]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - parser.c
Use the LIBS properly
[xonotic/gmqcc.git] / parser.c
index c1d3fb1d786641ecd3611c3e2f66337b897d968c..a19db282629e128dd0b9de61a150ba3385619e0b 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -2,7 +2,7 @@
  * Copyright (C) 2012, 2013
  *     Wolfgang Bumiller
  *     Dale Weiler
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a copy of
  * this software and associated documentation files (the "Software"), to deal in
  * the Software without restriction, including without limitation the rights to
@@ -217,6 +217,7 @@ static ast_value* parser_const_float(parser_t *parser, double d)
     out = ast_value_new(ctx, "#IMMEDIATE", TYPE_FLOAT);
     out->cvq      = CV_CONST;
     out->hasvalue = true;
+    out->isimm    = true;
     out->constval.vfloat = d;
     vec_push(parser->imm_float, out);
     return out;
@@ -257,10 +258,10 @@ static ast_value* parser_const_string(parser_t *parser, const char *str, bool do
 {
     size_t hash = util_hthash(parser->ht_imm_string, str);
     ast_value *out;
-    if ( (out = util_htgeth(parser->ht_imm_string, str, hash)) ) {
+    if ( (out = (ast_value*)util_htgeth(parser->ht_imm_string, str, hash)) ) {
         if (dotranslate && out->name[0] == '#') {
             char name[32];
-            snprintf(name, sizeof(name), "dotranslate_%lu", (unsigned long)(parser->translated++));
+            util_snprintf(name, sizeof(name), "dotranslate_%lu", (unsigned long)(parser->translated++));
             ast_value_set_name(out, name);
         }
         return out;
@@ -273,12 +274,13 @@ static ast_value* parser_const_string(parser_t *parser, const char *str, bool do
     */
     if (dotranslate) {
         char name[32];
-        snprintf(name, sizeof(name), "dotranslate_%lu", (unsigned long)(parser->translated++));
+        util_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->cvq      = CV_CONST;
     out->hasvalue = true;
+    out->isimm    = true;
     out->constval.vstring = parser_strdup(str);
     vec_push(parser->imm_string, out);
     util_htseth(parser->ht_imm_string, str, hash, out);
@@ -296,6 +298,7 @@ static ast_value* parser_const_vector(parser_t *parser, vector v)
     out = ast_value_new(parser_ctx(parser), "#IMMEDIATE", TYPE_VECTOR);
     out->cvq      = CV_CONST;
     out->hasvalue = true;
+    out->isimm    = true;
     out->constval.vvec = v;
     vec_push(parser->imm_vector, out);
     return out;
@@ -1888,6 +1891,8 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels)
                 vec_push(parser->labels, lbl);
             }
         }
+        if (!var && !strcmp(parser_tokval(parser), "__FUNC__"))
+            var = (ast_expression*)parser_const_string(parser, parser->function->name, false);
         if (!var) {
             /* intrinsics */
             if (!strcmp(parser_tokval(parser), "__builtin_debug_typestring")) {
@@ -1899,10 +1904,8 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels)
              */
             else if (!strncmp(parser_tokval(parser), "__builtin_", 10)) {
                 var = intrin_func(parser, parser_tokval(parser) + 10 /* skip __builtin */);
-            } else {
-                var = intrin_func(parser, parser_tokval(parser));
             }
-                
+
             if (!var) {
                 char *correct = NULL;
                 size_t i;
@@ -2182,8 +2185,27 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
             wantop = true;
         }
         else {
-            parseerror(parser, "expected operator or end of statement");
-            goto onerr;
+            /* in this case we might want to allow constant string concatenation */
+            bool concatenated = false;
+            if (parser->tok == TOKEN_STRINGCONST && vec_size(sy.out)) {
+                ast_expression *lexpr = vec_last(sy.out).out;
+                if (ast_istype(lexpr, ast_value)) {
+                    ast_value *last = (ast_value*)lexpr;
+                    if (last->isimm == true && last->cvq == CV_CONST &&
+                        last->hasvalue && last->expression.vtype == TYPE_STRING)
+                    {
+                        char *newstr = NULL;
+                        util_asprintf(&newstr, "%s%s", last->constval.vstring, parser_tokval(parser));
+                        vec_last(sy.out).out = (ast_expression*)parser_const_string(parser, newstr, false);
+                        mem_d(newstr);
+                        concatenated = true;
+                    }
+                }
+            }
+            if (!concatenated) {
+                parseerror(parser, "expected operator or end of statement");
+                goto onerr;
+            }
         }
 
         if (!parser_next(parser)) {
@@ -4227,13 +4249,13 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
         varargs->expression.flags |= AST_FLAG_IS_VARARG;
         varargs->expression.next = (ast_expression*)ast_value_new(ast_ctx(var), NULL, TYPE_VECTOR);
         varargs->expression.count = 0;
-        snprintf(name, sizeof(name), "%s##va##SET", var->name);
+        util_snprintf(name, sizeof(name), "%s##va##SET", var->name);
         if (!parser_create_array_setter_proto(parser, varargs, name)) {
             ast_delete(varargs);
             ast_block_delete(block);
             goto enderrfn;
         }
-        snprintf(name, sizeof(name), "%s##va##GET", var->name);
+        util_snprintf(name, sizeof(name), "%s##va##GET", var->name);
         if (!parser_create_array_getter_proto(parser, varargs, varargs->expression.next, name)) {
             ast_delete(varargs);
             ast_block_delete(block);
@@ -5114,7 +5136,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
     bool      cleanvar  = true;
     bool      wasarray  = false;
 
-    ast_member *me[3];
+    ast_member *me[3] = { NULL, NULL, NULL };
 
     if (!localblock && is_static)
         parseerror(parser, "`static` qualifier is not supported in global scope");
@@ -5171,7 +5193,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
         /*
          * store the vstring back to var for alias and
          * deprecation messages.
-         */   
+         */
         if (var->expression.flags & AST_FLAG_DEPRECATED ||
             var->expression.flags & AST_FLAG_ALIAS)
             var->desc = vstring;
@@ -5268,7 +5290,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
                         ast_value_set_name(proto->expression.params[i], var->expression.params[i]->name);
                     if (!parser_check_qualifiers(parser, var, proto)) {
                         retval = false;
-                        if (proto->desc) 
+                        if (proto->desc)
                             mem_d(proto->desc);
                         proto = NULL;
                         goto cleanup;
@@ -5409,13 +5431,13 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
                         /*
                          * add alias to aliases table and to corrector
                          * so corrections can apply for aliases as well.
-                         */  
+                         */
                         util_htset(parser->aliases, var->name, find);
 
                         /*
                          * add to corrector so corrections can work
                          * even for aliases too.
-                         */ 
+                         */
                         correct_add (
                              vec_last(parser->correct_variables),
                             &vec_last(parser->correct_variables_score),
@@ -5441,7 +5463,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
                             /*
                              * add to corrector so corrections can work
                              * even for aliases too.
-                             */  
+                             */
                             correct_add (
                                  vec_last(parser->correct_variables),
                                 &vec_last(parser->correct_variables_score),
@@ -5533,10 +5555,10 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
          */
         if (var->expression.vtype == TYPE_ARRAY) {
             char name[1024];
-            snprintf(name, sizeof(name), "%s##SET", var->name);
+            util_snprintf(name, sizeof(name), "%s##SET", var->name);
             if (!parser_create_array_setter(parser, var, name))
                 goto cleanup;
-            snprintf(name, sizeof(name), "%s##GET", var->name);
+            util_snprintf(name, sizeof(name), "%s##GET", var->name);
             if (!parser_create_array_getter(parser, var, var->expression.next, name))
                 goto cleanup;
         }
@@ -5554,14 +5576,14 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
                 goto cleanup;
             }
 
-            snprintf(name, sizeof(name), "%s##SETF", var->name);
+            util_snprintf(name, sizeof(name), "%s##SETF", var->name);
             if (!parser_create_array_field_setter(parser, array, name))
                 goto cleanup;
 
             telem = ast_type_copy(ast_ctx(var), array->expression.next);
             tfield = ast_value_new(ast_ctx(var), "<.type>", TYPE_FIELD);
             tfield->expression.next = telem;
-            snprintf(name, sizeof(name), "%s##GETFP", var->name);
+            util_snprintf(name, sizeof(name), "%s##GETFP", var->name);
             if (!parser_create_array_getter(parser, array, (ast_expression*)tfield, name)) {
                 ast_delete(tfield);
                 goto cleanup;