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