|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T b
Length: 6350 (0x18ce)
Types: TextFile
Names: »binding.h«
└─⟦060c9c824⟧ Bits:30007080 DKUUG TeX 2/12/89
└─⟦this⟧ »./DVIware/laser-setters/umd-dvi/h/binding.h«
/* 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; \
}