3 * Copyright (c) 1996-2001, Darren Hiebert
5 * This source code is released for free distribution under the terms of the
6 * GNU General Public License.
8 * This module contains functions to sort the tag entries.
14 #include "general.h" /* must always come first */
16 #if defined (HAVE_STDLIB_H)
17 # include <stdlib.h> /* to declare malloc () */
22 #include <glib/gstdio.h>
30 #ifdef TRAP_MEMORY_CALLS
31 # include "safe_malloc.h"
35 * FUNCTION DEFINITIONS
38 extern void catFile (const char *const name
)
40 FILE *const fp
= g_fopen (name
, "r");
46 while ((c
= getc (fp
)) != EOF
)
55 #ifdef NON_CONST_PUTENV_PROTOTYPE
58 # define PE_CONST const
61 extern void externalSortTags (const boolean toStdout
)
63 const char *const sortCommand
= "sort -u -o";
64 PE_CONST
char *const sortOrder1
= "LC_COLLATE=C";
65 PE_CONST
char *const sortOrder2
= "LC_ALL=C";
66 const size_t length
= 4 + strlen (sortOrder1
) + strlen (sortOrder2
) +
67 strlen (sortCommand
) + (2 * strlen (tagFileName ()));
68 char *const cmd
= (char *) g_try_malloc (length
+ 1);
73 /* Ensure ASCII value sort order.
76 setenv ("LC_COLLATE", "C", 1);
77 setenv ("LC_ALL", "C", 1);
78 sprintf (cmd
, "%s %s %s", sortCommand
, tagFileName (), tagFileName ());
83 sprintf (cmd
, "%s %s %s", sortCommand
, tagFileName (), tagFileName ());
85 sprintf (cmd
, "%s %s %s %s %s", sortOrder1
, sortOrder2
, sortCommand
,
86 tagFileName (), tagFileName ());
89 verbose ("system (\"%s\")\n", cmd
);
95 error (FATAL
| PERROR
, "cannot sort tag file");
97 catFile (tagFileName ());
103 * These functions provide a basic internal sort. No great memory
104 * optimization is performed (e.g. recursive subdivided sorts),
105 * so have lots of memory if you have large tag files.
108 static void failedSort (MIO
*const mio
, const char* msg
)
110 const char* const cannotSort
= "cannot sort tag file";
114 error (FATAL
| PERROR
, "%s", cannotSort
);
116 error (FATAL
, "%s: %s", msg
, cannotSort
);
119 static int compareTags (const void *const one
, const void *const two
)
121 const char *const line1
= *(const char* const*) one
;
122 const char *const line2
= *(const char* const*) two
;
124 return strcmp (line1
, line2
);
127 static void writeSortedTags (char **const table
, const size_t numTags
,
128 const boolean toStdout
)
133 /* Write the sorted lines back into the tag file.
136 mio
= mio_new_fp (stdout
, NULL
);
139 mio
= mio_new_file_full (tagFileName (), "w", g_fopen
, fclose
);
141 failedSort (mio
, NULL
);
143 for (i
= 0 ; i
< numTags
; ++i
)
145 /* Here we filter out identical tag *lines* (including search
146 * pattern) if this is not an xref file.
148 if (i
== 0 || Option
.xref
|| strcmp (table
[i
], table
[i
-1]) != 0)
149 if (mio_puts (mio
, table
[i
]) == EOF
)
150 failedSort (mio
, NULL
);
153 fflush (mio_file_get_fp (mio
));
157 extern void internalSortTags (const boolean toStdout
)
159 vString
*vLine
= vStringNew ();
164 /* Allocate a table of line pointers to be sorted.
166 size_t numTags
= TagFile
.numTags
.added
+ TagFile
.numTags
.prev
;
167 const size_t tableSize
= numTags
* sizeof (char *);
168 char **const table
= (char **) g_try_malloc (tableSize
); /* line pointers */
169 DebugStatement ( size_t mallocSize
= tableSize
; ) /* cumulative total */
172 failedSort (mio
, "out of memory");
174 /* Open the tag file and place its lines into allocated buffers.
176 mio
= mio_new_file_full (tagFileName (), "r", g_fopen
, fclose
);
178 failedSort (mio
, NULL
);
179 for (i
= 0 ; i
< numTags
&& ! mio_eof (mio
) ; )
181 line
= readLine (vLine
, mio
);
185 failedSort (mio
, NULL
);
188 else if (*line
== '\0' || strcmp (line
, "\n") == 0)
189 ; /* ignore blank lines */
192 const size_t stringSize
= strlen (line
) + 1;
194 table
[i
] = (char *) g_try_malloc (stringSize
);
195 if (table
[i
] == NULL
)
196 failedSort (mio
, "out of memory");
197 DebugStatement ( mallocSize
+= stringSize
; )
198 strcpy (table
[i
], line
);
204 vStringDelete (vLine
);
208 qsort (table
, numTags
, sizeof (*table
), compareTags
);
210 writeSortedTags (table
, numTags
, toStdout
);
212 PrintStatus (("sort memory: %ld bytes\n", (long) mallocSize
));
213 for (i
= 0 ; i
< numTags
; ++i
)
220 /* vi:set tabstop=8 shiftwidth=4: */