home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / n / bind / bind-4.001 / bind-4~ / bind-4.9.3-BETA9 / contrib / dnsparse / dnslex.c < prev    next >
C/C++ Source or Header  |  1994-04-08  |  6KB  |  262 lines

  1. #ifndef lint
  2. char rcsid_[] = "Id: dnslex.c,v 2.0 90/09/11 11:07:31 hakanson Rel $";
  3. char rcsid[] = "BIND $Id: dnslex.c,v 1.2 1994/04/09 03:43:03 vixie Exp $";
  4. #endif /* lint */
  5.  
  6. /*
  7.  * A lexical analyzer for DNS master files.
  8.  *   Marion Hakanson (hakanson@cse.ogi.edu)
  9.  *   Oregon Graduate Institute of Science and Technology
  10.  *
  11.  * Copyright (c) 1990, Marion Hakanson.
  12.  *
  13.  * You may distribute under the terms of the GNU General Public License
  14.  * as specified in the README file that comes with the dnsparse kit.
  15.  *
  16.  * This program accepts as input DNS master files, as described
  17.  * in RFC-1035.  It breaks up the input in such a way that a single
  18.  * resource record (RR) is output on a single line, with a delimiter
  19.  * character between each token (or field) of the RR.
  20.  *
  21.  * The output format was designed for consumption by programs such
  22.  * as awk or perl, so the delimiter character can be used to quickly
  23.  * split the RR into its components.
  24.  *
  25.  * It is likely that one could change the add_*char, end_word, and
  26.  * end_line macros to put chars into a separate buffer or perform
  27.  * some other function, and thus use do_dblex() inside a full parser
  28.  * program (such as a DNS server).
  29.  *
  30.  * One other thing.  This program could probably have been written
  31.  * in lex instead of C, but lex has a number of builtin limits to
  32.  * the length of expressions (where RFC-1035 does not, in all cases).
  33.  * I probably should have used flex instead, but the simple state
  34.  * machine below was not that tough to implement, and it's also
  35.  * pretty quick and pretty small.
  36.  */
  37.  
  38. #include <stdio.h>
  39.  
  40. #if !defined(SYSV) && !defined(__STDC__)
  41. #define strchr index    /* system dependent */
  42. #define strrchr index
  43. extern char *strchr(), *strrchr();
  44. #endif
  45.  
  46. extern getopt(), optind, opterr;
  47. extern char *optarg;
  48.  
  49. /*
  50.  *  Because Convex has true library function feof() which is
  51.  *  patently wrong (it test bit _IOREAD) we need feof() as
  52.  *  a macro.
  53.  *  Because also stdio.h is also broken on ConvexOS 10.2 we
  54.  *  don't get the macro. So we are left to our own devices
  55.  *  with it.
  56.  */
  57.  
  58. #if defined(__convex__) && !defined(feof)
  59. #  define   feof(p)    ((p)->_flag&_IOEOF)
  60. #endif
  61.  
  62. #define FALSE 0
  63. #define TRUE  1
  64.  
  65. /* Globals */
  66. char *prog;
  67.  
  68.  
  69. usage_and_die()
  70. {
  71.     fprintf(stderr, "usage: %s [-d <char>]\n", prog);
  72.     exit(1);
  73. }
  74.  
  75.  
  76.  
  77. /* Special (to DNS) chars we output in printed (non-decimal-escaped) form */
  78. #define SPECS " \t\n;()\\.@"    /* for consumption by strchr() */
  79. #define SPECP " \\t\\n;()\\.@"    /* for consumption by fprintf() */
  80.  
  81.  
  82. main(argc, argv)
  83.     int  argc;
  84.     char **argv;
  85. {
  86. int opt;
  87.  
  88. /* Defaults */
  89. register FILE    *ifile = stdin,
  90.         *ofile = stdout;
  91. char delim = ':';
  92.  
  93. if ( prog = strrchr(argv[0], '/') )
  94.     prog++;
  95. else
  96.     prog = argv[0];
  97.  
  98. /* Parse the arguments */
  99. opterr = 0;
  100. while ( (opt = getopt(argc, argv, "d:")) != EOF )
  101.     switch ((char)opt)
  102.     {
  103.     case '?':
  104.         usage_and_die();
  105.         break;
  106.     case 'd':
  107.         delim = *optarg;
  108.         break;
  109.     default:
  110.         /* Not supposed to happen. */
  111.         fprintf(stderr, "%s: Hey getopt(3)!  Wake up!\n", prog);
  112.         usage_and_die();
  113.         break;
  114.     }
  115.         
  116.  
  117. /* This saves checking every char output against delim */
  118. if ( strchr(SPECS, delim) != NULL ) {
  119.     fprintf(stderr, "%s: delimiter '%c' cannot be one of '%s'.\n",
  120.             prog, delim, SPECP);
  121.     exit(1);
  122. }
  123.  
  124. (void) do_dblex(ifile, ofile, delim);
  125.  
  126. exit(0);
  127. }
  128.  
  129.  
  130.  
  131. int
  132. do_dblex (ifile, ofile, delim)
  133.     register FILE *ifile, *ofile;
  134.     char delim;
  135. {
  136. register int c;
  137. register int newword = FALSE;
  138. register int wordlen = 0;
  139. register int linelen = 0;
  140. int inbrackets = FALSE;
  141. int inquotes = FALSE;
  142.  
  143. /* no delim after last word on a line */
  144. #define add_char(c) \
  145. ( \
  146.     (newword ? (newword = FALSE, putc(delim,ofile)) : 0), \
  147.     putc((c),ofile), \
  148.     wordlen++ \
  149. )
  150.  
  151. /* don't count the backslash, but do check for delim */
  152. #define add_esc_char(c) ( add_char('\\'), putc((c),ofile) )
  153. #define add_dec_char(c) ( add_char('\\'), fprintf(ofile,"%3.3d",(char)(c)) )
  154.  
  155. /* ignore empty words except at beginning of a line */
  156. #define end_word() \
  157. ( \
  158.     (wordlen > 0 || linelen == 0) ? ( \
  159.     newword = TRUE, \
  160.     wordlen = 0, \
  161.     linelen++ \
  162.     ) : (0) \
  163. )
  164.  
  165. /* no delim at beginning of line; ignore empty lines */
  166. #define end_line() \
  167. ( \
  168.     (wordlen > 0) ? linelen++ : (0), \
  169.     newword = FALSE, \
  170.     wordlen = 0, \
  171.     (linelen > 0) ? ( \
  172.     putc('\n', ofile), \
  173.     linelen = 0 \
  174.     ) : (0) \
  175. )
  176.  
  177.  
  178.  
  179. while ( ! feof(ifile) ) {
  180.  
  181.     c = getc(ifile);
  182.     switch (c) {
  183.     case EOF:
  184.         break;
  185.     case ' ':
  186.     case '\t':
  187.         if ( inquotes )
  188.         add_esc_char(c);
  189.         else {
  190.         end_word();
  191.         while ( (c = getc(ifile)) != EOF && (c == ' ' || c == '\t') );
  192.         ungetc(c, ifile);
  193.         }
  194.         break;
  195.     case '\n':
  196.         if ( inquotes )
  197.         ; /* do nothing */
  198.         else if ( inbrackets )
  199.         end_word();
  200.         else
  201.         end_line();
  202.         break;
  203.     case ';':
  204.         if ( inquotes )
  205.         add_esc_char(c);
  206.         else {
  207.         if ( ! inbrackets )
  208.             end_line();
  209.         while ( (c = getc(ifile)) != EOF && c != '\n' ); /* skip */
  210.         }
  211.         break;
  212.     case '"':
  213.         if ( inquotes )
  214.         inquotes = FALSE;
  215.         else
  216.         inquotes = TRUE;
  217.         break;
  218.     case '(':
  219.         if ( inbrackets || inquotes )
  220.         add_esc_char(c);
  221.         else {
  222.         inbrackets = TRUE;
  223.         end_word();
  224.         }
  225.         break;
  226.     case ')':
  227.         if ( inbrackets && (! inquotes) ) {
  228.         inbrackets = FALSE;
  229.         end_word();
  230.         } else
  231.         add_esc_char(c);
  232.         break;
  233.     case '\\':
  234.         if ( (c = getc(ifile)) == EOF ) {
  235.         add_esc_char('\\');
  236.         end_line();
  237.         } else if ( c == '\n' ) {
  238.         if ( ! inquotes )
  239.             end_word();
  240.         } else if ( c == delim )
  241.         add_dec_char(c);    /* no delims inside fields */
  242.         else
  243.         add_esc_char(c);
  244.         break;
  245.     case '.':
  246.     case '@':
  247.         if ( inquotes )
  248.         add_esc_char(c);
  249.         else
  250.         add_char(c);
  251.         break;
  252.     default:
  253.         if ( c == delim )
  254.         add_dec_char(c);    /* no delims inside fields */
  255.         else
  256.         add_char(c);
  257.     }
  258. }
  259.  
  260. }
  261.  
  262.