116
116
extern void addTotals (
117
const unsigned int files, const long unsigned int lines,
118
const long unsigned int bytes)
117
const unsigned int files, const long unsigned int lines,
118
const long unsigned int bytes)
120
Totals.files += files;
121
Totals.lines += lines;
122
Totals.bytes += bytes;
120
Totals.files += files;
121
Totals.lines += lines;
122
Totals.bytes += bytes;
125
125
extern boolean isDestinationStdout (void)
127
boolean toStdout = FALSE;
127
boolean toStdout = FALSE;
129
if (Option.xref || Option.filter ||
130
(Option.tagFileName != NULL && (strcmp (Option.tagFileName, "-") == 0
129
if (Option.xref || Option.filter ||
130
(Option.tagFileName != NULL && (strcmp (Option.tagFileName, "-") == 0
131
131
#if defined (VMS)
132
|| strcmp (Option.tagFileName, "sys$output") == 0
132
|| strcmp (Option.tagFileName, "sys$output") == 0
134
|| strcmp (Option.tagFileName, "/dev/stdout") == 0
134
|| strcmp (Option.tagFileName, "/dev/stdout") == 0
141
141
#if defined (HAVE_OPENDIR)
142
142
static boolean recurseUsingOpendir (const char *const dirName)
144
boolean resize = FALSE;
145
DIR *const dir = opendir (dirName);
147
error (WARNING | PERROR, "cannot recurse into directory \"%s\"", dirName);
150
struct dirent *entry;
151
while ((entry = readdir (dir)) != NULL)
153
if (strcmp (entry->d_name, ".") != 0 &&
154
strcmp (entry->d_name, "..") != 0)
157
if (strcmp (dirName, ".") == 0)
158
filePath = vStringNewInit (entry->d_name);
160
filePath = combinePathAndFile (dirName, entry->d_name);
161
resize |= createTagsForEntry (vStringValue (filePath));
144
boolean resize = FALSE;
145
DIR *const dir = opendir (dirName);
147
error (WARNING | PERROR, "cannot recurse into directory \"%s\"", dirName);
150
struct dirent *entry;
151
while ((entry = readdir (dir)) != NULL)
153
if (strcmp (entry->d_name, ".") != 0 &&
154
strcmp (entry->d_name, "..") != 0)
157
if (strcmp (dirName, ".") == 0)
158
filePath = vStringNewInit (entry->d_name);
160
filePath = combinePathAndFile (dirName, entry->d_name);
161
resize |= createTagsForEntry (vStringValue (filePath));
162
vStringDelete (filePath);
170
#elif defined (HAVE_FINDFIRST) || defined (HAVE__FINDFIRST)
172
static boolean createTagsForWildcardEntry (
173
const char *const pattern, const size_t dirLength,
174
const char *const entryName)
176
boolean resize = FALSE;
177
/* we must not recurse into the directories "." or ".." */
178
if (strcmp (entryName, ".") != 0 && strcmp (entryName, "..") != 0)
180
vString *const filePath = vStringNew ();
181
vStringNCopyS (filePath, pattern, dirLength);
182
vStringCatS (filePath, entryName);
183
resize = createTagsForEntry (vStringValue (filePath));
162
184
vStringDelete (filePath);
170
#elif defined (HAVE_FINDFIRST) || defined (HAVE__FINDFIRST)
172
static boolean createTagsForWildcardEntry (
173
const char *const pattern, const size_t dirLength,
174
const char *const entryName)
176
boolean resize = FALSE;
177
/* we must not recurse into the directories "." or ".." */
178
if (strcmp (entryName, ".") != 0 && strcmp (entryName, "..") != 0)
180
vString *const filePath = vStringNew ();
181
vStringNCopyS (filePath, pattern, dirLength);
182
vStringCatS (filePath, entryName);
183
resize = createTagsForEntry (vStringValue (filePath));
184
vStringDelete (filePath);
189
189
static boolean createTagsForWildcardUsingFindfirst (const char *const pattern)
191
boolean resize = FALSE;
192
const size_t dirLength = baseFilename (pattern) - pattern;
191
boolean resize = FALSE;
192
const size_t dirLength = baseFilename (pattern) - pattern;
193
193
#if defined (HAVE_FINDFIRST)
194
struct ffblk fileInfo;
195
int result = findfirst (pattern, &fileInfo, FA_DIREC);
198
const char *const entry = (const char *) fileInfo.ff_name;
199
resize |= createTagsForWildcardEntry (pattern, dirLength, entry);
200
result = findnext (&fileInfo);
194
struct ffblk fileInfo;
195
int result = findfirst (pattern, &fileInfo, FA_DIREC);
198
const char *const entry = (const char *) fileInfo.ff_name;
199
resize |= createTagsForWildcardEntry (pattern, dirLength, entry);
200
result = findnext (&fileInfo);
202
202
#elif defined (HAVE__FINDFIRST)
203
struct _finddata_t fileInfo;
204
findfirst_t hFile = _findfirst (pattern, &fileInfo);
203
struct _finddata_t fileInfo;
204
findfirst_t hFile = _findfirst (pattern, &fileInfo);
209
const char *const entry = (const char *) fileInfo.name;
210
resize |= createTagsForWildcardEntry (pattern, dirLength, entry);
211
} while (_findnext (hFile, &fileInfo) == 0);
209
const char *const entry = (const char *) fileInfo.name;
210
resize |= createTagsForWildcardEntry (pattern, dirLength, entry);
211
} while (_findnext (hFile, &fileInfo) == 0);
218
218
#elif defined (AMIGA)
220
220
static boolean createTagsForAmigaWildcard (const char *const pattern)
222
boolean resize = FALSE;
223
struct AnchorPath *const anchor =
224
(struct AnchorPath *) eMalloc ((size_t) ANCHOR_SIZE);
222
boolean resize = FALSE;
223
struct AnchorPath *const anchor =
224
(struct AnchorPath *) eMalloc ((size_t) ANCHOR_SIZE);
227
memset (anchor, 0, (size_t) ANCHOR_SIZE);
228
anchor->ap_Strlen = ANCHOR_BUF_SIZE;
229
/* Allow '.' for current directory */
227
memset (anchor, 0, (size_t) ANCHOR_SIZE);
228
anchor->ap_Strlen = ANCHOR_BUF_SIZE;
229
/* Allow '.' for current directory */
231
anchor->ap_Flags = APF_DODOT | APF_DOWILD;
231
anchor->ap_Flags = APF_DODOT | APF_DOWILD;
233
anchor->ap_Flags = APF_DoDot | APF_DoWild;
233
anchor->ap_Flags = APF_DoDot | APF_DoWild;
235
result = MatchFirst ((UBYTE *) pattern, anchor);
238
resize |= createTagsForEntry ((char *) anchor->ap_Buf);
239
result = MatchNext (anchor);
235
result = MatchFirst ((UBYTE *) pattern, anchor);
238
resize |= createTagsForEntry ((char *) anchor->ap_Buf);
239
result = MatchNext (anchor);
247
247
static boolean recurseIntoDirectory (const char *const dirName)
249
boolean resize = FALSE;
250
if (isRecursiveLink (dirName))
251
verbose ("ignoring \"%s\" (recursive link)\n", dirName);
252
else if (! Option.recurse)
253
verbose ("ignoring \"%s\" (directory)\n", dirName);
256
verbose ("RECURSING into directory \"%s\"\n", dirName);
249
boolean resize = FALSE;
250
if (isRecursiveLink (dirName))
251
verbose ("ignoring \"%s\" (recursive link)\n", dirName);
252
else if (! Option.recurse)
253
verbose ("ignoring \"%s\" (directory)\n", dirName);
256
verbose ("RECURSING into directory \"%s\"\n", dirName);
257
257
#if defined (HAVE_OPENDIR)
258
resize = recurseUsingOpendir (dirName);
258
resize = recurseUsingOpendir (dirName);
259
259
#elif defined (HAVE_FINDFIRST) || defined (HAVE__FINDFIRST)
261
vString *const pattern = vStringNew ();
262
vStringCopyS (pattern, dirName);
263
vStringPut (pattern, OUTPUT_PATH_SEPARATOR);
264
vStringCatS (pattern, "*.*");
265
resize = createTagsForWildcardUsingFindfirst (vStringValue (pattern));
266
vStringDelete (pattern);
261
vString *const pattern = vStringNew ();
262
vStringCopyS (pattern, dirName);
263
vStringPut (pattern, OUTPUT_PATH_SEPARATOR);
264
vStringCatS (pattern, "*.*");
265
resize = createTagsForWildcardUsingFindfirst (vStringValue (pattern));
266
vStringDelete (pattern);
268
268
#elif defined (AMIGA)
270
vString *const pattern = vStringNew ();
271
if (*dirName != '\0' && strcmp (dirName, ".") != 0)
273
vStringCopyS (pattern, dirName);
274
if (dirName [strlen (dirName) - 1] != '/')
275
vStringPut (pattern, '/');
277
vStringCatS (pattern, "#?");
278
resize = createTagsForAmigaWildcard (vStringValue (pattern));
279
vStringDelete (pattern);
270
vString *const pattern = vStringNew ();
271
if (*dirName != '\0' && strcmp (dirName, ".") != 0)
273
vStringCopyS (pattern, dirName);
274
if (dirName [strlen (dirName) - 1] != '/')
275
vStringPut (pattern, '/');
277
vStringCatS (pattern, "#?");
278
resize = createTagsForAmigaWildcard (vStringValue (pattern));
279
vStringDelete (pattern);
286
286
static boolean createTagsForEntry (const char *const entryName)
288
boolean resize = FALSE;
289
fileStatus *status = eStat (entryName);
291
Assert (entryName != NULL);
292
if (isExcludedFile (entryName))
293
verbose ("excluding \"%s\"\n", entryName);
294
else if (status->isSymbolicLink && ! Option.followLinks)
295
verbose ("ignoring \"%s\" (symbolic link)\n", entryName);
296
else if (! status->exists)
297
error (WARNING | PERROR, "cannot open source file \"%s\"", entryName);
298
else if (status->isDirectory)
299
resize = recurseIntoDirectory (entryName);
300
else if (! status->isNormalFile)
301
verbose ("ignoring \"%s\" (special file)\n", entryName);
303
resize = parseFile (entryName);
288
boolean resize = FALSE;
289
fileStatus *status = eStat (entryName);
291
Assert (entryName != NULL);
292
if (isExcludedFile (entryName))
293
verbose ("excluding \"%s\"\n", entryName);
294
else if (status->isSymbolicLink && ! Option.followLinks)
295
verbose ("ignoring \"%s\" (symbolic link)\n", entryName);
296
else if (! status->exists)
297
error (WARNING | PERROR, "cannot open source file \"%s\"", entryName);
298
else if (status->isDirectory)
299
resize = recurseIntoDirectory (entryName);
300
else if (! status->isNormalFile)
301
verbose ("ignoring \"%s\" (special file)\n", entryName);
303
resize = parseFile (entryName);
308
308
#ifdef MANUAL_GLOBBING
310
310
static boolean createTagsForWildcardArg (const char *const arg)
312
boolean resize = FALSE;
313
vString *const pattern = vStringNewInit (arg);
314
char *patternS = vStringValue (pattern);
312
boolean resize = FALSE;
313
vString *const pattern = vStringNewInit (arg);
314
char *patternS = vStringValue (pattern);
316
316
#if defined (HAVE_FINDFIRST) || defined (HAVE__FINDFIRST)
317
/* We must transform the "." and ".." forms into something that can
318
* be expanded by the findfirst/_findfirst functions.
320
if (Option.recurse &&
321
(strcmp (patternS, ".") == 0 || strcmp (patternS, "..") == 0))
323
vStringPut (pattern, OUTPUT_PATH_SEPARATOR);
324
vStringCatS (pattern, "*.*");
326
resize |= createTagsForWildcardUsingFindfirst (patternS);
317
/* We must transform the "." and ".." forms into something that can
318
* be expanded by the findfirst/_findfirst functions.
320
if (Option.recurse &&
321
(strcmp (patternS, ".") == 0 || strcmp (patternS, "..") == 0))
323
vStringPut (pattern, OUTPUT_PATH_SEPARATOR);
324
vStringCatS (pattern, "*.*");
326
resize |= createTagsForWildcardUsingFindfirst (patternS);
328
vStringDelete (pattern);
328
vStringDelete (pattern);
334
static boolean createTagsForArgs (cookedArgs* const args)
334
static boolean createTagsForArgs (cookedArgs *const args)
336
boolean resize = FALSE;
336
boolean resize = FALSE;
338
/* Generate tags for each argument on the command line.
340
while (! cArgOff (args))
342
const char *const arg = cArgItem (args);
338
/* Generate tags for each argument on the command line.
340
while (! cArgOff (args))
342
const char *const arg = cArgItem (args);
344
344
#ifdef MANUAL_GLOBBING
345
resize |= createTagsForWildcardArg (arg);
345
resize |= createTagsForWildcardArg (arg);
347
resize |= createTagsForEntry (arg);
347
resize |= createTagsForEntry (arg);
355
355
/* Read from an opened file a list of file names for which to generate tags.
357
static boolean createTagsFromFileInput (FILE* const fp, const boolean filter)
357
static boolean createTagsFromFileInput (FILE *const fp, const boolean filter)
359
boolean resize = FALSE;
362
cookedArgs* args = cArgNewFromLineFile (fp);
364
while (! cArgOff (args))
359
boolean resize = FALSE;
366
resize |= createTagsForEntry (cArgItem (args));
369
if (Option.filterTerminator != NULL)
370
fputs (Option.filterTerminator, stdout);
362
cookedArgs *args = cArgNewFromLineFile (fp);
364
while (! cArgOff (args))
366
resize |= createTagsForEntry (cArgItem (args));
369
if (Option.filterTerminator != NULL)
370
fputs (Option.filterTerminator, stdout);
381
381
/* Read from a named file a list of file names for which to generate tags.
383
static boolean createTagsFromListFile (const char* const fileName)
383
static boolean createTagsFromListFile (const char *const fileName)
386
Assert (fileName != NULL);
387
if (strcmp (fileName, "-") == 0)
388
resize = createTagsFromFileInput (stdin, FALSE);
391
FILE* const fp = fopen (fileName, "r");
393
error (FATAL | PERROR, "cannot open list file \"%s\"", fileName);
394
resize = createTagsFromFileInput (fp, FALSE);
386
Assert (fileName != NULL);
387
if (strcmp (fileName, "-") == 0)
388
resize = createTagsFromFileInput (stdin, FALSE);
391
FILE *const fp = fopen (fileName, "r");
393
error (FATAL | PERROR, "cannot open list file \"%s\"", fileName);
394
resize = createTagsFromFileInput (fp, FALSE);
400
400
#if defined (HAVE_CLOCK)
401
401
# define CLOCK_AVAILABLE
402
402
# ifndef CLOCKS_PER_SEC
403
# define CLOCKS_PER_SEC 1000000
403
# define CLOCKS_PER_SEC 1000000
405
405
#elif defined (HAVE_TIMES)
406
406
# define CLOCK_AVAILABLE
407
407
# define CLOCKS_PER_SEC 60
408
408
static clock_t clock (void)
413
return (buf.tms_utime + buf.tms_stime);
413
return (buf.tms_utime + buf.tms_stime);
416
416
# define clock() (clock_t)0
419
419
static void printTotals (const clock_t *const timeStamps)
421
const unsigned long totalTags = TagFile.numTags.added +
422
TagFile.numTags.prev;
424
fprintf (errout, "%ld file%s, %ld line%s (%ld kB) scanned",
425
Totals.files, plural (Totals.files),
426
Totals.lines, plural (Totals.lines),
428
#ifdef CLOCK_AVAILABLE
430
const double interval = ((double) (timeStamps [1] - timeStamps [0])) /
433
fprintf (errout, " in %.01f seconds", interval);
434
if (interval != (double) 0.0)
435
fprintf (errout, " (%lu kB/s)",
436
(unsigned long) (Totals.bytes / interval) / 1024L);
439
fputc ('\n', errout);
441
fprintf (errout, "%lu tag%s added to tag file",
442
TagFile.numTags.added, plural (TagFile.numTags.added));
444
fprintf (errout, " (now %lu tags)", totalTags);
445
fputc ('\n', errout);
447
if (totalTags > 0 && Option.sorted != SO_UNSORTED)
449
fprintf (errout, "%lu tag%s sorted", totalTags, plural (totalTags));
450
#ifdef CLOCK_AVAILABLE
451
fprintf (errout, " in %.02f seconds",
452
((double) (timeStamps [2] - timeStamps [1])) / CLOCKS_PER_SEC);
454
fputc ('\n', errout);
421
const unsigned long totalTags = TagFile.numTags.added +
422
TagFile.numTags.prev;
424
fprintf (errout, "%ld file%s, %ld line%s (%ld kB) scanned",
425
Totals.files, plural (Totals.files),
426
Totals.lines, plural (Totals.lines),
428
#ifdef CLOCK_AVAILABLE
430
const double interval = ((double) (timeStamps [1] - timeStamps [0])) /
433
fprintf (errout, " in %.01f seconds", interval);
434
if (interval != (double) 0.0)
435
fprintf (errout, " (%lu kB/s)",
436
(unsigned long) (Totals.bytes / interval) / 1024L);
439
fputc ('\n', errout);
441
fprintf (errout, "%lu tag%s added to tag file",
442
TagFile.numTags.added, plural (TagFile.numTags.added));
444
fprintf (errout, " (now %lu tags)", totalTags);
445
fputc ('\n', errout);
447
if (totalTags > 0 && Option.sorted != SO_UNSORTED)
449
fprintf (errout, "%lu tag%s sorted", totalTags, plural (totalTags));
450
#ifdef CLOCK_AVAILABLE
451
fprintf (errout, " in %.02f seconds",
452
((double) (timeStamps [2] - timeStamps [1])) / CLOCKS_PER_SEC);
454
fputc ('\n', errout);
458
fprintf (errout, "longest tag line = %lu\n",
459
(unsigned long) TagFile.max.line);
458
fprintf (errout, "longest tag line = %lu\n",
459
(unsigned long) TagFile.max.line);
463
static void makeTags (cookedArgs* args)
465
clock_t timeStamps [3];
466
boolean resize = FALSE;
467
boolean files = (boolean)(! cArgOff (args) || Option.fileList != NULL
470
if (! files && ! Option.recurse)
472
if (filesRequired ())
473
error (FATAL, "No files specified. Try \"%s --help\".",
474
getExecutableName ());
463
static boolean etagsInclude (void)
465
return (boolean)(Option.etags && Option.etagsInclude != NULL);
468
static void makeTags (cookedArgs *args)
470
clock_t timeStamps [3];
471
boolean resize = FALSE;
472
boolean files = (boolean)(! cArgOff (args) || Option.fileList != NULL
477
if (filesRequired ())
478
error (FATAL, "No files specified. Try \"%s --help\".",
479
getExecutableName ());
480
else if (! Option.recurse && ! etagsInclude ())
478
484
#define timeStamp(n) timeStamps[(n)]=(Option.printTotals ? clock():(clock_t)0)
484
if (! cArgOff (args))
486
verbose ("Reading command line arguments\n");
487
resize = createTagsForArgs (args);
489
if (Option.fileList != NULL)
491
verbose ("Reading list file\n");
492
resize = (boolean) (createTagsFromListFile (Option.fileList) || resize);
496
verbose ("Reading filter input\n");
497
resize = (boolean) (createTagsFromFileInput (stdin, TRUE) || resize);
499
if (! files && Option.recurse)
500
resize = recurseIntoDirectory (".");
505
closeTagFile (resize);
509
if (Option.printTotals)
510
printTotals (timeStamps);
490
if (! cArgOff (args))
492
verbose ("Reading command line arguments\n");
493
resize = createTagsForArgs (args);
495
if (Option.fileList != NULL)
497
verbose ("Reading list file\n");
498
resize = (boolean) (createTagsFromListFile (Option.fileList) || resize);
502
verbose ("Reading filter input\n");
503
resize = (boolean) (createTagsFromFileInput (stdin, TRUE) || resize);
505
if (! files && Option.recurse)
506
resize = recurseIntoDirectory (".");
511
closeTagFile (resize);
515
if (Option.printTotals)
516
printTotals (timeStamps);
518
524
extern int main (int __unused__ argc, char **argv)
522
extern int getredirection (int *ac, char ***av);
528
extern int getredirection (int *ac, char ***av);
524
/* do wildcard expansion and I/O redirection */
525
getredirection (&argc, &argv);
530
/* do wildcard expansion and I/O redirection */
531
getredirection (&argc, &argv);
529
/* This program doesn't work when started from the Workbench */
535
/* This program doesn't work when started from the Workbench */
535
_wildcard (&argc, &argv); /* expand wildcards in argument list */
541
_wildcard (&argc, &argv); /* expand wildcards in argument list */
538
544
#if defined (macintosh) && BUILD_MPW_TOOL == 0
539
argc = ccommand (&argv);
545
argc = ccommand (&argv);
542
setCurrentDirectory ();
543
setExecutableName (*argv++);
546
args = cArgNewFromArgv (argv);
547
previewFirstOption (args);
548
testEtagsInvocation ();
549
initializeParsing ();
551
readOptionConfiguration ();
552
verbose ("Reading initial options from command line\n");
561
freeRoutineResources ();
562
freeSourceFileResources ();
563
freeTagFileResources ();
564
freeOptionResources ();
565
freeParserResources ();
566
freeRegexResources ();
548
setCurrentDirectory ();
549
setExecutableName (*argv++);
552
args = cArgNewFromArgv (argv);
553
previewFirstOption (args);
554
testEtagsInvocation ();
555
initializeParsing ();
557
readOptionConfiguration ();
558
verbose ("Reading initial options from command line\n");
567
freeRoutineResources ();
568
freeSourceFileResources ();
569
freeTagFileResources ();
570
freeOptionResources ();
571
freeParserResources ();
572
freeRegexResources ();
572
/* vi:set tabstop=8 shiftwidth=4: */
578
/* vi:set tabstop=4 shiftwidth=4: */