home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / rcs57pc3.zip / rcs / src / ident.c < prev    next >
C/C++ Source or Header  |  1995-06-16  |  7KB  |  272 lines

  1. /* Identify RCS keyword strings in files.  */
  2.  
  3. /* Copyright 1982, 1988, 1989 Walter Tichy
  4.    Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
  5.    Distributed under license by the Free Software Foundation, Inc.
  6.  
  7. This file is part of RCS.
  8.  
  9. RCS is free software; you can redistribute it and/or modify
  10. it under the terms of the GNU General Public License as published by
  11. the Free Software Foundation; either version 2, or (at your option)
  12. any later version.
  13.  
  14. RCS is distributed in the hope that it will be useful,
  15. but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. GNU General Public License for more details.
  18.  
  19. You should have received a copy of the GNU General Public License
  20. along with RCS; see the file COPYING.
  21. If not, write to the Free Software Foundation,
  22. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23.  
  24. Report problems and direct all questions to:
  25.  
  26.     rcs-bugs@cs.purdue.edu
  27.  
  28. */
  29.  
  30. /*
  31.  * $Log: ident.c,v $
  32.  * Revision 5.9  1995/06/16 06:19:24  eggert
  33.  * Update FSF address.
  34.  *
  35.  * Revision 5.8  1995/06/01 16:23:43  eggert
  36.  * (exiterr, reportError): New functions, needed for DOS and OS/2 ports.
  37.  * (scanfile): Use them.
  38.  *
  39.  * Revision 5.7  1994/03/20 04:52:58  eggert
  40.  * Remove `exiting' from identExit.
  41.  *
  42.  * Revision 5.6  1993/11/09 17:40:15  eggert
  43.  * Add -V.
  44.  *
  45.  * Revision 5.5  1993/11/03 17:42:27  eggert
  46.  * Test for char == EOF, not char < 0.
  47.  *
  48.  * Revision 5.4  1992/01/24  18:44:19  eggert
  49.  * lint -> RCS_lint
  50.  *
  51.  * Revision 5.3  1991/09/10  22:15:46  eggert
  52.  * Open files with FOPEN_R, not FOPEN_R_WORK,
  53.  * because they might be executables, not working files.
  54.  *
  55.  * Revision 5.2  1991/08/19  03:13:55  eggert
  56.  * Report read errors immediately.
  57.  *
  58.  * Revision 5.1  1991/02/25  07:12:37  eggert
  59.  * Don't report empty keywords.  Check for I/O errors.
  60.  *
  61.  * Revision 5.0  1990/08/22  08:12:37  eggert
  62.  * Don't limit output to known keywords.
  63.  * Remove arbitrary limits and lint.  Ansify and Posixate.
  64.  *
  65.  * Revision 4.5  89/05/01  15:11:54  narten
  66.  * changed copyright header to reflect current distribution rules
  67.  * 
  68.  * Revision 4.4  87/10/23  17:09:57  narten
  69.  * added exit(0) so exit return code would be non random
  70.  * 
  71.  * Revision 4.3  87/10/18  10:23:55  narten
  72.  * Updating version numbers. Changes relative to 1.1 are actually relative
  73.  * to 4.1
  74.  * 
  75.  * Revision 1.3  87/07/09  09:20:52  trinkle
  76.  * Added check to make sure there is at least one arg before comparing argv[1]
  77.  * with "-q".  This necessary on machines that don't allow dereferncing null
  78.  * pointers (i.e. Suns).
  79.  * 
  80.  * Revision 1.2  87/03/27  14:21:47  jenkins
  81.  * Port to suns
  82.  * 
  83.  * Revision 4.1  83/05/10  16:31:02  wft
  84.  * Added option -q and input from reading stdin.
  85.  * Marker matching is now done with trymatch() (independent of keywords).
  86.  * 
  87.  * Revision 3.4  83/02/18  17:37:49  wft
  88.  * removed printing of new line after last file.
  89.  *
  90.  * Revision 3.3  82/12/04  12:48:55  wft
  91.  * Added LOCKER.
  92.  *
  93.  * Revision 3.2  82/11/28  18:24:17  wft
  94.  * removed Suffix; added ungetc to avoid skipping over trailing KDELIM.
  95.  *
  96.  * Revision 3.1  82/10/13  15:58:51  wft
  97.  * fixed type of variables receiving from getc() (char-->int).
  98. */
  99.  
  100. #include  "rcsbase.h"
  101.  
  102. static int match P((FILE*));
  103. static int scanfile P((FILE*,char const*,int));
  104. static void reportError P((char const*));
  105.  
  106. mainProg(identId, "ident", "$Id: ident.c,v 5.9 1995/06/16 06:19:24 eggert Exp $")
  107. /*  Ident searches the named files for all occurrences
  108.  *  of the pattern $@: text $ where @ is a keyword.
  109.  */
  110.  
  111. {
  112.    FILE *fp;
  113.    int quiet = 0;
  114.    int status = EXIT_SUCCESS;
  115.    char const *a;
  116.  
  117.    while ((a = *++argv)  &&  *a=='-')
  118.     while (*++a)
  119.         switch (*a) {
  120.         case 'q':
  121.             quiet = 1;
  122.             break;
  123.  
  124.         case 'V':
  125.             VOID printf("RCS version %s\n", RCS_version_string);
  126.             quiet = -1;
  127.             break;
  128.  
  129.         default:
  130.             VOID fprintf(stderr,
  131.             "ident: usage: ident -{qV} [file...]\n"
  132.             );
  133.             exitmain(EXIT_FAILURE);
  134.             break;
  135.         }
  136.  
  137.    if (0 <= quiet)
  138.        if (!a)
  139.         VOID scanfile(stdin, (char*)0, quiet);
  140.        else
  141.         do {
  142.         if (!(fp = fopen(a, FOPEN_RB))) {
  143.             reportError(a);
  144.             status = EXIT_FAILURE;
  145.         } else if (
  146.             scanfile(fp, a, quiet) != 0
  147.             || (argv[1]  &&  putchar('\n') == EOF)
  148.         )
  149.             break;
  150.         } while ((a = *++argv));
  151.  
  152.    if (ferror(stdout) || fclose(stdout)!=0) {
  153.       reportError("standard output");
  154.       status = EXIT_FAILURE;
  155.    }
  156.    exitmain(status);
  157. }
  158.  
  159. #if RCS_lint
  160. #    define exiterr identExit
  161. #endif
  162.     void
  163. exiterr()
  164. {
  165.     _exit(EXIT_FAILURE);
  166. }
  167.  
  168.     static void
  169. reportError(s)
  170.     char const *s;
  171. {
  172.     int e = errno;
  173.     VOID fprintf(stderr, "%s error: ", cmdid);
  174.     errno = e;
  175.     perror(s);
  176. }
  177.  
  178.  
  179.     static int
  180. scanfile(file, name, quiet)
  181.     register FILE *file;
  182.     char const *name;
  183.     int quiet;
  184. /* Function: scan an open file with descriptor file for keywords.
  185.  * Return -1 if there's a write error; exit immediately on a read error.
  186.  */
  187. {
  188.    register int c;
  189.  
  190.    if (name) {
  191.       VOID printf("%s:\n", name);
  192.       if (ferror(stdout))
  193.      return -1;
  194.    } else
  195.       name = "standard input";
  196.    c = 0;
  197.    while (c != EOF  ||  ! (feof(file)|ferror(file))) {
  198.       if (c == KDELIM) {
  199.      if ((c = match(file)))
  200.         continue;
  201.      if (ferror(stdout))
  202.         return -1;
  203.      quiet = true;
  204.       }
  205.       c = getc(file);
  206.    }
  207.    if (ferror(file) || fclose(file) != 0) {
  208.       reportError(name);
  209.       /*
  210.       * The following is equivalent to exit(EXIT_FAILURE), but we invoke
  211.       * exiterr to keep lint happy.  The DOS and OS/2 ports need exiterr.
  212.       */
  213.       VOID fflush(stderr);
  214.       VOID fflush(stdout);
  215.       exiterr();
  216.    }
  217.    if (!quiet)
  218.       VOID fprintf(stderr, "%s warning: no id keywords in %s\n", cmdid, name);
  219.    return 0;
  220. }
  221.  
  222.  
  223.  
  224.     static int
  225. match(fp)   /* group substring between two KDELIM's; then do pattern match */
  226.    register FILE *fp;
  227. {
  228.    char line[BUFSIZ];
  229.    register int c;
  230.    register char * tp;
  231.  
  232.    tp = line;
  233.    while ((c = getc(fp)) != VDELIM) {
  234.       if (c == EOF  &&  feof(fp) | ferror(fp))
  235.      return c;
  236.       switch (ctab[c]) {
  237.      case LETTER: case Letter:
  238.         *tp++ = c;
  239.         if (tp < line+sizeof(line)-4)
  240.            break;
  241.         /* fall into */
  242.      default:
  243.         return c ? c : '\n'/* anything but 0 or KDELIM or EOF */;
  244.       }
  245.    }
  246.    if (tp == line)
  247.       return c;
  248.    *tp++ = c;
  249.    if ((c = getc(fp)) != ' ')
  250.       return c ? c : '\n';
  251.    *tp++ = c;
  252.    while( (c = getc(fp)) != KDELIM ) {
  253.       if (c == EOF  &&  feof(fp) | ferror(fp))
  254.         return c;
  255.       switch (ctab[c]) {
  256.      default:
  257.         *tp++ = c;
  258.         if (tp < line+sizeof(line)-2)
  259.            break;
  260.         /* fall into */
  261.      case NEWLN: case UNKN:
  262.         return c ? c : '\n';
  263.       }
  264.    }
  265.    if (tp[-1] != ' ')
  266.       return c;
  267.    *tp++ = c;     /*append trailing KDELIM*/
  268.    *tp   = '\0';
  269.    VOID printf("     %c%s\n", KDELIM, line);
  270.    return 0;
  271. }
  272.