Date: Wed, 14 Jul 2004 23:51:51 -0300 From: =?ISO-8859-1?Q?Jos=E9_de_Paula?= <espinafre@gmail.com> To: freebsd-hackers@freebsd.org Subject: [PATCH] basic modelines for contrib/nvi Message-ID: <5ef8c2f004071419517bdc9f3e@mail.gmail.com>
next in thread | raw e-mail | index | archive | help
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 */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?5ef8c2f004071419517bdc9f3e>