1 /* $Header: util.c,v 3.0 89/10/18 15:32:43 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 89/10/18 15:32:43 lwall
29 static char nomem[] = "Out of memory!\n";
31 /* paranoid version of malloc */
37 /* NOTE: Do not call the next three routines directly. Use the macros
38 * in handy.h, so that we can easily redefine everything to do tracking of
39 * allocated hunks back to the original New to track down any memory leaks.
49 ptr = malloc(size?size:1); /* malloc(0) is NASTY on our system */
53 fprintf(stderr,"0x%x: (%05d) malloc %d bytes\n",ptr,an++,size);
56 fprintf(stderr,"0x%lx: (%05d) malloc %d bytes\n",ptr,an++,size);
62 fputs(nomem,stdout) FLUSH;
71 /* paranoid version of realloc */
74 saferealloc(where,size)
82 fatal("Null realloc");
83 ptr = realloc(where,size?size:1); /* realloc(0) is NASTY on our system */
87 fprintf(stderr,"0x%x: (%05d) rfree\n",where,an++);
88 fprintf(stderr,"0x%x: (%05d) realloc %d bytes\n",ptr,an++,size);
92 fprintf(stderr,"0x%lx: (%05d) rfree\n",where,an++);
93 fprintf(stderr,"0x%lx: (%05d) realloc %d bytes\n",ptr,an++,size);
100 fputs(nomem,stdout) FLUSH;
109 /* safe version of free */
118 fprintf(stderr,"0x%x: (%05d) free\n",where,an++);
121 fprintf(stderr,"0x%lx: (%05d) free\n",where,an++);
131 #define ALIGN sizeof(long)
138 register char *where;
140 where = safemalloc(size + ALIGN);
144 return where + ALIGN;
148 safexrealloc(where,size)
152 return saferealloc(where - ALIGN, size + ALIGN) + ALIGN;
164 x = where[0] + 100 * where[1];
173 for (i = 0; i < MAXXCOUNT; i++) {
174 if (xcount[i] != lastxcount[i]) {
175 fprintf(stderr,"%2d %2d\t%ld\n", i / 100, i % 100, xcount[i]);
176 lastxcount[i] = xcount[i];
181 #endif /* LEAKTEST */
183 /* copy a string up to some (non-backslashed) delimiter, if any */
186 cpytill(to,from,fromend,delim,retlen)
187 register char *to, *from;
188 register char *fromend;
194 for (; from < fromend; from++,to++) {
196 if (from[1] == delim)
198 else if (from[1] == '\\')
201 else if (*from == delim)
206 *retlen = to - origto;
210 /* return ptr to little string in big string, NULL if not found */
211 /* This routine was donated by Corey Satten. */
216 register char *little;
218 register char *s, *x;
229 for (x=big,s=little; *s; /**/ ) {
243 /* same as instr but allow embedded nulls */
246 ninstr(big, bigend, little, lend)
248 register char *bigend;
252 register char *s, *x;
253 register int first = *little;
254 register char *littleend = lend;
256 if (!first && little > littleend)
258 bigend -= littleend - little++;
259 while (big <= bigend) {
262 for (x=big,s=little; s < littleend; /**/ ) {
274 /* reverse of the above--find last substring */
277 rninstr(big, bigend, little, lend)
283 register char *bigbeg;
284 register char *s, *x;
285 register int first = *little;
286 register char *littleend = lend;
288 if (!first && little > littleend)
291 big = bigend - (littleend - little++);
292 while (big >= bigbeg) {
295 for (x=big+2,s=little; s < littleend; /**/ ) {
307 unsigned char fold[] = {
308 0, 1, 2, 3, 4, 5, 6, 7,
309 8, 9, 10, 11, 12, 13, 14, 15,
310 16, 17, 18, 19, 20, 21, 22, 23,
311 24, 25, 26, 27, 28, 29, 30, 31,
312 32, 33, 34, 35, 36, 37, 38, 39,
313 40, 41, 42, 43, 44, 45, 46, 47,
314 48, 49, 50, 51, 52, 53, 54, 55,
315 56, 57, 58, 59, 60, 61, 62, 63,
316 64, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
317 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
318 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
319 'x', 'y', 'z', 91, 92, 93, 94, 95,
320 96, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
321 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
322 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
323 'X', 'Y', 'Z', 123, 124, 125, 126, 127,
324 128, 129, 130, 131, 132, 133, 134, 135,
325 136, 137, 138, 139, 140, 141, 142, 143,
326 144, 145, 146, 147, 148, 149, 150, 151,
327 152, 153, 154, 155, 156, 157, 158, 159,
328 160, 161, 162, 163, 164, 165, 166, 167,
329 168, 169, 170, 171, 172, 173, 174, 175,
330 176, 177, 178, 179, 180, 181, 182, 183,
331 184, 185, 186, 187, 188, 189, 190, 191,
332 192, 193, 194, 195, 196, 197, 198, 199,
333 200, 201, 202, 203, 204, 205, 206, 207,
334 208, 209, 210, 211, 212, 213, 214, 215,
335 216, 217, 218, 219, 220, 221, 222, 223,
336 224, 225, 226, 227, 228, 229, 230, 231,
337 232, 233, 234, 235, 236, 237, 238, 239,
338 240, 241, 242, 243, 244, 245, 246, 247,
339 248, 249, 250, 251, 252, 253, 254, 255
342 static unsigned char freq[] = {
343 1, 2, 84, 151, 154, 155, 156, 157,
344 165, 246, 250, 3, 158, 7, 18, 29,
345 40, 51, 62, 73, 85, 96, 107, 118,
346 129, 140, 147, 148, 149, 150, 152, 153,
347 255, 182, 224, 205, 174, 176, 180, 217,
348 233, 232, 236, 187, 235, 228, 234, 226,
349 222, 219, 211, 195, 188, 193, 185, 184,
350 191, 183, 201, 229, 181, 220, 194, 162,
351 163, 208, 186, 202, 200, 218, 198, 179,
352 178, 214, 166, 170, 207, 199, 209, 206,
353 204, 160, 212, 216, 215, 192, 175, 173,
354 243, 172, 161, 190, 203, 189, 164, 230,
355 167, 248, 227, 244, 242, 255, 241, 231,
356 240, 253, 169, 210, 245, 237, 249, 247,
357 239, 168, 252, 251, 254, 238, 223, 221,
358 213, 225, 177, 197, 171, 196, 159, 4,
359 5, 6, 8, 9, 10, 11, 12, 13,
360 14, 15, 16, 17, 19, 20, 21, 22,
361 23, 24, 25, 26, 27, 28, 30, 31,
362 32, 33, 34, 35, 36, 37, 38, 39,
363 41, 42, 43, 44, 45, 46, 47, 48,
364 49, 50, 52, 53, 54, 55, 56, 57,
365 58, 59, 60, 61, 63, 64, 65, 66,
366 67, 68, 69, 70, 71, 72, 74, 75,
367 76, 77, 78, 79, 80, 81, 82, 83,
368 86, 87, 88, 89, 90, 91, 92, 93,
369 94, 95, 97, 98, 99, 100, 101, 102,
370 103, 104, 105, 106, 108, 109, 110, 111,
371 112, 113, 114, 115, 116, 117, 119, 120,
372 121, 122, 123, 124, 125, 126, 127, 128,
373 130, 131, 132, 133, 134, 135, 136, 137,
374 138, 139, 141, 142, 143, 144, 145, 146
378 fbmcompile(str, iflag)
382 register unsigned char *s;
383 register unsigned char *table;
385 register int len = str->str_cur;
389 str_grow(str,len+258);
391 table = (unsigned char*)(str->str_ptr + len + 1);
393 table = Null(unsigned char*);
396 for (i = 0; i < 256; i++) {
401 while (s >= (unsigned char*)(str->str_ptr))
404 if (table[*s] == len) {
407 table[*s] = table[fold[*s]] = i;
421 str->str_pok |= SP_FBM; /* deep magic */
424 s = (unsigned char*)(str->str_ptr); /* deeper magic */
426 s = Null(unsigned char*);
429 register int tmp, foldtmp;
430 str->str_pok |= SP_CASEFOLD;
431 for (i = 0; i < len; i++) {
433 foldtmp=freq[fold[s[i]]];
434 if (tmp < frequency && foldtmp < frequency) {
436 /* choose most frequent among the two */
437 frequency = (tmp > foldtmp) ? tmp : foldtmp;
442 for (i = 0; i < len; i++) {
443 if (freq[s[i]] < frequency) {
445 frequency = freq[s[i]];
449 str->str_rare = s[rarest];
450 str->str_state = rarest;
453 fprintf(stderr,"rarest char %c at %d\n",str->str_rare, str->str_state);
458 fbminstr(big, bigend, littlestr)
460 register unsigned char *bigend;
463 register unsigned char *s;
465 register int littlelen;
466 register unsigned char *little;
467 register unsigned char *table;
468 register unsigned char *olds;
469 register unsigned char *oldlittle;
472 if (!(littlestr->str_pok & SP_FBM))
473 return instr((char*)big,littlestr->str_ptr);
476 littlelen = littlestr->str_cur;
478 if (littlestr->str_pok & SP_TAIL && !multiline) { /* tail anchored? */
479 little = (unsigned char*)littlestr->str_ptr;
480 if (littlestr->str_pok & SP_CASEFOLD) { /* oops, fake it */
481 big = bigend - littlelen; /* just start near end */
482 if (bigend[-1] == '\n' && little[littlelen-1] != '\n')
486 s = bigend - littlelen;
487 if (*s == *little && bcmp(s,little,littlelen)==0)
488 return (char*)s; /* how sweet it is */
489 else if (bigend[-1] == '\n' && little[littlelen-1] != '\n') {
491 if (*s == *little && bcmp(s,little,littlelen)==0)
497 table = (unsigned char*)(littlestr->str_ptr + littlelen + 1);
499 table = Null(unsigned char*);
501 s = big + --littlelen;
502 oldlittle = little = table - 2;
503 if (littlestr->str_pok & SP_CASEFOLD) { /* case insensitive? */
506 if (tmp = table[*s]) {
510 tmp = littlelen; /* less expensive than calling strncmp() */
513 if (*--s == *--little || fold[*s] == *little)
515 s = olds + 1; /* here we pay the price for failure */
517 if (s < bigend) /* fake up continue to outer loop */
530 if (tmp = table[*s]) {
534 tmp = littlelen; /* less expensive than calling strncmp() */
537 if (*--s == *--little)
539 s = olds + 1; /* here we pay the price for failure */
541 if (s < bigend) /* fake up continue to outer loop */
555 screaminstr(bigstr, littlestr)
559 register unsigned char *s, *x;
560 register unsigned char *big;
562 register int previous;
564 register unsigned char *little;
565 register unsigned char *bigend;
566 register unsigned char *littleend;
568 if ((pos = screamfirst[littlestr->str_rare]) < 0)
571 little = (unsigned char *)(littlestr->str_ptr);
573 little = Null(unsigned char *);
575 littleend = little + littlestr->str_cur;
577 previous = littlestr->str_state;
579 big = (unsigned char *)(bigstr->str_ptr);
581 big = Null(unsigned char*);
583 bigend = big + bigstr->str_cur;
585 while (pos < previous) {
587 if (!(pos += screamnext[pos]))
591 if (littlestr->str_pok & SP_CASEFOLD) { /* case insignificant? */
593 if (big[pos] != first && big[pos] != fold[first])
595 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
598 if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
605 return (char *)(big+pos);
611 pos += screamnext[pos] /* does this goof up anywhere? */
619 if (big[pos] != first)
621 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
631 return (char *)(big+pos);
637 pos += screamnext[pos]
646 /* copy a string to a safe spot */
652 register char *newaddr;
654 New(902,newaddr,strlen(str)+1,char);
655 (void)strcpy(newaddr,str);
659 /* same thing but with a known length */
666 register char *newaddr;
668 New(903,newaddr,len+1,char);
669 (void)bcopy(str,newaddr,len); /* might not be null terminated */
670 newaddr[len] = '\0'; /* is now */
674 /* grow a static string to at least a certain length */
677 growstr(strptr,curlen,newlen)
682 if (newlen > *curlen) { /* need more room? */
684 Renew(*strptr,newlen,char);
686 New(905,*strptr,newlen,char);
695 mess(pat,a1,a2,a3,a4)
702 (void)sprintf(s,pat,a1,a2,a3,a4);
706 (void)sprintf(s," at %s line %ld",
707 in_eval?filename:origfilename, (long)line);
711 stab_io(last_in_stab) &&
712 stab_io(last_in_stab)->lines ) {
713 (void)sprintf(s,", <%s> line %ld",
714 last_in_stab == argvstab ? "" : stab_name(last_in_stab),
715 (long)stab_io(last_in_stab)->lines);
718 (void)strcpy(s,".\n");
723 fatal(pat,a1,a2,a3,a4)
728 extern char *e_tmpname;
730 mess(pat,a1,a2,a3,a4);
732 str_set(stab_val(stabent("@",TRUE)),buf);
736 (void)fflush(stderr);
738 (void)UNLINK(e_tmpname);
740 exit(errno?errno:(statusvalue?statusvalue:255));
744 warn(pat,a1,a2,a3,a4)
748 mess(pat,a1,a2,a3,a4);
756 (void)fflush(stderr);
775 pat = va_arg(args, char *);
777 (void) vsprintf(s,pat,args);
782 (void)sprintf(s," at %s line %ld",
783 in_eval?filename:origfilename, (long)line);
787 stab_io(last_in_stab) &&
788 stab_io(last_in_stab)->lines ) {
789 (void)sprintf(s,", <%s> line %ld",
790 last_in_stab == argvstab ? "" : last_in_stab->str_magic->str_ptr,
791 (long)stab_io(last_in_stab)->lines);
794 (void)strcpy(s,".\n");
804 extern char *e_tmpname;
814 str_set(stab_val(stabent("@",TRUE)),buf);
818 (void)fflush(stderr);
820 (void)UNLINK(e_tmpname);
822 exit((int)(errno?errno:(statusvalue?statusvalue:255)));
846 (void)fflush(stderr);
850 static bool firstsetenv = TRUE;
851 extern char **environ;
857 register int i=envix(nam); /* where does it go? */
861 environ[i] = environ[i+1];
866 if (!environ[i]) { /* does not exist yet */
867 if (firstsetenv) { /* need we copy environment? */
871 New(901,tmpenv, i+2, char*);
873 for (j=0; j<i; j++) /* copy environment */
874 tmpenv[j] = environ[j];
875 environ = tmpenv; /* tell exec where it is now */
878 Renew(environ, i+2, char*); /* just expand it a bit */
879 environ[i+1] = Nullch; /* make sure it's null terminated */
881 New(904, environ[i], strlen(nam) + strlen(val) + 2, char);
882 /* this may or may not be in */
883 /* the old environ structure */
884 (void)sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
891 register int i, len = strlen(nam);
893 for (i = 0; environ[i]; i++) {
894 if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
895 break; /* strnEQ must come first to avoid */
896 } /* potential SEGV's */
901 unlnk(f) /* unlink all versions of a file */
906 for (i = 0; unlink(f) >= 0; i++) ;
948 vsprintf(dest, pat, args)
949 char *dest, *pat, *args;
954 fakebuf._cnt = 32767;
955 fakebuf._flag = _IOWRT|_IOSTRG;
956 _doprnt(pat, args, &fakebuf); /* what a kludge */
957 (void)putc('\0', &fakebuf);
961 return 0; /* perl doesn't use return value */
967 vfprintf(fd, pat, args)
971 _doprnt(pat, args, fd);
972 return 0; /* wrong, but perl doesn't use the return value */
979 #if BYTEORDER != 04321
984 #if (BYTEORDER & 1) == 0
987 result = ((s & 255) << 8) + ((s >> 8) & 255);
1003 #if BYTEORDER == 01234
1004 u.c[0] = (l >> 24) & 255;
1005 u.c[1] = (l >> 16) & 255;
1006 u.c[2] = (l >> 8) & 255;
1010 #if ((BYTEORDER - 01111) & 0444) || !(BYTEORDER & 7)
1011 fatal("Unknown BYTEORDER\n");
1016 for (o = BYTEORDER - 01111, s = 0; s < 32; o >>= 3, s += 8) {
1017 u.c[o & 7] = (l >> s) & 255;
1033 #if BYTEORDER == 01234
1034 u.c[0] = (l >> 24) & 255;
1035 u.c[1] = (l >> 16) & 255;
1036 u.c[2] = (l >> 8) & 255;
1040 #if ((BYTEORDER - 01111) & 0444) || !(BYTEORDER & 7)
1041 fatal("Unknown BYTEORDER\n");
1048 for (o = BYTEORDER - 01111, s = 0; s < 32; o >>= 3, s += 8) {
1049 l |= (u.c[o & 7] & 255) << s;
1056 #endif /* BYTEORDER != 04321 */
1065 register int this, that;
1068 int doexec = strNE(cmd,"-");
1072 this = (*mode == 'w');
1074 while ((pid = (doexec?vfork():fork())) < 0) {
1075 if (errno != EAGAIN) {
1078 fatal("Can't fork");
1087 if (p[THIS] != (*mode == 'r')) {
1088 dup2(p[THIS], *mode == 'r');
1092 do_exec(cmd); /* may or may not use the shell */
1095 if (tmpstab = stabent("$",allstabs))
1096 str_numset(STAB_STR(tmpstab),(double)getpid());
1102 str = afetch(pidstatary,p[this],TRUE);
1103 str_numset(str,(double)pid);
1106 return fdopen(p[this], mode);
1115 while (dup(oldfd) != newfd) ; /* good enough for our purposes */
1123 register int result;
1125 void (*hstat)(), (*istat)(), (*qstat)();
1127 int (*hstat)(), (*istat)(), (*qstat)();
1133 str = afetch(pidstatary,fileno(ptr),TRUE);
1135 pid = (int)str_gnum(str);
1138 hstat = signal(SIGHUP, SIG_IGN);
1139 istat = signal(SIGINT, SIG_IGN);
1140 qstat = signal(SIGQUIT, SIG_IGN);
1142 if (wait4(pid,&status,0,Null(struct rusage *)) < 0)
1145 if (pid < 0) /* already exited? */
1146 status = str->str_cur;
1148 while ((result = wait(&status)) != pid && result >= 0)
1149 pidgone(result,status);
1154 signal(SIGHUP, hstat);
1155 signal(SIGINT, istat);
1156 signal(SIGQUIT, qstat);
1157 str_numset(str,0.0);
1171 for (count = pidstatary->ary_fill; count >= 0; --count) {
1172 if ((str = afetch(pidstatary,count,FALSE)) &&
1173 ((int)str->str_u.str_nval) == pid) {
1174 str_numset(str, -str->str_u.str_nval);
1175 str->str_cur = status;
1184 register unsigned char *s1;
1185 register unsigned char *s2;
1191 if (tmp = *s1++ - *s2++)