Flags.c revision 6747b715
1/*
2 * Copyright (c) 1997  Metro Link Incorporated
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 *
22 * Except as contained in this notice, the name of the Metro Link shall not be
23 * used in advertising or otherwise to promote the sale, use or other dealings
24 * in this Software without prior written authorization from Metro Link.
25 *
26 */
27/*
28 * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
29 *
30 * Permission is hereby granted, free of charge, to any person obtaining a
31 * copy of this software and associated documentation files (the "Software"),
32 * to deal in the Software without restriction, including without limitation
33 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
34 * and/or sell copies of the Software, and to permit persons to whom the
35 * Software is furnished to do so, subject to the following conditions:
36 *
37 * The above copyright notice and this permission notice shall be included in
38 * all copies or substantial portions of the Software.
39 *
40 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
41 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
42 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
43 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
44 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
45 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
46 * OTHER DEALINGS IN THE SOFTWARE.
47 *
48 * Except as contained in this notice, the name of the copyright holder(s)
49 * and author(s) shall not be used in advertising or otherwise to promote
50 * the sale, use or other dealings in this Software without prior written
51 * authorization from the copyright holder(s) and author(s).
52 */
53
54
55/* View/edit this file with tab stops set to 4 */
56
57#ifdef HAVE_XORG_CONFIG_H
58#include <xorg-config.h>
59#endif
60
61#include "xf86Parser.h"
62#include "xf86tokens.h"
63#include "Configint.h"
64#include <math.h>
65#include <X11/Xfuncproto.h>
66
67extern LexRec val;
68
69static xf86ConfigSymTabRec ServerFlagsTab[] =
70{
71	{ENDSECTION, "endsection"},
72	{NOTRAPSIGNALS, "notrapsignals"},
73	{DONTZAP, "dontzap"},
74	{DONTZOOM, "dontzoom"},
75	{DISABLEVIDMODE, "disablevidmodeextension"},
76	{ALLOWNONLOCAL, "allownonlocalxvidtune"},
77	{DISABLEMODINDEV, "disablemodindev"},
78	{MODINDEVALLOWNONLOCAL, "allownonlocalmodindev"},
79	{ALLOWMOUSEOPENFAIL, "allowmouseopenfail"},
80	{OPTION, "option"},
81	{BLANKTIME, "blanktime"},
82	{STANDBYTIME, "standbytime"},
83	{SUSPENDTIME, "suspendtime"},
84	{OFFTIME, "offtime"},
85	{DEFAULTLAYOUT, "defaultserverlayout"},
86	{-1, ""},
87};
88
89#define CLEANUP xf86freeFlags
90
91XF86ConfFlagsPtr
92xf86parseFlagsSection (void)
93{
94	int token;
95	parsePrologue (XF86ConfFlagsPtr, XF86ConfFlagsRec)
96
97	while ((token = xf86getToken (ServerFlagsTab)) != ENDSECTION)
98	{
99		int hasvalue = FALSE;
100		int strvalue = FALSE;
101		int tokentype;
102		switch (token)
103		{
104		case COMMENT:
105			ptr->flg_comment = xf86addComment(ptr->flg_comment, val.str);
106			break;
107			/*
108			 * these old keywords are turned into standard generic options.
109			 * we fall through here on purpose
110			 */
111		case DEFAULTLAYOUT:
112			strvalue = TRUE;
113		case BLANKTIME:
114		case STANDBYTIME:
115		case SUSPENDTIME:
116		case OFFTIME:
117			hasvalue = TRUE;
118		case NOTRAPSIGNALS:
119		case DONTZAP:
120		case DONTZOOM:
121		case DISABLEVIDMODE:
122		case ALLOWNONLOCAL:
123		case DISABLEMODINDEV:
124		case MODINDEVALLOWNONLOCAL:
125		case ALLOWMOUSEOPENFAIL:
126			{
127				int i = 0;
128				while (ServerFlagsTab[i].token != -1)
129				{
130					char *tmp;
131
132					if (ServerFlagsTab[i].token == token)
133					{
134						char *valstr = NULL;
135						/* can't use strdup because it calls malloc */
136						tmp = strdup (ServerFlagsTab[i].name);
137						if (hasvalue)
138						{
139							tokentype = xf86getSubToken(&(ptr->flg_comment));
140							if (strvalue) {
141								if (tokentype != STRING)
142									Error (QUOTE_MSG, tmp);
143								valstr = val.str;
144							} else {
145								if (tokentype != NUMBER)
146									Error (NUMBER_MSG, tmp);
147								valstr = malloc(16);
148								if (valstr)
149									sprintf(valstr, "%d", val.num);
150							}
151						}
152						ptr->flg_option_lst = xf86addNewOption
153							(ptr->flg_option_lst, tmp, valstr);
154					}
155					i++;
156				}
157			}
158			break;
159		case OPTION:
160			ptr->flg_option_lst = xf86parseOption(ptr->flg_option_lst);
161			break;
162
163		case EOF_TOKEN:
164			Error (UNEXPECTED_EOF_MSG, NULL);
165			break;
166		default:
167			Error (INVALID_KEYWORD_MSG, xf86tokenString ());
168			break;
169		}
170	}
171
172#ifdef DEBUG
173	printf ("Flags section parsed\n");
174#endif
175
176	return ptr;
177}
178
179#undef CLEANUP
180
181void
182xf86printServerFlagsSection (FILE * f, XF86ConfFlagsPtr flags)
183{
184	XF86OptionPtr p;
185
186	if ((!flags) || (!flags->flg_option_lst))
187		return;
188	p = flags->flg_option_lst;
189	fprintf (f, "Section \"ServerFlags\"\n");
190	if (flags->flg_comment)
191		fprintf (f, "%s", flags->flg_comment);
192	xf86printOptionList(f, p, 1);
193	fprintf (f, "EndSection\n\n");
194}
195
196static XF86OptionPtr
197addNewOption2 (XF86OptionPtr head, char *name, char *val, int used)
198{
199	XF86OptionPtr new, old = NULL;
200
201	/* Don't allow duplicates, free old strings */
202	if (head != NULL && (old = xf86findOption(head, name)) != NULL) {
203		new = old;
204		free(new->opt_name);
205		free(new->opt_val);
206	}
207	else
208		new = calloc (1, sizeof (XF86OptionRec));
209	new->opt_name = name;
210	new->opt_val = val;
211	new->opt_used = used;
212
213	if (old)
214		return head;
215	return ((XF86OptionPtr) xf86addListItem ((glp) head, (glp) new));
216}
217
218XF86OptionPtr
219xf86addNewOption (XF86OptionPtr head, char *name, char *val)
220{
221	return addNewOption2(head, name, val, 0);
222}
223
224void
225xf86freeFlags (XF86ConfFlagsPtr flags)
226{
227	if (flags == NULL)
228		return;
229	xf86optionListFree (flags->flg_option_lst);
230	TestFree(flags->flg_comment);
231	free (flags);
232}
233
234XF86OptionPtr
235xf86optionListDup (XF86OptionPtr opt)
236{
237	XF86OptionPtr newopt = NULL;
238	char *val;
239
240	while (opt)
241	{
242		val = opt->opt_val ? strdup(opt->opt_val) : NULL;
243		newopt = xf86addNewOption(newopt, strdup(opt->opt_name), val);
244		newopt->opt_used = opt->opt_used;
245		if (opt->opt_comment)
246			newopt->opt_comment = strdup(opt->opt_comment);
247		opt = opt->list.next;
248	}
249	return newopt;
250}
251
252void
253xf86optionListFree (XF86OptionPtr opt)
254{
255	XF86OptionPtr prev;
256
257	while (opt)
258	{
259		TestFree (opt->opt_name);
260		TestFree (opt->opt_val);
261		TestFree (opt->opt_comment);
262		prev = opt;
263		opt = opt->list.next;
264		free (prev);
265	}
266}
267
268char *
269xf86optionName(XF86OptionPtr opt)
270{
271	if (opt)
272		return opt->opt_name;
273	return 0;
274}
275
276char *
277xf86optionValue(XF86OptionPtr opt)
278{
279	if (opt)
280		return opt->opt_val;
281	return 0;
282}
283
284XF86OptionPtr
285xf86newOption(char *name, char *value)
286{
287	XF86OptionPtr opt;
288
289	opt = calloc(1, sizeof (XF86OptionRec));
290	if (!opt)
291		return NULL;
292
293	opt->opt_used = 0;
294	opt->list.next = 0;
295	opt->opt_name = name;
296	opt->opt_val = value;
297
298	return opt;
299}
300
301XF86OptionPtr
302xf86nextOption(XF86OptionPtr list)
303{
304	if (!list)
305		return NULL;
306	return list->list.next;
307}
308
309/*
310 * this function searches the given option list for the named option and
311 * returns a pointer to the option rec if found. If not found, it returns
312 * NULL
313 */
314
315XF86OptionPtr
316xf86findOption (XF86OptionPtr list, const char *name)
317{
318	while (list)
319	{
320		if (xf86nameCompare (list->opt_name, name) == 0)
321			return list;
322		list = list->list.next;
323	}
324	return NULL;
325}
326
327/*
328 * this function searches the given option list for the named option. If
329 * found and the option has a parameter, a pointer to the parameter is
330 * returned.  If the option does not have a parameter an empty string is
331 * returned.  If the option is not found, a NULL is returned.
332 */
333
334char *
335xf86findOptionValue (XF86OptionPtr list, const char *name)
336{
337	XF86OptionPtr p = xf86findOption (list, name);
338
339	if (p)
340	{
341		if (p->opt_val)
342			return p->opt_val;
343		else
344			return "";
345	}
346	return NULL;
347}
348
349XF86OptionPtr
350xf86optionListCreate( const char **options, int count, int used )
351{
352	XF86OptionPtr p = NULL;
353	char *t1, *t2;
354	int i;
355
356	if (count == -1)
357	{
358		for (count = 0; options[count]; count++)
359			;
360	}
361	if( (count % 2) != 0 )
362	{
363		fprintf( stderr, "xf86optionListCreate: count must be an even number.\n" );
364		return NULL;
365	}
366	for (i = 0; i < count; i += 2)
367	{
368		/* can't use strdup because it calls malloc */
369		t1 = malloc (sizeof (char) *
370				(strlen (options[i]) + 1));
371		strcpy (t1, options[i]);
372		t2 = malloc (sizeof (char) *
373				(strlen (options[i + 1]) + 1));
374		strcpy (t2, options[i + 1]);
375		p = addNewOption2 (p, t1, t2, used);
376	}
377
378	return p;
379}
380
381/* the 2 given lists are merged. If an option with the same name is present in
382 * both, the option from the user list - specified in the second argument -
383 * is used. The end result is a single valid list of options. Duplicates
384 * are freed, and the original lists are no longer guaranteed to be complete.
385 */
386XF86OptionPtr
387xf86optionListMerge (XF86OptionPtr head, XF86OptionPtr tail)
388{
389	XF86OptionPtr a, b, ap = NULL, bp = NULL;
390
391	a = tail;
392	b = head;
393	while (tail && b) {
394		if (xf86nameCompare (a->opt_name, b->opt_name) == 0) {
395			if (b == head)
396				head = a;
397			else
398				bp->list.next = a;
399			if (a == tail)
400				tail = a->list.next;
401			else
402				ap->list.next = a->list.next;
403			a->list.next = b->list.next;
404			b->list.next = NULL;
405			xf86optionListFree (b);
406			b = a->list.next;
407			bp = a;
408			a = tail;
409			ap = NULL;
410		} else {
411			ap = a;
412			if (!(a = a->list.next)) {
413				a = tail;
414				bp = b;
415				b = b->list.next;
416				ap = NULL;
417			}
418		}
419	}
420
421	if (head) {
422		for (a = head; a->list.next; a = a->list.next)
423			;
424		a->list.next = tail;
425	} else
426		head = tail;
427
428	return head;
429}
430
431char *
432xf86uLongToString(unsigned long i)
433{
434	char *s;
435	int l;
436
437	l = ceil(log10((double)i) + 2.5);
438	s = malloc(l);
439	if (!s)
440		return NULL;
441	sprintf(s, "%lu", i);
442	return s;
443}
444
445XF86OptionPtr
446xf86parseOption(XF86OptionPtr head)
447{
448	XF86OptionPtr option, cnew, old;
449	char *name, *comment = NULL;
450	int token;
451
452	if ((token = xf86getSubToken(&comment)) != STRING) {
453		xf86parseError(BAD_OPTION_MSG, NULL);
454		free(comment);
455		return head;
456	}
457
458	name = val.str;
459	if ((token = xf86getSubToken(&comment)) == STRING) {
460		option = xf86newOption(name, val.str);
461		option->opt_comment = comment;
462		if ((token = xf86getToken(NULL)) == COMMENT)
463			option->opt_comment = xf86addComment(option->opt_comment, val.str);
464		else
465			xf86unGetToken(token);
466	}
467	else {
468		option = xf86newOption(name, NULL);
469		option->opt_comment = comment;
470		if (token == COMMENT)
471			option->opt_comment = xf86addComment(option->opt_comment, val.str);
472		else
473			xf86unGetToken(token);
474	}
475
476	old = NULL;
477
478	/* Don't allow duplicates */
479	if (head != NULL && (old = xf86findOption(head, name)) != NULL) {
480		cnew = old;
481		free(option->opt_name);
482		TestFree(option->opt_val);
483		TestFree(option->opt_comment);
484		free(option);
485	}
486	else
487		cnew = option;
488
489	if (old == NULL)
490		return ((XF86OptionPtr)xf86addListItem((glp)head, (glp)cnew));
491
492	return head;
493}
494
495void
496xf86printOptionList(FILE *fp, XF86OptionPtr list, int tabs)
497{
498	int i;
499
500	if (!list)
501		return;
502	while (list) {
503		for (i = 0; i < tabs; i++)
504			fputc('\t', fp);
505		if (list->opt_val)
506			fprintf(fp, "Option	    \"%s\" \"%s\"", list->opt_name, list->opt_val);
507		else
508			fprintf(fp, "Option	    \"%s\"", list->opt_name);
509		if (list->opt_comment)
510			fprintf(fp, "%s", list->opt_comment);
511		else
512			fputc('\n', fp);
513		list = list->list.next;
514	}
515}
516