home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / lang / perl4.035.V010.lzh / perl4.035 / src / util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-22  |  36.6 KB  |  1,832 lines

  1. /* $RCSfile: util.c,v $$Revision: 4.0.1.6 $$Date: 92/06/11 21:18:47 $
  2.  *
  3.  *    Copyright (c) 1991, Larry Wall
  4.  *
  5.  *    You may distribute under the terms of either the GNU General Public
  6.  *    License or the Artistic License, as specified in the README file.
  7.  *
  8.  * $Log:    util.c,v $
  9.  * Revision 4.0.1.6  92/06/11  21:18:47  lwall
  10.  * patch34: boneheaded typo in my_bcopy()
  11.  * 
  12.  * Revision 4.0.1.5  92/06/08  16:08:37  lwall
  13.  * patch20: removed implicit int declarations on functions
  14.  * patch20: Perl now distinguishes overlapped copies from non-overlapped
  15.  * patch20: fixed confusion between a *var's real name and its effective name
  16.  * patch20: bcopy() and memcpy() now tested for overlap safety
  17.  * patch20: added Atari ST portability
  18.  * 
  19.  * Revision 4.0.1.4  91/11/11  16:48:54  lwall
  20.  * patch19: study was busted by 4.018
  21.  * patch19: added little-endian pack/unpack options
  22.  * 
  23.  * Revision 4.0.1.3  91/11/05  19:18:26  lwall
  24.  * patch11: safe malloc code now integrated into Perl's malloc when possible
  25.  * patch11: index("little", "longer string") could visit faraway places
  26.  * patch11: warn '-' x 10000 dumped core
  27.  * patch11: forked exec on non-existent program now issues a warning
  28.  * 
  29.  * Revision 4.0.1.2  91/06/07  12:10:42  lwall
  30.  * patch4: new copyright notice
  31.  * patch4: made some allowances for "semi-standard" C
  32.  * patch4: index() could blow up searching for null string
  33.  * patch4: taintchecks could improperly modify parent in vfork()
  34.  * patch4: exec would close files even if you cleared close-on-exec flag
  35.  * 
  36.  * Revision 4.0.1.1  91/04/12  09:19:25  lwall
  37.  * patch1: random cleanup in cpp namespace
  38.  * 
  39.  * Revision 4.0  91/03/20  01:56:39  lwall
  40.  * 4.0 baseline.
  41.  * 
  42.  */
  43. /*SUPPRESS 112*/
  44.  
  45. #include "EXTERN.h"
  46. #include "perl.h"
  47.  
  48. #ifdef AMIGA
  49. #include <unistd.h>
  50. #define DEFPOPEN
  51. #endif
  52.  
  53. #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
  54. #include <signal.h>
  55. #endif
  56.  
  57. #ifdef I_VFORK
  58. #  include <vfork.h>
  59. #endif
  60.  
  61. #ifdef I_VARARGS
  62. #  include <varargs.h>
  63. #endif
  64.  
  65. #ifdef I_FCNTL
  66. #  include <fcntl.h>
  67. #endif
  68. #ifdef I_SYS_FILE
  69. #  include <sys/file.h>
  70. #endif
  71.  
  72. #define FLUSH
  73.  
  74. #ifndef safemalloc
  75.  
  76. static char nomem[] = "Out of memory!\n";
  77.  
  78. /* paranoid version of malloc */
  79.  
  80. #ifdef DEBUGGING
  81. static int an = 0;
  82. #endif
  83.  
  84. /* NOTE:  Do not call the next three routines directly.  Use the macros
  85.  * in handy.h, so that we can easily redefine everything to do tracking of
  86.  * allocated hunks back to the original New to track down any memory leaks.
  87.  */
  88.  
  89. char *
  90. safemalloc(size)
  91. #ifdef MSDOS
  92. unsigned long size;
  93. #else
  94. MEM_SIZE size;
  95. #endif /* MSDOS */
  96. {
  97.     char *ptr;
  98. #ifndef STANDARD_C
  99.     char *malloc();
  100. #endif /* ! STANDARD_C */
  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.  
  113.     ptr = malloc(size?size:1);    /* malloc(0) is NASTY on our system */
  114.  
  115. #ifdef DEBUGGING
  116. #  if !(defined(I286) || defined(atarist))
  117.     if (debug & 128)
  118.     fprintf(stderr,"0x%x: (%05d) malloc %ld bytes\n",ptr,an++,(long)size);
  119. #  else
  120.     if (debug & 128)
  121.     fprintf(stderr,"0x%lx: (%05d) malloc %ld bytes\n",ptr,an++,(long)size);
  122. #  endif
  123. #endif
  124.     if (ptr != Nullch)
  125.     return ptr;
  126.     else if (nomemok)
  127.     return Nullch;
  128.     else {
  129.     fprintf(stderr, "safemalloc failed for %d bytes\n", size);
  130.     fputs(nomem,stderr) FLUSH;
  131.     exit(1);
  132.     }
  133.     /*NOTREACHED*/
  134. #ifdef lint
  135.     return ptr;
  136. #endif
  137. }
  138.  
  139. /* paranoid version of realloc */
  140.  
  141. char *
  142. saferealloc(where,size)
  143. char *where;
  144. #ifndef MSDOS
  145. MEM_SIZE size;
  146. #else
  147. unsigned long size;
  148. #endif /* MSDOS */
  149. {
  150.     char *ptr;
  151. #ifndef STANDARD_C
  152.     char *realloc();
  153. #endif /* ! STANDARD_C */
  154.  
  155. #ifdef MSDOS
  156.     if (size > 0xffff) {
  157.         fprintf(stderr, "Reallocation too large: %lx\n", size) FLUSH;
  158.         exit(1);
  159.     }
  160. #endif /* MSDOS */
  161.     if (!where)
  162.     fatal("Null realloc");
  163. #ifdef DEBUGGING
  164.     if ((long)size < 0)
  165.     fatal("panic: realloc");
  166. #endif
  167.     ptr = realloc(where,size?size:1);    /* realloc(0) is NASTY on our system */
  168. #ifdef DEBUGGING
  169. #  if !(defined(I286) || defined(atarist))
  170.     if (debug & 128) {
  171.     fprintf(stderr,"0x%x: (%05d) rfree\n",where,an++);
  172.     fprintf(stderr,"0x%x: (%05d) realloc %ld bytes\n",ptr,an++,(long)size);
  173.     }
  174. #  else
  175.     if (debug & 128) {
  176.     fprintf(stderr,"0x%lx: (%05d) rfree\n",where,an++);
  177.     fprintf(stderr,"0x%lx: (%05d) realloc %ld bytes\n",ptr,an++,(long)size);
  178.     }
  179. #  endif
  180. #endif
  181.     if (ptr != Nullch)
  182.     return ptr;
  183.     else if (nomemok)
  184.     return Nullch;
  185.     else {
  186.     fputs("saferealloc failed.\n", stderr);
  187.     fputs(nomem,stderr) FLUSH;
  188.     exit(1);
  189.     }
  190.     /*NOTREACHED*/
  191. #ifdef lint
  192.     return ptr;
  193. #endif
  194. }
  195.  
  196. /* safe version of free */
  197.  
  198. void
  199. safefree(where)
  200. char *where;
  201. {
  202. #ifdef DEBUGGING
  203. #  if !(defined(I286) || defined(atarist))
  204.     if (debug & 128)
  205.     fprintf(stderr,"0x%x: (%05d) free\n",where,an++);
  206. #  else
  207.     if (debug & 128)
  208.     fprintf(stderr,"0x%lx: (%05d) free\n",where,an++);
  209. #  endif
  210. #endif
  211.     if (where) {
  212.     /*SUPPRESS 701*/
  213.     free(where);
  214.     }
  215. }
  216.  
  217. #endif /* !safemalloc */
  218.  
  219. #ifdef LEAKTEST
  220.  
  221. #define ALIGN sizeof(long)
  222.  
  223. char *
  224. safexmalloc(x,size)
  225. int x;
  226. MEM_SIZE size;
  227. {
  228.     register char *where;
  229.  
  230.     where = safemalloc(size + ALIGN);
  231.     xcount[x]++;
  232.     where[0] = x % 100;
  233.     where[1] = x / 100;
  234.     return where + ALIGN;
  235. }
  236.  
  237. char *
  238. safexrealloc(where,size)
  239. char *where;
  240. MEM_SIZE size;
  241. {
  242.     return saferealloc(where - ALIGN, size + ALIGN) + ALIGN;
  243. }
  244.  
  245. void
  246. safexfree(where)
  247. char *where;
  248. {
  249.     int x;
  250.  
  251.     if (!where)
  252.     return;
  253.     where -= ALIGN;
  254.     x = where[0] + 100 * where[1];
  255.     xcount[x]--;
  256.     safefree(where);
  257. }
  258.  
  259. static void
  260. xstat()
  261. {
  262.     register int i;
  263.  
  264.     for (i = 0; i < MAXXCOUNT; i++) {
  265.     if (xcount[i] > lastxcount[i]) {
  266.         fprintf(stderr,"%2d %2d\t%ld\n", i / 100, i % 100, xcount[i]);
  267.         lastxcount[i] = xcount[i];
  268.     }
  269.     }
  270. }
  271.  
  272. #endif /* LEAKTEST */
  273.  
  274. /* copy a string up to some (non-backslashed) delimiter, if any */
  275.  
  276. char *
  277. cpytill(to,from,fromend,delim,retlen)
  278. register char *to;
  279. register char *from;
  280. register char *fromend;
  281. register int delim;
  282. int *retlen;
  283. {
  284.     char *origto = to;
  285.  
  286.     for (; from < fromend; from++,to++) {
  287.     if (*from == '\\') {
  288.         if (from[1] == delim)
  289.         from++;
  290.         else if (from[1] == '\\')
  291.         *to++ = *from++;
  292.     }
  293.     else if (*from == delim)
  294.         break;
  295.     *to = *from;
  296.     }
  297.     *to = '\0';
  298.     *retlen = to - origto;
  299.     return from;
  300. }
  301.  
  302. /* return ptr to little string in big string, NULL if not found */
  303. /* This routine was donated by Corey Satten. */
  304.  
  305. char *
  306. instr(big, little)
  307. register char *big;
  308. register char *little;
  309. {
  310.     register char *s, *x;
  311.     register int first;
  312.  
  313.     if (!little)
  314.     return big;
  315.     first = *little++;
  316.     if (!first)
  317.     return big;
  318.     while (*big) {
  319.     if (*big++ != first)
  320.         continue;
  321.     for (x=big,s=little; *s; /**/ ) {
  322.         if (!*x)
  323.         return Nullch;
  324.         if (*s++ != *x++) {
  325.         s--;
  326.         break;
  327.         }
  328.     }
  329.     if (!*s)
  330.         return big-1;
  331.     }
  332.     return Nullch;
  333. }
  334.  
  335. /* same as instr but allow embedded nulls */
  336.  
  337. char *
  338. ninstr(big, bigend, little, lend)
  339. register char *big;
  340. register char *bigend;
  341. char *little;
  342. char *lend;
  343. {
  344.     register char *s, *x;
  345.     register int first = *little;
  346.     register char *littleend = lend;
  347.  
  348.     if (!first && little > littleend)
  349.     return big;
  350.     if (bigend - big < littleend - little)
  351.     return Nullch;
  352.     bigend -= littleend - little++;
  353.     while (big <= bigend) {
  354.     if (*big++ != first)
  355.         continue;
  356.     for (x=big,s=little; s < littleend; /**/ ) {
  357.         if (*s++ != *x++) {
  358.         s--;
  359.         break;
  360.         }
  361.     }
  362.     if (s >= littleend)
  363.         return big-1;
  364.     }
  365.     return Nullch;
  366. }
  367.  
  368. /* reverse of the above--find last substring */
  369.  
  370. char *
  371. rninstr(big, bigend, little, lend)
  372. register char *big;
  373. char *bigend;
  374. char *little;
  375. char *lend;
  376. {
  377.     register char *bigbeg;
  378.     register char *s, *x;
  379.     register int first = *little;
  380.     register char *littleend = lend;
  381.  
  382.     if (!first && little > littleend)
  383.     return bigend;
  384.     bigbeg = big;
  385.     big = bigend - (littleend - little++);
  386.     while (big >= bigbeg) {
  387.     if (*big-- != first)
  388.         continue;
  389.     for (x=big+2,s=little; s < littleend; /**/ ) {
  390.         if (*s++ != *x++) {
  391.         s--;
  392.         break;
  393.         }
  394.     }
  395.     if (s >= littleend)
  396.         return big+1;
  397.     }
  398.     return Nullch;
  399. }
  400.  
  401. unsigned char fold[] = {
  402.     0,    1,    2,    3,    4,    5,    6,    7,
  403.     8,    9,    10,    11,    12,    13,    14,    15,
  404.     16,    17,    18,    19,    20,    21,    22,    23,
  405.     24,    25,    26,    27,    28,    29,    30,    31,
  406.     32,    33,    34,    35,    36,    37,    38,    39,
  407.     40,    41,    42,    43,    44,    45,    46,    47,
  408.     48,    49,    50,    51,    52,    53,    54,    55,
  409.     56,    57,    58,    59,    60,    61,    62,    63,
  410.     64,    'a',    'b',    'c',    'd',    'e',    'f',    'g',
  411.     'h',    'i',    'j',    'k',    'l',    'm',    'n',    'o',
  412.     'p',    'q',    'r',    's',    't',    'u',    'v',    'w',
  413.     'x',    'y',    'z',    91,    92,    93,    94,    95,
  414.     96,    'A',    'B',    'C',    'D',    'E',    'F',    'G',
  415.     'H',    'I',    'J',    'K',    'L',    'M',    'N',    'O',
  416.     'P',    'Q',    'R',    'S',    'T',    'U',    'V',    'W',
  417.     'X',    'Y',    'Z',    123,    124,    125,    126,    127,
  418.     128,    129,    130,    131,    132,    133,    134,    135,
  419.     136,    137,    138,    139,    140,    141,    142,    143,
  420.     144,    145,    146,    147,    148,    149,    150,    151,
  421.     152,    153,    154,    155,    156,    157,    158,    159,
  422.     160,    161,    162,    163,    164,    165,    166,    167,
  423.     168,    169,    170,    171,    172,    173,    174,    175,
  424.     176,    177,    178,    179,    180,    181,    182,    183,
  425.     184,    185,    186,    187,    188,    189,    190,    191,
  426.     192,    193,    194,    195,    196,    197,    198,    199,
  427.     200,    201,    202,    203,    204,    205,    206,    207,
  428.     208,    209,    210,    211,    212,    213,    214,    215,
  429.     216,    217,    218,    219,    220,    221,    222,    223,    
  430.     224,    225,    226,    227,    228,    229,    230,    231,
  431.     232,    233,    234,    235,    236,    237,    238,    239,
  432.     240,    241,    242,    243,    244,    245,    246,    247,
  433.     248,    249,    250,    251,    252,    253,    254,    255
  434. };
  435.  
  436. static unsigned char freq[] = {
  437.     1,    2,    84,    151,    154,    155,    156,    157,
  438.     165,    246,    250,    3,    158,    7,    18,    29,
  439.     40,    51,    62,    73,    85,    96,    107,    118,
  440.     129,    140,    147,    148,    149,    150,    152,    153,
  441.     255,    182,    224,    205,    174,    176,    180,    217,
  442.     233,    232,    236,    187,    235,    228,    234,    226,
  443.     222,    219,    211,    195,    188,    193,    185,    184,
  444.     191,    183,    201,    229,    181,    220,    194,    162,
  445.     163,    208,    186,    202,    200,    218,    198,    179,
  446.     178,    214,    166,    170,    207,    199,    209,    206,
  447.     204,    160,    212,    216,    215,    192,    175,    173,
  448.     243,    172,    161,    190,    203,    189,    164,    230,
  449.     167,    248,    227,    244,    242,    255,    241,    231,
  450.     240,    253,    169,    210,    245,    237,    249,    247,
  451.     239,    168,    252,    251,    254,    238,    223,    221,
  452.     213,    225,    177,    197,    171,    196,    159,    4,
  453.     5,    6,    8,    9,    10,    11,    12,    13,
  454.     14,    15,    16,    17,    19,    20,    21,    22,
  455.     23,    24,    25,    26,    27,    28,    30,    31,
  456.     32,    33,    34,    35,    36,    37,    38,    39,
  457.     41,    42,    43,    44,    45,    46,    47,    48,
  458.     49,    50,    52,    53,    54,    55,    56,    57,
  459.     58,    59,    60,    61,    63,    64,    65,    66,
  460.     67,    68,    69,    70,    71,    72,    74,    75,
  461.     76,    77,    78,    79,    80,    81,    82,    83,
  462.     86,    87,    88,    89,    90,    91,    92,    93,
  463.     94,    95,    97,    98,    99,    100,    101,    102,
  464.     103,    104,    105,    106,    108,    109,    110,    111,
  465.     112,    113,    114,    115,    116,    117,    119,    120,
  466.     121,    122,    123,    124,    125,    126,    127,    128,
  467.     130,    131,    132,    133,    134,    135,    136,    137,
  468.     138,    139,    141,    142,    143,    144,    145,    146
  469. };
  470.  
  471. void
  472. fbmcompile(str, iflag)
  473. STR *str;
  474. int iflag;
  475. {
  476.     register unsigned char *s;
  477.     register unsigned char *table;
  478.     register unsigned int i;
  479.     register unsigned int len = str->str_cur;
  480.     int rarest = 0;
  481.     unsigned int frequency = 256;
  482.  
  483.     Str_Grow(str,len+258);
  484. #ifndef lint
  485.     table = (unsigned char*)(str->str_ptr + len + 1);
  486. #else
  487.     table = Null(unsigned char*);
  488. #endif
  489.     s = table - 2;
  490.     for (i = 0; i < 256; i++) {
  491.     table[i] = len;
  492.     }
  493.     i = 0;
  494. #ifndef lint
  495.     while (s >= (unsigned char*)(str->str_ptr))
  496. #endif
  497.     {
  498.     if (table[*s] == len) {
  499. #ifndef pdp11
  500.         if (iflag)
  501.         table[*s] = table[fold[*s]] = i;
  502. #else
  503.         if (iflag) {
  504.         int j;
  505.         j = fold[*s];
  506.         table[j] = i;
  507.         table[*s] = i;
  508.         }
  509. #endif /* pdp11 */
  510.         else
  511.         table[*s] = i;
  512.     }
  513.     s--,i++;
  514.     }
  515.     str->str_pok |= SP_FBM;        /* deep magic */
  516.  
  517. #ifndef lint
  518.     s = (unsigned char*)(str->str_ptr);        /* deeper magic */
  519. #else
  520.     s = Null(unsigned char*);
  521. #endif
  522.     if (iflag) {
  523.     register unsigned int tmp, foldtmp;
  524.     str->str_pok |= SP_CASEFOLD;
  525.     for (i = 0; i < len; i++) {
  526.         tmp=freq[s[i]];
  527.         foldtmp=freq[fold[s[i]]];
  528.         if (tmp < frequency && foldtmp < frequency) {
  529.         rarest = i;
  530.         /* choose most frequent among the two */
  531.         frequency = (tmp > foldtmp) ? tmp : foldtmp;
  532.         }
  533.     }
  534.     }
  535.     else {
  536.     for (i = 0; i < len; i++) {
  537.         if (freq[s[i]] < frequency) {
  538.         rarest = i;
  539.         frequency = freq[s[i]];
  540.         }
  541.     }
  542.     }
  543.     str->str_rare = s[rarest];
  544.     str->str_state = rarest;
  545. #ifdef DEBUGGING
  546.     if (debug & 512)
  547.     fprintf(stderr,"rarest char %c at %d\n",str->str_rare, str->str_state);
  548. #endif
  549. }
  550.  
  551. char *
  552. fbminstr(big, bigend, littlestr)
  553. unsigned char *big;
  554. register unsigned char *bigend;
  555. STR *littlestr;
  556. {
  557.     register unsigned char *s;
  558.     register int tmp;
  559.     register int littlelen;
  560.     register unsigned char *little;
  561.     register unsigned char *table;
  562.     register unsigned char *olds;
  563.     register unsigned char *oldlittle;
  564.  
  565. #ifndef lint
  566.     if (!(littlestr->str_pok & SP_FBM)) {
  567.     if (!littlestr->str_ptr)
  568.         return (char*)big;
  569.     return ninstr((char*)big,(char*)bigend,
  570.         littlestr->str_ptr, littlestr->str_ptr + littlestr->str_cur);
  571.     }
  572. #endif
  573.  
  574.     littlelen = littlestr->str_cur;
  575. #ifndef lint
  576.     if (littlestr->str_pok & SP_TAIL && !multiline) {    /* tail anchored? */
  577.     if (littlelen > bigend - big)
  578.         return Nullch;
  579.     little = (unsigned char*)littlestr->str_ptr;
  580.     if (littlestr->str_pok & SP_CASEFOLD) {    /* oops, fake it */
  581.         big = bigend - littlelen;        /* just start near end */
  582.         if (bigend[-1] == '\n' && little[littlelen-1] != '\n')
  583.         big--;
  584.     }
  585.     else {
  586.         s = bigend - littlelen;
  587.         if (*s == *little && bcmp(s,little,littlelen)==0)
  588.         return (char*)s;        /* how sweet it is */
  589.         else if (bigend[-1] == '\n' && little[littlelen-1] != '\n'
  590.           && s > big) {
  591.             s--;
  592.         if (*s == *little && bcmp(s,little,littlelen)==0)
  593.             return (char*)s;
  594.         }
  595.         return Nullch;
  596.     }
  597.     }
  598.     table = (unsigned char*)(littlestr->str_ptr + littlelen + 1);
  599. #else
  600.     table = Null(unsigned char*);
  601. #endif
  602.     if (--littlelen >= bigend - big)
  603.     return Nullch;
  604.     s = big + littlelen;
  605.     oldlittle = little = table - 2;
  606.     if (littlestr->str_pok & SP_CASEFOLD) {    /* case insensitive? */
  607.     if (s < bigend) {
  608.       top1:
  609.         /*SUPPRESS 560*/
  610.         if (tmp = table[*s]) {
  611. #ifdef POINTERRIGOR
  612.         if (bigend - s > tmp) {
  613.             s += tmp;
  614.             goto top1;
  615.         }
  616. #else
  617.         if ((s += tmp) < bigend)
  618.             goto top1;
  619. #endif
  620.         return Nullch;
  621.         }
  622.         else {
  623.         tmp = littlelen;    /* less expensive than calling strncmp() */
  624.         olds = s;
  625.         while (tmp--) {
  626.             if (*--s == *--little || fold[*s] == *little)
  627.             continue;
  628.             s = olds + 1;    /* here we pay the price for failure */
  629.             little = oldlittle;
  630.             if (s < bigend)    /* fake up continue to outer loop */
  631.             goto top1;
  632.             return Nullch;
  633.         }
  634. #ifndef lint
  635.         return (char *)s;
  636. #endif
  637.         }
  638.     }
  639.     }
  640.     else {
  641.     if (s < bigend) {
  642.       top2:
  643.         /*SUPPRESS 560*/
  644.         if (tmp = table[*s]) {
  645. #ifdef POINTERRIGOR
  646.         if (bigend - s > tmp) {
  647.             s += tmp;
  648.             goto top2;
  649.         }
  650. #else
  651.         if ((s += tmp) < bigend)
  652.             goto top2;
  653. #endif
  654.         return Nullch;
  655.         }
  656.         else {
  657.         tmp = littlelen;    /* less expensive than calling strncmp() */
  658.         olds = s;
  659.         while (tmp--) {
  660.             if (*--s == *--little)
  661.             continue;
  662.             s = olds + 1;    /* here we pay the price for failure */
  663.             little = oldlittle;
  664.             if (s < bigend)    /* fake up continue to outer loop */
  665.             goto top2;
  666.             return Nullch;
  667.         }
  668. #ifndef lint
  669.         return (char *)s;
  670. #endif
  671.         }
  672.     }
  673.     }
  674.     return Nullch;
  675. }
  676.  
  677. char *
  678. screaminstr(bigstr, littlestr)
  679. STR *bigstr;
  680. STR *littlestr;
  681. {
  682.     register unsigned char *s, *x;
  683.     register unsigned char *big;
  684.     register int pos;
  685.     register int previous;
  686.     register int first;
  687.     register unsigned char *little;
  688.     register unsigned char *bigend;
  689.     register unsigned char *littleend;
  690.  
  691.     if ((pos = screamfirst[littlestr->str_rare]) < 0) 
  692.     return Nullch;
  693. #ifndef lint
  694.     little = (unsigned char *)(littlestr->str_ptr);
  695. #else
  696.     little = Null(unsigned char *);
  697. #endif
  698.     littleend = little + littlestr->str_cur;
  699.     first = *little++;
  700.     previous = littlestr->str_state;
  701. #ifndef lint
  702.     big = (unsigned char *)(bigstr->str_ptr);
  703. #else
  704.     big = Null(unsigned char*);
  705. #endif
  706.     bigend = big + bigstr->str_cur;
  707.     while (pos < previous) {
  708. #ifndef lint
  709.     if (!(pos += screamnext[pos]))
  710. #endif
  711.         return Nullch;
  712.     }
  713. #ifdef POINTERRIGOR
  714.     if (littlestr->str_pok & SP_CASEFOLD) {    /* case insignificant? */
  715.     do {
  716.         if (big[pos-previous] != first && big[pos-previous] != fold[first])
  717.         continue;
  718.         for (x=big+pos+1-previous,s=little; s < littleend; /**/ ) {
  719.         if (x >= bigend)
  720.             return Nullch;
  721.         if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
  722.             s--;
  723.             break;
  724.         }
  725.         }
  726.         if (s == littleend)
  727. #ifndef lint
  728.         return (char *)(big+pos-previous);
  729. #else
  730.         return Nullch;
  731. #endif
  732.     } while (
  733. #ifndef lint
  734.         pos += screamnext[pos]    /* does this goof up anywhere? */
  735. #else
  736.         pos += screamnext[0]
  737. #endif
  738.         );
  739.     }
  740.     else {
  741.     do {
  742.         if (big[pos-previous] != first)
  743.         continue;
  744.         for (x=big+pos+1-previous,s=little; s < littleend; /**/ ) {
  745.         if (x >= bigend)
  746.             return Nullch;
  747.         if (*s++ != *x++) {
  748.             s--;
  749.             break;
  750.         }
  751.         }
  752.         if (s == littleend)
  753. #ifndef lint
  754.         return (char *)(big+pos-previous);
  755. #else
  756.         return Nullch;
  757. #endif
  758.     } while (
  759. #ifndef lint
  760.         pos += screamnext[pos]
  761. #else
  762.         pos += screamnext[0]
  763. #endif
  764.         );
  765.     }
  766. #else /* !POINTERRIGOR */
  767.     big -= previous;
  768.     if (littlestr->str_pok & SP_CASEFOLD) {    /* case insignificant? */
  769.     do {
  770.         if (big[pos] != first && big[pos] != fold[first])
  771.         continue;
  772.         for (x=big+pos+1,s=little; s < littleend; /**/ ) {
  773.         if (x >= bigend)
  774.             return Nullch;
  775.         if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
  776.             s--;
  777.             break;
  778.         }
  779.         }
  780.         if (s == littleend)
  781. #ifndef lint
  782.         return (char *)(big+pos);
  783. #else
  784.         return Nullch;
  785. #endif
  786.     } while (
  787. #ifndef lint
  788.         pos += screamnext[pos]    /* does this goof up anywhere? */
  789. #else
  790.         pos += screamnext[0]
  791. #endif
  792.         );
  793.     }
  794.     else {
  795.     do {
  796.         if (big[pos] != first)
  797.         continue;
  798.         for (x=big+pos+1,s=little; s < littleend; /**/ ) {
  799.         if (x >= bigend)
  800.             return Nullch;
  801.         if (*s++ != *x++) {
  802.             s--;
  803.             break;
  804.         }
  805.         }
  806.         if (s == littleend)
  807. #ifndef lint
  808.         return (char *)(big+pos);
  809. #else
  810.         return Nullch;
  811. #endif
  812.     } while (
  813. #ifndef lint
  814.         pos += screamnext[pos]
  815. #else
  816.         pos += screamnext[0]
  817. #endif
  818.         );
  819.     }
  820. #endif /* POINTERRIGOR */
  821.     return Nullch;
  822. }
  823.  
  824. /* copy a string to a safe spot */
  825.  
  826. char *
  827. savestr(str)
  828. char *str;
  829. {
  830.     register char *newaddr;
  831.  
  832.     New(902,newaddr,strlen(str)+1,char);
  833.     (void)strcpy(newaddr,str);
  834.     return newaddr;
  835. }
  836.  
  837. /* same thing but with a known length */
  838.  
  839. char *
  840. nsavestr(str, len)
  841. char *str;
  842. register int len;
  843. {
  844.     register char *newaddr;
  845.  
  846.     New(903,newaddr,len+1,char);
  847.     Copy(str,newaddr,len,char);        /* might not be null terminated */
  848.     newaddr[len] = '\0';        /* is now */
  849.     return newaddr;
  850. }
  851.  
  852. /* grow a static string to at least a certain length */
  853.  
  854. void
  855. growstr(strptr,curlen,newlen)
  856. char **strptr;
  857. int *curlen;
  858. int newlen;
  859. {
  860.     if (newlen > *curlen) {        /* need more room? */
  861.     if (*curlen)
  862.         Renew(*strptr,newlen,char);
  863.     else
  864.         New(905,*strptr,newlen,char);
  865.     *curlen = newlen;
  866.     }
  867. }
  868.  
  869. #ifndef I_VARARGS
  870. /*VARARGS1*/
  871. char *
  872. mess(pat,a1,a2,a3,a4)
  873. char *pat;
  874. long a1, a2, a3, a4;
  875. {
  876.     char *s;
  877.     int usermess = strEQ(pat,"%s");
  878.     STR *tmpstr;
  879.  
  880.     s = buf;
  881.     if (usermess) {
  882.     tmpstr = str_mortal(&str_undef);
  883.     str_set(tmpstr, (char*)a1);
  884.     *s++ = tmpstr->str_ptr[tmpstr->str_cur-1];
  885.     }
  886.     else {
  887.     (void)sprintf(s,pat,a1,a2,a3,a4);
  888.     s += strlen(s);
  889.     }
  890.  
  891.     if (s[-1] != '\n') {
  892.     if (curcmd->c_line) {
  893.         (void)sprintf(s," at %s line %ld",
  894.           stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
  895.         s += strlen(s);
  896.     }
  897.     if (last_in_stab &&
  898.         stab_io(last_in_stab) &&
  899.         stab_io(last_in_stab)->lines ) {
  900.         (void)sprintf(s,", <%s> line %ld",
  901.           last_in_stab == argvstab ? "" : stab_ename(last_in_stab),
  902.           (long)stab_io(last_in_stab)->lines);
  903.         s += strlen(s);
  904.     }
  905.     (void)strcpy(s,".\n");
  906.     if (usermess)
  907.         str_cat(tmpstr,buf+1);
  908.     }
  909.     if (usermess)
  910.     return tmpstr->str_ptr;
  911.     else
  912.     return buf;
  913. }
  914.  
  915. /*VARARGS1*/
  916. void fatal(pat,a1,a2,a3,a4)
  917. char *pat;
  918. long a1, a2, a3, a4;
  919. {
  920.     extern FILE *e_fp;
  921.     extern char *e_tmpname;
  922.     char *tmps;
  923.     char *message;
  924.  
  925.     message = mess(pat,a1,a2,a3,a4);
  926.     if (in_eval) {
  927.     str_set(stab_val(stabent("@",TRUE)),message);
  928.     tmps = "_EVAL_";
  929.     while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
  930.       strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
  931. #ifdef DEBUGGING
  932.         if (debug & 4) {
  933.         deb("(Skipping label #%d %s)\n",loop_ptr,
  934.             loop_stack[loop_ptr].loop_label);
  935.         }
  936. #endif
  937.         loop_ptr--;
  938.     }
  939. #ifdef DEBUGGING
  940.     if (debug & 4) {
  941.         deb("(Found label #%d %s)\n",loop_ptr,
  942.         loop_stack[loop_ptr].loop_label);
  943.     }
  944. #endif
  945.     if (loop_ptr < 0) {
  946.         in_eval = 0;
  947.         fatal("Bad label: %s", tmps);
  948.     }
  949.     longjmp(loop_stack[loop_ptr].loop_env, 1);
  950.     }
  951.     fputs(message,stderr);
  952.     (void)fflush(stderr);
  953.     if (e_fp)
  954.     (void)UNLINK(e_tmpname);
  955.     statusvalue >>= 8;
  956.     exit((int)((errno&255)?errno:((statusvalue&255)?statusvalue:255)));
  957. }
  958.  
  959. /*VARARGS1*/
  960. void warn(pat,a1,a2,a3,a4)
  961. char *pat;
  962. long a1, a2, a3, a4;
  963. {
  964.     char *message;
  965.  
  966.     message = mess(pat,a1,a2,a3,a4);
  967.     fputs(message,stderr);
  968. #ifdef LEAKTEST
  969. #ifdef DEBUGGING
  970.     if (debug & 4096)
  971.     xstat();
  972. #endif
  973. #endif
  974.     (void)fflush(stderr);
  975. }
  976. #else
  977. /*VARARGS0*/
  978. char *
  979. mess(args)
  980. va_list args;
  981. {
  982.     char *pat;
  983.     char *s;
  984.     STR *tmpstr;
  985.     int usermess;
  986. #ifndef HAS_VPRINTF
  987. #ifdef CHARVSPRINTF
  988.     char *vsprintf();
  989. #else
  990.     int vsprintf();
  991. #endif
  992. #endif
  993.  
  994. #ifdef lint
  995.     pat = Nullch;
  996. #else
  997.     pat = va_arg(args, char *);
  998. #endif
  999.     s = buf;
  1000.     usermess = strEQ(pat, "%s");
  1001.     if (usermess) {
  1002.     tmpstr = str_mortal(&str_undef);
  1003.     str_set(tmpstr, va_arg(args, char *));
  1004.     *s++ = tmpstr->str_ptr[tmpstr->str_cur-1];
  1005.     }
  1006.     else {
  1007.     (void) vsprintf(s,pat,args);
  1008.     s += strlen(s);
  1009.     }
  1010.  
  1011.     if (s[-1] != '\n') {
  1012.     if (curcmd->c_line) {
  1013.         (void)sprintf(s," at %s line %ld",
  1014.           stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
  1015.         s += strlen(s);
  1016.     }
  1017.     if (last_in_stab &&
  1018.         stab_io(last_in_stab) &&
  1019.         stab_io(last_in_stab)->lines ) {
  1020.         (void)sprintf(s,", <%s> line %ld",
  1021.           last_in_stab == argvstab ? "" : last_in_stab->str_magic->str_ptr,
  1022.           (long)stab_io(last_in_stab)->lines);
  1023.         s += strlen(s);
  1024.     }
  1025.     (void)strcpy(s,".\n");
  1026.     if (usermess)
  1027.         str_cat(tmpstr,buf+1);
  1028.     }
  1029.  
  1030.     if (usermess)
  1031.     return tmpstr->str_ptr;
  1032.     else
  1033.     return buf;
  1034. }
  1035.  
  1036. /*VARARGS0*/
  1037. void fatal(va_alist)
  1038. va_dcl
  1039. {
  1040.     va_list args;
  1041.     extern FILE *e_fp;
  1042.     extern char *e_tmpname;
  1043.     char *tmps;
  1044.     char *message;
  1045.  
  1046. #ifndef lint
  1047.     va_start(args);
  1048. #else
  1049.     args = 0;
  1050. #endif
  1051.     message = mess(args);
  1052.     va_end(args);
  1053.     if (in_eval) {
  1054.     str_set(stab_val(stabent("@",TRUE)),message);
  1055.     tmps = "_EVAL_";
  1056.     while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
  1057.       strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
  1058. #ifdef DEBUGGING
  1059.         if (debug & 4) {
  1060.         deb("(Skipping label #%d %s)\n",loop_ptr,
  1061.             loop_stack[loop_ptr].loop_label);
  1062.         }
  1063. #endif
  1064.         loop_ptr--;
  1065.     }
  1066. #ifdef DEBUGGING
  1067.     if (debug & 4) {
  1068.         deb("(Found label #%d %s)\n",loop_ptr,
  1069.         loop_stack[loop_ptr].loop_label);
  1070.     }
  1071. #endif
  1072.     if (loop_ptr < 0) {
  1073.         in_eval = 0;
  1074.         fatal("Bad label: %s", tmps);
  1075.     }
  1076.     longjmp(loop_stack[loop_ptr].loop_env, 1);
  1077.     }
  1078.     fputs(message,stderr);
  1079.     (void)fflush(stderr);
  1080.     if (e_fp)
  1081.     (void)UNLINK(e_tmpname);
  1082.     statusvalue >>= 8;
  1083.     exit((int)((errno&255)?errno:((statusvalue&255)?statusvalue:255)));
  1084. }
  1085.  
  1086. /*VARARGS0*/
  1087. void warn(va_alist)
  1088. va_dcl
  1089. {
  1090.     va_list args;
  1091.     char *message;
  1092.  
  1093. #ifndef lint
  1094.     va_start(args);
  1095. #else
  1096.     args = 0;
  1097. #endif
  1098.     message = mess(args);
  1099.     va_end(args);
  1100.  
  1101.     fputs(message,stderr);
  1102. #ifdef LEAKTEST
  1103. #ifdef DEBUGGING
  1104.     if (debug & 4096)
  1105.     xstat();
  1106. #endif
  1107. #endif
  1108.     (void)fflush(stderr);
  1109. }
  1110. #endif
  1111.  
  1112. void
  1113. my_setenv(nam,val)
  1114. char *nam, *val;
  1115. {
  1116.     register int i=envix(nam);        /* where does it go? */
  1117.  
  1118.     if (environ == origenviron) {    /* need we copy environment? */
  1119.     int j;
  1120.     int max;
  1121.     char **tmpenv;
  1122.  
  1123.     /*SUPPRESS 530*/
  1124.     for (max = i; environ[max]; max++) ;
  1125.     New(901,tmpenv, max+2, char*);
  1126.     for (j=0; j<max; j++)        /* copy environment */
  1127.         tmpenv[j] = savestr(environ[j]);
  1128.     tmpenv[max] = Nullch;
  1129.     environ = tmpenv;        /* tell exec where it is now */
  1130.     }
  1131.     if (!val) {
  1132.     while (environ[i]) {
  1133.         environ[i] = environ[i+1];
  1134.         i++;
  1135.     }
  1136.     return;
  1137.     }
  1138.     if (!environ[i]) {            /* does not exist yet */
  1139.     Renew(environ, i+2, char*);    /* just expand it a bit */
  1140.     environ[i+1] = Nullch;    /* make sure it's null terminated */
  1141.     }
  1142.     else
  1143.     Safefree(environ[i]);
  1144.     New(904, environ[i], strlen(nam) + strlen(val) + 2, char);
  1145. #ifndef MSDOS
  1146.     (void)sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
  1147. #else
  1148.     /* MS-DOS requires environment variable names to be in uppercase */
  1149.     /* [Tom Dinger, 27 August 1990: Well, it doesn't _require_ it, but
  1150.      * some utilities and applications may break because they only look
  1151.      * for upper case strings. (Fixed strupr() bug here.)]
  1152.      */
  1153.     strcpy(environ[i],nam); strupr(environ[i]);
  1154.     (void)sprintf(environ[i] + strlen(nam),"=%s",val);
  1155. #endif /* MSDOS */
  1156. }
  1157.  
  1158. int
  1159. envix(nam)
  1160. char *nam;
  1161. {
  1162.     register int i, len = strlen(nam);
  1163.  
  1164.     for (i = 0; environ[i]; i++) {
  1165.     if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
  1166.         break;            /* strnEQ must come first to avoid */
  1167.     }                    /* potential SEGV's */
  1168.     return i;
  1169. }
  1170.  
  1171. #ifdef EUNICE
  1172. int
  1173. unlnk(f)    /* unlink all versions of a file */
  1174. char *f;
  1175. {
  1176.     int i;
  1177.  
  1178.     for (i = 0; unlink(f) >= 0; i++) ;
  1179.     return i ? 0 : -1;
  1180. }
  1181. #endif
  1182.  
  1183. #if !defined(HAS_BCOPY) || !defined(SAFE_BCOPY)
  1184. char *
  1185. my_bcopy(from,to,len)
  1186. register char *from;
  1187. register char *to;
  1188. register int len;
  1189. {
  1190.     char *retval = to;
  1191.  
  1192.     if (from - to >= 0) {
  1193.     while (len--)
  1194.         *to++ = *from++;
  1195.     }
  1196.     else {
  1197.     to += len;
  1198.     from += len;
  1199.     while (len--)
  1200.         *(--to) = *(--from);
  1201.     }
  1202.     return retval;
  1203. }
  1204. #endif
  1205.  
  1206. #if !defined(HAS_BZERO) && !defined(HAS_MEMSET)
  1207. char *
  1208. my_bzero(loc,len)
  1209. register char *loc;
  1210. register int len;
  1211. {
  1212.     char *retval = loc;
  1213.  
  1214.     while (len--)
  1215.     *loc++ = 0;
  1216.     return retval;
  1217. }
  1218. #endif
  1219.  
  1220. #ifndef HAS_MEMCMP
  1221. int
  1222. my_memcmp(s1,s2,len)
  1223. register unsigned char *s1;
  1224. register unsigned char *s2;
  1225. register int len;
  1226. {
  1227.     register int tmp;
  1228.  
  1229.     while (len--) {
  1230.     if (tmp = *s1++ - *s2++)
  1231.         return tmp;
  1232.     }
  1233.     return 0;
  1234. }
  1235. #endif /* HAS_MEMCMP */
  1236.  
  1237. #ifdef I_VARARGS
  1238. #ifndef HAS_VPRINTF
  1239.  
  1240. #ifdef CHARVSPRINTF
  1241. char *
  1242. #else
  1243. int
  1244. #endif
  1245. vsprintf(dest, pat, args)
  1246. char *dest, *pat, *args;
  1247. {
  1248.     FILE fakebuf;
  1249.  
  1250.     fakebuf._ptr = dest;
  1251.     fakebuf._cnt = 32767;
  1252. #ifndef _IOSTRG
  1253. #define _IOSTRG 0
  1254. #endif
  1255.     fakebuf._flag = _IOWRT|_IOSTRG;
  1256.     _doprnt(pat, args, &fakebuf);    /* what a kludge */
  1257.     (void)putc('\0', &fakebuf);
  1258. #ifdef CHARVSPRINTF
  1259.     return(dest);
  1260. #else
  1261.     return 0;        /* perl doesn't use return value */
  1262. #endif
  1263. }
  1264.  
  1265. #ifdef DEBUGGING
  1266. int
  1267. vfprintf(fd, pat, args)
  1268. FILE *fd;
  1269. char *pat, *args;
  1270. {
  1271.     _doprnt(pat, args, fd);
  1272.     return 0;        /* wrong, but perl doesn't use the return value */
  1273. }
  1274. #endif
  1275. #endif /* HAS_VPRINTF */
  1276. #endif /* I_VARARGS */
  1277.  
  1278. /*
  1279.  * I think my_swap(), htonl() and ntohl() have never been used.
  1280.  * perl.h contains last-chance references to my_swap(), my_htonl()
  1281.  * and my_ntohl().  I presume these are the intended functions;
  1282.  * but htonl() and ntohl() have the wrong names.  There are no
  1283.  * functions my_htonl() and my_ntohl() defined anywhere.
  1284.  * -DWS
  1285.  */
  1286. #ifdef MYSWAP
  1287. #if BYTEORDER != 0x4321
  1288. short
  1289. my_swap(s)
  1290. short s;
  1291. {
  1292. #if (BYTEORDER & 1) == 0
  1293.     short result;
  1294.  
  1295.     result = ((s & 255) << 8) + ((s >> 8) & 255);
  1296.     return result;
  1297. #else
  1298.     return s;
  1299. #endif
  1300. }
  1301.  
  1302. long
  1303. htonl(l)
  1304. register long l;
  1305. {
  1306.     union {
  1307.     long result;
  1308.     char c[sizeof(long)];
  1309.     } u;
  1310.  
  1311. #if BYTEORDER == 0x1234
  1312.     u.c[0] = (l >> 24) & 255;
  1313.     u.c[1] = (l >> 16) & 255;
  1314.     u.c[2] = (l >> 8) & 255;
  1315.     u.c[3] = l & 255;
  1316.     return u.result;
  1317. #else
  1318. #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
  1319.     fatal("Unknown BYTEORDER\n");
  1320. #else
  1321.     register int o;
  1322.     register int s;
  1323.  
  1324.     for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
  1325.     u.c[o & 0xf] = (l >> s) & 255;
  1326.     }
  1327.     return u.result;
  1328. #endif
  1329. #endif
  1330. }
  1331.  
  1332. long
  1333. ntohl(l)
  1334. register long l;
  1335. {
  1336.     union {
  1337.     long l;
  1338.     char c[sizeof(long)];
  1339.     } u;
  1340.  
  1341. #if BYTEORDER == 0x1234
  1342.     u.c[0] = (l >> 24) & 255;
  1343.     u.c[1] = (l >> 16) & 255;
  1344.     u.c[2] = (l >> 8) & 255;
  1345.     u.c[3] = l & 255;
  1346.     return u.l;
  1347. #else
  1348. #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
  1349.     fatal("Unknown BYTEORDER\n");
  1350. #else
  1351.     register int o;
  1352.     register int s;
  1353.  
  1354.     u.l = l;
  1355.     l = 0;
  1356.     for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
  1357.     l |= (u.c[o & 0xf] & 255) << s;
  1358.     }
  1359.     return l;
  1360. #endif
  1361. #endif
  1362. }
  1363.  
  1364. #endif /* BYTEORDER != 0x4321 */
  1365. #endif /* MYSWAP */
  1366.  
  1367. /*
  1368.  * Little-endian byte order functions - 'v' for 'VAX', or 'reVerse'.
  1369.  * If these functions are defined,
  1370.  * the BYTEORDER is neither 0x1234 nor 0x4321.
  1371.  * However, this is not assumed.
  1372.  * -DWS
  1373.  */
  1374.  
  1375. #define HTOV(name,type)                        \
  1376.     type                            \
  1377.     name (n)                        \
  1378.     register type n;                    \
  1379.     {                            \
  1380.         union {                        \
  1381.         type value;                    \
  1382.         char c[sizeof(type)];                \
  1383.         } u;                        \
  1384.         register int i;                    \
  1385.         register int s;                    \
  1386.         for (i = 0, s = 0; i < sizeof(u.c); i++, s += 8) {    \
  1387.         u.c[i] = (n >> s) & 0xFF;            \
  1388.         }                            \
  1389.         return u.value;                    \
  1390.     }
  1391.  
  1392. #define VTOH(name,type)                        \
  1393.     type                            \
  1394.     name (n)                        \
  1395.     register type n;                    \
  1396.     {                            \
  1397.         union {                        \
  1398.         type value;                    \
  1399.         char c[sizeof(type)];                \
  1400.         } u;                        \
  1401.         register int i;                    \
  1402.         register int s;                    \
  1403.         u.value = n;                    \
  1404.         n = 0;                        \
  1405.         for (i = 0, s = 0; i < sizeof(u.c); i++, s += 8) {    \
  1406.         n += (u.c[i] & 0xFF) << s;            \
  1407.         }                            \
  1408.         return n;                        \
  1409.     }
  1410.  
  1411. #if defined(HAS_HTOVS) && !defined(htovs)
  1412. HTOV(htovs,short)
  1413. #endif
  1414. #if defined(HAS_HTOVL) && !defined(htovl)
  1415. HTOV(htovl,long)
  1416. #endif
  1417. #if defined(HAS_VTOHS) && !defined(vtohs)
  1418. VTOH(vtohs,short)
  1419. #endif
  1420. #if defined(HAS_VTOHL) && !defined(vtohl)
  1421. VTOH(vtohl,long)
  1422. #endif
  1423.  
  1424. #if !defined(DOSISH) && !defined(DEFPOPEN)
  1425. FILE *
  1426. mypopen(cmd,mode)
  1427. char    *cmd;
  1428. char    *mode;
  1429. {
  1430.     int p[2];
  1431.     register int this, that;
  1432.     register int pid;
  1433.     STR *str;
  1434.     int doexec = strNE(cmd,"-");
  1435.  
  1436.     if (pipe(p) < 0)
  1437.     return Nullfp;
  1438.     this = (*mode == 'w');
  1439.     that = !this;
  1440. #ifdef TAINT
  1441.     if (doexec) {
  1442.     taintenv();
  1443.     taintproper("Insecure dependency in exec");
  1444.     }
  1445. #endif
  1446. #ifdef HAS_FORK
  1447.     while ((pid = (doexec?vfork():fork())) < 0) {
  1448. #else
  1449.     while ((pid = (doexec?vfork():vfork())) < 0) {
  1450. #endif
  1451.     if (errno != EAGAIN) {
  1452.         close(p[this]);
  1453.         if (!doexec)
  1454.         fatal("Can't fork");
  1455.         return Nullfp;
  1456.     }
  1457.     sleep(5);
  1458.     }
  1459.     if (pid == 0) {
  1460. #define THIS that
  1461. #define THAT this
  1462.     close(p[THAT]);
  1463.     if (p[THIS] != (*mode == 'r')) {
  1464.         dup2(p[THIS], *mode == 'r');
  1465.         close(p[THIS]);
  1466.     }
  1467.     if (doexec) {
  1468. #if !defined(HAS_FCNTL) || !defined(F_SETFD)
  1469.         int fd;
  1470.  
  1471. #ifndef NOFILE
  1472. #define NOFILE 20
  1473. #endif
  1474.         for (fd = maxsysfd + 1; fd < NOFILE; fd++)
  1475.         close(fd);
  1476. #endif
  1477.         do_exec(cmd);    /* may or may not use the shell */
  1478.         /* warn("Can't exec \"%s\": %s", cmd, strerror(errno));
  1479.         _exit(1); */
  1480.     }
  1481.     /*SUPPRESS 560*/
  1482.     if (tmpstab = stabent("$",allstabs))
  1483.         str_numset(STAB_STR(tmpstab),(double)getpid());
  1484.     forkprocess = 0;
  1485.     hclear(pidstatus, FALSE);    /* we have no children */
  1486.     return Nullfp;
  1487. #undef THIS
  1488. #undef THAT
  1489.     }
  1490.     do_execfree(); /* free any memory malloced by child on vfork */
  1491.     close(p[that]);
  1492.     if (p[that] < p[this]) {
  1493.     dup2(p[this], p[that]);
  1494.     close(p[this]);
  1495.     p[this] = p[that];
  1496.     }
  1497.     if(debug&16384) fprintf(stderr, "afetching: key = %d\n", p[this]);
  1498.  
  1499. #ifdef AMIGA
  1500.     str = afetch(fdpid,fileno(p[this]),TRUE);
  1501. #else
  1502.     str = afetch(fdpid,p[this],TRUE);
  1503. #endif
  1504.  
  1505.     str->str_u.str_useful = pid;
  1506.     forkprocess = pid;
  1507.     return fdopen(p[this], mode);
  1508. }
  1509. #else
  1510. #if defined(atarist) || defined(DEFPOPEN)
  1511. FILE *popen();
  1512. FILE *
  1513. mypopen(cmd,mode)
  1514. char    *cmd;
  1515. char    *mode;
  1516. {
  1517.     return popen(cmd, mode);
  1518. }
  1519. #endif
  1520.  
  1521. #endif /* !DOSISH */
  1522.  
  1523. #ifdef NOTDEF
  1524. dumpfds(s)
  1525. char *s;
  1526. {
  1527.     int fd;
  1528.     struct stat tmpstatbuf;
  1529.  
  1530.     fprintf(stderr,"%s", s);
  1531.     for (fd = 0; fd < 32; fd++) {
  1532.     if (fstat(fd,&tmpstatbuf) >= 0)
  1533.         fprintf(stderr," %d",fd);
  1534.     }
  1535.     fprintf(stderr,"\n");
  1536. }
  1537. #endif
  1538.  
  1539. #ifndef HAS_DUP2
  1540. dup2(oldfd,newfd)
  1541. int oldfd;
  1542. int newfd;
  1543. {
  1544. #if defined(HAS_FCNTL) && defined(F_DUPFD)
  1545.     close(newfd);
  1546.     fcntl(oldfd, F_DUPFD, newfd);
  1547. #else
  1548.     int fdtmp[256];
  1549.     int fdx = 0;
  1550.     int fd;
  1551.  
  1552.     if (oldfd == newfd)
  1553.     return 0;
  1554.     close(newfd);
  1555.     while ((fd = dup(oldfd)) != newfd)    /* good enough for low fd's */
  1556.     fdtmp[fdx++] = fd;
  1557.     while (fdx > 0)
  1558.     close(fdtmp[--fdx]);
  1559. #endif
  1560. }
  1561. #endif
  1562.  
  1563. #if !defined(DOSISH) && !defined(DEFPOPEN)
  1564. int
  1565. mypclose(ptr)
  1566. FILE *ptr;
  1567. {
  1568. #ifdef VOIDSIG
  1569.     void (*hstat)(), (*istat)(), (*qstat)();
  1570. #else
  1571.     int (*hstat)(), (*istat)(), (*qstat)();
  1572. #endif
  1573.     int status;
  1574.     STR *str;
  1575.     int pid;
  1576.  
  1577. #ifdef AMIGA
  1578.     str = afetch(fdpid,fileno(ptr),TRUE);
  1579. #else
  1580.     str = afetch(fdpid,fileno(ptr),TRUE);
  1581. #endif
  1582.  
  1583.     pid = (int)str->str_u.str_useful;
  1584.     astore(fdpid,fileno(ptr),Nullstr);
  1585.     fclose(ptr);
  1586. #ifdef UTS
  1587.     if(kill(pid, 0) < 0) { return(pid); }   /* HOM 12/23/91 */
  1588. #endif
  1589.     hstat = signal(SIGHUP, SIG_IGN);
  1590.     istat = signal(SIGINT, SIG_IGN);
  1591.     qstat = signal(SIGQUIT, SIG_IGN);
  1592.     pid = wait4pid(pid, &status, 0);
  1593.     signal(SIGHUP, hstat);
  1594.     signal(SIGINT, istat);
  1595.     signal(SIGQUIT, qstat);
  1596.     return(pid < 0 ? pid : status);
  1597. }
  1598. #endif
  1599.  
  1600. #ifndef DOSISH
  1601. int
  1602. wait4pid(pid,statusp,flags)
  1603. int pid;
  1604. int *statusp;
  1605. int flags;
  1606. {
  1607. #if !defined(HAS_WAIT4) && !defined(HAS_WAITPID)
  1608.     int result;
  1609.     STR *str;
  1610.     char spid[16];
  1611. #endif
  1612.  
  1613.     if (!pid)
  1614.     return -1;
  1615. #ifdef HAS_WAIT4
  1616.     return wait4((pid==-1)?0:pid,statusp,flags,Null(struct rusage *));
  1617. #else
  1618. #ifdef HAS_WAITPID
  1619.     return waitpid(pid,statusp,flags);
  1620. #else
  1621.     if (pid > 0) {
  1622.     sprintf(spid, "%d", pid);
  1623.     str = hfetch(pidstatus,spid,strlen(spid),FALSE);
  1624.     if (str != &str_undef) {
  1625.         *statusp = (int)str->str_u.str_useful;
  1626.         hdelete(pidstatus,spid,strlen(spid));
  1627.         return pid;
  1628.     }
  1629.     }
  1630.     else {
  1631.     HENT *entry;
  1632.  
  1633.     hiterinit(pidstatus);
  1634.     if (entry = hiternext(pidstatus)) {
  1635.         pid = atoi(hiterkey(entry,statusp));
  1636.         str = hiterval(pidstatus,entry);
  1637.         *statusp = (int)str->str_u.str_useful;
  1638.         sprintf(spid, "%d", pid);
  1639.         hdelete(pidstatus,spid,strlen(spid));
  1640.         return pid;
  1641.     }
  1642.     }
  1643.     if (flags)
  1644.     fatal("Can't do waitpid with flags");
  1645.     else {
  1646.     while ((result = wait(statusp)) != pid && pid > 0 && result >= 0)
  1647.         (void)pidgone(result,*statusp);
  1648.     if (result < 0)
  1649.         *statusp = -1;
  1650.     }
  1651.     return result;
  1652. #endif
  1653. #endif
  1654. }
  1655. #endif /* !DOSISH */
  1656.  
  1657. void
  1658. /*SUPPRESS 590*/
  1659. pidgone(pid,status)
  1660. int pid;
  1661. int status;
  1662. {
  1663. #if defined(HAS_WAIT4) || defined(HAS_WAITPID)
  1664. #else
  1665.     register STR *str;
  1666.     char spid[16];
  1667.  
  1668.     sprintf(spid, "%d", pid);
  1669.     str = hfetch(pidstatus,spid,strlen(spid),TRUE);
  1670.     str->str_u.str_useful = status;
  1671. #endif
  1672.     return;
  1673. }
  1674.  
  1675. #if defined(atarist) || defined(DEFPOPEN)
  1676. int pclose();
  1677. int
  1678. mypclose(ptr)
  1679. FILE *ptr;
  1680. {
  1681.     return pclose(ptr);
  1682. }
  1683. #endif
  1684.  
  1685. void
  1686. repeatcpy(to,from,len,count)
  1687. register char *to;
  1688. register char *from;
  1689. int len;
  1690. register int count;
  1691. {
  1692.     register int todo;
  1693.     register char *frombase = from;
  1694.  
  1695.     if (len == 1) {
  1696.     todo = *from;
  1697.     while (count-- > 0)
  1698.         *to++ = todo;
  1699.     return;
  1700.     }
  1701.     while (count-- > 0) {
  1702.     for (todo = len; todo > 0; todo--) {
  1703.         *to++ = *from++;
  1704.     }
  1705.     from = frombase;
  1706.     }
  1707. }
  1708.  
  1709. #ifndef CASTNEGFLOAT
  1710. unsigned long
  1711. castulong(f)
  1712. double f;
  1713. {
  1714.     long along;
  1715.  
  1716. #if CASTFLAGS & 2
  1717. #   define BIGDOUBLE 2147483648.0
  1718.     if (f >= BIGDOUBLE)
  1719.     return (unsigned long)(f-(long)(f/BIGDOUBLE)*BIGDOUBLE)|0x80000000;
  1720. #endif
  1721.     if (f >= 0.0)
  1722.     return (unsigned long)f;
  1723.     along = (long)f;
  1724.     return (unsigned long)along;
  1725. }
  1726. #endif
  1727.  
  1728. #ifndef HAS_RENAME
  1729. int
  1730. same_dirent(a,b)
  1731. char *a;
  1732. char *b;
  1733. {
  1734.     char *fa = rindex(a,'/');
  1735.     char *fb = rindex(b,'/');
  1736.     struct stat tmpstatbuf1;
  1737.     struct stat tmpstatbuf2;
  1738. #ifndef MAXPATHLEN
  1739. #define MAXPATHLEN 1024
  1740. #endif
  1741.     char tmpbuf[MAXPATHLEN+1];
  1742.  
  1743.     if (fa)
  1744.     fa++;
  1745.     else
  1746.     fa = a;
  1747.     if (fb)
  1748.     fb++;
  1749.     else
  1750.     fb = b;
  1751.     if (strNE(a,b))
  1752.     return FALSE;
  1753.     if (fa == a)
  1754.     strcpy(tmpbuf,".");
  1755.     else
  1756.     strncpy(tmpbuf, a, fa - a);
  1757.     if (stat(tmpbuf, &tmpstatbuf1) < 0)
  1758.     return FALSE;
  1759.     if (fb == b)
  1760.     strcpy(tmpbuf,".");
  1761.     else
  1762.     strncpy(tmpbuf, b, fb - b);
  1763.     if (stat(tmpbuf, &tmpstatbuf2) < 0)
  1764.     return FALSE;
  1765.     return tmpstatbuf1.st_dev == tmpstatbuf2.st_dev &&
  1766.        tmpstatbuf1.st_ino == tmpstatbuf2.st_ino;
  1767. }
  1768. #endif /* !HAS_RENAME */
  1769.  
  1770. unsigned long
  1771. scanoct(start, len, retlen)
  1772. char *start;
  1773. int len;
  1774. int *retlen;
  1775. {
  1776.     register char *s = start;
  1777.     register unsigned long retval = 0;
  1778.  
  1779.     while (len-- && *s >= '0' && *s <= '7') {
  1780.     retval <<= 3;
  1781.     retval |= *s++ - '0';
  1782.     }
  1783.     *retlen = s - start;
  1784.     return retval;
  1785. }
  1786.  
  1787. unsigned long
  1788. scanhex(start, len, retlen)
  1789. char *start;
  1790. int len;
  1791. int *retlen;
  1792. {
  1793.     register char *s = start;
  1794.     register unsigned long retval = 0;
  1795.     char *tmp;
  1796.  
  1797.     while (len-- && *s && (tmp = index(hexdigit, *s))) {
  1798.     retval <<= 4;
  1799.     retval |= (tmp - hexdigit) & 15;
  1800.     s++;
  1801.     }
  1802.     *retlen = s - start;
  1803.     return retval;
  1804. }
  1805.  
  1806. #ifdef AMIGA
  1807. int getfdkey(value)
  1808. int value;
  1809. {
  1810.     static int total=0;
  1811.     static int vals[BUFSIZ];
  1812.     int i;
  1813.  
  1814.     for(i=0; i< total; i++) {
  1815.  
  1816. #if defined(AMIGA) && defined(DEBUGGING)
  1817.     if(debug&16384) fprintf(stderr, "fd found at index: %d\n", i);
  1818. #endif
  1819.     if(vals[i] == value) return(i+1);
  1820.     }
  1821.     if((total+1) == BUFSIZ) {
  1822.     fatal("fdkey buffer limit reached - can't open pipe.\n");
  1823.     }
  1824.     vals[total++]=value;
  1825. #if defined(AMIGA) && defined(DEBUGGING)
  1826.     if(debug&16384) fprintf(stderr,"new fd at index: %d\n", i);
  1827. #endif
  1828.     return(total);
  1829. }
  1830. #endif
  1831.  
  1832.