Kannel: Open Source WAP and SMS gateway  $Revision: 5037 $
wslexer.c File Reference
#include "wsint.h"
#include "wsstree.h"
#include "wsgram.h"

Go to the source code of this file.

Macros

#define WS_IS_DECIMAL_DIGIT(ch)   ('0' <= (ch) && (ch) <= '9')
 
#define WS_DECIMAL_TO_INT(ch)   ((ch) - '0')
 
#define WS_IS_NON_ZERO_DIGIT(ch)   ('1' <= (ch) && (ch) <= '9')
 
#define WS_IS_OCTAL_DIGIT(ch)   ('0' <= (ch) && (ch) <= '7')
 
#define WS_OCTAL_TO_INT(ch)   ((ch) - '0')
 
#define WS_IS_HEX_DIGIT(ch)
 
#define WS_HEX_TO_INT(ch)
 
#define WS_IS_IDENTIFIER_LETTER(ch)
 
#define N(n)   n, sizeof(n) - 1
 

Functions

static WsBool lookup_keyword (char *id, size_t len, int *token_return)
 
static WsUInt32 buffer_to_int (WsCompilerPtr compiler, WsBuffer *buffer)
 
static WsBool read_float_from_point (WsCompiler *compiler, WsBuffer *buffer, WsFloat *result)
 
static WsBool read_float_from_exp (WsCompiler *compiler, WsBuffer *buffer, WsFloat *result)
 
int ws_yy_lex (YYSTYPE *yylval, YYLTYPE *yylloc, void *context)
 

Variables

struct {
   char *   name
 
   size_t   name_len
 
   int   token
 
keywords []
 
static int num_keywords = sizeof(keywords) / sizeof(keywords[0])
 

Macro Definition Documentation

#define N (   n)    n, sizeof(n) - 1

Definition at line 149 of file wslexer.c.

#define WS_DECIMAL_TO_INT (   ch)    ((ch) - '0')

Definition at line 81 of file wslexer.c.

#define WS_HEX_TO_INT (   ch)
Value:
('0' <= (ch) && (ch) <= '9' \
? ((ch) - '0') \
: ('a' <= (ch) && (ch) <= 'f' \
? ((ch) - 'a' + 10) \
: (ch) - 'A' + 10))

Definition at line 99 of file wslexer.c.

Referenced by ws_yy_lex().

#define WS_IS_DECIMAL_DIGIT (   ch)    ('0' <= (ch) && (ch) <= '9')

Definition at line 78 of file wslexer.c.

Referenced by read_float_from_exp(), read_float_from_point(), and ws_yy_lex().

#define WS_IS_HEX_DIGIT (   ch)
Value:
(('0' <= (ch) && (ch) <= '9') \
|| ('a' <= (ch) && (ch) <= 'f') \
|| ('A' <= (ch) && (ch) <= 'F'))

Definition at line 94 of file wslexer.c.

Referenced by ws_yy_lex().

#define WS_IS_IDENTIFIER_LETTER (   ch)
Value:
(('a' <= (ch) && (ch) <= 'z') \
|| ('A' <= (ch) && (ch) <= 'Z') \
|| (ch) == '_')

Definition at line 108 of file wslexer.c.

Referenced by ws_yy_lex().

#define WS_IS_NON_ZERO_DIGIT (   ch)    ('1' <= (ch) && (ch) <= '9')

Definition at line 85 of file wslexer.c.

Referenced by ws_yy_lex().

#define WS_IS_OCTAL_DIGIT (   ch)    ('0' <= (ch) && (ch) <= '7')

Definition at line 88 of file wslexer.c.

Referenced by ws_yy_lex().

#define WS_OCTAL_TO_INT (   ch)    ((ch) - '0')

Definition at line 91 of file wslexer.c.

Referenced by ws_yy_lex().

Function Documentation

static WsUInt32 buffer_to_int ( WsCompilerPtr  compiler,
WsBuffer buffer 
)
static

Definition at line 909 of file wslexer.c.

References ws_buffer_append_space(), ws_buffer_ptr(), ws_error_memory(), WS_INT32_MAX, and ws_src_error().

Referenced by ws_yy_lex().

910 {
911  unsigned char *p;
912  unsigned long value;
913 
914  /* Terminate the string. */
915  if (!ws_buffer_append_space(buffer, &p, 1)) {
916  ws_error_memory(compiler);
917  return 0;
918  }
919  p[0] = '\0';
920 
921  /* Convert the buffer into an integer number. The base is taken
922  from the bufer. */
923  errno = 0;
924  value = strtoul((char *) ws_buffer_ptr(buffer), NULL, 0);
925 
926  /* Check for overflow. We accept WS_INT32_MAX + 1 because we might
927  * be parsing the numeric part of '-2147483648'. */
928  if (errno == ERANGE || value > (WsUInt32) WS_INT32_MAX + 1)
929  ws_src_error(compiler, 0, "integer literal too large");
930 
931  /* All done. */
932  return (WsUInt32) value;
933 }
unsigned long WsUInt32
Definition: wsint.h:122
#define WS_INT32_MAX
Definition: wsint.h:109
WsBool ws_buffer_append_space(WsBuffer *buffer, unsigned char **p, size_t size)
Definition: wsbuffer.c:115
void ws_src_error(WsCompilerPtr compiler, WsUInt32 line, char *message,...)
Definition: wserror.c:145
void ws_error_memory(WsCompilerPtr compiler)
Definition: wserror.c:107
unsigned char * ws_buffer_ptr(WsBuffer *buffer)
Definition: wsbuffer.c:133
static WsBool lookup_keyword ( char *  id,
size_t  len,
int *  token_return 
)
static

Definition at line 876 of file wslexer.c.

References keywords, name, name_len, num_keywords, WS_FALSE, and WS_TRUE.

Referenced by ws_yy_lex().

877 {
878  int left = 0, center, right = num_keywords;
879 
880  while (left < right) {
881  size_t l;
882  int result;
883 
884  center = left + (right - left) / 2;
885 
886  l = keywords[center].name_len;
887  if (len < l)
888  l = len;
889 
890  result = memcmp(id, keywords[center].name, l);
891  if (result < 0 || (result == 0 && len < keywords[center].name_len))
892  /* The possible match is smaller. */
893  right = center;
894  else if (result > 0 || (result == 0 && len > keywords[center].name_len))
895  /* The possible match is bigger. */
896  left = center + 1;
897  else {
898  /* Found a match. */
899  *token_return = keywords[center].token;
900  return WS_TRUE;
901  }
902  }
903 
904  /* No match. */
905  return WS_FALSE;
906 }
size_t name_len
Definition: wslexer.c:156
Definition: wsint.h:131
static int num_keywords
Definition: wslexer.c:217
static struct @117 keywords[]
char * name
Definition: wslexer.c:155
static WsBool read_float_from_exp ( WsCompiler compiler,
WsBuffer buffer,
WsFloat result 
)
static

Definition at line 959 of file wslexer.c.

References WsCompilerRec::input, ws_buffer_append_space(), ws_buffer_ptr(), ws_error_memory(), WS_FALSE, ws_ieee754_encode_single(), WS_IEEE754_OK, WS_IS_DECIMAL_DIGIT, ws_src_error(), ws_stream_getc(), ws_stream_ungetc(), and WS_TRUE.

Referenced by read_float_from_point(), and ws_yy_lex().

961 {
962  WsUInt32 ch;
963  unsigned char *p;
964  int sign = '+';
965  unsigned char buf[4];
966 
967  /* Do we have an exponent part. */
968  if (!ws_stream_getc(compiler->input, &ch))
969  goto done;
970  if (ch != 'e' && ch != 'E') {
971  /* No exponent part. */
972  ws_stream_ungetc(compiler->input, ch);
973  goto done;
974  }
975 
976  /* Sign. */
977  if (!ws_stream_getc(compiler->input, &ch)) {
978  /* This is an error. */
979  ws_src_error(compiler, 0, "truncated float literal");
980  return WS_FALSE;
981  }
982  if (ch == '-')
983  sign = '-';
984  else if (ch == '+')
985  sign = '+';
986  else
987  ws_stream_ungetc(compiler->input, ch);
988 
989  /* DecimalDigits. */
990  if (!ws_stream_getc(compiler->input, &ch)) {
991  ws_src_error(compiler, 0, "truncated float literal");
992  return WS_FALSE;
993  }
994  if (!WS_IS_DECIMAL_DIGIT(ch)) {
995  ws_src_error(compiler, 0, "no decimal digits in exponent part");
996  return WS_FALSE;
997  }
998 
999  /* Append exponent part read so far. */
1000  if (!ws_buffer_append_space(buffer, &p, 2)) {
1001  ws_error_memory(compiler);
1002  return WS_FALSE;
1003  }
1004  p[0] = 'e';
1005  p[1] = sign;
1006 
1007  /* Read decimal digits. */
1008  while (WS_IS_DECIMAL_DIGIT(ch)) {
1009  if (!ws_buffer_append_space(buffer, &p, 1)) {
1010  ws_error_memory(compiler);
1011  return WS_FALSE;
1012  }
1013  p[0] = (unsigned char) ch;
1014 
1015  if (!ws_stream_getc(compiler->input, &ch))
1016  /* EOF. This is ok. */
1017  goto done;
1018  }
1019  /* Unget the extra character. */
1020  ws_stream_ungetc(compiler->input, ch);
1021 
1022  /* FALLTHROUGH */
1023 
1024 done:
1025 
1026  if (!ws_buffer_append_space(buffer, &p, 1)) {
1027  ws_error_memory(compiler);
1028  return WS_FALSE;
1029  }
1030  p[0] = 0;
1031 
1032  /* Now the buffer contains a valid floating point number. */
1033  *result = (WsFloat) strtod((char *) ws_buffer_ptr(buffer), NULL);
1034 
1035  /* Check that the generated floating point number fits to
1036  `float32'. */
1037  if (*result == HUGE_VAL || *result == -HUGE_VAL
1038  || ws_ieee754_encode_single(*result, buf) != WS_IEEE754_OK)
1039  ws_src_error(compiler, 0, "floating point literal too large");
1040 
1041  return WS_TRUE;
1042 }
Definition: wsint.h:131
unsigned long WsUInt32
Definition: wsint.h:122
double WsFloat
Definition: wsint.h:126
WsStream * input
Definition: wsint.h:196
WsBool ws_stream_getc(WsStream *stream, WsUInt32 *ch_return)
Definition: wsstream.c:74
WsIeee754Result ws_ieee754_encode_single(double value, unsigned char *buf)
Definition: wsieee754.c:94
void ws_stream_ungetc(WsStream *stream, WsUInt32 ch)
Definition: wsstream.c:101
#define WS_IS_DECIMAL_DIGIT(ch)
Definition: wslexer.c:78
WsBool ws_buffer_append_space(WsBuffer *buffer, unsigned char **p, size_t size)
Definition: wsbuffer.c:115
void ws_src_error(WsCompilerPtr compiler, WsUInt32 line, char *message,...)
Definition: wserror.c:145
void ws_error_memory(WsCompilerPtr compiler)
Definition: wserror.c:107
unsigned char * ws_buffer_ptr(WsBuffer *buffer)
Definition: wsbuffer.c:133
static WsBool read_float_from_point ( WsCompiler compiler,
WsBuffer buffer,
WsFloat result 
)
static

Definition at line 936 of file wslexer.c.

References WsCompilerRec::input, read_float_from_exp(), ws_buffer_append_space(), ws_error_memory(), WS_FALSE, WS_IS_DECIMAL_DIGIT, ws_stream_getc(), and ws_stream_ungetc().

Referenced by ws_yy_lex().

938 {
939  WsUInt32 ch;
940  unsigned char *p;
941 
942  while (ws_stream_getc(compiler->input, &ch)) {
943  if (WS_IS_DECIMAL_DIGIT(ch)) {
944  if (!ws_buffer_append_space(buffer, &p, 1)) {
945  ws_error_memory(compiler);
946  return WS_FALSE;
947  }
948  p[0] = (unsigned char) ch;
949  } else {
950  ws_stream_ungetc(compiler->input, ch);
951  break;
952  }
953  }
954 
955  return read_float_from_exp(compiler, buffer, result);
956 }
unsigned long WsUInt32
Definition: wsint.h:122
WsStream * input
Definition: wsint.h:196
WsBool ws_stream_getc(WsStream *stream, WsUInt32 *ch_return)
Definition: wsstream.c:74
void ws_stream_ungetc(WsStream *stream, WsUInt32 ch)
Definition: wsstream.c:101
#define WS_IS_DECIMAL_DIGIT(ch)
Definition: wslexer.c:78
WsBool ws_buffer_append_space(WsBuffer *buffer, unsigned char **p, size_t size)
Definition: wsbuffer.c:115
static WsBool read_float_from_exp(WsCompiler *compiler, WsBuffer *buffer, WsFloat *result)
Definition: wslexer.c:959
void ws_error_memory(WsCompilerPtr compiler)
Definition: wserror.c:107
int ws_yy_lex ( YYSTYPE yylval,
YYLTYPE yylloc,
void *  context 
)

Definition at line 221 of file wslexer.c.

References buffer_to_int(), COMPILER_MAGIC, YYLTYPE::first_line, gw_assert(), YYSTYPE::identifier, WsCompilerRec::input, YYSTYPE::integer, WsCompilerRec::linenum, lookup_keyword(), WsCompilerRec::magic, read_float_from_exp(), read_float_from_point(), YYSTYPE::string, tADDA, tAND, tANDA, tDIVA, tEQ, tFLOAT, tGE, tIDENTIFIER, tIDIV, tIDIVA, tINTEGER, tLE, tLSHIFT, tLSHIFTA, tMINUSMINUS, tMULA, tNE, token, tOR, tORA, tPLUSPLUS, tREMA, tRSSHIFT, tRSSHIFTA, tRSZSHIFT, tRSZSHIFTA, tSTRING, tSUBA, tXORA, type, YYSTYPE::vfloat, ws_buffer_append_space(), ws_buffer_init(), ws_buffer_len(), ws_buffer_uninit(), ws_error_memory(), ws_free(), WS_HEX_TO_INT, WS_IS_DECIMAL_DIGIT, WS_IS_HEX_DIGIT, WS_IS_IDENTIFIER_LETTER, WS_IS_NON_ZERO_DIGIT, WS_IS_OCTAL_DIGIT, ws_lexer_register_block(), ws_lexer_register_utf8(), ws_malloc(), WS_OCTAL_TO_INT, ws_realloc(), ws_src_error(), ws_stream_getc(), ws_stream_ungetc(), ws_utf8_alloc(), ws_utf8_append_char(), and ws_utf8_free().

222 {
223  WsCompiler *compiler = (WsCompiler *) context;
224  WsUInt32 ch, ch2;
225  WsBuffer buffer;
226  unsigned char *p;
227  WsBool success;
228 
229  /* Just check that we get the correct amount of arguments. */
230  gw_assert(compiler->magic == COMPILER_MAGIC);
231 
232  while (ws_stream_getc(compiler->input, &ch)) {
233  /* Save the token's line number. */
234  yylloc->first_line = compiler->linenum;
235 
236  switch (ch) {
237  case '\t': /* Whitespace characters. */
238  case '\v':
239  case '\f':
240  case ' ':
241  continue;
242 
243  case '\n': /* Line terminators. */
244  case '\r':
245  if (ch == '\r' && ws_stream_getc(compiler->input, &ch2)) {
246  if (ch2 != '\n')
247  ws_stream_ungetc(compiler->input, ch2);
248  }
249  compiler->linenum++;
250  continue;
251 
252  case '!': /* !, != */
253  if (ws_stream_getc(compiler->input, &ch2)) {
254  if (ch2 == '=')
255  return tNE;
256 
257  ws_stream_ungetc(compiler->input, ch2);
258  }
259  return '!';
260 
261  case '%': /* %, %= */
262  if (ws_stream_getc(compiler->input, &ch2)) {
263  if (ch2 == '=')
264  return tREMA;
265 
266  ws_stream_ungetc(compiler->input, ch2);
267  }
268  return '%';
269 
270  case '&': /* &, &&, &= */
271  if (ws_stream_getc(compiler->input, &ch2)) {
272  if (ch2 == '&')
273  return tAND;
274  if (ch2 == '=')
275  return tANDA;
276 
277  ws_stream_ungetc(compiler->input, ch2);
278  }
279  return '&';
280 
281  case '*': /* *, *= */
282  if (ws_stream_getc(compiler->input, &ch2)) {
283  if (ch2 == '=')
284  return tMULA;
285 
286  ws_stream_ungetc(compiler->input, ch2);
287  }
288  return '*';
289 
290  case '+': /* +, ++, += */
291  if (ws_stream_getc(compiler->input, &ch2)) {
292  if (ch2 == '+')
293  return tPLUSPLUS;
294  if (ch2 == '=')
295  return tADDA;
296 
297  ws_stream_ungetc(compiler->input, ch2);
298  }
299  return '+';
300 
301  case '-': /* -, --, -= */
302  if (ws_stream_getc(compiler->input, &ch2)) {
303  if (ch2 == '-')
304  return tMINUSMINUS;
305  if (ch2 == '=')
306  return tSUBA;
307 
308  ws_stream_ungetc(compiler->input, ch2);
309  }
310  return '-';
311 
312  case '.':
313  if (ws_stream_getc(compiler->input, &ch2)) {
314  if (WS_IS_DECIMAL_DIGIT(ch2)) {
315  /* DecimalFloatLiteral. */
316  ws_buffer_init(&buffer);
317 
318  if (!ws_buffer_append_space(&buffer, &p, 2)) {
319  ws_error_memory(compiler);
320  ws_buffer_uninit(&buffer);
321  return EOF;
322  }
323 
324  p[0] = '.';
325  p[1] = (unsigned char) ch2;
326 
327  success = read_float_from_point(compiler, &buffer,
328  &yylval->vfloat);
329  ws_buffer_uninit(&buffer);
330 
331  if (!success)
332  return EOF;
333 
334  return tFLOAT;
335  }
336 
337  ws_stream_ungetc(compiler->input, ch2);
338  }
339  return '.';
340 
341  case '/': /* /, /=, block or a single line comment */
342  if (ws_stream_getc(compiler->input, &ch2)) {
343  if (ch2 == '*') {
344  /* Block comment. */
345  while (1) {
346  if (!ws_stream_getc(compiler->input, &ch)) {
347  ws_src_error(compiler, 0, "EOF in comment");
348  return EOF;
349  }
350 
351  if (ch == '\n' || ch == '\r') {
352  /* Line terminators. */
353  if (ch == '\r' && ws_stream_getc(compiler->input,
354  &ch2)) {
355  if (ch2 != '\n')
356  ws_stream_ungetc(compiler->input, ch2);
357  }
358  compiler->linenum++;
359 
360  /* Continue reading the block comment. */
361  continue;
362  }
363 
364  if (ch == '*' && ws_stream_getc(compiler->input, &ch2)) {
365  if (ch2 == '/')
366  /* The end of the comment found. */
367  break;
368  ws_stream_ungetc(compiler->input, ch2);
369  }
370  }
371  /* Continue after the comment. */
372  continue;
373  }
374  if (ch2 == '/') {
375  /* Single line comment. */
376  while (1) {
377  if (!ws_stream_getc(compiler->input, &ch))
378  /* The end of input stream reached. We accept
379  this as a valid comment terminator. */
380  break;
381 
382  if (ch == '\n' || ch == '\r') {
383  /* Line terminators. */
384  if (ch == '\r' && ws_stream_getc(compiler->input,
385  &ch2)) {
386  if (ch2 != '\n')
387  ws_stream_ungetc(compiler->input, ch2);
388  }
389  /* The end of the line (and the comment)
390  reached. */
391  compiler->linenum++;
392  break;
393  }
394  }
395  /* Continue after the comment. */
396  continue;
397  }
398  if (ch2 == '=')
399  return tDIVA;
400 
401  ws_stream_ungetc(compiler->input, ch2);
402  }
403  return '/';
404 
405  case '<': /* <, <<, <<=, <= */
406  if (ws_stream_getc(compiler->input, &ch2)) {
407  if (ch2 == '<') {
408  if (ws_stream_getc(compiler->input, &ch2)) {
409  if (ch2 == '=')
410  return tLSHIFTA;
411 
412  ws_stream_ungetc(compiler->input, ch2);
413  }
414  return tLSHIFT;
415  }
416  if (ch2 == '=')
417  return tLE;
418 
419  ws_stream_ungetc(compiler->input, ch2);
420  }
421  return '<';
422 
423  case '=': /* =, == */
424  if (ws_stream_getc(compiler->input, &ch2)) {
425  if (ch2 == '=')
426  return tEQ;
427 
428  ws_stream_ungetc(compiler->input, ch2);
429  }
430  return '=';
431 
432  case '>': /* >, >=, >>, >>=, >>>, >>>= */
433  if (ws_stream_getc(compiler->input, &ch2)) {
434  if (ch2 == '>') {
435  if (ws_stream_getc(compiler->input, &ch2)) {
436  if (ch2 == '>') {
437  if (ws_stream_getc(compiler->input, &ch2)) {
438  if (ch2 == '=')
439  return tRSZSHIFTA;
440 
441  ws_stream_ungetc(compiler->input, ch2);
442  }
443  return tRSZSHIFT;
444  }
445  if (ch2 == '=')
446  return tRSSHIFTA;
447 
448  ws_stream_ungetc(compiler->input, ch2);
449  }
450  return tRSSHIFT;
451  }
452  if (ch2 == '=')
453  return tGE;
454 
455  ws_stream_ungetc(compiler->input, ch2);
456  }
457  return '>';
458 
459  case '^': /* ^, ^= */
460  if (ws_stream_getc(compiler->input, &ch2)) {
461  if (ch2 == '=')
462  return tXORA;
463 
464  ws_stream_ungetc(compiler->input, ch2);
465  }
466  return '^';
467 
468  case '|': /* |, |=, || */
469  if (ws_stream_getc(compiler->input, &ch2)) {
470  if (ch2 == '=')
471  return tORA;
472  if (ch2 == '|')
473  return tOR;
474 
475  ws_stream_ungetc(compiler->input, ch2);
476  }
477  return '|';
478 
479  case '#': /* The simple cases. */
480  case '(':
481  case ')':
482  case ',':
483  case ':':
484  case ';':
485  case '?':
486  case '{':
487  case '}':
488  case '~':
489  return (int) ch;
490 
491  case '\'': /* String literals. */
492  case '"':
493  {
494  WsUInt32 string_end_ch = ch;
495  WsUtf8String *str = ws_utf8_alloc();
496 
497  if (str == NULL) {
498  ws_error_memory(compiler);
499  return EOF;
500  }
501 
502  while (1) {
503  if (!ws_stream_getc(compiler->input, &ch)) {
504 eof_in_string_literal:
505  ws_src_error(compiler, 0, "EOF in string literal");
506  ws_utf8_free(str);
507  return EOF;
508  }
509  if (ch == string_end_ch)
510  /* The end of string reached. */
511  break;
512 
513  if (ch == '\\') {
514  /* An escape sequence. */
515  if (!ws_stream_getc(compiler->input, &ch))
516  goto eof_in_string_literal;
517 
518  switch (ch) {
519  case '\'':
520  case '"':
521  case '\\':
522  case '/':
523  /* The character as-is. */
524  break;
525 
526  case 'b':
527  ch = '\b';
528  break;
529 
530  case 'f':
531  ch = '\f';
532  break;
533 
534  case 'n':
535  ch = '\n';
536  break;
537 
538  case 'r':
539  ch = '\r';
540  break;
541 
542  case 't':
543  ch = '\t';
544  break;
545 
546  case 'x':
547  case 'u':
548  {
549  int i, len;
550  int type = ch;
551 
552  if (ch == 'x')
553  len = 2;
554  else
555  len = 4;
556 
557  ch = 0;
558  for (i = 0; i < len; i++) {
559  if (!ws_stream_getc(compiler->input, &ch2))
560  goto eof_in_string_literal;
561  if (!WS_IS_HEX_DIGIT(ch2)) {
562  ws_src_error(compiler, 0,
563  "malformed `\\%c' escape in "
564  "string literal", (char) type);
565  ch = 0;
566  break;
567  }
568  ch *= 16;
569  ch += WS_HEX_TO_INT(ch2);
570  }
571  }
572  break;
573 
574  default:
575  if (WS_IS_OCTAL_DIGIT(ch)) {
576  int i;
577  int limit = 3;
578 
579  ch = WS_OCTAL_TO_INT(ch);
580  if (ch > 3)
581  limit = 2;
582 
583  for (i = 1; i < limit; i++) {
584  if (!ws_stream_getc(compiler->input, &ch2))
585  goto eof_in_string_literal;
586  if (!WS_IS_OCTAL_DIGIT(ch2)) {
587  ws_stream_ungetc(compiler->input, ch2);
588  break;
589  }
590 
591  ch *= 8;
592  ch += WS_OCTAL_TO_INT(ch2);
593  }
594  } else {
595  ws_src_error(compiler, 0,
596  "unknown escape sequence `\\%c' in "
597  "string literal", (char) ch);
598  ch = 0;
599  }
600  break;
601  }
602  /* FALLTHROUGH */
603  }
604 
605  if (!ws_utf8_append_char(str, ch)) {
606  ws_error_memory(compiler);
607  ws_utf8_free(str);
608  return EOF;
609  }
610  }
611 
612  if (!ws_lexer_register_utf8(compiler, str)) {
613  ws_error_memory(compiler);
614  ws_utf8_free(str);
615  return EOF;
616  }
617 
618  gw_assert(str != NULL);
619  yylval->string = str;
620 
621  return tSTRING;
622  }
623  break;
624 
625  default:
626  /* Identifiers, keywords and number constants. */
627 
628  if (WS_IS_IDENTIFIER_LETTER(ch)) {
629  WsBool got;
630  int token;
631  unsigned char *p;
632  unsigned char *np;
633  size_t len = 0;
634 
635  /* An identifier or a keyword. We start with a 256
636  * bytes long buffer but it is expanded dynamically if
637  * needed. However, 256 should be enought for most
638  * cases since the byte-code format limits the function
639  * names to 255 characters. */
640  p = ws_malloc(256);
641  if (p == NULL) {
642  ws_error_memory(compiler);
643  return EOF;
644  }
645 
646  do {
647  /* Add one extra for the possible terminator
648  character. */
649  np = ws_realloc(p, len + 2);
650  if (np == NULL) {
651  ws_error_memory(compiler);
652  ws_free(p);
653  return EOF;
654  }
655 
656  p = np;
657 
658  /* This is ok since the only valid identifier names
659  * can be written in 7 bit ASCII. */
660  p[len++] = (unsigned char) ch;
661  } while ((got = ws_stream_getc(compiler->input, &ch))
663  || WS_IS_DECIMAL_DIGIT(ch)));
664 
665  if (got)
666  /* Put back the terminator character. */
667  ws_stream_ungetc(compiler->input, ch);
668 
669  /* Is it a keyword? */
670  if (lookup_keyword((char *) p, len, &token)) {
671  /* Yes it is... */
672  ws_free(p);
673 
674  /* ...except one case: `div='. */
675  if (token == tIDIV) {
676  if (ws_stream_getc(compiler->input, &ch)) {
677  if (ch == '=')
678  return tIDIVA;
679 
680  ws_stream_ungetc(compiler->input, ch);
681  }
682  }
683 
684  /* Return the token value. */
685  return token;
686  }
687 
688  /* It is a normal identifier. Let's pad the name with a
689  null-character. We have already allocated space for
690  it. */
691  p[len] = '\0';
692 
693  if (!ws_lexer_register_block(compiler, p)) {
694  ws_error_memory(compiler);
695  ws_free(p);
696  return EOF;
697  }
698 
699  gw_assert(p != NULL);
700  yylval->identifier = (char *) p;
701 
702  return tIDENTIFIER;
703  }
704 
705  if (WS_IS_NON_ZERO_DIGIT(ch)) {
706  /* A decimal integer literal or a decimal float
707  literal. */
708 
709  ws_buffer_init(&buffer);
710  if (!ws_buffer_append_space(&buffer, &p, 1)) {
711 number_error_memory:
712  ws_error_memory(compiler);
713  ws_buffer_uninit(&buffer);
714  return EOF;
715  }
716  p[0] = ch;
717 
718  while (ws_stream_getc(compiler->input, &ch)) {
719  if (WS_IS_DECIMAL_DIGIT(ch)) {
720  if (!ws_buffer_append_space(&buffer, &p, 1))
721  goto number_error_memory;
722  p[0] = ch;
723  } else if (ch == '.' || ch == 'e' || ch == 'E') {
724  /* DecimalFloatLiteral. */
725  if (ch == '.') {
726  if (!ws_buffer_append_space(&buffer, &p, 1))
727  goto number_error_memory;
728  p[0] = '.';
729 
730  success = read_float_from_point(compiler, &buffer,
731  &yylval->vfloat);
732  } else {
733  ws_stream_ungetc(compiler->input, ch);
734 
735  success = read_float_from_exp(compiler, &buffer,
736  &yylval->vfloat);
737  }
738  ws_buffer_uninit(&buffer);
739 
740  if (!success)
741  return EOF;
742 
743  return tFLOAT;
744  } else {
745  ws_stream_ungetc(compiler->input, ch);
746  break;
747  }
748  }
749 
750  /* Now the buffer contains an integer number as a
751  string. Let's convert it to an integer number. */
752  yylval->integer = buffer_to_int(compiler, &buffer);
753  ws_buffer_uninit(&buffer);
754 
755  /* Read a DecimalIntegerLiteral. */
756  return tINTEGER;
757  }
758 
759  if (ch == '0') {
760  /* The integer constant 0, an octal number or a
761  HexIntegerLiteral. */
762  if (ws_stream_getc(compiler->input, &ch2)) {
763  if (ch2 == 'x' || ch2 == 'X') {
764  /* HexIntegerLiteral. */
765 
766  ws_buffer_init(&buffer);
767  if (!ws_buffer_append_space(&buffer, &p, 2))
768  goto number_error_memory;
769 
770  p[0] = '0';
771  p[1] = 'x';
772 
773  while (ws_stream_getc(compiler->input, &ch)) {
774  if (WS_IS_HEX_DIGIT(ch)) {
775  if (!ws_buffer_append_space(&buffer, &p, 1))
776  goto number_error_memory;
777  p[0] = ch;
778  } else {
779  ws_stream_ungetc(compiler->input, ch);
780  break;
781  }
782  }
783 
784  if (ws_buffer_len(&buffer) == 2) {
785  ws_buffer_uninit(&buffer);
786  ws_src_error(compiler, 0,
787  "numeric constant with no digits");
788  yylval->integer = 0;
789  return tINTEGER;
790  }
791 
792  /* Now the buffer contains an integer number as
793  * a string. Let's convert it to an integer
794  * number. */
795  yylval->integer = buffer_to_int(compiler, &buffer);
796  ws_buffer_uninit(&buffer);
797 
798  /* Read a HexIntegerLiteral. */
799  return tINTEGER;
800  }
801  if (WS_IS_OCTAL_DIGIT(ch2)) {
802  /* OctalIntegerLiteral. */
803 
804  ws_buffer_init(&buffer);
805  if (!ws_buffer_append_space(&buffer, &p, 2))
806  goto number_error_memory;
807 
808  p[0] = '0';
809  p[1] = ch2;
810 
811  while (ws_stream_getc(compiler->input, &ch)) {
812  if (WS_IS_OCTAL_DIGIT(ch)) {
813  if (!ws_buffer_append_space(&buffer, &p, 1))
814  goto number_error_memory;
815  p[0] = ch;
816  } else {
817  ws_stream_ungetc(compiler->input, ch);
818  break;
819  }
820  }
821 
822  /* Convert the buffer into an intger number. */
823  yylval->integer = buffer_to_int(compiler, &buffer);
824  ws_buffer_uninit(&buffer);
825 
826  /* Read an OctalIntegerLiteral. */
827  return tINTEGER;
828  }
829  if (ch2 == '.' || ch2 == 'e' || ch2 == 'E') {
830  /* DecimalFloatLiteral. */
831  ws_buffer_init(&buffer);
832 
833  if (ch2 == '.') {
834  if (!ws_buffer_append_space(&buffer, &p, 1))
835  goto number_error_memory;
836  p[0] = '.';
837 
838  success = read_float_from_point(compiler, &buffer,
839  &yylval->vfloat);
840  } else {
841  ws_stream_ungetc(compiler->input, ch);
842 
843  success = read_float_from_exp(compiler, &buffer,
844  &yylval->vfloat);
845  }
846  ws_buffer_uninit(&buffer);
847 
848  if (!success)
849  return EOF;
850 
851  return tFLOAT;
852  }
853 
854  ws_stream_ungetc(compiler->input, ch2);
855  }
856 
857  /* Integer literal 0. */
858  yylval->integer = 0;
859  return tINTEGER;
860  }
861 
862  /* Garbage found from the input stream. */
863  ws_src_error(compiler, 0,
864  "garbage found from the input stream: character=0x%x",
865  ch);
866  return EOF;
867  break;
868  }
869  }
870 
871  return EOF;
872 }
WsUtf8String * string
Definition: wsgram.c:308
static WsBool lookup_keyword(char *id, size_t len, int *token_return)
Definition: wslexer.c:876
#define tPLUSPLUS
Definition: wsgram.c:230
Definition: parse.c:65
unsigned long WsUInt32
Definition: wsint.h:122
#define tDIVA
Definition: wsgram.c:238
void ws_free(void *ptr)
Definition: wsalloc.c:139
#define tRSSHIFT
Definition: wsgram.c:233
#define tRSZSHIFTA
Definition: wsgram.c:245
WsUInt32 magic
Definition: wsint.h:190
WsStream * input
Definition: wsint.h:196
#define WS_IS_HEX_DIGIT(ch)
Definition: wslexer.c:94
#define tGE
Definition: wsgram.c:226
#define tAND
Definition: wsgram.c:228
int type
Definition: smsc_cimd2.c:215
WsBool ws_stream_getc(WsStream *stream, WsUInt32 *ch_return)
Definition: wsstream.c:74
size_t ws_buffer_len(WsBuffer *buffer)
Definition: wsbuffer.c:139
void * ws_realloc(void *ptr, size_t size)
Definition: wsalloc.c:89
void ws_utf8_free(WsUtf8String *string)
Definition: wsutf8.c:188
static WsBool read_float_from_point(WsCompiler *compiler, WsBuffer *buffer, WsFloat *result)
Definition: wslexer.c:936
#define tRSSHIFTA
Definition: wsgram.c:244
#define tREMA
Definition: wsgram.c:242
WsUInt32 linenum
Definition: wsint.h:201
#define tLSHIFTA
Definition: wsgram.c:243
#define tOR
Definition: wsgram.c:229
WsBool ws_lexer_register_utf8(WsCompiler *compiler, WsUtf8String *string)
Definition: ws.c:267
int ws_utf8_append_char(WsUtf8String *string, unsigned long ch)
Definition: wsutf8.c:198
WsUtf8String * ws_utf8_alloc()
Definition: wsutf8.c:182
#define tIDIVA
Definition: wsgram.c:175
int token
Definition: wslexer.c:157
void ws_stream_ungetc(WsStream *stream, WsUInt32 ch)
Definition: wsstream.c:101
#define tFLOAT
Definition: wsgram.c:167
WsUInt32 integer
Definition: wsgram.c:305
#define WS_OCTAL_TO_INT(ch)
Definition: wslexer.c:91
#define WS_IS_DECIMAL_DIGIT(ch)
Definition: wslexer.c:78
void ws_buffer_init(WsBuffer *buffer)
Definition: wsbuffer.c:74
int first_line
Definition: wsgram.c:331
#define tEQ
Definition: wsgram.c:224
#define tMULA
Definition: wsgram.c:237
#define WS_IS_OCTAL_DIGIT(ch)
Definition: wslexer.c:88
#define tNE
Definition: wsgram.c:227
#define tSUBA
Definition: wsgram.c:236
#define WS_HEX_TO_INT(ch)
Definition: wslexer.c:99
gw_assert(wtls_machine->packet_to_send!=NULL)
void ws_buffer_uninit(WsBuffer *buffer)
Definition: wsbuffer.c:81
#define tLE
Definition: wsgram.c:225
#define tMINUSMINUS
Definition: wsgram.c:231
WsBool
Definition: wsint.h:128
WsBool ws_lexer_register_block(WsCompiler *compiler, void *ptr)
Definition: ws.c:248
WsFloat vfloat
Definition: wsgram.c:306
#define tINTEGER
Definition: wsgram.c:166
WsBool ws_buffer_append_space(WsBuffer *buffer, unsigned char **p, size_t size)
Definition: wsbuffer.c:115
#define tXORA
Definition: wsgram.c:241
#define tORA
Definition: wsgram.c:240
#define tLSHIFT
Definition: wsgram.c:232
#define tIDENTIFIER
Definition: wsgram.c:169
char * identifier
Definition: wsgram.c:307
static WsBool read_float_from_exp(WsCompiler *compiler, WsBuffer *buffer, WsFloat *result)
Definition: wslexer.c:959
#define WS_IS_IDENTIFIER_LETTER(ch)
Definition: wslexer.c:108
static WsUInt32 buffer_to_int(WsCompilerPtr compiler, WsBuffer *buffer)
Definition: wslexer.c:909
#define tIDIV
Definition: wsgram.c:174
#define tRSZSHIFT
Definition: wsgram.c:234
#define WS_IS_NON_ZERO_DIGIT(ch)
Definition: wslexer.c:85
#define tADDA
Definition: wsgram.c:235
void * ws_malloc(size_t size)
Definition: wsalloc.c:77
#define tANDA
Definition: wsgram.c:239
void ws_src_error(WsCompilerPtr compiler, WsUInt32 line, char *message,...)
Definition: wserror.c:145
#define COMPILER_MAGIC
Definition: wsint.h:185
void ws_error_memory(WsCompilerPtr compiler)
Definition: wserror.c:107
#define tSTRING
Definition: wsgram.c:168

Variable Documentation

struct { ... } keywords[]
char* name

Definition at line 155 of file wslexer.c.

Referenced by lookup_keyword().

size_t name_len

Definition at line 156 of file wslexer.c.

Referenced by http_header_find_first_real(), lookup_keyword(), and ws_bc_encode().

int num_keywords = sizeof(keywords) / sizeof(keywords[0])
static

Definition at line 217 of file wslexer.c.

Referenced by lookup_keyword().

See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.