1: /* $Header: str.c,v 1.0 87/12/18 13:07:26 root Exp $ 2: * 3: * $Log: str.c,v $ 4: * Revision 1.0 87/12/18 13:07:26 root 5: * Initial revision 6: * 7: */ 8: 9: #include "handy.h" 10: #include "EXTERN.h" 11: #include "util.h" 12: #include "a2p.h" 13: 14: str_numset(str,num) 15: register STR *str; 16: double num; 17: { 18: str->str_nval = num; 19: str->str_pok = 0; /* invalidate pointer */ 20: str->str_nok = 1; /* validate number */ 21: } 22: 23: char * 24: str_2ptr(str) 25: register STR *str; 26: { 27: register char *s; 28: 29: if (!str) 30: return ""; 31: GROWSTR(&(str->str_ptr), &(str->str_len), 24); 32: s = str->str_ptr; 33: if (str->str_nok) { 34: sprintf(s,"%.20g",str->str_nval); 35: while (*s) s++; 36: } 37: *s = '\0'; 38: str->str_cur = s - str->str_ptr; 39: str->str_pok = 1; 40: #ifdef DEBUGGING 41: if (debug & 32) 42: fprintf(stderr,"0x%lx ptr(%s)\n",str,str->str_ptr); 43: #endif 44: return str->str_ptr; 45: } 46: 47: double 48: str_2num(str) 49: register STR *str; 50: { 51: if (!str) 52: return 0.0; 53: if (str->str_len && str->str_pok) 54: str->str_nval = atof(str->str_ptr); 55: else 56: str->str_nval = 0.0; 57: str->str_nok = 1; 58: #ifdef DEBUGGING 59: if (debug & 32) 60: fprintf(stderr,"0x%lx num(%g)\n",str,str->str_nval); 61: #endif 62: return str->str_nval; 63: } 64: 65: str_sset(dstr,sstr) 66: STR *dstr; 67: register STR *sstr; 68: { 69: if (!sstr) 70: str_nset(dstr,No,0); 71: else if (sstr->str_nok) 72: str_numset(dstr,sstr->str_nval); 73: else if (sstr->str_pok) 74: str_nset(dstr,sstr->str_ptr,sstr->str_cur); 75: else 76: str_nset(dstr,"",0); 77: } 78: 79: str_nset(str,ptr,len) 80: register STR *str; 81: register char *ptr; 82: register int len; 83: { 84: GROWSTR(&(str->str_ptr), &(str->str_len), len + 1); 85: bcopy(ptr,str->str_ptr,len); 86: str->str_cur = len; 87: *(str->str_ptr+str->str_cur) = '\0'; 88: str->str_nok = 0; /* invalidate number */ 89: str->str_pok = 1; /* validate pointer */ 90: } 91: 92: str_set(str,ptr) 93: register STR *str; 94: register char *ptr; 95: { 96: register int len; 97: 98: if (!ptr) 99: ptr = ""; 100: len = strlen(ptr); 101: GROWSTR(&(str->str_ptr), &(str->str_len), len + 1); 102: bcopy(ptr,str->str_ptr,len+1); 103: str->str_cur = len; 104: str->str_nok = 0; /* invalidate number */ 105: str->str_pok = 1; /* validate pointer */ 106: } 107: 108: str_chop(str,ptr) /* like set but assuming ptr is in str */ 109: register STR *str; 110: register char *ptr; 111: { 112: if (!(str->str_pok)) 113: str_2ptr(str); 114: str->str_cur -= (ptr - str->str_ptr); 115: bcopy(ptr,str->str_ptr, str->str_cur + 1); 116: str->str_nok = 0; /* invalidate number */ 117: str->str_pok = 1; /* validate pointer */ 118: } 119: 120: str_ncat(str,ptr,len) 121: register STR *str; 122: register char *ptr; 123: register int len; 124: { 125: if (!(str->str_pok)) 126: str_2ptr(str); 127: GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + len + 1); 128: bcopy(ptr,str->str_ptr+str->str_cur,len); 129: str->str_cur += len; 130: *(str->str_ptr+str->str_cur) = '\0'; 131: str->str_nok = 0; /* invalidate number */ 132: str->str_pok = 1; /* validate pointer */ 133: } 134: 135: str_scat(dstr,sstr) 136: STR *dstr; 137: register STR *sstr; 138: { 139: if (!(sstr->str_pok)) 140: str_2ptr(sstr); 141: if (sstr) 142: str_ncat(dstr,sstr->str_ptr,sstr->str_cur); 143: } 144: 145: str_cat(str,ptr) 146: register STR *str; 147: register char *ptr; 148: { 149: register int len; 150: 151: if (!ptr) 152: return; 153: if (!(str->str_pok)) 154: str_2ptr(str); 155: len = strlen(ptr); 156: GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + len + 1); 157: bcopy(ptr,str->str_ptr+str->str_cur,len+1); 158: str->str_cur += len; 159: str->str_nok = 0; /* invalidate number */ 160: str->str_pok = 1; /* validate pointer */ 161: } 162: 163: char * 164: str_append_till(str,from,delim,keeplist) 165: register STR *str; 166: register char *from; 167: register int delim; 168: char *keeplist; 169: { 170: register char *to; 171: register int len; 172: 173: if (!from) 174: return Nullch; 175: len = strlen(from); 176: GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + len + 1); 177: str->str_nok = 0; /* invalidate number */ 178: str->str_pok = 1; /* validate pointer */ 179: to = str->str_ptr+str->str_cur; 180: for (; *from; from++,to++) { 181: if (*from == '\\' && from[1] && delim != '\\') { 182: if (!keeplist) { 183: if (from[1] == delim || from[1] == '\\') 184: from++; 185: else 186: *to++ = *from++; 187: } 188: else if (index(keeplist,from[1])) 189: *to++ = *from++; 190: else 191: from++; 192: } 193: else if (*from == delim) 194: break; 195: *to = *from; 196: } 197: *to = '\0'; 198: str->str_cur = to - str->str_ptr; 199: return from; 200: } 201: 202: STR * 203: str_new(len) 204: int len; 205: { 206: register STR *str; 207: 208: if (freestrroot) { 209: str = freestrroot; 210: freestrroot = str->str_link.str_next; 211: } 212: else { 213: str = (STR *) safemalloc(sizeof(STR)); 214: bzero((char*)str,sizeof(STR)); 215: } 216: if (len) 217: GROWSTR(&(str->str_ptr), &(str->str_len), len + 1); 218: return str; 219: } 220: 221: void 222: str_grow(str,len) 223: register STR *str; 224: int len; 225: { 226: if (len && str) 227: GROWSTR(&(str->str_ptr), &(str->str_len), len + 1); 228: } 229: 230: /* make str point to what nstr did */ 231: 232: void 233: str_replace(str,nstr) 234: register STR *str; 235: register STR *nstr; 236: { 237: safefree(str->str_ptr); 238: str->str_ptr = nstr->str_ptr; 239: str->str_len = nstr->str_len; 240: str->str_cur = nstr->str_cur; 241: str->str_pok = nstr->str_pok; 242: if (str->str_nok = nstr->str_nok) 243: str->str_nval = nstr->str_nval; 244: safefree((char*)nstr); 245: } 246: 247: void 248: str_free(str) 249: register STR *str; 250: { 251: if (!str) 252: return; 253: if (str->str_len) 254: str->str_ptr[0] = '\0'; 255: str->str_cur = 0; 256: str->str_nok = 0; 257: str->str_pok = 0; 258: str->str_link.str_next = freestrroot; 259: freestrroot = str; 260: } 261: 262: str_len(str) 263: register STR *str; 264: { 265: if (!str) 266: return 0; 267: if (!(str->str_pok)) 268: str_2ptr(str); 269: if (str->str_len) 270: return str->str_cur; 271: else 272: return 0; 273: } 274: 275: char * 276: str_gets(str,fp) 277: register STR *str; 278: register FILE *fp; 279: { 280: #ifdef STDSTDIO /* Here is some breathtakingly efficient cheating */ 281: 282: register char *bp; /* we're going to steal some values */ 283: register int cnt; /* from the stdio struct and put EVERYTHING */ 284: register char *ptr; /* in the innermost loop into registers */ 285: register char newline = '\n'; /* (assuming at least 6 registers) */ 286: int i; 287: int bpx; 288: 289: cnt = fp->_cnt; /* get count into register */ 290: str->str_nok = 0; /* invalidate number */ 291: str->str_pok = 1; /* validate pointer */ 292: if (str->str_len <= cnt) /* make sure we have the room */ 293: GROWSTR(&(str->str_ptr), &(str->str_len), cnt+1); 294: bp = str->str_ptr; /* move these two too to registers */ 295: ptr = fp->_ptr; 296: for (;;) { 297: while (--cnt >= 0) { /* this */ /* eat */ 298: if ((*bp++ = *ptr++) == newline) /* really */ /* dust */ 299: goto thats_all_folks; /* screams */ /* sed :-) */ 300: } 301: 302: fp->_cnt = cnt; /* deregisterize cnt and ptr */ 303: fp->_ptr = ptr; 304: i = _filbuf(fp); /* get more characters */ 305: cnt = fp->_cnt; 306: ptr = fp->_ptr; /* reregisterize cnt and ptr */ 307: 308: bpx = bp - str->str_ptr; /* prepare for possible relocation */ 309: GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + cnt + 1); 310: bp = str->str_ptr + bpx; /* reconstitute our pointer */ 311: 312: if (i == newline) { /* all done for now? */ 313: *bp++ = i; 314: goto thats_all_folks; 315: } 316: else if (i == EOF) /* all done for ever? */ 317: goto thats_all_folks; 318: *bp++ = i; /* now go back to screaming loop */ 319: } 320: 321: thats_all_folks: 322: fp->_cnt = cnt; /* put these back or we're in trouble */ 323: fp->_ptr = ptr; 324: *bp = '\0'; 325: str->str_cur = bp - str->str_ptr; /* set length */ 326: 327: #else /* !STDSTDIO */ /* The big, slow, and stupid way */ 328: 329: static char buf[4192]; 330: 331: if (fgets(buf, sizeof buf, fp) != Nullch) 332: str_set(str, buf); 333: else 334: str_set(str, No); 335: 336: #endif /* STDSTDIO */ 337: 338: return str->str_cur ? str->str_ptr : Nullch; 339: } 340: 341: void 342: str_inc(str) 343: register STR *str; 344: { 345: register char *d; 346: 347: if (!str) 348: return; 349: if (str->str_nok) { 350: str->str_nval += 1.0; 351: str->str_pok = 0; 352: return; 353: } 354: if (!str->str_pok) { 355: str->str_nval = 1.0; 356: str->str_nok = 1; 357: return; 358: } 359: for (d = str->str_ptr; *d && *d != '.'; d++) ; 360: d--; 361: if (!isdigit(*str->str_ptr) || !isdigit(*d) ) { 362: str_numset(str,atof(str->str_ptr) + 1.0); /* punt */ 363: return; 364: } 365: while (d >= str->str_ptr) { 366: if (++*d <= '9') 367: return; 368: *(d--) = '0'; 369: } 370: /* oh,oh, the number grew */ 371: GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + 2); 372: str->str_cur++; 373: for (d = str->str_ptr + str->str_cur; d > str->str_ptr; d--) 374: *d = d[-1]; 375: *d = '1'; 376: } 377: 378: void 379: str_dec(str) 380: register STR *str; 381: { 382: register char *d; 383: 384: if (!str) 385: return; 386: if (str->str_nok) { 387: str->str_nval -= 1.0; 388: str->str_pok = 0; 389: return; 390: } 391: if (!str->str_pok) { 392: str->str_nval = -1.0; 393: str->str_nok = 1; 394: return; 395: } 396: for (d = str->str_ptr; *d && *d != '.'; d++) ; 397: d--; 398: if (!isdigit(*str->str_ptr) || !isdigit(*d) || (*d == '0' && d == str->str_ptr)) { 399: str_numset(str,atof(str->str_ptr) - 1.0); /* punt */ 400: return; 401: } 402: while (d >= str->str_ptr) { 403: if (--*d >= '0') 404: return; 405: *(d--) = '9'; 406: } 407: } 408: 409: /* make a string that will exist for the duration of the expression eval */ 410: 411: STR * 412: str_static(oldstr) 413: STR *oldstr; 414: { 415: register STR *str = str_new(0); 416: static long tmps_size = -1; 417: 418: str_sset(str,oldstr); 419: if (++tmps_max > tmps_size) { 420: tmps_size = tmps_max; 421: if (!(tmps_size & 127)) { 422: if (tmps_size) 423: tmps_list = (STR**)saferealloc((char*)tmps_list, 424: (tmps_size + 128) * sizeof(STR*) ); 425: else 426: tmps_list = (STR**)safemalloc(128 * sizeof(char*)); 427: } 428: } 429: tmps_list[tmps_max] = str; 430: return str; 431: } 432: 433: STR * 434: str_make(s) 435: char *s; 436: { 437: register STR *str = str_new(0); 438: 439: str_set(str,s); 440: return str; 441: } 442: 443: STR * 444: str_nmake(n) 445: double n; 446: { 447: register STR *str = str_new(0); 448: 449: str_numset(str,n); 450: return str; 451: }