1/* Copyright 2009, 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
11static void addedges(OCnodenode);
12static void setroot(OCnode*,OClist*);
13static int isglobalname(const char* name);
14static int isdodsname(const char* name);
15static OCnodenewocnode(char* nameOCtype octypeDAPparsestatestate);
16static OCtype octypefor(Object etype);
17static OClistscopeduplicates(OClistlist);
18static 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 */
26void
27dap_tagparse(DAPparsestatestate, 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
42Object
43dap_datasetbody(DAPparsestatestateObject nameObject decls)
44{
45    OCnoderoot = newocnode((char*)name,OC_Dataset,state);
46    char* dupname = NULL;
47    OClistdups = scopeduplicates((OClist*)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 = (OClist*)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
67Object
68dap_attributebody(DAPparsestatestateObject attrlist)
69{
70    OCnodenode;
71    /* Check for and remove attribute duplicates */
72    OClistdups = scopeduplicates((OClist*)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 = (OClist*)attrlist;
85    addedges(node);
86    return NULL;
87}
88
89void
90dap_errorbody(DAPparsestatestate,
91   Object codeObject msgObject ptypeObject 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
99void
100dap_unrecognizedresponse(DAPparsestatestate)
101{
102    /* see if this is an HTTP error */
103    unsigned int httperr = 0;
104    int i;
105    char iv[32];
106    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
115Object
116dap_declarations(DAPparsestatestateObject declsObject decl)
117{
118    OClistalist = (OClist*)decls;
119    if(alist == NULL)
120  alist = oclistnew();
121    else
122 oclistpush(alist,(void*)decl);
123    return alist;
124}
125
126Object
127dap_arraydecls(DAPparsestatestateObject arraydeclsObject arraydecl)
128{
129    OClistalist = (OClist*)arraydecls;
130    if(alist == NULL)
131 alist = oclistnew();
132    else
133 oclistpush(alist,(void*)arraydecl);
134    return alist;
135}
136
137Object
138dap_arraydecl(DAPparsestatestateObject nameObject size)
139{
140    long value;
141    OCnodedim;
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
154Object
155dap_attrlist(DAPparsestatestateObject attrlistObject attrtuple)
156{
157    OClistalist = (OClist*)attrlist;
158    if(alist == NULL)
159 alist = oclistnew();
160    else {
161 if(attrtuple != NULL) {/* NULL=>alias encountered, ignore */
162            oclistpush(alist,(void*)attrtuple);
163 }
164    }
165    return alist;
166}
167
168Object
169dap_attrvalue(DAPparsestatestateObject valuelistObject valueObject etype)
170{
171    OClistalist = (OClist*)valuelist;
172    if(alist == NULLalist = oclistnew();
173    /* Watch out for null values */
174    if(value == NULLvalue = "";
175    oclistpush(alist,(void*)strdup(value));
176    return alist;
177}
178
179Object
180dap_attribute(DAPparsestatestateObject nameObject valuesObject etype)
181{
182    OCnodeatt;
183    att = newocnode((char*)name,OC_Attribute,state);
184    att->etype = octypefor(etype);
185    att->att.values = (OClist*)values;
186    return att;
187}
188
189Object
190dap_attrset(DAPparsestatestateObject nameObject attributes)
191{
192    OCnodeattset;
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 = (OClist*)attributes;
198    addedges(attset);
199    return attset;
200}
201
202static int
203isglobalname(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
215static int
216isdodsname(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
227static int
228isnumber(const char* text)
229{
230    for(;*text;text++) {if(!isdigit(*text)) return 0;}
231    return 1;
232}
233#endif
234
235static void
236dimension(OCnodenodeOClistdimensions)
237{
238    unsigned int i;
239    unsigned int rank = oclistlength(dimensions);
240    node->array.dimensions = (OClist*)dimensions;
241    node->array.rank = rank;
242    for(i=0;i<rank;i++) {
243        OCnodedim = (OCnode*)oclistget(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
255char*
256dimnameanon(char* basename, unsigned int index)
257{
258    char name[64];
259    sprintf(name,"%s_%d",basename,index);
260    return strdup(name);
261}
262
263Object
264dap_makebase(DAPparsestatestateObject nameObject etypeObject dimensions)
265{
266    OCnodenode;
267    node = newocnode((char*)name,OC_Atomic,state);
268    node->etype = octypefor(etype);
269    dimension(node,(OClist*)dimensions);
270    return node;
271}
272
273Object
274dap_makestructure(DAPparsestatestateObject nameObject dimensionsObject fields)
275{
276    OCnodenode;
277    OClistdups = scopeduplicates((OClist*)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,(OClist*)dimensions);
287    addedges(node);
288    return node;
289}
290
291Object
292dap_makesequence(DAPparsestatestateObject nameObject members)
293{
294    OCnodenode;
295    OClistdups = scopeduplicates((OClist*)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
307Object
308dap_makegrid(DAPparsestatestateObject nameObject arraydeclObject mapdecls)
309{
310    OCnodenode;
311    /* Check for duplicate map names */
312    OClistdups = scopeduplicates((OClist*)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 = (OClist*)mapdecls;
321    oclistinsert(node->subnodes,0,(void*)arraydecl);
322    addedges(node);
323    return node;
324}
325
326static void
327addedges(OCnodenode)
328{
329    unsigned int i;
330    if(node->subnodes == NULL) return;
331    for(i=0;i<oclistlength(node->subnodes);i++) {
332        OCnodesubnode = (OCnode*)oclistget(node->subnodes,i);
333 subnode->container = node;
334    }
335}
336
337static void
338setroot(OCnoderootOClistocnodes)
339{
340    size_t i;
341    for(i=0;i<oclistlength(ocnodes);i++) {
342 OCnodenode = (OCnode*)oclistget(ocnodes,i);
343 node->root = root;
344    }
345}
346
347int
348daperror(DAPparsestatestate, const char* msg)
349{
350    return dapsemanticerror(state,OC_EINVAL,msg);
351}
352
353int
354dapsemanticerror(DAPparsestatestateOCerror err, const char* msg)
355{
356    dap_parse_error(state,msg);
357    state->error = err; /* semantic error */
358    return 0;
359}
360
361static char*
362flatten(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 */
382static OCnode*
383newocnode(char* nameOCtype octypeDAPparsestatestate)
384{
385    OCnodenode = ocnode_new(name,octype,state->root);
386    oclistpush(state->ocnodes,(void*)node);
387    return node;
388}
389
390static int
391check_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_MINok=0;
398    if(value != NULL) *value = iv;
399    return ok;
400}
401
402static OClist*
403scopeduplicates(OClistlist)
404{
405    unsigned int i,j;
406    unsigned int len = oclistlength(list);
407    OClistdups = NULL;
408    for(i=0;i<len;i++) {
409 OCnodeio = (OCnode*)oclistget(list,i);
410retry:
411        for(j=i+1;j<len;j++) {
412     OCnodejo = (OCnode*)oclistget(list,j);
413     if(strcmp(io->name,jo->name)==0) {
414 if(dups == NULLdups = oclistnew();
415 oclistpush(dups,jo);
416 oclistremove(list,j);
417 len--;
418 goto retry;
419     }
420 }
421    }
422    return dups;
423}
424
425static OCtype
426octypefor(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
443void
444dap_parse_error(DAPparsestatestate, const char *fmt, ...)
445{
446    size_t lensuffixlenprefixlen;
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
465static void
466dap_parse_cleanup(DAPparsestatestate)
467{
468    daplexcleanup(&state->lexstate);
469    if(state->ocnodes != NULLocnodes_free(state->ocnodes);
470    state->ocnodes = NULL;
471    free(state);
472}
473
474static DAPparsestate*
475dap_parse_init(char* buf)
476{
477    DAPparsestatestate = (DAPparsestate*)ocmalloc(sizeof(DAPparsestate)); /*ocmalloc zeros*/
478    MEMCHECK(state,NULL);
479    if(buf==NULL) {
480        dap_parse_error(state,"dap_parse_init: no input buffer");
481 state->error = OC_EINVAL; /* semantic error */
482 dap_parse_cleanup(state);
483 return NULL;
484    }
485    daplexinit(buf,&state->lexstate);
486    return state;
487}
488
489/* Wrapper for dapparse */
490OCerror
491DAPparse(OCstateconnOCtreetree, char* parsestring)
492{
493    DAPparsestatestate = dap_parse_init(parsestring);
494    int parseresult;
495    OCerror ocerr = OC_NOERR;
496    state->ocnodes = oclistnew();
497    state->conn = conn;
498    if(ocdebug >= 2)
499 dapdebug = 1;
500    parseresult = dapparse(state);
501    if(parseresult == 0) {/* 0 => parse ok */
502 if(state->error == OC_EDAPSVC) {
503     /* we ended up parsing an error message from server */
504            conn->error.code = nulldup(state->code);
505            conn->error.message = nulldup(state->message);
506     tree->root = NULL;
507     /* Attempt to further decipher the error code */
508     if(state->code != NULL
509                && (strcmp(state->code,"404") == 0 /* tds returns 404 */
510     || strcmp(state->code,"5") == 0)) /* hyrax returns 5 */
511 ocerr = OC_ENOFILE;
512     else
513         ocerr = OC_EDAPSVC;
514 } else if(state->error != OC_NOERR) {
515     /* Parse failed for semantic reasons */
516     ocerr = state->error;
517 } else {
518            tree->root = state->root;
519     state->root = NULL; /* avoid reclaim */
520            tree->nodes = state->ocnodes;
521     state->ocnodes = NULL; /* avoid reclaim */
522            tree->root->tree = tree;
523     ocerr = OC_NOERR;
524 }
525    } else { /* Parse failed */
526 switch (tree->dxdclass) {
527 case OCDASocerr = OC_EDAS; break;
528 case OCDDSocerr = OC_EDDS; break;
529 case OCDATADDSocerr = OC_EDATADDS; break;
530 default: ocerr = OC_EDAPSVC;
531 }
532    }
533    dap_parse_cleanup(state);
534    return ocerr;
535}
536


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