Re: make_text related scanning improvements
Marcel Krüger <[email protected]> Fri, 18 May 2018 14:27:30 +0200
| Newsgroups | gmane.comp.tex.metapost |
|---|---|
| Message-ID | <[email protected]> |
---- On Fri, 18 May 2018 11:32:57 +0200 Hans Hagen <[email protected]> wrote ---- > On 5/18/2018 11:22 AM, Taco Hoekwater wrote: > > Hi, > > > >> On 18 May 2018, at 11:15, Hans Hagen <[email protected]> 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 -- http://tug.org/metapost/