/* * This file is placed into the public domain by the author, * Shigio Yamaguchi */ diff -c -r -N ../nvi-1.79.org/common/main.c ./common/main.c *** ../nvi-1.79.org/common/main.c Sat Oct 12 07:28:28 1996 --- ./common/main.c Fri Jul 13 13:38:45 2001 *************** *** 64,69 **** --- 64,72 ---- 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,123 **** /* Set the file snapshot flag. */ F_SET(gp, G_SNAPSHOT); #ifdef DEBUG ! while ((ch = getopt(argc, argv, "c:D:eFlRrSsT:t:vw:")) != EOF) #else ! while ((ch = getopt(argc, argv, "c:eFlRrSst:vw:")) != EOF) #endif switch (ch) { case 'c': /* Run the command. */ /* --- 116,128 ---- /* 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 + /* #endif */ switch (ch) { case 'c': /* Run the command. */ /* *************** *** 154,159 **** --- 159,169 ---- 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,257 **** --- 262,271 ---- } if (readonly) *oargp++ = O_READONLY; + /* #ifdef GTAGS */ + if (gtags) + *oargp++ = O_GTAGSMODE; + /* #endif */ if (secure) *oargp++ = O_SECURE; *oargp = -1; /* Options initialization. */ diff -c -r -N ../nvi-1.79.org/common/options.c ./common/options.c *** ../nvi-1.79.org/common/options.c Tue Oct 15 03:56:29 1996 --- ./common/options.c Fri Jul 13 13:38:45 2001 *************** *** 80,85 **** --- 80,89 ---- {"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,249 **** --- 248,256 ---- {"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 -c -r -N ../nvi-1.79.org/docs/USD.doc/vi.man/vi.1 ./docs/USD.doc/vi.man/vi.1 *** ../nvi-1.79.org/docs/USD.doc/vi.man/vi.1 Fri Oct 11 10:34:05 1996 --- ./docs/USD.doc/vi.man/vi.1 Fri Jul 13 13:38:45 2001 *************** *** 17,23 **** .SH SYNOPSIS .B ex [\c ! .B -eFRrSsv\c ] [\c .BI -c " cmd"\c ] [\c --- 17,23 ---- .SH SYNOPSIS .B ex [\c ! .B -eFGRrSsv\c ] [\c .BI -c " cmd"\c ] [\c *************** *** 28,34 **** .br .B vi [\c ! .B -eFlRrSv\c ] [\c .BI -c " cmd"\c ] [\c --- 28,34 ---- .br .B vi [\c ! .B -eFGlRrSv\c ] [\c .BI -c " cmd"\c ] [\c *************** *** 39,45 **** .br .B view [\c ! .B -eFRrSv\c ] [\c .BI -c " cmd"\c ] [\c --- 39,45 ---- .br .B view [\c ! .B -eFGRrSv\c ] [\c .BI -c " cmd"\c ] [\c *************** *** 121,126 **** --- 121,129 ---- .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,434 **** --- 432,439 ---- .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. *************** *** 1109,1114 **** --- 1114,1122 ---- .TP .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. diff -c -r -N ../nvi-1.79.org/ex/ex.c ./ex/ex.c *** ../nvi-1.79.org/ex/ex.c Fri Oct 11 07:49:46 1996 --- ./ex/ex.c Fri Jul 13 13:38:45 2001 *************** *** 935,941 **** } ecp->flagoff = 0; ! for (p = ecp->cmd->syntax; *p != '\0'; ++p) { /* * The force flag is sensitive to leading whitespace, i.e. * "next !" is different from "next!". Handle it before --- 935,946 ---- } ecp->flagoff = 0; ! p = ecp->cmd->syntax; ! /* #ifdef GTAGS */ ! if (ecp->cmd == &cmds[C_TAG] && O_ISSET(sp, O_GTAGSMODE)) ! p = "!wNo"; ! /* #endif */ ! for ( ; *p != '\0'; ++p) { /* * The force flag is sensitive to leading whitespace, i.e. * "next !" is different from "next!". Handle it before diff -c -r -N ../nvi-1.79.org/ex/ex_argv.c ./ex/ex_argv.c *** ../nvi-1.79.org/ex/ex_argv.c Sat Sep 21 09:33:02 1996 --- ./ex/ex_argv.c Fri Jul 13 13:38:45 2001 *************** *** 326,331 **** --- 326,334 ---- EX_PRIVATE *exp; char *bp, *t; size_t blen, len, off, tlen; + /* #ifdef GTAGS */ + char b[30]; + /* #endif */ /* Replace file name characters. */ for (bp = *bpp, blen = *blenp, len = *lenp; cmdlen > 0; --cmdlen, ++cmd) *************** *** 376,381 **** --- 379,401 ---- p += tlen; F_SET(excp, E_MODIFY); break; + /* #ifdef GTAGS */ + case '@': /* replace with line number */ + if (O_ISSET(sp, O_GTAGSMODE)) { + snprintf(b, sizeof(b), "%d", sp->lno); + t = b; + tlen = strlen(t); + len += tlen; + off = p - bp; + ADD_SPACE_RET(sp, bp, blen, len); + p = bp + off; + memcpy(p, t, tlen); + p += tlen; + F_SET(excp, E_MODIFY); + break; + } + goto ins_ch; + /* #endif */ case '\\': /* * QUOTING NOTE: diff -c -r -N ../nvi-1.79.org/ex/ex_tag.c ./ex/ex_tag.c *** ../nvi-1.79.org/ex/ex_tag.c Mon Sep 16 05:02:43 1996 --- ./ex/ex_tag.c Fri Jul 13 13:39:47 2001 *************** *** 18,23 **** --- 18,26 ---- #include #include /* XXX: param.h may not have included types.h */ + /* #ifdef GTAGS */ + #include + /* #endif */ #ifdef HAVE_SYS_MMAN_H #include *************** *** 46,51 **** --- 49,58 ---- 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 *, 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 *)); *************** *** 110,117 **** --- 117,208 ---- size_t cno; long tl; int force, istmp; + /* #ifdef GTAGS */ + int Pflag, fflag; + char options[BUFSIZ]; + /* #endif */ exp = EXP(sp); + /* #ifdef GTAGS */ + /* + * In gtagsmode, you can use global(1)'s option in tag command. + * For example: + * :tag -r strcmp -- locate referenced point of strcmp. + * :tag -P /vm/ -- list files in 'vm' directory. + * :tag -g init -- locate occurrence of string 'init'. + */ + if (O_ISSET(sp, O_GTAGSMODE)) { + char *last, *file; + int i; + + Pflag = fflag = 0; + options[0] = 0; + for (i = 0; i < cmdp->argc && *cmdp->argv[i]->bp == '-'; i++) { + char *p = cmdp->argv[i]->bp; + if (*++p == '-') { /* long name option */ + msgq(sp, M_ERR, "long name option not available."); + return (1); + } else { /* short name option */ + if ( index(p, 'c') + || index(p, 'n') + || index(p, 'p') + || index(p, 'u') + || index(p, 'v') + ) { + msgq(sp, M_ERR, "-c, -n, -p, -u and -v option not available."); + return (1); + } + if (index(p, 'P')) + Pflag = 1; + if (index(p, 'f')) + fflag = 1; + } + if (strlen(options) + strlen(cmdp->argv[i]->bp) + 1 < BUFSIZ) { + strcat(options, cmdp->argv[i]->bp); + strcat(options, " "); + } + } + if (i < cmdp->argc) { /* tag name exist */ + /* + * In gtagsmode, only one argument can be accepted. + */ + last = cmdp->argv[cmdp->argc - 1]->bp; + /* + * filename substitution only for -f and -P option. + */ + if (fflag || Pflag) { + if (*(last + 1) == NULL && (*last == '%' || *last == '#')) { + char *file = (*last == '%') ? sp->frp->name : sp->alt_name; + if (file == NULL) { + msgq(sp, M_ERR, + "116|No filename to substitute for %%"); + return (1); + } + if (Pflag && rindex(file, '/')) + last = rindex(file, '/'); + else + last = file; + } + } + if (exp->tag_last != NULL) + free(exp->tag_last); + exp->tag_last = strdup(last); + /* Taglength may limit the number of characters. */ + if ((tl = + O_VAL(sp, O_TAGLENGTH)) != 0 && strlen(exp->tag_last) > tl) + exp->tag_last[tl] = '\0'; + } else { /* no tag name */ + if (exp->tag_last == NULL) { + if (Pflag) + exp->tag_last = strdup(""); + else { + msgq(sp, M_ERR, "158|No previous tag entered"); + return (1); + } + } + } + } else + /* #endif */ switch (cmdp->argc) { case 1: if (exp->tag_last != NULL) *************** *** 138,145 **** } /* Get the tag information. */ ! if ((tqp = ctag_slist(sp, exp->tag_last)) == NULL) ! return (1); /* * Allocate all necessary memory before swapping screens. Initialize --- 229,243 ---- } /* Get the tag information. */ ! /* #ifdef GTAGS */ ! if (O_ISSET(sp, O_GTAGSMODE)) { ! if ((tqp = gtag_slist(sp, options, exp->tag_last, !fflag)) == NULL) ! return (1); ! } else { ! /* #endif */ ! if ((tqp = ctag_slist(sp, exp->tag_last)) == NULL) ! return (1); ! } /* * Allocate all necessary memory before swapping screens. Initialize *************** *** 969,974 **** --- 1067,1255 ---- return (0); } + /* #ifdef GTAGS */ + /* + * The getentry() parses both standard and extended ctags -x format. + * + * [standard format] + * + * +------------------------------------------------ + * |main 30 main.c main(argc, argv) + * |func 21 subr.c func(arg) + * + * The following commands write this format. + * o Traditinal Ctags with -x option + * o Global with -x option + * See + * + * [extended format] + * + * +---------------------------------------------------------- + * |main function 30 main.c main(argc, argv) + * |func function 21 subr.c func(arg) + * + * The following commands write this format. + * o Exuberant Ctags with -x option + * See + * + * Returns 0 on success, -1 on error. + * The tag, file, and line will each be NUL-terminated pointers + * into buf. + */ + static int + getentry(buf, tag, file, line) + char *buf; /* standard or extended ctags -x format data */ + char **tag; /* name of the tag we actually found */ + char **file; /* file in which to find this tag */ + char **line; /* line number of file where this tag is found */ + { + 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; + /* + * If the second part begin with other than digit, + * it is assumed tag type. Skip it. + */ + if (!isdigit(*p)) { + for (; *p && !isspace(*p); p++) /* (skip tag type) */ + ; + for (; *p && isspace(*p); p++) /* (skip blanks) */ + ; + } + if (!isdigit(*p)) + 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 (0); /* OK */ + err: + return (-1); /* ERROR */ + } + + /* + * gtag_slist -- + * Search the list of tags files for a tag, and return tag queue. + * + * In almost case, quote should be 1. + * quote = 0 enables ':tag -f *.c'. + */ + static TAGQ * + gtag_slist(sp, options, tag, quote) + SCR *sp; + char *options; + char *tag; + int quote; + { + EX_PRIVATE *exp; + TAGF *tfp; + TAGQ *tqp; + size_t len; + TAG *tp; + char *name, *file, *line; + char command[BUFSIZ]; + char buf[BUFSIZ]; + char tmp[30]; + char *tmpname, *com; + 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. + */ + strcpy(tmp, "/tmp/.nvi+global.XXXX"); + tmpname = mktemp(tmp); + com = (quote) ? "global -xa %s '%s' 2>%s" : "global -xa %s %s 2>%s"; + snprintf(command, sizeof(command), com, options, tag, tmpname); + if (fp = popen(command, "r")) { + int status; + 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) + 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); + } + status = pclose(fp); + if (status) { + if (WEXITSTATUS(status) == 2) + msgq(sp, M_ERR, "invalid option of global(1)."); + else { + char msg[128]; + FILE *ip = fopen(tmpname, "r"); + msg[0] = '\0'; + if (ip) { + if (fgets(msg, sizeof(msg), ip)) { + if (msg[strlen(msg) - 1] == '\n') + msg[strlen(msg) - 1] = '\0'; + } + fclose(ip); + } + if (msg[0] == '\0') + strcpy(msg, "global(1) ended abnormally."); + msgq(sp, M_ERR, "%s", msg); + } + (void)unlink(tmpname); + free(tqp); + return (NULL); + } + } + (void)unlink(tmpname); + + /* 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 -c -r -N ../nvi-1.79.org/include/options_def.h ./include/options_def.h *** ../nvi-1.79.org/include/options_def.h Wed Oct 23 22:53:10 1996 --- ./include/options_def.h Fri Jul 13 13:38:45 2001 *************** *** 16,79 **** #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 --- 16,80 ---- #define O_EXTENDED 15 #define O_FILEC 16 #define O_FLASH 17 ! #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 -c -r -N ../nvi-1.79.org/vi/v_ex.c ./vi/v_ex.c *** ../nvi-1.79.org/vi/v_ex.c Mon Sep 16 05:03:02 1996 --- ./vi/v_ex.c Fri Jul 13 13:38:45 2001 *************** *** 223,233 **** SCR *sp; VICMD *vp; { ! ARGS *ap[2], a; EXCMD cmd; 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)); } --- 223,269 ---- SCR *sp; VICMD *vp; { ! /* #ifdef GTAGS */ ! ARGS *ap[2], a[2]; ! /* ! #else ! ARGS *ap[3], a; ! #endif ! */ EXCMD cmd; + /* #ifdef GTAGS */ + size_t len; + int isempty; + char *p, *opt; + /* #endif */ + /* #ifdef GTAGS */ + if (O_ISSET(sp, O_GTAGSMODE)) { + if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty) == 0) { + p += vp->m_start.cno; + if (!isalpha(*p) && *p != '_') + return 0; + while (*p && (isalnum(*p) || *p == '_')) + p++; + while (*p && isblank(*p)) + p++; + if (*p == '(') /* function */ + opt = (vp->m_start.cno == 0) ? "-r" : "-x"; + else /* other symbol */ + opt = "-s"; + } + } + /* #endif */ ex_cinit(&cmd, C_TAG, 0, OOBLNO, 0, 0, ap); + /* #ifdef GTAGS */ + if (O_ISSET(sp, O_GTAGSMODE)) + ex_cadd(&cmd, &a[0], opt, strlen(opt)); + ex_cadd(&cmd, &a[1], VIP(sp)->keyw, strlen(VIP(sp)->keyw)); + /* + #else ex_cadd(&cmd, &a, VIP(sp)->keyw, strlen(VIP(sp)->keyw)); + #endif + */ return (v_exec_ex(sp, vp, &cmd)); }