1 /* Copyright 2010-2021 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #include <config.h>
17
18 #include <stdlib.h>
19 #include <string.h>
20
21 #include "command_ids.h"
22 #include "commands.h"
23 #include "errors.h"
24
25 #include "command_data.c"
26
27 COMMAND *user_defined_command_data = 0;
28 static size_t user_defined_number = 0;
29 static size_t user_defined_space = 0;
30
31 static int
compare_command_fn(const void * a,const void * b)32 compare_command_fn (const void *a, const void *b)
33 {
34 const COMMAND *ca = (COMMAND *) a;
35 const COMMAND *cb = (COMMAND *) b;
36
37 return strcmp (ca->cmdname, cb->cmdname);
38 }
39
40 /* Return element number in command_data array. Return 0 if not found. */
41 enum command_id
lookup_command(char * cmdname)42 lookup_command (char *cmdname)
43 {
44 COMMAND *c;
45 COMMAND target;
46 int i;
47
48 target.cmdname = cmdname;
49
50 /* Check for user-defined commands: macros, indexes, etc. */
51 /* Do this before looking in the built-in commands, in case the user uses
52 @definfoenclose or similar to override a command.
53 If speed is a problem, then we could set a bit in the flags on the
54 builtin command (maybe reusing CF_INFOENCLOSE) to say to look in the
55 user commands instead. */
56
57 for (i = 0; i < user_defined_number; i++)
58 {
59 if (!strcmp (user_defined_command_data[i].cmdname, cmdname))
60 return ((enum command_id) i) | USER_COMMAND_BIT;
61 }
62
63 c = (COMMAND *) bsearch (&target, builtin_command_data + 1,
64 /* number of elements */
65 sizeof (builtin_command_data) / sizeof (builtin_command_data[0]) - 1,
66 sizeof (builtin_command_data[0]),
67 compare_command_fn);
68
69 if (c)
70 return c - &builtin_command_data[0];
71
72
73 return 0;
74 }
75
76 /* Add a new user-defined Texinfo command, like an index or macro command. No
77 reference to NAME is retained. */
78 enum command_id
add_texinfo_command(char * name)79 add_texinfo_command (char *name)
80 {
81 if (user_defined_number == user_defined_space)
82 {
83 user_defined_command_data
84 = realloc (user_defined_command_data,
85 (user_defined_space += 10) * sizeof (COMMAND));
86 if (!user_defined_command_data)
87 fatal ("could not realloc");
88 }
89
90 user_defined_command_data[user_defined_number].cmdname = strdup (name);
91 user_defined_command_data[user_defined_number].flags = 0;
92 user_defined_command_data[user_defined_number].data = 0;
93
94 return ((enum command_id) user_defined_number++) | USER_COMMAND_BIT;
95 }
96
97 /* Remove CMD, for @unmacro. */
98 void
remove_texinfo_command(enum command_id cmd)99 remove_texinfo_command (enum command_id cmd)
100 {
101 cmd &= ~USER_COMMAND_BIT;
102 free (user_defined_command_data[cmd].cmdname);
103 user_defined_command_data[cmd].cmdname = strdup ("");
104 }
105
106 void
wipe_user_commands(void)107 wipe_user_commands (void)
108 {
109 int i;
110 for (i = 0; i < user_defined_number; i++)
111 free (user_defined_command_data[i].cmdname);
112 user_defined_number = 0;
113 }
114
115 /* Commands that terminate a paragraph. */
116 /* We may replace this function with a macro, or represent this infomation in
117 command_data. */
118 int
close_paragraph_command(enum command_id cmd)119 close_paragraph_command (enum command_id cmd)
120 {
121 if (cmd == CM_verbatim)
122 return 1;
123
124 /* Block commands except 'raw' and 'conditional'. */
125
126 if (command_data(cmd).flags & CF_block)
127 {
128 if (command_data(cmd).data == BLOCK_conditional
129 || command_data(cmd).data == BLOCK_raw)
130 return 0;
131 if (command_data(cmd).flags & CF_format_raw)
132 return 0;
133
134 return 1;
135 }
136
137 if (cmd == CM_titlefont
138 || cmd == CM_insertcopying
139 || cmd == CM_sp
140 || cmd == CM_verbatiminclude
141 || cmd == CM_page
142 || cmd == CM_item
143 || cmd == CM_itemx
144 || cmd == CM_tab
145 || cmd == CM_headitem
146 || cmd == CM_printindex
147 || cmd == CM_listoffloats
148 || cmd == CM_center
149 || cmd == CM_dircategory
150 || cmd == CM_contents
151 || cmd == CM_shortcontents
152 || cmd == CM_summarycontents
153 || cmd == CM_caption
154 || cmd == CM_shortcaption
155 || cmd == CM_setfilename
156 || cmd == CM_exdent)
157 return 1;
158
159 if ((command_data(cmd).flags & CF_sectioning)
160 && !(command_data(cmd).flags & CF_root))
161 return 1;
162
163 if ((command_data(cmd).flags & CF_def))
164 return 1;
165
166 return 0;
167 }
168
169 int
close_preformatted_command(enum command_id cmd_id)170 close_preformatted_command (enum command_id cmd_id)
171 {
172 return cmd_id != CM_sp && close_paragraph_command (cmd_id);
173 }
174
175 int
item_line_command(enum command_id cmd_id)176 item_line_command (enum command_id cmd_id)
177 {
178 return cmd_id == CM_table || cmd_id == CM_ftable || cmd_id == CM_vtable;
179 }
180