This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][libcpp] Macros for unique named functions / identifiers


The following patch adds macros CANON_BASE_FILE and CANON_LINE.
CANON_BASE_FILE is analogous to BASE_FILE, but not a string constant
and only preserves characters valid as an identifiers. CANON_LINE
is analogous to the line number and occurance count in the
preprocessed output. Together they can be used to make unique named
identifiers and functions across files.

Because column numbers are not maintained in every case we
use an occurance count shifted into the lower OCCUR_NUM_BITS of
the flat line number to form CANON_LINE.


http://gcc.gnu.org/ml/gcc-patches/2010-04/msg00038.html

Together with the deferred pragma patch proposed earlier, they can be
used for late expansion of nested function definitions.


2010-04-12  Rahul Kharche  <rahul@icerami.com>
	
	* cpplib.h (BT_CANON_BASE_FILE, BT_CANON_SPECLINE): New enums.
	* init.c (builtin_array): Add above to this array and register
new
	macros __CANON_BASE_FILE__, __CANON_LINE__.
	(cpp_create_reader): Initialize bt_canon_line_occur_count to 0.
	* internal.h (bt_canon_line_occur_count): Addeded to cpp_reader.
	* line-map.h (SOURCE_LINE_OCCURANCE, OCCUR_NUM_BITS): New
support
	macros to splice a line number and occurance count.
	* macro.c (make_identifier_name): New function.
	(_cpp_builtin_macro_text): Add case for BT_CANON_SPECLINE and
expand
	like __CANON_BASE_FILE__ using SOURCE_LINE_OCCURANCE. Add case
for
	BT_CANON_BASE_FILE and call make_identifier_name.


	* gcc.dg/cpp/canonmacros.c: New test for correct expansion of
	__CANON_BASE_FILE__ and __CANON_LINE__.


Index: gcc/doc/cpp.texi
===================================================================
--- gcc/doc/cpp.texi	(revision 158225)
+++ gcc/doc/cpp.texi	(working copy)
@@ -2030,6 +2030,22 @@ This macro expands to the name of the ma
 of a C string constant.  This is the source file that was specified
 on the command line of the preprocessor or C compiler.
 
+@item __CANON_BASE_FILE__
+This macro expands to the name of the main input file, like in the case
+of __BASE_FILE__, but not a string constant. Furthermore characters
that
+are invalid for function names (or identifiers) are stripped out
+from expansion. This is useful in creating named functions or
identifiers.
+
+@item __CANON_LINE__
+Similar to __LINE__ this macro expands to a decimal integer
corresponding
+to the line number. But, rather than referring to the line number in
the file
+that mentioned it, this macro expands to the final file it got included
in
+during preprocessing. It is analogous to the line number in the
preprocessed
+file. The line number is held in the higher bits. The lower 8 bits hold
an
+occurance count to make multiple occurances of this macro on a single
line
+unique. Together __CANON_BASE_FILE__ and __CANON_LINE__ can be used to
make a
+unique named function or identifier.
+
 @item __INCLUDE_LEVEL__
 This macro expands to a decimal integer constant that represents the
 depth of nesting in include files.  The value of this macro is
Index: gcc/testsuite/gcc.dg/cpp/canonmacros.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/canonmacros.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cpp/canonmacros.c	(revision 0)
@@ -0,0 +1,19 @@
+/* Verify that preprocessor expands __CANON_BASE_FILE__ and
__CANON_LINE__
+   macros correctly. This test is sensitive to line numbers, and will
need
+   updating if the test files are changed. */
+
+/* { dg-options --save-temps }  */
+
+#include "canonmacros.h"
+
+
+int main ()
+{
+  GENERATE_IDENTIFIER (__LINE__);
+  return 0;
+}
+  
+/* { dg-final { scan-file canonmacros.i "canonmacrosc_4864" } }
+   { dg-final { scan-file canonmacros.i "canonmacrosc_4865" } }
+   { dg-final { scan-file canonmacros.i "canonmacrosc_6658" } }
+   { dg-final { cleanup-saved-temps } } */
Index: gcc/testsuite/gcc.dg/cpp/canonmacros.h
===================================================================
--- gcc/testsuite/gcc.dg/cpp/canonmacros.h	(revision 0)
+++ gcc/testsuite/gcc.dg/cpp/canonmacros.h	(revision 0)
@@ -0,0 +1,16 @@
+
+#define AUTO_IDENTIFIER_NAME_EXPAND(name, line) name##_##line
+
+#define AUTO_IDENTIFIER_NAME(name, line, arg) \
+    AUTO_IDENTIFIER_NAME_EXPAND(name, line) (arg)
+
+#define GENERATE_IDENTIFIER(arg) \
+    AUTO_IDENTIFIER_NAME(__CANON_BASE_FILE__, __CANON_LINE__, arg)
+    
+int foo ()
+{
+  
+  GENERATE_IDENTIFIER (__LINE__); GENERATE_IDENTIFIER (__LINE__);
+  
+  return 0;
+}
Index: libcpp/macro.c
===================================================================
--- libcpp/macro.c	(revision 158225)
+++ libcpp/macro.c	(working copy)
@@ -71,6 +71,9 @@ static bool parse_params (cpp_reader *, 
 static void check_trad_stringification (cpp_reader *, const cpp_macro
*,
 					const cpp_string *);
 
+/* misc text processing functions */
+static void make_identifier_name (const char *, uchar *);
+
 /* Emits a warning if NODE is a macro defined in the main file that
    has not been used.  */
 int
@@ -187,6 +190,27 @@ _cpp_builtin_macro_text (cpp_reader *pfi
 	*buf = '\0';
       }
       break;
+      
+    case BT_CANON_BASE_FILE:
+      {
+	unsigned int len;
+	const char *name;
+	uchar *buf;
+	map = linemap_lookup (pfile->line_table,
pfile->line_table->highest_line);
+
+	while (! MAIN_FILE_P (map))
+	  map = INCLUDED_FROM (pfile->line_table, map);
+
+	name = map->to_file;
+	len = strlen (name);
+	/* Strip out any invalid characters from filename and make a
+	   valid function name. */
+	buf = _cpp_unaligned_alloc (pfile, len * 2 + 1);
+	make_identifier_name (name, buf);
+	result = buf;
+      }
+      break;
+
 
     case BT_INCLUDE_LEVEL:
       /* The line map depth counts the primary source as level 1, but
@@ -206,6 +230,21 @@ _cpp_builtin_macro_text (cpp_reader *pfi
 			    : pfile->cur_token[-1].src_loc);
       break;
 
+    case BT_CANON_SPECLINE:
+      map = &pfile->line_table->maps[pfile->line_table->used-1];
+      
+      while (! MAIN_FILE_P (map))
+        map = INCLUDED_FROM (pfile->line_table, map);
+
+      /* Splice in the occurance count with the line number to make
+         it unique. */
+      number = SOURCE_LINE_OCCURANCE (map,
pfile->cur_token[-1].src_loc,
+				      pfile->bt_canon_line_occur_count);
+      /* Update the free running occurance count. The least significant
+         OCCUR_NUM_BITS will be used. The count will wrap on overflow.
*/
+      pfile->bt_canon_line_occur_count++;
+      break;
+
       /* __STDC__ has the value 1 under normal circumstances.
 	 However, if (a) we are in a system header, (b) the option
 	 stdc_0_in_system_headers is true (set by target config), and
@@ -2108,3 +2147,17 @@ cpp_macro_definition (cpp_reader *pfile,
   *buffer = '\0';
   return pfile->macro_buffer;
 }
+
+static void
+make_identifier_name (const char *name, uchar *buf)
+{
+  char *op = (char *)buf;
+  while (*name != '\0')
+    {
+      if (ISALNUM (*name) || *name == '_')
+	*op++ = *name;
+      
+      name++;
+    }
+  *op = '\0';
+}
Index: libcpp/include/cpplib.h
===================================================================
--- libcpp/include/cpplib.h	(revision 158225)
+++ libcpp/include/cpplib.h	(working copy)
@@ -596,6 +596,8 @@ enum cpp_builtin_type
   BT_DATE,			/* `__DATE__' */
   BT_FILE,			/* `__FILE__' */
   BT_BASE_FILE,			/* `__BASE_FILE__' */
+  BT_CANON_BASE_FILE,		/* `__CANON_BASE_FILE__' */
+  BT_CANON_SPECLINE,		/* `__CANON_LINE__' */
   BT_INCLUDE_LEVEL,		/* `__INCLUDE_LEVEL__' */
   BT_TIME,			/* `__TIME__' */
   BT_STDC,			/* `__STDC__' */
Index: libcpp/include/line-map.h
===================================================================
--- libcpp/include/line-map.h	(revision 158225)
+++ libcpp/include/line-map.h	(working copy)
@@ -155,6 +155,11 @@ extern const struct line_map *linemap_lo
 #define SOURCE_COLUMN(MAP, LOC) \
   (((LOC) - (MAP)->start_location) & ((1 << (MAP)->column_bits) - 1))
 
+#define OCCUR_NUM_BITS	    8
+#define SOURCE_LINE_OCCURANCE(MAP, LOC, OCCUR) \
+    ((((LOC) >> (MAP)->column_bits) << OCCUR_NUM_BITS) \
+     + ((OCCUR) & ((1 << OCCUR_NUM_BITS) - 1)))
+ 
 /* Returns the last source line within a map.  This is the (last) line
    of the #include, or other directive, that caused a map change.  */
 #define LAST_SOURCE_LINE(MAP) \
Index: libcpp/init.c
===================================================================
--- libcpp/init.c	(revision 158225)
+++ libcpp/init.c	(working copy)
@@ -218,6 +218,9 @@ cpp_create_reader (enum c_lang lang, has
 
   /* Initialize table for push_macro/pop_macro.  */
   pfile->pushed_macros = 0;
+  
+  /* Initialize occurance count for BT_CANON_SPECLINE macro. */
+  pfile->bt_canon_line_occur_count = 0;
 
   /* The expression parser stack.  */
   _cpp_expand_op_stack (pfile);
@@ -340,18 +343,20 @@ struct builtin_macro
 #define B(n, t, f)    { DSC(n), t, f }
 static const struct builtin_macro builtin_array[] =
 {
-  B("__TIMESTAMP__",	 BT_TIMESTAMP,     false),
-  B("__TIME__",		 BT_TIME,          false),
-  B("__DATE__",		 BT_DATE,          false),
-  B("__FILE__",		 BT_FILE,          false),
-  B("__BASE_FILE__",	 BT_BASE_FILE,     false),
-  B("__LINE__",		 BT_SPECLINE,      true),
-  B("__INCLUDE_LEVEL__", BT_INCLUDE_LEVEL, true),
-  B("__COUNTER__",	 BT_COUNTER,       true),
+  B("__TIMESTAMP__",	   BT_TIMESTAMP,       false),
+  B("__TIME__",		   BT_TIME,            false),
+  B("__DATE__",		   BT_DATE,            false),
+  B("__FILE__",		   BT_FILE,            false),
+  B("__BASE_FILE__",	   BT_BASE_FILE,       false),
+  B("__LINE__",		   BT_SPECLINE,        true),
+  B("__CANON_LINE__",	   BT_CANON_SPECLINE,  false),
+  B("__CANON_BASE_FILE__", BT_CANON_BASE_FILE, true),
+  B("__INCLUDE_LEVEL__",   BT_INCLUDE_LEVEL,   true),
+  B("__COUNTER__",	   BT_COUNTER,         true),
   /* Keep builtins not used for -traditional-cpp at the end, and
      update init_builtins() if any more are added.  */
-  B("_Pragma",		 BT_PRAGMA,        true),
-  B("__STDC__",		 BT_STDC,          true),
+  B("_Pragma",		   BT_PRAGMA,          true),
+  B("__STDC__",		   BT_STDC,            true),
 };
 #undef B
 
Index: libcpp/internal.h
===================================================================
--- libcpp/internal.h	(revision 158225)
+++ libcpp/internal.h	(working copy)
@@ -489,6 +489,10 @@ struct cpp_reader
 
   /* List of saved macros by push_macro.  */
   struct def_pragma_macro *pushed_macros;
+  
+  /* Because the preprocessor does not maintain an accurate column
count
+     we need an occurance count to make BT_CANON_SPECLINE unique. */
+  unsigned int bt_canon_line_occur_count;
 };
 
 /* Character classes.  Based on the more primitive macros in
safe-ctype.h.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]