home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume27
/
distributed-c-2.1
/
part16
< prev
next >
Wrap
Text File
|
1993-12-22
|
89KB
|
2,815 lines
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 <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 16 (of 18)."
# Contents: dcc/dcc.y lib/ipc_msgsem.c
# Wrapped by vixie@gw.home.vix.com on Thu Dec 23 00:12:06 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'dcc/dcc.y' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'dcc/dcc.y'\"
else
echo shar: Extracting \"'dcc/dcc.y'\" \(42425 characters\)
sed "s/^X//" >'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 <stdio.h>
X#include <string.h>
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 <y_str> ENUMCONST
X%token <y_symb> IDENT TYPEDEF_NAME
X
X/*
X * nonterminal types
X */
X
X%type <y_str> translation_unit external_declaration function_definition
X%type <y_str> declaration declaration_list enumerator_list enumerator
X%type <y_str> parameter_type_list parameter_list parameter_declaration
X%type <y_str> identifier_list initializer initializer_list type_name
X%type <y_str> abstract_declarator direct_abstract_declarator
X%type <y_str> logical_OR_expression statement labeled_statement
X%type <y_str> expression_statement statement_list selection_statement
X%type <y_str> iteration_statement jump_statement select_statement
X%type <y_str> expression assignment_expression assignment_operator
X%type <y_str> conditional_expression constant_expression
X%type <y_str> logical_AND_expression inclusive_OR_expression
X%type <y_str> exclusive_OR_expression AND_expression equality_expression
X%type <y_str> relational_expression shift_expression additive_expression
X%type <y_str> multiplicative_expression cast_expression unary_expression
X%type <y_str> unary_operator process_creation parameterleiste
X%type <y_str> primary_expression argument_expression_list constant
X%type <y_str> process_location opt_identifier_list destroy_statement
X%type <y_str> process_definition immediate_alternative
X%type <y_str> timed_transaction_call
X%type <y_symb> process_parameter_list process_specification process_parameters
X%type <y_symb> process_transactions transaction_declaration
X%type <y_symb> transaction_declaration_list
X%type <y_arg> process_arguments process_arg_expr_list
X%type <y_comp> compound_statement
X%type <y_accept> accept_statement
X%type <y_select> select_list select_part alternative accept_alternative
X%type <y_select> terminate_alternative
X%type <y_post> postfix_expression
X%type <y_trans> transaction_call
X
X%type <y_ds> declaration_specifiers
X%type <y_scs> storage_class_specifier
X%type <y_ts> type_specifier
X%type <y_tq> type_qualifier
X%type <y_sus> struct_or_union_specifier
X%type <y_stl> struct_declaration_list
X%type <y_st> struct_declaration
X%type <y_sql> specifier_qualifier_list
X%type <y_sdl> struct_declarator_list
X%type <y_sd> struct_declarator
X%type <y_d> declarator
X%type <y_dd> direct_declarator
X%type <y_su> struct_or_union
X%type <y_p> pointer
X%type <y_tql> type_qualifier_list
X%type <y_es> enum_specifier
X%type <y_id> init_declarator
X%type <y_idl> 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 <stdio.h>
X#include <sys/types.h>
X#include <sys/ipc.h>
X#include <sys/msg.h>
X#include <sys/sem.h>
X#include <errno.h>
X#include <memory.h>
X#include <signal.h>
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