1 /* $Header: util.c,v 3.0.1.4 90/03/01 10:26:48 lwall Locked $
3 * Copyright (c) 1989, Larry Wall
5 * You may distribute under the terms of the GNU General Public License
6 * as specified in the README file that comes with the perl 3.0 kit.
9 * Revision 3.0.1.4 90/03/01 10:26:48 lwall
10 * patch9: fbminstr() called instr() rather than ninstr()
11 * patch9: nested evals clobbered their longjmp environment
12 * patch9: piped opens returned undefined rather than 0 in child
13 * patch9: the x operator is now up to 10 times faster
15 * Revision 3.0.1.3 89/12/21 20:27:41 lwall
16 * patch7: errno may now be a macro with an lvalue
18 * Revision 3.0.1.2 89/11/17 15:46:35 lwall
19 * patch5: BZERO separate from BCOPY now
20 * patch5: byteorder now is a hex value
22 * Revision 3.0.1.1 89/11/11 05:06:13 lwall
23 * patch2: made dup2 a little better
25 * Revision 3.0 89/10/18 15:32:43 lwall
44 static char nomem[] = "Out of memory!\n";
46 /* paranoid version of malloc */
52 /* NOTE: Do not call the next three routines directly. Use the macros
53 * in handy.h, so that we can easily redefine everything to do tracking of
54 * allocated hunks back to the original New to track down any memory leaks.
64 ptr = malloc(size?size:1); /* malloc(0) is NASTY on our system */
68 fprintf(stderr,"0x%x: (%05d) malloc %d bytes\n",ptr,an++,size);
71 fprintf(stderr,"0x%lx: (%05d) malloc %d bytes\n",ptr,an++,size);
77 fputs(nomem,stdout) FLUSH;
86 /* paranoid version of realloc */
89 saferealloc(where,size)
97 fatal("Null realloc");
98 ptr = realloc(where,size?size:1); /* realloc(0) is NASTY on our system */
102 fprintf(stderr,"0x%x: (%05d) rfree\n",where,an++);
103 fprintf(stderr,"0x%x: (%05d) realloc %d bytes\n",ptr,an++,size);
107 fprintf(stderr,"0x%lx: (%05d) rfree\n",where,an++);
108 fprintf(stderr,"0x%lx: (%05d) realloc %d bytes\n",ptr,an++,size);
115 fputs(nomem,stdout) FLUSH;
124 /* safe version of free */
133 fprintf(stderr,"0x%x: (%05d) free\n",where,an++);
136 fprintf(stderr,"0x%lx: (%05d) free\n",where,an++);
146 #define ALIGN sizeof(long)
153 register char *where;
155 where = safemalloc(size + ALIGN);
159 return where + ALIGN;
163 safexrealloc(where,size)
167 return saferealloc(where - ALIGN, size + ALIGN) + ALIGN;
179 x = where[0] + 100 * where[1];
188 for (i = 0; i < MAXXCOUNT; i++) {
189 if (xcount[i] != lastxcount[i]) {
190 fprintf(stderr,"%2d %2d\t%ld\n", i / 100, i % 100, xcount[i]);
191 lastxcount[i] = xcount[i];
196 #endif /* LEAKTEST */
198 /* copy a string up to some (non-backslashed) delimiter, if any */
201 cpytill(to,from,fromend,delim,retlen)
202 register char *to, *from;
203 register char *fromend;
209 for (; from < fromend; from++,to++) {
211 if (from[1] == delim)
213 else if (from[1] == '\\')
216 else if (*from == delim)
221 *retlen = to - origto;
225 /* return ptr to little string in big string, NULL if not found */
226 /* This routine was donated by Corey Satten. */
231 register char *little;
233 register char *s, *x;
244 for (x=big,s=little; *s; /**/ ) {
258 /* same as instr but allow embedded nulls */
261 ninstr(big, bigend, little, lend)
263 register char *bigend;
267 register char *s, *x;
268 register int first = *little;
269 register char *littleend = lend;
271 if (!first && little > littleend)
273 bigend -= littleend - little++;
274 while (big <= bigend) {
277 for (x=big,s=little; s < littleend; /**/ ) {
289 /* reverse of the above--find last substring */
292 rninstr(big, bigend, little, lend)
298 register char *bigbeg;
299 register char *s, *x;
300 register int first = *little;
301 register char *littleend = lend;
303 if (!first && little > littleend)
306 big = bigend - (littleend - little++);
307 while (big >= bigbeg) {
310 for (x=big+2,s=little; s < littleend; /**/ ) {
322 unsigned char fold[] = {
323 0, 1, 2, 3, 4, 5, 6, 7,
324 8, 9, 10, 11, 12, 13, 14, 15,
325 16, 17, 18, 19, 20, 21, 22, 23,
326 24, 25, 26, 27, 28, 29, 30, 31,
327 32, 33, 34, 35, 36, 37, 38, 39,
328 40, 41, 42, 43, 44, 45, 46, 47,
329 48, 49, 50, 51, 52, 53, 54, 55,
330 56, 57, 58, 59, 60, 61, 62, 63,
331 64, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
332 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
333 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
334 'x', 'y', 'z', 91, 92, 93, 94, 95,
335 96, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
336 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
337 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
338 'X', 'Y', 'Z', 123, 124, 125, 126, 127,
339 128, 129, 130, 131, 132, 133, 134, 135,
340 136, 137, 138, 139, 140, 141, 142, 143,
341 144, 145, 146, 147, 148, 149, 150, 151,
342 152, 153, 154, 155, 156, 157, 158, 159,
343 160, 161, 162, 163, 164, 165, 166, 167,
344 168, 169, 170, 171, 172, 173, 174, 175,
345 176, 177, 178, 179, 180, 181, 182, 183,
346 184, 185, 186, 187, 188, 189, 190, 191,
347 192, 193, 194, 195, 196, 197, 198, 199,
348 200, 201, 202, 203, 204, 205, 206, 207,
349 208, 209, 210, 211, 212, 213, 214, 215,
350 216, 217, 218, 219, 220, 221, 222, 223,
351 224, 225, 226, 227, 228, 229, 230, 231,
352 232, 233, 234, 235, 236, 237, 238, 239,
353 240, 241, 242, 243, 244, 245, 246, 247,
354 248, 249, 250, 251, 252, 253, 254, 255
357 static unsigned char freq[] = {
358 1, 2, 84, 151, 154, 155, 156, 157,
359 165, 246, 250, 3, 158, 7, 18, 29,
360 40, 51, 62, 73, 85, 96, 107, 118,
361 129, 140, 147, 148, 149, 150, 152, 153,
362 255, 182, 224, 205, 174, 176, 180, 217,
363 233, 232, 236, 187, 235, 228, 234, 226,
364 222, 219, 211, 195, 188, 193, 185, 184,
365 191, 183, 201, 229, 181, 220, 194, 162,
366 163, 208, 186, 202, 200, 218, 198, 179,
367 178, 214, 166, 170, 207, 199, 209, 206,
368 204, 160, 212, 216, 215, 192, 175, 173,
369 243, 172, 161, 190, 203, 189, 164, 230,
370 167, 248, 227, 244, 242, 255, 241, 231,
371 240, 253, 169, 210, 245, 237, 249, 247,
372 239, 168, 252, 251, 254, 238, 223, 221,
373 213, 225, 177, 197, 171, 196, 159, 4,
374 5, 6, 8, 9, 10, 11, 12, 13,
375 14, 15, 16, 17, 19, 20, 21, 22,
376 23, 24, 25, 26, 27, 28, 30, 31,
377 32, 33, 34, 35, 36, 37, 38, 39,
378 41, 42, 43, 44, 45, 46, 47, 48,
379 49, 50, 52, 53, 54, 55, 56, 57,
380 58, 59, 60, 61, 63, 64, 65, 66,
381 67, 68, 69, 70, 71, 72, 74, 75,
382 76, 77, 78, 79, 80, 81, 82, 83,
383 86, 87, 88, 89, 90, 91, 92, 93,
384 94, 95, 97, 98, 99, 100, 101, 102,
385 103, 104, 105, 106, 108, 109, 110, 111,
386 112, 113, 114, 115, 116, 117, 119, 120,
387 121, 122, 123, 124, 125, 126, 127, 128,
388 130, 131, 132, 133, 134, 135, 136, 137,
389 138, 139, 141, 142, 143, 144, 145, 146
393 fbmcompile(str, iflag)
397 register unsigned char *s;
398 register unsigned char *table;
400 register int len = str->str_cur;
404 str_grow(str,len+258);
406 table = (unsigned char*)(str->str_ptr + len + 1);
408 table = Null(unsigned char*);
411 for (i = 0; i < 256; i++) {
416 while (s >= (unsigned char*)(str->str_ptr))
419 if (table[*s] == len) {
422 table[*s] = table[fold[*s]] = i;
436 str->str_pok |= SP_FBM; /* deep magic */
439 s = (unsigned char*)(str->str_ptr); /* deeper magic */
441 s = Null(unsigned char*);
444 register int tmp, foldtmp;
445 str->str_pok |= SP_CASEFOLD;
446 for (i = 0; i < len; i++) {
448 foldtmp=freq[fold[s[i]]];
449 if (tmp < frequency && foldtmp < frequency) {
451 /* choose most frequent among the two */
452 frequency = (tmp > foldtmp) ? tmp : foldtmp;
457 for (i = 0; i < len; i++) {
458 if (freq[s[i]] < frequency) {
460 frequency = freq[s[i]];
464 str->str_rare = s[rarest];
465 str->str_state = rarest;
468 fprintf(stderr,"rarest char %c at %d\n",str->str_rare, str->str_state);
473 fbminstr(big, bigend, littlestr)
475 register unsigned char *bigend;
478 register unsigned char *s;
480 register int littlelen;
481 register unsigned char *little;
482 register unsigned char *table;
483 register unsigned char *olds;
484 register unsigned char *oldlittle;
487 if (!(littlestr->str_pok & SP_FBM))
488 return ninstr((char*)big,(char*)bigend,
489 littlestr->str_ptr, littlestr->str_ptr + littlestr->str_cur);
492 littlelen = littlestr->str_cur;
494 if (littlestr->str_pok & SP_TAIL && !multiline) { /* tail anchored? */
495 little = (unsigned char*)littlestr->str_ptr;
496 if (littlestr->str_pok & SP_CASEFOLD) { /* oops, fake it */
497 big = bigend - littlelen; /* just start near end */
498 if (bigend[-1] == '\n' && little[littlelen-1] != '\n')
502 s = bigend - littlelen;
503 if (*s == *little && bcmp(s,little,littlelen)==0)
504 return (char*)s; /* how sweet it is */
505 else if (bigend[-1] == '\n' && little[littlelen-1] != '\n') {
507 if (*s == *little && bcmp(s,little,littlelen)==0)
513 table = (unsigned char*)(littlestr->str_ptr + littlelen + 1);
515 table = Null(unsigned char*);
517 s = big + --littlelen;
518 oldlittle = little = table - 2;
519 if (littlestr->str_pok & SP_CASEFOLD) { /* case insensitive? */
522 if (tmp = table[*s]) {
526 tmp = littlelen; /* less expensive than calling strncmp() */
529 if (*--s == *--little || fold[*s] == *little)
531 s = olds + 1; /* here we pay the price for failure */
533 if (s < bigend) /* fake up continue to outer loop */
546 if (tmp = table[*s]) {
550 tmp = littlelen; /* less expensive than calling strncmp() */
553 if (*--s == *--little)
555 s = olds + 1; /* here we pay the price for failure */
557 if (s < bigend) /* fake up continue to outer loop */
571 screaminstr(bigstr, littlestr)
575 register unsigned char *s, *x;
576 register unsigned char *big;
578 register int previous;
580 register unsigned char *little;
581 register unsigned char *bigend;
582 register unsigned char *littleend;
584 if ((pos = screamfirst[littlestr->str_rare]) < 0)
587 little = (unsigned char *)(littlestr->str_ptr);
589 little = Null(unsigned char *);
591 littleend = little + littlestr->str_cur;
593 previous = littlestr->str_state;
595 big = (unsigned char *)(bigstr->str_ptr);
597 big = Null(unsigned char*);
599 bigend = big + bigstr->str_cur;
601 while (pos < previous) {
603 if (!(pos += screamnext[pos]))
607 if (littlestr->str_pok & SP_CASEFOLD) { /* case insignificant? */
609 if (big[pos] != first && big[pos] != fold[first])
611 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
614 if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
621 return (char *)(big+pos);
627 pos += screamnext[pos] /* does this goof up anywhere? */
635 if (big[pos] != first)
637 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
647 return (char *)(big+pos);
653 pos += screamnext[pos]
662 /* copy a string to a safe spot */
668 register char *newaddr;
670 New(902,newaddr,strlen(str)+1,char);
671 (void)strcpy(newaddr,str);
675 /* same thing but with a known length */
682 register char *newaddr;
684 New(903,newaddr,len+1,char);
685 (void)bcopy(str,newaddr,len); /* might not be null terminated */
686 newaddr[len] = '\0'; /* is now */
690 /* grow a static string to at least a certain length */
693 growstr(strptr,curlen,newlen)
698 if (newlen > *curlen) { /* need more room? */
700 Renew(*strptr,newlen,char);
702 New(905,*strptr,newlen,char);
709 mess(pat,a1,a2,a3,a4)
716 (void)sprintf(s,pat,a1,a2,a3,a4);
720 (void)sprintf(s," at %s line %ld",
721 in_eval?filename:origfilename, (long)line);
725 stab_io(last_in_stab) &&
726 stab_io(last_in_stab)->lines ) {
727 (void)sprintf(s,", <%s> line %ld",
728 last_in_stab == argvstab ? "" : stab_name(last_in_stab),
729 (long)stab_io(last_in_stab)->lines);
732 (void)strcpy(s,".\n");
737 fatal(pat,a1,a2,a3,a4)
742 extern char *e_tmpname;
745 mess(pat,a1,a2,a3,a4);
747 str_set(stab_val(stabent("@",TRUE)),buf);
749 while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
750 strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
753 deb("(Skipping label #%d %s)\n",loop_ptr,
754 loop_stack[loop_ptr].loop_label);
761 deb("(Found label #%d %s)\n",loop_ptr,
762 loop_stack[loop_ptr].loop_label);
767 fatal("Bad label: %s", tmps);
769 longjmp(loop_stack[loop_ptr].loop_env, 1);
772 (void)fflush(stderr);
774 (void)UNLINK(e_tmpname);
776 exit(errno?errno:(statusvalue?statusvalue:255));
780 warn(pat,a1,a2,a3,a4)
784 mess(pat,a1,a2,a3,a4);
792 (void)fflush(stderr);
811 pat = va_arg(args, char *);
813 (void) vsprintf(s,pat,args);
818 (void)sprintf(s," at %s line %ld",
819 in_eval?filename:origfilename, (long)line);
823 stab_io(last_in_stab) &&
824 stab_io(last_in_stab)->lines ) {
825 (void)sprintf(s,", <%s> line %ld",
826 last_in_stab == argvstab ? "" : last_in_stab->str_magic->str_ptr,
827 (long)stab_io(last_in_stab)->lines);
830 (void)strcpy(s,".\n");
840 extern char *e_tmpname;
851 str_set(stab_val(stabent("@",TRUE)),buf);
853 while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
854 strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
857 deb("(Skipping label #%d %s)\n",loop_ptr,
858 loop_stack[loop_ptr].loop_label);
865 deb("(Found label #%d %s)\n",loop_ptr,
866 loop_stack[loop_ptr].loop_label);
871 fatal("Bad label: %s", tmps);
873 longjmp(loop_stack[loop_ptr].loop_env, 1);
876 (void)fflush(stderr);
878 (void)UNLINK(e_tmpname);
880 exit((int)(errno?errno:(statusvalue?statusvalue:255)));
904 (void)fflush(stderr);
908 static bool firstsetenv = TRUE;
909 extern char **environ;
915 register int i=envix(nam); /* where does it go? */
919 environ[i] = environ[i+1];
924 if (!environ[i]) { /* does not exist yet */
925 if (firstsetenv) { /* need we copy environment? */
929 New(901,tmpenv, i+2, char*);
931 for (j=0; j<i; j++) /* copy environment */
932 tmpenv[j] = environ[j];
933 environ = tmpenv; /* tell exec where it is now */
936 Renew(environ, i+2, char*); /* just expand it a bit */
937 environ[i+1] = Nullch; /* make sure it's null terminated */
939 New(904, environ[i], strlen(nam) + strlen(val) + 2, char);
940 /* this may or may not be in */
941 /* the old environ structure */
942 (void)sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
949 register int i, len = strlen(nam);
951 for (i = 0; environ[i]; i++) {
952 if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
953 break; /* strnEQ must come first to avoid */
954 } /* potential SEGV's */
959 unlnk(f) /* unlink all versions of a file */
964 for (i = 0; unlink(f) >= 0; i++) ;
1008 vsprintf(dest, pat, args)
1009 char *dest, *pat, *args;
1013 fakebuf._ptr = dest;
1014 fakebuf._cnt = 32767;
1015 fakebuf._flag = _IOWRT|_IOSTRG;
1016 _doprnt(pat, args, &fakebuf); /* what a kludge */
1017 (void)putc('\0', &fakebuf);
1021 return 0; /* perl doesn't use return value */
1027 vfprintf(fd, pat, args)
1031 _doprnt(pat, args, fd);
1032 return 0; /* wrong, but perl doesn't use the return value */
1035 #endif /* VPRINTF */
1036 #endif /* VARARGS */
1039 #if BYTEORDER != 0x4321
1044 #if (BYTEORDER & 1) == 0
1047 result = ((s & 255) << 8) + ((s >> 8) & 255);
1060 char c[sizeof(long)];
1063 #if BYTEORDER == 0x1234
1064 u.c[0] = (l >> 24) & 255;
1065 u.c[1] = (l >> 16) & 255;
1066 u.c[2] = (l >> 8) & 255;
1070 #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
1071 fatal("Unknown BYTEORDER\n");
1076 for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
1077 u.c[o & 0xf] = (l >> s) & 255;
1090 char c[sizeof(long)];
1093 #if BYTEORDER == 0x1234
1094 u.c[0] = (l >> 24) & 255;
1095 u.c[1] = (l >> 16) & 255;
1096 u.c[2] = (l >> 8) & 255;
1100 #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
1101 fatal("Unknown BYTEORDER\n");
1108 for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
1109 l |= (u.c[o & 0xf] & 255) << s;
1116 #endif /* BYTEORDER != 0x4321 */
1125 register int this, that;
1128 int doexec = strNE(cmd,"-");
1132 this = (*mode == 'w');
1134 while ((pid = (doexec?vfork():fork())) < 0) {
1135 if (errno != EAGAIN) {
1138 fatal("Can't fork");
1147 if (p[THIS] != (*mode == 'r')) {
1148 dup2(p[THIS], *mode == 'r');
1152 #if !defined(FCNTL) || !defined(F_SETFD)
1158 for (fd = 3; fd < NOFILE; fd++)
1161 do_exec(cmd); /* may or may not use the shell */
1164 if (tmpstab = stabent("$",allstabs))
1165 str_numset(STAB_STR(tmpstab),(double)getpid());
1172 str = afetch(pidstatary,p[this],TRUE);
1173 str_numset(str,(double)pid);
1176 return fdopen(p[this], mode);
1184 struct stat tmpstatbuf;
1186 fprintf(stderr,"%s", s);
1187 for (fd = 0; fd < 32; fd++) {
1188 if (fstat(fd,&tmpstatbuf) >= 0)
1189 fprintf(stderr," %d",fd);
1191 fprintf(stderr,"\n");
1205 while ((fd = dup(oldfd)) != newfd) /* good enough for low fd's */
1208 close(fdtmp[--fdx]);
1216 register int result;
1218 void (*hstat)(), (*istat)(), (*qstat)();
1220 int (*hstat)(), (*istat)(), (*qstat)();
1226 str = afetch(pidstatary,fileno(ptr),TRUE);
1228 pid = (int)str_gnum(str);
1231 hstat = signal(SIGHUP, SIG_IGN);
1232 istat = signal(SIGINT, SIG_IGN);
1233 qstat = signal(SIGQUIT, SIG_IGN);
1235 if (wait4(pid,&status,0,Null(struct rusage *)) < 0)
1238 if (pid < 0) /* already exited? */
1239 status = str->str_cur;
1241 while ((result = wait(&status)) != pid && result >= 0)
1242 pidgone(result,status);
1247 signal(SIGHUP, hstat);
1248 signal(SIGINT, istat);
1249 signal(SIGQUIT, qstat);
1250 str_numset(str,0.0);
1264 for (count = pidstatary->ary_fill; count >= 0; --count) {
1265 if ((str = afetch(pidstatary,count,FALSE)) &&
1266 ((int)str->str_u.str_nval) == pid) {
1267 str_numset(str, -str->str_u.str_nval);
1268 str->str_cur = status;
1277 register unsigned char *s1;
1278 register unsigned char *s2;
1284 if (tmp = *s1++ - *s2++)
1292 repeatcpy(to,from,len,count)
1294 register char *from;
1299 register char *frombase = from;
1307 while (count-- > 0) {
1308 for (todo = len; todo > 0; todo--) {