[metapost] make_text related scanning improvements
Marcel Krüger
tex at 2krueger.de
Fri May 18 14:27:30 CEST 2018
---- On Fri, 18 May 2018 11:32:57 +0200 Hans Hagen <j.hagen at xs4all.nl> wrote ----
> On 5/18/2018 11:22 AM, Taco Hoekwater wrote:
> > Hi,
> >
> >> On 18 May 2018, at 11:15, Hans Hagen <j.hagen at xs4all.nl> wrote:
> >>
> >> changing fundamentals like this nearly always have side effects ... you cannot always know how these tools are used (for decades) ... you solve one problem and introduces a new one .. such is the world of tex / mp
> >
> > As the original ‘author’ of the reimplementation I can attest to that!
> >
> > It took half a dozen minor adjustments to the reimplementation just to make it compatible with pre-existing metapost source files, due to subtle differences between the Pascal and C handling of whitespace. I am not saying the code cannot be improved at all, but it seems likely that any changes at this point will have side-effects that break already existing metapost source files.
> right, so
>
> btex ... etex
>
> will stay as it is, but i'll look if
>
> verbatimtex ... etex
>
> can optionally (!) deal with newlines
>
> Hans
While I do not think the ConTeXt behaviour of escapting quotes, but not escaping newlines makes sense, I agree that it might be best to be conservative here.
This is a version of my original change, which accepts newlines only for verbatimtex and only when a option is passed:
(I know this is not the approach you want to take, but I wrote it anyway for personal experiments, so I thought there is no harm in posting it)
@x
MP mp_initialize (MP_options * opt) {
MP mp;
jmp_buf *buf = malloc (sizeof (jmp_buf));
if (buf == NULL || setjmp (*buf) != 0)
return NULL;
mp = mp_do_new (buf);
if (mp == NULL)
return NULL;
mp->userdata = opt->userdata;
mp->noninteractive = opt->noninteractive;
mp->extensions = opt->extensions;
set_callback_option (find_file);
@y
MP mp_initialize (MP_options * opt) {
MP mp;
jmp_buf *buf = malloc (sizeof (jmp_buf));
if (buf == NULL || setjmp (*buf) != 0)
return NULL;
mp = mp_do_new (buf);
if (mp == NULL)
return NULL;
mp->userdata = opt->userdata;
mp->noninteractive = opt->noninteractive;
mp->extensions = opt->extensions;
mp->multiline_verbatimtex = opt->multiline_verbatimtex ;
set_callback_option (find_file);
@z
@x
@ @<Pass btex ... etex to script@>=
{
int first ;
while ((loc < limit - 4) && (mp->buffer[loc] == ' ')) {
incr(loc);
}
first = loc ;
if (mp->buffer[loc-1] == ' ') {
decr(loc);
}
while (loc < limit - 5) {
if (mp->buffer[loc] == ' ') {
incr(loc);
if (mp->buffer[loc] == 'e') {
incr(loc);
if (mp->buffer[loc] == 't') {
incr(loc) ;
if (mp->buffer[loc] == 'e') {
incr(loc) ;
if (mp->buffer[loc] == 'x') {
/* start action */
char *s, *txt ;
int size ;
mp_value new_expr;
size = loc - first + 1 - 4 ;
if (size < 0) {
size = 0 ;
} else {
while ((size > 1) && (mp->buffer[first+size-1] == ' ')) {
decr(size);
}
}
txt = malloc(size+1);
if (size > 0) {
(void) memcpy (txt, mp->buffer + first, size);
}
txt[size] = '\0';
incr(loc);
s = mp->make_text(mp,txt,(cur_mod() == verbatim_code)) ; /* we could pass the size */
@<Run a script@>
/* done */
free(txt);
break ;
} else {
// decr(loc) ;
}
}
}
}
} else {
incr(loc);
}
}
}
@y
@ @<Option variables@>=
int multiline_verbatimtex;
@ @<Pass btex ... etex to script@>=
{
char *s, *txt, *orig_txt ;
int size, first ;
quarterword cclass; /* the |char_class| of previous token */
mp_value new_expr;
old_info = line;
size = 0;
first = loc ;
cclass = mp->char_class[mp->buffer[loc - 1]] ;
while ( cclass == letter_class
|| loc + 4 > limit
|| memcmp("etex", mp->buffer + loc, 4)
|| (loc + 4 < limit && letter_class == mp->char_class[mp->buffer[loc + 4]])) {
cclass = mp->char_class[mp->buffer[loc]];
if (loc == limit) {
if (size) {
txt = realloc(txt, size + limit - first + 1);
} else {
txt = malloc(limit - first + 1);
}
(void) memcpy (txt + size, mp->buffer + first, limit - first);
size += limit - first + 1;
if (cur_mod() == verbatim_code && mp->multiline_verbatimtex) {
txt[size - 1] = '\n';
if (move_to_next_line(mp)) {
char msg[256];
const char *hlp[] = {
"The file ended while I was looking for the `etex' to",
"finish this TeX material. I've inserted `etex' now.",
NULL };
mp_snprintf(msg, 256, "TeX mode didn't end; all text was ignored after line %d", (int)old_info);
mp_error (mp, msg, hlp, false);
goto READING_FINISHED;
}
first = loc;
cclass = percent_class;
} else {
char msg[256];
const char *hlp[] = {
"The line ended while I was looking for the `etex' to",
"finish this TeX material. I've inserted `etex' now.",
NULL };
mp_snprintf(msg, 256, "TeX mode didn't end at line %d", (int)old_info);
mp_error (mp, msg, hlp, false);
goto READING_FINISHED;
}
} else {
incr(loc);
}
}
if (size) {
txt = realloc(txt, size + loc - first + 1);
} else {
txt = malloc(loc - first + 1);
}
(void) memcpy (txt + size, mp->buffer + first, loc - first);
size += loc - first + 1;
loc += 4;
READING_FINISHED:
if (cur_mod() == btex_code) {
while ((size > 1) && (cclass == space_class || txt[size - 2] == '\n')) {
decr(size);
cclass = mp->char_class[(ASCII_code) txt[size - 2]];
}
}
orig_txt = txt;
cclass = mp->char_class[(ASCII_code) txt[0]];
while ((size > 1) && (cclass == space_class || txt[0] == '\n')) {
incr(txt);
decr(size);
cclass = mp->char_class[(ASCII_code) txt[0]];
}
txt[size - 1] = '\0';
s = mp->make_text(mp,txt,(cur_mod() == verbatim_code)) ; /* we could pass the size */
@<Run a script@>
free(orig_txt);
}
@z
diff --git a/source/texk/web2c/mplibdir/lmplib.c b/source/texk/web2c/mplibdir/lmplib.c
index d90482b8..724a4cc3 100644
--- a/source/texk/web2c/mplibdir/lmplib.c
+++ b/source/texk/web2c/mplibdir/lmplib.c
@@ -262,6 +262,7 @@ typedef enum {
P_ERROR_LINE, P_MAX_LINE, P_RANDOM_SEED, P_MATH_MODE,
P_INTERACTION, P_INI_VERSION, P_MEM_NAME, P_JOB_NAME, P_FIND_FILE,
P_RUN_SCRIPT, P_MAKE_TEXT, P_SCRIPT_ERROR, P_EXTENSIONS,
+ P_MULTILINE_VERBATIMTEX,
P__SENTINEL } mplib_parm_idx;
typedef struct {
@@ -270,18 +271,19 @@ typedef struct {
} mplib_parm_struct;
static mplib_parm_struct mplib_parms[] = {
- {"error_line", P_ERROR_LINE },
- {"print_line", P_MAX_LINE },
- {"random_seed", P_RANDOM_SEED },
- {"interaction", P_INTERACTION },
- {"job_name", P_JOB_NAME },
- {"find_file", P_FIND_FILE },
- {"run_script", P_RUN_SCRIPT },
- {"make_text", P_MAKE_TEXT },
- {"script_error", P_SCRIPT_ERROR },
- {"extensions", P_EXTENSIONS },
- {"math_mode", P_MATH_MODE },
- {NULL, P__SENTINEL }
+ {"error_line", P_ERROR_LINE },
+ {"print_line", P_MAX_LINE },
+ {"random_seed", P_RANDOM_SEED },
+ {"interaction", P_INTERACTION },
+ {"job_name", P_JOB_NAME },
+ {"find_file", P_FIND_FILE },
+ {"run_script", P_RUN_SCRIPT },
+ {"make_text", P_MAKE_TEXT },
+ {"script_error", P_SCRIPT_ERROR },
+ {"extensions", P_EXTENSIONS },
+ {"math_mode", P_MATH_MODE },
+ {"multiline_verbatimtex", P_MULTILINE_VERBATIMTEX },
+ {NULL, P__SENTINEL }
};
@@ -489,6 +491,7 @@ static int mplib_new(lua_State * L)
options->userdata = (void *) L;
options->noninteractive = 1; /* required ! */
options->extensions = 0 ;
+ options->multiline_verbatimtex = 0 ;
options->find_file = mplib_find_file;
options->run_script = mplib_run_script;
options->make_text = mplib_make_text;
@@ -548,6 +551,9 @@ static int mplib_new(lua_State * L)
case P_EXTENSIONS:
options->extensions = (int)lua_tointeger(L, -1);
break;
+ case P_MULTILINE_VERBATIMTEX:
+ options->multiline_verbatimtex = (int)lua_tointeger(L, -1);
+ break;
default:
break;
}
Best regards
Marcel Krüger
More information about the metapost
mailing list