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**      chkichar.c
82**
83**  FACILITY:
84**
85**      Interface Definition Language (IDL) Compiler
86**
87**  ABSTRACT:
88**
89**  IDL Compiler Semantic Checking for international character support.
90**
91*/
92
93#include <nidl.h>       /* Standard IDL defs */
94#include <checker.h>    /* Type and constant macros */
95#include <chkichar.h>   /* Protos for I-char checking */
96
97#include <acf_y.h>  /* ACF token values */
98#include <ast.h>        /* Abstract Syntax Tree defs */
99#include <astp.h>       /* AST processing defs */
100#include <command.h>    /* Command option defs */
101#include <errors.h>     /* Error reporting functions */
102#include <message.h>    /* reporting functions */
103
104/*
105**  C H K _ p a r a m _ c s
106**
107**  Checks a parameter node's I-char ([cs_*]) attributes.
108**  The passed type node is the dereferenced parameter type if the
109**  parameter is passed by reference.
110*/
111void CHK_param_cs
112(
113    AST_parameter_n_t   *param_p,       /* [in] Ptr to AST parameter node */
114    AST_type_n_t        *type_p         /* [in] Parameter type */
115)
116{
117    AST_parameter_n_t   *pp;
118    AST_field_attr_n_t  *fattr_p;
119
120    fattr_p = param_p->field_attrs;
121
122    /* Operation with [in] [cs_char] data requires [cs_stag] parameter */
123    if (AST_IN_SET(param_p)
124        && (type_p->cs_char_type != NULL
125            || FE_TEST(type_p->fe_info->flags, FE_CT_CS_CHAR)))
126    {
127        for (pp = param_p->uplink->parameters; pp != NULL; pp = pp->next)
128        {
129            if (AST_CS_STAG_SET(pp))
130                break;
131        }
132        if (pp == NULL)
133            CHECKER_acf_error(param_p, NIDL_OPINCSCHAR);
134    }
135
136    /* Operation with [out] [cs_char] data requires [cs_rtag] parameter */
137    if (AST_OUT_SET(param_p)
138        && (type_p->cs_char_type != NULL
139            || FE_TEST(type_p->fe_info->flags, FE_CT_CS_CHAR)))
140    {
141        for (pp = param_p->uplink->parameters; pp != NULL; pp = pp->next)
142        {
143            if (AST_CS_RTAG_SET(pp))
144                break;
145        }
146        if (pp == NULL)
147            CHECKER_acf_error(param_p, NIDL_OPOUTCSCHAR);
148    }
149
150    /* A [cs_stag] parameter must have the [in] attribute */
151    if (AST_CS_STAG_SET(param_p) && !AST_IN_SET(param_p))
152    {
153        ASTP_attr_flag_t attr2 = ASTP_IN;
154        CHECKER_error(param_p, NIDL_PRMDEPATTR, "cs_stag",
155            KEYWORDS_lookup_text(AST_attribute_to_token(&attr2)));
156    }
157
158    /* A [cs_drtag] parameter must have the [in] attribute */
159    if (AST_CS_DRTAG_SET(param_p) && !AST_IN_SET(param_p))
160    {
161        ASTP_attr_flag_t attr2 = ASTP_IN;
162        CHECKER_error(param_p, NIDL_PRMDEPATTR, "cs_drtag",
163            KEYWORDS_lookup_text(AST_attribute_to_token(&attr2)));
164    }
165
166    /* A [cs_rtag] parameter must have the [out] attribute */
167    if (AST_CS_RTAG_SET(param_p) && !AST_OUT_SET(param_p))
168    {
169        ASTP_attr_flag_t attr2 = ASTP_OUT;
170        CHECKER_error(param_p, NIDL_PRMDEPATTR, "cs_rtag",
171            KEYWORDS_lookup_text(AST_attribute_to_token(&attr2)));
172    }
173
174    /* Array attr can't be used for both [cs_char] and non-[cs_char] arrays */
175    if (FE_TEST(param_p->fe_info->flags, FE_USED_AS_CS_FLD_ATTR)
176        && FE_TEST(param_p->fe_info->flags, FE_USED_AS_REG_FLD_ATTR))
177        CHECKER_error(param_p, NIDL_ARRATTRSHR);
178
179    /* A [size_is] or [max_is] attr can't be applied to ptr to [cs_char] type */
180    if (type_p->kind == AST_pointer_k
181        && type_p->type_structure.pointer->pointee_type->cs_char_type != NULL
182        && fattr_p != NULL
183        && (fattr_p->max_is_vec != NULL || fattr_p->size_is_vec != NULL))
184        CHECKER_error(param_p, NIDL_CSARRSYN);
185
186    /* An array with [cs_char] base type cannot have [ptr] or [unique] attrs */
187    if (type_p->kind == AST_array_k
188        && type_p->type_structure.array->element_type->cs_char_type != NULL
189        && (AST_PTR_SET(param_p) || AST_UNIQUE_SET(param_p)))
190        CHECKER_error(param_p, NIDL_ARRPTRUNIQ, "cs_char");
191
192    /* A [cs_stag] param must precede any [in] [cs_char] data in a param list */
193    if (AST_CS_STAG_SET(param_p))
194    {
195        for (pp = param_p->uplink->parameters; pp != param_p; pp = pp->next)
196        {
197            if (AST_IN_SET(pp)
198                && (pp->type->cs_char_type != NULL
199                    || FE_TEST(pp->type->fe_info->flags, FE_CT_CS_CHAR)))
200                break;
201        }
202        if (pp != param_p)
203            CHECKER_error(param_p, NIDL_TAGBEFDATA);
204    }
205
206    /* A [cs_rtag] param must precede any [out][cs_char] data in a param list */
207    if (AST_CS_RTAG_SET(param_p))
208    {
209        for (pp = param_p->uplink->parameters; pp != param_p; pp = pp->next)
210        {
211            if (AST_OUT_SET(pp)
212                && (pp->type->cs_char_type != NULL
213                    || FE_TEST(pp->type->fe_info->flags, FE_CT_CS_CHAR)))
214                break;
215        }
216        if (pp != param_p)
217            CHECKER_error(param_p, NIDL_TAGAFTDATA);
218    }
219
220    /* A [handle] binding parameter cannot contain a [cs_char] type */
221    if (AST_HANDLE_SET(type_p)
222        && param_p == param_p->uplink->parameters   /* first param */
223        && (type_p->cs_char_type != NULL
224            || FE_TEST(type_p->fe_info->flags, FE_CT_CS_CHAR)))
225        CHECKER_error(param_p, NIDL_HANCTYPE, "cs_char");
226
227    /* Arrays of [cs_char] can only use the [size_is] and [length_is] attrs */
228    if (type_p->kind == AST_array_k
229        && type_p->type_structure.array->element_type->cs_char_type != NULL
230        && (AST_STRING_SET(type_p) || AST_STRING_SET(param_p)
231            || (fattr_p != NULL
232                && (fattr_p->min_is_vec != NULL
233                    || fattr_p->max_is_vec != NULL
234                    || fattr_p->first_is_vec != NULL
235                    || fattr_p->last_is_vec != NULL))))
236        CHECKER_error(param_p, NIDL_ARRTYPATTR, "cs_char");
237
238    /* Tag params must have type unsigned long int passed by value or ref */
239    if (  (AST_CS_STAG_SET(param_p)
240           || AST_CS_DRTAG_SET(param_p)
241           || AST_CS_RTAG_SET(param_p))
242        && type_p->kind != AST_long_unsigned_k )
243        CHECKER_error(param_p, NIDL_TAGPRMTYPE);
244
245    /* Use of [cs_stag] attribute requires -standard extended */
246    if (AST_CS_STAG_SET(param_p)
247        && (*(int *)CMD_vals[opt_standard] < opt_standard_dce_1_1))
248        CHECKER_acf_warning(param_p, NIDL_NOPORTATTR, "cs_stag",
249                            OPT_STD_EXTENDED);
250
251    /* Use of [cs_drtag] attribute requires -standard extended */
252    if (AST_CS_DRTAG_SET(param_p)
253        && (*(int *)CMD_vals[opt_standard] < opt_standard_dce_1_1))
254        CHECKER_acf_warning(param_p, NIDL_NOPORTATTR, "cs_drtag",
255                            OPT_STD_EXTENDED);
256
257    /* Use of [cs_rtag] attribute requires -standard extended */
258    if (AST_CS_RTAG_SET(param_p)
259        && (*(int *)CMD_vals[opt_standard] < opt_standard_dce_1_1))
260        CHECKER_acf_warning(param_p, NIDL_NOPORTATTR, "cs_rtag",
261                            OPT_STD_EXTENDED);
262}
263
264/*
265**  C H K _ o p _ c s
266**
267**  Checks an operation node's [cs_tag_rtn] attribute and other attributes
268**  relating to I-char support.
269*/
270void CHK_op_cs
271(
272    AST_operation_n_t   *op_p           /* [in] Ptr to AST operation node */
273)
274{
275    AST_parameter_n_t   *param_p;
276    int s=0, d=0, r=0;
277
278    /* Operation with [cs_tag_rtn] contains no codeset tag parameters */
279    if (op_p->cs_tag_rtn_name != NAMETABLE_NIL_ID)
280    {
281        for (param_p = op_p->parameters; param_p; param_p = param_p->next)
282        {
283            if (AST_CS_STAG_SET(param_p) || AST_CS_DRTAG_SET(param_p)
284                || AST_CS_RTAG_SET(param_p))
285                break;
286        }
287        if (param_p == NULL)
288            CHECKER_acf_warning(op_p, NIDL_OPNOTAGS);
289    }
290
291    /* The [name] attribute cannot be duplicated in the same parameter list */
292    for (param_p = op_p->parameters; param_p; param_p = param_p->next)
293    {
294        if (AST_CS_STAG_SET(param_p)) s++;
295        if (AST_CS_DRTAG_SET(param_p)) d++;
296        if (AST_CS_RTAG_SET(param_p)) r++;
297    }
298    if (s > 1)
299        CHECKER_acf_error(op_p, NIDL_DUPPRMATTR, "cs_stag");
300    if (d > 1)
301        CHECKER_acf_error(op_p, NIDL_DUPPRMATTR, "cs_drtag");
302    if (r > 1)
303        CHECKER_acf_error(op_p, NIDL_DUPPRMATTR, "cs_rtag");
304
305    /* Use of [cs_tag_rtn] attribute requires -standard extended */
306    if (op_p->cs_tag_rtn_name != NAMETABLE_NIL_ID
307        && (*(int *)CMD_vals[opt_standard] < opt_standard_dce_1_1))
308        CHECKER_acf_warning(op_p, NIDL_NOPORTATTR, "cs_tag_rtn",
309                            OPT_STD_EXTENDED);
310}
311
312/*
313**  C H K _ f i e l d _ c s
314**
315**  Checks a structure field node's I-char ([cs_*]) attributes.
316*/
317void CHK_field_cs
318(
319    AST_field_n_t       *field_p        /* [in] Ptr to AST field node */
320)
321{
322    AST_type_n_t        *type_p;
323    AST_field_attr_n_t  *fattr_p;
324
325    type_p = field_p->type;
326    fattr_p = field_p->field_attrs;
327
328    /* Array attr cannot be used for both [cs_char] and non-[cs_char] arrays */
329    if (FE_TEST(field_p->fe_info->flags, FE_USED_AS_CS_FLD_ATTR)
330        && FE_TEST(field_p->fe_info->flags, FE_USED_AS_REG_FLD_ATTR))
331        CHECKER_error(field_p, NIDL_ARRATTRSHR);
332
333    /* A [size_is] or [max_is] attr can't be applied to ptr to [cs_char] type */
334    if (type_p->kind == AST_pointer_k
335        && type_p->type_structure.pointer->pointee_type->cs_char_type != NULL
336        && fattr_p != NULL
337        && (fattr_p->max_is_vec != NULL || fattr_p->size_is_vec != NULL))
338        CHECKER_error(field_p, NIDL_CSARRSYN);
339
340    /* Arrays of [cs_char] can only use the [size_is] and [length_is] attrs */
341    if (type_p->kind == AST_array_k
342        && type_p->type_structure.array->element_type->cs_char_type != NULL
343        && (AST_STRING_SET(type_p) || AST_STRING_SET(field_p)
344            || (fattr_p != NULL
345                && (fattr_p->min_is_vec != NULL
346                    || fattr_p->max_is_vec != NULL
347                    || fattr_p->first_is_vec != NULL
348                    || fattr_p->last_is_vec != NULL))))
349        CHECKER_error(field_p, NIDL_ARRTYPATTR, "cs_char");
350}
351
352/*
353**  C H K _ p i p e _ b a s e _ t y p e _ c s
354**
355**  Checks a pipe node's base data type for [cs_char] attribute.
356*/
357void CHK_pipe_base_type_cs
358(
359    AST_pipe_n_t        *pipe_p,        /* [in] Ptr to AST pipe node */
360    AST_interface_n_t   *int_p ATTRIBUTE_UNUSED /* [in] Ptr to interface node */
361)
362{
363    AST_type_n_t        *type_p;        /* Pipe base data type node */
364
365    type_p = pipe_p->base_type;
366
367    /* The base type of a pipe cannot be or contain a [cs_char] type */
368    if (type_p->cs_char_type != NULL
369        || FE_TEST(type_p->fe_info->flags, FE_CT_CS_CHAR))
370        CHECKER_error(type_p, NIDL_PIPECTYPE, "cs_char");
371}
372
373/*
374**  C H K _ t y p e _ c s
375**
376**  Checks a type node's [cs_char] attribute.
377*/
378void CHK_type_cs
379(
380    AST_type_n_t        *top_type_p,    /* [in] Top-level presented type */
381    AST_type_n_t        *type_p,        /* [in] Ptr to AST type node */
382    AST_interface_n_t   *int_p          /* [in] Ptr to interface node */
383)
384{
385    char const          *type_name;     /* Type name */
386    int                 type_len;       /* Length of type name */
387    int                 max_len;        /* Maximum identifier length */
388
389    /* Types with the [cs_char] attribute cannot be nested */
390    if (type_p->cs_char_type != NULL
391        && FE_TEST(type_p->fe_info->flags, FE_CT_CS_CHAR))
392        CHECKER_acf_error(type_p, NIDL_TYPENEST, "cs_char");
393
394    /* A [transmit_as] transmitted type cannot contain a [cs_char] type */
395    if (type_p->cs_char_type != NULL
396        && FE_TEST(type_p->fe_info->flags, FE_USED_IN_TRANSMITTED))
397        CHECKER_error(type_p, NIDL_XMITCTYPE, "cs_char");
398
399    /* Arrays of [cs_char] type cannot be multidimensional */
400    if (type_p->kind == AST_array_k
401        && type_p->type_structure.array->element_type->cs_char_type != NULL
402        && type_p->type_structure.array->index_count > 1)
403        CHECKER_error(type_p, NIDL_ARRMULTID, "cs_char");
404
405    /* Type with [cs_char] cannot be or contain type with [transmit_as] */
406    if (top_type_p->cs_char_type != NULL
407        && (top_type_p->xmit_as_type != NULL
408            || FE_TEST(top_type_p->fe_info->flags, FE_HAS_XMIT_AS)) )
409    {
410        ASTP_attr_flag_t attr2 = ASTP_TRANSMIT_AS;
411        CHECKER_error(top_type_p, NIDL_TYPECTYPE, "cs_char",
412            KEYWORDS_lookup_text(AST_attribute_to_token(&attr2)));
413    }
414
415    /* Type with [cs_char] cannot be or contain type with [transmit_as] */
416    if (type_p->cs_char_type != NULL
417        && (type_p->rep_as_type != NULL
418            || FE_TEST(type_p->fe_info->flags, FE_HAS_REP_AS)) )
419        CHECKER_error(type_p, NIDL_TYPECTYPE, "cs_char", "represent_as");
420
421    if (type_p->cs_char_type != NULL
422        && type_p->kind != AST_byte_k
423        && !(type_p->kind == AST_structure_k
424             && CHK_struct_is_all_byte_fields(type_p->type_structure.structure)))
425        CHECKER_error(type_p, NIDL_TYPEOFBYTES, "cs_char");
426
427    /* ACF 'include' statement advised for definition of type 'name' */
428    if (int_p->includes == NULL
429        && type_p->cs_char_type != NULL
430        && ASTP_lookup_binding(null_parser_location,
431	    type_p->cs_char_type->type_name, fe_type_n_k, FALSE) == NULL)
432    {
433        char const *id_name;
434        NAMETABLE_id_to_string(type_p->cs_char_type->type_name, &id_name);
435        CHECKER_acf_warning(type_p, NIDL_INCLTYPE, id_name);
436    }
437
438    /* Maximum identifier length for [cs_char] type is 'n' characters */
439    if (type_p->cs_char_type != NULL
440        && type_p->name != NAMETABLE_NIL_ID)
441    {
442        NAMETABLE_id_to_string(type_p->name, &type_name);
443        type_len = strlen(type_name);
444        max_len = MAX_ID - strlen("_from_netcs");
445        if (type_len > max_len)
446            CHECKER_error(type_p, NIDL_MAXIDTYPE, "cs_char", max_len);
447    }
448
449    /* Use of [cs_char] attribute requires -standard extended */
450    if (type_p->cs_char_type != NULL
451        && (*(int *)CMD_vals[opt_standard] < opt_standard_dce_1_1))
452        CHECKER_acf_warning(type_p, NIDL_NOPORTATTR, "cs_char",
453                            OPT_STD_EXTENDED);
454}
455