Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / osf / uil / UilSarObj.c
1 /* 
2  *  @OSF_COPYRIGHT@
3  *  COPYRIGHT NOTICE
4  *  Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc.
5  *  ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for
6  *  the full copyright text.
7 */ 
8 /* 
9  * HISTORY
10 */ 
11 #ifdef REV_INFO
12 #ifndef lint
13 static char rcsid[] = "$XConsortium: UilSarObj.c /main/14 1995/07/14 09:37:30 drk $"
14 #endif
15 #endif
16
17 /*
18 *  (c) Copyright 1989, 1990, DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. */
19
20 /*
21 **++
22 **  FACILITY:
23 **
24 **      User Interface Language Compiler (UIL)
25 **
26 **  ABSTRACT:
27 **
28 **      This module contains the semantic action routines for
29 **      object definitions in the UIL.
30 **
31 **--
32 **/
33
34
35 /*
36 **
37 **  INCLUDE FILES
38 **
39 **/
40
41 #include "UilDefI.h"
42
43
44 /*
45 **
46 **  DEFINE and MACRO DEFINITIONS
47 **
48 **/
49
50 /*
51 **  This is a fast algorithm for mapping an integer (_size) to
52 **          0   _size <= 8
53 **          1   8 < _size <= 16
54 **          2   16 < _size <= 32
55 **          3   32 < _size <= 64
56 **          4   64 < _size 
57 **  The algorithm is based on the notion that the floating pt representation
58 **  of an integer has an exponent that is the log_base2( int ).
59 **
60 **  This algorithm is specific to the VAX.  An alternate layout of the
61 **  internal represention of a floating pt number could be supplied for
62 **  other architectures.
63 */
64
65 #define _compute_node_index( _size, _index ) \
66     {   unsigned short j, k; \
67         j = (_size); \
68         if (j <= 8) k = 0; \
69         else if (j <= 16) k = 1; \
70         else if (j <= 32) k = 2; \
71         else if (j <= 64) k = 3; \
72         else k = 4; \
73         (_index) = k; \
74     }
75           
76         
77
78 /*
79 **
80 **  EXTERNAL VARIABLE DECLARATIONS
81 **
82 **/
83
84 extern yystype                  gz_yynullval;
85 extern yystype                  yylval;
86
87
88 /*
89 **
90 **  GLOBAL VARIABLE DECLARATIONS
91 **
92 **/
93
94
95
96 /*
97 **
98 **  OWN VARIABLE DECLARATIONS
99 **
100 **/
101
102
103 \f
104 /*
105 **++
106 **  FUNCTIONAL DESCRIPTION:
107 **
108 **      This routine associates the latest comment block
109 **      with the current object frame.    RAP
110 **
111 **  FORMAL PARAMETERS:
112 **
113 **      object_frame            address of the parse stack frame for this
114 **                              object.
115 **
116 **      
117 **
118 **  IMPLICIT INPUTS:
119 **
120 **      none
121 **
122 **  IMPLICIT OUTPUTS:
123 **
124 **      none
125 **
126 **  FUNCTION VALUE:
127 **
128 **      void
129 **
130 **  SIDE EFFECTS:
131 **
132 **      the object frame contains the comment for this object.
133 **
134 **--
135 **/
136
137 void            sar_assoc_comment( object )
138
139 sym_obj_entry_type    *object;
140 {
141
142   object->obj_header.az_comment = (char *)_get_memory(strlen(comment_text)+1);
143   strcpy(object->obj_header.az_comment, comment_text);
144   comment_text[0] = '\0';
145
146 }
147
148 \f
149 /*
150 **++
151 **  FUNCTIONAL DESCRIPTION:
152 **
153 **      This routine creates the symbol node for the object, and
154 **      saves it in the object frame on the parse stack.
155 **
156 **  FORMAL PARAMETERS:
157 **
158 **      object_frame            address of the parse stack frame for this
159 **                              object.
160 **
161 **      object_type             type literal for this object.
162 **
163 **  IMPLICIT INPUTS:
164 **
165 **      none
166 **
167 **  IMPLICIT OUTPUTS:
168 **
169 **      none
170 **
171 **  FUNCTION VALUE:
172 **
173 **      void
174 **
175 **  SIDE EFFECTS:
176 **
177 **      the object frame contains the symbol node for this object.
178 **
179 **--
180 **/
181
182 void            sar_create_object
183         ( yystype *object_frame, unsigned char object_type )
184
185 {
186
187     sym_name_entry_type         * name_entry;
188     sym_obj_entry_type          * obj_entry;
189     int                         node_size;
190     yystype                     * source_frame;
191
192     source_frame = & yylval;
193
194     if (object_frame->b_tag != sar_k_null_frame)
195         {
196
197         /* 
198          ** First we check on the name to see if it has been previously used.
199          ** This function returns NULL if name cannot be used.
200          */
201         name_entry = (sym_name_entry_type *) sem_dcl_name (object_frame);
202         }
203     else
204         {
205         name_entry = NULL;
206         }
207
208 /*    Determine the size of the symbol node to allocate.    */
209
210     switch (object_type)
211         {
212         case sym_k_gadget_entry:
213         case sym_k_widget_entry:
214             node_size = sym_k_widget_entry_size;
215             break;
216
217         case sym_k_list_entry:
218             node_size = sym_k_list_entry_size;
219             break;
220
221         default:
222             _assert (FALSE, "unexpected object type");
223             break;
224         }
225
226 /*
227  * Allocate the symbol node, connect it to its name, and save source info
228  */
229     obj_entry = (sym_obj_entry_type *)
230         sem_allocate_node (object_type, node_size);
231     if (name_entry != NULL)
232         {
233         name_entry->az_object = (sym_entry_type *)obj_entry;
234         obj_entry->obj_header.az_name = (sym_name_entry_type *)name_entry;
235         }
236     _sar_save_source_pos (&obj_entry->header, source_frame );
237     sar_assoc_comment(obj_entry);  /* preserve comments */
238 /*
239  * Set the definition in progress bit.
240  */
241     obj_entry->obj_header.b_flags |= sym_m_def_in_progress;
242
243 /*
244  * Save the symbol node in the object frame.
245  */
246     object_frame->b_tag = sar_k_object_frame;
247     object_frame->b_type = object_type;
248     object_frame->value.az_symbol_entry = (sym_entry_type *)obj_entry;
249
250 }
251
252 \f
253 /*
254 **++
255 **  FUNCTIONAL DESCRIPTION:
256 **
257 **      This routine creates the symbol node for the child, and
258 **      saves it in the object frame on the parse stack.
259 **
260 **  FORMAL PARAMETERS:
261 **
262 **      object_frame            address of the parse stack frame for this
263 **                              object.
264 **
265 **  IMPLICIT INPUTS:
266 **
267 **      none
268 **
269 **  IMPLICIT OUTPUTS:
270 **
271 **      none
272 **
273 **  FUNCTION VALUE:
274 **
275 **      void
276 **
277 **  SIDE EFFECTS:
278 **
279 **      the object frame contains the symbol node for this child.
280 **
281 **--
282 **/
283
284 void            sar_create_child
285         ( yystype *object_frame )
286
287 {
288     sym_obj_entry_type          * obj_entry;
289     yystype                     * source_frame;
290
291     source_frame = & yylval;
292
293 /*
294  * Allocate the symbol node, set its type, and save source info
295  */
296     obj_entry = (sym_obj_entry_type *)
297         sem_allocate_node (sym_k_child_entry, sym_k_widget_entry_size);
298     obj_entry->header.b_type = 
299       object_frame->value.az_keyword_entry->b_subclass;
300
301     _sar_save_source_pos (&obj_entry->header, source_frame );
302     sar_assoc_comment(obj_entry);  /* preserve comments */
303 /*
304  * Indicate in compress table that this child type is used.
305  */
306     uil_child_compr[obj_entry->header.b_type] = 1;
307     
308 /*
309  * Set the definition in progress bit.
310  */
311     obj_entry->obj_header.b_flags |= sym_m_def_in_progress;
312
313 /*
314  * Save the symbol node in the object frame.
315  */
316     object_frame->b_tag = sar_k_object_frame;
317     object_frame->b_type = sym_k_child_entry;
318     object_frame->value.az_symbol_entry = (sym_entry_type *)obj_entry;
319
320 }
321
322 \f
323 /*
324 **++
325 **  FUNCTIONAL DESCRIPTION:
326 **
327 **      This routine creates and links a section node into the symbol table
328 **
329 **  FORMAL PARAMETERS:
330 **
331 **      id_frame        the token frame with the id for this entry.
332 **
333 **  IMPLICIT INPUTS:
334 **
335 **      sym_az_current_section_entry    global pointer to the "current" section
336 **
337 **  IMPLICIT OUTPUTS:
338 **
339 **      none
340 **
341 **  FUNCTION VALUE:
342 **
343 **      void
344 **
345 **  SIDE EFFECTS:
346 **
347 **--
348 **/
349
350 void    sar_link_section ( id_frame )
351
352 yystype                 * id_frame;
353
354 {
355 sym_section_entry_type  * section_entry;
356
357 /*
358  * Allocate a section entry. Link this entry of of the current section list
359  */
360 section_entry = (sym_section_entry_type *) sem_allocate_node
361     (sym_k_section_entry, sym_k_section_entry_size);
362 section_entry->next = (sym_entry_type *)
363     sym_az_current_section_entry->entries;
364 sym_az_current_section_entry->entries = (sym_entry_type *) section_entry;
365 section_entry->entries = id_frame->value.az_symbol_entry;
366
367 }
368 \f
369 /*
370 **++
371 **  FUNCTIONAL DESCRIPTION:
372 **
373 **      This routine saves the source information about where this
374 **      semi-colon entry ends.
375 **
376 **  FORMAL PARAMETERS:
377 **
378 **      semi_frame      the token frame for the terminating semi-colon
379 **                      for this entry.
380 **
381 **  IMPLICIT INPUTS:
382 **
383 **      sym_az_current_section_entry    global pointer to the
384 **              "current" section list
385 **
386 **  IMPLICIT OUTPUTS:
387 **
388 **      none
389 **
390 **  FUNCTION VALUE:
391 **
392 **      void
393 **
394 **  SIDE EFFECTS:
395 **
396 **      none
397 **
398 **--
399 **/
400
401 void    sar_save_src_semicolon_pos (semi_frame)
402
403 yystype                 * semi_frame;
404
405 {
406 sym_section_entry_type  * section_entry;
407
408 section_entry = (sym_section_entry_type *)
409     sym_az_current_section_entry->entries;
410 _sar_save_source_pos (&section_entry->entries->header, semi_frame);
411
412 }
413
414 \f
415 /*
416 **++
417 **  FUNCTIONAL DESCRIPTION:
418 **
419 **      This function saves the title end source for lists (i.e. "ARGUMENTS",
420 **      "CALLBACKS", "PROCEDURES", and "CONTROLS").  The source saved here
421 **      should be "}" or posibly an id_ref.
422 **
423 **  PARAMETERS:
424 **
425 **      close_frame     ptr to token frame for the closing source
426 **
427 **  IMPLICIT INPUTS:
428 **
429 **      the "current" list on the frame stack as returned by sem_find_object
430 **
431 **  IMPLICIT OUTPUTS:
432 **
433 **      none
434 **
435 **  FUNCTION VALUE:
436 **
437 **      void
438 **
439 **  SIDE EFFECTS:
440 **
441 **      none
442 **--
443 **/
444
445 void    sar_save_list_end (close_frame)
446
447 yystype     *close_frame;
448
449 {
450     sym_list_entry_type         * list_entry;
451     yystype                     * list_frame;
452
453     /*
454     ** Search the syntax stack for the object frame.
455     */
456
457     list_frame = sem_find_object (close_frame - 1);
458     list_entry = (sym_list_entry_type *) list_frame->value.az_symbol_entry;
459
460     _sar_save_source_pos ( &list_entry->header , close_frame );
461
462 }
463 \f
464 /*
465 **++
466 **  FUNCTIONAL DESCRIPTION:
467 **
468 **      This function saves the end source for just about any type
469 **      of entry.
470 **
471 **  PARAMETERS:
472 **
473 **      close_frame     ptr to token frame for the closing source (probably
474 **                      a semi-colon).
475 **
476 **  IMPLICIT INPUTS:
477 **
478 **      the "current" list on the frame stack as returned by sem_find_object
479 **
480 **  IMPLICIT OUTPUTS:
481 **
482 **      none
483 **
484 **  FUNCTION VALUE:
485 **
486 **      void
487 **
488 **  SIDE EFFECTS:
489 **
490 **      none
491 **--
492 **/
493
494 void    sar_save_src_entry_end (close_frame, entry_frame)
495
496 yystype    *close_frame;
497 yystype    *entry_frame;
498
499 {
500     sym_entry_type              * entry;
501
502     /*
503     ** Extract the entry from the frame.
504     */
505
506     entry = (sym_entry_type *) entry_frame->value.az_symbol_entry;
507
508     /*
509     ** Case on the type of entry (source gets put in a different spot for
510     ** control entries).
511     */
512
513     if (entry->header.b_tag == sym_k_control_entry)
514         {
515         sym_control_entry_type *control_entry = (sym_control_entry_type *)entry;
516
517         _sar_save_source_pos (&control_entry->az_con_obj->header, close_frame);
518         }
519
520     /*
521     ** Save the source info in the default place
522     */
523
524     _sar_save_source_pos ( &entry->header , close_frame );
525
526 }
527 \f
528 /*
529 **++
530 **  FUNCTIONAL DESCRIPTION:
531 **
532 **      This routine sets flags in the stack entry for the object.
533 **
534 **  FORMAL PARAMETERS:
535 **
536 **      current_frame           address of the current syntax stack frame
537 **
538 **      mask                    mask of flags to be set.
539 **
540 **  IMPLICIT INPUTS:
541 **
542 **      none
543 **
544 **  IMPLICIT OUTPUTS:
545 **
546 **      none
547 **
548 **  FUNCTION VALUE:
549 **
550 **      void
551 **
552 **  SIDE EFFECTS:
553 **
554 **      none
555 **
556 **--
557 **/
558
559 void    sar_set_object_flags 
560
561         (yystype *current_frame, unsigned char mask )
562
563 {
564
565     sym_obj_entry_type          * obj_entry;
566     yystype                     * object_frame;
567
568 /*    Search the syntax stack for the object frame.    */
569
570     object_frame = sem_find_object (current_frame - 1);
571     obj_entry = (sym_obj_entry_type *) object_frame->value.az_symbol_entry;
572
573 /*    Set the flags for the object entry.       */
574
575     obj_entry->obj_header.b_flags |= mask;
576
577 /*    If this is an exported or private object and it has a name, 
578 **    make an external entry for it.    
579 */
580
581     if ((mask & (sym_m_exported | sym_m_private)) &&
582         (obj_entry->obj_header.az_name != NULL))
583         {
584         sym_make_external_def (obj_entry->obj_header.az_name);
585         }
586
587 }
588
589 \f
590 /*
591 **++
592 **  FUNCTIONAL DESCRIPTION:
593 **
594 **      This routine unsets flags in the stack entry for the object.
595 **
596 **  FORMAL PARAMETERS:
597 **
598 **      current_frame           address of the current syntax stack frame
599 **
600 **      mask                    mask of flags to be unset.
601 **
602 **  IMPLICIT INPUTS:
603 **
604 **      none
605 **
606 **  IMPLICIT OUTPUTS:
607 **
608 **      none
609 **
610 **  FUNCTION VALUE:
611 **
612 **      void
613 **
614 **  SIDE EFFECTS:
615 **
616 **      none
617 **
618 **--
619 **/
620
621 void    sar_unset_object_flags 
622
623         (yystype *current_frame, unsigned char mask )
624
625 {
626     yystype                     * object_frame;
627
628 /*    Search the syntax stack for the object frame.    */
629
630     object_frame = sem_find_object (current_frame - 1);
631
632 /*    Unset the flags for the object entry.     */
633
634     object_frame->b_flags &= ~mask;
635
636 }
637
638 \f
639 /*
640 **++
641 **  FUNCTIONAL DESCRIPTION:
642 **
643 **      This routine sets the type in the stack entry for the (list) object.
644 **
645 **  FORMAL PARAMETERS:
646 **
647 **      current_frame           address of the current syntax stack frame
648 **
649 **  IMPLICIT INPUTS:
650 **
651 **      none
652 **
653 **  IMPLICIT OUTPUTS:
654 **
655 **      none
656 **
657 **  FUNCTION VALUE:
658 **
659 **      void
660 **
661 **  SIDE EFFECTS:
662 **
663 **      none
664 **
665 **--
666 **/
667
668 void            sar_set_list_type
669                         ( current_frame )
670
671 yystype         * current_frame;
672
673 {
674
675     sym_obj_entry_type          * obj_entry;
676     yystype                     * list_frame;
677
678 /*    Search the syntax stack for the list frame.    */
679     list_frame = sem_find_object (current_frame-1);
680     obj_entry = (sym_obj_entry_type *) list_frame->value.az_symbol_entry;
681
682 /*    Set the type for the list entry.  */
683     obj_entry->header.b_type = current_frame->b_type;
684
685 }
686
687 \f
688 /*
689 **++
690 **  FUNCTIONAL DESCRIPTION:
691 **
692 **      This routine sets the type in the stack entry for the (widget) object.
693 **
694 **  FORMAL PARAMETERS:
695 **
696 **      current_frame           address of the current syntax stack frame
697 **
698 **  IMPLICIT INPUTS:
699 **
700 **      none
701 **
702 **  IMPLICIT OUTPUTS:
703 **
704 **      none
705 **
706 **  FUNCTION VALUE:
707 **
708 **      void
709 **
710 **  SIDE EFFECTS:
711 **
712 **      none
713 **
714 **--
715 **/
716
717 void            sar_set_object_class
718                         ( current_frame )
719
720 yystype         * current_frame;
721
722 {
723
724     sym_obj_entry_type          * obj_entry;
725     yystype                     * object_frame;
726
727 /*    Search the syntax stack for the object frame.    */
728     object_frame = sem_find_object (current_frame-1);
729     obj_entry = (sym_obj_entry_type *) object_frame->value.az_symbol_entry;
730
731 /*    Set the type for the object entry.        */
732     obj_entry->header.b_type =
733         current_frame->value.az_keyword_entry->b_subclass;
734
735 /*    
736 **  Indicate in compression table that this object type is used.
737 **  Note that user defined widgets don't get compression code entires.
738 **  We always identify user defined widgets as MrmwcUnknown.
739 */
740     if ( obj_entry->header.b_type != uil_sym_user_defined_object )
741         uil_widget_compr[obj_entry->header.b_type] = 1;
742
743 }
744
745 \f
746 /*
747 **++
748 **  FUNCTIONAL DESCRIPTION:
749 **
750 **      This routine sets the variant in the stack entry for the object.
751 **
752 **  FORMAL PARAMETERS:
753 **
754 **      current_frame           address of the current syntax stack frame
755 **
756 **  IMPLICIT INPUTS:
757 **
758 **      none
759 **
760 **  IMPLICIT OUTPUTS:
761 **
762 **      none
763 **
764 **  FUNCTION VALUE:
765 **
766 **      void
767 **
768 **  SIDE EFFECTS:
769 **
770 **      none
771 **
772 **--
773 **/
774
775 void            sar_set_object_variant
776                         ( current_frame )
777
778 yystype         * current_frame;
779
780 {
781
782     sym_obj_entry_type          * obj_entry;
783     yystype                     * object_frame;
784
785 /*    Search the syntax stack for the object frame.    */
786
787     object_frame = sem_find_object (current_frame - 1);
788     obj_entry = (sym_obj_entry_type *) object_frame->value.az_symbol_entry;
789
790 /*    Set the variant for the object entry.     */
791
792     switch (current_frame->b_type)
793         {
794
795 /*    Use the module default for this object type.   */
796         case 0:
797             {
798             unsigned int        obj_type;
799
800             /*
801              * Pick up gadget variant (or widget variant) as specified
802              * by the module tables and the gadget variants
803              */
804             obj_type = obj_entry->header.b_type;
805             if (uil_urm_variant[obj_type] == sym_k_gadget_entry)
806                 {
807                 obj_entry->obj_header.b_flags |= sym_m_obj_is_gadget;
808                 obj_entry->header.b_type = uil_gadget_variants [obj_type];
809                 }
810
811             break;
812             }
813
814         case sym_k_widget_entry:
815             break;
816
817         case sym_k_gadget_entry:
818             {
819             unsigned int        obj_type;
820
821             /*
822              * Check if gadgets are supported for this object type.
823              * If so, change the object type to the matching code for
824              * the widget class which is the gadget.
825              */
826             obj_type = obj_entry->header.b_type;
827             if (uil_gadget_variants[obj_type] == 0)
828                 {
829                 yystype         * source_frame;
830
831                 source_frame = & yylval;
832                 diag_issue_diagnostic
833                     (d_gadget_not_sup,
834                      _sar_source_position (source_frame ),
835                      diag_object_text(obj_type),
836                      diag_object_text(obj_type) );
837                 }
838             else
839                 {
840                 obj_entry->obj_header.b_flags |= sym_m_obj_is_gadget;
841                 obj_entry->header.b_type = uil_gadget_variants [obj_type];
842                 }
843
844             break;
845             }
846
847         default:
848             _assert (FALSE, "unexpected variant type");
849             break;
850         }
851
852     /*
853     ** If this object is a gadget, mark that gadgets of this type have been
854     ** used so we can later assign it a compression code. This is a safety
855     ** set against the actual widget class.
856     */
857
858     if ((obj_entry->obj_header.b_flags & sym_m_obj_is_gadget) != 0)
859         uil_widget_compr[obj_entry->header.b_type] = 1;
860
861 }
862
863 \f
864 /*
865 **++
866 **  FUNCTIONAL DESCRIPTION:
867 **
868 **      This routine finds the object frame on the parse stack.
869 **
870 **  FORMAL PARAMETERS:
871 **
872 **      current_frame           address of the current parse stack frame.
873 **
874 **  IMPLICIT INPUTS:
875 **
876 **      none
877 **
878 **  IMPLICIT OUTPUTS:
879 **
880 **      none
881 **
882 **  FUNCTION VALUE:
883 **
884 **      address of the parse stack frame for this object.
885 **
886 **  SIDE EFFECTS:
887 **
888 **      none
889 **
890 **--
891 **/
892
893 yystype         * sem_find_object ( current_frame )
894
895 yystype         * current_frame;
896
897 {
898
899     yystype     * object_frame;
900
901     object_frame = current_frame;
902
903 /*    Search the syntax stack for the object frame.    */
904
905     while ( (object_frame->b_tag != sar_k_object_frame) &&
906             (object_frame->b_tag != sar_k_module_frame) )
907         object_frame--;
908
909     if (object_frame->b_tag != sar_k_object_frame)
910         _assert (FALSE, "missing object frame on the parser stack");
911
912    return (object_frame);
913
914 }
915 \f
916 /*
917 **++
918 **  FUNCTIONAL DESCRIPTION:
919 **
920 **      This routine processes a reference to an object in the
921 **      UIL.  The reference may be a forward reference.
922 **
923 **  FORMAL PARAMETERS:
924 **
925 **      ref_frame               address of the parse stack frame for
926 **                              the object reference.
927 **
928 **  IMPLICIT INPUTS:
929 **
930 **      none
931 **
932 **  IMPLICIT OUTPUTS:
933 **
934 **      none
935 **
936 **  FUNCTION VALUE:
937 **
938 **      none
939 **
940 **  SIDE EFFECTS:
941 **
942 **      none
943 **
944 **--
945 **/
946
947 void            sar_object_reference ( ref_frame )
948 yystype         * ref_frame;
949
950 {
951     yystype                     * obj_frame;
952     sym_obj_entry_type          * obj_entry;
953     sym_name_entry_type         * ref_name;
954     sym_obj_entry_type          * ref_entry;
955     sym_value_entry_type        * ref_value;
956     boolean                     invalid_ref;
957
958     yystype                     * source_frame;
959
960     source_frame = & yylval;
961
962 /*    Search the syntax stack for the object frame.    */
963
964     obj_frame = sem_find_object (ref_frame - 1);
965     obj_entry = (sym_obj_entry_type *) obj_frame->value.az_symbol_entry;
966     ref_name = (sym_name_entry_type *) ref_frame->value.az_symbol_entry;
967     ref_value = (sym_value_entry_type *) ref_name->az_object;
968     ref_entry = (sym_obj_entry_type *) ref_name->az_object;
969
970 /*    Check if this name was previously defined for a different usage.  */
971
972     if (ref_entry != NULL)
973         {
974         if ( ref_entry->header.b_tag==sym_k_widget_entry ||
975              ref_entry->header.b_tag==sym_k_gadget_entry ||
976              ref_entry->header.b_tag==sym_k_child_entry )
977             invalid_ref =
978                 (ref_entry->header.b_tag!=obj_entry->header.b_tag) ||
979                 ((ref_entry->header.b_type!=obj_entry->header.b_type) &&
980                  (uil_gadget_variants[ref_entry->header.b_type]!=
981                   obj_entry->header.b_type) &&
982                  (uil_gadget_variants[obj_entry->header.b_type]!=
983                   ref_entry->header.b_type));
984         else
985             invalid_ref =
986                 (ref_entry->header.b_tag!=obj_entry->header.b_tag) ||
987                 (ref_entry->header.b_type!=obj_entry->header.b_type);
988         
989         if ( invalid_ref )
990             {
991
992             char        * expected_type, * found_type;
993
994             if (ref_entry->header.b_tag == sym_k_list_entry)
995                 found_type = diag_tag_text (ref_entry->header.b_type);
996             else if (ref_entry->header.b_tag == sym_k_widget_entry)
997                 found_type = diag_object_text (ref_entry->header.b_type);
998             else if (ref_entry->header.b_tag == sym_k_gadget_entry)
999                 found_type = diag_object_text (ref_entry->header.b_type);
1000             else if (ref_entry->header.b_tag == sym_k_value_entry)
1001                 found_type = diag_value_text
1002                     (((sym_value_entry_type *) ref_entry)->b_type);
1003             else
1004                 found_type = "";
1005
1006             if (obj_entry->header.b_tag == sym_k_list_entry)
1007                 expected_type =
1008                     diag_tag_text (obj_entry->header.b_type);
1009             else
1010                 expected_type =
1011                     diag_object_text (obj_entry->header.b_type);
1012
1013             diag_issue_diagnostic
1014                 ( d_obj_type,
1015                   _sar_source_position ( source_frame ),
1016                   found_type,
1017                   diag_tag_text (ref_entry->header.b_tag),
1018                   expected_type,
1019                   diag_tag_text (obj_entry->header.b_tag) );
1020
1021             obj_entry->header.b_tag = sym_k_error_entry;
1022
1023             return;
1024             }
1025         }
1026
1027     switch (obj_entry->header.b_tag)
1028         {
1029
1030         case sym_k_list_entry:
1031             {
1032
1033     /*   Add this entry to the list.  A copy of the list will be made.    */
1034
1035             if ((ref_value != 0) && 
1036                 ((ref_value->obj_header.b_flags & sym_m_forward_ref) == 0))
1037                 {
1038                 ref_frame->value.az_symbol_entry = (sym_entry_type *)ref_entry;
1039                 sar_add_list_entry (ref_frame);
1040                 }
1041             else
1042                 sar_add_forward_list_entry (ref_frame);
1043             
1044             break;
1045             }
1046
1047         case sym_k_gadget_entry:
1048         case sym_k_widget_entry:
1049             {
1050             int         make_fwd_ref;
1051
1052     /*    Mark the widget as referenced.        */
1053
1054             ref_name->b_flags |= sym_m_referenced;
1055
1056     /*    Mark the referencing object       */
1057
1058         obj_entry->obj_header.b_flags |= sym_m_obj_is_reference;
1059
1060     /*    Forward references are allowed for widgets or gadgets.  */
1061
1062             if (ref_entry == NULL)
1063                 make_fwd_ref = TRUE;
1064             else
1065                 {
1066
1067     /*   A widget can reference itself; treat it as a forward reference. */
1068
1069                 if (ref_entry->obj_header.b_flags & sym_m_def_in_progress)
1070                     make_fwd_ref = TRUE;
1071                 else
1072                     make_fwd_ref = FALSE;
1073                 }
1074
1075             if (make_fwd_ref)
1076                 {
1077                 /*    Add forward reference entry for this widget.      */
1078
1079                 sym_make_forward_ref
1080                     (ref_frame,
1081                      obj_entry->header.b_type,
1082                      (char*)& obj_entry->obj_header.az_reference );
1083                 }
1084             else
1085                 {
1086                 /*   Save this reference in the widget. */
1087                 
1088                 obj_entry->obj_header.az_reference = (sym_entry_type *)ref_entry;
1089                 }
1090             
1091             break;
1092             }
1093
1094         default:
1095             {
1096             _assert (FALSE, "unexpected object reference type");
1097             break;
1098             }
1099         }
1100
1101 }
1102 \f
1103 /*
1104 **++
1105 **  FUNCTIONAL DESCRIPTION:
1106 **
1107 **      This routine updates the parent list of every object in the controls
1108 **      list(s) for this object.  Parent lists are required in order to check
1109 **      constraint arguments.
1110 **
1111 **  FORMAL PARAMETERS:
1112 **
1113 **      control_list_frame              address of the parse stack frame for
1114 **                                              the control list.
1115 **
1116 **  IMPLICIT INPUTS:
1117 **
1118 **      none
1119 **
1120 **  IMPLICIT OUTPUTS:
1121 **
1122 **      none
1123 **
1124 **  FUNCTION VALUE:
1125 **
1126 **      none
1127 **
1128 **  SIDE EFFECTS:
1129 **
1130 **      none
1131 **
1132 **--
1133 **/
1134
1135 void            sar_update_parent_list
1136                         ( control_list_frame )
1137
1138 yystype         * control_list_frame;
1139
1140 {
1141     yystype                     * widget_frame;
1142     sym_widget_entry_type       * widget_entry;
1143     sym_list_entry_type * control_list_entry;
1144
1145 /* Search the syntax stack for the widget frame. */
1146
1147     widget_frame = sem_find_object (control_list_frame - 1);
1148     widget_entry = (sym_widget_entry_type *)
1149                         widget_frame->value.az_symbol_entry;
1150
1151     _assert (widget_entry->header.b_tag == sym_k_widget_entry ||
1152              widget_entry->header.b_tag == sym_k_gadget_entry ||
1153              widget_entry->header.b_tag == sym_k_child_entry,
1154              "widget missing from the stack");
1155
1156 /* Get the control_list entry from the widget */
1157
1158     control_list_entry = (sym_list_entry_type *) 
1159                         control_list_frame->value.az_symbol_entry;
1160
1161     _assert ((control_list_entry->header.b_tag == sym_k_list_entry ||
1162               control_list_entry->header.b_tag == sym_k_error_entry),
1163              "list entry missing");
1164
1165 /* The control list contains control list entries as well as nested lists,
1166 ** which in turn contain list entries and nested lists.
1167 ** We need to call a recursive routine to traverse all the entries.
1168 */
1169
1170     parent_list_traverse(widget_entry, control_list_entry);
1171
1172 }
1173
1174 \f
1175 /*
1176 **++
1177 **  FUNCTIONAL DESCRIPTION:
1178 **
1179 **      This routine recursively traverses a control_list.  Control lists
1180 **      may contain control list entries as well as nested control lists.
1181 **      
1182 **      This routine also updates the parent list of every object in the 
1183 **      controls list(s) for this object.  Parent lists are required in order 
1184 **      to check constraint arguments.
1185 **
1186 **  FORMAL PARAMETERS:
1187 **
1188 **      widget_entry                    the widget to be entered in lists
1189 **      control_list_entry              A control_list or nested control list
1190 **                                      
1191 **
1192 **  IMPLICIT INPUTS:
1193 **
1194 **      none
1195 **
1196 **  IMPLICIT OUTPUTS:
1197 **
1198 **      none
1199 **
1200 **  FUNCTION VALUE:
1201 **
1202 **      none
1203 **
1204 **  SIDE EFFECTS:
1205 **
1206 **      none
1207 **
1208 **--
1209 **/
1210
1211 void parent_list_traverse (widget_entry, control_list_entry)
1212     sym_widget_entry_type       *widget_entry;
1213     sym_list_entry_type         *control_list_entry;
1214
1215 {
1216 sym_obj_entry_type              *control_list_member;
1217 sym_control_entry_type          *control_entry;
1218 sym_nested_list_entry_type      *nested_control_list_entry;
1219 sym_widget_entry_type           *control_widget;
1220 int                             found;
1221 sym_forward_ref_entry_type      *fwd_ref_entry;
1222 sym_parent_list_type            *parent_node;
1223 sym_parent_list_type            *parent_ptr;
1224
1225
1226     for (control_list_member = (sym_obj_entry_type *)control_list_entry ->
1227                                         obj_header.az_next;
1228         control_list_member != NULL;
1229         control_list_member = (sym_obj_entry_type *)control_list_member ->
1230                                         obj_header.az_next)
1231         {
1232         switch (control_list_member->header.b_tag)
1233             {
1234             case sym_k_nested_list_entry:
1235                 nested_control_list_entry = (sym_nested_list_entry_type *)
1236                         control_list_member;
1237                 /* Begin fixing DTS 9497 */
1238                 if(nested_control_list_entry->az_list)
1239                        parent_list_traverse (widget_entry,
1240                                       nested_control_list_entry->az_list);
1241                 /* End fixing DTS 9497 */
1242                 break;
1243             case sym_k_control_entry:
1244                 control_entry = (sym_control_entry_type *) control_list_member;
1245
1246 /*  Get a pointer to one of the actual widgets in the control list */
1247
1248                 control_widget =  control_entry->az_con_obj;
1249
1250 /*
1251 **  If it's a widget reference, go find it.  If you can't find it, it must
1252 **  be a forward reference.  If so, find the forward reference entry for it
1253 **  and update it with a pointer to its parent.
1254 */
1255     
1256                 if ( control_widget->
1257                         obj_header.b_flags & sym_m_obj_is_reference)
1258                     if ( control_widget->obj_header.az_reference == NULL )
1259                         {
1260
1261 /*  Forward reference. Update forward reference entry. */
1262
1263                         found = FALSE;
1264                         for (fwd_ref_entry = sym_az_forward_ref_chain;
1265                             ((fwd_ref_entry != NULL) && (found == FALSE));
1266                             fwd_ref_entry = fwd_ref_entry->az_next_ref)
1267                             {
1268                             if (fwd_ref_entry->a_update_location ==
1269                                 (char *) & control_widget->
1270                                 obj_header.az_reference)
1271                                 {
1272                                 found = TRUE;
1273                                 fwd_ref_entry->parent = widget_entry;
1274                                 }
1275                             }            
1276                         }
1277                     else
1278                         {
1279 /*  A widget reference, but already defined.  Go update its entry. */
1280
1281                         control_widget = (sym_widget_entry_type *)
1282                             control_widget->obj_header.az_reference;
1283                         found = FALSE;
1284                         for (parent_ptr = control_widget->parent_list;
1285                             ((parent_ptr != NULL) && (found == FALSE));
1286                             parent_ptr = parent_ptr->next)
1287                             {
1288                             if (parent_ptr->parent == widget_entry)
1289                                 found = TRUE;
1290                             }
1291                         if (found == FALSE)
1292                             {
1293                             parent_node = (sym_parent_list_type *) 
1294                                 sem_allocate_node (sym_k_parent_list_entry, 
1295                                                    sym_k_parent_list_size);
1296                             parent_node->next = control_widget->parent_list;
1297                             control_widget->parent_list = parent_node;
1298                             parent_node->parent = widget_entry;
1299                             }
1300                         }
1301                 else
1302                     {
1303 /*  An inline widget definition.  Go update its entry. */
1304
1305                     found = FALSE;
1306                     for (parent_ptr = control_widget->parent_list;
1307                         ((parent_ptr != NULL) && (found == FALSE));
1308                         parent_ptr = parent_ptr->next)
1309                         {
1310                         if (parent_ptr->parent == widget_entry)
1311                             found = TRUE;
1312                         }
1313                     if (found == FALSE)
1314                         {
1315                         parent_node = (sym_parent_list_type *) 
1316                             sem_allocate_node (sym_k_parent_list_entry,
1317                                                sym_k_parent_list_size);
1318                         parent_node->next = control_widget->parent_list;
1319                         control_widget->parent_list = parent_node;
1320                         parent_node->parent = widget_entry;
1321                         }
1322                     }
1323                 }
1324             }
1325
1326 }
1327
1328 \f
1329 /*
1330 **++
1331 **  FUNCTIONAL DESCRIPTION:
1332 **
1333 **      This routine saves a widget feature in the widget symbol node.
1334 **
1335 **  FORMAL PARAMETERS:
1336 **
1337 **      feature_frame           address of the parse stack frame for
1338 **                              the widget feature.
1339 **
1340 **  IMPLICIT INPUTS:
1341 **
1342 **      none
1343 **
1344 **  IMPLICIT OUTPUTS:
1345 **
1346 **      none
1347 **
1348 **  FUNCTION VALUE:
1349 **
1350 **      none
1351 **
1352 **  SIDE EFFECTS:
1353 **
1354 **      none
1355 **
1356 **--
1357 **/
1358
1359 void            sar_save_feature
1360                         ( feature_frame )
1361
1362 yystype         * feature_frame;
1363
1364 {
1365     yystype                     * widget_frame;
1366     sym_widget_entry_type       * widget_entry;
1367     sym_entry_type              * feature_entry;
1368     sym_entry_type              * * ptr;
1369
1370     yystype                     * source_frame;
1371
1372     source_frame = & yylval;
1373
1374 /*    Search the syntax stack for the widget frame.    */
1375
1376     widget_frame = sem_find_object (feature_frame - 1);
1377     widget_entry = (sym_widget_entry_type *)
1378                         widget_frame->value.az_symbol_entry;
1379
1380     _assert (widget_entry->header.b_tag == sym_k_widget_entry ||
1381              widget_entry->header.b_tag == sym_k_gadget_entry ||
1382              widget_entry->header.b_tag == sym_k_child_entry,
1383              "widget missing from the stack");
1384
1385     feature_entry = feature_frame->value.az_symbol_entry;
1386
1387     _assert ((feature_entry->header.b_tag == sym_k_list_entry ||
1388               feature_entry->header.b_tag == sym_k_error_entry),
1389              "list entry missing");
1390
1391     switch (feature_entry->header.b_type)
1392         {
1393
1394         case sym_k_argument_entry:
1395             ptr = (sym_entry_type * *) & widget_entry->az_arguments;
1396             break;
1397
1398         case sym_k_control_entry:
1399             ptr = (sym_entry_type * *) & widget_entry->az_controls;
1400             break;
1401
1402         case sym_k_callback_entry:
1403             ptr = (sym_entry_type * *) & widget_entry->az_callbacks;
1404             break;
1405
1406         case sym_k_error_entry:
1407             return;
1408
1409         default:
1410             _assert (FALSE, "unexpected widget feature");
1411             break;
1412         }
1413
1414 /*      Check for duplicate features.   */
1415
1416     if (* ptr != NULL)
1417         {
1418         diag_issue_diagnostic
1419                 ( d_dup_list,
1420                   _sar_source_position ( source_frame ),
1421                   diag_tag_text (feature_entry->header.b_type),
1422                   diag_tag_text (feature_entry->header.b_tag),
1423                   diag_object_text (widget_entry->header.b_type),
1424                   diag_tag_text (widget_entry->header.b_tag) );
1425
1426         return;
1427         }
1428
1429 /*      Save the feature in the widget. */
1430
1431     (* ptr) = feature_entry;
1432
1433 /*      Clear the feature frame from the stack. */
1434
1435     feature_frame->b_tag = sar_k_null_frame;
1436
1437 }
1438 \f
1439 /*
1440 **++
1441 **  FUNCTIONAL DESCRIPTION:
1442 **
1443 **      This routine processes an argument pair for an object.
1444 **
1445 **  FORMAL PARAMETERS:
1446 **
1447 **      argument_frame          address of the parse stack frame for
1448 **                              the argument reference.
1449 **
1450 **      value_frame             address of the parse stack frame for
1451 **                              the argument value.
1452 **
1453 **      equals_frame            address of the parse stack frame for the
1454 **                              equals sign.
1455 **
1456 **  IMPLICIT INPUTS:
1457 **
1458 **      none
1459 **
1460 **  IMPLICIT OUTPUTS:
1461 **
1462 **      none
1463 **
1464 **  FUNCTION VALUE:
1465 **
1466 **      none
1467 **
1468 **  SIDE EFFECTS:
1469 **
1470 **      none
1471 **
1472 **--
1473 **/
1474 void            sar_save_argument_pair
1475                   ( argument_frame, value_frame, equals_frame)
1476
1477 yystype         * argument_frame;
1478 yystype         * value_frame;
1479 yystype         * equals_frame;
1480
1481 {
1482
1483     yystype                     * object_frame;
1484     sym_argument_entry_type     * arg_entry;
1485     sym_list_entry_type         * list_entry;
1486     sym_value_entry_type        * val_value_entry;
1487     sym_value_entry_type        * arg_value_entry;
1488     unsigned char               actual_tag;
1489
1490     yystype                     * source_frame;
1491
1492
1493     source_frame = & yylval;
1494
1495 /*    Search the syntax stack for the object frame.    */
1496
1497     object_frame = sem_find_object (argument_frame - 1);
1498
1499     list_entry = (sym_list_entry_type *)
1500                         object_frame->value.az_symbol_entry;
1501
1502     _assert (list_entry->header.b_tag == sym_k_list_entry,
1503              "list entry missing");
1504
1505     arg_value_entry =
1506         (sym_value_entry_type *) argument_frame->value.az_symbol_entry;
1507
1508     _assert (arg_value_entry->header.b_tag == sym_k_value_entry,
1509              "argument value entry missing");
1510
1511     /*
1512     **  Save the source information (?)
1513     */
1514
1515     _sar_save_source_info ( &arg_value_entry->header , argument_frame , 
1516         argument_frame );
1517
1518     val_value_entry = (sym_value_entry_type *) value_frame->value.az_symbol_entry;
1519     actual_tag = val_value_entry->header.b_tag;
1520
1521 /*    Create and fill in the argument node.    */
1522
1523     arg_entry = (sym_argument_entry_type *) sem_allocate_node (
1524                         sym_k_argument_entry, sym_k_argument_entry_size);
1525
1526     /*
1527     ** If the argument is a forward reference, we'll patch in the
1528     ** address of the the referenced arg between passes.  Otherwise,
1529     ** just point to the referenced arg node.
1530     */
1531
1532     if ((argument_frame->b_flags & sym_m_forward_ref) != 0)
1533         sym_make_value_forward_ref (argument_frame, 
1534         (char*)&(arg_entry->az_arg_name), sym_k_patch_add);
1535     else
1536         arg_entry->az_arg_name =
1537             (sym_value_entry_type *) argument_frame->value.az_symbol_entry;
1538
1539     /*
1540     ** If the argument value is a forward reference, we'll patch in the
1541     ** address of the the referenced arg value between passes.  Otherwise,
1542     ** just point to the referenced arg value node.
1543     */
1544
1545     if ((value_frame->b_flags & sym_m_forward_ref) != 0)
1546         sym_make_value_forward_ref (value_frame, 
1547         (char*)&(arg_entry->az_arg_value), sym_k_patch_add);
1548     else
1549         arg_entry->az_arg_value = val_value_entry;
1550
1551     argument_frame->b_tag = sar_k_null_frame;
1552     argument_frame->value.az_symbol_entry = (sym_entry_type *) arg_entry;
1553
1554
1555 }
1556 \f
1557 /*
1558 **++
1559 **  FUNCTIONAL DESCRIPTION:
1560 **
1561 **  This routine processes a reason to procedure or procedure list binding 
1562 **  for a callback object in UIL.
1563 **
1564 **  FORMAL PARAMETERS:
1565 **
1566 **      reason_frame                address of the parse stack frame for
1567 **                                              the reason reference.
1568 **
1569 **      proc_ref_frame              address of the parse stack frame for
1570 **                                              the procedure reference.
1571 **
1572 **      equals_frame                address if the parse stack frame for
1573 **                                              the equals sign.
1574 **
1575 **  IMPLICIT INPUTS:
1576 **
1577 **      none
1578 **
1579 **  IMPLICIT OUTPUTS:
1580 **
1581 **      none
1582 **
1583 **  FUNCTION VALUE:
1584 **
1585 **      none
1586 **
1587 **  SIDE EFFECTS:
1588 **
1589 **      none
1590 **
1591 **--
1592 **/
1593
1594 void            sar_save_reason_binding
1595                         ( reason_frame, proc_ref_frame, equals_frame )
1596
1597 yystype         * reason_frame;
1598 yystype         * proc_ref_frame;
1599 yystype         * equals_frame;
1600
1601 {
1602
1603     yystype                     * object_frame;
1604     sym_callback_entry_type     * callback_entry;
1605     sym_list_entry_type         * list_entry;
1606     yystype                     * source_frame;
1607
1608     source_frame = & yylval;
1609
1610 /*    Search the syntax stack for the object frame.    */
1611
1612     object_frame = sem_find_object (reason_frame - 1);
1613
1614     list_entry = (sym_list_entry_type *) object_frame->value.az_symbol_entry;
1615
1616     _assert (list_entry->header.b_tag == sym_k_list_entry,
1617              "list entry missing");
1618
1619     /*
1620     ** Create and fill in the callback node.
1621     */
1622
1623     callback_entry = (sym_callback_entry_type *) sem_allocate_node (
1624                         sym_k_callback_entry, sym_k_callback_entry_size);
1625
1626     /*
1627     ** If the reason is a forward reference, we'll patch in the
1628     ** address of the the referenced reason between passes.  Otherwise,
1629     ** just point to the referenced reason node.
1630     */
1631
1632     if ((reason_frame->b_flags & sym_m_forward_ref) != 0)
1633         sym_make_value_forward_ref (reason_frame,
1634         (char*)&(callback_entry->az_call_reason_name), sym_k_patch_add);
1635     else
1636         callback_entry->az_call_reason_name =
1637             (sym_value_entry_type *) reason_frame->value.az_symbol_entry;
1638
1639
1640     /*
1641     ** Save source information
1642     */
1643 /*    _sar_save_source_info ( &reason_value_entry->header , reason_frame , 
1644 **      reason_frame );
1645 */
1646
1647     /*
1648     **    Note that proc_ref_frame may point to either a procedure reference
1649     **    or to a list of procedure reference nodes
1650     */
1651
1652     if (  proc_ref_frame->b_type == sym_k_list_entry)
1653         callback_entry->az_call_proc_ref_list =
1654                 (sym_list_entry_type *) proc_ref_frame->value.az_symbol_entry;
1655     else
1656         callback_entry->az_call_proc_ref =
1657             (sym_proc_ref_entry_type *) proc_ref_frame->value.az_symbol_entry;
1658
1659     reason_frame->b_tag = sar_k_null_frame;
1660     reason_frame->value.az_symbol_entry = (sym_entry_type *) callback_entry;
1661
1662 }
1663 \f
1664 /*
1665 **++
1666 **  FUNCTIONAL DESCRIPTION:
1667 **
1668 **    This routine processes a control clause.
1669 **
1670 **  FORMAL PARAMETERS:
1671 **
1672 **   managed_frame              address of the parse stack frame for
1673 **                              the managed flag for this control.
1674 **
1675 **   item_frame                 address of the parse stack frame for
1676 **                              the control item object.
1677 **
1678 **  IMPLICIT INPUTS:
1679 **
1680 **      none
1681 **
1682 **  IMPLICIT OUTPUTS:
1683 **
1684 **      none
1685 **
1686 **  FUNCTION VALUE:
1687 **
1688 **      none
1689 **
1690 **  SIDE EFFECTS:
1691 **
1692 **      none
1693 **
1694 **--
1695 **/
1696
1697 void            sar_save_control_item
1698                         ( managed_frame, item_frame )
1699
1700 yystype         * managed_frame;
1701 yystype         * item_frame;
1702
1703 {
1704
1705     yystype                     * object_frame;
1706     sym_control_entry_type      * control_entry;
1707     sym_list_entry_type         * list_entry;
1708     yystype                     * source_frame;
1709
1710     source_frame = & yylval;
1711
1712 /*    Search the syntax stack for the object frame.    */
1713
1714     object_frame = sem_find_object (managed_frame - 1);
1715
1716     list_entry =
1717         (sym_list_entry_type *) object_frame->value.az_symbol_entry;
1718
1719     _assert (list_entry->header.b_tag == sym_k_list_entry,
1720              "list entry missing");
1721
1722 /*      Verify that this type of item is allowed on this list.  */
1723
1724     if (list_entry->header.b_type != sym_k_control_entry)
1725         {
1726         diag_issue_diagnostic
1727             ( d_list_item,
1728              _sar_source_position ( source_frame ),
1729              diag_tag_text (sym_k_control_entry),
1730              diag_tag_text (list_entry->header.b_type),
1731              diag_tag_text (list_entry->header.b_tag) );
1732         
1733         return;
1734         }
1735
1736 /*    Create and fill in the control node.    */
1737
1738     control_entry = (sym_control_entry_type *) sem_allocate_node (
1739                         sym_k_control_entry, sym_k_control_entry_size);
1740
1741     control_entry->az_con_obj =
1742         (sym_widget_entry_type *) item_frame->value.az_symbol_entry;
1743
1744     control_entry->obj_header.b_flags = ( item_frame->b_flags |
1745                                               managed_frame->b_flags );
1746
1747     managed_frame->b_tag =
1748     item_frame->b_tag = sar_k_null_frame;
1749
1750     managed_frame->value.az_symbol_entry = (sym_entry_type *) control_entry;
1751
1752 }
1753 \f
1754 /*
1755 **++
1756 **  FUNCTIONAL DESCRIPTION:
1757 **
1758 **    This routine processes a control clause when an id is created in that
1759 **    clause.
1760 **
1761 **  FORMAL PARAMETERS:
1762 **
1763 **   control_frame              address of the parse stack frame for
1764 **                              the control list.
1765 **
1766 **   item_frame                 address of the parse stack frame for
1767 **                              the control item id.
1768 **
1769 **  IMPLICIT INPUTS:
1770 **
1771 **      none
1772 **
1773 **  IMPLICIT OUTPUTS:
1774 **
1775 **      none
1776 **
1777 **  FUNCTION VALUE:
1778 **
1779 **      none
1780 **
1781 **  SIDE EFFECTS:
1782 **
1783 **      none
1784 **
1785 **--
1786 **/
1787
1788 void            sar_save_control_widget
1789                         ( control_frame, item_frame )
1790
1791 yystype         * control_frame;
1792 yystype         * item_frame;
1793
1794 {
1795
1796     yystype                     * object_frame;
1797     sym_control_entry_type      * control_entry;
1798     sym_list_entry_type         * list_entry;
1799     yystype                     * source_frame;
1800     yystype                     temp_frame;
1801
1802     /*
1803     **  move the item_frame to the control_frame and
1804     **  the control_frame to the null_frame. This is done
1805     **  because the item_frame needs to be second in the list
1806     */
1807
1808     temp_frame = *item_frame;
1809     *item_frame = *control_frame;
1810     *control_frame = temp_frame;
1811
1812     source_frame = & yylval;
1813
1814 /*    Search the syntax stack for the object frame.    */
1815
1816     object_frame = sem_find_object (control_frame - 1);
1817
1818     list_entry =
1819         (sym_list_entry_type *) object_frame->value.az_symbol_entry;
1820
1821     _assert (list_entry->header.b_tag == sym_k_list_entry,
1822              "list entry missing");
1823
1824 /*      Verify that this type of item is allowed on this list.  */
1825
1826     if (list_entry->header.b_type != sym_k_control_entry)
1827         {
1828         diag_issue_diagnostic
1829             ( d_list_item,
1830              _sar_source_position ( source_frame ),
1831              diag_tag_text (sym_k_control_entry),
1832              diag_tag_text (list_entry->header.b_type),
1833              diag_tag_text (list_entry->header.b_tag) );
1834         
1835         return;
1836         }
1837
1838 /*    Create and fill in the control node.    */
1839
1840     control_entry = (sym_control_entry_type *) sem_allocate_node
1841         (sym_k_control_entry, sym_k_control_entry_size);
1842
1843     control_entry->az_con_obj =
1844         (sym_widget_entry_type *) item_frame->value.az_symbol_entry;
1845
1846     control_entry->obj_header.b_flags = item_frame->b_flags;
1847
1848     control_frame->b_tag =
1849     item_frame->b_tag = sar_k_null_frame;
1850
1851     control_frame->value.az_symbol_entry = (sym_entry_type *) control_entry;
1852
1853 }
1854 \f
1855 /*
1856 **++
1857 **  FUNCTIONAL DESCRIPTION:
1858 **
1859 **      This routine saves the source for a user defined create procedure
1860 **
1861 **  FORMAL PARAMETERS:
1862 **
1863 **      procedure_frame         address of the parse stack frame for
1864 **                              the text "PROCEDURE".
1865 **
1866 **      proc_id_frame           address of the parse stack frame for
1867 **                              the procedure reference.
1868 **
1869 **      proc_arg_frame          address of the parse stack frame for
1870 **                              the procedure argument value.
1871 **
1872 **  IMPLICIT INPUTS:
1873 **
1874 **      none
1875 **
1876 **  IMPLICIT OUTPUTS:
1877 **
1878 **      none
1879 **
1880 **  FUNCTION VALUE:
1881 **
1882 **      none
1883 **
1884 **  SIDE EFFECTS:
1885 **
1886 **      none
1887 **
1888 **--
1889 **/
1890
1891 void            sar_save_user_proc_ref_src
1892                         ( procedure_frame, proc_id_frame, proc_arg_frame)
1893
1894 yystype         * procedure_frame;
1895 yystype         * proc_id_frame;
1896 yystype         * proc_arg_frame;
1897
1898 {
1899     sym_proc_ref_entry_type     * proc_ref_entry;
1900
1901     proc_ref_entry = (sym_proc_ref_entry_type *)proc_id_frame->value.az_symbol_entry;
1902
1903     /*
1904     ** If the parameter arg clause was ommitted the source info should be null.
1905     ** We want to save the source for the "args" if it is there.
1906     */
1907     _sar_save_source_info (& proc_ref_entry->header, procedure_frame, proc_arg_frame );
1908
1909 }
1910 \f
1911 /*
1912 **++
1913 **  FUNCTIONAL DESCRIPTION:
1914 **
1915 **      This routine processes a procedure reference.
1916 **
1917 **  FORMAL PARAMETERS:
1918 **
1919 **      proc_id_frame           address of the parse stack frame for
1920 **                              the procedure reference.
1921 **
1922 **      proc_arg_frame          address of the parse stack frame for
1923 **                              the procedure argument value.
1924 **
1925 **      context                 indicates whether this is a callback
1926 **                              or a user-defined procedure reference.
1927 **
1928 **  IMPLICIT INPUTS:
1929 **
1930 **      none
1931 **
1932 **  IMPLICIT OUTPUTS:
1933 **
1934 **      none
1935 **
1936 **  FUNCTION VALUE:
1937 **
1938 **      none
1939 **
1940 **  SIDE EFFECTS:
1941 **
1942 **      none
1943 **
1944 **--
1945 **/
1946
1947 void            sar_process_proc_ref
1948                         ( proc_id_frame, proc_arg_frame, context )
1949
1950 yystype         * proc_id_frame;
1951 yystype         * proc_arg_frame;
1952 int             context;
1953
1954 {
1955
1956 /*    Call the common routine to get the procedure reference node, and
1957       return it in the stack frame.     */
1958
1959     proc_id_frame->value.az_symbol_entry = (sym_entry_type *)
1960                 sem_reference_procedure (
1961                         proc_id_frame, proc_arg_frame,
1962                         context );
1963
1964 /*    If this is the create proc for a user_defined widget, save it
1965       in the object node.       */
1966
1967     if (context == sym_k_object_proc)
1968         {
1969         yystype                 * widget_frame;
1970         sym_widget_entry_type   * widget_entry;
1971         
1972 /*    Search the syntax stack for the widget frame.  NOTE: gadgets can
1973               not have creation procedures; the grammar enforces this.     */
1974
1975         widget_frame = sem_find_object (proc_id_frame - 1);
1976         widget_entry =
1977             (sym_widget_entry_type *) widget_frame->value.az_symbol_entry;
1978         
1979         _assert (widget_entry->header.b_tag == sym_k_widget_entry,
1980                  "widget missing from the stack");
1981         
1982         if (widget_entry->header.b_type != uil_sym_user_defined_object)
1983             {
1984             yystype             * source_frame;
1985             
1986             source_frame = & yylval;
1987             diag_issue_diagnostic
1988                 (d_create_proc,
1989                  _sar_source_position ( source_frame ),
1990                  diag_object_text (widget_entry->header.b_type) );
1991             
1992             return;
1993             }
1994         else
1995             {
1996             widget_entry->az_create_proc =
1997                 (sym_proc_ref_entry_type *) proc_id_frame->value.az_symbol_entry;
1998             }
1999         
2000         }
2001
2002     return;    
2003
2004 }
2005 \f
2006 /*
2007 **++
2008 **  FUNCTIONAL DESCRIPTION:
2009 **
2010 **      This routine adds an entry to a list.
2011 **
2012 **  FORMAL PARAMETERS:
2013 **
2014 **      entry_frame             address of the parse stack frame for
2015 **                              the entry to be added to the list.
2016 **
2017 **  IMPLICIT INPUTS:
2018 **
2019 **      none
2020 **
2021 **  IMPLICIT OUTPUTS:
2022 **
2023 **      none
2024 **
2025 **  FUNCTION VALUE:
2026 **
2027 **      none
2028 **
2029 **  SIDE EFFECTS:
2030 **
2031 **      none
2032 **
2033 **--
2034 **/
2035
2036 void            sar_add_list_entry
2037                         ( entry_frame )
2038
2039 yystype         * entry_frame;
2040
2041 {
2042     yystype                     * list_frame;
2043     sym_list_entry_type         * list_entry;
2044     sym_obj_entry_type          * entry_entry;
2045
2046     yystype                     * source_frame;
2047
2048     source_frame = & yylval;
2049
2050 /*    Search the syntax stack for the list frame.    */
2051
2052     list_frame = sem_find_object (entry_frame - 1);
2053     list_entry = (sym_list_entry_type *) list_frame->value.az_symbol_entry;
2054
2055     _assert (list_entry->header.b_tag == sym_k_list_entry,
2056              "list entry missing");
2057
2058     entry_entry = (sym_obj_entry_type *) entry_frame->value.az_symbol_entry;
2059
2060     /*
2061     ** If we are including a list within a list, put a nested list entry
2062     ** in the list, and point it to the actual list.
2063     */
2064
2065     if  (entry_entry->header.b_tag == sym_k_list_entry)
2066         {
2067         sym_nested_list_entry_type      *nested_entry;
2068
2069         /*
2070         ** If this list is a reference to a previously defined list,
2071         ** then use the previously defined list.
2072         */
2073         if (entry_entry->obj_header.az_reference != NULL)
2074             {
2075             entry_entry = (sym_obj_entry_type *)
2076                 entry_entry->obj_header.az_reference;
2077             _assert (entry_entry->header.b_tag == sym_k_list_entry,
2078                      "entry list entry missing");
2079             }
2080
2081         /*
2082         ** Create a nested list entry to reference the nested list. This
2083         ** becomes the entry which will be added to the current list.
2084         */
2085         nested_entry = (sym_nested_list_entry_type *)
2086             sem_allocate_node (sym_k_nested_list_entry,
2087                                sym_k_nested_list_entry_size);
2088         nested_entry->header.b_type = entry_entry->header.b_type;
2089         nested_entry->az_list = (sym_list_entry_type *) entry_entry;
2090         entry_entry = (sym_obj_entry_type *) nested_entry;
2091         }
2092     else
2093         if (entry_entry->header.b_tag == sym_k_name_entry)
2094             {
2095             sym_nested_list_entry_type  *nested_entry;
2096             /*
2097             ** This is a forward reference to a named, nested list.
2098             */
2099             nested_entry = (sym_nested_list_entry_type *)
2100                 sem_allocate_node (sym_k_nested_list_entry,
2101                                    sym_k_nested_list_entry_size);
2102
2103             sym_make_value_forward_ref (entry_frame,
2104                 (char*)&(nested_entry->az_list),
2105                 sym_k_patch_list_add);
2106
2107             entry_entry = (sym_obj_entry_type *) nested_entry;
2108             }
2109
2110     /*
2111     ** Add the entry to front of the list
2112     ** The nested entry created above is included in this processing.
2113     */
2114     entry_entry->obj_header.az_next =
2115         (sym_entry_type *) list_entry->obj_header.az_next;
2116     list_entry->obj_header.az_next =
2117         (sym_entry_type *) entry_entry;
2118     list_entry->w_count++;
2119
2120     entry_frame->b_tag = sar_k_null_frame;
2121
2122 }
2123 \f
2124 /*
2125 **++
2126 **  FUNCTIONAL DESCRIPTION:
2127 **
2128 **      This routine adds a forward referenced list entry to a list.
2129 **      
2130 **
2131 **  FORMAL PARAMETERS:
2132 **
2133 **      entry_frame             address of the parse stack frame for
2134 **                              the entry to be added to the list.
2135 **
2136 **  IMPLICIT INPUTS:
2137 **
2138 **      none
2139 **
2140 **  IMPLICIT OUTPUTS:
2141 **
2142 **      none
2143 **
2144 **  FUNCTION VALUE:
2145 **
2146 **      none
2147 **
2148 **  SIDE EFFECTS:
2149 **
2150 **      none
2151 **
2152 **--
2153 **/
2154
2155 void            sar_add_forward_list_entry
2156                         ( entry_frame )
2157
2158 yystype         * entry_frame;
2159
2160 {
2161     yystype                     * list_frame;
2162     sym_list_entry_type         * list_entry;
2163     sym_obj_entry_type          * entry_entry;
2164     sym_name_entry_type         * name_entry;
2165     yystype                     * source_frame;
2166     sym_nested_list_entry_type  *nested_entry;
2167
2168     source_frame = & yylval;
2169
2170 /*    Search the syntax stack for the list frame.    */
2171
2172     list_frame = sem_find_object (entry_frame - 1);
2173     list_entry = (sym_list_entry_type *) list_frame->value.az_symbol_entry;
2174
2175     _assert (list_entry->header.b_tag == sym_k_list_entry,
2176              "list entry missing");
2177
2178     name_entry = (sym_name_entry_type *) entry_frame->value.az_symbol_entry;
2179
2180     nested_entry = (sym_nested_list_entry_type *)
2181         sem_allocate_node (sym_k_nested_list_entry,
2182                            sym_k_nested_list_entry_size);
2183
2184     sym_make_value_forward_ref (entry_frame,
2185         (char*)&(nested_entry->az_list),
2186         sym_k_patch_list_add);
2187
2188     entry_entry = (sym_obj_entry_type *) nested_entry;
2189
2190     /*
2191     ** Add the entry to front of the list
2192     ** The nested entry created above is included in this processing.
2193     */
2194     entry_entry->obj_header.az_next =
2195         (sym_entry_type *) list_entry->obj_header.az_next;
2196     list_entry->obj_header.az_next =
2197         (sym_entry_type *) entry_entry;
2198     list_entry->w_count++;
2199
2200     entry_frame->b_tag = sar_k_null_frame;
2201
2202 }
2203 \f
2204 /*
2205 **++
2206 **  FUNCTIONAL DESCRIPTION:
2207 **
2208 **      This routine verifies that the list or widget has been defined
2209 **      correctly. Virtually all such validation is actually done in pass 2.
2210 **
2211 **  FORMAL PARAMETERS:
2212 **
2213 **      current_frame           address of the current syntax stack frame
2214 **
2215 **  IMPLICIT INPUTS:
2216 **
2217 **      none
2218 **
2219 **  IMPLICIT OUTPUTS:
2220 **
2221 **      none
2222 **
2223 **  FUNCTION VALUE:
2224 **
2225 **      void
2226 **
2227 **  SIDE EFFECTS:
2228 **
2229 **      none
2230 **
2231 **--
2232 **/
2233
2234 void    sar_verify_object ( current_frame )
2235
2236 yystype                 * current_frame;
2237
2238 {
2239 yystype                         * obj_frame;
2240 sym_widget_entry_type           * widget_entry;
2241 unsigned int                    widget_type;
2242 sym_obj_entry_type              * obj_entry;
2243 yystype                         * source_frame;
2244
2245
2246
2247 /*
2248  * Search the syntax stack for the object frame.
2249  */
2250 source_frame = & yylval;
2251 obj_frame = sem_find_object (current_frame - 1);
2252 obj_entry = (sym_obj_entry_type *) obj_frame->value.az_symbol_entry;
2253
2254 switch (obj_entry->header.b_tag)
2255     {
2256     case sym_k_gadget_entry:
2257     case sym_k_widget_entry:
2258     
2259         /*
2260          * Clear the definition in progress bit.
2261          */
2262         _assert (obj_entry->obj_header.b_flags & sym_m_def_in_progress,
2263                  "widget definition not in progress");
2264         obj_entry->obj_header.b_flags &= (~ sym_m_def_in_progress);
2265         break;
2266     case sym_k_list_entry:
2267         /*
2268          * Clear the definition in progress bit and return.
2269          */
2270         _assert (obj_entry->obj_header.b_flags & sym_m_def_in_progress,
2271                  "list definition not in progress");
2272         obj_entry->obj_header.b_flags &= (~ sym_m_def_in_progress);
2273         return;
2274
2275     case sym_k_error_entry:
2276         return;
2277
2278     default:
2279         _assert (FALSE, "list or widget missing from the stack");
2280         break;
2281     }
2282
2283
2284 /*
2285  * If this is a user_defined widget, be sure the create proc was
2286  * specified if this is a declaration, and not specified if it
2287  * is a reference.
2288  */
2289 widget_entry = (sym_widget_entry_type *) obj_entry;
2290 widget_type = widget_entry->header.b_type;
2291 if (widget_type == uil_sym_user_defined_object)
2292     {
2293     if ((widget_entry->obj_header.b_flags & sym_m_obj_is_reference) != 0)
2294         {
2295         if (widget_entry->az_create_proc != NULL)
2296             {
2297             diag_issue_diagnostic
2298                 (d_create_proc_inv,
2299                  _sar_source_pos2(widget_entry),
2300                  diag_object_text (widget_type) );
2301             widget_entry->header.b_type = sym_k_error_object;
2302             }
2303         }
2304     else
2305         {
2306         if (widget_entry->az_create_proc == NULL)
2307             {
2308             diag_issue_diagnostic
2309                 (d_create_proc_req,
2310                  _sar_source_pos2(widget_entry),
2311                  diag_object_text (widget_type) );
2312             widget_entry->header.b_type = sym_k_error_object;
2313             }
2314         }
2315     }
2316
2317 }
2318
2319
2320 \f
2321 /*
2322 **++
2323 **  FUNCTIONAL DESCRIPTION:
2324 **
2325 **      This routine allocates a symbol node of the specified size
2326 **      and type.
2327 **
2328 **  FORMAL PARAMETERS:
2329 **
2330 **      node_tag        tag of node to allocate
2331 **      node_size       size of node to allocate
2332 **
2333 **  IMPLICIT INPUTS:
2334 **
2335 **
2336 **  IMPLICIT OUTPUTS:
2337 **
2338 **
2339 **  FUNCTION VALUE:
2340 **
2341 **      the address of the allocated node
2342 **
2343 **  SIDE EFFECTS:
2344 **
2345 **      The node is saved in the allocated node list
2346 **
2347 **--
2348 **/
2349
2350 sym_entry_type  * sem_allocate_node
2351         (unsigned char node_tag, unsigned short node_size )
2352
2353 {
2354
2355     sym_entry_type              * node_ptr;
2356
2357     node_ptr = (sym_entry_type *) XtCalloc (1, node_size);
2358     node_ptr->header.w_node_size = node_size;
2359     node_ptr->header.b_tag = node_tag;
2360     UrmPlistAppendPointer (sym_az_allocated_nodes, (XtPointer)node_ptr);
2361
2362     return node_ptr;
2363
2364 }
2365
2366 \f
2367 /*
2368 **++
2369 **  FUNCTIONAL DESCRIPTION:
2370 **
2371 **      This routine puts a symbol node on the free node list.
2372 **
2373 **  FORMAL PARAMETERS:
2374 **
2375 **      node_ptr        address of node to put on the free list
2376 **
2377 **  IMPLICIT INPUTS:
2378 **
2379 **
2380 **  IMPLICIT OUTPUTS:
2381 **
2382 **
2383 **  FUNCTION VALUE:
2384 **
2385 **      void
2386 **
2387 **  SIDE EFFECTS:
2388 **
2389 **--
2390 **/
2391
2392 void    sem_free_node ( node_ptr )
2393
2394 sym_entry_type          * node_ptr;
2395
2396 {
2397
2398     UrmPlistAppendPointer (sym_az_freed_nodes, (XtPointer)node_ptr);
2399     
2400 }
2401