예제 #1
0
파일: parse.c 프로젝트: mvollmer/dpm
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;
}
예제 #2
0
파일: parse.c 프로젝트: mvollmer/dpm
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);
}
예제 #3
0
파일: parse.c 프로젝트: mvollmer/dpm
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;
}
예제 #4
0
파일: lexer.c 프로젝트: nathan/logo
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
}