c0a09973ce8059535ea7c1e487c5fa2016ff8134
[pspp] / src / language / lexer / segment.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2010, 2011, 2013, 2016 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 "language/lexer/segment.h"
20
21 #include <limits.h>
22 #include <unistr.h>
23
24 #include "data/identifier.h"
25 #include "language/lexer/command-name.h"
26 #include "libpspp/assertion.h"
27 #include "libpspp/cast.h"
28
29 #include "gl/c-ctype.h"
30 #include "gl/c-strcase.h"
31
32 enum segmenter_state
33   {
34     S_SHBANG,
35     S_GENERAL,
36     S_COMMENT_1,
37     S_COMMENT_2,
38     S_DOCUMENT_1,
39     S_DOCUMENT_2,
40     S_DOCUMENT_3,
41     S_FILE_LABEL,
42     S_DO_REPEAT_1,
43     S_DO_REPEAT_2,
44     S_DO_REPEAT_3,
45     S_BEGIN_DATA_1,
46     S_BEGIN_DATA_2,
47     S_BEGIN_DATA_3,
48     S_BEGIN_DATA_4,
49     S_TITLE_1,
50     S_TITLE_2
51   };
52
53 #define SS_START_OF_LINE (1u << 0)
54 #define SS_START_OF_COMMAND (1u << 1)
55
56 static int segmenter_detect_command_name__ (const char *input,
57                                             size_t n, bool eof, int ofs);
58
59 static int
60 segmenter_u8_to_uc__ (ucs4_t *puc, const char *input_, size_t n, bool eof,
61                       size_t ofs)
62 {
63   const uint8_t *input = CHAR_CAST (const uint8_t *, input_);
64   int mblen;
65
66   assert (n > ofs);
67
68   input += ofs;
69   n -= ofs;
70
71   mblen = u8_mbtoucr (puc, input, n);
72   if (mblen >= 0)
73     return mblen;
74   else if (mblen != -2)
75     return u8_mbtouc (puc, input, n);
76   else if (eof)
77     {
78       *puc = 0xfffd;
79       return n;
80     }
81   else
82     return -1;
83 }
84
85 static int
86 segmenter_parse_shbang__ (struct segmenter *s, const char *input, size_t n,
87                           bool eof, enum segment_type *type)
88 {
89   if (input[0] == '#')
90     {
91       if (n >= 2)
92         {
93           if (input[1] == '!')
94             {
95               int ofs;
96
97               for (ofs = 2; ofs < n; ofs++)
98                 if (input[ofs] == '\n')
99                   {
100                     if (input[ofs] == '\n' && input[ofs - 1] == '\r')
101                       ofs--;
102
103                     s->state = S_GENERAL;
104                     s->substate = SS_START_OF_COMMAND;
105                     *type = SEG_SHBANG;
106                     return ofs;
107                   }
108
109               return eof ? ofs : -1;
110             }
111         }
112       else if (!eof)
113         return -1;
114     }
115
116   s->state = S_GENERAL;
117   s->substate = SS_START_OF_LINE | SS_START_OF_COMMAND;
118   return segmenter_push (s, input, n, eof, type);
119 }
120
121 static int
122 segmenter_parse_digraph__ (const char *seconds, struct segmenter *s,
123                            const char *input, size_t n, bool eof,
124                            enum segment_type *type)
125 {
126   assert (s->state == S_GENERAL);
127
128   *type = SEG_PUNCT;
129   s->substate = 0;
130   return (n < 2
131           ? (eof ? 1 : -1)
132           : (strchr (seconds, input[1]) != NULL ? 2 : 1));
133 }
134
135 static int
136 skip_comment (const char *input, size_t n, bool eof, size_t ofs)
137 {
138   for (; ofs < n; ofs++)
139     {
140       if (input[ofs] == '\n')
141         return ofs;
142       else if (input[ofs] == '*')
143         {
144           if (ofs + 1 >= n)
145             return eof ? ofs + 1 : -1;
146           else if (input[ofs + 1] == '/')
147             return ofs + 2;
148         }
149     }
150   return eof ? ofs : -1;
151 }
152
153 static int
154 skip_spaces_and_comments (const char *input, size_t n, bool eof, int ofs)
155 {
156   while (ofs < n)
157     {
158       ucs4_t uc;
159       int mblen;
160
161       mblen = segmenter_u8_to_uc__ (&uc, input, n, eof, ofs);
162       if (mblen < 0)
163         return -1;
164
165       if (uc == '/')
166         {
167           if (ofs + 1 >= n)
168             return eof ? ofs : -1;
169           else if (input[ofs + 1] != '*')
170             return ofs;
171
172           ofs = skip_comment (input, n, eof, ofs + 2);
173           if (ofs < 0)
174             return -1;
175         }
176       else if (lex_uc_is_space (uc) && uc != '\n')
177         ofs += mblen;
178       else
179         return ofs;
180     }
181
182   return eof ? ofs : -1;
183 }
184
185 static int
186 is_end_of_line (const char *input, size_t n, bool eof, int ofs)
187 {
188   if (ofs >= n)
189     return eof ? 1 : -1;
190   else if (input[ofs] == '\n')
191     return 1;
192   else if (input[ofs] == '\r')
193     {
194       if (ofs + 1 >= n)
195         return eof ? 1 : -1;
196       return input[ofs + 1] == '\n';
197     }
198   else
199     return 0;
200 }
201
202 static int
203 at_end_of_line (const char *input, size_t n, bool eof, int ofs)
204 {
205   ofs = skip_spaces_and_comments (input, n, eof, ofs);
206   if (ofs < 0)
207     return -1;
208
209   return is_end_of_line (input, n, eof, ofs);
210 }
211
212 static int
213 segmenter_parse_newline__ (const char *input, size_t n, bool eof,
214                            enum segment_type *type)
215 {
216   int ofs;
217
218   if (input[0] == '\n')
219     ofs = 1;
220   else
221     {
222       if (n < 2)
223         {
224           assert (!eof);
225           return -1;
226         }
227
228       assert (input[0] == '\r');
229       assert (input[1] == '\n');
230       ofs = 2;
231     }
232
233   *type = SEG_NEWLINE;
234   return ofs;
235 }
236
237 static int
238 skip_spaces (const char *input, size_t n, bool eof, size_t ofs)
239 {
240   while (ofs < n)
241     {
242       ucs4_t uc;
243       int mblen;
244
245       mblen = segmenter_u8_to_uc__ (&uc, input, n, eof, ofs);
246       if (mblen < 0)
247         return -1;
248
249       if (!lex_uc_is_space (uc) || uc == '\n')
250         return ofs;
251
252       ofs += mblen;
253     }
254
255   return eof ? ofs : -1;
256 }
257
258 static int
259 skip_digits (const char *input, size_t n, bool eof, int ofs)
260 {
261   for (; ofs < n; ofs++)
262     if (!c_isdigit (input[ofs]))
263       return ofs;
264   return eof ? ofs : -1;
265 }
266
267 static int
268 segmenter_parse_number__ (struct segmenter *s, const char *input, size_t n,
269                           bool eof, enum segment_type *type)
270 {
271   int ofs;
272
273   assert (s->state == S_GENERAL);
274
275   ofs = skip_digits (input, n, eof, 0);
276   if (ofs < 0)
277     return -1;
278
279   if (ofs >= n)
280     {
281       if (!eof)
282         return -1;
283       goto number;
284     };
285   if (input[ofs] == '.')
286     {
287       ofs = skip_digits (input, n, eof, ofs + 1);
288       if (ofs < 0)
289         return -1;
290     }
291
292   if (ofs >= n)
293     {
294       if (!eof)
295         return -1;
296       goto number;
297     }
298   if (input[ofs] == 'e' || input[ofs] == 'E')
299     {
300       ofs++;
301       if (ofs >= n)
302         {
303           if (!eof)
304             return -1;
305           goto expected_exponent;
306         }
307
308       if (input[ofs] == '+' || input[ofs] == '-')
309         {
310           ofs++;
311           if (ofs >= n)
312             {
313               if (!eof)
314                 return -1;
315               goto expected_exponent;
316             }
317         }
318
319       if (!c_isdigit (input[ofs]))
320         goto expected_exponent;
321
322       ofs = skip_digits (input, n, eof, ofs);
323       if (ofs < 0)
324         return -1;
325     }
326
327   if (input[ofs - 1] == '.')
328     {
329       int eol = at_end_of_line (input, n, eof, ofs);
330       if (eol < 0)
331         return -1;
332       else if (eol)
333         ofs--;
334     }
335
336 number:
337   *type = SEG_NUMBER;
338   s->substate = 0;
339   return ofs;
340
341 expected_exponent:
342   *type = SEG_EXPECTED_EXPONENT;
343   s->substate = 0;
344   return ofs;
345 }
346
347 static bool
348 is_reserved_word (const char *s, int n)
349 {
350   char s0, s1, s2, s3;
351
352   s0 = c_toupper (s[0]);
353   switch (n)
354     {
355     case 2:
356       s1 = c_toupper (s[1]);
357       return ((s0 == 'B' && s1 == 'Y')
358               || (s0 == 'E' && s1 == 'Q')
359               || (s0 == 'G' && (s1 == 'E' || s1 == 'T'))
360               || (s0 == 'L' && (s1 == 'E' || s1 == 'T'))
361               || (s0 == 'N' && s1 == 'E')
362               || (s0 == 'O' && s1 == 'R')
363               || (s0 == 'T' && s1 == 'O'));
364
365     case 3:
366       s1 = c_toupper (s[1]);
367       s2 = c_toupper (s[2]);
368       return ((s0 == 'A' && ((s1 == 'L' && s2 == 'L')
369                              || (s1 == 'N' && s2 == 'D')))
370               || (s0 == 'N' && s1 == 'O' && s2 == 'T'));
371
372     case 4:
373       s1 = c_toupper (s[1]);
374       s2 = c_toupper (s[2]);
375       s3 = c_toupper (s[3]);
376       return s0 == 'W' && s1 == 'I' && s2 == 'T' && s3 == 'H';
377
378     default:
379       return false;
380     }
381 }
382
383 static int
384 segmenter_parse_comment_1__ (struct segmenter *s,
385                              const char *input, size_t n, bool eof,
386                              enum segment_type *type)
387 {
388   int endcmd;
389   int ofs;
390
391   endcmd = -2;
392   ofs = 0;
393   while (ofs < n)
394     {
395       ucs4_t uc;
396       int mblen;
397
398       mblen = segmenter_u8_to_uc__ (&uc, input, n, eof, ofs);
399       if (mblen < 0)
400         return -1;
401
402       switch (uc)
403         {
404         case '.':
405           endcmd = ofs;
406           break;
407
408         case '\n':
409           if (ofs > 1 && input[ofs - 1] == '\r')
410             ofs--;
411           if (endcmd == -2)
412             {
413               /* Blank line ends comment command. */
414               s->state = S_GENERAL;
415               s->substate = SS_START_OF_COMMAND;
416               *type = SEG_SEPARATE_COMMANDS;
417               return ofs;
418             }
419           else if (endcmd >= 0)
420             {
421               /* '.' at end of line ends comment command. */
422               s->state = S_GENERAL;
423               s->substate = 0;
424               *type = SEG_COMMENT_COMMAND;
425               return endcmd;
426             }
427           else
428             {
429               /* Comment continues onto next line. */
430               *type = SEG_COMMENT_COMMAND;
431               s->state = S_COMMENT_2;
432               return ofs;
433             }
434           NOT_REACHED ();
435
436         default:
437           if (!lex_uc_is_space (uc))
438             endcmd = -1;
439           break;
440         }
441
442       ofs += mblen;
443     }
444
445   if (eof)
446     {
447       /* End of file. */
448       s->state = S_GENERAL;
449       s->substate = SS_START_OF_COMMAND;
450       *type = SEG_SEPARATE_COMMANDS;
451       return ofs;
452     }
453
454   return -1;
455 }
456
457 static int
458 segmenter_parse_comment_2__ (struct segmenter *s, const char *input,
459                              size_t n, bool eof, enum segment_type *type)
460 {
461   int ofs = segmenter_parse_newline__ (input, n, eof, type);
462   if (ofs < 0)
463     return -1;
464
465   int new_cmd;
466   if (ofs >= n)
467     {
468       if (!eof)
469         return -1;
470       new_cmd = false;
471     }
472   else
473     {
474       ucs4_t uc;
475       int mblen = segmenter_u8_to_uc__ (&uc, input, n, eof, ofs);
476       if (mblen < 0)
477         return -1;
478
479       if (uc == '+' || uc == '-' || uc == '.')
480         new_cmd = true;
481       else if (!lex_uc_is_space (uc))
482         switch (s->mode)
483           {
484           case SEG_MODE_INTERACTIVE:
485             new_cmd = false;
486             break;
487
488           case SEG_MODE_BATCH:
489             new_cmd = true;
490             break;
491
492           case SEG_MODE_AUTO:
493             new_cmd = segmenter_detect_command_name__ (input, n, eof, ofs);
494             if (new_cmd < 0)
495               return -1;
496             break;
497
498           default:
499             NOT_REACHED ();
500           }
501       else
502         new_cmd = false;
503     }
504
505   if (new_cmd)
506     {
507       s->state = S_GENERAL;
508       s->substate = SS_START_OF_LINE | SS_START_OF_COMMAND;
509     }
510   else
511     s->state = S_COMMENT_1;
512   return ofs;
513 }
514
515 static int
516 segmenter_parse_document_1__ (struct segmenter *s, const char *input, size_t n,
517                               bool eof, enum segment_type *type)
518 {
519   bool end_cmd;
520   int ofs;
521
522   end_cmd = false;
523   ofs = 0;
524   while (ofs < n)
525     {
526       ucs4_t uc;
527       int mblen;
528
529       mblen = segmenter_u8_to_uc__ (&uc, input, n, eof, ofs);
530       if (mblen < 0)
531         return -1;
532
533       switch (uc)
534         {
535         case '.':
536           end_cmd = true;
537           break;
538
539         case '\n':
540           if (ofs > 1 && input[ofs - 1] == '\r')
541             ofs--;
542
543           *type = SEG_DOCUMENT;
544           s->state = end_cmd ? S_DOCUMENT_3 : S_DOCUMENT_2;
545           return ofs;
546
547         default:
548           if (!lex_uc_is_space (uc))
549             end_cmd = false;
550           break;
551         }
552
553       ofs += mblen;
554     }
555   if (eof)
556     {
557       *type = SEG_DOCUMENT;
558       s->state = S_DOCUMENT_3;
559       return ofs;
560     }
561   return -1;
562 }
563
564 static int
565 segmenter_parse_document_2__ (struct segmenter *s, const char *input, size_t n,
566                               bool eof, enum segment_type *type)
567 {
568   int ofs;
569
570   ofs = segmenter_parse_newline__ (input, n, eof, type);
571   if (ofs < 0)
572     return -1;
573
574   s->state = S_DOCUMENT_1;
575   return ofs;
576 }
577
578 static int
579 segmenter_parse_document_3__ (struct segmenter *s, enum segment_type *type)
580 {
581   *type = SEG_END_COMMAND;
582   s->state = S_GENERAL;
583   s->substate = SS_START_OF_COMMAND | SS_START_OF_LINE;
584   return 0;
585 }
586
587 static int
588 segmenter_unquoted (const char *input, size_t n, bool eof, int ofs)
589
590 {
591   ofs = skip_spaces_and_comments (input, n, eof, ofs);
592   if (ofs < 0)
593     return -1;
594   else if (ofs < n)
595     {
596       char c = input[ofs];
597       return c != '\'' && c != '"' && c != '\n';
598     }
599   else
600     {
601       assert (eof);
602       return 0;
603     }
604 }
605
606 static int
607 next_id_in_command (const struct segmenter *s, const char *input, size_t n,
608                     bool eof, int ofs, char id[], size_t id_size)
609 {
610   struct segmenter sub;
611
612   assert (id_size > 0);
613
614   sub.mode = s->mode;
615   sub.state = S_GENERAL;
616   sub.substate = 0;
617   for (;;)
618     {
619       enum segment_type type;
620       int retval;
621
622       retval = segmenter_push (&sub, input + ofs, n - ofs, eof, &type);
623       if (retval < 0)
624         {
625           id[0] = '\0';
626           return -1;
627         }
628
629       switch (type)
630         {
631         case SEG_SHBANG:
632         case SEG_SPACES:
633         case SEG_COMMENT:
634         case SEG_NEWLINE:
635           break;
636
637         case SEG_IDENTIFIER:
638           if (retval < id_size)
639             {
640               memcpy (id, input + ofs, retval);
641               id[retval] = '\0';
642               return ofs + retval;
643             }
644           /* fall through */
645
646         case SEG_NUMBER:
647         case SEG_QUOTED_STRING:
648         case SEG_HEX_STRING:
649         case SEG_UNICODE_STRING:
650         case SEG_UNQUOTED_STRING:
651         case SEG_RESERVED_WORD:
652         case SEG_PUNCT:
653         case SEG_COMMENT_COMMAND:
654         case SEG_DO_REPEAT_COMMAND:
655         case SEG_INLINE_DATA:
656         case SEG_START_DOCUMENT:
657         case SEG_DOCUMENT:
658         case SEG_START_COMMAND:
659         case SEG_SEPARATE_COMMANDS:
660         case SEG_END_COMMAND:
661         case SEG_END:
662         case SEG_EXPECTED_QUOTE:
663         case SEG_EXPECTED_EXPONENT:
664         case SEG_UNEXPECTED_DOT:
665         case SEG_UNEXPECTED_CHAR:
666           id[0] = '\0';
667           return ofs + retval;
668         }
669       ofs += retval;
670     }
671 }
672
673 /* Called when INPUT begins with a character that can start off an ID token. */
674 static int
675 segmenter_parse_id__ (struct segmenter *s, const char *input, size_t n,
676                       bool eof, enum segment_type *type)
677 {
678   ucs4_t uc;
679   int ofs;
680
681   assert (n > 0);
682   assert (s->state == S_GENERAL);
683
684   ofs = u8_mbtouc (&uc, CHAR_CAST (const uint8_t *, input), n);
685   for (;;)
686     {
687       int mblen;
688
689       if (ofs >= n)
690         {
691           if (eof)
692             break;
693           return -1;
694         }
695
696       mblen = segmenter_u8_to_uc__ (&uc, input, n, eof, ofs);
697       if (mblen < 0)
698         return -1;
699       else if (!lex_uc_is_idn (uc))
700         break;
701
702       ofs += mblen;
703     }
704
705   if (input[ofs - 1] == '.')
706     {
707       int eol = at_end_of_line (input, n, eof, ofs);
708       if (eol < 0)
709         return -1;
710       else if (eol)
711         ofs--;
712     }
713
714   if (is_reserved_word (input, ofs))
715     *type = SEG_RESERVED_WORD;
716   else
717     *type = SEG_IDENTIFIER;
718
719   if (s->substate & SS_START_OF_COMMAND)
720     {
721       struct substring word = ss_buffer (input, ofs);
722
723       if (lex_id_match_n (ss_cstr ("COMMENT"), word, 4))
724         {
725           s->state = S_COMMENT_1;
726           return segmenter_parse_comment_1__ (s, input, n, eof, type);
727         }
728       else if (lex_id_match (ss_cstr ("DOCUMENT"), word))
729         {
730           s->state = S_DOCUMENT_1;
731           *type = SEG_START_DOCUMENT;
732           return 0;
733         }
734       else if (lex_id_match (ss_cstr ("TITLE"), word)
735                || lex_id_match (ss_cstr ("SUBTITLE"), word))
736         {
737           int result = segmenter_unquoted (input, n, eof, ofs);
738           if (result < 0)
739             return -1;
740           else if (result)
741             {
742               s->state = S_TITLE_1;
743               return ofs;
744             }
745         }
746       else if (lex_id_match (ss_cstr ("FILE"), word))
747         {
748           char id[16];
749
750           if (next_id_in_command (s, input, n, eof, ofs, id, sizeof id) < 0)
751             return -1;
752           else if (lex_id_match (ss_cstr ("LABEL"), ss_cstr (id)))
753             {
754               s->state = S_FILE_LABEL;
755               s->substate = 0;
756               return ofs;
757             }
758         }
759       else if (lex_id_match (ss_cstr ("DO"), word))
760         {
761           char id[16];
762
763           if (next_id_in_command (s, input, n, eof, ofs, id, sizeof id) < 0)
764             return -1;
765           else if (lex_id_match (ss_cstr ("REPEAT"), ss_cstr (id)))
766             {
767               s->state = S_DO_REPEAT_1;
768               s->substate = 0;
769               return ofs;
770             }
771         }
772       else if (lex_id_match (ss_cstr ("BEGIN"), word))
773         {
774           char id[16];
775           int ofs2;
776
777           ofs2 = next_id_in_command (s, input, n, eof, ofs, id, sizeof id);
778           if (ofs2 < 0)
779             return -1;
780           else if (lex_id_match (ss_cstr ("DATA"), ss_cstr (id)))
781             {
782               int eol;
783
784               ofs2 = skip_spaces_and_comments (input, n, eof, ofs2);
785               if (ofs2 < 0)
786                 return -1;
787
788               if (ofs2 >= n)
789                 assert (eof);
790               else if (input[ofs2] == '.')
791                 {
792                   ofs2 = skip_spaces_and_comments (input, n, eof, ofs2 + 1);
793                   if (ofs2 < 0)
794                     return -1;
795                 }
796
797               eol = is_end_of_line (input, n, eof, ofs2);
798               if (eol < 0)
799                 return -1;
800               else if (eol)
801                 {
802                   if (memchr (input, '\n', ofs2))
803                     s->state = S_BEGIN_DATA_1;
804                   else
805                     s->state = S_BEGIN_DATA_2;
806                   s->substate = 0;
807                   return ofs;
808                 }
809             }
810         }
811     }
812
813   s->substate = 0;
814   return ofs;
815 }
816
817 static int
818 segmenter_parse_string__ (enum segment_type string_type,
819                           int ofs, struct segmenter *s,
820                           const char *input, size_t n, bool eof,
821                           enum segment_type *type)
822 {
823   int quote = input[ofs];
824
825   ofs++;
826   while (ofs < n)
827     if (input[ofs] == quote)
828       {
829         ofs++;
830         if (ofs < n)
831           {
832             if (input[ofs] == quote)
833               {
834                 ofs++;
835                 continue;
836               }
837           }
838         else if (!eof)
839           return -1;
840
841         *type = string_type;
842         s->substate = 0;
843         return ofs;
844       }
845     else if (input[ofs] == '\n')
846       goto expected_quote;
847     else
848       ofs++;
849
850   if (eof)
851     goto expected_quote;
852
853   return -1;
854
855 expected_quote:
856   *type = SEG_EXPECTED_QUOTE;
857   s->substate = 0;
858   return ofs;
859 }
860
861 static int
862 segmenter_maybe_parse_string__ (enum segment_type string_type,
863                                 struct segmenter *s,
864                                 const char *input, size_t n, bool eof,
865                                 enum segment_type *type)
866 {
867   if (n < 2)
868     {
869       if (!eof)
870         return -1;
871     }
872   else if (input[1] == '\'' || input[1] == '"')
873     return segmenter_parse_string__ (string_type, 1, s, input, n, eof, type);
874
875   return segmenter_parse_id__ (s, input, n, eof, type);
876 }
877
878 static int
879 segmenter_parse_mid_command__ (struct segmenter *s,
880                                const char *input, size_t n, bool eof,
881                                enum segment_type *type)
882 {
883   ucs4_t uc;
884   int mblen;
885   int ofs;
886
887   assert (s->state == S_GENERAL);
888   assert (!(s->substate & SS_START_OF_LINE));
889
890   mblen = segmenter_u8_to_uc__ (&uc, input, n, eof, 0);
891   if (mblen < 0)
892     return -1;
893
894   switch (uc)
895     {
896     case '\n':
897       s->substate |= SS_START_OF_LINE;
898       *type = SEG_NEWLINE;
899       return 1;
900
901     case '/':
902       if (n < 2)
903         {
904           if (!eof)
905             return -1;
906         }
907       else if (input[1] == '*')
908         {
909           ofs = skip_comment (input, n, eof, 2);
910           if (ofs < 0)
911             return -1;
912
913           *type = SEG_COMMENT;
914           return ofs;
915         }
916
917       s->substate = 0;
918       *type = SEG_PUNCT;
919       return 1;
920
921     case '(': case ')': case ',': case '=': case '-':
922     case '[': case ']': case '&': case '|': case '+':
923       *type = SEG_PUNCT;
924       s->substate = 0;
925       return 1;
926
927     case '*':
928       if (s->substate & SS_START_OF_COMMAND)
929         {
930           /* '*' at the beginning of a command begins a comment. */
931           s->state = S_COMMENT_1;
932           return segmenter_parse_comment_1__ (s, input, n, eof, type);
933         }
934       else
935         return segmenter_parse_digraph__ ("*", s, input, n, eof, type);
936
937     case '<':
938       return segmenter_parse_digraph__ ("=>", s, input, n, eof, type);
939
940     case '>':
941       return segmenter_parse_digraph__ ("=", s, input, n, eof, type);
942
943     case '~':
944       return segmenter_parse_digraph__ ("=", s, input, n, eof, type);
945
946     case '.':
947       if (n < 2)
948         {
949           if (!eof)
950             return -1;
951         }
952       else if (c_isdigit (input[1]))
953         return segmenter_parse_number__ (s, input, n, eof, type);
954
955       int eol = at_end_of_line (input, n, eof, 1);
956       if (eol < 0)
957         return -1;
958
959       if (eol)
960         {
961           *type = SEG_END_COMMAND;
962           s->substate = SS_START_OF_COMMAND;
963         }
964       else
965         *type = SEG_UNEXPECTED_DOT;
966       return 1;
967
968     case '0': case '1': case '2': case '3': case '4':
969     case '5': case '6': case '7': case '8': case '9':
970       return segmenter_parse_number__ (s, input, n, eof, type);
971
972     case 'u': case 'U':
973       return segmenter_maybe_parse_string__ (SEG_UNICODE_STRING,
974                                              s, input, n, eof, type);
975
976     case 'x': case 'X':
977       return segmenter_maybe_parse_string__ (SEG_HEX_STRING,
978                                              s, input, n, eof, type);
979
980     case '\'': case '"':
981       return segmenter_parse_string__ (SEG_QUOTED_STRING, 0,
982                                        s, input, n, eof, type);
983
984     default:
985       if (lex_uc_is_space (uc))
986         {
987           ofs = skip_spaces (input, n, eof, mblen);
988           if (ofs < 0)
989             return -1;
990
991           if (input[ofs - 1] == '\r' && input[ofs] == '\n')
992             {
993               if (ofs == 1)
994                 {
995                   s->substate |= SS_START_OF_LINE;
996                   *type = SEG_NEWLINE;
997                   return 2;
998                 }
999               else
1000                 ofs--;
1001             }
1002           *type = SEG_SPACES;
1003           return ofs;
1004         }
1005       else if (lex_uc_is_id1 (uc))
1006         return segmenter_parse_id__ (s, input, n, eof, type);
1007       else
1008         {
1009           *type = SEG_UNEXPECTED_CHAR;
1010           s->substate = 0;
1011           return mblen;
1012         }
1013     }
1014 }
1015
1016 static int
1017 compare_commands (const void *a_, const void *b_)
1018 {
1019   const char *const *ap = a_;
1020   const char *const *bp = b_;
1021   const char *a = *ap;
1022   const char *b = *bp;
1023
1024   return c_strcasecmp (a, b);
1025 }
1026
1027 static const char **
1028 segmenter_get_command_name_candidates (unsigned char first)
1029 {
1030 #define DEF_CMD(STATES, FLAGS, NAME, FUNCTION) NAME,
1031 #define UNIMPL_CMD(NAME, DESCRIPTION) NAME,
1032   static const char *commands[] =
1033     {
1034 #include "language/command.def"
1035       ""
1036     };
1037   static size_t n_commands = (sizeof commands / sizeof *commands) - 1;
1038 #undef DEF_CMD
1039 #undef UNIMPL_CMD
1040
1041   static bool inited;
1042
1043   static const char **cindex[UCHAR_MAX + 1];
1044
1045   if (!inited)
1046     {
1047       size_t i;
1048
1049       inited = true;
1050
1051       qsort (commands, n_commands, sizeof *commands, compare_commands);
1052       for (i = 0; i < n_commands; i++)
1053         {
1054           unsigned char c = c_toupper (commands[i][0]);
1055           if (cindex[c] == NULL)
1056             cindex[c] = &commands[i];
1057         }
1058       for (i = 0; i <= UCHAR_MAX; i++)
1059         if (cindex[i] == NULL)
1060           cindex[i] = &commands[n_commands];
1061     }
1062
1063   return cindex[c_toupper (first)];
1064 }
1065
1066 static int
1067 segmenter_detect_command_name__ (const char *input, size_t n, bool eof,
1068                                  int ofs)
1069 {
1070   const char **commands;
1071
1072   input += ofs;
1073   n -= ofs;
1074   ofs = 0;
1075   for (;;)
1076     {
1077       ucs4_t uc;
1078       int mblen;
1079
1080       if (ofs >= n)
1081         {
1082           if (eof)
1083             break;
1084           return -1;
1085         }
1086
1087       mblen = segmenter_u8_to_uc__ (&uc, input, n, eof, ofs);
1088       if (mblen < 0)
1089         return -1;
1090
1091       if (uc == '\n'
1092           || !(lex_uc_is_space (uc) || lex_uc_is_idn (uc) || uc == '-'))
1093         break;
1094
1095       ofs += mblen;
1096     }
1097   if (!ofs)
1098     return 0;
1099
1100   if (input[ofs - 1] == '.')
1101     ofs--;
1102
1103   for (commands = segmenter_get_command_name_candidates (input[0]);
1104        c_toupper (input[0]) == c_toupper ((*commands)[0]);
1105        commands++)
1106     {
1107       int missing_words;
1108       bool exact;
1109
1110       if (command_match (ss_cstr (*commands), ss_buffer (input, ofs),
1111                          &exact, &missing_words)
1112           && missing_words <= 0)
1113         return 1;
1114     }
1115
1116   return 0;
1117 }
1118
1119 static int
1120 is_start_of_string__ (const char *input, size_t n, bool eof, int ofs)
1121 {
1122   if (ofs >= n)
1123     return eof ? 0 : -1;
1124
1125   int c = input[ofs];
1126   if (c == 'x' || c == 'X' || c == 'u' || c == 'U')
1127     {
1128       if (ofs + 1 >= n)
1129         return eof ? 0 : -1;
1130
1131       return input[ofs + 1] == '\'' || input[ofs + 1] == '"';
1132     }
1133   else
1134     return c == '\'' || c == '"' || c == '\n';
1135 }
1136
1137 static int
1138 segmenter_parse_start_of_line__ (struct segmenter *s,
1139                                  const char *input, size_t n, bool eof,
1140                                  enum segment_type *type)
1141 {
1142   ucs4_t uc;
1143   int mblen;
1144   int ofs;
1145
1146   assert (s->state == S_GENERAL);
1147   assert (s->substate & SS_START_OF_LINE);
1148
1149   mblen = segmenter_u8_to_uc__ (&uc, input, n, eof, 0);
1150   if (mblen < 0)
1151     return -1;
1152
1153   switch (uc)
1154     {
1155     case '+':
1156       ofs = skip_spaces_and_comments (input, n, eof, 1);
1157       if (ofs < 0)
1158         return -1;
1159       else
1160         {
1161           int is_string = is_start_of_string__ (input, n, eof, ofs);
1162           if (is_string < 0)
1163             return -1;
1164           else if (is_string)
1165             {
1166               /* This is punctuation that may separate pieces of a string. */
1167               *type = SEG_PUNCT;
1168               s->substate = 0;
1169               return 1;
1170             }
1171         }
1172       /* Fall through. */
1173
1174     case '-':
1175     case '.':
1176       *type = SEG_START_COMMAND;
1177       s->substate = SS_START_OF_COMMAND;
1178       return 1;
1179
1180     default:
1181       if (lex_uc_is_space (uc))
1182         {
1183           int eol = at_end_of_line (input, n, eof, 0);
1184           if (eol < 0)
1185             return -1;
1186           else if (eol)
1187             {
1188               s->substate = SS_START_OF_COMMAND;
1189               *type = SEG_SEPARATE_COMMANDS;
1190               return 0;
1191             }
1192           break;
1193         }
1194
1195       if (s->mode == SEG_MODE_INTERACTIVE || s->substate & SS_START_OF_COMMAND)
1196         break;
1197       else if (s->mode == SEG_MODE_AUTO)
1198         {
1199           int cmd = segmenter_detect_command_name__ (input, n, eof, 0);
1200           if (cmd < 0)
1201             return -1;
1202           else if (cmd == 0)
1203             break;
1204         }
1205       else
1206         assert (s->mode == SEG_MODE_BATCH);
1207
1208       s->substate = SS_START_OF_COMMAND;
1209       *type = SEG_START_COMMAND;
1210       return 0;
1211     }
1212
1213   s->substate = SS_START_OF_COMMAND;
1214   return segmenter_parse_mid_command__ (s, input, n, eof, type);
1215 }
1216
1217 static int
1218 segmenter_parse_file_label__ (struct segmenter *s,
1219                               const char *input, size_t n, bool eof,
1220                               enum segment_type *type)
1221 {
1222   struct segmenter sub;
1223   int ofs;
1224
1225   sub = *s;
1226   sub.state = S_GENERAL;
1227   ofs = segmenter_push (&sub, input, n, eof, type);
1228
1229   if (ofs < 0)
1230     return -1;
1231   else if (*type == SEG_IDENTIFIER)
1232     {
1233       int result;
1234
1235       assert (lex_id_match (ss_cstr ("LABEL"),
1236                             ss_buffer ((char *) input, ofs)));
1237       result = segmenter_unquoted (input, n, eof, ofs);
1238       if (result < 0)
1239         return -1;
1240       else
1241         {
1242           if (result)
1243             s->state = S_TITLE_1;
1244           else
1245             *s = sub;
1246           return ofs;
1247         }
1248     }
1249   else
1250     {
1251       s->substate = sub.substate;
1252       return ofs;
1253     }
1254 }
1255
1256 static int
1257 segmenter_subparse (struct segmenter *s,
1258                     const char *input, size_t n, bool eof,
1259                     enum segment_type *type)
1260 {
1261   struct segmenter sub;
1262   int ofs;
1263
1264   sub.mode = s->mode;
1265   sub.state = S_GENERAL;
1266   sub.substate = s->substate;
1267   ofs = segmenter_push (&sub, input, n, eof, type);
1268   s->substate = sub.substate;
1269   return ofs;
1270 }
1271
1272 static int
1273 segmenter_parse_do_repeat_1__ (struct segmenter *s,
1274                                const char *input, size_t n, bool eof,
1275                                enum segment_type *type)
1276 {
1277   int ofs = segmenter_subparse (s, input, n, eof, type);
1278   if (ofs < 0)
1279     return -1;
1280
1281   if (*type == SEG_START_COMMAND || *type == SEG_SEPARATE_COMMANDS)
1282     s->state = S_DO_REPEAT_2;
1283   else if (*type == SEG_END_COMMAND)
1284     {
1285       s->state = S_DO_REPEAT_3;
1286       s->substate = 1;
1287     }
1288
1289   return ofs;
1290 }
1291
1292 static int
1293 segmenter_parse_do_repeat_2__ (struct segmenter *s,
1294                                const char *input, size_t n, bool eof,
1295                                enum segment_type *type)
1296 {
1297   int ofs = segmenter_subparse (s, input, n, eof, type);
1298   if (ofs < 0)
1299     return -1;
1300
1301   if (*type == SEG_NEWLINE)
1302     {
1303       s->state = S_DO_REPEAT_3;
1304       s->substate = 1;
1305     }
1306
1307   return ofs;
1308 }
1309
1310 static bool
1311 check_repeat_command (struct segmenter *s,
1312                       const char *input, size_t n, bool eof)
1313 {
1314   int direction;
1315   char id[16];
1316   int ofs;
1317
1318   ofs = 0;
1319   if (input[ofs] == '+' || input[ofs] == '-')
1320     ofs++;
1321
1322   ofs = next_id_in_command (s, input, n, eof, ofs, id, sizeof id);
1323   if (ofs < 0)
1324     return false;
1325   else if (lex_id_match (ss_cstr ("DO"), ss_cstr (id)))
1326     direction = 1;
1327   else if (lex_id_match (ss_cstr ("END"), ss_cstr (id)))
1328     direction = -1;
1329   else
1330     return true;
1331
1332   ofs = next_id_in_command (s, input, n, eof, ofs, id, sizeof id);
1333   if (ofs < 0)
1334     return false;
1335
1336   if (lex_id_match (ss_cstr ("REPEAT"), ss_cstr (id)))
1337     s->substate += direction;
1338   return true;
1339 }
1340
1341 static int
1342 segmenter_parse_full_line__ (const char *input, size_t n, bool eof,
1343                              enum segment_type *type)
1344 {
1345   const char *newline = memchr (input, '\n', n);
1346   if (!newline)
1347     return eof ? n : -1;
1348
1349   ptrdiff_t ofs = newline - input;
1350   if (ofs == 0 || (ofs == 1 && input[0] == '\r'))
1351     {
1352       *type = SEG_NEWLINE;
1353       return ofs + 1;
1354     }
1355   else
1356     return ofs - (input[ofs - 1] == '\r');
1357 }
1358
1359 static int
1360 segmenter_parse_do_repeat_3__ (struct segmenter *s,
1361                                const char *input, size_t n, bool eof,
1362                                enum segment_type *type)
1363 {
1364   int ofs;
1365
1366   ofs = segmenter_parse_full_line__ (input, n, eof, type);
1367   if (ofs < 0 || (ofs > 0 && input[ofs - 1] == '\n'))
1368     return ofs;
1369   else if (!check_repeat_command (s, input, n, eof) && !eof)
1370     return -1;
1371   else if (s->substate == 0)
1372     {
1373       s->state = S_GENERAL;
1374       s->substate = SS_START_OF_COMMAND | SS_START_OF_LINE;
1375       return segmenter_push (s, input, n, eof, type);
1376     }
1377   else
1378     {
1379       *type = SEG_DO_REPEAT_COMMAND;
1380       return ofs;
1381     }
1382 }
1383
1384 static int
1385 segmenter_parse_begin_data_1__ (struct segmenter *s,
1386                                 const char *input, size_t n, bool eof,
1387                                 enum segment_type *type)
1388 {
1389   int ofs = segmenter_subparse (s, input, n, eof, type);
1390   if (ofs < 0)
1391     return -1;
1392
1393   if (*type == SEG_NEWLINE)
1394     s->state = S_BEGIN_DATA_2;
1395
1396   return ofs;
1397 }
1398
1399 static int
1400 segmenter_parse_begin_data_2__ (struct segmenter *s,
1401                                 const char *input, size_t n, bool eof,
1402                                 enum segment_type *type)
1403 {
1404   int ofs = segmenter_subparse (s, input, n, eof, type);
1405   if (ofs < 0)
1406     return -1;
1407
1408   if (*type == SEG_NEWLINE)
1409     s->state = S_BEGIN_DATA_3;
1410
1411   return ofs;
1412 }
1413
1414 static bool
1415 is_end_data (const char *input, size_t n)
1416 {
1417   const uint8_t *u_input = CHAR_CAST (const uint8_t *, input);
1418   bool endcmd;
1419   ucs4_t uc;
1420   int mblen;
1421   int ofs;
1422
1423   if (n < 4 || c_strncasecmp (input, "END", 3))
1424     return false;
1425
1426   ofs = 3;
1427   mblen = u8_mbtouc (&uc, u_input + ofs, n - ofs);
1428   if (!lex_uc_is_space (uc))
1429     return false;
1430   ofs += mblen;
1431
1432   if (n - ofs < 4 || c_strncasecmp (input + ofs, "DATA", 4))
1433     return false;
1434   ofs += 4;
1435
1436   endcmd = false;
1437   while (ofs < n)
1438     {
1439       mblen = u8_mbtouc (&uc, u_input + ofs, n - ofs);
1440       if (uc == '.')
1441         {
1442           if (endcmd)
1443             return false;
1444           endcmd = true;
1445         }
1446       else if (!lex_uc_is_space (uc))
1447         return false;
1448       ofs += mblen;
1449     }
1450
1451   return true;
1452 }
1453
1454 static int
1455 segmenter_parse_begin_data_3__ (struct segmenter *s,
1456                                 const char *input, size_t n, bool eof,
1457                                 enum segment_type *type)
1458 {
1459   int ofs;
1460
1461   ofs = segmenter_parse_full_line__ (input, n, eof, type);
1462   if (ofs < 0)
1463     return -1;
1464   else if (is_end_data (input, ofs))
1465     {
1466       s->state = S_GENERAL;
1467       s->substate = SS_START_OF_COMMAND | SS_START_OF_LINE;
1468       return segmenter_push (s, input, n, eof, type);
1469     }
1470   else
1471     {
1472       *type = SEG_INLINE_DATA;
1473       s->state = S_BEGIN_DATA_4;
1474       return input[ofs - 1] == '\n' ? 0 : ofs;
1475     }
1476 }
1477
1478 static int
1479 segmenter_parse_begin_data_4__ (struct segmenter *s,
1480                                 const char *input, size_t n, bool eof,
1481                                 enum segment_type *type)
1482 {
1483   int ofs;
1484
1485   ofs = segmenter_parse_newline__ (input, n, eof, type);
1486   if (ofs < 0)
1487     return -1;
1488
1489   s->state = S_BEGIN_DATA_3;
1490   return ofs;
1491 }
1492
1493 static int
1494 segmenter_parse_title_1__ (struct segmenter *s,
1495                            const char *input, size_t n, bool eof,
1496                            enum segment_type *type)
1497 {
1498   int ofs;
1499
1500   ofs = skip_spaces (input, n, eof, 0);
1501   if (ofs < 0)
1502     return -1;
1503   s->state = S_TITLE_2;
1504   *type = SEG_SPACES;
1505   return ofs;
1506 }
1507
1508 static int
1509 segmenter_parse_title_2__ (struct segmenter *s,
1510                            const char *input, size_t n, bool eof,
1511                            enum segment_type *type)
1512 {
1513   int endcmd;
1514   int ofs;
1515
1516   endcmd = -1;
1517   ofs = 0;
1518   while (ofs < n)
1519     {
1520       ucs4_t uc;
1521       int mblen;
1522
1523       mblen = segmenter_u8_to_uc__ (&uc, input, n, eof, ofs);
1524       if (mblen < 0)
1525         return -1;
1526
1527       switch (uc)
1528         {
1529         case '\n':
1530           goto end_of_line;
1531
1532         case '.':
1533           endcmd = ofs;
1534           break;
1535
1536         default:
1537           if (!lex_uc_is_space (uc))
1538             endcmd = -1;
1539           break;
1540         }
1541
1542       ofs += mblen;
1543     }
1544
1545   if (eof)
1546     {
1547     end_of_line:
1548       s->state = S_GENERAL;
1549       s->substate = 0;
1550       *type = SEG_UNQUOTED_STRING;
1551       return endcmd >= 0 ? endcmd : ofs;
1552     }
1553
1554   return -1;
1555 }
1556
1557 /* Returns the name of segment TYPE as a string.  The caller must not modify
1558    or free the returned string.
1559
1560    This is useful only for debugging and testing. */
1561 const char *
1562 segment_type_to_string (enum segment_type type)
1563 {
1564   switch (type)
1565     {
1566 #define SEG_TYPE(NAME) case SEG_##NAME: return #NAME;
1567       SEG_TYPES
1568 #undef SEG_TYPE
1569     default:
1570       return "unknown segment type";
1571     }
1572 }
1573
1574 /* Initializes S as a segmenter with the given syntax MODE.
1575
1576    A segmenter does not contain any external references, so nothing needs to be
1577    done to destroy one.  For the same reason, segmenters may be copied with
1578    plain struct assignment (or memcpy). */
1579 void
1580 segmenter_init (struct segmenter *s, enum segmenter_mode mode)
1581 {
1582   s->state = S_SHBANG;
1583   s->substate = 0;
1584   s->mode = mode;
1585 }
1586
1587 /* Returns the mode passed to segmenter_init() for S. */
1588 enum segmenter_mode
1589 segmenter_get_mode (const struct segmenter *s)
1590 {
1591   return s->mode;
1592 }
1593
1594 /* Attempts to label a prefix of S's remaining input with a segment type.  The
1595    caller supplies the first N bytes of the remaining input as INPUT, which
1596    must be a UTF-8 encoded string.  If EOF is true, then the N bytes supplied
1597    are the entire (remainder) of the input; if EOF is false, then further input
1598    is potentially available.
1599
1600    The input may contain '\n' or '\r\n' line ends in any combination.
1601
1602    If successful, returns the number of bytes in the segment at the beginning
1603    of INPUT (between 0 and N, inclusive) and stores the type of that segment
1604    into *TYPE.  The next call to segmenter_push() should not include those
1605    bytes as part of INPUT, because they have (figuratively) been consumed by
1606    the segmenter.
1607
1608    Failure occurs only if the segment type of the N bytes in INPUT cannot yet
1609    be determined.  In this case segmenter_push() returns -1.  If more input is
1610    available, the caller should obtain some more, then call again with a larger
1611    N.  If this is not enough, the process might need to repeat again and agin.
1612    If input is exhausted, then the caller may call again setting EOF to true.
1613    segmenter_push() will never return -1 when EOF is true.
1614
1615    The caller must not, in a sequence of calls, supply contradictory input.
1616    That is, bytes provided as part of INPUT in one call, but not consumed, must
1617    not be provided with *different* values on subsequent calls.  This is
1618    because segmenter_push() must often make decisions based on looking ahead
1619    beyond the bytes that it consumes. */
1620 int
1621 segmenter_push (struct segmenter *s, const char *input, size_t n, bool eof,
1622                 enum segment_type *type)
1623 {
1624   if (!n)
1625     {
1626       if (eof)
1627         {
1628           *type = SEG_END;
1629           return 0;
1630         }
1631       else
1632         return -1;
1633     }
1634
1635   switch (s->state)
1636     {
1637     case S_SHBANG:
1638       return segmenter_parse_shbang__ (s, input, n, eof, type);
1639
1640     case S_GENERAL:
1641       return (s->substate & SS_START_OF_LINE
1642               ? segmenter_parse_start_of_line__ (s, input, n, eof, type)
1643               : segmenter_parse_mid_command__ (s, input, n, eof, type));
1644
1645     case S_COMMENT_1:
1646       return segmenter_parse_comment_1__ (s, input, n, eof, type);
1647     case S_COMMENT_2:
1648       return segmenter_parse_comment_2__ (s, input, n, eof, type);
1649
1650     case S_DOCUMENT_1:
1651       return segmenter_parse_document_1__ (s, input, n, eof, type);
1652     case S_DOCUMENT_2:
1653       return segmenter_parse_document_2__ (s, input, n, eof, type);
1654     case S_DOCUMENT_3:
1655       return segmenter_parse_document_3__ (s, type);
1656
1657     case S_FILE_LABEL:
1658       return segmenter_parse_file_label__ (s, input, n, eof, type);
1659
1660     case S_DO_REPEAT_1:
1661       return segmenter_parse_do_repeat_1__ (s, input, n, eof, type);
1662     case S_DO_REPEAT_2:
1663       return segmenter_parse_do_repeat_2__ (s, input, n, eof, type);
1664     case S_DO_REPEAT_3:
1665       return segmenter_parse_do_repeat_3__ (s, input, n, eof, type);
1666
1667     case S_BEGIN_DATA_1:
1668       return segmenter_parse_begin_data_1__ (s, input, n, eof, type);
1669     case S_BEGIN_DATA_2:
1670       return segmenter_parse_begin_data_2__ (s, input, n, eof, type);
1671     case S_BEGIN_DATA_3:
1672       return segmenter_parse_begin_data_3__ (s, input, n, eof, type);
1673     case S_BEGIN_DATA_4:
1674       return segmenter_parse_begin_data_4__ (s, input, n, eof, type);
1675
1676     case S_TITLE_1:
1677       return segmenter_parse_title_1__ (s, input, n, eof, type);
1678     case S_TITLE_2:
1679       return segmenter_parse_title_2__ (s, input, n, eof, type);
1680     }
1681
1682   NOT_REACHED ();
1683 }
1684
1685 /* Returns the style of command prompt to display to an interactive user for
1686    input in S.  The return value is most accurate in mode SEG_MODE_INTERACTIVE
1687    and at the beginning of a line (that is, if segmenter_push() consumed as
1688    much as possible of the input up to a new-line).  */
1689 enum prompt_style
1690 segmenter_get_prompt (const struct segmenter *s)
1691 {
1692   switch (s->state)
1693     {
1694     case S_SHBANG:
1695       return PROMPT_FIRST;
1696
1697     case S_GENERAL:
1698       return s->substate & SS_START_OF_COMMAND ? PROMPT_FIRST : PROMPT_LATER;
1699
1700     case S_COMMENT_1:
1701     case S_COMMENT_2:
1702       return PROMPT_COMMENT;
1703
1704     case S_DOCUMENT_1:
1705     case S_DOCUMENT_2:
1706       return PROMPT_DOCUMENT;
1707     case S_DOCUMENT_3:
1708       return PROMPT_FIRST;
1709
1710     case S_FILE_LABEL:
1711       return PROMPT_LATER;
1712
1713     case S_DO_REPEAT_1:
1714     case S_DO_REPEAT_2:
1715       return s->substate & SS_START_OF_COMMAND ? PROMPT_FIRST : PROMPT_LATER;
1716     case S_DO_REPEAT_3:
1717       return PROMPT_DO_REPEAT;
1718
1719     case S_BEGIN_DATA_1:
1720       return PROMPT_FIRST;
1721     case S_BEGIN_DATA_2:
1722       return PROMPT_LATER;
1723     case S_BEGIN_DATA_3:
1724     case S_BEGIN_DATA_4:
1725       return PROMPT_DATA;
1726
1727     case S_TITLE_1:
1728     case S_TITLE_2:
1729       return PROMPT_FIRST;
1730     }
1731
1732   NOT_REACHED ();
1733 }