texlive[43128] Build/source/texk/web2c/luatexdir: luatexdir: sync

commits+kakuto at tug.org commits+kakuto at tug.org
Fri Feb 3 22:33:11 CET 2017


Revision: 43128
          http://tug.org/svn/texlive?view=revision&revision=43128
Author:   kakuto
Date:     2017-02-03 22:33:11 +0100 (Fri, 03 Feb 2017)
Log Message:
-----------
luatexdir: sync with the upstream (1.0.3)

Modified Paths:
--------------
    trunk/Build/source/texk/web2c/luatexdir/font/luafont.w
    trunk/Build/source/texk/web2c/luatexdir/font/texfont.h
    trunk/Build/source/texk/web2c/luatexdir/font/texfont.w
    trunk/Build/source/texk/web2c/luatexdir/font/writefont.w
    trunk/Build/source/texk/web2c/luatexdir/image/image.h
    trunk/Build/source/texk/web2c/luatexdir/image/writejpg.w
    trunk/Build/source/texk/web2c/luatexdir/lua/lcallbacklib.c
    trunk/Build/source/texk/web2c/luatexdir/lua/limglib.c
    trunk/Build/source/texk/web2c/luatexdir/lua/lnodelib.c
    trunk/Build/source/texk/web2c/luatexdir/lua/lpdflib.c
    trunk/Build/source/texk/web2c/luatexdir/lua/ltexlib.c
    trunk/Build/source/texk/web2c/luatexdir/lua/luatex-api.h
    trunk/Build/source/texk/web2c/luatexdir/luatex.c
    trunk/Build/source/texk/web2c/luatexdir/luatexcallbackids.h
    trunk/Build/source/texk/web2c/luatexdir/pdf/pdfgen.w
    trunk/Build/source/texk/web2c/luatexdir/pdf/pdfglyph.w
    trunk/Build/source/texk/web2c/luatexdir/pdf/pdflistout.w
    trunk/Build/source/texk/web2c/luatexdir/pdf/pdftables.h
    trunk/Build/source/texk/web2c/luatexdir/pdf/pdftypes.h
    trunk/Build/source/texk/web2c/luatexdir/tex/buildpage.w
    trunk/Build/source/texk/web2c/luatexdir/tex/commands.w
    trunk/Build/source/texk/web2c/luatexdir/tex/dumpdata.w
    trunk/Build/source/texk/web2c/luatexdir/tex/equivalents.h
    trunk/Build/source/texk/web2c/luatexdir/tex/linebreak.h
    trunk/Build/source/texk/web2c/luatexdir/tex/linebreak.w
    trunk/Build/source/texk/web2c/luatexdir/tex/mlist.w
    trunk/Build/source/texk/web2c/luatexdir/tex/packaging.h
    trunk/Build/source/texk/web2c/luatexdir/tex/packaging.w
    trunk/Build/source/texk/web2c/luatexdir/tex/scanning.w
    trunk/Build/source/texk/web2c/luatexdir/tex/texmath.w
    trunk/Build/source/texk/web2c/luatexdir/tex/texnodes.h
    trunk/Build/source/texk/web2c/luatexdir/tex/texnodes.w
    trunk/Build/source/texk/web2c/luatexdir/tex/textoken.w

Modified: trunk/Build/source/texk/web2c/luatexdir/font/luafont.w
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/font/luafont.w	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/font/luafont.w	2017-02-03 21:33:11 UTC (rev 43128)
@@ -29,6 +29,14 @@
     "unknown", "virtual", "real", NULL
 };
 
+const char *font_writingmode_strings[] = {
+    "unknown", "horizontal", "vertical", NULL
+};
+
+const char *font_identity_strings[] = {
+    "unknown", "horizontal", "vertical", NULL
+};
+
 const char *font_format_strings[] = {
     "unknown", "type1", "type3", "truetype", "opentype", NULL
 };
@@ -427,6 +435,8 @@
     dump_booleanfield(L,used,(font_used(f) ? true : false));
     dump_stringfield(L,type,font_type_strings[font_type(f)]);
     dump_stringfield(L,format,font_format_strings[font_format(f)]);
+    dump_stringfield(L,writingmode,font_writingmode_strings[font_writingmode(f)]);
+    dump_stringfield(L,identity,font_identity_strings[font_identity(f)]);
     dump_stringfield(L,embedding,font_embedding_strings[font_embedding(f)]);
 
     dump_intfield(L,units_per_em,font_units_per_em(f));
@@ -1409,6 +1419,10 @@
     set_font_type(f, i);
     i = n_enum_field(L, lua_key_index(format), unknown_format, font_format_strings);
     set_font_format(f, i);
+    i = n_enum_field(L, lua_key_index(writingmode), unknown_writingmode, font_writingmode_strings);
+    set_font_writingmode(f, i);
+    i = n_enum_field(L, lua_key_index(identity), unknown_identity, font_identity_strings);
+    set_font_identity(f, i);
     i = n_enum_field(L, lua_key_index(embedding), unknown_embedding, font_embedding_strings);
     set_font_embedding(f, i);
     if (font_encodingbytes(f) == 0 && (font_format(f) == opentype_format || font_format(f) == truetype_format)) {

Modified: trunk/Build/source/texk/web2c/luatexdir/font/texfont.h
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/font/texfont.h	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/font/texfont.h	2017-02-03 21:33:11 UTC (rev 43128)
@@ -150,6 +150,8 @@
     fm_entry *_font_map;
     int _font_type;
     int _font_format;
+    int _font_writingmode;
+    int _font_identity;
     int _font_embedding;
     int _font_bc;
     int _hyphen_char;
@@ -191,6 +193,18 @@
 } font_formats;
 
 typedef enum {
+    unknown_writingmode = 0,
+    horizontal_writingmode,
+    vertical_writingmode,
+} writingmode_types;
+
+typedef enum {
+    unknown_identity = 0,
+    horizontal_identity,
+    vertical_identity,
+} identity_types;
+
+typedef enum {
     unknown_embedding = 0,
     no_embedding,
     subset_embedding,
@@ -199,6 +213,8 @@
 
 extern const char *font_type_strings[];
 extern const char *font_format_strings[];
+extern const char *font_writingmodes_strings[];
+extern const char *font_identity_strings[];
 extern const char *font_embedding_strings[];
 
 #  define font_checksum(a)           font_tables[a]->_font_checksum
@@ -249,7 +265,6 @@
                                           strcmp(font_fullname(a),font_fullname(b))))
 #  define cmp_font_encodingname(a,b)     (!(font_encoding(a)!=NULL || font_encodingname(b)!=NULL || \
                                           strcmp(font_encodingname(a),font_encodingname(b))))
-
 #  define font_bc(a)                     font_tables[a]->_font_bc
 #  define set_font_bc(f,b)               font_bc(f) = b
 
@@ -269,6 +284,14 @@
 #  define font_format_name(a)            font_format_strings[font_tables[a]->_font_format]
 #  define set_font_format(a,b)           font_format(a) = b
 
+#  define font_writingmode(a)            font_tables[a]->_font_writingmode
+#  define font_writingmode_name(a)       font_writingmode_strings[font_tables[a]->_font_writingmode]
+#  define set_font_writingmode(a,b)      font_writingmode(a) = b
+
+#  define font_identity(a)               font_tables[a]->_font_identity
+#  define font_identity_name(a)          font_identity_strings[font_tables[a]->_font_identity]
+#  define set_font_identity(a,b)         font_identity(a) = b
+
 #  define font_embedding(a)              font_tables[a]->_font_embedding
 #  define set_font_embedding(a,b)        font_embedding(a) = b
 

Modified: trunk/Build/source/texk/web2c/luatexdir/font/texfont.w
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/font/texfont.w	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/font/texfont.w	2017-02-03 21:33:11 UTC (rev 43128)
@@ -113,11 +113,13 @@
     font_tables[id]->_param_base = NULL;
     font_tables[id]->_math_param_base = NULL;
 
-    set_font_bc(id, 1);         /* ec = 0 */
+    set_font_bc(id, 1);          /* ec = 0 */
+    set_font_writingmode(id, 0);
+    set_font_identity(id, 0);
     set_hyphen_char(id, '-');
     set_skew_char(id, -1);
-    font_slant(id) = 0;         /* vertical */
-    font_extend(id) = 1000;     /* normal width */
+    font_slant(id) = 0;          /* vertical */
+    font_extend(id) = 1000;      /* normal width */
 
     /* allocate eight values including 0 */
     set_font_params(id, 7);
@@ -1537,6 +1539,8 @@
     dump_int(f->_font_tounicode);
     dump_int(f->_font_type);
     dump_int(f->_font_format);
+    dump_int(f->_font_writingmode);
+    dump_int(f->_font_identity);
     dump_int(f->_font_embedding);
     dump_int(f->_font_bc);
     dump_int(f->_hyphen_char);
@@ -1714,6 +1718,8 @@
     undump_int(x); f->_font_tounicode = (char)x;
     undump_int(x); f->_font_type = x;
     undump_int(x); f->_font_format = x;
+    undump_int(x); f->_font_writingmode = x;
+    undump_int(x); f->_font_identity = x;
     undump_int(x); f->_font_embedding = x;
     undump_int(x); f->_font_bc = x;
     undump_int(x); f->_hyphen_char = x;

Modified: trunk/Build/source/texk/web2c/luatexdir/font/writefont.w
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/font/writefont.w	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/font/writefont.w	2017-02-03 21:33:11 UTC (rev 43128)
@@ -569,8 +569,9 @@
                 assert(0);
         }
     }
-    if (cidset != 0)
+    if ((! pdf->omit_cidset) && (cidset != 0)) {
         pdf_dict_add_ref(pdf, "CIDSet", cidset);
+    }
     /* TODO: Other optional keys for CID fonts.
        The most interesting one is
        \.{/Style << /Panose <12-byte string>>>}
@@ -1006,7 +1007,11 @@
     pdf_begin_dict(pdf);
     pdf_dict_add_name(pdf, "Type", "Font");
     pdf_dict_add_name(pdf, "Subtype", "Type0");
-    pdf_dict_add_name(pdf, "Encoding", "Identity-H");
+    if (font_identity(f) == vertical_identity) {
+        pdf_dict_add_name(pdf, "Encoding", "Identity-V");
+    } else {
+        pdf_dict_add_name(pdf, "Encoding", "Identity-H");
+    }
     pdf_dict_add_fontname(pdf, "BaseFont", fo->fd);
     i = pdf_create_obj(pdf, obj_type_others, 0);
     pdf_add_name(pdf, "DescendantFonts");

Modified: trunk/Build/source/texk/web2c/luatexdir/image/image.h
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/image/image.h	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/image/image.h	2017-02-03 21:33:11 UTC (rev 43128)
@@ -105,6 +105,7 @@
     int x_res;                  /* pixel resolution as in JPG/PNG/JBIG2 file */
     int y_res;
     int rotation;               /* rotation (multiples of 90 deg.) for PDF files */
+    int orientation;            /* jpeg orientation, 0=unset, 1=ul, 2=ur, 3=lr, 4=ll, 5-8 flipped */
     int colorspace;             /* number of /ColorSpace object */
     int group_ref;              /* if it's <=0, the page has no group */
     int total_pages;
@@ -149,6 +150,7 @@
 #  define img_xres(N)             ((N)->x_res)
 #  define img_yres(N)             ((N)->y_res)
 #  define img_rotation(N)         ((N)->rotation)
+#  define img_orientation(N)      ((N)->orientation)
 #  define img_colorspace(N)       ((N)->colorspace)
 #  define img_group_ref(N)        ((N)->group_ref)
 #  define img_totalpages(N)       ((N)->total_pages)

Modified: trunk/Build/source/texk/web2c/luatexdir/image/writejpg.w
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/image/writejpg.w	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/image/writejpg.w	2017-02-03 21:33:11 UTC (rev 43128)
@@ -98,22 +98,6 @@
 } JPEG_MARKER;
 
 @ @c
-static unsigned char myget_unsigned_byte (FILE *file)
-{
-    int ch;
-    ch = fgetc (file);
-    return (unsigned char) ch;
-}
-
-@ @c
-static unsigned short myget_unsigned_pair (FILE *file)
-{
-    unsigned short pair = myget_unsigned_byte(file);
-    pair = (pair << 8) | myget_unsigned_byte(file);
-    return pair;
-}
-
-@ @c
 static unsigned int read_exif_bytes(unsigned char **p, int n, int b)
 {
     unsigned int rval = 0;
@@ -144,8 +128,18 @@
     return rval;
 }
 
+@ The Exif block can contain the data on the resolution in two forms:
+XResolution, YResolution and ResolutionUnit (tag 282, 283 and 296)
+as well as PixelPerUnitX, PixelPerUnitY and PixelUnit (tag 0x5111,
+0x5112 and 0x5110). Tags 282, 293 and 296 have the priority,
+with ResolutionUnit set to inch by default, then 
+tag 0x5110, 0x5111 and 0x5112, where the only valid value for PixelUnit is 0.0254,
+and finally the given value xx and yy, 
+choosen if the Exif x and y resolution are not strictly positive.
+
+
 @ @c
-static void read_APP1_Exif (FILE *fp, unsigned short length, int *xx, int *yy)
+static void read_APP1_Exif (FILE *fp, unsigned short length, int *xx, int *yy, int *or)
 {
     /* this doesn't save the data, just reads the tags we need */
     /* based on info from http://www.exif.org/Exif2-2.PDF */
@@ -155,10 +149,24 @@
     char bigendian;
     int i;
     int num_fields, tag, type;
-    int value = 0, num = 0, den = 0; /* silence uninitialized warnings */
-    double xres = 72.0;
-    double yres = 72.0;
+    int value = 0;/* silence uninitialized warnings */
+    unsigned int num = 0;
+    unsigned int den = 0;
+    boolean found_x = false;
+    boolean found_y = false;
+    int tempx = 0;
+    int tempy = 0;
+    double xres = 0;
+    double yres = 0;
     double res_unit = 1.0;
+    unsigned int xres_ms = 0;
+    unsigned int yres_ms = 0;
+    double res_unit_ms = 0;
+    boolean found_x_ms = false;
+    boolean found_y_ms = false;
+    boolean found_res= false;
+
+    int orientation = 1;
     size_t ret_len;
     ret_len = fread(buffer, length, 1, fp);
     if (ret_len != 1)
@@ -189,12 +197,13 @@
                 value = *p++;
                 p += 3;
                 break;
-            case 3: /* short */
+            case 3: /* unsigned short */
+            case 8: /* signed short */
                 value = read_exif_bytes(&p, 2, bigendian);
                 p += 2;
                 break;
-            case 4: /* long */
-            case 9: /* slong */
+            case 4: /* unsigned long */
+            case 9: /* signed long */
                 value = read_exif_bytes(&p, 4, bigendian);
                 break;
             case 5: /* rational */
@@ -214,13 +223,20 @@
                 break;
         }
         switch (tag) {
+            case 274: /* orientation */
+                orientation = value;
+                break;
             case 282: /* x res */
-                if (den != 0)
+                if (den != 0) {
                     xres = num / den;
+                    found_x = true;
+		}
                 break;
             case 283: /* y res */
-                if (den != 0)
+                if (den != 0) {
                     yres = num / den;
+                    found_y = true ;
+		}
                 break;
             case 296: /* res unit */
                 switch (value) {
@@ -230,12 +246,56 @@
                     case 3:
                         res_unit = 2.54;
                         break;
+                    default:
+                        res_unit = 0;
+                        break;
                 }
-        }
+	   case 0x5110: /* PixelUnit */
+	        switch (value) {
+                    case 1:
+		        res_unit_ms = 0.0254; /* Unit is meter */
+			break;
+		    default:
+  		        res_unit_ms = 0; 
+		}
+	   case 0x5111: /* PixelPerUnitX */
+                found_x_ms = true ;
+	   	xres_ms = value;
+		break;
+	   case 0x5112: /* PixelPerUnitY */
+                found_y_ms = true ;
+		yres_ms = value ;
+		break;
+           }
+
+
+    }    
+    if (found_x && found_y && res_unit>0) {
+     found_res = true; 
+     tempx = (int)(xres * res_unit+0.5);
+     tempy = (int)(yres * res_unit+0.5);
+    } else if (found_x_ms && found_y_ms && res_unit_ms==0.0254) {
+     found_res = true; 
+     tempx = (int)(xres_ms * res_unit_ms+0.5);
+     tempy = (int)(yres_ms * res_unit_ms+0.5);
     }
+    if (found_res) {
+      if (tempx>0 && tempy>0) {
+       if (tempx!=(*xx) || tempy!=(*yy) && (*xx!=0 && (*yy!=0) )  ) {
+        formatted_warning("readjpg","Exif resolution  %ddpi x %ddpi differs from the input resolution %ddpi x %ddpi",tempx,tempy,*xx,*yy);
+       }
+       if (tempx==1 || tempy==1) {
+        formatted_warning("readjpg","Exif resolution %ddpi x %ddpi looks weird", tempx, tempy);
+       }
+       *xx = tempx;
+       *yy = tempy;
+     }else {
+       formatted_warning("readjpg","Bad Exif resolution  %ddpi x %ddpi (zero or negative value of a signed integer)",tempx,tempy);
+     }
+    }
 
-    *xx = (int)(xres * res_unit);
-    *yy = (int)(yres * res_unit);
+    *or = orientation;
+
 err:
     free(buffer);
     return;
@@ -268,97 +328,58 @@
     close_and_cleanup_jpg(idict);
 }
 
+@ The jpeg images are scanned for resolution, colorspace, depth, dimensions and
+orientation. We need to look at the exif blob for that. The original version did
+a quick test for jfif and exif but there can be more blobs later on. The current
+approach is to run over the linked list of blobs which is somewhat less efficient
+but not noticeable.
+
 @ @c
 void read_jpg_info(image_dict * idict)
 {
-    int i, units = 0;
-    unsigned short appmk, length;
-    unsigned char jpg_id[] = "JFIF";
+    int i, position, units = 0;
+    unsigned short length;
+    int okay = 0 ;
+    FILE *fp = img_file(idict);
     if (img_type(idict) != IMG_TYPE_JPG) {
         normal_error("readjpg","conflicting image dictionary");
     }
-    if (img_file(idict) != NULL) {
+    if (fp != NULL) {
         normal_error("readjpg","image data already read");
     }
+    fp = xfopen(img_filepath(idict), FOPEN_RBIN_MODE);
     img_totalpages(idict) = 1;
     img_pagenum(idict) = 1;
     img_xres(idict) = img_yres(idict) = 0;
-    img_file(idict) = xfopen(img_filepath(idict), FOPEN_RBIN_MODE);
-    if (img_file(idict) == NULL) {
+    img_file(idict) = fp;
+    if (fp == NULL) {
         normal_error("readjpg","unable to read image file");
     }
     img_jpg_ptr(idict) = xtalloc(1, jpg_img_struct);
-    xfseek(img_file(idict), 0, SEEK_END, img_filepath(idict));
-    img_jpg_ptr(idict)->length = xftell(img_file(idict), img_filepath(idict));
-    xfseek(img_file(idict), 0, SEEK_SET, img_filepath(idict));
-    if ((unsigned int) read2bytes(img_file(idict)) != 0xFFD8) {
+    xfseek(fp, 0, SEEK_END, img_filepath(idict));
+    img_jpg_ptr(idict)->length = xftell(fp, img_filepath(idict));
+    xfseek(fp, 0, SEEK_SET, img_filepath(idict));
+    if ((unsigned int) read2bytes(fp) != 0xFFD8) {
         normal_error("readjpg","no header found");
     }
-    /* currently JFIF and Exif files allow extracting |img_xres| and |img_yres| */
-    appmk = read2bytes(img_file(idict));
-    if (appmk == 0xFFE0) {
-        /* check for JFIF */
-        (void) read2bytes(img_file(idict));
-        for (i = 0; i < 5; i++) {
-            if (xgetc(img_file(idict)) != jpg_id[i])
-                break;
-        }
-        if (i == 5) {
-            /* it's JFIF */
-            (void) read2bytes(img_file(idict));
-            units = xgetc(img_file(idict));
-            img_xres(idict) = (int) read2bytes(img_file(idict));
-            img_yres(idict) = (int) read2bytes(img_file(idict));
-            switch (units) {
-            case 1:
-                /* pixels per inch */
-                if ((img_xres(idict) == 1) || (img_yres(idict) == 1)) {
-                    formatted_warning("readjpg","unusual resolution of %ddpi by %ddpi", img_xres(idict), img_yres(idict));
-                }
-                break;
-            case 2:
-                /* pixels per cm */
-                img_xres(idict) = (int) ((double) img_xres(idict) * 2.54);
-                img_yres(idict) = (int) ((double) img_yres(idict) * 2.54);
-                break;
-            default:
-                img_xres(idict) = img_yres(idict) = 0;
-                break;
+    xfseek(fp, 0, SEEK_SET, img_filepath(idict));
+    while (1) {
+        if (feof(fp)) {
+            if (okay) {
+                break ;
+            } else {
+                normal_error("readjpg","premature file end");
             }
-        }
-        /* if either xres or yres is 0 but the other isn't, set it to the value of the other */
-        if ((img_xres(idict) == 0) && (img_yres(idict) != 0)) {
-            img_xres(idict) = img_yres(idict);
-        }
-        if ((img_yres(idict) == 0) && (img_xres(idict) != 0)) {
-            img_yres(idict) = img_xres(idict);
-        }
-    } else if (appmk == 0xFFE1) {
-        /* check for Exif */
-        FILE *fp = img_file(idict);
-        int xxres = 0;
-        int yyres = 0;
-        char app_sig[32];
-        length = myget_unsigned_pair(fp) - 2;
-        if (length > 5) {
-            if (fread(app_sig, sizeof(char), 5, fp) != 5)
-                return;
-            length -= 5;
-            if (!memcmp(app_sig, "Exif\000", 5)) {
-                read_APP1_Exif(fp, length, &xxres, &yyres);
+        } else if (fgetc(fp) != 0xFF) {
+            if (okay) {
+                break ;
+            } else {
+                normal_error("readjpg","no marker found");
             }
         }
-        img_xres(idict) = xxres;
-        img_yres(idict) = yyres;
-    }
-    xfseek(img_file(idict), 0, SEEK_SET, img_filepath(idict));
-    while (1) {
-        if (feof(img_file(idict))) {
-            normal_error("readjpg","premature file end");
-        } else if (fgetc(img_file(idict)) != 0xFF) {
-            normal_error("readjpg","no marker found");
-        }
-        i = xgetc(img_file(idict));
+        i = xgetc(fp);
+        position = ftell(fp);
+        length = 0 ;
         switch (i) {
             case M_SOF3:  /* lossless */
             case M_SOF5:
@@ -378,12 +399,11 @@
                 }
             case M_SOF0:
             case M_SOF1:
-                (void) read2bytes(img_file(idict)); /* read segment length  */
-                img_colordepth(idict) = xgetc(img_file(idict));
-                img_ysize(idict) = (int) read2bytes(img_file(idict));
-                img_xsize(idict) = (int) read2bytes(img_file(idict));
-                img_jpg_color(idict) = xgetc(img_file(idict));
-                xfseek(img_file(idict), 0, SEEK_SET, img_filepath(idict));
+                length = (int) read2bytes(fp); /* read segment length  */
+                img_colordepth(idict) = xgetc(fp);
+                img_ysize(idict) = (int) read2bytes(fp);
+                img_xsize(idict) = (int) read2bytes(fp);
+                img_jpg_color(idict) = xgetc(fp);
                 switch (img_jpg_color(idict)) {
                     case JPG_GRAY:
                         img_procset(idict) |= PROCSET_IMAGE_B;
@@ -397,13 +417,60 @@
                     default:
                         formatted_error("readjpg","unsupported color space %i", (int) img_jpg_color(idict));
                 }
-                /*
-                    So we can optionally keep open a file in img.
-                */
-                if (! img_keepopen(idict)) {
-                    close_and_cleanup_jpg(idict);
+                okay = 1 ;
+                break ;
+            case M_APP0:
+                {
+                    char app_sig[32];
+                    length = (int) read2bytes(fp);
+                    if (length > 6) {
+                        if (fread(app_sig, sizeof(char), 5, fp) != 5)
+                            return;
+                        if (!memcmp(app_sig, "JFIF\000", 5)) {
+                            units = (int) read2bytes(fp);    /*skip two bytes, compiler is also happy*/
+                            units = xgetc(fp);
+                            img_xres(idict) = (int) read2bytes(fp);
+                            img_yres(idict) = (int) read2bytes(fp);
+                            switch (units) {
+                                case 1:
+                                    /* pixels per inch */
+                                    if ((img_xres(idict) == 1) || (img_yres(idict) == 1)) {
+                                        formatted_warning("readjpg","unusual resolution of %ddpi by %ddpi", img_xres(idict), img_yres(idict));
+                                    }
+                                    break;
+                                case 2:
+                                    /* pixels per cm */
+                                    img_xres(idict) = (int) ((double) img_xres(idict) * 2.54);
+                                    img_yres(idict) = (int) ((double) img_yres(idict) * 2.54);
+                                    break;
+                                default:
+                                    img_xres(idict) = img_yres(idict) = 0;
+                                    break;
+                                }
+                            }
+                        /* if either xres or yres is 0 but the other isn't, set it to the value of the other */
+                    }
                 }
-                return;
+                break;
+            case M_APP1:
+                {
+                    char app_sig[32];
+                    length = (int) read2bytes(fp);
+                    if (length > 7) {
+                        if (fread(app_sig, sizeof(char), 5, fp) != 5)
+                            return;
+                        if (!memcmp(app_sig, "Exif\000", 5)) {
+                            int xxres = img_xres(idict);
+                            int yyres = img_yres(idict);
+                            int orientation = img_orientation(idict);
+                            read_APP1_Exif(fp, length - 7, &xxres, &yyres, &orientation);
+                            img_xres(idict) = xxres;
+                            img_yres(idict) = yyres;
+                            img_orientation(idict) = orientation;
+                        }
+                    }
+                }
+                break;
             /* ignore markers without parameters */
             case M_SOI:
             case M_EOI:
@@ -419,11 +486,32 @@
                 break;
             default:
                 /* skip variable length markers */
-                xfseek(img_file(idict), (int) read2bytes(img_file(idict)) - 2, SEEK_CUR, img_filepath(idict));
+                length = (int) read2bytes(fp);
                 break;
         }
+        /*
+            printf("marker %X : %i %i\n",i,position,length);
+        */
+        if (length > 0) {
+            xfseek(fp, position + length, SEEK_SET, img_filepath(idict));
+        }
     }
-    normal_error("readjpg","unknown fatal error");
+    /* moved */
+    xfseek(fp, 0, SEEK_SET, img_filepath(idict));
+    if (! img_keepopen(idict)) {
+        close_and_cleanup_jpg(idict);
+    }
+    /* */
+    if (okay){
+        if ((img_xres(idict) == 0) && (img_yres(idict) != 0)) {
+            img_xres(idict) = img_yres(idict);
+        }
+        if ((img_yres(idict) == 0) && (img_xres(idict) != 0)) {
+            img_yres(idict) = img_xres(idict);
+        }
+    } else {
+        normal_error("readjpg","unknown fatal error");
+    }
 }
 
 @ @c

Modified: trunk/Build/source/texk/web2c/luatexdir/lua/lcallbacklib.c
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/lua/lcallbacklib.c	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/lua/lcallbacklib.c	2017-02-03 21:33:11 UTC (rev 43128)
@@ -73,6 +73,7 @@
     "insert_local_par",
     "contribute_filter",
     "call_edit",
+    "build_page_insert",
     NULL
 };
 

Modified: trunk/Build/source/texk/web2c/luatexdir/lua/limglib.c
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/lua/limglib.c	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/lua/limglib.c	2017-02-03 21:33:11 UTC (rev 43128)
@@ -394,6 +394,8 @@
         lua_pushinteger(L, img_yres(d));
     } else if (lua_key_eq(s,rotation)) {
         lua_pushinteger(L, img_rotation(d));
+    } else if (lua_key_eq(s,orientation)) {
+        lua_pushinteger(L, img_orientation(d));
     } else if (lua_key_eq(s,colorspace)) {
         if (img_colorspace(d) == 0) {
             lua_pushnil(L);

Modified: trunk/Build/source/texk/web2c/luatexdir/lua/lnodelib.c
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/lua/lnodelib.c	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/lua/lnodelib.c	2017-02-03 21:33:11 UTC (rev 43128)
@@ -618,7 +618,106 @@
     return 1;
 }
 
+/* getwhd: only core nodes */
 
+#define push_list_whd(n) \
+    lua_pushinteger(L, width(n));  \
+    lua_pushinteger(L, height(n)); \
+    lua_pushinteger(L, depth(n));  \
+
+#define push_char_whd(n) \
+    lua_pushinteger(L, char_width(font(n),character(n)));  \
+    lua_pushinteger(L, char_height(font(n),character(n))); \
+    lua_pushinteger(L, char_depth(font(n),character(n)));  \
+
+static int lua_nodelib_direct_getwhd(lua_State * L)
+{
+    halfword n = lua_tointeger(L, 1);
+    if (n != null) {
+        halfword t = type(n);
+        if ((t == hlist_node) || (t == vlist_node) || (t == rule_node) || (t == unset_node)) {
+            push_list_whd(n);
+            return 3;
+        } else if (t == glyph_node) {
+            push_char_whd(n);
+            return 3;
+        } else if (t == glue_node) {
+            halfword l = leader_ptr(n);
+            if (l != null) {
+                t = type(l) ;
+                if ((t == hlist_node) || (t == vlist_node) || (t == rule_node)) {
+                    push_list_whd(l);
+                    return 3;
+                }
+            }
+        }
+    }
+    return 0;
+}
+
+static int lua_nodelib_getwhd(lua_State * L)
+{
+    halfword *n = lua_touserdata(L, 1);
+    if (n != NULL) {
+        halfword t = type(*n);
+        if ((t == hlist_node) || (t == vlist_node) || (t == rule_node) || (t == unset_node)) {
+            push_list_whd(*n);
+            return 3;
+        } else if (t == glyph_node) {
+            push_char_whd(*n);
+            return 3;
+        } else if (t == glue_node) {
+            halfword l = leader_ptr(*n);
+            if (l != null) {
+                t = type(l) ;
+                if ((t == hlist_node) || (t == vlist_node) || (t == rule_node)) {
+                    push_list_whd(l);
+                    return 3;
+                }
+            }
+        }
+    }
+    return 0;
+}
+
+static int lua_nodelib_direct_setwhd(lua_State * L)
+{
+    halfword n = lua_tointeger(L, 1);
+    if (n != null) {
+        halfword t = type(n);
+        if (t == glue_node) {
+            n = leader_ptr(n);
+            if (n == null) {
+                return 0;
+            } else {
+                t = type(n);
+            }
+        }
+        if ((t == hlist_node) || (t == vlist_node) || (t == rule_node) || (t == unset_node)) {
+            int t = lua_gettop(L) ;
+            if (t > 1) {
+                width(n) = (halfword) lua_roundnumber(L, 2);
+                if (t > 2) {
+                    height(n) = (halfword) lua_roundnumber(L, 3);
+                    if (t > 3) {
+                        depth(n) = (halfword) lua_roundnumber(L, 4);
+                    } else {
+                        depth(n) = 0;
+                    }
+                } else {
+                    height(n) = 0;
+                    depth(n) = 0;
+                }
+            } else {
+                width(n) = 0;
+                height(n) = 0;
+                depth(n) = 0;
+            }
+        }
+    }
+    return 0;
+}
+
 /* node.getlist */
 
 static int lua_nodelib_getlist(lua_State * L)
@@ -1355,7 +1454,6 @@
     m = do_copy_node_list(n, s);
     lua_nodelib_push_fast(L,m);
     return 1;
-
 }
 
 /* node.direct.copy_list */
@@ -2268,7 +2366,7 @@
                             break;
                         } else {
                             lua_pushinteger(L,ret);
-                            lua_nodelib_push_fast(L, p);
+                            lua_nodelib_push_fast(L, c  );
                             return 2;
                         }
                     } else if (attribute_id(p) > i) {
@@ -2337,7 +2435,7 @@
                             break;
                         } else {
                             lua_pushinteger(L,ret);
-                            lua_pushinteger(L,p);
+                            lua_pushinteger(L,c);
                             return 2;
                         }
                     } else if (attribute_id(p) > i) {
@@ -2446,7 +2544,7 @@
 {
     halfword n = *check_isnode(L, 1);
     int top = lua_gettop(L) ;
-    if ((n != null) && (type(n) == glue_node || type(n) == glue_spec_node)) {
+    if ((n != null) && (type(n) == glue_node || type(n) == glue_spec_node || type(n) == math_node)) {
         width(n)         = ((top > 1 && lua_type(L, 2) == LUA_TNUMBER)) ? lua_roundnumber(L,2) : 0;
         stretch(n)       = ((top > 2 && lua_type(L, 3) == LUA_TNUMBER)) ? lua_roundnumber(L,3) : 0;
         shrink(n)        = ((top > 3 && lua_type(L, 4) == LUA_TNUMBER)) ? lua_roundnumber(L,4) : 0;
@@ -2462,7 +2560,7 @@
 {
     halfword n = lua_tointeger(L, 1);
     int top = lua_gettop(L) ;
-    if ((n != null) && (type(n) == glue_node || type(n) == glue_spec_node)) {
+    if ((n != null) && (type(n) == glue_node || type(n) == glue_spec_node || type(n) == math_node)) {
         width(n)         = ((top > 1 && lua_type(L, 2) == LUA_TNUMBER)) ? lua_roundnumber(L,2) : 0;
         stretch(n)       = ((top > 2 && lua_type(L, 3) == LUA_TNUMBER)) ? lua_roundnumber(L,3) : 0;
         shrink(n)        = ((top > 3 && lua_type(L, 4) == LUA_TNUMBER)) ? lua_roundnumber(L,4) : 0;
@@ -2477,8 +2575,14 @@
 static int lua_nodelib_get_glue(lua_State * L)
 {
     halfword n = *check_isnode(L, 1);
-    if ((n != null) && (type(n) == glue_node || type(n) == glue_spec_node)) {
+    if ((n != null) && (type(n) == glue_node || type(n) == glue_spec_node || type(n) == math_node)) {
+        int b = -1; /* false: only width, true or unset: 5 values */
+        if (lua_gettop(L) == 2) {
+            b = lua_toboolean(L, 2);
+        }
         lua_pushinteger(L,width(n));
+        if (b == 0)
+            return 1;
         lua_pushinteger(L,stretch(n));
         lua_pushinteger(L,shrink(n));
         lua_pushinteger(L,stretch_order(n));
@@ -2492,13 +2596,21 @@
 static int lua_nodelib_direct_get_glue(lua_State * L)
 {
     halfword n = lua_tointeger(L, 1);
-    if ((n != null) && (type(n) == glue_node || type(n) == glue_spec_node)) {
+    if ((n != null) && (type(n) == glue_node || type(n) == glue_spec_node || type(n) == math_node)) {
+        int b = -1;
+        if (lua_gettop(L) == 2) {
+            b = lua_toboolean(L, 2);
+        }
         lua_pushinteger(L,width(n));
-        lua_pushinteger(L,stretch(n));
-        lua_pushinteger(L,shrink(n));
-        lua_pushinteger(L,stretch_order(n));
-        lua_pushinteger(L,shrink_order(n));
-        return 5;
+        if (b == 0) {
+            return 1;
+        } else {
+            lua_pushinteger(L,stretch(n));
+            lua_pushinteger(L,shrink(n));
+            lua_pushinteger(L,stretch_order(n));
+            lua_pushinteger(L,shrink_order(n));
+            return 5;
+        }
     } else {
         return luaL_error(L, "glue (spec) expected");
     }
@@ -2507,7 +2619,7 @@
 static int lua_nodelib_is_zero_glue(lua_State * L)
 {
     halfword n = *check_isnode(L, 1);
-    if ((n != null) && (type(n) == glue_node || type(n) == glue_spec_node)) {
+    if ((n != null) && (type(n) == glue_node || type(n) == glue_spec_node || type(n) == math_node)) {
         lua_pushboolean(L,(width(n) == 0 && stretch(n) == 0 && shrink(n) == 0));
         return 1;
     } else {
@@ -2518,7 +2630,7 @@
 static int lua_nodelib_direct_is_zero_glue(lua_State * L)
 {
     halfword n = lua_tointeger(L, 1);
-    if ((n != null) && (type(n) == glue_node || type(n) == glue_spec_node)) {
+    if ((n != null) && (type(n) == glue_node || type(n) == glue_spec_node || type(n) == math_node)) {
         lua_pushboolean(L,(width(n) == 0 && stretch(n) == 0 && shrink(n) == 0));
         return 1;
     } else {
@@ -3953,7 +4065,8 @@
         if (! nodetype_has_attributes(t)) {
             lua_pushnil(L);
         } else {
-            nodelib_pushattr(L, node_attr(n));
+         /* nodelib_pushattr(L, node_attr(n)); */
+            lua_pushinteger(L, node_attr(n));
         }
     } else if (t == glyph_node) {
         if (lua_key_eq(s, font)) {
@@ -6109,7 +6222,6 @@
     return 0;
 }
 
-
 static int lua_nodelib_direct_setfield(lua_State * L)
 {
     const char *s;
@@ -6151,7 +6263,8 @@
         alink(n) = x;
     } else if (lua_key_eq(s, attr)) {
         if (nodetype_has_attributes(type(n))) {
-            nodelib_setattr(L, 3, n);
+         /* nodelib_setattr(L, 3, n); */
+            reassign_attribute(n,lua_tointeger(L, 3));
         }
     } else if (t == glyph_node) {
         if (lua_key_eq(s, subtype)) {
@@ -6701,7 +6814,6 @@
             luaL_error(L, "setbox: incompatible node type (%s)\n",get_node_name(type(j), subtype(j)));
             return 0;
         }
-
     }
     save_global_defs = global_defs_par;
     if (isglobal) {
@@ -7047,6 +7159,7 @@
     {"getbox", lua_nodelib_direct_getbox},
     {"getchar", lua_nodelib_direct_getcharacter},
     {"getdisc", lua_nodelib_direct_getdiscretionary},
+    {"getwhd", lua_nodelib_direct_getwhd},
     {"getfield", lua_nodelib_direct_getfield},
     {"getfont", lua_nodelib_direct_getfont},
     {"getid", lua_nodelib_direct_getid},
@@ -7085,6 +7198,7 @@
     {"setfield", lua_nodelib_direct_setfield},
     {"setchar", lua_nodelib_direct_setcharacter},
     {"setdisc", lua_nodelib_direct_setdiscretionary},
+    {"setwhd", lua_nodelib_direct_setwhd},
     {"setnext", lua_nodelib_direct_setnext},
     {"setprev", lua_nodelib_direct_setprev},
     {"setboth", lua_nodelib_direct_setboth},
@@ -7146,6 +7260,7 @@
     {"getprev", lua_nodelib_getprev},
     {"getboth", lua_nodelib_getboth},
     {"getdisc", lua_nodelib_getdiscretionary},
+    {"getwhd", lua_nodelib_getwhd},
     {"getlist", lua_nodelib_getlist},
     {"getleader", lua_nodelib_getleader},
     {"getid", lua_nodelib_getid},

Modified: trunk/Build/source/texk/web2c/luatexdir/lua/lpdflib.c
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/lua/lpdflib.c	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/lua/lpdflib.c	2017-02-03 21:33:11 UTC (rev 43128)
@@ -788,6 +788,36 @@
     return 0 ;
 }
 
+/* fonts */
+
+static int getpdfgentounicode(lua_State * L)
+{
+    lua_pushinteger(L, (pdf_gen_tounicode));
+    return 1 ;
+}
+
+static int getpdfomitcidset(lua_State * L)
+{
+    lua_pushinteger(L, (pdf_omit_cidset));
+    return 1 ;
+}
+
+static int setpdfgentounicode(lua_State * L)
+{
+    if (lua_type(L, 1) == LUA_TNUMBER) {
+        set_pdf_gen_tounicode(lua_tointeger(L, 1));
+    }
+    return 0 ;
+}
+
+static int setpdfomitcidset(lua_State * L)
+{
+    if (lua_type(L, 1) == LUA_TNUMBER) {
+        set_pdf_omit_cidset(lua_tointeger(L, 1));
+    }
+    return 0 ;
+}
+
 /* accuracy */
 
 static int l_get_decimal_digits(lua_State * L)
@@ -1186,8 +1216,12 @@
     { "getxformmargin", getpdfxformmargin },
     { "getinclusionerrorlevel", getpdfinclusionerrorlevel },
     { "getignoreunknownimages", getpdfignoreunknownimages },
+    { "getgentounicode", getpdfgentounicode },
+    { "getomitcidset", getpdfomitcidset },
     { "setinclusionerrorlevel", setpdfinclusionerrorlevel },
     { "setignoreunknownimages", setpdfignoreunknownimages },
+    { "setgentounicode", setpdfgentounicode },
+    { "setomitcidset", setpdfomitcidset },
     { "mapfile", l_mapfile },
     { "mapline", l_mapline },
     /* sentinel */

Modified: trunk/Build/source/texk/web2c/luatexdir/lua/ltexlib.c
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/lua/ltexlib.c	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/lua/ltexlib.c	2017-02-03 21:33:11 UTC (rev 43128)
@@ -866,7 +866,11 @@
     int top = lua_gettop(L);
     check_item_global(L,top,isglobal);
     value = check_isnode(L, top);
-    set_item_index_plus(L, top-1, skip_base, "skip", *value, isglobal, is_glue_assign, set_tex_skip_register, true);
+    if (type(*value) == glue_spec_node) {
+        set_item_index_plus(L, top-1, skip_base, "skip", *value, isglobal, is_glue_assign, set_tex_skip_register, true);
+    } else {
+        luaL_error(L, "glue_spec expected");
+    }
     return 0;
 }
 
@@ -916,18 +920,31 @@
 static int getglue(lua_State * L)
 {
     int value = 0;
-    get_item_index_plus(L, lua_gettop(L), skip_base, "skip", value, is_glue_assign, get_tex_skip_register, true);
+    int top = lua_gettop(L);
+    int b = -1; /* false: only width, true or unset: 5 values */
+    if (lua_type(L, top) == LUA_TBOOLEAN) {
+        b = lua_toboolean(L, top);
+        top -= 1 ;
+    }
+    get_item_index_plus(L, top, skip_base, "skip", value, is_glue_assign, get_tex_skip_register, true);
     if (value == null) {
-        lua_pushnil(L);
-        return 1;
+        lua_pushinteger(L,0);
+        if (b == 0)
+            return 1;
+        lua_pushinteger(L,0);
+        lua_pushinteger(L,0);
+        lua_pushinteger(L,0);
+        lua_pushinteger(L,0);
     } else {
         lua_pushinteger(L,width(value));
+        if (b == 0)
+            return 1;
         lua_pushinteger(L,stretch(value));
         lua_pushinteger(L,shrink(value));
         lua_pushinteger(L,stretch_order(value));
         lua_pushinteger(L,shrink_order(value));
-        return 5;
     }
+    return 5;
 }
 
 static int ismuskip(lua_State * L)
@@ -1234,18 +1251,20 @@
 
 static int vsetbox(lua_State * L, int is_global)
 {
-    int j, k, err;
-    int save_global_defs = global_defs_par;
-    if (is_global)
-        global_defs_par = 1;
+    int j, k, err, t;
+    int save_global_defs;
     k = get_box_id(L, -2, true);
     check_index_range(k, "setbox");
-    if (lua_isboolean(L, -1)) {
+    t = lua_type(L, -1);
+    if (t == LUA_TBOOLEAN) {
         j = lua_toboolean(L, -1);
-        if (j == 0)
+        if (j == 0) {
             j = null;
-        else
+        } else {
             return 0;
+        }
+    } else if (t == LUA_TNIL) {
+        j = null;
     } else {
         j = nodelist_from_lua(L);
         if (j != null && type(j) != hlist_node && type(j) != vlist_node) {
@@ -1252,8 +1271,11 @@
             luaL_error(L, "setbox: incompatible node type (%s)\n", get_node_name(type(j), subtype(j)));
             return 0;
         }
-
     }
+    save_global_defs = global_defs_par;
+    if (is_global) {
+        global_defs_par = 1;
+    }
     err = set_tex_box_register(k, j);
     global_defs_par = save_global_defs;
     if (err) {
@@ -1686,11 +1708,27 @@
                 }
                 assign_internal_value((isglobal ? 4 : 0), equiv(cur_cs1), j);
             } else if (is_glue_assign(cur_cmd1)) {
+                int a = isglobal;
+if (lua_type(L, i) == LUA_TNUMBER) {
+                halfword value = copy_node(zero_glue);
+                width(value) = lua_roundnumber(L,i);
+                if (i > 1) {
+                    stretch(value) = lua_roundnumber(L,i+1);
+                }
+                if (i > 3) {
+                    shrink(value) = lua_roundnumber(L,i+2);
+                }
+                if (i > 4) {
+                    stretch_order(value) = lua_tointeger(L,i+3);
+                }
+                if (i > 5) {
+                    shrink_order(value) = lua_tointeger(L,i+4);
+                }
+                define(equiv(cur_cs1), assign_glue_cmd, value);
+} else {
                 halfword *j1 = check_isnode(L, i);     /* the value */
-                {
-                    int a = isglobal;
-                    define(equiv(cur_cs1), assign_glue_cmd, *j1);
-                }
+                define(equiv(cur_cs1), assign_glue_cmd, *j1);
+}
             } else if (is_toks_assign(cur_cmd1)) {
                 if (lua_type(L,i) == LUA_TSTRING) {
                     j = tokenlist_from_lua(L);  /* uses stack -1 */
@@ -1771,7 +1809,7 @@
     return 1;
 }
 
-static int do_scan_internal(lua_State * L, int cur_cmd1, int cur_code)
+static int do_scan_internal(lua_State * L, int cur_cmd1, int cur_code, int values)
 {
     int texstr;
     char *str = NULL;
@@ -1787,7 +1825,18 @@
             break;
         case glue_val_level:
         case mu_val_level:
-            lua_nodelib_push_fast(L, copy_node(cur_val));
+            if (values == 0) {
+                lua_pushinteger(L,width(cur_val));
+            } else if (values == 1) {
+                lua_pushinteger(L,width(cur_val));
+                lua_pushinteger(L,stretch(cur_val));
+                lua_pushinteger(L,shrink(cur_val));
+                lua_pushinteger(L,stretch_order(cur_val));
+                lua_pushinteger(L,shrink_order(cur_val));
+                return 5;
+            } else {
+                lua_nodelib_push_fast(L, cur_val);
+            }
             break;
         default:
             texstr = the_scanned_result();
@@ -1864,7 +1913,7 @@
         case current_if_level_code:
         case current_if_type_code:
         case current_if_branch_code:
-            retval = do_scan_internal(L, last_item_cmd, cur_code);
+            retval = do_scan_internal(L, last_item_cmd, cur_code, -1);
             break;
         default:
             lua_pushnil(L);
@@ -1974,9 +2023,24 @@
 static int gettex(lua_State * L)
 {
     int cur_cs1 = -1;
-    int retval = 1;             /* default is to return nil  */
+    int retval = 1; /* default is to return nil  */
     int t = lua_gettop(L);
-    if (lua_type(L,t) == LUA_TSTRING) {   /* 1 == 'tex', 2 == 'boxmaxdepth', or 1 == 'boxmaxdepth' */
+    int b = -1 ;
+    if (t > 1 && lua_type(L,t) == LUA_TBOOLEAN) {
+        /*
+             0 == flush width only
+             1 == flush all glue parameters
+        */
+        b = lua_toboolean(L,t);
+        t = t - 1;
+    }
+    if (lua_type(L,t) == LUA_TSTRING) {
+        /*
+            1 == tex
+            2 == boxmaxdepth
+                or
+            1 == boxmaxdepth
+        */
         int texstr;
         size_t k;
         const char *st = lua_tolstring(L, t, &k);
@@ -2009,8 +2073,6 @@
             case assign_attr_cmd:
             case assign_dir_cmd:
             case assign_dimen_cmd:
-            case assign_glue_cmd:
-            case assign_mu_glue_cmd:
             case set_aux_cmd:
             case set_prev_graf_cmd:
             case set_page_int_cmd:
@@ -2017,8 +2079,12 @@
             case set_page_dimen_cmd:
             case char_given_cmd:
             case math_given_cmd:
-                retval = do_scan_internal(L, cur_cmd1, cur_code);
+                retval = do_scan_internal(L, cur_cmd1, cur_code, -1);
                 break;
+            case assign_glue_cmd:
+            case assign_mu_glue_cmd:
+                retval = do_scan_internal(L, cur_cmd1, cur_code, b);
+                break;
             case set_tex_shape_cmd:
                 retval = get_parshape(L);
                 break;
@@ -2026,7 +2092,7 @@
                 lua_pushnil(L);
                 break;
         }
-    } else if (t == 2) {
+    } else if ((t == 2) && (lua_type(L,2) == LUA_TSTRING)) {
 	    lua_rawget(L, 1);
     }
     return retval;
@@ -2368,6 +2434,7 @@
     return 0;
 }
 
+/*
 static int tex_hashpairs(lua_State * L)
 {
     int cmd, chr;
@@ -2384,8 +2451,8 @@
             chr = equiv(cs);
             make_token_table(L, cmd, chr, cs);
             lua_rawset(L, -3);
+            cs++;
         }
-        cs++;
     }
     return 1;
 }
@@ -2454,6 +2521,88 @@
     return 1;
 }
 
+*/
+
+static int tex_hashpairs(lua_State * L)
+{
+    str_number s = 0;
+    int cs = 1;
+    int nt = 0;
+    lua_newtable(L);
+    while (cs < hash_size) {
+        s = hash_text(cs);
+        if (s > 0) {
+            char *ss = makecstring(s);
+            lua_pushstring(L, ss);
+            free(ss);
+            lua_rawseti(L, -2, ++nt);
+        }
+        cs++;
+    }
+    return 1;
+}
+
+static int tex_primitives(lua_State * L)
+{
+    str_number s = 0;
+    int cs = 0;
+    int nt = 0;
+    lua_newtable(L);
+    while (cs < prim_size) {
+        s = get_prim_text(cs);
+        if (s > 0) {
+            char *ss = makecstring(s);
+            lua_pushstring(L, ss);
+            free(ss);
+            lua_rawseti(L, -2, ++nt);
+        }
+        cs++;
+    }
+    return 1;
+}
+
+static int tex_extraprimitives(lua_State * L)
+{
+    int n, i;
+    int mask = 0;
+    int cs = 0;
+    int nt = 0;
+    n = lua_gettop(L);
+    if (n == 0) {
+        mask = etex_command + luatex_command;
+    } else {
+        for (i = 1; i <= n; i++) {
+            if (lua_type(L,i) == LUA_TSTRING) {
+                const char *s = lua_tostring(L, i);
+                if (lua_key_eq(s,etex)) {
+                    mask |= etex_command;
+                } else if (lua_key_eq(s,tex)) {
+                    mask |= tex_command;
+                } else if (lua_key_eq(s,core)) {
+                    mask |= core_command;
+                } else if (lua_key_eq(s,luatex)) {
+                    mask |= luatex_command;
+                }
+            }
+        }
+    }
+    lua_newtable(L);
+    while (cs < prim_size) {
+        str_number s = 0;
+        s = get_prim_text(cs);
+        if (s > 0) {
+            if (get_prim_origin(cs) & mask) {
+                char *ss = makecstring(s);
+                lua_pushstring(L, ss);
+                free(ss);
+                lua_rawseti(L, -2, ++nt);
+            }
+        }
+        cs++;
+    }
+    return 1;
+}
+
 static int tex_enableprimitives(lua_State * L)
 {
     int n = lua_gettop(L);
@@ -2805,6 +2954,12 @@
         }
         zwclose(fmt_file);
     }
+    pdf_init_map_file("pdftex.map");
+    /* */
+    if (end_line_char_inactive)
+        decr(ilimit);
+    else
+        buffer[ilimit] = (packed_ASCII_code) end_line_char_par;
     fix_date_and_time();
     random_seed = (microseconds * 1000) + (epochseconds % 1000000);
     init_randoms(random_seed);

Modified: trunk/Build/source/texk/web2c/luatexdir/lua/luatex-api.h
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/lua/luatex-api.h	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/lua/luatex-api.h	2017-02-03 21:33:11 UTC (rev 43128)
@@ -607,6 +607,7 @@
 make_lua_key(hsize);\
 make_lua_key(hyphenchar);\
 make_lua_key(id);\
+make_lua_key(identity);\
 make_lua_key(image);\
 make_lua_key(imagetype);\
 make_lua_key(immediate);\
@@ -684,6 +685,7 @@
 make_lua_key(oldmath);\
 make_lua_key(ordering);\
 make_lua_key(options);\
+make_lua_key(orientation);\
 make_lua_key(origin);\
 make_lua_key(output);\
 make_lua_key(overlay_accent);\
@@ -829,6 +831,7 @@
 make_lua_key(yoffset); \
 make_lua_key(yres); \
 make_lua_key(ysize); \
+make_lua_key(writingmode); \
 make_lua_key(__index)
 
 #define set_init_keys \
@@ -974,6 +977,7 @@
 init_lua_key(hsize);\
 init_lua_key(hyphenchar);\
 init_lua_key(id);\
+init_lua_key(identity);\
 init_lua_key(image);\
 init_lua_key(imagetype);\
 init_lua_key(immediate);\
@@ -1046,6 +1050,7 @@
 init_lua_key(objnum);\
 init_lua_key(oldmath);\
 init_lua_key(options);\
+init_lua_key(orientation);\
 init_lua_key(origin);\
 init_lua_key(ordering);\
 init_lua_key(output);\
@@ -1186,6 +1191,7 @@
 init_lua_key(yoffset);\
 init_lua_key(yres);\
 init_lua_key(ysize);\
+init_lua_key(writingmode);\
 init_lua_key(__index);\
 init_lua_key_alias(empty_string,"");\
 init_lua_key_alias(lua_bytecodes_indirect,"lua.bytecodes.indirect");\
@@ -1390,6 +1396,7 @@
 use_lua_key(hsize);
 use_lua_key(hyphenchar);
 use_lua_key(id);
+use_lua_key(identity);
 use_lua_key(image);
 use_lua_key(imagetype);
 use_lua_key(immediate);
@@ -1466,6 +1473,7 @@
 use_lua_key(objnum);
 use_lua_key(oldmath);
 use_lua_key(options);
+use_lua_key(orientation);
 use_lua_key(origin);
 use_lua_key(ordering);
 use_lua_key(output);
@@ -1612,4 +1620,5 @@
 use_lua_key(yoffset);
 use_lua_key(yres);
 use_lua_key(ysize);
+use_lua_key(writingmode);
 use_lua_key(__index);

Modified: trunk/Build/source/texk/web2c/luatexdir/luatex.c
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/luatex.c	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/luatex.c	2017-02-03 21:33:11 UTC (rev 43128)
@@ -29,9 +29,9 @@
 #define TeX
 
 int luatex_version = 100;        /* \.{\\luatexversion}  */
-int luatex_revision = '0';      /* \.{\\luatexrevision}  */
-int luatex_date_info = 2016092700;     /* the compile date is now hardwired */
-const char *luatex_version_string = "1.0.0";
+int luatex_revision = '3';      /* \.{\\luatexrevision}  */
+int luatex_date_info = 2017011800;     /* the compile date is now hardwired :YEAR MONTH DAY HOUR*/
+const char *luatex_version_string = "1.0.3";
 const char *engine_name = my_name;     /* the name of this engine */
 
 #include <kpathsea/c-ctype.h>

Modified: trunk/Build/source/texk/web2c/luatexdir/luatexcallbackids.h
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/luatexcallbackids.h	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/luatexcallbackids.h	2017-02-03 21:33:11 UTC (rev 43128)
@@ -67,6 +67,7 @@
     insert_local_par_callback,
     contribute_filter_callback,
     call_edit_callback,
+    build_page_insert_callback,
     total_callbacks
 } callback_callback_types;
 

Modified: trunk/Build/source/texk/web2c/luatexdir/pdf/pdfgen.w
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/pdf/pdfgen.w	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/pdf/pdfgen.w	2017-02-03 21:33:11 UTC (rev 43128)
@@ -2269,6 +2269,7 @@
                 }
             }
             pdf->gen_tounicode = pdf_gen_tounicode;
+            pdf->omit_cidset = pdf_omit_cidset;
             k = pdf->head_tab[obj_type_font];
             while (k != 0) {
                 int f = obj_info(pdf, k);

Modified: trunk/Build/source/texk/web2c/luatexdir/pdf/pdfglyph.w
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/pdf/pdfglyph.w	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/pdf/pdfglyph.w	2017-02-03 21:33:11 UTC (rev 43128)
@@ -199,6 +199,17 @@
     scaledpos pos = pdf->posstruct->pos;
     if (!char_exists(f, c))
         return;
+    if (font_writingmode(f) == vertical_writingmode) {
+        if (p->wmode != WMODE_V) {
+            p->wmode = WMODE_V;
+            p->need_tm = true;
+        }
+    } else {
+        if (p->wmode != WMODE_H) {
+            p->wmode = WMODE_H;
+            p->need_tm = true;
+        }
+    }
     if (p->need_tf || f != pdf->f_cur || p->f_pdf != p->f_pdf_cur || p->fs.m != p->fs_cur.m || is_pagemode(p)) {
          pdf_goto_textmode(pdf);
          setup_fontparameters(pdf, f, ex);
@@ -210,7 +221,8 @@
     /* all movements */
     move = calc_pdfpos(p, pos); /* within text or chararray or char mode */
     if (move || p->need_tm) {
-        if (p->need_tm || (p->wmode == WMODE_H && (p->pdf_bt_pos.v.m + p->tm[5].m) != p->pdf.v.m)
+        if (p->need_tm
+        || (p->wmode == WMODE_H && (p->pdf_bt_pos.v.m + p->tm[5].m) != p->pdf.v.m)
         || (p->wmode == WMODE_V && (p->pdf_bt_pos.h.m + p->tm[4].m) != p->pdf.h.m)
         || abs(p->tj_delta.m) >= 1000000) {
             pdf_goto_textmode(pdf);

Modified: trunk/Build/source/texk/web2c/luatexdir/pdf/pdflistout.w
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/pdf/pdflistout.w	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/pdf/pdflistout.w	2017-02-03 21:33:11 UTC (rev 43128)
@@ -437,6 +437,18 @@
                         }
                     }
                     break;
+                case math_node:
+                    if (synctex) {
+                        synctexmath(p, this_box);
+                    }
+                    /* begin mathskip code */
+                    if (glue_is_zero(p)) {
+                        cur.h += surround(p);
+                        break;
+                    } else {
+                        /* fall through: mathskip */
+                    }
+                    /* end mathskip code */
                 case glue_node:
                     {
                         /* move right or output leaders, we use real multiplication */
@@ -646,18 +658,6 @@
                             out_what(pdf, p);
                     }
                     break;
-                case math_node:
-                    if (synctex) {
-                        synctexmath(p, this_box);
-                    }
-                    /* begin mathskip code */
-                    if (glue_is_zero(p)) {
-                        cur.h += surround(p);
-                        break;
-                    } else {
-                        /* fall through: mathskip */
-                    }
-                    /* end mathskip code */
                 case margin_kern_node:
                     cur.h += width(p);
                     break;

Modified: trunk/Build/source/texk/web2c/luatexdir/pdf/pdftables.h
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/pdf/pdftables.h	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/pdf/pdftables.h	2017-02-03 21:33:11 UTC (rev 43128)
@@ -137,6 +137,7 @@
     c_pdf_gen_tounicode,
     c_pdf_pk_fixed_dpi,
     c_pdf_suppress_optional_info,
+    c_pdf_omit_cidset,
 } pdf_backend_counters ;
 
 typedef enum {
@@ -182,6 +183,7 @@
 #  define pdf_gen_tounicode             get_tex_extension_count_register(c_pdf_gen_tounicode)
 #  define pdf_pk_fixed_dpi              get_tex_extension_count_register(c_pdf_pk_fixed_dpi)
 #  define pdf_suppress_optional_info    get_tex_extension_count_register(c_pdf_suppress_optional_info)
+#  define pdf_omit_cidset               get_tex_extension_count_register(c_pdf_omit_cidset)
 
 #  define pdf_h_origin                  get_tex_extension_dimen_register(d_pdf_h_origin)
 #  define pdf_v_origin                  get_tex_extension_dimen_register(d_pdf_v_origin)
@@ -201,6 +203,8 @@
 #  define set_pdf_minor_version(i)      set_tex_extension_count_register(c_pdf_minor_version,i)
 #  define set_pdf_compress_level(i)     set_tex_extension_count_register(c_pdf_compress_level,i)
 #  define set_pdf_obj_compress_level(i) set_tex_extension_count_register(c_pdf_obj_compress_level,i)
+#  define set_pdf_omit_cidset(i)        set_tex_extension_count_register(c_pdf_omit_cidset,i)
+#  define set_pdf_gen_tounicode(i)      set_tex_extension_count_register(c_pdf_gen_tounicode,i)
 
 #  define set_pdf_decimal_digits(i)     set_tex_extension_count_register(c_pdf_decimal_digits,i)
 #  define set_pdf_pk_resolution(i)      set_tex_extension_count_register(c_pdf_pk_resolution,i)

Modified: trunk/Build/source/texk/web2c/luatexdir/pdf/pdftypes.h
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/pdf/pdftypes.h	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/pdf/pdftypes.h	2017-02-03 21:33:11 UTC (rev 43128)
@@ -291,6 +291,7 @@
     int pk_fixed_dpi;
     int decimal_digits;
     int gen_tounicode;
+    int omit_cidset;
     int inclusion_copy_font;
     int minor_version;          /* fixed minor part of the PDF version */
     int compress_level;         /* level for zlib object stream compression */

Modified: trunk/Build/source/texk/web2c/luatexdir/tex/buildpage.w
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/tex/buildpage.w	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/tex/buildpage.w	2017-02-03 21:33:11 UTC (rev 43128)
@@ -289,6 +289,7 @@
     int pi = 0;                 /* penalty to be added to the badness */
     int n;                      /* insertion box number */
     scaled delta, h, w;         /* sizes used for insertion calculations */
+    int id, sk, i;
     if ((vlink(contrib_head) == null) || output_active)
         return;
     do {
@@ -406,8 +407,11 @@
                 freeze_page_specs(inserts_only);
             n = subtype(p);
             r = page_ins_head;
-            while (n >= subtype(vlink(r)))
+            i = 1 ;
+            while (n >= subtype(vlink(r))) {
                 r = vlink(r);
+                i = i + 1 ;
+            }
             if (subtype(r) != n) {
                 /* Create a page insertion node with |subtype(r)=qi(n)|, and
                    include the glue correction for box |n| in the
@@ -417,7 +421,12 @@
                    encountered for a new page. A user who changes the contents of \.{\\box}~|n|
                    after that first \.{\\insert}~|n| had better be either extremely careful
                    or extremely lucky, or both. */
-
+id = callback_defined(build_page_insert_callback);
+if (id != 0) {
+    run_callback(id, "dd->d",n,i,&sk);
+} else {
+    sk = n;
+}
                 q = new_node(inserting_node, n);
                 try_couple_nodes(q, vlink(r));
                 couple_nodes(r, q);
@@ -428,7 +437,8 @@
                 else
                     height(r) = height(box(n)) + depth(box(n));
                 best_ins_ptr(r) = null;
-                q = skip(n);
+            /*  q = skip(n); */
+q = skip(sk);
                 if (count(n) == 1000)
                     h = height(r);
                 else
@@ -435,11 +445,9 @@
                     h = x_over_n(height(r), 1000) * count(n);
                 page_goal = page_goal - h - width(q);
                 if (stretch_order(q) > 1)
-                    page_so_far[1 + stretch_order(q)] =
-                        page_so_far[1 + stretch_order(q)] + stretch(q);
+                    page_so_far[1 + stretch_order(q)] = page_so_far[1 + stretch_order(q)] + stretch(q);
                 else
-                    page_so_far[2 + stretch_order(q)] =
-                        page_so_far[2 + stretch_order(q)] + stretch(q);
+                    page_so_far[2 + stretch_order(q)] = page_so_far[2 + stretch_order(q)] + stretch(q);
                 page_shrink = page_shrink + shrink(q);
                 if ((shrink_order(q) != normal) && (shrink(q) != 0)) {
                     print_err("Infinite glue shrinkage inserted from \\skip");

Modified: trunk/Build/source/texk/web2c/luatexdir/tex/commands.w
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/tex/commands.w	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/tex/commands.w	2017-02-03 21:33:11 UTC (rev 43128)
@@ -51,6 +51,7 @@
     primitive_tex("medmuskip", assign_mu_glue_cmd, glue_base + med_mu_skip_code, glue_base + thin_mu_skip_code);
     primitive_tex("thickmuskip", assign_mu_glue_cmd, glue_base + thick_mu_skip_code, glue_base + thin_mu_skip_code);
     primitive_luatex("mathsurroundskip", assign_glue_cmd, glue_base + math_skip_code, glue_base);
+    primitive_luatex("mathsurroundmode", assign_int_cmd, int_base + math_skip_mode_code, int_base);
     primitive_tex("output", assign_toks_cmd, output_routine_loc, local_base);
     primitive_tex("everypar", assign_toks_cmd, every_par_loc, local_base);
     primitive_tex("everymath", assign_toks_cmd, every_math_loc, local_base);

Modified: trunk/Build/source/texk/web2c/luatexdir/tex/dumpdata.w
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/tex/dumpdata.w	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/tex/dumpdata.w	2017-02-03 21:33:11 UTC (rev 43128)
@@ -23,7 +23,7 @@
 
 /* we start with 907: the sum of the values of the bytes of "don knuth" */
 
-#define FORMAT_ID (907+20)
+#define FORMAT_ID (907+24)
 #if ((FORMAT_ID>=0) && (FORMAT_ID<=256))
 #error Wrong value for FORMAT_ID.
 #endif

Modified: trunk/Build/source/texk/web2c/luatexdir/tex/equivalents.h
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/tex/equivalents.h	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/tex/equivalents.h	2017-02-03 21:33:11 UTC (rev 43128)
@@ -285,17 +285,24 @@
 #  define shape_mode_code 94
 #  define first_valid_language_code 95
 #  define hyphenation_bounds_code 96
+#  define math_skip_mode_code 97
 
-#  define math_option_code 97
+#  define math_option_code (math_skip_mode_code+1)
 
-#  define mathoption_int_base (int_base+98)                             /* one reserve */
-#  define mathoption_int_last (int_base+106)
+#  define mathoption_int_base_code (math_option_code+1)                 /* one reserve */
+#  define mathoption_int_last_code (mathoption_int_base_code+8)
 
-#  define backend_int_base (int_base+107)
-#  define backend_int_last (int_base+131)
+#  define backend_int_base_code (mathoption_int_last_code+1)
+#  define backend_int_last_code (backend_int_base_code+32)              /* we need some 25 but take some slack */
 
-#  define tex_int_pars (132)                                            /* total number of integer parameters */
+#  define tex_int_pars (backend_int_last_code+1)                        /* total number of integer parameters */
 
+#  define mathoption_int_base (int_base+mathoption_int_base_code)
+#  define mathoption_int_last (int_base+mathoption_int_last_code)
+
+#  define backend_int_base (int_base+backend_int_base_code)
+#  define backend_int_last (int_base+backend_int_last_code)
+
 #  define page_direction_code (tex_int_pars)
 #  define body_direction_code (tex_int_pars+1)
 #  define par_direction_code  (tex_int_pars+2)
@@ -552,6 +559,7 @@
 #define space_skip_par                     glue_par(space_skip_code)
 #define xspace_skip_par                    glue_par(xspace_skip_code)
 #define math_skip_par                      glue_par(math_skip_code)
+#define math_skip_mode                     int_par(math_skip_mode_code)
 
 #define pre_display_size_par               dimen_par(pre_display_size_code)
 #define display_width_par                  dimen_par(display_width_code)
@@ -786,4 +794,9 @@
 #define end_template_token  (cs_token_flag+frozen_end_template)
 #define end_write_token     (cs_token_flag+end_write)
 
+/* for now here */
+
+#define xspace_skip_subtype (xspace_skip_code + 1)
+#define space_skip_subtype  (space_skip_code + 1)
+
 #endif

Modified: trunk/Build/source/texk/web2c/luatexdir/tex/linebreak.h
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/tex/linebreak.h	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/tex/linebreak.h	2017-02-03 21:33:11 UTC (rev 43128)
@@ -87,7 +87,7 @@
  || ((type((a)) == disc_node) && empty_disc(a)) \
  || ((type((a)) == kern_node) && ((width((a)) == 0) || (subtype((a)) == normal))) \
  || ((type((a)) == rule_node) && zero_dimensions(a)) \
- || ((type((a)) == math_node) && (surround((a)) == 0)) \
+ || ((type((a)) == math_node) && (surround((a)) == 0 || (glue_is_zero((a))))) \
  ||  (type((a)) == dir_node) \
  || ((type((a)) == hlist_node) && (list_ptr((a)) == null) && zero_dimensions(a)) \
  ||  (type((a)) == local_par_node) \

Modified: trunk/Build/source/texk/web2c/luatexdir/tex/linebreak.w
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/tex/linebreak.w	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/tex/linebreak.w	2017-02-03 21:33:11 UTC (rev 43128)
@@ -348,11 +348,11 @@
                     l = pop_node(); /* don't visit this node again */
                     run = false;
                 }
-if ((vlink(l) != null) && (type(l) == boundary_node) && (subtype(l) == protrusion_boundary) &&
-        ((boundary_value(l) == 1) || (boundary_value(l) == 3))) {
-    /* skip next node */
-    l = vlink(l);
-}
+                if ((vlink(l) != null) && (type(l) == boundary_node) && (subtype(l) == protrusion_boundary) &&
+                        ((boundary_value(l) == 1) || (boundary_value(l) == 3))) {
+                    /* skip next node */
+                    l = vlink(l);
+                }
                 if (vlink(l) != null) {
                     l = vlink(l);
                 } else if (hlist_stack_level == 0) {
@@ -393,11 +393,11 @@
                 l = pop_node();
             }
             if ((r != l) && (r != null)) {
-if ((alink(r) != null) && (type(r) == boundary_node) && (subtype(r) == protrusion_boundary) &&
-        ((boundary_value(r) == 2) || (boundary_value(r) == 3))) {
-    /* skip next node */
-    r = alink(r);
-}
+                if ((alink(r) != null) && (type(r) == boundary_node) && (subtype(r) == protrusion_boundary) &&
+                        ((boundary_value(r) == 2) || (boundary_value(r) == 3))) {
+                    /* skip next node */
+                    r = alink(r);
+                }
                 if (alink(r) != null) {
                     r = alink(r);
                 } else {        /* this is the input: \.{\\leavevmode\\penalty-10000\\penalty-10000} (bug \#268) */
@@ -898,7 +898,7 @@
         switch (type(s)) {
             case math_node:
                 /* begin mathskip code */
-                if (glue_is_zero(math_skip_par)) {
+                if (glue_is_zero(s)) {
                     break_width[1] -= surround(s);
                     break;
                 } else {
@@ -1840,7 +1840,7 @@
                 case math_node:
                     auto_breaking = (subtype(cur_p) == after);
                     /* begin mathskip code */
-                    if (glue_is_zero(math_skip_par)) {
+                    if (glue_is_zero(cur_p) || ignore_math_skip(cur_p)) {
                         kern_break();
                         break;
                     } else {

Modified: trunk/Build/source/texk/web2c/luatexdir/tex/mlist.w
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/tex/mlist.w	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/tex/mlist.w	2017-02-03 21:33:11 UTC (rev 43128)
@@ -66,13 +66,12 @@
 @ @c
 #define nDEBUG
 
-#define reset_attributes(p,newatt) do {                \
+#define reset_attributes(p,newatt) do { \
     delete_attribute_ref(node_attr(p)); \
-    node_attr(p) = newatt;                             \
-    if (newatt!=null) {                                \
-      assert(type(newatt)==attribute_list_node);       \
-      add_node_attr_ref(node_attr(p));                 \
-    }                                                  \
+    node_attr(p) = newatt;              \
+    if (newatt!=null) {                 \
+      add_node_attr_ref(node_attr(p));  \
+    }                                   \
   } while (0)
 
 #define DEFINE_MATH_PARAMETERS(A,B,C,D) do {                 \
@@ -88,11 +87,11 @@
     }                                                        \
   } while (0)
 
-#define DEFINE_DMATH_PARAMETERS(A,B,C,D) do {                \
-    if (B==text_size) {                                      \
-      def_math_param(A, display_style,(C),D);                \
-      def_math_param(A, cramped_display_style,(C),D);        \
-    }                                                        \
+#define DEFINE_DMATH_PARAMETERS(A,B,C,D) do {         \
+    if (B==text_size) {                               \
+      def_math_param(A, display_style,(C),D);         \
+      def_math_param(A, cramped_display_style,(C),D); \
+    }                                                 \
   } while (0)
 
 #define font_MATH_par(a,b) \
@@ -2662,7 +2661,6 @@
                     math_character(nucleus(q)) = c;
                 }
                 delta = char_italic(cur_f, cur_c);
-printf("delta %i\n",delta);
                 x = clean_box(nucleus(q), cur_style, cur_style);
                 if (delta != 0) {
                     if (do_new_math(cur_f)) {
@@ -3784,16 +3782,13 @@
         confusion("mathspacing");
     }
     if (x != 0) {
-        pointer y;
         if (x <= thick_mu_skip_code) {
             /* trap thin/med/thick settings cf. old TeX */
-            y = math_glue(glue_par(x), mmu);
-            z = new_glue(y);
+            z = math_glue(glue_par(x), mmu); /* allocates a glue */
             /* store a symbolic subtype */
             subtype(z) = (quarterword) (x + 1);
         } else {
-            y = math_glue(x, mmu);
-            z = new_glue(y);
+            z = math_glue(x, mmu); /* allocates a glue */
         }
     }
     return z;
@@ -4046,14 +4041,18 @@
                 math_glue_to_glue(q, cur_mu);
             } else if ((cur_size != text_size) && (subtype(q) == cond_math_glue)) {
                 p = vlink(q);
-                if (p != null)
-                    if ((type(p) == glue_node) || (type(p) == kern_node)) {
-                        couple_nodes(q,vlink(p));
-                        vlink(p) = null;
+         	if (p != null)
+                     if ((type(p) == glue_node) || (type(p) == kern_node)) {
+                       if (vlink(p) != null) {
+                            couple_nodes(q,vlink(p));
+                            vlink(p) = null;
+                        } else {
+                            vlink(q) = null;
+                        }
                         flush_node_list(p);
-                    }
+                     }
             }
-            goto DONE_WITH_NODE;
+	    goto DONE_WITH_NODE;
             break;
         case kern_node:
             math_kern(q, cur_mu);
@@ -4242,8 +4241,9 @@
             A low-level |free_node| is easier than attempting to nullify such dependant
             fields for all possible node and noad types.
         */
-        if (nodetype_has_attributes(type(r)))
+        if (nodetype_has_attributes(type(r))) {
             delete_attribute_ref(node_attr(r));
+        }
         reset_node_properties(r);
         free_node(r, get_node_size(type(r), subtype(r)));
     }

Modified: trunk/Build/source/texk/web2c/luatexdir/tex/packaging.h
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/tex/packaging.h	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/tex/packaging.h	2017-02-03 21:33:11 UTC (rev 43128)
@@ -147,4 +147,9 @@
 
 extern void begin_box(int box_context);
 
+#define math_skip_boundary(n) \
+(n && type(n) == glue_node && (subtype(n) == space_skip_subtype || subtype(n) == xspace_skip_subtype))
+
+extern int ignore_math_skip(halfword p) ;
+
 #endif

Modified: trunk/Build/source/texk/web2c/luatexdir/tex/packaging.w
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/tex/packaging.w	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/tex/packaging.w	2017-02-03 21:33:11 UTC (rev 43128)
@@ -191,12 +191,10 @@
 
 void scan_full_spec(group_code c, int spec_direction, int just_pack)
 {
-    int s;
-    int i;
-    int v;
-    int spec_code;
+    int s, i, v, spec_code;
     boolean done = false ;
     halfword attr_list;
+    boolean attr_done = false ;
     if (attr_list_cache == cache_disabled)
         update_attribute_cache();
     attr_list = attr_list_cache;
@@ -227,9 +225,9 @@
         scan_optional_equals();
         scan_int();
         v = cur_val;
-        if ((attr_list != null) && (attr_list == attr_list_cache)) {
+        if (! attr_done) {
             attr_list = copy_attribute_list(attr_list_cache);
-            add_node_attr_ref(attr_list); /* will be used once */
+            attr_done = true;
         }
         attr_list = do_set_attribute(attr_list, i, v);
         goto CONTINUE;
@@ -239,9 +237,6 @@
         spec_direction = cur_val;
         goto CONTINUE;
     }
-    if (attr_list == attr_list_cache) {
-        add_node_attr_ref(attr_list);
-    }
     if (scan_keyword("to")) {
         spec_code = exactly;
     } else if (scan_keyword("spread")) {
@@ -256,9 +251,9 @@
   QUICK:
     spec_code = additional;
     cur_val = 0;
-    add_node_attr_ref(attr_list);
     done = true;
   FOUND:
+    add_node_attr_ref(attr_list);
     set_saved_record(0, saved_boxcontext, 0, s);
     set_saved_record(1, saved_boxspec, spec_code, cur_val);
     /* DIR: Adjust |text_dir_ptr| for |scan_spec| */
@@ -281,6 +276,7 @@
     eq_word_define(int_base + text_direction_code, spec_direction);
 }
 
+
 @ To figure out the glue setting, |hpack| and |vpack| determine how much
 stretchability and shrinkability are present, considering all four orders of
 infinity. The highest order of infinity that has a nonzero coefficient is then
@@ -605,6 +601,35 @@
 @c
 int font_expand_ratio = 0;  /* current expansion ratio, needed for recursive call */
 
+int ignore_math_skip(halfword p)
+{
+    if (math_skip_mode == 6) {
+        if (subtype(p) == after) {
+            if (math_skip_boundary(vlink(p))) {
+                return 0;
+            }
+        } else {
+            if (math_skip_boundary(alink(p))) {
+                return 0;
+            }
+        }
+    } else if (math_skip_mode == 7) {
+        if (subtype(p) == after) {
+            if (! math_skip_boundary(vlink(p))) {
+                return 0;
+            }
+        } else {
+            if (! math_skip_boundary(alink(p))) {
+                return 0;
+            }
+        }
+    } else {
+        return 0;
+    }
+    reset_glue_to_zero(p);
+    return 1;
+}
+
 halfword hpack(halfword p, scaled w, int m, int pack_direction)
 {
     halfword r;                 /* the box node that will be returned */
@@ -744,6 +769,15 @@
                         d = depth(p);
                     break;
                 /* */
+                case math_node:
+                    /* begin mathskip code */
+                    if (glue_is_zero(p) || ignore_math_skip(p)) {
+                        x += surround(p);
+                        break;
+                    } else {
+                        /* fall through */
+                    }
+                    /* end mathskip code */
                 case glue_node:
                     /* Incorporate glue into the horizontal totals */
                     x += width(p);
@@ -802,15 +836,6 @@
                             hpack_dir = dir_dir(dir_ptr1);
                     }
                     break;
-                case math_node:
-                    /* begin mathskip code */
-                    if (glue_is_zero(p)) {
-                        x += surround(p);
-                        break;
-                    } else {
-                        /* fall through: mathskip */
-                    }
-                    /* end mathskip code */
                 case margin_kern_node:
                     if (m == cal_expand_ratio) {
                         int f = font(margin_char(p));
@@ -1187,11 +1212,11 @@
                 /* */
                 case math_node:
                     /* begin mathskip code */
-                    if (glue_is_zero(p)) {
+                    if (glue_is_zero(p) || ignore_math_skip(p)) {
                         siz.wd += surround(p);
                         break;
                     } else {
-                        /* fall through: mathskip */
+                        /* fall through */
                     }
                     /* end mathskip code */
                 case glue_node:

Modified: trunk/Build/source/texk/web2c/luatexdir/tex/scanning.w
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/tex/scanning.w	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/tex/scanning.w	2017-02-03 21:33:11 UTC (rev 43128)
@@ -140,9 +140,8 @@
 @c
 static void downgrade_cur_val(boolean delete_glue)
 {
-    halfword m;
     if (cur_val_level == glue_val_level) {
-        m = cur_val;
+        halfword m = cur_val;
         cur_val = width(m);
         if (delete_glue)
             flush_node(m);
@@ -152,19 +151,34 @@
     decr(cur_val_level);
 }
 
+/*
 void negate_cur_val(boolean delete_glue)
 {
-    halfword m;
     if (cur_val_level >= glue_val_level) {
-        m = cur_val;
+        halfword m = cur_val;
         cur_val = new_spec(m);
         if (delete_glue)
             flush_node(m);
-        /* Negate all three glue components of |cur_val| */
         negate(width(cur_val));
         negate(stretch(cur_val));
         negate(shrink(cur_val));
+    } else {
+        negate(cur_val);
+    }
+}
+*/
 
+void negate_cur_val(boolean modify_glue)
+{
+    if (cur_val_level >= glue_val_level) {
+        if (modify_glue) {
+            /* we modify in-place */
+        } else {
+            cur_val = new_spec(cur_val);
+        }
+        negate(width(cur_val));
+        negate(stretch(cur_val));
+        negate(shrink(cur_val));
     } else {
         negate(cur_val);
     }
@@ -296,7 +310,7 @@
         save_cur_chr = cur_chr;
         cur_chr = chr;
         /* Fetch an item in the current node, if appropriate */
-        /* Here is where \.{\\lastpenalty}, \.{\\lastkern}, and \.{\\lastskip} are
+        /* Here is where \.{\\lastpenalty}, \.{\\lastkern}, and \.{\\   } are
            implemented. The reference count for \.{\\lastskip} will be updated later.
 
            We also handle \.{\\inputlineno} and \.{\\badness} here, because they are
@@ -325,13 +339,16 @@
                 }
                 /* This code for reducing |cur_val_level| and\slash or negating the
                    result is similar to the one for all the other cases of
-                   |scan_something_internal|, with the difference that |scan_expr| has
-                   already increased the reference count of a glue specification.
+                   |scan_something_internal|; we free a glue_spec when needed.
                  */
                 while (cur_val_level > level) {
                     downgrade_cur_val(true);
                 }
                 if (negative) {
+                    /*
+                        we get a new glue spec node with negated values and the old
+                        intermediate is deleted
+                    */
                     negate_cur_val(true);
                 }
                 return succeeded;
@@ -475,7 +492,7 @@
             }
         } else {
             if (cur_chr == glue_val_level)
-                cur_val = zero_glue;
+                cur_val = zero_glue; /* a pointer */
             else
                 cur_val = 0;
             if (cur_chr == last_node_type_code) {
@@ -500,7 +517,8 @@
                     break;
                 case lastskip_code:
                     if (type(cur_list.tail_field) == glue_node)
-                        cur_val = new_glue(cur_list.tail_field);
+                     // cur_val = new_spec(cur_list.tail_field);
+                        cur_val = cur_list.tail_field;
                     if (subtype(cur_list.tail_field) == mu_glue)
                         cur_val_level = mu_val_level;
                     break;
@@ -519,7 +537,7 @@
                     break;
                 case lastskip_code:
                     if (last_glue != max_halfword)
-                        cur_val = last_glue; /* maybe new_glue */
+                        cur_val = last_glue;
                     break;
                 case last_node_type_code:
                     cur_val = last_node_type;
@@ -543,9 +561,10 @@
            If |negative| is |true|, |cur_val_level| is known to be |<=mu_val|.
          */
         if (negative) {
+            /* we create a new (negated) glue spec and keep the old one */
             negate_cur_val(false);
         } else if ((cur_val_level >= glue_val_level) && (cur_val_level <= mu_val_level)) {
-			cur_val = new_glue(cur_val);
+			cur_val = new_spec(cur_val);
         }
     }
     return succeeded;
@@ -660,8 +679,7 @@
             get_token();
             if (cur_cmd != math_style_cmd) {
                 print_err("Missing math style, treated as \\displaystyle");
-                help1
-                    ("A style should have been here; I inserted `\\displaystyle'.");
+                help1("A style should have been here; I inserted `\\displaystyle'.");
                 cur_val = display_style;
                 back_error();
             } else {
@@ -841,9 +859,10 @@
            If |negative| is |true|, |cur_val_level| is known to be |<=mu_val|.
          */
         if (negative) {
+            /* we create a new (negated) glue spec and keep the old one */
             negate_cur_val(false);
         } else if ((cur_val_level >= glue_val_level) && (cur_val_level <= mu_val_level)) {
-			cur_val = new_glue(cur_val);
+			cur_val = new_spec(cur_val);
         }
     }
 }
@@ -2485,8 +2504,8 @@
         t = f;
         if ((l >= glue_val_level) && (o != expr_none)) {
 	        /* do we really need to copy here ? */
-            t = new_spec(f);
-            flush_node(f);
+//            t = new_spec(f);
+//            flush_node(f);
             normalize_glue(t);
         } else {
             t = f;

Modified: trunk/Build/source/texk/web2c/luatexdir/tex/texmath.w
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/tex/texmath.w	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/tex/texmath.w	2017-02-03 21:33:11 UTC (rev 43128)
@@ -1778,6 +1778,7 @@
     halfword c;                 /* the type of generalized fraction we are scanning */
     pointer q;
     halfword options = 0;
+    halfword temp_value;
     c = cur_chr;
     if (incompleat_noad_par != null) {
         const char *hlp[] = {
@@ -1795,7 +1796,8 @@
         tex_error("Ambiguous; you need another { and }", hlp);
     } else {
         incompleat_noad_par = new_node(fraction_noad, 0);
-        numerator(incompleat_noad_par) = new_node(sub_mlist_node, 0);
+        temp_value = new_node(sub_mlist_node, 0);
+        numerator(incompleat_noad_par) = temp_value;
         math_list(numerator(incompleat_noad_par)) = vlink(head);
         vlink(head) = null;
         tail = head;
@@ -2430,9 +2432,34 @@
         }
         tail_append(new_math(math_surround_par, before));
         /* begin mathskip code */
-        if (! glue_is_zero(math_skip_par)) {
-            copy_glue_values(tail,math_skip_par);
-            surround(tail) = 0;
+        switch (math_skip_mode) {
+            case 0 :
+                /* obey mathsurround when zero glue */
+                if (! glue_is_zero(math_skip_par)) {
+                    copy_glue_values(tail,math_skip_par);
+                    surround(tail) = 0;
+                }
+                break ;
+            case 1 :
+                /* always left */
+            case 3 :
+                /* always both */
+            case 6 :
+                /* only when skip */
+                copy_glue_values(tail,math_skip_par);
+                surround(tail) = 0;
+                break ;
+            case 2 :
+                /* only right */
+                surround(tail) = 0;
+                break ;
+            case 4 :
+                /* ignore, obey marthsurround */
+                break ;
+            case 5:
+                /* all spacing disabled */
+                surround(tail) = 0;
+                break ;
         }
         /* end mathskip code */
         if (dir_math_save) {
@@ -2449,9 +2476,34 @@
         dir_math_save = false;
         tail_append(new_math(math_surround_par, after));
         /* begin mathskip code */
-        if (! glue_is_zero(math_skip_par)) {
-            copy_glue_values(tail,math_skip_par);
-            surround(tail) = 0;
+        switch (math_skip_mode) {
+            case 0 :
+                /* obey mathsurround when zero glue */
+                if (! glue_is_zero(math_skip_par)) {
+                    copy_glue_values(tail,math_skip_par);
+                    surround(tail) = 0;
+                }
+                break ;
+            case 2 :
+                /* always right */
+            case 3 :
+                /* always both */
+            case 6 :
+                /* only when skip */
+                copy_glue_values(tail,math_skip_par);
+                surround(tail) = 0;
+                break ;
+            case 1 :
+                /* only left */
+                surround(tail) = 0;
+                break ;
+            case 4 :
+                /* ignore, obey marthsurround */
+                break ;
+            case 5:
+                /* all spacing disabled */
+                surround(tail) = 0;
+                break ;
         }
         /* end mathskip code */
         space_factor_par = 1000;

Modified: trunk/Build/source/texk/web2c/luatexdir/tex/texnodes.h
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/tex/texnodes.h	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/tex/texnodes.h	2017-02-03 21:33:11 UTC (rev 43128)
@@ -376,7 +376,7 @@
     math_text_char_node,
     delim_node,                 /* shield fields */
     margin_kern_node,
-    glyph_node,
+    glyph_node,                 /* this and below have attributes */
     align_record_node,
     pseudo_file_node,
     pseudo_line_node,
@@ -947,6 +947,7 @@
 #  define ss_glue          fill_glue+glue_spec_size
 #  define fil_neg_glue     ss_glue+glue_spec_size
 #  define page_ins_head    fil_neg_glue+glue_spec_size
+
 #  define contrib_head     page_ins_head+temp_node_size
 #  define page_head        contrib_head+temp_node_size
 #  define temp_head        page_head+temp_node_size

Modified: trunk/Build/source/texk/web2c/luatexdir/tex/texnodes.w
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/tex/texnodes.w	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/tex/texnodes.w	2017-02-03 21:33:11 UTC (rev 43128)
@@ -1080,7 +1080,8 @@
 halfword copy_node(const halfword p)
 {
     halfword r;                 /* current node being fabricated for new list */
-    halfword w ;                /* whatsit subtype */
+    halfword w;                 /* whatsit subtype */
+    halfword t;                 /* type of node */
     register halfword s;        /* a helper variable for copying into variable mem  */
     register int i;
     if (copy_error(p)) {
@@ -1087,14 +1088,22 @@
         r = new_node(temp_node, 0);
         return r;
     }
-    i = get_node_size(type(p), subtype(p));
+    t = type(p);
+    i = get_node_size(t,subtype(p));
     r = get_node(i);
 
     (void) memcpy((void *) (varmem + r), (void *) (varmem + p), (sizeof(memory_word) * (unsigned) i));
 
+    /* possible speedup: */
+    /*
+        if t == glue_spec) {
+            return r;
+        }
+    */
+
     if (synctex_par) {
         /* handle synctex extension */
-        switch (type(p)) {
+        switch (t) {
             case math_node:
                 synctex_tag_math(r) = cur_input.synctex_tag_field;
                 synctex_line_math(r) = line;
@@ -1105,7 +1114,7 @@
                 break;
         }
     }
-    if (nodetype_has_attributes(type(p))) {
+    if (nodetype_has_attributes(t)) {
         add_node_attr_ref(node_attr(p));
         alink(r) = null;
         lua_properties_copy(r,p);
@@ -1112,7 +1121,7 @@
     }
     vlink(r) = null;
 
-    switch (type(p)) {
+    switch (t) {
         case glyph_node:
             copy_sub_list(lig_ptr(r),lig_ptr(p)) ;
             break;
@@ -1791,17 +1800,43 @@
     free_chain[s] = q;
 }
 
-@ @c
+@ At the start of the node memory area we reserve some special nodes,
+for instance frequently used glue specifications. We could as well just
+use new_glue here but for the moment we stick to the traditional approach.
+
+ at c
+#define initialize_glue(n,wi,st,sh,sto,sho) \
+    vlink(n) = null; \
+    type(n) = glue_spec_node; \
+    width(n) = wi; \
+    stretch(n) = st; \
+    shrink(n) = sh; \
+    stretch_order(n) = sto; \
+    shrink_order(n) = sho;
+
+#define initialize_whatever(n,t) \
+    vinfo(n) = 0; \
+    type(n) = t; \
+    vlink(n) = null; \
+    alink(n) = null;
+
+#define initialize_point(n) \
+    type(n) = glyph_node; \
+    subtype(n) = 0; \
+    vlink(n) = null; \
+    vinfo(n + 1) = null; \
+    alink(n) = null; \
+    font(n) = 0; \
+    character(n) = '.'; \
+    vinfo(n + 3) = 0; \
+    vlink(n + 3) = 0; \
+    vinfo(n + 4) = 0; \
+    vlink(n + 4) = 0;
+
 void init_node_mem(int t)
 {
     my_prealloc = var_mem_stat_max;
 
-    /*  message ?
-
-        assert(whatsit_node_data[user_defined_node].id == user_defined_node);
-        assert(node_data[passive_node].id == passive_node);
-    */
-
     varmem = (memory_word *) realloc((void *) varmem, sizeof(memory_word) * (unsigned) t);
     if (varmem == NULL) {
         overflow("node memory size", (unsigned) var_mem_max);
@@ -1819,112 +1854,32 @@
     vlink(rover) = rover;
     node_size(rover) = (t - rover);
     var_used = 0;
+
     /* initialize static glue specs */
-    width(zero_glue) = 0;
-    type(zero_glue) = glue_spec_node;
-    vlink(zero_glue) = null;
-    stretch(zero_glue) = 0;
-    stretch_order(zero_glue) = normal;
-    shrink(zero_glue) = 0;
-    shrink_order(zero_glue) = normal;
-    width(sfi_glue) = 0;
-    type(sfi_glue) = glue_spec_node;
-    vlink(sfi_glue) = null;
-    stretch(sfi_glue) = 0;
-    stretch_order(sfi_glue) = sfi;
-    shrink(sfi_glue) = 0;
-    shrink_order(sfi_glue) = normal;
-    width(fil_glue) = 0;
-    type(fil_glue) = glue_spec_node;
-    vlink(fil_glue) = null;
-    stretch(fil_glue) = unity;
-    stretch_order(fil_glue) = fil;
-    shrink(fil_glue) = 0;
-    shrink_order(fil_glue) = normal;
-    width(fill_glue) = 0;
-    type(fill_glue) = glue_spec_node;
-    vlink(fill_glue) = null;
-    stretch(fill_glue) = unity;
-    stretch_order(fill_glue) = fill;
-    shrink(fill_glue) = 0;
-    shrink_order(fill_glue) = normal;
-    width(ss_glue) = 0;
-    type(ss_glue) = glue_spec_node;
-    vlink(ss_glue) = null;
-    stretch(ss_glue) = unity;
-    stretch_order(ss_glue) = fil;
-    shrink(ss_glue) = unity;
-    shrink_order(ss_glue) = fil;
-    width(fil_neg_glue) = 0;
-    type(fil_neg_glue) = glue_spec_node;
-    vlink(fil_neg_glue) = null;
-    stretch(fil_neg_glue) = -unity;
-    stretch_order(fil_neg_glue) = fil;
-    shrink(fil_neg_glue) = 0;
-    shrink_order(fil_neg_glue) = normal;
+
+    initialize_glue(zero_glue,0,0,0,0,0);
+    initialize_glue(sfi_glue,0,0,0,sfi,0);
+    initialize_glue(fil_glue,0,unity,0,fil,0);
+    initialize_glue(fill_glue,0,unity,0,fill,0);
+    initialize_glue(ss_glue,0,unity,unity,fil,fil);
+    initialize_glue(fil_neg_glue,0,-unity,0,fil,0);
+
     /* initialize node list heads */
-    vinfo(page_ins_head) = 0;
-    type(page_ins_head) = temp_node;
-    vlink(page_ins_head) = null;
-    alink(page_ins_head) = null;
-    vinfo(contrib_head) = 0;
-    type(contrib_head) = temp_node;
-    vlink(contrib_head) = null;
-    alink(contrib_head) = null;
-    vinfo(page_head) = 0;
-    type(page_head) = temp_node;
-    vlink(page_head) = null;
-    alink(page_head) = null;
-    vinfo(temp_head) = 0;
-    type(temp_head) = temp_node;
-    vlink(temp_head) = null;
-    alink(temp_head) = null;
-    vinfo(hold_head) = 0;
-    type(hold_head) = temp_node;
-    vlink(hold_head) = null;
-    alink(hold_head) = null;
-    vinfo(adjust_head) = 0;
-    type(adjust_head) = temp_node;
-    vlink(adjust_head) = null;
-    alink(adjust_head) = null;
-    vinfo(pre_adjust_head) = 0;
-    type(pre_adjust_head) = temp_node;
-    vlink(pre_adjust_head) = null;
-    alink(pre_adjust_head) = null;
-    vinfo(active) = 0;
-    type(active) = unhyphenated_node;
-    vlink(active) = null;
-    alink(active) = null;
-    vinfo(align_head) = 0;
-    type(align_head) = temp_node;
-    vlink(align_head) = null;
-    alink(align_head) = null;
-    vinfo(end_span) = 0;
-    type(end_span) = span_node;
-    vlink(end_span) = null;
-    alink(end_span) = null;
-    type(begin_point) = glyph_node;
-    subtype(begin_point) = 0;
-    vlink(begin_point) = null;
-    vinfo(begin_point + 1) = null;
-    alink(begin_point) = null;
-    font(begin_point) = 0;
-    character(begin_point) = '.';
-    vinfo(begin_point + 3) = 0;
-    vlink(begin_point + 3) = 0;
-    vinfo(begin_point + 4) = 0;
-    vlink(begin_point + 4) = 0;
-    type(end_point) = glyph_node;
-    subtype(end_point) = 0;
-    vlink(end_point) = null;
-    vinfo(end_point + 1) = null;
-    alink(end_point) = null;
-    font(end_point) = 0;
-    character(end_point) = '.';
-    vinfo(end_point + 3) = 0;
-    vlink(end_point + 3) = 0;
-    vinfo(end_point + 4) = 0;
-    vlink(end_point + 4) = 0;
+
+    initialize_whatever(page_ins_head,temp_node);
+    initialize_whatever(contrib_head,temp_node);
+    initialize_whatever(page_head,temp_node);
+    initialize_whatever(temp_head,temp_node);
+    initialize_whatever(hold_head,temp_node);
+    initialize_whatever(adjust_head,temp_node);
+    initialize_whatever(pre_adjust_head,temp_node);
+    initialize_whatever(align_head,temp_node);
+
+    initialize_whatever(active,unhyphenated_node);
+    initialize_whatever(end_span,span_node);
+
+    initialize_point(begin_point);
+    initialize_point(end_point);
 }
 
 @ @c
@@ -3609,9 +3564,24 @@
 to be exactly one reference to the new specification.
 
 @c
-halfword new_spec(halfword p)
+halfword new_spec(halfword q) /* safeguard for copying a glue node */
 {
-    return copy_node(p == null ? zero_glue : p);
+    if (q == null) {
+        return copy_node(zero_glue);
+    } else if (type(q) == glue_spec_node) {
+        return copy_node(q);
+    } else if (type(q) == glue_node) {
+        halfword p = copy_node(zero_glue);
+        width(p) = width(q);
+        stretch(p) = stretch(q);
+        shrink(p) = shrink(q);
+        stretch_order(p) = stretch_order(q);
+        shrink_order(p) = shrink_order(q);
+        return p;
+    } else {
+        /* alternatively we can issue a warning */
+        return copy_node(zero_glue);
+    }
 }
 
 @ And here's a function that creates a glue node for a given parameter

Modified: trunk/Build/source/texk/web2c/luatexdir/tex/textoken.w
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/tex/textoken.w	2017-02-03 01:05:41 UTC (rev 43127)
+++ trunk/Build/source/texk/web2c/luatexdir/tex/textoken.w	2017-02-03 21:33:11 UTC (rev 43128)
@@ -2325,6 +2325,7 @@
     else if (scan_keyword("gentounicode"))         { do_variable_backend_int(c_pdf_gen_tounicode); }
     else if (scan_keyword("pkfixeddpi"))           { do_variable_backend_int(c_pdf_pk_fixed_dpi); }
     else if (scan_keyword("suppressoptionalinfo")) { do_variable_backend_int(c_pdf_suppress_optional_info); }
+    else if (scan_keyword("omitcidset"))           { do_variable_backend_int(c_pdf_omit_cidset); }
 
     else if (scan_keyword("horigin"))              { do_variable_backend_dimen(d_pdf_h_origin); }
     else if (scan_keyword("vorigin"))              { do_variable_backend_dimen(d_pdf_v_origin); }
@@ -2702,7 +2703,6 @@
             pop_selector;
             break;
         case normal_deviate_code:
-            scan_int();
             push_selector;
             print_int(norm_rand());
             pop_selector;



More information about the tex-live-commits mailing list