/brlcad/tags/rel-6-0-1/libbu/lex.c

https://bitbucket.org/vrrm/brl-cad-copy-for-fast-history-browsing-in-git · C · 277 lines · 171 code · 12 blank · 94 comment · 97 complexity · 26417902d74a2585fd336cc1a332b973 MD5 · raw file

  1. /* R T L E X . C
  2. *
  3. * Author -
  4. * Christopher T. Johnson
  5. *
  6. * Source -
  7. * Geometric Solutions, Inc.
  8. *
  9. * Distribution Status -
  10. * Public Domain, Distribution Unlimited.
  11. */
  12. #ifndef lint
  13. static const char RCSid[] = "@(#)$Header$ (ARL)";
  14. #endif
  15. #include "conf.h"
  16. #include <stdio.h>
  17. #include <ctype.h>
  18. #include <string.h>
  19. #include "machine.h"
  20. #include "externs.h"
  21. #include "bu.h"
  22. static int bu_lex_reading_comment = 0;
  23. /*
  24. * B U _ L E X _ G E T O N E
  25. */
  26. static char *
  27. bu_lex_getone(used, rtstr)
  28. int *used;
  29. struct bu_vls *rtstr;
  30. {
  31. register char *cp;
  32. register char *sp;
  33. register char *unit;
  34. int number;
  35. number = 1;
  36. *used = 0;
  37. BU_CK_VLS(rtstr);
  38. cp = bu_vls_addr(rtstr);
  39. top:
  40. if (bu_lex_reading_comment) {
  41. for(;;) {
  42. register char tc;
  43. tc = *cp; cp++;
  44. if (!tc) {
  45. return 0;
  46. }
  47. if (tc != '*') continue;
  48. if (*cp != '/') continue;
  49. cp++; /* Skip the '/' */
  50. break;
  51. }
  52. bu_lex_reading_comment = 0;
  53. }
  54. /*
  55. * skip leading blanks
  56. */
  57. for (; *cp && isspace(*cp); cp++);
  58. /*
  59. * Is this a comment? '#' to end of line is.
  60. */
  61. if (!*cp || *cp == '#') {
  62. return 0;
  63. }
  64. /*
  65. * Is this a 'C' multi-line comment?
  66. */
  67. if (*cp == '/' && *(cp+1)=='*') {
  68. cp += 2;
  69. bu_lex_reading_comment = 1;
  70. goto top;
  71. }
  72. /*
  73. * cp points to the first non-blank character.
  74. */
  75. sp = cp; /* start pointer */
  76. while (*cp) {
  77. register char tc;
  78. tc = *cp; cp++;
  79. /*
  80. * Numbers come in the following forms
  81. * [0-9]*
  82. * [0-9]*.[0-9][0-9]*
  83. * [0-9]*.[0-9][0-9]*{e|E}{+|-}[0-9][0-9]*
  84. */
  85. if (number) {
  86. /*
  87. * We have not seen anything to make this NOT
  88. * a number.
  89. */
  90. if (isdigit(tc)) {
  91. if (number == 5 || number == 6) number = 7;
  92. if (number == 3) number = 4;
  93. if (number == 1) number = 2;
  94. continue;
  95. }
  96. if (number==2 && tc == '.') {
  97. /*
  98. * [0-9][0-9]*.
  99. */
  100. number = 3;
  101. continue;
  102. }
  103. if (number == 4 && (tc == 'e' || tc == 'E')) {
  104. /*
  105. * [0-9][0-9]*.[0-9][0-9]*{e|E}
  106. */
  107. number = 5;
  108. continue;
  109. }
  110. if (number == 5 && (tc == '+' || tc == '-')) {
  111. /*
  112. * [0-9][0-9]*.[0-9][0-9]*{e|E}{+|-}
  113. */
  114. number = 6;
  115. continue;
  116. }
  117. if (number == 3) break;
  118. number = 0;
  119. }
  120. if (!isalnum(tc) && tc != '.' && tc != '_') break;
  121. }
  122. if (number == 6) --cp; /* subtract off the + or - */
  123. if (number == 3) --cp; /* subtract off the . */
  124. /*
  125. * All spaces have been skipped. (sp)
  126. * if we had NUMBER. or NUMBERe{+|-} that has be replaced (cp)
  127. */
  128. *used = cp - sp -1;
  129. if (*used == 0) *used = 1;
  130. unit = (char *)bu_malloc(*used+1, "unit token");
  131. strncpy(unit,sp,*used);
  132. unit[*used] = '\0';
  133. *used = sp-bu_vls_addr(rtstr) + *used;
  134. if (*used == 0) *used = 1;
  135. return unit;
  136. }
  137. /*
  138. * B U _ L E X
  139. */
  140. int
  141. bu_lex(
  142. union bu_lex_token *token,
  143. struct bu_vls *rtstr,
  144. struct bu_lex_key *keywords,
  145. struct bu_lex_key *symbols)
  146. {
  147. char *unit;
  148. char *cp;
  149. int used;
  150. /*
  151. * get a unit of information from rtstr.
  152. */
  153. used = 0;
  154. unit = bu_lex_getone(&used, rtstr);
  155. /*
  156. * Was line empty or commented out.
  157. */
  158. if (!unit) {
  159. if (used) bu_bomb("bu_lex: Null unit, and something used.\n");
  160. return BU_LEX_NEED_MORE;
  161. }
  162. /*
  163. * Decide if this unit is a symbol, number or identifier.
  164. */
  165. if (isdigit(*unit)) {
  166. /*
  167. * Humm, this could be a number.
  168. * octal -- 0[0-7]*
  169. * hex -- 0x[0-9a-f]*
  170. * dec -- [0-9][0-9]*
  171. * dbl -- [0-9][0-9]*.[0-9]*{{E|e}{+|-}[0-9][0-9]*}
  172. */
  173. if (*unit == '0') { /* any of the above */
  174. /*
  175. * octal -- 0[0-7]*
  176. */
  177. for (cp=unit; *cp && *cp>='0' && *cp <='7'; cp++);
  178. if (!*cp) { /* We have an octal value */
  179. token->type = BU_LEX_INT;
  180. sscanf(unit,"%o", (unsigned int *)&token->t_int.value);
  181. bu_free(unit,"unit token");
  182. return used;
  183. }
  184. /*
  185. * if it is not an octal number, maybe it is
  186. * a hex number?"
  187. * hex -- 0x[0-9a-f]*
  188. */
  189. cp=unit+1;
  190. if (*cp == 'x' || *cp == 'X') {
  191. for(;*cp && isxdigit(*cp);cp++);
  192. if (!*cp) {
  193. token->type = BU_LEX_INT;
  194. sscanf(unit,"%x",(unsigned int *)&token->t_int.value);
  195. bu_free(unit, "unit token");
  196. return used;
  197. }
  198. }
  199. }
  200. /*
  201. * This could be a decimal number, a double or an identifier.
  202. * dec -- [0-9][0-9]*
  203. */
  204. for (cp=unit; *cp && isdigit(*cp); cp++);
  205. if (!*cp) {
  206. token->type = BU_LEX_INT;
  207. sscanf(unit,"%d", &token->t_int.value);
  208. bu_free(unit, "unit token");
  209. return used;
  210. }
  211. /*
  212. * if we are here, then this is either a double or
  213. * an identifier.
  214. * dbl -- [0-9][0-9]*.[0-9]*{{E|e}{+|-}[0-9][0-9]*}
  215. *
  216. * *cp should be a '.'
  217. */
  218. if (*cp == '.') {
  219. for(cp++;*cp &&isdigit(*cp);cp++);
  220. if (*cp == 'e' || *cp == 'E') cp++;
  221. if (*cp == '+' || *cp == '-') cp++;
  222. for(;*cp &&isdigit(*cp);cp++);
  223. if (!*cp) {
  224. token->type = BU_LEX_DOUBLE;
  225. sscanf(unit, "%lg", &token->t_dbl.value);
  226. bu_free(unit, "unit token");
  227. return used;
  228. }
  229. }
  230. /*
  231. * Oh well, I guess it was not a number. That means it
  232. * must be something else.
  233. */
  234. }
  235. /*
  236. * We either have an identifier, keyword, or symbol.
  237. */
  238. if (symbols) {
  239. if (!*(unit+1) ) { /* single character, good choice for a symbol. */
  240. register struct bu_lex_key *sp;
  241. for (sp=symbols;sp->tok_val;sp++) {
  242. if (*sp->string == *unit) {
  243. token->type = BU_LEX_SYMBOL;
  244. token->t_key.value = sp->tok_val;
  245. bu_free(unit, "unit token");
  246. return used;
  247. }
  248. }
  249. }
  250. }
  251. if (keywords) {
  252. register struct bu_lex_key *kp;
  253. for (kp=keywords;kp->tok_val; kp++) {
  254. if (strcmp(kp->string, unit) == 0) {
  255. token->type = BU_LEX_KEYWORD;
  256. token->t_key.value = kp->tok_val;
  257. bu_free(unit, "unit token");
  258. return used;
  259. }
  260. }
  261. }
  262. token->type = BU_LEX_IDENT;
  263. token->t_id.value = unit;
  264. return used;
  265. }