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**      clihamts.c
81**
82**  FACILITY:
83**
84**      Interface Definition Language (IDL) Compiler
85**
86**  ABSTRACT:
87**
88**      Client binding handle stuff for MTS compiler
89**
90*/
91
92#include <nidl.h>
93#include <ast.h>
94#include <bedeck.h>
95#include <commstat.h>
96#include <ifspec.h>
97#include <clihamts.h>
98#include <dutils.h>
99#include <cspell.h>
100#include <cstubgen.h>
101#include <marshall.h>
102
103static char assoc_handle_name[] = "IDL_assoc_handle";
104char assoc_handle_ptr[] = "IDL_assoc_handle_p";
105
106/******************************************************************************/
107/*                                                                            */
108/*    Spell declaration of assoc_handle                                       */
109/*                                                                            */
110/******************************************************************************/
111static void CSPELL_decl_assoc_handle_vars
112(
113    FILE *fid,
114    BE_handle_info_t *p_handle_info
115)
116{
117    if ( (p_handle_info->handle_type == BE_impl_handle_t_k)
118         || (p_handle_info->handle_type == BE_context_handle_k)
119         || (p_handle_info->handle_type == BE_auto_handle_k) )
120    {
121        fprintf( fid, "error_status_t IDL_st2;\n" );
122    }
123    if ( (p_handle_info->handle_type == BE_rep_as_handle_t_k)
124         || (p_handle_info->handle_type == BE_rep_as_handle_t_p_k) )
125    {
126        fprintf( fid, "volatile handle_t *%s;\n", assoc_handle_ptr );
127    }
128    else
129    {
130        fprintf (fid, "volatile handle_t %s;\n", assoc_handle_name);
131    }
132}
133
134/******************************************************************************/
135/*                                                                            */
136/*    Analyze the type of handle to be used in the call, and emit any         */
137/*    necessary declarations                                                  */
138/*                                                                            */
139/******************************************************************************/
140void BE_setup_client_handle
141(
142    FILE *fid,
143    AST_interface_n_t *p_interface,
144    AST_operation_n_t *p_operation,
145    BE_handle_info_t *p_handle_info
146)
147{
148    AST_parameter_n_t *p_first_parameter;
149    AST_type_n_t *p_type;
150
151    p_handle_info->deref_assoc = ' ';
152    p_handle_info->deref_generic = ' ';
153    p_first_parameter = p_operation->parameters;
154    if (p_first_parameter != NULL)
155    {
156        p_type = p_first_parameter->type;
157
158        /* Look for [handle] before handle_t to deal correctly with
159            [transmit_as(...),handle] handle_t */
160        if ( AST_HANDLE_SET(p_type) )
161        {
162            /* Customized handle by value */
163            p_handle_info->handle_type = BE_parm_user_handle_k;
164            p_handle_info->assoc_name = assoc_handle_name;
165            CSPELL_decl_assoc_handle_vars(fid,p_handle_info);
166            NAMETABLE_id_to_string( p_type->name, &(p_handle_info->type_name) );
167            NAMETABLE_id_to_string( p_first_parameter->name,
168                    &(p_handle_info->user_handle_name) );
169            return;
170        }
171        if ( (p_type->kind == AST_pointer_k)
172             && AST_HANDLE_SET(p_type->type_structure.pointer->pointee_type) )
173        {
174            /* Customized handle by referemce */
175            p_handle_info->handle_type = BE_parm_user_handle_k;
176            p_handle_info->assoc_name = assoc_handle_name;
177            CSPELL_decl_assoc_handle_vars(fid,p_handle_info);
178            NAMETABLE_id_to_string(
179                          p_type->type_structure.pointer->pointee_type->name,
180                          &(p_handle_info->type_name) );
181            NAMETABLE_id_to_string( p_first_parameter->name,
182                    &(p_handle_info->user_handle_name) );
183            p_handle_info->deref_generic = '*';
184            return;
185        }
186        if (p_type->kind == AST_handle_k)
187        {
188            /* handle_t by value */
189            if (p_type->rep_as_type != NULL)
190            {
191                p_handle_info->handle_type = BE_rep_as_handle_t_k;
192                p_handle_info->rep_as_name = p_first_parameter->name;
193                p_handle_info->rep_as_type = p_type->name;
194                p_handle_info->assoc_name = assoc_handle_ptr;
195                p_handle_info->deref_assoc = '*';
196                CSPELL_decl_assoc_handle_vars(fid,p_handle_info);
197                return;
198            }
199            p_handle_info->handle_type = BE_parm_handle_t_k;
200            NAMETABLE_id_to_string(
201                    p_first_parameter->name,
202                    &(p_handle_info->assoc_name) );
203            return;
204        }
205        if ( (p_type->kind == AST_pointer_k)
206              && (p_type->type_structure.pointer->pointee_type->kind
207                    == AST_handle_k) )
208        {
209            /* handle_t by reference */
210            if (p_type->type_structure.pointer->pointee_type->rep_as_type
211                                                                != NULL)
212            {
213                p_handle_info->handle_type = BE_rep_as_handle_t_p_k;
214                p_handle_info->rep_as_name = p_first_parameter->name;
215                p_handle_info->rep_as_type = p_type->type_structure.pointer
216                                    ->pointee_type->name;
217                p_handle_info->assoc_name = assoc_handle_ptr;
218                p_handle_info->deref_assoc = '*';
219                CSPELL_decl_assoc_handle_vars(fid,p_handle_info);
220                return;
221            }
222            p_handle_info->handle_type = BE_parm_handle_t_k;
223            NAMETABLE_id_to_string(
224                    p_first_parameter->name,
225                    &(p_handle_info->assoc_name) );
226            p_handle_info->deref_assoc = '*';
227            return;
228        }
229        if ( AST_HAS_IN_CTX_SET(p_operation) )
230        {
231            /* Operation has an [in] or [in, out] context handle */
232            p_handle_info->handle_type = BE_context_handle_k;
233            p_handle_info->assoc_name = assoc_handle_name;
234            CSPELL_decl_assoc_handle_vars(fid,p_handle_info);
235            return;
236        }
237    }
238    if (p_interface->implicit_handle_name != NAMETABLE_NIL_ID)
239    {
240        p_handle_info->assoc_name = assoc_handle_name;
241        if ( ! AST_IMPLICIT_HANDLE_G_SET(p_interface) )
242        {
243            p_handle_info->handle_type = BE_impl_handle_t_k;
244            CSPELL_decl_assoc_handle_vars(fid,p_handle_info);
245            return;
246        }
247        CSPELL_decl_assoc_handle_vars(fid,p_handle_info);
248        /* Checker ensures we must have a [handle] type here */
249        p_handle_info->handle_type = BE_impl_user_handle_k;
250        NAMETABLE_id_to_string( p_interface->implicit_handle_type_name,
251                               &(p_handle_info->type_name) );
252        NAMETABLE_id_to_string( p_interface->implicit_handle_name,
253                               &(p_handle_info->user_handle_name) );
254        return;
255    }
256    /* If we get here, must be [auto_handle] */
257    p_handle_info->handle_type = BE_auto_handle_k;
258    p_handle_info->assoc_name = assoc_handle_name;
259    p_handle_info->auto_handle_idempotent_op =
260                    ( AST_IDEMPOTENT_SET(p_operation) ) ? true : false;
261    CSPELL_decl_assoc_handle_vars(fid,p_handle_info);
262    fprintf( fid, "idl_boolean IDL_timeout_was_set_low=idl_false;\n" );
263    return;
264}
265
266/******************************************************************************/
267/*                                                                            */
268/*    Spell "duplicate implicit handle_t handle"                              */
269/*                                                                            */
270/******************************************************************************/
271static void CSPELL_dup_implicit_handle_t
272(
273    FILE *fid,
274    AST_interface_n_t *p_interface
275)
276{
277    fprintf(fid,"rpc_binding_handle_copy(");
278    spell_name(fid, p_interface->implicit_handle_name);
279    fprintf(fid, ",(rpc_binding_handle_t*)&IDL_assoc_handle");
280    fprintf(fid, ",(error_status_t*)&IDL_ms.IDL_status);\n" );
281    CSPELL_test_status(fid);
282}
283
284/******************************************************************************/
285/*                                                                            */
286/*    Spell "use a generic handle to get a binding"                           */
287/*                                                                            */
288/******************************************************************************/
289static void CSPELL_bind_generic_handle
290(
291    FILE *fid,
292    BE_handle_info_t *p_handle_info
293)
294{
295        fprintf (fid,
296                 "IDL_assoc_handle = (volatile handle_t)%s_bind(%c%s%s);\n",
297                 p_handle_info->type_name, p_handle_info->deref_generic,
298                 p_handle_info->user_handle_name,
299                                                 " ");
300}
301
302/******************************************************************************/
303/*                                                                            */
304/*    Spell "use the [auto_handle] mechanism to get a binding"                */
305/*                                                                            */
306/******************************************************************************/
307static void CSPELL_bind_auto_handle
308(
309    FILE *fid,
310    AST_operation_n_t *p_operation ATTRIBUTE_UNUSED,
311    BE_stat_info_t *p_comm_stat_info ATTRIBUTE_UNUSED,
312    BE_stat_info_t *p_fault_stat_info ATTRIBUTE_UNUSED
313)
314{
315        fprintf (fid,"rpc_ss_make_import_cursor_valid(&IDL_auto_handle_mutex,\n");
316        fprintf (fid,    "&IDL_import_cursor,\n" );
317        fprintf (fid,
318                "   (rpc_if_handle_t)&IDL_ifspec,&IDL_auto_handle_status);\n" );
319        fprintf( fid, "if(IDL_auto_handle_status!=error_status_ok)\n" );
320        fprintf( fid, "{\n" );
321        fprintf( fid, "IDL_ms.IDL_status=IDL_auto_handle_status;\n");
322        fprintf( fid, "goto IDL_auto_binding_failure;\n");
323        fprintf( fid, "}\n" );
324        fprintf (fid, "IDL_find_server:\n");
325#ifdef PERFMON
326        fprintf (fid, "#ifdef PERFMON\n");
327	fprintf (fid, "IDL_TRY_N;\n");
328	fprintf (fid, "#endif\n");
329#endif
330        fprintf (fid, "DCETHREAD_TRY\n");
331#ifdef PERFMON
332        fprintf (fid, "#ifdef PERFMON\n");
333	fprintf (fid, "IDL_TRY_X;\n");
334	fprintf (fid, "#endif\n");
335#endif
336        fprintf (fid,"rpc_ss_import_cursor_advance(&IDL_auto_handle_mutex,\n");
337        fprintf (fid,  "&IDL_timeout_was_set_low,&IDL_import_cursor,\n" );
338        fprintf (fid,
339                   "(rpc_if_handle_t)&IDL_ifspec,&IDL_error_using_binding,\n" );
340        fprintf (fid,  "&IDL_interface_binding,(rpc_binding_handle_t*)&IDL_assoc_handle,\n");
341        fprintf (fid,  "(error_status_t*)&IDL_auto_handle_status,(error_status_t*)&IDL_ms.IDL_status);\n");
342        fprintf (fid, "if(IDL_ms.IDL_status!=error_status_ok)\n");
343        fprintf (fid, "{\n");
344        fprintf (fid, "IDL_ms.IDL_restartable=idl_false;\n");
345        fprintf (fid, "goto IDL_closedown;\n");
346        fprintf (fid, "}\n");
347}
348
349/******************************************************************************/
350/*                                                                            */
351/*    Spell "prepare for and make call to rpc_call_start"                     */
352/*                                                                            */
353/******************************************************************************/
354void CSPELL_call_start
355(
356    FILE *fid,
357    BE_handle_info_t *p_handle_info,
358    AST_interface_n_t *p_interface,
359    AST_operation_n_t *p_operation,
360    unsigned long op_num,            /* Number of current operation */
361    BE_stat_info_t *p_comm_stat_info,
362    BE_stat_info_t *p_fault_stat_info
363)
364{
365    AST_parameter_n_t *p_parameter;
366    char const *parameter_name;
367    char deref_context;
368    boolean found_in_context_handle;
369
370    if (p_handle_info->handle_type == BE_impl_handle_t_k)
371    {
372        CSPELL_dup_implicit_handle_t( fid, p_interface );
373    }
374    else if ((p_handle_info->handle_type == BE_parm_user_handle_k)
375        || (p_handle_info->handle_type == BE_impl_user_handle_k))
376    {
377        CSPELL_bind_generic_handle( fid, p_handle_info );
378    }
379    else if (p_handle_info->handle_type == BE_context_handle_k)
380    {
381        fprintf (fid, "IDL_assoc_handle = NULL;\n");
382        found_in_context_handle = false;
383        for (p_parameter = p_operation->parameters;
384             p_parameter != NULL;
385             p_parameter = p_parameter->next)
386        {
387            if ( AST_CONTEXT_SET(p_parameter) && AST_IN_SET(p_parameter)
388                    && !AST_OUT_SET(p_parameter) )
389            {
390                if (( p_parameter->type->type_structure.pointer->pointee_type
391                     ->kind != AST_pointer_k )
392                   )
393                {
394                    deref_context = ' ';
395                }
396                else deref_context = '*';  /* Dereference ptr to context */
397                NAMETABLE_id_to_string (p_parameter->name, &parameter_name);
398                fprintf (fid,
399                    "if ( %c(rpc_ss_caller_context_element_t %c*)%s != NULL )\n",
400                    deref_context, deref_context, parameter_name);
401                fprintf (fid, "{\n");
402                fprintf(fid, "rpc_binding_handle_copy(");
403                fprintf(fid, "(%c(rpc_ss_caller_context_element_t %c*)",
404                        deref_context, deref_context);
405                fprintf(fid, "%s)->using_handle,\n", parameter_name);
406                fprintf(fid, "(rpc_binding_handle_t*)&IDL_assoc_handle,");
407                fprintf(fid, "(error_status_t*)&IDL_ms.IDL_status);\n");
408                CSPELL_test_status (fid);
409                fprintf (fid, "}\n");
410                found_in_context_handle = true;
411                break;
412            }
413        }
414        if ( ! found_in_context_handle )
415        {
416            for (p_parameter = p_operation->parameters;
417                 p_parameter != NULL;
418                 p_parameter = p_parameter->next)
419            {
420                if ( AST_CONTEXT_SET(p_parameter) && AST_IN_SET(p_parameter)
421                    && AST_OUT_SET(p_parameter) )
422                {
423                    if ( p_parameter->type->type_structure.pointer->pointee_type
424                         ->kind == AST_void_k ) deref_context = ' ';
425                    else deref_context = '*';  /* Dereference ptr to context */
426                    NAMETABLE_id_to_string (p_parameter->name, &parameter_name);
427                    fprintf (fid,
428                        "if ( %c(rpc_ss_caller_context_element_t %c*)%s != NULL )\n",
429                        deref_context, deref_context, parameter_name);
430                    fprintf (fid, "{\n");
431                    fprintf(fid, "rpc_binding_handle_copy(");
432                    fprintf(fid, "(%c(rpc_ss_caller_context_element_t %c*)",
433                            deref_context, deref_context);
434                    fprintf(fid, "%s)->using_handle,\n", parameter_name);
435                    fprintf(fid, "(rpc_binding_handle_t*)&IDL_assoc_handle, ");
436                    fprintf(fid, "(error_status_t*)&IDL_ms.IDL_status);\n");
437                    CSPELL_test_status (fid);
438                    fprintf (fid, "goto IDL_make_assoc;\n");
439                    fprintf (fid, "}\n");
440                }
441            }
442            fprintf (fid, "IDL_make_assoc:\n  ");
443        }
444        /* If assoc_handle remains null, raise an exception */
445        fprintf (fid, "if(IDL_assoc_handle == NULL)\n");
446        fprintf (fid, "{\n");
447        fprintf (fid, "DCETHREAD_RAISE(rpc_x_ss_in_null_context);\n");
448        fprintf (fid, "}\n");
449    }
450    else if (p_handle_info->handle_type == BE_auto_handle_k)
451    {
452        fprintf (fid, "IDL_assoc_handle = NULL;\n");
453        CSPELL_bind_auto_handle( fid, p_operation, p_comm_stat_info,
454                                      p_fault_stat_info );
455    }
456    else if (p_handle_info->handle_type == BE_rep_as_handle_t_k)
457    {
458        fprintf( fid, "%s_from_local(&%s,(handle_t **)&%s);\n",
459                    BE_get_name(p_handle_info->rep_as_type),
460                    BE_get_name(p_handle_info->rep_as_name),
461                    assoc_handle_ptr );
462    }
463    else if (p_handle_info->handle_type == BE_rep_as_handle_t_p_k)
464    {
465        fprintf( fid, "%s_from_local(%s,(handle_t **)&%s);\n",
466                    BE_get_name(p_handle_info->rep_as_type),
467                    BE_get_name(p_handle_info->rep_as_name),
468                    assoc_handle_ptr );
469    }
470
471    /* Call user [binding_callout] routine if one was specified */
472    if (p_interface->binding_callout_name != NAMETABLE_NIL_ID)
473    {
474        spell_name(fid, p_interface->binding_callout_name);
475        fprintf(fid, "((rpc_binding_handle_t *)%c%s,\n",
476                ((p_handle_info->deref_assoc == '*') ? ' ' : '&'),
477                p_handle_info->assoc_name);
478        fprintf(fid, "(rpc_if_handle_t)&IDL_ifspec, ");
479        fprintf(fid, "(error_status_t *)&IDL_ms.IDL_status);\n");
480        CSPELL_test_status(fid);
481    }
482
483    fprintf(fid, "rpc_call_start((rpc_binding_handle_t)%c%s, 0",
484                    p_handle_info->deref_assoc, p_handle_info->assoc_name);
485    if ( AST_BROADCAST_SET(p_operation) )
486    {
487        fprintf( fid, "|rpc_c_call_brdcst" );
488    }
489    if ( AST_MAYBE_SET(p_operation) )
490    {
491        fprintf( fid, "|rpc_c_call_maybe" );
492    }
493    if ( AST_IDEMPOTENT_SET(p_operation) )
494    {
495        fprintf( fid, "|rpc_c_call_idempotent" );
496    }
497    fprintf(fid,",\n (rpc_if_handle_t)&IDL_ifspec,%ld,", op_num);
498    fprintf(fid,
499"(rpc_call_handle_t*)&IDL_ms.IDL_call_h,&IDL_transfer_syntax,(unsigned32*)&IDL_ms.IDL_status);\n");
500    CSPELL_test_status (fid);
501}
502
503/******************************************************************************/
504/*                                                                            */
505/*    Spell interface-wide declarations needed for [auto_handle]              */
506/*                                                                            */
507/******************************************************************************/
508void CSPELL_auto_handle_statics
509(
510    FILE * fid
511)
512{
513    /* Declare the variables */
514    fprintf( fid,
515"static RPC_SS_THREADS_ONCE_T IDL_interface_client_once = RPC_SS_THREADS_ONCE_INIT;\n" );
516    fprintf( fid, "static RPC_SS_THREADS_MUTEX_T IDL_auto_handle_mutex;\n" );
517    fprintf( fid, "static rpc_ns_handle_t IDL_import_cursor;\n" );
518    fprintf( fid,
519              "static rpc_binding_handle_t IDL_interface_binding = NULL;\n" );
520    fprintf( fid, "static idl_boolean IDL_error_using_binding = idl_false;\n");
521    fprintf( fid,
522  "static error_status_t IDL_auto_handle_status=rpc_s_ss_no_import_cursor;\n" );
523
524    /* And a procedure that will be called once to initialize them */
525    fprintf( fid, "static void IDL_auto_handle_init()\n" );
526    fprintf( fid, "{\n" );
527    fprintf( fid,
528            "RPC_SS_THREADS_MUTEX_CREATE( &IDL_auto_handle_mutex );\n" );
529    fprintf( fid, "}\n" );
530}
531
532/******************************************************************************/
533/*                                                                            */
534/*    Spell logic for whether to restart an [auto_handle] operation           */
535/*                                                                            */
536/******************************************************************************/
537void DDBE_spell_restart_logic
538(
539    FILE * fid,
540    AST_operation_n_t *p_operation ATTRIBUTE_UNUSED
541)
542{
543#ifdef PERFMON
544        fprintf (fid, "#ifdef PERFMON\n");
545	fprintf (fid, "IDL_ENDTRY_N;\n");
546	fprintf (fid, "#endif\n");
547#endif
548    fprintf( fid, "DCETHREAD_ENDTRY\n" );
549#ifdef PERFMON
550        fprintf (fid, "#ifdef PERFMON\n");
551	fprintf (fid, "IDL_ENDTRY_X;\n");
552	fprintf (fid, "#endif\n");
553#endif
554    fprintf( fid,
555 "if ((IDL_ms.IDL_status != error_status_ok) && (IDL_ms.IDL_status != rpc_s_no_more_bindings))\n" );
556    fprintf( fid, "{\n" );
557    fprintf( fid, "if (IDL_ms.IDL_restartable)\n" );
558    fprintf( fid, "{\n" );
559    fprintf( fid, "if (IDL_ms.IDL_call_h!=NULL) rpc_call_end((rpc_call_handle_t*)&IDL_ms.IDL_call_h");
560    fprintf( fid,     ",(unsigned32*)&IDL_ms.IDL_status);\n" );
561    fprintf( fid, "IDL_ms.IDL_call_h=NULL;\n" );
562    fprintf( fid, "rpc_ss_ndr_clean_up(&IDL_ms);\n" );
563    fprintf( fid, "IDL_ms.IDL_elt_p=NULL;\n" );
564    fprintf( fid, "goto IDL_find_server;\n" );
565    fprintf( fid, "}\n" );
566    fprintf( fid,
567"else rpc_ss_flag_error_on_binding(&IDL_auto_handle_mutex,\n");
568    fprintf (fid, "   &IDL_error_using_binding,\n" );
569    fprintf (fid,
570"   &IDL_interface_binding,(rpc_binding_handle_t*)&IDL_assoc_handle);\n}\n");
571
572}
573
574/******************************************************************************/
575/*                                                                            */
576/*  If the call was made on a binding handle made by rpc_binding_handle_copy, */
577/*    emit a call to rpc_binding_free                                         */
578/*                                                                            */
579/******************************************************************************/
580void CSPELL_binding_free_if_needed
581(
582    FILE *fid,
583    BE_handle_info_t *p_handle_info
584)
585{
586    if (p_handle_info->handle_type == BE_impl_handle_t_k)
587    {
588        fprintf( fid,
589     "rpc_binding_free((rpc_binding_handle_t*)&IDL_assoc_handle,&IDL_st2);\n" );
590    }
591    else if ( (p_handle_info->handle_type == BE_auto_handle_k)
592               || (p_handle_info->handle_type == BE_context_handle_k) )
593    {
594        fprintf( fid,
595"if(IDL_assoc_handle!=NULL)rpc_binding_free((rpc_binding_handle_t*)&IDL_assoc_handle,&IDL_st2);\n" );
596    }
597}
598