home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 1 / crawlyvol1.bin / program / compiler / nasm20b / nasm_src / crlf155.c < prev    next >
C/C++ Source or Header  |  1993-01-19  |  20KB  |  848 lines

  1. /* MEMO: tried TABCHAR stuff, for various files */
  2. #define LASTDITCH 1
  3. /* ---------------------------------------------------------------------- */
  4. /*                   Copyright (C) 1992 by Natürlich!                  */
  5. /*                      This file is copyrighted!                         */
  6. /*                Refer to the documentation for details.                 */
  7. /* ---------------------------------------------------------------------- */
  8. /* rev. history   1.0 --                                      */
  9. /*                1.1 --                                      */
  10. /*                1.2 --                                      */
  11. /*                1.3 -- got a bit more userfriendly          */
  12. /*                1.4 -- bug fix ?                            */
  13. /*                1.5 -- merged with tos_unix                 */
  14. /*                1.6 -- fixed little masking bug in <mode>   */
  15. /*                       different tabchar                    */
  16. /*                       last ditch code added                */
  17. /*                1.7 -- increased portability                */
  18. /*                       time date setting for everyone       */
  19. /* ---------------------------------------------------------- */
  20. #include "defines.h"
  21. #undef VERSION
  22. #undef REVISION
  23. #define VERSION   1
  24. #define REVISION  7
  25.  
  26. #include <stdio.h>
  27. #include <ctype.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include OSBIND
  31. #include "nasm.h"
  32.  
  33. #ifndef __hp9000s300
  34. # define MALLOCING 1
  35. #endif
  36.  
  37. #if OS == AMIGA || defined( SUN)
  38. # include <utime.h>
  39. #endif
  40.  
  41. #if OS == MSDOS && __TURBOC__
  42. # define perror( s)  fputs( s, stderr)
  43. #endif
  44.  
  45. #if OS == TOS || OS == MSDOS
  46. # if OS == TOS 
  47. #  include <ext.h>      /* for stat */
  48. # endif
  49. static struct ffblk  fbuf;
  50. #endif
  51.  
  52. #if OS == TOS
  53. # define LOSER()     keypress()
  54.   int   tossable;
  55.   void  keypress()
  56.   {
  57.      if( tossable)
  58.      {
  59.         while( Bconstat( 2))
  60.            Bconin( 2);
  61.         Bconin( 2);
  62.      }
  63.   }
  64.  
  65. # ifdef __TURBOC__      /* PUREC fouls up too */
  66. #  define stat( x, y)   mystat( y)
  67.  
  68.    void  mystat( p)
  69.    struct stat *p;
  70.    {
  71.       p->st_size = fbuf.ff_fsize;
  72.       p->st_mtime = *(long *) &fbuf.ff_ftime;   /* sorta hackish */
  73.    }
  74. # endif   
  75. #else
  76. # define LOSER()
  77. #endif
  78.  
  79.  
  80.  
  81. #ifdef __TURBOC__
  82. # define off_t    slword
  83. #endif
  84.  
  85.  
  86.  
  87. #if LASTDITCH
  88. # if OS == TOS || OS == MSDOS
  89.    static char ditch[ 128]  = "f:\\tmp\\";
  90. #  define DIR_SLASH '\\'
  91. # else
  92.    static char ditch[ 128] = "/tmp/";
  93. #  define DIR_SLASH '/'
  94. # endif
  95.  
  96.  
  97. void last_ditch( to_file, abuffer, size)
  98. char      *to_file;
  99. void huge *abuffer;
  100. lword     size;
  101. {
  102.    int   fd;
  103.    char  *z;
  104.  
  105.    strcat( ditch, (z = strrchr( to_file, DIR_SLASH)) ? z + 1 : to_file);
  106.    if( (fd = (int) Fkreate( ditch, 0644)) >= 0)
  107.    {
  108. # if OS == /* fucking */ MSDOS
  109.       _fmode = O_BINARY;
  110. # endif
  111.       Fwrite( fd, size, abuffer);
  112.       Fclose( fd);
  113.       fprintf( stderr, "*** Backup in \"%s\" ***\n", ditch);
  114.    }
  115. }
  116. #else
  117. # define last_ditch( x, y, z)
  118. #endif
  119.  
  120.  
  121. void nerror( s)
  122. char  *s;
  123. {
  124.    static char   buf[256];
  125.  
  126.    sprintf( buf, "crlf155: Error \"%s\"\n", s);
  127.    perror( buf);
  128.    LOSER();
  129.    exit(1);
  130. }
  131.  
  132. void nserror( s, t)
  133. char   *s, *t;
  134. {
  135.    static char   buf[256];
  136.  
  137.    sprintf( buf, s, t);
  138.    nerror( buf);
  139. }
  140.  
  141.  
  142.  
  143. #define MAXBUF  0x40000    /* sorry but the fucking HP malloc commits */
  144.                            /* suicide when fragmenting ... (or what ?)*/
  145. #if ! MALLOCING
  146. static char foobuf[ MAXBUF],
  147.             memerr2[] = "static buffer too small, recompile!";
  148. #endif
  149. static char huge *p;
  150. static char memerr1[] = "out of memory",
  151.             blurb[] =
  152. {
  153. 'c','r','l','f','1','5','5',' ','v',VERSION+'0','.',REVISION+'0',' ',
  154. '(','c',')',' ','1','9','9','2',' ','b','y',' ',
  155. 'N','a','t','u','e','r','l','i','c','h','!',
  156. ' ','-','-',' ','c','o','n','v','e','r','t','s',' ',
  157. #if OS == UNIX || AMIGA
  158.         'C','R','/','L','F',' ','t','o',' ','L','F',
  159. #else
  160.         'L','F',' ','t','o',' ','C','R','/','L','F',
  161. #endif
  162.          ' ','a','n','d',' ','m','o','r','e','.','.','.','\n'
  163. };
  164.  
  165. #if OS == TOS || OS == MSDOS
  166. # define UNIX_TOS    0
  167. # define TOS_UNIX    4
  168. # else
  169. # define TOS_UNIX    0
  170. # define UNIX_TOS    4
  171. #endif
  172.  
  173. #define ATARI_UNIX   1
  174. #define ATARI_TOS    2
  175. #define UNIX_ATARI   5
  176. #define TOS_ATARI    6
  177.  
  178.  
  179. FILE  *fp, *fq, *fopen();
  180. int   fd,
  181.       showstuff,
  182.       mode,
  183.       untabify,
  184.       tabchar,
  185.       eliminate,
  186.       tabs     = -1,
  187.       xtabc    = -1,
  188.       hardtabs = 1,
  189.       unmatched= 1;
  190.  
  191.  
  192. char huge *atari_tos( size)
  193. register lword size;
  194. {
  195.    register byte huge *q;
  196.  
  197. #if MALLOCING
  198.    if( ! (p = Malloc( size + size)))
  199.       nerror( memerr1);
  200. #else
  201.    if( size >= MAXBUF)
  202.       nerror( memerr2);
  203. #endif
  204.  
  205.    for( q = (byte huge *) p; size--;)
  206.    if( (*q++ = getc( fp)) == 155)
  207.    {
  208.       q[ -1] = '\r';
  209.       *q++   = '\n';
  210.    }
  211.    return( (char huge *) q);
  212. }
  213.  
  214.  
  215. char huge *atari_unix( size)
  216. register lword size;
  217. {
  218.    register byte  *q;
  219.    register int   c;
  220.  
  221. #if MALLOCING
  222.    if( ! (p = Malloc( size)))
  223.       nerror( memerr1);
  224. #else
  225.    if( size >= MAXBUF)
  226.       nerror( memerr2);
  227. #endif
  228.    for( q = (byte huge *) p; size--;)
  229.       *q++ = ((c = getc( fp)) == 155) ? '\n' : c;
  230.    return( (char huge *) q);
  231. }
  232.  
  233.  
  234. char huge *tos_atari( size)
  235. register lword   size;
  236. {
  237.    register char huge *q;
  238.  
  239. #if MALLOCING
  240.    if( ! (p = Malloc( size)))
  241.       nerror( memerr1);
  242. #else
  243.    if( size >= MAXBUF)
  244.       nerror( memerr2);
  245. #endif
  246.    for( q = p; size--;)
  247.       if( (*q++ = getc( fp)) == '\r' &&
  248.          (size-- ? ((*q++ = getc( fp)) == '\n') : (size = 0)))
  249.          q--[ -2] = 155;
  250.    return( q);
  251. }
  252.  
  253.  
  254. char huge *unix_atari( size)
  255. register lword size;
  256. {
  257.    register char huge  *q;
  258.    register int        c;
  259.  
  260. #if MALLOCING
  261.    if( ! (p = Malloc( (lword) size)))
  262.       nerror( memerr1);
  263. #else
  264.    if( size + size >= MAXBUF)
  265.       nerror( memerr2);
  266. #endif
  267.    for( q = p; size--;)
  268.       *q++ = (c = getc( fp)) == '\n' ? 155 : c;
  269.    return( q);
  270. }
  271.  
  272.  
  273. char huge   *none( size)
  274. register lword size;
  275. {
  276.    register char huge  *q;
  277.  
  278. #if MALLOCING
  279.    if( ! (p = Malloc( (lword) size)))
  280.       nerror( memerr1);
  281. #else
  282.    if( size + size >= MAXBUF)
  283.       nerror( memerr2);
  284. #endif
  285.    for( q = p; size--;)
  286.       *q++ = getc( fp);
  287.    return( q);
  288. }
  289.  
  290.  
  291.  
  292. char huge *unix_tos( size)
  293. lword size;
  294. {
  295.    register char huge *q;
  296.    register int       c;
  297.  
  298. #if MALLOCING
  299.    if( ! (p = Malloc( (lword) (size + size))))
  300.       nerror( memerr1);
  301. #else
  302.    if( size + size >= MAXBUF)
  303.       nerror( memerr2);
  304. #endif
  305.    for( q = p, c = 'a'; c != EOF;)
  306.       if( (*q++ = c = getc( fp)) == '\n')
  307.       {
  308.          q[ -1] = '\r';
  309.          *q++ = '\n';
  310.       }
  311.    return( q - 1);
  312. }
  313.  
  314.  
  315. char huge *tos_unix( size)
  316. lword size;
  317. {
  318.    register char huge *q;
  319.    register int       c;
  320.  
  321. #if MALLOCING
  322.    if( ! (p = Malloc( (lword) size)))
  323.       nerror( memerr1);
  324. #else
  325.    if( size >= MAXBUF)
  326.       nerror( memerr2);
  327. #endif
  328.    if( eliminate)
  329.    {
  330.       for( q = p, c = 'a'; c != EOF;)
  331.       {
  332.          while( (c = getc( fp)) == 032);
  333. #if OS == UNIX || AMIGA
  334.          if( (*q++ = c) == '\r' &&
  335.             (q[-1] = getc( fp)) != '\n')
  336.          {
  337.             *q = q[-1];
  338.             q[ -1] = c;
  339.             c = *q;
  340.          }
  341. #else
  342.          *q++ = c;
  343. #endif
  344.       }
  345.    }
  346.    else
  347.       for( q = p, c = 'a'; c != EOF;)
  348. #if OS == UNIX || AMIGA
  349.          if( (*q++ = c = getc( fp)) == '\r' &&
  350.             (q[-1] = getc( fp)) != '\n')
  351.          {
  352.             *q = q[-1];
  353.             q[ -1] = c;
  354.             c = *q;
  355.          }
  356. #else
  357.          *q++ = c = getc( fp);
  358. #endif
  359.    return( q - 1);
  360. }
  361.  
  362.  
  363. void  do_it( to_file)
  364. char  *to_file;
  365. {
  366.    off_t              size, oldsize;
  367.    struct stat        sbuf;
  368.    register char huge *q;
  369.    register lword     y;
  370.  
  371. #if ! MALLOCING
  372.    p = foobuf;
  373. #endif
  374.    if( q = getenv( "TMPDIR"))
  375.       strcpy( ditch, (char *) q);
  376.    if( ! (fp = fopen( to_file, (mode & 0xB) ? "rb" : "r" )))
  377.       nserror("File open of \"%s\" failed", to_file);
  378.    stat( to_file, &sbuf);
  379.  
  380.    if( ! (oldsize = sbuf.st_size))
  381.    {
  382.       printf("File \"%s\" is empty\n", to_file);
  383.       return;
  384.    }
  385.    if( showstuff)
  386.    {
  387.       printf("Converting \"%s\" with %ld bytes ", to_file, (long) oldsize);
  388.       fflush( stdout);
  389.    }
  390.  
  391.    if( (size_t) oldsize != (off_t) oldsize)
  392.       nerror("runtime: conversion problem");
  393.  
  394.    switch( mode)
  395.    {
  396.       default :
  397.          q = none( oldsize);
  398.          break;
  399.  
  400.       case UNIX_TOS :
  401.          q = unix_tos( oldsize);
  402.          break;
  403.  
  404.       case TOS_UNIX :
  405.          q = tos_unix( oldsize);
  406.          break;
  407.  
  408.       case ATARI_UNIX:
  409.          q = atari_unix( oldsize);
  410.          break;
  411.  
  412.       case UNIX_ATARI:
  413.          q = unix_atari( oldsize);
  414.          break;
  415.  
  416.       case TOS_ATARI:
  417.          q = tos_atari( oldsize);
  418.          break;
  419.  
  420.       case ATARI_TOS:
  421.          q = atari_tos( oldsize);
  422.    }
  423.    fclose( fp);
  424.  
  425.    size = (off_t) ( q - p);
  426.    if( untabify)
  427.       for( q = p, y = size; *q++ != tabchar && y; y--);
  428.  
  429.    if( untabify && y)
  430.    {
  431.       register lword    i, len;
  432.       register int      j, c;
  433.  
  434.       if( ! (fq = fopen( to_file, "wb")))
  435.          nserror("Opening of \"%s\" failed", to_file);
  436.       if( hardtabs)     /* won't expand last char in file */
  437.          for( q = p, i = len = 0, j = tabs; i != size - 1; i++)
  438.             if( (c = *q++) != tabchar)
  439.             {
  440.                if( putc( c, fq) == '\n' || ! --j)
  441.                   j = tabs;
  442.                len++;
  443.             }
  444.             else
  445.             {
  446.                while( j)
  447.                {
  448.                   putc( ' ', fq);
  449.                   len++;
  450.                   j--;
  451.                }
  452.                j = tabs;
  453.             }
  454.       else
  455.          for( q = p, len = i = 0; i != size - 1; i++)
  456.          {
  457.             if( (c = *q++) != tabchar)
  458.             {
  459.                putc( c, fq);
  460.                len++;
  461.             }
  462.             else
  463.                for( j = tabs; j; putc( ' ', fq), len++, j--);
  464.          }
  465.  
  466.       if( putc( *q, fq) == EOF)
  467.       {
  468.          fclose( fq);
  469.          last_ditch( to_file, p, size);
  470.          nerror("write failed");
  471.       }
  472.       if( showstuff)
  473.          printf("%s to %ld bytes\n", (len > oldsize) ? "up" : "down",
  474.                                         (long) len);
  475.       fclose( fq);
  476.    }
  477.    else
  478.       if( (mode & 0x3) || size != oldsize)
  479.       {
  480.          if( (fd = (int) Fkreate( to_file, 0644)) < 0)
  481.             nserror("Creation of \"%s\" failed", to_file);
  482. #if OS == /* fucking */ MSDOS
  483.          _fmode = O_BINARY;
  484. #endif
  485.          if( showstuff)
  486.             printf("%s to %ld bytes\n", (size > oldsize) ? "up" : "down",
  487.                                 (long) size);
  488.          if( size != Fwrite( fd, size, p))
  489.          {
  490.             Fclose( fd);
  491.             last_ditch( to_file, p, size);
  492.             nerror("write failed");
  493.          }
  494.          Fclose( fd);
  495.       }
  496.       else
  497.       {
  498.          if( showstuff)
  499.             puts( "to equal size. [no update]");
  500.         goto free_em;
  501.       }
  502.         /* due to CLOSE writing the creation date, we got to do this */
  503.  
  504. #if OS == TOS
  505.    if( (fd = (int) Fopen( to_file, 0)) < 0)
  506.       fprintf( stderr, "Someone snarfed your output file (not me!)\n");
  507.    else
  508.    {
  509.       Fdatime( (DOSTIME *) &sbuf.st_mtime, fd, 1);
  510.       Fclose( fd);
  511.    }
  512. #else
  513.    {
  514.       struct utimbuf  time;
  515.  
  516.       time.actime  = sbuf.st_atime;
  517.       time.modtime = sbuf.st_mtime;
  518.       if( utime( to_file, &time))
  519.          nserror("Timestamp update failed on \"%s\"", to_file);
  520.    }
  521. #endif           
  522. free_em:
  523. #if MALLOCING
  524.    Mfree( (void *) p)
  525. #endif
  526.    ;
  527. }
  528.  
  529.  
  530. main( argc, argv)
  531. int   argc;
  532. char  **argv;
  533. {
  534.    int   i = 0,
  535.          foo;
  536.  
  537.    if( argc == 1)
  538.       goto usage;
  539.    while( ++i < argc)
  540.    {
  541.       if( *argv[ i] == '-')
  542.          switch( argv[ i][ 1])
  543.          {
  544. #ifdef __DATE__
  545.             case ':' :
  546.                fputs( __DATE__, stderr);
  547. # ifdef __TIME__
  548.                fprintf( stderr, " %s", __TIME__);
  549. # endif
  550.                putc( '\n', stderr);
  551.                break;
  552. #endif
  553. #if OS == TOS
  554.             case 'T' :
  555.             case 't' :
  556.                tossable = ! tossable;
  557.                break;
  558. #endif
  559.             case 'V' :  /* at runtime would be better, but more painful */
  560.             case 'v' :  /* to code */
  561.                fputs( blurb, stderr);
  562.                break;
  563.  
  564.             case 'h' :
  565.             case 'H' :
  566.                hardtabs = ! hardtabs;
  567.                break;
  568.  
  569.        case 'z' :
  570.             case 'Z' :
  571.           eliminate = ! eliminate;
  572.           break;
  573.  
  574.             case 'a' :
  575.             case 'A' :
  576.                mode = (mode & 0xFC) | ATARI_UNIX;
  577.                break;
  578.             
  579.             case 'x' :
  580.             case 'X' :
  581.                mode = (mode & 0xFC) | ATARI_TOS;
  582.                break;
  583.  
  584.             case 'b' :
  585.             case 'B' :
  586.                mode ^= UNIX_TOS | TOS_UNIX;
  587.                break;
  588.  
  589.             case 'u' :
  590.             case 'U' :
  591.                untabify = ! untabify;
  592.                if( argv[ i][ 2] && sscanf( &argv[ i][ 2],"%X", &foo))
  593.                   tabs = foo;
  594.                break;
  595.  
  596.             case 's' :
  597.             case 'S' :
  598.                showstuff = ! showstuff;
  599.                break;
  600.  
  601.             case 'N' :
  602.             case 'n' :
  603.                mode ^= 0x8;
  604.                break;
  605.  
  606.             case 'C' :
  607.             case 'c' :
  608.             {
  609.                unsigned char  d = argv[ i][ 2];
  610.                
  611.                if( d == '\\')
  612.                   switch( argv[ i][ 2])
  613.                   {
  614.                      case 't' :
  615.                         d = '\t';
  616.                         break;
  617.                         
  618.                      case 'r' :
  619.                         d = '\r';
  620.                         break;
  621.  
  622.                      case 'b' :
  623.                         d = '\b';
  624.                         break;
  625.  
  626.                      case 'n' :
  627.                         d = '\b';
  628.                         break;
  629.  
  630.                      default  :
  631.                         goto usage;
  632.                   }                      
  633.                else
  634.                   if( d >= '0' && d <= '9')
  635.                      d = (char) atoi( &argv[ i][ 2]);
  636.                xtabc = d;
  637.                break;
  638.             }
  639.                                         
  640.             default  :
  641.                goto usage;
  642.          }
  643.       else
  644.       {
  645.          static char xbuf[ 256];
  646.          static char fname[ 13];
  647.          char        *p, *q;
  648.  
  649.          if( tabs < 0)
  650.             tabs = (mode == TOS_UNIX || mode == TOS_ATARI) ? 3 : 8;
  651.          tabchar = (xtabc < 0) 
  652.                      ? ((mode == ATARI_UNIX || mode == ATARI_TOS) 
  653.                            ? 127 : '\t') 
  654.                      : xtabc;
  655.  
  656. #if OS == TOS || OS == MSDOS     /* if findfirst works */
  657.          q = argv[ i];
  658.          p = xbuf;
  659.          strcpy( p, q);
  660.          if( ! (p = strrchr( q, '\\')))
  661.             p = xbuf;
  662.          else
  663.             p = xbuf + (int) ((q = p + 1) - argv[ i]);
  664.          strcpy( p, "*.*");
  665.          if( findfirst( xbuf, &fbuf, 0)) /* only normal files ? */
  666.             nserror("Directory search failed for \"%s\"", xbuf);
  667.          {
  668.             register char  *x, *y;
  669.  
  670.             do
  671.             {
  672.                for( x = fbuf.ff_name, y = fname; *x; y++, x++)
  673.                   *y = tolower( *x);
  674.                *y = 0;
  675.  
  676.                if( wildmat( fname, q))
  677.                {
  678.                   unmatched = 0;
  679.                   strcpy( p, fname);
  680.                   do_it( xbuf);
  681.                }
  682.             }
  683.             while( ! findnext( &fbuf));
  684.     }
  685. #else
  686.          do_it( argv[ i]);
  687.     unmatched = 0;
  688. #endif
  689.       }
  690.    }
  691.    return( unmatched);
  692.  
  693. usage:
  694.    fputs( "\
  695. usage: crlf155 ([flags] <pattern>)+\n\
  696. \t-a\t: convert 155 to LF\n\
  697. \t-n\t: just untabify\n\
  698. \t-x\t: convert 155 to CR/LF\n\
  699. \t-c<chr>\t: tab character\n\
  700. \t-h\t: no hardtabs\n\
  701. \t-z\t: eliminates ^Zs from MSDOS files\n\
  702. \t-b\t: backwards, change conversion direction, f.e. LF to 155\n\
  703. \t-u[val]\t: untabify, default spaces: TOS->UNIX : 3, UNIX->TOS : 8\n\
  704. \t-s\t: show some statistics for user amusement\n", stderr);
  705.  
  706. #if OS == TOS
  707.    fputs( "\
  708. \t-t\t: halt screen before exiting\n\n\
  709. \t\t* Warning: filenames and patterns: all lowercase!\n\
  710. \t\t  *.C won't work, *.c will\n", stderr);
  711. #endif
  712.    fputs( "\n\
  713. \t\t  Insure that there is enough discspace, else one file might\n\
  714. \t\t  get truncated\n", stderr);
  715.    LOSER();
  716.    exit(1);
  717. }
  718.  
  719. #if OS != UNIX
  720. /*  $Revision: 1.7 $
  721. **
  722. **  Do shell-style pattern matching for ?, \, [], and * characters.
  723. **  Might not be robust in face of malformed patterns; e.g., "foo[a-"
  724. **  could cause a segmentation violation.  It is 8bit clean.
  725. **
  726. **  Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
  727. **  Rich $alz is now <rsalz@bbn.com>.
  728. **  April, 1991:  Replaced mutually-recursive calls with in-line code
  729. **  for the star character.
  730. **
  731. **  Special thanks to Lars Mathiesen <thorinn@diku.dk> for the ABORT code.
  732. **  This can greatly speed up failing wildcard patterns.  For example:
  733. **      pattern: -*-*-*-*-*-*-12-*-*-*-m-*-*-*
  734. **      text 1:  -adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1
  735. **      text 2:  -adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1
  736. **  Text 1 matches with 51 calls, while text 2 fails with 54 calls.  Without
  737. **  the ABORT, then it takes 22310 calls to fail.  Ugh.  The following
  738. **  explanation is from Lars:
  739. **  The precondition that must be fulfilled is that DoMatch will consume
  740. **  at least one character in text.  This is true if *p is neither '*' nor
  741. **  '\0'.)  The last return has ABORT instead of FALSE to avoid quadratic
  742. **  behaviour in cases like pattern "*a*b*c*d" with text "abcxxxxx".  With
  743. **  FALSE, each star-loop has to run to the end of the text; with ABORT
  744. **  only the last one does.
  745. **
  746. **  Once the control of one instance of DoMatch enters the star-loop, that
  747. **  instance will return either TRUE or ABORT, and any calling instance
  748. **  will therefore return immediately after (without calling recursively
  749. **  again).  In effect, only one star-loop is ever active.  It would be
  750. **  possible to modify the code to maintain this context explicitly,
  751. **  eliminating all recursive calls at the cost of some complication and
  752. **  loss of clarity (and the ABORT stuff seems to be unclear enough by
  753. **  itself).  I think it would be unwise to try to get this into a
  754. **  released version unless you have a good test data base to try it out
  755. **  on.
  756. */
  757.  
  758. #define TRUE                    1
  759. #define FALSE                   0
  760. #define ABORT                   -1
  761.  
  762.  
  763.     /* What character marks an inverted character class? */
  764. #define NEGATE_CLASS            '^'
  765.     /* Is "*" a common pattern? */
  766. #define OPTIMIZE_JUST_STAR
  767.     /* Do tar(1) matching rules, which ignore a trailing slash? */
  768. #undef MATCH_TAR_PATTERN
  769.  
  770.  
  771. /*
  772. **  Match text and p, return TRUE, FALSE, or ABORT.
  773. */
  774. static int
  775. DoMatch(text, p)
  776.     char        *text;
  777.     char        *p;
  778. {
  779.     int last;
  780.     int matched;
  781.     int reverse;
  782.  
  783.     for ( ; *p; text++, p++) {
  784.         if (*text == '\0' && *p != '*')
  785.             return ABORT;
  786.         switch (*p) {
  787.         case '\\':
  788.             /* Literal match with following character. */
  789.             p++;
  790.             /* FALLTHROUGH */
  791.         default:
  792.             if (*text != *p)
  793.                 return FALSE;
  794.             continue;
  795.         case '?':
  796.             /* Match anything. */
  797.             continue;
  798.         case '*':
  799.             while (*++p == '*')
  800.                 /* Consecutive stars act just like one. */
  801.                 continue;
  802.             if (*p == '\0')
  803.                 /* Trailing star matches everything. */
  804.                 return TRUE;
  805.             while (*text)
  806.                 if ((matched = DoMatch(text++, p)) != FALSE)
  807.                     return matched;
  808.             return ABORT;
  809.         case '[':
  810.             reverse = p[1] == NEGATE_CLASS ? TRUE : FALSE;
  811.             if (reverse)
  812.                 /* Inverted character class. */
  813.                 p++;
  814.             for (last = 0400, matched = FALSE; *++p && *p != ']'; last = *p)
  815.                 /* This next line requires a good C compiler. */
  816.                 if (*p == '-' ? *text <= *++p && *text >= last : *text == *p)
  817.                     matched = TRUE;
  818.             if (matched == reverse)
  819.                 return FALSE;
  820.             continue;
  821.         }
  822.     }
  823.  
  824. #ifdef  MATCH_TAR_PATTERN
  825.     if (*text == '/')
  826.         return TRUE;
  827. #endif  /* MATCH_TAR_ATTERN */
  828.     return *text == '\0';
  829. }
  830.  
  831.  
  832. /*
  833. **  User-level routine.  Returns TRUE or FALSE.
  834. */
  835. int
  836. wildmat(text, p)
  837.     char        *text;
  838.     char        *p;
  839. {
  840. #ifdef  OPTIMIZE_JUST_STAR
  841.     if (p[0] == '*' && p[1] == '\0')
  842.         return TRUE;
  843. #endif  /* OPTIMIZE_JUST_STAR */
  844.     return DoMatch(text, p) == TRUE;
  845. }
  846. #endif
  847.  
  848.