[nasm:master] preproc: implement %str() and %strcat() functions

nasm-bot for H. Peter Anvin hpa at zytor.com
Fri Nov 11 19:04:05 PST 2022


Commit-ID:  57fbd34d9ff35a9b34873e896b0983d63a13ee32
Gitweb:     http://repo.or.cz/w/nasm.git?a=commitdiff;h=57fbd34d9ff35a9b34873e896b0983d63a13ee32
Author:     H. Peter Anvin <hpa at zytor.com>
AuthorDate: Fri, 11 Nov 2022 18:18:04 -0800
Committer:  H. Peter Anvin <hpa at zytor.com>
CommitDate: Fri, 11 Nov 2022 18:18:04 -0800

preproc: implement %str() and %strcat() functions

Add function equivalents of the %defstr and %strcat directives.

Signed-off-by: H. Peter Anvin <hpa at zytor.com>


---
 asm/preproc.c | 87 ++++++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 57 insertions(+), 30 deletions(-)

diff --git a/asm/preproc.c b/asm/preproc.c
index f3e4511f..ea18c270 100644
--- a/asm/preproc.c
+++ b/asm/preproc.c
@@ -3567,6 +3567,47 @@ static void assign_smacro(const char *mname, bool casesense,
     }
 }
 
+/*
+ * Implement string concatenation as used by the %strcat directive
+ * and function.
+ */
+static Token *pp_strcat(Token *tline, const char *dname)
+{
+
+    size_t len;
+    Token *t;
+    char *q, *qbuf;
+
+    len = 0;
+    list_for_each(t, tline) {
+        switch (t->type) {
+        case TOKEN_WHITESPACE:
+        case TOKEN_COMMA:
+            break;
+        case TOKEN_STR:
+            unquote_token(t);
+            len += t->len;
+            break;
+        default:
+            nasm_nonfatal("non-string passed to `%s': %s", dname,
+                          tok_text(t));
+            free_tlist(tline);
+            return NULL;
+        }
+    }
+
+    q = qbuf = nasm_malloc(len+1);
+    list_for_each(t, tline) {
+        if (t->type == TOKEN_INTERNAL_STR)
+            q = mempcpy(q, tok_text(t), t->len);
+    }
+    *q = '\0';
+
+    return make_tok_qstr_len(NULL, qbuf, len);
+    nasm_free(qbuf);
+    return t;
+}
+
 /**
  * find and process preprocessor directive in passed line
  * Find out if a line contains a preprocessor directive, and deal
@@ -3588,7 +3629,7 @@ static int do_directive(Token *tline, Token **output)
     bool casesense;
     int offset;
     const char *p;
-    char *q, *qbuf;
+    char *q;
     const char *found_path;
     const char *mname;
     struct ppscan pps;
@@ -3601,7 +3642,6 @@ static int do_directive(Token *tline, Token **output)
     struct tokenval tokval;
     expr *evalresult;
     int64_t count;
-    size_t len;
     errflags severity;
     const char *dname;          /* Name of directive, for messages */
 
@@ -4717,38 +4757,12 @@ issue_error:
         tline = expand_smacro(tline->next);
         last->next = NULL;
 
-        len = 0;
-        list_for_each(t, tline) {
-            switch (t->type) {
-            case TOKEN_WHITESPACE:
-            case TOKEN_COMMA:
-                break;
-            case TOKEN_STR:
-		unquote_token(t);
-                len += t->len;
-                break;
-            default:
-                nasm_nonfatal("non-string passed to `%s': %s", dname,
-			      tok_text(t));
-                free_tlist(tline);
-                goto done;
-            }
-        }
-
-        q = qbuf = nasm_malloc(len+1);
-        list_for_each(t, tline) {
-            if (t->type == TOKEN_INTERNAL_STR)
-                q = mempcpy(q, tok_text(t), t->len);
-        }
-        *q = '\0';
-
+        macro_start = pp_strcat(tline, dname);
         /*
          * We now have a macro name, an implicit parameter count of
-         * zero, and a numeric token to use as an expansion. Create
+         * zero, and a string token to use as an expansion. Create
          * and store an SMacro.
          */
-        macro_start = make_tok_qstr_len(NULL, qbuf, len);
-        nasm_free(qbuf);
         define_smacro(mname, casesense, macro_start, NULL);
         free_tlist(tline);
         break;
@@ -6838,6 +6852,9 @@ stdmac_is(const SMacro *s, Token **params, int nparams)
 /*
  * Join all expanded macro arguments with commas, e.g. %eval().
  * Remember that this needs to output the tokens in reverse order.
+ *
+ * This can also be used when only single argument is already ready
+ * to be emitted, e.g. %str().
  */
 static Token *
 stdmac_join(const SMacro *s, Token **params, int nparams)
@@ -6865,6 +6882,14 @@ stdmac_join(const SMacro *s, Token **params, int nparams)
     return tline;
 }
 
+/* %strcat() function */
+static Token *
+stdmac_strcat(const SMacro *s, Token **params, int nparams)
+{
+    nasm_assert(nparams == 1);
+    return pp_strcat(expand_smacro_noreset(params[0]), s->name);
+}
+
 /* Add magic standard macros */
 struct magic_macros {
     const char *name;
@@ -6881,6 +6906,8 @@ static void pp_add_magic_stdmac(void)
         { "__?BITS?__", true, 0, 0, stdmac_bits },
         { "__?PTR?__",  true, 0, 0, stdmac_ptr },
         { "%eval",      false, 1, SPARM_EVAL|SPARM_VARADIC, stdmac_join },
+        { "%str",       false, 1, SPARM_GREEDY|SPARM_STR, stdmac_join },
+        { "%strcat",    false, 1, SPARM_GREEDY, stdmac_strcat },
         { NULL, false, 0, 0, NULL }
     };
     const struct magic_macros *m;


More information about the Nasm-commits mailing list