On Fri, Sep 02, 2011 at 02:23:28PM -0300, Christiano F. Haesbaert wrote:
> On 2 September 2011 14:17, Matthew Dempsky <matt...@dempsky.org> wrote:
> > On Fri, Sep 2, 2011 at 8:55 AM, Sunil Nimmagadda
> > <su...@sunilnimmagadda.com> wrote:
> >> This diff adds tags support to Mg. I am NOT an emacs user so if this
> >> combination is a bit odd then please excuse. It parses the tags file
> >> generated by ctags(1) and maintains a tree. M-. on first character of
> >> a word jumps to it's definition and M-* jumps back to previous location.
> >
> > I'd love to have ctags support in mg.
> >
> 
> cscope would be cool too, if not too much bloat.

This diff adds some cscope support in mg. Keybindings are same as
xcscope that comes with emacs.

Find this symbol C-c s s
Find this global definition C-c s d
Find functions called by this function C-c s l
Find functions calling this function C-c s c
Find this text C-c s t
Find this egrep pattern C-c s e
Find this file C-c s f
Find files #including this file C-c s i

Find next symbol C-c s n
Find prev symbol C-c s p

Comments?

Index: Makefile
===================================================================
RCS file: /home/sunil/cvs/src/usr.bin/mg/Makefile,v
retrieving revision 1.25
diff -u -p -r1.25 Makefile
--- Makefile    28 Nov 2011 04:41:39 -0000      1.25
+++ Makefile    29 Feb 2012 18:06:23 -0000
@@ -2,6 +2,9 @@
 
 PROG=  mg
 
+#Uncomment to build cscope support. Cscope package is required.
+CSCOPE= yes
+
 LDADD+=        -lcurses -lutil
 DPADD+=        ${LIBCURSES} ${LIBUTIL}
 
@@ -25,6 +28,11 @@ SRCS=        autoexec.c basic.c buffer.c cinfo.
 # More or less standalone extensions.
 #
 SRCS+= cmode.c dired.c grep.c tags.c theo.c
+
+.ifdef CSCOPE
+CFLAGS+= -DCSCOPE
+SRCS+= cscope.c
+.endif
 
 afterinstall:
        ${INSTALL} -d ${DESTDIR}${DOCDIR}/mg
Index: buffer.c
===================================================================
RCS file: /home/sunil/cvs/src/usr.bin/mg/buffer.c,v
retrieving revision 1.77
diff -u -p -r1.77 buffer.c
--- buffer.c    23 Jan 2011 00:45:03 -0000      1.77
+++ buffer.c    29 Feb 2012 16:51:02 -0000
@@ -792,10 +792,8 @@ notmodified(int f, int n)
        return (TRUE);
 }
 
-#ifndef NO_HELP
 /*
- * Popbuf and set all windows to top of buffer.         Currently only used by
- * help functions.
+ * Popbuf and set all windows to top of buffer.
  */
 int
 popbuftop(struct buffer *bp, int flags)
@@ -814,7 +812,6 @@ popbuftop(struct buffer *bp, int flags)
        }
        return (popbuf(bp, flags) != NULL);
 }
-#endif
 
 /*
  * Return the working directory for the current buffer, terminated
Index: cscope.c
===================================================================
RCS file: cscope.c
diff -N cscope.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ cscope.c    29 Feb 2012 17:49:50 -0000
@@ -0,0 +1,378 @@
+/*
+ * Copyright (c) 2012 Sunil Nimmagadda <su...@sunilnimmagadda.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/queue.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "def.h"
+
+struct csmatch {
+       TAILQ_ENTRY(csmatch) entry;
+       int lineno;
+};
+
+struct csrecord {
+       TAILQ_ENTRY(csrecord) entry;
+       char *filename;
+       TAILQ_HEAD(matches, csmatch) matches;
+};
+
+static TAILQ_HEAD(csrecords, csrecord) csrecords = 
TAILQ_HEAD_INITIALIZER(csrecords);
+static struct csrecord *addentryr;
+static struct csrecord *currecord;
+static struct csmatch  *curmatch;
+static const char      *addentryfn;
+static const char      *csprompt[] = {
+       "Find this symbol: ",
+       "Find this global definition: ",
+       "Find functions called by this function: ",
+       "Find functions calling this function: ",
+       "Find this text string: ",
+       "Change this text string: ",
+       "Find this egrep pattern: ",
+       "Find this file: ",
+       "Find files #including this file: "
+};
+
+static int  addentry(const char *);
+static void csflush();
+static int  do_cscope(int);
+static int  getattr(const char *, char **, int *);
+static int  jumptomatch();
+
+/*
+ * Find this symbol. Bound to C-c s s
+ */
+/* ARGSUSED */
+int
+cssymbol(int f, int n)
+{
+       return (do_cscope(0));
+}
+
+/*
+ * Find this global definition. Bound to C-c s d
+ */
+/* ARGSUSED */int
+csdefinition(int f, int n)
+{
+       return (do_cscope(1));
+}
+
+/*
+ * Find functions called by this function. Bound to C-c s l
+ */
+/* ARGSUSED */
+int
+csfuncalled(int f, int n)
+{
+       return (do_cscope(2));
+}
+
+/*
+ * Find functions calling this function. Bound to C-c s c
+ */
+/* ARGSUSED */
+int
+cscallerfuncs(int f, int n)
+{
+       return (do_cscope(3));
+}
+
+/*
+ * Find this text. Bound to C-c s t
+ */
+/* ARGSUSED */
+int
+csfindtext(int f, int n)
+{
+       return (do_cscope(4));
+}
+
+/*
+ * Find this egrep pattern. Bound to C-c s e
+ */
+/* ARGSUSED */
+int
+csegrep(int f, int n)
+{
+       return (do_cscope(6));
+}
+
+/*
+ * Find this file. Bound to C-c s f
+ */
+/* ARGSUSED */
+int
+csfindfile(int f, int n)
+{
+       return (do_cscope(7));
+}
+
+/*
+ * Find files #including this file. Bound to C-c s i
+ */
+/* ARGSUSED */
+int
+csfindinc(int f, int n)
+{
+       return (do_cscope(8));
+}
+
+/*
+ * Next Symbol. Bound to C-c s n
+ */
+/* ARGSUSED */
+int
+csnextmatch(int f, int n)
+{
+       struct csrecord *r;
+       struct csmatch *m;
+       
+       if (curmatch == NULL) {
+               if ((r = TAILQ_FIRST(&csrecords)) == NULL) {
+                       ewprintf("The *cscope* buffer does not exist yet");
+                       return (FALSE);
+               }
+               currecord = r;
+               curmatch = TAILQ_FIRST(&r->matches);
+       } else {
+               m = TAILQ_NEXT(curmatch, entry);
+               if (m == NULL) {
+                       r = TAILQ_NEXT(currecord, entry);
+                       if (r == NULL) {
+                               ewprintf("The end of *cscope* buffer has been 
reached");
+                               return (FALSE);
+                       } else {
+                               currecord = r;
+                               curmatch = TAILQ_FIRST(&currecord->matches);
+                       }
+               } else
+                       curmatch = m;
+       }
+       return (jumptomatch());
+}
+
+/*
+ * Previous Symbol. Bound to C-c s p
+ */
+/* ARGSUSED */
+int
+csprevmatch(int f, int n)
+{
+       struct csmatch *m;
+       struct csrecord *r;
+
+       if (curmatch == NULL)
+               return (FALSE);
+       else {
+               m  = TAILQ_PREV(curmatch, matches, entry);
+               if (m)
+                       curmatch = m;
+               else {
+                       r = TAILQ_PREV(currecord, csrecords, entry);
+                       if (r == NULL) {
+                               ewprintf("The beginning of *cscope* buffer has 
been reached");
+                               return (FALSE);
+                       } else {
+                               currecord = r;
+                               curmatch = TAILQ_LAST(&currecord->matches, 
matches);
+                       }
+               }
+       }
+       return (jumptomatch());
+}
+
+/*
+ * The current symbol location is extracted from currecord->filename and 
+ * curmatch->lineno. Load the file similar to filevisit and goto the 
+ * lineno recorded.
+ */
+int
+jumptomatch()
+{
+       struct buffer *bp;
+       char *adjf;
+       
+       if (curmatch == NULL || currecord == NULL)
+               return (FALSE);
+       adjf = adjustname(currecord->filename, TRUE);
+       if (adjf == NULL)
+               return (FALSE);
+       if ((bp = findbuffer(adjf)) == NULL)
+               return (FALSE);
+       curbp = bp;
+       if (showbuffer(bp, curwp, WFFULL) != TRUE)
+               return (FALSE);
+       if (bp->b_fname[0] == '\0') {
+               if (readin(adjf) != TRUE)
+                       killbuffer(bp);
+       }
+       gotoline(FFARG, curmatch->lineno);
+       return (TRUE);
+       
+}
+
+/*
+ * Ask for the symbol, construct cscope commandline with the symbol
+ * and passed in index. Popen cscope, read the output into *cscope* 
+ * buffer and pop it.
+ */
+int
+do_cscope(int i)
+{
+       struct buffer *bp;
+       FILE *fpipe;
+       char pattern[BUFSIZ], cmd[BUFSIZ], title[BUFSIZ], *p, *buf;
+       int clen;
+       size_t len;
+
+       p = eread(csprompt[i], pattern, BUFSIZ, EFNEW | EFNUL);
+       if (p == NULL)
+               return (FALSE);
+       else if (p[0] == '\0')
+               return (FALSE);
+
+       csflush();
+       clen = snprintf(cmd, sizeof(cmd), "cscope -L -%d %s 2>/dev/null", i, 
pattern);
+       if (clen < 0 || clen >= sizeof(cmd))
+               return (FALSE);
+
+       if ((fpipe = popen(cmd, "r")) == NULL) {
+               ewprintf("problem opening pipe");
+               return (FALSE);
+       }
+       
+       bp = bfind("*cscope*", TRUE);
+       if (bclear(bp) != TRUE)
+               return (FALSE);
+       bp->b_flag |= BFREADONLY;
+
+       clen = snprintf(title, sizeof(title), "%s%s", csprompt[i], pattern);
+       if (clen < 0 || clen >= sizeof(title))
+               return (FALSE);
+       addline(bp, title);
+       addline(bp, ""); /* blank line */
+       
+       /* All lines are '\n' terminated */
+       while ((buf = fgetln(fpipe, &len)) != NULL) {
+               if (addentry(buf) != TRUE)
+                       return (FALSE);
+               buf[len - 1] = '\0';
+               addline(bp, buf);
+       }
+       pclose(fpipe);
+       return (popbuftop(bp, WNONE));
+}
+
+/*
+ * For each line read from cscope output, extract the filename and lineno
+ * attributes and add them to the list.
+ */
+int
+addentry(const char *csline)
+{
+       struct csrecord *r;
+       struct csmatch *m;
+       int lineno;
+       char *fname;
+
+       r = NULL;
+       if (getattr(csline, &fname, &lineno) == FALSE)
+               return (FALSE);
+       if (addentryfn == NULL || strcmp(addentryfn, fname) != 0) {
+               if ((r = malloc(sizeof(struct csrecord))) == NULL)
+                       goto cleanup;
+               addentryr = r;
+               r->filename = fname;
+               addentryfn = fname;
+               TAILQ_INIT(&r->matches);
+               if ((m = malloc(sizeof(struct csmatch))) == NULL)
+                       goto cleanup;
+               m->lineno = lineno;     
+               TAILQ_INSERT_TAIL(&r->matches, m, entry);
+               TAILQ_INSERT_TAIL(&csrecords, r, entry);
+       } else {
+               if ((m = malloc(sizeof(struct csmatch))) == NULL)
+                       goto cleanup;
+               m->lineno = lineno;
+               TAILQ_INSERT_TAIL(&addentryr->matches, m, entry);
+       }
+       return (TRUE);
+cleanup:
+       free(r);
+       free(fname);
+       return (FALSE);
+}
+
+/*
+ * A cscope line is of the form <filename> <function> <lineno> <text pattern>
+ * Extract the filename and lineno parts and return them.
+ */
+int
+getattr(const char *csline, char **fname, int *lineno)
+{
+       char *p, *line, *strlineno;     
+       const char *errstr;
+       
+       /* get the filename column */
+       if ((p = strchr(csline, ' ')) == NULL)
+               return (FALSE);
+       line = p + 1;
+       if ((*fname = strndup(csline, p - csline)) == NULL)
+               return (FALSE);
+       /* ignore function column */
+       if ((p = strchr(line, ' ')) == NULL)
+               return (FALSE);
+       line = p + 1;
+       /* extract lineno */
+       if ((p = strchr(line, ' ')) == NULL)
+               return (FALSE);
+       if ((strlineno = strndup(line, p - line)) == NULL)
+               return (FALSE);
+       *lineno = strtonum(strlineno, INT_MIN, INT_MAX, &errstr);
+       if (errstr)
+               return (FALSE);
+               
+       return (TRUE);
+}
+
+/*
+ * Delete entries and free memory.
+ */
+void
+csflush()
+{
+       struct csrecord *r;
+       struct csmatch *m;
+       
+       while ((r = TAILQ_FIRST(&csrecords)) != NULL) {
+               free(r->filename);
+               while ((m = TAILQ_FIRST(&r->matches)) != NULL) {
+                       TAILQ_REMOVE(&r->matches, m, entry);
+                       free(m);
+               }
+               TAILQ_REMOVE(&csrecords, r, entry);
+               free(r);
+       }
+       addentryr = NULL;
+       addentryfn = NULL;
+       currecord = NULL;
+       curmatch = NULL;
+}
Index: def.h
===================================================================
RCS file: /home/sunil/cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.118
diff -u -p -r1.118 def.h
--- def.h       10 Dec 2011 14:09:48 -0000      1.118
+++ def.h       29 Feb 2012 16:51:02 -0000
@@ -520,6 +520,20 @@ int                 findtag(int, int);
 int             poptag(int, int);
 int             tagsvisit(int, int);
 
+#ifdef CSCOPE
+/* cscope.c */
+int            cssymbol(int, int);
+int            csdefinition(int, int);
+int            csfuncalled(int, int);
+int            cscallerfuncs(int, int);
+int            csfindtext(int, int);
+int            csegrep(int, int);
+int            csfindfile(int, int);
+int            csfindinc(int, int);
+int            csnextmatch(int, int);
+int            csprevmatch(int, int);
+#endif /* CSCOPE */
+
 /* extend.c X */
 int             insert(int, int);
 int             bindtokey(int, int);
Index: funmap.c
===================================================================
RCS file: /home/sunil/cvs/src/usr.bin/mg/funmap.c,v
retrieving revision 1.35
diff -u -p -r1.35 funmap.c
--- funmap.c    28 Nov 2011 04:41:39 -0000      1.35
+++ funmap.c    29 Feb 2012 18:00:14 -0000
@@ -196,6 +196,18 @@ static struct funmap functnames[] = {
        {showcpos, "what-cursor-position",},
        {filewrite, "write-file",},
        {yank, "yank",},
+#ifdef CSCOPE
+       {cssymbol, "cscope-find-this-symbol",},
+       {csdefinition, "cscope-find-global-definition",},
+       {csfuncalled, "cscope-find-called-functions",},
+       {cscallerfuncs, "cscope-find-functions-calling-this-function",},
+       {csfindtext, "cscope-find-this-text-string",},
+       {csegrep, "cscope-find-egrep-pattern",},
+       {csfindfile, "cscope-find-this-file",},
+       {csfindinc, "cscope-find-files-including-file",},
+       {csnextmatch, "cscope-next-symbol",},
+       {csprevmatch, "cscope-prev-symbol",},
+#endif /* CSCOPE */
        {NULL, NULL,}
 };
 
Index: keymap.c
===================================================================
RCS file: /home/sunil/cvs/src/usr.bin/mg/keymap.c,v
retrieving revision 1.46
diff -u -p -r1.46 keymap.c
--- keymap.c    28 Nov 2011 04:41:39 -0000      1.46
+++ keymap.c    29 Feb 2012 16:51:02 -0000
@@ -41,6 +41,57 @@ struct KEYMAPE (2 + IMAPEXT) helpmap = {
 };
 #endif /* !NO_HELP */
 
+#ifdef CSCOPE
+static PF cCsc[] = {
+       cscallerfuncs,          /* c */
+       csdefinition,           /* d */
+       csegrep,                /* e */
+       csfindfile,             /* f */
+       rescan,                 /* g */
+       rescan,                 /* h */
+       csfindinc,              /* i */
+       rescan,                 /* j */
+       rescan,                 /* k */
+       rescan,                 /* l */
+       rescan,                 /* m */
+       csnextmatch,            /* n */
+       rescan,                 /* o */
+       csprevmatch,            /* p */
+       rescan,                 /* q */
+       rescan,                 /* r */ 
+       cssymbol,               /* s */
+       csfindtext              /* t */
+};
+
+static struct KEYMAPE (1 + IMAPEXT) cCsmap = {
+       1,
+       1 + IMAPEXT,
+       rescan,
+       {
+               {
+                       'c', 't', cCsc, NULL
+               }
+       }
+};
+
+static PF cCs[] = {
+       NULL                    /* s */
+};
+
+struct KEYMAPE (2 + IMAPEXT) ccmap = {
+       2,
+       2 + IMAPEXT,
+       rescan,
+       {
+               {
+                       CCHR('@'), CCHR('@'), (PF[]){ rescan }, NULL
+               },
+               {
+                       's', 's', cCs, (KEYMAP *) & cCsmap
+               }
+       }
+};
+#else
 struct KEYMAPE (1 + IMAPEXT) ccmap = {
        1,
        1 + IMAPEXT,
@@ -51,7 +102,7 @@ struct KEYMAPE (1 + IMAPEXT) ccmap = {
                }
        }
 };
-
+#endif /* CSCOPE */
 
 static PF cX4cF[] = {
        poptofile,              /* ^f */

Reply via email to