enum.patch

Doug Evans dje@transmeta.com
Mon Jun 5 17:41:00 GMT 2000


It is often useful to use the same header with C and assembly.
Enum's are useful in such situations so here's a patch that implements that.
I haven't tested all possible values.  What's here is enough
for my purposes.  I'm guessing any gotchas that need to be fixed can
be fixed.

I copied the code from s_set,pseudo_set.  The COFF stuff might be
unnecessary.

If you want it, and you need a copyright assignment, let me know.

2000-06-05  Doug Evans  <dje@casey.transmeta.com>

	Add support for .enum/.endenum.
	* read.h (s_enum,s_endenum): Declare.
	* read.c (last_enum_value): New static global.
	(skip_whitespace_and_newlines,parse_one_enum): New fns.
	(s_enum,s_endenum): New fns.

Index: read.c
===================================================================
RCS file: /cvs/src/src/gas/read.c,v
retrieving revision 1.23
diff -c -p -r1.23 read.c
*** read.c	2000/06/04 05:03:31	1.23
--- read.c	2000/06/06 00:30:50
*************** static const pseudo_typeS potable[] =
*** 326,334 ****
--- 326,336 ----
    {"elseif", s_elseif, (int) O_ne},
    {"end", s_end, 0},
    {"endc", s_endif, 0},
+   {"endenum", s_endenum, 0},
    {"endfunc", s_func, 1},
    {"endif", s_endif, 0},
  /* endef */
+   {"enum", s_enum, 0},
    {"equ", s_set, 0},
    {"equiv", s_set, 1},
    {"err", s_err, 0},
*************** s_app_file (appfile)
*** 1602,1607 ****
--- 1604,1746 ----
  #endif
  	}
      }
+ }
+ 
+ static int last_enum_value;
+ 
+ /* Result is 0 if EOF, 1 if success.  */
+ 
+ static int
+ skip_whitespace_and_newlines ()
+ {
+     while (1)
+       {
+ 	  SKIP_WHITESPACE ();
+ 	  if (! is_end_of_line[(unsigned char) *input_line_pointer])
+ 	    break;
+ 	  ++input_line_pointer;
+ 	  bump_line_counters ();
+ 	  if (input_line_pointer == buffer_limit)
+ 	    {
+ 	      buffer_limit = input_scrub_next_buffer (&input_line_pointer);
+ 	      if (buffer_limit == 0)
+ 		return 0;
+ 	    }
+       }
+     return 1;
+ }
+ 
+ static int
+ parse_one_enum ()
+ {
+   char *name;
+   char delim;
+   char *end_name;
+   symbolS *symbolP;
+   int equiv = 1;
+   int done_p = 0;
+   expressionS exp;
+ 
+   skip_whitespace_and_newlines ();
+ 
+   if (*input_line_pointer == '.')
+       return 1;
+ 
+   name = input_line_pointer;
+   delim = get_symbol_end ();
+   end_name = input_line_pointer;
+   *end_name = delim;
+ 
+   skip_whitespace_and_newlines ();
+ 
+   if (*input_line_pointer == ',')
+     {
+       ++last_enum_value;
+       ++input_line_pointer;
+     }
+   else if (*input_line_pointer == '.') /* FIXME: revisit */
+     {
+       ++last_enum_value;
+       done_p = 1;
+     }
+   else if (*input_line_pointer == '=')
+     {
+       ++input_line_pointer;
+       skip_whitespace_and_newlines ();
+ 
+       (void) expression (&exp);
+       if (exp.X_op == O_constant)
+ 	{
+ 	  last_enum_value = exp.X_add_number;
+ 	}
+       else
+ 	{
+ 	  as_bad ("invalid expression in enum value");
+ 	}
+     }
+   else
+     {
+       as_bad ("enum syntax error");
+       ignore_rest_of_line ();
+       return 0;
+     }
+ 
+   *end_name = 0;
+ 
+   if ((symbolP = symbol_find (name)) == NULL
+       && (symbolP = md_undefined_symbol (name)) == NULL)
+     {
+       symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
+ #ifdef OBJ_COFF /* FIXME: revisit */
+       /* "set" symbols are local unless otherwise specified. */
+       SF_SET_LOCAL (symbolP);
+ #endif /* OBJ_COFF */
+     }				/* make a new symbol */
+ 
+   symbol_table_insert (symbolP);
+ 
+   *end_name = delim;
+ 
+   /* FIXME: for now - need to decide desired behaviour.  */
+   if (equiv
+       && S_IS_DEFINED (symbolP)
+       && S_GET_SEGMENT (symbolP) != reg_section)
+     as_bad ("symbol `%s' already defined", S_GET_NAME (symbolP));
+ 
+   /* Assign the value.  */
+ 
+   S_SET_SEGMENT (symbolP, absolute_section);
+   S_SET_VALUE (symbolP, (valueT) last_enum_value);
+   symbol_set_frag (symbolP, &zero_address_frag);
+ 
+   /* Eat comma if one present.  */
+   if (*input_line_pointer == ',')
+     ++input_line_pointer;
+ 
+   return done_p;
+ }
+ 
+ void 
+ s_enum (ignore)
+      int ignore ATTRIBUTE_UNUSED;
+ {
+   int done_p;
+ 
+   demand_empty_rest_of_line ();
+ 
+   last_enum_value = -1;
+   done_p = 0;
+   while (! done_p)
+     {
+ 	done_p = parse_one_enum ();
+     }
+ }
+ 
+ void 
+ s_endenum (ignore)
+      int ignore ATTRIBUTE_UNUSED;
+ {
+   demand_empty_rest_of_line ();
  }
  
  /* Handle the .appline pseudo-op.  This is automatically generated by
Index: read.h
===================================================================
RCS file: /cvs/src/src/gas/read.h,v
retrieving revision 1.5
diff -c -p -r1.5 read.h
*** read.h	2000/05/21 18:26:10	1.5
--- read.h	2000/06/06 00:30:50
*************** extern void s_desc PARAMS ((int));
*** 133,139 ****
--- 133,141 ----
  extern void s_else PARAMS ((int arg));
  extern void s_elseif PARAMS ((int arg));
  extern void s_end PARAMS ((int arg));
+ extern void s_endenum PARAMS ((int arg));
  extern void s_endif PARAMS ((int arg));
+ extern void s_enum PARAMS ((int arg));
  extern void s_err PARAMS ((int));
  extern void s_fail PARAMS ((int));
  extern void s_fill PARAMS ((int));
Index: doc/as.texinfo
===================================================================
RCS file: /cvs/src/src/gas/doc/as.texinfo,v
retrieving revision 1.13
diff -c -p -r1.13 as.texinfo
*** as.texinfo	2000/05/29 18:48:26	1.13
--- as.texinfo	2000/06/06 00:30:51
*************** Some machine configurations provide addi
*** 3143,3151 ****
  @ifset COFF
  * Endef::                       @code{.endef}
  @end ifset
! 
  * Endfunc::                     @code{.endfunc}
  * Endif::                       @code{.endif}
  * Equ::                         @code{.equ @var{symbol}, @var{expression}}
  * Equiv::                       @code{.equiv @var{symbol}, @var{expression}}
  * Err::				@code{.err}
--- 3143,3152 ----
  @ifset COFF
  * Endef::                       @code{.endef}
  @end ifset
! * Endenum::                     @code{.endenum}
  * Endfunc::                     @code{.endfunc}
  * Endif::                       @code{.endif}
+ * Enum::                        @code{.enum}
  * Equ::                         @code{.equ @var{symbol}, @var{expression}}
  * Equiv::                       @code{.equiv @var{symbol}, @var{expression}}
  * Err::				@code{.err}
*************** directive but ignores it.
*** 3527,3532 ****
--- 3528,3539 ----
  @end ifset
  @end ifset
  
+ @node Endenum
+ @section @code{.endenum}
+ @cindex @code{endenum} directive
+ @code{.endenum} marks the end of an enumerated list specified with
+ @code{.enum}.  It must appear on a line by itself.
+ 
  @node Endfunc
  @section @code{.endfunc}
  @cindex @code{endfunc} directive
*************** directive but ignores it.
*** 3539,3544 ****
--- 3546,3578 ----
  @code{.endif} is part of the @code{@value{AS}} support for conditional assembly;
  it marks the end of a block of code that is only assembled
  conditionally.  @xref{If,,@code{.if}}.
+ 
+ @node Enum
+ @section @code{.enum}
+ @cindex @code{enum} directive
+ @code{.enum} marks the beginning of an enumerated list.
+ The list is terminated with @code{.endenum}.
+ Both @code{.enum} and @code{.endenum} must appear on a line by themselves,
+ however the syntax of the enumerated list is identical to @samp{C}.
+ The result is equivalent to specifying all of the enumerations with
+ @code{.equiv}.  @code{.enum} is useful in header files that need
+ to be shared with @samp{C}.
+ 
+ @smallexample
+ #ifdef ASSEMBLY
+ #define BEGINENUM .enum
+ #define ENDENUM .endenum
+ #else
+ #define BEGINENUM enum @{ /* add typedef,tag as necessary */
+ #define ENDENUM @};
+ #endif
+ 
+ BEGINENUM
+         a = 42, b, c,
+         d = b + (1 << 16),
+         e
+ ENDENUM
+ @end smallexample
  
  @node Equ
  @section @code{.equ @var{symbol}, @var{expression}}


More information about the Binutils mailing list