1 /* Copyright 2018, UCAR/Unidata and OPeNDAP, Inc.
2    See the COPYRIGHT file for more information.
3 */
4 
5 #include "config.h"
6 #include "dapparselex.h"
7 #include "dapy.h"
8 
9 /* Forward */
10 
11 static void addedges(OCnode* node);
12 static void setroot(OCnode*,NClist*);
13 static int isglobalname(const char* name);
14 static int isdodsname(const char* name);
15 static OCnode* newocnode(char* name, OCtype octype, DAPparsestate* state);
16 static OCtype octypefor(Object etype);
17 static NClist* scopeduplicates(NClist* list);
18 static int check_int32(char* val, long* value);
19 
20 
21 /****************************************************/
22 
23 /* Switch to DAS parsing SCAN_WORD definition */
24 
25 /* Use the initial keyword to indicate what we are parsing */
26 void
dap_tagparse(DAPparsestate * state,int kind)27 dap_tagparse(DAPparsestate* state, int kind)
28 {
29     switch (kind) {
30     case SCAN_DATASET:
31     case SCAN_ERROR:
32 	break;
33     case SCAN_ATTR:
34 	dapsetwordchars(state->lexstate,1);
35         break;
36     default:
37         fprintf(stderr,"tagparse: Unknown tag argument: %d\n",kind);
38     }
39 }
40 
41 
42 Object
dap_datasetbody(DAPparsestate * state,Object name,Object decls)43 dap_datasetbody(DAPparsestate* state, Object name, Object decls)
44 {
45     OCnode* root = newocnode((char*)name,OC_Dataset,state);
46     char* dupname = NULL;
47     NClist* dups = scopeduplicates((NClist*)decls);
48     if(dups != NULL) {
49 	/* Sometimes, some servers (i.e. Thredds)
50            return a dds with duplicate field names
51            at the dataset level; simulate an errorbody response
52         */
53 	ocnodes_free(dups);
54         dap_parse_error(state,"Duplicate dataset field names: %s",name,dupname);
55 	state->error = OC_ENAMEINUSE;
56 	return (Object)NULL;
57     }
58     root->subnodes = (NClist*)decls;
59     OCASSERT((state->root == NULL));
60     state->root = root;
61     state->root->root = state->root; /* make sure to cross link */
62     addedges(root);
63     setroot(root,state->ocnodes);
64     return NULL;
65 }
66 
67 Object
dap_attributebody(DAPparsestate * state,Object attrlist)68 dap_attributebody(DAPparsestate* state, Object attrlist)
69 {
70     OCnode* node;
71     /* Check for and remove attribute duplicates */
72     NClist* dups = scopeduplicates((NClist*)attrlist);
73     if(dups != NULL) {
74         ocnodes_free(dups);
75 	dap_parse_error(state,"Duplicate attribute names in same scope");
76 	state->error = OC_ENAMEINUSE; /* semantic error */
77 	return NULL;
78     }
79     node = newocnode(NULL,OC_Attributeset,state);
80     OCASSERT((state->root == NULL));
81     state->root = node;
82     /* make sure to cross link */
83     state->root->root = state->root;
84     node->subnodes = (NClist*)attrlist;
85     addedges(node);
86     return NULL;
87 }
88 
89 void
dap_errorbody(DAPparsestate * state,Object code,Object msg,Object ptype,Object prog)90 dap_errorbody(DAPparsestate* state,
91 	  Object code, Object msg, Object ptype, Object prog)
92 {
93     state->error = OC_EDAPSVC;
94     state->code     = nulldup((char*)code);
95     state->message  = nulldup((char*)msg);
96     /* Ignore ptype and prog for now */
97 }
98 
99 void
dap_unrecognizedresponse(DAPparsestate * state)100 dap_unrecognizedresponse(DAPparsestate* state)
101 {
102     /* see if this is an HTTP error */
103     unsigned int httperr = 0;
104     int i;
105     char iv[32];
106     (void)sscanf(state->lexstate->input,"%u ",&httperr);
107     sprintf(iv,"%u",httperr);
108     state->lexstate->next = state->lexstate->input;
109     /* Limit the amount of input to prevent runaway */
110     for(i=0;i<4096;i++) {if(state->lexstate->input[i] == '\0') break;}
111     state->lexstate->input[i] = '\0';
112     dap_errorbody(state,iv,state->lexstate->input,NULL,NULL);
113 }
114 
115 Object
dap_declarations(DAPparsestate * state,Object decls,Object decl)116 dap_declarations(DAPparsestate* state, Object decls, Object decl)
117 {
118     NClist* alist = (NClist*)decls;
119     if(alist == NULL)
120 	 alist = nclistnew();
121     else
122 	nclistpush(alist,(void*)decl);
123     return alist;
124 }
125 
126 Object
dap_arraydecls(DAPparsestate * state,Object arraydecls,Object arraydecl)127 dap_arraydecls(DAPparsestate* state, Object arraydecls, Object arraydecl)
128 {
129     NClist* alist = (NClist*)arraydecls;
130     if(alist == NULL)
131 	alist = nclistnew();
132     else
133 	nclistpush(alist,(void*)arraydecl);
134     return alist;
135 }
136 
137 Object
dap_arraydecl(DAPparsestate * state,Object name,Object size)138 dap_arraydecl(DAPparsestate* state, Object name, Object size)
139 {
140     long value;
141     OCnode* dim;
142     if(!check_int32(size,&value)) {
143 	dap_parse_error(state,"Dimension not an integer");
144 	state->error = OC_EDIMSIZE; /* signal semantic error */
145     }
146     if(name != NULL)
147 	dim = newocnode((char*)name,OC_Dimension,state);
148     else
149 	dim = newocnode(NULL,OC_Dimension,state);
150     dim->dim.declsize = value;
151     return dim;
152 }
153 
154 Object
dap_attrlist(DAPparsestate * state,Object attrlist,Object attrtuple)155 dap_attrlist(DAPparsestate* state, Object attrlist, Object attrtuple)
156 {
157     NClist* alist = (NClist*)attrlist;
158     if(alist == NULL)
159 	alist = nclistnew();
160     else {
161 	if(attrtuple != NULL) {/* NULL=>alias encountered, ignore */
162             nclistpush(alist,(void*)attrtuple);
163 	}
164     }
165     return alist;
166 }
167 
168 Object
dap_attrvalue(DAPparsestate * state,Object valuelist,Object value,Object etype)169 dap_attrvalue(DAPparsestate* state, Object valuelist, Object value, Object etype)
170 {
171     NClist* alist = (NClist*)valuelist;
172     if(alist == NULL) alist = nclistnew();
173     /* Watch out for null values */
174     if(value == NULL) value = "";
175     nclistpush(alist,(void*)strdup(value));
176     return alist;
177 }
178 
179 Object
dap_attribute(DAPparsestate * state,Object name,Object values,Object etype)180 dap_attribute(DAPparsestate* state, Object name, Object values, Object etype)
181 {
182     OCnode* att;
183     att = newocnode((char*)name,OC_Attribute,state);
184     att->etype = octypefor(etype);
185     att->att.values = (NClist*)values;
186     return att;
187 }
188 
189 Object
dap_attrset(DAPparsestate * state,Object name,Object attributes)190 dap_attrset(DAPparsestate* state, Object name, Object attributes)
191 {
192     OCnode* attset;
193     attset = newocnode((char*)name,OC_Attributeset,state);
194     /* Check var set vs global set */
195     attset->att.isglobal = isglobalname(name);
196     attset->att.isdods = isdodsname(name);
197     attset->subnodes = (NClist*)attributes;
198     addedges(attset);
199     return attset;
200 }
201 
202 static int
isglobalname(const char * name)203 isglobalname(const char* name)
204 {
205     int len = strlen(name);
206     int glen = strlen("global");
207     const char* p;
208     if(len < glen) return 0;
209     p = name + (len - glen);
210     if(strcasecmp(p,"global") != 0)
211 	return 0;
212     return 1;
213 }
214 
215 static int
isdodsname(const char * name)216 isdodsname(const char* name)
217 {
218     size_t len = strlen(name);
219     size_t glen = strlen("DODS");
220     if(len < glen) return 0;
221     if(ocstrncmp(name,"DODS",glen) != 0)
222 	return 0;
223     return 1;
224 }
225 
226 #if 0
227 static int
228 isnumber(const char* text)
229 {
230     for(;*text;text++) {if(!isdigit(*text)) return 0;}
231     return 1;
232 }
233 #endif
234 
235 static void
dimension(OCnode * node,NClist * dimensions)236 dimension(OCnode* node, NClist* dimensions)
237 {
238     unsigned int i;
239     unsigned int rank = nclistlength(dimensions);
240     node->array.dimensions = (NClist*)dimensions;
241     node->array.rank = rank;
242     for(i=0;i<rank;i++) {
243         OCnode* dim = (OCnode*)nclistget(node->array.dimensions,i);
244         dim->dim.array = node;
245 	dim->dim.arrayindex = i;
246 #if 0
247 	if(dim->name == NULL) {
248 	    dim->dim.anonymous = 1;
249 	    dim->name = dimnameanon(node->name,i);
250 	}
251 #endif
252     }
253 }
254 
255 char*
dimnameanon(char * basename,unsigned int index)256 dimnameanon(char* basename, unsigned int index)
257 {
258     char name[64];
259     sprintf(name,"%s_%d",basename,index);
260     return strdup(name);
261 }
262 
263 Object
dap_makebase(DAPparsestate * state,Object name,Object etype,Object dimensions)264 dap_makebase(DAPparsestate* state, Object name, Object etype, Object dimensions)
265 {
266     OCnode* node;
267     node = newocnode((char*)name,OC_Atomic,state);
268     node->etype = octypefor(etype);
269     dimension(node,(NClist*)dimensions);
270     return node;
271 }
272 
273 Object
dap_makestructure(DAPparsestate * state,Object name,Object dimensions,Object fields)274 dap_makestructure(DAPparsestate* state, Object name, Object dimensions, Object fields)
275 {
276     OCnode* node;
277     NClist* dups = scopeduplicates((NClist*)fields);
278     if(dups != NULL) {
279 	ocnodes_free(dups);
280         dap_parse_error(state,"Duplicate structure field names in same structure: %s",(char*)name);
281 	state->error = OC_ENAMEINUSE; /* semantic error */
282 	return (Object)NULL;
283     }
284     node = newocnode(name,OC_Structure,state);
285     node->subnodes = fields;
286     dimension(node,(NClist*)dimensions);
287     addedges(node);
288     return node;
289 }
290 
291 Object
dap_makesequence(DAPparsestate * state,Object name,Object members)292 dap_makesequence(DAPparsestate* state, Object name, Object members)
293 {
294     OCnode* node;
295     NClist* dups = scopeduplicates((NClist*)members);
296     if(dups != NULL) {
297 	ocnodes_free(dups);
298         dap_parse_error(state,"Duplicate sequence member names in same sequence: %s",(char*)name);
299 	return (Object)NULL;
300     }
301     node = newocnode(name,OC_Sequence,state);
302     node->subnodes = members;
303     addedges(node);
304     return node;
305 }
306 
307 Object
dap_makegrid(DAPparsestate * state,Object name,Object arraydecl,Object mapdecls)308 dap_makegrid(DAPparsestate* state, Object name, Object arraydecl, Object mapdecls)
309 {
310     OCnode* node;
311     /* Check for duplicate map names */
312     NClist* dups = scopeduplicates((NClist*)mapdecls);
313     if(dups != NULL) {
314 	ocnodes_free(dups);
315         dap_parse_error(state,"Duplicate grid map names in same grid: %s",(char*)name);
316 	state->error = OC_ENAMEINUSE; /* semantic error */
317 	return (Object)NULL;
318     }
319     node = newocnode(name,OC_Grid,state);
320     node->subnodes = (NClist*)mapdecls;
321     nclistinsert(node->subnodes,0,(void*)arraydecl);
322     addedges(node);
323     return node;
324 }
325 
326 static void
addedges(OCnode * node)327 addedges(OCnode* node)
328 {
329     unsigned int i;
330     if(node->subnodes == NULL) return;
331     for(i=0;i<nclistlength(node->subnodes);i++) {
332         OCnode* subnode = (OCnode*)nclistget(node->subnodes,i);
333 	subnode->container = node;
334     }
335 }
336 
337 static void
setroot(OCnode * root,NClist * ocnodes)338 setroot(OCnode* root, NClist* ocnodes)
339 {
340     size_t i;
341     for(i=0;i<nclistlength(ocnodes);i++) {
342 	OCnode* node = (OCnode*)nclistget(ocnodes,i);
343 	node->root = root;
344     }
345 }
346 
347 int
daperror(DAPparsestate * state,const char * msg)348 daperror(DAPparsestate* state, const char* msg)
349 {
350     return dapsemanticerror(state,OC_EINVAL,msg);
351 }
352 
353 int
dapsemanticerror(DAPparsestate * state,OCerror err,const char * msg)354 dapsemanticerror(DAPparsestate* state, OCerror err, const char* msg)
355 {
356     dap_parse_error(state,msg);
357     state->error = err; /* semantic error */
358     return 0;
359 }
360 
361 static char*
flatten(char * s,char * tmp,size_t tlen)362 flatten(char* s, char* tmp, size_t tlen)
363 {
364     int c;
365     char* p,*q;
366     strncpy(tmp,s,tlen);
367     tmp[tlen] = '\0';
368     p = (q = tmp);
369     while((c=*p++)) {
370 	switch (c) {
371 	case '\r': case '\n': break;
372 	case '\t': *q++ = ' '; break;
373 	case ' ': if(*p != ' ') *q++ = c; break;
374 	default: *q++ = c;
375 	}
376     }
377     *q = '\0';
378     return tmp;
379 }
380 
381 /* Create an ocnode and capture in the state->ocnode list */
382 static OCnode*
newocnode(char * name,OCtype octype,DAPparsestate * state)383 newocnode(char* name, OCtype octype, DAPparsestate* state)
384 {
385     OCnode* node = ocnode_new(name,octype,state->root);
386     nclistpush(state->ocnodes,(void*)node);
387     return node;
388 }
389 
390 static int
check_int32(char * val,long * value)391 check_int32(char* val, long* value)
392 {
393     char* ptr;
394     int ok = 1;
395     long iv = strtol(val,&ptr,0); /* 0=>auto determine base */
396     if((iv == 0 && val == ptr) || *ptr != '\0') {ok=0; iv=1;}
397     else if(iv > OC_INT32_MAX || iv < OC_INT32_MIN) ok=0;
398     if(value != NULL) *value = iv;
399     return ok;
400 }
401 
402 static NClist*
scopeduplicates(NClist * list)403 scopeduplicates(NClist* list)
404 {
405     unsigned int i,j;
406     unsigned int len = nclistlength(list);
407     NClist* dups = NULL;
408     for(i=0;i<len;i++) {
409 	OCnode* io = (OCnode*)nclistget(list,i);
410 retry:
411         for(j=i+1;j<len;j++) {
412 	    OCnode* jo = (OCnode*)nclistget(list,j);
413 	    if(strcmp(io->name,jo->name)==0) {
414 		if(dups == NULL) dups = nclistnew();
415 		nclistpush(dups,jo);
416 		nclistremove(list,j);
417 		len--;
418 		goto retry;
419 	    }
420 	}
421     }
422     return dups;
423 }
424 
425 static OCtype
octypefor(Object etype)426 octypefor(Object etype)
427 {
428     switch ((long)etype) {
429     case SCAN_BYTE: return OC_Byte;
430     case SCAN_INT16: return OC_Int16;
431     case SCAN_UINT16: return OC_UInt16;
432     case SCAN_INT32: return OC_Int32;
433     case SCAN_UINT32: return OC_UInt32;
434     case SCAN_FLOAT32: return OC_Float32;
435     case SCAN_FLOAT64: return OC_Float64;
436     case SCAN_URL: return OC_URL;
437     case SCAN_STRING: return OC_String;
438     default: abort();
439     }
440     return OC_NAT;
441 }
442 
443 void
dap_parse_error(DAPparsestate * state,const char * fmt,...)444 dap_parse_error(DAPparsestate* state, const char *fmt, ...)
445 {
446     size_t len, suffixlen, prefixlen;
447     va_list argv;
448     char* tmp = NULL;
449     va_start(argv,fmt);
450     (void) vfprintf(stderr,fmt,argv) ;
451     (void) fputc('\n',stderr) ;
452     len = strlen(state->lexstate->input);
453     suffixlen = strlen(state->lexstate->next);
454     prefixlen = (len - suffixlen);
455     tmp = (char*)ocmalloc(len+1);
456     flatten(state->lexstate->input,tmp,prefixlen);
457     (void) fprintf(stderr,"context: %s",tmp);
458     flatten(state->lexstate->next,tmp,suffixlen);
459     (void) fprintf(stderr,"^%s\n",tmp);
460     (void) fflush(stderr);	/* to ensure log files are current */
461     ocfree(tmp);
462     va_end(argv);
463 }
464 
465 static void
dap_parse_cleanup(DAPparsestate * state)466 dap_parse_cleanup(DAPparsestate* state)
467 {
468     daplexcleanup(&state->lexstate);
469     if(state->ocnodes != NULL) ocnodes_free(state->ocnodes);
470     state->ocnodes = NULL;
471     nullfree(state->code);
472     nullfree(state->message);
473     free(state);
474 }
475 
476 static DAPparsestate*
dap_parse_init(char * buf)477 dap_parse_init(char* buf)
478 {
479     DAPparsestate* state = (DAPparsestate*)ocmalloc(sizeof(DAPparsestate)); /*ocmalloc zeros*/
480     MEMCHECK(state,NULL);
481     if(buf==NULL) {
482         dap_parse_error(state,"dap_parse_init: no input buffer");
483 	state->error = OC_EINVAL; /* semantic error */
484 	dap_parse_cleanup(state);
485 	return NULL;
486     }
487     daplexinit(buf,&state->lexstate);
488     return state;
489 }
490 
491 /* Wrapper for dapparse */
492 OCerror
DAPparse(OCstate * conn,OCtree * tree,char * parsestring)493 DAPparse(OCstate* conn, OCtree* tree, char* parsestring)
494 {
495     DAPparsestate* state = dap_parse_init(parsestring);
496     int parseresult;
497     OCerror ocerr = OC_NOERR;
498     state->ocnodes = nclistnew();
499     state->conn = conn;
500     if(ocdebug >= 2)
501 	dapdebug = 1;
502     parseresult = dapparse(state);
503     if(parseresult == 0) {/* 0 => parse ok */
504 	if(state->error == OC_EDAPSVC) {
505 	    /* we ended up parsing an error message from server */
506             conn->error.code = nulldup(state->code);
507             conn->error.message = nulldup(state->message);
508 	    tree->root = NULL;
509 	    /* Attempt to further decipher the error code */
510 	    if(state->code != NULL
511                 && (strcmp(state->code,"404") == 0 /* tds returns 404 */
512 		    || strcmp(state->code,"5") == 0)) /* hyrax returns 5 */
513 		ocerr = OC_ENOFILE;
514 	    else
515 	        ocerr = OC_EDAPSVC;
516 	} else if(state->error != OC_NOERR) {
517 	    /* Parse failed for semantic reasons */
518 	    ocerr = state->error;
519 	} else {
520             tree->root = state->root;
521 	    state->root = NULL; /* avoid reclaim */
522             tree->nodes = state->ocnodes;
523 	    state->ocnodes = NULL; /* avoid reclaim */
524             tree->root->tree = tree;
525 	    ocerr = OC_NOERR;
526 	}
527     } else { /* Parse failed */
528 	switch (tree->dxdclass) {
529 	case OCDAS: ocerr = OC_EDAS; break;
530 	case OCDDS: ocerr = OC_EDDS; break;
531 	case OCDATADDS: ocerr = OC_EDATADDS; break;
532 	default: ocerr = OC_EDAPSVC;
533 	}
534     }
535     dap_parse_cleanup(state);
536     return ocerr;
537 }
538 
539