assign macro expansion now works
authorThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Mon, 12 May 2025 08:53:43 +0000 (01:53 -0700)
committerThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Mon, 12 May 2025 08:53:43 +0000 (01:53 -0700)
script_gcc_min-12🖉/directives.cc
script_gcc_min-12🖉/macro.cc

index c84ce05..de176d5 100644 (file)
@@ -2805,60 +2805,6 @@ _cpp_bracket_include(cpp_reader *pfile)
 // RT extensions 
 //--------------------------------------------------------------------------------
 
-const char *
-cpp_token_as_text(const cpp_token *token)
-{
-  static char buffer[128];
-
-  switch (token->type)
-    {
-    case CPP_NAME:
-      snprintf(buffer, sizeof(buffer), "identifier '%s'",
-               NODE_NAME(token->val.node.node));
-      break;
-
-    case CPP_NUMBER:
-    case CPP_STRING:
-    case CPP_CHAR:
-    case CPP_HEADER_NAME:
-      snprintf(buffer, sizeof(buffer), "'%.*s'",
-               token->val.str.len,
-               token->val.str.text);
-      break;
-
-    case CPP_EOF:
-      return "<EOF>";
-    case CPP_OTHER:
-      return "<OTHER>";
-    case CPP_OPEN_PAREN:
-      return "'('";
-    case CPP_CLOSE_PAREN:
-      return "')'";
-    case CPP_COMMA:
-      return "','";
-    case CPP_SEMICOLON:
-      return "';'";
-    case CPP_PLUS:
-      return "'+'";
-    case CPP_MINUS:
-      return "'-'";
-    case CPP_MULT:
-      return "'*'";
-    case CPP_DIV:
-      return "'/'";
-    case CPP_MOD:
-      return "'%'";
-    // ... handle other symbolic types as needed ...
-
-    default:
-      snprintf(buffer, sizeof(buffer), "<unknown type %d>", token->type);
-      break;
-    }
-
-  return buffer;
-}
-
-#if 0
 const char *
 cpp_token_as_text (const cpp_token *token)
 {
@@ -2902,7 +2848,28 @@ cpp_token_as_text (const cpp_token *token)
       return "'/'";
     case CPP_MOD:
       return "'%'";
-    // Add more token types as needed...
+    case CPP_MACRO_ARG:
+      snprintf(buffer, sizeof(buffer), "macro_param '$%s'",
+         NODE_NAME(token->val.macro_arg.spelling));
+      break;
+
+    case CPP_PADDING: return "<PADDING>";
+    case CPP_COMMENT: return "<COMMENT>";
+    case CPP_HASH: return "'#'";
+    case CPP_PASTE: return "'##'";
+    case CPP_ELLIPSIS: return "'...'";
+    case CPP_COLON: return "':'";
+    case CPP_OPEN_SQUARE: return "'['";
+    case CPP_CLOSE_SQUARE: return "']'";
+    case CPP_OPEN_BRACE: return "'{'";
+    case CPP_CLOSE_BRACE: return "'}'";
+    case CPP_DOT: return "'.'";
+    case CPP_DEREF: return "'->'";
+    case CPP_SCOPE: return "'::'";
+    case CPP_DOT_STAR: return "'.*'";
+    case CPP_DEREF_STAR: return "'->*'";
+    case CPP_PRAGMA: return "<_Pragma>";
+    case CPP_KEYWORD: return "<keyword>";
 
     default:
       snprintf(buffer, sizeof(buffer), "<unknown type %d>", token->type);
@@ -2945,7 +2912,6 @@ cpp_token_as_text (const cpp_token *token)
 
   return buffer;
 }
-#endif
 
 void print_token_list(const cpp_token *tokens ,size_t count){
   for (size_t i = 0; i < count; ++i)
index cfd021c..c82fec1 100644 (file)
@@ -4224,47 +4224,89 @@ static enum collect_body_tokens_status collect_body_tokens_1(
   bool following_paste_op = false;
   unsigned int num_extra_tokens = 0;
   int paren_depth = 1; 
-  cpp_token *token;
+  cpp_token *lex_token;
+  const cpp_token *token;
+  location_t *src_loc;
 
   for (vaopt_state vaopt_tracker (pfile, macro->variadic, NULL);; )
     {
-      // gets a token
-      if(!expand_tokens){
-        // first parses token onto `macro->exp.tokens[macro->count]`
+      // get a token
+      if(expand_tokens){
+        token = cpp_get_token_1 (pfile, src_loc);
+        fprintf( stderr, "token %s\n", cpp_token_as_text(token) );
+        macro = (cpp_macro *)_cpp_reserve_room(
+          pfile,
+          sizeof(cpp_macro) - sizeof(cpp_token) + macro->count * sizeof(cpp_token),
+          sizeof(cpp_token)
+        );
+        macro->exp.tokens[macro->count] = *token;
+        macro->count++;
+
+      }else{
+        // first parses lex_token onto `macro->exp.tokens[macro->count]`
         // then pulls the token off of `macro->exp.tokens[macro->count]`
         // reassigns macro due to possible macro->exp.tokens buffer expansion
         macro = lex_expansion_token(pfile, macro);
-        token = &macro->exp.tokens[macro->count++];
-      }else{
+        lex_token = &macro->exp.tokens[macro->count++];
+        fprintf( stderr, "lex_token %s\n", cpp_token_as_text(lex_token) );
+
+        // recognize macro args, give them type CPP_MACRO_ARG
+        if (macro->count > 1 && lex_token[-1].type == CPP_HASH && macro->fun_like)
+          {
+            if (lex_token->type == CPP_MACRO_ARG
+                || (macro->variadic
+                    && lex_token->type == CPP_NAME
+                    && lex_token->val.node.node == pfile->spec_nodes.n__VA_OPT__))
+              {
+                if (lex_token->flags & PREV_WHITE)
+                  lex_token->flags |= SP_PREV_WHITE;
+                if (lex_token[-1].flags & DIGRAPH)
+                  lex_token->flags |= SP_DIGRAPH;
+                lex_token->flags &= ~PREV_WHITE;
+                lex_token->flags |= STRINGIFY_ARG;
+                lex_token->flags |= lex_token[-1].flags & PREV_WHITE;
+                lex_token[-1] = lex_token[0];
+                macro->count--;
+              }
+            else if (CPP_OPTION (pfile, lang) != CLK_ASM)
+              {
+                cpp_error(pfile, CPP_DL_ERROR,
+                          "'#' is not followed by a macro parameter");
+                return CBT_ERR_HASH_NOT_FOLLOWED_BY_ARG;
+              }
+          }
 
+        if (lex_token->type == CPP_PASTE)
+          {
+            if (macro->count == 1)
+              {
+                cpp_error(pfile, CPP_DL_ERROR, paste_op_error_msg);
+                return CBT_ERR_PASTE_AT_END; // the font end of the buffer
+              }
+
+            if (following_paste_op)
+              {
+                num_extra_tokens++;
+                lex_token->val.token_no = macro->count - 1;
+              }
+            else
+              {
+                --macro->count;
+                lex_token[-1].flags |= PASTE_LEFT;
+                if (lex_token->flags & DIGRAPH)
+                  lex_token[-1].flags |= SP_DIGRAPH;
+                if (lex_token->flags & PREV_WHITE)
+                  lex_token[-1].flags |= SP_PREV_WHITE;
+              }
+            following_paste_op = true;
+          }
+        else{
+          following_paste_op = false;
+        }
+
+        token = lex_token;
       }
-      fprintf( stderr, "top of loop, read token %s\n", cpp_token_as_text(token) );
 
-      // recognize macro args, give them type CPP_MACRO_ARG
-      if (macro->count > 1 && token[-1].type == CPP_HASH && macro->fun_like)
-        {
-          if (token->type == CPP_MACRO_ARG
-              || (macro->variadic
-                  && token->type == CPP_NAME
-                  && token->val.node.node == pfile->spec_nodes.n__VA_OPT__))
-            {
-              if (token->flags & PREV_WHITE)
-                token->flags |= SP_PREV_WHITE;
-              if (token[-1].flags & DIGRAPH)
-                token->flags |= SP_DIGRAPH;
-              token->flags &= ~PREV_WHITE;
-              token->flags |= STRINGIFY_ARG;
-              token->flags |= token[-1].flags & PREV_WHITE;
-              token[-1] = token[0];
-              macro->count--;
-            }
-          else if (CPP_OPTION (pfile, lang) != CLK_ASM)
-            {
-              cpp_error(pfile, CPP_DL_ERROR,
-                        "'#' is not followed by a macro parameter");
-              return CBT_ERR_HASH_NOT_FOLLOWED_BY_ARG;
-            }
-        }
 
       // parentheses matching overhead
       if(paren_matching){
@@ -4302,34 +4344,6 @@ static enum collect_body_tokens_status collect_body_tokens_1(
         return CBT_OK;
       }
 
-      if (token->type == CPP_PASTE)
-        {
-          if (macro->count == 1)
-            {
-              cpp_error(pfile, CPP_DL_ERROR, paste_op_error_msg);
-              return CBT_ERR_PASTE_AT_END; // the font end of the buffer
-            }
-
-          if (following_paste_op)
-            {
-              num_extra_tokens++;
-              token->val.token_no = macro->count - 1;
-            }
-          else
-            {
-              --macro->count;
-              token[-1].flags |= PASTE_LEFT;
-              if (token->flags & DIGRAPH)
-                token[-1].flags |= SP_DIGRAPH;
-              if (token->flags & PREV_WHITE)
-                token[-1].flags |= SP_PREV_WHITE;
-            }
-          following_paste_op = true;
-        }
-      else{
-        following_paste_op = false;
-      }
-
       if (vaopt_tracker.update(token) == vaopt_state::ERROR){
         return CBT_ERR_VAOPT_STATE_INVALID;
       }
@@ -4355,7 +4369,6 @@ collect_body_tokens(
   int saved_keep_tokens = pfile->keep_tokens;
   int saved_in_directive = pfile->state.in_directive;
   cpp_token *token;
-  location_t src_loc;
 
   if (paren_matching)
     {
@@ -4415,9 +4428,8 @@ collect_body_tokens(
 
   The cpp_macro struct is defined in cpplib.h:  `struct GTY(()) cpp_macro {` it has a flexible array field in a union as a last member: cpp_token tokens[1];
 */
-static cpp_macro *
-create_iso_RT_macro (cpp_reader *pfile)
-{
+static cpp_macro *create_iso_RT_macro (cpp_reader *pfile){
+
   const char *paste_op_error_msg =
     N_("'##' cannot appear at either end of a macro expansion");
   unsigned int num_extra_tokens = 0;
@@ -4430,7 +4442,8 @@ create_iso_RT_macro (cpp_reader *pfile)
   /*
     After these six lines of code, the next token, hopefully being '(', will be in the variable 'token'.
 
-    Neither `first` nor `saved_cur_token` are referred to again, and I don't really understand the dance here. Apparently we need to provide pfile->cur_token with a buffer.
+    _cpp_lex_direct() is going to clobber  pfile->cur_token with the token pointer, so
+    it is saved then restored.
   */
     cpp_token first;
     cpp_token *saved_cur_token = pfile->cur_token;
@@ -4629,167 +4642,66 @@ _cpp_create_macro(cpp_reader *pfile, cpp_hashnode *node){
 // `#assign` directive
 //    called from directives.cc::do_assign()
 
-/* 
-  Given the cpp_reader and an assignment argument in the form of a macro.
-  Returns ... through the `result` argument.
-  Returns ...
-
-  Assign name_expr and body_expr arguments are each placed into a
-  macro instance, then are sent here to be expanded.
-
-  Push the context of a macro onto the context stack.  If we can
-  successfully expand the macro, we push a context containing its
-  yet-to-be-rescanned replacement list and return one.  LOCATION is
-  the location of the expansion point of the macro.
-
-  derived from enter_macro_context()
-*/
-static int
-enter_macro_context_RT_assign(
-  cpp_reader *pfile
-  ,cpp_macro *macro
-  //  ,const cpp_token *result  // not needed for assign
-  // ,location_t location // suprising, but all references to it are gone
-){
-  /* The presence of a macro invalidates a file's controlling macro.  */
-  pfile->mi_valid = false;
-  pfile->state.angled_headers = false;
-  pfile->about_to_expand_macro_p = true;
-
-      // not expanding a pragma
-
-      // Disable the macro within its expansion. 
-      // assign has no node at this point
-      // node->flags |= NODE_DISABLED;
-
-      // not lazy, doing it now
-      // no need to notify of macro use
-      // macro->paramc is indeed zero when we get here (assign has no parameters)
-
-      unsigned tokens_count = macro_real_token_count (macro);
-
-      // no need to check for the track_macro_expansion option
-
-      //_cpp_push_token_context (pfile, node, macro->exp.tokens, tokens_count);
-      // _cpp_push_token_context allows for a NULL node
-      _cpp_push_token_context (pfile, NULL, macro->exp.tokens, tokens_count);
-                                 
-      num_macro_tokens_counter += tokens_count;
-
-      // not inside of a pragma (inside of a #assign)
-
-      pfile->about_to_expand_macro_p = false;
-      return 1;
-
-      // removed code that is unreachable under these assumptions
-}
-
-static cpp_macro *
-collect_and_expand_macro (cpp_reader *pfile)
-{
-  // Step 1: Collect tokens
-  cpp_macro *unexpanded = _cpp_new_macro(
-    pfile,
-    cmk_macro,
-    _cpp_reserve_room(pfile, 0, sizeof(cpp_macro))
-  );
-
-  unexpanded->variadic = false;
-  unexpanded->paramc = 0;
-  unexpanded->parm.params = NULL;
-  unexpanded->fun_like = false;
-
-  const char *paste_op_error_msg =
-    N_("'##' cannot appear at either end of a macro expansion");
-
-  unsigned int num_extra_tokens = 0;
-  if(
-    !collect_body_tokens(
-       pfile
-       ,unexpanded
-       ,&num_extra_tokens
-       ,paste_op_error_msg
-       ,true // parenthesis delineated
-       ,false // expand tokens
-     )
-  )
-    return NULL;
-
-  if (unexpanded->count == 0)
-    return NULL;
-
-  fprintf(stderr, "assign directive expr before expansion:\n");
-  print_token_list(unexpanded->exp.tokens, unexpanded->count);
-
-  // Step 2: Commit unexpanded before allocating again
-  unexpanded = (cpp_macro *) _cpp_commit_buff(
-    pfile,
-    sizeof(cpp_macro) - sizeof(cpp_token)
-      + sizeof(cpp_token) * unexpanded->count
-  );
-
-  // Step 3: Expand
-  // enter_macro_context_RT_assign(pfile, unexpanded);
-
-  cpp_macro *expanded = _cpp_new_macro(
-    pfile,
-    cmk_macro,
-    _cpp_reserve_room(pfile, 0, sizeof(cpp_macro))
-  );
-
-  expanded->variadic = false;
-  expanded->paramc = 0;
-  expanded->parm.params = NULL;
-  expanded->fun_like = false;
-
-  size_t count = 0;
-  while (1)
-    {
-      const cpp_token *tok;
-      location_t loc;
-
-      tok = cpp_get_token_1(pfile, &loc);
-      if (tok->type == CPP_EOF)
-        break;
-
-      expanded->exp.tokens[count] = *tok;
-      expanded->exp.tokens[count].src_loc = loc;
-      count++;
-    }
-
-  expanded->count = count;
-
-  fprintf(stderr, "assign directive expr after expansion:\n");
-  print_token_list(expanded->exp.tokens, count);
-
-  // Step 4: Commit and return
-  expanded = (cpp_macro *) _cpp_commit_buff(
-    pfile,
-    sizeof(cpp_macro) - sizeof(cpp_token) + sizeof(cpp_token) * count
-  );
-
-  return expanded;
-}
-
-
 bool
 _cpp_create_assign(cpp_reader *pfile){
 
-  /* parse the name expr
+  /* name macro
 
-     We first parse the as though a cpp_macro definition to collect the arg list.
-     We then convert the macro arg list to a cpp_arg arg definition, so it can be
-     passed to expand_arg.
   */
-  cpp_macro *name_macro = collect_and_expand_macro(pfile);
-  // -if `name_macro` did not reduced to a name, issue error and bailout
-  // -if there is a macro in the symbol table with the given name, remove it
-  //  (if we can check if it was put there by assign first, that would be better)
+    cpp_macro *name_macro = _cpp_new_macro(
+      pfile
+      ,cmk_macro
+      ,_cpp_reserve_room( pfile, 0, sizeof(cpp_macro) ) 
+    );
+    name_macro->variadic = false;
+    name_macro->paramc = 0;
+    name_macro->parm.params = NULL;
+    name_macro->fun_like = false;
+
+    unsigned int num_extra_tokens = 0;
+    const char *paste_op_error_msg =
+      N_("'##' cannot appear at either end of a macro expansion");
+
+    collect_body_tokens(
+      pfile 
+      ,name_macro 
+      ,&num_extra_tokens 
+      ,paste_op_error_msg 
+      ,true // parenthesis delineated
+      ,true // tokens are expanded as part of a macro definition
+    );
+    fprintf(stderr,"name_macro->count %d\n" ,name_macro->count);
+    fprintf(stderr,"assign directive name expr:\n");
+    print_token_list(name_macro->exp.tokens ,name_macro->count);
+
+  /* check name and keep a copy
+
+   */
 
   /* parse the body macro
+
   */
-  cpp_macro *body_macro = collect_and_expand_macro(pfile);
-  // enter the macro into the symbol table using the aforementioned name
+    cpp_macro *body_macro = _cpp_new_macro(
+      pfile
+      ,cmk_macro
+      ,_cpp_reserve_room( pfile, 0, sizeof(cpp_macro) ) 
+    );
+    body_macro->variadic = false;
+    body_macro->paramc = 0;
+    body_macro->parm.params = NULL;
+    body_macro->fun_like = false;
+
+    collect_body_tokens(
+      pfile 
+      ,body_macro 
+      ,&num_extra_tokens 
+      ,paste_op_error_msg 
+      ,true // parenthesis delineated
+      ,false // tokens are not expanded as part of a macro definition
+    );
+    fprintf(stderr,"assign directive body expr:\n");
+    print_token_list(body_macro->exp.tokens ,body_macro->count);
+
 
   return true;
 }