version 1.19, 2023/03/08 04:43:11 |
version 1.20, 2023/03/22 18:10:07 |
|
|
{ |
{ |
char fname[NFILEN], *bufp, *temp; |
char fname[NFILEN], *bufp, *temp; |
struct stat sb; |
struct stat sb; |
|
|
if (getbufcwd(fname, sizeof(fname)) == FALSE) |
if (getbufcwd(fname, sizeof(fname)) == FALSE) |
fname[0] = '\0'; |
fname[0] = '\0'; |
|
|
if (strlcat(fname, DEFAULTFN, sizeof(fname)) >= sizeof(fname)) { |
if (strlcat(fname, DEFAULTFN, sizeof(fname)) >= sizeof(fname)) { |
dobeep(); |
dobeep(); |
ewprintf("Filename too long"); |
ewprintf("Filename too long"); |
return (FALSE); |
return (FALSE); |
} |
} |
|
|
bufp = eread("Visit tags table (default %s): ", fname, |
bufp = eread("Visit tags table (default %s): ", fname, |
NFILEN, EFFILE | EFCR | EFNEW | EFDEF, DEFAULTFN); |
NFILEN, EFFILE | EFCR | EFNEW | EFDEF, DEFAULTFN); |
if (bufp == NULL) |
if (bufp == NULL) |
|
|
ewprintf("Cannot access file %s", bufp); |
ewprintf("Cannot access file %s", bufp); |
return (FALSE); |
return (FALSE); |
} |
} |
|
|
if (tagsfn == NULL) { |
if (tagsfn == NULL) { |
if (bufp[0] == '\0') { |
if (bufp[0] == '\0') { |
if ((tagsfn = strdup(fname)) == NULL) { |
if ((tagsfn = strdup(fname)) == NULL) { |
|
|
tok = dtok; |
tok = dtok; |
else |
else |
tok = utok; |
tok = utok; |
|
|
if (tok[0] == '\0') { |
if (tok[0] == '\0') { |
dobeep(); |
dobeep(); |
ewprintf("There is no default tag"); |
ewprintf("There is no default tag"); |
return (FALSE); |
return (FALSE); |
} |
} |
|
|
if (tagsfn == NULL) |
if (tagsfn == NULL) |
if ((ret = tagsvisit(f, n)) != TRUE) |
if ((ret = tagsvisit(f, n)) != TRUE) |
return (ret); |
return (ret); |
|
|
unloadtags(void) |
unloadtags(void) |
{ |
{ |
struct ctag *var, *nxt; |
struct ctag *var, *nxt; |
|
|
for (var = RB_MIN(tagtree, &tags); var != NULL; var = nxt) { |
for (var = RB_MIN(tagtree, &tags); var != NULL; var = nxt) { |
nxt = RB_NEXT(tagtree, &tags, var); |
nxt = RB_NEXT(tagtree, &tags, var); |
RB_REMOVE(tagtree, &tags, var); |
RB_REMOVE(tagtree, &tags, var); |
|
|
} |
} |
|
|
/* |
/* |
* Lookup tag passed in tree and if found, push current location and |
* Lookup tag passed in tree and if found, push current location and |
* buffername onto stack, load the file with tag definition into a new |
* buffername onto stack, load the file with tag definition into a new |
* buffer and position dot at the pattern. |
* buffer and position dot at the pattern. |
*/ |
*/ |
|
|
struct tagpos *s; |
struct tagpos *s; |
char bname[NFILEN]; |
char bname[NFILEN]; |
int doto, dotline; |
int doto, dotline; |
|
|
if ((res = searchtag(tok)) == NULL) |
if ((res = searchtag(tok)) == NULL) |
return (FALSE); |
return (FALSE); |
|
|
doto = curwp->w_doto; |
doto = curwp->w_doto; |
dotline = curwp->w_dotline; |
dotline = curwp->w_dotline; |
/* record absolute filenames. Fixes issues when mg's cwd is not the |
/* record absolute filenames. Fixes issues when mg's cwd is not the |
|
|
dobeep(); |
dobeep(); |
ewprintf("filename too long"); |
ewprintf("filename too long"); |
return (FALSE); |
return (FALSE); |
} |
} |
|
|
if (loadbuffer(res->fname) == FALSE) |
if (loadbuffer(res->fname) == FALSE) |
return (FALSE); |
return (FALSE); |
|
|
if (searchpat(res->pat) == TRUE) { |
if (searchpat(res->pat) == TRUE) { |
if ((s = malloc(sizeof(struct tagpos))) == NULL) { |
if ((s = malloc(sizeof(struct tagpos))) == NULL) { |
dobeep(); |
dobeep(); |
|
|
{ |
{ |
struct line *dotp; |
struct line *dotp; |
struct tagpos *s; |
struct tagpos *s; |
|
|
if (SLIST_EMPTY(&shead)) { |
if (SLIST_EMPTY(&shead)) { |
dobeep(); |
dobeep(); |
ewprintf("No previous location for find-tag invocation"); |
ewprintf("No previous location for find-tag invocation"); |
|
|
return (FALSE); |
return (FALSE); |
curwp->w_dotline = s->dotline; |
curwp->w_dotline = s->dotline; |
curwp->w_doto = s->doto; |
curwp->w_doto = s->doto; |
|
|
/* storing of dotp in tagpos wouldn't work out in cases when |
/* storing of dotp in tagpos wouldn't work out in cases when |
* that buffer is killed by user(dangling pointer). Explicitly |
* that buffer is killed by user(dangling pointer). Explicitly |
* traverse till dotline for correct handling. |
* traverse till dotline for correct handling. |
*/ |
*/ |
dotp = curwp->w_bufp->b_headp; |
dotp = curwp->w_bufp->b_headp; |
while (s->dotline--) |
while (s->dotline--) |
dotp = dotp->l_fp; |
dotp = dotp->l_fp; |
|
|
curwp->w_dotp = dotp; |
curwp->w_dotp = dotp; |
free(s->bname); |
free(s->bname); |
free(s); |
free(s); |
|
|
} |
} |
|
|
/* |
/* |
* Parse the tags file and construct the tags tree. Remove escape |
* Parse the tags file and construct the tags tree. Remove escape |
* characters while parsing the file. |
* characters while parsing the file. |
*/ |
*/ |
int |
int |
|
|
{ |
{ |
char *l; |
char *l; |
FILE *fd; |
FILE *fd; |
|
|
if ((fd = fopen(fn, "r")) == NULL) { |
if ((fd = fopen(fn, "r")) == NULL) { |
dobeep(); |
dobeep(); |
ewprintf("Unable to open tags file: %s", fn); |
ewprintf("Unable to open tags file: %s", fn); |
|
|
void |
void |
closetags(void) |
closetags(void) |
{ |
{ |
struct tagpos *s; |
struct tagpos *s; |
|
|
while (!SLIST_EMPTY(&shead)) { |
while (!SLIST_EMPTY(&shead)) { |
s = SLIST_FIRST(&shead); |
s = SLIST_FIRST(&shead); |
SLIST_REMOVE_HEAD(&shead, entry); |
SLIST_REMOVE_HEAD(&shead, entry); |
|
|
/* |
/* |
* Strip away any special characters in pattern. |
* Strip away any special characters in pattern. |
* The pattern in ctags isn't a true regular expression. Its of the form |
* The pattern in ctags isn't a true regular expression. Its of the form |
* /^xxx$/ or ?^xxx$? and in some cases the "$" would be missing. Strip |
* /^xxx$/ or ?^xxx$? and in some cases the "$" would be missing. Strip |
* the leading and trailing special characters so the pattern matching |
* the leading and trailing special characters so the pattern matching |
* would be a simple string compare. Escape character is taken care by |
* would be a simple string compare. Escape character is taken care by |
* fparseln. |
* fparseln. |
*/ |
*/ |
char * |
char * |
strip(char *s, size_t len) |
strip(char *s, size_t len) |
{ |
{ |
/* first strip trailing special chars */ |
/* first strip trailing special chars */ |
s[len - 1] = '\0'; |
s[len - 1] = '\0'; |
if (s[len - 2] == '$') |
if (s[len - 2] == '$') |
s[len - 2] = '\0'; |
s[len - 2] = '\0'; |
|
|
/* then strip leading special chars */ |
/* then strip leading special chars */ |
s++; |
s++; |
if (*s == '^') |
if (*s == '^') |
s++; |
s++; |
|
|
return s; |
return s; |
} |
} |
|
|
|
|
addctag(char *l) |
addctag(char *l) |
{ |
{ |
struct ctag *t; |
struct ctag *t; |
|
|
if ((t = malloc(sizeof(struct ctag))) == NULL) { |
if ((t = malloc(sizeof(struct ctag))) == NULL) { |
dobeep(); |
dobeep(); |
ewprintf("Out of memory"); |
ewprintf("Out of memory"); |
|
|
} |
} |
|
|
/* |
/* |
* Return TRUE if dot is at beginning of a word or at beginning |
* Return TRUE if dot is at beginning of a word or at beginning |
* of line, else FALSE. |
* of line, else FALSE. |
*/ |
*/ |
int |
int |
|
|
struct line *odotp; |
struct line *odotp; |
int odoto, tdoto, odotline, size, r; |
int odoto, tdoto, odotline, size, r; |
char c; |
char c; |
|
|
/* Underscore character is to be treated as "inword" while |
/* Underscore character is to be treated as "inword" while |
* processing tokens unlike mg's default word traversal. Save |
* processing tokens unlike mg's default word traversal. Save |
* and restore its cinfo value so that tag matching works for |
* and restore its cinfo value so that tag matching works for |
|
|
*/ |
*/ |
c = cinfo['_']; |
c = cinfo['_']; |
cinfo['_'] = _MG_W; |
cinfo['_'] = _MG_W; |
|
|
odotp = curwp->w_dotp; |
odotp = curwp->w_dotp; |
odoto = curwp->w_doto; |
odoto = curwp->w_doto; |
odotline = curwp->w_dotline; |
odotline = curwp->w_dotline; |
|
|
/* Move backward unless we are at the beginning of a word or at |
/* Move backward unless we are at the beginning of a word or at |
* beginning of line. |
* beginning of line. |
*/ |
*/ |
if (!atbow()) |
if (!atbow()) |
if ((r = backword(f, n)) == FALSE) |
if ((r = backword(f, n)) == FALSE) |
goto cleanup; |
goto cleanup; |
|
|
tdoto = curwp->w_doto; |
tdoto = curwp->w_doto; |
|
|
if ((r = forwword(f, n)) == FALSE) |
if ((r = forwword(f, n)) == FALSE) |
goto cleanup; |
goto cleanup; |
|
|
/* strip away leading whitespace if any like emacs. */ |
/* strip away leading whitespace if any like emacs. */ |
while (ltext(curwp->w_dotp) && |
while (ltext(curwp->w_dotp) && |
isspace(lgetc(curwp->w_dotp, tdoto))) |
isspace(lgetc(curwp->w_dotp, tdoto))) |
tdoto++; |
tdoto++; |
|
|
size = curwp->w_doto - tdoto; |
size = curwp->w_doto - tdoto; |
if (size <= 0 || size >= MAX_TOKEN || |
if (size <= 0 || size >= MAX_TOKEN || |
ltext(curwp->w_dotp) == NULL) { |
ltext(curwp->w_dotp) == NULL) { |
r = FALSE; |
r = FALSE; |
goto cleanup; |
goto cleanup; |
} |
} |
strncpy(token, ltext(curwp->w_dotp) + tdoto, size); |
strncpy(token, ltext(curwp->w_dotp) + tdoto, size); |
token[size] = '\0'; |
token[size] = '\0'; |
r = TRUE; |
r = TRUE; |
|
|
cleanup: |
cleanup: |
cinfo['_'] = c; |
cinfo['_'] = c; |
curwp->w_dotp = odotp; |
curwp->w_dotp = odotp; |
|
|
* This is equivalent to filevisit from file.c. |
* This is equivalent to filevisit from file.c. |
* Look around to see if we can find the file in another buffer; if we |
* Look around to see if we can find the file in another buffer; if we |
* can't find it, create a new buffer, read in the text, and switch to |
* can't find it, create a new buffer, read in the text, and switch to |
* the new buffer. *scratch*, *grep*, *compile* needs to be handled |
* the new buffer. *scratch*, *grep*, *compile* needs to be handled |
* differently from other buffers which have "filenames". |
* differently from other buffers which have "filenames". |
*/ |
*/ |
int |
int |
|
|
} else { |
} else { |
return (FALSE); |
return (FALSE); |
} |
} |
} else { |
} else { |
if ((adjf = adjustname(bname, TRUE)) == NULL) |
if ((adjf = adjustname(bname, TRUE)) == NULL) |
return (FALSE); |
return (FALSE); |
if ((bufp = findbuffer(adjf)) == NULL) |
if ((bufp = findbuffer(adjf)) == NULL) |