1 /*
2  * Motif Tools Library, Version 3.1
3  * $Id: Include.c,v 1.2 2001/09/19 02:57:18 grmcdorman Exp $
4  *
5  * Written by David Flanagan.
6  * Copyright (c) 1992-2001 by David Flanagan.
7  * All Rights Reserved.  See the file COPYRIGHT for details.
8  * This is open source software.  See the file LICENSE for details.
9  * There is no warranty for this software.  See NO_WARRANTY for details.
10  *
11  * $Log: Include.c,v $
12  * Revision 1.2  2001/09/19 02:57:18  grmcdorman
13  * This change makes the following modifications:
14  *   A new program, printConfig, is provided. This is built by a
15  *   simple rule in the Makefile and not installed. It prints
16  *   significant defines from Xmt.tmpl.
17  *
18  *   XmtP.h is now generated from XmtP.h.in using printConfig. As
19  *   a result, code compiled outside of the Xmt Imakefiles will
20  *   have all of the Xmt.tmpl defines.
21  *
22  *   Source files are modified to use XmtP.h instead of Xmt.h.
23  *
24  *   WorkingBox.c is modified to use the new Progress widget.
25  *   It can be compiled in the old style if WORKINGBOX_USE_SCALE is
26  *   defined at compile time.
27  *
28  *   Because XmtP.h is generated dynamically, it is removed from CVS
29  *   with this check-in.
30  *
31  * Revision 1.1.1.1  2001/02/10 13:44:08  motiftools
32  * Initial import of Xmt310 to CVS
33  *
34  *
35  */
36 
37 #include <stdio.h>
38 #include <errno.h>
39 #ifdef VMS
40 #include <perror.h>
41 #endif
42 #include <Xmt/XmtP.h>
43 #include <Xmt/Include.h>
44 #include <Xmt/Hash.h>
45 #include <Xmt/Lexer.h>
46 #include <Xmt/AppResP.h>
47 #include <X11/IntrinsicP.h>
48 
49 #if NeedFunctionPrototypes
load_file_error(String filename)50 static void load_file_error(String filename)
51 #else
52 static void load_file_error(filename)
53 String filename;
54 #endif
55 {
56     XmtWarningMsg("XmtLoadResourceFile", "io",
57 		  "can't load file '%s':\n\t%s.",
58 		  filename, strerror(errno));
59 }
60 
61 
62 /* forward declaration */
63 #if NeedFunctionPrototypes
64 static void LoadResourceFileList(XrmDatabase *, Widget, StringConst);
65 #else
66 static void LoadResourceFileList();
67 #endif
68 
69 
70 #if NeedFunctionPrototypes
LoadResourceFile(XrmDatabase * db,Widget w,StringConst filename,Boolean user,Boolean override)71 static Boolean LoadResourceFile(XrmDatabase *db, Widget w,StringConst filename,
72 				Boolean user, Boolean override)
73 #else
74 static Boolean LoadResourceFile(db, w, filename, user, override)
75 XrmDatabase *db;
76 Widget w;
77 StringConst filename;
78 Boolean user;
79 Boolean override;
80 #endif
81 {
82     static XrmName required_names[2];
83     static XrmClass required_classes[2];
84     static required_quarks_inited = False;
85     XmtAppResources *app = XmtGetApplicationResources(w);
86     XrmRepresentation type;
87     XrmValue value;
88     XrmDatabase newdb = NULL;
89     XrmDatabase userdb = NULL;
90     String full_filename;
91     String user_filename;
92     Boolean found = False;
93     XrmQuark fileq;
94     XtPointer dummy;
95 
96     if (!filename || filename[0] == '\0') return False;
97 
98     /* find our application shell */
99     w = XmtGetApplicationShell(w);
100 
101     /*
102      * one time initialization
103      */
104     if (required_quarks_inited == False) {
105 	required_names[0] = XrmPermStringToQuark(XmtNxmtRequires);
106 	required_names[1] = NULLQUARK;
107 	required_classes[0] = XrmPermStringToQuark(XmtCXmtRequires);
108 	required_classes[1] = NULLQUARK;
109 	required_quarks_inited = True;
110     }
111 
112     /* test that the file is not already included */
113     fileq = XrmStringToQuark(filename);
114     if (XmtHashTableLookup(app->loaded_files_table,
115 			   (XtPointer)fileq, &dummy))
116 	return True;
117 
118     /*
119      * If the filename begins with / or ./ or ../, then we don't search for it.
120      * Otherwise, we've got to deal with paths.
121      */
122     if ((filename[0] == '/') ||
123 	 ((filename[0] == '.') && (filename[1] == '/')) ||
124 	 ((filename[0]=='.') && (filename[1]=='.') && (filename[2]=='/'))) {
125 	found = True;
126 	newdb = XrmGetFileDatabase(filename);
127 	if (!newdb) load_file_error((String)filename);
128     }
129     else {
130 	/*
131 	 * go look for a application or system file by the specified name.
132 	 * This call searches resourceFilePath under the directory configDir.
133 	 * If resourceFilePath is undefined or if no file is found there, it
134 	 * searches configFilePath, if it differs from resourceFilePath, or
135 	 * if configFilePath is undefined it uses a default path under teh
136 	 * directory configDir.
137 	 * If still no file, it searches XFILESEARCHPATH or the /usr/lib/X11
138 	 * default path.
139 	 */
140 	full_filename = XmtFindFile(w, "app-defaults", filename,
141 				    APPDEFAULTSSUFFIX,
142 				    NULL, app->resource_file_path,
143 				    XmtSearchAppPath | XmtSearchSysPath);
144 
145 	if (full_filename) {
146 	    newdb = XrmGetFileDatabase(full_filename);
147 	    if (!newdb) load_file_error(full_filename);
148 	    else found = True;
149 	    XtFree(full_filename);
150 	}
151 
152 	/* if user is True, go look for a user resource file
153 	 * and override the application file with it.
154 	 */
155 	if (user) {
156 	    user_filename = XmtFindFile(w, "app-defaults", filename,
157 					APPDEFAULTSSUFFIX,
158 					NULL, NULL, XmtSearchUserPath);
159 	    if (user_filename) {
160 		userdb = XrmGetFileDatabase(user_filename);
161 		if (!userdb) load_file_error(user_filename);
162 		else {
163 		    XrmMergeDatabases(userdb, &newdb);
164 		    found = True;
165 		}
166 		XtFree(user_filename);
167 	    }
168 	}
169     }
170 
171     /*
172      * if no file was found, warn
173      */
174     if (!found)
175 	XmtWarningMsg("XmtLoadResourceFile", "notFound",
176 		      "file '%s' not found.", filename);
177 
178     /* if there's no db at this point, quit */
179     if (!newdb) return False;
180 
181     /*
182      * remember that we loaded this file
183      */
184     XmtHashTableStore(app->loaded_files_table, (XtPointer)fileq, (XtPointer)1);
185 
186     /*
187      * check the new db for recursive include files
188      */
189     if (XrmQGetResource(newdb, required_names, required_classes,
190 			&type, &value) == True)
191 	LoadResourceFileList(db, w, value.addr);
192 
193     /*
194      * Finally, augment or override the db with the new db
195      * Note that this destroys newdb, so we don't have to do so explicitly.
196      */
197 #ifndef X11R5
198     if (!override)
199 	XmtWarningMsg("XmtLoadResourceFile", "cantAugment",
200 		      "the #augment directive only works with X11R5\n\tand later releases.  Overriding instead.");
201     XrmMergeDatabases(newdb, db);
202 #else
203     XrmCombineDatabase(newdb, db, override);
204 #endif
205 
206     return True;
207 }
208 
209 
210 static String keywords[] = {
211     "augment",
212     "override"
213 };
214 
215 #define AUGMENT 0
216 #define OVERRIDE 1
217 
218 #if NeedFunctionPrototypes
LoadResourceFileList(XrmDatabase * db,Widget w,StringConst list)219 static void LoadResourceFileList(XrmDatabase *db, Widget w, StringConst list)
220 #else
221 static void LoadResourceFileList(db, w, list)
222 XrmDatabase *db;
223 Widget w;
224 StringConst list;
225 #endif
226 {
227     XmtLexer l;
228     XmtLexerToken tok;
229     Boolean override = True;
230 
231     l = XmtLexerCreate(keywords, XtNumber(keywords));
232     XmtLexerInit(l, list);
233 
234     /*
235      * Parse the following grammar:
236      * ((directive | file) [','])*
237      * directive: ("#augment" | "#override")
238      * file: STRING | '<'[^> \t]*'>'
239      */
240     while((tok = XmtLexerGetToken(l)) != XmtLexerEndOfString) {
241 	switch(tok) {
242 	case XmtLexerSharp:
243 	    if (XmtLexerNextToken(l) != XmtLexerKeyword) goto syntax;
244 	    if (XmtLexerKeyValue(l) == AUGMENT) override = False;
245 	    else override = True;
246 	    XmtLexerConsumeToken(l);
247 	    break;
248 	case XmtLexerString:
249 	    (void)LoadResourceFile(db, w, XmtLexerStrValue(l), True, override);
250 	    XtFree(XmtLexerStrValue(l));
251 	    if (XmtLexerNextToken(l) == XmtLexerComma) XmtLexerConsumeToken(l);
252 	    break;
253 	case XmtLexerLess:
254 	    XmtLexerConsumeToken(l);
255 	    XmtLexerSkipWhite(l);
256 	    if (XmtLexerScan(l, "> \t", False) != XmtLexerString) goto syntax;
257 	    (void)LoadResourceFile(db,w, XmtLexerStrValue(l), False, override);
258 	    XtFree(XmtLexerStrValue(l));
259 	    if (XmtLexerNextToken(l) != XmtLexerGreater) goto syntax;
260 	    if (XmtLexerNextToken(l) == XmtLexerComma) XmtLexerConsumeToken(l);
261 	    break;
262 	default:
263 	    goto syntax;
264 	}
265     }
266     XmtLexerDestroy(l);
267     return;
268 
269  syntax:
270     XmtWarningMsg("XmtLoadResourceFileList", "syntax",
271 		  "syntax error in xmtRequires resource:\n\t%s",
272 		  list);
273     XmtLexerDestroy(l);
274     return;
275 }
276 
277 #if NeedFunctionPrototypes
XmtLoadResourceFile(Widget w,StringConst filename,XmtWideBoolean user,XmtWideBoolean override)278 Boolean XmtLoadResourceFile(Widget w, StringConst filename,
279 			    XmtWideBoolean user, XmtWideBoolean override)
280 #else
281 Boolean XmtLoadResourceFile(w, filename, user, override)
282 Widget w;
283 StringConst filename;
284 int user;
285 int override;
286 #endif
287 {
288     XrmDatabase db;
289 
290     w = XmtGetApplicationShell(w);
291     db = XmtDatabaseOfWidget(w);
292     return LoadResourceFile(&db, w, filename, user, override);
293 }
294 
295 #if NeedFunctionPrototypes
XmtLoadResourceFileList(Widget w,StringConst list)296 void XmtLoadResourceFileList(Widget w, StringConst list)
297 #else
298 void XmtLoadResourceFileList(w, list)
299 Widget w;
300 StringConst list;
301 #endif
302 {
303     XrmDatabase db;
304 
305     w = XmtGetApplicationShell(w);
306     db = XmtDatabaseOfWidget(w);
307     LoadResourceFileList(&db, w, list);
308 }
309