[PATCH v3] xfree86: Add option parsing for percent options.

Peter Hutterer peter.hutterer at who-t.net
Mon May 17 18:12:49 PDT 2010


In some cases, an option of "50%" would be preferable over fixed value
configuration - especially if the actual values are autoprobed.
Add a new set of functions to parse percent values from configurations.

The percent value parsing differs slightly - if the option is not to marked
as used (e.g. xf86CheckPercentOption()), no warning is emitted to the log
file if the value is not a percent value. This allows double-options (either
as % or as absolute number) without warnings.

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---

Changes to v2:
- xwin pieces added (untested). John, Yaakov, can you please give this a
  quick test?
- optionTypeToString missing bits added
- DESIGN.sgml updated to list the new option

 hw/xfree86/common/xf86Configure.c |    5 +++-
 hw/xfree86/common/xf86Opt.h       |    4 +++
 hw/xfree86/common/xf86Option.c    |   47 +++++++++++++++++++++++++++++++++++++
 hw/xfree86/common/xf86ShowOpts.c  |    2 +
 hw/xfree86/doc/sgml/DESIGN.sgml   |    6 ++++
 hw/xwin/winconfig.c               |   37 +++++++++++++++++++++++++++++
 hw/xwin/winconfig.h               |    2 +
 7 files changed, 102 insertions(+), 1 deletions(-)

diff --git a/hw/xfree86/common/xf86Configure.c b/hw/xfree86/common/xf86Configure.c
index 67bf08b..1573cc6 100644
--- a/hw/xfree86/common/xf86Configure.c
+++ b/hw/xfree86/common/xf86Configure.c
@@ -339,6 +339,8 @@ optionTypeToSting(OptionValueType type)
         return "[<bool>]";
     case OPTV_FREQ:
         return "<freq>";
+    case OPTV_PERCENT:
+        return "<percent>";
     default:
         return "";
     }
@@ -384,7 +386,8 @@ configureDeviceSection (int screennum)
 	    "        ### Available Driver options are:-\n"
 	    "        ### Values: <i>: integer, <f>: float, "
 			"<bool>: \"True\"/\"False\",\n"
-	    "        ### <string>: \"String\", <freq>: \"<f> Hz/kHz/MHz\"\n"
+	    "        ### <string>: \"String\", <freq>: \"<f> Hz/kHz/MHz\",\n"
+	    "        ### <percent>: \"<f>%\"\n"
 	    "        ### [arg]: arg optional\n";
 	ptr->dev_comment = xstrdup(descrip);
 	if (ptr->dev_comment) {
diff --git a/hw/xfree86/common/xf86Opt.h b/hw/xfree86/common/xf86Opt.h
index ce3d767..d75d3bf 100644
--- a/hw/xfree86/common/xf86Opt.h
+++ b/hw/xfree86/common/xf86Opt.h
@@ -51,6 +51,7 @@ typedef enum {
     OPTV_ANYSTR,                /* Any string, including an empty one */
     OPTV_REAL,
     OPTV_BOOLEAN,
+    OPTV_PERCENT,
     OPTV_FREQ
 } OptionValueType;
 
@@ -72,10 +73,12 @@ extern _X_EXPORT int xf86SetIntOption(pointer optlist, const char *name, int def
 extern _X_EXPORT double xf86SetRealOption(pointer optlist, const char *name, double deflt);
 extern _X_EXPORT char *xf86SetStrOption(pointer optlist, const char *name, char *deflt);
 extern _X_EXPORT int xf86SetBoolOption(pointer list, const char *name, int deflt );
+extern _X_EXPORT double xf86SetPercentOption(pointer list, const char *name, double deflt );
 extern _X_EXPORT int xf86CheckIntOption(pointer optlist, const char *name, int deflt);
 extern _X_EXPORT double xf86CheckRealOption(pointer optlist, const char *name, double deflt);
 extern _X_EXPORT char *xf86CheckStrOption(pointer optlist, const char *name, char *deflt);
 extern _X_EXPORT int xf86CheckBoolOption(pointer list, const char *name, int deflt );
+extern _X_EXPORT double xf86CheckPercentOption(pointer list, const char *name, double deflt );
 extern _X_EXPORT pointer xf86AddNewOption(pointer head, const char *name, const char *val );
 extern _X_EXPORT pointer xf86NewOption(char *name, char *value );
 extern _X_EXPORT pointer xf86NextOption(pointer list );
@@ -109,5 +112,6 @@ extern _X_EXPORT char *xf86NormalizeName(const char *s);
 extern _X_EXPORT pointer xf86ReplaceIntOption(pointer optlist,  const char *name, const int val);
 extern _X_EXPORT pointer xf86ReplaceRealOption(pointer optlist,  const char *name, const double val);
 extern _X_EXPORT pointer xf86ReplaceBoolOption(pointer optlist, const char *name, const Bool val);
+extern _X_EXPORT pointer xf86ReplacePercentOption(pointer optlist, const char *name, const double val);
 extern _X_EXPORT pointer xf86ReplaceStrOption(pointer optlist,  const char *name, const char* val);
 #endif
diff --git a/hw/xfree86/common/xf86Option.c b/hw/xfree86/common/xf86Option.c
index a2868bf..7971837 100644
--- a/hw/xfree86/common/xf86Option.c
+++ b/hw/xfree86/common/xf86Option.c
@@ -223,6 +223,18 @@ LookupBoolOption(pointer optlist, const char *name, int deflt, Bool markUsed)
     return deflt;
 }
 
+static int
+LookupPercentOption(pointer optlist, const char *name, double deflt, Bool markUsed)
+{
+    OptionInfoRec o;
+
+    o.name = name;
+    o.type = OPTV_PERCENT;
+    if (ParseOptionValue(-1, optlist, &o, markUsed))
+	deflt = o.value.realnum;
+    return deflt;
+}
+
 /* These xf86Set* functions are intended for use by non-screen specific code */
 
 int
@@ -252,6 +264,12 @@ xf86SetBoolOption(pointer optlist, const char *name, int deflt)
     return LookupBoolOption(optlist, name, deflt, TRUE);
 }
 
+double
+xf86SetPercentOption(pointer optlist, const char *name, double deflt)
+{
+    return LookupPercentOption(optlist, name, deflt, TRUE);
+}
+
 /*
  * These are like the Set*Option functions, but they don't mark the options
  * as used.
@@ -283,6 +301,12 @@ xf86CheckBoolOption(pointer optlist, const char *name, int deflt)
     return LookupBoolOption(optlist, name, deflt, FALSE);
 }
 
+
+double
+xf86CheckPercentOption(pointer optlist, const char *name, double deflt)
+{
+    return LookupPercentOption(optlist, name, deflt, FALSE);
+}
 /*
  * addNewOption() has the required property of replacing the option value
  * if the option is already present.
@@ -310,6 +334,14 @@ xf86ReplaceBoolOption(pointer optlist, const char *name, const Bool val)
 }
 
 pointer
+xf86ReplacePercentOption(pointer optlist, const char *name, const double val)
+{
+    char tmp[16];
+    sprintf(tmp, "%lf%%", val);
+    return xf86AddNewOption(optlist,name,tmp);
+}
+
+pointer
 xf86ReplaceStrOption(pointer optlist, const char *name, const char* val)
 {
       return xf86AddNewOption(optlist,name,val);
@@ -533,6 +565,21 @@ ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p,
 		p->found = FALSE;
 	    }
 	    break;
+	case OPTV_PERCENT:
+	    {
+		char tmp = 0;
+		/* awkward match, but %% doesn't increase the match counter,
+		 * hence 100 looks the same as 100% to the caller of sccanf
+		 */
+		if (sscanf(s, "%lf%c", &p->value.realnum, &tmp) != 2 || tmp != '%') {
+		    xf86DrvMsg(scrnIndex, X_WARNING,
+			       "Option \"%s\" requires a percent value\n", p->name);
+		    p->found = FALSE;
+		} else {
+		    p->found = TRUE;
+		}
+	    }
+	    break;
 	case OPTV_FREQ:	
 	    if (*s == '\0') {
 		xf86DrvMsg(scrnIndex, X_WARNING,
diff --git a/hw/xfree86/common/xf86ShowOpts.c b/hw/xfree86/common/xf86ShowOpts.c
index 04a9a8b..bd9b3d7 100644
--- a/hw/xfree86/common/xf86ShowOpts.c
+++ b/hw/xfree86/common/xf86ShowOpts.c
@@ -70,6 +70,8 @@ optionTypeToSting(OptionValueType type)
         return "<bool>";
     case OPTV_FREQ:
         return "<freq>";
+    case OPTV_PERCENT:
+        return "<percent>";
     default:
         return "<undef>";
     }
diff --git a/hw/xfree86/doc/sgml/DESIGN.sgml b/hw/xfree86/doc/sgml/DESIGN.sgml
index e95df79..8999e0c 100644
--- a/hw/xfree86/doc/sgml/DESIGN.sgml
+++ b/hw/xfree86/doc/sgml/DESIGN.sgml
@@ -2528,6 +2528,7 @@ Next, the higher level functions that most drivers would use.
           OPTV_ANYSTR,  /* Any string, including an empty one */
           OPTV_REAL,
           OPTV_BOOLEAN,
+          OPTV_PERCENT,
           OPTV_FREQ
       } OptionValueType;
 
@@ -2555,6 +2556,11 @@ Next, the higher level functions that most drivers would use.
       &s.code;freq.units&e.code; is set to &s.code;0&e.code;, and
       &s.code;freq.freq&e.code; is unscaled.
 
+      &s.code;OPTV_PERCENT&e.code; can be used for option values that are
+      specified in percent (e.g. "20%"). These values are a floating point
+      number with a percent sign appended. If the percent sign is missing,
+      the parser will fail to match the value.
+
       Typical usage is to setup an array of
       &s.code;OptionInfoRecs&e.code; with all fields initialised.
       The &s.code;value&e.code; and &s.code;found&e.code; fields get
diff --git a/hw/xwin/winconfig.c b/hw/xwin/winconfig.c
index b05867b..61be087 100644
--- a/hw/xwin/winconfig.c
+++ b/hw/xwin/winconfig.c
@@ -673,6 +673,18 @@ winSetRealOption (pointer optlist, const char *name, double deflt)
     deflt = o.value.realnum;
   return deflt;
 }
+
+double
+winSetPercentOption (pointer optlist, const char *name, double deflt)
+{
+  OptionInfoRec o;
+
+  o.name = name;
+  o.type = OPTV_PERCENT;
+  if (ParseOptionValue (-1, optlist, &o))
+    deflt = o.value.realnum;
+  return deflt;
+}
 #endif
 
 
@@ -851,6 +863,31 @@ ParseOptionValue (int scrnIndex, pointer options, OptionInfoPtr p)
 	      p->found = FALSE;
 	    }
 	  break;
+	case OPTV_PERCENT:
+	  if (*s == '\0')
+	    {
+	      winDrvMsg (scrnIndex, X_WARNING,
+			 "Option \"%s\" requires a percent value\n",
+			 p->name);
+	      p->found = FALSE;
+	    }
+	  else
+	    {
+	       double percent = strtod (s, &end);
+
+	       if (end != s && winNameCompare (end, "%"))
+		 {
+		   p->found = TRUE;
+		   p->value.realnum = percent;
+		 }
+	       else
+		 {
+		   winDrvMsg (scrnIndex, X_WARNING,
+			      "Option \"%s\" requires a frequency value\n",
+			       p->name);
+		   p->found = FALSE;
+		 }
+	    }
 	case OPTV_FREQ:
 	  if (*s == '\0')
 	    {
diff --git a/hw/xwin/winconfig.h b/hw/xwin/winconfig.h
index 058884a..4699ca8 100644
--- a/hw/xwin/winconfig.h
+++ b/hw/xwin/winconfig.h
@@ -256,6 +256,7 @@ typedef enum
   OPTV_ANYSTR,			/* Any string, including an empty one */
   OPTV_REAL,
   OPTV_BOOLEAN,
+  OPTV_PERCENT,
   OPTV_FREQ
 }
 OptionValueType;
@@ -289,6 +290,7 @@ char *winSetStrOption (pointer optlist, const char *name, char *deflt);
 int winSetBoolOption (pointer optlist, const char *name, int deflt);
 int winSetIntOption (pointer optlist, const char *name, int deflt);
 double winSetRealOption (pointer optlist, const char *name, double deflt);
+double winSetPercentOption (pointer optlist, const char *name, double deflt);
 #ifdef XWIN_XF86CONFIG
 XF86OptionPtr winFindOption (XF86OptionPtr list, const char *name);
 char *winFindOptionValue (XF86OptionPtr list, const char *name);
-- 
1.7.0.1



More information about the xorg-devel mailing list