* Implement options: expandtab gtagsmode matchchars * Fix tty garbling when quitting from recovery mode. * Don't coredump during autoindent edge case. * Set internal version to "nvi-1.81.6nb4 (2009-08-07)" * Crank pkgrevision to nb4.
179 lines
4.4 KiB
Text
179 lines
4.4 KiB
Text
$NetBSD: patch-au,v 1.1 2009/08/07 16:39:21 lukem Exp $
|
|
|
|
--- ../ex/ex_tag.c.orig 2007-11-19 03:41:42.000000000 +1100
|
|
+++ ../ex/ex_tag.c
|
|
@@ -46,6 +46,8 @@ static char *binary_search __P((char *,
|
|
static int compare __P((char *, char *, char *));
|
|
static void ctag_file __P((SCR *, TAGF *, char *, char **, size_t *));
|
|
static int ctag_search __P((SCR *, CHAR_T *, size_t, char *));
|
|
+static int getentry __P((char *, char **, char **, char **));
|
|
+static TAGQ *gtag_slist __P((SCR *, CHAR_T *, int));
|
|
static int ctag_sfile __P((SCR *, TAGF *, TAGQ *, char *));
|
|
static TAGQ *ctag_slist __P((SCR *, CHAR_T *));
|
|
static char *linear_search __P((char *, char *, char *, long));
|
|
@@ -87,6 +89,21 @@ ex_tag_first(SCR *sp, CHAR_T *tagarg)
|
|
}
|
|
|
|
/*
|
|
+ * ex_rtag_push -- ^]
|
|
+ * :rtag[!] [string]
|
|
+ *
|
|
+ * Enter a new TAGQ context based on a ctag string.
|
|
+ *
|
|
+ * PUBLIC: int ex_rtag_push __P((SCR *, EXCMD *));
|
|
+ */
|
|
+int
|
|
+ex_rtag_push(SCR *sp, EXCMD *cmdp)
|
|
+{
|
|
+ F_SET(cmdp, E_REFERENCE);
|
|
+ return ex_tag_push(sp, cmdp);
|
|
+}
|
|
+
|
|
+/*
|
|
* ex_tag_push -- ^]
|
|
* :tag[!] [string]
|
|
*
|
|
@@ -129,6 +146,11 @@ ex_tag_push(SCR *sp, EXCMD *cmdp)
|
|
}
|
|
|
|
/* Get the tag information. */
|
|
+ if (O_ISSET(sp, O_GTAGSMODE)) {
|
|
+ if ((tqp = gtag_slist(sp, exp->tag_last,
|
|
+ F_ISSET(cmdp, E_REFERENCE))) == NULL)
|
|
+ return (1);
|
|
+ } else
|
|
if ((tqp = ctag_slist(sp, exp->tag_last)) == NULL)
|
|
return (1);
|
|
|
|
@@ -980,6 +1002,131 @@ notfound: tag_msg(sp, TAG_SEARCH, tag)
|
|
}
|
|
|
|
/*
|
|
+ * getentry --
|
|
+ * get tag information from current line.
|
|
+ *
|
|
+ * gtags temporary file format.
|
|
+ * <tag> <lineno> <file> <image>
|
|
+ *
|
|
+ * sample.
|
|
+ * +------------------------------------------------
|
|
+ * |main 30 main.c main(argc, argv)
|
|
+ * |func 21 subr.c func(arg)
|
|
+ */
|
|
+static int
|
|
+getentry(char *buf, char **tag, char **file, char **line)
|
|
+{
|
|
+ char *p = buf;
|
|
+
|
|
+ for (*tag = p; *p && !isspace(*p); p++) /* tag name */
|
|
+ ;
|
|
+ if (*p == 0)
|
|
+ goto err;
|
|
+ *p++ = 0;
|
|
+ for (; *p && isspace(*p); p++) /* (skip blanks) */
|
|
+ ;
|
|
+ if (*p == 0)
|
|
+ goto err;
|
|
+ *line = p; /* line no */
|
|
+ for (*line = p; *p && !isspace(*p); p++)
|
|
+ ;
|
|
+ if (*p == 0)
|
|
+ goto err;
|
|
+ *p++ = 0;
|
|
+ for (; *p && isspace(*p); p++) /* (skip blanks) */
|
|
+ ;
|
|
+ if (*p == 0)
|
|
+ goto err;
|
|
+ *file = p; /* file name */
|
|
+ for (*file = p; *p && !isspace(*p); p++)
|
|
+ ;
|
|
+ if (*p == 0)
|
|
+ goto err;
|
|
+ *p = 0;
|
|
+
|
|
+ /* value check */
|
|
+ if (strlen(*tag) && strlen(*line) && strlen(*file) && atoi(*line) > 0)
|
|
+ return 1; /* OK */
|
|
+err:
|
|
+ return 0; /* ERROR */
|
|
+}
|
|
+
|
|
+/*
|
|
+ * gtag_slist --
|
|
+ * Search the list of tags files for a tag, and return tag queue.
|
|
+ */
|
|
+static TAGQ *
|
|
+gtag_slist(SCR *sp, CHAR_T *tag, int ref)
|
|
+{
|
|
+ EX_PRIVATE *exp;
|
|
+ TAGF *tfp;
|
|
+ TAGQ *tqp;
|
|
+ size_t len, nlen, slen, wlen;
|
|
+ int echk;
|
|
+ TAG *tp;
|
|
+ char *np;
|
|
+ char *name, *file, *search;
|
|
+ char command[BUFSIZ];
|
|
+ char buf[BUFSIZ];
|
|
+ CHAR_T *wp;
|
|
+ FILE *fp;
|
|
+
|
|
+ /* Allocate and initialize the tag queue structure. */
|
|
+ INT2CHAR(sp, tag, STRLEN(tag) + 1, np, nlen);
|
|
+ len = nlen - 1;
|
|
+ CALLOC_GOTO(sp, tqp, TAGQ *, 1, sizeof(TAGQ) + len + 1);
|
|
+ CIRCLEQ_INIT(&tqp->tagq);
|
|
+ tqp->tag = tqp->buf;
|
|
+ memcpy(tqp->tag, np, (tqp->tlen = len) + 1);
|
|
+
|
|
+ /*
|
|
+ * Find the tag, only display missing file messages once, and
|
|
+ * then only if we didn't find the tag.
|
|
+ */
|
|
+ snprintf(command, sizeof(command), "global -%s '%s'", ref ? "rx" : "x",
|
|
+ np);
|
|
+ if (fp = popen(command, "r")) {
|
|
+ while (fgets(buf, sizeof(buf), fp)) {
|
|
+ if (buf[strlen(buf)-1] == '\n') /* chop(buf) */
|
|
+ buf[strlen(buf)-1] = 0;
|
|
+ else
|
|
+ while (fgetc(fp) != '\n')
|
|
+ ;
|
|
+ if (getentry(buf, &name, &file, &search) == 0) {
|
|
+ echk = 1;
|
|
+ F_SET(tfp, TAGF_ERR);
|
|
+ break;
|
|
+ }
|
|
+ slen = strlen(search);
|
|
+ CALLOC_GOTO(sp, tp,
|
|
+ TAG *, 1, sizeof(TAG) + strlen(file) + 1 +
|
|
+ (slen + 1) * sizeof(CHAR_T));
|
|
+ tp->fname = (char *)tp->buf;
|
|
+ strcpy(tp->fname, file);
|
|
+ tp->fnlen = strlen(file);
|
|
+ tp->search = (CHAR_T *)(tp->fname + tp->fnlen + 1);
|
|
+ CHAR2INT(sp, search, slen + 1, wp, wlen);
|
|
+ MEMCPYW(tp->search, wp, (tp->slen = slen) + 1);
|
|
+ CIRCLEQ_INSERT_TAIL(&tqp->tagq, tp, q);
|
|
+ }
|
|
+ pclose(fp);
|
|
+ }
|
|
+
|
|
+ /* Check to see if we found anything. */
|
|
+ if (tqp->tagq.cqh_first == (void *)&tqp->tagq) {
|
|
+ msgq_str(sp, M_ERR, np, "162|%s: tag not found");
|
|
+ free(tqp);
|
|
+ return (NULL);
|
|
+ }
|
|
+
|
|
+ tqp->current = tqp->tagq.cqh_first;
|
|
+ return (tqp);
|
|
+
|
|
+alloc_err:
|
|
+ return (NULL);
|
|
+}
|
|
+
|
|
+/*
|
|
* ctag_slist --
|
|
* Search the list of tags files for a tag, and return tag queue.
|
|
*/
|