File: | src/gnu/usr.bin/texinfo/makeinfo/sectioning.c |
Warning: | line 423, column 5 2nd function call argument is an uninitialized value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* sectioning.c -- for @chapter, @section, ..., @contents ... | |||
2 | $Id: sectioning.c,v 1.1.1.3 2006/07/17 16:03:48 espie Exp $ | |||
3 | ||||
4 | Copyright (C) 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. | |||
5 | ||||
6 | This program is free software; you can redistribute it and/or modify | |||
7 | it under the terms of the GNU General Public License as published by | |||
8 | the Free Software Foundation; either version 2, or (at your option) | |||
9 | any later version. | |||
10 | ||||
11 | This program is distributed in the hope that it will be useful, | |||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
14 | GNU General Public License for more details. | |||
15 | ||||
16 | You should have received a copy of the GNU General Public License | |||
17 | along with this program; if not, write to the Free Software | |||
18 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
19 | ||||
20 | Originally written by Karl Heinz Marbaise <kama@hippo.fido.de>. */ | |||
21 | ||||
22 | #include "system.h" | |||
23 | #include "cmds.h" | |||
24 | #include "macro.h" | |||
25 | #include "makeinfo.h" | |||
26 | #include "node.h" | |||
27 | #include "toc.h" | |||
28 | #include "sectioning.h" | |||
29 | #include "xml.h" | |||
30 | ||||
31 | /* See comment in sectioning.h. */ | |||
32 | section_alist_type section_alist[] = { | |||
33 | { "unnumberedsubsubsec", 5, ENUM_SECT_NO0, TOC_YES1 }, | |||
34 | { "unnumberedsubsec", 4, ENUM_SECT_NO0, TOC_YES1 }, | |||
35 | { "unnumberedsec", 3, ENUM_SECT_NO0, TOC_YES1 }, | |||
36 | { "unnumbered", 2, ENUM_SECT_NO0, TOC_YES1 }, | |||
37 | { "centerchap", 2, ENUM_SECT_NO0, TOC_YES1 }, | |||
38 | ||||
39 | { "appendixsubsubsec", 5, ENUM_SECT_APP2, TOC_YES1 }, /* numbered like A.X.X.X */ | |||
40 | { "appendixsubsec", 4, ENUM_SECT_APP2, TOC_YES1 }, | |||
41 | { "appendixsec", 3, ENUM_SECT_APP2, TOC_YES1 }, | |||
42 | { "appendixsection", 3, ENUM_SECT_APP2, TOC_YES1 }, | |||
43 | { "appendix", 2, ENUM_SECT_APP2, TOC_YES1 }, | |||
44 | ||||
45 | { "subsubsec", 5, ENUM_SECT_YES1, TOC_YES1 }, | |||
46 | { "subsubsection", 5, ENUM_SECT_YES1, TOC_YES1 }, | |||
47 | { "subsection", 4, ENUM_SECT_YES1, TOC_YES1 }, | |||
48 | { "section", 3, ENUM_SECT_YES1, TOC_YES1 }, | |||
49 | { "chapter", 2, ENUM_SECT_YES1, TOC_YES1 }, | |||
50 | ||||
51 | { "subsubheading", 5, ENUM_SECT_NO0, TOC_NO0 }, | |||
52 | { "subheading", 4, ENUM_SECT_NO0, TOC_NO0 }, | |||
53 | { "heading", 3, ENUM_SECT_NO0, TOC_NO0 }, | |||
54 | { "chapheading", 2, ENUM_SECT_NO0, TOC_NO0 }, | |||
55 | { "majorheading", 2, ENUM_SECT_NO0, TOC_NO0 }, | |||
56 | ||||
57 | { "top", 1, ENUM_SECT_NO0, TOC_YES1 }, | |||
58 | { NULL((void *)0), 0, 0, 0 } | |||
59 | }; | |||
60 | ||||
61 | /* The argument of @settitle, used for HTML. */ | |||
62 | char *title = NULL((void *)0); | |||
63 | ||||
64 | ||||
65 | #define APPENDIX_MAGIC1024 1024 | |||
66 | #define UNNUMBERED_MAGIC2048 2048 | |||
67 | ||||
68 | /* Number memory for every level @chapter, @section, | |||
69 | @subsection, @subsubsection. */ | |||
70 | static int numbers [] = { 0, 0, 0, 0 }; | |||
71 | ||||
72 | /* enum_marker == APPENDIX_MAGIC then we are counting appendencies | |||
73 | enum_marker == UNNUMBERED_MAGIC then we are within unnumbered area. | |||
74 | Handling situations like this: | |||
75 | @unnumbered .. | |||
76 | @section ... */ | |||
77 | static int enum_marker = 0; | |||
78 | ||||
79 | /* Organized by level commands. That is, "*" == chapter, "=" == section. */ | |||
80 | static char *scoring_characters = "*=-."; | |||
81 | ||||
82 | /* Amount to offset the name of sectioning commands to levels by. */ | |||
83 | static int section_alist_offset = 0; | |||
84 | ||||
85 | /* These two variables are for @float, @cindex like commands that need to know | |||
86 | in which section they are used. */ | |||
87 | /* Last value returned by get_sectioning_number. */ | |||
88 | static char *last_sectioning_number = ""; | |||
89 | /* Last title used by sectioning_underscore, etc. */ | |||
90 | static char *last_sectioning_title = ""; | |||
91 | ||||
92 | /* num == ENUM_SECT_NO means unnumbered (should never call this) | |||
93 | num == ENUM_SECT_YES means numbered | |||
94 | num == ENUM_SECT_APP means numbered like A.1 and so on */ | |||
95 | static char * | |||
96 | get_sectioning_number (int level, int num) | |||
97 | { | |||
98 | static char s[100]; /* should ever be enough for 99.99.99.99 | |||
99 | Appendix A.1 */ | |||
100 | ||||
101 | char *p; | |||
102 | int i; | |||
103 | ||||
104 | s[0] = 0; | |||
105 | ||||
106 | /* create enumeration in front of chapter, section, subsection and so on. */ | |||
107 | for (i = 0; i < level; i++) | |||
108 | { | |||
109 | p = s + strlen (s); | |||
110 | if ((i == 0) && (enum_marker == APPENDIX_MAGIC1024)) | |||
111 | sprintf (p, "%c.", numbers[i] + 64); /* Should be changed to | |||
112 | be more portable */ | |||
113 | else | |||
114 | sprintf (p, "%d.", numbers[i]); | |||
115 | } | |||
116 | ||||
117 | /* the last number is never followed by a dot */ | |||
118 | p = s + strlen (s); | |||
119 | if ((num == ENUM_SECT_APP2) | |||
120 | && (i == 0) | |||
121 | && (enum_marker == APPENDIX_MAGIC1024)) | |||
122 | sprintf (p, _("Appendix %c")((const char *) ("Appendix %c")), numbers[i] + 64); | |||
123 | else | |||
124 | sprintf (p, "%d", numbers[i]); | |||
125 | ||||
126 | /* Poor man's cache :-) */ | |||
127 | if (strlen (last_sectioning_number)) | |||
128 | free (last_sectioning_number); | |||
129 | last_sectioning_number = xstrdup (s); | |||
130 | ||||
131 | return s; | |||
132 | } | |||
133 | ||||
134 | ||||
135 | /* Set the level of @top to LEVEL. Return the old level of @top. */ | |||
136 | int | |||
137 | set_top_section_level (int level) | |||
138 | { | |||
139 | int i, result = -1; | |||
140 | ||||
141 | for (i = 0; section_alist[i].name; i++) | |||
142 | if (strcmp (section_alist[i].name, "top") == 0) | |||
143 | { | |||
144 | result = section_alist[i].level; | |||
145 | section_alist[i].level = level; | |||
146 | break; | |||
147 | } | |||
148 | return result; | |||
149 | } | |||
150 | ||||
151 | ||||
152 | /* return the index of the given sectioning command in section_alist */ | |||
153 | static int | |||
154 | search_sectioning (char *text) | |||
155 | { | |||
156 | int i; | |||
157 | char *t; | |||
158 | ||||
159 | /* ignore the optional command prefix */ | |||
160 | if (text[0] == COMMAND_PREFIX'@') | |||
161 | text++; | |||
162 | ||||
163 | for (i = 0; (t = section_alist[i].name); i++) | |||
164 | { | |||
165 | if (strcmp (t, text) == 0) | |||
166 | { | |||
167 | return i; | |||
168 | } | |||
169 | } | |||
170 | return -1; | |||
171 | } | |||
172 | ||||
173 | /* Return an integer which identifies the type of section present in | |||
174 | TEXT -- 1 for @top, 2 for chapters, ..., 5 for subsubsections (as | |||
175 | specified in section_alist). We take into account any @lowersections | |||
176 | and @raisesections. If SECNAME is non-NULL, also return the | |||
177 | corresponding section name. */ | |||
178 | int | |||
179 | what_section (char *text, char **secname) | |||
180 | { | |||
181 | int index, j; | |||
182 | char *temp; | |||
183 | int return_val; | |||
184 | ||||
185 | find_section_command: | |||
186 | for (j = 0; text[j] && cr_or_whitespace (text[j])(((text[j]) == '\t' || (text[j]) == ' ') || (text[j]) == '\r' || (text[j]) == '\n'); j++); | |||
187 | if (text[j] != COMMAND_PREFIX'@') | |||
188 | return -1; | |||
189 | ||||
190 | text = text + j + 1; | |||
191 | ||||
192 | /* We skip @c, @comment, and @?index commands. */ | |||
193 | if ((strncmp (text, "comment", strlen ("comment")) == 0) || | |||
194 | (text[0] == 'c' && cr_or_whitespace (text[1])(((text[1]) == '\t' || (text[1]) == ' ') || (text[1]) == '\r' || (text[1]) == '\n')) || | |||
195 | (strcmp (text + 1, "index") == 0)) | |||
196 | { | |||
197 | while (*text++ != '\n'); | |||
198 | goto find_section_command; | |||
199 | } | |||
200 | ||||
201 | /* Handle italicized sectioning commands. */ | |||
202 | if (*text == 'i') | |||
203 | text++; | |||
204 | ||||
205 | for (j = 0; text[j] && !cr_or_whitespace (text[j])(((text[j]) == '\t' || (text[j]) == ' ') || (text[j]) == '\r' || (text[j]) == '\n'); j++); | |||
206 | ||||
207 | temp = xmalloc (1 + j); | |||
208 | strncpy (temp, text, j); | |||
209 | temp[j] = 0; | |||
210 | ||||
211 | index = search_sectioning (temp); | |||
212 | free (temp); | |||
213 | if (index >= 0) | |||
214 | { | |||
215 | return_val = section_alist[index].level + section_alist_offset; | |||
216 | if (return_val < 0) | |||
217 | return_val = 0; | |||
218 | else if (return_val > 5) | |||
219 | return_val = 5; | |||
220 | ||||
221 | if (secname) | |||
222 | { | |||
223 | int i; | |||
224 | int alist_size = sizeof (section_alist) / sizeof(section_alist_type); | |||
225 | /* Find location of offset sectioning entry, but don't go off | |||
226 | either end of the array. */ | |||
227 | int index_offset = MAX (index - section_alist_offset, 0)((index - section_alist_offset) > (0) ? (index - section_alist_offset ) : (0)); | |||
228 | index_offset = MIN (index_offset, alist_size - 1)((index_offset) < (alist_size - 1) ? (index_offset) : (alist_size - 1)); | |||
229 | ||||
230 | /* Also make sure we don't go into the next "group" of | |||
231 | sectioning changes, e.g., change from an @appendix to an | |||
232 | @heading or some such. */ | |||
233 | #define SIGN(expr)((expr) < 0 ? -1 : 1) ((expr) < 0 ? -1 : 1) | |||
234 | for (i = index; i != index_offset; i -= SIGN (section_alist_offset)((section_alist_offset) < 0 ? -1 : 1)) | |||
235 | { | |||
236 | /* As it happens, each group has unique .num/.toc values. */ | |||
237 | if (section_alist[i].num != section_alist[index_offset].num | |||
238 | || section_alist[i].toc != section_alist[index_offset].toc) | |||
239 | break; | |||
240 | } | |||
241 | *secname = section_alist[i].name; | |||
242 | } | |||
243 | return return_val; | |||
244 | } | |||
245 | return -1; | |||
246 | } | |||
247 | ||||
248 | /* Returns current top level division (ie. chapter, unnumbered) number. | |||
249 | - For chapters, returns the number. | |||
250 | - For unnumbered sections, returns empty string. | |||
251 | - For appendices, returns A, B, etc. */ | |||
252 | char * | |||
253 | current_chapter_number (void) | |||
254 | { | |||
255 | if (enum_marker == UNNUMBERED_MAGIC2048) | |||
256 | return xstrdup (""); | |||
257 | else if (enum_marker == APPENDIX_MAGIC1024) | |||
258 | { | |||
259 | char s[1]; | |||
260 | sprintf (s, "%c", numbers[0] + 64); | |||
261 | return xstrdup (s); | |||
262 | } | |||
263 | else | |||
264 | { | |||
265 | char s[5]; | |||
266 | sprintf (s, "%d", numbers[0]); | |||
267 | return xstrdup (s); | |||
268 | } | |||
269 | } | |||
270 | ||||
271 | /* Returns number of the last sectioning command used. */ | |||
272 | char * | |||
273 | current_sectioning_number (void) | |||
274 | { | |||
275 | if (enum_marker == UNNUMBERED_MAGIC2048 || !number_sections) | |||
276 | return xstrdup (""); | |||
277 | else | |||
278 | return xstrdup (last_sectioning_number); | |||
279 | } | |||
280 | ||||
281 | /* Returns arguments of the last sectioning command used. */ | |||
282 | char * | |||
283 | current_sectioning_name (void) | |||
284 | { | |||
285 | return xstrdup (last_sectioning_title); | |||
286 | } | |||
287 | ||||
288 | /* insert_and_underscore, sectioning_underscore and sectioning_html call this. */ | |||
289 | ||||
290 | static char * | |||
291 | handle_enum_increment (int level, int index) | |||
292 | { | |||
293 | /* Here is how TeX handles enumeration: | |||
294 | - Anything starting with @unnumbered is not enumerated. | |||
295 | - @majorheading and the like are not enumberated. */ | |||
296 | int i; | |||
297 | ||||
298 | /* First constraint above. */ | |||
299 | if (enum_marker == UNNUMBERED_MAGIC2048 && level == 0) | |||
300 | return xstrdup (""); | |||
301 | ||||
302 | /* Second constraint. */ | |||
303 | if (section_alist[index].num == ENUM_SECT_NO0) | |||
304 | return xstrdup (""); | |||
305 | ||||
306 | /* reset all counters which are one level deeper */ | |||
307 | for (i = level; i < 3; i++) | |||
308 | numbers [i + 1] = 0; | |||
309 | ||||
310 | numbers[level]++; | |||
311 | if (section_alist[index].num == ENUM_SECT_NO0 || enum_marker == UNNUMBERED_MAGIC2048 | |||
312 | || !number_sections) | |||
313 | return xstrdup (""); | |||
314 | else | |||
315 | return xstrdup (get_sectioning_number (level, section_alist[index].num)); | |||
316 | } | |||
317 | ||||
318 | ||||
319 | void | |||
320 | sectioning_underscore (char *cmd) | |||
321 | { | |||
322 | char *temp, *secname; | |||
323 | int level; | |||
324 | ||||
325 | /* If we're not indenting the first paragraph, we shall make it behave | |||
326 | like @noindent is called directly after the section heading. */ | |||
327 | if (! do_first_par_indent) | |||
328 | cm_noindent (); | |||
329 | ||||
330 | temp = xmalloc (2 + strlen (cmd)); | |||
331 | temp[0] = COMMAND_PREFIX'@'; | |||
332 | strcpy (&temp[1], cmd); | |||
333 | level = what_section (temp, &secname); | |||
334 | level -= 2; | |||
335 | if (level
| |||
336 | level = 0; | |||
337 | free (temp); | |||
338 | ||||
339 | /* If the argument to @top is empty, we try using the one from @settitle. | |||
340 | Warn if both are unusable. */ | |||
341 | if (STREQ (command, "top")(strcmp (command, "top") == 0)) | |||
342 | { | |||
343 | int save_input_text_offset = input_text_offset; | |||
344 | ||||
345 | get_rest_of_line (0, &temp); | |||
346 | ||||
347 | /* Due to get_rest_of_line ... */ | |||
348 | line_number--; | |||
349 | ||||
350 | if (strlen (temp) == 0 && (!title || strlen (title) == 0)) | |||
351 | warning ("Must specify a title with least one of @settitle or @top"); | |||
352 | ||||
353 | input_text_offset = save_input_text_offset; | |||
354 | } | |||
355 | ||||
356 | if (xml) | |||
357 | { | |||
358 | /* If the section appears in the toc, it means it's a real section | |||
359 | unlike majorheading, chapheading etc. */ | |||
360 | if (section_alist[search_sectioning (cmd)].toc == TOC_YES1) | |||
361 | { | |||
362 | xml_close_sections (level); | |||
363 | /* Mark the beginning of the section | |||
364 | If the next command is printindex, we will remove | |||
365 | the section and put an Index instead */ | |||
366 | flush_output (); | |||
367 | xml_last_section_output_position = output_paragraph_offset; | |||
368 | ||||
369 | get_rest_of_line (0, &temp); | |||
370 | ||||
371 | /* Use @settitle value if @top parameter is empty. */ | |||
372 | if (STREQ (command, "top")(strcmp (command, "top") == 0) && strlen(temp) == 0) | |||
373 | temp = xstrdup (title ? title : ""); | |||
374 | ||||
375 | /* Docbook does not support @unnumbered at all. So we provide numbers | |||
376 | that other formats use. @appendix seems to be fine though, so we let | |||
377 | Docbook handle that as usual. */ | |||
378 | if (docbook && enum_marker != APPENDIX_MAGIC1024) | |||
379 | { | |||
380 | if (section_alist[search_sectioning (cmd)].num == ENUM_SECT_NO0 | |||
381 | && section_alist[search_sectioning (cmd)].toc == TOC_YES1) | |||
382 | xml_insert_element_with_attribute (xml_element (secname), | |||
383 | START0, "label=\"%s\" xreflabel=\"%s\"", | |||
384 | handle_enum_increment (level, search_sectioning (cmd)), | |||
385 | text_expansion (temp)); | |||
386 | else | |||
387 | xml_insert_element_with_attribute (xml_element (secname), | |||
388 | START0, "label=\"%s\"", | |||
389 | handle_enum_increment (level, search_sectioning (cmd))); | |||
390 | } | |||
391 | else | |||
392 | xml_insert_element (xml_element (secname), START0); | |||
393 | ||||
394 | xml_insert_element (TITLE, START0); | |||
395 | xml_open_section (level, secname); | |||
396 | execute_string ("%s", temp); | |||
397 | xml_insert_element (TITLE, END1); | |||
398 | ||||
399 | free (temp); | |||
400 | } | |||
401 | else | |||
402 | { | |||
403 | if (docbook) | |||
404 | { | |||
405 | if (level > 0) | |||
406 | xml_insert_element_with_attribute (xml_element (secname), START0, | |||
407 | "renderas=\"sect%d\"", level); | |||
408 | else | |||
409 | xml_insert_element_with_attribute (xml_element (secname), START0, | |||
410 | "renderas=\"other\""); | |||
411 | } | |||
412 | else | |||
413 | xml_insert_element (xml_element (secname), START0); | |||
414 | ||||
415 | get_rest_of_line (0, &temp); | |||
416 | execute_string ("%s", temp); | |||
417 | free (temp); | |||
418 | ||||
419 | xml_insert_element (xml_element (secname), END1); | |||
420 | } | |||
421 | } | |||
422 | else if (html) | |||
423 | sectioning_html (level, secname); | |||
| ||||
424 | else | |||
425 | insert_and_underscore (level, secname); | |||
426 | } | |||
427 | ||||
428 | ||||
429 | /* Insert the text following input_text_offset up to the end of the line | |||
430 | in a new, separate paragraph. Directly underneath it, insert a | |||
431 | line of WITH_CHAR, the same length of the inserted text. */ | |||
432 | void | |||
433 | insert_and_underscore (int level, char *cmd) | |||
434 | { | |||
435 | int i, len; | |||
436 | int index; | |||
437 | int old_no_indent; | |||
438 | unsigned char *starting_pos, *ending_pos; | |||
439 | char *temp; | |||
440 | char with_char = scoring_characters[level]; | |||
441 | ||||
442 | close_paragraph (); | |||
443 | filling_enabled = indented_fill = 0; | |||
444 | old_no_indent = no_indent; | |||
445 | no_indent = 1; | |||
446 | ||||
447 | if (macro_expansion_output_stream && !executing_string) | |||
448 | append_to_expansion_output (input_text_offset + 1); | |||
449 | ||||
450 | get_rest_of_line (0, &temp); | |||
451 | ||||
452 | /* Use @settitle value if @top parameter is empty. */ | |||
453 | if (STREQ (command, "top")(strcmp (command, "top") == 0) && strlen(temp) == 0) | |||
454 | temp = xstrdup (title ? title : ""); | |||
455 | ||||
456 | starting_pos = output_paragraph + output_paragraph_offset; | |||
457 | ||||
458 | /* Poor man's cache for section title. */ | |||
459 | if (strlen (last_sectioning_title)) | |||
460 | free (last_sectioning_title); | |||
461 | last_sectioning_title = xstrdup (temp); | |||
462 | ||||
463 | index = search_sectioning (cmd); | |||
464 | if (index < 0) | |||
465 | { | |||
466 | /* should never happen, but a poor guy, named Murphy ... */ | |||
467 | warning (_("Internal error (search_sectioning) `%s'!")((const char *) ("Internal error (search_sectioning) `%s'!")), cmd); | |||
468 | return; | |||
469 | } | |||
470 | ||||
471 | /* This is a bit tricky: we must produce "X.Y SECTION-NAME" in the | |||
472 | Info output and in TOC, but only SECTION-NAME in the macro-expanded | |||
473 | output. */ | |||
474 | ||||
475 | /* Step 1: produce "X.Y" and add it to Info output. */ | |||
476 | add_word_args ("%s ", handle_enum_increment (level, index)); | |||
477 | ||||
478 | /* Step 2: add "SECTION-NAME" to both Info and macro-expanded output. */ | |||
479 | if (macro_expansion_output_stream && !executing_string) | |||
480 | { | |||
481 | char *temp1 = xmalloc (2 + strlen (temp)); | |||
482 | sprintf (temp1, "%s\n", temp); | |||
483 | remember_itext (input_text, input_text_offset); | |||
484 | me_execute_string (temp1); | |||
485 | free (temp1); | |||
486 | } | |||
487 | else | |||
488 | execute_string ("%s\n", temp); | |||
489 | ||||
490 | /* Step 3: pluck "X.Y SECTION-NAME" from the output buffer and | |||
491 | insert it into the TOC. */ | |||
492 | ending_pos = output_paragraph + output_paragraph_offset; | |||
493 | if (section_alist[index].toc == TOC_YES1) | |||
494 | toc_add_entry (substring (starting_pos, ending_pos - 1), | |||
495 | level, current_node, NULL((void *)0)); | |||
496 | ||||
497 | free (temp); | |||
498 | ||||
499 | len = (ending_pos - starting_pos) - 1; | |||
500 | for (i = 0; i < len; i++) | |||
501 | add_char (with_char); | |||
502 | insert ('\n'); | |||
503 | close_paragraph (); | |||
504 | filling_enabled = 1; | |||
505 | no_indent = old_no_indent; | |||
506 | } | |||
507 | ||||
508 | /* Insert the text following input_text_offset up to the end of the | |||
509 | line as an HTML heading element of the appropriate `level' and | |||
510 | tagged as an anchor for the current node.. */ | |||
511 | ||||
512 | void | |||
513 | sectioning_html (int level, char *cmd) | |||
514 | { | |||
515 | static int toc_ref_count = 0; | |||
516 | int index; | |||
517 | int old_no_indent; | |||
518 | unsigned char *starting_pos, *ending_pos; | |||
519 | char *temp, *toc_anchor = NULL((void *)0); | |||
520 | ||||
521 | close_paragraph (); | |||
522 | filling_enabled = indented_fill = 0; | |||
523 | old_no_indent = no_indent; | |||
524 | no_indent = 1; | |||
525 | ||||
526 | /* level 0 (chapter) is <h2>, and we go down from there. */ | |||
527 | add_html_block_elt_args ("<h%d class=\"%s\">", level + 2, cmd); | |||
528 | ||||
529 | /* If we are outside of any node, produce an anchor that | |||
530 | the TOC could refer to. */ | |||
531 | if (!current_node || !*current_node) | |||
532 | { | |||
533 | static const char a_name[] = "<a name=\""; | |||
534 | ||||
535 | starting_pos = output_paragraph + output_paragraph_offset; | |||
536 | add_word_args ("%sTOC%d\">", a_name, toc_ref_count++); | |||
537 | toc_anchor = substring (starting_pos + sizeof (a_name) - 1, | |||
538 | output_paragraph + output_paragraph_offset); | |||
539 | /* This must be added after toc_anchor is extracted, since | |||
540 | toc_anchor cannot include the closing </a>. For details, | |||
541 | see toc.c:toc_add_entry and toc.c:contents_update_html. | |||
542 | ||||
543 | Also, the anchor close must be output before the section name | |||
544 | in case the name itself contains an anchor. */ | |||
545 | add_word ("</a>"); | |||
546 | } | |||
547 | starting_pos = output_paragraph + output_paragraph_offset; | |||
548 | ||||
549 | if (macro_expansion_output_stream && !executing_string) | |||
550 | append_to_expansion_output (input_text_offset + 1); | |||
551 | ||||
552 | get_rest_of_line (0, &temp); | |||
553 | ||||
554 | /* Use @settitle value if @top parameter is empty. */ | |||
555 | if (STREQ (command, "top")(strcmp (command, "top") == 0) && strlen(temp) == 0) | |||
556 | temp = xstrdup (title ? title : ""); | |||
557 | ||||
558 | index = search_sectioning (cmd); | |||
559 | if (index < 0) | |||
560 | { | |||
561 | /* should never happen, but a poor guy, named Murphy ... */ | |||
562 | warning (_("Internal error (search_sectioning) \"%s\"!")((const char *) ("Internal error (search_sectioning) \"%s\"!" )), cmd); | |||
563 | return; | |||
564 | } | |||
565 | ||||
566 | /* Produce "X.Y" and add it to HTML output. */ | |||
567 | { | |||
568 | char *title_number = handle_enum_increment (level, index); | |||
569 | if (strlen (title_number) > 0) | |||
570 | add_word_args ("%s ", title_number); | |||
571 | } | |||
572 | ||||
573 | /* add the section name to both HTML and macro-expanded output. */ | |||
574 | if (macro_expansion_output_stream && !executing_string) | |||
575 | { | |||
576 | remember_itext (input_text, input_text_offset); | |||
577 | me_execute_string (temp); | |||
578 | write_region_to_macro_output ("\n", 0, 1); | |||
579 | } | |||
580 | else | |||
581 | execute_string ("%s", temp); | |||
582 | ||||
583 | ending_pos = output_paragraph + output_paragraph_offset; | |||
584 | ||||
585 | /* Pluck ``X.Y SECTION-NAME'' from the output buffer and insert it | |||
586 | into the TOC. */ | |||
587 | if (section_alist[index].toc == TOC_YES1) | |||
588 | toc_add_entry (substring (starting_pos, ending_pos), | |||
589 | level, current_node, toc_anchor); | |||
590 | ||||
591 | free (temp); | |||
592 | ||||
593 | if (outstanding_node) | |||
594 | outstanding_node = 0; | |||
595 | ||||
596 | add_word_args ("</h%d>", level + 2); | |||
597 | close_paragraph(); | |||
598 | filling_enabled = 1; | |||
599 | no_indent = old_no_indent; | |||
600 | } | |||
601 | ||||
602 | ||||
603 | /* Shift the meaning of @section to @chapter. */ | |||
604 | void | |||
605 | cm_raisesections (void) | |||
606 | { | |||
607 | discard_until ("\n"); | |||
608 | section_alist_offset--; | |||
609 | } | |||
610 | ||||
611 | /* Shift the meaning of @chapter to @section. */ | |||
612 | void | |||
613 | cm_lowersections (void) | |||
614 | { | |||
615 | discard_until ("\n"); | |||
616 | section_alist_offset++; | |||
617 | } | |||
618 | ||||
619 | /* The command still works, but prints a warning message in addition. */ | |||
620 | void | |||
621 | cm_ideprecated (int arg, int start, int end) | |||
622 | { | |||
623 | warning (_("%c%s is obsolete; use %c%s instead")((const char *) ("%c%s is obsolete; use %c%s instead")), | |||
624 | COMMAND_PREFIX'@', command, COMMAND_PREFIX'@', command + 1); | |||
625 | sectioning_underscore (command + 1); | |||
626 | } | |||
627 | ||||
628 | ||||
629 | /* Treat this just like @unnumbered. The only difference is | |||
630 | in node defaulting. */ | |||
631 | void | |||
632 | cm_top (void) | |||
633 | { | |||
634 | /* It is an error to have more than one @top. */ | |||
635 | if (top_node_seen && strcmp (current_node, "Top") != 0) | |||
636 | { | |||
637 | TAG_ENTRY *tag = tag_table; | |||
638 | ||||
639 | line_error (_("Node with %ctop as a section already exists")((const char *) ("Node with %ctop as a section already exists" )), | |||
640 | COMMAND_PREFIX'@'); | |||
641 | ||||
642 | while (tag) | |||
643 | { | |||
644 | if (tag->flags & TAG_FLAG_IS_TOP16) | |||
645 | { | |||
646 | file_line_error (tag->filename, tag->line_no, | |||
647 | _("Here is the %ctop node")((const char *) ("Here is the %ctop node")), COMMAND_PREFIX'@'); | |||
648 | return; | |||
649 | } | |||
650 | tag = tag->next_ent; | |||
651 | } | |||
652 | } | |||
653 | else | |||
654 | { | |||
655 | top_node_seen = 1; | |||
656 | ||||
657 | /* It is an error to use @top before using @node. */ | |||
658 | if (!tag_table) | |||
659 | { | |||
660 | char *top_name; | |||
661 | ||||
662 | get_rest_of_line (0, &top_name); | |||
663 | line_error (_("%ctop used before %cnode, defaulting to %s")((const char *) ("%ctop used before %cnode, defaulting to %s" )), | |||
664 | COMMAND_PREFIX'@', COMMAND_PREFIX'@', top_name); | |||
665 | execute_string ("@node Top, , (dir), (dir)\n@top %s\n", top_name); | |||
666 | free (top_name); | |||
667 | return; | |||
668 | } | |||
669 | ||||
670 | cm_unnumbered (); | |||
671 | ||||
672 | /* The most recently defined node is the top node. */ | |||
673 | tag_table->flags |= TAG_FLAG_IS_TOP16; | |||
674 | ||||
675 | /* Now set the logical hierarchical level of the Top node. */ | |||
676 | { | |||
677 | int orig_offset = input_text_offset; | |||
678 | ||||
679 | input_text_offset = search_forward (node_search_string, orig_offset); | |||
680 | ||||
681 | if (input_text_offset > 0) | |||
682 | { | |||
683 | int this_section; | |||
684 | ||||
685 | /* We have encountered a non-top node, so mark that one exists. */ | |||
686 | non_top_node_seen = 1; | |||
687 | ||||
688 | /* Move to the end of this line, and find out what the | |||
689 | sectioning command is here. */ | |||
690 | while (input_text[input_text_offset] != '\n') | |||
691 | input_text_offset++; | |||
692 | ||||
693 | if (input_text_offset < input_text_length) | |||
694 | input_text_offset++; | |||
695 | ||||
696 | this_section = what_section (input_text + input_text_offset, | |||
697 | NULL((void *)0)); | |||
698 | ||||
699 | /* If we found a sectioning command, then give the top section | |||
700 | a level of this section - 1. */ | |||
701 | if (this_section != -1) | |||
702 | set_top_section_level (this_section - 1); | |||
703 | } | |||
704 | input_text_offset = orig_offset; | |||
705 | } | |||
706 | } | |||
707 | } | |||
708 | ||||
709 | /* The remainder of the text on this line is a chapter heading. */ | |||
710 | void | |||
711 | cm_chapter (void) | |||
712 | { | |||
713 | enum_marker = 0; | |||
714 | sectioning_underscore ("chapter"); | |||
715 | } | |||
716 | ||||
717 | /* The remainder of the text on this line is a section heading. */ | |||
718 | void | |||
719 | cm_section (void) | |||
720 | { | |||
721 | sectioning_underscore ("section"); | |||
722 | } | |||
723 | ||||
724 | /* The remainder of the text on this line is a subsection heading. */ | |||
725 | void | |||
726 | cm_subsection (void) | |||
727 | { | |||
728 | sectioning_underscore ("subsection"); | |||
729 | } | |||
730 | ||||
731 | /* The remainder of the text on this line is a subsubsection heading. */ | |||
732 | void | |||
733 | cm_subsubsection (void) | |||
734 | { | |||
735 | sectioning_underscore ("subsubsection"); | |||
736 | } | |||
737 | ||||
738 | /* The remainder of the text on this line is an unnumbered heading. */ | |||
739 | void | |||
740 | cm_unnumbered (void) | |||
741 | { | |||
742 | enum_marker = UNNUMBERED_MAGIC2048; | |||
743 | sectioning_underscore ("unnumbered"); | |||
744 | } | |||
745 | ||||
746 | /* The remainder of the text on this line is an unnumbered section heading. */ | |||
747 | void | |||
748 | cm_unnumberedsec (void) | |||
749 | { | |||
750 | sectioning_underscore ("unnumberedsec"); | |||
751 | } | |||
752 | ||||
753 | /* The remainder of the text on this line is an unnumbered | |||
754 | subsection heading. */ | |||
755 | void | |||
756 | cm_unnumberedsubsec (void) | |||
757 | { | |||
758 | sectioning_underscore ("unnumberedsubsec"); | |||
759 | } | |||
760 | ||||
761 | /* The remainder of the text on this line is an unnumbered | |||
762 | subsubsection heading. */ | |||
763 | void | |||
764 | cm_unnumberedsubsubsec (void) | |||
765 | { | |||
766 | sectioning_underscore ("unnumberedsubsubsec"); | |||
767 | } | |||
768 | ||||
769 | /* The remainder of the text on this line is an appendix heading. */ | |||
770 | void | |||
771 | cm_appendix (void) | |||
772 | { | |||
773 | /* Reset top level number so we start from Appendix A */ | |||
774 | if (enum_marker != APPENDIX_MAGIC1024) | |||
775 | numbers [0] = 0; | |||
776 | enum_marker = APPENDIX_MAGIC1024; | |||
777 | sectioning_underscore ("appendix"); | |||
778 | } | |||
779 | ||||
780 | /* The remainder of the text on this line is an appendix section heading. */ | |||
781 | void | |||
782 | cm_appendixsec (void) | |||
783 | { | |||
784 | sectioning_underscore ("appendixsec"); | |||
785 | } | |||
786 | ||||
787 | /* The remainder of the text on this line is an appendix subsection heading. */ | |||
788 | void | |||
789 | cm_appendixsubsec (void) | |||
790 | { | |||
791 | sectioning_underscore ("appendixsubsec"); | |||
792 | } | |||
793 | ||||
794 | /* The remainder of the text on this line is an appendix | |||
795 | subsubsection heading. */ | |||
796 | void | |||
797 | cm_appendixsubsubsec (void) | |||
798 | { | |||
799 | sectioning_underscore ("appendixsubsubsec"); | |||
800 | } | |||
801 | ||||
802 | /* Compatibility functions substitute for chapter, section, etc. */ | |||
803 | void | |||
804 | cm_majorheading (void) | |||
805 | { | |||
806 | sectioning_underscore ("majorheading"); | |||
807 | } | |||
808 | ||||
809 | void | |||
810 | cm_chapheading (void) | |||
811 | { | |||
812 | sectioning_underscore ("chapheading"); | |||
813 | } | |||
814 | ||||
815 | void | |||
816 | cm_heading (void) | |||
817 | { | |||
818 | sectioning_underscore ("heading"); | |||
819 | } | |||
820 | ||||
821 | void | |||
822 | cm_subheading (void) | |||
823 | { | |||
824 | sectioning_underscore ("subheading"); | |||
825 | } | |||
826 | ||||
827 | void | |||
828 | cm_subsubheading (void) | |||
829 | { | |||
830 | sectioning_underscore ("subsubheading"); | |||
| ||||
831 | } |