home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / portfoli / grep / grep.c next >
Encoding:
Text File  |  1991-08-21  |  16.7 KB  |  466 lines

  1. /*
  2.  *
  3.  *
  4.  * The  information  in  this  document  is  subject  to  change
  5.  * without  notice  and  should not be construed as a commitment
  6.  * by Digital Equipment Corporation or by DECUS.
  7.  *
  8.  * Neither Digital Equipment Corporation, DECUS, nor the authors
  9.  * assume any responsibility for the use or reliability of  this
  10.  * document or the described software.
  11.  *
  12.  *      Copyright (C) 1980, DECUS
  13.  *
  14.  *
  15.  * General permission to copy or modify, but not for profit,  is
  16.  * hereby  granted,  provided that the above copyright notice is
  17.  * included and reference made to  the  fact  that  reproduction
  18.  * privileges were granted by DECUS≡pנij≡pנijijppנ≡pכ⇩î⇧Ç    êOכä⇧ëé@âכ≡pנ≡pij@≡pנijנê⇦ê◆ij≡pנij≡pנijנäÇäOÇנüâêOÖê ⇦Oî◆é⇧ê⇦נÇ⇦נÇנÇÇ⇦@≡pנijנ£Çê⇦üê    נêÇ⇦נ£ÖäOî◆é⇧ê⇦נבÇëê⇦נ£◆ij⓪@CואAנגוij⓪ÄijCגAנîéO£⇨äé⇦OÉ✓⇦Çij≡pנij≡pנijנ£Çê⇦üê    נüÇOÆÉOç£OÇ⇩⇧âנ£②@Cijנ£O£◆é⇧ê⇦נÉÇêOהBCגOîéOÖÄé    נÉijנä⇩⇧â≡pנij≡pנijנÉנÇÇ⇦Aנëê✓éêOÄ⇦@≡pנij≡pנijננננננê⇦ê◆נijij@Oכחëé⇦@Ç üÇ✓⇦ê◆כנננננבÇÄ⇧éêBppנijננננננê⇦ê◆נijij@Oכחëé⇦@Ç üÇ✓⇦ê◆נêrep"     (Decus)
  19.  *
  20.  * See below for more information.
  21.  *
  22.  */
  23.  
  24.  
  25. char    *documentation[] = {
  26. "grep searches a file for a given pattern.  Execute by",
  27. "   grep [flags] regular_expression file_list",
  28. "",
  29. "Flags are singleî⇨Ä⇦Ä ⇧ê⇦äP892õØØØ2Ø⓪1<É③ûô¥①⑥╱à①⓪⓪⓪⑥õÉ⓪⓪⓪⓪⓪'Ã6<É0É1ôÃ:⓪7ø⓪6ã´1œ4Ã3É64Ã2¨É4¨É894Ã:2Ø①⑥╱à①⓪⓪⓪⑥ø⓪⓪⓪⓪⓪⓪+אA@τגAג'ijG⇦'ג@⇩gij◆ה⇧IJD'ijIJD⇩'א⇧ה⇧ατא⇦⑨H⑧Ö[§זï⇨Bêê✓✓♪[ê✓✓✓✓✓①XXם✓ə[ÖHə\זÖXךYY⑨Y✓⑧ßHə]זə[ÖH¥[XÖ\êï⇨Bêê✓✓♪]ê✓✓✓✓✓③ף¢HÜ[¥✓¢ףï[X]⑧םə[Öזə[Ö\זï⇨Bêêï⇨Bêòə⑨H⑨Ü[⑨Wףə\§✓⑥⇨ו╱④⇨⇧ã⇦Φϕ³œ╱Φ⇧¯½¯④⇨u⌠¯❎⇨í❎⇨
  30. ijuקδIJו╱⑥⇨í❎⇨ï⑥⇨PS╱WîזÄij™⇩⇧ו╱❎⇨⇧Φ¥¯u⑨_◆[Xú❎⇨ë⑥⇨®⇩⇧¨⇧≤ºt③Õ⇦Çב_◆[ë⑥⇨[ë❎⇨♪ijבí◆⇨ï⑥    ⇨❎⇧âפú◆⇨ë⑥    ⇨¯╱⑥⇨í❎⇨-⇧ú❎⇨uÿבΦz²í❎⇨=u⇦ΦWבΦδã0Φ¯Φ/t⇧ב¯╱⑥⇨ו╱④⇨⇧ã⇦Φ9³&ïGGœ❎Φδ¯④⇨u≡¯❎⇨í❎⇨
  31. ijuסδ´Φ⌠²ãtΦ④³œ╱Φ(³¿⇧u@
  32. ijy⇦¿✓tτ3ijבו╱⓪⇨ו╱②⇨זΦכ²ãtΦ∮²œ╱Φ³¯⓪⇨u╱¯②⇨t♪
  33. ijxπ¿⇧u✓3ijב¨ Çδ◆¿ t✓¨
  34. ÇïIJ♪ijב¿@u❎¨⇩Çδ≥
  35. ijy"ו╱⓪⇨Φä²ãtΦñ²œ╱ΦÕ²¯⓪⇨â>⓪⇨tג
  36. ijxΣã④Φﲜ╱Φƒ²¿@t❎¨⇦Çδ¨¿⇩t❎¨╱Çδ㨠ǿ⓪t⌐¨✓ÇδñPã$δ⑦Pã4δ②PãDδPãTδ✓Pãdδ⇨PãtΦI²Y2ϕœ❎èד$≡
  37. ג∈ΦMⁿçצã⇩∈ΦEⁿ2ij∈Φ?ⁿçצèדסαסαסαסα
  38. ג∈Φ-ⁿçצã⇩∈Φ%ⁿ2ij∈ΦⁿçצèIJ$≡
  39. ג∈Φ③ⁿçצã⇩∈Φ♪ⁿ2ij∈Φ❎ⁿçצèIJסαסαסαסα
  40. ג∈Φ≤√çצã⇩∈Φδ√2ij∈Φσ√çצèג$ ∈בPí⑥⇨ג>④&ëE②X♪ijב&èE⇧ó⇩⇨:╱
  41. s†2Σעα⇨ןï/3ijבÕ⇧Ç
  42. ijבîזÄijÄן™⇩⇧ו╱❎⇨⇧ïF①ú◆⇨ïF③ú    ⇨ב&ïE②ú❎⇨3פ&ïE④è⇦÷IJ⇩t=¯¯u✓&ïEə&ïU⇨F①③V③ú◆⇨ë⑥    ⇨ב⇩⇦⇧⇩⇩°✓①⇦⇩⇦⇧⇩⇩°✓①⇦⇩⇦⇧⇩⇩°✓①⇦⇩⇦⇧⇩⇩°✓①⇦⇩⇦⇧⇩⇩°✓①⇦⇩⇦⇧⇩⇩°✓①⇦⇩⇦⇧⇩⇩°✓①⇦⇩⇦⇧⇩⇩°✓①⇦⇩⇦⇧⇩⇩°✓①⇦⇩⇦⇧⇩⇩°✓①⇦⇩⇦⇧⇩⇩°✓①⇦⇩⇦⇧⇩⇩°✓①⇦⇩⇦⇧⇩⇩°✓①⇦⇩⇦⇧⇩⇩°✓①⇦⇩⇦⇧⇩⇩°✓①⇦⇩⇦⇧⇩⇩°✓①⇦⇩⇦⇧⇩⇩°✓①⇦g⇩╱Wœ    ´å①ל!Õ0ל!<⇩t
  43. ´④œ    ל!Θª⇩ה╱⑨ ג>④ה╱∞
  44. ⇨&דu②3ח3פ¼</t
  45. <✓t≈< roδ±¼<✓t√< rdt⌡$∞<Tt5<Puδ¼<✓t√< rO</t∧<0r∩<9v$∞<Arσ<Fwβ,7δ⇩,0עΓעΓעΓעΓ
  46. סδנ¼<✓t√< r</t¡<0r∩<9wδ,02Σïךעβעβ⇨יעβ⇨זδךîזÄןÄijâ·t9ü·x⇩t#ü·x⇨tü·¶⇨t⑦ü·xÇt①ïא†å②Φë❎œ    ´å②ל!δ⓪ü·x⇨t
  47. Φ≥°ë⑥əΦת°â∙t⑥ïIJ=❎r=τ⇨w
  48. 3פ¨❎≈±ó⇧⇧3ijΦ╱∙ו╱④⇨B²ï④⇨2ΣΦø√2ΣΦ)∙;╱④⇨t⑨†H③Φ0❎†C③í④⇨Φ'❎´,③œ    ל!Θm⇧í④⇨-◆ú④⇨uזΦ©⇦Φא·t⇨ΘW⇧3ijΦd√ãÉΦd√Φã·u∈ã④Φ⌐°œ╱Φ©°<⇧t!´O③<⇩t①´n③<⇨t
  49. ´É③<❎t⇨´À③Pœ    ל!XΘ)⇧ã∮Φ+√Φw·t⇨Θ ⇧™⇩⇧ã⇦Φj°ו╱④⇨⇧œ╱Φx°½¯④⇨u⌠®⇩⇧¡=Zt+=\⇩t&=Z⇩t!=Z
  50. t⑥ï\◆♪ףt⑤†ÿ④Φ}⇦´ç④œ    ל!δ╱ה╱¼④⇧Éú②¡úα
  51. †⓪②¨Φ⇨Φ!⇦¡¡úל
  52. ¨
  53. †╱②Φ③⇦¡¡¡úי
  54. ≈&ל
  55. ≈&α
  56. ♪iju⇨ΘïP♪פt⇨Õ¯¯úה
  57. X¨✓≈±¨d†ך①ΦΣ⇨íי
  58. †∙①¨
  59. Φן⇨íə†≤①Φ ⇦á⇧⇧2Σïןעαעα⇨ב†<②¨Φ⇨Φ¨⇨´ך①œ    ל!á⇧⇧
  60. ijtəΦ7≈tה╱⇧⇧´②œ    ל!δ◆´<②œ    ל!Φ√⇩Ç>ז②ar♪á¼④4⇧ó¼④ΦΘ⇩´ה②œ    ל!δ2íə†`②Φº⇨œ    ´[②ל!Ç>⑨ u✓ה╱⑨⇧ΘÉ⇩_◆3ij&êE&ëE&îM⓪3ijבΦ⇨3ijΦן∙ã⓪Φן∙Φ$∙u8©«✓îזÄijÄן2ijó⇩⇨ó
  61. 3ijú¿④ú¬④ה╱⇨⇨™⇩⇧Õ⇧ú❎⇨í¿④ú◆⇨í¬④ú    ⇨Φש≈t⇩δéÇ>⇩⇨u~®⇩⇧ü¶ã⇧ל½us3פïäØ⇧≈ñœ⇧≈ñÀ⇧♪אta2ףïäØ⇧;╱ל
  62. t❎úל
  63. ø⇧ïäœ⇧;╱י
  64. t❎úי
  65. ø⇧ïäÀ⇧;╱α
  66. t❎úα
  67. ø⇧
  68. ףt.Φl⇩íα
  69. †Q④¨Φ⇨ΦÅ⇩íל
  70. †c④¨dΦâ⇩íי
  71. †n④¨dΦw⇩´:④œ    ל!®⇨ü<U¬t⇨Θá⇧®ij⇩™¡④¨@≤ñ®¡④á⇨⇨2Σעαעαעαעα⇨≡èD⇦
  72. iju①Ç>
  73. u◆´④③œ    ל!Θk⇧<⇧tT<⇦tP<╱t<❎u⇨Θ∙á⇩⇨2Σ¨
  74. †ץ③Φ⇩œ    ´ת③ל!Θ@⇧ïD ïT♪פuëF✓3ijëF⑤ëF⑦δ$ëF⑤ëV⑦3ijëF✓è⇦÷IJ⇩u⓪δ†ïD ëF✓3ijëF⑤ëF⑦³╱
  75. ΦJ⇧ïD✓ïT
  76. ⇨╱¿④③⑥¬④ëF①ëV③ú◆⇨ë⑥    ⇨™⇩⇧Õ⇧ú❎⇨Φx÷t⇩δ⑨á⇩⇧<Θt⇦<δuהF ⇧®⇧ﲨ≤ñá∞
  77. ⇩╱⇩⇨⇦Aó⇧③3פïF✓♪ijuïF⑤ïV⑦♪iju⇦♪פt❎¨✓≈±♪פt⇧@¨d†⇦③ΦH⇧´≤②œ    ל!³╱⇩⇨Ç>⇩⇨⓪w①³╱⇨⇨Ç>⇨⇨⇨w╱âד!Θכ³δ_ïD✓ïT
  78. ⇨╱¿④③⑥¬④ú¿④ë⑥¬④3פèD⇨èd⇩èץסגסגÇΣ⇨≈f≈fÇπ?³י2¯⇨בâפèL⇧
  79. חt
  80. ⇨Fâפ³חδ≥;╱¿④u╱;⑥¬④t◆ú¿④ë⑥¬④Θ«²_◆á
  81. iju⇩³ij&êEõ!÷β❎«✓&ëE&îM⓪&וE②&îM④Õ    ⇦ú⑧⇨3ijב®8⇧¨④™ז②Φ⇧ב¡Ç>¼④⇧t⇩åג½Γ≤בSQ3פïF✓♪ijuïF⑤ïV⑦♪פu⇦♪ijt-ø⇧♪פu❎=@r✓סπעΩעןδ∩=≈r❎¨⇧δ⇨¨U⇧≈±♪פt⇧@ëF♪ê^⇩Y[בîזÄij™«✓®®
  82. õ2ϕ≤ñâו⇩ü¯¥
  83. v∈בãhΦ⇨⌠¨⇦œ    ΦÃ÷3חœ    Φã÷ב3פê⑥ϕ④3פ≈±$✓╱ϕ④⇦0Ç>ϕ④u⇩ã ê◆CRïIJ3פ¨
  84. ≈±ïזXâ∙uשÇ>ϕ④u❎ã0êG¯בQR´⇦¨⇦צijïזâβâIJ0â∙9v⇨âIJ◆êCJuσZYב (c) 1991 Mountain Air Designs 
  85. Flash Drive software: Version 1.04A-S
  86. (C) 1991  BSE Company  Tustin, Calif. 
  87.  
  88. $XXX meg drive found: port xxxx
  89. xx sect/trk, XX heads, XXXX cyls
  90. $Power down mode not supported
  91. $XXXX second power down delay
  92. $Port XXXX not responding;
  93. load aborted.
  94. $XXXX: invalid port address.
  95. Using default port 8078 instead.
  96. $
  97. 1234567890123456789012345678901234567890
  98. $Logical drive x: xxx megabytes
  99. $No partitions defined
  100. $Interface test failed: xxxx xxxx
  101. $Diag. test: CONTROLLER ERROR
  102. $Diag. test: SECTOR BUFFER ERROR
  103. $Diag. test: CONTROL PROCESSOR ERROR
  104. $Diag. test: UNKNOWN TYPE ERROR
  105. $Unit xx : partition type is not
  106. compatible with this version of DOS
  107. $DOS version 2.x required.
  108. $Drive reconfigured for xxxx Cylinders, 
  109. xxx Heads, xxx Sectors per Track.
  110. $Drive signature: xxxx unknown.
  111. $k Stack Stack ⇧⇧Γ
  112. ª⇨»⇨    ⇦א⇨╱⇦╱⇦╱⇦ש⇨Ω⇨╱⇦╱⇦    ⇦.ë④.î╱⑥יPSQR╱WVU£ⁿîזÄןë&²î⑥¯·ÕⁿïαîזÄס√ג>④&è]⇩2¯:⑨~❎Õ⇨Çδ④עπ·Φ1⇧¯ù⑧⇨Φ<⇧√ג>④⇧&ëE⇨·í²ïαí¯Äס√¥]^_◆ZY[Xיã⇧&êE3ijבΦÄ⇦t⇧ב&ëm②îז&ëE④3ijבΦ{⇦t⇧בΦØ⇦&ג}Φ②⇩Φ[⇦בΦg⇦t⇧בΦß⇦&ג}Φ»⇩ΦG⇦בΦΘ¯t⇧בîזÄןג>④Φé⇦&ג}Φ (--pp > lp)       /* Move pattern down    */
  113.             *pp = pp[-1];        /* one byte             */
  114.          *pp =   (c == '*') ? STAR :
  115.             (c == '-') ? MINUS : PLUS;
  116.          pp = spp;               /* Restore pattern end  */
  117.          continue;
  118.       }
  119.       /*
  120.        * All the rest.
  121.        */
  122.       lp = pp;         /* Remember start       */
  123.       switch(c) {
  124.  
  125.       case '^':
  126.          store(BOL);
  127.          break;
  128.  
  129.       case '$':
  130.          store(EOL);
  131.          break;
  132.  
  133.       case '.':
  134.          store(ANY);
  135.          break;
  136.  
  137.       case '[':
  138.          s = cclass(source, s);
  139.          break;
  140.  
  141.       case ':':
  142.          if (*s) {
  143.             c = *s++;
  144.             switch(tolower(c)) {
  145.  
  146.             case 'a':
  147.             case 'A':
  148.                store(ALPHA);
  149.                break;
  150.  
  151.             case 'd':
  152.             case 'D':
  153.                store(DIGIT);
  154.                break;
  155.  
  156.             case 'n':
  157.             case 'N':
  158.                store(NALPHA);
  159.                break;
  160.  
  161.             case ' ':
  162.                store(PUNCT);
  163.                break;
  164.  
  165.             default:
  166.                badpat("Unknown : type", source, s);
  167.  
  168.             }
  169.             break;
  170.          }
  171.          else    badpat("No : type", source, s);
  172.  
  173.       case '\\':
  174.          if (*s)
  175.             c = *s++;
  176.  
  177.       default:
  178.          store(CHAR);
  179.          store(tolower(c));
  180.       }
  181.    }
  182.    store(ENDPAT);
  183.    store(0);                /* Terminate string     */
  184.    if (debug) {
  185.       for (lp = pbuf; lp < pp;) {
  186.          if ((c = (*lp++ & 0377)) < ' ')
  187.             printf("\\%o ", c);
  188.          else    printf("%c ", c);
  189.         }
  190.         printf("\n");
  191.    }
  192. }
  193.  
  194. /*******************************************************/
  195.  
  196. char *
  197. cclass(source, src)
  198. char       *source;   /* Pattern start -- for error msg.      */
  199. char       *src;      /* Class start           */
  200. /*
  201.  * Compile a class (within [])
  202.  */
  203. {
  204.    register char   *s;        /* Source pointer    */
  205.    register char   *cp;       /* Pattern start     */
  206.    register int    c;         /* Current character */
  207.    int             o;         /* Temp              */
  208.  
  209.    s = src;
  210.    o = CLASS;
  211.    if (*s == '^') {
  212.       ++s;
  213.       o = NCLASS;
  214.    }
  215.    store(o);
  216.    cp = pp;
  217.    store(0);                          /* Byte count      */
  218.    while ((c = *s++) && c!=']') {
  219.       if (c == '\\') {                /* Store quoted char    */
  220.          if ((c = *s++) == '\0')      /* Gotta get something  */
  221.             badpat("Class terminates badly", source, s);
  222.          else    store(tolower(c));
  223.       }
  224.       else if (c == '-' &&
  225.             (pp - cp) > 1 && *s != ']' && *s != '\0') {
  226.          c = pp[-1];             /* Range start     */
  227.          pp[-1] = RANGE;         /* Range signal    */
  228.          store(c);               /* Re-store start  */
  229.          c = *s++;               /* Get end char and*/
  230.          store(tolower(c));      /* Store it        */
  231.       }
  232.       else {
  233.          store(tolower(c));      /* Store normal char */
  234.       }
  235.    }
  236.    if (c != ']')
  237.       badpat("Unterminated class", source, s);
  238.    if ((c = (pp - cp)) >= 256)
  239.       badpat("Class too large", source, s);
  240.    if (c == 0)
  241.       badpat("Empty class", source, s);
  242.    *cp = c;
  243.    return(s);
  244. }
  245.  
  246. /*******************************************************/
  247.  
  248. store(op)
  249. {
  250.    if (pp >= &pbuf[PMAX])
  251.       error("Pattern too complex\n");
  252.    *pp++ = op;
  253. }
  254.  
  255.  
  256. /*******************************************************/
  257.  
  258. badpat(message, source, stop)
  259. char  *message;       /* Error message */
  260. char  *source;        /* Pattern start */
  261. char  *stop;          /* Pattern end   */
  262. {
  263.    register int    c;
  264.  
  265.    fprintf(stderr, "-GREP-E-%s, pattern is\"%s\"\n", message, source);
  266.    fprintf(stderr, "-GREP-E-Stopped at byte %d, '%c'\n",
  267.          stop-source, stop[-1]);
  268.    error("?GREP-E-Bad pattern\n");
  269. }
  270.  
  271.  
  272.  
  273. /*******************************************************/
  274.  
  275. grep(fp, fn)
  276. FILE       *fp;       /* File to process            */
  277. char       *fn;       /* File name (for -f option)  */
  278. /*
  279.  * Scan the file for the pattern in pbuf[]
  280.  */
  281. {
  282.    register int lno, count, m;
  283.  
  284.    lno = 0;
  285.    count = 0;
  286.    while (fgets(lbuf, LMAX, fp)) {
  287.       ++lno;
  288.       m = match();
  289.       if ((m && !vflag) || (!m && vflag)) {
  290.          ++count;
  291.          if (!cflag) {
  292.             if (fflag && fn) {
  293.                file(fn);
  294.                fn = 0;
  295.             }
  296.             if (nflag)
  297.                printf("%d\t", lno);
  298.             printf("%s\n", lbuf);
  299.          }
  300.       }
  301.    }
  302.    if (cflag) {
  303.       if (fflag && fn)
  304.          file(fn);
  305.       printf("%d\n", count);
  306.    }
  307. }
  308.  
  309.  
  310. /*******************************************************/
  311.  
  312. match()
  313. /*
  314.  * Match the current line (in lbuf[]), return 1 if it does.
  315.  */
  316. {
  317.    register char   *l;        /* Line pointer       */
  318.    char *pmatch();
  319.  
  320.    for (l = lbuf; *l; l++) {
  321.       if (pmatch(l, pbuf))
  322.          return(1);
  323.    }
  324.    return(0);
  325. }
  326.  
  327. /*******************************************************/
  328.  
  329. char *
  330. pmatch(line, pattern)
  331. char               *line;     /* (partial) line to match      */
  332. char               *pattern;  /* (partial) pattern to match   */
  333. {
  334.    register char   *l;        /* Current line pointer         */
  335.    register char   *p;        /* Current pattern pointer      */
  336.    register char   c;         /* Current character            */
  337.    char            *e;        /* End for STAR and PLUS match  */
  338.    int             op;        /* Pattern operation            */
  339.    int             n;         /* Class counter                */
  340.    char            *are;      /* Start of STAR match          */
  341.  
  342.    l = line;
  343.    if (debug > 1)
  344.       printf("pmatch(\"%s\")\n", line);
  345.    p = pattern;
  346.    while ((op = *p++) != ENDPAT) {
  347.       if (debug > 1)
  348.          printf("byte[%d] = 0%o, '%c', op = 0%o\n",
  349.                l-line, *l, *l, op);
  350.       switch(op) {
  351.  
  352.       case CHAR:
  353.          if (tolower(*l++) != *p++)
  354.             return(0);
  355.          break;
  356.  
  357.       case BOL:
  358.          if (l != lbuf)
  359.             return(0);
  360.          break;
  361.  
  362.       case EOL:
  363.          if (*l != '\0')
  364.             return(0);
  365.          break;
  366.  
  367.       case ANY:
  368.          if (*l++ == '\0')
  369.             return(0);
  370.          break;
  371.  
  372.       case DIGIT:
  373.          if ((c = *l++) < '0' || (c > '9'))
  374.             return(0);
  375.          break;
  376.  
  377.       case ALPHA:
  378.          c = tolower(*l++);
  379.          if (c < 'a' || c > 'z')
  380.             return(0);
  381.          break;
  382.  
  383.       case NALPHA:
  384.          c = tolower(*l++);
  385.          if (c >= 'a' && c <= 'z')
  386.             break;
  387.          else if (c < '0' || c > '9')
  388.             return(0);
  389.          break;
  390.  
  391.       case PUNCT:
  392.          c = *l++;
  393.          if (c == 0 || c > ' ')
  394.             return(0);
  395.          break;
  396.  
  397.       case CLASS:
  398.       case NCLASS:
  399.          c = tolower(*l++);
  400.          n = *p++ & 0377;
  401.          do {
  402.             if (*p == RANGE) {
  403.                p += 3;
  404.                n -= 2;
  405.                if (c >= p[-2] && c <= p[-1])
  406.                   break;
  407.             }
  408.             else if (c == *p++)
  409.                break;
  410.          } while (--n > 1);
  411.          if ((op == CLASS) == (n <= 1))
  412.             return(0);
  413.          if (op == CLASS)
  414.             p += n - 2;
  415.          break;
  416.  
  417.       case MINUS:
  418.          e = pmatch(l, p);       /* Look for a match    */
  419.          while (*p++ != ENDPAT); /* Skip over pattern   */
  420.          if (e)                  /* Got a match?        */
  421.             l = e;               /* Yes, update string  */
  422.          break;                  /* Always succeeds     */
  423.  
  424.       case PLUS:                 /* One or more ...     */
  425.          if ((l = pmatch(l, p)) == 0)
  426.             return(0);           /* Gotta have a match  */
  427.       case STAR:                 /* Zero or more ...    */
  428.          are = l;                /* Remember line start */
  429.          while (*l && (e = pmatch(l, p)))
  430.             l = e;               /* Get longest match   */
  431.          while (*p++ != ENDPAT); /* Skip over pattern   */
  432.          while (l >= are) {      /* Try to match rest   */
  433.             if (e = pmatch(l, p))
  434.                return(e);
  435.             --l;                 /* Nope, try earlier   */
  436.          }
  437.          return(0);              /* Nothing else worked */
  438.  
  439.       default:
  440.          printf("Bad op code %d\n", op);
  441.          error("Cannot happen -- match\n");
  442.       }
  443.    }
  444.    return(l);
  445. }
  446.  
  447. /*******************************************************/
  448.  
  449. error(s)
  450. char *s;
  451. {
  452.    fprintf(stderr, "%s", s);
  453.    exit(1);
  454. }
  455.  
  456. /*******************************************************/
  457.  
  458. #ifdef DeSmet
  459. fclose(file)
  460. FILE file;
  461. {
  462.      return(close(file));
  463. }
  464. #endif
  465. ə