Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / osf / uil / UilDB.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: UilDB.c /main/11 1996/11/21 20:03:11 drk $"
14 #endif
15 #endif
16
17 /*
18 *  (c) Copyright 1989, 1990, DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. */
19
20
21 /*
22  *++
23  *  FACILITY:
24  *
25  *      UIL Bindary Database :
26  *
27  *  ABSTRACT:
28  *
29  *--
30  */
31
32 /*
33  * This file contains routines which change the internal tables of UIL based on
34  * a binary data base parameter in the command line 
35  */
36
37
38 /*
39  *
40  *  INCLUDE FILES
41  *
42  */
43
44 #ifndef X_NOT_STDC_ENV
45 #include <stdlib.h>
46 #include <unistd.h>
47 #endif
48
49 #include <Mrm/MrmAppl.h>
50 #include <Mrm/Mrm.h>
51
52 #include "UilDefI.h"
53
54 #define X_INCLUDE_PWD_H
55 #define XOS_USE_XT_LOCKING
56 #include <X11/Xos_r.h>
57 #include <stdio.h>
58
59 /*
60  *
61  *  TABLE OF CONTENTS
62  *
63  *
64  */
65
66
67 /*
68  *
69  *  DEFINE and MACRO DEFINITIONS
70  *
71  */
72 #define _check_read( __number_returned ) \
73         if (( (__number_returned) != 1) || (feof(dbfile)) || (ferror(dbfile)) ) \
74         {  diag_issue_diagnostic( d_bad_database, diag_k_no_source, diag_k_no_column ); } 
75
76
77
78
79 /*
80  *
81  *  EXTERNAL VARIABLE DECLARATIONS
82  *
83  */
84
85 /*
86  *
87  *  GLOBAL VARIABLE DECLARATIONS
88  *
89  */
90
91
92 /*
93  *
94  *  OWN VARIABLE DECLARATIONS
95  *
96  */
97 static FILE *dbfile;
98 static int  num_bits;
99 \f
100 void db_incorporate()
101
102 /*
103  *++
104  *
105  *  PROCEDURE DESCRIPTION:
106  *
107  *      This routine incorporate the binary database passed in the command line.
108  *
109  *
110  *  FORMAL PARAMETERS:
111  *
112  *  IMPLICIT INPUTS:
113  *
114  *  IMPLICIT OUTPUTS:
115  *
116  *  FUNCTION VALUE:
117  *
118  *  SIDE EFFECTS:
119  *
120  *--
121  */
122
123 /*
124  *  External Functions
125  */
126
127 /*
128  *  Local variables
129  */
130 {
131     int                 return_num_items;
132     _db_header          header;
133     _db_globals         globals;
134
135     db_open_file();
136
137     return_num_items = fread (&globals, sizeof(_db_globals), 1, dbfile);
138     _check_read (return_num_items);
139
140     /*
141      * Some heuristics to see if this is a reasonable database.
142      * The magic numbers are about 10 times as big as the DXm database
143      * for DECWindows V3. The diagnostic does a fatal exit.
144      */
145     if ( globals.uil_max_arg>5000 ||
146          globals.uil_max_charset>200 ||
147          globals.charset_lang_table_max>1000 ||
148          globals.uil_max_object>500 ||
149          globals.uil_max_reason>1000 ||
150          globals.uil_max_enumval>3000 ||
151          globals.uil_max_enumset>1000 ||
152          globals.key_k_keyword_count>10000 ||
153          globals.key_k_keyword_max_length>200 ||
154          globals.uil_max_child>250)
155         diag_issue_diagnostic (d_bad_database,
156                                diag_k_no_source,
157                                diag_k_no_column);
158
159     uil_max_arg = globals.uil_max_arg ;
160     uil_max_charset = globals.uil_max_charset ;
161     charset_lang_table_max = globals.charset_lang_table_max ;
162     uil_max_object = globals.uil_max_object ;
163     uil_max_reason = globals.uil_max_reason ;
164     uil_max_enumval = globals.uil_max_enumval ;
165     uil_max_enumset = globals.uil_max_enumset ;
166     key_k_keyword_count = globals.key_k_keyword_count ;
167     key_k_keyword_max_length = globals.key_k_keyword_max_length ;
168     uil_max_child = globals.uil_max_child;
169     num_bits = (uil_max_object +7) / 8;
170
171     if (globals.version > DB_Compiled_Version) 
172         diag_issue_diagnostic( d_future_version, diag_k_no_source, diag_k_no_column );
173
174     for (;;) 
175         {
176         return_num_items = fread (&header, sizeof(_db_header), 1, dbfile);
177         if (feof(dbfile)) break;
178         _check_read (return_num_items);
179         switch (header.table_id)
180             {
181             case Constraint_Tab:
182                 constraint_tab = (unsigned char *) XtMalloc (header.table_size);
183                 return_num_items = fread (constraint_tab, 
184                                              sizeof(unsigned char) * header.num_items,
185                                              1, dbfile);
186                 _check_read (return_num_items);
187                 break;
188             case Argument_Type_Table_Value:
189                 /*
190                  * NOTE: The first entry is not used but we copy it anyway
191                  */
192                 argument_type_table = (unsigned char *) XtMalloc (header.table_size);
193                 return_num_items = fread (argument_type_table,
194                                              sizeof(unsigned char) * header.num_items,
195                                              1, dbfile);
196                 _check_read (return_num_items);
197                 break;
198             case Child_Class_Table:
199                 /*
200                  * NOTE: The first entry is not used but we copy it anyway
201                  */
202                 child_class_table = 
203                   (unsigned char *) XtMalloc (header.table_size);
204                 return_num_items = 
205                   fread (child_class_table,
206                          sizeof(unsigned char) * header.num_items, 1, dbfile);
207                 _check_read (return_num_items);
208                 break;
209             case Charset_Wrdirection_Table:
210                 charset_writing_direction_table = (unsigned char *) XtMalloc (header.table_size);
211                 return_num_items = fread (charset_writing_direction_table, 
212                                              sizeof(unsigned char) * header.num_items,
213                                              1, dbfile);
214                 _check_read (return_num_items);
215                 break;
216             case Charset_Parsdirection_Table:
217                 charset_parsing_direction_table = (unsigned char *) XtMalloc (header.table_size);
218                 return_num_items = fread (charset_parsing_direction_table, 
219                                              sizeof(unsigned char) * header.num_items,
220                                              1, dbfile);
221                 _check_read (return_num_items);
222                 break;
223             case Charset_Charsize_Table:
224                 charset_character_size_table = (unsigned char *) XtMalloc (header.table_size);
225                 return_num_items = fread (charset_character_size_table, 
226                                              sizeof(unsigned char) * header.num_items,
227                                              1, dbfile);
228                 _check_read (return_num_items);
229                 break;
230             case Key_Table:
231             case Key_Table_Case_Ins:
232                 db_read_ints_and_string (&header);
233                 break;
234             case Allowed_Argument_Table:
235             case Allowed_Child_Table:
236             case Allowed_Control_Table:
237             case Allowed_Reason_Table:
238                 db_read_char_table (&header);
239                 break;
240             case Charset_Xmstring_Names_Table:
241             case Charset_Lang_Names_Table:
242             case Uil_Widget_Names:
243             case Uil_Children_Names:
244             case Uil_Argument_Names:
245             case Uil_Reason_Names:
246             case Uil_Enumval_names:
247             case Uil_Charset_Names:
248             case Uil_Widget_Funcs:
249             case Uil_Argument_Toolkit_Names:
250             case Uil_Reason_Toolkit_Names:
251                 db_read_length_and_string (&header);
252                 break;
253             case Charset_Lang_Codes_Table:
254                 charset_lang_codes_table = (unsigned short int *) XtMalloc (header.table_size);
255                 return_num_items = fread (charset_lang_codes_table, 
256                                              header.table_size,
257                                              1, dbfile);
258                 _check_read (return_num_items);
259                 break;
260             case Argument_Enum_Set_Table:
261                 argument_enumset_table = (unsigned short int *) XtMalloc (header.table_size);
262                 return_num_items = fread (argument_enumset_table, 
263                                              header.table_size,
264                                              1, dbfile);
265                 _check_read (return_num_items);
266                 break;
267             case Related_Argument_Table:
268                 related_argument_table = (unsigned short int *) XtMalloc (header.table_size);
269                 return_num_items = fread (related_argument_table, 
270                                              header.table_size,
271                                              1, dbfile);
272                 _check_read (return_num_items);
273                 break;
274             case Uil_Gadget_Funcs:
275                 uil_gadget_variants = (unsigned short int *) XtMalloc (header.table_size);
276                 return_num_items = fread (uil_gadget_variants, 
277                                              header.table_size,
278                                              1, dbfile);
279                 _check_read (return_num_items);
280                 break;
281             case Uil_Urm_Nondialog_Class:
282                 uil_urm_nondialog_class = (unsigned short int *) XtMalloc (header.table_size);
283                 return_num_items = fread (uil_urm_nondialog_class, 
284                                              header.table_size,
285                                              1, dbfile);
286                 _check_read (return_num_items);
287                 break;
288             case Uil_Urm_Subtree_Resource:
289                 uil_urm_subtree_resource = (unsigned short int *) XtMalloc (header.table_size);
290                 return_num_items = fread (uil_urm_subtree_resource, 
291                                              header.table_size,
292                                              1, dbfile);
293                 _check_read (return_num_items);
294                 break;
295             case Enum_Set_Table:
296                 db_read_int_and_shorts(&header);
297                 break;
298             case Enumval_Values_Table:
299                 enumval_values_table = (int *) XtMalloc (header.table_size);
300                 return_num_items = fread (enumval_values_table, 
301                                              header.table_size,
302                                              1, dbfile);
303                 _check_read (return_num_items);
304                 break;
305             default:
306                 diag_issue_diagnostic( d_bad_database, diag_k_no_source, diag_k_no_column );
307             } /* end switch */
308         } /* end for */
309     fclose (dbfile);
310     return;
311 }
312
313
314 \f
315 void db_read_ints_and_string(header)
316     _db_header_ptr   header;
317
318 /*
319  *++
320  *
321  *  PROCEDURE DESCRIPTION:
322  *
323  *      This routine reads in tables of integers and one string unsigned chars and places them into 
324  *      memory. It will Malloc new space for the table. The tables supported
325  *      this routine are:
326  *
327  *          Key_Table:
328  *          Key_Table_Case_Ins:
329  *
330  *
331  *  FORMAL PARAMETERS:
332  *
333  *  IMPLICIT INPUTS:
334  *
335  *  IMPLICIT OUTPUTS:
336  *
337  *  FUNCTION VALUE:
338  *
339  *  SIDE EFFECTS:
340  *
341  *--
342  */
343
344 {
345
346 /*
347  *  External Functions
348  */
349
350 /*
351  *  Local variables
352  */
353         int                     return_num_items, i, string_size=0;
354         key_keytable_entry_type *table;
355         char                    *string_table;
356          
357         switch (header->table_id)
358             {
359             /*
360              * NOTE: Calloc is used here to protect against bad
361              *       pointers.
362              */
363             case Key_Table:
364                 key_table = (key_keytable_entry_type *) XtCalloc (1, header->table_size);
365                 table = key_table;
366                 break;
367             case Key_Table_Case_Ins:
368                 key_table_case_ins = (key_keytable_entry_type *) XtCalloc (1, header->table_size);
369                 table = key_table_case_ins;
370                 break;
371             default:
372                 diag_issue_internal_error ("Bad table_id in db_read_ints_and_string");
373             }
374
375         /* 
376          * Get the entire table with one read. 
377          * Then loop through the table and up the length of the strings.
378          * Get all the strings with one read.
379          * Reassign the addresses
380          */
381         return_num_items = fread(table, header->table_size, 1, dbfile);
382         _check_read (return_num_items);
383
384         for ( i=0 ; i<header->num_items; i++)
385             {
386             /*
387              * Add one for the null character on the string
388              */
389             string_size += table[i].b_length + 1;
390             };
391
392         string_table = XtMalloc (sizeof (char) * string_size);
393         return_num_items = fread(string_table, 
394                                     sizeof(unsigned char) * string_size,
395                                     1, dbfile);
396         _check_read (return_num_items);
397
398         for ( i=0 ; i<header->num_items; i++)
399             {
400             table[i].at_name = string_table;
401             string_table +=  table[i].b_length + 1; 
402             };
403
404         return;
405 }
406
407
408 \f
409 void db_read_char_table(header)
410     _db_header_ptr   header;
411
412 /*
413  *++
414  *
415  *  PROCEDURE DESCRIPTION:
416  *
417  *      This routine reads in tables of unsigned chars and places them into 
418  *      memory. It will Malloc new space for the table. The tables supported
419  *      this routine are:
420  *
421  *          Allowed_Argument_Table:
422  *          Allowed_Child_Table:
423  *          Allowed_Control_Table:
424  *          Allowed_Reason_Table:
425  *
426  *
427  *  FORMAL PARAMETERS:
428  *
429  *  IMPLICIT INPUTS:
430  *
431  *  IMPLICIT OUTPUTS:
432  *
433  *  FUNCTION VALUE:
434  *
435  *  SIDE EFFECTS:
436  *
437  *--
438  */
439
440 {
441
442 /*
443  *  External Functions
444  */
445
446 /*
447  *  Local variables
448  */
449         unsigned char   **ptr;
450         int             return_num_items, i;
451         unsigned char   *table;
452          
453         switch (header->table_id)
454             {
455             /*
456              * NOTE: Calloc is used here to protect against bad
457              *       pointers.
458              */
459             case Allowed_Argument_Table:
460                 allowed_argument_table = (unsigned char **) XtCalloc (1, header->table_size);
461                 ptr = allowed_argument_table;
462                 break;
463             case Allowed_Child_Table:
464                 allowed_child_table = 
465                   (unsigned char **) XtCalloc (1, header->table_size);
466                 ptr = allowed_child_table;
467                 break;
468             case Allowed_Control_Table:
469                 allowed_control_table = (unsigned char **) XtCalloc (1, header->table_size);
470                 ptr = allowed_control_table;
471                 break;
472             case Allowed_Reason_Table:
473                 allowed_reason_table = (unsigned char **) XtCalloc (1, header->table_size);
474                 ptr = allowed_reason_table;
475                 break;
476             default:
477                 diag_issue_internal_error ("Bad table_id in db_read_char_table");
478         }
479
480         /*
481          * Read in the entire table contents in one whack.
482          * Then go through the table and set the addresses
483          */
484         table = (unsigned char *) XtMalloc (sizeof (unsigned char) * header->num_items * num_bits);
485         return_num_items = fread(table, 
486                                     sizeof(char) * num_bits * header->num_items,
487                                     1, dbfile);
488         _check_read (return_num_items);
489         for ( i=1 ; i<=header->num_items; i++ )
490             {
491             ptr[i] = table;
492             table += num_bits;
493             };
494
495         return;
496 }
497
498
499 \f
500 void db_read_length_and_string(header)
501     _db_header_ptr   header;
502
503 /*
504  *++
505  *
506  *  PROCEDURE DESCRIPTION:
507  *
508  *      This routine reads in length and strings of unsigned chars and places them into 
509  *      memory. It will Malloc new space for the table. The tables supported
510  *      this routine are:
511  *
512  *          Charset_Xmstring_Names_Table:
513  *          Charset_Lang_Names_Table:
514  *          Uil_Widget_Names:
515  *          Uil_Children_Names:
516  *          Uil_Argument_Names:
517  *          Uil_Reason_Names:
518  *          Uil_Enumval_names:
519  *          Uil_Charset_Names:
520  *          Uil_Widget_Funcs:
521  *          Uil_Argument_Toolkit_Names:
522  *          Uil_Reason_Toolkit_Names:
523  *
524  *
525  *  FORMAL PARAMETERS:
526  *
527  *  IMPLICIT INPUTS:
528  *
529  *  IMPLICIT OUTPUTS:
530  *
531  *  FUNCTION VALUE:
532  *
533  *  SIDE EFFECTS:
534  *
535  *--
536  */
537
538 {
539
540 /*
541  *  External Functions
542  */
543
544 /*
545  *  Local variables
546  */
547         int             return_num_items, i, string_size=0;
548         int             *lengths;
549         char            *string_table;
550         char            **table;
551          
552         switch (header->table_id)
553             {
554             /*
555              * NOTE: Calloc is used here because it might be possible to
556              *       have a string of zero length, particularly for the
557              *       first record. Ergo we Calloc to protect against bad
558              *       pointers.
559              */
560             case Charset_Xmstring_Names_Table:
561                 charset_xmstring_names_table = (char **) XtCalloc (1, header->table_size);
562                 table = charset_xmstring_names_table;
563                 break;
564             case Charset_Lang_Names_Table:
565                 charset_lang_names_table = (char **) XtCalloc (1, header->table_size);
566                 table = charset_lang_names_table;
567                 break;
568             case Uil_Widget_Names:
569                 uil_widget_names = (char **) XtCalloc (1, header->table_size);
570                 table = uil_widget_names ;
571                 break;
572             case Uil_Children_Names:
573                 uil_child_names = (char **) XtCalloc (1, header->table_size);
574                 table = uil_child_names ;
575                 break;
576             case Uil_Argument_Names:
577                 uil_argument_names = (char **) XtCalloc (1, header->table_size);
578                 table = uil_argument_names;
579                 break;
580             case Uil_Reason_Names:
581                 uil_reason_names = (char **) XtCalloc (1, header->table_size);
582                 table = uil_reason_names;
583                 break;
584             case Uil_Enumval_names:
585                 uil_enumval_names = (char **) XtCalloc (1, header->table_size);
586                 table = uil_enumval_names;
587                 break;
588             case Uil_Charset_Names:
589                 uil_charset_names = (char **) XtCalloc (1, header->table_size);
590                 table = uil_charset_names;
591                 break;
592             case Uil_Widget_Funcs:
593                 uil_widget_funcs = (char **) XtCalloc (1, header->table_size);
594                 table = uil_widget_funcs;
595                 break;
596             case Uil_Argument_Toolkit_Names:
597                 uil_argument_toolkit_names = (char **) XtCalloc (1, header->table_size);
598                 table = uil_argument_toolkit_names;
599                 break;
600             case Uil_Reason_Toolkit_Names:
601                 uil_reason_toolkit_names = (char **) XtCalloc (1, header->table_size);
602                 table = uil_reason_toolkit_names;
603                 break;
604             default:
605                 diag_issue_internal_error ("Bad table_id in db_read_length_and_string");
606             }
607
608         /* 
609          * Get the lengths of all the strings with one read.  
610          * Then loop through the table and up the length of the strings.
611          * Get all the strings with one read. 
612          * Reassign the addresses using the length table and string table.
613          * Cleanup by Freeing length table.
614          * 
615          * NOTE: In some tables the counting starts at 1 not 0 so you
616          *       have to be carefull.
617          */
618
619         lengths = (int *) XtMalloc (sizeof (int) * (header->num_items + 1));
620         return_num_items = fread(lengths, 
621                                     sizeof(int) * (header->num_items + 1),
622                                     1, dbfile);
623         _check_read (return_num_items);
624         for ( i=0 ; i<=header->num_items; i++)
625             {
626             /*
627              * Add one for the null terminator
628              */
629             if (lengths[i])
630                 {
631                 string_size += lengths[i] + 1;
632                 }
633             }
634
635         string_table = XtMalloc (sizeof (unsigned char) * string_size);
636         return_num_items = fread(string_table, 
637                                     sizeof(unsigned char) * string_size,
638                                     1, dbfile);
639         _check_read (return_num_items);
640         for ( i=0 ; i<=header->num_items; i++)
641             {
642             if (lengths[i])
643                 {
644                 table[i] = string_table;
645 /* BEGIN HaL Fix CR 5618 */
646                   if ((header->table_id == Uil_Widget_Names) &&
647                       (strcmp(table[i], "user_defined") == 0))
648                     uil_sym_user_defined_object = i;
649 /* END HaL Fix CR 5618 */
650                 string_table +=  lengths[i] + 1;
651                 }
652             }
653
654         XtFree ((char *)lengths);
655
656         return;
657 }
658
659
660 \f
661 void db_read_int_and_shorts(header)
662     _db_header_ptr   header;
663
664 /*
665  *++
666  *
667  *  PROCEDURE DESCRIPTION:
668  *
669  *      This routine reads in a structure consisting of one integer and a 
670  *      pointer to a table of integer and places them into 
671  *      memory. It will Malloc new space for the table. The tables supported
672  *      this routine are:
673  *
674  *          Enum_Set_Table:
675  *
676  *
677  *  FORMAL PARAMETERS:
678  *
679  *  IMPLICIT INPUTS:
680  *
681  *  IMPLICIT OUTPUTS:
682  *
683  *  FUNCTION VALUE:
684  *
685  *  SIDE EFFECTS:
686  *
687  *--
688  */
689
690 {
691
692 /*
693  *  External Functions
694  */
695
696 /*
697  *  Local variables
698  */
699         int                     return_num_items, i, int_table_size=0;
700         UilEnumSetDescDef       *table;
701         unsigned short int      *int_table;
702          
703         switch (header->table_id)
704             {
705             case Enum_Set_Table:
706                 enum_set_table = (UilEnumSetDescDef *) XtCalloc (1, header->table_size);
707                 table = enum_set_table;
708                 break;
709             default:
710                 diag_issue_internal_error ("Bad table_id in db_read_int_shorts");
711             }
712
713         /* 
714          * Get the entire table with one read. 
715          * Then loop through the table and add up the number of ints in each int table.
716          * Get all the integer tables with one read.
717          * Reassign the addresses of the tables.
718          */
719         return_num_items = fread(table, header->table_size, 1, dbfile);
720         _check_read (return_num_items);
721         for ( i=0 ; i<=header->num_items; i++)
722             {
723             int_table_size += table[i].values_cnt;
724             }
725
726         int_table = (unsigned short int *) XtCalloc (1, sizeof (short) * int_table_size);
727         return_num_items = fread(int_table, 
728                                     sizeof(short) * int_table_size,
729                                     1, dbfile);
730         _check_read (return_num_items);
731         for ( i=0 ; i<=header->num_items; i++)
732             {
733             if (table[i].values_cnt)
734                 {
735                 table[i].values = int_table;
736                 int_table += table[i].values_cnt;
737                 }
738             }
739
740         return;
741 }
742
743
744 \f
745 void db_open_file ()
746
747 /*
748  *++
749  *
750  *  PROCEDURE DESCRIPTION:
751  *
752  *      This routine opens the binary database file in a platform-dependent way,
753  *      performing i18n language switching in order to do so.
754  *
755  *      Per the latest agreement on semantics, this routine does:
756  *              - first, try to open in the local directory (that is, with
757  *                no switching).
758  *              - second, try language switching and open
759  *
760  *  FORMAL PARAMETERS:
761  *
762  *      name            A system-dependent string specifying the IDB file
763  *                      to be opened.
764  *
765  *  IMPLICIT INPUTS:
766  *
767  *  IMPLICIT OUTPUTS:
768  *
769  *  FUNCTION VALUE:
770  *
771  *  SIDE EFFECTS:
772  *
773  *--
774  */
775
776 {
777
778 /*
779  *  External Functions
780  */
781
782 /*
783  *  Local variables
784  */
785         char                    *resolvedname;          /* current resolved name */
786         SubstitutionRec         subs[3];
787         char                    *wmdPath;
788
789         /*
790          * Use XtFindFile instead of XtResolvePathName. XtResolvePathName requires a
791          * display which UIL doesn't have. At the current time there is no support for
792          * $LANG in the path string. If such support was deamed necessary, the %L, %l,
793          * %t, %c values would be set up as subs here using globals from the fetch of
794          * LANG variable used to determine the default codeset (or vice versa depending
795          * on which is called first) 
796          *
797          * If the last 4 characters of the file name are not .bdb
798          * then pass in the suffix of .bdb. If a file isn't found with the suffix passed
799          * in then try without the suffix.
800          */
801
802         /*
803          * Make sure 'S' is the last one so we can remove the suffix for the first pass.
804          */
805         subs[0].match = 'N';
806         subs[0].substitution = Uil_cmd_z_command.ac_database;
807         subs[1].match = 'T';
808         subs[1].substitution = "wmd";
809         subs[2].match = 'S';
810         subs[2].substitution = ".wmd";
811
812         wmdPath = init_wmd_path(Uil_cmd_z_command.ac_database);
813
814         resolvedname = 0;
815
816         /*
817          * Check and see if the .wmd suffix is already on the file. If not then try to
818          * resolve the pathname with .wmd suffix first. If that fails or the suffix is
819          * already on the file then just try to resolve the pathname.
820          */
821         if ( strcmp (&Uil_cmd_z_command.ac_database[strlen(Uil_cmd_z_command.ac_database)-4],".wmd") != 0 ) 
822                 resolvedname = XtFindFile(wmdPath,
823                                               subs,
824                                               XtNumber(subs),
825                                               (XtFilePredicate)NULL);
826
827         /*
828          * No .wmd suffix or a failure to resolve the pathname with the .wmd suffix
829          * Try without the suffix.
830          */
831         subs[2].substitution = "";
832         if (resolvedname == 0) 
833                 resolvedname = XtFindFile(wmdPath,
834                                               subs,
835                                               XtNumber(subs),
836                                               (XtFilePredicate)NULL);
837
838         if (resolvedname == 0)
839             {
840             diag_issue_diagnostic( d_wmd_open,
841                                    diag_k_no_source, diag_k_no_column,
842                                    Uil_cmd_z_command.ac_database);
843             }
844
845         dbfile = fopen (resolvedname, "r");
846
847         /* If the file is not found, a fatal error is generated.        */
848         if (dbfile == NULL)
849             {
850             diag_issue_diagnostic( d_src_open,
851                                    diag_k_no_source, diag_k_no_column,
852                                    resolvedname);
853             }
854
855         return;
856 }
857
858
859 \f
860
861 String get_root_dir_name()
862 {
863         int uid;
864         _Xgetpwparams pwd_buf;
865         struct passwd *pwd_value;
866         static char *ptr = NULL;
867         char *outptr;
868
869         if (ptr == NULL)
870         {
871         if((ptr = (char *)getenv("HOME")) == NULL) 
872             {
873             if((ptr = (char *)getenv(USER_VAR)) != NULL) 
874                 {
875                 pwd_value = _XGetpwnam(ptr, pwd_buf);
876                 }
877             else 
878                 {
879                 uid = getuid();
880                 pwd_value = _XGetpwuid(uid, pwd_buf);
881                 }
882             if (pwd_value != NULL)
883                 {
884                 ptr = pwd_value->pw_dir;
885                 }
886             else 
887                 {
888                  ptr = "";
889                 }
890             }
891         }
892
893         outptr = XtMalloc (strlen(ptr) + 2);
894         strcpy (outptr, ptr);
895         strcat (outptr, "/");
896         return outptr; 
897 }
898 \f
899 /*
900  * XAPPLRES_DEFAULT and UIDPATH_DEFAULT are intentionally split to support
901  * SCCS. DO NOT reformat the lines else %-N-%-S could be converted by SCCS into
902  * something totally bizarre causing MrmOpenHierarchy failures.
903  */
904
905 /* The following are usually defined in the Makefile */
906
907 #ifndef LIBDIR
908 #define LIBDIR "/usr/lib/X11"
909 #endif
910 #ifndef INCDIR
911 #define INCDIR "/usr/include/X11"
912 #endif
913
914 static char libdir[] = LIBDIR;
915 static char incdir[] = INCDIR;
916
917 static char XAPPLRES_DEFAULT[] = "\
918 %%N\
919 %%S:\
920 %s/%%T/%%N\
921 %%S:\
922 %s%%T/%%N\
923 %%S:\
924 %s%%N\
925 %%S:\
926 %s/%%T/%%N\
927 %%S:\
928 %s/%%T/%%N\
929 %%S";
930
931 static char WMDPATH_DEFAULT[] = "\
932 %%N\
933 %%S:\
934 %s%%T/%%N\
935 %%S:\
936 %s%%N\
937 %%S:\
938 %s/%%L/%%T/%%N\
939 %%S:\
940 %s/%%T/%%N\
941 %%S";
942
943 static char ABSOLUTE_PATH[] = "\
944 %N\
945 %S";
946
947 String init_wmd_path(filename)
948     String      filename ;
949 {
950     String path;
951     String old_path;
952     String homedir;
953     String wmd_path;
954
955
956     if (filename[0] == '/')
957         {
958         wmd_path = XtMalloc(strlen(ABSOLUTE_PATH));
959         strcpy (wmd_path, ABSOLUTE_PATH);
960         }
961     else
962         {
963         path = (char *)getenv ("WMDPATH");
964         if (path  == NULL) 
965             {
966             homedir = get_root_dir_name();
967             old_path = (char *)getenv ("XAPPLRESDIR");
968             if (old_path == NULL) 
969                 {
970                 wmd_path = XtCalloc(1, 2*strlen(homedir) +
971                                  strlen(libdir) + strlen(incdir) +
972                                  strlen(WMDPATH_DEFAULT));
973                 sprintf( wmd_path, WMDPATH_DEFAULT,
974                          homedir, homedir, libdir, incdir);
975                 } 
976             else 
977                 {
978                 wmd_path = XtCalloc(1, 1*strlen(old_path) + 2*strlen(homedir) +
979                                  strlen(libdir) + strlen(incdir) +
980                                  strlen(XAPPLRES_DEFAULT));
981                 sprintf(wmd_path, XAPPLRES_DEFAULT, 
982                         old_path,
983                         homedir, homedir, libdir, incdir);
984                 }
985             XtFree (homedir);
986             }
987         else
988             {
989             wmd_path = XtMalloc(strlen(path) + 1);
990             strcpy (wmd_path, path);
991             free (path);
992             }
993         }
994     return (wmd_path);
995 }