home *** CD-ROM | disk | FTP | other *** search
/ APDL Public Domain 1 / APDL_PD1A.iso / program / language / perl / Source / C / Util < prev   
Encoding:
Text File  |  1991-02-09  |  25.4 KB  |  1,253 lines

  1. /* $Header: util.c,v 3.0.1.11 91/01/11 18:33:10 lwall Locked $
  2.  *
  3.  *    Copyright (c) 1989, Larry Wall
  4.  *
  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.
  7.  *
  8.  * $Log:    util.c,v $
  9.  * Revision 3.0.1.11  91/01/11  18:33:10  lwall
  10.  * patch42: die could exit with 0 value on some machines
  11.  * patch42: Configure checks typecasting behavior better
  12.  * 
  13.  * Revision 3.0.1.10  90/11/10  02:19:28  lwall
  14.  * patch38: random cleanup
  15.  * patch38: sequence of s/^x//; s/x$//; could screw up malloc
  16.  * 
  17.  * Revision 3.0.1.9  90/10/20  02:21:01  lwall
  18.  * patch37: tried to take strlen of integer on systems without wait4 or waitpid
  19.  * patch37: unreachable return eliminated
  20.  * 
  21.  * Revision 3.0.1.8  90/10/16  11:26:57  lwall
  22.  * patch29: added waitpid
  23.  * patch29: various portability fixes
  24.  * patch29: scripts now run at almost full speed under the debugger
  25.  * 
  26.  * Revision 3.0.1.7  90/08/13  22:40:26  lwall
  27.  * patch28: the NSIG hack didn't work right on Xenix
  28.  * patch28: rename was busted on systems without rename system call
  29.  * 
  30.  * Revision 3.0.1.6  90/08/09  05:44:55  lwall
  31.  * patch19: fixed double include of <signal.h>
  32.  * patch19: various MSDOS and OS/2 patches folded in
  33.  * patch19: open(STDOUT,"|command") left wrong descriptor attached to STDOUT
  34.  * 
  35.  * Revision 3.0.1.5  90/03/27  16:35:13  lwall
  36.  * patch16: MSDOS support
  37.  * patch16: support for machines that can't cast negative floats to unsigned ints
  38.  * patch16: tail anchored pattern could dump if string to search was shorter
  39.  * 
  40.  * Revision 3.0.1.4  90/03/01  10:26:48  lwall
  41.  * patch9: fbminstr() called instr() rather than ninstr()
  42.  * patch9: nested evals clobbered their longjmp environment
  43.  * patch9: piped opens returned undefined rather than 0 in child
  44.  * patch9: the x operator is now up to 10 times faster
  45.  * 
  46.  * Revision 3.0.1.3  89/12/21  20:27:41  lwall
  47.  * patch7: errno may now be a macro with an lvalue
  48.  * 
  49.  * Revision 3.0.1.2  89/11/17  15:46:35  lwall
  50.  * patch5: BZERO separate from BCOPY now
  51.  * patch5: byteorder now is a hex value
  52.  * 
  53.  * Revision 3.0.1.1  89/11/11  05:06:13  lwall
  54.  * patch2: made dup2 a little better
  55.  * 
  56.  * Revision 3.0  89/10/18  15:32:43  lwall
  57.  * 3.0 baseline
  58.  * 
  59.  */
  60.  
  61. #include "EXTERN.h"
  62. #include "perl.h"
  63. #include <signal.h>
  64.  
  65. #ifdef I_VFORK
  66. #  include <vfork.h>
  67. #endif
  68.  
  69. #ifdef I_VARARGS
  70. #  include <varargs.h>
  71. #endif
  72.  
  73. #ifdef I_STDARG
  74. #  include <stdarg.h>
  75. #endif
  76.  
  77. #define FLUSH
  78.  
  79. static char nomem[] = "Out of memory!\n";
  80.  
  81. /* paranoid version of malloc */
  82.  
  83. #ifdef DEBUGGING
  84. static int an = 0;
  85. #endif
  86.  
  87. /* NOTE:  Do not call the next three routines directly.  Use the macros
  88.  * in handy.h, so that we can easily redefine everything to do tracking of
  89.  * allocated hunks back to the original New to track down any memory leaks.
  90.  */
  91.  
  92. char *
  93. safemalloc(size)
  94. #ifdef MSDOS
  95. unsigned long size;
  96. #else
  97. MEM_SIZE size;
  98. #endif /* MSDOS */
  99. {
  100.     char *ptr;
  101.  
  102. #ifdef MSDOS
  103.     if (size > 0xffff) {
  104.         fprintf(stderr, "Allocation too large: %lx\n", size) FLUSH;
  105.         exit(1);
  106.     }
  107. #endif /* MSDOS */
  108. #ifdef DEBUGGING
  109.     if ((long)size < 0)
  110.     fatal("panic: malloc");
  111. #endif
  112.     ptr = malloc(size?size:1);    /* malloc(0) is NASTY on our system */
  113. #ifdef DEBUGGING
  114.     if (debug & 128)
  115.     fprintf(stderr,"%p: (%05d) malloc %d bytes\n",ptr,an++,size);
  116. #endif
  117.     if (ptr == Nullch) {
  118.     fputs(nomem,stderr) FLUSH;
  119.     exit(1);
  120.     }
  121.  
  122.     return ptr;
  123. }
  124.  
  125. /* paranoid version of realloc */
  126.  
  127. char *
  128. saferealloc(where,size)
  129. char *where;
  130. #ifndef MSDOS
  131. MEM_SIZE size;
  132. #else
  133. unsigned long size;
  134. #endif /* MSDOS */
  135. {
  136.     char *ptr;
  137.  
  138. #ifdef MSDOS
  139.     if (size > 0xffff) {
  140.         fprintf(stderr, "Reallocation too large: %lx\n", size) FLUSH;
  141.         exit(1);
  142.     }
  143. #endif /* MSDOS */
  144.     if (!where)
  145.     fatal("Null realloc");
  146. #ifdef DEBUGGING
  147.     if ((long)size < 0)
  148.     fatal("panic: realloc");
  149. #endif
  150.     ptr = realloc(where,size?size:1);    /* realloc(0) is NASTY on our system */
  151. #ifdef DEBUGGING
  152.     if (debug & 128) {
  153.     fprintf(stderr,"%p: (%05d) rfree\n",where,an++);
  154.     fprintf(stderr,"%p: (%05d) realloc %d bytes\n",ptr,an++,size);
  155.     }
  156. #endif
  157.     if (ptr == Nullch) {
  158.     fputs(nomem,stderr) FLUSH;
  159.     exit(1);
  160.     }
  161.  
  162.     return ptr;
  163. }
  164.  
  165. /* safe version of free */
  166.  
  167. void
  168. safefree(where)
  169. char *where;
  170. {
  171. #ifdef DEBUGGING
  172.     if (debug & 128)
  173.     fprintf(stderr,"%p: (%05d) free\n",where,an++);
  174. #endif
  175.     if (where) {
  176.     free(where);
  177.     }
  178. }
  179.  
  180. #ifdef LEAKTEST
  181.  
  182. #define ALIGN sizeof(long)
  183.  
  184. char *
  185. safexmalloc(x,size)
  186. int x;
  187. MEM_SIZE size;
  188. {
  189.     register char *where;
  190.  
  191.     where = safemalloc(size + ALIGN);
  192.     xcount[x]++;
  193.     where[0] = x % 100;
  194.     where[1] = x / 100;
  195.     return where + ALIGN;
  196. }
  197.  
  198. char *
  199. safexrealloc(where,size)
  200. char *where;
  201. MEM_SIZE size;
  202. {
  203.     return saferealloc(where - ALIGN, size + ALIGN) + ALIGN;
  204. }
  205.  
  206. void
  207. safexfree(where)
  208. char *where;
  209. {
  210.     int x;
  211.  
  212.     if (!where)
  213.     return;
  214.     where -= ALIGN;
  215.     x = where[0] + 100 * where[1];
  216.     xcount[x]--;
  217.     safefree(where);
  218. }
  219.  
  220. void
  221. xstat()
  222. {
  223.     register int i;
  224.  
  225.     for (i = 0; i < MAXXCOUNT; i++) {
  226.     if (xcount[i] != lastxcount[i]) {
  227.         fprintf(stderr,"%2d %2d\t%ld\n", i / 100, i % 100, xcount[i]);
  228.         lastxcount[i] = xcount[i];
  229.     }
  230.     }
  231. }
  232.  
  233. #endif /* LEAKTEST */
  234.  
  235. /* copy a string up to some (non-backslashed) delimiter, if any */
  236.  
  237. char *
  238. cpytill(to,from,fromend,delim,retlen)
  239. register char *to;
  240. register char *from;
  241. register char *fromend;
  242. register int delim;
  243. int *retlen;
  244. {
  245.     char *origto = to;
  246.  
  247.     for (; from < fromend; from++,to++) {
  248.     if (*from == '\\') {
  249.         if (from[1] == delim)
  250.         from++;
  251.         else if (from[1] == '\\')
  252.         *to++ = *from++;
  253.     }
  254.     else if (*from == delim)
  255.         break;
  256.     *to = *from;
  257.     }
  258.     *to = '\0';
  259.     *retlen = to - origto;
  260.     return from;
  261. }
  262.  
  263. /* return ptr to little string in big string, NULL if not found */
  264. /* This routine was donated by Corey Satten. */
  265.  
  266. char *
  267. instr(big, little)
  268. register char *big;
  269. register char *little;
  270. {
  271.     register char *s, *x;
  272.     register int first;
  273.  
  274.     if (!little)
  275.     return big;
  276.     first = *little++;
  277.     if (!first)
  278.     return big;
  279.     while (*big) {
  280.     if (*big++ != first)
  281.         continue;
  282.     for (x=big,s=little; *s; /**/ ) {
  283.         if (!*x)
  284.         return Nullch;
  285.         if (*s++ != *x++) {
  286.         s--;
  287.         break;
  288.         }
  289.     }
  290.     if (!*s)
  291.         return big-1;
  292.     }
  293.     return Nullch;
  294. }
  295.  
  296. /* same as instr but allow embedded nulls */
  297.  
  298. char *
  299. ninstr(big, bigend, little, lend)
  300. register char *big;
  301. register char *bigend;
  302. char *little;
  303. char *lend;
  304. {
  305.     register char *s, *x;
  306.     register int first = *little;
  307.     register char *littleend = lend;
  308.  
  309.     if (!first && little > littleend)
  310.     return big;
  311.     bigend -= littleend - little++;
  312.     while (big <= bigend) {
  313.     if (*big++ != first)
  314.         continue;
  315.     for (x=big,s=little; s < littleend; /**/ ) {
  316.         if (*s++ != *x++) {
  317.         s--;
  318.         break;
  319.         }
  320.     }
  321.     if (s >= littleend)
  322.         return big-1;
  323.     }
  324.     return Nullch;
  325. }
  326.  
  327. /* reverse of the above--find last substring */
  328.  
  329. char *
  330. rninstr(big, bigend, little, lend)
  331. register char *big;
  332. char *bigend;
  333. char *little;
  334. char *lend;
  335. {
  336.     register char *bigbeg;
  337.     register char *s, *x;
  338.     register int first = *little;
  339.     register char *littleend = lend;
  340.  
  341.     if (!first && little > littleend)
  342.     return bigend;
  343.     bigbeg = big;
  344.     big = bigend - (littleend - little++);
  345.     while (big >= bigbeg) {
  346.     if (*big-- != first)
  347.         continue;
  348.     for (x=big+2,s=little; s < littleend; /**/ ) {
  349.         if (*s++ != *x++) {
  350.         s--;
  351.         break;
  352.         }
  353.     }
  354.     if (s >= littleend)
  355.         return big+1;
  356.     }
  357.     return Nullch;
  358. }
  359.  
  360. unsigned char fold[] = {
  361.     0,    1,    2,    3,    4,    5,    6,    7,
  362.     8,    9,    10,    11,    12,    13,    14,    15,
  363.     16,    17,    18,    19,    20,    21,    22,    23,
  364.     24,    25,    26,    27,    28,    29,    30,    31,
  365.     32,    33,    34,    35,    36,    37,    38,    39,
  366.     40,    41,    42,    43,    44,    45,    46,    47,
  367.     48,    49,    50,    51,    52,    53,    54,    55,
  368.     56,    57,    58,    59,    60,    61,    62,    63,
  369.     64,    'a',    'b',    'c',    'd',    'e',    'f',    'g',
  370.     'h',    'i',    'j',    'k',    'l',    'm',    'n',    'o',
  371.     'p',    'q',    'r',    's',    't',    'u',    'v',    'w',
  372.     'x',    'y',    'z',    91,    92,    93,    94,    95,
  373.     96,    'A',    'B',    'C',    'D',    'E',    'F',    'G',
  374.     'H',    'I',    'J',    'K',    'L',    'M',    'N',    'O',
  375.     'P',    'Q',    'R',    'S',    'T',    'U',    'V',    'W',
  376.     'X',    'Y',    'Z',    123,    124,    125,    126,    127,
  377.     128,    129,    130,    131,    132,    133,    134,    135,
  378.     136,    137,    138,    139,    140,    141,    142,    143,
  379.     144,    145,    146,    147,    148,    149,    150,    151,
  380.     152,    153,    154,    155,    156,    157,    158,    159,
  381.     160,    161,    162,    163,    164,    165,    166,    167,
  382.     168,    169,    170,    171,    172,    173,    174,    175,
  383.     176,    177,    178,    179,    180,    181,    182,    183,
  384.     184,    185,    186,    187,    188,    189,    190,    191,
  385.     192,    193,    194,    195,    196,    197,    198,    199,
  386.     200,    201,    202,    203,    204,    205,    206,    207,
  387.     208,    209,    210,    211,    212,    213,    214,    215,
  388.     216,    217,    218,    219,    220,    221,    222,    223,    
  389.     224,    225,    226,    227,    228,    229,    230,    231,
  390.     232,    233,    234,    235,    236,    237,    238,    239,
  391.     240,    241,    242,    243,    244,    245,    246,    247,
  392.     248,    249,    250,    251,    252,    253,    254,    255
  393. };
  394.  
  395. static unsigned char freq[] = {
  396.     1,    2,    84,    151,    154,    155,    156,    157,
  397.     165,    246,    250,    3,    158,    7,    18,    29,
  398.     40,    51,    62,    73,    85,    96,    107,    118,
  399.     129,    140,    147,    148,    149,    150,    152,    153,
  400.     255,    182,    224,    205,    174,    176,    180,    217,
  401.     233,    232,    236,    187,    235,    228,    234,    226,
  402.     222,    219,    211,    195,    188,    193,    185,    184,
  403.     191,    183,    201,    229,    181,    220,    194,    162,
  404.     163,    208,    186,    202,    200,    218,    198,    179,
  405.     178,    214,    166,    170,    207,    199,    209,    206,
  406.     204,    160,    212,    216,    215,    192,    175,    173,
  407.     243,    172,    161,    190,    203,    189,    164,    230,
  408.     167,    248,    227,    244,    242,    255,    241,    231,
  409.     240,    253,    169,    210,    245,    237,    249,    247,
  410.     239,    168,    252,    251,    254,    238,    223,    221,
  411.     213,    225,    177,    197,    171,    196,    159,    4,
  412.     5,    6,    8,    9,    10,    11,    12,    13,
  413.     14,    15,    16,    17,    19,    20,    21,    22,
  414.     23,    24,    25,    26,    27,    28,    30,    31,
  415.     32,    33,    34,    35,    36,    37,    38,    39,
  416.     41,    42,    43,    44,    45,    46,    47,    48,
  417.     49,    50,    52,    53,    54,    55,    56,    57,
  418.     58,    59,    60,    61,    63,    64,    65,    66,
  419.     67,    68,    69,    70,    71,    72,    74,    75,
  420.     76,    77,    78,    79,    80,    81,    82,    83,
  421.     86,    87,    88,    89,    90,    91,    92,    93,
  422.     94,    95,    97,    98,    99,    100,    101,    102,
  423.     103,    104,    105,    106,    108,    109,    110,    111,
  424.     112,    113,    114,    115,    116,    117,    119,    120,
  425.     121,    122,    123,    124,    125,    126,    127,    128,
  426.     130,    131,    132,    133,    134,    135,    136,    137,
  427.     138,    139,    141,    142,    143,    144,    145,    146
  428. };
  429.  
  430. void
  431. fbmcompile(str, iflag)
  432. STR *str;
  433. int iflag;
  434. {
  435.     register unsigned char *s;
  436.     register unsigned char *table;
  437.     register int i;
  438.     register int len = str->str_cur;
  439.     int rarest = 0;
  440.     unsigned int frequency = 256;
  441.  
  442.     Str_Grow(str,len+258);
  443. #ifndef lint
  444.     table = (unsigned char*)(str->str_ptr + len + 1);
  445. #else
  446.     table = Null(unsigned char*);
  447. #endif
  448.     s = table - 2;
  449.     for (i = 0; i < 256; i++) {
  450.     table[i] = len;
  451.     }
  452.     i = 0;
  453. #ifndef lint
  454.     while (s >= (unsigned char*)(str->str_ptr))
  455. #endif
  456.     {
  457.     if (table[*s] == len) {
  458. #ifndef pdp11
  459.         if (iflag)
  460.         table[*s] = table[fold[*s]] = i;
  461. #else
  462.         if (iflag) {
  463.         int j;
  464.         j = fold[*s];
  465.         table[j] = i;
  466.         table[*s] = i;
  467.         }
  468. #endif /* pdp11 */
  469.         else
  470.         table[*s] = i;
  471.     }
  472.     s--,i++;
  473.     }
  474.     str->str_pok |= SP_FBM;        /* deep magic */
  475.  
  476. #ifndef lint
  477.     s = (unsigned char*)(str->str_ptr);        /* deeper magic */
  478. #else
  479.     s = Null(unsigned char*);
  480. #endif
  481.     if (iflag) {
  482.     register unsigned int tmp, foldtmp;
  483.     str->str_pok |= SP_CASEFOLD;
  484.     for (i = 0; i < len; i++) {
  485.         tmp=freq[s[i]];
  486.         foldtmp=freq[fold[s[i]]];
  487.         if (tmp < frequency && foldtmp < frequency) {
  488.         rarest = i;
  489.         /* choose most frequent among the two */
  490.         frequency = (tmp > foldtmp) ? tmp : foldtmp;
  491.         }
  492.     }
  493.     }
  494.     else {
  495.     for (i = 0; i < len; i++) {
  496.         if (freq[s[i]] < frequency) {
  497.         rarest = i;
  498.         frequency = freq[s[i]];
  499.         }
  500.     }
  501.     }
  502.     str->str_rare = s[rarest];
  503.     str->str_state = rarest;
  504. #ifdef DEBUGGING
  505.     if (debug & 512)
  506.     fprintf(stderr,"rarest char %c at %d\n",str->str_rare, str->str_state);
  507. #endif
  508. }
  509.  
  510. char *
  511. fbminstr(big, bigend, littlestr)
  512. unsigned char *big;
  513. register unsigned char *bigend;
  514. STR *littlestr;
  515. {
  516.     register unsigned char *s;
  517.     register int tmp;
  518.     register int littlelen;
  519.     register unsigned char *little;
  520.     register unsigned char *table;
  521.     register unsigned char *olds;
  522.     register unsigned char *oldlittle;
  523.  
  524. #ifndef lint
  525.     if (!(littlestr->str_pok & SP_FBM))
  526.     return ninstr((char*)big,(char*)bigend,
  527.         littlestr->str_ptr, littlestr->str_ptr + littlestr->str_cur);
  528. #endif
  529.  
  530.     littlelen = littlestr->str_cur;
  531. #ifndef lint
  532.     if (littlestr->str_pok & SP_TAIL && !multiline) {    /* tail anchored? */
  533.     if (littlelen > bigend - big)
  534.         return Nullch;
  535.     little = (unsigned char*)littlestr->str_ptr;
  536.     if (littlestr->str_pok & SP_CASEFOLD) {    /* oops, fake it */
  537.         big = bigend - littlelen;        /* just start near end */
  538.         if (bigend[-1] == '\n' && little[littlelen-1] != '\n')
  539.         big--;
  540.     }
  541.     else {
  542.         s = bigend - littlelen;
  543.         if (*s == *little && bcmp(s,little,littlelen)==0)
  544.         return (char*)s;        /* how sweet it is */
  545.         else if (bigend[-1] == '\n' && little[littlelen-1] != '\n'
  546.           && s > big) {
  547.             s--;
  548.         if (*s == *little && bcmp(s,little,littlelen)==0)
  549.             return (char*)s;
  550.         }
  551.         return Nullch;
  552.     }
  553.     }
  554.     table = (unsigned char*)(littlestr->str_ptr + littlelen + 1);
  555. #else
  556.     table = Null(unsigned char*);
  557. #endif
  558.     if (--littlelen >= bigend - big)
  559.     return Nullch;
  560.     s = big + littlelen;
  561.     oldlittle = little = table - 2;
  562.     if (littlestr->str_pok & SP_CASEFOLD) {    /* case insensitive? */
  563.     if (s < bigend) {
  564.       top1:
  565.         if ((tmp = table[*s]) != 0) {
  566. #ifdef POINTERRIGOR
  567.         if (bigend - s > tmp) {
  568.             s += tmp;
  569.             goto top1;
  570.         }
  571. #else
  572.         if ((s += tmp) < bigend)
  573.             goto top1;
  574. #endif
  575.         return Nullch;
  576.         }
  577.         else {
  578.         tmp = littlelen;    /* less expensive than calling strncmp() */
  579.         olds = s;
  580.         while (tmp--) {
  581.             if (*--s == *--little || fold[*s] == *little)
  582.             continue;
  583.             s = olds + 1;    /* here we pay the price for failure */
  584.             little = oldlittle;
  585.             if (s < bigend)    /* fake up continue to outer loop */
  586.             goto top1;
  587.             return Nullch;
  588.         }
  589. #ifndef lint
  590.         return (char *)s;
  591. #endif
  592.         }
  593.     }
  594.     }
  595.     else {
  596.     if (s < bigend) {
  597.       top2:
  598.         if ((tmp = table[*s]) != 0) {
  599. #ifdef POINTERRIGOR
  600.         if (bigend - s > tmp) {
  601.             s += tmp;
  602.             goto top2;
  603.         }
  604. #else
  605.         if ((s += tmp) < bigend)
  606.             goto top2;
  607. #endif
  608.         return Nullch;
  609.         }
  610.         else {
  611.         tmp = littlelen;    /* less expensive than calling strncmp() */
  612.         olds = s;
  613.         while (tmp--) {
  614.             if (*--s == *--little)
  615.             continue;
  616.             s = olds + 1;    /* here we pay the price for failure */
  617.             little = oldlittle;
  618.             if (s < bigend)    /* fake up continue to outer loop */
  619.             goto top2;
  620.             return Nullch;
  621.         }
  622. #ifndef lint
  623.         return (char *)s;
  624. #endif
  625.         }
  626.     }
  627.     }
  628.     return Nullch;
  629. }
  630.  
  631. char *
  632. screaminstr(bigstr, littlestr)
  633. STR *bigstr;
  634. STR *littlestr;
  635. {
  636.     register unsigned char *s, *x;
  637.     register unsigned char *big;
  638.     register int pos;
  639.     register int previous;
  640.     register int first;
  641.     register unsigned char *little;
  642.     register unsigned char *bigend;
  643.     register unsigned char *littleend;
  644.  
  645.     if ((pos = screamfirst[littlestr->str_rare]) < 0) 
  646.     return Nullch;
  647. #ifndef lint
  648.     little = (unsigned char *)(littlestr->str_ptr);
  649. #else
  650.     little = Null(unsigned char *);
  651. #endif
  652.     littleend = little + littlestr->str_cur;
  653.     first = *little++;
  654.     previous = littlestr->str_state;
  655. #ifndef lint
  656.     big = (unsigned char *)(bigstr->str_ptr);
  657. #else
  658.     big = Null(unsigned char*);
  659. #endif
  660.     bigend = big + bigstr->str_cur;
  661.     big -= previous;
  662.     while (pos < previous) {
  663. #ifndef lint
  664.     if (!(pos += screamnext[pos]))
  665. #endif
  666.         return Nullch;
  667.     }
  668.     if (littlestr->str_pok & SP_CASEFOLD) {    /* case insignificant? */
  669.     do {
  670.         if (big[pos] != first && big[pos] != fold[first])
  671.         continue;
  672.         for (x=big+pos+1,s=little; s < littleend; /**/ ) {
  673.         if (x >= bigend)
  674.             return Nullch;
  675.         if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
  676.             s--;
  677.             break;
  678.         }
  679.         }
  680.         if (s == littleend)
  681. #ifndef lint
  682.         return (char *)(big+pos);
  683. #else
  684.         return Nullch;
  685. #endif
  686.     } while (
  687. #ifndef lint
  688.         pos += screamnext[pos]    /* does this goof up anywhere? */
  689. #else
  690.         pos += screamnext[0]
  691. #endif
  692.         );
  693.     }
  694.     else {
  695.     do {
  696.         if (big[pos] != first)
  697.         continue;
  698.         for (x=big+pos+1,s=little; s < littleend; /**/ ) {
  699.         if (x >= bigend)
  700.             return Nullch;
  701.         if (*s++ != *x++) {
  702.             s--;
  703.             break;
  704.         }
  705.         }
  706.         if (s == littleend)
  707. #ifndef lint
  708.         return (char *)(big+pos);
  709. #else
  710.         return Nullch;
  711. #endif
  712.     } while (
  713. #ifndef lint
  714.         pos += screamnext[pos]
  715. #else
  716.         pos += screamnext[0]
  717. #endif
  718.         );
  719.     }
  720.     return Nullch;
  721. }
  722.  
  723. /* copy a string to a safe spot */
  724.  
  725. char *
  726. savestr(str)
  727. char *str;
  728. {
  729.     register char *newaddr;
  730.  
  731.     New(902,newaddr,strlen(str)+1,char);
  732.     (void)strcpy(newaddr,str);
  733.     return newaddr;
  734. }
  735.  
  736. /* same thing but with a known length */
  737.  
  738. char *
  739. nsavestr(str, len)
  740. char *str;
  741. register int len;
  742. {
  743.     register char *newaddr;
  744.  
  745.     New(903,newaddr,len+1,char);
  746.     (void)bcopy(str,newaddr,len);    /* might not be null terminated */
  747.     newaddr[len] = '\0';        /* is now */
  748.     return newaddr;
  749. }
  750.  
  751. /* grow a static string to at least a certain length */
  752.  
  753. void
  754. growstr(strptr,curlen,newlen)
  755. char **strptr;
  756. int *curlen;
  757. int newlen;
  758. {
  759.     if (newlen > *curlen) {        /* need more room? */
  760.     if (*curlen)
  761.         Renew(*strptr,newlen,char);
  762.     else
  763.         New(905,*strptr,newlen,char);
  764.     *curlen = newlen;
  765.     }
  766. }
  767.  
  768. #ifndef STDARG
  769. #ifndef VARARGS
  770. /*VARARGS1*/
  771. mess(pat,a1,a2,a3,a4)
  772. char *pat;
  773. long a1, a2, a3, a4;
  774. {
  775.     char *s;
  776.  
  777.     s = buf;
  778.     (void)sprintf(s,pat,a1,a2,a3,a4);
  779.     s += strlen(s);
  780.     if (s[-1] != '\n') {
  781.     if (curcmd->c_line) {
  782.         (void)sprintf(s," at %s line %ld",
  783.           stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
  784.         s += strlen(s);
  785.     }
  786.     if (last_in_stab &&
  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 ? "" : stab_name(last_in_stab),
  791.           (long)stab_io(last_in_stab)->lines);
  792.         s += strlen(s);
  793.     }
  794.     (void)strcpy(s,".\n");
  795.     }
  796. }
  797.  
  798. /*VARARGS1*/
  799. fatal(pat,a1,a2,a3,a4)
  800. char *pat;
  801. long a1, a2, a3, a4;
  802. {
  803.     extern FILE *e_fp;
  804.     extern char *e_tmpname;
  805.     char *tmps;
  806.  
  807.     mess(pat,a1,a2,a3,a4);
  808.     if (in_eval) {
  809.     str_set(stab_val(stabent("@",TRUE)),buf);
  810.     tmps = "_EVAL_";
  811.     while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
  812.       strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
  813. #ifdef DEBUGGING
  814.         if (debug & 4) {
  815.         deb("(Skipping label #%d %s)\n",loop_ptr,
  816.             loop_stack[loop_ptr].loop_label);
  817.         }
  818. #endif
  819.         loop_ptr--;
  820.     }
  821. #ifdef DEBUGGING
  822.     if (debug & 4) {
  823.         deb("(Found label #%d %s)\n",loop_ptr,
  824.         loop_stack[loop_ptr].loop_label);
  825.     }
  826. #endif
  827.     if (loop_ptr < 0) {
  828.         in_eval = 0;
  829.         fatal("Bad label: %s", tmps);
  830.     }
  831.     longjmp(loop_stack[loop_ptr].loop_env, 1);
  832.     }
  833.     fputs(buf,stderr);
  834.     (void)fflush(stderr);
  835.     if (e_fp)
  836.     (void)UNLINK(e_tmpname);
  837.     exit (statusvalue ? statusvalue : 255);
  838. }
  839.  
  840. /*VARARGS1*/
  841. warn(pat,a1,a2,a3,a4)
  842. char *pat;
  843. long a1, a2, a3, a4;
  844. {
  845.     mess(pat,a1,a2,a3,a4);
  846.     fputs(buf,stderr);
  847. #ifdef LEAKTEST
  848. #ifdef DEBUGGING
  849.     if (debug & 4096)
  850.     xstat();
  851. #endif
  852. #endif
  853.     (void)fflush(stderr);
  854. }
  855. #else /* VARARGS */
  856. /*VARARGS0*/
  857. void
  858. mess(args)
  859. va_list args;
  860. {
  861.     char *pat;
  862.     char *s;
  863.  
  864.     s = buf;
  865. #ifdef lint
  866.     pat = Nullch;
  867. #else
  868.     pat = va_arg(args, char *);
  869. #endif
  870.     (void) vsprintf(s,pat,args);
  871.  
  872.     s += strlen(s);
  873.     if (s[-1] != '\n') {
  874.     if (curcmd->c_line) {
  875.         (void)sprintf(s," at %s line %ld",
  876.           stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
  877.         s += strlen(s);
  878.     }
  879.     if (last_in_stab &&
  880.         stab_io(last_in_stab) &&
  881.         stab_io(last_in_stab)->lines ) {
  882.         (void)sprintf(s,", <%s> line %ld",
  883.           last_in_stab == argvstab ? "" : last_in_stab->str_magic->str_ptr,
  884.           (long)stab_io(last_in_stab)->lines);
  885.         s += strlen(s);
  886.     }
  887.     (void)strcpy(s,".\n");
  888.     }
  889. }
  890.  
  891. /*VARARGS0*/
  892. void
  893. fatal(va_alist)
  894. va_dcl
  895. {
  896.     va_list args;
  897.     extern FILE *e_fp;
  898.     extern char *e_tmpname;
  899.     char *tmps;
  900.  
  901. #ifndef lint
  902.     va_start(args);
  903. #else
  904.     args = 0;
  905. #endif
  906.     mess(args);
  907.     va_end(args);
  908.     if (in_eval) {
  909.     str_set(stab_val(stabent("@",TRUE)),buf);
  910.     tmps = "_EVAL_";
  911.     while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
  912.       strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
  913. #ifdef DEBUGGING
  914.         if (debug & 4) {
  915.         deb("(Skipping label #%d %s)\n",loop_ptr,
  916.             loop_stack[loop_ptr].loop_label);
  917.         }
  918. #endif
  919.         loop_ptr--;
  920.     }
  921. #ifdef DEBUGGING
  922.     if (debug & 4) {
  923.         deb("(Found label #%d %s)\n",loop_ptr,
  924.         loop_stack[loop_ptr].loop_label);
  925.     }
  926. #endif
  927.     if (loop_ptr < 0) {
  928.         in_eval = 0;
  929.         fatal("Bad label: %s", tmps);
  930.     }
  931.     longjmp(loop_stack[loop_ptr].loop_env, 1);
  932.     }
  933.     fputs(buf,stderr);
  934.     (void)fflush(stderr);
  935.     if (e_fp)
  936.     (void)UNLINK(e_tmpname);
  937.     exit (statusvalue ? statusvalue : 255);
  938. }
  939.  
  940. /*VARARGS0*/
  941. void
  942. warn(va_alist)
  943. va_dcl
  944. {
  945.     va_list args;
  946.  
  947. #ifndef lint
  948.     va_start(args);
  949. #else
  950.     args = 0;
  951. #endif
  952.     mess(args);
  953.     va_end(args);
  954.  
  955.     fputs(buf,stderr);
  956. #ifdef LEAKTEST
  957. #ifdef DEBUGGING
  958.     if (debug & 4096)
  959.     xstat();
  960. #endif
  961. #endif
  962.     (void)fflush(stderr);
  963. }
  964. #endif /* VARARGS */
  965. #else /* STDARG */
  966.  
  967. /*VARARGS0*/
  968. void
  969. vmess(char *pat, va_list ap)
  970. {
  971.     char *s;
  972.  
  973.     s = buf;
  974.  
  975.     (void) vsprintf(s,pat,ap);
  976.  
  977.     s += strlen(s);
  978.     if (s[-1] != '\n') {
  979.     if (curcmd->c_line) {
  980.         (void)sprintf(s," at %s line %ld",
  981.           stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
  982.         s += strlen(s);
  983.     }
  984.     if (last_in_stab &&
  985.         stab_io(last_in_stab) &&
  986.         stab_io(last_in_stab)->lines ) {
  987.         (void)sprintf(s,", <%s> line %ld",
  988.           last_in_stab == argvstab ? "" : last_in_stab->str_magic->str_ptr,
  989.           (long)stab_io(last_in_stab)->lines);
  990.         s += strlen(s);
  991.     }
  992.     (void)strcpy(s,".\n");
  993.     }
  994. }
  995.  
  996. /*VARARGS0*/
  997. void
  998. mess(char *pat, ...)
  999. {
  1000.     va_list ap;
  1001.  
  1002.     va_start(ap,pat);
  1003.     (void) vmess(pat,ap);
  1004.     va_end(ap);
  1005. }
  1006.  
  1007. /*VARARGS0*/
  1008. void
  1009. fatal(char *pat, ...)
  1010. {
  1011.     va_list ap;
  1012.     extern FILE *e_fp;
  1013.     extern char *e_tmpname;
  1014.     char *tmps;
  1015.  
  1016.     va_start(ap,pat);
  1017.     vmess(pat,ap);
  1018.     va_end(ap);
  1019.  
  1020.     if (in_eval) {
  1021.     str_set(stab_val(stabent("@",TRUE)),buf);
  1022.     tmps = "_EVAL_";
  1023.     while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
  1024.       strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
  1025. #ifdef DEBUGGING
  1026.         if (debug & 4) {
  1027.         deb("(Skipping label #%d %s)\n",loop_ptr,
  1028.             loop_stack[loop_ptr].loop_label);
  1029.         }
  1030. #endif
  1031.         loop_ptr--;
  1032.     }
  1033. #ifdef DEBUGGING
  1034.     if (debug & 4) {
  1035.         deb("(Found label #%d %s)\n",loop_ptr,
  1036.         loop_stack[loop_ptr].loop_label);
  1037.     }
  1038. #endif
  1039.     if (loop_ptr < 0) {
  1040.         in_eval = 0;
  1041.         fatal("Bad label: %s", tmps);
  1042.     }
  1043.     longjmp(loop_stack[loop_ptr].loop_env, 1);
  1044.     }
  1045.     fputs(buf,stderr);
  1046.     (void)fflush(stderr);
  1047.     if (e_fp)
  1048.     (void)UNLINK(e_tmpname);
  1049.     exit (statusvalue ? statusvalue : 255);
  1050. }
  1051.  
  1052. /*VARARGS0*/
  1053. void
  1054. warn(char *pat, ...)
  1055. {
  1056.     va_list ap;
  1057.  
  1058.     va_start(ap,pat);
  1059.     vmess(pat,ap);
  1060.     va_end(ap);
  1061.  
  1062.     fputs(buf,stderr);
  1063. #ifdef LEAKTEST
  1064. #ifdef DEBUGGING
  1065.     if (debug & 4096)
  1066.     xstat();
  1067. #endif
  1068. #endif
  1069.     (void)fflush(stderr);
  1070. }
  1071. #endif /* STDARG */
  1072.  
  1073. #ifndef ARM
  1074. static bool firstsetenv = TRUE;
  1075. extern char **environ;
  1076.  
  1077. void
  1078. setenv(nam,val)
  1079. char *nam, *val;
  1080. {
  1081.     register int i=envix(nam);        /* where does it go? */
  1082.  
  1083.     if (!val) {
  1084.     while (environ[i]) {
  1085.         environ[i] = environ[i+1];
  1086.         i++;
  1087.     }
  1088.     return;
  1089.     }
  1090.     if (!environ[i]) {            /* does not exist yet */
  1091.     if (firstsetenv) {        /* need we copy environment? */
  1092.         int j;
  1093.         char **tmpenv;
  1094.  
  1095.         New(901,tmpenv, i+2, char*);
  1096.         firstsetenv = FALSE;
  1097.         for (j=0; j<i; j++)        /* copy environment */
  1098.         tmpenv[j] = environ[j];
  1099.         environ = tmpenv;        /* tell exec where it is now */
  1100.     }
  1101.     else
  1102.         Renew(environ, i+2, char*);    /* just expand it a bit */
  1103.     environ[i+1] = Nullch;    /* make sure it's null terminated */
  1104.     }
  1105.     New(904, environ[i], strlen(nam) + strlen(val) + 2, char);
  1106.                     /* this may or may not be in */
  1107.                     /* the old environ structure */
  1108. #ifndef MSDOS
  1109.     (void)sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
  1110. #else
  1111.     /* MS-DOS requires environment variable names to be in uppercase */
  1112.     strcpy(environ[i],nam); strupr(environ[i],nam);
  1113.     (void)sprintf(environ[i] + strlen(nam),"=%s",val);
  1114. #endif /* MSDOS */
  1115. }
  1116.  
  1117. int
  1118. envix(nam)
  1119. char *nam;
  1120. {
  1121.     register int i, len = strlen(nam);
  1122.  
  1123.     for (i = 0; environ[i]; i++) {
  1124.     if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
  1125.         break;            /* strnEQ must come first to avoid */
  1126.     }                    /* potential SEGV's */
  1127.     return i;
  1128. }
  1129. #endif
  1130.  
  1131. #ifdef EUNICE
  1132. unlnk(f)    /* unlink all versions of a file */
  1133. char *f;
  1134. {
  1135.     int i;
  1136.  
  1137.     for (i = 0; unlink(f) >= 0; i++) ;
  1138.     return i ? 0 : -1;
  1139. }
  1140. #endif
  1141.  
  1142. #ifndef MEMCPY
  1143. #ifndef BCOPY
  1144. char *
  1145. bcopy(from,to,len)
  1146. register char *from;
  1147. register char *to;
  1148. register int len;
  1149. {
  1150.     char *retval = to;
  1151.  
  1152.     while (len--)
  1153.     *to++ = *from++;
  1154.     return retval;
  1155. }
  1156. #endif
  1157.  
  1158. #ifndef BZERO
  1159. char *
  1160. bzero(loc,len)
  1161. register char *loc;
  1162. register int len;
  1163. {
  1164.     char *retval = loc;
  1165.  
  1166.     while (len--)
  1167.     *loc++ = 0;
  1168.     return retval;
  1169. }
  1170. #endif
  1171. #endif
  1172.  
  1173. #ifdef VARARGS
  1174. #ifndef VPRINTF
  1175.  
  1176. #ifdef CHARVSPRINTF
  1177. char *
  1178. #else
  1179. int
  1180. #endif
  1181. vsprintf(dest, pat, args)
  1182. char *dest, *pat, *args;
  1183. {
  1184.     FILE fakebuf;
  1185.  
  1186.     fakebuf._ptr = dest;
  1187.     fakebuf._cnt = 32767;
  1188.     fakebuf._flag = _IOWRT|_IOSTRG;
  1189.     _doprnt(pat, args, &fakebuf);    /* what a kludge */
  1190.     (void)putc('\0', &fakebuf);
  1191. #ifdef CHARVSPRINTF
  1192.     return(dest);
  1193. #else
  1194.     return 0;        /* perl doesn't use return value */
  1195. #endif
  1196. }
  1197.  
  1198. #ifdef DEBUGGING
  1199. int
  1200. vfprintf(fd, pat, args)
  1201. FILE *fd;
  1202. char *pat, *args;
  1203. {
  1204.     _doprnt(pat, args, fd);
  1205.     return 0;        /* wrong, but perl doesn't use the return value */
  1206. }
  1207. #endif
  1208. #endif /* VPRINTF */
  1209. #endif /* VARARGS */
  1210.  
  1211. void
  1212. repeatcpy(to,from,len,count)
  1213. register char *to;
  1214. register char *from;
  1215. int len;
  1216. register int count;
  1217. {
  1218.     register int todo;
  1219.     register char *frombase = from;
  1220.  
  1221.     if (len == 1) {
  1222.     todo = *from;
  1223.     while (count-- > 0)
  1224.         *to++ = todo;
  1225.     return;
  1226.     }
  1227.     while (count-- > 0) {
  1228.     for (todo = len; todo > 0; todo--) {
  1229.         *to++ = *from++;
  1230.     }
  1231.     from = frombase;
  1232.     }
  1233. }
  1234.  
  1235. #ifndef CASTNEGFLOAT
  1236. unsigned long
  1237. castulong(f)
  1238. double f;
  1239. {
  1240.     long along;
  1241.  
  1242. #if CASTFLAGS & 2
  1243. #   define BIGDOUBLE 2147483648.0
  1244.     if (f >= BIGDOUBLE)
  1245.     return (unsigned long)(f-(long)(f/BIGDOUBLE)*BIGDOUBLE)|0x80000000;
  1246. #endif
  1247.     if (f >= 0.0)
  1248.     return (unsigned long)f;
  1249.     along = (long)f;
  1250.     return (unsigned long)along;
  1251. }
  1252. #endif
  1253.