5f7fc01310d4241288b39d038ceb1294c25c46f6
[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_MACRO_ID:
655         case SEG_NUMBER:
656         case SEG_QUOTED_STRING:
657         case SEG_HEX_STRING:
658         case SEG_UNICODE_STRING:
659         case SEG_UNQUOTED_STRING:
660         case SEG_RESERVED_WORD:
661         case SEG_PUNCT:
662         case SEG_COMMENT_COMMAND:
663         case SEG_DO_REPEAT_COMMAND:
664         case SEG_INLINE_DATA:
665         case SEG_START_DOCUMENT:
666         case SEG_DOCUMENT:
667         case SEG_START_COMMAND:
668         case SEG_SEPARATE_COMMANDS:
669         case SEG_END_COMMAND:
670         case SEG_END:
671         case SEG_EXPECTED_QUOTE:
672         case SEG_EXPECTED_EXPONENT:
673         case SEG_UNEXPECTED_DOT:
674         case SEG_UNEXPECTED_CHAR:
675           id[0] = '\0';
676           return ofs + retval;
677         }
678       ofs += retval;
679     }
680 }
681
682 /* Called when INPUT begins with a character that can start off an ID token. */
683 static int
684 segmenter_parse_id__ (struct segmenter *s, const char *input, size_t n,
685                       bool eof, enum segment_type *type)
686 {
687   ucs4_t uc;
688   int ofs;
689
690   assert (n > 0);
691   assert (s->state == S_GENERAL);
692
693   ofs = u8_mbtouc (&uc, CHAR_CAST (const uint8_t *, input), n);
694   for (;;)
695     {
696       int mblen;
697
698       if (ofs >= n)
699         {
700           if (eof)
701             break;
702           return -1;
703         }
704
705       mblen = segmenter_u8_to_uc__ (&uc, input, n, eof, ofs);
706       if (mblen < 0)
707         return -1;
708       else if (!lex_uc_is_idn (uc))
709         break;
710
711       ofs += mblen;
712     }
713
714   if (input[ofs - 1] == '.')
715     {
716       int eol = at_end_of_line (input, n, eof, ofs);
717       if (eol < 0)
718         return -1;
719       else if (eol)
720         ofs--;
721     }
722
723   *type = (is_reserved_word (input, ofs) ? SEG_RESERVED_WORD
724            : input[0] == '!' ? SEG_MACRO_ID
725            : 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     case '!':
993       return segmenter_parse_id__ (s, input, n, eof, type);
994
995     default:
996       if (lex_uc_is_space (uc))
997         {
998           ofs = skip_spaces (input, n, eof, mblen);
999           if (ofs < 0)
1000             return -1;
1001
1002           if (input[ofs - 1] == '\r' && input[ofs] == '\n')
1003             {
1004               if (ofs == 1)
1005                 {
1006                   s->substate |= SS_START_OF_LINE;
1007                   *type = SEG_NEWLINE;
1008                   return 2;
1009                 }
1010               else
1011                 ofs--;
1012             }
1013           *type = SEG_SPACES;
1014           return ofs;
1015         }
1016       else if (lex_uc_is_id1 (uc))
1017         return segmenter_parse_id__ (s, input, n, eof, type);
1018       else if (uc > 32 && uc < 127 && uc != '\\' && uc != '^')
1019         {
1020           *type = SEG_PUNCT;
1021           s->substate = 0;
1022           return 1;
1023         }
1024       else
1025         {
1026           *type = SEG_UNEXPECTED_CHAR;
1027           s->substate = 0;
1028           return mblen;
1029         }
1030     }
1031 }
1032
1033 static int
1034 compare_commands (const void *a_, const void *b_)
1035 {
1036   const char *const *ap = a_;
1037   const char *const *bp = b_;
1038   const char *a = *ap;
1039   const char *b = *bp;
1040
1041   return c_strcasecmp (a, b);
1042 }
1043
1044 static const char **
1045 segmenter_get_command_name_candidates (unsigned char first)
1046 {
1047 #define DEF_CMD(STATES, FLAGS, NAME, FUNCTION) NAME,
1048 #define UNIMPL_CMD(NAME, DESCRIPTION) NAME,
1049   static const char *commands[] =
1050     {
1051 #include "language/command.def"
1052       ""
1053     };
1054   static size_t n_commands = (sizeof commands / sizeof *commands) - 1;
1055 #undef DEF_CMD
1056 #undef UNIMPL_CMD
1057
1058   static bool inited;
1059
1060   static const char **cindex[UCHAR_MAX + 1];
1061
1062   if (!inited)
1063     {
1064       size_t i;
1065
1066       inited = true;
1067
1068       qsort (commands, n_commands, sizeof *commands, compare_commands);
1069       for (i = 0; i < n_commands; i++)
1070         {
1071           unsigned char c = c_toupper (commands[i][0]);
1072           if (cindex[c] == NULL)
1073             cindex[c] = &commands[i];
1074         }
1075       for (i = 0; i <= UCHAR_MAX; i++)
1076         if (cindex[i] == NULL)
1077           cindex[i] = &commands[n_commands];
1078     }
1079
1080   return cindex[c_toupper (first)];
1081 }
1082
1083 static int
1084 segmenter_detect_command_name__ (const char *input, size_t n, bool eof,
1085                                  int ofs)
1086 {
1087   const char **commands;
1088
1089   input += ofs;
1090   n -= ofs;
1091   ofs = 0;
1092   for (;;)
1093     {
1094       ucs4_t uc;
1095       int mblen;
1096
1097       if (ofs >= n)
1098         {
1099           if (eof)
1100             break;
1101           return -1;
1102         }
1103
1104       mblen = segmenter_u8_to_uc__ (&uc, input, n, eof, ofs);
1105       if (mblen < 0)
1106         return -1;
1107
1108       if (uc == '\n'
1109           || !(lex_uc_is_space (uc) || lex_uc_is_idn (uc) || uc == '-'))
1110         break;
1111
1112       ofs += mblen;
1113     }
1114   if (!ofs)
1115     return 0;
1116
1117   if (input[ofs - 1] == '.')
1118     ofs--;
1119
1120   for (commands = segmenter_get_command_name_candidates (input[0]);
1121        c_toupper (input[0]) == c_toupper ((*commands)[0]);
1122        commands++)
1123     {
1124       int missing_words;
1125       bool exact;
1126
1127       if (command_match (ss_cstr (*commands), ss_buffer (input, ofs),
1128                          &exact, &missing_words)
1129           && missing_words <= 0)
1130         return 1;
1131     }
1132
1133   return 0;
1134 }
1135
1136 static int
1137 is_start_of_string__ (const char *input, size_t n, bool eof, int ofs)
1138 {
1139   if (ofs >= n)
1140     return eof ? 0 : -1;
1141
1142   int c = input[ofs];
1143   if (c == 'x' || c == 'X' || c == 'u' || c == 'U')
1144     {
1145       if (ofs + 1 >= n)
1146         return eof ? 0 : -1;
1147
1148       return input[ofs + 1] == '\'' || input[ofs + 1] == '"';
1149     }
1150   else
1151     return c == '\'' || c == '"' || c == '\n';
1152 }
1153
1154 static int
1155 segmenter_parse_start_of_line__ (struct segmenter *s,
1156                                  const char *input, size_t n, bool eof,
1157                                  enum segment_type *type)
1158 {
1159   ucs4_t uc;
1160   int mblen;
1161   int ofs;
1162
1163   assert (s->state == S_GENERAL);
1164   assert (s->substate & SS_START_OF_LINE);
1165
1166   mblen = segmenter_u8_to_uc__ (&uc, input, n, eof, 0);
1167   if (mblen < 0)
1168     return -1;
1169
1170   switch (uc)
1171     {
1172     case '+':
1173       ofs = skip_spaces_and_comments (input, n, eof, 1);
1174       if (ofs < 0)
1175         return -1;
1176       else
1177         {
1178           int is_string = is_start_of_string__ (input, n, eof, ofs);
1179           if (is_string < 0)
1180             return -1;
1181           else if (is_string)
1182             {
1183               /* This is punctuation that may separate pieces of a string. */
1184               *type = SEG_PUNCT;
1185               s->substate = 0;
1186               return 1;
1187             }
1188         }
1189       /* Fall through. */
1190
1191     case '-':
1192     case '.':
1193       *type = SEG_START_COMMAND;
1194       s->substate = SS_START_OF_COMMAND;
1195       return 1;
1196
1197     default:
1198       if (lex_uc_is_space (uc))
1199         {
1200           int eol = at_end_of_line (input, n, eof, 0);
1201           if (eol < 0)
1202             return -1;
1203           else if (eol)
1204             {
1205               s->substate = SS_START_OF_COMMAND;
1206               *type = SEG_SEPARATE_COMMANDS;
1207               return 0;
1208             }
1209           break;
1210         }
1211
1212       if (s->mode == SEG_MODE_INTERACTIVE || s->substate & SS_START_OF_COMMAND)
1213         break;
1214       else if (s->mode == SEG_MODE_AUTO)
1215         {
1216           int cmd = segmenter_detect_command_name__ (input, n, eof, 0);
1217           if (cmd < 0)
1218             return -1;
1219           else if (cmd == 0)
1220             break;
1221         }
1222       else
1223         assert (s->mode == SEG_MODE_BATCH);
1224
1225       s->substate = SS_START_OF_COMMAND;
1226       *type = SEG_START_COMMAND;
1227       return 0;
1228     }
1229
1230   s->substate = SS_START_OF_COMMAND;
1231   return segmenter_parse_mid_command__ (s, input, n, eof, type);
1232 }
1233
1234 static int
1235 segmenter_parse_file_label__ (struct segmenter *s,
1236                               const char *input, size_t n, bool eof,
1237                               enum segment_type *type)
1238 {
1239   struct segmenter sub;
1240   int ofs;
1241
1242   sub = *s;
1243   sub.state = S_GENERAL;
1244   ofs = segmenter_push (&sub, input, n, eof, type);
1245
1246   if (ofs < 0)
1247     return -1;
1248   else if (*type == SEG_IDENTIFIER)
1249     {
1250       int result;
1251
1252       assert (lex_id_match (ss_cstr ("LABEL"),
1253                             ss_buffer ((char *) input, ofs)));
1254       result = segmenter_unquoted (input, n, eof, ofs);
1255       if (result < 0)
1256         return -1;
1257       else
1258         {
1259           if (result)
1260             s->state = S_TITLE_1;
1261           else
1262             *s = sub;
1263           return ofs;
1264         }
1265     }
1266   else
1267     {
1268       s->substate = sub.substate;
1269       return ofs;
1270     }
1271 }
1272
1273 static int
1274 segmenter_subparse (struct segmenter *s,
1275                     const char *input, size_t n, bool eof,
1276                     enum segment_type *type)
1277 {
1278   struct segmenter sub;
1279   int ofs;
1280
1281   sub.mode = s->mode;
1282   sub.state = S_GENERAL;
1283   sub.substate = s->substate;
1284   ofs = segmenter_push (&sub, input, n, eof, type);
1285   s->substate = sub.substate;
1286   return ofs;
1287 }
1288
1289 /* We are segmenting a DO REPEAT command, currently reading the syntax that
1290    defines the stand-in variables (the head) before the lines of syntax to be
1291    repeated (the body). */
1292 static int
1293 segmenter_parse_do_repeat_1__ (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_SEPARATE_COMMANDS)
1302     {
1303       /* We reached a blank line that separates the head from the body. */
1304       s->state = S_DO_REPEAT_2;
1305     }
1306   else if (*type == SEG_END_COMMAND || *type == SEG_START_COMMAND)
1307     {
1308       /* We reached the body. */
1309       s->state = S_DO_REPEAT_3;
1310       s->substate = 1;
1311     }
1312
1313   return ofs;
1314 }
1315
1316 /* We are segmenting a DO REPEAT command, currently reading a blank line that
1317    separates the head from the body. */
1318 static int
1319 segmenter_parse_do_repeat_2__ (struct segmenter *s,
1320                                const char *input, size_t n, bool eof,
1321                                enum segment_type *type)
1322 {
1323   int ofs = segmenter_subparse (s, input, n, eof, type);
1324   if (ofs < 0)
1325     return -1;
1326
1327   if (*type == SEG_NEWLINE)
1328     {
1329       /* We reached the body. */
1330       s->state = S_DO_REPEAT_3;
1331       s->substate = 1;
1332     }
1333
1334   return ofs;
1335 }
1336
1337 static bool
1338 check_repeat_command (struct segmenter *s,
1339                       const char *input, size_t n, bool eof)
1340 {
1341   int direction;
1342   char id[16];
1343   int ofs;
1344
1345   ofs = 0;
1346   if (input[ofs] == '+' || input[ofs] == '-')
1347     ofs++;
1348
1349   ofs = next_id_in_command (s, input, n, eof, ofs, id, sizeof id);
1350   if (ofs < 0)
1351     return false;
1352   else if (lex_id_match (ss_cstr ("DO"), ss_cstr (id)))
1353     direction = 1;
1354   else if (lex_id_match (ss_cstr ("END"), ss_cstr (id)))
1355     direction = -1;
1356   else
1357     return true;
1358
1359   ofs = next_id_in_command (s, input, n, eof, ofs, id, sizeof id);
1360   if (ofs < 0)
1361     return false;
1362
1363   if (lex_id_match (ss_cstr ("REPEAT"), ss_cstr (id)))
1364     s->substate += direction;
1365   return true;
1366 }
1367
1368 static int
1369 segmenter_parse_full_line__ (const char *input, size_t n, bool eof,
1370                              enum segment_type *type)
1371 {
1372   const char *newline = memchr (input, '\n', n);
1373   if (!newline)
1374     return eof ? n : -1;
1375
1376   ptrdiff_t ofs = newline - input;
1377   if (ofs == 0 || (ofs == 1 && input[0] == '\r'))
1378     {
1379       *type = SEG_NEWLINE;
1380       return ofs + 1;
1381     }
1382   else
1383     return ofs - (input[ofs - 1] == '\r');
1384 }
1385
1386 /* We are in the body of DO REPEAT, segmenting the lines of syntax that are to
1387    be repeated.  Report each line of syntax as a single SEG_DO_REPEAT_COMMAND.
1388
1389    DO REPEAT can be nested, so we look for DO REPEAT...END REPEAT blocks inside
1390    the lines we're segmenting.  s->substate counts the nesting level, starting
1391    at 1. */
1392 static int
1393 segmenter_parse_do_repeat_3__ (struct segmenter *s,
1394                                const char *input, size_t n, bool eof,
1395                                enum segment_type *type)
1396 {
1397   int ofs;
1398
1399   ofs = segmenter_parse_full_line__ (input, n, eof, type);
1400   if (ofs < 0 || (ofs > 0 && input[ofs - 1] == '\n'))
1401     return ofs;
1402   else if (!check_repeat_command (s, input, n, eof) && !eof)
1403     return -1;
1404   else if (s->substate == 0)
1405     {
1406       /* Nesting level dropped to 0, so we've finished reading the DO REPEAT
1407          body. */
1408       s->state = S_GENERAL;
1409       s->substate = SS_START_OF_COMMAND | SS_START_OF_LINE;
1410       return segmenter_push (s, input, n, eof, type);
1411     }
1412   else
1413     {
1414       *type = SEG_DO_REPEAT_COMMAND;
1415       return ofs;
1416     }
1417 }
1418
1419 static int
1420 segmenter_parse_begin_data_1__ (struct segmenter *s,
1421                                 const char *input, size_t n, bool eof,
1422                                 enum segment_type *type)
1423 {
1424   int ofs = segmenter_subparse (s, input, n, eof, type);
1425   if (ofs < 0)
1426     return -1;
1427
1428   if (*type == SEG_NEWLINE)
1429     s->state = S_BEGIN_DATA_2;
1430
1431   return ofs;
1432 }
1433
1434 static int
1435 segmenter_parse_begin_data_2__ (struct segmenter *s,
1436                                 const char *input, size_t n, bool eof,
1437                                 enum segment_type *type)
1438 {
1439   int ofs = segmenter_subparse (s, input, n, eof, type);
1440   if (ofs < 0)
1441     return -1;
1442
1443   if (*type == SEG_NEWLINE)
1444     s->state = S_BEGIN_DATA_3;
1445
1446   return ofs;
1447 }
1448
1449 static bool
1450 is_end_data (const char *input, size_t n)
1451 {
1452   const uint8_t *u_input = CHAR_CAST (const uint8_t *, input);
1453   bool endcmd;
1454   ucs4_t uc;
1455   int mblen;
1456   int ofs;
1457
1458   if (n < 4 || c_strncasecmp (input, "END", 3))
1459     return false;
1460
1461   ofs = 3;
1462   mblen = u8_mbtouc (&uc, u_input + ofs, n - ofs);
1463   if (!lex_uc_is_space (uc))
1464     return false;
1465   ofs += mblen;
1466
1467   if (n - ofs < 4 || c_strncasecmp (input + ofs, "DATA", 4))
1468     return false;
1469   ofs += 4;
1470
1471   endcmd = false;
1472   while (ofs < n)
1473     {
1474       mblen = u8_mbtouc (&uc, u_input + ofs, n - ofs);
1475       if (uc == '.')
1476         {
1477           if (endcmd)
1478             return false;
1479           endcmd = true;
1480         }
1481       else if (!lex_uc_is_space (uc))
1482         return false;
1483       ofs += mblen;
1484     }
1485
1486   return true;
1487 }
1488
1489 static int
1490 segmenter_parse_begin_data_3__ (struct segmenter *s,
1491                                 const char *input, size_t n, bool eof,
1492                                 enum segment_type *type)
1493 {
1494   int ofs;
1495
1496   ofs = segmenter_parse_full_line__ (input, n, eof, type);
1497   if (ofs < 0)
1498     return -1;
1499   else if (is_end_data (input, ofs))
1500     {
1501       s->state = S_GENERAL;
1502       s->substate = SS_START_OF_COMMAND | SS_START_OF_LINE;
1503       return segmenter_push (s, input, n, eof, type);
1504     }
1505   else
1506     {
1507       *type = SEG_INLINE_DATA;
1508       s->state = S_BEGIN_DATA_4;
1509       return input[ofs - 1] == '\n' ? 0 : ofs;
1510     }
1511 }
1512
1513 static int
1514 segmenter_parse_begin_data_4__ (struct segmenter *s,
1515                                 const char *input, size_t n, bool eof,
1516                                 enum segment_type *type)
1517 {
1518   int ofs;
1519
1520   ofs = segmenter_parse_newline__ (input, n, eof, type);
1521   if (ofs < 0)
1522     return -1;
1523
1524   s->state = S_BEGIN_DATA_3;
1525   return ofs;
1526 }
1527
1528 static int
1529 segmenter_parse_title_1__ (struct segmenter *s,
1530                            const char *input, size_t n, bool eof,
1531                            enum segment_type *type)
1532 {
1533   int ofs;
1534
1535   ofs = skip_spaces (input, n, eof, 0);
1536   if (ofs < 0)
1537     return -1;
1538   s->state = S_TITLE_2;
1539   *type = SEG_SPACES;
1540   return ofs;
1541 }
1542
1543 static int
1544 segmenter_parse_title_2__ (struct segmenter *s,
1545                            const char *input, size_t n, bool eof,
1546                            enum segment_type *type)
1547 {
1548   int endcmd;
1549   int ofs;
1550
1551   endcmd = -1;
1552   ofs = 0;
1553   while (ofs < n)
1554     {
1555       ucs4_t uc;
1556       int mblen;
1557
1558       mblen = segmenter_u8_to_uc__ (&uc, input, n, eof, ofs);
1559       if (mblen < 0)
1560         return -1;
1561
1562       switch (uc)
1563         {
1564         case '\n':
1565           goto end_of_line;
1566
1567         case '.':
1568           endcmd = ofs;
1569           break;
1570
1571         default:
1572           if (!lex_uc_is_space (uc))
1573             endcmd = -1;
1574           break;
1575         }
1576
1577       ofs += mblen;
1578     }
1579
1580   if (eof)
1581     {
1582     end_of_line:
1583       s->state = S_GENERAL;
1584       s->substate = 0;
1585       *type = SEG_UNQUOTED_STRING;
1586       return endcmd >= 0 ? endcmd : ofs;
1587     }
1588
1589   return -1;
1590 }
1591
1592 /* Returns the name of segment TYPE as a string.  The caller must not modify
1593    or free the returned string.
1594
1595    This is useful only for debugging and testing. */
1596 const char *
1597 segment_type_to_string (enum segment_type type)
1598 {
1599   switch (type)
1600     {
1601 #define SEG_TYPE(NAME) case SEG_##NAME: return #NAME;
1602       SEG_TYPES
1603 #undef SEG_TYPE
1604     default:
1605       return "unknown segment type";
1606     }
1607 }
1608
1609 /* Initializes S as a segmenter with the given syntax MODE.
1610
1611    A segmenter does not contain any external references, so nothing needs to be
1612    done to destroy one.  For the same reason, segmenters may be copied with
1613    plain struct assignment (or memcpy). */
1614 void
1615 segmenter_init (struct segmenter *s, enum segmenter_mode mode)
1616 {
1617   s->state = S_SHBANG;
1618   s->substate = 0;
1619   s->mode = mode;
1620 }
1621
1622 /* Returns the mode passed to segmenter_init() for S. */
1623 enum segmenter_mode
1624 segmenter_get_mode (const struct segmenter *s)
1625 {
1626   return s->mode;
1627 }
1628
1629 /* Attempts to label a prefix of S's remaining input with a segment type.  The
1630    caller supplies the first N bytes of the remaining input as INPUT, which
1631    must be a UTF-8 encoded string.  If EOF is true, then the N bytes supplied
1632    are the entire (remainder) of the input; if EOF is false, then further input
1633    is potentially available.
1634
1635    The input may contain '\n' or '\r\n' line ends in any combination.
1636
1637    If successful, returns the number of bytes in the segment at the beginning
1638    of INPUT (between 0 and N, inclusive) and stores the type of that segment
1639    into *TYPE.  The next call to segmenter_push() should not include those
1640    bytes as part of INPUT, because they have (figuratively) been consumed by
1641    the segmenter.
1642
1643    Failure occurs only if the segment type of the N bytes in INPUT cannot yet
1644    be determined.  In this case segmenter_push() returns -1.  If more input is
1645    available, the caller should obtain some more, then call again with a larger
1646    N.  If this is not enough, the process might need to repeat again and agin.
1647    If input is exhausted, then the caller may call again setting EOF to true.
1648    segmenter_push() will never return -1 when EOF is true.
1649
1650    The caller must not, in a sequence of calls, supply contradictory input.
1651    That is, bytes provided as part of INPUT in one call, but not consumed, must
1652    not be provided with *different* values on subsequent calls.  This is
1653    because segmenter_push() must often make decisions based on looking ahead
1654    beyond the bytes that it consumes. */
1655 int
1656 segmenter_push (struct segmenter *s, const char *input, size_t n, bool eof,
1657                 enum segment_type *type)
1658 {
1659   if (!n)
1660     {
1661       if (eof)
1662         {
1663           *type = SEG_END;
1664           return 0;
1665         }
1666       else
1667         return -1;
1668     }
1669
1670   switch (s->state)
1671     {
1672     case S_SHBANG:
1673       return segmenter_parse_shbang__ (s, input, n, eof, type);
1674
1675     case S_GENERAL:
1676       return (s->substate & SS_START_OF_LINE
1677               ? segmenter_parse_start_of_line__ (s, input, n, eof, type)
1678               : segmenter_parse_mid_command__ (s, input, n, eof, type));
1679
1680     case S_COMMENT_1:
1681       return segmenter_parse_comment_1__ (s, input, n, eof, type);
1682     case S_COMMENT_2:
1683       return segmenter_parse_comment_2__ (s, input, n, eof, type);
1684
1685     case S_DOCUMENT_1:
1686       return segmenter_parse_document_1__ (s, input, n, eof, type);
1687     case S_DOCUMENT_2:
1688       return segmenter_parse_document_2__ (s, input, n, eof, type);
1689     case S_DOCUMENT_3:
1690       return segmenter_parse_document_3__ (s, type);
1691
1692     case S_FILE_LABEL:
1693       return segmenter_parse_file_label__ (s, input, n, eof, type);
1694
1695     case S_DO_REPEAT_1:
1696       return segmenter_parse_do_repeat_1__ (s, input, n, eof, type);
1697     case S_DO_REPEAT_2:
1698       return segmenter_parse_do_repeat_2__ (s, input, n, eof, type);
1699     case S_DO_REPEAT_3:
1700       return segmenter_parse_do_repeat_3__ (s, input, n, eof, type);
1701
1702     case S_BEGIN_DATA_1:
1703       return segmenter_parse_begin_data_1__ (s, input, n, eof, type);
1704     case S_BEGIN_DATA_2:
1705       return segmenter_parse_begin_data_2__ (s, input, n, eof, type);
1706     case S_BEGIN_DATA_3:
1707       return segmenter_parse_begin_data_3__ (s, input, n, eof, type);
1708     case S_BEGIN_DATA_4:
1709       return segmenter_parse_begin_data_4__ (s, input, n, eof, type);
1710
1711     case S_TITLE_1:
1712       return segmenter_parse_title_1__ (s, input, n, eof, type);
1713     case S_TITLE_2:
1714       return segmenter_parse_title_2__ (s, input, n, eof, type);
1715     }
1716
1717   NOT_REACHED ();
1718 }
1719
1720 /* Returns the style of command prompt to display to an interactive user for
1721    input in S.  The return value is most accurate in mode SEG_MODE_INTERACTIVE
1722    and at the beginning of a line (that is, if segmenter_push() consumed as
1723    much as possible of the input up to a new-line).  */
1724 enum prompt_style
1725 segmenter_get_prompt (const struct segmenter *s)
1726 {
1727   switch (s->state)
1728     {
1729     case S_SHBANG:
1730       return PROMPT_FIRST;
1731
1732     case S_GENERAL:
1733       return s->substate & SS_START_OF_COMMAND ? PROMPT_FIRST : PROMPT_LATER;
1734
1735     case S_COMMENT_1:
1736     case S_COMMENT_2:
1737       return PROMPT_COMMENT;
1738
1739     case S_DOCUMENT_1:
1740     case S_DOCUMENT_2:
1741       return PROMPT_DOCUMENT;
1742     case S_DOCUMENT_3:
1743       return PROMPT_FIRST;
1744
1745     case S_FILE_LABEL:
1746       return PROMPT_LATER;
1747
1748     case S_DO_REPEAT_1:
1749     case S_DO_REPEAT_2:
1750       return s->substate & SS_START_OF_COMMAND ? PROMPT_FIRST : PROMPT_LATER;
1751     case S_DO_REPEAT_3:
1752       return PROMPT_DO_REPEAT;
1753
1754     case S_BEGIN_DATA_1:
1755       return PROMPT_FIRST;
1756     case S_BEGIN_DATA_2:
1757       return PROMPT_LATER;
1758     case S_BEGIN_DATA_3:
1759     case S_BEGIN_DATA_4:
1760       return PROMPT_DATA;
1761
1762     case S_TITLE_1:
1763     case S_TITLE_2:
1764       return PROMPT_FIRST;
1765     }
1766
1767   NOT_REACHED ();
1768 }