1 /* $Header: util.c,v 3.0.1.3 89/12/21 20:27:41 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.3 89/12/21 20:27:41 lwall
10 * patch7: errno may now be a macro with an lvalue
12 * Revision 3.0.1.2 89/11/17 15:46:35 lwall
13 * patch5: BZERO separate from BCOPY now
14 * patch5: byteorder now is a hex value
16 * Revision 3.0.1.1 89/11/11 05:06:13 lwall
17 * patch2: made dup2 a little better
19 * Revision 3.0 89/10/18 15:32:43 lwall
38 static char nomem[] = "Out of memory!\n";
40 /* paranoid version of malloc */
46 /* NOTE: Do not call the next three routines directly. Use the macros
47 * in handy.h, so that we can easily redefine everything to do tracking of
48 * allocated hunks back to the original New to track down any memory leaks.
58 ptr = malloc(size?size:1); /* malloc(0) is NASTY on our system */
62 fprintf(stderr,"0x%x: (%05d) malloc %d bytes\n",ptr,an++,size);
65 fprintf(stderr,"0x%lx: (%05d) malloc %d bytes\n",ptr,an++,size);
71 fputs(nomem,stdout) FLUSH;
80 /* paranoid version of realloc */
83 saferealloc(where,size)
91 fatal("Null realloc");
92 ptr = realloc(where,size?size:1); /* realloc(0) is NASTY on our system */
96 fprintf(stderr,"0x%x: (%05d) rfree\n",where,an++);
97 fprintf(stderr,"0x%x: (%05d) realloc %d bytes\n",ptr,an++,size);
101 fprintf(stderr,"0x%lx: (%05d) rfree\n",where,an++);
102 fprintf(stderr,"0x%lx: (%05d) realloc %d bytes\n",ptr,an++,size);
109 fputs(nomem,stdout) FLUSH;
118 /* safe version of free */
127 fprintf(stderr,"0x%x: (%05d) free\n",where,an++);
130 fprintf(stderr,"0x%lx: (%05d) free\n",where,an++);
140 #define ALIGN sizeof(long)
147 register char *where;
149 where = safemalloc(size + ALIGN);
153 return where + ALIGN;
157 safexrealloc(where,size)
161 return saferealloc(where - ALIGN, size + ALIGN) + ALIGN;
173 x = where[0] + 100 * where[1];
182 for (i = 0; i < MAXXCOUNT; i++) {
183 if (xcount[i] != lastxcount[i]) {
184 fprintf(stderr,"%2d %2d\t%ld\n", i / 100, i % 100, xcount[i]);
185 lastxcount[i] = xcount[i];
190 #endif /* LEAKTEST */
192 /* copy a string up to some (non-backslashed) delimiter, if any */
195 cpytill(to,from,fromend,delim,retlen)
196 register char *to, *from;
197 register char *fromend;
203 for (; from < fromend; from++,to++) {
205 if (from[1] == delim)
207 else if (from[1] == '\\')
210 else if (*from == delim)
215 *retlen = to - origto;
219 /* return ptr to little string in big string, NULL if not found */
220 /* This routine was donated by Corey Satten. */
225 register char *little;
227 register char *s, *x;
238 for (x=big,s=little; *s; /**/ ) {
252 /* same as instr but allow embedded nulls */
255 ninstr(big, bigend, little, lend)
257 register char *bigend;
261 register char *s, *x;
262 register int first = *little;
263 register char *littleend = lend;
265 if (!first && little > littleend)
267 bigend -= littleend - little++;
268 while (big <= bigend) {
271 for (x=big,s=little; s < littleend; /**/ ) {
283 /* reverse of the above--find last substring */
286 rninstr(big, bigend, little, lend)
292 register char *bigbeg;
293 register char *s, *x;
294 register int first = *little;
295 register char *littleend = lend;
297 if (!first && little > littleend)
300 big = bigend - (littleend - little++);
301 while (big >= bigbeg) {
304 for (x=big+2,s=little; s < littleend; /**/ ) {
316 unsigned char fold[] = {
317 0, 1, 2, 3, 4, 5, 6, 7,
318 8, 9, 10, 11, 12, 13, 14, 15,
319 16, 17, 18, 19, 20, 21, 22, 23,
320 24, 25, 26, 27, 28, 29, 30, 31,
321 32, 33, 34, 35, 36, 37, 38, 39,
322 40, 41, 42, 43, 44, 45, 46, 47,
323 48, 49, 50, 51, 52, 53, 54, 55,
324 56, 57, 58, 59, 60, 61, 62, 63,
325 64, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
326 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
327 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
328 'x', 'y', 'z', 91, 92, 93, 94, 95,
329 96, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
330 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
331 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
332 'X', 'Y', 'Z', 123, 124, 125, 126, 127,
333 128, 129, 130, 131, 132, 133, 134, 135,
334 136, 137, 138, 139, 140, 141, 142, 143,
335 144, 145, 146, 147, 148, 149, 150, 151,
336 152, 153, 154, 155, 156, 157, 158, 159,
337 160, 161, 162, 163, 164, 165, 166, 167,
338 168, 169, 170, 171, 172, 173, 174, 175,
339 176, 177, 178, 179, 180, 181, 182, 183,
340 184, 185, 186, 187, 188, 189, 190, 191,
341 192, 193, 194, 195, 196, 197, 198, 199,
342 200, 201, 202, 203, 204, 205, 206, 207,
343 208, 209, 210, 211, 212, 213, 214, 215,
344 216, 217, 218, 219, 220, 221, 222, 223,
345 224, 225, 226, 227, 228, 229, 230, 231,
346 232, 233, 234, 235, 236, 237, 238, 239,
347 240, 241, 242, 243, 244, 245, 246, 247,
348 248, 249, 250, 251, 252, 253, 254, 255
351 static unsigned char freq[] = {
352 1, 2, 84, 151, 154, 155, 156, 157,
353 165, 246, 250, 3, 158, 7, 18, 29,
354 40, 51, 62, 73, 85, 96, 107, 118,
355 129, 140, 147, 148, 149, 150, 152, 153,
356 255, 182, 224, 205, 174, 176, 180, 217,
357 233, 232, 236, 187, 235, 228, 234, 226,
358 222, 219, 211, 195, 188, 193, 185, 184,
359 191, 183, 201, 229, 181, 220, 194, 162,
360 163, 208, 186, 202, 200, 218, 198, 179,
361 178, 214, 166, 170, 207, 199, 209, 206,
362 204, 160, 212, 216, 215, 192, 175, 173,
363 243, 172, 161, 190, 203, 189, 164, 230,
364 167, 248, 227, 244, 242, 255, 241, 231,
365 240, 253, 169, 210, 245, 237, 249, 247,
366 239, 168, 252, 251, 254, 238, 223, 221,
367 213, 225, 177, 197, 171, 196, 159, 4,
368 5, 6, 8, 9, 10, 11, 12, 13,
369 14, 15, 16, 17, 19, 20, 21, 22,
370 23, 24, 25, 26, 27, 28, 30, 31,
371 32, 33, 34, 35, 36, 37, 38, 39,
372 41, 42, 43, 44, 45, 46, 47, 48,
373 49, 50, 52, 53, 54, 55, 56, 57,
374 58, 59, 60, 61, 63, 64, 65, 66,
375 67, 68, 69, 70, 71, 72, 74, 75,
376 76, 77, 78, 79, 80, 81, 82, 83,
377 86, 87, 88, 89, 90, 91, 92, 93,
378 94, 95, 97, 98, 99, 100, 101, 102,
379 103, 104, 105, 106, 108, 109, 110, 111,
380 112, 113, 114, 115, 116, 117, 119, 120,
381 121, 122, 123, 124, 125, 126, 127, 128,
382 130, 131, 132, 133, 134, 135, 136, 137,
383 138, 139, 141, 142, 143, 144, 145, 146
387 fbmcompile(str, iflag)
391 register unsigned char *s;
392 register unsigned char *table;
394 register int len = str->str_cur;
398 str_grow(str,len+258);
400 table = (unsigned char*)(str->str_ptr + len + 1);
402 table = Null(unsigned char*);
405 for (i = 0; i < 256; i++) {
410 while (s >= (unsigned char*)(str->str_ptr))
413 if (table[*s] == len) {
416 table[*s] = table[fold[*s]] = i;
430 str->str_pok |= SP_FBM; /* deep magic */
433 s = (unsigned char*)(str->str_ptr); /* deeper magic */
435 s = Null(unsigned char*);
438 register int tmp, foldtmp;
439 str->str_pok |= SP_CASEFOLD;
440 for (i = 0; i < len; i++) {
442 foldtmp=freq[fold[s[i]]];
443 if (tmp < frequency && foldtmp < frequency) {
445 /* choose most frequent among the two */
446 frequency = (tmp > foldtmp) ? tmp : foldtmp;
451 for (i = 0; i < len; i++) {
452 if (freq[s[i]] < frequency) {
454 frequency = freq[s[i]];
458 str->str_rare = s[rarest];
459 str->str_state = rarest;
462 fprintf(stderr,"rarest char %c at %d\n",str->str_rare, str->str_state);
467 fbminstr(big, bigend, littlestr)
469 register unsigned char *bigend;
472 register unsigned char *s;
474 register int littlelen;
475 register unsigned char *little;
476 register unsigned char *table;
477 register unsigned char *olds;
478 register unsigned char *oldlittle;
481 if (!(littlestr->str_pok & SP_FBM))
482 return instr((char*)big,littlestr->str_ptr);
485 littlelen = littlestr->str_cur;
487 if (littlestr->str_pok & SP_TAIL && !multiline) { /* tail anchored? */
488 little = (unsigned char*)littlestr->str_ptr;
489 if (littlestr->str_pok & SP_CASEFOLD) { /* oops, fake it */
490 big = bigend - littlelen; /* just start near end */
491 if (bigend[-1] == '\n' && little[littlelen-1] != '\n')
495 s = bigend - littlelen;
496 if (*s == *little && bcmp(s,little,littlelen)==0)
497 return (char*)s; /* how sweet it is */
498 else if (bigend[-1] == '\n' && little[littlelen-1] != '\n') {
500 if (*s == *little && bcmp(s,little,littlelen)==0)
506 table = (unsigned char*)(littlestr->str_ptr + littlelen + 1);
508 table = Null(unsigned char*);
510 s = big + --littlelen;
511 oldlittle = little = table - 2;
512 if (littlestr->str_pok & SP_CASEFOLD) { /* case insensitive? */
515 if (tmp = table[*s]) {
519 tmp = littlelen; /* less expensive than calling strncmp() */
522 if (*--s == *--little || fold[*s] == *little)
524 s = olds + 1; /* here we pay the price for failure */
526 if (s < bigend) /* fake up continue to outer loop */
539 if (tmp = table[*s]) {
543 tmp = littlelen; /* less expensive than calling strncmp() */
546 if (*--s == *--little)
548 s = olds + 1; /* here we pay the price for failure */
550 if (s < bigend) /* fake up continue to outer loop */
564 screaminstr(bigstr, littlestr)
568 register unsigned char *s, *x;
569 register unsigned char *big;
571 register int previous;
573 register unsigned char *little;
574 register unsigned char *bigend;
575 register unsigned char *littleend;
577 if ((pos = screamfirst[littlestr->str_rare]) < 0)
580 little = (unsigned char *)(littlestr->str_ptr);
582 little = Null(unsigned char *);
584 littleend = little + littlestr->str_cur;
586 previous = littlestr->str_state;
588 big = (unsigned char *)(bigstr->str_ptr);
590 big = Null(unsigned char*);
592 bigend = big + bigstr->str_cur;
594 while (pos < previous) {
596 if (!(pos += screamnext[pos]))
600 if (littlestr->str_pok & SP_CASEFOLD) { /* case insignificant? */
602 if (big[pos] != first && big[pos] != fold[first])
604 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
607 if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
614 return (char *)(big+pos);
620 pos += screamnext[pos] /* does this goof up anywhere? */
628 if (big[pos] != first)
630 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
640 return (char *)(big+pos);
646 pos += screamnext[pos]
655 /* copy a string to a safe spot */
661 register char *newaddr;
663 New(902,newaddr,strlen(str)+1,char);
664 (void)strcpy(newaddr,str);
668 /* same thing but with a known length */
675 register char *newaddr;
677 New(903,newaddr,len+1,char);
678 (void)bcopy(str,newaddr,len); /* might not be null terminated */
679 newaddr[len] = '\0'; /* is now */
683 /* grow a static string to at least a certain length */
686 growstr(strptr,curlen,newlen)
691 if (newlen > *curlen) { /* need more room? */
693 Renew(*strptr,newlen,char);
695 New(905,*strptr,newlen,char);
702 mess(pat,a1,a2,a3,a4)
709 (void)sprintf(s,pat,a1,a2,a3,a4);
713 (void)sprintf(s," at %s line %ld",
714 in_eval?filename:origfilename, (long)line);
718 stab_io(last_in_stab) &&
719 stab_io(last_in_stab)->lines ) {
720 (void)sprintf(s,", <%s> line %ld",
721 last_in_stab == argvstab ? "" : stab_name(last_in_stab),
722 (long)stab_io(last_in_stab)->lines);
725 (void)strcpy(s,".\n");
730 fatal(pat,a1,a2,a3,a4)
735 extern char *e_tmpname;
737 mess(pat,a1,a2,a3,a4);
739 str_set(stab_val(stabent("@",TRUE)),buf);
743 (void)fflush(stderr);
745 (void)UNLINK(e_tmpname);
747 exit(errno?errno:(statusvalue?statusvalue:255));
751 warn(pat,a1,a2,a3,a4)
755 mess(pat,a1,a2,a3,a4);
763 (void)fflush(stderr);
782 pat = va_arg(args, char *);
784 (void) vsprintf(s,pat,args);
789 (void)sprintf(s," at %s line %ld",
790 in_eval?filename:origfilename, (long)line);
794 stab_io(last_in_stab) &&
795 stab_io(last_in_stab)->lines ) {
796 (void)sprintf(s,", <%s> line %ld",
797 last_in_stab == argvstab ? "" : last_in_stab->str_magic->str_ptr,
798 (long)stab_io(last_in_stab)->lines);
801 (void)strcpy(s,".\n");
811 extern char *e_tmpname;
821 str_set(stab_val(stabent("@",TRUE)),buf);
825 (void)fflush(stderr);
827 (void)UNLINK(e_tmpname);
829 exit((int)(errno?errno:(statusvalue?statusvalue:255)));
853 (void)fflush(stderr);
857 static bool firstsetenv = TRUE;
858 extern char **environ;
864 register int i=envix(nam); /* where does it go? */
868 environ[i] = environ[i+1];
873 if (!environ[i]) { /* does not exist yet */
874 if (firstsetenv) { /* need we copy environment? */
878 New(901,tmpenv, i+2, char*);
880 for (j=0; j<i; j++) /* copy environment */
881 tmpenv[j] = environ[j];
882 environ = tmpenv; /* tell exec where it is now */
885 Renew(environ, i+2, char*); /* just expand it a bit */
886 environ[i+1] = Nullch; /* make sure it's null terminated */
888 New(904, environ[i], strlen(nam) + strlen(val) + 2, char);
889 /* this may or may not be in */
890 /* the old environ structure */
891 (void)sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
898 register int i, len = strlen(nam);
900 for (i = 0; environ[i]; i++) {
901 if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
902 break; /* strnEQ must come first to avoid */
903 } /* potential SEGV's */
908 unlnk(f) /* unlink all versions of a file */
913 for (i = 0; unlink(f) >= 0; i++) ;
957 vsprintf(dest, pat, args)
958 char *dest, *pat, *args;
963 fakebuf._cnt = 32767;
964 fakebuf._flag = _IOWRT|_IOSTRG;
965 _doprnt(pat, args, &fakebuf); /* what a kludge */
966 (void)putc('\0', &fakebuf);
970 return 0; /* perl doesn't use return value */
976 vfprintf(fd, pat, args)
980 _doprnt(pat, args, fd);
981 return 0; /* wrong, but perl doesn't use the return value */
988 #if BYTEORDER != 0x4321
993 #if (BYTEORDER & 1) == 0
996 result = ((s & 255) << 8) + ((s >> 8) & 255);
1009 char c[sizeof(long)];
1012 #if BYTEORDER == 0x1234
1013 u.c[0] = (l >> 24) & 255;
1014 u.c[1] = (l >> 16) & 255;
1015 u.c[2] = (l >> 8) & 255;
1019 #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
1020 fatal("Unknown BYTEORDER\n");
1025 for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
1026 u.c[o & 0xf] = (l >> s) & 255;
1039 char c[sizeof(long)];
1042 #if BYTEORDER == 0x1234
1043 u.c[0] = (l >> 24) & 255;
1044 u.c[1] = (l >> 16) & 255;
1045 u.c[2] = (l >> 8) & 255;
1049 #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
1050 fatal("Unknown BYTEORDER\n");
1057 for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
1058 l |= (u.c[o & 0xf] & 255) << s;
1065 #endif /* BYTEORDER != 0x4321 */
1074 register int this, that;
1077 int doexec = strNE(cmd,"-");
1081 this = (*mode == 'w');
1083 while ((pid = (doexec?vfork():fork())) < 0) {
1084 if (errno != EAGAIN) {
1087 fatal("Can't fork");
1096 if (p[THIS] != (*mode == 'r')) {
1097 dup2(p[THIS], *mode == 'r');
1101 #if !defined(FCNTL) || !defined(F_SETFD)
1107 for (fd = 3; fd < NOFILE; fd++)
1110 do_exec(cmd); /* may or may not use the shell */
1113 if (tmpstab = stabent("$",allstabs))
1114 str_numset(STAB_STR(tmpstab),(double)getpid());
1120 str = afetch(pidstatary,p[this],TRUE);
1121 str_numset(str,(double)pid);
1124 return fdopen(p[this], mode);
1132 struct stat tmpstatbuf;
1134 fprintf(stderr,"%s", s);
1135 for (fd = 0; fd < 32; fd++) {
1136 if (fstat(fd,&tmpstatbuf) >= 0)
1137 fprintf(stderr," %d",fd);
1139 fprintf(stderr,"\n");
1153 while ((fd = dup(oldfd)) != newfd) /* good enough for low fd's */
1156 close(fdtmp[--fdx]);
1164 register int result;
1166 void (*hstat)(), (*istat)(), (*qstat)();
1168 int (*hstat)(), (*istat)(), (*qstat)();
1174 str = afetch(pidstatary,fileno(ptr),TRUE);
1176 pid = (int)str_gnum(str);
1179 hstat = signal(SIGHUP, SIG_IGN);
1180 istat = signal(SIGINT, SIG_IGN);
1181 qstat = signal(SIGQUIT, SIG_IGN);
1183 if (wait4(pid,&status,0,Null(struct rusage *)) < 0)
1186 if (pid < 0) /* already exited? */
1187 status = str->str_cur;
1189 while ((result = wait(&status)) != pid && result >= 0)
1190 pidgone(result,status);
1195 signal(SIGHUP, hstat);
1196 signal(SIGINT, istat);
1197 signal(SIGQUIT, qstat);
1198 str_numset(str,0.0);
1212 for (count = pidstatary->ary_fill; count >= 0; --count) {
1213 if ((str = afetch(pidstatary,count,FALSE)) &&
1214 ((int)str->str_u.str_nval) == pid) {
1215 str_numset(str, -str->str_u.str_nval);
1216 str->str_cur = status;
1225 register unsigned char *s1;
1226 register unsigned char *s2;
1232 if (tmp = *s1++ - *s2++)