1 /*===========================================================================
2 *
3 * PUBLIC DOMAIN NOTICE
4 * National Center for Biotechnology Information
5 *
6 * This software/database is a "United States Government Work" under the
7 * terms of the United States Copyright Act. It was written as part of
8 * the author's official duties as a United States Government employee and
9 * thus cannot be copyrighted. This software/database is freely available
10 * to the public for use. The National Library of Medicine and the U.S.
11 * Government have not placed any restriction on its use or reproduction.
12 *
13 * Although all reasonable efforts have been taken to ensure the accuracy
14 * and reliability of the software and data, the NLM and the U.S.
15 * Government do not and cannot warrant the performance or results that
16 * may be obtained by using this software or data. The NLM and the U.S.
17 * Government disclaim all warranties, express or implied, including
18 * warranties of performance, merchantability or fitness for any particular
19 * purpose.
20 *
21 * Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26
27 %{
28 #include "kfg-parse.h"
29 #include <sysalloc.h>
30 #include <klib/rc.h>
31 #include <klib/namelist.h>
32
33 #define YYSTYPE_IS_DECLARED
34 #define YYSTYPE KFGSymbol
35 #include "config-tokens.h"
36
37 #define KFG_lex KFGScan_yylex
38
39 /* required parameter to VNamelistMake */
40 #define NAMELIST_ALLOC_BLKSIZE 10
41
42 static void ReportRc(KFGParseBlock* pb, KFGScanBlock* sb, rc_t rc);
43 static void AppendName(KFGScanBlock* sb, VNamelist*, const KFGToken*);
44 static void KFG_error(KFGParseBlock* pb, KFGScanBlock* sb, const char* msg);
45 %}
46
47 %pure-parser
48 %parse-param {KFGParseBlock* pb }
49 %lex-param {KFGToken* sb}
50 %parse-param {KFGScanBlock* sb }
51
52 %name-prefix="KFG_"
53
54 /* tokens without textual representation or internal for the scanner */
55 %token kfgEND_INPUT 0
56 %token kfgEND_LINE
57 %token kfgUNTERM_STRING
58 %token kfgUNTERM_ESCAPED_STRING
59 %token kfgUNRECOGNIZED
60 %token kfgVAR_REF
61 %token kfgUNTERM_VAR_REF
62 %token kfgASSIGN
63
64 /* tokens with a textual representation in pb */
65 %token <pb> kfgSTRING
66 %token <pb> kfgESCAPED_STRING
67 %token <pb> kfgABS_PATH
68 %token <pb> kfgREL_PATH
69
70 %union {
71 KFGToken pb;
72 const struct VNamelist* namelist;
73 }
74 %type <pb> pathname
75 %type <namelist> value
76
77 %destructor
78 {
79 VNamelistRelease($$);
80 } <namelist>
81
82 %%
83
84 config
85 : name_value_pairs
86 | kfgEND_INPUT
87 ;
88
89 name_value_pairs
90 : name_value_pair
91 | name_value_pairs name_value_pair
92 ;
93
94 name_value_pair
95 : pathname assign_op value line_end
96 {
97 rc_t rc=pb->write_nvp(sb->self, $1.tokenText, $1.tokenLength, $3);
98 if (rc != 0)
99 {
100 ReportRc(pb, sb, rc);
101 }
102 VNamelistRelease($3);
103 }
104 | kfgEND_LINE
105 | error line_end
106 ;
107
108 pathname
109 : kfgABS_PATH
110 | kfgREL_PATH
111 ;
112
113 assign_op
114 : kfgASSIGN
115 ;
116
117 value
118 : kfgSTRING { VNamelistMake(&$$, NAMELIST_ALLOC_BLKSIZE); AppendName(sb, $$, &$1); }
119 | kfgESCAPED_STRING { VNamelistMake(&$$, NAMELIST_ALLOC_BLKSIZE); AppendName(sb, $$, &$1); }
120 | value kfgSTRING { AppendName(sb, $1, &$2); $$=$1; }
121 | value kfgESCAPED_STRING { AppendName(sb, $1, &$2); $$=$1; }
122 ;
123
124 line_end
125 : kfgEND_LINE
126 | kfgEND_INPUT
127 ;
128
129 %%
130
131 #include <assert.h>
132 #include <klib/token.h>
133 #include <klib/writer.h>
134
135 void KFG_error(KFGParseBlock* pb, KFGScanBlock* sb, const char* msg)
136 {
137 sb->report_error(sb, msg);
138 }
139
ReportRc(KFGParseBlock * pb,KFGScanBlock * sb,rc_t rc)140 void ReportRc(KFGParseBlock* pb, KFGScanBlock* sb, rc_t rc)
141 {
142 char buf[1025];
143 size_t num_writ;
144 RCExplain(rc, buf, 1024, &num_writ);
145 buf[1024]=0;
146 yyerror(0, sb, buf);
147 }
148
AppendName(KFGScanBlock * sb,VNamelist * nl,const KFGToken * pb)149 void AppendName(KFGScanBlock* sb, VNamelist* nl, const KFGToken* pb)
150 { /* pb represents either a kfgSTRING or a kfgESCAPED_STRING with opening and closed quotes clipped */
151 rc_t rc;
152 KToken t;
153 size_t value_size;
154 char* buf;
155
156 if (pb->tokenLength == 0)
157 {
158 return;
159 }
160
161 t.id= pb->tokenId == kfgESCAPED_STRING ? eEscapedString : eString;
162 StringInit(&t.str, pb->tokenText-1, pb->tokenLength+2, (uint32_t) (pb->tokenLength + 2) ); /* compensate for clipped quotes in order to use KTokenToString */
163 buf=(char*)malloc(t.str.size);
164
165 /* KTokenToString removes opening and closing quotes and handles escapes if present */
166 rc = KTokenToString (&t, buf, t.str.size, &value_size);
167 if (rc != 0)
168 {
169 ReportRc(0, sb, rc);
170 }
171 else
172 {
173 assert(value_size < t.str.size);
174 buf[value_size]=0;
175 rc = VNamelistAppend(nl, buf);
176 if (rc != 0)
177 {
178 ReportRc(0, sb, rc);
179 }
180 }
181 free(buf);
182 }
183
184
185
186