Update HACKING for changed doc generation instructions
[geany-mirror.git] / tagmanager / ctags / sort.c
blob275d311800d6c1fba703e62ba3fcb0ef708ee8fe
1 /*
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.
9 */
12 * INCLUDE FILES
14 #include "general.h" /* must always come first */
16 #if defined (HAVE_STDLIB_H)
17 # include <stdlib.h> /* to declare malloc () */
18 #endif
19 #include <string.h>
20 #include <stdio.h>
21 #include <glib.h>
22 #include <glib/gstdio.h>
24 #include "entry.h"
25 #include "main.h"
26 #include "options.h"
27 #include "read.h"
28 #include "sort.h"
30 #ifdef TRAP_MEMORY_CALLS
31 # include "safe_malloc.h"
32 #endif
35 * FUNCTION DEFINITIONS
38 extern void catFile (const char *const name)
40 FILE *const fp = g_fopen (name, "r");
42 if (fp != NULL)
44 int c;
46 while ((c = getc (fp)) != EOF)
47 putchar (c);
48 fflush (stdout);
49 fclose (fp);
53 #ifdef EXTERNAL_SORT
55 #ifdef NON_CONST_PUTENV_PROTOTYPE
56 # define PE_CONST
57 #else
58 # define PE_CONST const
59 #endif
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);
69 int ret = -1;
71 if (cmd != NULL)
73 /* Ensure ASCII value sort order.
75 #ifdef HAVE_SETENV
76 setenv ("LC_COLLATE", "C", 1);
77 setenv ("LC_ALL", "C", 1);
78 sprintf (cmd, "%s %s %s", sortCommand, tagFileName (), tagFileName ());
79 #else
80 # ifdef HAVE_PUTENV
81 putenv (sortOrder1);
82 putenv (sortOrder2);
83 sprintf (cmd, "%s %s %s", sortCommand, tagFileName (), tagFileName ());
84 # else
85 sprintf (cmd, "%s %s %s %s %s", sortOrder1, sortOrder2, sortCommand,
86 tagFileName (), tagFileName ());
87 # endif
88 #endif
89 verbose ("system (\"%s\")\n", cmd);
90 ret = system (cmd);
91 g_free (cmd);
94 if (ret != 0)
95 error (FATAL | PERROR, "cannot sort tag file");
96 else if (toStdout)
97 catFile (tagFileName ());
100 #else
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";
111 if (mio != NULL)
112 mio_free (mio);
113 if (msg == NULL)
114 error (FATAL | PERROR, "%s", cannotSort);
115 else
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)
130 MIO *mio;
131 size_t i;
133 /* Write the sorted lines back into the tag file.
135 if (toStdout)
136 mio = mio_new_fp (stdout, NULL);
137 else
139 mio = mio_new_file_full (tagFileName (), "w", g_fopen, fclose);
140 if (mio == NULL)
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);
152 if (toStdout)
153 fflush (mio_file_get_fp (mio));
154 mio_free (mio);
157 extern void internalSortTags (const boolean toStdout)
159 vString *vLine = vStringNew ();
160 MIO *mio = NULL;
161 const char *line;
162 size_t i;
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 */
171 if (table == NULL)
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);
177 if (mio == NULL)
178 failedSort (mio, NULL);
179 for (i = 0 ; i < numTags && ! mio_eof (mio) ; )
181 line = readLine (vLine, mio);
182 if (line == NULL)
184 if (! mio_eof (mio))
185 failedSort (mio, NULL);
186 break;
188 else if (*line == '\0' || strcmp (line, "\n") == 0)
189 ; /* ignore blank lines */
190 else
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);
199 ++i;
202 numTags = i;
203 mio_free (mio);
204 vStringDelete (vLine);
206 /* Sort the lines.
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)
214 g_free (table [i]);
215 g_free (table);
218 #endif
220 /* vi:set tabstop=8 shiftwidth=4: */