1706f2543Smrg/* 2706f2543Smrg * Copyright (c) 1998-2003 by The XFree86 Project, Inc. 3706f2543Smrg * 4706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5706f2543Smrg * copy of this software and associated documentation files (the "Software"), 6706f2543Smrg * to deal in the Software without restriction, including without limitation 7706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the 9706f2543Smrg * Software is furnished to do so, subject to the following conditions: 10706f2543Smrg * 11706f2543Smrg * The above copyright notice and this permission notice shall be included in 12706f2543Smrg * all copies or substantial portions of the Software. 13706f2543Smrg * 14706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17706f2543Smrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18706f2543Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19706f2543Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20706f2543Smrg * OTHER DEALINGS IN THE SOFTWARE. 21706f2543Smrg * 22706f2543Smrg * Except as contained in this notice, the name of the copyright holder(s) 23706f2543Smrg * and author(s) shall not be used in advertising or otherwise to promote 24706f2543Smrg * the sale, use or other dealings in this Software without prior written 25706f2543Smrg * authorization from the copyright holder(s) and author(s). 26706f2543Smrg */ 27706f2543Smrg 28706f2543Smrg/* 29706f2543Smrg * Author: David Dawes <dawes@xfree86.org> 30706f2543Smrg * 31706f2543Smrg * This file includes public option handling functions. 32706f2543Smrg */ 33706f2543Smrg 34706f2543Smrg#ifdef HAVE_XORG_CONFIG_H 35706f2543Smrg#include <xorg-config.h> 36706f2543Smrg#endif 37706f2543Smrg 38706f2543Smrg#include <stdlib.h> 39706f2543Smrg#include <ctype.h> 40706f2543Smrg#include <X11/X.h> 41706f2543Smrg#include "os.h" 42706f2543Smrg#include "xf86.h" 43706f2543Smrg#include "xf86Xinput.h" 44706f2543Smrg#include "xf86Optrec.h" 45706f2543Smrg#include "xf86Parser.h" 46706f2543Smrg 47706f2543Smrgstatic Bool ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p, 48706f2543Smrg Bool markUsed); 49706f2543Smrg 50706f2543Smrg/* 51706f2543Smrg * xf86CollectOptions collects the options from each of the config file 52706f2543Smrg * sections used by the screen and puts the combined list in pScrn->options. 53706f2543Smrg * This function requires that the following have been initialised: 54706f2543Smrg * 55706f2543Smrg * pScrn->confScreen 56706f2543Smrg * pScrn->Entities[i]->device 57706f2543Smrg * pScrn->display 58706f2543Smrg * pScrn->monitor 59706f2543Smrg * 60706f2543Smrg * The extraOpts parameter may optionally contain a list of additional options 61706f2543Smrg * to include. 62706f2543Smrg * 63706f2543Smrg * The order of precedence for options is: 64706f2543Smrg * 65706f2543Smrg * extraOpts, display, confScreen, monitor, device 66706f2543Smrg */ 67706f2543Smrg 68706f2543Smrgvoid 69706f2543Smrgxf86CollectOptions(ScrnInfoPtr pScrn, pointer extraOpts) 70706f2543Smrg{ 71706f2543Smrg XF86OptionPtr tmp; 72706f2543Smrg XF86OptionPtr extras = (XF86OptionPtr)extraOpts; 73706f2543Smrg GDevPtr device; 74706f2543Smrg 75706f2543Smrg int i; 76706f2543Smrg 77706f2543Smrg pScrn->options = NULL; 78706f2543Smrg 79706f2543Smrg for (i=pScrn->numEntities - 1; i >= 0; i--) { 80706f2543Smrg device = xf86GetDevFromEntity(pScrn->entityList[i], 81706f2543Smrg pScrn->entityInstanceList[i]); 82706f2543Smrg if (device && device->options) { 83706f2543Smrg tmp = xf86optionListDup(device->options); 84706f2543Smrg if (pScrn->options) 85706f2543Smrg xf86optionListMerge(pScrn->options,tmp); 86706f2543Smrg else 87706f2543Smrg pScrn->options = tmp; 88706f2543Smrg } 89706f2543Smrg } 90706f2543Smrg if (pScrn->monitor->options) { 91706f2543Smrg tmp = xf86optionListDup(pScrn->monitor->options); 92706f2543Smrg if (pScrn->options) 93706f2543Smrg pScrn->options = xf86optionListMerge(pScrn->options, tmp); 94706f2543Smrg else 95706f2543Smrg pScrn->options = tmp; 96706f2543Smrg } 97706f2543Smrg if (pScrn->confScreen->options) { 98706f2543Smrg tmp = xf86optionListDup(pScrn->confScreen->options); 99706f2543Smrg if (pScrn->options) 100706f2543Smrg pScrn->options = xf86optionListMerge(pScrn->options, tmp); 101706f2543Smrg else 102706f2543Smrg pScrn->options = tmp; 103706f2543Smrg } 104706f2543Smrg if (pScrn->display->options) { 105706f2543Smrg tmp = xf86optionListDup(pScrn->display->options); 106706f2543Smrg if (pScrn->options) 107706f2543Smrg pScrn->options = xf86optionListMerge(pScrn->options, tmp); 108706f2543Smrg else 109706f2543Smrg pScrn->options = tmp; 110706f2543Smrg } 111706f2543Smrg if (extras) { 112706f2543Smrg tmp = xf86optionListDup(extras); 113706f2543Smrg if (pScrn->options) 114706f2543Smrg pScrn->options = xf86optionListMerge(pScrn->options, tmp); 115706f2543Smrg else 116706f2543Smrg pScrn->options = tmp; 117706f2543Smrg } 118706f2543Smrg} 119706f2543Smrg 120706f2543Smrg/* 121706f2543Smrg * xf86CollectInputOptions collects extra options for an InputDevice (other 122706f2543Smrg * than those added by the config backend). 123706f2543Smrg * The options are merged into the existing ones and thus take precedence 124706f2543Smrg * over the others. 125706f2543Smrg */ 126706f2543Smrg 127706f2543Smrgvoid 128706f2543Smrgxf86CollectInputOptions(InputInfoPtr pInfo, const char **defaultOpts) 129706f2543Smrg{ 130706f2543Smrg if (defaultOpts) { 131706f2543Smrg XF86OptionPtr tmp =xf86optionListCreate(defaultOpts, -1, 0); 132706f2543Smrg if (pInfo->options) 133706f2543Smrg pInfo->options = xf86optionListMerge(tmp, pInfo->options); 134706f2543Smrg else 135706f2543Smrg pInfo->options = tmp; 136706f2543Smrg } 137706f2543Smrg} 138706f2543Smrg 139706f2543Smrg/** 140706f2543Smrg * Duplicate the option list passed in. The returned pointer will be a newly 141706f2543Smrg * allocated option list and must be freed by the caller. 142706f2543Smrg */ 143706f2543Smrgpointer 144706f2543Smrgxf86OptionListDuplicate(pointer options) 145706f2543Smrg{ 146706f2543Smrg pointer o = NULL; 147706f2543Smrg 148706f2543Smrg while (options) 149706f2543Smrg { 150706f2543Smrg o = xf86AddNewOption(o, xf86OptionName(options), xf86OptionValue(options)); 151706f2543Smrg options = xf86nextOption(options); 152706f2543Smrg } 153706f2543Smrg 154706f2543Smrg return o; 155706f2543Smrg} 156706f2543Smrg 157706f2543Smrg 158706f2543Smrg/* Created for new XInput stuff -- essentially extensions to the parser */ 159706f2543Smrg 160706f2543Smrgstatic int 161706f2543SmrgLookupIntOption(pointer optlist, const char *name, int deflt, Bool markUsed) 162706f2543Smrg{ 163706f2543Smrg OptionInfoRec o; 164706f2543Smrg 165706f2543Smrg o.name = name; 166706f2543Smrg o.type = OPTV_INTEGER; 167706f2543Smrg if (ParseOptionValue(-1, optlist, &o, markUsed)) 168706f2543Smrg deflt = o.value.num; 169706f2543Smrg return deflt; 170706f2543Smrg} 171706f2543Smrg 172706f2543Smrg 173706f2543Smrgstatic double 174706f2543SmrgLookupRealOption(pointer optlist, const char *name, double deflt, 175706f2543Smrg Bool markUsed) 176706f2543Smrg{ 177706f2543Smrg OptionInfoRec o; 178706f2543Smrg 179706f2543Smrg o.name = name; 180706f2543Smrg o.type = OPTV_REAL; 181706f2543Smrg if (ParseOptionValue(-1, optlist, &o, markUsed)) 182706f2543Smrg deflt = o.value.realnum; 183706f2543Smrg return deflt; 184706f2543Smrg} 185706f2543Smrg 186706f2543Smrg 187706f2543Smrgstatic char * 188706f2543SmrgLookupStrOption(pointer optlist, const char *name, char *deflt, Bool markUsed) 189706f2543Smrg{ 190706f2543Smrg OptionInfoRec o; 191706f2543Smrg 192706f2543Smrg o.name = name; 193706f2543Smrg o.type = OPTV_STRING; 194706f2543Smrg if (ParseOptionValue(-1, optlist, &o, markUsed)) 195706f2543Smrg deflt = o.value.str; 196706f2543Smrg if (deflt) 197706f2543Smrg return strdup(deflt); 198706f2543Smrg else 199706f2543Smrg return NULL; 200706f2543Smrg} 201706f2543Smrg 202706f2543Smrg 203706f2543Smrgstatic int 204706f2543SmrgLookupBoolOption(pointer optlist, const char *name, int deflt, Bool markUsed) 205706f2543Smrg{ 206706f2543Smrg OptionInfoRec o; 207706f2543Smrg 208706f2543Smrg o.name = name; 209706f2543Smrg o.type = OPTV_BOOLEAN; 210706f2543Smrg if (ParseOptionValue(-1, optlist, &o, markUsed)) 211706f2543Smrg deflt = o.value.bool; 212706f2543Smrg return deflt; 213706f2543Smrg} 214706f2543Smrg 215706f2543Smrgstatic double 216706f2543SmrgLookupPercentOption(pointer optlist, const char *name, double deflt, Bool markUsed) 217706f2543Smrg{ 218706f2543Smrg OptionInfoRec o; 219706f2543Smrg 220706f2543Smrg o.name = name; 221706f2543Smrg o.type = OPTV_PERCENT; 222706f2543Smrg if (ParseOptionValue(-1, optlist, &o, markUsed)) 223706f2543Smrg deflt = o.value.realnum; 224706f2543Smrg return deflt; 225706f2543Smrg} 226706f2543Smrg 227706f2543Smrg/* These xf86Set* functions are intended for use by non-screen specific code */ 228706f2543Smrg 229706f2543Smrgint 230706f2543Smrgxf86SetIntOption(pointer optlist, const char *name, int deflt) 231706f2543Smrg{ 232706f2543Smrg return LookupIntOption(optlist, name, deflt, TRUE); 233706f2543Smrg} 234706f2543Smrg 235706f2543Smrg 236706f2543Smrgdouble 237706f2543Smrgxf86SetRealOption(pointer optlist, const char *name, double deflt) 238706f2543Smrg{ 239706f2543Smrg return LookupRealOption(optlist, name, deflt, TRUE); 240706f2543Smrg} 241706f2543Smrg 242706f2543Smrg 243706f2543Smrgchar * 244706f2543Smrgxf86SetStrOption(pointer optlist, const char *name, char *deflt) 245706f2543Smrg{ 246706f2543Smrg return LookupStrOption(optlist, name, deflt, TRUE); 247706f2543Smrg} 248706f2543Smrg 249706f2543Smrg 250706f2543Smrgint 251706f2543Smrgxf86SetBoolOption(pointer optlist, const char *name, int deflt) 252706f2543Smrg{ 253706f2543Smrg return LookupBoolOption(optlist, name, deflt, TRUE); 254706f2543Smrg} 255706f2543Smrg 256706f2543Smrgdouble 257706f2543Smrgxf86SetPercentOption(pointer optlist, const char *name, double deflt) 258706f2543Smrg{ 259706f2543Smrg return LookupPercentOption(optlist, name, deflt, TRUE); 260706f2543Smrg} 261706f2543Smrg 262706f2543Smrg/* 263706f2543Smrg * These are like the Set*Option functions, but they don't mark the options 264706f2543Smrg * as used. 265706f2543Smrg */ 266706f2543Smrgint 267706f2543Smrgxf86CheckIntOption(pointer optlist, const char *name, int deflt) 268706f2543Smrg{ 269706f2543Smrg return LookupIntOption(optlist, name, deflt, FALSE); 270706f2543Smrg} 271706f2543Smrg 272706f2543Smrg 273706f2543Smrgdouble 274706f2543Smrgxf86CheckRealOption(pointer optlist, const char *name, double deflt) 275706f2543Smrg{ 276706f2543Smrg return LookupRealOption(optlist, name, deflt, FALSE); 277706f2543Smrg} 278706f2543Smrg 279706f2543Smrg 280706f2543Smrgchar * 281706f2543Smrgxf86CheckStrOption(pointer optlist, const char *name, char *deflt) 282706f2543Smrg{ 283706f2543Smrg return LookupStrOption(optlist, name, deflt, FALSE); 284706f2543Smrg} 285706f2543Smrg 286706f2543Smrg 287706f2543Smrgint 288706f2543Smrgxf86CheckBoolOption(pointer optlist, const char *name, int deflt) 289706f2543Smrg{ 290706f2543Smrg return LookupBoolOption(optlist, name, deflt, FALSE); 291706f2543Smrg} 292706f2543Smrg 293706f2543Smrg 294706f2543Smrgdouble 295706f2543Smrgxf86CheckPercentOption(pointer optlist, const char *name, double deflt) 296706f2543Smrg{ 297706f2543Smrg return LookupPercentOption(optlist, name, deflt, FALSE); 298706f2543Smrg} 299706f2543Smrg/* 300706f2543Smrg * addNewOption() has the required property of replacing the option value 301706f2543Smrg * if the option is already present. 302706f2543Smrg */ 303706f2543Smrgpointer 304706f2543Smrgxf86ReplaceIntOption(pointer optlist, const char *name, const int val) 305706f2543Smrg{ 306706f2543Smrg char tmp[16]; 307706f2543Smrg sprintf(tmp,"%i",val); 308706f2543Smrg return xf86AddNewOption(optlist,name,tmp); 309706f2543Smrg} 310706f2543Smrg 311706f2543Smrgpointer 312706f2543Smrgxf86ReplaceRealOption(pointer optlist, const char *name, const double val) 313706f2543Smrg{ 314706f2543Smrg char tmp[32]; 315706f2543Smrg snprintf(tmp,32,"%f",val); 316706f2543Smrg return xf86AddNewOption(optlist,name,tmp); 317706f2543Smrg} 318706f2543Smrg 319706f2543Smrgpointer 320706f2543Smrgxf86ReplaceBoolOption(pointer optlist, const char *name, const Bool val) 321706f2543Smrg{ 322706f2543Smrg return xf86AddNewOption(optlist,name,val?"True":"False"); 323706f2543Smrg} 324706f2543Smrg 325706f2543Smrgpointer 326706f2543Smrgxf86ReplacePercentOption(pointer optlist, const char *name, const double val) 327706f2543Smrg{ 328706f2543Smrg char tmp[16]; 329706f2543Smrg sprintf(tmp, "%lf%%", val); 330706f2543Smrg return xf86AddNewOption(optlist,name,tmp); 331706f2543Smrg} 332706f2543Smrg 333706f2543Smrgpointer 334706f2543Smrgxf86ReplaceStrOption(pointer optlist, const char *name, const char* val) 335706f2543Smrg{ 336706f2543Smrg return xf86AddNewOption(optlist,name,val); 337706f2543Smrg} 338706f2543Smrg 339706f2543Smrgpointer 340706f2543Smrgxf86AddNewOption(pointer head, const char *name, const char *val) 341706f2543Smrg{ 342706f2543Smrg /* XXX These should actually be allocated in the parser library. */ 343706f2543Smrg char *tmp = val ? strdup(val) : NULL; 344706f2543Smrg char *tmp_name = strdup(name); 345706f2543Smrg 346706f2543Smrg return xf86addNewOption(head, tmp_name, tmp); 347706f2543Smrg} 348706f2543Smrg 349706f2543Smrg 350706f2543Smrgpointer 351706f2543Smrgxf86NewOption(char *name, char *value) 352706f2543Smrg{ 353706f2543Smrg return xf86newOption(name, value); 354706f2543Smrg} 355706f2543Smrg 356706f2543Smrg 357706f2543Smrgpointer 358706f2543Smrgxf86NextOption(pointer list) 359706f2543Smrg{ 360706f2543Smrg return xf86nextOption(list); 361706f2543Smrg} 362706f2543Smrg 363706f2543Smrgpointer 364706f2543Smrgxf86OptionListCreate(const char **options, int count, int used) 365706f2543Smrg{ 366706f2543Smrg return xf86optionListCreate(options, count, used); 367706f2543Smrg} 368706f2543Smrg 369706f2543Smrgpointer 370706f2543Smrgxf86OptionListMerge(pointer head, pointer tail) 371706f2543Smrg{ 372706f2543Smrg return xf86optionListMerge(head, tail); 373706f2543Smrg} 374706f2543Smrg 375706f2543Smrgvoid 376706f2543Smrgxf86OptionListFree(pointer opt) 377706f2543Smrg{ 378706f2543Smrg xf86optionListFree(opt); 379706f2543Smrg} 380706f2543Smrg 381706f2543Smrgchar * 382706f2543Smrgxf86OptionName(pointer opt) 383706f2543Smrg{ 384706f2543Smrg return xf86optionName(opt); 385706f2543Smrg} 386706f2543Smrg 387706f2543Smrgchar * 388706f2543Smrgxf86OptionValue(pointer opt) 389706f2543Smrg{ 390706f2543Smrg return xf86optionValue(opt); 391706f2543Smrg} 392706f2543Smrg 393706f2543Smrgvoid 394706f2543Smrgxf86OptionListReport(pointer parm) 395706f2543Smrg{ 396706f2543Smrg XF86OptionPtr opts = parm; 397706f2543Smrg 398706f2543Smrg while(opts) { 399706f2543Smrg if (xf86optionValue(opts)) 400706f2543Smrg xf86ErrorFVerb(5, "\tOption \"%s\" \"%s\"\n", 401706f2543Smrg xf86optionName(opts), xf86optionValue(opts)); 402706f2543Smrg else 403706f2543Smrg xf86ErrorFVerb( 5, "\tOption \"%s\"\n", xf86optionName(opts)); 404706f2543Smrg opts = xf86nextOption(opts); 405706f2543Smrg } 406706f2543Smrg} 407706f2543Smrg 408706f2543Smrg/* End of XInput-caused section */ 409706f2543Smrg 410706f2543Smrgpointer 411706f2543Smrgxf86FindOption(pointer options, const char *name) 412706f2543Smrg{ 413706f2543Smrg return xf86findOption(options, name); 414706f2543Smrg} 415706f2543Smrg 416706f2543Smrg 417706f2543Smrgchar * 418706f2543Smrgxf86FindOptionValue(pointer options, const char *name) 419706f2543Smrg{ 420706f2543Smrg return xf86findOptionValue(options, name); 421706f2543Smrg} 422706f2543Smrg 423706f2543Smrg 424706f2543Smrgvoid 425706f2543Smrgxf86MarkOptionUsed(pointer option) 426706f2543Smrg{ 427706f2543Smrg if (option != NULL) 428706f2543Smrg ((XF86OptionPtr)option)->opt_used = TRUE; 429706f2543Smrg} 430706f2543Smrg 431706f2543Smrg 432706f2543Smrgvoid 433706f2543Smrgxf86MarkOptionUsedByName(pointer options, const char *name) 434706f2543Smrg{ 435706f2543Smrg XF86OptionPtr opt; 436706f2543Smrg 437706f2543Smrg opt = xf86findOption(options, name); 438706f2543Smrg if (opt != NULL) 439706f2543Smrg opt->opt_used = TRUE; 440706f2543Smrg} 441706f2543Smrg 442706f2543SmrgBool 443706f2543Smrgxf86CheckIfOptionUsed(pointer option) 444706f2543Smrg{ 445706f2543Smrg if (option != NULL) 446706f2543Smrg return ((XF86OptionPtr)option)->opt_used; 447706f2543Smrg else 448706f2543Smrg return FALSE; 449706f2543Smrg} 450706f2543Smrg 451706f2543SmrgBool 452706f2543Smrgxf86CheckIfOptionUsedByName(pointer options, const char *name) 453706f2543Smrg{ 454706f2543Smrg XF86OptionPtr opt; 455706f2543Smrg 456706f2543Smrg opt = xf86findOption(options, name); 457706f2543Smrg if (opt != NULL) 458706f2543Smrg return opt->opt_used; 459706f2543Smrg else 460706f2543Smrg return FALSE; 461706f2543Smrg} 462706f2543Smrg 463706f2543Smrgvoid 464706f2543Smrgxf86ShowUnusedOptions(int scrnIndex, pointer options) 465706f2543Smrg{ 466706f2543Smrg XF86OptionPtr opt = options; 467706f2543Smrg 468706f2543Smrg while (opt) { 469706f2543Smrg if (opt->opt_name && !opt->opt_used) { 470706f2543Smrg xf86DrvMsg(scrnIndex, X_WARNING, "Option \"%s\" is not used\n", 471706f2543Smrg opt->opt_name); 472706f2543Smrg } 473706f2543Smrg opt = opt->list.next; 474706f2543Smrg } 475706f2543Smrg} 476706f2543Smrg 477706f2543Smrg 478706f2543Smrgstatic Bool 479706f2543SmrgGetBoolValue(OptionInfoPtr p, const char *s) 480706f2543Smrg{ 481706f2543Smrg return xf86getBoolValue(&p->value.bool, s); 482706f2543Smrg} 483706f2543Smrg 484706f2543Smrgstatic Bool 485706f2543SmrgParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p, 486706f2543Smrg Bool markUsed) 487706f2543Smrg{ 488706f2543Smrg char *s, *end; 489706f2543Smrg Bool wasUsed = FALSE; 490706f2543Smrg 491706f2543Smrg if ((s = xf86findOptionValue(options, p->name)) != NULL) { 492706f2543Smrg if (markUsed) { 493706f2543Smrg wasUsed = xf86CheckIfOptionUsedByName(options, p->name); 494706f2543Smrg xf86MarkOptionUsedByName(options, p->name); 495706f2543Smrg } 496706f2543Smrg switch (p->type) { 497706f2543Smrg case OPTV_INTEGER: 498706f2543Smrg if (*s == '\0') { 499706f2543Smrg if (markUsed) { 500706f2543Smrg xf86DrvMsg(scrnIndex, X_WARNING, 501706f2543Smrg "Option \"%s\" requires an integer value\n", 502706f2543Smrg p->name); 503706f2543Smrg } 504706f2543Smrg p->found = FALSE; 505706f2543Smrg } else { 506706f2543Smrg p->value.num = strtoul(s, &end, 0); 507706f2543Smrg if (*end == '\0') { 508706f2543Smrg p->found = TRUE; 509706f2543Smrg } else { 510706f2543Smrg if (markUsed) { 511706f2543Smrg xf86DrvMsg(scrnIndex, X_WARNING, 512706f2543Smrg "Option \"%s\" requires an integer value\n", 513706f2543Smrg p->name); 514706f2543Smrg } 515706f2543Smrg p->found = FALSE; 516706f2543Smrg } 517706f2543Smrg } 518706f2543Smrg break; 519706f2543Smrg case OPTV_STRING: 520706f2543Smrg if (*s == '\0') { 521706f2543Smrg if (markUsed) { 522706f2543Smrg xf86DrvMsg(scrnIndex, X_WARNING, 523706f2543Smrg "Option \"%s\" requires an string value\n", 524706f2543Smrg p->name); 525706f2543Smrg } 526706f2543Smrg p->found = FALSE; 527706f2543Smrg } else { 528706f2543Smrg p->value.str = s; 529706f2543Smrg p->found = TRUE; 530706f2543Smrg } 531706f2543Smrg break; 532706f2543Smrg case OPTV_ANYSTR: 533706f2543Smrg p->value.str = s; 534706f2543Smrg p->found = TRUE; 535706f2543Smrg break; 536706f2543Smrg case OPTV_REAL: 537706f2543Smrg if (*s == '\0') { 538706f2543Smrg if (markUsed) { 539706f2543Smrg xf86DrvMsg(scrnIndex, X_WARNING, 540706f2543Smrg "Option \"%s\" requires a floating point " 541706f2543Smrg "value\n", p->name); 542706f2543Smrg } 543706f2543Smrg p->found = FALSE; 544706f2543Smrg } else { 545706f2543Smrg p->value.realnum = strtod(s, &end); 546706f2543Smrg if (*end == '\0') { 547706f2543Smrg p->found = TRUE; 548706f2543Smrg } else { 549706f2543Smrg if (markUsed) { 550706f2543Smrg xf86DrvMsg(scrnIndex, X_WARNING, 551706f2543Smrg "Option \"%s\" requires a floating point " 552706f2543Smrg "value\n", p->name); 553706f2543Smrg } 554706f2543Smrg p->found = FALSE; 555706f2543Smrg } 556706f2543Smrg } 557706f2543Smrg break; 558706f2543Smrg case OPTV_BOOLEAN: 559706f2543Smrg if (GetBoolValue(p, s)) { 560706f2543Smrg p->found = TRUE; 561706f2543Smrg } else { 562706f2543Smrg if (markUsed) { 563706f2543Smrg xf86DrvMsg(scrnIndex, X_WARNING, 564706f2543Smrg "Option \"%s\" requires a boolean value\n", 565706f2543Smrg p->name); 566706f2543Smrg } 567706f2543Smrg p->found = FALSE; 568706f2543Smrg } 569706f2543Smrg break; 570706f2543Smrg case OPTV_PERCENT: 571706f2543Smrg { 572706f2543Smrg char tmp = 0; 573706f2543Smrg /* awkward match, but %% doesn't increase the match counter, 574706f2543Smrg * hence 100 looks the same as 100% to the caller of sccanf 575706f2543Smrg */ 576706f2543Smrg if (sscanf(s, "%lf%c", &p->value.realnum, &tmp) != 2 || tmp != '%') { 577706f2543Smrg if (markUsed) { 578706f2543Smrg xf86DrvMsg(scrnIndex, X_WARNING, 579706f2543Smrg "Option \"%s\" requires a percent value\n", p->name); 580706f2543Smrg } 581706f2543Smrg p->found = FALSE; 582706f2543Smrg } else { 583706f2543Smrg p->found = TRUE; 584706f2543Smrg } 585706f2543Smrg } 586706f2543Smrg break; 587706f2543Smrg case OPTV_FREQ: 588706f2543Smrg if (*s == '\0') { 589706f2543Smrg if (markUsed) { 590706f2543Smrg xf86DrvMsg(scrnIndex, X_WARNING, 591706f2543Smrg "Option \"%s\" requires a frequency value\n", 592706f2543Smrg p->name); 593706f2543Smrg } 594706f2543Smrg p->found = FALSE; 595706f2543Smrg } else { 596706f2543Smrg double freq = strtod(s, &end); 597706f2543Smrg int units = 0; 598706f2543Smrg 599706f2543Smrg if (end != s) { 600706f2543Smrg p->found = TRUE; 601706f2543Smrg if (!xf86NameCmp(end, "Hz")) 602706f2543Smrg units = 1; 603706f2543Smrg else if (!xf86NameCmp(end, "kHz") || 604706f2543Smrg !xf86NameCmp(end, "k")) 605706f2543Smrg units = 1000; 606706f2543Smrg else if (!xf86NameCmp(end, "MHz") || 607706f2543Smrg !xf86NameCmp(end, "M")) 608706f2543Smrg units = 1000000; 609706f2543Smrg else { 610706f2543Smrg if (markUsed) { 611706f2543Smrg xf86DrvMsg(scrnIndex, X_WARNING, 612706f2543Smrg "Option \"%s\" requires a frequency value\n", 613706f2543Smrg p->name); 614706f2543Smrg } 615706f2543Smrg p->found = FALSE; 616706f2543Smrg } 617706f2543Smrg if (p->found) 618706f2543Smrg freq *= (double)units; 619706f2543Smrg } else { 620706f2543Smrg if (markUsed) { 621706f2543Smrg xf86DrvMsg(scrnIndex, X_WARNING, 622706f2543Smrg "Option \"%s\" requires a frequency value\n", 623706f2543Smrg p->name); 624706f2543Smrg } 625706f2543Smrg p->found = FALSE; 626706f2543Smrg } 627706f2543Smrg if (p->found) { 628706f2543Smrg p->value.freq.freq = freq; 629706f2543Smrg p->value.freq.units = units; 630706f2543Smrg } 631706f2543Smrg } 632706f2543Smrg break; 633706f2543Smrg case OPTV_NONE: 634706f2543Smrg /* Should never get here */ 635706f2543Smrg p->found = FALSE; 636706f2543Smrg break; 637706f2543Smrg } 638706f2543Smrg if (p->found && markUsed) { 639706f2543Smrg int verb = 2; 640706f2543Smrg if (wasUsed) 641706f2543Smrg verb = 4; 642706f2543Smrg xf86DrvMsgVerb(scrnIndex, X_CONFIG, verb, "Option \"%s\"", p->name); 643706f2543Smrg if (!(p->type == OPTV_BOOLEAN && *s == 0)) { 644706f2543Smrg xf86ErrorFVerb(verb, " \"%s\"", s); 645706f2543Smrg } 646706f2543Smrg xf86ErrorFVerb(verb, "\n"); 647706f2543Smrg } 648706f2543Smrg } else if (p->type == OPTV_BOOLEAN) { 649706f2543Smrg /* Look for matches with options with or without a "No" prefix. */ 650706f2543Smrg char *n, *newn; 651706f2543Smrg OptionInfoRec opt; 652706f2543Smrg 653706f2543Smrg n = xf86NormalizeName(p->name); 654706f2543Smrg if (!n) { 655706f2543Smrg p->found = FALSE; 656706f2543Smrg return FALSE; 657706f2543Smrg } 658706f2543Smrg if (strncmp(n, "no", 2) == 0) { 659706f2543Smrg newn = n + 2; 660706f2543Smrg } else { 661706f2543Smrg free(n); 662706f2543Smrg if (asprintf(&n, "No%s", p->name) == -1) { 663706f2543Smrg p->found = FALSE; 664706f2543Smrg return FALSE; 665706f2543Smrg } 666706f2543Smrg newn = n; 667706f2543Smrg } 668706f2543Smrg if ((s = xf86findOptionValue(options, newn)) != NULL) { 669706f2543Smrg if (markUsed) 670706f2543Smrg xf86MarkOptionUsedByName(options, newn); 671706f2543Smrg if (GetBoolValue(&opt, s)) { 672706f2543Smrg p->value.bool = !opt.value.bool; 673706f2543Smrg p->found = TRUE; 674706f2543Smrg } else { 675706f2543Smrg xf86DrvMsg(scrnIndex, X_WARNING, 676706f2543Smrg "Option \"%s\" requires a boolean value\n", newn); 677706f2543Smrg p->found = FALSE; 678706f2543Smrg } 679706f2543Smrg } else { 680706f2543Smrg p->found = FALSE; 681706f2543Smrg } 682706f2543Smrg if (p->found && markUsed) { 683706f2543Smrg xf86DrvMsgVerb(scrnIndex, X_CONFIG, 2, "Option \"%s\"", newn); 684706f2543Smrg if (*s != 0) { 685706f2543Smrg xf86ErrorFVerb(2, " \"%s\"", s); 686706f2543Smrg } 687706f2543Smrg xf86ErrorFVerb(2, "\n"); 688706f2543Smrg } 689706f2543Smrg free(n); 690706f2543Smrg } else { 691706f2543Smrg p->found = FALSE; 692706f2543Smrg } 693706f2543Smrg return p->found; 694706f2543Smrg} 695706f2543Smrg 696706f2543Smrg 697706f2543Smrgvoid 698706f2543Smrgxf86ProcessOptions(int scrnIndex, pointer options, OptionInfoPtr optinfo) 699706f2543Smrg{ 700706f2543Smrg OptionInfoPtr p; 701706f2543Smrg 702706f2543Smrg for (p = optinfo; p->name != NULL; p++) { 703706f2543Smrg ParseOptionValue(scrnIndex, options, p, TRUE); 704706f2543Smrg } 705706f2543Smrg} 706706f2543Smrg 707706f2543Smrg 708706f2543SmrgOptionInfoPtr 709706f2543Smrgxf86TokenToOptinfo(const OptionInfoRec *table, int token) 710706f2543Smrg{ 711706f2543Smrg const OptionInfoRec *p, *match = NULL, *set = NULL; 712706f2543Smrg 713706f2543Smrg if (!table) { 714706f2543Smrg ErrorF("xf86TokenToOptinfo: table is NULL\n"); 715706f2543Smrg return NULL; 716706f2543Smrg } 717706f2543Smrg 718706f2543Smrg for (p = table; p->token >= 0; p++) { 719706f2543Smrg if (p->token == token) { 720706f2543Smrg match = p; 721706f2543Smrg if (p->found) 722706f2543Smrg set = p; 723706f2543Smrg } 724706f2543Smrg } 725706f2543Smrg 726706f2543Smrg if (set) 727706f2543Smrg return (OptionInfoPtr)set; 728706f2543Smrg else if (match) 729706f2543Smrg return (OptionInfoPtr)match; 730706f2543Smrg else 731706f2543Smrg return NULL; 732706f2543Smrg} 733706f2543Smrg 734706f2543Smrg 735706f2543Smrgconst char * 736706f2543Smrgxf86TokenToOptName(const OptionInfoRec *table, int token) 737706f2543Smrg{ 738706f2543Smrg const OptionInfoRec *p; 739706f2543Smrg 740706f2543Smrg p = xf86TokenToOptinfo(table, token); 741706f2543Smrg return p->name; 742706f2543Smrg} 743706f2543Smrg 744706f2543Smrg 745706f2543SmrgBool 746706f2543Smrgxf86IsOptionSet(const OptionInfoRec *table, int token) 747706f2543Smrg{ 748706f2543Smrg OptionInfoPtr p; 749706f2543Smrg 750706f2543Smrg p = xf86TokenToOptinfo(table, token); 751706f2543Smrg return p && p->found; 752706f2543Smrg} 753706f2543Smrg 754706f2543Smrg 755706f2543Smrgchar * 756706f2543Smrgxf86GetOptValString(const OptionInfoRec *table, int token) 757706f2543Smrg{ 758706f2543Smrg OptionInfoPtr p; 759706f2543Smrg 760706f2543Smrg p = xf86TokenToOptinfo(table, token); 761706f2543Smrg if (p && p->found) 762706f2543Smrg return p->value.str; 763706f2543Smrg else 764706f2543Smrg return NULL; 765706f2543Smrg} 766706f2543Smrg 767706f2543Smrg 768706f2543SmrgBool 769706f2543Smrgxf86GetOptValInteger(const OptionInfoRec *table, int token, int *value) 770706f2543Smrg{ 771706f2543Smrg OptionInfoPtr p; 772706f2543Smrg 773706f2543Smrg p = xf86TokenToOptinfo(table, token); 774706f2543Smrg if (p && p->found) { 775706f2543Smrg *value = p->value.num; 776706f2543Smrg return TRUE; 777706f2543Smrg } else 778706f2543Smrg return FALSE; 779706f2543Smrg} 780706f2543Smrg 781706f2543Smrg 782706f2543SmrgBool 783706f2543Smrgxf86GetOptValULong(const OptionInfoRec *table, int token, unsigned long *value) 784706f2543Smrg{ 785706f2543Smrg OptionInfoPtr p; 786706f2543Smrg 787706f2543Smrg p = xf86TokenToOptinfo(table, token); 788706f2543Smrg if (p && p->found) { 789706f2543Smrg *value = p->value.num; 790706f2543Smrg return TRUE; 791706f2543Smrg } else 792706f2543Smrg return FALSE; 793706f2543Smrg} 794706f2543Smrg 795706f2543Smrg 796706f2543SmrgBool 797706f2543Smrgxf86GetOptValReal(const OptionInfoRec *table, int token, double *value) 798706f2543Smrg{ 799706f2543Smrg OptionInfoPtr p; 800706f2543Smrg 801706f2543Smrg p = xf86TokenToOptinfo(table, token); 802706f2543Smrg if (p && p->found) { 803706f2543Smrg *value = p->value.realnum; 804706f2543Smrg return TRUE; 805706f2543Smrg } else 806706f2543Smrg return FALSE; 807706f2543Smrg} 808706f2543Smrg 809706f2543Smrg 810706f2543SmrgBool 811706f2543Smrgxf86GetOptValFreq(const OptionInfoRec *table, int token, 812706f2543Smrg OptFreqUnits expectedUnits, double *value) 813706f2543Smrg{ 814706f2543Smrg OptionInfoPtr p; 815706f2543Smrg 816706f2543Smrg p = xf86TokenToOptinfo(table, token); 817706f2543Smrg if (p && p->found) { 818706f2543Smrg if (p->value.freq.units > 0) { 819706f2543Smrg /* Units give, so the scaling is known. */ 820706f2543Smrg switch (expectedUnits) { 821706f2543Smrg case OPTUNITS_HZ: 822706f2543Smrg *value = p->value.freq.freq; 823706f2543Smrg break; 824706f2543Smrg case OPTUNITS_KHZ: 825706f2543Smrg *value = p->value.freq.freq / 1000.0; 826706f2543Smrg break; 827706f2543Smrg case OPTUNITS_MHZ: 828706f2543Smrg *value = p->value.freq.freq / 1000000.0; 829706f2543Smrg break; 830706f2543Smrg } 831706f2543Smrg } else { 832706f2543Smrg /* No units given, so try to guess the scaling. */ 833706f2543Smrg switch (expectedUnits) { 834706f2543Smrg case OPTUNITS_HZ: 835706f2543Smrg *value = p->value.freq.freq; 836706f2543Smrg break; 837706f2543Smrg case OPTUNITS_KHZ: 838706f2543Smrg if (p->value.freq.freq > 1000.0) 839706f2543Smrg *value = p->value.freq.freq / 1000.0; 840706f2543Smrg else 841706f2543Smrg *value = p->value.freq.freq; 842706f2543Smrg break; 843706f2543Smrg case OPTUNITS_MHZ: 844706f2543Smrg if (p->value.freq.freq > 1000000.0) 845706f2543Smrg *value = p->value.freq.freq / 1000000.0; 846706f2543Smrg else if (p->value.freq.freq > 1000.0) 847706f2543Smrg *value = p->value.freq.freq / 1000.0; 848706f2543Smrg else 849706f2543Smrg *value = p->value.freq.freq; 850706f2543Smrg } 851706f2543Smrg } 852706f2543Smrg return TRUE; 853706f2543Smrg } else 854706f2543Smrg return FALSE; 855706f2543Smrg} 856706f2543Smrg 857706f2543Smrg 858706f2543SmrgBool 859706f2543Smrgxf86GetOptValBool(const OptionInfoRec *table, int token, Bool *value) 860706f2543Smrg{ 861706f2543Smrg OptionInfoPtr p; 862706f2543Smrg 863706f2543Smrg p = xf86TokenToOptinfo(table, token); 864706f2543Smrg if (p && p->found) { 865706f2543Smrg *value = p->value.bool; 866706f2543Smrg return TRUE; 867706f2543Smrg } else 868706f2543Smrg return FALSE; 869706f2543Smrg} 870706f2543Smrg 871706f2543Smrg 872706f2543SmrgBool 873706f2543Smrgxf86ReturnOptValBool(const OptionInfoRec *table, int token, Bool def) 874706f2543Smrg{ 875706f2543Smrg OptionInfoPtr p; 876706f2543Smrg 877706f2543Smrg p = xf86TokenToOptinfo(table, token); 878706f2543Smrg if (p && p->found) { 879706f2543Smrg return p->value.bool; 880706f2543Smrg } else 881706f2543Smrg return def; 882706f2543Smrg} 883706f2543Smrg 884706f2543Smrg 885706f2543Smrgint 886706f2543Smrgxf86NameCmp(const char *s1, const char *s2) 887706f2543Smrg{ 888706f2543Smrg return xf86nameCompare(s1, s2); 889706f2543Smrg} 890706f2543Smrg 891706f2543Smrgchar * 892706f2543Smrgxf86NormalizeName(const char *s) 893706f2543Smrg{ 894706f2543Smrg char *ret, *q; 895706f2543Smrg const char *p; 896706f2543Smrg 897706f2543Smrg if (s == NULL) 898706f2543Smrg return NULL; 899706f2543Smrg 900706f2543Smrg ret = malloc(strlen(s) + 1); 901706f2543Smrg for (p = s, q = ret; *p != 0; p++) { 902706f2543Smrg switch (*p) { 903706f2543Smrg case '_': 904706f2543Smrg case ' ': 905706f2543Smrg case '\t': 906706f2543Smrg continue; 907706f2543Smrg default: 908706f2543Smrg if (isupper(*p)) 909706f2543Smrg *q++ = tolower(*p); 910706f2543Smrg else 911706f2543Smrg *q++ = *p; 912706f2543Smrg } 913706f2543Smrg } 914706f2543Smrg *q = '\0'; 915706f2543Smrg return ret; 916706f2543Smrg} 917