netcdf-c/libcdmr/ccelex.c
2011-06-10 18:47:26 +00:00

229 lines
5.6 KiB
C

/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "netcdf.h"
#include "nclist.h"
#include "ncbytes.h"
#include "cceconstraints.h"
#include "cceparselex.h"
/* Forward */
#ifdef PARSEDEBUG
static void dumptoken(CCElexstate* lexstate);
#endif
static int tohex(int c);
static void ceaddyytext(CCElexstate* lex, int c);
/****************************************************/
#ifdef UNUSED
static char* worddelims =
"{}[]:;=,";
#endif
/* Define 1 and > 1st legal characters */
static char* wordchars1 =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-+_/%\\";
static char* wordcharsn =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-+_/%\\";
/* Number characters */
static char* numchars1="+-0123456789";
static char* numcharsn="Ee.+-0123456789";
/**************************************************/
static int
ccelex(YYSTYPE* lvalp, CCEparsestate* state)
{
CCElexstate* lexstate = state->lexstate;
int token;
int c;
int len;
char* p=lexstate->next;
token = 0;
ncbytesclear(lexstate->yytext);
ncbytesnull(lexstate->yytext);
p=lexstate->next;
while(token == 0 && (c=*p)) {
if(c <= ' ' || c >= '\177') {p++; continue;}
if(c == '"') {
int more = 1;
/* We have a SCAN_STRINGCONST */
while(more && (c=*(++p))) {
switch (c) {
case '"': p++; more=0; break;
case '\\':
c=*(++p);
switch (c) {
case 'r': c = '\r'; break;
case 'n': c = '\n'; break;
case 'f': c = '\f'; break;
case 't': c = '\t'; break;
case 'x': {
int d1,d2;
c = '?';
++p;
d1 = tohex(*p++);
if(d1 < 0) {
cceerror(state,"Illegal \\xDD in SCAN_STRING");
} else {
d2 = tohex(*p++);
if(d2 < 0) {
cceerror(state,"Illegal \\xDD in SCAN_STRING");
} else {
c=(((unsigned int)d1)<<4) | (unsigned int)d2;
}
}
} break;
default: break;
}
break;
default: break;
}
ceaddyytext(lexstate,c);
}
token=SCAN_STRINGCONST;
} else if(strchr(numchars1,c) != NULL) {
/* we might have a SCAN_NUMBERCONST */
int isnumber = 0;
char* yytext;
char* endpoint;
ceaddyytext(lexstate,c);
for(p++;(c=*p);p++) {
if(strchr(numcharsn,c) == NULL) break;
ceaddyytext(lexstate,c);
}
/* See if this is a number */
ncbytesnull(lexstate->yytext);
yytext = ncbytescontents(lexstate->yytext);
(void)strtoll(yytext,&endpoint,10);
if(*yytext != '\0' && *endpoint == '\0')
isnumber = 1;
else {
(void)strtod(yytext,&endpoint);
if(*yytext != '\0' && *endpoint == '\0')
isnumber = 1; /* maybe */
}
/* A number followed by an id char is assumed to just be
a funny id */
if(isnumber && (*p == '\0' || strchr(wordcharsn,*p) == NULL)) {
token = SCAN_NUMBERCONST;
} else {
/* Now, if the funny word has a "." in it,
we have to back up to that dot */
char* dotpoint = strchr(yytext,'.');
if(dotpoint != NULL) {
p = dotpoint;
*dotpoint = '\0';
}
token = SCAN_WORD;
}
} else if(strchr(wordchars1,c) != NULL) {
/* we have a SCAN_WORD */
ceaddyytext(lexstate,c);
for(p++;(c=*p);p++) {
if(strchr(wordcharsn,c) == NULL) break;
ceaddyytext(lexstate,c);
}
token=SCAN_WORD;
} else {
/* we have a single char token */
token = c;
ceaddyytext(lexstate,c);
p++;
}
}
lexstate->next = p;
len = ncbyteslength(lexstate->yytext);
if(len > MAX_TOKEN_LENGTH) len = MAX_TOKEN_LENGTH;
strncpy(lexstate->lasttokentext,ncbytescontents(lexstate->yytext),len);
lexstate->lasttokentext[len] = '\0';
lexstate->lasttoken = token;
#ifdef PARSEDEBUG
if(ccedebug) dumptoken(lexstate);
#endif
/*Put return value onto Bison stack*/
if(ncbyteslength(lexstate->yytext) == 0)
*lvalp = NULL;
else {
*lvalp = ncbytesdup(lexstate->yytext);
nclistpush(lexstate->reclaim,(ncelem)*lvalp);
}
return token;
}
static void
ceaddyytext(CCElexstate* lex, int c)
{
ncbytesappend(lex->yytext,(char)c);
}
static int
tohex(int c)
{
if(c >= 'a' && c <= 'f') return (c - 'a') + 0xa;
if(c >= 'A' && c <= 'F') return (c - 'A') + 0xa;
if(c >= '0' && c <= '9') return (c - '0');
return -1;
}
#ifdef PARSEDEBUG
static void
dumptoken(CCElexstate* lexstate)
{
switch (lexstate->lasttoken) {
case SCAN_STRINGCONST:
fprintf(stderr,"TOKEN = |\"%s\"|\n",lexstate->lasttokentext);
break;
case SCAN_WORD:
case SCAN_NUMBERCONST:
default:
fprintf(stderr,"TOKEN = |%s|\n",lexstate->lasttokentext);
break;
}
}
#endif
static void
ccelexinit(char* input, CCElexstate** lexstatep)
{
CCElexstate* lexstate = (CCElexstate*)malloc(sizeof(CCElexstate));
if(lexstatep) *lexstatep = lexstate;
if(lexstate == NULL) return;
memset((void*)lexstate,0,sizeof(CCElexstate));
lexstate->input = strdup(input);
lexstate->next = lexstate->input;
lexstate->yytext = ncbytesnew();
lexstate->reclaim = nclistnew();
}
static void
ccelexcleanup(CCElexstate** lexstatep)
{
CCElexstate* lexstate = *lexstatep;
if(lexstate == NULL) return;
if(lexstate->input != NULL) free(lexstate->input);
if(lexstate->reclaim != NULL) {
while(nclistlength(lexstate->reclaim) > 0) {
char* word = (char*)nclistpop(lexstate->reclaim);
if(word) free(word);
}
nclistfree(lexstate->reclaim);
}
ncbytesfree(lexstate->yytext);
free(lexstate);
*lexstatep = NULL;
}