%prefixes% terminal = lex_; %maps% /* * ENTRY POINT * * The main entry point for is mapped onto a function named read_spec. */ specification -> read_spec; /* * TYPE MAPPINGS * * These maps give the relationship between the types used in the syntax * and in the C implementation. */ BOOLEAN -> int; COMMAND -> SID_COMMAND; COMMAND_KEY -> int; IDENTIFIER -> SID_IDENTIFIER; STRING -> SID_STRING; SUBSET_KEY -> SID_STRING; TYPE -> SID_TYPE; TYPE_KEY -> int; TYPE_LIST -> SID_TYPE; TYPE_QUAL -> unsigned; TYPE_SPEC -> unsigned; VERSION -> int; %header% @{ /* * Copyright (c) 2002, The Tendra Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Crown Copyright (c) 1997 * * This TenDRA(r) Computer Program is subject to Copyright * owned by the United Kingdom Secretary of State for Defence * acting through the Defence Evaluation and Research Agency * (DERA). It is made available to Recipients with a * royalty-free licence for its use, reproduction, transfer * to other parties and amendment for any purpose not excluding * product development provided that any such use et cetera * shall be deemed to be acceptance of the following conditions:- * * (1) Its Recipients shall ensure that this Notice is * reproduced upon any copies or amended versions of it; * * (2) Any amended version of it shall be clearly marked to * show both the nature of and the organisation responsible * for the relevant amendment or amendments; * * (3) Its onward transfer from a recipient to another * party shall be deemed to be that party's acceptance of * these conditions; * * (4) DERA gives no warranty or assurance as to its * quality or suitability for any purpose and DERA accepts * no liability whatsoever in relation to any use to which * it may be put. * * $TenDRA: tendra/src/tools/tspec/syntax.act,v 1.9 2005/10/31 10:17:01 stefanf Exp $ */ #include "config.h" #include "cstring.h" #include "msgcat.h" #include "object.h" #include "hash.h" #include "lex.h" #include "name.h" #include "syntax.h" #include "type.h" #include "utility.h" #include "variable.h" /* * PARSER TYPES * * These types give the implementations of the various types used * in the syntax. */ typedef char *SID_STRING; typedef type *SID_TYPE; typedef struct { char *iname; char *ename; int ivers; int evers; } SID_IDENTIFIER; /* * CURRENT FIELD NAME * * The name of the current structure is stored during a +FIELD * construct. */ static char *crt_field_name = null; static int anon_no = 0; /* * CV-QUALIFIER NAMES * * This table gives the mapping between the values used to represent * cv-qualifiers in the parser and the qualifier names used in the * internal representation. */ static char *cv_qualifier [] = { null, "const", "restrict", "const restrict", "volatile", "const volatile", "const restrict volatile" }; /* * COMPILATION MODE * * We allow unreached code in the automatically generated sections. */ #ifdef __TenDRA__ #pragma TenDRA begin #pragma TenDRA unreachable code allow #pragma TenDRA variable analysis off #endif @}, @{ /* * Copyright (c) 2002, The Tendra Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Crown Copyright (c) 1997 * * This TenDRA(r) Computer Program is subject to Copyright * owned by the United Kingdom Secretary of State for Defence * acting through the Defence Evaluation and Research Agency * (DERA). It is made available to Recipients with a * royalty-free licence for its use, reproduction, transfer * to other parties and amendment for any purpose not excluding * product development provided that any such use et cetera * shall be deemed to be acceptance of the following conditions:- * * (1) Its Recipients shall ensure that this Notice is * reproduced upon any copies or amended versions of it; * * (2) Any amended version of it shall be clearly marked to * show both the nature of and the organisation responsible * for the relevant amendment or amendments; * * (3) Its onward transfer from a recipient to another * party shall be deemed to be that party's acceptance of * these conditions; * * (4) DERA gives no warranty or assurance as to its * quality or suitability for any purpose and DERA accepts * no liability whatsoever in relation to any use to which * it may be put. * * $TenDRA: tendra/src/tools/tspec/syntax.act,v 1.9 2005/10/31 10:17:01 stefanf Exp $ */ #ifndef SYNTAX_INCLUDED #define SYNTAX_INCLUDED typedef object *SID_COMMAND; @}; %terminals% /* * TERMINALS * * The mapping of the terminals is trivial. */ name: () -> (s) = @{ @s = token_value; @}; number: () -> (s) = @{ @s = token_value; @}; string: () -> (s) = @{ @s = token_value; @}; variable: () -> (s) = @{ @s = token_value; @}; comment: () -> (s) = @{ @s = token_value; @}; insert: () -> (s) = @{ @s = token_value; @}; build-insert: () -> (s) = @{ @s = token_value; @}; %actions% /* * BOOLEAN CONSTANTS * * These actions describe the boolean constants. */ : () -> (b) = @{ @b = 0; @}; : () -> (b) = @{ @b = 1; @}; /* * BASIC TYPE SPECIFIERS * * These actions describe the basic type specifiers. */ : () -> (b) = @{ @b = BTYPE_CHAR; @}; : () -> (b) = @{ @b = BTYPE_SHORT; @}; : () -> (b) = @{ @b = BTYPE_INT; @}; : () -> (b) = @{ @b = BTYPE_LONG; @}; : () -> (b) = @{ @b = BTYPE_SIGNED; @}; : () -> (b) = @{ @b = BTYPE_UNSIGNED; @}; : () -> (b) = @{ @b = BTYPE_FLOAT; @}; : () -> (b) = @{ @b = BTYPE_DOUBLE; @}; : () -> (b) = @{ @b = BTYPE_VOID; @}; : (a, b) -> (c) = @{ while (@a & @b) { if (@a == BTYPE_LONG && allow_long_long) { @a = BTYPE_LLONG; } else { MSG_duplicate_type_specifier (); break; } } @c = (@a | @b); @}; /* * TYPE KEYS * * These actions describe the type keys. */ : () -> (t) = @{ @t = TYPE_GENERIC; @}; : () -> (t) = @{ @t = TYPE_STRUCT_TAG; @}; : () -> (t) = @{ @t = TYPE_UNION_TAG; @}; : () -> (t) = @{ @t = TYPE_ENUM_TAG; @}; : () -> (t) = @{ @t = TYPE_STRUCT; @}; : () -> (t) = @{ @t = TYPE_UNION; @}; : () -> (t) = @{ @t = TYPE_ENUM; @}; : () -> (t) = @{ @t = TYPE_INT; @}; : () -> (t) = @{ @t = TYPE_SIGNED; @}; : () -> (t) = @{ @t = TYPE_UNSIGNED; @}; : () -> (t) = @{ @t = TYPE_FLOAT; @}; : () -> (t) = @{ @t = TYPE_ARITH; @}; : () -> (t) = @{ @t = TYPE_SCALAR; @}; : () -> (t) = @{ @t = TYPE_LVALUE; @}; : () -> (t) = @{ @t = TYPE_RVALUE; @}; : (c, a) -> (t) = @{ if (@c == OBJ_CONST) { if (@a == TYPE_LVALUE) { MSG_constant_cant_be_lvalue (); } @t = TYPE_RVALUE; } else if (@c == OBJ_EXTERN) { @t = TYPE_LVALUE; } else { @t = @a; } @}; /* * TYPE QUALIFIERS * * These actions describe the type qualifiers. const is represented by 1, * restrict by 2 and volatile by 4. */ : () -> (c) = @{ @c = 0; @}; : (a) -> (c) = @{ if (@a & 1) MSG_duplicate_type_qualifier (); @c = (@a | 1); @}; : (a) -> (c) = @{ if (@a & 2) MSG_duplicate_type_qualifier (); @c = (@a | 2); @}; : (a) -> (c) = @{ if (@a & 4) MSG_duplicate_type_qualifier (); @c = (@a | 4); @}; /* * TYPE CONSTRUCTORS * * These actions describe the type constructors. */ : () -> (t) = @{ @t = null; @}; : (b) -> (t) = @{ @t = basic_type (@b); @}; : (s, tag) -> (t) = @{ @t = find_type (@s, any_version, @tag, 1); @}; : (s) -> (t) = @{ @t = special_type (@s); @}; : (s, p) -> (t) = @{ @t = inject_type (@s, @p); @}; : (c) -> (t) = @{ @t = make_subtype ((type *) null, TYPE_PTR); @t->v.str = cv_qualifier [@c]; @}; : (a) -> (t) = @{ @t = make_subtype ((type *) null, TYPE_ARRAY); @t->v.str = @a; @}; : (a) -> (t) = @{ @t = make_subtype ((type *) null, TYPE_BITFIELD); @t->v.str = @a; @}; : (p) -> (t) = @{ @t = make_subtype ((type *) null, TYPE_PROC); @t->v.next = @p; @}; : (p) -> (t) = @{ @t = make_subtype ((type *) null, TYPE_PROC); @t->v.next = @p; @}; : (s, c) -> (t) = @{ @t = make_subtype (@s, TYPE_QUALIFIER); @t->v.str = cv_qualifier [@c]; @}; : (s, lv) -> (t) = @{ @t = make_subtype (@s, @lv); @}; /* * TYPE LISTS * * These actions describe the parameter type lists. */ : () -> (p) = @{ @p = null; @}; : () -> (p) = @{ MSG_empty_parameter_list (); @p = null; @}; : (t, q) -> (p) = @{ @p = make_subtype (@t, TYPE_LIST); @p->v.next = @q; @}; : () -> (p) = @{ @p = make_subtype (type_ellipsis, TYPE_LIST); @p->v.next = null; @}; : (nm) -> () = @{ UNUSED (@nm); @}; /* * CONSTANT EXPRESSIONS * * These actions describe the constant expressions. */ : () -> (s) = @{ @s = ""; @}; : (a) -> (s) = @{ @s = string_concat ("-", @a); @}; : (a) -> (s) = @{ @s = string_concat ("!", @a); @}; : (a) -> (s) = @{ object *p = search_hash (exps, @a, any_version); if (p == null) { MSG_undefined_nat (@a); } else if (p->objtype != OBJ_NAT) { MSG_not_a_nat (@a); } @s = @a; @}; /* * CONDITIONAL COMPILATION MACROS * * These rules describe the special macros which can be used in * conditional compilation. */ : () -> (s) = @{ @s = BUILDING_MACRO; @}; : (a, b) -> (s) = @{ @s = macro_name (PROTECT_PREFIX, @a, @b, NULL); @}; /* * MACRO DEFINITION PARAMETERS * * These rules describe the macro definition parameter lists. */ : () -> (p) = @{ @p = null; @}; : () -> (p) = @{ @p = ""; @}; : (n, q) -> (p) = @{ @p = string_printf ("%s, %s", @n, @q); @}; /* * IDENTIFIERS * * These actions describe the identifier names. */ : () -> (nm) = @{ @nm = null; @}; : (fnm) -> (nm) = @{ if (crt_field_name) { @nm = string_printf ("%s.%s", crt_field_name, @fnm); } else { @nm = @fnm; } @}; : (tnm) -> (nm) = @{ @nm = token_name (@tnm); @}; : (a, va, b, vb) -> (id) = @{ @id.iname = @a; @id.ivers = @va; @id.ename = @b; @id.evers = @vb; @}; : () -> (id) = @{ char *nm = string_printf ("%s%d", HIDDEN_NAME, anon_no++); if (crt_field_name) { nm = string_printf ("%s.%s", crt_field_name, nm); } @id.iname = nm; @id.ivers = no_version; @id.ename = token_name (nm); @id.evers = no_version; @}; : () -> (v) = @{ @v = no_version; @}; : (n) -> (v) = @{ @v = atoi (@n); @}; /* * SUBSET NAMES * * These actions describe the subset names. */ : () -> (s) = @{ @s = "00"; @}; : () -> (s) = @{ @s = "10"; @}; : () -> (s) = @{ @s = "01"; @}; : () -> (s) = @{ @s = "11"; @}; : (a) -> (s) = @{ @s = string_concat (@a, "G"); @}; : (a) -> (s) = @{ @s = subset_name (@a, NULL, NULL); @}; : (a, b) -> (s) = @{ @s = subset_name (@a, @b, NULL); @}; : (a, b, c) -> (s) = @{ if (@b [0] == 0) @b = null; @s = subset_name (@a, @b, @c); @}; /* * COMMAND KEYS * * These actions describe the command keys. */ : () -> (c) = @{ @c = OBJ_CONST; @}; : () -> (c) = @{ @c = OBJ_EXP; @}; : () -> (c) = @{ @c = OBJ_EXTERN; @}; : () -> (c) = @{ @c = OBJ_FUNC; @}; : () -> (c) = @{ @c = OBJ_EXTERN; @}; : () -> (c) = @{ @c = OBJ_WEAK; @}; : () -> (c) = @{ @c = OBJ_IMPLEMENT; @}; : () -> (c) = @{ @c = OBJ_USE; @}; /* * COMMANDS * * These actions describe the basic command constructs. */ : () -> (c) = @{ @c = null; @}; : (a, b) -> (c) = @{ @c = join_object (@a, @b); @}; : (s) -> (c) = @{ object *p = make_subset (@s); info *i = p->u.u_info; if (i->subset) { char *nm = subset_name (i->api, i->file, NULL); object *q = search_hash (subsets, nm, no_version); update_time (p, q); } @c = crt_object; crt_object = p; @}; : (a, b) -> (c) = @{ object *p = crt_object; if (p) p->u.u_info->elements = @b; @c = make_object (NULL, OBJ_SET); @c->u.u_obj = p; crt_object = @a; @}; : (cmd, s, key) -> (c) = @{ object *p = make_subset (@s); update_time (crt_object, p); @c = make_object (@key, @cmd); @c->u.u_obj = p; @}; /* * VARIABLE COMMANDS * * These commands describe the variable assignment commands. */ : (a, b) -> () = @{ set_string (@a, @b); @}; : (a, b) -> () = @{ set_integer (@a, atoi (@b)); @}; : (a, b) -> () = @{ set_integer (@a, -atoi (@b)); @}; /* * SPECIFICATION COMMANDS * * These actions describe the constructs for the various specification * commands. */ : () -> (c) = @{ @c = null; @}; : (s) -> (c) = @{ @c = make_object (@s, OBJ_TEXT_INCL); @}; : (s) -> (c) = @{ @c = make_object (@s, OBJ_TEXT_INCL); @}; : (s) -> (c) = @{ @c = make_object (@s, OBJ_TEXT_SRC); @}; : (id, p, def) -> (c) = @{ char *def; object *p = make_exp (@id.iname, @id.ivers, OBJ_DEFINE); if (@p) { if (*@p) { def = string_printf ("(%s) %s", @p, @def); } else { def = string_printf ("() %s", @def); } } else { def = string_printf (" %s", @def); } p->u.u_str = def; @c = make_token (@id.ename, @id.evers, p, OBJ_EXTERN); @}; : (tag, id, e) -> (c) = @{ type *t = make_type (@id.iname, @id.ivers, @tag); t->v.obj2 = @e; @c = make_token (@id.ename, @id.evers, t->u.obj, OBJ_TYPE); @}; : (id, s) -> (c) = @{ object *p = make_exp (@id.iname, @id.ivers, OBJ_ENUMVAL); p->u.u_str = @s; @c = make_token (@id.ename, @id.evers, p, OBJ_EXTERN); @}; : (cmd, id, t) -> (c) = @{ object *p = make_exp (@id.iname, @id.ivers, @cmd); p->u.u_type = check_type (@t, @cmd); @c = make_token (@id.ename, @id.evers, p, @cmd); @}; : (id, m, t) -> (c) = @{ type *t = check_type (@t, OBJ_FIELD); field *f = make_field (@id.iname, @id.ivers, @m, t); @c = make_token (@id.ename, @id.evers, f->obj, OBJ_FIELD); @}; : (cmd, id, t) -> (c) = @{ object *p = make_exp (@id.iname, @id.ivers, @cmd); p->u.u_type = check_type (@t, OBJ_FUNC); @c = make_token (@id.ename, @id.evers, p, @cmd); @}; : (id, t) -> (c) = @{ object *p; int cmd = OBJ_MACRO; if (@t->id != TYPE_PROC) cmd = OBJ_EXP; p = make_exp (@id.iname, @id.ivers, cmd); p->u.u_type = check_type (@t, cmd); @c = make_token (@id.ename, @id.evers, p, cmd); @}; : (id) -> (c) = @{ object *p = make_exp (@id.iname, @id.ivers, OBJ_NAT); @c = make_token (@id.ename, @id.evers, p, OBJ_NAT); @}; : (id, t) -> (c) = @{ type *t = make_type (@id.iname, @id.ivers, TYPE_PROMOTE); type *s = expand_type (@t); switch (s->id) { case TYPE_INT : case TYPE_SIGNED : case TYPE_UNSIGNED : { break; } default : { MSG_non_integral_promotion_type (); break; } } t->v.next = s; @c = make_token (@id.ename, @id.evers, t->u.obj, OBJ_EXTERN); @}; : (id, t) -> (c) = @{ object *p = make_exp (@id.iname, @id.ivers, OBJ_STATEMENT); p->u.u_type = check_type (@t, OBJ_STATEMENT); @c = make_token (@id.ename, @id.evers, p, OBJ_STATEMENT); @}; : (id, s) -> (c) = @{ object *p = make_exp (@id.iname, @id.ivers, OBJ_TOKEN); p->u.u_str = @s; @c = make_token (@id.ename, @id.evers, p, OBJ_TOKEN); @}; : (tag, id) -> (c) = @{ type *t = make_type (@id.iname, @id.ivers, @tag); @c = make_token (@id.ename, @id.evers, t->u.obj, OBJ_TYPE); @}; : (id, t) -> (c) = @{ type *t = make_type (@id.iname, @id.ivers, TYPE_DEFINED); t->v.next = check_type (@t, OBJ_TYPE); @c = make_token (@id.ename, @id.evers, t->u.obj, OBJ_EXTERN); @}; /* * FIELD SPECIFICATION COMMANDS * * These actions describe the member specification constructs. */ : (id, tag) -> (t, c) = @{ @t = find_type (@id.iname, any_version, @tag, 0); if (@t == null) { @t = make_type (@id.iname, @id.ivers, @tag); @c = make_token (@id.ename, @id.evers, @t->u.obj, OBJ_TYPE); } else { @c = null; } @t = expand_type (@t); switch (@t->id) { case TYPE_STRUCT : case TYPE_UNION : case TYPE_STRUCT_TAG : case TYPE_UNION_TAG : { break; } default : { MSG_illegal_field_type (@id.iname); break; } } crt_field_name = @t->u.obj->name; @}; : (t, a, b, e) -> (c) = @{ if (@e) { if (@t->v.obj2) { char *nm = crt_field_name; MSG_redefinition_of_type (nm); } if (@b == null) { MSG_empty_struct_union_definition (); } else { @t->v.obj2 = @b; } if (@a == null) { /* This is a hack, do properly later */ @c = make_object (NULL, OBJ_TYPE); @c->u.u_type = @t; if (streq (@c->filename, @t->u.obj->filename)) { @t->state = 1; } else { @t->state = 3; } } else { @c = @a; } } else { @c = join_object (@a, @b); } crt_field_name = null; @}; /* * CONDITIONAL COMPILATION COMMANDS * * These actions describe the conditional compilation constructs. */ : (s) -> (c) = @{ @c = make_object (@s, OBJ_IF); @c->u.u_num = CMD_IF; @}; : (s) -> (c) = @{ @c = make_object (@s, OBJ_IF); @c->u.u_num = CMD_IFDEF; @}; : (s) -> (c) = @{ @c = make_object (@s, OBJ_IF); @c->u.u_num = CMD_IFNDEF; @}; : (i, s, a, b) -> (c) = @{ object *p, *q; p = join_object (@i, @a); if (@b) { q = make_object (@s, OBJ_IF); q->u.u_num = CMD_ELSE; p = join_object (p, q); p = join_object (p, @b); } q = make_object (@s, OBJ_IF); q->u.u_num = CMD_ENDIF; @c = join_object (p, q); @}; /* * SYNTAX ERROR * * This action describes the error message which is printed if a parse * error occurs. */ : () -> () = @{ MSG_syntax_error (); @}; %trailer% @{ @}, @{ #endif @};