This diff allows mg to log its internal status to a file. At the moment it only logs line information like front and back pointers in the linked list, how many characters are used and where the cursor is placed in the file, but I am finding it incredibly useful debugging mg at the moment.

Below is an example log file after opening a file with this contents:

abc
def
ghk

After I open the file in mg, I move forward a line (C-n), then move forward a character (C-f):

$ cat log/mg.log
next-line
3 3 0xc3a3557ae00 b^0xc3a592eac20 f.0xc3a592ea4a0 abc
 3 3 0xc3a592ea4a0 b^0xc3a3557ae00 f.0xc3a592ea660 def
 3 3 0xc3a592ea660 b^0xc3a592ea4a0 f.0xc3a307830e0 ghk
 0 0 0xc3a307830e0 b^0xc3a592ea660 f.0xc3a592eac20 (null)
 head 0xc3a592eac20 b^0xc3a307830e0 f.0xc3a3557ae00
(EOB)

forward-char
 3 3 0xc3a3557ae00 b^0xc3a592eac20 f.0xc3a592ea4a0 abc
3 3 0xc3a592ea4a0 b^0xc3a3557ae00 f.0xc3a592ea660 def
 3 3 0xc3a592ea660 b^0xc3a592ea4a0 f.0xc3a307830e0 ghk
 0 0 0xc3a307830e0 b^0xc3a592ea660 f.0xc3a592eac20 (null)
 head 0xc3a592eac20 b^0xc3a307830e0 f.0xc3a3557ae00
(EOB)

The three columns of pointer addresses are (from the 'def' line):

0xc3a592ea4a0 the lines own pointer.
0xc3a3557ae00 the pointer to back(b^) line
0xc3a592ea660 the pointer to forward(f.) line

The numbers at the start of the first four lines are l_size and l_used.

With this diff logging is not switched on by default and has to compiled into mg. -DMGDEBUG has to be added to the Makefile:

CFLAGS+=-Wall -DREGEX  -DMGDEBUG

And the comment removed from:

#SRCS+=  log.c

The information logged at the moment is viewable by gdb, however, if a bug that I have introduced doesn't present itself for XX number of key presses, I can struggle to work out what has caused it in gdb, logging like this makes problems I have introduced much more obvious and easier to fix.

I have tried to make the ifdefs as minimal as possible. Any objections to this diff?

Mark

Index: Makefile
===================================================================
RCS file: /cvs/src/usr.bin/mg/Makefile,v
retrieving revision 1.33
diff -u -p -u -p -r1.33 Makefile
--- Makefile    16 Sep 2016 17:17:40 -0000      1.33
+++ Makefile    7 Jun 2019 14:42:39 -0000
@@ -9,6 +9,7 @@ DPADD+= ${LIBCURSES} ${LIBUTIL}
 #
 #      REGEX           -- create regular expression functions.
 #      STARTUPFILE     -- look for and handle initialization file.
+#      MGDEBUG         -- debug mg internals to a log file.
 #
 CFLAGS+=-Wall -DREGEX

@@ -22,6 +23,11 @@ SRCS=        autoexec.c basic.c bell.c buffer.c
 # More or less standalone extensions.
 #
 SRCS+= cmode.c cscope.c dired.c grep.c tags.c
+
+#
+# -DMGDEBUG source file.
+#
+#SRCS+=        log.c

 afterinstall:
        ${INSTALL} -d -o root -g wheel ${DESTDIR}${DOCDIR}/mg
Index: kbd.c
===================================================================
RCS file: /cvs/src/usr.bin/mg/kbd.c,v
retrieving revision 1.30
diff -u -p -u -p -r1.30 kbd.c
--- kbd.c       26 Sep 2015 21:51:58 -0000      1.30
+++ kbd.c       7 Jun 2019 14:42:39 -0000
@@ -15,6 +15,10 @@
 #include "key.h"
 #include "macro.h"

+#ifdef  MGDEBUG
+#include "log.h"
+#endif
+
 #define METABIT 0x80

 #define PROMPTL 80
@@ -151,6 +155,11 @@ doin(void)
        while ((funct = doscan(curmap, (key.k_chars[key.k_count++] =
            getkey(TRUE)), &curmap)) == NULL)
                /* nothing */;
+
+#ifdef  MGDEBUG
+       if (!mglog(funct))
+               ewprintf("Problem with logging");
+#endif

        if (macrodef && macrocount < MAXMACRO)
                macro[macrocount++].m_funct = funct;
Index: log.c
===================================================================
RCS file: log.c
diff -N log.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ log.c       7 Jun 2019 14:42:39 -0000
@@ -0,0 +1,121 @@
+/*     $OpenBSD$       */
+
+/* + * This file is in the public domain.
+ *
+ * Author: Mark Lumsden <m...@showcomplex.com>
+ *
+ */
+
+/*
+ * Record a history of an mg session for temporal debugging.
+ * Sometimes pressing a key will set the scene for a bug only visible + * dozens of keystrokes later. gdb has its limitations in this scenario.
+ */
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "def.h"
+#include "log.h"
+#include "funmap.h"
+
+static char    mglogpath[20];
+
+int
+mglog(PF funct)
+{
+       struct line     *lp;
+       struct stat      sb;
+       char            *curline;
+       FILE            *fd;
+       int              i;
+
+       i = 0;
+
+       if(stat(mglogpath, &sb))
+               return (FALSE);
+
+       fd = fopen(mglogpath, "a");
+       if (fprintf(fd, "%s\n", function_name(funct)) == -1) {
+               fclose(fd);
+               return (FALSE);
+       }
+       lp = bfirstlp(curbp);
+
+       for(;;) {
+               i++;
+               curline = " ";
+               if (i == curwp->w_dotline)
+                       curline = ">";
+               if (fprintf(fd, "%s%d %d %p b^%p f.%p %s\n", curline,
+                   lp->l_size, lp->l_used, lp, lp->l_bp, lp->l_fp,
+                   lp->l_text) == -1) {
+                       fclose(fd);
+                       return (FALSE);
+               }
+               lp = lforw(lp);
+               if (lp == curbp->b_headp) {
+                       if (fprintf(fd, " head %p b^%p f.%p\n(EOB)\n\n",
+                           lp, lp->l_bp, lp->l_fp) == -1) {
+                               fclose(fd);
+                               return (FALSE);
+                       }
+                       break;
+               }
+       }
+       fclose(fd);
+
+       return (TRUE);
+}
+
+
+/*
+ * Make sure logging to log file can happen.
+ */
+int
+mgloginit(void)
+{
+       struct stat      sb;
+       mode_t           dir_mode, f_mode, oumask;
+       char            *mglogdir;
+       int              fd;
+
+       mglogdir = "./log/";
+
+       oumask = umask(0);
+       f_mode = 0777& ~oumask;
+       dir_mode = f_mode | S_IWUSR | S_IXUSR;
+
+       if(stat(mglogdir, &sb)) {
+               if (mkdir(mglogdir, dir_mode) != 0)
+                       return (FALSE);
+               if (chmod(mglogdir, f_mode) < 0)
+                       return (FALSE);
+       }
+       if (strlcpy(mglogpath, mglogdir, sizeof(mglogpath)) >
+           sizeof(mglogpath))
+               return (FALSE);
+       if (strlcat(mglogpath, mglogfile, sizeof(mglogpath)) >
+           sizeof(mglogpath))
+               return (FALSE);
+
+       if(stat(mglogpath, &sb))
+               fd = open(mglogpath, O_RDWR | O_CREAT | O_TRUNC, 0644);
+       else
+               fd = open(mglogpath, O_RDWR | O_TRUNC, 0644);
+
+       if (fd == -1)
+               return (FALSE);
+
+ close(fd); +
+       return (TRUE);
+}
Index: log.h
===================================================================
RCS file: log.h
diff -N log.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ log.h       7 Jun 2019 14:42:39 -0000
@@ -0,0 +1,14 @@
+/*      $OpenBSD$   */
+
+/* This file is in the public domain. */
+
+/*
+ * Specifically for mg logging functionality.
+ *
+ */
+
+int                     mglog(PF);
+int                      mgloginit(void);
+
+extern char             *mglogfile;
+
Index: main.c
===================================================================
RCS file: /cvs/src/usr.bin/mg/main.c,v
retrieving revision 1.85
diff -u -p -u -p -r1.85 main.c
--- main.c      13 Dec 2018 14:59:16 -0000      1.85
+++ main.c      7 Jun 2019 14:42:39 -0000
@@ -21,6 +21,11 @@
 #include "funmap.h"
 #include "macro.h"

+#ifdef  MGDEBUG
+#include "log.h"
+char            *mglogfile = "mg.log";
+#endif
+
 int             thisflag;                      /* flags, this command  */
 int             lastflag;                      /* flags, last command  */
 int             curgoal;                       /* goal column          */
@@ -86,6 +91,11 @@ main(int argc, char **argv)

        maps_init();            /* Keymaps and modes.           */
        funmap_init();          /* Functions.                   */
+
+#ifdef  MGDEBUG
+       if (!mgloginit())
+               errx(1, "Unable to create logging environment.");
+#endif

        /*
         * This is where we initialize standalone extensions that should

Reply via email to