CTWM
Loading...
Searching...
No Matches
/usr/src/RPM/BUILD/ctwm-4.1.0/parse.c
Go to the documentation of this file.
1/*
2 * Copyright 1988 by Evans & Sutherland Computer Corporation,
3 * Salt Lake City, Utah
4 * Portions Copyright 1989 by the Massachusetts Institute of Technology
5 * Cambridge, Massachusetts
6 *
7 * Copyright 1992 Claude Lecommandeur.
8 */
9
10/***********************************************************************
11 *
12 * $XConsortium: parse.c,v 1.52 91/07/12 09:59:37 dave Exp $
13 *
14 * parse the .twmrc file
15 *
16 * 17-Nov-87 Thomas E. LaStrange File created
17 * 10-Oct-90 David M. Sternlicht Storing saved colors on root
18 *
19 * Do the necessary modification to be integrated in ctwm.
20 * Can no longer be used for the standard twm.
21 *
22 * 22-April-92 Claude Lecommandeur.
23 *
24 ***********************************************************************/
25
26#include "ctwm.h"
27
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <strings.h>
32#ifdef USEM4
33# include <sys/types.h>
34# include <sys/wait.h>
35#endif
36
37#include "ctwm_atoms.h"
38#include "screen.h"
39#include "parse.h"
40#include "parse_int.h"
41#include "deftwmrc.h"
42#ifdef SOUNDS
43# include "sound.h"
44#endif
45
46#ifndef SYSTEM_INIT_FILE
47#error "No SYSTEM_INIT_FILE set"
48#endif
49
50static bool ParseStringList(const char **sl);
51
52/*
53 * With current bison, this is defined in the gram.tab.h, so this causes
54 * a warning for redundant declaration. With older bisons and byacc,
55 * it's not, so taking it out causes a warning for implicit declaration.
56 * A little looking around doesn't show any handy #define's we could use
57 * to be sure of the difference. This should quiet it down on gcc/clang
58 * anyway...
59 */
60#ifdef __GNUC__
61# pragma GCC diagnostic push
62# pragma GCC diagnostic ignored "-Wredundant-decls"
63extern int yyparse(void);
64# pragma GCC diagnostic pop
65#else
66extern int yyparse(void);
67#endif
68
69// Because of how this winds up shared with callback funcs in the
70// parsing, it's difficult to unwind from being global, so just accept
71// it.
72static FILE *twmrc;
73
74static int ptr = 0;
75static int len = 0;
76#define BUF_LEN 300
77static char buff[BUF_LEN + 1];
78static const char **stringListSource, *currentString;
79
80#ifdef NON_FLEX_LEX
81/*
82 * While these are (were) referenced in a number of places through the
83 * file, overflowlen is initialized to 0, only possibly changed in
84 * twmUnput(), and unless it's non-zero, neither is otherwise touched.
85 * So this is purely a twmUnput()-related var, and with flex, never used
86 * for anything.
87 */
88static char overflowbuff[20]; /* really only need one */
89static int overflowlen;
90#endif
91
92int ConstrainedMoveTime = 400; /* milliseconds, event times */
93bool ParseError; /* error parsing the .twmrc file */
94int RaiseDelay = 0; /* msec, for AutoRaise */
95int (*twmInputFunc)(void); /* used in lexer */
96
97static int twmrc_lineno;
98
99
100/* Actual file loader */
101static int ParseTwmrc(const char *filename);
102
103/* lex plumbing funcs */
104static bool doparse(int (*ifunc)(void), const char *srctypename,
105 const char *srcname);
106
107static int twmStringListInput(void);
108#ifndef USEM4
109static int twmFileInput(void);
110#else
111static int m4twmFileInput(void);
112#endif
113
114#if defined(YYDEBUG) && YYDEBUG
115int yydebug = 1;
116#endif
117
118
119/**
120 * Principal entry point from top-level code to parse the config file.
121 * This tries the various permutations of config files we could load.
122 * For most possible names, we try loading `$NAME.$SCREENNUM` before
123 * trying `$NAME`. If a `-f filename` is given on the command line, it's
124 * passed in here, and the normal `~/.[c]twmrc*` attempts are skipped if
125 * it's not found.
126 *
127 * \param filename A filename given in the -f command-line argument (or
128 * NULL)
129 * \return true/false for whether a valid config was parsed out from
130 * somewhere.
131 */
132bool
133LoadTwmrc(const char *filename)
134{
135 int ret = -1;
136 char *tryname = NULL;
137
138 /*
139 * Check for the twmrc file in the following order:
140 * 0. -f filename.#
141 * 1. -f filename
142 * (skip to 6 if -f was given)
143 * 2. .ctwmrc.#
144 * 3. .ctwmrc
145 * 4. .twmrc.#
146 * 5. .twmrc
147 * 6. system.ctwmrc
148 */
149#define TRY(fn) if((ret = ParseTwmrc(fn)) != -1) { goto DONE_TRYING; } (void)0
150
151 if(filename) {
152 /* -f filename.# */
153 asprintf(&tryname, "%s.%d", filename, Scr->screen);
154 if(tryname == NULL) {
155 // Oh, we're _screwed_...
156 return false;
157 }
158 TRY(tryname);
159
160 /* -f filename */
161 TRY(filename);
162
163 /* If we didn't get either from -f, don't try the ~ bits */
164 goto TRY_FALLBACK;
165 }
166
167 if(Home) {
168 /* ~/.ctwmrc.screennum */
169 free(tryname);
170 asprintf(&tryname, "%s/.ctwmrc.%d", Home, Scr->screen);
171 if(tryname == NULL) {
172 return false;
173 }
174 TRY(tryname);
175
176 // All later attempts are guaranteed shorter strings than that,
177 // so we can just keep sprintf'ing over it.
178
179 /* ~/.ctwmrc */
180 sprintf(tryname, "%s/.ctwmrc", Home);
181 TRY(tryname);
182
183 /* ~/.twmrc.screennum */
184 sprintf(tryname, "%s/.twmrc.%d", Home, Scr->screen);
185 TRY(tryname);
186
187 /* ~/.twmrc */
188 sprintf(tryname, "%s/.twmrc", Home);
189 TRY(tryname);
190 }
191
193 /* system.twmrc */
194 if((ret = ParseTwmrc(SYSTEM_INIT_FILE)) != -1) {
195 if(ret && filename) {
196 // If we were -f'ing, fell back to the system default, and
197 // that succeeeded, we warn. It's "normal"(ish) to not have
198 // a personal twmrc and fall back...
200 "%s: unable to open twmrc file %s, using %s instead\n",
202 }
203 goto DONE_TRYING;
204 }
205
206
208#undef TRY
209 free(tryname);
210
211 /*
212 * If we wound up with -1 all the way, we totally failed to find a
213 * file to work with. Fall back to builtin config.
214 */
215 if(ret == -1) {
216 // Only warn if -f.
217 if(filename) {
219 "%s: unable to open twmrc file %s, using built-in defaults instead\n",
221 }
223 }
224
225
226 /* Better have a useful value in ret... */
227 return ret;
228}
229
230
231/**
232 * Try parsing a file as a ctwmrc.
233 *
234 * \param filename The filename to try opening and parsing.
235 * \return -1,0,1. 0/1 should be treated as false/true for whether
236 * parsing the file succeeded. -1 means the file couldn't be opened.
237 */
238static int
240{
241 bool status;
242
243#if 0
244 fprintf(stderr, "%s(): Trying %s\n", __func__, filename);
245#endif
246
247 /* See if we can open the file */
248 if(!filename) {
249 return -1;
250 }
251 twmrc = fopen(filename, "r");
252 if(!twmrc) {
253 return -1;
254 }
255
256
257 /* Got it. Kick off the parsing, however we do it. */
258#ifdef USEM4
259 FILE *raw = NULL;
260 if(CLarg.GoThroughM4) {
261 /*
262 * Hold onto raw filehandle so we can fclose() it below, and
263 * swap twmrc over to the output from m4
264 */
265 raw = twmrc;
266 twmrc = start_m4(raw);
267 }
269 fclose(twmrc);
270 if(raw) {
271 fclose(raw);
272 }
273#else
275 fclose(twmrc);
276#endif
277
278 /* And we're done */
279 return status;
280
281 /* NOTREACHED */
282}
283
284static bool
285ParseStringList(const char **sl)
286{
288 currentString = *sl;
289 return doparse(twmStringListInput, "string list", NULL);
290}
291
292
293/*
294 * Util used throughout the code (possibly often wrongly?)
295 */
297{
298 fprintf(stderr, "%s: line %d: ", ProgramName, twmrc_lineno);
299}
300
301
302
303/*
304 * Everything below here is related to plumbing and firing off lex/yacc
305 */
306
307
308/*
309 * Backend func that takes an input-providing func and hooks it up to the
310 * lex/yacc parser to do the work
311 */
312static bool
313doparse(int (*ifunc)(void), const char *srctypename,
314 const char *srcname)
315{
316 ptr = 0;
317 len = 0;
318 twmrc_lineno = 0;
319 ParseError = false;
321#ifdef NON_FLEX_LEX
322 overflowlen = 0;
323#endif
324
325 yyparse();
326
327 if(ParseError) {
328 fprintf(stderr, "%s: errors found in twm %s",
330 if(srcname) {
331 fprintf(stderr, " \"%s\"", srcname);
332 }
333 fprintf(stderr, "\n");
334 }
335 return !(ParseError);
336}
337
338
339/*
340 * Various input routines for the lexer for the various sources of
341 * config.
342 */
343
344#ifndef USEM4
345#include <ctype.h>
346
347/* This has Tom's include() funtionality. This is utterly useless if you
348 * can use m4 for the same thing. Chris P. Ross */
349
350#define MAX_INCLUDES 10
351
357static int include_file = 0;
358
359
360static int twmFileInput(void)
361{
362#ifdef NON_FLEX_LEX
363 if(overflowlen) {
364 return (int) overflowbuff[--overflowlen];
365 }
366#endif
367
368 while(ptr == len) {
369 while(include_file) {
374 }
375 else {
376 break;
377 }
378 }
379
380 if(!include_file)
381 if(fgets(buff, BUF_LEN, twmrc) == NULL) {
382 return 0;
383 }
384 twmrc_lineno++;
385
386 if(strncmp(buff, "include", 7) == 0) {
387 /* Whoops, an include file! */
388 char *p = buff + 7, *q;
389 FILE *fp;
390
391 while(isspace(*p)) {
392 p++;
393 }
394 for(q = p; *q && !isspace(*q); q++) {
395 continue;
396 }
397 *q = 0;
398
399 if((fp = fopen(p, "r")) == NULL) {
400 fprintf(stderr, "%s: Unable to open included init file %s\n",
401 ProgramName, p);
402 continue;
403 }
404 if(++include_file >= MAX_INCLUDES) {
405 fprintf(stderr, "%s: init file includes nested too deep\n",
407 continue;
408 }
411 twmrc_lineno = 0;
413 continue;
414 }
415 ptr = 0;
416 len = strlen(buff);
417 }
418 return ((int)buff[ptr++]);
419}
420#else /* USEM4 */
421/* If you're going to use m4, use this version instead. Much simpler.
422 * m4 ism's credit to Josh Osborne (stripes) */
423
424static int m4twmFileInput(void)
425{
426 int line;
427 static FILE *cp = NULL;
428
429 if(cp == NULL && CLarg.keepM4_filename) {
430 cp = fopen(CLarg.keepM4_filename, "w");
431 if(cp == NULL) {
433 "%s: unable to create m4 output %s, ignoring\n",
434 ProgramName, CLarg.keepM4_filename);
435 CLarg.keepM4_filename = NULL;
436 }
437 }
438
439#ifdef NON_FLEX_LEX
440 if(overflowlen) {
441 return((int) overflowbuff[--overflowlen]);
442 }
443#endif
444
445 while(ptr == len) {
447 if(fgets(buff, BUF_LEN, twmrc) == NULL) {
448 if(cp) {
449 fclose(cp);
450 }
451 return(0);
452 }
453 if(cp) {
454 fputs(buff, cp);
455 }
456
457 if(sscanf(buff, "#line %d", &line)) {
458 twmrc_lineno = line - 1;
459 goto nextline;
460 }
461 else {
462 twmrc_lineno++;
463 }
464
465 ptr = 0;
466 len = strlen(buff);
467 }
468 return ((int)buff[ptr++]);
469}
470#endif /* USEM4 */
471
472
473static int twmStringListInput(void)
474{
475#ifdef NON_FLEX_LEX
476 if(overflowlen) {
477 return (int) overflowbuff[--overflowlen];
478 }
479#endif
480
481 /*
482 * return the character currently pointed to
483 */
484 if(currentString) {
485 unsigned int c = (unsigned int) * currentString++;
486
487 if(c) {
488 return c; /* if non-nul char */
489 }
490 currentString = *++stringListSource; /* advance to next bol */
491 return '\n'; /* but say that we hit last eol */
492 }
493 return 0; /* eof */
494}
495
496
497
498/*
499 * unput/output funcs for AT&T lex. No longer supported, and expected to
500 * be GC'd in a release or two.
501 */
502#ifdef NON_FLEX_LEX
503
504void twmUnput(int c)
505{
506 if(overflowlen < sizeof overflowbuff) {
508 }
509 else {
511 fprintf(stderr, "unable to unput character (%c)\n",
512 c);
513 }
514}
515
516void TwmOutput(int c)
517{
518 putchar(c);
519}
520
521#endif /* NON_FLEX_LEX */
static int PlaceX
Definition add_window.c:82
ctwm_cl_args CLarg
Definition clargs.c:27
char * ProgramName
Definition ctwm_main.c:146
char * Home
Definition ctwm_main.c:128
#define Scr
const char * defTwmrc[]
static char buff[300+1]
Definition parse.c:77
static bool ParseStringList(const char **sl)
Definition parse.c:285
static int ptr
Definition parse.c:74
bool ParseError
Definition parse.c:93
static int include_file
Definition parse.c:357
static bool doparse(int(*ifunc)(void), const char *srctypename, const char *srcname)
Definition parse.c:313
#define MAX_INCLUDES
Definition parse.c:350
static const char * currentString
Definition parse.c:78
int yyparse(void)
int ConstrainedMoveTime
Definition parse.c:92
#define BUF_LEN
Definition parse.c:76
static int twmStringListInput(void)
Definition parse.c:473
#define TRY(fn)
static const char ** stringListSource
Definition parse.c:78
int RaiseDelay
Definition parse.c:94
static int twmrc_lineno
Definition parse.c:97
static int twmFileInput(void)
Definition parse.c:360
static FILE * twmrc
Definition parse.c:72
void twmrc_error_prefix(void)
Definition parse.c:296
static struct incl rc_includes[10]
int(* twmInputFunc)(void)
Definition parse.c:95
static int ParseTwmrc(const char *filename)
Try parsing a file as a ctwmrc.
Definition parse.c:239
bool LoadTwmrc(const char *filename)
Principal entry point from top-level code to parse the config file.
Definition parse.c:133
static int len
Definition parse.c:75
FILE * start_m4(FILE *fraw)
Definition parse_m4.c:28
Definition parse.c:352
int lineno
Definition parse.c:355
FILE * fp
Definition parse.c:353
char * name
Definition parse.c:354