Annotation of coherent/d/usr/bin/pax/public/part06.sh, revision 1.1.1.1

1.1       root        1: # This is a shell archive.  Remove anything before this line, then unpack
                      2: # it by saving it into a file and typing "sh file".  To overwrite existing
                      3: # files, type "sh file -c".  You can also feed this as standard input via
                      4: # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
                      5: # will see the following message at the end:
                      6: #              "End of archive 6 (of 6)."
                      7: # Contents:  regexp.c Makefile
                      8: # Wrapped by mark@jhereg on Tue Dec 27 19:38:04 1988
                      9: PATH=/bin:/usr/bin:/usr/ucb ; export PATH
                     10: if test -f regexp.c -a "${1}" != "-c" ; then 
                     11:   echo shar: Will not over-write existing file \"regexp.c\"
                     12: else
                     13: echo shar: Extracting \"regexp.c\" \(30611 characters\)
                     14: sed "s/^X//" >regexp.c <<'END_OF_regexp.c'
                     15: X/* $Source: /u/mark/src/pax/RCS/regexp.c,v $
                     16: X *
                     17: X * $Revision: 1.1 $
                     18: X *
                     19: X * regexp.c - regular expression matching
                     20: X *
                     21: X * DESCRIPTION
                     22: X *
                     23: X *    Underneath the reformatting and comment blocks which were added to 
                     24: X *    make it consistent with the rest of the code, you will find a
                     25: X *    modified version of Henry Specer's regular expression library.
                     26: X *    Henry's functions were modified to provide the minimal regular
                     27: X *    expression matching, as required by P1003.  Henry's code was
                     28: X *    copyrighted, and copy of the copyright message and restrictions
                     29: X *    are provided, verbatim, below:
                     30: X *
                     31: X *    Copyright (c) 1986 by University of Toronto.
                     32: X *    Written by Henry Spencer.  Not derived from licensed software.
                     33: X *
                     34: X *    Permission is granted to anyone to use this software for any
                     35: X *    purpose on any computer system, and to redistribute it freely,
                     36: X *    subject to the following restrictions:
                     37: X *
                     38: X *    1. The author is not responsible for the consequences of use of
                     39: X *         this software, no matter how awful, even if they arise
                     40: X *       from defects in it.
                     41: X *
                     42: X *    2. The origin of this software must not be misrepresented, either
                     43: X *       by explicit claim or by omission.
                     44: X *
                     45: X *    3. Altered versions must be plainly marked as such, and must not
                     46: X *       be misrepresented as being the original software.
                     47: X *
                     48: X *    Beware that some of this code is subtly aware of the way operator
                     49: X *    precedence is structured in regular expressions.  Serious changes in
                     50: X *    regular-expression syntax might require a total rethink.
                     51: X *
                     52: X * AUTHORS
                     53: X *
                     54: X *     Mark H. Colburn, NAPS International ([email protected])
                     55: X *     Henry Spencer, University of Torronto ([email protected])
                     56: X *
                     57: X * Sponsored by The USENIX Association for public distribution. 
                     58: X *
                     59: X * $Log:      regexp.c,v $
                     60: X * Revision 1.1  88/12/23  18:02:32  mark
                     61: X * Initial revision
                     62: X * 
                     63: X */
                     64: X
                     65: X/* Headers */
                     66: X
                     67: X#include "pax.h"
                     68: X
                     69: X#ifndef lint
                     70: Xstatic char    *Ident = "$Id: regexp.c,v 1.1 88/12/23 18:02:32 mark Rel $";
                     71: X#endif
                     72: X
                     73: X
                     74: X/*
                     75: X * The "internal use only" fields in regexp.h are present to pass info from
                     76: X * compile to execute that permits the execute phase to run lots faster on
                     77: X * simple cases.  They are:
                     78: X *
                     79: X * regstart   char that must begin a match; '\0' if none obvious
                     80: X * reganch    is the match anchored (at beginning-of-line only)?
                     81: X * regmust    string (pointer into program) that match must include, or NULL
                     82: X * regmlen    length of regmust string
                     83: X *
                     84: X * Regstart and reganch permit very fast decisions on suitable starting points
                     85: X * for a match, cutting down the work a lot.  Regmust permits fast rejection
                     86: X * of lines that cannot possibly match.  The regmust tests are costly enough
                     87: X * that regcomp() supplies a regmust only if the r.e. contains something
                     88: X * potentially expensive (at present, the only such thing detected is * or +
                     89: X * at the start of the r.e., which can involve a lot of backup).  Regmlen is
                     90: X * supplied because the test in regexec() needs it and regcomp() is computing
                     91: X * it anyway.
                     92: X */
                     93: X
                     94: X/*
                     95: X * Structure for regexp "program".  This is essentially a linear encoding
                     96: X * of a nondeterministic finite-state machine (aka syntax charts or
                     97: X * "railroad normal form" in parsing technology).  Each node is an opcode
                     98: X * plus a "nxt" pointer, possibly plus an operand.  "Nxt" pointers of
                     99: X * all nodes except BRANCH implement concatenation; a "nxt" pointer with
                    100: X * a BRANCH on both ends of it is connecting two alternatives.  (Here we
                    101: X * have one of the subtle syntax dependencies:  an individual BRANCH (as
                    102: X * opposed to a collection of them) is never concatenated with anything
                    103: X * because of operator precedence.)  The operand of some types of node is
                    104: X * a literal string; for others, it is a node leading into a sub-FSM.  In
                    105: X * particular, the operand of a BRANCH node is the first node of the branch.
                    106: X * (NB this is *not* a tree structure:  the tail of the branch connects
                    107: X * to the thing following the set of BRANCHes.)  The opcodes are:
                    108: X */
                    109: X
                    110: X/* definition number  opnd?   meaning */
                    111: X#define       END     0               /* no   End of program. */
                    112: X#define       BOL     1               /* no   Match "" at beginning of line. */
                    113: X#define       EOL     2               /* no   Match "" at end of line. */
                    114: X#define       ANY     3               /* no   Match any one character. */
                    115: X#define       ANYOF   4               /* str  Match any character in this string. */
                    116: X#define       ANYBUT  5               /* str  Match any character not in this
                    117: X                               * string. */
                    118: X#define       BRANCH  6               /* node Match this alternative, or the
                    119: X                               * nxt... */
                    120: X#define       BACK    7               /* no   Match "", "nxt" ptr points backward. */
                    121: X#define       EXACTLY 8               /* str  Match this string. */
                    122: X#define       NOTHING 9               /* no   Match empty string. */
                    123: X#define       STAR    10              /* node Match this (simple) thing 0 or more
                    124: X                               * times. */
                    125: X#define       OPEN    20              /* no   Mark this point in input as start of
                    126: X                               * #n. */
                    127: X /* OPEN+1 is number 1, etc. */
                    128: X#define       CLOSE   30              /* no   Analogous to OPEN. */
                    129: X
                    130: X/*
                    131: X * Opcode notes:
                    132: X *
                    133: X * BRANCH     The set of branches constituting a single choice are hooked
                    134: X *            together with their "nxt" pointers, since precedence prevents
                    135: X *            anything being concatenated to any individual branch.  The
                    136: X *            "nxt" pointer of the last BRANCH in a choice points to the
                    137: X *            thing following the whole choice.  This is also where the
                    138: X *            final "nxt" pointer of each individual branch points; each
                    139: X *            branch starts with the operand node of a BRANCH node.
                    140: X *
                    141: X * BACK               Normal "nxt" pointers all implicitly point forward; BACK
                    142: X *            exists to make loop structures possible.
                    143: X *
                    144: X * STAR               complex '*', are implemented as circular BRANCH structures 
                    145: X *            using BACK.  Simple cases (one character per match) are 
                    146: X *            implemented with STAR for speed and to minimize recursive 
                    147: X *            plunges.
                    148: X *
                    149: X * OPEN,CLOSE ...are numbered at compile time.
                    150: X */
                    151: X
                    152: X/*
                    153: X * A node is one char of opcode followed by two chars of "nxt" pointer.
                    154: X * "Nxt" pointers are stored as two 8-bit pieces, high order first.  The
                    155: X * value is a positive offset from the opcode of the node containing it.
                    156: X * An operand, if any, simply follows the node.  (Note that much of the
                    157: X * code generation knows about this implicit relationship.)
                    158: X *
                    159: X * Using two bytes for the "nxt" pointer is vast overkill for most things,
                    160: X * but allows patterns to get big without disasters.
                    161: X */
                    162: X#define       OP(p)   (*(p))
                    163: X#define       NEXT(p) (((*((p)+1)&0377) + (*((p)+2)&0377))<<8)
                    164: X#define       OPERAND(p)      ((p) + 3)
                    165: X
                    166: X/*
                    167: X * Utility definitions.
                    168: X */
                    169: X
                    170: X#define       FAIL(m) { regerror(m); return(NULL); }
                    171: X#define       ISMULT(c)       ((c) == '*')
                    172: X#define       META    "^$.[()|*\\"
                    173: X#ifndef CHARBITS
                    174: X#define       UCHARAT(p)      ((int)*(unsigned char *)(p))
                    175: X#else
                    176: X#define       UCHARAT(p)      ((int)*(p)&CHARBITS)
                    177: X#endif
                    178: X
                    179: X/*
                    180: X * Flags to be passed up and down.
                    181: X */
                    182: X#define       HASWIDTH        01      /* Known never to match null string. */
                    183: X#define       SIMPLE          02      /* Simple enough to be STAR operand. */
                    184: X#define       SPSTART         04      /* Starts with * */
                    185: X#define       WORST           0       /* Worst case. */
                    186: X
                    187: X/*
                    188: X * Global work variables for regcomp().
                    189: X */
                    190: Xstatic char    *regparse;     /* Input-scan pointer. */
                    191: Xstatic int      regnpar;      /* () count. */
                    192: Xstatic char     regdummy;
                    193: Xstatic char    *regcode;      /* Code-emit pointer; &regdummy = don't. */
                    194: Xstatic long     regsize;      /* Code size. */
                    195: X
                    196: X/*
                    197: X * Forward declarations for regcomp()'s friends.
                    198: X */
                    199: X#ifndef STATIC
                    200: X#define       STATIC  static
                    201: X#endif
                    202: XSTATIC char    *reg();
                    203: XSTATIC char    *regbranch();
                    204: XSTATIC char    *regpiece();
                    205: XSTATIC char    *regatom();
                    206: XSTATIC char    *regnode();
                    207: XSTATIC char    *regnext();
                    208: XSTATIC void     regc();
                    209: XSTATIC void     reginsert();
                    210: XSTATIC void     regtail();
                    211: XSTATIC void     regoptail();
                    212: X#ifdef STRCSPN
                    213: XSTATIC int      strcspn();
                    214: X#endif
                    215: X
                    216: X/*
                    217: X - regcomp - compile a regular expression into internal code
                    218: X *
                    219: X * We can't allocate space until we know how big the compiled form will be,
                    220: X * but we can't compile it (and thus know how big it is) until we've got a
                    221: X * place to put the code.  So we cheat:  we compile it twice, once with code
                    222: X * generation turned off and size counting turned on, and once "for real".
                    223: X * This also means that we don't allocate space until we are sure that the
                    224: X * thing really will compile successfully, and we never have to move the
                    225: X * code and thus invalidate pointers into it.  (Note that it has to be in
                    226: X * one piece because free() must be able to free it all.)
                    227: X *
                    228: X * Beware that the optimization-preparation code in here knows about some
                    229: X * of the structure of the compiled regexp.
                    230: X */
                    231: Xregexp *regcomp(exp)
                    232: Xchar           *exp;
                    233: X{
                    234: X    register regexp *r;
                    235: X    register char  *scan;
                    236: X    register char  *longest;
                    237: X    register int    len;
                    238: X    int             flags;
                    239: X    extern char    *malloc();
                    240: X
                    241: X    if (exp == NULL)
                    242: X      FAIL("NULL argument");
                    243: X
                    244: X    /* First pass: determine size, legality. */
                    245: X    regparse = exp;
                    246: X    regnpar = 1;
                    247: X    regsize = 0L;
                    248: X    regcode = &regdummy;
                    249: X    regc(MAGIC);
                    250: X    if (reg(0, &flags) == NULL)
                    251: X      return (NULL);
                    252: X
                    253: X    /* Small enough for pointer-storage convention? */
                    254: X    if (regsize >= 32767L)    /* Probably could be 65535L. */
                    255: X      FAIL("regexp too big");
                    256: X
                    257: X    /* Allocate space. */
                    258: X    r = (regexp *) malloc(sizeof(regexp) + (unsigned) regsize);
                    259: X    if (r == NULL)
                    260: X      FAIL("out of space");
                    261: X
                    262: X    /* Second pass: emit code. */
                    263: X    regparse = exp;
                    264: X    regnpar = 1;
                    265: X    regcode = r->program;
                    266: X    regc(MAGIC);
                    267: X    if (reg(0, &flags) == NULL)
                    268: X      return (NULL);
                    269: X
                    270: X    /* Dig out information for optimizations. */
                    271: X    r->regstart = '\0';               /* Worst-case defaults. */
                    272: X    r->reganch = 0;
                    273: X    r->regmust = NULL;
                    274: X    r->regmlen = 0;
                    275: X    scan = r->program + 1;    /* First BRANCH. */
                    276: X    if (OP(regnext(scan)) == END) {   /* Only one top-level choice. */
                    277: X      scan = OPERAND(scan);
                    278: X
                    279: X      /* Starting-point info. */
                    280: X      if (OP(scan) == EXACTLY)
                    281: X          r->regstart = *OPERAND(scan);
                    282: X      else if (OP(scan) == BOL)
                    283: X          r->reganch++;
                    284: X
                    285: X      /*
                    286: X       * If there's something expensive in the r.e., find the longest
                    287: X       * literal string that must appear and make it the regmust.  Resolve
                    288: X       * ties in favor of later strings, since the regstart check works
                    289: X       * with the beginning of the r.e. and avoiding duplication
                    290: X       * strengthens checking.  Not a strong reason, but sufficient in the
                    291: X       * absence of others. 
                    292: X       */
                    293: X      if (flags & SPSTART) {
                    294: X          longest = NULL;
                    295: X          len = 0;
                    296: X          for (; scan != NULL; scan = regnext(scan))
                    297: X              if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
                    298: X                  longest = OPERAND(scan);
                    299: X                  len = strlen(OPERAND(scan));
                    300: X              }
                    301: X          r->regmust = longest;
                    302: X          r->regmlen = len;
                    303: X      }
                    304: X    }
                    305: X    return (r);
                    306: X}
                    307: X
                    308: X/*
                    309: X - reg - regular expression, i.e. main body or parenthesized thing
                    310: X *
                    311: X * Caller must absorb opening parenthesis.
                    312: X *
                    313: X * Combining parenthesis handling with the base level of regular expression
                    314: X * is a trifle forced, but the need to tie the tails of the branches to what
                    315: X * follows makes it hard to avoid.
                    316: X */
                    317: Xstatic char *reg(paren, flagp)
                    318: Xint             paren;                /* Parenthesized? */
                    319: Xint            *flagp;
                    320: X{
                    321: X    register char  *ret;
                    322: X    register char  *br;
                    323: X    register char  *ender;
                    324: X    register int    parno;
                    325: X    int             flags;
                    326: X
                    327: X    *flagp = HASWIDTH;                /* Tentatively. */
                    328: X
                    329: X    /* Make an OPEN node, if parenthesized. */
                    330: X    if (paren) {
                    331: X      if (regnpar >= NSUBEXP)
                    332: X          FAIL("too many ()");
                    333: X      parno = regnpar;
                    334: X      regnpar++;
                    335: X      ret = regnode(OPEN + parno);
                    336: X    } else
                    337: X      ret = NULL;
                    338: X
                    339: X    /* Pick up the branches, linking them together. */
                    340: X    br = regbranch(&flags);
                    341: X    if (br == NULL)
                    342: X      return (NULL);
                    343: X    if (ret != NULL)
                    344: X      regtail(ret, br);       /* OPEN -> first. */
                    345: X    else
                    346: X      ret = br;
                    347: X    if (!(flags & HASWIDTH))
                    348: X      *flagp &= ~HASWIDTH;
                    349: X    *flagp |= flags & SPSTART;
                    350: X    while (*regparse == '|') {
                    351: X      regparse++;
                    352: X      br = regbranch(&flags);
                    353: X      if (br == NULL)
                    354: X          return (NULL);
                    355: X      regtail(ret, br);       /* BRANCH -> BRANCH. */
                    356: X      if (!(flags & HASWIDTH))
                    357: X          *flagp &= ~HASWIDTH;
                    358: X      *flagp |= flags & SPSTART;
                    359: X    }
                    360: X
                    361: X    /* Make a closing node, and hook it on the end. */
                    362: X    ender = regnode((paren) ? CLOSE + parno : END);
                    363: X    regtail(ret, ender);
                    364: X
                    365: X    /* Hook the tails of the branches to the closing node. */
                    366: X    for (br = ret; br != NULL; br = regnext(br))
                    367: X      regoptail(br, ender);
                    368: X
                    369: X    /* Check for proper termination. */
                    370: X    if (paren && *regparse++ != ')') {
                    371: X      FAIL("unmatched ()");
                    372: X    } else if (!paren && *regparse != '\0') {
                    373: X      if (*regparse == ')') {
                    374: X          FAIL("unmatched ()");
                    375: X      } else
                    376: X          FAIL("junk on end");/* "Can't happen". */
                    377: X      /* NOTREACHED */
                    378: X    }
                    379: X    return (ret);
                    380: X}
                    381: X
                    382: X/*
                    383: X - regbranch - one alternative of an | operator
                    384: X *
                    385: X * Implements the concatenation operator.
                    386: X */
                    387: Xstatic char  *regbranch(flagp)
                    388: Xint            *flagp;
                    389: X{
                    390: X    register char  *ret;
                    391: X    register char  *chain;
                    392: X    register char  *latest;
                    393: X    int             flags;
                    394: X
                    395: X    *flagp = WORST;           /* Tentatively. */
                    396: X
                    397: X    ret = regnode(BRANCH);
                    398: X    chain = NULL;
                    399: X    while (*regparse != '\0' && *regparse != '|' && *regparse != ')') {
                    400: X      latest = regpiece(&flags);
                    401: X      if (latest == NULL)
                    402: X          return (NULL);
                    403: X      *flagp |= flags & HASWIDTH;
                    404: X      if (chain == NULL)      /* First piece. */
                    405: X          *flagp |= flags & SPSTART;
                    406: X      else
                    407: X          regtail(chain, latest);
                    408: X      chain = latest;
                    409: X    }
                    410: X    if (chain == NULL)                /* Loop ran zero times. */
                    411: X      regnode(NOTHING);
                    412: X
                    413: X    return (ret);
                    414: X}
                    415: X
                    416: X/*
                    417: X - regpiece - something followed by possible [*]
                    418: X *
                    419: X * Note that the branching code sequence used for * is somewhat optimized:  
                    420: X * they use the same NOTHING node as both the endmarker for their branch 
                    421: X * list and the body of the last branch.  It might seem that this node could 
                    422: X * be dispensed with entirely, but the endmarker role is not redundant.
                    423: X */
                    424: Xstatic char *regpiece(flagp)
                    425: Xint            *flagp;
                    426: X{
                    427: X    register char  *ret;
                    428: X    register char   op;
                    429: X    register char  *nxt;
                    430: X    int             flags;
                    431: X
                    432: X    ret = regatom(&flags);
                    433: X    if (ret == NULL)
                    434: X      return (NULL);
                    435: X
                    436: X    op = *regparse;
                    437: X    if (!ISMULT(op)) {
                    438: X      *flagp = flags;
                    439: X      return (ret);
                    440: X    }
                    441: X    if (!(flags & HASWIDTH))
                    442: X      FAIL("* operand could be empty");
                    443: X    *flagp = (WORST | SPSTART);
                    444: X
                    445: X    if (op == '*' && (flags & SIMPLE))
                    446: X      reginsert(STAR, ret);
                    447: X    else if (op == '*') {
                    448: X      /* Emit x* as (x&|), where & means "self". */
                    449: X      reginsert(BRANCH, ret); /* Either x */
                    450: X      regoptail(ret, regnode(BACK));  /* and loop */
                    451: X      regoptail(ret, ret);    /* back */
                    452: X      regtail(ret, regnode(BRANCH));  /* or */
                    453: X      regtail(ret, regnode(NOTHING)); /* null. */
                    454: X    } 
                    455: X    regparse++;
                    456: X    if (ISMULT(*regparse))
                    457: X      FAIL("nested *");
                    458: X
                    459: X    return (ret);
                    460: X}
                    461: X
                    462: X/*
                    463: X - regatom - the lowest level
                    464: X *
                    465: X * Optimization:  gobbles an entire sequence of ordinary characters so that
                    466: X * it can turn them into a single node, which is smaller to store and
                    467: X * faster to run.  Backslashed characters are exceptions, each becoming a
                    468: X * separate node; the code is simpler that way and it's not worth fixing.
                    469: X */
                    470: Xstatic char *regatom(flagp)
                    471: Xint            *flagp;
                    472: X{
                    473: X    register char  *ret;
                    474: X    int             flags;
                    475: X
                    476: X    *flagp = WORST;           /* Tentatively. */
                    477: X
                    478: X    switch (*regparse++) {
                    479: X    case '^':
                    480: X      ret = regnode(BOL);
                    481: X      break;
                    482: X    case '$':
                    483: X      ret = regnode(EOL);
                    484: X      break;
                    485: X    case '.':
                    486: X      ret = regnode(ANY);
                    487: X      *flagp |= HASWIDTH | SIMPLE;
                    488: X      break;
                    489: X    case '[':{
                    490: X          register int    class;
                    491: X          register int    classend;
                    492: X
                    493: X          if (*regparse == '^') {     /* Complement of range. */
                    494: X              ret = regnode(ANYBUT);
                    495: X              regparse++;
                    496: X          } else
                    497: X              ret = regnode(ANYOF);
                    498: X          if (*regparse == ']' || *regparse == '-')
                    499: X              regc(*regparse++);
                    500: X          while (*regparse != '\0' && *regparse != ']') {
                    501: X              if (*regparse == '-') {
                    502: X                  regparse++;
                    503: X                  if (*regparse == ']' || *regparse == '\0')
                    504: X                      regc('-');
                    505: X                  else {
                    506: X                      class = UCHARAT(regparse - 2) + 1;
                    507: X                      classend = UCHARAT(regparse);
                    508: X                      if (class > classend + 1)
                    509: X                          FAIL("invalid [] range");
                    510: X                      for (; class <= classend; class++)
                    511: X                          regc(class);
                    512: X                      regparse++;
                    513: X                  }
                    514: X              } else
                    515: X                  regc(*regparse++);
                    516: X          }
                    517: X          regc('\0');
                    518: X          if (*regparse != ']')
                    519: X              FAIL("unmatched []");
                    520: X          regparse++;
                    521: X          *flagp |= HASWIDTH | SIMPLE;
                    522: X      }
                    523: X      break;
                    524: X    case '(':
                    525: X      ret = reg(1, &flags);
                    526: X      if (ret == NULL)
                    527: X          return (NULL);
                    528: X      *flagp |= flags & (HASWIDTH | SPSTART);
                    529: X      break;
                    530: X    case '\0':
                    531: X    case '|':
                    532: X    case ')':
                    533: X      FAIL("internal urp");   /* Supposed to be caught earlier. */
                    534: X      break;
                    535: X    case '*':
                    536: X      FAIL("* follows nothing");
                    537: X      break;
                    538: X    case '\\':
                    539: X      if (*regparse == '\0')
                    540: X          FAIL("trailing \\");
                    541: X      ret = regnode(EXACTLY);
                    542: X      regc(*regparse++);
                    543: X      regc('\0');
                    544: X      *flagp |= HASWIDTH | SIMPLE;
                    545: X      break;
                    546: X    default:{
                    547: X          register int    len;
                    548: X          register char   ender;
                    549: X
                    550: X          regparse--;
                    551: X          len = strcspn(regparse, META);
                    552: X          if (len <= 0)
                    553: X              FAIL("internal disaster");
                    554: X          ender = *(regparse + len);
                    555: X          if (len > 1 && ISMULT(ender))
                    556: X              len--;          /* Back off clear of * operand. */
                    557: X          *flagp |= HASWIDTH;
                    558: X          if (len == 1)
                    559: X              *flagp |= SIMPLE;
                    560: X          ret = regnode(EXACTLY);
                    561: X          while (len > 0) {
                    562: X              regc(*regparse++);
                    563: X              len--;
                    564: X          }
                    565: X          regc('\0');
                    566: X      }
                    567: X      break;
                    568: X    }
                    569: X
                    570: X    return (ret);
                    571: X}
                    572: X
                    573: X/*
                    574: X - regnode - emit a node
                    575: X */
                    576: Xstatic char *regnode(op)
                    577: Xchar            op;
                    578: X{
                    579: X    register char  *ret;
                    580: X    register char  *ptr;
                    581: X
                    582: X    ret = regcode;
                    583: X    if (ret == &regdummy) {
                    584: X      regsize += 3;
                    585: X      return (ret);
                    586: X    }
                    587: X    ptr = ret;
                    588: X    *ptr++ = op;
                    589: X    *ptr++ = '\0';            /* Null "nxt" pointer. */
                    590: X    *ptr++ = '\0';
                    591: X    regcode = ptr;
                    592: X
                    593: X    return (ret);
                    594: X}
                    595: X
                    596: X/*
                    597: X - regc - emit (if appropriate) a byte of code
                    598: X */
                    599: Xstatic void regc(b)
                    600: Xchar            b;
                    601: X{
                    602: X    if (regcode != &regdummy)
                    603: X      *regcode++ = b;
                    604: X    else
                    605: X      regsize++;
                    606: X}
                    607: X
                    608: X/*
                    609: X - reginsert - insert an operator in front of already-emitted operand
                    610: X *
                    611: X * Means relocating the operand.
                    612: X */
                    613: Xstatic void reginsert(op, opnd)
                    614: Xchar            op;
                    615: Xchar           *opnd;
                    616: X{
                    617: X    register char  *src;
                    618: X    register char  *dst;
                    619: X    register char  *place;
                    620: X
                    621: X    if (regcode == &regdummy) {
                    622: X      regsize += 3;
                    623: X      return;
                    624: X    }
                    625: X    src = regcode;
                    626: X    regcode += 3;
                    627: X    dst = regcode;
                    628: X    while (src > opnd)
                    629: X      *--dst = *--src;
                    630: X
                    631: X    place = opnd;             /* Op node, where operand used to be. */
                    632: X    *place++ = op;
                    633: X    *place++ = '\0';
                    634: X    *place++ = '\0';
                    635: X}
                    636: X
                    637: X/*
                    638: X - regtail - set the next-pointer at the end of a node chain
                    639: X */
                    640: Xstatic void regtail(p, val)
                    641: Xchar           *p;
                    642: Xchar           *val;
                    643: X{
                    644: X    register char  *scan;
                    645: X    register char  *temp;
                    646: X    register int    offset;
                    647: X
                    648: X    if (p == &regdummy)
                    649: X      return;
                    650: X
                    651: X    /* Find last node. */
                    652: X    scan = p;
                    653: X    for (;;) {
                    654: X      temp = regnext(scan);
                    655: X      if (temp == NULL)
                    656: X          break;
                    657: X      scan = temp;
                    658: X    }
                    659: X
                    660: X    if (OP(scan) == BACK)
                    661: X      offset = scan - val;
                    662: X    else
                    663: X      offset = val - scan;
                    664: X    *(scan + 1) = (offset >> 8) & 0377;
                    665: X    *(scan + 2) = offset & 0377;
                    666: X}
                    667: X
                    668: X/*
                    669: X - regoptail - regtail on operand of first argument; nop if operandless
                    670: X */
                    671: Xstatic void regoptail(p, val)
                    672: Xchar           *p;
                    673: Xchar           *val;
                    674: X{
                    675: X    /* "Operandless" and "op != BRANCH" are synonymous in practice. */
                    676: X    if (p == NULL || p == &regdummy || OP(p) != BRANCH)
                    677: X      return;
                    678: X    regtail(OPERAND(p), val);
                    679: X}
                    680: X
                    681: X/*
                    682: X * regexec and friends
                    683: X */
                    684: X
                    685: X/*
                    686: X * Global work variables for regexec().
                    687: X */
                    688: Xstatic char    *reginput;     /* String-input pointer. */
                    689: Xstatic char    *regbol;               /* Beginning of input, for ^ check. */
                    690: Xstatic char   **regstartp;    /* Pointer to startp array. */
                    691: Xstatic char   **regendp;      /* Ditto for endp. */
                    692: X
                    693: X/*
                    694: X * Forwards.
                    695: X */
                    696: XSTATIC int      regtry();
                    697: XSTATIC int      regmatch();
                    698: XSTATIC int      regrepeat();
                    699: X
                    700: X#ifdef DEBUG
                    701: Xint             regnarrate = 0;
                    702: Xvoid            regdump();
                    703: XSTATIC char    *regprop();
                    704: X#endif
                    705: X
                    706: X/*
                    707: X - regexec - match a regexp against a string
                    708: X */
                    709: Xint regexec(prog, string)
                    710: Xregister regexp *prog;
                    711: Xregister char  *string;
                    712: X{
                    713: X    register char  *s;
                    714: X
                    715: X    /* Be paranoid... */
                    716: X    if (prog == NULL || string == NULL) {
                    717: X      regerror("NULL parameter");
                    718: X      return (0);
                    719: X    }
                    720: X    /* Check validity of program. */
                    721: X    if (UCHARAT(prog->program) != MAGIC) {
                    722: X      regerror("corrupted program");
                    723: X      return (0);
                    724: X    }
                    725: X    /* If there is a "must appear" string, look for it. */
                    726: X    if (prog->regmust != NULL) {
                    727: X      s = string;
                    728: X      while ((s = strchr(s, prog->regmust[0])) != NULL) {
                    729: X          if (strncmp(s, prog->regmust, prog->regmlen) == 0)
                    730: X              break;          /* Found it. */
                    731: X          s++;
                    732: X      }
                    733: X      if (s == NULL)          /* Not present. */
                    734: X          return (0);
                    735: X    }
                    736: X    /* Mark beginning of line for ^ . */
                    737: X    regbol = string;
                    738: X
                    739: X    /* Simplest case:  anchored match need be tried only once. */
                    740: X    if (prog->reganch)
                    741: X      return (regtry(prog, string));
                    742: X
                    743: X    /* Messy cases:  unanchored match. */
                    744: X    s = string;
                    745: X    if (prog->regstart != '\0')
                    746: X      /* We know what char it must start with. */
                    747: X      while ((s = strchr(s, prog->regstart)) != NULL) {
                    748: X          if (regtry(prog, s))
                    749: X              return (1);
                    750: X          s++;
                    751: X      }
                    752: X    else
                    753: X      /* We don't -- general case. */
                    754: X      do {
                    755: X          if (regtry(prog, s))
                    756: X              return (1);
                    757: X      } while (*s++ != '\0');
                    758: X
                    759: X    /* Failure. */
                    760: X    return (0);
                    761: X}
                    762: X
                    763: X/*
                    764: X - regtry - try match at specific point
                    765: X */
                    766: X#ifdef __STDC__
                    767: X
                    768: Xstatic int regtry(regexp *prog, char *string)
                    769: X
                    770: X#else
                    771: X
                    772: Xstatic int regtry(prog, string)
                    773: Xregexp         *prog;
                    774: Xchar           *string;
                    775: X
                    776: X#endif
                    777: X{
                    778: X    register int    i;
                    779: X    register char **sp;
                    780: X    register char **ep;
                    781: X
                    782: X    reginput = string;
                    783: X    regstartp = prog->startp;
                    784: X    regendp = prog->endp;
                    785: X
                    786: X    sp = prog->startp;
                    787: X    ep = prog->endp;
                    788: X    for (i = NSUBEXP; i > 0; i--) {
                    789: X      *sp++ = NULL;
                    790: X      *ep++ = NULL;
                    791: X    }
                    792: X    if (regmatch(prog->program + 1)) {
                    793: X      prog->startp[0] = string;
                    794: X      prog->endp[0] = reginput;
                    795: X      return (1);
                    796: X    } else
                    797: X      return (0);
                    798: X}
                    799: X
                    800: X/*
                    801: X - regmatch - main matching routine
                    802: X *
                    803: X * Conceptually the strategy is simple:  check to see whether the current
                    804: X * node matches, call self recursively to see whether the rest matches,
                    805: X * and then act accordingly.  In practice we make some effort to avoid
                    806: X * recursion, in particular by going through "ordinary" nodes (that don't
                    807: X * need to know whether the rest of the match failed) by a loop instead of
                    808: X * by recursion.
                    809: X */
                    810: X#ifdef __STDC__
                    811: X
                    812: Xstatic int regmatch(char *prog)
                    813: X
                    814: X#else
                    815: X
                    816: Xstatic int regmatch(prog)
                    817: Xchar           *prog;
                    818: X
                    819: X#endif
                    820: X{
                    821: X    register char  *scan;     /* Current node. */
                    822: X    char           *nxt;      /* nxt node. */
                    823: X
                    824: X    scan = prog;
                    825: X#ifdef DEBUG
                    826: X    if (scan != NULL && regnarrate)
                    827: X      fprintf(stderr, "%s(\n", regprop(scan));
                    828: X#endif
                    829: X    while (scan != NULL) {
                    830: X#ifdef DEBUG
                    831: X      if (regnarrate)
                    832: X          fprintf(stderr, "%s...\n", regprop(scan));
                    833: X#endif
                    834: X      nxt = regnext(scan);
                    835: X
                    836: X      switch (OP(scan)) {
                    837: X      case BOL:
                    838: X          if (reginput != regbol)
                    839: X              return (0);
                    840: X          break;
                    841: X      case EOL:
                    842: X          if (*reginput != '\0')
                    843: X              return (0);
                    844: X          break;
                    845: X      case ANY:
                    846: X          if (*reginput == '\0')
                    847: X              return (0);
                    848: X          reginput++;
                    849: X          break;
                    850: X      case EXACTLY:{
                    851: X              register int    len;
                    852: X              register char  *opnd;
                    853: X
                    854: X              opnd = OPERAND(scan);
                    855: X              /* Inline the first character, for speed. */
                    856: X              if (*opnd != *reginput)
                    857: X                  return (0);
                    858: X              len = strlen(opnd);
                    859: X              if (len > 1 && strncmp(opnd, reginput, len) != 0)
                    860: X                  return (0);
                    861: X              reginput += len;
                    862: X          }
                    863: X          break;
                    864: X      case ANYOF:
                    865: X          if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL)
                    866: X              return (0);
                    867: X          reginput++;
                    868: X          break;
                    869: X      case ANYBUT:
                    870: X          if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL)
                    871: X              return (0);
                    872: X          reginput++;
                    873: X          break;
                    874: X      case NOTHING:
                    875: X          break;
                    876: X      case BACK:
                    877: X          break;
                    878: X      case OPEN + 1:
                    879: X      case OPEN + 2:
                    880: X      case OPEN + 3:
                    881: X      case OPEN + 4:
                    882: X      case OPEN + 5:
                    883: X      case OPEN + 6:
                    884: X      case OPEN + 7:
                    885: X      case OPEN + 8:
                    886: X      case OPEN + 9:{
                    887: X              register int    no;
                    888: X              register char  *save;
                    889: X
                    890: X              no = OP(scan) - OPEN;
                    891: X              save = reginput;
                    892: X
                    893: X              if (regmatch(nxt)) {
                    894: X                  /*
                    895: X                   * Don't set startp if some later invocation of the same
                    896: X                   * parentheses already has. 
                    897: X                   */
                    898: X                  if (regstartp[no] == NULL)
                    899: X                      regstartp[no] = save;
                    900: X                  return (1);
                    901: X              } else
                    902: X                  return (0);
                    903: X          }
                    904: X          break;
                    905: X      case CLOSE + 1:
                    906: X      case CLOSE + 2:
                    907: X      case CLOSE + 3:
                    908: X      case CLOSE + 4:
                    909: X      case CLOSE + 5:
                    910: X      case CLOSE + 6:
                    911: X      case CLOSE + 7:
                    912: X      case CLOSE + 8:
                    913: X      case CLOSE + 9:{
                    914: X              register int    no;
                    915: X              register char  *save;
                    916: X
                    917: X              no = OP(scan) - CLOSE;
                    918: X              save = reginput;
                    919: X
                    920: X              if (regmatch(nxt)) {
                    921: X                  /*
                    922: X                   * Don't set endp if some later invocation of the same
                    923: X                   * parentheses already has. 
                    924: X                   */
                    925: X                  if (regendp[no] == NULL)
                    926: X                      regendp[no] = save;
                    927: X                  return (1);
                    928: X              } else
                    929: X                  return (0);
                    930: X          }
                    931: X          break;
                    932: X      case BRANCH:{
                    933: X              register char  *save;
                    934: X
                    935: X              if (OP(nxt) != BRANCH)  /* No choice. */
                    936: X                  nxt = OPERAND(scan);        /* Avoid recursion. */
                    937: X              else {
                    938: X                  do {
                    939: X                      save = reginput;
                    940: X                      if (regmatch(OPERAND(scan)))
                    941: X                          return (1);
                    942: X                      reginput = save;
                    943: X                      scan = regnext(scan);
                    944: X                  } while (scan != NULL && OP(scan) == BRANCH);
                    945: X                  return (0);
                    946: X                  /* NOTREACHED */
                    947: X              }
                    948: X          }
                    949: X          break;
                    950: X      case STAR:{
                    951: X              register char   nextch;
                    952: X              register int    no;
                    953: X              register char  *save;
                    954: X              register int    min;
                    955: X
                    956: X              /*
                    957: X               * Lookahead to avoid useless match attempts when we know
                    958: X               * what character comes next. 
                    959: X               */
                    960: X              nextch = '\0';
                    961: X              if (OP(nxt) == EXACTLY)
                    962: X                  nextch = *OPERAND(nxt);
                    963: X              min = (OP(scan) == STAR) ? 0 : 1;
                    964: X              save = reginput;
                    965: X              no = regrepeat(OPERAND(scan));
                    966: X              while (no >= min) {
                    967: X                  /* If it could work, try it. */
                    968: X                  if (nextch == '\0' || *reginput == nextch)
                    969: X                      if (regmatch(nxt))
                    970: X                          return (1);
                    971: X                  /* Couldn't or didn't -- back up. */
                    972: X                  no--;
                    973: X                  reginput = save + no;
                    974: X              }
                    975: X              return (0);
                    976: X          }
                    977: X          break;
                    978: X      case END:
                    979: X          return (1);         /* Success! */
                    980: X          break;
                    981: X      default:
                    982: X          regerror("memory corruption");
                    983: X          return (0);
                    984: X          break;
                    985: X      }
                    986: X
                    987: X      scan = nxt;
                    988: X    }
                    989: X
                    990: X    /*
                    991: X     * We get here only if there's trouble -- normally "case END" is the
                    992: X     * terminating point. 
                    993: X     */
                    994: X    regerror("corrupted pointers");
                    995: X    return (0);
                    996: X}
                    997: X
                    998: X/*
                    999: X - regrepeat - repeatedly match something simple, report how many
                   1000: X */
                   1001: X#ifdef __STDC__
                   1002: X
                   1003: Xstatic int regrepeat(char *p)
                   1004: X
                   1005: X#else
                   1006: X
                   1007: Xstatic int regrepeat(p)
                   1008: Xchar           *p;
                   1009: X
                   1010: X#endif
                   1011: X{
                   1012: X    register int    count = 0;
                   1013: X    register char  *scan;
                   1014: X    register char  *opnd;
                   1015: X
                   1016: X    scan = reginput;
                   1017: X    opnd = OPERAND(p);
                   1018: X    switch (OP(p)) {
                   1019: X    case ANY:
                   1020: X      count = strlen(scan);
                   1021: X      scan += count;
                   1022: X      break;
                   1023: X    case EXACTLY:
                   1024: X      while (*opnd == *scan) {
                   1025: X          count++;
                   1026: X          scan++;
                   1027: X      }
                   1028: X      break;
                   1029: X    case ANYOF:
                   1030: X      while (*scan != '\0' && strchr(opnd, *scan) != NULL) {
                   1031: X          count++;
                   1032: X          scan++;
                   1033: X      }
                   1034: X      break;
                   1035: X    case ANYBUT:
                   1036: X      while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
                   1037: X          count++;
                   1038: X          scan++;
                   1039: X      }
                   1040: X      break;
                   1041: X    default:                  /* Oh dear.  Called inappropriately. */
                   1042: X      regerror("internal foulup");
                   1043: X      count = 0;              /* Best compromise. */
                   1044: X      break;
                   1045: X    }
                   1046: X    reginput = scan;
                   1047: X
                   1048: X    return (count);
                   1049: X}
                   1050: X
                   1051: X
                   1052: X/*
                   1053: X - regnext - dig the "nxt" pointer out of a node
                   1054: X */
                   1055: X#ifdef __STDC__
                   1056: X
                   1057: Xstatic char *regnext(register char *p)
                   1058: X
                   1059: X#else
                   1060: X
                   1061: Xstatic char *regnext(p)
                   1062: Xregister char  *p;
                   1063: X
                   1064: X#endif
                   1065: X{
                   1066: X    register int    offset;
                   1067: X
                   1068: X    if (p == &regdummy)
                   1069: X      return (NULL);
                   1070: X
                   1071: X    offset = NEXT(p);
                   1072: X    if (offset == 0)
                   1073: X      return (NULL);
                   1074: X
                   1075: X    if (OP(p) == BACK)
                   1076: X      return (p - offset);
                   1077: X    else
                   1078: X      return (p + offset);
                   1079: X}
                   1080: X
                   1081: X#ifdef DEBUG
                   1082: X
                   1083: XSTATIC char    *regprop();
                   1084: X
                   1085: X/*
                   1086: X - regdump - dump a regexp onto stdout in vaguely comprehensible form
                   1087: X */
                   1088: X#ifdef __STDC__
                   1089: X
                   1090: Xvoid regdump(regexp *r)
                   1091: X
                   1092: X#else
                   1093: X
                   1094: Xvoid regdump(r)
                   1095: Xregexp         *r;
                   1096: X
                   1097: X#endif
                   1098: X{
                   1099: X    register char  *s;
                   1100: X    register char   op = EXACTLY;     /* Arbitrary non-END op. */
                   1101: X    register char  *nxt;
                   1102: X    extern char    *strchr();
                   1103: X
                   1104: X
                   1105: X    s = r->program + 1;
                   1106: X    while (op != END) {               /* While that wasn't END last time... */
                   1107: X      op = OP(s);
                   1108: X      printf("%2d%s", s - r->program, regprop(s));    /* Where, what. */
                   1109: X      nxt = regnext(s);
                   1110: X      if (nxt == NULL)        /* nxt ptr. */
                   1111: X          printf("(0)");
                   1112: X      else
                   1113: X          printf("(%d)", (s - r->program) + (nxt - s));
                   1114: X      s += 3;
                   1115: X      if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
                   1116: X          /* Literal string, where present. */
                   1117: X          while (*s != '\0') {
                   1118: X              putchar(*s);
                   1119: X              s++;
                   1120: X          }
                   1121: X          s++;
                   1122: X      }
                   1123: X      putchar('\n');
                   1124: X    }
                   1125: X
                   1126: X    /* Header fields of interest. */
                   1127: X    if (r->regstart != '\0')
                   1128: X      printf("start `%c' ", r->regstart);
                   1129: X    if (r->reganch)
                   1130: X      printf("anchored ");
                   1131: X    if (r->regmust != NULL)
                   1132: X      printf("must have \"%s\"", r->regmust);
                   1133: X    printf("\n");
                   1134: X}
                   1135: X
                   1136: X/*
                   1137: X - regprop - printable representation of opcode
                   1138: X */
                   1139: X#ifdef __STDC__
                   1140: X
                   1141: Xstatic char *regprop(char *op)
                   1142: X
                   1143: X#else
                   1144: X
                   1145: Xstatic char *regprop(op)
                   1146: Xchar           *op;
                   1147: X
                   1148: X#endif
                   1149: X{
                   1150: X    register char  *p;
                   1151: X    static char     buf[50];
                   1152: X
                   1153: X    strcpy(buf, ":");
                   1154: X
                   1155: X    switch (OP(op)) {
                   1156: X    case BOL:
                   1157: X      p = "BOL";
                   1158: X      break;
                   1159: X    case EOL:
                   1160: X      p = "EOL";
                   1161: X      break;
                   1162: X    case ANY:
                   1163: X      p = "ANY";
                   1164: X      break;
                   1165: X    case ANYOF:
                   1166: X      p = "ANYOF";
                   1167: X      break;
                   1168: X    case ANYBUT:
                   1169: X      p = "ANYBUT";
                   1170: X      break;
                   1171: X    case BRANCH:
                   1172: X      p = "BRANCH";
                   1173: X      break;
                   1174: X    case EXACTLY:
                   1175: X      p = "EXACTLY";
                   1176: X      break;
                   1177: X    case NOTHING:
                   1178: X      p = "NOTHING";
                   1179: X      break;
                   1180: X    case BACK:
                   1181: X      p = "BACK";
                   1182: X      break;
                   1183: X    case END:
                   1184: X      p = "END";
                   1185: X      break;
                   1186: X    case OPEN + 1:
                   1187: X    case OPEN + 2:
                   1188: X    case OPEN + 3:
                   1189: X    case OPEN + 4:
                   1190: X    case OPEN + 5:
                   1191: X    case OPEN + 6:
                   1192: X    case OPEN + 7:
                   1193: X    case OPEN + 8:
                   1194: X    case OPEN + 9:
                   1195: X      sprintf(buf + strlen(buf), "OPEN%d", OP(op) - OPEN);
                   1196: X      p = NULL;
                   1197: X      break;
                   1198: X    case CLOSE + 1:
                   1199: X    case CLOSE + 2:
                   1200: X    case CLOSE + 3:
                   1201: X    case CLOSE + 4:
                   1202: X    case CLOSE + 5:
                   1203: X    case CLOSE + 6:
                   1204: X    case CLOSE + 7:
                   1205: X    case CLOSE + 8:
                   1206: X    case CLOSE + 9:
                   1207: X      sprintf(buf + strlen(buf), "CLOSE%d", OP(op) - CLOSE);
                   1208: X      p = NULL;
                   1209: X      break;
                   1210: X    case STAR:
                   1211: X      p = "STAR";
                   1212: X      break;
                   1213: X    default:
                   1214: X      regerror("corrupted opcode");
                   1215: X      break;
                   1216: X    }
                   1217: X    if (p != NULL)
                   1218: X      strcat(buf, p);
                   1219: X    return (buf);
                   1220: X}
                   1221: X#endif
                   1222: X
                   1223: X/*
                   1224: X * The following is provided for those people who do not have strcspn() in
                   1225: X * their C libraries.  They should get off their butts and do something
                   1226: X * about it; at least one public-domain implementation of those (highly
                   1227: X * useful) string routines has been published on Usenet.
                   1228: X */
                   1229: X#ifdef STRCSPN
                   1230: X/*
                   1231: X * strcspn - find length of initial segment of s1 consisting entirely
                   1232: X * of characters not from s2
                   1233: X */
                   1234: X
                   1235: X#ifdef __STDC__
                   1236: X
                   1237: Xstatic int strcspn(char *s1, char *s2)
                   1238: X
                   1239: X#else
                   1240: X
                   1241: Xstatic int strcspn(s1, s2)
                   1242: Xchar           *s1;
                   1243: Xchar           *s2;
                   1244: X
                   1245: X#endif
                   1246: X{
                   1247: X    register char  *scan1;
                   1248: X    register char  *scan2;
                   1249: X    register int    count;
                   1250: X
                   1251: X    count = 0;
                   1252: X    for (scan1 = s1; *scan1 != '\0'; scan1++) {
                   1253: X      for (scan2 = s2; *scan2 != '\0';)       /* ++ moved down. */
                   1254: X          if (*scan1 == *scan2++)
                   1255: X              return (count);
                   1256: X      count++;
                   1257: X    }
                   1258: X    return (count);
                   1259: X}
                   1260: X#endif
                   1261: X
                   1262: X
                   1263: X/*
                   1264: X - regsub - perform substitutions after a regexp match
                   1265: X */
                   1266: X#ifdef __STDC__
                   1267: X
                   1268: Xvoid regsub(regexp *prog, char *source, char *dest)
                   1269: X
                   1270: X#else
                   1271: X
                   1272: Xvoid regsub(prog, source, dest)
                   1273: Xregexp         *prog;
                   1274: Xchar           *source;
                   1275: Xchar           *dest;
                   1276: X
                   1277: X#endif
                   1278: X{
                   1279: X    register char  *src;
                   1280: X    register char  *dst;
                   1281: X    register char   c;
                   1282: X    register int    no;
                   1283: X    register int    len;
                   1284: X    extern char    *strncpy();
                   1285: X
                   1286: X    if (prog == NULL || source == NULL || dest == NULL) {
                   1287: X      regerror("NULL parm to regsub");
                   1288: X      return;
                   1289: X    }
                   1290: X    if (UCHARAT(prog->program) != MAGIC) {
                   1291: X      regerror("damaged regexp fed to regsub");
                   1292: X      return;
                   1293: X    }
                   1294: X    src = source;
                   1295: X    dst = dest;
                   1296: X    while ((c = *src++) != '\0') {
                   1297: X      if (c == '&')
                   1298: X          no = 0;
                   1299: X      else if (c == '\\' && '0' <= *src && *src <= '9')
                   1300: X          no = *src++ - '0';
                   1301: X      else
                   1302: X          no = -1;
                   1303: X
                   1304: X      if (no < 0) {           /* Ordinary character. */
                   1305: X          if (c == '\\' && (*src == '\\' || *src == '&'))
                   1306: X              c = *src++;
                   1307: X          *dst++ = c;
                   1308: X      } else if (prog->startp[no] != NULL && prog->endp[no] != NULL) {
                   1309: X          len = prog->endp[no] - prog->startp[no];
                   1310: X          strncpy(dst, prog->startp[no], len);
                   1311: X          dst += len;
                   1312: X          if (len != 0 && *(dst - 1) == '\0') {       /* strncpy hit NUL. */
                   1313: X              regerror("damaged match string");
                   1314: X              return;
                   1315: X          }
                   1316: X      }
                   1317: X    }
                   1318: X    *dst++ = '\0';
                   1319: X}
                   1320: X
                   1321: X
                   1322: X#ifdef __STDC__
                   1323: X
                   1324: Xvoid regerror(char *s)
                   1325: X
                   1326: X#else
                   1327: X
                   1328: Xvoid regerror(s)
                   1329: Xchar           *s;
                   1330: X
                   1331: X#endif
                   1332: X{
                   1333: X    fprintf(stderr, "regexp(3): %s", s);
                   1334: X    exit(1);
                   1335: X}
                   1336: END_OF_regexp.c
                   1337: if test 30611 -ne `wc -c <regexp.c`; then
                   1338:     echo shar: \"regexp.c\" unpacked with wrong size!
                   1339: fi
                   1340: # end of overwriting check
                   1341: fi
                   1342: if test -f 'Makefile' -a "${1}" != "-c" ; then 
                   1343:   echo shar: Will not clobber existing file \"'Makefile'\"
                   1344: else
                   1345: echo shar: Extracting \"'Makefile'\" \(3296 characters\)
                   1346: sed "s/^X//" >'Makefile' <<'END_OF_FILE'
                   1347: X#
                   1348: X# PAX - read and write POSIX conformant tar and cpio archives 
                   1349: X#
                   1350: X# Written by Mark H. Colburn ([email protected])
                   1351: X#
                   1352: X# $Id: Makefile,v 1.1 88/12/23 18:02:42 mark Rel $
                   1353: X#
                   1354: X
                   1355: X#
                   1356: X# CONFIGURATION SECTION
                   1357: X#
                   1358: X# The following defines may need to be changed for each system which PAX
                   1359: X# is installed on.  Please review these settings before installing on your
                   1360: X# system.
                   1361: X
                   1362: X#
                   1363: X# You should define _POSIX_SOURCE if you are running on a POSIX system.  This
                   1364: X# include has to be in the command line because it has to appear before any
                   1365: X# include file is included in the source.  For most systems in use today,
                   1366: X# it should be left blank.
                   1367: X# 
                   1368: X# POSIX= -D_POSIX_SOURCE
                   1369: XPOSIX= 
                   1370: X
                   1371: X#
                   1372: X# Set CFLAGS to whatever makes your C compiler happy.  Be sure to include 
                   1373: X# the definition of $(POSIX) in the flag.
                   1374: X#
                   1375: XCFLAGS = -O $(POSIX)
                   1376: XCC = cc
                   1377: X
                   1378: X#
                   1379: X# Set LFLAGS to whatever makes your linker happy
                   1380: X#
                   1381: X#LDFLAGS = -s
                   1382: XLDFLAGS = 
                   1383: X
                   1384: X#
                   1385: X# Set LINTFLAGS to whatever makes your implementation of lint happy.  If
                   1386: X# you don't undef __STDC__ and you have an ANSI C compiler, lint will choke 
                   1387: X# on the function prototypes present in func.h
                   1388: X#
                   1389: XLINTFLAGS = -U__STDC__ $(POSIX)
                   1390: X
                   1391: X#
                   1392: X# BINDIR - points to the directory in which you want the final pax, tar and
                   1393: X# cpio binaries installed in.
                   1394: X#
                   1395: XBINDIR = /usr/local/bin
                   1396: X
                   1397: X#
                   1398: X# MANDIR - specify the directory in which the man pages will be installed
                   1399: X#
                   1400: XMAN5 = /usr/man/man5
                   1401: XMAN1 = /usr/man/man1
                   1402: X
                   1403: X#
                   1404: X# There are three different ways to get POSIX or BSD conformant directory 
                   1405: X# access routines: 1) they are installed in your system library, 2) you 
                   1406: X# are using Doug Gwyn's dirent library (/usr/lib/libdirent.a), or 3) you 
                   1407: X# need the source for the dirent package.  Based on that, pick one of the 
                   1408: X# following three options:
                   1409: X#
                   1410: X# 1. Pick the first dirent line and make sure that config.h is defined
                   1411: X#    correctly for your version of directory access routines.  THIS IS
                   1412: X#    THE LINE WHICH SHOULD BE USED FOR BSD SYSTEMS.
                   1413: X# 2. Chose the second dirent line which  used a library at link time.  You
                   1414: X#    may need to change the name of the library to match your system.
                   1415: X# 3. If you need #3, then you must copy everything in the subdirectory dirent 
                   1416: X#    to this directory and choose the DIROBJ lines.  Please note that this 
                   1417: X#    version of dirent has been modified to work as a stand-alone. 
                   1418: X#
                   1419: XDIRENT=
                   1420: X#DIRENT= -ldirent
                   1421: X#DIROBJ= paxdir.o
                   1422: X
                   1423: X#
                   1424: X# END CONFIGURATION SECTION 
                   1425: X#
                   1426: X# Nothing beyond this point should need to be changed.
                   1427: X#
                   1428: X
                   1429: XMISC   = Makefile pax.1 tar.5 cpio.5 README PATCHLEVEL
                   1430: XHEADERS= config.h func.h limits.h port.h pax.h 
                   1431: XSOURCE= pax.c append.c buffer.c cpio.c create.c extract.c fileio.c\
                   1432: X      link.c list.c mem.c namelist.c names.c pass.c pathname.c\
                   1433: X      port.c regexp.c replace.c tar.c ttyio.c warn.c wildmat.c
                   1434: XOBJECT= pax.o append.o buffer.o cpio.o create.o extract.o fileio.o\
                   1435: X      link.o list.o mem.o namelist.o names.o pass.o pathname.o\
                   1436: X      port.o regexp.o replace.o tar.o ttyio.o warn.o wildmat.o $(DIROBJ)
                   1437: XPROGS = pax tar cpio
                   1438: XPMAN1 = pax.1 tar.1
                   1439: XPMAN5 = pax.5 tar.5
                   1440: X
                   1441: Xall: $(PROGS)
                   1442: X
                   1443: Xinstall: $(PROGS)
                   1444: X      mv $(PROGS) $(BINDIR)
                   1445: X      cp $(PMAN1) $(MAN1)
                   1446: X#     cp $(PMAN5) $(MAN5)
                   1447: X
                   1448: Xclean:
                   1449: X      rm -f $(OBJECT)
                   1450: X      rm -f $(PROGS) a.out *.BAK *.bak 
                   1451: X
                   1452: Xlint:
                   1453: X      lint $(LINTFLAGS) $(SOURCE)
                   1454: X
                   1455: Xpax : $(OBJECT)
                   1456: X      $(CC) $(CFLAGS) -o pax $(OBJECT) $(DIRENT) 
                   1457: X
                   1458: Xtar: pax
                   1459: X      rm -f tar
                   1460: X      ln pax tar
                   1461: X
                   1462: Xcpio: pax
                   1463: X      rm -f cpio
                   1464: X      ln pax cpio
                   1465: X
                   1466: X$(OBJECT): $(HEADERS)
                   1467: END_OF_FILE
                   1468: if test 3296 -ne `wc -c <'Makefile'`; then
                   1469:     echo shar: \"'Makefile'\" unpacked with wrong size!
                   1470: fi
                   1471: # end of 'Makefile'
                   1472: fi
                   1473: echo shar: End of archive 6 \(of 6\).
                   1474: cp /dev/null ark6isdone
                   1475: MISSING=""
                   1476: for I in 1 2 3 4 5 6 ; do
                   1477:     if test ! -f ark${I}isdone ; then
                   1478:        MISSING="${MISSING} ${I}"
                   1479:     fi
                   1480: done
                   1481: if test "${MISSING}" = "" ; then
                   1482:     echo You have unpacked all 6 archives.
                   1483:     rm -f ark[1-9]isdone
                   1484: else
                   1485:     echo You still need to unpack the following archives:
                   1486:     echo "        " ${MISSING}
                   1487: fi
                   1488: ##  End of shell archive.
                   1489: exit 0
                   1490: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.