/*************************************************************************** parser.y (IDL yacc parser and tree generation) Copyright (C) 1998, 1999 Andrew T. Veliath This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. $Id: parser.y,v 1.163 2004/11/12 15:37:11 michael Exp $ ***************************************************************************/ %{ #include #include #include #include #include #include #include #include "rename.h" #include "util.h" #define REF_IDENTS #define do_binop(rv,op,a,b) do { \ if (IDL_binop_chktypes (op, a, b)) \ YYABORT; \ if (!(__IDL_flags & IDLF_NO_EVAL_CONST)) { \ rv = IDL_binop_eval (op, a, b); \ IDL_tree_free (a); \ IDL_tree_free (b); \ if (!rv) YYABORT; \ } else { \ rv = IDL_binop_new (op, a, b); \ } \ } while (0) #define do_unaryop(rv,op,a) do { \ if (IDL_unaryop_chktypes (op, a)) \ YYABORT; \ if (!(__IDL_flags & IDLF_NO_EVAL_CONST)) { \ rv = IDL_unaryop_eval (op, a); \ IDL_tree_free (a); \ if (!rv) YYABORT; \ } else { \ rv = IDL_unaryop_new (op, a); \ } \ } while (0) #define IS_INHIBIT_STATE() \ (__IDL_inhibits > 0 || \ ((__IDL_flags & IDLF_INHIBIT_INCLUDES) && \ (__IDL_flagsi & IDLFP_IN_INCLUDES) ) ) #define assign_declspec(tree,declspec) do { \ IDL_NODE_DECLSPEC (tree) = declspec; \ if ( IS_INHIBIT_STATE() ) { \ IDL_NODE_DECLSPEC (tree) |= \ IDLF_DECLSPEC_EXIST | \ IDLF_DECLSPEC_INHIBIT; \ } \ if ( __IDL_pidl > 0 ) { \ IDL_NODE_DECLSPEC (tree) |= \ IDLF_DECLSPEC_PIDL; \ } \ } while (0) #define assign_props(tree,props) do { \ if (__IDL_flags & IDLF_PROPERTIES) \ IDL_NODE_PROPERTIES (tree) = (props); \ else \ __IDL_free_properties (props); \ } while (0) extern int yylex (void); static IDL_declspec_t IDL_parse_declspec (const char *strspec); static int IDL_binop_chktypes (enum IDL_binop op, IDL_tree a, IDL_tree b); static int IDL_unaryop_chktypes (enum IDL_unaryop op, IDL_tree a); static IDL_tree IDL_binop_eval (enum IDL_binop op, IDL_tree a, IDL_tree b); static IDL_tree IDL_unaryop_eval (enum IDL_unaryop op, IDL_tree a); static IDL_tree list_start (IDL_tree a, gboolean filter_null); static IDL_tree list_chain (IDL_tree a, IDL_tree b, gboolean filter_null); static IDL_tree zlist_chain (IDL_tree a, IDL_tree b, gboolean filter_null); static int do_token_error (IDL_tree p, const char *message, gboolean prev); static void illegal_context_type_error (IDL_tree p, const char *what); static void illegal_type_error (IDL_tree p, const char *message); %} %union { IDL_tree tree; struct { IDL_tree tree; gpointer data; } treedata; GHashTable *hash_table; char *str; gboolean boolean; IDL_declspec_t declspec; IDL_longlong_t integer; double floatp; enum IDL_unaryop unaryop; enum IDL_param_attr paramattr; } /* Terminals */ %token TOK_ANY %token TOK_ATTRIBUTE %token TOK_BOOLEAN %token TOK_CASE %token TOK_CHAR %token TOK_CONST %token TOK_CONTEXT %token TOK_DEFAULT %token TOK_DOUBLE %token TOK_ENUM %token TOK_EXCEPTION %token TOK_FALSE %token TOK_FIXED %token TOK_FLOAT %token TOK_IN %token TOK_INOUT %token TOK_INTERFACE %token TOK_LONG %token TOK_MODULE %token TOK_NATIVE %token TOK_OBJECT %token TOK_OCTET %token TOK_ONEWAY %token TOK_OP_SCOPE %token TOK_OP_SHL %token TOK_OP_SHR %token TOK_OUT %token TOK_RAISES %token TOK_READONLY %token TOK_SEQUENCE %token TOK_SHORT %token TOK_STRING %token TOK_STRUCT %token TOK_SWITCH %token TOK_TRUE %token TOK_TYPECODE %token TOK_TYPEDEF %token TOK_UNION %token TOK_UNSIGNED %token TOK_VARARGS %token TOK_VOID %token TOK_WCHAR %token TOK_WSTRING %token TOK_FLOATP %token TOK_INTEGER %token TOK_DECLSPEC TOK_PROP_KEY %token TOK_PROP_VALUE TOK_NATIVE_TYPE %token TOK_IDENT TOK_SQSTRING TOK_DQSTRING TOK_FIXEDP %token TOK_CODEFRAG %token TOK_SRCFILE /* Non-Terminals */ %type add_expr %type and_expr %type any_type %type array_declarator %type attr_dcl %type attr_dcl_def %type base_type_spec %type boolean_lit %type boolean_type %type case_label %type case_label_list %type case_stmt %type case_stmt_list %type char_lit %type char_type %type codefrag %type complex_declarator %type const_dcl %type const_dcl_def %type const_exp %type const_type %type constr_type_spec %type context_expr %type cur_ns_new_or_prev_ident %type declarator %type declarator_list %type definition %type definition_list %type element_spec %type enum_type %type enumerator_list %type except_dcl %type except_dcl_def %type export %type export_list %type fixed_array_size %type fixed_array_size_list %type fixed_pt_const_type %type fixed_pt_lit %type fixed_pt_type %type floating_pt_lit %type floating_pt_type %type ident %type illegal_ident %type integer_lit %type integer_type %type interface %type interface_body %type interface_catch_ident %type is_context_expr %type is_raises_expr %type literal %type member %type member_list %type member_zlist %type module %type mult_expr %type new_ident %type new_or_prev_scope %type new_scope %type ns_global_ident %type ns_new_ident %type ns_prev_ident %type ns_scoped_name %type object_type %type octet_type %type op_dcl %type op_dcl_def %type op_param_type_spec %type op_param_type_spec_illegal %type op_type_spec %type or_expr %type param_dcl %type param_dcl_list %type param_type_spec %type pop_scope %type positive_int_const %type primary_expr %type raises_expr %type scoped_name %type scoped_name_list %type sequence_type %type shift_expr %type simple_declarator %type simple_declarator_list %type simple_type_spec %type specification %type srcfile %type string_lit %type string_lit_list %type string_type %type struct_type %type switch_body %type switch_type_spec %type template_type_spec %type type_dcl %type type_dcl_def %type type_declarator %type type_spec %type unary_expr %type union_type %type useless_semicolon %type wide_char_type %type wide_string_type %type xor_expr %type z_definition_list %type z_inheritance %type z_new_ident_catch %type z_new_scope_catch %type typecode_type %type parameter_dcls %type z_declspec module_declspec %type z_props prop_hash %type is_readonly is_oneway %type is_varargs is_cvarargs %type signed_int unsigned_int %type param_attribute %type sqstring dqstring dqstring_cat %type unary_op %% specification: /* empty */ { yyerror ("Empty file"); YYABORT; } | definition_list { __IDL_root = $1; } ; z_definition_list: /* empty */ { $$ = NULL; } | definition_list ; definition_list: definition { $$ = list_start ($1, TRUE); } | definition_list definition { $$ = list_chain ($1, $2, TRUE); } ; check_semicolon: ';' | /* empty */ { if (do_token_error ($0, "Missing semicolon after", TRUE)) YYABORT; } ; useless_semicolon: ';' { yyerror ("Dangling semicolon has no effect"); $$ = NULL; } ; check_comma: ',' | /* empty */ { if (do_token_error ($0, "Missing comma after", TRUE)) YYABORT; } ; illegal_ident: scoped_name { if (IDL_NODE_UP ($1)) do_token_error (IDL_NODE_UP ($1), "Illegal context for", FALSE); else yyerror ("Illegal context for identifier"); YYABORT; } ; definition: type_dcl check_semicolon | const_dcl check_semicolon | except_dcl check_semicolon | interface check_semicolon | module check_semicolon | codefrag | srcfile | illegal_ident | useless_semicolon ; module_declspec: z_declspec TOK_MODULE ; module: module_declspec new_or_prev_scope { if (IDL_NODE_UP ($2) != NULL && IDL_NODE_TYPE (IDL_NODE_UP ($2)) != IDLN_MODULE) { yyerror ("Module definition conflicts"); do_token_error (IDL_NODE_UP ($2), "with", FALSE); YYABORT; } } '{' z_definition_list '}' pop_scope { IDL_tree module; if ($5 == NULL) { yyerrorv ("Empty module declaration `%s' is not legal IDL", IDL_IDENT ($2).str); module = NULL; } if (__IDL_flags & IDLF_COMBINE_REOPENED_MODULES) { if (IDL_NODE_UP ($2) == NULL) module = IDL_module_new ($2, $5); else { module = IDL_NODE_UP ($2); IDL_MODULE (module).definition_list = IDL_list_concat (IDL_MODULE (module).definition_list, $5); module = NULL; } } else module = IDL_module_new ($2, $5); $$ = module; if ($$) assign_declspec ($$, $1); } ; /* We only catch these errors for non-pidl because we want to be able to compile the OMG CORBA .idl files which define interfaces by these names */ interface_catch_ident: new_or_prev_scope | TOK_OBJECT { yyerror ("Interfaces cannot be named `Object'"); YYABORT; } | TOK_TYPECODE { yyerror ("Interfaces cannot be named `TypeCode'"); YYABORT; } ; interface: z_declspec z_props TOK_INTERFACE interface_catch_ident { assert ($4 != NULL); assert (IDL_NODE_TYPE ($4) == IDLN_IDENT); assert (IDL_IDENT_TO_NS ($4) != NULL); assert (IDL_NODE_TYPE (IDL_IDENT_TO_NS ($4)) == IDLN_GENTREE); if (IDL_NODE_UP ($4) != NULL && IDL_NODE_TYPE (IDL_NODE_UP ($4)) != IDLN_INTERFACE && IDL_NODE_TYPE (IDL_NODE_UP ($4)) != IDLN_FORWARD_DCL) { yyerrorl ("Interface definition conflicts", __IDL_prev_token_line - __IDL_cur_token_line); do_token_error (IDL_NODE_UP ($4), "with", FALSE); YYABORT; } else if (IDL_NODE_UP ($4) != NULL && IDL_NODE_TYPE (IDL_NODE_UP ($4)) != IDLN_FORWARD_DCL) { yyerrorv ("Cannot redeclare interface `%s'", IDL_IDENT ($4).str); IDL_tree_error ($4, "Previous declaration of interface `%s'", IDL_IDENT ($4).str); YYABORT; } else if (IDL_NODE_UP ($4) != NULL && IDL_NODE_TYPE (IDL_NODE_UP ($4)) == IDLN_FORWARD_DCL) __IDL_assign_this_location ($4, __IDL_cur_filename, __IDL_cur_line); } pop_scope z_inheritance { IDL_GENTREE (IDL_IDENT_TO_NS ($4))._import = $7; IDL_ns_push_scope (__IDL_root_ns, IDL_IDENT_TO_NS ($4)); if (IDL_ns_check_for_ambiguous_inheritance ($4, $7)) __IDL_is_okay = FALSE; } '{' interface_body '}' pop_scope { $$ = IDL_interface_new ($4, $7, $10); assign_declspec ($$, $1); assign_props (IDL_INTERFACE ($$).ident, $2); } | z_declspec z_props TOK_INTERFACE interface_catch_ident pop_scope { if ($2) yywarningv (IDL_WARNING1, "Ignoring properties for forward declaration `%s'", IDL_IDENT ($4).str); $$ = IDL_forward_dcl_new ($4); assign_declspec ($$, $1); } ; z_inheritance: /* empty */ { $$ = NULL; } | ':' scoped_name_list { GHashTable *table = g_hash_table_new (g_direct_hash, g_direct_equal); gboolean die = FALSE; IDL_tree p = $2; assert (IDL_NODE_TYPE (p) == IDLN_LIST); for (; p != NULL && !die; p = IDL_LIST (p).next) { assert (IDL_LIST (p).data != NULL); assert (IDL_NODE_TYPE (IDL_LIST (p).data) == IDLN_IDENT); if (g_hash_table_lookup_extended (table, IDL_LIST (p).data, NULL, NULL)) { char *s = IDL_ns_ident_to_qstring (IDL_LIST (p).data, "::", 0); yyerrorv ("Cannot inherit from interface `%s' more than once", s); g_free (s); die = TRUE; break; } else g_hash_table_insert (table, IDL_LIST (p).data, NULL); if (IDL_NODE_TYPE (IDL_NODE_UP (IDL_LIST (p).data)) == IDLN_FORWARD_DCL) { char *s = IDL_ns_ident_to_qstring (IDL_LIST (p).data, "::", 0); yyerrorv ("Incomplete definition of interface `%s'", s); IDL_tree_error (IDL_LIST (p).data, "Previous forward declaration of `%s'", s); g_free (s); die = TRUE; } else if (IDL_NODE_TYPE (IDL_NODE_UP (IDL_LIST (p).data)) != IDLN_INTERFACE) { char *s = IDL_ns_ident_to_qstring (IDL_LIST (p).data, "::", 0); yyerrorv ("`%s' is not an interface", s); IDL_tree_error (IDL_LIST (p).data, "Previous declaration of `%s'", s); g_free (s); die = TRUE; } } g_hash_table_destroy (table); if (die) YYABORT; $$ = $2; } ; scoped_name_list: scoped_name { $$ = list_start ($1, TRUE); } | scoped_name_list check_comma scoped_name { $$ = list_chain ($1, $3, TRUE); } ; interface_body: export_list ; export_list: /* empty */ { $$ = NULL; } | export_list export { $$ = zlist_chain ($1, $2, TRUE); } ; export: type_dcl check_semicolon | except_dcl check_semicolon | op_dcl check_semicolon | attr_dcl check_semicolon | const_dcl check_semicolon | codefrag | useless_semicolon ; type_dcl: z_declspec type_dcl_def { $$ = $2; assign_declspec ($$, $1); } ; type_dcl_def: z_props TOK_TYPEDEF type_declarator { IDL_tree_node node; IDL_tree p, dcl; $$ = $3; node.properties = $1; for (p = IDL_TYPE_DCL ($3).dcls; p; p = IDL_LIST (p).next) { dcl = IDL_LIST (p).data; IDL_tree_properties_copy (&node, dcl); } __IDL_free_properties (node.properties); } | struct_type | union_type | enum_type | z_props TOK_NATIVE simple_declarator { $$ = IDL_native_new ($3); assign_props (IDL_NATIVE ($$).ident, $1); } | z_props TOK_NATIVE simple_declarator '(' { /* Enable native type scanning */ if (__IDL_pidl > 0) __IDL_flagsi |= IDLFP_NATIVE; else { yyerror ("Native syntax not enabled"); YYABORT; } } TOK_NATIVE_TYPE { $$ = IDL_native_new ($3); IDL_NATIVE ($$).user_type = $6; assign_props (IDL_NATIVE ($$).ident, $1); } ; type_declarator: type_spec declarator_list { $$ = IDL_type_dcl_new ($1, $2); } ; type_spec: simple_type_spec | constr_type_spec ; simple_type_spec: base_type_spec | template_type_spec | scoped_name ; constr_type_spec: struct_type | union_type | enum_type ; z_new_ident_catch: /* empty */ { yyerrorv ("Missing identifier in %s definition", $0); YYABORT; } | new_ident ; z_new_scope_catch: /* empty */ { yyerrorv ("Missing identifier in %s definition", $0); YYABORT; } | new_scope ; struct_type: z_props TOK_STRUCT { $$ = "struct"; } z_new_scope_catch '{' { g_hash_table_insert (__IDL_structunion_ht, $4, $4); $$ = IDL_type_struct_new ($4, NULL); } member_list '}' pop_scope { g_hash_table_remove (__IDL_structunion_ht, $4); $$ = $6; __IDL_assign_up_node ($$, $7); IDL_TYPE_STRUCT ($$).member_list = $7; assign_props (IDL_TYPE_STRUCT ($$).ident, $1); } ; union_type: z_props TOK_UNION { $$ = "union"; } z_new_scope_catch TOK_SWITCH '(' switch_type_spec ')' '{' { g_hash_table_insert (__IDL_structunion_ht, $4, $4); $$ = IDL_type_union_new ($4, $7, NULL); } switch_body '}' pop_scope { g_hash_table_remove (__IDL_structunion_ht, $4); $$ = $10; __IDL_assign_up_node ($$, $11); IDL_TYPE_UNION ($$).switch_body = $11; assign_props (IDL_TYPE_UNION ($$).ident, $1); } ; switch_type_spec: integer_type | char_type | boolean_type | enum_type | scoped_name ; switch_body: case_stmt_list ; case_stmt_list: case_stmt { $$ = list_start ($1, TRUE); } | case_stmt_list case_stmt { $$ = list_chain ($1, $2, TRUE); } ; case_stmt: case_label_list element_spec check_semicolon { $$ = IDL_case_stmt_new ($1, $2); } ; element_spec: type_spec declarator { char *s; $$ = IDL_member_new ($1, list_start ($2, TRUE)); if (IDL_NODE_TYPE ($1) == IDLN_IDENT && g_hash_table_lookup (__IDL_structunion_ht, $1)) { s = IDL_ns_ident_to_qstring ($2, "::", 0); yyerrorv ("Member `%s'", s); do_token_error (IDL_NODE_UP ($1), "recurses", TRUE); g_free (s); } } ; case_label_list: case_label { $$ = list_start ($1, FALSE); } | case_label_list case_label { $$ = list_chain ($1, $2, FALSE); } ; case_label: TOK_CASE const_exp ':' { $$ = $2; } | TOK_DEFAULT ':' { $$ = NULL; } ; const_dcl: z_declspec const_dcl_def { $$ = $2; assign_declspec ($$, $1); } ; const_dcl_def: TOK_CONST const_type new_ident '=' const_exp { $$ = IDL_const_dcl_new ($2, $3, $5); /* Should probably do some type checking here... */ } ; except_dcl: z_declspec except_dcl_def { $$ = $2; assign_declspec ($$, $1); } ; except_dcl_def: TOK_EXCEPTION new_scope '{' member_zlist '}' pop_scope { $$ = IDL_except_dcl_new ($2, $4); } ; member_zlist: /* empty */ { $$ = NULL; } | member_zlist member { $$ = zlist_chain ($1, $2, TRUE); } ; is_readonly: /* empty */ { $$ = FALSE; } | TOK_READONLY { $$ = TRUE; } ; attr_dcl: z_declspec attr_dcl_def { $$ = $2; assign_declspec ($$, $1); } ; attr_dcl_def: z_props is_readonly TOK_ATTRIBUTE { $$ = "attribute"; } param_type_spec simple_declarator_list { IDL_tree_node node; IDL_tree p, dcl; $$ = IDL_attr_dcl_new ($2, $5, $6); node.properties = $1; for (p = $6; p; p = IDL_LIST (p).next) { dcl = IDL_LIST (p).data; IDL_tree_properties_copy (&node, dcl); } __IDL_free_properties (node.properties); } ; param_type_spec: op_param_type_spec | TOK_VOID { yyerrorv ("Illegal type `void' for %s", $0); $$ = NULL; } ; op_param_type_spec_illegal: sequence_type | constr_type_spec ; op_param_type_spec: base_type_spec | string_type | wide_string_type | fixed_pt_type | scoped_name | op_param_type_spec_illegal { illegal_context_type_error ($1, $0); $$ = $1; } ; is_oneway: /* empty */ { $$ = FALSE; } | TOK_ONEWAY { $$ = TRUE; } ; op_dcl: z_declspec op_dcl_def { $$ = $2; assign_declspec ($$, $1); } ; op_dcl_def: z_props is_oneway op_type_spec new_scope parameter_dcls pop_scope is_raises_expr is_context_expr { $$ = IDL_op_dcl_new ($2, $3, $4, $5.tree, $7, $8); IDL_OP_DCL ($$).f_varargs = GPOINTER_TO_INT ($5.data); assign_props (IDL_OP_DCL ($$).ident, $1); } ; op_type_spec: { $$ = "operation return value"; } op_param_type_spec { $$ = $2; } | TOK_VOID { $$ = NULL; } ; is_varargs: /* empty */ { $$ = FALSE; } | TOK_VARARGS { $$ = TRUE; } ; is_cvarargs: /* empty */ { $$ = FALSE; } | ',' TOK_VARARGS { $$ = TRUE; } ; parameter_dcls: '(' param_dcl_list is_cvarargs ')' { $$.tree = $2; $$.data = GINT_TO_POINTER ($3); } | '(' is_varargs ')' { $$.tree = NULL; $$.data = GINT_TO_POINTER ($2); } ; param_dcl_list: param_dcl { $$ = list_start ($1, TRUE); } | param_dcl_list check_comma param_dcl { $$ = list_chain ($1, $3, TRUE); } ; param_dcl: z_props param_attribute { $$ = "parameter"; } param_type_spec simple_declarator { $$ = IDL_param_dcl_new ($2, $4, $5); assign_props (IDL_PARAM_DCL ($$).simple_declarator, $1); } ; param_attribute: TOK_IN { $$ = IDL_PARAM_IN; } | TOK_OUT { $$ = IDL_PARAM_OUT; } | TOK_INOUT { $$ = IDL_PARAM_INOUT; } | param_type_spec { yyerrorv ("Missing direction attribute (in, out, inout) before parameter"); IDL_tree_free ($1); } ; is_raises_expr: /* empty */ { $$ = NULL; } | raises_expr ; is_context_expr: /* empty */ { $$ = NULL; } | context_expr ; raises_expr: TOK_RAISES '(' scoped_name_list ')' { $$ = $3; } ; context_expr: TOK_CONTEXT '(' string_lit_list ')' { $$ = $3; } ; const_type: integer_type | char_type | octet_type | wide_char_type | boolean_type | floating_pt_type | string_type | wide_string_type | fixed_pt_const_type | scoped_name ; const_exp: or_expr ; or_expr: xor_expr | or_expr '|' xor_expr { do_binop ($$, IDL_BINOP_OR, $1, $3); } ; xor_expr: and_expr | xor_expr '^' and_expr { do_binop ($$, IDL_BINOP_XOR, $1, $3); } ; and_expr: shift_expr | and_expr '&' shift_expr { do_binop ($$, IDL_BINOP_AND, $1, $3); } ; shift_expr: add_expr | shift_expr TOK_OP_SHR add_expr { do_binop ($$, IDL_BINOP_SHR, $1, $3); } | shift_expr TOK_OP_SHL add_expr { do_binop ($$, IDL_BINOP_SHL, $1, $3); } ; add_expr: mult_expr | add_expr '+' mult_expr { do_binop ($$, IDL_BINOP_ADD, $1, $3); } | add_expr '-' mult_expr { do_binop ($$, IDL_BINOP_SUB, $1, $3); } ; mult_expr: unary_expr | mult_expr '*' unary_expr { do_binop ($$, IDL_BINOP_MULT, $1, $3); } | mult_expr '/' unary_expr { do_binop ($$, IDL_BINOP_DIV, $1, $3); } | mult_expr '%' unary_expr { do_binop ($$, IDL_BINOP_MOD, $1, $3); } ; unary_expr: unary_op primary_expr { do_unaryop ($$, $1, $2); } | primary_expr ; unary_op: '-' { $$ = IDL_UNARYOP_MINUS; } | '+' { $$ = IDL_UNARYOP_PLUS; } | '~' { $$ = IDL_UNARYOP_COMPLEMENT; } ; primary_expr: scoped_name { IDL_tree p, literal; assert (IDL_NODE_TYPE ($1) == IDLN_IDENT); p = IDL_NODE_UP ($1); if ((literal = IDL_resolve_const_exp ($1, IDLN_ANY))) { ++IDL_NODE_REFS (literal); $$ = literal; IDL_tree_free ($1); } else $$ = $1; } | literal | '(' const_exp ')' { $$ = $2; } ; literal: integer_lit | string_lit | char_lit | fixed_pt_lit | floating_pt_lit | boolean_lit ; enum_type: z_props TOK_ENUM { $$ = "enum"; } z_new_ident_catch '{' enumerator_list '}' { $$ = IDL_type_enum_new ($4, $6); assign_props (IDL_TYPE_ENUM ($$).ident, $1); } ; scoped_name: ns_scoped_name { assert ($1 != NULL); assert (IDL_NODE_TYPE ($1) == IDLN_GENTREE); assert (IDL_NODE_TYPE (IDL_GENTREE ($1).data) == IDLN_IDENT); $$ = IDL_GENTREE ($1).data; } ; ns_scoped_name: ns_prev_ident | TOK_OP_SCOPE ns_global_ident { $$ = $2; } | ns_scoped_name TOK_OP_SCOPE ident { IDL_tree p; assert (IDL_NODE_TYPE ($1) == IDLN_GENTREE); assert (IDL_NODE_TYPE ($3) == IDLN_IDENT); #ifdef YYDEBUG if (yydebug) fprintf (stderr, "ns: looking in `%s' for `%s'\n", IDL_IDENT (IDL_GENTREE ($1).data).str, IDL_IDENT($3).str); #endif if ((p = IDL_ns_lookup_this_scope (__IDL_root_ns, $1, $3, NULL)) == NULL) { yyerrorv ("`%s' undeclared identifier", IDL_IDENT ($3).str); IDL_tree_free ($3); YYABORT; } IDL_tree_free ($3); #ifdef REF_IDENTS ++IDL_NODE_REFS (IDL_GENTREE (p).data); #endif $$ = p; } ; enumerator_list: new_ident { $$ = list_start ($1, TRUE); } | enumerator_list check_comma new_ident { $$ = list_chain ($1, $3, TRUE); } ; member_list: member { $$ = list_start ($1, TRUE); } | member_list member { $$ = list_chain ($1, $2, TRUE); } ; member: type_spec declarator_list check_semicolon { char *s; $$ = IDL_member_new ($1, $2); if (IDL_NODE_TYPE ($1) == IDLN_IDENT && g_hash_table_lookup (__IDL_structunion_ht, $1)) { s = IDL_ns_ident_to_qstring (IDL_LIST ($2).data, "::", 0); yyerrorv ("Member `%s'", s); do_token_error (IDL_NODE_UP ($1), "recurses", TRUE); g_free (s); } } ; base_type_spec: floating_pt_type | integer_type | char_type | wide_char_type | boolean_type | octet_type | any_type | object_type | typecode_type ; template_type_spec: sequence_type | string_type | wide_string_type | fixed_pt_type ; sequence_type: TOK_SEQUENCE '<' simple_type_spec ',' positive_int_const '>' { $$ = IDL_type_sequence_new ($3, $5); } | TOK_SEQUENCE '<' simple_type_spec '>' { $$ = IDL_type_sequence_new ($3, NULL); } ; floating_pt_type: TOK_FLOAT { $$ = IDL_type_float_new (IDL_FLOAT_TYPE_FLOAT); } | TOK_DOUBLE { $$ = IDL_type_float_new (IDL_FLOAT_TYPE_DOUBLE); } | TOK_LONG TOK_DOUBLE { $$ = IDL_type_float_new (IDL_FLOAT_TYPE_LONGDOUBLE); } ; fixed_pt_type: TOK_FIXED '<' positive_int_const ',' integer_lit '>' { $$ = IDL_type_fixed_new ($3, $5); } ; fixed_pt_const_type: TOK_FIXED { $$ = IDL_type_fixed_new (NULL, NULL); } ; integer_type: signed_int { $$ = IDL_type_integer_new (TRUE, $1); } | unsigned_int { $$ = IDL_type_integer_new (FALSE, $1); } ; signed_int: signed_short_int { $$ = IDL_INTEGER_TYPE_SHORT; } | signed_long_int { $$ = IDL_INTEGER_TYPE_LONG; } | signed_longlong_int { $$ = IDL_INTEGER_TYPE_LONGLONG; } ; signed_short_int: TOK_SHORT ; signed_long_int: TOK_LONG ; signed_longlong_int: TOK_LONG TOK_LONG ; unsigned_int: unsigned_short_int { $$ = IDL_INTEGER_TYPE_SHORT; } | unsigned_long_int { $$ = IDL_INTEGER_TYPE_LONG; } | unsigned_longlong_int { $$ = IDL_INTEGER_TYPE_LONGLONG; } ; unsigned_short_int: TOK_UNSIGNED TOK_SHORT ; unsigned_long_int: TOK_UNSIGNED TOK_LONG ; unsigned_longlong_int: TOK_UNSIGNED TOK_LONG TOK_LONG ; char_type: TOK_CHAR { $$ = IDL_type_char_new (); } ; wide_char_type: TOK_WCHAR { $$ = IDL_type_wide_char_new (); } ; boolean_type: TOK_BOOLEAN { $$ = IDL_type_boolean_new (); } ; octet_type: TOK_OCTET { $$ = IDL_type_octet_new (); } ; any_type: TOK_ANY { $$ = IDL_type_any_new (); } ; object_type: TOK_OBJECT { $$ = IDL_type_object_new (); } ; typecode_type: TOK_TYPECODE { $$ = IDL_type_typecode_new (); } ; string_type: TOK_STRING '<' positive_int_const '>' { $$ = IDL_type_string_new ($3); } | TOK_STRING { $$ = IDL_type_string_new (NULL); } ; wide_string_type: TOK_WSTRING '<' positive_int_const '>' { $$ = IDL_type_wide_string_new ($3); } | TOK_WSTRING { $$ = IDL_type_wide_string_new (NULL); } ; declarator_list: declarator { $$ = list_start ($1, TRUE); } | declarator_list check_comma declarator { $$ = list_chain ($1, $3, TRUE); } ; declarator: simple_declarator | complex_declarator ; simple_declarator: new_ident ; complex_declarator: array_declarator ; simple_declarator_list: simple_declarator { $$ = list_start ($1, TRUE); } | simple_declarator_list check_comma simple_declarator { $$ = list_chain ($1, $3, TRUE); } ; array_declarator: new_ident fixed_array_size_list { IDL_tree p; int i; $$ = IDL_type_array_new ($1, $2); for (i = 1, p = $2; p; ++i, p = IDL_LIST (p).next) if (!IDL_LIST (p).data) { char *s = IDL_ns_ident_to_qstring ($1, "::", 0); yyerrorv ("Missing value in dimension %d of array `%s'", i, s); g_free (s); } } ; fixed_array_size_list: fixed_array_size { $$ = list_start ($1, FALSE); } | fixed_array_size_list fixed_array_size { $$ = list_chain ($1, $2, FALSE); } ; fixed_array_size: '[' positive_int_const ']' { $$ = $2; } | '[' ']' { $$ = NULL; } ; prop_hash: TOK_PROP_KEY TOK_PROP_VALUE { $$ = g_hash_table_new (IDL_strcase_hash, IDL_strcase_equal); g_hash_table_insert ($$, $1, $2); } | prop_hash ',' TOK_PROP_KEY TOK_PROP_VALUE { $$ = $1; g_hash_table_insert ($$, $3, $4); } | TOK_PROP_KEY { $$ = g_hash_table_new (IDL_strcase_hash, IDL_strcase_equal); g_hash_table_insert ($$, $1, g_strdup ("")); } | prop_hash ',' TOK_PROP_KEY { $$ = $1; g_hash_table_insert ($$, $3, g_strdup ("")); } ; ident: TOK_IDENT { $$ = IDL_ident_new ($1); } ; new_ident: ns_new_ident { assert ($1 != NULL); assert (IDL_NODE_TYPE ($1) == IDLN_GENTREE); assert (IDL_NODE_TYPE (IDL_GENTREE ($1).data) == IDLN_IDENT); $$ = IDL_GENTREE ($1).data; } ; new_scope: ns_new_ident { IDL_tree old_top = IDL_GENTREE (IDL_NS (__IDL_root_ns).current).data; IDL_ns_push_scope (__IDL_root_ns, $1); #ifdef YYDEBUG if (yydebug) fprintf (stderr, "ns: entering new scope `%s' of `%s'\n", IDL_IDENT (IDL_GENTREE (IDL_NS (__IDL_root_ns).current).data).str, IDL_IDENT(old_top).str); #endif assert (IDL_NODE_TYPE (IDL_GENTREE ($1).data) == IDLN_IDENT); $$ = IDL_GENTREE ($1).data; } ; new_or_prev_scope: cur_ns_new_or_prev_ident { IDL_tree old_top = IDL_GENTREE (IDL_NS (__IDL_root_ns).current).data; IDL_ns_push_scope (__IDL_root_ns, $1); assert (IDL_NS (__IDL_root_ns).current != NULL); assert (IDL_NODE_TYPE (IDL_NS (__IDL_root_ns).current) == IDLN_GENTREE); assert (IDL_GENTREE (IDL_NS (__IDL_root_ns).current).data != NULL); assert (IDL_NODE_TYPE (IDL_GENTREE (IDL_NS (__IDL_root_ns).current).data) == IDLN_IDENT); #ifdef YYDEBUG if (yydebug) fprintf (stderr,"ns: entering new/prev scope `%s' of `%s'\n", IDL_IDENT (IDL_GENTREE (IDL_NS (__IDL_root_ns).current).data).str, IDL_IDENT(old_top).str); #endif assert (IDL_NODE_TYPE (IDL_GENTREE ($1).data) == IDLN_IDENT); $$ = IDL_GENTREE ($1).data; } ; pop_scope: /* empty */ { IDL_tree cur_top = IDL_GENTREE (IDL_NS (__IDL_root_ns).current).data; IDL_ns_pop_scope (__IDL_root_ns); #ifdef YYDEBUG if (yydebug) fprintf (stderr, "ns: pop scope from `%s' to `%s'\n", IDL_IDENT(cur_top).str, IDL_IDENT (IDL_GENTREE (IDL_NS (__IDL_root_ns).current).data).str); #endif } ; ns_new_ident: ident { IDL_tree p; if ((p = IDL_ns_place_new (__IDL_root_ns, $1)) == NULL) { IDL_tree q; int i; p = IDL_ns_lookup_cur_scope (__IDL_root_ns, $1, NULL); for (i = 0, q = IDL_GENTREE (p).data; q && (IDL_NODE_TYPE (q) == IDLN_IDENT || IDL_NODE_TYPE (q) == IDLN_LIST) && i < 4; ++i) if (IDL_NODE_UP (q)) q = IDL_NODE_UP (q); if (q) { IDL_tree_error ($1, "`%s' conflicts", IDL_IDENT ($1).str); do_token_error (q, "with", FALSE); } else yyerrorv ("`%s' duplicate identifier", IDL_IDENT ($1).str); IDL_tree_free ($1); YYABORT; } assert (IDL_IDENT ($1)._ns_ref == p); #ifdef REF_IDENTS ++IDL_NODE_REFS (IDL_GENTREE (p).data); #endif if (__IDL_new_ident_comments != NULL) { assert (IDL_IDENT ($1).comments == NULL); IDL_IDENT ($1).comments = __IDL_new_ident_comments; __IDL_new_ident_comments = NULL; } $$ = p; } ; ns_prev_ident: ident { IDL_tree p; if ((p = IDL_ns_resolve_ident (__IDL_root_ns, $1)) == NULL) { yyerrorv ("`%s' undeclared identifier", IDL_IDENT ($1).str); IDL_tree_free ($1); YYABORT; } IDL_tree_free ($1); assert (IDL_GENTREE (p).data != NULL); assert (IDL_IDENT (IDL_GENTREE (p).data)._ns_ref == p); #ifdef REF_IDENTS ++IDL_NODE_REFS (IDL_GENTREE (p).data); #endif $$ = p; } ; cur_ns_new_or_prev_ident: ident { IDL_tree p; if ((p = IDL_ns_lookup_cur_scope (__IDL_root_ns, $1, NULL)) == NULL) { #ifdef YYDEBUG if (yydebug) fprintf (stderr, "ns: place_new `%s' in `%s'\n", IDL_IDENT($1).str, IDL_IDENT(IDL_GENTREE (IDL_NS (__IDL_root_ns).current).data).str ); #endif p = IDL_ns_place_new (__IDL_root_ns, $1); assert (p != NULL); assert (IDL_IDENT ($1)._ns_ref == p); if (__IDL_new_ident_comments != NULL) { assert (IDL_IDENT ($1).comments == NULL); IDL_IDENT ($1).comments = __IDL_new_ident_comments; __IDL_new_ident_comments = NULL; } } else { IDL_tree_free ($1); assert (IDL_GENTREE (p).data != NULL); assert (IDL_IDENT (IDL_GENTREE (p).data)._ns_ref == p); } #ifdef REF_IDENTS ++IDL_NODE_REFS (IDL_GENTREE (p).data); #endif $$ = p; } ; ns_global_ident: ident { IDL_tree p; if ((p = IDL_ns_lookup_this_scope ( __IDL_root_ns,IDL_NS (__IDL_root_ns).file, $1, NULL)) == NULL) { yyerrorv ("`%s' undeclared identifier", IDL_IDENT ($1).str); IDL_tree_free ($1); YYABORT; } IDL_tree_free ($1); assert (IDL_GENTREE (p).data != NULL); assert (IDL_IDENT (IDL_GENTREE (p).data)._ns_ref == p); #ifdef REF_IDENTS ++IDL_NODE_REFS (IDL_GENTREE (p).data); #endif $$ = p; } ; string_lit_list: string_lit { $$ = list_start ($1, TRUE); } | string_lit_list check_comma string_lit { $$ = list_chain ($1, $3, TRUE); } ; positive_int_const: const_exp { IDL_tree literal, ident = NULL; IDL_longlong_t value = 0; if ((literal = IDL_resolve_const_exp ($1, IDLN_INTEGER))) { assert (IDL_NODE_TYPE (literal) == IDLN_INTEGER); ++IDL_NODE_REFS (literal); value = IDL_INTEGER (literal).value; if ( literal != $1 ) IDL_tree_free ($1); } if (literal && IDL_NODE_UP (literal) && IDL_NODE_TYPE (IDL_NODE_UP (literal)) == IDLN_CONST_DCL) ident = IDL_CONST_DCL (IDL_NODE_UP (literal)).ident; if (literal == NULL) { if (!(__IDL_flags & IDLF_NO_EVAL_CONST)) yyerror ("Could not resolve constant expression"); $$ = $1; } else if (value == 0) { yyerror ("Zero array size is illegal"); if (ident) IDL_tree_error (ident, "From constant declared here"); $$ = NULL; } else if (value < 0) { yywarningv (IDL_WARNING1, "Cannot use negative value %" IDL_LL "d, using %" IDL_LL "d", value, -value); if (ident) IDL_tree_warning (ident, IDL_WARNING1, "From constant declared here"); $$ = IDL_integer_new (-value); } else $$ = IDL_integer_new (value); } ; z_declspec: /* empty */ { $$ = 0; } | TOK_DECLSPEC { $$ = IDL_parse_declspec ($1); g_free ($1); } ; z_props: /* empty */ { $$ = NULL; } | '[' { /* Enable property scanning */ if (__IDL_flags & IDLF_PROPERTIES) __IDL_flagsi |= IDLFP_PROPERTIES; else { yyerror ("Property syntax not enabled"); YYABORT; } } prop_hash ']' { $$ = $3; } ; integer_lit: TOK_INTEGER { $$ = IDL_integer_new ($1); } ; string_lit: dqstring_cat { $$ = IDL_string_new ($1); } ; char_lit: sqstring { $$ = IDL_char_new ($1); } ; fixed_pt_lit: TOK_FIXEDP { $$ = IDL_fixed_new ($1); } ; floating_pt_lit: TOK_FLOATP { $$ = IDL_float_new ($1); } ; boolean_lit: TOK_TRUE { $$ = IDL_boolean_new (TRUE); } | TOK_FALSE { $$ = IDL_boolean_new (FALSE); } ; codefrag: z_declspec TOK_CODEFRAG { $$ = $2; assign_declspec ($$, $1); } ; srcfile: TOK_SRCFILE { $$ = $1; } ; dqstring_cat: dqstring | dqstring_cat dqstring { char *catstr = g_malloc (strlen ($1) + strlen ($2) + 1); strcpy (catstr, $1); g_free ($1); strcat (catstr, $2); g_free ($2); $$ = catstr; } ; dqstring: TOK_DQSTRING { char *s = IDL_do_escapes ($1); g_free ($1); $$ = s; } ; sqstring: TOK_SQSTRING { char *s = IDL_do_escapes ($1); g_free ($1); $$ = s; } ; %% void __IDL_parser_reset (void) { yyclearin; } static const char *IDL_ns_get_cur_prefix (IDL_ns ns) { IDL_tree p; p = IDL_NS (ns).current; assert (p != NULL); while (p && !IDL_GENTREE (p)._cur_prefix) p = IDL_NODE_UP (p); return p ? IDL_GENTREE (p)._cur_prefix : NULL; } gchar *IDL_ns_ident_make_repo_id (IDL_ns ns, IDL_tree p, const char *p_prefix, int *major, int *minor) { GString *s = g_string_new (NULL); const char *prefix; char *q; assert (p != NULL); if (IDL_NODE_TYPE (p) == IDLN_IDENT) p = IDL_IDENT_TO_NS (p); assert (p != NULL); prefix = p_prefix ? p_prefix : IDL_ns_get_cur_prefix (ns); q = IDL_ns_ident_to_qstring (p, "/", 0); g_string_printf (s, "IDL:%s%s%s:%d.%d", prefix ? prefix : "", prefix && *prefix ? "/" : "", q, major ? *major : 1, minor ? *minor : 0); g_free (q); q = s->str; g_string_free (s, FALSE); return q; } static const char *get_name_token (const char *s, char **tok) { const char *begin = s; int state = 0; if (!s) return NULL; while (g_ascii_isspace (*s)) ++s; while (1) switch (state) { case 0: /* Unknown */ if (*s == ':') state = 1; else if (isalnum ((int)*s) || *s == '_') { begin = s; state = 2; } else return NULL; break; case 1: /* Scope */ if (strncmp (s, "::", 2) == 0) { char *r = g_malloc (3); strcpy (r, "::"); *tok = r; return s + 2; } else /* Invalid */ return NULL; break; case 2: if (isalnum ((int)*s) || *s == '_') ++s; else { char *r = g_malloc (s - begin + 1); strncpy (r, begin, s - begin + 1); r[s - begin] = 0; *tok = r; return s; } break; } } static IDL_tree IDL_ns_pragma_parse_name (IDL_ns ns, const char *s) { IDL_tree p = IDL_NS (ns).current, q; int start = 1; char *tok; /* This is a hack to allow directives for an ident (such * as and interface) to be located within the scope of * that identifier. */ if ( p && (q=IDL_GENTREE(p).data)!=0 && IDL_NODE_TYPE(q)==IDLN_IDENT && strcmp(s,IDL_IDENT(q).str)==0 ) { return p; } while (p && *s && (s = get_name_token (s, &tok))) { if (tok == NULL) return NULL; if (strcmp (tok, "::") == 0) { if (start) { /* Globally scoped */ p = IDL_NS (ns).file; } g_free (tok); } else { IDL_tree ident = IDL_ident_new (tok); p = IDL_ns_lookup_this_scope (__IDL_root_ns, p, ident, NULL); IDL_tree_free (ident); } start = 0; } return p; } void IDL_ns_ID (IDL_ns ns, const char *s) { char name[1024], id[1024]; IDL_tree p, ident; int n; n = sscanf (s, "%1023s \"%1023s\"", name, id); if (n < 2 && __IDL_is_parsing) { yywarning (IDL_WARNING1, "Malformed pragma ID"); return; } if (id[strlen (id) - 1] == '"') id[strlen (id) - 1] = 0; p = IDL_ns_pragma_parse_name (__IDL_root_ns, name); if (!p && __IDL_is_parsing) { yywarningv (IDL_WARNING1, "Unknown identifier `%s' in pragma ID", name); return; } /* We have resolved the identifier, so assign the repo id */ assert (IDL_NODE_TYPE (p) == IDLN_GENTREE); assert (IDL_GENTREE (p).data != NULL); assert (IDL_NODE_TYPE (IDL_GENTREE (p).data) == IDLN_IDENT); ident = IDL_GENTREE (p).data; if (IDL_IDENT_REPO_ID (ident) != NULL) g_free (IDL_IDENT_REPO_ID (ident)); IDL_IDENT_REPO_ID (ident) = g_strdup (id); } void IDL_ns_version (IDL_ns ns, const char *s) { char name[1024]; int n, major, minor; IDL_tree p, ident; n = sscanf (s, "%1023s %u.%u", name, &major, &minor); if (n < 3 && __IDL_is_parsing) { yywarning (IDL_WARNING1, "Malformed pragma version"); return; } p = IDL_ns_pragma_parse_name (__IDL_root_ns, name); if (!p && __IDL_is_parsing) { yywarningv (IDL_WARNING1, "Unknown identifier `%s' in pragma version", name); return; } /* We have resolved the identifier, so assign the repo id */ assert (IDL_NODE_TYPE (p) == IDLN_GENTREE); assert (IDL_GENTREE (p).data != NULL); assert (IDL_NODE_TYPE (IDL_GENTREE (p).data) == IDLN_IDENT); ident = IDL_GENTREE (p).data; if (IDL_IDENT_REPO_ID (ident) != NULL) { char *v = strrchr (IDL_IDENT_REPO_ID (ident), ':'); if (v) { GString *s; *v = 0; s = g_string_new (NULL); g_string_printf (s, "%s:%d.%d", IDL_IDENT_REPO_ID (ident), major, minor); g_free (IDL_IDENT_REPO_ID (ident)); IDL_IDENT_REPO_ID (ident) = s->str; g_string_free (s, FALSE); } else if (__IDL_is_parsing) yywarningv (IDL_WARNING1, "Cannot find RepositoryID OMG IDL version in ID `%s'", IDL_IDENT_REPO_ID (ident)); } else IDL_IDENT_REPO_ID (ident) = IDL_ns_ident_make_repo_id ( __IDL_root_ns, p, NULL, &major, &minor); } int IDL_inhibit_get (void) { g_return_val_if_fail (__IDL_is_parsing, -1); return __IDL_inhibits; } void IDL_inhibit_push (void) { g_return_if_fail (__IDL_is_parsing); ++__IDL_inhibits; } void IDL_inhibit_pop (void) { g_return_if_fail (__IDL_is_parsing); if (--__IDL_inhibits < 0) __IDL_inhibits = 0; } static void IDL_inhibit (IDL_ns ns, const char *s) { if (g_ascii_strcasecmp ("push", s) == 0) IDL_inhibit_push (); else if (g_ascii_strcasecmp ("pop", s) == 0) IDL_inhibit_pop (); } static void IDL_typecodes_as_tok (IDL_ns ns, const char *s) { if (g_ascii_strcasecmp ("push", s) == 0) ++(__IDL_typecodes_as_tok); else if (g_ascii_strcasecmp ("pop", s) == 0) --(__IDL_typecodes_as_tok); } static void IDL_pidl (IDL_ns ns, const char *s) { if (g_ascii_strcasecmp ("push", s) == 0) ++(__IDL_pidl); else if (g_ascii_strcasecmp ("pop", s) == 0) --(__IDL_pidl); } void __IDL_do_pragma (const char *s) { int n; char directive[256]; g_return_if_fail (__IDL_is_parsing); g_return_if_fail (s != NULL); if (sscanf (s, "%255s%n", directive, &n) < 1) return; s += n; while (g_ascii_isspace (*s)) ++s; if (strcmp (directive, "prefix") == 0) IDL_ns_prefix (__IDL_root_ns, s); else if (strcmp (directive, "ID") == 0) IDL_ns_ID (__IDL_root_ns, s); else if (strcmp (directive, "version") == 0) IDL_ns_version (__IDL_root_ns, s); else if (strcmp (directive, "inhibit") == 0) IDL_inhibit (__IDL_root_ns, s); else if (strcmp (directive, "typecodes_as_tok") == 0) IDL_typecodes_as_tok (__IDL_root_ns, s); else if (strcmp (directive, "pidl") == 0) IDL_pidl (__IDL_root_ns, s); } static IDL_declspec_t IDL_parse_declspec (const char *strspec) { IDL_declspec_t flags = IDLF_DECLSPEC_EXIST; if (strspec == NULL) return flags; if (strcmp (strspec, "inhibit") == 0) flags |= IDLF_DECLSPEC_INHIBIT; if (strcmp (strspec, "pidl") == 0) flags |= IDLF_DECLSPEC_PIDL; else if (__IDL_is_parsing) yywarningv (IDL_WARNING1, "Ignoring unknown declspec `%s'", strspec); return flags; } IDL_tree IDL_file_set (const char *filename, int line) { IDL_fileinfo *fi; IDL_tree tree = NULL; g_return_val_if_fail (__IDL_is_parsing, NULL); if (filename) { const char *oldfilename = __IDL_cur_filename; gboolean wasInhibit = IS_INHIBIT_STATE(); gboolean isTop = #ifdef HAVE_CPP_PIPE_STDIN strlen (filename)==0; #else __IDL_tmp_filename && strcmp (filename, __IDL_tmp_filename)==0; #endif if ( isTop ) { filename = __IDL_real_filename; __IDL_flagsi &= ~IDLFP_IN_INCLUDES; } else { __IDL_flagsi |= IDLFP_IN_INCLUDES; } if ((fi=g_hash_table_lookup(__IDL_filename_hash, filename)) ) { __IDL_cur_fileinfo = fi; ++(fi->seenCnt); } else { fi = g_new0 (IDL_fileinfo, 1); fi->name = g_strdup(filename); g_hash_table_insert (__IDL_filename_hash, fi->name, fi); } __IDL_cur_fileinfo = fi; __IDL_cur_filename = fi->name; if ( (__IDL_flags & IDLF_SRCFILES)!=0 && (oldfilename==0 || strcmp(oldfilename,fi->name)!=0) ) { tree = IDL_srcfile_new(fi->name, fi->seenCnt, isTop, wasInhibit); } } if (__IDL_cur_line > 0) __IDL_cur_line = line; return tree; } void IDL_file_get (const char **filename, int *line) { g_return_if_fail (__IDL_is_parsing); if (filename) *filename = __IDL_cur_filename; if (line) *line = __IDL_cur_line; } static int do_token_error (IDL_tree p, const char *message, gboolean prev) { int dienow; char *what = NULL, *who = NULL; assert (p != NULL); dienow = IDL_tree_get_node_info (p, &what, &who); assert (what != NULL); if (who && *who) IDL_tree_error (p, "%s %s `%s'", message, what, who); else IDL_tree_error (p, "%s %s", message, what); return dienow; } static void illegal_context_type_error (IDL_tree p, const char *what) { GString *s = g_string_new (NULL); g_string_printf (s, "Illegal type `%%s' for %s", what); illegal_type_error (p, s->str); g_string_free (s, TRUE); } static void illegal_type_error (IDL_tree p, const char *message) { GString *s; s = IDL_tree_to_IDL_string (p, NULL, IDLF_OUTPUT_NO_NEWLINES); yyerrorv (message, s->str); g_string_free (s, TRUE); } static IDL_tree list_start (IDL_tree a, gboolean filter_null) { IDL_tree p; if (!a && filter_null) return NULL; p = IDL_list_new (a); return p; } static IDL_tree list_chain (IDL_tree a, IDL_tree b, gboolean filter_null) { IDL_tree p; if (filter_null) { if (!b) return a; if (!a) return list_start (b, filter_null); } p = IDL_list_new (b); a = IDL_list_concat (a, p); return a; } static IDL_tree zlist_chain (IDL_tree a, IDL_tree b, gboolean filter_null) { if (a == NULL) return list_start (b, filter_null); else return list_chain (a, b, filter_null); } static int IDL_binop_chktypes (enum IDL_binop op, IDL_tree a, IDL_tree b) { if (IDL_NODE_TYPE (a) != IDLN_BINOP && IDL_NODE_TYPE (b) != IDLN_BINOP && IDL_NODE_TYPE (a) != IDLN_UNARYOP && IDL_NODE_TYPE (b) != IDLN_UNARYOP && IDL_NODE_TYPE (a) != IDL_NODE_TYPE (b)) { yyerror ("Invalid mix of types in constant expression"); return -1; } switch (op) { case IDL_BINOP_MULT: case IDL_BINOP_DIV: case IDL_BINOP_ADD: case IDL_BINOP_SUB: break; case IDL_BINOP_MOD: case IDL_BINOP_SHR: case IDL_BINOP_SHL: case IDL_BINOP_AND: case IDL_BINOP_OR: case IDL_BINOP_XOR: if ((IDL_NODE_TYPE (a) != IDLN_INTEGER || IDL_NODE_TYPE (b) != IDLN_INTEGER) && !(IDL_NODE_TYPE (a) == IDLN_BINOP || IDL_NODE_TYPE (b) == IDLN_BINOP || IDL_NODE_TYPE (a) == IDLN_UNARYOP || IDL_NODE_TYPE (b) == IDLN_UNARYOP)) { yyerror ("Invalid operation on non-integer value"); return -1; } break; } return 0; } static int IDL_unaryop_chktypes (enum IDL_unaryop op, IDL_tree a) { switch (op) { case IDL_UNARYOP_PLUS: case IDL_UNARYOP_MINUS: break; case IDL_UNARYOP_COMPLEMENT: if (IDL_NODE_TYPE (a) != IDLN_INTEGER && !(IDL_NODE_TYPE (a) == IDLN_BINOP || IDL_NODE_TYPE (a) == IDLN_UNARYOP)) { yyerror ("Operand to complement must be integer"); return -1; } break; } return 0; } static IDL_tree IDL_binop_eval_integer (enum IDL_binop op, IDL_tree a, IDL_tree b) { IDL_tree p = NULL; assert (IDL_NODE_TYPE (a) == IDLN_INTEGER); switch (op) { case IDL_BINOP_MULT: p = IDL_integer_new (IDL_INTEGER (a).value * IDL_INTEGER (b).value); break; case IDL_BINOP_DIV: if (IDL_INTEGER (b).value == 0) { yyerror ("Divide by zero in constant expression"); return NULL; } p = IDL_integer_new (IDL_INTEGER (a).value / IDL_INTEGER (b).value); break; case IDL_BINOP_ADD: p = IDL_integer_new (IDL_INTEGER (a).value + IDL_INTEGER (b).value); break; case IDL_BINOP_SUB: p = IDL_integer_new (IDL_INTEGER (a).value - IDL_INTEGER (b).value); break; case IDL_BINOP_MOD: if (IDL_INTEGER (b).value == 0) { yyerror ("Modulo by zero in constant expression"); return NULL; } p = IDL_integer_new (IDL_INTEGER (a).value % IDL_INTEGER (b).value); break; case IDL_BINOP_SHR: p = IDL_integer_new (IDL_INTEGER (a).value >> IDL_INTEGER (b).value); break; case IDL_BINOP_SHL: p = IDL_integer_new (IDL_INTEGER (a).value << IDL_INTEGER (b).value); break; case IDL_BINOP_AND: p = IDL_integer_new (IDL_INTEGER (a).value & IDL_INTEGER (b).value); break; case IDL_BINOP_OR: p = IDL_integer_new (IDL_INTEGER (a).value | IDL_INTEGER (b).value); break; case IDL_BINOP_XOR: p = IDL_integer_new (IDL_INTEGER (a).value ^ IDL_INTEGER (b).value); break; } return p; } static IDL_tree IDL_binop_eval_float (enum IDL_binop op, IDL_tree a, IDL_tree b) { IDL_tree p = NULL; assert (IDL_NODE_TYPE (a) == IDLN_FLOAT); switch (op) { case IDL_BINOP_MULT: p = IDL_float_new (IDL_FLOAT (a).value * IDL_FLOAT (b).value); break; case IDL_BINOP_DIV: if (IDL_FLOAT (b).value == 0.0) { yyerror ("Divide by zero in constant expression"); return NULL; } p = IDL_float_new (IDL_FLOAT (a).value / IDL_FLOAT (b).value); break; case IDL_BINOP_ADD: p = IDL_float_new (IDL_FLOAT (a).value + IDL_FLOAT (b).value); break; case IDL_BINOP_SUB: p = IDL_float_new (IDL_FLOAT (a).value - IDL_FLOAT (b).value); break; default: break; } return p; } static IDL_tree IDL_binop_eval (enum IDL_binop op, IDL_tree a, IDL_tree b) { assert (IDL_NODE_TYPE (a) == IDL_NODE_TYPE (b)); switch (IDL_NODE_TYPE (a)) { case IDLN_INTEGER: return IDL_binop_eval_integer (op, a, b); case IDLN_FLOAT: return IDL_binop_eval_float (op, a, b); default: return NULL; } } static IDL_tree IDL_unaryop_eval_integer (enum IDL_unaryop op, IDL_tree a) { IDL_tree p = NULL; assert (IDL_NODE_TYPE (a) == IDLN_INTEGER); switch (op) { case IDL_UNARYOP_PLUS: p = IDL_integer_new (IDL_INTEGER (a).value); break; case IDL_UNARYOP_MINUS: p = IDL_integer_new (-IDL_INTEGER (a).value); break; case IDL_UNARYOP_COMPLEMENT: p = IDL_integer_new (~IDL_INTEGER (a).value); break; } return p; } static IDL_tree IDL_unaryop_eval_fixed (enum IDL_unaryop op, IDL_tree a) { IDL_tree p = NULL; assert (IDL_NODE_TYPE (a) == IDLN_FIXED); switch (op) { case IDL_UNARYOP_PLUS: p = IDL_fixed_new (IDL_FIXED (a).value); break; default: break; } return p; } static IDL_tree IDL_unaryop_eval_float (enum IDL_unaryop op, IDL_tree a) { IDL_tree p = NULL; assert (IDL_NODE_TYPE (a) == IDLN_FLOAT); switch (op) { case IDL_UNARYOP_PLUS: p = IDL_float_new (IDL_FLOAT (a).value); break; case IDL_UNARYOP_MINUS: p = IDL_float_new (-IDL_FLOAT (a).value); break; default: break; } return p; } static IDL_tree IDL_unaryop_eval (enum IDL_unaryop op, IDL_tree a) { switch (IDL_NODE_TYPE (a)) { case IDLN_INTEGER: return IDL_unaryop_eval_integer (op, a); case IDLN_FIXED: return IDL_unaryop_eval_fixed (op, a); case IDLN_FLOAT: return IDL_unaryop_eval_float (op, a); default: return NULL; } } IDL_tree IDL_resolve_const_exp (IDL_tree p, IDL_tree_type type) { gboolean resolved_value = FALSE, die = FALSE; gboolean wrong_type = FALSE; while (!resolved_value && !die) { if (IDL_NODE_TYPE (p) == IDLN_IDENT) { IDL_tree q = IDL_NODE_UP (p); assert (q != NULL); if (IDL_NODE_UP (q) && IDL_NODE_TYPE (IDL_NODE_UP (q)) == IDLN_TYPE_ENUM) { p = q; die = TRUE; break; } else if (IDL_NODE_TYPE (q) != IDLN_CONST_DCL) { p = q; wrong_type = TRUE; die = TRUE; } else p = IDL_CONST_DCL (q).const_exp; } if (p == NULL || IDL_NODE_TYPE (p) == IDLN_BINOP || IDL_NODE_TYPE (p) == IDLN_UNARYOP) { die = TRUE; continue; } resolved_value = IDL_NODE_IS_LITERAL (p); } if (resolved_value && type != IDLN_ANY && IDL_NODE_TYPE (p) != type) wrong_type = TRUE; if (wrong_type) { yyerror ("Invalid type for constant"); IDL_tree_error (p, "Previous resolved type declaration"); return NULL; } return resolved_value ? p : NULL; } void IDL_queue_new_ident_comment (const char *str) { g_return_if_fail (str != NULL); __IDL_new_ident_comments = g_slist_append (__IDL_new_ident_comments, g_strdup (str)); } /* * Local variables: * mode: C * c-basic-offset: 8 * tab-width: 8 * indent-tabs-mode: t * End: */