Merge from vendor branch BIND:
[dragonfly.git] / contrib / dhcp-3.0 / common / conflex.c
1 /* conflex.c
2
3    Lexical scanner for dhcpd config file... */
4
5 /*
6  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
7  * Copyright (c) 1995-2003 by Internet Software Consortium
8  *
9  * Permission to use, copy, modify, and distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
16  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  *
21  *   Internet Systems Consortium, Inc.
22  *   950 Charter Street
23  *   Redwood City, CA 94063
24  *   <info@isc.org>
25  *   http://www.isc.org/
26  *
27  * This software has been written for Internet Systems Consortium
28  * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29  * To learn more about Internet Systems Consortium, see
30  * ``http://www.isc.org/''.  To learn more about Vixie Enterprises,
31  * see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
32  * ``http://www.nominum.com''.
33  */
34
35 #ifndef lint
36 static char copyright[] =
37 "$Id: conflex.c,v 1.92.2.9 2004/11/24 17:39:15 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
38 #endif /* not lint */
39
40 #include "dhcpd.h"
41 #include <ctype.h>
42
43 static int get_char PROTO ((struct parse *));
44 static enum dhcp_token get_token PROTO ((struct parse *));
45 static void skip_to_eol PROTO ((struct parse *));
46 static enum dhcp_token read_string PROTO ((struct parse *));
47 static enum dhcp_token read_number PROTO ((int, struct parse *));
48 static enum dhcp_token read_num_or_name PROTO ((int, struct parse *));
49 static enum dhcp_token intern PROTO ((char *, enum dhcp_token));
50
51 isc_result_t new_parse (cfile, file, inbuf, buflen, name, eolp)
52         struct parse **cfile;
53         int file;
54         char *inbuf;
55         unsigned buflen;
56         const char *name;
57         int eolp;
58 {
59         struct parse *tmp;
60
61         tmp = dmalloc (sizeof (struct parse), MDL);
62         if (!tmp)
63                 return ISC_R_NOMEMORY;
64         memset (tmp, 0, sizeof *tmp);
65
66         tmp -> token = 0;
67         tmp -> tlname = name;
68         tmp -> lpos = tmp -> line = 1;
69         tmp -> cur_line = tmp -> line1;
70         tmp -> prev_line = tmp -> line2;
71         tmp -> token_line = tmp -> cur_line;
72         tmp -> cur_line [0] = tmp -> prev_line [0] = 0;
73         tmp -> warnings_occurred = 0;
74         tmp -> file = file;
75         tmp -> eol_token = eolp;
76
77         tmp -> bufix = 0;
78         tmp -> buflen = buflen;
79         if (inbuf) {
80                 tmp -> bufsiz = 0;
81                 tmp -> inbuf = inbuf;
82         } else {
83                 tmp -> inbuf = dmalloc (8192, MDL);
84                 if (!tmp -> inbuf) {
85                         dfree (tmp, MDL);
86                         return ISC_R_NOMEMORY;
87                 }
88                 tmp -> bufsiz = 8192;
89         }
90
91         *cfile = tmp;
92         return ISC_R_SUCCESS;
93 }
94
95 isc_result_t end_parse (cfile)
96         struct parse **cfile;
97 {
98         if ((*cfile) -> bufsiz)
99                 dfree ((*cfile) -> inbuf, MDL);
100         dfree (*cfile, MDL);
101         *cfile = (struct parse *)0;
102         return ISC_R_SUCCESS;
103 }
104
105 static int get_char (cfile)
106         struct parse *cfile;
107 {
108         /* My kingdom for WITH... */
109         int c;
110
111         if (cfile -> bufix == cfile -> buflen) {
112                 if (cfile -> file != -1) {
113                         cfile -> buflen =
114                                 read (cfile -> file,
115                                       cfile -> inbuf, cfile -> bufsiz);
116                         if (cfile -> buflen == 0) {
117                                 c = EOF;
118                                 cfile -> bufix = 0;
119                         } else if (cfile -> buflen < 0) {
120                                 c = EOF;
121                                 cfile -> bufix = cfile -> buflen = 0;
122                         } else {
123                                 c = cfile -> inbuf [0];
124                                 cfile -> bufix = 1;
125                         }
126                 } else
127                         c = EOF;
128         } else {
129                 c = cfile -> inbuf [cfile -> bufix];
130                 cfile -> bufix++;
131         }
132
133         if (!cfile -> ugflag) {
134                 if (c == EOL) {
135                         if (cfile -> cur_line == cfile -> line1) {      
136                                 cfile -> cur_line = cfile -> line2;
137                                 cfile -> prev_line = cfile -> line1;
138                         } else {
139                                 cfile -> cur_line = cfile -> line1;
140                                 cfile -> prev_line = cfile -> line2;
141                         }
142                         cfile -> line++;
143                         cfile -> lpos = 1;
144                         cfile -> cur_line [0] = 0;
145                 } else if (c != EOF) {
146                         if (cfile -> lpos <= 80) {
147                                 cfile -> cur_line [cfile -> lpos - 1] = c;
148                                 cfile -> cur_line [cfile -> lpos] = 0;
149                         }
150                         cfile -> lpos++;
151                 }
152         } else
153                 cfile -> ugflag = 0;
154         return c;               
155 }
156
157 static enum dhcp_token get_token (cfile)
158         struct parse *cfile;
159 {
160         int c;
161         enum dhcp_token ttok;
162         static char tb [2];
163         int l, p, u;
164
165         do {
166                 l = cfile -> line;
167                 p = cfile -> lpos;
168                 u = cfile -> ugflag;
169
170                 c = get_char (cfile);
171 #ifdef OLD_LEXER
172                 if (c == '\n' && p == 1 && !u
173                     && cfile -> comment_index < sizeof cfile -> comments)
174                         cfile -> comments [cfile -> comment_index++] = '\n';
175 #endif
176
177                 if (!(c == '\n' && cfile -> eol_token)
178                     && isascii (c) && isspace (c))
179                         continue;
180                 if (c == '#') {
181 #ifdef OLD_LEXER
182                         if (cfile -> comment_index < sizeof cfile -> comments)
183                             cfile -> comments [cfile -> comment_index++] = '#';
184 #endif
185                         skip_to_eol (cfile);
186                         continue;
187                 }
188                 if (c == '"') {
189                         cfile -> lexline = l;
190                         cfile -> lexchar = p;
191                         ttok = read_string (cfile);
192                         break;
193                 }
194                 if ((isascii (c) && isdigit (c)) || c == '-') {
195                         cfile -> lexline = l;
196                         cfile -> lexchar = p;
197                         ttok = read_number (c, cfile);
198                         break;
199                 } else if (isascii (c) && isalpha (c)) {
200                         cfile -> lexline = l;
201                         cfile -> lexchar = p;
202                         ttok = read_num_or_name (c, cfile);
203                         break;
204                 } else if (c == EOF) {
205                         ttok = END_OF_FILE;
206                         cfile -> tlen = 0;
207                         break;
208                 } else {
209                         cfile -> lexline = l;
210                         cfile -> lexchar = p;
211                         tb [0] = c;
212                         tb [1] = 0;
213                         cfile -> tval = tb;
214                         cfile -> tlen = 1;
215                         ttok = c;
216                         break;
217                 }
218         } while (1);
219         return ttok;
220 }
221
222 enum dhcp_token next_token (rval, rlen, cfile)
223         const char **rval;
224         unsigned *rlen;
225         struct parse *cfile;
226 {
227         int rv;
228
229         if (cfile -> token) {
230                 if (cfile -> lexline != cfile -> tline)
231                         cfile -> token_line = cfile -> cur_line;
232                 cfile -> lexchar = cfile -> tlpos;
233                 cfile -> lexline = cfile -> tline;
234                 rv = cfile -> token;
235                 cfile -> token = 0;
236         } else {
237                 rv = get_token (cfile);
238                 cfile -> token_line = cfile -> cur_line;
239         }
240         if (rval)
241                 *rval = cfile -> tval;
242         if (rlen)
243                 *rlen = cfile -> tlen;
244 #ifdef DEBUG_TOKENS
245         fprintf (stderr, "%s:%d ", cfile -> tval, rv);
246 #endif
247         return rv;
248 }
249
250 enum dhcp_token peek_token (rval, rlen, cfile)
251         const char **rval;
252         unsigned int *rlen;
253         struct parse *cfile;
254 {
255         int x;
256
257         if (!cfile -> token) {
258                 cfile -> tlpos = cfile -> lexchar;
259                 cfile -> tline = cfile -> lexline;
260                 cfile -> token = get_token (cfile);
261                 if (cfile -> lexline != cfile -> tline)
262                         cfile -> token_line = cfile -> prev_line;
263
264                 x = cfile -> lexchar;
265                 cfile -> lexchar = cfile -> tlpos;
266                 cfile -> tlpos = x;
267
268                 x = cfile -> lexline;
269                 cfile -> lexline = cfile -> tline;
270                 cfile -> tline = x;
271         }
272         if (rval)
273                 *rval = cfile -> tval;
274         if (rlen)
275                 *rlen = cfile -> tlen;
276 #ifdef DEBUG_TOKENS
277         fprintf (stderr, "(%s:%d) ", cfile -> tval, cfile -> token);
278 #endif
279         return cfile -> token;
280 }
281
282 static void skip_to_eol (cfile)
283         struct parse *cfile;
284 {
285         int c;
286         do {
287                 c = get_char (cfile);
288                 if (c == EOF)
289                         return;
290 #ifdef OLD_LEXER
291                 if (cfile -> comment_index < sizeof (cfile -> comments))
292                         comments [cfile -> comment_index++] = c;
293 #endif
294                 if (c == EOL) {
295                         return;
296                 }
297         } while (1);
298 }
299
300 static enum dhcp_token read_string (cfile)
301         struct parse *cfile;
302 {
303         int i;
304         int bs = 0;
305         int c;
306         int value = 0;
307         int hex = 0;
308
309         for (i = 0; i < sizeof cfile -> tokbuf; i++) {
310               again:
311                 c = get_char (cfile);
312                 if (c == EOF) {
313                         parse_warn (cfile, "eof in string constant");
314                         break;
315                 }
316                 if (bs == 1) {
317                         switch (c) {
318                               case 't':
319                                 cfile -> tokbuf [i] = '\t';
320                                 break;
321                               case 'r':
322                                 cfile -> tokbuf [i] = '\r';
323                                 break;
324                               case 'n':
325                                 cfile -> tokbuf [i] = '\n';
326                                 break;
327                               case 'b':
328                                 cfile -> tokbuf [i] = '\b';
329                                 break;
330                               case '0':
331                               case '1':
332                               case '2':
333                               case '3':
334                                 hex = 0;
335                                 value = c - '0';
336                                 ++bs;
337                                 goto again;
338                               case 'x':
339                                 hex = 1;
340                                 value = 0;
341                                 ++bs;
342                                 goto again;
343                               default:
344                                 cfile -> tokbuf [i] = c;
345                                 bs = 0;
346                                 break;
347                         }
348                         bs = 0;
349                 } else if (bs > 1) {
350                         if (hex) {
351                                 if (c >= '0' && c <= '9') {
352                                         value = value * 16 + (c - '0');
353                                 } else if (c >= 'a' && c <= 'f') {
354                                         value = value * 16 + (c - 'a' + 10);
355                                 } else if (c >= 'A' && c <= 'F') {
356                                         value = value * 16 + (c - 'A' + 10);
357                                 } else {
358                                         parse_warn (cfile,
359                                                     "invalid hex digit: %x",
360                                                     c);
361                                         bs = 0;
362                                         continue;
363                                 }
364                                 if (++bs == 4) {
365                                         cfile -> tokbuf [i] = value;
366                                         bs = 0;
367                                 } else
368                                         goto again;
369                         } else {
370                                 if (c >= '0' && c <= '9') {
371                                         value = value * 8 + (c - '0');
372                                 } else {
373                                     if (value != 0) {
374                                         parse_warn (cfile,
375                                                     "invalid octal digit %x",
376                                                     c);
377                                         continue;
378                                     } else
379                                         cfile -> tokbuf [i] = 0;
380                                     bs = 0;
381                                 }
382                                 if (++bs == 4) {
383                                         cfile -> tokbuf [i] = value;
384                                         bs = 0;
385                                 } else
386                                         goto again;
387                         }
388                 } else if (c == '\\') {
389                         bs = 1;
390                         goto again;
391                 } else if (c == '"')
392                         break;
393                 else
394                         cfile -> tokbuf [i] = c;
395         }
396         /* Normally, I'd feel guilty about this, but we're talking about
397            strings that'll fit in a DHCP packet here... */
398         if (i == sizeof cfile -> tokbuf) {
399                 parse_warn (cfile,
400                             "string constant larger than internal buffer");
401                 --i;
402         }
403         cfile -> tokbuf [i] = 0;
404         cfile -> tlen = i;
405         cfile -> tval = cfile -> tokbuf;
406         return STRING;
407 }
408
409 static enum dhcp_token read_number (c, cfile)
410         int c;
411         struct parse *cfile;
412 {
413         int seenx = 0;
414         int i = 0;
415         int token = NUMBER;
416
417         cfile -> tokbuf [i++] = c;
418         for (; i < sizeof cfile -> tokbuf; i++) {
419                 c = get_char (cfile);
420                 if (!seenx && c == 'x') {
421                         seenx = 1;
422 #ifndef OLD_LEXER
423                 } else if (isascii (c) && !isxdigit (c) &&
424                            (c == '-' || c == '_' || isalpha (c))) {
425                         token = NAME;
426                 } else if (isascii (c) && !isdigit (c) && isxdigit (c)) {
427                         token = NUMBER_OR_NAME;
428 #endif
429                 } else if (!isascii (c) || !isxdigit (c)) {
430                         if (c != EOF) {
431                                 cfile -> bufix--;
432                                 cfile -> ugflag = 1;
433                         }
434                         break;
435                 }
436                 cfile -> tokbuf [i] = c;
437         }
438         if (i == sizeof cfile -> tokbuf) {
439                 parse_warn (cfile,
440                             "numeric token larger than internal buffer");
441                 --i;
442         }
443         cfile -> tokbuf [i] = 0;
444         cfile -> tlen = i;
445         cfile -> tval = cfile -> tokbuf;
446         return token;
447 }
448
449 static enum dhcp_token read_num_or_name (c, cfile)
450         int c;
451         struct parse *cfile;
452 {
453         int i = 0;
454         enum dhcp_token rv = NUMBER_OR_NAME;
455         cfile -> tokbuf [i++] = c;
456         for (; i < sizeof cfile -> tokbuf; i++) {
457                 c = get_char (cfile);
458                 if (!isascii (c) ||
459                     (c != '-' && c != '_' && !isalnum (c))) {
460                         if (c != EOF) {
461                                 cfile -> bufix--;
462                                 cfile -> ugflag = 1;
463                         }
464                         break;
465                 }
466                 if (!isxdigit (c))
467                         rv = NAME;
468                 cfile -> tokbuf [i] = c;
469         }
470         if (i == sizeof cfile -> tokbuf) {
471                 parse_warn (cfile, "token larger than internal buffer");
472                 --i;
473         }
474         cfile -> tokbuf [i] = 0;
475         cfile -> tlen = i;
476         cfile -> tval = cfile -> tokbuf;
477         return intern (cfile -> tval, rv);
478 }
479
480 static enum dhcp_token intern (atom, dfv)
481         char *atom;
482         enum dhcp_token dfv;
483 {
484         if (!isascii (atom [0]))
485                 return dfv;
486
487         switch (tolower (atom [0])) {
488               case '-':
489                 if (atom [1] == 0)
490                         return MINUS;
491                 break;
492
493               case 'a':
494                 if (!strncasecmp (atom + 1, "uth", 3)) {
495                         if (!strncasecmp (atom + 3, "uthenticat", 10)) {
496                                 if (!strcasecmp (atom + 13, "ed"))
497                                         return AUTHENTICATED;
498                                 if (!strcasecmp (atom + 13, "ion"))
499                                         return AUTHENTICATION;
500                                 break;
501                         }
502                         if (!strcasecmp (atom + 1, "uthoritative"))
503                                 return AUTHORITATIVE;
504                         break;
505                 }
506                 if (!strcasecmp (atom + 1, "nd"))
507                         return AND;
508                 if (!strcasecmp (atom + 1, "ppend"))
509                         return APPEND;
510                 if (!strcasecmp (atom + 1, "llow"))
511                         return ALLOW;
512                 if (!strcasecmp (atom + 1, "lias"))
513                         return ALIAS;
514                 if (!strcasecmp (atom + 1, "lgorithm"))
515                         return ALGORITHM;
516                 if (!strcasecmp (atom + 1, "bandoned"))
517                         return TOKEN_ABANDONED;
518                 if (!strcasecmp (atom + 1, "dd"))
519                         return TOKEN_ADD;
520                 if (!strcasecmp (atom + 1, "ll"))
521                         return ALL;
522                 if (!strcasecmp (atom + 1, "t"))
523                         return AT;
524                 if (!strcasecmp (atom + 1, "rray"))
525                         return ARRAY;
526                 if (!strcasecmp (atom + 1, "ddress"))
527                         return ADDRESS;
528                 if (!strcasecmp (atom + 1, "ctive"))
529                         return TOKEN_ACTIVE;
530                 break;
531               case 'b':
532                 if (!strcasecmp (atom + 1, "ackup"))
533                         return TOKEN_BACKUP;
534                 if (!strcasecmp (atom + 1, "ootp"))
535                         return TOKEN_BOOTP;
536                 if (!strcasecmp (atom + 1, "inding"))
537                         return BINDING;
538                 if (!strcasecmp (atom + 1, "inary-to-ascii"))
539                         return BINARY_TO_ASCII;
540                 if (!strcasecmp (atom + 1, "ackoff-cutoff"))
541                         return BACKOFF_CUTOFF;
542                 if (!strcasecmp (atom + 1, "ooting"))
543                         return BOOTING;
544                 if (!strcasecmp (atom + 1, "oot-unknown-clients"))
545                         return BOOT_UNKNOWN_CLIENTS;
546                 if (!strcasecmp (atom + 1, "reak"))
547                         return BREAK;
548                 if (!strcasecmp (atom + 1, "illing"))
549                         return BILLING;
550                 if (!strcasecmp (atom + 1, "oolean"))
551                         return BOOLEAN;
552                 if (!strcasecmp (atom + 1, "alance"))
553                         return BALANCE;
554                 if (!strcasecmp (atom + 1, "ound"))
555                         return BOUND;
556                 break;
557               case 'c':
558                 if (!strcasecmp (atom + 1, "ase"))
559                         return CASE;
560                 if (!strcasecmp (atom + 1, "ommit"))
561                         return COMMIT;
562                 if (!strcasecmp (atom + 1, "ode"))
563                         return CODE;
564                 if (!strcasecmp (atom + 1, "onfig-option"))
565                         return CONFIG_OPTION;
566                 if (!strcasecmp (atom + 1, "heck"))
567                         return CHECK;
568                 if (!strcasecmp (atom + 1, "lass"))
569                         return CLASS;
570                 if (!strcasecmp (atom + 1, "lose"))
571                         return TOKEN_CLOSE;
572                 if (!strcasecmp (atom + 1, "reate"))
573                         return TOKEN_CREATE;
574                 if (!strcasecmp (atom + 1, "iaddr"))
575                         return CIADDR;
576                 if (!strncasecmp (atom + 1, "lient", 5)) {
577                         if (!strcasecmp (atom + 6, "-identifier"))
578                                 return CLIENT_IDENTIFIER;
579                         if (!strcasecmp (atom + 6, "-hostname"))
580                                 return CLIENT_HOSTNAME;
581                         if (!strcasecmp (atom + 6, "-state"))
582                                 return CLIENT_STATE;
583                         if (!strcasecmp (atom + 6, "-updates"))
584                                 return CLIENT_UPDATES;
585                         if (!strcasecmp (atom + 6, "s"))
586                                 return CLIENTS;
587                 }
588                 if (!strcasecmp (atom + 1, "oncat"))
589                         return CONCAT;
590                 if (!strcasecmp (atom + 1, "onnect"))
591                         return CONNECT;
592                 if (!strcasecmp (atom + 1, "ommunications-interrupted"))
593                         return COMMUNICATIONS_INTERRUPTED;
594                 if (!strcasecmp (atom + 1, "ltt"))
595                         return CLTT;
596                 break;
597               case 'd':
598                 if (!strcasecmp (atom + 1, "ns-update"))
599                         return DNS_UPDATE;
600                 if (!strcasecmp (atom + 1, "ns-delete"))
601                         return DNS_DELETE;
602                 if (!strcasecmp (atom + 1, "omain"))
603                         return DOMAIN;
604                 if (!strcasecmp (atom + 1, "omain-name"))
605                         return DOMAIN_NAME;
606                 if (!strcasecmp (atom + 1, "o-forward-update"))
607                         return DO_FORWARD_UPDATE;
608                 if (!strcasecmp (atom + 1, "ebug"))
609                         return TOKEN_DEBUG;
610                 if (!strcasecmp (atom + 1, "eny"))
611                         return DENY;
612                 if (!strcasecmp (atom + 1, "eleted"))
613                         return TOKEN_DELETED;
614                 if (!strcasecmp (atom + 1, "elete"))
615                         return TOKEN_DELETE;
616                 if (!strncasecmp (atom + 1, "efault", 6)) {
617                         if (!atom [7])
618                                 return DEFAULT;
619                         if (!strcasecmp (atom + 7, "-lease-time"))
620                                 return DEFAULT_LEASE_TIME;
621                         break;
622                 }
623                 if (!strncasecmp (atom + 1, "ynamic", 6)) {
624                         if (!atom [7])
625                                 return DYNAMIC;
626                         if (!strncasecmp (atom + 7, "-bootp", 6)) {
627                                 if (!atom [13])
628                                         return DYNAMIC_BOOTP;
629                                 if (!strcasecmp (atom + 13, "-lease-cutoff"))
630                                         return DYNAMIC_BOOTP_LEASE_CUTOFF;
631                                 if (!strcasecmp (atom + 13, "-lease-length"))
632                                         return DYNAMIC_BOOTP_LEASE_LENGTH;
633                                 break;
634                         }
635                 }
636                 if (!strcasecmp (atom + 1, "uplicates"))
637                         return DUPLICATES;
638                 if (!strcasecmp (atom + 1, "eclines"))
639                         return DECLINES;
640                 if (!strncasecmp (atom + 1, "efine", 5)) {
641                         if (!strcasecmp (atom + 6, "d"))
642                                 return DEFINED;
643                         if (!atom [6])
644                                 return DEFINE;
645                 }
646                 break;
647               case 'e':
648                 if (isascii (atom [1]) && tolower (atom [1]) == 'x') {
649                         if (!strcasecmp (atom + 2, "tract-int"))
650                                 return EXTRACT_INT;
651                         if (!strcasecmp (atom + 2, "ists"))
652                                 return EXISTS;
653                         if (!strcasecmp (atom + 2, "piry"))
654                                 return EXPIRY;
655                         if (!strcasecmp (atom + 2, "pire"))
656                                 return EXPIRE;
657                         if (!strcasecmp (atom + 2, "pired"))
658                                 return TOKEN_EXPIRED;
659                 }
660                 if (!strcasecmp (atom + 1, "ncode-int"))
661                         return ENCODE_INT;
662                 if (!strcasecmp (atom + 1, "thernet"))
663                         return ETHERNET;
664                 if (!strcasecmp (atom + 1, "nds"))
665                         return ENDS;
666                 if (!strncasecmp (atom + 1, "ls", 2)) {
667                         if (!strcasecmp (atom + 3, "e"))
668                                 return ELSE;
669                         if (!strcasecmp (atom + 3, "if"))
670                                 return ELSIF;
671                         break;
672                 }
673                 if (!strcasecmp (atom + 1, "rror"))
674                         return ERROR;
675                 if (!strcasecmp (atom + 1, "val"))
676                         return EVAL;
677                 if (!strcasecmp (atom + 1, "ncapsulate"))
678                         return ENCAPSULATE;
679                 break;
680               case 'f':
681                 if (!strcasecmp (atom + 1, "atal"))
682                         return FATAL;
683                 if (!strcasecmp (atom + 1, "ilename"))
684                         return FILENAME;
685                 if (!strcasecmp (atom + 1, "ixed-address"))
686                         return FIXED_ADDR;
687                 if (!strcasecmp (atom + 1, "ddi"))
688                         return FDDI;
689                 if (!strcasecmp (atom + 1, "ormerr"))
690                         return NS_FORMERR;
691                 if (!strcasecmp (atom + 1, "unction"))
692                         return FUNCTION;
693                 if (!strcasecmp (atom + 1, "ailover"))
694                         return FAILOVER;
695                 if (!strcasecmp (atom + 1, "ree"))
696                         return TOKEN_FREE;
697                 break;
698               case 'g':
699                 if (!strcasecmp (atom + 1, "iaddr"))
700                         return GIADDR;
701                 if (!strcasecmp (atom + 1, "roup"))
702                         return GROUP;
703                 if (!strcasecmp (atom + 1, "et-lease-hostnames"))
704                         return GET_LEASE_HOSTNAMES;
705                 break;
706               case 'h':
707                 if (!strcasecmp (atom + 1, "ba"))
708                         return HBA;
709                 if (!strcasecmp (atom + 1, "ost"))
710                         return HOST;
711                 if (!strcasecmp (atom + 1, "ost-decl-name"))
712                         return HOST_DECL_NAME;
713                 if (!strcasecmp (atom + 1, "ardware"))
714                         return HARDWARE;
715                 if (!strcasecmp (atom + 1, "ostname"))
716                         return HOSTNAME;
717                 if (!strcasecmp (atom + 1, "elp"))
718                         return TOKEN_HELP;
719                 break;
720               case 'i':
721                 if (!strcasecmp (atom + 1, "nclude"))
722                         return INCLUDE;
723                 if (!strcasecmp (atom + 1, "nteger"))
724                         return INTEGER;
725                 if (!strcasecmp (atom + 1, "nfinite"))
726                         return INFINITE;
727                 if (!strcasecmp (atom + 1, "nfo"))
728                         return INFO;
729                 if (!strcasecmp (atom + 1, "p-address"))
730                         return IP_ADDRESS;
731                 if (!strcasecmp (atom + 1, "nitial-interval"))
732                         return INITIAL_INTERVAL;
733                 if (!strcasecmp (atom + 1, "nterface"))
734                         return INTERFACE;
735                 if (!strcasecmp (atom + 1, "dentifier"))
736                         return IDENTIFIER;
737                 if (!strcasecmp (atom + 1, "f"))
738                         return IF;
739                 if (!strcasecmp (atom + 1, "s"))
740                         return IS;
741                 if (!strcasecmp (atom + 1, "gnore"))
742                         return IGNORE;
743                 break;
744               case 'k':
745                 if (!strncasecmp (atom + 1, "nown", 4)) {
746                         if (!strcasecmp (atom + 5, "-clients"))
747                                 return KNOWN_CLIENTS;
748                         if (!atom[5])
749                                 return KNOWN;
750                         break;
751                 }
752                 if (!strcasecmp (atom + 1, "ey"))
753                         return KEY;
754                 break;
755               case 'l':
756                 if (!strcasecmp (atom + 1, "ease"))
757                         return LEASE;
758                 if (!strcasecmp (atom + 1, "eased-address"))
759                         return LEASED_ADDRESS;
760                 if (!strcasecmp (atom + 1, "ease-time"))
761                         return LEASE_TIME;
762                 if (!strcasecmp (atom + 1, "imit"))
763                         return LIMIT;
764                 if (!strcasecmp (atom + 1, "et"))
765                         return LET;
766                 if (!strcasecmp (atom + 1, "oad"))
767                         return LOAD;
768                 if (!strcasecmp (atom + 1, "og"))
769                         return LOG;
770                 break;
771               case 'm':
772                 if (!strncasecmp (atom + 1, "ax", 2)) {
773                         if (!atom [3])
774                                 return TOKEN_MAX;
775                         if (!strcasecmp (atom + 3, "-lease-time"))
776                                 return MAX_LEASE_TIME;
777                         if (!strcasecmp (atom + 3, "-transmit-idle"))
778                                 return MAX_TRANSMIT_IDLE;
779                         if (!strcasecmp (atom + 3, "-response-delay"))
780                                 return MAX_RESPONSE_DELAY;
781                         if (!strcasecmp (atom + 3, "-unacked-updates"))
782                                 return MAX_UNACKED_UPDATES;
783                 }
784                 if (!strncasecmp (atom + 1, "in-", 3)) {
785                         if (!strcasecmp (atom + 4, "lease-time"))
786                                 return MIN_LEASE_TIME;
787                         if (!strcasecmp (atom + 4, "secs"))
788                                 return MIN_SECS;
789                         break;
790                 }
791                 if (!strncasecmp (atom + 1, "edi", 3)) {
792                         if (!strcasecmp (atom + 4, "a"))
793                                 return MEDIA;
794                         if (!strcasecmp (atom + 4, "um"))
795                                 return MEDIUM;
796                         break;
797                 }
798                 if (!strcasecmp (atom + 1, "atch"))
799                         return MATCH;
800                 if (!strcasecmp (atom + 1, "embers"))
801                         return MEMBERS;
802                 if (!strcasecmp (atom + 1, "y"))
803                         return MY;
804                 if (!strcasecmp (atom + 1, "clt"))
805                         return MCLT;
806                 break;
807               case 'n':
808                 if (!strcasecmp (atom + 1, "ormal"))
809                         return NORMAL;
810                 if (!strcasecmp (atom + 1, "ameserver"))
811                         return NAMESERVER;
812                 if (!strcasecmp (atom + 1, "etmask"))
813                         return NETMASK;
814                 if (!strcasecmp (atom + 1, "ever"))
815                         return NEVER;
816                 if (!strcasecmp (atom + 1, "ext-server"))
817                         return NEXT_SERVER;
818                 if (!strcasecmp (atom + 1, "ot"))
819                         return TOKEN_NOT;
820                 if (!strcasecmp (atom + 1, "o"))
821                         return NO;
822                 if (!strcasecmp (atom + 1, "s-update"))
823                         return NS_UPDATE;
824                 if (!strcasecmp (atom + 1, "oerror"))
825                         return NS_NOERROR;
826                 if (!strcasecmp (atom + 1, "otauth"))
827                         return NS_NOTAUTH;
828                 if (!strcasecmp (atom + 1, "otimp"))
829                         return NS_NOTIMP;
830                 if (!strcasecmp (atom + 1, "otzone"))
831                         return NS_NOTZONE;
832                 if (!strcasecmp (atom + 1, "xdomain"))
833                         return NS_NXDOMAIN;
834                 if (!strcasecmp (atom + 1, "xrrset"))
835                         return NS_NXRRSET;
836                 if (!strcasecmp (atom + 1, "ull"))
837                         return TOKEN_NULL;
838                 if (!strcasecmp (atom + 1, "ext"))
839                         return TOKEN_NEXT;
840                 if (!strcasecmp (atom + 1, "ew"))
841                         return TOKEN_NEW;
842                 break;
843               case 'o':
844                 if (!strcasecmp (atom + 1, "mapi"))
845                         return OMAPI;
846                 if (!strcasecmp (atom + 1, "r"))
847                         return OR;
848                 if (!strcasecmp (atom + 1, "n"))
849                         return ON;
850                 if (!strcasecmp (atom + 1, "pen"))
851                         return TOKEN_OPEN;
852                 if (!strcasecmp (atom + 1, "ption"))
853                         return OPTION;
854                 if (!strcasecmp (atom + 1, "ne-lease-per-client"))
855                         return ONE_LEASE_PER_CLIENT;
856                 if (!strcasecmp (atom + 1, "f"))
857                         return OF;
858                 if (!strcasecmp (atom + 1, "wner"))
859                         return OWNER;
860                 break;
861               case 'p':
862                 if (!strcasecmp (atom + 1, "repend"))
863                         return PREPEND;
864                 if (!strcasecmp (atom + 1, "acket"))
865                         return PACKET;
866                 if (!strcasecmp (atom + 1, "ool"))
867                         return POOL;
868                 if (!strcasecmp (atom + 1, "seudo"))
869                         return PSEUDO;
870                 if (!strcasecmp (atom + 1, "eer"))
871                         return PEER;
872                 if (!strcasecmp (atom + 1, "rimary"))
873                         return PRIMARY;
874                 if (!strncasecmp (atom + 1, "artner", 6)) {
875                         if (!atom [7])
876                                 return PARTNER;
877                         if (!strcasecmp (atom + 7, "-down"))
878                                 return PARTNER_DOWN;
879                 }
880                 if (!strcasecmp (atom + 1, "ort"))
881                         return PORT;
882                 if (!strcasecmp (atom + 1, "otential-conflict"))
883                         return POTENTIAL_CONFLICT;
884                 if (!strcasecmp (atom + 1, "ick-first-value") ||
885                     !strcasecmp (atom + 1, "ick"))
886                         return PICK;
887                 if (!strcasecmp (atom + 1, "aused"))
888                         return PAUSED;
889                 break;
890               case 'r':
891                 if (!strcasecmp (atom + 1, "esolution-interrupted"))
892                         return RESOLUTION_INTERRUPTED;
893                 if (!strcasecmp (atom + 1, "ange"))
894                         return RANGE;
895                 if (!strcasecmp (atom + 1, "ecover"))
896                         return RECOVER;
897                 if (!strcasecmp (atom + 1, "ecover-done"))
898                         return RECOVER_DONE;
899                 if (!strcasecmp (atom + 1, "ecover-wait"))
900                         return RECOVER_WAIT;
901                 if (!strcasecmp (atom + 1, "econtact-interval"))
902                         return RECONTACT_INTERVAL;
903                 if (!strcasecmp (atom + 1, "equest"))
904                         return REQUEST;
905                 if (!strcasecmp (atom + 1, "equire"))
906                         return REQUIRE;
907                 if (!strcasecmp (atom + 1, "equire"))
908                         return REQUIRE;
909                 if (!strcasecmp (atom + 1, "etry"))
910                         return RETRY;
911                 if (!strcasecmp (atom + 1, "eturn"))
912                         return RETURN;
913                 if (!strcasecmp (atom + 1, "enew"))
914                         return RENEW;
915                 if (!strcasecmp (atom + 1, "ebind"))
916                         return REBIND;
917                 if (!strcasecmp (atom + 1, "eboot"))
918                         return REBOOT;
919                 if (!strcasecmp (atom + 1, "eject"))
920                         return REJECT;
921                 if (!strcasecmp (atom + 1, "everse"))
922                         return REVERSE;
923                 if (!strcasecmp (atom + 1, "elease"))
924                         return RELEASE;
925                 if (!strcasecmp (atom + 1, "efused"))
926                         return NS_REFUSED;
927                 if (!strcasecmp (atom + 1, "eleased"))
928                         return TOKEN_RELEASED;
929                 if (!strcasecmp (atom + 1, "eset"))
930                         return TOKEN_RESET;
931                 if (!strcasecmp (atom + 1, "eserved"))
932                         return TOKEN_RESERVED;
933                 if (!strcasecmp (atom + 1, "emove"))
934                         return REMOVE;
935                 if (!strcasecmp (atom + 1, "efresh"))
936                         return REFRESH;
937                 break;
938               case 's':
939                 if (!strcasecmp (atom + 1, "tate"))
940                         return STATE;
941                 if (!strcasecmp (atom + 1, "ecret"))
942                         return SECRET;
943                 if (!strcasecmp (atom + 1, "ervfail"))
944                         return NS_SERVFAIL;
945                 if (!strcasecmp (atom + 1, "witch"))
946                         return SWITCH;
947                 if (!strcasecmp (atom + 1, "igned"))
948                         return SIGNED;
949                 if (!strcasecmp (atom + 1, "tring"))
950                         return STRING_TOKEN;
951                 if (!strcasecmp (atom + 1, "uffix"))
952                         return SUFFIX;
953                 if (!strcasecmp (atom + 1, "earch"))
954                         return SEARCH;
955                 if (!strcasecmp (atom + 1, "tarts"))
956                         return STARTS;
957                 if (!strcasecmp (atom + 1, "iaddr"))
958                         return SIADDR;
959                 if (!strcasecmp (atom + 1, "hared-network"))
960                         return SHARED_NETWORK;
961                 if (!strcasecmp (atom + 1, "econdary"))
962                         return SECONDARY;
963                 if (!strcasecmp (atom + 1, "erver-name"))
964                         return SERVER_NAME;
965                 if (!strcasecmp (atom + 1, "erver-identifier"))
966                         return SERVER_IDENTIFIER;
967                 if (!strcasecmp (atom + 1, "erver"))
968                         return SERVER;
969                 if (!strcasecmp (atom + 1, "elect-timeout"))
970                         return SELECT_TIMEOUT;
971                 if (!strcasecmp (atom + 1, "elect"))
972                         return SELECT;
973                 if (!strcasecmp (atom + 1, "end"))
974                         return SEND;
975                 if (!strcasecmp (atom + 1, "cript"))
976                         return SCRIPT;
977                 if (!strcasecmp (atom + 1, "upersede"))
978                         return SUPERSEDE;
979                 if (!strncasecmp (atom + 1, "ub", 2)) {
980                         if (!strcasecmp (atom + 3, "string"))
981                                 return SUBSTRING;
982                         if (!strcasecmp (atom + 3, "net"))
983                                 return SUBNET;
984                         if (!strcasecmp (atom + 3, "class"))
985                                 return SUBCLASS;
986                         break;
987                 }
988                 if (!strcasecmp (atom + 1, "pawn"))
989                         return SPAWN;
990                 if (!strcasecmp (atom + 1, "pace"))
991                         return SPACE;
992                 if (!strcasecmp (atom + 1, "tatic"))
993                         return STATIC;
994                 if (!strcasecmp (atom + 1, "plit"))
995                         return SPLIT;
996                 if (!strcasecmp (atom + 1, "et"))
997                         return TOKEN_SET;
998                 if (!strcasecmp (atom + 1, "econds"))
999                         return SECONDS;
1000                 if (!strcasecmp (atom + 1, "hutdown"))
1001                         return SHUTDOWN;
1002                 if (!strcasecmp (atom + 1, "tartup"))
1003                         return STARTUP;
1004                 break;
1005               case 't':
1006                 if (!strcasecmp (atom + 1, "imestamp"))
1007                         return TIMESTAMP;
1008                 if (!strcasecmp (atom + 1, "imeout"))
1009                         return TIMEOUT;
1010                 if (!strcasecmp (atom + 1, "oken-ring"))
1011                         return TOKEN_RING;
1012                 if (!strcasecmp (atom + 1, "ext"))
1013                         return TEXT;
1014                 if (!strcasecmp (atom + 1, "stp"))
1015                         return TSTP;
1016                 if (!strcasecmp (atom + 1, "sfp"))
1017                         return TSFP;
1018                 if (!strcasecmp (atom + 1, "ransmission"))
1019                         return TRANSMISSION;
1020                 break;
1021               case 'u':
1022                 if (!strcasecmp (atom + 1, "nset"))
1023                         return UNSET;
1024                 if (!strcasecmp (atom + 1, "nsigned"))
1025                         return UNSIGNED;
1026                 if (!strcasecmp (atom + 1, "id"))
1027                         return UID;
1028                 if (!strncasecmp (atom + 1, "se", 2)) {
1029                         if (!strcasecmp (atom + 3, "r-class"))
1030                                 return USER_CLASS;
1031                         if (!strcasecmp (atom + 3, "-host-decl-names"))
1032                                 return USE_HOST_DECL_NAMES;
1033                         if (!strcasecmp (atom + 3,
1034                                          "-lease-addr-for-default-route"))
1035                                 return USE_LEASE_ADDR_FOR_DEFAULT_ROUTE;
1036                         break;
1037                 }
1038                 if (!strncasecmp (atom + 1, "nknown", 6)) {
1039                         if (!strcasecmp (atom + 7, "-clients"))
1040                                 return UNKNOWN_CLIENTS;
1041                         if (!strcasecmp (atom + 7, "-state"))
1042                                 return UNKNOWN_STATE;
1043                         if (!atom [7])
1044                                 return UNKNOWN;
1045                         break;
1046                 }
1047                 if (!strcasecmp (atom + 1, "nauthenticated"))
1048                         return AUTHENTICATED;
1049                 if (!strcasecmp (atom + 1, "pdated-dns-rr"))
1050                         return UPDATED_DNS_RR;
1051                 if (!strcasecmp (atom + 1, "pdate"))
1052                         return UPDATE;
1053                 break;
1054               case 'v':
1055                 if (!strcasecmp (atom + 1, "endor-class"))
1056                         return VENDOR_CLASS;
1057                 if (!strcasecmp (atom + 1, "endor"))
1058                         return VENDOR;
1059                 break;
1060               case 'w':
1061                 if (!strcasecmp (atom + 1, "ith"))
1062                         return WITH;
1063                 break;
1064               case 'y':
1065                 if (!strcasecmp (atom + 1, "iaddr"))
1066                         return YIADDR;
1067                 if (!strcasecmp (atom + 1, "xdomain"))
1068                         return NS_YXDOMAIN;
1069                 if (!strcasecmp (atom + 1, "xrrset"))
1070                         return NS_YXRRSET;
1071                 break;
1072               case 'z':
1073                 if (!strcasecmp (atom + 1, "one"))
1074                         return ZONE;
1075                 break;
1076         }
1077         return dfv;
1078 }