Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / osf / wml / wmlresolve.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: wmlresolve.c /main/9 1995/08/29 11:11:05 drk $"
14 #endif
15 #endif
16 /*
17 *  (c) Copyright 1989, 1990, DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. */
18
19 /*
20  * This module contains all routines which perform semantic analysis of
21  * the parsed WML specification. It is responsible for building all
22  * ordered structures which can be directly translated into literal
23  * code values for the various .h files. It is responsible for performing
24  * inheritance of resources for all classes.
25  *
26  * Input:
27  *      the ordered list of syntactic objects in wml_synobj_ptr
28  *
29  * Output:
30  *
31  */
32
33
34 #include "wml.h"
35
36 #if defined(__STDC__)
37 #include <stdlib.h>
38 #endif
39 #include <stdio.h>
40
41 /*
42  * Routines used only in this module
43  */
44 void wmlResolveGenerateSymK ();
45 void wmlResolveValidateClass ();
46 void wmlResolvePrintReport ();
47
48 void wmlResolveSymKDataType ();
49 void wmlResolveSymKChild ();
50 void wmlResolveSymKEnumVal ();
51 void wmlResolveSymKEnumSet ();
52 void wmlResolveSymKReason ();
53 void wmlResolveSymKArgument ();
54 void wmlResolveSymKRelated ();
55 void wmlResolveSymKClass ();
56 void wmlResolveSymKCtrlList ();
57 void wmlResolveSymKCharSet ();
58
59 void wmlResolveClassInherit ();
60 void wmlResolveClearRefPointers ();
61 void wmlResolveInitRefObj ();
62 void wmlResolveInitChildRefObj ();
63
64 void wmlResolvePrintClass ();
65 void wmlResolvePrintClassArgs ();
66 void wmlResolvePrintClassReasons ();
67
68 ObjectPtr wmlResolveFindObject ();
69 void wmlIssueReferenceError ();
70 void wmlIssueIllegalReferenceError ();
71 void wmlIssueError ();
72
73
74 \f
75 /*
76  * The control routine for semantic analysis. It calls the various phases.
77  */
78
79 void wmlResolveDescriptors ()
80
81 {
82
83 /*
84  * Perform the code assignment pass. This results in assignment of sym_k_...
85  * codes to all entities. Also, all objects and cross-linking are validated.
86  */
87 wmlResolveGenerateSymK ();
88 printf ("\nInitial validation and reference resolution complete");
89
90 /*
91  * Perform class inheritance and validation
92  */
93 wmlResolveValidateClass ();
94 printf ("\nClass validation and inheritance complete");
95
96 /*
97  * Print a report
98  */
99 if ( wml_err_count > 0 ) return;
100 wmlResolvePrintReport ();
101
102 }
103
104
105 \f
106 /*
107  * Routine to linearize and assign sym_k... literals for objects. Simply
108  * a dispatching routine.
109  */
110
111 void wmlResolveGenerateSymK ()
112
113 {
114
115 /*
116  * Process the datatype objects
117  */
118 wmlResolveSymKDataType ();
119
120 /*
121  * Process the enumeration value and enumeration sets
122  */
123 wmlResolveSymKEnumVal ();
124 wmlResolveSymKEnumSet ();
125
126 /*
127  * Process the resources, producing argument and reason vectors.
128  */
129 wmlResolveSymKReason ();
130 wmlResolveSymKArgument ();
131
132 /*
133  * Bind related arguments
134  */
135 wmlResolveSymKRelated ();
136
137 /*
138  * Process the class definitions
139  */
140 wmlResolveSymKClass ();
141
142 /*
143  * Process the controls list definitions
144  */
145 wmlResolveSymKCtrlList ();
146
147 /*
148  * Process the charset objects
149  */
150 wmlResolveSymKCharSet ();
151
152 /* Process the child definitions. */
153 wmlResolveSymKChild();
154
155 }
156
157
158 \f
159 /*
160  * Routine to linearize data types
161  *
162  * - Generate the wml_obj_datatype... vector of resolved data type objects,
163  *   ordered lexicographically.
164  *   Do name processing, and acquire links to any other objects named in
165  *   the syntactic descriptor.
166  */
167
168 void wmlResolveSymKDataType ()
169
170 {
171
172 WmlSynDataTypeDefPtr    cursyn;         /* current syntactic object */
173 WmlDataTypeDefPtr       newobj;         /* new resolved object */
174 int                     ndx;            /* loop index */
175
176 /*
177  * Initialize the object vector. Then process the syntactic vector,
178  * processing each datatype object encountered (the vector is ordered).
179  * create and append a resolved object for each one encountered. This
180  * will be ordered as well.
181  */
182 wmlInitHList (wml_obj_datatype_ptr, 50, TRUE);
183 for ( ndx=0 ; ndx<wml_synobj_ptr->cnt ; ndx++ )
184     {
185     cursyn = (WmlSynDataTypeDefPtr) wml_synobj_ptr->hvec[ndx].objptr;
186     if ( cursyn->validation != WmlDataTypeDefValid ) continue;
187
188 /*
189  * Create and initialize new object. Append to resolved object vector.
190  */
191     newobj = (WmlDataTypeDefPtr) malloc (sizeof(WmlDataTypeDef));
192     newobj->syndef = cursyn;
193     cursyn->rslvdef = newobj;
194     if ( cursyn->int_lit != NULL )
195         newobj->tkname = cursyn->int_lit;
196     else
197         newobj->tkname = cursyn->name;
198     wmlInsertInHList (wml_obj_datatype_ptr, newobj->tkname, (ObjectPtr)newobj);
199
200 /*
201  * Validate any object references in the syntactic object
202  */
203
204     }
205
206 }
207
208 \f
209 /*
210  * Routine to linearize children
211  *
212  * - Generate the wml_obj_child... vector of resolved child objects,
213  *   ordered lexicographically.  Assign sym_k_... values while doing so.
214  *   Link child to its class. 
215  */
216
217 void wmlResolveSymKChild ()
218
219 {
220
221 WmlSynChildDefPtr       cursyn;         /* current syntactic object */
222 WmlChildDefPtr          newobj;         /* new resolved object */
223 int                     code;           /* assigned sym_k code value */
224 int                     ndx;            /* loop index */
225
226 /*
227  * Initialize the object vector. Then process the syntactic vector,
228  * processing each child object encountered (the vector is ordered).
229  * create and append a resolved object for each one encountered. This
230  * will be ordered as well.
231  */
232 wmlInitHList (wml_obj_child_ptr, 50, TRUE);
233 for ( ndx=0 ; ndx<wml_synobj_ptr->cnt ; ndx++ )
234     {
235     cursyn = (WmlSynChildDefPtr) wml_synobj_ptr->hvec[ndx].objptr;
236     if ( cursyn->validation != WmlChildDefValid ) continue;
237
238 /*
239  * Create and initialize new object. Append to resolved object vector.
240  */
241     newobj = (WmlChildDefPtr) malloc (sizeof(WmlChildDef));
242     newobj->syndef = cursyn;
243     cursyn->rslvdef = newobj;
244     newobj->tkname = cursyn->name;
245     wmlInsertInHList (wml_obj_child_ptr, newobj->tkname, (ObjectPtr)newobj);
246
247 /* Link class to the resolved object. */
248 if (cursyn->class != NULL)
249   newobj->class = (WmlClassDefPtr)
250     wmlResolveFindObject(cursyn->class, WmlClassDefValid, cursyn->name);
251   }
252
253 /*
254  * All objects are in the vector. The order is the code order, so
255  * process it again and assign codes to each object
256  */
257 code = 1;
258 for ( ndx=0 ; ndx<wml_obj_child_ptr->cnt ; ndx++ )
259     {
260     newobj = (WmlChildDefPtr) wml_obj_child_ptr->hvec[ndx].objptr;
261     newobj->sym_code = code;
262     code += 1;
263     }
264
265 }
266
267
268 \f
269 /*
270  * Routine to linearize and assign sym_k values to enumeration values
271  *
272  * - Generate the wml_obj_datatype... vector of resolved data type objects,
273  *   ordered lexicographically. No sym_k_... values are needed for
274  *   enumeration values, so don't assign any.
275  */
276
277 void wmlResolveSymKEnumVal ()
278
279 {
280
281 WmlSynEnumSetDefPtr     cures;          /* current enumeration set */
282 WmlSynEnumSetValDefPtr  curesv;         /* current enum set value */
283 WmlSynEnumValueDefPtr   cursyn;         /* current syntactic object */
284 WmlEnumValueDefPtr      newobj;         /* new resolved object */
285 int                     ndx;            /* loop index */
286 int                     code;           /* sym_k_... code */
287
288
289 /*
290  * Perform defaulting. Process all the enumeration sets, and define a
291  * syntactic object for every enumeration value named in an enumeration set
292  * which has no syntactic entry. If there is an error in a name, then
293  * this error won't be detected until we attempt to compile the output .h files.
294  */
295 for ( ndx=0 ; ndx<wml_synobj_ptr->cnt ; ndx++ )
296     {
297     cures = (WmlSynEnumSetDefPtr) wml_synobj_ptr->hvec[ndx].objptr;
298     if ( cures->validation != WmlEnumSetDefValid ) continue;
299     for (curesv=cures->values ; curesv!=NULL ; curesv=curesv->next)
300         if ( wmlFindInHList(wml_synobj_ptr,curesv->name) < 0 )
301             wmlCreateEnumValue (curesv->name);
302     }
303
304 /*
305  * Initialize the object vector. Then process the syntactic vector,
306  * processing each enumeration value object encountered (the vector is ordered).
307  * create and append a resolved object for each one encountered. This
308  * will be ordered as well.
309  */
310 wmlInitHList (wml_obj_enumval_ptr, 50, TRUE);
311 for ( ndx=0 ; ndx<wml_synobj_ptr->cnt ; ndx++ )
312     {
313     cursyn = (WmlSynEnumValueDefPtr) wml_synobj_ptr->hvec[ndx].objptr;
314     if ( cursyn->validation != WmlEnumValueDefValid ) continue;
315
316 /*
317  * Create and initialize new object. Append to resolved object vector.
318  */
319     newobj = (WmlEnumValueDefPtr) malloc (sizeof(WmlEnumValueDef));
320     newobj->syndef = cursyn;
321     cursyn->rslvdef = newobj;
322     wmlInsertInHList (wml_obj_enumval_ptr, cursyn->name, (ObjectPtr)newobj);
323     }
324
325 /*
326  * All objects are in the vector. That order is the code order, so
327  * process it again and assign codes to each object
328  */
329 code = 1;
330 for ( ndx=0 ; ndx<wml_obj_enumval_ptr->cnt ; ndx++ )
331     {
332     newobj = (WmlEnumValueDefPtr) wml_obj_enumval_ptr->hvec[ndx].objptr;
333     newobj->sym_code = code;
334     code += 1;
335     }
336
337 }
338
339
340 \f
341 /*
342  * Routine to linearize and assign sym_k values to enumeration sets
343  *
344  * - Generate the wml_obj_datatype... vector of resolved data type objects,
345  *   ordered lexicographically. No sym_k_... values are needed for
346  *   enumeration values, so don't assign any.
347  */
348
349 void wmlResolveSymKEnumSet ()
350
351 {
352
353 WmlSynEnumSetDefPtr     cursyn;         /* current syntactic object */
354 WmlEnumSetDefPtr        newobj;         /* new resolved object */
355 int                     ndx;            /* loop index */
356 int                     code;           /* sym_k_... code */
357 WmlSynEnumSetValDefPtr  esvelm;         /* current syntactic list element */
358 WmlEnumValueDefPtr      evobj;          /* current enumeration value */
359 WmlEnumSetValDefPtr     esvobj;         /* current list element */
360
361 /*
362  * Initialize the object vector. Then process the syntactic vector,
363  * processing each enumeration set object encountered (the vector is ordered).
364  * create and append a resolved object for each one encountered. This
365  * will be ordered as well.
366  */
367 wmlInitHList (wml_obj_enumset_ptr, 20, TRUE);
368 for ( ndx=0 ; ndx<wml_synobj_ptr->cnt ; ndx++ )
369     {
370     cursyn = (WmlSynEnumSetDefPtr) wml_synobj_ptr->hvec[ndx].objptr;
371     if ( cursyn->validation != WmlEnumSetDefValid ) continue;
372
373 /*
374  * Create and initialize new object. Append to resolved object vector.
375  */
376     newobj = (WmlEnumSetDefPtr) malloc (sizeof(WmlEnumSetDef));
377     newobj->syndef = cursyn;
378     cursyn->rslvdef = newobj;
379     newobj->tkname = cursyn->name;
380     newobj->dtype_def = (WmlDataTypeDefPtr)
381         wmlResolveFindObject (cursyn->datatype,
382                               WmlDataTypeDefValid,
383                               cursyn->name);
384     wmlInsertInHList (wml_obj_enumset_ptr, newobj->tkname, (ObjectPtr)newobj);
385     }
386
387 /*
388  * All objects are in the vector. That order is the code order, so
389  * process it again and assign codes to each object. Simultaneously construct
390  * a vector of resolved enumeration values, and count them.
391  */
392 code = 1;
393 for ( ndx=0 ; ndx<wml_obj_enumset_ptr->cnt ; ndx++ )
394     {
395     newobj = (WmlEnumSetDefPtr) wml_obj_enumset_ptr->hvec[ndx].objptr;
396     newobj->sym_code = code;
397     code += 1;
398
399 /*
400  * Validate and construct a resolved enumeration value list
401  */
402     cursyn = newobj->syndef;
403     newobj->values_cnt = 0;
404     newobj->values = NULL;
405     for ( esvelm=cursyn->values ; esvelm!=NULL ; esvelm=esvelm->next )
406         {
407         evobj = (WmlEnumValueDefPtr)
408             wmlResolveFindObject (esvelm->name,
409                                   WmlEnumValueDefValid,
410                                   cursyn->name);
411         if ( evobj == NULL ) continue;
412         esvobj = (WmlEnumSetValDefPtr) malloc (sizeof(WmlEnumSetValDef));
413         esvobj->value = evobj;
414         esvobj->next = newobj->values;
415         newobj->values = esvobj;
416         newobj->values_cnt += 1;
417         }
418     }
419
420 }
421
422
423 \f
424 /*
425  * Routine to linearize and assign sym_k values to reasons.
426  *
427  * - Generate the wml_obj_reason... vector of resolved reason objects,
428  *   ordered lexicographically. Assign a sym_k_... value as this is done.
429  *   Do name processing, and acquire links to any other objects named in
430  *   the syntactic descriptor.
431  */
432
433 void wmlResolveSymKReason ()
434
435 {
436
437 WmlSynResourceDefPtr    cursyn;         /* current syntactic object */
438 WmlResourceDefPtr       newobj;         /* new resolved object */
439 int                     ndx;            /* loop index */
440 int                     code;           /* assigned sym_k code value */
441 char                    errmsg[300];
442
443 /*
444  * Initialize the object vector. Then process the syntactic vector,
445  * processing each reason resource object encountered (the vector is ordered).
446  * create and append a resolved object for each one encountered. This
447  * will be ordered as well.
448  */
449 wmlInitHList (wml_obj_reason_ptr, 100, TRUE);
450 for ( ndx=0 ; ndx<wml_synobj_ptr->cnt ; ndx++ )
451     {
452     cursyn = (WmlSynResourceDefPtr) wml_synobj_ptr->hvec[ndx].objptr;
453     if ( cursyn->validation != WmlResourceDefValid ) continue;
454     if ( cursyn->type != WmlResourceTypeReason ) continue;
455     newobj = (WmlResourceDefPtr) malloc (sizeof(WmlResourceDef));
456
457 /*
458  * Create and initialize new object. Append to resolved object vector.
459  */
460     newobj->syndef = cursyn;
461     cursyn->rslvdef = newobj;
462     if ( cursyn->int_lit != NULL )
463         newobj->tkname = cursyn->int_lit;
464     else
465         newobj->tkname = cursyn->name;
466     newobj->dtype_def = NULL;
467     newobj->enumset_def = NULL;
468     newobj->related_code = 0;
469     wmlInsertInHList (wml_obj_reason_ptr, newobj->tkname, (ObjectPtr)newobj);
470
471 /*
472  * Validate any object references in the syntactic object
473  * Reason can't bind to some objects.
474  */
475     if ( cursyn->datatype != NULL )
476         wmlIssueIllegalReferenceError (cursyn->name, "DataType");
477
478     }
479
480 /*
481  * All objects are in the vector. That order is the code order, so
482  * process it again and assign codes to each object
483  */
484 code = 1;
485 for ( ndx=0 ; ndx<wml_obj_reason_ptr->cnt ; ndx++ )
486     {
487     newobj = (WmlResourceDefPtr) wml_obj_reason_ptr->hvec[ndx].objptr;
488     newobj->sym_code = code;
489     code += 1;
490     }
491
492 }
493
494
495 \f
496 /*
497  * Routine to linearize and assign sym_k values to arguments.
498  *
499  * - Generate the wml_obj_arg... vector of resovled reason objects,
500  *   ordered lexicographically. Assign a sym_k_... values while doing so.
501  *   validate the data type for each argument, and link it to its data type
502  *   object.
503  *   Do name processing, and acquire links to any other objects named in
504  *   the syntactic descriptor.
505  */
506
507 void wmlResolveSymKArgument ()
508
509 {
510
511
512 WmlSynResourceDefPtr    cursyn;         /* current syntactic object */
513 WmlResourceDefPtr       newobj;         /* new resolved object */
514 int                     ndx;            /* loop index */
515 int                     code;           /* assigned sym_k code value */
516 char                    errmsg[300];
517
518 /*
519  * Initialize the object vector. Then process the syntactic vector,
520  * processing each reason resource object encountered (the vector is ordered).
521  * create and append a resolved object for each one encountered. This
522  * will be ordered as well.
523  */
524 wmlInitHList (wml_obj_arg_ptr, 500, TRUE);
525 for ( ndx=0 ; ndx<wml_synobj_ptr->cnt ; ndx++ )
526     {
527     cursyn = (WmlSynResourceDefPtr) wml_synobj_ptr->hvec[ndx].objptr;
528     if ( cursyn->validation != WmlResourceDefValid ) continue;
529     if ( cursyn->type == WmlResourceTypeReason ) continue;
530     newobj = (WmlResourceDefPtr) malloc (sizeof(WmlResourceDef));
531
532 /*
533  * Create and initialize new object. Append to resolved object vector.
534  */
535     newobj->syndef = cursyn;
536     cursyn->rslvdef = newobj;
537     if ( cursyn->int_lit != NULL )
538         newobj->tkname = cursyn->int_lit;
539     else
540         newobj->tkname = cursyn->name;
541     newobj->related_code = 0;
542     newobj->enumset_def = NULL;
543     wmlInsertInHList (wml_obj_arg_ptr, newobj->tkname, (ObjectPtr)newobj);
544
545 /*
546  * Validate any object references in the syntactic object
547  */
548     newobj->dtype_def = (WmlDataTypeDefPtr)
549         wmlResolveFindObject (cursyn->datatype,
550                               WmlDataTypeDefValid,
551                               cursyn->name);
552     if ( cursyn->enumset != NULL )
553         newobj->enumset_def = (WmlEnumSetDefPtr)
554             wmlResolveFindObject (cursyn->enumset,
555                                   WmlEnumSetDefValid,
556                                   cursyn->name);
557
558     }
559
560 /*
561  * All objects are in the vector. The order is the code order, so
562  * process it again and assign codes to each object
563  */
564 code = 1;
565 for ( ndx=0 ; ndx<wml_obj_arg_ptr->cnt ; ndx++ )
566     {
567     newobj = (WmlResourceDefPtr) wml_obj_arg_ptr->hvec[ndx].objptr;
568     newobj->sym_code = code;
569     code += 1;
570     }
571
572 }
573
574
575 \f
576 /*
577  * Routine to resolve related argument references.
578  *
579  * Search the argument vector for any argument with its related
580  * argument set. Find the related argument, and bind the relation.
581  * The binding only goes one way.
582  */
583
584 void wmlResolveSymKRelated ()
585
586 {
587
588 WmlResourceDefPtr       srcobj;         /* object with related reference */
589 WmlResourceDefPtr       dstobj;         /* other object in binding */
590 WmlSynResourceDefPtr    srcsynobj;      /* source syntactic object */
591 int                     ndx;            /* loop index */
592
593
594 /*
595  * Scan all arguments for related argument bindings.
596  */
597 for ( ndx=0 ; ndx<wml_obj_arg_ptr->cnt ; ndx++ )
598     {
599     srcobj = (WmlResourceDefPtr) wml_obj_arg_ptr->hvec[ndx].objptr;
600     srcsynobj = srcobj->syndef;
601     if ( srcsynobj->related != NULL )
602         {
603         dstobj = (WmlResourceDefPtr)
604             wmlResolveFindObject (srcsynobj->related,
605                                   WmlResourceDefValid,
606                                   srcsynobj->name);
607         if ( dstobj != NULL )
608             srcobj->related_code = dstobj->sym_code;
609         }
610     }
611 }
612
613  
614 \f
615 /*
616  * Routine to linearize and assign sym_k values to classes
617  *
618  * There are two linearizations of classes:
619  *      - all classes in wml_obj_allclass...
620  *      - all widgets and gadgets in wml_obj_class...
621  * Create and linearize all class objects into these vectors. Assign sym_k
622  * codes. Link all subclasses to their superclasses. Perform name processing
623  * and link to any other named object.
624  *
625  * Resources are not inherited and linked at this time.
626  */
627
628 void wmlResolveSymKClass ()
629
630 {
631
632 WmlSynClassDefPtr       cursyn;         /* current syntactic object */
633 WmlClassDefPtr          newobj;         /* new resolved object */
634 int                     ndx;            /* loop index */
635 int                     code;           /* assigned sym_k code value */
636 char                    errmsg[300];
637
638
639 /*
640  * Initialize the object vectors. Then process the syntactic vector,
641  * processing each class object encountered (the vector is ordered).
642  * create and append a resolved object for each one encountered. This
643  * will be ordered as well.
644  */
645 wmlInitHList (wml_obj_allclass_ptr, 200, TRUE);
646 wmlInitHList (wml_obj_class_ptr, 200, TRUE);
647 for ( ndx=0 ; ndx<wml_synobj_ptr->cnt ; ndx++ )
648     {
649     cursyn = (WmlSynClassDefPtr) wml_synobj_ptr->hvec[ndx].objptr;
650     if ( cursyn->validation != WmlClassDefValid ) continue;
651
652 /*
653  * Create and initialize new object. Append to resolved object vector.
654  */
655     newobj = (WmlClassDefPtr) malloc (sizeof(WmlClassDef));
656     newobj->syndef = cursyn;
657     cursyn->rslvdef = newobj;
658     newobj->superclass = NULL;
659     newobj->parentclass = NULL;
660     if ( cursyn->int_lit != NULL )
661         newobj->tkname = cursyn->int_lit;
662     else
663         newobj->tkname = cursyn->name;
664     newobj->inherit_done = FALSE;
665     newobj->arguments = NULL;
666     newobj->reasons = NULL;
667     newobj->controls = NULL;
668     newobj->children = NULL;
669     newobj->variant = NULL;
670     newobj->nondialog = NULL;
671     newobj->ctrlmapto = NULL;
672     switch ( cursyn->type )
673         {
674         case WmlClassTypeMetaclass:
675             wmlInsertInHList
676                 (wml_obj_allclass_ptr, newobj->tkname, (ObjectPtr)newobj);
677             break;
678         case WmlClassTypeGadget:
679         case WmlClassTypeWidget:
680             wmlInsertInHList
681                 (wml_obj_allclass_ptr, newobj->tkname, (ObjectPtr)newobj);
682             wmlInsertInHList
683                 (wml_obj_class_ptr, newobj->tkname, (ObjectPtr)newobj);
684             break;
685         }
686
687 /*
688  * Require a convenience function name
689  */
690     if ( cursyn->type != WmlClassTypeMetaclass )
691         if ( cursyn->convfunc == NULL )
692             {
693             sprintf (errmsg, "Class %s does not have a convenience function",
694                      cursyn->name);
695             wmlIssueError (errmsg);
696             }   
697
698 /*
699  * Validate any object references in the syntactic object
700  */
701     if ( cursyn->ctrlmapto != NULL )
702         newobj->ctrlmapto = (WmlResourceDefPtr)
703             wmlResolveFindObject (cursyn->ctrlmapto,
704                                   WmlResourceDefValid,
705                                   cursyn->name);
706
707     }
708
709 /*
710  * All objects are in the vector. That order is the code order, so
711  * process it again and assign codes to each object
712  */
713 code = 1;
714 for ( ndx=0 ; ndx<wml_obj_class_ptr->cnt ; ndx++ )
715     {
716     newobj = (WmlClassDefPtr) wml_obj_class_ptr->hvec[ndx].objptr;
717     newobj->sym_code = code;
718     code += 1;
719     }
720
721 }
722
723
724 \f
725 /*
726  * Routine to validate controls lists
727  *
728  * Construct and linearize resolved controls lists. The linearized list
729  * is used to resolve references.
730  */
731
732 void wmlResolveSymKCtrlList ()
733
734 {
735
736 WmlSynCtrlListDefPtr    cursyn;         /* current syntactic object */
737 WmlCtrlListDefPtr       newobj;         /* new resolved object */
738 WmlSynClassCtrlDefPtr   refptr;         /* current controls reference */
739 WmlClassCtrlDefPtr      ctrlobj;        /* resolved control reference */
740 WmlClassDefPtr          classobj;       /* the controlled class */
741 int                     ndx;            /* loop index */
742
743
744 /*
745  * Process each control list. Construct a resolved control list for each
746  */
747 wmlInitHList (wml_obj_ctrlist_ptr, 20, TRUE);
748 for ( ndx=0 ; ndx<wml_synobj_ptr->cnt ; ndx++ )
749     {
750     cursyn = (WmlSynCtrlListDefPtr) wml_synobj_ptr->hvec[ndx].objptr;
751     if ( cursyn->validation != WmlCtrlListDefValid ) continue;
752
753 /*
754  * Create and initialize new object. Append to resolved object vector.
755  */
756     newobj = (WmlCtrlListDefPtr) malloc (sizeof(WmlCtrlListDef));
757     newobj->syndef = cursyn;
758     cursyn->rslvdef = newobj;
759     newobj->controls = NULL;
760     wmlInsertInHList (wml_obj_ctrlist_ptr, cursyn->name, (ObjectPtr)newobj);
761
762 /*
763  * Validate and construct a resolved controls reference list.
764  */
765     for ( refptr=cursyn->controls ; refptr!=NULL ; refptr=refptr->next )
766         {
767         classobj = (WmlClassDefPtr)
768             wmlResolveFindObject (refptr->name,
769                                   WmlClassDefValid,
770                                   cursyn->name);
771         if ( classobj == NULL ) continue;
772         ctrlobj = (WmlClassCtrlDefPtr) malloc (sizeof(WmlClassCtrlDef));
773         ctrlobj->next = newobj->controls;
774         newobj->controls = ctrlobj;
775         ctrlobj->ctrl = classobj;
776         }
777     }
778
779 }
780
781
782 \f
783 /*
784  * Routine to linearize and assign sym_k values to character sets
785  *
786  * - Generate the wml_obj_charset... vector of resolved data type objects,
787  *   ordered lexicographically. Assign a sym_k... value as this is done.
788  *   Do name processing, and acquire links to any other objects named in
789  *   the syntactic descriptor.
790  */
791
792 void wmlResolveSymKCharSet ()
793
794 {
795
796 WmlSynCharSetDefPtr     cursyn;         /* current syntactic object */
797 WmlCharSetDefPtr        newobj;         /* new resolved object */
798 int                     ndx;            /* loop index */
799 int                     code;           /* assigned sym_k code value */
800 char                    errmsg[300];
801
802
803 /*
804  * Initialize the object vector. Then process the syntactic vector,
805  * processing each charset object encountered (the vector is ordered).
806  * create and append a resolved object for each one encountered. This
807  * will be ordered as well.
808  */
809 wmlInitHList (wml_obj_charset_ptr, 50, TRUE);
810 for ( ndx=0 ; ndx<wml_synobj_ptr->cnt ; ndx++ )
811     {
812     cursyn = (WmlSynCharSetDefPtr) wml_synobj_ptr->hvec[ndx].objptr;
813     if ( cursyn->validation != WmlCharSetDefValid ) continue;
814
815 /*
816  * Create and initialize new object. Append to resolved object vector.
817  */
818     newobj = (WmlCharSetDefPtr) malloc (sizeof(WmlCharSetDef));
819     newobj->syndef = cursyn;
820     cursyn->rslvdef = newobj;
821     if ( cursyn->int_lit != NULL )
822         newobj->tkname = cursyn->int_lit;
823     else
824         newobj->tkname = cursyn->name;
825     wmlInsertInHList (wml_obj_charset_ptr, newobj->tkname, (ObjectPtr)newobj);
826
827 /*
828  * Parsing direction defaults to writing direction if unspecified
829  */
830     if ( cursyn->parsedirection == WmlAttributeUnspecified )
831         cursyn->parsedirection = cursyn->direction;
832
833 /*
834  * Require StandardsName attribute for character set
835  */
836     if ( cursyn->xms_name == NULL )
837         {
838         sprintf (errmsg, "CharacterSet %s does not have a StandardsName",
839                  cursyn->name);
840         wmlIssueError (errmsg);
841         }       
842
843     }
844
845 /*
846  * All objects are in the vector. That order is the code order, so
847  * process it again and assign codes to each object. We start at code
848  * 2 since 1 is reserved for sym_k_userdefined_charset
849  */
850 code = 2;
851 for ( ndx=0 ; ndx<wml_obj_charset_ptr->cnt ; ndx++ )
852     {
853     newobj = (WmlCharSetDefPtr) wml_obj_charset_ptr->hvec[ndx].objptr;
854     newobj->sym_code = code;
855     code += 1;
856     }
857
858 }
859
860
861 \f
862 /*
863  * Routine to perform class inheritance and validation.
864  *
865  * This routine has two major phases:
866  *      - Complete resolution of class references, and expand out
867  *        controls list.
868  *      - Perform inheritance of resources, partitioning them into
869  *        into arguments and reasons. When complete, the class has
870  *        a list of all its resources, including copies from a 
871  *        superclass and possibly a parentclass.
872  *        Excluded resources remain in the list, and are simply marked.
873  */
874
875 void wmlResolveValidateClass ()
876
877 {
878
879 int                     ndx;            /* loop index */
880 int                     max;            /* maximum code value */
881 WmlClassDefPtr          clsobj;         /* current class object */
882 WmlSynClassDefPtr       synobj;         /* syntactic class object */
883 WmlClassDefPtr          superobj;       /* superclass */
884 WmlClassDefPtr          parentobj;      /* parentclass */
885 WmlClassDefPtr          widgobj;        /* gadget's widget class */
886 WmlSynClassCtrlDefPtr   refptr;         /* current controls reference */
887 WmlClassCtrlDefPtr      ctrlobj;        /* resolved control reference */
888 int                     refndx;         /* index in vector */
889 WmlClassDefPtr          refcls;         /* referenced class object */
890 WmlCtrlListDefPtr       reflist;        /* controls list object */
891 WmlClassCtrlDefPtr      listelem;       /* control reference in list */
892 char                    errmsg[300];
893
894
895 /*
896  * Acquire the superclass pointer for each widget and gadget class
897  */
898 for ( ndx=0 ; ndx<wml_obj_allclass_ptr->cnt ; ndx++ )
899     {
900     clsobj = (WmlClassDefPtr) wml_obj_allclass_ptr->hvec[ndx].objptr;
901     synobj = clsobj->syndef;
902     if ( synobj->superclass != NULL )
903         {
904         superobj = (WmlClassDefPtr)
905             wmlResolveFindObject (synobj->superclass,
906                                   WmlClassDefValid,
907                                   synobj->name);
908         if ( superobj == NULL ) continue;
909         clsobj->superclass = superobj;
910         }
911     }
912
913 /*
914  * Acquire the parentclass pointer (if one exists),
915  * for each widget and gadget class
916  */
917 for ( ndx=0 ; ndx<wml_obj_allclass_ptr->cnt ; ndx++ )
918     {
919     clsobj = (WmlClassDefPtr) wml_obj_allclass_ptr->hvec[ndx].objptr;
920     synobj = clsobj->syndef;
921     if ( synobj->parentclass != NULL )
922         {
923         parentobj = (WmlClassDefPtr)
924             wmlResolveFindObject (synobj->parentclass,
925                                   WmlClassDefValid,
926                                   synobj->name);
927         if ( parentobj == NULL ) continue;
928         clsobj->parentclass = parentobj;
929         }
930     }
931
932 /*
933  * Link each gadget class with its widget class (both ways).
934  * Link any class with a non-dialog version to the non-dialog class.
935  */
936 for ( ndx=0 ; ndx<wml_obj_class_ptr->cnt ; ndx++ )
937     {
938     clsobj = (WmlClassDefPtr) wml_obj_class_ptr->hvec[ndx].objptr;
939     synobj = clsobj->syndef;
940     if ( synobj->type == WmlClassTypeGadget )
941         {
942         if ( synobj->widgetclass == NULL )
943             {
944             sprintf (errmsg, "Gadget class %s has no widgetclass reference",
945                      synobj->name);
946             wmlIssueError (errmsg);
947             }
948         else
949             {
950             widgobj = (WmlClassDefPtr)
951                 wmlResolveFindObject
952                     (synobj->widgetclass,
953                      WmlClassDefValid,
954                      synobj->name);
955             if ( widgobj != NULL )
956                 {
957                 clsobj->variant = widgobj;
958                 widgobj->variant = clsobj;
959                 }
960             }
961         }
962     if ( synobj->dialog == TRUE )
963         {
964         clsobj->nondialog = clsobj->superclass;
965         while ( clsobj->nondialog->syndef->dialog == TRUE )
966             clsobj->nondialog = clsobj->nondialog->superclass;
967         }
968     else
969         if ( clsobj->superclass != NULL )
970             {
971             synobj->dialog = clsobj->superclass->syndef->dialog;
972             clsobj->nondialog = clsobj->superclass->nondialog;
973             }
974     }
975
976 /*
977  * Construct the list of resolved controls. Control lists are expanded
978  * in place.
979  */
980 for ( ndx=0 ; ndx<wml_obj_class_ptr->cnt ; ndx++ )
981     {
982     clsobj = (WmlClassDefPtr) wml_obj_class_ptr->hvec[ndx].objptr;
983     synobj = clsobj->syndef;
984     for ( refptr=synobj->controls ; refptr!= NULL ; refptr=refptr->next )
985         {
986         refndx = wmlFindInHList (wml_obj_class_ptr, refptr->name);
987         if ( refndx >= 0 )
988             {
989             refcls = (WmlClassDefPtr) wml_obj_class_ptr->hvec[refndx].objptr;
990             ctrlobj = (WmlClassCtrlDefPtr) malloc (sizeof(WmlClassCtrlDef));
991             ctrlobj->next = clsobj->controls;
992             clsobj->controls = ctrlobj;
993             ctrlobj->ctrl = refcls;
994             continue;
995             }
996         refndx = wmlFindInHList (wml_obj_ctrlist_ptr, refptr->name);
997         if ( refndx >= 0 )
998             {
999             reflist = (WmlCtrlListDefPtr)
1000                 wml_obj_ctrlist_ptr->hvec[refndx].objptr;
1001             for ( listelem=reflist->controls ;
1002                   listelem!=NULL ;
1003                   listelem=listelem->next)
1004                 {
1005                 ctrlobj = (WmlClassCtrlDefPtr)
1006                     malloc (sizeof(WmlClassCtrlDef));
1007                 ctrlobj->next = clsobj->controls;
1008                 clsobj->controls = ctrlobj;
1009                 ctrlobj->ctrl = listelem->ctrl;
1010                 }
1011             continue;
1012             }
1013         wmlIssueReferenceError (synobj->name, refptr->name);
1014         continue;
1015         }
1016     }
1017
1018 /*
1019  * Perform resource inheritance for each class. This constructs the
1020  * arguments and reasons reference vectors.
1021  */
1022 for ( ndx=0 ; ndx<wml_obj_allclass_ptr->cnt ; ndx++ )
1023     {
1024     clsobj = (WmlClassDefPtr) wml_obj_allclass_ptr->hvec[ndx].objptr;
1025     wmlResolveClassInherit (clsobj);
1026     }
1027
1028 }
1029
1030
1031 \f
1032 /*
1033  * Routine to perform resource inheritance for a class.
1034  *
1035  * This routine constructs the argument and reason resource and child reference
1036  * vectors for a class. It first ensures the superclass (if any) has
1037  * been inited. It then makes a copy of the superclass lists. It repeats this
1038  * procedure for the parentclass (if any.) Finally, it
1039  * merges in the resources from the syntactic object. It uses the
1040  * resolved resource or child object to point to the matching reference object 
1041  * in the list being created as an aid to search doing overrides. This also
1042  * detects whether a resource or child is already in the list (if so, it is 
1043  * assumed to be inherited).
1044  */
1045
1046 void wmlResolveClassInherit (clsobj)
1047     WmlClassDefPtr              clsobj;
1048
1049 {
1050
1051 WmlClassDefPtr          superobj;       /* superclass object */
1052 WmlClassDefPtr          parentobj;      /* parentclass object */
1053 int                     ndx;            /* loop index */
1054 WmlResourceDefPtr       resobj;         /* current resource object */
1055 WmlClassResDefPtr       refobj;         /* current resource reference */
1056 WmlClassResDefPtr       srcref;         /* source of copy */
1057 WmlChildDefPtr          childobj;       /* current child object */
1058 WmlClassChildDefPtr     crefobj;        /* current child reference */
1059 WmlClassChildDefPtr     csrcref;        /* child source of copy */
1060 WmlSynClassDefPtr       synobj;         /* this class' syntactic object */
1061 WmlSynClassResDefPtr    refptr;         /* syntactic resource reference */
1062 WmlSynClassChildDefPtr  crefptr;        /* syntactic child reference */
1063
1064
1065 /*
1066  * Done if inheritance previously performed. Ensure the superclass is
1067  * done.
1068  */
1069 if ( clsobj == NULL ) return;
1070 if ( clsobj->inherit_done ) return;
1071 superobj = clsobj->superclass;
1072 wmlResolveClassInherit (superobj);
1073 parentobj = clsobj->parentclass;
1074 wmlResolveClassInherit (parentobj);
1075 synobj = clsobj->syndef;
1076
1077 /*
1078  * Clear the active reference pointer in the resolved resource objects.
1079  */
1080 wmlResolveClearRefPointers ();
1081
1082 /*
1083  * Copy the superclass resources, setting the reference pointer as we go.
1084  */
1085 if ( superobj != NULL )
1086     {
1087     for ( srcref=superobj->arguments ; srcref!=NULL ; srcref=srcref->next )
1088         {
1089         refobj = (WmlClassResDefPtr) malloc (sizeof(WmlClassResDef));
1090         refobj->next = clsobj->arguments;
1091         clsobj->arguments = refobj;
1092         wmlResolveInitRefObj (refobj, srcref);
1093         }
1094     for ( srcref=superobj->reasons ; srcref!=NULL ; srcref=srcref->next )
1095         {
1096         refobj = (WmlClassResDefPtr) malloc (sizeof(WmlClassResDef));
1097         refobj->next = clsobj->reasons;
1098         clsobj->reasons = refobj;
1099         wmlResolveInitRefObj (refobj, srcref);
1100         }
1101     for (csrcref = superobj->children ; csrcref!=NULL ; csrcref=csrcref->next)
1102       {
1103         crefobj = (WmlClassChildDefPtr) malloc (sizeof(WmlClassChildDef));
1104         crefobj->next = clsobj->children;
1105         clsobj->children = crefobj;
1106         wmlResolveInitChildRefObj (crefobj, csrcref);
1107       }
1108     }
1109
1110 /*
1111  * Copy the parentclass resources, setting the reference pointer as we go.
1112  */
1113 if ( parentobj != NULL )
1114     {
1115     for ( srcref=parentobj->arguments ; srcref!=NULL ; srcref=srcref->next )
1116         {
1117           if (srcref->act_resource->ref_ptr == NULL)
1118             {
1119               refobj = (WmlClassResDefPtr) malloc (sizeof(WmlClassResDef));
1120               refobj->next = clsobj->arguments;
1121               clsobj->arguments = refobj;
1122               wmlResolveInitRefObj (refobj, srcref);
1123             }
1124         }
1125     for ( srcref=parentobj->reasons ; srcref!=NULL ; srcref=srcref->next )
1126         {
1127           if (srcref->act_resource->ref_ptr == NULL)
1128             {
1129               refobj = (WmlClassResDefPtr) malloc (sizeof(WmlClassResDef));
1130               refobj->next = clsobj->reasons;
1131               clsobj->reasons = refobj;
1132               wmlResolveInitRefObj (refobj, srcref);
1133             }
1134         }
1135     for (csrcref = parentobj->children ; csrcref!=NULL ; csrcref=csrcref->next)
1136       {
1137         if (csrcref->act_child->ref_ptr == NULL)
1138           {
1139             crefobj = (WmlClassChildDefPtr) malloc (sizeof(WmlClassChildDef));
1140             crefobj->next = clsobj->children;
1141             clsobj->children = crefobj;
1142             wmlResolveInitChildRefObj (crefobj, csrcref);
1143           }
1144       }
1145     }
1146
1147 /*
1148  * Process the resources belonging to this class. They may either be
1149  * new resources, or override ones already in the list. Partition them
1150  * into arguments and reasons.
1151  */
1152 for ( refptr=synobj->resources ; refptr!=NULL ; refptr=refptr->next )
1153     {
1154     resobj = (WmlResourceDefPtr) wmlResolveFindObject (refptr->name,
1155                                                        WmlResourceDefValid,
1156                                                        synobj->name);
1157     if ( resobj == NULL ) continue;
1158
1159     /*
1160      * Acquire the resolved resource object, and the resource reference.
1161      * New references are linked in to the proper list, and have their
1162      * defaults set.
1163      */
1164     if ( resobj->ref_ptr != NULL )
1165         refobj = resobj->ref_ptr;
1166     else
1167         {
1168         refobj = (WmlClassResDefPtr) malloc (sizeof(WmlClassResDef));
1169         refobj->act_resource = resobj;
1170         resobj->ref_ptr = refobj;
1171         refobj->over_dtype = NULL;
1172         refobj->dflt = NULL;
1173         refobj->exclude = WmlAttributeUnspecified;
1174         if ( resobj->syndef->type == WmlResourceTypeReason )
1175             {
1176             refobj->next = clsobj->reasons;
1177             clsobj->reasons = refobj;
1178             }
1179         else
1180             {
1181             refobj->next = clsobj->arguments;
1182             clsobj->arguments = refobj;
1183             }
1184         }
1185
1186     /*
1187      * Override any values in the reference which are explicit in the
1188      * syntactic reference.
1189      */
1190     if ( refptr->type != NULL )
1191         refobj->over_dtype = (WmlDataTypeDefPtr)
1192             wmlResolveFindObject (refptr->type,
1193                                   WmlDataTypeDefValid,
1194                                   synobj->name);
1195     if ( refptr->dflt != NULL )
1196         refobj->dflt = refptr->dflt;
1197     if ( refptr->exclude != WmlAttributeUnspecified )
1198         refobj->exclude = refptr->exclude;
1199     }
1200
1201 /*
1202  * Process the children belonging to this class. 
1203  */
1204 for ( crefptr = synobj->children ; crefptr!=NULL ; crefptr = crefptr->next )
1205   {
1206     childobj = (WmlChildDefPtr) wmlResolveFindObject (crefptr->name,
1207                                                      WmlChildDefValid,
1208                                                      synobj->name);
1209     if ( childobj == NULL ) continue;
1210
1211     /*
1212      * Acquire the resolved child object, and the child reference.
1213      * New references are linked in to the proper list, and have their
1214      * defaults set.
1215      */
1216     if ( childobj->ref_ptr != NULL )
1217         crefobj = childobj->ref_ptr;
1218     else
1219       {
1220         crefobj = (WmlClassChildDefPtr) malloc (sizeof(WmlClassChildDef));
1221         crefobj->act_child = childobj;
1222         childobj->ref_ptr = crefobj;
1223         crefobj->next = clsobj->children;
1224         clsobj->children = crefobj;
1225       }
1226   }
1227
1228 /*
1229  * inheritance complete
1230  */
1231 clsobj->inherit_done = TRUE;
1232
1233 }
1234
1235
1236 \f
1237 /*
1238  * Routine to copy a resource reference
1239  */
1240
1241 void wmlResolveInitRefObj (dstobj, srcobj)
1242     WmlClassResDefPtr           dstobj;
1243     WmlClassResDefPtr           srcobj;
1244
1245 {
1246
1247 WmlResourceDefPtr       resobj;
1248
1249
1250 resobj = srcobj->act_resource;
1251 dstobj->act_resource = resobj;
1252 resobj->ref_ptr = dstobj;
1253 dstobj->over_dtype = srcobj->over_dtype;
1254 dstobj->dflt = srcobj->dflt;
1255 dstobj->exclude = srcobj->exclude;
1256
1257 }
1258
1259 \f
1260 /*
1261  * Routine to copy a child reference
1262  */
1263
1264 void wmlResolveInitChildRefObj (dstobj, srcobj)
1265     WmlClassChildDefPtr         dstobj;
1266     WmlClassChildDefPtr         srcobj;
1267
1268 {
1269
1270 WmlChildDefPtr  childobj;
1271
1272 childobj = srcobj->act_child;
1273 dstobj->act_child = childobj;
1274 childobj->ref_ptr = dstobj;
1275
1276 }
1277
1278
1279 \f
1280 /*
1281  * Routine to print a report in a file.
1282  *
1283  * This routine dumps the developed database into the file 'wml.report'
1284  */
1285
1286 void wmlResolvePrintReport ()
1287
1288 {
1289
1290 FILE                    *outfil;        /* output file */
1291 int                     ndx;            /* loop index */
1292 WmlClassDefPtr          clsobj;         /* current class */
1293
1294
1295 /*
1296  * Open the output file.
1297  */
1298 outfil = fopen ( "wml.report", "w");
1299 if ( outfil == NULL )
1300     {
1301     printf ("\nCouldn't open wml.report");
1302     return;
1303     }
1304
1305 /*
1306  * Go through all classes. Print basic information, then dump their
1307  * resources. The main purpose of this report is to show the actual
1308  * resources and controls for the class.
1309  */
1310
1311 for ( ndx=0 ; ndx<wml_obj_allclass_ptr->cnt ; ndx++ )
1312     {
1313     clsobj = (WmlClassDefPtr) wml_obj_allclass_ptr->hvec[ndx].objptr;
1314     wmlMarkReferencePointers (clsobj);
1315     wmlResolvePrintClass (outfil, clsobj);
1316     }
1317
1318
1319 /*
1320  * close the output file
1321  */
1322 fprintf (outfil, "\n\n");
1323 printf ("\nCreated report file wml.report");
1324 fclose (outfil);
1325
1326 }
1327
1328
1329 \f
1330 /*
1331  * Print the information for a class
1332  */
1333
1334 void wmlResolvePrintClass (outfil, clsobj)
1335     FILE                        *outfil;
1336     WmlClassDefPtr              clsobj;
1337
1338 {
1339
1340 int                     ndx;            /* loop index */
1341 WmlSynClassDefPtr       synobj;         /* syntactic object */
1342 WmlClassCtrlDefPtr      ctrlref;        /* controls reference */
1343 WmlClassDefPtr          ctrlobj;        /* current class in control */
1344
1345
1346 synobj = clsobj->syndef;
1347 fprintf (outfil, "\n\n\nClass %s:", synobj->name);
1348 switch ( synobj->type )
1349     {
1350     case WmlClassTypeMetaclass:
1351         fprintf (outfil, "\n  Type: Metaclass\t");
1352         if ( synobj->superclass != NULL )
1353             fprintf (outfil, "Superclass: %s\t", synobj->superclass);
1354         if ( synobj->parentclass != NULL )
1355             fprintf (outfil, "Parentclass: %s\t", synobj->parentclass);
1356         break;
1357     case WmlClassTypeWidget:
1358         fprintf (outfil, "\n  Type: Widget\t");
1359         if ( synobj->superclass != NULL )
1360             fprintf (outfil, "Superclass: %s\t", synobj->superclass);
1361         if ( synobj->parentclass != NULL )
1362             fprintf (outfil, "Parentclass: %s\t", synobj->parentclass);
1363         if ( clsobj->variant != NULL )
1364             fprintf (outfil, "\n  Associated gadget class: %s\t",
1365                      clsobj->variant->syndef->name);
1366         if ( synobj->convfunc != NULL )
1367             fprintf (outfil, "Convenience function: %s", synobj->convfunc);
1368         break;
1369     case WmlClassTypeGadget:
1370         fprintf (outfil, "\n  Type: Gadget\t");
1371         if ( synobj->superclass != NULL )
1372             fprintf (outfil, "Superclass: %s\t", synobj->superclass);
1373         if ( synobj->parentclass != NULL )
1374             fprintf (outfil, "Parentclass: %s\t", synobj->parentclass);
1375         if ( clsobj->variant != NULL )
1376             fprintf (outfil, "\n  Associated widget class: %s\t",
1377                      clsobj->variant->syndef->name);
1378         if ( synobj->convfunc != NULL )
1379             fprintf (outfil, "Convenience function: %s", synobj->convfunc);
1380         break;
1381     }
1382
1383 /*
1384  * Print associated non-dialog class
1385  */
1386 if ( clsobj->nondialog != NULL )
1387     fprintf (outfil, "\n  DialogClass: True\tNon-dialog ancestor: %s\t",
1388              clsobj->nondialog->syndef->name);
1389
1390 /*
1391  * Print the arguments valid in the class. First the new resources for the
1392  * class are printed, then each ancestor's contribution is printed. This
1393  * is intended to match the way resources are printed in the toolkit manual,
1394  * so that checking is as easy as possible.
1395  */
1396 fprintf (outfil, "\n  Arguments:");
1397 wmlResolvePrintClassArgs (outfil, clsobj);
1398
1399 /*
1400  * Print the reasons valid in the class
1401  */
1402 fprintf (outfil, "\n  Reasons:");
1403 wmlResolvePrintClassReasons (outfil, clsobj);
1404
1405 /*
1406  * Print the controls valid in the class
1407  */
1408 fprintf (outfil, "\n  Controls:");
1409 for ( ndx=0 ; ndx<wml_obj_class_ptr->cnt ; ndx++ )
1410     {
1411     ctrlobj = (WmlClassDefPtr) wml_obj_class_ptr->hvec[ndx].objptr;
1412     if ( ctrlobj->ref_ptr == NULL ) continue;
1413     fprintf (outfil, "\n    %s", ctrlobj->syndef->name);
1414     }
1415
1416 }
1417
1418
1419 \f
1420 /*
1421  * Routine to print the arguments for a class
1422  *
1423  * This routine prints out the currently marked arguments which are
1424  * present in this class. Each argument which is printed is remarked
1425  * so that it won't be printed again. This routine first prints the
1426  * superclass arguments, so that the printing order becomes the top-down
1427  * inheritance order.
1428  */
1429
1430 void wmlResolvePrintClassArgs (outfil, clsobj)
1431     FILE                        *outfil;
1432     WmlClassDefPtr              clsobj;
1433
1434 {
1435
1436 int                     prthdr = TRUE;  /* print header line */
1437 int                     ndx;            /* loop index */
1438 WmlSynClassDefPtr       synobj;         /* syntactic object */
1439 WmlClassResDefPtr       resref;         /* resource reference */
1440 int                     constr = FALSE; /* check for constraints */
1441 WmlResourceDefPtr       resobj;         /* current resource */
1442 WmlSynResourceDefPtr    synres;         /* syntactic resource object */
1443
1444
1445 /*
1446  * Print the superclass arguments
1447  */
1448 if ( clsobj->superclass != NULL )
1449     wmlResolvePrintClassArgs (outfil, clsobj->superclass);
1450
1451 /*
1452  * Print the parentclass arguments
1453  */
1454 if ( clsobj->parentclass != NULL )
1455     wmlResolvePrintClassArgs (outfil, clsobj->parentclass);
1456
1457 /*
1458  * Print the arguments for this class. Unmark the reference so it won't
1459  * be printed again.
1460  */
1461 synobj = clsobj->syndef;
1462 for ( ndx=0 ; ndx<wml_obj_arg_ptr->cnt ; ndx++ )
1463     {
1464     resobj = (WmlResourceDefPtr) wml_obj_arg_ptr->hvec[ndx].objptr;
1465     resref = resobj->ref_ptr;
1466     if ( resref == NULL ) continue;
1467     if ( wmlResolveResIsMember(resobj,clsobj->arguments) == NULL ) continue;
1468     synres = resobj->syndef;
1469     switch ( synres->type )
1470         {
1471         case WmlResourceTypeArgument:
1472         case WmlResourceTypeSubResource:
1473             break;
1474         case WmlResourceTypeConstraint:
1475             constr = TRUE;
1476             break;
1477         default:
1478             continue;
1479             break;
1480         }
1481     if ( prthdr )
1482         {
1483         fprintf (outfil, "\n    %s argument set:", synobj->name);
1484         prthdr = FALSE;
1485         }
1486         
1487     fprintf (outfil, "\n      %s", synres->name);
1488     fprintf (outfil, "\n\tType = %s", resobj->dtype_def->syndef->name);
1489     if ( strcmp(synres->name,synres->resliteral) != 0 )
1490         fprintf (outfil, "\tResourceLiteral = %s", synres->resliteral);
1491     switch ( resref->exclude )
1492         {
1493         case WmlAttributeTrue:
1494             fprintf (outfil, "\n\tExclude = True;");
1495             break;
1496         case WmlAttributeFalse:
1497             fprintf (outfil, "\n\tExclude = False;");
1498             break;
1499         }
1500     if ( resref->dflt != NULL )
1501         fprintf (outfil, "\n\tDefault = \"%s\"", resref->dflt);
1502     else
1503         if ( synres->dflt != NULL )
1504             fprintf (outfil, "\n\tDefault = \"%s\"", synres->dflt);
1505     resobj->ref_ptr = NULL;
1506     }
1507
1508 /*
1509  * Print the constraints valid in the class
1510  */
1511 if ( constr )
1512     {
1513     prthdr = TRUE;
1514     for ( ndx=0 ; ndx<wml_obj_arg_ptr->cnt ; ndx++ )
1515         {
1516         resobj = (WmlResourceDefPtr) wml_obj_arg_ptr->hvec[ndx].objptr;
1517         resref = resobj->ref_ptr;
1518         if ( resref == NULL ) continue;
1519         if ( wmlResolveResIsMember(resobj,clsobj->arguments) == NULL ) continue;
1520         synres = resobj->syndef;
1521         switch ( synres->type )
1522             {
1523             case WmlResourceTypeConstraint:
1524                 break;
1525             default:
1526                 continue;
1527                 break;
1528             }
1529         if ( prthdr )
1530             {
1531             fprintf (outfil, "\n    %s constraint set:", synobj->name);
1532             prthdr = FALSE;
1533             }
1534         fprintf (outfil, "\n      %s", synres->name);
1535         if ( strcmp(synres->name,synres->resliteral) != 0 )
1536             fprintf (outfil, "\tResourceLiteral = %s", synres->resliteral);
1537         switch ( resref->exclude )
1538             {
1539             case WmlAttributeTrue:
1540                 fprintf (outfil, "\n\tExclude = True;");
1541                 break;
1542             case WmlAttributeFalse:
1543                 fprintf (outfil, "\n\tExclude = False;");
1544                 break;
1545             }
1546         if ( resref->dflt != NULL )
1547             fprintf (outfil, "\n\tDefault = \"%s\"", resref->dflt);
1548         else
1549             if ( synres->dflt != NULL )
1550                 fprintf (outfil, "\n\tDefault = \"%s\"", synres->dflt);
1551         resobj->ref_ptr = NULL;
1552         }
1553     }
1554
1555 }
1556
1557
1558 \f
1559 /*
1560  * Routine to print reasons in a class.
1561  *
1562  * Like printing arguments, only reasons instead.
1563  */
1564
1565 void wmlResolvePrintClassReasons (outfil, clsobj)
1566     FILE                        *outfil;
1567     WmlClassDefPtr              clsobj;
1568
1569 {
1570
1571 int                     prthdr = TRUE;  /* print header flag */
1572 int                     ndx;            /* loop index */
1573 WmlSynClassDefPtr       synobj;         /* syntactic object */
1574 WmlClassResDefPtr       resref;         /* resource reference */
1575 WmlResourceDefPtr       resobj;         /* current resource */
1576 WmlSynResourceDefPtr    synres;         /* syntactic resource object */
1577
1578
1579 /*
1580  * Print the superclass reasons
1581  */
1582 if ( clsobj->superclass != NULL )
1583     wmlResolvePrintClassReasons (outfil, clsobj->superclass);
1584
1585 /*
1586  * Print the parentclass reasons
1587  */
1588 if ( clsobj->parentclass != NULL )
1589     wmlResolvePrintClassReasons (outfil, clsobj->parentclass);
1590
1591 /*
1592  * Print the reasons for this class. Unmark the reference so it won't
1593  * be printed again.
1594  */
1595 synobj = clsobj->syndef;
1596 for ( ndx=0 ; ndx<wml_obj_reason_ptr->cnt ; ndx++ )
1597     {
1598     resobj = (WmlResourceDefPtr) wml_obj_reason_ptr->hvec[ndx].objptr;
1599     resref = resobj->ref_ptr;
1600     if ( resref == NULL ) continue;
1601     if ( wmlResolveResIsMember(resobj,clsobj->reasons) == NULL ) continue;
1602     synres = resobj->syndef;
1603     if ( prthdr )
1604         {
1605         fprintf (outfil, "\n    %s reason set:", synobj->name);
1606         prthdr = FALSE;
1607         }
1608     fprintf (outfil, "\n      %s", synres->name);
1609     if ( strcmp(synres->name,synres->resliteral) != 0 )
1610         fprintf (outfil, "\tResourceLiteral = %s", synres->resliteral);
1611     switch ( resref->exclude )
1612         {
1613         case WmlAttributeTrue:
1614             fprintf (outfil, "\n\tExclude = True;");
1615             break;
1616         case WmlAttributeFalse:
1617             fprintf (outfil, "\n\tExclude = False;");
1618             break;
1619         }
1620     resobj->ref_ptr = NULL;
1621     }
1622 }
1623
1624
1625 \f
1626 /*
1627  * Routine to mark reference pointers for a class
1628  *
1629  * This routine clears all reference pointers, then marks the class and
1630  * resource objects to flag those contained in the current class. This
1631  * allows processing of the widget and resource vectors in order to produce
1632  * bit masks or reports.
1633  */
1634
1635 void wmlMarkReferencePointers (clsobj)
1636     WmlClassDefPtr              clsobj;
1637
1638 {
1639
1640 int                     ndx;            /* loop index */
1641 WmlClassDefPtr          mrkcls;         /* class object to mark */
1642 WmlResourceDefPtr       mrkres;         /* resource object to mark */
1643 WmlClassResDefPtr       resref;         /* resource reference */
1644 WmlClassCtrlDefPtr      ctrlref;        /* controls reference */
1645
1646
1647 /*
1648  * Clear the reference pointers. Then go through the arguments, reasons,
1649  * and controls lists, and mark the referenced classes.
1650  */
1651 wmlResolveClearRefPointers ();
1652 for ( resref=clsobj->arguments ; resref!= NULL ; resref=resref->next )
1653     resref->act_resource->ref_ptr = resref;
1654 for ( resref=clsobj->reasons ; resref!= NULL ; resref=resref->next )
1655     resref->act_resource->ref_ptr = resref;
1656 for ( ctrlref=clsobj->controls ; ctrlref!=NULL ; ctrlref=ctrlref->next )
1657     ctrlref->ctrl->ref_ptr = ctrlref;
1658
1659 }
1660
1661
1662 \f
1663 /*
1664  * Routine to clear reference pointers
1665  */
1666
1667 void wmlResolveClearRefPointers ()
1668
1669 {
1670
1671 int                     ndx;            /* loop index */
1672 WmlClassDefPtr          mrkcls;         /* class object to mark */
1673 WmlResourceDefPtr       mrkres;         /* resource object to mark */
1674 WmlChildDefPtr          mrkcld;         /* child object to mark */
1675
1676 for ( ndx=0 ; ndx<wml_obj_allclass_ptr->cnt ; ndx++ )
1677     {
1678     mrkcls = (WmlClassDefPtr) wml_obj_allclass_ptr->hvec[ndx].objptr;
1679     mrkcls->ref_ptr = NULL;
1680     }
1681 for ( ndx=0 ; ndx<wml_obj_reason_ptr->cnt ; ndx++ )
1682     {
1683     mrkres = (WmlResourceDefPtr) wml_obj_reason_ptr->hvec[ndx].objptr;
1684     mrkres->ref_ptr = NULL;
1685     }
1686 for ( ndx=0 ; ndx<wml_obj_arg_ptr->cnt ; ndx++ )
1687     {
1688     mrkres = (WmlResourceDefPtr) wml_obj_arg_ptr->hvec[ndx].objptr;
1689     mrkres->ref_ptr = NULL;
1690     }
1691 for ( ndx=0 ; ndx<wml_obj_child_ptr->cnt ; ndx++ )
1692     {
1693     mrkcld = (WmlChildDefPtr) wml_obj_child_ptr->hvec[ndx].objptr;
1694     mrkcld->ref_ptr = NULL;
1695     }
1696
1697 }
1698
1699
1700 \f
1701 /*
1702  * Routine to find an object for binding. The name is always looked
1703  * in the syntactic object list, since all references made by the
1704  * user are in that list (resolved objects may be entered under
1705  * an internal literal, and not be found). This routine always attempts to
1706  * return a resolved object (which depends on object type). It also guarantees
1707  * that the object it finds matches the given type.
1708  *
1709  *      name            the object to be found
1710  *      type            type the object should match
1711  *      requester       requester name, for error messages
1712  *
1713  * Returns:     pointer to the object found
1714  */
1715
1716 ObjectPtr wmlResolveFindObject (name, type, requester)
1717     char                        *name;
1718     int                         type;
1719     char                        *requester;
1720
1721 {
1722
1723 int                     objndx;         /* the object index in the list */
1724 WmlSynDefPtr            synobj;         /* syntactic object */
1725 char                    errmsg[300];
1726
1727
1728 objndx = wmlFindInHList (wml_synobj_ptr, name);
1729 if ( objndx < 0 )
1730     {
1731     wmlIssueReferenceError (requester, name);
1732     return NULL;
1733     }
1734 synobj = (WmlSynDefPtr) wml_synobj_ptr ->hvec[objndx].objptr;
1735 if ( synobj->validation != type )
1736     {
1737     sprintf (errmsg,
1738              "Object %s references object %s\n\tin a context where a different type of object is required",
1739             requester, name);
1740     wmlIssueError (errmsg);
1741     return NULL;
1742     }
1743 switch ( synobj->validation )
1744     {
1745     case WmlClassDefValid:
1746     case WmlResourceDefValid:
1747     case WmlDataTypeDefValid:
1748     case WmlCtrlListDefValid:
1749     case WmlEnumSetDefValid:
1750     case WmlEnumValueDefValid:
1751     case WmlChildDefValid:
1752         return (ObjectPtr) synobj->rslvdef;
1753         break;
1754     default:
1755         return (ObjectPtr) synobj;
1756     }
1757
1758 }
1759
1760
1761 /*
1762  * Report an object reference error
1763  *
1764  *      srcname         the object making the reference
1765  *      badname         the missing object
1766  */
1767
1768 void wmlIssueReferenceError (srcname, badname)
1769     char                        *srcname;
1770     char                        *badname;
1771
1772 {
1773
1774 printf ("\nObject %s references undefined object %s", srcname, badname);
1775 wml_err_count += 1;
1776
1777 }
1778
1779
1780 /*
1781  * Report an attempt to make a reference which is not supported.
1782  */
1783
1784 void wmlIssueIllegalReferenceError (srcname, badname)
1785     char                        *srcname;
1786     char                        *badname;
1787
1788 {
1789
1790 printf ("\nObject %s cannot reference a %s object", srcname, badname);
1791 wml_err_count += 1;
1792
1793 }
1794
1795
1796 /*
1797  * Report an error string.
1798  */
1799 void wmlIssueError (errstg)
1800     char                        *errstg;
1801
1802 {
1803
1804 printf ("\n%s", errstg);
1805 wml_err_count += 1;
1806
1807 }