📄 parse.c
字号:
if (token == ARRAY) { token = next_token (&val, (unsigned *)0, cfile); if (token != OF) { parse_warn (cfile, "expecting \"of\"."); skip_to_semi (cfile); return 0; } arrayp = 1; token = next_token (&val, (unsigned *)0, cfile); } if (token == LBRACE) { recordp = 1; token = next_token (&val, (unsigned *)0, cfile); } /* At this point we're expecting a data type. */ next_type: if (has_encapsulation) { parse_warn (cfile, "encapsulate must always be the last item."); skip_to_semi (cfile); return 0; } switch (token) { case ARRAY: if (arrayp) { parse_warn (cfile, "no nested arrays."); skip_to_rbrace (cfile, recordp); if (recordp) skip_to_semi (cfile); return 0; } token = next_token (&val, (unsigned *)0, cfile); if (token != OF) { parse_warn (cfile, "expecting \"of\"."); skip_to_semi (cfile); return 0; } arrayp = recordp + 1; token = next_token (&val, (unsigned *)0, cfile); if ((recordp) && (token == LBRACE)) { parse_warn (cfile, "only uniform array inside record."); skip_to_rbrace (cfile, recordp + 1); skip_to_semi (cfile); return 0; } goto next_type; case BOOLEAN: type = 'f'; break; case INTEGER: is_signed = 1; parse_integer: token = next_token (&val, (unsigned *)0, cfile); if (token != NUMBER) { parse_warn (cfile, "expecting number."); skip_to_rbrace (cfile, recordp); if (recordp) skip_to_semi (cfile); return 0; } switch (atoi (val)) { case 8: type = is_signed ? 'b' : 'B'; break; case 16: type = is_signed ? 's' : 'S'; break; case 32: type = is_signed ? 'l' : 'L'; break; default: parse_warn (cfile, "%s bit precision is not supported.", val); skip_to_rbrace (cfile, recordp); if (recordp) skip_to_semi (cfile); return 0; } break; case SIGNED: is_signed = 1; parse_signed: token = next_token (&val, (unsigned *)0, cfile); if (token != INTEGER) { parse_warn (cfile, "expecting \"integer\" keyword."); skip_to_rbrace (cfile, recordp); if (recordp) skip_to_semi (cfile); return 0; } goto parse_integer; case UNSIGNED: is_signed = 0; goto parse_signed; case IP_ADDRESS: type = 'I'; break; case DOMAIN_NAME: type = 'd'; goto no_arrays; case TEXT: type = 't'; no_arrays: if (arrayp) { parse_warn (cfile, "arrays of text strings not %s", "yet supported."); skip_to_rbrace (cfile, recordp); if (recordp) skip_to_semi (cfile); return 0; } no_more_in_record = 1; break; case STRING_TOKEN: type = 'X'; goto no_arrays; case ENCAPSULATE: token = next_token (&val, (unsigned *)0, cfile); if (!is_identifier (token)) { parse_warn (cfile, "expecting option space identifier"); skip_to_semi (cfile); return 0; } if (strlen (val) + tokix + 2 > sizeof (tokbuf)) goto toobig; tokbuf [tokix++] = 'E'; strcpy (&tokbuf [tokix], val); tokix += strlen (val); type = '.'; has_encapsulation = 1; break; default: parse_warn (cfile, "unknown data type %s", val); skip_to_rbrace (cfile, recordp); if (recordp) skip_to_semi (cfile); return 0; } if (tokix == sizeof tokbuf) { toobig: parse_warn (cfile, "too many types in record."); skip_to_rbrace (cfile, recordp); if (recordp) skip_to_semi (cfile); return 0; } tokbuf [tokix++] = type; if (recordp) { token = next_token (&val, (unsigned *)0, cfile); if (arrayp > recordp) { if (tokix == sizeof tokbuf) { parse_warn (cfile, "too many types in record."); skip_to_rbrace (cfile, 1); skip_to_semi (cfile); return 0; } arrayp = 0; tokbuf[tokix++] = 'a'; } if (token == COMMA) { if (no_more_in_record) { parse_warn (cfile, "%s must be at end of record.", type == 't' ? "text" : "string"); skip_to_rbrace (cfile, 1); if (recordp) skip_to_semi (cfile); return 0; } token = next_token (&val, (unsigned *)0, cfile); goto next_type; } if (token != RBRACE) { parse_warn (cfile, "expecting right brace."); skip_to_rbrace (cfile, 1); if (recordp) skip_to_semi (cfile); return 0; } } if (!parse_semi (cfile)) { parse_warn (cfile, "semicolon expected."); skip_to_semi (cfile); if (recordp) skip_to_semi (cfile); return 0; } if (has_encapsulation && arrayp) { parse_warn (cfile, "Arrays of encapsulations don't make sense."); return 0; } if (has_encapsulation && tokbuf [0] == 'E') has_encapsulation = 0; s = dmalloc (tokix + (arrayp ? 1 : 0) + (has_encapsulation ? 1 : 0) + 1, MDL); if (!s) log_fatal ("no memory for option format."); if (has_encapsulation) s [0] = 'e'; memcpy (s + has_encapsulation, tokbuf, tokix); tokix += has_encapsulation; if (arrayp) s [tokix++] = (arrayp > recordp) ? 'a' : 'A'; s [tokix] = 0; option -> format = s; if (option -> universe -> options [option -> code]) { /* XXX Free the option, but we can't do that now because they XXX may start out static. */ } option -> universe -> options [option -> code] = option; option_hash_add (option -> universe -> hash, (const char *)option -> name, 0, option, MDL); return 1;}/* * base64 :== NUMBER_OR_STRING */int parse_base64 (data, cfile) struct data_string *data; struct parse *cfile;{ enum dhcp_token token; const char *val; int i, j, k; unsigned acc = 0; static unsigned char from64 [] = {64, 64, 64, 64, 64, 64, 64, 64, /* \"#$%&' */ 64, 64, 64, 62, 64, 64, 64, 63, /* ()*+,-./ */ 52, 53, 54, 55, 56, 57, 58, 59, /* 01234567 */ 60, 61, 64, 64, 64, 64, 64, 64, /* 89:;<=>? */ 64, 0, 1, 2, 3, 4, 5, 6, /* @ABCDEFG */ 7, 8, 9, 10, 11, 12, 13, 14, /* HIJKLMNO */ 15, 16, 17, 18, 19, 20, 21, 22, /* PQRSTUVW */ 23, 24, 25, 64, 64, 64, 64, 64, /* XYZ[\]^_ */ 64, 26, 27, 28, 29, 30, 31, 32, /* 'abcdefg */ 33, 34, 35, 36, 37, 38, 39, 40, /* hijklmno */ 41, 42, 43, 44, 45, 46, 47, 48, /* pqrstuvw */ 49, 50, 51, 64, 64, 64, 64, 64}; /* xyz{|}~ */ struct string_list *bufs = (struct string_list *)0, *last = (struct string_list *)0, *t; int cc = 0; int terminated = 0; /* It's possible for a + or a / to cause a base64 quantity to be tokenized into more than one token, so we have to parse them all in before decoding. */ do { unsigned l; token = next_token (&val, &l, cfile); t = dmalloc (l + sizeof *t, MDL); if (!t) log_fatal ("no memory for base64 buffer."); memset (t, 0, (sizeof *t) - 1); memcpy (t -> string, val, l + 1); cc += l; if (last) last -> next = t; else bufs = t; last = t; token = peek_token (&val, (unsigned *)0, cfile); } while (token == NUMBER_OR_NAME || token == NAME || token == EQUAL || token == NUMBER || token == PLUS || token == SLASH || token == STRING); data -> len = cc; data -> len = (data -> len * 3) / 4; if (!buffer_allocate (&data -> buffer, data -> len, MDL)) { parse_warn (cfile, "can't allocate buffer for base64 data."); data -> len = 0; data -> data = (unsigned char *)0; return 0; } j = k = 0; for (t = bufs; t; t = t -> next) { for (i = 0; t -> string [i]; i++) { unsigned foo = t -> string [i]; if (terminated && foo != '=') { parse_warn (cfile, "stuff after base64 '=' terminator: %s.", &t -> string [i]); goto bad; } if (foo < ' ' || foo > 'z') { bad64: parse_warn (cfile, "invalid base64 character %d.", t -> string [i]); bad: data_string_forget (data, MDL); goto out; } if (foo == '=') terminated = 1; else { foo = from64 [foo - ' ']; if (foo == 64) goto bad64; acc = (acc << 6) + foo; switch (k % 4) { case 0: break; case 1: data -> buffer -> data [j++] = (acc >> 4); acc = acc & 0x0f; break; case 2: data -> buffer -> data [j++] = (acc >> 2); acc = acc & 0x03; break; case 3: data -> buffer -> data [j++] = acc; acc = 0; break; } } k++; } } if (k % 4) { if (acc) { parse_warn (cfile, "partial base64 value left over: %d.", acc); } } data -> len = j; data -> data = data -> buffer -> data; out: for (t = bufs; t; t = last) { last = t -> next; dfree (t, MDL); } if (data -> len) return 1; else return 0;}/* * colon-seperated-hex-list :== NUMBER | * NUMBER COLON colon-seperated-hex-list */int parse_cshl (data, cfile) struct data_string *data; struct parse *cfile;{ u_int8_t ibuf [128]; unsigned ilen = 0; unsigned tlen = 0; struct option_tag *sl = (struct option_tag *)0; struct option_tag *next, **last = &sl; enum dhcp_token token; const char *val; unsigned char *rvp; do { token = next_token (&val, (unsigned *)0, cfile); if (token != NUMBER && token != NUMBER_OR_NAME) { parse_warn (cfile, "expecting hexadecimal number."); skip_to_semi (cfile); for (; sl; sl = next) { next = sl -> next; dfree (sl, MDL); } return 0; } if (ilen == sizeof ibuf) { next = (struct option_tag *) dmalloc (ilen - 1 + sizeof (struct option_tag), MDL); if (!next) log_fatal ("no memory for string list."); memcpy (next -> data, ibuf, ilen); *last = next; last = &next -> next; tlen += ilen; ilen = 0; } convert_num (cfile, &ibuf [ilen++], val, 16, 8); token = peek_token (&val, (unsigned *)0, cfile); if (token != COLON) break; token = next_token (&val, (unsigned *)0, cfile); } while (1); if (!buffer_allocate (&data -> buffer, tlen + ilen, MDL)) log_fatal ("no memory to store octet data."); data -> data = &data -> buffer -> data [0]; data -> len = tlen + ilen; data -> terminated = 0; rvp = &data -> buffer -> data [0]; while (sl) { next = sl -> next; memcpy (rvp, sl -> data, sizeof ibuf); rvp += sizeof ibuf; dfree (sl, MDL); sl = next; } memcpy (rvp, ibuf, ilen); return 1;}/* * executable-statements :== executable-statement executable-statements | * executable-statement * * executable-statement :== * IF if-statement | * ADD class-name SEMI | * BREAK SEMI | * OPTION option-parameter SEMI | * SUPERSEDE option-parameter SEMI | * PREPEND option-parameter SEMI | * APPEND option-parameter SEMI */int parse_executable_statements (statements, cfile, lose, case_context) struct executable_statement **statements; struct parse *cfile; int *lose; enum expression_context case_context;{ struct executable_statement **next; next = statements; while (parse_executable_statement (next, cfile, lose, case_context)) next = &((*next) -> next); if (!*lose) return 1; return 0;}int parse_executable_statement (result, cfile, lose, case_context) struct executable_statement **result; struct parse *cfile; int *lose; enum expression_context case_context;{ enum dhcp_token token; const char *val; struct executable_statement base; struct class *cta; struct option *option; struct option_cache *cache; int known; int flag; int i; struct dns_zone *zone; isc_result_t status; char *s; token = peek_token (&val, (unsigned *)0, cfile); switch (token) { case IF: next_token (&val, (unsigned *)0, cfile); return parse_if_statement (result, cfile, lose); case TOKEN_ADD: token = next_token (&val, (unsigned *)0, cfile); token = next_token (&val, (unsigned *)0, cfile); if (token != STRING) { parse_warn (cfile, "expecting class name."); skip_to_semi (cfile); *lose = 1; return 0; } cta = (struct class *)0; status = find_class (&cta, val, MDL); if (status != ISC_R_SUCCESS) { parse_warn (cfile, "class %s: %s", val, isc_result_totext (status)); skip_to_semi (cfile); *lose = 1; return 0; } if (!parse_semi (cfile)) { *lose = 1; return 0; } if (!executable_statement_allocate (result, MDL)) log_fatal ("no memory for new statement."); (*result) -> op = add_statement; (*result) -> data.add = cta; break; case BREAK: token = next_token (&val, (unsigned *)0, cfile); if (!parse_semi (cfile)) { *lose = 1; return 0; } if (!executable_statement_allocate (result, MDL)) log_fatal ("no memory for new statement."); (*result) -> op = break_statement; break; case SEND:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -