You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

str.c 11KB

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