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