[PATCH] basic modelines for contrib/nvi
José de Paula
espinafre at gmail.com
Wed Jul 14 19:51:52 PDT 2004
I hacked together this little patch to contrib/nvi to make it support
simple modelines. The original author of nvi (Keith Bostic) says in
the sources that modelines are not to be implemented because of
security concerns, but I believe that implementing them after vim's
style (i.e., only allowing arguments to the 'set' option in modelines)
doesn't pose any security threat. Besides, I find them quite useful
when editing some specific files, for which I want specific settings.
Acceptable modelines are in the form: (ex/vi regex)
.*[[:blank:]]\+\(vi\)\|\(ex\):options
where 'options' are space- or colon-separated arguments to 'set'.
Well, please tell me what you think about it, and whether I should
file a PR to get this included. Without further ado, here is the
patch:
diff -Nru a/common/exf.c b/common/exf.c
--- a/common/exf.c Wed Jul 14 22:22:19 2004
+++ b/common/exf.c Wed Jul 14 23:33:17 2004
@@ -42,6 +42,83 @@
#include "common.h"
+char * parse_modeline(sp, line, size)
+ SCR *sp;
+ char *line;
+ int size;
+{
+ char *cmd, *ex;
+ int i;
+
+ cmd = malloc(sizeof (*cmd) * size);
+
+ if ( !(ex = strstr(line, "vi:")) && !(ex = strstr(line, "ex:")) )
+ return NULL; /* no modelines here */
+ if ( (ex != line) && !isblank(*(ex - 1)))
+ return NULL; /* no modelines here either */
+
+ /* What we have to do is initialize *cmd with 'set ',
+ * change colons to spaces and append the resulting mess
+ * to cmd.
+ */
+ strcpy(cmd, "set ");
+ i = strlen(cmd);
+ ex += 3;
+ while(*ex != '\n' && *ex != '\r' && i < size) /* run till end of line */
+ {
+ if(*ex == ':')
+ cmd[i] = ' ';
+ else
+ cmd[i] = *ex;
+ i++;
+ ex++;
+ }
+ cmd[i] = '\0';
+
+ return cmd;
+}
+
+/*
+ * We look for a modeline, and return a cooked string ready to be
+ * run by ex_run_str.
+ * the first one is found; if there is no modeline, return NULL.
+ */
+char * get_modeline(sp)
+ SCR * sp;
+{
+ char *cmd, *line;
+ int i, lnop, linesz, lineempty;
+
+ line = malloc(sizeof(*line) * 255); /* shall we have a modeline
longer than that? */
+
+ if (db_last(sp, &lnop))
+ return NULL;
+ if (lnop == 0)
+ return NULL;
+
+ for (i = 1; i <= lnop && i <= 5; i++)
+ {
+ db_eget(sp, i, &line, &linesz, &lineempty);
+ if(lineempty)
+ continue;
+ if ( (cmd = parse_modeline(sp, line, linesz)) != NULL)
+ return cmd;
+ }
+
+ /* just like before, but counting lines from bottom up */
+ for (i = lnop; i > 0 && i >= (lnop - 5); i--)
+ {
+ db_eget(sp, i, &line, &linesz, &lineempty);
+ if(lineempty)
+ continue;
+ if ( (cmd = parse_modeline(sp, line, linesz)) != NULL)
+ return cmd;
+ }
+
+ /* If we reached this point, there is nothing to return. Therefore, */
+ return NULL;
+}
+
static int file_backup __P((SCR *, char *, char *));
static void file_cinit __P((SCR *));
static void file_comment __P((SCR *));
@@ -520,6 +597,7 @@
MARK m;
size_t len;
int nb;
+ char *cmd;
/* Set some basic defaults. */
sp->lno = 1;
@@ -612,6 +690,14 @@
*/
m.lno = sp->lno;
m.cno = sp->cno;
+
+ if (O_ISSET(sp, O_MODELINE)) {
+ cmd = get_modeline(sp);
+ if (cmd != NULL)
+ if (ex_run_str(sp, "modeline", cmd, strlen(cmd), 0, 0))
+ return;
+ }
+
(void)mark_set(sp, ABSMARK1, &m, 0);
}
diff -Nru a/common/options.c b/common/options.c
--- a/common/options.c Wed Jul 14 22:22:19 2004
+++ b/common/options.c Wed Jul 14 22:32:54 2004
@@ -124,7 +124,7 @@
* example of what your intro CS professor referred to as the perils of
* mixing code and data. Don't add it, or I will kill you.
*/
- {"modeline", NULL, OPT_0BOOL, OPT_NOSET},
+ {"modeline", NULL, OPT_0BOOL, 0},
/* O_MSGCAT 4.4BSD */
{"msgcat", f_msgcat, OPT_STR, 0},
/* O_NOPRINT 4.4BSD */
More information about the freebsd-hackers
mailing list