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