Kannel: Open Source WAP and SMS gateway  svn-r5335
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

int ws_yy_lex (YYSTYPE *yylval, YYLTYPE *yylloc, WsCompiler *compiler)
 
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)
 

Variables

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

Macro Definition Documentation

◆ N

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

Definition at line 151 of file wslexer.c.

◆ WS_DECIMAL_TO_INT

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

Definition at line 81 of file wslexer.c.

◆ WS_HEX_TO_INT

#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().

◆ WS_IS_DECIMAL_DIGIT

#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().

◆ WS_IS_HEX_DIGIT

#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().

◆ WS_IS_IDENTIFIER_LETTER

#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().

◆ WS_IS_NON_ZERO_DIGIT

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

Definition at line 85 of file wslexer.c.

Referenced by ws_yy_lex().

◆ WS_IS_OCTAL_DIGIT

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

Definition at line 88 of file wslexer.c.

Referenced by ws_yy_lex().

◆ WS_OCTAL_TO_INT

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

Definition at line 91 of file wslexer.c.

Referenced by ws_yy_lex().

Function Documentation

◆ buffer_to_int()

static WsUInt32 buffer_to_int ( WsCompilerPtr  compiler,
WsBuffer buffer 
)
static

Definition at line 910 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().

911 {
912  unsigned char *p;
913  unsigned long value;
914 
915  /* Terminate the string. */
916  if (!ws_buffer_append_space(buffer, &p, 1)) {
917  ws_error_memory(compiler);
918  return 0;
919  }
920  p[0] = '\0';
921 
922  /* Convert the buffer into an integer number. The base is taken
923  from the bufer. */
924  errno = 0;
925  value = strtoul((char *) ws_buffer_ptr(buffer), NULL, 0);
926 
927  /* Check for overflow. We accept WS_INT32_MAX + 1 because we might
928  * be parsing the numeric part of '-2147483648'. */
929  if (errno == ERANGE || value > (WsUInt32) WS_INT32_MAX + 1)
930  ws_src_error(compiler, 0, "integer literal too large");
931 
932  /* All done. */
933  return (WsUInt32) value;
934 }
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

◆ lookup_keyword()

static WsBool lookup_keyword ( char *  id,
size_t  len,
int *  token_return 
)
static

Definition at line 877 of file wslexer.c.

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

Referenced by ws_yy_lex().

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

◆ read_float_from_exp()

static WsBool read_float_from_exp ( WsCompiler compiler,
WsBuffer buffer,
WsFloat result 
)
static

Definition at line 960 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().

962 {
963  WsUInt32 ch;
964  unsigned char *p;
965  int sign = '+';
966  unsigned char buf[4];
967 
968  /* Do we have an exponent part. */
969  if (!ws_stream_getc(compiler->input, &ch))
970  goto done;
971  if (ch != 'e' && ch != 'E') {
972  /* No exponent part. */
973  ws_stream_ungetc(compiler->input, ch);
974  goto done;
975  }
976 
977  /* Sign. */
978  if (!ws_stream_getc(compiler->input, &ch)) {
979  /* This is an error. */
980  ws_src_error(compiler, 0, "truncated float literal");
981  return WS_FALSE;
982  }
983  if (ch == '-')
984  sign = '-';
985  else if (ch == '+')
986  sign = '+';
987  else
988  ws_stream_ungetc(compiler->input, ch);
989 
990  /* DecimalDigits. */
991  if (!ws_stream_getc(compiler->input, &ch)) {
992  ws_src_error(compiler, 0, "truncated float literal");
993  return WS_FALSE;
994  }
995  if (!WS_IS_DECIMAL_DIGIT(ch)) {
996  ws_src_error(compiler, 0, "no decimal digits in exponent part");
997  return WS_FALSE;
998  }
999 
1000  /* Append exponent part read so far. */
1001  if (!ws_buffer_append_space(buffer, &p, 2)) {
1002  ws_error_memory(compiler);
1003  return WS_FALSE;
1004  }
1005  p[0] = 'e';
1006  p[1] = sign;
1007 
1008  /* Read decimal digits. */
1009  while (WS_IS_DECIMAL_DIGIT(ch)) {
1010  if (!ws_buffer_append_space(buffer, &p, 1)) {
1011  ws_error_memory(compiler);
1012  return WS_FALSE;
1013  }
1014  p[0] = (unsigned char) ch;
1015 
1016  if (!ws_stream_getc(compiler->input, &ch))
1017  /* EOF. This is ok. */
1018  goto done;
1019  }
1020  /* Unget the extra character. */
1021  ws_stream_ungetc(compiler->input, ch);
1022 
1023  /* FALLTHROUGH */
1024 
1025 done:
1026 
1027  if (!ws_buffer_append_space(buffer, &p, 1)) {
1028  ws_error_memory(compiler);
1029  return WS_FALSE;
1030  }
1031  p[0] = 0;
1032 
1033  /* Now the buffer contains a valid floating point number. */
1034  *result = (WsFloat) strtod((char *) ws_buffer_ptr(buffer), NULL);
1035 
1036  /* Check that the generated floating point number fits to
1037  `float32'. */
1038  if (*result == HUGE_VAL || *result == -HUGE_VAL
1039  || ws_ieee754_encode_single(*result, buf) != WS_IEEE754_OK)
1040  ws_src_error(compiler, 0, "floating point literal too large");
1041 
1042  return WS_TRUE;
1043 }
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

◆ read_float_from_point()

static WsBool read_float_from_point ( WsCompiler compiler,
WsBuffer buffer,
WsFloat result 
)
static

Definition at line 937 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().

939 {
940  WsUInt32 ch;
941  unsigned char *p;
942 
943  while (ws_stream_getc(compiler->input, &ch)) {
944  if (WS_IS_DECIMAL_DIGIT(ch)) {
945  if (!ws_buffer_append_space(buffer, &p, 1)) {
946  ws_error_memory(compiler);
947  return WS_FALSE;
948  }
949  p[0] = (unsigned char) ch;
950  } else {
951  ws_stream_ungetc(compiler->input, ch);
952  break;
953  }
954  }
955 
956  return read_float_from_exp(compiler, buffer, result);
957 }
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:960
void ws_error_memory(WsCompilerPtr compiler)
Definition: wserror.c:107

◆ ws_yy_lex()

int ws_yy_lex ( YYSTYPE yylval,
YYLTYPE yylloc,
WsCompiler compiler 
)

Definition at line 223 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().

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

Variable Documentation

◆ keywords

◆ name

char* name

Definition at line 157 of file wslexer.c.

Referenced by lookup_keyword().

◆ name_len

◆ num_keywords

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

Definition at line 219 of file wslexer.c.

Referenced by lookup_keyword().

◆ token

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