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 #ifdef HAVE_XORG_CONFIG_H 55 #include <xorg-config.h> 56 #endif 57 58 #include "xf86Parser.h" 59 #include "xf86tokens.h" 60 #include "Configint.h" 61 #include <X11/Xfuncproto.h> 62 #include "Xprintf.h" 63 #include "optionstr.h" 64 65 66 static const xf86ConfigSymTabRec ServerFlagsTab[] = { 67 {ENDSECTION, "endsection"}, 68 {DONTZAP, "dontzap"}, 69 {DONTZOOM, "dontzoom"}, 70 {DISABLEVIDMODE, "disablevidmodeextension"}, 71 {ALLOWNONLOCAL, "allownonlocalxvidtune"}, 72 {DISABLEMODINDEV, "disablemodindev"}, 73 {MODINDEVALLOWNONLOCAL, "allownonlocalmodindev"}, 74 {ALLOWMOUSEOPENFAIL, "allowmouseopenfail"}, 75 {OPTION, "option"}, 76 {BLANKTIME, "blanktime"}, 77 {STANDBYTIME, "standbytime"}, 78 {SUSPENDTIME, "suspendtime"}, 79 {OFFTIME, "offtime"}, 80 {DEFAULTLAYOUT, "defaultserverlayout"}, 81 {-1, ""}, 82 }; 83 84 #define CLEANUP xf86freeFlags 85 86 XF86ConfFlagsPtr 87 xf86parseFlagsSection(void) 88 { 89 int token; 90 91 parsePrologue(XF86ConfFlagsPtr, XF86ConfFlagsRec) 92 93 while ((token = xf86getToken(ServerFlagsTab)) != ENDSECTION) { 94 int hasvalue = FALSE; 95 int strvalue = FALSE; 96 int tokentype; 97 98 switch (token) { 99 case COMMENT: 100 ptr->flg_comment = xf86addComment(ptr->flg_comment, xf86_lex_val.str); 101 free(xf86_lex_val.str); 102 xf86_lex_val.str = NULL; 103 break; 104 /* 105 * these old keywords are turned into standard generic options. 106 * we fall through here on purpose 107 */ 108 case DEFAULTLAYOUT: 109 strvalue = TRUE; 110 /* fallthrough */ 111 case BLANKTIME: 112 case STANDBYTIME: 113 case SUSPENDTIME: 114 case OFFTIME: 115 hasvalue = TRUE; 116 /* fallthrough */ 117 case DONTZAP: 118 case DONTZOOM: 119 case DISABLEVIDMODE: 120 case ALLOWNONLOCAL: 121 case DISABLEMODINDEV: 122 case MODINDEVALLOWNONLOCAL: 123 case ALLOWMOUSEOPENFAIL: 124 { 125 int i = 0; 126 127 while (ServerFlagsTab[i].token != -1) { 128 char *tmp; 129 130 if (ServerFlagsTab[i].token == token) { 131 char *valstr = NULL; 132 133 tmp = strdup(ServerFlagsTab[i].name); 134 if (hasvalue) { 135 tokentype = xf86getSubToken(&(ptr->flg_comment)); 136 if (strvalue) { 137 if (tokentype != STRING) 138 Error(QUOTE_MSG, tmp); 139 valstr = xf86_lex_val.str; 140 } 141 else { 142 if (tokentype != NUMBER) 143 Error(NUMBER_MSG, tmp); 144 if (asprintf(&valstr, "%d", xf86_lex_val.num) == -1) 145 valstr = NULL; 146 } 147 } 148 ptr->flg_option_lst = xf86addNewOption 149 (ptr->flg_option_lst, tmp, valstr); 150 } 151 i++; 152 } 153 } 154 break; 155 case OPTION: 156 ptr->flg_option_lst = xf86parseOption(ptr->flg_option_lst); 157 break; 158 159 case EOF_TOKEN: 160 Error(UNEXPECTED_EOF_MSG); 161 break; 162 default: 163 Error(INVALID_KEYWORD_MSG, xf86tokenString()); 164 break; 165 } 166 } 167 168 #ifdef DEBUG 169 printf("Flags section parsed\n"); 170 #endif 171 172 return ptr; 173 } 174 175 #undef CLEANUP 176 177 void 178 xf86printServerFlagsSection(FILE * f, XF86ConfFlagsPtr flags) 179 { 180 XF86OptionPtr p; 181 182 if ((!flags) || (!flags->flg_option_lst)) 183 return; 184 p = flags->flg_option_lst; 185 fprintf(f, "Section \"ServerFlags\"\n"); 186 if (flags->flg_comment) 187 fprintf(f, "%s", flags->flg_comment); 188 xf86printOptionList(f, p, 1); 189 fprintf(f, "EndSection\n\n"); 190 } 191 192 static XF86OptionPtr 193 addNewOption2(XF86OptionPtr head, char *name, char *_val, int used) 194 { 195 XF86OptionPtr new, old = NULL; 196 197 /* Don't allow duplicates, free old strings */ 198 if (head != NULL && (old = xf86findOption(head, name)) != NULL) { 199 new = old; 200 free(new->opt_name); 201 free(new->opt_val); 202 } 203 else 204 new = calloc(1, sizeof(*new)); 205 new->opt_name = name; 206 new->opt_val = _val; 207 new->opt_used = used; 208 209 if (old) 210 return head; 211 return ((XF86OptionPtr) xf86addListItem((glp) head, (glp) new)); 212 } 213 214 XF86OptionPtr 215 xf86addNewOption(XF86OptionPtr head, char *name, char *_val) 216 { 217 return addNewOption2(head, name, _val, 0); 218 } 219 220 void 221 xf86freeFlags(XF86ConfFlagsPtr flags) 222 { 223 if (flags == NULL) 224 return; 225 xf86optionListFree(flags->flg_option_lst); 226 TestFree(flags->flg_comment); 227 free(flags); 228 } 229 230 XF86OptionPtr 231 xf86optionListDup(XF86OptionPtr opt) 232 { 233 XF86OptionPtr newopt = NULL; 234 char *_val; 235 236 while (opt) { 237 _val = opt->opt_val ? strdup(opt->opt_val) : NULL; 238 newopt = xf86addNewOption(newopt, strdup(opt->opt_name), _val); 239 newopt->opt_used = opt->opt_used; 240 if (opt->opt_comment) 241 newopt->opt_comment = strdup(opt->opt_comment); 242 opt = opt->list.next; 243 } 244 return newopt; 245 } 246 247 void 248 xf86optionListFree(XF86OptionPtr opt) 249 { 250 XF86OptionPtr prev; 251 252 while (opt) { 253 TestFree(opt->opt_name); 254 TestFree(opt->opt_val); 255 TestFree(opt->opt_comment); 256 prev = opt; 257 opt = opt->list.next; 258 free(prev); 259 } 260 } 261 262 char * 263 xf86optionName(XF86OptionPtr opt) 264 { 265 if (opt) 266 return opt->opt_name; 267 return 0; 268 } 269 270 char * 271 xf86optionValue(XF86OptionPtr opt) 272 { 273 if (opt) 274 return opt->opt_val; 275 return 0; 276 } 277 278 XF86OptionPtr 279 xf86newOption(char *name, char *value) 280 { 281 XF86OptionPtr opt; 282 283 opt = calloc(1, sizeof(*opt)); 284 if (!opt) 285 return NULL; 286 287 opt->opt_used = 0; 288 opt->list.next = 0; 289 opt->opt_name = name; 290 opt->opt_val = value; 291 292 return opt; 293 } 294 295 XF86OptionPtr 296 xf86nextOption(XF86OptionPtr list) 297 { 298 if (!list) 299 return NULL; 300 return list->list.next; 301 } 302 303 /* 304 * this function searches the given option list for the named option and 305 * returns a pointer to the option rec if found. If not found, it returns 306 * NULL 307 */ 308 309 XF86OptionPtr 310 xf86findOption(XF86OptionPtr list, const char *name) 311 { 312 while (list) { 313 if (xf86nameCompare(list->opt_name, name) == 0) 314 return list; 315 list = list->list.next; 316 } 317 return NULL; 318 } 319 320 /* 321 * this function searches the given option list for the named option. If 322 * found and the option has a parameter, a pointer to the parameter is 323 * returned. If the option does not have a parameter an empty string is 324 * returned. If the option is not found, a NULL is returned. 325 */ 326 327 const char * 328 xf86findOptionValue(XF86OptionPtr list, const char *name) 329 { 330 XF86OptionPtr p = xf86findOption(list, name); 331 332 if (p) { 333 if (p->opt_val) 334 return p->opt_val; 335 else 336 return ""; 337 } 338 return NULL; 339 } 340 341 XF86OptionPtr 342 xf86optionListCreate(const char **options, int count, int used) 343 { 344 XF86OptionPtr p = NULL; 345 char *t1, *t2; 346 int i; 347 348 if (count == -1) { 349 for (count = 0; options[count]; count++); 350 } 351 if ((count % 2) != 0) { 352 fprintf(stderr, 353 "xf86optionListCreate: count must be an even number.\n"); 354 return NULL; 355 } 356 for (i = 0; i < count; i += 2) { 357 t1 = strdup(options[i]); 358 t2 = strdup(options[i + 1]); 359 p = addNewOption2(p, t1, t2, used); 360 } 361 362 return p; 363 } 364 365 /* the 2 given lists are merged. If an option with the same name is present in 366 * both, the option from the user list - specified in the second argument - 367 * is used. The end result is a single valid list of options. Duplicates 368 * are freed, and the original lists are no longer guaranteed to be complete. 369 */ 370 XF86OptionPtr 371 xf86optionListMerge(XF86OptionPtr head, XF86OptionPtr tail) 372 { 373 XF86OptionPtr a, b, ap = NULL, bp = NULL; 374 375 a = tail; 376 b = head; 377 while (tail && b) { 378 if (xf86nameCompare(a->opt_name, b->opt_name) == 0) { 379 if (b == head) 380 head = a; 381 else 382 bp->list.next = a; 383 if (a == tail) 384 tail = a->list.next; 385 else 386 ap->list.next = a->list.next; 387 a->list.next = b->list.next; 388 b->list.next = NULL; 389 xf86optionListFree(b); 390 b = a->list.next; 391 bp = a; 392 a = tail; 393 ap = NULL; 394 } 395 else { 396 ap = a; 397 if (!(a = a->list.next)) { 398 a = tail; 399 bp = b; 400 b = b->list.next; 401 ap = NULL; 402 } 403 } 404 } 405 406 if (head) { 407 for (a = head; a->list.next; a = a->list.next); 408 a->list.next = tail; 409 } 410 else 411 head = tail; 412 413 return head; 414 } 415 416 char * 417 xf86uLongToString(unsigned long i) 418 { 419 char *s; 420 421 if (asprintf(&s, "%lu", i) == -1) 422 return NULL; 423 return s; 424 } 425 426 XF86OptionPtr 427 xf86parseOption(XF86OptionPtr head) 428 { 429 XF86OptionPtr option, cnew, old; 430 char *name, *comment = NULL; 431 int token; 432 433 if ((token = xf86getSubToken(&comment)) != STRING) { 434 xf86parseError(BAD_OPTION_MSG); 435 free(comment); 436 return head; 437 } 438 439 name = xf86_lex_val.str; 440 if ((token = xf86getSubToken(&comment)) == STRING) { 441 option = xf86newOption(name, xf86_lex_val.str); 442 option->opt_comment = comment; 443 if ((token = xf86getToken(NULL)) == COMMENT) { 444 option->opt_comment = xf86addComment(option->opt_comment, xf86_lex_val.str); 445 free(xf86_lex_val.str); 446 xf86_lex_val.str = NULL; 447 } else { 448 xf86unGetToken(token); 449 } 450 } 451 else { 452 option = xf86newOption(name, NULL); 453 option->opt_comment = comment; 454 if (token == COMMENT) { 455 option->opt_comment = xf86addComment(option->opt_comment, xf86_lex_val.str); 456 free(xf86_lex_val.str); 457 xf86_lex_val.str = NULL; 458 } else { 459 xf86unGetToken(token); 460 } 461 } 462 463 old = NULL; 464 465 /* Don't allow duplicates */ 466 if (head != NULL && (old = xf86findOption(head, name)) != NULL) { 467 cnew = old; 468 free(option->opt_name); 469 TestFree(option->opt_val); 470 TestFree(option->opt_comment); 471 free(option); 472 } 473 else 474 cnew = option; 475 476 if (old == NULL) 477 return ((XF86OptionPtr) xf86addListItem((glp) head, (glp) cnew)); 478 479 return head; 480 } 481 482 void 483 xf86printOptionList(FILE * fp, XF86OptionPtr list, int tabs) 484 { 485 int i; 486 487 if (!list) 488 return; 489 while (list) { 490 for (i = 0; i < tabs; i++) 491 fputc('\t', fp); 492 if (list->opt_val) 493 fprintf(fp, "Option \"%s\" \"%s\"", list->opt_name, 494 list->opt_val); 495 else 496 fprintf(fp, "Option \"%s\"", list->opt_name); 497 if (list->opt_comment) 498 fprintf(fp, "%s", list->opt_comment); 499 else 500 fputc('\n', fp); 501 list = list->list.next; 502 } 503 } 504