/* Extract messages until the next balanced closing parenthesis. Extracted messages are added to MLP. Return true upon eof, false upon closing parenthesis. */ static bool extract_parenthesized (message_list_ty *mlp, flag_context_ty outer_context, flag_context_list_iterator_ty context_iter, bool in_i18n) { int state; /* 1 or 2 inside _( ... ), otherwise 0 */ int plural_state = 0; /* defined only when in states 1 and 2 */ message_ty *plural_mp = NULL; /* defined only when in states 1 and 2 */ /* Context iterator that will be used if the next token is a '('. */ flag_context_list_iterator_ty next_context_iter = passthrough_context_list_iterator; /* Current context. */ flag_context_ty inner_context = inherited_context (outer_context, flag_context_list_iterator_advance (&context_iter)); /* Start state is 0 or 1. */ state = (in_i18n ? 1 : 0); for (;;) { token_ty token; if (in_i18n) phase8_get (&token); else phase5_get (&token); switch (token.type) { case token_type_i18n: if (extract_parenthesized (mlp, inner_context, next_context_iter, true)) return true; next_context_iter = null_context_list_iterator; state = 0; continue; case token_type_string_literal: if (state == 1) { lex_pos_ty pos; pos.file_name = logical_file_name; pos.line_number = token.line_number; if (plural_state == 0) { /* Seen an msgid. */ plural_mp = remember_a_message (mlp, NULL, token.string, inner_context, &pos, NULL, token.comment); plural_state = 1; state = 2; } else { /* Seen an msgid_plural. */ if (plural_mp != NULL) remember_a_message_plural (plural_mp, token.string, inner_context, &pos, token.comment); state = 0; } drop_reference (token.comment); } else { free_token (&token); state = 0; } next_context_iter = null_context_list_iterator; continue; case token_type_symbol: next_context_iter = flag_context_list_iterator ( flag_context_list_table_lookup ( flag_context_list_table, token.string, strlen (token.string))); free_token (&token); state = 0; continue; case token_type_lparen: if (extract_parenthesized (mlp, inner_context, next_context_iter, false)) return true; next_context_iter = null_context_list_iterator; state = 0; continue; case token_type_rparen: return false; case token_type_comma: if (state == 2) state = 1; else state = 0; inner_context = inherited_context (outer_context, flag_context_list_iterator_advance ( &context_iter)); next_context_iter = passthrough_context_list_iterator; continue; case token_type_other: next_context_iter = null_context_list_iterator; state = 0; continue; case token_type_eof: return true; default: abort (); } } }
/* Extract messages until the next balanced closing parenthesis. Extracted messages are added to MLP. Return true upon eof, false upon closing parenthesis. */ static bool extract_parenthesized (message_list_ty *mlp, flag_context_ty outer_context, flag_context_list_iterator_ty context_iter, struct arglist_parser *argparser) { /* Current argument number. */ int arg = 1; /* 0 when no keyword has been seen. 1 right after a keyword is seen. */ int state; /* Parameters of the keyword just seen. Defined only in state 1. */ const struct callshapes *next_shapes = NULL; /* Whether to implicitly assume the next tokens are arguments even without a '('. */ bool next_is_argument = false; /* Context iterator that will be used if the next token is a '('. */ flag_context_list_iterator_ty next_context_iter = passthrough_context_list_iterator; /* Current context. */ flag_context_ty inner_context = inherited_context (outer_context, flag_context_list_iterator_advance (&context_iter)); /* Start state is 0. */ state = 0; for (;;) { token_ty token; x_awk_lex (&token); if (next_is_argument && token.type != token_type_lparen) { /* An argument list starts, even though there is no '('. */ context_iter = next_context_iter; outer_context = inner_context; inner_context = inherited_context (outer_context, flag_context_list_iterator_advance ( &context_iter)); } switch (token.type) { case token_type_symbol: { void *keyword_value; if (hash_find_entry (&keywords, token.string, strlen (token.string), &keyword_value) == 0) { next_shapes = (const struct callshapes *) keyword_value; state = 1; } else state = 0; } next_is_argument = (strcmp (token.string, "print") == 0 || strcmp (token.string, "printf") == 0); next_context_iter = flag_context_list_iterator ( flag_context_list_table_lookup ( flag_context_list_table, token.string, strlen (token.string))); free (token.string); continue; case token_type_lparen: if (extract_parenthesized (mlp, inner_context, next_context_iter, arglist_parser_alloc (mlp, state ? next_shapes : NULL))) { arglist_parser_done (argparser, arg); return true; } next_is_argument = false; next_context_iter = null_context_list_iterator; state = 0; continue; case token_type_rparen: arglist_parser_done (argparser, arg); return false; case token_type_comma: arg++; inner_context = inherited_context (outer_context, flag_context_list_iterator_advance ( &context_iter)); next_is_argument = false; next_context_iter = passthrough_context_list_iterator; state = 0; continue; case token_type_string: { lex_pos_ty pos; pos.file_name = logical_file_name; pos.line_number = token.line_number; if (extract_all) remember_a_message (mlp, NULL, token.string, inner_context, &pos, NULL, savable_comment); else arglist_parser_remember (argparser, arg, token.string, inner_context, pos.file_name, pos.line_number, savable_comment); } next_is_argument = false; next_context_iter = null_context_list_iterator; state = 0; continue; case token_type_i18nstring: { lex_pos_ty pos; pos.file_name = logical_file_name; pos.line_number = token.line_number; remember_a_message (mlp, NULL, token.string, inner_context, &pos, NULL, savable_comment); } next_is_argument = false; next_context_iter = null_context_list_iterator; state = 0; continue; case token_type_semicolon: /* An argument list ends, and a new statement begins. */ /* FIXME: Should handle newline that acts as statement separator in the same way. */ /* FIXME: Instead of resetting outer_context here, it may be better to recurse in the next_is_argument handling above, waiting for the next semicolon or other statement terminator. */ outer_context = null_context; context_iter = null_context_list_iterator; next_is_argument = false; next_context_iter = passthrough_context_list_iterator; inner_context = inherited_context (outer_context, flag_context_list_iterator_advance ( &context_iter)); state = 0; continue; case token_type_eof: arglist_parser_done (argparser, arg); return true; case token_type_other: next_is_argument = false; next_context_iter = null_context_list_iterator; state = 0; continue; default: abort (); } } }
/* Extract messages until the next balanced closing parenthesis or bracket. Extracted messages are added to MLP. DELIM can be either token_type_rparen or token_type_rbracket, or token_type_eof to accept both. Return true upon eof, false upon closing parenthesis. */ static bool extract_balanced (message_list_ty *mlp, token_type_ty delim, flag_context_ty outer_context, flag_context_list_iterator_ty context_iter, struct arglist_parser *argparser) { /* Current argument number. */ int arg = 1; /* 0 when no keyword has been seen. 1 right after a keyword is seen. */ int state; /* Parameters of the keyword just seen. Defined only in state 1. */ const struct callshapes *next_shapes = NULL; /* Context iterator that will be used if the next token is a '('. */ flag_context_list_iterator_ty next_context_iter = passthrough_context_list_iterator; /* Current context. */ flag_context_ty inner_context = inherited_context (outer_context, flag_context_list_iterator_advance (&context_iter)); /* Start state is 0. */ state = 0; for (;;) { token_ty token; x_php_lex (&token); switch (token.type) { case token_type_symbol: { void *keyword_value; if (hash_find_entry (&keywords, token.string, strlen (token.string), &keyword_value) == 0) { next_shapes = (const struct callshapes *) keyword_value; state = 1; } else state = 0; } next_context_iter = flag_context_list_iterator ( flag_context_list_table_lookup ( flag_context_list_table, token.string, strlen (token.string))); free (token.string); continue; case token_type_lparen: if (extract_balanced (mlp, token_type_rparen, inner_context, next_context_iter, arglist_parser_alloc (mlp, state ? next_shapes : NULL))) { arglist_parser_done (argparser, arg); return true; } next_context_iter = null_context_list_iterator; state = 0; continue; case token_type_rparen: if (delim == token_type_rparen || delim == token_type_eof) { arglist_parser_done (argparser, arg); return false; } next_context_iter = null_context_list_iterator; state = 0; continue; case token_type_comma: arg++; inner_context = inherited_context (outer_context, flag_context_list_iterator_advance ( &context_iter)); next_context_iter = passthrough_context_list_iterator; state = 0; continue; case token_type_lbracket: if (extract_balanced (mlp, token_type_rbracket, null_context, null_context_list_iterator, arglist_parser_alloc (mlp, NULL))) { arglist_parser_done (argparser, arg); return true; } case token_type_rbracket: if (delim == token_type_rbracket || delim == token_type_eof) { arglist_parser_done (argparser, arg); return false; } next_context_iter = null_context_list_iterator; state = 0; continue; case token_type_string_literal: { lex_pos_ty pos; pos.file_name = logical_file_name; pos.line_number = token.line_number; if (extract_all) remember_a_message (mlp, NULL, token.string, inner_context, &pos, token.comment); else arglist_parser_remember (argparser, arg, token.string, inner_context, pos.file_name, pos.line_number, token.comment); drop_reference (token.comment); } next_context_iter = null_context_list_iterator; state = 0; continue; case token_type_dot: case token_type_operator1: case token_type_operator2: case token_type_other: next_context_iter = null_context_list_iterator; state = 0; continue; case token_type_eof: arglist_parser_done (argparser, arg); return true; default: abort (); } } }
void extract_rst (FILE *f, const char *real_filename, const char *logical_filename, flag_context_list_table_ty *flag_table, msgdomain_list_ty *mdlp) { static char *buffer; static int bufmax; message_list_ty *mlp = mdlp->item[0]->messages; int line_number; line_number = 1; for (;;) { int c; int bufpos; char *location; char *msgid; lex_pos_ty pos; c = getc (f); if (c == EOF) break; /* Ignore blank line. */ if (c == '\n') { line_number++; continue; } /* Ignore comment line. */ if (c == '#') { do c = getc (f); while (c != EOF && c != '\n'); if (c == EOF) break; line_number++; continue; } /* Read ModuleName.ConstName. */ bufpos = 0; for (;;) { if (c == EOF || c == '\n') { error_with_progname = false; error (EXIT_FAILURE, 0, _("%s:%d: invalid string definition"), logical_filename, line_number); error_with_progname = true; } if (bufpos >= bufmax) { bufmax = 2 * bufmax + 10; buffer = xrealloc (buffer, bufmax); } if (c == '=') break; buffer[bufpos++] = c; c = getc (f); if (c == EOF && ferror (f)) goto bomb; } buffer[bufpos] = '\0'; location = xstrdup (buffer); /* Read StringExpression. */ bufpos = 0; for (;;) { c = getc (f); if (c == EOF) break; else if (c == '\n') { line_number++; break; } else if (c == '\'') { for (;;) { c = getc (f); /* Embedded single quotes like 'abc''def' don't occur. See fpc-1.0.4/compiler/cresstr.pas. */ if (c == EOF || c == '\n' || c == '\'') break; if (bufpos >= bufmax) { bufmax = 2 * bufmax + 10; buffer = xrealloc (buffer, bufmax); } buffer[bufpos++] = c; } if (c == EOF) break; else if (c == '\n') { line_number++; break; } } else if (c == '#') { int n; c = getc (f); if (c == EOF && ferror (f)) goto bomb; if (c == EOF || !c_isdigit (c)) { error_with_progname = false; error (EXIT_FAILURE, 0, _("%s:%d: missing number after #"), logical_filename, line_number); error_with_progname = true; } n = (c - '0'); for (;;) { c = getc (f); if (c == EOF || !c_isdigit (c)) break; n = n * 10 + (c - '0'); } if (bufpos >= bufmax) { bufmax = 2 * bufmax + 10; buffer = xrealloc (buffer, bufmax); } buffer[bufpos++] = (unsigned char) n; if (c == EOF) break; ungetc (c, f); } else if (c == '+') { c = getc (f); if (c == EOF) break; if (c == '\n') line_number++; else ungetc (c, f); } else { error_with_progname = false; error (EXIT_FAILURE, 0, _("%s:%d: invalid string expression"), logical_filename, line_number); error_with_progname = true; } } if (bufpos >= bufmax) { bufmax = 2 * bufmax + 10; buffer = xrealloc (buffer, bufmax); } buffer[bufpos] = '\0'; msgid = xstrdup (buffer); pos.file_name = location; pos.line_number = (size_t)(-1); remember_a_message (mlp, NULL, msgid, null_context, &pos, NULL); /* Here c is the last read character: EOF or '\n'. */ if (c == EOF) break; } if (ferror (f)) { bomb: error (EXIT_FAILURE, errno, _("error while reading \"%s\""), real_filename); } }
void extract_smalltalk (FILE *f, const char *real_filename, const char *logical_filename, flag_context_list_table_ty *flag_table, msgdomain_list_ty *mdlp) { message_list_ty *mlp = mdlp->item[0]->messages; fp = f; real_file_name = real_filename; logical_file_name = xstrdup (logical_filename); line_number = 1; last_comment_line = -1; last_non_comment_line = -1; /* Eat tokens until eof is seen. */ { /* 0 when no "NLS" has been seen. 1 after "NLS". 2 after "NLS ?". 3 after "NLS at:". 4 after "NLS at: <string>". 5 after "NLS at: <string> plural:". */ int state; /* Remember the message containing the msgid, for msgid_plural. Non-NULL in states 4, 5. */ message_ty *plural_mp = NULL; /* Start state is 0. */ state = 0; for (;;) { token_ty token; x_smalltalk_lex (&token); switch (token.type) { case token_type_symbol: state = (strcmp (token.string, "NLS") == 0 ? 1 : strcmp (token.string, "?") == 0 && state == 1 ? 2 : strcmp (token.string, "at:") == 0 && state == 1 ? 3 : strcmp (token.string, "plural:") == 0 && state == 4 ? 5 : 0); free (token.string); break; case token_type_string_literal: if (state == 2) { lex_pos_ty pos; pos.file_name = logical_file_name; pos.line_number = token.line_number; remember_a_message (mlp, NULL, token.string, null_context, &pos, savable_comment); state = 0; break; } if (state == 3) { lex_pos_ty pos; pos.file_name = logical_file_name; pos.line_number = token.line_number; plural_mp = remember_a_message (mlp, NULL, token.string, null_context, &pos, savable_comment); state = 4; break; } if (state == 5) { lex_pos_ty pos; pos.file_name = logical_file_name; pos.line_number = token.line_number; remember_a_message_plural (plural_mp, token.string, null_context, &pos, savable_comment); state = 0; break; } state = 0; free (token.string); break; case token_type_uniq: case token_type_other: state = 0; break; case token_type_eof: break; default: abort (); } if (token.type == token_type_eof) break; } } /* Close scanner. */ fp = NULL; real_file_name = NULL; logical_file_name = NULL; line_number = 0; }