Values no longer appear as external variable numbers
authorRick van Rein <rick@openfortress.nl>
Fri, 19 Oct 2018 14:33:53 +0000 (14:33 +0000)
committervanrein <rick@openfortress.nl>
Fri, 19 Oct 2018 17:29:09 +0000 (19:29 +0200)
VARKIND_VARIABLE for the generator's set (var_x) and not (?003)
VARKIND_CONSTANT of VARTP_INTEGER, _FLOAT, _STRING, _BLOB map to SQL

src/pulley/pulleyscript/parserpp.cpp
src/pulley/pulleyscript/pulley.lex
src/pulley/pulleyscript/pulley.yacc
src/pulley/pulleyscript/squeal.c
src/pulley/pulleyscript/variable.c
src/pulley/pulleyscript/variable.h

index bcf7bd0..a044e61 100644 (file)
@@ -244,7 +244,7 @@ public:
                        {
                                struct var_value* value = var_share_value(m_prs.vartab, binding);
                                std::vector<std::string> expressions;
-                               decode_parameter_binding(m_prs.vartab, value->typed_blob.str, value->typed_blob.len, expressions);
+                               decode_parameter_binding(m_prs.vartab, value->typed_blob.ptr, value->typed_blob.len, expressions);
 
                                for (auto s : expressions)
                                {
@@ -496,7 +496,7 @@ std::forward_list< std::string > SteamWorks::PulleyScript::Parser::Private::find
                auto bound_varnums = variables_for_generator(i);  // Variables on the right-hand side of binding
                m_variables_per_generator.emplace_back(bound_varnums.size());  // New vector of names
 
-               explain_binding(m_prs.vartab, value->typed_blob.str, value->typed_blob.len, filterexp, bound_varnums, m_variables_per_generator.back());
+               explain_binding(m_prs.vartab, value->typed_blob.ptr, value->typed_blob.len, filterexp, bound_varnums, m_variables_per_generator.back());
        }
 
        for (gennum_t g=0; g<count; g++) {
@@ -641,7 +641,7 @@ void SteamWorks::PulleyScript::Parser::Private::find_backends()
                {
                        struct var_value* value = var_share_value(m_prs.vartab, binding);
                        std::vector<std::string> expressions;
-                       decode_parameter_binding(m_prs.vartab, value->typed_blob.str, value->typed_blob.len, expressions);
+                       decode_parameter_binding(m_prs.vartab, value->typed_blob.ptr, value->typed_blob.len, expressions);
                        m_backends.emplace_front(name, expressions);
 
                        varnum_t* var_list = nullptr;
index 87fd20a..cbc4d3c 100644 (file)
@@ -223,6 +223,7 @@ printf ("Funny semicolon in %s ignored\n", yytext);
                                if (*here == '\\') {
                                        here++;
                                        // Continue with the next, even a quote
+                                       //TODO// '\n' -> 'n' :-)
                                }
                                *copy++ = *here++;
                        }
@@ -241,7 +242,7 @@ printf ("Funny semicolon in %s ignored\n", yytext);
                                yy_fatal_error ("Out of memory replicating hexbyte string", prs);
                        }
                        val.type = VARTP_BLOB;
-                       val.typed_blob.str = copy;
+                       val.typed_blob.ptr = copy;
                        val.typed_blob.len = 0;
                        hex = 1;
                        while (*here) {
@@ -264,7 +265,7 @@ printf ("Funny semicolon in %s ignored\n", yytext);
                        }
                        yylval->varnum = var_have (prs->vartab, yytext, VARKIND_CONSTANT);
                        var_set_value (prs->vartab, yylval->varnum, &val);
-                       hash_token_blob (hbuf, BLOB, val.typed_blob.str, val.typed_blob.len);
+                       hash_token_blob (hbuf, BLOB, val.typed_blob.ptr, val.typed_blob.len);
                        return BLOB;
                }
 
index 0d0da2c..f796772 100644 (file)
@@ -185,9 +185,9 @@ varnum_t _store_binding (struct parser *prs, char *bndname, struct var_value *va
        varnum_t binding = var_have (prs->vartab, bndname, VARKIND_BINDING);
        varval->type = VARTP_BLOB;
        varval->typed_blob.len = sizeof (prs->action) - prs->action_sp;
-       varval->typed_blob.str = malloc (varval->typed_blob.len);
-       assert (varval->typed_blob.str != NULL);
-       memcpy (varval->typed_blob.str, &prs->action [prs->action_sp],
+       varval->typed_blob.ptr = malloc (varval->typed_blob.len);
+       assert (varval->typed_blob.ptr != NULL);
+       memcpy (varval->typed_blob.ptr, &prs->action [prs->action_sp],
                        varval->typed_blob.len);
        var_set_value (prs->vartab, binding, varval);
 
@@ -210,7 +210,7 @@ void _flushO (struct parser *prs, hash_t linehash, gennum_t g) {
        binding = _store_binding (prs, bndname, &varval);
 //DEBUG//
 printf ("Binding %s V%d G%d created: >>> ", bndname, binding, g);
-ptr = varval.typed_blob.str;
+ptr = varval.typed_blob.ptr;
 len = varval.typed_blob.len;
 while (len-- > 0) {
        printf ("%02x ", *ptr++);
index 7e3fb7c..bfeb6f6 100644 (file)
@@ -221,30 +221,35 @@ static void sqlbuf_exchg (struct sqlbuf *wbuf, bool get_not_set) {
        }
 }
 
-
-/* Given a (char **) for an output buffer, write text to it, possibly adding to
- * its size to make this possible.
+/* Given a (char **) for an output buffer, write a (ptr,len) blob to it,
+ * possibly adding to its size to make this possible.
  */
-static void sqlbuf_write (struct sqlbuf *buf, const char *addend) {
+static void sqlbuf_writeblob (struct sqlbuf *buf, const char *blob, int len) {
        char *buf2;
        int   siz2;
-       int len = strlen (addend);
        assert (buf->ofs <= buf->siz);
        if (buf->siz < buf->ofs + len) {
                siz2 = buf->siz + (buf->siz >> 2) + len;
                buf2 = realloc (buf->buf, siz2);
                if (buf2 == NULL) {
-                       ERROR("Out of memory while writing \"%s\" to squeal buffer\n", addend);
+                       ERROR("Out of memory while writing %d bytes to squeal buffer\n", len);
                        exit (1);
                }
                memset(buf2 + buf->ofs, 0, siz2 - buf->ofs);
                buf->buf = buf2;
                buf->siz = siz2;
        }
-       memcpy (buf->buf + buf->ofs, addend, len);
+       memcpy (buf->buf + buf->ofs, blob, len);
        buf->ofs += len;
 }
 
+/* Given a (char **) for an output buffer, write text to it, possibly adding to
+ * its size to make this possible.
+ */
+static void sqlbuf_write (struct sqlbuf *buf, const char *addend) {
+       sqlbuf_writeblob (buf, addend, strlen (addend));
+}
+
 
 /* Run an SQL statement from the given sqlbuf string.  Reset the buffer when done.
  * Return 0 on success, 1 on failure.
@@ -624,6 +629,101 @@ void squeal_delete_forks(struct squeal *squeal, gennum_t gennum, const char *ent
 /********** BACKEND STRUCTURE CREATION **********/
 
 
+/* Produce the SQLite3 text form of an expression variable depending on its varkind:
+ *  - VARIABLE not in param are inserted in ?003 form
+ *  - VARIABLE in param such as x, y are inserted with a var_ prefix
+ *  - CONSTANT INTEGER and FLOAT are printed by C
+ *  - CONSTANT STRING is printed with single quotes; internal single quote is doubled
+ *  - CONSTANT BLOB is printed as X'(hexdump)'
+ *  - ATTRTYPE, PARAMETER, DRIVERNAME, BINDING should not occur in expressions
+ */
+void squeal_produce_expression_variable (struct sqlbuf *sql, struct vartab *vartab, bitset_t *params, varnum_t vn) {
+       varkind_t vk = var_get_kind (vartab, vn);
+       struct var_value *vv = var_share_value (vartab, vn);
+       char linebuf [90];
+       char varid [20];
+       int i;
+       char *ptr;
+       switch (vk) {
+       //
+       // Plain variables; may be parameters that are produced by the current generator or not
+       case VARKIND_VARIABLE:
+               if (!bitset_test (params, vn)) {
+                       /* No need to prefix var_ or anything, separate id space */
+                       snprintf (varid, sizeof (varid)-1, "?%03d", PARAM_OFS + vn);
+                       sqlbuf_write (sql, varid);
+               } else {
+                       sqlbuf_write (sql, "var_");
+                       sqlbuf_write (sql, var_get_name (vartab, vn));
+               }
+               break;
+       //
+       // Constants; forms are INTEGER, FLOAT, STRING, BLOB
+       case VARKIND_CONSTANT:
+               switch (vv->type) {
+               case VARTP_INTEGER:
+                       snprintf (linebuf, sizeof (linebuf)-1, "%d", vv->typed_integer);
+                       sqlbuf_write (sql, linebuf);
+                       break;
+               case VARTP_FLOAT:
+                       snprintf (linebuf, sizeof (linebuf)-1, "%f", vv->typed_float);
+                       sqlbuf_write (sql, linebuf);
+                       break;
+               case VARTP_STRING:
+                       // Format is 'How''s your mood today?'
+                       // Input is NUL-terminated, and flex already
+                       // took care of input quoting and escaping
+                       sqlbuf_write (sql, vv->typed_string);
+                       sqlbuf_write (sql, "'");
+                       ptr = vv->typed_string;
+                       while (1) {
+                               i = 0;
+                               while (ptr [i] && (ptr [i] != '\'')) {
+                                       i++;
+                               }
+                               sqlbuf_writeblob (sql, ptr, i);
+                               if (ptr [i] == '\'') {
+                                       sqlbuf_write (sql, "''");
+                                       ptr += i + 1;
+                               } else {
+                                       // ptr [i] == '\0'
+                                       break;
+                               }
+                       }
+                       sqlbuf_write (sql, "'");
+                       break;
+               case VARTP_BLOB:
+                       // Format is X'0123456789abcdef'
+                       sqlbuf_write (sql, "X'");
+                       ptr = vv->typed_blob.ptr;
+                       i   = vv->typed_blob.len;
+                       while (i-- > 0) {
+                               sprintf (linebuf, "%02X", *ptr++);
+                               sqlbuf_write (sql, linebuf);
+                       }
+                       sqlbuf_write (sql, "'");
+                       break;
+               default:
+                       fprintf (stderr, "Unsupported variable type (%d)\n", vv->type);
+                       exit (1);
+               }
+               break;
+       //
+       // Misplaced ATTRTYPE, PARAMETER, DRIVERNAME, BINDING
+       case VARKIND_ATTRTYPE:
+       case VARKIND_PARAMETER:
+       case VARKIND_DRIVERNAME:
+       case VARKIND_BINDING:
+               fprintf (stderr, "Unwanted variable kind in expression (%d)\n", vk);
+               exit (1);
+       //
+       // We should never run into unknown variable kinds
+       default:
+               fprintf (stderr, "Unknown variable kind (%d)\n", vk);
+               exit (1);
+       }
+}
+
 /* TODO: Mockup code to produce expressions for driver output generation
  */
 void squeal_produce_expression (struct sqlbuf *sql, struct vartab *vartab, bitset_t *params, int *exp, size_t explen) {
@@ -631,7 +731,6 @@ void squeal_produce_expression (struct sqlbuf *sql, struct vartab *vartab, bitse
        int *subexp;
        size_t subexplen;
        varnum_t v1, v2;
-       char varid [20];
        cnd_parse_operation (exp, explen, &operator, &operands, &subexp, &subexplen);
        switch (operator) {
        case CND_TRUE:
@@ -667,13 +766,7 @@ void squeal_produce_expression (struct sqlbuf *sql, struct vartab *vartab, bitse
        case CND_GE:
                v2 = cnd_parse_variable (&subexp, &subexplen);
                v1 = cnd_parse_variable (&subexp, &subexplen);
-               if (!bitset_test (params, v1)) {
-                       snprintf (varid, sizeof (varid)-1, "?%03d", PARAM_OFS + v1);
-                       sqlbuf_write (sql, varid);
-               } else {
-                       sqlbuf_write (sql, "var_");
-                       sqlbuf_write (sql, var_get_name (vartab, v1));
-               }
+               squeal_produce_expression_variable (sql, vartab, params, v1);
                sqlbuf_write (sql,
                        (operator == CND_EQ)? " = ":
                        (operator == CND_NE)? " <> ":
@@ -682,14 +775,7 @@ void squeal_produce_expression (struct sqlbuf *sql, struct vartab *vartab, bitse
                        (operator == CND_LE)? " <= ":
                        (operator == CND_GE)? " >= ":
                                              " ERROR ");
-               if (!bitset_test (params, v2)) {
-                       /* No need to prefix var_ or anything, separate id space */
-                       snprintf (varid, sizeof (varid)-1, "?%03d", PARAM_OFS + v2);
-                       sqlbuf_write (sql, varid);
-               } else {
-                       sqlbuf_write (sql, "var_");
-                       sqlbuf_write (sql, var_get_name (vartab, v2));
-               }
+               squeal_produce_expression_variable (sql, vartab, params, v2);
                break;
        default:
                ERROR("Unknown operation code %d with %d operands\n", operator, operands);
index 5e2b435..bb592e2 100644 (file)
@@ -73,8 +73,8 @@ static void var_cleanup (struct vartab *tab, varnum_t varnum) {
        }
        if (var->value.type == VARTP_BLOB)
        {
-               free(var->value.typed_blob.str);
-               var->value.typed_blob.str = NULL;
+               free(var->value.typed_blob.ptr);
+               var->value.typed_blob.ptr = NULL;
                var->value.typed_blob.len = 0;
        }
 }
@@ -369,7 +369,7 @@ void var_set_value (struct vartab *tab, varnum_t varnum, struct var_value *val)
                free (dst->typed_string);
                break;
        case VARTP_BLOB:
-               free (dst->typed_blob.str);
+               free (dst->typed_blob.ptr);
                break;
        case VARTP_ATTROPTS:
                here = dst->typed_attropts;
index 1067cba..673ff45 100644 (file)
@@ -62,7 +62,7 @@ struct var_value {
                float union_float;
                char *union_string;
                struct {
-                       uint8_t *str;
+                       uint8_t *ptr;
                        uint32_t len;
                } union_blob;
                struct list_attropt *union_attropts;