/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- get_lang_entry
- usage
- help
- main
- cmp
- isnotfunction
- dbg_print
/*
* Copyright (c) 1998, 1999, 2000, 2001, 2002, 2003, 2005
* Tama Communications Corporation
*
* This file is part of GNU GLOBAL.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#include <stdio.h>
#ifdef STDC_HEADERS
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "getopt.h"
#include "global.h"
#include "gctags.h"
#include "const.h"
int main(int, char **);
static void usage(void);
static void help(void);
struct words {
const char *name;
int val;
};
struct words *words;
static int tablesize;
static char *langmap;
int bflag; /* -b: force level 1 block start */
int eflag; /* -e: force level 1 block end */
int nflag; /* -n: doen't print tag */
int qflag; /* -q: quiet mode */
int rflag; /* -r: function reference */
int sflag; /* -s: collect symbols */
int wflag; /* -w: warning message */
int vflag; /* -v: verbose mode */
int show_version;
int show_help;
int debug;
/*----------------------------------------------------------------------*/
/* Parser switch */
/*----------------------------------------------------------------------*/
/*
* This is the linkage section of each parsers.
* If you want to support new language, you must define parser procedure
* which requires file name as an argument.
*/
struct lang_entry {
const char *lang_name;
void (*parser)(const char *); /* parser procedure */
};
/*
* The first entry is default language.
*/
static struct lang_entry lang_switch[] = {
/* lang_name parser_proc */
{"c", C}, /* DEFAULT */
{"yacc", yacc},
{"cpp", Cpp},
{"java", java},
{"php", php},
{"asm", assembly}
};
#define DEFAULT_ENTRY &lang_switch[0]
/*
* get language entry.
*
* i) lang language name (NULL means 'not specified'.)
* r) language entry
*/
static struct lang_entry *
get_lang_entry(const char *lang)
{
int i, size = sizeof(lang_switch) / sizeof(struct lang_entry);
/*
* if language not specified, it assumes default language.
*/
if (lang == NULL)
return DEFAULT_ENTRY;
for (i = 0; i < size; i++)
if (!strcmp(lang, lang_switch[i].lang_name))
return &lang_switch[i];
/*
* if specified language not found, it assumes default language.
*/
return DEFAULT_ENTRY;
}
static void
usage(void)
{
fputs(usage_const, stderr);
exit(2);
}
static void
help(void)
{
fputs(usage_const, stdout);
fputs(help_const, stdout);
exit(0);
}
/*
* Though the -d(--define) and -t(--typedef) option was removed,
* the entries have been left not to bring error messages.
*/
static struct option const long_options[] = {
{"begin-block", no_argument, NULL, 'b'},
{"define", no_argument, NULL, 'd'},
{"end-block", no_argument, NULL, 'e'},
{"no-tags", no_argument, NULL, 'n'},
{"quiet", no_argument, NULL, 'q'},
{"reference", no_argument, NULL, 'r'},
{"symbol", no_argument, NULL, 's'},
{"typedef", no_argument, NULL, 't'},
{"verbose", no_argument, NULL, 'v'},
{"warning", no_argument, NULL, 'w'},
/* long name only */
{"debug", no_argument, &debug, 1},
{"langmap", required_argument, NULL, 0},
{"version", no_argument, &show_version, 1},
{"help", no_argument, &show_help, 1},
{ 0 }
};
int
main(int argc, char **argv)
{
char *p;
int optchar;
int option_index = 0;
while ((optchar = getopt_long(argc, argv, "bdenqrstvw", long_options, &option_index)) != EOF) {
switch(optchar) {
case 0:
p = (char *)long_options[option_index].name;
if (!strcmp(p, "langmap"))
langmap = optarg;
break;
case 'b':
bflag++;
break;
case 'd':
break;
case 'e':
eflag++;
break;
case 'n':
nflag++;
break;
case 'q':
qflag++;
break;
case 'r':
rflag++;
sflag = 0;
break;
case 's':
sflag++;
rflag = 0;
break;
case 't':
break;
case 'v':
vflag++;
break;
case 'w':
wflag++;
break;
default:
usage();
/* NOTREACHED */
}
}
if (show_version)
version(NULL, vflag);
else if (show_help)
help();
/*
* If langmap is not passed as argument, environment variable
* GTAGSLANGMAP should be checked. Gtags(1) call gtags-parser
* in this method.
*/
if (langmap == NULL)
langmap = getenv("GTAGSLANGMAP");
if (langmap == NULL)
langmap = DEFAULTLANGMAP;
setup_langmap(langmap);
argc -= optind;
argv += optind;
if (argc < 1)
usage();
if (getenv("GTAGSWARNING"))
wflag++;
/*
* This is a hack for FreeBSD.
* In the near future, it will be removed.
*/
#ifdef __DJGPP__
if (test("r", NOTFUNCTION) || test("r", DOS_NOTFUNCTION))
#else
if (test("r", NOTFUNCTION))
#endif
{
FILE *ip;
STRBUF *sb = strbuf_open(0);
STRBUF *ib = strbuf_open(0);
char *p;
int i;
if ((ip = fopen(NOTFUNCTION, "r")) == 0)
#ifdef __DJGPP__
if ((ip = fopen(DOS_NOTFUNCTION, "r")) == 0)
#endif
die("'%s' cannot read.", NOTFUNCTION);
for (tablesize = 0; (p = strbuf_fgets(ib, ip, STRBUF_NOCRLF)) != NULL; tablesize++)
strbuf_puts0(sb, p);
fclose(ip);
words = (struct words *)check_malloc(sizeof(struct words) * tablesize);
/*
* Don't free *p.
*/
p = (char *)check_malloc(strbuf_getlen(sb) + 1);
memcpy(p, strbuf_value(sb), strbuf_getlen(sb) + 1);
for (i = 0; i < tablesize; i++) {
words[i].name = p;
p += strlen(p) + 1;
}
qsort(words, tablesize, sizeof(struct words), cmp);
strbuf_close(sb);
strbuf_close(ib);
}
/*
* pick up files and parse them.
*/
for (; argc > 0; argv++, argc--) {
const char *lang, *suffix;
struct lang_entry *ent;
/* get suffix of the path. */
suffix = locatestring(argv[0], ".", MATCH_LAST);
if (!suffix)
continue;
lang = decide_lang(suffix);
if (lang == NULL)
continue;
if (vflag)
fprintf(stderr, "suffix '%s' assumed language '%s'.\n", suffix, lang);
/*
* Select parser.
* If lang == NULL then default parser is selected.
*/
ent = get_lang_entry(lang);
/*
* call language specific parser.
*/
ent->parser(argv[0]);
}
return 0;
}
int
cmp(const void *s1, const void *s2)
{
return strcmp(((struct words *)s1)->name, ((struct words *)s2)->name);
}
int
isnotfunction(char *name)
{
struct words tmp;
struct words *result;
if (words == NULL)
return 0;
tmp.name = name;
result = (struct words *)bsearch(&tmp, words, tablesize, sizeof(struct words), cmp);
return (result != NULL) ? 1 : 0;
}
void
dbg_print(int level, const char *s)
{
if (!debug)
return;
fprintf(stderr, "[%04d]", lineno);
for (; level > 0; level--)
fprintf(stderr, " ");
fprintf(stderr, "%s\n", s);
}