a "replacement" for awk and sed
[p5sagit/p5-mst-13.2.git] / str.c
CommitLineData
8d063cd8 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
15str_reset(s)
16register 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
50str_numset(str,num)
51register STR *str;
52double num;
53{
54 str->str_nval = num;
55 str->str_pok = 0; /* invalidate pointer */
56 str->str_nok = 1; /* validate number */
57}
58
59char *
60str_2ptr(str)
61register 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
83double
84str_2num(str)
85register 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
101str_sset(dstr,sstr)
102STR *dstr;
103register 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
115str_nset(str,ptr,len)
116register STR *str;
117register char *ptr;
118register 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
128str_set(str,ptr)
129register STR *str;
130register 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
144str_chop(str,ptr) /* like set but assuming ptr is in str */
145register STR *str;
146register 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
156str_ncat(str,ptr,len)
157register STR *str;
158register char *ptr;
159register 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
171str_scat(dstr,sstr)
172STR *dstr;
173register 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
181str_cat(str,ptr)
182register STR *str;
183register 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
199char *
200str_append_till(str,from,delim,keeplist)
201register STR *str;
202register char *from;
203register int delim;
204char *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
238STR *
239str_new(len)
240int 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
258void
259str_grow(str,len)
260register STR *str;
261int 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
269void
270str_replace(str,nstr)
271register STR *str;
272register 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
284void
285str_free(str)
286register 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
299str_len(str)
300register 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
312char *
313str_gets(str,fp)
314register STR *str;
315register 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
370thats_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 }
375thats_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
396STR *
397interp(str,s)
398register STR *str;
399register 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
425void
426str_inc(str)
427register 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
462void
463str_dec(str)
464register 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
495STR *
496str_static(oldstr)
497STR *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
517STR *
518str_make(s)
519char *s;
520{
521 register STR *str = str_new(0);
522
523 str_set(str,s);
524 return str;
525}
526
527STR *
528str_nmake(n)
529double n;
530{
531 register STR *str = str_new(0);
532
533 str_numset(str,n);
534 return str;
535}