1 /* $Header: util.c,v 3.0.1.1 89/11/11 05:06:13 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.1 89/11/11 05:06:13 lwall
10 * patch2: made dup2 a little better
12 * Revision 3.0 89/10/18 15:32:43 lwall
32 static char nomem[] = "Out of memory!\n";
34 /* paranoid version of malloc */
40 /* NOTE: Do not call the next three routines directly. Use the macros
41 * in handy.h, so that we can easily redefine everything to do tracking of
42 * allocated hunks back to the original New to track down any memory leaks.
52 ptr = malloc(size?size:1); /* malloc(0) is NASTY on our system */
56 fprintf(stderr,"0x%x: (%05d) malloc %d bytes\n",ptr,an++,size);
59 fprintf(stderr,"0x%lx: (%05d) malloc %d bytes\n",ptr,an++,size);
65 fputs(nomem,stdout) FLUSH;
74 /* paranoid version of realloc */
77 saferealloc(where,size)
85 fatal("Null realloc");
86 ptr = realloc(where,size?size:1); /* realloc(0) is NASTY on our system */
90 fprintf(stderr,"0x%x: (%05d) rfree\n",where,an++);
91 fprintf(stderr,"0x%x: (%05d) realloc %d bytes\n",ptr,an++,size);
95 fprintf(stderr,"0x%lx: (%05d) rfree\n",where,an++);
96 fprintf(stderr,"0x%lx: (%05d) realloc %d bytes\n",ptr,an++,size);
103 fputs(nomem,stdout) FLUSH;
112 /* safe version of free */
121 fprintf(stderr,"0x%x: (%05d) free\n",where,an++);
124 fprintf(stderr,"0x%lx: (%05d) free\n",where,an++);
134 #define ALIGN sizeof(long)
141 register char *where;
143 where = safemalloc(size + ALIGN);
147 return where + ALIGN;
151 safexrealloc(where,size)
155 return saferealloc(where - ALIGN, size + ALIGN) + ALIGN;
167 x = where[0] + 100 * where[1];
176 for (i = 0; i < MAXXCOUNT; i++) {
177 if (xcount[i] != lastxcount[i]) {
178 fprintf(stderr,"%2d %2d\t%ld\n", i / 100, i % 100, xcount[i]);
179 lastxcount[i] = xcount[i];
184 #endif /* LEAKTEST */
186 /* copy a string up to some (non-backslashed) delimiter, if any */
189 cpytill(to,from,fromend,delim,retlen)
190 register char *to, *from;
191 register char *fromend;
197 for (; from < fromend; from++,to++) {
199 if (from[1] == delim)
201 else if (from[1] == '\\')
204 else if (*from == delim)
209 *retlen = to - origto;
213 /* return ptr to little string in big string, NULL if not found */
214 /* This routine was donated by Corey Satten. */
219 register char *little;
221 register char *s, *x;
232 for (x=big,s=little; *s; /**/ ) {
246 /* same as instr but allow embedded nulls */
249 ninstr(big, bigend, little, lend)
251 register char *bigend;
255 register char *s, *x;
256 register int first = *little;
257 register char *littleend = lend;
259 if (!first && little > littleend)
261 bigend -= littleend - little++;
262 while (big <= bigend) {
265 for (x=big,s=little; s < littleend; /**/ ) {
277 /* reverse of the above--find last substring */
280 rninstr(big, bigend, little, lend)
286 register char *bigbeg;
287 register char *s, *x;
288 register int first = *little;
289 register char *littleend = lend;
291 if (!first && little > littleend)
294 big = bigend - (littleend - little++);
295 while (big >= bigbeg) {
298 for (x=big+2,s=little; s < littleend; /**/ ) {
310 unsigned char fold[] = {
311 0, 1, 2, 3, 4, 5, 6, 7,
312 8, 9, 10, 11, 12, 13, 14, 15,
313 16, 17, 18, 19, 20, 21, 22, 23,
314 24, 25, 26, 27, 28, 29, 30, 31,
315 32, 33, 34, 35, 36, 37, 38, 39,
316 40, 41, 42, 43, 44, 45, 46, 47,
317 48, 49, 50, 51, 52, 53, 54, 55,
318 56, 57, 58, 59, 60, 61, 62, 63,
319 64, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
320 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
321 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
322 'x', 'y', 'z', 91, 92, 93, 94, 95,
323 96, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
324 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
325 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
326 'X', 'Y', 'Z', 123, 124, 125, 126, 127,
327 128, 129, 130, 131, 132, 133, 134, 135,
328 136, 137, 138, 139, 140, 141, 142, 143,
329 144, 145, 146, 147, 148, 149, 150, 151,
330 152, 153, 154, 155, 156, 157, 158, 159,
331 160, 161, 162, 163, 164, 165, 166, 167,
332 168, 169, 170, 171, 172, 173, 174, 175,
333 176, 177, 178, 179, 180, 181, 182, 183,
334 184, 185, 186, 187, 188, 189, 190, 191,
335 192, 193, 194, 195, 196, 197, 198, 199,
336 200, 201, 202, 203, 204, 205, 206, 207,
337 208, 209, 210, 211, 212, 213, 214, 215,
338 216, 217, 218, 219, 220, 221, 222, 223,
339 224, 225, 226, 227, 228, 229, 230, 231,
340 232, 233, 234, 235, 236, 237, 238, 239,
341 240, 241, 242, 243, 244, 245, 246, 247,
342 248, 249, 250, 251, 252, 253, 254, 255
345 static unsigned char freq[] = {
346 1, 2, 84, 151, 154, 155, 156, 157,
347 165, 246, 250, 3, 158, 7, 18, 29,
348 40, 51, 62, 73, 85, 96, 107, 118,
349 129, 140, 147, 148, 149, 150, 152, 153,
350 255, 182, 224, 205, 174, 176, 180, 217,
351 233, 232, 236, 187, 235, 228, 234, 226,
352 222, 219, 211, 195, 188, 193, 185, 184,
353 191, 183, 201, 229, 181, 220, 194, 162,
354 163, 208, 186, 202, 200, 218, 198, 179,
355 178, 214, 166, 170, 207, 199, 209, 206,
356 204, 160, 212, 216, 215, 192, 175, 173,
357 243, 172, 161, 190, 203, 189, 164, 230,
358 167, 248, 227, 244, 242, 255, 241, 231,
359 240, 253, 169, 210, 245, 237, 249, 247,
360 239, 168, 252, 251, 254, 238, 223, 221,
361 213, 225, 177, 197, 171, 196, 159, 4,
362 5, 6, 8, 9, 10, 11, 12, 13,
363 14, 15, 16, 17, 19, 20, 21, 22,
364 23, 24, 25, 26, 27, 28, 30, 31,
365 32, 33, 34, 35, 36, 37, 38, 39,
366 41, 42, 43, 44, 45, 46, 47, 48,
367 49, 50, 52, 53, 54, 55, 56, 57,
368 58, 59, 60, 61, 63, 64, 65, 66,
369 67, 68, 69, 70, 71, 72, 74, 75,
370 76, 77, 78, 79, 80, 81, 82, 83,
371 86, 87, 88, 89, 90, 91, 92, 93,
372 94, 95, 97, 98, 99, 100, 101, 102,
373 103, 104, 105, 106, 108, 109, 110, 111,
374 112, 113, 114, 115, 116, 117, 119, 120,
375 121, 122, 123, 124, 125, 126, 127, 128,
376 130, 131, 132, 133, 134, 135, 136, 137,
377 138, 139, 141, 142, 143, 144, 145, 146
381 fbmcompile(str, iflag)
385 register unsigned char *s;
386 register unsigned char *table;
388 register int len = str->str_cur;
392 str_grow(str,len+258);
394 table = (unsigned char*)(str->str_ptr + len + 1);
396 table = Null(unsigned char*);
399 for (i = 0; i < 256; i++) {
404 while (s >= (unsigned char*)(str->str_ptr))
407 if (table[*s] == len) {
410 table[*s] = table[fold[*s]] = i;
424 str->str_pok |= SP_FBM; /* deep magic */
427 s = (unsigned char*)(str->str_ptr); /* deeper magic */
429 s = Null(unsigned char*);
432 register int tmp, foldtmp;
433 str->str_pok |= SP_CASEFOLD;
434 for (i = 0; i < len; i++) {
436 foldtmp=freq[fold[s[i]]];
437 if (tmp < frequency && foldtmp < frequency) {
439 /* choose most frequent among the two */
440 frequency = (tmp > foldtmp) ? tmp : foldtmp;
445 for (i = 0; i < len; i++) {
446 if (freq[s[i]] < frequency) {
448 frequency = freq[s[i]];
452 str->str_rare = s[rarest];
453 str->str_state = rarest;
456 fprintf(stderr,"rarest char %c at %d\n",str->str_rare, str->str_state);
461 fbminstr(big, bigend, littlestr)
463 register unsigned char *bigend;
466 register unsigned char *s;
468 register int littlelen;
469 register unsigned char *little;
470 register unsigned char *table;
471 register unsigned char *olds;
472 register unsigned char *oldlittle;
475 if (!(littlestr->str_pok & SP_FBM))
476 return instr((char*)big,littlestr->str_ptr);
479 littlelen = littlestr->str_cur;
481 if (littlestr->str_pok & SP_TAIL && !multiline) { /* tail anchored? */
482 little = (unsigned char*)littlestr->str_ptr;
483 if (littlestr->str_pok & SP_CASEFOLD) { /* oops, fake it */
484 big = bigend - littlelen; /* just start near end */
485 if (bigend[-1] == '\n' && little[littlelen-1] != '\n')
489 s = bigend - littlelen;
490 if (*s == *little && bcmp(s,little,littlelen)==0)
491 return (char*)s; /* how sweet it is */
492 else if (bigend[-1] == '\n' && little[littlelen-1] != '\n') {
494 if (*s == *little && bcmp(s,little,littlelen)==0)
500 table = (unsigned char*)(littlestr->str_ptr + littlelen + 1);
502 table = Null(unsigned char*);
504 s = big + --littlelen;
505 oldlittle = little = table - 2;
506 if (littlestr->str_pok & SP_CASEFOLD) { /* case insensitive? */
509 if (tmp = table[*s]) {
513 tmp = littlelen; /* less expensive than calling strncmp() */
516 if (*--s == *--little || fold[*s] == *little)
518 s = olds + 1; /* here we pay the price for failure */
520 if (s < bigend) /* fake up continue to outer loop */
533 if (tmp = table[*s]) {
537 tmp = littlelen; /* less expensive than calling strncmp() */
540 if (*--s == *--little)
542 s = olds + 1; /* here we pay the price for failure */
544 if (s < bigend) /* fake up continue to outer loop */
558 screaminstr(bigstr, littlestr)
562 register unsigned char *s, *x;
563 register unsigned char *big;
565 register int previous;
567 register unsigned char *little;
568 register unsigned char *bigend;
569 register unsigned char *littleend;
571 if ((pos = screamfirst[littlestr->str_rare]) < 0)
574 little = (unsigned char *)(littlestr->str_ptr);
576 little = Null(unsigned char *);
578 littleend = little + littlestr->str_cur;
580 previous = littlestr->str_state;
582 big = (unsigned char *)(bigstr->str_ptr);
584 big = Null(unsigned char*);
586 bigend = big + bigstr->str_cur;
588 while (pos < previous) {
590 if (!(pos += screamnext[pos]))
594 if (littlestr->str_pok & SP_CASEFOLD) { /* case insignificant? */
596 if (big[pos] != first && big[pos] != fold[first])
598 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
601 if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
608 return (char *)(big+pos);
614 pos += screamnext[pos] /* does this goof up anywhere? */
622 if (big[pos] != first)
624 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
634 return (char *)(big+pos);
640 pos += screamnext[pos]
649 /* copy a string to a safe spot */
655 register char *newaddr;
657 New(902,newaddr,strlen(str)+1,char);
658 (void)strcpy(newaddr,str);
662 /* same thing but with a known length */
669 register char *newaddr;
671 New(903,newaddr,len+1,char);
672 (void)bcopy(str,newaddr,len); /* might not be null terminated */
673 newaddr[len] = '\0'; /* is now */
677 /* grow a static string to at least a certain length */
680 growstr(strptr,curlen,newlen)
685 if (newlen > *curlen) { /* need more room? */
687 Renew(*strptr,newlen,char);
689 New(905,*strptr,newlen,char);
698 mess(pat,a1,a2,a3,a4)
705 (void)sprintf(s,pat,a1,a2,a3,a4);
709 (void)sprintf(s," at %s line %ld",
710 in_eval?filename:origfilename, (long)line);
714 stab_io(last_in_stab) &&
715 stab_io(last_in_stab)->lines ) {
716 (void)sprintf(s,", <%s> line %ld",
717 last_in_stab == argvstab ? "" : stab_name(last_in_stab),
718 (long)stab_io(last_in_stab)->lines);
721 (void)strcpy(s,".\n");
726 fatal(pat,a1,a2,a3,a4)
731 extern char *e_tmpname;
733 mess(pat,a1,a2,a3,a4);
735 str_set(stab_val(stabent("@",TRUE)),buf);
739 (void)fflush(stderr);
741 (void)UNLINK(e_tmpname);
743 exit(errno?errno:(statusvalue?statusvalue:255));
747 warn(pat,a1,a2,a3,a4)
751 mess(pat,a1,a2,a3,a4);
759 (void)fflush(stderr);
778 pat = va_arg(args, char *);
780 (void) vsprintf(s,pat,args);
785 (void)sprintf(s," at %s line %ld",
786 in_eval?filename:origfilename, (long)line);
790 stab_io(last_in_stab) &&
791 stab_io(last_in_stab)->lines ) {
792 (void)sprintf(s,", <%s> line %ld",
793 last_in_stab == argvstab ? "" : last_in_stab->str_magic->str_ptr,
794 (long)stab_io(last_in_stab)->lines);
797 (void)strcpy(s,".\n");
807 extern char *e_tmpname;
817 str_set(stab_val(stabent("@",TRUE)),buf);
821 (void)fflush(stderr);
823 (void)UNLINK(e_tmpname);
825 exit((int)(errno?errno:(statusvalue?statusvalue:255)));
849 (void)fflush(stderr);
853 static bool firstsetenv = TRUE;
854 extern char **environ;
860 register int i=envix(nam); /* where does it go? */
864 environ[i] = environ[i+1];
869 if (!environ[i]) { /* does not exist yet */
870 if (firstsetenv) { /* need we copy environment? */
874 New(901,tmpenv, i+2, char*);
876 for (j=0; j<i; j++) /* copy environment */
877 tmpenv[j] = environ[j];
878 environ = tmpenv; /* tell exec where it is now */
881 Renew(environ, i+2, char*); /* just expand it a bit */
882 environ[i+1] = Nullch; /* make sure it's null terminated */
884 New(904, environ[i], strlen(nam) + strlen(val) + 2, char);
885 /* this may or may not be in */
886 /* the old environ structure */
887 (void)sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
894 register int i, len = strlen(nam);
896 for (i = 0; environ[i]; i++) {
897 if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
898 break; /* strnEQ must come first to avoid */
899 } /* potential SEGV's */
904 unlnk(f) /* unlink all versions of a file */
909 for (i = 0; unlink(f) >= 0; i++) ;
951 vsprintf(dest, pat, args)
952 char *dest, *pat, *args;
957 fakebuf._cnt = 32767;
958 fakebuf._flag = _IOWRT|_IOSTRG;
959 _doprnt(pat, args, &fakebuf); /* what a kludge */
960 (void)putc('\0', &fakebuf);
964 return 0; /* perl doesn't use return value */
970 vfprintf(fd, pat, args)
974 _doprnt(pat, args, fd);
975 return 0; /* wrong, but perl doesn't use the return value */
982 #if BYTEORDER != 04321
987 #if (BYTEORDER & 1) == 0
990 result = ((s & 255) << 8) + ((s >> 8) & 255);
1006 #if BYTEORDER == 01234
1007 u.c[0] = (l >> 24) & 255;
1008 u.c[1] = (l >> 16) & 255;
1009 u.c[2] = (l >> 8) & 255;
1013 #if ((BYTEORDER - 01111) & 0444) || !(BYTEORDER & 7)
1014 fatal("Unknown BYTEORDER\n");
1019 for (o = BYTEORDER - 01111, s = 0; s < 32; o >>= 3, s += 8) {
1020 u.c[o & 7] = (l >> s) & 255;
1036 #if BYTEORDER == 01234
1037 u.c[0] = (l >> 24) & 255;
1038 u.c[1] = (l >> 16) & 255;
1039 u.c[2] = (l >> 8) & 255;
1043 #if ((BYTEORDER - 01111) & 0444) || !(BYTEORDER & 7)
1044 fatal("Unknown BYTEORDER\n");
1051 for (o = BYTEORDER - 01111, s = 0; s < 32; o >>= 3, s += 8) {
1052 l |= (u.c[o & 7] & 255) << s;
1059 #endif /* BYTEORDER != 04321 */
1068 register int this, that;
1071 int doexec = strNE(cmd,"-");
1075 this = (*mode == 'w');
1077 while ((pid = (doexec?vfork():fork())) < 0) {
1078 if (errno != EAGAIN) {
1081 fatal("Can't fork");
1090 if (p[THIS] != (*mode == 'r')) {
1091 dup2(p[THIS], *mode == 'r');
1095 #if !defined(FCNTL) || !defined(F_SETFD)
1101 for (fd = 3; fd < NOFILE; fd++)
1104 do_exec(cmd); /* may or may not use the shell */
1107 if (tmpstab = stabent("$",allstabs))
1108 str_numset(STAB_STR(tmpstab),(double)getpid());
1114 str = afetch(pidstatary,p[this],TRUE);
1115 str_numset(str,(double)pid);
1118 return fdopen(p[this], mode);
1126 struct stat tmpstatbuf;
1128 fprintf(stderr,"%s", s);
1129 for (fd = 0; fd < 32; fd++) {
1130 if (fstat(fd,&tmpstatbuf) >= 0)
1131 fprintf(stderr," %d",fd);
1133 fprintf(stderr,"\n");
1147 while ((fd = dup(oldfd)) != newfd) /* good enough for low fd's */
1150 close(fdtmp[--fdx]);
1158 register int result;
1160 void (*hstat)(), (*istat)(), (*qstat)();
1162 int (*hstat)(), (*istat)(), (*qstat)();
1168 str = afetch(pidstatary,fileno(ptr),TRUE);
1170 pid = (int)str_gnum(str);
1173 hstat = signal(SIGHUP, SIG_IGN);
1174 istat = signal(SIGINT, SIG_IGN);
1175 qstat = signal(SIGQUIT, SIG_IGN);
1177 if (wait4(pid,&status,0,Null(struct rusage *)) < 0)
1180 if (pid < 0) /* already exited? */
1181 status = str->str_cur;
1183 while ((result = wait(&status)) != pid && result >= 0)
1184 pidgone(result,status);
1189 signal(SIGHUP, hstat);
1190 signal(SIGINT, istat);
1191 signal(SIGQUIT, qstat);
1192 str_numset(str,0.0);
1206 for (count = pidstatary->ary_fill; count >= 0; --count) {
1207 if ((str = afetch(pidstatary,count,FALSE)) &&
1208 ((int)str->str_u.str_nval) == pid) {
1209 str_numset(str, -str->str_u.str_nval);
1210 str->str_cur = status;
1219 register unsigned char *s1;
1220 register unsigned char *s2;
1226 if (tmp = *s1++ - *s2++)