home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS - Coast to Coast
/
simteldosarchivecoasttocoast.iso
/
eel
/
tagmod.zip
/
TAGMOD.E
Wrap
Text File
|
1990-10-28
|
16KB
|
645 lines
/************************************************************************
* "Epsilon", "EEL" and "Lugaru" are trademarks of Lugaru Software, Ltd. *
* *
* Copyright (C) 1988, 1990 Lugaru Software Ltd. All rights reserved. *
* *
* Limited permission is hereby granted to reproduce and modify this *
* copyrighted material provided that the resulting code is used only in *
* conjunction with Lugaru products and that this notice is retained in *
* any such reproduction or modification. *
************************************************************************/
#include "eel.h"
/*
* This file replaces tags.e from Lugaru, it is their source code.
* Don't try a diff, I routinely reindent their code because the
* way they indent makes me puke. I can't help it mommy, they
* took my Lisp Machine and forced me to write C.
*
* I have modified this file such that it can tag typedef C structures,
* and function like macros. Some small changes will make it tag
* all #define things but there are too many in my system for this to be
* useful so I removed those changes. Other random changes are the
* ability to tag things which contain regex characters (languages
* like lisp (DEFVAR *FOO* NIL) screw up on the '*'), the ability
* to tag lisp and scheme files (all things that start with def). Changes
* are marked with KSH. I also changed the default file name to tags
* since I can't stand the name default.tag.
*
* This file also contains the command M-x tag-project (for c and h files
* hardwired). To use it, you must set up the the project_directories
* variable and the project_directory variable. The behavior of
* pluck-tag and goto-tag is changed such that if there is no tag file
* in the current directory, the project tag file is used by default
* (no matter where you are). This requires your tags to be absolute.
*
* If you downloaded and use the file grep.e, there are some functions
* in here which are also in grep. You figure out how to structure it.
* Also, I have commented call to push_point below. Uncomment it
* if you downloaded and use pointstk.e and you want to save your place
* when you meta-dot (C-x . if you insist).
*
* NB: Tagging structures and #defines slows down the tagging process, but
* I use an Everex Step 386/33 at work and 486/25 at home, so I don't
* really care (or notice). You might not want to use this on an XT :)
*/
/*
* Set these variables as follows if your project root is D:\FOO and contains
* subdirectories BAR, BAZ and vendor supplied library source in C:\BLETCH
*
* project_directories = ".;BAR;BAZ;C:\\BLETCH"
*
* project_directory = "D:\\FOO"
*/
char project_directories[256] = ""; /* KSH */
char project_directory[FNAMELEN] = ""; /* KSH */
char initial_tag_file[FNAMELEN] = "tags"; /* KSH */
char tag_relative = 0; /* if nonzero, use relative pathname for tags */
init_tags()
{
char buf[FNAMELEN];
if (!exist("-tags")) {
strcpy(buf, initial_tag_file);
absolute(buf);
load_tags(buf);
}
}
load_tags(file)
char *file;
{
char *oldbuf = bufname;
int i;
zap("-tags");
bufname = "-tags";
i = read_file(file, strip_returns.default);
case_fold = case_fold.default; /* KSH */
bufname = oldbuf;
if (i && i != 2) {
delete_buffer("-tags");
quick_abort();
}
}
do_save_tags() /* save tags to their file if unsaved */
{
char *oldbuf = bufname;
if (exist("-tags")) {
bufname = "-tags";
if (modified) { /* saved tags must always be sorted */
sayput("Sorting tags...");
sort_another("-tags");
do_save_file(1, 1, 1);
}
bufname = oldbuf;
}
}
re_enquote(targ, source) /* from lispmode.e */
char *targ;
char *source;
{
char ch;
while (ch = *source++)
{
if (index ("^*%()\\[]|", ch)) *targ++ = '%';
*targ++ = ch;
}
*targ++ = '\0';
}
char tag_mat[80]; /* value returned by tag_match during completion */
char *tag_match(s, start)
char *s;
{
char quoted[80];
char *oldbuf = bufname, *res = 0, tmp[80];
int found;
int old_fold = case_fold;
case_fold = 0;
re_enquote (quoted, s); /* KSH */
bufname = "-tags";
if ((start & STARTMATCH) && modified)
do_save_tags();
if (start & STARTMATCH) {
point = 0;
sprintf(tmp, "\n%s", s);
if (!parse_string(1, quoted, (char *) 0) && *quoted) /* KSH */
search(1, tmp);
to_begin_line();
}
if ((!*quoted || parse_string(1, quoted, (char *) 0)) /* KSH */
&& (found = parse_string(1, "^[^;\n]+;", tag_mat))) {
tag_mat[found - 1] = 0;
nl_forward();
res = tag_mat;
}
bufname = oldbuf;
case_fold = old_fold;
return res;
}
get_tag(res, pr) /* do completion on tags */
char *res, *pr;
{
comp_read(res, pr, tag_match, 0, "");
}
go_tag(s) /* if none, go to next tag */
char *s;
{
short resp;
if (do_go_tag(s))
return;
do {
sayput("Tag %s has moved, retag file %s [Y]? ", s, filename);
refresh();
resp = tolower(getkey());
check_abort();
} while (!index("yn \r\n", resp));
say("");
if (resp != 'n') {
do_retag_file(filename);
if (!do_go_tag(s))
error("Tag %s is not in file %s", s, filename);
}
}
do_go_tag(s) /* go to tag s and return nonzero, or 0 if we can't */
char *s; /* if s is empty, use next tag & fill in s */
{
char pat[150], *oldbuf = bufname, *file, *p;
char quoted[150]; /* KSH */
int pos;
re_enquote (quoted, s); /* KSH */
bufname = "-tags";
if (*quoted) {
sprintf(pat, "^%s;.*", quoted);
point = 0;
if (!re_search(1, pat))
error("%s is not in the tag list", s);
} else if (!re_search(1, "^.*;.*"))
error("no more tags");
grab(matchstart, point, pat); /* tag, file, line # */
file = index(pat, ';');
*file++ = 0;
if (!*quoted) /* KSH */
{
strcpy(s, pat); /* save tag */
re_enquote (quoted, s); /* KSH */
}
p = index(file, ';'); /* find start of line # */
pos = strtoi(p + 1, 10);
*p = 0;
bufname = oldbuf;
absolute(file);
/* push_point(); */ /* KSH */
locate_window("", file);
find_it(file, strip_returns.default);
sprintf(pat, "%s[^a-zA-Z0-9_]", quoted);
point = pos;
return parse_string(1, pat, (char *) 0);
}
command select_tag_file() on cx_tab[ALT(',')]
{ /* switch to a particular tags file */
char file[80], *def, *old = bufname;
do_save_tags();
bufname = "-tags";
def = exist("-tags") ? filename : initial_tag_file;
bufname = old;
get_file(file, "Tag file", def);
load_tags(file);
say("Tags loaded from %s", file);
}
command clear_tags() /* erase all tags */
{
init_tags();
zap("-tags");
do_save_tags();
}
command tag_files() on cx_tab[ALT('.')]
{
char pat[FNAMELEN], *s;
init_tags();
get_file(pat, "Add/update tags for files matching", filename);
iter = 0;
if (!(s = file_match(pat, 2)))
error("No matches");
for (; s; s = file_match(pat, 0)) {
delete_tags(s);
tag_a_file(s);
}
do_save_tags();
say("%s tagged.", pat);
}
tag_a_file(s)
char *s;
{
char subr[40], *ext, *orig = bufname, *temp = 0;
int ok, err = 0, opoint;
if (!look_file(s)) {
if (!temp)
temp = temp_buf();
bufname = temp;
err = read_file(s, strip_returns.default);
if (!err)
call_mode(filename);
}
if (!err) {
ext = get_extension(s);
sprintf(subr, "tag-suffix-%s", *ext ? (ext + 1) : "none");
opoint = point;
point = 0;
ok = try_calling(subr) || try_calling("tag-suffix-default");
point = opoint;
}
bufname = orig;
if (temp)
delete_buffer(temp);
if (err) /* couldn't read file */
quick_abort(); /* already showed error msg */
else if (!ok)
error("Don't know how to tag the file %s", s);
}
tag_suffix_asm() /* tag all labels or procs in the file */
{
char func[70];
int start, ofold = case_fold;
case_fold = 1;
while (re_search(1, "^[ \t]*([a-z0-9@$_]+)[ \t]*:")) {
grab(start = find_group(1, 1), find_group(1, 0), func);
add_tag(func, filename, start);
}
point = 0;
while (re_search(1, "^[ \t]*([a-z0-9@$_]+)[ \t]+proc[ \t\n;]+")) {
grab(start = find_group(1, 1), find_group(1, 0), func);
add_tag(func, filename, start);
}
case_fold = ofold;
}
tag_suffix_e() { tag_suffix_c(); }
tag_suffix_h() { tag_suffix_c(); }
tag_suffix_c() /* tag all c functions in this file */
{
int end;
while (re_search(1, "({|(/%*)|(#define[ \t]+[a-zA-Z0-9_]+%([^)]*%))|//|[a-zA-Z0-9_]+)")) {
end = point; /* find {, comment open, or ident */
point = matchstart;
if (curchar() == '{')
skip_c_braces();
else if (curchar() == '/') {
if (character(point + 1) == '*') {
point += 2;
search(1, "*/");
} else
nl_forward(); /* c++ comment */
} else if (!good_c_tag())
point = end;
}
}
skip_c_braces() /* skip over c function definition */
{
int level = 0;
char c, buf[4];
strcpy(buf, "X|\\");
while (re_search(1, "[{}\"']|/%*|//")) {
buf[0] = c = character(point - 1);
if (c == '\"' || c == '\'')
while (re_search(1, buf)
&& character(point - 1) == '\\')
point++;
else if (c == '*')
point++, search(1, "*/");
else if (c == '/') /* c++ comment */
nl_forward();
else if (c == '{')
level++;
else if (!--level)
break;
}
}
good_c_tag() /* return 1 if at a valid c func def & tag it */
{
char func[150];
int start = point;
if (curchar() == '#') /* KSH */
{
if (re_search (1, "[ \t]+"))
{
start = point;
if (!parse_string(1, "[a-zA-Z0-9_]+", func))
{
return (0);
}
re_search (1, "[^\\][ \t]*\n");
}
else
{
to_end_line();
return (0);
}
}
else if (parse_string (1, "typedef", (char *) 0)) /* KSH */
{
point += 7;
if (re_search (1, "[^a-zA-Z0-9_]+"))
{
if (re_search (1, "struct[ \t\n]+[a-zA-Z0-9_]*[ \t\n]*{"))
{
int end;
int found = 0;
point--;
skip_c_braces();
while (re_search (1, "((/%*)|//|;)"))
{
point = matchstart;
if (curchar() == '/')
{
if (character(point + 1) == '*')
{
point += 2;
search(1, "*/");
}
else
{
nl_forward(); /* c++ comment */
}
}
else
{
break;
}
}
end = point;
re_search (-1, "[ \t\n]*");
while (parse_string (-1, "[a-zA-Z0-9_]+", func))
{
add_tag(func, filename, point);
found++;
re_search (-1, "[ \t\n]*");
point--;
if (curchar() == ',')
{
point--;
re_search (-1, "[ \t]*");
}
else
{
break;
}
}
point = end;
return (found);
}
}
to_end_line();
return (0);
}
else
{
point = start;
if (!parse_string(1, "[a-zA-Z0-9_]+", func))
{
return (0);
}
if (!parse_string(1, "[ \t]*%(", (char *) 0))
{
return (0);
}
if (!move_level(1, "(", ")"))
{
return (0);
}
re_search(1, "([ \t\n]|(/%*([^*]|%*[^/])*%*/)|//.*)*");
if (!parse_string(1, "[A-Za-z{]", (char *) 0))
{
return (0);
}
}
add_tag(func, filename, start);
return (1);
}
add_tag(func, file, pos)
char *func, *file;
{
char rel[FNAMELEN], *oldbuf = bufname;
if (tag_relative) /* use relative version instead */
relative(file, rel), file = rel;
say("Adding %s in %s", func, file);
bufname = "-tags";
point = 0;
bprintf("%s;%s;%d\n", func, file, pos);
bufname = oldbuf;
}
do_retag_file(file)
char *file;
{
delete_tags(file);
tag_a_file(file);
do_save_tags();
}
delete_tags(file) /* delete all tags pointing to file */
char *file;
{
int start;
char rel[FNAMELEN], pat[FNAMELEN], *oldbuf = bufname;
if (tag_relative) /* use relative version instead */
relative(file, rel), file = rel;
bufname = "-tags";
point = 0;
sprintf(pat, ";%s;", file);
while (search(1, pat)) {
to_begin_line();
start = point;
nl_forward();
delete(start, point);
}
bufname = oldbuf;
}
tag_suffix_lsp() /* KSH */
{
int old_case_fold = case_fold;
int end;
int start;
char func[80];
case_fold = 1;
while (re_search (1, "^%(def"))
{
forward_one_sexp ();
forward_one_sexp ();
end = point;
backward_one_sexp ();
start = point;
if (character (start) == '\'') start++;
grab (start, end, func);
add_tag (func, filename, start);
point = end;
}
case_fold = old_case_fold;
}
tag_suffix_scm() { tag_suffix_lsp(); } /* KSH */
/* tag_suffix_kms() { tag_suffix_lsp(); } /* KSH */
pathname_as_directory(spec) /* KSH */
char *spec;
{
int i = strlen (spec);
if (i && spec[i - 1] != '\\')
{
spec[i] = '\\';
spec[i + 1] = 0;
}
}
char *strchr (s, c) /* KSH */
char *s;
char c;
{
while (*s)
{
if (*s == c)
return (s);
s++;
}
return (0);
}
init_tags_path() /* KSH */
{
strcpy(initial_tag_file, project_directory);
pathname_as_directory(initial_tag_file);
strcat(initial_tag_file, "tags");
}
init_tags_default() /* KSH */
{
struct file_info finfo;
if (!check_file(initial_tag_file, &finfo))
{
init_tags_path();
}
init_tags();
}
command tag_project() /* KSH */
{
char str[sizeof(project_directories)];
char *s = str;
char *ss = s;
char files[80];
char *fs;
int i;
char *hfiles = "*.h";
char *cfiles = "*.c";
char *ext = cfiles;
if (has_arg)
{
ext = hfiles;
}
iter = 0;
delete_buffer ("-tags");
init_tags_path();
init_tags();
while (1)
{
strcpy (str, project_directories);
s = str;
while (s)
{
ss = strchr (s, ';');
if (ss) *ss++ = 0;
if (strcmp (s, ".") == 0)
{
strcpy (files, project_directory);
}
else
{
strcpy (files, s);
absolute (files);
if (strcmp (files, s) != 0)
{
strcpy (files, project_directory);
pathname_as_directory (files);
strcat (files, s);
}
}
pathname_as_directory (files);
strcat (files, ext);
s = ss;
for (fs = file_match (files, 2); fs; fs = file_match (files, 0))
{
tag_a_file (fs);
}
}
if (ext == cfiles)
ext = hfiles;
else
break;
}
do_save_tags ();
}
command pluck_tag() on cx_tab[',']
{ /* read a function name at point & go there via tags */
char tag[80];
init_tags_default (); /* KSH */
iter = 0;
point--;
re_search(1, word_pattern);
re_search(-1, word_pattern);
grab(point, matchstart, tag);
go_tag(tag);
}
command goto_tag() on cx_tab['.'] /* asks for a tag, then goes there */
{
char tag[80];
init_tags_default(); /* KSH */
iter = 0;
if (!has_arg)
get_tag(tag, "Find tag [next tag]: ");
else
*tag = 0;
go_tag(tag);
}