00001
00002
00003
00004
00005
00006 #include "common.h"
00007 #include "localmem.h"
00008 #include "snofmake.h"
00009 #include "errabort.h"
00010
00011 static char const rcsid[] = "$Id: snofmake.c,v 1.5 2003/05/06 07:33:44 kate Exp $";
00012
00013 static jmp_buf errRecover;
00014
00015 static void ourErrAbort()
00016
00017
00018 {
00019 longjmp(errRecover, -1);
00020 }
00021
00022 static struct lm *lm;
00023
00024 static void initMem()
00025 {
00026 lm = lmInit((1<<16));
00027 }
00028
00029 static void cleanupMem()
00030 {
00031 lmCleanup(&lm);
00032 }
00033
00034 static void *localNeedMem(int size)
00035 {
00036 return lmAlloc(lm, size);
00037 }
00038
00039 struct offsetList
00040 {
00041 struct offsetList *next;
00042 char *name;
00043 unsigned offset;
00044 };
00045
00046 static struct offsetList *newOffset(char *name, int nameLen)
00047
00048 {
00049 struct offsetList *nl = localNeedMem(sizeof(*nl));
00050 nl->name = localNeedMem(nameLen+1);
00051 memcpy(nl->name, name, nameLen);
00052 nl->name[nameLen] = 0;
00053 return nl;
00054 }
00055
00056 static int cmpOffsetPointers(const void *va, const void *vb)
00057
00058 {
00059 struct offsetList **pa, **pb;
00060 struct offsetList *a, *b;
00061 pa = (struct offsetList **)va;
00062 pb = (struct offsetList **)vb;
00063 a = *pa;
00064 b = *pb;
00065 return strcmp(a->name, b->name);
00066 }
00067
00068 static int longestNameSize(struct offsetList *list)
00069 {
00070 struct offsetList *el;
00071 int size, longestSize = 0;
00072
00073 for (el = list; el != NULL; el = el->next)
00074 {
00075 size = strlen(el->name);
00076 if (size > longestSize)
00077 {
00078 longestSize = size;
00079 }
00080 }
00081 return longestSize;
00082 }
00083
00084 static struct offsetList *makeOffsetList(FILE *inFile,
00085 boolean (*nextRecord)(FILE *inFile, void *data, char **rName, int *rNameLen), void *data)
00086
00087 {
00088 struct offsetList *list = NULL;
00089 struct offsetList *newEl;
00090 for (;;)
00091 {
00092 long offset = ftell(inFile);
00093 char *name;
00094 int nameLen;
00095 if (!nextRecord(inFile, data, &name, &nameLen))
00096 break;
00097 if (nameLen > 0)
00098 {
00099 newEl = newOffset(name, nameLen);
00100 newEl->offset = offset;
00101 newEl->next = list;
00102 list = newEl;
00103 }
00104 }
00105 slReverse(&list);
00106 return list;
00107 }
00108
00109 boolean warnAboutDupes(struct offsetList **array, int size)
00110
00111 {
00112 char *name, *prevName;
00113 int i;
00114 boolean ok = TRUE;
00115
00116 if (size < 2)
00117 return FALSE;
00118 prevName = array[0]->name;
00119 for (i=1; i<size; ++i)
00120 {
00121 name = array[i]->name;
00122 if (!differentWord(name, prevName))
00123 {
00124 warn("Duplicate strings: %s %s", prevName, name);
00125 ok = FALSE;
00126 }
00127 prevName = name;
00128 }
00129 return ok;
00130 }
00131
00132 static void makeIndex(FILE *in, FILE *out,
00133 boolean (*nextRecord)(FILE *in, void *data, char **rName, int *rNameLen), void *data,
00134 boolean dupeOk)
00135
00136 {
00137 struct offsetList *list;
00138 int listSize;
00139 struct offsetList **array;
00140 int i;
00141 struct offsetList *el;
00142 int nameSize;
00143 char *nameBuf;
00144 char *indexSig;
00145 int indexSigSize;
00146
00147 printf("Reading input\n");
00148 list = makeOffsetList(in, nextRecord, data);
00149 listSize = slCount(list);
00150 array = localNeedMem(listSize * sizeof(*array));
00151 nameSize = longestNameSize(list)+1;
00152
00153 printf("Got %d offsets %d nameSize. Sorting...\n", listSize, nameSize);
00154 nameBuf = localNeedMem(nameSize);
00155
00156
00157 for (i=0, el = list; i<listSize; i+=1, el = el->next)
00158 array[i] = el;
00159
00160
00161 qsort(array, listSize, sizeof(array[0]), cmpOffsetPointers);
00162 if (!dupeOk)
00163 warnAboutDupes(array, listSize);
00164
00165
00166 printf("Writing index file \n");
00167 snofSignature(&indexSig, &indexSigSize);
00168 mustWrite(out, indexSig, indexSigSize);
00169 mustWrite(out, &nameSize, sizeof(nameSize));
00170
00171
00172 for (i=0; i<listSize; ++i)
00173 {
00174 zeroBytes(nameBuf, nameSize);
00175 strcpy(nameBuf, array[i]->name);
00176 mustWrite(out, nameBuf, nameSize);
00177 mustWrite(out, &array[i]->offset, sizeof(array[i]->offset));
00178 }
00179 }
00180
00181 boolean snofDupeOkIndex(FILE *inFile, char *outName,
00182 boolean (*nextRecord)(FILE *inFile, void *data, char **rName, int *rNameLen),
00183 void *data, boolean dupeOk)
00184
00185
00186 {
00187 FILE *outFile;
00188 int status;
00189
00190
00191 if ((outFile = fopen(outName, "wb")) == NULL)
00192 {
00193 fprintf(stderr, "Couldn't create index file %s\n", outName);
00194 return FALSE;
00195 }
00196 initMem();
00197
00198
00199 status = setjmp(errRecover);
00200 if (status == 0)
00201 {
00202 pushAbortHandler(ourErrAbort);
00203 makeIndex(inFile, outFile, nextRecord, data, dupeOk);
00204 }
00205 popAbortHandler();
00206
00207
00208 fclose(outFile);
00209 cleanupMem();
00210 return status == 0;
00211 }
00212
00213 boolean snofMakeIndex(FILE *inFile, char *outName,
00214 boolean (*nextRecord)(FILE *inFile, void *data, char **rName, int *rNameLen),
00215 void *data)
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226 {
00227 return snofDupeOkIndex(inFile, outName, nextRecord, data, FALSE);
00228 }
00229