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**  NAME
79**
80**      ASTP_COM.C
81**
82**  FACILITY:
83**
84**      Interface Definition Language (IDL) Compiler
85**
86**  ABSTRACT:
87**
88**      Common routines shared between the AST builder modules.
89**
90**  VERSION: DCE 1.0
91**
92*/
93
94#include <nidl.h>
95#include <nametbl.h>
96#include <errors.h>
97#include <astp.h>
98#include <nidlmsg.h>
99#include <nidl_y.h>
100#include <checker.h>
101#include <message.h>
102#include <backend.h>
103#include <command.h>
104#include <irep.h>
105
106static AST_type_n_t *AST_propagate_typedef (
107    parser_location_p location,
108    AST_type_n_t *type_node_ptr,
109    ASTP_declarator_n_t *declarator_ptr,
110    ASTP_attributes_t   *attributes
111);
112
113static AST_array_n_t *AST_propagate_array_type (
114    parser_location_p		  location,
115    AST_type_n_t *type_node_ptr,
116    AST_type_n_t *element_type_node_ptr,
117    ASTP_declarator_op_n_t *declarator_op_ptr
118);
119
120static void ASTP_verify_non_anonymous (
121    parser_location_p location,
122    AST_type_n_t *type,
123    ASTP_declarator_n_t *declarator_ptr
124);
125
126
127
128/*
129 *  A S T P _ a d d _ n a m e _ b i n d i n g
130 *  ==========================================
131 *
132 * This routine add a binding between the name and
133 * node specified.  If the name is already declared
134 * the NIDL_NAMEALRDEC error message is displayed.
135 */
136
137void ASTP_add_name_binding
138(
139	 parser_location_p  location,
140    NAMETABLE_id_t name,
141    void          *AST_node
142)
143{
144    char        const *identifier; /* place to receive the identifier text pointer */
145    ASTP_node_t const *binding;    /* place to recieve binding */
146    char        const *filename;   /* place to receive the filename text pointer */
147    int issue_error;
148    int issue_case_warning ATTRIBUTE_UNUSED;
149
150    /*
151     * Check to see if there is already a constant binding to the name.
152     * If there is, then we can't make this declaration because constants
153     * are implemented as #define which are global.
154     */
155    binding = NAMETABLE_lookup_binding(name);
156    if ((binding != NULL) && (binding->fe_info->node_kind == fe_constant_n_k))
157        issue_error = true;
158    else
159        /* Add the name to nametable and bind it to the specified node */
160        issue_error = !NAMETABLE_add_binding (name, AST_node);
161
162    /*
163     * If the name binding failed, output the error message.
164     */
165    if (issue_error)
166    {
167	/* FIXME binding can become NULL */
168
169	assert(NULL != binding);
170
171        NAMETABLE_id_to_string (name, &identifier);
172
173        /* Select message and file information as present */
174        if ((binding->fe_info != (fe_info_t *)NULL) &&
175            (binding->fe_info->source_line != 0) &&
176            (binding->fe_info->file != STRTAB_NULL_STR))
177        {
178            STRTAB_str_to_string(binding->fe_info->file, &filename);
179            log_error (location->lineno, NIDL_NAMEPREVDECLAT, identifier,
180                    filename, binding->fe_info->source_line, NULL);
181        }
182        else
183            log_error (location->lineno, NIDL_NAMEALRDEC, identifier, NULL);
184    }
185
186    return;
187}
188
189/*-----------------------------------------------------------------------*/
190/*
191 *  A S T P _ v a l i d a t e _ f o r w a r d _ r e f
192 *  =================================================
193 *
194 * This routine verifies that the specified type
195 * is not a forward reference to an incomplete struct/union
196 * by tag.  This is to prevent the generation of nonstandard C code
197 * that may not compile.  Forward references to incomplete types
198 * are only allowed in contexts where allocation size information is
199 * not needed (e.g. a pointer to the type, or in a typedef).  If
200 * the type passed to this routine is not yet completely defined, then
201 * an error will be issued.
202 */
203
204void ASTP_validate_forward_ref
205(
206	 parser_location_p location,
207    AST_type_n_t *type
208)
209{
210    /*
211     * Check that the base type is not an incomplete struct/union
212     */
213    if (AST_DEF_AS_TAG_SET(type) &&
214        ((type->kind == AST_disc_union_k) ||
215         (type->kind == AST_structure_k)) &&
216        (type->type_structure.structure == NULL))
217    {
218        char const *identifier;
219        NAMETABLE_id_to_string(type->fe_info->tag_name, &identifier);
220        log_error(location->lineno, NIDL_DEFNOTCOMP, identifier, NULL);
221    }
222}
223
224/*
225 *  A S T P _ v a l i d a t e _ f o r w a r d _ r e f _ s c o p e
226 *  =============================================================
227 *
228 * This routine verifies that the specified type is not a forward reference
229 * to an incomplete type by tag that by (ANSI C) definition is in a different
230 * lexical scope than the eventual type and tag definition.  This is to prevent
231 * the generation of nonstandard C code that may not compile.  Forward
232 * references to incomplete types must be at the same scoping level.
233 */
234
235static void ASTP_validate_forward_ref_scope
236(
237    parser_location_p location,
238    AST_type_n_t *type,
239    ASTP_node_t  *parent_node
240)
241{
242    /*
243     * Check that the base type is not an incomplete struct/union
244     */
245    if (AST_DEF_AS_TAG_SET(type)
246        && type->type_structure.structure == NULL
247        && parent_node->fe_info->node_kind == fe_parameter_n_k)
248    {
249        /* Forward tag reference in this declaration is not ANSI C compliant */
250        char const *identifier;
251        NAMETABLE_id_to_string(type->fe_info->tag_name, &identifier);
252        log_warning(location->lineno, NIDL_FWDTAGREF, identifier, NULL);
253    }
254}
255
256/*-----------------------------------------------------------------------*/
257
258/*
259 * A S T P _ c h a s e _ p t r _ t o _ k i n d
260 * ===========================================
261 *
262 * Chase a pointer type until a specified
263 * "kind" type is found.
264 *
265 * Inputs:
266 *  type_node   The starting type node which SHOULD
267 *              be a pointer kind.
268 *
269 *  kind        The "kind" of type node we're
270 *              searching for.
271 *
272 * Outputs:
273 *
274 *
275 * Function Value:
276 *  Pointer to the type node which contains
277 *  the kind.  If search failed, NULL is returned.
278 *  If successful, returned type node's fe_info
279 *  pointer count if set to the number of pointer
280 *  nodes traversed.
281 */
282AST_type_n_t *ASTP_chase_ptr_to_kind
283(
284    AST_type_n_t *type_node,
285    AST_type_k_t kind
286)
287{
288    AST_type_n_t *tp;
289    short int    pointer_count;
290
291    for (tp= type_node, pointer_count = 0;
292        (tp->kind != kind ) && (tp->kind == AST_pointer_k);
293        tp = tp->type_structure.pointer->pointee_type, pointer_count++)
294    {
295        /* Chase pointer until we find the "kind" type node */
296    }
297
298    if (tp->kind != kind)
299    {
300        tp = NULL;
301    }
302    else
303    {
304        tp->fe_info->pointer_count = pointer_count;
305    }
306
307    return tp;
308}
309
310/*-------------------------------------------------------------------*/
311
312/*
313 * A S T P _ c h a s e _ p t r _ t o _ t y p e
314 * ===========================================
315 *
316 * Chase a pointer type until a non-pointer is
317 * is found, i.e. until the base type is found.
318 *
319 * Inputs:
320 *  type_node   The starting type node which SHOULD
321 *              be a pointer kind.
322 *
323 * Outputs:
324 *
325 *
326 * Function Value:
327 *  Pointer to the type node which lives
328 *  at the end of the chain of pointers.
329 *  The returned type node's fe_info pointer_count
330 *  field is set to the number of pointer nodes
331 *  traversed.
332 */
333AST_type_n_t *ASTP_chase_ptr_to_type
334(
335    AST_type_n_t *type_node
336)
337{
338    AST_type_n_t *tp;
339    short int    pointer_count;
340
341    for (tp= type_node, pointer_count = 0;
342        (tp->kind == AST_pointer_k);
343        tp = tp->type_structure.pointer->pointee_type, pointer_count++)
344    {
345        /* Chase pointer until we find the base type node */
346    }
347
348    tp->fe_info->pointer_count = pointer_count;
349
350    return tp;
351}
352
353/*-------------------------------------------------------------------*/
354
355/*
356 *  A S T _ c l o n e _ c o n s t a n t
357 *  ===================================
358 *
359 *  Clone a constant node.
360 *
361 */
362
363AST_constant_n_t *AST_clone_constant
364(
365	 parser_location_p location,
366    AST_constant_n_t *constant_node_p
367)
368{
369    AST_constant_n_t *new_const_node_p;
370
371    /*
372     * Create constant node of the appropriate kind and
373     * replicate value  and fe_info constant kind information
374     */
375
376    new_const_node_p = AST_constant_node (location, constant_node_p->kind);
377
378    switch (new_const_node_p->kind)
379    {
380        case AST_boolean_const_k:
381            new_const_node_p->value.boolean_val =
382                    constant_node_p->value.boolean_val;
383            break;
384
385        case AST_char_const_k:
386            new_const_node_p->value.char_val =
387                    constant_node_p->value.char_val;
388            break;
389
390        case AST_int_const_k:
391            new_const_node_p->value.int_val =
392                    constant_node_p->value.int_val;
393            break;
394
395        case AST_string_const_k:
396            new_const_node_p->value.string_val =
397                    constant_node_p->value.string_val;
398            break;
399
400        default:
401            break;
402    }
403
404    /* Get the constant kind from the front end info */
405    new_const_node_p->fe_info->fe_type_id =
406            constant_node_p->fe_info->fe_type_id;
407    new_const_node_p->fe_info->type_specific.const_kind =
408            constant_node_p->fe_info->type_specific.const_kind;
409
410    return new_const_node_p;
411}
412
413/*----------------------------------------------------------------------*/
414
415/*
416 *  A S T _ c o n c a t _ e l e m e n t
417 *
418 *  A generic list handling routine that concatenates a element (which
419 *  may be itself a singly-linked list) to a singly-linked list of the
420 *  same type.
421 *
422 *  Assumptions:
423 *      All element types have the next and last pointers as the first
424 *      fields in the structure.
425 *
426 *  Function Value:
427 *      The updated list header.
428 */
429
430ASTP_node_t *AST_concat_element
431(
432    ASTP_node_t *list_head,
433    ASTP_node_t *element
434)
435{
436    /* Check for null element.  Grammer will sometimes call us this way */
437    if (element == NULL)
438    {
439        return list_head;
440    }
441
442    /* List is empty.  Link in new element or list */
443    if (list_head == NULL)
444    {
445        list_head = element;
446        return list_head;
447    }
448
449    /* Only one item on list. Link in new element or list */
450    if (list_head->last == NULL)
451    {
452        if (element->last == NULL)
453        {
454            list_head->last = element;
455            list_head->next = element;
456            return list_head;
457        }
458
459        list_head->last = element->last;
460        list_head->next = element;
461        return list_head;
462    }
463
464    /* Multiple items exist on list. */
465    list_head->last->next = element;
466    if (element->last != NULL)
467    {
468        list_head->last = element->last;
469    }
470    else
471    {
472        list_head->last = element;
473    }
474
475    return list_head;
476
477}
478
479/*---------------------------------------------------------------------*/
480
481/*
482 *  A S T P _ l o o k u p _ b i n d i n g
483 *  ==========================================
484 *
485 * This routine looks up a binding of a particular
486 * AST node.
487 *
488 * Inputs:
489 *      name          Name identifier to lookup.
490 *      node_kind     The node kind the binding should be.
491 *      noforward_ref True, if forward references are not
492 *                    expected.
493 * Outputs:
494 *      None.
495 *
496 * Function Value:
497 *      If successful, the node bound to the name of the
498 *      particular type, otherwise NULL is returned.
499 */
500
501ASTP_node_t *ASTP_lookup_binding
502(
503	 parser_location_p			location,
504    NAMETABLE_id_t      name,
505    fe_node_k_t         node_kind,
506    boolean             noforward_ref
507
508)
509{
510    ASTP_node_t     *bound_node;
511    char const      *identifier;
512
513    /*
514     * Lookup binding
515     */
516    bound_node = (ASTP_node_t *) NAMETABLE_lookup_binding(name);
517
518    /*
519     * If not found tell them if the caller wants
520     * us to.  This is for parameters and field
521     * array bound attributes which can be
522     * forward referenced.
523     */
524    if ((bound_node == NULL) && noforward_ref)
525    {
526        NAMETABLE_id_to_string (name, &identifier);
527        log_error(location->lineno, NIDL_NAMENOTFND, identifier, NULL) ;
528    }
529#if 0
530	 /* If they are looking for a type and we got an ORPC interface, chase
531	  * through to the underlying type information */
532	 if (node_kind == fe_type_n_k && bound_node &&
533				bound_node->fe_info->node_kind == fe_interface_n_k &&
534				AST_OBJECT_SET((AST_interface_n_t*)bound_node))
535		  return bound_node->type_structure;
536		  bound_node = (ASTP_node_t*)((AST_interface_n_t*)bound_node)->orpc_intf_type;
537#endif
538    /*
539     * If binding node of wrong type, return NULL, and tell them.
540     */
541    if ((bound_node != NULL) &&
542        (bound_node->fe_info->node_kind != node_kind))
543    {
544        /* If forward references are not allowed, output error message now */
545        if (noforward_ref)
546        {
547            NAMETABLE_id_to_string (name, &identifier);
548
549            switch (node_kind)
550            {
551                case fe_constant_n_k:
552                    log_error(location->lineno, NIDL_NAMENOTCONST, identifier,
553			      NULL) ;
554                    break;
555
556                case fe_type_n_k:
557                    log_error(location->lineno, NIDL_NAMENOTTYPE, identifier,
558			      NULL) ;
559                    break;
560
561                case fe_field_n_k:
562                    log_error(location->lineno, NIDL_NAMENOTFIELD, identifier,
563			      NULL) ;
564                    break;
565
566                case fe_parameter_n_k:
567                    log_error(location->lineno, NIDL_NAMENOTPARAM, identifier,
568			      NULL) ;
569                    break;
570
571                default:
572                    break;
573            }
574
575            /* State where the name was previously declared, if known */
576            if ((bound_node->fe_info->source_line != 0) &&
577                (bound_node->fe_info->file != STRTAB_NULL_STR))
578            {
579                char const *filename; /* place to receive the filename text pointer */
580                STRTAB_str_to_string(bound_node->fe_info->file, &filename);
581                log_error (location->lineno, NIDL_NAMEPREVDECLAT, identifier,
582                        filename, bound_node->fe_info->source_line, NULL);
583            }
584        }
585
586        /* Return Null, so caller doesn't use wrong node type that we found */
587        bound_node = NULL;
588    }
589
590    return bound_node;
591}
592
593/*-----------------------------------------------------------------------*/
594
595/*
596 *  A S T _ p o i n t e r _ n o d e
597 *  ===============================
598 *
599 *  Create and initialize a pointer node
600 */
601
602AST_pointer_n_t * AST_pointer_node
603(
604    parser_location_p location,
605    AST_type_n_t * pointee
606)
607{
608    AST_pointer_n_t * pointer_node_ptr;
609
610    pointer_node_ptr = NEW (AST_pointer_n_t);
611    pointer_node_ptr->pointee_type = pointee;
612    ASTP_set_fe_info (location, &pointer_node_ptr->fe_info, fe_pointer_n_k);
613    return pointer_node_ptr;
614}
615
616/*---------------------------------------------------------------------*/
617
618/*
619 *  A S T _ d e c l a r a t o r s _ t o _ t y p e s
620 *  ===============================================
621 *
622 * For each of the linked declarator nodes, allocate a
623 * type node and collapse the declarator node to the
624 * type node, forming a list of type pointer nodes.
625 *
626 * INPUTS:
627 *  type_ptr        Pointer to type node.
628 *  declarators_ptr Pointer to list of declarator nodes.
629 *
630 * OUTPUTS:
631 *  None.
632 *
633 * FUNCTION VALUE:
634 *  Pointer to a list of type node pointers.
635 *
636 * NOTES:
637 *  The original type node is used for the first declarator node.
638 *
639 */
640
641AST_type_p_n_t *AST_declarators_to_types
642(
643    parser_location_p location,
644    AST_interface_n_t * ifp,
645    AST_type_n_t *type_ptr,
646    ASTP_declarator_n_t *declarators_ptr,
647    ASTP_attributes_t   *attributes
648)
649{
650    AST_type_p_n_t
651        *type_p_list = NULL,        /* List of type pointer nodes */
652        *type_p_ptr;                /* Created for each type node */
653
654    ASTP_declarator_n_t
655        gen_declarator,             /* Generated declarator for use as base */
656        *base_dp = NULL,            /* Base declarator used for the base    */
657                                    /* type name and generates other types. */
658        *dp;                        /* For traversing through declarators   */
659
660    AST_type_n_t
661        *base_type = type_ptr;      /* Base type used to generate other all */
662                                    /* other types derived in this typedef. */
663
664    /*
665     * Look for a simple declarator to use when generating the base type node.
666     * All other types are generated from the base type.
667     */
668    for (dp = declarators_ptr;
669            dp != (ASTP_declarator_n_t *) NULL;
670            dp = dp->next)
671    {
672        if (dp->next_op == NULL)
673        {
674            /*
675             * Save the base declarator so we can skip over it during our second
676             * pass over the declarators.
677             */
678            base_dp = dp;
679
680            /*
681             * If the original type is a struct/union with tag and this is a simple
682             * declarator (not a pointer, array or function), then we must do some
683             * special processing to set the name in the type node for tag
684             * references to the type name.  The tag name is only stored in the
685             * structure_node pointed to by the type node.
686             */
687            if ((type_ptr->fe_info->tag_ptr != NULL) &&
688                (type_ptr->fe_info->tag_ptr->name == NAMETABLE_NIL_ID))
689                type_ptr->fe_info->tag_ptr->name = base_dp->name;
690
691            /*
692             * All that's needed in this loop so exit loop
693             */
694            break;
695        }
696    }
697
698    /*
699     *  If we did not find a base declarator to use and the base type is not
700     *  named, then generate a named base declarator from which to build all
701     *  of the more complicated types.
702     */
703    if ((base_dp == NULL) &&                      /* No simple declarator */
704        (base_type->name == NAMETABLE_NIL_ID) &&  /* Base type is anonymous */
705        ((base_type->kind == AST_structure_k) ||  /* a struct or union */
706         (base_type->kind == AST_disc_union_k)) &&
707	(base_type->fe_info->tag_name == NAMETABLE_NIL_ID)) /* union/struct doesn't have a tag name */
708    {
709        base_dp = &gen_declarator;
710        base_dp->name = AST_generate_name(ifp,"");
711        base_dp->next = NULL;
712        base_dp->last = NULL;
713        base_dp->next_op = NULL;
714        base_dp->last_op = NULL;
715        base_dp->fe_info = NULL;
716    }
717
718    /*
719     * create a type for the simple type declared in this typedef and
720     * use it to generate the types for other declarators in this typedef.
721     */
722    if (base_dp != NULL)
723    {
724        ASTP_attributes_t local_attributes;  /* copy of attributes that     */
725        local_attributes = *attributes;      /* we can manipulate           */
726
727        /* Create a type pointer node */
728        type_p_ptr = AST_type_ptr_node(location);
729
730        /*
731         * Propagate declarator to the type node, merge in any attributes, and
732         * Link type node to type pointer node, and form type pointer list.
733         */
734        base_type = AST_propagate_typedef(location, type_ptr, base_dp, &local_attributes);
735        type_p_ptr->type = base_type;
736        type_p_list = (AST_type_p_n_t *)AST_concat_element (
737                        (ASTP_node_t *)type_p_list, (ASTP_node_t *)type_p_ptr);
738
739        /*
740         *  If we are processing a generated declarator, ignore all pointer
741         *  attributes
742         */
743        if (base_dp == &gen_declarator)
744              ASTP_CLR_ATTR(&local_attributes,ASTP_IGNORE|ASTP_PTR|ASTP_REF|
745                          ASTP_UNIQUE|ASTP_STRING);
746
747        /* Set the type attributes to the new type node */
748        AST_set_type_attrs(location, type_p_ptr->type, &local_attributes);
749
750        /*
751         * If there is an associated DEF_AS_TAG type node, then make sure to
752         * set on that type node as well.
753         */
754        if (type_p_ptr->type->fe_info->tag_ptr != NULL)
755            AST_set_type_attrs(location, type_p_ptr->type->fe_info->tag_ptr, &local_attributes);
756     }
757
758    /*
759     * For each of the declarators create a new type as described by the
760     * declarators.  These types will all be dervied from the base type.
761     */
762    for (dp = declarators_ptr;
763            dp != (ASTP_declarator_n_t *) NULL;
764            dp = dp->next)
765    {
766        /* Skip over the base declarator because it's been processed */
767        if (dp == base_dp) continue;
768
769        /* Create a type pointer node */
770        type_p_ptr = AST_type_ptr_node(location);
771
772        /*
773         * Propagate declarator to the type node, merge in any attributes, and
774         * Link type node to type pointer node, and form type pointer list.
775         */
776        type_p_ptr->type = AST_propagate_typedef(location, base_type, dp, attributes);
777        type_p_list =  (AST_type_p_n_t *)AST_concat_element (
778                        (ASTP_node_t *)type_p_list, (ASTP_node_t *)type_p_ptr);
779
780        /* Set the type attributes to the new type node */
781        AST_set_type_attrs(location, type_p_ptr->type, attributes);
782
783        /*
784         * If there is an associated DEF_AS_TAG type node, then make sure to
785         * set on that type node as well.
786         */
787        if (type_p_ptr->type->fe_info->tag_ptr != NULL)
788            AST_set_type_attrs(location, type_p_ptr->type->fe_info->tag_ptr, attributes);
789    }
790
791    /* Free temporary declarators list */
792    ASTP_free_declarators(declarators_ptr);
793
794    return type_p_list;
795}
796
797/*---------------------------------------------------------------------*/
798
799/*
800 *
801 * A S T _ p r o p a g a t e _ a r r a y _ t y p e
802 * ===============================================
803 *
804 * Create the AST array node and propagate
805 * the array index information pointed to by
806 * the declarator node to the array node
807 *
808 * Note, that in the declarator node, the
809 * array index is a linked list of AST Private
810 * array index nodes.  With the AST array node,
811 * it is implemented as a vector.
812 */
813
814AST_array_n_t *AST_propagate_array_type
815(
816    parser_location_p		  location,
817    AST_type_n_t            *type_node_ptr,
818    AST_type_n_t            *element_type_node_ptr,
819    ASTP_declarator_op_n_t  *declarator_op_ptr
820)
821{
822    AST_array_n_t        *array_node_ptr;
823    ASTP_array_index_n_t *index_ptr;
824    AST_array_index_n_t  *array_index_node;
825    unsigned short       index_count;
826    boolean              is_conformant = FALSE;
827
828    /* Create the array node, creating linking in a element type node */
829    array_node_ptr = AST_array_node(location, element_type_node_ptr);
830
831    /* Propagate the array indice information */
832
833    /* Count the number of dimensions */
834    for (index_ptr = declarator_op_ptr->op_info.indices, index_count=0;
835         index_ptr != NULL;
836         index_ptr = index_ptr->next, index_count++)
837         {};
838
839    array_node_ptr->index_count = index_count;
840
841    /* Allocate (and initialize) the array index vector */
842    array_node_ptr->index_vec = AST_array_index_node(location, index_count);
843
844    /*
845     * Fill in the index information pointed
846     * to by the array node and set the FIXED flags.
847     */
848    for (index_ptr = declarator_op_ptr->op_info.indices,
849         array_index_node = array_node_ptr->index_vec;
850         index_ptr != NULL;
851         index_ptr=index_ptr->next, array_index_node++)
852    {
853        if (index_ptr->lower_bound != NULL)
854        {
855            array_index_node->lower_bound = index_ptr->lower_bound;
856            AST_SET_FIXED_LOWER(array_index_node);
857        }
858        else
859        {
860            is_conformant = TRUE;
861        }
862
863        if (index_ptr->upper_bound != NULL)
864        {
865            array_index_node->upper_bound = index_ptr->upper_bound;
866            AST_SET_FIXED_UPPER(array_index_node);
867        }
868        else
869        {
870            is_conformant = TRUE;
871        }
872
873    }
874
875    /*
876     * If any dimension of the array is not fixed,
877     * set the conformant flag in the type node
878     * specifying an unfixed allocation size
879     */
880    if (is_conformant)
881    {
882        AST_SET_CONFORMANT(type_node_ptr);
883    }
884
885    return array_node_ptr;
886}
887
888/*---------------------------------------------------------------------*/
889
890/*
891 *
892 *  A S T _ p r o p a g a t e _ t y p e _ a t t r s
893 *  ===============================================
894 *
895 *  Check for the presence of the REF, PTR or UNIQUE attribute
896 *  and set the specified flag in the parameter or
897 *  field's type node if present.
898 *  We need to clone the type if the new type
899 *  is (build by AST_propagate_type()) is a simple declarator.
900 *
901 *  This processing is done here (called from
902 *  propagate_types() to minimize on the cloning,
903 *  since we know we just created a new anonymous
904 *  type (no clone) or used the current type (clone).
905 *
906 *  We also propagate type attributes which are also
907 *  field/parameter/arm attributes to the field/parameter/arm node.
908 *  These currently are string, small, and ignore.
909 */
910
911static AST_type_n_t *AST_propagate_type_attrs
912(
913    parser_location_p location,
914    AST_type_n_t *type_node_ptr,
915    ASTP_attributes_t *attributes,
916    boolean needs_clone ATTRIBUTE_UNUSED,
917    ASTP_node_t *parent_node
918)
919{
920    AST_type_n_t *return_type;          /* type node to return */
921    ASTP_attr_flag_t ptr_attrs = 0;
922
923    return_type = type_node_ptr;
924
925    /*
926     * Only one of [unique], [ptr], or [ref] can be specified.
927     * If that is not the case, output an error stating that the
928     * two specified are conflicting.
929     */
930    if (attributes != NULL)
931    {
932        /* Copy the iid_is name */
933        return_type->iid_is_name = attributes->iid_is_name;
934
935        /*
936         *  If any pointer attrs are set, make sure only one of them is
937         *  specified.
938         */
939        ptr_attrs = (attributes->attr_flags) & (ASTP_UNIQUE|ASTP_PTR|ASTP_REF);
940        if ((ptr_attrs != 0) &&
941            !((ptr_attrs == ASTP_REF) || (ptr_attrs == ASTP_PTR) ||
942              (ptr_attrs == ASTP_UNIQUE)))
943        {
944            ASTP_attr_flag_t attr1 = ASTP_REF;
945            ASTP_attr_flag_t attr2 = ASTP_PTR;
946            if (!ASTP_TEST_ATTR(attributes,ASTP_REF)) attr1 = ASTP_UNIQUE;
947            if (!ASTP_TEST_ATTR(attributes,ASTP_PTR)) attr2 = ASTP_UNIQUE;
948            log_error(location->lineno, NIDL_CONFLICTATTR,
949                  KEYWORDS_lookup_text(AST_attribute_to_token(&attr1)),
950                  KEYWORDS_lookup_text(AST_attribute_to_token(&attr2)), NULL);
951        }
952
953        /*
954         * Handle V1 attributes specified on an instance, by propagating to
955         * the type node where they are expected.  Since this is propagation
956         * from instance to type, only do it for anonymous types.  If the
957         * type is not anonymous the V1 attributes should have been set
958         * in the typedef in which it is declared.  Since we don't clear
959         * the attribute, an error will occur in the routine AST_set_flags.
960         */
961        if (return_type->name == NAMETABLE_NIL_ID)
962        {
963            if (ASTP_TEST_ATTR(attributes,ASTP_UNALIGN))
964                AST_SET_UNALIGN(return_type);
965            if (ASTP_TEST_ATTR(attributes,ASTP_SMALL))
966                AST_SET_SMALL(return_type);
967            if (ASTP_TEST_ATTR(attributes,ASTP_STRING0))
968                AST_SET_STRING0(return_type);
969            if (ASTP_TEST_ATTR(attributes,ASTP_V1_ENUM))
970                AST_SET_V1_ENUM(return_type);
971            if (ASTP_TEST_ATTR(attributes,ASTP_SWITCH_TYPE))
972            {
973                /*
974                 * Valid only on non-encapsulated union type
975                 * on a field or parameter instance.
976                 */
977                if (return_type->kind == AST_disc_union_k
978                    && return_type->type_structure.disc_union->discrim_name
979                       == NAMETABLE_NIL_ID
980                    && (parent_node->fe_info->node_kind == fe_parameter_n_k
981                        || parent_node->fe_info->node_kind == fe_field_n_k))
982                {
983                    return_type->type_structure.disc_union->discrim_type
984                        = ASTP_switch_type;
985                    ASTP_CLR_ATTR(attributes,ASTP_SWITCH_TYPE);
986                }
987            }
988
989            /* Remove the type-attributes, as they are now on the type */
990            ASTP_CLR_ATTR(attributes,ASTP_UNALIGN|ASTP_SMALL|ASTP_STRING0|ASTP_V1_ENUM);
991        }
992    }
993
994    /*
995     * Do type attributes for parameter nodes
996     */
997    if (parent_node->fe_info->node_kind == fe_parameter_n_k)
998    {
999        /*
1000         * Process explicit [ptr], [ref], or [unique]
1001         */
1002         if (ptr_attrs != 0)
1003         {
1004            /* valid for anonymous pointer or array types only */
1005            if (((return_type->name == NAMETABLE_NIL_ID) &&
1006                (return_type->kind == AST_pointer_k)) ||
1007                (return_type->kind == AST_array_k))
1008            {
1009            }
1010            else
1011            {
1012                /*
1013                 * Output error, PTR or UNIQUE not valid on parameter
1014                 * being passed by value.
1015                 */
1016                log_error(location->lineno, NIDL_PRMBYREF,
1017                  KEYWORDS_lookup_text(AST_attribute_to_token(&ptr_attrs)),
1018		  NULL);
1019            }
1020
1021        }
1022        else
1023        {
1024            /*
1025             *  Process default.  [REF] is implied for a parameter
1026             *  that is an anonymous pointer or
1027             *  an array type without any attributes.
1028             */
1029            if (((return_type->name == NAMETABLE_NIL_ID) &&
1030                 (return_type->kind == AST_pointer_k)) ||
1031                 (return_type->kind == AST_array_k))
1032            {
1033                /*
1034                 *  Don't set [ref] on void* types because it is either a
1035                 *  context handle, or checker will issue an error on it.
1036					  *  Also, don't set [ref] on interface* types.
1037                 */
1038                if (!((return_type->kind == AST_pointer_k) &&
1039                    (return_type->type_structure.pointer->pointee_type->kind == AST_void_k) ))
1040					 {
1041						  if (return_type->type_structure.pointer->pointee_type->kind != AST_interface_k)
1042								AST_SET_REF(((AST_parameter_n_t*)parent_node));
1043					 }
1044            }
1045            else
1046            {
1047                /*
1048                 *  Not anonymous array or pointer, so propagate ptr, ref, &
1049                 *  unique attributes from type to parameter
1050                 *
1051                 */
1052                if (AST_PTR_SET(return_type))
1053                    AST_SET_PTR((AST_parameter_n_t *)parent_node);
1054                if (AST_REF_SET(return_type))
1055                    AST_SET_REF((AST_parameter_n_t *)parent_node);
1056                if (AST_UNIQUE_SET(return_type))
1057                    AST_SET_UNIQUE((AST_parameter_n_t *)parent_node);
1058            }
1059        } /* End pointer attributes processing */
1060
1061        /*
1062         * Propagate small, string, and string0 attributes to the parameter node
1063         */
1064         if (AST_SMALL_SET(return_type))
1065            AST_SET_SMALL((AST_parameter_n_t *)parent_node);
1066
1067         if (AST_STRING_SET(return_type))
1068            AST_SET_STRING((AST_parameter_n_t *)parent_node);
1069
1070         if (AST_STRING0_SET(return_type))
1071            AST_SET_STRING0((AST_parameter_n_t *)parent_node);
1072
1073    }  /* End if parameter node */
1074
1075    /*
1076     * Do the type attributes for field and arm nodes
1077     */
1078    if ((parent_node->fe_info->node_kind == fe_field_n_k) ||
1079        (parent_node->fe_info->node_kind == fe_arm_n_k))
1080    {
1081        if (ptr_attrs == 0)
1082        {
1083            /*
1084             * Propagate ptr, ref, or unique to the arm and field nodes.
1085             */
1086             if (AST_PTR_SET(return_type))
1087             {
1088                if (parent_node->fe_info->node_kind == fe_field_n_k)
1089                    AST_SET_PTR((AST_field_n_t *)parent_node);
1090                else
1091                    AST_SET_PTR((AST_arm_n_t *)parent_node);
1092             }
1093             if (AST_REF_SET(return_type))
1094             {
1095                if (parent_node->fe_info->node_kind == fe_field_n_k)
1096                    AST_SET_REF((AST_field_n_t *)parent_node);
1097                else
1098                    AST_SET_REF((AST_arm_n_t *)parent_node);
1099             }
1100             if (AST_UNIQUE_SET(return_type))
1101             {
1102                if (parent_node->fe_info->node_kind == fe_field_n_k)
1103                    AST_SET_UNIQUE((AST_field_n_t *)parent_node);
1104                else
1105                    AST_SET_UNIQUE((AST_arm_n_t *)parent_node);
1106             }
1107        }
1108        else /* Attributes specified, make sure pointer is anonymous */
1109        {
1110            /* Only valid for anonymous pointers */
1111            if (return_type->name != NAMETABLE_NIL_ID)
1112            {
1113                if (ASTP_TEST_ATTR(attributes,ASTP_REF))
1114                    log_error(location->lineno,NIDL_REFATTRPTR, NULL);
1115                if (ASTP_TEST_ATTR(attributes,ASTP_PTR))
1116                    log_error(location->lineno,NIDL_PTRATTRPTR, NULL);
1117                if (ASTP_TEST_ATTR(attributes,ASTP_UNIQUE))
1118                    log_error(location->lineno,NIDL_UNIQATTRPTR, NULL);
1119            }
1120        }  /* End pointer attributes processing */
1121
1122        /*
1123         * Propagate small, string and string0 to the arm and field nodes.
1124         */
1125         if (AST_SMALL_SET(return_type))
1126         {
1127            if (parent_node->fe_info->node_kind == fe_field_n_k)
1128                AST_SET_SMALL((AST_field_n_t *)parent_node);
1129            else
1130                AST_SET_SMALL((AST_arm_n_t *)parent_node);
1131         }
1132
1133         if (AST_STRING_SET(return_type))
1134         {
1135            if (parent_node->fe_info->node_kind == fe_field_n_k)
1136                AST_SET_STRING((AST_field_n_t *)parent_node);
1137            else
1138                AST_SET_STRING((AST_arm_n_t *)parent_node);
1139         }
1140
1141         if (AST_STRING0_SET(return_type))
1142         {
1143            if (parent_node->fe_info->node_kind == fe_field_n_k)
1144                AST_SET_STRING0((AST_field_n_t *)parent_node);
1145            else
1146                AST_SET_STRING0((AST_arm_n_t *)parent_node);
1147         }
1148
1149        /*
1150         * Propagate ignore to the field node.
1151         */
1152         if (AST_IGNORE_SET(return_type) &&
1153            (parent_node->fe_info->node_kind == fe_field_n_k))
1154         {
1155            AST_SET_IGNORE((AST_field_n_t *)parent_node);
1156         }
1157
1158    }   /* End if field/arm node */
1159
1160    return return_type;
1161}
1162
1163/*---------------------------------------------------------------------*/
1164
1165/*
1166 *
1167 *  A S T _ p r o p a g a t e  _ t y p e d e f
1168 *  ==========================================
1169 *
1170 *  Propagate a declarator type to the new type node defined
1171 *  with the TYPEDEF keyword.  The new type is allocated and
1172 *  initialized based upon the declarator and the specified
1173 *  type node.
1174 */
1175
1176static AST_type_n_t *AST_propagate_typedef
1177(
1178    parser_location_p location,
1179    AST_type_n_t *type_node_ptr,
1180    ASTP_declarator_n_t *declarator_ptr,
1181    ASTP_attributes_t   *attributes
1182)
1183{
1184    AST_type_n_t *return_type;          /* type node to return */
1185    AST_type_n_t *current_type;         /* type node to return */
1186    ASTP_declarator_op_n_t  *dop;       /* declarator operation ptr */
1187
1188    /* If there is no declarator operation, we need only copy the type */
1189    if (declarator_ptr->next_op == NULL)
1190    {
1191        /*
1192         * If the type is anonymous, not a base type, and
1193         * isn't identified by a struct/union tag, then we
1194         * can just use it to create the declaration.
1195         */
1196        if ((type_node_ptr->name == NAMETABLE_NIL_ID) &&
1197            !type_is_base(type_node_ptr) &&
1198            !AST_DEF_AS_TAG_SET(type_node_ptr))
1199        {
1200            return_type = type_node_ptr;
1201        }
1202        else
1203        {
1204            return_type = AST_type_node(location, type_node_ptr->kind);
1205            return_type->type_structure = type_node_ptr->type_structure;
1206            return_type->flags = type_node_ptr->flags;
1207            return_type->xmit_as_type = type_node_ptr->xmit_as_type;
1208            /*
1209             * The result type, if [transmit_as], should not inherit attributes
1210             * from the base type that only affect transmissible types, because
1211             * the result type is not transmissible, it is the presented type.
1212             */
1213            if (ASTP_TEST_ATTR(attributes, ASTP_TRANSMIT_AS))
1214            {
1215                AST_CLR_STRING(return_type);    AST_CLR_STRING0(return_type);
1216                AST_CLR_UNIQUE(return_type);    AST_CLR_REF(return_type);
1217                AST_CLR_IGNORE(return_type);    AST_CLR_SMALL(return_type);
1218                AST_CLR_CONTEXT_RD(return_type);AST_CLR_PTR(return_type);
1219            }
1220        }
1221
1222        /*
1223         * For simple declarators, if the base type is named, set
1224         * the defined_as pointer of the result type to the named type.
1225         */
1226        if ((type_node_ptr->name != NAMETABLE_NIL_ID) &&
1227            !AST_DEF_AS_TAG_SET(type_node_ptr))
1228                return_type->defined_as = type_node_ptr;
1229        /*
1230         * Do processing for possibly forward referenced tags.
1231         * 1) Propagate the incomplete, tag_ptr, and tag_name fields of the fe_info.
1232         * 2) Make sure that the DEF_AS_TAG bit is clear.
1233         * 3) If the original type was incomplete, make sure that this type
1234         *    is added to the tag reference list for later processing.
1235         */
1236        return_type->fe_info->tag_ptr = type_node_ptr->fe_info->tag_ptr;
1237        return_type->fe_info->tag_name = type_node_ptr->fe_info->tag_name;
1238        if (FE_TEST(type_node_ptr->fe_info->flags,FE_INCOMPLETE))
1239        {
1240            FE_SET(return_type->fe_info->flags,FE_INCOMPLETE);
1241            ASTP_save_tag_ref(type_node_ptr->fe_info->tag_name,
1242                        type_node_ptr->kind,return_type);
1243        }
1244    }
1245    else
1246    {
1247        return_type = type_node_ptr;
1248        /* Loop through declarator operations to generate the result type */
1249        for (dop = declarator_ptr->next_op; dop; dop = dop->next_op)
1250        {
1251            /* Specify the result type depending upon the declarator */
1252            current_type = return_type;
1253            switch (dop->op_kind)
1254            {
1255                case AST_array_k:               /* Array declarator */
1256                    return_type = AST_type_node(location, dop->op_kind);
1257                    return_type->type_structure.array =
1258                            AST_propagate_array_type(location,
1259												return_type, current_type, dop);
1260                    break;
1261
1262                case AST_pointer_k:             /* Pointer declarator */
1263                    {
1264                    int i;
1265
1266                    /* Create the pointer node for each STAR specified */
1267                    for (i = dop->op_info.pointer_count; i > 0; i--)
1268                    {
1269                        boolean is_void = (current_type->kind == AST_void_k);
1270                        return_type = AST_type_node(location, dop->op_kind);
1271                        return_type->type_structure.pointer =
1272                                AST_pointer_node(location, current_type);
1273                        current_type = return_type;
1274
1275                        /*
1276                         * Do not use [pointer_default] attribute for the following:
1277                         *    types with [transmit_as] attribute
1278                         *    types with [context_handle] attribute
1279                         *    void * types (they must be context handles)
1280                         *    toplevel pointer with [ptr], [ref], or [unique]
1281                         *    [local] interfaces
1282                         */
1283                        if (ASTP_TEST_ATTR(attributes,ASTP_TRANSMIT_AS)) continue;
1284                        if (ASTP_TEST_ATTR(attributes,ASTP_CONTEXT)) continue;
1285                        if (is_void) continue;
1286                        if ((dop->next_op == NULL) && (i == 1) &&
1287                           (ASTP_TEST_ATTR(attributes,ASTP_PTR|ASTP_REF|
1288                            ASTP_UNIQUE) != 0))
1289                                  continue;
1290								if (current_type->type_structure.pointer->pointee_type->kind == AST_interface_k)
1291									 continue;
1292                        /*
1293                         *  If none of the above exceptions apply, obtain the
1294                         *  pointer class from the default for the module, if
1295                         *  any.
1296                         */
1297                        switch (the_interface->pointer_default)
1298                        {
1299                          case 0:            /* No interface default */
1300                              if (!AST_LOCAL_SET(the_interface))
1301                              {
1302                                  char const *identifier;
1303                                  NAMETABLE_id_to_string (
1304                                      declarator_ptr->name, &identifier);
1305                                  log_warning(location->lineno,
1306					      NIDL_MISSPTRCLASS, identifier,
1307					      NULL);
1308                                  AST_SET_PTR(return_type); /* default: [ptr] */
1309                              }
1310                              break;
1311                          case ASTP_PTR:      AST_SET_PTR(return_type); break;
1312                          case ASTP_REF:      AST_SET_REF(return_type); break;
1313                          case ASTP_UNIQUE:AST_SET_UNIQUE(return_type); break;
1314                          default:  /* shouldn't get here */
1315                                error(NIDL_INTERNAL_ERROR, __FILE__, __LINE__);
1316                        }
1317                    }
1318                    break;
1319                    }
1320
1321                case AST_function_k:    /* Function declarator */
1322                    return_type = AST_type_node(location, dop->op_kind);
1323                    return_type->type_structure.function =
1324                            AST_function_node(location,
1325											current_type, declarator_ptr->name,
1326										   dop->op_info.routine_params);
1327                    break;
1328
1329                default:        /* Shouldn't get here */
1330                    error(NIDL_INTERNAL_ERROR, __FILE__, __LINE__);
1331                    break;
1332            }
1333
1334            /*
1335             * Do processing for possibly forward referenced tags.
1336             * 1) Propagate the incomplete and tag_ptr fields of the fe_info.
1337             * 2) Make sure that the REF_AS_TAG bit is clear.
1338             * 3) If the original type was incomplete, make sure that this type
1339             *    is added to the tag reference list for later processing.
1340             */
1341            return_type->fe_info->tag_ptr = type_node_ptr->fe_info->tag_ptr;
1342            return_type->fe_info->tag_name = type_node_ptr->fe_info->tag_name;
1343            if (FE_TEST(type_node_ptr->fe_info->flags,FE_INCOMPLETE))
1344            {
1345                FE_SET(return_type->fe_info->flags,FE_INCOMPLETE);
1346                ASTP_save_tag_ref(type_node_ptr->fe_info->tag_name,
1347                            type_node_ptr->kind,return_type);
1348            }
1349        }
1350    }
1351
1352    /* Set the type node name to the declarator's name */
1353    return_type->name = declarator_ptr->name;
1354
1355    /* Add name to nametable and bind to new type */
1356    ASTP_add_name_binding (location, return_type->name, return_type);
1357
1358    return return_type;
1359}
1360
1361/*---------------------------------------------------------------------*/
1362
1363/*
1364 *
1365 *  A S T _ p r o p a g a t e _ t y p e
1366 *  ===================================
1367 *
1368 *  Given a type and a declarator this function returns a
1369 *  type representing the combination of the specified type and
1370 *  declarator.  If the result is "simple" type, the original
1371 *  type_ptr is returned.  If the result is a "complex" type, a
1372 *  new type node is allocated and initialized.
1373 */
1374
1375AST_type_n_t *AST_propagate_type
1376(
1377    parser_location_p location,
1378    AST_type_n_t *type_node_ptr,
1379    ASTP_declarator_n_t *declarator_ptr,
1380    ASTP_attributes_t *attributes,
1381    ASTP_node_t *parent_node
1382)
1383{
1384    AST_type_n_t *return_type;          /* type node to return */
1385    AST_type_n_t *current_type;         /* type node to return */
1386    ASTP_declarator_op_n_t  *dop;       /* declarator operation ptr */
1387    enum
1388    {
1389        simple_type,
1390        complex_type
1391    } last_op_kind;             /* New type is either simple or complex type */
1392
1393    return_type = type_node_ptr;
1394    last_op_kind = simple_type; /* If no declarator_ops, then simple_type */
1395
1396    ASTP_validate_forward_ref_scope(location, type_node_ptr, parent_node);
1397
1398    /* Loop through declarator operations to generate the result type */
1399    for (dop = declarator_ptr->next_op; dop; dop = dop->next_op)
1400    {
1401        last_op_kind = complex_type;    /* Assume complex */
1402
1403        /* Specify the result type depending upon the declarator */
1404        current_type = return_type;
1405        switch (dop->op_kind)
1406        {
1407            case AST_array_k:           /* Array declarator */
1408                ASTP_validate_forward_ref(location, current_type);
1409                return_type = AST_type_node(location, dop->op_kind);
1410                return_type->type_structure.array =
1411                        AST_propagate_array_type(location,
1412										return_type, current_type, dop);
1413                break;
1414
1415            case AST_pointer_k:         /* Pointer declarator */
1416                {
1417                int i;
1418
1419                /* Create the pointer node for each STAR specified */
1420                for (i = dop->op_info.pointer_count; i > 0; i--)
1421                {
1422                    boolean is_void = (current_type->kind == AST_void_k);
1423
1424                    ASTP_verify_non_anonymous(location, current_type, declarator_ptr);
1425
1426                    return_type = AST_type_node(location, dop->op_kind);
1427                    return_type->type_structure.pointer =
1428                            AST_pointer_node(location, current_type);
1429                    current_type = return_type;
1430
1431                    /*
1432                     * Do not use [pointer_default] attribute for the following:
1433                     *    operation results (are always [ptr]),
1434                     *    constants
1435                     *    types with [transmit_as] attribute
1436                     *    types with [context_handle] attribute
1437                     *    void * types (they must be context handles)
1438                     *    toplevel pointer with with [ptr], [ref] or [unique]
1439                     *    toplevel anonymous param pointers
1440                     *    [local] interfaces
1441                     */
1442                    if (parent_node->fe_info->node_kind == fe_operation_n_k)
1443                              continue;
1444                    if (parent_node->fe_info->node_kind == fe_constant_n_k)
1445                              continue;
1446                    if (ASTP_TEST_ATTR(attributes,ASTP_TRANSMIT_AS)) continue;
1447                    if (ASTP_TEST_ATTR(attributes,ASTP_CONTEXT)) continue;
1448                    if (is_void) continue;
1449                    if ((dop->next_op == NULL) && (i == 1) && (ASTP_TEST_ATTR(
1450                        attributes,ASTP_PTR|ASTP_REF|ASTP_UNIQUE) != 0))
1451                              continue;
1452                    if ((dop->next_op == NULL) && (i == 1) &&
1453                        (parent_node->fe_info->node_kind == fe_parameter_n_k))
1454                              continue;
1455						  if (current_type->type_structure.pointer->pointee_type->kind == AST_interface_k)
1456								continue;
1457
1458                    /*
1459                     *  If we passed all of the exceptions, obtain the pointer
1460                     *  class from the default, and add to pointer.
1461                     */
1462                    switch (the_interface->pointer_default)
1463                    {
1464                    case 0:             /* No interface default */
1465                          if (!AST_LOCAL_SET(the_interface))
1466                          {
1467                              char const *identifier;
1468                              NAMETABLE_id_to_string (
1469                                  declarator_ptr->name, &identifier);
1470                              log_warning(location->lineno, NIDL_MISSPTRCLASS,
1471					  identifier, NULL);
1472                              AST_SET_PTR(return_type); /* default: [ptr] */
1473                          }
1474                          break;
1475                    case ASTP_PTR:      AST_SET_PTR(return_type); break;
1476                    case ASTP_REF:      AST_SET_REF(return_type); break;
1477                    case ASTP_UNIQUE:AST_SET_UNIQUE(return_type); break;
1478                    default:            /* shouldn't get here */
1479                            error(NIDL_INTERNAL_ERROR, __FILE__, __LINE__);
1480                    }
1481                }
1482                break;
1483                }
1484
1485            case AST_function_k:    /* Function declarator */
1486                ASTP_validate_forward_ref(location, current_type);
1487                return_type = AST_type_node(location, dop->op_kind);
1488                return_type->type_structure.function =
1489                        AST_function_node(location,
1490										current_type, declarator_ptr->name,
1491										dop->op_info.routine_params);
1492                break;
1493
1494            default:                /* Shouldn't get here */
1495                error(NIDL_INTERNAL_ERROR, __FILE__, __LINE__);
1496                break;
1497        }
1498    }
1499
1500    /*
1501     * Set the special (REF, PTR, UNIQUE) field/parameter/arm attributes
1502     * to the type node, and propagate the appropriate type attributes
1503     * back to the field/parameter/arm node.
1504     */
1505    return_type =
1506        AST_propagate_type_attrs(location, return_type, attributes,
1507                                 (boolean)(last_op_kind == simple_type),
1508                                 (ASTP_node_t *)parent_node);
1509
1510    return return_type;
1511}
1512
1513/*---------------------------------------------------------------------*/
1514
1515/*
1516 * A S T P _ s a v e _ f i e l d _ r e f _ c o n t e x t
1517 * =====================================================
1518 *
1519 * Saves the necessary information in a field reference
1520 * context block such that it can be processed at a
1521 * later time.
1522 *
1523 * Inputs:
1524 *  name                Nametable identifier specifying the reference name.
1525 *  field_ref_addr      The field reference address where the pointer to the
1526 *                      referenced parameter node goes when it is later defined.
1527 * Outputs:
1528 *  None.
1529 *
1530 * Function value:
1531 *  None.
1532 *
1533 */
1534static void ASTP_save_field_ref_context
1535(
1536    NAMETABLE_id_t name,
1537    AST_field_ref_n_t *field_ref_addr,
1538    fe_info_t *fe_info
1539)
1540{
1541    ASTP_field_ref_ctx_t *field_ref_ctx_ptr;
1542
1543    field_ref_ctx_ptr = NEW (ASTP_field_ref_ctx_t);
1544    field_ref_ctx_ptr->fe_info = fe_info;
1545
1546    /* Save context and link to context list */
1547    field_ref_ctx_ptr->name = name;
1548    field_ref_ctx_ptr->field_ref_ptr = field_ref_addr;
1549
1550    ASTP_field_ref_ctx_list = (ASTP_field_ref_ctx_t *)
1551                    AST_concat_element((ASTP_node_t *)ASTP_field_ref_ctx_list,
1552                                        (ASTP_node_t *)field_ref_ctx_ptr);
1553
1554    return;
1555}
1556
1557/*--------------------------------------------------------------------*/
1558
1559/*
1560 *  A S T _ s e t _ a r r a y _ r e p _ t y p e
1561 *  ============================================
1562 *
1563 *  This routine should be called with pointer that has the [string] attribute.
1564 *  It sets the array_rep_type of the type passed if it is pointer and it
1565 *  doesn't yet have an array rep.
1566 */
1567
1568void ASTP_set_array_rep_type
1569(
1570    parser_location_p   location,
1571    AST_type_n_t        *type_node_ptr,
1572    AST_type_n_t        *array_base_type,
1573    boolean             is_varying
1574)
1575{
1576    char *identifier ATTRIBUTE_UNUSED;
1577    AST_type_p_n_t *tp_node ATTRIBUTE_UNUSED;    /* type pointer node for interface's
1578                                   linked list of transmit_as types */
1579
1580    /* If the type is pointer, and no array_rep_type then create one */
1581    if (type_node_ptr->kind == AST_pointer_k)
1582    {
1583        if (type_node_ptr->type_structure.pointer->pointee_type->array_rep_type == NULL)
1584        {
1585            /*
1586             * No array node, so special processing, for pointers treated as
1587             * arrays.  We now fill-in the array_rep_type field of the pointer node
1588             * to contain a conformant array node representing the pointer as if it
1589             * had been declared using array syntax.
1590             */
1591            AST_type_n_t    *array_rep_of_pointer;
1592            AST_array_n_t   *array_node;
1593
1594            array_node = AST_array_node(location, array_base_type);
1595            array_node->index_count = 1;
1596            array_node->index_vec = AST_array_index_node(location, 1);
1597            array_node->index_vec->lower_bound = zero_constant_p;
1598            AST_SET_FIXED_LOWER(array_node->index_vec);
1599
1600            array_rep_of_pointer = AST_type_node(location, AST_array_k);
1601            array_rep_of_pointer->type_structure.array = array_node;
1602            AST_SET_CONFORMANT(array_rep_of_pointer);
1603            type_node_ptr->type_structure.pointer->pointee_type->array_rep_type = array_rep_of_pointer;
1604
1605            /*
1606             * Do the same processing on the original of a DEF_AS_TAG node.
1607             */
1608            if (AST_DEF_AS_TAG_SET(type_node_ptr->type_structure.pointer->pointee_type) &&
1609                (type_node_ptr->type_structure.pointer->pointee_type->fe_info->original != NULL) &&
1610                (type_node_ptr->type_structure.pointer->pointee_type->fe_info->original->array_rep_type == NULL))
1611            {
1612                ASTP_set_array_rep_type(location, type_node_ptr,
1613                    type_node_ptr->type_structure.pointer->pointee_type->fe_info->original,
1614                    is_varying);
1615            }
1616        }
1617
1618        /*
1619         * Set the varying flag on the type, if referenced as varying inorder
1620         * to indicate that the pointed at routine must be generated to
1621         * support varying instances.
1622         */
1623        if (is_varying)
1624        {
1625            AST_SET_VARYING(type_node_ptr->type_structure.pointer->pointee_type->array_rep_type);
1626
1627            /*
1628             * Do the same processing on the original of a DEF_AS_TAG node.
1629             */
1630            if (AST_DEF_AS_TAG_SET(type_node_ptr->type_structure.pointer->pointee_type) &&
1631               (type_node_ptr->type_structure.pointer->pointee_type->fe_info->original != NULL) &&
1632               (type_node_ptr->type_structure.pointer->pointee_type->fe_info->original->array_rep_type != NULL))
1633            {
1634                AST_SET_VARYING(type_node_ptr->type_structure.pointer->pointee_type->fe_info->original->array_rep_type);
1635            }
1636        }
1637    }
1638}
1639
1640/*--------------------------------------------------------------------*/
1641
1642/*
1643 *  A S T _ l o o k u p _ f i e l d _ a t t r
1644 *
1645 *  Returns TRUE if the specified field attribute appears in the specified
1646 *  attribute list.
1647 */
1648
1649boolean AST_lookup_field_attr
1650(
1651    ASTP_attributes_t   *attributes,    /* [in] Attributes - bounds field is */
1652                                        /*      linked list of field attrs   */
1653    ASTP_attr_k_t       field_attr      /* [in] Field attribute to look up */
1654)
1655{
1656    ASTP_type_attr_n_t  *bound_p;
1657
1658    for (bound_p = attributes->bounds; bound_p != NULL; bound_p = bound_p->next)
1659    {
1660        if (bound_p->kind == field_attr)
1661            return TRUE;
1662    }
1663
1664    return FALSE;
1665}
1666
1667/*--------------------------------------------------------------------*/
1668
1669/*
1670 *  A S T _ s e t _ f i e l d _ a t t r s
1671 *  =====================================
1672 *
1673 *  Set the field attributes of a parameter or structure.  In addition, if type
1674 *  is a pointer used as an array, the array_rep_type field of the pointer node
1675 *  is filled in with a type node used to represent the array implicitly created
1676 *  by using a pointer in this manner.
1677 *
1678 * Inputs:
1679 *  attributes   attr_flags = boolean attributes
1680 *               array_bounds = a pointer to a linked list describing the field
1681 *                   attributes that were specified.
1682 *
1683 *  parent_node  Pointer to the parent node containing the
1684 *               field attribute pointer.  This is either
1685 *               a pointer to a parameter node or field node.
1686 *               For parameters, this is used to track down
1687 *               the array node to get the array dimension.
1688 *               Used to also access the fe_info to see determine
1689 *               node it is, so we know whether we dealing with
1690 *               a field or parameter attributes.
1691 *
1692 *  type_node   Pointer to the type node representing the
1693 *              field or parameter type.
1694 *
1695 * Outputs:
1696 *  None.
1697 *
1698 * Function Value:
1699 *  Pointer to the field attribute node created.
1700 *
1701 */
1702
1703AST_field_attr_n_t *AST_set_field_attrs
1704(
1705    parser_location_p   location,
1706    ASTP_attributes_t  *attributes,
1707    ASTP_node_t		  *parent_node,
1708    AST_type_n_t       *type_node
1709)
1710{
1711    AST_field_attr_n_t
1712            *field_attr_node;   /* Pointer to field attribute node */
1713    AST_field_ref_n_t
1714            *field_ref_vector = NULL;  /* Pointer to the field_ref vector */
1715    ASTP_type_attr_n_t
1716            *attr_ptr,          /* Pointer to an element of array_bounds */
1717            *next_attr_ptr;     /* For loop - next attribute to process */
1718    ASTP_node_t
1719            *referent_node;     /* Pointer to node describing the reference
1720                                     specified as the array bound */
1721    AST_type_n_t
1722            *clone_type ATTRIBUTE_UNUSED,        /* For setting conformant flag for pointer types */
1723            *tp;                /* For loop to get to index_count */
1724    unsigned short
1725            dimension = 0,          /* number of dimensions for the array */
1726            index_count;        /* Used to catch mismatch in number of
1727                                    references specified and dimension */
1728    boolean pointer_as_array = FALSE,
1729            noforward_ref = TRUE;   /* Forward refs. allowed only for parameters */
1730    ASTP_attr_k_t
1731            current_attr_kind;  /* Current attribute being worked on */
1732    boolean array_attr_valid = TRUE;    /* Array attrs valid on this type */
1733    boolean neu_attr_valid = FALSE;     /* Nonencap union attrs valid on type */
1734
1735    /*
1736     *  If no bounds information, and not arrayified via [string], done
1737     */
1738    if ((attributes->bounds == NULL) && !ASTP_TEST_ATTR(attributes,(ASTP_STRING)))
1739       return (AST_field_attr_n_t *)NULL;
1740
1741  /*
1742   * Assume that array attrs and switch attr are to be mutually exclusive
1743   * (because arrays of non-encapsulated unions are not yet allowed), so if
1744   * the type node is a pointer and the pointee type is a union with no
1745   * discriminator name, we can usually assume this is a reference to a non-
1746   * encapsulated union type, and only the switch attr is to be valid.
1747   * However if the union type is incomplete (thus the union node address is
1748   * not yet initialized), it follows that the pointer is a self-referential
1749   * pointer to a union type.  This could be an arrayified encapsulated union
1750   * self-reference or a simple pointer to a non-encapsulated union self-
1751   * reference.  Look at the attributes specified, and if switch_is is present,
1752   * assume the latter, otherwise, assume the former.  This code will need work
1753   * if/when we support arrays of non-encapsulated unions.
1754   */
1755  tp = ASTP_chase_ptr_to_kind(type_node, AST_disc_union_k);
1756  if (tp != NULL
1757      && ( (tp->type_structure.disc_union != NULL
1758            && tp->type_structure.disc_union->discrim_name == NAMETABLE_NIL_ID)
1759        || (FE_TEST(tp->fe_info->flags, FE_INCOMPLETE)
1760            && AST_lookup_field_attr(attributes, switch_is_k)) ))
1761  {
1762    dimension = 1;
1763    array_attr_valid = FALSE;
1764    neu_attr_valid = TRUE;
1765  }
1766  else
1767  {
1768    /*
1769     * Determine dimension of the array for
1770     * allocating field_reference vector.
1771     */
1772    tp = ASTP_chase_ptr_to_kind(type_node, AST_array_k);
1773
1774    /*
1775     *  If there is no array node, then verify that this type may be arrayified
1776     *  via attributes.  If not, issue an error.
1777     */
1778    if (tp == NULL)
1779    {
1780        if (((parent_node->fe_info->node_kind == fe_field_n_k) &&
1781             (type_node->kind != AST_pointer_k)) ||
1782            ((parent_node->fe_info->node_kind == fe_parameter_n_k) &&
1783             ((type_node->kind != AST_pointer_k)||
1784              (type_node->name != NAMETABLE_NIL_ID))))
1785        {
1786            /*
1787             *  Output an error (except when only [string] attribute is present
1788             *  because this is caught by checker) and return if we don't find
1789             *  an array node or anonymous pointer hanging off of this type.
1790             */
1791            if (attributes->bounds != NULL)
1792            {
1793                if (attributes->bounds->kind == range_k)
1794                {
1795                  AST_exp_n_t *exp;
1796
1797                  field_attr_node = AST_field_attr_node(location);
1798                  field_attr_node->range = NEW(AST_tuple_n_t);
1799
1800                  exp = attributes->bounds->b.expr;
1801                  field_attr_node->range->value[0] =
1802							ASTP_expr_integer_value(location, exp->exp.expression.oper1);
1803                  field_attr_node->range->value[1] =
1804							ASTP_expr_integer_value(location, exp->exp.expression.oper2);
1805
1806                  if (field_attr_node->range->value[0] > field_attr_node->range->value[1])
1807                      log_error(location->lineno, NIDL_INVALIDRANGE, NULL);
1808
1809                  return field_attr_node;
1810                }
1811                /* Base the error on the first invalid "bounds" attribute. */
1812                else if (attributes->bounds->kind == switch_is_k)
1813                  log_error(location->lineno, NIDL_SWATTRNEU, NULL);
1814                else
1815                  log_error(location->lineno, NIDL_SIZEARRTYPE, NULL);
1816				}
1817            return (AST_field_attr_n_t *)NULL;
1818        }
1819    }
1820
1821    /*
1822     * We now know we either have an array or a top level pointer used an
1823     * array.  If we found an array node, we can directly access it.
1824     */
1825    if (tp != NULL)
1826    {
1827        dimension = tp->type_structure.array->index_count;
1828    }
1829
1830    /* If create the array_rep_type for this pointee */
1831    else if (type_node->kind == AST_pointer_k)
1832	 {
1833		  tp = type_node;
1834		  while(tp->type_structure.pointer->pointee_type->kind == AST_pointer_k && tp->kind != AST_interface_k)
1835				tp = tp->type_structure.pointer->pointee_type;
1836
1837		  dimension = 1;
1838		  pointer_as_array = TRUE;
1839		  ASTP_set_array_rep_type(location, type_node,
1840					 type_node->type_structure.pointer->pointee_type,
1841					 FALSE);
1842	 }
1843
1844    /*
1845     *  If only arrayified via [string] then all we needed to do was fill in
1846     *  the array_rep_type of the pointer which we have done, so return
1847     */
1848    if (attributes->bounds == NULL)
1849    {
1850        ASTP_set_array_rep_type(location, type_node,
1851            type_node->type_structure.pointer->pointee_type,
1852            TRUE);
1853        return (AST_field_attr_n_t *)NULL;
1854    }
1855  }
1856
1857    /* Allocate and initialize field attribute node */
1858    field_attr_node = AST_field_attr_node(location);
1859
1860    /*
1861     * A field attribute node points to a vector of
1862     * field reference nodes, one for each dimension,
1863     * and tells whether the node contains a valid
1864     * reference.  If valid, it points to the field or
1865     * parameter node containing the attribute reference.
1866     *
1867     * Note, parameter references can be forwarded.  (This
1868     * is not allowed for field references).
1869     * If the parameter is referenced before the formal parameter
1870     * definition, we save the context containing a the address
1871     * to place the reference pointer, and patch it up later on
1872     * when finishing up the operation.
1873     */
1874
1875    /*
1876     * Loop through the array bound linked list creating the
1877     * field reference vector for each field attribute present.
1878     * An inner loop processes the field references for each
1879     * dimension of the same array bound type.
1880     */
1881
1882    for (attr_ptr=attributes->bounds;
1883         attr_ptr != NULL;
1884         attr_ptr= attr_ptr->next)
1885    {
1886        if (attr_ptr->kind != switch_is_k && !array_attr_valid)
1887        {
1888            log_error(location->lineno, NIDL_SIZEARRTYPE, NULL);
1889            return (AST_field_attr_n_t *)NULL;
1890        }
1891        if (attr_ptr->kind == switch_is_k && !neu_attr_valid)
1892        {
1893            log_error(location->lineno, NIDL_SWATTRNEU, NULL);
1894            return (AST_field_attr_n_t *)NULL;
1895        }
1896        /*
1897         * Get (create if not yet specified) the field reference vector
1898         * for the attribute specified.
1899         */
1900        switch (attr_ptr->kind)
1901        {
1902				case iid_is_k:
1903					 if (field_attr_node->iid_is == NULL)
1904					 {
1905						  field_attr_node->iid_is =
1906							  AST_field_ref_node(location, dimension);
1907					 }
1908					 field_ref_vector = field_attr_node->iid_is;
1909					 break;
1910            case first_is_k:
1911                if (field_attr_node->first_is_vec == NULL)
1912                {
1913                    field_attr_node->first_is_vec =
1914							  AST_field_ref_node(location, dimension);
1915                }
1916                field_ref_vector = field_attr_node->first_is_vec;
1917                break;
1918
1919            case last_is_k:
1920                if (field_attr_node->last_is_vec == NULL)
1921                {
1922                    field_attr_node->last_is_vec =
1923							  AST_field_ref_node(location, dimension);
1924                }
1925                field_ref_vector = field_attr_node->last_is_vec;
1926                break;
1927
1928            case length_is_k:
1929                if (field_attr_node->length_is_vec == NULL)
1930                {
1931                    field_attr_node->length_is_vec =
1932							  AST_field_ref_node(location, dimension);
1933                }
1934                field_ref_vector = field_attr_node->length_is_vec;
1935                break;
1936
1937            case min_is_k:
1938                if (field_attr_node->min_is_vec == NULL)
1939                {
1940                    field_attr_node->min_is_vec =
1941							  AST_field_ref_node(location, dimension);
1942                }
1943                field_ref_vector = field_attr_node->min_is_vec;
1944                break;
1945
1946            case max_is_k:
1947                if (field_attr_node->max_is_vec == NULL)
1948                {
1949                    field_attr_node->max_is_vec =
1950							  AST_field_ref_node(location, dimension);
1951                }
1952                field_ref_vector = field_attr_node->max_is_vec;
1953                break;
1954
1955            case size_is_k:
1956                if (field_attr_node->size_is_vec == NULL)
1957                {
1958                    field_attr_node->size_is_vec =
1959							  AST_field_ref_node(location, dimension);
1960                }
1961                field_ref_vector = field_attr_node->size_is_vec;
1962                break;
1963            case switch_is_k:
1964                if (field_attr_node->switch_is == NULL)
1965                {
1966                    field_attr_node->switch_is =
1967							  AST_field_ref_node(location, 1);
1968                }
1969                field_ref_vector = field_attr_node->switch_is;
1970                break;
1971
1972            default:
1973                break;
1974        }
1975
1976        /* Set varying flag if last_is/length_is/first_is */
1977        if ((attr_ptr->kind == last_is_k)   ||
1978            (attr_ptr->kind == length_is_k) ||
1979            (attr_ptr->kind == first_is_k))
1980            {
1981                if (parent_node->fe_info->node_kind == fe_parameter_n_k)
1982                {
1983                    AST_SET_VARYING((AST_parameter_n_t*)parent_node);
1984                }
1985                else
1986                {
1987                    AST_SET_VARYING((AST_field_n_t*)parent_node);
1988                }
1989
1990                if (pointer_as_array)
1991                {
1992                    ASTP_set_array_rep_type(location, type_node,
1993                        type_node->type_structure.pointer->pointee_type,
1994                        TRUE);
1995                }
1996            }
1997
1998        /* Process all references specified for this attribute */
1999        current_attr_kind = attr_ptr->kind;
2000        next_attr_ptr = attr_ptr;
2001        index_count = 0;
2002        do
2003        {
2004            assert(field_ref_vector != NULL);
2005
2006            if (index_count >= dimension)
2007            {
2008                log_error(location->lineno, NIDL_SIZEMISMATCH, NULL);
2009                break;
2010            }
2011
2012            /* Get next attribute reference */
2013            attr_ptr = next_attr_ptr;
2014
2015            /* Proceed if reference name was specified */
2016            if (attr_ptr->is_expr || attr_ptr->b.simple.name != NAMETABLE_NIL_ID)
2017			{
2018				AST_exp_n_t * exp = NULL;
2019
2020				/*
2021				 * Set the pointer count.
2022				 * (This will need to be a bit more
2023				 * sophisicated IF/WHEN IDL supports full
2024				 * declarators for array bound references.)
2025				 */
2026				if (attr_ptr->is_expr)
2027				{
2028					exp = attr_ptr->b.expr;
2029					/*
2030					 * NB: extended simple expressions to handle multiple and
2031					 * division by 4 and 8 to handle LOGON_HOURS. This should
2032					 * be fixed properly as part of complex expression support.
2033					 *
2034					 * 03-04-10 lukeh
2035					 */
2036					if (ASTP_expr_is_simple(location, exp))
2037               {
2038						/* chase the dereferences */
2039						while(exp->exp_type == AST_EXP_UNARY_STAR)
2040                  {
2041							field_ref_vector->fe_info->pointer_count++;
2042							exp = attr_ptr->b.expr = exp->exp.expression.oper1;
2043						}
2044						switch(exp->exp_type)
2045                  {
2046							case AST_EXP_CONSTANT:
2047								break;
2048							case AST_EXP_BINARY_SLASH:
2049								switch (ASTP_expr_integer_value(location, exp->exp.expression.oper2))
2050                        {
2051									case 8: field_ref_vector->xtra_opcode = IR_EXP_FC_DIV_8; break;
2052									case 4: field_ref_vector->xtra_opcode = IR_EXP_FC_DIV_4; break;
2053									case 2: field_ref_vector->xtra_opcode = IR_EXP_FC_DIV_2; break;
2054									default: log_error(location->lineno, NIDL_ONLYSIMPLEEXP, NULL); return NULL;
2055								}
2056								exp = exp->exp.expression.oper1;
2057								break;
2058							case AST_EXP_BINARY_STAR:
2059								switch (ASTP_expr_integer_value(location, exp->exp.expression.oper2))
2060                        {
2061									case 8: field_ref_vector->xtra_opcode = IR_EXP_FC_MUL_8; break;
2062									case 4: field_ref_vector->xtra_opcode = IR_EXP_FC_MUL_4; break;
2063									case 2: field_ref_vector->xtra_opcode = IR_EXP_FC_MUL_2; break;
2064									default: log_error(location->lineno, NIDL_ONLYSIMPLEEXP, NULL); return NULL;
2065								}
2066								exp = exp->exp.expression.oper1;
2067								break;
2068							case AST_EXP_BINARY_PLUS:
2069								field_ref_vector->xtra_opcode = IR_EXP_FC_ADD_1;
2070								exp = exp->exp.expression.oper1;
2071								break;
2072							case AST_EXP_BINARY_MINUS:
2073								field_ref_vector->xtra_opcode = IR_EXP_FC_SUB_1;
2074								exp = exp->exp.expression.oper1;
2075								break;
2076							case AST_EXP_BINARY_AND:
2077								switch(ASTP_expr_integer_value(location, exp->exp.expression.oper1->exp.expression.oper2))
2078								{
2079									case 1:
2080										field_ref_vector->xtra_opcode = IR_EXP_FC_ALIGN_2;
2081										break;
2082									case 3:
2083										field_ref_vector->xtra_opcode = IR_EXP_FC_ALIGN_4;
2084										break;
2085									case 7:
2086										field_ref_vector->xtra_opcode = IR_EXP_FC_ALIGN_4;
2087										break;
2088								}
2089								exp = exp->exp.expression.oper1->exp.expression.oper1;
2090								while(exp->exp_type == AST_EXP_UNARY_STAR)
2091                        {
2092									field_ref_vector->fe_info->pointer_count++;
2093									exp = attr_ptr->b.expr = exp->exp.expression.oper1;
2094								}
2095								break;
2096						}
2097						if (exp->exp_type != AST_EXP_CONSTANT)
2098						{
2099							log_error(location->lineno, NIDL_ONLYSIMPLEEXP, NULL);
2100							return NULL;
2101						}
2102                  else if (exp->exp.constant.type != AST_nil_const_k)
2103						{
2104							field_ref_vector->constant = true;
2105							field_ref_vector->ref.integer =
2106								ASTP_expr_integer_value(location, exp);
2107						}
2108                  else
2109                  {
2110							field_ref_vector->constant = false;
2111                  }
2112						attr_ptr->is_expr = false;
2113						/* apply the EXP_CONSTANT details to the stuff below */
2114						attr_ptr->b.simple.name = exp->exp.constant.name;
2115					}
2116					else
2117					{
2118						log_error(location->lineno, NIDL_ONLYSIMPLEEXP, NULL) ;
2119						return NULL;
2120					}
2121				}
2122				else if (attr_ptr->b.simple.pointer)
2123				{
2124					field_ref_vector->fe_info->pointer_count = 1;
2125				}
2126
2127				/*
2128				 * Lookup binding, output error if invalid type,
2129				 * but allow forward references for parameters and fields.
2130				 */
2131				if ((parent_node->fe_info->node_kind == fe_parameter_n_k) ||
2132						(parent_node->fe_info->node_kind == fe_field_n_k))
2133				{
2134					noforward_ref = FALSE;
2135				}
2136
2137				referent_node = (ASTP_node_t *)
2138						ASTP_lookup_binding(location, attr_ptr->b.simple.name,
2139								parent_node->fe_info->node_kind,
2140								noforward_ref);
2141				/*
2142				 * Set valid bit and fill in reference pointer
2143				 * if lookup succeeded.
2144				 */
2145				if (referent_node != NULL)
2146				{
2147					field_ref_vector->valid = TRUE;
2148
2149					if (parent_node->fe_info->node_kind == fe_parameter_n_k)
2150					{
2151						field_ref_vector->ref.p_ref =
2152							(AST_parameter_n_t *)referent_node;
2153					}
2154					else
2155					{
2156						field_ref_vector->ref.f_ref =
2157							(AST_field_n_t *)referent_node;
2158					}
2159				}
2160				else if (field_ref_vector->constant == true)
2161				{
2162					field_ref_vector->valid = true;
2163				}
2164				else
2165				{
2166					/*
2167					 * If name binding is unknown, save context if
2168					 * we're dealing with parameters or fields, otherwise
2169					 * output an error.
2170					 */
2171					if ((parent_node->fe_info->node_kind == fe_parameter_n_k) ||
2172							(parent_node->fe_info->node_kind == fe_field_n_k))
2173					{
2174						/* Name not bound yet, save context for later */
2175						ASTP_save_field_ref_context(
2176								attr_ptr->b.simple.name,
2177								field_ref_vector,
2178								parent_node->fe_info);
2179					}
2180					else
2181					{
2182						char const *identifier;
2183						NAMETABLE_id_to_string (attr_ptr->b.simple.name,
2184								&identifier);
2185						log_error(location->lineno, NIDL_NAMENOTFND, identifier, NULL) ;
2186					}
2187				}
2188			}
2189
2190            /*
2191             * Point to next array bound element
2192             * and reference vector element.
2193             */
2194            next_attr_ptr = next_attr_ptr->next;
2195            field_ref_vector++;
2196            index_count++;
2197        }
2198        while ( (attr_ptr->next != NULL) &&
2199                (attr_ptr->next->kind == current_attr_kind)) ;
2200
2201    } /* end for processing all attributes in attributes->bounds */
2202
2203    return field_attr_node;
2204
2205}
2206
2207/*--------------------------------------------------------------------*/
2208
2209/*
2210 *  A S T _ s e t _ t y p e _ a t t r s
2211 *  ===================================
2212 *
2213 *  Merge the boolean and non-boolean attributes
2214 *  to the type node.
2215 */
2216
2217AST_type_n_t *AST_set_type_attrs
2218(
2219	 parser_location_p       location,
2220    AST_type_n_t        *type_node_ptr,
2221    ASTP_attributes_t   *attributes
2222)
2223{
2224    AST_type_p_n_t *tp_node;    /* type pointer node for interface's
2225                                   linked list of transmit_as types */
2226
2227    /* Propagate the boolean attributes to the type node */
2228    AST_set_flags(location, &type_node_ptr->flags,(ASTP_node_t *)type_node_ptr, attributes);
2229
2230    /* if this is a [v1_enum] enum make it be a long at NDR level */
2231    if (AST_V1_ENUM_SET(type_node_ptr))
2232    {
2233        type_node_ptr->ndr_size = 4;
2234        type_node_ptr->alignment_size = type_node_ptr->ndr_size;
2235    }
2236
2237    /* If [string] on a pointer type and no array_rep_type then create one */
2238    if (ASTP_TEST_ATTR(attributes,(ASTP_STRING)) &&
2239       (type_node_ptr->kind == AST_pointer_k))
2240    {
2241        ASTP_set_array_rep_type(location, type_node_ptr,
2242            type_node_ptr->type_structure.pointer->pointee_type,
2243            TRUE);
2244    }
2245
2246    /* Check the transmit_as attribute */
2247    if (ASTP_TEST_ATTR(attributes,ASTP_TRANSMIT_AS))
2248    {
2249        type_node_ptr->xmit_as_type = ASTP_transmit_as_type;
2250        if (type_node_ptr->xmit_as_type == NULL)
2251            INTERNAL_ERROR("ASTP_transmit_as_type is NULL when attribute set");
2252    }
2253    /* Check the switch_type attribute */
2254    if (ASTP_TEST_ATTR(attributes,ASTP_SWITCH_TYPE))
2255    {
2256        if (type_node_ptr->kind != AST_disc_union_k)
2257            log_error(location->lineno, NIDL_SWTYPENEU, NULL);        /* non-union type */
2258        else if (type_node_ptr->type_structure.disc_union == NULL)
2259            ASTP_validate_forward_ref(location, type_node_ptr);   /* incomplete type */
2260        else if (type_node_ptr->type_structure.disc_union->discrim_name
2261                 != NAMETABLE_NIL_ID)                   /* encap union type */
2262            log_error(location->lineno, NIDL_SWTYPENEU, NULL);
2263        else
2264        {
2265            type_node_ptr->type_structure.disc_union->discrim_type
2266                = ASTP_switch_type;
2267            if (ASTP_switch_type == NULL)
2268                INTERNAL_ERROR("ASTP_switch_type is NULL when attribute set");
2269        }
2270    }
2271
2272    /* Check for pipe type and link onto pipe_types list */
2273    if (type_node_ptr->kind == AST_pipe_k)
2274    {
2275        /*
2276         * Create a new type pointer node and link the pipe type on to
2277         * pipe_types list to be later put on the interface node
2278         */
2279        tp_node = AST_type_ptr_node(location);
2280        tp_node->type = type_node_ptr;
2281
2282        the_interface->pipe_types = (AST_type_p_n_t *)
2283                        AST_concat_element((ASTP_node_t *)the_interface->pipe_types,
2284                                           (ASTP_node_t *)tp_node);
2285    }
2286
2287    return type_node_ptr;
2288}
2289
2290/*---------------------------------------------------------------------*/
2291
2292/*
2293 *  A S T P _ f r e e _ d e c l a r a t o r s
2294 *  ==========================================
2295 *
2296 *  Loop through the specified list of declarators and free
2297 *  them and any indices that are hanging off of the
2298 *  declarators.
2299 *
2300 */
2301
2302void ASTP_free_declarators
2303(
2304    ASTP_declarator_n_t *declarators_ptr
2305)
2306{
2307    ASTP_declarator_n_t
2308        *dp,                        /*  For traversing through declarators */
2309        *next_dp;
2310
2311    ASTP_declarator_op_n_t
2312        *dop,                       /*  For traversing through declarators */
2313        *next_dop;
2314
2315    ASTP_array_index_n_t
2316        *index_node,                /* For freeing array index nodes */
2317        *next_index;                /* "" */
2318
2319    /* Free temporary declarators list */
2320    for (dp = declarators_ptr, next_dp = declarators_ptr;
2321            next_dp != (ASTP_declarator_n_t *) NULL;
2322            dp= next_dp)
2323    {
2324        next_dp = dp->next;     /* Save next link before freeing */
2325
2326        /* Free declarator operations linked list */
2327        for (dop = dp->next_op, next_dop = dp->next_op;
2328             next_dop != NULL;
2329             dop = next_dop)
2330        {
2331            /* Free array indices linked list in this declarator op, if any */
2332            if (dop->op_kind == AST_array_k)
2333            {
2334                for (index_node = dop->op_info.indices, next_index = dop->op_info.indices;
2335                     next_index != NULL;
2336                     index_node = next_index)
2337                {
2338                    next_index = index_node->next;
2339                    FREE(index_node);
2340                }
2341            }
2342
2343            next_dop = dop->next_op;
2344            FREE(dop);
2345        }
2346
2347        FREE(dp);
2348    }
2349
2350    return;
2351}
2352
2353/*-----------------------------------------------------------------------*/
2354
2355/*
2356 *  A S T P _ f r e e _ s i m p l e _ l i s t
2357 *  =========================================
2358 *
2359 *  Loop through a list of simple elements, i.e.
2360 *  no allocated lists hanging off the list element.
2361 *
2362 */
2363
2364void ASTP_free_simple_list
2365(
2366    ASTP_node_t *list_ptr
2367)
2368{
2369    ASTP_node_t *lp,
2370                 *next_lp;
2371
2372    for (lp = list_ptr, next_lp = list_ptr;
2373            next_lp != (ASTP_node_t *) NULL;
2374            lp = next_lp)
2375    {
2376        next_lp = lp->next;
2377        FREE(lp);
2378    }
2379
2380    return;
2381}
2382
2383/*-----------------------------------------------------------------------*/
2384
2385/*
2386 * A S T P _ p a t c h _ f i e l d _ r e f e r e n c e
2387 * ===================================================
2388 *
2389 * Patches the field reference node parameter node address
2390 * which at the time the field attribute was parsed,
2391 * a binding of a parameter type was not yet defined.
2392 *
2393 * Inputs:
2394 *  None.
2395 *
2396 * Outputs:
2397 *  None.
2398 *
2399 * Function value:
2400 *  None.
2401 *
2402 */
2403void ASTP_patch_field_reference
2404(
2405	parser_location_p location
2406)
2407{
2408    ASTP_field_ref_ctx_t *field_ref_ctx;
2409    AST_parameter_n_t    *parameter_node_ptr;
2410    AST_field_n_t    *field_node_ptr;
2411
2412    for (field_ref_ctx = ASTP_field_ref_ctx_list;
2413         field_ref_ctx != NULL;
2414         field_ref_ctx = field_ref_ctx->next)
2415    {
2416        /* Processing for parameter references */
2417        if (field_ref_ctx->fe_info->node_kind == fe_parameter_n_k)
2418        {
2419            /* Lookup binding and output error if not found or invalid type */
2420            parameter_node_ptr = (AST_parameter_n_t *)
2421                                    ASTP_lookup_binding(location, field_ref_ctx->name,
2422                                                        fe_parameter_n_k, TRUE);
2423            if (parameter_node_ptr != NULL)
2424            {
2425                field_ref_ctx->field_ref_ptr->ref.p_ref = parameter_node_ptr;
2426                field_ref_ctx->field_ref_ptr->valid = TRUE;
2427            }
2428        }
2429
2430        /* Processing for field references */
2431        if (field_ref_ctx->fe_info->node_kind == fe_field_n_k)
2432        {
2433            /* Lookup binding and output error if not found or invalid type */
2434            field_node_ptr = (AST_field_n_t *)
2435                                    ASTP_lookup_binding(location, field_ref_ctx->name,
2436                                                        fe_field_n_k, TRUE);
2437            if (field_node_ptr != NULL)
2438            {
2439                field_ref_ctx->field_ref_ptr->ref.f_ref = field_node_ptr;
2440                field_ref_ctx->field_ref_ptr->valid = TRUE;
2441            }
2442        }
2443    }
2444
2445    ASTP_field_ref_ctx_list = NULL;     /* NULL listhead */
2446
2447    return;
2448}
2449
2450/*---------------------------------------------------------------------*/
2451
2452/*
2453 *  A S T P _ s e t _ f e _ i n f o
2454 *  ===============================
2455 *
2456 *  Allocate and initialize a fe_info node and link it
2457 *  into the fe_info field of the specified node.  The
2458 *  be_info field is set to NULL.
2459 *
2460 *  Inputs:
2461 *      node_ptr -- node to have the fe_info and be_info set
2462 *      fe_node_kind -- type of fe_node to create
2463 */
2464void ASTP_set_fe_info
2465(
2466    parser_location_p location,
2467    fe_info_t  **fe_info_ptr,
2468    fe_node_k_t  fe_node_kind
2469)
2470{
2471    fe_info_t *fe_info;
2472
2473    fe_info = *fe_info_ptr = BE_ctx_malloc(sizeof (fe_info_t));
2474
2475    fe_info->source_line = location->lineno;
2476    fe_info->file = location->fileid;
2477    fe_info->acf_source_line = 0;
2478    fe_info->acf_file = 0;
2479    fe_info->node_kind = fe_node_kind;
2480    fe_info->fe_type_id = fe_source_only;
2481    fe_info->tag_ptr = NULL;
2482    fe_info->tag_name = NAMETABLE_NIL_ID;
2483    fe_info->gen_index = 0;
2484    fe_info->pointer_count = 0;
2485    fe_info->flags = 0;
2486    fe_info->original = NULL;
2487}
2488
2489/*---------------------------------------------------------------------*/
2490
2491/*
2492 *  A S T P _ s a v e _ t a g _ r e f
2493 *  =================================
2494 *
2495 *  Allocate and initialize a tag reference node and link it
2496 *  into the ASTP_tag_ref_list to be processed at a later
2497 *  time.
2498 *
2499 *  Inputs:
2500 *      node_ptr -- node to have the fe_info and be_info set
2501 *      fe_node_kind -- type of fe_node to create
2502 */
2503
2504void ASTP_save_tag_ref
2505(
2506    NAMETABLE_id_t      identifier,
2507    AST_type_k_t        kind,
2508    AST_type_n_t        *type_node_ptr
2509)
2510{
2511    ASTP_tag_ref_n_t    *tag_ref_node_ptr;      /* Tag reference node */
2512
2513    /*
2514     * Make sure the type node specified could be a forward reference
2515     */
2516    if ((type_node_ptr->kind != AST_structure_k) &&
2517        (type_node_ptr->kind != AST_disc_union_k))  return;
2518
2519    /*
2520     * Then build a tag ref node and add to the list to be processed later to
2521     * fill in the structure information in the type node when it becomes
2522     * known.
2523     */
2524    tag_ref_node_ptr = NEW (ASTP_tag_ref_n_t);
2525    tag_ref_node_ptr->ref_kind = kind;
2526    tag_ref_node_ptr->name = identifier;
2527    tag_ref_node_ptr->type_node_ptr = type_node_ptr;
2528    ASTP_tag_ref_list = (ASTP_tag_ref_n_t *)
2529            AST_concat_element((ASTP_node_t *)ASTP_tag_ref_list,
2530                               (ASTP_node_t *)tag_ref_node_ptr);
2531
2532    /*
2533     * Mark the specified type node as incomplete
2534     */
2535    FE_SET(type_node_ptr->fe_info->flags,FE_INCOMPLETE);
2536}
2537
2538/*---------------------------------------------------------------------*/
2539
2540/*
2541 *  A S T P _ p r o c e s s _ c o n t e x t _ t y p e
2542 *  =================================================
2543 *
2544 *  This routine provides the processing needed for types that have
2545 *  context_handle attribute.  If not already marked with the
2546 *  [context_handle] it is added to the ASTP_context_handle_types_list
2547 *
2548 *  Inputs:
2549 *      type_node_ptr -- The newly found context_handle type.
2550 */
2551
2552static void ASTP_process_context_type
2553(
2554    AST_type_n_t *type_node_ptr
2555)
2556{
2557    AST_SET_CONTEXT_RD(type_node_ptr);
2558}
2559
2560/*---------------------------------------------------------------------*/
2561
2562/*
2563 *  A S T _ s e t _ f l a g s
2564 *  =======================================
2565 *
2566 *  This routine accepts a node and the vector of flag bits from
2567 *  the grammar.  It verifies the the attributes are valid in this
2568 *  context, issues errors for those that are not, and then sets
2569 *  the bits in the flags word specified.
2570 *
2571 *  Inputs:
2572 *      field_node_ptr -- node on which to set attributes
2573 *      flags -- address of flags structure
2574 */
2575
2576void AST_set_flags
2577(
2578	 parser_location_p			 location,
2579    AST_flags_t         *flags,
2580    ASTP_node_t         *node_ptr,
2581    ASTP_attributes_t   *attributes
2582)
2583{
2584#define COPY_IF_LARGER(a,b) {if ((b) > (a)) (a) = (b);}
2585    ASTP_type_attr_n_t  *bp;                /* pointer to loop through bounds */
2586    ASTP_attr_flag_t    current_attribute;
2587    ASTP_attr_flag_t    valid_attr_flags;
2588    long                message_number = 0;
2589    boolean             bounds_illegal = TRUE;
2590
2591    /*
2592     * Determine which flags are valid for this node type
2593     */
2594    switch (node_ptr->fe_info->node_kind)
2595    {
2596        case fe_field_n_k:
2597            valid_attr_flags = ASTP_FIELD_FLAGS;
2598            message_number = NIDL_ILLFIELDATTR;
2599            bounds_illegal = FALSE;
2600            break;
2601        case fe_arm_n_k:
2602            valid_attr_flags = ASTP_ARM_FLAGS;
2603            message_number = NIDL_ILLMEMATTR;
2604            break;
2605        case fe_type_n_k:
2606            valid_attr_flags = ASTP_TYPE_FLAGS;
2607            message_number = NIDL_ILLTYPEATTR;
2608            break;
2609        case fe_parameter_n_k:
2610            valid_attr_flags = ASTP_PARAMETER_FLAGS;
2611            message_number = NIDL_ILLPARAMATTR;
2612            bounds_illegal = FALSE;
2613            break;
2614        case fe_operation_n_k:
2615            valid_attr_flags = ASTP_OPERATION_FLAGS;
2616            message_number = NIDL_ILLOPATTR;
2617            break;
2618        case fe_interface_n_k:
2619            valid_attr_flags = 0;
2620            message_number = NIDL_ILLINTATTR;
2621            break;
2622        default:
2623            valid_attr_flags = 0;
2624            break;
2625    }
2626
2627    /*
2628     * Loop through all possible attributes and either set the
2629     * attribute on the target node, or issue a message that it
2630     * is not valid on this node type.
2631     */
2632    for (current_attribute = 1;         /* start with first bit */
2633          current_attribute != 0 && current_attribute <= (unsigned) ASTP_MAX_ATTRIBUTE; /* until and including last bit */
2634          current_attribute <<= 1)      /* Next higher bit */
2635    {
2636        /* Check if the attribute flag is set */
2637        if (ASTP_TEST_ATTR(attributes,current_attribute))
2638        {
2639            /* Yes, so make sure it is valid on this node type before setting */
2640            if ((current_attribute & ~valid_attr_flags) == 0)
2641            {
2642                switch (current_attribute)
2643                {
2644                 /* With BROADCAST, IDEMPOTENT is implicit */
2645                 case ASTP_BROADCAST:
2646                      *flags |= (AST_BROADCAST | AST_IDEMPOTENT); break;
2647
2648                 /* MAYBE implies IDEMPOTENT */
2649                 case ASTP_MAYBE:
2650                      *flags |= (AST_MAYBE | AST_IDEMPOTENT); break;
2651
2652                 case ASTP_IDEMPOTENT:
2653                      *flags |= AST_IDEMPOTENT; break;
2654
2655                 case ASTP_REFLECT_DELETIONS:
2656                      *flags |= AST_REFLECT_DELETIONS; break;
2657
2658					  case ASTP_LOCAL:
2659							 *flags |= AST_LOCAL; break;
2660
2661                 case ASTP_IN:
2662                      *flags |= AST_IN; break;
2663
2664                 case ASTP_IN_SHAPE:
2665                      *flags |= AST_IN_SHAPE; break;
2666
2667                 case ASTP_OUT:
2668                      *flags |= AST_OUT; break;
2669
2670                 case ASTP_OUT_SHAPE:
2671                      *flags |= AST_OUT_SHAPE; break;
2672
2673                 case ASTP_STRING:
2674                      *flags |= AST_STRING; break;
2675
2676                 case ASTP_STRING0:
2677                      *flags |= AST_STRING0; break;
2678
2679                 case ASTP_UNIQUE:
2680                      *flags |= AST_UNIQUE; break;
2681
2682                 case ASTP_REF:
2683                      *flags |= AST_REF; break;
2684
2685                 case ASTP_PTR:
2686                      *flags |= AST_PTR; break;
2687
2688                 case ASTP_V1_ENUM:
2689                      *flags |= AST_V1_ENUM; break;
2690
2691                 case ASTP_IGNORE:
2692                      *flags |= AST_IGNORE; break;
2693
2694                 case ASTP_SMALL:
2695                      *flags |= AST_SMALL; break;
2696
2697                 case ASTP_HANDLE:
2698                      *flags |= AST_HANDLE; break;
2699
2700                 case ASTP_UNALIGN:
2701                      *flags |= AST_UNALIGN; break;
2702
2703                 case ASTP_ALIGN_SMALL:
2704                 case ASTP_ALIGN_SHORT:
2705                 case ASTP_ALIGN_LONG:
2706                 case ASTP_ALIGN_HYPER:
2707                 {
2708                    log_error(location->lineno, NIDL_NYSALIGN, NULL);
2709#if 0
2710                    AST_type_n_t *type_node_ptr = (AST_type_n_t *)node_ptr;
2711
2712                    /* Set alignment requirement on type */
2713                    switch (current_attribute)
2714                    {
2715                    case ASTP_ALIGN_SMALL:
2716                        COPY_IF_LARGER(type_node_ptr->alignment_size, NDR_C_SMALL_INT_SIZE)
2717                        break;
2718                    case ASTP_ALIGN_SHORT:
2719                        COPY_IF_LARGER(type_node_ptr->alignment_size, NDR_C_SHORT_INT_SIZE)
2720                        break;
2721                    case ASTP_ALIGN_LONG:
2722                        COPY_IF_LARGER(type_node_ptr->alignment_size, NDR_C_LONG_INT_SIZE)
2723                        break;
2724                    case ASTP_ALIGN_HYPER:
2725                        COPY_IF_LARGER(type_node_ptr->alignment_size, NDR_C_HYPER_INT_SIZE)
2726                        break;
2727                    }
2728
2729                    /* Disallow align on anything by arrays of bytes */
2730                    if (!((node_ptr->fe_info->node_kind == fe_type_n_k) &&
2731                        (type_node_ptr->kind == AST_array_k) &&
2732                        (type_node_ptr->type_structure.array != NULL) &&
2733                        (type_node_ptr->type_structure.array->index_count == 1) &&
2734                        (type_node_ptr->type_structure.array->element_type->kind == AST_byte_k)))
2735                    {
2736                        log_error(location->lineno, NIDL_ALIGNBYTEARRAY, NULL);
2737                    }
2738#endif
2739                    break;
2740                 }
2741
2742                  /* process type node with [context_handle] attribute */
2743                  case ASTP_CONTEXT:
2744                  {
2745                    if (node_ptr->fe_info->node_kind == fe_type_n_k)
2746                            ASTP_process_context_type((AST_type_n_t *)node_ptr);
2747                    else
2748                            *flags |= AST_CONTEXT;
2749                    break;
2750                  }
2751
2752                  /* Transmit_as handled in AST_set_type_attrs */
2753                  case ASTP_TRANSMIT_AS:
2754                      break;
2755                  /* switch_type handled in AST_set_type_attrs */
2756                  case ASTP_SWITCH_TYPE:
2757                      break;
2758                  /* range handled in AST_set_type_attrs */
2759                  case ASTP_RANGE:
2760                      break;
2761
2762                  /* Attribute has not been handled, bug */
2763                  default:
2764                      error(NIDL_INTERNAL_ERROR, __FILE__, __LINE__);
2765                 }
2766            }
2767            else
2768            {
2769                /*
2770                 * It is not valid on this node type, so issue an error message
2771                 */
2772                log_error(location->lineno, message_number,
2773                    KEYWORDS_lookup_text(AST_attribute_to_token(&current_attribute)), NULL);
2774            }
2775        }
2776    }
2777
2778    /*
2779     * Issue errors on the bounds attributes if the are illegal here
2780     */
2781    if (bounds_illegal)
2782        for (bp = attributes->bounds; bp; bp = bp->next)
2783        {
2784            long    token = 0;
2785            switch (bp->kind)
2786            {
2787                case last_is_k:         token = LAST_IS_KW; break;
2788                case first_is_k:        token = FIRST_IS_KW; break;
2789                case max_is_k:          token = MAX_IS_KW; break;
2790                case length_is_k:       token = LENGTH_IS_KW; break;
2791                case size_is_k:         token = SIZE_IS_KW; break;
2792                case switch_is_k:       token = SWITCH_IS_KW; break;
2793					 case min_is_k:          token = MIN_IS_KW; break;
2794					 case iid_is_k:          token = IID_IS_KW; break;
2795					 case range_k:           token = RANGE_KW; break;
2796            }
2797            log_error(location->lineno, message_number, KEYWORDS_lookup_text(token), NULL) ;
2798        }
2799}
2800
2801/*---------------------------------------------------------------------*/
2802
2803/*
2804 *  A S T _ a t t r i b u t e _ t o _ t o k e n
2805 *  ===========================================
2806 *
2807 *  This routine accepts an attribute value and
2808 *  returns it's token number.
2809 *
2810 *  Inputs:
2811 *      attribute -- Attribute to return the text of
2812 *
2813 *  Returns:
2814 *      long -- token number for the specified attribute
2815 */
2816
2817long AST_attribute_to_token
2818(
2819    ASTP_attr_flag_t    *attribute
2820)
2821{
2822    switch (*attribute)
2823    {
2824        case ASTP_ALIGN_SMALL:  return ALIGN_KW;
2825        case ASTP_ALIGN_SHORT:  return ALIGN_KW;
2826        case ASTP_ALIGN_LONG:   return ALIGN_KW;
2827        case ASTP_ALIGN_HYPER:  return ALIGN_KW;
2828        case ASTP_BROADCAST:    return BROADCAST_KW;
2829        case ASTP_MAYBE:        return MAYBE_KW;
2830        case ASTP_IDEMPOTENT:   return IDEMPOTENT_KW;
2831        case ASTP_REFLECT_DELETIONS:   return REFLECT_DELETIONS_KW;
2832        case ASTP_IN:           return IN_KW;
2833        case ASTP_OUT:          return OUT_KW;
2834        case ASTP_STRING:       return STRING_KW;
2835        case ASTP_STRING0:      return V1_STRING_KW;
2836        case ASTP_IN_SHAPE:     return IN_KW;
2837        case ASTP_OUT_SHAPE:    return OUT_KW;
2838        case ASTP_UNIQUE:       return UNIQUE_KW;
2839        case ASTP_PTR:          return PTR_KW;
2840        case ASTP_REF:          return REF_KW;
2841        case ASTP_IGNORE:       return IGNORE_KW;
2842        case ASTP_SMALL:        return V1_ARRAY_KW;
2843        case ASTP_HANDLE:       return HANDLE_KW;
2844        case ASTP_CONTEXT:      return CONTEXT_HANDLE_KW;
2845        case ASTP_TRANSMIT_AS:  return TRANSMIT_AS_KW;
2846        case ASTP_UNALIGN:      return V1_STRUCT_KW;
2847        case ASTP_V1_ENUM:      return V1_ENUM_KW;
2848        case ASTP_CASE:         return CASE_KW;
2849        case ASTP_DEFAULT:      return DEFAULT_KW;
2850        case ASTP_SWITCH_TYPE:  return SWITCH_TYPE_KW;
2851        default:                return 0;
2852    }
2853}
2854
2855/*---------------------------------------------------------------------*/
2856
2857/*
2858 *  A S T _ g e n e r a t e _ n a m e
2859 *  ===========================================
2860 *
2861 *  This routine generates a name from the
2862 *  the unique id stored in the interface
2863 *  node and specified suffix.  The name contains
2864 *  the interface name and version plus a unique
2865 *  integer.
2866 *
2867 *  Inputs:
2868 *      int_p -- interface node
2869 *      suffix -- char * to be appended to generated name
2870 *
2871 *  Returns:
2872 *      NAMETABLE_id_t -- name table entry for generated name
2873 */
2874
2875NAMETABLE_id_t AST_generate_name
2876(
2877      AST_interface_n_t   *int_p,
2878      const char          *suffix
2879)
2880{
2881    char        gen_name[MAX_ID+1];  /* Buffer for generated tag name */
2882    char const  *int_name;      /* Interface name */
2883
2884    /* retrieve the interface name */
2885    NAMETABLE_id_to_string(int_p->name, &int_name);
2886    sprintf(gen_name, "%s_v%ld_%ld_%ld%s", int_name, int_p->version%65536,
2887          int_p->version/65536, int_p->fe_info->gen_index++,suffix);
2888
2889    if (strlen(gen_name) > MAX_ID)
2890        message_print(NIDL_NAMETOOLONG, nidl_yylineno);
2891
2892    return NAMETABLE_add_id(gen_name);
2893}
2894
2895/*---------------------------------------------------------------------*/
2896
2897/*
2898 *  A S T P _ v a l i d a t e _ i n t e g e r
2899 *  ===========================================
2900 *
2901 *  This routine accepts an ASTP expression struct
2902 *  and coerces it into an integer for use in an
2903 *  integer constant expression.  If this is not possible,
2904 *  and error results.
2905 *
2906 */
2907
2908void ASTP_validate_integer
2909(
2910    parser_location_p location,
2911    AST_exp_n_t *exp_node
2912)
2913{
2914
2915	  if (!ASTP_evaluate_expr(location, exp_node, true))	{
2916			log_error(location->lineno, NIDL_NONINTEXP, NULL);
2917			return;
2918	  }
2919
2920	 /*
2921	 *  If not already a long, then must be a constant node, so attempt to
2922	 *  coerce it to an int.
2923	 */
2924	 if (exp_node->exp.constant.type != AST_int_const_k)
2925	 {
2926		  switch (exp_node->exp.constant.val.other->kind)
2927		  {
2928				case AST_int_const_k:
2929					 exp_node->exp.constant.type = AST_int_const_k;
2930					 exp_node->exp.constant.val.integer = exp_node->exp.constant.val.other->value.int_val;
2931					 break;
2932				case AST_char_const_k:
2933					 exp_node->exp.constant.type = AST_int_const_k;
2934					 exp_node->exp.constant.val.integer = exp_node->exp.constant.val.other->value.char_val;
2935					 break;
2936				default:
2937					 exp_node->exp.constant.type = AST_int_const_k;
2938					 exp_node->exp.constant.val.integer = 0;
2939					 log_error(location->lineno,NIDL_NONINTEXP, NULL);
2940					 break;
2941		  }
2942	 }
2943}
2944/*---------------------------------------------------------------------*/
2945
2946/*
2947 *  A S T P _ v e r i f y _ n o n _ a n o n y m o u s
2948 *  =================================================
2949 *
2950 *  This routine accepts a type and verifies that
2951 *  it may be pointed-at without the problems of
2952 *  anonymous structures/unions not being compatible with
2953 *  similarly defined structures/unions.
2954 *
2955 */
2956
2957static void ASTP_verify_non_anonymous
2958(
2959	 parser_location_p location,
2960    AST_type_n_t *type,
2961    ASTP_declarator_n_t *declarator_ptr
2962)
2963{
2964    /*
2965     *  Check that the base type is not an anonymous struct/union (has no name
2966     *  and no tag name)
2967     */
2968    if (!AST_DEF_AS_TAG_SET(type) &&
2969        (type->name == NAMETABLE_NIL_ID) &&
2970         (((type->kind == AST_disc_union_k) &&
2971            (type->type_structure.disc_union != NULL) &&
2972            (type->type_structure.disc_union->tag_name == NAMETABLE_NIL_ID))
2973        ||
2974          ((type->kind == AST_structure_k) &&
2975            (type->type_structure.structure != NULL) &&
2976            (type->type_structure.structure->tag_name == NAMETABLE_NIL_ID))))
2977    {
2978        char const *identifier;
2979        NAMETABLE_id_to_string(declarator_ptr->name, &identifier);
2980        log_warning(location->lineno, NIDL_ANONTYPE, identifier, NULL);
2981    }
2982
2983}
2984
2985void ASTP_set_implicit_handle(
2986	 AST_interface_n_t   *int_p,
2987	 NAMETABLE_id_t type_name,
2988	 NAMETABLE_id_t	handle_name
2989	 )
2990{
2991	if (type_name != NAMETABLE_NIL_ID)	{
2992		AST_type_n_t * type_p;
2993
2994		type_p = (AST_type_n_t*)NAMETABLE_lookup_binding(type_name);
2995		if (type_p != NULL && type_p->fe_info->node_kind == fe_type_n_k)
2996		{
2997			int_p->implicit_handle_name = handle_name;
2998			int_p->implicit_handle_type = type_p;
2999			int_p->implicit_handle_type_name = type_p->name;
3000			if (AST_HANDLE_SET(type_p))
3001				AST_SET_IMPLICIT_HANDLE_G(int_p);
3002		}
3003		else	{
3004			/* A user-defined type not defined in IDL */
3005			int_p->implicit_handle_type_name = type_name;
3006			int_p->implicit_handle_type = NULL;
3007			int_p->implicit_handle_name = handle_name;
3008			AST_SET_IMPLICIT_HANDLE_G(int_p);
3009		}
3010	}
3011	else	{
3012		int_p->implicit_handle_name = handle_name;
3013		int_p->implicit_handle_type = ASTP_handle_ptr;
3014	}
3015}
3016
3017/*---------------------------------------------------------------------*/
3018/* preserve coding style vim: set tw=78 sw=3 ts=3: */
3019