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