~ctwm/ctwm/trunk

304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
1
/*
554.1.10 by Matthew Fuller
Pull out the simple cases of long-form twm+Claude copyright/license
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.
11 by Claude Lecommandeur
CTWM version 3.2p1
8
 */
1 by Claude Lecommandeur
CTWM version 1.1
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
395.1.1 by Matthew Fuller
Move ctwm.h to always be included first.
26
#include "ctwm.h"
27
1 by Claude Lecommandeur
CTWM version 1.1
28
#include <stdio.h>
491.1.14 by Matthew Fuller
Remove incorrect pre-ANSI potential override prototypes for malloc()
29
#include <stdlib.h>
324.1.11 by Matthew Fuller
Replace a bunch of XmuCopyISOLatin1Lowered() faffery with strcasecmp()
30
#include <string.h>
31
#include <strings.h>
431.1.21 by Matthew Fuller
GC a few unnecessary headers here, and hide the wait() related bits
32
#ifdef USEM4
33
# include <sys/types.h>
34
# include <sys/wait.h>
35
#endif
340.1.1 by Matthew Fuller
Rearrange includes to be in what we'll call the Proper Order.
36
335.1.1 by Olaf 'Rhialto' Seibert
Automated Atoms, now for the ctwm core. Step 1: replacement of the many
37
#include "ctwm_atoms.h"
1 by Claude Lecommandeur
CTWM version 1.1
38
#include "screen.h"
39
#include "parse.h"
387.1.1 by Matthew Fuller
Bust out a lot of the m4 parsing handling from parse.c into a separate
40
#include "parse_int.h"
382.1.5 by Matthew Fuller
char **defTwmrc being only used in one file means we might as well
41
#include "deftwmrc.h"
136.1.5 by Richard Levitte
Get declarations of sound functions properly, and don't redeclare
42
#ifdef SOUNDS
43
#  include "sound.h"
44
#endif
1 by Claude Lecommandeur
CTWM version 1.1
45
46
#ifndef SYSTEM_INIT_FILE
431.1.22 by Matthew Fuller
Shouldn't be possible to not have this set, since we set it in the
47
#error "No SYSTEM_INIT_FILE set"
1 by Claude Lecommandeur
CTWM version 1.1
48
#endif
49
492.2.97 by Matthew Fuller
bool-ify flags and return values related to config file parsing.
50
static bool ParseStringList(const char **sl);
382.1.6 by Matthew Fuller
Now we can make ParseStringList() static too.
51
384.1.12 by Matthew Fuller
It turns out we sometimes need this extern, and sometimes don't, and
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"
390 by Matthew Fuller
Rerun 'make indent' after VMS reorbit, which cleans up a few nits.
63
extern int yyparse(void);
384.1.12 by Matthew Fuller
It turns out we sometimes need this extern, and sometimes don't, and
64
# pragma GCC diagnostic pop
65
#else
390 by Matthew Fuller
Rerun 'make indent' after VMS reorbit, which cleans up a few nits.
66
extern int yyparse(void);
384.1.12 by Matthew Fuller
It turns out we sometimes need this extern, and sometimes don't, and
67
#endif
9 by Claude Lecommandeur
CTWM version 3.1
68
639.1.6 by Matthew Fuller
Add a comment about a global and slightly tweak another.
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.
1 by Claude Lecommandeur
CTWM version 1.1
72
static FILE *twmrc;
431.1.23 by Matthew Fuller
Move #define down toward where it's used.
73
1 by Claude Lecommandeur
CTWM version 1.1
74
static int ptr = 0;
75
static int len = 0;
431.1.23 by Matthew Fuller
Move #define down toward where it's used.
76
#define BUF_LEN 300
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
77
static char buff[BUF_LEN + 1];
382.1.2 by Matthew Fuller
defTwmrc is actually a const char *[], so declare it right in the
78
static const char **stringListSource, *currentString;
1 by Claude Lecommandeur
CTWM version 1.1
79
639.1.6 by Matthew Fuller
Add a comment about a global and slightly tweak another.
80
#ifdef NON_FLEX_LEX
386.1.2 by Matthew Fuller
These overflow vars are only used by the unput func, so aren't
81
/*
639.1.6 by Matthew Fuller
Add a comment about a global and slightly tweak another.
82
 * While these are (were) referenced in a number of places through the
386.1.2 by Matthew Fuller
These overflow vars are only used by the unput func, so aren't
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
 */
88
static char overflowbuff[20];           /* really only need one */
89
static int overflowlen;
90
#endif
91
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
92
int ConstrainedMoveTime = 400;          /* milliseconds, event times */
492.2.97 by Matthew Fuller
bool-ify flags and return values related to config file parsing.
93
bool ParseError;                        /* error parsing the .twmrc file */
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
94
int RaiseDelay = 0;                     /* msec, for AutoRaise */
431.1.12 by Matthew Fuller
Another looks-like-a-prototype-but-actually-a-global-var. Move up
95
int (*twmInputFunc)(void);              /* used in lexer */
4 by Claude Lecommandeur
CTWM version 2.0
96
431.1.26 by Matthew Fuller
This var is now only used in this file, so we can staticize it and
97
static int twmrc_lineno;
98
431.1.24 by Matthew Fuller
Move doparse() down a little in the file, and make clear before it
99
639.1.2 by Matthew Fuller
Split and rename ParseTwmrc() so the func outside code calls is called
100
/* Actual file loader */
639.1.3 by Matthew Fuller
Do a minimal conversion splitting the "construct filename" and "try
101
static int ParseTwmrc(const char *filename);
639.1.2 by Matthew Fuller
Split and rename ParseTwmrc() so the func outside code calls is called
102
431.1.24 by Matthew Fuller
Move doparse() down a little in the file, and make clear before it
103
/* lex plumbing funcs */
492.2.97 by Matthew Fuller
bool-ify flags and return values related to config file parsing.
104
static bool doparse(int (*ifunc)(void), const char *srctypename,
105
                    const char *srcname);
431.1.24 by Matthew Fuller
Move doparse() down a little in the file, and make clear before it
106
93 by Richard Levitte
- Convert all functions to use proper prototypes.
107
static int twmStringListInput(void);
108
#ifndef USEM4
109
static int twmFileInput(void);
110
#else
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
111
static int m4twmFileInput(void);
8 by Claude Lecommandeur
CTWM version 3.0
112
#endif
1 by Claude Lecommandeur
CTWM version 1.1
113
384.1.9 by Matthew Fuller
Depending on yacc, YYDEBUG may be undef or 0 for off, so check both.
114
#if defined(YYDEBUG) && YYDEBUG
39 by Richard Levitte
Add possibility to debug the parser...
115
int yydebug = 1;
116
#endif
117
431.1.13 by Matthew Fuller
Improve some comments on funcs/blocks of the file.
118
639.1.16 by Matthew Fuller
doxygen-ize the entry function and tweak a comment.
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.
431.1.13 by Matthew Fuller
Improve some comments on funcs/blocks of the file.
131
 */
492.2.97 by Matthew Fuller
bool-ify flags and return values related to config file parsing.
132
bool
639.1.13 by Matthew Fuller
const-ify.
133
LoadTwmrc(const char *filename)
1 by Claude Lecommandeur
CTWM version 1.1
134
{
639.1.8 by Matthew Fuller
Rewrite without the loop and as straight-line logic. This should
135
	int ret = -1;
639.1.11 by Matthew Fuller
Instead of a fixed-length buffer (with no bounds checking) and weird
136
	char *tryname = NULL;
1 by Claude Lecommandeur
CTWM version 1.1
137
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
138
	/*
139
	 * Check for the twmrc file in the following order:
371.2.7 by Matthew Fuller
Take out remnants of documentation for differing config file names on
140
	 *   0.  -f filename.#
141
	 *   1.  -f filename
639.1.16 by Matthew Fuller
doxygen-ize the entry function and tweak a comment.
142
	 *       (skip to 6 if -f was given)
371.2.7 by Matthew Fuller
Take out remnants of documentation for differing config file names on
143
	 *   2.  .ctwmrc.#
144
	 *   3.  .ctwmrc
145
	 *   4.  .twmrc.#
146
	 *   5.  .twmrc
147
	 *   6.  system.ctwmrc
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
148
	 */
639.1.10 by Matthew Fuller
Add an explicit void statement here to be sure we consistently ; the
149
#define TRY(fn) if((ret = ParseTwmrc(fn)) != -1) { goto DONE_TRYING; }  (void)0
639.1.8 by Matthew Fuller
Rewrite without the loop and as straight-line logic. This should
150
151
	if(filename) {
152
		/* -f filename.# */
639.1.11 by Matthew Fuller
Instead of a fixed-length buffer (with no bounds checking) and weird
153
		asprintf(&tryname, "%s.%d", filename, Scr->screen);
639.1.12 by Matthew Fuller
Be extra careful. If we can't allocate memory sufficient to hold a fs
154
		if(tryname == NULL) {
155
			// Oh, we're _screwed_...
156
			return false;
157
		}
639.1.11 by Matthew Fuller
Instead of a fixed-length buffer (with no bounds checking) and weird
158
		TRY(tryname);
639.1.8 by Matthew Fuller
Rewrite without the loop and as straight-line logic. This should
159
160
		/* -f filename */
161
		TRY(filename);
162
639.1.11 by Matthew Fuller
Instead of a fixed-length buffer (with no bounds checking) and weird
163
		/* If we didn't get either from -f, don't try the ~ bits */
164
		goto TRY_FALLBACK;
639.1.8 by Matthew Fuller
Rewrite without the loop and as straight-line logic. This should
165
	}
166
167
	if(Home) {
168
		/* ~/.ctwmrc.screennum */
639.1.11 by Matthew Fuller
Instead of a fixed-length buffer (with no bounds checking) and weird
169
		free(tryname);
170
		asprintf(&tryname, "%s/.ctwmrc.%d", Home, Scr->screen);
639.1.12 by Matthew Fuller
Be extra careful. If we can't allocate memory sufficient to hold a fs
171
		if(tryname == NULL) {
172
			return false;
173
		}
639.1.11 by Matthew Fuller
Instead of a fixed-length buffer (with no bounds checking) and weird
174
		TRY(tryname);
175
176
		// All later attempts are guaranteed shorter strings than that,
177
		// so we can just keep sprintf'ing over it.
639.1.8 by Matthew Fuller
Rewrite without the loop and as straight-line logic. This should
178
179
		/* ~/.ctwmrc */
639.1.11 by Matthew Fuller
Instead of a fixed-length buffer (with no bounds checking) and weird
180
		sprintf(tryname, "%s/.ctwmrc", Home);
181
		TRY(tryname);
639.1.8 by Matthew Fuller
Rewrite without the loop and as straight-line logic. This should
182
183
		/* ~/.twmrc.screennum */
639.1.11 by Matthew Fuller
Instead of a fixed-length buffer (with no bounds checking) and weird
184
		sprintf(tryname, "%s/.twmrc.%d", Home, Scr->screen);
185
		TRY(tryname);
639.1.8 by Matthew Fuller
Rewrite without the loop and as straight-line logic. This should
186
187
		/* ~/.twmrc */
639.1.11 by Matthew Fuller
Instead of a fixed-length buffer (with no bounds checking) and weird
188
		sprintf(tryname, "%s/.twmrc", Home);
189
		TRY(tryname);
639.1.8 by Matthew Fuller
Rewrite without the loop and as straight-line logic. This should
190
	}
191
639.1.11 by Matthew Fuller
Instead of a fixed-length buffer (with no bounds checking) and weird
192
TRY_FALLBACK:
639.1.8 by Matthew Fuller
Rewrite without the loop and as straight-line logic. This should
193
	/* system.twmrc */
639.1.11 by Matthew Fuller
Instead of a fixed-length buffer (with no bounds checking) and weird
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...
199
			fprintf(stderr,
200
			        "%s:  unable to open twmrc file %s, using %s instead\n",
201
			        ProgramName, filename, SYSTEM_INIT_FILE);
202
		}
203
		goto DONE_TRYING;
204
	}
205
206
207
DONE_TRYING:
639.1.8 by Matthew Fuller
Rewrite without the loop and as straight-line logic. This should
208
#undef TRY
639.1.11 by Matthew Fuller
Instead of a fixed-length buffer (with no bounds checking) and weird
209
	free(tryname);
210
639.1.3 by Matthew Fuller
Do a minimal conversion splitting the "construct filename" and "try
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) {
639.1.11 by Matthew Fuller
Instead of a fixed-length buffer (with no bounds checking) and weird
216
		// Only warn if -f.
639.1.3 by Matthew Fuller
Do a minimal conversion splitting the "construct filename" and "try
217
		if(filename) {
218
			fprintf(stderr,
219
			        "%s:  unable to open twmrc file %s, using built-in defaults instead\n",
220
			        ProgramName, filename);
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
221
		}
639.1.3 by Matthew Fuller
Do a minimal conversion splitting the "construct filename" and "try
222
		return ParseStringList(defTwmrc);
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
 */
238
static int
239
ParseTwmrc(const char *filename)
240
{
639.1.14 by Matthew Fuller
Tweak some comments and shuffle around where some vars are declared.
241
	bool status;
242
639.1.7 by Matthew Fuller
Add a 0'd debug line and slightly adjust some of the filename testing
243
#if 0
244
	fprintf(stderr, "%s(): Trying %s\n", __func__, filename);
245
#endif
246
639.1.14 by Matthew Fuller
Tweak some comments and shuffle around where some vars are declared.
247
	/* See if we can open the file */
248
	if(!filename) {
249
		return -1;
250
	}
639.1.3 by Matthew Fuller
Do a minimal conversion splitting the "construct filename" and "try
251
	twmrc = fopen(filename, "r");
639.1.4 by Matthew Fuller
make indent. Mostly whitespace adjustments for removing of block.
252
	if(!twmrc) {
639.1.3 by Matthew Fuller
Do a minimal conversion splitting the "construct filename" and "try
253
		return -1;
639.1.4 by Matthew Fuller
make indent. Mostly whitespace adjustments for removing of block.
254
	}
639.1.3 by Matthew Fuller
Do a minimal conversion splitting the "construct filename" and "try
255
639.1.14 by Matthew Fuller
Tweak some comments and shuffle around where some vars are declared.
256
257
	/* Got it.  Kick off the parsing, however we do it. */
431.1.14 by Matthew Fuller
Rewrite this flow a little so we're not hopping in and out of #ifdef
258
#ifdef USEM4
639.1.4 by Matthew Fuller
make indent. Mostly whitespace adjustments for removing of block.
259
	FILE *raw = NULL;
260
	if(CLarg.GoThroughM4) {
431.1.17 by Matthew Fuller
Whitespace and comments to clarify flow through the func.
261
		/*
639.1.4 by Matthew Fuller
make indent. Mostly whitespace adjustments for removing of block.
262
		 * Hold onto raw filehandle so we can fclose() it below, and
263
		 * swap twmrc over to the output from m4
431.1.17 by Matthew Fuller
Whitespace and comments to clarify flow through the func.
264
		 */
639.1.4 by Matthew Fuller
make indent. Mostly whitespace adjustments for removing of block.
265
		raw = twmrc;
266
		twmrc = start_m4(raw);
267
	}
268
	status = doparse(m4twmFileInput, "file", filename);
269
	fclose(twmrc);
270
	if(raw) {
271
		fclose(raw);
272
	}
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
273
#else
639.1.4 by Matthew Fuller
make indent. Mostly whitespace adjustments for removing of block.
274
	status = doparse(twmFileInput, "file", filename);
275
	fclose(twmrc);
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
276
#endif
431.1.17 by Matthew Fuller
Whitespace and comments to clarify flow through the func.
277
639.1.4 by Matthew Fuller
make indent. Mostly whitespace adjustments for removing of block.
278
	/* And we're done */
279
	return status;
431.1.17 by Matthew Fuller
Whitespace and comments to clarify flow through the func.
280
281
	/* NOTREACHED */
1 by Claude Lecommandeur
CTWM version 1.1
282
}
283
492.2.97 by Matthew Fuller
bool-ify flags and return values related to config file parsing.
284
static bool
285
ParseStringList(const char **sl)
1 by Claude Lecommandeur
CTWM version 1.1
286
{
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
287
	stringListSource = sl;
288
	currentString = *sl;
497.1.17 by Matthew Fuller
Don't cast NULL to particular pointer types.
289
	return doparse(twmStringListInput, "string list", NULL);
1 by Claude Lecommandeur
CTWM version 1.1
290
}
291
292
431.1.25 by Matthew Fuller
twmrc_error_prefix() is used widely through the code, not just in the
293
/*
294
 * Util used throughout the code (possibly often wrongly?)
295
 */
431.1.28 by Matthew Fuller
make indent
296
void twmrc_error_prefix(void)
431.1.25 by Matthew Fuller
twmrc_error_prefix() is used widely through the code, not just in the
297
{
431.1.28 by Matthew Fuller
make indent
298
	fprintf(stderr, "%s:  line %d:  ", ProgramName, twmrc_lineno);
431.1.25 by Matthew Fuller
twmrc_error_prefix() is used widely through the code, not just in the
299
}
300
301
431.1.24 by Matthew Fuller
Move doparse() down a little in the file, and make clear before it
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
 */
492.2.97 by Matthew Fuller
bool-ify flags and return values related to config file parsing.
312
static bool
313
doparse(int (*ifunc)(void), const char *srctypename,
314
        const char *srcname)
431.1.24 by Matthew Fuller
Move doparse() down a little in the file, and make clear before it
315
{
316
	ptr = 0;
317
	len = 0;
318
	twmrc_lineno = 0;
492.2.97 by Matthew Fuller
bool-ify flags and return values related to config file parsing.
319
	ParseError = false;
431.1.24 by Matthew Fuller
Move doparse() down a little in the file, and make clear before it
320
	twmInputFunc = ifunc;
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",
329
		        ProgramName, srctypename);
330
		if(srcname) {
331
			fprintf(stderr, " \"%s\"", srcname);
332
		}
333
		fprintf(stderr, "\n");
334
	}
577.1.8 by Matthew Fuller
When I bool-ified doparse() in r492.2.97, I accidentally reversed the
335
	return !(ParseError);
431.1.24 by Matthew Fuller
Move doparse() down a little in the file, and make clear before it
336
}
337
338
431.1.13 by Matthew Fuller
Improve some comments on funcs/blocks of the file.
339
/*
340
 * Various input routines for the lexer for the various sources of
341
 * config.
1 by Claude Lecommandeur
CTWM version 1.1
342
 */
343
8 by Claude Lecommandeur
CTWM version 3.0
344
#ifndef USEM4
293 by Matthew Fuller
In this (probably almost unused) !USEM4 case, we need ctype.h for
345
#include <ctype.h>
8 by Claude Lecommandeur
CTWM version 3.0
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
352
static struct incl {
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
353
	FILE *fp;
354
	char *name;
355
	int lineno;
8 by Claude Lecommandeur
CTWM version 3.0
356
} rc_includes[MAX_INCLUDES];
357
static int include_file = 0;
358
359
240.1.2 by Rhialto
3 - Selected a number of cleanups from Stefan Monnier
360
static int twmFileInput(void)
1 by Claude Lecommandeur
CTWM version 1.1
361
{
386.1.2 by Matthew Fuller
These overflow vars are only used by the unput func, so aren't
362
#ifdef NON_FLEX_LEX
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
363
	if(overflowlen) {
364
		return (int) overflowbuff[--overflowlen];
365
	}
386.1.2 by Matthew Fuller
These overflow vars are only used by the unput func, so aren't
366
#endif
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
367
368
	while(ptr == len) {
369
		while(include_file) {
370
			if(fgets(buff, BUF_LEN, rc_includes[include_file].fp) == NULL) {
371
				free(rc_includes[include_file].name);
372
				fclose(rc_includes[include_file].fp);
373
				twmrc_lineno = rc_includes[include_file--].lineno;
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",
406
				        ProgramName);
407
				continue;
408
			}
409
			rc_includes[include_file].fp = fp;
410
			rc_includes[include_file].lineno = twmrc_lineno;
411
			twmrc_lineno = 0;
491.1.5 by Matthew Fuller
Replace malloc();strcpy(); with strdup().
412
			rc_includes[include_file].name = strdup(p);
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
413
			continue;
414
		}
415
		ptr = 0;
416
		len = strlen(buff);
417
	}
418
	return ((int)buff[ptr++]);
1 by Claude Lecommandeur
CTWM version 1.1
419
}
8 by Claude Lecommandeur
CTWM version 3.0
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
93 by Richard Levitte
- Convert all functions to use proper prototypes.
424
static int m4twmFileInput(void)
8 by Claude Lecommandeur
CTWM version 3.0
425
{
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
426
	int line;
427
	static FILE *cp = NULL;
428
389.1.31 by Matthew Fuller
Switch these 3 M4-related command line args into the CLargs structure
429
	if(cp == NULL && CLarg.keepM4_filename) {
430
		cp = fopen(CLarg.keepM4_filename, "w");
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
431
		if(cp == NULL) {
432
			fprintf(stderr,
433
			        "%s:  unable to create m4 output %s, ignoring\n",
389.1.31 by Matthew Fuller
Switch these 3 M4-related command line args into the CLargs structure
434
			        ProgramName, CLarg.keepM4_filename);
435
			CLarg.keepM4_filename = NULL;
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
436
		}
437
	}
438
386.1.2 by Matthew Fuller
These overflow vars are only used by the unput func, so aren't
439
#ifdef NON_FLEX_LEX
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
440
	if(overflowlen) {
441
		return((int) overflowbuff[--overflowlen]);
442
	}
386.1.2 by Matthew Fuller
These overflow vars are only used by the unput func, so aren't
443
#endif
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
444
445
	while(ptr == len) {
446
nextline:
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++]);
8 by Claude Lecommandeur
CTWM version 3.0
469
}
470
#endif /* USEM4 */
471
1 by Claude Lecommandeur
CTWM version 1.1
472
93 by Richard Levitte
- Convert all functions to use proper prototypes.
473
static int twmStringListInput(void)
1 by Claude Lecommandeur
CTWM version 1.1
474
{
386.1.2 by Matthew Fuller
These overflow vars are only used by the unput func, so aren't
475
#ifdef NON_FLEX_LEX
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
476
	if(overflowlen) {
477
		return (int) overflowbuff[--overflowlen];
478
	}
386.1.2 by Matthew Fuller
These overflow vars are only used by the unput func, so aren't
479
#endif
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
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 */
1 by Claude Lecommandeur
CTWM version 1.1
494
}
495
496
431.1.24 by Matthew Fuller
Move doparse() down a little in the file, and make clear before it
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
 */
386.1.1 by Matthew Fuller
Create a NON_FLEX_LEX define to hide non-flex-only bits behind, and
502
#ifdef NON_FLEX_LEX
503
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
504
void twmUnput(int c)
1 by Claude Lecommandeur
CTWM version 1.1
505
{
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
506
	if(overflowlen < sizeof overflowbuff) {
507
		overflowbuff[overflowlen++] = (char) c;
508
	}
509
	else {
510
		twmrc_error_prefix();
511
		fprintf(stderr, "unable to unput character (%c)\n",
512
		        c);
513
	}
1 by Claude Lecommandeur
CTWM version 1.1
514
}
515
93 by Richard Levitte
- Convert all functions to use proper prototypes.
516
void TwmOutput(int c)
1 by Claude Lecommandeur
CTWM version 1.1
517
{
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
518
	putchar(c);
1 by Claude Lecommandeur
CTWM version 1.1
519
}
520
386.1.1 by Matthew Fuller
Create a NON_FLEX_LEX define to hide non-flex-only bits behind, and
521
#endif /* NON_FLEX_LEX */