示例#1
0
 /* consume_garbage()
  *
  * Advance until the current character is non-whitespace and non-comment.
  */
 void consume_garbage() {
   consume_whitespace();
   if(strategy == JsonParse::COMMENTS) {
     bool comment_found = false;
     do {
       comment_found = consume_comment();
       consume_whitespace();
     }
     while(comment_found);
   }
 }
示例#2
0
    /* get_next_token()
     *
     * Return the next non-whitespace character. If the end of the input is reached,
     * flag an error and return 0.
     */
    char get_next_token() {
        consume_whitespace();
        if (i == str.size())
            return fail("unexpected end of input", 0);

        return str[i++];
    }
bool next_line(ParserData* data) {
	//TODO error/warning on remaining text!
	read_line(data);
	if (!data->eof) {
		data->linenumber++;
		data->column = 0;
		consume_whitespace(data);
		if (data->column >= data->linelength || data->line[data->column] == '#') {
			next_line(data);
		}
		return true;
	}
	return false;
}
示例#4
0
文件: sexpr.C 项目: bougyman/sfs
void
gread_gob (gread_state *ignore)
{
  consume_whitespace ();
  int c = gget ();

  switch (c) {
    case EOF:
      gerror (); // unexpected end of input
    case '(':
      {
      gread_res = NULL;
      gread_state *state = New gread_state;
      state->list.elms = state->list.elmstail = NULL;
      ggoto (gread_list, state);
      }
    case ')':
      gerror (); // unbalanced parentheses
    case '"':
      {
      gread_state *state = New gread_state;
      state->chars = New str;
      ggoto (gread_string, state);
      }
    default:
      if (isdigit (c)) {
        gread_state *state = New gread_state;
        state->chars = New str;
        state->chars->append (c);
        ggoto (gread_integer, state);
      }
      else if (issymbolchar (c)) {
        gread_state *state = New gread_state;
        state->chars = New str;
        state->chars->append (tolower (c));
        ggoto (gread_symbol, state);
      }
      else
        gerror (); // unexpected character
  }
}
示例#5
0
文件: sexpr.C 项目: bougyman/sfs
void
gread_list (gread_state *state)
{
  if (gread_res) {
    gpair *newpair = New gpair (gread_res, bottom);
    gpair *head = state->list.elms;
    gpair *tail = state->list.elmstail;
    if (tail) {
      tail->cdr = newpair;
      tail = newpair;
    }
    else
      head = tail = newpair;
    state->list.elms = head;
    state->list.elmstail = tail;
  }

  consume_whitespace ();
  int c = gget ();
  switch (c) {
    case EOF:
      gerror ();
    case ')':
      {
        gpair *elms = state->list.elms;
        delete state;
        if (elms)
          greturn (elms);
        else
          greturn (bottom);
      }
    default:
      gunget (c);
      gpush (gread_list, state);
      ggoto (gread_gob, NULL);
  }
}
示例#6
0
void top_level_consume_token(TokenizeContext &context)
{
    if (is_identifier_first_letter(context.next())) {

        if (context.next() <= 'm') {
            // a through m
            if (try_to_consume_keyword(context, tok_And)) return;
            if (try_to_consume_keyword(context, tok_Break)) return;
            if (try_to_consume_keyword(context, tok_Case)) return;
            if (try_to_consume_keyword(context, tok_Continue)) return;
            if (try_to_consume_keyword(context, tok_Def)) return;
            if (try_to_consume_keyword(context, tok_Discard)) return;
            if (try_to_consume_keyword(context, tok_Else)) return;
            if (try_to_consume_keyword(context, tok_Elif)) return;
            if (try_to_consume_keyword(context, tok_False)) return;
            if (try_to_consume_keyword(context, tok_For)) return;
            if (try_to_consume_keyword(context, tok_If)) return;
            if (try_to_consume_keyword(context, tok_In)) return;
            if (try_to_consume_keyword(context, tok_Import)) return;
            if (try_to_consume_keyword(context, tok_Include)) return;
            if (try_to_consume_keyword(context, tok_Let)) return;
        } else {
            // n through z
            if (try_to_consume_keyword(context, tok_Namespace)) return;
            if (try_to_consume_keyword(context, tok_Not)) return;
            if (try_to_consume_keyword(context, tok_Nil)) return;
            if (try_to_consume_keyword(context, tok_Or)) return;
            if (try_to_consume_keyword(context, tok_Return)) return;
            if (try_to_consume_keyword(context, tok_State)) return;
            if (try_to_consume_keyword(context, tok_Struct)) return;
            if (try_to_consume_keyword(context, tok_Switch)) return;
            if (try_to_consume_keyword(context, tok_True)) return;
            if (try_to_consume_keyword(context, tok_Require)) return;
            if (try_to_consume_keyword(context, tok_RequireLocal)) return;
            if (try_to_consume_keyword(context, tok_Package)) return;
            if (try_to_consume_keyword(context, tok_Section)) return;
            if (try_to_consume_keyword(context, tok_While)) return;
        }

        consume_identifier(context);
        return;
    }

    if (is_whitespace(context.next())) {
        consume_whitespace(context);
        return;
    }

    if (context.next() == '0'
        && context.next(1) == 'x') {
        consume_hex_number(context);
        return;
    }

    if (match_number(context)) {
        consume_number(context);
        return;
    }

    // Check for specific characters
    switch(context.next()) {
        case '(':
            context.consume(tok_LParen, 1);
            return;
        case ')':
            context.consume(tok_RParen, 1);
            return;
        case '{':
            if (context.next(1) == '-') {
                consume_multiline_comment(context);
                return;
            }
            context.consume(tok_LBrace, 1);
            return;
        case '}':
            context.consume(tok_RBrace, 1);
            return;
        case '[':
            context.consume(tok_LSquare, 1);
            return;
        case ']':
            context.consume(tok_RSquare, 1);
            return;
        case ',':
            context.consume(tok_Comma, 1);
            return;
        case '@':
            context.consume(tok_At, 1);
            return;
        case '=':
            if (context.next(1) == '=') {
                context.consume(tok_DoubleEquals, 2);
                return;
            }  else if (context.next(1) == '>') {
                context.consume(tok_FatArrow, 2);
                return;
            }

            context.consume(tok_Equals, 1);
            return;
        case '"':
        case '\'':
            consume_string_literal(context);
            return;
        case '\n':
            context.consume(tok_Newline, 1);
            return;
        case '.':
            if (context.next(1) == '.') {
                if (context.next(2) == '.') {
                    context.consume(tok_Ellipsis, 3); 
                } else {
                    context.consume(tok_TwoDots, 2);
                }
            } else if (context.next(1) == '@') {
                context.consume(tok_DotAt, 2);
            } else {
                context.consume(tok_Dot, 1);
            }
            return;
        case '?':
            context.consume(tok_Question, 1);
            return;
        case '*':
            if (context.next(1) == '=') {
                context.consume(tok_StarEquals, 2);
                return;
            }
            if (context.next(1) == '*') {
                context.consume(tok_DoubleStar, 2);
                return;
            }

            context.consume(tok_Star, 1);
            return;
        case '/':
            if (context.next(1) == '=') {
                context.consume(tok_SlashEquals, 2);
                return;
            }
            if (context.next(1) == '/') {
                context.consume(tok_DoubleSlash, 2);
                return;
            }
            context.consume(tok_Slash, 1);
            return;
        case '!':
            if (context.next(1) == '=') {
                context.consume(tok_NotEquals, 2);
                return;
            }
            break;

        case ':':
            if (context.next(1) == '=') {
                context.consume(tok_ColonEquals, 2);
                return;
            }
            else if (context.next(1) == ':') {
                context.consume(tok_DoubleColon, 2);
                return;
            } else if (is_acceptable_inside_identifier(context.next(1))) {
                return consume_symbol(context);
            }

            context.consume(tok_Colon, 1);
            return;
        case '+':
            if (context.next(1) == '=') {
                context.consume(tok_PlusEquals, 2);
            } else {
                context.consume(tok_Plus, 1);
            }
            return;
        case '-':
            if (context.next(1) == '>') {
                context.consume(tok_RightArrow, 2);
                return;
            }

            if (context.next(1) == '-')
                return consume_comment(context);

            if (context.next(1) == '=') {
                context.consume(tok_MinusEquals, 2);
                return;
            }

            context.consume(tok_Minus, 1);
            return;

        case '<':
            if (context.next(1) == '<' && context.next(2) == '<') {
                consume_triple_quoted_string_literal(context);
                return;
            }

            if (context.next(1) == '=') {
                context.consume(tok_LThanEq, 2);
                return;
            }
            if (context.next(1) == '-') {
                context.consume(tok_LeftArrow, 2);
                return;
            }
            context.consume(tok_LThan, 1);
            return;

        case '>':
            if (context.next(1) == '=')
                context.consume(tok_GThanEq, 2);
            else
                context.consume(tok_GThan, 1);
            return;

        case '%':
            context.consume(tok_Percent, 1);
            return;

        case '|':
            if (context.next(1) == '|')
                context.consume(tok_DoubleVerticalBar, 2);
            else
                context.consume(tok_VerticalBar, 1);
            return;

        case '&':
            if (context.next(1) == '&')
                context.consume(tok_DoubleAmpersand, 2);
            else
                context.consume(tok_Ampersand, 1);
            return;

        case ';':
            context.consume(tok_Semicolon, 1);
            return;

        case '#':
            consume_color_literal(context);
            return;
    }

    // Fall through, consume the next letter as UNRECOGNIZED
    context.consume(tok_Unrecognized, 1);
}
SdfNode* parse_entry(ParserData* data) {

	// First try to parse a label.
	char* label;
	int length = consume_label(data, &label);
	if (length == 0) {
		// We did not find a label!
		return error(data, EXPECTED_LABEL);
	}

	// Create the node for this element
	SdfNode* element = new_valued_node(label, length);

	// Now try to get a { or :
	if (consume(data, '{')) {
		// This entry is a struct-valued entry

		// End the current line
		if (!next_line(data)) {
			sdf_free_tree(element);
			return error(data, EXPECTED_END_OF_LINE);
		}

		// Parse children until the closing bracket is found.
		while (!consume(data, '}')) {
			SdfNode* child = parse_entry(data);
			if (child != NULL) {
				add_child(element, child);
			} else {
				// Syntax error in contents
				sdf_free_tree(element);
				return NULL;
			}
		}
	} else if (consume(data, ':')) {
		// This entry is a single-valued entry

		// Consume leading white space
		consume_whitespace(data);

		// Try to get a simple or quoted string
		SdfNode* value;
		if (data->line[data->column] == '"') {
			// Quoted string
			value = consume_quoted_string(data);
		} else {
			// Simple string
			char* string;
			length = consume_label(data, &string);
			value = new_valued_node(string, length);
		}
		add_child(element, value);
	} else {
		// Failed to get a { or :
		sdf_free_tree(element);
		return error(data, EXPECTED_ENTRY);
	}

	// And we need a final newline, except when we are at the end of the file.
	if (!next_line(data) && !data->eof) {
		// Encountered something else than a newline or EOF
		sdf_free_tree(element);
		return error(data, EXPECTED_END_OF_LINE);
	}

	return element;
}
示例#8
0
文件: reader.c 项目: qyqx/wisp
/* Read a single sexp from the reader. */
object_t *read_sexp (reader_t * r)
{
  /* Check for a shebang line. */
  if (r->shebang == -1)
    {
      char str[2];
      str[0] = reader_getc (r);
      str[1] = reader_getc (r);
      if (str[0] == '#' && str[1] == '!')
	{
	  /* Looks like a she-bang line. */
	  r->shebang = 1;
	  consume_line (r);
	}
      else
	{
	  r->shebang = 0;
	  reader_putc (r, str[1]);
	  reader_putc (r, str[0]);
	}
    }

  r->done = 0;
  r->error = 0;
  push (r);
  print_prompt (r);
  while (!r->eof && !r->error && (list_empty (r) || stack_height (r) > 1))
    {
      int nc, c = reader_getc (r);
      switch (c)
	{
	case EOF:
	  r->eof = 1;
	  break;

	  /* Comments */
	case ';':
	  consume_line (r);
	  break;

	  /* Dotted pair */
	case '.':
	  nc = reader_getc (r);
	  if (strchr (" \t\r\n()", nc) != NULL)
	    {
	      if (r->state->dotpair_mode > 0)
		read_error (r, "invalid dotted pair syntax");
	      else if (r->state->vector_mode > 0)
		read_error (r, "dotted pair not allowed in vector");
	      else
		{
		  r->state->dotpair_mode = 1;
		  reader_putc (r, nc);
		}
	    }
	  else
	    {
	      /* Turn it into a decimal point. */
	      reader_putc (r, nc);
	      reader_putc (r, '.');
	      reader_putc (r, '0');
	    }
	  break;

	  /* Whitespace */
	case '\n':
	  r->linecnt++;
	  print_prompt (r);
	case ' ':
	case '\t':
	case '\r':
	  break;

	  /* Parenthesis */
	case '(':
	  push (r);
	  break;
	case ')':
	  if (r->state->quote_mode)
	    read_error (r, "unbalanced parenthesis");
	  else if (r->state->vector_mode)
	    read_error (r, "unbalanced brackets");
	  else
	    addpop (r);
	  break;

	  /* Vectors */
	case '[':
	  push (r);
	  r->state->vector_mode = 1;
	  break;
	case ']':
	  if (r->state->quote_mode)
	    read_error (r, "unbalanced parenthesis");
	  else if (!r->state->vector_mode)
	    read_error (r, "unbalanced brackets");
	  else
	    addpop (r);
	  break;

	  /* Quoting */
	case '\'':
	  push (r);
	  add (r, quote);
	  if (!r->error)
	    r->state->quote_mode = 1;
	  break;

	  /* strings */
	case '"':
	  buf_read (r, "\"");
	  add (r, parse_str (r));
	  reader_getc (r);	/* Throw away other quote. */
	  break;

	  /* numbers and symbols */
	default:
	  buf_append (r, c);
	  buf_read (r, " \t\r\n()[];");
	  object_t *o = parse_atom (r);
	  if (!r->error)
	    add (r, o);
	  break;
	}
    }
  if (!r->eof && !r->error)
    consume_whitespace (r);
  if (r->error)
    return err_symbol;

  /* Check state */
  r->done = 1;
  if (stack_height (r) > 1 || r->state->quote_mode
      || r->state->dotpair_mode == 1)
    {
      read_error (r, "premature end of file");
      return err_symbol;
    }
  if (list_empty (r))
    {
      obj_destroy (pop (r));
      return NIL;
    }

  object_t *wrap = pop (r);
  object_t *sexp = UPREF (CAR (wrap));
  obj_destroy (wrap);
  return sexp;
}
示例#9
0
void top_level_consume_token(TokenizeContext &context)
{
    if (is_identifier_first_letter(context.next())) {

        if (try_to_consume_keyword(context, TK_DEF)) return;
        if (try_to_consume_keyword(context, TK_TYPE)) return;
        if (try_to_consume_keyword(context, TK_BEGIN)) return;
        if (try_to_consume_keyword(context, TK_END)) return;
        if (try_to_consume_keyword(context, TK_IF)) return;
        if (try_to_consume_keyword(context, TK_ELSE)) return;
        if (try_to_consume_keyword(context, TK_ELIF)) return;
        if (try_to_consume_keyword(context, TK_FOR)) return;
        if (try_to_consume_keyword(context, TK_STATE)) return;
        if (try_to_consume_keyword(context, TK_IN)) return;
        if (try_to_consume_keyword(context, TK_TRUE)) return;
        if (try_to_consume_keyword(context, TK_FALSE)) return;
        // check 'do once' before 'do'
        if (try_to_consume_keyword(context, TK_DO_ONCE)) return;
        if (try_to_consume_keyword(context, TK_DO)) return;
        if (try_to_consume_keyword(context, TK_NAMESPACE)) return;
        if (try_to_consume_keyword(context, TK_INCLUDE)) return;
        if (try_to_consume_keyword(context, TK_IMPORT)) return;
        if (try_to_consume_keyword(context, TK_AND)) return;
        if (try_to_consume_keyword(context, TK_OR)) return;
        if (try_to_consume_keyword(context, TK_DISCARD)) return;
        if (try_to_consume_keyword(context, TK_NULL)) return;
        if (try_to_consume_keyword(context, TK_RETURN)) return;
        if (try_to_consume_keyword(context, TK_BREAK)) return;
        if (try_to_consume_keyword(context, TK_CONTINUE)) return;
        if (try_to_consume_keyword(context, TK_SWITCH)) return;
        if (try_to_consume_keyword(context, TK_CASE)) return;
        if (try_to_consume_keyword(context, TK_WHILE)) return;

        consume_identifier(context);
        return;
    }

    if (is_whitespace(context.next())) {
        consume_whitespace(context);
        return;
    }

    if (context.next() == '0'
            && context.next(1) == 'x') {
        consume_hex_number(context);
        return;
    }

    if (match_number(context)) {
        consume_number(context);
        return;
    }

    // Check for specific characters
    switch(context.next()) {
    case '(':
        context.consume(TK_LPAREN, 1);
        return;
    case ')':
        context.consume(TK_RPAREN, 1);
        return;
    case '{':
        if (context.next(1) == '-') {
            consume_multiline_comment(context);
            return;
        }
        context.consume(TK_LBRACE, 1);
        return;
    case '}':
        context.consume(TK_RBRACE, 1);
        return;
    case '[':
        context.consume(TK_LBRACKET, 1);
        return;
    case ']':
        context.consume(TK_RBRACKET, 1);
        return;
    case ',':
        context.consume(TK_COMMA, 1);
        return;
    case '@':
        if (context.next(1) == '.') {
            context.consume(TK_AT_DOT, 2);
        } else {
            context.consume(TK_AT_SIGN, 1);
        }
        return;
    case '=':
        if (context.next(1) == '=') {
            context.consume(TK_DOUBLE_EQUALS, 2);
            return;
        }

        context.consume(TK_EQUALS, 1);
        return;
    case '"':
    case '\'':
        consume_string_literal(context);
        return;
    case '\n':
        context.consume(TK_NEWLINE, 1);
        return;
    case '.':
        if (context.next(1) == '.') {
            if (context.next(2) == '.') {
                context.consume(TK_ELLIPSIS, 3);
            } else {
                context.consume(TK_TWO_DOTS, 2);
            }
        } else {
            context.consume(TK_DOT, 1);
        }
        return;
    case '?':
        context.consume(TK_QUESTION, 1);
        return;
    case '*':
        if (context.next(1) == '=') {
            context.consume(TK_STAR_EQUALS, 2);
            return;
        }

        context.consume(TK_STAR, 1);
        return;
    case '/':
        if (context.next(1) == '=') {
            context.consume(TK_SLASH_EQUALS, 2);
            return;
        }
        if (context.next(1) == '/') {
            context.consume(TK_DOUBLE_SLASH, 2);
            return;
        }
        context.consume(TK_SLASH, 1);
        return;
    case '!':
        if (context.next(1) == '=') {
            context.consume(TK_NOT_EQUALS, 2);
            return;
        }
        break;

    case ':':
        if (context.next(1) == '=') {
            context.consume(TK_COLON_EQUALS, 2);
            return;
        }
        else if (context.next(1) == ':') {
            context.consume(TK_DOUBLE_COLON, 2);
            return;
        } else if (is_identifier_first_letter(context.next(1))) {
            return consume_name(context);
        }

        context.consume(TK_COLON, 1);
        return;
    case '+':
        if (context.next(1) == '=') {
            context.consume(TK_PLUS_EQUALS, 2);
        } else {
            context.consume(TK_PLUS, 1);
        }
        return;
    case '-':
        if (context.next(1) == '>') {
            context.consume(TK_RIGHT_ARROW, 2);
            return;
        }

        if (context.next(1) == '-')
            return consume_comment(context);

        if (context.next(1) == '=') {
            context.consume(TK_MINUS_EQUALS, 2);
            return;
        }

        context.consume(TK_MINUS, 1);
        return;

    case '<':
        if (context.next(1) == '<' && context.next(2) == '<') {
            consume_triple_quoted_string_literal(context);
            return;
        }

        if (context.next(1) == '=') {
            context.consume(TK_LTHANEQ, 2);
            return;
        }
        if (context.next(1) == '-') {
            context.consume(TK_LEFT_ARROW, 2);
            return;
        }
        context.consume(TK_LTHAN, 1);
        return;

    case '>':
        if (context.next(1) == '=') {
            context.consume(TK_GTHANEQ, 2);
            return;
        }
        context.consume(TK_GTHAN, 1);
        return;

    case '%':
        context.consume(TK_PERCENT, 1);
        return;

    case '|':
        if (context.next(1) == '|') {
            context.consume(TK_DOUBLE_VERTICAL_BAR, 2);
            return;
        }
        break;

    case '&':
        if (context.next(1) == '&') {
            context.consume(TK_DOUBLE_AMPERSAND, 2);
            return;
        }

        context.consume(TK_AMPERSAND, 1);
        return;

    case ';':
        context.consume(TK_SEMICOLON, 1);
        return;

    case '#':
        consume_color_literal(context);
        return;
    }

    // Fall through, consume the next letter as UNRECOGNIZED
    context.consume(TK_UNRECOGNIZED, 1);
}
示例#10
0
static void
read_psffm(char *file)
{
	int	fd;
	static char	msgfile[MAXPATHLEN];
	wchar_t	*linebufptr, *p;
	char	*bufptr = 0;
	int	quotefound;	/* double quote was seen */
	int	inmsgid = 0;	/* indicates "msgid" was seen */
	int	inmsgstr = 0;	/* indicates "msgstr" was seen */
	int	indomain = 0;	/* indicates "domain" was seen */
	wchar_t	wc;
	char	mb;
	int	n;
	char	token_found;	/* Boolean value */
	unsigned int	bufptr_index = 0; /* current index of bufptr */
	char	*mbuf, *addr;
	size_t	fsize, ln_size, ll;
	wchar_t	*linebufhead = NULL;
	struct stat64	statbuf;
	char	*filename;

	/*
	 * For each po file to be read,
	 * 1) set domain to default and
	 * 2) set linenumer to 0.
	 */
	(void) strcpy(gcurrent_domain, DEFAULT_DOMAIN);
	linenum = 0;

	if (!inputdir) {
		filename = Xstrdup(file);
	} else {
		size_t	dirlen, filelen, len;

		dirlen = strlen(inputdir);
		filelen = strlen(file);
		len = dirlen + 1 + filelen + 1;
		filename = (char *)Xmalloc(len);
		(void) memcpy(filename, inputdir, dirlen);
		*(filename + dirlen) = '/';
		(void) memcpy(filename + dirlen + 1, file, filelen);
		*(filename + dirlen + 1 + filelen) = '\0';
	}

	fd = open(filename, O_RDONLY);
	if (fd == -1) {
		error(gettext(ERR_OPEN_FAILED), filename);
		/* NOTREACHED */
	}
	if (fstat64(fd, &statbuf) == -1) {
		error(gettext(ERR_STAT_FAILED), filename);
		/* NOTREACHED */
	}
	fsize = (size_t)statbuf.st_size;
	if (fsize == 0) {
		/*
		 * The size of the specified po file is 0.
		 * In Solaris 8 and earlier, msgfmt was silent
		 * for the null po file.  So, just returns
		 * without generating an error message.
		 */
		(void) close(fd);
		free(filename);
		return;
	}
	addr = mmap(NULL, fsize, PROT_READ, MAP_SHARED, fd, 0);
	if (addr == MAP_FAILED) {
		error(gettext(ERR_MMAP_FAILED), filename);
		/* NOTREACHED */
	}
	(void) close(fd);

	if (!sun_p)
		check_gnu(addr, fsize);

	mbuf = addr;
	for (;;) {
		if (linebufhead) {
			free(linebufhead);
			linebufhead = NULL;
		}
		ln_size = _mbsntowcs(&linebufhead, &mbuf, &fsize);
		if (ln_size == (size_t)-1) {
			error(gettext(ERR_READ_FAILED), filename);
			/* NOTREACHED */
		} else if (ln_size == 0) {
			break;	/* End of File. */
		}
		linenum++;

		linebufptr = linebufhead;
		quotefound = 0;

		switch (*linebufptr) {
			case L'#':	/* comment    */
			case L'\n':	/* empty line */
				continue;
			case L'\"': /* multiple lines of msgid and msgstr */
				quotefound = 1;
				break;
		}

		/*
		 * Process MSGID Tokens.
		 */
		token_found = (wcsncmp(MSGID_TOKEN, linebufptr,
				MSGID_LEN) == 0) ? 1 : 0;

		if (token_found || (quotefound && inmsgid)) {

			if (token_found) {
				if (!CK_NXT_CH(linebufptr, MSGID_LEN+1)) {
					diag(gettext(ERR_NOSPC), linenum);
					error(gettext(ERR_EXITING));
					/* NOTREACHED */
				}
			}

			if (inmsgid && !quotefound) {
				warning(gettext(WARN_NO_MSGSTR), msgid_linenum);
				continue;
			}
			if (inmsgstr) {
				sortit(gmsgid, gmsgstr);
				(void) memset(gmsgid, 0, gmsgid_size);
				(void) memset(gmsgstr, 0, gmsgstr_size);
			}

			if (inmsgid) {
				/* multiple lines of msgid */
				/* cancel the previous null termination */
				bufptr_index--;
			} else {
				/*
				 * The first line of msgid.
				 * Save linenum of msgid to be used when
				 * printing warning or error message.
				 */
				msgid_linenum = linenum;
				p = linebufptr;
				linebufptr = consume_whitespace(
					linebufptr + MSGID_LEN);
				ln_size -= linebufptr - p;
				bufptr = gmsgid;
				bufptr_index = 0;
			}

			inmsgid = 1;
			inmsgstr = 0;
			indomain = 0;
			goto load_buffer;
		}

		/*
		 * Process MSGSTR Tokens.
		 */
		token_found = (wcsncmp(MSGSTR_TOKEN, linebufptr,
			MSGSTR_LEN) == 0) ? 1 : 0;
		if (token_found || (quotefound && inmsgstr)) {

			if (token_found) {
				if (!CK_NXT_CH(linebufptr, MSGSTR_LEN+1)) {
					diag(gettext(ERR_NOSPC), linenum);
					error(gettext(ERR_EXITING));
					/* NOTREACHED */
				}
			}


			if (inmsgstr && !quotefound) {
				warning(gettext(WARN_NO_MSGID), msgstr_linenum);
				continue;
			}
			if (inmsgstr) {
				/* multiple lines of msgstr */
				/* cancel the previous null termination */
				bufptr_index--;
			} else {
				/*
				 * The first line of msgstr.
				 * Save linenum of msgid to be used when
				 * printing warning or error message.
				 */
				msgstr_linenum = linenum;
				p = linebufptr;
				linebufptr = consume_whitespace(
					linebufptr + MSGSTR_LEN);
				ln_size -= linebufptr - p;
				bufptr = gmsgstr;
				bufptr_index = 0;
			}

			inmsgstr = 1;
			inmsgid = 0;
			indomain = 0;
			goto load_buffer;
		}

		/*
		 * Process DOMAIN Tokens.
		 * Add message id and message string to sorted list
		 * if msgstr was processed last time.
		 */
		token_found = (wcsncmp(DOMAIN_TOKEN, linebufptr,
			DOMAIN_LEN) == 0) ? 1 : 0;
		if ((token_found) || (quotefound && indomain)) {
			if (token_found) {
				if (!CK_NXT_CH(linebufptr, DOMAIN_LEN+1)) {
					diag(gettext(ERR_NOSPC), linenum);
					error(gettext(ERR_EXITING));
					/* NOTREACHED */
				}
			}


			/*
			 * process msgid and msgstr pair for previous domain
			 */
			if (inmsgstr) {
				sortit(gmsgid, gmsgstr);
			}

			/* refresh msgid and msgstr buffer */
			if (inmsgstr || inmsgid) {
				(void) memset(gmsgid, 0, gmsgid_size);
				(void) memset(gmsgstr, 0, gmsgstr_size);
			}

			if (indomain) {
				/* multiple lines of domain */
				/* cancel the previous null termination */
				bufptr_index--;
			} else {
				p = linebufptr;
				linebufptr = consume_whitespace(
					linebufptr + DOMAIN_LEN);
				(void) memset(gcurrent_domain, 0,
						sizeof (gcurrent_domain));
				ln_size -= linebufptr - p;
				bufptr = gcurrent_domain;
				bufptr_index = 0;
			}

			indomain = 1;
			inmsgid = 0;
			inmsgstr = 0;
		} /* if */

load_buffer:
		/*
		 * Now, fill up the buffer pointed by bufptr.
		 * At this point bufptr should point to one of
		 * msgid, msgptr, or current_domain.
		 * Otherwise, the entire line is ignored.
		 */

		if (!bufptr) {
			warning(gettext(WARN_SYNTAX_ERR), linenum);
			continue;
		}

		if (*linebufptr++ != L'\"') {
			warning(gettext(WARN_MISSING_QUOTE), linenum);
			--linebufptr;
		}
		quotefound = 0;

		/*
		 * If there is not enough space in the buffer,
		 * increase buffer by ln_size by realloc.
		 */
		ll = ln_size * mbcurmax;
		if (bufptr == gmsgid) {
			if (gmsgid_size < (bufptr_index + ll)) {
				gmsgid = (char *)Xrealloc(gmsgid,
					bufptr_index + ll);
				bufptr = gmsgid;
				gmsgid_size = bufptr_index + ll;
			}
		} else if (bufptr == gmsgstr) {
			if (gmsgstr_size < (bufptr_index + ll)) {
				gmsgstr = (char *)Xrealloc(gmsgstr,
					bufptr_index + ll);
				bufptr = gmsgstr;
				gmsgstr_size = bufptr_index + ll;
			}
		}

		while (wc = *linebufptr++) {
			switch (wc) {
			case L'\n':
				if (!quotefound) {
warning(gettext(WARN_MISSING_QUOTE_AT_EOL), linenum);
				}
				break;

			case L'\"':
				quotefound = 1;
				break;

			case L'\\':
				if ((mb = expand_meta(&linebufptr)) != NULL)
					bufptr[bufptr_index++] = mb;
				break;

			default:
				if ((n = wctomb(&bufptr[bufptr_index], wc)) > 0)
					bufptr_index += n;
			} /* switch */
			if (quotefound) {
				/*
				 * Check if any remaining characters
				 * after closing quote.
				 */
				linebufptr = consume_whitespace(linebufptr);
				if (*linebufptr != L'\n') {
					warning(gettext(WARN_INVALID_STRING),
						linenum);
				}
				break;
			}
		} /* while */

		bufptr[bufptr_index++] = '\0';

		(void) strcpy(msgfile, gcurrent_domain);
		(void) strcat(msgfile, ".mo");
	} /* for(;;) */

	if (inmsgstr) {
		sortit(gmsgid, gmsgstr);
	}

	if (linebufhead)
		free(linebufhead);
	if (munmap(addr, statbuf.st_size) == -1) {
		error(gettext(ERR_MUNMAP_FAILED), filename);
		/* NOTREACHED */
	}

	free(filename);
	return;

} /* read_psffm */
示例#11
0
char *
parse_function_definition(Functions *functions, char cell_str[2], char *f_ptr, char *f_end, Cell *cell)
{
  u32 function_index = get_function_index(cell_str);

  char *start_f_ptr = f_ptr;

  consume_whitespace(f_ptr, f_end);

  if (str_eq(f_ptr, "->", 2))
  {
    // Function Definition
    log(L_Parser, "Parsing function definition,");

    f_ptr += 2;

    Function *function = functions->hash_table + function_index;

    if (function->type != FUNCTION_NULL)
    {
      log(L_Parser, "Function already defined, ignore this definition.");
    }
    else
    {
      function->name[0] = cell_str[0];
      function->name[1] = cell_str[1];

      consume_whitespace(f_ptr, f_end);

      if (*f_ptr == '=')
      {
        log(L_Parser, "  Type: Assignment,");

        ++f_ptr;
        consume_whitespace(f_ptr, f_end);

        u32 assignment_value;
        char *end_num_f_ptr = get_num(f_ptr, f_end, &assignment_value);

        if (end_num_f_ptr == f_ptr)
        {
          function->type = FUNCTION_NULL;
          log(L_Parser, "  Function invalid: Assignment value missing.");
        }
        else
        {
          log(L_Parser, "  Value: %d", assignment_value);
          f_ptr = end_num_f_ptr;

          function->value = assignment_value;
          function->type = FUNCTION_ASSIGNMENT;
        }
      }
      else if ((f_ptr[0] == '+' ||
                f_ptr[0] == '-' ||
                f_ptr[0] == '*' ||
                f_ptr[0] == '/') && f_ptr[1] == '=')
      {
        log(L_Parser, "  Type: Operator,");

        char sign = f_ptr[0];

        f_ptr += 2;
        consume_whitespace(f_ptr, f_end);

        u32 assignment_value;
        char *end_num_f_ptr = get_num(f_ptr, f_end, &assignment_value);
        if (end_num_f_ptr == f_ptr)
        {
          function->type = FUNCTION_NULL;
          log(L_Parser, "  Invalid function: Operator value missing.");
        }
        else
        {
          log(L_Parser, "  Value: %d", assignment_value);
          f_ptr = end_num_f_ptr;

          function->value = assignment_value;

          switch (sign)
          {
            case '+':
            {
              function->type = FUNCTION_INCREMENT;
            } break;
            case '-':
            {
              function->type = FUNCTION_DECREMENT;
            } break;
            case '*':
            {
              function->type = FUNCTION_MULTIPLY;
            } break;
            case '/':
            {
              function->type = FUNCTION_DIVIDE;
            } break;
          }
        }
      }
      else if (str_eq(f_ptr, "IF", 2) || str_eq(f_ptr, "if", 2))
      {
        log(L_Parser, "  Type: Conditional,");

        f_ptr += 2;
        consume_whitespace(f_ptr, f_end);

        FunctionType conditional_func_type;
        b32 valid_condition = true;

        if (str_eq(f_ptr, "<=", 2))
        {
          f_ptr += 2;
          conditional_func_type = FUNCTION_LESS_EQUAL;
        }
        else if (*f_ptr == '<')
        {
          f_ptr += 1;
          conditional_func_type = FUNCTION_LESS;
        }
        else if (str_eq(f_ptr, ">=", 2))
        {
          f_ptr += 2;
          conditional_func_type = FUNCTION_GREATER_EQUAL;
        }
        else if (*f_ptr == '>')
        {
          f_ptr += 1;
          conditional_func_type = FUNCTION_GREATER;
        }
        else if (str_eq(f_ptr, "==", 2))
        {
          f_ptr += 2;
          conditional_func_type = FUNCTION_EQUAL;
        }
        else if (str_eq(f_ptr, "!=", 2))
        {
          f_ptr += 2;
          conditional_func_type = FUNCTION_NOT_EQUAL;
        }
        else
        {
          log(L_Parser, "  Invalid function: Conditional operator missing.");
          function->type = FUNCTION_NULL;
          valid_condition = false;
        }

        if (valid_condition)
        {
          consume_whitespace(f_ptr, f_end);

          u32 condition_value;
          char *end_num_f_ptr = get_num(f_ptr, f_end, &condition_value);
          if (end_num_f_ptr == f_ptr)
          {
            log(L_Parser, "  Invalid function: Missing condition value.");
            function->type = FUNCTION_NULL;
          }
          else
          {
            log(L_Parser, "  Condition value: %d", condition_value);
            f_ptr = end_num_f_ptr;

            consume_whitespace(f_ptr, f_end);

            if (!(str_eq(f_ptr, "THEN", 4) || str_eq(f_ptr, "then", 4)))
            {
              log(L_Parser, "  Invalid function: Missing 'THEN' keyword.");
              function->type = FUNCTION_NULL;
            }
            else
            {
              f_ptr += 4;
              consume_whitespace(f_ptr, f_end);

              V2 true_direction;
              char *end_true_direction_f_ptr = get_direction(f_ptr, &true_direction);
              if (end_true_direction_f_ptr == f_ptr)
              {
                log(L_Parser, "  Invalid function: Missing 'THEN' direction.");
                function->type = FUNCTION_NULL;
              }
              else
              {
                log(L_Parser, "  THEN direction: (%f, %f)", true_direction.x, true_direction.y);
                f_ptr = end_true_direction_f_ptr;

                consume_whitespace(f_ptr, f_end);

                b32 valid_conditional_function = true;
                b32 else_exists = false;
                V2 false_direction;

                // ELSE is optional
                if (str_eq(f_ptr, "ELSE", 4) || str_eq(f_ptr, "else", 4))
                {
                  else_exists = true;

                  f_ptr += 4;
                  consume_whitespace(f_ptr, f_end);

                  char *end_false_direction_f_ptr = get_direction(f_ptr, &false_direction);
                  if (end_false_direction_f_ptr == f_ptr)
                  {
                    log(L_Parser, "Invalid function: Missing 'ELSE' direction.");
                    valid_conditional_function = false;
                    function->type = FUNCTION_NULL;
                  }
                  else
                  {
                    log(L_Parser, "  ELSE direction: (%f, %f)", false_direction.x, false_direction.y);
                    f_ptr = end_false_direction_f_ptr;

                    valid_conditional_function = true;
                  }
                }

                if (valid_conditional_function)
                {
                  function->type = conditional_func_type;
                  function->conditional.value = condition_value;
                  function->conditional.true_direction = true_direction;

                  function->conditional.else_exists = else_exists;
                  if (else_exists)
                  {
                    function->conditional.false_direction = false_direction;
                  }
                }

              }
            }
          }
        }
      }
    }

    if (function->type != FUNCTION_NULL)
    {
      ++functions->n_functions;
    }

    consume_until_newline(f_ptr, f_end);
  }
  else
  {
    f_ptr = start_f_ptr;
  }

  return f_ptr;
}