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 <[email protected]>
+ *
+ * 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 */