This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perl 2.0 (no announcement message available)
[perl5.git] / util.c
1 /* $Header: util.c,v 2.0 88/06/05 00:15:11 root Exp $
2  *
3  * $Log:        util.c,v $
4  * Revision 2.0  88/06/05  00:15:11  root
5  * Baseline version 2.0.
6  * 
7  */
8
9 #include "EXTERN.h"
10 #include "perl.h"
11
12 #define FLUSH
13
14 static char nomem[] = "Out of memory!\n";
15
16 /* paranoid version of malloc */
17
18 #ifdef DEBUGGING
19 static int an = 0;
20 #endif
21
22 char *
23 safemalloc(size)
24 MEM_SIZE size;
25 {
26     char *ptr;
27     char *malloc();
28
29     ptr = malloc(size?size:1);  /* malloc(0) is NASTY on our system */
30 #ifdef DEBUGGING
31     if (debug & 128)
32         fprintf(stderr,"0x%x: (%05d) malloc %d bytes\n",ptr,an++,size);
33 #endif
34     if (ptr != Nullch)
35         return ptr;
36     else {
37         fputs(nomem,stdout) FLUSH;
38         exit(1);
39     }
40     /*NOTREACHED*/
41 }
42
43 /* paranoid version of realloc */
44
45 char *
46 saferealloc(where,size)
47 char *where;
48 MEM_SIZE size;
49 {
50     char *ptr;
51     char *realloc();
52
53     if (!where)
54         fatal("Null realloc");
55     ptr = realloc(where,size?size:1);   /* realloc(0) is NASTY on our system */
56 #ifdef DEBUGGING
57     if (debug & 128) {
58         fprintf(stderr,"0x%x: (%05d) rfree\n",where,an++);
59         fprintf(stderr,"0x%x: (%05d) realloc %d bytes\n",ptr,an++,size);
60     }
61 #endif
62     if (ptr != Nullch)
63         return ptr;
64     else {
65         fputs(nomem,stdout) FLUSH;
66         exit(1);
67     }
68     /*NOTREACHED*/
69 }
70
71 /* safe version of free */
72
73 safefree(where)
74 char *where;
75 {
76 #ifdef DEBUGGING
77     if (debug & 128)
78         fprintf(stderr,"0x%x: (%05d) free\n",where,an++);
79 #endif
80     if (where) {
81         free(where);
82     }
83 }
84
85 #ifdef NOTDEF
86 /* safe version of string copy */
87
88 char *
89 safecpy(to,from,len)
90 char *to;
91 register char *from;
92 register int len;
93 {
94     register char *dest = to;
95
96     if (from != Nullch) 
97         for (len--; len && (*dest++ = *from++); len--) ;
98     *dest = '\0';
99     return to;
100 }
101 #endif /*NOTDEF*/
102
103 #ifdef undef
104 /* safe version of string concatenate, with \n deletion and space padding */
105
106 char *
107 safecat(to,from,len)
108 char *to;
109 register char *from;
110 register int len;
111 {
112     register char *dest = to;
113
114     len--;                              /* leave room for null */
115     if (*dest) {
116         while (len && *dest++) len--;
117         if (len) {
118             len--;
119             *(dest-1) = ' ';
120         }
121     }
122     if (from != Nullch)
123         while (len && (*dest++ = *from++)) len--;
124     if (len)
125         dest--;
126     if (*(dest-1) == '\n')
127         dest--;
128     *dest = '\0';
129     return to;
130 }
131 #endif
132
133 /* copy a string up to some (non-backslashed) delimiter, if any */
134
135 char *
136 cpytill(to,from,delim)
137 register char *to, *from;
138 register int delim;
139 {
140     for (; *from; from++,to++) {
141         if (*from == '\\') {
142             if (from[1] == delim)
143                 from++;
144             else if (from[1] == '\\')
145                 *to++ = *from++;
146         }
147         else if (*from == delim)
148             break;
149         *to = *from;
150     }
151     *to = '\0';
152     return from;
153 }
154
155 /* return ptr to little string in big string, NULL if not found */
156 /* This routine was donated by Corey Satten. */
157
158 char *
159 instr(big, little)
160 register char *big;
161 register char *little;
162 {
163     register char *s, *x;
164     register int first = *little++;
165
166     if (!first)
167         return big;
168     while (*big) {
169         if (*big++ != first)
170             continue;
171         for (x=big,s=little; *s; /**/ ) {
172             if (!*x)
173                 return Nullch;
174             if (*s++ != *x++) {
175                 s--;
176                 break;
177             }
178         }
179         if (!*s)
180             return big-1;
181     }
182     return Nullch;
183 }
184
185 #ifdef NOTDEF
186 void
187 bmcompile(str)
188 STR *str;
189 {
190     register char *s;
191     register char *table;
192     register int i;
193     register int len = str->str_cur;
194
195     str_grow(str,len+128);
196     s = str->str_ptr;
197     table = s + len;
198     for (i = 1; i < 128; i++) {
199         table[i] = len;
200     }
201     i = 0;
202     while (*s) {
203         if (!isascii(*s))
204             return;
205         if (table[*s] == len)
206             table[*s] = i;
207         s++,i++;
208     }
209     str->str_pok |= 2;          /* deep magic */
210 }
211 #endif /* NOTDEF */
212
213 static unsigned char freq[] = {
214         1,      2,      84,     151,    154,    155,    156,    157,
215         165,    246,    250,    3,      158,    7,      18,     29,
216         40,     51,     62,     73,     85,     96,     107,    118,
217         129,    140,    147,    148,    149,    150,    152,    153,
218         255,    182,    224,    205,    174,    176,    180,    217,
219         233,    232,    236,    187,    235,    228,    234,    226,
220         222,    219,    211,    195,    188,    193,    185,    184,
221         191,    183,    201,    229,    181,    220,    194,    162,
222         163,    208,    186,    202,    200,    218,    198,    179,
223         178,    214,    166,    170,    207,    199,    209,    206,
224         204,    160,    212,    216,    215,    192,    175,    173,
225         243,    172,    161,    190,    203,    189,    164,    230,
226         167,    248,    227,    244,    242,    255,    241,    231,
227         240,    253,    169,    210,    245,    237,    249,    247,
228         239,    168,    252,    251,    254,    238,    223,    221,
229         213,    225,    177,    197,    171,    196,    159,    4,
230         5,      6,      8,      9,      10,     11,     12,     13,
231         14,     15,     16,     17,     19,     20,     21,     22,
232         23,     24,     25,     26,     27,     28,     30,     31,
233         32,     33,     34,     35,     36,     37,     38,     39,
234         41,     42,     43,     44,     45,     46,     47,     48,
235         49,     50,     52,     53,     54,     55,     56,     57,
236         58,     59,     60,     61,     63,     64,     65,     66,
237         67,     68,     69,     70,     71,     72,     74,     75,
238         76,     77,     78,     79,     80,     81,     82,     83,
239         86,     87,     88,     89,     90,     91,     92,     93,
240         94,     95,     97,     98,     99,     100,    101,    102,
241         103,    104,    105,    106,    108,    109,    110,    111,
242         112,    113,    114,    115,    116,    117,    119,    120,
243         121,    122,    123,    124,    125,    126,    127,    128,
244         130,    131,    132,    133,    134,    135,    136,    137,
245         138,    139,    141,    142,    143,    144,    145,    146
246 };
247
248 void
249 fbmcompile(str)
250 STR *str;
251 {
252     register char *s;
253     register char *table;
254     register int i;
255     register int len = str->str_cur;
256     int rarest = 0;
257     int frequency = 256;
258
259     str_grow(str,len+128);
260     table = str->str_ptr + len;         /* actually points at final '\0' */
261     s = table - 1;
262     for (i = 1; i < 128; i++) {
263         table[i] = len;
264     }
265     i = 0;
266     while (s >= str->str_ptr) {
267         if (!isascii(*s))
268             return;
269         if (table[*s] == len)
270             table[*s] = i;
271         s--,i++;
272     }
273     str->str_pok |= 2;          /* deep magic */
274
275     s = str->str_ptr;           /* deeper magic */
276     for (i = 0; i < len; i++) {
277         if (freq[s[i]] < frequency) {
278             rarest = i;
279             frequency = freq[s[i]];
280         }
281     }
282     str->str_rare = s[rarest];
283     str->str_prev = rarest;
284 #ifdef DEBUGGING
285     if (debug & 512)
286         fprintf(stderr,"rarest char %c at %d\n",str->str_rare, str->str_prev);
287 #endif
288 }
289
290 #ifdef NOTDEF
291 char *
292 bminstr(big, biglen, littlestr)
293 register char *big;
294 int biglen;
295 STR *littlestr;
296 {
297     register char *s;
298     register int tmp;
299     register char *little = littlestr->str_ptr;
300     int littlelen = littlestr->str_cur;
301     register char *table = little + littlelen;
302
303     s = big + biglen - littlelen;
304     while (s >= big) {
305         if (tmp = table[*s]) {
306             s -= tmp;
307         }
308         else {
309             if (strnEQ(s,little,littlelen))
310                 return s;
311             s--;
312         }
313     }
314     return Nullch;
315 }
316 #endif /* NOTDEF */
317
318 char *
319 fbminstr(big, bigend, littlestr)
320 char *big;
321 register char *bigend;
322 STR *littlestr;
323 {
324     register char *s;
325     register int tmp;
326     register int littlelen;
327     register char *little;
328     register char *table;
329     register char *olds;
330     register char *oldlittle;
331     register int min;
332     char *screaminstr();
333
334     if (littlestr->str_pok != 3)
335         return instr(big,littlestr->str_ptr);
336
337     littlelen = littlestr->str_cur;
338     table = littlestr->str_ptr + littlelen;
339     s = big + --littlelen;
340     oldlittle = little = table - 1;
341     while (s < bigend) {
342       top:
343         if (tmp = table[*s]) {
344             s += tmp;
345         }
346         else {
347             tmp = littlelen;    /* less expensive than calling strncmp() */
348             olds = s;
349             while (tmp--) {
350                 if (*--s == *--little)
351                     continue;
352                 s = olds + 1;   /* here we pay the price for failure */
353                 little = oldlittle;
354                 if (s < bigend) /* fake up continue to outer loop */
355                     goto top;
356                 return Nullch;
357             }
358             return s;
359         }
360     }
361     return Nullch;
362 }
363
364 char *
365 screaminstr(bigstr, littlestr)
366 STR *bigstr;
367 STR *littlestr;
368 {
369     register char *s, *x;
370     register char *big = bigstr->str_ptr;
371     register int pos;
372     register int previous;
373     register int first;
374     register char *little;
375
376     if ((pos = screamfirst[littlestr->str_rare]) < 0) 
377         return Nullch;
378     little = littlestr->str_ptr;
379     first = *little++;
380     previous = littlestr->str_prev;
381     big -= previous;
382     while (pos < previous) {
383         if (!(pos += screamnext[pos]))
384             return Nullch;
385     }
386     do {
387         if (big[pos] != first)
388             continue;
389         for (x=big+pos+1,s=little; *s; /**/ ) {
390             if (!*x)
391                 return Nullch;
392             if (*s++ != *x++) {
393                 s--;
394                 break;
395             }
396         }
397         if (!*s)
398             return big+pos;
399     } while (pos += screamnext[pos]);
400     return Nullch;
401 }
402
403 /* copy a string to a safe spot */
404
405 char *
406 savestr(str)
407 char *str;
408 {
409     register char *newaddr = safemalloc((MEM_SIZE)(strlen(str)+1));
410
411     (void)strcpy(newaddr,str);
412     return newaddr;
413 }
414
415 /* grow a static string to at least a certain length */
416
417 void
418 growstr(strptr,curlen,newlen)
419 char **strptr;
420 int *curlen;
421 int newlen;
422 {
423     if (newlen > *curlen) {             /* need more room? */
424         if (*curlen)
425             *strptr = saferealloc(*strptr,(MEM_SIZE)newlen);
426         else
427             *strptr = safemalloc((MEM_SIZE)newlen);
428         *curlen = newlen;
429     }
430 }
431
432 extern int errno;
433
434 /*VARARGS1*/
435 mess(pat,a1,a2,a3,a4)
436 char *pat;
437 {
438     char *s;
439
440     s = tokenbuf;
441     sprintf(s,pat,a1,a2,a3,a4);
442     s += strlen(s);
443     if (s[-1] != '\n') {
444         if (line) {
445             sprintf(s," at %s line %ld",
446               in_eval?filename:origfilename, (long)line);
447             s += strlen(s);
448         }
449         if (last_in_stab &&
450             last_in_stab->stab_io &&
451             last_in_stab->stab_io->lines ) {
452             sprintf(s,", <%s> line %ld",
453               last_in_stab == argvstab ? "" : last_in_stab->stab_name,
454               (long)last_in_stab->stab_io->lines);
455             s += strlen(s);
456         }
457         strcpy(s,".\n");
458     }
459 }
460
461 /*VARARGS1*/
462 fatal(pat,a1,a2,a3,a4)
463 char *pat;
464 {
465     extern FILE *e_fp;
466     extern char *e_tmpname;
467
468     mess(pat,a1,a2,a3,a4);
469     if (in_eval) {
470         str_set(stabent("@",TRUE)->stab_val,tokenbuf);
471         longjmp(eval_env,1);
472     }
473     fputs(tokenbuf,stderr);
474     fflush(stderr);
475     if (e_fp)
476         UNLINK(e_tmpname);
477     statusvalue >>= 8;
478     exit(errno?errno:(statusvalue?statusvalue:255));
479 }
480
481 /*VARARGS1*/
482 warn(pat,a1,a2,a3,a4)
483 char *pat;
484 {
485     mess(pat,a1,a2,a3,a4);
486     fputs(tokenbuf,stderr);
487     fflush(stderr);
488 }
489
490 static bool firstsetenv = TRUE;
491 extern char **environ;
492
493 void
494 setenv(nam,val)
495 char *nam, *val;
496 {
497     register int i=envix(nam);          /* where does it go? */
498
499     if (!environ[i]) {                  /* does not exist yet */
500         if (firstsetenv) {              /* need we copy environment? */
501             int j;
502 #ifndef lint
503             char **tmpenv = (char**)    /* point our wand at memory */
504                 safemalloc((i+2) * sizeof(char*));
505 #else
506             char **tmpenv = Null(char **);
507 #endif /* lint */
508     
509             firstsetenv = FALSE;
510             for (j=0; j<i; j++)         /* copy environment */
511                 tmpenv[j] = environ[j];
512             environ = tmpenv;           /* tell exec where it is now */
513         }
514 #ifndef lint
515         else
516             environ = (char**) saferealloc((char*) environ,
517                 (i+2) * sizeof(char*));
518                                         /* just expand it a bit */
519 #endif /* lint */
520         environ[i+1] = Nullch;  /* make sure it's null terminated */
521     }
522     environ[i] = safemalloc((MEM_SIZE)(strlen(nam) + strlen(val) + 2));
523                                         /* this may or may not be in */
524                                         /* the old environ structure */
525     sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
526 }
527
528 int
529 envix(nam)
530 char *nam;
531 {
532     register int i, len = strlen(nam);
533
534     for (i = 0; environ[i]; i++) {
535         if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
536             break;                      /* strnEQ must come first to avoid */
537     }                                   /* potential SEGV's */
538     return i;
539 }
540
541 #ifdef EUNICE
542 unlnk(f)        /* unlink all versions of a file */
543 char *f;
544 {
545     int i;
546
547     for (i = 0; unlink(f) >= 0; i++) ;
548     return i ? 0 : -1;
549 }
550 #endif
551
552 #ifndef BCOPY
553 #ifndef MEMCPY
554 char *
555 bcopy(from,to,len)
556 register char *from;
557 register char *to;
558 register int len;
559 {
560     char *retval = to;
561
562     while (len--)
563         *to++ = *from++;
564     return retval;
565 }
566
567 char *
568 bzero(loc,len)
569 register char *loc;
570 register int len;
571 {
572     char *retval = loc;
573
574     while (len--)
575         *loc++ = 0;
576     return retval;
577 }
578 #endif
579 #endif