geany  1.38
About: Geany is a text editor (using GTK2) with basic features of an integrated development environment (syntax highlighting, code folding, symbol name auto-completion, ...). F: office T: editor programming GTK+ IDE
  Fossies Dox: geany-1.38.tar.bz2  ("unofficial" and yet experimental doxygen-generated source code documentation)  

sort.c
Go to the documentation of this file.
1/*
2* Copyright (c) 1996-2002, Darren Hiebert
3*
4* This source code is released for free distribution under the terms of the
5* GNU General Public License version 2 or (at your option) any later version.
6*
7* This module contains functions to sort the tag entries.
8*/
9
10/*
11* INCLUDE FILES
12*/
13#include "general.h" /* must always come first */
14
15#if defined (HAVE_IO_H)
16# include <io.h>
17#endif
18#include <stdlib.h> /* to declare malloc () */
19#if defined (HAVE_UNISTD_H)
20# include <unistd.h>
21#endif
22#include <string.h>
23#include <stdio.h>
24
25#include "debug.h"
26#include "entry_p.h"
27#include "options_p.h"
28#include "read.h"
29#include "routines.h"
30#include "sort_p.h"
31
32/*
33* FUNCTION DEFINITIONS
34*/
35
36extern void catFile (MIO *mio)
37{
38 if (mio != NULL)
39 {
40 int c;
41 mio_seek (mio, 0, SEEK_SET);
42 while ((c = mio_getc (mio)) != EOF)
43 putchar (c);
44 fflush (stdout);
45 }
46}
47
48#ifdef EXTERNAL_SORT
49
50#ifdef NON_CONST_PUTENV_PROTOTYPE
51# define PE_CONST
52#else
53# define PE_CONST const
54#endif
55
56/*
57 Output file name should not be evaluated in system(3) function.
58 The name must be used as is. Quotations are required to block the
59 evaluation.
60
61 Normal single-quotes are used to quote a cstring:
62 a => 'a'
63 " => '"'
64
65 If a single-quote is included in the cstring, use double quotes for quoting it.
66 ' => ''"'"''
67*/
68static void appendCstringWithQuotes (vString *dest, const char* cstr)
69{
70#ifdef WIN32
71 vStringCatS (dest, cstr);
72#else
73 vStringPut (dest, '\'');
74 for (const char *o = cstr; *o; o++)
75 {
76 if (*o == '\'')
77 vStringCatS (dest, "'\"'\"'");
78 else
79 vStringPut (dest, *o);
80 }
81 vStringPut (dest, '\'');
82#endif
83}
84
85extern void externalSortTags (const bool toStdout, MIO *tagFile)
86{
87 const char *const sortNormalCommand = "sort -u";
88 const char *const sortFoldedCommand = "sort -u -f";
89 const char *sortCommand =
90 Option.sorted == SO_FOLDSORTED ? sortFoldedCommand : sortNormalCommand;
91# ifndef HAVE_SETENV
92 PE_CONST char *const sortOrder1 = "LC_COLLATE=C";
93 PE_CONST char *const sortOrder2 = "LC_ALL=C";
94# endif
95 vString *cmd = vStringNew ();
96 int ret = -1;
97
98 if (cmd != NULL)
99 {
100 /* Ensure ASCII value sort order.
101 */
102#if defined (HAVE_SETENV) || defined (HAVE_PUTENV)
103# ifdef HAVE_SETENV
104 setenv ("LC_COLLATE", "C", 1);
105 setenv ("LC_ALL", "C", 1);
106# else
107 putenv (sortOrder1);
108 putenv (sortOrder2);
109# endif
110 vStringCatS (cmd, sortCommand);
111 if (! toStdout)
112 {
113 vStringCatS (cmd, " -o ");
114 appendCstringWithQuotes (cmd, tagFileName ());
115 vStringPut (cmd, ' ');
116 appendCstringWithQuotes (cmd, tagFileName ());
117 }
118#else
119 vStringCatS (cmd, sortOrder1);
120 vStringPut (cmd, ' ');
121 vStringCatS (cmd, sortOrder2);
122 vStringPut (cmd, ' ');
123 vStringCatS (cmd, sortCommand);
124 if (! toStdout)
125 {
126 vStringCats (cmd, " -o ");
127 appendCstringWithQuotes (cmd, tagFileName ());
128 vStringPut (cmd, ' ');
129 appendCstringWithQuotes (cmd, tagFileName ());
130 }
131#endif
132 verbose ("system (\"%s\")\n", vStringValue (cmd));
133 if (toStdout)
134 {
135 const int fdstdin = 0;
136 int fdsave;
137
138 fdsave = dup (fdstdin);
139 if (fdsave < 0)
140 error (FATAL | PERROR, "cannot save stdin fd");
141 if (dup2 (fileno (mio_file_get_fp (tagFile)), fdstdin) < 0)
142 error (FATAL | PERROR, "cannot redirect stdin");
143 if (lseek (fdstdin, 0, SEEK_SET) != 0)
144 error (FATAL | PERROR, "cannot rewind tag file");
145 ret = system (vStringValue (cmd));
146 if (dup2 (fdsave, fdstdin) < 0)
147 error (FATAL | PERROR, "cannot restore stdin fd");
148 close (fdsave);
149 }
150 else
151 ret = system (vStringValue (cmd));
152 vStringDelete (cmd);
153 }
154 if (ret != 0)
155 error (FATAL | PERROR, "cannot sort tag file");
156}
157
158#else
159
160/*
161 * These functions provide a basic internal sort. No great memory
162 * optimization is performed (e.g. recursive subdivided sorts),
163 * so have lots of memory if you have large tag files.
164 */
165
166extern void failedSort (MIO *const mio, const char* msg)
167{
168 const char* const cannotSort = "cannot sort tag file";
169 if (mio != NULL)
170 mio_unref (mio);
171 if (msg == NULL)
172 error (FATAL | PERROR, "%s", cannotSort);
173 else
174 error (FATAL, "%s: %s", msg, cannotSort);
175}
176
177static int compareTagsFolded(const void *const one, const void *const two)
178{
179 const char *const line1 = *(const char* const*) one;
180 const char *const line2 = *(const char* const*) two;
181
182 return struppercmp (line1, line2);
183}
184
185static int compareTags (const void *const one, const void *const two)
186{
187 const char *const line1 = *(const char* const*) one;
188 const char *const line2 = *(const char* const*) two;
189
190 return strcmp (line1, line2);
191}
192
193static void writeSortedTags (
194 char **const table, const size_t numTags, const bool toStdout, bool newlineReplaced)
195{
196 MIO *mio;
197 size_t i;
198
199 /* Write the sorted lines back into the tag file.
200 */
201 if (toStdout)
202 mio = mio_new_fp (stdout, NULL);
203 else
204 {
205 mio = mio_new_file (tagFileName (), "w");
206 if (mio == NULL)
207 failedSort (mio, NULL);
208 }
209 for (i = 0 ; i < numTags ; ++i)
210 {
211 /* Here we filter out identical tag *lines* (including search
212 * pattern) if this is not an xref file.
213 */
214 if (i == 0 || Option.xref || strcmp (table [i], table [i-1]) != 0)
215 {
216 if (mio_puts (mio, table [i]) == EOF)
217 failedSort (mio, NULL);
218 else if (newlineReplaced)
219 mio_putc (mio, '\n');
220 }
221 }
222 if (toStdout)
223 mio_flush (mio);
224 mio_unref (mio);
225}
226
227extern void internalSortTags (const bool toStdout, MIO* mio, size_t numTags)
228{
229 vString *vLine = vStringNew ();
230 const char *line;
231 size_t i;
232 int (*cmpFunc)(const void *, const void *);
233 bool newlineReplaced = false;
234
235 /* Allocate a table of line pointers to be sorted.
236 */
237 const size_t tableSize = numTags * sizeof (char *);
238 char **table = (char **) malloc (tableSize); /* line pointers */
239 DebugStatement ( size_t mallocSize = tableSize; ) /* cumulative total */
240
241
243 if (table == NULL)
244 failedSort (mio, "out of memory");
245
246 for (i = 0 ; i < numTags && ! mio_eof (mio) ; )
247 {
248 line = readLineRaw (vLine, mio);
249 if (line == NULL)
250 {
251 if (! mio_eof (mio))
252 failedSort (mio, NULL);
253 break;
254 }
255 else if (*line == '\0' || strcmp (line, "\n") == 0)
256 ; /* ignore blank lines */
257 else
258 {
259 const size_t stringSize = strlen (line) + 1;
260
261 table [i] = (char *) malloc (stringSize);
262 if (table [i] == NULL)
263 failedSort (mio, "out of memory");
264 DebugStatement ( mallocSize += stringSize; )
265 strcpy (table [i], line);
266 if (table[i][stringSize - 2] == '\n')
267 {
268 table[i][stringSize - 2] = '\0';
269 newlineReplaced = true;
270 }
271 ++i;
272 }
273 }
274 numTags = i;
275 vStringDelete (vLine);
276
277 /* Sort the lines.
278 */
279 qsort (table, numTags, sizeof (*table), cmpFunc);
280
281 writeSortedTags (table, numTags, toStdout, newlineReplaced);
282
283 PrintStatus (("sort memory: %ld bytes\n", (long) mallocSize));
284 for (i = 0 ; i < numTags ; ++i)
285 free (table [i]);
286 free (table);
287}
288
289#endif
#define DebugStatement(x)
Definition: debug.h:45
#define PrintStatus(x)
Definition: debug.h:46
const char * tagFileName(void)
Definition: entry.c:149
void error(const errorSelection selection, const char *const format,...)
Definition: error.c:53
vString * line
Definition: geany_cobol.c:133
MIO * mio_new_fp(FILE *fp, MIOFCloseFunc close_func)
mio_new_fp: @fp: An opened #FILE object @close_func: (allow-none): Function used to close @fp when th...
Definition: mio.c:259
int mio_getc(MIO *mio)
mio_getc: @mio: A MIO object
Definition: mio.c:884
MIO * mio_new_file(const char *filename, const char *mode)
mio_new_file: @filename: Filename to open, same as the fopen()'s first argument @mode: Mode in which ...
Definition: mio.c:234
int mio_seek(MIO *mio, long offset, int whence)
mio_seek: @mio: A MIO object @offset: Offset of the new place, from @whence @whence: Move origin.
Definition: mio.c:1101
int mio_eof(MIO *mio)
mio_eof: @mio: A MIO object
Definition: mio.c:1052
int mio_flush(MIO *mio)
mio_flush: @mio: A MIO object
Definition: mio.c:1335
FILE * mio_file_get_fp(MIO *mio)
mio_file_get_fp: @mio: A MIO object
Definition: mio.c:432
int mio_puts(MIO *mio, const char *s)
mio_puts: @mio: A MIO object @s: The string to write
Definition: mio.c:762
int mio_putc(MIO *mio, int c)
mio_putc: @mio: A MIO object : The character to write
Definition: mio.c:729
int mio_unref(MIO *mio)
mio_unref: @mio: A MIO object
Definition: mio.c:480
void verbose(const char *const format,...)
Definition: options.c:655
optionValues Option
Definition: options.c:137
@ SO_FOLDSORTED
Definition: options_p.h:63
#define NULL
Definition: rbtree.h:150
char * readLineRaw(vString *const vLine, MIO *const mio)
Definition: read.c:1016
int struppercmp(const char *s1, const char *s2)
Definition: routines.c:283
@ PERROR
Definition: routines.h:37
@ FATAL
Definition: routines.h:37
GtkWidget * close
Definition: sidebar.c:56
static int compareTags(const void *const one, const void *const two)
Definition: sort.c:185
void catFile(MIO *mio)
Definition: sort.c:36
static int compareTagsFolded(const void *const one, const void *const two)
Definition: sort.c:177
void failedSort(MIO *const mio, const char *msg)
Definition: sort.c:166
static void writeSortedTags(char **const table, const size_t numTags, const bool toStdout, bool newlineReplaced)
Definition: sort.c:193
void internalSortTags(const bool toStdout, MIO *mio, size_t numTags)
Definition: sort.c:227
if(!stash_group_load_from_file(group, filename)) g_warning(_("Could not load keyfile %s!")
MIO:
Definition: mio.c:136
Definition: entry.c:87
sortType sorted
Definition: options_p.h:95
vString * vStringNew(void)
Definition: vstring.c:70
void vStringDelete(vString *const string)
Definition: vstring.c:60
void vStringCatS(vString *const string, const char *const s)
Definition: vstring.c:146
#define vStringValue(vs)
Definition: vstring.h:28
static void vStringPut(vString *const string, const int c)
Definition: vstring.h:101