clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name files.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/gnu/usr.bin/texinfo/obj/makeinfo -resource-dir /usr/local/lib/clang/13.0.0 -D HAVE_CONFIG_H -I . -I /usr/src/gnu/usr.bin/texinfo/makeinfo -I .. -I /usr/src/gnu/usr.bin/texinfo/lib -I ../intl -D LOCALEDIR="/usr/share/locale" -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/gnu/usr.bin/texinfo/obj/makeinfo -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/gnu/usr.bin/texinfo/makeinfo/files.c
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 | |
| 20 | |
| 21 | #include "system.h" |
| 22 | #include "files.h" |
| 23 | #include "html.h" |
| 24 | #include "index.h" |
| 25 | #include "macro.h" |
| 26 | #include "makeinfo.h" |
| 27 | #include "node.h" |
| 28 | |
| 29 | FSTACK *filestack = NULL; |
| 30 | |
| 31 | static int node_filename_stack_index = 0; |
| 32 | static int node_filename_stack_size = 0; |
| 33 | static char **node_filename_stack = NULL; |
| 34 |
|
| 35 | |
| 36 | |
| 37 | |
| 38 | |
| 39 | |
| 40 | static char * |
| 41 | extract_colon_unit (char *string, int *index) |
| 42 | { |
| 43 | int start; |
| 44 | int path_sep_char = PATH_SEP[0]; |
| 45 | int i = *index; |
| 46 | |
| 47 | if (!string || (i >= strlen (string))) |
| 48 | return NULL; |
| 49 | |
| 50 | |
| 51 | |
| 52 | |
| 53 | |
| 54 | |
| 55 | if (i && string[i] == path_sep_char) |
| 56 | i++; |
| 57 | |
| 58 | start = i; |
| 59 | while (string[i] && string[i] != path_sep_char) i++; |
| 60 | *index = i; |
| 61 | |
| 62 | if (i == start) |
| 63 | { |
| 64 | if (string[i]) |
| 65 | (*index)++; |
| 66 | |
| 67 | |
| 68 | return xstrdup (""); |
| 69 | } |
| 70 | else |
| 71 | { |
| 72 | char *value; |
| 73 | |
| 74 | value = xmalloc (1 + (i - start)); |
| 75 | memcpy (value, &string[start], (i - start)); |
| 76 | value [i - start] = 0; |
| 77 | |
| 78 | return value; |
| 79 | } |
| 80 | } |
| 81 | |
| 82 | |
| 83 | |
| 84 | |
| 85 | |
| 86 | char * |
| 87 | get_file_info_in_path (char *filename, char *path, struct stat *finfo) |
| 88 | { |
| 89 | char *dir; |
| 90 | int result, index = 0; |
| 91 | |
| 92 | if (path == NULL) |
| 93 | path = "."; |
| 94 | |
| 95 | |
| 96 | if (IS_ABSOLUTE (filename) |
| 97 | || (*filename == '.' |
| 98 | && (IS_SLASH (filename[1]) |
| 99 | || (filename[1] == '.' && IS_SLASH (filename[2]))))) |
| 100 | { |
| 101 | if (stat (filename, finfo) == 0) |
| 102 | return xstrdup (filename); |
| 103 | else |
| 104 | return NULL; |
| 105 | } |
| 106 | |
| 107 | while ((dir = extract_colon_unit (path, &index))) |
| 108 | { |
| 109 | char *fullpath; |
| 110 | |
| 111 | if (!*dir) |
| 112 | { |
| 113 | free (dir); |
| 114 | dir = xstrdup ("."); |
| 115 | } |
| 116 | |
| 117 | fullpath = xmalloc (2 + strlen (dir) + strlen (filename)); |
| 118 | sprintf (fullpath, "%s/%s", dir, filename); |
| 119 | free (dir); |
| 120 | |
| 121 | result = stat (fullpath, finfo); |
| 122 | |
| 123 | if (result == 0) |
| 124 | return fullpath; |
| 125 | else |
| 126 | free (fullpath); |
| 127 | } |
| 128 | return NULL; |
| 129 | } |
| 130 | |
| 131 | |
| 132 | void |
| 133 | prepend_to_include_path (char *path) |
| 134 | { |
| 135 | if (!include_files_path) |
| 136 | { |
| 137 | include_files_path = xstrdup (path); |
| 138 | include_files_path = xrealloc (include_files_path, |
| 139 | strlen (include_files_path) + 3); |
| 140 | strcat (strcat (include_files_path, PATH_SEP), "."); |
| 141 | } |
| 142 | else |
| 143 | { |
| 144 | char *tmp = xstrdup (include_files_path); |
| 145 | include_files_path = xrealloc (include_files_path, |
| 146 | strlen (include_files_path) + strlen (path) + 2); |
| 147 | strcpy (include_files_path, path); |
| 148 | strcat (include_files_path, PATH_SEP); |
| 149 | strcat (include_files_path, tmp); |
| 150 | free (tmp); |
| 151 | } |
| 152 | } |
| 153 | |
| 154 | void |
| 155 | append_to_include_path (char *path) |
| 156 | { |
| 157 | if (!include_files_path) |
| 158 | include_files_path = xstrdup ("."); |
| 159 | |
| 160 | include_files_path = (char *) xrealloc (include_files_path, |
| 161 | 2 + strlen (include_files_path) + strlen (path)); |
| 162 | strcat (include_files_path, PATH_SEP); |
| 163 | strcat (include_files_path, path); |
| 164 | } |
| 165 | |
| 166 | |
| 167 | void |
| 168 | pop_path_from_include_path (void) |
| 169 | { |
| 170 | int i = 0; |
| 171 | char *tmp; |
| 172 | |
| 173 | if (include_files_path) |
| 1 | Assuming 'include_files_path' is null | |
|
| |
| 174 | for (i = 0; i < strlen (include_files_path) |
| 175 | && include_files_path[i] != ':'; i++); |
| 176 | |
| 177 | |
| 178 | tmp = (char *) xmalloc (strlen (include_files_path) - i); |
| 3 | | Null pointer passed as 1st argument to string length function |
|
| 179 | strcpy (tmp, (char *) include_files_path + i + 1); |
| 180 | |
| 181 | free (include_files_path); |
| 182 | include_files_path = tmp; |
| 183 | } |
| 184 |
|
| 185 | |
| 186 | |
| 187 | |
| 188 | |
| 189 | |
| 190 | char * |
| 191 | find_and_load (char *filename, int use_path) |
| 192 | { |
| 193 | struct stat fileinfo; |
| 194 | long file_size; |
| 195 | int file = -1, count = 0; |
| 196 | char *fullpath, *result; |
| 197 | int n, bytes_to_read; |
| 198 | |
| 199 | result = fullpath = NULL; |
| 200 | |
| 201 | fullpath |
| 202 | = get_file_info_in_path (filename, use_path ? include_files_path : NULL, |
| 203 | &fileinfo); |
| 204 | |
| 205 | if (!fullpath) |
| 206 | goto error_exit; |
| 207 | |
| 208 | filename = fullpath; |
| 209 | file_size = (long) fileinfo.st_size; |
| 210 | |
| 211 | file = open (filename, O_RDONLY); |
| 212 | if (file < 0) |
| 213 | goto error_exit; |
| 214 | |
| 215 | |
| 216 | result = xmalloc (file_size + 2); |
| 217 | |
| 218 | |
| 219 | |
| 220 | |
| 221 | |
| 222 | |
| 223 | bytes_to_read = file_size; |
| 224 | while ((n = read (file, result + count, bytes_to_read)) > 0) |
| 225 | { |
| 226 | count += n; |
| 227 | bytes_to_read -= n; |
| 228 | } |
| 229 | if (0 < count && count < file_size) |
| 230 | result = xrealloc (result, count + 2); |
| 231 | else if (n == -1) |
| 232 | error_exit: |
| 233 | { |
| 234 | if (result) |
| 235 | free (result); |
| 236 | |
| 237 | if (fullpath) |
| 238 | free (fullpath); |
| 239 | |
| 240 | if (file != -1) |
| 241 | close (file); |
| 242 | |
| 243 | return NULL; |
| 244 | } |
| 245 | close (file); |
| 246 | |
| 247 | |
| 248 | input_text = result; |
| 249 | input_text_length = count; |
| 250 | input_filename = fullpath; |
| 251 | node_filename = xstrdup (fullpath); |
| 252 | input_text_offset = 0; |
| 253 | line_number = 1; |
| 254 | |
| 255 | |
| 256 | |
| 257 | input_text[input_text_length] = '\n'; |
| 258 | |
| 259 | input_text[input_text_length+1] = 0; |
| 260 | return result; |
| 261 | } |
| 262 |
|
| 263 | |
| 264 | static void |
| 265 | push_node_filename (void) |
| 266 | { |
| 267 | if (node_filename_stack_index + 1 > node_filename_stack_size) |
| 268 | node_filename_stack = xrealloc |
| 269 | (node_filename_stack, (node_filename_stack_size += 10) * sizeof (char *)); |
| 270 | |
| 271 | node_filename_stack[node_filename_stack_index] = node_filename; |
| 272 | node_filename_stack_index++; |
| 273 | } |
| 274 | |
| 275 | static void |
| 276 | pop_node_filename (void) |
| 277 | { |
| 278 | node_filename = node_filename_stack[--node_filename_stack_index]; |
| 279 | } |
| 280 | |
| 281 | |
| 282 | void |
| 283 | pushfile (void) |
| 284 | { |
| 285 | FSTACK *newstack = xmalloc (sizeof (FSTACK)); |
| 286 | newstack->filename = input_filename; |
| 287 | newstack->text = input_text; |
| 288 | newstack->size = input_text_length; |
| 289 | newstack->offset = input_text_offset; |
| 290 | newstack->line_number = line_number; |
| 291 | newstack->next = filestack; |
| 292 | |
| 293 | filestack = newstack; |
| 294 | push_node_filename (); |
| 295 | } |
| 296 | |
| 297 | |
| 298 | void |
| 299 | popfile (void) |
| 300 | { |
| 301 | FSTACK *tos = filestack; |
| 302 | |
| 303 | if (!tos) |
| 304 | abort (); |
| 305 | |
| 306 | if (macro_expansion_output_stream) |
| 307 | { |
| 308 | maybe_write_itext (input_text, input_text_offset); |
| 309 | forget_itext (input_text); |
| 310 | } |
| 311 | |
| 312 | |
| 313 | filestack = filestack->next; |
| 314 | |
| 315 | |
| 316 | if (!executing_string && !me_executing_string) |
| 317 | discard_braces (); |
| 318 | |
| 319 | |
| 320 | input_filename = tos->filename; |
| 321 | input_text = tos->text; |
| 322 | input_text_length = tos->size; |
| 323 | input_text_offset = tos->offset; |
| 324 | line_number = tos->line_number; |
| 325 | free (tos); |
| 326 | |
| 327 | |
| 328 | pop_node_filename (); |
| 329 | } |
| 330 | |
| 331 | |
| 332 | void |
| 333 | flush_file_stack (void) |
| 334 | { |
| 335 | while (filestack) |
| 336 | { |
| 337 | char *fname = input_filename; |
| 338 | char *text = input_text; |
| 339 | popfile (); |
| 340 | free (fname); |
| 341 | free (text); |
| 342 | } |
| 343 | } |
| 344 | |
| 345 | |
| 346 | |
| 347 | static int |
| 348 | skip_directory_part (char *filename) |
| 349 | { |
| 350 | int i = strlen (filename) - 1; |
| 351 | |
| 352 | while (i && !IS_SLASH (filename[i])) |
| 353 | i--; |
| 354 | if (IS_SLASH (filename[i])) |
| 355 | i++; |
| 356 | else if (filename[i] && HAVE_DRIVE (filename)) |
| 357 | i = 2; |
| 358 | |
| 359 | return i; |
| 360 | } |
| 361 | |
| 362 | static char * |
| 363 | filename_non_directory (char *name) |
| 364 | { |
| 365 | return xstrdup (name + skip_directory_part (name)); |
| 366 | } |
| 367 | |
| 368 | |
| 369 | |
| 370 | |
| 371 | char * |
| 372 | filename_part (char *filename) |
| 373 | { |
| 374 | char *basename = filename_non_directory (filename); |
| 375 | |
| 376 | #ifdef REMOVE_OUTPUT_EXTENSIONS |
| 377 | |
| 378 | { |
| 379 | char *temp = strrchr (basename, '.'); |
| 380 | if (temp) |
| 381 | *temp = 0; |
| 382 | } |
| 383 | #endif /* REMOVE_OUTPUT_EXTENSIONS */ |
| 384 | return basename; |
| 385 | } |
| 386 | |
| 387 | |
| 388 | char * |
| 389 | pathname_part (char *filename) |
| 390 | { |
| 391 | char *result = NULL; |
| 392 | int i; |
| 393 | |
| 394 | filename = expand_filename (filename, ""); |
| 395 | |
| 396 | i = skip_directory_part (filename); |
| 397 | if (i) |
| 398 | { |
| 399 | result = xmalloc (1 + i); |
| 400 | strncpy (result, filename, i); |
| 401 | result[i] = 0; |
| 402 | } |
| 403 | free (filename); |
| 404 | return result; |
| 405 | } |
| 406 | |
| 407 | |
| 408 | static char * |
| 409 | full_pathname (char *filename) |
| 410 | { |
| 411 | int initial_character; |
| 412 | char *result; |
| 413 | |
| 414 | |
| 415 | if (!filename || !*filename) |
| 416 | return xstrdup (""); |
| 417 | |
| 418 | |
| 419 | if (IS_ABSOLUTE (filename) || |
| 420 | (*filename == '.' && |
| 421 | (IS_SLASH (filename[1]) || |
| 422 | (filename[1] == '.' && IS_SLASH (filename[2]))))) |
| 423 | return xstrdup (filename); |
| 424 | |
| 425 | initial_character = *filename; |
| 426 | if (initial_character != '~') |
| 427 | { |
| 428 | char *localdir = xmalloc (1025); |
| 429 | #ifdef HAVE_GETCWD |
| 430 | if (!getcwd (localdir, 1024)) |
| 431 | #else |
| 432 | if (!getwd (localdir)) |
| 433 | #endif |
| 434 | { |
| 435 | fprintf (stderr, _("%s: getwd: %s, %s\n"), |
| 436 | progname, filename, localdir); |
| 437 | xexit (1); |
| 438 | } |
| 439 | |
| 440 | strcat (localdir, "/"); |
| 441 | strcat (localdir, filename); |
| 442 | result = xstrdup (localdir); |
| 443 | free (localdir); |
| 444 | } |
| 445 | else |
| 446 | { |
| 447 | |
| 448 | |
| 449 | #ifndef WIN32 |
| 450 | if (IS_SLASH (filename[1])) |
| 451 | { |
| 452 | |
| 453 | |
| 454 | char *temp_home; |
| 455 | |
| 456 | temp_home = (char *) getenv ("HOME"); |
| 457 | result = xmalloc (strlen (&filename[1]) |
| 458 | + 1 |
| 459 | + temp_home ? strlen (temp_home) |
| 460 | : 0); |
| 461 | *result = 0; |
| 462 | |
| 463 | if (temp_home) |
| 464 | strcpy (result, temp_home); |
| 465 | |
| 466 | strcat (result, &filename[1]); |
| 467 | } |
| 468 | else |
| 469 | { |
| 470 | struct passwd *user_entry; |
| 471 | int i, c; |
| 472 | char *username = xmalloc (257); |
| 473 | |
| 474 | for (i = 1; (c = filename[i]); i++) |
| 475 | { |
| 476 | if (IS_SLASH (c)) |
| 477 | break; |
| 478 | else |
| 479 | username[i - 1] = c; |
| 480 | } |
| 481 | if (c) |
| 482 | username[i - 1] = 0; |
| 483 | |
| 484 | user_entry = getpwnam (username); |
| 485 | |
| 486 | if (!user_entry) |
| 487 | return xstrdup (filename); |
| 488 | |
| 489 | result = xmalloc (1 + strlen (user_entry->pw_dir) |
| 490 | + strlen (&filename[i])); |
| 491 | strcpy (result, user_entry->pw_dir); |
| 492 | strcat (result, &filename[i]); |
| 493 | } |
| 494 | #endif /* not WIN32 */ |
| 495 | } |
| 496 | return result; |
| 497 | } |
| 498 | |
| 499 | |
| 500 | char * |
| 501 | expand_filename (char *filename, char *input_name) |
| 502 | { |
| 503 | int i; |
| 504 | |
| 505 | if (filename) |
| 506 | { |
| 507 | filename = full_pathname (filename); |
| 508 | if (IS_ABSOLUTE (filename) |
| 509 | || (*filename == '.' && |
| 510 | (IS_SLASH (filename[1]) || |
| 511 | (filename[1] == '.' && IS_SLASH (filename[2]))))) |
| 512 | return filename; |
| 513 | } |
| 514 | else |
| 515 | { |
| 516 | filename = filename_non_directory (input_name); |
| 517 | |
| 518 | if (!*filename) |
| 519 | { |
| 520 | free (filename); |
| 521 | filename = xstrdup ("noname.texi"); |
| 522 | } |
| 523 | |
| 524 | for (i = strlen (filename) - 1; i; i--) |
| 525 | if (filename[i] == '.') |
| 526 | break; |
| 527 | |
| 528 | if (!i) |
| 529 | i = strlen (filename); |
| 530 | |
| 531 | if (i + 6 > (strlen (filename))) |
| 532 | filename = xrealloc (filename, i + 6); |
| 533 | strcpy (filename + i, html ? ".html" : ".info"); |
| 534 | return filename; |
| 535 | } |
| 536 | |
| 537 | if (IS_ABSOLUTE (input_name)) |
| 538 | { |
| 539 | |
| 540 | char *result; |
| 541 | |
| 542 | i = strlen (input_name) - 1; |
| 543 | |
| 544 | result = xmalloc (1 + strlen (input_name) + strlen (filename)); |
| 545 | strcpy (result, input_name); |
| 546 | |
| 547 | while (!IS_SLASH (result[i]) && i) |
| 548 | i--; |
| 549 | if (IS_SLASH (result[i])) |
| 550 | i++; |
| 551 | |
| 552 | strcpy (&result[i], filename); |
| 553 | free (filename); |
| 554 | return result; |
| 555 | } |
| 556 | return filename; |
| 557 | } |
| 558 | |
| 559 | char * |
| 560 | output_name_from_input_name (char *name) |
| 561 | { |
| 562 | return expand_filename (NULL, name); |
| 563 | } |
| 564 | |
| 565 | |
| 566 | |
| 567 | |
| 568 | |
| 569 | |
| 570 | |
| 571 | char * |
| 572 | normalize_filename (char *fname) |
| 573 | { |
| 574 | int maxlen; |
| 575 | char orig[PATH_MAX + 1]; |
| 576 | int i; |
| 577 | char *lastdot, *p; |
| 578 | |
| 579 | #ifdef _PC_NAME_MAX |
| 580 | maxlen = pathconf (fname, _PC_NAME_MAX); |
| 581 | if (maxlen < 1) |
| 582 | #endif |
| 583 | maxlen = PATH_MAX; |
| 584 | |
| 585 | i = skip_directory_part (fname); |
| 586 | if (fname[i] == '\0') |
| 587 | return fname; |
| 588 | strcpy (orig, fname + i); |
| 589 | |
| 590 | switch (maxlen) |
| 591 | { |
| 592 | case 12: |
| 593 | if (orig[0] == '.') |
| 594 | orig[0] = '_'; |
| 595 | lastdot = strrchr (orig, '.'); |
| 596 | if (!lastdot) |
| 597 | lastdot = orig + strlen (orig); |
| 598 | strncpy (fname + i, orig, lastdot - orig); |
| 599 | for (p = fname + i; |
| 600 | p < fname + i + (lastdot - orig) && p < fname + i + 8; |
| 601 | p++) |
| 602 | if (*p == '.') |
| 603 | *p = '_'; |
| 604 | *p = '\0'; |
| 605 | if (*lastdot == '.') |
| 606 | strncat (fname + i, lastdot, 4); |
| 607 | break; |
| 608 | case 14: |
| 609 | strcpy (fname + i, orig); |
| 610 | if (strlen (fname + i) > 14) |
| 611 | fname[i + 14] = '\0'; |
| 612 | break; |
| 613 | default: |
| 614 | strcpy (fname + i, orig); |
| 615 | if (strlen (fname) > maxlen - 1) |
| 616 | fname[maxlen - 1] = '\0'; |
| 617 | break; |
| 618 | } |
| 619 | |
| 620 | return fname; |
| 621 | } |
| 622 |
|
| 623 | |
| 624 | |
| 625 | |
| 626 | |
| 627 | static DELAYED_WRITE *delayed_writes = NULL; |
| 628 | int handling_delayed_writes = 0; |
| 629 | |
| 630 | void |
| 631 | register_delayed_write (char *delayed_command) |
| 632 | { |
| 633 | DELAYED_WRITE *new; |
| 634 | |
| 635 | if (!current_output_filename || !*current_output_filename) |
| 636 | { |
| 637 | |
| 638 | warning (_("`%s' omitted before output filename"), delayed_command); |
| 639 | return; |
| 640 | } |
| 641 | |
| 642 | if (STREQ (current_output_filename, "-")) |
| 643 | { |
| 644 | |
| 645 | |
| 646 | warning (_("`%s' omitted since writing to stdout"), delayed_command); |
| 647 | return; |
| 648 | } |
| 649 | |
| 650 | |
| 651 | |
| 652 | if (FILENAME_CMP (current_output_filename, NULL_DEVICE) == 0 |
| 653 | || FILENAME_CMP (current_output_filename, ALSO_NULL_DEVICE) == 0) |
| 654 | return; |
| 655 | |
| 656 | |
| 657 | |
| 658 | if (!executing_string && html) |
| 659 | html_output_head (); |
| 660 | |
| 661 | flush_output (); |
| 662 | |
| 663 | new = xmalloc (sizeof (DELAYED_WRITE)); |
| 664 | new->command = xstrdup (delayed_command); |
| 665 | new->filename = xstrdup (current_output_filename); |
| 666 | new->input_filename = xstrdup (input_filename); |
| 667 | new->position = output_position; |
| 668 | new->calling_line = line_number; |
| 669 | new->node = current_node ? xstrdup (current_node): ""; |
| 670 | |
| 671 | new->node_order = node_order; |
| 672 | new->index_order = index_counter; |
| 673 | |
| 674 | new->next = delayed_writes; |
| 675 | delayed_writes = new; |
| 676 | } |
| 677 | |
| 678 | void |
| 679 | handle_delayed_writes (void) |
| 680 | { |
| 681 | DELAYED_WRITE *temp = (DELAYED_WRITE *) reverse_list |
| 682 | ((GENERIC_LIST *) delayed_writes); |
| 683 | int position_shift_amount, line_number_shift_amount; |
| 684 | char *delayed_buf; |
| 685 | |
| 686 | handling_delayed_writes = 1; |
| 687 | |
| 688 | while (temp) |
| 689 | { |
| 690 | delayed_buf = find_and_load (temp->filename, 0); |
| 691 | |
| 692 | if (output_paragraph_offset > 0) |
| 693 | { |
| 694 | error (_("Output buffer not empty.")); |
| 695 | return; |
| 696 | } |
| 697 | |
| 698 | if (!delayed_buf) |
| 699 | { |
| 700 | fs_error (temp->filename); |
| 701 | return; |
| 702 | } |
| 703 | |
| 704 | output_stream = fopen (temp->filename, "w"); |
| 705 | if (!output_stream) |
| 706 | { |
| 707 | fs_error (temp->filename); |
| 708 | return; |
| 709 | } |
| 710 | |
| 711 | if (fwrite (delayed_buf, 1, temp->position, output_stream) != temp->position) |
| 712 | { |
| 713 | fs_error (temp->filename); |
| 714 | return; |
| 715 | } |
| 716 | |
| 717 | { |
| 718 | int output_position_at_start = output_position; |
| 719 | int line_number_at_start = output_line_number; |
| 720 | |
| 721 | |
| 722 | |
| 723 | input_filename = temp->input_filename; |
| 724 | line_number = temp->calling_line; |
| 725 | |
| 726 | execute_string ("%s", temp->command); |
| 727 | flush_output (); |
| 728 | |
| 729 | |
| 730 | |
| 731 | position_shift_amount = output_position - output_position_at_start; |
| 732 | line_number_shift_amount = output_line_number - line_number_at_start; |
| 733 | } |
| 734 | |
| 735 | if (fwrite (delayed_buf + temp->position, 1, |
| 736 | input_text_length - temp->position, output_stream) |
| 737 | != input_text_length - temp->position |
| 738 | || fclose (output_stream) != 0) |
| 739 | fs_error (temp->filename); |
| 740 | |
| 741 | |
| 742 | free (delayed_buf); |
| 743 | |
| 744 | |
| 745 | |
| 746 | if (!html && !xml) |
| 747 | { |
| 748 | TAG_ENTRY *node; |
| 749 | for (node = tag_table; node; node = node->next_ent) |
| 750 | if (node->order > temp->node_order) |
| 751 | node->position += position_shift_amount; |
| 752 | } |
| 753 | |
| 754 | |
| 755 | |
| 756 | { |
| 757 | int i; |
| 758 | for (i = 0; i < defined_indices; i++) |
| 759 | if (name_index_alist[i]) |
| 760 | { |
| 761 | char *name = ((INDEX_ALIST *) name_index_alist[i])->name; |
| 762 | INDEX_ELT *index; |
| 763 | for (index = index_list (name); index; index = index->next) |
| 764 | if ((no_headers || STREQ (index->node, temp->node)) |
| 765 | && index->entry_number > temp->index_order) |
| 766 | index->output_line += line_number_shift_amount; |
| 767 | } |
| 768 | } |
| 769 | |
| 770 | |
| 771 | |
| 772 | { |
| 773 | DELAYED_WRITE *future_write = temp->next; |
| 774 | while (future_write) |
| 775 | { |
| 776 | if (STREQ (temp->filename, future_write->filename)) |
| 777 | future_write->position += position_shift_amount; |
| 778 | future_write = future_write->next; |
| 779 | } |
| 780 | } |
| 781 | |
| 782 | temp = temp->next; |
| 783 | } |
| 784 | } |