This is sort.c in view mode; [Download] [Up]
/***************************************************************************** * $Id: sort.c,v 1.5 1997/04/06 02:13:52 darren Exp $ * * Copyright (c) 1996-1997, Darren Hiebert * * Contains functions to sort the tag entries. *****************************************************************************/ /*============================================================================ = Include files ============================================================================*/ #ifdef HAVE_CONFIG_H # include <config.h> #endif #ifdef DEBUG # include <assert.h> #endif #include "ctags.h" /*============================================================================ = Function prototypes ============================================================================*/ /* Tag sorting functions. */ #ifdef EXTERNAL_SORT static void catFile __ARGS((const char *const name)); static void reportWarnings __ARGS((void)); #else static void failedSort __ARGS((const char *const msg)); static int compareTags __ARGS((const void *const one, const void *const two)); static void writeSortedTags __ARGS((char **const table, const boolean toStdout)); #endif /*============================================================================ = Function definitions ============================================================================*/ #ifdef EXTERNAL_SORT static void catFile( name ) const char *const name; { FILE *const fp = fopen(name, "r"); if (fp != NULL) { int c; while ((c = getc(fp)) != EOF) putc(c, fp); fclose(fp); } } static void reportWarnings() { #ifdef AWK if (strlen(AWK) > (size_t)0) { const char *const awkProgTemplate = "%s{if ($1==prev){printf(\"Duplicate entry in \") | \"cat>&2\"; if ($%d!=prevfile) printf(\"%%s and \",prevfile) | \"cat>&2\"; printf(\"%%s: %%s\\n\",$%d,$1) | \"cat>&2\"; } else {prev=$1;prevfile=$%d}}"; char *awkProg; const char *begin; size_t length; int fileArg; if (Option.xref) { fileArg = 4; begin = ""; } else { fileArg = 2; begin = "BEGIN{FS=\"\\t\"}"; } length = strlen(awkProgTemplate) + strlen(begin) + 3; awkProg = (char *)malloc(length); if (awkProg != NULL) { const char *const cmdTemplate = "%s '%s' %s"; char *cmd; int ret; sprintf(awkProg, awkProgTemplate, begin, fileArg, fileArg, fileArg); length = strlen(cmdTemplate) + strlen(AWK) + strlen(awkProg) + strlen(TagFile.name); cmd = (char *)malloc(length); if (cmd != NULL) { sprintf(cmd, cmdTemplate, AWK, awkProg, TagFile.name); ret = system(cmd); free(cmd); } free(awkProg); } } #endif } extern void externalSortTags( toStdout ) const boolean toStdout; { const char *const sortTemplate = "sort -o %s %s"; const size_t length = strlen(sortTemplate) + 2 * strlen(TagFile.name); char *const cmd = (char *)malloc(length); if (cmd != NULL) { int ret; sprintf(cmd, sortTemplate, TagFile.name, TagFile.name); ret = system(cmd); free(cmd); if (ret == 0 && Option.warnings) reportWarnings(); } if (toStdout) catFile(TagFile.name); } #else /*---------------------------------------------------------------------------- * These functions provide a basic internal sort. No great memory * optimization is performed (e.g. recursive subdivided sorts), * so have lots of memory if you have large tag files. *--------------------------------------------------------------------------*/ static void failedSort( msg ) const char *const msg; { if (TagFile.fp != NULL) { fclose(TagFile.fp); TagFile.fp = NULL; } if (msg == NULL) fputs("ctags: Insufficient memory\n", errout); else perror(msg); fprintf(errout, "Cannot sort tag file.\n"); exit(1); } static int compareTags( one, two ) const void *const one; const void *const two; { const char *const line1 = *(const char *const *const)one; const char *const line2 = *(const char *const *const)two; return strcmp(line1, line2); } static void writeSortedTags( table, toStdout ) char **const table; const boolean toStdout; { char *thisTag = NULL, *prevTag = NULL, *thisFile = NULL, *prevFile = NULL; size_t i; if (Option.warnings) { thisTag = malloc(TagFile.max.tag + (size_t)1); prevTag = malloc(TagFile.max.tag + (size_t)1); thisFile = malloc(TagFile.max.file + (size_t)1); prevFile = malloc(TagFile.max.file + (size_t)1); if (thisTag == NULL || prevTag == NULL || thisFile == NULL || prevFile == NULL) { perror("Cannot generate duplicate warnings\n"); } *prevTag = *thisTag = '\0'; *prevFile = *thisFile = '\0'; } /* Write the sorted lines back into the tag file. */ if (toStdout) TagFile.fp = stdout; else { TagFile.fp = fopen(TagFile.name, "w"); if (TagFile.fp == NULL) failedSort(TagFile.name); } for (i = 0 ; i < TagFile.numTags ; ++i) { /* Here we filter out identical tag *lines* (including search * pattern) if this is not an xref file. */ if (i == 0 || Option.xref || strcmp(table[i], table[i-1]) != 0) if (fputs(table[i], TagFile.fp) == EOF) failedSort(TagFile.name); if (Option.warnings) { int fields; if (Option.xref) fields = sscanf(table[i],"%s %*s %*s %s", thisTag, thisFile); else fields = sscanf(table[i],"%[^\t]\t%[^\t]", thisTag, thisFile); if (fields == 2 && strcmp(thisTag, prevTag) == 0) { fprintf(errout, "Duplicate entry in "); if (strcmp(thisFile, prevFile) != 0) fprintf(errout, "%s and ", prevFile); fprintf(errout, "%s: %s\n", thisFile, thisTag); } strcpy(prevTag , thisTag ); strcpy(prevFile, thisFile); } } if (Option.warnings) { free(thisTag); free(prevTag); free(thisFile); free(prevFile); } if (! toStdout) fclose(TagFile.fp); } extern void internalSortTags( toStdout ) const boolean toStdout; { char *buffer, **table; const size_t maxLength = TagFile.max.line + 1; /* include room for null */ size_t tableSize, mallocSize; size_t i; /* Allocate the memory buffer for the tag file lines. This includes a * table of line pointers which will be sorted. */ tableSize = TagFile.numTags * sizeof(*table); buffer = malloc(maxLength); /* read buffer */ table = malloc(tableSize); if (buffer == NULL || table == NULL) failedSort(NULL); mallocSize = maxLength + tableSize; /* Open the tag file and place its lines into allocated buffers. */ TagFile.fp = fopen(TagFile.name, "r"); if (TagFile.fp == NULL) failedSort(TagFile.name); for (i = 0 ; i < TagFile.numTags && !feof(TagFile.fp) ; ++i) { size_t stringSize; if (fgets(buffer, (int)maxLength, TagFile.fp) == NULL && ! feof(TagFile.fp)) failedSort(TagFile.name); stringSize = strlen(buffer) + 1; table[i] = (char *)malloc(stringSize); if (table[i] == NULL) failedSort(NULL); mallocSize += stringSize; strcpy(table[i], buffer); } #ifdef DEBUG assert(i == TagFile.numTags); /* this should always be the case */ #endif fclose(TagFile.fp); /* Sort the lines. */ qsort(table, TagFile.numTags, sizeof(*table), #ifndef USING_PROTOTYPES (int (*)()) #endif compareTags); writeSortedTags(table, toStdout); #ifdef DEBUG if (debug(DEBUG_STATUS)) printf("sort memory: %ld bytes\n", (long)mallocSize); #endif for (i = 0 ; i < TagFile.numTags ; ++i) free(table[i]); free(table); free(buffer); } #endif /* vi:set tabstop=8 shiftwidth=4: */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.