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