3 Common parser code for dhcpd and dhclient. */
6 * Copyright (c) 2004-2005 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
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.
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.
21 * Internet Systems Consortium, Inc.
23 * Redwood City, CA 94063
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''.
36 static char copyright
[] =
37 "$Id$ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n";
42 /* Enumerations can be specified in option formats, and are used for
43 parsing, so we define the routines that manage them here. */
45 struct enumeration
*enumerations
;
47 void add_enumeration (struct enumeration
*enumeration
)
49 enumeration
-> next
= enumerations
;
50 enumerations
= enumeration
;
53 struct enumeration
*find_enumeration (const char *name
, int length
)
55 struct enumeration
*e
;
57 for (e
= enumerations
; e
; e
= e
-> next
)
58 if (strlen (e
-> name
) == length
&&
59 !memcmp (e
-> name
, name
, (unsigned)length
))
61 return (struct enumeration
*)0;
64 struct enumeration_value
*find_enumeration_value (const char *name
,
68 struct enumeration
*e
;
71 e
= find_enumeration (name
, length
);
73 for (i
= 0; e
-> values
[i
].name
; i
++) {
74 if (!strcmp (value
, e
-> values
[i
].name
))
75 return &e
-> values
[i
];
78 return (struct enumeration_value
*)0;
81 /* Skip to the semicolon ending the current statement. If we encounter
82 braces, the matching closing brace terminates the statement. If we
83 encounter a right brace but haven't encountered a left brace, return
84 leaving the brace in the token buffer for the caller. If we see a
85 semicolon and haven't seen a left brace, return. This lets us skip
90 statement foo bar { statement { } }
95 void skip_to_semi (cfile
)
98 skip_to_rbrace (cfile
, 0);
101 void skip_to_rbrace (cfile
, brace_count
)
105 enum dhcp_token token
;
108 #if defined (DEBUG_TOKEN)
109 log_error ("skip_to_rbrace: %d\n", brace_count
);
112 token
= peek_token (&val
, (unsigned *)0, cfile
);
113 if (token
== RBRACE
) {
114 token
= next_token (&val
, (unsigned *)0, cfile
);
120 } else if (token
== LBRACE
) {
122 } else if (token
== SEMI
&& !brace_count
) {
123 token
= next_token (&val
, (unsigned *)0, cfile
);
125 } else if (token
== EOL
) {
126 /* EOL only happens when parsing /etc/resolv.conf,
127 and we treat it like a semicolon because the
128 resolv.conf file is line-oriented. */
129 token
= next_token (&val
, (unsigned *)0, cfile
);
132 token
= next_token (&val
, (unsigned *)0, cfile
);
133 } while (token
!= END_OF_FILE
);
136 int parse_semi (cfile
)
139 enum dhcp_token token
;
142 token
= next_token (&val
, (unsigned *)0, cfile
);
144 parse_warn (cfile
, "semicolon expected.");
145 skip_to_semi (cfile
);
151 /* string-parameter :== STRING SEMI */
153 int parse_string (cfile
, sptr
, lptr
)
159 enum dhcp_token token
;
163 token
= next_token (&val
, &len
, cfile
);
164 if (token
!= STRING
) {
165 parse_warn (cfile
, "expecting a string");
166 skip_to_semi (cfile
);
169 s
= (char *)dmalloc (len
+ 1, MDL
);
171 log_fatal ("no memory for string %s.", val
);
172 memcpy (s
, val
, len
+ 1);
174 if (!parse_semi (cfile
)) {
188 * hostname :== IDENTIFIER
190 * | hostname DOT IDENTIFIER
193 char *parse_host_name (cfile
)
197 enum dhcp_token token
;
204 /* Read a dotted hostname... */
206 /* Read a token, which should be an identifier. */
207 token
= peek_token (&val
, (unsigned *)0, cfile
);
208 if (!is_identifier (token
) && token
!= NUMBER
)
210 token
= next_token (&val
, (unsigned *)0, cfile
);
212 /* Store this identifier... */
213 if (!(s
= (char *)dmalloc (strlen (val
) + 1, MDL
)))
214 log_fatal ("can't allocate temp space for hostname.");
216 c
= cons ((caddr_t
)s
, c
);
217 len
+= strlen (s
) + 1;
218 /* Look for a dot; if it's there, keep going, otherwise
220 token
= peek_token (&val
, (unsigned *)0, cfile
);
222 token
= next_token (&val
, (unsigned *)0, cfile
);
226 } while (token
== DOT
);
228 /* Should be at least one token. */
232 /* Assemble the hostname together into a string. */
233 if (!(s
= (char *)dmalloc (len
+ ltid
, MDL
)))
234 log_fatal ("can't allocate space for hostname.");
241 unsigned l
= strlen ((char *)(c
-> car
));
243 memcpy (t
, (char *)(c
-> car
), l
);
244 /* Free up temp space. */
245 dfree (c
-> car
, MDL
);
254 /* ip-addr-or-hostname :== ip-address | hostname
255 ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
257 Parse an ip address or a hostname. If uniform is zero, put in
258 an expr_substring node to limit hostnames that evaluate to more
259 than one IP address. */
261 int parse_ip_addr_or_hostname (expr
, cfile
, uniform
)
262 struct expression
**expr
;
267 enum dhcp_token token
;
268 unsigned char addr
[4];
269 unsigned len
= sizeof addr
;
271 struct expression
*x
= (struct expression
*)0;
273 token
= peek_token (&val
, (unsigned *)0, cfile
);
274 if (is_identifier (token
)) {
275 name
= parse_host_name (cfile
);
278 if (!make_host_lookup (expr
, name
)) {
284 if (!make_limit (&x
, *expr
, 4))
286 expression_dereference (expr
, MDL
);
289 } else if (token
== NUMBER
) {
290 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8))
292 return make_const_data (expr
, addr
, len
, 0, 1, MDL
);
294 if (token
!= RBRACE
&& token
!= LBRACE
)
295 token
= next_token (&val
, (unsigned *)0, cfile
);
296 parse_warn (cfile
, "%s (%d): expecting IP address or hostname",
299 skip_to_semi (cfile
);
307 * ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
310 int parse_ip_addr (cfile
, addr
)
315 // enum dhcp_token token;
318 if (parse_numeric_aggregate (cfile
, addr
-> iabuf
,
319 &addr
-> len
, DOT
, 10, 8))
325 * hardware-parameter :== HARDWARE hardware-type colon-seperated-hex-list SEMI
326 * hardware-type :== ETHERNET | TOKEN_RING | FDDI
329 void parse_hardware_param (cfile
, hardware
)
331 struct hardware
*hardware
;
334 enum dhcp_token token
;
338 token
= next_token (&val
, (unsigned *)0, cfile
);
341 hardware
-> hbuf
[0] = HTYPE_ETHER
;
344 hardware
-> hbuf
[0] = HTYPE_IEEE802
;
347 hardware
-> hbuf
[0] = HTYPE_FDDI
;
350 if (!strncmp (val
, "unknown-", 8)) {
351 hardware
-> hbuf
[0] = atoi (&val
[8]);
354 "expecting a network hardware type");
355 skip_to_semi (cfile
);
361 /* Parse the hardware address information. Technically,
362 it would make a lot of sense to restrict the length of the
363 data we'll accept here to the length of a particular hardware
364 address type. Unfortunately, there are some broken clients
365 out there that put bogus data in the chaddr buffer, and we accept
366 that data in the lease file rather than simply failing on such
369 token
= peek_token (&val
, (unsigned *)0, cfile
);
371 hardware
-> hlen
= 1;
374 t
= parse_numeric_aggregate (cfile
, (unsigned char *)0, &hlen
,
377 hardware
-> hlen
= 1;
380 if (hlen
+ 1 > sizeof hardware
-> hbuf
) {
382 parse_warn (cfile
, "hardware address too long");
384 hardware
-> hlen
= hlen
+ 1;
385 memcpy ((unsigned char *)&hardware
-> hbuf
[1], t
, hlen
);
386 if (hlen
+ 1 < sizeof hardware
-> hbuf
)
387 memset (&hardware
-> hbuf
[hlen
+ 1], 0,
388 (sizeof hardware
-> hbuf
) - hlen
- 1);
393 token
= next_token (&val
, (unsigned *)0, cfile
);
395 parse_warn (cfile
, "expecting semicolon.");
396 skip_to_semi (cfile
);
400 /* lease-time :== NUMBER SEMI */
402 void parse_lease_time (cfile
, timep
)
407 enum dhcp_token token
;
409 token
= next_token (&val
, (unsigned *)0, cfile
);
410 if (token
!= NUMBER
) {
411 parse_warn (cfile
, "Expecting numeric lease time");
412 skip_to_semi (cfile
);
415 convert_num (cfile
, (unsigned char *)timep
, val
, 10, 32);
416 /* Unswap the number - convert_num returns stuff in NBO. */
417 *timep
= ntohl (*timep
); /* XXX */
422 /* No BNF for numeric aggregates - that's defined by the caller. What
423 this function does is to parse a sequence of numbers seperated by
424 the token specified in seperator. If max is zero, any number of
425 numbers will be parsed; otherwise, exactly max numbers are
426 expected. Base and size tell us how to internalize the numbers
427 once they've been tokenized. */
429 unsigned char *parse_numeric_aggregate (cfile
, buf
,
430 max
, seperator
, base
, size
)
439 enum dhcp_token token
;
440 unsigned char *bufp
= buf
, *s
, *t
;
445 bufp
= (unsigned char *)dmalloc (*max
* size
/ 8, MDL
);
447 log_fatal ("no space for numeric aggregate");
454 token
= peek_token (&val
, (unsigned *)0, cfile
);
455 if (token
!= seperator
) {
458 if (token
!= RBRACE
&& token
!= LBRACE
)
459 token
= next_token (&val
,
462 parse_warn (cfile
, "too few numbers.");
464 skip_to_semi (cfile
);
465 return (unsigned char *)0;
467 token
= next_token (&val
, (unsigned *)0, cfile
);
469 token
= next_token (&val
, (unsigned *)0, cfile
);
471 if (token
== END_OF_FILE
) {
472 parse_warn (cfile
, "unexpected end of file");
476 /* Allow NUMBER_OR_NAME if base is 16. */
477 if (token
!= NUMBER
&&
478 (base
!= 16 || token
!= NUMBER_OR_NAME
)) {
479 parse_warn (cfile
, "expecting numeric value.");
480 skip_to_semi (cfile
);
481 return (unsigned char *)0;
483 /* If we can, convert the number now; otherwise, build
484 a linked list of all the numbers. */
486 convert_num (cfile
, s
, val
, base
, size
);
489 t
= (unsigned char *)dmalloc (strlen (val
) + 1, MDL
);
491 log_fatal ("no temp space for number.");
492 strcpy ((char *)t
, val
);
493 c
= cons ((caddr_t
)t
, c
);
495 } while (++count
!= *max
);
497 /* If we had to cons up a list, convert it now. */
499 bufp
= (unsigned char *)dmalloc (count
* size
/ 8, MDL
);
501 log_fatal ("no space for numeric aggregate.");
502 s
= bufp
+ count
- size
/ 8;
507 convert_num (cfile
, s
, (char *)(c
-> car
), base
, size
);
509 /* Free up temp space. */
510 dfree (c
-> car
, MDL
);
517 void convert_num (cfile
, buf
, str
, base
, size
)
524 const char *ptr
= str
;
535 /* If base wasn't specified, figure it out from the data. */
537 if (ptr
[0] == '0') {
538 if (ptr
[1] == 'x') {
541 } else if (isascii (ptr
[1]) && isdigit (ptr
[1])) {
554 /* XXX assumes ASCII... */
556 tval
= tval
- 'a' + 10;
557 else if (tval
>= 'A')
558 tval
= tval
- 'A' + 10;
559 else if (tval
>= '0')
562 parse_warn (cfile
, "Bogus number: %s.", str
);
567 "Bogus number %s: digit %d not in base %d",
571 val
= val
* base
+ tval
;
575 max
= (1 << (size
- 1));
577 max
= (1 << (size
- 1)) + ((1 << (size
- 1)) - 1);
582 "%s%lo exceeds max (%d) for precision.",
584 (unsigned long)val
, max
);
588 "%s%lx exceeds max (%d) for precision.",
590 (unsigned long)val
, max
);
594 "%s%lu exceeds max (%d) for precision.",
596 (unsigned long)val
, max
);
604 *buf
= -(unsigned long)val
;
607 putShort (buf
, -(long)val
);
610 putLong (buf
, -(long)val
);
614 "Unexpected integer size: %d\n", size
);
620 *buf
= (u_int8_t
)val
;
623 putUShort (buf
, (u_int16_t
)val
);
630 "Unexpected integer size: %d\n", size
);
637 * date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER
638 * NUMBER COLON NUMBER COLON NUMBER SEMI |
639 * NUMBER NUMBER SLASH NUMBER SLASH NUMBER
640 * NUMBER COLON NUMBER COLON NUMBER NUMBER SEMI |
643 * Dates are stored in GMT or with a timezone offset; first number is day
644 * of week; next is year/month/day; next is hours:minutes:seconds on a
645 * 24-hour clock, followed by the timezone offset in seconds, which is
649 TIME
parse_date (cfile
)
654 int tzoff
, year
, mon
, mday
, hour
, min
, sec
;
656 enum dhcp_token token
;
657 static int months
[11] = { 31, 59, 90, 120, 151, 181,
658 212, 243, 273, 304, 334 };
660 /* Day of week, or "never"... */
661 token
= next_token (&val
, (unsigned *)0, cfile
);
662 if (token
== NEVER
) {
663 if (!parse_semi (cfile
))
668 if (token
!= NUMBER
) {
669 parse_warn (cfile
, "numeric day of week expected.");
671 skip_to_semi (cfile
);
674 /* We completely ignore wday */
677 token
= next_token (&val
, (unsigned *)0, cfile
);
678 if (token
!= NUMBER
) {
679 parse_warn (cfile
, "numeric year expected.");
681 skip_to_semi (cfile
);
685 /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until
686 somebody invents a time machine, I think we can safely disregard
687 it. This actually works around a stupid Y2K bug that was present
688 in a very early beta release of dhcpd. */
693 /* Slash seperating year from month... */
694 token
= next_token (&val
, (unsigned *)0, cfile
);
695 if (token
!= SLASH
) {
697 "expected slash seperating year from month.");
699 skip_to_semi (cfile
);
704 token
= next_token (&val
, (unsigned *)0, cfile
);
705 if (token
!= NUMBER
) {
706 parse_warn (cfile
, "numeric month expected.");
708 skip_to_semi (cfile
);
711 mon
= atoi (val
) - 1;
713 /* Slash seperating month from day... */
714 token
= next_token (&val
, (unsigned *)0, cfile
);
715 if (token
!= SLASH
) {
717 "expected slash seperating month from day.");
719 skip_to_semi (cfile
);
723 /* Day of month... */
724 token
= next_token (&val
, (unsigned *)0, cfile
);
725 if (token
!= NUMBER
) {
726 parse_warn (cfile
, "numeric day of month expected.");
728 skip_to_semi (cfile
);
734 token
= next_token (&val
, (unsigned *)0, cfile
);
735 if (token
!= NUMBER
) {
736 parse_warn (cfile
, "numeric hour expected.");
738 skip_to_semi (cfile
);
743 /* Colon seperating hour from minute... */
744 token
= next_token (&val
, (unsigned *)0, cfile
);
745 if (token
!= COLON
) {
747 "expected colon seperating hour from minute.");
749 skip_to_semi (cfile
);
754 token
= next_token (&val
, (unsigned *)0, cfile
);
755 if (token
!= NUMBER
) {
756 parse_warn (cfile
, "numeric minute expected.");
758 skip_to_semi (cfile
);
763 /* Colon seperating minute from second... */
764 token
= next_token (&val
, (unsigned *)0, cfile
);
765 if (token
!= COLON
) {
767 "expected colon seperating hour from minute.");
769 skip_to_semi (cfile
);
774 token
= next_token (&val
, (unsigned *)0, cfile
);
775 if (token
!= NUMBER
) {
776 parse_warn (cfile
, "numeric minute expected.");
778 skip_to_semi (cfile
);
783 token
= peek_token (&val
, (unsigned *)0, cfile
);
784 if (token
== NUMBER
) {
785 token
= next_token (&val
, (unsigned *)0, cfile
);
790 /* Make sure the date ends in a semicolon... */
791 if (!parse_semi (cfile
))
794 /* Guess the time value... */
795 guess
= ((((((365 * (year
- 70) + /* Days in years since '70 */
796 (year
- 69) / 4 + /* Leap days since '70 */
797 (mon
/* Days in months this year */
800 (mon
> 1 && /* Leap day this year */
801 !((year
- 72) & 3)) +
802 mday
- 1) * 24) + /* Day of month */
804 min
) * 60) + sec
+ tzoff
;
806 /* This guess could be wrong because of leap seconds or other
807 weirdness we don't know about that the system does. For
808 now, we're just going to accept the guess, but at some point
809 it might be nice to do a successive approximation here to
810 get an exact value. Even if the error is small, if the
811 server is restarted frequently (and thus the lease database
812 is reread), the error could accumulate into something
819 * option-name :== IDENTIFIER |
820 IDENTIFIER . IDENTIFIER
823 struct option
*parse_option_name (cfile
, allocate
, known
)
829 enum dhcp_token token
;
831 struct universe
*universe
;
832 struct option
*option
;
834 token
= next_token (&val
, (unsigned *)0, cfile
);
835 if (!is_identifier (token
)) {
837 "expecting identifier after option keyword.");
839 skip_to_semi (cfile
);
840 return (struct option
*)0;
842 uname
= dmalloc (strlen (val
) + 1, MDL
);
844 log_fatal ("no memory for uname information.");
846 token
= peek_token (&val
, (unsigned *)0, cfile
);
848 /* Go ahead and take the DOT token... */
849 token
= next_token (&val
, (unsigned *)0, cfile
);
851 /* The next token should be an identifier... */
852 token
= next_token (&val
, (unsigned *)0, cfile
);
853 if (!is_identifier (token
)) {
854 parse_warn (cfile
, "expecting identifier after '.'");
856 skip_to_semi (cfile
);
857 return (struct option
*)0;
860 /* Look up the option name hash table for the specified
862 universe
= (struct universe
*)0;
863 if (!universe_hash_lookup (&universe
, universe_hash
,
865 parse_warn (cfile
, "no option space named %s.", uname
);
866 skip_to_semi (cfile
);
867 return (struct option
*)0;
870 /* Use the default hash table, which contains all the
871 standard dhcp option names. */
873 universe
= &dhcp_universe
;
876 /* Look up the actual option info... */
877 option
= (struct option
*)0;
878 option_hash_lookup (&option
, universe
-> hash
, val
, 0, MDL
);
880 /* If we didn't get an option structure, it's an undefined option. */
885 /* If we've been told to allocate, that means that this
886 (might) be an option code definition, so we'll create
887 an option structure just in case. */
889 option
= new_option (MDL
);
891 option
-> name
= val
;
895 s
= dmalloc (strlen (val
) + 1, MDL
);
897 log_fatal ("no memory for option %s.%s",
898 universe
-> name
, val
);
902 option
-> universe
= universe
;
907 parse_warn (cfile
, "no option named %s", val
);
909 parse_warn (cfile
, "no option named %s in space %s",
911 skip_to_semi (cfile
);
912 return (struct option
*)0;
915 /* Free the initial identifier token. */
920 /* IDENTIFIER SEMI */
922 void parse_option_space_decl (cfile
)
927 struct universe
**ua
, *nu
;
930 next_token (&val
, (unsigned *)0, cfile
); /* Discard the SPACE token,
931 which was checked by the
933 token
= next_token (&val
, (unsigned *)0, cfile
);
934 if (!is_identifier (token
)) {
935 parse_warn (cfile
, "expecting identifier.");
936 skip_to_semi (cfile
);
939 nu
= new_universe (MDL
);
941 log_fatal ("No memory for new option space.");
943 /* Set up the server option universe... */
944 s
= dmalloc (strlen (val
) + 1, MDL
);
946 log_fatal ("No memory for new option space name.");
949 nu
-> lookup_func
= lookup_hashed_option
;
950 nu
-> option_state_dereference
=
951 hashed_option_state_dereference
;
952 nu
-> foreach
= hashed_option_space_foreach
;
953 nu
-> save_func
= save_hashed_option
;
954 nu
-> delete_func
= delete_hashed_option
;
955 nu
-> encapsulate
= hashed_option_space_encapsulate
;
956 nu
-> decode
= parse_option_buffer
;
957 nu
-> length_size
= 1;
959 nu
-> store_tag
= putUChar
;
960 nu
-> store_length
= putUChar
;
961 nu
-> index
= universe_count
++;
962 if (nu
-> index
>= universe_max
) {
963 ua
= dmalloc (universe_max
* 2 * sizeof *ua
, MDL
);
965 log_fatal ("No memory to expand option space array.");
966 memcpy (ua
, universes
, universe_max
* sizeof *ua
);
968 dfree (universes
, MDL
);
971 universes
[nu
-> index
] = nu
;
972 option_new_hash (&nu
-> hash
, 1, MDL
);
974 log_fatal ("Can't allocate %s option hash table.", nu
-> name
);
975 universe_hash_add (universe_hash
, nu
-> name
, 0, nu
, MDL
);
979 /* This is faked up to look good right now. Ideally, this should do a
980 recursive parse and allow arbitrary data structure definitions, but for
981 now it just allows you to specify a single type, an array of single types,
982 a sequence of types, or an array of sequences of types.
984 ocd :== NUMBER EQUALS ocsd SEMI
988 ARRAY OF ocsd_simple_type_sequence
990 ocsd_type_sequence :== LBRACE ocsd_types RBRACE
992 ocsd_simple_type_sequence :== LBRACE ocsd_simple_types RBRACE
994 ocsd_types :== ocsd_type |
997 ocsd_type :== ocsd_simple_type |
998 ARRAY OF ocsd_simple_type
1000 ocsd_simple_types :== ocsd_simple_type |
1001 ocsd_simple_types ocsd_simple_type
1003 ocsd_simple_type :== BOOLEAN |
1005 SIGNED INTEGER NUMBER |
1006 UNSIGNED INTEGER NUMBER |
1010 ENCAPSULATE identifier */
1012 int parse_option_code_definition (cfile
, option
)
1013 struct parse
*cfile
;
1014 struct option
*option
;
1017 enum dhcp_token token
;
1018 unsigned arrayp
= 0;
1020 int no_more_in_record
= 0;
1027 int has_encapsulation
= 0;
1029 /* Parse the option code. */
1030 token
= next_token (&val
, (unsigned *)0, cfile
);
1031 if (token
!= NUMBER
) {
1032 parse_warn (cfile
, "expecting option code number.");
1033 skip_to_semi (cfile
);
1036 option
-> code
= atoi (val
);
1038 token
= next_token (&val
, (unsigned *)0, cfile
);
1039 if (token
!= EQUAL
) {
1040 parse_warn (cfile
, "expecting \"=\"");
1041 skip_to_semi (cfile
);
1045 /* See if this is an array. */
1046 token
= next_token (&val
, (unsigned *)0, cfile
);
1047 if (token
== ARRAY
) {
1048 token
= next_token (&val
, (unsigned *)0, cfile
);
1050 parse_warn (cfile
, "expecting \"of\".");
1051 skip_to_semi (cfile
);
1055 token
= next_token (&val
, (unsigned *)0, cfile
);
1058 if (token
== LBRACE
) {
1060 token
= next_token (&val
, (unsigned *)0, cfile
);
1063 /* At this point we're expecting a data type. */
1065 if (has_encapsulation
) {
1067 "encapsulate must always be the last item.");
1068 skip_to_semi (cfile
);
1075 parse_warn (cfile
, "no nested arrays.");
1076 skip_to_rbrace (cfile
, recordp
);
1078 skip_to_semi (cfile
);
1081 token
= next_token (&val
, (unsigned *)0, cfile
);
1083 parse_warn (cfile
, "expecting \"of\".");
1084 skip_to_semi (cfile
);
1087 arrayp
= recordp
+ 1;
1088 token
= next_token (&val
, (unsigned *)0, cfile
);
1089 if ((recordp
) && (token
== LBRACE
)) {
1091 "only uniform array inside record.");
1092 skip_to_rbrace (cfile
, recordp
+ 1);
1093 skip_to_semi (cfile
);
1103 token
= next_token (&val
, (unsigned *)0, cfile
);
1104 if (token
!= NUMBER
) {
1105 parse_warn (cfile
, "expecting number.");
1106 skip_to_rbrace (cfile
, recordp
);
1108 skip_to_semi (cfile
);
1111 switch (atoi (val
)) {
1113 type
= is_signed
? 'b' : 'B';
1116 type
= is_signed
? 's' : 'S';
1119 type
= is_signed
? 'l' : 'L';
1123 "%s bit precision is not supported.", val
);
1124 skip_to_rbrace (cfile
, recordp
);
1126 skip_to_semi (cfile
);
1133 token
= next_token (&val
, (unsigned *)0, cfile
);
1134 if (token
!= INTEGER
) {
1135 parse_warn (cfile
, "expecting \"integer\" keyword.");
1136 skip_to_rbrace (cfile
, recordp
);
1138 skip_to_semi (cfile
);
1156 parse_warn (cfile
, "arrays of text strings not %s",
1158 skip_to_rbrace (cfile
, recordp
);
1160 skip_to_semi (cfile
);
1163 no_more_in_record
= 1;
1170 token
= next_token (&val
, (unsigned *)0, cfile
);
1171 if (!is_identifier (token
)) {
1173 "expecting option space identifier");
1174 skip_to_semi (cfile
);
1177 if (strlen (val
) + tokix
+ 2 > sizeof (tokbuf
))
1179 tokbuf
[tokix
++] = 'E';
1180 strcpy (&tokbuf
[tokix
], val
);
1181 tokix
+= strlen (val
);
1183 has_encapsulation
= 1;
1187 parse_warn (cfile
, "unknown data type %s", val
);
1188 skip_to_rbrace (cfile
, recordp
);
1190 skip_to_semi (cfile
);
1194 if (tokix
== sizeof tokbuf
) {
1196 parse_warn (cfile
, "too many types in record.");
1197 skip_to_rbrace (cfile
, recordp
);
1199 skip_to_semi (cfile
);
1202 tokbuf
[tokix
++] = type
;
1205 token
= next_token (&val
, (unsigned *)0, cfile
);
1206 if (arrayp
> recordp
) {
1207 if (tokix
== sizeof tokbuf
) {
1209 "too many types in record.");
1210 skip_to_rbrace (cfile
, 1);
1211 skip_to_semi (cfile
);
1215 tokbuf
[tokix
++] = 'a';
1217 if (token
== COMMA
) {
1218 if (no_more_in_record
) {
1220 "%s must be at end of record.",
1221 type
== 't' ? "text" : "string");
1222 skip_to_rbrace (cfile
, 1);
1224 skip_to_semi (cfile
);
1227 token
= next_token (&val
, (unsigned *)0, cfile
);
1230 if (token
!= RBRACE
) {
1231 parse_warn (cfile
, "expecting right brace.");
1232 skip_to_rbrace (cfile
, 1);
1234 skip_to_semi (cfile
);
1238 if (!parse_semi (cfile
)) {
1239 parse_warn (cfile
, "semicolon expected.");
1240 skip_to_semi (cfile
);
1242 skip_to_semi (cfile
);
1245 if (has_encapsulation
&& arrayp
) {
1247 "Arrays of encapsulations don't make sense.");
1250 if (has_encapsulation
&& tokbuf
[0] == 'E')
1251 has_encapsulation
= 0;
1252 s
= dmalloc (tokix
+
1254 (has_encapsulation
? 1 : 0) + 1, MDL
);
1256 log_fatal ("no memory for option format.");
1257 if (has_encapsulation
)
1259 memcpy (s
+ has_encapsulation
, tokbuf
, tokix
);
1260 tokix
+= has_encapsulation
;
1262 s
[tokix
++] = (arrayp
> recordp
) ? 'a' : 'A';
1264 option
-> format
= s
;
1265 if (option
-> universe
-> options
[option
-> code
]) {
1266 /* XXX Free the option, but we can't do that now because they
1267 XXX may start out static. */
1269 option
-> universe
-> options
[option
-> code
] = option
;
1270 option_hash_add (option
-> universe
-> hash
,
1271 (const char *)option
-> name
,
1277 * base64 :== NUMBER_OR_STRING
1280 int parse_base64 (data
, cfile
)
1281 struct data_string
*data
;
1282 struct parse
*cfile
;
1284 enum dhcp_token token
;
1288 static unsigned char
1289 from64
[] = {64, 64, 64, 64, 64, 64, 64, 64, /* \"#$%&' */
1290 64, 64, 64, 62, 64, 64, 64, 63, /* ()*+,-./ */
1291 52, 53, 54, 55, 56, 57, 58, 59, /* 01234567 */
1292 60, 61, 64, 64, 64, 64, 64, 64, /* 89:;<=>? */
1293 64, 0, 1, 2, 3, 4, 5, 6, /* @ABCDEFG */
1294 7, 8, 9, 10, 11, 12, 13, 14, /* HIJKLMNO */
1295 15, 16, 17, 18, 19, 20, 21, 22, /* PQRSTUVW */
1296 23, 24, 25, 64, 64, 64, 64, 64, /* XYZ[\]^_ */
1297 64, 26, 27, 28, 29, 30, 31, 32, /* 'abcdefg */
1298 33, 34, 35, 36, 37, 38, 39, 40, /* hijklmno */
1299 41, 42, 43, 44, 45, 46, 47, 48, /* pqrstuvw */
1300 49, 50, 51, 64, 64, 64, 64, 64}; /* xyz{|}~ */
1301 struct string_list
*bufs
= (struct string_list
*)0,
1302 *last
= (struct string_list
*)0,
1307 /* It's possible for a + or a / to cause a base64 quantity to be
1308 tokenized into more than one token, so we have to parse them all
1309 in before decoding. */
1313 token
= next_token (&val
, &l
, cfile
);
1314 t
= dmalloc (l
+ sizeof *t
, MDL
);
1316 log_fatal ("no memory for base64 buffer.");
1317 memset (t
, 0, (sizeof *t
) - 1);
1318 memcpy (t
-> string
, val
, l
+ 1);
1325 token
= peek_token (&val
, (unsigned *)0, cfile
);
1326 } while (token
== NUMBER_OR_NAME
|| token
== NAME
|| token
== EQUAL
||
1327 token
== NUMBER
|| token
== PLUS
|| token
== SLASH
||
1331 data
-> len
= (data
-> len
* 3) / 4;
1332 if (!buffer_allocate (&data
-> buffer
, data
-> len
, MDL
)) {
1333 parse_warn (cfile
, "can't allocate buffer for base64 data.");
1335 data
-> data
= (unsigned char *)0;
1340 for (t
= bufs
; t
; t
= t
-> next
) {
1341 for (i
= 0; t
-> string
[i
]; i
++) {
1342 unsigned foo
= t
-> string
[i
];
1343 if (terminated
&& foo
!= '=') {
1345 "stuff after base64 '=' terminator: %s.",
1349 if (foo
< ' ' || foo
> 'z') {
1352 "invalid base64 character %d.",
1355 data_string_forget (data
, MDL
);
1361 foo
= from64
[foo
- ' '];
1364 acc
= (acc
<< 6) + foo
;
1369 data
-> buffer
-> data
[j
++] = (acc
>> 4);
1374 data
-> buffer
-> data
[j
++] = (acc
>> 2);
1378 data
-> buffer
-> data
[j
++] = acc
;
1389 "partial base64 value left over: %d.",
1394 data
-> data
= data
-> buffer
-> data
;
1396 for (t
= bufs
; t
; t
= last
) {
1408 * colon-seperated-hex-list :== NUMBER |
1409 * NUMBER COLON colon-seperated-hex-list
1412 int parse_cshl (data
, cfile
)
1413 struct data_string
*data
;
1414 struct parse
*cfile
;
1416 u_int8_t ibuf
[128];
1419 struct option_tag
*sl
= (struct option_tag
*)0;
1420 struct option_tag
*next
, **last
= &sl
;
1421 enum dhcp_token token
;
1426 token
= next_token (&val
, (unsigned *)0, cfile
);
1427 if (token
!= NUMBER
&& token
!= NUMBER_OR_NAME
) {
1428 parse_warn (cfile
, "expecting hexadecimal number.");
1429 skip_to_semi (cfile
);
1430 for (; sl
; sl
= next
) {
1436 if (ilen
== sizeof ibuf
) {
1437 next
= (struct option_tag
*)
1439 sizeof (struct option_tag
), MDL
);
1441 log_fatal ("no memory for string list.");
1442 memcpy (next
-> data
, ibuf
, ilen
);
1444 last
= &next
-> next
;
1448 convert_num (cfile
, &ibuf
[ilen
++], val
, 16, 8);
1450 token
= peek_token (&val
, (unsigned *)0, cfile
);
1453 token
= next_token (&val
, (unsigned *)0, cfile
);
1456 if (!buffer_allocate (&data
-> buffer
, tlen
+ ilen
, MDL
))
1457 log_fatal ("no memory to store octet data.");
1458 data
-> data
= &data
-> buffer
-> data
[0];
1459 data
-> len
= tlen
+ ilen
;
1460 data
-> terminated
= 0;
1462 rvp
= &data
-> buffer
-> data
[0];
1465 memcpy (rvp
, sl
-> data
, sizeof ibuf
);
1471 memcpy (rvp
, ibuf
, ilen
);
1476 * executable-statements :== executable-statement executable-statements |
1477 * executable-statement
1479 * executable-statement :==
1481 * ADD class-name SEMI |
1483 * OPTION option-parameter SEMI |
1484 * SUPERSEDE option-parameter SEMI |
1485 * PREPEND option-parameter SEMI |
1486 * APPEND option-parameter SEMI
1489 int parse_executable_statements (statements
, cfile
, lose
, case_context
)
1490 struct executable_statement
**statements
;
1491 struct parse
*cfile
;
1493 enum expression_context case_context
;
1495 struct executable_statement
**next
;
1498 while (parse_executable_statement (next
, cfile
, lose
, case_context
))
1499 next
= &((*next
) -> next
);
1505 int parse_executable_statement (result
, cfile
, lose
, case_context
)
1506 struct executable_statement
**result
;
1507 struct parse
*cfile
;
1509 enum expression_context case_context
;
1511 enum dhcp_token token
;
1513 // struct executable_statement base;
1515 struct option
*option
;
1516 struct option_cache
*cache
;
1520 struct dns_zone
*zone
;
1521 isc_result_t status
;
1524 token
= peek_token (&val
, (unsigned *)0, cfile
);
1527 next_token (&val
, (unsigned *)0, cfile
);
1528 return parse_if_statement (result
, cfile
, lose
);
1531 token
= next_token (&val
, (unsigned *)0, cfile
);
1532 token
= next_token (&val
, (unsigned *)0, cfile
);
1533 if (token
!= STRING
) {
1534 parse_warn (cfile
, "expecting class name.");
1535 skip_to_semi (cfile
);
1539 cta
= (struct class *)0;
1540 status
= find_class (&cta
, val
, MDL
);
1541 if (status
!= ISC_R_SUCCESS
) {
1542 parse_warn (cfile
, "class %s: %s",
1543 val
, isc_result_totext (status
));
1544 skip_to_semi (cfile
);
1548 if (!parse_semi (cfile
)) {
1552 if (!executable_statement_allocate (result
, MDL
))
1553 log_fatal ("no memory for new statement.");
1554 (*result
) -> op
= add_statement
;
1555 (*result
) -> data
.add
= cta
;
1559 token
= next_token (&val
, (unsigned *)0, cfile
);
1560 if (!parse_semi (cfile
)) {
1564 if (!executable_statement_allocate (result
, MDL
))
1565 log_fatal ("no memory for new statement.");
1566 (*result
) -> op
= break_statement
;
1570 token
= next_token (&val
, (unsigned *)0, cfile
);
1572 option
= parse_option_name (cfile
, 0, &known
);
1577 return parse_option_statement (result
, cfile
, 1, option
,
1578 send_option_statement
);
1582 token
= next_token (&val
, (unsigned *)0, cfile
);
1584 option
= parse_option_name (cfile
, 0, &known
);
1589 return parse_option_statement (result
, cfile
, 1, option
,
1590 supersede_option_statement
);
1601 token
= next_token (&val
, (unsigned *)0, cfile
);
1602 cache
= (struct option_cache
*)0;
1603 if (!parse_allow_deny (&cache
, cfile
, flag
))
1605 if (!executable_statement_allocate (result
, MDL
))
1606 log_fatal ("no memory for new statement.");
1607 (*result
) -> op
= supersede_option_statement
;
1608 (*result
) -> data
.option
= cache
;
1612 token
= next_token (&val
, (unsigned *)0, cfile
);
1613 token
= peek_token (&val
, (unsigned *)0, cfile
);
1615 goto switch_default
;
1617 option
= parse_option_name (cfile
, 0, &known
);
1622 return parse_option_statement (result
, cfile
, 1, option
,
1623 default_option_statement
);
1626 token
= next_token (&val
, (unsigned *)0, cfile
);
1628 option
= parse_option_name (cfile
, 0, &known
);
1633 return parse_option_statement (result
, cfile
, 1, option
,
1634 prepend_option_statement
);
1637 token
= next_token (&val
, (unsigned *)0, cfile
);
1639 option
= parse_option_name (cfile
, 0, &known
);
1644 return parse_option_statement (result
, cfile
, 1, option
,
1645 append_option_statement
);
1648 token
= next_token (&val
, (unsigned *)0, cfile
);
1649 return parse_on_statement (result
, cfile
, lose
);
1652 token
= next_token (&val
, (unsigned *)0, cfile
);
1653 return parse_switch_statement (result
, cfile
, lose
);
1656 token
= next_token (&val
, (unsigned *)0, cfile
);
1657 if (case_context
== context_any
) {
1659 "case statement in inappropriate scope.");
1661 skip_to_semi (cfile
);
1664 return parse_case_statement (result
,
1665 cfile
, lose
, case_context
);
1668 token
= next_token (&val
, (unsigned *)0, cfile
);
1669 if (case_context
== context_any
) {
1670 parse_warn (cfile
, "switch default statement in %s",
1671 "inappropriate scope.");
1676 if (!executable_statement_allocate (result
, MDL
))
1677 log_fatal ("no memory for default statement.");
1678 (*result
) -> op
= default_statement
;
1684 token
= next_token (&val
, (unsigned *)0, cfile
);
1685 if (token
== DEFINE
)
1690 token
= next_token (&val
, (unsigned *)0, cfile
);
1691 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
1693 "%s can't be a variable name", val
);
1695 skip_to_semi (cfile
);
1700 if (!executable_statement_allocate (result
, MDL
))
1701 log_fatal ("no memory for set statement.");
1702 (*result
) -> op
= flag
? define_statement
: set_statement
;
1703 (*result
) -> data
.set
.name
= dmalloc (strlen (val
) + 1, MDL
);
1704 if (!(*result
)->data
.set
.name
)
1705 log_fatal ("can't allocate variable name");
1706 strcpy ((*result
) -> data
.set
.name
, val
);
1707 token
= next_token (&val
, (unsigned *)0, cfile
);
1709 if (token
== LPAREN
) {
1710 struct string_list
*head
, *cur
, *new;
1711 struct expression
*expr
;
1712 head
= cur
= (struct string_list
*)0;
1714 token
= next_token (&val
,
1715 (unsigned *)0, cfile
);
1716 if (token
== RPAREN
)
1718 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
1720 "expecting argument name");
1721 skip_to_rbrace (cfile
, 0);
1723 executable_statement_dereference
1727 new = ((struct string_list
*)
1728 dmalloc (sizeof (struct string_list
) +
1729 strlen (val
), MDL
));
1731 log_fatal ("can't allocate string.");
1732 memset (new, 0, sizeof *new);
1733 strcpy (new -> string
, val
);
1740 token
= next_token (&val
,
1741 (unsigned *)0, cfile
);
1742 } while (token
== COMMA
);
1744 if (token
!= RPAREN
) {
1745 parse_warn (cfile
, "expecting right paren.");
1747 skip_to_semi (cfile
);
1749 executable_statement_dereference (result
, MDL
);
1753 token
= next_token (&val
, (unsigned *)0, cfile
);
1754 if (token
!= LBRACE
) {
1755 parse_warn (cfile
, "expecting left brace.");
1759 expr
= (struct expression
*)0;
1760 if (!(expression_allocate (&expr
, MDL
)))
1761 log_fatal ("can't allocate expression.");
1762 expr
-> op
= expr_function
;
1763 if (!fundef_allocate (&expr
-> data
.func
, MDL
))
1764 log_fatal ("can't allocate fundef.");
1765 expr
-> data
.func
-> args
= head
;
1766 (*result
) -> data
.set
.expr
= expr
;
1768 if (!(parse_executable_statements
1769 (&expr
-> data
.func
-> statements
, cfile
, lose
,
1775 token
= next_token (&val
, (unsigned *)0, cfile
);
1776 if (token
!= RBRACE
) {
1777 parse_warn (cfile
, "expecting rigt brace.");
1781 if (token
!= EQUAL
) {
1783 "expecting '=' in %s statement.",
1784 flag
? "define" : "set");
1788 if (!parse_expression (&(*result
) -> data
.set
.expr
,
1789 cfile
, lose
, context_any
,
1790 (struct expression
**)0,
1794 "expecting expression.");
1797 skip_to_semi (cfile
);
1798 executable_statement_dereference (result
, MDL
);
1801 if (!parse_semi (cfile
)) {
1803 executable_statement_dereference (result
, MDL
);
1810 token
= next_token (&val
, (unsigned *)0, cfile
);
1812 token
= next_token (&val
, (unsigned *)0, cfile
);
1813 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
1815 "%s can't be a variable name", val
);
1816 skip_to_semi (cfile
);
1821 if (!executable_statement_allocate (result
, MDL
))
1822 log_fatal ("no memory for set statement.");
1823 (*result
) -> op
= unset_statement
;
1824 (*result
) -> data
.unset
= dmalloc (strlen (val
) + 1, MDL
);
1825 if (!(*result
)->data
.unset
)
1826 log_fatal ("can't allocate variable name");
1827 strcpy ((*result
) -> data
.unset
, val
);
1828 if (!parse_semi (cfile
)) {
1830 executable_statement_dereference (result
, MDL
);
1836 token
= next_token (&val
, (unsigned *)0, cfile
);
1838 if (!executable_statement_allocate (result
, MDL
))
1839 log_fatal ("no memory for eval statement.");
1840 (*result
) -> op
= eval_statement
;
1842 if (!parse_expression (&(*result
) -> data
.eval
,
1843 cfile
, lose
, context_data
, /* XXX */
1844 (struct expression
**)0, expr_none
)) {
1847 "expecting data expression.");
1850 skip_to_semi (cfile
);
1851 executable_statement_dereference (result
, MDL
);
1854 if (!parse_semi (cfile
)) {
1856 executable_statement_dereference (result
, MDL
);
1861 token
= next_token (&val
, (unsigned *)0, cfile
);
1863 if (!executable_statement_allocate (result
, MDL
))
1864 log_fatal ("no memory for return statement.");
1865 (*result
) -> op
= return_statement
;
1867 if (!parse_expression (&(*result
) -> data
.retval
,
1868 cfile
, lose
, context_data
,
1869 (struct expression
**)0, expr_none
)) {
1872 "expecting data expression.");
1875 skip_to_semi (cfile
);
1876 executable_statement_dereference (result
, MDL
);
1879 if (!parse_semi (cfile
)) {
1881 executable_statement_dereference (result
, MDL
);
1887 token
= next_token (&val
, (unsigned *)0, cfile
);
1889 if (!executable_statement_allocate (result
, MDL
))
1890 log_fatal ("no memory for log statement.");
1891 (*result
) -> op
= log_statement
;
1893 token
= next_token (&val
, (unsigned *)0, cfile
);
1894 if (token
!= LPAREN
) {
1895 parse_warn (cfile
, "left parenthesis expected.");
1896 skip_to_semi (cfile
);
1901 token
= peek_token (&val
, (unsigned *)0, cfile
);
1903 if (token
== FATAL
) {
1904 (*result
) -> data
.log
.priority
= log_priority_fatal
;
1905 } else if (token
== ERROR
) {
1906 (*result
) -> data
.log
.priority
= log_priority_error
;
1907 } else if (token
== TOKEN_DEBUG
) {
1908 (*result
) -> data
.log
.priority
= log_priority_debug
;
1909 } else if (token
== INFO
) {
1910 (*result
) -> data
.log
.priority
= log_priority_info
;
1912 (*result
) -> data
.log
.priority
= log_priority_debug
;
1916 token
= next_token (&val
, (unsigned *)0, cfile
);
1917 token
= next_token (&val
, (unsigned *)0, cfile
);
1918 if (token
!= COMMA
) {
1919 parse_warn (cfile
, "comma expected.");
1920 skip_to_semi (cfile
);
1926 if (!(parse_data_expression
1927 (&(*result
) -> data
.log
.expr
, cfile
, lose
))) {
1928 skip_to_semi (cfile
);
1933 token
= next_token (&val
, (unsigned *)0, cfile
);
1934 if (token
!= RPAREN
) {
1935 parse_warn (cfile
, "right parenthesis expected.");
1936 skip_to_semi (cfile
);
1941 token
= next_token (&val
, (unsigned *)0, cfile
);
1942 if (token
!= SEMI
) {
1943 parse_warn (cfile
, "semicolon expected.");
1944 skip_to_semi (cfile
);
1950 /* Not really a statement, but we parse it here anyway
1951 because it's appropriate for all DHCP agents with
1954 token
= next_token (&val
, (unsigned *)0, cfile
);
1955 zone
= (struct dns_zone
*)0;
1956 if (!dns_zone_allocate (&zone
, MDL
))
1957 log_fatal ("no memory for new zone.");
1958 zone
-> name
= parse_host_name (cfile
);
1959 if (!zone
-> name
) {
1960 parse_warn (cfile
, "expecting hostname.");
1963 skip_to_semi (cfile
);
1964 dns_zone_dereference (&zone
, MDL
);
1967 i
= strlen (zone
-> name
);
1968 if (zone
-> name
[i
- 1] != '.') {
1969 s
= dmalloc ((unsigned)i
+ 2, MDL
);
1971 parse_warn (cfile
, "no trailing '.' on zone");
1974 strcpy (s
, zone
-> name
);
1977 dfree (zone
-> name
, MDL
);
1980 if (!parse_zone (zone
, cfile
))
1982 status
= enter_dns_zone (zone
);
1983 if (status
!= ISC_R_SUCCESS
) {
1984 parse_warn (cfile
, "dns zone key %s: %s",
1985 zone
-> name
, isc_result_totext (status
));
1986 dns_zone_dereference (&zone
, MDL
);
1989 dns_zone_dereference (&zone
, MDL
);
1992 /* Also not really a statement, but same idea as above. */
1994 token
= next_token (&val
, (unsigned *)0, cfile
);
1995 if (!parse_key (cfile
)) {
2002 if (config_universe
&& is_identifier (token
)) {
2003 option
= (struct option
*)0;
2004 option_hash_lookup (&option
, config_universe
-> hash
,
2007 token
= next_token (&val
,
2008 (unsigned *)0, cfile
);
2009 return parse_option_statement
2010 (result
, cfile
, 1, option
,
2011 supersede_option_statement
);
2015 if (token
== NUMBER_OR_NAME
|| token
== NAME
) {
2016 /* This is rather ugly. Since function calls are
2017 data expressions, fake up an eval statement. */
2018 if (!executable_statement_allocate (result
, MDL
))
2019 log_fatal ("no memory for eval statement.");
2020 (*result
) -> op
= eval_statement
;
2022 if (!parse_expression (&(*result
) -> data
.eval
,
2023 cfile
, lose
, context_data
,
2024 (struct expression
**)0,
2027 parse_warn (cfile
, "expecting "
2031 skip_to_semi (cfile
);
2032 executable_statement_dereference (result
, MDL
);
2035 if (!parse_semi (cfile
)) {
2037 executable_statement_dereference (result
, MDL
);
2050 /* zone-statements :== zone-statement |
2051 zone-statement zone-statements
2053 PRIMARY ip-addresses SEMI |
2054 SECONDARY ip-addresses SEMI |
2056 ip-addresses :== ip-addr-or-hostname |
2057 ip-addr-or-hostname COMMA ip-addresses
2058 key-reference :== KEY STRING |
2061 int parse_zone (struct dns_zone
*zone
, struct parse
*cfile
)
2066 struct option_cache
*oc
;
2069 token
= next_token (&val
, (unsigned *)0, cfile
);
2070 if (token
!= LBRACE
) {
2071 parse_warn (cfile
, "expecting left brace");
2076 token
= peek_token (&val
, (unsigned *)0, cfile
);
2079 if (zone
-> primary
) {
2081 "more than one primary.");
2082 skip_to_semi (cfile
);
2085 if (!option_cache_allocate (&zone
-> primary
, MDL
))
2086 log_fatal ("can't allocate primary option cache.");
2087 oc
= zone
-> primary
;
2091 if (zone
-> secondary
) {
2092 parse_warn (cfile
, "more than one secondary.");
2093 skip_to_semi (cfile
);
2096 if (!option_cache_allocate (&zone
-> secondary
, MDL
))
2097 log_fatal ("can't allocate secondary.");
2098 oc
= zone
-> secondary
;
2100 token
= next_token (&val
, (unsigned *)0, cfile
);
2102 struct expression
*expr
= (struct expression
*)0;
2103 if (!parse_ip_addr_or_hostname (&expr
, cfile
, 0)) {
2105 "expecting IP addr or hostname.");
2106 skip_to_semi (cfile
);
2109 if (oc
-> expression
) {
2110 struct expression
*old
=
2111 (struct expression
*)0;
2112 expression_reference (&old
,
2115 expression_dereference (&oc
-> expression
,
2117 if (!make_concat (&oc
-> expression
,
2119 log_fatal ("no memory for concat.");
2120 expression_dereference (&expr
, MDL
);
2121 expression_dereference (&old
, MDL
);
2123 expression_reference (&oc
-> expression
,
2125 expression_dereference (&expr
, MDL
);
2127 token
= next_token (&val
, (unsigned *)0, cfile
);
2128 } while (token
== COMMA
);
2129 if (token
!= SEMI
) {
2130 parse_warn (cfile
, "expecting semicolon.");
2131 skip_to_semi (cfile
);
2137 token
= next_token (&val
, (unsigned *)0, cfile
);
2138 token
= peek_token (&val
, (unsigned *)0, cfile
);
2139 if (token
== STRING
) {
2140 token
= next_token (&val
, (unsigned *)0, cfile
);
2141 key_name
= (char *)0;
2143 key_name
= parse_host_name (cfile
);
2145 parse_warn (cfile
, "expecting key name.");
2146 skip_to_semi (cfile
);
2151 if (omapi_auth_key_lookup_name (&zone
-> key
, val
) !=
2153 parse_warn (cfile
, "unknown key %s", val
);
2155 dfree (key_name
, MDL
);
2156 if (!parse_semi (cfile
))
2166 token
= next_token (&val
, (unsigned *)0, cfile
);
2167 if (token
!= RBRACE
) {
2168 parse_warn (cfile
, "expecting right brace.");
2174 /* key-statements :== key-statement |
2175 key-statement key-statements
2177 ALGORITHM host-name SEMI |
2178 secret-definition SEMI
2179 secret-definition :== SECRET base64val |
2182 int parse_key (struct parse
*cfile
)
2187 struct auth_key
*key
;
2188 struct data_string ds
;
2189 isc_result_t status
;
2192 key
= (struct auth_key
*)0;
2193 if (omapi_auth_key_new (&key
, MDL
) != ISC_R_SUCCESS
)
2194 log_fatal ("no memory for key");
2196 token
= peek_token (&val
, (unsigned *)0, cfile
);
2197 if (token
== STRING
) {
2198 token
= next_token (&val
, (unsigned *)0, cfile
);
2199 key
-> name
= dmalloc (strlen (val
) + 1, MDL
);
2201 log_fatal ("no memory for key name.");
2202 strcpy (key
-> name
, val
);
2205 key
-> name
= parse_host_name (cfile
);
2207 parse_warn (cfile
, "expecting key name.");
2208 skip_to_semi (cfile
);
2213 token
= next_token (&val
, (unsigned *)0, cfile
);
2214 if (token
!= LBRACE
) {
2215 parse_warn (cfile
, "expecting left brace");
2220 token
= next_token (&val
, (unsigned *)0, cfile
);
2223 if (key
-> algorithm
) {
2225 "key %s: too many algorithms",
2229 key
-> algorithm
= parse_host_name (cfile
);
2230 if (!key
-> algorithm
) {
2232 "expecting key algorithm name.");
2235 if (!parse_semi (cfile
))
2237 /* If the algorithm name isn't an FQDN, tack on
2238 the .SIG-ALG.REG.NET. domain. */
2239 s
= strrchr (key
-> algorithm
, '.');
2241 static char add
[] = ".SIG-ALG.REG.INT.";
2242 s
= dmalloc (strlen (key
-> algorithm
) +
2245 log_error ("no memory for key %s.",
2249 strcpy (s
, key
-> algorithm
);
2251 dfree (key
-> algorithm
, MDL
);
2252 key
-> algorithm
= s
;
2254 /* If there is no trailing '.', hack one in. */
2255 s
= dmalloc (strlen (key
-> algorithm
) + 2, MDL
);
2257 log_error ("no memory for key %s.",
2261 strcpy (s
, key
-> algorithm
);
2263 dfree (key
-> algorithm
, MDL
);
2264 key
-> algorithm
= s
;
2270 parse_warn (cfile
, "key %s: too many secrets",
2275 memset (&ds
, 0, sizeof(ds
));
2276 if (!parse_base64 (&ds
, cfile
))
2278 status
= omapi_data_string_new (&key
-> key
, ds
.len
,
2280 if (status
!= ISC_R_SUCCESS
)
2282 memcpy (key
-> key
-> value
,
2283 ds
.buffer
-> data
, ds
.len
);
2284 data_string_forget (&ds
, MDL
);
2286 if (!parse_semi (cfile
))
2295 if (token
!= RBRACE
) {
2296 parse_warn (cfile
, "expecting right brace.");
2299 /* Allow the BIND 8 syntax, which has a semicolon after each
2301 token
= peek_token (&val
, (unsigned *)0, cfile
);
2303 token
= next_token (&val
, (unsigned *)0, cfile
);
2305 /* Remember the key. */
2306 status
= omapi_auth_key_enter (key
);
2307 if (status
!= ISC_R_SUCCESS
) {
2308 parse_warn (cfile
, "tsig key %s: %s",
2309 key
-> name
, isc_result_totext (status
));
2312 omapi_auth_key_dereference (&key
, MDL
);
2316 skip_to_rbrace (cfile
, 1);
2318 omapi_auth_key_dereference (&key
, MDL
);
2323 * on-statement :== event-types LBRACE executable-statements RBRACE
2324 * event-types :== event-type OR event-types |
2326 * event-type :== EXPIRY | COMMIT | RELEASE
2329 int parse_on_statement (result
, cfile
, lose
)
2330 struct executable_statement
**result
;
2331 struct parse
*cfile
;
2334 enum dhcp_token token
;
2337 if (!executable_statement_allocate (result
, MDL
))
2338 log_fatal ("no memory for new statement.");
2339 (*result
) -> op
= on_statement
;
2342 token
= next_token (&val
, (unsigned *)0, cfile
);
2345 (*result
) -> data
.on
.evtypes
|= ON_EXPIRY
;
2349 (*result
) -> data
.on
.evtypes
|= ON_COMMIT
;
2353 (*result
) -> data
.on
.evtypes
|= ON_RELEASE
;
2357 (*result
) -> data
.on
.evtypes
|= ON_TRANSMISSION
;
2361 parse_warn (cfile
, "expecting a lease event type");
2362 skip_to_semi (cfile
);
2364 executable_statement_dereference (result
, MDL
);
2367 token
= next_token (&val
, (unsigned *)0, cfile
);
2368 } while (token
== OR
);
2370 /* Semicolon means no statements. */
2374 if (token
!= LBRACE
) {
2375 parse_warn (cfile
, "left brace expected.");
2376 skip_to_semi (cfile
);
2378 executable_statement_dereference (result
, MDL
);
2381 if (!parse_executable_statements (&(*result
) -> data
.on
.statements
,
2382 cfile
, lose
, context_any
)) {
2384 /* Try to even things up. */
2386 token
= next_token (&val
,
2387 (unsigned *)0, cfile
);
2388 } while (token
!= END_OF_FILE
&& token
!= RBRACE
);
2389 executable_statement_dereference (result
, MDL
);
2393 token
= next_token (&val
, (unsigned *)0, cfile
);
2394 if (token
!= RBRACE
) {
2395 parse_warn (cfile
, "right brace expected.");
2396 skip_to_semi (cfile
);
2398 executable_statement_dereference (result
, MDL
);
2405 * switch-statement :== LPAREN expr RPAREN LBRACE executable-statements RBRACE
2409 int parse_switch_statement (result
, cfile
, lose
)
2410 struct executable_statement
**result
;
2411 struct parse
*cfile
;
2414 enum dhcp_token token
;
2417 if (!executable_statement_allocate (result
, MDL
))
2418 log_fatal ("no memory for new statement.");
2419 (*result
) -> op
= switch_statement
;
2421 token
= next_token (&val
, (unsigned *)0, cfile
);
2422 if (token
!= LPAREN
) {
2423 parse_warn (cfile
, "expecting left brace.");
2426 skip_to_semi (cfile
);
2428 executable_statement_dereference (result
, MDL
);
2432 if (!parse_expression (&(*result
) -> data
.s_switch
.expr
,
2433 cfile
, lose
, context_data_or_numeric
,
2434 (struct expression
**)0, expr_none
)) {
2437 "expecting data or numeric expression.");
2443 token
= next_token (&val
, (unsigned *)0, cfile
);
2444 if (token
!= RPAREN
) {
2445 parse_warn (cfile
, "right paren expected.");
2449 token
= next_token (&val
, (unsigned *)0, cfile
);
2450 if (token
!= LBRACE
) {
2451 parse_warn (cfile
, "left brace expected.");
2454 if (!(parse_executable_statements
2455 (&(*result
) -> data
.s_switch
.statements
, cfile
, lose
,
2456 (is_data_expression ((*result
) -> data
.s_switch
.expr
)
2457 ? context_data
: context_numeric
)))) {
2459 skip_to_rbrace (cfile
, 1);
2460 executable_statement_dereference (result
, MDL
);
2464 token
= next_token (&val
, (unsigned *)0, cfile
);
2465 if (token
!= RBRACE
) {
2466 parse_warn (cfile
, "right brace expected.");
2473 * case-statement :== CASE expr COLON
2477 int parse_case_statement (result
, cfile
, lose
, case_context
)
2478 struct executable_statement
**result
;
2479 struct parse
*cfile
;
2481 enum expression_context case_context
;
2483 enum dhcp_token token
;
2486 if (!executable_statement_allocate (result
, MDL
))
2487 log_fatal ("no memory for new statement.");
2488 (*result
) -> op
= case_statement
;
2490 if (!parse_expression (&(*result
) -> data
.c_case
,
2491 cfile
, lose
, case_context
,
2492 (struct expression
**)0, expr_none
))
2495 parse_warn (cfile
, "expecting %s expression.",
2496 (case_context
== context_data
2497 ? "data" : "numeric"));
2501 skip_to_semi (cfile
);
2502 executable_statement_dereference (result
, MDL
);
2506 token
= next_token (&val
, (unsigned *)0, cfile
);
2507 if (token
!= COLON
) {
2508 parse_warn (cfile
, "colon expected.");
2515 * if-statement :== boolean-expression LBRACE executable-statements RBRACE
2518 * else-statement :== <null> |
2519 * ELSE LBRACE executable-statements RBRACE |
2520 * ELSE IF if-statement |
2521 * ELSIF if-statement
2524 int parse_if_statement (result
, cfile
, lose
)
2525 struct executable_statement
**result
;
2526 struct parse
*cfile
;
2529 enum dhcp_token token
;
2533 if (!executable_statement_allocate (result
, MDL
))
2534 log_fatal ("no memory for if statement.");
2536 (*result
) -> op
= if_statement
;
2538 token
= peek_token (&val
, (unsigned *)0, cfile
);
2539 if (token
== LPAREN
) {
2541 next_token (&val
, (unsigned *)0, cfile
);
2546 if (!parse_boolean_expression (&(*result
) -> data
.ie
.expr
,
2549 parse_warn (cfile
, "boolean expression expected.");
2550 executable_statement_dereference (result
, MDL
);
2554 #if defined (DEBUG_EXPRESSION_PARSE)
2555 print_expression ("if condition", (*result
) -> data
.ie
.expr
);
2558 token
= next_token (&val
, (unsigned *)0, cfile
);
2559 if (token
!= RPAREN
) {
2560 parse_warn (cfile
, "expecting right paren.");
2562 executable_statement_dereference (result
, MDL
);
2566 token
= next_token (&val
, (unsigned *)0, cfile
);
2567 if (token
!= LBRACE
) {
2568 parse_warn (cfile
, "left brace expected.");
2569 skip_to_semi (cfile
);
2571 executable_statement_dereference (result
, MDL
);
2574 if (!parse_executable_statements (&(*result
) -> data
.ie
.tc
,
2575 cfile
, lose
, context_any
)) {
2577 /* Try to even things up. */
2579 token
= next_token (&val
,
2580 (unsigned *)0, cfile
);
2581 } while (token
!= END_OF_FILE
&& token
!= RBRACE
);
2582 executable_statement_dereference (result
, MDL
);
2586 token
= next_token (&val
, (unsigned *)0, cfile
);
2587 if (token
!= RBRACE
) {
2588 parse_warn (cfile
, "right brace expected.");
2589 skip_to_semi (cfile
);
2591 executable_statement_dereference (result
, MDL
);
2594 token
= peek_token (&val
, (unsigned *)0, cfile
);
2595 if (token
== ELSE
) {
2596 token
= next_token (&val
, (unsigned *)0, cfile
);
2597 token
= peek_token (&val
, (unsigned *)0, cfile
);
2599 token
= next_token (&val
, (unsigned *)0, cfile
);
2600 if (!parse_if_statement (&(*result
) -> data
.ie
.fc
,
2604 "expecting if statement");
2605 executable_statement_dereference (result
, MDL
);
2609 } else if (token
!= LBRACE
) {
2610 parse_warn (cfile
, "left brace or if expected.");
2611 skip_to_semi (cfile
);
2613 executable_statement_dereference (result
, MDL
);
2616 token
= next_token (&val
, (unsigned *)0, cfile
);
2617 if (!(parse_executable_statements
2618 (&(*result
) -> data
.ie
.fc
,
2619 cfile
, lose
, context_any
))) {
2620 executable_statement_dereference (result
, MDL
);
2623 token
= next_token (&val
, (unsigned *)0, cfile
);
2624 if (token
!= RBRACE
) {
2625 parse_warn (cfile
, "right brace expected.");
2626 skip_to_semi (cfile
);
2628 executable_statement_dereference (result
, MDL
);
2632 } else if (token
== ELSIF
) {
2633 token
= next_token (&val
, (unsigned *)0, cfile
);
2634 if (!parse_if_statement (&(*result
) -> data
.ie
.fc
,
2638 "expecting conditional.");
2639 executable_statement_dereference (result
, MDL
);
2644 (*result
) -> data
.ie
.fc
= (struct executable_statement
*)0;
2650 * boolean_expression :== CHECK STRING |
2651 * NOT boolean-expression |
2652 * data-expression EQUAL data-expression |
2653 * data-expression BANG EQUAL data-expression |
2654 * boolean-expression AND boolean-expression |
2655 * boolean-expression OR boolean-expression
2656 * EXISTS OPTION-NAME
2659 int parse_boolean_expression (expr
, cfile
, lose
)
2660 struct expression
**expr
;
2661 struct parse
*cfile
;
2664 /* Parse an expression... */
2665 if (!parse_expression (expr
, cfile
, lose
, context_boolean
,
2666 (struct expression
**)0, expr_none
))
2669 if (!is_boolean_expression (*expr
) &&
2670 (*expr
) -> op
!= expr_variable_reference
&&
2671 (*expr
) -> op
!= expr_funcall
) {
2672 parse_warn (cfile
, "Expecting a boolean expression.");
2674 expression_dereference (expr
, MDL
);
2681 * data_expression :== SUBSTRING LPAREN data-expression COMMA
2682 * numeric-expression COMMA
2683 * numeric-expression RPAREN |
2684 * CONCAT LPAREN data-expression COMMA
2685 data-expression RPAREN
2686 * SUFFIX LPAREN data_expression COMMA
2687 * numeric-expression RPAREN |
2688 * OPTION option_name |
2690 * PACKET LPAREN numeric-expression COMMA
2691 * numeric-expression RPAREN |
2693 * colon_seperated_hex_list
2696 int parse_data_expression (expr
, cfile
, lose
)
2697 struct expression
**expr
;
2698 struct parse
*cfile
;
2701 /* Parse an expression... */
2702 if (!parse_expression (expr
, cfile
, lose
, context_data
,
2703 (struct expression
**)0, expr_none
))
2706 if (!is_data_expression (*expr
) &&
2707 (*expr
) -> op
!= expr_variable_reference
&&
2708 (*expr
) -> op
!= expr_funcall
) {
2709 expression_dereference (expr
, MDL
);
2710 parse_warn (cfile
, "Expecting a data expression.");
2718 * numeric-expression :== EXTRACT_INT LPAREN data-expression
2719 * COMMA number RPAREN |
2723 int parse_numeric_expression (expr
, cfile
, lose
)
2724 struct expression
**expr
;
2725 struct parse
*cfile
;
2728 /* Parse an expression... */
2729 if (!parse_expression (expr
, cfile
, lose
, context_numeric
,
2730 (struct expression
**)0, expr_none
))
2733 if (!is_numeric_expression (*expr
) &&
2734 (*expr
) -> op
!= expr_variable_reference
&&
2735 (*expr
) -> op
!= expr_funcall
) {
2736 expression_dereference (expr
, MDL
);
2737 parse_warn (cfile
, "Expecting a numeric expression.");
2745 * dns-expression :==
2746 * UPDATE LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
2747 * data-expression COMMA numeric-expression RPAREN
2748 * DELETE LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
2749 * data-expression RPAREN
2750 * EXISTS LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
2751 * data-expression RPAREN
2752 * NOT EXISTS LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
2753 * data-expression RPAREN
2754 * ns-class :== IN | CHAOS | HS | NUMBER
2755 * ns-type :== A | PTR | MX | TXT | NUMBER
2758 int parse_dns_expression (expr
, cfile
, lose
)
2759 struct expression
**expr
;
2760 struct parse
*cfile
;
2763 /* Parse an expression... */
2764 if (!parse_expression (expr
, cfile
, lose
, context_dns
,
2765 (struct expression
**)0, expr_none
))
2768 if (!is_dns_expression (*expr
) &&
2769 (*expr
) -> op
!= expr_variable_reference
&&
2770 (*expr
) -> op
!= expr_funcall
) {
2771 expression_dereference (expr
, MDL
);
2772 parse_warn (cfile
, "Expecting a dns update subexpression.");
2779 /* Parse a subexpression that does not contain a binary operator. */
2781 int parse_non_binary (expr
, cfile
, lose
, context
)
2782 struct expression
**expr
;
2783 struct parse
*cfile
;
2785 enum expression_context context
;
2787 enum dhcp_token token
;
2789 struct collection
*col
;
2790 // struct option *option;
2791 struct expression
*nexp
, **ep
;
2793 enum expr_op opcode
;
2796 // struct executable_statement *stmt;
2799 // isc_result_t status, code;
2802 token
= peek_token (&val
, (unsigned *)0, cfile
);
2804 /* Check for unary operators... */
2807 token
= next_token (&val
, (unsigned *)0, cfile
);
2808 token
= next_token (&val
, (unsigned *)0, cfile
);
2809 if (token
!= STRING
) {
2810 parse_warn (cfile
, "string expected.");
2811 skip_to_semi (cfile
);
2815 for (col
= collections
; col
; col
= col
-> next
)
2816 if (!strcmp (col
-> name
, val
))
2819 parse_warn (cfile
, "unknown collection.");
2823 if (!expression_allocate (expr
, MDL
))
2824 log_fatal ("can't allocate expression");
2825 (*expr
) -> op
= expr_check
;
2826 (*expr
) -> data
.check
= col
;
2830 token
= next_token (&val
, (unsigned *)0, cfile
);
2831 if (context
== context_dns
) {
2832 token
= peek_token (&val
, (unsigned *)0, cfile
);
2835 if (!expression_allocate (expr
, MDL
))
2836 log_fatal ("can't allocate expression");
2837 (*expr
) -> op
= expr_not
;
2838 if (!parse_non_binary (&(*expr
) -> data
.not,
2839 cfile
, lose
, context_boolean
)) {
2841 parse_warn (cfile
, "expression expected");
2842 skip_to_semi (cfile
);
2845 expression_dereference (expr
, MDL
);
2848 if (!is_boolean_expression ((*expr
) -> data
.not)) {
2850 parse_warn (cfile
, "boolean expression expected");
2851 skip_to_semi (cfile
);
2852 expression_dereference (expr
, MDL
);
2858 token
= next_token (&val
, (unsigned *)0, cfile
);
2859 if (!parse_expression (expr
, cfile
, lose
, context
,
2860 (struct expression
**)0, expr_none
)) {
2862 parse_warn (cfile
, "expression expected");
2863 skip_to_semi (cfile
);
2868 token
= next_token (&val
, (unsigned *)0, cfile
);
2869 if (token
!= RPAREN
) {
2871 parse_warn (cfile
, "right paren expected");
2872 skip_to_semi (cfile
);
2878 if (context
== context_dns
)
2880 token
= next_token (&val
, (unsigned *)0, cfile
);
2881 if (!expression_allocate (expr
, MDL
))
2882 log_fatal ("can't allocate expression");
2883 (*expr
) -> op
= expr_exists
;
2885 (*expr
) -> data
.option
= parse_option_name (cfile
, 0, &known
);
2886 if (!(*expr
) -> data
.option
) {
2888 expression_dereference (expr
, MDL
);
2894 token
= next_token (&val
, (unsigned *)0, cfile
);
2895 if (!expression_allocate (expr
, MDL
))
2896 log_fatal ("can't allocate expression");
2897 (*expr
) -> op
= expr_static
;
2901 token
= next_token (&val
, (unsigned *)0, cfile
);
2902 if (!expression_allocate (expr
, MDL
))
2903 log_fatal ("can't allocate expression");
2904 (*expr
) -> op
= expr_known
;
2908 token
= next_token (&val
, (unsigned *)0, cfile
);
2909 if (!expression_allocate (expr
, MDL
))
2910 log_fatal ("can't allocate expression");
2911 (*expr
) -> op
= expr_substring
;
2913 token
= next_token (&val
, (unsigned *)0, cfile
);
2914 if (token
!= LPAREN
) {
2916 expression_dereference (expr
, MDL
);
2917 parse_warn (cfile
, "left parenthesis expected.");
2922 if (!parse_data_expression (&(*expr
) -> data
.substring
.expr
,
2925 expression_dereference (expr
, MDL
);
2928 "expecting data expression.");
2929 skip_to_semi (cfile
);
2935 token
= next_token (&val
, (unsigned *)0, cfile
);
2936 if (token
!= COMMA
) {
2938 expression_dereference (expr
, MDL
);
2939 parse_warn (cfile
, "comma expected.");
2945 if (!parse_numeric_expression
2946 (&(*expr
) -> data
.substring
.offset
,cfile
, lose
)) {
2950 "expecting numeric expression.");
2951 skip_to_semi (cfile
);
2954 expression_dereference (expr
, MDL
);
2958 token
= next_token (&val
, (unsigned *)0, cfile
);
2962 if (!parse_numeric_expression
2963 (&(*expr
) -> data
.substring
.len
, cfile
, lose
))
2966 token
= next_token (&val
, (unsigned *)0, cfile
);
2967 if (token
!= RPAREN
) {
2969 parse_warn (cfile
, "right parenthesis expected.");
2971 expression_dereference (expr
, MDL
);
2977 token
= next_token (&val
, (unsigned *)0, cfile
);
2978 if (!expression_allocate (expr
, MDL
))
2979 log_fatal ("can't allocate expression");
2980 (*expr
) -> op
= expr_suffix
;
2982 token
= next_token (&val
, (unsigned *)0, cfile
);
2983 if (token
!= LPAREN
)
2986 if (!parse_data_expression (&(*expr
) -> data
.suffix
.expr
,
2990 token
= next_token (&val
, (unsigned *)0, cfile
);
2994 if (!parse_numeric_expression (&(*expr
) -> data
.suffix
.len
,
2998 token
= next_token (&val
, (unsigned *)0, cfile
);
2999 if (token
!= RPAREN
)
3004 token
= next_token (&val
, (unsigned *)0, cfile
);
3005 if (!expression_allocate (expr
, MDL
))
3006 log_fatal ("can't allocate expression");
3007 (*expr
) -> op
= expr_concat
;
3009 token
= next_token (&val
, (unsigned *)0, cfile
);
3010 if (token
!= LPAREN
)
3013 if (!parse_data_expression (&(*expr
) -> data
.concat
[0],
3017 token
= next_token (&val
, (unsigned *)0, cfile
);
3022 if (!parse_data_expression (&(*expr
) -> data
.concat
[1],
3026 token
= next_token (&val
, (unsigned *)0, cfile
);
3028 if (token
== COMMA
) {
3029 nexp
= (struct expression
*)0;
3030 if (!expression_allocate (&nexp
, MDL
))
3031 log_fatal ("can't allocate at CONCAT2");
3032 nexp
-> op
= expr_concat
;
3033 expression_reference (&nexp
-> data
.concat
[0],
3035 expression_dereference (expr
, MDL
);
3036 expression_reference (expr
, nexp
, MDL
);
3037 expression_dereference (&nexp
, MDL
);
3038 goto concat_another
;
3041 if (token
!= RPAREN
)
3045 case BINARY_TO_ASCII
:
3046 token
= next_token (&val
, (unsigned *)0, cfile
);
3047 if (!expression_allocate (expr
, MDL
))
3048 log_fatal ("can't allocate expression");
3049 (*expr
) -> op
= expr_binary_to_ascii
;
3051 token
= next_token (&val
, (unsigned *)0, cfile
);
3052 if (token
!= LPAREN
)
3055 if (!parse_numeric_expression (&(*expr
) -> data
.b2a
.base
,
3059 token
= next_token (&val
, (unsigned *)0, cfile
);
3063 if (!parse_numeric_expression (&(*expr
) -> data
.b2a
.width
,
3067 token
= next_token (&val
, (unsigned *)0, cfile
);
3071 if (!parse_data_expression (&(*expr
) -> data
.b2a
.seperator
,
3075 token
= next_token (&val
, (unsigned *)0, cfile
);
3079 if (!parse_data_expression (&(*expr
) -> data
.b2a
.buffer
,
3083 token
= next_token (&val
, (unsigned *)0, cfile
);
3084 if (token
!= RPAREN
)
3089 token
= next_token (&val
, (unsigned *)0, cfile
);
3090 if (!expression_allocate (expr
, MDL
))
3091 log_fatal ("can't allocate expression");
3092 (*expr
) -> op
= expr_reverse
;
3094 token
= next_token (&val
, (unsigned *)0, cfile
);
3095 if (token
!= LPAREN
)
3098 if (!(parse_numeric_expression
3099 (&(*expr
) -> data
.reverse
.width
, cfile
, lose
)))
3102 token
= next_token (&val
, (unsigned *)0, cfile
);
3106 if (!(parse_data_expression
3107 (&(*expr
) -> data
.reverse
.buffer
, cfile
, lose
)))
3110 token
= next_token (&val
, (unsigned *)0, cfile
);
3111 if (token
!= RPAREN
)
3116 /* pick (a, b, c) actually produces an internal representation
3117 that looks like pick (a, pick (b, pick (c, nil))). */
3118 token
= next_token (&val
, (unsigned *)0, cfile
);
3119 if (!(expression_allocate (expr
, MDL
)))
3120 log_fatal ("can't allocate expression");
3122 token
= next_token (&val
, (unsigned *)0, cfile
);
3123 if (token
!= LPAREN
)
3126 nexp
= (struct expression
*)0;
3127 expression_reference (&nexp
, *expr
, MDL
);
3129 nexp
-> op
= expr_pick_first_value
;
3130 if (!(parse_data_expression
3131 (&nexp
-> data
.pick_first_value
.car
,
3135 token
= next_token (&val
, (unsigned *)0, cfile
);
3136 if (token
== COMMA
) {
3137 struct expression
*foo
= (struct expression
*)0;
3138 if (!expression_allocate (&foo
, MDL
))
3139 log_fatal ("can't allocate expr");
3140 expression_reference
3141 (&nexp
-> data
.pick_first_value
.cdr
, foo
, MDL
);
3142 expression_dereference (&nexp
, MDL
);
3143 expression_reference (&nexp
, foo
, MDL
);
3144 expression_dereference (&foo
, MDL
);
3146 } while (token
== COMMA
);
3147 expression_dereference (&nexp
, MDL
);
3149 if (token
!= RPAREN
)
3153 /* dns-update and dns-delete are present for historical
3154 purposes, but are deprecated in favor of ns-update
3155 in combination with update, delete, exists and not
3159 #if !defined (NSUPDATE)
3161 "Please rebuild dhcpd with --with-nsupdate.");
3163 token
= next_token (&val
, (unsigned *)0, cfile
);
3164 if (token
== DNS_UPDATE
)
3165 opcode
= expr_ns_add
;
3167 opcode
= expr_ns_delete
;
3169 token
= next_token (&val
, (unsigned *)0, cfile
);
3170 if (token
!= LPAREN
)
3173 token
= next_token (&val
, (unsigned *)0, cfile
);
3174 if (token
!= STRING
) {
3176 "parse_expression: expecting string.");
3178 skip_to_semi (cfile
);
3183 if (!strcasecmp (val
, "a"))
3185 else if (!strcasecmp (val
, "ptr"))
3187 else if (!strcasecmp (val
, "mx"))
3189 else if (!strcasecmp (val
, "cname"))
3191 else if (!strcasecmp (val
, "TXT"))
3194 parse_warn (cfile
, "unexpected rrtype: %s", val
);
3198 s
= (opcode
== expr_ns_add
3200 : "old-dns-delete");
3201 cptr
= dmalloc (strlen (s
) + 1, MDL
);
3203 log_fatal ("can't allocate name for %s", s
);
3205 if (!expression_allocate (expr
, MDL
))
3206 log_fatal ("can't allocate expression");
3207 (*expr
) -> op
= expr_funcall
;
3208 (*expr
) -> data
.funcall
.name
= cptr
;
3210 /* Fake up a function call. */
3211 ep
= &(*expr
) -> data
.funcall
.arglist
;
3212 if (!expression_allocate (ep
, MDL
))
3213 log_fatal ("can't allocate expression");
3214 (*ep
) -> op
= expr_arg
;
3215 if (!make_const_int (&(*ep
) -> data
.arg
.val
, u
))
3216 log_fatal ("can't allocate rrtype value.");
3218 token
= next_token (&val
, (unsigned *)0, cfile
);
3221 ep
= &((*ep
) -> data
.arg
.next
);
3222 if (!expression_allocate (ep
, MDL
))
3223 log_fatal ("can't allocate expression");
3224 (*ep
) -> op
= expr_arg
;
3225 if (!(parse_data_expression (&(*ep
) -> data
.arg
.val
,
3229 token
= next_token (&val
, (unsigned *)0, cfile
);
3233 ep
= &((*ep
) -> data
.arg
.next
);
3234 if (!expression_allocate (ep
, MDL
))
3235 log_fatal ("can't allocate expression");
3236 (*ep
) -> op
= expr_arg
;
3237 if (!(parse_data_expression (&(*ep
) -> data
.arg
.val
,
3241 if (opcode
== expr_ns_add
) {
3242 token
= next_token (&val
, (unsigned *)0, cfile
);
3246 ep
= &((*ep
) -> data
.arg
.next
);
3247 if (!expression_allocate (ep
, MDL
))
3248 log_fatal ("can't allocate expression");
3249 (*ep
) -> op
= expr_arg
;
3250 if (!(parse_numeric_expression (&(*ep
) -> data
.arg
.val
,
3253 "expecting numeric expression.");
3258 token
= next_token (&val
, (unsigned *)0, cfile
);
3259 if (token
!= RPAREN
)
3264 #if !defined (NSUPDATE)
3266 "Please rebuild dhcpd with --with-nsupdate.");
3268 token
= next_token (&val
, (unsigned *)0, cfile
);
3269 if (!expression_allocate (expr
, MDL
))
3270 log_fatal ("can't allocate expression");
3272 token
= next_token (&val
, (unsigned *)0, cfile
);
3273 if (token
!= LPAREN
)
3278 nexp
-> op
= expr_dns_transaction
;
3279 if (!(parse_dns_expression
3280 (&nexp
-> data
.dns_transaction
.car
,
3286 "expecting dns expression.");
3287 expression_dereference (expr
, MDL
);
3292 token
= next_token (&val
, (unsigned *)0, cfile
);
3294 if (token
== COMMA
) {
3295 if (!(expression_allocate
3296 (&nexp
-> data
.dns_transaction
.cdr
,
3299 ("can't allocate expression");
3300 nexp
= nexp
-> data
.dns_transaction
.cdr
;
3302 } while (token
== COMMA
);
3304 if (token
!= RPAREN
)
3308 /* NOT EXISTS is special cased above... */
3310 token
= peek_token (&val
, (unsigned *)0, cfile
);
3311 if (token
!= EXISTS
) {
3312 parse_warn (cfile
, "expecting DNS prerequisite.");
3316 opcode
= expr_ns_not_exists
;
3319 opcode
= expr_ns_add
;
3322 opcode
= expr_ns_delete
;
3325 opcode
= expr_ns_exists
;
3327 token
= next_token (&val
, (unsigned *)0, cfile
);
3329 #if !defined (NSUPDATE)
3331 "Please rebuild dhcpd with --with-nsupdate.");
3333 if (!expression_allocate (expr
, MDL
))
3334 log_fatal ("can't allocate expression");
3335 (*expr
) -> op
= opcode
;
3337 token
= next_token (&val
, (unsigned *)0, cfile
);
3338 if (token
!= LPAREN
)
3341 token
= next_token (&val
, (unsigned *)0, cfile
);
3342 if (!is_identifier (token
) && token
!= NUMBER
) {
3343 parse_warn (cfile
, "expecting identifier or number.");
3345 expression_dereference (expr
, MDL
);
3346 skip_to_semi (cfile
);
3351 if (token
== NUMBER
)
3352 (*expr
) -> data
.ns_add
.rrclass
= atoi (val
);
3353 else if (!strcasecmp (val
, "in"))
3354 (*expr
) -> data
.ns_add
.rrclass
= C_IN
;
3355 else if (!strcasecmp (val
, "chaos"))
3356 (*expr
) -> data
.ns_add
.rrclass
= C_CHAOS
;
3357 else if (!strcasecmp (val
, "hs"))
3358 (*expr
) -> data
.ns_add
.rrclass
= C_HS
;
3360 parse_warn (cfile
, "unexpected rrclass: %s", val
);
3364 token
= next_token (&val
, (unsigned *)0, cfile
);
3368 token
= next_token (&val
, (unsigned *)0, cfile
);
3369 if (!is_identifier (token
) && token
!= NUMBER
) {
3370 parse_warn (cfile
, "expecting identifier or number.");
3374 if (token
== NUMBER
)
3375 (*expr
) -> data
.ns_add
.rrtype
= atoi (val
);
3376 else if (!strcasecmp (val
, "a"))
3377 (*expr
) -> data
.ns_add
.rrtype
= T_A
;
3378 else if (!strcasecmp (val
, "ptr"))
3379 (*expr
) -> data
.ns_add
.rrtype
= T_PTR
;
3380 else if (!strcasecmp (val
, "mx"))
3381 (*expr
) -> data
.ns_add
.rrtype
= T_MX
;
3382 else if (!strcasecmp (val
, "cname"))
3383 (*expr
) -> data
.ns_add
.rrtype
= T_CNAME
;
3384 else if (!strcasecmp (val
, "TXT"))
3385 (*expr
) -> data
.ns_add
.rrtype
= T_TXT
;
3387 parse_warn (cfile
, "unexpected rrtype: %s", val
);
3391 token
= next_token (&val
, (unsigned *)0, cfile
);
3395 if (!(parse_data_expression
3396 (&(*expr
) -> data
.ns_add
.rrname
, cfile
, lose
)))
3399 token
= next_token (&val
, (unsigned *)0, cfile
);
3403 if (!(parse_data_expression
3404 (&(*expr
) -> data
.ns_add
.rrdata
, cfile
, lose
)))
3407 if (opcode
== expr_ns_add
) {
3408 token
= next_token (&val
, (unsigned *)0, cfile
);
3412 if (!(parse_numeric_expression
3413 (&(*expr
) -> data
.ns_add
.ttl
, cfile
,
3417 "expecting numeric expression.");
3422 token
= next_token (&val
, (unsigned *)0, cfile
);
3423 if (token
!= RPAREN
)
3429 if (!expression_allocate (expr
, MDL
))
3430 log_fatal ("can't allocate expression");
3431 (*expr
) -> op
= (token
== OPTION
3433 : expr_config_option
);
3434 token
= next_token (&val
, (unsigned *)0, cfile
);
3436 (*expr
) -> data
.option
= parse_option_name (cfile
, 0, &known
);
3437 if (!(*expr
) -> data
.option
) {
3439 expression_dereference (expr
, MDL
);
3445 token
= next_token (&val
, (unsigned *)0, cfile
);
3446 if (!expression_allocate (expr
, MDL
))
3447 log_fatal ("can't allocate expression");
3448 (*expr
) -> op
= expr_hardware
;
3451 case LEASED_ADDRESS
:
3452 token
= next_token (&val
, (unsigned *)0, cfile
);
3453 if (!expression_allocate (expr
, MDL
))
3454 log_fatal ("can't allocate expression");
3455 (*expr
) -> op
= expr_leased_address
;
3459 token
= next_token (&val
, (unsigned *)0, cfile
);
3460 if (!expression_allocate (expr
, MDL
))
3461 log_fatal ("can't allocate expression");
3462 (*expr
) -> op
= expr_client_state
;
3466 token
= next_token (&val
, (unsigned *)0, cfile
);
3467 if (!expression_allocate (expr
, MDL
))
3468 log_fatal ("can't allocate expression");
3469 (*expr
) -> op
= expr_filename
;
3473 token
= next_token (&val
, (unsigned *)0, cfile
);
3474 if (!expression_allocate (expr
, MDL
))
3475 log_fatal ("can't allocate expression");
3476 (*expr
) -> op
= expr_sname
;
3480 token
= next_token (&val
, (unsigned *)0, cfile
);
3481 if (!expression_allocate (expr
, MDL
))
3482 log_fatal ("can't allocate expression");
3483 (*expr
) -> op
= expr_lease_time
;
3487 token
= next_token (&val
, (unsigned *)0, cfile
);
3488 if (!expression_allocate (expr
, MDL
))
3489 log_fatal ("can't allocate expression");
3490 (*expr
) -> op
= expr_null
;
3493 case HOST_DECL_NAME
:
3494 token
= next_token (&val
, (unsigned *)0, cfile
);
3495 if (!expression_allocate (expr
, MDL
))
3496 log_fatal ("can't allocate expression");
3497 (*expr
) -> op
= expr_host_decl_name
;
3500 case UPDATED_DNS_RR
:
3501 token
= next_token (&val
, (unsigned *)0, cfile
);
3503 token
= next_token (&val
, (unsigned *)0, cfile
);
3504 if (token
!= LPAREN
)
3507 token
= next_token (&val
, (unsigned *)0, cfile
);
3508 if (token
!= STRING
) {
3509 parse_warn (cfile
, "expecting string.");
3514 if (!strcasecmp (val
, "a"))
3515 s
= "ddns-fwd-name";
3516 else if (!strcasecmp (val
, "ptr"))
3517 s
= "ddns-rev-name";
3519 parse_warn (cfile
, "invalid DNS rrtype: %s", val
);
3523 token
= next_token (&val
, (unsigned *)0, cfile
);
3524 if (token
!= RPAREN
)
3527 if (!expression_allocate (expr
, MDL
))
3528 log_fatal ("can't allocate expression");
3529 (*expr
) -> op
= expr_variable_reference
;
3530 (*expr
) -> data
.variable
=
3531 dmalloc (strlen (s
) + 1, MDL
);
3532 if (!(*expr
) -> data
.variable
)
3533 log_fatal ("can't allocate variable name.");
3534 strcpy ((*expr
) -> data
.variable
, s
);
3538 token
= next_token (&val
, (unsigned *)0, cfile
);
3539 if (!expression_allocate (expr
, MDL
))
3540 log_fatal ("can't allocate expression");
3541 (*expr
) -> op
= expr_packet
;
3543 token
= next_token (&val
, (unsigned *)0, cfile
);
3544 if (token
!= LPAREN
)
3547 if (!parse_numeric_expression (&(*expr
) -> data
.packet
.offset
,
3551 token
= next_token (&val
, (unsigned *)0, cfile
);
3555 if (!parse_numeric_expression (&(*expr
) -> data
.packet
.len
,
3559 token
= next_token (&val
, (unsigned *)0, cfile
);
3560 if (token
!= RPAREN
)
3565 token
= next_token (&val
, &len
, cfile
);
3566 if (!make_const_data (expr
, (const unsigned char *)val
,
3568 log_fatal ("can't make constant string expression.");
3572 token
= next_token (&val
, (unsigned *)0, cfile
);
3573 token
= next_token (&val
, (unsigned *)0, cfile
);
3574 if (token
!= LPAREN
) {
3575 parse_warn (cfile
, "left parenthesis expected.");
3580 if (!expression_allocate (expr
, MDL
))
3581 log_fatal ("can't allocate expression");
3583 if (!parse_data_expression (&(*expr
) -> data
.extract_int
,
3587 "expecting data expression.");
3588 skip_to_semi (cfile
);
3591 expression_dereference (expr
, MDL
);
3595 token
= next_token (&val
, (unsigned *)0, cfile
);
3596 if (token
!= COMMA
) {
3597 parse_warn (cfile
, "comma expected.");
3599 expression_dereference (expr
, MDL
);
3603 token
= next_token (&val
, (unsigned *)0, cfile
);
3604 if (token
!= NUMBER
) {
3605 parse_warn (cfile
, "number expected.");
3607 expression_dereference (expr
, MDL
);
3610 switch (atoi (val
)) {
3612 (*expr
) -> op
= expr_extract_int8
;
3616 (*expr
) -> op
= expr_extract_int16
;
3620 (*expr
) -> op
= expr_extract_int32
;
3625 "unsupported integer size %d", atoi (val
));
3627 skip_to_semi (cfile
);
3628 expression_dereference (expr
, MDL
);
3632 token
= next_token (&val
, (unsigned *)0, cfile
);
3633 if (token
!= RPAREN
) {
3634 parse_warn (cfile
, "right parenthesis expected.");
3636 expression_dereference (expr
, MDL
);
3642 token
= next_token (&val
, (unsigned *)0, cfile
);
3643 token
= next_token (&val
, (unsigned *)0, cfile
);
3644 if (token
!= LPAREN
) {
3645 parse_warn (cfile
, "left parenthesis expected.");
3650 if (!expression_allocate (expr
, MDL
))
3651 log_fatal ("can't allocate expression");
3653 if (!parse_numeric_expression (&(*expr
) -> data
.encode_int
,
3655 parse_warn (cfile
, "expecting numeric expression.");
3656 skip_to_semi (cfile
);
3658 expression_dereference (expr
, MDL
);
3662 token
= next_token (&val
, (unsigned *)0, cfile
);
3663 if (token
!= COMMA
) {
3664 parse_warn (cfile
, "comma expected.");
3666 expression_dereference (expr
, MDL
);
3670 token
= next_token (&val
, (unsigned *)0, cfile
);
3671 if (token
!= NUMBER
) {
3672 parse_warn (cfile
, "number expected.");
3674 expression_dereference (expr
, MDL
);
3677 switch (atoi (val
)) {
3679 (*expr
) -> op
= expr_encode_int8
;
3683 (*expr
) -> op
= expr_encode_int16
;
3687 (*expr
) -> op
= expr_encode_int32
;
3692 "unsupported integer size %d", atoi (val
));
3694 skip_to_semi (cfile
);
3695 expression_dereference (expr
, MDL
);
3699 token
= next_token (&val
, (unsigned *)0, cfile
);
3700 if (token
!= RPAREN
) {
3701 parse_warn (cfile
, "right parenthesis expected.");
3703 expression_dereference (expr
, MDL
);
3709 /* If we're in a numeric context, this should just be a
3710 number, by itself. */
3711 if (context
== context_numeric
||
3712 context
== context_data_or_numeric
) {
3713 next_token (&val
, (unsigned *)0, cfile
);
3714 if (!expression_allocate (expr
, MDL
))
3715 log_fatal ("can't allocate expression");
3716 (*expr
) -> op
= expr_const_int
;
3717 (*expr
) -> data
.const_int
= atoi (val
);
3721 case NUMBER_OR_NAME
:
3722 if (!expression_allocate (expr
, MDL
))
3723 log_fatal ("can't allocate expression");
3725 (*expr
) -> op
= expr_const_data
;
3726 if (!parse_cshl (&(*expr
) -> data
.const_data
, cfile
)) {
3727 expression_dereference (expr
, MDL
);
3736 token
= next_token (&val
, (unsigned *)0, cfile
);
3737 if (!expression_allocate (expr
, MDL
))
3738 log_fatal ("can't allocate expression");
3739 (*expr
) -> op
= expr_const_int
;
3740 (*expr
) -> data
.const_int
= known
;
3744 known
= ISC_R_SUCCESS
;
3748 known
= ISC_R_NOTAUTH
;
3752 known
= ISC_R_NOTIMPLEMENTED
;
3756 known
= ISC_R_NOTZONE
;
3760 known
= ISC_R_NXDOMAIN
;
3764 known
= ISC_R_NXRRSET
;
3768 known
= ISC_R_REFUSED
;
3772 known
= ISC_R_SERVFAIL
;
3776 known
= ISC_R_YXDOMAIN
;
3780 known
= ISC_R_YXRRSET
;
3788 known
= S_REBOOTING
;
3792 known
= S_SELECTING
;
3796 known
= S_REQUESTING
;
3808 known
= S_REBINDING
;
3812 token
= next_token (&val
, (unsigned *)0, cfile
);
3813 token
= next_token (&val
, (unsigned *)0, cfile
);
3814 if (token
!= LPAREN
)
3817 token
= next_token (&val
, (unsigned *)0, cfile
);
3818 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
3819 parse_warn (cfile
, "%s can't be a variable name", val
);
3820 skip_to_semi (cfile
);
3825 if (!expression_allocate (expr
, MDL
))
3826 log_fatal ("can't allocate expression");
3827 (*expr
) -> op
= expr_variable_exists
;
3828 (*expr
) -> data
.variable
= dmalloc (strlen (val
) + 1, MDL
);
3829 if (!(*expr
)->data
.variable
)
3830 log_fatal ("can't allocate variable name");
3831 strcpy ((*expr
) -> data
.variable
, val
);
3832 token
= next_token (&val
, (unsigned *)0, cfile
);
3833 if (token
!= RPAREN
)
3837 /* Not a valid start to an expression... */
3839 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
)
3842 token
= next_token (&val
, (unsigned *)0, cfile
);
3844 /* Save the name of the variable being referenced. */
3845 cptr
= dmalloc (strlen (val
) + 1, MDL
);
3847 log_fatal ("can't allocate variable name");
3850 /* Simple variable reference, as far as we can tell. */
3851 token
= peek_token (&val
, (unsigned *)0, cfile
);
3852 if (token
!= LPAREN
) {
3853 if (!expression_allocate (expr
, MDL
))
3854 log_fatal ("can't allocate expression");
3855 (*expr
) -> op
= expr_variable_reference
;
3856 (*expr
) -> data
.variable
= cptr
;
3860 token
= next_token (&val
, (unsigned *)0, cfile
);
3861 if (!expression_allocate (expr
, MDL
))
3862 log_fatal ("can't allocate expression");
3863 (*expr
) -> op
= expr_funcall
;
3864 (*expr
) -> data
.funcall
.name
= cptr
;
3866 /* Now parse the argument list. */
3867 ep
= &(*expr
) -> data
.funcall
.arglist
;
3869 if (!expression_allocate (ep
, MDL
))
3870 log_fatal ("can't allocate expression");
3871 (*ep
) -> op
= expr_arg
;
3872 if (!parse_expression (&(*ep
) -> data
.arg
.val
,
3873 cfile
, lose
, context_any
,
3874 (struct expression
**)0,
3878 "expecting expression.");
3881 skip_to_semi (cfile
);
3882 expression_dereference (expr
, MDL
);
3885 ep
= &((*ep
) -> data
.arg
.next
);
3886 token
= next_token (&val
, (unsigned *)0, cfile
);
3887 } while (token
== COMMA
);
3888 if (token
!= RPAREN
) {
3889 parse_warn (cfile
, "Right parenthesis expected.");
3890 skip_to_semi (cfile
);
3892 expression_dereference (expr
, MDL
);
3900 /* Parse an expression. */
3902 int parse_expression (expr
, cfile
, lose
, context
, plhs
, binop
)
3903 struct expression
**expr
;
3904 struct parse
*cfile
;
3906 enum expression_context context
;
3907 struct expression
**plhs
;
3910 enum dhcp_token token
;
3912 struct expression
*rhs
= (struct expression
*)0, *tmp
;
3913 struct expression
*lhs
= (struct expression
*)0;
3914 enum expr_op next_op
;
3915 enum expression_context
3916 lhs_context
= context_any
,
3917 rhs_context
= context_any
;
3919 /* Consume the left hand side we were passed. */
3921 expression_reference (&lhs
, *plhs
, MDL
);
3922 expression_dereference (plhs
, MDL
);
3926 if (!parse_non_binary (&rhs
, cfile
, lose
, context
)) {
3927 /* If we already have a left-hand side, then it's not
3928 okay for there not to be a right-hand side here, so
3929 we need to flag it as an error. */
3933 "expecting right-hand side.");
3935 skip_to_semi (cfile
);
3937 expression_dereference (&lhs
, MDL
);
3942 /* At this point, rhs contains either an entire subexpression,
3943 or at least a left-hand-side. If we do not see a binary token
3944 as the next token, we're done with the expression. */
3946 token
= peek_token (&val
, (unsigned *)0, cfile
);
3949 token
= next_token (&val
, (unsigned *)0, cfile
);
3950 token
= peek_token (&val
, (unsigned *)0, cfile
);
3951 if (token
!= EQUAL
) {
3952 parse_warn (cfile
, "! in boolean context without =");
3954 skip_to_semi (cfile
);
3956 expression_dereference (&lhs
, MDL
);
3959 next_op
= expr_not_equal
;
3960 context
= expression_context (rhs
);
3964 next_op
= expr_equal
;
3965 context
= expression_context (rhs
);
3970 context
= expression_context (rhs
);
3975 context
= expression_context (rhs
);
3980 context
= expression_context (rhs
);
3984 next_op
= expr_subtract
;
3985 context
= expression_context (rhs
);
3989 next_op
= expr_divide
;
3990 context
= expression_context (rhs
);
3994 next_op
= expr_multiply
;
3995 context
= expression_context (rhs
);
3999 next_op
= expr_remainder
;
4000 context
= expression_context (rhs
);
4004 next_op
= expr_binary_and
;
4005 context
= expression_context (rhs
);
4009 next_op
= expr_binary_or
;
4010 context
= expression_context (rhs
);
4014 next_op
= expr_binary_xor
;
4015 context
= expression_context (rhs
);
4019 next_op
= expr_none
;
4022 /* If we have no lhs yet, we just parsed it. */
4024 /* If there was no operator following what we just parsed,
4025 then we're done - return it. */
4026 if (next_op
== expr_none
) {
4031 rhs
= (struct expression
*)0;
4033 next_token (&val
, (unsigned *)0, cfile
);
4037 /* If the next binary operator is of greater precedence than the
4038 * current operator, then rhs we have parsed so far is actually
4039 * the lhs of the next operator. To get this value, we have to
4042 if (binop
!= expr_none
&& next_op
!= expr_none
&&
4043 op_precedence (binop
, next_op
) < 0) {
4045 /* Eat the subexpression operator token, which we pass to
4046 * parse_expression...we only peek()'d earlier.
4048 token
= next_token (&val
, (unsigned *)0, cfile
);
4050 /* Continue parsing of the right hand side with that token. */
4052 rhs
= (struct expression
*)0;
4053 if (!parse_expression (&rhs
, cfile
, lose
, op_context (next_op
),
4057 "expecting a subexpression");
4062 next_op
= expr_none
;
4065 if (binop
!= expr_none
) {
4066 rhs_context
= expression_context(rhs
);
4067 lhs_context
= expression_context(lhs
);
4069 if ((rhs_context
!= context_any
) && (lhs_context
!= context_any
) &&
4070 (rhs_context
!= lhs_context
)) {
4071 parse_warn (cfile
, "illegal expression relating different types");
4072 skip_to_semi (cfile
);
4073 expression_dereference (&rhs
, MDL
);
4074 expression_dereference (&lhs
, MDL
);
4080 case expr_not_equal
:
4082 if ((rhs_context
!= context_data_or_numeric
) &&
4083 (rhs_context
!= context_data
) &&
4084 (rhs_context
!= context_numeric
) &&
4085 (rhs_context
!= context_any
)) {
4086 parse_warn (cfile
, "expecting data/numeric expression");
4087 skip_to_semi (cfile
);
4088 expression_dereference (&rhs
, MDL
);
4096 if ((rhs_context
!= context_boolean
) &&
4097 (rhs_context
!= context_any
)) {
4098 parse_warn (cfile
, "expecting boolean expressions");
4099 skip_to_semi (cfile
);
4100 expression_dereference (&rhs
, MDL
);
4110 case expr_remainder
:
4111 case expr_binary_and
:
4112 case expr_binary_or
:
4113 case expr_binary_xor
:
4114 if ((rhs_context
!= context_numeric
) &&
4115 (rhs_context
!= context_any
)) {
4116 parse_warn (cfile
, "expecting numeric expressions");
4117 skip_to_semi (cfile
);
4118 expression_dereference (&rhs
, MDL
);
4129 /* Now, if we didn't find a binary operator, we're done parsing
4130 this subexpression, so combine it with the preceding binary
4131 operator and return the result. */
4132 if (next_op
== expr_none
) {
4133 if (!expression_allocate (expr
, MDL
))
4134 log_fatal ("Can't allocate expression!");
4136 (*expr
) -> op
= binop
;
4137 /* All the binary operators' data union members
4138 are the same, so we'll cheat and use the member
4139 for the equals operator. */
4140 (*expr
) -> data
.equal
[0] = lhs
;
4141 (*expr
) -> data
.equal
[1] = rhs
;
4145 /* Eat the operator token - we now know it was a binary operator... */
4146 token
= next_token (&val
, (unsigned *)0, cfile
);
4148 /* Now combine the LHS and the RHS using binop. */
4149 tmp
= (struct expression
*)0;
4150 if (!expression_allocate (&tmp
, MDL
))
4151 log_fatal ("No memory for equal precedence combination.");
4153 /* Store the LHS and RHS. */
4154 tmp
-> data
.equal
[0] = lhs
;
4155 tmp
-> data
.equal
[1] = rhs
;
4159 tmp
= (struct expression
*)0;
4160 rhs
= (struct expression
*)0;
4162 /* Recursions don't return until we have parsed the end of the
4163 expression, so if we recursed earlier, we can now return what
4165 if (next_op
== expr_none
) {
4174 /* option-statement :== identifier DOT identifier <syntax> SEMI
4175 | identifier <syntax> SEMI
4177 Option syntax is handled specially through format strings, so it
4178 would be painful to come up with BNF for it. However, it always
4179 starts as above and ends in a SEMI. */
4181 int parse_option_statement (result
, cfile
, lookups
, option
, op
)
4182 struct executable_statement
**result
;
4183 struct parse
*cfile
;
4185 struct option
*option
;
4186 enum statement_op op
;
4189 enum dhcp_token token
;
4190 const char *fmt
= NULL
;
4191 struct expression
*expr
= (struct expression
*)0;
4192 struct expression
*tmp
;
4194 // struct executable_statement *stmt;
4197 token
= peek_token (&val
, (unsigned *)0, cfile
);
4198 if (token
== SEMI
) {
4199 /* Eat the semicolon... */
4200 token
= next_token (&val
, (unsigned *)0, cfile
);
4204 if (token
== EQUAL
) {
4205 /* Eat the equals sign. */
4206 token
= next_token (&val
, (unsigned *)0, cfile
);
4208 /* Parse a data expression and use its value for the data. */
4209 if (!parse_data_expression (&expr
, cfile
, &lose
)) {
4210 /* In this context, we must have an executable
4211 statement, so if we found something else, it's
4215 "expecting a data expression.");
4216 skip_to_semi (cfile
);
4221 /* We got a valid expression, so use it. */
4225 /* Parse the option data... */
4227 /* Set a flag if this is an array of a simple type (i.e.,
4228 not an array of pairs of IP addresses, or something
4230 int uniform
= option
-> format
[1] == 'A';
4233 /* Set fmt to start of format for 'A' and one char back
4235 if ((fmt
!= NULL
) &&
4236 (fmt
!= option
-> format
) && (*fmt
== 'a'))
4239 fmt
= ((fmt
== NULL
) ||
4240 (*fmt
== 'A')) ? option
-> format
: fmt
;
4242 /* 'a' means always uniform */
4243 uniform
|= (fmt
[1] == 'a');
4245 for ( ; *fmt
; fmt
++) {
4246 if ((*fmt
== 'A') || (*fmt
== 'a'))
4251 expr
= (struct expression
*)0;
4252 if (!parse_option_token (&expr
, cfile
, &fmt
,
4253 tmp
, uniform
, lookups
)) {
4254 if (fmt
[1] != 'o') {
4256 expression_dereference (&tmp
,
4261 tmp
= (struct expression
*)0;
4264 expression_dereference (&tmp
, MDL
);
4266 if ((*fmt
== 'A') || (*fmt
== 'a')) {
4267 token
= peek_token (&val
, (unsigned *)0, cfile
);
4268 /* Comma means: continue with next element in array */
4269 if (token
== COMMA
) {
4270 token
= next_token (&val
,
4271 (unsigned *)0, cfile
);
4274 /* no comma: end of array.
4275 'A' or end of string means: leave the loop */
4276 if ((*fmt
== 'A') || (fmt
[1] == '\0'))
4278 /* 'a' means: go on with next char */
4284 } while ((*fmt
== 'A') || (*fmt
== 'a'));
4287 if (!parse_semi (cfile
))
4289 if (!executable_statement_allocate (result
, MDL
))
4290 log_fatal ("no memory for option statement.");
4291 (*result
) -> op
= op
;
4292 if (expr
&& !option_cache (&(*result
) -> data
.option
,
4293 (struct data_string
*)0, expr
, option
, MDL
))
4294 log_fatal ("no memory for option cache");
4296 expression_dereference (&expr
, MDL
);
4300 int parse_option_token (rv
, cfile
, fmt
, expr
, uniform
, lookups
)
4301 struct expression
**rv
;
4302 struct parse
*cfile
;
4304 struct expression
*expr
;
4309 enum dhcp_token token
;
4310 struct expression
*t
= (struct expression
*)0;
4311 unsigned char buf
[4];
4313 // unsigned char *ob;
4317 struct enumeration_value
*e
;
4321 token
= next_token (&val
, &len
, cfile
);
4322 if (!is_identifier (token
)) {
4323 if ((*fmt
) [1] != 'o') {
4324 parse_warn (cfile
, "expecting identifier.");
4326 skip_to_semi (cfile
);
4330 if (!make_const_data (&t
, (const unsigned char *)val
,
4332 log_fatal ("No memory for %s", val
);
4336 g
= strchr (*fmt
, '.');
4339 "malformed encapsulation format (bug!)");
4340 skip_to_semi (cfile
);
4345 token
= peek_token (&val
, (unsigned *)0, cfile
);
4346 if (token
== NUMBER_OR_NAME
|| token
== NUMBER
) {
4347 if (!expression_allocate (&t
, MDL
))
4349 if (!parse_cshl (&t
-> data
.const_data
, cfile
)) {
4350 expression_dereference (&t
, MDL
);
4353 t
-> op
= expr_const_data
;
4355 token
= next_token (&val
, &len
, cfile
);
4357 if(token
== STRING
) {
4358 if (!make_const_data (&t
,
4359 (const unsigned char *)val
,
4361 log_fatal ("No memory for \"%s\"", val
);
4362 } else if ((*fmt
) [1] != 'o') {
4363 parse_warn (cfile
, "expecting string %s.",
4364 "or hexadecimal data");
4365 skip_to_semi (cfile
);
4372 case 'd': /* Domain name... */
4373 val
= parse_host_name (cfile
);
4375 parse_warn (cfile
, "not a valid domain name.");
4376 skip_to_semi (cfile
);
4382 case 't': /* Text string... */
4383 token
= next_token (&val
, &len
, cfile
);
4384 if (token
!= STRING
&& !is_identifier (token
)) {
4385 if ((*fmt
) [1] != 'o') {
4386 parse_warn (cfile
, "expecting string.");
4388 skip_to_semi (cfile
);
4393 if (!make_const_data (&t
, (const unsigned char *)val
,
4395 log_fatal ("No memory for concatenation");
4400 g
= strchr (*fmt
, '.');
4402 parse_warn (cfile
, "malformed %s (bug!)",
4403 "enumeration format");
4405 skip_to_semi (cfile
);
4409 token
= next_token (&val
, (unsigned *)0, cfile
);
4410 if (!is_identifier (token
)) {
4412 "identifier expected");
4415 e
= find_enumeration_value (f
, (*fmt
) - f
, val
);
4417 parse_warn (cfile
, "unknown value");
4420 if (!make_const_data (&t
, &e
-> value
, 1, 0, 1, MDL
))
4424 case 'I': /* IP address or hostname. */
4426 if (!parse_ip_addr_or_hostname (&t
, cfile
, uniform
))
4429 if (!parse_ip_addr (cfile
, &addr
))
4431 if (!make_const_data (&t
, addr
.iabuf
, addr
.len
,
4437 case 'T': /* Lease interval. */
4438 token
= next_token (&val
, (unsigned *)0, cfile
);
4439 if (token
!= INFINITE
)
4442 if (!make_const_data (&t
, buf
, 4, 0, 1, MDL
))
4446 case 'L': /* Unsigned 32-bit integer... */
4447 case 'l': /* Signed 32-bit integer... */
4448 token
= next_token (&val
, (unsigned *)0, cfile
);
4450 if ((token
!= NUMBER
) && (token
!= NUMBER_OR_NAME
)) {
4452 if ((*fmt
) [1] != 'o') {
4453 parse_warn (cfile
, "expecting number.");
4455 skip_to_semi (cfile
);
4459 convert_num (cfile
, buf
, val
, 0, 32);
4460 if (!make_const_data (&t
, buf
, 4, 0, 1, MDL
))
4464 case 's': /* Signed 16-bit integer. */
4465 case 'S': /* Unsigned 16-bit integer. */
4466 token
= next_token (&val
, (unsigned *)0, cfile
);
4467 if ((token
!= NUMBER
) && (token
!= NUMBER_OR_NAME
))
4469 convert_num (cfile
, buf
, val
, 0, 16);
4470 if (!make_const_data (&t
, buf
, 2, 0, 1, MDL
))
4474 case 'b': /* Signed 8-bit integer. */
4475 case 'B': /* Unsigned 8-bit integer. */
4476 token
= next_token (&val
, (unsigned *)0, cfile
);
4477 if ((token
!= NUMBER
) && (token
!= NUMBER_OR_NAME
))
4479 convert_num (cfile
, buf
, val
, 0, 8);
4480 if (!make_const_data (&t
, buf
, 1, 0, 1, MDL
))
4484 case 'f': /* Boolean flag. */
4485 token
= next_token (&val
, (unsigned *)0, cfile
);
4486 if (!is_identifier (token
)) {
4487 if ((*fmt
) [1] != 'o')
4488 parse_warn (cfile
, "expecting identifier.");
4490 if ((*fmt
) [1] != 'o') {
4492 skip_to_semi (cfile
);
4496 if (!strcasecmp (val
, "true")
4497 || !strcasecmp (val
, "on"))
4499 else if (!strcasecmp (val
, "false")
4500 || !strcasecmp (val
, "off"))
4502 else if (!strcasecmp (val
, "ignore"))
4505 if ((*fmt
) [1] != 'o')
4506 parse_warn (cfile
, "expecting boolean.");
4509 if (!make_const_data (&t
, buf
, 1, 0, 1, MDL
))
4514 parse_warn (cfile
, "Bad format %c in parse_option_token.",
4516 skip_to_semi (cfile
);
4520 if (!make_concat (rv
, expr
, t
))
4523 expression_reference (rv
, t
, MDL
);
4524 expression_dereference (&t
, MDL
);
4528 int parse_option_decl (oc
, cfile
)
4529 struct option_cache
**oc
;
4530 struct parse
*cfile
;
4535 u_int8_t hunkbuf
[1024];
4536 unsigned hunkix
= 0;
4537 const char *fmt
, *f
;
4538 struct option
*option
;
4539 struct iaddr ip_addr
;
4545 struct enumeration_value
*e
;
4547 option
= parse_option_name (cfile
, 0, &known
);
4551 /* Parse the option data... */
4553 /* Set a flag if this is an array of a simple type (i.e.,
4554 not an array of pairs of IP addresses, or something
4556 // int uniform = option -> format [1] == 'A';
4558 for (fmt
= option
-> format
; *fmt
; fmt
++) {
4563 fmt
= strchr (fmt
, '.');
4566 "malformed %s (bug!)",
4567 "encapsulation format");
4568 skip_to_semi (cfile
);
4572 len
= parse_X (cfile
, &hunkbuf
[hunkix
],
4573 sizeof hunkbuf
- hunkix
);
4577 case 't': /* Text string... */
4578 token
= next_token (&val
,
4580 if (token
!= STRING
) {
4582 "expecting string.");
4583 skip_to_semi (cfile
);
4586 if (hunkix
+ len
+ 1 > sizeof hunkbuf
) {
4588 "option data buffer %s",
4590 skip_to_semi (cfile
);
4593 memcpy (&hunkbuf
[hunkix
], val
, len
+ 1);
4600 fmt
= strchr (fmt
, '.');
4603 "malformed %s (bug!)",
4604 "enumeration format");
4606 skip_to_semi (cfile
);
4609 token
= next_token (&val
,
4610 (unsigned *)0, cfile
);
4611 if (!is_identifier (token
)) {
4613 "identifier expected");
4616 e
= find_enumeration_value (f
, fmt
- f
, val
);
4626 case 'I': /* IP address. */
4627 if (!parse_ip_addr (cfile
, &ip_addr
))
4633 if (hunkix
+ len
> sizeof hunkbuf
) {
4635 "option data buffer %s",
4637 skip_to_semi (cfile
);
4640 memcpy (&hunkbuf
[hunkix
], dp
, len
);
4644 case 'L': /* Unsigned 32-bit integer... */
4645 case 'l': /* Signed 32-bit integer... */
4646 token
= next_token (&val
,
4647 (unsigned *)0, cfile
);
4648 if ((token
!= NUMBER
) &&
4649 (token
!= NUMBER_OR_NAME
)) {
4652 "expecting number.");
4654 skip_to_semi (cfile
);
4657 convert_num (cfile
, buf
, val
, 0, 32);
4662 case 's': /* Signed 16-bit integer. */
4663 case 'S': /* Unsigned 16-bit integer. */
4664 token
= next_token (&val
,
4665 (unsigned *)0, cfile
);
4666 if ((token
!= NUMBER
) &&
4667 (token
!= NUMBER_OR_NAME
))
4669 convert_num (cfile
, buf
, val
, 0, 16);
4674 case 'b': /* Signed 8-bit integer. */
4675 case 'B': /* Unsigned 8-bit integer. */
4676 token
= next_token (&val
,
4677 (unsigned *)0, cfile
);
4678 if ((token
!= NUMBER
) &&
4679 (token
!= NUMBER_OR_NAME
))
4681 convert_num (cfile
, buf
, val
, 0, 8);
4686 case 'f': /* Boolean flag. */
4687 token
= next_token (&val
,
4688 (unsigned *)0, cfile
);
4689 if (!is_identifier (token
)) {
4691 "expecting identifier.");
4694 skip_to_semi (cfile
);
4697 if (!strcasecmp (val
, "true")
4698 || !strcasecmp (val
, "on"))
4700 else if (!strcasecmp (val
, "false")
4701 || !strcasecmp (val
, "off"))
4705 "expecting boolean.");
4713 log_error ("parse_option_param: Bad format %c",
4715 skip_to_semi (cfile
);
4719 token
= next_token (&val
, (unsigned *)0, cfile
);
4720 } while (*fmt
== 'A' && token
== COMMA
);
4722 if (token
!= SEMI
) {
4723 parse_warn (cfile
, "semicolon expected.");
4724 skip_to_semi (cfile
);
4728 bp
= (struct buffer
*)0;
4729 if (!buffer_allocate (&bp
, hunkix
+ nul_term
, MDL
))
4730 log_fatal ("no memory to store option declaration.");
4732 log_fatal ("out of memory allocating option data.");
4733 memcpy (bp
-> data
, hunkbuf
, hunkix
+ nul_term
);
4735 if (!option_cache_allocate (oc
, MDL
))
4736 log_fatal ("out of memory allocating option cache.");
4738 (*oc
) -> data
.buffer
= bp
;
4739 (*oc
) -> data
.data
= &bp
-> data
[0];
4740 (*oc
) -> data
.terminated
= nul_term
;
4741 (*oc
) -> data
.len
= hunkix
;
4742 (*oc
) -> option
= option
;
4746 /* Consider merging parse_cshl into this. */
4748 int parse_X (cfile
, buf
, max
)
4749 struct parse
*cfile
;
4758 token
= peek_token (&val
, (unsigned *)0, cfile
);
4759 if (token
== NUMBER_OR_NAME
|| token
== NUMBER
) {
4762 token
= next_token (&val
, (unsigned *)0, cfile
);
4763 if (token
!= NUMBER
&& token
!= NUMBER_OR_NAME
) {
4765 "expecting hexadecimal constant.");
4766 skip_to_semi (cfile
);
4769 convert_num (cfile
, &buf
[len
], val
, 16, 8);
4772 "hexadecimal constant too long.");
4773 skip_to_semi (cfile
);
4776 token
= peek_token (&val
, (unsigned *)0, cfile
);
4778 token
= next_token (&val
,
4779 (unsigned *)0, cfile
);
4780 } while (token
== COLON
);
4782 } else if (token
== STRING
) {
4783 token
= next_token (&val
, &len
, cfile
);
4784 if (len
+ 1 > max
) {
4785 parse_warn (cfile
, "string constant too long.");
4786 skip_to_semi (cfile
);
4789 memcpy (buf
, val
, len
+ 1);
4791 parse_warn (cfile
, "expecting string or hexadecimal data");
4792 skip_to_semi (cfile
);
4798 int parse_warn (struct parse
*cfile
, const char *fmt
, ...)
4806 do_percentm (mbuf
, fmt
);
4807 /* %Audit% This is log output. %2004.06.17,Safe%
4808 * If we truncate we hope the user can get a hint from the log.
4810 snprintf (fbuf
, sizeof fbuf
, "%s line %d: %s",
4811 cfile
-> tlname
, cfile
-> lexline
, mbuf
);
4813 va_start (list
, fmt
);
4814 vsnprintf (mbuf
, sizeof mbuf
, fbuf
, list
);
4819 cfile
-> token_line
[i
] && i
< (cfile
-> lexchar
- 1); i
++) {
4820 if (lix
< (sizeof lexbuf
) - 1)
4821 lexbuf
[lix
++] = ' ';
4822 if (cfile
-> token_line
[i
] == '\t') {
4824 lix
< (sizeof lexbuf
) - 1 && (lix
& 7); lix
++)
4831 syslog (log_priority
| LOG_ERR
, "%s", mbuf
);
4832 syslog (log_priority
| LOG_ERR
, "%s", cfile
-> token_line
);
4833 if (cfile
-> lexchar
< 81)
4834 syslog (log_priority
| LOG_ERR
, "%s^", lexbuf
);
4838 write (STDERR_FILENO
, mbuf
, strlen (mbuf
));
4839 write (STDERR_FILENO
, "\n", 1);
4840 write (STDERR_FILENO
, cfile
-> token_line
,
4841 strlen (cfile
-> token_line
));
4842 write (STDERR_FILENO
, "\n", 1);
4843 if (cfile
-> lexchar
< 81)
4844 write (STDERR_FILENO
, lexbuf
, lix
);
4845 write (STDERR_FILENO
, "^\n", 2);
4848 cfile
-> warnings_occurred
= 1;