1/*
2 * Copyright (c) 2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1.  Redistributions of source code must retain the above copyright
11 *     notice, this list of conditions and the following disclaimer.
12 * 2.  Redistributions in binary form must reproduce the above copyright
13 *     notice, this list of conditions and the following disclaimer in the
14 *     documentation and/or other materials provided with the distribution.
15 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
16 *     contributors may be used to endorse or promote products derived from
17 *     this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * Portions of this software have been released under the following terms:
31 *
32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC.
33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY
34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION
35 *
36 * To anyone who acknowledges that this file is provided "AS IS"
37 * without any express or implied warranty:
38 * permission to use, copy, modify, and distribute this file for any
39 * purpose is hereby granted without fee, provided that the above
40 * copyright notices and this notice appears in all source code copies,
41 * and that none of the names of Open Software Foundation, Inc., Hewlett-
42 * Packard Company or Digital Equipment Corporation be used
43 * in advertising or publicity pertaining to distribution of the software
44 * without specific, written prior permission.  Neither Open Software
45 * Foundation, Inc., Hewlett-Packard Company nor Digital
46 * Equipment Corporation makes any representations about the suitability
47 * of this software for any purpose.
48 *
49 * Copyright (c) 2007, Novell, Inc. All rights reserved.
50 * Redistribution and use in source and binary forms, with or without
51 * modification, are permitted provided that the following conditions
52 * are met:
53 *
54 * 1.  Redistributions of source code must retain the above copyright
55 *     notice, this list of conditions and the following disclaimer.
56 * 2.  Redistributions in binary form must reproduce the above copyright
57 *     notice, this list of conditions and the following disclaimer in the
58 *     documentation and/or other materials provided with the distribution.
59 * 3.  Neither the name of Novell Inc. nor the names of its contributors
60 *     may be used to endorse or promote products derived from this
61 *     this software without specific prior written permission.
62 *
63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY
67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
73 *
74 * @APPLE_LICENSE_HEADER_END@
75 */
76
77/*
78**  NAME:
79**
80**      sstubmts.c
81**
82**  FACILITY:
83**
84**      Interface Definition Language (IDL) Compiler
85**
86**  ABSTRACT:
87**
88**  Generation of server stub file for MTS compiler
89**
90*/
91
92#include <nidl.h>
93#include <ast.h>
94#include <bedeck.h>
95#include <command.h>
96#include <ddbe.h>
97#include <ifspec.h>
98#include <cspeldcl.h>
99#include <cspell.h>
100#include <mtsbacke.h>
101#include <mtspipes.h>
102#include <sstubmts.h>
103#include <user_exc.h>
104#include <clihandl.h>
105#include <icharsup.h>
106#include <cstubmts.h>
107
108typedef struct param_node_link_t {
109    AST_parameter_n_t *p_param;
110    struct param_node_link_t *p_next;
111} param_node_link_t;
112/* Used to build a list of "interesting" parameters of an operation */
113
114typedef enum {
115                                /* handle_t parameter with [represent_as] */
116    BE_no_rep_as_handle_t_k,  /* not present */
117    BE_val_rep_as_handle_t_k, /* passed by value */
118    BE_ref_rep_as_handle_t_k  /* passed by reference */
119} BE_rep_as_handle_t_k_t;
120
121static char rep_as_handle_name[] = "IDL_handle_rep_as";
122
123/*
124 * BE_server_binding_analyze
125 *
126 * Find whether operation can be called by [auto_handle] client, and
127 * whether there is a first handle_t parameter with a [represent_as] attribute
128 *
129 */
130static void BE_server_binding_analyze
131(
132    AST_operation_n_t *p_operation,
133    boolean *server_binding_explicit, /* TRUE if no client can use [auto_handle]
134                                         binding with this operation */
135    BE_rep_as_handle_t_k_t *p_rep_as_handle_param,
136    NAMETABLE_id_t *p_rep_as_type_name,  /* type of handle param */
137    NAMETABLE_id_t *p_binding_handle_name
138)
139{
140    AST_parameter_n_t *p_first_parameter;
141    AST_type_n_t *p_type, *p_pointee_type;
142
143    *p_rep_as_handle_param = BE_no_rep_as_handle_t_k;
144    *p_binding_handle_name = NAMETABLE_add_id("IDL_binding_handle");
145    p_first_parameter = p_operation->parameters;
146    if ( p_first_parameter == NULL )
147    {
148        /* No parameters */
149        *server_binding_explicit = false;
150        return;
151    }
152    p_type = p_first_parameter->type;
153    if ( p_type->kind == AST_handle_k )
154    {
155        /* handle_t by value */
156        *server_binding_explicit = true;
157        *p_binding_handle_name = p_first_parameter->name;
158        if ( p_type->rep_as_type != NULL )
159        {
160            *p_rep_as_handle_param = BE_val_rep_as_handle_t_k;
161            *p_rep_as_type_name = p_type->name;
162        }
163        return;
164    }
165    if ( AST_HANDLE_SET(p_type) )
166    {
167        /* Customized handle by value */
168        *server_binding_explicit = true;
169        return;
170    }
171    if ( p_type->kind == AST_pointer_k )
172    {
173        p_pointee_type = p_type->type_structure.pointer->pointee_type;
174        if ( p_pointee_type->kind == AST_handle_k )
175        {
176            /* handle_t by reference */
177            *server_binding_explicit = true;
178            *p_binding_handle_name = p_first_parameter->name;
179            if ( p_pointee_type->rep_as_type != NULL )
180            {
181                *p_rep_as_handle_param = BE_ref_rep_as_handle_t_k;
182                *p_rep_as_type_name = p_pointee_type->name;
183            }
184            return;
185        }
186        if ( AST_HANDLE_SET(p_pointee_type) )
187        {
188            /* Customized handle by reference */
189            *server_binding_explicit = true;
190            return;
191        }
192    }
193    if ( AST_HAS_IN_CTX_SET(p_operation) )
194    {
195        *server_binding_explicit = true;
196        return;
197    }
198    if ( AST_EXPLICIT_HANDLE_SET(p_operation) )
199    {
200        /* [explicit_handle] in ACF */
201        *server_binding_explicit = false;
202        return;
203    }
204    *server_binding_explicit = false;
205    return;
206}
207
208/*
209 * CSPELL_zero_initializer
210 *
211 * Emit a type-specific zero-initializer for a parameter that has been declared
212 * on the stack of a server stub routine.
213 */
214static void CSPELL_zero_initializer
215(
216    FILE *fid,
217    const AST_type_n_t *type
218)
219{
220
221	switch (type->kind)
222	{
223	    case AST_pointer_k:
224	    case AST_handle_k:
225		fprintf(fid, " = NULL");
226		break;
227	    case AST_boolean_k:
228		fprintf(fid, " = ndr_false");
229		break;
230	    case AST_short_float_k:
231	    case AST_long_float_k:
232		fprintf(fid, " = 0.0");
233		break;
234	    case AST_small_integer_k:
235	    case AST_short_integer_k:
236	    case AST_long_integer_k:
237	    case AST_small_unsigned_k:
238	    case AST_short_unsigned_k:
239	    case AST_long_unsigned_k:
240		fprintf(fid, " = 0");
241		break;
242	    case AST_hyper_integer_k:
243		fprintf(fid, " = 0ULL");
244		break;
245	    case AST_hyper_unsigned_k:
246		fprintf(fid, " = 0LL");
247		break;
248	    case AST_array_k:
249	    case AST_structure_k:
250	    case AST_disc_union_k:
251		fprintf(fid, " = {}");
252		break;
253	    default:
254		fprintf(fid, " /* no initializer for kind %d */", type->kind);
255		break;
256	}
257}
258
259/*
260 * DDBE_spell_stack_surrogates
261 *
262 * Spell server surrogates as stack variables
263 */
264static void DDBE_spell_stack_surrogates
265(
266    FILE *fid,
267    param_node_link_t **p_fixed_char_array_list ATTRIBUTE_UNUSED,
268                /* Pointer to list of fixed size character array parameters */
269    AST_operation_n_t *p_operation
270)
271{
272    unsigned long param_index;
273    AST_parameter_n_t *pp;  /* Pointer down list of parameters */
274    AST_type_n_t array_elt_ptr_type_node;
275    AST_pointer_n_t array_elt_ptr_pointer_node;
276
277    param_index = 0;
278    for (pp = p_operation->parameters; pp != NULL; pp = pp->next)
279    {
280        param_index++;
281        if (param_index == 1)
282        {
283            if (pp->type->kind == AST_handle_k)
284            {
285                continue;
286            }
287            else if ( (pp->type->kind == AST_pointer_k)
288                      && (pp->type->type_structure.pointer->pointee_type->kind
289                                                     == AST_handle_k) )
290            {
291                continue;
292            }
293        }
294        if (AST_REF_SET(pp) && (pp->type->rep_as_type == NULL)
295            && (AST_CONFORMANT_SET(pp->type)
296                      || (DDBE_ARRAYIFIED(pp)
297                          && AST_CONFORMANT_SET(pp->type->type_structure.
298                             pointer->pointee_type->array_rep_type))))
299        {
300            /* [ref] arrayified pointer or array without [ptr] or [unique]
301                 Storage allocated by interpreter */
302            continue;
303        }
304        if ((pp->type->kind == AST_pointer_k) && AST_REF_SET(pp)
305                 && AST_CONFORMANT_SET(pp->type->type_structure.pointer
306                                        ->pointee_type)
307                 && (pp->type->type_structure.pointer->pointee_type
308                        ->rep_as_type == NULL))
309        {
310            /* [ref] pointer to conformant object
311                 Storage allocated by interpreter */
312            continue;
313        }
314        /*
315         * No surrogate is needed for a [heap] parameter unless it has a
316         * non-[ref] pointer attribute in which case a surrogate for the
317         * pointer is needed and the pointee is allocated in the Interpreter.
318         */
319        if (AST_HEAP_SET(pp) && !AST_PTR_SET(pp) && !AST_UNIQUE_SET(pp))
320        {
321            /* No stack surrogate. Storage allocated by interpreter */
322            continue;
323        }
324        if (AST_CONTEXT_SET(pp))
325        {
326            /* Special data structure for context handle */
327            fprintf(fid,"IDL_ee_context_t %s;\n", BE_get_name(pp->name));
328            continue;
329        }
330        if (AST_CONTEXT_SET(pp))
331        {
332            /* Special data structure for context handle */
333            fprintf(fid,"IDL_ee_context_t %s;\n", BE_get_name(pp->name));
334            continue;
335        }
336        if (pp->type->kind == AST_pointer_k)
337        {
338            CSPELL_typed_name(fid,
339                              (AST_REF_SET(pp)
340                               ? pp->type->type_structure.pointer->pointee_type
341                               : pp->type),
342                              pp->name, NULL, false, true, false);
343
344	    CSPELL_zero_initializer(fid,
345		    AST_REF_SET(pp) ? pp->type->type_structure.pointer->pointee_type
346                               : pp->type);
347        }
348        else if ( (pp->type->kind == AST_array_k)
349                    && (AST_UNIQUE_SET(pp) || AST_PTR_SET(pp)) )
350        {
351            array_elt_ptr_pointer_node.pointee_type
352                = pp->type->type_structure.array->element_type;
353            array_elt_ptr_type_node.name = NAMETABLE_NIL_ID;
354            array_elt_ptr_type_node.kind = AST_pointer_k;
355            array_elt_ptr_type_node.flags = 0;
356            array_elt_ptr_type_node.xmit_as_type = NULL;
357            array_elt_ptr_type_node.rep_as_type = NULL;
358            array_elt_ptr_type_node.cs_char_type = NULL;
359            array_elt_ptr_type_node.array_rep_type = NULL;
360            array_elt_ptr_type_node.type_structure.pointer
361                = &array_elt_ptr_pointer_node;
362            CSPELL_typed_name(fid, &array_elt_ptr_type_node,
363                              pp->name, NULL, false, true, false);
364	    CSPELL_zero_initializer(fid, &array_elt_ptr_type_node);
365        }
366        else
367	{
368            CSPELL_typed_name(fid, pp->type, pp->name, NULL, false, true,
369                                false);
370	    CSPELL_zero_initializer(fid, pp->type);
371	}
372        fprintf(fid, ";\n");
373    }
374}
375
376/*
377 * CSPELL_manager_call
378 *
379 * Emit a call to a manager operation
380 */
381static void CSPELL_manager_call
382(
383    FILE *fid,
384    AST_interface_n_t *p_interface,
385    AST_operation_n_t *p_operation,
386    BE_rep_as_handle_t_k_t rep_as_handle_param,
387    NAMETABLE_id_t rep_as_type_name,
388    NAMETABLE_id_t binding_handle_name
389)
390{
391    AST_parameter_n_t *pp;  /* Pointer down list of parameters */
392    int param_index;        /* Index of parameter in param list */
393    int visible_param_count;    /* Number of parameters spelt into call */
394
395    if ( rep_as_handle_param != BE_no_rep_as_handle_t_k )
396    {
397        fprintf( fid, "%s_to_local(&%s,&%s);\n",
398                BE_get_name(rep_as_type_name),
399                BE_get_name(binding_handle_name),
400                rep_as_handle_name );
401    }
402
403    fprintf (fid, "\n/* manager call */\n");
404    fprintf( fid, "IDL_manager_entered = ndr_true;\n" );
405    fprintf( fid, "RPC_SS_THREADS_DISABLE_ASYNC(IDL_async_cancel_state);\n");
406
407    if (AST_NO_CANCEL_SET(p_operation))
408        fprintf( fid, "RPC_SS_THREADS_DISABLE_GENERAL(IDL_general_cancel_state);\n" );
409    else
410        fprintf( fid, "RPC_SS_THREADS_ENABLE_GENERAL(IDL_general_cancel_state);\n" );
411
412    if (p_operation->result->type->kind != AST_void_k)
413    {
414        if (AST_CONTEXT_SET(p_operation->result))
415            fprintf(fid, "IDL_function_result.local = ");
416        else
417            fprintf(fid, "IDL_function_result = ");
418    }
419
420    fprintf(fid, "(*((%s_v%ld_%ld_epv_t *)IDL_mgr_epv)->",
421            BE_get_name(p_interface->name), (p_interface->version%65536),
422            (p_interface->version/65536));
423            spell_name(fid, p_operation->name);
424
425    fprintf(fid,")(");
426    visible_param_count = 0;
427    param_index = 1;
428    for (pp = p_operation->parameters; pp != NULL; pp = pp->next)
429    {
430        if (AST_HIDDEN_SET(pp))
431        {
432            /* Parameter does not appear in signature delivered to user */
433            /* Note that hidden parameter cannot appear before binding handle */
434            param_index++;
435            continue;
436        }
437        else
438        {
439            visible_param_count++;
440            if (visible_param_count > 1)
441                fprintf (fid, ",\n ");
442        }
443        if (param_index == 1)
444        {
445            if ( rep_as_handle_param != BE_no_rep_as_handle_t_k )
446            {
447                fprintf( fid, "%c%s",
448                  ((rep_as_handle_param == BE_ref_rep_as_handle_t_k)
449                                                                        )
450                                                                    ? '&' : ' ',
451                  rep_as_handle_name );
452                param_index++;
453                continue;
454            }
455            else if (pp->type->kind == AST_handle_k)
456            {
457                spell_name(fid, binding_handle_name);
458                param_index++;
459                continue;
460            }
461            else if ( (pp->type->kind == AST_pointer_k)
462                      && (pp->type->type_structure.pointer->pointee_type->kind
463                                                     == AST_handle_k) )
464            {
465                fprintf(fid, "&%s", BE_get_name(binding_handle_name));
466                param_index++;
467                continue;
468            }
469        }
470
471        if ((AST_HEAP_SET(pp)
472            || (AST_CONFORMANT_SET(pp->type)
473                 && !AST_UNIQUE_SET(pp) && !AST_PTR_SET(pp))
474            || ((pp->type->kind == AST_pointer_k) && AST_REF_SET(pp)
475                    && (BE_Is_Arrayified(pp,pp->type)
476                        || AST_CONFORMANT_SET(pp->type->type_structure.pointer
477                                                ->pointee_type))))
478           )
479        {
480            /*
481             * Cast needed on (void *) pointer to dynamically allocated store.
482             * A different cast is needed if we need to dereference the ptr.
483             */
484            boolean deref;
485            if ((pp->type->kind == AST_array_k)
486                && (AST_UNIQUE_SET(pp) || AST_PTR_SET(pp)))
487            {
488                DDBE_spell_manager_param_cast( fid, pp->type );
489                fprintf(fid, "*(rpc_void_p_t *)");
490            }
491            else
492            {
493                deref = ((pp->type->kind != AST_pointer_k)
494                     && (pp->type->kind != AST_array_k)
495                    );
496                if (!deref)
497                    DDBE_spell_manager_param_cast( fid, pp->type );
498                fprintf( fid, "%c", ((deref) ? '*' : ' ') );
499                if (deref)
500                    CSPELL_ptr_cast_exp( fid, pp->type );
501            }
502            fprintf( fid, "(IDL_param_vec[%d])", param_index );
503        }
504        else if (AST_CONTEXT_SET(pp))
505        {
506            /* Opaque context handle type requires cast */
507            if (pp->type->type_structure.pointer->pointee_type->kind
508                == AST_pointer_k
509                &&  pp->type->type_structure.pointer->pointee_type->
510                    type_structure.pointer->pointee_type->kind
511                    == AST_structure_k)
512                CSPELL_cast_exp(fid, pp->type);
513            /* Context handle by value is pointer to void,
514                              by reference is pointer to pointer to void */
515            fprintf( fid, "%c%s.local",
516                     ((pp->type->type_structure.pointer->pointee_type->kind
517                                                            == AST_pointer_k)
518                                                                            )
519                                                                    ? '&' : ' ',
520                     BE_get_name(pp->name) );
521        }
522        else
523        {
524            if (
525                   ((pp->type->kind == AST_pointer_k) && AST_REF_SET(pp)
526                    && !(BE_Is_Arrayified(pp,pp->type))) )
527            {
528                /* non-arrayified parameter passed by reference, but not for interfaces */
529					if (!(pp->type->kind == AST_pointer_k && pp->type->type_structure.pointer->pointee_type->kind == AST_interface_k))
530                fprintf(fid, "&");
531            }
532            spell_name(fid, pp->name);
533        }
534
535        param_index++;
536    }
537
538    fprintf(fid, ");\n");
539    fprintf( fid,
540              "RPC_SS_THREADS_RESTORE_GENERAL(IDL_general_cancel_state);\n" );
541    fprintf( fid, "RPC_SS_THREADS_RESTORE_ASYNC(IDL_async_cancel_state);\n");
542
543    if ( rep_as_handle_param != BE_no_rep_as_handle_t_k )
544    {
545        fprintf( fid, "%s_free_local(&%s);\n",
546                BE_get_name(rep_as_type_name),
547                rep_as_handle_name );
548    }
549}
550
551/*
552 * DDBE_convert_out_contexts
553 *
554 * Convert user [out] context handles from local format to wire format
555 * and change the param vector entries to point at the wire formats
556 *
557 */
558static void DDBE_convert_out_contexts
559(
560    FILE *fid,
561    AST_operation_n_t *p_operation,
562    NAMETABLE_id_t binding_handle_name
563)
564{
565    AST_parameter_n_t *pp;
566
567    if ( AST_CONTEXT_SET(p_operation->result) )
568    {
569        fprintf(fid,
570"rpc_ss_ee_ctx_to_wire(IDL_function_result.local,&IDL_function_result.wire, %s,",
571        BE_get_name(binding_handle_name));
572        if ( AST_CONTEXT_RD_SET(p_operation->result->type) )
573        {
574            spell_name(fid, p_operation->result->type->name);
575            fprintf(fid, "_rundown, ");
576        }
577        else
578            fprintf(fid, "(void (*)())NULL, ");
579        fprintf(fid, "idl_false, &IDL_ms.IDL_status);\n");
580        CSPELL_test_status(fid);
581    }
582
583    for (pp = p_operation->parameters; pp != NULL; pp = pp->next)
584    {
585        if ( AST_OUT_SET(pp) && AST_CONTEXT_SET(pp) )
586        {
587            fprintf(fid, "rpc_ss_ee_ctx_to_wire(%s.local, &%s.wire, %s,",
588                    BE_get_name(pp->name), BE_get_name(pp->name),
589                    BE_get_name(binding_handle_name));
590            /* [out] context must be passed by reference.
591                    Does it require rundown? */
592            if ( AST_CONTEXT_RD_SET(pp->type->type_structure.pointer
593                                                            ->pointee_type) )
594            {
595                spell_name(fid, pp->type->type_structure.pointer
596                                                          ->pointee_type->name);
597                fprintf(fid, "_rundown, ");
598            }
599            else
600                fprintf(fid, "(void (*)())NULL, ");
601            fprintf(fid, "%s, &IDL_ms.IDL_status);\n",
602                         AST_IN_SET(pp) ? "idl_true" : "idl_false");
603            CSPELL_test_status(fid);
604        }
605    }
606}
607
608/*
609 *  CSPELL_server_stub_routine
610 *
611 *  Generate a server stub routine for an operation
612 */
613static void CSPELL_server_stub_routine
614(
615    FILE *fid,
616    language_k_t language ATTRIBUTE_UNUSED,
617    AST_interface_n_t *p_interface,
618    AST_operation_n_t *p_operation,
619    int num_declared_exceptions,    /* Count of user declared exceptions */
620    int num_extern_exceptions,       /* Count of user extern_exceptions */
621    boolean *cmd_opt
622)
623{
624    long first_pipe;        /* Index of first pipe to be processed */
625    boolean explicit_binding;
626    BE_rep_as_handle_t_k_t rep_as_handle_param;
627    NAMETABLE_id_t rep_as_type_name = NULL;
628    NAMETABLE_id_t binding_handle_name;
629    param_node_link_t *fixed_char_array_list = NULL;
630                /* List of fixed size character array parameters */
631    BE_cs_info_t cs_info;           /* I-char machinery description */
632    BE_handle_info_t handle_info;
633    boolean midl_mode = cmd_opt[opt_midl];
634
635    BE_server_binding_analyze(p_operation, &explicit_binding,
636                 &rep_as_handle_param, &rep_as_type_name, &binding_handle_name);
637    handle_info.deref_assoc = ' ';
638    NAMETABLE_id_to_string(binding_handle_name, &handle_info.assoc_name);
639
640    fprintf (fid, "\nstatic void op%d_ssr", p_operation->op_number);
641
642    fprintf (fid, "\n");
643
644    fprintf (fid, "(\n");
645    fprintf (fid, " handle_t %s,\n", handle_info.assoc_name);
646    fprintf (fid, " rpc_call_handle_t IDL_call_h,\n");
647    fprintf (fid, " rpc_iovector_elt_p_t IDL_elt_p,\n");
648    fprintf (fid, " ndr_format_p_t IDL_drep_p,\n");
649    fprintf (fid, " __IDL_UNUSED__ rpc_transfer_syntax_p_t IDL_transfer_syntax_p,\n");
650    fprintf (fid, " rpc_mgr_epv_t IDL_mgr_epv,\n");
651    fprintf (fid, " error_status_t *IDL_status_p\n)\n");
652
653    fprintf (fid, "{\n");
654    fprintf(fid, "IDL_ms_t IDL_ms;\n");
655    fprintf(fid, "volatile ndr_boolean IDL_manager_entered = ndr_false;\n");
656    fprintf(fid,
657         "volatile RPC_SS_THREADS_CANCEL_STATE_T IDL_async_cancel_state=RPC_SS_THREADS_CANCEL_STATE_T_INITIALIZER;\n");
658    fprintf(fid,
659         "volatile RPC_SS_THREADS_CANCEL_STATE_T IDL_general_cancel_state=RPC_SS_THREADS_CANCEL_STATE_T_INITIALIZER;\n");
660    fprintf(fid, "idl_byte IDL_stack_packet[IDL_STACK_PACKET_SIZE];\n");
661
662    if (AST_HAS_IN_PIPES_SET(p_operation)
663    || AST_HAS_OUT_PIPES_SET(p_operation))
664    {
665        fprintf(fid, "long IDL_current_pipe = 0;\n");
666    }
667
668    DDBE_spell_param_vec_def( fid, p_operation, BE_server_side,
669                              BE_cmd_opt, BE_cmd_val );
670    DDBE_spell_stack_surrogates( fid,
671                                 &fixed_char_array_list,
672                                 p_operation );
673
674    /* Does operation use I-char machinery? If so, declare needed variables */
675    BE_cs_analyze_and_spell_vars(fid, p_operation, BE_server_side, &cs_info);
676
677    if (AST_HAS_IN_PTRS_SET(p_operation)
678    || AST_HAS_OUT_PTRS_SET(p_operation)
679    || AST_ENABLE_ALLOCATE_SET(p_operation))
680    {
681        fprintf(fid, "rpc_ss_thread_support_ptrs_t IDL_support_ptrs;\n");
682    }
683
684    /* If there is a function result, we need somewhere to put it */
685    if (p_operation->result->type->kind != AST_void_k)
686    {
687        if ( AST_CONTEXT_SET(p_operation->result) )
688        {
689            /* Declare stack workspace for the wire form of context handle
690                    function result */
691            fprintf(fid, "IDL_ee_context_t IDL_function_result;\n");
692        }
693        else
694        {
695            CSPELL_typed_name(fid, p_operation->result->type,
696                            NAMETABLE_add_id("IDL_function_result"),
697                            NULL, false, true, false);
698            fprintf(fid, ";\n");
699        }
700    }
701
702    if ( rep_as_handle_param != BE_no_rep_as_handle_t_k )
703    {
704        fprintf( fid, "%s %s;\n",
705                      BE_get_name(rep_as_type_name), rep_as_handle_name );
706    }
707
708    if (AST_HAS_IN_CTX_SET(p_operation)
709        || AST_HAS_OUT_CTX_SET(p_operation))
710    {
711        fprintf(fid, "rpc_client_handle_t IDL_client_id=NULL;\n");
712    }
713
714    /*
715     *  Start of executable code
716     */
717    fprintf(fid, "RPC_SS_INIT_SERVER\n");
718    fprintf(fid, "rpc_ss_init_marsh_state(IDL_type_vec, &IDL_ms);\n");
719
720    /* Centeris: set memory management callbacks if in midl mode */
721    if (midl_mode)
722    {
723        fprintf(fid, "IDL_ms.IDL_mem_handle.alloc = midl_user_allocate;\n");
724        fprintf(fid, "IDL_ms.IDL_mem_handle.free = midl_user_free;\n");
725    }
726
727    fprintf(fid,
728             "IDL_ms.IDL_stack_packet_status = IDL_stack_packet_unused_k;\n");
729    fprintf(fid, "IDL_ms.IDL_stack_packet_addr = IDL_stack_packet;\n");
730    fprintf(fid, "DCETHREAD_TRY\n");
731    fprintf(fid, "IDL_ms.IDL_offset_vec = IDL_offset_vec;\n");
732    fprintf(fid, "IDL_ms.IDL_rtn_vec = IDL_rtn_vec;\n");
733    fprintf(fid, "IDL_ms.IDL_call_h = (volatile rpc_call_handle_t)IDL_call_h;\n");
734    fprintf(fid, "IDL_ms.IDL_drep = *IDL_drep_p;\n");
735
736    fprintf(fid, "IDL_ms.IDL_elt_p = IDL_elt_p;\n");
737    DDBE_spell_param_vec_init( fid, p_operation, BE_server_side,
738                               BE_cmd_opt, BE_cmd_val );
739    fprintf(fid, "IDL_ms.IDL_param_vec = IDL_param_vec;\n");
740    fprintf(fid, "IDL_ms.IDL_side = IDL_server_side_k;\n");
741    fprintf(fid, "IDL_ms.IDL_language = ");
742        fprintf(fid, "IDL_lang_c_k");
743    fprintf(fid, ";\n");
744
745    /* Does operation use I-char machinery? If so, set up needed state */
746    BE_spell_cs_state(fid, "IDL_ms.", BE_server_side, &cs_info);
747    if (cs_info.cs_machinery)
748        fprintf(fid, "IDL_ms.IDL_h=%s;\n", handle_info.assoc_name);
749
750    /* If there are user exceptions which are not external, initialize them */
751    if (num_declared_exceptions != 0)
752    {
753        fprintf(fid,
754             "RPC_SS_THREADS_ONCE(&IDL_exception_once,IDL_exceptions_init);\n");
755    }
756
757    /*
758     *  Is there a reference from this client to a context?
759     */
760    if (AST_HAS_IN_CTX_SET(p_operation)
761        || AST_HAS_OUT_CTX_SET(p_operation))
762    {
763        fprintf(fid,
764"rpc_ss_ctx_client_ref_count_i_2(%s,&IDL_client_id,(error_status_t*)&IDL_ms.IDL_status);\n",
765              handle_info.assoc_name);
766        CSPELL_test_status(fid);
767    }
768
769    /*
770     * Node initializations
771     */
772    if (AST_HAS_IN_PTRS_SET(p_operation)
773    || AST_HAS_OUT_PTRS_SET(p_operation)
774    || AST_ENABLE_ALLOCATE_SET(p_operation))
775    {
776        fprintf( fid,
777"rpc_ss_create_support_ptrs( &IDL_support_ptrs,&IDL_ms.IDL_mem_handle);\n" );
778        if (AST_HAS_FULL_PTRS_SET(p_operation))
779        {
780            fprintf(fid,
781"rpc_ss_init_node_table(&IDL_ms.IDL_node_table,&IDL_ms.IDL_mem_handle);\n");
782            if (AST_REFLECT_DELETIONS_SET(p_operation))
783            {
784                fprintf(fid,
785                     "rpc_ss_enable_reflect_deletes(IDL_ms.IDL_node_table);\n");
786            }
787        }
788    }
789
790    /*
791     * Pipe initializations
792     */
793    if (AST_HAS_IN_PIPES_SET(p_operation) || AST_HAS_OUT_PIPES_SET(p_operation))
794    {
795        DDBE_init_server_pipes( fid, p_operation, &first_pipe );
796        fprintf( fid, "IDL_current_pipe=(%ld);\n", first_pipe );
797    }
798
799    /* Unmarshall the ins */
800        DDBE_spell_marsh_or_unmar( fid, p_operation, "rpc_ss_ndr_unmar_interp",
801                                "&IDL_ms", BE_server_side, BE_unmarshalling_k );
802
803    /* If there is I-char machinery,  call the [cs_tag_rtn] if there is one */
804    BE_spell_cs_tag_rtn_call(fid, "IDL_ms.", p_operation, BE_server_side,
805                             &handle_info, &cs_info, false);
806
807    CSPELL_manager_call(fid, p_interface, p_operation,
808                    rep_as_handle_param, rep_as_type_name, binding_handle_name);
809
810    DDBE_convert_out_contexts(fid, p_operation, binding_handle_name);
811
812    if (AST_HAS_IN_PIPES_SET(p_operation) || AST_HAS_OUT_PIPES_SET(p_operation))
813    {
814        fprintf( fid, "if (IDL_current_pipe != %d)\n", BE_FINISHED_WITH_PIPES );
815        fprintf( fid, "{\n" );
816        fprintf( fid, "DCETHREAD_RAISE(rpc_x_ss_pipe_discipline_error);\n" );
817        fprintf( fid, "}\n" );
818    }
819
820    /* Marshall the outs */
821        fprintf(fid, "{\n");
822        DDBE_spell_marsh_or_unmar( fid, p_operation, "rpc_ss_ndr_marsh_interp",
823                                "&IDL_ms", BE_server_side, BE_marshalling_k );
824        fprintf(fid, "if (IDL_ms.IDL_iovec.num_elt != 0)\n");
825        fprintf(fid,
826"  rpc_call_transmit((rpc_call_handle_t)IDL_ms.IDL_call_h,(rpc_iovector_p_t)&IDL_ms.IDL_iovec,\n");
827        fprintf(fid,
828            "  (unsigned32*)&IDL_ms.IDL_status);  /* Send remaining outs */\n");
829        fprintf(fid, "\n}");
830
831    fprintf(fid, "\nIDL_closedown: __IDL_UNUSED_LABEL__;\n");
832    fprintf(fid, "DCETHREAD_CATCH_ALL(THIS_CATCH)\n");
833
834    fprintf(fid, "if ( IDL_manager_entered )\n{\n");
835    fprintf(fid,
836              "RPC_SS_THREADS_RESTORE_GENERAL(IDL_general_cancel_state);\n");
837    fprintf(fid, "RPC_SS_THREADS_RESTORE_ASYNC(IDL_async_cancel_state);\n");
838    fprintf(fid, "}\n");
839
840    /*
841     * For all exceptions other than report status, send the exception to the
842     * client.  For the report status exception, just fall through and
843     * perform the normal failing status reporting.
844     */
845        fprintf(fid, "rpc_ss_ndr_clean_up(&IDL_ms);\n");
846    fprintf(fid,
847         "if (!RPC_SS_EXC_MATCHES(THIS_CATCH,&rpc_x_ss_pipe_comm_error))\n{\n");
848    fprintf(fid, "if ( ! IDL_manager_entered )\n{\n");
849    if ( ! explicit_binding )
850    {
851        fprintf(fid, "IDL_ms.IDL_status = rpc_s_manager_not_entered;\n");
852    }
853    fprintf(fid, "}\n");
854    if ( ! explicit_binding )
855    {
856        fprintf(fid, "else\n");
857    }
858    fprintf(fid,"{\n");
859        fprintf(fid,"rpc_ss_send_server_exception_2(IDL_call_h,THIS_CATCH,%d,%s,&IDL_ms);\n",
860            num_declared_exceptions + num_extern_exceptions,
861            (num_declared_exceptions + num_extern_exceptions) ? "IDL_exception_addresses" : "NULL"
862	    );
863    fprintf(fid, "IDL_ms.IDL_status = error_status_ok;\n}\n");
864    fprintf(fid, "}\n");
865    fprintf(fid, "DCETHREAD_ENDTRY\n");
866
867    if (AST_HAS_IN_CTX_SET(p_operation)
868        || AST_HAS_OUT_CTX_SET(p_operation))
869    {
870        fprintf(fid,
871             "rpc_ss_ctx_client_ref_count_d_2(%s, IDL_client_id);\n",
872              handle_info.assoc_name);
873    }
874
875    if (AST_HAS_IN_PTRS_SET(p_operation)
876    || AST_HAS_OUT_PTRS_SET(p_operation)
877    || AST_ENABLE_ALLOCATE_SET(p_operation))
878    {
879        fprintf( fid, "rpc_ss_destroy_support_ptrs();\n" );
880    }
881    fprintf(fid, "if (IDL_ms.IDL_mem_handle.memory)\n{\n");
882    fprintf(fid, " rpc_ss_mem_free(&IDL_ms.IDL_mem_handle);\n}\n");
883    fprintf(fid, "if (IDL_ms.IDL_status != error_status_ok)\n{\n");
884    fprintf(fid, "if (IDL_ms.IDL_status == rpc_s_call_cancelled)\n{\n");
885    fprintf(fid,   "rpc_ss_send_server_exception(");
886    fprintf(fid,      "IDL_call_h,&RPC_SS_THREADS_X_CANCELLED);\n");
887    fprintf(fid,   "IDL_ms.IDL_status = error_status_ok;\n");
888    fprintf(fid,  "}\nelse\n{\n");
889    if ( ! explicit_binding )
890    {
891        fprintf(fid, "if (IDL_manager_entered)\n");
892    }
893    fprintf(fid,   "{\nrpc_ss_send_server_exception(");
894    fprintf(fid,      "IDL_call_h,&rpc_x_ss_remote_comm_failure);\n");
895    fprintf(fid,   "IDL_ms.IDL_status = error_status_ok;\n");
896    fprintf(fid, "}\n}\n}\n");
897
898    /* When reached here IDL_ms.IDL_status is either error_status_ok
899     * or rpc_s_manager_not_entered
900     */
901    fprintf(fid, "*IDL_status_p = IDL_ms.IDL_status;\n");
902
903    fprintf(fid, "}\n");
904}
905
906/*
907 * BE_gen_sstub
908 *
909 * Public entry point for server stub file generation
910 */
911void BE_gen_sstub
912(
913    FILE *fid,              /* Handle for emitted C text */
914    AST_interface_n_t *p_interface,     /* Ptr to AST interface node */
915    language_k_t language,  /* Language stub is to interface to */
916    char header_name[],     /* Name of header file to be included in stub */
917    boolean *cmd_opt,
918    void **cmd_val,
919    DDBE_vectors_t *dd_vip    /* Data driven BE vector information ptr */
920)
921{
922    AST_export_n_t *p_export;
923    AST_operation_n_t *p_operation;
924    boolean first;
925    /* Exceptions may be declared or external. We need a count of both */
926    int num_declared_exceptions;
927    int num_extern_exceptions;
928
929    /*
930     * Emit a #pragma nostandard to suppress warnings on non-standard C usage
931     */
932    CSPELL_suppress_stub_warnings(fid);
933
934    /*
935     * Emit #defines and #includes
936     */
937    CSPELL_mts_includes(fid, header_name);
938
939    /*
940     *  Set up interpreter data structures
941     */
942    DDBE_spell_offset_vec( fid, dd_vip, cmd_opt, cmd_val );
943    DDBE_spell_rtn_vec( fid, dd_vip, cmd_opt, cmd_val, FALSE );
944    DDBE_spell_type_vec( fid, dd_vip, cmd_opt, cmd_val );
945
946    /* If there are any user exceptions, emit the necessary declarations */
947    DDBE_user_exceptions(fid, p_interface,
948                         &num_declared_exceptions, &num_extern_exceptions);
949
950    /*
951     *  Emit manager entry point vector, if requested
952     */
953    if (cmd_opt[opt_mepv])
954	CSPELL_manager_epv(fid, p_interface);
955
956    /*
957     * Emit operation definitions
958     */
959    for (p_export = p_interface->exports; p_export; p_export = p_export->next)
960        if ((p_export->kind == AST_operation_k)
961                && ( ! AST_ENCODE_SET(p_export->thing_p.exported_operation))
962                && ( ! AST_DECODE_SET(p_export->thing_p.exported_operation)))
963        {
964            BE_push_malloc_ctx();
965            NAMETABLE_set_temp_name_mode();
966            p_operation = p_export->thing_p.exported_operation;
967            CSPELL_server_stub_routine(fid, language, p_interface, p_operation,
968                                       num_declared_exceptions, num_extern_exceptions, cmd_opt);
969            NAMETABLE_clear_temp_name_mode();
970            BE_pop_malloc_ctx();
971        }
972
973    /*
974     * Emit server epv
975     */
976    fprintf (fid, "\nstatic rpc_v2_server_stub_proc_t IDL_epva[] = \n{\n");
977    first = true;
978    for (p_export = p_interface->exports; p_export; p_export = p_export->next)
979        if (p_export->kind == AST_operation_k)
980        {
981            if (first)
982                first = false;
983            else
984                fprintf(fid, ",\n");
985            if (AST_ENCODE_SET(p_export->thing_p.exported_operation)
986                || AST_DECODE_SET(p_export->thing_p.exported_operation))
987            {
988                fprintf(fid, "NULL");
989            }
990            else
991                fprintf(
992                    fid, " (rpc_v2_server_stub_proc_t)op%d_ssr",
993                    p_export->thing_p.exported_operation->op_number
994                    );
995        }
996    fprintf (fid, "\n};\n");
997
998    /*
999     * Emit static if_spec definition and global exported pointer
1000     */
1001    CSPELL_interface_def(fid, p_interface, BE_server_stub_k, cmd_opt[opt_mepv]);
1002
1003    /*
1004     * Emit a closing #pragma standard to match the nostandard pragma above
1005     */
1006    CSPELL_restore_stub_warnings(fid);
1007}
1008