From 0b5550c241229764120d133af80a0cbab5937ddd Mon Sep 17 00:00:00 2001 From: Martin Schröder Date: Mon, 24 Mar 2008 15:47:15 +0000 Subject: First step of importing luatex (up to r1121) git-svn-id: svn://tug.org/texlive/trunk@7124 c570f23f-e606-0410-a88d-b1316a301751 --- Build/source/texk/web2c/luatexdir/tex/texnodes.c | 1694 ++++++++++++++++++++++ 1 file changed, 1694 insertions(+) create mode 100644 Build/source/texk/web2c/luatexdir/tex/texnodes.c (limited to 'Build/source/texk/web2c/luatexdir/tex/texnodes.c') diff --git a/Build/source/texk/web2c/luatexdir/tex/texnodes.c b/Build/source/texk/web2c/luatexdir/tex/texnodes.c new file mode 100644 index 00000000000..06004160503 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/tex/texnodes.c @@ -0,0 +1,1694 @@ +/* $Id: texnodes.c 1103 2008-03-11 14:32:50Z taco $ */ + +#include "luatex-api.h" +#include +#include "nodes.h" + +#define MAX_CHAIN_SIZE 12 + +volatile memory_word *varmem = NULL; + +#ifndef NDEBUG +char *varmem_sizes = NULL; +#endif + +halfword var_mem_max = 0; +halfword rover = 0; + +halfword free_chain[MAX_CHAIN_SIZE] = {null}; + +static int prealloc=0; + +int fix_node_lists=1; + +int free_error_seen = 0; +int copy_error_seen = 0; + +halfword slow_get_node (integer s) ; /* defined below */ +int copy_error (halfword p) ; /* define below */ + +#undef link /* defined by cpascal.h */ +#define info(a) fixmem[(a)].hhlh +#define link(a) fixmem[(a)].hhrh + +#define fake_node 100 +#define fake_node_size 2 +#define fake_node_name "fake" + +#define variable_node_size 2 + + +char * node_fields_list [] = { "attr", "width", "depth", "height", "dir", "shift", + "glue_order", "glue_sign", "glue_set" , "list", NULL }; +char * node_fields_rule [] = { "attr", "width", "depth", "height", "dir", NULL }; +char * node_fields_insert [] = { "attr", "cost", "depth", "height", "spec", "list", NULL }; +char * node_fields_mark [] = { "attr", "class", "mark", NULL }; +char * node_fields_adjust [] = { "attr", "list", NULL }; +char * node_fields_disc [] = { "attr", "pre", "post", "replace", NULL }; +char * node_fields_math [] = { "attr", "surround", NULL }; +char * node_fields_glue [] = { "attr", "spec", "leader", NULL }; +char * node_fields_kern [] = { "attr", "kern", NULL }; +char * node_fields_penalty [] = { "attr", "penalty", NULL }; +char * node_fields_unset [] = { "attr", "width", "depth", "height", "dir", "shrink", + "glue_order", "glue_sign", "stretch" , "span", "list", NULL }; +char * node_fields_margin_kern [] = { "attr", "width", "glyph", NULL }; +char * node_fields_glyph [] = { "attr", "char", "font", "lang", "left", "right", "uchyph", + "components", "xoffset", "yoffset", NULL }; +char * node_fields_style [] = { NULL }; +char * node_fields_choice [] = { NULL }; +char * node_fields_ord [] = { NULL }; +char * node_fields_op [] = { NULL }; +char * node_fields_bin [] = { NULL }; +char * node_fields_rel [] = { NULL }; +char * node_fields_open [] = { NULL }; +char * node_fields_close [] = { NULL }; +char * node_fields_punct [] = { NULL }; +char * node_fields_inner [] = { NULL }; +char * node_fields_radical [] = { NULL }; +char * node_fields_fraction [] = { NULL }; +char * node_fields_under [] = { NULL }; +char * node_fields_over [] = { NULL }; +char * node_fields_accent [] = { NULL }; +char * node_fields_vcenter [] = { NULL }; +char * node_fields_left [] = { NULL }; +char * node_fields_right [] = { NULL }; + +char * node_fields_inserting [] = { "height", "last_ins_ptr", "best_ins_ptr", NULL}; + +char * node_fields_splitup [] = { "height", "last_ins_ptr", "best_ins_ptr", + "broken_ptr", "broken_ins", NULL}; + +char * node_fields_action [] = { "action_type", "named_id", "action_id", + "file", "new_window", "data", "ref_count", NULL }; +char * node_fields_attribute [] = { "number", "value", NULL }; +char * node_fields_glue_spec [] = { "width", "stretch", "shrink", + "stretch_order", "shrink_order", "ref_count", NULL }; +char * node_fields_attribute_list [] = { NULL }; + +char * node_fields_whatsit_open [] = { "attr", "stream", "name", "area", "ext", NULL }; +char * node_fields_whatsit_write [] = { "attr", "stream", "data", NULL }; +char * node_fields_whatsit_close [] = { "attr", "stream", NULL }; +char * node_fields_whatsit_special [] = { "attr", "data", NULL }; + +char * node_fields_whatsit_local_par [] = { "attr", "pen_inter", "pen_broken", "dir", + "box_left", "box_left_width", "box_right", "box_right_width", NULL }; +char * node_fields_whatsit_dir [] = { "attr", "dir", "level", "dvi_ptr", "dvi_h", NULL }; + +char * node_fields_whatsit_pdf_literal [] = { "attr", "mode", "data", NULL }; +char * node_fields_whatsit_pdf_refobj [] = { "attr", "objnum", NULL }; +char * node_fields_whatsit_pdf_refxform [] = { "attr", "width", "height", "depth", "objnum", NULL }; +char * node_fields_whatsit_pdf_refximage [] = { "attr", "width", "height", "depth", "objnum", NULL }; +char * node_fields_whatsit_pdf_annot [] = { "attr", "width", "height", "depth", "objnum", "data", NULL }; +char * node_fields_whatsit_pdf_start_link [] = { "attr", "width", "height", "depth", + "objnum", "link_attr", "action", NULL }; +char * node_fields_whatsit_pdf_end_link [] = { "attr", NULL }; +char * node_fields_whatsit_pdf_dest [] = { "attr", "width", "height", "depth", + "named_id", "dest_id", "dest_type", "xyz_zoom", "objnum", NULL }; +char * node_fields_whatsit_pdf_thread [] = { "attr", "width", "height", "depth", + "named_id", "thread_id", "thread_attr", NULL }; +char * node_fields_whatsit_pdf_start_thread [] = { "attr", "width", "height", "depth", + "named_id", "thread_id", "thread_attr", NULL }; +char * node_fields_whatsit_pdf_end_thread [] = { "attr", NULL }; +char * node_fields_whatsit_pdf_save_pos [] = { "attr", NULL }; +char * node_fields_whatsit_late_lua [] = { "attr", "reg", "data", NULL }; +char * node_fields_whatsit_close_lua [] = { "attr", "reg", NULL }; +char * node_fields_whatsit_pdf_colorstack [] = { "attr", "stack", "cmd", "data", NULL }; +char * node_fields_whatsit_pdf_setmatrix [] = { "attr", "data", NULL }; +char * node_fields_whatsit_pdf_save [] = { "attr", NULL }; +char * node_fields_whatsit_pdf_restore [] = { "attr", NULL }; +char * node_fields_whatsit_cancel_boundary [] = { "attr", NULL }; +char * node_fields_whatsit_user_defined [] = { "attr", "user_id", "type", "value", NULL }; + +node_info node_data[] = { + { hlist_node, box_node_size, node_fields_list, "hlist" }, + { vlist_node, box_node_size, node_fields_list, "vlist" }, + { rule_node, rule_node_size, node_fields_rule, "rule" }, + { ins_node, ins_node_size, node_fields_insert, "ins" }, + { mark_node, mark_node_size, node_fields_mark, "mark" }, + { adjust_node, adjust_node_size, node_fields_adjust, "adjust" }, + { fake_node, fake_node_size, NULL, fake_node_name }, /* don't touch this! */ + { disc_node, disc_node_size, node_fields_disc, "disc" }, + { whatsit_node, -1, NULL, "whatsit" }, + { math_node, math_node_size, node_fields_math, "math" }, + { glue_node, glue_node_size, node_fields_glue, "glue" }, + { kern_node, kern_node_size, node_fields_kern, "kern" }, + { penalty_node, penalty_node_size, node_fields_penalty, "penalty" }, + { unset_node, box_node_size, node_fields_unset, "unset" }, + { style_node, style_node_size, node_fields_style, "style" }, + { choice_node, style_node_size, node_fields_choice, "choice" }, + { ord_noad, noad_size, node_fields_ord, "ord" }, + { op_noad, noad_size, node_fields_op, "op" }, + { bin_noad, noad_size, node_fields_bin, "bin" }, + { rel_noad, noad_size, node_fields_rel, "rel" }, + { open_noad, noad_size, node_fields_open, "open" }, + { close_noad, noad_size, node_fields_close, "close" }, + { punct_noad, noad_size, node_fields_punct, "punct" }, + { inner_noad, noad_size, node_fields_inner, "inner" }, + { radical_noad, radical_noad_size, node_fields_radical, "radical" }, + { fraction_noad, fraction_noad_size, node_fields_fraction, "fraction" }, + { under_noad, noad_size, node_fields_under, "under" }, + { over_noad, noad_size, node_fields_over, "over" }, + { accent_noad, accent_noad_size, node_fields_accent, "accent" }, + { vcenter_noad, noad_size, node_fields_vcenter, "vcenter" }, + { left_noad, noad_size, node_fields_left, "left" }, + { right_noad, noad_size, node_fields_right, "right" }, + { margin_kern_node, margin_kern_node_size, node_fields_margin_kern, "margin_kern" }, + { glyph_node, glyph_node_size, node_fields_glyph, "glyph" }, /* 33 */ + { align_record_node, box_node_size, NULL, "align_record" }, + { pseudo_file_node, pseudo_file_node_size, NULL, "pseudo_file" }, + { pseudo_line_node, variable_node_size, NULL, "pseudo_line" }, + { inserting_node, page_ins_node_size, node_fields_inserting, "page_insert" }, + { split_up_node, page_ins_node_size, node_fields_splitup, "split_insert" }, + { expr_node, expr_node_size, NULL, "expr_stack" }, + { nesting_node, nesting_node_size, NULL, "nested_list" }, /* 40 */ + { span_node, span_node_size, NULL, "span" }, + { attribute_node, attribute_node_size, node_fields_attribute, "attribute" }, + { glue_spec_node, glue_spec_size, node_fields_glue_spec, "glue_spec" }, + { attribute_list_node, attribute_node_size, node_fields_attribute_list,"attribute_list" }, + { action_node, pdf_action_size, node_fields_action, "action" }, + { temp_node, temp_node_size, NULL, "temp" }, + { align_stack_node, align_stack_node_size, NULL, "align_stack" }, + { movement_node, movement_node_size, NULL, "movement_stack" }, + { if_node, if_node_size, NULL, "if_stack" }, + { unhyphenated_node, active_node_size, NULL, "unhyphenated" }, /* 50 */ + { hyphenated_node, active_node_size, NULL, "hyphenated" }, + { delta_node, delta_node_size, NULL, "delta" }, + { passive_node, passive_node_size, NULL, "passive" }, + { shape_node, variable_node_size, NULL, "shape" }, + { -1, -1, NULL, NULL }}; + +#define last_normal_node shape_node + +node_info whatsit_node_data[] = { + { open_node, open_node_size, node_fields_whatsit_open, "open" }, + { write_node, write_node_size, node_fields_whatsit_write, "write" }, + { close_node, close_node_size, node_fields_whatsit_close, "close" }, + { special_node, special_node_size, node_fields_whatsit_special, "special" }, + { fake_node, fake_node_size, NULL, fake_node_name }, + { fake_node, fake_node_size, NULL, fake_node_name }, + { local_par_node, local_par_size, node_fields_whatsit_local_par, "local_par" }, + { dir_node, dir_node_size, node_fields_whatsit_dir, "dir" }, + { pdf_literal_node, write_node_size, node_fields_whatsit_pdf_literal, "pdf_literal" }, + { fake_node, fake_node_size, NULL, fake_node_name }, + { pdf_refobj_node, pdf_refobj_node_size, node_fields_whatsit_pdf_refobj, "pdf_refobj" }, + { fake_node, fake_node_size, NULL, fake_node_name }, + { pdf_refxform_node, pdf_refxform_node_size, node_fields_whatsit_pdf_refxform, "pdf_refxform" }, + { fake_node, fake_node_size, NULL, fake_node_name }, + { pdf_refximage_node, pdf_refximage_node_size, node_fields_whatsit_pdf_refximage, "pdf_refximage" }, + { pdf_annot_node, pdf_annot_node_size, node_fields_whatsit_pdf_annot, "pdf_annot" }, + { pdf_start_link_node, pdf_annot_node_size, node_fields_whatsit_pdf_start_link, "pdf_start_link" }, + { pdf_end_link_node, pdf_end_link_node_size, node_fields_whatsit_pdf_end_link, "pdf_end_link" }, + { fake_node, fake_node_size, NULL, fake_node_name }, + { pdf_dest_node, pdf_dest_node_size, node_fields_whatsit_pdf_dest, "pdf_dest" }, + { pdf_thread_node, pdf_thread_node_size, node_fields_whatsit_pdf_thread, "pdf_thread" }, + { pdf_start_thread_node, pdf_thread_node_size, node_fields_whatsit_pdf_start_thread,"pdf_start_thread"}, + { pdf_end_thread_node, pdf_end_thread_node_size, node_fields_whatsit_pdf_end_thread, "pdf_end_thread" }, + { pdf_save_pos_node, pdf_save_pos_node_size, node_fields_whatsit_pdf_save_pos, "pdf_save_pos" }, + { pdf_thread_data_node, pdf_thread_node_size, NULL, "pdf_thread_data" }, + { pdf_link_data_node, pdf_annot_node_size, NULL, "pdf_link_data" }, + { fake_node, fake_node_size, NULL, fake_node_name }, + { fake_node, fake_node_size, NULL, fake_node_name }, + { fake_node, fake_node_size, NULL, fake_node_name }, + { fake_node, fake_node_size, NULL, fake_node_name }, + { fake_node, fake_node_size, NULL, fake_node_name }, + { fake_node, fake_node_size, NULL, fake_node_name }, + { fake_node, fake_node_size, NULL, fake_node_name }, + { fake_node, fake_node_size, NULL, fake_node_name }, + { fake_node, fake_node_size, NULL, fake_node_name }, + { late_lua_node, write_node_size, node_fields_whatsit_late_lua, "late_lua" }, + { close_lua_node, write_node_size, node_fields_whatsit_close_lua, "close_lua" }, + { fake_node, fake_node_size, NULL, fake_node_name }, + { fake_node, fake_node_size, NULL, fake_node_name }, + { pdf_colorstack_node, pdf_colorstack_node_size, node_fields_whatsit_pdf_colorstack, "pdf_colorstack" }, + { pdf_setmatrix_node, pdf_setmatrix_node_size, node_fields_whatsit_pdf_setmatrix, "pdf_setmatrix" }, + { pdf_save_node, pdf_save_node_size, node_fields_whatsit_pdf_save, "pdf_save" }, + { pdf_restore_node, pdf_restore_node_size, node_fields_whatsit_pdf_restore, "pdf_restore" }, + { cancel_boundary_node, cancel_boundary_size, node_fields_whatsit_cancel_boundary, "cancel_boundary" }, + { user_defined_node, user_defined_node_size, node_fields_whatsit_user_defined, "user_defined" }, + { -1, -1, NULL, NULL }}; + +#define last_whatsit_node user_defined_node + +#define get_node_size(i,j) (i!=whatsit_node ? node_data[i].size : whatsit_node_data[j].size) +#define get_node_name(i,j) (i!=whatsit_node ? node_data[i].name : whatsit_node_data[j].name) + +halfword +new_node(int i, int j) { + register int s; + register halfword n; + s = get_node_size(i,j); + n = get_node(s); + /* it should be possible to do this memset at free_node() */ + /* type() and subtype() will be set below, and vlink() is + set to null by get_node(), so we can do we clearing one + word less than |s| */ + (void)memset((void *)(varmem+n+1),0, (sizeof(memory_word)*(s-1))); + switch (i) { + case glyph_node: + init_lang_data(n); + break; + case glue_node: + case kern_node: + case glue_spec_node: + break; + case hlist_node: + case vlist_node: + box_dir(n)=-1; + break; + case whatsit_node: + if (j==open_node) { + open_name(n) = get_nullstr(); + open_area(n) = open_name(n); + open_ext(n) = open_name(n); + } + break; + case disc_node: + pre_break(n)=pre_break_head(n); + type(pre_break(n))= nesting_node; + subtype(pre_break(n))=pre_break_head(0); + post_break(n)=post_break_head(n); + type(post_break(n))= nesting_node; + subtype(post_break(n))=post_break_head(0); + no_break(n)=no_break_head(n); + type(no_break(n))= nesting_node; + subtype(no_break(n))=no_break_head(0); + break; + case rule_node: + depth(n)=null_flag; + height(n)=null_flag; + rule_dir(n)=-1; + /* fall through */ + case unset_node: + width(n) = null_flag; + break; + case pseudo_line_node: + case shape_node: + /* this is a trick that makes pseudo_files slightly slower, + * but the overall allocation faster then an explicit test + * at the top of new_node(). + */ + free_node(n,variable_node_size); + n = slow_get_node(j); + (void)memset((void *)(varmem+n+1),0, (sizeof(memory_word)*(j-1))); + break; + default: + break; + } + if (nodetype_has_attributes(i)) { + build_attribute_list(n); + } + type(n)=i; + subtype(n)=j; + return n; +} + +halfword +raw_glyph_node(void) { + register halfword n; + n = get_node(glyph_node_size); + (void)memset((void *)(varmem+n+1),0, (sizeof(memory_word)*(glyph_node_size-1))); + type(n)=glyph_node; + subtype(n)=0; + return n; +} + +halfword +new_glyph_node(void) { + register halfword n; + n = get_node(glyph_node_size); + (void)memset((void *)(varmem+n+1),0, (sizeof(memory_word)*(glyph_node_size-1))); + type(n)=glyph_node; + subtype(n)=0; + build_attribute_list(n); + return n; +} + + +/* makes a duplicate of the node list that starts at |p| and returns a + pointer to the new list */ + +halfword +copy_node_list(halfword p) { + halfword q; /* previous position in new list */ + halfword h = null; /* head of the list */ + copy_error_seen = 0; + while (p!=null) { + register halfword s = copy_node(p); + if (h==null) { + h = s; + } else { + couple_nodes(q,s); + } + q=s; + p=vlink(p); + } + return h; +} + + /* make a dupe of a single node */ +halfword +copy_node(const halfword p) { + halfword r; /* current node being fabricated for new list */ + register halfword s; /* a helper variable for copying into variable mem */ + register int i; + if (copy_error(p)) { + r = new_node(temp_node,0); + return r; + } + i = get_node_size(type(p), subtype(p)); + r = get_node(i); + (void)memcpy((void *)(varmem+r),(void *)(varmem+p),(sizeof(memory_word)*i)); + + if (nodetype_has_attributes(type(p))) { + add_node_attr_ref(node_attr(p)); + alink(r)=null; /* needs checking */ + } + vlink(r)=null; + switch (type(p)) { + case glyph_node: + s=copy_node_list(lig_ptr(p)); + lig_ptr(r)=s; + break; + case glue_node: + add_glue_ref(glue_ptr(p)); + s=copy_node_list(leader_ptr(p)); + leader_ptr(r)=s; + break; + case hlist_node: + case vlist_node: + case unset_node: + s=copy_node_list(list_ptr(p)); + list_ptr(r)=s; + break; + case ins_node: + add_glue_ref(split_top_ptr(p)); + s=copy_node_list(ins_ptr(p)); + ins_ptr(r)=s; + break; + case margin_kern_node: + s=copy_node(margin_char(p)); + margin_char(r)=s; + break; + case disc_node: + pre_break(r)=pre_break_head(r); + if (vlink_pre_break(p)!=null) { + s=copy_node_list(vlink_pre_break(p)); + alink(s)=pre_break(r); + tlink_pre_break(r)=tail_of_list(s); + vlink_pre_break(r)=s; + } else { + assert(tlink(pre_break(r))==null); + } + post_break(r)=post_break_head(r); + if (vlink_post_break(p)!=null) { + s=copy_node_list(vlink_post_break(p)); + alink(s)=post_break(r); + tlink_post_break(r)=tail_of_list(s); + vlink_post_break(r)=s; + } else { + assert(tlink_post_break(r)==null); + } + no_break(r)=no_break_head(r); + if (vlink(no_break(p))!=null) { + s=copy_node_list(vlink_no_break(p)); + alink(s)=no_break(r); + tlink_no_break(r)=tail_of_list(s); + vlink_no_break(r)=s; + } else { + assert(tlink_no_break(r)==null); + } + break; + case mark_node: + add_token_ref(mark_ptr(p)); + break; + case adjust_node: + s=copy_node_list(adjust_ptr(p)); + adjust_ptr(r)=s; + break; + case glue_spec_node: + glue_ref_count(r)=null; + break; + case whatsit_node: + switch (subtype(p)) { + case dir_node: + case local_par_node: + break; + case write_node: + case special_node: + add_token_ref(write_tokens(p)); + break; + case pdf_literal_node: + add_token_ref(pdf_literal_data(p)); + break; + case pdf_colorstack_node: + if (pdf_colorstack_cmd(p) <= colorstack_data) + add_token_ref(pdf_colorstack_data(p)); + break; + case pdf_setmatrix_node: + add_token_ref(pdf_setmatrix_data(p)); + break; + case late_lua_node: + add_token_ref(late_lua_data(p)); + break; + case pdf_annot_node: + add_token_ref(pdf_annot_data(p)); + break; + case pdf_start_link_node: + if (pdf_link_attr(r) != null) + add_token_ref(pdf_link_attr(r)); + add_action_ref(pdf_link_action(r)); + break; + case pdf_dest_node: + if (pdf_dest_named_id(p) > 0) + add_token_ref(pdf_dest_id(p)); + break; + case pdf_thread_node: + case pdf_start_thread_node: + if (pdf_thread_named_id(p) > 0) + add_token_ref(pdf_thread_id(p)); + if (pdf_thread_attr(p) != null) + add_token_ref(pdf_thread_attr(p)); + break; + case user_defined_node: + switch (user_node_type(p)) { + case 'a': add_node_attr_ref(user_node_value(p)); + break; + case 't': add_token_ref(user_node_value(p)); + break; + case 'n': + s=copy_node_list(user_node_value(p)); + user_node_value(r)=s; + break; + } + break; + default: + break; + } + break; + } + return r; +} + +int valid_node (halfword p) { + if (p>prealloc) { + if (p0) + return 1; + } + } else { + return 1; + } + return 0; +} + +static void +do_free_error (halfword p) { + char errstr[255]= {0}; + char *errhlp[] = {"When I tried to free the node mentioned in the error message, it turned", + "out it was not (or no longer) actually in use.", + "Errors such as these are often caused by Lua node list alteration,", + "but could also point to a bug in the executable. It should be safe to continue.", + NULL}; + + check_node_mem(); + if (free_error_seen) + return; + + halfword r = null; + free_error_seen = 1; + if (type(p)==glyph_node) { + snprintf(errstr,255,"Attempt to double-free glyph (%c) node %d, ignored", (int)character (p), (int)p); + } else { + snprintf(errstr,255,"Attempt to double-free %s node %d, ignored", get_node_name(type(p),subtype(p)), (int)p); + } + tex_error(errstr,errhlp); + for (r=prealloc+1;rprealloc && varmem_sizes[s]==0) + s--; + if (s!=null + && s!=prealloc + && s!=var_mem_max + && (r-s)prealloc); + assert(p=0); + assert(pprealloc && varmem_sizes[p]==0) { + do_copy_error(p); + return 1; /* copy free node */ + } + return 0; +} + + + +void +flush_node (halfword p) { + + if (p==null) /* legal, but no-op */ + return; + + if (free_error(p)) + return; + + switch(type(p)) { + case glyph_node: + flush_node_list(lig_ptr(p)); + break; + case glue_node: + delete_glue_ref(glue_ptr(p)); + flush_node_list(leader_ptr(p)); + break; + + case attribute_node: + case attribute_list_node: + case temp_node: + case glue_spec_node: + case rule_node: + case kern_node: + case math_node: + case penalty_node: + break; + + case hlist_node: + case vlist_node: + case unset_node: + flush_node_list(list_ptr(p)); + break; + case whatsit_node: + switch (subtype(p)) { + + case dir_node: + break; + case open_node: + case write_node: + case close_node: + case pdf_save_node: + case pdf_restore_node: + case cancel_boundary_node: + case close_lua_node: + case pdf_refobj_node: + case pdf_refxform_node: + case pdf_refximage_node: + case pdf_end_link_node: + case pdf_end_thread_node: + case pdf_save_pos_node: + case local_par_node: + break; + + case special_node: + delete_token_ref(write_tokens(p)); + break; + case pdf_literal_node: + delete_token_ref(pdf_literal_data(p)); + break; + case pdf_colorstack_node: + if (pdf_colorstack_cmd(p) <= colorstack_data) + delete_token_ref(pdf_colorstack_data(p)); + break; + case pdf_setmatrix_node: + delete_token_ref(pdf_setmatrix_data(p)); + break; + case late_lua_node: + delete_token_ref(late_lua_data(p)); + break; + case pdf_annot_node: + delete_token_ref(pdf_annot_data(p)); + break; + + case pdf_link_data_node: + break; + + case pdf_start_link_node: + if (pdf_link_attr(p) != null) + delete_token_ref(pdf_link_attr(p)); + delete_action_ref(pdf_link_action(p)); + break; + case pdf_dest_node: + if (pdf_dest_named_id(p) > 0) + delete_token_ref(pdf_dest_id(p)); + break; + + case pdf_thread_data_node: + break; + + case pdf_thread_node: + case pdf_start_thread_node: + if (pdf_thread_named_id(p) > 0 ) delete_token_ref(pdf_thread_id(p)); + if (pdf_thread_attr(p) != null) delete_token_ref(pdf_thread_attr(p)); + break; + case user_defined_node: + switch( user_node_type(p)) { + case 'a': delete_attribute_ref(user_node_value(p)); break; + case 't': delete_token_ref(user_node_value(p)); break; + case 'n': flush_node_list(user_node_value(p)); break; + default: tconfusion("extuser"); break; + } + break; + + default: + tconfusion("ext3"); + return; + + } + break; + case ins_node: + flush_node_list(ins_ptr(p)); + delete_glue_ref(split_top_ptr(p)); + break; + case margin_kern_node: + flush_node(margin_char(p)); + break; + case mark_node: + delete_token_ref(mark_ptr(p)); + break; + case disc_node: + flush_node_list(vlink(pre_break(p))); + flush_node_list(vlink(post_break(p))); + flush_node_list(vlink(no_break(p))); + break; + case adjust_node: + flush_node_list(adjust_ptr(p)); + break; + case style_node: + break; + case choice_node: + flush_node_list(display_mlist(p)); + flush_node_list(text_mlist(p)); + flush_node_list(script_mlist(p)); + flush_node_list(script_script_mlist(p)); + break; + case ord_noad: + case op_noad: + case bin_noad: + case rel_noad: + case open_noad: + case close_noad: + case punct_noad: + case inner_noad: + case radical_noad: + case over_noad: + case under_noad: + case vcenter_noad: + case accent_noad: + + /* + * if (math_type(nucleus(p))>=sub_box) + * flush_node_list(vinfo(nucleus(p))); + * if (math_type(supscr(p))>=sub_box) + * flush_node_list(vinfo(supscr(p))); + * if (math_type(subscr(p))>=sub_box) + * flush_node_list(vinfo(subscr(p))); + */ + + break; + case left_noad: + case right_noad: + break; + case fraction_noad: + flush_node_list(vinfo(numerator(p))); + flush_node_list(vinfo(denominator(p))); + break; + case pseudo_file_node: + flush_node_list(pseudo_lines(p)); + break; + case pseudo_line_node: + case shape_node: + free_node(p,subtype(p)); + return; + break; + case align_stack_node: + case span_node: + case movement_node: + case if_node: + case nesting_node: + case unhyphenated_node: + case hyphenated_node: + case delta_node: + case passive_node: + case action_node: + case inserting_node: + case split_up_node: + case expr_node: + break; + default: + fprintf(stdout,"flush_node: type is %d\n", type(p)); + return; + + } + if (nodetype_has_attributes(type(p))) + delete_attribute_ref(node_attr(p)); + free_node(p,get_node_size(type(p),subtype(p))); + return; +} + +void +flush_node_list(halfword pp) { /* erase list of nodes starting at |p| */ + register halfword p=pp; + free_error_seen = 0; + if (p==null) /* legal, but no-op */ + return; + if (free_error(p)) + return; + + while (p!=null) { + register halfword q = vlink(p); + flush_node(p); + p=q; + } +} + +static int test_count = 1; + +#define dorangetest(a,b,c) do { \ + if (!(b>=0 && b 0) + check_token_ref(pdf_dest_id(p)); + break; + case pdf_thread_node: + case pdf_start_thread_node: + if (pdf_thread_named_id(p) > 0 ) check_token_ref(pdf_thread_id(p)); + if (pdf_thread_attr(p) != null) check_token_ref(pdf_thread_attr(p)); + break; + case user_defined_node: + switch( user_node_type(p)) { + case 'a': check_attribute_ref(user_node_value(p)); break; + case 't': check_token_ref(user_node_value(p)); break; + case 'n': dorangetest(p,user_node_value(p),var_mem_max); break; + default: tconfusion("extuser"); break; + } + break; + case dir_node: + case open_node: + case write_node: + case close_node: + case pdf_save_node: + case pdf_restore_node: + case cancel_boundary_node: + case close_lua_node: + case pdf_refobj_node: + case pdf_refxform_node: + case pdf_refximage_node: + case pdf_end_link_node: + case pdf_end_thread_node: + case pdf_save_pos_node: + case local_par_node: + break; + default: + tconfusion("ext3"); + } + break; + case margin_kern_node: + check_node(margin_char(p)); + break; + case disc_node: + dorangetest(p,vlink(pre_break(p)),var_mem_max); + dorangetest(p,vlink(post_break(p)),var_mem_max); + dorangetest(p,vlink(no_break(p)),var_mem_max); + break; + case adjust_node: + dorangetest(p,adjust_ptr(p),var_mem_max); + break; + case pseudo_file_node: + dorangetest(p,pseudo_lines(p),var_mem_max); + break; + case pseudo_line_node: + case shape_node: + break; + case choice_node: + dorangetest(p,display_mlist(p),var_mem_max); + dorangetest(p,text_mlist(p),var_mem_max); + dorangetest(p,script_mlist(p),var_mem_max); + dorangetest(p,script_script_mlist(p),var_mem_max); + break; + case fraction_noad: + dorangetest(p,vinfo(numerator(p)),var_mem_max); + dorangetest(p,vinfo(denominator(p)),var_mem_max); + break; + case rule_node: + case kern_node: + case math_node: + case penalty_node: + case mark_node: + case style_node: + case ord_noad: + case op_noad: + case bin_noad: + case rel_noad: + case open_noad: + case close_noad: + case punct_noad: + case inner_noad: + case radical_noad: + case over_noad: + case under_noad: + case vcenter_noad: + case accent_noad: + case left_noad: + case right_noad: + case attribute_list_node: + case attribute_node: + case glue_spec_node: + case temp_node: + case align_stack_node: + case movement_node: + case if_node: + case nesting_node: + case span_node: + case unhyphenated_node: + case hyphenated_node: + case delta_node: + case passive_node: + case expr_node: + break; + default: + fprintf(stdout,"check_node: type is %d\n", type(p)); + } +} + +void +check_static_node_mem (void) { + dotest(zero_glue,width(zero_glue),0); + dotest(zero_glue,type(zero_glue),glue_spec_node); + dotest(zero_glue,vlink(zero_glue),null); + dotest(zero_glue,stretch(zero_glue),0); + dotest(zero_glue,stretch_order(zero_glue),normal); + dotest(zero_glue,shrink(zero_glue),0); + dotest(zero_glue,shrink_order(zero_glue),normal); + + dotest(sfi_glue,width(sfi_glue),0); + dotest(sfi_glue,type(sfi_glue),glue_spec_node); + dotest(sfi_glue,vlink(sfi_glue),null); + dotest(sfi_glue,stretch(sfi_glue),0); + dotest(sfi_glue,stretch_order(sfi_glue),sfi); + dotest(sfi_glue,shrink(sfi_glue),0); + dotest(sfi_glue,shrink_order(sfi_glue),normal); + + dotest(fil_glue,width(fil_glue),0); + dotest(fil_glue,type(fil_glue),glue_spec_node); + dotest(fil_glue,vlink(fil_glue),null); + dotest(fil_glue,stretch(fil_glue),unity); + dotest(fil_glue,stretch_order(fil_glue),fil); + dotest(fil_glue,shrink(fil_glue),0); + dotest(fil_glue,shrink_order(fil_glue),normal); + + dotest(fill_glue,width(fill_glue),0); + dotest(fill_glue,type(fill_glue),glue_spec_node); + dotest(fill_glue,vlink(fill_glue),null); + dotest(fill_glue,stretch(fill_glue),unity); + dotest(fill_glue,stretch_order(fill_glue),fill); + dotest(fill_glue,shrink(fill_glue),0); + dotest(fill_glue,shrink_order(fill_glue),normal); + + dotest(ss_glue,width(ss_glue),0); + dotest(ss_glue,type(ss_glue),glue_spec_node); + dotest(ss_glue,vlink(ss_glue),null); + dotest(ss_glue,stretch(ss_glue),unity); + dotest(ss_glue,stretch_order(ss_glue),fil); + dotest(ss_glue,shrink(ss_glue),unity); + dotest(ss_glue,shrink_order(ss_glue),fil); + + dotest(fil_neg_glue,width(fil_neg_glue),0); + dotest(fil_neg_glue,type(fil_neg_glue),glue_spec_node); + dotest(fil_neg_glue,vlink(fil_neg_glue),null); + dotest(fil_neg_glue,stretch(fil_neg_glue),-unity); + dotest(fil_neg_glue,stretch_order(fil_neg_glue),fil); + dotest(fil_neg_glue,shrink(fil_neg_glue),0); + dotest(fil_neg_glue,shrink_order(fil_neg_glue),normal); +} + +void +check_node_mem(void ) { + int i; + check_static_node_mem(); + + for (i=(prealloc+1);i0) { + check_node(i); + } + } + test_count++; +} + +void +fix_node_list (halfword head) { + halfword p,q; + if (head==null) + return; + p = head; + q = vlink(p); + while (q!=null) { + alink(q) = p; + p = q; + q = vlink(p); + } +} + +halfword +get_node (integer s) { + register halfword r; + + /*check_static_node_mem();*/ + assert(sx) { + /* todo ? it is perhaps possible to merge the new node with an existing rover */ + vlink (x) = rover; + node_size(x) = (var_mem_max-x); + while(vlink(rover)!=vlink(x)) {rover=vlink(rover);} + vlink (rover) = x; + } +} + +#if 0 +void test_rovers (char *s) { + int q = rover; + int r = q; + fprintf(stdout,"%s: {rover=%d,size=%d,link=%d}",s,r,node_size(r),vlink(r)); + while (vlink(r)!=q) { + r = vlink(r); + fprintf(stdout,",{rover=%d,size=%d,link=%d}",r,node_size(r),vlink(r)); + } + fprintf(stdout,"\n"); +} +#else +#define test_rovers(a) +#endif + +halfword +slow_get_node (integer s) { + register int t; + + RETRY: + t = node_size(rover); + assert(vlink(rover)s) { + register halfword r; + /* allocating from the bottom helps decrease page faults */ + r = rover; + rover += s; + vlink(rover)=vlink(r); + node_size(rover) = node_size(r) - s; + if (vlink(rover)!=r) { /* list is longer than one */ + halfword q = r; + while (vlink(q)!=r) { q=vlink(q);} + vlink(q) += s; + } else { + vlink(rover) += s; + } + test_rovers("taken"); + assert(vlink(rover)127 ? 127 : s); +#endif + vlink(r)=null; + var_used += s; /* maintain usage statistics */ + return r; /* this is the only exit */ + } else { + int x; + /* attempt to keep the free list small */ + if (vlink(rover)!=rover) { + if (ts) { + goto RETRY; + } + rover=vlink(rover); + } + } + } + /* if we are still here, it was apparently impossible to get a match */ + x = (var_mem_max>>2)+s; + varmem = (memory_word *)realloc((void *)varmem,sizeof(memory_word)*(var_mem_max+x)); + if (varmem==NULL) { + overflow_string("node memory size",var_mem_max); + } + memset ((void *)(varmem+var_mem_max),0,x*sizeof(memory_word)); + +#ifndef NDEBUG + varmem_sizes = (char *)realloc(varmem_sizes,sizeof(char)*(var_mem_max+x)); + if (varmem_sizes==NULL) { + overflow_string("node memory size",var_mem_max); + } + memset ((void *)(varmem_sizes+var_mem_max),0,x*sizeof(char)); +#endif + + /* todo ? it is perhaps possible to merge the new memory with an existing rover */ + vlink(var_mem_max) = rover; + node_size(var_mem_max) = x; + while(vlink(rover)!=vlink(var_mem_max)) {rover=vlink(rover);} + vlink (rover) = var_mem_max; + rover = var_mem_max; + test_rovers("realloc"); + var_mem_max += x; + goto RETRY; + } +} + +char * +sprint_node_mem_usage (void) { + int i,b; + + char *s, *ss; + char msg[256]; + int node_counts[last_normal_node+last_whatsit_node+2] = {0}; + + for (i=(var_mem_max-1);i>prealloc;i--) { + if (varmem_sizes[i]>0) { + if (type(i)>last_normal_node+last_whatsit_node) { + node_counts[last_normal_node+last_whatsit_node+1] ++; + } else if (type(i)==whatsit_node){ + node_counts[(subtype(i)+last_normal_node+1)] ++; + } else { + node_counts[type(i)] ++; + } + } + } + s = strdup(""); + b=0; + for (i=0;i0) { + int j = (i>(last_normal_node+1) ? (i-last_normal_node-1) : 0); + snprintf(msg,255,"%s%d %s",(b ? ", " : ""), + (int)node_counts[i], + get_node_name((i>last_normal_node ? whatsit_node : i),j)); + ss = concat(s,msg); + free (s); + s = ss; + b=1; + } + } + return s; +} + +halfword +list_node_mem_usage (void) { + halfword i, j; + halfword p = null,q = null; + char *saved_varmem_sizes = xmallocarray (char, var_mem_max); + memcpy (saved_varmem_sizes,varmem_sizes,var_mem_max); + for (i=prealloc+1;i<(var_mem_max-1);i++) { + if (saved_varmem_sizes[i]>0) { + j = copy_node(i); + if (p==null) { + q = j; + } else { + vlink(p)=j; + } + p = j; + } + } + free(saved_varmem_sizes); + return q; +} + +void +print_node_mem_stats (int num, int online) { + int i,b; + halfword j; + char msg[256]; + char *s; + integer free_chain_counts[MAX_CHAIN_SIZE] = {0}; + + snprintf(msg,255,"node memory in use: %d words out of %d", (int)(var_used+prealloc), (int)var_mem_max); + tprint_nl(msg); + tprint_nl("rapidly available: "); + b=0; + for (i=1;i0) { + snprintf(msg,255,"%s%d:%d",(b ? ", " : ""),i, (int)free_chain_counts[i]); + tprint(msg); + b=1; + } + } + tprint(" nodes"); + s = sprint_node_mem_usage(); + tprint_nl("current usage: "); + tprint(s); free(s); + tprint(" nodes"); + print_nlp(); /* newline, if needed */ +} + +/* this belongs in the web but i couldn't find the correct syntactic place */ + +halfword +new_span_node(halfword n, int s, scaled w) { + halfword p=new_node(span_node,0); + span_link(p)=n; + span_span(p)=s; + width(p)=w; + return p; +} + +halfword +string_to_pseudo(integer l,integer pool_ptr, integer nl) { + halfword i, r, q = null; + four_quarters w; + int sz; + halfword h = new_node(pseudo_file_node,0); + while (l1) { + w.b0=str_pool[m++]; + w.b1=str_pool[m++]; + w.b2=str_pool[m++]; + w.b3=str_pool[m++]; + varmem[++i].qqqq=w; + } + w.b0 = (l>m ? str_pool[m++] : ' '); + w.b1 = (l>m ? str_pool[m++] : ' '); + w.b2 = (l>m ? str_pool[m++] : ' '); + w.b3 = (l>m ? str_pool[m] : ' '); + varmem[++i].qqqq=w; + if (pseudo_lines(h)==null) { + pseudo_lines(h) = r; + q = r; + } else { + couple_nodes(q,r); + } + q = vlink(q); + if (str_pool[l]==nl) l++; + } + return h; +} + +/* attribute stuff */ + +static halfword +new_attribute_node (unsigned int i, int v) { + register halfword r = get_node(attribute_node_size); + type(r) = attribute_node; + attribute_id(r)= i; + attribute_value(r)= v; + return r; +} + +halfword +copy_attribute_list(halfword n) { + halfword q = get_node(attribute_node_size); + register halfword p = q; + type(p) = attribute_list_node; + attr_list_ref(p)=0; + n = vlink(n); + while (n!=null) { + register halfword r = get_node(attribute_node_size); + /* the link will be fixed automatically in the next loop */ + (void)memcpy((void *)(varmem+r),(void *)(varmem+n),(sizeof(memory_word)*attribute_node_size)); + vlink(p) = r; + p = r; + n = vlink(n); + } + return q; +} + +void +update_attribute_cache(void) { + halfword p; + register int i; + attr_list_cache=get_node(attribute_node_size); + type(attr_list_cache) = attribute_list_node; + attr_list_ref(attr_list_cache)=0; + p=attr_list_cache; + for (i=0;i<=max_used_attr;i++) { + register int v = get_attribute(i); + if (v>=0) { + register halfword r = new_attribute_node(i,v); + vlink(p)=r; + p=r; + } + } + if (vlink(attr_list_cache)==null) { + free_node(attr_list_cache,attribute_node_size); + attr_list_cache = null; + } + return; +} + +void +build_attribute_list(halfword b) { + if (max_used_attr>=0) { + if (attr_list_cache==cache_disabled) { + update_attribute_cache(); + if (attr_list_cache == null) + return; + } + attr_list_ref(attr_list_cache)++; + node_attr(b)=attr_list_cache; + } +} + +void +delete_attribute_ref(halfword b) { + if (b!=null){ + assert(type(b)==attribute_list_node); + attr_list_ref(b)--; + if (attr_list_ref(b)==0) { + if (b==attr_list_cache) + attr_list_cache=cache_disabled; + free_node_chain(b,attribute_node_size); + } + /* maintain sanity */ + if (attr_list_ref(b)<0) + attr_list_ref(b)=0; + } +} + +/* |p| is an attr list head, or zero */ + +halfword +do_set_attribute (halfword p, int i, int val) { + register halfword q; + register int j = 0; + if (p==null) { /* add a new head & node */ + q = get_node(attribute_node_size); + type(q) = attribute_list_node; + attr_list_ref(q)=1; + p = new_attribute_node(i,val); + vlink(q)=p; + return q; + } + + assert(vlink(p)!=null); + while (vlink(p)!=null) { + int t = attribute_id(vlink(p)); + if (t==i && attribute_value(vlink(p))==val) + return q; /* no need to do anything */ + if (t>=i) + break; + j++; + p = vlink(p); + } + + p = q; + while (j-->0) p = vlink(p); + if (attribute_id(vlink(p))==i) { + attribute_value(vlink(p))=val; + } else { /* add a new node */ + halfword r = new_attribute_node(i,val); + vlink(r)=vlink(p); + vlink(p)=r; + } + return q; +} + +void +set_attribute (halfword n, int i, int val) { + register halfword p; + register int j = 0; + if (!nodetype_has_attributes(type(n))) + return; + p = node_attr(n); + if (p==null) { /* add a new head & node */ + p = get_node(attribute_node_size); + type(p) = attribute_list_node; + attr_list_ref(p)=1; + node_attr(n) = p ; + p = new_attribute_node(i,val); + vlink(node_attr(n))=p; + return; + } + assert(vlink(p)!=null); + while (vlink(p)!=null) { + int t = attribute_id(vlink(p)); + if (t==i && attribute_value(vlink(p))==val) + return; + if (t>=i) + break; + j++; + p = vlink(p); + } + p = node_attr(n); + if (attr_list_ref(p)!=1) { + if (attr_list_ref(p)>1) { + p = copy_attribute_list (p); + delete_attribute_ref(node_attr(n)); + node_attr(n) = p; + } else { + fprintf(stdout,"Node %d has an attribute list that is free already\n",(int)n); + } + attr_list_ref(p)=1; + } + while (j-->0) p = vlink(p); + + if (attribute_id(vlink(p))==i) { + attribute_value(vlink(p))=val; + } else { /* add a new node */ + halfword r = new_attribute_node(i,val); + vlink(r)=vlink(p); + vlink(p)=r; + } + return; +} + + +int +unset_attribute (halfword n, int i, int val) { + register halfword p; + register int t; + register int j = 0; + + if (!nodetype_has_attributes(type(n))) + return null; + p = node_attr(n); + if (p==null) + return -1; + assert (vlink(p)!=null); + while (vlink(p)!=null) { + t = attribute_id(vlink(p)); + if (t>i) + return -1; + if (t==i) + break; + j++; + p = vlink(p); + } + /* if we are still here, the attribute exists */ + p = node_attr(n); + if (attr_list_ref(p)!=1) { + if (attr_list_ref(p)>1) { + p = copy_attribute_list (p); + delete_attribute_ref(node_attr(n)); + node_attr(n) = p; + } else { + fprintf(stdout,"Node %d has an attribute list that is free already\n",(int)n); + } + attr_list_ref(p)=1; + } + p = vlink(p); + while (j-->0) p = vlink(p); + t = attribute_value(p); + if (val==-1 || t==val) { + attribute_value(p)=-1; + } + return t; +} + +int +has_attribute (halfword n,int i, int val) { + register halfword p; + if (!nodetype_has_attributes(type(n))) + return -1; + p = node_attr(n); + if (p==null || vlink(p)==null) + return -1; + p = vlink(p); + while (p!=null) { + if (attribute_id(p)==i) { + int ret = attribute_value(p); + if (val==-1 || val==ret) + return ret; + return -1; + } else if (attribute_id(p)>i) { + return -1; + } + p=vlink(p); + } + return -1; +} + -- cgit v1.2.3