]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - parser.c
converted qcvm.1 to mdoc
[xonotic/gmqcc.git] / parser.c
index d64dd2e1de187c2f133b528b07a0a443cf1591a4..bfd8e845ddfc1c320df6e5df1b472953f12107aa 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -630,7 +630,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
             {
 #if 0
                 /* This is not broken in fteqcc anymore */
-                if (opts.standard != COMPILER_GMQCC) {
+                if (OPTS_OPTION_U32(OPTION_STANDARD) != COMPILER_GMQCC) {
                     /* this error doesn't need to make us bail out */
                     (void)!parsewarning(parser, WARN_EXTENSIONS,
                                         "accessing array-field members of an entity without parenthesis\n"
@@ -1101,7 +1101,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                 }
                 else
                     assignop = type_storep_instr[exprs[0]->expression.vtype];
-                if (assignop == AINSTR_END || !ast_compare_type(field->expression.next, exprs[1]))
+                if (assignop == VINSTR_END || !ast_compare_type(field->expression.next, exprs[1]))
                 {
                     ast_type_to_string(field->expression.next, ty1, sizeof(ty1));
                     ast_type_to_string(exprs[1], ty2, sizeof(ty2));
@@ -1128,7 +1128,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                     assignop = type_store_instr[exprs[0]->expression.vtype];
                 }
 
-                if (assignop == AINSTR_END) {
+                if (assignop == VINSTR_END) {
                     ast_type_to_string(exprs[0], ty1, sizeof(ty1));
                     ast_type_to_string(exprs[1], ty2, sizeof(ty2));
                     compile_error(ctx, "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
@@ -1784,7 +1784,7 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels)
                  * We should also consider adding correction tables for
                  * other things as well.
                  */
-                if (opts.correction) {
+                if (OPTS_OPTION_BOOL(OPTION_CORRECTION)) {
                     correction_t corr;
                     correct_init(&corr);
 
@@ -2635,7 +2635,7 @@ static bool parse_for_go(parser_t *parser, ast_block *block, ast_expression **ou
 
     if (typevar || parser->tok == TOKEN_TYPENAME) {
 #if 0
-        if (opts.standard != COMPILER_GMQCC) {
+        if (OPTS_OPTION_U32(OPTION_STANDARD) != COMPILER_GMQCC) {
             if (parsewarning(parser, WARN_EXTENSIONS,
                              "current standard does not allow variable declarations in for-loop initializers"))
                 goto onerr;
@@ -3292,26 +3292,15 @@ static bool parse_eol(parser_t *parser)
     return parser->tok == TOKEN_EOL;
 }
 
-/*
- * Traditionally you'd implement warning, error, and message
- * directives in the preprocessor. However, like #pragma, these
- * shouldn't depend on -fftepp to utilize.  So they're instead
- * implemented here.
- */   
-enum {
-    PARSE_DIRECTIVE_ERROR,
-    PARSE_DIRECTIVE_MESSAGE,
-    PARSE_DIRECTIVE_WARNING,
-    PARSE_DIRECTIVE_COUNT
-};
-
-static const char *parser_directives[PARSE_DIRECTIVE_COUNT] = {
-    "error",
-    "message",
-    "warning"
-};
-
-static bool parse_pragma_do(parser_t *parser) {
+static bool parse_pragma_do(parser_t *parser)
+{
+    if (!parser_next(parser) ||
+        parser->tok != TOKEN_IDENT ||
+        strcmp(parser_tokval(parser), "pragma"))
+    {
+        parseerror(parser, "expected `pragma` keyword after `#`, got `%s`", parser_tokval(parser));
+        return false;
+    }
     if (!parse_skipwhite(parser) || parser->tok != TOKEN_IDENT) {
         parseerror(parser, "expected pragma, got `%s`", parser_tokval(parser));
         return false;
@@ -3322,102 +3311,35 @@ static bool parse_pragma_do(parser_t *parser) {
             parseerror(parser, "`noref` pragma requires an argument: 0 or 1");
             return false;
         }
-
         parser->noref = !!parser_token(parser)->constval.i;
-
         if (!parse_eol(parser)) {
             parseerror(parser, "parse error after `noref` pragma");
             return false;
         }
-    } else {
-        (void)!parsewarning(parser, WARN_UNKNOWN_PRAGMAS, "ignoring #pragma %s", parser_tokval(parser));
-        return false;
     }
-    return true;
-}
-
-static bool parse_directive_or_pragma_do(parser_t *parser, bool *pragma) {
-
-    size_t type = PARSE_DIRECTIVE_COUNT;
-
-    if (!parser_next(parser) || parser->tok != TOKEN_IDENT) {
-        parseerror(parser, "expected `pragma, error, message, warning` after `#`, got `%s`",
-            parser_tokval(parser));
-
+    else
+    {
+        (void)!parsewarning(parser, WARN_UNKNOWN_PRAGMAS, "ignoring #pragma %s", parser_tokval(parser));
         return false;
     }
 
-    if (!strcmp(parser_tokval(parser), "pragma" )) {
-        *pragma = true;
-
-        return parse_pragma_do(parser);
-    }
-
-    if (!strcmp(parser_tokval(parser), "error"  )) type = PARSE_DIRECTIVE_ERROR;
-    if (!strcmp(parser_tokval(parser), "message")) type = PARSE_DIRECTIVE_MESSAGE;
-    if (!strcmp(parser_tokval(parser), "warning")) type = PARSE_DIRECTIVE_WARNING;
-
-    switch (type) {
-        case PARSE_DIRECTIVE_ERROR:
-        case PARSE_DIRECTIVE_MESSAGE:
-        case PARSE_DIRECTIVE_WARNING:
-            *pragma = false;
-
-            if (!parse_skipwhite(parser) || parser->tok != TOKEN_STRINGCONST) {
-                parseerror(parser, "expected %s, got `%`", parser_directives[type], parser_tokval(parser));
-                return false;
-            }
-
-            switch (type) {
-                case PARSE_DIRECTIVE_ERROR:
-                    con_cprintmsg(&parser->lex->tok.ctx, LVL_ERROR, "error", parser_tokval(parser));
-                    compile_errors ++; /* hack */
-                    break;
-                    /*break;*/
-
-                case PARSE_DIRECTIVE_MESSAGE:
-                    con_cprintmsg(&parser->lex->tok.ctx, LVL_MSG, "message", parser_tokval(parser));
-                    break;
-
-                case PARSE_DIRECTIVE_WARNING:
-                    con_cprintmsg(&parser->lex->tok.ctx, LVL_WARNING, "warning", parser_tokval(parser));
-                    break;
-            }
-
-            if (!parse_eol(parser)) {
-                parseerror(parser, "parse error after `%` directive", parser_directives[type]);
-                return false;
-            }
-
-            return (type != PARSE_DIRECTIVE_ERROR);
-
-        default:
-            parseerror(parser, "invalid directive `%s`", parser_tokval(parser));
-            return false;
-    }
-
     return true;
 }
 
-static bool parse_directive_or_pragma(parser_t *parser)
+static bool parse_pragma(parser_t *parser)
 {
     bool rv;
-    bool pragma; /* true when parsing pragma */
     parser->lex->flags.preprocessing = true;
-    parser->lex->flags.mergelines    = true;
-
-    rv = parse_directive_or_pragma_do(parser, &pragma);
-
+    parser->lex->flags.mergelines = true;
+    rv = parse_pragma_do(parser);
     if (parser->tok != TOKEN_EOL) {
-        parseerror(parser, "junk after %s", (pragma) ? "pragma" : "directive");
+        parseerror(parser, "junk after pragma");
         rv = false;
     }
     parser->lex->flags.preprocessing = false;
-    parser->lex->flags.mergelines    = false;
-
+    parser->lex->flags.mergelines = false;
     if (!parser_next(parser)) {
-        parseerror(parser, "parse error after %s", (pragma) ? "pragma" : "directive");
+        parseerror(parser, "parse error after pragma");
         rv = false;
     }
     return rv;
@@ -3443,7 +3365,7 @@ static bool parse_statement(parser_t *parser, ast_block *block, ast_expression *
             parseerror(parser, "cannot declare a variable from here");
             return false;
         }
-        if (opts.standard == COMPILER_QCC) {
+        if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC) {
             if (parsewarning(parser, WARN_EXTENSIONS, "missing 'local' keyword when declaring a local variable"))
                 return false;
         }
@@ -3510,7 +3432,7 @@ static bool parse_statement(parser_t *parser, ast_block *block, ast_expression *
         }
         else if (!strcmp(parser_tokval(parser), "for"))
         {
-            if (opts.standard == COMPILER_QCC) {
+            if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC) {
                 if (parsewarning(parser, WARN_EXTENSIONS, "for loops are not recognized in the original Quake C standard, to enable try an alternate standard --std=?"))
                     return false;
             }
@@ -4112,7 +4034,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
 
     if (parser->tok == ';')
         return parser_next(parser);
-    else if (opts.standard == COMPILER_QCC)
+    else if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC)
         parseerror(parser, "missing semicolon after function body (mandatory with -std=qcc)");
     return retval;
 
@@ -4628,7 +4550,7 @@ static ast_value *parse_parameter_list(parser_t *parser, ast_value *var)
         vec_free(params);
 
     /* sanity check */
-    if (vec_size(params) > 8 && opts.standard == COMPILER_QCC)
+    if (vec_size(params) > 8 && OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC)
         (void)!parsewarning(parser, WARN_EXTENSIONS, "more than 8 parameters are not supported by this standard");
 
     /* parse-out */
@@ -4842,7 +4764,7 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_va
     }
 
     /* now there may be function parens again */
-    if (parser->tok == '(' && opts.standard == COMPILER_QCC)
+    if (parser->tok == '(' && OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC)
         parseerror(parser, "C-style function syntax is not allowed in -std=qcc");
     if (parser->tok == '(' && wasarray)
         parseerror(parser, "arrays as part of a return type is not supported");
@@ -4981,7 +4903,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
 
         /* Part 0: finish the type */
         if (parser->tok == '(') {
-            if (opts.standard == COMPILER_QCC)
+            if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC)
                 parseerror(parser, "C-style function syntax is not allowed in -std=qcc");
             var = parse_parameter_list(parser, var);
             if (!var) {
@@ -5004,7 +4926,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
         }
         /* for functions returning functions */
         while (parser->tok == '(') {
-            if (opts.standard == COMPILER_QCC)
+            if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC)
                 parseerror(parser, "C-style function syntax is not allowed in -std=qcc");
             var = parse_parameter_list(parser, var);
             if (!var) {
@@ -5074,7 +4996,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
                     goto cleanup;
                     */
                 }
-                if ((opts.standard == COMPILER_QCC || opts.standard == COMPILER_FTEQCC) &&
+                if ((OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC || OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_FTEQCC) &&
                     (old = parser_find_global(parser, var->name)))
                 {
                     parseerror(parser, "cannot declare a field and a global of the same name with -std=qcc");
@@ -5146,7 +5068,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
                         ast_delete(var);
                         var = proto;
                     }
-                    if (opts.standard == COMPILER_QCC &&
+                    if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC &&
                         (old = parser_find_field(parser, var->name)))
                     {
                         parseerror(parser, "cannot declare a field and a global of the same name with -std=qcc");
@@ -5177,7 +5099,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
                     retval = false;
                     goto cleanup;
                 }
-                if (opts.standard != COMPILER_GMQCC) {
+                if (OPTS_OPTION_U32(OPTION_STANDARD) != COMPILER_GMQCC) {
                     ast_delete(var);
                     var = NULL;
                     goto skipvar;
@@ -5357,7 +5279,7 @@ skipvar:
             break;
         }
 
-        if (localblock && opts.standard == COMPILER_QCC) {
+        if (localblock && OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC) {
             if (parsewarning(parser, WARN_LOCAL_CONSTANTS,
                              "initializing expression turns variable `%s` into a constant in this standard",
                              var->name) )
@@ -5377,7 +5299,7 @@ skipvar:
                 break;
             }
         }
-        else if (opts.standard == COMPILER_QCC) {
+        else if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC) {
             parseerror(parser, "expected '=' before function body in this standard");
         }
 
@@ -5598,7 +5520,7 @@ static bool parser_global_statement(parser_t *parser)
     }
     else if (parser->tok == '#')
     {
-        return parse_directive_or_pragma(parser);
+        return parse_pragma(parser);
     }
     else if (parser->tok == '$')
     {
@@ -5738,7 +5660,7 @@ bool parser_init()
     parser->const_vec[1] = ast_value_new(empty_ctx, "<vector.y>", TYPE_NOEXPR);
     parser->const_vec[2] = ast_value_new(empty_ctx, "<vector.z>", TYPE_NOEXPR);
 
-    if (opts.add_info) {
+    if (OPTS_OPTION_BOOL(OPTION_ADD_INFO)) {
         parser->reserved_version = ast_value_new(empty_ctx, "reserved:version", TYPE_STRING);
         parser->reserved_version->cvq = CV_CONST;
         parser->reserved_version->hasvalue = true;
@@ -6027,7 +5949,7 @@ bool parser_finish(const char *output)
             return false;
         }
     }
-    if (opts.dump)
+    if (OPTS_OPTION_BOOL(OPTION_DUMP))
         ir_builder_dump(ir, con_out);
     for (i = 0; i < vec_size(parser->functions); ++i) {
         if (!ir_function_finalize(parser->functions[i]->ir_func)) {
@@ -6044,7 +5966,7 @@ bool parser_finish(const char *output)
     }
 
     if (retval) {
-        if (opts.dumpfin)
+        if (OPTS_OPTION_BOOL(OPTION_DUMPFIN))
             ir_builder_dump(ir, con_out);
 
         generate_checksum(parser);