/ctags58/sort.c

https://github.com/howiefh/vimfiles · C · 230 lines · 164 code · 31 blank · 35 comment · 45 complexity · dbe774579c9f334702cc2bfe4c4cb041 MD5 · raw file

  1. /*
  2. * $Id: sort.c 498 2007-02-17 22:43:15Z dhiebert $
  3. *
  4. * Copyright (c) 1996-2002, Darren Hiebert
  5. *
  6. * This source code is released for free distribution under the terms of the
  7. * GNU General Public License.
  8. *
  9. * This module contains functions to sort the tag entries.
  10. */
  11. /*
  12. * INCLUDE FILES
  13. */
  14. #include "general.h" /* must always come first */
  15. #if defined (HAVE_STDLIB_H)
  16. # include <stdlib.h> /* to declare malloc () */
  17. #endif
  18. #include <string.h>
  19. #include <stdio.h>
  20. #include "debug.h"
  21. #include "entry.h"
  22. #include "options.h"
  23. #include "read.h"
  24. #include "routines.h"
  25. #include "sort.h"
  26. /*
  27. * FUNCTION DEFINITIONS
  28. */
  29. extern void catFile (const char *const name)
  30. {
  31. FILE *const fp = fopen (name, "r");
  32. if (fp != NULL)
  33. {
  34. int c;
  35. while ((c = getc (fp)) != EOF)
  36. putchar (c);
  37. fflush (stdout);
  38. fclose (fp);
  39. }
  40. }
  41. #ifdef EXTERNAL_SORT
  42. #ifdef NON_CONST_PUTENV_PROTOTYPE
  43. # define PE_CONST
  44. #else
  45. # define PE_CONST const
  46. #endif
  47. extern void externalSortTags (const boolean toStdout)
  48. {
  49. const char *const sortNormalCommand = "sort -u -o";
  50. const char *const sortFoldedCommand = "sort -u -f -o";
  51. const char *sortCommand =
  52. Option.sorted == SO_FOLDSORTED ? sortFoldedCommand : sortNormalCommand;
  53. PE_CONST char *const sortOrder1 = "LC_COLLATE=C";
  54. PE_CONST char *const sortOrder2 = "LC_ALL=C";
  55. const size_t length = 4 + strlen (sortOrder1) + strlen (sortOrder2) +
  56. strlen (sortCommand) + (2 * strlen (tagFileName ()));
  57. char *const cmd = (char *) malloc (length + 1);
  58. int ret = -1;
  59. if (cmd != NULL)
  60. {
  61. /* Ensure ASCII value sort order.
  62. */
  63. #ifdef HAVE_SETENV
  64. setenv ("LC_COLLATE", "C", 1);
  65. setenv ("LC_ALL", "C", 1);
  66. sprintf (cmd, "%s %s %s", sortCommand, tagFileName (), tagFileName ());
  67. #else
  68. # ifdef HAVE_PUTENV
  69. putenv (sortOrder1);
  70. putenv (sortOrder2);
  71. sprintf (cmd, "%s %s %s", sortCommand, tagFileName (), tagFileName ());
  72. # else
  73. sprintf (cmd, "%s %s %s %s %s", sortOrder1, sortOrder2, sortCommand,
  74. tagFileName (), tagFileName ());
  75. # endif
  76. #endif
  77. verbose ("system (\"%s\")\n", cmd);
  78. ret = system (cmd);
  79. free (cmd);
  80. }
  81. if (ret != 0)
  82. error (FATAL | PERROR, "cannot sort tag file");
  83. else if (toStdout)
  84. catFile (tagFileName ());
  85. }
  86. #else
  87. /*
  88. * These functions provide a basic internal sort. No great memory
  89. * optimization is performed (e.g. recursive subdivided sorts),
  90. * so have lots of memory if you have large tag files.
  91. */
  92. static void failedSort (FILE *const fp, const char* msg)
  93. {
  94. const char* const cannotSort = "cannot sort tag file";
  95. if (fp != NULL)
  96. fclose (fp);
  97. if (msg == NULL)
  98. error (FATAL | PERROR, cannotSort);
  99. else
  100. error (FATAL, "%s: %s", msg, cannotSort);
  101. }
  102. static int compareTagsFolded(const void *const one, const void *const two)
  103. {
  104. const char *const line1 = *(const char* const*) one;
  105. const char *const line2 = *(const char* const*) two;
  106. return struppercmp (line1, line2);
  107. }
  108. static int compareTags (const void *const one, const void *const two)
  109. {
  110. const char *const line1 = *(const char* const*) one;
  111. const char *const line2 = *(const char* const*) two;
  112. return strcmp (line1, line2);
  113. }
  114. static void writeSortedTags (
  115. char **const table, const size_t numTags, const boolean toStdout)
  116. {
  117. FILE *fp;
  118. size_t i;
  119. /* Write the sorted lines back into the tag file.
  120. */
  121. if (toStdout)
  122. fp = stdout;
  123. else
  124. {
  125. fp = fopen (tagFileName (), "w");
  126. if (fp == NULL)
  127. failedSort (fp, NULL);
  128. }
  129. for (i = 0 ; i < numTags ; ++i)
  130. {
  131. /* Here we filter out identical tag *lines* (including search
  132. * pattern) if this is not an xref file.
  133. */
  134. if (i == 0 || Option.xref || strcmp (table [i], table [i-1]) != 0)
  135. if (fputs (table [i], fp) == EOF)
  136. failedSort (fp, NULL);
  137. }
  138. if (toStdout)
  139. fflush (fp);
  140. else
  141. fclose (fp);
  142. }
  143. extern void internalSortTags (const boolean toStdout)
  144. {
  145. vString *vLine = vStringNew ();
  146. FILE *fp = NULL;
  147. const char *line;
  148. size_t i;
  149. int (*cmpFunc)(const void *, const void *);
  150. /* Allocate a table of line pointers to be sorted.
  151. */
  152. size_t numTags = TagFile.numTags.added + TagFile.numTags.prev;
  153. const size_t tableSize = numTags * sizeof (char *);
  154. char **const table = (char **) malloc (tableSize); /* line pointers */
  155. DebugStatement ( size_t mallocSize = tableSize; ) /* cumulative total */
  156. cmpFunc = Option.sorted == SO_FOLDSORTED ? compareTagsFolded : compareTags;
  157. if (table == NULL)
  158. failedSort (fp, "out of memory");
  159. /* Open the tag file and place its lines into allocated buffers.
  160. */
  161. fp = fopen (tagFileName (), "r");
  162. if (fp == NULL)
  163. failedSort (fp, NULL);
  164. for (i = 0 ; i < numTags && ! feof (fp) ; )
  165. {
  166. line = readLine (vLine, fp);
  167. if (line == NULL)
  168. {
  169. if (! feof (fp))
  170. failedSort (fp, NULL);
  171. break;
  172. }
  173. else if (*line == '\0' || strcmp (line, "\n") == 0)
  174. ; /* ignore blank lines */
  175. else
  176. {
  177. const size_t stringSize = strlen (line) + 1;
  178. table [i] = (char *) malloc (stringSize);
  179. if (table [i] == NULL)
  180. failedSort (fp, "out of memory");
  181. DebugStatement ( mallocSize += stringSize; )
  182. strcpy (table [i], line);
  183. ++i;
  184. }
  185. }
  186. numTags = i;
  187. fclose (fp);
  188. vStringDelete (vLine);
  189. /* Sort the lines.
  190. */
  191. qsort (table, numTags, sizeof (*table), cmpFunc);
  192. writeSortedTags (table, numTags, toStdout);
  193. PrintStatus (("sort memory: %ld bytes\n", (long) mallocSize));
  194. for (i = 0 ; i < numTags ; ++i)
  195. free (table [i]);
  196. free (table);
  197. }
  198. #endif
  199. /* vi:set tabstop=4 shiftwidth=4: */