Newsgroups: comp.sources.unix From: pleierc@informatik.tu-muenchen.de (Christoph Pleier) Subject: v27i190: distributed-c-2.1 - Distributed C Development Environment, V2.1, Part16/18 References: <1.756634932.28500@gw.home.vix.com> Sender: unix-sources-moderator@gw.home.vix.com Approved: vixie@gw.home.vix.com Submitted-By: pleierc@informatik.tu-muenchen.de (Christoph Pleier) Posting-Number: Volume 27, Issue 190 Archive-Name: distributed-c-2.1/part16 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'dcc/dcc.y' <<'END_OF_FILE' X/*************************************************************************** X * * X * @@@@ @@@ @@@@@ @@@@@ @@@@@ @@@ @@@@ @ @ @@@@@ @@@@@ @@@@ @@@ * X * @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ * X * @ @ @ @@@@@ @ @@@@@ @ @@@@@ @ @ @ @@@@@ @ @ @ * X * @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ * X * @@@@ @@@ @@@@@ @ @ @ @@@ @@@@ @@@@@ @ @@@@@ @@@@ @@@ * X * * X * A compiler for distributed programming with C * X * * X * d c c . y * X * * X * Package : Compiler * X * Version : 1.4 * X * CreationDate : 05.07.90 * X * LastUpDate : 18.10.93 * X * * X * The YACC - grammar for Distributed C. * X * * X * Portions Copyright 1990 Franz Distler * X * Copyright (C) 1990-1994 by Christoph Pleier * X * All rights reserved! * X ***************************************************************************/ X X/* X * This file is part of the Distributed C Development Environment (DCDE). X * DCDE is free software; you can redistribute it and/or modify X * it under the terms written in the README-file. X * DCDE is distributed in the hope that it will be useful, X * but WITHOUT ANY WARRANTY; without even the implied warranty of X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. X * See the file README for more details. X */ X X%{ X#include X#include X#include "config.h" X#include "extern.h" X#include "functions.h" X#include "com_Errno.h" X X#define DECERRFLAG if (errflag) \ X --errflag X%} X X/* X * the type of the value stack X */ X X%union { X int y_int; /* an integer value */ X SYMBTABEL *y_symb; /* a symbol table entry */ X char *y_str; /* a string */ X ARG_LIST *y_arg; /* an argument expression list */ X POSTATTR *y_post; /* a postfix expression attribute */ X COMPATTR *y_comp; /* a compound statement attribute */ X ACCEPTATTR *y_accept; /* an accept statement attribute */ X SELECTATTR *y_select; /* a select statement attribute */ X TRANSATTR *y_trans; /* a transaction_call attribute */ X DS_ATTR *y_ds; /* a declaration specifiers attribute */ X SUS_ATTR *y_sus; /* a struct or union specifier attribute */ X SCS_ATTR *y_scs; /* a storage class specifier attribute */ X TS_ATTR *y_ts; /* a type specifier attribute */ X TQ_ATTR *y_tq; /* a type qualifier attribute */ X SU_ATTR *y_su; /* a struct or union attribute */ X SD_ATTR *y_sd; /* a struct declarator attribute */ X ST_ATTR *y_st; /* a struct declaration attribute */ X SQL_ATTR *y_sql; /* a specifier qualifier list attribute */ X SDL_ATTR *y_sdl; /* a struct declarator list attribute */ X STL_ATTR *y_stl; /* a struct declaration list attribute */ X TQL_ATTR *y_tql; /* a type qualifier list attribute */ X D_ATTR *y_d; /* a declarator attribute */ X DD_ATTR *y_dd; /* a direct declarator attribute */ X P_ATTR *y_p; /* a pointer attribute */ X ES_ATTR *y_es; /* a enum specifier attribute */ X ID_ATTR *y_id; /* a init declarator attribute */ X IDL_ATTR *y_idl; /* a init declarator list attribute */ X} X X/* X * characters X */ X X%token ',' ';' ':' '.' '+' '-' '*' '/' '%' '~' '!' '&' '|' '^' X%token '=' '<' '>' '{' '}' '[' ']' '(' ')' '\"' '\'' '\\' '@' X X/* X * special characters X */ X X%token ARROW EEQUAL GE LE LOGAND LOGOR LSHIFT RSHIFT NOTEQUAL TREEPOINT X%token AMPERS_ASSIGN MUL_ASSIGN DIV_ASSIGN HAT_ASSIGN MOD_ASSIGN X%token LSHIFT_ASSIGN RSHIFT_ASSIGN PIPE_ASSIGN PLUS_ASSIGN MINUS_ASSIGN X%token MINUSMINUS PLUSPLUS X%token ENDOFINPUT X X/* X * reserved words X */ X X%token AT ACCEPT AUTO BODY BREAK CASE CHAR CONST CONTINUE CREATE DEFAULT X%token DESTROY DO DOUBLE ELSE ENUM EXTERN FLOAT FOR GOTO HOST IF INT LOCAL X%token LONG OR PROCESS REGISTER RETURN SELECT SHORT SIGNED SIZEOF SPEC STATIC X%token STRUCT SWITCH TERMINATE TRANS TRETURN TYPEDEF UNION UNSIGNED VOID X%token VOLATILE WHILE WITHIN X X/* X * special terminals X */ X X%token CHR_CONST INT_CONST FLOAT_CONST STR_CONST X%token ENUMCONST X%token IDENT TYPEDEF_NAME X X/* X * nonterminal types X */ X X%type translation_unit external_declaration function_definition X%type declaration declaration_list enumerator_list enumerator X%type parameter_type_list parameter_list parameter_declaration X%type identifier_list initializer initializer_list type_name X%type abstract_declarator direct_abstract_declarator X%type logical_OR_expression statement labeled_statement X%type expression_statement statement_list selection_statement X%type iteration_statement jump_statement select_statement X%type expression assignment_expression assignment_operator X%type conditional_expression constant_expression X%type logical_AND_expression inclusive_OR_expression X%type exclusive_OR_expression AND_expression equality_expression X%type relational_expression shift_expression additive_expression X%type multiplicative_expression cast_expression unary_expression X%type unary_operator process_creation parameterleiste X%type primary_expression argument_expression_list constant X%type process_location opt_identifier_list destroy_statement X%type process_definition immediate_alternative X%type timed_transaction_call X%type process_parameter_list process_specification process_parameters X%type process_transactions transaction_declaration X%type transaction_declaration_list X%type process_arguments process_arg_expr_list X%type compound_statement X%type accept_statement X%type select_list select_part alternative accept_alternative X%type terminate_alternative X%type postfix_expression X%type transaction_call X X%type declaration_specifiers X%type storage_class_specifier X%type type_specifier X%type type_qualifier X%type struct_or_union_specifier X%type struct_declaration_list X%type struct_declaration X%type specifier_qualifier_list X%type struct_declarator_list X%type struct_declarator X%type declarator X%type direct_declarator X%type struct_or_union X%type pointer X%type type_qualifier_list X%type enum_specifier X%type init_declarator X%type init_declarator_list X X/* X * the start token X */ X X%start program X X%% X X/* X * the grammar syntax and actions X */ X Xprogram: X {(void) init_symbtab();} X translation_unit X {/* KEEP THIS ORDER OF FUNCTION CALLS!!! */ X#if defined(HETEROGENEOUS) || defined(CHECK_XDR) X (void) build_xdrfile(); X#endif /* HETEROGENEOUS /**/ X (void) build_includefile(); X (void) build_makefile(); X if (mainflag) X fputs($2, outfile); X /* (void) display_symbol_table(); */ X } X ; X Xtranslation_unit: X external_declaration X | translation_unit external_declaration X {$$ = Strcat($1, $2); X Free($2); X } X ; X Xexternal_declaration: X function_definition X | process_specification X {$$ = strmalloc("\n");} X | process_definition X | declaration X ; X Xfunction_definition: X declaration_specifiers declarator X {(void) make_function($1, $2); X blk_push(); X } X declaration_list compound_statement X {$$ = gencode_function($1, $2, $4, $5); X Free((char *) $2); X Free($4); X Free((char *) $5); X blk_pop(); X } X | declarator X {(void) make_function(NULL, $1); X blk_push(); X } X declaration_list compound_statement X {$$ = gencode_function(NULL, $1, $3, $4); X Free((char *) $1); X Free((char *) $4); X blk_pop(); X } X | declaration_specifiers declarator X {(void) make_function($1, $2); X blk_push(); X } X compound_statement X {$$ = gencode_function($1, $2, "", $4); X Free((char *) $2); X Free((char *) $4); X blk_pop(); X } X | declarator X {(void) make_function(NULL, $1); X blk_push(); X } X compound_statement X {$$ = gencode_function(NULL, $1, "", $3); X Free((char *) $1); X /* Free((char *) $3->stats); */ X blk_pop(); X } X ; X Xprocess_specification: X PROCESS SPEC IDENT X {$$ = make_process($3); X blk_push(); X } X process_parameters process_transactions X {DECERRFLAG; X blk_pop(); X (void) add_process_info($3, $5, $6); X (void) add_trans_info($3, $6); X } X | PROCESS SPEC error X {yynerrs--; X Errno = EINPROCSPEC; X Error(NULL, ""); X } X IDENT process_parameters process_transactions X {$$ = make_process($6);} X ; X Xprocess_parameters: X '(' ')' X {$$ = (SYMBTABEL *) NULL;} X | '(' process_parameter_list ')' X {$$ = $2;} X | error X {yynerrs--; X Errno = EPROCPAREXP; X Error(NULL, ""); X $$ = (SYMBTABEL *) NULL; X } X | error X {yynerrs--; X Errno = EPROCPAREXP2; X Error(NULL, ""); X } X '(' process_parameter_list ')' X {$$ = (SYMBTABEL *) NULL;} X ; X Xprocess_parameter_list: X declaration_specifiers IDENT X {$$ = add_parm_type(mark_struct_or_type_def_for_XDR($1), make_parameter($2));} X | declaration_specifiers IDENT ',' process_parameter_list X {$$ = link_parameters(add_parm_type(mark_struct_or_type_def_for_XDR($1), make_parameter($2)), $4);} X | error X {yynerrs--; X Errno = EINPROCPARAM; X Error(NULL, ""); X $$ = (SYMBTABEL *) NULL; X } X | declaration_specifiers error X {yynerrs--; X Errno = EINPROCPARAM; X Error(NULL, ""); X $$ = (SYMBTABEL *) NULL; X } X | declaration_specifiers IDENT error X {yynerrs--; X Errno = EINPROCPARAM; X Error(NULL, ""); X $$ = (SYMBTABEL *) NULL; X } X | declaration_specifiers IDENT error X {yynerrs--; X Errno = EINPROCPARAM; X Error(NULL, ""); X } X process_parameter_list X {$$ = (SYMBTABEL *) NULL;} X | error X {yynerrs--; X Errno = EINPROCPARAM; X Error(NULL, ""); X } X ',' process_parameter_list X {$$ = (SYMBTABEL *) NULL;} X | error X {yynerrs--; X Errno = EINPROCPARAM; X Error(NULL, ""); X } X process_parameter_list X {$$ = (SYMBTABEL *) NULL;} X ; X Xprocess_transactions: X ';' X {$$ = (SYMBTABEL *) NULL;} X | '{' transaction_declaration_list '}' X {$$ = $2;} X | error X {yynerrs--; X Errno = EPROCTRANSEXP; X Error(NULL, ""); X } X ';' X {yyerrok; X $$ = (SYMBTABEL *) NULL; X } X | error X {yynerrs--; X Errno = EPROCTRANSEXP2; X Error(NULL, ""); X } X '{' transaction_declaration_list '}' X {$$ = $4;} X ; X Xtransaction_declaration_list: X transaction_declaration X | transaction_declaration_list transaction_declaration X {$$ = link_transactions($1, $2);} X ; X Xtransaction_declaration: X TRANS declaration_specifiers IDENT X {(void) mark_struct_or_type_def_for_XDR($2); X $$ = make_transaction($3); X blk_push(); X } X process_parameters ';' X {blk_pop(); X $$ = add_transaction_info($3, $2, $5); X } X | TRANS error X {yynerrs--; X Errno = EINTRANSDECL; X Error(NULL, ""); X } X ';' X {yyerrok; X $$ = (SYMBTABEL *) NULL; X } X | TRANS error X {yynerrs--; X Errno = EINTRANSDECL2; X Error(NULL, ""); X } X IDENT process_parameters ';' X {yyerrok; X $$ = make_transaction($4); X } X | TRANS declaration_specifiers error X {yynerrs--; X Errno = EINTRANSDECL3; X Error(NULL, ""); X } X IDENT process_parameters ';' X {yyerrok; X $$ = make_transaction($5); X } X ; X Xprocess_definition: X PROCESS BODY IDENT X {(void) make_process_def($3); X (void) gen_process_creation_routine($3); X (void) gen_call_transaction_routines($3); X bodyflag = TRUE; X blk_push(); X (void) reenter_process_comps($3); X } X '(' opt_identifier_list ')' X {(void) gen_process_file($3);} X compound_statement X {(void) gencode_process_body($3, $9); X $$ = strmalloc(""); X bodyflag = FALSE; X blk_pop(); X } X | PROCESS BODY error X {yynerrs--; X Errno = EINPROCDEF; X Error(NULL, ""); X } X IDENT '(' opt_identifier_list ')' compound_statement X {(void) make_process_def($5); X $$ = strmalloc(""); X } X ; X Xdeclaration: X declaration_specifiers init_declarator_list ';' X {$$ = evaluate_declaration($1, $2); X DECERRFLAG; X } X | declaration_specifiers ';' X {$$ = evaluate_declaration($1, NULL); X DECERRFLAG; X } X ; X Xdeclaration_list: X declaration X | declaration_list declaration X {$$ = Strcat($1, $2); X Free($2); X } X | declaration_list error X ; X Xdeclaration_specifiers: X storage_class_specifier declaration_specifiers X {$$ = gen_declaration_specifiers_attr($1, NULL, NULL, $2);} X | storage_class_specifier X {$$ = gen_declaration_specifiers_attr($1, NULL, NULL, NULL);} X | type_specifier declaration_specifiers X {$$ = gen_declaration_specifiers_attr(NULL, $1, NULL, $2);} X | type_specifier X {$$ = gen_declaration_specifiers_attr(NULL, $1, NULL, NULL);} X | type_qualifier declaration_specifiers X {$$ = gen_declaration_specifiers_attr(NULL, NULL, $1, $2);} X | type_qualifier X {$$ = gen_declaration_specifiers_attr(NULL, NULL, $1, NULL);} X ; X Xstorage_class_specifier: X AUTO X {$$ = gen_storage_class_spec_attr(SCS_ATTR_AUTO);} X | REGISTER X {$$ = gen_storage_class_spec_attr(SCS_ATTR_REGISTER);} X | STATIC X {$$ = gen_storage_class_spec_attr(SCS_ATTR_STATIC);} X | EXTERN X {$$ = gen_storage_class_spec_attr(SCS_ATTR_EXTERN);} X | TYPEDEF X {$$ = gen_storage_class_spec_attr(SCS_ATTR_TYPEDEF);} X ; X Xtype_specifier: X VOID X {$$ = gen_type_specifier_attr(TS_ATTR_VOID, NULL, NULL, NULL);} X | CHAR X {$$ = gen_type_specifier_attr(TS_ATTR_CHAR, NULL, NULL, NULL);} X | SHORT X {$$ = gen_type_specifier_attr(TS_ATTR_SHORT, NULL, NULL, NULL);} X | INT X {$$ = gen_type_specifier_attr(TS_ATTR_INT, NULL, NULL, NULL);} X | LONG X {$$ = gen_type_specifier_attr(TS_ATTR_LONG, NULL, NULL, NULL);} X | FLOAT X {$$ = gen_type_specifier_attr(TS_ATTR_FLOAT, NULL, NULL, NULL);} X | DOUBLE X {$$ = gen_type_specifier_attr(TS_ATTR_DOUBLE, NULL, NULL, NULL);} X | PROCESS IDENT X {(void) is_process($2); X processptr = $2; X $$ = gen_type_specifier_attr(TS_ATTR_PROCESS, NULL, NULL, $2); X } X | SIGNED X {$$ = gen_type_specifier_attr(TS_ATTR_SIGNED, NULL, NULL, NULL);} X | UNSIGNED X {$$ = gen_type_specifier_attr(TS_ATTR_UNSIGNED, NULL, NULL, NULL);} X | enum_specifier X {$$ = gen_type_specifier_attr(TS_ATTR_ENUM, $1, NULL, NULL);} X | struct_or_union_specifier X {$$ = gen_type_specifier_attr(TS_ATTR_STRUCT, NULL, $1, NULL);} X | TYPEDEF_NAME /* IDENT */ X {$$ = gen_type_specifier_attr(TS_ATTR_TYPENAME, NULL, NULL, $1);} X ; X Xtype_qualifier: X CONST X {$$ = gen_type_qualifier_attr(TQ_ATTR_CONST);} X | VOLATILE X {$$ = gen_type_qualifier_attr(TQ_ATTR_VOLATILE);} X ; X Xstruct_or_union_specifier: X struct_or_union IDENT X {blk_push();} X '{' struct_declaration_list '}' X {blk_pop(); X (void) make_structure($2); X (void) add_struct_or_union_info($1, $2, $5); X $$ = gen_struct_or_union_spec_attr($1, $2, $5); X } X | struct_or_union X {blk_push();} X '{' struct_declaration_list '}' X {blk_pop(); X $$ = gen_struct_or_union_spec_attr($1, NULL, $4); X } X | struct_or_union IDENT X {$$ = gen_struct_or_union_spec_attr($1, $2, NULL);} X X /* Typedef_names are not alled as structure tag names. X * The next production is semantically not correct! X * But to allow declarations which use the same identifier as X * structure tag name and as subsequent type definition, e. g. X * "typedef struct NAME { ... } NAME;", we made the following X * hack. X */ X | struct_or_union TYPEDEF_NAME X {$$ = gen_struct_or_union_spec_attr($1, $2, NULL);} X X | struct_or_union error IDENT '{' struct_declaration_list '}' X {$$ = NULL;} X | struct_or_union error '{' struct_declaration_list '}' error X {$$ = NULL;} X ; X Xstruct_or_union: X STRUCT X {$$ = gen_struct_or_union_attr(SU_ATTR_STRUCT);} X | UNION X {$$ = gen_struct_or_union_attr(SU_ATTR_UNION);} X ; X Xstruct_declaration_list: X struct_declaration X {$$ = gen_stru_declaration_list_attr($1);} X | struct_declaration_list struct_declaration X {$$ = add_struct_declaration($1, gen_stru_declaration_list_attr($2));} X | error X {$$ = NULL;} X | struct_declaration_list error X ; X Xinit_declarator_list: X init_declarator X {$$ = gen_init_declarator_list_attr($1);} X | init_declarator_list ',' init_declarator X {$$ = add_init_declarator_list($1, gen_init_declarator_list_attr($3));} X | error X {$$ = NULL;} X | init_declarator_list error init_declarator X | init_declarator_list ',' error X ; X Xinit_declarator: X declarator X {$$ = gen_init_declarator_attr($1, NULL);} X | declarator '=' initializer X {$$ = gen_init_declarator_attr($1, $3);} X | declarator '=' error X {$$ = gen_init_declarator_attr($1, NULL);} X | error '=' initializer X {$$ = NULL;} X ; X Xstruct_declaration: X specifier_qualifier_list struct_declarator_list ';' X {$$ = gen_struct_declaration_attr($1, $2); X DECERRFLAG; X } X | error ';' X {yyerrok; X $$ = NULL; X } X ; X Xspecifier_qualifier_list: X type_specifier specifier_qualifier_list X {$$ = add_spec_qual_list(gen_spec_qual_list_attr($1, NULL), $2);} X | type_specifier X {$$ = gen_spec_qual_list_attr($1, NULL);} X | type_qualifier specifier_qualifier_list X {$$ = add_spec_qual_list(gen_spec_qual_list_attr(NULL, $1), $2);} X | type_qualifier X {$$ = gen_spec_qual_list_attr(NULL, $1);} X ; X Xstruct_declarator_list: X struct_declarator X {$$ = gen_struct_declarator_list_attr($1);} X | struct_declarator_list ',' struct_declarator X {$$ = add_struct_declarator($1, gen_struct_declarator_list_attr($3));} X | error X {$$ = NULL;} X | struct_declarator_list error struct_declarator X | struct_declarator_list ',' error X ; X Xstruct_declarator: X declarator X {$$ = gen_struct_declarator_attr($1, NULL);} X | declarator ':' constant_expression X {$$ = gen_struct_declarator_attr($1, $3);} X | ':' constant_expression X {$$ = gen_struct_declarator_attr(NULL, $2);} X | declarator ':' error constant_expression X {$$ = NULL;} X | ':' error constant_expression X {$$ = NULL;} X ; X Xenum_specifier: X ENUM IDENT '{' enumerator_list '}' X {$$ = gen_enum_specifier_attr(Strcatmany(strmalloc("enum "), 4, X $2->name," { ",$4," } ")); X Free($4); X } X | ENUM '{' enumerator_list '}' X {$$ = gen_enum_specifier_attr(Strcatmany(strmalloc("enum { "), X 2, $3, " } ")); X Free($3); X } X | ENUM IDENT X {$$ = gen_enum_specifier_attr(Strcat(strmalloc("enum "), $2->name));} X | ENUM error X {$$ = gen_enum_specifier_attr(strmalloc(""));} X ; X Xenumerator_list: X enumerator X | enumerator_list ',' enumerator X {$$ = Strcatmany($1, 2, ",", $3); X Free($3); X } X ; X Xenumerator: X IDENT X {$$ = strmalloc($1->name);} X | IDENT '=' constant_expression X {$$ = Strcatmany(strmalloc($1->name), 2, " = ", $3); X Free($3); X } X | error X {$$ = strmalloc("");} X | IDENT '=' error X {$$ = strmalloc("");} X | error constant_expression X {$$ = $2;} X | IDENT error X {$$ = strmalloc("");} X | IDENT error constant_expression X {$$ = $3;} X ; X Xdeclarator: X pointer direct_declarator X {$$ = gen_declarator_attr($1, $2);} X | direct_declarator X {$$ = gen_declarator_attr(NULL, $1);} X | pointer error X {$$ = NULL;} X | pointer error direct_declarator X {$$ = NULL;} X ; X Xdirect_declarator: X IDENT X {$$ = gen_direct_decl_attr(DD_ATTR_IDENT, $1, NULL, NULL, NULL);} X | '(' declarator ')' X {$$ = gen_direct_decl_attr(DD_ATTR_BRACED, NULL, $2, NULL, NULL);} X | direct_declarator '[' constant_expression ']' X {$$ = gen_direct_decl_attr(DD_ATTR_ARRAY, NULL, NULL, $1, $3);} X | direct_declarator '[' ']' X {$$ = gen_direct_decl_attr(DD_ATTR_ARRAY, NULL, NULL, $1, NULL);} X | direct_declarator '(' X {blk_push();} X parameterleiste ')' X {blk_pop(); X $$ = gen_direct_decl_attr(DD_ATTR_FUNC, NULL, NULL, $1, $4); X } X ; X Xparameterleiste: X identifier_list X | parameter_type_list X | /* empty */ X {$$ = strmalloc("");} X ; X Xpointer: X '*' type_qualifier_list X {$$ = gen_pointer_attr(P_ATTR_1, $2, NULL);} X | '*' X {$$ = gen_pointer_attr(P_ATTR_2, NULL, NULL);} X | '*' type_qualifier_list pointer X {$$ = gen_pointer_attr(P_ATTR_3, $2, $3);} X | '*' pointer X {$$ = gen_pointer_attr(P_ATTR_4, NULL, $2);} X ; X Xtype_qualifier_list: X type_qualifier X {$$ = gen_type_qualifier_list_attr($1);} X | type_qualifier_list type_qualifier X {$$ = add_type_qualifier($1, gen_type_qualifier_list_attr($2));} X ; X Xparameter_type_list: X parameter_list X | parameter_list ',' TREEPOINT X {$$ = Strcat($1, ", ...");} X | error TREEPOINT X {$$ = strmalloc("");} X | error ',' TREEPOINT X {$$ = strmalloc("");} X | parameter_list ',' error X ; X Xparameter_list: X parameter_declaration X | parameter_list ',' parameter_declaration X {$$ = Strcatmany($1, 2, ",", $3); X Free($3); X } X | error parameter_declaration X {$$ = $2;} X | error ',' parameter_declaration X {$$ = $3;} X ; X Xparameter_declaration: X declaration_specifiers declarator X {*convert_buffer = 0; X convert_buffer = convert_ds_to_string(convert_buffer, $1); X convert_buffer = convert_d_to_string(convert_buffer, $2); X $$ = strmalloc(convert_buffer); X } X | declaration_specifiers abstract_declarator X {$$ = Strcat(convert_ds_to_string(strmalloc(""), $1), $2); X Free($2); X } X | declaration_specifiers X {$$ = convert_ds_to_string(strmalloc(""), $1);} X | declaration_specifiers error abstract_declarator X {$$ = NULL;} X | declaration_specifiers error X {$$ = NULL;} X ; X Xopt_identifier_list: X /* empty */ X {$$ = strmalloc("");} X | identifier_list X {DECERRFLAG;} X ; X Xidentifier_list: X IDENT X {$$ = strmalloc($1->name);} X | IDENT ',' identifier_list X {$$ = Strcatmany(strmalloc($1->name), 2, ", ", $3); X Free($3); X } X | error X {$$ = strmalloc("");} X | error identifier_list X {$$ = $2;} X | IDENT error identifier_list X {$$ = $3;} X | error ',' identifier_list X {$$ = $3;} X ; X Xinitializer: X assignment_expression X | '{' initializer_list '}' X {$$ = Strcatmany(strmalloc("{ "), 2, $2, " }"); X Free($2); X } X | '{' initializer_list ',' '}' X {$$ = Strcatmany(strmalloc("{ "), 2, $2, ", }"); X Free($2); X } X ; X Xinitializer_list: X initializer X | initializer_list ',' initializer X {$$ = Strcatmany($1, 2, ",", $3); X Free($3); X } X | error X {$$ = strmalloc("");} X | initializer_list error initializer X {$$ = $1; X Free($3); X } X | initializer_list ',' error X | initializer_list error X ; X Xtype_name: X specifier_qualifier_list abstract_declarator X {$$ = Strcat(convert_sql_to_string(strmalloc(""), $1), $2); X Free($2); X } X | specifier_qualifier_list X {$$ = convert_sql_to_string(strmalloc(""), $1);} X | error X {$$ = strmalloc("");} X | specifier_qualifier_list error X {$$ = convert_sql_to_string(strmalloc(""), $1);} X | specifier_qualifier_list error abstract_declarator X {$$ = Strcat(convert_sql_to_string(strmalloc(""), $1), $3); X Free($3); X } X ; X Xabstract_declarator: X pointer X {$$ = convert_p_to_string(strmalloc(""), $1);} X | pointer direct_abstract_declarator X {$$ = Strcat(convert_p_to_string(strmalloc(""), $1), $2); X Free($2); X } X | direct_abstract_declarator X | pointer error direct_abstract_declarator X {$$ = NULL;} X ; X Xdirect_abstract_declarator: X '(' abstract_declarator ')' X {$$ = Strcatmany(strmalloc("("), 2, $2, ")"); X Free($2); X } X | direct_abstract_declarator '[' constant_expression ']' X {$$ = Strcatmany($1, 3, "[", $3, "]"); X Free($3); X } X | '[' constant_expression ']' X {$$ = Strcatmany(strmalloc("["), 2, $2, "]"); X Free($2); X } X | direct_abstract_declarator '[' ']' X {$$ = Strcat($1, "[]");} X | '[' ']' X {$$ = strmalloc("[]");} X | direct_abstract_declarator '(' parameter_type_list ')' X {$$ = Strcatmany($1, 3, "(", $3, ")"); X Free($3); X } X | '(' parameter_type_list ')' X {$$ = Strcatmany(strmalloc("("), 2, $2, ")"); X Free($2); X } X | direct_abstract_declarator '(' ')' X {$$ = Strcat($1, "()");} X | '(' ')' X {$$ = strmalloc("()");} X ; X Xstatement: X labeled_statement X | expression_statement X | {blk_push();} X compound_statement X {blk_pop(); X $$ = Strcatmany(strmalloc("{\n"),4,$2->decls,"\n",$2->stats,"\n}\n"); X Free($2->decls); X /* Free($2->stats); */ X Free((char *) $2); X } X | selection_statement X | iteration_statement X | jump_statement X | accept_statement X {$$ = generate_transaction_code($1); X DECERRFLAG; X } X | select_statement X | destroy_statement X ; X Xlabeled_statement: X IDENT ':' statement X {$$ = Strcatmany(strmalloc($1->name), 2, ":\n", $3); X Free($3); X } X | IDENT error statement X {$$ = $3;} X | IDENT error ':' statement X {$$ = $4;} X | IDENT ':' error statement X {$$ = $4;} X | CASE constant_expression ':' statement X {$$ = Strcatmany(strmalloc("case "), 3, $2, ":\n", $4); X Free($2); X Free($4); X } X | CASE error constant_expression ':' statement X {$$ = $3; X Free($5); X } X | CASE constant_expression error ':' statement X {$$ = $2; X Free($5); X } X | CASE constant_expression ':' error statement X {$$ = $2; X Free($5); X } X | DEFAULT ':' statement X {$$ = Strcat(strmalloc("default:\n"), $3); X Free($3); X } X | DEFAULT error statement X {$$ = ($3);} X | DEFAULT error ':' statement X {$$ = ($4);} X | DEFAULT ':' error statement X {$$ = ($4);} X ; X Xexpression_statement: X expression ';' X {$$ = Strcat($1, ";\n"); X yyerrok; X DECERRFLAG; X } X | ';' X {$$ = strmalloc(";\n"); X yyerrok; X DECERRFLAG; X } X ; X Xcompound_statement: X '{' declaration_list statement_list '}' X {$$ = create_compound_attribute($2, $3);} X | '{' statement_list '}' X {$$ = create_compound_attribute("", $2);} X | '{' declaration_list '}' X {$$ = create_compound_attribute($2, "");} X | '{' '}' X {$$ = create_compound_attribute("", "");} X | '{' error X {$$ = NULL;} X ; X Xstatement_list: X statement X | statement_list statement X {$$ = Strcat($1, $2); X Free($2); X } X | statement_list error X ; X Xselection_statement: X IF '(' expression ')' statement X {$$ = Strcatmany(strmalloc("if ("), 3, $3, ") ", $5); X Free($3); X Free($5); X } X | IF '(' expression ')' statement ELSE statement X {$$ = Strcatmany(strmalloc("if ("),5,$3,") ",$5," else ",$7); X Free($3); X Free($5); X Free($7); X } X | IF error X {$$ = strmalloc("");} X | IF '(' error X {$$ = strmalloc("");} X | IF '(' expression error X {$$ = $3;} X | IF '(' expression ')' error X {$$ = $3;} X | IF '(' expression ')' statement ELSE error X {$$ = $3;} X | SWITCH '(' expression ')' statement X {$$ = Strcatmany(strmalloc("switch("), 3, $3, ") ", $5); X Free($3); X Free($5); X } X | SWITCH error X {$$ = strmalloc("");} X | SWITCH '(' error X {$$ = strmalloc("");} X | SWITCH '(' expression error X {$$ = $3;} X | SWITCH '(' expression ')' error X {$$ = $3;} X ; X Xiteration_statement: X WHILE '(' expression ')' statement X {$$ = Strcatmany(strmalloc("while("), 3, $3, ") ", $5); X Free($3); X Free($5); X } X | WHILE error X {$$ = strmalloc("");} X | WHILE '(' error X {$$ = strmalloc("");} X | WHILE '(' expression error X {$$ = $3;} X | WHILE '(' expression ')' error X {$$ = $3;} X | DO statement WHILE '(' expression ')' ';' X {$$ = Strcatmany(strmalloc("do "), 4, $2, " while(", $5,");\n"); X Free($2); X Free($5); X yyerrok; X DECERRFLAG; X } X | DO error ';' X {$$ = strmalloc("");} X | DO statement error ';' X {$$ = $2;} X | DO statement WHILE error ';' X {$$ = $2;} X | DO statement WHILE '(' error ';' X {$$ = $2;} X | DO statement WHILE '(' expression error ';' X {$$ = $2; X Free($5); X } X | DO statement WHILE '(' expression ')' error ';' X {$$ = $2; X Free($5); X } X | FOR '(' expression ';' expression ';' expression ')' statement X {$$ = Strcatmany(strmalloc("for("), 7, $3, "; ", $5, "; ", $7, ") ", $9); X Free($3); X Free($5); X Free($7); X Free($9); X } X | FOR '(' ';' expression ';' expression ')' statement X {$$ = Strcatmany(strmalloc("for( ; "), 5, $4, "; ", $6, ") ", $8); X Free($4); X Free($6); X Free($8); X } X | FOR '(' expression ';' ';' expression ')' statement X {$$ = Strcatmany(strmalloc("for("), 5, $3, "; ; ", $6, ") ", $8); X Free($3); X Free($6); X Free($8); X } X | FOR '(' ';' ';' expression ')' statement X {$$ = Strcatmany(strmalloc("for( ; ; "), 3, $5, ") ", $7); X Free($5); X Free($7); X } X | FOR '(' expression ';' expression ';' ')' statement X {$$ = Strcatmany(strmalloc("for("), 5, $3, "; ", $5, "; ) ", $8); X Free($3); X Free($5); X Free($8); X } X | FOR '(' ';' expression ';' ')' statement X {$$ = Strcatmany(strmalloc("for( ; "), 3, $4, "; ) ", $7); X Free($4); X Free($7); X } X | FOR '(' expression ';' ';' ')' statement X {$$ = Strcatmany(strmalloc("for("), 3, $3, "; ; ) ", $7); X Free($3); X Free($7); X } X | FOR '(' ';' ';' ')' statement X {$$ = Strcat(strmalloc("for( ; ; ) "), $6); X Free($6); X } X | FOR error X {$$ = strmalloc("");} X | FOR '(' error X {$$ = strmalloc("");} X | FOR '(' error ')' statement X {$$ = $5;} X | FOR error ')' statement X {$$ = $4;} X ; X Xjump_statement: X GOTO IDENT ';' X {$$ = Strcatmany(strmalloc("goto "), 2, $2->name, ";\n"); X DECERRFLAG; X } X | GOTO IDENT error ';' X {$$ = strmalloc("");} X | GOTO error ';' X {$$ = strmalloc(""); X DECERRFLAG; X } X | CONTINUE ';' X {$$ = strmalloc("continue;\n"); X DECERRFLAG; X } X | CONTINUE error ';' X {$$ = strmalloc(""); X DECERRFLAG; X } X | BREAK ';' X {$$ = strmalloc("break;\n"); X DECERRFLAG; X } X | BREAK error ';' X {$$ = strmalloc(""); X DECERRFLAG; X } X | RETURN expression ';' X {$$ = Strcatmany(strmalloc("return "), 2, $2, ";\n"); X Free($2); X DECERRFLAG; X } X | RETURN error ';' X {$$ = strmalloc("");} X | RETURN ';' X {$$ = strmalloc("return;\n"); X DECERRFLAG; X } X | TRETURN expression ';' X {$$ = generate_treturn_code($2); X Free($2); X DECERRFLAG; X } X | TRETURN ';' X {$$ = generate_treturn_code(NULL); X DECERRFLAG; X } X ; X Xaccept_statement: X ACCEPT IDENT '(' opt_identifier_list ')' X {$2 = add_transaction_label(check_transaction($2)); X blk_push(); X (void) reenter_transaction_params($2); X } X compound_statement X {blk_pop(); X $$ = create_accept_attribute($2, $7); X } X | ACCEPT IDENT ';' X {$$ = create_accept_attribute(check_transaction($2), create_compound_attribute("", ""));} X | ACCEPT error X {yynerrs--; X Errno = EINACCSTAT; X Error(NULL, ""); X } X ';' X {yyerrok; X $$ = create_accept_attribute(NULL, NULL); X } X | ACCEPT error X {yynerrs--; X Errno = EINACCSTAT2; X Error(NULL, ""); X } X IDENT '(' opt_identifier_list ')' ';' X {yyerrok; X $$ = create_accept_attribute(NULL, NULL); X } X | ACCEPT IDENT error X {yynerrs--; X Errno = EINACCSTAT3; X Error(NULL, ""); X } X '(' opt_identifier_list ')' ';' X {yyerrok; X $$ = create_accept_attribute(NULL, NULL); X } X | ACCEPT IDENT '(' opt_identifier_list ')' error X {yynerrs--; X Errno = EINACCSTAT4; X Error(NULL, ""); X } X ';' X {yyerrok; X $$ = create_accept_attribute(NULL, NULL); X } X ; X Xselect_statement: X SELECT '{' select_list '}' X {$$ = generate_select_code($3);} X | SELECT error X {yynerrs--; X Errno = EINSELSTAT; X Error(NULL, ""); X $$ = strmalloc(""); X } X ; X Xselect_list: X select_part X | select_part OR select_list X {$$ = link_select_attributes($1, $3);} X | error X {yynerrs--; X Errno = EINSELSTAT; X Error(NULL, ""); X $$ = create_select_attribute(ERROR, NULL, NULL); X } X | error X {yynerrs--; X Errno = EINSELSTAT; X Error(NULL, ""); X } X select_list X {$$ = $3;} X | error X {yynerrs--; X Errno = EINSELSTAT2; X Error(NULL, ""); X } X OR select_list X {$$ = $4;} X ; X Xselect_part: X alternative X | '(' expression ')' ':' alternative X {$$ = add_guard_to_attr($5, $2);} X | error X {yynerrs--; X Errno = EINSELPART; X Error(NULL, ""); X } X ':' alternative X {$$ = $4;} X ; X Xalternative: X accept_alternative X | terminate_alternative X | immediate_alternative X {$$ = create_select_attribute(ALT_IMMEDIATE, NULL, $1);} X ; X Xaccept_alternative: X accept_statement statement_list X {$$ = create_select_attribute(ALT_ACCEPT, $1, $2);} X | accept_statement error X {yynerrs--; X Errno = EINACCALTERN; X Error(NULL, ""); X $$ = create_select_attribute(ERROR, NULL, NULL); X } X | accept_statement error X {yynerrs--; X Errno = EINACCALTERN; X Error(NULL, ""); X } X statement_list X {$$ = create_select_attribute(ERROR, NULL, NULL);} X ; X Xterminate_alternative: X TERMINATE X {$$ = create_select_attribute(ALT_TERMINATE, NULL, NULL);} X ; X Ximmediate_alternative: X labeled_statement X | expression_statement X | compound_statement X {$$ = Strcatmany(strmalloc("{\n"),4,$1->decls,"\n",$1->stats,"\n}\n"); X Free($1->decls); X Free($1->stats); X Free((char *) $1); X } X | selection_statement X | iteration_statement X | jump_statement X ; X Xdestroy_statement: X DESTROY '(' postfix_expression ')' X {$$ = generate_destroy_process_code($3->codestr);} X | DESTROY error X {yynerrs--; X Errno = EINDESTRSTAT; X Error(NULL, ""); X $$ = strmalloc(""); X } X ; X Xexpression: X assignment_expression X | expression ',' assignment_expression X {$$ = Strcatmany($1, 2, ", ", $3); X Free($3); X } X | expression ',' error X | error ',' assignment_expression X {$$ = $3;} X ; X Xassignment_expression: X conditional_expression X | unary_expression assignment_operator assignment_expression X {$$ = Strcatmany($1, 2, $2, $3); X Free($3); X } X | unary_expression assignment_operator error X {Free($2);} X | unary_expression assignment_operator error assignment_expression X {Free($2); X Free($4); X } X ; X Xassignment_operator: X '=' X {$$ = " = ";} X | MUL_ASSIGN X {$$ = " *= ";} X | DIV_ASSIGN X {$$ = " /= ";} X | MOD_ASSIGN X {$$ = " %= ";} X | PLUS_ASSIGN X {$$ = " += ";} X | MINUS_ASSIGN X {$$ = " -= ";} X | LSHIFT_ASSIGN X {$$ = " <<= ";} X | RSHIFT_ASSIGN X {$$ = " >>= ";} X | AMPERS_ASSIGN X {$$ = " &= ";} X | HAT_ASSIGN X {$$ = " ^= ";} X | PIPE_ASSIGN X {$$ = " |= ";} X ; X Xconditional_expression: X logical_OR_expression X | logical_OR_expression '?' expression ':' conditional_expression X {$$ = Strcatmany($1, 4, " ? ", $3, " : ", $5); X Free($3); X Free($5); X } X | timed_transaction_call X ; X Xtimed_transaction_call: X WITHIN logical_OR_expression '?' '(' transaction_call X ':' expression ')' X {$$ = generate_call_transaction_code($2, $5->target, $5->symbol, $5->arg, $7);} X | WITHIN error X {yynerrs--; X Errno = EINTIMEDTRANS; X Error(NULL, ""); X $$ = strmalloc(""); X } X | WITHIN logical_OR_expression error X {yynerrs--; X Errno = EINTIMEDTRANS; X Error(NULL, ""); X } X ')' X {$$ = strmalloc("");} X ; X Xconstant_expression: X conditional_expression X ; X Xlogical_OR_expression: X logical_AND_expression X | logical_OR_expression LOGOR logical_AND_expression X {$$ = Strcatmany($1, 2, " || ", $3); X Free($3); X } X ; X Xlogical_AND_expression: X inclusive_OR_expression X | logical_AND_expression LOGAND inclusive_OR_expression X {$$ = Strcatmany($1, 2, " && ", $3); X Free($3); X } X ; X Xinclusive_OR_expression: X exclusive_OR_expression X | inclusive_OR_expression '|' exclusive_OR_expression X {$$ = Strcatmany($1, 2, " | ", $3); X Free($3); X } X ; X Xexclusive_OR_expression: X AND_expression X | exclusive_OR_expression '^' AND_expression X {$$ = Strcatmany($1, 2, " ^ ", $3); X Free($3); X } X ; X XAND_expression: X equality_expression X | AND_expression '&' equality_expression X {$$ = Strcatmany($1, 2, " & ", $3); X Free($3); X } X ; X Xequality_expression: X relational_expression X | equality_expression EEQUAL relational_expression X {$$ = Strcatmany($1, 2, " == ", $3); X Free($3); X } X | equality_expression NOTEQUAL relational_expression X {$$ = Strcatmany($1, 2, " != ", $3); X Free($3); X } X ; X Xrelational_expression: X shift_expression X | relational_expression '<' shift_expression X {$$ = Strcatmany($1, 2, " < ", $3); X Free($3); X } X | relational_expression '>' shift_expression X {$$ = Strcatmany($1, 2, " > ", $3); X Free($3); X } X | relational_expression LE shift_expression X {$$ = Strcatmany($1, 2, " <= ", $3); X Free($3); X } X | relational_expression GE shift_expression X {$$ = Strcatmany($1, 2, " >= ", $3); X Free($3); X } X ; X Xshift_expression: X additive_expression X | shift_expression LSHIFT additive_expression X {$$ = Strcatmany($1, 2, " << ", $3); X Free($3); X } X | shift_expression RSHIFT additive_expression X {$$ = Strcatmany($1, 2, " >> ", $3); X Free($3); X } X ; X Xadditive_expression: X multiplicative_expression X | additive_expression '+' multiplicative_expression X {$$ = Strcatmany($1, 2, " + ", $3); X Free($3); X } X | additive_expression '-' multiplicative_expression X {$$ = Strcatmany($1, 2, " - ", $3); X Free($3); X } X ; X Xmultiplicative_expression: X cast_expression X | multiplicative_expression '*' cast_expression X {$$ = Strcatmany($1, 2, " * ", $3); X Free($3); X } X | multiplicative_expression '/' cast_expression X {$$ = Strcatmany($1, 2, " / ", $3); X Free($3); X } X | multiplicative_expression '%' cast_expression X {$$ = Strcatmany($1, 2, " % ", $3); X Free($3); X } X ; X Xcast_expression: X unary_expression X | '(' type_name ')' cast_expression X {$$ = Strcatmany(strmalloc("("), 3, $2, ") ", $4); X Free($2); X Free($4); X } X ; X Xunary_expression: X postfix_expression X {$$=$1->codestr;} X | PLUSPLUS unary_expression X {$$ = Strcat(strmalloc("++"), $2); X Free($2); X } X | PLUSPLUS error X {$$ = strmalloc("");} X | MINUSMINUS unary_expression X {$$ = Strcat(strmalloc("--"), $2); X Free($2); X } X | MINUSMINUS error X {$$ = strmalloc("");} X | unary_operator cast_expression X {$$ = Strcat($1, $2); X Free($2); X } X | unary_operator error X | SIZEOF unary_expression X {$$ = Strcat(strmalloc("sizeof "), $2); X Free($2); X } X | SIZEOF error X {$$ = strmalloc("");} X | SIZEOF '(' type_name ')' X {$$ = Strcatmany(strmalloc("sizeof("), 2, $3, ")"); X Free($3); X } X ; X Xunary_operator: X '&' X {$$ = strmalloc("&");} X | '*' X {$$ = strmalloc("*");} X | '+' X {$$ = strmalloc("+");} X | '-' X {$$ = strmalloc("-");} X | '~' X {$$ = strmalloc("~");} X | '!' X {$$ = strmalloc("!");} X ; X Xpostfix_expression: X primary_expression X {$$ = create_post_expr_attr($1);} X | postfix_expression '[' expression ']' X {$1->codestr = Strcatmany($1->codestr, 3, "[", $3, "]"); X Free($3); X } X | postfix_expression '(' argument_expression_list ')' X {$1->codestr = Strcatmany($1->codestr, 3, "(", $3, ")"); X Free($3); X } X | postfix_expression '(' ')' X {$1->codestr = Strcat($1->codestr, "()");} X | postfix_expression '.' IDENT X {$1->idents = update_post_expr_attr($1->idents, $3); X $1->codestr = Strcatmany($1->codestr, 2, ".", $3->name); X } X | postfix_expression '.' error X | postfix_expression ARROW IDENT X {$1->idents = update_post_expr_attr($1->idents, $3); X $1->codestr = Strcatmany($1->codestr, 2, "->", $3->name); X } X | postfix_expression ARROW error X | postfix_expression PLUSPLUS X {$$->codestr = Strcat($1->codestr, "++");} X | postfix_expression MINUSMINUS X {$$->codestr = Strcat($1->codestr, "--");} X | process_creation X {$$=create_post_expr_attr($1);} X | transaction_call X {$1->target=generate_call_transaction_code(NULL,$1->target, $1->symbol, $1->arg, NULL); X $$=create_post_expr_attr($1->target); X } X ; X Xprocess_creation: X CREATE IDENT '(' process_arguments ')' process_location X {$$ = generate_process_creation_code($2, $4, $6);} X | CREATE error X {yynerrs--; X Errno = EINPROCCREATE; X Error(NULL, ""); X $$ = strmalloc(""); X } X | CREATE error X {yynerrs--; X Errno = EINPROCCREATE2; X Error(NULL, ""); X } X IDENT '(' process_arguments ')' process_location X {$$ = $8;} X | CREATE IDENT error X {yynerrs--; X Errno = EINPROCCREATE3; X Error(NULL, ""); X } X '(' process_arguments ')' process_location X {$$ = $8;} X ; X Xprocess_arguments: X /* empty */ X {$$ = (ARG_LIST *) NULL;} X | process_arg_expr_list X ; X Xprocess_arg_expr_list: X assignment_expression X {$$ = create_arg_list_elem($1);} X | assignment_expression ',' process_arg_expr_list X {$$ = link_arguments(create_arg_list_elem($1), $3);} X | error X {yynerrs--; X Errno = EINPROCARGS; X Error(NULL, ""); X $$ = (ARG_LIST *) NULL; X } X | error X {yynerrs--; X Errno = EINPROCARGS; X Error(NULL, ""); X } X ',' process_arg_expr_list X {$$ = $4;} X | assignment_expression error X {Free($1); X yynerrs--; X Errno = EINPROCARGS; X Error(NULL, ""); X } X process_arg_expr_list X {$$ = $4;} X ; X Xprocess_location: X LOCAL X {$$ = strmalloc("\"local\"");} X | AT HOST '(' assignment_expression ')' X {$$ = $4;} X | /* empty */ X {$$ = strmalloc("NULL");} X | AT error X {yynerrs--; X Errno = EINPROCLOC; X Error(NULL, ""); X $$ = strmalloc(""); X } X | AT HOST error X {yynerrs--; X Errno = EINPROCLOC; X Error(NULL, ""); X $$ = strmalloc(""); X } X ; X Xtransaction_call: X postfix_expression X {blk_push;} X '@' IDENT X {blk_pop;} X '(' process_arguments ')' X {$$ = create_trans_attr($1, get_process($4), $7);} X/* | postfix_expression '@' error X {$$->target=$1->codestr; X $$->symbol=NULL; X $$->arg=NULL; X yynerrs--; X Errno = EINTRANSCALL; X Error(NULL, ""); X } X | postfix_expression '@' IDENT error X {$$->target=$1->codestr; X $$->symbol=NULL; X $$->arg=NULL; X yynerrs--; X Errno = EINTRANSCALL; X Error(NULL, ""); X } X*/ ; X Xprimary_expression: X IDENT X {$$ = strmalloc($1->name);} X | constant X | STR_CONST X {$$ = strmalloc(yytext);} X | '(' expression ')' X {$$ = Strcatmany(strmalloc("("), 2, $2, ")"); X Free($2); X } X ; X Xargument_expression_list: X assignment_expression X | argument_expression_list ',' assignment_expression X {$$ = Strcatmany($1, 2, ",", $3); X Free($3); X } X | error X {$$ = strmalloc("");} X | argument_expression_list error X | argument_expression_list error assignment_expression X ; X Xconstant: X INT_CONST X {$$ = strmalloc(yytext);} X | CHR_CONST X {$$ = strmalloc(yytext);} X | FLOAT_CONST X {$$ = strmalloc(yytext);} X | ENUMCONST /*IDENT */ X {$$ = strmalloc(yytext);} X ; X X%% X X#include "lex.yy.c" END_OF_FILE if test 42425 -ne `wc -c <'dcc/dcc.y'`; then echo shar: \"'dcc/dcc.y'\" unpacked with wrong size! fi # end of 'dcc/dcc.y' fi if test -f 'lib/ipc_msgsem.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'lib/ipc_msgsem.c'\" else echo shar: Extracting \"'lib/ipc_msgsem.c'\" \(41235 characters\) sed "s/^X//" >'lib/ipc_msgsem.c' <<'END_OF_FILE' X/*************************************************************************** X * * X * @@@@ @@@ @@@@@ @@@@@ @@@@@ @@@ @@@@ @ @ @@@@@ @@@@@ @@@@ @@@ * X * @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ * X * @ @ @ @@@@@ @ @@@@@ @ @@@@@ @ @ @ @@@@@ @ @ @ * X * @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ * X * @@@@ @@@ @@@@@ @ @ @ @@@ @@@@ @@@@@ @ @@@@@ @@@@ @@@ * X * * X * A compiler for distributed programming with C * X * * X * i p c _ m s g s e m . c * X * * X * Package : Runtime Library * X * Version : 1.0 * X * CreationDate : 10.07.90 * X * LastUpDate : 15.10.90 * X * * X * This file contains the hardware dependent routines building the message * X * passing layer based on message queues and semaphores. * X * * X * Copyright (C) 1990-1994 by Christoph Pleier * X * All rights reserved! * X ***************************************************************************/ X X/* X * This file is part of the Distributed C Development Environment (DCDE). X * DCDE is free software; you can redistribute it and/or modify X * it under the terms written in the README-file. X * DCDE is distributed in the hope that it will be useful, X * but WITHOUT ANY WARRANTY; without even the implied warranty of X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. X * See the file README for more details. X */ X X#include X#include X#include X#include X#include X#include X#include X#include X#include "ipc_msgsem.h" X#include "run_Errno.h" X X/* define this to add code to display additional informations about: */ X#define DEBUG_IPC /* message pssing */ X/* #define DEBUG_MSG /* semaphore and message queue actions */ X X/* To avoid that processes whose connection attempt is refused several times X * (e.g. if the called process tries itself to connect to the calling process) X * let grow the load of the computer nodes because of the busy waiting X * character, we raise each time a connection attempt is refused the delay X * until the connecting process is allowed to retry the attempt. X * The delay starts at MCON_RETRY_DELAY_MIN and is raised in steps of X * MCON_RETRY_DELAY_STEP until MCON_RETRY_DELAY_MAX. After the connection X * attempt succeeded or the operation is timed out the delay is reset to the X * min. value. X * X * Note: the values specify milliseconds X */ X#define MCON_RETRY_DELAY_MIN 100 X#define MCON_RETRY_DELAY_MAX 5000 X#define MCON_RETRY_DELAY_STEP 100 X X/* to store the actual retry delay */ Xint mcon_retry_delay = MCON_RETRY_DELAY_MIN; X X#ifdef DEBUG_IPC X/* the flag to control the debug messages output */ Xint _debug_ipc = 0; X#endif /* DEBUG_IPC /**/ X X/* the used external global variables */ Xextern int errno, /* system error code */ X Errno, /* function error code */ X _debugflush; /* flush debug messages or not */ Xextern char *sys_errlist[], /* system error messages */ X *_programname, /* name of program */ X *_processname, /* name of process */ X _processprefix[]; /* process specifying string */ Xextern FILE *_debugout; /* where to write the debug messages */ X X/* the timeout flag */ Xstatic int timeout; X X/* set timer, if time equals 0 clear timer */ X#define SETTIMER(time) timeout = FALSE; \ X signal(SIGALRM, timeout_proc); \ X (void) alarm(time); X X#ifdef DEBUG_IPC X# define DEBUGPUTS(msg) if (_debug_ipc) { \ X fprintf(_debugout, "[ipc] %s %s\n", \ X _processprefix, msg); \ X if (_debugflush) \ X fflush(_debugout); \ X } X# define DEBUGDISPERR(msg) if (_debug_ipc) { \ X fprintf(_debugout, "[ipc] %s error: %s\n", \ X _processprefix, msg); \ X fprintf(_debugout, "[ipc] %s reason: %s\n",\ X _processprefix, sys_errlist[errno]); \ X if (_debugflush) \ X fflush(_debugout); \ X } X#else X# define DEBUGPUTS(msg) { /* nothing */ } X# define DEBUGDISPERR(msg) { /* nothing */ } X#endif X X/* if timeout is set, return ERROR */ X#define RETURN_IF_TIMEOUT if (timeout) { \ X DEBUGPUTS("TIMEOUT"); \ X Errno = ETIMEOUT; \ X return(ERROR); \ X } X X/****************************************************************************** X * timeout_proc() * X * * X * Sets the timeout flag 'timeout' to indicate a timeout error. * X * * X * Return values: none! * X ******************************************************************************/ Xstatic int Xtimeout_proc() X{ X DEBUGPUTS("***** timeout_proc():"); X timeout = TRUE; X} /* timeout_proc */ X X/****************************************************************************** X * create_msq() * X * * X * Creates a message queue identifier, an associated message queue and data * X * structure. * X * * X * Return values: new msqid upon success / -1 = error * X ******************************************************************************/ Xstatic int Xcreate_msq() X{ X#ifdef DEBUG_MSG X puts("[msg] ***** create_msq()"); X#endif /* DEBUG_MSG /**/ X return(msgget((key_t) IPC_PRIVATE, IPC_CREAT | MSG_PERMISSION)); X} /* create_msq */ X X/****************************************************************************** X * remove_msq() * X * * X * Removes the message queue identifier specified by 'msqid' from the system * X * destroys the message queue and data structure associated with it. * X * * X * Return values: 0 = success / -1 = error * X ******************************************************************************/ Xstatic int Xremove_msq(msqid) Xint msqid; X{ X static struct msqid_ds dummy; X X#ifdef DEBUG_MSG X puts("[msg] ***** remove_msq()"); X printf("[msg] params: msqid = %d\n", msqid); X#endif /* DEBUG_MSG /**/ X return(msgctl(msqid, IPC_RMID, &dummy)); X} /* remove_msq */ X X/****************************************************************************** X * msq_set_permission() * X * * X * Sets the value of the following members of the data structure associated * X * with 'msqid' into the structure pointed to by 'buf': * X * msg_perm.uid, msg_perm.gid, msg_perm.mode, msg_qbytes * X * * X * Return values: 0 = success / -1 = error * X ******************************************************************************/ Xstatic int Xmsq_set_permission(msqid, uid, gid, mode, qbytes) Xint msqid; Xushort uid, gid, mode, qbytes; X{ X static struct msqid_ds msqbuf; X X#ifdef DEBUG_MSG X puts("[msg] ***** msq_set_permission()"); X printf("[msg] params: msqid = %d, uid = %d, gid = %d\n", X msqid, uid, gid); X printf("[msg] mode = %d, qbytes = %d\n", mode, qbytes); X#endif /* DEBUG_MSG /**/ X msqbuf.msg_perm.uid = uid; X msqbuf.msg_perm.gid = gid; X msqbuf.msg_perm.mode = mode; X msqbuf.msg_qbytes = qbytes; X return(msgctl(msqid, IPC_SET, &msqbuf)); X} /* msq_set_permission */ X X/****************************************************************************** X * msq_display_status() * X * * X * Displays the current value of each member of the data structure associated * X * with the message queue identifier 'msqid'. * X * * X * Return values: 0 = success / -1 = error * X ******************************************************************************/ Xstatic int Xmsq_display_status(msqid) Xint msqid; X{ X static struct msqid_ds msqbuf; X X#ifdef DEBUG_MSG X puts("[msg] ***** msq_display_status()"); X printf("[msg] params: msqid = %d\n", msqid); X#endif /* DEBUG_MSG /**/ X printf("Values associated to message queue identifier '%d':\n", msqid); X if (msq_get_status(msqid, &msqbuf) == -1) X return(-1); X printf(" creator user id : %d\n", msqbuf.msg_perm.cuid); X printf(" creator group id : %d\n", msqbuf.msg_perm.cgid); X printf(" user id : %d\n", msqbuf.msg_perm.uid); X printf(" group id : %d\n", msqbuf.msg_perm.gid); X printf(" r/w permission : %d\n", msqbuf.msg_perm.mode); X printf(" number of msgs on queue : %d\n", msqbuf.msg_qnum); X printf("max number of bytes on queue : %d\n", msqbuf.msg_qbytes); X printf("pid of last msgsnd operation : %d\n", msqbuf.msg_lspid); X printf("pid of last msgrcv operation : %d\n", msqbuf.msg_lrpid); X printf(" last msgsnd time : %s", ctime(&msqbuf.msg_stime)); X printf(" last msgrcv time : %s", ctime(&msqbuf.msg_rtime)); X printf(" last change time : %s", ctime(&msqbuf.msg_ctime)); X return(0); X} /* msq_display_status */ X X/****************************************************************************** X * msq_get_status() * X * * X * Places the current value of each member of the data structure associated * X * with 'msqid' into the structure pointed to by 'msqbuf'. * X * * X * Return values: 0 = success / -1 = error * X ******************************************************************************/ Xstatic int Xmsq_get_status(msqid, msqbuf) Xint msqid; Xstruct msqid_ds *msqbuf; X{ X#ifdef DEBUG_MSG X puts("[msg] ***** msq_get_status()"); X printf("[msg] params: msqid = %d, msqbuf = %d\n", msqid, msqbuf); X#endif /* DEBUG_MSG /**/ X return(msgctl(msqid, IPC_STAT, msqbuf)); X} /* msq_get_status */ X X/****************************************************************************** X * create_sem() * X * * X * Creates a semaphore identifier and an associated data structure. * X * * X * Return values: new semid = success / -1 = error * X ******************************************************************************/ Xstatic int Xcreate_sem() X{ X#ifdef DEBUG_MSG X puts("[msg] ***** create_sem()"); X#endif /* DEBUG_MSG /**/ X return(semget((key_t) IPC_PRIVATE, 1, IPC_CREAT | SEM_PERMISSION)); X} /* create_sem */ X X/****************************************************************************** X * remove_sem() * X * * X * Removes the semaphore identifier specified by 'semid' from the system and * X * destroys the data structure accosiated with it. * X * * X * Return values: 0 = success / -1 = error * X ******************************************************************************/ Xstatic int Xremove_sem(semid) Xint semid; X{ X char dummy; X X#ifdef DEBUG_MSG X puts("[msg] ***** remove_sem()"); X printf("[msg] params: semid = %d\n", semid); X#endif /* DEBUG_MSG /**/ X return(semctl(semid, 0, IPC_RMID, &dummy)); X} /* remove_sem */ X X/****************************************************************************** X * sem_get_val() * X * * X * Gets the value of the semaphore 'semid'. * X * * X * Return values: semaphore value = success / -1 = error * X ******************************************************************************/ Xstatic int Xsem_get_val(semid) Xint semid; X{ X static union semun arg; X X#ifdef DEBUG_MSG X puts("[msg] ***** sem_get_val()"); X printf("[msg] params: semid = %d\n", semid); X#endif /* DEBUG_MSG /**/ X return(semctl(semid, 0, GETVAL, arg)); X} /* sem_get_val */ X X/****************************************************************************** X * sem_set_val() * X * * X * Sets the value of the semaphore 'semid' to 'value'. * X * * X * Return values: 0 = success / -1 = error * X ******************************************************************************/ Xstatic int Xsem_set_val(semid, value) Xint semid, value; X{ X static union semun arg; X X#ifdef DEBUG_MSG X puts("[msg] ***** sem_set_val()"); X printf("[msg] params: semid = %d, value = %d\n", semid, value); X#endif /* DEBUG_MSG /**/ X arg.val = value; X return(semctl(semid, 0, SETVAL, arg)); X} /* sem_set_val */ X X/****************************************************************************** X * sem_set_permission() * X * * X * Sets the value of the following members of the data structure associated * X * with 'semid' into the structure pointed to by 'buf': * X * sem_perm.uid, sem_perm.gid, sem_perm.mode * X * * X * Return values: 0 = success / -1 = error * X ******************************************************************************/ Xstatic int Xsem_set_permission(semid, uid, gid, mode) Xint semid; Xushort uid, gid, mode; X{ X int result; X static union semun arg; X X#ifdef DEBUG_MSG X puts("[msg] ***** sem_set_permission()"); X printf("[msg] params: semid = %d, uid = %d, gid = %d, mode = %d\n", X semid, uid, gid, mode); X#endif /* DEBUG_MSG /**/ X arg.buf = (struct semid_ds *) malloc(sizeof(struct semid_ds)); X if (arg.buf == NULL) X return(-1); X arg.buf->sem_perm.uid = uid; X arg.buf->sem_perm.gid = gid; X arg.buf->sem_perm.mode = mode; X result = semctl(semid, 0, IPC_SET, arg); X free(arg.buf); X return(result); X} /* sem_set_permission */ X X/****************************************************************************** X * sem_display_status() * X * * X * Displays the current value of each member of the data structure associated * X * with the semaphore specified by 'msqid'. * X * * X * Return values: 0 = success / -1 = error * X ******************************************************************************/ Xstatic int Xsem_display_status(semid) Xint semid; X{ X static union semun arg; X X#ifdef DEBUG_MSG X puts("[msg] ***** sem_display_status()"); X printf("[msg] params: semid = %d\n", semid); X#endif /* DEBUG_MSG /**/ X arg.buf = (struct semid_ds *) malloc(sizeof(struct semid_ds)); X if (arg.buf == NULL) X return(-1); X printf("Values associated to semaphore identifier '%d':\n", semid); X if (sem_get_status(semid, arg) == -1) { X free(arg.buf); X return(-1); X } X printf(" creator user id : %d\n", arg.buf->sem_perm.cuid); X printf(" creator group id : %d\n", arg.buf->sem_perm.cgid); X printf(" user id : %d\n", arg.buf->sem_perm.uid); X printf(" group id : %d\n", arg.buf->sem_perm.gid); X printf(" r/w permission : %d\n", arg.buf->sem_perm.mode); X printf("number of sems in set : %d\n", arg.buf->sem_nsems); X printf(" last operation time : %s", ctime(&arg.buf->sem_otime)); X printf(" last change time : %s", ctime(&arg.buf->sem_ctime)); X free(arg.buf); X return(0); X} /* sem_display_status */ X X/****************************************************************************** X * sem_get_status() * X * * X * Places the current value of each member of the data structure associated * X * with 'semid' into the structure pointed to by 'arg.buf'. * X * * X * Return values: 0 = success / -1 = error * X ******************************************************************************/ Xstatic int Xsem_get_status(semid, arg) Xint semid; Xunion semun arg; X{ X#ifdef DEBUG_MSG X puts("[msg] ***** sem_get_status()"); X printf("[msg] params: semid = %d, arg = %d\n", semid, arg); X#endif /* DEBUG_MSG /**/ X return(semctl(semid, 0, IPC_STAT, arg)); X} /* sem_get_status */ X X/****************************************************************************** X * _create_port() * X * * X * Creates a new communication endpoint. * X * * X * Return values: OK = success / ERROR = error * X ******************************************************************************/ Xint X_create_port(port) XPORTDESCR *port; X{ X#ifdef DEBUG_IPC X if (_debug_ipc) { X fprintf(_debugout, "[ipc] %s ***** _create_port():\n", _processprefix); X fprintf(_debugout, "[ipc] %s &port = %d\n", _processprefix, port); X } X#endif /* DEBUG_IPC /**/ X /* set Errno */ X Errno = ECREATEPORT; X /* create a new message queue */ X DEBUGPUTS("creating message queue"); X if ((port->msqid = create_msq()) < 0) { X DEBUGDISPERR("can't create a new message queue"); X return(ERROR); X } X /* create a new semaphore */ X DEBUGPUTS("creating semaphore"); X if ((port->semid = create_sem()) < 0) { X DEBUGDISPERR("can't create a new semaphore"); X return(ERROR); X } X /* initialize semaphore as locked */ X DEBUGPUTS("initializing semaphore as locked"); X if (sem_set_val(port->semid, LOCKED) < 0) { X DEBUGDISPERR("can't initialize sempahore"); X return(ERROR); X } X return(OK); X} /* _create_port */ X X/****************************************************************************** X * _delete_port() * X * * X * Deletes the communication endpoint specified by 'port'. * X * * X * Return values: OK = success / ERROR = error * X ******************************************************************************/ Xint X_delete_port(port) XPORTDESCR *port; X{ X#ifdef DEBUG_IPC X if (_debug_ipc) { X fprintf(_debugout, "[ipc] %s ***** _delete_port():\n", _processprefix); X _display_port_info("[ipc]", "port", *port); X } X#endif /* DEBUG_IPC /**/ X /* set Errno */ X Errno = EDELETEPORT; X /* remove message queue and semaphore */ X DEBUGPUTS("removing message queue and semaphore"); X if (remove_msq(port->msqid) || remove_sem(port->semid)) { X DEBUGDISPERR("can't remove message queue or semaphore"); X return(ERROR); X } X return(OK); X} /* _delete_port */ X X/****************************************************************************** X * _accept_connection() * X * * X * Communication endpoint 'port' waits 'time' real time seconds for a * X * connection request (if 'time' equals 0 then the operation is unlimited!). * X * * X * Return values: OK = success / ERROR = error * X ******************************************************************************/ Xint X_accept_connection(con_port, port, time) XCONNECTIONDESCR *con_port; XPORTDESCR *port; Xunsigned time; X{ X register int i; X int rcv_msqid; X static struct msgbuf msgp; X static struct msqid_ds msqbuf; X static struct sembuf sops; X static PORTDESCR snd_port; X X#ifdef DEBUG_IPC X if (_debug_ipc) { X fprintf(_debugout, "[ipc] %s ***** _accept_connection():\n", X _processprefix); X fprintf(_debugout, "[ipc] %s &con_port = %d\n", _processprefix, X con_port); X _display_port_info("[ipc]", "port", *port); X fprintf(_debugout, "[ipc] %s time = %d\n", _processprefix, time); X } X#endif /* DEBUG_IPC /**/ X /* set Errno */ X Errno = EACPTCON; X /* set timer, if time equals 0 clear timer */ X SETTIMER(time); X /* try to get a connection request message */ X do { X /* unlock port! */ X DEBUGPUTS("unlocking port"); X sops.sem_num = 0; X sops.sem_op = 1; X sops.sem_flg = 0; X if (semop(port->semid, &sops, 1)) { X DEBUGDISPERR("can't unlock port"); X return(ERROR); X } X /* get first message of own message queue */ X DEBUGPUTS("receiving request"); X if (time == 0) { X if (msgrcv(port->msqid,&msgp,sizeof(PORTDESCR),(long) 0,0) < 0) { X sops.sem_num = 0; X sops.sem_op = -1; X sops.sem_flg = 0; X if (semop(port->semid, &sops, 1)) { X DEBUGDISPERR("can't do semaphore operation"); X return(ERROR); X } X DEBUGPUTS("port locked"); X DEBUGDISPERR("can't receive request message"); X return(ERROR); X } X } else { X do { X if (timeout) { X sops.sem_num = 0; X sops.sem_op = -1; X sops.sem_flg = 0; X if (semop(port->semid, &sops, 1)) { X DEBUGDISPERR("can't do semaphore operation"); X return(ERROR); X } X DEBUGPUTS("port unlocked"); X } X RETURN_IF_TIMEOUT; X } while(msgrcv(port->msqid,&msgp,sizeof(PORTDESCR),(long) 0,0) < 0); X } X DEBUGPUTS("port locked"); X } while(msgp.mtype != CONNECTION_REQUEST); X /* connection established. Now initialize con_port! */ X (void) memcpy(&snd_port, msgp.mtext, sizeof(PORTDESCR)); X con_port->own_port.msqid = port->msqid; X con_port->own_port.semid = port->semid; X con_port->other_port.msqid = snd_port.msqid; X con_port->other_port.semid = snd_port.semid; X#ifdef DEBUG_IPC X if (_debug_ipc) { X fprintf(_debugout, "[ipc] %s got a connection\n", _processprefix); X _display_connection_port_info("[ipc]", "con_port", *con_port); X } X#endif /* DEBUG_IPC /**/ X /* clear own message queue and send connection refused messages to X * all other connection requesters X */ X DEBUGPUTS("clearing own message queue!"); X if (msq_get_status(port->msqid, &msqbuf)) { X DEBUGDISPERR("can't get status of message queue"); X return(ERROR); X } X for (i=1; i<=msqbuf.msg_qnum; i++) { X if (msgrcv(port->msqid, &msgp, MAXMSGSIZE, (long) 0, 0) < 0) { X DEBUGDISPERR("can't delete useless message"); X return(ERROR); X } X /* only connection requests are of interest! */ X if (msgp.mtype != CONNECTION_REQUEST) X continue; X /* determine sender */ X (void) memcpy(&snd_port, msgp.mtext, sizeof(PORTDESCR)); X rcv_msqid = snd_port.msqid; X#ifdef DEBUG_IPC X if (_debug_ipc) X fprintf(_debugout, "[ipc] connection to port (msqid = %d, semid = %d) refused\n", X snd_port.msqid, snd_port.semid); X#endif /* DEBUG_IPC /**/ X /* send reply message to refused requester */ X msgp.mtype = CONNECTION_REFUSED; X snd_port.msqid = port->msqid; X snd_port.semid = port->semid; X (void) memcpy(msgp.mtext, &snd_port, sizeof(PORTDESCR)); X if (msgsnd(rcv_msqid, &msgp, sizeof(PORTDESCR), 0)) { X DEBUGDISPERR("can't send >>connection refused<< message"); X return(ERROR); X } X } /* for */ X DEBUGPUTS("sending reply"); X /* send reply message to accepted connection requester */ X msgp.mtype = CONNECTION_ACCEPTED; X snd_port.msqid = port->msqid; X snd_port.semid = port->semid; X (void) memcpy(msgp.mtext, &snd_port, sizeof(PORTDESCR)); X if (time == 0) { X if (msgsnd(con_port->other_port.msqid,&msgp,sizeof(PORTDESCR),0)) { X DEBUGDISPERR("can't send reply message"); X return(ERROR); X } X } else { X do { X RETURN_IF_TIMEOUT; X } while(msgsnd(con_port->other_port.msqid,&msgp,sizeof(PORTDESCR),0)<0); X } X /* clear timer and return */ X (void) alarm(0); X DEBUGPUTS("connection accepted"); X return(OK); X} /* _accept_connection */ X X/****************************************************************************** X * _make_connection() * X * * X * Communication endpoint 'port1' tries 'time' real time seconds to connect * X * to 'port2' (if 'time' equals 0 then the operation is unlimited!). * X * * X * Return values: OK = success / ERROR = error * X ******************************************************************************/ Xint X_make_connection(con_port, port1, port2, time) XCONNECTIONDESCR *con_port; XPORTDESCR *port1; XPORTDESCR *port2; Xunsigned time; X{ X static struct msgbuf msgp; X static struct sembuf sops; X static PORTDESCR snd_port; X X#ifdef DEBUG_IPC X if (_debug_ipc) { X fprintf(_debugout, "[ipc] %s ***** _make_connection():\n", X _processprefix); X fprintf(_debugout, "[ipc] %s &con_port = %d\n", _processprefix, X con_port); X _display_port_info("[ipc]", "port1", *port1); X _display_port_info("[ipc]", "port2", *port2); X fprintf(_debugout, "[ipc] %s time = %d\n", _processprefix, time); X } X#endif /* DEBUG_IPC /**/ X /* Set Errno */ X Errno = EMAKECON; X /* set timer, if time equals 0 clear timer */ X SETTIMER(time); X /* initialize request message */ X msgp.mtype = CONNECTION_REQUEST; X snd_port.msqid = port1->msqid; X snd_port.semid = port1->semid; X (void) memcpy(msgp.mtext, &snd_port, sizeof(PORTDESCR)); X while(!timeout) { X if (time == 0) { X /* X * without time limit! X */ X /* wait as long as other port is locked */ X sops.sem_num = 0; X sops.sem_op = -1; X sops.sem_flg = 0; X if (semop(port2->semid, &sops, 1)) { X DEBUGDISPERR("can't do semaphore operation"); X return(ERROR); X } X DEBUGPUTS("port unlocked"); X /* send request message */ X DEBUGPUTS("sending request"); X if (msgsnd(port2->msqid, &msgp, sizeof(PORTDESCR), 0)) { X DEBUGDISPERR("can't send request message"); X return(ERROR); X } X /* wait for reply message */ X DEBUGPUTS("receiving reply"); X if (msgrcv(port1->msqid, &msgp, sizeof(PORTDESCR), (long) 0,0) < 0){ X DEBUGDISPERR("can't receive reply message"); X return(ERROR); X } X } else { X /* X * with time limit! X */ X /* wait as long as other port is locked */ X sops.sem_num = 0; X sops.sem_op = -1; X sops.sem_flg = 0; X if (semop(port2->semid, &sops, 1)) { X if (errno == EINTR && timeout) { X Errno = ETIMEOUT; X DEBUGPUTS("TIMEOUT"); X } else X DEBUGDISPERR("can't do semaphore operation"); X return(ERROR); X } X DEBUGPUTS("port unlocked"); X /* send request message */ X DEBUGPUTS("sending request"); X do { X RETURN_IF_TIMEOUT; X } while(msgsnd(port2->msqid, &msgp, sizeof(PORTDESCR), 0) < 0); X /* wait for reply message */ X DEBUGPUTS("receiving reply"); X do { X RETURN_IF_TIMEOUT; X } while(msgrcv(port1->msqid,&msgp,sizeof(PORTDESCR),(long)0,0) < 0); X } X switch(msgp.mtype) { X case CONNECTION_ACCEPTED: X con_port->own_port.msqid = port1->msqid; X con_port->own_port.semid = port1->semid; X con_port->other_port.msqid = port2->msqid; X con_port->other_port.semid = port2->semid; X mcon_retry_delay = MCON_RETRY_DELAY_MIN; X#ifdef DEBUG_IPC X if (_debug_ipc) { X fprintf(_debugout, "[ipc] %s connection established\n", X _processprefix); X _display_connection_port_info("[ipc]", "con_port", *con_port); X fprintf(_debugout, "[ipc] %s retry delay now %d\n", X _processprefix, mcon_retry_delay); X if (_debugflush) X fflush(_debugout); X } X#endif /* DEBUG_IPC /**/ X /* clear timer and return */ X (void) alarm(0); X return(OK); X /* break; */ X case CONNECTION_REQUEST: X case CONNECTION_REFUSED: X if (msgp.mtype == CONNECTION_REFUSED) { X DEBUGPUTS("connection refused"); X } else { X DEBUGPUTS("wrong reply message"); X } X nap(mcon_retry_delay); X if (mcon_retry_delay < MCON_RETRY_DELAY_MAX) X mcon_retry_delay += MCON_RETRY_DELAY_STEP; X#ifdef DEBUG_IPC X if (_debug_ipc) { X fprintf(_debugout, "[ipc] %s retry delay now %d\n", X _processprefix, mcon_retry_delay); X if (_debugflush) X fflush(_debugout); X } X#endif /* DEBUG_IPC /**/ X DEBUGPUTS("trying again"); X continue; X /* break; */ X default: X DEBUGPUTS("unknown reply message"); X errno = 0; X Errno = EFATAL; X return(ERROR); X } /* switch */ X } /* while */ X DEBUGPUTS("TIMEOUT"); X mcon_retry_delay = MCON_RETRY_DELAY_MIN; X#ifdef DEBUG_IPC X if (_debug_ipc) { X fprintf(_debugout, "[ipc] %s retry delay now %d\n", X _processprefix, mcon_retry_delay); X if (_debugflush) X fflush(_debugout); X } X#endif /* DEBUG_IPC /**/ X Errno = ETIMEOUT; X return(ERROR); X} /* _make_connection */ X X/****************************************************************************** X * _close_connection() * X * * X * The connection associated to connection port 'con_port' is closed. * X * * X * Return values: OK = success / ERROR = error * X ******************************************************************************/ Xint X_close_connection(con_port) XCONNECTIONDESCR *con_port; X{ X register int i; X static struct msqid_ds msqbuf; X static struct msgbuf msgp; X X#ifdef DEBUG_IPC X if (_debug_ipc) { X fprintf(_debugout, "[ipc] %s ***** _close_connection():\n", X _processprefix); X _display_connection_port_info("[ipc]", "con_port", *con_port); X } X#endif /* DEBUG_IPC /**/ X /* Set Errno */ X Errno = ECLOSECON; X /* delete all messages of own message queue */ X if (msq_get_status(con_port->own_port.msqid, &msqbuf)) { X DEBUGDISPERR("can't get status of message queue"); X return(ERROR); X } X#ifdef DEBUG_IPC X if (_debug_ipc) X fprintf(_debugout, "[ipc] %s deleting %d messages\n", _processprefix, X msqbuf.msg_qnum); X#endif X for (i=1; i<=msqbuf.msg_qnum; i++) { X if (msgrcv(con_port->own_port.msqid,&msgp,MAXMSGSIZE,(long) 0,0) < 0) { X DEBUGDISPERR("can't delete message"); X return(ERROR); X } X } X DEBUGPUTS("connection closed"); X return(OK); X} /* _close_connection */ X X/****************************************************************************** X * _recv_data() * X * * X * 'number' bytes are received from connection port 'con_port' and stored * X * into 'buffer'. 'time' is the maximum real time in seconds to wait for a * X * message to arrive (if 'time' equals 0 the waiting is unlimited). * X * * X * Return values: number of received bytes upon success / ERROR = error * X ******************************************************************************/ Xint X_recv_data(con_port, buffer, number, time) XCONNECTIONDESCR *con_port; Xchar *buffer; Xint number; Xunsigned time; X{ X int bytes; X static struct msgbuf msgp; X X#ifdef DEBUG_IPC X if (_debug_ipc) { X fprintf(_debugout, "[ipc] %s ***** _recv_data():\n", _processprefix); X _display_connection_port_info("[ipc]", "con_port", *con_port); X fprintf(_debugout, "[ipc] %s buffer = %d, number = %d\n", X _processprefix, buffer, number); X fprintf(_debugout, "[ipc] %s time = %d\n", _processprefix, time); X } X#endif /* DEBUG_IPC /**/ X /* set Errno */ X Errno = ERECVDATA; X /* set timer, if time equals 0 clear timer */ X SETTIMER(time); X if (time == 0) { X if ((bytes = msgrcv(con_port->own_port.msqid,&msgp,number,(long) 0,0)) < 0) { X DEBUGDISPERR("can't receive message"); X return(ERROR); X } X } else { X do { X RETURN_IF_TIMEOUT; X } while((bytes = msgrcv(con_port->own_port.msqid,&msgp,number,(long) 0,0)) < 0); X } X /* check for correct sender! */ X if (msgp.mtype != con_port->other_port.msqid) { X fputs("Panic: disastrous error in _recv_data(ipc_Xenix.c):\n", stderr); X fputs(" wrong message received!\n", stderr); X fprintf(stderr, " msgp.mtype = %d, con_port->other_port.msqid = %d\n", X msgp.mtype, con_port->other_port.msqid); X fputs(" stopping program!\n", stderr); X fflush(stderr); X exit(-1); X } X (void) memcpy(buffer, msgp.mtext, bytes); X (void) alarm(0); X return(bytes); X} /* _recv_data */ X X/****************************************************************************** X * _send_data() * X * * X * 'number' bytes, stored in 'buffer', are send to connection port 'con_port'.* X * 'time' is the maximum real time in seconds to retry sending upon error (if * X * 'time' equals 0 the waiting is unlimited). * X * * X * Return values: number of sent bytes upon success / ERROR = error * X ******************************************************************************/ Xint X_send_data(con_port, buffer, number, time) XCONNECTIONDESCR *con_port; Xchar *buffer; Xint number; Xunsigned time; X{ X static struct msgbuf msgp; X X#ifdef DEBUG_IPC X if (_debug_ipc) { X fprintf(_debugout, "[ipc] %s ***** _send_data():\n", _processprefix); X _display_connection_port_info("[ipc]", "con_port", *con_port); X fprintf(_debugout, "[ipc] %s buffer = %d, number = %d\n", X _processprefix, buffer, number); X fprintf(_debugout, "[ipc] %s time = %d\n", _processprefix, time); X } X#endif /* DEBUG_IPC /**/ X /* set Errno */ X Errno = ESENDDATA; X /* set timer, if time equals 0 clear timer */ X SETTIMER(time); X /* message type is the own message queue identifier. X * This is used to verifiy message passing! X */ X msgp.mtype = (long) con_port->own_port.msqid; X (void) memcpy(msgp.mtext, buffer, number); X if (time == 0) { X if (msgsnd(con_port->other_port.msqid, &msgp, number, 0)) { X DEBUGDISPERR("can't send message"); X return(ERROR); X } X } else { X do { X RETURN_IF_TIMEOUT; X } while(msgsnd(con_port->other_port.msqid, &msgp, number, 0) < 0); X } X (void) alarm(0); X return(number); X} /* _send_data */ X X/* ============================= DEBUG Routines ============================= */ X X/****************************************************************************** X * _display_port_info() * X * * X * Displays the components of the structure PORTDESCR specified by 'port'. * X * * X * Return values: always OK for success * X ******************************************************************************/ Xint X_display_port_info(prefix, msg, port) Xchar *prefix, *msg; XPORTDESCR port; X{ X fprintf(_debugout, "%s %s %s: msqid = %d, semid = %d\n", prefix, X _processprefix, msg, port.msqid, port.semid); X return(OK); X} /* _display_port_info */ X X/****************************************************************************** X * _display_connection_port_info() * X * * X * Displays the components of the structure CONNECTIONDESCR specified by * X * 'con_port'. * X * * X * Return values: always OK for success * X ******************************************************************************/ Xint X_display_connection_port_info(prefix, msg, con_port) Xchar *prefix, *msg; XCONNECTIONDESCR con_port; X{ X fprintf(_debugout, "%s %s %s: own_port: msqid = %d, semid = %d\n", prefix, X _processprefix, msg, con_port.own_port.msqid, con_port.own_port.semid); X fprintf(_debugout, "%s %s %s: other_port: msqid = %d, semid = %d\n", prefix, X _processprefix, msg, con_port.other_port.msqid, X con_port.other_port.semid); X return(OK); X} /* _display_connection_port_info */ X X/****************************************************************************** X * _input_port_info() * X * * X * Input the port information for 'port'. * X * * X * Return values: none * X ******************************************************************************/ Xint X_input_port_info(port) XPORTDESCR *port; X{ X printf("msqid = "); X scanf("%d", &(port->msqid)); X printf("semid = "); X scanf("%d", &(port->semid)); X} /* _input_port_info */ END_OF_FILE if test 41235 -ne `wc -c <'lib/ipc_msgsem.c'`; then echo shar: \"'lib/ipc_msgsem.c'\" unpacked with wrong size! fi # end of 'lib/ipc_msgsem.c' fi echo shar: End of archive 16 \(of 18\). cp /dev/null ark16isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 18 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0