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