ioc/dbStatic: Add JSON parsing of field values
The parsing removes all white-space outside of quotes from the JSON. dbRecordField() now strips quotes from simple string values itself.
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2009 UChicago Argonne LLC, as Operator of Argonne
|
||||
* Copyright (c) 2016 UChicago Argonne LLC, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
newline "\n"
|
||||
backslash "\\"
|
||||
doublequote "\""
|
||||
@@ -15,6 +16,18 @@ escape {backslash}.
|
||||
stringchar [^"\n\\]
|
||||
bareword [a-zA-Z0-9_\-+:.\[\]<>;]
|
||||
|
||||
punctuation [:,\[\]{}]
|
||||
normalchar [^"\\\0-\x1f]
|
||||
escapedchar ({backslash}["\\/bfnrt])
|
||||
hexdigit [0-9a-fA-F]
|
||||
unicodechar ({backslash}"u"{hexdigit}{4})
|
||||
jsonchar ({normalchar}|{escapedchar}|{unicodechar})
|
||||
jsondqstr ({doublequote}{jsonchar}*{doublequote})
|
||||
int ("-"?([0-9]|[1-9][0-9]+))
|
||||
frac ("."[0-9]+)
|
||||
exp ([eE][+-]?[0-9]+)
|
||||
number ({int}{frac}?{exp}?)
|
||||
|
||||
%{
|
||||
#undef YY_INPUT
|
||||
#define YY_INPUT(b,r,ms) (r=(*db_yyinput)((char *)b,ms))
|
||||
@@ -27,6 +40,8 @@ static int yyreset(void)
|
||||
|
||||
%}
|
||||
|
||||
%x JSON
|
||||
|
||||
%%
|
||||
|
||||
"include" return(tokenINCLUDE);
|
||||
@@ -49,18 +64,18 @@ static int yyreset(void)
|
||||
"variable" return(tokenVARIABLE);
|
||||
|
||||
{bareword}+ { /* unquoted string or number */
|
||||
yylval.Str = dbmfStrdup(yytext);
|
||||
yylval.Str = dbmfStrdup((char *) yytext);
|
||||
return(tokenSTRING);
|
||||
}
|
||||
|
||||
{doublequote}({stringchar}|{escape})*{doublequote} { /* quoted string */
|
||||
yylval.Str = dbmfStrdup(yytext+1);
|
||||
yylval.Str = dbmfStrdup((char *) yytext+1);
|
||||
yylval.Str[strlen(yylval.Str)-1] = '\0';
|
||||
return(tokenSTRING);
|
||||
}
|
||||
|
||||
%.* { /*C definition in recordtype*/
|
||||
yylval.Str = dbmfStrdup(yytext+1);
|
||||
yylval.Str = dbmfStrdup((char *) yytext+1);
|
||||
return(tokenCDEFS);
|
||||
}
|
||||
|
||||
@@ -71,13 +86,30 @@ static int yyreset(void)
|
||||
"," return(yytext[0]);
|
||||
|
||||
{comment}.* ;
|
||||
{whitespace} ;
|
||||
|
||||
{doublequote}({stringchar}|{escape})*{newline} { /* bad string */
|
||||
yyerrorAbort("Newline in string, closing quote missing");
|
||||
}
|
||||
|
||||
. {
|
||||
<JSON>"null" return jsonNULL;
|
||||
<JSON>"true" return jsonTRUE;
|
||||
<JSON>"false" return jsonFALSE;
|
||||
|
||||
<JSON>{punctuation} return yytext[0];
|
||||
|
||||
<JSON>{jsondqstr} {
|
||||
yylval.Str = dbmfStrdup((char *) yytext);
|
||||
return jsonSTRING;
|
||||
}
|
||||
|
||||
<JSON>{number} {
|
||||
yylval.Str = dbmfStrdup((char *) yytext);
|
||||
return jsonNUMBER;
|
||||
}
|
||||
|
||||
<INITIAL,JSON>{whitespace} ;
|
||||
|
||||
<INITIAL,JSON>. {
|
||||
char message[40];
|
||||
YY_BUFFER_STATE *dummy=0;
|
||||
|
||||
|
||||
@@ -1048,6 +1048,11 @@ static void dbRecordField(char *name,char *value)
|
||||
yyerror(NULL);
|
||||
return;
|
||||
}
|
||||
if (*value == '"') {
|
||||
/* jsonSTRING values still have their quotes */
|
||||
value++;
|
||||
value[strlen(value) - 1] = 0;
|
||||
}
|
||||
dbTranslateEscape(value, value); /* yuck: in-place, but safe */
|
||||
status = dbPutString(pdbentry,value);
|
||||
if(status) {
|
||||
|
||||
@@ -17,6 +17,11 @@ static int yyAbort = 0;
|
||||
|
||||
%start database
|
||||
|
||||
%union
|
||||
{
|
||||
char *Str;
|
||||
}
|
||||
|
||||
%token tokenINCLUDE tokenPATH tokenADDPATH
|
||||
%token tokenALIAS tokenMENU tokenCHOICE tokenRECORDTYPE
|
||||
%token tokenFIELD tokenINFO tokenREGISTRAR
|
||||
@@ -24,10 +29,10 @@ static int yyAbort = 0;
|
||||
%token tokenRECORD tokenGRECORD tokenVARIABLE tokenFUNCTION
|
||||
%token <Str> tokenSTRING tokenCDEFS
|
||||
|
||||
%union
|
||||
{
|
||||
char *Str;
|
||||
}
|
||||
%token jsonNULL jsonTRUE jsonFALSE
|
||||
%token <Str> jsonNUMBER jsonSTRING
|
||||
%type <Str> json_value json_object json_array
|
||||
%type <Str> json_members json_pair json_elements
|
||||
|
||||
%%
|
||||
|
||||
@@ -247,10 +252,11 @@ record_body: /* empty */
|
||||
record_field_list: record_field_list record_field
|
||||
| record_field;
|
||||
|
||||
record_field: tokenFIELD '(' tokenSTRING ',' tokenSTRING ')'
|
||||
record_field: tokenFIELD '(' tokenSTRING ','
|
||||
{ BEGIN JSON; } json_value { BEGIN INITIAL; } ')'
|
||||
{
|
||||
if(dbStaticDebug>2) printf("record_field %s %s\n",$3,$5);
|
||||
dbRecordField($3,$5); dbmfFree($3); dbmfFree($5);
|
||||
if(dbStaticDebug>2) printf("record_field %s %s\n",$3,$6);
|
||||
dbRecordField($3,$6); dbmfFree($3); dbmfFree($6);
|
||||
}
|
||||
| tokenINFO '(' tokenSTRING ',' tokenSTRING ')'
|
||||
{
|
||||
@@ -270,6 +276,61 @@ alias: tokenALIAS '(' tokenSTRING ',' tokenSTRING ')'
|
||||
dbAlias($3,$5); dbmfFree($3); dbmfFree($5);
|
||||
};
|
||||
|
||||
json_object: '{' '}'
|
||||
{
|
||||
$$ = "{}";
|
||||
if (dbStaticDebug>2) printf("json %s\n", $$);
|
||||
}
|
||||
| '{' json_members '}'
|
||||
{
|
||||
$$ = dbmfStrcat3("{", $2, "}");
|
||||
dbmfFree($2);
|
||||
if (dbStaticDebug>2) printf("json %s\n", $$);
|
||||
};
|
||||
|
||||
json_members: json_pair
|
||||
| json_pair ',' json_members
|
||||
{
|
||||
$$ = dbmfStrcat3($1, ",", $3);
|
||||
dbmfFree($1); dbmfFree($3);
|
||||
if (dbStaticDebug>2) printf("json %s\n", $$);
|
||||
};
|
||||
|
||||
json_pair: jsonSTRING ':' json_value
|
||||
{
|
||||
$$ = dbmfStrcat3($1, ":", $3);
|
||||
dbmfFree($1); dbmfFree($3);
|
||||
if (dbStaticDebug>2) printf("json %s\n", $$);
|
||||
};
|
||||
|
||||
json_array: '[' ']'
|
||||
{
|
||||
$$ = "[]";
|
||||
if (dbStaticDebug>2) printf("json %s\n", $$);
|
||||
}
|
||||
| '[' json_elements ']'
|
||||
{
|
||||
$$ = dbmfStrcat3("[", $2, "]");
|
||||
dbmfFree($2);
|
||||
if (dbStaticDebug>2) printf("json %s\n", $$);
|
||||
};
|
||||
|
||||
json_elements: json_value
|
||||
| json_value ',' json_elements
|
||||
{
|
||||
$$ = dbmfStrcat3($1, ",", $3);
|
||||
dbmfFree($1); dbmfFree($3);
|
||||
if (dbStaticDebug>2) printf("json %s\n", $$);
|
||||
};
|
||||
|
||||
json_value: jsonNULL { $$ = "null"; }
|
||||
| jsonTRUE { $$ = "true"; }
|
||||
| jsonFALSE { $$ = "false"; }
|
||||
| jsonNUMBER
|
||||
| jsonSTRING
|
||||
| json_array
|
||||
| json_object ;
|
||||
|
||||
|
||||
%%
|
||||
|
||||
|
||||
Reference in New Issue
Block a user