1*9a747e4fSDavid du Colombier #include <u.h> 2*9a747e4fSDavid du Colombier #include <libc.h> 3*9a747e4fSDavid du Colombier #include <draw.h> 4*9a747e4fSDavid du Colombier #include <html.h> 5*9a747e4fSDavid du Colombier #include "impl.h" 6*9a747e4fSDavid du Colombier 7*9a747e4fSDavid du Colombier Rune* whitespace = L" \t\n\r"; 8*9a747e4fSDavid du Colombier Rune* notwhitespace = L"^ \t\n\r"; 9*9a747e4fSDavid du Colombier 10*9a747e4fSDavid du Colombier // All lists start out like List structure. 11*9a747e4fSDavid du Colombier // List itself can be used as list of int. 12*9a747e4fSDavid du Colombier int 13*9a747e4fSDavid du Colombier _listlen(List* l) 14*9a747e4fSDavid du Colombier { 15*9a747e4fSDavid du Colombier int n = 0; 16*9a747e4fSDavid du Colombier 17*9a747e4fSDavid du Colombier while(l != nil) { 18*9a747e4fSDavid du Colombier l = l->next; 19*9a747e4fSDavid du Colombier n++; 20*9a747e4fSDavid du Colombier } 21*9a747e4fSDavid du Colombier return n; 22*9a747e4fSDavid du Colombier } 23*9a747e4fSDavid du Colombier 24*9a747e4fSDavid du Colombier // Cons 25*9a747e4fSDavid du Colombier List* 26*9a747e4fSDavid du Colombier _newlist(int val, List* rest) 27*9a747e4fSDavid du Colombier { 28*9a747e4fSDavid du Colombier List* ans; 29*9a747e4fSDavid du Colombier 30*9a747e4fSDavid du Colombier ans = (List*)emalloc(sizeof(List)); 31*9a747e4fSDavid du Colombier ans->val = val; 32*9a747e4fSDavid du Colombier ans->next = rest; 33*9a747e4fSDavid du Colombier return ans; 34*9a747e4fSDavid du Colombier } 35*9a747e4fSDavid du Colombier 36*9a747e4fSDavid du Colombier // Reverse a list in place 37*9a747e4fSDavid du Colombier List* 38*9a747e4fSDavid du Colombier _revlist(List* l) 39*9a747e4fSDavid du Colombier { 40*9a747e4fSDavid du Colombier List* newl; 41*9a747e4fSDavid du Colombier List* nextl; 42*9a747e4fSDavid du Colombier 43*9a747e4fSDavid du Colombier newl = nil; 44*9a747e4fSDavid du Colombier while(l != nil) { 45*9a747e4fSDavid du Colombier nextl = l->next; 46*9a747e4fSDavid du Colombier l->next = newl; 47*9a747e4fSDavid du Colombier newl = l; 48*9a747e4fSDavid du Colombier l = nextl; 49*9a747e4fSDavid du Colombier } 50*9a747e4fSDavid du Colombier return newl; 51*9a747e4fSDavid du Colombier } 52*9a747e4fSDavid du Colombier 53*9a747e4fSDavid du Colombier // The next few routines take a "character class" as argument. 54*9a747e4fSDavid du Colombier // e.g., "a-zA-Z", or "^ \t\n" 55*9a747e4fSDavid du Colombier // (ranges indicated by - except in first position; 56*9a747e4fSDavid du Colombier // ^ is first position means "not in" the following class) 57*9a747e4fSDavid du Colombier 58*9a747e4fSDavid du Colombier // Splitl splits s[0:n] just before first character of class cl. 59*9a747e4fSDavid du Colombier // Answers go in (p1, n1) and (p2, n2). 60*9a747e4fSDavid du Colombier // If no split, the whole thing goes in the first component. 61*9a747e4fSDavid du Colombier // Note: answers contain pointers into original string. 62*9a747e4fSDavid du Colombier void 63*9a747e4fSDavid du Colombier _splitl(Rune* s, int n, Rune* cl, Rune** p1, int* n1, Rune** p2, int* n2) 64*9a747e4fSDavid du Colombier { 65*9a747e4fSDavid du Colombier Rune* p; 66*9a747e4fSDavid du Colombier 67*9a747e4fSDavid du Colombier p = _Strnclass(s, cl, n); 68*9a747e4fSDavid du Colombier *p1 = s; 69*9a747e4fSDavid du Colombier if(p == nil) { 70*9a747e4fSDavid du Colombier *n1 = n; 71*9a747e4fSDavid du Colombier *p2 = nil; 72*9a747e4fSDavid du Colombier *n2 = 0; 73*9a747e4fSDavid du Colombier } 74*9a747e4fSDavid du Colombier else { 75*9a747e4fSDavid du Colombier *p2 = p; 76*9a747e4fSDavid du Colombier *n1 = p-s; 77*9a747e4fSDavid du Colombier *n2 = n-*n1; 78*9a747e4fSDavid du Colombier } 79*9a747e4fSDavid du Colombier } 80*9a747e4fSDavid du Colombier 81*9a747e4fSDavid du Colombier // Splitr splits s[0:n] just after last character of class cl. 82*9a747e4fSDavid du Colombier // Answers go in (p1, n1) and (p2, n2). 83*9a747e4fSDavid du Colombier // If no split, the whole thing goes in the last component. 84*9a747e4fSDavid du Colombier // Note: answers contain pointers into original string. 85*9a747e4fSDavid du Colombier void 86*9a747e4fSDavid du Colombier _splitr(Rune* s, int n, Rune* cl, Rune** p1, int* n1, Rune** p2, int* n2) 87*9a747e4fSDavid du Colombier { 88*9a747e4fSDavid du Colombier Rune* p; 89*9a747e4fSDavid du Colombier 90*9a747e4fSDavid du Colombier p = _Strnrclass(s, cl, n); 91*9a747e4fSDavid du Colombier if(p == nil) { 92*9a747e4fSDavid du Colombier *p1 = nil; 93*9a747e4fSDavid du Colombier *n1 = 0; 94*9a747e4fSDavid du Colombier *p2 = s; 95*9a747e4fSDavid du Colombier *n2 = n; 96*9a747e4fSDavid du Colombier } 97*9a747e4fSDavid du Colombier else { 98*9a747e4fSDavid du Colombier *p1 = s; 99*9a747e4fSDavid du Colombier *p2 = p+1; 100*9a747e4fSDavid du Colombier *n1 = *p2-s; 101*9a747e4fSDavid du Colombier *n2 = n-*n1; 102*9a747e4fSDavid du Colombier } 103*9a747e4fSDavid du Colombier } 104*9a747e4fSDavid du Colombier 105*9a747e4fSDavid du Colombier // Splitall splits s[0:n] into parts that are separated by characters from class cl. 106*9a747e4fSDavid du Colombier // Each part will have nonzero length. 107*9a747e4fSDavid du Colombier // At most alen parts are found, and pointers to their starts go into 108*9a747e4fSDavid du Colombier // the strarr array, while their lengths go into the lenarr array. 109*9a747e4fSDavid du Colombier // The return value is the number of parts found. 110*9a747e4fSDavid du Colombier int 111*9a747e4fSDavid du Colombier _splitall(Rune* s, int n, Rune* cl, Rune** strarr, int* lenarr, int alen) 112*9a747e4fSDavid du Colombier { 113*9a747e4fSDavid du Colombier int i; 114*9a747e4fSDavid du Colombier Rune* p; 115*9a747e4fSDavid du Colombier Rune* q; 116*9a747e4fSDavid du Colombier Rune* slast; 117*9a747e4fSDavid du Colombier 118*9a747e4fSDavid du Colombier if(s == nil || n == 0) 119*9a747e4fSDavid du Colombier return 0; 120*9a747e4fSDavid du Colombier i = 0; 121*9a747e4fSDavid du Colombier p = s; 122*9a747e4fSDavid du Colombier slast = s+n; 123*9a747e4fSDavid du Colombier while(p < slast && i < alen) { 124*9a747e4fSDavid du Colombier while(p < slast && _inclass(*p, cl)) 125*9a747e4fSDavid du Colombier p++; 126*9a747e4fSDavid du Colombier if(p == slast) 127*9a747e4fSDavid du Colombier break; 128*9a747e4fSDavid du Colombier q = _Strnclass(p, cl, slast-p); 129*9a747e4fSDavid du Colombier if(q == nil) 130*9a747e4fSDavid du Colombier q = slast; 131*9a747e4fSDavid du Colombier assert(q > p && q <= slast); 132*9a747e4fSDavid du Colombier strarr[i] = p; 133*9a747e4fSDavid du Colombier lenarr[i] = q-p; 134*9a747e4fSDavid du Colombier i++; 135*9a747e4fSDavid du Colombier p = q; 136*9a747e4fSDavid du Colombier } 137*9a747e4fSDavid du Colombier return i; 138*9a747e4fSDavid du Colombier } 139*9a747e4fSDavid du Colombier 140*9a747e4fSDavid du Colombier // Find part of s that excludes leading and trailing whitespace, 141*9a747e4fSDavid du Colombier // and return that part in *pans (and its length in *panslen). 142*9a747e4fSDavid du Colombier void 143*9a747e4fSDavid du Colombier _trimwhite(Rune* s, int n, Rune** pans, int* panslen) 144*9a747e4fSDavid du Colombier { 145*9a747e4fSDavid du Colombier Rune* p; 146*9a747e4fSDavid du Colombier Rune* q; 147*9a747e4fSDavid du Colombier 148*9a747e4fSDavid du Colombier p = nil; 149*9a747e4fSDavid du Colombier if(n > 0) { 150*9a747e4fSDavid du Colombier p = _Strnclass(s, notwhitespace, n); 151*9a747e4fSDavid du Colombier if(p != nil) { 152*9a747e4fSDavid du Colombier q = _Strnrclass(s, notwhitespace, n); 153*9a747e4fSDavid du Colombier assert(q != nil); 154*9a747e4fSDavid du Colombier n = q+1-p; 155*9a747e4fSDavid du Colombier } 156*9a747e4fSDavid du Colombier } 157*9a747e4fSDavid du Colombier *pans = p; 158*9a747e4fSDavid du Colombier *panslen = n; 159*9a747e4fSDavid du Colombier } 160*9a747e4fSDavid du Colombier 161*9a747e4fSDavid du Colombier // _Strclass returns a pointer to the first element of s that is 162*9a747e4fSDavid du Colombier // a member of class cl, nil if none. 163*9a747e4fSDavid du Colombier Rune* 164*9a747e4fSDavid du Colombier _Strclass(Rune* s, Rune* cl) 165*9a747e4fSDavid du Colombier { 166*9a747e4fSDavid du Colombier Rune* p; 167*9a747e4fSDavid du Colombier 168*9a747e4fSDavid du Colombier for(p = s; *p != 0; p++) 169*9a747e4fSDavid du Colombier if(_inclass(*p, cl)) 170*9a747e4fSDavid du Colombier return p; 171*9a747e4fSDavid du Colombier return nil; 172*9a747e4fSDavid du Colombier } 173*9a747e4fSDavid du Colombier 174*9a747e4fSDavid du Colombier // _Strnclass returns a pointer to the first element of s[0:n] that is 175*9a747e4fSDavid du Colombier // a member of class cl, nil if none. 176*9a747e4fSDavid du Colombier Rune* 177*9a747e4fSDavid du Colombier _Strnclass(Rune* s, Rune* cl, int n) 178*9a747e4fSDavid du Colombier { 179*9a747e4fSDavid du Colombier Rune* p; 180*9a747e4fSDavid du Colombier 181*9a747e4fSDavid du Colombier for(p = s; n-- && *p != 0; p++) 182*9a747e4fSDavid du Colombier if(_inclass(*p, cl)) 183*9a747e4fSDavid du Colombier return p; 184*9a747e4fSDavid du Colombier return nil; 185*9a747e4fSDavid du Colombier } 186*9a747e4fSDavid du Colombier 187*9a747e4fSDavid du Colombier // _Strrclass returns a pointer to the last element of s that is 188*9a747e4fSDavid du Colombier // a member of class cl, nil if none 189*9a747e4fSDavid du Colombier Rune* 190*9a747e4fSDavid du Colombier _Strrclass(Rune* s, Rune* cl) 191*9a747e4fSDavid du Colombier { 192*9a747e4fSDavid du Colombier Rune* p; 193*9a747e4fSDavid du Colombier 194*9a747e4fSDavid du Colombier if(s == nil || *s == 0) 195*9a747e4fSDavid du Colombier return nil; 196*9a747e4fSDavid du Colombier p = s + runestrlen(s) - 1; 197*9a747e4fSDavid du Colombier while(p >= s) { 198*9a747e4fSDavid du Colombier if(_inclass(*p, cl)) 199*9a747e4fSDavid du Colombier return p; 200*9a747e4fSDavid du Colombier p--; 201*9a747e4fSDavid du Colombier }; 202*9a747e4fSDavid du Colombier return nil; 203*9a747e4fSDavid du Colombier } 204*9a747e4fSDavid du Colombier 205*9a747e4fSDavid du Colombier // _Strnrclass returns a pointer to the last element of s[0:n] that is 206*9a747e4fSDavid du Colombier // a member of class cl, nil if none 207*9a747e4fSDavid du Colombier Rune* 208*9a747e4fSDavid du Colombier _Strnrclass(Rune* s, Rune* cl, int n) 209*9a747e4fSDavid du Colombier { 210*9a747e4fSDavid du Colombier Rune* p; 211*9a747e4fSDavid du Colombier 212*9a747e4fSDavid du Colombier if(s == nil || *s == 0 || n == 0) 213*9a747e4fSDavid du Colombier return nil; 214*9a747e4fSDavid du Colombier p = s + n - 1; 215*9a747e4fSDavid du Colombier while(p >= s) { 216*9a747e4fSDavid du Colombier if(_inclass(*p, cl)) 217*9a747e4fSDavid du Colombier return p; 218*9a747e4fSDavid du Colombier p--; 219*9a747e4fSDavid du Colombier }; 220*9a747e4fSDavid du Colombier return nil; 221*9a747e4fSDavid du Colombier } 222*9a747e4fSDavid du Colombier 223*9a747e4fSDavid du Colombier // Is c in the class cl? 224*9a747e4fSDavid du Colombier int 225*9a747e4fSDavid du Colombier _inclass(Rune c, Rune* cl) 226*9a747e4fSDavid du Colombier { 227*9a747e4fSDavid du Colombier int n; 228*9a747e4fSDavid du Colombier int ans; 229*9a747e4fSDavid du Colombier int negate; 230*9a747e4fSDavid du Colombier int i; 231*9a747e4fSDavid du Colombier 232*9a747e4fSDavid du Colombier n = runestrlen(cl); 233*9a747e4fSDavid du Colombier if(n == 0) 234*9a747e4fSDavid du Colombier return 0; 235*9a747e4fSDavid du Colombier ans = 0; 236*9a747e4fSDavid du Colombier negate = 0; 237*9a747e4fSDavid du Colombier if(cl[0] == '^') { 238*9a747e4fSDavid du Colombier negate = 1; 239*9a747e4fSDavid du Colombier cl++; 240*9a747e4fSDavid du Colombier n--; 241*9a747e4fSDavid du Colombier } 242*9a747e4fSDavid du Colombier for(i = 0; i < n; i++) { 243*9a747e4fSDavid du Colombier if(cl[i] == '-' && i > 0 && i < n - 1) { 244*9a747e4fSDavid du Colombier if(c >= cl[i - 1] && c <= cl[i + 1]) { 245*9a747e4fSDavid du Colombier ans = 1; 246*9a747e4fSDavid du Colombier break; 247*9a747e4fSDavid du Colombier } 248*9a747e4fSDavid du Colombier i++; 249*9a747e4fSDavid du Colombier } 250*9a747e4fSDavid du Colombier else if(c == cl[i]) { 251*9a747e4fSDavid du Colombier ans = 1; 252*9a747e4fSDavid du Colombier break; 253*9a747e4fSDavid du Colombier } 254*9a747e4fSDavid du Colombier } 255*9a747e4fSDavid du Colombier if(negate) 256*9a747e4fSDavid du Colombier ans = !ans; 257*9a747e4fSDavid du Colombier return ans; 258*9a747e4fSDavid du Colombier } 259*9a747e4fSDavid du Colombier 260*9a747e4fSDavid du Colombier // Is pre a prefix of s? 261*9a747e4fSDavid du Colombier int 262*9a747e4fSDavid du Colombier _prefix(Rune* pre, Rune* s) 263*9a747e4fSDavid du Colombier { 264*9a747e4fSDavid du Colombier int ns; 265*9a747e4fSDavid du Colombier int n; 266*9a747e4fSDavid du Colombier int k; 267*9a747e4fSDavid du Colombier 268*9a747e4fSDavid du Colombier ns = runestrlen(s); 269*9a747e4fSDavid du Colombier n = runestrlen(pre); 270*9a747e4fSDavid du Colombier if(ns < n) 271*9a747e4fSDavid du Colombier return 0; 272*9a747e4fSDavid du Colombier for(k = 0; k < n; k++) { 273*9a747e4fSDavid du Colombier if(pre[k] != s[k]) 274*9a747e4fSDavid du Colombier return 0; 275*9a747e4fSDavid du Colombier } 276*9a747e4fSDavid du Colombier return 1; 277*9a747e4fSDavid du Colombier } 278*9a747e4fSDavid du Colombier 279*9a747e4fSDavid du Colombier // Like Strcmp, but use exactly n chars of s1 (assume s1 has at least n chars). 280*9a747e4fSDavid du Colombier // Also, do a case-insensitive match, assuming s2 281*9a747e4fSDavid du Colombier // has no chars in [A-Z], only their lowercase versions. 282*9a747e4fSDavid du Colombier // (This routine is used for in-place keyword lookup, where s2 is in a keyword 283*9a747e4fSDavid du Colombier // list and s1 is some substring, possibly mixed-case, in a buffer.) 284*9a747e4fSDavid du Colombier int 285*9a747e4fSDavid du Colombier _Strncmpci(Rune *s1, int n1, Rune *s2) 286*9a747e4fSDavid du Colombier { 287*9a747e4fSDavid du Colombier Rune c1, c2; 288*9a747e4fSDavid du Colombier 289*9a747e4fSDavid du Colombier for(;;) { 290*9a747e4fSDavid du Colombier if(n1-- == 0) { 291*9a747e4fSDavid du Colombier if(*s2 == 0) 292*9a747e4fSDavid du Colombier return 0; 293*9a747e4fSDavid du Colombier return -1; 294*9a747e4fSDavid du Colombier } 295*9a747e4fSDavid du Colombier c1 = *s1++; 296*9a747e4fSDavid du Colombier c2 = *s2++; 297*9a747e4fSDavid du Colombier if(c1 >= 'A' && c1 <= 'Z') 298*9a747e4fSDavid du Colombier c1 = c1 - 'A' + 'a'; 299*9a747e4fSDavid du Colombier if(c1 != c2) { 300*9a747e4fSDavid du Colombier if(c1 > c2) 301*9a747e4fSDavid du Colombier return 1; 302*9a747e4fSDavid du Colombier return -1; 303*9a747e4fSDavid du Colombier } 304*9a747e4fSDavid du Colombier } 305*9a747e4fSDavid du Colombier } 306*9a747e4fSDavid du Colombier 307*9a747e4fSDavid du Colombier // emalloc and copy 308*9a747e4fSDavid du Colombier Rune* 309*9a747e4fSDavid du Colombier _Strdup(Rune* s) 310*9a747e4fSDavid du Colombier { 311*9a747e4fSDavid du Colombier if(s == nil) 312*9a747e4fSDavid du Colombier return nil; 313*9a747e4fSDavid du Colombier return _Strndup(s, runestrlen(s)); 314*9a747e4fSDavid du Colombier } 315*9a747e4fSDavid du Colombier 316*9a747e4fSDavid du Colombier // emalloc and copy n chars of s (assume s is at least that long), 317*9a747e4fSDavid du Colombier // and add 0 terminator. 318*9a747e4fSDavid du Colombier // Return nil if n==0. 319*9a747e4fSDavid du Colombier Rune* 320*9a747e4fSDavid du Colombier _Strndup(Rune* s, int n) 321*9a747e4fSDavid du Colombier { 322*9a747e4fSDavid du Colombier Rune* ans; 323*9a747e4fSDavid du Colombier 324*9a747e4fSDavid du Colombier if(n <= 0) 325*9a747e4fSDavid du Colombier return nil; 326*9a747e4fSDavid du Colombier ans = _newstr(n); 327*9a747e4fSDavid du Colombier memmove(ans, s, n*sizeof(Rune)); 328*9a747e4fSDavid du Colombier ans[n] = 0; 329*9a747e4fSDavid du Colombier return ans; 330*9a747e4fSDavid du Colombier } 331*9a747e4fSDavid du Colombier // emalloc enough room for n Runes, plus 1 null terminator. 332*9a747e4fSDavid du Colombier // (Not initialized to anything.) 333*9a747e4fSDavid du Colombier Rune* 334*9a747e4fSDavid du Colombier _newstr(int n) 335*9a747e4fSDavid du Colombier { 336*9a747e4fSDavid du Colombier return (Rune*)emalloc((n+1)*sizeof(Rune)); 337*9a747e4fSDavid du Colombier } 338*9a747e4fSDavid du Colombier 339*9a747e4fSDavid du Colombier // emalloc and copy s+t 340*9a747e4fSDavid du Colombier Rune* 341*9a747e4fSDavid du Colombier _Strdup2(Rune* s, Rune* t) 342*9a747e4fSDavid du Colombier { 343*9a747e4fSDavid du Colombier int ns, nt; 344*9a747e4fSDavid du Colombier Rune* ans; 345*9a747e4fSDavid du Colombier Rune* p; 346*9a747e4fSDavid du Colombier 347*9a747e4fSDavid du Colombier ns = runestrlen(s); 348*9a747e4fSDavid du Colombier nt = runestrlen(t); 349*9a747e4fSDavid du Colombier if(ns+nt == 0) 350*9a747e4fSDavid du Colombier return nil; 351*9a747e4fSDavid du Colombier ans = _newstr(ns+nt); 352*9a747e4fSDavid du Colombier p = _Stradd(ans, s, ns); 353*9a747e4fSDavid du Colombier p = _Stradd(p, t, nt); 354*9a747e4fSDavid du Colombier *p = 0; 355*9a747e4fSDavid du Colombier return ans; 356*9a747e4fSDavid du Colombier } 357*9a747e4fSDavid du Colombier 358*9a747e4fSDavid du Colombier // Return emalloc'd substring s[start:stop], 359*9a747e4fSDavid du Colombier Rune* 360*9a747e4fSDavid du Colombier _Strsubstr(Rune* s, int start, int stop) 361*9a747e4fSDavid du Colombier { 362*9a747e4fSDavid du Colombier Rune* t; 363*9a747e4fSDavid du Colombier 364*9a747e4fSDavid du Colombier if(start == stop) 365*9a747e4fSDavid du Colombier return nil; 366*9a747e4fSDavid du Colombier t = _Strndup(s+start, stop-start); 367*9a747e4fSDavid du Colombier return t; 368*9a747e4fSDavid du Colombier } 369*9a747e4fSDavid du Colombier 370*9a747e4fSDavid du Colombier // Copy n chars to s1 from s2, and return s1+n 371*9a747e4fSDavid du Colombier Rune* 372*9a747e4fSDavid du Colombier _Stradd(Rune* s1, Rune* s2, int n) 373*9a747e4fSDavid du Colombier { 374*9a747e4fSDavid du Colombier if(n == 0) 375*9a747e4fSDavid du Colombier return s1; 376*9a747e4fSDavid du Colombier memmove(s1, s2, n*sizeof(Rune)); 377*9a747e4fSDavid du Colombier return s1+n; 378*9a747e4fSDavid du Colombier } 379*9a747e4fSDavid du Colombier 380*9a747e4fSDavid du Colombier // Like strtol, but converting from Rune* string 381*9a747e4fSDavid du Colombier 382*9a747e4fSDavid du Colombier #define LONG_MAX 2147483647L 383*9a747e4fSDavid du Colombier #define LONG_MIN -2147483648L 384*9a747e4fSDavid du Colombier 385*9a747e4fSDavid du Colombier long 386*9a747e4fSDavid du Colombier _Strtol(Rune* nptr, Rune** endptr, int base) 387*9a747e4fSDavid du Colombier { 388*9a747e4fSDavid du Colombier Rune* p; 389*9a747e4fSDavid du Colombier long n, nn; 390*9a747e4fSDavid du Colombier int c, ovfl, v, neg, ndig; 391*9a747e4fSDavid du Colombier 392*9a747e4fSDavid du Colombier p = nptr; 393*9a747e4fSDavid du Colombier neg = 0; 394*9a747e4fSDavid du Colombier n = 0; 395*9a747e4fSDavid du Colombier ndig = 0; 396*9a747e4fSDavid du Colombier ovfl = 0; 397*9a747e4fSDavid du Colombier 398*9a747e4fSDavid du Colombier /* 399*9a747e4fSDavid du Colombier * White space 400*9a747e4fSDavid du Colombier */ 401*9a747e4fSDavid du Colombier for(;;p++){ 402*9a747e4fSDavid du Colombier switch(*p){ 403*9a747e4fSDavid du Colombier case ' ': 404*9a747e4fSDavid du Colombier case '\t': 405*9a747e4fSDavid du Colombier case '\n': 406*9a747e4fSDavid du Colombier case '\f': 407*9a747e4fSDavid du Colombier case '\r': 408*9a747e4fSDavid du Colombier case '\v': 409*9a747e4fSDavid du Colombier continue; 410*9a747e4fSDavid du Colombier } 411*9a747e4fSDavid du Colombier break; 412*9a747e4fSDavid du Colombier } 413*9a747e4fSDavid du Colombier 414*9a747e4fSDavid du Colombier /* 415*9a747e4fSDavid du Colombier * Sign 416*9a747e4fSDavid du Colombier */ 417*9a747e4fSDavid du Colombier if(*p=='-' || *p=='+') 418*9a747e4fSDavid du Colombier if(*p++ == '-') 419*9a747e4fSDavid du Colombier neg = 1; 420*9a747e4fSDavid du Colombier 421*9a747e4fSDavid du Colombier /* 422*9a747e4fSDavid du Colombier * Base 423*9a747e4fSDavid du Colombier */ 424*9a747e4fSDavid du Colombier if(base==0){ 425*9a747e4fSDavid du Colombier if(*p != '0') 426*9a747e4fSDavid du Colombier base = 10; 427*9a747e4fSDavid du Colombier else{ 428*9a747e4fSDavid du Colombier base = 8; 429*9a747e4fSDavid du Colombier if(p[1]=='x' || p[1]=='X'){ 430*9a747e4fSDavid du Colombier p += 2; 431*9a747e4fSDavid du Colombier base = 16; 432*9a747e4fSDavid du Colombier } 433*9a747e4fSDavid du Colombier } 434*9a747e4fSDavid du Colombier }else if(base==16 && *p=='0'){ 435*9a747e4fSDavid du Colombier if(p[1]=='x' || p[1]=='X') 436*9a747e4fSDavid du Colombier p += 2; 437*9a747e4fSDavid du Colombier }else if(base<0 || 36<base) 438*9a747e4fSDavid du Colombier goto Return; 439*9a747e4fSDavid du Colombier 440*9a747e4fSDavid du Colombier /* 441*9a747e4fSDavid du Colombier * Non-empty sequence of digits 442*9a747e4fSDavid du Colombier */ 443*9a747e4fSDavid du Colombier for(;; p++,ndig++){ 444*9a747e4fSDavid du Colombier c = *p; 445*9a747e4fSDavid du Colombier v = base; 446*9a747e4fSDavid du Colombier if('0'<=c && c<='9') 447*9a747e4fSDavid du Colombier v = c - '0'; 448*9a747e4fSDavid du Colombier else if('a'<=c && c<='z') 449*9a747e4fSDavid du Colombier v = c - 'a' + 10; 450*9a747e4fSDavid du Colombier else if('A'<=c && c<='Z') 451*9a747e4fSDavid du Colombier v = c - 'A' + 10; 452*9a747e4fSDavid du Colombier if(v >= base) 453*9a747e4fSDavid du Colombier break; 454*9a747e4fSDavid du Colombier nn = n*base + v; 455*9a747e4fSDavid du Colombier if(nn < n) 456*9a747e4fSDavid du Colombier ovfl = 1; 457*9a747e4fSDavid du Colombier n = nn; 458*9a747e4fSDavid du Colombier } 459*9a747e4fSDavid du Colombier 460*9a747e4fSDavid du Colombier Return: 461*9a747e4fSDavid du Colombier if(ndig == 0) 462*9a747e4fSDavid du Colombier p = nptr; 463*9a747e4fSDavid du Colombier if(endptr) 464*9a747e4fSDavid du Colombier *endptr = p; 465*9a747e4fSDavid du Colombier if(ovfl){ 466*9a747e4fSDavid du Colombier if(neg) 467*9a747e4fSDavid du Colombier return LONG_MIN; 468*9a747e4fSDavid du Colombier return LONG_MAX; 469*9a747e4fSDavid du Colombier } 470*9a747e4fSDavid du Colombier if(neg) 471*9a747e4fSDavid du Colombier return -n; 472*9a747e4fSDavid du Colombier return n; 473*9a747e4fSDavid du Colombier } 474*9a747e4fSDavid du Colombier 475*9a747e4fSDavid du Colombier // Convert buf[0:n], bytes whose character set is chset, 476*9a747e4fSDavid du Colombier // into a emalloc'd null-terminated Unicode string. 477*9a747e4fSDavid du Colombier Rune* 478*9a747e4fSDavid du Colombier toStr(uchar* buf, int n, int chset) 479*9a747e4fSDavid du Colombier { 480*9a747e4fSDavid du Colombier int i; 481*9a747e4fSDavid du Colombier int m; 482*9a747e4fSDavid du Colombier Rune ch; 483*9a747e4fSDavid du Colombier Rune* ans; 484*9a747e4fSDavid du Colombier 485*9a747e4fSDavid du Colombier switch(chset) { 486*9a747e4fSDavid du Colombier case US_Ascii: 487*9a747e4fSDavid du Colombier case ISO_8859_1: 488*9a747e4fSDavid du Colombier ans = (Rune*)emalloc((n+1)*sizeof(Rune)); 489*9a747e4fSDavid du Colombier for(i = 0; i < n; i++) 490*9a747e4fSDavid du Colombier ans[i] = buf[i]; 491*9a747e4fSDavid du Colombier ans[n] = 0; 492*9a747e4fSDavid du Colombier break; 493*9a747e4fSDavid du Colombier 494*9a747e4fSDavid du Colombier case UTF_8: 495*9a747e4fSDavid du Colombier m = 0; 496*9a747e4fSDavid du Colombier for(i = 0; i < n; ) { 497*9a747e4fSDavid du Colombier i += chartorune(&ch, (char*)(buf+i)); 498*9a747e4fSDavid du Colombier m++; 499*9a747e4fSDavid du Colombier } 500*9a747e4fSDavid du Colombier ans = (Rune*)emalloc((m+1)*sizeof(Rune)); 501*9a747e4fSDavid du Colombier m = 0; 502*9a747e4fSDavid du Colombier for(i = 0; i < n; ) { 503*9a747e4fSDavid du Colombier i += chartorune(&ch, (char*)(buf+i)); 504*9a747e4fSDavid du Colombier ans[m++] = ch; 505*9a747e4fSDavid du Colombier } 506*9a747e4fSDavid du Colombier ans[m] = 0; 507*9a747e4fSDavid du Colombier break; 508*9a747e4fSDavid du Colombier 509*9a747e4fSDavid du Colombier default: 510*9a747e4fSDavid du Colombier ans = nil; 511*9a747e4fSDavid du Colombier assert(0); 512*9a747e4fSDavid du Colombier } 513*9a747e4fSDavid du Colombier return ans; 514*9a747e4fSDavid du Colombier } 515*9a747e4fSDavid du Colombier 516*9a747e4fSDavid du Colombier // Convert buf[0:n], Unicode characters, 517*9a747e4fSDavid du Colombier // into an emalloc'd null-terminated string in character set chset. 518*9a747e4fSDavid du Colombier // Use 0x80 for unconvertable characters. 519*9a747e4fSDavid du Colombier uchar* 520*9a747e4fSDavid du Colombier fromStr(Rune* buf, int n, int chset) 521*9a747e4fSDavid du Colombier { 522*9a747e4fSDavid du Colombier uchar* ans; 523*9a747e4fSDavid du Colombier int i, lim, m; 524*9a747e4fSDavid du Colombier Rune ch; 525*9a747e4fSDavid du Colombier uchar* p; 526*9a747e4fSDavid du Colombier uchar s[UTFmax]; 527*9a747e4fSDavid du Colombier 528*9a747e4fSDavid du Colombier ans = nil; 529*9a747e4fSDavid du Colombier switch(chset) { 530*9a747e4fSDavid du Colombier case US_Ascii: 531*9a747e4fSDavid du Colombier case ISO_8859_1: 532*9a747e4fSDavid du Colombier ans = (uchar*)emalloc(n+1); 533*9a747e4fSDavid du Colombier lim = (chset==US_Ascii)? 127 : 255; 534*9a747e4fSDavid du Colombier for(i = 0; i < n; i++) { 535*9a747e4fSDavid du Colombier ch = buf[i]; 536*9a747e4fSDavid du Colombier if(ch > lim) 537*9a747e4fSDavid du Colombier ch = 0x80; 538*9a747e4fSDavid du Colombier ans[i] = ch; 539*9a747e4fSDavid du Colombier } 540*9a747e4fSDavid du Colombier ans[n] = 0; 541*9a747e4fSDavid du Colombier break; 542*9a747e4fSDavid du Colombier 543*9a747e4fSDavid du Colombier case UTF_8: 544*9a747e4fSDavid du Colombier m = 0; 545*9a747e4fSDavid du Colombier for(i = 0; i < n; i++) { 546*9a747e4fSDavid du Colombier m += runetochar((char*)s, &buf[i]); 547*9a747e4fSDavid du Colombier } 548*9a747e4fSDavid du Colombier ans = (uchar*)emalloc(m+1); 549*9a747e4fSDavid du Colombier p = ans; 550*9a747e4fSDavid du Colombier for(i = 0; i < n; i++) 551*9a747e4fSDavid du Colombier p += runetochar((char*)p, &buf[i]); 552*9a747e4fSDavid du Colombier *p = 0; 553*9a747e4fSDavid du Colombier break; 554*9a747e4fSDavid du Colombier 555*9a747e4fSDavid du Colombier default: 556*9a747e4fSDavid du Colombier assert(0); 557*9a747e4fSDavid du Colombier } 558*9a747e4fSDavid du Colombier return ans; 559*9a747e4fSDavid du Colombier 560*9a747e4fSDavid du Colombier } 561*9a747e4fSDavid du Colombier 562*9a747e4fSDavid du Colombier // Convert n to emalloc'd String. 563*9a747e4fSDavid du Colombier Rune* 564*9a747e4fSDavid du Colombier _ltoStr(int n) 565*9a747e4fSDavid du Colombier { 566*9a747e4fSDavid du Colombier int m; 567*9a747e4fSDavid du Colombier uchar buf[20]; 568*9a747e4fSDavid du Colombier 569*9a747e4fSDavid du Colombier m = snprint((char*)buf, sizeof(buf), "%d", n); 570*9a747e4fSDavid du Colombier return toStr(buf, m, US_Ascii); 571*9a747e4fSDavid du Colombier } 572