diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /dviware/umddvi/h/binding.h |
Initial commit
Diffstat (limited to 'dviware/umddvi/h/binding.h')
-rw-r--r-- | dviware/umddvi/h/binding.h | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/dviware/umddvi/h/binding.h b/dviware/umddvi/h/binding.h new file mode 100644 index 0000000000..330ff2c170 --- /dev/null +++ b/dviware/umddvi/h/binding.h @@ -0,0 +1,194 @@ +/* C-TeX function and variable bindings */ + +/* + * Copyright (c) 1987 University of Maryland Department of Computer Science. + * All rights reserved. Permission to copy for any purpose is hereby granted + * so long as this copyright notice remains intact. + */ + +#ifdef StringSizeof +/* + * If StringSizeof is defined, we assume that (sizeof "string_const") is + * equal to (strlen("string_const") + 1); see the DefXXX macros below. + */ +#endif + +/* + * Here are the various flags that can be in the b_flags field of a struct + * BoundName. + */ +#define BIsSpecial 1 /* a special int or dimen, or a font; + assignments to these are always + global */ +#define BIsOuter 2 /* \outer, may not appear in macro def'n */ +#define BIsLong 4 /* \long, may contain \outer s anyway */ +#define BIsUndef 8 /* not defined anymore - used when a def'n + local to a group is destroyed by exiting + the group */ + +/* + * SPECIAL + * 1. Integers: + * \spacefactor \prevgraf \deadcycles \insertpenalties + * 2. Dimens: + * \prevdepth \pagegoal \pagetotal \pagestretch \pagefilstretch + * \pagefillstretch \pagefilllstretch \pageshrink \pagedepth + */ + +enum BindingKind { + ProcBound, VarBound, IntBound, DimenBound, CodeBound, + FontBound +}; + +union BindUnion { + int (*b_proc)(); /* iff ProcBound */ + struct node *b_var; /* iff VarBound */ + i32 *b_int; /* iff IntBound */ + scaled *b_dimen; /* iff DimenBound */ + i32 b_code; /* iff CodeBound */ + struct FontInfo *b_font; /* iff FontBound */ +}; + +/* + * The basic entity of C-TeX is the `BoundName'. It is either a wired-in + * procedure (e.g. \let, \def, \vskip) or variable (\hsize, \parskip), or a + * user-defined macro/variable/whatnot. These are indistinguishable from + * one another (except that only wired procedures are ProcBound). + * + * There are also `CodeBound' things, which have no b_name and no b_flags. + * In fact, they are really BoundNameCodes, but they need similar treatment, + * so they get a similar structure. + */ +struct BoundName { + enum BindingKind b_binding; /* the kind of thing it is */ + union BindUnion b_bound; /* the current binding */ + struct SavedVal *b_AfterGroupRst; + /* The saved value for restoration + after the current group. This + is a pointer into the current + AfterGroupRst list. */ + struct string b_name; /* the name of this thing */ + int b_flags; /* various flags */ +}; + +/* + * \catcodes, \lccodes, etc are CodeBound, and are really arrays of these: + */ +struct BoundNameCode { + enum BindingKind b_binding; + union BindUnion b_bound; + struct SavedVal *b_AfterGroupRst; +}; + +/* + * Saved values (changes that are local to a group) are stored in a doubly + * linked list; this is so that constructs like + * {\advance\count0 by1 \global\advance\count0 by1} + * can easily delete restorations that are no longer needed (having been + * overridden by a \global operation). In other words, we never have + * any `save stack buildup'. This requires the `spaghetti' below: a + * current group level (so if b_AfterGroupRst is set, we can tell whether + * the saved val is for this level) and moreover any inner saves for this + * BoundName. + * + * To illustrate what is going on, suppose that we have count1==0. Now we + * begin group number 1, then 2. Now we set count1 to 5, and since it has + * no AfterGroupRst we save the 0 at level 2. Now we increment count1, and + * since it has an AfterGroupRst, we check the level. It is 2; everything + * is fine, and count1 is set to 6. Now we begin group 3, and again increment + * count1. The level is 2, so we make a new SavedVal and set its level to + * 3. (We now have count1==7, save==6 when exiting level 3, save==0 when + * exiting 2.) Now the user does a \global\count1=42, so alas!, all those + * saved values are useless. To get rid of them, we delete the current + * SavedVal, and its inner, and its inner's inner, and so forth, then clear + * the AfterGroupRst pointer. Voila! A global \count1, set to 42. + * + * Note that we save CodeBound changes here too. Since CodeBound objects + * have no flags, some care is needed during restoration. + */ +struct SavedVal { + int sv_level; /* the level to which this belongs */ + struct SavedVal *sv_next; /* linked list */ + struct SavedVal *sv_prev; /* or more precisely, queue */ + struct SavedVal *sv_inner; /* the inner saved value (from the + previous group that saved this) */ + union BindUnion sv_val; /* the saved value (note that saved + values are always the same type + as current values---i.e., types + are fixed) */ + struct BoundName *sv_b; /* the BoundName to which it belongs */ + int sv_flags; /* the saved b_flags (if applicable) */ +}; + +struct BoundName **NewNames; /* during initialization, each internal + BoundName is stashed in the table to + which this points */ + +int CurrentGroup; /* the group level number of the current + group; incremented for { and decremented + for }, etc */ + +struct SavedVal *AfterGroupRst;/* the current list for restoring locally + modified BoundNames */ + +/* + * The following hackery will make the compiler complain in the event + * of a dropped semicolon, without making lint complain. + */ +#ifdef lint +#define do_nothing (void) rand() +#else +#define do_nothing 0 +#endif + +/* + * Save a binding. + */ +#define SaveB(b) \ + if ((b)->b_AfterGroupRst == NULL || \ + (b)->b_AfterGroupRst->sv_level != CurrentGroup) \ + DoSave(b); \ + else \ + do_nothing + +/* + * Undo a save. + */ +#define UnSaveB(b) \ + if ((b)->b_AfterGroupRst) \ + DoUnsave(b); \ + else \ + do_nothing + +#ifdef StringSizeof +#define InitStrAndLen(str,cstr) (str.s_len = sizeof cstr-1, str.s_str = cstr) +#else +#define InitStrAndLen(str,cstr) (str.s_len = strlen(str.s_str = cstr)) +#endif + +#define SetBFlags(f) NewNames[-1].b_flags |= (f) + +#define DefIntVar(addr, name) { \ + static struct BoundName _b; \ + InitStrAndLen(_b.b_name, name); \ + _b.b_binding = IntBound; \ + _b.b_bound.b_int = addr; \ + *NewNames++ = &_b; \ +} + +#define DefDimenVar(addr, name) { \ + static struct BoundName _b; \ + InitStrAndLen(_b.b_name, name); \ + _b.b_binding = DimenBound; \ + _b.b_bound.b_dimen = addr; \ + *NewNames++ = &_b; \ +} + +#define DefProc(name, proc, flags) { \ + static struct BoundName _b; \ + InitStrAndLen(_b.b_name, name); \ + _b.b_binding = ProcBound; \ + _b.b_bound.b_proc = proc; \ + _b.b_bound.b_flags = flags; \ + *NewNames++ = &_b; \ +} |