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_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 (FILE *const fp
, 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.
139 fp
= g_fopen (tagFileName (), "w");
141 failedSort (fp
, 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 (fputs (table
[i
], fp
) == EOF
)
150 failedSort (fp
, NULL
);
158 extern void internalSortTags (const boolean toStdout
)
160 vString
*vLine
= vStringNew ();
165 /* Allocate a table of line pointers to be sorted.
167 size_t numTags
= TagFile
.numTags
.added
+ TagFile
.numTags
.prev
;
168 const size_t tableSize
= numTags
* sizeof (char *);
169 char **const table
= (char **) g_malloc (tableSize
); /* line pointers */
170 DebugStatement ( size_t mallocSize
= tableSize
; ) /* cumulative total */
173 failedSort (fp
, "out of memory");
175 /* Open the tag file and place its lines into allocated buffers.
177 fp
= g_fopen (tagFileName (), "r");
179 failedSort (fp
, NULL
);
180 for (i
= 0 ; i
< numTags
&& ! feof (fp
) ; )
182 line
= readLine (vLine
, fp
);
186 failedSort (fp
, NULL
);
189 else if (*line
== '\0' || strcmp (line
, "\n") == 0)
190 ; /* ignore blank lines */
193 const size_t stringSize
= strlen (line
) + 1;
195 table
[i
] = (char *) g_malloc (stringSize
);
196 if (table
[i
] == NULL
)
197 failedSort (fp
, "out of memory");
198 DebugStatement ( mallocSize
+= stringSize
; )
199 strcpy (table
[i
], line
);
205 vStringDelete (vLine
);
209 qsort (table
, numTags
, sizeof (*table
), compareTags
);
211 writeSortedTags (table
, numTags
, toStdout
);
213 PrintStatus (("sort memory: %ld bytes\n", (long) mallocSize
));
214 for (i
= 0 ; i
< numTags
; ++i
)
221 /* vi:set tabstop=8 shiftwidth=4: */