|
|
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; ®dummy = 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 = ®dummy; ! 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 == ®dummy) { ! 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 != ®dummy) ! 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 == ®dummy) { ! 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 == ®dummy) ! 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 == ®dummy || 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 == ®dummy) ! 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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.