[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