From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from krisdoz.my.domain (kristaps@localhost [127.0.0.1]) by krisdoz.my.domain (8.14.3/8.14.3) with ESMTP id o5987Dl3000415 for ; Wed, 9 Jun 2010 04:07:14 -0400 (EDT) Received: (from kristaps@localhost) by krisdoz.my.domain (8.14.3/8.14.3/Submit) id o5987DPx015702; Wed, 9 Jun 2010 04:07:13 -0400 (EDT) Date: Wed, 9 Jun 2010 04:07:13 -0400 (EDT) Message-Id: <201006090807.o5987DPx015702@krisdoz.my.domain> X-Mailinglist: mdocml-source Reply-To: source@mdocml.bsd.lv MIME-Version: 1.0 From: kristaps@mdocml.bsd.lv To: source@mdocml.bsd.lv Subject: mdocml: Have the standard manpage header and footer print on every page X-Mailer: activitymail 1.26, http://search.cpan.org/dist/activitymail/ Content-Type: text/plain; charset=utf-8 Log Message: ----------- Have the standard manpage header and footer print on every page of -Tps output. This is more tricky than you may think: we can't just call the header function out-of-state (i.e., before a flushln has occured) because we'd clobber our current state. Thus, we call at the beginning and dump the output into an auxiliary buffer. For the record, I don't think there's any other clean way to do this. The only other Way That Works is to copy-aside *all* termp state, zero it, and do the necessary headf/footf. This is just as complex, as memory needs to be alloc'd and free'd per margin. Unfortunately, this prohibits page numbering (the margin is only printed once), so I'll probably end up re-writing this down the line. Modified Files: -------------- mdocml: man_term.c mdoc_term.c term.h term_ascii.c term_ps.c Revision Data ------------- Index: term.h =================================================================== RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/term.h,v retrieving revision 1.60 retrieving revision 1.61 diff -Lterm.h -Lterm.h -u -p -r1.60 -r1.61 --- term.h +++ term.h @@ -41,12 +41,15 @@ enum termfont { typedef void (*term_margin)(struct termp *, const void *); struct termp_ps { - int psstate; /* -Tps: state of ps output */ -#define PS_INLINE (1 << 0) -#define PS_MARGINS (1 << 1) - size_t pscol; /* -Tps: visible column */ - size_t psrow; /* -Tps: visible row */ - size_t pspage; /* -Tps: current page */ + int psstate; /* state of ps output */ +#define PS_INLINE (1 << 0) /* we're in a word */ +#define PS_MARGINS (1 << 1) /* we're in the margins */ + size_t pscol; /* visible column */ + size_t psrow; /* visible row */ + char *psmarg; /* margin buf */ + size_t psmargsz; /* margin buf size */ + size_t psmargcur; /* current pos in margin buf */ + size_t pspage; /* current page */ }; struct termp { Index: man_term.c =================================================================== RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/man_term.c,v retrieving revision 1.73 retrieving revision 1.74 diff -Lman_term.c -Lman_term.c -u -p -r1.73 -r1.74 --- man_term.c +++ man_term.c @@ -73,9 +73,9 @@ struct termact { static int a2width(const struct man_node *); static int a2height(const struct man_node *); -static void print_man_head(struct termp *, const void *); static void print_man_nodelist(DECL_ARGS); static void print_man_node(DECL_ARGS); +static void print_man_head(struct termp *, const void *); static void print_man_foot(struct termp *, const void *); static void print_bvspace(struct termp *, const struct man_node *); Index: term_ascii.c =================================================================== RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/term_ascii.c,v retrieving revision 1.2 retrieving revision 1.3 diff -Lterm_ascii.c -Lterm_ascii.c -u -p -r1.2 -r1.3 --- term_ascii.c +++ term_ascii.c @@ -87,7 +87,6 @@ static void ascii_letter(struct termp *p, char c) { - /* Just push onto the screen. */ putchar(c); } Index: mdoc_term.c =================================================================== RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/mdoc_term.c,v retrieving revision 1.144 retrieving revision 1.145 diff -Lmdoc_term.c -Lmdoc_term.c -u -p -r1.144 -r1.145 --- mdoc_term.c +++ mdoc_term.c @@ -65,9 +65,9 @@ static void print_bvspace(struct termp const struct mdoc_node *, const struct mdoc_node *); static void print_mdoc_node(DECL_ARGS); -static void print_mdoc_head(struct termp *, const void *); static void print_mdoc_nodelist(DECL_ARGS); -static void print_foot(struct termp *, const void *); +static void print_mdoc_head(struct termp *, const void *); +static void print_mdoc_foot(struct termp *, const void *); static void synopsis_pre(struct termp *, const struct mdoc_node *); @@ -276,7 +276,8 @@ terminal_mdoc(void *arg, const struct md p->maxrmargin = p->defrmargin; p->tabwidth = 5; - term_begin(p, print_mdoc_head, print_foot, mdoc_meta(mdoc)); + term_begin(p, print_mdoc_head, + print_mdoc_foot, mdoc_meta(mdoc)); if (NULL == p->symtab) switch (p->enc) { @@ -348,9 +349,8 @@ print_mdoc_node(DECL_ARGS) } -/* ARGSUSED */ static void -print_foot(struct termp *p, const void *arg) +print_mdoc_foot(struct termp *p, const void *arg) { char buf[DATESIZ], os[BUFSIZ]; const struct mdoc_meta *m; @@ -400,7 +400,6 @@ print_foot(struct termp *p, const void * } -/* ARGSUSED */ static void print_mdoc_head(struct termp *p, const void *arg) { Index: term_ps.c =================================================================== RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/term_ps.c,v retrieving revision 1.3 retrieving revision 1.4 diff -Lterm_ps.c -Lterm_ps.c -u -p -r1.3 -r1.4 --- term_ps.c +++ term_ps.c @@ -18,9 +18,13 @@ #include "config.h" #endif +#include + #include +#include #include #include +#include #include "out.h" #include "main.h" @@ -34,12 +38,28 @@ #define PS_CHAR_BOTMARG 24 #define PS_CHAR_BOT (PS_CHAR_BOTMARG + 36) +#define PS_BUFSLOP 128 +#define PS_GROWBUF(p, sz) \ + do if ((p)->engine.ps.psmargcur + (sz) > \ + (p)->engine.ps.psmargsz) { \ + (p)->engine.ps.psmargsz += /* CONSTCOND */ \ + MAX(PS_BUFSLOP, (sz)); \ + (p)->engine.ps.psmarg = realloc \ + ((p)->engine.ps.psmarg, \ + (p)->engine.ps.psmargsz); \ + if (NULL == (p)->engine.ps.psmarg) { \ + perror(NULL); \ + exit(EXIT_FAILURE); \ + } \ + } while (/* CONSTCOND */ 0) + static void ps_letter(struct termp *, char); static void ps_begin(struct termp *); static void ps_end(struct termp *); -static void ps_pageopen(struct termp *); static void ps_advance(struct termp *, size_t); static void ps_endline(struct termp *); +static void ps_printf(struct termp *, const char *, ...); +static void ps_putchar(struct termp *, char); void * @@ -63,8 +83,68 @@ ps_alloc(void) void ps_free(void *arg) { + struct termp *p; + + p = (struct termp *)arg; + + if (p->engine.ps.psmarg) + free(p->engine.ps.psmarg); + + term_free(p); +} + + +static void +ps_printf(struct termp *p, const char *fmt, ...) +{ + va_list ap; + int pos; + + va_start(ap, fmt); + + /* + * If we're running in regular mode, then pipe directly into + * vprintf(). If we're processing margins, then push the data + * into our growable margin buffer. + */ + + if ( ! (PS_MARGINS & p->engine.ps.psstate)) { + vprintf(fmt, ap); + va_end(ap); + return; + } + + /* + * XXX: I assume that the in-margin print won't exceed + * PS_BUFSLOP (128 bytes), which is reasonable but still an + * assumption that will cause pukeage if it's not the case. + */ + + PS_GROWBUF(p, PS_BUFSLOP); + + pos = (int)p->engine.ps.psmargcur; + vsnprintf(&p->engine.ps.psmarg[pos], PS_BUFSLOP, fmt, ap); + p->engine.ps.psmargcur = strlen(p->engine.ps.psmarg); +} + + +static void +ps_putchar(struct termp *p, char c) +{ + int pos; + + /* See ps_printf(). */ + + if ( ! (PS_MARGINS & p->engine.ps.psstate)) { + putchar(c); + return; + } - term_free((struct termp *)arg); + PS_GROWBUF(p, 2); + + pos = (int)p->engine.ps.psmargcur++; + p->engine.ps.psmarg[pos] = c; + p->engine.ps.psmarg[pos] = '\0'; } @@ -73,6 +153,15 @@ static void ps_end(struct termp *p) { + /* + * At the end of the file, do one last showpage. This is the + * same behaviour as groff(1) and works for multiple pages as + * well as just one. + */ + + assert(p->engine.ps.psmarg && p->engine.ps.psmarg[0]); + printf("%s", p->engine.ps.psmarg); + printf("showpage\n"); printf("%s\n", "%%EOF"); } @@ -90,9 +179,47 @@ ps_begin(struct termp *p) printf("%s\n", "/Courier"); printf("%s\n", "10 selectfont"); - p->engine.ps.pspage = 1; p->engine.ps.psstate = 0; - ps_pageopen(p); + + if (p->engine.ps.psmarg) { + assert(p->engine.ps.psmargsz); + p->engine.ps.psmarg[0] = '\0'; + } + + p->engine.ps.psmargcur = 0; + + /* + * Now dump the margins into our margin buffer. If we don't do + * this, we'd break any current state to run the header and + * footer with each and evern new page. + */ + + p->engine.ps.pscol = PS_CHAR_LEFT; + p->engine.ps.psrow = PS_CHAR_TOPMARG; + + p->engine.ps.psstate |= PS_MARGINS; + + (*p->headf)(p, p->argf); + (*p->endline)(p); + + p->engine.ps.psstate &= ~PS_MARGINS; + assert(0 == p->engine.ps.psstate); + + p->engine.ps.pscol = PS_CHAR_LEFT; + p->engine.ps.psrow = PS_CHAR_BOTMARG; + p->engine.ps.psstate |= PS_MARGINS; + + (*p->footf)(p, p->argf); + (*p->endline)(p); + + p->engine.ps.psstate &= ~PS_MARGINS; + assert(0 == p->engine.ps.psstate); + + p->engine.ps.pscol = PS_CHAR_LEFT; + p->engine.ps.psrow = PS_CHAR_TOP; + + assert(p->engine.ps.psmarg); + assert('\0' != p->engine.ps.psmarg[0]); } @@ -105,10 +232,9 @@ ps_letter(struct termp *p, char c) * If we're not in a PostScript "word" context, then * open one now at the current cursor. */ - printf("%zu %zu moveto\n", + ps_printf(p, "%zu %zu moveto\n(", p->engine.ps.pscol, p->engine.ps.psrow); - putchar('('); p->engine.ps.psstate |= PS_INLINE; } @@ -125,64 +251,25 @@ ps_letter(struct termp *p, char c) case (')'): /* FALLTHROUGH */ case ('\\'): - putchar('\\'); + ps_putchar(p, '\\'); break; default: break; } /* Write the character and adjust where we are on the page. */ - putchar(c); + ps_putchar(p, c); p->engine.ps.pscol += PS_CHAR_WIDTH; } -/* - * Open a page. This is only used for -Tps at the moment. It opens a - * page context, printing the header and the footer. THE OUTPUT BUFFER - * MUST BE EMPTY. If it is not, output will ghost on the next line and - * we'll be all gross and out of state. - */ -static void -ps_pageopen(struct termp *p) -{ - - assert(TERMTYPE_PS == p->type); - assert(0 == p->engine.ps.psstate); - - p->engine.ps.pscol = PS_CHAR_LEFT; - p->engine.ps.psrow = PS_CHAR_TOPMARG; - p->engine.ps.psstate |= PS_MARGINS; - - (*p->headf)(p, p->argf); - (*p->endline)(p); - - p->engine.ps.psstate &= ~PS_MARGINS; - assert(0 == p->engine.ps.psstate); - - p->engine.ps.pscol = PS_CHAR_LEFT; - p->engine.ps.psrow = PS_CHAR_BOTMARG; - p->engine.ps.psstate |= PS_MARGINS; - - (*p->footf)(p, p->argf); - (*p->endline)(p); - - p->engine.ps.psstate &= ~PS_MARGINS; - assert(0 == p->engine.ps.psstate); - - p->engine.ps.pscol = PS_CHAR_LEFT; - p->engine.ps.psrow = PS_CHAR_TOP; - -} - - static void ps_advance(struct termp *p, size_t len) { if (PS_INLINE & p->engine.ps.psstate) { /* Dump out any existing line scope. */ - printf(") show\n"); + ps_printf(p, ") show\n"); p->engine.ps.psstate &= ~PS_INLINE; } @@ -195,7 +282,7 @@ ps_endline(struct termp *p) { if (PS_INLINE & p->engine.ps.psstate) { - printf(") show\n"); + ps_printf(p, ") show\n"); p->engine.ps.psstate &= ~PS_INLINE; } @@ -208,11 +295,8 @@ ps_endline(struct termp *p) return; } - /* - * XXX: can't run pageopen() until we're certain a flushln() has - * occured, else the buf will reopen in an awkward state on the - * next line. - */ + assert(p->engine.ps.psmarg && p->engine.ps.psmarg[0]); + printf("%s", p->engine.ps.psmarg); printf("showpage\n"); p->engine.ps.psrow = PS_CHAR_TOP; } -- To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv