/************************************************************************ * "Epsilon", "EEL" and "Lugaru" are trademarks of Lugaru Software, Ltd. * * * * Copyright (C) 1988, 1989 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. * * * * * * Last Update: 29-Sep-1989 21:57:29 * * Revision History: * * 29-Sep-1989 by Stephen Degler * * Added show_tag function and more support for intel 80x86 assembler. * * * ************************************************************************/ #include "eel.h" char initial_tag_file[80] = "default.tag"; init_tags() { char buf[80]; 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, 1); 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(); } bufname = oldbuf; } } char tag_mat[80]; /* value returned by tag_match during completion */ char *tag_match(s, start) char *s; { char *oldbuf = bufname, *res = 0, tmp[80]; int found; bufname = "-tags"; if ((start & 1) && modified) do_save_tags(); if (start & 1) { point = 0; sprintf(tmp, "\n%s", s); if (!parse_string(1, s, (char *) 0) && *s) search(1, tmp); to_begin_line(); } if ((!*s || parse_string(1, s, (char *) 0)) && (found = parse_string(1, "^[^;\n]+;", tag_mat))) { tag_mat[found - 1] = 0; nl_forward(); res = tag_mat; } bufname = oldbuf; return res; } get_tag(res, pr) /* do completion on tags */ char *res, *pr; { comp_read(res, pr, tag_match, 0, ""); } char word_pattern[80]; command pluck_tag() on cx_tab[','] { /* read a function name at point & go there via tags */ char tag[80]; init_tags(); iter = 0; point--; re_search(1, word_pattern); re_search(-1, word_pattern); grab(point, matchstart, tag); go_tag(tag); } command show_tag() on cx_tab['/'] /* opens a window and displays tags */ { char tag[80]; int win; /* current window number */ win = window_number; init_tags(); iter = 0; point--; re_search(1, word_pattern); re_search(-1, word_pattern); grab(point, matchstart, tag); if ( number_of_windows() == 1 ) { split_window(); window_size = 8; } else { window_number = -1; } go_tag(tag); } command goto_tag() on cx_tab['.'] /* asks for a tag, then goes there */ { char tag[80]; init_tags(); iter = 0; get_tag(tag, "Find tag: "); go_tag(tag); } go_tag(s) 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; { char pat[150], *oldbuf = bufname, *file, *p; int pos; bufname = "-tags"; sprintf(pat, "^%s;.*", s); point = 0; if (!re_search(1, pat)) error("%s is not in the tag list", s); grab(matchstart, point, pat); file = index(pat, ';') + 1; p = index(file, ';'); pos = strtoi(p + 1, 10); *p = 0; bufname = oldbuf; absolute(file); /* locate_window("", file); */ find_it(file, 1); sprintf(pat, "%s[^a-zA-Z0-9_]", s); 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[80], *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; find_it(s, 1); ext = get_extension(s); sprintf(subr, "tag-suffix-%s", *ext ? (ext + 1) : "none"); if (!try_calling(subr) && !try_calling("tag-suffix-default")) 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, opoint = point, ofold = case_fold; case_fold = 1; point = 0; /* 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); } */ while (re_search(1, "^[ \t]*([a-z0-9@$_]+)[ \t]+((equ[ \t]+)|(d[bwdqt][ \t]+)|(struc[ \t\n;])|(proc[ \t\n;]+)|(macro[ \t\n;]+))" )) { grab(start = find_group(1, 1), find_group(1, 0), func); add_tag(func, filename, start); } case_fold = ofold; point = opoint; } tag_suffix_mac() { tag_suffix_asm(); } tag_suffix_inc() { tag_suffix_asm(); } tag_suffix_e() { tag_suffix_c(); } tag_suffix_h() { tag_suffix_c(); } tag_suffix_c() /* tag all c functions in this file */ { int end, opoint = point; point = 0; while (re_search(1, "({|(/%*)|[a-zA-Z0-9_]+)")) { end = point; /* find {, comment open, or ident */ point = matchstart; if (curchar() == '{') skip_c_braces(); else if (curchar() == '/') { point += 2; search(1, "*/"); } else if (!good_c_tag()) point = end; } point = opoint; } 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 == '{') level++; else if (!--level) break; } } good_c_tag() /* return 1 if at a valid c func def & tag it */ { char func[70]; int len, start = point; point += (len = parse_string(1, "[a-zA-Z0-9_]+", func)); if (!len || !parse_string(1, "[ \t]*%(", (char *) 0) || !search(1, ")")) return 0; /* after identifier, skip over arg list */ do { /* then whitespace/comments */ while (index(" \t\n", curchar())) point++; } while (curchar() == '/' && character(point + 1) == '*' && (point += 2, search(1, "*/"))); if (!parse_string(1, "[A-Za-z{]", (char *) 0)) return 0; /* must not have one of these chars */ add_tag(func, filename, start); return 1; } add_tag(func, file, pos) char *func, *file; { char *oldbuf = bufname; 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; { char pat[80], *oldbuf = bufname; int start; bufname = "-tags"; point = 0; sprintf(pat, ";%s;", file); while (search(1, pat)) { to_begin_line(); start = point; nl_forward(); delete(start, point); } bufname = oldbuf; }