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
66extern LexRec val;
67
68static xf86ConfigSymTabRec MonitorTab[] =
69{
70	{ENDSECTION, "endsection"},
71	{IDENTIFIER, "identifier"},
72	{VENDOR, "vendorname"},
73	{MODEL, "modelname"},
74	{USEMODES, "usemodes"},
75	{MODELINE, "modeline"},
76	{DISPLAYSIZE, "displaysize"},
77	{HORIZSYNC, "horizsync"},
78	{VERTREFRESH, "vertrefresh"},
79	{MODE, "mode"},
80	{GAMMA, "gamma"},
81	{OPTION, "option"},
82	{-1, ""},
83};
84
85static xf86ConfigSymTabRec ModesTab[] =
86{
87	{ENDSECTION, "endsection"},
88	{IDENTIFIER, "identifier"},
89	{MODELINE, "modeline"},
90	{MODE, "mode"},
91	{-1, ""},
92};
93
94static xf86ConfigSymTabRec TimingTab[] =
95{
96	{TT_INTERLACE, "interlace"},
97	{TT_PHSYNC, "+hsync"},
98	{TT_NHSYNC, "-hsync"},
99	{TT_PVSYNC, "+vsync"},
100	{TT_NVSYNC, "-vsync"},
101	{TT_CSYNC, "composite"},
102	{TT_PCSYNC, "+csync"},
103	{TT_NCSYNC, "-csync"},
104	{TT_DBLSCAN, "doublescan"},
105	{TT_HSKEW, "hskew"},
106	{TT_BCAST, "bcast"},
107	{TT_VSCAN, "vscan"},
108	{-1, ""},
109};
110
111static xf86ConfigSymTabRec ModeTab[] =
112{
113	{DOTCLOCK, "dotclock"},
114	{HTIMINGS, "htimings"},
115	{VTIMINGS, "vtimings"},
116	{FLAGS, "flags"},
117	{HSKEW, "hskew"},
118	{BCAST, "bcast"},
119	{VSCAN, "vscan"},
120	{ENDMODE, "endmode"},
121	{-1, ""},
122};
123
124#define CLEANUP xf86freeModeLineList
125
126static void
127xf86freeModeLineList (XF86ConfModeLinePtr ptr)
128{
129	XF86ConfModeLinePtr prev;
130	while (ptr)
131	{
132		TestFree (ptr->ml_identifier);
133		TestFree (ptr->ml_comment);
134		prev = ptr;
135		ptr = ptr->list.next;
136		free (prev);
137	}
138}
139
140static XF86ConfModeLinePtr
141xf86parseModeLine (void)
142{
143	int token;
144	parsePrologue (XF86ConfModeLinePtr, XF86ConfModeLineRec)
145
146	/* Identifier */
147	if (xf86getSubToken (&(ptr->ml_comment)) != STRING)
148		Error ("ModeLine identifier expected", NULL);
149	ptr->ml_identifier = val.str;
150
151	/* DotClock */
152	if (xf86getSubToken (&(ptr->ml_comment)) != NUMBER)
153		Error ("ModeLine dotclock expected", NULL);
154	ptr->ml_clock = (int) (val.realnum * 1000.0 + 0.5);
155
156	/* HDisplay */
157	if (xf86getSubToken (&(ptr->ml_comment)) != NUMBER)
158		Error ("ModeLine Hdisplay expected", NULL);
159	ptr->ml_hdisplay = val.num;
160
161	/* HSyncStart */
162	if (xf86getSubToken (&(ptr->ml_comment)) != NUMBER)
163		Error ("ModeLine HSyncStart expected", NULL);
164	ptr->ml_hsyncstart = val.num;
165
166	/* HSyncEnd */
167	if (xf86getSubToken (&(ptr->ml_comment)) != NUMBER)
168		Error ("ModeLine HSyncEnd expected", NULL);
169	ptr->ml_hsyncend = val.num;
170
171	/* HTotal */
172	if (xf86getSubToken (&(ptr->ml_comment)) != NUMBER)
173		Error ("ModeLine HTotal expected", NULL);
174	ptr->ml_htotal = val.num;
175
176	/* VDisplay */
177	if (xf86getSubToken (&(ptr->ml_comment)) != NUMBER)
178		Error ("ModeLine Vdisplay expected", NULL);
179	ptr->ml_vdisplay = val.num;
180
181	/* VSyncStart */
182	if (xf86getSubToken (&(ptr->ml_comment)) != NUMBER)
183		Error ("ModeLine VSyncStart expected", NULL);
184	ptr->ml_vsyncstart = val.num;
185
186	/* VSyncEnd */
187	if (xf86getSubToken (&(ptr->ml_comment)) != NUMBER)
188		Error ("ModeLine VSyncEnd expected", NULL);
189	ptr->ml_vsyncend = val.num;
190
191	/* VTotal */
192	if (xf86getSubToken (&(ptr->ml_comment)) != NUMBER)
193		Error ("ModeLine VTotal expected", NULL);
194	ptr->ml_vtotal = val.num;
195
196	token = xf86getSubTokenWithTab (&(ptr->ml_comment), TimingTab);
197	while ((token == TT_INTERLACE) || (token == TT_PHSYNC) ||
198		   (token == TT_NHSYNC) || (token == TT_PVSYNC) ||
199		   (token == TT_NVSYNC) || (token == TT_CSYNC) ||
200		   (token == TT_PCSYNC) || (token == TT_NCSYNC) ||
201		   (token == TT_DBLSCAN) || (token == TT_HSKEW) ||
202		   (token == TT_VSCAN) || (token == TT_BCAST))
203	{
204		switch (token)
205		{
206
207		case TT_INTERLACE:
208			ptr->ml_flags |= XF86CONF_INTERLACE;
209			break;
210		case TT_PHSYNC:
211			ptr->ml_flags |= XF86CONF_PHSYNC;
212			break;
213		case TT_NHSYNC:
214			ptr->ml_flags |= XF86CONF_NHSYNC;
215			break;
216		case TT_PVSYNC:
217			ptr->ml_flags |= XF86CONF_PVSYNC;
218			break;
219		case TT_NVSYNC:
220			ptr->ml_flags |= XF86CONF_NVSYNC;
221			break;
222		case TT_CSYNC:
223			ptr->ml_flags |= XF86CONF_CSYNC;
224			break;
225		case TT_PCSYNC:
226			ptr->ml_flags |= XF86CONF_PCSYNC;
227			break;
228		case TT_NCSYNC:
229			ptr->ml_flags |= XF86CONF_NCSYNC;
230			break;
231		case TT_DBLSCAN:
232			ptr->ml_flags |= XF86CONF_DBLSCAN;
233			break;
234		case TT_HSKEW:
235			if (xf86getSubToken (&(ptr->ml_comment)) != NUMBER)
236				Error (NUMBER_MSG, "Hskew");
237			ptr->ml_hskew = val.num;
238			ptr->ml_flags |= XF86CONF_HSKEW;
239			break;
240		case TT_BCAST:
241			ptr->ml_flags |= XF86CONF_BCAST;
242			break;
243		case TT_VSCAN:
244			if (xf86getSubToken (&(ptr->ml_comment)) != NUMBER)
245				Error (NUMBER_MSG, "Vscan");
246			ptr->ml_vscan = val.num;
247			ptr->ml_flags |= XF86CONF_VSCAN;
248			break;
249		case EOF_TOKEN:
250			Error (UNEXPECTED_EOF_MSG, NULL);
251			break;
252		default:
253			Error (INVALID_KEYWORD_MSG, xf86tokenString ());
254			break;
255		}
256		token = xf86getSubTokenWithTab (&(ptr->ml_comment), TimingTab);
257	}
258	xf86unGetToken (token);
259
260#ifdef DEBUG
261	printf ("ModeLine parsed\n");
262#endif
263	return ptr;
264}
265
266static XF86ConfModeLinePtr
267xf86parseVerboseMode (void)
268{
269	int token, token2;
270	int had_dotclock = 0, had_htimings = 0, had_vtimings = 0;
271	parsePrologue (XF86ConfModeLinePtr, XF86ConfModeLineRec)
272
273		if (xf86getSubToken (&(ptr->ml_comment)) != STRING)
274		Error ("Mode name expected", NULL);
275	ptr->ml_identifier = val.str;
276	while ((token = xf86getToken (ModeTab)) != ENDMODE)
277	{
278		switch (token)
279		{
280		case COMMENT:
281			ptr->ml_comment = xf86addComment(ptr->ml_comment, val.str);
282			break;
283		case DOTCLOCK:
284			if ((token = xf86getSubToken (&(ptr->ml_comment))) != NUMBER)
285				Error (NUMBER_MSG, "DotClock");
286			ptr->ml_clock = (int) (val.realnum * 1000.0 + 0.5);
287			had_dotclock = 1;
288			break;
289		case HTIMINGS:
290			if (xf86getSubToken (&(ptr->ml_comment)) == NUMBER)
291				ptr->ml_hdisplay = val.num;
292			else
293				Error ("Horizontal display expected", NULL);
294
295			if (xf86getSubToken (&(ptr->ml_comment)) == NUMBER)
296				ptr->ml_hsyncstart = val.num;
297			else
298				Error ("Horizontal sync start expected", NULL);
299
300			if (xf86getSubToken (&(ptr->ml_comment)) == NUMBER)
301				ptr->ml_hsyncend = val.num;
302			else
303				Error ("Horizontal sync end expected", NULL);
304
305			if (xf86getSubToken (&(ptr->ml_comment)) == NUMBER)
306				ptr->ml_htotal = val.num;
307			else
308				Error ("Horizontal total expected", NULL);
309			had_htimings = 1;
310			break;
311		case VTIMINGS:
312			if (xf86getSubToken (&(ptr->ml_comment)) == NUMBER)
313				ptr->ml_vdisplay = val.num;
314			else
315				Error ("Vertical display expected", NULL);
316
317			if (xf86getSubToken (&(ptr->ml_comment)) == NUMBER)
318				ptr->ml_vsyncstart = val.num;
319			else
320				Error ("Vertical sync start expected", NULL);
321
322			if (xf86getSubToken (&(ptr->ml_comment)) == NUMBER)
323				ptr->ml_vsyncend = val.num;
324			else
325				Error ("Vertical sync end expected", NULL);
326
327			if (xf86getSubToken (&(ptr->ml_comment)) == NUMBER)
328				ptr->ml_vtotal = val.num;
329			else
330				Error ("Vertical total expected", NULL);
331			had_vtimings = 1;
332			break;
333		case FLAGS:
334			token = xf86getSubToken (&(ptr->ml_comment));
335			if (token != STRING)
336				Error (QUOTE_MSG, "Flags");
337			while (token == STRING)
338			{
339				token2 = xf86getStringToken (TimingTab);
340				switch (token2)
341				{
342				case TT_INTERLACE:
343					ptr->ml_flags |= XF86CONF_INTERLACE;
344					break;
345				case TT_PHSYNC:
346					ptr->ml_flags |= XF86CONF_PHSYNC;
347					break;
348				case TT_NHSYNC:
349					ptr->ml_flags |= XF86CONF_NHSYNC;
350					break;
351				case TT_PVSYNC:
352					ptr->ml_flags |= XF86CONF_PVSYNC;
353					break;
354				case TT_NVSYNC:
355					ptr->ml_flags |= XF86CONF_NVSYNC;
356					break;
357				case TT_CSYNC:
358					ptr->ml_flags |= XF86CONF_CSYNC;
359					break;
360				case TT_PCSYNC:
361					ptr->ml_flags |= XF86CONF_PCSYNC;
362					break;
363				case TT_NCSYNC:
364					ptr->ml_flags |= XF86CONF_NCSYNC;
365					break;
366				case TT_DBLSCAN:
367					ptr->ml_flags |= XF86CONF_DBLSCAN;
368					break;
369				case EOF_TOKEN:
370					Error (UNEXPECTED_EOF_MSG, NULL);
371					break;
372				default:
373					Error ("Unknown flag string", NULL);
374					break;
375				}
376				token = xf86getSubToken (&(ptr->ml_comment));
377			}
378			xf86unGetToken (token);
379			break;
380		case HSKEW:
381			if (xf86getSubToken (&(ptr->ml_comment)) != NUMBER)
382				Error ("Horizontal skew expected", NULL);
383			ptr->ml_flags |= XF86CONF_HSKEW;
384			ptr->ml_hskew = val.num;
385			break;
386		case VSCAN:
387			if (xf86getSubToken (&(ptr->ml_comment)) != NUMBER)
388				Error ("Vertical scan count expected", NULL);
389			ptr->ml_flags |= XF86CONF_VSCAN;
390			ptr->ml_vscan = val.num;
391			break;
392		case EOF_TOKEN:
393			Error (UNEXPECTED_EOF_MSG, NULL);
394			break;
395		default:
396			Error ("Unexepcted token in verbose \"Mode\" entry\n", NULL);
397		}
398	}
399	if (!had_dotclock)
400		Error ("the dotclock is missing", NULL);
401	if (!had_htimings)
402		Error ("the horizontal timings are missing", NULL);
403	if (!had_vtimings)
404		Error ("the vertical timings are missing", NULL);
405
406#ifdef DEBUG
407	printf ("Verbose Mode parsed\n");
408#endif
409	return ptr;
410}
411
412#undef CLEANUP
413
414#define CLEANUP xf86freeMonitorList
415
416XF86ConfMonitorPtr
417xf86parseMonitorSection (void)
418{
419	int has_ident = FALSE;
420	int token;
421	parsePrologue (XF86ConfMonitorPtr, XF86ConfMonitorRec)
422
423		while ((token = xf86getToken (MonitorTab)) != ENDSECTION)
424	{
425		switch (token)
426		{
427		case COMMENT:
428			ptr->mon_comment = xf86addComment(ptr->mon_comment, val.str);
429			break;
430		case IDENTIFIER:
431			if (xf86getSubToken (&(ptr->mon_comment)) != STRING)
432				Error (QUOTE_MSG, "Identifier");
433			if (has_ident == TRUE)
434				Error (MULTIPLE_MSG, "Identifier");
435			ptr->mon_identifier = val.str;
436			has_ident = TRUE;
437			break;
438		case VENDOR:
439			if (xf86getSubToken (&(ptr->mon_comment)) != STRING)
440				Error (QUOTE_MSG, "Vendor");
441			ptr->mon_vendor = val.str;
442			break;
443		case MODEL:
444			if (xf86getSubToken (&(ptr->mon_comment)) != STRING)
445				Error (QUOTE_MSG, "ModelName");
446			ptr->mon_modelname = val.str;
447			break;
448		case MODE:
449			HANDLE_LIST (mon_modeline_lst, xf86parseVerboseMode,
450						 XF86ConfModeLinePtr);
451			break;
452		case MODELINE:
453			HANDLE_LIST (mon_modeline_lst, xf86parseModeLine,
454						 XF86ConfModeLinePtr);
455			break;
456		case DISPLAYSIZE:
457			if (xf86getSubToken (&(ptr->mon_comment)) != NUMBER)
458				Error (DISPLAYSIZE_MSG, NULL);
459			ptr->mon_width = val.realnum;
460			if (xf86getSubToken (&(ptr->mon_comment)) != NUMBER)
461				Error (DISPLAYSIZE_MSG, NULL);
462			ptr->mon_height = val.realnum;
463			break;
464
465		case HORIZSYNC:
466			if (xf86getSubToken (&(ptr->mon_comment)) != NUMBER)
467				Error (HORIZSYNC_MSG, NULL);
468			do {
469				if (ptr->mon_n_hsync >= CONF_MAX_HSYNC)
470					Error ("Sorry. Too many horizontal sync intervals.", NULL);
471				ptr->mon_hsync[ptr->mon_n_hsync].lo = val.realnum;
472				switch (token = xf86getSubToken (&(ptr->mon_comment)))
473				{
474					case COMMA:
475						ptr->mon_hsync[ptr->mon_n_hsync].hi =
476						ptr->mon_hsync[ptr->mon_n_hsync].lo;
477						break;
478					case DASH:
479						if (xf86getSubToken (&(ptr->mon_comment)) != NUMBER ||
480						    (float)val.realnum < ptr->mon_hsync[ptr->mon_n_hsync].lo)
481							Error (HORIZSYNC_MSG, NULL);
482						ptr->mon_hsync[ptr->mon_n_hsync].hi = val.realnum;
483						if ((token = xf86getSubToken (&(ptr->mon_comment))) == COMMA)
484							break;
485						ptr->mon_n_hsync++;
486						goto HorizDone;
487					default:
488						/* We cannot currently know if a '\n' was found,
489						 * or this is a real error
490						 */
491						ptr->mon_hsync[ptr->mon_n_hsync].hi =
492						ptr->mon_hsync[ptr->mon_n_hsync].lo;
493						ptr->mon_n_hsync++;
494						goto HorizDone;
495				}
496				ptr->mon_n_hsync++;
497			} while ((token = xf86getSubToken (&(ptr->mon_comment))) == NUMBER);
498HorizDone:
499			xf86unGetToken (token);
500			break;
501
502		case VERTREFRESH:
503			if (xf86getSubToken (&(ptr->mon_comment)) != NUMBER)
504				Error (VERTREFRESH_MSG, NULL);
505			do {
506				ptr->mon_vrefresh[ptr->mon_n_vrefresh].lo = val.realnum;
507				switch (token = xf86getSubToken (&(ptr->mon_comment)))
508				{
509					case COMMA:
510						ptr->mon_vrefresh[ptr->mon_n_vrefresh].hi =
511						ptr->mon_vrefresh[ptr->mon_n_vrefresh].lo;
512						break;
513					case DASH:
514						if (xf86getSubToken (&(ptr->mon_comment)) != NUMBER ||
515						    (float)val.realnum < ptr->mon_vrefresh[ptr->mon_n_vrefresh].lo)
516							Error (VERTREFRESH_MSG, NULL);
517						ptr->mon_vrefresh[ptr->mon_n_vrefresh].hi = val.realnum;
518						if ((token = xf86getSubToken (&(ptr->mon_comment))) == COMMA)
519							break;
520						ptr->mon_n_vrefresh++;
521						goto VertDone;
522					default:
523						/* We cannot currently know if a '\n' was found,
524						 * or this is a real error
525						 */
526						ptr->mon_vrefresh[ptr->mon_n_vrefresh].hi =
527						ptr->mon_vrefresh[ptr->mon_n_vrefresh].lo;
528						ptr->mon_n_vrefresh++;
529						goto VertDone;
530				}
531				if (ptr->mon_n_vrefresh >= CONF_MAX_VREFRESH)
532					Error ("Sorry. Too many vertical refresh intervals.", NULL);
533				ptr->mon_n_vrefresh++;
534			} while ((token = xf86getSubToken (&(ptr->mon_comment))) == NUMBER);
535VertDone:
536			xf86unGetToken (token);
537			break;
538
539		case GAMMA:
540			if( xf86getSubToken (&(ptr->mon_comment)) != NUMBER )
541			{
542				Error (INVALID_GAMMA_MSG, NULL);
543			}
544			else
545			{
546				ptr->mon_gamma_red = ptr->mon_gamma_green =
547					ptr->mon_gamma_blue = val.realnum;
548				if( xf86getSubToken (&(ptr->mon_comment)) == NUMBER )
549				{
550					ptr->mon_gamma_green = val.realnum;
551					if( xf86getSubToken (&(ptr->mon_comment)) == NUMBER )
552					{
553						ptr->mon_gamma_blue = val.realnum;
554					}
555					else
556					{
557						Error (INVALID_GAMMA_MSG, NULL);
558					}
559				}
560				else
561					xf86unGetToken (token);
562			}
563			break;
564		case OPTION:
565			ptr->mon_option_lst = xf86parseOption(ptr->mon_option_lst);
566			break;
567		case USEMODES:
568		        {
569				XF86ConfModesLinkPtr mptr;
570
571				if ((token = xf86getSubToken (&(ptr->mon_comment))) != STRING)
572					Error (QUOTE_MSG, "UseModes");
573
574				/* add to the end of the list of modes sections
575				   referenced here */
576				mptr = calloc (1, sizeof (XF86ConfModesLinkRec));
577				mptr->list.next = NULL;
578				mptr->ml_modes_str = val.str;
579				mptr->ml_modes = NULL;
580				ptr->mon_modes_sect_lst = (XF86ConfModesLinkPtr)
581					xf86addListItem((GenericListPtr)ptr->mon_modes_sect_lst,
582						    (GenericListPtr)mptr);
583			}
584			break;
585		case EOF_TOKEN:
586			Error (UNEXPECTED_EOF_MSG, NULL);
587			break;
588		default:
589			xf86parseError (INVALID_KEYWORD_MSG, xf86tokenString ());
590			CLEANUP (ptr);
591			return NULL;
592			break;
593		}
594	}
595
596	if (!has_ident)
597		Error (NO_IDENT_MSG, NULL);
598
599#ifdef DEBUG
600	printf ("Monitor section parsed\n");
601#endif
602	return ptr;
603}
604
605#undef CLEANUP
606#define CLEANUP xf86freeModesList
607
608XF86ConfModesPtr
609xf86parseModesSection (void)
610{
611	int has_ident = FALSE;
612	int token;
613	parsePrologue (XF86ConfModesPtr, XF86ConfModesRec)
614
615	while ((token = xf86getToken (ModesTab)) != ENDSECTION)
616	{
617		switch (token)
618		{
619		case COMMENT:
620			ptr->modes_comment = xf86addComment(ptr->modes_comment, val.str);
621			break;
622		case IDENTIFIER:
623			if (xf86getSubToken (&(ptr->modes_comment)) != STRING)
624				Error (QUOTE_MSG, "Identifier");
625			if (has_ident == TRUE)
626				Error (MULTIPLE_MSG, "Identifier");
627			ptr->modes_identifier = val.str;
628			has_ident = TRUE;
629			break;
630		case MODE:
631			HANDLE_LIST (mon_modeline_lst, xf86parseVerboseMode,
632						 XF86ConfModeLinePtr);
633			break;
634		case MODELINE:
635			HANDLE_LIST (mon_modeline_lst, xf86parseModeLine,
636						 XF86ConfModeLinePtr);
637			break;
638		default:
639			xf86parseError (INVALID_KEYWORD_MSG, xf86tokenString ());
640			CLEANUP (ptr);
641			return NULL;
642			break;
643		}
644	}
645
646	if (!has_ident)
647		Error (NO_IDENT_MSG, NULL);
648
649#ifdef DEBUG
650	printf ("Modes section parsed\n");
651#endif
652	return ptr;
653}
654
655#undef CLEANUP
656
657void
658xf86printMonitorSection (FILE * cf, XF86ConfMonitorPtr ptr)
659{
660	int i;
661	XF86ConfModeLinePtr mlptr;
662	XF86ConfModesLinkPtr mptr;
663
664	while (ptr)
665	{
666		mptr = ptr->mon_modes_sect_lst;
667		fprintf (cf, "Section \"Monitor\"\n");
668		if (ptr->mon_comment)
669			fprintf (cf, "%s", ptr->mon_comment);
670		if (ptr->mon_identifier)
671			fprintf (cf, "\tIdentifier   \"%s\"\n", ptr->mon_identifier);
672		if (ptr->mon_vendor)
673			fprintf (cf, "\tVendorName   \"%s\"\n", ptr->mon_vendor);
674		if (ptr->mon_modelname)
675			fprintf (cf, "\tModelName    \"%s\"\n", ptr->mon_modelname);
676		while (mptr) {
677			fprintf (cf, "\tUseModes     \"%s\"\n", mptr->ml_modes_str);
678			mptr = mptr->list.next;
679		}
680		if (ptr->mon_width)
681			fprintf (cf, "\tDisplaySize  %d\t%d\n",
682					 ptr->mon_width,
683					 ptr->mon_height);
684		for (i = 0; i < ptr->mon_n_hsync; i++)
685		{
686			fprintf (cf, "\tHorizSync    %2.1f - %2.1f\n",
687					 ptr->mon_hsync[i].lo,
688					 ptr->mon_hsync[i].hi);
689		}
690		for (i = 0; i < ptr->mon_n_vrefresh; i++)
691		{
692			fprintf (cf, "\tVertRefresh  %2.1f - %2.1f\n",
693					 ptr->mon_vrefresh[i].lo,
694					 ptr->mon_vrefresh[i].hi);
695		}
696		if (ptr->mon_gamma_red) {
697			if (ptr->mon_gamma_red == ptr->mon_gamma_green
698				&& ptr->mon_gamma_red == ptr->mon_gamma_blue)
699			{
700				fprintf (cf, "\tGamma        %.4g\n",
701					ptr->mon_gamma_red);
702			} else {
703				fprintf (cf, "\tGamma        %.4g %.4g %.4g\n",
704					ptr->mon_gamma_red,
705					ptr->mon_gamma_green,
706					ptr->mon_gamma_blue);
707			}
708		}
709		for (mlptr = ptr->mon_modeline_lst; mlptr; mlptr = mlptr->list.next)
710		{
711			fprintf (cf, "\tModeLine     \"%s\" %2.1f ",
712					 mlptr->ml_identifier, mlptr->ml_clock / 1000.0);
713			fprintf (cf, "%d %d %d %d %d %d %d %d",
714					 mlptr->ml_hdisplay, mlptr->ml_hsyncstart,
715					 mlptr->ml_hsyncend, mlptr->ml_htotal,
716					 mlptr->ml_vdisplay, mlptr->ml_vsyncstart,
717					 mlptr->ml_vsyncend, mlptr->ml_vtotal);
718			if (mlptr->ml_flags & XF86CONF_PHSYNC)
719				fprintf (cf, " +hsync");
720			if (mlptr->ml_flags & XF86CONF_NHSYNC)
721				fprintf (cf, " -hsync");
722			if (mlptr->ml_flags & XF86CONF_PVSYNC)
723				fprintf (cf, " +vsync");
724			if (mlptr->ml_flags & XF86CONF_NVSYNC)
725				fprintf (cf, " -vsync");
726			if (mlptr->ml_flags & XF86CONF_INTERLACE)
727				fprintf (cf, " interlace");
728			if (mlptr->ml_flags & XF86CONF_CSYNC)
729				fprintf (cf, " composite");
730			if (mlptr->ml_flags & XF86CONF_PCSYNC)
731				fprintf (cf, " +csync");
732			if (mlptr->ml_flags & XF86CONF_NCSYNC)
733				fprintf (cf, " -csync");
734			if (mlptr->ml_flags & XF86CONF_DBLSCAN)
735				fprintf (cf, " doublescan");
736			if (mlptr->ml_flags & XF86CONF_HSKEW)
737				fprintf (cf, " hskew %d", mlptr->ml_hskew);
738			if (mlptr->ml_flags & XF86CONF_BCAST)
739				fprintf (cf, " bcast");
740			fprintf (cf, "\n");
741		}
742		xf86printOptionList(cf, ptr->mon_option_lst, 1);
743		fprintf (cf, "EndSection\n\n");
744		ptr = ptr->list.next;
745	}
746}
747
748void
749xf86printModesSection (FILE * cf, XF86ConfModesPtr ptr)
750{
751	XF86ConfModeLinePtr mlptr;
752
753	while (ptr)
754	{
755		fprintf (cf, "Section \"Modes\"\n");
756		if (ptr->modes_comment)
757			fprintf (cf, "%s", ptr->modes_comment);
758		if (ptr->modes_identifier)
759			fprintf (cf, "\tIdentifier     \"%s\"\n", ptr->modes_identifier);
760		for (mlptr = ptr->mon_modeline_lst; mlptr; mlptr = mlptr->list.next)
761		{
762			fprintf (cf, "\tModeLine     \"%s\" %2.1f ",
763					 mlptr->ml_identifier, mlptr->ml_clock / 1000.0);
764			fprintf (cf, "%d %d %d %d %d %d %d %d",
765					 mlptr->ml_hdisplay, mlptr->ml_hsyncstart,
766					 mlptr->ml_hsyncend, mlptr->ml_htotal,
767					 mlptr->ml_vdisplay, mlptr->ml_vsyncstart,
768					 mlptr->ml_vsyncend, mlptr->ml_vtotal);
769			if (mlptr->ml_flags & XF86CONF_PHSYNC)
770				fprintf (cf, " +hsync");
771			if (mlptr->ml_flags & XF86CONF_NHSYNC)
772				fprintf (cf, " -hsync");
773			if (mlptr->ml_flags & XF86CONF_PVSYNC)
774				fprintf (cf, " +vsync");
775			if (mlptr->ml_flags & XF86CONF_NVSYNC)
776				fprintf (cf, " -vsync");
777			if (mlptr->ml_flags & XF86CONF_INTERLACE)
778				fprintf (cf, " interlace");
779			if (mlptr->ml_flags & XF86CONF_CSYNC)
780				fprintf (cf, " composite");
781			if (mlptr->ml_flags & XF86CONF_PCSYNC)
782				fprintf (cf, " +csync");
783			if (mlptr->ml_flags & XF86CONF_NCSYNC)
784				fprintf (cf, " -csync");
785			if (mlptr->ml_flags & XF86CONF_DBLSCAN)
786				fprintf (cf, " doublescan");
787			if (mlptr->ml_flags & XF86CONF_HSKEW)
788				fprintf (cf, " hskew %d", mlptr->ml_hskew);
789			if (mlptr->ml_flags & XF86CONF_VSCAN)
790				fprintf (cf, " vscan %d", mlptr->ml_vscan);
791			if (mlptr->ml_flags & XF86CONF_BCAST)
792				fprintf (cf, " bcast");
793			if (mlptr->ml_comment)
794				fprintf (cf, "%s", mlptr->ml_comment);
795			else
796				fprintf (cf, "\n");
797		}
798		fprintf (cf, "EndSection\n\n");
799		ptr = ptr->list.next;
800	}
801}
802
803void
804xf86freeMonitorList (XF86ConfMonitorPtr ptr)
805{
806	XF86ConfMonitorPtr prev;
807
808	while (ptr)
809	{
810		TestFree (ptr->mon_identifier);
811		TestFree (ptr->mon_vendor);
812		TestFree (ptr->mon_modelname);
813		TestFree (ptr->mon_comment);
814		xf86optionListFree (ptr->mon_option_lst);
815		xf86freeModeLineList (ptr->mon_modeline_lst);
816		prev = ptr;
817		ptr = ptr->list.next;
818		free (prev);
819	}
820}
821
822void
823xf86freeModesList (XF86ConfModesPtr ptr)
824{
825	XF86ConfModesPtr prev;
826
827	while (ptr)
828	{
829		TestFree (ptr->modes_identifier);
830		TestFree (ptr->modes_comment);
831		xf86freeModeLineList (ptr->mon_modeline_lst);
832		prev = ptr;
833		ptr = ptr->list.next;
834		free (prev);
835	}
836}
837
838XF86ConfMonitorPtr
839xf86findMonitor (const char *ident, XF86ConfMonitorPtr p)
840{
841	while (p)
842	{
843		if (xf86nameCompare (ident, p->mon_identifier) == 0)
844			return p;
845
846		p = p->list.next;
847	}
848	return NULL;
849}
850
851XF86ConfModesPtr
852xf86findModes (const char *ident, XF86ConfModesPtr p)
853{
854	while (p)
855	{
856		if (xf86nameCompare (ident, p->modes_identifier) == 0)
857			return p;
858
859		p = p->list.next;
860	}
861	return NULL;
862}
863
864XF86ConfModeLinePtr
865xf86findModeLine (const char *ident, XF86ConfModeLinePtr p)
866{
867	while (p)
868	{
869		if (xf86nameCompare (ident, p->ml_identifier) == 0)
870			return p;
871
872		p = p->list.next;
873	}
874	return NULL;
875}
876
877int
878xf86validateMonitor (XF86ConfigPtr p, XF86ConfScreenPtr screen)
879{
880	XF86ConfMonitorPtr monitor = screen->scrn_monitor;
881	XF86ConfModesLinkPtr modeslnk = monitor->mon_modes_sect_lst;
882	XF86ConfModesPtr modes;
883	while(modeslnk)
884	{
885		modes = xf86findModes (modeslnk->ml_modes_str, p->conf_modes_lst);
886		if (!modes)
887		{
888			xf86validationError (UNDEFINED_MODES_MSG,
889					     modeslnk->ml_modes_str,
890					     screen->scrn_identifier);
891			return FALSE;
892		}
893		modeslnk->ml_modes = modes;
894		modeslnk = modeslnk->list.next;
895	}
896	return TRUE;
897}
898