root/trunk/texinfo/texinfo-4.8a-fixes-1.patch

Revision 1821, 20.2 kB (checked in by robert, 1 year ago)

Fix oops... the patch is for 'texinfo-4.8a', not 'texinfo-4.8'

  • texinfo-4.8/doc/texindex.1

    old new  
    1 .\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.34
    2 .TH TEXINDEX "1" "December 2004" "texindex 4.8" "User Commands" 
     1.\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.35
     2.TH TEXINDEX "1" "November 2006" "texindex 4.8.90" "User Commands" 
    33.SH NAME 
    44texindex \- sort Texinfo index files 
    55.SH SYNOPSIS 
     
    1313\fB\-h\fR, \fB\-\-help\fR 
    1414display this help and exit 
    1515.TP 
    16 \fB\-k\fR, \fB\-\-keep\fR 
    17 keep temporary files around after processing 
    18 .TP 
    19 \fB\-\-no\-keep\fR 
    20 do not keep temporary files around after processing (default) 
    21 .TP 
    2216\fB\-o\fR, \fB\-\-output\fR FILE 
    2317send output to FILE 
    2418.TP 
     
    2923general questions and discussion to help\-texinfo@gnu.org. 
    3024Texinfo home page: http://www.gnu.org/software/texinfo/ 
    3125.SH COPYRIGHT 
    32 Copyright \(co 2004 Free Software Foundation, Inc. 
    33 There is NO warranty.  You may redistribute this software 
     26Copyright \(co 2005 Free Software Foundation, Inc. 
     27There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A 
     28PARTICULAR PURPOSE.  You may redistribute copies of GNU texinfo 
    3429under the terms of the GNU General Public License. 
    35 For more information about these matters, see the files named COPYING. 
     30For more information about these matters, see the file named COPYING. 
    3631.SH "SEE ALSO" 
    3732The full documentation for 
    3833.B texindex 
  • texinfo-4.8/util/texindex.c

    old new  
    11/* texindex -- sort TeX index dribble output into an actual index. 
    2    $Id: texindex.c,v 1.11 2004/04/11 17:56:47 karl Exp $ 
     2   $Id: texindex.c,v 1.19 2007/02/22 00:24:19 karl Exp $ 
    33 
    44   Copyright (C) 1987, 1991, 1992, 1996, 1997, 1998, 1999, 2000, 2001, 
    5    2002, 2003, 2004 Free Software Foundation, Inc. 
     5   2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. 
    66 
    77   This program is free software; you can redistribute it and/or modify 
    88   it under the terms of the GNU General Public License as published by 
     
    1616 
    1717   You should have received a copy of the GNU General Public License 
    1818   along with this program; if not, write to the Free Software 
    19    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307. */ 
     19   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301. */ 
    2020 
    2121#include "system.h" 
    2222#include <getopt.h> 
    2323 
    24 static char *program_name = "texindex"; 
     24char *program_name = "texindex"; 
    2525 
    2626#if defined (emacs) 
    2727#  include "../src/config.h" 
     
    3737#define memset(ptr, ignore, count) bzero (ptr, count) 
    3838#endif 
    3939 
    40 char *mktemp (char *); 
    41  
    4240#if !defined (SEEK_SET) 
    4341#  define SEEK_SET 0 
    4442#  define SEEK_CUR 1 
    4543#  define SEEK_END 2 
    4644#endif /* !SEEK_SET */ 
    4745 
    48 struct linebuffer; 
    49  
    5046/* When sorting in core, this structure describes one line 
    5147   and the position and length of its first keyfield.  */ 
    5248struct lineinfo 
     
    9692/* The allocated length of `linearray'. */ 
    9793long nlines; 
    9894 
    99 /* Directory to use for temporary files.  On Unix, it ends with a slash.  */ 
    100 char *tempdir; 
    101  
    102 /* Number of last temporary file.  */ 
    103 int tempcount; 
    104  
    105 /* Number of last temporary file already deleted. 
    106    Temporary files are deleted by `flush_tempfiles' in order of creation.  */ 
    107 int last_deleted_tempcount; 
    108  
    10995/* During in-core sort, this points to the base of the data block 
    11096   which contains all the lines of data.  */ 
    11197char *text_base; 
     
    117103   determine whether we need initials in the sorted form.  */ 
    118104char first_initial; 
    119105 
    120 /* Additional command switches .*/ 
    121  
    122 /* Nonzero means do not delete tempfiles -- for debugging. */ 
    123 int keep_tempfiles; 
    124  
    125106/* Forward declarations of functions in this file. */ 
    126107void decode_command (int argc, char **argv); 
    127108void sort_in_core (char *infile, int total, char *outfile); 
    128 void sort_offline (char *infile, off_t total, char *outfile); 
    129109char **parsefile (char *filename, char **nextline, char *data, long int size); 
    130110char *find_field (struct keyfield *keyfield, char *str, long int *lengthptr); 
    131111char *find_pos (char *str, int words, int chars, int ignore_blanks); 
     
    137117                   long int length1, long int pos1, char *start2, 
    138118                   long int length2, long int pos2); 
    139119int compare_full (const void *, const void *); 
    140 long readline (struct linebuffer *linebuffer, FILE *stream); 
    141 int merge_files (char **infiles, int nfiles, char *outfile); 
    142 int merge_direct (char **infiles, int nfiles, char *outfile); 
    143120void pfatal_with_name (const char *name); 
    144121void fatal (const char *format, const char *arg); 
    145122void error (const char *format, const char *arg); 
    146123void *xmalloc (), *xrealloc (); 
    147 char *concat (char *s1, char *s2); 
    148 void flush_tempfiles (int to_count); 
     124static char *concat3 (const char *, const char *, const char *); 
    149125  
    150 #define MAX_IN_CORE_SORT 500000 
    151  
    152126int 
    153127main (int argc, char **argv) 
    154128{ 
    155129  int i; 
    156130 
    157   tempcount = 0; 
    158   last_deleted_tempcount = 0; 
    159  
    160131#ifdef HAVE_SETLOCALE 
    161132  /* Set locale via LC_ALL.  */ 
    162133  setlocale (LC_ALL, ""); 
     
    220191 
    221192      outfile = outfiles[i]; 
    222193      if (!outfile) 
    223         outfile = concat (infiles[i], "s"); 
     194        outfile = concat3 (infiles[i], "s", ""); 
    224195 
    225196      need_initials = 0; 
    226197      first_initial = '\0'; 
    227198 
    228       if (ptr < MAX_IN_CORE_SORT) 
    229         /* Sort a small amount of data. */ 
    230         sort_in_core (infiles[i], (int)ptr, outfile); 
    231       else 
    232         sort_offline (infiles[i], ptr, outfile); 
     199      if (ptr != (int)ptr) 
     200        { 
     201          fprintf (stderr, "%s: %s: file too large\n", program_name, 
     202                   infiles[i]); 
     203          xexit (1); 
     204        } 
     205      sort_in_core (infiles[i], (int)ptr, outfile); 
    233206    } 
    234207 
    235   flush_tempfiles (tempcount); 
    236208  xexit (0); 
    237209  return 0; /* Avoid bogus warnings.  */ 
    238210} 
     
    250222TEXINDEX_OPTION texindex_options[] = { 
    251223  { "--help", "-h", (int *)NULL, 0, (char *)NULL, 
    252224      N_("display this help and exit") }, 
    253   { "--keep", "-k", &keep_tempfiles, 1, (char *)NULL, 
    254       N_("keep temporary files around after processing") }, 
    255   { "--no-keep", 0, &keep_tempfiles, 0, (char *)NULL, 
    256       N_("do not keep temporary files around after processing (default)") }, 
    257225  { "--output", "-o", (int *)NULL, 0, "FILE", 
    258226      N_("send output to FILE") }, 
    259227  { "--version", (char *)NULL, (int *)NULL, 0, (char *)NULL, 
     
    308276  char **ip; 
    309277  char **op; 
    310278 
    311   /* Store default values into parameter variables. */ 
    312  
    313   tempdir = getenv ("TMPDIR"); 
    314   if (tempdir == NULL) 
    315     tempdir = getenv ("TEMP"); 
    316   if (tempdir == NULL) 
    317     tempdir = getenv ("TMP"); 
    318   if (tempdir == NULL) 
    319     tempdir = DEFAULT_TMPDIR; 
    320   else 
    321     tempdir = concat (tempdir, "/"); 
    322  
    323   keep_tempfiles = 0; 
    324  
    325279  /* Allocate ARGC input files, which must be enough.  */ 
    326280 
    327281  infiles = (char **) xmalloc (argc * sizeof (char *)); 
     
    339293            { 
    340294              printf ("texindex (GNU %s) %s\n", PACKAGE, VERSION); 
    341295              puts (""); 
    342               puts ("Copyright (C) 2004 Free Software Foundation, Inc."); 
    343               printf (_("There is NO warranty.  You may redistribute this software\n\ 
     296      printf (_("\ 
     297Copyright (C) %s Free Software Foundation, Inc.\n\ 
     298There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n\ 
     299PARTICULAR PURPOSE.  You may redistribute copies of GNU %s\n\ 
    344300under the terms of the GNU General Public License.\n\ 
    345 For more information about these matters, see the files named COPYING.\n")); 
     301For more information about these matters, see the file named COPYING.\n"), 
     302              "2005", PACKAGE); 
    346303              xexit (0); 
    347304            } 
    348305          else if ((strcmp (arg, "--keep") == 0) || 
    349306                   (strcmp (arg, "-k") == 0)) 
    350307            { 
    351               keep_tempfiles = 1; 
     308              /* Ignore, for backward compatibility */ 
    352309            } 
    353310          else if ((strcmp (arg, "--help") == 0) || 
    354311                   (strcmp (arg, "-h") == 0)) 
     
    384341    usage (1); 
    385342} 
    386343  
    387 /* Return a name for temporary file COUNT. */ 
    388  
    389 static char * 
    390 maketempname (int count) 
    391 { 
    392   static char *tempbase = NULL; 
    393   char tempsuffix[10]; 
    394  
    395   if (!tempbase) 
    396     { 
    397       int fd; 
    398       tempbase = concat (tempdir, "txidxXXXXXX"); 
    399  
    400       fd = mkstemp (tempbase); 
    401       if (fd == -1) 
    402         pfatal_with_name (tempbase); 
    403     } 
    404  
    405   sprintf (tempsuffix, ".%d", count); 
    406   return concat (tempbase, tempsuffix); 
    407 } 
    408  
    409  
    410 /* Delete all temporary files up to TO_COUNT. */ 
    411  
    412 void 
    413 flush_tempfiles (int to_count) 
    414 { 
    415   if (keep_tempfiles) 
    416     return; 
    417   while (last_deleted_tempcount < to_count) 
    418     unlink (maketempname (++last_deleted_tempcount)); 
    419 } 
    420  
    421   
    422344/* Compare LINE1 and LINE2 according to the specified set of keyfields. */ 
    423345 
    424346int 
     
    801723    } 
    802724} 
    803725  
    804 /* A `struct linebuffer' is a structure which holds a line of text. 
    805    `readline' reads a line from a stream into a linebuffer 
    806    and works regardless of the length of the line.  */ 
    807  
    808 struct linebuffer 
    809 { 
    810   long size; 
    811   char *buffer; 
    812 }; 
    813  
    814 /* Initialize LINEBUFFER for use. */ 
    815  
    816 void 
    817 initbuffer (struct linebuffer *linebuffer) 
    818 { 
    819   linebuffer->size = 200; 
    820   linebuffer->buffer = (char *) xmalloc (200); 
    821 } 
    822  
    823 /* Read a line of text from STREAM into LINEBUFFER. 
    824    Return the length of the line.  */ 
    825  
    826 long 
    827 readline (struct linebuffer *linebuffer, FILE *stream) 
    828 { 
    829   char *buffer = linebuffer->buffer; 
    830   char *p = linebuffer->buffer; 
    831   char *end = p + linebuffer->size; 
    832  
    833   while (1) 
    834     { 
    835       int c = getc (stream); 
    836       if (p == end) 
    837         { 
    838           buffer = (char *) xrealloc (buffer, linebuffer->size *= 2); 
    839           p += buffer - linebuffer->buffer; 
    840           end += buffer - linebuffer->buffer; 
    841           linebuffer->buffer = buffer; 
    842         } 
    843       if (c < 0 || c == '\n') 
    844         { 
    845           *p = 0; 
    846           break; 
    847         } 
    848       *p++ = c; 
    849     } 
    850  
    851   return p - buffer; 
    852 } 
    853   
    854 /* Sort an input file too big to sort in core.  */ 
    855  
    856 void 
    857 sort_offline (char *infile, off_t total, char *outfile) 
    858 { 
    859   /* More than enough. */ 
    860   int ntemps = 2 * (total + MAX_IN_CORE_SORT - 1) / MAX_IN_CORE_SORT; 
    861   char **tempfiles = (char **) xmalloc (ntemps * sizeof (char *)); 
    862   FILE *istream = fopen (infile, "r"); 
    863   int i; 
    864   struct linebuffer lb; 
    865   long linelength; 
    866   int failure = 0; 
    867  
    868   initbuffer (&lb); 
    869  
    870   /* Read in one line of input data.  */ 
    871  
    872   linelength = readline (&lb, istream); 
    873  
    874   if (lb.buffer[0] != '\\' && lb.buffer[0] != '@') 
    875     { 
    876       error (_("%s: not a texinfo index file"), infile); 
    877       return; 
    878     } 
    879  
    880   /* Split up the input into `ntemps' temporary files, or maybe fewer, 
    881      and put the new files' names into `tempfiles' */ 
    882  
    883   for (i = 0; i < ntemps; i++) 
    884     { 
    885       char *outname = maketempname (++tempcount); 
    886       FILE *ostream = fopen (outname, "w"); 
    887       long tempsize = 0; 
    888  
    889       if (!ostream) 
    890         pfatal_with_name (outname); 
    891       tempfiles[i] = outname; 
    892  
    893       /* Copy lines into this temp file as long as it does not make file 
    894          "too big" or until there are no more lines.  */ 
    895  
    896       while (tempsize + linelength + 1 <= MAX_IN_CORE_SORT) 
    897         { 
    898           tempsize += linelength + 1; 
    899           fputs (lb.buffer, ostream); 
    900           putc ('\n', ostream); 
    901  
    902           /* Read another line of input data.  */ 
    903  
    904           linelength = readline (&lb, istream); 
    905           if (!linelength && feof (istream)) 
    906             break; 
    907  
    908           if (lb.buffer[0] != '\\' && lb.buffer[0] != '@') 
    909             { 
    910               error (_("%s: not a texinfo index file"), infile); 
    911               failure = 1; 
    912               goto fail; 
    913             } 
    914         } 
    915       fclose (ostream); 
    916       if (feof (istream)) 
    917         break; 
    918     } 
    919  
    920   free (lb.buffer); 
    921  
    922 fail: 
    923   /* Record number of temp files we actually needed.  */ 
    924  
    925   ntemps = i; 
    926  
    927   /* Sort each tempfile into another tempfile. 
    928     Delete the first set of tempfiles and put the names of the second 
    929     into `tempfiles'. */ 
    930  
    931   for (i = 0; i < ntemps; i++) 
    932     { 
    933       char *newtemp = maketempname (++tempcount); 
    934       sort_in_core (tempfiles[i], MAX_IN_CORE_SORT, newtemp); 
    935       if (!keep_tempfiles) 
    936         unlink (tempfiles[i]); 
    937       tempfiles[i] = newtemp; 
    938     } 
    939  
    940   if (failure) 
    941     return; 
    942  
    943   /* Merge the tempfiles together and indexify. */ 
    944  
    945   merge_files (tempfiles, ntemps, outfile); 
    946 } 
    947   
    948726/* Sort INFILE, whose size is TOTAL, 
    949727   assuming that is small enough to be done in-core, 
    950728   then indexify it and send the output to OUTFILE (or to stdout).  */ 
     
    13481126 
    13491127  for (next_line = linearray; next_line != stop_line; next_line++) 
    13501128    { 
    1351       /* If -u was specified, output the line only if distinct from 
    1352          previous one.  */ 
     1129      /* Output the line only if distinct from previous one.  */ 
    13531130      if (next_line == linearray 
    13541131      /* Compare previous line with this one, using only the 
    13551132         explicitly specd keyfields. */ 
     
    13691146  finish_index (ostream); 
    13701147} 
    13711148  
    1372 /* Assume (and optionally verify) that each input file is sorted; 
    1373    merge them and output the result. 
    1374    Returns nonzero if any input file fails to be sorted. 
    1375  
    1376    This is the high-level interface that can handle an unlimited 
    1377    number of files.  */ 
    1378  
    1379 #define MAX_DIRECT_MERGE 10 
    1380  
    1381 int 
    1382 merge_files (char **infiles, int nfiles, char *outfile) 
    1383 { 
    1384   char **tempfiles; 
    1385   int ntemps; 
    1386   int i; 
    1387   int value = 0; 
    1388   int start_tempcount = tempcount; 
    1389  
    1390   if (nfiles <= MAX_DIRECT_MERGE) 
    1391     return merge_direct (infiles, nfiles, outfile); 
    1392  
    1393   /* Merge groups of MAX_DIRECT_MERGE input files at a time, 
    1394      making a temporary file to hold each group's result.  */ 
    1395  
    1396   ntemps = (nfiles + MAX_DIRECT_MERGE - 1) / MAX_DIRECT_MERGE; 
    1397   tempfiles = (char **) xmalloc (ntemps * sizeof (char *)); 
    1398   for (i = 0; i < ntemps; i++) 
    1399     { 
    1400       int nf = MAX_DIRECT_MERGE; 
    1401       if (i + 1 == ntemps) 
    1402         nf = nfiles - i * MAX_DIRECT_MERGE; 
    1403       tempfiles[i] = maketempname (++tempcount); 
    1404       value |= merge_direct (&infiles[i * MAX_DIRECT_MERGE], nf, tempfiles[i]); 
    1405     } 
    1406  
    1407   /* All temporary files that existed before are no longer needed 
    1408      since their contents have been merged into our new tempfiles. 
    1409      So delete them.  */ 
    1410   flush_tempfiles (start_tempcount); 
    1411  
    1412   /* Now merge the temporary files we created.  */ 
    1413  
    1414   merge_files (tempfiles, ntemps, outfile); 
    1415  
    1416   free (tempfiles); 
    1417  
    1418   return value; 
    1419 } 
    1420   
    1421 /* Assume (and optionally verify) that each input file is sorted; 
    1422    merge them and output the result. 
    1423    Returns nonzero if any input file fails to be sorted. 
    1424  
    1425    This version of merging will not work if the number of 
    1426    input files gets too high.  Higher level functions 
    1427    use it only with a bounded number of input files.  */ 
    1428  
    1429 int 
    1430 merge_direct (char **infiles, int nfiles, char *outfile) 
    1431 { 
    1432   struct linebuffer *lb1, *lb2; 
    1433   struct linebuffer **thisline, **prevline; 
    1434   FILE **streams; 
    1435   int i; 
    1436   int nleft; 
    1437   int lossage = 0; 
    1438   int *file_lossage; 
    1439   struct linebuffer *prev_out = 0; 
    1440   FILE *ostream = stdout; 
    1441  
    1442   if (outfile) 
    1443     { 
    1444       ostream = fopen (outfile, "w"); 
    1445     } 
    1446   if (!ostream) 
    1447     pfatal_with_name (outfile); 
    1448  
    1449   init_index (); 
    1450  
    1451   if (nfiles == 0) 
    1452     { 
    1453       if (outfile) 
    1454         fclose (ostream); 
    1455       return 0; 
    1456     } 
    1457  
    1458   /* For each file, make two line buffers.  Also, for each file, there 
    1459      is an element of `thisline' which points at any time to one of the 
    1460      file's two buffers, and an element of `prevline' which points to 
    1461      the other buffer.  `thisline' is supposed to point to the next 
    1462      available line from the file, while `prevline' holds the last file 
    1463      line used, which is remembered so that we can verify that the file 
    1464      is properly sorted. */ 
    1465  
    1466   /* lb1 and lb2 contain one buffer each per file. */ 
    1467   lb1 = (struct linebuffer *) xmalloc (nfiles * sizeof (struct linebuffer)); 
    1468   lb2 = (struct linebuffer *) xmalloc (nfiles * sizeof (struct linebuffer)); 
    1469  
    1470   /* thisline[i] points to the linebuffer holding the next available 
    1471      line in file i, or is zero if there are no lines left in that file.  */ 
    1472   thisline = (struct linebuffer **) 
    1473     xmalloc (nfiles * sizeof (struct linebuffer *)); 
    1474   /* prevline[i] points to the linebuffer holding the last used line 
    1475      from file i.  This is just for verifying that file i is properly 
    1476      sorted.  */ 
    1477   prevline = (struct linebuffer **) 
    1478     xmalloc (nfiles * sizeof (struct linebuffer *)); 
    1479   /* streams[i] holds the input stream for file i.  */ 
    1480   streams = (FILE **) xmalloc (nfiles * sizeof (FILE *)); 
    1481   /* file_lossage[i] is nonzero if we already know file i is not 
    1482      properly sorted.  */ 
    1483   file_lossage = (int *) xmalloc (nfiles * sizeof (int)); 
    1484  
    1485   /* Allocate and initialize all that storage. */ 
    1486  
    1487   for (i = 0; i < nfiles; i++) 
    1488     { 
    1489       initbuffer (&lb1[i]); 
    1490       initbuffer (&lb2[i]); 
    1491       thisline[i] = &lb1[i]; 
    1492       prevline[i] = &lb2[i]; 
    1493       file_lossage[i] = 0; 
    1494       streams[i] = fopen (infiles[i], "r"); 
    1495       if (!streams[i]) 
    1496         pfatal_with_name (infiles[i]); 
    1497  
    1498       readline (thisline[i], streams[i]); 
    1499     } 
    1500  
    1501   /* Keep count of number of files not at eof. */ 
    1502   nleft = nfiles; 
    1503  
    1504   while (nleft) 
    1505     { 
    1506       struct linebuffer *best = 0; 
    1507       struct linebuffer *exch; 
    1508       int bestfile = -1; 
    1509       int i; 
    1510  
    1511       /* Look at the next avail line of each file; choose the least one.  */ 
    1512  
    1513       for (i = 0; i < nfiles; i++) 
    1514         { 
    1515           if (thisline[i] && 
    1516               (!best || 
    1517                0 < compare_general (best->buffer, thisline[i]->buffer, 
    1518                                  (long) bestfile, (long) i, num_keyfields))) 
    1519             { 
    1520               best = thisline[i]; 
    1521               bestfile = i; 
    1522             } 
    1523         } 
    1524  
    1525       /* Output that line, unless it matches the previous one and we 
    1526          don't want duplicates. */ 
    1527  
    1528       if (!(prev_out && 
    1529             !compare_general (prev_out->buffer, 
    1530                               best->buffer, 0L, 1L, num_keyfields - 1))) 
    1531         indexify (best->buffer, ostream); 
    1532       prev_out = best; 
    1533  
    1534       /* Now make the line the previous of its file, and fetch a new 
    1535          line from that file.  */ 
    1536  
    1537       exch = prevline[bestfile]; 
    1538       prevline[bestfile] = thisline[bestfile]; 
    1539       thisline[bestfile] = exch; 
    1540  
    1541       while (1) 
    1542         { 
    1543           /* If the file has no more, mark it empty. */ 
    1544  
    1545           if (feof (streams[bestfile])) 
    1546             { 
    1547               thisline[bestfile] = 0; 
    1548               /* Update the number of files still not empty. */ 
    1549               nleft--; 
    1550               break; 
    1551             } 
    1552           readline (thisline[bestfile], streams[bestfile]); 
    1553           if (thisline[bestfile]->buffer[0] || !feof (streams[bestfile])) 
    1554             break; 
    1555         } 
    1556     } 
    1557  
    1558   finish_index (ostream); 
    1559  
    1560   /* Free all storage and close all input streams. */ 
    1561  
    1562   for (i = 0; i < nfiles; i++) 
    1563     { 
    1564       fclose (streams[i]); 
    1565       free (lb1[i].buffer); 
    1566       free (lb2[i].buffer); 
    1567     } 
    1568   free (file_lossage); 
    1569   free (lb1); 
    1570   free (lb2); 
    1571   free (thisline); 
    1572   free (prevline); 
    1573   free (streams); 
    1574  
    1575   if (outfile) 
    1576     fclose (ostream); 
    1577  
    1578   return lossage; 
    1579 } 
    1580   
    15811149/* Print error message and exit.  */ 
    15821150 
    15831151void 
     
    16121180} 
    16131181 
    16141182  
    1615 /* Return a newly-allocated string concatenating S1 and S2.  */ 
     1183/* Return a newly-allocated string concatenating S1, S2, and S3.  */ 
    16161184 
    1617 char * 
    1618 concat (char *s1, char *s2
     1185static char * 
     1186concat3 (const char *s1, const char *s2, const char *s3
    16191187{ 
    1620   int len1 = strlen (s1), len2 = strlen (s2)
    1621   char *result = (char *) xmalloc (len1 + len2 + 1); 
     1188  int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3)
     1189  char *result = (char *) xmalloc (len1 + len2 + len3 + 1); 
    16221190 
    16231191  strcpy (result, s1); 
    16241192  strcpy (result + len1, s2); 
    1625   *(result + len1 + len2) = 0; 
     1193  strcpy (result + len1 + len2, s3); 
     1194  *(result + len1 + len2 + len3) = 0; 
    16261195 
    16271196  return result; 
    16281197} 
Note: See TracBrowser for help on using the browser.