EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  <20102011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  <20102011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: Re: Small patch for asynMask bitmask values
From: Angus Gratton <[email protected]>
To: Eric Norum <[email protected]>, Mark Rivers <[email protected]>
Cc: tech-talk <[email protected]>
Date: Fri, 20 Aug 2010 17:07:35 +1000
On Thu, 2010-08-19 at 21:03 -0700, Eric Norum wrote:
> Have a look at 'postfix()' and 'calcPerform()' in the appDevGuide.
> 

Perfect! Here's a new version of the patch, bit less trivial, that uses
postfix() and calcPerform(). Now you can use any CALC-compatible
expression for the mask, provided that it doesn't contain whitespace,
commas, or parentheses.

I normally try not to commit code on Friday afternoons, but this patch
is pretty simple so I think I'm safe. ;)

- Angus

Slightly O/T: Having now encountered various pieces of parser code in
EPICS, it seems to me that many places in the framework would benefit
from using a tokenizer/parser framework. It seems like a few standard
syntaxes could be applied to most of the parsing done around the place.
Of course I know that's quite a big job. I wish I had time to volunteer
to try and implement it, but I thought I'd mention it as a talking point
anyway because it's been bothering me. :).


Index: asyn/devEpics/asynEpicsUtils.c
===================================================================
--- asyn/devEpics/asynEpicsUtils.c	(revision 21)
+++ asyn/devEpics/asynEpicsUtils.c	(working copy)
@@ -26,6 +26,7 @@
 #include <shareLib.h>
 #include "asynEpicsUtils.h"
 #include <epicsExport.h>
+#include <postfix.h>
 
 static asynStatus parseLink(asynUser *pasynUser, DBLINK *plink, 
                    char **port, int *addr, char **userParam);
@@ -155,7 +156,42 @@
     }
     return(asynSuccess);
 }
-
+
+
+// Scan a value for a bitmask, which can be any CALC-compatible value
+// that does not contain whitespace, commas or parentheses
+epicsUInt32 scanMaskValue(char *start, char **end)
+{
+	// find the end of this expression
+	*end = start;
+	while(!isspace(**end) && **end != 0 && **end != ')' && **end != ',') (*end)++;	
+
+	// Make a temporary complete infix string from start to end
+	char endChar = **end;
+	**end = 0;
+
+	// Build the postfix expression
+	char pfix[INFIX_TO_POSTFIX_SIZE(strlen(start)+1)];
+	short error;
+	long res = postfix(start, pfix, &error);
+
+	**end = endChar; // fix the source string back up
+	if(res) {
+		errno = EINVAL;
+		return 0;
+	}
+	
+	double result;
+	res = calcPerform(NULL, &result, pfix);
+	if(res) {
+		errno = EINVAL;
+		return 0;
+	}
+
+	errno=0;
+	return (epicsUInt32) result;
+}
+
 static asynStatus parseLinkMask(asynUser *pasynUser, DBLINK *plink, 
                    char **port, int *addr, epicsUInt32 *mask,char **userParam)
 {
@@ -196,7 +232,7 @@
     pnext = skipWhite(pnext,1);
     if(*pnext==0 || *pnext==')') goto error;
     errno = 0;
-    *mask = strtoul(pnext,&endp,0);
+    *mask = scanMaskValue(pnext, &endp);
     if(errno) goto error;
     /*next is timeout*/
     pnext = endp;
Index: documentation/asynDriver.html
===================================================================
--- documentation/asynDriver.html	(revision 21)
+++ documentation/asynDriver.html	(working copy)
@@ -3933,7 +3933,11 @@
     interface asynUInt32Digital. The INP or OUT field must define asynMask. The mask
     specified in the argument to asynMask is used in the calls to asynUInt32Digital
     methods. In addition it is used to set the mask fields in bi and bo records and
-    the mask and shft fields in mbbi, mbbo, mbbiDirect, and mbboDirect records.</p>
+    the mask and shft fields in mbbi, mbbo, mbbiDirect, and mbboDirect records. Mask
+    values can be specified as decimal or hexadecimal integers, or simple mathematical
+    expressions like 1<<9, 1+2, or ~0x3. Acceptable mask expressions are any that 
+    would be accepted by the CALC record, provided they contain no whitespace, commas 
+    or parentheses.)</p>
   <ul>
     <li>biRecord
       <p>
@@ -3992,7 +3996,7 @@
     Binary Output Example Record</p>
   <pre>record(bo,"boUInt32Bit2") {
     field(DTYP,"asynUInt32Digital")
-    field(OUT,"@asynMask( $(port) , 0, 0x4 , 1.0) ")
+    field(OUT,"@asynMask( $(port) , 0, 1<<2 , 1.0) ")
     field(ZNAM,"zero")
     field(ONAM,"one")
 }</pre>

References:
Small patch for asynMask bitmask values Angus Gratton
Re: Small patch for asynMask bitmask values Eric Norum
Re: Small patch for asynMask bitmask values Angus Gratton
Re: Small patch for asynMask bitmask values Eric Norum

Navigate by Date:
Prev: Re: Asyn and I/O intr scanning Hinko Kocevar
Next: msi again Benjamin Franksen
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  <20102011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Prev: Re: Small patch for asynMask bitmask values Eric Norum
Next: msi again Benjamin Franksen
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  <20102011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
ANJ, 02 Sep 2010 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·