-
Notifications
You must be signed in to change notification settings - Fork 12
/
roff.h
536 lines (493 loc) · 19.3 KB
/
roff.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
/*
* Most functions and variables in neatroff are prefixed with tokens
* that indicate their purpose, such as:
*
* + tr_xyz: the implementation of troff request .xyz (mostly tr.c)
* + in_xyz: input layer (in.c)
* + cp_xyz: copy-mode interpretation layer (cp.c)
* + ren_xyz: rendering characters into lines (ren.c)
* + out_xyz: output layer for generating troff output (out.c)
* + dev_xyz: output devices (dev.c)
* + num_xyz: number registers (reg.c)
* + str_xyz: string registers (reg.c)
* + env_xyz: environments (reg.c)
* + eval_xyz: integer expression evaluation (eval.c)
* + font_xyz: fonts (font.c)
* + sbuf_xyz: variable length string buffers (sbuf.c)
* + dict_xyz: dictionaries (dict.c)
* + wb_xyz: word buffers (wb.c)
* + fmt_xyz: line formatting buffers (fmt.c)
* + n_xyz: builtin number register xyz
* + c_xyz: characters for requests like hc and mc
*
*/
/* predefined array limits */
#define PATHLEN 1024 /* path length */
#define NFILES 16 /* number of input files */
#define NFONTS 32 /* number of fonts */
#define FNLEN 32 /* font name length */
#define GNLEN 32 /* glyph name length */
#define GNFMT "%31s" /* glyph name scanf format */
#define NMLEN 128 /* macro/register/environment name length */
#define RNLEN NMLEN /* register/macro name */
#define NREGS 8192 /* number of mapped names */
#define NARGS 32 /* number of macro arguments */
#define NPREV 16 /* environment stack depth */
#define NTRAPS 1024 /* number of traps per page */
#define NIES 128 /* number of nested .ie commands */
#define NTABS 32 /* number of tab stops */
#define NCMAPS 512 /* number of character translations (.tr) */
#define NSSTR 32 /* number of nested sstr_push() calls */
#define NFIELDS 32 /* number of fields */
#define NCHARS 32 /* number of characters for .eos, .hydash, .hystop */
#define MAXFRAC 100000 /* maximum value of the fractional part */
#define NCDEFS 128 /* number of character definitions (.char) */
#define NHYPHS 16384 /* hyphenation dictionary/patterns (.hw) */
#define NHYPHSWORD 32 /* number of hyphenations per word */
#define NHCODES 512 /* number of .hcode characters */
#define WORDLEN 256 /* word length (for hyph.c) */
#define NFEATS 128 /* number of features per font */
#define NSCRPS 64 /* number of scripts per font */
#define NLANGS 64 /* number of languages per font */
/* converting scales */
#define SC_IN (dev_res) /* inch in units */
#define SC_PT (SC_IN / 72) /* point in units */
#define SC_EM (n_s * SC_IN / 72)
/* escape sequences */
#define ESC_Q "bCDhHjlLNoRSvwxXZ?" /* \X'ccc' quoted escape sequences */
#define ESC_P "*fgkmns" /* \Xc \X(cc \X[ccc] escape sequences */
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) < (b) ? (b) : (a))
#define LEN(a) (sizeof(a) / sizeof((a)[0]))
/* special characters */
extern int c_ec; /* escape character (\) */
extern int c_cc; /* basic control character (.) */
extern int c_c2; /* no-break control character (') */
extern char c_pc[]; /* page number character (%) */
#define c_ni 4 /* non-interpreted copy-mode escape */
#define c_hc env_hc()/* hyphenation character */
#define c_mc env_mc()/* margin character (.mc) */
#define c_tc env_tc()
#define c_lc env_lc()
#define c_bp "\\:" /* zero-width word break point */
#define c_nb "\\~" /* stretchable no-break space */
/* number registers */
#define num_get(id) (*nreg(id))
void num_set(int id, int val);
void num_inc(int id, int pos);
void num_del(int id);
char *num_str(int id);
char *num_getfmt(int id);
void num_setfmt(int id, char *fmt);
void num_setinc(int id, int val);
int *nreg(int id);
int eval(char *s, int unit);
int eval_up(char **s, int unit);
int eval_re(char *s, int orig, int unit);
/* string registers */
void str_set(int id, char *s);
void str_dset(int id, void *d);
char *str_get(int id);
void *str_dget(int id);
void str_rm(int id);
void str_rn(int src, int dst);
/* saving and restoring registers before and after printing diverted lines */
void odiv_beg(void);
void odiv_end(void);
/* enviroments */
void env_init(void);
void env_done(void);
struct fmt *env_fmt(void);
struct wb *env_wb(void);
char *env_hc(void);
char *env_mc(void);
char *env_tc(void);
char *env_lc(void);
int tab_next(int pos);
int tab_type(int pos);
/* mapping integers to sets */
struct iset *iset_make(void);
void iset_free(struct iset *iset);
int *iset_get(struct iset *iset, int key);
void iset_put(struct iset *iset, int key, int ent);
int iset_len(struct iset *iset, int key);
int iset_has(struct iset *iset, int key, int ent);
/* mapping strings to longs */
struct dict *dict_make(int notfound, int dupkeys, int hashlen);
void dict_free(struct dict *d);
void dict_put(struct dict *d, char *key, int val);
int dict_get(struct dict *d, char *key);
int dict_idx(struct dict *d, char *key);
char *dict_key(struct dict *d, int idx);
int dict_val(struct dict *d, int idx);
int dict_prefix(struct dict *d, char *key, int *idx);
/* device related variables */
extern int dev_res;
extern int dev_uwid;
extern int dev_hor;
extern int dev_ver;
struct glyph {
char id[GNLEN]; /* device-dependent glyph identifier */
char name[GNLEN]; /* the first character mapped to this glyph */
struct font *font; /* glyph font */
short wid; /* character width */
short llx, lly, urx, ury; /* character bounding box */
short type; /* character type; ascender/descender */
};
/* output device functions */
int dev_open(char *dir, char *dev);
void dev_close(void);
int dev_mnt(int pos, char *id, char *name);
int dev_pos(char *id);
struct font *dev_font(int pos);
int dev_fontpos(struct font *fn);
struct glyph *dev_glyph(char *c, int fn);
/* font-related functions */
struct font *font_open(char *path);
void font_close(struct font *fn);
struct glyph *font_glyph(struct font *fn, char *id);
struct glyph *font_find(struct font *fn, char *name);
int font_map(struct font *fn, char *name, char *id);
int font_mapped(struct font *fn, char *name);
int font_special(struct font *fn);
int font_wid(struct font *fn, int sz, int w);
int font_gwid(struct font *fn, struct font *cfn, int sz, int w);
int font_swid(struct font *fn, int sz, int ss);
void font_setcs(struct font *fn, int cs, int ps);
int font_getcs(struct font *fn);
void font_setbd(struct font *fn, int bd);
int font_getbd(struct font *fn);
void font_track(struct font *fn, int s1, int n1, int s2, int n2);
void font_setzoom(struct font *fn, int zoom);
int font_zoom(struct font *fn, int sz);
int font_feat(struct font *fn, char *name, int val);
void font_scrp(struct font *fn, char *name);
void font_lang(struct font *fn, char *name);
int font_layout(struct font *fn, struct glyph **src, int nsrc, int sz,
struct glyph **dst, int *dmap,
int *x, int *y, int *xadv, int *yadv, int lg, int kn);
/* different layers of neatroff */
int in_next(void); /* input layer */
int cp_next(void); /* copy-mode layer */
int tr_next(void); /* troff layer */
void in_push(char *s, char **args);
void in_so(char *path); /* .so request */
void in_nx(char *path); /* .nx request */
void in_ex(void); /* .ex request */
void in_lf(char *path, int ln); /* .lf request */
void in_queue(char *path); /* queue the given input file */
char *in_arg(int i); /* look up argument */
int in_nargs(void); /* number of arguments */
void in_shift(void); /* shift the arguments */
void in_back(int c); /* push back input character */
int in_top(void); /* the first pushed-back character */
char *in_filename(void); /* current filename */
int in_lnum(void); /* current line number */
void cp_blk(int skip); /* skip or read the next line or block */
void cp_reqbeg(void); /* beginning of a request line */
void cp_copymode(int mode); /* do not interpret \w and \E */
#define cp_back in_back /* cp.c is stateless */
int tr_nextreq(void); /* read the next troff request */
void tr_req(int reg, char **args); /* execute a built-in troff request */
/* variable length string buffer */
struct sbuf {
char *s; /* allocated buffer */
int sz; /* buffer size */
int n; /* length of the string stored in s */
};
void sbuf_init(struct sbuf *sbuf);
void sbuf_done(struct sbuf *sbuf);
char *sbuf_out(struct sbuf *sbuf);
char *sbuf_buf(struct sbuf *sbuf);
void sbuf_add(struct sbuf *sbuf, int c);
void sbuf_append(struct sbuf *sbuf, char *s);
void sbuf_printf(struct sbuf *sbuf, char *s, ...);
void sbuf_cut(struct sbuf *sbuf, int n);
int sbuf_len(struct sbuf *sbuf);
int sbuf_empty(struct sbuf *sbuf);
/* word buffer */
struct wb {
struct sbuf sbuf;
int f, s, m, cd; /* the last output font and size */
int r_f, r_s, r_m, r_cd;/* current font and size; use n_f and n_s if -1 */
int part; /* partial input (\c) */
int cost; /* the extra cost of line break after this word */
int els_neg, els_pos; /* extra line spacing */
int h, v; /* buffer vertical and horizontal positions */
int ct, sb, st; /* \w registers */
int llx, lly, urx, ury; /* bounding box */
int icleft; /* pending left italic correction */
/* queued subword */
char sub_c[WORDLEN][GNLEN]; /* the collected subword */
int sub_n; /* collected subword length */
int sub_collect; /* enable subword collection */
};
void wb_init(struct wb *wb);
void wb_done(struct wb *wb);
void wb_hmov(struct wb *wb, int n);
void wb_vmov(struct wb *wb, int n);
void wb_els(struct wb *wb, int els);
void wb_etc(struct wb *wb, char *x);
void wb_put(struct wb *wb, char *c);
void wb_putraw(struct wb *wb, char *c);
void wb_putexpand(struct wb *wb, char *c);
int wb_part(struct wb *wb);
void wb_setpart(struct wb *wb);
int wb_cost(struct wb *wb);
void wb_setcost(struct wb *wb, int cost);
void wb_drawl(struct wb *wb, int c, int h, int v);
void wb_drawc(struct wb *wb, int c, int r);
void wb_drawe(struct wb *wb, int c, int h, int v);
void wb_drawa(struct wb *wb, int c, int h1, int v1, int h2, int v2);
void wb_drawxbeg(struct wb *wb, int c);
void wb_drawxdot(struct wb *wb, int h, int v);
void wb_drawxcmd(struct wb *wb, char *cmd);
void wb_drawxend(struct wb *wb);
void wb_italiccorrection(struct wb *wb);
void wb_italiccorrectionleft(struct wb *wb);
void wb_cat(struct wb *wb, struct wb *src);
void wb_catstr(struct wb *wb, char *beg, char *end);
int wb_wid(struct wb *wb);
int wb_hpos(struct wb *wb);
int wb_vpos(struct wb *wb);
int wb_empty(struct wb *wb);
int wb_eos(struct wb *wb);
void wb_wconf(struct wb *wb, int *ct, int *st, int *sb,
int *llx, int *lly, int *urx, int *ury);
void wb_reset(struct wb *wb);
char *wb_buf(struct wb *wb);
void wb_fnszget(struct wb *wb, int *fn, int *sz, int *m, int *cd);
void wb_fnszset(struct wb *wb, int fn, int sz, int m, int cd);
void wb_flushdir(struct wb *wb);
void wb_reset(struct wb *wb);
int wb_keshideh(char *word, struct wb *dst, int wid);
int wb_hywid(struct wb *wb);
int wb_swid(struct wb *wb);
int c_eossent(char *s);
int c_eostran(char *s);
int c_hydash(char *s);
int c_hystop(char *s);
int c_hymark(char *s);
/* character translation (.tr) */
void cmap_add(char *c1, char *c2);
char *cmap_map(char *c);
/* character definition (.char) */
char *cdef_map(char *c, int fn);
int cdef_expand(struct wb *wb, char *c, int fn);
/* hyphenation flags */
#define HY_LAST 0x02 /* do not hyphenate last lines */
#define HY_FINAL2 0x04 /* do not hyphenate the final two characters */
#define HY_FIRST2 0x08 /* do not hyphenate the first two characters */
void hyphenate(char *hyphs, char *word, int flg);
int hy_cput(char *d, char *s);
void hyph_init(void);
void hyph_done(void);
/* adjustment types */
#define AD_C 0 /* center */
#define AD_L 1 /* adjust left margin (flag) */
#define AD_R 2 /* adjust right margin (flag) */
#define AD_B 3 /* adjust both margin (mask) */
#define AD_P 4 /* paragraph-at-once adjustment (flag) */
#define AD_K 8 /* keshideh adjustment (flag) */
/* line formatting */
struct fmt *fmt_alloc(void);
void fmt_free(struct fmt *fmt);
int fmt_wid(struct fmt *fmt);
void fmt_space(struct fmt *fmt);
void fmt_suppressnl(struct fmt *fmt);
int fmt_word(struct fmt *fmt, struct wb *wb);
int fmt_newline(struct fmt *fmt);
int fmt_fillreq(struct fmt *f);
int fmt_fill(struct fmt *fmt, int br);
int fmt_morelines(struct fmt *fmt);
int fmt_morewords(struct fmt *fmt);
char *fmt_nextline(struct fmt *fmt, int *w,
int *li, int *lI, int *ll, int *els_neg, int *els_pos);
/* rendering */
int render(void); /* the main loop */
int ren_parse(struct wb *wb, char *c);
int ren_char(struct wb *wb, int (*next)(void), void (*back)(int));
int ren_wid(int (*next)(void), void (*back)(int));
void ren_tl(int (*next)(void), void (*back)(int));
void ren_hline(struct wb *wb, int l, char *c); /* horizontal line */
void ren_hlcmd(struct wb *wb, char *arg); /* \l */
void ren_vlcmd(struct wb *wb, char *arg); /* \L */
void ren_bcmd(struct wb *wb, char *arg); /* \b */
void ren_ocmd(struct wb *wb, char *arg); /* \o */
void ren_dcmd(struct wb *wb, char *arg); /* \D */
void ren_zcmd(struct wb *wb, char *arg); /* \Z */
/* out.c */
void out_line(char *s); /* output rendered line */
void out_x(char *s); /* output \X requests */
void out(char *s, ...); /* output troff cmd */
/* troff commands */
void tr_ab(char **args);
void tr_bp(char **args);
void tr_br(char **args);
void tr_ce(char **args);
void tr_ch(char **args);
void tr_cl(char **args);
void tr_di(char **args);
void tr_divbeg(char **args);
void tr_divend(char **args);
void tr_divvs(char **args);
void tr_dt(char **args);
void tr_em(char **args);
void tr_ev(char **args);
void tr_fc(char **args);
void tr_fi(char **args);
void tr_fp(char **args);
void tr_fspecial(char **args);
void tr_ft(char **args);
void tr_hcode(char **args);
void tr_hpf(char **args);
void tr_hpfa(char **args);
void tr_hw(char **args);
void tr_in(char **args);
void tr_ll(char **args);
void tr_mk(char **args);
void tr_ne(char **args);
void tr_nf(char **args);
void tr_ns(char **args);
void tr_os(char **args);
void tr_pn(char **args);
void tr_ps(char **args);
void tr_rs(char **args);
void tr_rt(char **args);
void tr_sp(char **args);
void tr_sv(char **args);
void tr_ta(char **args);
void tr_ti(char **args);
void tr_wh(char **args);
void tr_popren(char **args);
void tr_transparent(char **args);
void tr_in2(char **args);
void tr_ti2(char **args);
void tr_l2r(char **args);
void tr_r2l(char **args);
void tr_init(void);
void tr_done(void);
char *tr_args(char **args, int brk, int (*next)(void), void (*back)(int));
/* helpers */
void errmsg(char *msg, ...);
void errdie(char *msg);
void *xmalloc(long len);
void *mextend(void *old, long oldsz, long newsz, int memsz);
/* utf-8 parsing */
int utf8len(int c);
int utf8next(char *s, int (*next)(void));
int utf8read(char **s, char *d);
int utf8one(char *s);
/* reading escapes and characters */
int charnext(char *c, int (*next)(void), void (*back)(int));
int charread(char **s, char *c);
int charnext_delim(char *c, int (*next)(void), void (*back)(int), char *delim);
int charread_delim(char **s, char *c, char *delim);
void charnext_str(char *d, char *c);
char *quotednext(int (*next)(void), void (*back)(int));
char *unquotednext(int cmd, int (*next)(void), void (*back)(int));
int escread(char **s, char **d);
/* string streams; nested next()/back() interface for string buffers */
void sstr_push(char *s);
char *sstr_pop(void);
int sstr_next(void);
void sstr_back(int c);
/* internal commands */
#define TR_DIVBEG "\07<" /* diversion begins */
#define TR_DIVEND "\07>" /* diversion ends */
#define TR_DIVVS "\07V" /* the amount of \n(.v inside diversions */
#define TR_POPREN "\07P" /* exit render_rec() */
/* mapping register, macro and environment names to indices */
#define DOTMAP(c2) (c2) /* optimized mapping for ".x" names */
int map(char *s); /* map name s to an index */
char *map_name(int id); /* return the name mapped to id */
void map_done(void);
/* text direction */
extern int dir_do;
void dir_fix(struct sbuf *sbuf, char *s);
void dir_done(void);
/* colors */
#define CLR_R(c) (((c) >> 16) & 0xff)
#define CLR_G(c) (((c) >> 8) & 0xff)
#define CLR_B(c) ((c) & 0xff)
#define CLR_RGB(r, g, b) (((r) << 16) | ((g) << 8) | (b))
char *clr_str(int c);
int clr_get(char *s);
/* builtin number registers; n_X for .X register */
#define n_a (*nreg(DOTMAP('a')))
#define n_cp (*nreg(DOTMAP('C')))
#define n_d (*nreg(DOTMAP('d')))
#define n_f (*nreg(DOTMAP('f')))
#define n_h (*nreg(DOTMAP('h')))
#define n_i (*nreg(DOTMAP('i')))
#define n_it (*nreg(map(".it"))) /* .it trap macro */
#define n_itn (*nreg(map(".itn"))) /* .it lines left */
#define n_I (*nreg(DOTMAP('I'))) /* base indent */
#define n_j (*nreg(DOTMAP('j')))
#define n_l (*nreg(DOTMAP('l')))
#define n_L (*nreg(DOTMAP('L')))
#define n_lsn (*nreg(map("lsn"))) /* for .lsm */
#define n_n (*nreg(DOTMAP('n')))
#define n_nI (*nreg(map(".nI"))) /* i for .nm */
#define n_nm (*nreg(map(".nm"))) /* .nm enabled */
#define n_nM (*nreg(map(".nM"))) /* m for .nm */
#define n_nn (*nreg(map(".nn"))) /* remaining .nn */
#define n_nS (*nreg(map(".nS"))) /* s for .nm */
#define n_m (*nreg(DOTMAP('m')))
#define n_mc (*nreg(map(".mc"))) /* .mc enabled */
#define n_mcn (*nreg(map(".mcn"))) /* .mc distance */
#define n_o (*nreg(DOTMAP('o')))
#define n_p (*nreg(DOTMAP('p')))
#define n_s (*nreg(DOTMAP('s')))
#define n_u (*nreg(DOTMAP('u')))
#define n_v (*nreg(DOTMAP('v')))
#define n_ct (*nreg(map("ct")))
#define n_td (*nreg(map(".td"))) /* text direction */
#define n_cd (*nreg(map(".cd"))) /* current direction */
#define n_dl (*nreg(map("dl")))
#define n_dn (*nreg(map("dn")))
#define n_ln (*nreg(map("ln")))
#define n_nl (*nreg(map("nl")))
#define n_sb (*nreg(map("sb")))
#define n_st (*nreg(map("st")))
#define n_pg (*nreg(map("%"))) /* % */
#define n_PG (*nreg(DOTMAP('%'))) /* number of ejected pages */
#define n_lb (*nreg(map(".b0"))) /* input line beg */
#define n_ce (*nreg(map(".ce"))) /* .ce remaining */
#define n_f0 (*nreg(map(".f0"))) /* last .f */
#define n_lg (*nreg(map(".lg"))) /* .lg mode */
#define n_hy (*nreg(map(".hy"))) /* .hy mode */
#define n_hycost (*nreg(map(".hycost"))) /* hyphenation cost */
#define n_hycost2 (*nreg(map(".hycost2"))) /* hyphenation cost #2 */
#define n_hycost3 (*nreg(map(".hycost3"))) /* hyphenation cost #3 */
#define n_hlm (*nreg(map(".hlm"))) /* .hlm */
#define n_i0 (*nreg(map(".i0"))) /* last .i */
#define n_ti (*nreg(map(".ti"))) /* pending .ti */
#define n_kn (*nreg(map(".kn"))) /* .kn mode */
#define n_tI (*nreg(map(".tI"))) /* pending .ti2 */
#define n_I0 (*nreg(map(".I0"))) /* last .I */
#define n_l0 (*nreg(map(".l0"))) /* last .l */
#define n_L0 (*nreg(map(".L0"))) /* last .L */
#define n_m0 (*nreg(map(".m0"))) /* last .m */
#define n_mk (*nreg(map(".mk"))) /* .mk internal register */
#define n_na (*nreg(map(".na"))) /* .na mode */
#define n_ns (*nreg(map(".ns"))) /* .ns mode */
#define n_o0 (*nreg(map(".o0"))) /* last .o */
#define n_pmll (*nreg(map(".pmll"))) /* minimum line length (.pmll) */
#define n_pmllcost (*nreg(map(".pmllcost"))) /* short line cost */
#define n_ss (*nreg(map(".ss"))) /* word space (.ss) */
#define n_sss (*nreg(map(".sss"))) /* sentence space (.ss) */
#define n_ssh (*nreg(map(".ssh"))) /* word space compression (.ssh) */
#define n_s0 (*nreg(map(".s0"))) /* last .s */
#define n_sv (*nreg(map(".sv"))) /* .sv value */
#define n_lt (*nreg(map(".lt"))) /* .lt value */
#define n_t0 (*nreg(map(".lt0"))) /* previous .lt value */
#define n_v0 (*nreg(map(".v0"))) /* last .v */
#define n_llx (*nreg(map("bbllx"))) /* \w bounding box */
#define n_lly (*nreg(map("bblly"))) /* \w bounding box */
#define n_urx (*nreg(map("bburx"))) /* \w bounding box */
#define n_ury (*nreg(map("bbury"))) /* \w bounding box */
/* functions for implementing read-only registers */
int f_nexttrap(void); /* .t */
int f_divreg(void); /* .z */
int f_hpos(void); /* .k */