static uintmax_t dpm_parse_uint (dyn_input in, const char *str, int len, int base, uintmax_t max) { uintmax_t val; const char *ptr = str, *end = str + len; while (ptr < end && whitespace_p (*ptr)) ptr++; val = 0; while (ptr < end && *ptr >= '0' && *ptr < '0' + base) { uintmax_t old = val; val = val * base + *ptr - '0'; if (val < old) goto out_of_range; ptr++; } if (val > max) { out_of_range: dyn_error ("value out of range: %ls", str, len); } while (ptr < end && whitespace_p (*ptr)) ptr++; if (*ptr && ptr != end) dyn_error ("junk at end of number: %ls", str, len); return val; }
void dpm_parse_comma_fields_step (dpm_parse_comma_fields *iter) { dyn_input in = iter->in; dyn_input_skip (in, " \t\n"); if (dyn_input_grow (in, 1) < 1) { iter->field = NULL; return; } dyn_input_set_mark (in); dyn_input_find (in, ","); iter->field = dyn_input_mark (in); iter->len = dyn_input_pos (in) - iter->field; while (iter->len > 0 && whitespace_p (iter->field[iter->len-1])) iter->len--; if (dyn_input_looking_at (in, ",")) dyn_input_advance (in, 1); }
void dpm_parse_control_fields_step (dpm_parse_control_fields *iter) { dyn_input in = iter->in; dyn_input_set_mark (in); while (dyn_input_find (in, ":\n") || dyn_input_pos (in) > dyn_input_mark (in)) { if (dyn_input_pos (in) == dyn_input_mark (in)) { /* Empty line. Gobble it up when we haven't seen a field yet. */ if (iter->starting) { dyn_input_advance (in, 1); dyn_input_set_mark (in); } else { iter->name = NULL; return; } } else { int value_off; if (!dyn_input_looking_at (in, ":")) dyn_error ("No field name"); iter->name_len = dyn_input_pos (in) - dyn_input_mark (in); dyn_input_advance (in, 1); value_off = dyn_input_pos (in) - dyn_input_mark (in); dyn_input_find_after (in, "\n"); while (dyn_input_looking_at (in, " ") || dyn_input_looking_at (in, "\t")) dyn_input_find_after (in, "\n"); iter->value_len = dyn_input_pos (in) - dyn_input_mark (in) - value_off; iter->name = dyn_input_mark (in); iter->value = iter->name + value_off; while (iter->value_len > 0 && whitespace_p (iter->value[0])) { iter->value++; iter->value_len--; } while (iter->value_len > 0 && whitespace_p (iter->value[iter->value_len-1])) { iter->value_len--; } iter->starting = false; return; } } iter->name = NULL; }
static void logo_Lexer_advance(logo_Lexer *self) { #define opv(_name, _value) do { self->token = (logo_Token) { .type = logo_Token_ ## _name, .value = _value, .start = start, .end = logo_Stream_position(self->stream) }; return; } while (0) #define op(_name) opv(_name, NULL) long start = logo_Stream_position(self->stream); int c = logo_Stream_next(self->stream); bool whitespace = false; trim: if (whitespace_p(c) || ((self->list_level || self->in_proc) && newline_p(c))) { start = logo_Stream_position(self->stream); c = logo_Stream_next(self->stream); whitespace = true; goto trim; } if (c == '#') { if (logo_Stream_next(self->stream) == '!') { do { c = logo_Stream_next(self->stream); } while (!newline_p(c) && c != logo_Stream_END); start = logo_Stream_position(self->stream) - 1; goto trim; } logo_Stream_skip(self->stream, -1); } if (c == ';' && self->list_level == 0) { do { c = logo_Stream_next(self->stream); } while (!newline_p(c) && c != logo_Stream_END); start = logo_Stream_position(self->stream) - 1; goto trim; } switch (c) { case logo_Stream_END: op(END); case '[': ++self->list_level; op(LBRACKET); case ']': if (self->list_level > 0) --self->list_level; op(RBRACKET); } if (newline_p(c)) { do { c = logo_Stream_next(self->stream); } while (newline_p(c)); logo_Stream_skip(self->stream, -1); op(NEWLINE); } if (self->list_level || self->in_proc) { size_t size = 0; do { ++size; c = logo_Stream_next(self->stream); } while (lword_p(c)); logo_Stream_skip(self->stream, -size - 1); char *s = malloc(size + 1), *p; for (p = s; p < s + size; ++p) { *p = logo_Stream_next(self->stream); } *p = 0; if (self->in_proc && strcmp(s, "end") == 0) { free(s); op(PROCEND); } opv(WORD, s); } switch (c) { case '(': op(LPAREN); case ')': op(RPAREN); case ':': op(COLON); case '?': op(QUESTION); case '+': op(ADD); case '-': if (whitespace && !whitespace_p(logo_Stream_peek(self->stream))) { op(INVERSE); } op(SUB); case '*': op(MUL); case '/': op(DIV); case '=': op(EQUAL); case '>': if (logo_Stream_peek(self->stream) == '=') { logo_Stream_next(self->stream); op(GTE); } op(GT); case '<': if (logo_Stream_peek(self->stream) == '=') { logo_Stream_next(self->stream); op(LTE); } if (logo_Stream_peek(self->stream) == '>') { logo_Stream_next(self->stream); op(NOTEQUAL); } op(LT); } if (c == '"') { size_t size = 0; c = logo_Stream_next(self->stream); while (word_p(c)) { ++size; c = logo_Stream_next(self->stream); } logo_Stream_skip(self->stream, -size - 1); char *s = malloc(size + 1), *p; for (p = s; p < s + size; ++p) { *p = logo_Stream_next(self->stream); } *p = 0; opv(WORD, s); } if (digit_p(c)) { size_t size = 0; #define next do { ++size; c = logo_Stream_next(self->stream); } while (0) do { do next; while (digit_p(c)); if (c == '.') { next; if (!digit_p(c)) break; do next; while (digit_p(c)); } if (c == 'e' || c == 'E') { next; if (c == '+' || c == '-') next; if (!digit_p(c)) break; do next; while (digit_p(c)); } if (name_p(c)) break; logo_Stream_skip(self->stream, -size - 1); char *s = malloc(size + 1), *p; for (p = s; p < s + size; ++p) { *p = logo_Stream_next(self->stream); } *p = 0; opv(NUMBER, s); } while (false); #undef next logo_Stream_skip(self->stream, -size - 1); c = logo_Stream_next(self->stream); } if (name_p(c)) { size_t size = 0; do { ++size; c = logo_Stream_next(self->stream); } while (name_p(c)); logo_Stream_skip(self->stream, -size - 1); char *s = malloc(size), *p; for (p = s; p < s + size; ++p) { *p = logo_Stream_next(self->stream); } *p = 0; opv(NAME, s); } #undef op }