This is the mail archive of the
binutils@sourceware.cygnus.com
mailing list for the binutils project.
enum.patch
- To: binutils at sourceware dot cygnus dot com
- Subject: enum.patch
- From: Doug Evans <dje at transmeta dot com>
- Date: Mon, 5 Jun 2000 17:41:06 -0700
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}}