diff --git a/contrib/nvi/build/Makefile.in b/contrib/nvi/build/Makefile.in index 54025e7d3b9d..d9c260988f98 100644 --- a/contrib/nvi/build/Makefile.in +++ b/contrib/nvi/build/Makefile.in @@ -3,7 +3,7 @@ srcdir= @srcdir@/.. CC= @CC@ OPTFLAG=@OPTFLAG@ -CFLAGS= -c $(OPTFLAG) @CFLAGS@ -I. -I$(srcdir)/include @CPPFLAGS@ +CFLAGS= -c $(OPTFLAG) @CFLAGS@ -I. -I$(srcdir)/include @CPPFLAGS@ -DGTAGS LDFLAGS=@LDFLAGS@ PERL= @vi_cv_path_perl@ PERLLIB=@vi_cv_perllib@ diff --git a/contrib/nvi/common/main.c b/contrib/nvi/common/main.c index 6fb2ed1fe2f0..7e9580389dbe 100644 --- a/contrib/nvi/common/main.c +++ b/contrib/nvi/common/main.c @@ -64,6 +64,9 @@ editor(gp, argc, argv) size_t len; u_int flags; int ch, flagchk, lflag, secure, startup, readonly, rval, silent; +#ifdef GTAGS + int gtags = 0; +#endif char *tag_f, *wsizearg, path[256]; /* Initialize the busy routine, if not defined by the screen. */ @@ -113,10 +116,18 @@ editor(gp, argc, argv) /* Set the file snapshot flag. */ F_SET(gp, G_SNAPSHOT); +#ifdef GTAGS +#ifdef DEBUG + while ((ch = getopt(argc, argv, "c:D:eFGlRrSsT:t:vw:")) != EOF) +#else + while ((ch = getopt(argc, argv, "c:eFGlRrSst:vw:")) != EOF) +#endif +#else #ifdef DEBUG while ((ch = getopt(argc, argv, "c:D:eFlRrSsT:t:vw:")) != EOF) #else while ((ch = getopt(argc, argv, "c:eFlRrSst:vw:")) != EOF) +#endif #endif switch (ch) { case 'c': /* Run the command. */ @@ -154,6 +165,11 @@ editor(gp, argc, argv) case 'F': /* No snapshot. */ F_CLR(gp, G_SNAPSHOT); break; +#ifdef GTAGS + case 'G': /* gtags mode. */ + gtags = 1; + break; +#endif case 'l': /* Set lisp, showmatch options. */ lflag = 1; break; @@ -252,6 +268,10 @@ editor(gp, argc, argv) } if (readonly) *oargp++ = O_READONLY; +#ifdef GTAGS + if (gtags) + *oargp++ = O_GTAGSMODE; +#endif if (secure) *oargp++ = O_SECURE; *oargp = -1; /* Options initialization. */ diff --git a/contrib/nvi/common/options.c b/contrib/nvi/common/options.c index 4d4f768b1634..fe310fc89d91 100644 --- a/contrib/nvi/common/options.c +++ b/contrib/nvi/common/options.c @@ -80,6 +80,10 @@ OPTLIST const optlist[] = { {"filec", NULL, OPT_STR, 0}, /* O_FLASH HPUX */ {"flash", NULL, OPT_1BOOL, 0}, +#ifdef GTAGS +/* O_GTAGSMODE FreeBSD2.2 */ + {"gtagsmode", NULL, OPT_0BOOL, 0}, +#endif /* O_HARDTABS 4BSD */ {"hardtabs", NULL, OPT_NUM, 0}, /* O_ICLOWER 4.4BSD */ @@ -244,6 +248,9 @@ static OABBREV const abbrev[] = { {"eb", O_ERRORBELLS}, /* 4BSD */ {"ed", O_EDCOMPATIBLE}, /* 4BSD */ {"ex", O_EXRC}, /* System V (undocumented) */ +#ifdef GTAGS + {"gt", O_GTAGSMODE}, /* FreeBSD2.2 */ +#endif {"ht", O_HARDTABS}, /* 4BSD */ {"ic", O_IGNORECASE}, /* 4BSD */ {"li", O_LINES}, /* 4.4BSD */ diff --git a/contrib/nvi/docs/USD.doc/vi.man/vi.1 b/contrib/nvi/docs/USD.doc/vi.man/vi.1 index 22aee3e7e952..2275b942bf60 100644 --- a/contrib/nvi/docs/USD.doc/vi.man/vi.1 +++ b/contrib/nvi/docs/USD.doc/vi.man/vi.1 @@ -17,7 +17,7 @@ ex, vi, view \- text editors .SH SYNOPSIS .B ex [\c -.B -eFRrSsv\c +.B -eFGRrSsv\c ] [\c .BI -c " cmd"\c ] [\c @@ -28,7 +28,7 @@ ex, vi, view \- text editors .br .B vi [\c -.B -eFlRrSv\c +.B -eFGlRrSv\c ] [\c .BI -c " cmd"\c ] [\c @@ -39,7 +39,7 @@ ex, vi, view \- text editors .br .B view [\c -.B -eFRrSv\c +.B -eFGRrSv\c ] [\c .BI -c " cmd"\c ] [\c @@ -121,6 +121,9 @@ the file during your edit session.) .B \-l Start editing with the lisp and showmatch options set. .TP +.B \-G +Start editing in gtags mode, as if the gtagsmode option was set. +.TP .B \-R Start editing in read-only mode, as if the command name was .IR view , @@ -429,6 +432,8 @@ commands or cancel partial commands. .TP .B "" Push a tag reference onto the tag stack. +In gtagsmode, if at the first column of line, +locate function references otherwise function definitions. .TP .B "" Switch to the most recently edited file. @@ -940,6 +945,9 @@ Grow or shrink the current screen. .B "rew[ind][!]" Rewind the argument list. .TP +.B "rta[g][!] tagstring" +Edit the file refering the specified tag. (Only in gtagsmode) +.TP .B "se[t] [option[=[value]] ...] [nooption ...] [option? ...] [all]" Display or set editor options. .TP @@ -1110,6 +1118,9 @@ command line. .B "flash [on]" Flash the screen instead of beeping the keyboard on error. .TP +.B "gtagsmode, gt [off]" +Use GTAGS and GRTAGS instead of tags. +.TP .B "hardtabs, ht [8]" Set the spacing between hardware tab settings. .TP diff --git a/contrib/nvi/ex/ex.h b/contrib/nvi/ex/ex.h index 5870990b744e..f40be8ac9bfa 100644 --- a/contrib/nvi/ex/ex.h +++ b/contrib/nvi/ex/ex.h @@ -152,6 +152,9 @@ struct _excmd { #define E_SEARCH_WMSG 0x01000000 /* Display search-wrapped message. */ #define E_USELASTCMD 0x02000000 /* Use the last command. */ #define E_VISEARCH 0x04000000 /* It's really a vi search command. */ +#ifdef GTAGS +#define E_REFERENCE 0x08000000 /* locate function references */ +#endif u_int32_t flags; /* Current flags. */ }; diff --git a/contrib/nvi/ex/ex_cmd.c b/contrib/nvi/ex/ex_cmd.c index 8f7fc8da7a13..8c9801df4291 100644 --- a/contrib/nvi/ex/ex_cmd.c +++ b/contrib/nvi/ex/ex_cmd.c @@ -302,6 +302,13 @@ EXCMDLIST const cmds[] = { "!", "rew[ind][!]", "re-edit all the files in the file argument list"}, +#ifdef GTAGS +/* C_RTAG */ + {"rtag", ex_rtag_push, E_NEWSCREEN, + "!w1o", + "[Rr]ta[g][!] [string]", + "edit the file containing the tag"}, +#endif /* * !!! * Adding new commands starting with 's' may break the substitute command code diff --git a/contrib/nvi/ex/ex_tag.c b/contrib/nvi/ex/ex_tag.c index 461b1526ef00..7396b7a0bfcf 100644 --- a/contrib/nvi/ex/ex_tag.c +++ b/contrib/nvi/ex/ex_tag.c @@ -46,6 +46,10 @@ static char *binary_search __P((char *, char *, 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 *, size_t, char *)); +#ifdef GTAGS +static int getentry __P((char *, char *, char *, char *)); +static TAGQ *gtag_slist __P((SCR *, char *, int)); +#endif static int ctag_sfile __P((SCR *, TAGF *, TAGQ *, char *)); static TAGQ *ctag_slist __P((SCR *, char *)); static char *linear_search __P((char *, char *, char *)); @@ -89,6 +93,25 @@ ex_tag_first(sp, tagarg) return (0); } +#ifdef GTAGS +/* + * 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(sp, cmdp) + SCR *sp; + EXCMD *cmdp; +{ + F_SET(cmdp, E_REFERENCE); + return ex_tag_push(sp, cmdp); +} +#endif + /* * ex_tag_push -- ^] * :tag[!] [string] @@ -138,6 +161,12 @@ ex_tag_push(sp, cmdp) } /* Get the tag information. */ +#ifdef GTAGS + if (O_ISSET(sp, O_GTAGSMODE)) { + if ((tqp = gtag_slist(sp, exp->tag_last, F_ISSET(cmdp, E_REFERENCE))) == NULL) + return (1); + } else +#endif if ((tqp = ctag_slist(sp, exp->tag_last)) == NULL) return (1); @@ -969,6 +998,119 @@ notfound: tag_msg(sp, TAG_SEARCH, tag); return (0); } +#ifdef GTAGS +/* + * getentry -- + * get tag information from current line. + * + * gtags temporary file format. + * + * + * sample. + * +------------------------------------------------ + * |main 30 main.c main(argc, argv) + * |func 21 subr.c func(arg) + */ +static int +getentry(buf, tag, file, line) + char *buf, *tag, *file, *line; +{ + char *p; + + p = tag; + while (*buf && !isspace(*buf)) /* tag name */ + *p++ = *buf++; + *p = 0; + while (*buf && isspace(*buf)) /* skip blanks */ + buf++; + p = line; + while (*buf && !isspace(*buf)) /* line no */ + *p++ = *buf++; + *p = 0; + while (*buf && isspace(*buf)) /* skip blanks */ + buf++; + p = file; + while (*buf && !isspace(*buf)) /* file name */ + *p++ = *buf++; + *p = 0; + + /* value check */ + if (strlen(tag) && strlen(line) && strlen(file) && atoi(line) > 0) + return 1; /* OK */ + return 0; /* ERROR */ +} + +/* + * gtag_slist -- + * Search the list of tags files for a tag, and return tag queue. + */ +static TAGQ * +gtag_slist(sp, tag, ref) + SCR *sp; + char *tag; + int ref; +{ + EX_PRIVATE *exp; + TAGF *tfp; + TAGQ *tqp; + size_t len; + int echk; + TAG *tp; + static char name[80], file[200], line[10]; + char command[200]; + char buf[BUFSIZ+1]; + FILE *fp; + + /* Allocate and initialize the tag queue structure. */ + len = strlen(tag); + CALLOC_GOTO(sp, tqp, TAGQ *, 1, sizeof(TAGQ) + len + 1); + CIRCLEQ_INIT(&tqp->tagq); + tqp->tag = tqp->buf; + memcpy(tqp->tag, tag, (tqp->tlen = len) + 1); + + /* + * Find the tag, only display missing file messages once, and + * then only if we didn't find the tag. + */ + sprintf(command, "global -%s '%s'", ref ? "rx" : "x", tag); + 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, line) == 0) { + echk = 1; + F_SET(tfp, TAGF_ERR); + break; + } + CALLOC_GOTO(sp, tp, + TAG *, 1, sizeof(TAG) + strlen(file) + 1 + strlen(line) + 1); + tp->fname = tp->buf; + strcpy(tp->fname, file); + tp->fnlen = strlen(file); + tp->search = tp->fname + tp->fnlen + 1; + strcpy(tp->search, line); + 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, tag, "162|%s: tag not found"); + free(tqp); + return (NULL); + } + + tqp->current = tqp->tagq.cqh_first; + return (tqp); + +alloc_err: + return (NULL); +} +#endif /* * ctag_slist -- * Search the list of tags files for a tag, and return tag queue. diff --git a/contrib/nvi/include/ex_def.h b/contrib/nvi/include/ex_def.h index 2e69b4872f59..56e831d4565f 100644 --- a/contrib/nvi/include/ex_def.h +++ b/contrib/nvi/include/ex_def.h @@ -47,32 +47,33 @@ #define C_RECOVER 46 #define C_RESIZE 47 #define C_REWIND 48 -#define C_SUBSTITUTE 49 -#define C_SCRIPT 50 -#define C_SET 51 -#define C_SHELL 52 -#define C_SOURCE 53 -#define C_STOP 54 -#define C_SUSPEND 55 -#define C_T 56 -#define C_TAG 57 -#define C_TAGNEXT 58 -#define C_TAGPOP 59 -#define C_TAGPREV 60 -#define C_TAGTOP 61 -#define C_TCLCMD 62 -#define C_UNDO 63 -#define C_UNABBREVIATE 64 -#define C_UNMAP 65 -#define C_V 66 -#define C_VERSION 67 -#define C_VISUAL_EX 68 -#define C_VISUAL_VI 69 -#define C_VIUSAGE 70 -#define C_WRITE 71 -#define C_WN 72 -#define C_WQ 73 -#define C_XIT 74 -#define C_YANK 75 -#define C_Z 76 -#define C_SUBTILDE 77 +#define C_RTAG 49 +#define C_SUBSTITUTE 50 +#define C_SCRIPT 51 +#define C_SET 52 +#define C_SHELL 53 +#define C_SOURCE 54 +#define C_STOP 55 +#define C_SUSPEND 56 +#define C_T 57 +#define C_TAG 58 +#define C_TAGNEXT 59 +#define C_TAGPOP 60 +#define C_TAGPREV 61 +#define C_TAGTOP 62 +#define C_TCLCMD 63 +#define C_UNDO 64 +#define C_UNABBREVIATE 65 +#define C_UNMAP 66 +#define C_V 67 +#define C_VERSION 68 +#define C_VISUAL_EX 69 +#define C_VISUAL_VI 70 +#define C_VIUSAGE 71 +#define C_WRITE 72 +#define C_WN 73 +#define C_WQ 74 +#define C_XIT 75 +#define C_YANK 76 +#define C_Z 77 +#define C_SUBTILDE 78 diff --git a/contrib/nvi/include/ex_extern.h b/contrib/nvi/include/ex_extern.h index ed01701f1185..ce09b1ca9746 100644 --- a/contrib/nvi/include/ex_extern.h +++ b/contrib/nvi/include/ex_extern.h @@ -89,6 +89,7 @@ int re_compile __P((SCR *, char *, size_t, char **, size_t *, regex_t *, u_int)); void re_error __P((SCR *, int, regex_t *)); int ex_tag_first __P((SCR *, char *)); +int ex_rtag_push __P((SCR *, EXCMD *)); int ex_tag_push __P((SCR *, EXCMD *)); int ex_tag_next __P((SCR *, EXCMD *)); int ex_tag_prev __P((SCR *, EXCMD *)); diff --git a/contrib/nvi/include/options_def.h b/contrib/nvi/include/options_def.h index 089fa7f4ea4c..d2e637cb7a2f 100644 --- a/contrib/nvi/include/options_def.h +++ b/contrib/nvi/include/options_def.h @@ -16,64 +16,65 @@ #define O_EXTENDED 15 #define O_FILEC 16 #define O_FLASH 17 -#define O_HARDTABS 18 -#define O_ICLOWER 19 -#define O_IGNORECASE 20 -#define O_KEYTIME 21 -#define O_LEFTRIGHT 22 -#define O_LINES 23 -#define O_LISP 24 -#define O_LIST 25 -#define O_LOCKFILES 26 -#define O_MAGIC 27 -#define O_MATCHTIME 28 -#define O_MESG 29 -#define O_MODELINE 30 -#define O_MSGCAT 31 -#define O_NOPRINT 32 -#define O_NUMBER 33 -#define O_OCTAL 34 -#define O_OPEN 35 -#define O_OPTIMIZE 36 -#define O_PARAGRAPHS 37 -#define O_PATH 38 -#define O_PRINT 39 -#define O_PROMPT 40 -#define O_READONLY 41 -#define O_RECDIR 42 -#define O_REDRAW 43 -#define O_REMAP 44 -#define O_REPORT 45 -#define O_RULER 46 -#define O_SCROLL 47 -#define O_SEARCHINCR 48 -#define O_SECTIONS 49 -#define O_SECURE 50 -#define O_SHELL 51 -#define O_SHELLMETA 52 -#define O_SHIFTWIDTH 53 -#define O_SHOWMATCH 54 -#define O_SHOWMODE 55 -#define O_SIDESCROLL 56 -#define O_SLOWOPEN 57 -#define O_SOURCEANY 58 -#define O_TABSTOP 59 -#define O_TAGLENGTH 60 -#define O_TAGS 61 -#define O_TERM 62 -#define O_TERSE 63 -#define O_TILDEOP 64 -#define O_TIMEOUT 65 -#define O_TTYWERASE 66 -#define O_VERBOSE 67 -#define O_W1200 68 -#define O_W300 69 -#define O_W9600 70 -#define O_WARN 71 -#define O_WINDOW 72 -#define O_WINDOWNAME 73 -#define O_WRAPLEN 74 -#define O_WRAPMARGIN 75 -#define O_WRAPSCAN 76 -#define O_WRITEANY 77 -#define O_OPTIONCOUNT 78 +#define O_GTAGSMODE 18 +#define O_HARDTABS 19 +#define O_ICLOWER 20 +#define O_IGNORECASE 21 +#define O_KEYTIME 22 +#define O_LEFTRIGHT 23 +#define O_LINES 24 +#define O_LISP 25 +#define O_LIST 26 +#define O_LOCKFILES 27 +#define O_MAGIC 28 +#define O_MATCHTIME 29 +#define O_MESG 30 +#define O_MODELINE 31 +#define O_MSGCAT 32 +#define O_NOPRINT 33 +#define O_NUMBER 34 +#define O_OCTAL 35 +#define O_OPEN 36 +#define O_OPTIMIZE 37 +#define O_PARAGRAPHS 38 +#define O_PATH 39 +#define O_PRINT 40 +#define O_PROMPT 41 +#define O_READONLY 42 +#define O_RECDIR 43 +#define O_REDRAW 44 +#define O_REMAP 45 +#define O_REPORT 46 +#define O_RULER 47 +#define O_SCROLL 48 +#define O_SEARCHINCR 49 +#define O_SECTIONS 50 +#define O_SECURE 51 +#define O_SHELL 52 +#define O_SHELLMETA 53 +#define O_SHIFTWIDTH 54 +#define O_SHOWMATCH 55 +#define O_SHOWMODE 56 +#define O_SIDESCROLL 57 +#define O_SLOWOPEN 58 +#define O_SOURCEANY 59 +#define O_TABSTOP 60 +#define O_TAGLENGTH 61 +#define O_TAGS 62 +#define O_TERM 63 +#define O_TERSE 64 +#define O_TILDEOP 65 +#define O_TIMEOUT 66 +#define O_TTYWERASE 67 +#define O_VERBOSE 68 +#define O_W1200 69 +#define O_W300 70 +#define O_W9600 71 +#define O_WARN 72 +#define O_WINDOW 73 +#define O_WINDOWNAME 74 +#define O_WRAPLEN 75 +#define O_WRAPMARGIN 76 +#define O_WRAPSCAN 77 +#define O_WRITEANY 78 +#define O_OPTIONCOUNT 79 diff --git a/contrib/nvi/vi/v_ex.c b/contrib/nvi/vi/v_ex.c index 359080c656e3..bcb0ea6a5fd5 100644 --- a/contrib/nvi/vi/v_ex.c +++ b/contrib/nvi/vi/v_ex.c @@ -226,6 +226,11 @@ v_tagpush(sp, vp) ARGS *ap[2], a; EXCMD cmd; +#ifdef GTAGS + if (O_ISSET(sp, O_GTAGSMODE) && vp->m_start.cno == 0) + ex_cinit(&cmd, C_RTAG, 0, OOBLNO, 0, 0, ap); + else +#endif ex_cinit(&cmd, C_TAG, 0, OOBLNO, 0, 0, ap); ex_cadd(&cmd, &a, VIP(sp)->keyw, strlen(VIP(sp)->keyw)); return (v_exec_ex(sp, vp, &cmd));