1 /* end_line.c -- what to do at the end of a whole line of input */
2 /* Copyright 2010-2019 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 #include <stdlib.h>
19 #include <string.h>
20 #include <ctype.h>
21
22 #include "parser.h"
23 #include "text.h"
24 #include "input.h"
25 #include "convert.h"
26 #include "labels.h"
27 #include "indices.h"
28
29 void
check_internal_node(NODE_SPEC_EXTRA * nse)30 check_internal_node (NODE_SPEC_EXTRA *nse)
31 {
32 if (nse && nse->manual_content
33 && nse->manual_content->contents.number > 0)
34 {
35 char *texi = node_extra_to_texi (nse);
36 line_error ("syntax for an external node used for `%s'", texi);
37 free (texi);
38 }
39 }
40
41 int
check_empty_node(NODE_SPEC_EXTRA * nse,enum command_id cmd)42 check_empty_node (NODE_SPEC_EXTRA *nse,
43 enum command_id cmd)
44 {
45 if (!nse || !nse->node_content || nse->node_content->contents.number == 0)
46 {
47 line_error ("empty argument in @%s", command_name(cmd));
48 return 0;
49 }
50 else
51 return 1;
52 }
53
54 int
check_node_label(NODE_SPEC_EXTRA * nse,enum command_id cmd)55 check_node_label (NODE_SPEC_EXTRA *nse,
56 enum command_id cmd)
57 {
58 check_internal_node (nse);
59 return check_empty_node (nse, cmd);
60 }
61
62 static int
is_decimal_number(char * string)63 is_decimal_number (char *string)
64 {
65 char *p = string;
66 char *first_digits = 0;
67 char *second_digits = 0;
68
69 if (string[0] == '\0')
70 return 0;
71
72 if (strchr (digit_chars, *p))
73 p = first_digits = string + strspn (string, digit_chars);
74
75 if (*p == '.')
76 {
77 p++;
78 if (strchr (digit_chars, *p))
79 p = second_digits = p + strspn (p, digit_chars);
80 }
81
82 if (*p /* Bytes remaining at end of argument. */
83 || (!first_digits && !second_digits)) /* Need digits either
84 before or after the
85 decimal point. */
86 {
87 return 0;
88 }
89
90 return 1;
91 }
92
93 static int
is_whole_number(char * string)94 is_whole_number (char *string)
95 {
96 if (string[strspn (string, digit_chars)] == '\0')
97 return 1;
98 return 0;
99 }
100
101 /* Return end of argument before comment and whitespace. */
102 char *
skip_comment(char * q,int * has_comment)103 skip_comment (char *q, int *has_comment)
104 {
105 char *q1;
106 while (1)
107 {
108 q1 = strstr (q, "@c");
109 if (!q1)
110 {
111 q = q + strlen (q);
112 break;
113 }
114 q = q1 + 2;
115 if (!memcmp (q, "omment", 6))
116 q += 6;
117
118 /* TeX control sequence name ends at an escape character or
119 whitespace. */
120 if (*q == '@' || strchr (whitespace_chars, *q))
121 {
122 q = q1;
123 *has_comment = 1;
124 break;
125 }
126 }
127
128 /* q is now either at the end of the string, or at the start of a comment.
129 Find the start of any trailing whitespace. */
130 while (strchr (whitespace_chars, q[-1]))
131 q--;
132
133 return q;
134 }
135
136 /* Process argument to special line command. */
137 ELEMENT *
parse_special_misc_command(char * line,enum command_id cmd,int * has_comment)138 parse_special_misc_command (char *line, enum command_id cmd, int *has_comment)
139 {
140 #define ADD_ARG(string, len) do { \
141 ELEMENT *E = new_element (ET_NONE); \
142 text_append_n (&E->text, string, len); \
143 add_to_element_contents (args, E); \
144 } while (0)
145
146 ELEMENT *args = new_element (ET_NONE);
147 char *p = 0, *q = 0, *r = 0;
148 char *value = 0, *remaining = 0;;
149
150 switch (cmd)
151 {
152 case CM_set:
153 {
154 p = line;
155 p += strspn (p, whitespace_chars);
156 if (!*p)
157 goto set_no_name;
158 if (!isalnum (*p) && *p != '-' && *p != '_')
159 goto set_invalid;
160 q = strpbrk (p,
161 " \t\f\r\n" /* whitespace */
162 "{\\}~^+\"<>|@"); /* other bytes that aren't allowed */
163 /* see also read_flag_name function in end_line.c */
164
165 r = skip_comment (p, has_comment);
166
167 if (!strchr (whitespace_chars, *q) && *q != '@')
168 goto set_invalid;
169
170 if (*q == '@')
171 {
172 /* Check for a comment, e.g. "@set flag@c comment" */
173 if (q != r)
174 goto set_invalid;
175 }
176
177 ADD_ARG(p, q - p); /* name */
178
179 p = q + strspn (q, whitespace_chars);
180 /* Actually, whitespace characters except form feed. */
181
182 if (r >= p)
183 ADD_ARG(p, r - p); /* value */
184 else
185 ADD_ARG("", 0);
186
187 store_value (args->contents.list[0]->text.text,
188 args->contents.list[1]->text.text);
189
190 break;
191 set_no_name:
192 line_error ("@set requires a name");
193 break;
194 set_invalid:
195 line_error ("bad name for @set");
196 break;
197 }
198 case CM_clear:
199 {
200 char *flag = 0;
201 p = line;
202 p += strspn (p, whitespace_chars);
203 if (!*p)
204 goto clear_no_name;
205 q = p;
206 flag = read_flag_name (&q);
207 if (!flag)
208 goto clear_invalid;
209 r = q + strspn (q, whitespace_chars);
210 if (*r)
211 goto clear_invalid; /* Trailing argument. */
212
213 ADD_ARG (p, q - p);
214 clear_value (flag);
215 free (flag);
216
217 break;
218 clear_no_name:
219 line_error ("@clear requires a name");
220 break;
221 clear_invalid:
222 free (flag);
223 line_error ("bad name for @clear");
224 break;
225 }
226 case CM_unmacro:
227 p = line;
228 p += strspn (p, whitespace_chars);
229 if (!*p)
230 goto unmacro_noname;
231 q = p;
232 value = read_command_name (&q);
233 if (!value)
234 goto unmacro_badname;
235 /* FIXME: Check comment syntax is right */
236 delete_macro (value);
237 ADD_ARG(value, q - p);
238 debug ("UNMACRO %s", value);
239 free (value);
240 break;
241 unmacro_noname:
242 line_error ("@unmacro requires a name");
243 break;
244 unmacro_badname:
245 line_error ("bad name for @unmacro");
246 break;
247 case CM_clickstyle:
248 p = line;
249 p += strspn (p, whitespace_chars);
250 if (*p++ != '@')
251 goto clickstyle_invalid;
252 q = p;
253 value = read_command_name (&q);
254 if (!value)
255 goto clickstyle_invalid;
256 ADD_ARG (p - 1, q - p + 1);
257 free (global_clickstyle); global_clickstyle = value;
258 if (!memcmp (q, "{}", 2))
259 q += 2;
260 remaining = q;
261 /* FIXME: check comment */
262 break;
263 clickstyle_invalid:
264 line_error ("@clickstyle should only accept an @-command as argument, "
265 "not `%s'", line);
266 free (value);
267 break;
268 default:
269 fatal ("unknown special line command");
270 }
271
272 if (remaining)
273 {
274 remaining += strspn (remaining, whitespace_chars);
275 if (*remaining)
276 {
277 line_warn ("remaining argument on @%s line: %s",
278 command_name(cmd), remaining);
279 }
280 }
281 return args;
282 #undef ADD_ARG
283 }
284
285 /* Parse the arguments to a line command. Return an element whose contents
286 is an array of the arguments. For some commands, there is further
287 processing of the arguments (for example, for an @alias, remember the
288 alias.) */
289 ELEMENT *
parse_line_command_args(ELEMENT * line_command)290 parse_line_command_args (ELEMENT *line_command)
291 {
292 #define ADD_ARG(string) do { \
293 ELEMENT *E = new_element (ET_NONE); \
294 text_append (&E->text, string); \
295 add_to_element_contents (line_args, E); \
296 } while (0)
297
298 ELEMENT *arg = line_command->args.list[0];
299 ELEMENT *line_args;
300 enum command_id cmd;
301 char *line;
302
303 cmd = line_command->cmd;
304 if (arg->contents.number == 0)
305 {
306 command_error (line_command, "@%s missing argument", command_name(cmd));
307 add_extra_integer (line_command, "missing_argument", 1);
308 return 0;
309 }
310
311 if (arg->contents.number > 1 || arg->contents.list[0]->text.end == 0)
312 {
313 line_error ("superfluous argument to @%s", command_name (cmd));
314 }
315 if (arg->contents.list[0]->text.end == 0)
316 return 0;
317
318 line_args = new_element (ET_NONE);
319 line = arg->contents.list[0]->text.text;
320
321 switch (cmd)
322 {
323 case CM_alias:
324 {
325 /* @alias NEW = EXISTING */
326 char *new = 0, *existing = 0;
327 enum command_id new_cmd, existing_cmd;
328
329 new = read_command_name (&line);
330 if (!new)
331 goto alias_invalid;
332
333 line += strspn (line, whitespace_chars);
334 if (*line != '=')
335 goto alias_invalid;
336 line++;
337 line += strspn (line, whitespace_chars);
338
339 if (!isalnum (*line))
340 goto alias_invalid;
341 existing = read_command_name (&line);
342 if (!existing)
343 goto alias_invalid;
344
345 if (*line)
346 goto alias_invalid; /* Trailing argument. */
347
348 ADD_ARG(new);
349 ADD_ARG(existing);
350
351 existing_cmd = lookup_command (existing);
352 if (!existing_cmd)
353 break; /* TODO: Error message */
354 else
355 {
356 if (command_data(existing_cmd).flags & CF_block)
357 line_warn ("environment command %s as argument to @alias",
358 command_name(existing_cmd));
359 }
360
361 /* Remember the alias. */
362 new_cmd = add_texinfo_command (new);
363 new_cmd &= ~USER_COMMAND_BIT;
364 user_defined_command_data[new_cmd].flags |= CF_ALIAS;
365
366 user_defined_command_data[new_cmd].data = existing_cmd;
367 /* Note the data field is an int, existing_cmd is
368 enum command_id, so would have problems if enum command_id
369 were wider than an int. */
370
371 free (new); free (existing);
372
373 break;
374 alias_invalid:
375 line_error ("bad argument to @alias");
376 free (new); free (existing);
377 break;
378 }
379 case CM_definfoenclose:
380 {
381 /* @definfoenclose phoo,//,\\ */
382 char *new_command = 0, *start = 0, *end = 0;
383 enum command_id new_cmd;
384 int len;
385
386 new_command = read_command_name (&line);
387 if (!new_command)
388 goto definfoenclose_invalid;
389
390 line += strspn (line, whitespace_chars);
391 if (*line != ',')
392 goto definfoenclose_invalid;
393 line++;
394 line += strspn (line, whitespace_chars);
395
396 /* TODO: Can we have spaces in the delimiters? */
397 len = strcspn (line, ",");
398 start = strndup (line, len);
399 line += len;
400
401 if (!*line)
402 goto definfoenclose_invalid; /* Not enough args. */
403 line++; /* Past ','. */
404 line += strspn (line, whitespace_chars);
405 len = strcspn (line, ",");
406 end = strndup (line, len);
407
408 if (*line == ',')
409 goto definfoenclose_invalid; /* Too many args. */
410
411 /* Remember it. */
412 new_cmd = add_texinfo_command (new_command);
413 add_infoenclose (new_cmd, start, end);
414 new_cmd &= ~USER_COMMAND_BIT;
415
416 user_defined_command_data[new_cmd].flags
417 |= (CF_INFOENCLOSE | CF_brace);
418 user_defined_command_data[new_cmd].data = BRACE_style;
419
420 ADD_ARG(new_command); free (new_command);
421 ADD_ARG(start); free (start);
422 ADD_ARG(end); free (end);
423
424 break;
425 definfoenclose_invalid:
426 line_error ("bad argument to @definfoenclose");
427 free (new_command); free (start); free (end);
428 break;
429 }
430 case CM_columnfractions:
431 {
432 /* @multitable @columnfractions .33 .33 .33 */
433 ELEMENT *new;
434 char *p, *q;
435
436 if (!*line)
437 {
438 line_error ("empty @columnfractions");
439 break;
440 }
441 p = line;
442 while (1)
443 {
444 char *arg;
445
446 p += strspn (p, whitespace_chars);
447 if (!*p)
448 break;
449 q = strpbrk (p, whitespace_chars);
450 if (!q)
451 q = p + strlen (p);
452
453 arg = strndup (p, q - p);
454
455 /* Check argument is valid. */
456 if (!is_decimal_number (arg))
457 {
458 line_error ("column fraction not a number: %s", arg);
459 }
460 else
461 {
462 new = new_element (ET_NONE);
463 text_append_n (&new->text, p, q - p);
464 add_to_element_contents (line_args, new);
465 }
466 free (arg);
467 p = q;
468 }
469 break;
470 }
471 case CM_sp:
472 {
473 /* Argument is at least one digit. */
474 if (strchr (digit_chars, *line)
475 && !*(line + 1 + strspn (line + 1, digit_chars)))
476 {
477 ADD_ARG(line);
478 }
479 else
480 line_error ("@sp arg must be numeric, not `%s'", line);
481 break;
482 }
483 case CM_defindex:
484 case CM_defcodeindex:
485 {
486 char *name = 0;
487 char *p = line;
488
489 name = read_command_name (&p);
490 if (*p)
491 goto defindex_invalid; /* Trailing characters. */
492
493 /* Disallow index names NAME where it is likely that for
494 a source file BASE.texi, there will be other files called
495 BASE.NAME in the same directory. This is to prevent such
496 files being overwritten by the files read by texindex. */
497 {
498 static char *forbidden_index_names[] = {
499 "cp", "fn", "ky", "pg", "tp", "vr",
500 "cps", "fns", "kys", "pgs", "tps", "vrs",
501 "info", "ps", "pdf", "htm", "html",
502 "log", "aux", "dvi", "texi", "txi",
503 "texinfo", "tex", "bib", 0
504 };
505 char **ptr;
506 for (ptr = forbidden_index_names; *ptr; ptr++)
507 if (!strcmp (name, *ptr))
508 goto defindex_reserved;
509
510 if (index_by_name (name))
511 { free (name); break; }
512 }
513
514 add_index (name, cmd == CM_defcodeindex ? 1 : 0);
515 ADD_ARG(name);
516
517 break;
518 defindex_invalid:
519 line_error ("bad argument to @%s: %s",
520 command_name(cmd), line);
521 free (name);
522 break;
523 defindex_reserved:
524 line_error ("reserved index name %s", name);
525 free (name);
526 break;
527 }
528 case CM_synindex:
529 case CM_syncodeindex:
530 {
531 /* synindex FROM TO */
532 char *from = 0, *to = 0;
533 INDEX *from_index, *to_index;
534 char *p = line;
535
536 if (!isalnum (*p))
537 goto synindex_invalid;
538 from = read_command_name (&p);
539 if (!from)
540 goto synindex_invalid;
541
542 p += strspn (p, whitespace_chars);
543
544 if (!isalnum (*p))
545 goto synindex_invalid;
546 to = read_command_name (&p);
547 if (!to)
548 goto synindex_invalid;
549 if (*p)
550 goto synindex_invalid; /* More at end of line. */
551
552 from_index = index_by_name (from);
553 to_index = index_by_name (to);
554 if (!from_index)
555 line_error ("unknown source index in @%s: %s",
556 command_name(cmd), from);
557 if (!to_index)
558 line_error ("unknown destination index in @%s: %s",
559 command_name(cmd), to);
560
561 if (from_index && to_index)
562 {
563 INDEX *current_to = to_index;
564 /* Find ultimate index this merges to. */
565 current_to = ultimate_index (current_to);
566
567 if (current_to != from_index)
568 {
569 from_index->merged_in = current_to;
570 from_index->in_code = (cmd == CM_syncodeindex);
571 ADD_ARG(from);
572 ADD_ARG(to);
573 /* Note that 'current_to' may not end up as the index
574 'from_index' merges into if there are further @synindex
575 commands. */
576 }
577 else
578 line_warn ("@%s leads to a merging of %s in itself, ignoring",
579 command_name(cmd), from);
580 }
581
582 free (from);
583 free (to);
584
585 break;
586 synindex_invalid:
587 line_error ("bad argument to @%s: %s",
588 command_name(cmd), line);
589 free (from); free (to);
590 break;
591 }
592 case CM_printindex:
593 {
594 char *arg;
595 char *p = line;
596 arg = read_command_name (&p);
597 if (!arg || *p)
598 line_error ("bad argument to @printindex: %s", line);
599 else
600 {
601 INDEX *idx = index_by_name (arg);
602 if (!idx)
603 line_error ("unknown index `%s' in @printindex", arg);
604 else
605 {
606 if (idx->merged_in)
607 {
608 INDEX *i2;
609 for (i2 = idx; (i2->merged_in); i2 = i2->merged_in)
610 ;
611 line_warn
612 ("printing an index `%s' merged in another one, `%s'",
613 arg, i2->name);
614 }
615 if (!current_node && !current_section && !current_region ())
616 {
617 line_warn ("printindex before document beginning: "
618 "@printindex %s", arg);
619 }
620 ADD_ARG (arg);
621 }
622 }
623 free (arg);
624 break;
625 }
626 case CM_everyheadingmarks:
627 case CM_everyfootingmarks:
628 case CM_evenheadingmarks:
629 case CM_oddheadingmarks:
630 case CM_evenfootingmarks:
631 case CM_oddfootingmarks:
632 {
633 if (!strcmp (line, "top") || !strcmp (line, "bottom"))
634 {
635 ADD_ARG (line);
636 }
637 else
638 line_error ("@%s arg must be `top' or `bottom', not `%s'",
639 command_name(cmd), line);
640
641 break;
642 }
643 case CM_fonttextsize:
644 {
645 if (!strcmp (line, "10") || !strcmp (line, "11"))
646 {
647 ADD_ARG (line);
648 }
649 else
650 line_error ("Only @fonttextsize 10 or 11 is supported, not "
651 "`%s'", line);
652 break;
653 }
654 case CM_footnotestyle:
655 {
656 if (!strcmp (line, "separate") || !strcmp (line, "end"))
657 {
658 ADD_ARG(line);
659 }
660 else
661 line_error ("@footnotestyle arg must be "
662 "`separate' or `end', not `%s'", line);
663 break;
664 }
665 case CM_setchapternewpage:
666 {
667 if (!strcmp (line, "on") || !strcmp (line, "off")
668 || !strcmp (line, "odd"))
669 {
670 ADD_ARG(line);
671 }
672 else
673 line_error ("@setchapternewpage arg must be "
674 "`on', `off' or `odd', not `%s'", line);
675 break;
676 }
677 case CM_need:
678 {
679 /* valid: 2, 2., .2, 2.2 */
680
681 if (is_decimal_number (line))
682 ADD_ARG(line);
683 else
684 line_error ("bad argument to @need: %s", line);
685
686 break;
687 }
688 case CM_paragraphindent:
689 {
690 if (!strcmp (line, "none") || !strcmp (line, "asis")
691 || is_whole_number (line))
692 ADD_ARG(line);
693 else
694 line_error ("@paragraphindent arg must be "
695 "numeric/`none'/`asis', not `%s'", line);
696 break;
697 }
698 case CM_firstparagraphindent:
699 {
700 if (!strcmp (line, "none") || !strcmp (line, "insert"))
701 {
702 ADD_ARG(line);
703 }
704 else
705 line_error ("@firstparagraph arg must be "
706 "`none' or `insert', not `%s'", line);
707
708 break;
709 }
710 case CM_exampleindent:
711 {
712 if (!strcmp (line, "asis") || is_whole_number (line))
713 ADD_ARG(line);
714 else
715 line_error ("@exampleindent arg must be "
716 "numeric/`asis', not `%s'", line);
717 break;
718 }
719 case CM_frenchspacing:
720 case CM_xrefautomaticsectiontitle:
721 case CM_codequoteundirected:
722 case CM_codequotebacktick:
723 case CM_deftypefnnewline:
724 {
725 if (!strcmp (line, "on") || !strcmp (line, "off"))
726 {
727 ADD_ARG(line);
728 }
729 else
730 line_error ("expected @%s on or off, not `%s'",
731 command_name(cmd), line);
732
733 break;
734 }
735 case CM_kbdinputstyle:
736 {
737 if (!strcmp (line, "code"))
738 global_kbdinputstyle = kbd_code;
739 else if (!strcmp (line, "example"))
740 global_kbdinputstyle = kbd_example;
741 else if (!strcmp (line, "distinct"))
742 global_kbdinputstyle = kbd_distinct;
743 else goto kdbinputstyle_invalid;
744
745 ADD_ARG(line);
746
747 if (0)
748 {
749 kdbinputstyle_invalid:
750 line_error ("@kbdinputstyle arg must be "
751 "`code'/`example'/`distinct', not `%s'", line);
752 }
753 break;
754 }
755 case CM_allowcodebreaks:
756 {
757 if (!strcmp (line, "true") || !strcmp (line, "false"))
758 {
759 ADD_ARG(line);
760 }
761 else
762 line_error ("@allowcodebreaks arg must be "
763 "`true' or `false', not `%s'", line);
764 break;
765 }
766 case CM_urefbreakstyle:
767 {
768 if (!strcmp (line, "after") || !strcmp (line, "before")
769 || !strcmp (line, "none"))
770 {
771 ADD_ARG(line);
772 }
773 else
774 line_error ("@urefbreakstyle arg must be "
775 "`after'/`before'/`none', not `%s'", line);
776 break;
777 }
778 case CM_headings:
779 {
780 if (!strcmp (line, "off") || !strcmp (line, "on")
781 || !strcmp (line, "double") || !strcmp (line, "singleafter")
782 || !strcmp (line, "doubleafter"))
783 {
784 ADD_ARG(line);
785 }
786 else
787 line_error ("bad argument to @headings: %s", line);
788 break;
789 }
790 default:
791 ;
792 }
793 if (line_args->contents.number == 0)
794 {
795 destroy_element (line_args);
796 return 0;
797 }
798 else
799 return line_args;
800
801 #undef ADD_ARG
802 }
803
804 /* NODE->contents is the Texinfo for the specification of a node. This
805 function sets three fields on the returned object:
806
807 manual_content - Texinfo tree for a manual name extracted from the
808 node specification.
809 node_content - Texinfo tree for the node name on its own
810 normalized - a string with the node name after HTML node name
811 normalization is applied
812
813 Objects returned from this function are used as an 'extra' key in a
814 few places: the elements of a 'nodes_manuals' array (itself an extra key),
815 the 'menu_entry_node' key on a 'menu_entry' element (not to be confused
816 with an ET_menu_entry_node element, which occurs in the args of a
817 'menu_entry' element), and in the 'node_argument' key of a cross-reference
818 command (like @xref). */
819 NODE_SPEC_EXTRA *
parse_node_manual(ELEMENT * node)820 parse_node_manual (ELEMENT *node)
821 {
822 NODE_SPEC_EXTRA *result;
823 ELEMENT *new;
824 int idx = 0; /* index into node->contents */
825
826 result = malloc (sizeof (NODE_SPEC_EXTRA));
827 result->manual_content = result->node_content = 0;
828
829 /* If the content starts with a '(', try to get a manual name. */
830 if (node->contents.number > 0 && node->contents.list[0]->text.end > 0
831 && node->contents.list[0]->text.text[0] == '(')
832 {
833 ELEMENT *manual, *first;
834 char *opening_bracket, *closing_bracket;
835
836 /* Handle nested parentheses in the manual name, for whatever reason. */
837 int bracket_count = 1; /* Number of ( seen minus number of ) seen. */
838
839 manual = new_element (ET_NONE);
840
841 /* If the first contents element is "(" followed by more text, split
842 the leading "(" into its own element. */
843 first = node->contents.list[0];
844 if (first->text.end > 1)
845 {
846 memmove (first->text.text, first->text.text + 1, first->text.end);
847 first->text.end--;
848 new = new_element (0);
849 text_append_n (&new->text, "(", 1);
850 insert_into_contents (node, new, 0);
851 }
852 idx++;
853
854 for (; idx < node->contents.number; idx++)
855 {
856 ELEMENT *e = node->contents.list[idx];
857 char *p, *q;
858
859 if (e->text.end == 0)
860 {
861 /* Put this element in the manual contents. */
862 add_to_contents_as_array (manual, e);
863 continue;
864 }
865 p = e->text.text;
866 while (p < e->text.text + e->text.end
867 && bracket_count > 0)
868 {
869 opening_bracket = strchr (p, '(');
870 closing_bracket = strchr (p, ')');
871 if (!opening_bracket && !closing_bracket)
872 {
873 break;
874 }
875 else if (opening_bracket && !closing_bracket)
876 {
877 bracket_count++;
878 p = opening_bracket + 1;
879 }
880 else if (!opening_bracket && closing_bracket)
881 {
882 bracket_count--;
883 p = closing_bracket + 1;
884 }
885 else if (opening_bracket < closing_bracket)
886 {
887 bracket_count++;
888 p = opening_bracket + 1;
889 }
890 else if (opening_bracket > closing_bracket)
891 {
892 bracket_count--;
893 p = closing_bracket + 1;
894 }
895 }
896
897 if (bracket_count > 0)
898 add_to_contents_as_array (manual, e);
899 else /* end of filename component */
900 {
901 /* Split the element in two, putting the part before the ")"
902 in the manual name, leaving the part afterwards for the
903 node name. */
904 remove_from_contents (node, idx); /* Remove 'e'. */
905
906 p--; /* point at ) */
907 if (p > e->text.text)
908 {
909 /* text before ), part of the manual name */
910 new = new_element (ET_NONE);
911 text_append_n (&new->text, e->text.text,
912 p - e->text.text);
913 insert_into_contents (node, new, idx++);
914
915 add_to_contents_as_array (manual, new);
916 }
917
918 new = new_element (0);
919 text_append_n (&new->text, ")", 1);
920 insert_into_contents (node, new, idx++);
921
922 /* Skip ')' and any following whitespace.
923 Note that we don't manage to skip any multibyte
924 UTF-8 space characters here. */
925 p++;
926 q = p + strspn (p, whitespace_chars);
927 if (q > p)
928 {
929 new = new_element (0);
930 text_append_n (&new->text, p, q - p);
931 insert_into_contents (node, new, idx++);
932 }
933
934 p = q;
935 if (*p)
936 {
937 /* text after ), part of the node name. */
938 new = new_element (ET_NONE);
939 text_append_n (&new->text, p,
940 e->text.text + e->text.end - p);
941 insert_into_contents (node, new, idx);
942 }
943 destroy_element (e);
944 break;
945 }
946 } /* for */
947
948 if (bracket_count == 0)
949 result->manual_content = manual;
950 else /* unbalanced */
951 {
952 destroy_element (manual);
953 idx = 0; /* Back to the start, and consider the whole thing
954 as a node name. */
955 }
956 }
957
958 /* If anything left, it is the node name. */
959 if (idx < node->contents.number)
960 {
961 new = new_element (0);
962 insert_slice_into_contents (new, 0, node, idx, node->contents.number);
963 result->node_content = new;
964 }
965
966 return result;
967 }
968
969 /* Array of recorded @float's. */
970 FLOAT_RECORD *floats_list = 0;
971 size_t floats_number = 0;
972 size_t floats_space = 0;
973
974 int
parse_float_type(ELEMENT * current)975 parse_float_type (ELEMENT *current)
976 {
977 EXTRA_FLOAT_TYPE *eft;
978 eft = malloc (sizeof (EXTRA_FLOAT_TYPE));
979 eft->content = 0;
980 eft->normalized = 0;
981
982 if (current->args.number > 0)
983 {
984 if (current->args.list[0]->contents.number > 0)
985 {
986 char *normalized;
987 normalized = convert_to_texinfo (current->args.list[0]);
988 eft->content = current->args.list[0];
989 eft->normalized = normalized;
990
991 add_extra_float_type (current, "type", eft);
992 return 1;
993 }
994 }
995 eft->normalized = strdup ("");
996 add_extra_float_type (current, "type", eft);
997 return 0;
998 }
999
1000 /* Actions to be taken at the end of a line that started a block that
1001 has to be ended with "@end". */
1002 ELEMENT *
end_line_starting_block(ELEMENT * current)1003 end_line_starting_block (ELEMENT *current)
1004 {
1005 enum context c;
1006 c = pop_context ();
1007 if (c != ct_line)
1008 fatal ("line context expected");
1009
1010 if (current->parent->cmd == CM_multitable)
1011 {
1012 /* Parse prototype row for a @multitable. Handling
1013 of @columnfractions is done elsewhere. */
1014
1015 int i;
1016 ELEMENT *prototypes = new_element (ET_NONE);
1017
1018 for (i = 0; i < current->contents.number; i++)
1019 {
1020 ELEMENT *e = contents_child_by_index(current, i);
1021
1022 if (e->type == ET_bracketed)
1023 {
1024 /* Copy and change the type of the element. */
1025
1026 ELEMENT *new;
1027 new = malloc (sizeof (ELEMENT));
1028 memcpy (new, e, sizeof (ELEMENT));
1029 new->type = ET_bracketed_multitable_prototype;
1030 new->parent = 0;
1031 new->extra_number = 0;
1032 add_to_contents_as_array (prototypes, new);
1033 }
1034 else if (e->text.end > 0)
1035 {
1036 /* Split the text up by whitespace. */
1037 char *p, *p2;
1038 p = e->text.text;
1039 while (1)
1040 {
1041 ELEMENT *new;
1042 p2 = p + strspn (p, whitespace_chars);
1043 if (!*p2)
1044 break;
1045 p = p2 + strcspn (p2, whitespace_chars);
1046 new = new_element (ET_row_prototype);
1047 text_append_n (&new->text, p2, p - p2);
1048 add_to_contents_as_array (prototypes, new);
1049 }
1050 }
1051 else
1052 {
1053 if (e->cmd != CM_c && e->cmd != CM_comment)
1054 {
1055 char *texi;
1056 texi = convert_to_texinfo (e);
1057 command_warn (current,
1058 "unexpected argument on @%s line: %s",
1059 command_name(current->parent->cmd),
1060 texi);
1061 free (texi);
1062 }
1063 }
1064 }
1065
1066 {
1067 int max_columns = prototypes->contents.number;
1068 add_extra_integer (current->parent, "max_columns", max_columns);
1069 if (max_columns == 0)
1070 command_warn (current->parent, "empty multitable");
1071 }
1072 add_extra_contents_oot (current->parent, "prototypes", prototypes);
1073 /* See code in destroy_element for how prototypes is deallocated. */
1074 }
1075 isolate_last_space (current);
1076
1077 current = current->parent;
1078 if (counter_value (&count_remaining_args, current) != -1)
1079 counter_pop (&count_remaining_args);
1080
1081 /* Don't consider empty argument of block @-command as argument,
1082 reparent them as contents. */
1083 if (current->args.list[0]->contents.number > 0
1084 && current->args.list[0]->contents.list[0]->type
1085 == ET_empty_line_after_command)
1086 {
1087 ELEMENT *e = remove_from_contents (current->args.list[0], 0);
1088 insert_into_contents (current, e, 0);
1089 destroy_element (pop_element_from_args (current));
1090 }
1091
1092 if (current->cmd == CM_float)
1093 {
1094 char *type = "";
1095 KEY_PAIR *k;
1096 EXTRA_FLOAT_TYPE *eft;
1097 current->line_nr = line_nr;
1098 if (current->args.number >= 2)
1099 {
1100 NODE_SPEC_EXTRA *float_label;
1101 float_label = parse_node_manual (args_child_by_index (current, 1));
1102 check_internal_node (float_label);
1103
1104 register_label (current, float_label->node_content);
1105 if (float_label->manual_content)
1106 destroy_element (float_label->manual_content);
1107 free (float_label);
1108 }
1109 parse_float_type (current);
1110 k = lookup_extra (current, "type");
1111 if (k)
1112 {
1113 eft = (EXTRA_FLOAT_TYPE *) k->value;
1114 type = eft->normalized;
1115 }
1116 /* add to global 'floats' array */
1117 if (floats_number == floats_space)
1118 {
1119 floats_list = realloc (floats_list,
1120 (floats_space += 5) * sizeof (FLOAT_RECORD));
1121 }
1122 floats_list[floats_number].type = type;
1123 floats_list[floats_number++].element = current;
1124 if (current_section)
1125 add_extra_element (current, "float_section", current_section);
1126 }
1127
1128 if (command_flags(current) & CF_blockitem)
1129 {
1130 if (current->cmd == CM_enumerate)
1131 {
1132 char *spec = "1";
1133
1134 if (current->args.number > 0
1135 && current->args.list[0]->contents.number > 0)
1136 {
1137 if (current->args.list[0]->contents.number > 1)
1138 command_error (current, "superfluous argument to @%s",
1139 command_name(current->cmd));
1140 ELEMENT *g = current->args.list[0]->contents.list[0];
1141 /* Check if @enumerate specification is either a single
1142 letter or a string of digits. */
1143 if (g->text.end == 1 && isalpha (g->text.text[0])
1144 || (g->text.end > 0
1145 && !*(g->text.text
1146 + strspn (g->text.text, "0123456789"))))
1147 {
1148 spec = g->text.text;
1149 }
1150 else
1151 command_error (current, "bad argument to @%s",
1152 command_name(current->cmd));
1153 }
1154 add_extra_string_dup (current, "enumerate_specification", spec);
1155 }
1156 else if (item_line_command (current->cmd))
1157 {
1158 KEY_PAIR *k;
1159 k = lookup_extra (current, "command_as_argument");
1160 if (!k)
1161 command_error (current,
1162 "%s requires an argument: the formatter for @item",
1163 command_name(current->cmd));
1164 else
1165 {
1166 ELEMENT *e = k->value;
1167 if (!(command_flags(e) & CF_brace)
1168 || (command_data(e->cmd).data == 0))
1169 {
1170 command_error (current,
1171 "command @%s not accepting argument in brace "
1172 "should not be on @%s line",
1173 command_name(e->cmd),
1174 command_name(current->cmd));
1175 k->key = "";
1176 k->type = extra_deleted;
1177 /* FIXME: Error message for accent commands is done
1178 elsewhere (3040). */
1179 }
1180 }
1181 }
1182
1183 /* check that command_as_argument of the @itemize is alone on the line,
1184 otherwise it is not a command_as_argument */
1185 if (current->cmd == CM_itemize)
1186 {
1187 KEY_PAIR *k;
1188 k = lookup_extra (current, "command_as_argument");
1189 if (k)
1190 {
1191 int i;
1192 ELEMENT *e = args_child_by_index (current, 0);
1193
1194 for (i = 0; i < e->contents.number; i++)
1195 {
1196 if (contents_child_by_index (e, i) == k->value)
1197 {
1198 i++;
1199 break;
1200 }
1201 }
1202 for (; i < e->contents.number; i++)
1203 {
1204 ELEMENT *f = contents_child_by_index (e, i);
1205 if (f->cmd != CM_c
1206 && f->cmd != CM_comment
1207 && !(f->text.end > 0
1208 && !*(f->text.text
1209 + strspn (f->text.text, whitespace_chars))))
1210 {
1211 k->value->type = ET_NONE;
1212 k->key = "";
1213 k->type = extra_deleted;
1214 break;
1215 }
1216 }
1217 }
1218 }
1219
1220 // Check if command_as_argument isn't an accent command
1221 if (current->cmd == CM_itemize || item_line_command(current->cmd))
1222 {
1223 KEY_PAIR *k = lookup_extra (current, "command_as_argument");
1224 if (k && k->value)
1225 {
1226 enum command_id cmd = k->value->cmd;
1227 if (cmd && (command_data(cmd).flags & CF_accent))
1228 {
1229 command_warn (current, "accent command `@%s' "
1230 "not allowed as @%s argument",
1231 command_name(cmd),
1232 command_name(current->cmd));
1233 k->key = "";
1234 k->value = 0;
1235 k->type = extra_deleted;
1236 }
1237 }
1238 }
1239
1240 /* if no command_as_argument given, default to @bullet for
1241 @itemize, and @asis for @table. */
1242 if (current->cmd == CM_itemize
1243 && (current->args.number == 0
1244 || current->args.list[0]->contents.number == 0))
1245 {
1246 ELEMENT *e;
1247
1248 e = new_element (ET_command_as_argument_inserted);
1249 e->cmd = CM_bullet;
1250 insert_into_args (current, e, 0);
1251 add_extra_element (current, "command_as_argument", e);
1252 }
1253 else if (item_line_command (current->cmd)
1254 && !lookup_extra (current, "command_as_argument"))
1255 {
1256 ELEMENT *e;
1257
1258 e = new_element (ET_command_as_argument_inserted);
1259 e->cmd = CM_asis;
1260 insert_into_args (current, e, 0);
1261 add_extra_element (current, "command_as_argument", e);
1262 }
1263
1264 {
1265 ELEMENT *bi = new_element (ET_before_item);
1266 add_to_element_contents (current, bi);
1267 current = bi;
1268 }
1269 } /* CF_blockitem */
1270
1271 if (command_flags(current) & CF_menu)
1272 {
1273 /* Start reading a menu. Processing will continue in
1274 handle_menu in menus.c. */
1275
1276 ELEMENT *menu_comment = new_element (ET_menu_comment);
1277 add_to_element_contents (current, menu_comment);
1278 current = menu_comment;
1279 debug ("MENU_COMMENT OPEN");
1280 push_context (ct_preformatted);
1281 }
1282 current = begin_preformatted (current);
1283
1284 return current;
1285 }
1286
1287 /* Actions to be taken at the end of an argument to a line command
1288 not starting a block. @end is processed in here. */
1289 static ELEMENT *
end_line_misc_line(ELEMENT * current)1290 end_line_misc_line (ELEMENT *current)
1291 {
1292 enum command_id cmd;
1293 int arg_type;
1294 enum context c;
1295 ELEMENT *misc_cmd;
1296 char *end_command = 0;
1297 enum command_id end_id;
1298 int included_file = 0;
1299
1300 isolate_last_space (current);
1301
1302 current = current->parent;
1303 misc_cmd = current;
1304 cmd = current->cmd;
1305 if (!cmd)
1306 fatal ("command name unknown for @end");
1307
1308 arg_type = command_data(cmd).data;
1309
1310 /* Check 'line' is top of the context stack */
1311 c = pop_context ();
1312 if (c != ct_line)
1313 fatal ("line context expected");
1314
1315 debug ("MISC END %s", command_name(cmd));
1316
1317 if (arg_type > 0)
1318 {
1319 ELEMENT *args = parse_line_command_args (current);
1320 if (args)
1321 add_extra_misc_args (current, "misc_args", args);
1322 }
1323 else if (arg_type == LINE_text)
1324 {
1325 char *text = 0;
1326 int superfluous_arg = 0;
1327
1328 if (current->args.number > 0)
1329 text = convert_to_text (current->args.list[0], &superfluous_arg);
1330
1331 if (!text || !strcmp (text, ""))
1332 {
1333 if (!superfluous_arg)
1334 line_warn ("@%s missing argument", command_name(cmd));
1335 add_extra_integer (current, "missing_argument", 1);
1336 free (text);
1337 }
1338 else
1339 {
1340 add_extra_string (current, "text_arg", text);
1341 if (current->cmd == CM_end)
1342 {
1343 char *line = text;
1344
1345 /* Set end_command - used below. */
1346 end_command = read_command_name (&line);
1347 if (end_command)
1348 {
1349 /* Check if argument is a block Texinfo command. */
1350 end_id = lookup_command (end_command);
1351 if (end_id == 0 || !(command_data(end_id).flags & CF_block))
1352 {
1353 command_warn (current, "unknown @end %s", end_command);
1354 free (end_command); end_command = 0;
1355 }
1356 else
1357 {
1358 debug ("END BLOCK %s", end_command);
1359 /* Handle conditional block commands (e.g. @ifinfo) */
1360
1361 /* If we are in a non-ignored conditional, there is not
1362 an element for the block in the tree; it is recorded
1363 in the conditional stack. Pop it and check it is the
1364 same as the one given in the @end line. */
1365
1366 if (command_data(end_id).data == BLOCK_conditional)
1367 {
1368 enum command_id popped;
1369 if (conditional_number == 0)
1370 goto conditional_stack_fail;
1371 popped = pop_conditional_stack ();
1372 if (popped != end_id)
1373 {
1374 push_conditional_stack (popped);
1375 goto conditional_stack_fail;
1376 }
1377 if (0)
1378 {
1379 conditional_stack_fail:
1380 command_error (current, "unmatched `@end'");
1381 free (end_command); end_command = 0;
1382 }
1383 }
1384 if (end_command)
1385 {
1386 add_extra_string (current, "command_argument",
1387 end_command);
1388 }
1389 if (end_command
1390 && (superfluous_arg
1391 || line[strspn (line, whitespace_chars)] != '\0'))
1392 {
1393 char *line, *line2;
1394 line = convert_to_texinfo (current->args.list[0]);
1395
1396 line2 = line;
1397 line2 += strspn (line2, whitespace_chars);
1398 free (read_command_name (&line2));
1399 command_error (current,
1400 "superfluous argument to @end %s: "
1401 "%s", end_command, line2);
1402 superfluous_arg = 0; /* Don't issue another error
1403 message below. */
1404 free (line);
1405 }
1406 }
1407 }
1408 else
1409 {
1410 command_error (current, "bad argument to @end: %s", line);
1411 }
1412 }
1413 else if (superfluous_arg)
1414 {
1415 /* An error message is issued below. */
1416 }
1417 else if (current->cmd == CM_include)
1418 {
1419 int status;
1420 char *fullpath;
1421 debug ("Include %s", text);
1422
1423 fullpath = locate_include_file (text);
1424 if (!fullpath)
1425 {
1426 command_error (current,
1427 "@include: could not find %s", text);
1428 }
1429 else
1430 {
1431 status = input_push_file (fullpath);
1432 if (status)
1433 {
1434 command_error (current,
1435 "@include: could not open %s:",
1436 text,
1437 strerror (status));
1438 }
1439 else
1440 included_file = 1;
1441 free (fullpath);
1442 }
1443 }
1444 else if (current->cmd == CM_verbatiminclude)
1445 {
1446 if (global_info.input_perl_encoding)
1447 add_extra_string_dup (current, "input_perl_encoding",
1448 global_info.input_perl_encoding);
1449 }
1450 else if (current->cmd == CM_documentencoding)
1451 {
1452 int i; char *p, *text2;
1453 char *texinfo_encoding, *perl_encoding, *input_encoding;
1454 /* See tp/Texinfo/Encoding.pm (whole file) */
1455
1456 /* Three concepts of encoding:
1457 texinfo_encoding -- one of the encodings supported as an
1458 argument to @documentencoding, documented
1459 in Texinfo manual
1460 perl_encoding -- used for charset conversion within Perl
1461 input_encoding -- for output within an HTML file */
1462
1463 text2 = strdup (text);
1464 for (p = text2; *p; p++)
1465 *p = tolower (*p);
1466
1467 /* Get texinfo_encoding from what was in the document */
1468 {
1469 static char *canonical_encodings[] = {
1470 "us-ascii", "utf-8", "iso-8859-1",
1471 "iso-8859-15","iso-8859-2","koi8-r", "koi8-u",
1472 0
1473 };
1474
1475 texinfo_encoding = 0;
1476 for (i = 0; (canonical_encodings[i]); i++)
1477 {
1478 if (!strcmp (text2, canonical_encodings[i]))
1479 {
1480 texinfo_encoding = canonical_encodings[i];
1481 break;
1482 }
1483 }
1484 if (!texinfo_encoding)
1485 {
1486 command_warn (current, "encoding `%s' is not a "
1487 "canonical texinfo encoding", text);
1488 }
1489 }
1490
1491 /* Get perl_encoding. */
1492 perl_encoding = 0;
1493 if (texinfo_encoding)
1494 perl_encoding = texinfo_encoding;
1495 else
1496 {
1497 int i;
1498 static char *known_encodings[] = {
1499 "shift_jis",
1500 "latin1",
1501 0
1502 };
1503 for (i = 0; (known_encodings[i]); i++)
1504 {
1505 if (!strcmp (text2, known_encodings[i]))
1506 {
1507 perl_encoding = known_encodings[i];
1508 break;
1509 }
1510 }
1511 }
1512 free (text2);
1513
1514 if (perl_encoding)
1515 {
1516 struct encoding_map {
1517 char *from; char *to;
1518 };
1519 static struct encoding_map map[] = {
1520 "utf-8", "utf-8-strict",
1521 "us-ascii", "ascii",
1522 "shift_jis", "shiftjis",
1523 "latin1", "iso-8859-1"
1524 };
1525 for (i = 0; i < sizeof map / sizeof *map; i++)
1526 {
1527 if (!strcmp (perl_encoding, map[i].from))
1528 {
1529 perl_encoding = map[i].to;
1530 break;
1531 }
1532 }
1533 add_extra_string_dup (current, "input_perl_encoding",
1534 perl_encoding);
1535 free (global_info.input_perl_encoding);
1536 global_info.input_perl_encoding = strdup (perl_encoding);
1537 }
1538 else
1539 {
1540 command_warn (current, "unrecognized encoding name `%s'",
1541 text);
1542 /* Texinfo::Encoding calls Encode::Alias, so knows
1543 about more encodings than what we know about here.
1544 TODO: Check when perl_encoding could be defined when
1545 texinfo_encoding isn't.
1546 Maybe we should check if an iconv conversion is possible
1547 from this encoding to UTF-8. */
1548
1549 }
1550
1551 /* Set input_encoding from perl_encoding */
1552 input_encoding = 0;
1553 if (perl_encoding)
1554 {
1555 struct encoding_map {
1556 char *from; char *to;
1557 };
1558 static struct encoding_map map[] = {
1559 "utf8", "utf-8",
1560 "utf-8-strict","utf-8",
1561 "ascii", "us-ascii",
1562 "shiftjis", "shift_jis",
1563 "latin-1", "iso-8859-1",
1564 "iso-8859-1", "iso-8859-1",
1565 "iso-8859-2", "iso-8859-2",
1566 "iso-8859-15", "iso-8859-15",
1567 "koi8-r", "koi8",
1568 "koi8-u", "koi8",
1569 };
1570 input_encoding = perl_encoding;
1571 for (i = 0; i < sizeof map / sizeof *map; i++)
1572 {
1573 /* Elements in first column map to elements in
1574 second column. Elements in second column map
1575 to themselves. */
1576 if (!strcasecmp (input_encoding, map[i].from)
1577 || !strcasecmp (input_encoding, map[i].to))
1578 {
1579 input_encoding = map[i].to;
1580 break;
1581 }
1582 }
1583 }
1584 if (input_encoding)
1585 {
1586 add_extra_string_dup (current, "input_encoding_name",
1587 input_encoding);
1588
1589 global_info.input_encoding_name = strdup (input_encoding);
1590 set_input_encoding (input_encoding);
1591 }
1592 }
1593 else if (current->cmd == CM_documentlanguage)
1594 {
1595 char *p, *q;
1596
1597 /* Texinfo::Common::warn_unknown_language checks with
1598 tp/Texinfo/Documentlanguages.pm, which is an automatically
1599 generated list of official IANA language codes. For now,
1600 just check if the language code looks right. */
1601
1602 p = text;
1603 while (isalpha (*p))
1604 p++;
1605 if (*p && *p != '_')
1606 {
1607 /* non-alphabetic char in language code */
1608 command_warn (current, "%s is not a valid language code",
1609 text);
1610 }
1611 else
1612 {
1613 if (p - text > 4)
1614 {
1615 /* looks too long */
1616 char c = *p;
1617 *p = 0;
1618 command_warn (current, "%s is not a valid language code",
1619 text);
1620 *p = c;
1621 }
1622 if (*p == '_')
1623 {
1624 q = p + 1;
1625 p = q;
1626 /* Language code should be of the form LL_CC,
1627 language code followed by country code. */
1628 while (isalpha (*p))
1629 p++;
1630 if (*p || p - q > 4)
1631 {
1632 /* non-alphabetic char in country code or code
1633 is too long. */
1634 command_warn (current,
1635 "%s is not a valid region code", q);
1636 }
1637 }
1638 }
1639
1640 free (global_documentlanguage);
1641 global_documentlanguage = strdup (text);
1642 /* FIXME: check customization variable */
1643 }
1644 }
1645 if (superfluous_arg)
1646 {
1647 char *texi_line, *p, *p1;
1648 p = convert_to_texinfo (args_child_by_index(current, 0));
1649
1650 texi_line = p;
1651 while (isspace (*texi_line))
1652 texi_line++;
1653
1654 /* Trim leading and trailing whitespace. */
1655 p1 = strchr (texi_line, '\0');
1656 if (p1 > texi_line)
1657 {
1658 while (p1 > texi_line && isspace (p1[-1]))
1659 p1--;
1660 c = *p1;
1661 *p1 = '\0';
1662 }
1663 command_error (current, "bad argument to @%s: %s",
1664 command_name(current->cmd), texi_line);
1665 free (p);
1666 }
1667 }
1668 else if (current->cmd == CM_node)
1669 {
1670 int i;
1671 ELEMENT *arg;
1672
1673 NODE_SPEC_EXTRA **nodes_manuals;
1674
1675 /* Construct 'nodes_manuals' array. Maximum of four elements
1676 (node name, up, prev, next). */
1677 nodes_manuals = malloc (sizeof (NODE_SPEC_EXTRA *) * 5);
1678
1679 for (i = 0; i < current->args.number && i < 4; i++)
1680 {
1681 arg = current->args.list[i];
1682 nodes_manuals[i] = parse_node_manual (arg);
1683 }
1684 nodes_manuals[i] = 0;
1685
1686 add_extra_node_spec_array (current, "nodes_manuals", nodes_manuals);
1687
1688 check_internal_node (nodes_manuals[0]);
1689
1690 if (nodes_manuals[0])
1691 {
1692 ELEMENT *label = 0;
1693 if (nodes_manuals[0]->node_content)
1694 {
1695 /* Copy the first 'node_content' array, to avoid the complication
1696 of it being referenced in two different places.
1697 This might be better with a separate function. */
1698
1699 label = new_element (0);
1700 int i;
1701
1702 for (i = 0; i<nodes_manuals[0]->node_content->contents.number;
1703 i++)
1704 {
1705 add_to_contents_as_array (label,
1706 contents_child_by_index(nodes_manuals[0]->node_content, i));
1707 }
1708 }
1709 register_label (current, label);
1710 }
1711
1712 current_node = current;
1713 }
1714 else if (current->cmd == CM_listoffloats)
1715 {
1716 parse_float_type (current);
1717 }
1718 else
1719 {
1720 /* All the other "line" commands. Check they have an argument. Empty
1721 @top is allowed. */
1722 if (current->args.list[0]->contents.number == 0
1723 && current->cmd != CM_top)
1724 {
1725 command_warn (current, "@%s missing argument",
1726 command_name(current->cmd));
1727 add_extra_integer (current, "missing_argument", 1);
1728 }
1729 else
1730 {
1731 if ((current->parent->cmd == CM_ftable
1732 || current->parent->cmd == CM_vtable)
1733 && (current->cmd == CM_item || current->cmd == CM_itemx))
1734 {
1735 enter_index_entry (current->parent->cmd,
1736 current->cmd,
1737 current,
1738 current->args.list[0]);
1739 }
1740 else
1741 {
1742 // 3273 FIXME possibly check for @def... command
1743 }
1744
1745
1746 /* Index commands */
1747 if (command_flags(current) & CF_index_entry_command)
1748 {
1749 enter_index_entry (current->cmd, current->cmd, current,
1750 current->args.list[0]);
1751 current->type = ET_index_entry_command;
1752 }
1753 }
1754 }
1755
1756 current = current->parent;
1757 if (end_command) /* Set above */
1758 {
1759 /* More processing of @end */
1760 ELEMENT *end_elt;
1761
1762 debug ("END COMMAND %s", end_command);
1763
1764 /* Reparent the "@end" element to be a child of the block element. */
1765 end_elt = pop_element_from_contents (current);
1766
1767 /* If not a conditional */
1768 if (command_data(end_id).data != BLOCK_conditional)
1769 {
1770 ELEMENT *closed_command;
1771 /* This closes tree elements (e.g. paragraphs) until we reach
1772 end_command. It can print an error if another block command
1773 is found first. */
1774 current = close_commands (current, end_id, &closed_command, 0);
1775 if (!closed_command)
1776 destroy_element_and_children (end_elt);
1777 else
1778 {
1779 add_extra_element (closed_command, "end_command", end_elt);
1780 close_command_cleanup (closed_command);
1781
1782 add_to_element_contents (closed_command, end_elt);
1783
1784 if (command_flags(closed_command) & CF_menu
1785 && current_context () == ct_menu)
1786 {
1787 ELEMENT *e;
1788 debug ("CLOSE menu but still in menu context");
1789 e = new_element (ET_menu_comment);
1790 add_to_element_contents (current, e);
1791 current = e;
1792 push_context (ct_preformatted);
1793 }
1794 }
1795 if (close_preformatted_command (end_id))
1796 current = begin_preformatted (current);
1797 }
1798 else
1799 {
1800 /* The "@end" line does not appear in the final tree for a
1801 conditional block. */
1802 destroy_element_and_children (end_elt);
1803 }
1804 }
1805 else
1806 {
1807 if (close_preformatted_command (cmd))
1808 current = begin_preformatted (current);
1809 }
1810
1811 /* If a file was included, remove the include command completely.
1812 Also ignore @setfilename in included file, as said in the manual. */
1813 if (included_file || (cmd == CM_setfilename && top_file_index () > 0))
1814 destroy_element_and_children (pop_element_from_contents (current));
1815 else if (cmd == CM_setfilename && (current_node || current_section))
1816 command_warn (misc_cmd, "@setfilename after the first element");
1817 else if (cmd == CM_columnfractions)
1818 {
1819 ELEMENT *before_item;
1820 KEY_PAIR *misc_args;
1821
1822 /* Check if in multitable. */
1823 if (!current->parent || current->parent->cmd != CM_multitable)
1824 {
1825 command_error (current,
1826 "@columnfractions only meaningful on a @multitable line");
1827 }
1828 else
1829 {
1830 pop_context (); /* ct_line */;
1831
1832 current = current->parent;
1833
1834 if ((misc_args = lookup_extra (misc_cmd, "misc_args")))
1835 {
1836 add_extra_element (current, "columnfractions", misc_cmd);
1837 add_extra_integer (current, "max_columns",
1838 misc_args->value->contents.number);
1839 }
1840 else
1841 add_extra_integer (current, "max_columns", 0);
1842
1843 before_item = new_element (ET_before_item);
1844 add_to_element_contents (current, before_item);
1845 current = before_item;
1846 }
1847 }
1848 else if (command_data(cmd).flags & CF_root)
1849 {
1850 current = last_contents_child (current);
1851 if (cmd == CM_node)
1852 counter_pop (&count_remaining_args);
1853
1854 /* Destroy all contents (TODO: check why do we do this?) */
1855 while (last_contents_child (current))
1856 destroy_element (pop_element_from_contents (current));
1857
1858 /* Set 'associated_section' extra key for a node. */
1859 if (cmd != CM_node && cmd != CM_part)
1860 {
1861 if (current_node)
1862 {
1863 if (!lookup_extra (current_node, "associated_section"))
1864 {
1865 add_extra_element
1866 (current_node, "associated_section", current);
1867 add_extra_element
1868 (current, "associated_node", current_node);
1869 }
1870 }
1871
1872 if (current_part)
1873 {
1874 add_extra_element (current, "associated_part", current_part);
1875 add_extra_element (current_part, "part_associated_section",
1876 current);
1877 if (current->cmd == CM_top)
1878 {
1879 line_error_ext (1, ¤t_part->line_nr,
1880 "@part should not be associated with @top");
1881 }
1882 current_part = 0;
1883 }
1884
1885 current_section = current;
1886 }
1887 else if (cmd == CM_part)
1888 {
1889 current_part = current;
1890 if (current_node
1891 && !lookup_extra (current_node, "associated_section"))
1892 {
1893 line_warn ("@node precedes @part, but parts may not be "
1894 "associated with nodes");
1895 }
1896 }
1897 }
1898
1899 return current;
1900 }
1901
1902 /* Actions to be taken when a whole line of input has been processed */
1903 ELEMENT *
end_line(ELEMENT * current)1904 end_line (ELEMENT *current)
1905 {
1906 ELEMENT *current_old = current; /* Used at very end of function */
1907
1908 /* If empty line, start a new paragraph. */
1909 if (last_contents_child (current)
1910 && last_contents_child (current)->type == ET_empty_line)
1911 {
1912 debug ("END EMPTY LINE");
1913 if (current->type == ET_paragraph)
1914 {
1915 ELEMENT *e;
1916 /* Remove empty_line element. */
1917 e = pop_element_from_contents (current);
1918
1919 current = end_paragraph (current, 0, 0);
1920
1921 /* Add empty_line to higher-level element. */
1922 add_to_element_contents (current, e);
1923 }
1924 else if (current->type == ET_preformatted
1925 && current->parent->type == ET_menu_entry_description)
1926 {
1927 ELEMENT *empty_line, *e;
1928 empty_line = pop_element_from_contents (current);
1929 if (current->contents.number == 0)
1930 {
1931 current = current->parent;
1932 destroy_element (pop_element_from_contents (current));
1933 }
1934 else
1935 current = current->parent;
1936
1937 pop_context (); //ct_preformatted
1938
1939 current = current->parent->parent;
1940 e = new_element (ET_menu_comment);
1941 add_to_element_contents (current, e);
1942
1943 current = e;
1944 e = new_element (ET_preformatted);
1945 add_to_element_contents (current, e);
1946
1947 current = e;
1948 e = new_element (ET_after_description_line);
1949 text_append (&e->text, empty_line->text.text);
1950 destroy_element (empty_line);
1951 add_to_element_contents (current, e);
1952
1953 push_context (ct_preformatted);
1954 debug ("MENU: END DESCRIPTION, OPEN COMMENT");
1955 }
1956 else if (in_paragraph_context (current_context ()))
1957 {
1958 current = end_paragraph (current, 0, 0);
1959 }
1960 }
1961 /* The end of the line of a menu. */
1962 else if (current->type == ET_menu_entry_name
1963 || current->type == ET_menu_entry_node)
1964 {
1965 ELEMENT *end_comment = 0;
1966 int empty_menu_entry_node = 0;
1967
1968 if (current->type == ET_menu_entry_node)
1969 {
1970 ELEMENT *last = last_contents_child (current);
1971
1972 if (current->contents.number > 0
1973 && (last->cmd == CM_c || last->cmd == CM_comment))
1974 {
1975 end_comment = pop_element_from_contents (current);
1976 }
1977
1978 /* If contents empty or is all whitespace. */
1979 if (current->contents.number == 0
1980 || (current->contents.number == 1
1981 && last->text.end > 0
1982 && !last->text.text[strspn (last->text.text,
1983 whitespace_chars)]))
1984 {
1985 empty_menu_entry_node = 1;
1986 if (end_comment)
1987 add_to_element_contents (current, end_comment);
1988 }
1989 }
1990
1991 /* Abort the menu entry if there is no destination node given. */
1992 if (empty_menu_entry_node || current->type == ET_menu_entry_name)
1993 {
1994 ELEMENT *menu, *menu_entry, *description_or_menu_comment = 0;
1995 debug ("FINALLY NOT MENU ENTRY");
1996 menu = current->parent->parent;
1997 menu_entry = pop_element_from_contents (menu);
1998 if (menu->contents.number > 0
1999 && last_contents_child(menu)->type == ET_menu_entry)
2000 {
2001 ELEMENT *entry, *description = 0;
2002 int j;
2003
2004 entry = last_contents_child(menu);
2005 for (j = entry->args.number - 1; j >= 0; j--)
2006 {
2007 ELEMENT *e = args_child_by_index (entry, j);
2008 if (e->type == ET_menu_entry_description)
2009 {
2010 description = e;
2011 break;
2012 }
2013 }
2014 if (description)
2015 description_or_menu_comment = description;
2016 else
2017 {
2018 ELEMENT *e;
2019 /* "Normally this cannot happen." */
2020 bug ("no description in menu entry");
2021 e = new_element (ET_menu_entry_description);
2022 add_to_element_args (entry, e);
2023 description_or_menu_comment = e;
2024 }
2025 }
2026 else if (menu->contents.number > 0
2027 && last_contents_child(menu)->type == ET_menu_comment)
2028 {
2029 description_or_menu_comment = last_contents_child(menu);
2030 }
2031 if (description_or_menu_comment)
2032 {
2033 current = description_or_menu_comment;
2034 if (current->contents.number > 0
2035 && last_contents_child(current)->type == ET_preformatted)
2036 current = last_contents_child(current);
2037 else
2038 {
2039 /* This should not happen */
2040 bug ("description or menu comment not in preformatted");
2041 ELEMENT *e;
2042 e = new_element (ET_preformatted);
2043 add_to_element_contents (current, e);
2044 current = e;
2045 }
2046 push_context (ct_preformatted);
2047 }
2048 else
2049 {
2050 ELEMENT *e;
2051 e = new_element (ET_menu_comment);
2052 add_to_element_contents (menu, e);
2053 current = e;
2054 e = new_element (ET_preformatted);
2055 add_to_element_contents (current, e);
2056 current = e;
2057 push_context (ct_preformatted);
2058 debug ("THEN MENU_COMMENT OPEN");
2059 }
2060 {
2061 int i, j;
2062 for (i = 0; i < menu_entry->args.number; i++)
2063 {
2064 ELEMENT *arg = args_child_by_index(menu_entry, i);
2065 if (arg->text.end > 0)
2066 current = merge_text (current, arg->text.text);
2067 else
2068 {
2069 ELEMENT *e;
2070 for (j = 0; j < arg->contents.number; j++)
2071 {
2072 e = contents_child_by_index (arg, j);
2073 if (e->text.end > 0)
2074 {
2075 current = merge_text (current, e->text.text);
2076 destroy_element (e);
2077 }
2078 else
2079 {
2080 add_to_element_contents (current, e);
2081 }
2082 }
2083 }
2084 destroy_element (arg);
2085 }
2086 destroy_element (menu_entry);
2087 }
2088 }
2089 else
2090 {
2091 debug ("MENU ENTRY END LINE");
2092 current = current->parent;
2093 current = enter_menu_entry_node (current);
2094 if (end_comment)
2095 add_to_element_contents (current, end_comment);
2096 }
2097 }
2098
2099 /* End of a definition line, like @deffn */
2100 else if (current->parent && current->parent->type == ET_def_line)
2101 {
2102 enum command_id def_command, original_def_command;
2103 DEF_INFO *def_info = 0;
2104 static DEF_INFO zero_def_info; /* always stays zeroed */
2105 KEY_PAIR *k;
2106
2107 if (pop_context () != ct_def)
2108 fatal ("def context expected");
2109
2110 k = lookup_extra (current->parent, "original_def_cmdname");
2111 if (k)
2112 original_def_command = lookup_command ((char *) k->value);
2113 else
2114 original_def_command = current->parent->parent->cmd;
2115
2116 def_command = original_def_command;
2117 /* Strip an trailing x from the command, e.g. @deffnx -> @deffn */
2118 if (command_data(def_command).flags & CF_line)
2119 {
2120 char *stripped = strdup (command_name(def_command));
2121 stripped[strlen (stripped) - 1] = '\0';
2122 def_command = lookup_command (stripped);
2123 free (stripped);
2124 }
2125
2126 def_info = parse_def (def_command, current);
2127
2128 /* Record the index entry if def_info is not empty. */
2129 if (!memcmp(def_info, &zero_def_info, sizeof (DEF_INFO)))
2130 {
2131 free (def_info);
2132 command_warn (current->parent, "missing category for @%s",
2133 command_name (original_def_command));
2134 }
2135 else
2136 {
2137 ELEMENT *index_entry = 0; /* Index entry text. */
2138
2139 add_extra_def_info (current->parent, "def_parsed_hash", def_info);
2140
2141 if (def_info->name)
2142 {
2143 char *t;
2144 /* Set index_entry unless an empty ET_bracketed_def_content. */
2145 if (def_info->name->type == ET_bracketed_def_content
2146 && (def_info->name->contents.number == 0
2147 || (def_info->name->contents.number == 1
2148 && (t = def_info->name->contents.list[0]->text.text)
2149 && t[strspn (t, whitespace_chars)] == '\0')))
2150 {
2151 }
2152 else
2153 index_entry = def_info->name;
2154 }
2155
2156 if (index_entry)
2157 {
2158 ELEMENT *index_contents = 0;
2159
2160 if (def_info->class &&
2161 (def_command == CM_defop
2162 || def_command == CM_deftypeop
2163 || def_command == CM_defmethod
2164 || def_command == CM_deftypemethod
2165 || def_command == CM_defivar
2166 || def_command == CM_deftypeivar
2167 || def_command == CM_deftypecv))
2168 {
2169 add_extra_string_dup (current->parent, "documentlanguage",
2170 global_documentlanguage);
2171 }
2172 else
2173 {
2174 index_contents = new_element (ET_NONE);
2175 if (index_contents->contents.number == 0)
2176 add_to_contents_as_array (index_contents, index_entry);
2177 }
2178
2179 enter_index_entry (def_command,
2180 original_def_command,
2181 current->parent,
2182 index_contents);
2183 }
2184 else
2185 {
2186 command_warn (current->parent, "missing name for @%s",
2187 command_name (original_def_command));
2188 }
2189 }
2190
2191 current = current->parent->parent;
2192 current = begin_preformatted (current);
2193 }
2194 /* End of a line starting a block. */
2195 else if (current->type == ET_block_line_arg)
2196 {
2197 current = end_line_starting_block (current);
2198 }
2199
2200 /* after an "@end verbatim" */
2201 else if (current->contents.number
2202 && last_contents_child(current)->type == ET_empty_line_after_command
2203 && contents_child_by_index(current, -2)
2204 && contents_child_by_index(current, -2)->cmd == CM_verbatim)
2205 {
2206 /*
2207 if we are after a @end verbatim, we must restart a preformatted if needed,
2208 since there is no @end command explicitly associated to raw commands
2209 it won't be done elsewhere.
2210 */
2211
2212 current = begin_preformatted (current);
2213 }
2214 else if (current->type == ET_line_arg)
2215 {
2216 current = end_line_misc_line (current);
2217 }
2218 else if (current->contents.number == 1
2219 && current->contents.list[0]->type == ET_empty_line_after_command
2220 || current->contents.number == 2
2221 && current->contents.list[0]->type == ET_empty_line_after_command
2222 && (current->contents.list[1]->cmd == CM_c
2223 || current->contents.list[1]->cmd == CM_comment))
2224 {
2225 if (current->type == ET_preformatted
2226 || current->type == ET_rawpreformatted)
2227 {
2228 /* Empty line after a @menu, or before a preformatted. Reparent
2229 to the menu or other format. */
2230 ELEMENT *parent, *to_reparent;
2231
2232 parent = current->parent;
2233 if (parent->type == ET_menu_comment
2234 && parent->contents.number == 1)
2235 {
2236 parent = parent->parent;
2237 }
2238 to_reparent = pop_element_from_contents (parent);
2239 debug ("LINE AFTER COMMAND IN PREFORMATTED");
2240 while (current->contents.number > 0)
2241 {
2242 ELEMENT *e;
2243 e = remove_from_contents (current, 0);
2244 add_to_element_contents (parent, e);
2245 }
2246 add_to_element_contents (parent, to_reparent);
2247 }
2248 }
2249
2250 /* 'line' or 'def' at top of "context stack" - this happens when
2251 line commands are nested (always incorrectly?) */
2252 if (current_context () == ct_line || current_context () == ct_def)
2253 {
2254 debug ("Still opened line command");
2255 if (current_context () == ct_def)
2256 {
2257 while (current->parent
2258 && current->parent->type != ET_def_line)
2259 {
2260 current = close_current (current, 0, 0);
2261 }
2262 }
2263 else
2264 {
2265 while (current->parent
2266 && current->type != ET_line_arg
2267 && current->type != ET_block_line_arg)
2268 {
2269 current = close_current (current, 0, 0);
2270 }
2271 }
2272
2273 if (current == current_old)
2274 fatal ("infinite loop when closing commands");
2275
2276 current = end_line (current);
2277 }
2278 return current;
2279 }
2280
2281