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**      ddspell.c
82**
83**  FACILITY:
84**
85**      Interface Definition Language (IDL) Compiler
86**
87**  ABSTRACT:
88**
89**  Data Driven Backend - Support routines to spell C source vector definitions
90**  and code to interface with a Marshalling Interpreter.
91**
92*/
93
94#include <ddbe.h>
95#include <astp.h>
96#include <command.h>
97#include <message.h>
98#include <mtsbacke.h>
99#include <nidlmsg.h>
100#include <cspell.h>
101
102/*
103 * Conditional macro to spell a comment containing the current vector index.
104 */
105#ifdef DUMPERS
106#define DDBE_SPELL_INDEX(_fid, _index) \
107    fprintf(_fid, "/* %s */ ", DDBE_spell_long(_index))
108#else
109#define DDBE_SPELL_INDEX(_fid, _index)
110#endif
111
112/*
113 * Conditional macro to spell a comment if the comment stringtable ID non-NULL.
114 */
115#ifdef DUMPERS
116#define DDBE_SPELL_COMMENT(_fid, _comment_id, _comment_fmt, _comment_buf) \
117    if (_comment_id != STRTAB_NULL_STR) \
118    { \
119        STRTAB_str_to_string(_comment_id, &_comment_buf); \
120        fprintf(_fid, _comment_fmt, _comment_buf); \
121    }
122#else
123#define DDBE_SPELL_COMMENT(_fid, _comment_id, _comment_fmt, _comment_buf)
124#endif
125
126/*
127 * Conditional macros to spell a string with zero, one, or two printf arguments.
128 */
129#ifdef DUMPERS
130#define DDBE_SPELL_TEXT(_fid, _string) \
131    fprintf(_fid, _string)
132
133#define DDBE_SPELL_TEXT_1ARG(_fid, _fmt, _arg) \
134    fprintf(_fid, _fmt, _arg)
135
136#define DDBE_SPELL_TEXT_2ARG(_fid, _fmt, _arg1, _arg2) \
137    fprintf(_fid, _fmt, _arg1, _arg2)
138#else
139#define DDBE_SPELL_TEXT(_fid, _string)
140#define DDBE_SPELL_TEXT_1ARG(_fid, _fmt, _arg)
141#define DDBE_SPELL_TEXT_2ARG(_fid, _fmt, _arg1, _arg2)
142#endif
143
144/**************************************/
145/*  Private speller support routines  */
146/**************************************/
147
148/*
149 *  D D B E _ s p e l l _ l o n g
150 *  D D B E _ s p e l l _ l o n g _ n f
151 *
152 *  Returns a string that represents a long integer in either hex or decimal.
153 *  DDBE_spell_long spells the long with filler chars for right justification.
154 *  DDBE_spell_long_nf spells the long with no filler chars.
155 *
156 *  Implicit Input: DDBE_stub_hex - TRUE => return hex format, FALSE => decimal
157 *  Restriction:
158 *      For simplicity of implementation, the routine uses a global buffer.
159 *      Thus routine is not reentrant and call will overwrite previous buffer
160 *      contents.  Do not code two calls to this routine in one printf call.
161 */
162static char DDBE_long_buf[DDBE_MAX_EXPR];
163
164static char *DDBE_spell_long
165(
166    long            val             /* [in] long value */
167)
168{
169    if (DDBE_stub_hex)
170        sprintf(DDBE_long_buf, "0x%04lx", val);
171    else
172        sprintf(DDBE_long_buf, "%6ld", val);
173
174    return DDBE_long_buf;
175}
176
177static char *DDBE_spell_long_nf
178(
179    long            val             /* [in] long value */
180)
181{
182    if (DDBE_stub_hex)
183        sprintf(DDBE_long_buf, "0x%lx", val);
184    else
185        sprintf(DDBE_long_buf, "%ld", val);
186
187    return DDBE_long_buf;
188}
189
190/*
191 *  D D B E _ s p e l l _ l o n g _ v a l
192 *
193 *  Spells a 'long' value as a series of bytes so that the resulting data
194 *  encoding is not dependent on the platform's integer endianism.
195 */
196static void DDBE_spell_long_val
197(
198    FILE            *fid,           /* [in] output file handle */
199    DDBE_vec_rep_t  *vec_p,         /* [in] ptr to vector entry list */
200    boolean         little_endian ATTRIBUTE_UNUSED   /* [in] T/F => spell as little/big endian */
201)
202{
203    byte        *bp;
204    int         i;
205#ifdef DUMPERS
206    char const       *comment;
207#endif
208
209    bp = (byte *)&vec_p->val.long_val;
210
211    for (i = 0; i < 4 /*sizeof(idl_long_int)*/; i++)
212	fprintf(fid, "0x%02x,", bp[i]);
213
214#ifdef DUMPERS
215    STRTAB_str_to_string(vec_p->comment, &comment);
216    fprintf(fid, "\t/* long %s %s */",
217            DDBE_spell_long_nf(vec_p->val.long_val), comment);
218#endif
219    fprintf(fid, "\n");
220}
221
222/*
223 *  D D B E _ s p e l l _ s h o r t _ b y t e s
224 *
225 *  Spells a 'short' value as a series of bytes so that the resulting data
226 *  encoding is not dependent on the platform's integer endianism.
227 */
228static void DDBE_spell_short_bytes
229(
230    FILE            *fid,           /* [in] output file handle */
231    unsigned short  *val,           /* [in] value to print */
232    boolean         little_endian ATTRIBUTE_UNUSED  /* [in] T/F => spell as little/big endian */
233)
234{
235    byte        *bp;
236    int         i;
237
238    bp = (byte *)val;
239
240    for (i = 0; i < 2 /*sizeof(idl_short_int)*/; i++)
241	fprintf(fid, "0x%02x,", bp[i]);
242}
243
244/*
245 *  D D B E _ s p e l l _ l o n g _ b y t e s
246 *
247 *  Spells a 'long' value as a series of bytes so that the resulting data
248 *  encoding is not dependent on the platform's integer endianism.
249 */
250static void DDBE_spell_long_bytes
251(
252    FILE            *fid,           /* [in] output file handle */
253    unsigned long   *val,           /* [in] value to print */
254    boolean         little_endian ATTRIBUTE_UNUSED  /* [in] T/F => spell as little/big endian */
255)
256{
257    byte        *bp;
258    int         i;
259
260    bp = (byte *)val;
261
262    for (i = 0; i < 4 /*sizeof(idl_long_int)*/; i++)
263	fprintf(fid, "0x%02x,", bp[i]);
264}
265
266/*
267 *  D D B E _ s p e l l _ l o n g _ b o o l _ v a l
268 *
269 *  Spells a 'long' representation of a boolean value as a series of bytes so
270 *  that the resulting data encoding is not dependent on the platform's integer
271 *  endianism.
272 */
273static void DDBE_spell_long_bool_val
274(
275    FILE            *fid,           /* [in] output file handle */
276    DDBE_vec_rep_t  *vec_p,         /* [in] ptr to vector entry list */
277    boolean         little_endian   /* [in] T/F => spell as little/big endian */
278)
279{
280    const char        *sym;
281#ifdef DUMPERS
282    char const       *comment;
283#endif
284
285    if (vec_p->val.long_val == 0)
286        sym = "idl_false";
287    else
288        sym = "idl_true";
289
290    /*
291     * Regardless of whether we're running on little/big endian or spelling
292     * for little/big endian, the first byte spelt is the low-order byte.
293     */
294    if (little_endian)
295	fprintf(fid, "%s,0x00,0x00,0x00,", sym);
296    else
297	fprintf(fid, "0x00,0x00,0x00,%s,", sym);
298#ifdef DUMPERS
299    STRTAB_str_to_string(vec_p->comment, &comment);
300    fprintf(fid, "\t/* long %s %s */",
301            DDBE_spell_long_nf(vec_p->val.long_val), comment);
302#endif
303    fprintf(fid, "\n");
304}
305
306/*
307 *  D D B E _ l a s t _ f i e l d
308 *
309 *  Returns pointer to last field node in structure type.  If last field is
310 *  a nested struct returns the last field in the innermost struct.  Also
311 *  returns an field expression, e.g. "last_toplevel_field.last_nested_field".
312 *
313 *  Assumption: Input type is a structure.
314 */
315static void DDBE_last_field
316(
317    AST_type_n_t        *type_p,    /* [in] ptr to AST type node */
318    AST_field_n_t       **p_field_p,/*[out] ptr to AST field node */
319    STRTAB_str_t        *field_expr /*[out] field expression */
320)
321{
322    AST_structure_n_t   *struct_p;
323    AST_field_n_t       *field_p;
324    char const          *field_name;
325    char                expr[DDBE_MAX_EXPR];
326    boolean             nested;
327
328    expr[0] = '\0';
329    nested = FALSE;
330    struct_p = type_p->type_structure.structure;
331
332    field_p = struct_p->fields;
333    while (field_p != NULL)
334    {
335        if (field_p->next == NULL)
336        {
337            *p_field_p = field_p;
338            NAMETABLE_id_to_string(field_p->name, &field_name);
339            if (nested)
340                strlcat(expr, ".", sizeof(expr));
341            strlcat(expr, field_name, sizeof(expr));
342
343            if (field_p->type->kind == AST_structure_k)
344            {
345                nested = TRUE;
346                field_p = field_p->type->type_structure.structure->fields;
347                continue;
348            }
349        }
350        field_p = field_p->next;
351    }
352
353    *field_expr = STRTAB_add_string(expr);
354}
355
356/*
357 *  D D B E _ s i z e o f _ e x p r
358 *
359 *  Spells an expression for the size of a data type.
360 */
361static void DDBE_sizeof_expr
362(
363    FILE                *fid,       /* [in] output file handle */
364    AST_type_n_t        *type_p,    /* [in] ptr to AST type node */
365    STRTAB_str_t        comment_id ATTRIBUTE_UNUSED /* [in] ID of comment string */
366)
367{
368#ifdef DUMPERS
369    char const          *comment;   /* Comment string */
370#endif
371
372    if (AST_CONFORMANT_SET(type_p))
373    {
374        AST_field_n_t   *field_p;   /* Ptr to conformant array field node */
375        STRTAB_str_t    field_expr;
376        char const      *field_text;
377
378        if (type_p->kind != AST_structure_k)
379        {
380            INTERNAL_ERROR("sizeof conformant array not supported");
381            return;
382        }
383        DDBE_last_field(type_p, &field_p, &field_expr);
384        STRTAB_str_to_string(field_expr, &field_text);
385#if defined(ultrix)
386        fprintf(fid, "IDL_offsetofarr(");
387#else
388        fprintf(fid, "offsetof(");
389#endif
390        CSPELL_typed_name(fid, type_p, NAMETABLE_NIL_ID /*instance name*/,
391            (AST_type_n_t *)NULL /*in_typedef*/,
392            TRUE /*in_struct*/, TRUE /*spell_tag*/, FALSE /*encoding_services*/
393            );
394        fprintf(fid, ", %s)", field_text);
395    }
396    else
397    {
398        fprintf(fid, "sizeof");
399        CSPELL_cast_exp(fid, type_p);
400    }
401
402    DDBE_SPELL_COMMENT(fid, comment_id, "\t/* %s */", comment);
403}
404
405/*
406 *  D D B E _ s i z e o f _ e x p r _ u s e _ i n s t
407 *
408 *  Spells an expression for the size of a data type.  Requires the instance
409 *  declarations that are spelt by DDBE_spell_offset_instances.
410 */
411static void DDBE_sizeof_expr_use_inst
412(
413    FILE                *fid,       /* [in] output file handle */
414    AST_type_n_t        *type_p,    /* [in] ptr to AST type node */
415    STRTAB_str_t        comment_id ATTRIBUTE_UNUSED /* [in] ID of comment string */
416)
417{
418    char const          *inst_name; /* Name of generated instance of type */
419#ifdef DUMPERS
420    char const                *comment;   /* Comment string */
421#endif
422
423    NAMETABLE_id_to_string(type_p->be_info.dd_type->inst_name, &inst_name);
424
425    if (AST_CONFORMANT_SET(type_p))
426    {
427        AST_field_n_t   *field_p;   /* Ptr to conformant array field node */
428        STRTAB_str_t    field_expr;
429        char const      *field_text;
430
431        if (type_p->kind != AST_structure_k)
432        {
433            INTERNAL_ERROR("sizeof conformant array not supported");
434            return;
435        }
436        DDBE_last_field(type_p, &field_p, &field_expr);
437        STRTAB_str_to_string(field_expr, &field_text);
438        fprintf(fid, "(idl_byte *)%s.%s - (idl_byte *)&%s",
439                inst_name, field_text, inst_name);
440    }
441    else
442        fprintf(fid, "sizeof(%s)", inst_name);
443
444    DDBE_SPELL_COMMENT(fid, comment_id, "\t/* %s */", comment);
445}
446
447/*****************************/
448/*  Public utility routines  */
449/*****************************/
450
451/*
452 *  D D B E _ c f m t _ a r r _ l o c a l _ r e p
453 *
454 *  Returns TRUE if a parameter's local representation is any form of
455 *  a conformant array.
456 */
457boolean DDBE_cfmt_arr_local_rep
458(
459    AST_parameter_n_t   *param_p    /* [in] Ptr to AST parameter node */
460)
461{
462    AST_type_n_t        *type_p;
463
464    type_p = param_p->type;
465
466    /* A conformant array without represent_as */
467    if (AST_CONFORMANT_SET(type_p)
468        && type_p->rep_as_type == NULL)
469        return TRUE;
470
471    /* A [ref] pointer to a conformant object without represent_as */
472    if (AST_REF_SET(param_p) && type_p->kind == AST_pointer_k
473        && AST_CONFORMANT_SET(type_p->type_structure.pointer->pointee_type)
474        && type_p->type_structure.pointer->pointee_type->rep_as_type == NULL)
475        return TRUE;
476
477    /* An arrayified pointer whose array representation is conformant */
478    if (DDBE_ARRAYIFIED(param_p)
479        && AST_CONFORMANT_SET(
480                type_p->type_structure.pointer->pointee_type->array_rep_type))
481        return TRUE;
482
483    return FALSE;
484}
485
486/*************************************/
487/*  Public speller support routines  */
488/*************************************/
489
490/*
491 *  D D B E _ s p e l l _ o f f s e t _ i n s t a n c e s
492 *
493 *  Spells an instance declaration of each type that is represented in the
494 *  offset vector.  This is necessary so that the data is portable.
495 */
496void DDBE_spell_offset_instances
497(
498    FILE                *fid,       /* [in] output file handle */
499    DDBE_vectors_t      *vip,       /* [in] vector information pointer */
500    boolean             *cmd_opt ATTRIBUTE_UNUSED,   /* [in] array of cmd option flags */
501    void                **cmd_val ATTRIBUTE_UNUSED  /* [in] array of cmd option values */
502)
503{
504    DDBE_vec_rep_t      *vec_p;     /* Ptr to offset vector entry list */
505    AST_type_n_t        *type_p;    /* Ptr to AST structure type node */
506    AST_rep_as_n_t      *rep_p;     /* Ptr to AST represent_as node */
507    AST_cs_char_n_t     *ichar_p;   /* Ptr to AST cs_char node */
508    boolean             in_struct;  /* T => in struct (for speller) */
509
510    for (vec_p = vip->offset_p; vec_p != NULL; vec_p = vec_p->next)
511    {
512        if (vec_p->kind != DDBE_vec_sizeof_k)
513            continue;
514
515        type_p = vec_p->val.type_p;
516
517        if (type_p->kind == AST_disc_union_k && type_p->
518            type_structure.disc_union->discrim_name == NAMETABLE_NIL_ID)
519            in_struct = FALSE;
520        else
521            in_struct = TRUE;
522        fprintf(fid, "static ");
523        /*
524         * Null out and later restore represent_as node address, if any,
525         * to prevent spelling of local type - we want network type.
526         * Same for cs_char.
527         */
528        rep_p = type_p->rep_as_type;
529        type_p->rep_as_type = NULL;
530        ichar_p = type_p->cs_char_type;
531        type_p->cs_char_type = NULL;
532        CSPELL_typed_name(fid, type_p, type_p->be_info.dd_type->inst_name,
533            (AST_type_n_t *)NULL, in_struct, TRUE /*spell_tag*/,
534            FALSE /*encoding_services*/);
535        type_p->rep_as_type = rep_p;
536        type_p->cs_char_type = ichar_p;
537        fprintf(fid, ";\n");
538    }
539
540    fflush(fid);
541}
542
543/*
544 *  D D B E _ s p e l l _ o f f s e t _ v e c
545 *
546 *  Spells the offset vector definition and initialization.  Does not require
547 *  the instance declarations that are spelt by DDBE_spell_offset_instances,
548 *  and thus is the most straightforward way of spelling the offset vector.
549 */
550void DDBE_spell_offset_vec
551(
552    FILE                *fid,       /* [in] output file handle */
553    DDBE_vectors_t      *vip,       /* [in] vector information pointer */
554    boolean             *cmd_opt ATTRIBUTE_UNUSED,   /* [in] array of cmd option flags */
555    void                **cmd_val ATTRIBUTE_UNUSED  /* [in] array of cmd option values */
556)
557{
558    DDBE_vec_rep_t      *vec_p;     /* Ptr to offset vector entry list */
559    AST_type_n_t        *type_p = NULL;    /* Ptr to AST type node */
560    AST_rep_as_n_t      *rep_p = NULL;     /* Ptr to AST represent_as node */
561    AST_cs_char_n_t     *ichar_p = NULL;   /* Ptr to AST cs_char node */
562#ifdef DUMPERS
563    char const                *comment;   /* Comment text */
564#endif
565    boolean             in_struct = false;  /* T => in struct (for speller) */
566
567    vec_p = vip->offset_p;
568
569    fprintf(fid, "static idl_ulong_int %soffset_vec[] = {\n", DDBE_PREFIX_IDL);
570    fprintf(fid, "0,");
571    DDBE_SPELL_TEXT(fid, "\t/* sentinel */");
572    fprintf(fid, "\n");
573
574    while (vec_p != NULL)
575    {
576        switch (vec_p->kind)
577        {
578        case DDBE_vec_comment_k:
579            DDBE_SPELL_COMMENT(fid, vec_p->comment, "\t\t/* %s */\n", comment);
580            break;
581
582        case DDBE_vec_expr_long_k:
583        {
584            /* Simple expression for long value */
585            char const *long_expr;
586
587            STRTAB_str_to_string(vec_p->val.expr, &long_expr);
588            DDBE_SPELL_INDEX(fid, vec_p->index);
589            fprintf(fid, "(idl_ulong_int)%s,", long_expr);
590
591            DDBE_SPELL_COMMENT(fid, vec_p->comment, "\t/* %s */", comment);
592            fprintf(fid, "\n");
593            break;
594        }
595
596        case DDBE_vec_sizeof_k:
597            type_p = vec_p->val.type_p;
598            /*
599             * Null out and later restore represent_as node address, if any,
600             * to prevent spelling of local type - we want network type.
601             * Same for cs_char.
602             */
603            rep_p = type_p->rep_as_type;
604            type_p->rep_as_type = NULL;
605            ichar_p = type_p->cs_char_type;
606            type_p->cs_char_type = NULL;
607            DDBE_SPELL_INDEX(fid, vec_p->index);
608            DDBE_sizeof_expr(fid, type_p, vec_p->comment);
609            fprintf(fid, ",\n");
610            type_p->rep_as_type = rep_p;
611            type_p->cs_char_type = ichar_p;
612            break;
613
614        case DDBE_vec_noop_k:
615            break;
616
617        case DDBE_vec_offset_begin_k:
618            type_p = vec_p->val.type_p;
619            if (type_p->kind == AST_disc_union_k && type_p->
620                type_structure.disc_union->discrim_name == NAMETABLE_NIL_ID)
621                in_struct = FALSE;
622            else
623                in_struct = TRUE;
624            /*
625             * Null out and later restore represent_as node address, if any,
626             * to prevent spelling of local type - we want network type.
627             * Same for cs_char.
628             */
629            rep_p = type_p->rep_as_type;
630            type_p->rep_as_type = NULL;
631            ichar_p = type_p->cs_char_type;
632            type_p->cs_char_type = NULL;
633            break;
634
635        case DDBE_vec_offset_end_k:
636            /* Restore node addresses that were saved above */
637            assert(type_p != NULL);
638
639            type_p->rep_as_type = rep_p;
640            type_p->cs_char_type = ichar_p;
641            break;
642
643        case DDBE_vec_expr_k:
644        case DDBE_vec_expr_arr_k:
645        {
646            /*
647             * field offset: &((type *)NULL)->field-expr - NULL
648             */
649            char const *field_expr;
650
651            STRTAB_str_to_string(vec_p->val.expr, &field_expr);
652            DDBE_SPELL_INDEX(fid, vec_p->index);
653
654#if defined(ultrix)
655          if (vec_p->kind == DDBE_vec_expr_arr_k)
656            fprintf(fid, "IDL_offsetofarr(");
657          else
658#endif
659            fprintf(fid, "offsetof(");
660            CSPELL_typed_name(fid, type_p, NAMETABLE_NIL_ID /*instance name*/,
661                (AST_type_n_t *)NULL /*in_typedef*/,
662                in_struct, TRUE /*spell_tag*/, FALSE /*encoding_services*/);
663            fprintf(fid, ", %s),", field_expr);
664
665            DDBE_SPELL_COMMENT(fid, vec_p->comment, "\t/* %s */", comment);
666            fprintf(fid, "\n");
667            break;
668        }
669
670        default:
671            INTERNAL_ERROR("Invalid offset vector entry kind");
672        }
673
674        vec_p = vec_p->next;
675    }
676
677    fprintf(fid, "0");
678    DDBE_SPELL_TEXT(fid, "\t/* sentinel */");
679    fprintf(fid, "\n};\n\n");
680}
681
682/*
683 *  D D B E _ s p e l l _ o f f s e t _ v e c _ u s e _ i n s t
684 *
685 *  Spells the offset vector definition.  Requires the instance declarations
686 *  that are spelt by DDBE_spell_offset_instances.
687 *
688 *  NOTE:
689 *  The resulting declaration will not compile successfully under some C
690 *  compilers.  On those platforms it will be necessary to call DDBE_init_
691 *  offset_vec to spell a routine which must be called once per interface to
692 *  initialize the offset vector.
693 */
694void DDBE_spell_offset_vec_use_inst
695(
696    FILE                *fid,       /* [in] output file handle */
697    DDBE_vectors_t      *vip,       /* [in] vector information pointer */
698    boolean             *cmd_opt ATTRIBUTE_UNUSED,   /* [in] array of cmd option flags */
699    void                **cmd_val ATTRIBUTE_UNUSED  /* [in] array of cmd option values */
700)
701{
702    DDBE_vec_rep_t      *vec_p;     /* Ptr to offset vector entry list */
703    AST_type_n_t        *type_p;    /* Ptr to AST type node */
704    char const          *inst_name; /* Name of generated instance of type */
705#ifdef DUMPERS
706    char const               *comment;   /* Comment text */
707#endif
708
709    vec_p = vip->offset_p;
710    inst_name = NULL;
711
712    fprintf(fid, "static idl_ulong_int %soffset_vec[] = {\n", DDBE_PREFIX_IDL);
713    fprintf(fid, "0,");
714    DDBE_SPELL_TEXT(fid, "\t/* sentinel */");
715    fprintf(fid, "\n");
716
717    while (vec_p != NULL)
718    {
719        type_p = vec_p->val.type_p;
720
721        switch (vec_p->kind)
722        {
723        case DDBE_vec_comment_k:
724            DDBE_SPELL_COMMENT(fid, vec_p->comment, "\t\t/* %s */\n", comment);
725            break;
726
727        case DDBE_vec_expr_long_k:
728        {
729            /* Simple expression for long value */
730            char const *long_expr;
731
732            STRTAB_str_to_string(vec_p->val.expr, &long_expr);
733            DDBE_SPELL_INDEX(fid, vec_p->index);
734            fprintf(fid, "%s,", long_expr);
735
736            DDBE_SPELL_COMMENT(fid, vec_p->comment, "\t/* %s */", comment);
737            fprintf(fid, "\n");
738            break;
739        }
740
741        case DDBE_vec_sizeof_k:
742            DDBE_SPELL_INDEX(fid, vec_p->index);
743            DDBE_sizeof_expr_use_inst(fid, type_p, vec_p->comment);
744            fprintf(fid, ",\n");
745            break;
746
747        case DDBE_vec_noop_k:
748            break;
749
750        case DDBE_vec_offset_end_k:
751            inst_name = NULL;
752            break;
753
754        case DDBE_vec_offset_begin_k:
755            /* Form instance name for struct */
756            NAMETABLE_id_to_string(type_p->be_info.dd_type->inst_name,
757                &inst_name);
758            break;
759
760        case DDBE_vec_expr_k:
761        case DDBE_vec_expr_arr_k:
762        {
763            /*
764             * field offset: &inst.field-expr - &inst
765             */
766            char const *field_expr;
767
768            STRTAB_str_to_string(vec_p->val.expr, &field_expr);
769            DDBE_SPELL_INDEX(fid, vec_p->index);
770            fprintf(fid, "(idl_byte *)%s%s.%s - (idl_byte *)&%s,",
771                    (vec_p->kind == DDBE_vec_expr_arr_k) ? "" : "&",
772                    inst_name, field_expr, inst_name);
773
774            DDBE_SPELL_COMMENT(fid, vec_p->comment, "\t/* %s */", comment);
775            fprintf(fid, "\n");
776            break;
777        }
778
779        default:
780            INTERNAL_ERROR("Invalid offset vector entry kind");
781        }
782
783        vec_p = vec_p->next;
784    }
785
786    fprintf(fid, "0");
787    DDBE_SPELL_TEXT(fid, "\t/* sentinel */");
788    fprintf(fid, "\n};\n\n");
789}
790
791/*
792 *  D D B E _ i n i t _ o f f s e t _ v e c
793 *
794 *  Spells an uninitialized definition of the offset vector and a routine
795 *  IDL_init_offset_vec which must be called once per interface to initialize
796 *  the offset vector.  Alternative to using DDBE_spell_offset_vec_use_inst.
797 */
798void DDBE_init_offset_vec
799(
800    FILE                *fid,       /* [in] output file handle */
801    DDBE_vectors_t      *vip,       /* [in] vector information pointer */
802    boolean             *cmd_opt ATTRIBUTE_UNUSED,   /* [in] array of cmd option flags */
803    void                **cmd_val ATTRIBUTE_UNUSED  /* [in] array of cmd option values */
804)
805{
806    DDBE_vec_rep_t      *vec_p;     /* Ptr to offset vector entry list */
807    AST_type_n_t        *type_p;    /* Ptr to AST type node */
808    unsigned long       last_index; /* Last index spelled */
809    char const          *inst_name; /* Name of generated instance of type */
810#ifdef DUMPERS
811    char const               *comment;   /* Comment text */
812#endif
813
814    vec_p = vip->offset_p;
815    inst_name = NULL;
816
817    fprintf(fid, "static idl_ulong_int %soffset_vec[%s];\n\n",
818            DDBE_PREFIX_IDL, DDBE_spell_long_nf(vip->offset_vec_size));
819
820    fprintf(fid, "static void %sinit_offset_vec\n", DDBE_PREFIX_IDL);
821    fprintf(fid, "(void)\n");
822    fprintf(fid, "{\n");
823
824    fprintf(fid, "%soffset_vec[%s] = 0;", DDBE_PREFIX_IDL, DDBE_spell_long(0));
825    DDBE_SPELL_TEXT(fid, "\t/* sentinel */");
826    fprintf(fid, "\n");
827    last_index = 0;
828
829    while (vec_p != NULL)
830    {
831        type_p = vec_p->val.type_p;
832
833        switch (vec_p->kind)
834        {
835        case DDBE_vec_comment_k:
836            DDBE_SPELL_COMMENT(fid, vec_p->comment, "/*\n * %s\n */\n", comment);
837            break;
838
839        case DDBE_vec_expr_long_k:
840        {
841            /* Simple expression for long value */
842            char const *long_expr;
843
844            STRTAB_str_to_string(vec_p->val.expr, &long_expr);
845            fprintf(fid, "%soffset_vec[%s] = ", DDBE_PREFIX_IDL,
846                    DDBE_spell_long(vec_p->index));
847            fprintf(fid, "%s;", long_expr);
848            last_index = vec_p->index;
849
850            DDBE_SPELL_COMMENT(fid, vec_p->comment, "\t/* %s */", comment);
851            fprintf(fid, "\n");
852            break;
853        }
854
855        case DDBE_vec_sizeof_k:
856            fprintf(fid, "%soffset_vec[%s] = ", DDBE_PREFIX_IDL,
857                    DDBE_spell_long(vec_p->index));
858            DDBE_sizeof_expr_use_inst(fid, type_p, vec_p->comment);
859            fprintf(fid, ";\n");
860            last_index = vec_p->index;
861            break;
862
863        case DDBE_vec_noop_k:
864            break;
865
866        case DDBE_vec_offset_end_k:
867            inst_name = NULL;
868            break;
869
870        case DDBE_vec_offset_begin_k:
871            /* Form instance name for struct */
872            NAMETABLE_id_to_string(type_p->be_info.dd_type->inst_name,
873                &inst_name);
874            break;
875
876        case DDBE_vec_expr_k:
877        case DDBE_vec_expr_arr_k:
878        {
879            /*
880             * field offset: &inst.field-expr - &inst
881             */
882            char const *field_expr;
883
884            STRTAB_str_to_string(vec_p->val.expr, &field_expr);
885            fprintf(fid, "%soffset_vec[%s] = ", DDBE_PREFIX_IDL,
886                    DDBE_spell_long(vec_p->index));
887            fprintf(fid, "(idl_byte *)%s%s.%s - (idl_byte *)&%s;",
888                    (vec_p->kind == DDBE_vec_expr_arr_k) ? "" : "&",
889                    inst_name, field_expr, inst_name);
890            last_index = vec_p->index;
891
892            DDBE_SPELL_COMMENT(fid, vec_p->comment, "\t/* %s */", comment);
893            fprintf(fid, "\n");
894            break;
895        }
896
897        default:
898            INTERNAL_ERROR("Invalid offset vector entry kind");
899        }
900
901        vec_p = vec_p->next;
902    }
903
904    fprintf(fid, "%soffset_vec[%s] = 0;", DDBE_PREFIX_IDL,
905            DDBE_spell_long(last_index+1));
906    DDBE_SPELL_TEXT(fid, "\t/* sentinel */");
907    fprintf(fid, "\n}\n\n");
908}
909
910/*
911 *  D D B E _ s p e l l _ r t n _ v e c
912 *
913 *  Spells the routine vector definition.
914 */
915void DDBE_spell_rtn_vec
916(
917    FILE                *fid,       /* [in] output file handle */
918    DDBE_vectors_t      *vip,       /* [in] vector information pointer */
919    boolean             *cmd_opt ATTRIBUTE_UNUSED,   /* [in] array of cmd option flags */
920    void                **cmd_val ATTRIBUTE_UNUSED,  /* [in] array of cmd option values */
921    boolean         client_side    /* [in] T=>client only, F=>server only */
922)
923{
924    DDBE_vec_rep_t      *vec_p;     /* Ptr to routine vector entry list */
925    char const *rtn_name;
926#ifdef DUMPERS
927    char const    *comment;
928#endif
929
930    vec_p = vip->rtn_p;
931
932    fprintf(fid, "static IDL_rtn_func_t %srtn_vec[] = {\n", DDBE_PREFIX_IDL);
933    fprintf(fid, "(IDL_rtn_func_t)NULL,");
934    DDBE_SPELL_TEXT(fid, "\t/* sentinel */");
935    fprintf(fid, "\n");
936
937    for ( ; vec_p != NULL; vec_p = vec_p->next)
938	 {
939		 if (vec_p->kind == DDBE_vec_noop_k)
940			 continue;
941		 if (vec_p->kind == DDBE_vec_comment_k)
942		 {
943			 DDBE_SPELL_COMMENT(fid, vec_p->comment, "/* %s */\n", comment);
944			 continue;
945		 }
946
947		 NAMETABLE_id_to_string(vec_p->val.name, &rtn_name);
948		 DDBE_SPELL_INDEX(fid, vec_p->index);
949		 if (   (vec_p->kind == DDBE_vec_name_client_k && !client_side)
950				 || (vec_p->kind == DDBE_vec_name_server_k && client_side) )
951			 fprintf(fid, "(IDL_rtn_func_t)NULL,\n");
952		 else
953			 fprintf(fid, "(IDL_rtn_func_t)%s,\n", rtn_name);
954	 }
955
956    fprintf(fid, "(IDL_rtn_func_t)NULL");
957    DDBE_SPELL_TEXT(fid, "\t/* sentinel */");
958    fprintf(fid, "\n};\n\n");
959}
960
961/*
962 *  D D B E _ s p e l l _ t y p e _ v e c _ p r e a m b l e
963 *
964 *  Spells the preamble portion of the type vector definition.
965 *  Assumes: vip->type_vec_size is offset to addenda portion of type vector.
966 */
967void DDBE_spell_type_vec_preamble
968(
969    FILE                *fid,       /* [in] output file handle */
970    DDBE_vectors_t      *vip        /* [in] vector information pointer */
971)
972{
973    AST_interface_n_t   *int_p;     /* Ptr to AST interface node */
974    AST_export_n_t      *export_p;  /* Ptr to AST export node */
975    AST_operation_n_t   *oper_p;    /* Ptr to AST operation node */
976    char const          *int_name;  /* Interface name */
977    char const          *oper_name; /* Operation name */
978    byte                *bp;        /* Pointer to byte stream */
979    char                *getenvres; /* Environment variable translation */
980    unsigned long       index;      /* Type vector index */
981    unsigned long       longint;    /* 4-byte integer data */
982    unsigned short      shortint;   /* 2-byte integer data */
983    boolean         spell_stg_info; /* TRUE => spell storage information list */
984
985    int_p = vip->ast_int_p;
986    NAMETABLE_id_to_string(int_p->name, &int_name);
987
988    getenvres = getenv("IDL_GEN_INTF_DATA");
989    spell_stg_info = (getenvres != NULL);
990
991    /*
992     * NOTE: Currently assume ASCII encodings.
993     */
994    DDBE_SPELL_INDEX(fid, 0);
995    fprintf(fid, "0xff,0xff,0xff,0xff,\n");
996
997    DDBE_SPELL_INDEX(fid, 4);
998    if (DDBE_little_endian){
999	fprintf(fid, "1,");
1000	DDBE_SPELL_TEXT(fid, "\t\t/* little endian */");
1001    }
1002    else{
1003	fprintf(fid, "0,");
1004	DDBE_SPELL_TEXT(fid, "\t\t/* big endian */");
1005    }
1006    fprintf(fid, "\n");
1007
1008    DDBE_SPELL_INDEX(fid, 5);
1009    fprintf(fid, "0,");
1010    DDBE_SPELL_TEXT(fid, "\t\t/* ASCII */");
1011    fprintf(fid, "\n");
1012
1013    DDBE_SPELL_INDEX(fid, 6);
1014    fprintf(fid, "0xff,0xff,\n");
1015
1016    shortint = DDBE_VER_MAJOR;
1017    DDBE_SPELL_INDEX(fid, 8);
1018    DDBE_spell_short_bytes(fid, &shortint, DDBE_little_endian);
1019    DDBE_SPELL_TEXT_1ARG(fid, "\t/* interpreter encoding major version %d */",
1020                         shortint);
1021    fprintf(fid, "\n");
1022
1023    shortint = DDBE_VER_MINOR;
1024    DDBE_SPELL_INDEX(fid, 10);
1025    DDBE_spell_short_bytes(fid, &shortint, DDBE_little_endian);
1026    DDBE_SPELL_TEXT_1ARG(fid, "\t/* interpreter encoding minor version %d */",
1027                         shortint);
1028    fprintf(fid, "\n");
1029
1030    shortint = int_p->version % 65536;
1031    DDBE_SPELL_INDEX(fid, 12);
1032    DDBE_spell_short_bytes(fid, &shortint, DDBE_little_endian);
1033    DDBE_SPELL_TEXT_2ARG(fid, "\t/* interface %s major version %d */",
1034                         int_name, shortint);
1035    fprintf(fid, "\n");
1036
1037    shortint = int_p->version / 65536;
1038    DDBE_SPELL_INDEX(fid, 14);
1039    DDBE_spell_short_bytes(fid, &shortint, DDBE_little_endian);
1040    DDBE_SPELL_TEXT_2ARG(fid, "\t/* interface %s minor version %d */",
1041                         int_name, shortint);
1042    fprintf(fid, "\n");
1043
1044    longint = int_p->uuid.time_low;
1045    DDBE_SPELL_INDEX(fid, 16);
1046    DDBE_spell_long_bytes(fid, &longint, DDBE_little_endian);
1047    DDBE_SPELL_TEXT(fid, "\t/* uuid time_low */");
1048    fprintf(fid, "\n");
1049
1050    shortint = int_p->uuid.time_mid;
1051    DDBE_SPELL_INDEX(fid, 20);
1052    DDBE_spell_short_bytes(fid, &shortint, DDBE_little_endian);
1053    DDBE_SPELL_TEXT(fid, "\t/* uuid time_mid */");
1054    fprintf(fid, "\n");
1055
1056    shortint = int_p->uuid.time_hi_and_version;
1057    DDBE_SPELL_INDEX(fid, 22);
1058    DDBE_spell_short_bytes(fid, &shortint, DDBE_little_endian);
1059    DDBE_SPELL_TEXT(fid, "\t/* uuid time_hi_and_version */");
1060    fprintf(fid, "\n");
1061
1062    DDBE_SPELL_INDEX(fid, 24);
1063    fprintf(fid, "0x%02x,", int_p->uuid.clock_seq_hi_and_reserved);
1064    DDBE_SPELL_TEXT(fid, "\t\t/* uuid clock_seq_hi_and_reserved */");
1065    fprintf(fid, "\n");
1066
1067    DDBE_SPELL_INDEX(fid, 25);
1068    fprintf(fid, "0x%02x,", int_p->uuid.clock_seq_low);
1069    DDBE_SPELL_TEXT(fid, "\t\t/* uuid clock_seq_low */");
1070    fprintf(fid, "\n");
1071
1072    bp = int_p->uuid.node;
1073    DDBE_SPELL_INDEX(fid, 26);
1074    fprintf(fid, "0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,",
1075            bp[0], bp[1], bp[2], bp[3], bp[4], bp[5]);
1076    DDBE_SPELL_TEXT(fid, "\t/* uuid node */");
1077    fprintf(fid, "\n");
1078
1079    DDBE_SPELL_INDEX(fid, 32);
1080    if (spell_stg_info)
1081    {
1082        /* Assume storage info immediately follows bugs list */
1083        longint = vip->type_vec_size + (NUM_BUGS/32 + 1) * 4;
1084        DDBE_spell_long_bytes(fid, &longint, DDBE_little_endian);
1085        DDBE_SPELL_TEXT_1ARG(fid, "\t/* index of storage information = %s */",
1086                             DDBE_spell_long_nf(longint));
1087    }
1088    else
1089    {
1090        fprintf(fid, "0x00,0x00,0x00,0x00,");
1091        DDBE_SPELL_TEXT(fid, "\t/* no storage information */");
1092    }
1093    fprintf(fid, "\n");
1094
1095    longint = NUM_BUGS;
1096    DDBE_SPELL_INDEX(fid, 36);
1097    DDBE_spell_long_bytes(fid, &longint, DDBE_little_endian);
1098    DDBE_SPELL_TEXT_1ARG(fid, "\t/* number of bug flags = %ld */", longint);
1099    fprintf(fid, "\n");
1100
1101    longint = vip->type_vec_size;
1102    DDBE_SPELL_INDEX(fid, 40);
1103    DDBE_spell_long_bytes(fid, &longint, DDBE_little_endian);
1104    DDBE_SPELL_TEXT_1ARG(fid, "\t/* index of bug flags = %s */",
1105                         DDBE_spell_long_nf(longint));
1106    fprintf(fid, "\n");
1107
1108    DDBE_SPELL_INDEX(fid, 44);
1109    fprintf(fid, "0xff,0xff,0xff,0xff,\n");
1110
1111    DDBE_SPELL_INDEX(fid, 48);
1112    fprintf(fid, "0xff,0xff,0xff,0xff,\n");
1113
1114    DDBE_SPELL_INDEX(fid, 52);
1115    fprintf(fid, "0xff,0xff,0xff,0xff,\n");
1116
1117    DDBE_SPELL_INDEX(fid, 56);
1118    fprintf(fid, "0xff,0xff,0xff,0xff,\n");
1119
1120    longint = int_p->op_count;
1121    DDBE_SPELL_INDEX(fid, 60);
1122    DDBE_spell_long_bytes(fid, &longint, DDBE_little_endian);
1123    DDBE_SPELL_TEXT_1ARG(fid, "\t/* number of operations = %ld */", longint);
1124    fprintf(fid, "\n");
1125
1126    index = DDBE_PARAM_START;
1127    ASSERTION(DDBE_PARAM_START == 64);
1128
1129    /*
1130     * Process each operation in the interface.
1131     */
1132    for (export_p = int_p->exports; export_p != NULL; export_p = export_p->next)
1133    {
1134        if (export_p->kind == AST_operation_k)
1135        {
1136            oper_p = export_p->thing_p.exported_operation;
1137            NAMETABLE_id_to_string(oper_p->name, &oper_name);
1138
1139            DDBE_SPELL_INDEX(fid, index);
1140            longint = 0;
1141            /*
1142             * The following code assumes these definitions in rpcbase.idl:
1143             *  const long  rpc_c_call_brdcst               = 0x00000001;
1144             *  const long  rpc_c_call_idempotent           = 0x00000002;
1145             *  const long  rpc_c_call_maybe                = 0x00000004;
1146             */
1147            if (AST_BROADCAST_SET(oper_p))  longint |= 1;
1148            if (AST_IDEMPOTENT_SET(oper_p)) longint |= 2;
1149            if (AST_MAYBE_SET(oper_p))      longint |= 4;
1150            DDBE_spell_long_bytes(fid, &longint, DDBE_little_endian);
1151            DDBE_SPELL_TEXT_1ARG(fid, "\t/* operation %s flags */", oper_name);
1152            fprintf(fid, "\n");
1153            index += 4; /* 4 = sizeof(idl_long) */
1154
1155            longint = oper_p->be_info.dd_oper->num_params;
1156            DDBE_SPELL_INDEX(fid, index);
1157            DDBE_spell_long_bytes(fid, &longint, DDBE_little_endian);
1158            DDBE_SPELL_TEXT_2ARG(fid, "\t/* number of %s params = %ld */",
1159                                 oper_name, longint);
1160            fprintf(fid, "\n");
1161            index += 4; /* 4 = sizeof(idl_long) */
1162
1163            longint = oper_p->be_info.dd_oper->num_srv_ins;
1164            DDBE_SPELL_INDEX(fid, index);
1165            DDBE_spell_long_bytes(fid, &longint, DDBE_little_endian);
1166            DDBE_SPELL_TEXT_2ARG(fid, "\t/* number of %s [in]s  = %ld */",
1167                                 oper_name, longint);
1168            fprintf(fid, "\n");
1169            index += 4; /* 4 = sizeof(idl_long) */
1170
1171            if (oper_p->be_info.dd_oper->ins_type_vec_p == NULL)
1172            {
1173                DDBE_SPELL_INDEX(fid, index);
1174                fprintf(fid, "0xff,0xff,0xff,0xff,\n");
1175            }
1176            else
1177            {
1178                longint = oper_p->be_info.dd_oper->ins_type_vec_p->index;
1179                DDBE_SPELL_INDEX(fid, index);
1180                DDBE_spell_long_bytes(fid, &longint, DDBE_little_endian);
1181                DDBE_SPELL_TEXT_2ARG(fid, "\t/* index  of %s [in]s  = %s */",
1182                                     oper_name, DDBE_spell_long_nf(longint));
1183                fprintf(fid, "\n");
1184            }
1185            index += 4; /* 4 = sizeof(idl_long) */
1186
1187            longint = oper_p->be_info.dd_oper->num_outs;
1188            DDBE_SPELL_INDEX(fid, index);
1189            DDBE_spell_long_bytes(fid, &longint, DDBE_little_endian);
1190            DDBE_SPELL_TEXT_2ARG(fid, "\t/* number of %s [out]s = %ld */",
1191                                 oper_name, longint);
1192            fprintf(fid, "\n");
1193            index += 4; /* 4 = sizeof(idl_long) */
1194
1195            if (oper_p->be_info.dd_oper->outs_type_vec_p == NULL)
1196            {
1197                DDBE_SPELL_INDEX(fid, index);
1198                fprintf(fid, "0xff,0xff,0xff,0xff,\n");
1199            }
1200            else
1201            {
1202                longint = oper_p->be_info.dd_oper->outs_type_vec_p->index;
1203                DDBE_SPELL_INDEX(fid, index);
1204                DDBE_spell_long_bytes(fid, &longint, DDBE_little_endian);
1205                DDBE_SPELL_TEXT_2ARG(fid, "\t/* index  of %s [out]s = %s */",
1206                                     oper_name, DDBE_spell_long_nf(longint));
1207                fprintf(fid, "\n");
1208            }
1209            index += 4; /* 4 = sizeof(idl_long) */
1210        }
1211    }
1212}
1213
1214/*
1215 *  D D B E _ s p e l l _ t y p e _ v e c _ a d d e n d a
1216 *
1217 *  Spells the addenda portion of the type vector definition.
1218 *  Assumes: vip->type_vec_size does not include the addenda on entry,
1219 *           but does include alignment pad bytes before the addenda.
1220 *           vip->type_vec_size does include the addenda on exit.
1221 */
1222void DDBE_spell_type_vec_addenda
1223(
1224    FILE                *fid,       /* [in] output file handle */
1225    DDBE_vectors_t      *vip,       /* [io] vector information pointer */
1226    boolean             *cmd_opt ATTRIBUTE_UNUSED,   /* [in] array of cmd option flags */
1227    void                **cmd_val  /* [in] array of cmd option values */
1228)
1229{
1230    unsigned long size,index,longint; /* 4-byte integer data */
1231    byte                *p4;        /* Pointer to 4-byte integer */
1232    boolean             *do_bug;    /* Pointer to array of bug flags */
1233    char                *getenvres; /* Environment variable translation */
1234    DDBE_vec_rep_t      *vec_p;     /* Ptr to vector entry in list */
1235    int                 bugnum;     /* Current bug number being processed */
1236    int                 i, j;
1237    boolean         spell_stg_info; /* TRUE => spell storage information list */
1238
1239    p4 = (byte *)&longint;
1240
1241    /*
1242     * Process bugs flags.  Bug numbers start at 1, bug 0 value is a don't-care.
1243     */
1244    do_bug = (boolean *)cmd_val[opt_do_bug];
1245    index  = vip->type_vec_size;
1246    bugnum = 0;
1247    for (i = 0; i <= NUM_BUGS/32; i++)
1248    {
1249        longint = 0;
1250        for (j = 0; j < 32 && bugnum <= NUM_BUGS; j++)
1251        {
1252            if (do_bug[bugnum])
1253                longint |= (1 << j);
1254            bugnum++;
1255        }
1256        DDBE_SPELL_INDEX(fid, index);
1257        fprintf(fid, "0x%02x,0x%02x,0x%02x,0x%02x,",p4[0], p4[1], p4[2], p4[3]);
1258        DDBE_SPELL_TEXT(fid, "\t/* bug flags */");
1259        fprintf(fid, "\n");
1260        index += 4;
1261    }
1262
1263    /*
1264     * Process storage information.
1265     */
1266    getenvres = getenv("IDL_GEN_INTF_DATA");
1267    spell_stg_info = (getenvres != NULL);
1268    if (!spell_stg_info)
1269        return;
1270
1271    /* Count type information entries; note guaranteed sentinel entry at head */
1272    for (i = 0, vec_p = vip->type_info_p->next;
1273         vec_p != NULL;
1274         i++, vec_p = vec_p->next)
1275        ;
1276
1277    /*
1278     * Compute size of type vector and do initial information entries:
1279     *  total size (in bytes) of type vector
1280     *  total size (in idl_ulong_ints) of offset vector
1281     *  total size (in pointer-sized words) of routine vector
1282     *  number of 'offset types'
1283     *  index of 'offset types'
1284     */
1285    size = index + 20 /*5 entries above*/ + i*4 /*offset types list*/
1286                 +  1 /* single byte sentinel entry */;
1287
1288    longint = size;
1289    DDBE_SPELL_INDEX(fid, index);
1290    fprintf(fid, "0x%02x,0x%02x,0x%02x,0x%02x,",p4[0], p4[1], p4[2], p4[3]);
1291    DDBE_SPELL_TEXT_1ARG(fid, "\t/* type vector size = %s */",
1292                         DDBE_spell_long_nf(longint));
1293    fprintf(fid, "\n");
1294    index += 4;
1295
1296    longint = vip->offset_vec_size;
1297    DDBE_SPELL_INDEX(fid, index);
1298    fprintf(fid, "0x%02x,0x%02x,0x%02x,0x%02x,",p4[0], p4[1], p4[2], p4[3]);
1299    DDBE_SPELL_TEXT_1ARG(fid, "\t/* offset vector size = %s */",
1300                         DDBE_spell_long_nf(longint));
1301    fprintf(fid, "\n");
1302    index += 4;
1303
1304    longint = vip->rtn_vec_size;
1305    DDBE_SPELL_INDEX(fid, index);
1306    fprintf(fid, "0x%02x,0x%02x,0x%02x,0x%02x,",p4[0], p4[1], p4[2], p4[3]);
1307    DDBE_SPELL_TEXT_1ARG(fid, "\t/* routine vector size = %s */",
1308                         DDBE_spell_long_nf(longint));
1309    fprintf(fid, "\n");
1310    index += 4;
1311
1312    longint = i;
1313    DDBE_SPELL_INDEX(fid, index);
1314    fprintf(fid, "0x%02x,0x%02x,0x%02x,0x%02x,",p4[0], p4[1], p4[2], p4[3]);
1315    DDBE_SPELL_TEXT_1ARG(fid, "\t/* number of offset types = %ld */", longint);
1316    fprintf(fid, "\n");
1317    index += 4;
1318
1319    longint = index + 4;  /* offset types list immediately follows this word */
1320    DDBE_SPELL_INDEX(fid, index);
1321    fprintf(fid, "0x%02x,0x%02x,0x%02x,0x%02x,",p4[0], p4[1], p4[2], p4[3]);
1322    DDBE_SPELL_TEXT_1ARG(fid, "\t/* index of offset types = %s */",
1323                         DDBE_spell_long_nf(longint));
1324    fprintf(fid, "\n");
1325    index += 4;
1326
1327    /* Walk type information list; note guaranteed sentinel entry at head */
1328    for (vec_p = vip->type_info_p->next; vec_p != NULL; vec_p = vec_p->next)
1329    {
1330        DDBE_SPELL_INDEX(fid, index);
1331        longint = vec_p->val.ref_p->index;
1332        DDBE_spell_long_bytes(fid, &longint, DDBE_little_endian);
1333        DDBE_SPELL_TEXT_1ARG(fid, "\t/* %s */", DDBE_spell_long(longint));
1334        fprintf(fid, "\n");
1335        index += 4;
1336    }
1337
1338    vip->type_vec_size = size;
1339}
1340
1341/*
1342 *  D D B E _ s p e l l _ t y p e _ v e c
1343 *
1344 *  Spells the type vector definition.
1345 */
1346void DDBE_spell_type_vec
1347(
1348    FILE                *fid,       /* [in] output file handle */
1349    DDBE_vectors_t      *vip,       /* [in] vector information pointer */
1350    boolean             *cmd_opt,   /* [in] array of cmd option flags */
1351    void                **cmd_val   /* [in] array of cmd option values */
1352)
1353{
1354    DDBE_vec_rep_t      *vec_p;     /* Ptr to type vector entry list */
1355    char const *name;
1356    char const *expr;
1357#ifdef DUMPERS
1358    char const   *comment;
1359#endif
1360    int     i;
1361
1362    vec_p = vip->type_p;
1363
1364    fprintf(fid, "static idl_byte %stype_vec[] = {\n", DDBE_PREFIX_IDL);
1365    DDBE_spell_type_vec_preamble(fid, vip);
1366
1367    while (vec_p != NULL)
1368    {
1369        switch (vec_p->kind)
1370        {
1371        case DDBE_vec_byte_k:
1372        case DDBE_vec_byte_3m4_k:
1373            DDBE_SPELL_INDEX(fid, vec_p->index);
1374            fprintf(fid, "%d,", vec_p->val.byte_val);
1375            DDBE_SPELL_COMMENT(fid, vec_p->comment, "\t/* %s */", comment);
1376            fprintf(fid, "\n");
1377            break;
1378
1379        case DDBE_vec_comment_k:
1380            DDBE_SPELL_COMMENT(fid, vec_p->comment, "\t\t/* %s */\n", comment);
1381            break;
1382
1383        case DDBE_vec_expr_byte_k:
1384            STRTAB_str_to_string(vec_p->val.expr, &expr);
1385            DDBE_SPELL_INDEX(fid, vec_p->index);
1386            fprintf(fid, "%s,", expr);
1387            DDBE_SPELL_COMMENT(fid, vec_p->comment, "\t/* %s */", comment);
1388            fprintf(fid, "\n");
1389            break;
1390
1391        case DDBE_vec_long_k:
1392            DDBE_SPELL_INDEX(fid, vec_p->index);
1393            DDBE_spell_long_val(fid, vec_p, DDBE_little_endian);
1394            break;
1395
1396        case DDBE_vec_long_bool_k:
1397            DDBE_SPELL_INDEX(fid, vec_p->index);
1398            DDBE_spell_long_bool_val(fid, vec_p, DDBE_little_endian);
1399            break;
1400
1401        case DDBE_vec_noop_k:
1402            break;
1403
1404        case DDBE_vec_pad_k:
1405            /*
1406             * A pad entry says to pad the vector with a number of filler bytes.
1407             * Spell out the proper number of filler bytes.
1408             */
1409            DDBE_SPELL_INDEX(fid, vec_p->index);
1410            for (i = 0; i < vec_p->val.byte_val; i++)
1411                fprintf(fid, "0xff,");
1412            DDBE_SPELL_TEXT(fid, "\t/* filler */");
1413            fprintf(fid, "\n");
1414            break;
1415        case DDBE_vec_short_k:
1416            DDBE_SPELL_INDEX(fid, vec_p->index);
1417            DDBE_spell_short_bytes(fid, (unsigned short *)&vec_p->val.short_val,
1418                DDBE_little_endian);
1419            fprintf(fid, "\n");
1420            break;
1421
1422        case DDBE_vec_tag_k:
1423            DDBE_SPELL_INDEX(fid, vec_p->index);
1424            NAMETABLE_id_to_string(vec_p->val.name, &name);
1425            fprintf(fid, "%s,\n", name);
1426            break;
1427
1428        case DDBE_vec_type_kind_k:
1429            DDBE_SPELL_INDEX(fid, vec_p->index);
1430            DDBE_spell_type_kind(fid, vec_p);
1431            break;
1432
1433        case DDBE_vec_expr_arr_k:
1434        case DDBE_vec_expr_k:
1435        case DDBE_vec_name_k:
1436        case DDBE_vec_name_client_k:
1437        case DDBE_vec_name_server_k:
1438        case DDBE_vec_offset_begin_k:
1439        case DDBE_vec_offset_end_k:
1440        case DDBE_vec_sizeof_k:
1441            INTERNAL_ERROR("Vector entry not valid for type vector");
1442
1443        case DDBE_vec_indirect_k:
1444        case DDBE_vec_reference_k:
1445            INTERNAL_ERROR("Unexpected indirect type vector entry");
1446
1447        default:
1448            INTERNAL_ERROR("Invalid type vector entry");
1449        }
1450
1451        vec_p = vec_p->next;
1452    }
1453
1454    DDBE_spell_type_vec_addenda(fid, vip, cmd_opt, cmd_val);
1455
1456    fprintf(fid, "0");
1457    DDBE_SPELL_TEXT(fid, "\t\t/* sentinel */");
1458    fprintf(fid, "\n};\n\n");
1459}
1460
1461/*
1462 *  D D B E _ s p e l l _ p a r a m _ v e c _ d e f
1463 *
1464 *  Spell the definition of the parameter vector for an operation.
1465 */
1466void DDBE_spell_param_vec_def
1467(
1468    FILE            *fid,           /* [in] output file handle */
1469    AST_operation_n_t *oper_p,      /* [in] ptr to AST operation node */
1470    BE_side_t       side,           /* [in] client or server side code */
1471    boolean         *cmd_opt ATTRIBUTE_UNUSED,       /* [in] array of cmd option flags */
1472    void            **cmd_val ATTRIBUTE_UNUSED      /* [in] array of cmd option values */
1473)
1474{
1475    DDBE_oper_i_t   *oper_i_p;      /* Ptr to operation info node */
1476    AST_parameter_n_t *param_p;     /* Ptr to AST parameter node */
1477    unsigned long   param_num;      /* Parameter number */
1478    char const      *param_name;    /* Parameter name */
1479
1480    oper_i_p = oper_p->be_info.dd_oper;
1481
1482    fprintf(fid, "rpc_void_p_t %sparam_vec[%ld];\n", DDBE_PREFIX_IDL,
1483            oper_i_p->num_params);
1484    /*
1485     * Any idl_short_float passed by value needs an idl_short_float stacklocal
1486     * on the client side which is assigned the parameter value in case the
1487     * parameter was promoted to an idl_long_float.
1488     */
1489    if (side == BE_client_side)
1490    {
1491        for (param_num = 1, param_p = oper_p->parameters;
1492             param_p != NULL;
1493             param_num++,   param_p = param_p->next)
1494        {
1495            if (param_p->type->kind == AST_short_float_k)
1496            {
1497                NAMETABLE_id_to_string(param_p->name, &param_name);
1498                fprintf(fid, "idl_short_float IDL_short_float_%ld = %s;\n",
1499                        param_num, param_name);
1500            }
1501        }
1502    }
1503}
1504
1505/*
1506 *  D D B E _ s p e l l _ p a r a m _ v e c _ i n i t
1507 *
1508 *  Spell the initialization of the parameter vector for an operation.
1509 */
1510void DDBE_spell_param_vec_init
1511(
1512    FILE            *fid,           /* [in] output file handle */
1513    AST_operation_n_t *oper_p,      /* [in] ptr to AST operation node */
1514    BE_side_t       side,           /* [in] client or server side code */
1515    boolean         *cmd_opt ATTRIBUTE_UNUSED,       /* [in] array of cmd option flags */
1516    void            **cmd_val ATTRIBUTE_UNUSED      /* [in] array of cmd option values */
1517)
1518{
1519    AST_parameter_n_t *param_p;     /* Ptr to AST parameter node */
1520    DDBE_oper_i_t   *oper_i_p;      /* Ptr to operation info node */
1521    unsigned long   param_num;      /* Parameter number */
1522    char const      *param_name;    /* Parameter name */
1523    boolean         spell_value;    /* TRUE => spell param value not address */
1524
1525    oper_i_p = oper_p->be_info.dd_oper;
1526
1527    /* Function result is stored in a local variable, unless we are using an
1528        additional parameter on the client side for a non-C language or the
1529        function result is 'char' on the client side and -lang fortran. */
1530    if (oper_p->result->type->kind != AST_void_k)
1531        fprintf(fid, "%sparam_vec[0] = (rpc_void_p_t)%cIDL_function_result;\n",
1532                DDBE_PREFIX_IDL,
1533                (
1534                  false
1535                ) ? ' ' : '&' );
1536
1537    for (param_num = 1, param_p = oper_p->parameters;
1538         param_p != NULL;
1539         param_num++,   param_p = param_p->next)
1540    {
1541        /*
1542         * Server side conformant parameters that do not have a represent_as
1543         * type are allocated from heap elsewhere in the server stub routine
1544         * so no initialization is needed here.
1545         */
1546        if (side == BE_server_side && AST_REF_SET(param_p)
1547            && DDBE_cfmt_arr_local_rep(param_p) )
1548            continue;
1549
1550        NAMETABLE_id_to_string(param_p->name, &param_name);
1551        fprintf(fid, "%sparam_vec[%ld] = (rpc_void_p_t)",
1552                DDBE_PREFIX_IDL, param_num);
1553
1554        if (AST_HEAP_SET(param_p) && side == BE_server_side
1555            && !AST_PTR_SET(param_p) && !AST_UNIQUE_SET(param_p)
1556        )
1557        {
1558            fprintf(fid, "rpc_ss_mem_alloc(&IDL_ms.IDL_mem_handle, sizeof");
1559            if (param_p->type->kind == AST_pointer_k && AST_REF_SET(param_p))
1560                CSPELL_cast_exp(fid,
1561                    param_p->type->type_structure.pointer->pointee_type);
1562            else
1563                CSPELL_cast_exp(fid, param_p->type);
1564            fprintf(fid, ");\n");
1565        }
1566        else if (param_p->type->kind == AST_short_float_k
1567                 && side == BE_client_side)
1568        {
1569            fprintf(fid, "&IDL_short_float_%ld;\n", param_num);
1570        }
1571        else
1572        {
1573            spell_value =
1574                (   (side == BE_client_side
1575                     && !(param_p->type->kind == AST_pointer_k
1576                             && param_p->type->type_structure.pointer
1577                                ->pointee_type->kind == AST_interface_k)
1578                     && (AST_REF_SET(param_p)
1579                                                ))
1580                 || (side == BE_server_side && AST_REF_SET(param_p)
1581                     && (param_p->type->kind == AST_array_k
1582                         || (param_p->type->kind == AST_pointer_k
1583                             && param_p->type->type_structure.pointer
1584                                ->pointee_type->kind == AST_array_k))) );
1585            fprintf(fid, "%s%s;\n", (spell_value) ? "" : "&", param_name);
1586        }
1587    }
1588
1589    if (param_num != oper_i_p->num_params)
1590    {
1591        INTERNAL_ERROR("Param count does not match param vec allocation");
1592    }
1593}
1594
1595/*
1596 *  D D B E _ s p e l l _ m a r s h _ o r _ u n m a r
1597 *
1598 *  Spells the code to marshall or unmarshall the parameters in an operation.
1599 */
1600void DDBE_spell_marsh_or_unmar
1601(
1602    FILE            *fid,           /* [in] output file handle */
1603    AST_operation_n_t *oper_p,      /* [in] ptr to AST operation node */
1604    const char      *interp_name,   /* [in] marshalling interpreter rtn name */
1605    const char      *state_ptr_name,/* [in] name of state pointer variable */
1606    BE_side_t       side,           /* [in] client or server side code */
1607    BE_marshalling_k_t mar_or_unmar /* [in] spell marshall or unmarshall code */
1608)
1609{
1610    DDBE_oper_i_t   *oper_i_p;      /* Ptr to operation info node */
1611    boolean         in_params;      /* TRUE => processing [in] parameters */
1612
1613    oper_i_p = oper_p->be_info.dd_oper;
1614
1615    in_params = ((side == BE_client_side && mar_or_unmar == BE_marshalling_k)
1616              || (side == BE_server_side && mar_or_unmar == BE_unmarshalling_k));
1617
1618    /* Marshalling interpreter routine name */
1619    fprintf(fid, "%s(", interp_name);
1620
1621    /* Number of parameters */
1622    fprintf(fid, "\n    %ld,",
1623        (in_params) ? ((side == BE_server_side) ?
1624                        oper_i_p->num_srv_ins : oper_i_p->num_ins)
1625                    : oper_i_p->num_outs);
1626    DDBE_SPELL_TEXT_1ARG(fid, "\t/* number of [%s] parameters */",
1627                         ((in_params) ? "in" : "out"));
1628
1629    /* Type vector index of first param */
1630    fprintf(fid, "\n    %s,",
1631        (in_params) ? DDBE_spell_long_nf(oper_i_p->ins_type_index)
1632                      : DDBE_spell_long_nf(oper_i_p->outs_type_index));
1633    DDBE_SPELL_TEXT_1ARG(fid,
1634                         "\t/* type vector index of first [%s] parameter */",
1635                         ((in_params) ? "in" : "out"));
1636
1637    /* Param vector, marshalling state */
1638    fprintf(fid, "\n    IDL_param_vec, %s", state_ptr_name);
1639
1640    /* End of routine call */
1641    fprintf(fid, ");\n");
1642}
1643