~ubuntu-branches/ubuntu/maverick/texinfo/maverick

« back to all changes in this revision

Viewing changes to makeinfo/files.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Preining
  • Date: 2005-10-28 15:10:30 UTC
  • mto: (2.1.1 dapper) (3.1.4 hardy)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20051028151030-9nsf2s2k2z3fktjt
Tags: upstream-4.8
ImportĀ upstreamĀ versionĀ 4.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* files.c -- file-related functions for makeinfo.
2
 
   $Id: files.c,v 1.10 2002/01/16 15:52:45 karl Exp $
 
2
   $Id: files.c,v 1.5 2004/07/27 00:06:31 karl Exp $
3
3
 
4
 
   Copyright (C) 1998, 99, 2000, 01, 02 Free Software Foundation, Inc.
 
4
   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
 
5
   Foundation, Inc.
5
6
 
6
7
   This program is free software; you can redistribute it and/or modify
7
8
   it under the terms of the GNU General Public License as published by
19
20
 
20
21
#include "system.h"
21
22
#include "files.h"
 
23
#include "html.h"
 
24
#include "index.h"
22
25
#include "macro.h"
23
26
#include "makeinfo.h"
 
27
#include "node.h"
24
28
 
25
29
FSTACK *filestack = NULL;
26
30
 
27
31
static int node_filename_stack_index = 0;
28
32
static int node_filename_stack_size = 0;
29
33
static char **node_filename_stack = NULL;
30
 
 
31
34
 
32
35
/* Looking for include files.  */
33
36
 
35
38
   return the next one pointed to by INDEX, or NULL if there are no more.
36
39
   Advance INDEX to the character after the colon. */
37
40
static char *
38
 
extract_colon_unit (string, index)
39
 
     char *string;
40
 
     int *index;
 
41
extract_colon_unit (char *string, int *index)
41
42
{
42
43
  int start;
43
44
  int path_sep_char = PATH_SEP[0];
82
83
   When found, return the stat () info for FILENAME in FINFO.
83
84
   If PATH is NULL, only the current directory is searched.
84
85
   If the file could not be found, return a NULL pointer. */
85
 
static char *
86
 
get_file_info_in_path (filename, path, finfo)
87
 
     char *filename, *path;
88
 
     struct stat *finfo;
 
86
char *
 
87
get_file_info_in_path (char *filename, char *path, struct stat *finfo)
89
88
{
90
89
  char *dir;
91
90
  int result, index = 0;
128
127
    }
129
128
  return NULL;
130
129
}
 
130
 
 
131
/* Prepend and append new paths to include_files_path.  */
 
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); /* 3 for ":.\0" */
 
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); /* 2 for ":\0" */
 
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
/* Remove the first path from the include_files_path.  */
 
167
void
 
168
pop_path_from_include_path (void)
 
169
{
 
170
  int i = 0;
 
171
  char *tmp;
 
172
 
 
173
  if (include_files_path)
 
174
    for (i = 0; i < strlen (include_files_path)
 
175
        && include_files_path[i] != ':'; i++);
 
176
 
 
177
  /* Advance include_files_path to the next char from ':'  */
 
178
  tmp = (char *) xmalloc (strlen (include_files_path) - i);
 
179
  strcpy (tmp, (char *) include_files_path + i + 1);
 
180
 
 
181
  free (include_files_path);
 
182
  include_files_path = tmp;
 
183
}
131
184
 
132
185
/* Find and load the file named FILENAME.  Return a pointer to
133
 
   the loaded file, or NULL if it can't be loaded. */
 
186
   the loaded file, or NULL if it can't be loaded.  If USE_PATH is zero,
 
187
   just look for the given file (this is used in handle_delayed_writes),
 
188
   else search along include_files_path.   */
 
189
 
134
190
char *
135
 
find_and_load (filename)
136
 
     char *filename;
 
191
find_and_load (char *filename, int use_path)
137
192
{
138
193
  struct stat fileinfo;
139
194
  long file_size;
143
198
 
144
199
  result = fullpath = NULL;
145
200
 
146
 
  fullpath = get_file_info_in_path (filename, include_files_path, &fileinfo);
 
201
  fullpath
 
202
    = get_file_info_in_path (filename, use_path ? include_files_path : NULL, 
 
203
                             &fileinfo);
147
204
 
148
205
  if (!fullpath)
149
206
    goto error_exit;
204
261
}
205
262
 
206
263
/* Pushing and popping files.  */
207
 
void
208
 
push_node_filename ()
 
264
static void
 
265
push_node_filename (void)
209
266
{
210
267
  if (node_filename_stack_index + 1 > node_filename_stack_size)
211
268
    node_filename_stack = xrealloc
215
272
  node_filename_stack_index++;
216
273
}
217
274
 
218
 
void
219
 
pop_node_filename ()
 
275
static void
 
276
pop_node_filename (void)
220
277
{
221
278
  node_filename = node_filename_stack[--node_filename_stack_index];
222
279
}
223
280
 
224
281
/* Save the state of the current input file. */
225
282
void
226
 
pushfile ()
 
283
pushfile (void)
227
284
{
228
285
  FSTACK *newstack = xmalloc (sizeof (FSTACK));
229
286
  newstack->filename = input_filename;
239
296
 
240
297
/* Make the current file globals be what is on top of the file stack. */
241
298
void
242
 
popfile ()
 
299
popfile (void)
243
300
{
244
301
  FSTACK *tos = filestack;
245
302
 
273
330
 
274
331
/* Flush all open files on the file stack. */
275
332
void
276
 
flush_file_stack ()
 
333
flush_file_stack (void)
277
334
{
278
335
  while (filestack)
279
336
    {
288
345
/* Return the index of the first character in the filename
289
346
   which is past all the leading directory characters.  */
290
347
static int
291
 
skip_directory_part (filename)
292
 
     char *filename;
 
348
skip_directory_part (char *filename)
293
349
{
294
350
  int i = strlen (filename) - 1;
295
351
 
303
359
  return i;
304
360
}
305
361
 
306
 
char *
307
 
filename_non_directory (name)
308
 
     char *name;
 
362
static char *
 
363
filename_non_directory (char *name)
309
364
{
310
365
  return xstrdup (name + skip_directory_part (name));
311
366
}
314
369
   filename without the path information, or extensions.
315
370
   This conses up a new string. */
316
371
char *
317
 
filename_part (filename)
318
 
     char *filename;
 
372
filename_part (char *filename)
319
373
{
320
374
  char *basename = filename_non_directory (filename);
321
375
 
322
376
#ifdef REMOVE_OUTPUT_EXTENSIONS
323
377
  /* See if there is an extension to remove.  If so, remove it. */
324
378
  {
325
 
    char *temp;
326
 
 
327
 
    temp = strrchr (basename, '.');
 
379
    char *temp = strrchr (basename, '.');
328
380
    if (temp)
329
381
      *temp = 0;
330
382
  }
334
386
 
335
387
/* Return the pathname part of filename.  This can be NULL. */
336
388
char *
337
 
pathname_part (filename)
338
 
     char *filename;
 
389
pathname_part (char *filename)
339
390
{
340
 
  char *expand_filename ();
341
391
  char *result = NULL;
342
392
  int i;
343
393
 
354
404
  return result;
355
405
}
356
406
 
357
 
/* Return the expansion of FILENAME. */
358
 
char *
359
 
expand_filename (filename, input_name)
360
 
     char *filename, *input_name;
361
 
{
362
 
  int i;
363
 
  char *full_pathname ();
364
 
 
365
 
  if (filename)
366
 
    {
367
 
      filename = full_pathname (filename);
368
 
      if (IS_ABSOLUTE (filename)
369
 
          || (*filename == '.' &&
370
 
              (IS_SLASH (filename[1]) ||
371
 
               (filename[1] == '.' && IS_SLASH (filename[2])))))
372
 
        return filename;
373
 
    }
374
 
  else
375
 
    {
376
 
      filename = filename_non_directory (input_name);
377
 
 
378
 
      if (!*filename)
379
 
        {
380
 
          free (filename);
381
 
          filename = xstrdup ("noname.texi");
382
 
        }
383
 
 
384
 
      for (i = strlen (filename) - 1; i; i--)
385
 
        if (filename[i] == '.')
386
 
          break;
387
 
 
388
 
      if (!i)
389
 
        i = strlen (filename);
390
 
 
391
 
      if (i + 6 > (strlen (filename)))
392
 
        filename = xrealloc (filename, i + 6);
393
 
      strcpy (filename + i, html ? ".html" : ".info");
394
 
      return filename;
395
 
    }
396
 
 
397
 
  if (IS_ABSOLUTE (input_name))
398
 
    {
399
 
      /* Make it so that relative names work. */
400
 
      char *result;
401
 
      
402
 
      i = strlen (input_name) - 1;
403
 
 
404
 
      result = xmalloc (1 + strlen (input_name) + strlen (filename));
405
 
      strcpy (result, input_name);
406
 
 
407
 
      while (!IS_SLASH (result[i]) && i)
408
 
        i--;
409
 
      if (IS_SLASH (result[i]))
410
 
        i++;
411
 
 
412
 
      strcpy (&result[i], filename);
413
 
      free (filename);
414
 
      return result;
415
 
    }
416
 
  return filename;
417
 
}
418
 
 
419
407
/* Return the full path to FILENAME. */
420
 
char *
421
 
full_pathname (filename)
422
 
     char *filename;
 
408
static char *
 
409
full_pathname (char *filename)
423
410
{
424
411
  int initial_character;
425
412
  char *result;
509
496
  return result;
510
497
}
511
498
 
512
 
char *
513
 
output_name_from_input_name (name)
514
 
     char *name;
 
499
/* Return the expansion of FILENAME. */
 
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
      /* Make it so that relative names work. */
 
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)
515
561
{
516
562
  return expand_filename (NULL, name);
517
563
}
523
569
   never be longer than the original, otherwise we couldn't be sure we
524
570
   have enough space in the original string to modify it in place.  */
525
571
char *
526
 
normalize_filename (fname)
527
 
     char *fname;
 
572
normalize_filename (char *fname)
528
573
{
529
574
  int maxlen;
530
575
  char orig[PATH_MAX + 1];
574
619
 
575
620
  return fname;
576
621
}
 
622
 
 
623
/* Delayed writing functions.  A few of the commands
 
624
   needs to be handled at the end, namely @contents,
 
625
   @shortcontents, @printindex and @listoffloats.
 
626
   These functions take care of that.  */
 
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
      /* Cannot register if we don't know what the output file is.  */
 
638
      warning (_("`%s' omitted before output filename"), delayed_command);
 
639
      return;
 
640
    }
 
641
 
 
642
  if (STREQ (current_output_filename, "-"))
 
643
    {
 
644
      /* Do not register a new write if the output file is not seekable.
 
645
         Let the user know about it first, though.  */
 
646
      warning (_("`%s' omitted since writing to stdout"), delayed_command);
 
647
      return;
 
648
    }
 
649
 
 
650
  /* Don't complain if the user is writing /dev/null, since surely they
 
651
     don't care, but don't register the delayed write, either.  */
 
652
  if (FILENAME_CMP (current_output_filename, NULL_DEVICE) == 0
 
653
      || FILENAME_CMP (current_output_filename, ALSO_NULL_DEVICE) == 0)
 
654
    return;
 
655
    
 
656
  /* We need the HTML header in the output,
 
657
     to get a proper output_position.  */
 
658
  if (!executing_string && html)
 
659
    html_output_head ();
 
660
  /* Get output_position updated.  */
 
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
        /* In order to make warnings and errors
 
722
           refer to the correct line number.  */
 
723
        input_filename = temp->input_filename;
 
724
        line_number = temp->calling_line;
 
725
 
 
726
        execute_string ("%s", temp->command);
 
727
        flush_output ();
 
728
 
 
729
        /* Since the output file is modified, following delayed writes
 
730
           need to be updated by this amount.  */
 
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
      /* Done with the buffer.  */
 
742
      free (delayed_buf);
 
743
 
 
744
      /* Update positions in tag table for nodes that are defined after
 
745
         the line this delayed write is registered.  */
 
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
      /* Something similar for the line numbers in all of the defined
 
755
         indices.  */
 
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
      /* Shift remaining delayed positions
 
771
         by the length of this write.  */
 
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
}