1/*
2 * Copyright (c) 2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1.  Redistributions of source code must retain the above copyright
11 *     notice, this list of conditions and the following disclaimer.
12 * 2.  Redistributions in binary form must reproduce the above copyright
13 *     notice, this list of conditions and the following disclaimer in the
14 *     documentation and/or other materials provided with the distribution.
15 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
16 *     contributors may be used to endorse or promote products derived from
17 *     this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * Portions of this software have been released under the following terms:
31 *
32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC.
33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY
34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION
35 *
36 * To anyone who acknowledges that this file is provided "AS IS"
37 * without any express or implied warranty:
38 * permission to use, copy, modify, and distribute this file for any
39 * purpose is hereby granted without fee, provided that the above
40 * copyright notices and this notice appears in all source code copies,
41 * and that none of the names of Open Software Foundation, Inc., Hewlett-
42 * Packard Company or Digital Equipment Corporation be used
43 * in advertising or publicity pertaining to distribution of the software
44 * without specific, written prior permission.  Neither Open Software
45 * Foundation, Inc., Hewlett-Packard Company nor Digital
46 * Equipment Corporation makes any representations about the suitability
47 * of this software for any purpose.
48 *
49 * Copyright (c) 2007, Novell, Inc. All rights reserved.
50 * Redistribution and use in source and binary forms, with or without
51 * modification, are permitted provided that the following conditions
52 * are met:
53 *
54 * 1.  Redistributions of source code must retain the above copyright
55 *     notice, this list of conditions and the following disclaimer.
56 * 2.  Redistributions in binary form must reproduce the above copyright
57 *     notice, this list of conditions and the following disclaimer in the
58 *     documentation and/or other materials provided with the distribution.
59 * 3.  Neither the name of Novell Inc. nor the names of its contributors
60 *     may be used to endorse or promote products derived from this
61 *     this software without specific prior written permission.
62 *
63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY
67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
73 *
74 * @APPLE_LICENSE_HEADER_END@
75 */
76
77/*
78**
79**  NAME:
80**
81**      acf.y
82**
83**  FACILITY:
84**
85**      Interface Definition Language (IDL) Compiler
86**
87**  ABSTRACT:
88**
89**  ACF Parser Grammar and parser helper functions
90**
91**  VERSION: DCE 1.0
92**
93*/
94
95/*******************************
96 *  parser declarations section  *
97 *******************************/
98
99%{
100
101  /* Tank Trap to stop older yacc parsers */
102  /* Bison defines the macro YYBISON      */
103
104#ifndef YYBISON
105This grammar file needs to be built with GNU Bison V1.25 or later.
106  GNU Bison can be be obtained from ftp://prep.ai.mit.edu:/pub/gnu
107#endif
108
109/* Declarations in this section are copied from yacc source to y_tab.c. */
110#include <stdarg.h>
111
112#include <nidl.h>               /* IDL compiler-wide defs */
113
114#include <ast.h>                /* Abstract Syntax Tree defs */
115#include <astp.h>               /* Import AST processing routine defs */
116#include <command.h>            /* Command line defs */
117#include <message.h>            /* Error message defs */
118#include <nidlmsg.h>            /* Error message IDs */
119#include <files.h>
120#include <propagat.h>
121#include <checker.h>
122
123#define YYDEBUG 1
124
125extern AST_interface_n_t *the_interface;    /* Ptr to AST interface node */
126extern boolean ASTP_parsing_main_idl;       /* True when parsing main IDL */
127
128typedef union                   /* Attributes bitmask */
129{
130    struct
131    {
132        unsigned auto_handle    : 1;
133        unsigned binding_callout: 1;
134        unsigned code           : 1;
135        unsigned comm_status    : 1;
136        unsigned cs_char        : 1;
137        unsigned cs_drtag       : 1;
138        unsigned cs_rtag        : 1;
139        unsigned cs_stag        : 1;
140        unsigned cs_tag_rtn     : 1;
141        unsigned decode         : 1;
142        unsigned enable_allocate: 1;
143        unsigned encode         : 1;
144        unsigned explicit_handle: 1;
145        unsigned extern_exceps  : 1;
146        unsigned fault_status   : 1;
147        unsigned heap           : 1;
148        unsigned implicit_handle: 1;
149        unsigned in_line        : 1;
150        unsigned nocode         : 1;
151        unsigned out_of_line    : 1;
152        unsigned represent_as   : 1;
153        unsigned nocancel       : 1;
154    }   bit;
155    long    mask;
156}   acf_attrib_t;
157
158typedef struct acf_param_t      /* ACF parameter info structure */
159{
160    struct acf_param_t *next;                   /* Forward link */
161    acf_attrib_t    parameter_attr;             /* Parameter attributes */
162    NAMETABLE_id_t  param_id;                   /* Parameter name */
163}   acf_param_t;
164
165/* An opaque pointer. */
166#ifndef YY_TYPEDEF_YY_SCANNER_T
167#define YY_TYPEDEF_YY_SCANNER_T
168typedef void* yyscan_t;
169#endif
170
171typedef struct acf_parser_state_t
172{
173    yyscan_t	acf_yyscanner;
174    unsigned	acf_yynerrs;
175    parser_location_t acf_location;
176
177    boolean	acf_dumpers;
178
179    acf_attrib_t acf_interface_attr;	/* Interface attributes */
180    acf_attrib_t acf_type_attr;		/* Type attributes */
181    acf_attrib_t acf_operation_attr;	/* Operation attributes */
182    acf_attrib_t acf_parameter_attr;	/* Parameter attributes */
183
184    const char * acf_interface_name;        /* Interface name */
185    const char * acf_impl_name;             /* Implicit handle name */
186    const char * acf_type_name;             /* Current type name */
187    const char * acf_repr_type_name;        /* Current represent_as type */
188    const char * acf_cs_char_type_name;     /* Current cs_char type */
189    const char * acf_operation_name;        /* Current operation name */
190    const char * acf_cs_tag_rtn_name;       /* Current cs_tag_rtn name */
191    const char * acf_binding_callout_name;  /* Current binding_callout name */
192    boolean	 acf_named_type;    /* True if parsed type is named type */
193
194    AST_include_n_t * acf_include_list;	    /* List of AST include nodes */
195    AST_include_n_t * acf_include_p;        /* Ptr to a created include node */
196
197    acf_param_t * acf_parameter_list;	    /* Param list for curr. operation */
198    acf_param_t * acf_parameter_free_list;  /* True if param attrs specified */
199    boolean       acf_parameter_attr_list;  /* True if param attrs specified */
200} acf_parser_state_t;
201
202/*
203 * Forward declarations to shut up the compiler
204 */
205
206static boolean lookup_exception(acf_parser_state_t *, NAMETABLE_id_t,
207	boolean, AST_exception_n_t **);
208static boolean lookup_type(acf_parser_state_t *, char const *, boolean,
209	NAMETABLE_id_t *, AST_type_n_t **);
210static boolean lookup_operation(acf_parser_state_t *, char const *,
211	boolean, NAMETABLE_id_t *, AST_operation_n_t **);
212static boolean lookup_parameter(acf_parser_state_t *, AST_operation_n_t *,
213	char const *, boolean, NAMETABLE_id_t *, AST_parameter_n_t **);
214static boolean lookup_rep_as_name(AST_type_p_n_t *, NAMETABLE_id_t, AST_type_n_t **, char const **);
215static boolean lookup_cs_char_name(AST_type_p_n_t *, NAMETABLE_id_t, AST_type_n_t **, char const * *);
216static acf_param_t * alloc_param(acf_parser_state_t *);
217static void free_param(acf_parser_state_t *, acf_param_t *);
218static void free_param_list(acf_parser_state_t *, acf_param_t **);
219void add_param_to_list(acf_param_t *, acf_param_t **);
220static void append_parameter(acf_parser_state_t *, AST_operation_n_t *,
221	char const *, acf_attrib_t *);
222static void process_rep_as_type(acf_parser_state_t *, AST_interface_n_t *,
223	AST_type_n_t *, char const *);
224static void process_cs_char_type(acf_parser_state_t *, AST_interface_n_t *,
225	AST_type_n_t *, char const *);
226static void dump_attributes(acf_parser_state_t *, const char *, const char *, acf_attrib_t *);
227
228/*
229 * Warning and Error stuff
230 */
231
232static void acf_yyerror ( YYLTYPE *, acf_parser_p, char const *);
233
234/*
235**  a c f _ e r r o r
236**
237**  Issues an error message, and bumps the error count.
238**
239*/
240static void acf_error
241(
242    acf_parser_state_t * acf,
243    long msgid,
244    ...
245)
246{
247    va_list ap;
248
249    va_start(ap, msgid);
250    vlog_error(acf_yylineno(acf), msgid, ap);
251    va_end(ap);
252
253    acf->acf_yynerrs++;
254}
255
256/*
257**  a c f _ w a r n i n g
258**
259**  Issues a warning message.
260**
261*/
262static void acf_warning
263(
264    acf_parser_state_t * acf,
265    long msgid,
266    ...
267)
268{
269    va_list ap;
270
271    va_start(ap, msgid);
272
273    vlog_warning(acf_yylineno(acf), msgid, ap);
274
275    va_end(ap);
276}
277
278%}
279
280%locations
281%defines
282%error-verbose
283%pure-parser
284%name-prefix="acf_yy"
285
286/* Tell Bison that the Flexer takes a yyscan_t parameter. */
287%lex-param { void * lexxer }
288/* Tell Bison that we will pass the yyscan_t scanner into yyparse. */
289%parse-param { acf_parser_state_t * acf }
290
291/* Tell Bison how to get the lexxer argument from the parser state. */
292%{
293#define lexxer acf->acf_yyscanner
294%}
295
296/*------------------------------------*
297 *  yylval and yyval type definition  *
298 *------------------------------------*/
299
300/*
301 * Union declaration defines the possible datatypes of the external variables
302 * yylval and yyval.
303 */
304
305%union
306{
307    NAMETABLE_id_t  y_id;       /* Identifier */
308    STRTAB_str_t    y_string;   /* Text string */
309}
310
311%{
312#include <acf_l.h>
313%}
314
315/*-----------------------------*
316 *  Tokens used by the parser  *
317 *-----------------------------*/
318
319/* Keywords */
320
321%token AUTO_HANDLE_KW
322%token BINDING_CALLOUT_KW
323%token CODE_KW
324%token COMM_STATUS_KW
325%token CS_CHAR_KW
326%token CS_TAG_RTN_KW
327%token ENABLE_ALLOCATE_KW
328%token EXPLICIT_HANDLE_KW
329%token EXTERN_EXCEPS_KW
330%token FAULT_STATUS_KW
331%token HANDLE_T_KW
332%token HEAP_KW
333%token IMPLICIT_HANDLE_KW
334%token INCLUDE_KW
335%token INTERFACE_KW
336%token IN_LINE_KW
337%token NOCODE_KW
338%token NOCANCEL_KW
339%token OUT_OF_LINE_KW
340%token REPRESENT_AS_KW
341%token TYPEDEF_KW
342
343/* Punctuation */
344
345%token COMMA
346%token LBRACE
347%token LBRACKET
348%token LPAREN
349%token RBRACE
350%token RBRACKET
351%token RPAREN
352%token SEMI
353%token TILDE
354%token UNKNOWN  /* Unrecognized by LEX */
355
356/* Tokens setting yylval */
357
358%token <y_id>       IDENTIFIER
359%token <y_string>   STRING
360
361/*-----------------------------*
362 *  Starting state for parser  *
363 *-----------------------------*/
364
365%start acf_interface
366
367%%
368
369/****************************
370 *  parser grammar section  *
371 ****************************/
372
373acf_interface:
374        acf_interface_header acf_interface_body
375    ;
376
377acf_interface_header:
378        acf_interface_attr_list INTERFACE_KW acf_interface_name
379    {
380        char const      *ast_int_name;  /* Interface name in AST node */
381        NAMETABLE_id_t  impl_name_id;   /* Nametable id of impl_handle var */
382
383        if (acf->acf_dumpers)
384	{
385            dump_attributes(acf, "ACF interface", acf->acf_interface_name,
386		    &acf->acf_interface_attr);
387	}
388
389        /* Store source information. */
390        if (the_interface->fe_info != NULL)
391        {
392            the_interface->fe_info->acf_file = acf->acf_location.fileid;
393            the_interface->fe_info->acf_source_line = acf_yylineno(acf);
394        }
395
396        /*
397         *  Interface attributes are saved for main and imported interfaces.
398         *  the_interface = pointer to main or imported interface node
399         *
400         *  Make sure that the interface name in the ACF agrees with the
401         *  interface name in the main IDL file.  Then set the parsed
402         *  attributes in the interface node.
403         *
404         *  interface_attr = bitmask of interface attributes parsed.
405         *  interface_name = ACF interface name parsed.
406         */
407
408        NAMETABLE_id_to_string(the_interface->name, &ast_int_name);
409
410        if (strcmp(acf->acf_interface_name, ast_int_name) != 0)
411        {
412            char const *acf_int_name;   /* Ptr to permanent copy */
413            NAMETABLE_id_t name_id;     /* Handle on permanent copy */
414            char const *file_name;      /* Related file name */
415
416            name_id = NAMETABLE_add_id(acf->acf_interface_name);
417            NAMETABLE_id_to_string(name_id, &acf_int_name);
418
419            STRTAB_str_to_string(the_interface->fe_info->file, &file_name);
420
421            acf_error(acf, NIDL_INTNAMDIF, acf_int_name, ast_int_name);
422            acf_error(acf, NIDL_NAMEDECLAT, ast_int_name, file_name,
423                      the_interface->fe_info->source_line);
424        }
425        else
426        {
427            if (acf->acf_interface_attr.bit.code)
428                AST_SET_CODE(the_interface);
429            if (acf->acf_interface_attr.bit.nocode)
430                AST_SET_NO_CODE(the_interface);
431            if (acf->acf_interface_attr.bit.decode)
432                AST_SET_DECODE(the_interface);
433            if (acf->acf_interface_attr.bit.encode)
434                AST_SET_ENCODE(the_interface);
435            if (acf->acf_interface_attr.bit.explicit_handle)
436                AST_SET_EXPLICIT_HANDLE(the_interface);
437            if (acf->acf_interface_attr.bit.in_line)
438                AST_SET_IN_LINE(the_interface);
439            if (acf->acf_interface_attr.bit.out_of_line)
440                AST_SET_OUT_OF_LINE(the_interface);
441            if (acf->acf_interface_attr.bit.auto_handle)
442                AST_SET_AUTO_HANDLE(the_interface);
443            if (acf->acf_interface_attr.bit.nocancel)
444                AST_SET_NO_CANCEL(the_interface);
445
446            if (acf->acf_interface_attr.bit.cs_tag_rtn)
447                the_interface->cs_tag_rtn_name = NAMETABLE_add_id(acf->acf_cs_tag_rtn_name);
448            if (acf->acf_interface_attr.bit.binding_callout)
449	    {
450                the_interface->binding_callout_name =
451		    NAMETABLE_add_id(acf->acf_binding_callout_name);
452	    }
453
454            if (acf->acf_interface_attr.bit.implicit_handle)
455            {
456                /* Store the [implicit_handle] variable name in nametbl. */
457                impl_name_id = NAMETABLE_add_id(acf->acf_impl_name);
458
459	        ASTP_set_implicit_handle(the_interface,
460		    acf->acf_named_type ? NAMETABLE_add_id(acf->acf_type_name)
461			       : NAMETABLE_NIL_ID,
462		    impl_name_id);
463
464            }
465        }
466
467        acf->acf_interface_name = NULL;
468        acf->acf_type_name = NULL;
469        acf->acf_impl_name = NULL;
470        acf->acf_binding_callout_name = NULL;
471        acf->acf_cs_tag_rtn_name = NULL;
472        acf->acf_interface_attr.mask = 0;        /* Reset attribute mask */
473    }
474    ;
475
476acf_interface_attr_list:
477        LBRACKET acf_interface_attrs RBRACKET
478    |   /* Nothing */
479    ;
480
481acf_interface_attrs:
482        acf_interface_attr
483    |   acf_interface_attrs COMMA acf_interface_attr
484    ;
485
486acf_interface_attr:
487        acf_code_attr
488    {
489        if (acf->acf_interface_attr.bit.code)
490            log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
491        acf->acf_interface_attr.bit.code = TRUE;
492    }
493    |   acf_nocode_attr
494    {
495        if (acf->acf_interface_attr.bit.nocode)
496            log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
497        acf->acf_interface_attr.bit.nocode = TRUE;
498    }
499    |   acf_binding_callout_attr
500    {
501        if (acf->acf_interface_attr.bit.binding_callout)
502            log_error(acf_yylineno(acf), NIDL_ATTRUSEMULT, NULL);
503        acf->acf_interface_attr.bit.binding_callout = TRUE;
504    }
505    |   acf_cs_tag_rtn_attr
506    {
507        if (acf->acf_interface_attr.bit.cs_tag_rtn)
508            log_error(acf_yylineno(acf), NIDL_ATTRUSEMULT, NULL);
509        acf->acf_interface_attr.bit.cs_tag_rtn = TRUE;
510    }
511    |   acf_explicit_handle_attr
512    {
513        if (acf->acf_interface_attr.bit.explicit_handle)
514            log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
515        acf->acf_interface_attr.bit.explicit_handle = TRUE;
516    }
517    |   acf_nocancel_attr
518    {
519        if (acf->acf_interface_attr.bit.nocancel)
520            log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
521        acf->acf_interface_attr.bit.nocancel = TRUE;
522    }
523    |   acf_inline_attr
524    {
525        if (acf->acf_interface_attr.bit.in_line)
526            log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
527        acf->acf_interface_attr.bit.in_line = TRUE;
528    }
529    |   acf_outofline_attr
530    {
531        if (acf->acf_interface_attr.bit.out_of_line)
532            log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
533        acf->acf_interface_attr.bit.out_of_line = TRUE;
534    }
535    |   acf_implicit_handle_attr
536    {
537        if (acf->acf_interface_attr.bit.implicit_handle)
538            log_error(acf_yylineno(acf), NIDL_ATTRUSEMULT, NULL);
539        acf->acf_interface_attr.bit.implicit_handle = TRUE;
540    }
541    |   acf_auto_handle_attr
542    {
543        if (acf->acf_interface_attr.bit.auto_handle)
544            log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
545        acf->acf_interface_attr.bit.auto_handle = TRUE;
546    }
547    |   acf_extern_exceps_attr
548    {
549        if (acf->acf_interface_attr.bit.extern_exceps)
550            log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
551        acf->acf_interface_attr.bit.extern_exceps = TRUE;
552    }
553    |   IDENTIFIER
554    {
555        if (NAMETABLE_add_id("decode") == $<y_id>1)
556        {
557            if (acf->acf_interface_attr.bit.decode)
558                log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
559            acf->acf_interface_attr.bit.decode = TRUE;
560        }
561        else if (NAMETABLE_add_id("encode") == $<y_id>1)
562        {
563            if (acf->acf_interface_attr.bit.encode)
564                log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
565            acf->acf_interface_attr.bit.encode = TRUE;
566        }
567        else
568            log_error(acf_yylineno(acf), NIDL_ERRINATTR, NULL);
569    }
570    ;
571
572acf_implicit_handle_attr:
573        IMPLICIT_HANDLE_KW LPAREN acf_implicit_handle RPAREN
574    ;
575
576acf_implicit_handle:
577        acf_impl_type acf_impl_name
578    ;
579
580acf_impl_type:
581        acf_handle_type
582    {
583        acf->acf_named_type = FALSE;
584    }
585    |   IDENTIFIER
586    {
587        NAMETABLE_id_to_string($<y_id>1, &acf->acf_type_name);
588        acf->acf_named_type = TRUE;
589    }
590    ;
591
592acf_handle_type:
593        HANDLE_T_KW
594    ;
595
596acf_impl_name:
597        IDENTIFIER
598    {
599        NAMETABLE_id_to_string($<y_id>1, &acf->acf_impl_name);
600    }
601    ;
602
603acf_extern_exceps_attr:
604        EXTERN_EXCEPS_KW LPAREN acf_ext_excep_list RPAREN
605    |   EXTERN_EXCEPS_KW
606    {
607        if (ASTP_parsing_main_idl)
608        {
609            AST_exception_n_t *excep_p;
610            for (excep_p = the_interface->exceptions;
611                 excep_p != NULL;
612                 excep_p = excep_p->next)
613            {
614                AST_SET_EXTERN(excep_p);
615            }
616        }
617    }
618    ;
619
620acf_ext_excep_list:
621        acf_ext_excep
622    |   acf_ext_excep_list COMMA acf_ext_excep
623    ;
624
625acf_ext_excep:
626        IDENTIFIER
627    {
628        AST_exception_n_t *excep_p;
629        if (ASTP_parsing_main_idl)
630            if (lookup_exception(acf, $<y_id>1, TRUE, &excep_p))
631                AST_SET_EXTERN(excep_p);
632    }
633    ;
634
635acf_interface_name:
636        IDENTIFIER
637    {
638        NAMETABLE_id_to_string($<y_id>1, &acf->acf_interface_name);
639    }
640    ;
641
642acf_interface_body:
643        LBRACE acf_body_elements RBRACE
644    |   LBRACE RBRACE
645    |   error
646        { log_error(acf_yylineno(acf), NIDL_SYNTAXERR, NULL); }
647    |   error RBRACE
648        { log_error(acf_yylineno(acf), NIDL_SYNTAXERR, NULL); }
649    ;
650
651acf_body_elements:
652        acf_body_element
653    |   acf_body_elements acf_body_element
654    ;
655
656acf_body_element:
657        acf_include SEMI
658    |   acf_type_declaration SEMI
659    |   acf_operation_declaration SEMI
660    |   error SEMI
661        {
662            log_error(acf_yylineno(acf), NIDL_SYNTAXERR, NULL);
663            /* Re-initialize attr masks to avoid sticky attributes */
664            acf->acf_interface_attr.mask = 0;
665            acf->acf_type_attr.mask      = 0;
666            acf->acf_operation_attr.mask = 0;
667            acf->acf_parameter_attr.mask = 0;
668        }
669    ;
670
671acf_include:
672        INCLUDE_KW acf_include_list
673        {
674        if (ASTP_parsing_main_idl)
675	{
676            the_interface->includes = (AST_include_n_t *)
677                AST_concat_element((ASTP_node_t *)the_interface->includes,
678                                   (ASTP_node_t *)acf->acf_include_list);
679	}
680        acf->acf_include_list = NULL;
681        }
682    |   INCLUDE_KW error
683        { log_error(acf_yylineno(acf), NIDL_SYNTAXERR, NULL); }
684    ;
685
686acf_include_list:
687        acf_include_name
688    |   acf_include_list COMMA acf_include_name
689    ;
690
691acf_include_name:
692        STRING
693    {
694        if (ASTP_parsing_main_idl)
695        {
696            char const      *parsed_include_file;
697            char            include_type[PATH_MAX];
698            char            include_file[PATH_MAX];
699            STRTAB_str_t    include_file_id;
700
701            STRTAB_str_to_string($<y_string>1, &parsed_include_file);
702
703            /*
704             * Log warning if include name contains a file extension.
705             * Tack on the correct extension based on the -lang option.
706             */
707            FILE_parse(parsed_include_file, (char *)NULL, 0, (char *)NULL, 0,
708                       include_type, sizeof (include_type));
709            if (include_type[0] != '\0')
710                acf_warning(acf, NIDL_INCLUDEXT);
711
712            FILE_form_filespec(parsed_include_file, (char *)NULL,
713							   ".h",
714                               (char *)NULL, include_file, sizeof(include_file));
715
716            /* Create an include node. */
717            include_file_id = STRTAB_add_string(include_file);
718            acf->acf_include_p = AST_include_node(acf_location(acf),
719		    include_file_id, $<y_string>1);
720
721            /* Store source information. */
722            if (acf->acf_include_p->fe_info != NULL)
723            {
724                acf->acf_include_p->fe_info->acf_file = acf->acf_location.fileid;
725                acf->acf_include_p->fe_info->acf_source_line = acf_yylineno(acf);
726            }
727
728            acf->acf_include_list = (AST_include_n_t *)
729                AST_concat_element((ASTP_node_t *)acf->acf_include_list,
730                                   (ASTP_node_t *)acf->acf_include_p);
731        }
732    }
733    ;
734
735acf_type_declaration:
736        TYPEDEF_KW error
737        { log_error(acf_yylineno(acf), NIDL_SYNTAXERR, NULL); }
738    |   TYPEDEF_KW acf_type_attr_list acf_named_type_list
739    {
740        acf->acf_type_attr.mask = 0;    /* Reset attribute mask */
741        acf->acf_repr_type_name = NULL; /* Reset represent_as type name */
742        acf->acf_cs_char_type_name = NULL;       /* Reset cs_char type name */
743    }
744    ;
745
746acf_named_type_list:
747        acf_named_type
748    {
749        acf->acf_type_name = NULL;               /* Reset type name */
750    }
751    |   acf_named_type_list COMMA acf_named_type
752    {
753        acf->acf_type_name = NULL;               /* Reset type name */
754    }
755    ;
756
757acf_named_type:
758        IDENTIFIER
759    {
760        NAMETABLE_id_t  type_id;        /* Nametable id of type name */
761        AST_type_n_t    *type_p;        /* Ptr to AST type node */
762
763        NAMETABLE_id_to_string($<y_id>1, &acf->acf_type_name);
764
765        if (acf->acf_dumpers)
766	{
767            dump_attributes(acf, "ACF type",
768		    acf->acf_type_name, &acf->acf_type_attr);
769	}
770
771        /*
772         *  Lookup the type_name parsed and verify that it is a valid type
773         *  node.  Then set the parsed attributes in the type node.
774         *
775         *  type_attr = bitmask of type attributes parsed.
776         *  type_name = name of type_t node to look up.
777         *  [repr_type_name] = name of represent_as type.
778         *  [cs_char_type_name] = name of cs_char type.
779         */
780
781        if (lookup_type(acf, acf->acf_type_name, TRUE, &type_id, &type_p))
782        {
783            /* Store source information. */
784            if (type_p->fe_info != NULL)
785            {
786                type_p->fe_info->acf_file = acf->acf_location.fileid;
787                type_p->fe_info->acf_source_line = acf_yylineno(acf);
788            }
789
790            if (acf->acf_type_attr.bit.heap
791                && type_p->kind != AST_pipe_k
792                && !AST_CONTEXT_RD_SET(type_p))
793                PROP_set_type_attr(type_p,AST_HEAP);
794            if (acf->acf_type_attr.bit.in_line)
795                PROP_set_type_attr(type_p,AST_IN_LINE);
796            if ((acf->acf_type_attr.bit.out_of_line) &&
797                (type_p->kind != AST_pointer_k) &&
798                (type_p->xmit_as_type == NULL))
799                PROP_set_type_attr(type_p,AST_OUT_OF_LINE);
800            if (acf->acf_type_attr.bit.represent_as)
801                process_rep_as_type(acf, the_interface, type_p, acf->acf_repr_type_name);
802            if (acf->acf_type_attr.bit.cs_char)
803                process_cs_char_type(acf, the_interface, type_p, acf->acf_cs_char_type_name);
804        }
805    }
806    ;
807
808acf_type_attr_list:
809        LBRACKET acf_rest_of_attr_list
810    |   /* Nothing */
811    ;
812
813acf_rest_of_attr_list:
814        acf_type_attrs RBRACKET
815    |   error SEMI
816        {
817        log_error(acf_yylineno(acf), NIDL_MISSONATTR, NULL);
818        }
819    |   error RBRACKET
820        {
821        log_error(acf_yylineno(acf), NIDL_ERRINATTR, NULL);
822        }
823    ;
824
825acf_type_attrs:
826        acf_type_attr
827    |   acf_type_attrs COMMA acf_type_attr
828    ;
829
830acf_type_attr:
831        acf_represent_attr
832    {
833        if (acf->acf_type_attr.bit.represent_as)
834            log_error(acf_yylineno(acf), NIDL_ATTRUSEMULT, NULL);
835        acf->acf_type_attr.bit.represent_as = TRUE;
836    }
837    |   acf_cs_char_attr
838    {
839        if (acf->acf_type_attr.bit.cs_char)
840            log_error(acf_yylineno(acf), NIDL_ATTRUSEMULT, NULL);
841        acf->acf_type_attr.bit.cs_char = TRUE;
842    }
843    |   acf_heap_attr
844    {
845        if (acf->acf_type_attr.bit.heap)
846            log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
847        acf->acf_type_attr.bit.heap = TRUE;
848    }
849    |   acf_inline_attr
850    {
851        if (acf->acf_type_attr.bit.in_line)
852            log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
853        acf->acf_type_attr.bit.in_line = TRUE;
854    }
855    |   acf_outofline_attr
856    {
857        if (acf->acf_type_attr.bit.out_of_line)
858            log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
859        acf->acf_type_attr.bit.out_of_line = TRUE;
860    }
861    ;
862
863acf_represent_attr:
864        REPRESENT_AS_KW LPAREN acf_repr_type RPAREN
865    ;
866
867acf_repr_type:
868        IDENTIFIER
869    {
870        NAMETABLE_id_to_string($<y_id>1, &acf->acf_repr_type_name);
871    }
872    ;
873
874acf_cs_char_attr:
875        CS_CHAR_KW LPAREN acf_cs_char_type RPAREN
876    ;
877
878acf_cs_char_type:
879        IDENTIFIER
880    {
881        NAMETABLE_id_to_string($<y_id>1, &acf->acf_cs_char_type_name);
882    }
883    ;
884
885acf_operation_declaration:
886        acf_op_attr_list acf_operations
887    {
888        acf->acf_operation_attr.mask = 0;        /* Reset attribute mask */
889        acf->acf_cs_tag_rtn_name     = NULL;     /* Reset cs_tag_rtn name */
890    }
891    ;
892
893acf_operations:
894        acf_operation
895    |   acf_operations COMMA acf_operation
896    ;
897
898acf_operation:
899        IDENTIFIER LPAREN acf_parameter_list RPAREN
900    {
901        acf_param_t         *p;         /* Ptr to local parameter structure */
902        NAMETABLE_id_t      op_id;      /* Nametable id of operation name */
903        NAMETABLE_id_t      param_id;   /* Nametable id of parameter name */
904        AST_operation_n_t   *op_p;      /* Ptr to AST operation node */
905        AST_parameter_n_t   *param_p;   /* Ptr to AST parameter node */
906        boolean             log_error;  /* TRUE => error if name not found */
907        char const          *param_name;/* character string of param id */
908
909        NAMETABLE_id_to_string($<y_id>1, &acf->acf_operation_name);
910
911        if (acf->acf_dumpers)
912	{
913            dump_attributes(acf, "ACF operation",
914		    acf->acf_operation_name, &acf->acf_operation_attr);
915	}
916
917        /*
918         *  Operation and parameter attributes are ignored for imported
919         *  interfaces.  Operations and parameters within imported interfaces
920         *  are not put in the AST.
921         */
922        if (ASTP_parsing_main_idl)
923        {
924            /*
925             *  Lookup the operation_name parsed and verify that it is a valid
926             *  operation node.  Then set the parsed attributes in the operation
927             *  node.  For each parameter_name that was parsed for this
928             *  operation, chase the parameter list off the AST operation node
929             *  to verify that it is a valid parameter for that operation.
930             *  Then set the parsed attributes for that parameter into the
931             *  relevant parameter node.
932             *
933             *  operation_attr = bitmask of operation attributes parsed.
934             *  operation_name = name of routine_t node to look up.
935             *  [cs_tag_rtn_name] = cs_tag_rtn name.
936             *  parameter_list = linked list of parameter information.
937             */
938
939            if (lookup_operation(acf, acf->acf_operation_name, TRUE, &op_id, &op_p))
940            {
941                /* Store source information. */
942                if (op_p->fe_info != NULL)
943                {
944                    op_p->fe_info->acf_file = acf->acf_location.fileid;
945                    op_p->fe_info->acf_source_line = acf_yylineno(acf);
946                }
947
948                if (acf->acf_operation_attr.bit.comm_status)
949                {
950                    /*
951                     * Assume the AST Builder always builds a result param,
952                     * even for void operations.
953                     */
954                    AST_SET_COMM_STATUS(op_p->result);
955                }
956                if (acf->acf_operation_attr.bit.fault_status)
957                    AST_SET_FAULT_STATUS(op_p->result);
958
959                if (acf->acf_operation_attr.bit.code)
960                    AST_SET_CODE(op_p);
961                if (acf->acf_operation_attr.bit.nocode)
962                    AST_SET_NO_CODE(op_p);
963                if (acf->acf_operation_attr.bit.decode)
964                    AST_SET_DECODE(op_p);
965                if (acf->acf_operation_attr.bit.encode)
966                    AST_SET_ENCODE(op_p);
967                if (acf->acf_operation_attr.bit.enable_allocate)
968                    AST_SET_ENABLE_ALLOCATE(op_p);
969                if (acf->acf_operation_attr.bit.explicit_handle)
970                    AST_SET_EXPLICIT_HANDLE(op_p);
971                if (acf->acf_operation_attr.bit.nocancel)
972                    AST_SET_NO_CANCEL(op_p);
973                if (acf->acf_operation_attr.bit.cs_tag_rtn)
974                    op_p->cs_tag_rtn_name = NAMETABLE_add_id(acf->acf_cs_tag_rtn_name);
975
976                for (p = acf->acf_parameter_list ; p != NULL ; p = p->next)
977                {
978                    /*
979                     * Most parameter attributes, if present, require that the
980                     * referenced parameter be defined in the IDL.  If only
981                     * [comm_status] and/or [fault_status] is present, the
982                     * parameter  needn't be IDL-defined.
983                     */
984                    if (!p->parameter_attr.bit.heap
985                        &&  !p->parameter_attr.bit.in_line
986                        &&  !p->parameter_attr.bit.out_of_line
987                        &&  !p->parameter_attr.bit.cs_stag
988                        &&  !p->parameter_attr.bit.cs_drtag
989                        &&  !p->parameter_attr.bit.cs_rtag
990                        &&  (p->parameter_attr.bit.comm_status
991                             || p->parameter_attr.bit.fault_status))
992                        log_error = FALSE;
993                    else
994                        log_error = TRUE;
995
996                    NAMETABLE_id_to_string(p->param_id, &param_name);
997                    if (lookup_parameter(acf, op_p, param_name, log_error,
998                                         &param_id, &param_p))
999                    {
1000                        /* Store source information. */
1001                        if (param_p->fe_info != NULL)
1002                        {
1003                            param_p->fe_info->acf_file = acf->acf_location.fileid;
1004                            param_p->fe_info->acf_source_line = acf_yylineno(acf);
1005                        }
1006
1007                        if (p->parameter_attr.bit.comm_status)
1008                            AST_SET_COMM_STATUS(param_p);
1009                        if (p->parameter_attr.bit.fault_status)
1010                            AST_SET_FAULT_STATUS(param_p);
1011                        if (p->parameter_attr.bit.heap)
1012                        {
1013                            AST_type_n_t *ref_type_p;
1014                            ref_type_p = param_follow_ref_ptr(param_p,
1015                                                              CHK_follow_ref);
1016                            if (ref_type_p->kind != AST_pipe_k
1017                                && !AST_CONTEXT_SET(param_p)
1018                                && !AST_CONTEXT_RD_SET(ref_type_p)
1019                                && !type_is_scalar(ref_type_p))
1020                                AST_SET_HEAP(param_p);
1021                        }
1022                        if (p->parameter_attr.bit.in_line)
1023                            AST_SET_IN_LINE(param_p);
1024                        /*
1025                         * We parse the [out_of_line] parameter attribute,
1026                         * but disallow it.
1027                         */
1028                        if (p->parameter_attr.bit.out_of_line)
1029                            acf_error(acf, NIDL_INVOOLPRM);
1030                        if (p->parameter_attr.bit.cs_stag)
1031                            AST_SET_CS_STAG(param_p);
1032                        if (p->parameter_attr.bit.cs_drtag)
1033                            AST_SET_CS_DRTAG(param_p);
1034                        if (p->parameter_attr.bit.cs_rtag)
1035                            AST_SET_CS_RTAG(param_p);
1036                    }
1037                    else if (log_error == FALSE)
1038                    {
1039                        /*
1040                         * Lookup failed, but OK since the parameter only has
1041                         * attribute(s) that specify an additional parameter.
1042                         * Append a parameter to the operation parameter list.
1043                         */
1044                        NAMETABLE_id_to_string(p->param_id, &param_name);
1045                        append_parameter(acf, op_p, param_name, &p->parameter_attr);
1046                    }
1047                }
1048            }
1049        }
1050
1051        free_param_list(acf, &acf->acf_parameter_list);       /* Free parameter list */
1052
1053        acf->acf_operation_name = NULL;
1054    }
1055    ;
1056
1057acf_op_attr_list:
1058        LBRACKET acf_op_attrs RBRACKET
1059    |   /* Nothing */
1060    ;
1061
1062acf_op_attrs:
1063        acf_op_attr
1064    |   acf_op_attrs COMMA acf_op_attr
1065    ;
1066
1067acf_op_attr:
1068        acf_commstat_attr
1069    {
1070        if (acf->acf_operation_attr.bit.comm_status)
1071            log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
1072        acf->acf_operation_attr.bit.comm_status = TRUE;
1073    }
1074    |   acf_code_attr
1075    {
1076        if (acf->acf_operation_attr.bit.code)
1077            log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
1078        acf->acf_operation_attr.bit.code = TRUE;
1079    }
1080    |   acf_nocode_attr
1081    {
1082        if (acf->acf_operation_attr.bit.nocode)
1083            log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
1084        acf->acf_operation_attr.bit.nocode = TRUE;
1085    }
1086    |   acf_cs_tag_rtn_attr
1087    {
1088        if (acf->acf_operation_attr.bit.cs_tag_rtn)
1089            log_error(acf_yylineno(acf), NIDL_ATTRUSEMULT, NULL);
1090        acf->acf_operation_attr.bit.cs_tag_rtn = TRUE;
1091    }
1092    |   acf_enable_allocate_attr
1093    {
1094        if (acf->acf_operation_attr.bit.enable_allocate)
1095            log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
1096        acf->acf_operation_attr.bit.enable_allocate = TRUE;
1097    }
1098    |   acf_explicit_handle_attr
1099    {
1100        if (acf->acf_operation_attr.bit.explicit_handle)
1101            log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
1102        acf->acf_operation_attr.bit.explicit_handle = TRUE;
1103    }
1104    |   acf_nocancel_attr
1105    {
1106        if (acf->acf_operation_attr.bit.nocancel)
1107            log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
1108        acf->acf_operation_attr.bit.nocancel = TRUE;
1109    }
1110    |   acf_faultstat_attr
1111    {
1112        if (acf->acf_operation_attr.bit.fault_status)
1113            log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
1114        acf->acf_operation_attr.bit.fault_status = TRUE;
1115    }
1116    |   IDENTIFIER
1117    {
1118        if (NAMETABLE_add_id("decode") == $<y_id>1)
1119        {
1120            if (acf->acf_operation_attr.bit.decode)
1121                log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
1122            acf->acf_operation_attr.bit.decode = TRUE;
1123        }
1124        else if (NAMETABLE_add_id("encode") == $<y_id>1)
1125        {
1126            if (acf->acf_operation_attr.bit.encode)
1127                log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
1128            acf->acf_operation_attr.bit.encode = TRUE;
1129        }
1130        else
1131            log_error(acf_yylineno(acf), NIDL_ERRINATTR, NULL);
1132    }
1133    ;
1134
1135acf_binding_callout_attr:
1136        BINDING_CALLOUT_KW LPAREN acf_binding_callout_name RPAREN
1137    ;
1138
1139acf_binding_callout_name:
1140        IDENTIFIER
1141    {
1142        NAMETABLE_id_to_string($<y_id>1, &acf->acf_binding_callout_name);
1143    }
1144    ;
1145
1146acf_cs_tag_rtn_attr:
1147        CS_TAG_RTN_KW LPAREN acf_cs_tag_rtn_name RPAREN
1148    ;
1149
1150acf_cs_tag_rtn_name:
1151        IDENTIFIER
1152    {
1153        NAMETABLE_id_to_string($<y_id>1, &acf->acf_cs_tag_rtn_name);
1154    }
1155    ;
1156
1157acf_parameter_list:
1158        acf_parameters
1159    |   /* Nothing */
1160    ;
1161
1162acf_parameters:
1163        acf_parameter
1164    |   acf_parameters COMMA acf_parameter
1165    ;
1166
1167acf_parameter:
1168        acf_param_attr_list IDENTIFIER
1169    {
1170        if (acf->acf_dumpers)
1171        {
1172            char const *param_name;
1173            NAMETABLE_id_to_string($<y_id>2, &param_name);
1174            dump_attributes(acf, "ACF parameter",
1175		    param_name, &acf->acf_parameter_attr);
1176        }
1177
1178        if (acf->acf_parameter_attr_list) /* If there were param attributes: */
1179        {
1180            acf_param_t *p;             /* Pointer to parameter record */
1181
1182            /*
1183             * Allocate and initialize a parameter record.
1184             */
1185            p = alloc_param(acf);
1186            p->parameter_attr = acf->acf_parameter_attr;
1187            p->param_id = $<y_id>2;
1188
1189            /*
1190             * Add to end of parameter list.
1191             */
1192            add_param_to_list(p, &acf->acf_parameter_list);
1193
1194            acf->acf_parameter_attr.mask = 0;
1195        }
1196    }
1197    ;
1198
1199acf_param_attr_list:
1200        LBRACKET acf_param_attrs RBRACKET
1201    {
1202        acf->acf_parameter_attr_list = TRUE;     /* Flag that we have param attributes */
1203    }
1204    |   /* Nothing */
1205    {
1206        acf->acf_parameter_attr_list = FALSE;
1207    }
1208    ;
1209
1210acf_param_attrs:
1211        acf_param_attr
1212    |   acf_param_attrs COMMA acf_param_attr
1213    ;
1214
1215acf_param_attr:
1216        acf_commstat_attr
1217    {
1218        if (acf->acf_parameter_attr.bit.comm_status)
1219            log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
1220        acf->acf_parameter_attr.bit.comm_status = TRUE;
1221    }
1222    |   acf_faultstat_attr
1223    {
1224        if (acf->acf_parameter_attr.bit.fault_status)
1225            log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
1226        acf->acf_parameter_attr.bit.fault_status = TRUE;
1227    }
1228    |   acf_heap_attr
1229    {
1230        if (acf->acf_parameter_attr.bit.heap)
1231            log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
1232        acf->acf_parameter_attr.bit.heap = TRUE;
1233    }
1234    |   acf_inline_attr
1235    {
1236        if (acf->acf_parameter_attr.bit.in_line)
1237            log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
1238        acf->acf_parameter_attr.bit.in_line = TRUE;
1239    }
1240    |   acf_outofline_attr
1241    {
1242        if (acf->acf_parameter_attr.bit.out_of_line)
1243            log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
1244        acf->acf_parameter_attr.bit.out_of_line = TRUE;
1245    }
1246    |   IDENTIFIER
1247    {
1248        if (NAMETABLE_add_id("cs_stag") == $<y_id>1)
1249        {
1250            if (acf->acf_parameter_attr.bit.cs_stag)
1251                log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
1252            acf->acf_parameter_attr.bit.cs_stag = TRUE;
1253        }
1254        else if (NAMETABLE_add_id("cs_drtag") == $<y_id>1)
1255        {
1256            if (acf->acf_parameter_attr.bit.cs_drtag)
1257                log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
1258            acf->acf_parameter_attr.bit.cs_drtag = TRUE;
1259        }
1260        else if (NAMETABLE_add_id("cs_rtag") == $<y_id>1)
1261        {
1262            if (acf->acf_parameter_attr.bit.cs_rtag)
1263                log_warning(acf_yylineno(acf), NIDL_MULATTRDEF, NULL);
1264            acf->acf_parameter_attr.bit.cs_rtag = TRUE;
1265        }
1266        else
1267            log_error(acf_yylineno(acf), NIDL_ERRINATTR, NULL);
1268    }
1269    ;
1270
1271acf_auto_handle_attr:   AUTO_HANDLE_KW;
1272acf_code_attr:          CODE_KW;
1273acf_nocode_attr:        NOCODE_KW;
1274acf_enable_allocate_attr: ENABLE_ALLOCATE_KW;
1275acf_explicit_handle_attr: EXPLICIT_HANDLE_KW;
1276acf_nocancel_attr:      NOCANCEL_KW;
1277acf_heap_attr:          HEAP_KW;
1278acf_inline_attr:        IN_LINE_KW;
1279acf_outofline_attr:     OUT_OF_LINE_KW;
1280acf_commstat_attr:      COMM_STATUS_KW;
1281acf_faultstat_attr:     FAULT_STATUS_KW;
1282
1283%%
1284
1285/***************************
1286 *  yacc programs section  *
1287 ***************************/
1288
1289/*
1290 *  a c f _ p a r s e r _ a l l o c
1291 *
1292 *  Function:   Called to create an new ACF parser object
1293 *
1294 */
1295
1296acf_parser_p acf_parser_alloc
1297(
1298    boolean     *cmd_opt_arr,   /* [in] Array of command option flags */
1299    void        **cmd_val_arr,  /* [in] Array of command option values */
1300    char        *acf_file       /* [in] ACF file name */
1301)
1302{
1303    acf_parser_state_t * acf;
1304
1305    acf = NEW(acf_parser_state_t);
1306
1307    acf->acf_dumpers = FALSE;
1308
1309#ifdef DUMPERS
1310    if (cmd_opt_arr[opt_dump_acf])
1311	acf->acf_dumpers = TRUE;
1312#else
1313    (void)cmd_opt_arr;
1314#endif
1315
1316    /* Set global (STRTAB_str_t error_file_name_id) for error processing. */
1317    set_name_for_errors(acf_file);
1318    acf->acf_location.fileid = STRTAB_add_string(acf_file);
1319
1320   // XXX save file name ID in parser state
1321
1322    acf->acf_interface_attr.mask = 0;
1323    acf->acf_type_attr.mask      = 0;
1324    acf->acf_operation_attr.mask = 0;
1325    acf->acf_parameter_attr.mask = 0;
1326
1327    acf->acf_interface_name      = NULL;
1328    acf->acf_type_name           = NULL;
1329    acf->acf_repr_type_name      = NULL;
1330    acf->acf_cs_char_type_name   = NULL;
1331    acf->acf_operation_name      = NULL;
1332    acf->acf_binding_callout_name= NULL;
1333    acf->acf_cs_tag_rtn_name     = NULL;
1334
1335    acf->acf_include_list        = NULL;
1336
1337    acf->acf_parameter_list      = NULL;
1338    acf->acf_parameter_free_list = NULL;
1339
1340    return acf;
1341}
1342
1343/*
1344 *  a c f _ p a r s e r _ d e s t r o y
1345 *
1346 *  Function:   Called after ACF parsing to free allocated memory.
1347 *
1348 */
1349
1350void acf_parser_destroy
1351(
1352    acf_parser_p acf
1353)
1354{
1355    acf_param_t *p, *q;     /* Ptrs to parameter record */
1356
1357    p = acf->acf_parameter_free_list;
1358
1359    while (p != NULL)
1360    {
1361        q = p;
1362        p = p->next;
1363        FREE(q);
1364    }
1365
1366    if (acf->acf_yyscanner)
1367    {
1368	acf_yylex_destroy(acf->acf_yyscanner);
1369    }
1370
1371    FREE(acf);
1372    yyin_p = NULL;
1373    yylineno_p = NULL;
1374}
1375
1376void acf_parser_input
1377(
1378    acf_parser_p acf,
1379    FILE * in
1380)
1381{
1382
1383    assert(acf->acf_yyscanner == NULL);
1384
1385    acf_yylex_init(&acf->acf_yyscanner);
1386    acf_yyset_in(in, acf->acf_yyscanner);
1387
1388    yyin_p = in;
1389    yylineno_p = &acf->acf_location.lineno;
1390}
1391
1392unsigned acf_yylineno
1393(
1394   acf_parser_p acf
1395)
1396{
1397   return acf_yyget_lineno(acf->acf_yyscanner);
1398}
1399
1400const parser_location_t * acf_location
1401(
1402   acf_parser_p acf
1403)
1404{
1405    /* Update the current location before handing it back ... */
1406    acf->acf_location.lineno = acf_yylineno(acf);
1407    acf->acf_location.location = *acf_yyget_lloc(acf->acf_yyscanner);
1408    acf->acf_location.text = acf_yyget_text(acf->acf_yyscanner);
1409
1410    return &acf->acf_location;
1411}
1412
1413unsigned acf_errcount
1414(
1415   acf_parser_p acf
1416)
1417{
1418   return acf->acf_yynerrs;
1419}
1420
1421static void acf_yyerror
1422(
1423    YYLTYPE * yylloc ATTRIBUTE_UNUSED,
1424    acf_parser_p acf,
1425    char const * message
1426)
1427{
1428    const struct parser_location_t * loc;
1429    loc = acf_location(acf);
1430    idl_yyerror(loc, message);
1431}
1432
1433/*
1434**  l o o k u p _ e x c e p t i o n
1435**
1436**  Looks up a name in the nametable, and if it is bound to a valid exception
1437**  node, returns the address of the exception node.
1438**
1439**  Returns:    TRUE if lookup succeeds, FALSE otherwise.
1440*/
1441
1442static boolean lookup_exception
1443(
1444    acf_parser_state_t *acf,
1445    NAMETABLE_id_t  excep_id,     /* [in] Nametable id of exception name */
1446    boolean         log_error,    /* [in] TRUE => log error if name not found */
1447    AST_exception_n_t **excep_ptr /*[out] Ptr to AST exception node */
1448)
1449{
1450    AST_exception_n_t *excep_p;     /* Ptr to node bound to looked up name */
1451    char const      *perm_excep_name;   /* Ptr to permanent copy */
1452    NAMETABLE_id_t  name_id ATTRIBUTE_UNUSED;            /* Handle on permanent copy */
1453
1454    if (excep_id != NAMETABLE_NIL_ID)
1455    {
1456        excep_p = (AST_exception_n_t *)NAMETABLE_lookup_binding(excep_id);
1457
1458        if (excep_p != NULL && excep_p->fe_info->node_kind == fe_exception_n_k)
1459        {
1460            *excep_ptr = excep_p;
1461            return TRUE;
1462        }
1463    }
1464
1465    if (log_error)
1466    {
1467        NAMETABLE_id_to_string(excep_id, &perm_excep_name);
1468        acf_error(acf, NIDL_EXCNOTDEF, perm_excep_name);
1469    }
1470
1471    *excep_ptr = NULL;
1472    return FALSE;
1473}
1474
1475/*
1476**  l o o k u p _ t y p e
1477**
1478**  Looks up a name in the nametable, and if it is bound to a valid type
1479**  node, returns the address of the type node.
1480**
1481**  Returns:    TRUE if lookup succeeds, FALSE otherwise.
1482*/
1483
1484static boolean lookup_type
1485(
1486    acf_parser_state_t *acf,
1487    char const      *type_name, /* [in] Name to look up */
1488    boolean         log_error,  /* [in] TRUE => log error if name not found */
1489    NAMETABLE_id_t  *type_id,   /*[out] Nametable id of type name */
1490    AST_type_n_t    **type_ptr  /*[out] Ptr to AST type node */
1491)
1492{
1493    AST_type_n_t    *type_p;    /* Ptr to node bound to looked up name */
1494    char const      *perm_type_name;    /* Ptr to permanent copy */
1495    NAMETABLE_id_t  name_id;            /* Handle on permanent copy */
1496
1497    *type_id = NAMETABLE_lookup_id(type_name);
1498
1499    if (*type_id != NAMETABLE_NIL_ID)
1500    {
1501        type_p = (AST_type_n_t *)NAMETABLE_lookup_binding(*type_id);
1502
1503        if (type_p != NULL && type_p->fe_info->node_kind == fe_type_n_k)
1504        {
1505            *type_ptr = type_p;
1506            return TRUE;
1507        }
1508    }
1509
1510    if (log_error)
1511    {
1512        name_id = NAMETABLE_add_id(type_name);
1513        NAMETABLE_id_to_string(name_id, &perm_type_name);
1514        acf_error(acf, NIDL_TYPNOTDEF, perm_type_name);
1515    }
1516
1517    *type_ptr = NULL;
1518    return FALSE;
1519}
1520
1521/*
1522**  l o o k u p _ o p e r a t i o n
1523**
1524**  Looks up a name in the nametable, and if it is bound to a valid operation
1525**  node, returns the address of the operation node.
1526**
1527**  Returns:    TRUE if lookup succeeds, FALSE otherwise.
1528*/
1529
1530static boolean lookup_operation
1531(
1532    acf_parser_state_t *acf,
1533    char const      *op_name,   /* [in] Name to look up */
1534    boolean         log_error,  /* [in] TRUE => log error if name not found */
1535    NAMETABLE_id_t  *op_id,     /*[out] Nametable id of operation name */
1536    AST_operation_n_t **op_ptr  /*[out] Ptr to AST operation node */
1537)
1538{
1539    AST_operation_n_t   *op_p;  /* Ptr to node bound to looked up name */
1540    char const      *perm_op_name;      /* Ptr to permanent copy */
1541    NAMETABLE_id_t  name_id;            /* Handle on permanent copy */
1542
1543    *op_id = NAMETABLE_lookup_id(op_name);
1544
1545    if (*op_id != NAMETABLE_NIL_ID)
1546    {
1547        op_p = (AST_operation_n_t *)NAMETABLE_lookup_binding(*op_id);
1548
1549        if (op_p != NULL && op_p->fe_info->node_kind == fe_operation_n_k)
1550        {
1551            *op_ptr = op_p;
1552            return TRUE;
1553        }
1554    }
1555
1556    if (log_error)
1557    {
1558        name_id = NAMETABLE_add_id(op_name);
1559        NAMETABLE_id_to_string(name_id, &perm_op_name);
1560        acf_error(acf, NIDL_OPNOTDEF, perm_op_name);
1561    }
1562
1563    *op_ptr = NULL;
1564    return FALSE;
1565}
1566
1567/*
1568**  l o o k u p _ p a r a m e t e r
1569**
1570**  Searches an operation node's parameter list for the parameter name passed.
1571**  If found, returns the address of the parameter node.
1572**
1573**  Returns:    TRUE if lookup succeeds, FALSE otherwise.
1574*/
1575
1576static boolean lookup_parameter
1577(
1578    acf_parser_state_t  *acf,
1579    AST_operation_n_t   *op_p,          /* [in] Ptr to AST operation node */
1580    char const          *param_name,    /* [in] Parameter name to look up */
1581    boolean             log_error,      /* [in] TRUE=> log error if not found */
1582    NAMETABLE_id_t      *param_id,      /*[out] Nametable id of param name */
1583    AST_parameter_n_t   **param_ptr     /*[out] Ptr to AST parameter node */
1584)
1585{
1586    AST_parameter_n_t   *param_p;       /* Ptr to operation parameter node */
1587    char const          *op_param_name; /* Name of an operation parameter */
1588    char const          *op_name;       /* Operation name */
1589    char const      *perm_param_name;   /* Ptr to permanent copy */
1590    NAMETABLE_id_t  name_id;            /* Handle on permanent copy */
1591
1592    for (param_p = op_p->parameters ; param_p != NULL ; param_p = param_p->next)
1593    {
1594        NAMETABLE_id_to_string(param_p->name, &op_param_name);
1595
1596        if (strcmp(param_name, op_param_name) == 0)
1597        {
1598            *param_id   = param_p->name;
1599            *param_ptr  = param_p;
1600            return TRUE;
1601        }
1602    }
1603
1604    if (log_error)
1605    {
1606        char const *file_name;     /* Related file name */
1607
1608        NAMETABLE_id_to_string(op_p->name, &op_name);
1609        name_id = NAMETABLE_add_id(param_name);
1610        NAMETABLE_id_to_string(name_id, &perm_param_name);
1611
1612        STRTAB_str_to_string(op_p->fe_info->file, &file_name);
1613
1614        acf_error(acf, NIDL_PRMNOTDEF, perm_param_name, op_name);
1615        acf_error(acf, NIDL_NAMEDECLAT, op_name, file_name,
1616                  op_p->fe_info->source_line);
1617    }
1618
1619    return FALSE;
1620}
1621
1622/*
1623**  l o o k u p _ r e p _ a s _ n a m e
1624**
1625**  Scans a list of type nodes that have represent_as types for a match with
1626**  the type name given by the parameter repr_name_id.  If so, returns the
1627**  address of the found type node and a pointer to the associated
1628**  represent_as type name.
1629**
1630**  Returns:    TRUE if lookup succeeds, FALSE otherwise.
1631*/
1632
1633static boolean lookup_rep_as_name
1634(
1635    AST_type_p_n_t  *typep_p,           /* [in] Listhead of type ptr nodes */
1636    NAMETABLE_id_t  repr_name_id,       /* [in] represent_as name to look up */
1637    AST_type_n_t    **ret_type_p,       /*[out] Type node if found */
1638    char const      **ret_type_name     /*[out] Type name if found */
1639)
1640{
1641    AST_type_n_t    *type_p;            /* Ptr to a type node */
1642
1643    for ( ; typep_p != NULL ; typep_p = typep_p->next )
1644    {
1645        type_p = typep_p->type;
1646        if (type_p->name == repr_name_id)
1647        {
1648            *ret_type_p = type_p;
1649            NAMETABLE_id_to_string(type_p->rep_as_type->type_name,
1650                                   ret_type_name);
1651            return TRUE;
1652        }
1653    }
1654
1655    return FALSE;
1656}
1657
1658/*
1659**  l o o k u p _ c s _ c h a r _ n a m e
1660**
1661**  Scans a list of type nodes that have cs_char types for a match with
1662**  the type name given by the parameter cs_char_name_id.  If so, returns the
1663**  address of the found type node and a pointer to the associated
1664**  cs_char type name.
1665**
1666**  Returns:    TRUE if lookup succeeds, FALSE otherwise.
1667*/
1668
1669static boolean lookup_cs_char_name
1670(
1671    AST_type_p_n_t  *typep_p,           /* [in] Listhead of type ptr nodes */
1672    NAMETABLE_id_t  cs_char_name_id,    /* [in] cs_char name to look up */
1673    AST_type_n_t    **ret_type_p,       /*[out] Type node if found */
1674    char const      **ret_type_name     /*[out] Type name if found */
1675)
1676{
1677    AST_type_n_t    *type_p;            /* Ptr to a type node */
1678
1679    for ( ; typep_p != NULL ; typep_p = typep_p->next )
1680    {
1681        type_p = typep_p->type;
1682        if (type_p->name == cs_char_name_id)
1683        {
1684            *ret_type_p = type_p;
1685            NAMETABLE_id_to_string(type_p->cs_char_type->type_name,
1686                                   ret_type_name);
1687            return TRUE;
1688        }
1689    }
1690
1691    return FALSE;
1692}
1693
1694/*
1695 *  a c f _ a l l o c _ p a r a m
1696 *
1697 *  Function:   Allocates an acf_param_t, either from the free list or heap.
1698 *
1699 *  Returns:    Address of acf_param_t
1700 *
1701 *  Globals:    parameter_free_list - listhead for free list
1702 *
1703 *  Side Effects:   Exits program if unable to allocate memory.
1704 */
1705
1706static acf_param_t *alloc_param
1707(
1708    acf_parser_state_t * acf
1709)
1710{
1711    acf_param_t *p;     /* Ptr to parameter record */
1712
1713    if (acf->acf_parameter_free_list != NULL)
1714    {
1715        p = acf->acf_parameter_free_list;
1716        acf->acf_parameter_free_list = acf->acf_parameter_free_list->next;
1717    }
1718    else
1719    {
1720        p = NEW (acf_param_t);
1721        p->next                 = NULL;
1722        p->parameter_attr.mask  = 0;
1723        p->param_id             = NAMETABLE_NIL_ID;
1724    }
1725
1726    return p;
1727}
1728
1729/*
1730 *  a c f _ f r e e _ p a r a m
1731 *
1732 *  Function:   Frees an acf_param_t by reinitilizing it and returning it to
1733 *              the head of the free list.
1734 *
1735 *  Input:      p - Pointer to acf_param_t record
1736 *
1737 *  Globals:    parameter_free_list - listhead for free list
1738 */
1739
1740static void free_param
1741(
1742    acf_parser_state_t * acf,
1743    acf_param_t *p              /* [in] Pointer to acf_param_t record */
1744)
1745{
1746    p->parameter_attr.mask  = 0;
1747    p->param_id             = NAMETABLE_NIL_ID;
1748
1749    p->next                 = acf->acf_parameter_free_list;
1750    acf->acf_parameter_free_list     = p;
1751}
1752
1753/*
1754 *  a c f _ f r e e _ p a r a m _ l i s t
1755 *
1756 *  Function:   Frees a list of acf_param_t records.
1757 *
1758 *  Input:      list - Address of list pointer
1759 *
1760 *  Output:     list pointer = NULL
1761 */
1762
1763static void free_param_list
1764(
1765    acf_parser_state_t * acf,
1766    acf_param_t **list          /* [in] Address of list pointer */
1767)
1768{
1769    acf_param_t *p, *q;     /* Ptrs to parameter record */
1770
1771    p = *list;
1772
1773    while (p != NULL)
1774    {
1775        q = p;
1776        p = p->next;
1777        free_param(acf, q);
1778    }
1779
1780    *list = NULL;            /* List now empty */
1781}
1782
1783/*
1784 *  a d d _ p a r a m _ t o _ l i s t
1785 *
1786 *  Function:   Add a acf_param_t record to the end of a list.
1787 *
1788 *  Inputs:     p - Pointer to parameter record
1789 *              list - Address of list pointer
1790 *
1791 *  Outputs:    List is modified.
1792 */
1793
1794void add_param_to_list
1795(
1796    acf_param_t *p,             /* [in] Pointer to parameter record */
1797    acf_param_t **list          /* [in] Address of list pointer */
1798)
1799{
1800    acf_param_t *q;         /* Ptr to parameter record */
1801
1802    if (*list == NULL)      /* If list empty */
1803        *list = p;          /* then list now points at param */
1804    else
1805    {
1806        for (q = *list ; q->next != NULL ; q = q->next)
1807            ;
1808        q->next = p;        /* else last record in list now points at param */
1809    }
1810
1811    p->next = NULL;         /* Param is now last in list */
1812}
1813
1814/*
1815**  a p p e n d _ p a r a m e t e r
1816**
1817**  Appends a parameter to an operation's parameter list.
1818*/
1819
1820static void append_parameter
1821(
1822    acf_parser_state_t  *acf,
1823    AST_operation_n_t   *op_p,          /* [in] Ptr to AST operation node */
1824    char const          *param_name,    /* [in] Parameter name */
1825    acf_attrib_t        *param_attr     /* [in] Parameter attributes */
1826)
1827{
1828    NAMETABLE_id_t      new_param_id;   /* Nametable id of new parameter name */
1829    AST_parameter_n_t   *new_param_p;   /* Ptr to new parameter node */
1830    AST_type_n_t        *new_type_p;    /* Ptr to new parameter type node */
1831    AST_pointer_n_t     *new_ptr_p;     /* Ptr to new pointer node */
1832    NAMETABLE_id_t      status_id;      /* Nametable id of status_t */
1833    AST_type_n_t        *status_type_p; /* Type node bound to status_t name */
1834    AST_parameter_n_t   *param_p;       /* Ptr to operation parameter node */
1835
1836    /* Look up error_status_t type. */
1837    status_id = NAMETABLE_add_id("error_status_t");
1838    status_type_p = (AST_type_n_t *)NAMETABLE_lookup_binding(status_id);
1839    if (status_type_p == NULL)
1840    {
1841        acf_error(acf, NIDL_ERRSTATDEF, "error_status_t", "nbase.idl");
1842        return;
1843    }
1844
1845    /*
1846     * Have to create an '[out] error_status_t *param_name' parameter
1847     * that has the specified parameter attributes.
1848     */
1849    new_param_id = NAMETABLE_add_id(param_name);
1850    new_param_p = AST_parameter_node(acf_location(acf), new_param_id);
1851    new_type_p  = AST_type_node(acf_location(acf), AST_pointer_k);
1852    new_ptr_p   = AST_pointer_node(acf_location(acf), status_type_p);
1853
1854    new_type_p->type_structure.pointer = new_ptr_p;
1855    AST_SET_REF(new_type_p);
1856
1857    new_param_p->name = new_param_id;
1858    new_param_p->type = new_type_p;
1859    new_param_p->uplink = op_p;
1860    if (param_attr->bit.comm_status)
1861        AST_SET_ADD_COMM_STATUS(new_param_p);
1862    if (param_attr->bit.fault_status)
1863        AST_SET_ADD_FAULT_STATUS(new_param_p);
1864    AST_SET_OUT(new_param_p);
1865    AST_SET_REF(new_param_p);
1866
1867    param_p = op_p->parameters;
1868    if (param_p == NULL)
1869    {
1870        /* Was null param list, now has one param. */
1871        op_p->parameters = new_param_p;
1872    }
1873    else if (param_p->last == NULL)
1874    {
1875        /* Was one param, now have two params. */
1876        param_p->next = new_param_p;
1877        param_p->last = new_param_p;
1878    }
1879    else
1880    {
1881        /* Was more than one param, now have one more. */
1882        param_p->last->next = new_param_p;
1883        param_p->last = new_param_p;
1884    }
1885}
1886
1887/*
1888**  p r o c e s s _ r e p _ a s _ t y p e
1889**
1890**  Processes a [represent_as] clause applied to a type.  Validates that
1891**  [represent_as] types are not nested.  Adds the type to a list of types
1892**  that have the [represent_as] attribute.
1893*/
1894
1895static void process_rep_as_type
1896(
1897    acf_parser_state_t  *acf,
1898    AST_interface_n_t   *int_p,     /* [in] Ptr to AST interface node */
1899    AST_type_n_t        *type_p,    /* [in] Ptr to AST type node */
1900    char const      *ref_type_name  /* [in] Name in represent_as() clause */
1901)
1902{
1903    NAMETABLE_id_t  ref_type_id;    /* Nametable id of referenced name */
1904    char const      *file_name;     /* Related file name */
1905    char const      *perm_name;     /* Permanent copy of referenced name */
1906    AST_type_n_t    *parent_type_p; /* Parent type with same attribute */
1907    char const      *parent_name;   /* Name of parent type */
1908
1909    ref_type_id = NAMETABLE_add_id(ref_type_name);
1910
1911    /*
1912     * Report error if the type name referenced in the attribute is an AST
1913     * type which also has the same attribute, i.e. types with this attribute
1914     * cannot nest.
1915     */
1916    if (lookup_rep_as_name(int_p->ra_types, ref_type_id, &parent_type_p,
1917                           &perm_name))
1918    {
1919        NAMETABLE_id_to_string(parent_type_p->name, &parent_name);
1920        STRTAB_str_to_string(parent_type_p->fe_info->acf_file, &file_name);
1921
1922        acf_error(acf, NIDL_REPASNEST);
1923        acf_error(acf, NIDL_TYPEREPAS, parent_name, perm_name);
1924        acf_error(acf, NIDL_NAMEDECLAT, parent_name, file_name,
1925                  parent_type_p->fe_info->acf_source_line);
1926    }
1927
1928    /*
1929     * If the type node already has a type name for this attribute,
1930     * this one must duplicate that same name.
1931     */
1932    if (type_p->rep_as_type != NULL)
1933    {
1934        NAMETABLE_id_to_string(type_p->rep_as_type->type_name, &perm_name);
1935
1936        if (strcmp(perm_name, ref_type_name) != 0)
1937        {
1938            char const *new_ref_type_name; /* Ptr to permanent copy */
1939            NAMETABLE_id_t  name_id;       /* Handle on perm copy */
1940
1941            name_id = NAMETABLE_add_id(ref_type_name);
1942            NAMETABLE_id_to_string(name_id, &new_ref_type_name);
1943
1944            STRTAB_str_to_string(
1945                            type_p->rep_as_type->fe_info->acf_file, &file_name);
1946
1947            acf_error(acf, NIDL_CONFREPRTYPE, new_ref_type_name, perm_name);
1948            acf_error(acf, NIDL_NAMEDECLAT, perm_name, file_name,
1949                      type_p->rep_as_type->fe_info->acf_source_line);
1950        }
1951    }
1952    else
1953    {
1954        /*
1955         * Process valid [represent_as] clause.
1956         */
1957        AST_type_p_n_t  *typep_p;       /* Used to link type nodes */
1958        AST_rep_as_n_t  *repas_p;       /* Ptr to represent_as node */
1959
1960        /* Add represent_as type name and build rep_as AST node. */
1961
1962        repas_p = type_p->rep_as_type =
1963	    AST_represent_as_node(acf_location(acf),ref_type_id);
1964        /* Store source information. */
1965        if (repas_p->fe_info != NULL)
1966        {
1967            repas_p->fe_info->acf_file = acf->acf_location.fileid;
1968            repas_p->fe_info->acf_source_line = acf_yylineno(acf);
1969        }
1970
1971        /* Check for associated def-as-tag node. */
1972
1973        if (type_p->fe_info->tag_ptr != NULL)
1974            type_p->fe_info->tag_ptr->rep_as_type = type_p->rep_as_type;
1975
1976        /* Link type node into list of represent_as types. */
1977
1978        typep_p = AST_type_ptr_node(acf_location(acf));
1979        typep_p->type = type_p;
1980
1981        int_p->ra_types = (AST_type_p_n_t *)AST_concat_element(
1982                                                (ASTP_node_t *)int_p->ra_types,
1983                                                (ASTP_node_t *)typep_p);
1984    }
1985}
1986
1987/*
1988**  p r o c e s s _ c s _ c h a r _ t y p e
1989**
1990**  Processes a [cs_char] clause applied to a type.  Validates that
1991**  [cs_char] types are not nested.  Adds the type to a list of types
1992**  that have the [cs_char] attribute.
1993*/
1994
1995static void process_cs_char_type
1996(
1997    acf_parser_state_t  *acf,
1998    AST_interface_n_t   *int_p,     /* [in] Ptr to AST interface node */
1999    AST_type_n_t        *type_p,    /* [in] Ptr to AST type node */
2000    char const      *ref_type_name  /* [in] Name in cs_char() clause */
2001)
2002{
2003    NAMETABLE_id_t  ref_type_id;    /* Nametable id of referenced name */
2004    char const      *file_name;     /* Related file name */
2005    char const      *perm_name;     /* Permanent copy of referenced name */
2006    AST_type_n_t    *parent_type_p; /* Parent type with same attribute */
2007    char const      *parent_name;   /* Name of parent type */
2008
2009    ref_type_id = NAMETABLE_add_id(ref_type_name);
2010
2011    /*
2012     * Report error if the type name referenced in the attribute is an AST
2013     * type which also has the same attribute, i.e. types with this attribute
2014     * cannot nest.
2015     */
2016    if (lookup_cs_char_name(int_p->cs_types, ref_type_id, &parent_type_p,
2017                            &perm_name))
2018    {
2019        NAMETABLE_id_to_string(parent_type_p->name, &parent_name);
2020        STRTAB_str_to_string(parent_type_p->fe_info->acf_file, &file_name);
2021
2022        /*** This needs updating ***/
2023        acf_error(acf, NIDL_REPASNEST);
2024        acf_error(acf, NIDL_TYPEREPAS, parent_name, perm_name);
2025        acf_error(acf, NIDL_NAMEDECLAT, parent_name, file_name,
2026                  parent_type_p->fe_info->acf_source_line);
2027    }
2028
2029    /*
2030     * If the type node already has a type name for this attribute,
2031     * this one must duplicate that same name.
2032     */
2033    if (type_p->cs_char_type != NULL)
2034    {
2035        NAMETABLE_id_to_string(type_p->cs_char_type->type_name, &perm_name);
2036
2037        if (strcmp(perm_name, ref_type_name) != 0)
2038        {
2039            char const *new_ref_type_name; /* Ptr to permanent copy */
2040            NAMETABLE_id_t  name_id;    /* Handle on perm copy */
2041
2042            name_id = NAMETABLE_add_id(ref_type_name);
2043            NAMETABLE_id_to_string(name_id, &new_ref_type_name);
2044
2045            STRTAB_str_to_string(
2046                        type_p->cs_char_type->fe_info->acf_file, &file_name);
2047
2048            /*** This needs updating ***/
2049            acf_error(acf, NIDL_CONFREPRTYPE, new_ref_type_name, perm_name);
2050            acf_error(acf, NIDL_NAMEDECLAT, perm_name, file_name,
2051                      type_p->cs_char_type->fe_info->acf_source_line);
2052        }
2053    }
2054    else
2055    {
2056        /*
2057         * Process valid [cs_char] clause.
2058         */
2059        AST_type_p_n_t  *typep_p;       /* Used to link type nodes */
2060        AST_cs_char_n_t *cschar_p;      /* Ptr to cs_char node */
2061
2062        /* Add cs_char type name and build cs_char AST node. */
2063
2064        cschar_p = type_p->cs_char_type = AST_cs_char_node(
2065				acf_location(acf), ref_type_id);
2066        /* Store source information. */
2067        if (cschar_p->fe_info != NULL)
2068        {
2069            cschar_p->fe_info->acf_file = acf->acf_location.fileid;
2070            cschar_p->fe_info->acf_source_line = acf_yylineno(acf);
2071        }
2072
2073        /* Check for associated def-as-tag node. */
2074
2075        if (type_p->fe_info->tag_ptr != NULL)
2076            type_p->fe_info->tag_ptr->cs_char_type = type_p->cs_char_type;
2077
2078        /* Link type node into list of cs_char types. */
2079
2080        typep_p = AST_type_ptr_node(acf_location(acf));
2081        typep_p->type = type_p;
2082
2083        int_p->cs_types = (AST_type_p_n_t *)AST_concat_element(
2084                                                (ASTP_node_t *)int_p->cs_types,
2085                                                (ASTP_node_t *)typep_p);
2086    }
2087}
2088
2089/*
2090 *  d u m p _ a t t r i b u t e s
2091 *
2092 *  Function:   Prints list of attributes parsed for a particular node type
2093 *
2094 *  Inputs:     header_text - Initial text before node name and attributes
2095 *              node_name   - Name of interface, type, operation, or parameter
2096 *              node_attr_p - Address of node attributes structure
2097 *
2098 *  Globals:    repr_type_name  - represent_as type name, used if bit is set
2099 *              cs_char_type_name - cs_char type name, used if bit is set
2100 *              cs_tag_rtn_name - cs_tag_rtn name, used if bit is set
2101 *              binding_callout_name - binding_callout name, used if bit is set
2102 */
2103
2104static void dump_attributes
2105(
2106    acf_parser_state_t *acf,
2107    const char	    *header_text,       /* [in] Initial output text */
2108    char const      *node_name,         /* [in] Name of tree node */
2109    acf_attrib_t    *node_attr_p        /* [in] Node attributes ptr */
2110)
2111#define MAX_ATTR_TEXT   1024    /* Big enough for lots of extern_exceptions */
2112{
2113    char            attr_text[MAX_ATTR_TEXT];   /* Buf for formatting attrs */
2114    int             pos;                /* Position in buffer */
2115    acf_attrib_t    node_attr;          /* Node attributes */
2116
2117    node_attr = *node_attr_p;
2118
2119    printf("%s %s", header_text, node_name);
2120
2121    if (node_attr.mask == 0)
2122    {
2123        printf("\n");
2124    }
2125    else
2126    {
2127        printf(" attributes: ");
2128        strlcpy(attr_text, "[", sizeof (attr_text));
2129
2130        if (node_attr.bit.auto_handle)
2131            strlcat(attr_text, "auto_handle, ", sizeof(attr_text));
2132        if (node_attr.bit.code)
2133            strlcat(attr_text, "code, ", sizeof(attr_text));
2134        if (node_attr.bit.nocode)
2135            strlcat(attr_text, "nocode, ", sizeof(attr_text));
2136        if (node_attr.bit.comm_status)
2137            strlcat(attr_text, "comm_status, ", sizeof(attr_text));
2138        if (node_attr.bit.decode)
2139            strlcat(attr_text, "decode, ", sizeof(attr_text));
2140        if (node_attr.bit.enable_allocate)
2141            strlcat(attr_text, "enable_allocate, ", sizeof(attr_text));
2142        if (node_attr.bit.encode)
2143            strlcat(attr_text, "encode, ", sizeof(attr_text));
2144        if (node_attr.bit.explicit_handle)
2145            strlcat(attr_text, "explicit_handle, ", sizeof(attr_text));
2146        if (node_attr.bit.nocancel)
2147            strlcat(attr_text, "nocancel, ", sizeof(attr_text));
2148        if (node_attr.bit.extern_exceps && ASTP_parsing_main_idl)
2149        {
2150            AST_exception_n_t   *excep_p;
2151            char const               *name;
2152            strlcat(attr_text, "extern_exceptions(", sizeof(attr_text));
2153            for (excep_p = the_interface->exceptions;
2154                 excep_p != NULL;
2155                 excep_p = excep_p->next)
2156            {
2157                if (AST_EXTERN_SET(excep_p))
2158                {
2159                    NAMETABLE_id_to_string(excep_p->name, &name);
2160                    strlcat(attr_text, name, sizeof(attr_text));
2161                    strlcat(attr_text, ",", sizeof(attr_text));
2162                }
2163            }
2164            attr_text[strlen(attr_text)-1] = '\0';  /* overwrite trailing ',' */
2165            strlcat(attr_text, "), ", sizeof(attr_text));
2166        }
2167        if (node_attr.bit.fault_status)
2168            strlcat(attr_text, "fault_status, ", sizeof(attr_text));
2169        if (node_attr.bit.heap)
2170            strlcat(attr_text, "heap, ", sizeof(attr_text));
2171        if (node_attr.bit.implicit_handle)
2172            strlcat(attr_text, "implicit_handle, ", sizeof(attr_text));
2173        if (node_attr.bit.in_line)
2174            strlcat(attr_text, "in_line, ", sizeof(attr_text));
2175        if (node_attr.bit.out_of_line)
2176            strlcat(attr_text, "out_of_line, ", sizeof(attr_text));
2177        if (node_attr.bit.cs_stag)
2178            strlcat(attr_text, "cs_stag, ", sizeof(attr_text));
2179        if (node_attr.bit.cs_drtag)
2180            strlcat(attr_text, "cs_drtag, ", sizeof(attr_text));
2181        if (node_attr.bit.cs_rtag)
2182            strlcat(attr_text, "cs_rtag, ", sizeof(attr_text));
2183        if (node_attr.bit.represent_as)
2184        {
2185            strlcat(attr_text, "represent_as(", sizeof(attr_text));
2186            strlcat(attr_text, acf->acf_repr_type_name, sizeof(attr_text));
2187            strlcat(attr_text, "), ", sizeof(attr_text));
2188        }
2189        if (node_attr.bit.cs_char)
2190        {
2191            strlcat(attr_text, "cs_char(", sizeof(attr_text));
2192            strlcat(attr_text, acf->acf_cs_char_type_name, sizeof(attr_text));
2193            strlcat(attr_text, "), ", sizeof(attr_text));
2194        }
2195        if (node_attr.bit.cs_tag_rtn)
2196        {
2197            strlcat(attr_text, "cs_tag_rtn(", sizeof(attr_text));
2198            strlcat(attr_text, acf->acf_cs_tag_rtn_name, sizeof(attr_text));
2199            strlcat(attr_text, "), ", sizeof(attr_text));
2200        }
2201        if (node_attr.bit.binding_callout)
2202        {
2203            strlcat(attr_text, "binding_callout(", sizeof(attr_text));
2204            strlcat(attr_text, acf->acf_binding_callout_name, sizeof(attr_text));
2205            strlcat(attr_text, "), ", sizeof(attr_text));
2206        }
2207
2208        /* Overwrite trailing ", " with "]" */
2209
2210        pos = strlen(attr_text) - strlen(", ");
2211        attr_text[pos] = ']';
2212        attr_text[pos+1] = '\0';
2213
2214        printf("%s\n", attr_text);
2215    }
2216}
2217
2218/* preserve coding style vim: set tw=78 sw=4 : */
2219