Flags.c revision 4642e01f
1/*
2 *
3 * Copyright (c) 1997  Metro Link Incorporated
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
20 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Except as contained in this notice, the name of the Metro Link shall not be
24 * used in advertising or otherwise to promote the sale, use or other dealings
25 * in this Software without prior written authorization from Metro Link.
26 *
27 */
28/*
29 * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
30 *
31 * Permission is hereby granted, free of charge, to any person obtaining a
32 * copy of this software and associated documentation files (the "Software"),
33 * to deal in the Software without restriction, including without limitation
34 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
35 * and/or sell copies of the Software, and to permit persons to whom the
36 * Software is furnished to do so, subject to the following conditions:
37 *
38 * The above copyright notice and this permission notice shall be included in
39 * all copies or substantial portions of the Software.
40 *
41 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
44 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
45 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
46 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
47 * OTHER DEALINGS IN THE SOFTWARE.
48 *
49 * Except as contained in this notice, the name of the copyright holder(s)
50 * and author(s) shall not be used in advertising or otherwise to promote
51 * the sale, use or other dealings in this Software without prior written
52 * authorization from the copyright holder(s) and author(s).
53 */
54
55
56/* View/edit this file with tab stops set to 4 */
57
58#ifdef HAVE_XORG_CONFIG_H
59#include <xorg-config.h>
60#endif
61
62#include "xf86Parser.h"
63#include "xf86tokens.h"
64#include "Configint.h"
65#include <math.h>
66#include <X11/Xfuncproto.h>
67
68extern LexRec val;
69
70static xf86ConfigSymTabRec ServerFlagsTab[] =
71{
72	{ENDSECTION, "endsection"},
73	{NOTRAPSIGNALS, "notrapsignals"},
74	{DONTZAP, "dontzap"},
75	{DONTZOOM, "dontzoom"},
76	{DISABLEVIDMODE, "disablevidmodeextension"},
77	{ALLOWNONLOCAL, "allownonlocalxvidtune"},
78	{DISABLEMODINDEV, "disablemodindev"},
79	{MODINDEVALLOWNONLOCAL, "allownonlocalmodindev"},
80	{ALLOWMOUSEOPENFAIL, "allowmouseopenfail"},
81	{OPTION, "option"},
82	{BLANKTIME, "blanktime"},
83	{STANDBYTIME, "standbytime"},
84	{SUSPENDTIME, "suspendtime"},
85	{OFFTIME, "offtime"},
86	{DEFAULTLAYOUT, "defaultserverlayout"},
87	{-1, ""},
88};
89
90#define CLEANUP xf86freeFlags
91
92XF86ConfFlagsPtr
93xf86parseFlagsSection (void)
94{
95	int token;
96	parsePrologue (XF86ConfFlagsPtr, XF86ConfFlagsRec)
97
98	while ((token = xf86getToken (ServerFlagsTab)) != ENDSECTION)
99	{
100		int hasvalue = FALSE;
101		int strvalue = FALSE;
102		int tokentype;
103		switch (token)
104		{
105		case COMMENT:
106			ptr->flg_comment = xf86addComment(ptr->flg_comment, val.str);
107			break;
108			/*
109			 * these old keywords are turned into standard generic options.
110			 * we fall through here on purpose
111			 */
112		case DEFAULTLAYOUT:
113			strvalue = TRUE;
114		case BLANKTIME:
115		case STANDBYTIME:
116		case SUSPENDTIME:
117		case OFFTIME:
118			hasvalue = TRUE;
119		case NOTRAPSIGNALS:
120		case DONTZAP:
121		case DONTZOOM:
122		case DISABLEVIDMODE:
123		case ALLOWNONLOCAL:
124		case DISABLEMODINDEV:
125		case MODINDEVALLOWNONLOCAL:
126		case ALLOWMOUSEOPENFAIL:
127			{
128				int i = 0;
129				while (ServerFlagsTab[i].token != -1)
130				{
131					char *tmp;
132
133					if (ServerFlagsTab[i].token == token)
134					{
135						char *valstr = NULL;
136						/* can't use strdup because it calls malloc */
137						tmp = xf86configStrdup (ServerFlagsTab[i].name);
138						if (hasvalue)
139						{
140							tokentype = xf86getSubToken(&(ptr->flg_comment));
141							if (strvalue) {
142								if (tokentype != STRING)
143									Error (QUOTE_MSG, tmp);
144								valstr = val.str;
145							} else {
146								if (tokentype != NUMBER)
147									Error (NUMBER_MSG, tmp);
148								valstr = xf86confmalloc(16);
149								if (valstr)
150									sprintf(valstr, "%d", val.num);
151							}
152						}
153						ptr->flg_option_lst = xf86addNewOption
154							(ptr->flg_option_lst, tmp, valstr);
155					}
156					i++;
157				}
158			}
159			break;
160		case OPTION:
161			ptr->flg_option_lst = xf86parseOption(ptr->flg_option_lst);
162			break;
163
164		case EOF_TOKEN:
165			Error (UNEXPECTED_EOF_MSG, NULL);
166			break;
167		default:
168			Error (INVALID_KEYWORD_MSG, xf86tokenString ());
169			break;
170		}
171	}
172
173#ifdef DEBUG
174	printf ("Flags section parsed\n");
175#endif
176
177	return ptr;
178}
179
180#undef CLEANUP
181
182void
183xf86printServerFlagsSection (FILE * f, XF86ConfFlagsPtr flags)
184{
185	XF86OptionPtr p;
186
187	if ((!flags) || (!flags->flg_option_lst))
188		return;
189	p = flags->flg_option_lst;
190	fprintf (f, "Section \"ServerFlags\"\n");
191	if (flags->flg_comment)
192		fprintf (f, "%s", flags->flg_comment);
193	xf86printOptionList(f, p, 1);
194	fprintf (f, "EndSection\n\n");
195}
196
197static XF86OptionPtr
198addNewOption2 (XF86OptionPtr head, char *name, char *val, int used)
199{
200	XF86OptionPtr new, old = NULL;
201
202	/* Don't allow duplicates, free old strings */
203	if (head != NULL && (old = xf86findOption(head, name)) != NULL) {
204		new = old;
205		xf86conffree(new->opt_name);
206		xf86conffree(new->opt_val);
207	}
208	else
209		new = xf86confcalloc (1, sizeof (XF86OptionRec));
210	new->opt_name = name;
211	new->opt_val = val;
212	new->opt_used = used;
213
214	if (old)
215		return head;
216	return ((XF86OptionPtr) xf86addListItem ((glp) head, (glp) new));
217}
218
219XF86OptionPtr
220xf86addNewOption (XF86OptionPtr head, char *name, char *val)
221{
222	return addNewOption2(head, name, val, 0);
223}
224
225void
226xf86freeFlags (XF86ConfFlagsPtr flags)
227{
228	if (flags == NULL)
229		return;
230	xf86optionListFree (flags->flg_option_lst);
231	TestFree(flags->flg_comment);
232	xf86conffree (flags);
233}
234
235XF86OptionPtr
236xf86optionListDup (XF86OptionPtr opt)
237{
238	XF86OptionPtr newopt = NULL;
239
240	while (opt)
241	{
242		newopt = xf86addNewOption(newopt, xf86configStrdup(opt->opt_name),
243					  xf86configStrdup(opt->opt_val));
244		newopt->opt_used = opt->opt_used;
245		if (opt->opt_comment)
246			newopt->opt_comment = xf86configStrdup(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		xf86conffree (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 = xf86confcalloc(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
334_X_EXPORT char *
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 = xf86confmalloc (sizeof (char) *
370				(strlen (options[i]) + 1));
371		strcpy (t1, options[i]);
372		t2 = xf86confmalloc (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 = (int)(ceil(log10((double)i) + 2.5));
438	s = xf86confmalloc(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		if (comment)
455			xf86conffree(comment);
456		return (head);
457	}
458
459	name = val.str;
460	if ((token = xf86getSubToken(&comment)) == STRING) {
461		option = xf86newOption(name, val.str);
462		option->opt_comment = comment;
463		if ((token = xf86getToken(NULL)) == COMMENT)
464			option->opt_comment = xf86addComment(option->opt_comment, val.str);
465		else
466			xf86unGetToken(token);
467	}
468	else {
469		option = xf86newOption(name, NULL);
470		option->opt_comment = comment;
471		if (token == COMMENT)
472			option->opt_comment = xf86addComment(option->opt_comment, val.str);
473		else
474			xf86unGetToken(token);
475	}
476
477	old = NULL;
478
479	/* Don't allow duplicates */
480	if (head != NULL && (old = xf86findOption(head, name)) != NULL) {
481		cnew = old;
482		xf86conffree(option->opt_name);
483		TestFree(option->opt_val);
484		TestFree(option->opt_comment);
485		xf86conffree(option);
486	}
487	else
488		cnew = option;
489
490	if (old == NULL)
491		return ((XF86OptionPtr)xf86addListItem((glp)head, (glp)cnew));
492
493	return (head);
494}
495
496void
497xf86printOptionList(FILE *fp, XF86OptionPtr list, int tabs)
498{
499	int i;
500
501	if (!list)
502		return;
503	while (list) {
504		for (i = 0; i < tabs; i++)
505			fputc('\t', fp);
506		if (list->opt_val)
507			fprintf(fp, "Option	    \"%s\" \"%s\"", list->opt_name, list->opt_val);
508		else
509			fprintf(fp, "Option	    \"%s\"", list->opt_name);
510		if (list->opt_comment)
511			fprintf(fp, "%s", list->opt_comment);
512		else
513			fputc('\n', fp);
514		list = list->list.next;
515	}
516}
517