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 **      cspell.c
82 **
83 **  FACILITY:
84 **
85 **      Interface Definition Language (IDL) Compiler
86 **
87 **  ABSTRACT:
88 **
89 **      Routines needed by more than one module to output C source
90 **
91 **  VERSION: DCE 1.1
92 **
93 */
94
95#include <nidl.h>
96#include <ast.h>
97#include <cspell.h>
98#include <cspeldcl.h>
99#include <genpipes.h>
100#include <bedeck.h>
101
102/*
103 * The following define, typedef, and four static functions are the
104 * rep for the type_tail_t data type which represents the residual suffix
105 * which must be emitted in a declarator after the name being typed.
106 */
107
108#define MAX_TAIL_LEN 15
109
110typedef enum {p_k, a_k, f_k} type_kind_t;
111typedef struct {
112	int len;
113	struct {
114		type_kind_t kind;
115		union {
116			struct {
117				AST_array_n_t *array;
118				boolean in_typedef_or_struct;
119			} array_info;
120			struct {
121				AST_parameter_n_t *param_list;
122				boolean function_def;
123			} function_info;
124		} content;
125	}  vec[MAX_TAIL_LEN];
126} type_tail_t;
127
128static void CSPELL_add_paren_to_tail
129(
130 type_tail_t *tail
131)
132{
133	int i;
134
135	i = (tail->len) ++;
136	if (tail->len > MAX_TAIL_LEN) INTERNAL_ERROR("Data structure too compilicated; Tail array overflow");
137	(tail->vec)[i].kind = p_k;
138}
139
140static void CSPELL_add_array_to_tail
141(
142 type_tail_t *tail,
143 AST_array_n_t *array,
144 boolean in_typedef_or_struct
145)
146{
147	int i;
148
149	i = (tail->len) ++;
150	if (tail->len > MAX_TAIL_LEN) INTERNAL_ERROR("Data structure too compilicated; Tail array overflow");
151	(tail->vec)[i].kind = a_k;
152	(tail->vec)[i].content.array_info.array = array;
153	(tail->vec)[i].content.array_info.in_typedef_or_struct =
154		in_typedef_or_struct;
155}
156
157static void CSPELL_add_func_to_tail
158(
159 type_tail_t *tail,
160 AST_parameter_n_t *pl,
161 boolean function_def
162)
163{
164	int i;
165
166	i = (tail->len) ++;
167	if (tail->len > MAX_TAIL_LEN) INTERNAL_ERROR("Data structure too compilicated; Tail array overflow");
168	(tail->vec)[i].kind = f_k;
169	(tail->vec)[i].content.function_info.param_list = pl;
170	(tail->vec)[i].content.function_info.function_def = function_def;
171}
172
173static void CSPELL_array_bounds (
174		FILE *fid,
175		AST_array_n_t *array,
176		boolean in_typedef_or_struct
177		);
178
179static void CSPELL_function_sig (
180		FILE *fid,
181		AST_parameter_n_t *pp,
182		boolean func_def,
183		boolean encoding_services
184		);
185
186static void CSPELL_type_tail
187(
188 FILE *fid,
189 type_tail_t *tail,
190 boolean encoding_services   /* TRUE => [encode] or [decode] on operation */
191)
192{
193	int i;
194
195	for (i = 0; i < tail->len; i++)
196		switch (tail->vec[i].kind) {
197			case p_k:
198				fprintf (fid, ")");
199				break;
200			case a_k:
201				CSPELL_array_bounds (
202						fid,
203						tail->vec[i].content.array_info.array,
204						tail->vec[i].content.array_info.in_typedef_or_struct);
205				break;
206			case f_k:
207				CSPELL_function_sig (
208						fid,
209						tail->vec[i].content.function_info.param_list,
210						tail->vec[i].content.function_info.function_def,
211						encoding_services);
212				break;
213			default:
214				INTERNAL_ERROR("Invalid tail kind");
215		}
216}
217
218/*
219 * spell_name
220 *
221 * Output an identifier to the file specified
222 */
223void spell_name
224(
225 FILE *fid,
226 NAMETABLE_id_t name
227)
228{
229	char const *str;
230
231	NAMETABLE_id_to_string (name, &str);
232	fprintf (fid, "%s", str);
233}
234
235static void CSPELL_type_exp (
236		FILE *fid,
237		AST_type_n_t *tp,
238		type_tail_t *tail,
239		AST_type_n_t *in_typedef,
240		boolean in_struct,
241		boolean func_def,
242		boolean spell_tag
243		);
244
245/*
246 * C S P E L L _ s c a l a r _ t y p e _ s u f f i x
247 */
248boolean CSPELL_scalar_type_suffix
249(
250 FILE *fid,
251 AST_type_n_t *tp
252)
253{
254	boolean result = true;
255
256	/* prepend a 'u' for unsigned types */
257	switch (tp->kind) {
258		case AST_small_unsigned_k:
259		case AST_short_unsigned_k:
260		case AST_long_unsigned_k:
261		case AST_hyper_unsigned_k:
262			fprintf (fid, "u");
263		default:
264			/* nothing */
265			break;
266	}
267
268	switch (tp->kind) {
269		case AST_boolean_k:
270			fprintf (fid, "boolean");
271			break;
272
273		case AST_byte_k:
274			fprintf (fid, "byte");
275			break;
276
277		case AST_character_k:
278			fprintf (fid, "char");
279			break;
280
281		case AST_small_integer_k:
282		case AST_small_unsigned_k:
283			fprintf (fid, "small_int");
284			break;
285
286		case AST_short_integer_k:
287		case AST_short_unsigned_k:
288			fprintf (fid, "short_int");
289			break;
290
291		case AST_long_integer_k:
292		case AST_long_unsigned_k:
293			fprintf (fid, "long_int");
294			break;
295
296		case AST_hyper_integer_k:
297		case AST_hyper_unsigned_k:
298			fprintf (fid, "hyper_int");
299			break;
300
301		case AST_short_float_k:
302			fprintf (fid, "short_float");
303			break;
304
305		case AST_long_float_k:
306			fprintf (fid, "long_float");
307			break;
308
309		case AST_enum_k:
310			fprintf (fid, "enum");
311			break;
312
313		default:
314			result = false;
315	}
316	return result;
317}
318
319/*
320 * s p e l l _ i d l _ s c a l a r _ t y p e _ n a m e
321 */
322static void spell_idl_scalar_type_name
323(
324 FILE *fid,
325 AST_type_n_t *tp
326)
327{
328
329	fprintf(fid, "idl_");
330
331	if (CSPELL_scalar_type_suffix(fid, tp))
332		fprintf(fid, " ");
333	else
334		INTERNAL_ERROR("Invalid type kind");
335}
336
337/*
338 * CSPELL_function_sig
339 *
340 * Spell a function's parameter list
341 */
342static void CSPELL_function_sig
343(
344 FILE *fid,
345 AST_parameter_n_t *pp,
346 boolean func_def ATTRIBUTE_UNUSED,
347 boolean encoding_services   /* TRUE => [encode] or [decode] on operation */
348)
349{
350    fprintf (fid, "(\n");
351    CSPELL_parameter_list (fid, pp, encoding_services);
352    fprintf (fid, "\n)");
353}
354
355/*
356 * DDBE_array_is_C_like
357 *
358 * Returns TRUE if there is a natural C mapping for an array
359 */
360static boolean DDBE_array_is_C_like
361(
362 AST_array_n_t *array
363)
364{
365	int i;
366	AST_array_index_n_t *index_array_ptr;
367
368	index_array_ptr = array->index_vec;
369	/* Test for dynamic bounds in dimensions other than the first */
370	for (i = 1; i < array->index_count; i++)
371	{
372		index_array_ptr ++;
373		if ( !(AST_FIXED_LOWER_SET(index_array_ptr))
374				|| !(AST_FIXED_UPPER_SET(index_array_ptr)) )
375		{
376			return( false );
377		}
378	}
379	return( true );
380}
381
382/*
383 * CSPELL_array_bounds
384 *
385 * Spell an array's bounds
386 *
387 */
388static void CSPELL_array_bounds
389(
390 FILE *fid,
391 AST_array_n_t *array,
392 boolean in_typedef_or_struct
393)
394{
395	int i;
396	AST_array_index_n_t *index_array_ptr;
397	long array_dim_size;    /* Size of array in current dimension */
398
399	if ( ! DDBE_array_is_C_like(array) )
400	{
401		if( ! in_typedef_or_struct ) fprintf (fid, "[]");
402		else fprintf (fid, "[1]");
403		return;
404	}
405
406	index_array_ptr = array->index_vec;
407	for (i = 0; i < array->index_count; i++) {
408		if ( (AST_FIXED_LOWER_SET(index_array_ptr))
409				&& (AST_FIXED_UPPER_SET(index_array_ptr)) ) {
410			/* Fixed bounds, convert to C syntax */
411			array_dim_size = index_array_ptr->upper_bound->value.int_val
412				- index_array_ptr->lower_bound->value.int_val + 1;
413			fprintf (fid, "[%ld]", array_dim_size);
414		}
415		else {
416			/* Varying bounds */
417			if ((i == 0) && ( ! in_typedef_or_struct )) fprintf (fid, "[]");
418			else fprintf (fid, "[1]");
419			/* Tell lies as C does not understand conformant non-first bound
420				or conformant bounds within structures or typedefs  */
421		}
422		index_array_ptr ++;
423	}
424}
425
426/*
427 * CSPELL_pipe_struct_routine_decl
428 *
429 * Spell one function pointer type of a pipe's rep type
430 */
431void CSPELL_pipe_struct_routine_decl
432(
433 FILE *fid,
434 AST_type_n_t *p_pipe_type,
435 BE_pipe_routine_k_t routine_kind,
436 boolean cast
437)
438{
439	type_tail_t tail;
440	const char *name = "";
441
442	/* choose a name for the pipe field, unless a cast expression */
443	if (!cast)
444	{
445		name = (routine_kind == BE_pipe_push_k) ? "push" :
446			((routine_kind == BE_pipe_pull_k) ? "pull" : "alloc");
447	}
448
449	fprintf( fid, "void (* %s)(\n",name);
450	fprintf (fid, "rpc_ss_pipe_state_t state,\n" );
451	if ( routine_kind == BE_pipe_alloc_k )
452	{
453		fprintf( fid, "idl_ulong_int bsize,\n" );
454	}
455
456	tail.len = 0;
457	CSPELL_type_exp (fid, p_pipe_type->type_structure.pipe->base_type,
458			&tail, NULL, false, false, true);
459	fprintf( fid, "%s*buf,\n",
460			(routine_kind == BE_pipe_alloc_k) ? "*" : "");
461	CSPELL_type_tail (fid, &tail, false);
462
463	if ( routine_kind == BE_pipe_pull_k )
464	{
465		fprintf( fid, "idl_ulong_int esize,\n" );
466	}
467	fprintf( fid, "idl_ulong_int %c%ccount\n",
468			((routine_kind == BE_pipe_push_k) ? ' ' : '*'),
469			((routine_kind == BE_pipe_alloc_k) ? 'b' : 'e') );
470	fprintf (fid, ")" );
471	if (!cast) fprintf (fid, ";\n");
472}
473
474/*
475 * CSPELL_pipe_def
476 *
477 * Spell a pipe's concrete rep type
478 */
479static void CSPELL_pipe_def
480(
481 FILE *fid,
482 AST_type_n_t *p_pipe_type
483)
484{
485	/* Declare the structure that represents the pipe */
486	fprintf( fid, "struct " );
487	spell_name (fid, p_pipe_type->name);
488	fprintf( fid, " {\n" );
489	CSPELL_pipe_struct_routine_decl( fid, p_pipe_type, BE_pipe_pull_k, FALSE );
490	CSPELL_pipe_struct_routine_decl( fid, p_pipe_type, BE_pipe_push_k, FALSE );
491	CSPELL_pipe_struct_routine_decl( fid, p_pipe_type, BE_pipe_alloc_k, FALSE );
492	fprintf( fid, "rpc_ss_pipe_state_t state;\n" );
493	fprintf( fid, "} " );
494}
495
496/*
497 * CSPELL_type_exp
498 *
499 * Spell a type exp by writing its prefix (i.e. the portion before the
500 * name in a declarator) to file fid and by building a rep of its suffix
501 * in the tail data structure.
502 */
503static void CSPELL_type_exp
504(
505 FILE *fid,
506 AST_type_n_t *tp,
507 type_tail_t *tail,
508 AST_type_n_t *in_typedef,
509 boolean in_struct,
510 boolean func_def,
511 boolean spell_tag
512)
513{
514	AST_field_n_t           *fp;
515	AST_arm_n_t             *cp;
516	AST_disc_union_n_t      *vp;
517	AST_constant_n_t        *ecp;
518	int                     pointer_count;
519	AST_type_n_t            *pointee_tp;
520	boolean                 parenthesized;
521	boolean                 first = true;
522	boolean                 n_e_union;
523
524	/*
525	 * If we are in the process of defining a type which was defined as
526	 * another type, emit the definiend.
527	 */
528	if (in_typedef == tp && tp->defined_as)
529		CSPELL_type_exp (
530				fid,
531				tp->defined_as,
532				tail,
533				in_typedef,
534				in_struct,
535				func_def,
536				spell_tag);
537
538	/*
539	 * If the type has the [represent_as] attribute, emit its local rep name.
540	 */
541	else if (in_typedef != tp && tp->rep_as_type
542			&& !(in_typedef != NULL && in_typedef->name == tp->name))
543	{
544		fprintf( fid, "/* Type must appear in user header or IDL */ " );
545		spell_name (fid, tp->rep_as_type->type_name);
546		fprintf (fid, " ");
547	}
548
549	/*
550	 * If the type has the [cs_char] attribute, emit its local name.
551	 */
552	else if (in_typedef != tp && tp->cs_char_type
553			&& !(in_typedef != NULL && in_typedef->name == tp->name))
554	{
555		fprintf( fid, "/* Type must appear in user header or IDL */ " );
556		spell_name (fid, tp->cs_char_type->type_name);
557		fprintf (fid, " ");
558	}
559
560	/*
561	 * If we are spelling a type which was expressed simply as "struct foo"
562	 * or "union foo" then just echo its original expression
563	 */
564	else if (AST_DEF_AS_TAG_SET(tp))
565	{
566		if (tp->kind == AST_disc_union_k
567				&& tp->type_structure.disc_union->discrim_name == NAMETABLE_NIL_ID)
568			fprintf(fid, "union ");
569		else
570			fprintf (fid, "struct ");
571		if (tp->kind == AST_structure_k)
572			spell_name (fid, tp->type_structure.structure->tag_name);
573		else if (tp->kind == AST_disc_union_k)
574			spell_name (fid, tp->type_structure.disc_union->tag_name);
575		fprintf (fid, " ");
576	}
577
578	/*
579	 * If we are not in the process of defining the type and it has a name,
580	 * emit it.
581	 */
582	else if (in_typedef != tp && tp->name != NAMETABLE_NIL_ID)
583	{
584		spell_name (fid, tp->name);
585		fprintf (fid, " ");
586	}
587
588	/*
589	 * The DEF_AS_TAG case above took care of in_typedef cases where only a
590	 * tag name should be emitted.  If we have gotten this far and we are still
591	 * in_typedef, then the complete structure or union body must be emitted.
592	 * However, if we are not in_typedef, then we should just use a tagname
593	 * here if one exists.
594	 */
595	else if (in_typedef == NULL && tp->kind == AST_structure_k &&
596			tp->type_structure.structure->tag_name != NAMETABLE_NIL_ID)
597	{
598		fprintf (fid, "struct ");
599		spell_name (fid, tp->type_structure.structure->tag_name);
600		fprintf (fid, " ");
601	}
602
603	else if (in_typedef == NULL && tp->kind == AST_disc_union_k &&
604			tp->type_structure.disc_union->tag_name != NAMETABLE_NIL_ID)
605	{
606		if (tp->type_structure.disc_union->discrim_name == NAMETABLE_NIL_ID)
607			fprintf (fid, "union ");
608		else
609			fprintf (fid, "struct ");
610		spell_name (fid, tp->type_structure.disc_union->tag_name);
611		fprintf (fid, " ");
612	}
613
614	else switch (tp->kind) {
615
616		case AST_boolean_k:
617		case AST_byte_k:
618		case AST_small_integer_k:
619		case AST_small_unsigned_k:
620		case AST_short_integer_k:
621		case AST_short_unsigned_k:
622		case AST_long_integer_k:
623		case AST_long_unsigned_k:
624		case AST_hyper_integer_k:
625		case AST_hyper_unsigned_k:
626		case AST_character_k:
627		case AST_short_float_k:
628		case AST_long_float_k:
629			spell_idl_scalar_type_name (fid, tp);
630			break;
631
632		case AST_handle_k:
633			fprintf (fid, "handle_t ");
634			break;
635
636		case AST_enum_k:
637			fprintf (fid, "enum {");
638			for (ecp = tp->type_structure.enumeration->enum_constants;
639					ecp != NULL; ecp = ecp->next) {
640				if (first)
641					first = false;
642				else
643					fprintf (fid, ",\n");
644				spell_name (fid, ecp->name);
645				fprintf(fid, " = %ld", ecp->value.int_val);
646			}
647			fprintf (fid, "} ");
648			break;
649
650		case AST_structure_k:
651			fprintf (fid, "struct ");
652			if ( spell_tag )
653				spell_name (fid, tp->type_structure.structure->tag_name);
654			fprintf (fid, " {\n");
655			for (fp = tp->type_structure.structure->fields; fp != NULL;
656					fp = fp->next) {
657				CSPELL_typed_name (
658						fid,
659						fp->type,
660						fp->name,
661						in_typedef,
662						true,
663						true,
664						false);
665				fprintf (fid, ";\n");
666			}
667			fprintf (fid, "} ");
668			break;
669
670		case AST_disc_union_k:
671			vp = tp->type_structure.disc_union;
672			n_e_union = (vp->discrim_name == NAMETABLE_NIL_ID);
673			if ( ! n_e_union )
674			{
675				fprintf (fid, "struct ");
676				if ( spell_tag )
677					spell_name (fid, tp->type_structure.disc_union->tag_name);
678				fprintf (fid, " {\n");
679				/*
680				 * Use the parameters the procedure was called with
681				 * We know we are declaring a scalar and they will be set null
682				 */
683				CSPELL_typed_name (
684						fid,
685						vp->discrim_type,
686						vp->discrim_name,
687						in_typedef,
688						true,
689						true,
690						false);
691				fprintf (fid, ";\n");
692			}
693			fprintf (fid, "union ");
694			if ( n_e_union && spell_tag )
695				spell_name (fid, tp->type_structure.disc_union->tag_name);
696			fprintf (fid, " {\n");
697			for (cp = vp->arms; cp != NULL; cp = cp->next)
698			{
699				CSPELL_labels (fid, cp->labels);
700				if (cp->type == NULL)
701					fprintf (fid, "/* Empty arm */\n");
702				else
703				{
704					CSPELL_typed_name (
705							fid,
706							cp->type,
707							cp->name,
708							in_typedef,
709							true,
710							true,
711							false);
712					fprintf (fid, ";\n");
713				}
714			}
715			fprintf (fid, "} ");
716			if ( ! n_e_union )
717			{
718				spell_name (fid, vp->union_name);
719				fprintf (fid, ";\n");
720				fprintf (fid, "} ");
721			}
722			break;
723
724		case AST_pipe_k:
725			CSPELL_pipe_def(fid, tp);
726			break;
727
728		case AST_void_k:
729			fprintf (fid, "void ");
730			break;
731
732		case AST_array_k:
733			CSPELL_add_array_to_tail (
734					tail,
735					tp->type_structure.array,
736					(tp == in_typedef) || in_struct);
737			CSPELL_type_exp (
738					fid,
739					tp->type_structure.array->element_type,
740					tail,
741					in_typedef,
742					in_struct,
743					false,
744					spell_tag);
745			break;
746
747		case AST_pointer_k:
748			pointer_count = 0;
749			pointee_tp = tp;
750			while (pointee_tp->kind == AST_pointer_k
751					&& (in_typedef == pointee_tp ||
752						pointee_tp->name == NAMETABLE_NIL_ID))
753			{
754				pointee_tp = pointee_tp->type_structure.pointer->pointee_type;
755				pointer_count++;
756			}
757			if (( parenthesized = (pointee_tp->kind == AST_array_k
758							|| pointee_tp->kind == AST_function_k)))
759				CSPELL_add_paren_to_tail (tail);
760
761			if (pointee_tp->kind == AST_void_k) {
762				fprintf (fid, "idl_void_p_t ");
763				pointer_count--;
764			}
765			else
766				CSPELL_type_exp (
767						fid,
768						pointee_tp,
769						tail,
770						in_typedef,
771						in_struct,
772						false,
773						spell_tag);
774
775			if (parenthesized)
776				fprintf (fid, "(");
777			for (; pointer_count; pointer_count--)
778				fprintf (fid, "*");
779			break;
780
781		case AST_function_k:
782			CSPELL_add_func_to_tail(
783					tail,
784					tp->type_structure.function->parameters,
785					func_def);
786			CSPELL_type_exp(
787					fid,
788					tp->type_structure.function->result->type,
789					tail,
790					in_typedef,
791					in_struct,
792					false,
793					true);
794			break;
795
796		default:
797			INTERNAL_ERROR("Unknown type kind in CSPELL_type_exp");
798	}
799
800}
801
802/*
803 * CSPELL_typed_name
804 */
805void CSPELL_typed_name
806(
807 FILE *fid,
808 AST_type_n_t *type,
809 NAMETABLE_id_t name,
810 AST_type_n_t *in_typedef,
811 boolean in_struct,
812 boolean spell_tag,
813 boolean encoding_services   /* TRUE => [encode] or [decode] on operation */
814)
815{
816	type_tail_t tail;
817
818	tail.len = 0;
819	CSPELL_type_exp (fid, type, &tail, in_typedef, in_struct, false, spell_tag);
820	spell_name (fid, name);
821	CSPELL_type_tail (fid, &tail, encoding_services);
822}
823
824/*
825 * CSPELL_function_def_header
826 */
827void CSPELL_function_def_header
828(
829 FILE *fid,
830 AST_operation_n_t *oper,
831 NAMETABLE_id_t name
832)
833{
834	type_tail_t tail;
835	AST_type_n_t func_type_node;
836
837	func_type_node = *BE_function_p;
838	func_type_node.type_structure.function = oper;
839
840	tail.len = 0;
841	CSPELL_type_exp (fid, &func_type_node, &tail, NULL, false, true, true);
842	spell_name (fid, name);
843	CSPELL_type_tail ( fid, &tail,
844			(AST_ENCODE_SET(oper) || AST_DECODE_SET(oper)) );
845}
846
847/*
848 * CSPELL_type_exp_simple
849 */
850void CSPELL_type_exp_simple
851(
852 FILE *fid,
853 AST_type_n_t *tp
854)
855{
856	CSPELL_typed_name(fid, tp, NAMETABLE_NIL_ID, NULL, false, true, false);
857}
858
859/*
860 * CSPELL_var_decl
861 *
862 * Spell a variable declaration
863 */
864void CSPELL_var_decl
865(
866 FILE *fid,
867 AST_type_n_t *type,
868 NAMETABLE_id_t name
869)
870{
871	CSPELL_typed_name (fid, type, name, NULL, false, true, false);
872	fprintf (fid, ";\n");
873}
874
875/*
876 * CSPELL_cast_exp
877 */
878void CSPELL_cast_exp
879(
880 FILE *fid,
881 AST_type_n_t *tp
882)
883{
884	fprintf (fid, "(");
885	CSPELL_typed_name (fid, tp, NAMETABLE_NIL_ID, NULL, false, true, false);
886	fprintf (fid, ")");
887}
888
889/*
890 * CSPELL_ptr_cast_exp
891 */
892void CSPELL_ptr_cast_exp
893(
894 FILE *fid,
895 AST_type_n_t *tp
896)
897{
898	AST_type_n_t    pointer_type;
899	AST_pointer_n_t pointer;
900
901	/*
902	 * Build temporary nodes to construct a pointer to the passed type,
903	 * then spell the cast expression using normal mechanism.
904	 */
905	memset(&pointer_type, 0, sizeof(pointer_type));
906	pointer_type.kind = AST_pointer_k;
907	pointer_type.type_structure.pointer = &pointer;
908
909	memset(&pointer, 0, sizeof(pointer));
910	pointer.pointee_type = tp;
911
912	CSPELL_cast_exp(fid, &pointer_type);
913}
914
915/*
916 * DDBE_spell_manager_param_cast
917 *
918 * If the parameter being passed to the manager is an array, cast it as a
919*  pointer to the array base type
920*/
921void DDBE_spell_manager_param_cast
922(
923 FILE *fid,
924 AST_type_n_t *tp
925)
926{
927	type_tail_t tail;
928	AST_type_n_t *tp_for_type_exp;
929	AST_type_n_t array_slice_type;
930	AST_array_n_t array_slice_desc;
931
932	fprintf (fid, "(");
933	tail.len = 0;
934	if (tp->kind == AST_array_k)
935	{
936		if ((tp->type_structure.array->index_count == 1)
937				|| !DDBE_array_is_C_like(tp->type_structure.array))
938			tp_for_type_exp = tp->type_structure.array->element_type;
939		else
940		{
941			array_slice_desc.element_type
942				= tp->type_structure.array->element_type;
943			array_slice_desc.index_count
944				= tp->type_structure.array->index_count - 1;
945			array_slice_desc.index_vec
946				= &(tp->type_structure.array->index_vec[1]);
947			array_slice_type = *tp;
948			array_slice_type.name = NAMETABLE_NIL_ID;
949			array_slice_type.type_structure.array = &array_slice_desc;
950			tp_for_type_exp = &array_slice_type;
951		}
952	}
953	else
954		tp_for_type_exp = tp;
955	CSPELL_type_exp (fid, tp_for_type_exp, &tail, NULL, false, false, true);
956
957	if (tp->kind == AST_array_k)
958		fprintf (fid, "(*)");
959
960	CSPELL_type_tail (fid, &tail, false);
961
962	fprintf (fid, ")");
963}
964
965/*
966 * CSPELL_midl_compatibility_allocators
967 */
968void CSPELL_midl_compatibility_allocators
969(
970 FILE *fid
971)
972{
973	fprintf (fid,
974	    "static inline idl_void_p_t IDL_midl_user_allocate(\n"
975	    "    idl_void_p_t context, idl_size_t nbytes)\n"
976	    "{\n"
977	    "    (void)context;\n"
978	    "    return midl_user_allocate(nbytes);\n"
979	    "}\n\n"
980	    "static inline void IDL_midl_user_free(\n"
981	    "    idl_void_p_t context, idl_void_p_t ptr)\n"
982	    "{\n"
983	    "    (void)context;\n"
984	    "    midl_user_free(ptr);\n"
985	    "}\n\n");
986}
987
988/*
989 * CSPELL_suppress_stub_warnings
990 *
991 * Emit a #pragma nostandard to suppress warnings on non-standard C usage and
992 * warnings on legitimate C that is flagged by compilers using high warning
993 * levels.
994 */
995void CSPELL_suppress_stub_warnings
996(
997 FILE *fid
998)
999{
1000    fprintf(fid, "#if __GNUC__\n");
1001    fprintf(fid, "#pragma GCC diagnostic ignored \"-Wmissing-field-initializers\"\n");
1002    fprintf(fid, "#pragma GCC diagnostic ignored \"-Wmissing-braces\"\n");
1003    fprintf(fid, "#endif\n");
1004}
1005
1006void CSPELL_restore_stub_warnings
1007(
1008 FILE *fid ATTRIBUTE_UNUSED
1009)
1010{
1011}
1012