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