Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / osf / uil / UilP2Out.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* 
24  *  @OSF_COPYRIGHT@
25  *  COPYRIGHT NOTICE
26  *  Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc.
27  *  ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for
28  *  the full copyright text.
29 */ 
30 /* 
31  * HISTORY
32 */ 
33 #ifdef REV_INFO
34 #ifndef lint
35 static char rcsid[] = "$TOG: UilP2Out.c /main/15 1997/03/12 15:17:24 dbl $"
36 #endif
37 #endif
38
39 /*
40 *  (c) Copyright 1989, 1990, DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. */
41
42 /*
43 **++
44 **  FACILITY:
45 **
46 **      User Interface Language Compiler (UIL)
47 **
48 **  ABSTRACT:
49 **
50 **      This module contain the routines for creating the UID file.
51 **
52 **--
53 **/
54
55
56 /*
57 **
58 **  INCLUDE FILES
59 **
60 **/
61
62 #ifdef DXM_V11
63 #include <DXm/DXmHelpB.h>
64 #endif
65
66 #include "UilDefI.h"
67 #include "UilSymGen.h"
68
69 /*
70 **
71 **  DEFINE and MACRO DEFINITIONS
72 **
73 **/
74
75 #ifdef WORD64
76 #define _shift 3
77 #else
78 #define _shift 2
79 #endif
80
81 #define initial_context_size 2048
82 /* alpha port note:
83    the original define makes some assumptions on the sizes of the
84    structures when calculating this value. I 'think' I have devined
85    the intent of this and have replaced it with a more generic
86    calculation.
87    */
88 #define out_k_last_offset \
89         (((src_k_max_source_line_length +1) / sizeof(sym_entry_type *)))
90
91 /* #define out_k_last_offset ((sizeof( src_source_buffer_type )>>_shift)-2) */
92
93 typedef struct  _out_queue_type
94 {
95     struct _out_queue_type  *az_prior_queue;
96     sym_entry_type          *entry[out_k_last_offset + 1];
97 } out_queue_type;
98
99
100 /*
101 **
102 **  EXTERNAL VARIABLE DECLARATIONS
103 **
104 **/
105
106 char    *_get_memory();
107 void    _free_memory();
108
109 /*
110 **
111 **  GLOBAL VARIABLE DECLARATIONS
112 **
113 **/
114
115
116 /*
117 **
118 **  OWN VARIABLE DECLARATIONS
119 **
120 **/
121
122 externaldef(uil_comp_glbl) IDBFile              out_az_idbfile_id;
123
124 static  URMResourceContext      *out_az_context;
125 static  out_queue_type          *out_az_queue;
126 static  int                     out_l_next_offset;
127 static UidCompressionTable      *extern_arg_compr;
128 static UidCompressionTable      *extern_class_compr;
129
130
131 \f
132 /*
133 **++
134 **  FUNCTIONAL DESCRIPTION:
135 **
136 **      This function begins the process of creating the UID file.  It
137 **      handles:
138 **          1) creating the UID file and closing it
139 **          2) initializing the queue of other objects to be processed
140 **          3) creating the module widget 
141 **          4) emitting exported literals and procedures
142 **          5) creating the compression code table for this UID file
143 **
144 **  FORMAL PARAMETERS:
145 **
146 **      none
147 **
148 **  IMPLICIT INPUTS:
149 **
150 **      sym_az_external_def_chain   list of exported object
151 **      src_az_avail_source_buffer  use source buffers for queue of objects
152 **                                  requiring further attention
153 **
154 **  IMPLICIT OUTPUTS:
155 **
156 **      src_az_avail_source_buffer
157 **
158 **  FUNCTION VALUE:
159 **
160 **      void
161 **
162 **  SIDE EFFECTS:
163 **
164 **      UID file is created
165 **
166 **--
167 **/
168
169 void    sem_output_uid_file()
170
171 {
172     sym_external_def_entry_type *ext_entry;
173     char                        *module_version;
174     char                        *module_name;
175     status                      urm_status;
176     sym_entry_type              *symbol_entry;
177     int                         topmost_widget_count;
178     int                         topmost_index;
179     struct
180     {   MrmOsOpenParam  os_param;
181         char            result_file[256];
182     } uid_fcb;
183
184
185     /*
186     **  No UID file is created if any error severity message has
187     **  been emitted.
188     */
189
190     if (uil_l_compile_status >= uil_k_error_status)
191     {
192         diag_issue_diagnostic( 
193             d_no_uid,
194             diag_k_no_source,
195             diag_k_no_column );
196
197         return;
198     }
199
200     /*
201     **  Request URM hold error message and report via status rather
202     **  that sending them to stdout.  This permits the compiler to
203     **  deal with the messages as it does with others.
204     */
205
206     urm_status =
207     Urm__UT_SetErrorReport( URMErrOutMemory );
208     if( urm_status != MrmSUCCESS)
209         issue_urm_error( "allocating context" );
210
211     /*
212     **  Open the UID file
213     */
214     uid_fcb.os_param.version = MrmOsOpenParamVersion;
215
216
217     /* clobber flag lets a.uid replace an existing a.uid */
218     uid_fcb.os_param.nam_flg.clobber_flg = TRUE;
219
220     module_version = "";
221     module_name = sym_az_module_entry->obj_header.az_name->c_text;
222
223     if (sym_az_module_entry->az_version != NULL)
224         module_version = sym_az_module_entry->az_version->value.c_value;
225
226     urm_status = UrmIdbOpenFileWrite
227                   ( Uil_cmd_z_command.ac_resource_file,
228                     & uid_fcb.os_param,
229                     _host_compiler,
230                     _compiler_version,
231                     module_name,
232                     module_version,
233                     &out_az_idbfile_id,
234                     uid_fcb.result_file );
235
236     if (urm_status != MrmSUCCESS)
237     {
238         diag_issue_diagnostic( 
239             d_uid_open,
240             diag_k_no_source,
241             diag_k_no_column,
242             uid_fcb.result_file );
243
244         return;
245     }
246
247
248     /*
249     **  Set the name of the file we are accessing as the current file and call
250     **  the Status callback routine to report our progress.
251     */
252     Uil_current_file =  uid_fcb.result_file;
253     if (Uil_cmd_z_command.status_cb != (Uil_continue_type(*)())NULL)
254         diag_report_status();    
255
256
257     /*
258     **  Create a context
259     */
260
261     urm_status =
262         UrmGetResourceContext ( _get_memory, _free_memory, 
263         initial_context_size, &out_az_context );
264     if( urm_status != MrmSUCCESS)
265         issue_urm_error( "allocating context" );
266
267     /*
268     **  Initialize queue of objects to be processed.
269     */
270
271     out_l_next_offset = 0;
272     out_az_queue = (out_queue_type *)src_az_avail_source_buffer;
273     out_az_queue->az_prior_queue = NULL;
274     src_az_avail_source_buffer = 
275         src_az_avail_source_buffer->az_prior_source_buffer;
276
277     /*
278     **  Count the number of topmost widgets by scanning the external list.
279     **  A topmost widget is one that is not referenced.
280     */
281
282     topmost_widget_count = 0;
283
284     for (ext_entry = sym_az_external_def_chain;  
285          ext_entry != NULL;  
286          ext_entry = ext_entry->az_next_object)
287     {
288         symbol_entry = ext_entry->az_name->az_object;
289
290         if (symbol_entry->header.b_tag == sym_k_widget_entry)
291             if ((((sym_widget_entry_type *)symbol_entry)->
292                     obj_header.az_name->b_flags & sym_m_referenced) == 0)
293                 topmost_widget_count++;
294
295     }
296
297     /*
298     **  Initialize the context to build the interface module.
299     */
300
301     urm_status =
302     UrmIFMInitModule
303         ( out_az_context, topmost_widget_count, URMaPublic, FALSE );
304     if( urm_status != MrmSUCCESS)
305         issue_urm_error( "initializing module" );
306
307     /*
308     **  Create the compression code table for use with this UID file.
309     */
310
311     create_int_compression_codes();
312
313     /* 
314     **  Exported objects are on a chain that we will now walk.
315     **  They can be of 3 types: widgets, gadgets and values.
316     **  Values, gadgets and widgets are pushed on LIFO queue and processed 
317     **  shortly.
318     **  Each widget on the list is top most if it is not referenced.  Topmost
319     **  widgets are added to the current context for the interface module.
320     */
321
322     topmost_index = 0;
323
324     for (ext_entry = sym_az_external_def_chain;  
325          ext_entry != NULL;  
326          ext_entry = ext_entry->az_next_object)
327     {
328         /*
329         **  Call the Status callback routine to report our progress.
330         */
331       /* %COMPLETE */
332       Uil_percent_complete=CEIL(
333             80+ (.20 *((float)topmost_index/(float)(topmost_widget_count+.5)))*100, 80);
334
335         if (Uil_cmd_z_command.status_cb != (Uil_continue_type(*)())NULL)
336             diag_report_status();    
337
338         symbol_entry = ext_entry->az_name->az_object;
339
340         switch (symbol_entry->header.b_tag)
341         {
342
343         case sym_k_value_entry:
344         {
345             sym_value_entry_type   *value_entry;
346
347             value_entry = (sym_value_entry_type *)symbol_entry;
348         
349             value_entry->output_state = sym_k_queued;
350
351             push( (sym_entry_type *)value_entry );
352
353             break;
354         }
355
356         case sym_k_gadget_entry:
357         case sym_k_widget_entry:
358         {
359             sym_widget_entry_type   *widget_entry;
360
361             widget_entry = (sym_widget_entry_type *)symbol_entry;
362         
363             if ((widget_entry->obj_header.az_name->b_flags & sym_m_referenced)
364                 == 0)
365             {
366                 widget_entry->output_state = sym_k_queued;
367
368                 push((sym_entry_type *) widget_entry );
369
370                 urm_status = 
371                 UrmIFMSetTopmost
372                     ( out_az_context, 
373                       topmost_index, 
374                       widget_entry->obj_header.az_name->c_text );
375                 if( urm_status != MrmSUCCESS)
376                     issue_urm_error( "adding topmost widget" );
377
378                 topmost_index++;
379             }
380
381             break;
382         }
383
384         default:
385             _assert( FALSE, "unexpected entry on external chain");
386             break;
387         }
388     }
389
390     /*
391     **  Emit the Interface Module
392     */
393
394     urm_status =
395     UrmIFMPutModule
396         ( out_az_idbfile_id, module_name, out_az_context );
397     if( urm_status != MrmSUCCESS)
398         {
399         if (urm_status == MrmEOF)
400             diag_issue_diagnostic ( d_uid_write, diag_k_no_source, 
401                                     diag_k_no_column, Uil_current_file );
402         else
403             issue_urm_error( "emitting module" );
404         }
405
406     if (Uil_cmd_z_command.v_show_machine_code) {
407         save_module_machine_code 
408             ( src_az_module_source_record, out_az_context );
409     }
410
411     /*
412     **  Start to process the widgets that have been pushed on
413     **  the queue.
414     */
415
416     for (symbol_entry = pop();  symbol_entry != NULL;  symbol_entry = pop() )
417     {
418         /*
419         **  Call the Status callback routine to report our progress.
420         */
421         if (Uil_cmd_z_command.status_cb != (Uil_continue_type(*)())NULL)
422             diag_report_status();    
423
424         switch (symbol_entry->header.b_tag)
425         {
426
427         case sym_k_value_entry:
428             out_emit_value(( sym_value_entry_type *) symbol_entry );
429             break;
430
431         case sym_k_widget_entry:
432         case sym_k_gadget_entry:
433         case sym_k_child_entry:
434             out_emit_widget(( sym_widget_entry_type *) symbol_entry );
435             break;
436
437         default:
438             _assert( FALSE, "unexpected entry popped during output");
439             break;
440         }
441     }
442
443     create_ext_compression_codes ();
444
445     /*
446     **  Close the UID file - if there are errors don't keep the file
447     */
448
449     urm_status = (uil_l_compile_status < uil_k_error_status);
450
451     if (!urm_status)
452     {
453         diag_issue_diagnostic
454             ( d_no_uid, diag_k_no_source, diag_k_no_column );
455     }
456
457     urm_status =
458     UrmIdbCloseFile( out_az_idbfile_id, urm_status );
459         out_az_idbfile_id = NULL;
460     if( urm_status != MrmSUCCESS)
461       diag_issue_diagnostic
462         ( d_uid_write, diag_k_no_source, diag_k_no_column, Uil_current_file );
463
464
465     /*
466     **  Free the context 
467     */
468
469     urm_status =
470     UrmFreeResourceContext( out_az_context );
471     if( urm_status != MrmSUCCESS)
472         issue_urm_error( "freeing context" );
473
474 }
475 \f
476 /*
477 **++
478 **  FUNCTIONAL DESCRIPTION:
479 **
480 **      This function pushes a symbol table entry into a LIFO queue.
481 **
482 **  FORMAL PARAMETERS:
483 **
484 **      sym_entry               pointer to symbol table to push
485 **
486 **  IMPLICIT INPUTS:
487 **
488 **      out_l_next_offset       next offset in current queue
489 **      out_az_queue            current queue
490 **      src_az_avail_source_buffer
491 **                              next available queue buffer
492 **
493 **  IMPLICIT OUTPUTS:
494 **
495 **      same as inputs
496 **
497 **  FUNCTION VALUE:
498 **
499 **      void
500 **
501 **  SIDE EFFECTS:
502 **
503 **      argument is placed on a queue
504 **
505 **--
506 **/
507
508 void    push(sym_entry)
509
510 sym_entry_type  *sym_entry;
511
512 {
513
514     out_queue_type  *next_queue;
515
516     /*
517     **  We reuse source buffers for the output queues.
518     */
519
520     if (out_l_next_offset > out_k_last_offset)
521     {
522         if (src_az_avail_source_buffer == NULL)
523         {
524             src_az_avail_source_buffer = 
525                 (src_source_buffer_type *)
526                     _get_memory( sizeof( src_source_buffer_type ) );
527             src_az_avail_source_buffer->az_prior_source_buffer = NULL;
528         }
529
530         next_queue = (out_queue_type *)src_az_avail_source_buffer;
531         src_az_avail_source_buffer = 
532             src_az_avail_source_buffer->az_prior_source_buffer;
533
534         next_queue->az_prior_queue = out_az_queue;
535         out_az_queue = next_queue;
536         out_l_next_offset = 0;
537     }
538
539     out_az_queue->entry[out_l_next_offset] = sym_entry;
540
541     out_l_next_offset++;
542
543 }
544 \f
545 /*
546 **++
547 **  FUNCTIONAL DESCRIPTION:
548 **
549 **      This function pops a symbol table entry from a LIFO queue.
550 **
551 **  FORMAL PARAMETERS:
552 **
553 **      none
554 **
555 **  IMPLICIT INPUTS:
556 **
557 **      out_l_next_offset       next offset in current queue
558 **      out_az_queue            current queue
559 **      src_az_avail_source_buffer
560 **                              next available queue buffer
561 **
562 **  IMPLICIT OUTPUTS:
563 **
564 **      same as inputs
565 **
566 **  FUNCTION VALUE:
567 **
568 **      sym_entry               pointer to symbol table popped
569 **      NULL                    when no more to pop
570 **
571 **  SIDE EFFECTS:
572 **
573 **      none
574 **
575 **--
576 **/
577
578 sym_entry_type  *pop()
579
580 {
581
582     src_source_buffer_type  *avail_buffer;
583
584     out_l_next_offset--;
585
586     if (out_l_next_offset < 0)
587     {
588         avail_buffer = (src_source_buffer_type *)out_az_queue;
589         out_az_queue = out_az_queue->az_prior_queue;
590         avail_buffer->az_prior_source_buffer = src_az_avail_source_buffer;
591         src_az_avail_source_buffer = avail_buffer;
592
593         if (out_az_queue == NULL)
594             return NULL;
595
596         out_l_next_offset = out_k_last_offset;
597     }
598
599     return out_az_queue->entry[out_l_next_offset];
600
601 }
602 \f
603 /*
604 **++
605 **  FUNCTIONAL DESCRIPTION:
606 **
607 **      This function builds the URM record for a widget.
608 **
609 **  FORMAL PARAMETERS:
610 **
611 **      widget_entry        symbol table pointer for a widget
612 **
613 **  IMPLICIT INPUTS:
614 **
615 **      none
616 **
617 **  IMPLICIT OUTPUTS:
618 **
619 **      none
620 **
621 **  FUNCTION VALUE:
622 **
623 **      void
624 **
625 **  SIDE EFFECTS:
626 **
627 **      write a widget record to UID file
628 **      push other objects on the queue to be processed
629 **
630 **--
631 **/
632
633 void    out_emit_widget( widget_entry )
634
635 sym_widget_entry_type   *widget_entry;
636
637 {
638
639 char                            buffer[32];
640 char                            *widget_name;
641 char                            *widget_class_name;
642 unsigned int                    widget_class;
643 unsigned long                   widget_variety;
644 int                             arg_count;
645 int                             related_arg_count;
646 int                             arglist_index;
647 sym_list_entry_type             *list_entry;
648 MrmCode                         access_code;
649 status                          urm_status;
650 MrmCode                         subtree_code;
651 sym_control_entry_type          *subtree_control;
652
653
654 _assert( (widget_entry->header.b_tag == sym_k_widget_entry) ||
655          (widget_entry->header.b_tag == sym_k_gadget_entry) ||
656          (widget_entry->header.b_tag == sym_k_child_entry),
657          "object to be emitted is not an object" );
658
659 _assert( (widget_entry->obj_header.b_flags & 
660          (sym_m_exported | sym_m_private)),
661          "object being emitted is not exported or private" );
662
663 if (widget_entry->header.b_tag == sym_k_child_entry)
664   widget_variety = UilMrmAutoChildVariety;
665 else widget_variety = UilMrmWidgetVariety;
666
667 /*
668 * Each real widget needs a name.  Automatic children just get an
669 * empty string since the name is stored in the compression tables.
670 * For real widgets, we use the user provided name
671 * if there is one; otherwise widgetfile#-line#-col# 
672 * For example, widget-1-341-111 was defined in file=1, line=341
673 * and column=11
674 */
675 if (widget_variety == UilMrmAutoChildVariety)
676   widget_name = "";
677 else if (widget_entry->obj_header.az_name == NULL)
678   {
679     sprintf(buffer, "widget-%d-%d-%d", 
680             widget_entry->header.az_src_rec->b_file_number,
681             widget_entry->header.az_src_rec->w_line_number,
682             widget_entry->header.b_src_pos);
683     widget_name = buffer;
684   }
685 else
686     widget_name = widget_entry->obj_header.az_name->c_text;
687
688 access_code = URMaPublic;
689 if (widget_entry->obj_header.b_flags & sym_m_private)
690     access_code = URMaPrivate;
691
692 urm_status = UrmCWRInit (out_az_context, widget_name, access_code, FALSE);
693 if( urm_status != MrmSUCCESS)
694     issue_urm_error( "initializing context" );
695
696     /*
697     **  Set the class of the widget. 
698     */
699
700     widget_class_name = NULL;
701
702     arg_count = 0;
703     related_arg_count = 0;
704     subtree_control = NULL;
705
706     /*
707     ** Special processing 1: User defined widgets have the class as
708     ** creation routine
709     */
710     if ( widget_entry->header.b_type == uil_sym_user_defined_object )
711         {
712         widget_class_name = 
713             widget_entry->az_create_proc->az_proc_def->obj_header.az_name->c_text;
714         }
715
716     /*
717     ** Special processing 2. Widgets which map their (single) control to
718     ** a (subtree) resource. This handles the convention (originally invented
719     ** for the pulldown menu which is the child of a cascade button) that
720     ** subtrees which must be instantiated to serve as a resource value are
721     ** treated as children rather than as widget references. Multiple
722     ** children issue a diagnostic.
723     */
724     subtree_code = uil_urm_subtree_resource[widget_entry->header.b_type];
725     if ( subtree_code != 0 )
726         {
727         int                         count;
728
729         list_entry = widget_entry->az_controls;
730         count = 0;
731         extract_subtree_control (list_entry, &subtree_control, &count);
732         switch ( count )
733             {
734             case 0:
735                 break;
736             case 1:
737                 arg_count += 1;
738                 break;
739             default:
740                 arg_count += 1;
741                 diag_issue_diagnostic
742                     (d_single_control,
743                      _sar_source_pos2(subtree_control),
744                      diag_object_text(widget_entry->header.b_type));
745                 break;
746             }
747       }
748
749
750     /*
751      * Set the class in the widget record
752      */
753     if (widget_variety == UilMrmAutoChildVariety)
754       widget_class = uil_child_compr[widget_entry->header.b_type];
755     else widget_class = uil_widget_compr[widget_entry->header.b_type];      
756
757
758     /*
759      * User defined widgets don't get compressed.  
760      */
761
762     if (widget_entry->header.b_type == uil_sym_user_defined_object)
763         widget_class = MrmwcUnknown;
764
765     urm_status =
766     UrmCWRSetClass( out_az_context, 
767                     widget_class,
768                     widget_class_name,
769                     widget_variety );
770     if( urm_status != MrmSUCCESS)
771         issue_urm_error( "setting class" );
772
773     /*
774     **  Check the callback list for the creation reason and process it.
775     **  Do this first since it affects arg_count.
776     */
777     list_entry = widget_entry->az_callbacks;
778     if (list_entry != NULL)
779         {
780         sym_callback_entry_type     *callback_entry;
781
782         arg_count += compute_list_size (list_entry, sym_k_callback_entry);
783         callback_entry = NULL;
784         extract_create_callback (list_entry, &callback_entry);
785         if ( callback_entry != NULL )
786             {
787             arglist_index = 0;
788             emit_callback (callback_entry, &arglist_index, TRUE);
789             arg_count -= 1;
790             }
791         }
792
793     /*
794     **  Output the list of arguments.  Arguments are either callbacks
795     **  or arguments.
796     */
797
798     if (widget_entry->az_arguments != NULL)
799         arg_count += compute_list_size
800             (widget_entry->az_arguments, sym_k_argument_entry);
801
802     if (arg_count > 0)
803         {
804         urm_status =
805         UrmCWRInitArglist( out_az_context, arg_count );
806         if( urm_status != MrmSUCCESS)
807             issue_urm_error( "initializing arglist" );
808         arglist_index = arg_count - 1;
809
810         /*
811         **      Process the callbacks, then the arguments
812         */
813         process_all_callbacks
814             (widget_entry->az_callbacks, &arglist_index);
815         process_all_arguments
816             (widget_entry->az_arguments, &arglist_index, &related_arg_count);
817
818         /*
819         ** Process a control which is to be entered as a subtree resource. Mark
820         ** the control so it won't be processed again.
821         */
822         if (subtree_control != NULL)
823             {
824             MrmCode         widget_access;
825             MrmCode         widget_form;
826             char            *widget_index;
827             MrmResource_id  widget_id;
828             
829             urm_status =
830             UrmCWRSetCompressedArgTag
831                 (out_az_context, arglist_index,
832                 uil_arg_compr[subtree_code], 0);
833             if( urm_status != MrmSUCCESS)
834                 issue_urm_error( "setting compressed arg" );
835
836             widget_form = 
837                 ref_control( subtree_control, 
838                             &widget_access, &widget_index, &widget_id );
839             urm_status =
840                 UrmCWRSetArgResourceRef
841                     (out_az_context,
842                      arglist_index,
843                      widget_access,
844                      URMgWidget,
845                      RGMwrTypeSubTree,
846                      widget_form,
847                      widget_index,
848                      widget_id );
849             if( urm_status != MrmSUCCESS)
850                 issue_urm_error( "setting arg reference" );
851             subtree_control->header.b_tag = sym_k_error_entry;
852
853             arglist_index++;
854             
855             }
856         }
857
858     /*
859     **  Process controls
860     */
861
862     list_entry = widget_entry->az_controls;
863
864     if (list_entry != NULL)
865         {
866         int                         widget_index;
867
868         /*
869         **  The list of controls is in reverse order.  To correct for
870         **  this, controls are placed in the list from bottom to top.
871         **  Thus widget_index represent the last slot in the list used.
872         */
873
874         widget_index = compute_list_size (list_entry, sym_k_control_entry);
875         if (widget_index > 0)
876             {
877             urm_status =
878                 UrmCWRInitChildren (out_az_context, widget_index );
879             if ( urm_status != MrmSUCCESS)
880                 issue_urm_error( "initializing children" );
881             process_all_controls (list_entry, &widget_index);
882             }
883         }
884
885     /*
886     **  If we have any related arguments, report the number.
887     */
888
889     if (related_arg_count > 0)
890         UrmCWRSetExtraArgs( out_az_context, related_arg_count );
891
892     /*
893     **  Emit the widget record to UID file
894     **  All widgets are indexed as long as they are named.  This is so
895     **  they can be included in module interface structure.
896     */
897
898     if (widget_entry->obj_header.az_name == NULL)
899         {
900         if (widget_entry->resource_id == 0 )
901             {
902             urm_status =
903             UrmIdbGetResourceId
904                 ( out_az_idbfile_id, &(widget_entry->resource_id) );
905             if( urm_status != MrmSUCCESS)
906                 issue_urm_error( "obtaining resource id" );
907             }
908
909         urm_status =
910             UrmPutRIDWidget
911             (out_az_idbfile_id,
912              widget_entry->resource_id,
913              out_az_context );
914         }
915     else
916         urm_status =
917             UrmPutIndexedWidget
918             (out_az_idbfile_id,
919              widget_name,
920              out_az_context );
921
922     if( urm_status != MrmSUCCESS)
923         {
924         if (urm_status == MrmEOF)
925             diag_issue_diagnostic ( d_uid_write, diag_k_no_source, 
926                                     diag_k_no_column, Uil_current_file );
927         else
928             issue_urm_error( "emitting widget" );
929         }
930
931     if (Uil_cmd_z_command.v_show_machine_code)
932         {
933         save_widget_machine_code (widget_entry, out_az_context);
934         }
935
936     widget_entry->output_state = sym_k_emitted;
937     }
938
939
940 \f
941 /*
942 **++
943 **  FUNCTIONAL DESCRIPTION:
944 **
945 **      This routine extracts the controlled widget (top-level) from
946 **      a controls list for subtree resources (those whose subtree must
947 **      be instantiated as part of parent creation, but which are
948 **      implemented as resources, not children). It returns the count of
949 **      the number of such entries found, and a pointer to the last one
950 **      encountered.
951 **
952 **  FORMAL PARAMETERS:
953 **
954 **      list_entry              the list to be (recursively) searched
955 **      menu_entry              to return a ponter to the pulldown menu
956 **      count                   counts the number of entries found
957 **
958 **  IMPLICIT INPUTS:
959 **
960 **  IMPLICIT OUTPUTS:
961 **
962 **  FUNCTION VALUE:
963 **
964 **      void
965 **
966 **  SIDE EFFECTS:
967 **
968 **--
969 **/
970
971 void extract_subtree_control (list_entry, menu_entry, count)
972     sym_list_entry_type         *list_entry;
973     sym_control_entry_type      **menu_entry;
974     int                         *count;
975     
976 {
977
978 /*
979  * Local variables
980  */
981 sym_obj_entry_type              *list_member;
982 sym_nested_list_entry_type      *nested_list_entry;
983 sym_control_entry_type          *control_entry;
984
985
986 /*
987  * Process the list elements, recursing on nested lists. Ignore error entries.
988  */
989 if ( list_entry == NULL ) return;
990 for (list_member=(sym_obj_entry_type *)list_entry->obj_header.az_next;
991      list_member!=NULL;
992      list_member=(sym_obj_entry_type *)list_member->obj_header.az_next)
993     switch ( list_member->header.b_tag )
994         {
995         case sym_k_nested_list_entry:
996             nested_list_entry = (sym_nested_list_entry_type *) list_member;
997             extract_subtree_control
998                 (nested_list_entry->az_list, menu_entry, count);
999             break;
1000         case sym_k_control_entry:
1001             control_entry = (sym_control_entry_type *) list_member;
1002             *count += 1;
1003             *menu_entry = control_entry;
1004             
1005         }
1006
1007 }
1008
1009
1010 \f
1011 /*
1012 **++
1013 **  FUNCTIONAL DESCRIPTION:
1014 **
1015 **      This routine searches a callbacks list (and any nested lists)
1016 **      for the create callback.
1017 **
1018 **  FORMAL PARAMETERS:
1019 **
1020 **      list_entry              the list to be (recursively) searched
1021 **      create_entry            to return a pointer to the create entry
1022 **
1023 **  IMPLICIT INPUTS:
1024 **
1025 **  IMPLICIT OUTPUTS:
1026 **
1027 **  FUNCTION VALUE:
1028 **
1029 **      void
1030 **
1031 **  SIDE EFFECTS:
1032 **
1033 **--
1034 **/
1035
1036 void extract_create_callback (list_entry, create_entry)
1037     sym_list_entry_type         *list_entry;
1038     sym_callback_entry_type     **create_entry;
1039     
1040 {
1041
1042 /*
1043  * Local variables
1044  */
1045 sym_obj_entry_type              *list_member;
1046 sym_nested_list_entry_type      *nested_list_entry;
1047 sym_callback_entry_type         *callback_entry;
1048 sym_value_entry_type            *value_entry;
1049 key_keytable_entry_type         *key_entry;
1050
1051
1052 /*
1053  * Process the list elements, recursing on nested lists. Ignore error entries.
1054  */
1055 if ( list_entry == NULL ) return;
1056 for (list_member=(sym_obj_entry_type *)list_entry->obj_header.az_next;
1057      list_member!=NULL;
1058      list_member=(sym_obj_entry_type *)list_member->obj_header.az_next)
1059     switch ( list_member->header.b_tag )
1060         {
1061         case sym_k_nested_list_entry:
1062             nested_list_entry = (sym_nested_list_entry_type *) list_member;
1063             extract_create_callback
1064                 (nested_list_entry->az_list, create_entry);
1065             break;
1066         case sym_k_callback_entry:
1067             callback_entry = (sym_callback_entry_type *) list_member;
1068             value_entry = callback_entry->az_call_reason_name;
1069             if (value_entry->obj_header.b_flags & sym_m_builtin)
1070                 {
1071                 key_entry = 
1072                     (key_keytable_entry_type *)value_entry->value.l_integer;
1073                 if ( strcmp(uil_reason_toolkit_names[key_entry->b_subclass],
1074                             MrmNcreateCallback) == 0 )
1075                     {
1076                     *create_entry = callback_entry;
1077                     return;
1078                     }
1079                 }
1080             break;
1081         }
1082
1083 }
1084
1085
1086 \f
1087 /*
1088 **++
1089 **  FUNCTIONAL DESCRIPTION:
1090 **
1091 **      This routine processes all valid callbacks in an callbacks list,
1092 **      recursing on nested lists. Each valid callback is emitted to
1093 **      the output.
1094 **
1095 **  FORMAL PARAMETERS:
1096 **
1097 **      list_entry              the list to be (recursively) processed
1098 **      arglist_index           the modifiable index of arguments in the
1099 **                              output argslist.
1100 **
1101 **  IMPLICIT INPUTS:
1102 **
1103 **  IMPLICIT OUTPUTS:
1104 **
1105 **  FUNCTION VALUE:
1106 **
1107 **      void
1108 **
1109 **  SIDE EFFECTS:
1110 **
1111 **--
1112 **/
1113
1114 void process_all_callbacks (list_entry, arglist_index)
1115     sym_list_entry_type         *list_entry;
1116     int                         *arglist_index;
1117     
1118 {
1119
1120 /*
1121  * Local variables
1122  */
1123 sym_obj_entry_type              *list_member;
1124 sym_nested_list_entry_type      *nested_list_entry;
1125 sym_callback_entry_type         *callback_entry;
1126
1127
1128 /*
1129  * Process the list elements, recursing on nested lists. Ignore error entries.
1130  */
1131 if ( list_entry == NULL ) return;
1132 for (list_member=(sym_obj_entry_type *)list_entry->obj_header.az_next;
1133      list_member!=NULL;
1134      list_member=(sym_obj_entry_type *)list_member->obj_header.az_next)
1135     switch ( list_member->header.b_tag )
1136         {
1137         case sym_k_nested_list_entry:
1138             nested_list_entry = (sym_nested_list_entry_type *) list_member;
1139             process_all_callbacks (nested_list_entry->az_list, arglist_index);
1140             break;
1141         case sym_k_callback_entry:
1142             callback_entry = (sym_callback_entry_type *) list_member;
1143             emit_callback (callback_entry, arglist_index, FALSE);
1144             break;
1145         case sym_k_error_entry:
1146             break;
1147         default:
1148             _assert (FALSE, "unknown entry in callback list");
1149             break;
1150         }
1151
1152 }
1153
1154
1155 \f
1156 /*
1157 **++
1158 **  FUNCTIONAL DESCRIPTION:
1159 **
1160 **      This routine processes all valid arguments in an arguments list,
1161 **      recursing on nested lists. Each valid argument is emitted to
1162 **      the output.
1163 **
1164 **  FORMAL PARAMETERS:
1165 **
1166 **      list_entry              the list to be (recursively) processed
1167 **      arglist_index           the modifiable index of arguments in the
1168 **                              output argslist.
1169 **      related_count           the modifiable count of related args
1170 **
1171 **  IMPLICIT INPUTS:
1172 **
1173 **  IMPLICIT OUTPUTS:
1174 **
1175 **  FUNCTION VALUE:
1176 **
1177 **      void
1178 **
1179 **  SIDE EFFECTS:
1180 **
1181 **--
1182 **/
1183
1184 void process_all_arguments (list_entry, arglist_index, related_count)
1185     sym_list_entry_type         *list_entry;
1186     int                         *arglist_index;
1187     int                         *related_count;
1188     
1189 {
1190
1191 /*
1192  * Local variables
1193  */
1194 sym_obj_entry_type              *list_member;
1195 sym_nested_list_entry_type      *nested_list_entry;
1196 sym_argument_entry_type         *argument_entry;
1197
1198
1199 /*
1200  * Process the list elements, recursing on nested lists. Ignore error entries.
1201  */
1202 if ( list_entry == NULL ) return;
1203 for (list_member=(sym_obj_entry_type *)list_entry->obj_header.az_next;
1204      list_member!=NULL;
1205      list_member=(sym_obj_entry_type *)list_member->obj_header.az_next)
1206     switch ( list_member->header.b_tag )
1207         {
1208         case sym_k_nested_list_entry:
1209             nested_list_entry = (sym_nested_list_entry_type *) list_member;
1210             process_all_arguments
1211                 (nested_list_entry->az_list, arglist_index, related_count);
1212             break;
1213         case sym_k_argument_entry:
1214             argument_entry = (sym_argument_entry_type *) list_member;
1215             emit_argument (argument_entry, *arglist_index, related_count);
1216             *arglist_index -= 1;
1217             break;
1218         case sym_k_error_entry:
1219             break;
1220         default:
1221             _assert (FALSE, "unknown entry in argument list");
1222             break;
1223         }
1224
1225 }
1226
1227
1228 \f
1229 /*
1230 **++
1231 **  FUNCTIONAL DESCRIPTION:
1232 **
1233 **      This routine processes all valid controls in an controls list,
1234 **      recursing on nested lists. Each valid control is emitted to
1235 **      the output.
1236 **
1237 **  FORMAL PARAMETERS:
1238 **
1239 **      list_entry              the list to be (recursively) processed
1240 **      widget_index            the modifiable index of children
1241 **
1242 **  IMPLICIT INPUTS:
1243 **
1244 **  IMPLICIT OUTPUTS:
1245 **
1246 **  FUNCTION VALUE:
1247 **
1248 **      void
1249 **
1250 **  SIDE EFFECTS:
1251 **
1252 **--
1253 **/
1254
1255 void process_all_controls (list_entry, widget_index)
1256     sym_list_entry_type         *list_entry;
1257     int                         *widget_index;
1258     
1259 {
1260
1261 /*
1262  * Local variables
1263  */
1264 sym_obj_entry_type              *list_member;
1265 sym_nested_list_entry_type      *nested_list_entry;
1266 sym_control_entry_type          *control_entry;
1267
1268
1269 /*
1270  * Process the list elements, recursing on nested lists. Ignore error entries.
1271  */
1272 if ( list_entry == NULL ) return;
1273 for (list_member=(sym_obj_entry_type *)list_entry->obj_header.az_next;
1274      list_member!=NULL;
1275      list_member=(sym_obj_entry_type *)list_member->obj_header.az_next)
1276     switch ( list_member->header.b_tag )
1277         {
1278         case sym_k_nested_list_entry:
1279             nested_list_entry = (sym_nested_list_entry_type *) list_member;
1280             process_all_controls (nested_list_entry->az_list, widget_index);
1281             break;
1282         case sym_k_control_entry:
1283             control_entry = (sym_control_entry_type *) list_member;
1284             *widget_index -= 1;
1285             emit_control (control_entry, *widget_index);
1286             break;
1287         case sym_k_error_entry:
1288             break;
1289         default:
1290             _assert (FALSE, "unknown entry in control list");
1291             break;
1292         }
1293
1294 }
1295
1296
1297 \f
1298 /*
1299 **++
1300 **  FUNCTIONAL DESCRIPTION:
1301 **
1302 **      This function builds the URM record for a value.
1303 **
1304 **  FORMAL PARAMETERS:
1305 **
1306 **      value_entry         symbol table pointer for a value
1307 **
1308 **  IMPLICIT INPUTS:
1309 **
1310 **      none
1311 **
1312 **  IMPLICIT OUTPUTS:
1313 **
1314 **      none
1315 **
1316 **  FUNCTION VALUE:
1317 **
1318 **      void
1319 **
1320 **  SIDE EFFECTS:
1321 **
1322 **      write a value record to UID file
1323 **
1324 **--
1325 **/
1326
1327 void    out_emit_value( value_entry )
1328
1329 sym_value_entry_type    *value_entry;
1330
1331 {
1332     MrmCode         access;
1333     int             value_size;
1334     MrmType         value_type;
1335     int             value_count;    
1336     char            *buffer;
1337     status          urm_status;
1338     XmString        tmp_str;
1339     
1340     _assert( value_entry->header.b_tag == sym_k_value_entry,
1341              "object to be emitted is not a value" );
1342
1343     _assert( (value_entry->obj_header.b_flags & (sym_m_exported | sym_m_private)),
1344              "value being emitted is not exported or private" );
1345
1346     access = URMaPublic;
1347
1348     if (value_entry->obj_header.b_flags & sym_m_private)
1349     {
1350         if (value_entry->resource_id == 0 )
1351         {
1352             urm_status =
1353             UrmIdbGetResourceId
1354                 ( out_az_idbfile_id, &(value_entry->resource_id) );
1355             if( urm_status != MrmSUCCESS)
1356                 issue_urm_error( "obtaining resource id" );
1357         }
1358
1359         access = URMaPrivate;
1360     }
1361
1362     /* 
1363     **  Case on the type of literal.
1364     */
1365
1366     value_type = Urm_code_from_uil_type( value_entry->b_type );
1367     switch (value_entry->b_type)
1368         {
1369         case sym_k_bool_value:
1370         case sym_k_integer_value:
1371             _assert(access == URMaPublic, 
1372                     "private value should not get resource ids");
1373             value_size = sizeof(long);
1374             break;
1375
1376         case sym_k_horizontal_integer_value:
1377         case sym_k_vertical_integer_value:
1378             value_size = sizeof(RGMUnitsInteger);
1379             break;
1380
1381         case sym_k_float_value:
1382             _assert(access == URMaPublic, 
1383                     "private floats should not get resource ids");
1384             value_size = sizeof (double);
1385             break;
1386
1387         case sym_k_horizontal_float_value:
1388         case sym_k_vertical_float_value:
1389             value_size = sizeof(RGMUnitsFloat);
1390             break;
1391
1392         case sym_k_single_float_value:
1393             _assert(access == URMaPublic,
1394                     "private single floats should not get resource ids");
1395             value_size = sizeof(float);
1396             break;
1397
1398         case sym_k_compound_string_value:
1399             tmp_str = value_entry->value.xms_value;
1400             value_size = 
1401               XmCvtXmStringToByteStream(tmp_str, 
1402                                 (unsigned char **)&(value_entry->value.c_value));
1403             XmStringFree(tmp_str);
1404             break;
1405
1406         case sym_k_font_value:
1407         case sym_k_fontset_value:
1408             {
1409             /*
1410              * Size is FontItem plus size of charset name string and
1411              * size of font name string.
1412              */
1413              value_size = sizeof(RGMFontItem)
1414                + strlen(sem_charset_name(value_entry->b_charset,
1415                                          value_entry->az_charset_value)) 
1416                  + 1 + strlen(value_entry->value.c_value) + 1;
1417             break;
1418             }
1419         case sym_k_color_value:
1420             /* null on end of color name accounted for in RGMColorDesc */
1421             value_size = sizeof( RGMColorDesc ) + value_entry->w_length;
1422             break;
1423
1424         case sym_k_rgb_value:
1425             {
1426             sym_value_entry_type    *value_segment;
1427
1428             value_size = sizeof( RGMIntegerVector );
1429             value_count = 0;
1430             for (value_segment = value_entry->az_first_table_value;
1431                  value_segment != NULL;
1432                  value_segment =  value_segment->az_next_table_value)
1433                 {
1434                 value_size += sizeof(long);
1435                 value_count++;
1436                 }
1437             break;
1438             }
1439
1440         case sym_k_color_table_value:
1441             value_size = compute_color_table_size( value_entry );
1442             break;
1443
1444         case sym_k_icon_value:
1445             value_size = compute_icon_size( value_entry );
1446             break;
1447
1448         case sym_k_char_8_value:
1449         case sym_k_reason_value:
1450         case sym_k_argument_value:
1451         case sym_k_class_rec_name_value:
1452         case sym_k_xbitmapfile_value:
1453         case sym_k_keysym_value:
1454         case sym_k_localized_string_value:
1455             /* BEGIN OSF Fix CR 4859 */
1456 /* END OSF Fix CR 4859 */
1457             value_size = value_entry->w_length + 1;  /* +1 for the null */
1458             break;
1459
1460 /* BEGIN OSF Fix CR 4859 */
1461         case sym_k_wchar_string_value:
1462             value_size = sizeof(RGMWCharEntry) +
1463               value_entry->az_first_table_value->w_length;  
1464             break;
1465 /* END OSF Fix CR 4859 */
1466         case sym_k_identifier_value:
1467             value_size = value_entry->w_length;  /* includes the null */
1468             break;
1469
1470         case sym_k_string_table_value:
1471             {
1472             sym_value_entry_type        *value_segment;
1473             
1474             /* value_size accounts for header and null at end of the index */
1475             value_size = sizeof( RGMTextVector ); 
1476             value_count = 0;
1477
1478             /* 
1479              **  Determine the size of the string table by adding together
1480              **  the lengths of component strings.  Before the string is a
1481              **  table of words.  The first word is the number of component
1482              **  string.  Next comes the word offsets of each of the strings
1483              **  from the start of the buffer.
1484              */
1485             for (value_segment=value_entry->az_first_table_value;
1486                  value_segment != NULL;  
1487                  value_segment = value_segment->az_next_table_value)
1488                 {
1489                 value_count++;
1490
1491                 value_size += 
1492                   XmCvtXmStringToByteStream(value_segment->value.xms_value, NULL) +
1493                     sizeof( RGMTextEntry );
1494                 }
1495             break;
1496             }
1497
1498
1499         case sym_k_asciz_table_value:
1500             {
1501             sym_value_entry_type        *value_segment;
1502
1503             /* value_size accounts for header and null at end of the index */
1504             value_size = sizeof( RGMTextVector ); 
1505             value_count = 0;
1506
1507             /* 
1508              **  Determine the size of the string table by adding together
1509              **  the lengths of component strings.  Before the string is a
1510              **  table of words.  The first word is the number of component
1511              **  string.  Next comes the word offsets of each of the strings
1512              **  from the start of the buffer.
1513              */
1514
1515             for (value_segment=value_entry->az_first_table_value;
1516                  value_segment != NULL;  
1517                  value_segment = value_segment->az_next_table_value)
1518                 {
1519                 value_count++;
1520                 value_size +=
1521                     value_segment->w_length + sizeof(RGMTextEntry) + 1;
1522                 }
1523             break;
1524             }
1525
1526         case sym_k_integer_table_value:
1527             {
1528             sym_value_entry_type        *value_segment;
1529             
1530             /*
1531              **  The size needed for the vector is the size of the header
1532              **  information followed by the the list of integers.  Add in
1533              **  the header size here.
1534              */
1535             value_size = sizeof( RGMIntegerVector ); 
1536             value_count = 0;
1537
1538             /* 
1539              **  Determine the size of the integer table by adding together
1540              **  the lengths of component integers to the header.
1541              */
1542
1543             for (value_segment = value_entry->az_first_table_value;  
1544                  value_segment != NULL;  
1545                  value_segment = value_segment->az_next_table_value)
1546                 {
1547                 value_size += sizeof(long);
1548                 value_count++;
1549                 }
1550             break;
1551             }
1552
1553
1554         case sym_k_font_table_value:
1555             {
1556             sym_value_entry_type        *font_value;
1557
1558             /*
1559              * Size is size of basic table, plus strings for all FontItems.
1560              * We allocate one fewer FontItems than specified in the structure
1561              * definition.
1562              */
1563             /* value_size accounts for header and null at end of the index */
1564             value_size = sizeof(RGMFontList) - sizeof(RGMFontItem); 
1565             value_count = 0;
1566             
1567             /* 
1568              **  Determine the size of the font list by adding together
1569              **  the lengths of component fonts.  Each component is a FontItem
1570              **  in the list, plus space for the charset name and font name.
1571              */
1572             for (font_value = value_entry->az_first_table_value;  
1573                  font_value != NULL;  
1574                  font_value = font_value->az_next_table_value)
1575                 {
1576                 /* Fix for CR 5266 Part 2a -- Pull az_charset_value off of
1577                  *                    font_value, rather than value_entry.
1578                  */
1579                 value_count += 1;
1580                 value_size += sizeof(RGMFontItem)
1581                     + strlen(sem_charset_name(font_value->b_charset,
1582                                               font_value->az_charset_value))
1583                       + 1 + strlen(font_value->value.c_value) + 1;
1584                 }
1585             break;
1586             }
1587
1588         case sym_k_trans_table_value:
1589             {
1590             sym_value_entry_type        *value_segment;
1591             
1592             value_size = 0;
1593
1594             /*
1595              **  Determine the length of the translation table by adding
1596              **  together the length of the component strings.
1597              */
1598             for (value_segment = value_entry->az_first_table_value;  
1599                  value_segment != NULL;  
1600                  value_segment = value_segment->az_next_table_value)
1601                 value_size += value_segment->w_length + 1;
1602             break;
1603             }
1604         
1605         default:
1606             _assert( FALSE, "unexpected value type" );
1607         }
1608
1609     /*
1610     **  Check that the context is large enough to hold the value
1611     */
1612
1613     if ((int)(UrmRCSize( out_az_context ) ) < value_size)
1614         {
1615         if( MrmSUCCESS != 
1616            UrmResizeResourceContext( out_az_context, value_size ))
1617             issue_urm_error( "allocating context" );
1618         urm_status = UrmResizeResourceContext( out_az_context, value_size );
1619         if ( urm_status != MrmSUCCESS)
1620             {
1621             if (urm_status == MrmTOO_MANY)
1622                 {
1623                 diag_issue_diagnostic
1624                     ( d_value_too_large,
1625                      (src_source_record_type *)value_entry->header.az_src_rec,
1626                      diag_k_no_column,
1627                      value_entry->obj_header.az_name->c_text );
1628                 }
1629             else
1630                 issue_urm_error( "allocating context" );
1631             }
1632         }
1633     
1634     
1635     /*
1636     **  Move the literal to the context.
1637     */
1638
1639     UrmRCSetGroup( out_az_context, URMgLiteral );
1640     UrmRCSetType( out_az_context, value_type );
1641     UrmRCSetAccess( out_az_context, access );
1642     UrmRCSetLock( out_az_context, FALSE );
1643     UrmRCSetSize( out_az_context, value_size );
1644
1645     buffer = (char *) UrmRCBuffer( out_az_context );
1646
1647     bzero( buffer, value_size );
1648
1649     switch (value_entry->b_type)
1650         {
1651         case sym_k_bool_value:
1652         case sym_k_integer_value:
1653         case sym_k_float_value:
1654         case sym_k_reason_value:
1655         case sym_k_argument_value:
1656             _move( buffer, &value_entry->value.l_integer, value_size );
1657             break;
1658
1659         case sym_k_single_float_value:
1660             _move( buffer, &value_entry->value.single_float, value_size);
1661             break;
1662
1663         case sym_k_char_8_value:
1664         case sym_k_localized_string_value:
1665         case sym_k_identifier_value:
1666         case sym_k_class_rec_name_value:
1667         case sym_k_xbitmapfile_value:
1668         case sym_k_keysym_value:
1669         case sym_k_compound_string_value:
1670             _move( buffer, value_entry->value.c_value, value_size );
1671             break;
1672
1673 /* BEGIN OSF Fix CR 4859 */
1674         case sym_k_wchar_string_value:
1675           {
1676             RGMWCharEntryPtr  wcharentry;
1677             
1678             wcharentry = (RGMWCharEntryPtr)buffer;
1679             
1680             wcharentry->wchar_item.count = value_size;
1681             
1682             _move(wcharentry->wchar_item.bytes,
1683                   value_entry->az_first_table_value->value.c_value, value_size);
1684             break;
1685           }
1686 /* END OSF Fix CR 4859 */
1687           
1688         case sym_k_font_value:
1689         case sym_k_fontset_value:
1690             {
1691             RGMFontItemPtr      fontitem;
1692             MrmOffset           textoffs;
1693             char                *textptr;
1694             char                *charset_name;
1695             int                 text_len;
1696             
1697             fontitem = (RGMFontItemPtr) buffer;
1698             textoffs = (MrmOffset) sizeof(RGMFontItem);
1699             textptr = (char *)fontitem+textoffs;
1700             
1701             charset_name = sem_charset_name (value_entry->b_charset, 
1702                                              value_entry->az_charset_value);
1703             text_len = strlen(charset_name) + 1;
1704
1705             fontitem->type = Urm_code_from_uil_type(value_entry->b_type);
1706             fontitem->cset.cs_offs = textoffs;
1707             strcpy (textptr, charset_name);
1708             textoffs += text_len;
1709             textptr += text_len;
1710             fontitem->font.font_offs = textoffs;
1711             strcpy (textptr, value_entry->value.c_value);
1712             
1713             break;
1714             }
1715
1716         case sym_k_color_value:
1717             {
1718             RGMColorDesc        *color_buffer;
1719             
1720             color_buffer = (RGMColorDesc *)buffer;
1721             
1722             switch (value_entry->b_arg_type)
1723                 {
1724                 case sym_k_unspecified_color:
1725                     color_buffer->mono_state = URMColorMonochromeUnspecified;
1726                     break;
1727                 case sym_k_foreground_color:
1728                     color_buffer->mono_state = URMColorMonochromeForeground;
1729                     break;
1730                 case sym_k_background_color:
1731                     color_buffer->mono_state = URMColorMonochromeBackground;
1732                     break;
1733                 }
1734
1735             color_buffer->desc_type = URMColorDescTypeName;
1736
1737             _move( color_buffer->desc.name, 
1738                   value_entry->value.c_value, 
1739                   value_entry->w_length + 1 );
1740             
1741             break;
1742             }
1743
1744         case sym_k_rgb_value:
1745             {
1746             sym_value_entry_type        *value_segment;
1747             RGMColorDesc                *color_buffer;
1748             int                         color_vector[3];
1749             int                         index;
1750
1751             color_buffer = (RGMColorDesc *)buffer;
1752             index = value_count;
1753             
1754             index--;
1755             for (value_segment=value_entry->az_first_table_value;
1756                  value_segment != NULL;
1757                  value_segment = value_segment->az_next_table_value)
1758                 {
1759                 color_vector[index] = (long) value_segment->value.l_integer;
1760                 index--;
1761                 }
1762             
1763             color_buffer->desc_type = URMColorDescTypeRGB;
1764             color_buffer->desc.rgb.red = color_vector[0];
1765             color_buffer->desc.rgb.green = color_vector[1];
1766             color_buffer->desc.rgb.blue = color_vector[2];
1767             color_buffer->mono_state = URMColorMonochromeUnspecified;
1768
1769             break;
1770             }
1771
1772
1773         case sym_k_color_table_value:
1774             create_color_table( value_entry, buffer );
1775             break;
1776
1777         case sym_k_icon_value:
1778             create_icon( value_entry, buffer );
1779             break;
1780
1781         case sym_k_string_table_value:
1782             {
1783             sym_value_entry_type        *value_segment;
1784             int                         text_offset;
1785             int                         index;
1786             int                         segment_size;
1787             RGMTextVector               *string_vector;
1788             
1789             /*
1790              **  Value entries are reversed.  Need to fill the buffer
1791              **  from the end to front.
1792              */
1793             text_offset = value_size;
1794             string_vector = (RGMTextVector *)buffer;
1795             string_vector->validation = URMTextVectorValid;
1796             string_vector->count = value_count;
1797             index = value_count;
1798             string_vector->item[index].pointer = NULL;
1799             
1800             for (value_segment=value_entry->az_first_table_value;
1801                  value_segment != NULL;  
1802                  value_segment = value_segment->az_next_table_value)
1803                 {
1804                   tmp_str = value_segment->value.xms_value;
1805                   segment_size = 
1806                     XmCvtXmStringToByteStream(tmp_str, 
1807                                       (unsigned char **)&(value_segment->value.c_value));
1808                   XmStringFree(tmp_str);
1809                   text_offset -= segment_size;
1810                   _move(&(buffer[text_offset]), 
1811                         value_segment->value.c_value, segment_size);
1812                   index--;
1813                   string_vector->item[index].text_item.offset = text_offset;
1814                   string_vector->item[index].text_item.rep_type =
1815                     MrmRtypeCString;
1816                 }
1817             break;
1818             }
1819
1820         case sym_k_asciz_table_value:
1821             {
1822             sym_value_entry_type        *value_segment;
1823             int                         text_offset;
1824             int                         index;
1825             int                         segment_size;
1826             RGMTextVector               *string_vector;
1827             
1828             /*
1829              **  Value entries are reversed.  Need to fill the buffer
1830              **  from the end to front.
1831              */
1832             text_offset = value_size;
1833             string_vector = (RGMTextVector *)buffer;
1834             string_vector->validation = URMTextVectorValid;
1835             string_vector->count = value_count;
1836             index = value_count;
1837             string_vector->item[index].pointer = NULL;
1838
1839             for (value_segment=value_entry->az_first_table_value;
1840                  value_segment != NULL;  
1841                  value_segment = value_segment->az_next_table_value)
1842                 {
1843                 segment_size = value_segment->w_length + 1;
1844                 buffer[text_offset-1] = '\0';
1845                 text_offset -= segment_size;
1846                 _move( &(buffer[text_offset]), 
1847                       value_segment->value.c_value, segment_size - 1);
1848                 index--;
1849                 string_vector->item[index].text_item.offset = text_offset;
1850                 string_vector->item[index].text_item.rep_type = MrmRtypeChar8;
1851                 }
1852             break;
1853             }
1854
1855         case sym_k_integer_table_value:
1856             {
1857             sym_value_entry_type        *value_segment;
1858             int                         index;
1859             RGMIntegerVector            *integer_vector;
1860
1861             /*
1862              **  Fill in the header information
1863              */
1864             integer_vector = (RGMIntegerVector *)buffer;
1865             integer_vector->validation = URMIntegerVectorValid;
1866             integer_vector->count = value_count;
1867
1868             /*
1869              **  Value entries are reversed.  Need to fill the buffer
1870              **  from the end to front.
1871              */
1872             index = value_count - 1;
1873             for (value_segment=value_entry->az_first_table_value;
1874                  value_segment != NULL;  
1875                  value_segment = value_segment->az_next_table_value)
1876                 {
1877                 integer_vector->item [index] =
1878                     (long) value_segment->value.l_integer;
1879                 index--;
1880                 }
1881             break;
1882             }
1883
1884         case sym_k_font_table_value:
1885             {
1886             RGMFontListPtr              fontlist;
1887             RGMFontItemPtr              fontitem;
1888             sym_value_entry_type        *font_value;
1889             int                         textoffs;
1890             char                        *textptr;
1891             int                         index;
1892             char                        *charset_name;
1893             int                         text_len;
1894             
1895             /*
1896              **  Font items are in correct order.
1897              */
1898             fontlist = (RGMFontList *)buffer;
1899             fontlist->validation = URMFontListValid;
1900             fontlist->count = value_count;
1901
1902             /*
1903              **  textoffs need to be the offset just beyond the last
1904              **  FontItem in the list. One FontItem is already allocated,
1905              **  so account for it in sizing.
1906              */
1907             textoffs = sizeof (RGMFontList) +
1908                 sizeof(RGMFontItem)*(value_count-1);
1909             textptr = (char *)fontlist+textoffs;
1910             
1911             for (index = 0,
1912                  font_value = value_entry->az_first_table_value;  
1913                  font_value != NULL;  
1914                  index++, font_value = font_value->az_next_table_value)
1915                 {
1916                 fontitem = &fontlist->item[index];
1917                 /*
1918                  * Fix for CR 5266 Part 2b -- Pull az_charset_value off of
1919                  *                    font_value, rather than value_entry.
1920                  */
1921                 charset_name = 
1922                   sem_charset_name (font_value->b_charset, 
1923                                     font_value->az_charset_value);
1924
1925                 fontitem->type = Urm_code_from_uil_type(font_value->b_type);
1926                 fontitem->cset.cs_offs = textoffs;
1927                 strcpy (textptr, charset_name);
1928                 text_len = strlen(charset_name) + 1;
1929                 textoffs += text_len;
1930                 textptr += text_len;
1931                 fontitem->font.font_offs = textoffs;
1932                 strcpy (textptr, font_value->value.c_value);
1933                 text_len = strlen(font_value->value.c_value) + 1;
1934                 textoffs += text_len;
1935                 textptr += text_len;
1936                 }
1937             break;
1938             }
1939
1940         case sym_k_trans_table_value:
1941             {
1942             sym_value_entry_type        *value_segment;
1943             int                         offset;
1944             int                         segment_size;
1945             
1946             /*
1947              **  Value entries are reversed.  Need to fill the buffer
1948              **  from the end to front.
1949              */
1950
1951             offset = value_size;
1952             for (value_segment = value_entry->az_first_table_value;  
1953                  value_segment != NULL;  
1954                  value_segment = value_segment->az_next_table_value)
1955                 {
1956                 buffer[offset - 1] = '\n';
1957                 segment_size = value_segment->w_length + 1;
1958                 offset -= segment_size;
1959                 _move( &(buffer[offset]), 
1960                       value_segment->value.c_value, segment_size-1 );
1961                 }
1962             buffer[value_size - 1] = 0;
1963             break;
1964             }
1965
1966         case sym_k_horizontal_integer_value:
1967         case sym_k_vertical_integer_value:
1968             {
1969             RGMUnitsIntegerPtr uiptr;
1970
1971             uiptr = (RGMUnitsIntegerPtr) buffer;
1972             uiptr->value = value_entry->value.l_integer;
1973             uiptr->units = value_entry->b_arg_type;
1974             break;
1975             }
1976
1977         case sym_k_horizontal_float_value:
1978         case sym_k_vertical_float_value:
1979             {
1980             RGMUnitsFloatPtr ufptr;
1981
1982             ufptr = (RGMUnitsFloatPtr) buffer;
1983             *((double *)(&ufptr->value[0])) = value_entry->value.d_real;
1984             ufptr->units = value_entry->b_arg_type;
1985             break;
1986             }
1987         }
1988
1989     /*
1990     **  Output the literal
1991     */
1992     if (access == URMaPublic)
1993         urm_status = UrmPutIndexedLiteral
1994             (out_az_idbfile_id,
1995              value_entry->obj_header.az_name->c_text,
1996              out_az_context);
1997     else
1998         urm_status = UrmPutRIDLiteral
1999             (out_az_idbfile_id, value_entry->resource_id, out_az_context);
2000
2001     if( urm_status != MrmSUCCESS)
2002         {
2003         if (urm_status == MrmEOF)
2004             diag_issue_diagnostic ( d_uid_write, diag_k_no_source, 
2005                                     diag_k_no_column, Uil_current_file );
2006         else
2007             issue_urm_error( "emitting literal" );
2008         }
2009     
2010     if (Uil_cmd_z_command.v_show_machine_code)
2011         save_value_machine_code (value_entry, out_az_context);
2012     
2013     value_entry->output_state = sym_k_emitted;
2014     
2015     }
2016
2017 \f
2018 /*
2019 **++
2020 **  FUNCTIONAL DESCRIPTION:
2021 **
2022 **      This function builds the callback argument for a widget record
2023 **
2024 **  FORMAL PARAMETERS:
2025 **
2026 **      callback_entry      symbol table pointer for the callback
2027 **      arglist_index       index in arglist to place callback
2028 **                          (this is an in/out argument)
2029 **      emit_create         true: emit a create reason
2030 **                          false: skip create reason
2031 **
2032 **  IMPLICIT INPUTS:
2033 **
2034 **      none
2035 **
2036 **  IMPLICIT OUTPUTS:
2037 **
2038 **      none
2039 **
2040 **  FUNCTION VALUE:
2041 **
2042 **      void
2043 **
2044 **  SIDE EFFECTS:
2045 **
2046 **      callback data is added to out_az_context
2047 **
2048 **--
2049 **/
2050
2051 void    emit_callback
2052
2053         (sym_callback_entry_type *callback_entry,
2054         int *arglist_index,
2055         boolean emit_create)
2056
2057 {
2058 sym_value_entry_type            *reason_entry;
2059 sym_proc_ref_entry_type         *proc_ref_entry_next;
2060 int                             proc_ref_index;
2061 int                             proc_count;
2062 boolean                         qcreate = FALSE;
2063 MrmOffset                       callback_offset;
2064 status                          urm_status;
2065
2066 /*
2067  * Count number of entries in callback list
2068  */
2069 if ( callback_entry->az_call_proc_ref != 0 )
2070     proc_count = 1;
2071 else
2072     proc_count = count_proc (callback_entry->az_call_proc_ref_list, 0);
2073
2074 /*
2075 ** Reasons can take several forms:
2076 **    1) create reason: value is builtin - keyword Urm value is "created"
2077 **      this need special handling
2078 **    2) builtin reasons: value is builtin - keyword Urm value as URM
2079 **      compressed equivalent argument
2080 **    3) non-builtin private: value is not builtin but private -
2081 **      use an uncompressed argument tag
2082 **    4) non-builtin public: value is not builtin and public -
2083 **      not supported yet
2084 */
2085
2086 reason_entry = callback_entry->az_call_reason_name;
2087 if ( reason_entry->obj_header.b_flags & sym_m_builtin )
2088     {
2089     key_keytable_entry_type *key_entry;
2090     
2091     key_entry = (key_keytable_entry_type *) reason_entry->value.l_integer;
2092     qcreate =
2093         (strcmp(uil_reason_toolkit_names[key_entry->b_subclass],
2094                 MrmNcreateCallback) == 0);
2095     if ( qcreate )
2096         {
2097         /*
2098          **     case 1: create reason - return if we are not to emit
2099          **     otherwise use special routine to describe
2100          */
2101         if ( !emit_create ) return;
2102         urm_status = UrmCWRSetCreationCallback
2103             (out_az_context,
2104              proc_count,
2105              &callback_offset);
2106         if( urm_status != MrmSUCCESS)
2107             {
2108             if (urm_status == MrmEOF)
2109                 diag_issue_diagnostic ( d_uid_write, diag_k_no_source, 
2110                                         diag_k_no_column, Uil_current_file );
2111             else
2112                 issue_urm_error ("emitting creation callback");
2113             }
2114
2115         }
2116     else
2117         {
2118         /*
2119          **     case 2: builtin case - use a compressed argument
2120          */
2121         urm_status = UrmCWRSetCompressedArgTag
2122             (out_az_context,
2123              *arglist_index,
2124              uil_reas_compr[key_entry->b_subclass],
2125              0);        
2126             if( urm_status != MrmSUCCESS)
2127                 issue_urm_error( "setting compressed arg" );
2128         }
2129     }
2130 else
2131     {
2132     /*
2133      **  Non private reasons and arguments are not supported
2134      */
2135     if ( reason_entry->obj_header.b_flags & (sym_m_imported|sym_m_exported) )
2136         {
2137         diag_issue_diagnostic
2138             (d_not_impl, diag_k_no_source, diag_k_no_column,
2139              "EXPORTED and IMPORTED arguments and reasons" );
2140         return;
2141         }
2142     
2143     /*
2144      **  case 3: private, non-builtin case - use an uncompressed argument
2145      */
2146     urm_status = UrmCWRSetUncompressedArgTag
2147         (out_az_context,
2148          *arglist_index,
2149          reason_entry->value.c_value);
2150     if( urm_status != MrmSUCCESS)
2151         issue_urm_error( "setting uncompressed arg" );
2152     }
2153
2154 /*
2155  * Create the callback value (this is not done for the create callback)
2156  */
2157 if ( ! qcreate )
2158     {
2159     urm_status = UrmCWRSetArgCallback
2160         (out_az_context, *arglist_index, proc_count, &callback_offset);
2161     if( urm_status != MrmSUCCESS)
2162         issue_urm_error ("setting callback arg");
2163     }
2164
2165 /*
2166  * Create the callback procedures
2167  */
2168 if (callback_entry->az_call_proc_ref != 0)
2169     {
2170     proc_ref_index = 0;
2171     proc_ref_entry_next = callback_entry->az_call_proc_ref;
2172     }
2173 else
2174     {
2175     proc_ref_index = proc_count - 1;
2176     proc_ref_entry_next = 
2177         (sym_proc_ref_entry_type *) callback_entry->
2178             az_call_proc_ref_list->obj_header.az_next;
2179     }
2180 emit_callback_procedures
2181     (proc_ref_entry_next, &proc_ref_index, callback_offset);
2182 *arglist_index = *arglist_index - 1;
2183
2184 }
2185
2186 \f
2187 /*
2188 **++
2189 **  FUNCTIONAL DESCRIPTION:
2190 **
2191 **      This function counts the number of procedures in a procedure list
2192 **      including nested procedure lists.
2193 **
2194 **  FORMAL PARAMETERS:
2195 **
2196 **      proc_list           list of procedures (and nested list entries)
2197 **      count               count of procedures encountered so far
2198 **
2199 **  IMPLICIT INPUTS:
2200 **
2201 **      none
2202 **
2203 **  IMPLICIT OUTPUTS:
2204 **
2205 **      none
2206 **
2207 **  FUNCTION VALUE:
2208 **
2209 **      count of procedures in procedure list
2210 **
2211 **  SIDE EFFECTS:
2212 **
2213 **      none
2214 **
2215 **--
2216 **/
2217
2218 int     count_proc(proc_list, count)
2219 sym_list_entry_type     *proc_list;
2220 int                     count;
2221
2222 {
2223     sym_obj_entry_type          *proc_list_next;
2224
2225     for (proc_list_next = (sym_obj_entry_type *)proc_list->obj_header.az_next;
2226                             proc_list_next != 0;
2227                             proc_list_next = (sym_obj_entry_type *)
2228                                 proc_list_next->obj_header.az_next)
2229         {
2230         switch (proc_list_next->header.b_tag)
2231             {
2232             case sym_k_nested_list_entry:
2233                 count = count_proc(((sym_nested_list_entry_type *)
2234                         proc_list_next)->
2235                         az_list, 
2236                         count);
2237                 break;
2238             case sym_k_proc_ref_entry:
2239                 count++;
2240                 break;
2241             default:
2242                 _assert(FALSE, "unknown entry in procedures list");
2243             }
2244         }
2245         return (count);
2246 }
2247
2248 \f
2249 /*
2250 **++
2251 **  FUNCTIONAL DESCRIPTION:
2252 **
2253 **      This function output a procedure list referenced by a callback entry
2254 **
2255 **  FORMAL PARAMETERS:
2256 **
2257 **      proc_ref_entry_next next procedure reference entry
2258 **      proc_ref_index      index of procedure in procedure list (for Mrm)
2259 **      callback_offset     offset of callback (for Mrm)
2260 **
2261 **  IMPLICIT INPUTS:
2262 **
2263 **      none
2264 **
2265 **  IMPLICIT OUTPUTS:
2266 **
2267 **      none
2268 **
2269 **  FUNCTION VALUE:
2270 **
2271 **      void
2272 **
2273 **  SIDE EFFECTS:
2274 **
2275 **      none
2276 **
2277 **--
2278 **/
2279
2280 /*
2281  * Fix for CR 4772 - Change the proc_ref_index entry from an integer to an 
2282  *                   integer pointer to allow for proper construction of 
2283  *                   internal callback arrays.
2284  */
2285 void    emit_callback_procedures
2286
2287         (sym_proc_ref_entry_type *proc_ref_entry_next,
2288         int *proc_ref_index,
2289         MrmOffset callback_offset)
2290
2291 {
2292     sym_proc_def_entry_type *proc_def_entry;
2293     sym_value_entry_type    *proc_arg_entry;
2294     MrmCode                 arg_access;
2295     MrmCode                 arg_form;
2296     char                    *arg_index;
2297     MrmResource_id          arg_id;
2298     MrmCode                 arg_type, arg_group;
2299     long                    arg_value;
2300     sym_nested_list_entry_type  *nested_proc_list_entry;
2301     sym_list_entry_type     *proc_list_entry;
2302     status                  urm_status;
2303
2304     for (
2305         ;
2306         proc_ref_entry_next != 0;
2307         proc_ref_entry_next = 
2308             (sym_proc_ref_entry_type *) proc_ref_entry_next->
2309             obj_header.az_next)
2310
2311         {
2312         switch (proc_ref_entry_next->header.b_tag)
2313             {
2314             case sym_k_nested_list_entry:
2315                 nested_proc_list_entry = (sym_nested_list_entry_type *)
2316                     proc_ref_entry_next;
2317                 proc_list_entry = nested_proc_list_entry->az_list;
2318                 emit_callback_procedures (( sym_proc_ref_entry_type *)proc_list_entry->obj_header.az_next, 
2319                     proc_ref_index,             
2320                     callback_offset);
2321                 break;
2322             case sym_k_proc_ref_entry:
2323                 proc_def_entry = proc_ref_entry_next->az_proc_def;
2324                 proc_arg_entry = proc_ref_entry_next->az_arg_value;
2325
2326                 if (proc_arg_entry == NULL)
2327                     {
2328                         arg_type = MrmRtypeNull;
2329                         arg_value = 0L;
2330                         arg_form = URMrImmediate;
2331                     }
2332                 else
2333                     {
2334                         arg_form = ref_value
2335                                     ( proc_arg_entry, 
2336                                       &arg_type, &arg_value, &arg_access, &arg_index,
2337                                       &arg_id, &arg_group );
2338                     }
2339     
2340                 if (arg_form == URMrImmediate)
2341                     urm_status =
2342                 UrmCWRSetCallbackItem
2343                     ( out_az_context, callback_offset, *proc_ref_index,
2344                       proc_def_entry->obj_header.az_name->c_text,
2345                       arg_type,
2346                       arg_value );
2347                 else
2348                     urm_status =
2349                 UrmCWRSetCallbackItemRes
2350                     ( out_az_context, callback_offset, *proc_ref_index,
2351                       proc_def_entry->obj_header.az_name->c_text,
2352                       arg_group,
2353                       arg_access,
2354                       arg_type,
2355                       arg_form,
2356                       arg_index,
2357                       arg_id );
2358     
2359                 if( urm_status != MrmSUCCESS)
2360                     issue_urm_error( "setting callback proc" );
2361                 *proc_ref_index = *proc_ref_index - 1;
2362                 break;
2363
2364             case sym_k_error_entry:
2365                 break;
2366             default:
2367                 _assert (FALSE, "unknown entry in procedures list");
2368                 break;
2369             }
2370         }
2371 }
2372 \f
2373 /*
2374 **++
2375 **  FUNCTIONAL DESCRIPTION:
2376 **
2377 **      This function builds an argument for a widget record
2378 **
2379 **  FORMAL PARAMETERS:
2380 **
2381 **      argument_entry      symbol table pointer for the argument
2382 **      arglist_index       index in arglist to place argument
2383 **
2384 **  IMPLICIT INPUTS:
2385 **
2386 **      none
2387 **
2388 **  IMPLICIT OUTPUTS:
2389 **
2390 **      none
2391 **
2392 **  FUNCTION VALUE:
2393 **
2394 **      void
2395 **
2396 **  SIDE EFFECTS:
2397 **
2398 **      argument data is added to out_az_context
2399 **
2400 **--
2401 **/
2402
2403 void    emit_argument( argument_entry, arglist_index, related_arg_count )
2404
2405 sym_argument_entry_type *argument_entry;
2406 int                     arglist_index;
2407 int                     *related_arg_count;
2408
2409 {
2410 sym_value_entry_type            *arg_name_entry;
2411 sym_value_entry_type            *arg_value_entry;
2412 MrmCode                         arg_access;
2413 MrmCode                         arg_form;
2414 char                            *arg_index;
2415 MrmResource_id                  arg_id;
2416 MrmCode                         arg_type, arg_group;
2417 long                            arg_value;
2418 unsigned char                   expected_type;
2419 status                          urm_status;
2420
2421
2422 /*
2423  *      For an argument, we must:
2424  *          1) create the argument 
2425  *          2) create the argument value
2426  */
2427
2428 arg_name_entry = argument_entry->az_arg_name;
2429 if (arg_name_entry->obj_header.b_flags & sym_m_builtin)
2430     {
2431     key_keytable_entry_type *key_entry;
2432     
2433     key_entry = (key_keytable_entry_type *)arg_name_entry->value.l_integer;
2434     
2435     urm_status = UrmCWRSetCompressedArgTag
2436         (out_az_context,
2437          arglist_index,
2438          uil_arg_compr[key_entry->b_subclass],
2439          uil_arg_compr[related_argument_table[key_entry->b_subclass]]); 
2440     if ( related_argument_table[key_entry->b_subclass] != 0 )
2441         *related_arg_count += 1;
2442     if( urm_status != MrmSUCCESS)
2443         issue_urm_error( "setting compressed arg" );
2444     }
2445 else
2446     {
2447     /*
2448      **  Non private reasons and arguments are not supported
2449      */
2450     
2451     if ( arg_name_entry->obj_header.b_flags & (sym_m_imported|sym_m_exported) )
2452         {
2453         diag_issue_diagnostic
2454             (d_not_impl, diag_k_no_source, diag_k_no_column,
2455              "EXPORTED and IMPORTED arguments and reasons" );
2456             return;
2457         }
2458
2459     /*
2460      **  case 3: private, non-builtin case - use an uncompressed argument
2461      */
2462         urm_status = UrmCWRSetUncompressedArgTag
2463             (out_az_context,
2464              arglist_index,
2465              arg_name_entry->value.c_value);
2466     if( urm_status != MrmSUCCESS)
2467         issue_urm_error( "setting uncompressed arg" );
2468     }
2469
2470 /*
2471  * Acquire the argument parameters. If it is an immediate value, set it.
2472  * Else set it up as a literal or widget reference. For literal references,
2473  * the expected type must be set up in order to enable coercion in Mrm.
2474  */
2475 arg_value_entry = argument_entry->az_arg_value;
2476 arg_form = ref_value
2477     (arg_value_entry,
2478      &arg_type,
2479      &arg_value,
2480      &arg_access,
2481      &arg_index,
2482      &arg_id,
2483      &arg_group);
2484 if (arg_form == URMrImmediate)
2485     urm_status = UrmCWRSetArgValue
2486         (out_az_context,
2487          arglist_index,
2488          arg_type,
2489          arg_value );
2490 else
2491     {
2492     switch ( arg_group )
2493         {
2494         case URMgLiteral:
2495             if ( argument_entry->az_arg_name->obj_header.b_flags &
2496                 sym_m_builtin )
2497                 {
2498                 key_keytable_entry_type         * keytable_entry;
2499             
2500                 keytable_entry = (key_keytable_entry_type *)
2501                     argument_entry->az_arg_name->value.l_integer;
2502                 _assert (keytable_entry->b_class == tkn_k_class_argument,
2503                          "name is not an argument");
2504                 expected_type =
2505                     argument_type_table[keytable_entry->b_subclass];
2506                 }
2507             else
2508                 expected_type = argument_entry->az_arg_name->b_arg_type;
2509             urm_status = UrmCWRSetArgResourceRef
2510                 (out_az_context,
2511                  arglist_index,
2512                  arg_access,
2513                  arg_group,
2514                  Urm_code_from_uil_type(expected_type),
2515                  arg_form,
2516                  arg_index,
2517                  arg_id );
2518             break;
2519         case URMgWidget:
2520             urm_status = UrmCWRSetArgResourceRef
2521                 (out_az_context,
2522                  arglist_index,
2523                  arg_access,
2524                  arg_group,
2525                  RGMwrTypeReference,
2526                  arg_form,
2527                  arg_index,
2528                  arg_id );
2529             break;
2530         }
2531     }
2532     
2533 if( urm_status != MrmSUCCESS)
2534     issue_urm_error ("setting arg value");
2535
2536 }
2537 \f
2538 /*
2539 **++
2540 **  FUNCTIONAL DESCRIPTION:
2541 **
2542 **      This function builds a control for a widget record
2543 **
2544 **  FORMAL PARAMETERS:
2545 **
2546 **      control_entry       symbol table pointer for the control
2547 **      control_offset      offset of object in the control list
2548 **
2549 **  IMPLICIT INPUTS:
2550 **
2551 **      none
2552 **
2553 **  IMPLICIT OUTPUTS:
2554 **
2555 **      none
2556 **
2557 **  FUNCTION VALUE:
2558 **
2559 **      void
2560 **
2561 **  SIDE EFFECTS:
2562 **
2563 **      control data is added to out_az_context
2564 **
2565 **--
2566 **/
2567
2568 void    emit_control( control_entry, control_offset )
2569
2570 sym_control_entry_type  *control_entry;
2571 int                     control_offset;
2572
2573 {
2574     MrmCode                 access;
2575     MrmCode                 form;
2576     char                    *index;
2577     MrmResource_id          id;
2578     status                  urm_status;
2579     sym_widget_entry_type   *widget_entry;
2580     Boolean                 managed;
2581
2582     /*
2583     **  1) Process the object reference
2584     **  2) set object as a child of current context
2585     */
2586
2587     form = ref_control( control_entry, &access, &index, &id );
2588
2589     /* Truly gross hack.  Fix in WML before beta */
2590 #ifndef sym_k_XmRenderTable_object
2591 #define sym_k_XmRenderTable_object 0
2592 #endif
2593 #ifndef sym_k_XmRendition_object
2594 #define sym_k_XmRendition_object 0
2595 #endif
2596 #ifndef sym_k_XmTabList_object
2597 #define sym_k_XmTabList_object 0
2598 #endif
2599     widget_entry = control_entry->az_con_obj;
2600
2601     while (widget_entry->obj_header.az_reference != NULL)
2602       widget_entry = 
2603         (sym_widget_entry_type *)widget_entry->obj_header.az_reference;
2604
2605     managed = ((widget_entry->header.b_type != sym_k_XmRenderTable_object) &&
2606                (widget_entry->header.b_type != sym_k_XmRendition_object) &&
2607                (widget_entry->header.b_type != sym_k_XmTabList_object) &&
2608                ((control_entry->obj_header.b_flags & sym_m_managed) != 0));
2609     
2610     /*
2611     **  Add the object as a child.
2612     */
2613
2614     urm_status =
2615     UrmCWRSetChild
2616         ( out_az_context,
2617           control_offset,
2618           managed,
2619           access,
2620           form,
2621           index,
2622           id );
2623     
2624     if( urm_status != MrmSUCCESS)
2625         issue_urm_error( "setting child" );
2626
2627 }
2628 \f
2629 /*
2630 **++
2631 **  FUNCTIONAL DESCRIPTION:
2632 **
2633 **      This function process a reference to a value.
2634 **
2635 **  FORMAL PARAMETERS:
2636 **
2637 **      arg_value_entry     (in)  value entry to process
2638 **      arg_type            (out) URM argument type
2639 **      arg_value           (out) argument value if immediate
2640 **      arg_access          (out) private or public
2641 **      arg_index           (out) index if value is an index
2642 **      arg_id              (out) resource id if value is a resource id
2643 **      arg_group           (out) URM group (widget or literal)
2644 **
2645 **  IMPLICIT INPUTS:
2646 **
2647 **      none
2648 **
2649 **  IMPLICIT OUTPUTS:
2650 **
2651 **      none
2652 **
2653 **  FUNCTION VALUE:
2654 **
2655 **      URMrIndex, URMrRID, URMrImmediate (class of value)
2656 **      defines which of the output parameters have meaning
2657 **
2658 **  SIDE EFFECTS:
2659 **
2660 **      none
2661 **
2662 **--
2663 **/
2664
2665 MrmCode ref_value(value_entry, 
2666                   arg_type, arg_value, arg_access, arg_index, arg_id, arg_group)
2667
2668 sym_value_entry_type    *value_entry;
2669 MrmCode                 *arg_type;
2670 long                    *arg_value;
2671 MrmCode                 *arg_access;
2672 char                    **arg_index;
2673 MrmResource_id          *arg_id;
2674 MrmCode                 *arg_group;
2675
2676 {
2677
2678     status      urm_status;
2679
2680     *arg_value = 0L;
2681     *arg_index = NULL;
2682     *arg_id = 0;
2683     *arg_group = URMgLiteral;
2684
2685     /*  This value may actually be a widget reference, so check for this
2686         case first.    */
2687
2688     if (value_entry->header.b_tag == sym_k_widget_entry)
2689         {
2690         
2691         /*  Set up a dummy control entry, and process the widget reference.  */
2692
2693         sym_control_entry_type  control_entry;
2694         sym_widget_entry_type   * widget_entry;
2695         
2696         widget_entry = (sym_widget_entry_type *)value_entry;
2697         control_entry.header.b_tag = sym_k_control_entry;
2698         control_entry.az_con_obj = widget_entry;
2699         
2700         *arg_group = URMgWidget;
2701         *arg_type = RGMwrTypeReference;
2702         
2703         return ref_control (&control_entry, arg_access, arg_index, arg_id);
2704         }
2705
2706     *arg_type = Urm_code_from_uil_type( value_entry->b_type );
2707
2708     if (value_entry->obj_header.b_flags & sym_m_private)
2709         {
2710         *arg_access = URMaPrivate;
2711
2712         switch (value_entry->b_type)
2713             {
2714             case sym_k_bool_value:
2715             case sym_k_integer_value:
2716                 *arg_value = value_entry->value.l_integer;
2717                 return URMrImmediate;
2718
2719             case sym_k_float_value:
2720                 *arg_value = (long)(&(value_entry->value.d_real));
2721                 return URMrImmediate;
2722
2723             case sym_k_single_float_value:
2724                 *arg_value = (long)(value_entry->value.single_float);
2725                 return URMrImmediate;
2726
2727             case sym_k_char_8_value:
2728             case sym_k_font_value:
2729             case sym_k_fontset_value:
2730             case sym_k_color_value:
2731             case sym_k_reason_value:
2732             case sym_k_argument_value:
2733             case sym_k_trans_table_value:
2734             case sym_k_asciz_table_value:
2735             case sym_k_integer_table_value:
2736             case sym_k_string_table_value:
2737             case sym_k_color_table_value:
2738             case sym_k_icon_value:
2739             case sym_k_font_table_value:
2740             case sym_k_compound_string_value:
2741             case sym_k_identifier_value:
2742             case sym_k_class_rec_name_value:
2743             case sym_k_xbitmapfile_value:
2744             case sym_k_keysym_value:
2745             case sym_k_rgb_value:
2746             case sym_k_wchar_string_value:
2747             case sym_k_localized_string_value:
2748             case sym_k_horizontal_integer_value:
2749             case sym_k_vertical_integer_value:
2750             case sym_k_horizontal_float_value:
2751             case sym_k_vertical_float_value:
2752                 if (value_entry->resource_id == 0 )
2753                     {
2754                     urm_status =
2755                         UrmIdbGetResourceId
2756                             (out_az_idbfile_id, &(value_entry->resource_id) );
2757                     if ( urm_status != MrmSUCCESS )
2758                         issue_urm_error( "obtaining resource id" );
2759                     }
2760
2761                 if (value_entry->output_state == sym_k_not_processed)
2762                     {
2763                     value_entry->output_state = sym_k_queued;
2764                     push((sym_entry_type *) value_entry );
2765                     }
2766                 
2767                 *arg_id = value_entry->resource_id;
2768                 return URMrRID;
2769                 
2770             default:
2771                 _assert( FALSE, "unexpected value type" );
2772                 return URMrImmediate;
2773             }
2774         
2775         }
2776
2777     /*
2778     **  Only Imported and Exported Values reach this point
2779     */
2780
2781     *arg_access = URMaPublic;
2782     *arg_index = (char *)(value_entry->obj_header.az_name->c_text);
2783
2784     if ((value_entry->obj_header.b_flags & sym_m_exported) &&
2785         (value_entry->output_state == sym_k_not_processed))
2786         {
2787         value_entry->output_state = sym_k_queued;
2788         push((sym_entry_type *) value_entry );
2789         }
2790
2791     return URMrIndex;
2792
2793 }
2794 \f
2795 /*
2796 **++
2797 **  FUNCTIONAL DESCRIPTION:
2798 **
2799 **      This function process a reference to a control (widget or gadget)
2800 **
2801 **  FORMAL PARAMETERS:
2802 **
2803 **      control_entry       (in)  control entry for widget reference
2804 **      access              (out) private or public
2805 **      index               (out) index if widget is an index
2806 **      id                  (out) resource id if widget is a resource id
2807 **
2808 **  IMPLICIT INPUTS:
2809 **
2810 **      none
2811 **
2812 **  IMPLICIT OUTPUTS:
2813 **
2814 **      none
2815 **
2816 **  FUNCTION VALUE:
2817 **
2818 **      URMrIndex, URMrRID (class of control)
2819 **      defines which of the output parameters have meaning
2820 **
2821 **  SIDE EFFECTS:
2822 **
2823 **      none
2824 **
2825 **--
2826 **/
2827
2828 MrmCode ref_control(control_entry, access, index, id)
2829
2830 sym_control_entry_type  *control_entry;
2831 MrmCode                 *access;
2832 char                    **index;
2833 MrmResource_id          *id;
2834
2835 {
2836
2837     sym_widget_entry_type   *widget_entry;
2838     MrmCode                 form;
2839     status                  urm_status;
2840
2841     _assert( control_entry->header.b_tag == sym_k_control_entry,
2842              "expecting a control entry" );
2843
2844     /*
2845     **  For a control, we must:
2846     **      1) determine if this is a definition or a reference
2847     **      2) queue the widget to be created if it isn't yet
2848     **      3) get a resource id for the control if unnamed
2849     */
2850
2851     widget_entry = control_entry->az_con_obj;
2852
2853     /*
2854     **  If the reference field is set, this is a reference to a control
2855     **  defined elsewhere.  Otherwise it is an inline definition.
2856     */
2857
2858     while (widget_entry->obj_header.az_reference != NULL)
2859         widget_entry = 
2860             (sym_widget_entry_type *)widget_entry->obj_header.az_reference;
2861
2862     /*
2863     **  Queue the control to be processed if it has not already been
2864     **  emitted or queued for processing.
2865     */
2866
2867     if ((widget_entry->obj_header.b_flags & (sym_m_exported | sym_m_private))
2868         && 
2869         (widget_entry->output_state == sym_k_not_processed)
2870        )
2871     {
2872         widget_entry->output_state = sym_k_queued;
2873
2874         push((sym_entry_type *) widget_entry );
2875     }
2876
2877     if (widget_entry->obj_header.az_name == NULL)
2878     {
2879         /*
2880         **  Need a resource id.
2881         */
2882
2883         if (widget_entry->resource_id == 0 )
2884         {
2885             urm_status =
2886             UrmIdbGetResourceId
2887                 ( out_az_idbfile_id, &(widget_entry->resource_id) );
2888             if( urm_status != MrmSUCCESS)
2889                 issue_urm_error( "obtaining resource id" );
2890         }
2891
2892         form = URMrRID;
2893         *id = widget_entry->resource_id;
2894         *index = NULL;
2895     }
2896     else
2897     {
2898         /*
2899         **  Need an index
2900         */
2901
2902         form = URMrIndex;
2903         *index = widget_entry->obj_header.az_name->c_text;
2904         *id = 0 ;
2905     }
2906
2907     *access = URMaPublic;
2908
2909     if (widget_entry->obj_header.b_flags & sym_m_private)
2910         *access = URMaPrivate;
2911
2912     return form;
2913
2914 }
2915
2916 \f
2917 /*
2918 **++
2919 **  FUNCTIONAL DESCRIPTION:
2920 **
2921 **      This function issue a diagnostic for an error detected by URM.
2922 **
2923 **  FORMAL PARAMETERS:
2924 **
2925 **      problem         string indicating what p2_output was trying to do
2926 **
2927 **  IMPLICIT INPUTS:
2928 **
2929 **      out_az_context  context in error (hold further info about error)
2930 **
2931 **  IMPLICIT OUTPUTS:
2932 **
2933 **      none
2934 **
2935 **  FUNCTION VALUE:
2936 **
2937 **      void
2938 **
2939 **  SIDE EFFECTS:
2940 **
2941 **      diagnostic is issued - compilation stops
2942 **
2943 **--
2944 **/
2945
2946 void    issue_urm_error( problem )
2947
2948 char    *problem;
2949
2950 {
2951     char    buffer[132];
2952
2953     sprintf(buffer, "while %s encountered %s", 
2954             problem, 
2955             Urm__UT_LatestErrorMessage());
2956
2957     diag_issue_internal_error( buffer );
2958 }
2959 \f
2960 /*
2961  *++
2962  *
2963  *  PROCEDURE DESCRIPTION:
2964  *
2965  *      This procedure maps uil literal type to Urm equivalent types
2966  *
2967  *  FORMAL PARAMETERS:
2968  *
2969  *      uil_type         uil types sym_k_..._value
2970  *
2971  *  IMPLICIT INPUTS:
2972  *
2973  *      none
2974  *
2975  *  IMPLICIT OUTPUTS:
2976  *
2977  *      none
2978  *
2979  *  FUNCTION VALUE:
2980  *
2981  *      corresponding RGMrType... code
2982  *
2983  *  SIDE EFFECTS:
2984  *
2985  *      none
2986  *
2987  *--
2988  */
2989
2990 MrmCode Urm_code_from_uil_type( uil_type )
2991
2992 int     uil_type;
2993
2994 {
2995
2996     switch (uil_type)
2997     {
2998     case sym_k_integer_value:               return MrmRtypeInteger;
2999     case sym_k_horizontal_integer_value:    return MrmRtypeHorizontalInteger;
3000     case sym_k_vertical_integer_value:      return MrmRtypeVerticalInteger;
3001     case sym_k_bool_value:                  return MrmRtypeBoolean;
3002     case sym_k_char_8_value:                return MrmRtypeChar8;
3003     case sym_k_localized_string_value:      return MrmRtypeChar8;
3004     case sym_k_argument_value:              return MrmRtypeChar8;
3005     case sym_k_reason_value:                return MrmRtypeChar8;
3006     case sym_k_trans_table_value:           return MrmRtypeTransTable;
3007     case sym_k_asciz_table_value:           return MrmRtypeChar8Vector;
3008     case sym_k_string_table_value:          return MrmRtypeCStringVector;
3009     case sym_k_compound_string_value:       return MrmRtypeCString;
3010     case sym_k_wchar_string_value:          return MrmRtypeWideCharacter; 
3011     case sym_k_integer_table_value:         return MrmRtypeIntegerVector;
3012     case sym_k_color_value:                 return MrmRtypeColor;
3013     case sym_k_color_table_value:           return MrmRtypeColorTable;
3014     case sym_k_icon_value:                  return MrmRtypeIconImage;
3015     case sym_k_float_value:                 return MrmRtypeFloat;
3016     case sym_k_horizontal_float_value:      return MrmRtypeHorizontalFloat;
3017     case sym_k_vertical_float_value:        return MrmRtypeVerticalFloat;
3018     case sym_k_font_value:                  return MrmRtypeFont;
3019     case sym_k_fontset_value:               return MrmRtypeFontSet;
3020     case sym_k_font_table_value:            return MrmRtypeFontList;
3021     case sym_k_identifier_value:            return MrmRtypeAddrName;
3022     case sym_k_class_rec_name_value:        return MrmRtypeClassRecName;
3023     case sym_k_xbitmapfile_value:           return MrmRtypeXBitmapFile;
3024     case sym_k_widget_ref_value:            return MrmRtypeAny;
3025     case sym_k_pixmap_value:                return MrmRtypeIconImage;
3026     case sym_k_any_value:                   return MrmRtypeAny;
3027     case sym_k_keysym_value:                return MrmRtypeKeysym;    
3028     case sym_k_single_float_value:          return MrmRtypeSingleFloat;
3029     case sym_k_rgb_value:                   return MrmRtypeColor;
3030
3031     default:
3032         _assert( FALSE, "unknown value type" );
3033         return 0;
3034     }
3035
3036 }
3037
3038
3039 \f
3040 /*
3041 **++
3042 **  FUNCTIONAL DESCRIPTION:
3043 **
3044 **      This function computes the size of a color table.
3045 **
3046 **  FORMAL PARAMETERS:
3047 **
3048 **      table_entry         value entry for the color table
3049 **
3050 **  IMPLICIT INPUTS:
3051 **
3052 **      none
3053 **
3054 **  IMPLICIT OUTPUTS:
3055 **
3056 **      none
3057 **
3058 **  FUNCTION VALUE:
3059 **
3060 **      size of the color table
3061 **
3062 **  SIDE EFFECTS:
3063 **
3064 **      colors within the color table may be allocated
3065 **
3066 **--
3067 **/
3068
3069 int     compute_color_table_size(table_entry)
3070
3071 sym_value_entry_type    *table_entry;
3072
3073 {
3074     sym_value_entry_type    *color_entry;
3075     int                     size;
3076     int                     i;
3077     MrmCode                 arg_type;
3078     long                    arg_value;
3079     MrmCode                 arg_access;
3080     char                    *arg_index;
3081     MrmResource_id          arg_id;
3082     MrmCode                 arg_group;
3083
3084     /*
3085     **  Compute the size of the ColorTable plus the size of the Color
3086     **  table entries (one per color including fore and back ground).
3087     **  Multiply entry size by max_index rather than max_index + 1
3088     **  since RGMColorTable includes 1 entry. Note that descriptors
3089     **  are sized to consume fullword-aligned blocks of memory in
3090     **  to preserve alignment for processors requiring such alignment.
3091     */
3092
3093     size = sizeof(RGMColorTable) +
3094         sizeof(RGMColorTableEntry)*table_entry->b_max_index;
3095     size = _FULLWORD (size);
3096
3097     /*
3098     **  Compute space needed for resource descriptors for the colors.
3099     */
3100
3101     for (i = 0;  i < (int)table_entry->b_table_count;  i++)
3102     {
3103         color_entry = table_entry->value.z_color[i].az_color;
3104
3105         /*
3106         **  Default colors have az_color set to 0=back and 1=fore.
3107         **  These require ColorTableEntries but no resource descriptors.
3108         */
3109
3110         if ((long)color_entry > 1)
3111         {
3112             /*
3113             **  Call ref_value for each of the colors in the color table.
3114             **  This will cause them to be created if necessary and also
3115             **  classify the type of resource needed.
3116             */
3117
3118             table_entry->value.z_color[i].w_desc_offset = size;
3119
3120             switch (ref_value( color_entry,
3121                                & arg_type, & arg_value, & arg_access,
3122                                & arg_index, & arg_id, & arg_group ) )
3123             {
3124             case URMrRID:
3125                 size += sizeof (RGMResourceDesc);
3126                 size = _FULLWORD (size);
3127                 break;
3128             case URMrIndex:
3129                 size += sizeof(RGMResourceDesc) - sizeof(MrmResource_id) +
3130                         strlen(arg_index)+1;
3131                 size = _FULLWORD (size);
3132                 break;
3133             default:
3134                 _assert( FALSE, "immediate color values not supported" );
3135             }
3136         }
3137     }
3138
3139     table_entry->w_length = size;
3140
3141     return size;
3142
3143 }
3144 \f
3145 /*
3146 **++
3147 **  FUNCTIONAL DESCRIPTION:
3148 **
3149 **      This function creates a color table in a context.
3150 **
3151 **  FORMAL PARAMETERS:
3152 **
3153 **      table_entry         value entry for the color table
3154 **      buffer              pointer to a context buffer
3155 **
3156 **  IMPLICIT INPUTS:
3157 **
3158 **      none
3159 **
3160 **  IMPLICIT OUTPUTS:
3161 **
3162 **      none
3163 **
3164 **  FUNCTION VALUE:
3165 **
3166 **      void
3167 **
3168 **  SIDE EFFECTS:
3169 **
3170 **      none
3171 **
3172 **--
3173 **/
3174
3175 void    create_color_table(table_entry, buffer)
3176
3177 sym_value_entry_type    *table_entry;
3178 char                    *buffer;
3179
3180 {
3181     RGMColorTable           *table;
3182     RGMColorTableEntry      *item;
3183     RGMResourceDesc         *desc;
3184     int                     i;
3185     MrmCode                 arg_form;
3186     MrmCode                 arg_type;
3187     long                    arg_value;
3188     MrmCode                 arg_access;
3189     char                    *arg_index;
3190     MrmResource_id          arg_id;
3191     MrmCode                 arg_group;
3192
3193     /*
3194     **  Fill in the Color Table fields
3195     */
3196
3197     table = (RGMColorTable *)buffer;
3198
3199     table->validation = URMColorTableValid;
3200     table->count = table_entry->b_max_index + 1;
3201
3202     /*
3203     **  Loop thru the colors in the table setting up both the index
3204     **  of offset for the colors and their resource descriptors.
3205     */
3206
3207     item = table->item;
3208
3209     for (i = 0;  i < (int)table_entry->b_table_count;  i++)
3210     {
3211         int     index;
3212
3213         index = table_entry->value.z_color[i].b_index;
3214         table->item[index].color_item.coffs = 
3215             table_entry->value.z_color[i].w_desc_offset;
3216         desc = (RGMResourceDesc *)
3217                     (buffer + table_entry->value.z_color[i].w_desc_offset);
3218
3219         /*
3220         **  Default colors have b_index set to 0=back and 1=fore.
3221         **  These require ColorTableEntries but no resource descriptors.
3222         */
3223
3224         if (index > 1)
3225         {
3226             table->item[index].type = MrmRtypeResource;
3227
3228             /*
3229             **  Call ref_value for each of the colors in the color table.
3230             **  This provide the necessary info to fill in the resource
3231             **  descriptor
3232             */
3233
3234             arg_form = ref_value( table_entry->value.z_color[i].az_color,
3235                                   & arg_type, & arg_value, & arg_access,
3236                                   & arg_index, & arg_id, & arg_group );
3237
3238             desc->access = arg_access;
3239             desc->type = arg_form;
3240             desc->res_group = arg_group;
3241             desc->cvt_type = arg_type;
3242
3243             switch (arg_form)
3244             {
3245             case URMrRID:
3246                 desc->size = sizeof( RGMResourceDesc );
3247                 desc->key.id = arg_id;
3248                 break;
3249             case URMrIndex:
3250                 desc->size = strlen( arg_index ) + 1;
3251                 _move( desc->key.index, arg_index, desc->size );
3252                 desc->size += sizeof( RGMResourceDesc ) - 
3253                               sizeof( MrmResource_id );
3254                 break;
3255             default:
3256                 _assert( FALSE, "immediate color values not supported" );
3257             }
3258         }
3259     }
3260
3261 }
3262 \f
3263 /*
3264 **++
3265 **  FUNCTIONAL DESCRIPTION:
3266 **
3267 **      This function computes the size of an icon.
3268 **
3269 **  FORMAL PARAMETERS:
3270 **
3271 **      icon_entry          value entry for the icon
3272 **
3273 **  IMPLICIT INPUTS:
3274 **
3275 **      none
3276 **
3277 **  IMPLICIT OUTPUTS:
3278 **
3279 **      none
3280 **
3281 **  FUNCTION VALUE:
3282 **
3283 **      size of the icon
3284 **
3285 **  SIDE EFFECTS:
3286 **
3287 **      color table within the icon may be allocated
3288 **
3289 **--
3290 **/
3291
3292 int     compute_icon_size(icon_entry)
3293
3294 sym_value_entry_type    *icon_entry;
3295
3296 {
3297     int                     size;
3298     int                     pixel_type;
3299     MrmCode                 arg_type;
3300     long                    arg_value;
3301     MrmCode                 arg_access;
3302     char                    *arg_index;
3303     MrmResource_id          arg_id;
3304     MrmCode                 arg_group;
3305
3306     /*
3307     **  The size of the icon consist of the size of the RGMIconImage
3308     **  structure + the size of the color table resource descriptor
3309     **  + the actual data.
3310     */
3311
3312     size = sizeof( RGMIconImage );
3313
3314     /*
3315     **  Compute space needed for the color table resource descriptor
3316     **
3317     **  Call ref_value.
3318     **  This will cause the table to be created if necessary and also
3319     **  classify the type of resource needed.
3320     */
3321
3322     switch (ref_value( icon_entry->value.z_icon->az_color_table,
3323                        & arg_type, & arg_value, & arg_access,
3324                        & arg_index, & arg_id, & arg_group ) )
3325     {
3326     case URMrRID:
3327         size += sizeof( RGMResourceDesc );
3328         break;
3329     case URMrIndex:
3330         size += sizeof( RGMResourceDesc ) - sizeof( MrmResource_id ) +
3331                 strlen( arg_index ) + 1;
3332         break;
3333     default:
3334         _assert( FALSE, "immediate color table values not supported" );
3335     }
3336
3337     /*
3338     **  Save the offset of the data for later.
3339     */
3340
3341     icon_entry->b_data_offset = size;
3342
3343     /*
3344     **  Bits per pixel is based on the number of colors used.
3345     **  Pixel_type:
3346     **          0       for 1 bit pixels
3347     **          1       for 2 bit pixels
3348     **          2       for 4 bit pixels
3349     **          3       for 8 bit pixels
3350     **  URM's pixels size encoding is pixel_type + 1
3351     **  Pixel_size = 1 << pixel_type
3352     */
3353
3354     pixel_type = icon_entry->value.z_icon->az_color_table->b_max_index;
3355
3356     if (pixel_type < 2)
3357         pixel_type = 0;
3358     else if (pixel_type < 4)
3359         pixel_type = 1;
3360     else if (pixel_type < 16)
3361         pixel_type = 2;
3362     else
3363         pixel_type = 3;
3364
3365     icon_entry->b_pixel_type = pixel_type;
3366
3367     /*
3368     **  Size is width * height - each row must be an even number of bytes
3369     */
3370
3371     size += ((int)((icon_entry->value.z_icon->w_width << pixel_type) + 7) / 8)
3372              * icon_entry->value.z_icon->w_height;
3373
3374     icon_entry->w_length = size;
3375
3376     return size;
3377
3378 }
3379 \f
3380 /*
3381 **++
3382 **  FUNCTIONAL DESCRIPTION:
3383 **
3384 **      This function creates an icon in a context buffer
3385 **
3386 **  FORMAL PARAMETERS:
3387 **
3388 **      icon_entry          value entry for the icon
3389 **      buffer              pointer to context buffer
3390 **
3391 **  IMPLICIT INPUTS:
3392 **
3393 **      none
3394 **
3395 **  IMPLICIT OUTPUTS:
3396 **
3397 **      none
3398 **
3399 **  FUNCTION VALUE:
3400 **
3401 **      void
3402 **
3403 **  SIDE EFFECTS:
3404 **
3405 **      buffer is filled in
3406 **
3407 **--
3408 **/
3409
3410 void    create_icon(icon_entry,buffer)
3411
3412 sym_value_entry_type    *icon_entry;
3413 char                    *buffer;
3414
3415 {
3416     sym_value_entry_type    *row_entry;
3417     RGMIconImage            *icon;
3418     RGMResourceDesc         *desc;
3419     MrmCode                 arg_form;
3420     MrmCode                 arg_type;
3421     long                    arg_value;
3422     MrmCode                 arg_access;
3423     char                    *arg_index;
3424     MrmResource_id          arg_id;
3425     MrmCode                 arg_group;
3426
3427     unsigned char           *sbyte;
3428     unsigned char           *tbyte;
3429     int                     w_len;
3430     int                     p_len;
3431     int                     i;
3432     int                     j;
3433     char                    pixel_type;
3434     char                    pixel_size;
3435     char                    pixel_per_byte;
3436
3437     /*
3438     **  Fill in the fixed location fields of the IconImage.
3439     */
3440
3441     icon = (RGMIconImage *)buffer;
3442
3443     icon->validation = URMIconImageValid;
3444     pixel_type = icon_entry->b_pixel_type;
3445     icon->pixel_size = pixel_type + 1;
3446     icon->width = icon_entry->value.z_icon->w_width;
3447     icon->height = icon_entry->value.z_icon->w_height;
3448     icon->ct_type = MrmRtypeResource;
3449     icon->color_table.ctoff = sizeof( RGMIconImage );
3450     icon->pixel_data.pdoff = icon_entry->b_data_offset;
3451
3452     /*
3453     **  Place color table resource descriptor in the context.
3454     **
3455     **  Call ref_value which will return all info need to complete
3456     **  the description.
3457     */
3458
3459     arg_form = ref_value( icon_entry->value.z_icon->az_color_table,
3460                           & arg_type, & arg_value, & arg_access,
3461                           & arg_index, & arg_id, & arg_group );
3462
3463     desc = (RGMResourceDesc *)(buffer + sizeof( RGMIconImage ));
3464
3465     desc->access = arg_access;
3466     desc->type = arg_form;
3467     desc->res_group = arg_group;
3468     desc->cvt_type = MrmRtypeResource;
3469
3470     switch (arg_form)
3471     {
3472     case URMrRID:
3473         desc->size = sizeof( RGMResourceDesc );
3474         desc->key.id = arg_id;
3475         break;
3476     case URMrIndex:
3477         desc->size = strlen( arg_index ) + 1;
3478         _move( desc->key.index, arg_index, desc->size );
3479         desc->size += sizeof( RGMResourceDesc ) - 
3480                       sizeof( MrmResource_id );
3481         break;
3482     default:
3483         _assert( FALSE, "immediate color values not supported" );
3484     }
3485
3486     /*
3487     **  Now move the pixels into the buffer
3488     **  Variable usage:
3489     **      sbyte:  base of source byte stream
3490     **      tbyte:  current position in target byte stream
3491     **      w_len:  # of pixels that will go into integral # of bytes
3492     **      p_len:  # of pixels that will go into final byte
3493     */
3494
3495     pixel_per_byte = 8 >> pixel_type;
3496     pixel_size = 1 << pixel_type;
3497
3498     tbyte = (unsigned char *)(buffer + icon_entry->b_data_offset);
3499
3500     for (row_entry = icon_entry->value.z_icon->az_rows,
3501          w_len = ((int)row_entry->w_length / (int)pixel_per_byte) * pixel_per_byte,
3502          p_len = row_entry->w_length - w_len;
3503
3504          row_entry != NULL;  
3505
3506          row_entry = row_entry->az_next_table_value)
3507     {
3508         sbyte = (unsigned char *)row_entry->value.c_value;
3509
3510         for (i = 0;  i < w_len; tbyte++)
3511         {
3512             for (*tbyte = 0, j = 0;  
3513                  j < 8;  
3514                  j += pixel_size )
3515             {
3516                 unsigned char   t;
3517
3518                 t = sbyte[i++] << j;
3519                 *tbyte |= t;
3520             }
3521         }
3522
3523         if (p_len > 0)
3524         {
3525             for ( *tbyte = 0, j = 0;
3526                   j < (p_len * pixel_size);
3527                   j += pixel_size  )
3528             {
3529                 unsigned char   t;
3530
3531                 t = sbyte[i++] << j;
3532                 *tbyte |= t;
3533             }
3534             tbyte++;
3535         }
3536     }
3537 }
3538
3539
3540 \f
3541 /*
3542 **++
3543 **  FUNCTIONAL DESCRIPTION:
3544 **
3545 **      This function counts the number of valid, usable entries in a
3546 **      list. It simply accumulates all the nodes in the list (recursively)
3547 **      which match the given node type.
3548 **
3549 **  FORMAL PARAMETERS:
3550 **
3551 **      list_entry              the list to be counted
3552 **      type                    the node type to match
3553 **
3554 **  IMPLICIT INPUTS:
3555 **
3556 **  IMPLICIT OUTPUTS:
3557 **
3558 **  FUNCTION VALUE:
3559 **
3560 **      the number of nodes which matched the type
3561 **
3562 **  SIDE EFFECTS:
3563 **
3564 **--
3565 **/
3566
3567 int compute_list_size (list_entry, type)
3568     sym_list_entry_type         *list_entry;
3569     int                         type;
3570
3571 {
3572
3573 /*
3574  * Local variables
3575  */
3576 sym_obj_entry_type              *list_member;
3577 sym_nested_list_entry_type      *nested_list_entry;
3578 int                             count = 0;
3579
3580 /*
3581  * loop down the list
3582  */
3583 if ( list_entry == NULL ) return 0;
3584 for (list_member=(sym_obj_entry_type *)list_entry->obj_header.az_next;
3585      list_member!=NULL;
3586      list_member=(sym_obj_entry_type *)list_member->obj_header.az_next)
3587     switch ( list_member->header.b_tag )
3588         {
3589         case sym_k_nested_list_entry:
3590             nested_list_entry = (sym_nested_list_entry_type *) list_member;
3591             count += compute_list_size (nested_list_entry->az_list, type);
3592             break;
3593         default:
3594             if ( list_member->header.b_tag == (char)type )
3595                 count += 1;
3596             break;
3597         }
3598
3599 return count;
3600
3601 }
3602 \f
3603 /*
3604 **++
3605 **  FUNCTIONAL DESCRIPTION:
3606 **
3607 **      This routine creates the internal compression code tables.  
3608 **
3609 **      Upon calling this routine, the internal compression code tables
3610 **      (uil_arg_compr, uil_reas_compr, and uil_widget_compr) have zero 
3611 **      entries for resources which have not been referenced in this UIL 
3612 **      module and have one entries for resrources which have been referenced.  
3613 **
3614 **      This routine assigns increasing integers to each non-zero entry in the
3615 **      internal compression code tables.
3616 **
3617 **      The internal compression code tables are indexed by subclass to yield
3618 **      the external compression code values which are written to the UID file. 
3619 **
3620 **  FORMAL PARAMETERS:
3621 **
3622 **      none
3623 **
3624 **  IMPLICIT INPUTS:
3625 **
3626 **      uil_arg_compr
3627 **      uil_reas_compr
3628 **      uil_widget_compr
3629 **
3630 **  IMPLICIT OUTPUTS:
3631 **
3632 **      uil_arg_compr
3633 **      uil_reas_compr
3634 **      uil_widget_compr
3635 **
3636 **  FUNCTION VALUE:
3637 **
3638 **      void
3639 **
3640 **  SIDE EFFECTS:
3641 **
3642 **--
3643 **/
3644
3645 void create_int_compression_codes ()
3646 {
3647
3648 /*
3649  * Local variables
3650  */
3651 int     i;
3652 int     compression_code = 2;
3653
3654     /*
3655     ** Request compression codes for all subtree resources.
3656     */
3657
3658     for ( i=0 ; i<uil_max_object ; i++ )
3659         if ( uil_urm_subtree_resource[i] != 0 )
3660             uil_arg_compr[uil_urm_subtree_resource[i]] = 1;
3661
3662     /*
3663     ** Create compression code tables for object classes. This include
3664     ** both widgets and gadgets, since both have class literals.
3665     **
3666     */
3667
3668     for (i = 0 ; i <= uil_max_object; i++)
3669         {
3670         if (uil_widget_compr[i] == 1)
3671             uil_widget_compr[i] = compression_code++;
3672         }
3673
3674     /*
3675     ** Create compression code tables for arguments
3676     **
3677     */
3678
3679     compression_code = 2;
3680     for (i = 0 ; i <= uil_max_arg ; i++)
3681         {
3682         if (uil_arg_compr[i] == 1)
3683             uil_arg_compr[i] = compression_code++;
3684         }
3685
3686     /*
3687     ** Create compression code tables for reasons.
3688     ** Note that the numbering continues from where we left off with args.
3689     */
3690
3691     for (i = 0;
3692         i <= uil_max_reason;
3693         i++)
3694         {
3695         if (uil_reas_compr[i] == 1)
3696             uil_reas_compr[i] = compression_code++;
3697         }
3698
3699     /*
3700     ** Create compression code tables for automatic children.
3701     ** Note that numbering continues where we left off with reasons.
3702     */
3703     for (i = 0; i <= uil_max_child; i++)
3704         {
3705         if (uil_child_compr[i] == 1)
3706             uil_child_compr[i] = compression_code++;
3707         }
3708
3709 }
3710
3711 \f
3712 /*
3713 **++
3714 **  FUNCTIONAL DESCRIPTION:
3715 **
3716 **      This routine creates the external compression code tables.  
3717 **
3718 **
3719 **      This routine writes the corresponding toolkit name to the external
3720 **      compression code table for each non-zero entry in the internal
3721 **      compression code table.
3722 **
3723 **      The internal compression code tables are indexed by subclass to yield
3724 **      the external compression code values which are written to the UID file. 
3725 **      The external compression codes are used as an index to the external
3726 **      compression code tables so that MRM can map the compression code into
3727 **      the corresponding toolkit name.
3728 **
3729 **  FORMAL PARAMETERS:
3730 **
3731 **      none
3732 **
3733 **  IMPLICIT INPUTS:
3734 **
3735 **      uil_arg_compr
3736 **      uil_reas_compr
3737 **      uil_widget_compr
3738 **
3739 **  IMPLICIT OUTPUTS:
3740 **
3741 **      extern_args_compr
3742 **      extern_widget_compr
3743 **      %ArgCmpr (index for argument compression table in UID file)
3744 **      %ReasCmpr (index for reason compression table in UID file)
3745 **      %ClassCmpr (index for class compression table in UID file)
3746 **
3747 **  FUNCTION VALUE:
3748 **
3749 **      void
3750 **
3751 **  SIDE EFFECTS:
3752 **
3753 **--
3754 **/
3755
3756 void create_ext_compression_codes ()
3757 {
3758
3759 /*
3760  * Local variables
3761  */
3762 int     i;
3763 int     comp_code;
3764 int     next_code;
3765 int     text_offset;
3766 int     arg_value_count;
3767 int     arg_value_size;
3768 char    *arg_buffer;
3769 int     class_value_count;
3770 int     class_value_size;
3771 char    *class_buffer;
3772 status  urm_status;
3773
3774     /*
3775     ** Create compression code tables for arguments
3776     **
3777     ** Determine number of elements in external compression table 
3778     ** ( extern_arg_compr[] ) and size of external compression table.
3779     */
3780
3781     arg_value_size = sizeof (UidCompressionTable);
3782     arg_value_count = UilMrmReservedCodeCount;
3783     next_code = UilMrmMinValidCode;
3784     for (i = 0;
3785         i <= uil_max_arg;
3786         i++)
3787         {
3788         if (uil_arg_compr[i] != 0)
3789             {
3790             arg_value_count++;
3791             next_code++;
3792             if (uil_argument_toolkit_names[i] == NULL)
3793                 {
3794                 _assert (FALSE, "unknown argument")
3795                 }
3796             else
3797                 arg_value_size += strlen(uil_argument_toolkit_names[i]) + 1;
3798             }
3799         }
3800
3801     /*
3802     ** Add compression codes for reasons
3803     */
3804
3805     for (i = 0;
3806         i <= uil_max_reason;
3807         i++)
3808         {
3809         if (uil_reas_compr[i] != 0)
3810             {
3811             arg_value_count++;
3812             next_code++;
3813             if (uil_reason_toolkit_names[i] == NULL)
3814                 {
3815                 _assert (FALSE, "unknown argument")
3816                 }
3817             else
3818                 arg_value_size += strlen(uil_reason_toolkit_names[i]) + 1;
3819             }
3820         }
3821
3822     /*
3823     ** Add compression codes for automatic children
3824     */
3825
3826     for (i = 0; i <= uil_max_child; i++)
3827       {
3828         if (uil_child_compr[i] != 0)
3829           {
3830             arg_value_count++;
3831             next_code++;
3832             arg_value_size += strlen(uil_child_names[i]) + 1;
3833           }
3834       }
3835
3836     /*
3837     ** Add the space for the table's vector entries (the next code counts
3838     ** one more space than we need, but as a zero-based code has the
3839     ** correct number in it).
3840     */
3841     arg_value_size += sizeof(UidCTableEntry) * next_code;
3842
3843
3844     /*
3845     ** Check that the resource context is large enough to hold the value
3846     */
3847
3848     if ( (int)(UrmRCSize( out_az_context )) < arg_value_size )
3849         {
3850         if( MrmSUCCESS != 
3851            UrmResizeResourceContext( out_az_context, arg_value_size ))
3852             issue_urm_error( "allocating context" );
3853         }
3854
3855     /*
3856     ** Set up the resource context and point extern_arg_compr to the resource
3857     ** context buffer.
3858     */
3859
3860     UrmRCSetGroup( out_az_context, URMgLiteral );
3861     UrmRCSetType( out_az_context, sym_k_asciz_table_value );
3862     UrmRCSetAccess( out_az_context, URMaPublic );
3863     UrmRCSetLock( out_az_context, FALSE );
3864     UrmRCSetSize( out_az_context, arg_value_size );
3865
3866     arg_buffer = (char *) UrmRCBuffer( out_az_context );
3867
3868     extern_arg_compr = (UidCompressionTable *)arg_buffer;
3869     bzero (arg_buffer, arg_value_size);
3870
3871     /*
3872     ** Now fill in the actual value of the external compresion code
3873     ** table ( extern_arg_compr[] ).  
3874     */
3875
3876     extern_arg_compr->validation = UidCompressionTableValid;
3877     extern_arg_compr->num_entries = arg_value_count;
3878 #ifdef WORD64
3879     text_offset = ((int)&extern_arg_compr->entry[arg_value_count]
3880                    - (int)extern_arg_compr) * sizeof(int);
3881 #else
3882     text_offset = (long)&extern_arg_compr->entry[arg_value_count]
3883         - (long)extern_arg_compr;
3884 #endif
3885     comp_code = UilMrmMinValidCode;
3886     for ( i = 0 ; i<=uil_max_arg ; i++ )
3887         {
3888         if (uil_arg_compr[i] != 0)
3889             {
3890             _move( &(arg_buffer[text_offset]), 
3891                   uil_argument_toolkit_names[i], 
3892                   strlen(uil_argument_toolkit_names[i]) + 1);
3893             extern_arg_compr->entry[comp_code].stoffset = text_offset;
3894             text_offset += (strlen(uil_argument_toolkit_names[i]) + 1);
3895             comp_code++;
3896             }
3897         }
3898
3899     for ( i = 0 ; i<=uil_max_reason ; i++ )
3900         {
3901         if (uil_reas_compr[i] != 0)
3902             {
3903             _move( &(arg_buffer[text_offset]), 
3904                   uil_reason_toolkit_names[i], 
3905                   strlen(uil_reason_toolkit_names[i]) + 1);
3906             extern_arg_compr->entry[comp_code].stoffset = 
3907                 text_offset;
3908             text_offset += (strlen(uil_reason_toolkit_names[i]) + 1);
3909             comp_code++;
3910             }
3911         }
3912
3913     for ( i = 0 ; i<=uil_max_child ; i++ )
3914       {
3915         if (uil_child_compr[i] != 0)
3916           {
3917             char *name;
3918             
3919             if (strncmp(uil_child_names[i], AUTO_CHILD_PREFIX, 
3920                         strlen(AUTO_CHILD_PREFIX)) == 0)
3921               name = (uil_child_names[i] + strlen(AUTO_CHILD_PREFIX));
3922             else name = uil_child_names[i];
3923
3924             _move( &(arg_buffer[text_offset]), name, strlen(name) + 1);
3925             extern_arg_compr->entry[comp_code].stoffset = text_offset;
3926             text_offset += (strlen(name) + 1);
3927             comp_code++;
3928           }
3929       }
3930
3931     /*
3932     ** Finally write the argument compression code table out to the UID file
3933     */
3934     urm_status = 
3935       UrmPutIndexedLiteral (out_az_idbfile_id, 
3936                             UilMrmResourceTableIndex, out_az_context);
3937     if (urm_status != MrmSUCCESS)
3938         {
3939         if (urm_status == MrmEOF)
3940             diag_issue_diagnostic ( d_uid_write, diag_k_no_source, 
3941                                     diag_k_no_column, Uil_current_file );
3942         else
3943             issue_urm_error("emitting literal");
3944         }
3945
3946 \f
3947     /*
3948     ** Create compression code tables for classes
3949     **
3950     ** Determine number of elements in external compression table 
3951     ** ( extern_class_compr[] ) and size of external 
3952     ** compression table.
3953     ** PROBABL ERROR: WHAT ABOUT GADGETS???
3954     */
3955
3956     class_value_size = sizeof (UidCompressionTable);
3957     class_value_count = UilMrmReservedCodeCount;
3958     next_code = UilMrmMinValidCode;
3959     for (i = 0;
3960         i <= uil_max_object;
3961         i++)
3962         if (uil_widget_compr[i] != 0)
3963             {
3964             class_value_count++;
3965             next_code++;
3966             if (uil_widget_funcs[i] == NULL)
3967                 {
3968                 _assert (FALSE, "unknown class")
3969                 }
3970             else
3971                 class_value_size += strlen(uil_widget_funcs[i]) + 1;
3972             }
3973
3974     /*
3975     ** Again, compute the additional size for the vector.
3976     */
3977
3978     class_value_size += sizeof(UidCTableEntry) * next_code;
3979
3980     /*
3981     ** Check that the resource context is large enough to hold the value
3982     */
3983
3984     if ( (int)(UrmRCSize(out_az_context)) < class_value_size )
3985         {
3986         if( MrmSUCCESS != 
3987            UrmResizeResourceContext( out_az_context, class_value_size ))
3988             issue_urm_error( "allocating context" );
3989         }
3990
3991     /*
3992     ** Set up the resource context and point extern_class_compr to the resource
3993     ** context buffer.
3994     */
3995
3996     UrmRCSetGroup( out_az_context, URMgLiteral );
3997     UrmRCSetType( out_az_context, sym_k_asciz_table_value );
3998     UrmRCSetAccess( out_az_context, URMaPublic );
3999     UrmRCSetLock( out_az_context, FALSE );
4000     UrmRCSetSize( out_az_context, class_value_size );
4001
4002     class_buffer = (char *) UrmRCBuffer( out_az_context );
4003
4004     extern_class_compr = (UidCompressionTable *)class_buffer;
4005     bzero (class_buffer, class_value_size);
4006
4007     /*
4008     ** Now fill in the actual value of the external compresion code
4009     ** table ( extern_class_compr[] ).  
4010     */
4011
4012     extern_class_compr->validation = UidCompressionTableValid;
4013     extern_class_compr->num_entries = class_value_count;
4014 #ifdef WORD64
4015     text_offset = ((int)&extern_class_compr->entry[class_value_count]
4016                    - (int)extern_class_compr) * sizeof(int);
4017 #else
4018     text_offset = (long)&extern_class_compr->entry[class_value_count]
4019         - (long)extern_class_compr;
4020 #endif
4021     comp_code = UilMrmMinValidCode;
4022     for ( i = 0;
4023         i <= uil_max_object;
4024         i++)
4025         {
4026         if (uil_widget_compr[i] != 0)
4027             {
4028             _move( &(class_buffer[text_offset]), 
4029                 uil_widget_funcs[i], 
4030                 strlen(uil_widget_funcs[i]) + 1);
4031             extern_class_compr->entry[comp_code].stoffset = 
4032                 text_offset;
4033             text_offset += (strlen(uil_widget_funcs[i]) + 1);
4034             comp_code++;
4035             }
4036         }
4037
4038     /*
4039     ** Finally write the class compression code table out to the UID file
4040     */
4041     urm_status = 
4042       UrmPutIndexedLiteral (out_az_idbfile_id, UilMrmClassTableIndex, 
4043                             out_az_context);
4044     if (urm_status != MrmSUCCESS)
4045         {
4046         if (urm_status == MrmEOF)
4047             diag_issue_diagnostic ( d_uid_write, diag_k_no_source, 
4048                                     diag_k_no_column, Uil_current_file );
4049         else
4050             issue_urm_error("emitting literal");
4051         }
4052 }