1/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
2   See the COPYRIGHT file for more information. */
3
4#include "config.h"
5#ifdef HAVE_STRINGS_H
6#include <strings.h>
7#endif
8#include "dapparselex.h"
9#include "dapy.h"
10
11#undef URLCVT /* NEVER turn this on */
12
13#define DAP2ENCODE
14#ifdef DAP2ENCODE
15#define KEEPSLASH
16#endif
17
18/* Forward */
19static void dumptoken(DAPlexstatelexstate);
20static void dapaddyytext(DAPlexstatelex, int c);
21#ifndef DAP2ENCODE
22static int tohex(int c);
23#endif
24
25/****************************************************/
26
27#ifdef INFORMATIONAL
28/* Set of all ascii printable characters */
29static char ascii[] = " !\"#$%&'()*+,-./:;<=>?@[]\\^_`|{}~";
30
31/* Define the set of legal nonalphanum characters as specified in the DAP2 spec. */
32static char* daplegal ="_!~*'-\"";
33#endif
34
35static char* ddsworddelims =
36  "{}[]:;=,";
37
38/* Define 1 and > 1st legal characters */
39static char* ddswordchars1 =
40  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-+_/%\\.*";
41static char* ddswordcharsn =
42  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-+_/%\\.*#";
43static char* daswordcharsn =
44  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-+_/%\\.*#:";
45static char* cewordchars1 =
46  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-+_/%\\";
47static char* cewordcharsn =
48  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-+_/%\\";
49
50/* Current sets of legal characters */
51/*
52static char* wordchars1 = NULL;
53static char* wordcharsn = NULL;
54static char* worddelims = NULL;
55*/
56
57static char* keywords[] = {
58"alias",
59"array",
60"attributes",
61"byte",
62"dataset",
63"error",
64"float32",
65"float64",
66"grid",
67"int16",
68"int32",
69"maps",
70"sequence",
71"string",
72"structure",
73"uint16",
74"uint32",
75"url",
76"code",
77"message",
78"program_type",
79"program",
80NULL /* mark end of the keywords list */
81};
82
83static int keytokens[] = {
84SCAN_ALIAS,
85SCAN_ARRAY,
86SCAN_ATTR,
87SCAN_BYTE,
88SCAN_DATASET,
89SCAN_ERROR,
90SCAN_FLOAT32,
91SCAN_FLOAT64,
92SCAN_GRID,
93SCAN_INT16,
94SCAN_INT32,
95SCAN_MAPS,
96SCAN_SEQUENCE,
97SCAN_STRING,
98SCAN_STRUCTURE,
99SCAN_UINT16,
100SCAN_UINT32,
101SCAN_URL,
102SCAN_CODE,
103SCAN_MESSAGE,
104SCAN_PTYPE,
105SCAN_PROG
106};
107
108/**************************************************/
109
110int
111daplex(YYSTYPElvalpDAPparsestatestate)
112{
113    DAPlexstatelexstate = state->lexstate;
114    int token;
115    int c;
116    unsigned int i;
117    char* p;
118    char* tmp;
119    YYSTYPE lval = NULL;
120
121    token = 0;
122    ocbytesclear(lexstate->yytext);
123    /* invariant: p always points to current char */
124    for(p=lexstate->next;token==0&&(c=*p);p++) {
125 if(c == '\n') {
126     lexstate->lineno++;
127 } else if(c <= ' ' || c == '\177') {
128     /* whitespace: ignore */
129 } else if(c == '#') {
130     /* single line comment */
131     while((c=*(++p))) {if(c == '\n') break;}
132 } else if(strchr(lexstate->worddelims,c) != NULL) {
133     /* don't put in lexstate->yytext to avoid memory leak */
134     token = c;
135 } else if(c == '"') {
136     int more = 1;
137     /* We have a string token; will be reported as WORD_STRING */
138     while(more && (c=*(++p))) {
139         if(c == '"') {
140     more = 0;
141     continue;
142 }
143#ifdef DAP2ENCODE
144 if(c == '\\') {
145     /* Resolve spec ambiguity about handling of \c:
146 1. !KEEPSLASH: convert \c to c for any character c
147 2. KEEPSLASH: convert \c to \c for any character c;
148    that is, keep the backslash.
149 It is clear that the problem being addressed was \".
150 But it is unclear what to to do about \n: convert to
151                        Ascii LF or leave as \n.
152                        This code will leave as \n and assume higher levels
153                        of code will address the issue.
154     */
155#ifdef KEEPSLASH
156     dapaddyytext(lexstate,c);
157#endif
158     c=*(++p);
159     if(c == '\0') more = 0;
160 }
161#else /*Non-standard*/
162 switch (c) {
163 case '\\':
164     c=*(++p);
165     switch (c) {
166     case 'r': c = '\r'; break;
167     case 'n': c = '\n'; break;
168     case 'f': c = '\f'; break;
169     case 't': c = '\t'; break;
170     case 'x': {
171 int d1,d2;
172 c = '?';
173 ++p;
174         d1 = tohex(*p++);
175 if(d1 < 0) {
176     daperror(state,"Illegal \\xDD in TOKEN_STRING");
177 } else {
178     d2 = tohex(*p++);
179     if(d2 < 0) {
180         daperror(state,"Illegal \\xDD in TOKEN_STRING");
181     } else {
182 c=(((unsigned int)d1)<<4) | (unsigned int)d2;
183     }
184 }
185     } break;
186     default: break;
187     }
188     break;
189 default: break;
190 }
191#endif /*!DAP2ENCODE*/
192 if(moredapaddyytext(lexstate,c);
193     }
194     token=WORD_STRING;
195 } else if(strchr(lexstate->wordchars1,c) != NULL) {
196     int isdatamark = 0;
197     /* we have a WORD_WORD */
198     dapaddyytext(lexstate,c);
199     while((c=*(++p))) {
200#ifdef URLCVT
201 if(c == '%' && p[1] != 0 && p[2] != 0
202     && strchr(hexdigits,p[1]) != NULL
203                            && strchr(hexdigits,p[2]) != NULL) {
204     int d1,d2;
205     d1 = tohex(p[1]);
206     d2 = tohex(p[2]);
207     if(d1 >= 0 || d2 >= 0) {
208 c=(((unsigned int)d1)<<4) | (unsigned int)d2;
209 p+=2;
210     }
211 } else {
212     if(strchr(lexstate->wordcharsn,c) == NULL) {p--; break;}
213 }
214 dapaddyytext(lexstate,c);
215#else
216 if(strchr(lexstate->wordcharsn,c) == NULL) {p--; break;}
217 dapaddyytext(lexstate,c);
218#endif
219     }
220     /* Special check for Data: */
221     tmp = ocbytescontents(lexstate->yytext);
222     if(strcmp(tmp,"Data")==0 && *p == ':') {
223 dapaddyytext(lexstate,*p); p++;
224 if(p[0] == '\n') {
225     token = SCAN_DATA;
226     isdatamark = 1;
227     p++;
228         } else if(p[0] == '\r' && p[1] == '\n') {
229     token = SCAN_DATA;
230     isdatamark = 1;
231     p+=2;
232 }
233     }
234     if(!isdatamark) {
235         /* check for keyword */
236         token=WORD_WORD; /* assume */
237         for(i=0;;i++) {
238     if(keywords[i] == NULL) break;
239     if(strcasecmp(keywords[i],tmp)==0) {
240         token=keytokens[i];
241         break;
242     }
243 }
244     }
245 } else { /* illegal */
246 }
247    }
248    lexstate->next = p;
249    strncpy(lexstate->lasttokentext,ocbytescontents(lexstate->yytext),MAX_TOKEN_LENGTH);
250    lexstate->lasttoken = token;
251    if(ocdebug >= 2)
252 dumptoken(lexstate);
253
254    /*Put return value onto Bison stack*/
255
256    if(ocbyteslength(lexstate->yytext) == 0)
257        lval = NULL;
258    else {
259        lval = ocbytesdup(lexstate->yytext);
260 oclistpush(lexstate->reclaim,(void*)lval);
261    }
262    if(lvalp) *lvalp = lval;
263    return token;      /* Return the type of the token.  */
264}
265
266static void
267dapaddyytext(DAPlexstatelex, int c)
268{
269    ocbytesappend(lex->yytext,c);
270}
271
272#ifndef DAP2ENCODE
273static int
274tohex(int c)
275{
276    if(c >= 'a' && c <= 'f') return (c - 'a') + 0xa;
277    if(c >= 'A' && c <= 'F') return (c - 'A') + 0xa;
278    if(c >= '0' && c <= '9') return (c - '0');
279    return -1;
280}
281#endif
282
283static void
284dumptoken(DAPlexstatelexstate)
285{
286    fprintf(stderr,"TOKEN = |%s|\n",ocbytescontents(lexstate->yytext));
287}
288
289/*
290Simple lexer
291*/
292
293void
294dapsetwordchars(DAPlexstatelexstate, int kind)
295{
296    switch (kind) {
297    case 0:
298 lexstate->worddelims = ddsworddelims;
299 lexstate->wordchars1 = ddswordchars1;
300 lexstate->wordcharsn = ddswordcharsn;
301 break;
302    case 1:
303 lexstate->worddelims = ddsworddelims;
304 lexstate->wordchars1 = ddswordchars1;
305 lexstate->wordcharsn = daswordcharsn;
306 break;
307    case 2:
308 lexstate->worddelims = ddsworddelims;
309 lexstate->wordchars1 = cewordchars1;
310 lexstate->wordcharsn = cewordcharsn;
311 break;
312    default: break;
313    }
314}
315
316void
317daplexinit(char* inputDAPlexstate** lexstatep)
318{
319    DAPlexstatelexstate;
320    if(lexstatep == NULL) return; /* no point in building it */
321    lexstate = (DAPlexstate*)malloc(sizeof(DAPlexstate));
322    *lexstatep = lexstate;
323    if(lexstate == NULL) return;
324    memset((void*)lexstate,0,sizeof(DAPlexstate));
325    lexstate->input = strdup(input);
326    lexstate->next = lexstate->input;
327    lexstate->yytext = ocbytesnew();
328    lexstate->reclaim = oclistnew();
329    dapsetwordchars(lexstate,0); /* Assume DDS */
330}
331
332void
333daplexcleanup(DAPlexstate** lexstatep)
334{
335    DAPlexstatelexstate = *lexstatep;
336    if(lexstate == NULL) return;
337    if(lexstate->input != NULLocfree(lexstate->input);
338    if(lexstate->reclaim != NULL) {
339 while(oclistlength(lexstate->reclaim) > 0) {
340     char* word = (char*)oclistpop(lexstate->reclaim);
341     if(word) free(word);
342 }
343 oclistfree(lexstate->reclaim);
344    }
345    ocbytesfree(lexstate->yytext);
346    free(lexstate);
347    *lexstatep = NULL;
348}
349
350/* Dap identifiers will come to us with some
351   characters escaped using the URL notation of
352   %HH. The assumption here is that any character
353   that is encoded is left encoded, except as follows:
354   1. if the encoded character is in fact a legal DAP2 character
355      (alphanum+"_!~*'-\"") then it is decoded, otherwise not.
356*/
357#ifndef DECODE_IDENTIFIERS
358static char* decodelist =
359  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_!~*'-\"";
360#endif
361
362char*
363dapdecode(DAPlexstatelexstate, char* name)
364{
365    char* decoded = NULL;
366#ifdef DECODE_IDENTIFIERS
367    decoded = ocuridecode(name);
368#else
369    decoded = ocuridecodeonly(name,decodelist);
370#endif
371    oclistpush(lexstate->reclaim,(void*)decoded);
372    return decoded;
373}


HyperKWIC - Version 7.20DA executed at 11:37 on 27 Oct 2017 | Polyhedron Solutions - INTERNAL USE | COMMERCIAL (Any O/S) SN 4AKIed