ast_value **imm_float;
ast_value **imm_string;
ast_value **imm_vector;
+ size_t translated;
/* must be deleted first, they reference immediates and values */
ast_value **accessors;
return util_strdup(str);
}
-static ast_value* parser_const_string(parser_t *parser, const char *str)
+static ast_value* parser_const_string(parser_t *parser, const char *str, bool dotranslate)
{
size_t i;
ast_value *out;
if (!strcmp(parser->imm_string[i]->constval.vstring, str))
return parser->imm_string[i];
}
- out = ast_value_new(parser_ctx(parser), "#IMMEDIATE", TYPE_STRING);
+ if (dotranslate) {
+ char name[32];
+ snprintf(name, sizeof(name), "dotranslate_%lu", (unsigned long)(parser->translated++));
+ out = ast_value_new(parser_ctx(parser), name, TYPE_STRING);
+ } else
+ out = ast_value_new(parser_ctx(parser), "#IMMEDIATE", TYPE_STRING);
out->isconst = true;
out->constval.vstring = parser_strdup(str);
vec_push(parser->imm_string, out);
else
parser->memberof = 0;
- if (parser->tok == TOKEN_IDENT)
+ if (OPTS_FLAG(TRANSLATABLE_STRINGS) &&
+ parser->tok == TOKEN_IDENT && !strcmp(parser_tokval(parser), "_"))
+ {
+ /* a translatable string */
+ ast_value *val;
+
+ if (wantop) {
+ parseerror(parser, "expected operator or end of statement, got constant");
+ goto onerr;
+ }
+
+ parser->lex->flags.noops = true;
+ if (!parser_next(parser) || parser->tok != '(') {
+ parseerror(parser, "use _(\"string\") to create a translatable string constant");
+ goto onerr;
+ }
+ parser->lex->flags.noops = false;
+ if (!parser_next(parser) || parser->tok != TOKEN_STRINGCONST) {
+ parseerror(parser, "expected a constant string in translatable-string extension");
+ goto onerr;
+ }
+ val = parser_const_string(parser, parser_tokval(parser), true);
+ wantop = true;
+ if (!val)
+ return false;
+ vec_push(sy.out, syexp(parser_ctx(parser), (ast_expression*)val));
+ DEBUGSHUNTDO(con_out("push string\n"));
+
+ if (!parser_next(parser) || parser->tok != ')') {
+ parseerror(parser, "expected closing paren after translatable string");
+ goto onerr;
+ }
+ }
+ else if (parser->tok == TOKEN_IDENT)
{
ast_expression *var;
if (wantop) {
goto onerr;
}
wantop = true;
- val = parser_const_string(parser, parser_tokval(parser));
+ val = parser_const_string(parser, parser_tokval(parser), false);
if (!val)
return false;
vec_push(sy.out, syexp(parser_ctx(parser), (ast_expression*)val));
const char *name = NULL;
bool isfield = false;
bool wasarray = false;
+ size_t morefields = 0;
ctx = parser_ctx(parser);
parseerror(parser, "expected typename for field definition");
return NULL;
}
+
+ /* Further dots are handled seperately because they won't be part of the
+ * basetype
+ */
+ while (parser->tok == '.') {
+ ++morefields;
+ if (!parser_next(parser)) {
+ parseerror(parser, "expected typename for field definition");
+ return NULL;
+ }
+ }
+
if (parser->tok == TOKEN_IDENT)
cached_typedef = parser_find_typedef(parser, parser_tokval(parser), 0);
if (!cached_typedef && parser->tok != TOKEN_TYPENAME) {
ast_value_set_name(var, "<type(from_def)>");
} else
var = ast_value_new(ctx, "<type>", parser_token(parser)->constval.t);
+
+ for (; morefields; --morefields) {
+ tmp = ast_value_new(ctx, "<.type>", TYPE_FIELD);
+ tmp->expression.next = (ast_expression*)var;
+ var = tmp;
+ }
+
/* do not yet turn into a field - remember:
* .void() foo; is a field too
* .void()() foo; is a function
}
}
- me[0] = me[1] = me[2] = NULL;
- cleanvar = false;
}
+ me[0] = me[1] = me[2] = NULL;
+ cleanvar = false;
/* Part 2.2
* deal with arrays
*/
if (parser->tok != '{') {
if (parser->tok != '=') {
- parseerror(parser, "missing semicolon or initializer");
+ parseerror(parser, "missing semicolon or initializer, got: `%s`", parser_tokval(parser));
break;
}
parseerror(parser, "expected variable declaration after 'const'");
return false;
}
+ if (parser->tok == TOKEN_IDENT && !strcmp(parser_tokval(parser), "var")) {
+ (void)!parsewarning(parser, WARN_CONST_VAR, "ignoring `var` after const qualifier");
+ if (!parser_next(parser)) {
+ parseerror(parser, "expected variable declaration after 'const var'");
+ return false;
+ }
+ }
return parse_variable(parser, NULL, true, true, NULL);
}
else if (!strcmp(parser_tokval(parser), "typedef")) {