1 /*
2  * +-------------------------------------------------------+
3  * |                                                       |
4  * |     videogen                                          |
5  * |                                                       |
6  * |     a simple XFree86 Modeline calculator              |
7  * |     (c) 1997-2003, Szabolcs Rumi                      |
8  * |                                                       |
9  * |     http://www.dynaweb.hu/opensource/videogen         |
10  * |                                                       |
11  * |     the videogen package is distributed under the     |
12  * |     GNU General Public License Version 2 (GPLv2)      |
13  * |                                                       |
14  * +-------------------------------------------------------+
15  */
16 
17 
18 
19 
20 
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 
25 #include "config.h"
26 #include "videogen.h"
27 
28 
29 
30 
31 
32 arg_opt_t opts[] =
33 {
34 			{	"-h",	NULL,	0	},
35 			{	"-v",	NULL,	0	},
36 			{	"-q",	NULL,	0	},
37 			{	"-fb",	NULL,	0	},
38 			{	"-nfb",	NULL,	0	},
39 			{	"-nv",	NULL,	0	},
40 			{	"-nnv",	NULL,	0	},
41 			{	"-f",	NULL,	0	},
42 			{	"-m",	NULL,	0	},
43 			{	"-mdc",	NULL,	0	},
44 			{	"-mhf", NULL,	0	},
45 			{	"-mvf",	NULL,	0	},
46 			{	"-dvf",	NULL,	0	},
47 			{	"-hv",	NULL,	0	},
48 			{	"-vv",	NULL,	0	},
49 			{	"-hfp",	NULL,	0	},
50 			{	"-hbp",	NULL,	0	},
51 			{	"-hsp",	NULL,	0	},
52 			{	"-vfp",	NULL,	0	},
53 			{	"-vbp",	NULL,	0	},
54 			{	"-vsp",	NULL,	0	},
55 			{	NULL,	NULL,	0	}
56 };
57 
58 
59 
60 
61 
62 int
arg_action(arg_parse_t * ap)63 arg_action (arg_parse_t *ap)
64 {
65 	unsigned int x_uint, y_uint;
66 	double x_double;
67 
68 	char *serr = NULL;		/* for using with strtol(), strtod() */
69 
70 
71 
72 	/*
73 	fprintf (stdout, "argument %u matches option %u: %s == %s\n",
74 			ap->aindex, ap->oindex, (*ap->options)[ap->oindex].ao_option, (*ap->options)[ap->oindex].ao_parameter);
75 	*/
76 
77 	/*
78 	 * taking appropriate actions for each argument type
79 	 */
80 
81 	switch (ap->oindex)
82 	{
83 		case 0:	{
84 				banner ();
85 				usage ();
86 				exit (0);	/* either reading help or using the program... */
87 				break;
88 			}
89 
90 		case 1:	{
91 				if (commit_verbose (CFG_PREC_CMDLINE, &verbose, 1) == 0)
92 					pmsg (VL_DEBUG, "[cmdline] arg %u: verbose mode on\n", ap->aindex);
93 				break;
94 			}
95 
96 		case 2:	{
97 				if (commit_verbose (CFG_PREC_CMDLINE, &verbose, 0) == 0)
98 					pmsg (VL_DEBUG, "[cmdline] arg %u: verbose mode off\n", ap->aindex);
99 				break;
100 			}
101 
102 		case 3: {
103 				if (commit_fbset (CFG_PREC_CMDLINE, &fbset, 1) == 0)
104                                 	pmsg (VL_DEBUG, "[cmdline] arg %u: fbset mode on\n", ap->aindex);
105 				break;
106 			}
107 
108 		case 4: {
109 				if (commit_fbset (CFG_PREC_CMDLINE, &fbset, 0) == 0)
110                                 	pmsg (VL_DEBUG, "[cmdline] arg %u: fbset mode off\n", ap->aindex);
111 				break;
112 			}
113 
114 		case 5: {
115 				if (commit_nvidia (CFG_PREC_CMDLINE, &nvidia, 1) == 0)
116                                 	pmsg (VL_DEBUG, "[cmdline] arg %u: nvidia compatibility mode on\n", ap->aindex);
117 				break;
118 			}
119 
120 		case 6: {
121 				if (commit_nvidia (CFG_PREC_CMDLINE, &nvidia, 0) == 0)
122                                 	pmsg (VL_DEBUG, "[cmdline] arg %u: nvidia compatibility mode off\n", ap->aindex);
123 				break;
124 			}
125 
126 		case 7: {
127 				if ((*ap->options)[ap->oindex].ao_flags & ARG_FOUND_PARM)
128 				{
129 					cfgfile = (*ap->options)[ap->oindex].ao_parameter;
130 					pmsg (VL_DEBUG, "[cmdline] arg %u: config file set to %s\n", ap->aindex, cfgfile);
131 				}
132 				break;
133 			}
134 
135 		case 8: {
136 				if ((*ap->options)[ap->oindex].ao_flags & ARG_FOUND_PARM)
137 				{
138 					if (sscanf ((*ap->options)[ap->oindex].ao_parameter, "%ux%u", &x_uint, &y_uint) == 2)
139 					{
140 						switch (commit_mode (CFG_PREC_CMDLINE, &modes, &num_modes, x_uint, y_uint))
141 						{
142 							case -1: 	break;
143 
144 							case 0: {
145 									pmsg (VL_DEBUG, "[cmdline] arg %u: added mode %ux%u\n", ap->aindex, x_uint, y_uint);
146 									break;
147 								}
148 
149 							case 5: {
150 									pmsg (VL_DEBUG, "[cmdline] arg %u: too many modes, dropping %ux%u\n", ap->aindex, x_uint, y_uint);
151 									pmsg (VL_VERBOSE, "no more than 256 modes are allowed, dropping %ux%u\n", x_uint, y_uint);
152 									break;
153 								}
154 
155 							default: {
156 									pmsg (VL_DEBUG, "[cmdline] arg %u: %s has an invalid parameter \"%s\"\n", ap->aindex,
157 										(*ap->options)[ap->oindex].ao_option, (*ap->options)[ap->oindex].ao_parameter);
158 									pmsg (VL_VERBOSE, "argument %u (%s) has an invalid parameter\n", ap->aindex, ap->argv[ap->aindex]);
159 									return (-1);
160 								}
161 						}
162 					}
163 					else
164 						return (-1);
165 				}
166 				else
167 					return (-1);
168 
169 				break;
170 			}
171 
172 		case 9: {
173 				if ((*ap->options)[ap->oindex].ao_flags & ARG_FOUND_PARM)
174 				{
175 					x_double = strtod ((*ap->options)[ap->oindex].ao_parameter, &serr);
176 
177 					if ((*(*ap->options)[ap->oindex].ao_parameter != '\0') && (*serr == '\0'))
178 					{
179 						switch (commit_max_dotclk (CFG_PREC_CMDLINE, &max_dotclk, x_double))
180 						{
181 							case -1:	break;
182 
183 							case 0:	{
184 									pmsg (VL_DEBUG, "[cmdline] arg %u: max_dotclk = %0.0f MHz\n", ap->aindex, x_double);
185 									break;
186 								}
187 
188 							default: {
189 									pmsg (VL_DEBUG, "[cmdline] arg %u: %s has an invalid parameter \"%s\"\n", ap->aindex,
190 										(*ap->options)[ap->oindex].ao_option, (*ap->options)[ap->oindex].ao_parameter);
191 									pmsg (VL_VERBOSE, "argument %u (%s) has an invalid parameter\n", ap->aindex, ap->argv[ap->aindex]);
192 									return (-1);
193 								}
194 						}
195 					}
196 					else
197 						return (-1);
198 				}
199 				else
200 					return (-1);
201 
202 				break;
203 			}
204 
205 		case 10: {
206 				if ((*ap->options)[ap->oindex].ao_flags & ARG_FOUND_PARM)
207 				{
208 					x_double = strtod ((*ap->options)[ap->oindex].ao_parameter, &serr);
209 
210 					if ((*(*ap->options)[ap->oindex].ao_parameter != '\0') && (*serr == '\0'))
211 					{
212 						switch (commit_max_hfreq (CFG_PREC_CMDLINE, &max_hfreq, x_double))
213 						{
214 							case -1:	break;
215 
216 							case 0:	{
217 									pmsg (VL_DEBUG, "[cmdline] arg %u: max_hfreq = %0.1f kHz\n", ap->aindex, x_double);
218 									break;
219 								}
220 
221 							default: {
222 									pmsg (VL_DEBUG, "[cmdline] arg %u: %s has an invalid parameter \"%s\"\n", ap->aindex,
223 										(*ap->options)[ap->oindex].ao_option, (*ap->options)[ap->oindex].ao_parameter);
224 									pmsg (VL_VERBOSE, "argument %u (%s) has an invalid parameter\n", ap->aindex, ap->argv[ap->aindex]);
225 									return (-1);
226 								}
227 						}
228 					}
229 					else
230 						return (-1);
231 				}
232 				else
233 					return (-1);
234 
235 				break;
236 			}
237 
238 		case 11: {
239 				if ((*ap->options)[ap->oindex].ao_flags & ARG_FOUND_PARM)
240 				{
241 					x_double = strtod ((*ap->options)[ap->oindex].ao_parameter, &serr);
242 
243 					if ((*(*ap->options)[ap->oindex].ao_parameter != '\0') && (*serr == '\0'))
244 					{
245 						switch (commit_max_vfreq (CFG_PREC_CMDLINE, &max_vfreq, x_double))
246 						{
247 							case -1:	break;
248 
249 							case 0:	{
250 									pmsg (VL_DEBUG, "[cmdline] arg %u: max_vfreq = %0.1f Hz\n", ap->aindex, x_double);
251 									break;
252 								}
253 
254 							default: {
255 									pmsg (VL_DEBUG, "[cmdline] arg %u: %s has an invalid parameter \"%s\"\n", ap->aindex,
256 										(*ap->options)[ap->oindex].ao_option, (*ap->options)[ap->oindex].ao_parameter);
257 									pmsg (VL_VERBOSE, "argument %u (%s) has an invalid parameter\n", ap->aindex, ap->argv[ap->aindex]);
258 									return (-1);
259 								}
260 						}
261 					}
262 					else
263 						return (-1);
264 				}
265 				else
266 					return (-1);
267 
268 				break;
269 			}
270 
271 		case 12: {
272 				if ((*ap->options)[ap->oindex].ao_flags & ARG_FOUND_PARM)
273 				{
274 					x_double = strtod ((*ap->options)[ap->oindex].ao_parameter, &serr);
275 
276 					if ((*(*ap->options)[ap->oindex].ao_parameter != '\0') && (*serr == '\0'))
277 					{
278 						switch (commit_desired_vfreq (CFG_PREC_CMDLINE, &desired_vfreq, x_double))
279 						{
280 							case -1:	break;
281 
282 							case 0:	{
283 									pmsg (VL_DEBUG, "[cmdline] arg %u: desired_vfreq = %0.1f Hz\n", ap->aindex, x_double);
284 									break;
285 								}
286 
287 							default: {
288 									pmsg (VL_DEBUG, "[cmdline] arg %u: %s has an invalid parameter \"%s\"\n", ap->aindex,
289 										(*ap->options)[ap->oindex].ao_option, (*ap->options)[ap->oindex].ao_parameter);
290 									pmsg (VL_VERBOSE, "argument %u (%s) has an invalid parameter\n", ap->aindex, ap->argv[ap->aindex]);
291 									return (-1);
292 								}
293 						}
294 					}
295 					else
296 						return (-1);
297 				}
298 				else
299 					return (-1);
300 
301 				break;
302 			}
303 
304 		case 13: {
305 				if ((*ap->options)[ap->oindex].ao_flags & ARG_FOUND_PARM)
306 				{
307 					x_double = strtod ((*ap->options)[ap->oindex].ao_parameter, &serr);
308 
309 					if ((*(*ap->options)[ap->oindex].ao_parameter != '\0') && (*serr == '\0'))
310 					{
311 						switch (commit_hvisible (CFG_PREC_CMDLINE, &hvisible, x_double))
312 						{
313 							case -1:	break;
314 
315 							case 0:	{
316 									pmsg (VL_DEBUG, "[cmdline] arg %u: hvisible = %0.0f %\n", ap->aindex, x_double);
317 									break;
318 								}
319 
320 							default: {
321 									pmsg (VL_DEBUG, "[cmdline] arg %u: %s has an invalid parameter \"%s\"\n", ap->aindex,
322 										(*ap->options)[ap->oindex].ao_option, (*ap->options)[ap->oindex].ao_parameter);
323 									pmsg (VL_VERBOSE, "argument %u (%s) has an invalid parameter\n", ap->aindex, ap->argv[ap->aindex]);
324 									return (-1);
325 								}
326 						}
327 					}
328 					else
329 						return (-1);
330 				}
331 				else
332 					return (-1);
333 
334 				break;
335 			}
336 
337 		case 14: {
338 				if ((*ap->options)[ap->oindex].ao_flags & ARG_FOUND_PARM)
339 				{
340 					x_double = strtod ((*ap->options)[ap->oindex].ao_parameter, &serr);
341 
342 					if ((*(*ap->options)[ap->oindex].ao_parameter != '\0') && (*serr == '\0'))
343 					{
344 						switch (commit_vvisible (CFG_PREC_CMDLINE, &vvisible, x_double))
345 						{
346 							case -1:	break;
347 
348 							case 0:	{
349 									pmsg (VL_DEBUG, "[cmdline] arg %u: vvisible = %0.0f %\n", ap->aindex, x_double);
350 									break;
351 								}
352 
353 							default: {
354 									pmsg (VL_DEBUG, "[cmdline] arg %u: %s has an invalid parameter \"%s\"\n", ap->aindex,
355 										(*ap->options)[ap->oindex].ao_option, (*ap->options)[ap->oindex].ao_parameter);
356 									pmsg (VL_VERBOSE, "argument %u (%s) has an invalid parameter\n", ap->aindex, ap->argv[ap->aindex]);
357 									return (-1);
358 								}
359 						}
360 					}
361 					else
362 						return (-1);
363 				}
364 				else
365 					return (-1);
366 
367 				break;
368 			}
369 
370 		case 15: {
371 				if ((*ap->options)[ap->oindex].ao_flags & ARG_FOUND_PARM)
372 				{
373 					x_double = strtod ((*ap->options)[ap->oindex].ao_parameter, &serr);
374 
375 					if ((*(*ap->options)[ap->oindex].ao_parameter != '\0') && (*serr == '\0'))
376 					{
377 						switch (commit_hfporch (CFG_PREC_CMDLINE, &hfporch, x_double))
378 						{
379 							case -1:	break;
380 
381 							case 0:	{
382 									pmsg (VL_DEBUG, "[cmdline] arg %u: hfporch = %0.0f ticks\n", ap->aindex, x_double);
383 									break;
384 								}
385 
386 							default: {
387 									pmsg (VL_DEBUG, "[cmdline] arg %u: %s has an invalid parameter \"%s\"\n", ap->aindex,
388 										(*ap->options)[ap->oindex].ao_option, (*ap->options)[ap->oindex].ao_parameter);
389 									pmsg (VL_VERBOSE, "argument %u (%s) has an invalid parameter\n", ap->aindex, ap->argv[ap->aindex]);
390 									return (-1);
391 								}
392 						}
393 					}
394 					else
395 						return (-1);
396 				}
397 				else
398 					return (-1);
399 
400 				break;
401 			}
402 
403 		case 16: {
404 				if ((*ap->options)[ap->oindex].ao_flags & ARG_FOUND_PARM)
405 				{
406 					x_double = strtod ((*ap->options)[ap->oindex].ao_parameter, &serr);
407 
408 					if ((*(*ap->options)[ap->oindex].ao_parameter != '\0') && (*serr == '\0'))
409 					{
410 						switch (commit_hbporch (CFG_PREC_CMDLINE, &hbporch, x_double))
411 						{
412 							case -1:	break;
413 
414 							case 0:	{
415 									pmsg (VL_DEBUG, "[cmdline] arg %u: hbporch = %0.0f ticks\n", ap->aindex, x_double);
416 									break;
417 								}
418 
419 							default: {
420 									pmsg (VL_DEBUG, "[cmdline] arg %u: %s has an invalid parameter \"%s\"\n", ap->aindex,
421 										(*ap->options)[ap->oindex].ao_option, (*ap->options)[ap->oindex].ao_parameter);
422 									pmsg (VL_VERBOSE, "argument %u (%s) has an invalid parameter\n", ap->aindex, ap->argv[ap->aindex]);
423 									return (-1);
424 								}
425 						}
426 					}
427 					else
428 						return (-1);
429 				}
430 				else
431 					return (-1);
432 
433 				break;
434 			}
435 
436 		case 17: {
437 				if ((*ap->options)[ap->oindex].ao_flags & ARG_FOUND_PARM)
438 				{
439 					x_double = strtod ((*ap->options)[ap->oindex].ao_parameter, &serr);
440 
441 					if ((*(*ap->options)[ap->oindex].ao_parameter != '\0') && (*serr == '\0'))
442 					{
443 						switch (commit_hsync (CFG_PREC_CMDLINE, &hsync, x_double))
444 						{
445 							case -1:	break;
446 
447 							case 0:	{
448 									pmsg (VL_DEBUG, "[cmdline] arg %u: hsync = %0.1f usec\n", ap->aindex, x_double);
449 									break;
450 								}
451 
452 							default: {
453 									pmsg (VL_DEBUG, "[cmdline] arg %u: %s has an invalid parameter \"%s\"\n", ap->aindex,
454 										(*ap->options)[ap->oindex].ao_option, (*ap->options)[ap->oindex].ao_parameter);
455 									pmsg (VL_VERBOSE, "argument %u (%s) has an invalid parameter\n", ap->aindex, ap->argv[ap->aindex]);
456 									return (-1);
457 								}
458 						}
459 					}
460 					else
461 						return (-1);
462 				}
463 				else
464 					return (-1);
465 
466 				break;
467 			}
468 
469 		case 18: {
470 				if ((*ap->options)[ap->oindex].ao_flags & ARG_FOUND_PARM)
471 				{
472 					x_double = strtod ((*ap->options)[ap->oindex].ao_parameter, &serr);
473 
474 					if ((*(*ap->options)[ap->oindex].ao_parameter != '\0') && (*serr == '\0'))
475 					{
476 						switch (commit_vfporch (CFG_PREC_CMDLINE, &vfporch, x_double))
477 						{
478 							case -1:	break;
479 
480 							case 0:	{
481 									pmsg (VL_DEBUG, "[cmdline] arg %u: vfporch = %0.0f ticks\n", ap->aindex, x_double);
482 									break;
483 								}
484 
485 							default: {
486 									pmsg (VL_DEBUG, "[cmdline] arg %u: %s has an invalid parameter \"%s\"\n", ap->aindex,
487 										(*ap->options)[ap->oindex].ao_option, (*ap->options)[ap->oindex].ao_parameter);
488 									pmsg (VL_VERBOSE, "argument %u (%s) has an invalid parameter\n", ap->aindex, ap->argv[ap->aindex]);
489 									return (-1);
490 								}
491 						}
492 					}
493 					else
494 						return (-1);
495 				}
496 				else
497 					return (-1);
498 
499 				break;
500 			}
501 
502 		case 19: {
503 				if ((*ap->options)[ap->oindex].ao_flags & ARG_FOUND_PARM)
504 				{
505 					x_double = strtod ((*ap->options)[ap->oindex].ao_parameter, &serr);
506 
507 					if ((*(*ap->options)[ap->oindex].ao_parameter != '\0') && (*serr == '\0'))
508 					{
509 						switch (commit_vbporch (CFG_PREC_CMDLINE, &vbporch, x_double))
510 						{
511 							case -1:	break;
512 
513 							case 0:	{
514 									pmsg (VL_DEBUG, "[cmdline] arg %u: vbporch = %0.0f ticks\n", ap->aindex, x_double);
515 									break;
516 								}
517 
518 							default: {
519 									pmsg (VL_DEBUG, "[cmdline] arg %u: %s has an invalid parameter \"%s\"\n", ap->aindex,
520 										(*ap->options)[ap->oindex].ao_option, (*ap->options)[ap->oindex].ao_parameter);
521 									pmsg (VL_VERBOSE, "argument %u (%s) has an invalid parameter\n", ap->aindex, ap->argv[ap->aindex]);
522 									return (-1);
523 								}
524 						}
525 					}
526 					else
527 						return (-1);
528 				}
529 				else
530 					return (-1);
531 
532 				break;
533 			}
534 
535 		case 20: {
536 				if ((*ap->options)[ap->oindex].ao_flags & ARG_FOUND_PARM)
537 				{
538 					x_double = strtod ((*ap->options)[ap->oindex].ao_parameter, &serr);
539 
540 					if ((*(*ap->options)[ap->oindex].ao_parameter != '\0') && (*serr == '\0'))
541 					{
542 						switch (commit_vsync (CFG_PREC_CMDLINE, &vsync, x_double))
543 						{
544 							case -1:	break;
545 
546 							case 0:	{
547 									pmsg (VL_DEBUG, "[cmdline] arg %u: vsync = %0.0f usec\n", ap->aindex, x_double);
548 									break;
549 								}
550 
551 							default: {
552 									pmsg (VL_DEBUG, "[cmdline] arg %u: %s has an invalid parameter \"%s\"\n", ap->aindex,
553 										(*ap->options)[ap->oindex].ao_option, (*ap->options)[ap->oindex].ao_parameter);
554 									pmsg (VL_VERBOSE, "argument %u (%s) has an invalid parameter\n", ap->aindex, ap->argv[ap->aindex]);
555 									return (-1);
556 								}
557 						}
558 					}
559 					else
560 						return (-1);
561 				}
562 				else
563 					return (-1);
564 
565 				break;
566 			}
567 
568 		default: {
569 				pmsg (VL_DEBUG, "[cmdline] arg %u: unrecognized argument \"%s\"\n", ap->aindex, ap->argv[ap->aindex]);
570 				pmsg (VL_VERBOSE, "invalid argument %u (%s)\n", ap->aindex, ap->argv[ap->aindex]);
571 				return (-1);
572 			}
573 	}
574 
575 	return (0);
576 }
577 
578 
579 
580 
581 
582 int
arg_parse(arg_parse_t * ap,int (* arg_action)(arg_parse_t *))583 arg_parse (arg_parse_t *ap, int (*arg_action) (arg_parse_t *))
584 {
585 	char *eq;
586 	int match;
587 
588 
589 
590 	/*
591 	 * parse all arguments present on the command line
592 	 */
593 
594 	ap->aindex = 1;
595 	while (ap->aindex < ap->argc)
596 	{
597 		ap->oindex = 0;
598 		match = 0;
599 
600 		while ((*ap->options)[ap->oindex].ao_option != NULL)
601 		{
602 			if ((eq = strchr (ap->argv[ap->aindex], '=')) == NULL)
603 			{
604 				/*
605 				 * argument does not have a parameter
606 				 */
607 
608 				if (strcmp ((*ap->options)[ap->oindex].ao_option, ap->argv[ap->aindex]) == 0)
609 				{
610 					match++;
611 					(*ap->options)[ap->oindex].ao_flags |= ARG_FOUND;
612 
613 					if ((*arg_action) (ap) < 0)
614 						return (-1);
615 				}
616 			}
617 			else
618 			{
619 				/*
620 				 * argument does have a parameter
621 				 */
622 
623 				*eq = '\0';	/* temporarily split string at the equal sign */
624 
625 				if (strcmp ((*ap->options)[ap->oindex].ao_option, ap->argv[ap->aindex]) == 0)
626 				{
627 					match++;
628 					(*ap->options)[ap->oindex].ao_flags |= ARG_FOUND;
629 					(*ap->options)[ap->oindex].ao_flags |= ARG_FOUND_PARM;
630 					(*ap->options)[ap->oindex].ao_parameter = eq + 1;
631 
632 					*eq = '=';	/* restore equal sign */
633 					if ((*arg_action) (ap) < 0)
634 						return (-1);
635 				}
636 				else
637 					*eq = '=';	/* restore equal sign */
638 			}
639 
640 			ap->oindex++;
641 		}
642 
643 		if (((*ap->options)[ap->oindex].ao_option != NULL) && (match == 0))
644 		{
645 			ap->oindex = -1;	/* signal unmatched argument */
646 			if ((*arg_action) (ap) < 0)
647 				return (-1);
648 		}
649 
650 		ap->aindex++;
651 	}
652 
653 	return (0);
654 }
655 
656 
657 
658 
659 
660 /* EOF */
661