616b70081259eaaea471f3d29033ed95635b0541
[pspp-builds.git] / src / language / lexer / lexer.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 1997-9, 2000, 2006, 2009, 2010 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18
19 #include "lexer.h"
20 #include <c-ctype.h>
21 #include <c-strtod.h>
22 #include <errno.h>
23 #include <limits.h>
24 #include <math.h>
25 #include <stdarg.h>
26 #include <stdint.h>
27 #include <stdlib.h>
28 #include <language/command.h>
29 #include <data/settings.h>
30 #include <libpspp/assertion.h>
31 #include <libpspp/getl.h>
32 #include <libpspp/message.h>
33 #include <libpspp/str.h>
34 #include <output/journal.h>
35 #include <output/text-item.h>
36
37 #include "xalloc.h"
38
39 #include "gettext.h"
40 #define _(msgid) gettext (msgid)
41 #define N_(msgid) msgid
42
43 struct lexer
44 {
45   struct string line_buffer;
46
47   struct source_stream *ss;
48
49   int token;      /* Current token. */
50   double tokval;  /* T_POS_NUM, T_NEG_NUM: the token's value. */
51
52   struct string tokstr;   /* T_ID, T_STRING: token string value. */
53
54   char *prog; /* Pointer to next token in line_buffer. */
55   bool dot;   /* True only if this line ends with a terminal dot. */
56
57   int put_token ; /* If nonzero, next token returned by lex_get().
58                     Used only in exceptional circumstances. */
59
60   struct string put_tokstr;
61   double put_tokval;
62 };
63
64
65 static int parse_id (struct lexer *);
66
67 /* How a string represents its contents. */
68 enum string_type
69   {
70     CHARACTER_STRING,   /* Characters. */
71     BINARY_STRING,      /* Binary digits. */
72     OCTAL_STRING,       /* Octal digits. */
73     HEX_STRING          /* Hexadecimal digits. */
74   };
75
76 static int parse_string (struct lexer *, enum string_type);
77 \f
78 /* Initialization. */
79
80 /* Initializes the lexer. */
81 struct lexer *
82 lex_create (struct source_stream *ss)
83 {
84   struct lexer *lexer = xzalloc (sizeof (*lexer));
85
86   ds_init_empty (&lexer->tokstr);
87   ds_init_empty (&lexer->put_tokstr);
88   ds_init_empty (&lexer->line_buffer);
89   lexer->ss = ss;
90
91   return lexer;
92 }
93
94 struct source_stream *
95 lex_get_source_stream (const struct lexer *lex)
96 {
97   return lex->ss;
98 }
99
100 enum syntax_mode
101 lex_current_syntax_mode (const struct lexer *lex)
102 {
103   return source_stream_current_syntax_mode (lex->ss);
104 }
105
106 enum error_mode
107 lex_current_error_mode (const struct lexer *lex)
108 {
109   return source_stream_current_error_mode (lex->ss);
110 }
111
112
113 void
114 lex_destroy (struct lexer *lexer)
115 {
116   if ( NULL != lexer )
117     {
118       ds_destroy (&lexer->put_tokstr);
119       ds_destroy (&lexer->tokstr);
120       ds_destroy (&lexer->line_buffer);
121
122       free (lexer);
123     }
124 }
125
126 \f
127 /* Common functions. */
128
129 /* Copies put_token, lexer->put_tokstr, put_tokval into token, tokstr,
130    tokval, respectively, and sets tokid appropriately. */
131 static void
132 restore_token (struct lexer *lexer)
133 {
134   assert (lexer->put_token != 0);
135   lexer->token = lexer->put_token;
136   ds_assign_string (&lexer->tokstr, &lexer->put_tokstr);
137   lexer->tokval = lexer->put_tokval;
138   lexer->put_token = 0;
139 }
140
141 /* Copies token, tokstr, lexer->tokval into lexer->put_token, put_tokstr,
142    put_lexer->tokval respectively. */
143 static void
144 save_token (struct lexer *lexer)
145 {
146   lexer->put_token = lexer->token;
147   ds_assign_string (&lexer->put_tokstr, &lexer->tokstr);
148   lexer->put_tokval = lexer->tokval;
149 }
150
151 /* Parses a single token, setting appropriate global variables to
152    indicate the token's attributes. */
153 void
154 lex_get (struct lexer *lexer)
155 {
156   /* Find a token. */
157   for (;;)
158     {
159       if (NULL == lexer->prog && ! lex_get_line (lexer) )
160         {
161           lexer->token = T_STOP;
162           return;
163         }
164
165       /* If a token was pushed ahead, return it. */
166       if (lexer->put_token)
167         {
168           restore_token (lexer);
169           return;
170         }
171
172       for (;;)
173         {
174           /* Skip whitespace. */
175           while (c_isspace ((unsigned char) *lexer->prog))
176             lexer->prog++;
177
178           if (*lexer->prog)
179             break;
180
181           if (lexer->dot)
182             {
183               lexer->dot = 0;
184               lexer->token = T_ENDCMD;
185               return;
186             }
187           else if (!lex_get_line (lexer))
188             {
189               lexer->prog = NULL;
190               lexer->token = T_STOP;
191               return;
192             }
193
194           if (lexer->put_token)
195             {
196               restore_token (lexer);
197               return;
198             }
199         }
200
201
202       /* Actually parse the token. */
203       ds_clear (&lexer->tokstr);
204
205       switch (*lexer->prog)
206         {
207         case '-': case '.':
208         case '0': case '1': case '2': case '3': case '4':
209         case '5': case '6': case '7': case '8': case '9':
210           {
211             char *tail;
212
213             /* `-' can introduce a negative number, or it can be a token by
214                itself. */
215             if (*lexer->prog == '-')
216               {
217                 ds_put_byte (&lexer->tokstr, *lexer->prog++);
218                 while (c_isspace ((unsigned char) *lexer->prog))
219                   lexer->prog++;
220
221                 if (!c_isdigit ((unsigned char) *lexer->prog) && *lexer->prog != '.')
222                   {
223                     lexer->token = T_DASH;
224                     break;
225                   }
226                 lexer->token = T_NEG_NUM;
227               }
228             else
229               lexer->token = T_POS_NUM;
230
231             /* Parse the number, copying it into tokstr. */
232             while (c_isdigit ((unsigned char) *lexer->prog))
233               ds_put_byte (&lexer->tokstr, *lexer->prog++);
234             if (*lexer->prog == '.')
235               {
236                 ds_put_byte (&lexer->tokstr, *lexer->prog++);
237                 while (c_isdigit ((unsigned char) *lexer->prog))
238                   ds_put_byte (&lexer->tokstr, *lexer->prog++);
239               }
240             if (*lexer->prog == 'e' || *lexer->prog == 'E')
241               {
242                 ds_put_byte (&lexer->tokstr, *lexer->prog++);
243                 if (*lexer->prog == '+' || *lexer->prog == '-')
244                   ds_put_byte (&lexer->tokstr, *lexer->prog++);
245                 while (c_isdigit ((unsigned char) *lexer->prog))
246                   ds_put_byte (&lexer->tokstr, *lexer->prog++);
247               }
248
249             /* Parse as floating point. */
250             lexer->tokval = c_strtod (ds_cstr (&lexer->tokstr), &tail);
251             if (*tail)
252               {
253                 msg (SE, _("%s does not form a valid number."),
254                      ds_cstr (&lexer->tokstr));
255                 lexer->tokval = 0.0;
256
257                 ds_clear (&lexer->tokstr);
258                 ds_put_byte (&lexer->tokstr, '0');
259               }
260
261             break;
262           }
263
264         case '\'': case '"':
265           lexer->token = parse_string (lexer, CHARACTER_STRING);
266           break;
267
268         case '+':
269           lexer->token = T_PLUS;
270           lexer->prog++;
271           break;
272
273         case '/':
274           lexer->token = T_SLASH;
275           lexer->prog++;
276           break;
277
278         case '=':
279           lexer->token = T_EQUALS;
280           lexer->prog++;
281           break;
282
283         case '(':
284           lexer->token = T_LPAREN;
285           lexer->prog++;
286           break;
287
288         case ')':
289           lexer->token = T_RPAREN;
290           lexer->prog++;
291           break;
292
293         case '[':
294           lexer->token = T_LBRACK;
295           lexer->prog++;
296           break;
297
298         case ']':
299           lexer->token = T_RBRACK;
300           lexer->prog++;
301           break;
302
303         case ',':
304           lexer->token = T_COMMA;
305           lexer->prog++;
306           break;
307
308         case '*':
309           if (*++lexer->prog == '*')
310             {
311               lexer->prog++;
312               lexer->token = T_EXP;
313             }
314           else
315             lexer->token = T_ASTERISK;
316           break;
317
318         case '<':
319           if (*++lexer->prog == '=')
320             {
321               lexer->prog++;
322               lexer->token = T_LE;
323             }
324           else if (*lexer->prog == '>')
325             {
326               lexer->prog++;
327               lexer->token = T_NE;
328             }
329           else
330             lexer->token = T_LT;
331           break;
332
333         case '>':
334           if (*++lexer->prog == '=')
335             {
336               lexer->prog++;
337               lexer->token = T_GE;
338             }
339           else
340             lexer->token = T_GT;
341           break;
342
343         case '~':
344           if (*++lexer->prog == '=')
345             {
346               lexer->prog++;
347               lexer->token = T_NE;
348             }
349           else
350             lexer->token = T_NOT;
351           break;
352
353         case '&':
354           lexer->prog++;
355           lexer->token = T_AND;
356           break;
357
358         case '|':
359           lexer->prog++;
360           lexer->token = T_OR;
361           break;
362
363         case 'b': case 'B':
364           if (lexer->prog[1] == '\'' || lexer->prog[1] == '"')
365             lexer->token = parse_string (lexer, BINARY_STRING);
366           else
367             lexer->token = parse_id (lexer);
368           break;
369
370         case 'o': case 'O':
371           if (lexer->prog[1] == '\'' || lexer->prog[1] == '"')
372             lexer->token = parse_string (lexer, OCTAL_STRING);
373           else
374             lexer->token = parse_id (lexer);
375           break;
376
377         case 'x': case 'X':
378           if (lexer->prog[1] == '\'' || lexer->prog[1] == '"')
379             lexer->token = parse_string (lexer, HEX_STRING);
380           else
381             lexer->token = parse_id (lexer);
382           break;
383
384         default:
385           if (lex_is_id1 (*lexer->prog))
386             {
387               lexer->token = parse_id (lexer);
388               break;
389             }
390           else
391             {
392               unsigned char c = *lexer->prog++;
393               char *c_name = xasprintf (c_isgraph (c) ? "%c" : "\\%o", c);
394               msg (SE, _("Bad character in input: `%s'."), c_name);
395               free (c_name);
396               continue;
397             }
398         }
399       break;
400     }
401 }
402
403 /* Parses an identifier at the current position into tokstr.
404    Returns the correct token type. */
405 static int
406 parse_id (struct lexer *lexer)
407 {
408   struct substring rest_of_line
409     = ss_substr (ds_ss (&lexer->line_buffer),
410                  ds_pointer_to_position (&lexer->line_buffer, lexer->prog),
411                  SIZE_MAX);
412   struct substring id = ss_head (rest_of_line,
413                                  lex_id_get_length (rest_of_line));
414   lexer->prog += ss_length (id);
415
416   ds_assign_substring (&lexer->tokstr, id);
417   return lex_id_to_token (id);
418 }
419
420 /* Reports an error to the effect that subcommand SBC may only be
421    specified once. */
422 void
423 lex_sbc_only_once (const char *sbc)
424 {
425   msg (SE, _("Subcommand %s may only be specified once."), sbc);
426 }
427
428 /* Reports an error to the effect that subcommand SBC is
429    missing. */
430 void
431 lex_sbc_missing (struct lexer *lexer, const char *sbc)
432 {
433   lex_error (lexer, _("missing required subcommand %s"), sbc);
434 }
435
436 /* Prints a syntax error message containing the current token and
437    given message MESSAGE (if non-null). */
438 void
439 lex_error (struct lexer *lexer, const char *message, ...)
440 {
441   struct string s;
442
443   ds_init_empty (&s);
444
445   if (lexer->token == T_STOP)
446     ds_put_cstr (&s, _("Syntax error at end of file"));
447   else if (lexer->token == T_ENDCMD)
448     ds_put_cstr (&s, _("Syntax error at end of command"));
449   else
450     {
451       char *token_rep = lex_token_representation (lexer);
452       ds_put_format (&s, _("Syntax error at `%s'"), token_rep);
453       free (token_rep);
454     }
455
456   if (message)
457     {
458       va_list args;
459
460       ds_put_cstr (&s, ": ");
461
462       va_start (args, message);
463       ds_put_vformat (&s, message, args);
464       va_end (args);
465     }
466
467   msg (SE, "%s.", ds_cstr (&s));
468   ds_destroy (&s);
469 }
470
471 /* Checks that we're at end of command.
472    If so, returns a successful command completion code.
473    If not, flags a syntax error and returns an error command
474    completion code. */
475 int
476 lex_end_of_command (struct lexer *lexer)
477 {
478   if (lexer->token != T_ENDCMD)
479     {
480       lex_error (lexer, _("expecting end of command"));
481       return CMD_FAILURE;
482     }
483   else
484     return CMD_SUCCESS;
485 }
486 \f
487 /* Token testing functions. */
488
489 /* Returns true if the current token is a number. */
490 bool
491 lex_is_number (struct lexer *lexer)
492 {
493   return lexer->token == T_POS_NUM || lexer->token == T_NEG_NUM;
494 }
495
496
497 /* Returns true if the current token is a string. */
498 bool
499 lex_is_string (struct lexer *lexer)
500 {
501   return lexer->token == T_STRING;
502 }
503
504
505 /* Returns the value of the current token, which must be a
506    floating point number. */
507 double
508 lex_number (struct lexer *lexer)
509 {
510   assert (lex_is_number (lexer));
511   return lexer->tokval;
512 }
513
514 /* Returns true iff the current token is an integer. */
515 bool
516 lex_is_integer (struct lexer *lexer)
517 {
518   return (lex_is_number (lexer)
519           && lexer->tokval > LONG_MIN
520           && lexer->tokval <= LONG_MAX
521           && floor (lexer->tokval) == lexer->tokval);
522 }
523
524 /* Returns the value of the current token, which must be an
525    integer. */
526 long
527 lex_integer (struct lexer *lexer)
528 {
529   assert (lex_is_integer (lexer));
530   return lexer->tokval;
531 }
532 \f
533 /* Token matching functions. */
534
535 /* If TOK is the current token, skips it and returns true
536    Otherwise, returns false. */
537 bool
538 lex_match (struct lexer *lexer, enum token_type t)
539 {
540   if (lexer->token == t)
541     {
542       lex_get (lexer);
543       return true;
544     }
545   else
546     return false;
547 }
548
549 /* If the current token is the identifier S, skips it and returns
550    true.  The identifier may be abbreviated to its first three
551    letters.
552    Otherwise, returns false. */
553 bool
554 lex_match_id (struct lexer *lexer, const char *s)
555 {
556   return lex_match_id_n (lexer, s, 3);
557 }
558
559 /* If the current token is the identifier S, skips it and returns
560    true.  The identifier may be abbreviated to its first N
561    letters.
562    Otherwise, returns false. */
563 bool
564 lex_match_id_n (struct lexer *lexer, const char *s, size_t n)
565 {
566   if (lexer->token == T_ID
567       && lex_id_match_n (ss_cstr (s), lex_tokss (lexer), n))
568     {
569       lex_get (lexer);
570       return true;
571     }
572   else
573     return false;
574 }
575
576 /* If the current token is integer N, skips it and returns true.
577    Otherwise, returns false. */
578 bool
579 lex_match_int (struct lexer *lexer, int x)
580 {
581   if (lex_is_integer (lexer) && lex_integer (lexer) == x)
582     {
583       lex_get (lexer);
584       return true;
585     }
586   else
587     return false;
588 }
589 \f
590 /* Forced matches. */
591
592 /* If this token is identifier S, fetches the next token and returns
593    nonzero.
594    Otherwise, reports an error and returns zero. */
595 bool
596 lex_force_match_id (struct lexer *lexer, const char *s)
597 {
598   if (lex_match_id (lexer, s))
599     return true;
600   else
601     {
602       lex_error (lexer, _("expecting `%s'"), s);
603       return false;
604     }
605 }
606
607 /* If the current token is T, skips the token.  Otherwise, reports an
608    error and returns from the current function with return value false. */
609 bool
610 lex_force_match (struct lexer *lexer, enum token_type t)
611 {
612   if (lexer->token == t)
613     {
614       lex_get (lexer);
615       return true;
616     }
617   else
618     {
619       lex_error (lexer, _("expecting `%s'"), lex_token_name (t));
620       return false;
621     }
622 }
623
624 /* If this token is a string, does nothing and returns true.
625    Otherwise, reports an error and returns false. */
626 bool
627 lex_force_string (struct lexer *lexer)
628 {
629   if (lex_is_string (lexer))
630     return true;
631   else
632     {
633       lex_error (lexer, _("expecting string"));
634       return false;
635     }
636 }
637
638 /* If this token is an integer, does nothing and returns true.
639    Otherwise, reports an error and returns false. */
640 bool
641 lex_force_int (struct lexer *lexer)
642 {
643   if (lex_is_integer (lexer))
644     return true;
645   else
646     {
647       lex_error (lexer, _("expecting integer"));
648       return false;
649     }
650 }
651
652 /* If this token is a number, does nothing and returns true.
653    Otherwise, reports an error and returns false. */
654 bool
655 lex_force_num (struct lexer *lexer)
656 {
657   if (lex_is_number (lexer))
658     return true;
659
660   lex_error (lexer, _("expecting number"));
661   return false;
662 }
663
664 /* If this token is an identifier, does nothing and returns true.
665    Otherwise, reports an error and returns false. */
666 bool
667 lex_force_id (struct lexer *lexer)
668 {
669   if (lexer->token == T_ID)
670     return true;
671
672   lex_error (lexer, _("expecting identifier"));
673   return false;
674 }
675
676 /* Weird token functions. */
677
678 /* Returns the likely type of the next token, or 0 if it's hard to tell. */
679 enum token_type
680 lex_look_ahead (struct lexer *lexer)
681 {
682   if (lexer->put_token)
683     return lexer->put_token;
684
685   for (;;)
686     {
687       if (NULL == lexer->prog && ! lex_get_line (lexer) )
688         return 0;
689
690       for (;;)
691         {
692           while (c_isspace ((unsigned char) *lexer->prog))
693             lexer->prog++;
694           if (*lexer->prog)
695             break;
696
697           if (lexer->dot)
698             return T_ENDCMD;
699           else if (!lex_get_line (lexer))
700             return 0;
701
702           if (lexer->put_token)
703             return lexer->put_token;
704         }
705
706       switch (toupper ((unsigned char) *lexer->prog))
707         {
708         case 'X': case 'B': case 'O':
709           if (lexer->prog[1] == '\'' || lexer->prog[1] == '"')
710             return T_STRING;
711           /* Fall through */
712
713         case '-':
714           return T_DASH;
715
716         case '.':
717         case '0': case '1': case '2': case '3': case '4':
718         case '5': case '6': case '7': case '8': case '9':
719           return T_POS_NUM;
720
721         case '\'': case '"':
722           return T_STRING;
723
724         case '+':
725           return T_PLUS;
726
727         case '/':
728           return T_SLASH;
729
730         case '=':
731           return T_EQUALS;
732
733         case '(':
734           return T_LPAREN;
735
736         case ')':
737           return T_RPAREN;
738
739         case '[':
740           return T_LBRACK;
741
742         case ']':
743           return T_RBRACK;
744
745         case ',':
746           return T_COMMA;
747
748         case '*':
749           return lexer->prog[1] == '*' ? T_EXP : T_ASTERISK;
750
751         case '<':
752           return (lexer->prog[1] == '=' ? T_LE
753                   : lexer->prog[1] == '>' ? T_NE
754                   : T_LT);
755
756         case '>':
757           return lexer->prog[1] == '=' ? T_GE : T_GT;
758
759         case '~':
760           return lexer->prog[1] == '=' ? T_NE : T_NOT;
761
762         case '&':
763           return T_AND;
764
765         case '|':
766           return T_OR;
767
768         default:
769           if (lex_is_id1 (*lexer->prog))
770             return T_ID;
771           return 0;
772         }
773     }
774 }
775
776 /* Makes the current token become the next token to be read; the
777    current token is set to T. */
778 void
779 lex_put_back (struct lexer *lexer, enum token_type t)
780 {
781   save_token (lexer);
782   lexer->token = t;
783 }
784 \f
785 /* Weird line processing functions. */
786
787 /* Returns the entire contents of the current line. */
788 const char *
789 lex_entire_line (const struct lexer *lexer)
790 {
791   return ds_cstr (&lexer->line_buffer);
792 }
793
794 const struct string *
795 lex_entire_line_ds (const struct lexer *lexer)
796 {
797   return &lexer->line_buffer;
798 }
799
800 /* As lex_entire_line(), but only returns the part of the current line
801    that hasn't already been tokenized. */
802 const char *
803 lex_rest_of_line (const struct lexer *lexer)
804 {
805   return lexer->prog;
806 }
807
808 /* Returns true if the current line ends in a terminal dot,
809    false otherwise. */
810 bool
811 lex_end_dot (const struct lexer *lexer)
812 {
813   return lexer->dot;
814 }
815
816 /* Causes the rest of the current input line to be ignored for
817    tokenization purposes. */
818 void
819 lex_discard_line (struct lexer *lexer)
820 {
821   ds_cstr (&lexer->line_buffer);  /* Ensures ds_end points to something valid */
822   lexer->prog = ds_end (&lexer->line_buffer);
823   lexer->dot = false;
824   lexer->put_token = 0;
825 }
826
827
828 /* Discards the rest of the current command.
829    When we're reading commands from a file, we skip tokens until
830    a terminal dot or EOF.
831    When we're reading commands interactively from the user,
832    that's just discarding the current line, because presumably
833    the user doesn't want to finish typing a command that will be
834    ignored anyway. */
835 void
836 lex_discard_rest_of_command (struct lexer *lexer)
837 {
838   if (!getl_is_interactive (lexer->ss))
839     {
840       while (lexer->token != T_STOP && lexer->token != T_ENDCMD)
841         lex_get (lexer);
842     }
843   else
844     lex_discard_line (lexer);
845 }
846 \f
847 /* Weird line reading functions. */
848
849 /* Remove C-style comments in STRING, begun by slash-star and
850    terminated by star-slash or newline. */
851 static void
852 strip_comments (struct string *string)
853 {
854   char *cp;
855   int quote;
856   bool in_comment;
857
858   in_comment = false;
859   quote = EOF;
860   for (cp = ds_cstr (string); *cp; )
861     {
862       /* If we're not in a comment, check for quote marks. */
863       if (!in_comment)
864         {
865           if (*cp == quote)
866             quote = EOF;
867           else if (*cp == '\'' || *cp == '"')
868             quote = *cp;
869         }
870
871       /* If we're not inside a quotation, check for comment. */
872       if (quote == EOF)
873         {
874           if (cp[0] == '/' && cp[1] == '*')
875             {
876               in_comment = true;
877               *cp++ = ' ';
878               *cp++ = ' ';
879               continue;
880             }
881           else if (in_comment && cp[0] == '*' && cp[1] == '/')
882             {
883               in_comment = false;
884               *cp++ = ' ';
885               *cp++ = ' ';
886               continue;
887             }
888         }
889
890       /* Check commenting. */
891       if (in_comment)
892         *cp = ' ';
893       cp++;
894     }
895 }
896
897 /* Prepares LINE, which is subject to the given SYNTAX rules, for
898    tokenization by stripping comments and determining whether it
899    is the beginning or end of a command and storing into
900    *LINE_STARTS_COMMAND and *LINE_ENDS_COMMAND appropriately. */
901 void
902 lex_preprocess_line (struct string *line,
903                      enum syntax_mode syntax,
904                      bool *line_starts_command,
905                      bool *line_ends_command)
906 {
907   strip_comments (line);
908   ds_rtrim (line, ss_cstr (CC_SPACES));
909   *line_ends_command = ds_chomp (line, '.') || ds_is_empty (line);
910   *line_starts_command = false;
911   if (syntax == GETL_BATCH)
912     {
913       int first = ds_first (line);
914       *line_starts_command = !c_isspace (first);
915       if (first == '+' || first == '-')
916         *ds_data (line) = ' ';
917     }
918 }
919
920 /* Reads a line, without performing any preprocessing. */
921 bool
922 lex_get_line_raw (struct lexer *lexer)
923 {
924   bool ok = getl_read_line (lexer->ss, &lexer->line_buffer);
925   if (ok)
926     {
927       const char *line = ds_cstr (&lexer->line_buffer);
928       text_item_submit (text_item_create (TEXT_ITEM_SYNTAX, line));
929     }
930   else
931     lexer->prog = NULL;
932   return ok;
933 }
934
935 /* Reads a line for use by the tokenizer, and preprocesses it by
936    removing comments, stripping trailing whitespace and the
937    terminal dot, and removing leading indentors. */
938 bool
939 lex_get_line (struct lexer *lexer)
940 {
941   bool line_starts_command;
942
943   if (!lex_get_line_raw (lexer))
944     return false;
945
946   lex_preprocess_line (&lexer->line_buffer,
947                        lex_current_syntax_mode (lexer),
948                        &line_starts_command, &lexer->dot);
949
950   if (line_starts_command)
951     lexer->put_token = T_ENDCMD;
952
953   lexer->prog = ds_cstr (&lexer->line_buffer);
954   return true;
955 }
956 \f
957 /* Token names. */
958
959 /* Returns the name of a token. */
960 const char *
961 lex_token_name (enum token_type token)
962 {
963   switch (token)
964     {
965     case T_ID:
966     case T_POS_NUM:
967     case T_NEG_NUM:
968     case T_STRING:
969       NOT_REACHED ();
970
971     case T_STOP:
972       return "";
973
974     case T_ENDCMD:
975       return ".";
976
977     case T_PLUS:
978       return "+";
979
980     case T_DASH:
981       return "-";
982
983     case T_ASTERISK:
984       return "*";
985
986     case T_SLASH:
987       return "/";
988
989     case T_EQUALS:
990       return "=";
991
992     case T_LPAREN:
993       return "(";
994
995     case T_RPAREN:
996       return ")";
997
998     case T_LBRACK:
999       return "[";
1000
1001     case T_RBRACK:
1002       return "]";
1003
1004     case T_COMMA:
1005       return ",";
1006
1007     case T_AND:
1008       return "AND";
1009
1010     case T_OR:
1011       return "OR";
1012
1013     case T_NOT:
1014       return "NOT";
1015
1016     case T_EQ:
1017       return "EQ";
1018
1019     case T_GE:
1020       return ">=";
1021
1022     case T_GT:
1023       return ">";
1024
1025     case T_LE:
1026       return "<=";
1027
1028     case T_LT:
1029       return "<";
1030
1031     case T_NE:
1032       return "~=";
1033
1034     case T_ALL:
1035       return "ALL";
1036
1037     case T_BY:
1038       return "BY";
1039
1040     case T_TO:
1041       return "TO";
1042
1043     case T_WITH:
1044       return "WITH";
1045
1046     case T_EXP:
1047       return "**";
1048     }
1049
1050   NOT_REACHED ();
1051 }
1052
1053 /* Returns an ASCII representation of the current token as a
1054    malloc()'d string. */
1055 char *
1056 lex_token_representation (struct lexer *lexer)
1057 {
1058   char *token_rep;
1059
1060   switch (lexer->token)
1061     {
1062     case T_ID:
1063     case T_POS_NUM:
1064     case T_NEG_NUM:
1065       return ss_xstrdup (lex_tokss (lexer));
1066
1067     case T_STRING:
1068       {
1069         struct substring ss;
1070         int hexstring = 0;
1071         char *sp, *dp;
1072
1073         ss = lex_tokss (lexer);
1074         for (sp = ss_data (ss); sp < ss_end (ss); sp++)
1075           if (!c_isprint ((unsigned char) *sp))
1076             {
1077               hexstring = 1;
1078               break;
1079             }
1080
1081         token_rep = xmalloc (2 + ss_length (ss) * 2 + 1 + 1);
1082
1083         dp = token_rep;
1084         if (hexstring)
1085           *dp++ = 'X';
1086         *dp++ = '\'';
1087
1088         for (sp = ss_data (ss); sp < ss_end (ss); sp++)
1089           if (!hexstring)
1090             {
1091               if (*sp == '\'')
1092                 *dp++ = '\'';
1093               *dp++ = (unsigned char) *sp;
1094             }
1095           else
1096             {
1097               *dp++ = (((unsigned char) *sp) >> 4)["0123456789ABCDEF"];
1098               *dp++ = (((unsigned char) *sp) & 15)["0123456789ABCDEF"];
1099             }
1100         *dp++ = '\'';
1101         *dp = '\0';
1102
1103         return token_rep;
1104       }
1105
1106     default:
1107       return xstrdup (lex_token_name (lexer->token));
1108     }
1109 }
1110 \f
1111 /* Really weird functions. */
1112
1113 /* Skip a COMMENT command. */
1114 void
1115 lex_skip_comment (struct lexer *lexer)
1116 {
1117   for (;;)
1118     {
1119       if (!lex_get_line (lexer))
1120         {
1121           lexer->put_token = T_STOP;
1122           lexer->prog = NULL;
1123           return;
1124         }
1125
1126       if (lexer->put_token == T_ENDCMD)
1127         break;
1128
1129       ds_cstr (&lexer->line_buffer); /* Ensures ds_end will point to a valid char */
1130       lexer->prog = ds_end (&lexer->line_buffer);
1131       if (lexer->dot)
1132         break;
1133     }
1134 }
1135 \f
1136 /* Private functions. */
1137
1138 /* When invoked, tokstr contains a string of binary, octal, or
1139    hex digits, according to TYPE.  The string is converted to
1140    characters having the specified values. */
1141 static void
1142 convert_numeric_string_to_char_string (struct lexer *lexer,
1143                                        enum string_type type)
1144 {
1145   const char *base_name;
1146   int base;
1147   int chars_per_byte;
1148   size_t byte_cnt;
1149   size_t i;
1150   char *p;
1151
1152   switch (type)
1153     {
1154     case BINARY_STRING:
1155       base_name = _("binary");
1156       base = 2;
1157       chars_per_byte = 8;
1158       break;
1159     case OCTAL_STRING:
1160       base_name = _("octal");
1161       base = 8;
1162       chars_per_byte = 3;
1163       break;
1164     case HEX_STRING:
1165       base_name = _("hex");
1166       base = 16;
1167       chars_per_byte = 2;
1168       break;
1169     default:
1170       NOT_REACHED ();
1171     }
1172
1173   byte_cnt = ds_length (&lexer->tokstr) / chars_per_byte;
1174   if (ds_length (&lexer->tokstr) % chars_per_byte)
1175     msg (SE, _("String of %s digits has %zu characters, which is not a "
1176                "multiple of %d."),
1177          base_name, ds_length (&lexer->tokstr), chars_per_byte);
1178
1179   p = ds_cstr (&lexer->tokstr);
1180   for (i = 0; i < byte_cnt; i++)
1181     {
1182       int value;
1183       int j;
1184
1185       value = 0;
1186       for (j = 0; j < chars_per_byte; j++, p++)
1187         {
1188           int v;
1189
1190           if (*p >= '0' && *p <= '9')
1191             v = *p - '0';
1192           else
1193             {
1194               static const char alpha[] = "abcdef";
1195               const char *q = strchr (alpha, tolower ((unsigned char) *p));
1196
1197               if (q)
1198                 v = q - alpha + 10;
1199               else
1200                 v = base;
1201             }
1202
1203           if (v >= base)
1204             msg (SE, _("`%c' is not a valid %s digit."), *p, base_name);
1205
1206           value = value * base + v;
1207         }
1208
1209       ds_cstr (&lexer->tokstr)[i] = (unsigned char) value;
1210     }
1211
1212   ds_truncate (&lexer->tokstr, byte_cnt);
1213 }
1214
1215 /* Parses a string from the input buffer into tokstr.  The input
1216    buffer pointer lexer->prog must point to the initial single or double
1217    quote.  TYPE indicates the type of string to be parsed.
1218    Returns token type. */
1219 static int
1220 parse_string (struct lexer *lexer, enum string_type type)
1221 {
1222   if (type != CHARACTER_STRING)
1223     lexer->prog++;
1224
1225   /* Accumulate the entire string, joining sections indicated by +
1226      signs. */
1227   for (;;)
1228     {
1229       /* Single or double quote. */
1230       int c = *lexer->prog++;
1231
1232       /* Accumulate section. */
1233       for (;;)
1234         {
1235           /* Check end of line. */
1236           if (*lexer->prog == '\0')
1237             {
1238               msg (SE, _("Unterminated string constant."));
1239               goto finish;
1240             }
1241
1242           /* Double quote characters to embed them in strings. */
1243           if (*lexer->prog == c)
1244             {
1245               if (lexer->prog[1] == c)
1246                 lexer->prog++;
1247               else
1248                 break;
1249             }
1250
1251           ds_put_byte (&lexer->tokstr, *lexer->prog++);
1252         }
1253       lexer->prog++;
1254
1255       /* Skip whitespace after final quote mark. */
1256       if (lexer->prog == NULL)
1257         break;
1258       for (;;)
1259         {
1260           while (c_isspace ((unsigned char) *lexer->prog))
1261             lexer->prog++;
1262           if (*lexer->prog)
1263             break;
1264
1265           if (lexer->dot)
1266             goto finish;
1267
1268           if (!lex_get_line (lexer))
1269             goto finish;
1270         }
1271
1272       /* Skip plus sign. */
1273       if (*lexer->prog != '+')
1274         break;
1275       lexer->prog++;
1276
1277       /* Skip whitespace after plus sign. */
1278       if (lexer->prog == NULL)
1279         break;
1280       for (;;)
1281         {
1282           while (c_isspace ((unsigned char) *lexer->prog))
1283             lexer->prog++;
1284           if (*lexer->prog)
1285             break;
1286
1287           if (lexer->dot)
1288             goto finish;
1289
1290           if (!lex_get_line (lexer))
1291             {
1292               msg (SE, _("Unexpected end of file in string concatenation."));
1293               goto finish;
1294             }
1295         }
1296
1297       /* Ensure that a valid string follows. */
1298       if (*lexer->prog != '\'' && *lexer->prog != '"')
1299         {
1300           msg (SE, _("String expected following `+'."));
1301           goto finish;
1302         }
1303     }
1304
1305   /* We come here when we've finished concatenating all the string sections
1306      into one large string. */
1307 finish:
1308   if (type != CHARACTER_STRING)
1309     convert_numeric_string_to_char_string (lexer, type);
1310
1311   return T_STRING;
1312 }
1313 \f
1314 /* Token Accessor Functions */
1315
1316 enum token_type
1317 lex_token (const struct lexer *lexer)
1318 {
1319   return lexer->token;
1320 }
1321
1322 double
1323 lex_tokval (const struct lexer *lexer)
1324 {
1325   return lexer->tokval;
1326 }
1327
1328 /* Returns the null-terminated string value associated with LEXER's current
1329    token.  For a T_ID token, this is the identifier, and for a T_STRING token,
1330    this is the string.  For other tokens the value is undefined. */
1331 const char *
1332 lex_tokcstr (const struct lexer *lexer)
1333 {
1334   return ds_cstr (&lexer->tokstr);
1335 }
1336
1337 /* Returns the string value associated with LEXER's current token.  For a T_ID
1338    token, this is the identifier, and for a T_STRING token, this is the string.
1339    For other tokens the value is undefined. */
1340 struct substring
1341 lex_tokss (const struct lexer *lexer)
1342 {
1343   return ds_ss (&lexer->tokstr);
1344 }
1345
1346 /* If the lexer is positioned at the (pseudo)identifier S, which
1347    may contain a hyphen ('-'), skips it and returns true.  Each
1348    half of the identifier may be abbreviated to its first three
1349    letters.
1350    Otherwise, returns false. */
1351 bool
1352 lex_match_hyphenated_word (struct lexer *lexer, const char *s)
1353 {
1354   const char *hyphen = strchr (s, '-');
1355   if (hyphen == NULL)
1356     return lex_match_id (lexer, s);
1357   else if (lexer->token != T_ID
1358            || !lex_id_match (ss_buffer (s, hyphen - s), lex_tokss (lexer))
1359            || lex_look_ahead (lexer) != T_DASH)
1360     return false;
1361   else
1362     {
1363       lex_get (lexer);
1364       lex_force_match (lexer, T_DASH);
1365       lex_force_match_id (lexer, hyphen + 1);
1366       return true;
1367     }
1368 }
1369