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