xref: /Universal-ctags/extra-cmds/readtags-cmd.c (revision d453aacfb88c1c59e3850594e8437c4ed9b52ebf)
1c1f9ae0dSMasatake YAMATO /*
2c1f9ae0dSMasatake YAMATO *   Copyright (c) 1996-2003, Darren Hiebert
3c1f9ae0dSMasatake YAMATO *
4c1f9ae0dSMasatake YAMATO *   This source code is released into the public domain.
5c1f9ae0dSMasatake YAMATO *
6c1f9ae0dSMasatake YAMATO *   This module contains functions for reading tag files.
7c1f9ae0dSMasatake YAMATO */
8c1f9ae0dSMasatake YAMATO 
968f5fd96SMasatake YAMATO #include "general.h"
1068f5fd96SMasatake YAMATO 
11c1f9ae0dSMasatake YAMATO #include "readtags.h"
12c1f9ae0dSMasatake YAMATO #include "printtags.h"
13d5355984SMasatake YAMATO #include "routines.h"
14d5355984SMasatake YAMATO #include "routines_p.h"
15c1f9ae0dSMasatake YAMATO #include <string.h>		/* strerror */
16c1f9ae0dSMasatake YAMATO #include <stdlib.h>		/* exit */
17c1f9ae0dSMasatake YAMATO #include <stdio.h>		/* stderr */
18c1f9ae0dSMasatake YAMATO 
19c1f9ae0dSMasatake YAMATO static const char *TagFileName = "tags";
20c1f9ae0dSMasatake YAMATO static const char *ProgramName;
21c1f9ae0dSMasatake YAMATO static int extensionFields;
22c1f9ae0dSMasatake YAMATO static int SortOverride;
23c1f9ae0dSMasatake YAMATO static sortType SortMethod;
24c1f9ae0dSMasatake YAMATO static int allowPrintLineNumber;
25c1f9ae0dSMasatake YAMATO static int debugMode;
26c1f9ae0dSMasatake YAMATO static int escaping;
27c1f9ae0dSMasatake YAMATO #ifdef READTAGS_DSL
28c1f9ae0dSMasatake YAMATO #include "dsl/qualifier.h"
29c1f9ae0dSMasatake YAMATO static QCode *Qualifier;
306a93d1bcSMasatake YAMATO #include "dsl/sorter.h"
316a93d1bcSMasatake YAMATO static SCode *Sorter;
32*d453aacfSMasatake YAMATO #include "dsl/formatter.h"
33*d453aacfSMasatake YAMATO static FCode *Formatter;
34c1f9ae0dSMasatake YAMATO #endif
35c1f9ae0dSMasatake YAMATO 
tagsStrerror(int err)364adb68e3SMasatake YAMATO static const char* tagsStrerror (int err)
374adb68e3SMasatake YAMATO {
384adb68e3SMasatake YAMATO 	if (err > 0)
394adb68e3SMasatake YAMATO 		return strerror (err);
404adb68e3SMasatake YAMATO 	else if (err < 0)
414adb68e3SMasatake YAMATO 	{
424adb68e3SMasatake YAMATO 		switch (err)
434adb68e3SMasatake YAMATO 		{
444adb68e3SMasatake YAMATO 		case TagErrnoUnexpectedSortedMethod:
454adb68e3SMasatake YAMATO 			return "Unexpected sorted method";
464adb68e3SMasatake YAMATO 		case TagErrnoUnexpectedFormat:
474adb68e3SMasatake YAMATO 			return "Unexpected format number";
484adb68e3SMasatake YAMATO 		case TagErrnoUnexpectedLineno:
494adb68e3SMasatake YAMATO 			return "Unexpected value for line: field";
504adb68e3SMasatake YAMATO 		case TagErrnoInvalidArgument:
514adb68e3SMasatake YAMATO 			return "Unexpected argument passed to the API function";
524adb68e3SMasatake YAMATO 		default:
534adb68e3SMasatake YAMATO 			return "Unknown error";
544adb68e3SMasatake YAMATO 		}
554adb68e3SMasatake YAMATO 	}
564adb68e3SMasatake YAMATO 	else
574adb68e3SMasatake YAMATO 		return "no error";
584adb68e3SMasatake YAMATO }
594adb68e3SMasatake YAMATO 
printTag(const tagEntry * entry)60c1f9ae0dSMasatake YAMATO static void printTag (const tagEntry *entry)
61c1f9ae0dSMasatake YAMATO {
62c1f9ae0dSMasatake YAMATO 	tagPrintOptions opts = {
63c1f9ae0dSMasatake YAMATO 		.extensionFields = extensionFields,
64c1f9ae0dSMasatake YAMATO 		.lineNumber = allowPrintLineNumber,
65c1f9ae0dSMasatake YAMATO 		.escaping = escaping,
66c1f9ae0dSMasatake YAMATO 	};
67edacac16SMasatake YAMATO 	tagsPrint (entry, &opts, NULL, stdout);
68c1f9ae0dSMasatake YAMATO }
69c1f9ae0dSMasatake YAMATO 
70*d453aacfSMasatake YAMATO #ifdef READTAGS_DSL
printTagWithFormatter(const tagEntry * entry)71*d453aacfSMasatake YAMATO static void printTagWithFormatter (const tagEntry *entry)
72*d453aacfSMasatake YAMATO {
73*d453aacfSMasatake YAMATO 	f_print (entry, Formatter, stdout);
74*d453aacfSMasatake YAMATO }
75*d453aacfSMasatake YAMATO #endif
76*d453aacfSMasatake YAMATO 
printPseudoTag(const tagEntry * entry)77c1f9ae0dSMasatake YAMATO static void printPseudoTag (const tagEntry *entry)
78c1f9ae0dSMasatake YAMATO {
79c1f9ae0dSMasatake YAMATO 	tagPrintOptions opts = {
80c1f9ae0dSMasatake YAMATO 		.extensionFields = extensionFields,
81c1f9ae0dSMasatake YAMATO 		.lineNumber = allowPrintLineNumber,
82c1f9ae0dSMasatake YAMATO 		.escaping = escaping,
83c1f9ae0dSMasatake YAMATO 	};
84edacac16SMasatake YAMATO 	tagsPrintPseudoTag (entry, &opts, NULL, stdout);
85c1f9ae0dSMasatake YAMATO }
86c1f9ae0dSMasatake YAMATO 
876a93d1bcSMasatake YAMATO #ifdef READTAGS_DSL
freeCopiedTag(tagEntry * e)886a93d1bcSMasatake YAMATO static void freeCopiedTag (tagEntry *e)
896a93d1bcSMasatake YAMATO {
906a93d1bcSMasatake YAMATO 	free ((void *)e->name);
916a93d1bcSMasatake YAMATO 	free ((void *)e->file);
926a93d1bcSMasatake YAMATO 	if (e->address.pattern)
936a93d1bcSMasatake YAMATO 		free ((void *)e->address.pattern);
946a93d1bcSMasatake YAMATO 	if (e->kind)
956a93d1bcSMasatake YAMATO 		free ((void *)e->kind);
966a93d1bcSMasatake YAMATO 	for (unsigned short c = 0; c < e->fields.count; c++)
976a93d1bcSMasatake YAMATO 	{
986a93d1bcSMasatake YAMATO 		free ((void *)e->fields.list[c].key);
996a93d1bcSMasatake YAMATO 		free ((void *)e->fields.list[c].value);
1006a93d1bcSMasatake YAMATO 	}
1016a93d1bcSMasatake YAMATO 	if (e->fields.count)
1026a93d1bcSMasatake YAMATO 		free ((void *)e->fields.list);
1036a93d1bcSMasatake YAMATO 	free ((void *)e);
1046a93d1bcSMasatake YAMATO }
1056a93d1bcSMasatake YAMATO 
copyTag(tagEntry * o)1066a93d1bcSMasatake YAMATO static tagEntry *copyTag (tagEntry *o)
1076a93d1bcSMasatake YAMATO {
1086a93d1bcSMasatake YAMATO 	tagEntry *n;
1096a93d1bcSMasatake YAMATO 
1106a93d1bcSMasatake YAMATO 	n = calloc (1, sizeof  (*o));
1116a93d1bcSMasatake YAMATO 	if (!n)
1126a93d1bcSMasatake YAMATO 		perror (__FUNCTION__);
1136a93d1bcSMasatake YAMATO 
1146a93d1bcSMasatake YAMATO 	n->name = strdup (o->name);
1156a93d1bcSMasatake YAMATO 
1166a93d1bcSMasatake YAMATO 	if (!n->name)
1176a93d1bcSMasatake YAMATO 		perror (__FUNCTION__);
1186a93d1bcSMasatake YAMATO 
1196a93d1bcSMasatake YAMATO 	if (o->file)
1206a93d1bcSMasatake YAMATO 		n->file = strdup (o->file);
1216a93d1bcSMasatake YAMATO 	if (o->file && !n->file)
1226a93d1bcSMasatake YAMATO 		perror (__FUNCTION__);
1236a93d1bcSMasatake YAMATO 
1246a93d1bcSMasatake YAMATO 	if (o->address.pattern)
1256a93d1bcSMasatake YAMATO 	{
1266a93d1bcSMasatake YAMATO 		n->address.pattern = strdup (o->address.pattern);
1276a93d1bcSMasatake YAMATO 		if (!n->address.pattern)
1286a93d1bcSMasatake YAMATO 			perror (__FUNCTION__);
1296a93d1bcSMasatake YAMATO 	}
1306a93d1bcSMasatake YAMATO 
1316a93d1bcSMasatake YAMATO 	n->address.lineNumber = o->address.lineNumber;
1326a93d1bcSMasatake YAMATO 
1336a93d1bcSMasatake YAMATO 	if (o->kind)
1346a93d1bcSMasatake YAMATO 	{
1356a93d1bcSMasatake YAMATO 		n->kind = strdup (o->kind);
1366a93d1bcSMasatake YAMATO 		if (!n->kind)
1376a93d1bcSMasatake YAMATO 			perror (__FUNCTION__);
1386a93d1bcSMasatake YAMATO 	}
1396a93d1bcSMasatake YAMATO 
1406a93d1bcSMasatake YAMATO 	n->fileScope = o->fileScope;
1416a93d1bcSMasatake YAMATO 	n->fields.count = o->fields.count;
1426a93d1bcSMasatake YAMATO 
1436a93d1bcSMasatake YAMATO 	if (o->fields.count == 0)
1446a93d1bcSMasatake YAMATO 		return n;
1456a93d1bcSMasatake YAMATO 
1466a93d1bcSMasatake YAMATO 	n->fields.list = malloc (o->fields.count *sizeof (*o->fields.list));
1476a93d1bcSMasatake YAMATO 	if (!n->fields.list)
1486a93d1bcSMasatake YAMATO 		perror (__FUNCTION__);
1496a93d1bcSMasatake YAMATO 
1506a93d1bcSMasatake YAMATO 	for (unsigned short c = 0; c < o->fields.count; c++)
1516a93d1bcSMasatake YAMATO 	{
1526a93d1bcSMasatake YAMATO 		n->fields.list[c].key = strdup (o->fields.list[c].key);
1536a93d1bcSMasatake YAMATO 		if (!n->fields.list[c].key)
1546a93d1bcSMasatake YAMATO 			perror (__FUNCTION__);
1556a93d1bcSMasatake YAMATO 
1566a93d1bcSMasatake YAMATO 		n->fields.list[c].value = strdup (o->fields.list[c].value);
1576a93d1bcSMasatake YAMATO 		if (!n->fields.list[c].value)
1586a93d1bcSMasatake YAMATO 			perror (__FUNCTION__);
1596a93d1bcSMasatake YAMATO 	}
1606a93d1bcSMasatake YAMATO 
1616a93d1bcSMasatake YAMATO 	return n;
1626a93d1bcSMasatake YAMATO }
1636a93d1bcSMasatake YAMATO 
1646a93d1bcSMasatake YAMATO struct tagEntryHolder {
1656a93d1bcSMasatake YAMATO 	tagEntry *e;
1666a93d1bcSMasatake YAMATO };
1676a93d1bcSMasatake YAMATO struct tagEntryArray {
1686a93d1bcSMasatake YAMATO 	int count;
1696a93d1bcSMasatake YAMATO 	int length;
1706a93d1bcSMasatake YAMATO 	struct tagEntryHolder *a;
1716a93d1bcSMasatake YAMATO };
1726a93d1bcSMasatake YAMATO 
tagEntryArrayNew(void)1736a93d1bcSMasatake YAMATO struct tagEntryArray *tagEntryArrayNew (void)
1746a93d1bcSMasatake YAMATO {
1756a93d1bcSMasatake YAMATO 	struct tagEntryArray * a = malloc (sizeof (struct tagEntryArray));
1766a93d1bcSMasatake YAMATO 	if (!a)
1776a93d1bcSMasatake YAMATO 		perror(__FUNCTION__);
1786a93d1bcSMasatake YAMATO 
1796a93d1bcSMasatake YAMATO 	a->count = 0;
1806a93d1bcSMasatake YAMATO 	a->length = 1024;
1816a93d1bcSMasatake YAMATO 	a->a = malloc(a->length * sizeof (a->a[0]));
1826a93d1bcSMasatake YAMATO 	if (!a->a)
1836a93d1bcSMasatake YAMATO 		perror(__FUNCTION__);
1846a93d1bcSMasatake YAMATO 
1856a93d1bcSMasatake YAMATO 	return a;
1866a93d1bcSMasatake YAMATO }
1876a93d1bcSMasatake YAMATO 
tagEntryArrayPush(struct tagEntryArray * a,tagEntry * e)1886a93d1bcSMasatake YAMATO void tagEntryArrayPush (struct tagEntryArray *a, tagEntry *e)
1896a93d1bcSMasatake YAMATO {
1906a93d1bcSMasatake YAMATO 	if (a->count + 1 == a->length)
1916a93d1bcSMasatake YAMATO 	{
1926a93d1bcSMasatake YAMATO 		if (a->length * 2 < a->length)
1936a93d1bcSMasatake YAMATO 			perror("Too large array allocation");
1946a93d1bcSMasatake YAMATO 
1956a93d1bcSMasatake YAMATO 		struct tagEntryHolder *tmp = realloc (a->a, sizeof (a->a[0]) * (a->length * 2));
1966a93d1bcSMasatake YAMATO 		if (!tmp)
1976a93d1bcSMasatake YAMATO 			perror(__FUNCTION__);
1986a93d1bcSMasatake YAMATO 
1996a93d1bcSMasatake YAMATO 		a->a = tmp;
2006a93d1bcSMasatake YAMATO 		a->length *= 2;
2016a93d1bcSMasatake YAMATO 	}
2026a93d1bcSMasatake YAMATO 
2036a93d1bcSMasatake YAMATO 	a->a[a->count++].e = e;
2046a93d1bcSMasatake YAMATO }
2056a93d1bcSMasatake YAMATO 
tagEntryArrayFree(struct tagEntryArray * a,int freeTags)2066a93d1bcSMasatake YAMATO void tagEntryArrayFree (struct tagEntryArray *a, int freeTags)
2076a93d1bcSMasatake YAMATO {
2086a93d1bcSMasatake YAMATO 	if (freeTags)
2096a93d1bcSMasatake YAMATO 	{
2106a93d1bcSMasatake YAMATO 		for (int i = 0; i < a->count; i++)
2116a93d1bcSMasatake YAMATO 			freeCopiedTag (a->a[i].e);
2126a93d1bcSMasatake YAMATO 	}
2136a93d1bcSMasatake YAMATO 	free (a->a);
2146a93d1bcSMasatake YAMATO 	free (a);
2156a93d1bcSMasatake YAMATO }
2166a93d1bcSMasatake YAMATO 
compareTagEntry(const void * a,const void * b)2176a93d1bcSMasatake YAMATO static int compareTagEntry (const void *a, const void *b)
2186a93d1bcSMasatake YAMATO {
2196a93d1bcSMasatake YAMATO 	return s_compare (((struct tagEntryHolder *)a)->e, ((struct tagEntryHolder *)b)->e, Sorter);
2206a93d1bcSMasatake YAMATO }
2216a93d1bcSMasatake YAMATO 
walkTags(tagFile * const file,tagEntry * first_entry,tagResult (* nextfn)(tagFile * const,tagEntry *),void (* actionfn)(const tagEntry *))222c1f9ae0dSMasatake YAMATO static void walkTags (tagFile *const file, tagEntry *first_entry,
223c1f9ae0dSMasatake YAMATO 					  tagResult (* nextfn) (tagFile *const, tagEntry *),
224c1f9ae0dSMasatake YAMATO 					  void (* actionfn) (const tagEntry *))
225c1f9ae0dSMasatake YAMATO {
2266a93d1bcSMasatake YAMATO 	struct tagEntryArray *a = NULL;
2276a93d1bcSMasatake YAMATO 
2286a93d1bcSMasatake YAMATO 	if (Sorter)
2296a93d1bcSMasatake YAMATO 		a = tagEntryArrayNew ();
2306a93d1bcSMasatake YAMATO 
231c1f9ae0dSMasatake YAMATO 	do
232c1f9ae0dSMasatake YAMATO 	{
233c1f9ae0dSMasatake YAMATO 		if (Qualifier)
234c1f9ae0dSMasatake YAMATO 		{
235c1f9ae0dSMasatake YAMATO 			int i = q_is_acceptable (Qualifier, first_entry);
236c1f9ae0dSMasatake YAMATO 			switch (i)
237c1f9ae0dSMasatake YAMATO 			{
238c1f9ae0dSMasatake YAMATO 			case Q_REJECT:
239c1f9ae0dSMasatake YAMATO 				continue;
240c1f9ae0dSMasatake YAMATO 			case Q_ERROR:
241c1f9ae0dSMasatake YAMATO 				exit (1);
242c1f9ae0dSMasatake YAMATO 			}
243c1f9ae0dSMasatake YAMATO 		}
2446a93d1bcSMasatake YAMATO 
2456a93d1bcSMasatake YAMATO 		if (a)
2466a93d1bcSMasatake YAMATO 		{
2476a93d1bcSMasatake YAMATO 			tagEntry *e = copyTag (first_entry);
2486a93d1bcSMasatake YAMATO 			tagEntryArrayPush (a, e);
2496a93d1bcSMasatake YAMATO 		}
2506a93d1bcSMasatake YAMATO 		else
251c1f9ae0dSMasatake YAMATO 			(* actionfn) (first_entry);
252c1f9ae0dSMasatake YAMATO 	} while ( (*nextfn) (file, first_entry) == TagSuccess);
2536a93d1bcSMasatake YAMATO 
2544adb68e3SMasatake YAMATO 	int err = tagsGetErrno (file);
2554adb68e3SMasatake YAMATO 	if (err != 0)
2564adb68e3SMasatake YAMATO 	{
2574adb68e3SMasatake YAMATO 		fprintf (stderr, "%s: error in walktTags(): %s\n",
2584adb68e3SMasatake YAMATO 				 ProgramName,
2594adb68e3SMasatake YAMATO 				 tagsStrerror (err));
2604adb68e3SMasatake YAMATO 		exit (1);
2614adb68e3SMasatake YAMATO 	}
2626a93d1bcSMasatake YAMATO 
2636a93d1bcSMasatake YAMATO 	if (a)
2646a93d1bcSMasatake YAMATO 	{
2656a93d1bcSMasatake YAMATO 		qsort (a->a, a->count, sizeof (a->a[0]), compareTagEntry);
2666a93d1bcSMasatake YAMATO 		for (int i = 0; i < a->count; i++)
2676a93d1bcSMasatake YAMATO 			(* actionfn) (a->a[i].e);
2686a93d1bcSMasatake YAMATO 		tagEntryArrayFree (a, 1);
269c1f9ae0dSMasatake YAMATO 	}
2706a93d1bcSMasatake YAMATO }
2716a93d1bcSMasatake YAMATO #else
walkTags(tagFile * const file,tagEntry * first_entry,tagResult (* nextfn)(tagFile * const,tagEntry *),void (* actionfn)(const tagEntry *))2726a93d1bcSMasatake YAMATO static void walkTags (tagFile *const file, tagEntry *first_entry,
2736a93d1bcSMasatake YAMATO 					  tagResult (* nextfn) (tagFile *const, tagEntry *),
2746a93d1bcSMasatake YAMATO 					  void (* actionfn) (const tagEntry *))
2756a93d1bcSMasatake YAMATO {
2766a93d1bcSMasatake YAMATO 	do
2776a93d1bcSMasatake YAMATO 		(* actionfn) (first_entry);
2786a93d1bcSMasatake YAMATO 	while ( (*nextfn) (file, first_entry) == TagSuccess);
2794adb68e3SMasatake YAMATO 
2804adb68e3SMasatake YAMATO 	int err = tagsGetErrno (file);
2814adb68e3SMasatake YAMATO 	if (err != 0)
2824adb68e3SMasatake YAMATO 	{
2834adb68e3SMasatake YAMATO 		fprintf (stderr, "%s: error in walktTags(): %s\n",
2844adb68e3SMasatake YAMATO 				 ProgramName,
2854adb68e3SMasatake YAMATO 				 tagsStrerror (err));
2864adb68e3SMasatake YAMATO 		exit (1);
2874adb68e3SMasatake YAMATO 	}
2886a93d1bcSMasatake YAMATO }
2896a93d1bcSMasatake YAMATO #endif
290c1f9ae0dSMasatake YAMATO 
copyFile(FILE * in,FILE * out)291d5355984SMasatake YAMATO static int copyFile (FILE *in, FILE *out)
292d5355984SMasatake YAMATO {
293d5355984SMasatake YAMATO #define BUFSIZE (4096 * 10)
294d5355984SMasatake YAMATO 	static unsigned char buffer [BUFSIZE];
295d5355984SMasatake YAMATO 
296d5355984SMasatake YAMATO 	while (1)
297d5355984SMasatake YAMATO 	{
298d5355984SMasatake YAMATO 		size_t r, t;
299d5355984SMasatake YAMATO 
300d5355984SMasatake YAMATO 		r = fread (buffer, 1, BUFSIZE, in);
301d5355984SMasatake YAMATO 		if (!r)
302d5355984SMasatake YAMATO 		{
303d5355984SMasatake YAMATO 			if (ferror(in))
304d5355984SMasatake YAMATO 			{
305d5355984SMasatake YAMATO 				fprintf (stderr, "%s: error in reading from stdin\n", ProgramName);
306d5355984SMasatake YAMATO 				return -1;
307d5355984SMasatake YAMATO 			}
308d5355984SMasatake YAMATO 			/* EOF */
309d5355984SMasatake YAMATO 			break;
310d5355984SMasatake YAMATO 		}
311d5355984SMasatake YAMATO 		t = fwrite (buffer, 1, r, out);
312d5355984SMasatake YAMATO 		if (r != t)
313d5355984SMasatake YAMATO 		{
314d5355984SMasatake YAMATO 			fprintf (stderr, "%s error in writing to the temporarily file", ProgramName);
315d5355984SMasatake YAMATO 			return -1;
316d5355984SMasatake YAMATO 		}
317d5355984SMasatake YAMATO 	}
318d5355984SMasatake YAMATO 	return 0;
319d5355984SMasatake YAMATO }
320d5355984SMasatake YAMATO 
removeTagFile(void)321d5355984SMasatake YAMATO static void removeTagFile (void)
322d5355984SMasatake YAMATO {
323d5355984SMasatake YAMATO 	remove (TagFileName);
324d5355984SMasatake YAMATO 	eFree ((char *)TagFileName);
325d5355984SMasatake YAMATO }
326d5355984SMasatake YAMATO 
openTags(const char * const filePath,tagFileInfo * const info)327d5355984SMasatake YAMATO static tagFile *openTags (const char *const filePath, tagFileInfo *const info)
328d5355984SMasatake YAMATO {
329d5355984SMasatake YAMATO 	if (strcmp (filePath, "-") == 0)
330d5355984SMasatake YAMATO 	{
331d5355984SMasatake YAMATO 		char *tempName = NULL;
332d5355984SMasatake YAMATO 		FILE *tempFP = tempFileFP ("w", &tempName);
333d5355984SMasatake YAMATO 
334d5355984SMasatake YAMATO 		if (tempFP == NULL)
335d5355984SMasatake YAMATO 		{
336d5355984SMasatake YAMATO 			fprintf (stderr, "%s: failed to make a temporarily file for storing data from stdin\n",
337d5355984SMasatake YAMATO 					 ProgramName);
338d5355984SMasatake YAMATO 			exit (1);
339d5355984SMasatake YAMATO 		}
340d5355984SMasatake YAMATO 		TagFileName = tempName;
341d5355984SMasatake YAMATO 		atexit (removeTagFile);
342d5355984SMasatake YAMATO 
343d5355984SMasatake YAMATO 		if (copyFile (stdin, tempFP) < 0)
344d5355984SMasatake YAMATO 		{
345d5355984SMasatake YAMATO 			fclose (tempFP);
346d5355984SMasatake YAMATO 			exit (1);
347d5355984SMasatake YAMATO 		}
348d5355984SMasatake YAMATO 
349d5355984SMasatake YAMATO 		if (fflush (tempFP) < 0)
350d5355984SMasatake YAMATO 		{
351d5355984SMasatake YAMATO 			fprintf (stderr, "%s: failed to flush a temporarily file for storing data from stdin\n",
352d5355984SMasatake YAMATO 					 ProgramName);
353d5355984SMasatake YAMATO 			exit (1);
354d5355984SMasatake YAMATO 		}
355d5355984SMasatake YAMATO 		fclose (tempFP);
356d5355984SMasatake YAMATO 		return tagsOpen (tempName, info);
357d5355984SMasatake YAMATO 	}
358d5355984SMasatake YAMATO 
359d5355984SMasatake YAMATO 	return tagsOpen (filePath, info);
360d5355984SMasatake YAMATO }
361d5355984SMasatake YAMATO 
findTag(const char * const name,const int options)362c1f9ae0dSMasatake YAMATO static void findTag (const char *const name, const int options)
363c1f9ae0dSMasatake YAMATO {
364c1f9ae0dSMasatake YAMATO 	tagFileInfo info;
365c1f9ae0dSMasatake YAMATO 	tagEntry entry;
366d5355984SMasatake YAMATO 	tagFile *const file = openTags (TagFileName, &info);
3674adb68e3SMasatake YAMATO 	if (file == NULL || !info.status.opened)
368c1f9ae0dSMasatake YAMATO 	{
369c1f9ae0dSMasatake YAMATO 		fprintf (stderr, "%s: cannot open tag file: %s: %s\n",
3704adb68e3SMasatake YAMATO 				 ProgramName, tagsStrerror (info.status.error_number), TagFileName);
3714adb68e3SMasatake YAMATO 		if (file)
3724adb68e3SMasatake YAMATO 			tagsClose (file);
373c1f9ae0dSMasatake YAMATO 		exit (1);
374c1f9ae0dSMasatake YAMATO 	}
375c1f9ae0dSMasatake YAMATO 	else
376c1f9ae0dSMasatake YAMATO 	{
3774adb68e3SMasatake YAMATO 		int err = 0;
378c1f9ae0dSMasatake YAMATO 		if (SortOverride)
3794adb68e3SMasatake YAMATO 		{
3804adb68e3SMasatake YAMATO 			if (tagsSetSortType (file, SortMethod) != TagSuccess)
3814adb68e3SMasatake YAMATO 			{
3824adb68e3SMasatake YAMATO 				err = tagsGetErrno (file);
3834adb68e3SMasatake YAMATO 				fprintf (stderr, "%s: cannot set sort type to %d: %s\n",
3844adb68e3SMasatake YAMATO 						 ProgramName,
3854adb68e3SMasatake YAMATO 						 SortMethod,
3864adb68e3SMasatake YAMATO 						 tagsStrerror (err));
3874adb68e3SMasatake YAMATO 				exit (1);
3884adb68e3SMasatake YAMATO 			}
3894adb68e3SMasatake YAMATO 		}
390c1f9ae0dSMasatake YAMATO 		if (debugMode)
391c1f9ae0dSMasatake YAMATO 			fprintf (stderr, "%s: searching for \"%s\" in \"%s\"\n",
392c1f9ae0dSMasatake YAMATO 					 ProgramName, name, TagFileName);
393c1f9ae0dSMasatake YAMATO 		if (tagsFind (file, &entry, name, options) == TagSuccess)
394*d453aacfSMasatake YAMATO 			walkTags (file, &entry, tagsFindNext,
395*d453aacfSMasatake YAMATO #ifdef READTAGS_DSL
396*d453aacfSMasatake YAMATO 					  Formatter? printTagWithFormatter:
397*d453aacfSMasatake YAMATO #endif
398*d453aacfSMasatake YAMATO 					  printTag);
3994adb68e3SMasatake YAMATO 		else if ((err = tagsGetErrno (file)) != 0)
4004adb68e3SMasatake YAMATO 		{
4014adb68e3SMasatake YAMATO 			fprintf (stderr, "%s: error in tagsFind(): %s\n",
4024adb68e3SMasatake YAMATO 					 ProgramName,
4034adb68e3SMasatake YAMATO 					 tagsStrerror (err));
4044adb68e3SMasatake YAMATO 			exit (1);
4054adb68e3SMasatake YAMATO 		}
406c1f9ae0dSMasatake YAMATO 		tagsClose (file);
407c1f9ae0dSMasatake YAMATO 	}
408c1f9ae0dSMasatake YAMATO }
409c1f9ae0dSMasatake YAMATO 
listTags(int pseudoTags)410c1f9ae0dSMasatake YAMATO static void listTags (int pseudoTags)
411c1f9ae0dSMasatake YAMATO {
412c1f9ae0dSMasatake YAMATO 	tagFileInfo info;
413c1f9ae0dSMasatake YAMATO 	tagEntry entry;
414d5355984SMasatake YAMATO 	tagFile *const file = openTags (TagFileName, &info);
4154adb68e3SMasatake YAMATO 	if (file == NULL || !info.status.opened)
416c1f9ae0dSMasatake YAMATO 	{
417c1f9ae0dSMasatake YAMATO 		fprintf (stderr, "%s: cannot open tag file: %s: %s\n",
4184adb68e3SMasatake YAMATO 				 ProgramName,
4194adb68e3SMasatake YAMATO 				 tagsStrerror (info.status.error_number),
4204adb68e3SMasatake YAMATO 				 TagFileName);
4214adb68e3SMasatake YAMATO 		if (file)
4224adb68e3SMasatake YAMATO 			tagsClose (file);
423c1f9ae0dSMasatake YAMATO 		exit (1);
424c1f9ae0dSMasatake YAMATO 	}
425c1f9ae0dSMasatake YAMATO 	else if (pseudoTags)
426c1f9ae0dSMasatake YAMATO 	{
4274adb68e3SMasatake YAMATO 		int err = 0;
428c1f9ae0dSMasatake YAMATO 		if (tagsFirstPseudoTag (file, &entry) == TagSuccess)
429c1f9ae0dSMasatake YAMATO 			walkTags (file, &entry, tagsNextPseudoTag, printPseudoTag);
4304adb68e3SMasatake YAMATO 		else if ((err = tagsGetErrno (file)) != 0)
4314adb68e3SMasatake YAMATO 		{
4324adb68e3SMasatake YAMATO 			fprintf (stderr, "%s: error in tagsFirstPseudoTag(): %s\n",
4334adb68e3SMasatake YAMATO 					 ProgramName,
4344adb68e3SMasatake YAMATO 					 tagsStrerror (err));
4354adb68e3SMasatake YAMATO 			exit (1);
4364adb68e3SMasatake YAMATO 		}
437c1f9ae0dSMasatake YAMATO 		tagsClose (file);
438c1f9ae0dSMasatake YAMATO 	}
439c1f9ae0dSMasatake YAMATO 	else
440c1f9ae0dSMasatake YAMATO 	{
4414adb68e3SMasatake YAMATO 		int err = 0;
442c1f9ae0dSMasatake YAMATO 		if (tagsFirst (file, &entry) == TagSuccess)
443*d453aacfSMasatake YAMATO 			walkTags (file, &entry, tagsNext,
444*d453aacfSMasatake YAMATO #ifdef READTAGS_DSL
445*d453aacfSMasatake YAMATO 					  Formatter? printTagWithFormatter:
446*d453aacfSMasatake YAMATO #endif
447*d453aacfSMasatake YAMATO 					  printTag);
4484adb68e3SMasatake YAMATO 		else if ((err = tagsGetErrno (file)) != 0)
4494adb68e3SMasatake YAMATO 		{
4504adb68e3SMasatake YAMATO 			fprintf (stderr, "%s: error in tagsFirst(): %s\n",
4514adb68e3SMasatake YAMATO 					 ProgramName,
4524adb68e3SMasatake YAMATO 					 tagsStrerror (err));
4534adb68e3SMasatake YAMATO 			exit (1);
4544adb68e3SMasatake YAMATO 		}
455c1f9ae0dSMasatake YAMATO 		tagsClose (file);
456c1f9ae0dSMasatake YAMATO 	}
457c1f9ae0dSMasatake YAMATO }
458c1f9ae0dSMasatake YAMATO 
459c1f9ae0dSMasatake YAMATO static const char *const Usage =
460c1f9ae0dSMasatake YAMATO 	"Find tag file entries matching specified names.\n\n"
461c1f9ae0dSMasatake YAMATO 	"Usage: \n"
462c1f9ae0dSMasatake YAMATO 	"    %s -h | --help\n"
463c1f9ae0dSMasatake YAMATO 	"        Print this help message.\n"
464c1f9ae0dSMasatake YAMATO #ifdef READTAGS_DSL
465c1f9ae0dSMasatake YAMATO 	"    %s -H POSTPROCESSOR | --help-expression POSTPROCESSOR\n"
466c1f9ae0dSMasatake YAMATO 	"        Print available terms that can be used in POSTPROCESSOR expression.\n"
467*d453aacfSMasatake YAMATO 	"        POSTPROCESSOR: filter sorter formatter\n"
468c1f9ae0dSMasatake YAMATO #endif
469c1f9ae0dSMasatake YAMATO 	"    %s [OPTIONS] ACTION\n"
470c1f9ae0dSMasatake YAMATO 	"        Do the specified action.\n"
471c1f9ae0dSMasatake YAMATO 	"Actions:\n"
472c1f9ae0dSMasatake YAMATO 	"    -l | --list\n"
473c1f9ae0dSMasatake YAMATO 	"        List regular tags.\n"
474c1f9ae0dSMasatake YAMATO 	"    [-] NAME...\n"
475c1f9ae0dSMasatake YAMATO 	"        List regular tags matching NAME(s).\n"
476c1f9ae0dSMasatake YAMATO 	"        \"-\" indicates arguments after this as NAME(s) even if they start with -.\n"
477c1f9ae0dSMasatake YAMATO 	"    -D | --list-pseudo-tags\n"
478c1f9ae0dSMasatake YAMATO 	"        List pseudo tags.\n"
479c1f9ae0dSMasatake YAMATO 	"Options:\n"
480c1f9ae0dSMasatake YAMATO 	"    -d | --debug\n"
481c1f9ae0dSMasatake YAMATO 	"        Turn on debugging output.\n"
482c1f9ae0dSMasatake YAMATO 	"    -E | --escape-output\n"
483c1f9ae0dSMasatake YAMATO 	"        Escape characters like tabs in output as described in tags(5).\n"
484c1f9ae0dSMasatake YAMATO 	"    -e | --extension-fields\n"
485c1f9ae0dSMasatake YAMATO 	"        Include extension fields in output.\n"
486c1f9ae0dSMasatake YAMATO 	"    -i | --icase-match\n"
487c1f9ae0dSMasatake YAMATO 	"        Perform case-insensitive matching in the NAME action.\n"
488c1f9ae0dSMasatake YAMATO 	"    -n | --line-number\n"
489c1f9ae0dSMasatake YAMATO 	"        Also include the line number field when -e option is given.\n"
490c1f9ae0dSMasatake YAMATO 	"    -p | --prefix-match\n"
491c1f9ae0dSMasatake YAMATO 	"        Perform prefix matching in the NAME action.\n"
492c1f9ae0dSMasatake YAMATO 	"    -t TAGFILE | --tag-file TAGFILE\n"
493c1f9ae0dSMasatake YAMATO 	"        Use specified tag file (default: \"tags\").\n"
494d5355984SMasatake YAMATO 	"        \"-\" indicates taking tag file data from standard input.\n"
495c1f9ae0dSMasatake YAMATO 	"    -s[0|1|2] | --override-sort-detection METHOD\n"
496c1f9ae0dSMasatake YAMATO 	"        Override sort detection of tag file.\n"
497c1f9ae0dSMasatake YAMATO 	"        METHOD: unsorted|sorted|foldcase\n"
498c1f9ae0dSMasatake YAMATO #ifdef READTAGS_DSL
499*d453aacfSMasatake YAMATO 	"    -F EXP | --formatter EXP\n"
500*d453aacfSMasatake YAMATO 	"        Format the tags listed by ACTION with EXP when printing.\n"
501c1f9ae0dSMasatake YAMATO 	"    -Q EXP | --filter EXP\n"
502c1f9ae0dSMasatake YAMATO 	"        Filter the tags listed by ACTION with EXP before printing.\n"
5036a93d1bcSMasatake YAMATO 	"    -S EXP | --sorter EXP\n"
5046a93d1bcSMasatake YAMATO 	"        Sort the tags listed by ACTION with EXP before printing.\n"
505c1f9ae0dSMasatake YAMATO #endif
506c1f9ae0dSMasatake YAMATO 	;
507c1f9ae0dSMasatake YAMATO 
printUsage(FILE * stream,int exitCode)508c1f9ae0dSMasatake YAMATO static void printUsage(FILE* stream, int exitCode)
509c1f9ae0dSMasatake YAMATO {
5107b006d1aSMasatake YAMATO 	fprintf (stream, Usage, ProgramName,
5117b006d1aSMasatake YAMATO #ifdef READTAGS_DSL
5127b006d1aSMasatake YAMATO 			 ProgramName,
5137b006d1aSMasatake YAMATO #endif
5147b006d1aSMasatake YAMATO 			 ProgramName);
515c1f9ae0dSMasatake YAMATO 	exit (exitCode);
516c1f9ae0dSMasatake YAMATO }
517c1f9ae0dSMasatake YAMATO 
518c1f9ae0dSMasatake YAMATO #ifdef READTAGS_DSL
printFilterExpression(FILE * stream,int exitCode)519c1f9ae0dSMasatake YAMATO static void printFilterExpression (FILE *stream, int exitCode)
520c1f9ae0dSMasatake YAMATO {
521c1f9ae0dSMasatake YAMATO 	fprintf (stream, "Filter expression: \n");
522c1f9ae0dSMasatake YAMATO 	q_help (stream);
523c1f9ae0dSMasatake YAMATO 	exit (exitCode);
524c1f9ae0dSMasatake YAMATO }
525c1f9ae0dSMasatake YAMATO 
printSorterExpression(FILE * stream,int exitCode)5266a93d1bcSMasatake YAMATO static void printSorterExpression (FILE *stream, int exitCode)
5276a93d1bcSMasatake YAMATO {
5286a93d1bcSMasatake YAMATO 	fprintf (stream, "Sorter expression: \n");
5296a93d1bcSMasatake YAMATO 	s_help (stream);
5306a93d1bcSMasatake YAMATO 	exit (exitCode);
5316a93d1bcSMasatake YAMATO }
5326a93d1bcSMasatake YAMATO 
printFormatterExpression(FILE * stream,int exitCode)533*d453aacfSMasatake YAMATO static void printFormatterExpression (FILE *stream, int exitCode)
534*d453aacfSMasatake YAMATO {
535*d453aacfSMasatake YAMATO 	fprintf (stream, "Formatter expression: \n");
536*d453aacfSMasatake YAMATO 	f_help (stream);
537*d453aacfSMasatake YAMATO 	exit (exitCode);
538*d453aacfSMasatake YAMATO }
539*d453aacfSMasatake YAMATO 
compileExpression(const char * exp,void * (* compiler)(EsObject *),const char * compiler_name)540dafe0ab9SMasatake YAMATO static void *compileExpression(const char* exp, void * (*compiler) (EsObject *),
541dafe0ab9SMasatake YAMATO 							   const char *compiler_name)
542c1f9ae0dSMasatake YAMATO {
543c1f9ae0dSMasatake YAMATO 	EsObject *sexp = es_read_from_string (exp, NULL);
544dafe0ab9SMasatake YAMATO 	void *code;
545c1f9ae0dSMasatake YAMATO 
546c1f9ae0dSMasatake YAMATO 	if (es_error_p (sexp))
547c1f9ae0dSMasatake YAMATO 	{
548c1f9ae0dSMasatake YAMATO 		fprintf (stderr,
549dafe0ab9SMasatake YAMATO 				 "Failed to read the expression for %s: %s\n", compiler_name, exp);
550c1f9ae0dSMasatake YAMATO 		fprintf (stderr,
551c1f9ae0dSMasatake YAMATO 				 "Reason: %s\n", es_error_name (sexp));
552c1f9ae0dSMasatake YAMATO 		exit (1);
553c1f9ae0dSMasatake YAMATO 	}
554c1f9ae0dSMasatake YAMATO 
555dafe0ab9SMasatake YAMATO 	code = compiler (sexp);
556dafe0ab9SMasatake YAMATO 	if (code == NULL)
557c1f9ae0dSMasatake YAMATO 	{
558c1f9ae0dSMasatake YAMATO 		fprintf (stderr,
559dafe0ab9SMasatake YAMATO 				 "Failed to compile the expression of %s: %s\n", compiler_name, exp);
560c1f9ae0dSMasatake YAMATO 		exit (1);
561c1f9ae0dSMasatake YAMATO 	}
562c1f9ae0dSMasatake YAMATO 	es_object_unref (sexp);
563dafe0ab9SMasatake YAMATO 	return code;
564c1f9ae0dSMasatake YAMATO }
565c1f9ae0dSMasatake YAMATO #endif
5666a93d1bcSMasatake YAMATO 
main(int argc,char ** argv)567c1f9ae0dSMasatake YAMATO extern int main (int argc, char **argv)
568c1f9ae0dSMasatake YAMATO {
569c1f9ae0dSMasatake YAMATO 	int options = 0;
570c1f9ae0dSMasatake YAMATO 	int actionSupplied = 0;
571c1f9ae0dSMasatake YAMATO 	int i;
572c1f9ae0dSMasatake YAMATO 	int ignore_prefix = 0;
573c1f9ae0dSMasatake YAMATO 
574c1f9ae0dSMasatake YAMATO 	ProgramName = argv [0];
575d5355984SMasatake YAMATO 	setExecutableName (ProgramName);
576c1f9ae0dSMasatake YAMATO 	if (argc == 1)
577c1f9ae0dSMasatake YAMATO 		printUsage(stderr, 1);
578c1f9ae0dSMasatake YAMATO 	for (i = 1  ;  i < argc  ;  ++i)
579c1f9ae0dSMasatake YAMATO 	{
580c1f9ae0dSMasatake YAMATO 		const char *const arg = argv [i];
581c1f9ae0dSMasatake YAMATO 		if (ignore_prefix || arg [0] != '-')
582c1f9ae0dSMasatake YAMATO 		{
583c1f9ae0dSMasatake YAMATO 			findTag (arg, options);
584c1f9ae0dSMasatake YAMATO 			actionSupplied = 1;
585c1f9ae0dSMasatake YAMATO 		}
586c1f9ae0dSMasatake YAMATO 		else if (arg [0] == '-' && arg [1] == '\0')
587c1f9ae0dSMasatake YAMATO 			ignore_prefix = 1;
588c1f9ae0dSMasatake YAMATO 		else if (arg [0] == '-' && arg [1] == '-')
589c1f9ae0dSMasatake YAMATO 		{
590c1f9ae0dSMasatake YAMATO 			const char *optname = arg + 2;
591c1f9ae0dSMasatake YAMATO 			if (strcmp (optname, "debug") == 0)
592c1f9ae0dSMasatake YAMATO 				debugMode++;
593c1f9ae0dSMasatake YAMATO 			else if (strcmp (optname, "list-pseudo-tags") == 0)
594c1f9ae0dSMasatake YAMATO 			{
595c1f9ae0dSMasatake YAMATO 				listTags (1);
596c1f9ae0dSMasatake YAMATO 				actionSupplied = 1;
597c1f9ae0dSMasatake YAMATO 			}
598c1f9ae0dSMasatake YAMATO 			else if (strcmp (optname, "help") == 0)
599c1f9ae0dSMasatake YAMATO 				printUsage (stdout, 0);
600c1f9ae0dSMasatake YAMATO #ifdef READTAGS_DSL
601c1f9ae0dSMasatake YAMATO 			else if (strcmp (optname, "help-expression") == 0)
602c1f9ae0dSMasatake YAMATO 			{
603c1f9ae0dSMasatake YAMATO 				if (i + 1 < argc)
604c1f9ae0dSMasatake YAMATO 				{
605c1f9ae0dSMasatake YAMATO 					const char *exp_klass = argv [++i];
606c1f9ae0dSMasatake YAMATO 					if (strcmp (exp_klass, "filter") == 0)
607c1f9ae0dSMasatake YAMATO 						printFilterExpression (stdout, 0);
6086a93d1bcSMasatake YAMATO 					if (strcmp (exp_klass, "sorter") == 0)
6096a93d1bcSMasatake YAMATO 						printSorterExpression (stdout, 0);
610*d453aacfSMasatake YAMATO 					if (strcmp (exp_klass, "formatter") == 0)
611*d453aacfSMasatake YAMATO 						printFormatterExpression (stdout, 0);
612c1f9ae0dSMasatake YAMATO 					else
613c1f9ae0dSMasatake YAMATO 					{
614edc2fc0eSAmaiKinono 						fprintf (stderr, "%s: unknown expression class for --%s option\n",
615c1f9ae0dSMasatake YAMATO 								 ProgramName, optname);
616c1f9ae0dSMasatake YAMATO 						exit (1);
617c1f9ae0dSMasatake YAMATO 
618c1f9ae0dSMasatake YAMATO 					}
619c1f9ae0dSMasatake YAMATO 				}
620c1f9ae0dSMasatake YAMATO 				else
621c1f9ae0dSMasatake YAMATO 				{
622edc2fc0eSAmaiKinono 					fprintf (stderr, "%s: missing expression class for --%s option\n",
623c1f9ae0dSMasatake YAMATO 							 ProgramName, optname);
624c1f9ae0dSMasatake YAMATO 					exit (1);
625c1f9ae0dSMasatake YAMATO 				}
626c1f9ae0dSMasatake YAMATO 			}
627c1f9ae0dSMasatake YAMATO #endif
628c1f9ae0dSMasatake YAMATO 			else if (strcmp (optname, "escape-output") == 0)
629c1f9ae0dSMasatake YAMATO 				escaping = 1;
630c1f9ae0dSMasatake YAMATO 			else if (strcmp (optname, "extension-fields") == 0)
631c1f9ae0dSMasatake YAMATO 				extensionFields = 1;
632c1f9ae0dSMasatake YAMATO 			else if (strcmp (optname, "icase-match") == 0)
633c1f9ae0dSMasatake YAMATO 				options |= TAG_IGNORECASE;
634c1f9ae0dSMasatake YAMATO 			else if (strcmp (optname, "prefix-match") == 0)
635c1f9ae0dSMasatake YAMATO 				options |= TAG_PARTIALMATCH;
636c1f9ae0dSMasatake YAMATO 			else if (strcmp (optname, "list") == 0)
637c1f9ae0dSMasatake YAMATO 			{
638c1f9ae0dSMasatake YAMATO 				listTags (0);
639c1f9ae0dSMasatake YAMATO 				actionSupplied = 1;
640c1f9ae0dSMasatake YAMATO 			}
641c1f9ae0dSMasatake YAMATO 			else if (strcmp (optname, "line-number") == 0)
642c1f9ae0dSMasatake YAMATO 				allowPrintLineNumber = 1;
643c1f9ae0dSMasatake YAMATO 			else if (strcmp (optname, "tag-file") == 0)
644c1f9ae0dSMasatake YAMATO 			{
645c1f9ae0dSMasatake YAMATO 				if (i + 1 < argc)
646c1f9ae0dSMasatake YAMATO 					TagFileName = argv [++i];
647c1f9ae0dSMasatake YAMATO 				else
648c1f9ae0dSMasatake YAMATO 					printUsage (stderr, 1);
649c1f9ae0dSMasatake YAMATO 			}
650c1f9ae0dSMasatake YAMATO 			else if (strcmp (optname, "override-sort-detection") == 0)
651c1f9ae0dSMasatake YAMATO 			{
652c1f9ae0dSMasatake YAMATO 				if (i + 1 < argc)
653c1f9ae0dSMasatake YAMATO 				{
654c1f9ae0dSMasatake YAMATO 					const char *sort_spec = argv [++i];
655c1f9ae0dSMasatake YAMATO 					if (strcmp (sort_spec, "0") == 0
656c1f9ae0dSMasatake YAMATO 						|| strcmp (sort_spec, "unsorted") == 0)
657c1f9ae0dSMasatake YAMATO 						SortMethod = 0;
658c1f9ae0dSMasatake YAMATO 					else if (strcmp (sort_spec, "1") == 0
659c1f9ae0dSMasatake YAMATO 							 || strcmp (sort_spec, "sorted") == 0)
660c1f9ae0dSMasatake YAMATO 						SortMethod = 1;
661c1f9ae0dSMasatake YAMATO 					else if (strcmp (sort_spec, "2") == 0
662c1f9ae0dSMasatake YAMATO 							 || strcmp (sort_spec, "foldcase") == 0)
663c1f9ae0dSMasatake YAMATO 						SortMethod = 2;
664c1f9ae0dSMasatake YAMATO 					else
665c1f9ae0dSMasatake YAMATO 					{
666edc2fc0eSAmaiKinono 						fprintf (stderr, "%s: unknown sort method for --%s option\n",
667c1f9ae0dSMasatake YAMATO 								 ProgramName, optname);
668c1f9ae0dSMasatake YAMATO 						exit (1);
669c1f9ae0dSMasatake YAMATO 					}
670c1f9ae0dSMasatake YAMATO 				}
671c1f9ae0dSMasatake YAMATO 				else
672c1f9ae0dSMasatake YAMATO 				{
673edc2fc0eSAmaiKinono 					fprintf (stderr, "%s: missing sort method for --%s option\n",
674c1f9ae0dSMasatake YAMATO 							 ProgramName, optname);
675c1f9ae0dSMasatake YAMATO 					exit (1);
676c1f9ae0dSMasatake YAMATO 				}
677c1f9ae0dSMasatake YAMATO 			}
678c1f9ae0dSMasatake YAMATO #ifdef READTAGS_DSL
679c1f9ae0dSMasatake YAMATO 			else if (strcmp (optname, "filter") == 0)
680c1f9ae0dSMasatake YAMATO 			{
681c1f9ae0dSMasatake YAMATO 				if (i + 1 < argc)
682dafe0ab9SMasatake YAMATO 					Qualifier = compileExpression (argv[++i],
683dafe0ab9SMasatake YAMATO 												   (void * (*)(EsObject *))q_compile,
684dafe0ab9SMasatake YAMATO 												   optname);
685c1f9ae0dSMasatake YAMATO 				else
686c1f9ae0dSMasatake YAMATO 				{
687edc2fc0eSAmaiKinono 					fprintf (stderr, "%s: missing filter expression for --%s option\n",
688c1f9ae0dSMasatake YAMATO 							 ProgramName, optname);
689c1f9ae0dSMasatake YAMATO 					exit (1);
690c1f9ae0dSMasatake YAMATO 				}
691c1f9ae0dSMasatake YAMATO 			}
6926a93d1bcSMasatake YAMATO 			else if (strcmp (optname, "sorter") == 0)
6936a93d1bcSMasatake YAMATO 			{
6946a93d1bcSMasatake YAMATO 				if (i + 1 < argc)
6956a93d1bcSMasatake YAMATO 					Sorter = compileExpression (argv[++i],
6966a93d1bcSMasatake YAMATO 												(void * (*)(EsObject *))s_compile,
6976a93d1bcSMasatake YAMATO 												optname);
6986a93d1bcSMasatake YAMATO 				else
6996a93d1bcSMasatake YAMATO 				{
700edc2fc0eSAmaiKinono 					fprintf (stderr, "%s: missing sorter expression for --%s option\n",
7016a93d1bcSMasatake YAMATO 							 ProgramName, optname);
7026a93d1bcSMasatake YAMATO 					exit (1);
7036a93d1bcSMasatake YAMATO 				}
7046a93d1bcSMasatake YAMATO 			}
705*d453aacfSMasatake YAMATO 			else if (strcmp (optname, "formatter") == 0)
706*d453aacfSMasatake YAMATO 			{
707*d453aacfSMasatake YAMATO 				if (i + 1 < argc)
708*d453aacfSMasatake YAMATO 					Sorter = compileExpression (argv[++i],
709*d453aacfSMasatake YAMATO 												(void * (*)(EsObject *))f_compile,
710*d453aacfSMasatake YAMATO 												optname);
711*d453aacfSMasatake YAMATO 				else
712*d453aacfSMasatake YAMATO 				{
713*d453aacfSMasatake YAMATO 					fprintf (stderr, "%s: missing formatter expression for --%s option\n",
714*d453aacfSMasatake YAMATO 							 ProgramName, optname);
715*d453aacfSMasatake YAMATO 					exit (1);
716*d453aacfSMasatake YAMATO 				}
717*d453aacfSMasatake YAMATO 			}
718c1f9ae0dSMasatake YAMATO #endif
719c1f9ae0dSMasatake YAMATO 			else
720c1f9ae0dSMasatake YAMATO 			{
721edc2fc0eSAmaiKinono 				fprintf (stderr, "%s: unknown long options: --%s\n",
722c1f9ae0dSMasatake YAMATO 						 ProgramName, optname);
723c1f9ae0dSMasatake YAMATO 				exit (1);
724c1f9ae0dSMasatake YAMATO 				break;
725c1f9ae0dSMasatake YAMATO 			}
726c1f9ae0dSMasatake YAMATO 		}
727c1f9ae0dSMasatake YAMATO 		else
728c1f9ae0dSMasatake YAMATO 		{
729c1f9ae0dSMasatake YAMATO 			size_t j;
730c1f9ae0dSMasatake YAMATO 			for (j = 1  ;  arg [j] != '\0'  ;  ++j)
731c1f9ae0dSMasatake YAMATO 			{
732c1f9ae0dSMasatake YAMATO 				switch (arg [j])
733c1f9ae0dSMasatake YAMATO 				{
734c1f9ae0dSMasatake YAMATO 					case 'd': debugMode++; break;
735c1f9ae0dSMasatake YAMATO 					case 'D': listTags (1); actionSupplied = 1; break;
736c1f9ae0dSMasatake YAMATO 					case 'h': printUsage (stdout, 0); break;
737c1f9ae0dSMasatake YAMATO #ifdef READTAGS_DSL
738c1f9ae0dSMasatake YAMATO 					case 'H':
739c1f9ae0dSMasatake YAMATO 						if (i + 1 < argc)
740c1f9ae0dSMasatake YAMATO 						{
741c1f9ae0dSMasatake YAMATO 							const char *exp_klass = argv [++i];
742c1f9ae0dSMasatake YAMATO 							if (strcmp (exp_klass, "filter") == 0)
743c1f9ae0dSMasatake YAMATO 								printFilterExpression (stdout, 0);
7446a93d1bcSMasatake YAMATO 							else if (strcmp (exp_klass, "sorter") == 0)
7456a93d1bcSMasatake YAMATO 								printSorterExpression (stdout, 0);
746*d453aacfSMasatake YAMATO 							else if (strcmp (exp_klass, "formatter") == 0)
747*d453aacfSMasatake YAMATO 								printFormatterExpression (stdout, 0);
748c1f9ae0dSMasatake YAMATO 							else
749c1f9ae0dSMasatake YAMATO 								printUsage(stderr, 1);
750c1f9ae0dSMasatake YAMATO 						}
751c1f9ae0dSMasatake YAMATO 						else
752c1f9ae0dSMasatake YAMATO 							printUsage(stderr, 1);
753c1f9ae0dSMasatake YAMATO #endif
754c1f9ae0dSMasatake YAMATO 					case 'E': escaping = 1; break;
755c1f9ae0dSMasatake YAMATO 					case 'e': extensionFields = 1;         break;
756c1f9ae0dSMasatake YAMATO 					case 'i': options |= TAG_IGNORECASE;   break;
757c1f9ae0dSMasatake YAMATO 					case 'p': options |= TAG_PARTIALMATCH; break;
758c1f9ae0dSMasatake YAMATO 					case 'l': listTags (0); actionSupplied = 1; break;
759c1f9ae0dSMasatake YAMATO 					case 'n': allowPrintLineNumber = 1; break;
760c1f9ae0dSMasatake YAMATO 					case 't':
761c1f9ae0dSMasatake YAMATO 						if (arg [j+1] != '\0')
762c1f9ae0dSMasatake YAMATO 						{
763c1f9ae0dSMasatake YAMATO 							TagFileName = arg + j + 1;
764c1f9ae0dSMasatake YAMATO 							j += strlen (TagFileName);
765c1f9ae0dSMasatake YAMATO 						}
766c1f9ae0dSMasatake YAMATO 						else if (i + 1 < argc)
767c1f9ae0dSMasatake YAMATO 							TagFileName = argv [++i];
768c1f9ae0dSMasatake YAMATO 						else
769c1f9ae0dSMasatake YAMATO 							printUsage(stderr, 1);
770c1f9ae0dSMasatake YAMATO 						break;
771c1f9ae0dSMasatake YAMATO 					case 's':
772c1f9ae0dSMasatake YAMATO 						SortOverride = 1;
773c1f9ae0dSMasatake YAMATO 						++j;
774c1f9ae0dSMasatake YAMATO 						if (arg [j] == '\0')
775c1f9ae0dSMasatake YAMATO 							SortMethod = TAG_SORTED;
776c1f9ae0dSMasatake YAMATO 						else if (strchr ("012", arg[j]) != NULL)
777c1f9ae0dSMasatake YAMATO 							SortMethod = (sortType) (arg[j] - '0');
778c1f9ae0dSMasatake YAMATO 						else
779c1f9ae0dSMasatake YAMATO 							printUsage(stderr, 1);
780c1f9ae0dSMasatake YAMATO 						break;
781c1f9ae0dSMasatake YAMATO #ifdef READTAGS_DSL
782c1f9ae0dSMasatake YAMATO 					case 'Q':
783c1f9ae0dSMasatake YAMATO 						if (i + 1 == argc)
784c1f9ae0dSMasatake YAMATO 							printUsage(stderr, 1);
785dafe0ab9SMasatake YAMATO 						Qualifier = compileExpression (argv[++i],
786dafe0ab9SMasatake YAMATO 													   (void * (*)(EsObject *))q_compile,
787dafe0ab9SMasatake YAMATO 													   "filter");
788c1f9ae0dSMasatake YAMATO 						break;
7896a93d1bcSMasatake YAMATO 					case 'S':
7906a93d1bcSMasatake YAMATO 						if (i + 1 == argc)
7916a93d1bcSMasatake YAMATO 							printUsage(stderr, 1);
7926a93d1bcSMasatake YAMATO 						Sorter = compileExpression (argv[++i],
7936a93d1bcSMasatake YAMATO 													   (void * (*)(EsObject *))s_compile,
7946a93d1bcSMasatake YAMATO 													   "sorter");
7956a93d1bcSMasatake YAMATO 						break;
796*d453aacfSMasatake YAMATO 					case 'F':
797*d453aacfSMasatake YAMATO 						if (i + 1 == argc)
798*d453aacfSMasatake YAMATO 							printUsage(stderr, 1);
799*d453aacfSMasatake YAMATO 						Formatter = compileExpression (argv[++i],
800*d453aacfSMasatake YAMATO 													   (void * (*)(EsObject *))f_compile,
801*d453aacfSMasatake YAMATO 													   "formatter");
802*d453aacfSMasatake YAMATO 						break;
803c1f9ae0dSMasatake YAMATO #endif
804c1f9ae0dSMasatake YAMATO 					default:
805c1f9ae0dSMasatake YAMATO 						fprintf (stderr, "%s: unknown option: %c\n",
806c1f9ae0dSMasatake YAMATO 									ProgramName, arg[j]);
807c1f9ae0dSMasatake YAMATO 						exit (1);
808c1f9ae0dSMasatake YAMATO 						break;
809c1f9ae0dSMasatake YAMATO 				}
810c1f9ae0dSMasatake YAMATO 			}
811c1f9ae0dSMasatake YAMATO 		}
812c1f9ae0dSMasatake YAMATO 	}
813c1f9ae0dSMasatake YAMATO 	if (! actionSupplied)
814c1f9ae0dSMasatake YAMATO 	{
815c1f9ae0dSMasatake YAMATO 		fprintf (stderr,
816c1f9ae0dSMasatake YAMATO 			"%s: no action specified: specify one of NAME, -l or -D\n",
817c1f9ae0dSMasatake YAMATO 			ProgramName);
818c1f9ae0dSMasatake YAMATO 		exit (1);
819c1f9ae0dSMasatake YAMATO 	}
82055a1e1f3SMasatake YAMATO #ifdef READTAGS_DSL
82155a1e1f3SMasatake YAMATO 	if (Qualifier)
82255a1e1f3SMasatake YAMATO 		q_destroy (Qualifier);
82355a1e1f3SMasatake YAMATO 	if (Sorter)
82455a1e1f3SMasatake YAMATO 		s_destroy (Sorter);
825*d453aacfSMasatake YAMATO 	if (Formatter)
826*d453aacfSMasatake YAMATO 		f_destroy (Formatter);
82755a1e1f3SMasatake YAMATO #endif
828c1f9ae0dSMasatake YAMATO 	return 0;
829c1f9ae0dSMasatake YAMATO }
830