/* 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); } }
/* 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; }
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 } }
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); } }
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; }
/* 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; }
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); }
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 */
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; }