| File: | src/gnu/usr.bin/texinfo/makeinfo/sectioning.c |
| Warning: | line 425, 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 | } |