123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480 |
- /* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
- See the COPYRIGHT file for more information. */
- #include "config.h"
- #include "dapparselex.h"
- /* Forward */
- static void addedges(OCnode* node);
- static void setroot(OCnode*,OClist*);
- static int isglobalname(char* name);
- static OCnode* newocnode(char* name, OCtype octype, DAPparsestate* state);
- static OCtype octypefor(Object etype);
- static char* scopeduplicates(OClist* list);
- static int check_int32(char* val, long* value);
- /****************************************************/
- /* Switch to DAS parsing SCAN_WORD definition */
- /* Use the initial keyword to indicate what we are parsing */
- void
- dap_tagparse(DAPparsestate* state, int kind)
- {
- switch (kind) {
- case SCAN_DATASET:
- case SCAN_ERROR:
- break;
- case SCAN_ATTR:
- dapsetwordchars(state->lexstate,1);
- break;
- default:
- fprintf(stderr,"tagparse: Unknown tag argument: %d\n",kind);
- }
- }
- Object
- dap_datasetbody(DAPparsestate* state, Object name, Object decls)
- {
- OCnode* root = newocnode((char*)name,OC_Dataset,state);
- root->subnodes = (OClist*)decls;
- OCASSERT((state->root == NULL));
- state->root = root;
- state->root->root = state->root; /* make sure to cross link */
- addedges(root);
- setroot(root,state->ocnodes);
- return NULL;
- }
- Object
- dap_attributebody(DAPparsestate* state, Object attrlist)
- {
- OCnode* node = newocnode(NULL,OC_Attributeset,state);
- OCASSERT((state->root == NULL));
- state->root = node;
- /* make sure to cross link */
- state->root->root = state->root;
- node->subnodes = (OClist*)attrlist;
- addedges(node);
- return NULL;
- }
- void
- dap_errorbody(DAPparsestate* state,
- Object code, Object msg, Object ptype, Object prog)
- {
- state->svcerror = 1;
- state->code = nulldup((char*)code);
- state->message = nulldup((char*)msg);
- /* Ignore ptype and prog for now */
- }
- void
- dap_unrecognizedresponse(DAPparsestate* state)
- {
- /* see if this is an HTTP error */
- unsigned int httperr = 0;
- int i;
- char iv[32];
- sscanf(state->lexstate->input,"%u ",&httperr);
- sprintf(iv,"%u",httperr);
- state->lexstate->next = state->lexstate->input;
- /* Limit the amount of input to prevent runaway */
- for(i=0;i<4096;i++) {if(state->lexstate->input[i] == '\0') break;}
- state->lexstate->input[i] = '\0';
- dap_errorbody(state,iv,state->lexstate->input,NULL,NULL);
- }
- Object
- dap_declarations(DAPparsestate* state, Object decls, Object decl)
- {
- OClist* alist = (OClist*)decls;
- if(alist == NULL)
- alist = oclistnew();
- else
- oclistpush(alist,(ocelem)decl);
- return alist;
- }
- Object
- dap_arraydecls(DAPparsestate* state, Object arraydecls, Object arraydecl)
- {
- OClist* alist = (OClist*)arraydecls;
- if(alist == NULL)
- alist = oclistnew();
- else
- oclistpush(alist,(ocelem)arraydecl);
- return alist;
- }
- Object
- dap_arraydecl(DAPparsestate* state, Object name, Object size)
- {
- long value;
- OCnode* dim;
- if(!check_int32(size,&value))
- dap_parse_error(state,"Dimension not an integer");
- if(name != NULL)
- dim = newocnode((char*)name,OC_Dimension,state);
- else
- dim = newocnode(NULL,OC_Dimension,state);
- dim->dim.declsize = value;
- return dim;
- }
- Object
- dap_attrlist(DAPparsestate* state, Object attrlist, Object attrtuple)
- {
- OClist* alist = (OClist*)attrlist;
- if(alist == NULL)
- alist = oclistnew();
- else {
- char* dupname;
- if(attrtuple != NULL) {/* NULL=>alias encountered, ignore */
- oclistpush(alist,(ocelem)attrtuple);
- if((dupname=scopeduplicates(alist))!=NULL) {
- dap_parse_error(state,"Duplicate attribute names in same scope: %s",dupname);
- /* Remove this attribute */
- oclistpop(alist);
- }
- }
- }
- return alist;
- }
- Object
- dap_attrvalue(DAPparsestate* state, Object valuelist, Object value, Object etype)
- {
- OClist* alist = (OClist*)valuelist;
- if(alist == NULL) alist = oclistnew();
- /* Watch out for null values */
- if(value == NULL) value = "";
- oclistpush(alist,(ocelem)strdup(value));
- return alist;
- }
- Object
- dap_attribute(DAPparsestate* state, Object name, Object values, Object etype)
- {
- OCnode* att;
- att = newocnode((char*)name,OC_Attribute,state);
- att->etype = octypefor(etype);
- att->att.values = (OClist*)values;
- return att;
- }
- Object
- dap_attrset(DAPparsestate* state, Object name, Object attributes)
- {
- OCnode* attset;
- attset = newocnode((char*)name,OC_Attributeset,state);
- /* Check var set vs global set */
- attset->att.isglobal = isglobalname(name);
- attset->subnodes = (OClist*)attributes;
- addedges(attset);
- return attset;
- }
- static int
- isglobalname(char* name)
- {
- int len = strlen(name);
- int glen = strlen("global");
- char* p;
- if(len < glen) return 0;
- p = name + (len - glen);
- if(strcasecmp(p,"global") != 0)
- return 0;
- return 1;
- }
- #if 0
- static int
- isnumber(const char* text)
- {
- for(;*text;text++) {if(!isdigit(*text)) return 0;}
- return 1;
- }
- #endif
- static void
- dimension(OCnode* node, OClist* dimensions)
- {
- unsigned int i;
- unsigned int rank = oclistlength(dimensions);
- node->array.dimensions = (OClist*)dimensions;
- node->array.rank = rank;
- for(i=0;i<rank;i++) {
- OCnode* dim = (OCnode*)oclistget(node->array.dimensions,i);
- dim->dim.array = node;
- dim->dim.arrayindex = i;
- #if 0
- if(dim->name == NULL) {
- dim->dim.anonymous = 1;
- dim->name = dimnameanon(node->name,i);
- }
- #endif
- }
- }
- char*
- dimnameanon(char* basename, unsigned int index)
- {
- char name[64];
- sprintf(name,"%s_%d",basename,index);
- return strdup(name);
- }
- Object
- dap_makebase(DAPparsestate* state, Object name, Object etype, Object dimensions)
- {
- OCnode* node;
- node = newocnode((char*)name,OC_Primitive,state);
- node->etype = octypefor(etype);
- dimension(node,(OClist*)dimensions);
- return node;
- }
- Object
- dap_makestructure(DAPparsestate* state, Object name, Object dimensions, Object fields)
- {
- OCnode* node;
- char* dupname;
- if((dupname=scopeduplicates((OClist*)fields))!= NULL) {
- dap_parse_error(state,"Duplicate structure field names in same scope: %s.%s",(char*)name,dupname);
- return (Object)NULL;
- }
- node = newocnode(name,OC_Structure,state);
- node->subnodes = fields;
- dimension(node,(OClist*)dimensions);
- addedges(node);
- return node;
- }
- Object
- dap_makesequence(DAPparsestate* state, Object name, Object members)
- {
- OCnode* node;
- char* dupname;
- if((dupname=scopeduplicates((OClist*)members)) != NULL) {
- dap_parse_error(state,"Duplicate sequence member names in same scope: %s.%s",(char*)name,dupname);
- return (Object)NULL;
- }
- node = newocnode(name,OC_Sequence,state);
- node->subnodes = members;
- addedges(node);
- return node;
- }
- Object
- dap_makegrid(DAPparsestate* state, Object name, Object arraydecl, Object mapdecls)
- {
- OCnode* node;
- /* Check for duplicate map names */
- char* dupname;
- if((dupname=scopeduplicates((OClist*)mapdecls)) != NULL) {
- dap_parse_error(state,"Duplicate grid map names in same scope: %s.%s",(char*)name,dupname);
- return (Object)NULL;
- }
- node = newocnode(name,OC_Grid,state);
- node->subnodes = (OClist*)mapdecls;
- oclistinsert(node->subnodes,0,(ocelem)arraydecl);
- addedges(node);
- return node;
- }
- static void
- addedges(OCnode* node)
- {
- unsigned int i;
- if(node->subnodes == NULL) return;
- for(i=0;i<oclistlength(node->subnodes);i++) {
- OCnode* subnode = (OCnode*)oclistget(node->subnodes,i);
- subnode->container = node;
- }
- }
- static void
- setroot(OCnode* root, OClist* ocnodes)
- {
- int i;
- for(i=0;i<oclistlength(ocnodes);i++) {
- OCnode* node = (OCnode*)oclistget(ocnodes,i);
- node->root = root;
- }
- }
- int
- daperror(DAPparsestate* state, const char* msg)
- {
- dap_parse_error(state,msg);
- return 0;
- }
- static char*
- flatten(char* s, char* tmp, int tlen)
- {
- int c;
- char* p,*q;
- strncpy(tmp,s,tlen);
- tmp[tlen] = '\0';
- p = (q = tmp);
- while((c=*p++)) {
- switch (c) {
- case '\r': case '\n': break;
- case '\t': *q++ = ' '; break;
- case ' ': if(*p != ' ') *q++ = c; break;
- default: *q++ = c;
- }
- }
- *q = '\0';
- return tmp;
- }
- /* Create an ocnode and capture in the state->ocnode list */
- static OCnode*
- newocnode(char* name, OCtype octype, DAPparsestate* state)
- {
- OCnode* node = ocmakenode(name,octype,state->root);
- oclistpush(state->ocnodes,(ocelem)node);
- return node;
- }
- static int
- check_int32(char* val, long* value)
- {
- char* ptr;
- int ok = 1;
- long iv = strtol(val,&ptr,0); /* 0=>auto determine base */
- if((iv == 0 && val == ptr) || *ptr != '\0') {ok=0; iv=1;}
- else if(iv > OC_INT32_MAX || iv < OC_INT32_MIN) ok=0;
- if(value != NULL) *value = iv;
- return ok;
- }
- static char*
- scopeduplicates(OClist* list)
- {
- unsigned int i,j;
- for(i=0;i<oclistlength(list);i++) {
- OCnode* io = (OCnode*)oclistget(list,i);
- for(j=i+1;j<oclistlength(list);j++) {
- OCnode* jo = (OCnode*)oclistget(list,j);
- if(strcmp(io->name,jo->name)==0)
- return io->name;
- }
- }
- return NULL;
- }
- static OCtype
- octypefor(Object etype)
- {
- switch ((long)etype) {
- case SCAN_BYTE: return OC_Byte;
- case SCAN_INT16: return OC_Int16;
- case SCAN_UINT16: return OC_UInt16;
- case SCAN_INT32: return OC_Int32;
- case SCAN_UINT32: return OC_UInt32;
- case SCAN_FLOAT32: return OC_Float32;
- case SCAN_FLOAT64: return OC_Float64;
- case SCAN_URL: return OC_URL;
- case SCAN_STRING: return OC_String;
- default: abort();
- }
- return OC_NAT;
- }
- void
- dap_parse_error(DAPparsestate* state, const char *fmt, ...)
- {
- size_t len, suffixlen, prefixlen;
- va_list argv;
- char* tmp = NULL;
- va_start(argv,fmt);
- (void) vfprintf(stderr,fmt,argv) ;
- (void) fputc('\n',stderr) ;
- len = strlen(state->lexstate->input);
- suffixlen = strlen(state->lexstate->next);
- prefixlen = (len - suffixlen);
- tmp = (char*)ocmalloc(len+1);
- flatten(state->lexstate->input,tmp,prefixlen);
- (void) fprintf(stderr,"context: %s",tmp);
- flatten(state->lexstate->next,tmp,suffixlen);
- (void) fprintf(stderr,"^%s\n",tmp);
- (void) fflush(stderr); /* to ensure log files are current */
- ocfree(tmp);
- }
- static void
- dap_parse_cleanup(DAPparsestate* state)
- {
- daplexcleanup(&state->lexstate);
- if(state->ocnodes != NULL) ocfreenodes(state->ocnodes);
- state->ocnodes = NULL;
- free(state);
- }
- static DAPparsestate*
- dap_parse_init(char* buf)
- {
- DAPparsestate* state = (DAPparsestate*)ocmalloc(sizeof(DAPparsestate)); /*ocmalloc zeros*/
- MEMCHECK(state,(DAPparsestate*)NULL);
- if(buf==NULL) {
- dap_parse_error(state,"dap_parse_init: no input buffer");
- dap_parse_cleanup(state);
- return NULL;
- }
- daplexinit(buf,&state->lexstate);
- return state;
- }
- /* Wrapper for dapparse */
- OCerror
- DAPparse(OCstate* conn, OCtree* tree, char* parsestring)
- {
- DAPparsestate* state = dap_parse_init(parsestring);
- int parseresult;
- OCerror ocerr = OC_NOERR;
- state->ocnodes = oclistnew();
- state->conn = conn;
- if(ocdebug >= 2)
- dapdebug = 1;
- parseresult = dapparse(state);
- if(parseresult == 0) {/* 0 => parse ok */
- /* Check to see if we ended up parsing an error message */
- if(state->svcerror) {
- conn->error.code = nulldup(state->code);
- conn->error.message = nulldup(state->message);
- tree->root = NULL;
- /* Attempt to further decipher the error code */
- if(state->code != NULL
- && (strcmp(state->code,"404") == 0 /* tds returns 404 */
- || strcmp(state->code,"5") == 0)) /* hyrax returns 5 */
- ocerr = OC_ENOFILE;
- else
- ocerr = OC_EDAPSVC;
- } else {
- OCASSERT((state->root != NULL));
- tree->root = state->root;
- state->root = NULL; /* avoid reclaim */
- tree->nodes = state->ocnodes;
- state->ocnodes = NULL; /* avoid reclaim */
- tree->root->tree = tree;
- ocerr = OC_NOERR;
- }
- } else { /* Parse failed */
- switch (tree->dxdclass) {
- case OCDAS: ocerr = OC_EDAS; break;
- case OCDDS: ocerr = OC_EDDS; break;
- case OCDATADDS: ocerr = OC_EDATADDS; break;
- default: ocerr = OC_EDAPSVC;
- }
- }
- dap_parse_cleanup(state);
- return ocerr;
- }
|