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**      cstubmts.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 <command.h>
95#include <cspell.h>
96#include <cspeldcl.h>
97#include <ddbe.h>
98#include <ifspec.h>
99#include <commstat.h>
100#include <clihamts.h>
101#include <cstubgen.h>
102#include <mtsbacke.h>
103#include <cstubmts.h>
104#include <user_exc.h>
105#include <icharsup.h>
106#include <hdgen.h>
107
108BE_handle_info_t BE_handle_info;
109
110static AST_interface_n_t * the_interface = NULL;
111
112//centeris wfu to keep track of the cpp_quotes in between interfaces
113static AST_cpp_quote_n_t * global_cppquotes = NULL;
114
115static AST_cpp_quote_n_t * global_cppquotes_post = NULL;
116
117/******************************************************************************/
118/*                                                                            */
119/*    Spell test of status after runtime call                                 */
120/*                                                                            */
121/******************************************************************************/
122void CSPELL_test_status
123(
124    FILE *fid
125)
126{
127    fprintf(fid,
128             "if (IDL_ms.IDL_status != error_status_ok) goto IDL_closedown;\n");
129}
130
131/******************************************************************************/
132/*                                                                            */
133/*    Spell test of status after rpc_call_transceive                          */
134/*                                                                            */
135/******************************************************************************/
136void CSPELL_test_transceive_status
137(
138    FILE *fid
139)
140{
141    fprintf(fid, "if (IDL_ms.IDL_status != error_status_ok)\n{\n");
142    fprintf(fid, "IDL_ms.IDL_elt_p = NULL;\n");
143    if ( ( BE_handle_info.handle_type == BE_auto_handle_k )
144          && ( ! BE_handle_info.auto_handle_idempotent_op ) )
145    {
146        fprintf(fid,
147"IDL_ms.IDL_restartable=IDL_ms.IDL_restartable&&(!(rpc_call_did_mgr_execute\n");
148        fprintf(fid,"  ((rpc_call_handle_t)IDL_ms.IDL_call_h,&IDL_st2)));\n");
149    }
150    fprintf(fid, "goto IDL_closedown;\n}\n");
151}
152
153/******************************************************************************/
154/*                                                                            */
155/*    Spell client stub routine header                                        */
156/*                                                                            */
157/******************************************************************************/
158void CSPELL_csr_header
159(
160    FILE *fid,
161    char const *p_interface_name,       /* Ptr to name of interface */
162    AST_operation_n_t *p_operation, /* Ptr to operation node */
163    boolean use_internal_name       /* use internal name if true */
164)
165{
166	char op_internal_name[3 * MAX_ID];
167	NAMETABLE_id_t emitted_name;
168	AST_parameter_n_t * handle_param = NULL;
169
170	if (use_internal_name) {
171		sprintf(op_internal_name, "op%d_csr", p_operation->op_number);
172		emitted_name = NAMETABLE_add_id(op_internal_name);
173		fprintf(fid, "\nstatic ");
174	}
175	else if (AST_OBJECT_SET(the_interface))	{
176		sprintf(op_internal_name, "%sProxy::%s", p_interface_name,
177				BE_get_name(p_operation->name));
178		emitted_name = NAMETABLE_add_id(op_internal_name);
179
180		/* Skip handle params */
181		if (BE_is_handle_param(p_operation->parameters))	{
182			handle_param = p_operation->parameters;
183			p_operation->parameters = p_operation->parameters->next;
184		}
185	} else {
186		fprintf (fid, "\n");
187		emitted_name = p_operation->name;
188	}
189
190	CSPELL_function_def_header (fid, p_operation, emitted_name);
191
192	CSPELL_finish_synopsis (fid, p_operation->parameters);
193
194	/* restore skipped handle params */
195	if (handle_param)
196		p_operation->parameters->next = handle_param;
197
198}
199
200/******************************************************************************/
201/*                                                                            */
202/*    Generation of a stub for a client operation call                        */
203/*                                                                            */
204/******************************************************************************/
205static void CSPELL_client_stub_routine
206(
207    FILE *fid,                      /* Handle for emitted C text */
208    AST_interface_n_t *p_interface, /* Ptr to AST interface node */
209    language_k_t language ATTRIBUTE_UNUSED,          /* Language stub is to interface to */
210    AST_operation_n_t *p_operation, /* Ptr to AST operation node */
211    char const *p_interface_name,   /* Ptr to name of interface */
212    unsigned long op_num,           /* Number of current operation */
213    boolean *cmd_opt,               /* Command line options */
214    int num_declared_exceptions,    /* Count of user declared exceptions */
215    int num_extern_exceptions       /* Count of user extern_exceptions */
216)
217{
218    BE_stat_info_t comm_stat_info;
219    BE_stat_info_t fault_stat_info;
220    BE_cs_info_t cs_info;           /* I-char machinery description */
221    boolean use_internal_name = cmd_opt[opt_cepv];
222    boolean midl_mode = cmd_opt[opt_midl];
223
224    /* What sort of status reporting? */
225    BE_get_comm_stat_info( p_operation, &comm_stat_info );
226    BE_get_fault_stat_info( p_operation, &fault_stat_info );
227
228    /* Routine header */
229    CSPELL_csr_header(fid, p_interface_name, p_operation,
230        use_internal_name);
231
232    fprintf (fid, "{\n");
233
234	 if (AST_OBJECT_SET(p_interface))	{
235		 /* If we skipped a handle param, add it as a local var */
236		 if (BE_is_handle_param(p_operation->parameters))
237			 CSPELL_var_decl(fid, p_operation->parameters->type,
238					 p_operation->parameters->name);
239
240	 }
241
242    /*
243     * Analyze the association handle the call is being made on;
244     * declare assoc_handle if necessary
245     */
246    BE_setup_client_handle (fid, p_interface, p_operation, &BE_handle_info);
247
248    /*
249     * Does operation use I-char machinery? If so, declare any needed variables
250     */
251    BE_cs_analyze_and_spell_vars(fid, p_operation, BE_client_side, &cs_info);
252
253    /*
254     * Standard local variables
255     */
256    fprintf(fid, "rpc_transfer_syntax_t\t\tIDL_transfer_syntax;\n");
257    fprintf(fid, "rpc_iovector_elt_t\t\tIDL_outs;\n");
258    fprintf(fid, "volatile ndr_ulong_int\t\tIDL_fault_code=error_status_ok;\n");
259    fprintf(fid, "volatile ndr_ulong_int\t\tIDL_user_fault_id=0;\n");
260    fprintf(fid,
261           "volatile RPC_SS_THREADS_CANCEL_STATE_T IDL_async_cancel_state;\n");
262    fprintf(fid, "IDL_ms_t\t\tIDL_ms;\n");
263    fprintf(fid, "idl_byte\t\tIDL_stack_packet[IDL_STACK_PACKET_SIZE];\n");
264
265    DDBE_spell_param_vec_def( fid, p_operation, BE_client_side,
266                              BE_cmd_opt, BE_cmd_val );
267
268    /* If there is a function result, we need somewhere to put it */
269    if ( (p_operation->result->type->kind != AST_void_k)
270       )
271    {
272        CSPELL_typed_name(fid, p_operation->result->type,
273                            NAMETABLE_add_id("IDL_function_result"),
274                            NULL, false, true, false);
275        fprintf(fid, ";\n");
276    }
277
278    /*
279     * Start of executable code
280     */
281    fprintf(fid, "\nRPC_SS_INIT_CLIENT\n");
282    fprintf(fid, "RPC_SS_THREADS_DISABLE_ASYNC(IDL_async_cancel_state);\n");
283    if ( BE_handle_info.handle_type == BE_auto_handle_k )
284    {
285        fprintf( fid, "IDL_ms.IDL_restartable=idl_true;\n" );
286        fprintf(fid,
287     "RPC_SS_THREADS_ONCE(&IDL_interface_client_once,IDL_auto_handle_init);\n");
288    }
289    else
290    {
291	/*
292	 *  To support those platforms which do not allow both a CATCH and
293	 *  FINALLY clause on the same TRY, we generate one TRY block with a
294	 *  catch clause nested inside another TRY block with the FINALLY
295	 *  clause.  We conditionally generate the extra TRY statement only for
296	 *  non-auto handle case because for auto-handle we already have an
297	 *  nest TRY block.
298	 */
299#ifdef NO_TRY_CATCH_FINALLY
300	fprintf(fid, "DCETHREAD_TRY\n");
301#endif
302    }
303
304    /* If there are user exceptions which are not external, initialize them */
305    if (num_declared_exceptions != 0)
306    {
307        fprintf(fid,
308             "RPC_SS_THREADS_ONCE(&IDL_exception_once,IDL_exceptions_init);\n");
309    }
310
311    fprintf(fid, "rpc_ss_init_marsh_state(IDL_type_vec, &IDL_ms);\n");
312
313    /* Centeris: set alloc/free function pointers if in MIDL mode */
314
315    if (midl_mode)
316    {
317        fprintf(fid, "IDL_ms.IDL_mem_handle.alloc = midl_user_allocate;\n");
318        fprintf(fid, "IDL_ms.IDL_mem_handle.free = midl_user_free;\n");
319        fprintf(fid, "rpc_ss_set_client_alloc_free(IDL_midl_user_allocate, IDL_midl_user_free);\n");
320    }
321
322    fprintf(fid,
323             "IDL_ms.IDL_stack_packet_status = IDL_stack_packet_unused_k;\n");
324    fprintf(fid, "IDL_ms.IDL_stack_packet_addr = IDL_stack_packet;\n");
325    fprintf(fid, "DCETHREAD_TRY\n");
326    fprintf(fid, "IDL_ms.IDL_call_h = 0;\n");
327    fprintf(fid, "IDL_ms.IDL_elt_p = NULL;\n");
328    fprintf(fid, "IDL_ms.IDL_offset_vec = IDL_offset_vec;\n");
329    fprintf(fid, "IDL_ms.IDL_rtn_vec = IDL_rtn_vec;\n");
330    DDBE_spell_param_vec_init( fid, p_operation, BE_client_side,
331                               BE_cmd_opt, BE_cmd_val );
332    fprintf(fid, "IDL_ms.IDL_param_vec = IDL_param_vec;\n");
333    fprintf(fid, "IDL_ms.IDL_side = IDL_client_side_k;\n");
334    fprintf(fid, "IDL_ms.IDL_language = ");
335        fprintf(fid, "IDL_lang_c_k");
336    fprintf(fid, ";\n");
337
338    if (AST_HAS_FULL_PTRS_SET(p_operation) &&
339        (AST_HAS_IN_PTRS_SET(p_operation) || AST_HAS_OUT_PTRS_SET(p_operation)))
340    {
341        fprintf(fid,
342"rpc_ss_init_node_table(&IDL_ms.IDL_node_table,&IDL_ms.IDL_mem_handle);\n");
343    }
344
345    if (AST_HAS_OUT_PTRS_SET(p_operation) )
346    {
347        /* The following call is done here to enable PRT testing */
348        fprintf(fid, "rpc_ss_mts_client_estab_alloc(&IDL_ms);\n");
349    }
350
351    /* Does operation use I-char machinery? If so, set up needed state */
352    BE_spell_cs_state(fid, "IDL_ms.", BE_client_side, &cs_info);
353    /*          And call the [cs_tag_rtn] if there is one */
354    BE_spell_cs_tag_rtn_call(fid, "IDL_ms.", p_operation, BE_client_side,
355                             &BE_handle_info, &cs_info, false);
356
357/* WEZ:setup the handle here ? */
358
359    CSPELL_call_start(fid, &BE_handle_info, p_interface, p_operation, op_num,
360                        &comm_stat_info, &fault_stat_info);
361
362    if (AST_HAS_IN_CTX_SET(p_operation)
363        || AST_HAS_OUT_CTX_SET(p_operation)
364        || cs_info.cs_machinery)
365    {
366        fprintf(fid, "IDL_ms.IDL_h=(handle_t)%c%s;\n",
367                     BE_handle_info.deref_assoc, BE_handle_info.assoc_name);
368    }
369
370    /* Marshall the ins */
371        DDBE_spell_marsh_or_unmar( fid, p_operation, "rpc_ss_ndr_marsh_interp",
372                                "&IDL_ms", BE_client_side, BE_marshalling_k );
373
374    fprintf(fid,"IDL_ms.IDL_elt_p = &IDL_outs;\n");
375    fprintf(fid,
376"rpc_call_transceive((rpc_call_handle_t)IDL_ms.IDL_call_h,(rpc_iovector_p_t)&IDL_ms.IDL_iovec,\n");
377        fprintf(fid,
378"  IDL_ms.IDL_elt_p,&IDL_ms.IDL_drep,(unsigned32*)&IDL_ms.IDL_status);\n");
379
380    /* !!WORKAROUND!! for problem with buff_dealloc for [maybe] operation
381                      with CN runtime */
382    if (AST_MAYBE_SET(p_operation))
383        fprintf(fid, "IDL_outs.buff_dealloc=NULL;\n");
384
385    CSPELL_test_transceive_status(fid);
386
387    /* Unmarshall the outs */
388        DDBE_spell_marsh_or_unmar( fid, p_operation, "rpc_ss_ndr_unmar_interp",
389                                "&IDL_ms", BE_client_side, BE_unmarshalling_k );
390
391    fprintf(fid, "IDL_closedown: __IDL_UNUSED_LABEL__;\n");
392
393    /*
394     * Catch the error that indicates that st has be set to a failing status
395     * that should be reported, and then do normal cleanup processing.  If
396     * for some reason the status is not set, then set it.
397     */
398    fprintf(fid, "DCETHREAD_CATCH(rpc_x_ss_pipe_comm_error)\n");
399    if ( BE_handle_info.handle_type == BE_auto_handle_k )
400    {
401        DDBE_spell_restart_logic( fid, p_operation );
402
403        /*
404         * This label is used when no valid auto-handle binding can be
405         * found.  The call to this is generated in CSPELL_bind_auto_handle
406         * when no valid binding can be found.
407         */
408        fprintf(fid, "IDL_auto_binding_failure:;\n");
409    }
410    else {
411	/*
412	 *  Add the matching ENDTRY for the nested TRY/CATCH block, if
413	 *  necessary, as decribed above.
414	 */
415#ifdef NO_TRY_CATCH_FINALLY
416	fprintf(fid, "DCETHREAD_ENDTRY\n");
417#endif
418    }
419
420    /*
421     * Normal cleanup processing to free up resources and end the call and
422     * and report any faults or failing statuses.
423     */
424    fprintf(fid, "DCETHREAD_FINALLY\n");
425        fprintf(fid, "rpc_ss_ndr_clean_up(&IDL_ms);\n");
426
427    /* End the call, but only if we have one to end for auto handle */
428    if ( BE_handle_info.handle_type == BE_auto_handle_k )
429        fprintf(fid, "if(IDL_ms.IDL_call_h!=NULL)");
430    fprintf(fid,
431"rpc_ss_call_end_2(&IDL_ms.IDL_call_h,&IDL_fault_code,&IDL_user_fault_id,&IDL_ms.IDL_status);\n");
432    CSPELL_binding_free_if_needed( fid, &BE_handle_info );
433
434    /* Must free user binding after ending the call */
435    if ((BE_handle_info.handle_type == BE_parm_user_handle_k)
436        || (BE_handle_info.handle_type == BE_impl_user_handle_k))
437    {
438        /* There is a user handle to unbind. As we are inside an exception
439           handler, we don't want any exception the unbind causes */
440        fprintf (fid, "DCETHREAD_TRY\n");
441        fprintf (fid, "%s_unbind(%c%s%s, (handle_t)IDL_assoc_handle);\n",
442            BE_handle_info.type_name, BE_handle_info.deref_generic,
443            BE_handle_info.user_handle_name,
444                                            "");
445        fprintf (fid, "DCETHREAD_FINALLY\n");
446    }
447
448    /* If [represent_as] on handle_t parameter, release the handle_t */
449    if ((BE_handle_info.handle_type == BE_rep_as_handle_t_k)
450        || (BE_handle_info.handle_type == BE_rep_as_handle_t_p_k))
451    {
452        fprintf (fid, "DCETHREAD_TRY\n");
453        fprintf( fid, "%s_free_inst((handle_t *)%s);\n",
454                    BE_get_name(BE_handle_info.rep_as_type),
455                    assoc_handle_ptr );
456        fprintf (fid, "DCETHREAD_FINALLY\n");
457    }
458
459    /* Release memory allocated by stub code */
460    fprintf(fid, "if (IDL_ms.IDL_mem_handle.memory)\n{\n");
461    fprintf(fid, " rpc_ss_mem_free(&IDL_ms.IDL_mem_handle);\n}\n");
462
463    /* Give status information to client, or raise the appropriate exception */
464    CSPELL_return_status( fid, &comm_stat_info, &fault_stat_info,
465        "IDL_ms.IDL_status",
466        ( (comm_stat_info.type == BE_stat_result_k)
467            || (fault_stat_info.type == BE_stat_result_k) )
468                ? "IDL_function_result" : (char *)NULL,
469        num_declared_exceptions + num_extern_exceptions, "&IDL_ms" );
470
471    fprintf(fid, "RPC_SS_THREADS_RESTORE_ASYNC(IDL_async_cancel_state);\n");
472    if ((BE_handle_info.handle_type == BE_parm_user_handle_k)
473        || (BE_handle_info.handle_type == BE_impl_user_handle_k)
474        || (BE_handle_info.handle_type == BE_rep_as_handle_t_k)
475        || (BE_handle_info.handle_type == BE_rep_as_handle_t_p_k))
476    {
477        fprintf(fid, "DCETHREAD_ENDTRY\n");
478    }
479    fprintf(fid, "DCETHREAD_ENDTRY\n");
480
481    /* Set the return value */
482    if ( (p_operation->result->type->kind != AST_void_k)
483       )
484        fprintf(fid, "return IDL_function_result;\n");
485    fprintf (fid, "}\n");
486/* WEZ:we could spell out c -> c++ mappings here */
487}
488
489/******************************************************************************/
490/*                                                                            */
491/*    Stub for an operation with [encode] or [decode] attribute               */
492/*                                                                            */
493/******************************************************************************/
494void DDBE_spell_pickling_stub
495(
496    FILE *fid,
497    AST_interface_n_t *p_interface, /* Ptr to AST interface node */
498    char const *p_interface_name,   /* Ptr to name of interface */
499    AST_operation_n_t *p_operation, /* Ptr to operation node */
500    boolean use_internal_name       /* use internal name if true */
501)
502{
503    boolean encode_decode;  /* True if operation has [encode] and [decode] */
504    const char *action_type;
505    BE_stat_info_t comm_stat_info;
506    BE_stat_info_t fault_stat_info;
507    BE_cs_info_t cs_info;           /* I-char machinery description */
508
509    /* What sort of status reporting? */
510    BE_get_comm_stat_info( p_operation, &comm_stat_info );
511    BE_get_fault_stat_info( p_operation, &fault_stat_info );
512
513    BE_setup_client_handle (fid, p_interface, p_operation, &BE_handle_info);
514    encode_decode = (AST_ENCODE_SET(p_operation)
515                                            && AST_DECODE_SET(p_operation));
516
517    CSPELL_csr_header(fid, p_interface_name, p_operation, use_internal_name);
518
519    fprintf(fid, "{\n");
520    /*
521     * Standard local variables
522     */
523    fprintf(fid, "volatile ndr_ulong_int IDL_fault_code=error_status_ok;\n");
524    fprintf(fid, "volatile ndr_ulong_int IDL_user_fault_id=0;\n");
525    fprintf(fid,
526           "volatile RPC_SS_THREADS_CANCEL_STATE_T IDL_async_cancel_state;\n");
527    fprintf(fid, "IDL_es_state_t *IDL_es_state_p;\n");
528    fprintf(fid, "volatile IDL_ms_t *IDL_msp;\n");
529    fprintf(fid, "idl_es_transfer_syntax_t IDL_es_transfer_syntax;\n");
530    DDBE_spell_param_vec_def( fid, p_operation, BE_client_side,
531                              BE_cmd_opt, BE_cmd_val );
532
533    /* If there is a function result, we need somewhere to put it */
534    if ( (p_operation->result->type->kind != AST_void_k)
535       )
536    {
537        CSPELL_typed_name(fid, p_operation->result->type,
538                            NAMETABLE_add_id("IDL_function_result"),
539                            NULL, false, true, false);
540        fprintf(fid, ";\n");
541    }
542
543    /*
544     * Does operation use I-char machinery? If so, declare any needed variables
545     */
546    BE_cs_analyze_and_spell_vars(fid, p_operation, BE_client_side, &cs_info);
547
548    /*
549     * Start of executable code
550     */
551    fprintf(fid, "RPC_SS_INIT_CLIENT\n");
552    fprintf(fid, "RPC_SS_THREADS_DISABLE_ASYNC(IDL_async_cancel_state);\n");
553    fprintf(fid, "IDL_es_state_p = (IDL_es_state_t *)%c%s;\n",
554                BE_handle_info.deref_assoc, BE_handle_info.assoc_name);
555    fprintf(fid, "IDL_msp = (volatile IDL_ms_t *)IDL_es_state_p->IDL_msp;\n");
556    fprintf(fid, "IDL_msp->IDL_offset_vec = IDL_offset_vec;\n");
557    fprintf(fid, "IDL_msp->IDL_rtn_vec = IDL_rtn_vec;\n");
558    fprintf(fid, "DCETHREAD_TRY\n");
559    DDBE_spell_param_vec_init( fid, p_operation, BE_client_side,
560                               BE_cmd_opt, BE_cmd_val );
561    fprintf(fid, "IDL_msp->IDL_param_vec = IDL_param_vec;\n");
562    fprintf(fid, "IDL_msp->IDL_side = IDL_client_side_k;\n");
563    fprintf(fid, "IDL_msp->IDL_language = ");
564        fprintf(fid, "IDL_lang_c_k");
565    fprintf(fid, ";\n");
566
567    if (AST_HAS_FULL_PTRS_SET(p_operation) &&
568        (AST_HAS_IN_PTRS_SET(p_operation) || AST_HAS_OUT_PTRS_SET(p_operation)))
569    {
570        fprintf(fid,
571"rpc_ss_init_node_table(&IDL_msp->IDL_node_table,&IDL_msp->IDL_mem_handle);\n");
572    }
573
574    if (AST_HAS_OUT_PTRS_SET(p_operation) )
575    {
576        fprintf(fid, "rpc_ss_mts_client_estab_alloc(IDL_msp);\n");
577    }
578
579    /* Does operation use I-char machinery? If so, set up needed state */
580    BE_spell_cs_state(fid, "IDL_msp->", BE_client_side, &cs_info);
581    if (cs_info.cs_machinery)
582        fprintf(fid, "IDL_msp->IDL_h=NULL;\n");
583
584    if (encode_decode)
585        action_type = "IDL_both_k";
586    else if (AST_ENCODE_SET(p_operation))
587        action_type = "IDL_encoding_k";
588    else
589        action_type = "IDL_decoding_k";
590    fprintf(fid,
591"idl_es_before_interp_call(%c%s,(rpc_if_handle_t)&IDL_ifspec,\n",
592                BE_handle_info.deref_assoc, BE_handle_info.assoc_name);
593    fprintf(fid,
594"  IDL_type_vec,%d,%s,&IDL_es_transfer_syntax,(IDL_msp_t)IDL_msp);\n",
595                p_operation->op_number, action_type);
596
597    /* If there is I-char machinery,  call the [cs_tag_rtn] if there is one */
598    BE_spell_cs_tag_rtn_call(fid, "IDL_msp->", p_operation, BE_client_side,
599                             &BE_handle_info, &cs_info, true);
600
601        if (encode_decode)
602            fprintf(fid,
603                    "if (IDL_es_state_p->IDL_action == IDL_encoding_k)\n{\n");
604        if (AST_ENCODE_SET(p_operation))
605            DDBE_spell_marsh_or_unmar( fid, p_operation,
606                                       "rpc_ss_ndr_marsh_interp",
607                                       "(IDL_msp_t)IDL_msp",
608                                       BE_client_side, BE_marshalling_k );
609        if (encode_decode)
610            fprintf(fid, "}\nelse\n{\n");
611        if (AST_DECODE_SET(p_operation))
612            DDBE_spell_marsh_or_unmar( fid, p_operation,
613                                       "rpc_ss_ndr_unmar_interp",
614                                       "(IDL_msp_t)IDL_msp",
615                                       BE_client_side, BE_unmarshalling_k );
616        if (encode_decode)
617            fprintf(fid, "}\n");
618    fprintf(fid, "idl_es_after_interp_call((IDL_msp_t)IDL_msp);\n");
619    fprintf(fid, "DCETHREAD_CATCH(rpc_x_ss_pipe_comm_error)\n");
620    fprintf(fid, "DCETHREAD_FINALLY\n");
621
622    /* Clean-up code */
623    fprintf(fid, "idl_es_clean_up((IDL_msp_t)IDL_msp);\n");
624
625    /* Give status information to client, or raise the appropriate exception */
626    CSPELL_return_status( fid, &comm_stat_info, &fault_stat_info,
627        "IDL_msp->IDL_status",
628        ( (comm_stat_info.type == BE_stat_result_k)
629            || (fault_stat_info.type == BE_stat_result_k) )
630                ? "IDL_function_result" : (char *)NULL,
631        0, "(IDL_msp_t)IDL_msp" );
632    fprintf(fid, "RPC_SS_THREADS_RESTORE_ASYNC(IDL_async_cancel_state);\n");
633
634    fprintf(fid, "DCETHREAD_ENDTRY\n");
635
636    /* Set the return value */
637    if ( (p_operation->result->type->kind != AST_void_k)
638       )
639    {
640        fprintf(fid, "return IDL_function_result;\n");
641    }
642    fprintf (fid, "}\n");
643}
644
645/******************************************************************************/
646/*                                                                            */
647/*    Main control flow for generating a client stub                          */
648/*                                                                            */
649/******************************************************************************/
650void DDBE_gen_cstub
651(
652    FILE *fid,                      /* Handle for emitted C text */
653    AST_interface_n_t *p_interface, /* Ptr to AST interface node */
654    language_k_t language,          /* Language stub is to interface to */
655    char header_name[],         /* Name of header file to be included in stub */
656    boolean *cmd_opt,
657    void **cmd_val,
658    DDBE_vectors_t *dd_vip    /* Data driven BE vector information ptr */
659)
660{
661    AST_export_n_t *p_export;
662    AST_operation_n_t *p_operation;
663    char const *p_interface_name;
664    boolean first;
665    /* Exceptions may be declared or external. We need a count of both */
666    int num_declared_exceptions;
667    int num_extern_exceptions;
668    boolean midl_mode = cmd_opt[opt_midl];
669
670    the_interface = p_interface;
671    NAMETABLE_id_to_string(p_interface->name, &p_interface_name);
672
673    /*
674     * Emit a #pragma nostandard to suppress warnings on non-standard C usage
675     */
676    CSPELL_suppress_stub_warnings(fid);
677
678    /*
679     * Emit #defines and #includes
680     */
681    CSPELL_mts_includes(fid, header_name);
682
683    /*
684     * Emit MIDL-compatible allocator wrappers
685     */
686    if (midl_mode)
687    {
688	CSPELL_midl_compatibility_allocators(fid);
689    }
690
691    /*
692     * Emit if_spec definition
693     */
694    CSPELL_interface_def(fid, p_interface, BE_client_stub_k, false);
695
696    /* If necessary, emit statics needed for [auto_handle] */
697    if ( AST_AUTO_HANDLE_SET(p_interface) || AST_OBJECT_SET(p_interface))
698    {
699        CSPELL_auto_handle_statics( fid );
700    }
701
702	 /* Declare the Proxy class for ORPC */
703	 if (AST_OBJECT_SET(p_interface))	{
704		 BE_gen_orpc_defs(fid, p_interface, proxy_def);
705	 }
706
707    /* If there is an implicit handle, declare it */
708    if (p_interface->implicit_handle_name != NAMETABLE_NIL_ID)
709    {
710            fprintf( fid, "globaldef " );
711        if ( ! AST_IMPLICIT_HANDLE_G_SET(p_interface) )
712        {
713            fprintf(fid, "handle_t ");
714        }
715        else
716        {
717            spell_name( fid, p_interface->implicit_handle_type_name);
718            fprintf( fid, " " );
719        }
720        spell_name( fid, p_interface->implicit_handle_name);
721        fprintf( fid, ";\n" );
722    }
723
724    /* If there are any user exceptions, emit the necessary declarations */
725    DDBE_user_exceptions(fid, p_interface,
726                         &num_declared_exceptions, &num_extern_exceptions);
727
728    /*
729     *  Set up interpreter data structures
730     */
731    DDBE_spell_offset_vec( fid, dd_vip, cmd_opt, cmd_val );
732    DDBE_spell_rtn_vec( fid, dd_vip, cmd_opt, cmd_val, TRUE );
733    DDBE_spell_type_vec( fid, dd_vip, cmd_opt, cmd_val );
734
735    /*
736     * Emit operation definitions
737     */
738    for (p_export = p_interface->exports; p_export; p_export = p_export->next)
739    {
740        if (p_export->kind == AST_operation_k)
741        {
742            BE_push_malloc_ctx();
743            NAMETABLE_set_temp_name_mode();
744            p_operation = p_export->thing_p.exported_operation;
745            if (!AST_NO_CODE_SET(p_operation))
746            {
747                if (AST_ENCODE_SET(p_operation) || AST_DECODE_SET(p_operation))
748                    DDBE_spell_pickling_stub(fid, p_interface,
749                        p_interface_name, p_operation, cmd_opt[opt_cepv]);
750                else
751                    CSPELL_client_stub_routine(
752                        fid, p_interface, language,
753                        p_operation, p_interface_name, p_operation->op_number,
754                        /* cmd_opt[opt_cepv], */ cmd_opt, num_declared_exceptions,
755                        num_extern_exceptions);
756            }
757            NAMETABLE_clear_temp_name_mode();
758            BE_pop_malloc_ctx();
759        }
760    }
761
762    if (cmd_opt[opt_cepv]) {
763        /*
764         * Emit EPV declarations
765         */
766        fprintf(fid, "/* global */ %s_v%ld_%ld_epv_t %s_v%ld_%ld_c_epv = {\n",
767            p_interface_name,
768            (p_interface->version%65536), (p_interface->version/65536),
769            p_interface_name,
770            (p_interface->version%65536), (p_interface->version/65536));
771
772        first = true;
773
774        for (p_export = p_interface->exports; p_export;
775                p_export = p_export->next)
776            if (p_export->kind == AST_operation_k)
777        {
778            if (first) first = false;
779            else fprintf (fid, ",\n");
780            p_operation = p_export->thing_p.exported_operation;
781            if (!AST_NO_CODE_SET(p_operation))
782            {
783                fprintf(fid, " op%d_csr", p_operation->op_number);
784            }
785            else fprintf(fid, " NULL");
786        }
787        fprintf (fid, "\n};\n");
788    }
789
790    /*
791     * Emit a closing #pragma standard to match the nostandard pragma above
792     */
793    CSPELL_restore_stub_warnings(fid);
794
795    the_interface = NULL;
796}
797