On Thu, Mar 01, 2012 at 10:27:19AM +0100, Janne Johansson wrote:

> Is there a way to have less "magic numbers" here and actually have
> some readable #defines or anything?
> The code would of course be the same, but these numbered calls look ugly to 
> me.
> 
> </mode nitpick=off>

Here is a diff with #defines and also does pretty printing of lines in
cscope buffer like emacs.

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    1 Mar 2012 19:34:54 -0000
@@ -0,0 +1,423 @@
+/*
+ * 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 <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "def.h"
+
+#define CSSYMBOL 0
+#define CSDEFINITION 1
+#define CSCALLEDFUNCS 2
+#define CSCALLERFUNCS 3
+#define CSTEXT 4
+#define CSEGREP 6
+#define CSFINDFILE 7
+#define CSINCLUDES 8
+
+struct cstokens {
+       const char *fname;
+       const char *function;
+       const char *lineno;
+       const char *pattern;
+};
+
+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(struct buffer *, char *);
+static void csflush();
+static int  do_cscope(int);
+static int  getattr(char *, struct cstokens *);
+static int  jumptomatch();
+static void prettyprint(struct buffer *, struct cstokens *);
+static const char *ltrim(const char *);
+
+/*
+ * Find this symbol. Bound to C-c s s
+ */
+/* ARGSUSED */
+int
+cssymbol(int f, int n)
+{
+       return (do_cscope(CSSYMBOL));
+}
+
+/*
+ * Find this global definition. Bound to C-c s d
+ */
+/* ARGSUSED */int
+csdefinition(int f, int n)
+{
+       return (do_cscope(CSDEFINITION));
+}
+
+/*
+ * Find functions called by this function. Bound to C-c s l
+ */
+/* ARGSUSED */
+int
+csfuncalled(int f, int n)
+{
+       return (do_cscope(CSCALLEDFUNCS));
+}
+
+/*
+ * Find functions calling this function. Bound to C-c s c
+ */
+/* ARGSUSED */
+int
+cscallerfuncs(int f, int n)
+{
+       return (do_cscope(CSCALLERFUNCS));
+}
+
+/*
+ * Find this text. Bound to C-c s t
+ */
+/* ARGSUSED */
+int
+csfindtext(int f, int n)
+{
+       return (do_cscope(CSTEXT));
+}
+
+/*
+ * Find this egrep pattern. Bound to C-c s e
+ */
+/* ARGSUSED */
+int
+csegrep(int f, int n)
+{
+       return (do_cscope(CSEGREP));
+}
+
+/*
+ * Find this file. Bound to C-c s f
+ */
+/* ARGSUSED */
+int
+csfindfile(int f, int n)
+{
+       return (do_cscope(CSFINDFILE));
+}
+
+/*
+ * Find files #including this file. Bound to C-c s i
+ */
+/* ARGSUSED */
+int
+csfindinc(int f, int n)
+{
+       return (do_cscope(CSINCLUDES));
+}
+
+/*
+ * 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);
+       
+       /* All lines are '\n' terminated */
+       while ((buf = fgetln(fpipe, &len)) != NULL) {
+               buf[len - 1] = '\0';
+               if (addentry(bp, buf) != TRUE)
+                       return (FALSE);
+       }
+       pclose(fpipe);
+       return (popbuftop(bp, WNONE));
+}
+
+/*
+ * For each line read from cscope output, extract the tokens,
+ * add them to list and pretty print a line in *cscope* buffer.
+ */
+int
+addentry(struct buffer *bp, char *csline)
+{
+       struct csrecord *r;
+       struct csmatch *m;
+       struct cstokens t;
+       int lineno;
+       char buf[BUFSIZ];
+       const char *errstr;
+
+       r = NULL;
+       if (getattr(csline, &t) == FALSE)
+               return (FALSE);
+
+       lineno = strtonum(t.lineno, INT_MIN, INT_MAX, &errstr);
+       if (errstr)
+               return (FALSE);
+               
+       if (addentryfn == NULL || strcmp(addentryfn, t.fname) != 0) {
+               if ((r = malloc(sizeof(struct csrecord))) == NULL)
+                       goto cleanup;
+               addentryr = r;
+               if ((r->filename = strdup(t.fname)) == NULL)
+                       return (FALSE);
+               addentryfn = r->filename;
+               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);
+               addline(bp, "");
+               if (snprintf(buf, sizeof(buf), "*** %s", t.fname) < 0)
+                       goto cleanup;
+               addline(bp, buf);
+       } else {
+               if ((m = malloc(sizeof(struct csmatch))) == NULL)
+                       goto cleanup;
+               m->lineno = lineno;
+               TAILQ_INSERT_TAIL(&addentryr->matches, m, entry);
+       }
+       prettyprint(bp, &t);
+       return (TRUE);
+cleanup:
+       free(r);
+       return (FALSE);
+}
+
+/*
+ * Cscope line: <filename> <function> <lineno> <pattern>
+ */
+int
+getattr(char *line, struct cstokens *t)
+{
+       char *p;
+
+       if ((p = strchr(line, ' ')) == NULL)
+               return (FALSE);
+       *p++ = '\0';
+       t->fname = line;
+       line = p;
+
+       if ((p = strchr(line, ' ')) == NULL)
+               return (FALSE);
+       *p++ = '\0';
+       t->function = line;
+       line = p;
+
+       if ((p = strchr(line, ' ')) == NULL)
+               return (FALSE);
+       *p++ = '\0';
+       t->lineno = line;
+
+       if (*p == '\0')
+               return (FALSE);
+       t->pattern = p;
+
+       return (TRUE);
+}
+
+void
+prettyprint(struct buffer *bp, struct cstokens *t)
+{
+       char buf[BUFSIZ];
+
+       if (snprintf(buf, sizeof(buf), "%s[%s]\t\t%s",
+           t->function, t->lineno, ltrim(t->pattern)) < 0)
+               return;
+       addline(bp, buf);
+}
+
+const char *
+ltrim(const char *s)
+{
+       while (isspace(*s))
+               s++;
+       return s;
+}
+
+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