dcelex.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
  2. See the COPYRIGHT file for more information. */
  3. #include "config.h"
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <assert.h>
  8. #include "netcdf.h"
  9. #include "nclist.h"
  10. #include "ncbytes.h"
  11. #include "dceconstraints.h"
  12. #include "dceparselex.h"
  13. /* Forward */
  14. static void dumptoken(DCElexstate* lexstate);
  15. static int tohex(int c);
  16. static void ceaddyytext(DCElexstate* lex, int c);
  17. /****************************************************/
  18. /* Define 1 and > 1st legal characters */
  19. static char* wordchars1 =
  20. "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-+_/%\\";
  21. static char* wordcharsn =
  22. "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-+_/%\\";
  23. /* Number characters */
  24. static char* numchars1="+-0123456789";
  25. static char* numcharsn="Ee.+-0123456789";
  26. /**************************************************/
  27. int
  28. dcelex(YYSTYPE* lvalp, DCEparsestate* state)
  29. {
  30. DCElexstate* lexstate = state->lexstate;
  31. int token;
  32. int c;
  33. int len;
  34. char* p=lexstate->next;
  35. token = 0;
  36. ncbytesclear(lexstate->yytext);
  37. ncbytesnull(lexstate->yytext);
  38. p=lexstate->next;
  39. while(token == 0 && (c=*p)) {
  40. if(c <= ' ' || c >= '\177') {p++; continue;}
  41. if(c == '"') {
  42. int more = 1;
  43. /* We have a SCAN_STRINGCONST */
  44. while(more && (c=*(++p))) {
  45. switch (c) {
  46. case '"': p++; more=0; break;
  47. case '\\':
  48. c=*(++p);
  49. switch (c) {
  50. case 'r': c = '\r'; break;
  51. case 'n': c = '\n'; break;
  52. case 'f': c = '\f'; break;
  53. case 't': c = '\t'; break;
  54. case 'x': {
  55. int d1,d2;
  56. c = '?';
  57. ++p;
  58. d1 = tohex(*p++);
  59. if(d1 < 0) {
  60. dceerror(state,"Illegal \\xDD in SCAN_STRING");
  61. } else {
  62. d2 = tohex(*p++);
  63. if(d2 < 0) {
  64. dceerror(state,"Illegal \\xDD in SCAN_STRING");
  65. } else {
  66. c=(((unsigned int)d1)<<4) | (unsigned int)d2;
  67. }
  68. }
  69. } break;
  70. default: break;
  71. }
  72. break;
  73. default: break;
  74. }
  75. ceaddyytext(lexstate,c);
  76. }
  77. token=SCAN_STRINGCONST;
  78. } else if(strchr(numchars1,c) != NULL) {
  79. /* we might have a SCAN_NUMBERCONST */
  80. int isnumber = 0;
  81. char* yytext;
  82. char* endpoint;
  83. ceaddyytext(lexstate,c);
  84. for(p++;(c=*p);p++) {
  85. if(strchr(numcharsn,c) == NULL) break;
  86. ceaddyytext(lexstate,c);
  87. }
  88. /* See if this is a number */
  89. ncbytesnull(lexstate->yytext);
  90. yytext = ncbytescontents(lexstate->yytext);
  91. (void)strtoll(yytext,&endpoint,10);
  92. if(*yytext != '\0' && *endpoint == '\0')
  93. isnumber = 1;
  94. else {
  95. (void)strtod(yytext,&endpoint);
  96. if(*yytext != '\0' && *endpoint == '\0')
  97. isnumber = 1; /* maybe */
  98. }
  99. /* A number followed by an id char is assumed to just be
  100. a funny id */
  101. if(isnumber && (*p == '\0' || strchr(wordcharsn,*p) == NULL)) {
  102. token = SCAN_NUMBERCONST;
  103. } else {
  104. /* Now, if the funny word has a "." in it,
  105. we have to back up to that dot */
  106. char* dotpoint = strchr(yytext,'.');
  107. if(dotpoint != NULL) {
  108. p = dotpoint;
  109. *dotpoint = '\0';
  110. }
  111. token = SCAN_WORD;
  112. }
  113. } else if(strchr(wordchars1,c) != NULL) {
  114. /* we have a SCAN_WORD */
  115. ceaddyytext(lexstate,c);
  116. for(p++;(c=*p);p++) {
  117. if(strchr(wordcharsn,c) == NULL) break;
  118. ceaddyytext(lexstate,c);
  119. }
  120. token=SCAN_WORD;
  121. } else {
  122. /* we have a single char token */
  123. token = c;
  124. ceaddyytext(lexstate,c);
  125. p++;
  126. }
  127. }
  128. lexstate->next = p;
  129. len = ncbyteslength(lexstate->yytext);
  130. if(len > MAX_TOKEN_LENGTH) len = MAX_TOKEN_LENGTH;
  131. strncpy(lexstate->lasttokentext,ncbytescontents(lexstate->yytext),len);
  132. lexstate->lasttokentext[len] = '\0';
  133. lexstate->lasttoken = token;
  134. if(dcedebug) dumptoken(lexstate);
  135. /*Put return value onto Bison stack*/
  136. if(ncbyteslength(lexstate->yytext) == 0)
  137. *lvalp = NULL;
  138. else {
  139. *lvalp = ncbytesdup(lexstate->yytext);
  140. nclistpush(lexstate->reclaim,(ncelem)*lvalp);
  141. }
  142. return token;
  143. }
  144. static void
  145. ceaddyytext(DCElexstate* lex, int c)
  146. {
  147. ncbytesappend(lex->yytext,(char)c);
  148. }
  149. static int
  150. tohex(int c)
  151. {
  152. if(c >= 'a' && c <= 'f') return (c - 'a') + 0xa;
  153. if(c >= 'A' && c <= 'F') return (c - 'A') + 0xa;
  154. if(c >= '0' && c <= '9') return (c - '0');
  155. return -1;
  156. }
  157. static void
  158. dumptoken(DCElexstate* lexstate)
  159. {
  160. switch (lexstate->lasttoken) {
  161. case SCAN_STRINGCONST:
  162. fprintf(stderr,"TOKEN = |\"%s\"|\n",lexstate->lasttokentext);
  163. break;
  164. case SCAN_WORD:
  165. case SCAN_NUMBERCONST:
  166. default:
  167. fprintf(stderr,"TOKEN = |%s|\n",lexstate->lasttokentext);
  168. break;
  169. }
  170. }
  171. void
  172. dcelexinit(char* input, DCElexstate** lexstatep)
  173. {
  174. DCElexstate* lexstate = (DCElexstate*)malloc(sizeof(DCElexstate));
  175. if(lexstatep) *lexstatep = lexstate;
  176. if(lexstate == NULL) return;
  177. memset((void*)lexstate,0,sizeof(DCElexstate));
  178. lexstate->input = strdup(input);
  179. lexstate->next = lexstate->input;
  180. lexstate->yytext = ncbytesnew();
  181. lexstate->reclaim = nclistnew();
  182. }
  183. void
  184. dcelexcleanup(DCElexstate** lexstatep)
  185. {
  186. DCElexstate* lexstate = *lexstatep;
  187. if(lexstate == NULL) return;
  188. if(lexstate->input != NULL) free(lexstate->input);
  189. if(lexstate->reclaim != NULL) {
  190. while(nclistlength(lexstate->reclaim) > 0) {
  191. char* word = (char*)nclistpop(lexstate->reclaim);
  192. if(word) free(word);
  193. }
  194. nclistfree(lexstate->reclaim);
  195. }
  196. ncbytesfree(lexstate->yytext);
  197. free(lexstate);
  198. *lexstatep = NULL;
  199. }