1/*
2 * Copyright (c) 2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1.  Redistributions of source code must retain the above copyright
11 *     notice, this list of conditions and the following disclaimer.
12 * 2.  Redistributions in binary form must reproduce the above copyright
13 *     notice, this list of conditions and the following disclaimer in the
14 *     documentation and/or other materials provided with the distribution.
15 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
16 *     contributors may be used to endorse or promote products derived from
17 *     this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * Portions of this software have been released under the following terms:
31 *
32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC.
33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY
34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION
35 *
36 * To anyone who acknowledges that this file is provided "AS IS"
37 * without any express or implied warranty:
38 * permission to use, copy, modify, and distribute this file for any
39 * purpose is hereby granted without fee, provided that the above
40 * copyright notices and this notice appears in all source code copies,
41 * and that none of the names of Open Software Foundation, Inc., Hewlett-
42 * Packard Company or Digital Equipment Corporation be used
43 * in advertising or publicity pertaining to distribution of the software
44 * without specific, written prior permission.  Neither Open Software
45 * Foundation, Inc., Hewlett-Packard Company nor Digital
46 * Equipment Corporation makes any representations about the suitability
47 * of this software for any purpose.
48 *
49 * Copyright (c) 2007, Novell, Inc. All rights reserved.
50 * Redistribution and use in source and binary forms, with or without
51 * modification, are permitted provided that the following conditions
52 * are met:
53 *
54 * 1.  Redistributions of source code must retain the above copyright
55 *     notice, this list of conditions and the following disclaimer.
56 * 2.  Redistributions in binary form must reproduce the above copyright
57 *     notice, this list of conditions and the following disclaimer in the
58 *     documentation and/or other materials provided with the distribution.
59 * 3.  Neither the name of Novell Inc. nor the names of its contributors
60 *     may be used to endorse or promote products derived from this
61 *     this software without specific prior written permission.
62 *
63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY
67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
73 *
74 * @APPLE_LICENSE_HEADER_END@
75 */
76
77/*
78**
79**  NAME:
80**
81**      checker.c
82**
83**  FACILITY:
84**
85**      Interface Definition Language (IDL) Compiler
86**
87**  ABSTRACT:
88**
89**  IDL Compiler Semantic Checking.
90**
91**  VERSION: DCE 1.0
92*/
93
94#include <stdarg.h>
95
96#include <nidl.h>       /* Standard IDL defs */
97#include <checker.h>    /* Type and constant macros */
98#include <chkichar.h>   /* Protos for I-char checking */
99
100#include <acf_y.h>  /* ACF token values */
101#include <ast.h>        /* Abstract Syntax Tree defs */
102#include <astp.h>       /* AST processing defs */
103#include <command.h>    /* Command option defs */
104#include <errors.h>     /* Error reporting functions */
105#include <message.h>    /* reporting functions */
106
107extern const char *acf_keyword_lookup(
108    int token_value     /* Numeric value of keyword token */
109);
110
111extern int  error_count;        /* Count of semantic errors */
112
113/* Local copy of pointers to command line information. */
114
115static boolean *cmd_opt;   /* Array of command option flags */
116static void    **cmd_val;  /* Array of command option values */
117
118/* Necessary forward function declarations. */
119
120static void type_check(
121    AST_type_n_t        *type_p,        /* [in] Ptr to AST type node */
122    ASTP_node_t         *node_p,        /* [in] Parent node of type node */
123    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
124);
125
126/*
127**  s t r u c t u r e   u t i l i t y   r o u t i n e s
128**
129**  Structure "properties" used by other checks.
130*/
131
132/*
133**  C H K _ s t r u c t _ i s _ a l l _ b y t e _ f i e l d s
134**
135**  Returns TRUE if a struct consists only of scalar byte fields.
136*/
137
138boolean CHK_struct_is_all_byte_fields
139(
140    AST_structure_n_t   *struct_p       /* [in] Ptr to AST structure node */
141)
142
143{
144    AST_field_n_t       *field_p;       /* A field in the structure */
145
146    for (field_p = struct_p->fields ; field_p != NULL ; field_p = field_p->next)
147        if (field_p->type->kind != AST_byte_k)
148            return FALSE;
149
150    return TRUE;
151}
152
153/*
154**  t y p e   u t i l i t y   r o u t i n e s
155**
156**  Type "properties" used by other checks.
157*/
158
159/*
160**  t y p e _ i s _ s t r i n g
161**
162**  Returns TRUE if a type can be used as a valid [string] data type:
163**  A 1-dim array of char or byte, or a pointer to a char or byte, OR
164**  a (1-dim array of) or (pointer to) (struct containing only byte fields).
165**  OR, a {1-dim array of | pointer to} unsigned short or unsigned long.
166*/
167
168static boolean type_is_string
169(
170    AST_type_n_t        *type_p         /* [in] Ptr to AST type node */
171)
172{
173    unsigned short      index_count;    /* Number of array dimensions */
174    AST_type_n_t        *base_type_p;   /* Base type of array */
175
176    if (type_p->kind == AST_array_k)
177    {
178        index_count = type_p->type_structure.array->index_count;
179        base_type_p = type_p->type_structure.array->element_type;
180    }
181    else if (type_p->kind == AST_pointer_k)
182    {
183        index_count = 1;
184        base_type_p = type_p->type_structure.pointer->pointee_type;
185    }
186    else
187        return FALSE;
188
189    if (index_count == 1
190        &&  (base_type_p->kind == AST_character_k
191            ||  base_type_p->kind == AST_byte_k
192            ||  base_type_p->kind == AST_short_unsigned_k
193            ||  base_type_p->kind == AST_long_unsigned_k
194            ||  (base_type_p->kind == AST_structure_k
195                &&  CHK_struct_is_all_byte_fields
196                        (base_type_p->type_structure.structure))))
197        return TRUE;
198
199    return FALSE;
200}
201
202/*
203**  t y p e _ i s _ v 1 _ s t r i n g
204**
205**  Returns TRUE if a type can be used as a valid [v1_string] data type:
206**  An array of char, in array syntax, with lower bound 0 and fixed upper
207**  bound.  If the array is multidimensional, the minor dimension must meet
208**  these criteria.
209*/
210
211static boolean type_is_v1_string
212(
213    AST_type_n_t        *type_p         /* [in] Ptr to AST type node */
214)
215{
216    AST_array_n_t       *array_p;       /* Ptr to array node */
217    AST_array_index_n_t *index_p;       /* Array index node for minor dim */
218
219    if (type_p->kind != AST_array_k)
220        return FALSE;
221
222    array_p = type_p->type_structure.array;
223
224    if (array_p->element_type->kind != AST_character_k)
225        return FALSE;
226
227    index_p = &array_p->index_vec[array_p->index_count - 1];
228
229    if (!AST_CONFORMANT_SET(type_p)
230        &&  index_p->lower_bound != NULL
231        &&  index_p->lower_bound->kind == AST_int_const_k
232        &&  index_p->lower_bound->value.int_val == 0
233        &&  index_p->upper_bound != NULL
234        &&  index_p->upper_bound->kind == AST_int_const_k)
235        return TRUE;
236
237    return FALSE;
238}
239
240/*
241**  t y p e _ x m i t _ t y p e
242**
243**  Given a (presented) type, returns the transmissible type.  These two types
244**  are only different when the type has a [transmit_as] attribute.
245*/
246
247static AST_type_n_t * type_xmit_type
248(
249    AST_type_n_t        *type_p         /* [in] Ptr to AST type node */
250)
251{
252    while (type_p->xmit_as_type != NULL)
253        type_p = type_p->xmit_as_type;
254
255    return type_p;
256}
257
258/*
259**  a r r a y   u t i l i t y   r o u t i n e s
260**
261**  Array "properties" used by other checks.
262*/
263
264/*
265**  a r r a y _ i s _ c o n f o r m a n t _ u p p e r
266**
267**  Returns TRUE if an array is conformant in an upper dimension
268**  (i.e., a dimension other than the first dimension).
269*/
270
271static boolean array_is_conformant_upper
272(
273    AST_array_n_t       *array_p        /* [in] Ptr to AST array node */
274)
275{
276    AST_array_index_n_t *index_p;       /* Ptr to array index node */
277    int                 i;              /* Integer array dimension 0..N-1 */
278
279    index_p = array_p->index_vec;       /* Point at index vector */
280
281    /* Check dimensions 1..N-1 for conformance (1st dim is index 0). */
282
283    for (i = 1, index_p++ ; i < array_p->index_count ; i++, index_p++)
284    {
285        if (!AST_FIXED_LOWER_SET(index_p)
286            ||  !AST_FIXED_UPPER_SET(index_p))
287            return TRUE;    /* Conformant in this dimension */
288    }
289
290    return FALSE;
291}
292
293/*
294**  a r r a y _ i s _ l a r g e
295**
296**  Returns TRUE if an array has a total (all dimensions) of >65535 elements.
297*/
298
299static boolean array_is_large
300(
301    AST_array_n_t       *array_p        /* [in] Ptr to AST array node */
302)
303{
304    AST_array_index_n_t *index_p;       /* Ptr to array index node */
305    int                 i;              /* Integer array dimension 0..N-1 */
306    long                dim_size;       /* Size of one array dimension */
307    long                elem_cnt;       /* Running total of array elements */
308
309    index_p = array_p->index_vec;       /* Point at index vector */
310    elem_cnt = 1;
311
312    /*
313     * Go through each dimension of the array computing the size of the
314     * array in that dimension, and multiplying it into the running total
315     * of elements.  If the total becomes >65535, the array is "large".
316     * For conformant dimensions, we don't know the eventual
317     * size of the dimension.  All we can really do is assume the smallest
318     * size for that dimension (1) and continue with our check, as the
319     * array still might be large from the fixed dimensions alone.
320     */
321    for (i = 0 ; i < array_p->index_count ; i++, index_p++)
322    {
323        if (AST_FIXED_LOWER_SET(index_p)
324            &&  AST_FIXED_UPPER_SET(index_p))
325        {
326            dim_size =  index_p->upper_bound->value.int_val -
327                        index_p->lower_bound->value.int_val + 1;
328            /*
329             * If the dimension itself has >65535 elements, the array is large.
330             * This special case check is needed to avoid the possibility of
331             * integer overflow on the running product.
332             */
333            if (dim_size > 65535)
334                return TRUE;    /* Large in this dimension */
335
336            /* If the total number of elements is >65535, the array is large. */
337            elem_cnt = elem_cnt * dim_size;
338            if (elem_cnt > 65535)
339                return TRUE;    /* Large in overall size */
340        }
341    }
342
343    return FALSE;
344}
345
346/*
347**  a r r a y _ h a s _ o p e n _ l b
348**
349**  Returns TRUE if an array has an open lower bound in any dimension.
350*/
351
352static boolean array_has_open_lb
353(
354    AST_array_n_t       *array_p        /* [in] Ptr to AST array node */
355)
356{
357    AST_array_index_n_t *index_p;       /* Ptr to array index node */
358    int                 i;              /* Integer array dimension 0..N-1 */
359
360    index_p = array_p->index_vec;       /* Point at index vector */
361
362    /* Go through each dimension of the array checking for open lower bound. */
363
364    for (i = 0 ; i < array_p->index_count ; i++, index_p++)
365        if (!AST_FIXED_LOWER_SET(index_p))
366            return TRUE;
367
368    return FALSE;
369}
370
371/*
372**  p a r a m e t e r   u t i l i t y   r o u t i n e s
373**
374**  Utility routines for parameter nodes, used by other checks.
375*/
376
377/*
378**  p a r a m _ f o l l o w _ r e f _ p t r
379**
380**  Dereferences a parameter's type if it is a pointer and it meets certain
381**  conditions.  Some of the conditions apply always; others are dependent
382**  on the 'mode' argument (see below, and checker.h).
383**
384**  The general intent of this function is to follow reference pointers.
385**  However, there are ambiguities as to what that really means, and
386**  different dereferencing behavior is required depending on the need.
387**  Thus, the 'mode' argument allows one to tweak what this routine does.
388**
389**  Returns address of pointee type node if the type was dereferenced.
390**  Returns address of parameter's type node if the type was NOT dereferenced.
391*/
392
393AST_type_n_t * param_follow_ref_ptr     /* Returns ptr to type node */
394(
395    AST_parameter_n_t   *param_p,       /* [in] Ptr to AST parameter node */
396    CHK_follow_t        mode            /* [in] Follow mode */
397)
398{
399    AST_type_n_t        *type_p;        /* Ptr to AST type node */
400    AST_type_n_t        *ptee_type_p;   /* Pointee type */
401
402    type_p = param_p->type;
403
404    if (type_p->kind != AST_pointer_k)
405        return type_p;
406
407    ptee_type_p = type_p->type_structure.pointer->pointee_type;
408
409    /*
410     * The pointer is followed, with these EXCEPTIONS:
411     *  - on a function result parameter, which by def can't be a ref ptr
412     *  - void *, since "void passed-by-reference" makes no sense
413     *  - function pointer
414     *  - arrayified [string] pointers (but not pointer to string array)
415     *
416     * These additional EXCEPTIONS apply when the indicated mode(s) are selected
417     * (see checker.h):
418     *  - a named pointer                (mode == CHK_follow_any)
419     *  - a [unique] or [ptr] pointer    (mode != CHK_follow_any)
420     *  - arrayified via size attributes (mode != CHK_follow_ref_arr_siz)
421     */
422                                                /* EXCEPTIONS to following:  */
423    if (param_p == param_p->uplink->result      /* The result param          */
424        ||  ptee_type_p->kind == AST_void_k     /* (void *)                  */
425        ||  ptee_type_p->kind == AST_function_k /* Function pointer          */
426        ||  (type_p->name != NAMETABLE_NIL_ID   /* Not anonymous             */
427             && mode == CHK_follow_any)         /*   AND follow any mode     */
428        ||  (!AST_REF_SET(param_p)            /* [unique] attribute        */
429             && mode != CHK_follow_any)         /*  AND not follow any mode  */
430        ||  (param_p->field_attrs != NULL       /* Arrayified via size attrs */
431             && instance_has_array_attr(param_p)/*   array not switch attr   */
432             && mode != CHK_follow_ref_arr_siz) /*   BUT mode = don't follow */
433        ||  ((AST_STRING_SET(type_p)            /* Arrayified via [string]   */
434              || AST_STRING_SET(param_p))       /*   on type or param, AND   */
435             && type_is_string(type_p)))        /*  not superfluous pointer  */
436        return type_p;
437
438    return ptee_type_p;
439}
440
441/*
442**  d e f a u l t _ t o _ a u t o _ h a n d l e
443**
444**  Issues message that auto_handle is assumed for a particular operation.
445**
446**  Implicit Outputs:   def_auto_handle
447*/
448
449static int def_auto_handle = 0;
450
451static void default_to_auto_handle
452(
453    AST_operation_n_t   *op_p,          /* [in] Ptr to AST operation node */
454    int                 message_id      /* [in] message it display */
455)
456{
457    char const *id_name;   /* Operation name */
458
459    NAMETABLE_id_to_string(op_p->name, &id_name);
460    message_print(message_id, id_name);
461    def_auto_handle++;
462}
463
464
465/*
466**  i n s t a n c e   u t i l i t y   r o u t i n e s
467**
468**  Instance "properties" used by other checks.
469**  An "instance" is an instance (arm, field, parameter) of some data type.
470*/
471
472/*
473**  i n s t a n c e _ i s _ v a r y i n g _ u p p e r
474**
475**  Returns TRUE if an instance of an array is varying in an upper dimension
476**  (i.e., a dimension other than the first dimension).
477*/
478
479static boolean instance_is_varying_upper
480(
481    AST_array_n_t       *array_p,       /* [in] Ptr to AST array node */
482    AST_field_attr_n_t  *fattr_p        /* [in] Ptr to AST field attr. node */
483)
484{
485    AST_field_ref_n_t   *first_p;       /* first_is ref for a dimension */
486    AST_field_ref_n_t   *last_p;        /* last_is ref for a dimension */
487    AST_field_ref_n_t   *length_p;      /* length_is ref for a dimension */
488    int                 i;              /* Integer array dimension 0..N-1 */
489
490    if (fattr_p == NULL)
491        return FALSE;
492
493    first_p  = fattr_p->first_is_vec;
494    last_p   = fattr_p->last_is_vec;
495    length_p = fattr_p->length_is_vec;
496
497    /* Check dimensions 1..N-1 for varying attribute (1st dim is index 0). */
498
499    for (i = 1 ; i < array_p->index_count ; i++)
500    {
501        if (first_p != NULL)
502        {
503            first_p++;
504            if (first_p->valid)
505                return TRUE;    /* Varying in this dimension */
506        }
507
508        if (last_p != NULL)
509        {
510            last_p++;
511            if (last_p->valid)
512                return TRUE;    /* Varying in this dimension */
513        }
514
515        if (length_p != NULL)
516        {
517            length_p++;
518            if (length_p->valid)
519                return TRUE;    /* Varying in this dimension */
520        }
521    }
522
523    return FALSE;
524}
525
526/*
527**  f a t t r _ s w i t c h _ i s
528**
529**  Checks a field attribute node's [switch_is] attribute.
530*/
531
532static void fattr_switch_is
533(
534    AST_field_attr_n_t  *fattr_p,       /* [in] Ptr to AST field attr. node */
535    ASTP_node_t         *node_p,        /* [in] Ptr to field or param node */
536    AST_type_n_t        *type_p         /* [in] Ptr to field/param data type */
537)
538{
539    AST_type_n_t        *ref_type_p;    /* Ptr to size info field/param type */
540    AST_type_n_t        *deref_type_p;  /* Dereferenced field/param type */
541    AST_type_n_t        *sw_type_p;     /* [switch_type] type */
542    NAMETABLE_id_t      ref_name;       /* Field/param name */
543    boolean             is_ref_ptr;     /* TRUE => ref_type_p is [ref] ptr */
544
545    /* Checks assume presence of switch_is attr and union data type. */
546
547    if (fattr_p->switch_is == NULL)
548        return;
549
550    type_p = ASTP_chase_ptr_to_kind(type_p, AST_disc_union_k);
551    if (type_p == NULL)
552        /* Parser supposed to catch this. */
553        error(NIDL_INTERNAL_ERROR, __FILE__, __LINE__);
554
555    sw_type_p = type_p->type_structure.disc_union->discrim_type;
556    if (sw_type_p == NULL) return;
557
558    /* Pick up [switch_is] field or parameter reference, if any. */
559
560    if (node_p->fe_info->node_kind == fe_field_n_k)
561    {
562        ref_type_p = fattr_p->switch_is->ref.f_ref->type;
563        ref_name   = fattr_p->switch_is->ref.f_ref->name;
564        is_ref_ptr = (AST_REF_SET(fattr_p->switch_is->ref.f_ref));
565    }
566    else
567    {
568        ref_type_p = fattr_p->switch_is->ref.p_ref->type;
569        ref_name   = fattr_p->switch_is->ref.p_ref->name;
570        is_ref_ptr = (AST_REF_SET(fattr_p->switch_is->ref.p_ref));
571    }
572
573    /*
574     * Param/field referenced in [switch_is] might be a ptr.  Chase ptr
575     * to its base type.  This sets deref_type_p->fe_info->pointer_count
576     * to the number of dereferences needed to get to the base type.
577     */
578    deref_type_p = ASTP_chase_ptr_to_type(ref_type_p);
579
580    /* The union switch variable 'name' cannot have [ptr] or [unique] attr */
581
582    if (deref_type_p->fe_info->pointer_count > 0
583        &&  !is_ref_ptr)
584    {
585        char const *id_name;       /* [switch_is] variable name */
586        NAMETABLE_id_to_string(ref_name, &id_name);
587        CHECKER_error(fattr_p, NIDL_NEUSWPTR, id_name);
588    }
589
590    /* Data type of [switch_is] variable does not agree with [switch_type] */
591
592    if (deref_type_p->kind != sw_type_p->kind)
593    {
594        char const *id_name;       /* [switch_is] variable name */
595        char const *sw_type_name;  /* [switch_type] name, if any */
596
597        NAMETABLE_id_to_string(ref_name, &id_name);
598        NAMETABLE_id_to_string(sw_type_p->name, &sw_type_name);
599        if (sw_type_name == NULL) sw_type_name = "";
600
601        CHECKER_error(fattr_p, NIDL_SWDATATYPE, id_name, sw_type_name);
602    }
603
604    /* A [switch_is] variable must not have a represent_as type */
605
606    if (deref_type_p->rep_as_type != NULL)
607        CHECKER_error(fattr_p, NIDL_DISCRIMREPAS);
608
609    /* A [switch_is] variable must not have a transmit_as type */
610
611    if (deref_type_p->xmit_as_type != NULL)
612        CHECKER_error(fattr_p, NIDL_DISCRIMXMITAS);
613}
614/*
615**  f a t t r _ c h e c k _ s i z e
616**
617**  Checks a field attribute node for missing or inconsistent size attributes.
618*/
619
620static void fattr_check_size
621(
622    AST_field_attr_n_t  *fattr_p,       /* [in] Ptr to AST field attr. node */
623    ASTP_node_t         *node_p,        /* [in] Ptr to field or param node */
624    AST_type_n_t        *type_p,        /* [in] Ptr to field data type node */
625    AST_interface_n_t   *int_p,         /* [in] Ptr to interface node */
626    unsigned short      dim             /* [in] Array dimension to check */
627)
628{
629    AST_array_n_t       *array_p;       /* Ptr to array node */
630    AST_array_index_n_t *index_p = NULL;       /* Ptr to array index node */
631    boolean             str_attr_set;   /* T => [string] on type or instance */
632
633    /* Determine if [string] attribute set on type or instance. */
634
635    if (AST_STRING_SET(type_p)
636        ||  (node_p->fe_info->node_kind == fe_field_n_k
637            &&  AST_STRING_SET((AST_field_n_t *)node_p))
638        ||  (node_p->fe_info->node_kind == fe_parameter_n_k
639            &&  AST_STRING_SET((AST_parameter_n_t *)node_p)))
640        str_attr_set = TRUE;
641    else
642        str_attr_set = FALSE;
643
644    /*
645     * Assume parser won't put field attribute node on non-arrays.
646     * An array can be represented either in normal array syntax,
647     * or as a pointer that has any of the array attributes.
648     */
649    if (type_p->kind == AST_array_k)
650    {
651        array_p = type_p->type_structure.array;
652        index_p = &array_p->index_vec[dim];
653    }
654    else
655        array_p = NULL;
656
657    /* Can't have both [max_is] and [size_is] attributes */
658
659    if (fattr_p->max_is_vec != NULL
660        &&  fattr_p->max_is_vec[dim].valid
661        &&  fattr_p->size_is_vec != NULL
662        &&  fattr_p->size_is_vec[dim].valid)
663        CHECKER_error(fattr_p, NIDL_MAXSIZECONF);
664
665    /* Can't have constant [size_is] and varying [min_is] */
666
667    if (fattr_p->min_is_vec != NULL
668        &&  fattr_p->min_is_vec[dim].valid
669        &&  fattr_p->min_is_vec[dim].constant == false
670        &&  fattr_p->size_is_vec != NULL
671        &&  fattr_p->size_is_vec[dim].valid
672        &&  fattr_p->size_is_vec[dim].constant == true)
673	CHECKER_error(fattr_p, NIDL_CONSTREQ);
674
675    /* Can't have both [last_is] and [length_is] attributes */
676
677    if (fattr_p->last_is_vec != NULL
678        &&  fattr_p->last_is_vec[dim].valid
679        &&  fattr_p->length_is_vec != NULL
680        &&  fattr_p->length_is_vec[dim].valid)
681        CHECKER_error(fattr_p, NIDL_LASTLENCONF);
682
683    /* Can't have constant [length_is] and varying [first_is] */
684
685    if (fattr_p->first_is_vec != NULL
686        &&  fattr_p->first_is_vec[dim].valid
687        &&  fattr_p->first_is_vec[dim].constant == false
688        &&  fattr_p->length_is_vec != NULL
689        &&  fattr_p->length_is_vec[dim].valid
690        &&  fattr_p->length_is_vec[dim].constant == true)
691	CHECKER_error(fattr_p, NIDL_CONSTREQ);
692
693    /*
694     * Forgo the remaining checks if the field or parameter type is a pointer
695     * to an array, since mixed pointer and array declarations with array size
696     * attributes are disallowed by other checks.
697     */
698    if (type_p->kind == AST_pointer_k)
699    {
700        AST_type_n_t    *ref_type_p;    /* Pointee data type */
701
702        ref_type_p = ASTP_chase_ptr_to_type(type_p);
703        if (ref_type_p->kind == AST_array_k)
704            return;
705    }
706    else if (fattr_p->range != NULL && !type_is_rangeable(type_p))
707    {
708        CHECKER_error(fattr_p, NIDL_RANGEATTR);
709    }
710
711    /* [max_is] or [size_is] attribute required */
712
713    if (array_p != NULL     /* Array in array syntax */
714        &&  !AST_LOCAL_SET(int_p)
715        &&  type_p->xmit_as_type == NULL
716        &&  !AST_FIXED_UPPER_SET(index_p)
717        &&  (fattr_p->max_is_vec == NULL
718            ||  !fattr_p->max_is_vec[dim].valid)
719        &&  (fattr_p->size_is_vec == NULL
720            ||  !fattr_p->size_is_vec[dim].valid))
721        CHECKER_error(fattr_p, NIDL_MAXSIZEATTR);
722
723    if (array_p == NULL     /* Non-[string] array in pointer syntax */
724        &&  !str_attr_set
725        &&  (fattr_p->first_is_vec != NULL
726            ||  fattr_p->last_is_vec != NULL
727            ||  fattr_p->length_is_vec != NULL
728            ||  fattr_p->min_is_vec != NULL)
729        &&  fattr_p->max_is_vec == NULL
730        &&  fattr_p->size_is_vec == NULL)
731        CHECKER_error(fattr_p, NIDL_MAXSIZEATTR);
732
733    /* [min_is] attribute required */
734
735    if (array_p != NULL
736        &&  !AST_LOCAL_SET(int_p)
737        &&  type_p->xmit_as_type == NULL
738        &&  !AST_FIXED_LOWER_SET(index_p)
739        &&  (fattr_p->min_is_vec == NULL
740            ||  !fattr_p->min_is_vec[dim].valid))
741        CHECKER_error(fattr_p, NIDL_MINATTREQ);
742
743    if (array_p != NULL && fattr_p->range != NULL)
744        CHECKER_error(fattr_p, NIDL_RANGEATTR);
745}
746
747/*
748**  f a t t r _ f i r s t _ i s
749**
750**  Checks a field attribute node's [first_is] attribute.
751*/
752
753static void fattr_first_is
754(
755    AST_field_attr_n_t  *fattr_p,       /* [in] Ptr to AST field attr. node */
756    ASTP_node_t         *node_p,        /* [in] Ptr to field or param node */
757    unsigned short      dim             /* [in] Array dimension to check */
758)
759{
760    AST_type_n_t        *ref_type_p;    /* Ptr to size info field/param type */
761    AST_type_n_t        *deref_type_p = NULL;  /* Dereferenced field/param type */
762    NAMETABLE_id_t      ref_name = 0;       /* Field/param name */
763    boolean             is_ref_ptr = false;     /* TRUE => ref_type_p is [ref] ptr */
764
765    /* Pick up [first_is] field or parameter reference, if any. */
766
767    if (fattr_p->first_is_vec != NULL
768        &&  fattr_p->first_is_vec[dim].valid)
769    {
770        if (fattr_p->first_is_vec[dim].constant)
771	    return;
772
773        if (node_p->fe_info->node_kind == fe_field_n_k)
774        {
775            ref_type_p = fattr_p->first_is_vec[dim].ref.f_ref->type;
776            ref_name   = fattr_p->first_is_vec[dim].ref.f_ref->name;
777            is_ref_ptr = (AST_REF_SET(fattr_p->first_is_vec[dim].ref.f_ref));
778        }
779        else
780        {
781            ref_type_p = fattr_p->first_is_vec[dim].ref.p_ref->type;
782            ref_name   = fattr_p->first_is_vec[dim].ref.p_ref->name;
783            is_ref_ptr = (AST_REF_SET(fattr_p->first_is_vec[dim].ref.p_ref));
784        }
785
786        /*
787         * Param/field referenced in [first_is] might be a ptr.  Chase ptr
788         * to its base type.  This sets deref_type_p->fe_info->pointer_count
789         * to the number of dereferences needed to get to the base type.
790         */
791        deref_type_p = ASTP_chase_ptr_to_type(ref_type_p);
792        assert(deref_type_p != NULL);
793
794        /* [first_is] variable must be of type integer */
795
796        if (!type_is_index(deref_type_p)
797                 ||  deref_type_p->fe_info->pointer_count
798                 != fattr_p->first_is_vec[dim].fe_info->pointer_count)
799            CHECKER_error(fattr_p, NIDL_FIRSTYPEINT);
800
801        /* A size attribute variable must not have a represent_as type */
802
803        if (deref_type_p->rep_as_type != NULL)
804            CHECKER_error(fattr_p, NIDL_SIZEVARREPAS);
805
806        /* A size attribute variable must not have a transmit_as type */
807
808        if (deref_type_p->xmit_as_type != NULL)
809            CHECKER_error(fattr_p, NIDL_SIZEVARXMITAS);
810
811        /* The array size attr var 'name' can not have [ptr] or [unique] attr */
812
813        if (deref_type_p->fe_info->pointer_count > 0
814            &&  !is_ref_ptr)
815        {
816            char const *id_name;       /* [first_is] variable name */
817
818            NAMETABLE_id_to_string(ref_name, &id_name);
819
820            CHECKER_error(fattr_p, NIDL_SIZEPRMPTR, id_name);
821        }
822    }
823}
824
825/*
826**  f a t t r _ l a s t _ i s
827**
828**  Checks a field attribute node's [last_is] attribute.
829*/
830
831static void fattr_last_is
832(
833    AST_field_attr_n_t  *fattr_p,       /* [in] Ptr to AST field attr. node */
834    ASTP_node_t         *node_p,        /* [in] Ptr to field or param node */
835    unsigned short      dim             /* [in] Array dimension to check */
836)
837{
838    AST_type_n_t        *ref_type_p;    /* Ptr to size info field/param type */
839    AST_type_n_t        *deref_type_p = NULL;  /* Dereferenced field/param type */
840    NAMETABLE_id_t      ref_name = 0;       /* Field/param name */
841    boolean             is_ref_ptr = false;     /* TRUE => ref_type_p is [ref] ptr */
842
843    /* Pick up [last_is] field or parameter reference, if any. */
844
845    if (fattr_p->last_is_vec != NULL
846        &&  fattr_p->last_is_vec[dim].valid)
847    {
848        if (fattr_p->last_is_vec[dim].constant)
849	    return;
850
851        if (node_p->fe_info->node_kind == fe_field_n_k)
852        {
853            ref_type_p = fattr_p->last_is_vec[dim].ref.f_ref->type;
854            ref_name   = fattr_p->last_is_vec[dim].ref.f_ref->name;
855            is_ref_ptr = (AST_REF_SET(fattr_p->last_is_vec[dim].ref.f_ref));
856        }
857        else
858        {
859            ref_type_p = fattr_p->last_is_vec[dim].ref.p_ref->type;
860            ref_name   = fattr_p->last_is_vec[dim].ref.p_ref->name;
861            is_ref_ptr = (AST_REF_SET(fattr_p->last_is_vec[dim].ref.p_ref));
862        }
863
864        /*
865         * Param/field referenced in [last_is] might be a ptr.  Chase ptr
866         * to its base type.  This sets deref_type_p->fe_info->pointer_count
867         * to the number of dereferences needed to get to the base type.
868         */
869        deref_type_p = ASTP_chase_ptr_to_type(ref_type_p);
870        assert(deref_type_p != NULL);
871
872        /* [last_is] variable must be of type integer */
873
874        if (!type_is_index(deref_type_p)
875                 ||  deref_type_p->fe_info->pointer_count
876                 != fattr_p->last_is_vec[dim].fe_info->pointer_count)
877            CHECKER_error(fattr_p, NIDL_LASTYPEINT);
878
879        /* A size attribute variable must not have a represent_as type */
880
881        if (deref_type_p->rep_as_type != NULL)
882            CHECKER_error(fattr_p, NIDL_SIZEVARREPAS);
883
884        /* A size attribute variable must not have a transmit_as type */
885
886        if (deref_type_p->xmit_as_type != NULL)
887            CHECKER_error(fattr_p, NIDL_SIZEVARXMITAS);
888
889        /* The array size attr var 'name' can not have [ptr] or [unique] attr */
890
891        if (deref_type_p->fe_info->pointer_count > 0
892            &&  !is_ref_ptr)
893        {
894            char const *id_name;       /* [last_is] variable name */
895
896            NAMETABLE_id_to_string(ref_name, &id_name);
897
898            CHECKER_error(fattr_p, NIDL_SIZEPRMPTR, id_name);
899        }
900    }
901}
902
903/*
904**  f a t t r _ l e n g t h _ i s
905**
906**  Checks a field attribute node's [length_is] attribute.
907*/
908
909static void fattr_length_is
910(
911    AST_field_attr_n_t  *fattr_p,       /* [in] Ptr to AST field attr. node */
912    ASTP_node_t         *node_p,        /* [in] Ptr to field or param node */
913    unsigned short      dim             /* [in] Array dimension to check */
914)
915{
916    AST_type_n_t        *ref_type_p;    /* Ptr to size info field/param type */
917    AST_type_n_t        *deref_type_p = NULL;  /* Dereferenced field/param type */
918    NAMETABLE_id_t      ref_name = 0;       /* Field/param name */
919    boolean             is_ref_ptr = false;     /* TRUE => ref_type_p is [ref] ptr */
920
921    /* Pick up [length_is] field or parameter reference, if any. */
922
923    if (fattr_p->length_is_vec != NULL
924        &&  fattr_p->length_is_vec[dim].valid)
925    {
926        if (fattr_p->length_is_vec[dim].constant)
927	    return;
928
929        if (node_p->fe_info->node_kind == fe_field_n_k)
930        {
931            ref_type_p = fattr_p->length_is_vec[dim].ref.f_ref->type;
932            ref_name   = fattr_p->length_is_vec[dim].ref.f_ref->name;
933            is_ref_ptr = (AST_REF_SET(fattr_p->length_is_vec[dim].ref.f_ref));
934        }
935        else
936        {
937            ref_type_p = fattr_p->length_is_vec[dim].ref.p_ref->type;
938            ref_name   = fattr_p->length_is_vec[dim].ref.p_ref->name;
939            is_ref_ptr = (AST_REF_SET(fattr_p->length_is_vec[dim].ref.p_ref));
940        }
941
942        /*
943         * Param/field referenced in [length_is] might be a ptr.  Chase ptr
944         * to its base type.  This sets deref_type_p->fe_info->pointer_count
945         * to the number of dereferences needed to get to the base type.
946         */
947        deref_type_p = ASTP_chase_ptr_to_type(ref_type_p);
948        assert(deref_type_p != NULL);
949
950        /* [length_is] variable must be of type integer */
951
952        if (!type_is_index(deref_type_p)
953                 ||  deref_type_p->fe_info->pointer_count
954                 != fattr_p->length_is_vec[dim].fe_info->pointer_count)
955            CHECKER_error(fattr_p, NIDL_LENTYPEINT);
956
957        /* A size attribute variable must not have a represent_as type */
958
959        if (deref_type_p->rep_as_type != NULL)
960            CHECKER_error(fattr_p, NIDL_SIZEVARREPAS);
961
962        /* A size attribute variable must not have a transmit_as type */
963
964        if (deref_type_p->xmit_as_type != NULL)
965            CHECKER_error(fattr_p, NIDL_SIZEVARXMITAS);
966
967        /* The array size attr var 'name' can not have [ptr] or [unique] attr */
968
969        if (deref_type_p->fe_info->pointer_count > 0
970            &&  !is_ref_ptr)
971        {
972            char const *id_name;       /* [length_is] variable name */
973
974            NAMETABLE_id_to_string(ref_name, &id_name);
975
976            CHECKER_error(fattr_p, NIDL_SIZEPRMPTR, id_name);
977        }
978    }
979}
980
981/*
982**  f a t t r _ m i n _ i s
983**
984**  Checks a field attribute node's [min_is] attribute.
985*/
986
987static void fattr_min_is
988(
989    AST_field_attr_n_t  *fattr_p,       /* [in] Ptr to AST field attr. node */
990    ASTP_node_t         *node_p,        /* [in] Ptr to field or param node */
991    AST_type_n_t        *type_p,        /* [in] Ptr to field/param data type */
992    unsigned short      dim             /* [in] Array dimension to check */
993)
994{
995    AST_array_n_t       *array_p;       /* Ptr to array node */
996    AST_array_index_n_t *index_p = NULL;       /* Ptr to array index node */
997    AST_type_n_t        *ref_type_p;    /* Ptr to size info field/param type */
998    AST_type_n_t        *deref_type_p = NULL;  /* Dereferenced field/param type */
999    NAMETABLE_id_t      ref_name = 0;       /* Field/param name */
1000    boolean             is_ref_ptr = false;     /* TRUE => ref_type_p is [ref] ptr */
1001
1002    /*
1003     * Assume parser won't put field attribute node on non-arrays.
1004     * An array can be represented either in normal array syntax,
1005     * or as a pointer that has any of the array attributes.
1006     */
1007    if (type_p->kind == AST_array_k)
1008    {
1009        array_p = type_p->type_structure.array;
1010        index_p = &array_p->index_vec[dim];
1011    }
1012    else
1013        array_p = NULL;
1014
1015    /* Pick up [min_is] field or parameter reference, if any. */
1016
1017    if (fattr_p->min_is_vec != NULL
1018        &&  fattr_p->min_is_vec[dim].valid
1019        &&  fattr_p->min_is_vec[dim].constant == false)
1020    {
1021        if (node_p->fe_info->node_kind == fe_field_n_k)
1022        {
1023            ref_type_p = fattr_p->min_is_vec[dim].ref.f_ref->type;
1024            ref_name   = fattr_p->min_is_vec[dim].ref.f_ref->name;
1025            is_ref_ptr = (AST_REF_SET(fattr_p->min_is_vec[dim].ref.f_ref));
1026        }
1027        else
1028        {
1029            ref_type_p = fattr_p->min_is_vec[dim].ref.p_ref->type;
1030            ref_name   = fattr_p->min_is_vec[dim].ref.p_ref->name;
1031            is_ref_ptr = (AST_REF_SET(fattr_p->min_is_vec[dim].ref.p_ref));
1032        }
1033
1034        /*
1035         * Param/field referenced in [min_is] might be a ptr.  Chase ptr
1036         * to its base type.  This sets deref_type_p->fe_info->pointer_count
1037         * to the number of dereferences needed to get to the base type.
1038         */
1039        deref_type_p = ASTP_chase_ptr_to_type(ref_type_p);
1040    }
1041
1042    /* Arrays with a nonzero lower bound require -standard extended */
1043
1044    /*
1045     * Anonymous type checking will pick this up for anonymous array types in
1046     * array syntax.  Normal type checking will pick it up for named types at
1047     * the typedef site.  Therefore, we only need to handle the pointer case.
1048     */
1049    if (type_p->kind == AST_pointer_k
1050        &&  fattr_p->min_is_vec != NULL
1051        &&  (*(int *)cmd_val[opt_standard] <= opt_standard_dce_1_0))
1052        CHECKER_warning(fattr_p, NIDL_NOPORTNZLB, OPT_STD_EXTENDED);
1053
1054    /* [min_is] variable <var> invalid: lower bound fixed in dimension <n> */
1055
1056    if (array_p != NULL
1057        &&  fattr_p->min_is_vec != NULL
1058        &&  (!type_is_array(type_p)
1059            ||  (type_is_array(type_p)
1060                &&  fattr_p->min_is_vec[dim].valid
1061                &&  AST_FIXED_LOWER_SET(index_p))))
1062        CHECKER_error(fattr_p, NIDL_MINCFMTYPE, dim+1);
1063
1064    /* Constants are excused from further checks */
1065
1066    if (fattr_p->min_is_vec != NULL
1067        &&  fattr_p->min_is_vec[dim].valid
1068        &&  fattr_p->min_is_vec[dim].constant)
1069        return;
1070
1071    /* [min_is] variable must be of type integer */
1072
1073    if (fattr_p->min_is_vec != NULL
1074        &&  fattr_p->min_is_vec[dim].valid) {
1075
1076        assert(deref_type_p != NULL);
1077
1078        if (!type_is_index(deref_type_p)
1079                ||  deref_type_p->fe_info->pointer_count
1080                    != fattr_p->min_is_vec[dim].fe_info->pointer_count)
1081            CHECKER_error(fattr_p, NIDL_MINTYPEINT);
1082
1083        /* A size attribute variable must not have a represent_as type */
1084
1085        if (deref_type_p->rep_as_type != NULL)
1086            CHECKER_error(fattr_p, NIDL_SIZEVARREPAS);
1087
1088        /* A size attribute variable must not have a transmit_as type */
1089
1090        if (deref_type_p->xmit_as_type != NULL)
1091            CHECKER_error(fattr_p, NIDL_SIZEVARXMITAS);
1092
1093        /* The array size attr var 'name' can not have [ptr] or [unique] attr */
1094
1095        if (deref_type_p->fe_info->pointer_count > 0
1096            &&  !is_ref_ptr)
1097        {
1098            char const *id_name;       /* [min_is] variable name */
1099
1100            NAMETABLE_id_to_string(ref_name, &id_name);
1101
1102            CHECKER_error(fattr_p, NIDL_SIZEPRMPTR, id_name);
1103        }
1104    }
1105}
1106
1107/*
1108**  f a t t r _ m a x _ i s
1109**
1110**  Checks a field attribute node's [max_is] attribute.
1111*/
1112
1113static void fattr_max_is
1114(
1115    AST_field_attr_n_t  *fattr_p,       /* [in] Ptr to AST field attr. node */
1116    ASTP_node_t         *node_p,        /* [in] Ptr to field or param node */
1117    AST_type_n_t        *type_p,        /* [in] Ptr to field/param data type */
1118    unsigned short      dim             /* [in] Array dimension to check */
1119)
1120{
1121    AST_array_n_t       *array_p;       /* Ptr to array node */
1122    AST_array_index_n_t *index_p = NULL;       /* Ptr to array index node */
1123    AST_type_n_t        *ref_type_p;    /* Ptr to size info field/param type */
1124    AST_type_n_t        *deref_type_p = NULL;  /* Dereferenced field/param type */
1125    NAMETABLE_id_t      ref_name = 0;       /* Field/param name */
1126    boolean             is_ref_ptr = false;     /* TRUE => ref_type_p is [ref] ptr */
1127
1128    /*
1129     * Assume parser won't put field attribute node on non-arrays.
1130     * An array can be represented either in normal array syntax,
1131     * or as a pointer that has any of the array attributes.
1132     */
1133    if (type_p->kind == AST_array_k)
1134    {
1135        array_p = type_p->type_structure.array;
1136        index_p = &array_p->index_vec[dim];
1137    }
1138    else
1139        array_p = NULL;
1140
1141    /* Pick up [max_is] field or parameter reference, if any. */
1142
1143    if (fattr_p->max_is_vec != NULL
1144        &&  fattr_p->max_is_vec[dim].valid
1145        &&  fattr_p->max_is_vec[dim].constant == false)
1146    {
1147        if (node_p->fe_info->node_kind == fe_field_n_k)
1148        {
1149            ref_type_p = fattr_p->max_is_vec[dim].ref.f_ref->type;
1150            ref_name   = fattr_p->max_is_vec[dim].ref.f_ref->name;
1151            is_ref_ptr = (AST_REF_SET(fattr_p->max_is_vec[dim].ref.f_ref));
1152        }
1153        else
1154        {
1155            ref_type_p = fattr_p->max_is_vec[dim].ref.p_ref->type;
1156            ref_name   = fattr_p->max_is_vec[dim].ref.p_ref->name;
1157            is_ref_ptr = (AST_REF_SET(fattr_p->max_is_vec[dim].ref.p_ref));
1158        }
1159
1160        /*
1161         * Param/field referenced in [max_is] might be a ptr.  Chase ptr
1162         * to its base type.  This sets deref_type_p->fe_info->pointer_count
1163         * to the number of dereferences needed to get to the base type.
1164         */
1165        deref_type_p = ASTP_chase_ptr_to_type(ref_type_p);
1166    }
1167
1168    /* [max_is] variable <var> invalid: upper bound fixed in dimension <n> */
1169
1170    if (array_p != NULL
1171        &&  fattr_p->max_is_vec != NULL
1172        &&  (!type_is_array(type_p)
1173            ||  (type_is_array(type_p)
1174                &&  fattr_p->max_is_vec[dim].valid
1175                &&  AST_FIXED_UPPER_SET(index_p))))
1176        CHECKER_error(fattr_p, NIDL_MAXCFMTYPE, dim+1);
1177
1178    /* Constants are excused from further checks */
1179
1180    if (fattr_p->max_is_vec != NULL
1181        &&  fattr_p->max_is_vec[dim].valid
1182        &&  fattr_p->max_is_vec[dim].constant == true)
1183        return;
1184
1185    /* [max_is] variable must be of type integer */
1186
1187    if (fattr_p->max_is_vec != NULL
1188        &&  fattr_p->max_is_vec[dim].valid) {
1189
1190        assert(deref_type_p != NULL);
1191
1192        if (!type_is_index(deref_type_p)
1193                ||  deref_type_p->fe_info->pointer_count
1194                    != fattr_p->max_is_vec[dim].fe_info->pointer_count)
1195            CHECKER_error(fattr_p, NIDL_MAXTYPEINT);
1196
1197        /* A size attribute variable must not have a represent_as type */
1198
1199        if (deref_type_p->rep_as_type != NULL)
1200            CHECKER_error(fattr_p, NIDL_SIZEVARREPAS);
1201
1202        /* A size attribute variable must not have a transmit_as type */
1203
1204        if (deref_type_p->xmit_as_type != NULL)
1205            CHECKER_error(fattr_p, NIDL_SIZEVARXMITAS);
1206
1207        /* The array size attr var 'name' can not have [ptr] or [unique] attr */
1208
1209        if (deref_type_p->fe_info->pointer_count > 0
1210            &&  !is_ref_ptr)
1211        {
1212            char const *id_name;       /* [max_is] variable name */
1213
1214            NAMETABLE_id_to_string(ref_name, &id_name);
1215
1216            CHECKER_error(fattr_p, NIDL_SIZEPRMPTR, id_name);
1217        }
1218    }
1219}
1220
1221/*
1222**  f a t t r _ s i z e _ i s
1223**
1224**  Checks a field attribute node's [size_is] attribute.
1225*/
1226
1227static void fattr_size_is
1228(
1229    AST_field_attr_n_t  *fattr_p,       /* [in] Ptr to AST field attr. node */
1230    ASTP_node_t         *node_p,        /* [in] Ptr to field or param node */
1231    AST_type_n_t        *type_p,        /* [in] Ptr to field/param data type */
1232    unsigned short      dim             /* [in] Array dimension to check */
1233)
1234{
1235    AST_array_n_t       *array_p;       /* Ptr to array node */
1236    AST_array_index_n_t *index_p = NULL;       /* Ptr to array index node */
1237    AST_type_n_t        *ref_type_p;    /* Ptr to size info field/param type */
1238    AST_type_n_t        *deref_type_p = NULL;  /* Dereferenced field/param type */
1239    NAMETABLE_id_t      ref_name = 0;       /* Field/param name */
1240    boolean             is_ref_ptr = false;     /* TRUE => ref_type_p is [ref] ptr */
1241
1242    /*
1243     * Assume parser won't put field attribute node on non-arrays.
1244     * An array can be represented either in normal array syntax,
1245     * or as a pointer that has any of the array attributes.
1246     */
1247    if (type_p->kind == AST_array_k)
1248    {
1249        array_p = type_p->type_structure.array;
1250        index_p = &array_p->index_vec[dim];
1251    }
1252    else
1253        array_p = NULL;
1254
1255    /* Pick up [size_is] field or parameter reference, if any. */
1256
1257    if (fattr_p->size_is_vec != NULL
1258        &&  fattr_p->size_is_vec[dim].valid
1259        &&  fattr_p->size_is_vec[dim].constant == false)
1260    {
1261        if (node_p->fe_info->node_kind == fe_field_n_k)
1262        {
1263            ref_type_p = fattr_p->size_is_vec[dim].ref.f_ref->type;
1264            ref_name   = fattr_p->size_is_vec[dim].ref.f_ref->name;
1265            is_ref_ptr = (AST_REF_SET(fattr_p->size_is_vec[dim].ref.f_ref));
1266        }
1267        else
1268        {
1269            ref_type_p = fattr_p->size_is_vec[dim].ref.p_ref->type;
1270            ref_name   = fattr_p->size_is_vec[dim].ref.p_ref->name;
1271            is_ref_ptr = (AST_REF_SET(fattr_p->size_is_vec[dim].ref.p_ref));
1272        }
1273
1274        /*
1275         * Param/field referenced in [size_is] might be a ptr.  Chase ptr
1276         * to its base type.  This sets deref_type_p->fe_info->pointer_count
1277         * to the number of dereferences needed to get to the base type.
1278         */
1279        deref_type_p = ASTP_chase_ptr_to_type(ref_type_p);
1280    }
1281
1282    /* [size_is] variable <var> invalid: upper bound fixed in dimension <n> */
1283
1284    if (array_p != NULL
1285        &&  fattr_p->size_is_vec != NULL
1286        &&  (!type_is_array(type_p)
1287            ||  (type_is_array(type_p)
1288                &&  fattr_p->size_is_vec[dim].valid
1289                &&  AST_FIXED_UPPER_SET(index_p))))
1290        CHECKER_error(fattr_p, NIDL_SIZECFMTYPE, dim+1);
1291
1292    /* Constants are excused from further checks */
1293
1294    if (fattr_p->size_is_vec != NULL
1295        &&  fattr_p->size_is_vec[dim].valid
1296        &&  fattr_p->size_is_vec[dim].constant == true)
1297        return;
1298
1299    /* [size_is] variable must be of type integer */
1300
1301    if (fattr_p->size_is_vec != NULL
1302        &&  fattr_p->size_is_vec[dim].valid) {
1303
1304        assert(deref_type_p != NULL);
1305
1306        if (!type_is_index(deref_type_p)
1307                ||  deref_type_p->fe_info->pointer_count
1308                    != fattr_p->size_is_vec[dim].fe_info->pointer_count)
1309            CHECKER_error(fattr_p, NIDL_SIZETYPEINT);
1310
1311        /* A size attribute variable must not have a represent_as type */
1312
1313        if (deref_type_p->rep_as_type != NULL)
1314            CHECKER_error(fattr_p, NIDL_SIZEVARREPAS);
1315
1316        /* A size attribute variable must not have a transmit_as type */
1317
1318        if (deref_type_p->xmit_as_type != NULL)
1319            CHECKER_error(fattr_p, NIDL_SIZEVARXMITAS);
1320
1321        /* The array size attr var 'name' can not have [ptr] or [unique] attr */
1322
1323        if (deref_type_p->fe_info->pointer_count > 0
1324            &&  !is_ref_ptr)
1325        {
1326            char const *id_name;       /* [size_is] variable name */
1327
1328            NAMETABLE_id_to_string(ref_name, &id_name);
1329
1330            CHECKER_error(fattr_p, NIDL_SIZEPRMPTR, id_name);
1331        }
1332    }
1333}
1334
1335/*
1336**  f a t t r _ p a r a m _ c o n f o r m a n t
1337**
1338**  Checks an field attribute node associated with a parameter node to make
1339**  sure that a conformant array's size information parameters have the [in]
1340**  parameter attribute.
1341*/
1342
1343static void fattr_param_conformant
1344(
1345    AST_field_attr_n_t  *fattr_p,       /* [in] Ptr to AST field attr. node */
1346    AST_parameter_n_t   *param_p,       /* [in] Ptr to associated param node */
1347    AST_interface_n_t   *int_p,         /* [in] Ptr to interface node */
1348    unsigned short      dim             /* [in] Array dimension */
1349)
1350{
1351    /* [min_is] parameter must have [in] attribute */
1352
1353    if (!AST_LOCAL_SET(int_p)
1354        &&  param_p->type->xmit_as_type == NULL
1355        &&  fattr_p->min_is_vec != NULL
1356        &&  fattr_p->min_is_vec[dim].valid
1357        &&  fattr_p->min_is_vec[dim].constant == false
1358        &&  AST_IN_SET(param_p)
1359        &&  !AST_IN_SET(fattr_p->min_is_vec[dim].ref.p_ref))
1360        CHECKER_error(fattr_p, NIDL_MININATTR);
1361
1362    /* [max_is] parameter must have [in] attribute */
1363
1364    if (!AST_LOCAL_SET(int_p)
1365        &&  param_p->type->xmit_as_type == NULL
1366        &&  fattr_p->max_is_vec != NULL
1367        &&  fattr_p->max_is_vec[dim].valid
1368        &&  fattr_p->max_is_vec[dim].constant == false
1369        &&  AST_IN_SET(param_p)
1370        &&  !AST_IN_SET(fattr_p->max_is_vec[dim].ref.p_ref))
1371        CHECKER_error(fattr_p, NIDL_MAXINATTR);
1372
1373    /* [size_is] parameter must have [in] attribute */
1374
1375    if (!AST_LOCAL_SET(int_p)
1376        &&  param_p->type->xmit_as_type == NULL
1377        &&  fattr_p->size_is_vec != NULL
1378        &&  fattr_p->size_is_vec[dim].valid
1379        &&  fattr_p->size_is_vec[dim].constant == false
1380        &&  AST_IN_SET(param_p)
1381        &&  !AST_IN_SET(fattr_p->size_is_vec[dim].ref.p_ref))
1382        CHECKER_error(fattr_p, NIDL_SIZEINATTR);
1383}
1384
1385/*
1386**  f a t t r _ p a r a m _ v a r y i n g
1387**
1388**  Checks an field attribute node associated with a parameter node to make
1389**  sure that a varying array's directional attributes are consistent with
1390**  the corresponding size information parameter's directional attributes.
1391*/
1392
1393static void fattr_param_varying
1394(
1395    AST_field_attr_n_t  *fattr_p,       /* [in] Ptr to AST field attr. node */
1396    AST_parameter_n_t   *param_p,       /* [in] Ptr to associated param node */
1397    AST_interface_n_t   *int_p,         /* [in] Ptr to interface node */
1398    unsigned short      dim             /* [in] Array dimension */
1399)
1400{
1401    /* [first_is] parameter must have [in] attribute */
1402
1403    if (!AST_LOCAL_SET(int_p)
1404        &&  param_p->type->xmit_as_type == NULL
1405        &&  fattr_p->first_is_vec != NULL
1406        &&  fattr_p->first_is_vec[dim].valid
1407        &&  fattr_p->first_is_vec[dim].constant == false
1408        &&  AST_IN_SET(param_p)
1409        &&  !AST_IN_SET(fattr_p->first_is_vec[dim].ref.p_ref))
1410        CHECKER_error(fattr_p, NIDL_FIRSTINATTR);
1411
1412    /* [last_is] parameter must have [in] attribute */
1413
1414    if (!AST_LOCAL_SET(int_p)
1415        &&  param_p->type->xmit_as_type == NULL
1416        &&  fattr_p->last_is_vec != NULL
1417        &&  fattr_p->last_is_vec[dim].valid
1418        &&  fattr_p->last_is_vec[dim].constant == false
1419        &&  AST_IN_SET(param_p)
1420        &&  !AST_IN_SET(fattr_p->last_is_vec[dim].ref.p_ref))
1421        CHECKER_error(fattr_p, NIDL_LASTINATTR);
1422
1423    /* [length_is] parameter must have [in] attribute */
1424
1425    if (!AST_LOCAL_SET(int_p)
1426        &&  param_p->type->xmit_as_type == NULL
1427        &&  fattr_p->length_is_vec != NULL
1428        &&  fattr_p->length_is_vec[dim].valid
1429        &&  fattr_p->length_is_vec[dim].constant == false
1430        &&  AST_IN_SET(param_p)
1431        &&  !AST_IN_SET(fattr_p->length_is_vec[dim].ref.p_ref))
1432        CHECKER_error(fattr_p, NIDL_LENINATTR);
1433}
1434
1435/*
1436**  f a t t r _ p a r a m _ c h e c k
1437**
1438**  Checks an AST field attribute node.  This set of checks is specific to
1439**  field attribute nodes associated with parameters.  (Field attribute nodes
1440**  can also occur in field nodes).
1441*/
1442
1443static void fattr_param_check
1444(
1445    AST_field_attr_n_t  *fattr_p,       /* [in] Ptr to AST field attr. node */
1446    AST_parameter_n_t   *param_p,       /* [in] Ptr to associated param node */
1447    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
1448)
1449{
1450    unsigned short      dim;            /* Array dimension */
1451    unsigned short      max_dim;        /* Maximum dimension */
1452    AST_type_n_t        *type_p;        /* Parameter data type */
1453
1454    type_p = param_p->type;
1455
1456    /*
1457     * Assume parser won't put field attribute node on non-arrays.
1458     * An array can be represented either in normal array syntax,
1459     * or as a pointer that has any of the array attributes.
1460     */
1461    if (type_p->kind == AST_array_k)
1462        max_dim = type_p->type_structure.array->index_count;
1463    else
1464        max_dim = 1;    /* Arrays in pointer form can only be 1-dimensional */
1465
1466    /* Check field attributes in each dimension of the array. */
1467
1468    for (dim = 0 ; dim < max_dim ; dim++)
1469    {
1470        fattr_param_conformant(fattr_p, param_p, int_p, dim);
1471        fattr_param_varying(fattr_p, param_p, int_p, dim);
1472    }
1473}
1474
1475/*
1476**  f a t t r _ c h e c k
1477**
1478**  Checks an AST field attribute node.
1479*/
1480
1481static void fattr_check
1482(
1483    AST_field_attr_n_t  *fattr_p,       /* [in] Ptr to AST field attr. node */
1484    ASTP_node_t         *node_p,        /* [in] Ptr to field or param node */
1485    AST_type_n_t        *type_p,        /* [in] Ptr to field/param data type */
1486    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
1487)
1488{
1489    unsigned short      dim;            /* Array dimension */
1490    unsigned short      max_dim;        /* Maximum dimension */
1491
1492    /*
1493     * Assume parser won't put field attribute node on non-arrays.
1494     * An array can be represented either in normal array syntax,
1495     * or as a pointer that has any of the array attributes.
1496     */
1497    if (type_p->kind == AST_array_k)
1498        max_dim = type_p->type_structure.array->index_count;
1499    else
1500        max_dim = 1;    /* Arrays in pointer form can only be 1-dimensional */
1501
1502    /* [max_is,length_is] or [size_is,last_is] used together */
1503
1504    if (    ((fattr_p->max_is_vec != NULL) && (fattr_p->length_is_vec != NULL))
1505        ||  ((fattr_p->size_is_vec != NULL) && (fattr_p->last_is_vec != NULL)))
1506        CHECKER_warning(fattr_p, NIDL_MIXEDARRATTR);
1507
1508    fattr_switch_is(fattr_p, node_p, type_p);
1509    /* Check field attributes in each dimension of the array. */
1510
1511    for (dim = 0 ; dim < max_dim ; dim++)
1512    {
1513        fattr_check_size(fattr_p, node_p, type_p, int_p, dim);
1514        fattr_first_is(fattr_p, node_p, dim);
1515        fattr_last_is(fattr_p, node_p, dim);
1516        fattr_length_is(fattr_p, node_p, dim);
1517        fattr_min_is(fattr_p, node_p, type_p, dim);
1518        fattr_max_is(fattr_p, node_p, type_p, dim);
1519        fattr_size_is(fattr_p, node_p, type_p, dim);
1520    }
1521}
1522
1523/*
1524**  i n d e x _ c o n s t _ t y p e
1525**
1526**  Checks an array index node's constant type.
1527*/
1528
1529static void index_const_type
1530(
1531    AST_array_index_n_t *index_p        /* [in] Ptr to AST array index node */
1532)
1533{
1534    /* Invalid array index type */
1535
1536    if ((AST_FIXED_LOWER_SET(index_p)
1537            && !const_is_integer(index_p->lower_bound))
1538        ||
1539        (AST_FIXED_UPPER_SET(index_p)
1540            && !const_is_integer(index_p->upper_bound)))
1541        CHECKER_error(index_p, NIDL_INVARRIND);
1542}
1543
1544/*
1545**  i n d e x _ b o u n d s
1546**
1547**  Checks an array index node's bounds.
1548*/
1549
1550static void index_bounds
1551(
1552    AST_array_index_n_t *index_p        /* [in] Ptr to AST array index node */
1553)
1554{
1555    /* Lower bound must not be greater than upper bound */
1556
1557    if (AST_FIXED_LOWER_SET(index_p)
1558        &&  AST_FIXED_UPPER_SET(index_p)
1559        &&  index_p->lower_bound->value.int_val
1560            > index_p->upper_bound->value.int_val)
1561        CHECKER_error(index_p, NIDL_LBLESSUB);
1562
1563    /* Arrays with a nonzero lower bound require -standard extended */
1564
1565    if (   (!AST_FIXED_LOWER_SET(index_p)
1566            || index_p->lower_bound->value.int_val != 0)
1567        && (*(int *)cmd_val[opt_standard] <= opt_standard_dce_1_0) )
1568        CHECKER_warning(index_p, NIDL_NOPORTNZLB, OPT_STD_EXTENDED);
1569}
1570
1571/*
1572**  i n d e x _ c h e c k
1573**
1574**  Checks an AST array index node.
1575*/
1576
1577static void index_check
1578(
1579    AST_array_index_n_t *index_p        /* [in] Ptr to AST array index node */
1580)
1581{
1582    index_const_type(index_p);
1583    index_bounds(index_p);
1584}
1585
1586/*
1587**  a r r a y _ e l e m e n t _ t y p e
1588**
1589**  Checks the data type of the elements of an array.
1590*/
1591
1592static void array_element_type
1593(
1594    ASTP_node_t         *node_p,        /* [in] Ptr to array or pointer node */
1595    AST_type_n_t        *type_p,        /* [in] Ptr to array elem type node */
1596    AST_type_n_t        *arr_type_p,    /* [in] Ptr to array | ptr type node */
1597    AST_interface_n_t   *int_p,          /* [in] Ptr to interface node */
1598    boolean             arrayified      /* [in] true if arrayified pointer */
1599)
1600{
1601	AST_type_n_t        *etype_p;       /* Array element presented type */
1602
1603	/* If the array element type is anonymous, it must undergo type checks. */
1604
1605	if (type_is_anonymous(type_p))
1606		type_check(type_p, (ASTP_node_t *)node_p, int_p);
1607
1608	etype_p = type_p;
1609	type_p = type_xmit_type(type_p);    /* Pick up transmissible type */
1610
1611	/*
1612	 * Array elements cannot be conformant arrays or structures
1613	 * Exceptions: Array elements types that are the target of a [transmit_as]
1614	 * and have determinable size (i.e. either [string] or a struct).
1615	 */
1616	if (AST_CONFORMANT_SET(type_p)
1617			&& !(etype_p != type_p && AST_STRING_SET(type_p))
1618			&& !(etype_p != type_p && type_p->kind == AST_structure_k) )
1619		CHECKER_error(node_p, NIDL_ARRELEMCFMT);
1620
1621	/* Array elements cannot be pipes */
1622
1623	if (type_p->kind == AST_pipe_k)
1624		CHECKER_error(node_p, NIDL_ARRELEMPIPE);
1625
1626	/* Array elements cannot be context handles */
1627
1628	if (AST_CONTEXT_RD_SET(type_p))
1629		CHECKER_error(node_p, NIDL_ARRELEMCTX);
1630
1631	/* Function pointers are not valid as elements of conformant arrays */
1632
1633	if (!AST_LOCAL_SET(int_p)
1634			&&  type_is_function(type_p)
1635			&&  (AST_CONFORMANT_SET(arr_type_p) || arrayified))
1636		CHECKER_error(node_p, NIDL_FPCFMTARR);
1637
1638	/* Array elements cannot be of type handle_t */
1639
1640	if (!AST_LOCAL_SET(int_p)
1641			&&  type_p->kind == AST_handle_k)
1642#if 0   /** Obsolete **/
1643		&&  type_p->xmit_as_type == NULL)
1644#endif
1645			CHECKER_error(node_p, NIDL_HANARRELEM);
1646
1647	/* void is valid only in an operation or pointer declaration */
1648
1649	if (type_p->kind == AST_void_k)
1650		CHECKER_error(node_p, NIDL_VOIDOPPTR);
1651
1652	/* void * must be used in conjunction with the [context_handle] attribute */
1653
1654	if (!AST_LOCAL_SET(int_p)
1655#if 0   /** Obsolete **/
1656			&&  type_p->xmit_as_type == NULL
1657#endif
1658			&&  type_p->kind == AST_pointer_k
1659			&&  type_p->type_structure.pointer->pointee_type->kind == AST_void_k
1660			&&  !AST_CONTEXT_RD_SET(type_p)
1661			)
1662	{
1663		CHECKER_error(node_p, NIDL_PTRVOIDCTX);
1664	}
1665
1666	/* The [ignore] attribute is not allowed on array elements */
1667
1668	if (AST_IGNORE_SET(type_p))
1669		CHECKER_error(node_p, NIDL_IGNARRELEM);
1670}
1671
1672/*
1673**  a r r a y _ c h e c k
1674**
1675**  Checks an array.  Note that both array and pointer nodes can
1676**  represent arrays.
1677*/
1678
1679static void array_check
1680(
1681    ASTP_node_t         *node_p,        /* [in] Ptr to array or pointer node */
1682    AST_type_n_t        *arr_type_p,    /* [in] Array or ptr type node */
1683    ASTP_node_t         *parent_p,      /* [in] Parent of array or ptr type */
1684    AST_type_n_t        *type_p,        /* [in] Ptr to array elem type node */
1685    AST_interface_n_t   *int_p,         /* [in] Ptr to interface node */
1686    boolean             arrayified      /* [in] true if arrayified pointer */
1687)
1688{
1689    unsigned short      dim;            /* Array dimension */
1690
1691    /* Arrays with [transmit_as] can't be conformant or varying */
1692
1693    if (arr_type_p->xmit_as_type != NULL
1694        &&  (AST_CONFORMANT_SET(arr_type_p)
1695            ||  (parent_p->fe_info->node_kind == fe_parameter_n_k
1696                &&  ((AST_parameter_n_t *)parent_p)->field_attrs != NULL)
1697            ||  (parent_p->fe_info->node_kind == fe_field_n_k
1698                &&  ((AST_field_n_t *)parent_p)->field_attrs != NULL)))
1699        CHECKER_error(parent_p, NIDL_ARRXMITOPEN);
1700
1701    array_element_type(node_p, type_p, arr_type_p, int_p, arrayified);
1702
1703    /* Arrays of non-encapsulated unions are not allowed */
1704
1705    if (type_p->kind == AST_disc_union_k
1706        &&  type_p->type_structure.disc_union->discrim_name == NAMETABLE_NIL_ID)
1707        CHECKER_error(arr_type_p, NIDL_NEUARRAY);
1708
1709	/* Don't allow arrays of interfaces */
1710	 if (type_p->kind == AST_interface_k)	{
1711		 char const * id_name;
1712		 NAMETABLE_id_to_string(type_p->name, &id_name);
1713		 CHECKER_error(arr_type_p, NIDL_INTREFNOTALO, id_name);
1714	 }
1715
1716    /*
1717     * If the array is represented in array (as opposed to pointer) syntax,
1718     * then check the indices of each dimension of the array.
1719     */
1720    if (node_p->fe_info->node_kind == fe_array_n_k)
1721    {
1722        AST_array_n_t       *array_p;   /* Ptr to array node */
1723
1724        array_p = (AST_array_n_t *)node_p;
1725
1726        for (dim = 0
1727            ;   dim < array_p->index_count
1728            ;   dim++)
1729            index_check(&array_p->index_vec[dim]);
1730    }
1731}
1732
1733/*
1734**  p a r a m _ t y p e
1735**
1736**  Checks an parameter node's data type.
1737*/
1738
1739static void param_type
1740(
1741    AST_parameter_n_t   *param_p,       /* [in] Ptr to AST parameter node */
1742    AST_type_n_t        *top_type_p,    /* [in] Top-level parameter type */
1743    AST_type_n_t        *type_p,        /* [in] Parameter type */
1744    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
1745)
1746{
1747#if 0
1748    AST_type_n_t        *btype_p;       /* Base type */
1749
1750    /*
1751     * First, special case checks that do want to look at a toplevel [ref]
1752     * pointer (most look through this pointer).
1753     */
1754
1755    /* Cannot have more than one level of indirection to a ne union */
1756
1757    btype_p = ASTP_chase_ptr_to_kind(top_type_p, AST_disc_union_k);
1758
1759    if (btype_p != NULL
1760        &&  btype_p->kind == AST_disc_union_k
1761        &&  btype_p->type_structure.disc_union->discrim_name == NAMETABLE_NIL_ID
1762        &&  btype_p->fe_info->pointer_count > 1)
1763        CHECKER_error(top_type_p, NIDL_PTRNEUNION);
1764#endif
1765
1766    /*
1767     * If the parameter type is anonymous, it must undergo type checks.
1768     * Note that the passed type_p is the dereferenced parameter type if
1769     * pass-by-reference mechanism was implied; i.e. top-level *'s that
1770     * indicate pass-by-reference and are not arrays are not type-checked.
1771     */
1772    if (type_is_anonymous(type_p))
1773        type_check(type_p, (ASTP_node_t *)param_p, int_p);
1774
1775    type_p = type_xmit_type(type_p);    /* Pick up transmissible type */
1776
1777    /* void is valid only in an operation or pointer declaration */
1778
1779    if (type_p->kind == AST_void_k
1780        &&  param_p != param_p->uplink->result) /* Not the result param */
1781        CHECKER_error(param_p, NIDL_VOIDOPPTR);
1782
1783    /* void * must be used in conjunction with the [context_handle] attr */
1784
1785    if (!AST_LOCAL_SET(int_p)
1786        &&  type_p->xmit_as_type == NULL /* Allow if void* is NOT transmitted */
1787        &&  type_p->kind == AST_pointer_k
1788        &&  type_p->type_structure.pointer->pointee_type->kind == AST_void_k
1789        &&  !AST_CONTEXT_RD_SET(type_p)
1790        &&  !AST_CONTEXT_SET(param_p)
1791		&& !AST_LOCAL_SET(param_p->uplink)
1792		  )
1793        CHECKER_error(param_p, NIDL_PTRVOIDCTX);
1794
1795    /* A type with [transmit_as] may not have other type attributes */
1796
1797    if (top_type_p->xmit_as_type != NULL
1798        &&
1799        (AST_STRING_SET(param_p)
1800         || AST_STRING0_SET(param_p)
1801         || AST_UNIQUE_SET(param_p)
1802         || AST_SMALL_SET(param_p)
1803         || AST_CONTEXT_SET(param_p)
1804         ))
1805        CHECKER_error(param_p, NIDL_XMITTYPEATTRS);
1806
1807    /*
1808     * V1 attributes are incompatible with this type
1809     * Note: Issue error only if the same error doesn't fire for the type.
1810     */
1811    if (FE_TEST(param_p->fe_info->flags, FE_HAS_V1_ATTR)
1812        &&  FE_TEST(param_p->fe_info->flags, FE_HAS_V2_ATTR)
1813        &&  ! ( FE_TEST(type_p->fe_info->flags, FE_HAS_V1_ATTR)
1814                &&  FE_TEST(type_p->fe_info->flags, FE_HAS_V2_ATTR) ))
1815        CHECKER_warning(param_p, NIDL_INCOMPATV1);
1816
1817    /* Array function results are not allowed */
1818
1819    if (type_p->kind == AST_array_k
1820        && param_p == param_p->uplink->result)
1821        CHECKER_error(param_p, NIDL_ARRFUNRES);
1822}
1823
1824/*
1825**  p a r a m _ s i z e
1826**
1827**  Checks an parameter node to see if array size information is required.
1828*/
1829
1830static void param_size
1831(
1832    AST_parameter_n_t   *param_p,       /* [in] Ptr to AST parameter node */
1833    AST_type_n_t        *top_type_p,    /* [in] Top-level parameter type */
1834    AST_type_n_t        *type_p,        /* [in] Parameter type */
1835    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
1836)
1837{
1838    AST_field_attr_n_t  *fattr_p;       /* Field attributes */
1839
1840    fattr_p = param_p->field_attrs;
1841
1842    /* Array size information required */
1843
1844    if (!AST_LOCAL_SET(int_p)
1845        &&  type_p->xmit_as_type == NULL
1846        &&  fattr_p == NULL
1847        &&  type_is_array(type_p)
1848        &&  (AST_CONFORMANT_SET(type_p)
1849            ||  AST_VARYING_SET(param_p))
1850        &&  !AST_STRING_SET(type_p)     /* [string] cases handled below */
1851        &&  !AST_STRING_SET(param_p))
1852    {
1853        char const *id_name;
1854
1855        NAMETABLE_id_to_string(param_p->name, &id_name);
1856        CHECKER_error(param_p, NIDL_ARRSIZEINFO, id_name);
1857    }
1858
1859    /*
1860     * Array size information required on conformant [string] arrays only
1861     * if an [out]-only parameter; otherwise, size is implicitly determined
1862     * by the length of the string.  Size info is not required for a [ptr]
1863     * char * string (which includes an operation result char * string)
1864     * or a [unique] char * string.
1865     */
1866    if (!AST_LOCAL_SET(int_p)
1867        &&  type_p->xmit_as_type == NULL
1868        &&  fattr_p == NULL
1869        &&  (   (type_p->kind == AST_array_k
1870                &&  AST_CONFORMANT_SET(type_p))
1871             || (type_p->kind == AST_pointer_k
1872                &&  param_p->uplink->result != param_p  /* not op result */
1873                &&  !AST_PTR_SET(type_p) && !AST_UNIQUE_SET(type_p)) )
1874        &&  (AST_STRING_SET(type_p) || AST_STRING_SET(param_p))
1875        &&  !AST_IN_SET(param_p))
1876    {
1877        char const *id_name;
1878
1879        NAMETABLE_id_to_string(param_p->name, &id_name);
1880        CHECKER_error(param_p, NIDL_ARRSIZEINFO, id_name);
1881    }
1882
1883    /* A [string] array can not have varying array attributes */
1884
1885    if (!AST_LOCAL_SET(int_p)
1886        &&  type_p->xmit_as_type == NULL
1887        &&  AST_STRING_SET(param_p)
1888        &&  fattr_p != NULL
1889        &&  (fattr_p->first_is_vec != NULL
1890            ||  fattr_p->last_is_vec != NULL
1891            ||  fattr_p->length_is_vec != NULL))
1892        CHECKER_error(param_p, NIDL_STRVARY);
1893
1894    /* Arrays with [transmit_as] can't be conformant or varying */
1895
1896    if (type_p->xmit_as_type != NULL
1897        &&  fattr_p != NULL)
1898        CHECKER_error(param_p, NIDL_ARRXMITOPEN);
1899
1900    /*
1901     * Current rules allow mixed open array [] and pointer * syntax ONLY
1902     * of the form *..*param[][N]..[N], i.e. when param is a [multidimensional]
1903     * array of pointers (that, currently, can be conformant or varying in the
1904     * first dimension only).  Pointers to open arrays are not allowed due to
1905     * the ambiguity as to which * or [] the array size attributes apply to.
1906     *
1907     * Builder only allows one open array dimension when pointer and array
1908     * syntax is mixed.  It will detect errors on such examples as:
1909     *      [in, size_is(s1,s2)] long (*param)[]
1910     *
1911     * A corollary is that in declarations with more than one * and no [] or
1912     * [N], array size information applies to the rightmost * only.
1913     * Builder will detect errors on such examples as:
1914     *      [in, size_is(s1,s2)] long **param
1915     *
1916     * Checker detects these 3 cases separately:
1917     *      [in, size_is(s)] long (*..*param)[N]..[N]       ARRSYNTAX
1918     *      [in, size_is(s)] long (*..*param)[][N]..[N]     PTRCFMTARR
1919     *      [in, length_is(l)] long (*..*param)[N]..[N]     PTRVARYARR
1920     */
1921    if (top_type_p->kind == AST_pointer_k)
1922    {
1923        AST_type_n_t    *ref_type_p;    /* Pointee data type */
1924
1925        ref_type_p = ASTP_chase_ptr_to_type(top_type_p);
1926
1927        /* Use array syntax to declare multidimensional arrays */
1928
1929        if (ref_type_p->kind == AST_array_k
1930            &&  !AST_CONFORMANT_SET(ref_type_p)
1931            &&  fattr_p != NULL
1932            &&  (fattr_p->min_is_vec != NULL
1933                ||  fattr_p->max_is_vec != NULL
1934                ||  fattr_p->size_is_vec != NULL))
1935            CHECKER_error(param_p, NIDL_ARRSYNTAX);
1936
1937        /* Pointers to conformant arrays are not allowed */
1938
1939        /*
1940         * Can't just check for conformant set since a string can be conformant
1941         * and not require size attributes; a ptr to such a string is legal.
1942         */
1943        if (ref_type_p->kind == AST_array_k
1944            &&  AST_CONFORMANT_SET(ref_type_p)
1945            &&  (!AST_STRING_SET(ref_type_p)
1946                ||  (fattr_p != NULL
1947                    &&  (fattr_p->min_is_vec != NULL
1948                        ||  fattr_p->max_is_vec != NULL
1949                        ||  fattr_p->size_is_vec != NULL))))
1950        {
1951            CHECKER_error(param_p, NIDL_PTRCFMTARR);
1952            return;     /* Return with no further checking */
1953        }
1954
1955        /* Pointers to varying arrays are not allowed */
1956
1957        /*
1958         * Can't just check for varying set since a string is implicitly vary-
1959         * ing and cannot have length attrs; a ptr to such a string is legal.
1960         */
1961        if (ref_type_p->kind == AST_array_k
1962            &&  fattr_p != NULL
1963            &&  (fattr_p->first_is_vec != NULL
1964                ||  fattr_p->last_is_vec != NULL
1965                ||  fattr_p->length_is_vec != NULL))
1966        {
1967            CHECKER_error(param_p, NIDL_PTRVARYARR);
1968            return;     /* Return with no further checking */
1969        }
1970    }
1971
1972    /* An [out] conformant array must be a top-level param or under a full pointer */
1973
1974    /*
1975     * Note that this check covers any [out] conformant array below top-level
1976     * that is not under a full pointer.  Top-level [out] conformant arrays
1977     * are handled by the ARRSIZEINFO and *INATTR checks.
1978     */
1979    if (!AST_LOCAL_SET(int_p)
1980        &&  param_p->type->xmit_as_type == NULL
1981        &&  !AST_IN_SET(param_p)
1982        &&  FE_TEST(param_p->fe_info->flags, FE_HAS_CFMT_ARR))
1983        CHECKER_error(param_p, NIDL_OUTCFMTARR);
1984}
1985
1986/*
1987**  p a r a m _ s t r u c t
1988**
1989**  Checks a parameter node - structure specific checks.
1990*/
1991
1992static void param_struct
1993(
1994    AST_parameter_n_t   *param_p,       /* [in] Ptr to AST parameter node */
1995    AST_type_n_t        *top_type_p,    /* [in] Top-level parameter type */
1996    AST_type_n_t        *type_p         /* [in] Parameter type */
1997)
1998{
1999    type_p = type_xmit_type(type_p);    /* Pick up transmissible type */
2000
2001    /* All checks below assume that parameter data type is structure. */
2002
2003    if (type_p->kind != AST_structure_k)
2004        return;
2005
2006    /* Structures containing conformant arrays must be passed by reference */
2007
2008    if (!AST_OUT_SET(param_p)
2009        &&  top_type_p->kind != AST_pointer_k
2010        &&  AST_CONFORMANT_SET(type_p))
2011        CHECKER_error(param_p, NIDL_CFMTARRREF);
2012}
2013
2014/*
2015**  p a r a m _ p i p e
2016**
2017**  Checks a parameter node - pipe specific checks.
2018*/
2019
2020static void param_pipe
2021(
2022    AST_parameter_n_t   *param_p,       /* [in] Ptr to AST parameter node */
2023    AST_type_n_t        *top_type_p ATTRIBUTE_UNUSED,    /* [in] Top-level parameter type */
2024    AST_type_n_t        *type_p         /* [in] Parameter type */
2025)
2026{
2027    type_p = type_xmit_type(type_p);    /* Pick up transmissible type */
2028
2029    /* [ptr] attribute not valid on pipe parameters */
2030
2031    if (type_p->kind == AST_pipe_k
2032        &&  AST_PTR_SET(param_p))
2033        CHECKER_error(param_p, NIDL_PTRPIPE);
2034
2035    /* Operation result may not be a pipe */
2036
2037    if (param_p == param_p->uplink->result
2038        &&  type_p->kind == AST_pipe_k)
2039        CHECKER_error(param_p, NIDL_OPRESPIPE);
2040}
2041
2042/*
2043**  p a r a m _ i n _ l i n e
2044**
2045**  Checks an parameter node's [in_line] and [out_of_line] attributes.
2046*/
2047
2048static void param_in_line
2049(
2050    AST_parameter_n_t   *param_p,       /* [in] Ptr to AST parameter node */
2051    AST_type_n_t        *type_p         /* [in] Parameter type */
2052)
2053{
2054    /* Can't have both [in_line] and [out_of_line] parameter attributes */
2055
2056    if (AST_IN_LINE_SET(param_p)
2057        &&  AST_OUT_OF_LINE_SET(param_p))
2058        CHECKER_acf_error(param_p, NIDL_PRMLINEATTR);
2059
2060    /* [in_line] and [out_of_line] attributes apply only to non-scalar types */
2061
2062    if ((AST_IN_LINE_SET(param_p) || AST_OUT_OF_LINE_SET(param_p))
2063        &&  type_is_scalar(type_p))
2064    {
2065        char const *file_name;     /* Related file name */
2066        char const *type_name;     /* Data type name */
2067
2068        STRTAB_str_to_string(type_p->fe_info->file, &file_name);
2069        NAMETABLE_id_to_string(type_p->name, &type_name);
2070
2071        CHECKER_acf_warning(param_p, NIDL_LINENONSCAL);
2072        CHECKER_acf_warning(param_p, NIDL_NAMEDECLAT, type_name, file_name,
2073                          type_p->fe_info->source_line);
2074    }
2075}
2076
2077/*
2078**  p a r a m _ s t r i n g
2079**
2080**  Checks an parameter node's [string] and [v1_string] attributes.
2081*/
2082
2083static void param_string
2084(
2085    AST_parameter_n_t   *param_p,       /* [in] Ptr to AST parameter node */
2086    AST_type_n_t        *type_p         /* [in] Parameter type */
2087)
2088{
2089    /* A [v1_string] must be an array of char with fixed bounds */
2090
2091    if (AST_STRING0_SET(param_p)
2092        &&  !type_is_v1_string(type_p))
2093        CHECKER_error(param_p, NIDL_STRV1FIXED);
2094
2095    /* The [v1_string] attribute can only be applied to a [v1_array] */
2096
2097    if ((AST_STRING0_SET(param_p) || AST_STRING0_SET(type_p))
2098        &&  !(AST_SMALL_SET(param_p) || AST_SMALL_SET(type_p)))
2099        CHECKER_error(param_p, NIDL_STRV1ARRAY);
2100
2101    /* The [string] attribute cannot be applied to a [v1_array] */
2102
2103    if ((AST_STRING_SET(param_p) && AST_SMALL_SET(param_p))
2104        ||  (AST_STRING_SET(param_p) && AST_SMALL_SET(type_p))
2105        ||  (AST_STRING_SET(type_p) && AST_SMALL_SET(param_p)))
2106        CHECKER_error(param_p, NIDL_STRARRAYV1);
2107
2108    /* Cannot have both [string] and [v1_string] attributes */
2109
2110    if (    (AST_STRING_SET(param_p) || AST_STRING_SET(type_p))
2111        &&  (AST_STRING0_SET(param_p) || AST_STRING0_SET(type_p))   )
2112    {
2113        ASTP_attr_flag_t attr1 = ASTP_STRING;
2114        ASTP_attr_flag_t attr2 = ASTP_STRING0;
2115
2116        CHECKER_error(param_p, NIDL_CONFLICTATTR,
2117            KEYWORDS_lookup_text(AST_attribute_to_token(&attr1)),
2118            KEYWORDS_lookup_text(AST_attribute_to_token(&attr2)));
2119    }
2120
2121    /*
2122     * Forgo last check if the declaration is a pointer to an array and either
2123     * (the declaration has size attributes) or (the array is conformant and
2124     * not a string), since mixed pointer and array declarations that either
2125     * have or require array size attributes are disallowed by other checks.
2126     */
2127    if (type_p->kind == AST_pointer_k)
2128    {
2129        AST_type_n_t    *ref_type_p;    /* Pointee data type */
2130
2131        ref_type_p = ASTP_chase_ptr_to_type(type_p);
2132        if (ref_type_p->kind == AST_array_k
2133            &&  (param_p->field_attrs != NULL
2134                ||  (AST_CONFORMANT_SET(ref_type_p)
2135                    &&  !AST_STRING_SET(ref_type_p))))
2136            return;
2137    }
2138
2139    /* [string] attribute valid only for one-dim arrays of char or byte */
2140
2141    if (AST_STRING_SET(param_p)
2142        &&  !type_is_string(param_p->type))
2143        CHECKER_error(param_p, NIDL_STRCHARBYTE);
2144}
2145
2146/*
2147**  p a r a m _ p o i n t e r
2148**
2149**  Checks an parameter node's attributes related to pointers.
2150*/
2151
2152static void param_pointer
2153(
2154    AST_parameter_n_t   *param_p,       /* [in] Ptr to AST parameter node */
2155    AST_type_n_t        *top_type_p,    /* [in] Top-level parameter type */
2156    AST_type_n_t        *type_p,        /* [in] Parameter type */
2157    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
2158)
2159{
2160    boolean pointer_attr_valid = FALSE;
2161
2162    /*
2163     *  The AST Builder catches these errors on param ptr attributes:
2164     *      [ref] parameter requires explicit top-level '*'
2165     *      [ptr] parameter requires explicit top-level '*'
2166     *      [unique] parameter requires explicit top-level '*'
2167     */
2168
2169    /* [out,ptr] parameters are not allowed */
2170
2171    if (AST_OUT_SET(param_p)
2172        &&  !AST_IN_SET(param_p)
2173        &&  AST_PTR_SET(param_p)
2174        &&  param_p->uplink->result != param_p) /* Not the result param */
2175        CHECKER_error(param_p, NIDL_OUTPTRPRM);
2176
2177    /* [out,unique] parameters are not allowed */
2178
2179    if (AST_OUT_SET(param_p)
2180        &&  !AST_IN_SET(param_p)
2181        &&  AST_UNIQUE_SET(param_p)
2182        &&  param_p->uplink->result != param_p) /* Not the result param */
2183        CHECKER_error(param_p, NIDL_OUTUNIQPRM);
2184
2185    /* [ref] function results are not valid */
2186
2187    if (param_p->uplink->result == param_p      /* IS the result param */
2188        &&  AST_REF_SET(param_p))
2189        CHECKER_error(param_p, NIDL_REFFUNRES);
2190
2191    /* [unique] function results are not valid */
2192
2193    if (param_p->uplink->result == param_p      /* IS the result param */
2194        &&  AST_UNIQUE_SET(param_p))
2195        CHECKER_error(param_p, NIDL_UNIQFUNRES);
2196
2197    if (top_type_p->kind == AST_array_k
2198        ||  (top_type_p->kind == AST_pointer_k
2199            &&  top_type_p->type_structure.pointer->pointee_type->kind
2200                != AST_void_k))
2201        pointer_attr_valid = TRUE;
2202
2203    /* [ref] attribute valid only for pointer or array types */
2204
2205    if (AST_REF_SET(param_p) && !pointer_attr_valid)
2206        CHECKER_error(param_p, NIDL_REFATTRPTR);
2207
2208    /* [unique] attribute valid only for pointer or array types */
2209
2210    if (AST_UNIQUE_SET(param_p) && !pointer_attr_valid)
2211        CHECKER_error(param_p, NIDL_UNIQATTRPTR);
2212
2213    /* [ptr] attribute valid only for pointer or array types */
2214
2215    if (AST_PTR_SET(param_p) && !pointer_attr_valid)
2216        CHECKER_error(param_p, NIDL_PTRATTRPTR);
2217
2218    /* [unique] attribute requires -standard extended */
2219
2220    if (AST_UNIQUE_SET(param_p)
2221        &&  (*(int *)cmd_val[opt_standard] <= opt_standard_dce_1_0))
2222        CHECKER_warning(param_p, NIDL_NOPORTUNIQUE, OPT_STD_EXTENDED);
2223
2224#if 0
2225	/* if the parameter is a pointer to an interface, then it should ignore
2226	 * the pointer attributes REF, UNIQUE or PTR */
2227	 if (top_type_p->kind == AST_pointer_k && type_p->kind == AST_interface_k
2228			 && AST_REF_SET(param_p))
2229		 CHECKER_warning(param_p, NIDL_PTRATTBIGN);
2230	 if (type_p->kind == AST_pointer_k && type_p->type_structure.pointer->pointee_type->kind == AST_interface_k
2231			 && (AST_UNIQUE_SET(param_p) || AST_PTR_SET(param_p)))
2232		 CHECKER_warning(param_p, NIDL_PTRATTBIGN);
2233#endif
2234
2235    /*
2236     * If the parameter is a pointer, and it is not a pointer to an array,
2237     * and it has any of the array attributes, then it is an arrayified
2238     * pointer and it must undergo the checks for arrays.
2239     */
2240    if (type_p->kind == AST_pointer_k
2241        &&  type_p->type_structure.pointer->pointee_type->kind != AST_array_k
2242#if 0
2243        &&  (param_p->field_attrs != NULL
2244#endif
2245        &&  (instance_has_array_attr(param_p)
2246            ||  AST_STRING_SET(type_p)
2247            ||  AST_STRING_SET(param_p)))
2248    {
2249        array_check((ASTP_node_t *)type_p->type_structure.pointer,
2250                    type_p,
2251                    (ASTP_node_t *)param_p,
2252                    type_p->type_structure.pointer->pointee_type,
2253                    int_p,
2254                    true);
2255
2256        /*  <7810113> [in, out,unique] parameters are not allowed for arrays */
2257        if (AST_OUT_SET(param_p)
2258            &&  AST_IN_SET(param_p)
2259            &&  AST_UNIQUE_SET(param_p)
2260            &&  param_p->uplink->result != param_p) /* Not the result param */
2261            CHECKER_error(param_p, NIDL_OUTUNIQPRM);
2262    }
2263}
2264
2265/*
2266**  p a r a m _ s m a l l
2267**
2268**  Checks an parameter node's [v1_array] attribute.
2269*/
2270
2271static void param_small
2272(
2273    AST_parameter_n_t   *param_p,       /* [in] Ptr to AST parameter node */
2274    AST_type_n_t        *top_type_p,    /* [in] Top-level parameter type */
2275    AST_type_n_t        *type_p        /* [in] Parameter type */
2276)
2277{
2278    AST_array_n_t       *array_p;       /* Ptr to array node */
2279    AST_field_attr_n_t  *fattr_p;       /* Ptr to field attribute node */
2280
2281    /* A [v1_array] must be in array, not pointer, syntax */
2282
2283    if (AST_SMALL_SET(param_p)
2284        &&  (type_p->kind == AST_pointer_k
2285            ||  top_type_p->kind == AST_pointer_k))
2286        CHECKER_error(param_p, NIDL_SMALLARRSYN);
2287
2288    /*
2289     * Remaining checks only apply to array types in array syntax.
2290     * V1 did not allow arrays in pointer syntax.
2291     */
2292    if (!type_is_array_np(type_p))
2293        return;
2294
2295    fattr_p = param_p->field_attrs;
2296    array_p = type_p->type_structure.array;
2297
2298    /* A [v1_array] can be conformant or varying in the first dimension only */
2299
2300    if (AST_SMALL_SET(param_p)
2301        &&  ((AST_CONFORMANT_SET(type_p)
2302                && array_is_conformant_upper(array_p))
2303            ||
2304            (AST_VARYING_SET(param_p)
2305                && instance_is_varying_upper(array_p, param_p->field_attrs))))
2306        CHECKER_error(param_p, NIDL_SMALLMULTID);
2307
2308    /* [v1_array] attribute invalid for array with more than 65535 elements */
2309
2310    if (AST_SMALL_SET(param_p)
2311        &&  array_is_large(array_p))
2312        CHECKER_error(param_p, NIDL_SMALLINV);
2313
2314    /* A conformant [v1_array] must also be varying */
2315
2316    if ((AST_SMALL_SET(type_p) || AST_SMALL_SET(param_p))
2317        &&  AST_CONFORMANT_SET(type_p)
2318        &&  !AST_VARYING_SET(param_p))
2319        CHECKER_error(param_p, NIDL_SMALLCFMT);
2320
2321    /* A [v1_array] can not have the [min_is] or [first_is] attributes */
2322
2323    if ((AST_SMALL_SET(type_p) || AST_SMALL_SET(param_p))
2324        &&  fattr_p != NULL
2325        &&  (fattr_p->min_is_vec != NULL
2326            ||  fattr_p->first_is_vec != NULL))
2327        CHECKER_error(param_p, NIDL_SMALLMINFIRST);
2328}
2329
2330/*
2331**  p a r a m _ c o n t e x t
2332**
2333**  Checks an parameter node's [context_handle] attribute.
2334*/
2335
2336static void param_context
2337(
2338    AST_parameter_n_t   *param_p,       /* [in] Ptr to AST parameter node */
2339    AST_type_n_t        *top_type_p,    /* [in] Top-level parameter type */
2340    AST_type_n_t        *type_p         /* [in] Parameter type */
2341)
2342{
2343    AST_type_n_t        *deref_type_p;  /* Explicit pointer's pointee type */
2344    boolean             type_is_pointer;/* Type is real pointer, not void* */
2345
2346    deref_type_p = param_follow_ref_ptr(param_p, CHK_follow_any);
2347    /*
2348     * Special case code to follow an operation result pointer.  This allows
2349     * us to catch and disallow pointer to context handle operation results.
2350     */
2351    if (param_p->uplink->result == param_p
2352        &&  type_p->kind == AST_pointer_k
2353        &&  type_p->type_structure.pointer->pointee_type->kind != AST_void_k)
2354        deref_type_p = type_p->type_structure.pointer->pointee_type;
2355
2356    /* [context_handle] attribute only applies to void * types */
2357
2358    if (AST_CONTEXT_SET(param_p)
2359        &&  !AST_CONTEXT_RD_SET(type_p) /* no error if already done for type */
2360        &&  (deref_type_p->kind != AST_pointer_k
2361            ||  (deref_type_p->kind == AST_pointer_k
2362                &&  deref_type_p->type_structure.pointer->pointee_type->kind
2363                    != AST_void_k)))
2364            CHECKER_error(param_p, NIDL_CTXPTRVOID);
2365
2366    type_is_pointer = (deref_type_p != top_type_p);
2367
2368    /* [unique] pointers to context handles are not allowed */
2369
2370    if (type_is_pointer
2371        &&  (AST_CONTEXT_SET(param_p) || AST_CONTEXT_RD_SET(deref_type_p))
2372        &&  AST_UNIQUE_SET(param_p))
2373        CHECKER_error(param_p, NIDL_UNIQCTXHAN);
2374
2375    /* Full pointers to context handles are not allowed */
2376
2377    if (type_is_pointer
2378        &&  (AST_CONTEXT_SET(param_p) || AST_CONTEXT_RD_SET(deref_type_p))
2379        &&  AST_PTR_SET(param_p)
2380        &&  deref_type_p->kind != AST_structure_k)  /* opaque ctx handle */
2381        CHECKER_error(param_p, NIDL_PTRCTXHAN);
2382}
2383
2384/*
2385**  p a r a m _ v a r y i n g
2386**
2387**  Checks an parameter node's "varying" (synthesized) attribute.
2388*/
2389
2390static void param_varying
2391(
2392    AST_parameter_n_t   *param_p,       /* [in] Ptr to AST parameter node */
2393    AST_type_n_t        *type_p,        /* [in] Parameter type */
2394    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
2395)
2396{
2397    /*
2398     * Assume that if the varying attribute is set, the parameter is an
2399     * array type and the field_attrs field is valid.  An array can be
2400     * represented either in normal array syntax, or as a pointer that
2401     * has any of the array attributes.
2402     */
2403    if (type_p->kind != AST_array_k)
2404        return;     /* All checks below assume normal array syntax */
2405
2406    /* Arrays varying in other than the first dim require -standard extended */
2407
2408    if (!AST_LOCAL_SET(int_p)
2409        &&  type_p->xmit_as_type == NULL
2410        &&  AST_VARYING_SET(param_p)
2411        &&  instance_is_varying_upper(type_p->type_structure.array,
2412                                      param_p->field_attrs)
2413        &&  (*(int *)cmd_val[opt_standard] <= opt_standard_dce_1_0))
2414        CHECKER_warning(param_p, NIDL_NOPORTVARY, OPT_STD_EXTENDED);
2415}
2416
2417/*
2418**  p a r a m _ d i r e c t i o n
2419**
2420**  Checks an parameter node's [in] and [out] attributes.
2421*/
2422
2423static void param_direction
2424(
2425    AST_parameter_n_t   *param_p,       /* [in] Ptr to AST parameter node */
2426    AST_type_n_t        *top_type_p,    /* [in] Top-level parameter type */
2427    AST_type_n_t        *type_p,        /* [in] Parameter type */
2428    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
2429)
2430{
2431    type_p = type_xmit_type(type_p);    /* Pick up transmissible type */
2432
2433    /* Parameter must have a least one of [in] and [out] attributes */
2434
2435    if (type_p->kind != AST_void_k
2436		  &&  !AST_LOCAL_SET(int_p)
2437        &&  !AST_IN_SET(param_p)
2438        &&  !AST_OUT_SET(param_p))
2439        CHECKER_error(param_p, NIDL_PRMINOROUT);
2440
2441    /* [out] parameters must be passed by reference */
2442
2443    if (AST_OUT_SET(param_p)
2444        &&  top_type_p->kind != AST_array_k /* Arrays are implicitly by ref */
2445        &&  param_p->uplink->result != param_p      /* Not the result param */
2446        &&  ((top_type_p->kind != AST_pointer_k
2447             && top_type_p->kind != AST_pipe_k)     /* Pipes an exception */
2448          || (top_type_p->kind == AST_pointer_k     /* void * is special */
2449             && top_type_p->type_structure.pointer->pointee_type->kind
2450                == AST_void_k)
2451			 || (top_type_p->kind == AST_pointer_k
2452				 && top_type_p->type_structure.pointer->pointee_type->kind == AST_interface_k)
2453			 ))
2454        CHECKER_error(param_p, NIDL_OUTPRMREF);
2455
2456    /* [out] parameter requires explicit top-level '*' */
2457
2458    if (!AST_LOCAL_SET(int_p)
2459        &&  AST_OUT_SET(param_p)
2460        &&  param_p->uplink->result != param_p  /* Not the result param */
2461        &&  top_type_p->kind == AST_pointer_k
2462        &&  top_type_p->type_structure.pointer->pointee_type->kind
2463            != AST_function_k               /* Func ptrs an exception */
2464        &&  top_type_p->name != NAMETABLE_NIL_ID)
2465        CHECKER_error(param_p, NIDL_OUTSTAR);
2466
2467    /* Function pointer parameters can only be [in] parameters */
2468
2469    if (AST_OUT_SET(param_p)
2470        &&  type_p->kind == AST_pointer_k
2471        &&  type_p->type_structure.pointer->pointee_type->kind
2472            == AST_function_k)
2473        CHECKER_error(param_p, NIDL_FPINPRM);
2474
2475    /* [in(shape)] is not yet supported */
2476
2477    if (AST_IN_SHAPE_SET(param_p))
2478        CHECKER_error(param_p, NIDL_NYSINSHAPE);
2479
2480    /* [out(shape)] is not yet supported */
2481
2482    if (AST_OUT_SHAPE_SET(param_p))
2483        CHECKER_error(param_p, NIDL_NYSOUTSHAPE);
2484
2485    if (type_p->kind == AST_pointer_k)
2486        type_p = ASTP_chase_ptr_to_kind(type_p, AST_disc_union_k);
2487
2488    /* An [in] or [in,out] union must have an [in] discriminator */
2489
2490    if (AST_IN_SET(param_p)
2491        &&  type_p != NULL
2492        &&  type_p->kind == AST_disc_union_k
2493        &&  type_p->type_structure.disc_union->discrim_name == NAMETABLE_NIL_ID
2494        &&  param_p->field_attrs != NULL
2495        &&  param_p->field_attrs->switch_is != NULL
2496        &&  !AST_IN_SET(param_p->field_attrs->switch_is->ref.p_ref))
2497        CHECKER_error(param_p, NIDL_DISCRIMIN);
2498
2499    /* An [in,out] or [out] union must have an [out] discriminator */
2500
2501#if 0
2502    if (AST_OUT_SET(param_p)
2503        &&  type_p != NULL
2504        &&  type_p->kind == AST_disc_union_k
2505        &&  type_p->type_structure.disc_union->discrim_name == NAMETABLE_NIL_ID
2506        &&  param_p->field_attrs != NULL
2507        &&  param_p->field_attrs->switch_is != NULL
2508        &&  !AST_OUT_SET(param_p->field_attrs->switch_is->ref.p_ref))
2509        CHECKER_error(param_p, NIDL_DISCRIMOUT);
2510#endif
2511
2512}
2513
2514/*
2515**  p a r a m _ c o m m _ s t a t u s
2516**
2517**  Checks an parameter node's [comm_status] attribute.
2518*/
2519
2520static void param_comm_status
2521(
2522    AST_parameter_n_t   *param_p,       /* [in] Ptr to AST parameter node */
2523    AST_type_n_t        *type_p         /* [in] Parameter type */
2524)
2525{
2526    char const *type_name;     /* Data type name */
2527
2528    /* [comm_status] parameter must be an [out] parameter */
2529
2530    if (AST_COMM_STATUS_SET(param_p)
2531        &&  param_p != param_p->uplink->result  /* Op result special cased */
2532        &&  !AST_OUT_SET(param_p))
2533        CHECKER_error(param_p, NIDL_STSPRMOUT,
2534            acf_keyword_lookup(COMM_STATUS_KW));
2535
2536    /* [fault_status] parameter must be an [out] parameter */
2537
2538    if (AST_FAULT_STATUS_SET(param_p)
2539        &&  param_p != param_p->uplink->result  /* Op result special cased */
2540        &&  !AST_OUT_SET(param_p))
2541        CHECKER_error(param_p, NIDL_STSPRMOUT,
2542            acf_keyword_lookup(FAULT_STATUS_KW));
2543
2544    /* Chase type down to base named type. */
2545
2546    while (type_p->defined_as != NULL)
2547        type_p = type_p->defined_as;
2548    NAMETABLE_id_to_string(type_p->name, &type_name);
2549
2550    /* [comm_status] parameter must be of type error_status_t */
2551
2552    if (AST_COMM_STATUS_SET(param_p)
2553        &&  param_p != param_p->uplink->result  /* Op result special cased */
2554        &&  strcmp(type_name, "error_status_t") != 0)
2555        CHECKER_error(param_p, NIDL_STSVARTYPE,
2556            acf_keyword_lookup(COMM_STATUS_KW));
2557
2558    /* [fault_status] parameter must be of type error_status_t */
2559
2560    if (AST_FAULT_STATUS_SET(param_p)
2561        &&  param_p != param_p->uplink->result  /* Op result special cased */
2562        &&  strcmp(type_name, "error_status_t") != 0)
2563        CHECKER_error(param_p, NIDL_STSVARTYPE,
2564            acf_keyword_lookup(FAULT_STATUS_KW));
2565
2566    /* A [comm_status] operation must return a value of type error_status_t */
2567
2568    if (AST_COMM_STATUS_SET(param_p)
2569        &&  param_p == param_p->uplink->result  /* The operation result */
2570        &&  strcmp(type_name, "error_status_t") != 0)
2571        CHECKER_error(param_p->uplink, NIDL_STSRETVAL,
2572            acf_keyword_lookup(COMM_STATUS_KW));
2573
2574    /* A [fault_status] operation must return a value of type error_status_t */
2575
2576    if (AST_FAULT_STATUS_SET(param_p)
2577        &&  param_p == param_p->uplink->result  /* The operation result */
2578        &&  strcmp(type_name, "error_status_t") != 0)
2579        CHECKER_error(param_p->uplink, NIDL_STSRETVAL,
2580            acf_keyword_lookup(FAULT_STATUS_KW));
2581}
2582static void param_switch_is
2583(
2584    AST_parameter_n_t   *param_p,       /* [in] Ptr to AST parameter node */
2585    AST_type_n_t        *type_p         /* [in] Parameter type */
2586)
2587{
2588    if (type_p->kind == AST_pointer_k)
2589        type_p = ASTP_chase_ptr_to_kind(type_p, AST_disc_union_k);
2590
2591    /* A non-encapsulated union declaration must have a [switch_is] attribute */
2592
2593    if (type_p != NULL
2594        &&  type_p->kind == AST_disc_union_k
2595        &&  type_p->type_structure.disc_union->discrim_name == NAMETABLE_NIL_ID
2596        &&  (param_p->field_attrs == NULL
2597            ||  param_p->field_attrs->switch_is == NULL))
2598        CHECKER_error(param_p, NIDL_NEUSWATTR);
2599}
2600
2601/*
2602**  p a r a m _ f i r s t _ h a n d l e
2603**
2604**  Checks a parameter node's first parameter to make sure it is a
2605**  handle if explicit handles are in use.
2606*/
2607
2608static void param_first_handle
2609(
2610    AST_parameter_n_t   *param_p,       /* [in] Ptr to AST parameter node */
2611    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
2612)
2613{
2614    AST_operation_n_t   *op_p;          /* Operation containing the parameter */
2615    AST_type_n_t        *type_p;        /* Param type (deref'd if necess.) */
2616
2617    op_p = param_p->uplink;
2618
2619    /*
2620     * If the parameter type has a top-level '*' which indicates passing
2621     * mechanism only, follow the pointer to the data of interest.
2622     *      top_type_p  = top-level parameter type
2623     *      type_p      = possibly dereferenced parameter type
2624     */
2625    type_p = param_follow_ref_ptr(param_p, CHK_follow_any);
2626
2627    /* No binding handle parameter for 'operation' - auto_handle assumed. */
2628
2629    if (int_p->implicit_handle_name == NAMETABLE_NIL_ID
2630			 && !AST_OBJECT_SET(int_p)
2631        &&  !AST_AUTO_HANDLE_SET(int_p)
2632        &&  !AST_LOCAL_SET(int_p)
2633        &&  !type_is_handle(type_p)
2634        &&  !AST_HAS_IN_CTX_SET(op_p))
2635        default_to_auto_handle(op_p, NIDL_DEFAUTOHAN);
2636#if 0   /** Don't default to auto_handle for op ct. [in,out] context handles **/
2637    else if (int_p->implicit_handle_name == NAMETABLE_NIL_ID
2638        &&  !AST_AUTO_HANDLE_SET(int_p)
2639        &&  !AST_LOCAL_SET(int_p)
2640        &&  !type_is_handle(type_p)
2641        &&  AST_HAS_IN_OUT_CTX_SET(op_p))
2642        default_to_auto_handle(op_p, NIDL_POSSAUTOHAN);
2643#endif
2644
2645    /* handle_t binding parameter must be an [in] parameter */
2646
2647    if (!AST_LOCAL_SET(int_p)
2648        &&  type_p->kind == AST_handle_k
2649        &&  (!AST_IN_SET(param_p) || AST_OUT_SET(param_p)))
2650        CHECKER_error(param_p, NIDL_HANPRMIN);
2651
2652    /* [handle] binding parameter must be an in parameter */
2653
2654    if (!AST_LOCAL_SET(int_p)
2655        &&  AST_HANDLE_SET(type_p)
2656        &&  !AST_IN_SET(param_p))
2657        CHECKER_error(param_p, NIDL_HANDLEIN);
2658
2659    /* [ptr] attribute invalid on binding handle parameter */
2660
2661    if (!AST_LOCAL_SET(int_p)
2662        &&  type_is_handle(type_p)
2663        &&  AST_PTR_SET(param_p))
2664        CHECKER_error(param_p, NIDL_PTRATTRHAN);
2665
2666    /* [unique] attribute invalid on binding handle parameter */
2667
2668    if (!AST_LOCAL_SET(int_p)
2669        &&  type_is_handle(type_p)
2670        &&  AST_UNIQUE_SET(param_p))
2671        CHECKER_error(param_p, NIDL_UNIQATTRHAN);
2672
2673    /* handle_t first parameter must not have [transmit_as] type */
2674
2675    if (!AST_LOCAL_SET(int_p)
2676        &&  type_p->kind == AST_handle_k
2677        &&  !AST_HANDLE_SET(type_p)
2678        &&  type_p->xmit_as_type != NULL)
2679        CHECKER_error(param_p, NIDL_HANXMITAS);
2680
2681    /* Type with [transmit_as] cannot be used in defn of type with [handle] */
2682
2683    if (AST_HANDLE_SET(type_p)
2684        &&  type_p->defined_as != NULL
2685        &&  FE_TEST(type_p->defined_as->fe_info->flags, FE_HAS_XMIT_AS))
2686    {
2687        ASTP_attr_flag_t attr1 = ASTP_TRANSMIT_AS;
2688        ASTP_attr_flag_t attr2 = ASTP_HANDLE;
2689        CHECKER_error(param_p, NIDL_TYPEATTRUSE,
2690            KEYWORDS_lookup_text(AST_attribute_to_token(&attr1)),
2691            KEYWORDS_lookup_text(AST_attribute_to_token(&attr2)));
2692    }
2693
2694    /* Type with [handle] cannot be used in defn of type with [transmit_as] */
2695
2696    if (type_p->xmit_as_type != NULL
2697        &&  type_p->defined_as != NULL
2698        &&  AST_HANDLE_SET(type_p->defined_as))
2699    {
2700        ASTP_attr_flag_t attr1 = ASTP_HANDLE;
2701        ASTP_attr_flag_t attr2 = ASTP_TRANSMIT_AS;
2702        CHECKER_error(param_p, NIDL_TYPEATTRUSE,
2703            KEYWORDS_lookup_text(AST_attribute_to_token(&attr1)),
2704            KEYWORDS_lookup_text(AST_attribute_to_token(&attr2)));
2705    }
2706}
2707
2708/*
2709**  p a r a m _ c h e c k _ f i r s t
2710**
2711**  Checks an AST parameter node.  This set of checks applies only to
2712**  the first parameter in an operation.
2713*/
2714
2715static void param_check_first
2716(
2717    AST_parameter_n_t   *param_p,       /* [in] Ptr to AST parameter node */
2718    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
2719)
2720{
2721    param_first_handle(param_p, int_p);
2722}
2723
2724/*
2725**  p a r a m _ c h e c k _ n o n _ h a n d l e
2726**
2727**  Checks an AST parameter node.  This check applies only to parameters
2728**  in an operation that can not be handles.
2729*/
2730
2731static void param_check_non_handle
2732(
2733    AST_parameter_n_t   *param_p,       /* [in] Ptr to AST parameter node */
2734    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
2735)
2736{
2737    AST_type_n_t        *type_p;        /* Param type (deref'd if necess.) */
2738
2739    /*
2740     * If the parameter type has a top-level '*' which indicates passing
2741     * mechanism only, follow the pointer to the data of interest.
2742     *      top_type_p  = top-level parameter type
2743     *      type_p      = possibly dereferenced parameter type
2744     */
2745    type_p = param_follow_ref_ptr(param_p, CHK_follow_ref);
2746
2747    /* handle_t as other than first parameter requires [transmit_as] */
2748
2749    if (!AST_LOCAL_SET(int_p)
2750        &&  type_p->kind == AST_handle_k
2751        &&  type_p->xmit_as_type == NULL)
2752        CHECKER_error(param_p, NIDL_HANFIRSTPRM);
2753}
2754
2755/*
2756**  p a r a m _ c h e c k
2757**
2758**  Checks an AST parameter node.
2759*/
2760
2761static void param_check
2762(
2763    AST_parameter_n_t   *param_p,       /* [in] Ptr to AST parameter node */
2764    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
2765)
2766{
2767    AST_field_attr_n_t  *fattr_p;       /* Field attributes assoc. with param */
2768    AST_type_n_t        *top_type_p;    /* Top-level parameter type */
2769    AST_type_n_t        *type_p;        /* Param type (deref'd if necess.) */
2770    AST_type_n_t        *deref_type_p;  /* Param type (deref'd if necess.) */
2771
2772    /*
2773     * If the parameter type has a top-level '*' which indicates passing
2774     * mechanism only, follow the pointer to the data of interest.
2775     *      top_type_p   = top-level parameter type
2776     *      type_p       = possibly dereferenced parameter type
2777     *      deref_type_p = possibly dereferenced parameter type
2778     */
2779    top_type_p   = param_p->type;
2780    type_p       = param_follow_ref_ptr(param_p, CHK_follow_ref);
2781    deref_type_p = param_follow_ref_ptr(param_p, CHK_follow_any);
2782
2783    param_type(param_p, top_type_p, type_p, int_p);
2784
2785    /* Check parameter's field attributes, if any. */
2786
2787    fattr_p = param_p->field_attrs;
2788    if (fattr_p != NULL)
2789    {
2790        fattr_check(fattr_p, (ASTP_node_t *)param_p, type_p, int_p);
2791        fattr_param_check(fattr_p, param_p, int_p);
2792    }
2793
2794	/* Interface must have a * */
2795	 if (type_p->kind == AST_interface_k)	{
2796		char const * id_name;
2797		 NAMETABLE_id_to_string(type_p->name, &id_name);
2798		 CHECKER_error(param_p, NIDL_INTREFNOTALO, id_name);
2799	 }
2800
2801    param_size(param_p, top_type_p, type_p, int_p);
2802    param_struct(param_p, top_type_p, type_p);
2803    param_pipe(param_p, top_type_p, deref_type_p);
2804
2805    param_in_line(param_p, type_p);
2806    param_string(param_p, type_p);
2807    param_pointer(param_p, top_type_p, type_p, int_p);
2808    param_small(param_p, top_type_p, type_p);
2809    param_context(param_p, top_type_p, deref_type_p);
2810    param_varying(param_p, type_p, int_p);
2811
2812    param_direction(param_p, top_type_p, type_p, int_p);
2813    param_comm_status(param_p, type_p);
2814    param_switch_is(param_p, type_p);
2815
2816    CHK_param_cs(param_p, type_p);
2817}
2818
2819/*
2820**  o p _ h a n d l e
2821**
2822**  Checks an operation node to see if a handle parameter is required.
2823*/
2824
2825static void op_handle
2826(
2827    AST_operation_n_t   *op_p,          /* [in] Ptr to AST operation node */
2828    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
2829)
2830{
2831    /* No binding handle parameter for 'operation' - auto_handle assumed. */
2832
2833    if (int_p->implicit_handle_name == NAMETABLE_NIL_ID
2834        &&  !AST_AUTO_HANDLE_SET(int_p)
2835        &&  !AST_LOCAL_SET(int_p)
2836		  &&  !AST_OBJECT_SET(int_p)
2837        &&  op_p->parameters == NULL)
2838        default_to_auto_handle(op_p, NIDL_DEFAUTOHAN);
2839}
2840
2841/*
2842**  o p _ c o m m _ s t a t u s
2843**
2844**  Checks an operation node to make sure there is at most 1 comm_status param.
2845*/
2846
2847static void op_comm_status
2848(
2849    AST_operation_n_t   *op_p           /* [in] Ptr to AST operation node */
2850)
2851{
2852    AST_parameter_n_t   *param_p;       /* A parameter in the operation */
2853    int     comm_status_count;          /* Number [comm_status] parameters */
2854    int     fault_status_count;         /* Number [fault_status] parameters */
2855
2856    comm_status_count = 0;
2857    fault_status_count = 0;
2858
2859    if (AST_COMM_STATUS_SET(op_p->result))
2860        comm_status_count++;
2861    if (AST_FAULT_STATUS_SET(op_p->result))
2862        fault_status_count++;
2863
2864    for (param_p = op_p->parameters; param_p != NULL; param_p = param_p->next)
2865    {
2866        if (AST_COMM_STATUS_SET(param_p) || AST_ADD_COMM_STATUS_SET(param_p))
2867            comm_status_count++;
2868        if (AST_FAULT_STATUS_SET(param_p) || AST_ADD_FAULT_STATUS_SET(param_p))
2869            fault_status_count++;
2870    }
2871
2872    /* Operation can have at most one [comm_status] parameter */
2873
2874    if (comm_status_count > 1)
2875        CHECKER_acf_error(op_p, NIDL_STSATTRONCE,
2876            acf_keyword_lookup(COMM_STATUS_KW));
2877
2878    /* Operation can have at most one [fault_status] parameter */
2879
2880    if (fault_status_count > 1)
2881        CHECKER_acf_error(op_p, NIDL_STSATTRONCE,
2882            acf_keyword_lookup(FAULT_STATUS_KW));
2883}
2884
2885/*
2886**  o p _ b r o a d c a s t
2887**
2888**  Checks an operation node's [broadcast] attribute.
2889*/
2890
2891static void op_broadcast
2892(
2893    AST_operation_n_t   *op_p           /* [in] Ptr to AST operation node */
2894)
2895{
2896    /* Can't have [broadcast] attribute on operation with pipes */
2897
2898    if (AST_BROADCAST_SET(op_p)
2899        &&  (AST_HAS_IN_PIPES_SET(op_p) || AST_HAS_OUT_PIPES_SET(op_p)))
2900        CHECKER_error(op_p, NIDL_BROADPIPE);
2901}
2902
2903/*
2904**  o p _ m a y b e
2905**
2906**  Checks an operation node's [maybe] attribute.
2907*/
2908
2909static void op_maybe
2910(
2911    AST_operation_n_t   *op_p           /* [in] Ptr to AST operation node */
2912)
2913{
2914    /* [maybe] operations cannot have [out] parameters */
2915
2916    if (AST_MAYBE_SET(op_p)
2917        &&  (AST_HAS_OUTS_SET(op_p) || AST_HAS_OUT_PIPES_SET(op_p)))
2918        CHECKER_error(op_p, NIDL_MAYBEOUTPRM);
2919}
2920
2921/*
2922**  o p _ c o d e
2923**
2924**  Checks an operation node's [code] and [nocode] attributes.
2925*/
2926
2927static void op_code
2928(
2929    AST_operation_n_t   *op_p           /* [in] Ptr to AST operation node */
2930)
2931{
2932    /* Can't have both [code] and [nocode] operation attributes */
2933
2934    if (AST_CODE_SET(op_p)
2935        &&  AST_NO_CODE_SET(op_p))
2936        CHECKER_acf_error(op_p, NIDL_OPCODEATTR);
2937
2938    /* [nocode] attribute does not apply to server stub */
2939
2940    if (AST_NO_CODE_SET(op_p)
2941        &&  cmd_opt[opt_emit_sstub]
2942        &&  !cmd_opt[opt_emit_cstub])
2943        CHECKER_acf_warning(op_p, NIDL_SRVNOCODE);
2944}
2945
2946/*
2947**  o p _ i d e m p o t e n t
2948**
2949**  Checks an operation node's [idempotent] attribute.
2950*/
2951
2952static void op_idempotent
2953(
2954    AST_operation_n_t   *op_p           /* [in] Ptr to AST operation node */
2955)
2956{
2957    /* Can't have [idempotent] attribute on operation with pipes */
2958
2959    if (AST_IDEMPOTENT_SET(op_p)
2960        &&  !AST_BROADCAST_SET(op_p)    /* broadcast gens its own error */
2961        &&  (AST_HAS_IN_PIPES_SET(op_p) || AST_HAS_OUT_PIPES_SET(op_p)))
2962        CHECKER_error(op_p, NIDL_IDEMPIPE);
2963}
2964
2965/*
2966**  o p _ e n c o d e
2967**
2968**  Checks an operation node's [encode] and [decode] attributes.
2969*/
2970
2971static void op_encode
2972(
2973    AST_operation_n_t   *op_p           /* [in] Ptr to AST operation node */
2974)
2975{
2976    AST_parameter_n_t   *param_p;       /* A parameter in the operation */
2977    AST_parameter_n_t   *p1;            /* First parameter in the operation */
2978    boolean             all_in_out;     /* T => all parameters [in,out] */
2979    boolean             all_in;         /* T => all parameters [in]-only */
2980    boolean             all_out;        /* T => all parameters [out]-only */
2981    boolean             p1_is_handle_t; /* T => p1 non-NULL, type handle_t */
2982
2983    if (AST_NO_CODE_SET(op_p))
2984        return;
2985    if (!AST_ENCODE_SET(op_p) && !AST_DECODE_SET(op_p))
2986        return;
2987
2988    all_in_out = TRUE;
2989    all_in     = TRUE;
2990    all_out    = TRUE;
2991    p1 = op_p->parameters;
2992    if (p1 != NULL
2993        && (p1->type->kind == AST_handle_k
2994            || (p1->type->kind == AST_pointer_k
2995                && p1->type->type_structure.pointer->pointee_type->kind
2996                   == AST_handle_k)))
2997        p1_is_handle_t = TRUE;
2998    else
2999        p1_is_handle_t = FALSE;
3000    param_p = ((p1 != NULL) ? p1 : op_p->result);
3001
3002    while (TRUE)
3003    {
3004        if (AST_IN_SET(param_p) && !AST_OUT_SET(param_p))
3005        {
3006            /* [in]-only (binding handle parameter excluded) */
3007            if ( !(param_p == p1 && p1_is_handle_t) )
3008            {
3009                all_out = FALSE;
3010                all_in_out = FALSE;
3011            }
3012        }
3013        else if (!AST_IN_SET(param_p) && AST_OUT_SET(param_p))
3014        {
3015            /* [out]-only (ACF-added [*_status] parameter excluded) */
3016            if (!AST_ADD_COMM_STATUS_SET(param_p)
3017                && !AST_ADD_FAULT_STATUS_SET(param_p))
3018            {
3019                all_in = FALSE;
3020                all_in_out = FALSE;
3021            }
3022        }
3023        else if (AST_IN_SET(param_p) && AST_OUT_SET(param_p))
3024        {
3025            /* [in,out] */
3026            all_in = FALSE;
3027            all_out = FALSE;
3028        }
3029
3030        /* Operation with [encode] has [out]-only parameter P */
3031        /* Note an ACF-added [*_status] parameter is exception to this rule */
3032        if (AST_ENCODE_SET(op_p) && !AST_DECODE_SET(op_p)
3033            &&  AST_OUT_SET(param_p) && !AST_IN_SET(param_p)
3034            &&  !AST_ADD_COMM_STATUS_SET(param_p)
3035            &&  !AST_ADD_FAULT_STATUS_SET(param_p))
3036        {
3037            char const *id_name;
3038            NAMETABLE_id_to_string(param_p->name, &id_name);
3039            CHECKER_warning(param_p, NIDL_ENCOUTONLY, id_name);
3040        }
3041
3042        /* Operation with [decode] has [in]-only parameter P */
3043        /* Note a handle_t first parameter is an exception to this rule */
3044        if (AST_DECODE_SET(op_p) && !AST_ENCODE_SET(op_p)
3045            &&  AST_IN_SET(param_p) && !AST_OUT_SET(param_p)
3046            &&  !(param_p == p1 && p1_is_handle_t) )
3047        {
3048            char const *id_name;
3049            NAMETABLE_id_to_string(param_p->name, &id_name);
3050            CHECKER_warning(param_p, NIDL_DECINONLY, id_name);
3051        }
3052
3053        /* A [fault_status] parameter has no utility in this operation */
3054        if (AST_FAULT_STATUS_SET(param_p) || AST_ADD_FAULT_STATUS_SET(param_p))
3055            CHECKER_acf_warning(op_p, NIDL_NOFLTPARAM);
3056
3057        /* Update to next parameter or operation result */
3058        if (param_p == op_p->result)
3059            break;
3060        param_p = param_p->next;
3061        if (param_p == NULL)
3062            param_p = op_p->result;
3063    }
3064
3065    /* Operation with [encode] must have at least one [in] or [in,out] param */
3066
3067    if (AST_ENCODE_SET(op_p) && !AST_DECODE_SET(op_p) && all_out)
3068        CHECKER_error(op_p, NIDL_ENCNOPARAMS);
3069
3070    /* Operation with [decode] must have at least one [out] or [in,out] param */
3071
3072    if (AST_DECODE_SET(op_p) && !AST_ENCODE_SET(op_p) && all_in)
3073        CHECKER_error(op_p, NIDL_DECNOPARAMS);
3074
3075    /* Operation with [encode,decode] must have all [in,out] parameters */
3076
3077    if (AST_ENCODE_SET(op_p) && AST_DECODE_SET(op_p) && !all_in_out)
3078        CHECKER_error(op_p, NIDL_ENCDECDIR);
3079
3080    /* Operation with [encode] or [decode] may not contain pipe parameters */
3081
3082    if (   (AST_ENCODE_SET(op_p) || AST_DECODE_SET(op_p))
3083        && (AST_HAS_IN_PIPES_SET(op_p) || AST_HAS_OUT_PIPES_SET(op_p)) )
3084        CHECKER_error(op_p, NIDL_ENCDECPIPE);
3085
3086    /* Operation with [encode] or [decode] must use explicit binding */
3087
3088    /*
3089     * Note: if explicit handle added via ACF attribute, propagator has
3090     * already added a handle_t parameter to the operation.
3091     */
3092    if (   (AST_ENCODE_SET(op_p) || AST_DECODE_SET(op_p))
3093        && !p1_is_handle_t )
3094        CHECKER_error(op_p, NIDL_ENCDECBIND);
3095
3096    /* Use of [encode] attribute requires -standard extended */
3097    if (AST_ENCODE_SET(op_p)
3098        && (*(int *)cmd_val[opt_standard] < opt_standard_dce_1_1))
3099        CHECKER_acf_warning(op_p, NIDL_NOPORTATTR, "encode", OPT_STD_EXTENDED);
3100
3101    /* Use of [decode] attribute requires -standard extended */
3102    if (AST_DECODE_SET(op_p)
3103        && (*(int *)cmd_val[opt_standard] < opt_standard_dce_1_1))
3104        CHECKER_acf_warning(op_p, NIDL_NOPORTATTR, "decode", OPT_STD_EXTENDED);
3105}
3106
3107/*
3108**  o p e r a t i o n _ c h e c k
3109**
3110**  Checks an AST operation node.
3111*/
3112
3113static void operation_check
3114(
3115    AST_operation_n_t   *op_p,          /* [in] Ptr to AST operation node */
3116    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
3117)
3118{
3119    AST_parameter_n_t   *param_p;       /* A parameter in the operation */
3120
3121    op_handle(op_p, int_p);
3122    op_comm_status(op_p);
3123
3124    op_broadcast(op_p);
3125    op_maybe(op_p);
3126    op_code(op_p);
3127    op_idempotent(op_p);
3128    op_encode(op_p);
3129    CHK_op_cs(op_p);
3130
3131    /* Must compile stubs with ANSI C to avoid promotion of float to double */
3132
3133    if (FE_TEST(op_p->fe_info->flags, FE_HAS_VAL_FLOAT)
3134       )
3135    {
3136        char const *id_name;   /* Operation name */
3137
3138        NAMETABLE_id_to_string(op_p->name, &id_name);
3139        CHECKER_warning(op_p, NIDL_FLOATPROM, id_name);
3140    }
3141
3142    /* Operation with [reflect_deletions] has no [in] or [in,out] full ptrs */
3143
3144    if (AST_REFLECT_DELETIONS_SET(op_p)
3145        &&  !FE_TEST(op_p->fe_info->flags, FE_HAS_IN_FULL_PTR))
3146        CHECKER_warning(op_p, NIDL_OPREFDELIN);
3147
3148    /* Use of [reflect_deletions] attribute requires -standard extended */
3149    if (AST_REFLECT_DELETIONS_SET(op_p)
3150        && (*(int *)cmd_val[opt_standard] < opt_standard_dce_1_1))
3151    {
3152        ASTP_attr_flag_t attr1 = ASTP_REFLECT_DELETIONS;
3153        CHECKER_warning(op_p, NIDL_NOPORTATTR,
3154            KEYWORDS_lookup_text(AST_attribute_to_token(&attr1)),
3155            OPT_STD_EXTENDED);
3156    }
3157
3158    /* Check each parameter in the operation. */
3159
3160    param_p = op_p->parameters;
3161    if (param_p != NULL)
3162    {
3163        /* The first parameter in an operation is handled separately. */
3164
3165        param_check_first(param_p, int_p);
3166        param_check(param_p, int_p);
3167
3168        /* Check the remaining parameters, if any. */
3169
3170        while ((param_p = param_p->next) != NULL)
3171        {
3172            param_check_non_handle(param_p, int_p);
3173            param_check(param_p, int_p);
3174        }
3175    }
3176
3177    /* Check the operation result, if any. */
3178
3179    if (op_p->result != NULL)
3180    {
3181        param_check_non_handle(op_p->result, int_p);
3182        param_check(op_p->result, int_p);
3183    }
3184}
3185
3186/*
3187**  f i e l d _ t y p e
3188**
3189**  Checks a field node's data type.
3190*/
3191
3192static void field_type
3193(
3194    AST_field_n_t       *field_p,       /* [in] Ptr to AST field node */
3195    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
3196)
3197{
3198    AST_type_n_t        *type_p;        /* Data type of the field */
3199
3200    type_p = field_p->type;
3201
3202    /* If the field type is anonymous, it must undergo type checks. */
3203
3204    if (type_is_anonymous(type_p))
3205        type_check(type_p, (ASTP_node_t *)field_p, int_p);
3206
3207    /* A type with [transmit_as] may not have other type attributes */
3208
3209    if (type_p->xmit_as_type != NULL
3210        &&
3211        (AST_STRING_SET(field_p)
3212         || AST_STRING0_SET(field_p)
3213         || AST_UNIQUE_SET(field_p)
3214         || AST_REF_SET(field_p)
3215         || AST_IGNORE_SET(field_p)
3216         || AST_SMALL_SET(field_p)
3217         || AST_CONTEXT_SET(field_p)
3218         || AST_PTR_SET(field_p)))
3219        CHECKER_error(field_p, NIDL_XMITTYPEATTRS);
3220
3221    /* A field cannot be of presented type for which xmit type is conformant */
3222
3223    if (type_p->xmit_as_type != NULL
3224        &&  AST_CONFORMANT_SET(type_p->xmit_as_type))
3225        CHECKER_error(field_p, NIDL_FLDXMITCFMT);
3226
3227    type_p = type_xmit_type(type_p);    /* Pick up transmissible type */
3228
3229    /* A conformant field must be the last field in structure */
3230
3231    if (!AST_LOCAL_SET(int_p)
3232        &&  field_p->next != NULL
3233        &&  AST_CONFORMANT_SET(type_p)
3234        &&  type_p->kind != AST_pointer_k)  /* ptr does not make struct cfmt */
3235        CHECKER_error(field_p, NIDL_CFMTFLDLAST);
3236
3237    /* Pipes not valid as structure fields */
3238
3239    if (type_p->kind == AST_pipe_k)
3240        CHECKER_error(field_p, NIDL_PIPESTRFLD);
3241
3242	/* interface must have a * */
3243	 if (type_p->kind == AST_interface_k)	{
3244		 char const * id_name;
3245		 NAMETABLE_id_to_string(type_p->name, &id_name);
3246		 CHECKER_error(field_p, NIDL_INTREFNOTALO, id_name);
3247	 }
3248
3249    /* Context handles not valid as structure fields */
3250
3251    if (AST_CONTEXT_RD_SET(type_p)
3252        ||  AST_CONTEXT_SET(field_p))
3253        CHECKER_error(field_p, NIDL_CTXSTRFLD);
3254
3255    /* Function pointers not valid as structure fields */
3256
3257    if (!AST_LOCAL_SET(int_p)
3258        &&  type_is_function(type_p)
3259        &&  type_p->xmit_as_type == NULL /* allowed if void* is not xmited */
3260		  )
3261        CHECKER_error(field_p, NIDL_FPSTRFLD);
3262
3263    /* Structure fields cannot be of type handle_t */
3264
3265    if (type_p->kind == AST_handle_k)
3266#if 0   /** Obsolete **/
3267        &&  type_p->xmit_as_type == NULL)
3268#endif
3269        CHECKER_error(field_p, NIDL_HANSTRFLD);
3270
3271    /* void is valid only in an operation or pointer declaration */
3272
3273    if (type_p->kind == AST_void_k)
3274        CHECKER_error(field_p, NIDL_VOIDOPPTR);
3275
3276    /* void * must be used in conjunction with the [context_handle] attr */
3277
3278    if (!AST_LOCAL_SET(int_p)
3279        &&  type_p->kind == AST_pointer_k
3280        &&  type_p->type_structure.pointer->pointee_type->kind == AST_void_k
3281        &&  !AST_CONTEXT_RD_SET(type_p)
3282        &&  !AST_CONTEXT_SET(field_p)
3283		  )
3284        CHECKER_error(field_p, NIDL_PTRVOIDCTX);
3285
3286    /*
3287     * V1 attributes are incompatible with this type
3288     * Note: Issue error only if the same error doesn't fire for the type.
3289     */
3290    if (FE_TEST(field_p->fe_info->flags, FE_HAS_V1_ATTR)
3291        &&  FE_TEST(field_p->fe_info->flags, FE_HAS_V2_ATTR)
3292        &&  ! ( FE_TEST(type_p->fe_info->flags, FE_HAS_V1_ATTR)
3293                &&  FE_TEST(type_p->fe_info->flags, FE_HAS_V2_ATTR) ))
3294        CHECKER_warning(field_p, NIDL_INCOMPATV1);
3295}
3296
3297/*
3298**  f i e l d _ s i z e
3299**
3300**  Checks a field node to see if array size information is required.
3301*/
3302
3303static void field_size
3304(
3305    AST_field_n_t       *field_p,       /* [in] Ptr to AST field node */
3306    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
3307)
3308{
3309    AST_type_n_t        *type_p;        /* Data type of the field */
3310    AST_field_attr_n_t  *fattr_p;       /* Field attributes */
3311
3312    type_p = field_p->type;
3313    fattr_p = field_p->field_attrs;
3314
3315    /* Array size information required */
3316
3317    if (!AST_LOCAL_SET(int_p)
3318        &&  type_p->kind != AST_structure_k /* Struct has its own size info */
3319        &&  type_p->xmit_as_type == NULL
3320        &&  fattr_p == NULL
3321        &&  (AST_CONFORMANT_SET(type_p)
3322            ||  AST_VARYING_SET(field_p))
3323        &&  !AST_STRING_SET(type_p)         /* [string] a possible exception */
3324        &&  !AST_STRING_SET(field_p))       /* if used in an [in] param      */
3325    {
3326        char const *id_name;
3327
3328        NAMETABLE_id_to_string(field_p->name, &id_name);
3329        CHECKER_error(field_p, NIDL_ARRSIZEINFO, id_name);
3330    }
3331
3332    /* A [string] array can not have varying array attributes */
3333
3334    if (!AST_LOCAL_SET(int_p)
3335        &&  type_p->xmit_as_type == NULL
3336        &&  AST_STRING_SET(field_p)
3337        &&  fattr_p != NULL
3338        &&  (fattr_p->first_is_vec != NULL
3339            ||  fattr_p->last_is_vec != NULL
3340            ||  fattr_p->length_is_vec != NULL))
3341        CHECKER_error(field_p, NIDL_STRVARY);
3342
3343    /* Arrays with [transmit_as] can't be conformant or varying */
3344
3345    /*
3346     * Note that pointers that represent arrays are excluded from the test.
3347     * Since the instance of the pointer turns it into an array,
3348     * field_pointer calls array_check, which will detect the error.
3349     */
3350    if (type_p->xmit_as_type != NULL
3351        &&  fattr_p != NULL
3352        &&  type_p->kind != AST_pointer_k)
3353        CHECKER_error(field_p, NIDL_ARRXMITOPEN);
3354
3355    /*
3356     * Current rules allow mixed open array [] and pointer * syntax ONLY
3357     * of the form *..*param[][N]..[N], i.e. when param is a [multidimensional]
3358     * array of pointers (that, currently, can be conformant or varying in the
3359     * first dimension only).  Pointers to open arrays are not allowed due to
3360     * the ambiguity as to which * or [] the array size attributes apply to.
3361     *
3362     * Builder only allows one open array dimension when pointer and array
3363     * syntax is mixed.  It will detect errors on such examples as:
3364     *      [in, size_is(s1,s2)] long (*param)[]
3365     *
3366     * A corollary is that in declarations with more than one * and no [] or
3367     * [N], array size information applies to the rightmost * only.
3368     * Builder will detect errors on such examples as:
3369     *      [in, size_is(s1,s2)] long **param
3370     *
3371     * Checker detects these 3 cases separately:
3372     *      [in, size_is(s)] long (*..*param)[N]..[N]       ARRSYNTAX
3373     *      [in, size_is(s)] long (*..*param)[][N]..[N]     PTRCFMTARR
3374     *      [in, length_is(l)] long (*..*param)[N]..[N]     PTRVARYARR
3375     */
3376    if (type_p->kind == AST_pointer_k)
3377    {
3378        AST_type_n_t    *ref_type_p;    /* Pointee data type */
3379
3380        ref_type_p = ASTP_chase_ptr_to_type(type_p);
3381
3382        /* Use array syntax to declare multidimensional arrays */
3383
3384        if (ref_type_p->kind == AST_array_k
3385            &&  !AST_CONFORMANT_SET(ref_type_p)
3386            &&  fattr_p != NULL
3387            &&  (fattr_p->min_is_vec != NULL
3388                ||  fattr_p->max_is_vec != NULL
3389                ||  fattr_p->size_is_vec != NULL))
3390            CHECKER_error(field_p, NIDL_ARRSYNTAX);
3391
3392        /* Pointers to conformant arrays are not allowed */
3393
3394        /*
3395         * Can't just check for conformant set since a string can be conformant
3396         * and not require size attributes; a ptr to such a string is legal.
3397         */
3398        if (ref_type_p->kind == AST_array_k
3399            &&  AST_CONFORMANT_SET(ref_type_p)
3400            &&  (!AST_STRING_SET(ref_type_p)
3401                ||  (fattr_p != NULL
3402                    &&  (fattr_p->min_is_vec != NULL
3403                        ||  fattr_p->max_is_vec != NULL
3404                        ||  fattr_p->size_is_vec != NULL))))
3405        {
3406            CHECKER_error(field_p, NIDL_PTRCFMTARR);
3407            return;     /* Return with no further checking */
3408        }
3409
3410        /* Pointers to varying arrays are not allowed */
3411
3412        /*
3413         * Can't just check for varying set since a string is implicitly vary-
3414         * ing and cannot have length attrs; a ptr to such a string is legal.
3415         */
3416        if (ref_type_p->kind == AST_array_k
3417            &&  fattr_p != NULL
3418            &&  (fattr_p->first_is_vec != NULL
3419                ||  fattr_p->last_is_vec != NULL
3420                ||  fattr_p->length_is_vec != NULL))
3421        {
3422            CHECKER_error(field_p, NIDL_PTRVARYARR);
3423            return;     /* Return with no further checking */
3424        }
3425    }
3426}
3427
3428/*
3429**  f i e l d _ i n _ l i n e
3430**
3431**  Checks a field node's [in_line] and [out_of_line] attributes.
3432*/
3433
3434static void field_in_line
3435(
3436    AST_field_n_t       *field_p        /* [in] Ptr to AST field node */
3437)
3438{
3439    AST_type_n_t        *type_p;        /* Data type of the field */
3440
3441    type_p = field_p->type;
3442
3443    /* Can't have both [in_line] and [out_of_line] attributes */
3444
3445    if (AST_IN_LINE_SET(field_p)
3446        &&  AST_OUT_OF_LINE_SET(field_p))
3447        CHECKER_acf_error(field_p, NIDL_CONFLINEATTR);
3448
3449    /* [in_line] and [out_of_line] attributes apply only to non-scalar types */
3450
3451    if ((AST_IN_LINE_SET(field_p) || AST_OUT_OF_LINE_SET(field_p))
3452        &&  type_is_scalar(type_p))
3453    {
3454        char const *file_name;     /* Related file name */
3455        char const *type_name;     /* Data type name */
3456
3457        STRTAB_str_to_string(type_p->fe_info->file, &file_name);
3458        NAMETABLE_id_to_string(type_p->name, &type_name);
3459
3460        CHECKER_acf_warning(field_p, NIDL_LINENONSCAL);
3461        CHECKER_acf_warning(field_p, NIDL_NAMEDECLAT, type_name, file_name,
3462                          type_p->fe_info->source_line);
3463    }
3464}
3465
3466/*
3467**  f i e l d _ s t r i n g
3468**
3469**  Checks a field node's [string] and [v1_string] attributes.
3470*/
3471
3472static void field_string
3473(
3474    AST_field_n_t       *field_p        /* [in] Ptr to AST field node */
3475)
3476{
3477    AST_type_n_t        *type_p;        /* Data type of the field */
3478
3479    type_p = field_p->type;
3480
3481    /* A [v1_string] must be an array of char with fixed bounds */
3482
3483    if (AST_STRING0_SET(field_p)
3484        &&  !type_is_v1_string(type_p))
3485        CHECKER_error(field_p, NIDL_STRV1FIXED);
3486
3487    /* The [v1_string] attribute can only be applied to a [v1_array] */
3488
3489    if ((AST_STRING0_SET(field_p) || AST_STRING0_SET(type_p))
3490        &&  !(AST_SMALL_SET(field_p) || AST_SMALL_SET(type_p)))
3491        CHECKER_error(field_p, NIDL_STRV1ARRAY);
3492
3493    /* The [string] attribute cannot be applied to a [v1_array] */
3494
3495    if ((AST_STRING_SET(field_p) && AST_SMALL_SET(field_p))
3496        ||  (AST_STRING_SET(field_p) && AST_SMALL_SET(type_p))
3497        ||  (AST_STRING_SET(type_p) && AST_SMALL_SET(field_p)))
3498        CHECKER_error(field_p, NIDL_STRARRAYV1);
3499
3500    /* Cannot have both [string] and [v1_string] attributes */
3501
3502    if (    (AST_STRING_SET(field_p) || AST_STRING_SET(type_p))
3503        &&  (AST_STRING0_SET(field_p) || AST_STRING0_SET(type_p))   )
3504    {
3505        ASTP_attr_flag_t attr1 = ASTP_STRING;
3506        ASTP_attr_flag_t attr2 = ASTP_STRING0;
3507
3508        CHECKER_error(field_p, NIDL_CONFLICTATTR,
3509            KEYWORDS_lookup_text(AST_attribute_to_token(&attr1)),
3510            KEYWORDS_lookup_text(AST_attribute_to_token(&attr2)));
3511    }
3512
3513    /*
3514     * Forgo last check if the declaration is a pointer to an array and either
3515     * (the declaration has size attributes) or (the array is conformant and
3516     * not a string), since mixed pointer and array declarations that either
3517     * have or require array size attributes are disallowed by other checks.
3518     */
3519    if (type_p->kind == AST_pointer_k)
3520    {
3521        AST_type_n_t    *ref_type_p;    /* Pointee data type */
3522
3523        ref_type_p = ASTP_chase_ptr_to_type(type_p);
3524        if (ref_type_p->kind == AST_array_k
3525            &&  (field_p->field_attrs != NULL
3526                ||  (AST_CONFORMANT_SET(ref_type_p)
3527                    &&  !AST_STRING_SET(ref_type_p))))
3528            return;
3529    }
3530
3531    /* [string] attribute valid only for one-dim arrays of char or byte */
3532
3533    if (AST_STRING_SET(field_p)
3534        &&  !type_is_string(type_p))
3535        CHECKER_error(field_p, NIDL_STRCHARBYTE);
3536}
3537
3538/*
3539**  f i e l d _ p o i n t e r
3540**
3541**  Checks a field node's attributes related to pointers.
3542*/
3543
3544static void field_pointer
3545(
3546    AST_field_n_t       *field_p,       /* [in] Ptr to AST field node */
3547    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
3548)
3549{
3550    AST_type_n_t        *type_p;        /* Data type of the field */
3551    boolean pointer_attr_valid = FALSE;
3552
3553    type_p = field_p->type;
3554
3555    if (type_p->kind == AST_pointer_k
3556        &&  type_p->type_structure.pointer->pointee_type->kind != AST_void_k)
3557        pointer_attr_valid = TRUE;
3558
3559    /* [ref] attribute valid only for pointer or array types */
3560
3561    if (AST_REF_SET(field_p) && !pointer_attr_valid)
3562        CHECKER_error(field_p, NIDL_REFATTRPTR);
3563
3564    /* [unique] attribute valid only for pointer or array types */
3565
3566    if (AST_UNIQUE_SET(field_p) && !pointer_attr_valid)
3567        CHECKER_error(field_p, NIDL_UNIQATTRPTR);
3568
3569    /* [ptr] attribute valid only for pointer or array types */
3570
3571    if (AST_PTR_SET(field_p) && !pointer_attr_valid)
3572        CHECKER_error(field_p, NIDL_PTRATTRPTR);
3573
3574    /* [unique] attribute requires -standard extended */
3575
3576    if (AST_UNIQUE_SET(field_p)
3577        &&  (*(int *)cmd_val[opt_standard] <= opt_standard_dce_1_0))
3578        CHECKER_warning(field_p, NIDL_NOPORTUNIQUE, OPT_STD_EXTENDED);
3579
3580    /* An array with a pointer attribute is valid only as a parameter. */
3581
3582    if (type_p->kind == AST_array_k &&
3583        (AST_REF_SET(field_p) || AST_PTR_SET(field_p) || AST_UNIQUE_SET(field_p)))
3584        CHECKER_error(field_p, NIDL_ARRPTRPRM);
3585
3586	/* ignore REF, UNIQUE, PTR attributes on pointers to interfaces */
3587#if 0
3588	 if (type_p->kind == AST_pointer_k && type_p->type_structure.pointer->pointee_type->kind == AST_interface_k
3589			 && (AST_UNIQUE_SET(field_p) || AST_REF_SET(field_p) || AST_PTR_SET(field_p)))
3590		 CHECKER_warning(field_p, NIDL_PTRATTBIGN);
3591#endif
3592    /*
3593     * If the field is a pointer, and it is not a pointer to an array,
3594     * and it has any of the array attributes, then it is an arrayified
3595     * pointer and it must undergo the checks for arrays.
3596     */
3597    if (type_p->kind == AST_pointer_k
3598        &&  type_p->type_structure.pointer->pointee_type->kind != AST_array_k
3599#if 0
3600        &&  (field_p->field_attrs != NULL
3601#endif
3602        &&  (instance_has_array_attr(field_p)
3603            ||  AST_STRING_SET(type_p)
3604            ||  AST_STRING_SET(field_p)))
3605    {
3606        array_check((ASTP_node_t *)type_p->type_structure.pointer,
3607                    type_p,
3608                    (ASTP_node_t *)field_p,
3609                    type_p->type_structure.pointer->pointee_type,
3610                    int_p,
3611                    true);
3612    }
3613}
3614
3615/*
3616**  f i e l d _ s m a l l
3617**
3618**  Checks a field node's [v1_array] attribute.
3619*/
3620
3621static void field_small
3622(
3623    AST_field_n_t       *field_p        /* [in] Ptr to AST field node */
3624)
3625{
3626    AST_type_n_t        *type_p;        /* Data type of the field */
3627    AST_array_n_t       *array_p;       /* Ptr to array node */
3628    AST_field_attr_n_t  *fattr_p;       /* Ptr to field attribute node */
3629
3630    type_p = field_p->type;
3631
3632    /* A [v1_array] must be in array, not pointer, syntax */
3633
3634    if (AST_SMALL_SET(field_p)
3635        &&  type_p->kind == AST_pointer_k)
3636        CHECKER_error(field_p, NIDL_SMALLARRSYN);
3637
3638    /*
3639     * Remaining checks only apply to array types in array syntax.
3640     * V1 did not allow arrays in pointer syntax.
3641     */
3642    if (!type_is_array_np(type_p))
3643        return;
3644
3645    fattr_p = field_p->field_attrs;
3646    array_p = type_p->type_structure.array;
3647
3648    /* A [v1_array] can be conformant or varying in the first dimension only */
3649
3650    if (AST_SMALL_SET(field_p)
3651        &&  ((AST_CONFORMANT_SET(type_p)
3652                && array_is_conformant_upper(array_p))
3653            ||
3654            (AST_VARYING_SET(field_p)
3655                && instance_is_varying_upper(array_p, field_p->field_attrs))))
3656        CHECKER_error(field_p, NIDL_SMALLMULTID);
3657
3658    /* [v1_array] attribute invalid for array with more than 65535 elements */
3659
3660    if (AST_SMALL_SET(field_p)
3661        &&  array_is_large(array_p))
3662        CHECKER_error(field_p, NIDL_SMALLINV);
3663
3664    /* A conformant [v1_array] must also be varying */
3665
3666    if ((AST_SMALL_SET(type_p) || AST_SMALL_SET(field_p))
3667        &&  AST_CONFORMANT_SET(type_p)
3668        &&  !AST_VARYING_SET(field_p))
3669        CHECKER_error(field_p, NIDL_SMALLCFMT);
3670
3671    /* A [v1_array] can not have the [min_is] or [first_is] attributes */
3672
3673    if ((AST_SMALL_SET(type_p) || AST_SMALL_SET(field_p))
3674        &&  fattr_p != NULL
3675        &&  (fattr_p->min_is_vec != NULL
3676            ||  fattr_p->first_is_vec != NULL))
3677        CHECKER_error(field_p, NIDL_SMALLMINFIRST);
3678}
3679
3680/*
3681**  f i e l d _ c o n t e x t
3682**
3683**  Checks a field node's [context_handle] attribute.
3684*/
3685
3686static void field_context
3687(
3688    AST_field_n_t       *field_p        /* [in] Ptr to AST field node */
3689)
3690{
3691    AST_type_n_t        *type_p;        /* Data type of the field */
3692
3693    type_p = field_p->type;
3694
3695    /* [context_handle] attribute only applies to void * types */
3696
3697    if (AST_CONTEXT_SET(field_p)
3698        &&  (type_p->kind != AST_pointer_k
3699            ||  (type_p->kind == AST_pointer_k
3700                &&  type_p->type_structure.pointer->pointee_type->kind
3701                    != AST_void_k)))
3702        CHECKER_error(field_p, NIDL_CTXPTRVOID);
3703
3704    /* [unique] pointers to context handles are not allowed */
3705
3706    if (AST_UNIQUE_SET(field_p)
3707        &&  type_p->kind == AST_pointer_k
3708        &&  AST_CONTEXT_RD_SET(type_p->type_structure.pointer->pointee_type))
3709        CHECKER_error(field_p, NIDL_UNIQCTXHAN);
3710
3711    /* Full pointers to context handles are not allowed */
3712
3713    if (AST_PTR_SET(field_p)
3714        &&  type_p->kind == AST_pointer_k
3715        &&  AST_CONTEXT_RD_SET(type_p->type_structure.pointer->pointee_type))
3716        CHECKER_error(field_p, NIDL_PTRCTXHAN);
3717}
3718
3719/*
3720**  f i e l d _ v a r y i n g
3721**
3722**  Checks an field node's "varying" (synthesized) attribute.
3723*/
3724
3725static void field_varying
3726(
3727    AST_field_n_t       *field_p,       /* [in] Ptr to AST field node */
3728    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
3729)
3730{
3731    AST_type_n_t        *type_p;        /* Field data type */
3732
3733    type_p = field_p->type;
3734
3735    /*
3736     * Assume that if the varying attribute is set, the field is an
3737     * array type and the field_attrs field is valid.  An array can be
3738     * represented either in normal array syntax, or as a pointer that
3739     * has any of the array attributes.
3740     */
3741    if (type_p->kind != AST_array_k)
3742        return;     /* All checks below assume normal array syntax */
3743
3744    /* Arrays varying in other than the first dim require -standard extended */
3745
3746    if (!AST_LOCAL_SET(int_p)
3747        &&  type_p->xmit_as_type == NULL
3748        &&  AST_VARYING_SET(field_p)
3749        &&  instance_is_varying_upper(type_p->type_structure.array,
3750                                      field_p->field_attrs)
3751        &&  (*(int *)cmd_val[opt_standard] <= opt_standard_dce_1_0))
3752        CHECKER_warning(field_p, NIDL_NOPORTVARY, OPT_STD_EXTENDED);
3753}
3754
3755/*
3756**  f i e l d _ i g n o r e
3757**
3758**  Checks an field node's [ignore] attribute.
3759*/
3760
3761static void field_ignore
3762(
3763    AST_field_n_t       *field_p        /* [in] Ptr to AST field node */
3764)
3765{
3766    AST_type_n_t        *type_p;        /* Field data type */
3767
3768    type_p = field_p->type;
3769
3770    /* The [ignore] attribute is valid only for pointers */
3771
3772    if (AST_IGNORE_SET(field_p)
3773        &&  type_p->kind != AST_pointer_k)
3774        CHECKER_error(field_p, NIDL_IGNATTRPTR);
3775}
3776static void field_switch_is
3777(
3778    AST_field_n_t       *field_p        /* [in] Ptr to AST field node */
3779)
3780{
3781    AST_type_n_t        *type_p;        /* Field data type */
3782
3783    type_p = field_p->type;
3784
3785    if (type_p->kind == AST_pointer_k)
3786        type_p = ASTP_chase_ptr_to_kind(type_p, AST_disc_union_k);
3787
3788    /* A non-encapsulated union declaration must have a [switch_is] attribute */
3789
3790    if (type_p != NULL
3791        &&  type_p->kind == AST_disc_union_k
3792        &&  type_p->type_structure.disc_union->discrim_name == NAMETABLE_NIL_ID
3793        &&  (field_p->field_attrs == NULL
3794            ||  field_p->field_attrs->switch_is == NULL))
3795        CHECKER_error(field_p, NIDL_NEUSWATTR);
3796}
3797
3798/*
3799**  f i e l d _ c h e c k
3800**
3801**  Checks an AST field node.
3802*/
3803
3804static void field_check
3805(
3806    AST_field_n_t       *field_p,       /* [in] Ptr to AST field node */
3807    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
3808)
3809{
3810    AST_field_attr_n_t  *fattr_p;       /* Ptr to field attribute node */
3811
3812    field_type(field_p, int_p);
3813    field_size(field_p, int_p);
3814
3815    field_in_line(field_p);
3816    field_string(field_p);
3817    field_pointer(field_p, int_p);
3818    field_small(field_p);
3819    field_context(field_p);
3820    field_varying(field_p, int_p);
3821    field_ignore(field_p);
3822    field_switch_is(field_p);
3823
3824    CHK_field_cs(field_p);
3825
3826    /* If there is a field attribute node, check it. */
3827
3828    fattr_p = field_p->field_attrs;
3829    if (fattr_p != NULL)
3830        fattr_check(fattr_p, (ASTP_node_t *)field_p, field_p->type, int_p);
3831}
3832
3833/*
3834**  s t r u c t _ c h e c k
3835**
3836**  Checks an AST structure node.
3837*/
3838
3839static void struct_check
3840(
3841    AST_structure_n_t   *struct_p,      /* [in] Ptr to AST structure node */
3842    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
3843)
3844{
3845    AST_field_n_t       *field_p;       /* A field of the structure */
3846
3847    /* Check each field node in the structure. */
3848
3849    field_p = struct_p->fields;
3850    while (field_p != NULL)
3851    {
3852        field_check(field_p, int_p);
3853        field_p = field_p->next;
3854    }
3855}
3856
3857/*
3858**  f p _ p a r a m _ h a n d l e
3859**
3860**  Checks a parameter node that is part of a function pointer operation
3861**  for any issues around handles.
3862*/
3863
3864static void fp_param_handle
3865(
3866    AST_parameter_n_t   *param_p,       /* [in] Ptr to AST parameter node */
3867    AST_type_n_t        *type_p,        /* [in] Parameter type */
3868    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
3869)
3870{
3871    type_p = type_xmit_type(type_p);    /* Pick up transmissible type */
3872
3873    /* Function pointer parameters cannot be of type handle_t */
3874
3875    if (!AST_LOCAL_SET(int_p)
3876        &&  type_p->kind == AST_handle_k)
3877        CHECKER_error(param_p, NIDL_FPHANPRM);
3878
3879#if 0   /** This warning is disabled. **/
3880    /* [handle] attribute of function pointer parameter ignored */
3881
3882    if (AST_HANDLE_SET(type_p))
3883        CHECKER_warning(param_p, NIDL_FPHANATTR);
3884#endif
3885}
3886
3887/*
3888**  f p _ p a r a m _ c h e c k
3889**
3890**  Checks a parameter node that is part of a function pointer operation.
3891**  Many of these checks are identical to those for interface operations.
3892**  Compare this routine to param_check to see the differences.
3893*/
3894
3895static void fp_param_check
3896(
3897    AST_parameter_n_t   *param_p,       /* [in] Ptr to AST parameter node */
3898    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
3899)
3900{
3901    AST_field_attr_n_t  *fattr_p;       /* Field attributes assoc. with param */
3902    AST_type_n_t        *top_type_p;    /* Top-level parameter type */
3903    AST_type_n_t        *type_p;        /* Param type (deref'd if necess.) */
3904    AST_type_n_t        *deref_type_p;  /* Param type (deref'd if necess.) */
3905
3906    /*
3907     * If the parameter type has a top-level '*' which indicates passing
3908     * mechanism only, follow the pointer to the data of interest.
3909     *      top_type_p   = top-level parameter type
3910     *      type_p       = possibly dereferenced parameter type
3911     *      deref_type_p = possibly dereferenced parameter type
3912     */
3913    top_type_p   = param_p->type;
3914    type_p       = param_follow_ref_ptr(param_p, CHK_follow_ref);
3915    deref_type_p = param_follow_ref_ptr(param_p, CHK_follow_any);
3916
3917    param_type(param_p, top_type_p, type_p, int_p);
3918
3919    /* Check parameter's field attributes, if any. */
3920
3921    fattr_p = param_p->field_attrs;
3922    if (fattr_p != NULL)
3923        fattr_check(fattr_p, (ASTP_node_t *)param_p, param_p->type, int_p);
3924
3925    param_size(param_p, top_type_p, type_p, int_p);
3926    param_struct(param_p, top_type_p, type_p);
3927    param_pipe(param_p, top_type_p, deref_type_p);
3928
3929    param_string(param_p, type_p);
3930    param_pointer(param_p, top_type_p, type_p, int_p);
3931    param_small(param_p, top_type_p, type_p);
3932    param_context(param_p, top_type_p, deref_type_p);
3933    param_varying(param_p, type_p, int_p);
3934
3935    fp_param_handle(param_p, type_p, int_p);
3936}
3937
3938/*
3939**  f u n c t i o n _ p t r _ c h e c k
3940**
3941**  Checks an AST function pointer node.
3942*/
3943
3944static void function_ptr_check
3945(
3946    AST_operation_n_t   *op_p,          /* [in] Ptr to operation node */
3947    AST_type_n_t        *type_p,        /* [in] Ptr to type node of pointer */
3948    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
3949)
3950{
3951    AST_parameter_n_t   *param_p;       /* A parameter in the operation */
3952
3953/*
3954 * For now, assume that none of the operation attributes are allowed
3955 * on function pointer operations.
3956 */
3957
3958    /* Function pointers are currently allowed only in local interfaces */
3959
3960    if (!AST_LOCAL_SET(int_p)
3961        &&  type_p->xmit_as_type == NULL)
3962        CHECKER_error(op_p, NIDL_FPLOCINT);
3963
3964    /* Check each parameter in the function. */
3965
3966    for (param_p = op_p->parameters; param_p != NULL; param_p = param_p->next)
3967        fp_param_check(param_p, int_p);
3968
3969    /* Check the function result, if any. */
3970
3971    if (op_p->result != NULL)
3972        fp_param_check(op_p->result, int_p);
3973}
3974
3975/*
3976**  p t r _ p o i n t e e _ t y p e
3977**
3978**  Checks a pointer node's pointee type.
3979*/
3980
3981static void ptr_pointee_type
3982(
3983    AST_pointer_n_t     *ptr_p,         /* [in] Ptr to AST pointer node */
3984    AST_type_n_t        *ptr_type_p,    /* [in] Pointer type node */
3985    ASTP_node_t         *node_p,        /* [in] Parent node of ptr type node */
3986    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
3987)
3988{
3989    AST_type_n_t        *type_p;        /* Pointee data type node */
3990
3991    /*
3992     * Note: No need to pick up transmissible type - if a pointed-at type is
3993     * used in [transmit_as] it must be a named type, so type checking will do.
3994     */
3995    type_p = ptr_p->pointee_type;
3996
3997    /*
3998     * If the pointer's parent has any array size attributes, then this
3999     * pointer represents an array - ignore the normal pointer checking.
4000     */
4001    if (    (node_p->fe_info->node_kind == fe_parameter_n_k
4002            &&  ((AST_parameter_n_t *)node_p)->field_attrs != NULL)
4003        ||  (node_p->fe_info->node_kind == fe_field_n_k
4004            &&  ((AST_field_n_t *)node_p)->field_attrs != NULL))
4005        return;
4006
4007    /* Pointers to pipes valid only in parameter declarations */
4008
4009    if (type_p->kind == AST_pipe_k
4010        &&  node_p->fe_info->node_kind != fe_parameter_n_k)
4011        CHECKER_error(ptr_p, NIDL_INVPTRPIPE);
4012
4013    /* Pointers to context handles valid only in parameter declarations */
4014
4015    if (AST_CONTEXT_RD_SET(type_p)
4016        &&  node_p->fe_info->node_kind != fe_parameter_n_k
4017            /* OK in opaque context handle typedef */
4018        &&  !(node_p->fe_info->node_kind == fe_export_n_k
4019              && type_p->kind == AST_structure_k
4020              && AST_DEF_AS_TAG_SET(type_p)))
4021        CHECKER_error(ptr_p, NIDL_INVPTRCTX);
4022
4023    /* Pointers to type handle_t valid only in parameter declarations */
4024
4025    if (type_p->kind == AST_handle_k
4026        &&  node_p->fe_info->node_kind != fe_parameter_n_k)
4027        CHECKER_error(ptr_p, NIDL_HANDLEPTR);
4028
4029    /* void * must be used in conjunction with the [context_handle] attribute */
4030    /*
4031     * (1) Don't report error if parent node is parameter and [context_handle]
4032     * is set on the parameter.  This is one case where an attribute can apply
4033     * to other than the top-level * (e.g. in [out,context_handle] void **p,
4034     * the [context_handle] parameter attribute applies to the second-level *
4035     * which is an anonymous type without the [context_handle] attribute).
4036     */
4037    if (!AST_LOCAL_SET(int_p)
4038        &&  type_p->kind == AST_pointer_k
4039        &&  type_p->type_structure.pointer->pointee_type->kind == AST_void_k
4040        &&  !AST_CONTEXT_RD_SET(type_p)
4041        &&  !(node_p->fe_info->node_kind == fe_parameter_n_k /* (1) */
4042              && AST_CONTEXT_SET((AST_parameter_n_t *)node_p))
4043		  )
4044        CHECKER_error(node_p, NIDL_PTRVOIDCTX);
4045
4046    /* If this is a function pointer, call routine to check it. */
4047
4048    if (type_p->kind == AST_function_k)
4049        function_ptr_check(type_p->type_structure.function, ptr_type_p, int_p);
4050}
4051
4052/*
4053**  p t r _ c h e c k
4054**
4055**  Checks an AST pointer node.
4056*/
4057
4058static void ptr_check
4059(
4060    AST_pointer_n_t     *ptr_p,         /* [in] Ptr to AST pointer node */
4061    AST_type_n_t        *ptr_type_p,    /* [in] Pointer type node */
4062    ASTP_node_t         *node_p,        /* [in] Parent node of ptr type node */
4063    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
4064)
4065{
4066    ptr_pointee_type(ptr_p, ptr_type_p, node_p, int_p);
4067}
4068
4069/*
4070**  p i p e _ b a s e _ t y p e
4071**
4072**  Checks a pipe node's base data type.
4073*/
4074
4075static void pipe_base_type
4076(
4077    AST_pipe_n_t        *pipe_p,        /* [in] Ptr to AST pipe node */
4078    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
4079)
4080{
4081    AST_type_n_t        *type_p;        /* Pipe base data type node */
4082
4083    type_p = pipe_p->base_type;
4084
4085    /* If the pipe base type is anonymous, it must undergo type checks. */
4086
4087    if (type_is_anonymous(type_p))
4088        type_check(type_p, (ASTP_node_t *)pipe_p, int_p);
4089
4090    /* Base type of a pipe can't be a pipe type */
4091
4092    if (type_p->kind == AST_pipe_k)
4093        CHECKER_error(pipe_p, NIDL_PIPEBASETYP);
4094
4095    /* Base type of a pipe can't be a [context_handle] type */
4096
4097    if (AST_CONTEXT_RD_SET(type_p))
4098        CHECKER_error(pipe_p, NIDL_CTXBASETYP);
4099
4100    /* Base type of a pipe can't be a conformant type */
4101
4102    if (AST_CONFORMANT_SET(type_p))
4103        CHECKER_error(pipe_p, NIDL_CFMTBASETYP);
4104
4105    /* Base type of a pipe cannot be handle_t */
4106
4107    if (type_p->kind == AST_handle_k)
4108        CHECKER_error(pipe_p, NIDL_HANPIPEBASE);
4109
4110    /* Base type of a pipe cannot be a function pointer */
4111
4112    if (type_is_function(type_p))
4113        CHECKER_error(pipe_p, NIDL_FPPIPEBASE);
4114
4115	/* Cant be an interface or interface reference */
4116	 if (type_p->kind == AST_interface_k)
4117		 CHECKER_error(pipe_p, NIDL_PIPECTYPE, "interface");
4118	if (type_p->kind == AST_pointer_k && type_p->type_structure.pointer->pointee_type->kind == AST_interface_k)
4119		 CHECKER_error(pipe_p, NIDL_PIPECTYPE, "interface reference");
4120
4121    /* Base type of a pipe can't be or contain a pointer */
4122
4123    if (!type_is_function(type_p)
4124        &&  FE_TEST(type_p->fe_info->flags, FE_HAS_PTR))
4125        CHECKER_error(pipe_p, NIDL_PTRBASETYP);
4126
4127    /* Base type of a pipe may not have a [transmit_as] type */
4128
4129    if (type_p->xmit_as_type != NULL)
4130        CHECKER_error(pipe_p, NIDL_XMITPIPEBASE);
4131
4132    /* void is valid only in an operation or pointer declaration */
4133
4134    if (type_p->kind == AST_void_k)
4135        CHECKER_error(pipe_p, NIDL_VOIDOPPTR);
4136
4137    /* void * must be used in conjunction with the [context_handle] attribute */
4138
4139    if (!AST_LOCAL_SET(int_p)
4140        &&  type_p->xmit_as_type == NULL
4141        &&  type_p->kind == AST_pointer_k
4142        &&  type_p->type_structure.pointer->pointee_type->kind == AST_void_k
4143        &&  !AST_CONTEXT_RD_SET(type_p)
4144		  )
4145        CHECKER_error(pipe_p, NIDL_PTRVOIDCTX);
4146
4147    CHK_pipe_base_type_cs(pipe_p, int_p);
4148}
4149
4150/*
4151**  p i p e _ c h e c k
4152**
4153**  Checks an AST pipe node.
4154*/
4155
4156static void pipe_check
4157(
4158    AST_pipe_n_t        *pipe_p,        /* [in] Ptr to AST pipe node */
4159    AST_type_n_t        *type_p,        /* [in] Ptr to pipe data type node */
4160    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
4161)
4162{
4163    /* A pipe may not have a [transmit_as] type */
4164
4165    if (type_p->xmit_as_type != NULL)
4166        CHECKER_error(pipe_p, NIDL_PIPEXMITAS);
4167
4168    /* Pipes must be defined with typedef */
4169
4170    if (type_p->name == NAMETABLE_NIL_ID)
4171        CHECKER_error(pipe_p, NIDL_ANONPIPE);
4172
4173    pipe_base_type(pipe_p, int_p);
4174}
4175
4176/*
4177**  e n u m _ c h e c k
4178**
4179**  Checks an AST enumeration node.
4180*/
4181
4182static void enum_check
4183(
4184    AST_enumeration_n_t *enum_p,        /* [in] Ptr to AST enumeration node */
4185    AST_type_n_t        *type_p         /* [in] Ptr to enum data type node */
4186)
4187{
4188    /* Use of anonymous enum may not be portable across C compilers */
4189    if (type_is_anonymous(type_p))
4190        CHECKER_warning(enum_p, NIDL_NOPORTANON, "enum");
4191}
4192
4193/*
4194**  c l a b e l _ v a l u e
4195**
4196**  Checks a case label node's constant value.
4197*/
4198
4199static void clabel_value
4200(
4201    AST_case_label_n_t  *clabel_p,      /* [in] Ptr to AST case label node */
4202    AST_type_n_t        *type_p         /* [in] Union discriminator data type */
4203)
4204{
4205    AST_constant_n_t    *const_p;       /* Constant value in case label */
4206
4207    /* Ignore if default case in union, which does not have a value. */
4208
4209    if (clabel_p->default_label)
4210        return;
4211
4212    const_p = clabel_p->value;
4213
4214    /* Invalid case label type */
4215
4216    if (!const_is_integer(const_p)
4217        &&  !const_is_enum(const_p)
4218        &&  const_p->kind != AST_boolean_const_k
4219        &&  const_p->kind != AST_char_const_k)
4220    {
4221        CHECKER_error(clabel_p, NIDL_INVCASETYP);
4222        return;
4223    }
4224
4225    /* Case label type does not agree with discriminator type */
4226
4227    if ((type_is_integer(type_p)
4228            &&  !const_is_integer(const_p))
4229        ||  (type_is_enum(type_p)
4230            &&  !const_is_enum(const_p))
4231        ||  (type_p->kind == AST_boolean_k
4232            &&  const_p->kind != AST_boolean_const_k)
4233        ||  (type_p->kind == AST_character_k
4234            &&  const_p->kind != AST_char_const_k))
4235    {
4236        CHECKER_error(clabel_p, NIDL_CASEDISCTYPE);
4237        return;
4238    }
4239
4240    /* Case label must be a constant from discriminator's enumeration type */
4241
4242    if (type_is_enum(type_p))
4243    {
4244        char const      *clabel_name;   /* Name of case label constant */
4245        char const      *econst_name;   /* Name of a constant in enumeration */
4246        AST_enumeration_n_t *enum_p;    /* Ptr to enumeration node */
4247        AST_constant_n_t    *econst_p;  /* Ptr to a constant node in the enum */
4248
4249        NAMETABLE_id_to_string(const_p->name, &clabel_name);
4250        if (clabel_name == NULL)
4251            return;             /* Shouldn't happen */
4252
4253        enum_p = type_p->type_structure.enumeration;
4254
4255        econst_p = enum_p->enum_constants;
4256        while (econst_p != NULL)
4257        {
4258            NAMETABLE_id_to_string(econst_p->name, &econst_name);
4259            if (econst_name == NULL)
4260                continue;       /* Shouldn't happen */
4261
4262            if (strcmp(clabel_name, econst_name) == 0)
4263                return;         /* Matching constant in right enum; return */
4264
4265            econst_p = econst_p->next;
4266        }
4267
4268        /* Matching constant name not found in the relevant enumeration. */
4269
4270        CHECKER_error(clabel_p, NIDL_CASECONENUM);
4271    }
4272}
4273
4274/*
4275**  c l a b e l _ c h e c k
4276**
4277**  Checks an AST case label node.
4278*/
4279
4280static void clabel_check
4281(
4282    AST_case_label_n_t  *clabel_p,      /* [in] Ptr to AST case label node */
4283    AST_type_n_t        *type_p         /* [in] Union discriminator data type */
4284)
4285{
4286    clabel_value(clabel_p, type_p);
4287}
4288
4289/*
4290**  a r m _ t y p e
4291**
4292**  Check an arm node's data type.
4293*/
4294
4295static void arm_type
4296(
4297    AST_arm_n_t         *arm_p,         /* [in] Ptr to AST arm node */
4298    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
4299)
4300{
4301    AST_type_n_t        *type_p;        /* Data type of the arm */
4302
4303    type_p = arm_p->type;
4304    if (type_p == NULL)
4305        return;
4306
4307    /* If the arm type is anonymous, it must undergo type checks. */
4308
4309    if (type_is_anonymous(type_p))
4310        type_check(type_p, (ASTP_node_t *)arm_p, int_p);
4311
4312    /* A type with [transmit_as] may not have other type attributes */
4313
4314    if (type_p->xmit_as_type != NULL
4315        &&
4316        (AST_STRING_SET(arm_p)
4317         || AST_STRING0_SET(arm_p)
4318         || AST_UNIQUE_SET(arm_p)
4319         || AST_REF_SET(arm_p)
4320         || AST_SMALL_SET(arm_p)
4321         || AST_CONTEXT_SET(arm_p)
4322         || AST_PTR_SET(arm_p)))
4323        CHECKER_error(arm_p, NIDL_XMITTYPEATTRS);
4324
4325    type_p = type_xmit_type(type_p);    /* Pick up transmissible type */
4326
4327    /* Conformant arrays or structures are invalid within unions */
4328	/* WEZ:FIXME we need them for ORPC! */
4329#ifdef notdef
4330    if (AST_CONFORMANT_SET(type_p))
4331        CHECKER_error(arm_p, NIDL_CFMTUNION);
4332#endif
4333
4334	/* interface must have a * */
4335	 if (type_p->kind == AST_interface_k)	{
4336		 char const * id_name;
4337		 NAMETABLE_id_to_string(type_p->name, &id_name);
4338		 CHECKER_error(arm_p, NIDL_INTREFNOTALO, id_name);
4339	 }
4340
4341    /* Pipes not valid as members of unions */
4342
4343    if (type_p->kind == AST_pipe_k)
4344        CHECKER_error(arm_p, NIDL_PIPEUNIMEM);
4345
4346    /* Context handles not valid as members of unions */
4347
4348    if (AST_CONTEXT_RD_SET(type_p)
4349        ||  AST_CONTEXT_SET(arm_p))
4350        CHECKER_error(arm_p, NIDL_CTXUNIMEM);
4351
4352    /* Function pointers not valid as members of unions */
4353
4354    if (!AST_LOCAL_SET(int_p)
4355        &&  type_is_function(type_p))
4356#if 0   /** Obsolete **/
4357        &&  type_p->xmit_as_type == NULL)
4358#endif
4359        CHECKER_error(arm_p, NIDL_FPUNIMEM);
4360
4361    /* Members of unions cannot be of type handle_t */
4362
4363    if (type_p->kind == AST_handle_k)
4364#if 0   /** Obsolete **/
4365        &&  type_p->xmit_as_type == NULL)
4366#endif
4367        CHECKER_error(arm_p, NIDL_HANUNIMEM);
4368
4369    /* void is valid only in an operation or pointer declaration */
4370
4371    if (type_p->kind == AST_void_k)
4372        CHECKER_error(arm_p, NIDL_VOIDOPPTR);
4373
4374    /* void * must be used in conjunction with the [context_handle] attribute */
4375
4376    if (!AST_LOCAL_SET(int_p)
4377#if 0   /** Obsolete **/
4378        &&  type_p->xmit_as_type == NULL
4379#endif
4380        &&  type_p->kind == AST_pointer_k
4381        &&  type_p->type_structure.pointer->pointee_type->kind == AST_void_k
4382        &&  !AST_CONTEXT_RD_SET(type_p)
4383        &&  !AST_CONTEXT_SET(arm_p)
4384		  )
4385        CHECKER_error(arm_p, NIDL_PTRVOIDCTX);
4386
4387    /*
4388     * V1 attributes are incompatible with this type
4389     * Note: Issue error only if the same error doesn't fire for the type.
4390     */
4391    if (FE_TEST(arm_p->fe_info->flags, FE_HAS_V1_ATTR)
4392        &&  FE_TEST(arm_p->fe_info->flags, FE_HAS_V2_ATTR)
4393        &&  ! ( FE_TEST(type_p->fe_info->flags, FE_HAS_V1_ATTR)
4394                &&  FE_TEST(type_p->fe_info->flags, FE_HAS_V2_ATTR) ))
4395        CHECKER_warning(arm_p, NIDL_INCOMPATV1);
4396}
4397
4398/*
4399**  a r m _ s t r i n g
4400**
4401**  Checks an arm node's [string] and [v1_string] attributes.
4402*/
4403
4404static void arm_string
4405(
4406    AST_arm_n_t         *arm_p          /* [in] Ptr to AST arm node */
4407)
4408{
4409    AST_type_n_t        *type_p;        /* Data type of the arm */
4410
4411    type_p = arm_p->type;               /* Possibly NULL */
4412
4413    /* Remaining checks do not apply to an empty arm. */
4414
4415    if (type_p == NULL)
4416        return;
4417
4418    /* A [v1_string] must be an array of char with fixed bounds */
4419
4420    if (AST_STRING0_SET(arm_p)
4421        &&  !type_is_v1_string(type_p))
4422        CHECKER_error(arm_p, NIDL_STRV1FIXED);
4423
4424    /* The [v1_string] attribute can only be applied to a [v1_array] */
4425
4426    if ((AST_STRING0_SET(arm_p) || AST_STRING0_SET(type_p))
4427        &&  !(AST_SMALL_SET(arm_p) || AST_SMALL_SET(type_p)))
4428        CHECKER_error(arm_p, NIDL_STRV1ARRAY);
4429
4430    /* The [string] attribute cannot be applied to a [v1_array] */
4431
4432    if ((AST_STRING_SET(arm_p) && AST_SMALL_SET(arm_p))
4433        ||  (AST_STRING_SET(arm_p) && AST_SMALL_SET(type_p))
4434        ||  (AST_STRING_SET(type_p) && AST_SMALL_SET(arm_p)))
4435        CHECKER_error(arm_p, NIDL_STRARRAYV1);
4436
4437    /* [string] attribute valid only for one-dim arrays of char or byte */
4438
4439    if (AST_STRING_SET(arm_p)
4440        &&  !type_is_string(type_p))
4441        CHECKER_error(arm_p, NIDL_STRCHARBYTE);
4442
4443    /* Cannot have both [string] and [v1_string] attributes */
4444
4445    if (    (AST_STRING_SET(arm_p) || AST_STRING_SET(type_p))
4446        &&  (AST_STRING0_SET(arm_p) || AST_STRING0_SET(type_p))   )
4447    {
4448        ASTP_attr_flag_t attr1 = ASTP_STRING;
4449        ASTP_attr_flag_t attr2 = ASTP_STRING0;
4450
4451        CHECKER_error(arm_p, NIDL_CONFLICTATTR,
4452            KEYWORDS_lookup_text(AST_attribute_to_token(&attr1)),
4453            KEYWORDS_lookup_text(AST_attribute_to_token(&attr2)));
4454    }
4455}
4456
4457/*
4458**  a r m _ p o i n t e r
4459**
4460**  Checks an arm node's attributes related to pointers.
4461*/
4462
4463static void arm_pointer
4464(
4465    AST_arm_n_t         *arm_p,         /* [in] Ptr to AST arm node */
4466    AST_interface_n_t   *int_p ATTRIBUTE_UNUSED         /* [in] Ptr to interface node */
4467)
4468{
4469    AST_type_n_t        *type_p;        /* Data type of the arm */
4470    boolean pointer_attr_valid = FALSE;
4471
4472    type_p = arm_p->type;
4473    if (type_p == NULL)
4474        return;
4475
4476    type_p = type_xmit_type(type_p);    /* Pick up transmissible type */
4477
4478    /* An arm of a union can't be or contain a [ref] pointer */
4479	/* WEZ:FIXME we need this for ORPC */
4480#ifdef nodef
4481    if (FE_TEST(type_p->fe_info->flags, FE_HAS_REF_PTR) ||
4482        AST_REF_SET(arm_p))
4483        CHECKER_error(arm_p, NIDL_ARMREFPTR);
4484#endif
4485    if (type_p->kind == AST_pointer_k
4486        &&  type_p->type_structure.pointer->pointee_type->kind != AST_void_k)
4487        pointer_attr_valid = TRUE;
4488
4489    /* [ref] attribute valid only for pointer or array types */
4490
4491    if (AST_REF_SET(arm_p) && !pointer_attr_valid)
4492        CHECKER_error(arm_p, NIDL_REFATTRPTR);
4493
4494#if 0
4495	/* ignore REF, UNIQUE or PTR for pointers to interfaces */
4496	 if (type_p->kind == AST_pointer_k && type_p->type_structure.pointer->pointee_type->kind == AST_interface_k
4497			 && (AST_UNIQUE_SET(arm_p) || AST_REF_SET(arm_p) || AST_PTR_SET(arm_p)))
4498		 CHECKER_warning(arm_p, NIDL_PTRATTBIGN);
4499#endif
4500    /* An arm of a union can't be or contain a [unique] pointer */
4501
4502#ifdef notdef
4503    if (FE_TEST(type_p->fe_info->flags, FE_HAS_UNIQUE_PTR) ||
4504        AST_UNIQUE_SET(arm_p))
4505        CHECKER_error(arm_p, NIDL_ARMUNIQUEPTR);
4506#endif
4507
4508    /* [unique] attribute valid only for pointer or array types */
4509
4510    if (AST_UNIQUE_SET(arm_p) && !pointer_attr_valid)
4511        CHECKER_error(arm_p, NIDL_UNIQATTRPTR);
4512
4513    /* [ptr] attribute valid only for pointer or array types */
4514
4515    if (AST_PTR_SET(arm_p) && !pointer_attr_valid)
4516        CHECKER_error(arm_p, NIDL_PTRATTRPTR);
4517
4518    /* [unique] attribute requires -standard extended */
4519
4520    if (AST_UNIQUE_SET(arm_p)
4521        &&  (*(int *)cmd_val[opt_standard] <= opt_standard_dce_1_0))
4522        CHECKER_warning(arm_p, NIDL_NOPORTUNIQUE, OPT_STD_EXTENDED);
4523
4524    /* An array with a pointer attribute is valid only as a parameter. */
4525
4526    /*
4527     * Have to check type attrs as well as arm attributes for the obscure case
4528     * of transmit_as type whose transmissible type is an array with a pointer
4529     * attr, since propagation from type to arm doesn't happen in this case.
4530     */
4531    if (type_p->kind == AST_array_k &&
4532        (AST_REF_SET(arm_p) || AST_PTR_SET(arm_p) || AST_UNIQUE_SET(arm_p) ||
4533         AST_REF_SET(type_p) || AST_PTR_SET(type_p) || AST_UNIQUE_SET(type_p)))
4534        CHECKER_error(arm_p, NIDL_ARRPTRPRM);
4535
4536    /*
4537     * **NOTE**: It could be valid for an arm to be a varying array, however
4538     * the AST can not represent this since there is no arm_p->field_attrs
4539     * field.  If there were, an arm that is a pointer and has any of the
4540     * array attributes would undergo the checks for arrays here.
4541     */
4542}
4543
4544/*
4545**  a r m _ s m a l l
4546**
4547**  Checks an arm node's [v1_array] attribute.
4548*/
4549
4550static void arm_small
4551(
4552    AST_arm_n_t         *arm_p          /* [in] Ptr to AST arm node */
4553)
4554{
4555    AST_type_n_t        *type_p;        /* Data type of the arm */
4556    AST_array_n_t       *array_p;       /* Ptr to array node */
4557
4558    type_p = arm_p->type;               /* Possibly NULL */
4559
4560    /* Check only applies to array types. */
4561
4562    if (type_p == NULL
4563        ||  !type_is_array_np(type_p))
4564        return;
4565
4566    array_p = type_p->type_structure.array;
4567
4568    /* [v1_array] attribute invalid for array with more than 65535 elements */
4569
4570    if (AST_SMALL_SET(arm_p)
4571        &&  array_is_large(array_p))
4572        CHECKER_error(arm_p, NIDL_SMALLINV);
4573}
4574
4575/*
4576**  a r m _ c o n t e x t
4577**
4578**  Checks an arm node's [context_handle] attribute.
4579*/
4580
4581static void arm_context
4582(
4583    AST_arm_n_t         *arm_p          /* [in] Ptr to AST arm node */
4584)
4585{
4586    AST_type_n_t        *type_p;        /* Data type of the arm */
4587
4588    type_p = arm_p->type;
4589    if (type_p == NULL)
4590        return;
4591
4592    /* [context_handle] attribute only applies to void * types */
4593
4594    if (AST_CONTEXT_SET(arm_p)
4595        &&  (type_p->kind != AST_pointer_k
4596            ||  (type_p->kind == AST_pointer_k
4597                &&  type_p->type_structure.pointer->pointee_type->kind
4598                    != AST_void_k)))
4599        CHECKER_error(arm_p, NIDL_CTXPTRVOID);
4600
4601    /* [unique] pointers to context handles are not allowed */
4602
4603    if (AST_UNIQUE_SET(arm_p)
4604        &&  type_p->kind == AST_pointer_k
4605        &&  AST_CONTEXT_RD_SET(type_p->type_structure.pointer->pointee_type))
4606        CHECKER_error(arm_p, NIDL_UNIQCTXHAN);
4607
4608    /* Full pointers to context handles are not allowed */
4609
4610    if (AST_PTR_SET(arm_p)
4611        &&  type_p->kind == AST_pointer_k
4612        &&  AST_CONTEXT_RD_SET(type_p->type_structure.pointer->pointee_type))
4613        CHECKER_error(arm_p, NIDL_PTRCTXHAN);
4614}
4615
4616/*
4617**  a r m _ c h e c k
4618**
4619**  Checks an AST arm node.
4620*/
4621
4622static void arm_check
4623(
4624    AST_arm_n_t         *arm_p,         /* [in] Ptr to AST arm node */
4625    AST_type_n_t        *type_p,        /* [in] Discriminator data type */
4626    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
4627)
4628{
4629    AST_case_label_n_t  *clabel_p;      /* List of case labels for this arm */
4630
4631    arm_type(arm_p, int_p);
4632
4633    arm_string(arm_p);
4634    arm_pointer(arm_p, int_p);
4635    arm_small(arm_p);
4636    arm_context(arm_p);
4637
4638    /* Check each case label for this arm. */
4639
4640    if (type_p == NULL) return;
4641    clabel_p = arm_p->labels;
4642    while (clabel_p != NULL)
4643    {
4644        clabel_check(clabel_p, type_p);
4645        clabel_p = clabel_p->next;
4646    }
4647}
4648
4649/*
4650**  u n i o n _ d i s c r i m _ t y p e
4651**
4652**  Checks a discriminated union node's discriminator data type.
4653*/
4654
4655static void union_discrim_type
4656(
4657    AST_disc_union_n_t  *union_p        /* [in] Ptr to AST discr. union node */
4658)
4659{
4660    AST_type_n_t        *type_p;        /* Discriminator data type */
4661
4662    type_p = union_p->discrim_type;
4663    if (type_p == NULL) return;
4664
4665    /* Union discriminator type must be int, char, boolean, or enum */
4666
4667    if (!type_is_index(type_p)
4668        &&  !type_is_enum(type_p)
4669        &&  type_p->kind != AST_boolean_k
4670        &&  type_p->kind != AST_character_k)
4671        CHECKER_error(union_p, NIDL_UNIDISCTYP);
4672}
4673
4674/*
4675**  u n i o n _ c a s e _ l a b e l s
4676**
4677**  Checks a discriminated union's case label values for uniqueness.
4678*/
4679
4680static void union_case_labels
4681(
4682    AST_disc_union_n_t  *union_p        /* [in] Ptr to AST discr. union node */
4683)
4684{
4685    AST_arm_n_t         *arm_p;         /* Ptr to one arm node of the union */
4686    AST_case_label_n_t  *clabel_p;      /* Ptr to one case label of the arm */
4687    AST_arm_n_t         *s_arm_p;       /* Ptr to a subsequent arm */
4688    AST_case_label_n_t  *s_clabel_p;    /* Ptr to a subsequent case label */
4689    boolean             dup;            /* True if duplicate case label */
4690
4691    arm_p = union_p->arms;
4692    while (arm_p != NULL)
4693    {
4694        clabel_p = arm_p->labels;
4695        while (clabel_p != NULL)
4696        {
4697            /*
4698             * Check all subsequent arms for a repeated case label value.
4699             * A repeated case label value within an arm is OK.
4700             */
4701            s_arm_p = arm_p->next;
4702            while (s_arm_p != NULL)
4703            {
4704                s_clabel_p = s_arm_p->labels;
4705
4706                /* Go through all labels of this subsequent arm. */
4707
4708                dup = FALSE;
4709
4710                while (s_clabel_p != NULL)
4711                {
4712                    /* Check for duplicate "case default:" */
4713
4714                    if (clabel_p->default_label && s_clabel_p->default_label)
4715                        dup = TRUE;
4716                    else if (clabel_p->value != NULL
4717                            && s_clabel_p->value != NULL
4718                            && clabel_p->value->kind == s_clabel_p->value->kind)
4719                    {
4720                        /* Check for duplicate case label values. */
4721
4722                        switch (clabel_p->value->kind)
4723                        {
4724                        case AST_nil_const_k:
4725                            break;
4726                        case AST_int_const_k:
4727                            dup = (clabel_p->value->value.int_val
4728                                   == s_clabel_p->value->value.int_val);
4729                            break;
4730                        case AST_hyper_int_const_k:
4731                            dup = (clabel_p->value->value.hyper_int_val.high
4732                                   == s_clabel_p->value->value.hyper_int_val.high
4733                                  &&
4734                                   clabel_p->value->value.hyper_int_val.low
4735                                   == s_clabel_p->value->value.hyper_int_val.low);
4736                            break;
4737                        case AST_char_const_k:
4738                            dup = (clabel_p->value->value.char_val
4739                                   == s_clabel_p->value->value.char_val);
4740                            break;
4741                        case AST_string_const_k:
4742                            break;
4743                        case AST_boolean_const_k:
4744                            dup = (clabel_p->value->value.boolean_val
4745                                   == s_clabel_p->value->value.boolean_val);
4746                            break;
4747                        default:
4748                            error(NIDL_INTERNAL_ERROR, __FILE__, __LINE__);
4749                        }   /* switch (clabel_p->value->kind) */
4750                    }   /* else if (same constant kinds) */
4751
4752                    /* Duplicate case label value invalid */
4753
4754                    if (dup)
4755                    {
4756                        CHECKER_error(s_clabel_p, NIDL_DUPCASEVAL);
4757                        break;
4758                    }
4759
4760                    s_clabel_p = s_clabel_p->next;
4761                }   /* while (s_clabel_p != NULL) */
4762
4763                if (dup)
4764                    break;
4765                else
4766                    s_arm_p = s_arm_p->next;
4767            }   /* while (s_arm_p != NULL) */
4768
4769            clabel_p = clabel_p->next;
4770        }   /* while (clabel_p != NULL) */
4771
4772        arm_p = arm_p->next;
4773    }   /* while (arm_p != NULL) */
4774}
4775
4776/*
4777**  u n i o n _ c h e c k
4778**
4779**  Checks an AST discriminated union node.
4780*/
4781
4782static void union_check
4783(
4784    AST_disc_union_n_t  *union_p,       /* [in] Ptr to AST discr. union node */
4785    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
4786)
4787{
4788    AST_arm_n_t         *arm_p;         /* Ptr to one arm node of the union */
4789
4790    union_discrim_type(union_p);
4791    union_case_labels(union_p);
4792
4793    /* Use of a nonencapsulated union requires -standard extended */
4794
4795    if (union_p->discrim_name == NAMETABLE_NIL_ID
4796        &&  (*(int *)cmd_val[opt_standard] <= opt_standard_dce_1_0))
4797        CHECKER_warning(union_p, NIDL_NOPORTNEU, OPT_STD_EXTENDED);
4798
4799    /* Check each arm of the union. */
4800
4801    arm_p = union_p->arms;
4802    while (arm_p != NULL)
4803    {
4804        arm_check(arm_p, union_p->discrim_type, int_p);
4805        arm_p = arm_p->next;
4806    }
4807}
4808
4809/*
4810**  t y p e _ n a m e _ l e n
4811**
4812**  Checks a type node's name length.
4813*/
4814
4815static void type_name_len
4816(
4817    AST_type_n_t        *top_type_p,    /* [in] Top-level presented type */
4818    AST_type_n_t        *type_p,        /* [in] Ptr to AST type node */
4819    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
4820)
4821{
4822    char const          *type_name;     /* Type name */
4823    int                 type_len;       /* Length of type name */
4824    int                 max_len;        /* Maximum identifier length */
4825
4826    if (!AST_LOCAL_SET(int_p)
4827        &&  top_type_p->name != NAMETABLE_NIL_ID
4828        &&  top_type_p->xmit_as_type != NULL)   /* Pres type != transmit type */
4829    {
4830        NAMETABLE_id_to_string(top_type_p->name, &type_name);
4831        if (type_name == NULL)
4832            return;     /* Shouldn't happen */
4833
4834        type_len = strlen(type_name);
4835
4836        /* Maximum id length for type with [transmit_as] is <n> characters */
4837
4838        max_len = MAX_ID - strlen("_from_xmit");
4839        if (type_len > max_len)
4840            CHECKER_error(top_type_p, NIDL_MAXIDTYPTA, max_len);
4841    }
4842
4843    if (type_p->name == NAMETABLE_NIL_ID)
4844        return;
4845
4846    NAMETABLE_id_to_string(type_p->name, &type_name);
4847    if (type_name == NULL)
4848        return;     /* Shouldn't happen */
4849
4850    type_len = strlen(type_name);
4851
4852    /* Maximum identifier length for [handle] type is <n> characters */
4853
4854    max_len = MAX_ID - strlen("_unbind");
4855    if (!AST_LOCAL_SET(int_p)
4856        &&  type_len > max_len
4857        &&  AST_HANDLE_SET(type_p))
4858        CHECKER_error(type_p, NIDL_MAXIDTYPHAN, max_len);
4859
4860    /* Maximum identifier length for [context_handle] type is <n> characters */
4861
4862    max_len = MAX_ID - strlen("_rundown");
4863    if (!AST_LOCAL_SET(int_p)
4864        &&  type_len > max_len
4865        &&  AST_CONTEXT_RD_SET(type_p))
4866        CHECKER_error(type_p, NIDL_MAXIDTYPCH, max_len);
4867
4868    /* Maximum identifier length for pointed-to type is <n> characters */
4869
4870    max_len = MAX_ID - strlen("_mr");
4871    if (!AST_LOCAL_SET(int_p)
4872        &&  !AST_IN_VARYING_SET(type_p) && !AST_OUT_VARYING_SET(type_p)
4873        &&  type_len > max_len
4874        &&  FE_TEST(type_p->fe_info->flags,FE_POINTED_AT))
4875    {
4876        char const *file_name;
4877        AST_type_n_t *ptr_type_p = type_p->fe_info->type_specific.pointer_type;
4878
4879        CHECKER_error(type_p, NIDL_MAXIDTYPPT, max_len);
4880        /* Give location of pointer declaration that points at this type. */
4881        STRTAB_str_to_string(ptr_type_p->fe_info->file, &file_name);
4882        CHECKER_warning(type_p, NIDL_NAMEREFAT, file_name,
4883            ptr_type_p->fe_info->source_line);
4884    }
4885
4886    max_len = MAX_ID - strlen("_mrV");
4887    if (!AST_LOCAL_SET(int_p)
4888        &&  (AST_IN_VARYING_SET(type_p) || AST_OUT_VARYING_SET(type_p))
4889        &&  type_len > max_len
4890        &&  FE_TEST(type_p->fe_info->flags,FE_POINTED_AT))
4891    {
4892        char const *file_name;
4893        AST_type_n_t *ptr_type_p = type_p->fe_info->type_specific.pointer_type;
4894
4895        CHECKER_error(type_p, NIDL_MAXIDTYPPT, max_len);
4896        /* Give location of pointer declaration that points at this type. */
4897        STRTAB_str_to_string(ptr_type_p->fe_info->file, &file_name);
4898        CHECKER_warning(type_p, NIDL_NAMEREFAT, file_name,
4899            ptr_type_p->fe_info->source_line);
4900    }
4901
4902    /* Maximum identifier length for pipe type is <n> characters */
4903
4904    max_len = MAX_ID - strlen("_h");
4905    if (!AST_LOCAL_SET(int_p)
4906        &&  type_len > max_len
4907        &&  type_p->kind == AST_pipe_k)
4908        CHECKER_error(type_p, NIDL_MAXIDTYPPIPE, max_len);
4909
4910    /* Maximum identifier length for [represent_as] type is <n> characters */
4911
4912    max_len = MAX_ID - strlen("_from_local");
4913    if (!AST_LOCAL_SET(int_p)
4914        &&  type_len > max_len
4915        &&  type_p->rep_as_type != NULL)
4916        CHECKER_error(type_p, NIDL_MAXIDTYPRA, max_len);
4917
4918    /* Maximum identifier length for [out_of_line] type is <n> characters */
4919
4920    max_len = MAX_ID - strlen("Omr");
4921    if (!AST_LOCAL_SET(int_p)
4922        &&  !AST_IN_VARYING_SET(type_p) && !AST_OUT_VARYING_SET(type_p)
4923        &&  type_len > max_len
4924        &&  AST_OUT_OF_LINE_SET(type_p))
4925        CHECKER_error(type_p, NIDL_MAXIDTYPOOL, max_len);
4926
4927    max_len = MAX_ID - strlen("OmrV");
4928    if (!AST_LOCAL_SET(int_p)
4929        &&  (AST_IN_VARYING_SET(type_p) || AST_OUT_VARYING_SET(type_p))
4930        &&  type_len > max_len
4931        &&  AST_OUT_OF_LINE_SET(type_p))
4932        CHECKER_error(type_p, NIDL_MAXIDTYPOOL, max_len);
4933}
4934
4935/*
4936**  t y p e _ i n _ l i n e
4937**
4938**  Checks a type node's [in_line] and [out_of_line] attributes.
4939*/
4940
4941static void type_in_line
4942(
4943    AST_type_n_t        *type_p         /* [in] Ptr to AST type node */
4944)
4945{
4946    /* Can't have both [in_line] and [out_of_line] type attributes */
4947
4948    if (AST_IN_LINE_SET(type_p)
4949        &&  AST_OUT_OF_LINE_SET(type_p))
4950        CHECKER_acf_error(type_p, NIDL_TYPLINEATTR);
4951
4952    /* [in_line] and [out_of_line] attributes apply only to non-scalar types */
4953
4954    if ((AST_IN_LINE_SET(type_p) || AST_OUT_OF_LINE_SET(type_p))
4955        &&  type_is_scalar(type_p))
4956    {
4957        char const *file_name;     /* Related file name */
4958        char const *type_name;     /* Data type name */
4959
4960        STRTAB_str_to_string(type_p->fe_info->file, &file_name);
4961        NAMETABLE_id_to_string(type_p->name, &type_name);
4962
4963        CHECKER_acf_warning(type_p, NIDL_LINENONSCAL);
4964        CHECKER_acf_warning(type_p, NIDL_NAMEDECLAT, type_name, file_name,
4965                          type_p->fe_info->source_line);
4966    }
4967}
4968
4969/*
4970**  t y p e _ s t r i n g
4971**
4972**  Checks a type node's [string] and [v1_string] attributes.
4973*/
4974
4975static void type_string
4976(
4977    AST_type_n_t        *type_p         /* [in] Ptr to AST type node */
4978)
4979{
4980    /* A [v1_string] must be an array of char with fixed bounds */
4981
4982    if (AST_STRING0_SET(type_p)
4983        &&  !type_is_v1_string(type_p))
4984        CHECKER_error(type_p, NIDL_STRV1FIXED);
4985
4986    /* The [string] attribute cannot be applied to a [v1_array] */
4987
4988    if (AST_STRING_SET(type_p) && AST_SMALL_SET(type_p))
4989        CHECKER_error(type_p, NIDL_STRARRAYV1);
4990
4991    /* [string] attribute valid only for one-dim arrays of char or byte */
4992
4993    if (AST_STRING_SET(type_p)
4994        &&  !type_is_string(type_p))
4995        CHECKER_error(type_p, NIDL_STRCHARBYTE);
4996
4997    /* Cannot have both [string] and [v1_string] attributes */
4998
4999    if (AST_STRING_SET(type_p)
5000        &&  AST_STRING0_SET(type_p))
5001    {
5002        ASTP_attr_flag_t attr1 = ASTP_STRING;
5003        ASTP_attr_flag_t attr2 = ASTP_STRING0;
5004
5005        CHECKER_error(type_p, NIDL_CONFLICTATTR,
5006            KEYWORDS_lookup_text(AST_attribute_to_token(&attr1)),
5007            KEYWORDS_lookup_text(AST_attribute_to_token(&attr2)));
5008    }
5009}
5010
5011/*
5012**  t y p e _ p o i n t e r
5013**
5014**  Checks a type node's attributes related to pointers.
5015*/
5016
5017static void type_pointer
5018(
5019    AST_type_n_t        *type_p         /* [in] Ptr to AST type node */
5020)
5021{
5022    boolean pointer_attr_valid = FALSE;
5023
5024    if (type_p->kind == AST_array_k
5025        ||  (type_p->kind == AST_pointer_k
5026            &&  type_p->type_structure.pointer->pointee_type->kind
5027                != AST_void_k))
5028        pointer_attr_valid = TRUE;
5029
5030    /* [ref] attribute valid only for pointer or array types */
5031
5032    if (AST_REF_SET(type_p) && !pointer_attr_valid)
5033        CHECKER_error(type_p, NIDL_REFATTRPTR);
5034
5035    /* [unique] attribute valid only for pointer or array types */
5036
5037    if (AST_UNIQUE_SET(type_p) && !pointer_attr_valid)
5038        CHECKER_error(type_p, NIDL_UNIQATTRPTR);
5039#if 0
5040	/* ignore REF, UNIQUE or PTR for pointers to interfaces */
5041	 if (type_p->kind == AST_pointer_k && type_p->type_structure.pointer->pointee_type->kind == AST_interface_k
5042			 && (AST_UNIQUE_SET(type_p) || AST_REF_SET(type_p) || AST_PTR_SET(type_p)))
5043		 CHECKER_warning(type_p, NIDL_PTRATTBIGN);
5044#endif
5045    /* [ptr] attribute valid only for pointer or array types */
5046
5047    if (AST_PTR_SET(type_p) && !pointer_attr_valid)
5048        CHECKER_error(type_p, NIDL_PTRATTRPTR);
5049
5050    /* [unique] attribute requires -standard extended */
5051
5052    if (AST_UNIQUE_SET(type_p)
5053        &&  (*(int *)cmd_val[opt_standard] <= opt_standard_dce_1_0))
5054        CHECKER_warning(type_p, NIDL_NOPORTUNIQUE, OPT_STD_EXTENDED);
5055
5056    /* An array with a pointer attribute is valid only as a parameter. */
5057
5058    if (FE_TEST(type_p->fe_info->flags, FE_HAS_PTR_ARRAY))
5059        CHECKER_error(type_p, NIDL_ARRPTRPRM);
5060
5061    /* Cannot have more than one level of indirection to a ne union */
5062
5063#if 0
5064    {
5065    AST_type_n_t *top_type_p = type_p;
5066    type_p = ASTP_chase_ptr_to_kind(type_p, AST_disc_union_k);
5067    if (type_p != NULL
5068        &&  type_p->kind == AST_disc_union_k
5069        &&  type_p->type_structure.disc_union->discrim_name == NAMETABLE_NIL_ID
5070        &&  type_p->fe_info->pointer_count > 1)
5071        CHECKER_error(top_type_p, NIDL_PTRNEUNION);
5072    }
5073#endif
5074}
5075
5076/*
5077**  t y p e _ s m a l l
5078**
5079**  Checks a type node's [v1_array] attribute.
5080*/
5081
5082static void type_small
5083(
5084    AST_type_n_t        *type_p         /* [in] Ptr to AST type node */
5085)
5086{
5087    AST_array_n_t       *array_p;       /* Ptr to array node */
5088
5089    /* A [v1_array] must be in array, not pointer, syntax */
5090
5091    if (AST_SMALL_SET(type_p)
5092        &&  type_p->kind == AST_pointer_k)
5093        CHECKER_error(type_p, NIDL_SMALLARRSYN);
5094
5095    /*
5096     * Remaining checks only apply to array types in array syntax.
5097     * V1 did not allow arrays in pointer syntax.
5098     */
5099    if (!type_is_array_np(type_p))
5100        return;
5101
5102    array_p = type_p->type_structure.array;
5103
5104    /* A [v1_array] can be conformant or varying in the first dimension only */
5105
5106    if (AST_SMALL_SET(type_p)
5107        &&  AST_CONFORMANT_SET(type_p)
5108        &&  array_is_conformant_upper(array_p))
5109        CHECKER_error(type_p, NIDL_SMALLMULTID);
5110
5111    /* [v1_array] attribute invalid for array with more than 65535 elements */
5112
5113    if (AST_SMALL_SET(type_p)
5114        &&  array_is_large(array_p))
5115        CHECKER_error(type_p, NIDL_SMALLINV);
5116
5117    /* A [v1_array] cannot have a conformant lower bound */
5118
5119    if (AST_SMALL_SET(type_p)
5120        &&  AST_CONFORMANT_SET(type_p)
5121        &&  array_has_open_lb(array_p))
5122        CHECKER_error(type_p, NIDL_SMALLOPENLB);
5123}
5124
5125/*
5126**  t y p e _ c o n t e x t
5127**
5128**  Checks a type node's [context_handle] and [handle] attributes.
5129*/
5130
5131static void type_context
5132(
5133    AST_type_n_t        *type_p         /* [in] Ptr to AST type node */
5134)
5135{
5136    /* [context_handle] attribute only applies to void * types */
5137
5138    if (AST_CONTEXT_RD_SET(type_p)
5139        &&  (type_p->kind != AST_pointer_k
5140            ||  (type_p->kind == AST_pointer_k
5141                &&  type_p->type_structure.pointer->pointee_type->kind
5142                    != AST_void_k
5143                    /* OK in opaque context handle typedef */
5144                &&  !(type_p->type_structure.pointer->pointee_type->kind
5145                      == AST_structure_k
5146                      && AST_DEF_AS_TAG_SET(type_p->type_structure.pointer->
5147                                            pointee_type)))))
5148        CHECKER_error(type_p, NIDL_CTXPTRVOID);
5149
5150    /* [unique] pointers to context handles are not allowed */
5151
5152    if (AST_UNIQUE_SET(type_p)
5153        &&  type_p->kind == AST_pointer_k
5154        &&  AST_CONTEXT_RD_SET(type_p->type_structure.pointer->pointee_type))
5155        CHECKER_error(type_p, NIDL_UNIQCTXHAN);
5156
5157    /* Full pointers to context handles are not allowed */
5158
5159    if (AST_PTR_SET(type_p)
5160        &&  type_p->kind == AST_pointer_k
5161        &&  AST_CONTEXT_RD_SET(type_p->type_structure.pointer->pointee_type))
5162        CHECKER_error(type_p, NIDL_PTRCTXHAN);
5163
5164    /* Attribute [handle] cannot be applied to a void * type */
5165
5166    if (AST_HANDLE_SET(type_p)
5167        && type_p->kind == AST_pointer_k
5168        && type_p->type_structure.pointer->pointee_type->kind == AST_void_k)
5169    {
5170        ASTP_attr_flag_t attr1 = ASTP_HANDLE;
5171        CHECKER_error(type_p, NIDL_ATTRPTRVOID,
5172            KEYWORDS_lookup_text(AST_attribute_to_token(&attr1)));
5173    }
5174
5175    /* The [handle] attribute is valid only on transmittable types */
5176
5177    if (AST_HANDLE_SET(type_p)
5178        && type_p->kind == AST_handle_k)
5179        CHECKER_error(type_p, NIDL_HANATTRTRAN);
5180
5181    /* The attributes [handle] and [represent_as] cannot occur together */
5182
5183    if (AST_HANDLE_SET(type_p)
5184        && type_p->rep_as_type != NULL)
5185    {
5186        ASTP_attr_flag_t attr1 = ASTP_HANDLE;
5187        CHECKER_error(type_p, NIDL_CONFLICTATTR,
5188            KEYWORDS_lookup_text(AST_attribute_to_token(&attr1)),
5189            "represent_as");
5190    }
5191}
5192
5193/*
5194**  t y p e _ c o n f o r m a n t
5195**
5196**  Checks a type node's "conformant" (synthesized) attribute.
5197*/
5198
5199static void type_conformant
5200(
5201    AST_type_n_t        *type_p,        /* [in] Ptr to AST type node */
5202    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
5203)
5204{
5205    AST_array_n_t       *array_p;       /* Ptr to array node */
5206
5207    /* Remaining check only applies to array types in array syntax. */
5208
5209    if (!type_is_array_np(type_p))
5210        return;
5211
5212    array_p = type_p->type_structure.array;
5213
5214    /* Arrays conformant in other than first dim require -standard extended */
5215
5216    if (!AST_LOCAL_SET(int_p)
5217        &&  AST_CONFORMANT_SET(type_p)
5218        &&  array_is_conformant_upper(array_p)
5219        &&  (*(int *)cmd_val[opt_standard] <= opt_standard_dce_1_0))
5220        CHECKER_warning(type_p, NIDL_NOPORTCFMT, OPT_STD_EXTENDED);
5221}
5222
5223/*
5224**  t y p e _ i g n o r e
5225**
5226**  Checks a type node's [ignore] attribute.
5227*/
5228
5229static void type_ignore
5230(
5231    AST_type_n_t        *type_p         /* [in] Ptr to AST type node */
5232)
5233{
5234    /* The [ignore] attribute is valid only for pointers */
5235
5236    if (AST_IGNORE_SET(type_p)
5237        &&  type_p->kind != AST_pointer_k)
5238        CHECKER_error(type_p, NIDL_IGNATTRPTR);
5239}
5240
5241/*
5242**  t y p e _ s w i t c h _ t y p e
5243**
5244**  Checks a type node's [switch_type] attribute.
5245*/
5246
5247static void type_switch_type
5248(
5249    AST_type_n_t        *type_p         /* [in] Ptr to AST type node */
5250)
5251{
5252    /* A non-encapsulated union type must have a [switch_type] attribute */
5253
5254    if (type_p->kind == AST_disc_union_k
5255        &&  type_p->type_structure.disc_union->discrim_name == NAMETABLE_NIL_ID
5256        &&  type_p->type_structure.disc_union->discrim_type == NULL)
5257        CHECKER_error(type_p, NIDL_NEUSWTYPE);
5258}
5259
5260/*
5261**  t y p e _ t r a n s m i t _ a s
5262**
5263**  Checks a type node's [transmit_as] attribute.
5264*/
5265
5266static void type_transmit_as
5267(
5268    AST_type_n_t        *top_type_p,    /* [in] Top-level presented type */
5269    AST_type_n_t        *type_p         /* [in] Ptr to AST type node */
5270)
5271{
5272    if (top_type_p->xmit_as_type == NULL)   /* Presented type = transmit type */
5273        return;
5274
5275    /*
5276     *  types with [transmit_as] can't be conformant not locally because
5277     *  of conversion routines and not on the net because of the net type is
5278     *  freed immediately after marshalling so there is no place to unmarshall
5279     *  the net type in to on the client side after the call.  This restriction
5280     *  could be lifted with enough programming.
5281     */
5282
5283    /* Local [transmit_as] type can not be a conformant array */
5284
5285    if (AST_CONFORMANT_SET(type_p)
5286        &&  !AST_STRING_SET(type_p)
5287        &&  type_is_array(type_p))
5288        CHECKER_error(top_type_p, NIDL_XMITCFMTARR);
5289
5290    /* Net [transmit_as] type can not be a conformant array */
5291
5292    if (AST_CONFORMANT_SET(top_type_p->xmit_as_type)
5293        &&  !AST_STRING_SET(top_type_p->xmit_as_type)
5294        &&  type_is_array(top_type_p->xmit_as_type))
5295        CHECKER_error(top_type_p, NIDL_XMITCFMTARR);
5296
5297    /* Presented type can't be conformant */
5298
5299    if (AST_CONFORMANT_SET(top_type_p)
5300        &&  top_type_p->kind == AST_structure_k)
5301        CHECKER_error(top_type_p, NIDL_STRUCTXMITCFMT);
5302
5303    /* A translated transmissible type cannot contain pointers. */
5304
5305    if (FE_TEST(type_p->fe_info->flags, FE_HAS_REF_PTR))
5306    {
5307        ASTP_attr_flag_t attr = ASTP_REF;
5308
5309        CHECKER_error(type_p, NIDL_XMITPTR,
5310            KEYWORDS_lookup_text(AST_attribute_to_token(&attr)));
5311    }
5312    if (FE_TEST(type_p->fe_info->flags, FE_HAS_FULL_PTR))
5313    {
5314        ASTP_attr_flag_t attr = ASTP_PTR;
5315
5316        CHECKER_error(type_p, NIDL_XMITPTR,
5317            KEYWORDS_lookup_text(AST_attribute_to_token(&attr)));
5318    }
5319    if (FE_TEST(type_p->fe_info->flags, FE_HAS_UNIQUE_PTR))
5320    {
5321        ASTP_attr_flag_t attr = ASTP_UNIQUE;
5322
5323        CHECKER_error(type_p, NIDL_XMITPTR,
5324            KEYWORDS_lookup_text(AST_attribute_to_token(&attr)));
5325    }
5326
5327    /* A type used in a transmit_as clause cannot have a represent_as type */
5328
5329    if (type_p->rep_as_type != NULL)
5330        CHECKER_error(type_p, NIDL_XMITASREP);
5331
5332    /* A type with [transmit_as] may not have other type attributes */
5333
5334    if (AST_STRING_SET(top_type_p)
5335        ||  AST_STRING0_SET(top_type_p)
5336        ||  AST_UNIQUE_SET(top_type_p)
5337        ||  AST_REF_SET(top_type_p)
5338        ||  AST_IGNORE_SET(top_type_p)
5339        ||  AST_SMALL_SET(top_type_p)
5340        ||  AST_CONTEXT_RD_SET(top_type_p)
5341        ||  AST_PTR_SET(top_type_p))
5342        CHECKER_error(top_type_p, NIDL_XMITTYPEATTRS);
5343
5344    /* A [transmit_as] type cannot be a non-encapsulated union */
5345
5346    if (type_p->kind == AST_disc_union_k
5347        &&  type_p->type_structure.disc_union->discrim_name == NAMETABLE_NIL_ID)
5348        CHECKER_error(top_type_p, NIDL_NEUXMITAS);
5349
5350    /* A non-encapsulated union cannot have a [transmit_as] type */
5351
5352    if (top_type_p->kind == AST_disc_union_k
5353     && top_type_p->type_structure.disc_union->discrim_name == NAMETABLE_NIL_ID)
5354        CHECKER_error(top_type_p, NIDL_NEUXMITYPE);
5355}
5356
5357/*
5358**  t y p e _ r e p r e s e n t _ a s
5359**
5360**  Checks a type node's [represent_as] attribute.
5361*/
5362
5363static void type_represent_as
5364(
5365    AST_type_n_t        *type_p,        /* [in] Top-level presented type */
5366    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
5367)
5368{
5369    if (type_p->rep_as_type == NULL)   /* Presented type = Net type */
5370        return;
5371
5372    /*
5373     *  types with [represent_as] can't be conformant on the net because the
5374     *  net type is freed immediately after marshalling so there is no place to
5375     *  unmarshall the net type in to on the client side after the call.  This
5376     *  restriction could be lifted with enough programming.
5377     */
5378
5379    /* Net type can not be conformant */
5380
5381    if (AST_CONFORMANT_SET(type_p))
5382        CHECKER_error(type_p, NIDL_TYPEREPCFMT);
5383
5384    /* A translated transmissible type cannot contain pointers. */
5385
5386    if (FE_TEST(type_p->fe_info->flags, FE_HAS_REF_PTR))
5387    {
5388        ASTP_attr_flag_t attr = ASTP_REF;
5389
5390        CHECKER_error(type_p, NIDL_XMITPTR,
5391            KEYWORDS_lookup_text(AST_attribute_to_token(&attr)));
5392    }
5393    if (FE_TEST(type_p->fe_info->flags, FE_HAS_FULL_PTR))
5394    {
5395        ASTP_attr_flag_t attr = ASTP_PTR;
5396
5397        CHECKER_error(type_p, NIDL_XMITPTR,
5398            KEYWORDS_lookup_text(AST_attribute_to_token(&attr)));
5399    }
5400    if (FE_TEST(type_p->fe_info->flags, FE_HAS_UNIQUE_PTR))
5401    {
5402        ASTP_attr_flag_t attr = ASTP_UNIQUE;
5403
5404        CHECKER_error(type_p, NIDL_XMITPTR,
5405            KEYWORDS_lookup_text(AST_attribute_to_token(&attr)));
5406    }
5407
5408    /* ACF 'include' statement advised for definition of type 'name' */
5409
5410    if (int_p->includes == NULL
5411        &&  ASTP_lookup_binding(null_parser_location,
5412				type_p->rep_as_type->type_name,
5413                                fe_type_n_k, FALSE) == NULL)
5414    {
5415        char const*id_name;
5416
5417        NAMETABLE_id_to_string(type_p->rep_as_type->type_name, &id_name);
5418        CHECKER_acf_warning(type_p, NIDL_INCLTYPE, id_name);
5419    }
5420
5421    {
5422    AST_type_n_t *rep_type_p = (AST_type_n_t *) /* IDL rep_as type, if any */
5423        ASTP_lookup_binding(null_parser_location,
5424			type_p->rep_as_type->type_name, fe_type_n_k, FALSE);
5425
5426    /* A [represent_as] type cannot be a non-encapsulated union */
5427
5428    if (rep_type_p != NULL
5429        &&  rep_type_p->kind == AST_disc_union_k
5430        &&  rep_type_p->type_structure.disc_union->discrim_name
5431            == NAMETABLE_NIL_ID)
5432        CHECKER_acf_error(type_p, NIDL_NEUREPAS);
5433    }
5434
5435    /* A non-encapsulated union cannot have a [represent_as] type */
5436
5437    if (type_p->kind == AST_disc_union_k
5438        &&  type_p->type_structure.disc_union->discrim_name == NAMETABLE_NIL_ID)
5439        CHECKER_acf_error(type_p, NIDL_NEUREPTYPE);
5440}
5441
5442/*
5443**  t y p e _ c h e c k
5444**
5445**  Checks an AST type node.
5446*/
5447
5448static void type_check
5449(
5450    AST_type_n_t        *type_p,        /* [in] Ptr to AST type node */
5451    ASTP_node_t         *node_p,        /* [in] Parent node of type node */
5452    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
5453)
5454{
5455    AST_type_n_t        *xmit_type_p;   /* Transmissible type */
5456	char const * id_name;
5457    /*
5458     * Pick up the transmissible type (the top-level, presented, type is
5459     * different from the the transmissible type if it has a [transmit_as]).
5460     * Most checks are done on the transmissible, not presented, type.
5461     */
5462    xmit_type_p = type_xmit_type(type_p);
5463
5464    if (!AST_LOCAL_SET(int_p))
5465        type_name_len(type_p, xmit_type_p, int_p);
5466
5467    type_in_line(xmit_type_p);
5468    type_string(xmit_type_p);
5469    type_pointer(xmit_type_p);
5470    type_small(xmit_type_p);
5471    type_context(xmit_type_p);
5472    type_conformant(xmit_type_p, int_p);
5473    type_ignore(xmit_type_p);
5474    type_switch_type(xmit_type_p);
5475    type_transmit_as(type_p, xmit_type_p);
5476    type_represent_as(xmit_type_p, int_p);
5477    CHK_type_cs(type_p, xmit_type_p, int_p);
5478
5479    /* V1 attributes are incompatible with this type */
5480
5481    if (FE_TEST(type_p->fe_info->flags, FE_HAS_V1_ATTR)
5482        &&  FE_TEST(type_p->fe_info->flags, FE_HAS_V2_ATTR))
5483        CHECKER_warning(type_p, NIDL_INCOMPATV1);
5484
5485    switch (type_p->kind)
5486    {
5487    case AST_handle_k:
5488    case AST_boolean_k:
5489    case AST_byte_k:
5490    case AST_character_k:
5491    case AST_small_integer_k:
5492    case AST_short_integer_k:
5493    case AST_long_integer_k:
5494    case AST_hyper_integer_k:
5495    case AST_small_unsigned_k:
5496    case AST_short_unsigned_k:
5497    case AST_long_unsigned_k:
5498    case AST_hyper_unsigned_k:
5499    case AST_short_float_k:
5500    case AST_long_float_k:
5501    case AST_void_k:
5502        break;      /* No checks for these types */
5503
5504    case AST_enum_k:
5505        enum_check(type_p->type_structure.enumeration, type_p);
5506        break;
5507
5508    case AST_array_k:
5509        array_check((ASTP_node_t *)type_p->type_structure.array,
5510                    type_p,
5511                    node_p,
5512                    type_p->type_structure.array->element_type,
5513                    int_p,
5514                    false);
5515        break;
5516
5517    case AST_structure_k:
5518        struct_check(type_p->type_structure.structure, int_p);
5519        break;
5520
5521    case AST_pipe_k:
5522        pipe_check(type_p->type_structure.pipe, type_p, int_p);
5523        break;
5524
5525    case AST_pointer_k:
5526        ptr_check(type_p->type_structure.pointer, type_p, node_p, int_p);
5527        break;
5528
5529    case AST_function_k:
5530        /* Function type declaration is not allowed */
5531        if (!AST_LOCAL_SET(int_p))
5532            CHECKER_error(type_p, NIDL_FUNTYPDCL);
5533        break;
5534
5535    case AST_disc_union_k:
5536        union_check(type_p->type_structure.disc_union, int_p);
5537        break;
5538
5539	case AST_interface_k:
5540		  /* Interface type declaration is not allowed */
5541		  NAMETABLE_id_to_string(type_p->name, &id_name);
5542		  CHECKER_error(type_p, NIDL_INTREFNOTALO, id_name);
5543		  break;
5544
5545    default:
5546        error(NIDL_INTERNAL_ERROR, __FILE__, __LINE__);
5547    }
5548}
5549
5550/*
5551**  c o n s t a n t _ c h e c k
5552**
5553**  Checks an AST constant node.
5554*/
5555
5556static void constant_check
5557(
5558    AST_constant_n_t    *const_p ATTRIBUTE_UNUSED       /* [in] Ptr to AST constant node */
5559)
5560{
5561}
5562
5563/*
5564**  e x p o r t _ c h e c k
5565**
5566**  Checks an AST export node.
5567*/
5568
5569static void export_check
5570(
5571    AST_export_n_t      *export_p,      /* [in] Ptr to AST export node */
5572    AST_interface_n_t   *int_p,         /* [in] Ptr to interface node */
5573    AST_interface_n_t   *parent_int_p   /* [in] Parent interface node */
5574)
5575{
5576
5577    switch (export_p->kind)
5578    {
5579    case AST_cpp_quote_k:
5580        break;
5581
5582    case AST_constant_k:
5583        constant_check(export_p->thing_p.exported_constant);
5584        break;
5585
5586    case AST_operation_k:
5587        if (parent_int_p == NULL)   /* main interface */
5588            operation_check(export_p->thing_p.exported_operation, int_p);
5589        break;
5590
5591    case AST_type_k:
5592        type_check(export_p->thing_p.exported_type, (ASTP_node_t *)export_p,
5593                   int_p);
5594        break;
5595
5596    default:
5597        error(NIDL_INTERNAL_ERROR, __FILE__, __LINE__);
5598    }
5599}
5600
5601/*
5602**  i n t _ n a m e _ l e n
5603**
5604**  Checks an interface node's name length.
5605*/
5606
5607static void int_name_len
5608(
5609    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
5610)
5611{
5612    char const   *int_name;      /* Interface name */
5613    unsigned int max_len;        /* Maximum identifier length */
5614
5615    NAMETABLE_id_to_string(int_p->name, &int_name);
5616    if (int_name == NULL)
5617        return;     /* Shouldn't happen */
5618
5619    /* Maximum identifier length for interface name is <n> characters */
5620
5621    max_len = MAX_ID - strlen("_v#_#_c_ifspec");    /* Could do better here */
5622    if (strlen(int_name) > max_len)
5623        CHECKER_error(int_p, NIDL_MAXIDINTF, max_len);
5624}
5625
5626/*
5627**  i n t _ i n _ l i n e
5628**
5629**  Checks an interface node's [in_line] and [out_of_line] attributes.
5630*/
5631
5632static void int_in_line
5633(
5634    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
5635)
5636{
5637    /* Can't have both [in_line] and [out_of_line] interface attributes */
5638
5639    if (AST_IN_LINE_SET(int_p)
5640        &&  AST_OUT_OF_LINE_SET(int_p))
5641        CHECKER_acf_error(int_p, NIDL_INTLINEATTR);
5642}
5643
5644/*
5645**  i n t _ c o d e
5646**
5647**  Checks an interface node's [code] and [nocode] attributes.
5648*/
5649
5650static void int_code
5651(
5652    AST_interface_n_t   *int_p,         /* [in] Ptr to interface node */
5653    AST_interface_n_t   *parent_int_p   /* [in] Parent interface node */
5654)
5655{
5656    /* Can't have both [code] and [nocode] interface attributes */
5657
5658    if (AST_CODE_SET(int_p)
5659        &&  AST_NO_CODE_SET(int_p))
5660        CHECKER_acf_error(int_p, NIDL_INTCODEATTR);
5661
5662    /* [nocode] attribute does not apply to server stub */
5663
5664    if (parent_int_p == NULL    /* main interface */
5665        &&  AST_NO_CODE_SET(int_p)
5666        &&  cmd_opt[opt_emit_sstub]
5667        &&  !cmd_opt[opt_emit_cstub])
5668        CHECKER_acf_warning(int_p, NIDL_SRVNOCODE);
5669
5670    /* At least one operation should have the [code] attribute */
5671
5672    if (parent_int_p == NULL    /* main interface */
5673        &&  int_p->op_count > 0)
5674    {
5675        AST_export_n_t *export_p;
5676        boolean code_op = FALSE;
5677
5678        for (export_p = int_p->exports; export_p; export_p = export_p->next)
5679        {
5680            if (export_p->kind != AST_operation_k) continue;
5681            if (AST_CODE_SET(export_p->thing_p.exported_operation))
5682            {
5683                code_op = TRUE;
5684                break;
5685            }
5686        }
5687        if (!code_op)
5688            CHECKER_acf_warning(int_p, NIDL_NOCODEOPS);
5689    }
5690}
5691
5692/*
5693**  i n t _ h a n d l e
5694**
5695**  Checks an interface node's attributes relating to handles/binding.
5696*/
5697
5698static void int_handle
5699(
5700    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
5701)
5702{
5703    /* Can't have both [auto_handle] and [implicit_handle] interface attrs */
5704
5705    if (int_p->implicit_handle_name != NAMETABLE_NIL_ID
5706        &&  AST_AUTO_HANDLE_SET(int_p))
5707        CHECKER_acf_error(int_p, NIDL_CONFHANATTR);
5708
5709    /*
5710     * [implicit_handle] variable must either be of type handle_t
5711     * or have the [handle] type attribute
5712     */
5713    if (int_p->implicit_handle_name != NAMETABLE_NIL_ID
5714        &&  int_p->implicit_handle_type != NULL /* is an IDL-defined type */
5715        &&  !type_is_handle(int_p->implicit_handle_type))
5716        CHECKER_acf_error(int_p, NIDL_IMPHANVAR);
5717}
5718
5719/*
5720**  i n t _ l o c a l
5721**
5722**  Checks an interface node's [local] and [uuid] attributes.
5723*/
5724
5725static void int_local
5726(
5727    AST_interface_n_t   *int_p,         /* [in] Ptr to interface node */
5728    AST_interface_n_t   *parent_int_p   /* [in] Parent interface node */
5729)
5730{
5731    boolean             uuid_null;
5732
5733    uuid_null = uuid_is_null(&int_p->uuid);
5734
5735    /* [uuid] attribute invalid when [local] attribute is specified */
5736
5737    if (AST_LOCAL_SET(int_p)
5738        &&  !uuid_null && !AST_OBJECT_SET(int_p))
5739        CHECKER_error(int_p, NIDL_UUIDINV);
5740
5741    /*
5742     * If this is a non-local interface being imported by a local interface,
5743     * then pretend that it is a local interface as well.
5744     */
5745    if (!AST_LOCAL_SET(int_p)
5746        &&  parent_int_p != NULL
5747        &&  AST_LOCAL_SET(parent_int_p))
5748        AST_SET_LOCAL(int_p);
5749
5750    /* Interface UUID must be specified */
5751
5752    if (!AST_LOCAL_SET(int_p)
5753        &&  uuid_null
5754        &&  parent_int_p == NULL    /* main interface */
5755        &&  int_p->op_count != 0)
5756        CHECKER_error(int_p, NIDL_INTUUIDREQ);
5757
5758    /* A non-local interface cannot import a local interface */
5759
5760    if (parent_int_p != NULL
5761        &&  !AST_LOCAL_SET(parent_int_p)
5762        &&  AST_LOCAL_SET(int_p))
5763        CHECKER_error(int_p, NIDL_IMPORTLOCAL);
5764}
5765
5766/* Checks an interface node's inheritance attributes */
5767static void int_inherit(AST_interface_n_t * int_p)
5768{
5769	char const * id_name;	/* name for [switch_is] */
5770	/* check to see if there is a binding for the inherited interface;
5771	 * if not, complain about it */
5772	if (int_p->inherited_interface_name != NAMETABLE_NIL_ID)	{
5773		/* WEZ:TODO only valid for ORPC */
5774		if (!NAMETABLE_lookup_local(int_p->inherited_interface_name))	{
5775			NAMETABLE_id_to_string(int_p->inherited_interface_name, &id_name);
5776			//CHECKER_error(int_p, NIDL_INHERITNOTDEF, id_name);
5777		}
5778	}
5779}
5780
5781/*
5782**  i n t e r f a c e _ c h e c k
5783**
5784**  Checks the AST interface node.
5785*/
5786
5787static void interface_check
5788(
5789    AST_interface_n_t   *int_p,         /* [in] Ptr to interface node */
5790    AST_interface_n_t   *parent_int_p   /* [in] Parent interface node */
5791)
5792{
5793    AST_export_n_t      *export_p;      /* Ptr to export node */
5794    AST_import_n_t      *import_p;      /* Ptr to import node */
5795
5796    int_name_len(int_p);
5797
5798    int_in_line(int_p);
5799    int_code(int_p, parent_int_p);
5800    int_handle(int_p);
5801    int_local(int_p, parent_int_p);
5802    int_inherit(int_p);
5803
5804    /* Check any interfaces that this interface imports. */
5805
5806    import_p = int_p->imports;
5807    while (import_p != NULL)
5808    {
5809        if (import_p->interface != NULL)
5810            interface_check(import_p->interface, int_p);
5811        import_p = import_p->next;
5812    }
5813
5814    /* Check everything that is exported by the interface. */
5815
5816    export_p = int_p->exports;
5817    while (export_p != NULL)
5818    {
5819        export_check(export_p, int_p, parent_int_p);
5820        export_p = export_p->next;
5821    }
5822
5823    /* For the main interface only, process the pointed-at types list. */
5824
5825    if (parent_int_p == NULL)
5826    {
5827        AST_type_p_n_t  *typep_p;
5828        AST_type_n_t    *type_p;
5829
5830        for (typep_p = int_p->pa_types
5831             ;  typep_p != NULL
5832             ;  typep_p = typep_p->next)
5833        {
5834            type_p = typep_p->type;
5835
5836            /* Pointers to [v1_enum] types are not allowed */
5837
5838            if (type_p->kind == AST_enum_k
5839                &&  AST_V1_ENUM_SET(type_p))
5840                CHECKER_error(type_p, NIDL_PTRV1ENUM);
5841        }
5842
5843        /* Use of [exceptions] attribute requires -standard extended */
5844        if (int_p->exceptions != NULL
5845            && (*(int *)cmd_val[opt_standard] < opt_standard_dce_1_1))
5846            CHECKER_warning(int_p, NIDL_NOPORTATTR,
5847                            "exceptions", OPT_STD_EXTENDED);
5848    }
5849	if (AST_OBJECT_SET(int_p) && ASTP_IF_AF_SET(int_p, ASTP_IF_VERSION))	{
5850		CHECKER_warning(int_p, NIDL_CONFLICTATTR, "version", "object");
5851	}
5852	if (!AST_OBJECT_SET(int_p) && int_p->inherited_interface_name != NAMETABLE_NIL_ID)	{
5853		CHECKER_warning(int_p, NIDL_ANCREQSOBJ);
5854	}
5855
5856}
5857
5858/*
5859**  C H E C K E R _ m a i n
5860**
5861**  Main routine of semantic checking component of IDL compiler.
5862**  Does semantic checking of the interface definition (and any imported
5863**  items that are referred to in the interface).
5864*/
5865
5866boolean CHECKER_main            /* Returns TRUE on success */
5867(
5868    boolean     *cmd_opt_arr,   /* [in] Array of command option flags */
5869    void        **cmd_val_arr,  /* [in] Array of command option values */
5870    AST_interface_n_t *int_p    /* [in] Ptr to AST interface node */
5871)
5872{
5873    /* Save passed command array addresses in static storage. */
5874    cmd_opt = cmd_opt_arr;
5875    cmd_val = cmd_val_arr;
5876
5877    /*
5878     * Check the interface.  The interface node is the root of the AST.
5879     * Each function above checks an AST node that hangs off the main
5880     * interface node.
5881     */
5882    interface_check(int_p, NULL);
5883
5884    /*
5885     * If we defaulted to auto_handle for any operations,
5886     * set [auto_handle] on the interface.
5887     */
5888    if (def_auto_handle > 0)
5889        AST_SET_AUTO_HANDLE(int_p);
5890
5891    /* Return success if no errors, failure otherwise. */
5892    return (error_count == 0);
5893}
5894
5895/*
5896**  C H E C K E R _ e r r o r
5897**
5898**  Handles any semantic errors detected.  Determines the source file and
5899**  line number of the error from the AST node; passes this information and
5900**  its remaining parameters onto the error logging routine.
5901**
5902*/
5903void CHECKER_error
5904(
5905    void                *in_node_p,
5906    long                msgid,
5907	...
5908)
5909{
5910    ASTP_node_t *node_p = in_node_p;
5911	va_list arglist;
5912
5913	va_start (arglist, msgid);
5914
5915    vlog_source_error(node_p->fe_info->file,
5916                     node_p->fe_info->source_line,
5917                     msgid, arglist);
5918
5919	va_end (arglist);
5920}
5921
5922/*
5923**  C H E C K E R _ w a r n i n g
5924**
5925**  Handles any semantic warnings detected.  Determines the source file and
5926**  line number of the warning from the AST node; passes this information and
5927**  its remaining parameters onto the warning logging routine.
5928**
5929*/
5930void CHECKER_warning
5931(
5932	void                *in_node_p,
5933	long                msgid,
5934	...
5935)
5936{
5937    ASTP_node_t *node_p = in_node_p;
5938	va_list arglist;
5939
5940	va_start (arglist, msgid);
5941
5942    vlog_source_warning(node_p->fe_info->file,
5943					  node_p->fe_info->source_line,
5944					  msgid, arglist);
5945
5946	va_end (arglist);
5947}
5948
5949/*
5950**  C H E C K E R _ a c f _ e r r o r
5951**
5952**  Handles any semantic errors detected on ACF-related attributes.  Determines
5953**  the source file and line number of the error from the AST node; passes this
5954**  information and its remaining parameters onto the error logging routine.
5955**
5956*/
5957void CHECKER_acf_error
5958(
5959	void                *in_node_p,
5960	long                msgid,
5961	...
5962)
5963{
5964    ASTP_node_t *node_p = in_node_p;
5965    va_list arglist;
5966
5967    va_start (arglist, msgid);
5968
5969    if (node_p->fe_info->acf_file != (STRTAB_str_t)0)
5970    {
5971        vlog_source_error(node_p->fe_info->acf_file,
5972                         node_p->fe_info->acf_source_line,
5973                         msgid, arglist);
5974    }
5975    else
5976    {
5977        vlog_source_error(node_p->fe_info->file,
5978                         node_p->fe_info->source_line,
5979                         msgid, arglist);
5980    }
5981
5982    va_end (arglist);
5983}
5984
5985/*
5986**  C H E C K E R _ a c f _ w a r n i n g
5987**
5988**  Handles any semantic warnings detected on ACF-related attrs.  Determines
5989**  the source file and line number of warning from the AST node; passes this
5990**  information and its remaining parameters onto the warning logging routine.
5991**
5992*/
5993void CHECKER_acf_warning
5994(
5995	void                *in_node_p,
5996	long                msgid,
5997	...
5998)
5999{
6000    ASTP_node_t *node_p = in_node_p;
6001	va_list arglist;
6002
6003	va_start (arglist, msgid);
6004
6005    if (node_p->fe_info->acf_file != (STRTAB_str_t)0)
6006        vlog_source_warning(node_p->fe_info->acf_file,
6007                           node_p->fe_info->acf_source_line,
6008                           msgid, arglist);
6009    else
6010        vlog_source_warning(node_p->fe_info->file,
6011                           node_p->fe_info->source_line,
6012                           msgid, arglist);
6013
6014	va_end (arglist);
6015}
6016
6017/*
6018**  t y p e _ i s _ b a s e
6019**
6020**  Returns true if the specified type node is for a base type, false otherwise.
6021*/
6022
6023boolean type_is_base
6024(
6025    AST_type_n_t *type_p    /* [in] Ptr to AST type node */
6026)
6027{
6028    return      ((type_p) == ASTP_char_ptr
6029        ||  (type_p) == ASTP_boolean_ptr
6030        ||  (type_p) == ASTP_byte_ptr
6031        ||  (type_p) == ASTP_void_ptr
6032        ||  (type_p) == ASTP_handle_ptr
6033        ||  (type_p) == ASTP_short_float_ptr
6034        ||  (type_p) == ASTP_long_float_ptr
6035        ||  (type_p) == ASTP_small_int_ptr
6036        ||  (type_p) == ASTP_short_int_ptr
6037        ||  (type_p) == ASTP_long_int_ptr
6038        ||  (type_p) == ASTP_hyper_int_ptr
6039        ||  (type_p) == ASTP_small_unsigned_ptr
6040        ||  (type_p) == ASTP_short_unsigned_ptr
6041        ||  (type_p) == ASTP_long_unsigned_ptr
6042        ||  (type_p) == ASTP_hyper_unsigned_ptr);
6043}
6044