diff options
| author | jtc <jtc@NetBSD.org> | 1993-07-15 16:40:48 +0000 |
|---|---|---|
| committer | jtc <jtc@NetBSD.org> | 1993-07-15 16:40:48 +0000 |
| commit | 100ce3fca625fc503d57e48e739c7dd94c8ee9ba (patch) | |
| tree | bf1ad7bd866943ee2ab4d2ca3fab9b93b25523d4 /gnu/usr.bin | |
| parent | f81ad74956fa9f174cc06568ddf328470c416eac (diff) | |
Check in remainder of groff 1.08
Diffstat (limited to 'gnu/usr.bin')
50 files changed, 10945 insertions, 1414 deletions
diff --git a/gnu/usr.bin/groff/tfmtodit/Makefile b/gnu/usr.bin/groff/tfmtodit/Makefile new file mode 100644 index 00000000000..b3c738407c1 --- /dev/null +++ b/gnu/usr.bin/groff/tfmtodit/Makefile @@ -0,0 +1,11 @@ +# Makefile for tfmtodit + +PROG= tfmtodit +SRCS= tfmtodit.cc +CFLAGS+= -I$(.CURDIR)/../include +LDADD+= $(LIBGROFF) -lm +DPADD+= $(LIBGROFF) $(LIBMATH) + +.include <bsd.prog.mk> +.include "../../Makefile.inc" +.include "../Makefile.cfg" diff --git a/gnu/usr.bin/groff/tfmtodit/Makefile.dep b/gnu/usr.bin/groff/tfmtodit/Makefile.dep new file mode 100644 index 00000000000..9e1b9f56c37 --- /dev/null +++ b/gnu/usr.bin/groff/tfmtodit/Makefile.dep @@ -0,0 +1,2 @@ +tfmtodit.o : tfmtodit.cc ../include/lib.h ../include/errarg.h \ + ../include/error.h ../include/assert.h ../include/cset.h diff --git a/gnu/usr.bin/groff/tfmtodit/tfmtodit.1 b/gnu/usr.bin/groff/tfmtodit/tfmtodit.1 new file mode 100644 index 00000000000..248f595034d --- /dev/null +++ b/gnu/usr.bin/groff/tfmtodit/tfmtodit.1 @@ -0,0 +1,150 @@ +.\" -*- nroff -*- +.ie t .ds tx T\h'-.1667m'\v'.224m'E\v'-.224m'\h'-.125m'X +.el .ds tx TeX +.\" Like TP, but if specified indent is more than half +.\" the current line-length - indent, use the default indent. +.de Tp +.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP +.el .TP "\\$1" +.. +.TH TFMTODIT 1 "6 August 1992" "Groff Version 1.08" +.SH NAME +tfmtodit \- create font files for use with groff \-Tdvi +.SH SYNOPSIS +.B tfmtodit +[ +.B \-sv +] +[ +.BI \-g gf_file +] +[ +.BI \-k skewchar +] +.I tfm_file +.I map_file +.I font +.SH DESCRIPTION +.B tfmtodit +creates a font file for use with +.B +groff \-Tdvi\fR. +.I tfm_file +is the name of the \*(tx font metric file for the font. +.I map_file +is a file giving the groff names for characters in the font; +this file should consist of a sequence of lines of the form: +.IP +.I +n c1 c2 \fR.\|.\|. +.LP +where +.I n +is a decimal integer giving the position of the character in the font, +and +.IR c1 , +.IR c2 ,.\|.\|. +are the groff names of the character. +If a character has no groff names but exists in the tfm file, +then it will be put in the groff font file as an unnamed character. +.I font +is the name of the groff font file. +The groff font file is written to +.IR font . +.LP +The +.B \-s +option should be given if the font is special +(a font is +.I special +if +.B troff +should search it whenever +a character is not found in the current font.) +If the font is special, +it should be listed in the +.B fonts +command in the DESC file; +if it is not special, there is no need to list it, since +.B troff +can automatically mount it when it's first used. +.LP +To do a good job of math typesetting, groff requires +font metric information not present in the tfm file. +The reason for this is that \*(tx has separate math italic fonts +whereas groff uses normal italic fonts for math. +The additional information required by groff is given by the +two arguments to the +.B math_fit +macro in the Metafont programs for the Computer Modern fonts. +In a text font (a font for which +.B math_fitting +is false), Metafont normally ignores these two arguments. +Metafont can be made to put this information in the gf file +by loading the following definition after +.B cmbase +when creating +.BR cm.base : +.IP +.nf +.ft B +def ignore_math_fit(expr left_adjustment,right_adjustment) = + special "adjustment"; + numspecial left_adjustment*16/designsize; + numspecial right_adjustment*16/designsize; + enddef; +.fi +.ft R +.LP +The gf file created using this modified +.B cm.base +should be specified with the +.B \-g +option. +The +.B \-g +option should not be given for a font for which +.B math_fitting +is true. +.SH OPTIONS +.TP +.B \-v +Print the version number. +.TP +.B \-s +The font is special. +The effect of this option is to add the +.B special +command to the font file. +.TP +.BI \-k n +The skewchar of this font is at position +.IR n . +.I n +should be an integer; +it may be given in decimal, +or with a leading +.B 0 +in octal, +or with a leading +.B 0x +in hexadecimal. +The effect of this option is to ignore any kerns whose second component +is the specified character. +.TP +.BI \-g gf_file +.I gf_file +is a gf file produced by Metafont containing special and numspecial +commands giving additional font metric information. +.SH FILES +.Tp \w'\fB/usr/share/groff_font/devdvi/DESC'u+2n +.B /usr/share/groff_font/devdvi/DESC +Device desciption file. +.TP +.BI /usr/share/groff_font/devdvi/ F +Font description file for font +.IR F . +.SH "SEE ALSO" +.BR groff (1), +.BR grodvi (1), +.BR groff_font (5) diff --git a/gnu/usr.bin/groff/tfmtodit/tfmtodit.cc b/gnu/usr.bin/groff/tfmtodit/tfmtodit.cc new file mode 100644 index 00000000000..851735d163b --- /dev/null +++ b/gnu/usr.bin/groff/tfmtodit/tfmtodit.cc @@ -0,0 +1,850 @@ +// -*- C++ -*- +/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +This file is part of groff. + +groff is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. + +groff is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License along +with groff; see the file COPYING. If not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* I have tried to incorporate the changes needed for TeX 3.0 tfm files, +but I haven't tested them. */ + +/* Groff requires more font metric information than TeX. The reason +for this is that TeX has separate Math Italic fonts, whereas groff +uses normal italic fonts for math. The two additional pieces of +information required by groff correspond to the two arguments to the +math_fit() macro in the Metafont programs for the CM fonts. In the +case of a font for which math_fitting is false, these two arguments +are normally ignored by Metafont. We need to get hold of these two +parameters and put them in the groff font file. + +We do this by loading this definition after cmbase when creating cm.base. + +def ignore_math_fit(expr left_adjustment,right_adjustment) = + special "adjustment"; + numspecial left_adjustment*16/designsize; + numspecial right_adjustment*16/designsize; + enddef; + +This puts the two arguments to the math_fit macro into the gf file. +(They will appear in the gf file immediately before the character to +which they apply.) We then create a gf file using this cm.base. Then +we run tfmtodit and specify this gf file with the -g option. + +This need only be done for a font for which math_fitting is false; +When it's true, the left_correction and subscript_correction should +both be zero. */ + +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <string.h> +#include <errno.h> +#include "lib.h" +#include "errarg.h" +#include "error.h" +#include "assert.h" +#include "cset.h" + +/* Values in the tfm file should be multiplied by this. */ + +#define MULTIPLIER 1 + +struct char_info_word { + unsigned char width_index; + char height_index; + char depth_index; + char italic_index; + char tag; + unsigned char remainder; +}; + +struct lig_kern_command { + unsigned char skip_byte; + unsigned char next_char; + unsigned char op_byte; + unsigned char remainder; +}; + +class tfm { + int bc; + int ec; + int nw; + int nh; + int nd; + int ni; + int nl; + int nk; + int np; + int cs; + int ds; + char_info_word *char_info; + int *width; + int *height; + int *depth; + int *italic; + lig_kern_command *lig_kern; + int *kern; + int *param; +public: + tfm(); + ~tfm(); + int load(const char *); + int contains(int); + int get_width(int); + int get_height(int); + int get_depth(int); + int get_italic(int); + int get_param(int, int *); + int get_checksum(); + int get_design_size(); + int get_lig(unsigned char, unsigned char, unsigned char *); + friend class kern_iterator; +}; + +class kern_iterator { + tfm *t; + int c; + int i; +public: + kern_iterator(tfm *); + int next(unsigned char *c1, unsigned char *c2, int *k); +}; + + +kern_iterator::kern_iterator(tfm *p) +: t(p), i(-1), c(t->bc) +{ +} + +int kern_iterator::next(unsigned char *c1, unsigned char *c2, int *k) +{ + for (; c <= t->ec; c++) + if (t->char_info[c - t->bc].tag == 1) { + if (i < 0) { + i = t->char_info[c - t->bc].remainder; + if (t->lig_kern[i].skip_byte > 128) + i = (256*t->lig_kern[i].op_byte + + t->lig_kern[i].remainder); + } + for (;;) { + int skip = t->lig_kern[i].skip_byte; + if (skip <= 128 && t->lig_kern[i].op_byte >= 128) { + *c1 = c; + *c2 = t->lig_kern[i].next_char; + *k = t->kern[256*(t->lig_kern[i].op_byte - 128) + + t->lig_kern[i].remainder]; + if (skip == 128) { + c++; + i = -1; + } + else + i += skip + 1; + return 1; + } + if (skip >= 128) + break; + i += skip + 1; + } + i = -1; + } + return 0; +} + +tfm::tfm() +: char_info(0), width(0), height(0), depth(0), italic(0), lig_kern(0), + kern(0), param(0) +{ +} + +int tfm::get_lig(unsigned char c1, unsigned char c2, unsigned char *cp) +{ + if (contains(c1) && char_info[c1 - bc].tag == 1) { + int i = char_info[c1 - bc].remainder; + if (lig_kern[i].skip_byte > 128) + i = 256*lig_kern[i].op_byte + lig_kern[i].remainder; + for (;;) { + int skip = lig_kern[i].skip_byte; + if (skip > 128) + break; + // We are only interested in normal ligatures, for which + // op_byte == 0. + if (lig_kern[i].op_byte == 0 + && lig_kern[i].next_char == c2) { + *cp = lig_kern[i].remainder; + return 1; + } + if (skip == 128) + break; + i += skip + 1; + } + } + return 0; +} + +int tfm::contains(int i) +{ + return i >= bc && i <= ec && char_info[i - bc].width_index != 0; +} + +int tfm::get_width(int i) +{ + return width[char_info[i - bc].width_index]; +} + +int tfm::get_height(int i) +{ + return height[char_info[i - bc].height_index]; +} + +int tfm::get_depth(int i) +{ + return depth[char_info[i - bc].depth_index]; +} + +int tfm::get_italic(int i) +{ + return italic[char_info[i - bc].italic_index]; +} + +int tfm::get_param(int i, int *p) +{ + if (i <= 0 || i > np) + return 0; + else { + *p = param[i - 1]; + return 1; + } +} + +int tfm::get_checksum() +{ + return cs; +} + +int tfm::get_design_size() +{ + return ds; +} + +tfm::~tfm() +{ + a_delete char_info; + a_delete width; + a_delete height; + a_delete depth; + a_delete italic; + a_delete lig_kern; + a_delete kern; + a_delete param; +} + +int read2(unsigned char *&s) +{ + int n; + n = *s++ << 8; + n |= *s++; + return n; +} + +int read4(unsigned char *&s) +{ + int n; + n = *s++ << 24; + n |= *s++ << 16; + n |= *s++ << 8; + n |= *s++; + return n; +} + + +int tfm::load(const char *file) +{ + errno = 0; + FILE *fp = fopen(file, "r"); + if (!fp) { + error("can't open `%1': %2", file, strerror(errno)); + return 0; + } + int c1 = getc(fp); + int c2 = getc(fp); + if (c1 == EOF || c2 == EOF) { + fclose(fp); + error("unexpected end of file on `%1'", file); + return 0; + } + int lf = (c1 << 8) + c2; + int toread = lf*4 - 2; + unsigned char *buf = new unsigned char[toread]; + if (fread(buf, 1, toread, fp) != toread) { + if (feof(fp)) + error("unexpected end of file on `%1'", file); + else + error("error on file `%1'", file); + a_delete buf; + fclose(fp); + return 0; + } + fclose(fp); + if (lf < 6) { + error("bad tfm file `%1': impossibly short", file); + a_delete buf; + return 0; + } + unsigned char *ptr = buf; + int lh = read2(ptr); + bc = read2(ptr); + ec = read2(ptr); + nw = read2(ptr); + nh = read2(ptr); + nd = read2(ptr); + ni = read2(ptr); + nl = read2(ptr); + nk = read2(ptr); + int ne = read2(ptr); + np = read2(ptr); + if (6 + lh + (ec - bc + 1) + nw + nh + nd + ni + nl + nk + ne + np != lf) { + error("bad tfm file `%1': lengths do not sum", file); + a_delete buf; + return 0; + } + if (lh < 2) { + error("bad tfm file `%1': header too short", file); + a_delete buf; + return 0; + } + char_info = new char_info_word[ec - bc + 1]; + width = new int[nw]; + height = new int[nh]; + depth = new int[nd]; + italic = new int[ni]; + lig_kern = new lig_kern_command[nl]; + kern = new int[nk]; + param = new int[np]; + int i; + cs = read4(ptr); + ds = read4(ptr); + ptr += (lh-2)*4; + for (i = 0; i < ec - bc + 1; i++) { + char_info[i].width_index = *ptr++; + unsigned char tem = *ptr++; + char_info[i].depth_index = tem & 0xf; + char_info[i].height_index = tem >> 4; + tem = *ptr++; + char_info[i].italic_index = tem >> 2; + char_info[i].tag = tem & 3; + char_info[i].remainder = *ptr++; + } + for (i = 0; i < nw; i++) + width[i] = read4(ptr); + for (i = 0; i < nh; i++) + height[i] = read4(ptr); + for (i = 0; i < nd; i++) + depth[i] = read4(ptr); + for (i = 0; i < ni; i++) + italic[i] = read4(ptr); + for (i = 0; i < nl; i++) { + lig_kern[i].skip_byte = *ptr++; + lig_kern[i].next_char = *ptr++; + lig_kern[i].op_byte = *ptr++; + lig_kern[i].remainder = *ptr++; + } + for (i = 0; i < nk; i++) + kern[i] = read4(ptr); + ptr += ne*4; + for (i = 0; i < np; i++) + param[i] = read4(ptr); + assert(ptr == buf + lf*4 - 2); + a_delete buf; + return 1; +} + +class gf { + int left[256]; + int right[256]; + static int sread4(int *p, FILE *fp); + static int uread3(int *p, FILE *fp); + static int uread2(int *p, FILE *fp); + static int skip(int n, FILE *fp); +public: + gf(); + int load(const char *file); + int get_left_adjustment(int i) { return left[i]; } + int get_right_adjustment(int i) { return right[i]; } +}; + +gf::gf() +{ + for (int i = 0; i < 256; i++) + left[i] = right[i] = 0; +} + +int gf::load(const char *file) +{ + enum { + paint_0 = 0, + paint1 = 64, + boc = 67, + boc1 = 68, + eoc = 69, + skip0 = 70, + skip1 = 71, + new_row_0 = 74, + xxx1 = 239, + yyy = 243, + no_op = 244, + pre = 247, + post = 248 + }; + int got_an_adjustment = 0; + int pending_adjustment = 0; + int left_adj, right_adj; + const int gf_id_byte = 131; + errno = 0; + FILE *fp = fopen(file, "r"); + if (!fp) { + error("can't open `%1': %2", file, strerror(errno)); + return 0; + } + if (getc(fp) != pre || getc(fp) != gf_id_byte) { + error("bad gf file"); + return 0; + } + int n = getc(fp); + if (n == EOF) + goto eof; + if (!skip(n, fp)) + goto eof; + for (;;) { + int op = getc(fp); + if (op == EOF) + goto eof; + if (op == post) + break; + if ((op >= paint_0 && op <= paint_0 + 63) + || (op >= new_row_0 && op <= new_row_0 + 164)) + continue; + switch (op) { + case no_op: + case eoc: + case skip0: + break; + case paint1: + case skip1: + if (!skip(1, fp)) + goto eof; + break; + case paint1 + 1: + case skip1 + 1: + if (!skip(2, fp)) + goto eof; + break; + case paint1 + 2: + case skip1 + 2: + if (!skip(3, fp)) + goto eof; + break; + case boc: + { + int code; + if (!sread4(&code, fp)) + goto eof; + if (pending_adjustment) { + pending_adjustment = 0; + left[code & 0377] = left_adj; + right[code & 0377] = right_adj; + } + if (!skip(20, fp)) + goto eof; + break; + } + case boc1: + { + int code = getc(fp); + if (code == EOF) + goto eof; + if (pending_adjustment) { + pending_adjustment = 0; + left[code] = left_adj; + right[code] = right_adj; + } + if (!skip(4, fp)) + goto eof; + break; + } + case xxx1: + { + int len = getc(fp); + if (len == EOF) + goto eof; + char buf[256]; + if (fread(buf, 1, len, fp) != len) + goto eof; + if (len == 10 /* strlen("adjustment") */ + && memcmp(buf, "adjustment", len) == 0) { + int c = getc(fp); + if (c != yyy) { + if (c != EOF) + ungetc(c, fp); + break; + } + if (!sread4(&left_adj, fp)) + goto eof; + c = getc(fp); + if (c != yyy) { + if (c != EOF) + ungetc(c, fp); + break; + } + if (!sread4(&right_adj, fp)) + goto eof; + got_an_adjustment = 1; + pending_adjustment = 1; + } + break; + } + case xxx1 + 1: + if (!uread2(&n, fp) || !skip(n, fp)) + goto eof; + break; + case xxx1 + 2: + if (!uread3(&n, fp) || !skip(n, fp)) + goto eof; + break; + case xxx1 + 3: + if (!sread4(&n, fp) || !skip(n, fp)) + goto eof; + break; + case yyy: + if (!skip(4, fp)) + goto eof; + break; + default: + fatal("unrecognized opcode `%1'", op); + break; + } + } + if (!got_an_adjustment) + warning("no adjustment specials found in gf file"); + return 1; + eof: + error("unexpected end of file"); + return 0; +} + +int gf::sread4(int *p, FILE *fp) +{ + *p = getc(fp); + if (*p >= 128) + *p -= 256; + *p <<= 8; + *p |= getc(fp); + *p <<= 8; + *p |= getc(fp); + *p <<= 8; + *p |= getc(fp); + return !ferror(fp) && !feof(fp); +} + +int gf::uread3(int *p, FILE *fp) +{ + *p = getc(fp); + *p <<= 8; + *p |= getc(fp); + *p <<= 8; + *p |= getc(fp); + return !ferror(fp) && !feof(fp); +} + +int gf::uread2(int *p, FILE *fp) +{ + *p = getc(fp); + *p <<= 8; + *p |= getc(fp); + return !ferror(fp) && !feof(fp); +} + +int gf::skip(int n, FILE *fp) +{ + while (--n >= 0) + if (getc(fp) == EOF) + return 0; + return 1; +} + + +struct char_list { + char *ch; + char_list *next; + char_list(const char *, char_list * = 0); +}; + +char_list::char_list(const char *s, char_list *p) : ch(strsave(s)), next(p) +{ +} + + +int read_map(const char *file, char_list **table) +{ + errno = 0; + FILE *fp = fopen(file, "r"); + if (!fp) { + error("can't open `%1': %2", file, strerror(errno)); + return 0; + } + for (int i = 0; i < 256; i++) + table[i] = 0; + char buf[512]; + int lineno = 0; + while (fgets(buf, int(sizeof(buf)), fp)) { + lineno++; + char *ptr = buf; + while (csspace(*ptr)) + ptr++; + if (*ptr == '\0' || *ptr == '#') + continue; + ptr = strtok(ptr, " \n\t"); + if (!ptr) + continue; + int n; + if (sscanf(ptr, "%d", &n) != 1) { + error("%1:%2: bad map file", file, lineno); + fclose(fp); + return 0; + } + if (n < 0 || n > 255) { + error("%1:%2: code out of range", file, lineno); + fclose(fp); + return 0; + } + ptr = strtok(0, " \n\t"); + if (!ptr) { + error("%1:%2: missing names", file, lineno); + fclose(fp); + return 0; + } + for (; ptr; ptr = strtok(0, " \n\t")) + table[n] = new char_list(ptr, table[n]); + } + fclose(fp); + return 1; +} + + +/* Every character that can participate in a ligature appears in the +lig_chars table. `ch' gives the full-name of the character, `name' +gives the groff name of the character, `i' gives its index in +the encoding, which is filled in later (-1 if it does not appear). */ + +struct { + const char *ch; + int i; +} lig_chars[] = { + "f", -1, + "i", -1, + "l", -1, + "ff", -1, + "fi", -1, + "fl", -1, + "Fi", -1, + "Fl", -1, +}; + +// Indices into lig_chars[]. + +enum { CH_f, CH_i, CH_l, CH_ff, CH_fi, CH_fl, CH_ffi, CH_ffl }; + +// Each possible ligature appears in this table. + +struct { + unsigned char c1, c2, res; + const char *ch; +} lig_table[] = { + CH_f, CH_f, CH_ff, "ff", + CH_f, CH_i, CH_fi, "fi", + CH_f, CH_l, CH_fl, "fl", + CH_ff, CH_i, CH_ffi, "ffi", + CH_ff, CH_l, CH_ffl, "ffl", + }; + +static void usage(); + +int main(int argc, char **argv) +{ + program_name = argv[0]; + int special_flag = 0; + int skewchar = -1; + int opt; + const char *gf_file = 0; + while ((opt = getopt(argc, argv, "svg:k:")) != EOF) + switch (opt) { + case 'g': + gf_file = optarg; + break; + case 's': + special_flag = 1; + break; + case 'k': + { + char *ptr; + long n = strtol(optarg, &ptr, 0); + if ((n == 0 && ptr == optarg) + || *ptr != '\0' + || n < 0 + || n > UCHAR_MAX) + error("invalid skewchar"); + else + skewchar = (int)n; + break; + } + case 'v': + { + extern const char *version_string; + fprintf(stderr, "tfmtodit version %s\n", version_string); + fflush(stderr); + break; + } + case '?': + usage(); + break; + case EOF: + assert(0); + } + if (argc - optind != 3) + usage(); + gf g; + if (gf_file) { + if (!g.load(gf_file)) + return 1; + } + const char *tfm_file = argv[optind]; + const char *map_file = argv[optind + 1]; + const char *font_file = argv[optind + 2]; + tfm t; + if (!t.load(tfm_file)) + return 1; + char_list *table[256]; + if (!read_map(map_file, table)) + return 1; + errno = 0; + if (!freopen(font_file, "w", stdout)) { + error("can't open `%1' for writing: %2", font_file, strerror(errno)); + return 1; + } + printf("name %s\n", font_file); + if (special_flag) + fputs("special\n", stdout); + char *internal_name = strsave(argv[optind]); + int len = strlen(internal_name); + if (len > 4 && strcmp(internal_name + len - 4, ".tfm") == 0) + internal_name[len - 4] = '\0'; + char *s = strrchr(internal_name, '/'); + printf("internalname %s\n", s ? s + 1 : internal_name); + int n; + if (t.get_param(2, &n)) { + if (n > 0) + printf("spacewidth %d\n", n*MULTIPLIER); + } + if (t.get_param(1, &n) && n != 0) + printf("slant %f\n", atan2(n/double(1<<20), 1.0)*180.0/M_PI); + int xheight; + if (!t.get_param(5, &xheight)) + xheight = 0; + int i; + // Print the list of ligatures. + // First find the indices of each character that can participate in + // a ligature. + for (i = 0; i < 256; i++) + for (int j = 0; j < sizeof(lig_chars)/sizeof(lig_chars[0]); j++) + for (char_list *p = table[i]; p; p = p->next) + if (strcmp(lig_chars[j].ch, p->ch) == 0) + lig_chars[j].i = i; + // For each possible ligature, if its participants all exist, + // and it appears as a ligature in the tfm file, include in + // the list of ligatures. + int started = 0; + for (i = 0; i < sizeof(lig_table)/sizeof(lig_table[0]); i++) { + int i1 = lig_chars[lig_table[i].c1].i; + int i2 = lig_chars[lig_table[i].c2].i; + int r = lig_chars[lig_table[i].res].i; + if (i1 >= 0 && i2 >= 0 && r >= 0) { + unsigned char c; + if (t.get_lig(i1, i2, &c) && c == r) { + if (!started) { + started = 1; + fputs("ligatures", stdout); + } + printf(" %s", lig_table[i].ch); + } + } + } + if (started) + fputs(" 0\n", stdout); + printf("checksum %d\n", t.get_checksum()); + printf("designsize %d\n", t.get_design_size()); + // Now print out the kerning information. + int had_kern = 0; + kern_iterator iter(&t); + unsigned char c1, c2; + int k; + while (iter.next(&c1, &c2, &k)) + if (c2 != skewchar) { + k *= MULTIPLIER; + char_list *q = table[c2]; + for (char_list *p1 = table[c1]; p1; p1 = p1->next) + for (char_list *p2 = q; p2; p2 = p2->next) { + if (!had_kern) { + printf("kernpairs\n"); + had_kern = 1; + } + printf("%s %s %d\n", p1->ch, p2->ch, k); + } + } + printf("charset\n"); + char_list unnamed("---"); + for (i = 0; i < 256; i++) + if (t.contains(i)) { + char_list *p = table[i] ? table[i] : &unnamed; + int m[6]; + m[0] = t.get_width(i); + m[1] = t.get_height(i); + m[2] = t.get_depth(i); + m[3] = t.get_italic(i); + m[4] = g.get_left_adjustment(i); + m[5] = g.get_right_adjustment(i); + printf("%s\t%d", p->ch, m[0]*MULTIPLIER); + for (int j = int(sizeof(m)/sizeof(m[0])) - 1; j > 0; j--) + if (m[j] != 0) + break; + for (int k = 1; k <= j; k++) + printf(",%d", m[k]*MULTIPLIER); + int type = 0; + if (m[2] > 0) + type = 1; + if (m[1] > xheight) + type += 2; + printf("\t%d\t%04o\n", type, i); + for (p = p->next; p; p = p->next) + printf("%s\t\"\n", p->ch); + } + return 0; +} + +static void usage() +{ + fprintf(stderr, "usage: %s [-sv] [-g gf_file] [-k skewchar] tfm_file map_file font\n", + program_name); + exit(1); +} diff --git a/gnu/usr.bin/groff/tmac/Makefile b/gnu/usr.bin/groff/tmac/Makefile new file mode 100644 index 00000000000..eac75f94eaf --- /dev/null +++ b/gnu/usr.bin/groff/tmac/Makefile @@ -0,0 +1,26 @@ +# Makefile for groff macros + +TMACOWN?= bin +TMACGRP?= bin +TMACMODE?= 444 +TMACDIR?= /usr/share/tmac + +MAN7= groff_ms.0 +MLINKS= groff_ms.7 ms.7 + +FILES= tmac.pic tmac.ps tmac.psnew tmac.psold tmac.pspic tmac.psatk\ + tmac.dvi tmac.tty tmac.tty-char tmac.X tmac.Xps tmac.latin1\ + man.local eqnrc troffrc + +afterinstall: + for f in ${FILES}; do \ + install -c -o ${TMACOWN} -g ${TMACGRP} -m ${TMACMODE} \ + ${.CURDIR}/$$f ${DESTDIR}${TMACDIR}; \ + done + install -c -o ${TMACOWN} -g ${TMACGRP} -m ${TMACMODE} \ + ${.CURDIR}/tmac.s ${DESTDIR}${TMACDIR}/tmac.${tmac_s} + install -c -o ${TMACOWN} -g ${TMACGRP} -m ${TMACMODE} \ + ${.CURDIR}/tmac.an ${DESTDIR}${TMACDIR}/tmac.an.old + +.include <bsd.prog.mk> +.include "../Makefile.cfg" diff --git a/gnu/usr.bin/groff/tmac/TODO b/gnu/usr.bin/groff/tmac/TODO new file mode 100644 index 00000000000..5213fc274c0 --- /dev/null +++ b/gnu/usr.bin/groff/tmac/TODO @@ -0,0 +1,38 @@ +Support multiple line-spacing. + +Improve the device independence of the character definitions. + +If we have footnotes in the abstract in RP format, then the footnote +will appear on the cover sheet, which it should, but also on the first +page, which it should not. + +Should we allow multi-page cover-sheets? + +Warn about automatically numbered footnotes in floating keeps. + +When we bring back the footnote overflow at the top of page, it would +be more efficient to avoid diverting it again. (Need to keep track of +footnote height.) + +Possibly have a place above which the footnote trap must not be +placed. + +Improved indexing, not using tm, controlled by string variable (eg +-dIDX=file.idx). + +When changing from multi-column to narrower columns, we could avoid +doing a @super-eject. (This might not be a good idea.) + +Think about cutmarks. Possibly implement CM. + +Implement thesis Mode (TM, CT). + +Implement more V10 features. + +Should this + +.LP +.rs +.sp \n(.tu + +print two pages? diff --git a/gnu/usr.bin/groff/tmac/eqnrc b/gnu/usr.bin/groff/tmac/eqnrc new file mode 100644 index 00000000000..eab720cf34d --- /dev/null +++ b/gnu/usr.bin/groff/tmac/eqnrc @@ -0,0 +1,60 @@ +.\" Startup file for eqn. +.EQ +sdefine << %{ < back 20 < }% +sdefine >> %{ > back 20 > }% + +sdefine dot %accent "\fR\(a.\fP"% +sdefine dotdot %accent "\fR\(ad\fP"% +sdefine vec %accent {up 52 "\s[\En[.s]/2u]\(->\s0"}% +sdefine dyad %accent {up 52 "\s[\En[.s]/2u]\(<>\s0"}% + +sdefine cdot %type "binary" \(md% + +ifdef X75 ! define X %1% ! +ifdef X100 ! define X %1% ! +ifdef X75-12 ! define X %1% ! +ifdef X100-12 ! define X %1% ! + +ifdef ps ! define ps|X %1% ! +ifdef X ! define ps|X %1% ! + +ifdef ps|X ! sdefine inf %"\s[\En[.s]*13u/10u]\v'12M'\(if\v'-12M'\s0"% ! + +ifdef dvi ! +sdefine int %{type "operator" vcenter \(is}% +sdefine sum %{type "operator" vcenter \[sum]}% +sdefine prod %{type "operator" vcenter \[product]}% +sdefine coprod %{type "operator" vcenter \[coproduct]}% +set num1 68 +set num2 39 +set denom1 69 +set denom2 34 +set sup1 41 +set sup2 36 +set sup3 29 +set sup_drop 39 +set sub_drop 5 +set axis_height 25 +set x_height 43 +set default_rule_thickness 4 +set big_op_spacing1 11 +set big_op_spacing2 16 +set big_op_spacing3 20 +set big_op_spacing4 60 +set big_op_spacing5 10 +! + +ifdef X ! set axis_height 32 ! + +ifdef ps|X ! set draw_lines 1 ! + +ifdef ascii ! define n %1% ! +ifdef latin1 ! define n %1% ! +ifdef n ! +set nroff 1 +! + +undef X +undef ps|X +undef n +.EN diff --git a/gnu/usr.bin/groff/tmac/groff_ms.7 b/gnu/usr.bin/groff/tmac/groff_ms.7 new file mode 100644 index 00000000000..a2aacb80e48 --- /dev/null +++ b/gnu/usr.bin/groff/tmac/groff_ms.7 @@ -0,0 +1,210 @@ +.\" -*- nroff -*- +.TH GROFF_MS 7 "6 August 1992" "Groff Version 1.08" +.SH NAME +groff_ms \- groff ms macros +.SH SYNOPSIS +.B groff +.B \-ms +[ +.IR options .\|.\|. +] +[ +.IR files .\|.\|. +] +.SH DESCRIPTION +This manual page describes the GNU version of the ms macros, +which is part of the groff document formatting system. +The groff ms macros are intended to be compatible with the 4.3 +.SM BSD +Unix ms macros subject to the following limitations: +.IP \(bu +the internals of groff ms are not similar to the internals of Unix ms +and so documents that depend upon implementation details of Unix ms +may well not work with groff ms; +.IP \(bu +there is no support for typewriter-like devices; +.IP \(bu +Berkeley localisms, in particular the +.B TM +and +.B CT +macros, are not implemented; +.IP \(bu +groff ms +does not provide cut marks; +.IP \(bu +multiple line spacing is not allowed +(use a larger vertical spacing instead); +.IP \(bu +groff ms does not work in compatibility mode (eg with the +.B \-C +option); +.IP \(bu +the error-handling policy of groff ms +is to detect and report errors, +rather than silently to ignore them. +.LP +The groff ms macros make use of many features of GNU troff +and therefore cannot be used with any other troff. +.LP +Bell Labs localisms are not implemented in either the +.SM BSD +ms macros or in the groff ms macros. +.LP +Some Unix ms documentation says that the +.B CW +and +.B GW +number registers can be used to control the column width and +gutter width respectively. +This is not the case. +These number registers are not used in groff ms. +.LP +Macros that cause a reset set the indent. +Macros that change the indent do not increment or decrement +the indent, but rather set it absolutely. +This can cause problems for documents that define +additional macros of their own. +The solution is to use not the +.B in +request but instead the +.B RS +and +.B RE +macros. +.LP +The number register +.B GS +is set to 1 by the groff ms macros, +but is not used by the Unix ms macros. +It is intended that documents that need to determine whether +they are being formatted with Unix ms or groff ms make use of this +number register. +.LP +Footnotes are implemented so that they can safely be used within +keeps and displays. +Automatically numbered footnotes within floating keeps are +not recommended. +It is safe to have another +.B \e** +between a +.B \e** +and the corresponding +.BR .FS ; +it is required only that each +.B .FS +occur after the corresponding +.B \e** +and that the occurrences of +.B .FS +are in the same order as the corresponding occurrences of +.BR \e** . +.LP +The strings +.B \e*{ +and +.B \e*} +can be used to begin and end a superscript. +.LP +Some Unix V10 ms features are implemented. +The +.BR B , +.BR I +and +.B BI +macros can have an optional third argument which will be printed +in the current font before the first argument. +There is a macro +.B CW +like +.B B +that changes to a constant-width font. +.LP +The following strings can be redefined to adapt the groff ms macros +to languages other than English: +.LP +.nf +.ta \w'REFERENCES'u+2n +String Default Value +.sp .3v +REFERENCES References +ABSTRACT ABSTRACT +TOC Table of Contents +MONTH1 January +MONTH2 February +MONTH3 March +MONTH4 April +MONTH5 May +MONTH6 June +MONTH7 July +MONTH8 August +MONTH9 September +MONTH10 October +MONTH11 November +MONTH12 December +.fi +.LP +The font family is reset from the string +.BR FAM ; +at initialization if this string is undefined it is set to the current +font family. +The point size, vertical spacing, and inter-paragraph spacing for footnotes +are taken from the number registers +.BR FPS , +.BR FVS , +and +.BR FPD ; +at initialization these are set to +.BR \en(PS-2 , +.BR \en[FPS]+2 , +and +.B \en(PD/2 +respectively; however, if any of these registers has been defined +before initialization, it will not be set. +.LP +Right-aligned displays are available with +.B ".DS R" +and +.BR .RD . +.LP +The following conventions are used for names of macros, strings and +number registers. +External names available to documents that use the groff ms +macros contain only uppercase letters and digits. +Internally the macros are divided into modules. +Names used only within one module are of the form +.IB module * name\fR. +Names used outside the module in which they are defined are of the form +.IB module @ name\fR. +Names associated with a particular environment are of the form +.IB environment : name; +these are used only within the +.B par +module, +and +.I name +does not have a module prefix. +Constructed names used to implement arrays are of the form +.IB array ! index\fR. +Thus the groff ms macros reserve the following names: +.IP \(bu +names containing +.BR * ; +.IP \(bu +names containing +.BR @ ; +.IP \(bu +names containing +.BR : ; +.IP \(bu +names containing only uppercase letters and digits. +.SH FILES +.B /usr/share/tmac/tmac.s +.SH "SEE ALSO" +.BR groff (1), +.BR troff (1), +.BR tbl (1), +.BR pic (1), +.BR eqn (1) +.br +.BR ms (7) diff --git a/gnu/usr.bin/groff/tmac/man.local b/gnu/usr.bin/groff/tmac/man.local new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/gnu/usr.bin/groff/tmac/man.local diff --git a/gnu/usr.bin/groff/tmac/tmac.X b/gnu/usr.bin/groff/tmac/tmac.X new file mode 100644 index 00000000000..044113fe92e --- /dev/null +++ b/gnu/usr.bin/groff/tmac/tmac.X @@ -0,0 +1,45 @@ +.nr _C \n(.C +.cp 0 +.ftr CW CR +.ftr C CR +.ftr CO CI +.ftr CX CBI +.ftr H HR +.ftr HO HI +.ftr HX HBI +.ftr NX NBI +.char \(ru \D'l .5m 0' +.char \(ul \v'.25m'\D'l .5m 0'\v'-.25m' +.char \(br \v'.25m'\D'l 0 -1m'\v'.75m' +.char ~ \v'-.55m'\\s[\\n(.s/2u]\v'.2m'\(ti\v'-.2m'\s0\v'.55m' +.char ^ \v'-.55m'\\s[\\n(.s/2u]\v'.3m'\(ha\v'-.3m'\s0\v'.55m' +.if !c\(va .char \(va \o'\(ua\(da' +.if !c\(em .char \(em -- +.if !c\(en .char \(en \- +.if !c\(fi .char \(fi fi +.if !c\(fl .char \(fl fl +.if !c\(ff .char \(ff ff +.if !c\(Fi .char \(Fi ffi +.if !c\(Fl .char \(Fl ffl +.if !c\(ci .char \(ci \v'-.25m'\h'.05m'\D'c .5m'\h'.05m'\v'.25m' +.if !c\(sq .char \(sq \h'.05m'\D'l .5m 0'\D'l 0 -.5m'\D'l -.5m 0'\D'l 0 .5m'\h'.55m' +.if !c\(ga .char \(ga \Z'\v'-.7m'\D'l .22m .18m''\h'.33m' +.if !c\(dg .char \(dg \Z'\h'.25m'\v'.15m'\D'l 0 -.8m'\v'.2m'\h'-.195m'\ +\D'l .39m 0''\h'.5m' +.if !c\(dd .char \(dd \Z'\h'.25m'\v'.15m'\D'l 0 -.8m'\v'.2m'\h'-.195m'\ +\D'l .39m 0'\v'.4m'\D'l -.39m 0''\h'.5m' +.if !c\(lq .char \(lq `` +.if !c\(rq .char \(rq '' +.if !c\(Bq .char \(bq ,, +.if !c\(OE .char \(OE O\h'-.25m'E +.if !c\(oe .char \(oe o\h'-.14m'e +.if !c\(ah .char \(ah \v'-.55m'\s[\En[.s]/2u]v\s0\v'.55m' +.if !c\(ao .char \(ao \v'-.55m'\s[\En[.s]*6u/10u]\D'c .25m'\s0\v'.55m' +.if !c\(ho .char \(ho \s[\En[.s]/2u]\v'.4m'c\v'-.4m'\s0 +.if !c\(lh .tr \(lh\(lA +.if !c\(rh .tr \(rh\(rA +.if !c\(bq .tr \(bq, +.if !c\(aq .tr \(aq' +.if '\*(.T'X100' .char \(rn \h'-\w'\(sr'u'\(rn\h'\w'\(sr'u' +.if !\n(_C .mso tmac.pspic +.cp \n(_C diff --git a/gnu/usr.bin/groff/tmac/tmac.Xps b/gnu/usr.bin/groff/tmac/tmac.Xps new file mode 100644 index 00000000000..92471abbc13 --- /dev/null +++ b/gnu/usr.bin/groff/tmac/tmac.Xps @@ -0,0 +1,44 @@ +.do mso tmac.ps +.nr _C \n(.C +.cp 0 +.de Xps-char +.char \\$1 \Z"\X'ps: invis'\\$2\X'ps: endinvis'"\\$1 +.. +.Xps-char \(bu \fS\(bu\fP +.Xps-char \(em "\v'-.25m'\h'.05m'\D'l .9m 0'\h'.05m'" +.Xps-char \(aq ' +.Xps-char \(bq , +.Xps-char \(Bq ,, +.Xps-char \(lq `` +.Xps-char \(rq '' +.Xps-char \(OE OE +.Xps-char \(oe oe +.Xps-char \(Fn \fS\(Fn\fP +.Xps-char \(vS \o'\(ahS' +.Xps-char \(vs \o'\(ahs' +.Xps-char \(vZ \o'\(ahZ' +.Xps-char \(vz \o'\(ahz' +.Xps-char \(/L \o'/L' +.Xps-char \(/l \o'/l' +.Xps-char \(:Y \o'\(adY' +.Xps-char \(a" \(sd +.Xps-char \(a. \v'-.6m'. +.Xps-char \(ga "\Z'\v'-.7m'\D'l .22m .18m''\h'.33m'" +.Xps-char \(ab \v'-.55m'\s'\\\\n(.s*6u/10u'u\s0 +.Xps-char \(ah \v'-.55m'\s[\En[.s]/2u]v\s0\v'.55m' +.Xps-char \(ao "\v'-.55m'\s[\En[.s]*6u/10u]\D'c .25m'\s0\v'.55m'" +.Xps-char \(ho \s[\En[.s]/2u]\v'.4m'c\v'-.4m'\s0 +.Xps-char \(.i i +.Xps-char \(fo < +.Xps-char \(fc > +.Xps-char \(OK \s'\\\\n(.s*6u/10u'\e\s0/ +.Xps-char \(tm \v'-.3m'\s'\\\\n(.s*6u/10u'TM\s0\v'.3m' +.Xps-char \(dd "\Z'\h'.25m'\v'.15m'\D'l 0 -.8m'\v'.2m'\h'-.195m'\ +\D'l .39m 0'\v'.4m'\D'l -.39m 0''\h'.5m'" +.Xps-char \(dg "\Z'\h'.25m'\v'.15m'\D'l 0 -.8m'\v'.2m'\h'-.195m'\ +\D'l .39m 0''\h'.5m'" +.Xps-char \(en \- +.Xps-char \(%0 %\s'\\\\n(.s*6u/10u'\fI0\fP\s0 +.Xps-char \(lh \(-> +.Xps-char \(rh \(<- +.cp \n(_C diff --git a/gnu/usr.bin/groff/tmac/tmac.an b/gnu/usr.bin/groff/tmac/tmac.an new file mode 100644 index 00000000000..017a6a8c091 --- /dev/null +++ b/gnu/usr.bin/groff/tmac/tmac.an @@ -0,0 +1,326 @@ +.\"Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. +.\" Written by James Clark (jjc@jclark.com) +.\" +.\"This file is part of groff. +.\" +.\"groff is free software; you can redistribute it and/or modify it under +.\"the terms of the GNU General Public License as published by the Free +.\"Software Foundation; either version 2, or (at your option) any later +.\"version. +.\" +.\"groff is distributed in the hope that it will be useful, but WITHOUT ANY +.\"WARRANTY; without even the implied warranty of MERCHANTABILITY or +.\"FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +.\"for more details. +.\" +.\"You should have received a copy of the GNU General Public License along +.\"with groff; see the file COPYING. If not, write to the Free Software +.\"Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +.\" +.\" -rC1 => number pages continuously, rather than start each at 1 +.\" -rD1 => double-sided printing, ie different odd and even page footers +.\" -rPnnn => number first page nnn +.\" -rXnnn => number pages after nnn as nnna, nnnb, nnnc, ... +.\" +.\" The file man.local is loaded at the end. Put local additions there. +.\" If you need to add things to TH, use `.am TH'. +.\" +.if !\n(.g .ab These man macros work only with groff. +.nr _C \n(.C +.cp 0 +.if !rD .nr D 0 +.if !rC .nr C 0 +.if rP .pn 0\nP +.\" .TH title section extra1 extra2 extra3 +.de TH +.cp 0 +.de an-init \" We have to do it like this to get multiple man pages right. +.ds an-title "\\$1 +.ds an-section "\\$2 +.ds an-extra1 "\\$3 +.ie \\n[.$]>3 .ds an-extra2 "\\$4 +.el .ds an-extra2 \"Sun Release 4.0 +.ie \\n[.$]>4 .ds an-extra3 "\\$5 +.el .ds an-extra3 \"UNIX Programmer's Manual +.ds an-init +\\.. +.DT +.nr IN 7.2n +.nr LL 6.5i +.PD +.nr PS 10 \" normal point-size +.nr SN 3n \" the indentation of sub-sub-headings relative to sub-headings +.nr an-level 1 +.nr an-margin \\n[IN] +.nr an-prevailing-indent \\n[IN] +.nr an-tag-sep 1n +.nr an-no-space-flag 0 +.nr an-break-flag 0 +.nr an-div? 0 +.wh 0 an-header +.wh -1i an-footer +.wh -.5i an-p-footer +.if \\n[nl]>0 \{\ +. ie \\nC .bp \\n%+1 +. el .bp 1 +.\} +.. +.de DT +.ta T .5i \" This sets tabs every .5 inches +.. +.de PD +.ie \\n[.$] .nr PD (v;\\$1) +.el .nr PD .4v>?\n[.V] +.. +.de an-header +.an-init +.ev 1 +.sp .5i +.tl '\\*[an-title](\\*[an-section])'\\*[an-extra3]'\\*[an-title](\\*[an-section])' +.sp |1i +.ev +.ns +.. +.de an-footer +'bp +.. +.af an-page-letter a +.de an-p-footer +.ev 1 +.ds an-page-string \\n% +.if rX \{\ +. if \\n%>\\nX \{\ +. nr an-page-letter \\n%-\\nX +. ds an-page-string \\nX\\n[an-page-letter] +.\}\} +.ie \\nD \{\ +. if o .tl '\\*[an-extra2]'\\*[an-extra1]'\\*[an-page-string]' +. if e .tl '\\*[an-page-string]'\\*[an-extra1]'\\*[an-extra2]' +.\} +.el .tl '\\*[an-extra2]'\\*[an-extra1]'\\*[an-page-string]' +.ev +.. +.de SH +.sp \\n[PD]u +.nr an-level 1 +.nr an-margin \\n[IN] +.nr an-prevailing-indent \\n[IN] +.fi +.in \\n[IN]u +.ti 0 +.it 1 an-trap +.nr an-no-space-flag 1 +.nr an-break-flag 1 +.ps \\n[PS]-1 +.ft B +.ne 2v+1u +.if \\n[.$] \&\\$* +.. +.de SS +.sp \\n[PD]u +.nr an-level 1 +.nr an-margin \\n[IN] +.nr an-prevailing-indent \\n[IN] +.fi +.in \\n[IN]u +.ti \\n[SN]u +.it 1 an-trap +.nr an-no-space-flag 1 +.nr an-break-flag 1 +.ps \\n[PS] +.ft B +.ne 2v+1u +.if \\n[.$] \&\\$* +.. +.de B +.it 1 an-trap +.ft B +.if \\n[.$] \&\\$* +.. +.de I +.it 1 an-trap +.ft I +.if \\n[.$] \&\\$* +.. +.de SM +.it 1 an-trap +.ps -1 +.if \\n[.$] \&\\$* +.. +.de SB +.it 1 an-trap +.ps -1 +.ft B +.if \\n[.$] \&\\$* +.. +.de TP +.sp \\n[PD]u +.if \\n[.$] .nr an-prevailing-indent (n;\\$1) +.it 1 an-trap +.if !\\n[an-div?] .di an-div +.in 0 +.nr an-div? 1 +.. +.de an-trap +.ft R +.ps \\n[PS] +.if \\n[an-break-flag] \{\ +. br +. nr an-break-flag 0 +.\} +.if \\n[an-no-space-flag] \{\ +. ns +. nr an-no-space-flag 0 +.\} +.if \\n[an-div?] .an-do-tag +.. +.de an-do-tag +.nr an-div? 0 +.br +.di +.in \\n[an-margin]u+\\n[an-prevailing-indent]u +.ti -\\n[an-prevailing-indent]u +.ie \\n[dl]+\\n[an-tag-sep]>\\n[an-prevailing-indent] \{\ +. ne 2v+1u +. an-div +. br +.\} +.el \{\ +. chop an-div +. ne 1v+1u +\\*[an-div]\\h'|\\n[an-prevailing-indent]u'\c +.\} +.. +.de LP +.br +.sp \\n[PD]u +.ps \\n[PS] +.ft R +.in \\n[an-margin]u +.nr an-prevailing-indent \\n[IN] +.. +.als PP LP +.als P LP +.de IP +.ie !\\n[.$] \{\ +. ps \\n[PS] +. ft R +. sp \\n[PD]u +. ne 1v+1u +. in \\n[an-margin]u+\\n[an-prevailing-indent]u +.\} +.el \{\ +. ie \\n[.$]-1 .TP "\\$2" +. el .TP +\&\\$1 +.\} +.. +.de HP +.ps \\n[PS] +.ft R +.sp \\n[PD]u +.ne 1v+1u +.if \\n[.$] .nr an-prevailing-indent (n;\\$1) +.in \\n[an-margin]u+\\n[an-prevailing-indent]u +.ti \\n[an-margin]u +.. +.de RI +.if \\n[.$] \{\ +. ds an-result \&\\$1 +. shift +. while \\n[.$]>=2 \{\ +. as an-result \,\fI\\$1\fR\/\\$2 +. shift 2 +. \} +. if \\n[.$] .as an-result \,\fI\\$1\fR +\\*[an-result] +.\} +.. +.de IR +.if \\n[.$] \{\ +. ds an-result \&\fI\\$1\fR +. shift +. while \\n[.$]>=2 \{\ +. as an-result \/\\$1\fI\,\\$2\fR +. shift 2 +. \} +. if \\n[.$] .as an-result \/\\$1 +\\*[an-result] +.\} +.. +.de IB +.if \\n[.$] \{\ +. ds an-result \&\fI\\$1 +. shift +. while \\n[.$]>=2 \{\ +. as an-result \/\\fB\\$1\fI\,\\$2 +. shift 2 +. \} +. if \\n[.$] .as an-result \/\\fB\\$1 +\\*[an-result] +. ft R +.\} +.. +.de BI +.if \\n[.$] \{\ +. ds an-result \&\fB\\$1 +. shift +. while \\n[.$]>=2 \{\ +. as an-result \,\fI\\$1\fB\/\\$2 +. shift 2 +. \} +. if \\n[.$] .as an-result \,\fI\\$1 +\\*[an-result] +. ft R +.\} +.. +.de RB +.ds an-result \& +.while \\n[.$]>=2 \{\ +. as an-result \fR\\$1\fB\\$2 +. shift 2 +.\} +.if \\n[.$] .as an-result \fR\\$1 +\\*[an-result] +.ft R +.. +.de BR +.ds an-result \& +.while \\n[.$]>=2 \{\ +. as an-result \fB\\$1\fR\\$2 +. shift 2 +.\} +.if \\n[.$] .as an-result \fB\\$1 +\\*[an-result] +.ft R +.. +.de RS +.br +.nr an-saved-margin\\n[an-level] \\n[an-margin] +.nr an-saved-prevailing-indent\\n[an-level] \\n[an-prevailing-indent] +.ie \\n[.$] .nr an-margin +(n;\\$1) +.el .nr an-margin +\\n[an-prevailing-indent] +.in \\n[an-margin]u +.nr an-prevailing-indent \\n[IN] +.nr an-level +1 +.. +.de RE +.br +.ie \\n[.$] .nr an-level (;\\$1)<?\\n[an-level] +.el .nr an-level -1 +.nr an-level 1>?\\n[an-level] +.nr an-margin \\n[an-saved-margin\\n[an-level]] +.nr an-prevailing-indent \\n[an-saved-prevailing-indent\\n[an-level]] +.in \\n[an-margin]u +.. +.ds S \s[\\n[PS]] +.ie c\[rg] .ds R \[rg] +.el .ds R (Reg.) +.ie c\[tm] .ds Tm \[tm] +.el .ds Tm (TM) +.ds lq \(lq +.ds rq \(rq +.hy 14 +.\" Load local modifications. +.mso man.local +.cp \n(_C diff --git a/gnu/usr.bin/groff/tmac/tmac.dvi b/gnu/usr.bin/groff/tmac/tmac.dvi new file mode 100644 index 00000000000..c64fc73ce73 --- /dev/null +++ b/gnu/usr.bin/groff/tmac/tmac.dvi @@ -0,0 +1,132 @@ +.nr _C \n(.C +.cp 0 +.ftr CR CW +.ftr C CW +.ftr TT CW +.ftr HR H +.\" This uses the dvi-char_1 string in font CW, dvi-char_0 otherwise. +.char _ \R'dvi-char_ \\n(.f=\f(CW\\n(.f\fP'\\*[dvi-char_\\n[dvi-char_]] +.char \[ul] \R'dvi-char_ \w'M'=\w'i''\\*[dvi-char_\\n[dvi-char_]] +.\" Normally use a rule. +.ds dvi-char_0 \v'.23m'\D'R .5m .04m'\v'-.04m'\v'-.23m' +.\" In font CW use a real _ character. +.ds dvi-char_1 _ +.if !c\[rn] .char \[rn] \D'R .5m -.04m'\v'.04m' +.if !c\[br] .char \[br] \Z'\v'.25m'\D'R .04m -1m'' +.if !c\[ru] .char \[ru] \v'-.02m'\D'R .5m .04m'\v'-.04m'\v'.02m' +.if !c\[co] .char \[co] \z\(ci\h'\w'\(ci'u-\w'c'u/2u'c\h'\w'\(ci'u-\w'c'u/2u' +.if !c\[rg] .char \[rg] \z\(ci\h'\w'\(ci'u-\w'r'u/2u'r\h'\w'\(ci'u-\w'r'u/2u' +.if !c\[fm] .char \[fm] \v'-.35m'\s[\\n(.s*7u/10u]\[prime]\s0\v'.35m' +.if !c\[de] .char \[de] \h'.05m'\v'-.54m'\D'c .3m'\v'.54m'\h'.05m' +.if !c\[ct] .char \[ct] \o'c/' +.if !c\[sq] .char \[sq] \Z'\h'.05m'\D'R .4m -.04m'\v'.04m'\h'-.04m'\ +\D'R .04m -.4m'\v'.04m'\D'R -.4m -.04m'\D'R .04m .4m''\h'.5m' +.\"char \[sq] \h'.05m'\D'l .4m 0'\D'l 0 -.4m'\D'l -.4m 0'\D'l 0 .4m'\h'.45m' +.if !c\[!=] .char \[!=] \[slashnot]\(eq +.if !c\[tm] .char \[tm] \v'-.3m'\s[\\n(.s/2u]TM\s0\v'.3m' +.if !c\[aq] .char \[aq] ' +.if !c\[bq] .char \[bq] , +.if !c\[Bq] .char \[Bq] ,\h'\w'\(rq'u-(2u*\w"'"u)', +.if !c\[ho] .char \[ho] \s[\En[.s]/2u]\v'.4m'c\v'-.4m'\s0 +.if !c\[-D] .char \[-D] \Z'\v'-.1m'\h'.05m'-'D +.if !c\[Sd] .char \[Sd] \Z'\v'-.3m'\h'.35m'-'\(pd +.if !c\[TP] .char \[TP] I\h'-.25m'\v'-.33m'\s[\En[.s]*6u/10u]\v'.33m'D\ +\v'-.33m'\s0\v'.33m' +.if !c\[Tp] .char \[Tp] \zlp +.cflags 8 \(an +.if !c\[an] .char \[an] \h'-.167m'\(mi\h'-.167m' +.\" Define some fractions. +.de dvi-frac +.if !c\[\\$1\\$2] .char \[\\$1\\$2] \ +\v'-.25m'\s[\\\\n(.s*7u/10u]\\$1\s0\v'.25m'\h'-.2m'\ +/\h'-.2m'\v'.25m'\s[\\\\n(.s*7u/10u]\\$2\s0\v'-.25m' +.. +.dvi-frac 1 2 +.dvi-frac 3 4 +.dvi-frac 1 4 +.dvi-frac 1 8 +.dvi-frac 3 8 +.dvi-frac 5 8 +.dvi-frac 7 8 +.\" support for ISO Latin-1 +.if !c\[S1] .char \[S1] \v'-.2m'\s-31\s+3\v'+.2m' +.if !c\[S2] .char \[S2] \v'-.2m'\s-32\s+3\v'+.2m' +.if !c\[S3] .char \[S3] \v'-.2m'\s-33\s+3\v'+.2m' +.if !c\[Of] .char \[Of] \v'-.2m'\s'\En(.s*6u/10u'\o'_a'\s0\v'.2m' +.if !c\[Om] .char \[Om] \v'-.2m'\s'\En(.s*6u/10u'\o'_o'\s0\v'.2m' +.if !c\[Fo] .char \[Fo] << +.if !c\[Fc] .char \[Fc] >> +.if !c\[bb] .char \[bb] | +.if !c\[Ye] .char \[Ye] \o'-Y' +.if !c\[Cs] .char \[Cs] \o'\[mu]o' +.de dvi-achar +.\" Note that character definitions are always interpreted with +.\" compatibility mode off. +.if !c\\$1 \{\ +.char \\$1 \\$3\ +\k[acc]\ +\h'(u;-\w'\\$2'-\w'\\$3'/2+\\\\n[skw]+(\w'x'*0)-\\\\n[skw])'\ +\v'(u;\w'x'*0+\\\\n[rst]+(\w'\\$3'*0)-\\\\n[rst])'\ +\\$2\ +\v'(u;\w'x'*0-\\\\n[rst]+(\w'\\$3'*0)+\\\\n[rst])'\ +\h'|\\\\n[acc]u' +.\} +.hcode \\$1\\$4 +.. +.dvi-achar \(`A \` A a +.dvi-achar \('A \' A a +.dvi-achar \(^A ^ A a +.dvi-achar \(~A ~ A a +.dvi-achar \(:A \(ad A a +.dvi-achar \(oA \(ao A a +.dvi-achar \(`E \` E e +.dvi-achar \('E \' E e +.dvi-achar \(^E ^ E e +.dvi-achar \(:E \(ad E e +.dvi-achar \(`I \` I i +.dvi-achar \('I \' I i +.dvi-achar \(^I ^ I i +.dvi-achar \(:I \(ad I i +.dvi-achar \(~N ~ N n +.dvi-achar \(`O \` O o +.dvi-achar \('O \' O o +.dvi-achar \(^O ^ O o +.dvi-achar \(~O ~ O o +.dvi-achar \(:O \(ad O o +.dvi-achar \(`U \` U u +.dvi-achar \('U \' U u +.dvi-achar \(^U ^ U u +.dvi-achar \(:U \(ad U u +.dvi-achar \('Y \' Y y +.dvi-achar \(`a \` a a +.dvi-achar \('a \' a a +.dvi-achar \(^a ^ a a +.dvi-achar \(~a ~ a a +.dvi-achar \(:a \(ad a a +.dvi-achar \(oa \(ao a a +.dvi-achar \(`e \` e e +.dvi-achar \('e \' e e +.dvi-achar \(^e ^ e e +.dvi-achar \(:e \(ad e e +.dvi-achar \(`i \` \(.i i +.dvi-achar \('i \' \(.i i +.dvi-achar \(^i ^ \(.i i +.dvi-achar \(:i \(ad \(.i i +.dvi-achar \(~n ~ n n +.dvi-achar \(`o \` o o +.dvi-achar \('o \' o o +.dvi-achar \(^o ^ o o +.dvi-achar \(~o ~ o o +.dvi-achar \(:o \(ad o o +.dvi-achar \(`u \` u u +.dvi-achar \('u \' u u +.dvi-achar \(^u ^ u u +.dvi-achar \(:u \(ad u u +.dvi-achar \('y \' y y +.dvi-achar \(:y \(ad y y +.char \(,C \o'\(acc' +.hcode \(,Cc +.char \(,c \o'\(acc' +.hcode \(,cc +.cp \n(_C +.do mso tmac.latin1 diff --git a/gnu/usr.bin/groff/tmac/tmac.latin1 b/gnu/usr.bin/groff/tmac/tmac.latin1 new file mode 100644 index 00000000000..f33ea2164dd --- /dev/null +++ b/gnu/usr.bin/groff/tmac/tmac.latin1 @@ -0,0 +1,101 @@ +.nr _C \n(.C +.cp 0 +.de latin1-tr +.if c\\$2 .if !c\\$1 .tr \\$1\\$2 +.. +.latin1-tr \[char161] \(r! +.latin1-tr \[char162] \(ct +.latin1-tr \[char163] \(Po +.latin1-tr \[char164] \(Cs +.latin1-tr \[char165] \(Ye +.latin1-tr \[char166] \(bb +.latin1-tr \[char167] \(sc +.latin1-tr \[char168] \(ad +.latin1-tr \[char169] \(co +.latin1-tr \[char170] \(Of +.latin1-tr \[char171] \(Fo +.latin1-tr \[char172] \(no +.latin1-tr \[char173] \(hy +.latin1-tr \[char174] \(rg +.latin1-tr \[char175] \(a- +.latin1-tr \[char176] \(de +.latin1-tr \[char177] \(+- +.latin1-tr \[char178] \(S2 +.latin1-tr \[char179] \(S3 +.latin1-tr \[char180] \(aa +.latin1-tr \[char181] \(*m +.latin1-tr \[char182] \(ps +.latin1-tr \[char183] \(md +.latin1-tr \[char184] \(ac +.latin1-tr \[char185] \(S1 +.latin1-tr \[char186] \(Om +.latin1-tr \[char187] \(Fc +.latin1-tr \[char188] \(14 +.latin1-tr \[char189] \(12 +.latin1-tr \[char190] \(34 +.latin1-tr \[char191] \(r? +.latin1-tr \[char192] \(`A +.latin1-tr \[char193] \('A +.latin1-tr \[char194] \(^A +.latin1-tr \[char195] \(~A +.latin1-tr \[char196] \(:A +.latin1-tr \[char197] \(oA +.latin1-tr \[char198] \(AE +.latin1-tr \[char199] \(,C +.latin1-tr \[char200] \(`E +.latin1-tr \[char201] \('E +.latin1-tr \[char202] \(^E +.latin1-tr \[char203] \(:E +.latin1-tr \[char204] \(`I +.latin1-tr \[char205] \('I +.latin1-tr \[char206] \(^I +.latin1-tr \[char207] \(:I +.latin1-tr \[char208] \(-D +.latin1-tr \[char209] \(~N +.latin1-tr \[char210] \(`O +.latin1-tr \[char211] \('O +.latin1-tr \[char212] \(^O +.latin1-tr \[char213] \(~O +.latin1-tr \[char214] \(:O +.latin1-tr \[char215] \(mu +.latin1-tr \[char216] \(/O +.latin1-tr \[char217] \(`U +.latin1-tr \[char218] \('U +.latin1-tr \[char219] \(^U +.latin1-tr \[char220] \(:U +.latin1-tr \[char221] \('Y +.latin1-tr \[char222] \(TP +.latin1-tr \[char223] \(ss +.latin1-tr \[char224] \(`a +.latin1-tr \[char225] \('a +.latin1-tr \[char226] \(^a +.latin1-tr \[char227] \(~a +.latin1-tr \[char228] \(:a +.latin1-tr \[char229] \(oa +.latin1-tr \[char230] \(ae +.latin1-tr \[char231] \(,c +.latin1-tr \[char232] \(`e +.latin1-tr \[char233] \('e +.latin1-tr \[char234] \(^e +.latin1-tr \[char235] \(:e +.latin1-tr \[char236] \(`i +.latin1-tr \[char237] \('i +.latin1-tr \[char238] \(^i +.latin1-tr \[char239] \(:i +.latin1-tr \[char240] \(Sd +.latin1-tr \[char241] \(~n +.latin1-tr \[char242] \(`o +.latin1-tr \[char243] \('o +.latin1-tr \[char244] \(^o +.latin1-tr \[char245] \(~o +.latin1-tr \[char246] \(:o +.latin1-tr \[char247] \(di +.latin1-tr \[char248] \(/o +.latin1-tr \[char249] \(`u +.latin1-tr \[char250] \('u +.latin1-tr \[char251] \(^u +.latin1-tr \[char252] \(:u +.latin1-tr \[char253] \('y +.latin1-tr \[char254] \(Tp +.latin1-tr \[char255] \(:y +.cp \n(_C diff --git a/gnu/usr.bin/groff/tmac/tmac.pic b/gnu/usr.bin/groff/tmac/tmac.pic new file mode 100644 index 00000000000..1177fc09d17 --- /dev/null +++ b/gnu/usr.bin/groff/tmac/tmac.pic @@ -0,0 +1,10 @@ +.de PS +.br +.sp .3v +.ne 0\\$1+1v+\n(.Vu +.in \\n(.lu-\\n(.iu-0\\$2/2u>?0 +.. +.de PE +.in +.sp .3v+.5m +.. diff --git a/gnu/usr.bin/groff/tmac/tmac.ps b/gnu/usr.bin/groff/tmac/tmac.ps new file mode 100644 index 00000000000..d7d655dbad4 --- /dev/null +++ b/gnu/usr.bin/groff/tmac/tmac.ps @@ -0,0 +1,52 @@ +.nr _C \n(.C +.cp 0 +.ftr AX ABI +.ftr KR BMR +.ftr KI BMI +.ftr KB BMB +.ftr KX BMBI +.ftr CW CR +.ftr CO CI +.ftr CX CBI +.ftr H HR +.ftr HO HI +.ftr HX HBI +.ftr Hr HNR +.ftr Hi HNI +.ftr Hb HNB +.ftr Hx HNBI +.ftr NX NBI +.ftr PA PR +.ftr PX PBI +.ftr ZI ZCMI +.ftr C CR +.cflags 8 \(an +.char \(rn \h'-\w'\(sr'u'\(rn\h'\w'\(sr'u' +.char \(mo \h'.08m'\(mo\h'-.08m' +.char \(nm \h'.08m'\(nm\h'-.08m' +.char \[parenlefttp] \[parenlefttp]\h'.016m' +.char \[parenleftbt] \[parenleftbt]\h'.016m' +.char \[parenleftex] \[parenleftex]\h'.016m' +.char \[parenrighttp] \[parenrighttp]\h'.016m' +.char \[parenrightbt] \[parenrightbt]\h'.016m' +.char \[parenrightex] \[parenrightex]\h'.016m' +.if !c\[va] .char \[va] \o'\[ua]\[da]' +.if !c\[ci] \ +.char \[ci] \v'-.25m'\h'.05m'\D'c .5m'\h'.05m'\v'.25m' +.if !c\[sq] \ +.char \[sq] \h'.05m'\D'l .5m 0'\D'l 0 -.5m'\D'l -.5m 0'\D'l 0 .5m'\h'.55m' +.if !c\[ru] .char \[ru] \D'l .5m 0' +.if !c\[ul] .char \[ul] \v'.25m'\D'l .5m 0'\v'-.25m' +.if !c\[br] .char \[br] \Z'\v'.25m'\D'l 0 -1m'' +.if !c\[or] .char \[or] \h'.1m'\Z'\D'l 0 -.675m''\h'.1m' +.if !c\[Fi] .char \[Fi] ffi +.if !c\[Fl] .char \[Fl] ffl +.if !c\[ff] .char \[ff] ff +.if !c\[ij] .char \[ij] ij +.if !c\[IJ] .char \[IJ] IJ +.if !c\[tm] .char \[tm] \s-3\v'-.3m'TM\v'+.3m'\s+3 +.\" pic tests this register to see whether it should use \X'ps:...' +.nr 0p 1 +.cp \n(_C +.if !\n(.C .mso tmac.pspic +.do mso tmac.psold diff --git a/gnu/usr.bin/groff/tmac/tmac.psatk b/gnu/usr.bin/groff/tmac/tmac.psatk new file mode 100644 index 00000000000..b59d23a24e7 --- /dev/null +++ b/gnu/usr.bin/groff/tmac/tmac.psatk @@ -0,0 +1,61 @@ +.\" Implementation of the ATK PB and PE macros for use with groff and grops. +.\" Load this after tmac.atk. +.nr zT 0 +.if '\*(.T'ps' .nr zT 1 +.nr psatk-unit 1p +.de psatk-defs +ps: mdef 5 +/PB { + /saved save def + currentpoint translate + \n[psatk-unit] u -\n[psatk-unit] u scale + userdict begin + /showpage {} def +} bind def +/PE { + end + saved restore +} bind def +/troffadjust { + pop 0 +} bind def +.. +.de PB +.ne \\$1p +.nr zT \\n(zT>0 +\\*[PB\\n(zT]\\ +.. +.de PE +\\*[PE\\n(zT]\\ +.. +.ds PB0 +.\" The last line before the "'PE" is "\}" rather than ".\}". This +.\" would cause a spurious space to be introduced before any picture +.\" that was the first thing on a line. So we have to catch that and +.\" remove it. +.de PB1 +.ev psatk +.fi +.di psatk-mac +\!ps: exec PB +.. +.de PE0 +\v'-.75m'\ +\D'l \\$1p 0'\D'l 0 \\$2p'\D'l -\\$1p 0'\D'l 0 -\\$2p'\ +\h'\\$1p'\v'.75m'\x'\\$2p-1m>?0'\c +.. +.ds psatk-init \Y[psatk-defs] +.de PE1 +\!PE +.di +.di null +.br +.di +.rm null +.ev +\v'-.75m'\ +\\*[psatk-init]\Y[psatk-mac]\ +\h'\\$1p'\v'.75m'\x'\\$2p-1m>?0'\c +.rm psatk-mac +.if \\n(.P .ds psatk-init +.. diff --git a/gnu/usr.bin/groff/tmac/tmac.psfig b/gnu/usr.bin/groff/tmac/tmac.psfig new file mode 100644 index 00000000000..5f4111ce6a1 --- /dev/null +++ b/gnu/usr.bin/groff/tmac/tmac.psfig @@ -0,0 +1,87 @@ +.\" These are macros to make psfig work with groff. +.\" They require that psfig be patched as described in ../grops/psfig.diff. +.de psfig-defs +ps: mdef 100 + +% wid ht llx lly urx ury psfigstart - + +/psfigstart { + /level1 save def + /ury exch def + /urx exch def + /lly exch def + /llx exch def + /ht exch u def + /wid exch u def + currentpoint ht add translate + wid urx llx sub div ht ury lly sub div neg scale + llx neg lly neg translate + + % set the graphics state to default values + 0 setgray + 0 setlinecap + 1 setlinewidth + 0 setlinejoin + 10 setmiterlimit + [] 0 setdash + newpath + /showpage {} def +} bind def + +% psfigclip - + +/psfigclip { + currentpoint newpath + llx lly moveto + urx lly lineto + urx ury lineto + llx ury lineto + closepath clip + newpath moveto +} bind def + +% psfigend - + +/psfigend { + level1 restore +} bind def + +% globalstart - + +/globalstart { + % save the current space code on the stack + SC + level0 restore +} bind def + +% globalend - + +/globalend { + end + BP + /SC exch def + DEFS begin +} bind def +.. +.de psfig-init +.if \\n[.P] \{\ +\Y[psfig-defs] +. br +. sp -1 +. ds psfig-init\" empty +. rm psfig-defs +.\} +.. +.de F+ +.br +.psfig-init +.nr psfig-fill \\n[.u] +.nf +.sp -.5 +.if !\\n[.$] .ce 9999 +.. +.de F- +.br +.ce 0 +.if \\n[psfig-fill] .fi +.. diff --git a/gnu/usr.bin/groff/tmac/tmac.psnew b/gnu/usr.bin/groff/tmac/tmac.psnew new file mode 100644 index 00000000000..e13bdb88696 --- /dev/null +++ b/gnu/usr.bin/groff/tmac/tmac.psnew @@ -0,0 +1,26 @@ +.\" Undo the effect of tmac.psold. This gives access to the additional +.\" characters that are present in the text fonts of newer PostScript +.\" printers. It is a bad idea to use this if you are going to +.\" distribute the resulting PostScript output to others. +.nr _C \n(.C +.cp 0 +.rchar \('y\('Y\(12\(14\(34\(S1\(S2\(S3\(bb\(de\(Tp\(TP\(-D\(Sd +.tr \[char166]\[char166] +.tr \[char176]\[char176] +.tr \[char177]\[char177] +.tr \[char178]\[char178] +.tr \[char179]\[char179] +.tr \[char181]\[char181] +.tr \[char185]\[char185] +.tr \[char188]\[char188] +.tr \[char189]\[char189] +.tr \[char190]\[char190] +.tr \[char208]\[char208] +.tr \[char215]\[char215] +.tr \[char221]\[char221] +.tr \[char222]\[char222] +.tr \[char240]\[char240] +.tr \[char247]\[char247] +.tr \[char253]\[char253] +.tr \[char254]\[char254] +.cp \n(_C diff --git a/gnu/usr.bin/groff/tmac/tmac.psold b/gnu/usr.bin/groff/tmac/tmac.psold new file mode 100644 index 00000000000..04a5f6df49f --- /dev/null +++ b/gnu/usr.bin/groff/tmac/tmac.psold @@ -0,0 +1,60 @@ +.\" In the newer PostScript printers, the text fonts contain all ISO Latin-1 +.\" characters. The font description files that comes with groff match +.\" these fonts. The text fonts in older PostScript printers are missing +.\" some of these characters. This file prevents those characters from +.\" being used. This will allow the PostScript output to be printed on both +.\" old and new printers. The effect of this file can be undone by +.\" tmac.psnew. +.nr _C \n(.C +.cp 0 +.\" Define an accented character. +.de ps-achar +.\" Note that character definitions are always interpreted with +.\" compatibility mode off. +.char \\$1 \\$3\ +\k[acc]\ +\h'(u;-\w'\\$2'-\w'\\$3'/2+\\\\n[skw]+(\w'x'*0)-\\\\n[skw])'\ +\v'(u;\w'x'*0+\\\\n[rst]+(\w'\\$3'*0)-\\\\n[rst])'\ +\\$2\ +\v'(u;\w'x'*0-\\\\n[rst]+(\w'\\$3'*0)+\\\\n[rst])'\ +\h'|\\\\n[acc]u' +.ie '\\$3'\(.i' .hcode \\$1i +.el .hcode \\$1\\$3 +.. +.ps-achar \['y] \(aa y +.ps-achar \['Y] \(aa Y +.char \[12] \v'-.7m\s[\\n(.s*6u/10u]+.7m'1\v'-.7m\s0+.7m'\ +\(f/\s[\\n(.s*6u/10u]2\s0 +.char \[14] \v'-.7m\s[\\n(.s*6u/10u]+.7m'1\v'-.7m\s0+.7m'\ +\(f/\s[\\n(.s*6u/10u]4\s0 +.char \[34] \v'-.7m\s[\\n(.s*6u/10u]+.7m'3\v'-.7m\s0+.7m'\ +\(f/\s[\\n(.s*6u/10u]4\s0 +.char \[S1] \v'-.2m'\s-31\s+3\v'+.2m' +.char \[S2] \v'-.2m'\s-32\s+3\v'+.2m' +.char \[S3] \v'-.2m'\s-33\s+3\v'+.2m' +.char \[bb] | +.char \[de] \fS\(de +.char \[-D] \Z'\v'-.1m'-'D +.char \[TP] \ +I\h'-.25m'\v'-.33m'\s'\En(.s*6u/10u'\v'.33m'D\v'-.33m'\s0\v'.33m' +.char \[Sd] \Z'\v'-.3m'\h'.2m'-'\(pd +.char \[Tp] \zlp +.tr \[char166]\[bb] +.tr \[char176]\[de] +.tr \[char177]\[+-] +.tr \[char178]\[S2] +.tr \[char179]\[S3] +.tr \[char181]\[*m] +.tr \[char185]\[S1] +.tr \[char188]\[14] +.tr \[char189]\[12] +.tr \[char190]\[34] +.tr \[char208]\[-D] +.tr \[char215]\[mu] +.tr \[char221]\['Y] +.tr \[char222]\[TP] +.tr \[char240]\[Sd] +.tr \[char247]\[di] +.tr \[char253]\['y] +.tr \[char254]\[Tp] +.cp \n(_C diff --git a/gnu/usr.bin/groff/tmac/tmac.pspic b/gnu/usr.bin/groff/tmac/tmac.pspic new file mode 100644 index 00000000000..9923907ff71 --- /dev/null +++ b/gnu/usr.bin/groff/tmac/tmac.pspic @@ -0,0 +1,41 @@ +.\" Define the PSPIC macro. +.\" When used other than with -Tps, it will draw a box around where +.\" the picture would go. +.de ps-bb +.nr ps-nargs \\n[.$] +.if \\n[ps-nargs]=4 \{\ +. nr ps-llx 0\\$1 +. nr ps-lly 0\\$2 +. nr ps-urx 0\\$3 +. nr ps-ury 0\\$4 +.\} +.. +.de PSPIC +.br +.sy echo .ps-bb `psbb \\$1` >/tmp/psbb\\n[$$] +.so /tmp/psbb\\n[$$] +.if \\n[ps-nargs]=4 \{\ +. nr ps-wid (\\n[ps-urx]-\\n[ps-llx]) +. nr ps-ht (\\n[ps-ury]-\\n[ps-lly]) +. if \\n[ps-wid]<0 .nr ps-wid 0-\\n[ps-wid] +. if \\n[ps-ht]<0 .nr ps-ht 0-\\n[ps-ht] +. ie \\n[.$]>=2 .nr ps-deswid (i;\\$2) +. el .nr ps-deswid \\n[.l]-\\n[.i]<?\\n[ps-wid]p +. ie \\n[.$]>=3 .nr ps-desht (i;\\$3) +. el .nr ps-desht \\n[ps-deswid]*1000+(\\n[ps-wid]/2)/\\n[ps-wid]\ +*\\n[ps-ht]+500/1000 +. ne \\n[ps-desht]u+1v +. nr ps-offset \\n[.l]-\\n[.i]-\\n[ps-deswid]/2 +. ie \\n[.$]>=3 .ds ps-desht \\n[ps-desht] +. el .ds ps-desht \" empty +\h'\\n[ps-offset]u'\ +\X'ps: invis'\ +\Z'\D'p 0 \\n[ps-desht]u \\n[ps-deswid]u 0 0 -\\n[ps-desht]u''\ +\X'ps: endinvis'\ +\v'\\n[ps-desht]u'\X'ps: import \\$1 \ +\\n[ps-llx] \\n[ps-lly] \\n[ps-urx] \\n[ps-ury] \\n[ps-deswid] \\*[ps-desht]' +. br +. sp \\n[ps-desht]u +.\} +.sy rm /tmp/psbb\\n[$$] +.. diff --git a/gnu/usr.bin/groff/tmac/tmac.s b/gnu/usr.bin/groff/tmac/tmac.s new file mode 100644 index 00000000000..9afb7e6f0bf --- /dev/null +++ b/gnu/usr.bin/groff/tmac/tmac.s @@ -0,0 +1,1803 @@ +.ig +Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +This file is part of groff. + +groff is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. + +groff is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License along +with groff; see the file COPYING. If not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +.. +.if !\n(.g .ab These ms macros require groff. +.if \n(.C \ +. ab The groff ms macros do not work in compatibility mode. +.\" Enable warnings. You can delete this if you want. +.warn +.\" See if already loaded. +.if r GS .nx +.nr GS 1 +.de @error +.tm \\n(.F:\\n(.c: macro error: \\$* +.. +.de @warning +.tm \\n(.F:\\n(.c: macro warning: \\$* +.. +.de @fatal +.ab \\n(.F:\\n(.c: fatal macro error: \\$* +.. +.de @not-implemented +.@error sorry, \\$0 not implemented +.als \\$0 @nop +.. +.als TM @not-implemented +.als CT @not-implemented +.de @nop +.. +.de @init +.\" a non-empty environment +.ev ne +\c +.ev +.ev nf +'nf +.ev +.. +.ds REFERENCES References +.ds ABSTRACT ABSTRACT +.ds TOC Table of Contents +.ds MONTH1 January +.ds MONTH2 February +.ds MONTH3 March +.ds MONTH4 April +.ds MONTH5 May +.ds MONTH6 June +.ds MONTH7 July +.ds MONTH8 August +.ds MONTH9 September +.ds MONTH10 October +.ds MONTH11 November +.ds MONTH12 December +.ds MO \\*[MONTH\n[mo]] +.nr *year \n[yr]+1900 +.ds DY \n[dy] \*[MO] \n[*year] +.de ND +.if \\n[.$] .ds DY "\\$* +.. +.de DA +.if \\n[.$] .ds DY "\\$* +.ds CF \\*[DY] +.. +.\" indexing +.de IX +.tm \\$1\t\\$2\t\\$3\t\\$4 ... \\n[PN] +.. +.\" print an error message and then try to recover +.de @error-recover +.@error \\$@ (recovering) +.nr *pop-count 0 +.while !'\\n(.z'' \{\ +. \"@warning automatically terminating diversion \\n(.z +. ie d @div-end!\\n(.z .@div-end!\\n(.z +. el .*div-end-default +. nr *pop-count +1 +. \" ensure that we don't loop forever +. if \\n[*pop-count]>20 .@fatal recovery failed +.\} +.while !'\\n[.ev]'0' .ev +.par@reset-env +.par@reset +.. +.de *div-end-default +.ds *last-div \\n(.z +.br +.di +.ev nf +.\\*[*last-div] +.ev +.. +.\" **************************** +.\" ******** module cov ******** +.\" **************************** +.\" Cover sheet and first page. +.de cov*err-not-after-first-page +.@error \\$0 is not allowed after the first page has started +.. +.de cov*err-not-before-tl +.@error \\$0 is not allowed before TL +.. +.de cov*err-not-again +.@error \\$0 is not allowed more than once +.. +.de cov*err-not-after-ab +.@error \\$0 is not allowed after first AB, LP, PP, IP, SH or NH +.. +.als AU cov*err-not-before-tl +.als AI cov*err-not-before-tl +.als AB cov*err-not-before-tl +.de cov*first-page-init +.rm cov*first-page-init +.par@init +.als RP cov*err-not-after-first-page +.@init +.ie \\n[cov*rp-format] \{\ +. pg@cs-top +. als FS cov*FS +. als FE cov*FE +.\} +.el \{\ +. pg@top +. als FS @FS +. als FE @FE +.\} +.wh 0 pg@top +.. +.wh 0 cov*first-page-init +.\" This handles the case where FS occurs before TL or LP. +.de FS +.br +\\*[FS]\\ +.. +.nr cov*rp-format 0 +.nr cov*rp-no 0 +.\" released paper format +.de RP +.nr cov*rp-format 1 +.if \\n[.$] .if '\\$1'no' .nr cov*rp-no 1 +.pn 0 +.. +.de TL +.br +.als TL cov*err-not-again +.rn @AB AB +.rn @AU AU +.rn @AI AI +.di cov*tl-div +.par@reset +.ft B +.ps +2 +.vs +3p +.ll (u;\\n[LL]*5/6) +.nr cov*n-au 0 +.. +.de @AU +.par@reset +.if !'\\n(.z'' \{\ +. br +. di +.\} +.nr cov*n-au +1 +.di cov*au-div!\\n[cov*n-au] +.nf +.ft I +.ps \\n[PS] +.. +.de @AI +.par@reset +.if !'\\n(.z'' \{\ +. br +. di +.\} +.ie !\\n[cov*n-au] .@error AI before AU +.el \{\ +. di cov*ai-div!\\n[cov*n-au] +. nf +. ft R +. ps \\n[PS] +.\} +.. +.de LP +.if !'\\n[.z]'' \{\ +. br +. di +.\} +.br +.cov*ab-init +.cov*print +\\*[\\$0]\\ +.. +.als IP LP +.als PP LP +.als XP LP +.als NH LP +.als SH LP +.als MC LP +.als RT LP +.als XS LP +.de cov*ab-init +.als cov*ab-init @nop +.als LP @LP +.als IP @IP +.als PP @PP +.als XP @XP +.als RT @RT +.als XS @XS +.als SH @SH +.als NH @NH +.als QP @QP +.als RS @RS +.als RE @RE +.als QS @QS +.als QE @QE +.als MC @MC +.als EQ @EQ +.als EN @EN +.als AB cov*err-not-after-ab +.als AU par@AU +.als AI par@AI +.als TL par@TL +.. +.de @AB +.if !'\\n(.z'' \{\ +. br +. di +.\} +.cov*ab-init +.di cov*ab-div +.par@ab-indent +.par@reset +.if !'\\$1'no' \{\ +. ft I +. ce 1 +\\*[ABSTRACT] +. sp +. ft R +.\} +.ns +.@PP +.. +.de AE +.ie '\\n(.z'cov*ab-div' \{\ +. als AE cov*err-not-again +. br +. di +.\" nr cov*ab-height \\n[dn] +. par@reset-env +. par@reset +. cov*print +.\} +.el .@error AE without AB +.. +.de @div-end!cov*ab-div +.AE +.. +.de cov*print +.als cov*print @nop +.ie d cov*tl-div \{\ +. ie \\n[cov*rp-format] .cov*rp-print +. el .cov*draft-print +.\} +.el \{\ +. if \\n[cov*rp-format] \{\ +. @warning RP format but no TL +. bp 1 +. als FS @FS +. als FE @FE +. \} +. br +.\} +.. +.de cov*rp-print +.nr cov*page-length \\n[.p] +.pl 1000i +.cov*tl-au-print +.sp 3 +.if d cov*ab-div \{\ +. nf +. cov*ab-div +.\} +.sp 3 +.par@reset +\\*[DY] +.br +.if \\n[cov*fn-height] \{\ +. sp |(u;\\n[cov*page-length]-\\n[FM]\ +-\\n[cov*fn-height]-\\n[fn@sep-dist]>?\\n[nl]) +. fn@print-sep +. ev nf +. cov*fn-div +. ev +. ie \\n[cov*rp-no] .rm cov*fn-div +. el \{\ +. rn cov*fn-div fn@overflow-div +. nr fn@have-overflow 1 +. \} +.\} +.als FS @FS +.als FE @FE +.\" If anything was printed below where the footer line is normally printed, +.\" then that's an overflow. +.if -\\n[FM]/2+1v+\\n[cov*page-length]<\\n[nl] .@error cover sheet overflow +.pl \\n[cov*page-length]u +.bp 1 +.if !\\n[cov*rp-no] .cov*tl-au-print +.rs +.sp 1 +.. +.de cov*draft-print +.cov*tl-au-print +.if d cov*ab-div \{\ +. nf +. sp 2 +. cov*ab-div +.\} +.sp 1 +.. +.de cov*tl-au-print +.par@reset +.nf +.rs +.sp 3 +.ce 9999 +.cov*tl-div +.nr cov*i 1 +.nr cov*sp 1v +.while \\n[cov*i]<=\\n[cov*n-au] \{\ +. sp \\n[cov*sp]u +. cov*au-div!\\n[cov*i] +. ie d cov*ai-div!\\n[cov*i] \{\ +. sp .5v +. cov*ai-div!\\n[cov*i] +. nr cov*sp 1v +. \} +. el .nr cov*sp .5v +. nr cov*i +1 +.\} +.ce 0 +.. +.nr cov*fn-height 0 +.nr cov*in-fn 0 +.\" start of footnote on cover +.de cov*FS +.if \\n[cov*in-fn] \{\ +. @error nested FS +. FE +.\} +.nr cov*in-fn 1 +.ev fn +.par@reset-env +.da cov*fn-div +.if !\\n[cov*fn-height] .ns +.ie \\n[.$] .FP "\\$1" no +.el .@LP +.. +.de @div-end!cov*fn-div +.cov*FE +.. +.\" end of footnote on cover +.de cov*FE +.ie '\\n(.z'cov*fn-div' \{\ +. br +. ev +. di +. nr cov*in-fn 0 +. nr cov*fn-height +\\n[dn] +.\} +.el .@error FE without matching FS +.. +.\" *************************** +.\" ******** module pg ******** +.\" *************************** +.\" Page-level formatting. +.\" > 0 if we have a footnote on the current page +.nr pg@fn-flag 0 +.nr pg@colw 0 +.nr pg@fn-colw 0 +.nr HM 1i +.nr FM 1i +.nr PO 1i +.ds LF +.ds CF +.ds RF +.ds LH +.ds CH -\\n[PN]- +.ds RH +.ds pg*OH '\\*[LH]'\\*[CH]'\\*[RH]' +.ds pg*EH '\\*[LH]'\\*[CH]'\\*[RH]' +.ds pg*OF '\\*[LF]'\\*[CF]'\\*[RF]' +.ds pg*EF '\\*[LF]'\\*[CF]'\\*[RF]' +.de OH +.ds pg*\\$0 "\\$* +.. +.als EH OH +.als OF OH +.als EF OH +.de PT +.ie \\n%=1 .if \\n[pg*P1] .tl \\*[pg*OH] +.el \{\ +. ie o .tl \\*[pg*OH] +. el .tl \\*[pg*EH] +.\} +.. +.de BT +.ie o .tl \\*[pg*OF] +.el .tl \\*[pg*EF] +.. +.nr pg*P1 0 +.de P1 +.nr pg*P1 1 +.. +.wh -\n[FM]u pg@bottom +.wh -\n[FM]u/2u pg*footer +.nr MINGW 2n +.nr pg@ncols 1 +.de @MC +.if !'\\n(.z'' .error-recover MC while diversion open +.br +.ie \\n[pg@ncols]>1 .pg@super-eject +.el \{\ +. \" flush out any floating keeps +. while \\n[kp@tail]>\\n[kp@head] \{\ +. rs +. bp +. \} +.\} +.ie !\\n(.$ \{\ +. nr pg@colw \\n[LL]*7/15 +. nr pg*gutw \\n[LL]-(2*\\n[pg@colw]) +. nr pg@ncols 2 +.\} +.el \{\ +. nr pg@colw (n;\\$1)<?\\n[LL] +. ie \\n[.$]<2 .nr pg*gutw \\n[MINGW] +. el .nr pg*gutw (n;\\$2) +. nr pg@ncols \\n[LL]-\\n[pg@colw]/(\\n[pg@colw]+\\n[pg*gutw])+1 +. ie \\n[pg@ncols]>1 \ +. nr pg*gutw \\n[LL]-(\\n[pg@ncols]*\\n[pg@colw])/(\\n[pg@ncols]-1) +. el .nr pg*gutw 0 +.\} +.mk pg*col-top +.ns +.nr pg*col-num 0 +.nr pg@fn-colw \\n[pg@colw]*5/6 +.par@reset +.. +.de 2C +.MC +.. +.de 1C +.MC \\n[LL]u +.. +.\" top of page macro +.de pg@top +.ch pg*footer -\\n[FM]u/2u +.nr PN \\n% +.nr pg*col-num 0 +.nr pg@fn-bottom-margin 0 +.nr pg*saved-po \\n[PO] +.po \\n[PO]u +.ev h +.par@reset +.sp (u;\\n[HM]/2) +.PT +.sp |\\n[HM]u +.if d HD .HD +.mk pg@header-bottom +.ev +.mk pg*col-top +.pg*start-col +.. +.de pg*start-col +.\" Handle footnote overflow before floating keeps, because the keep +.\" might contain an embedded footnote. +.fn@top-hook +.kp@top-hook +.tbl@top-hook +.ns +.. +.de pg@cs-top +.sp \\n[HM]u +.\" move pg@bottom and pg*footer out of the way +.ch pg@bottom \\n[.p]u*2u +.ch pg*footer \\n[.p]u*2u +.ns +.. +.de pg@bottom +.tbl@bottom-hook +.if \\n[pg@fn-flag] .fn@bottom-hook +.nr pg*col-num +1 +.ie \\n[pg*col-num]<\\n[pg@ncols] .pg*end-col +.el .pg*end-page +.. +.de pg*end-col +'sp |\\n[pg*col-top]u +.po (u;\\n[pg*saved-po]+(\\n[pg@colw]+\\n[pg*gutw]*\\n[pg*col-num])) +.\"po +(u;\\n[pg@colw]+\\n[pg*gutw]) +.pg*start-col +.. +.de pg*end-page +.po \\n[pg*saved-po]u +.\" Make sure we don't exit if there are still floats or footnotes left-over. +.ie \\n[kp@head]<\\n[kp@tail]:\\n[fn@have-overflow] \{\ +. \" Switching environments ensures that we don't get an unnecessary +. \" blank line at the top of the page. +. ev ne +' bp +. ev +.\} +.el \{\ +. \" If the text has ended and there are no more footnotes or keeps, exit. +. if \\n[pg@text-ended] .ex +. if r pg*next-number \{\ +. pn \\n[pg*next-number] +. rr pg*next-number +. if d pg*next-format \{\ +. af PN \\*[pg*next-format] +. rm pg*next-format +. \} +. \} +' bp +.\} +.. +.\" pg@begin number format +.de pg@begin +.ie \\n[.$]>0 \{\ +. nr pg*next-number (;\\$1) +. ie \\n[.$]>1 .ds pg*next-format \\$2 +. el .rm pg*next-format +.\} +.el .rr pg*next-number +.pg@super-eject +.. +.\" print the footer line +.de pg*footer +.ev h +.par@reset +.BT +.ev +.. +.\" flush out any keeps or footnotes +.de pg@super-eject +.br +.if !'\\n(.z'' .@error-recover diversion open while ejecting page +.\" Make sure we stay in the end macro while there is still footnote overflow +.\" left, or floating keeps. +.while \\n[kp@tail]>\\n[kp@head]:\\n[pg@fn-flag] \{\ +. rs +. bp +.\} +.bp +.. +.nr pg@text-ended 0 +.de pg@end-text +.br +.nr pg@text-ended 1 +.pg@super-eject +.. +.em pg@end-text +.\" *************************** +.\" ******** module fn ******** +.\" *************************** +.\" Footnotes. +.nr fn@sep-dist 8p +.ev fn +.\" Round it vertically +.vs \n[fn@sep-dist]u +.nr fn@sep-dist \n[.v] +.ev +.nr fn*text-num 0 1 +.nr fn*note-num 0 1 +.ds * \\*[par@sup-start]\En+[fn*text-num]\\*[par@sup-end] +.nr fn*open 0 +.\" normal FS +.de @FS +.ie \\n[.$] .fn*do-FS "\\$1" no +.el \{\ +. ie \\n[fn*text-num]>\\n[fn*note-num] .fn*do-FS \\n+[fn*note-num] +. el .fn*do-FS +.\} +.. +.\" Second argument of `no' means don't embellish the first argument. +.de fn*do-FS +.if \\n[fn*open] .@error-recover nested FS +.nr fn*open 1 +.if \\n[.u] \{\ +. \" Ensure that the first line of the footnote is on the same page +. \" as the reference. I think this is minimal. +. ev fn +. nr fn*need 1v +. ev +. ie \\n[pg@fn-flag] .nr fn*need +\\n[fn:PD] +. el .nr fn*need +\\n[fn@sep-dist] +. ne \\n[fn*need]u+\\n[.V]u>?0 +.\} +.ev fn +.par@reset-env +.fn*start-div +.par@reset +.ie \\n[.$] .FP \\$@ +.el .@LP +.. +.de @FE +.ie !\\n[fn*open] .@error FE without FS +.el \{\ +. nr fn*open 0 +. br +. ev +. fn*end-div +.\} +.. +.nr fn@have-overflow 0 +.\" called at the top of each column +.de fn@top-hook +.nr fn*max-width 0 +.nr fn*page-bottom-pos 0-\\n[FM]-\\n[pg@fn-bottom-margin] +.ch pg@bottom \\n[fn*page-bottom-pos]u +.if \\n[fn@have-overflow] \{\ +. nr fn@have-overflow 0 +. fn*start-div +. ev nf +. fn@overflow-div +. ev +. fn*end-div +.\} +.. +.\" This is called at the bottom of the column if pg@fn-flag is set. +.de fn@bottom-hook +.nr pg@fn-flag 0 +.nr fn@have-overflow 0 +.nr fn@bottom-pos \\n[.p]-\\n[FM]-\\n[pg@fn-bottom-margin]+\\n[.v] +.ev fn +.nr fn@bottom-pos -\\n[.v] +.ev +.ie \\n[nl]+\\n[fn@sep-dist]+\n[.V]>\\n[fn@bottom-pos] \{\ +. rn fn@div fn@overflow-div +. nr fn@have-overflow 1 +.\} +.el \{\ +. if \\n[pg@ncols]>1 \ +. if \\n[fn*max-width]>\\n[pg@fn-colw] \ +. nr pg@fn-bottom-margin \\n[.p]-\\n[FM]-\\n[nl]+1v +. wh \\n[fn@bottom-pos]u fn*catch-overflow +. fn@print-sep +. ev nf +. fn@div +. rm fn@div +. ev +. if '\\n(.z'fn@overflow-div' \{\ +. di +. nr fn@have-overflow \\n[dn]>0 +. \} +. ch fn*catch-overflow +.\} +.. +.de fn*catch-overflow +.di fn@overflow-div +.. +.nr fn*embed-count 0 +.de @div-end!fn@div +.br +.if '\\n[.ev]'fn' .ev +.fn*end-div +.nr fn*open 0 +.. +.als @div-end!fn*embed-div @div-end!fn@div +.de fn*start-div +.ie '\\n(.z'' \{\ +. da fn@div +. if !\\n[pg@fn-flag] .ns +.\} +.el .di fn*embed-div +.. +.de fn*end-div +.ie '\\n(.z'fn@div' \{\ +. di +. nr fn*page-bottom-pos -\\n[dn] +. nr fn*max-width \\n[fn*max-width]>?\\n[dl] +. if !\\n[pg@fn-flag] .nr fn*page-bottom-pos -\\n[fn@sep-dist] +. nr pg@fn-flag 1 +. nr fn*page-bottom-pos \\n[nl]-\\n[.p]+\n[.V]>?\\n[fn*page-bottom-pos] +. ch pg@bottom \\n[fn*page-bottom-pos]u +.\} +.el \{\ +. ie '\\n(.z'fn*embed-div' \{\ +. di +. rn fn*embed-div fn*embed-div!\\n[fn*embed-count] +\!. fn*embed-start \\n[fn*embed-count] +. rs +' sp (u;\\n[dn]+\\n[fn@sep-dist]+\\n[.V]) +\!. fn*embed-end +. nr fn*embed-count +1 +. \} +. el \{\ +. ev fn +. @error-recover unclosed diversion within footnote +. \} +.\} +.. +.de fn*embed-start +.ie '\\n(.z'' \{\ +. fn*start-div +. ev nf +. fn*embed-div!\\$1 +. rm fn*embed-div!\\$1 +. ev +. fn*end-div +. di fn*null +.\} +.el \{\ +\!. fn*embed-start \\$1 +. rs +.\} +.. +.de fn*embed-end +.ie '\\n(.z'fn*null' \{\ +. di +. rm fn*null +.\} +.el \!.fn*embed-end +.. +.\" It's important that fn@print-sep use up exactly fn@sep-dist vertical space. +.de fn@print-sep +.ev fn +.in 0 +.vs \\n[fn@sep-dist]u +\D'l 1i 0' +.br +.ev +.. +.\" *************************** +.\" ******** module kp ******** +.\" *************************** +.\" Keeps. +.de KS +.br +.di kp*div +.. +.de KF +.if !'\\n(.z'' .@error-recover KF while open diversion +.di kp*fdiv +.ev k +.par@reset-env +.par@reset +.. +.de KE +.ie '\\n(.z'kp*div' .kp*end +.el \{\ +. ie '\\n(.z'kp*fdiv' .kp*fend +. el .@error KE without KS or KF +.\} +.. +.de @div-end!kp*div +.kp*end +.. +.de @div-end!kp*fdiv +.kp*fend +.. +.de kp*need +.ie '\\n(.z'' .ds@need \\$1 +.el \!.kp*need \\$1 +.. +.\" end non-floating keep +.de kp*end +.br +.di +.kp*need \\n[dn] +.ev nf +.kp*div +.ev +.rm kp*div +.. +.\" Floating keeps. +.nr kp@head 0 +.nr kp@tail 0 +.\" end floating keep +.de kp*fend +.br +.ev +.di +.ie \\n[.t]-(\\n[.k]>0*1v)>\\n[dn] \{\ +. br +. ev nf +. kp*fdiv +. rm kp*fdiv +. ev +.\} +.el \{\ +. rn kp*fdiv kp*div!\\n[kp@tail] +. nr kp*ht!\\n[kp@tail] 0\\n[dn] +. nr kp@tail +1 +.\} +.. +.\" top of page processing for KF +.nr kp*doing-top 0 +.de kp@top-hook +.if !\\n[kp*doing-top] \{\ +. nr kp*doing-top 1 +. kp*do-top +. nr kp*doing-top 0 +.\} +.. +.de kp*do-top +.\" If the first keep won't fit, only force it out if we haven't had a footnote +.\" and we're at the top of the page. +.nr kp*force \\n[pg@fn-flag]=0&(\\n[nl]<=\\n[pg@header-bottom]) +.nr kp*fits 1 +.while \\n[kp@tail]>\\n[kp@head]&\\n[kp*fits] \{\ +. ie \\n[.t]>\\n[kp*ht!\\n[kp@head]]:\\n[kp*force] \{\ +. nr kp*force 0 +. \" It's important to advance kp@head before bringing +. \" back the keep, so that if the last line of the +. \" last keep springs the bottom of page trap, a new +. \" page will not be started unnecessarily. +. rn kp*div!\\n[kp@head] kp*temp +. nr kp@head +1 +. ev nf +. kp*temp +. ev +. rm kp*temp +. \} +. el .nr kp*fits 0 +.\} +.. +.\" *************************** +.\" ******** module ds ******** +.\" *************************** +.\" Displays and non-floating keeps. +.de DE +.ds*end!\\n[\\n[.ev]:ds-type] +.nr \\n[.ev]:ds-type 0 +.. +.de ds@auto-end +.if \\n[\\n[.ev]:ds-type] \{\ +. @error automatically terminating display +. DE +.\} +.. +.de @div-end!ds*div +.ie \\n[\\n[.ev]:ds-type] .DE +.el .ds*end!2 +.. +.de ds*end!0 +.@error DE without DS, ID, CD, LD or BD +.. +.de LD +.br +.nr \\n[.ev]:ds-type 1 +.par@reset +.nf +.sp \\n[DD]u +.. +.de ID +.LD +.ie \\n[.$] .in +(n;\\$1) +.el .in +\\n[DI]u +.. +.de CD +.LD +.ce 9999 +.. +.de RD +.LD +.rj 9999 +.. +.de ds*common-end +.par@reset +.sp \\n[DD]u +.. +.als ds*end!1 ds*common-end +.de BD +.LD +.nr \\n[.ev]:ds-type 2 +.di ds*div +.. +.de ds*end!2 +.br +.ie '\\n(.z'ds*div' \{\ +. di +. nf +. in (u;\\n[.l]-\\n[dl]/2) +. ds*div +. rm ds*div +. ds*common-end +.\} +.el .@error-recover mismatched DE +.. +.de DS +.br +.di ds*div +.ie '\\$1'B' \{\ +. LD +. nr \\n[.ev]:ds-type 4 +.\} +.el \{\ +. ie '\\$1'L' .LD +. el \{\ +. ie '\\$1'C' .CD +. el \{\ +. ie '\\$1'R' .RD +. el \{\ +. ie '\\$1'I' .ID \\$2 +. el .ID \\$1 +. \} +. \} +. \} +. nr \\n[.ev]:ds-type 3 +.\} +.. +.de ds@need +.if '\\n(.z'' \{\ +. while \\n[.t]<=(\\$1)&(\\n[nl]>\\n[pg@header-bottom]) \{\ +. rs +' sp \\n[.t]u +. \} +.\} +.. +.de ds*end!3 +.br +.ie '\\n(.z'ds*div' \{\ +. di +. ds@need \\n[dn] +. ev nf +. ds*div +. ev +. rm ds*div +. ds*common-end +.\} +.el .@error-recover mismatched DE +.. +.de ds*end!4 +.ie '\\n(.z'ds*div' \{\ +. br +. di +. nf +. in (u;\\n[.l]-\\n[dl]/2) +. ds@need \\n[dn] +. ds*div +. rm ds*div +. ds*common-end +.\} +.el .@error-recover mismatched DE +.. +.\" **************************** +.\" ******** module par ******** +.\" **************************** +.\" Paragraph-level formatting. +.nr PS 10 +.nr LL 6i +.de par*vs +.\" If it's too big to be in points, treat it as units. +.ie (p;\\$1)>=40p .vs (u;\\$1) +.el .vs (p;\\$1) +.. +.de par@ab-indent +.nr 0:li (u;\\n[LL]/12) +.nr 0:ri \\n[0:li] +.. +.de par*env-init +.aln \\n[.ev]:PS PS +.aln \\n[.ev]:VS VS +.aln \\n[.ev]:LL LL +.aln \\n[.ev]:MCLL LL +.aln \\n[.ev]:LT LT +.aln \\n[.ev]:MCLT LT +.aln \\n[.ev]:PI PI +.aln \\n[.ev]:PD PD +.ad \\n[par*adj] +.par@reset-env +.. +.\" happens when the first page begins +.de par@init +.if !rLT .nr LT \\n[LL] +.if !rFL .nr FL \\n[LL]*5/6 +.if !rVS .nr VS \\n[PS]+2 +.ps \\n[PS] +.if !rDI .nr DI .5i +.if !rQI .nr QI 5n +.if !rPI .nr PI 5n +.par*vs \\n[VS] +.if !rPD .nr PD .3v>?\n(.V +.if !rDD .nr DD .5v>?\n(.V +.if !dFAM .ds FAM \\n[.fam] +.nr par*adj \\n[.j] +.par*env-init +.ev h +.par*env-init +.ev +.ev fn +.par*env-init +.ev +.ev k +.par*env-init +.ev +.aln 0:MCLL pg@colw +.aln 0:MCLT pg@colw +.aln k:MCLL pg@colw +.aln k:MCLT pg@colw +.if !rFPS .nr FPS \\n[PS]-2 +.if !rFVS .nr FVS \\n[FPS]+2 +.if !rFI .nr FI 2n +.if !rFPD .nr FPD \\n[PD]/2 +.aln fn:PS FPS +.aln fn:VS FVS +.aln fn:LL FL +.aln fn:LT FL +.aln fn:PI FI +.aln fn:PD FPD +.aln fn:MCLL pg@fn-colw +.aln fn:MCLT pg@fn-colw +.. +.de par@reset-env +.nr \\n[.ev]:il 0 +.nr \\n[.ev]:li 0 +.nr \\n[.ev]:ri 0 +.nr \\n[.ev]:ai \\n[\\n[.ev]:PI] +.nr \\n[.ev]:pli 0 +.nr \\n[.ev]:pri 0 +.nr \\n[.ev]:ds-type 0 +.. +.\" par@reset +.de par@reset +.br +.ce 0 +.rj 0 +.ul 0 +.fi +.ie \\n[pg@ncols]>1 \{\ +. ll (u;\\n[\\n[.ev]:MCLL]-\\n[\\n[.ev]:ri]-\\n[\\n[.ev]:pri]) +. lt \\n[\\n[.ev]:MCLT]u +.\} +.el \{\ +. ll (u;\\n[\\n[.ev]:LL]-\\n[\\n[.ev]:ri]-\\n[\\n[.ev]:pri]) +. lt \\n[\\n[.ev]:LT]u +.\} +.in (u;\\n[\\n[.ev]:li]+\\n[\\n[.ev]:pli]) +.ft 1 +.fam \\*[FAM] +.ps \\n[\\n[.ev]:PS] +.par*vs \\n[\\n[.ev]:VS] +.ls 1 +.TA +.hy 14 +.. +.als @RT par@reset +.\" This can be redefined by the user. +.de TA +.ta T 5n +.. +.de par*start +.ds@auto-end +.nr \\n[.ev]:pli \\$1 +.nr \\n[.ev]:pri \\$2 +.par@reset +.sp \\n[\\n[.ev]:PD]u +.ne 1v+\\n(.Vu +.. +.de par@finish +.nr \\n[.ev]:pli 0 +.nr \\n[.ev]:pri 0 +.par@reset +.. +.\" normal LP +.de @LP +.par*start 0 0 +.nr \\n[.ev]:ai \\n[\\n[.ev]:PI] +.. +.de @PP +.par*start 0 0 +.nr \\n[.ev]:ai \\n[\\n[.ev]:PI] +.ti +\\n[\\n[.ev]:ai]u +.. +.de @QP +.nr \\n[.ev]:ai \\n[\\n[.ev]:PI] +.par*start \\n[QI] \\n[QI] +.. +.de @XP +.par*start \\n[\\n[.ev]:PI] 0 +.ti -\\n[\\n[.ev]:PI]u +.. +.de @IP +.if \\n[.$]>1 .nr \\n[.ev]:ai (n;\\$2) +.par*start \\n[\\n[.ev]:ai] 0 +.if !'\\$1'' \{\ +. \" Divert the label so as to freeze any spaces. +. di par*label +. in 0 +. nf +\&\\$1 +. di +. in +. fi +. chop par*label +. ti -\\n[\\n[.ev]:ai]u +. ie \\n[dl]+1n<=\\n[\\n[.ev]:ai] \\*[par*label]\h'|\\n[\\n[.ev]:ai]u'\c +. el \{\ +\\*[par*label] +. br +. \} +. rm par*label +.\} +.. +.de @RS +.br +.nr \\n[.ev]:li!\\n[\\n[.ev]:il] \\n[\\n[.ev]:li] +.nr \\n[.ev]:ri!\\n[\\n[.ev]:il] \\n[\\n[.ev]:ri] +.nr \\n[.ev]:ai!\\n[\\n[.ev]:il] \\n[\\n[.ev]:ai] +.nr \\n[.ev]:pli!\\n[\\n[.ev]:il] \\n[\\n[.ev]:pli] +.nr \\n[.ev]:pri!\\n[\\n[.ev]:il] \\n[\\n[.ev]:pri] +.nr \\n[.ev]:il +1 +.nr \\n[.ev]:li +\\n[\\n[.ev]:ai] +.nr \\n[.ev]:ai \\n[\\n[.ev]:PI] +.par@reset +.. +.de @RE +.br +.ie \\n[\\n[.ev]:il] \{\ +. nr \\n[.ev]:il -1 +. nr \\n[.ev]:ai \\n[\\n[.ev]:ai!\\n[\\n[.ev]:il]] +. nr \\n[.ev]:li \\n[\\n[.ev]:li!\\n[\\n[.ev]:il]] +. nr \\n[.ev]:ri \\n[\\n[.ev]:ri!\\n[\\n[.ev]:il]] +. nr \\n[.ev]:pli \\n[\\n[.ev]:pli!\\n[\\n[.ev]:il]] +. nr \\n[.ev]:pri \\n[\\n[.ev]:pri!\\n[\\n[.ev]:il]] +.\} +.el .@error unbalanced \\$0 +.par@reset +.. +.de @QS +.br +.nr \\n[.ev]:li!\\n[\\n[.ev]:il] \\n[\\n[.ev]:li] +.nr \\n[.ev]:ri!\\n[\\n[.ev]:il] \\n[\\n[.ev]:ri] +.nr \\n[.ev]:ai!\\n[\\n[.ev]:il] \\n[\\n[.ev]:ai] +.nr \\n[.ev]:pli!\\n[\\n[.ev]:il] \\n[\\n[.ev]:pli] +.nr \\n[.ev]:pri!\\n[\\n[.ev]:il] \\n[\\n[.ev]:pri] +.nr \\n[.ev]:il +1 +.nr \\n[.ev]:li +\\n[QI] +.nr \\n[.ev]:ri +\\n[QI] +.nr \\n[.ev]:ai \\n[\\n[.ev]:PI] +.par@reset +.. +.als @QE @RE +.\" start boxed text +.de B1 +.br +.di par*box-div +.nr \\n[.ev]:li +1n +.nr \\n[.ev]:ri +1n +.par@reset +.. +.de @div-end!par*box-div +.B2 +.. +.\" end boxed text +.\" Postpone the drawing of the box until we're in the top-level diversion, +.\" in case there's a footnote inside the box. +.de B2 +.ie '\\n(.z'par*box-div' \{\ +. br +. di +. ds@need \\n[dn] +. par*box-mark-top +. ev nf +. par*box-div +. ev +. nr \\n[.ev]:ri -1n +. nr \\n[.ev]:li -1n +. par@finish +. par*box-draw \\n[.i]u \\n[.l]u +.\} +.el .@error B2 without B1 +.. +.de par*box-mark-top +.ie '\\n[.z]'' .mk par*box-top +.el \!.par*box-mark-top +.. +.de par*box-draw +.ie '\\n[.z]'' \{\ +. nr par*box-in \\n[.i] +. nr par*box-ll \\n[.l] +. nr par*box-vpt \\n[.vpt] +. vpt 0 +. in \\$1 +. ll \\$2 +\v'-1v+.25m'\ +\D'l (u;\\n[.l]-\\n[.i]) 0'\ +\D'l 0 |\\n[par*box-top]u'\ +\D'l -(u;\\n[.l]-\\n[.i]) 0'\ +\D'l 0 -|\\n[par*box-top]u' +. br +. sp -1 +. in \\n[par*box-in]u +. ll \\n[par*box-ll]u +. vpt \\n[par*box-vpt] +.\} +.el \!.par*box-draw \\$1 \\$2 +.. +.de @SH +.par@finish +.\" Keep together the heading and the first two lines of the next paragraph. +.ne 3v+\\n[\\n[.ev]:PD]u+\\n(.Vu +.sp 1 +.ft B +.. +.\" TL, AU, and AI are aliased to these in cov*ab-init. +.de par@TL +.par@finish +.sp 1 +.ft B +.ps +2 +.vs +3p +.ce 9999 +.. +.de par@AU +.par@finish +.sp 1 +.ft I +.ce 9999 +.. +.de par@AI +.par@finish +.sp .5 +.ce 9999 +.. +.\" In paragraph macros. +.de NL +.ps \\n[\\n[.ev]:PS] +.. +.de SM +.ps -2 +.. +.de LG +.ps +2 +.. +.de R +.ft R +.. +.\" par*define-font-macro macro font +.de par*define-font-macro +.de \\$1 +.ie \\\\n[.$] \{\ +. nr par*prev-font \\\\n[.f] +\&\\\\$3\f[\\$2]\\\\$1\f[\\\\n[par*prev-font]]\\\\$2 +.\} +.el .ft \\$2 +\\.. +.. +.par*define-font-macro B B +.par*define-font-macro I I +.par*define-font-macro BI BI +.par*define-font-macro CW CR +.\" underline a word +.de UL +\Z'\\$1'\v'.25m'\D'l \w'\\$1'u 0'\v'-.25m'\\$2 +.. +.\" box a word +.de BX +.nr par*bxw \w'\\$1'+.4m +\Z'\v'.25m'\D'l 0 -1m'\D'l \\n[par*bxw]u 0'\D'l 0 1m'\D'l -\\n[par*bxw]u 0''\ +\Z'\h'.2m'\\$1'\ +\h'\\n[par*bxw]u' +.. +.\" The first time UX is used, put a registered mark after it. +.ds par*ux-rg \(rg +.de UX +\s[\\n[.s]*8u/10u]UNIX\s0\\$1\\*[par*ux-rg] +.ds par*ux-rg +.. +.ds par@sup-start \v'-.9m\s'\En[.s]*7u/10u'+.7m' +.als { par@sup-start +.ds par@sup-end \v'-.7m\s0+.9m' +.als } par@sup-end +.\" footnote paragraphs +.\" FF is the footnote format +.nr FF 0 +.\" This can be redefined. It gets a second argument of `no' if the first +.\" argument was supplied by the user, rather than automatically. +.de FP +.br +.if !d par*fp!\\n[FF] \{\ +. @error unknown footnote format `\\n[FF]' +. nr FF 0 +.\} +.ie '\\$2'no' .par*fp!\\n[FF]-no "\\$1" +.el .par*fp!\\n[FF] "\\$1" +.. +.de par*fp!0 +.@PP +\&\\*[par@sup-start]\\$1\\*[par@sup-end]\ \c +.. +.de par*fp!0-no +.@PP +\&\\$1\ \c +.. +.de par*fp!1 +.@PP +\&\\$1.\ \c +.. +.de par*fp!1-no +.@PP +\&\\$1\ \c +.. +.de par*fp!2 +.@LP +\&\\$1.\ \c +.. +.de par*fp!2-no +.@LP +\&\\$1\ \c +.. +.de par*fp!3 +.@IP "\\$1." (u;\\n[\\n[.ev]:PI]*2) +.. +.de par*fp!3-no +.@IP "\\$1" (u;\\n[\\n[.ev]:PI]*2) +.. +.\" *************************** +.\" ******** module nh ******** +.\" *************************** +.\" Numbered headings. +.\" nh*hl is the level of the last heading +.nr nh*hl 0 +.\" numbered heading +.de @NH +.ie '\\$1'S' \{\ +. shift +. nr nh*hl 0 +. while \\n[.$] \{\ +. nr nh*hl +1 +. nr H\\n[nh*hl] 0\\$1 +. shift +. \} +. if !\\n[nh*hl] \{\ +. nr H1 1 +. nr nh*hl 1 +. @error missing arguments to .NH S +. \} +.\} +.el \{\ +. nr nh*ohl \\n[nh*hl] +. ie \\n[.$] \{\ +. nr nh*hl 0\\$1 +. ie \\n[nh*hl]<=0 \{\ +. nr nh*ohl 0 +. nr nh*hl 1 +. \} +. el \{\ +. if \\n[nh*hl]-\\n[nh*ohl]>1 \ +. @warning .NH \\n[nh*ohl] followed by .NH \\n[nh*hl] +. \} +. \} +. el .nr nh*hl 1 +. while \\n[nh*hl]>\\n[nh*ohl] \{\ +. nr nh*ohl +1 +. nr H\\n[nh*ohl] 0 +. \} +. nr H\\n[nh*hl] +1 +.\} +.ds SN +.nr nh*i 0 +.while \\n[nh*i]<\\n[nh*hl] \{\ +. nr nh*i +1 +. as SN \\n[H\\n[nh*i]]. +.\} +.SH +\\*[SN] +.. +.\" **************************** +.\" ******** module toc ******** +.\" **************************** +.\" Table of contents generation. +.de @XS +.da toc*div +.ev h +.ie \\n[.$] .XA "\\$1" +.el .XA +.. +.de @div-end!toc*div +.XE +.. +.de XA +.ie '\\n(.z'toc*div' \{\ +. if d toc*num .toc*end-entry +. ie \\n[.$] \{\ +. ie '\\$1'no' .ds toc*num +. el .ds toc*num "\\$1 +. \} +. el .ds toc*num \\n[PN] +. LP +. na +. ll -8n +. in (n;0\\$2) +.\} +.el .@error XA without XS +.. +.de XE +.ie '\\n(.z'toc*div' \{\ +. if d toc*num .toc*end-entry +. ev +. di +.\} +.el .@error XS without XE +.. +.de toc*end-entry +\\a\\t\\*[toc*num] +.br +.rm toc*num +.. +.de PX +.1C +.if !'\\$1'no' \{\ +. ce 1 +. ps \\n[PS]+2 +. ft B +\\*[TOC] +. ft +. ps +.\} +.nf +.char \[toc*leader-char] .\h'1m' +.lc \[toc*leader-char] +.ta (u;\\n[.l]-\\n[.i]-\w'000') (u;\\n[.l]-\\n[.i])R +.sp 2 +.toc*div +.par@reset +.. +.\" print the table of contents on page i +.de TC +.P1 +.pg@begin 1 i +.PX \\$1 +.. +.\" **************************** +.\" ******** module eqn ******** +.\" **************************** +.\" Eqn support. +.de EQ +.. +.de EN +.. +.de @EQ +.br +.ds eqn*num "\\$2 +.ie '\\$1'L' .nr eqn*type 0 +.el \{\ +. ie '\\$1'I' .nr eqn*type 1 +. el \{\ +. nr eqn*type 2 +. if !'\\$1'C' .ds eqn*num "\\$1 +. \} +.\} +.di eqn*div +.in 0 +.nf +.. +.de @div-end!eqn*div +.@EN +.. +.\" Note that geqn mark and lineup work correctly in centered equations. +.de @EN +.ie !'\\n(.z'eqn*div' .@error-recover mismatched EN +.el \{\ +. br +. di +. nr eqn*have-num 0 +. if !'\\*[eqn*num]'' .nr eqn*have-num 1 +. if \\n[dl]:\\n[eqn*have-num] \{\ +. sp \\n[DD]u +. par@reset +. ds eqn*tabs \\n[.tabs] +. nf +. ie \\n[dl] \{\ +. ds@need \\n[dn]u-1v+\n[.V]u +. chop eqn*div +. ie \\n[eqn*type]=0 \{\ +. ta (u;\\n[.l]-\\n[.i])R +\\*[eqn*div]\t\\*[eqn*num] +. \} +. el \{\ +. ie \\n[eqn*type]=1 .ta \\n[DI]u \ +(u;\\n[.l]-\\n[.i])R +. el .ta (u;\\n[.l]-\\n[.i]/2)C \ +(u;\\n[.l]-\\n[.i])R +\t\\*[eqn*div]\t\\*[eqn*num] +. \} +. \} +. el \{\ +. ta (u;\\n[.l]-\\n[.i])R +\t\\*[eqn*num] +. \} +. sp \\n[DD]u +. fi +. ta \\*[eqn*tabs] +. \} +.\} +.. +.\" **************************** +.\" ******** module tbl ******** +.\" **************************** +.\" Tbl support. +.nr tbl*have-header 0 +.de TS +.\" The break is necessary in the case where the first page has not yet begun. +.br +.sp \\n[DD]u +.if '\\$1'H' .di tbl*header-div +.. +.de tbl@top-hook +.if \\n[tbl*have-header] \{\ +. ie \\n[.t]-\\n[tbl*header-ht]-1v .tbl*print-header +. el .sp \\n[.t]u +.\} +.. +.de tbl*print-header +.ev nf +.tbl*header-div +.ev +.mk #T +.. +.de TH +.ie '\\n[.z]'tbl*header-div' \{\ +. nr T. 0 +. T# +. br +. di +. ie \\n[dn]+\\n[FM]+\\n[HM]+2v>=\\n[.p] \{\ +. @error ridiculously long table header +. ds@need \\n[dn] +. tbl*print-header +. \} +. el \{\ +. nr tbl*header-ht \\n[dn] +. ds@need \\n[dn]u+1v +. tbl*print-header +. nr tbl*have-header 1 +. \} +.\} +.el .@error-recover .TH without .TS H +.. +.de @div-end!tbl*header-div +.TH +.TE +.. +.de TE +.ie '\\n(.z'tbl*header-div' .@error-recover .TS H but no .TH before .TE +.el \{\ +. nr tbl*have-header 0 +. sp \\n[DD]u +.\} +.\" reset tabs +.TA +.. +.de tbl@bottom-hook +.if \\n[tbl*have-header] \{\ +. nr T. 1 +. T# +.\} +.. +.de T& +.. +.\" **************************** +.\" ******** module pic ******** +.\" **************************** +.\" Pic support. +.\" PS height width +.de PS +.br +.sp \\n[DD]u +.ie \\n[.$]<2 .@error bad arguments to PS (not preprocessed with pic?) +.el \{\ +. ds@need (u;\\$1)+1v +. in +(u;\\n[.l]-\\n[.i]-\\$2/2>?0) +.\} +.. +.de PE +.par@reset +.sp \\n[DD]u+.5m +.. +.\" **************************** +.\" ******** module ref ******** +.\" **************************** +.\" Refer support. +.de ]- +.rm [A [B [C [D [E [G [I [J [N [O [P [Q [R [S [T [V +.rm ref*string +.. +.\" Other +.ds ref*spec!0 Q A T1 S V N P I C D O +.\" Journal article +.ds ref*spec!1 Q A T2 J S V N P I C D O +.\" Book +.ds ref*spec!2 Q A T1 S V P I C D O +.\" Article within book +.ds ref*spec!3 Q A T2 B E S V P I C D O +.\" Tech report +.ds ref*spec!4 Q A T2 R G P I C D O +.\" ][ type +.de ][ +.if r [T \{\ +. als [T1 [T +. als [T2 [T +.\} +.ie d ref*spec!\\$1 .ref*build \\*[ref*spec!\\$1] +.el \{\ +. @error unknown reference type `\\$1' +. ref*build \\*[ref*spec!0] +.\} +.ref*print +.rm ref*string +.rm [F [T1 [T2 +.. +.\" start of reference number +.ds [. \\*[par@sup-start] +.\" end of reference number +.ds .] \\*[par@sup-end] +.\" period before reference +.ds <. . +.\" period after reference +.ds >. \" empty +.\" comma before reference +.ds <, , +.\" comma after reference +.ds >, \" empty +.\" start collected references +.de ]< +.als ref*print ref*end-print +.SH +\&\\*[REFERENCES] +.par@reset +.. +.\" end collected references +.de ]> +.par@finish +.als ref*print ref*normal-print +.. +.de ref*normal-print +.ie d [F .FS "\\*([.\\*([F\\*(.]" +.el .FS \& +\\*[ref*string] +.FE +.. +.de ref*end-print +.ie d [F .IP "\\*([F." +.el .XP +\\*[ref*string] +.. +.als ref*print ref*normal-print +.de ref*build +.rm ref*string ref*post-punct +.nr ref*suppress-period 1 +.while \\n[.$] \{\ +. if d [\\$1 \{\ +. ie d ref*add-\\$1 .ref*add-\\$1 +. el .ref*add-dflt \\$1 +. \} +. shift +.\} +.\" now add a final period +.ie d ref*string \{\ +. if !\\n[ref*suppress-period] .as ref*string . +. if d ref*post-punct \{\ +. as ref*string "\\*[ref*post-punct] +. rm ref*post-punct +. \} +.\} +.el .ds ref*string +.. +.de ref*add-T1 +.ref*field T , "\fI" "" "\fP" +.if r [T .nr ref*suppress-period \\n([T +.. +.de ref*add-T2 +.ref*field T , "\\*Q" "" "\\*U" +.if r [T .nr ref*suppress-period \\n([T +.. +.de ref*add-P +.ie \\n([P>0 .ref*field P , "pp. " +.el .ref*field P , "p. " +.. +.de ref*add-J +.ref*field J , \fI "" \fP +.. +.de ref*add-D +.ref*field D "" ( ) +.. +.de ref*add-E +.ref*field E , "ed. " +.. +.de ref*add-G +.ref*field G "" ( ) +.. +.de ref*add-B +.ref*field B "" "in \fI" "" \fP +.. +.de ref*add-O +.ref*field O . +.ie r [O .nr ref*suppress-period \\n([O +.el .nr ref*suppress-period 1 +.. +.de ref*add-A +.ref*field A , +.if r [A .nr ref*suppress-period \\n([A +.. +.de ref*add-dflt +.ref*field \\$1 , +.. +.\" First argument is the field letter. +.\" Second argument is the punctuation character to use to separate this field +.\" from the previous field. +.\" Third argument is a string with which to prefix this field. +.\" Fourth argument is a string with which to postfix this field. +.\" Fifth argument is a string to add after the punctuation character supplied +.\" by the next field. +.de ref*field +.if d ref*string \{\ +. ie d ref*post-punct \{\ +. as ref*string "\\$2\\*[ref*post-punct] \" +. rm ref*post-punct +. \} +. el .as ref*string "\\$2 \" +.\} +.as ref*string "\\$3\\*([\\$1\\$4 +.if \\n[.$]>4 .ds ref*post-punct "\\$5 +.nr ref*suppress-period 0 +.. +.\" **************************** +.\" ******** module acc ******** +.\" **************************** +.\" Accents and special characters. +.ds Q \(lq +.ds U \(rq +.ds - \(em +.\" Characters +.\" The idea of this definition is for the top of the 3 to be at the x-height. +.if !c\[yogh] .char \[yogh] \Z'\v'\w'x'*0-\En[rst]u'\s[\En[.s]*8u/10u]\ +\v'\w'3'*0+\En[rst]u'3\s0'\h'\w'\s[\En[.s]*8u/10u]3'u' +.\" Accents +.de acc*over-def +.ds \\$1 \Z'\v'(u;\w'x'*0+\En[rst]-\En[.cht])'\ +\h'(u;-\En[skw]+(-\En[.w]-\w'\\$2'/2)+\En[.csk])'\\$2' +.. +.de acc*under-def +.ds \\$1 \Z'\v'\En[.cdp]u'\h'(u;-\En[.w]-\w'\\$2'/2)'\\$2' +.. +.de acc*slash-def +.ds \\$1 \Z'\h'(u;-\En[.w]-\w'\\$2'/2)'\ +\v'(u;\En[.cdp]-\En[.cht]+\En[rst]+\En[rsb]/2)'\\$2' +.. +.de acc*prefix-def +.ds \\$1 \Z'\h'(u;\w'x'-\w'\\$2'/2)'\\$2' +.. +.acc*prefix-def ' \' +.acc*prefix-def ` \` +.acc*prefix-def ^ ^ +.acc*prefix-def , \(ac +.acc*prefix-def : \(ad +.acc*prefix-def ~ ~ +.\" improved accent marks +.de AM +.acc*over-def ' \' +.acc*over-def ` \` +.acc*over-def ^ ^ +.acc*over-def ~ ~ +.acc*over-def : \(ad +.acc*over-def v \(ah +.acc*over-def _ \(a- +.acc*over-def o \(ao +.acc*under-def , \(ac +.acc*under-def . \s[\En[.s]*8u/10u]\v'.2m'.\v'-.2m'\s0 +.acc*under-def hook \(ho +.acc*slash-def / / +.char \[hooko] o\\\\*[hook] +.ds q \[hooko] +.ds 3 \[yogh] +.ds D- \(-D\" Icelandic uppercase eth +.ds d- \(Sd\" Icelandic lowercase eth +.ds Th \(TP\" Icelandic uppercase thorn +.ds th \(Tp\" Icelandic lowercase thorn +.ds 8 \(ss\" German double s +.ds Ae \(AE\" AE ligature +.ds ae \(ae\" ae ligature +.ds Oe \(OE\" OE ligature +.ds oe \(oe\" oe ligature +.ds ? \(r?\" upside down ? +.ds ! \(r!\" upside down ! +.. +.\" Make sure that no blank lines creep in at the end of this file. diff --git a/gnu/usr.bin/groff/tmac/tmac.tty b/gnu/usr.bin/groff/tmac/tmac.tty new file mode 100644 index 00000000000..4d5193fe3ab --- /dev/null +++ b/gnu/usr.bin/groff/tmac/tmac.tty @@ -0,0 +1,48 @@ +.nr _C \n(.C +.cp 0 +.nroff +.ftr CW B +.ftr C B +.ftr CR B +.po 0 +.if c\[char173] .shc \[char173] +.de tty-char +.if !c\\$1 .char \\$1 "\\$2 +.. +.if c\(md .tr \(bu\(md +.tty-char \(bu \z+o +.tty-char \(14 1/4 +.tty-char \(12 1/2 +.tty-char \(34 3/4 +.tty-char \(ff ff +.tty-char \(fi fi +.tty-char \(fl fl +.tty-char \(Fi ffi +.tty-char \(Fl ffl +.tty-char \(<- <- +.tty-char \(-> -> +.tty-char \(<> <-> +.tty-char \(em -- +.tty-char \(+- +- +.tty-char \(co (C) +.tty-char \(<= <= +.tty-char \(>= >= +.tty-char \(!= != +.tty-char \(== == +.tty-char \(~= ~= +.tty-char \(sq [] +.tty-char \(lh <= +.tty-char \(rh => +.tty-char \(lA <= +.tty-char \(rA => +.tty-char \(hA <=> +.tty-char \(rg (R) +.tty-char \(OE OE +.tty-char \(oe oe +.tty-char \(AE AE +.tty-char \(ae ae +.tty-char \(an - +.cp \n(_C +.\" If you want the character definitions in tmac.tty-char to be loaded +.\" automatically, remove the `\"' from the next line. +.\"do mso tmac.tty-char diff --git a/gnu/usr.bin/groff/tmac/tmac.tty-char b/gnu/usr.bin/groff/tmac/tmac.tty-char new file mode 100644 index 00000000000..9815e6c0f0e --- /dev/null +++ b/gnu/usr.bin/groff/tmac/tmac.tty-char @@ -0,0 +1,196 @@ +.\" This file defines standard troff characters and some groff characters for +.\" use with -Tascii and -Tlatin1. +.\" +.\" These definitions are chosen so that, as far as possible, they: +.\" - work with both -Tascii and -Tlatin1. +.\" - work on devices that display only the last overstruck character +.\" as well as on devices that support overstriking +.\" - represent the character's graphical shape (not its meaning) +.\" +.nr _C \n(.C +.cp 0 +.de tty-char +.if !c\\$1 .char \\$1 "\\$2 +.. +.ie c\(a- .ds tty-rn \(a- +.el .ds tty-rn \v'-1m'_\v'+1m' +.tty-char \(tm tm +.tty-char \(rn \*[tty-rn] +.tty-char \(ua \z|^ +.tty-char \(da \z|v +.tty-char \(sc S +.tty-char \(ct \z/c +.tty-char \(dg \z|- +.tty-char \(dd \z|= +.tty-char \(ib (\z=_ +.tty-char \(ip \z=_) +.tty-char \(sb (= +.tty-char \(sp =) +.tty-char \(if oo +.tty-char \(pt oc +.tty-char \(es {} +.tty-char \(ca (^) +.tty-char \(cu U +.tty-char \(de o +.tty-char \(di -:- +.tty-char \(no ~ +.tty-char \(gr \Z'\*[tty-rn]'V +.tty-char \(is \z'\z,I +.tty-char \(mo E +.tty-char \(pd a +.tty-char \(sr \e/ +.tty-char \(*C \z_H +.tty-char \(*D \z_/\z_\e +.tty-char \(*F \zIO +.tty-char \(*G |\*[tty-rn] +.tty-char \(*H \z-O +.tty-char \(*L /\e +.tty-char \(*P TT +.tty-char \(*Q \zIY +.tty-char \(*S \z_\Z'\*[tty-rn]'> +.tty-char \(*W \z_O +.if c\(ss .tty-char \(*b \(ss +.tty-char \(*b B +.tty-char \(*a a +.tty-char \(*c \z,E +.tty-char \(*d d +.tty-char \(*e e +.tty-char \(*f \z|o +.tty-char \(+f \z|o +.tty-char \(*g y +.tty-char \(*h \z-0 +.tty-char \(+h \z-0 +.tty-char \(*i i +.tty-char \(*k k +.tty-char \(*l \z>\e +.tty-char \(*m \z,u +.tty-char \(*n v +.tty-char \(*p \z-n +.tty-char \(+p \z-w +.tty-char \(*q \z|u +.tty-char \(*r p +.tty-char \(*s \z-o +.tty-char \(*t \z~t +.tty-char \(*u u +.tty-char \(*w w +.tty-char \(*x x +.tty-char \(*y n +.tty-char \(*z \z,C +.tty-char \(ts s +.\" Definition of \(ss should follow that of \(*b. +.tty-char \(ss B +.tty-char \(c* \zO\(mu +.tty-char \(c+ \zO+ +.tty-char \(AN ^ +.tty-char \(OR v +.tty-char \(uA \z=^ +.tty-char \(dA \z=v +.if c\(md .tty-char \(a. \(md +.tty-char \(Im I +.tty-char \(Re R +.tty-char \(/L \z/L +.tty-char \(/l \z/l +.tty-char \(%0 %o +.tty-char \(ao o +.tty-char \(a" """" +.tty-char \(ah v +.tty-char \(ho \(ac +.tty-char \(/_ \z_/ +.tty-char \(=~ =~ +.tty-char \(Ah N +.tty-char \(CR _| +.tty-char \(fa \z-V +.tty-char \(nm \z/E +.tty-char \(pp \z_| +.tty-char \(sd '' +.tty-char \(st -) +.tty-char \(te 3 +.if c\(md .tty-char \(tf .\(md. +.tty-char \(tf .:. +.tty-char \(wp p +.tty-char \(~~ ~~ +.tty-char \(Fn \z,f +.tty-char \(Bq ,, +.tty-char \(bq , +.tty-char \(lz <> +.\" Latin-1 characters +.tty-char \(r! \z,i +.tty-char \(Po \z-L +.tty-char \(Cs \zox +.tty-char \(Ye \z=Y +.tty-char \(bb | +.tty-char \(ad """" +.tty-char \(Of \z_a +.tty-char \(Fo << +.tty-char \(a- \*[tty-rn] +.tty-char \(S2 2 +.tty-char \(S3 3 +.tty-char \(ps 9| +.tty-char \(md . +.tty-char \(ac , +.tty-char \(S1 1 +.tty-char \(Om \z_o +.tty-char \(Fc >> +.tty-char \(r? \z'c +.tty-char \(`A \z`A +.tty-char \('A \z'A +.tty-char \(^A \z^A +.tty-char \(~A \z~A +.tty-char \(:A \z"A +.tty-char \(oA \zoA +.tty-char \(,C \z,C +.tty-char \(`E \z`E +.tty-char \('E \z'E +.tty-char \(^E \z^E +.tty-char \(:E \z"E +.tty-char \(`I \z`I +.tty-char \('I \z'I +.tty-char \(^I \z^I +.tty-char \(:I \z"I +.tty-char \(-D \z-D +.tty-char \(~N \z~N +.tty-char \(`O \z`O +.tty-char \('O \z'O +.tty-char \(^O \z^O +.tty-char \(~O \z~O +.tty-char \(:O \z"O +.tty-char \(/O \z/O +.tty-char \(`U \z`U +.tty-char \('U \z'U +.tty-char \(^U \z^U +.tty-char \(:U \z"U +.tty-char \('Y \z'Y +.tty-char \(TP \zIb +.tty-char \(`a \z`a +.tty-char \('a \z'a +.tty-char \(^a \z^a +.tty-char \(~a \z~a +.tty-char \(:a \z"a +.tty-char \(oa \zoa +.tty-char \(,c \z,c +.tty-char \(`e \z`e +.tty-char \('e \z'e +.tty-char \(^e \z^e +.tty-char \(:e \z"e +.tty-char \(`i \z`i +.tty-char \('i \z'i +.tty-char \(^i \z^i +.tty-char \(:i \z"i +.tty-char \(Sd \z`\z'o +.tty-char \(~n \z~n +.tty-char \(`o \z`o +.tty-char \('o \z'o +.tty-char \(^o \z^o +.tty-char \(~o \z~o +.tty-char \(:o \z"o +.tty-char \(/o \z/o +.tty-char \(`u \z`u +.tty-char \('u \z'u +.tty-char \(^u \z^u +.tty-char \(:u \z"u +.tty-char \('y \z'y +.tty-char \(Tp \zpb +.tty-char \(:y \z"y +.\"tty-char \(:y \ij +.cp \n(_C +.do mso tmac.latin1 diff --git a/gnu/usr.bin/groff/tmac/troffrc b/gnu/usr.bin/groff/tmac/troffrc new file mode 100644 index 00000000000..f3140d8e6ab --- /dev/null +++ b/gnu/usr.bin/groff/tmac/troffrc @@ -0,0 +1,24 @@ +.\" Startup file for troff. +.\" This is tested by pic. +.nr 0p 0 +.\" Use .do here, so that it works with -C. +.\" The groff command defines the .X string if the -X option was given. +.ie r.X .do ds troffrc!ps tmac.Xps +.el .do ds troffrc!ps tmac.ps +.do ds troffrc!dvi tmac.dvi +.do ds troffrc!X75 tmac.X +.do ds troffrc!X75-12 tmac.X +.do ds troffrc!X100 tmac.X +.do ds troffrc!X100-12 tmac.X +.do ds troffrc!ascii tmac.tty +.do ds troffrc!latin1 tmac.tty +.do if d troffrc!\*[.T] \ +. do mso \*[troffrc!\*[.T]] +.do rm troffrc!ps troffrc!Xps troffrc!dvi troffrc!X75 troffrc!X75-12 \ +troffrc!X100 troffrc!X100-12 +.do tr \[char160] +.\" Set the hyphenation language to `us'. +.do hla us +.\" Load hyphenation patterns from `hyphen.us' (in the tmac directory). +.do hpf hyphen.us +.\" Don't let blank lines creep in here. diff --git a/gnu/usr.bin/groff/troff/Makefile b/gnu/usr.bin/groff/troff/Makefile index 45b21cbd8b2..1be2342d199 100644 --- a/gnu/usr.bin/groff/troff/Makefile +++ b/gnu/usr.bin/groff/troff/Makefile @@ -1,21 +1,35 @@ -# @(#)Makefile 6.2 (Berkeley) 3/3/91 - -.include "../Makefile.g++" -.include "../../Makefile.inc" +# Makefile for troff PROG= troff -HYPHENDIR= /usr/share/misc -SRCS= column.cc dictionary.cc div.cc env.cc input.cc \ - node.cc number.cc reg.cc symbol.cc -LDADD+= $(.CURDIR)/../libgroff/obj/libgroff.a -lm -# Delete the -Ig++-include after we fix libg++ and install it -CXXFLAGS+= -I$(.CURDIR) -I$(.CURDIR)/../libgroff \ - -I$(.CURDIR)/../../../lib/libg++/g++-include \ - -DMACROPATH=\"/usr/share/tmac\" -DSTORE_WIDTH \ - -DHYPHENFILE=\"$(HYPHENDIR)/hyphen\" +SRCS= env.cc node.cc input.cc div.cc symbol.cc dictionary.cc reg.cc \ + number.cc majorminor.cc +CFLAGS+= -I$(.CURDIR)/../include +LDADD+= $(LIBGROFF) -lm +DPADD+= $(LIBGROFF) $(LIBMATH) + +CLEANFILES+= majorminor.cc +majorminor.cc: $(.CURDIR)/../VERSION + @echo Making $@ + @-rm -f $@ + @echo const char \*major_version = \ + \"`sed -e 's/^\([^.]*\)\..*$$/\1/' $(.CURDIR)/../VERSION`\"\; >$@ + @echo const char \*minor_version = \ + \"`sed -e 's/^[^.]*\.\([0-9]*\).*$$/\1/' $(.CURDIR)/../VERSION`\"\; >>$@ + +install_data: hyphen.us + -test -d $(datadir) || mkdir $(datadir) + -test -d $(datasubdir) || mkdir $(datasubdir) + -test -d $(tmacdir) || mkdir $(tmacdir) + -rm -f $(tmacdir)/hyphen.us + $(INSTALL_DATA) $(srcdir)/hyphen.us $(tmacdir)/hyphen.us + +uninstall_sub: + -rm -f $(tmacdir)/hyphen.us afterinstall: - install -c -o bin -g bin -m 444 $(.CURDIR)/hyphen \ - $(DESTDIR)$(HYPHENDIR)/hyphen + install -c -o bin -g bin -m 444 $(.CURDIR)/hyphen.us \ + $(DESTDIR)$(tmacdir)/hyphen.us .include <bsd.prog.mk> +.include "../../Makefile.inc" +.include "../Makefile.cfg" diff --git a/gnu/usr.bin/groff/troff/Makefile.dep b/gnu/usr.bin/groff/troff/Makefile.dep new file mode 100644 index 00000000000..b1fd7791e16 --- /dev/null +++ b/gnu/usr.bin/groff/troff/Makefile.dep @@ -0,0 +1,34 @@ +env.o : env.cc troff.h ../include/lib.h ../include/assert.h \ + ../include/device.h ../include/cset.h ../include/cmap.h \ + ../include/errarg.h ../include/error.h symbol.h dictionary.h hvunits.h \ + env.h request.h node.h token.h div.h reg.h charinfo.h \ + ../include/searchpath.h ../include/macropath.h +node.o : node.cc troff.h ../include/lib.h ../include/assert.h \ + ../include/device.h ../include/cset.h ../include/cmap.h \ + ../include/errarg.h ../include/error.h symbol.h dictionary.h hvunits.h \ + env.h request.h node.h token.h charinfo.h ../include/font.h reg.h +input.o : input.cc troff.h ../include/lib.h ../include/assert.h \ + ../include/device.h ../include/cset.h ../include/cmap.h \ + ../include/errarg.h ../include/error.h symbol.h dictionary.h hvunits.h \ + env.h request.h node.h reg.h token.h div.h charinfo.h ../include/font.h \ + ../include/searchpath.h ../include/macropath.h ../include/defs.h \ + ../include/posix.h +div.o : div.cc troff.h ../include/lib.h ../include/assert.h \ + ../include/device.h ../include/cset.h ../include/cmap.h \ + ../include/errarg.h ../include/error.h symbol.h dictionary.h hvunits.h \ + env.h request.h node.h token.h div.h reg.h +symbol.o : symbol.cc troff.h ../include/lib.h ../include/assert.h \ + ../include/device.h ../include/cset.h ../include/cmap.h \ + ../include/errarg.h ../include/error.h symbol.h +dictionary.o : dictionary.cc troff.h ../include/lib.h ../include/assert.h \ + ../include/device.h ../include/cset.h ../include/cmap.h \ + ../include/errarg.h ../include/error.h symbol.h dictionary.h +reg.o : reg.cc troff.h ../include/lib.h ../include/assert.h \ + ../include/device.h ../include/cset.h ../include/cmap.h \ + ../include/errarg.h ../include/error.h symbol.h dictionary.h token.h \ + request.h reg.h +number.o : number.cc troff.h ../include/lib.h ../include/assert.h \ + ../include/device.h ../include/cset.h ../include/cmap.h \ + ../include/errarg.h ../include/error.h symbol.h hvunits.h env.h token.h \ + div.h +majorminor.o : majorminor.cc diff --git a/gnu/usr.bin/groff/troff/TODO b/gnu/usr.bin/groff/troff/TODO index 9fa49206f89..f67707490ed 100644 --- a/gnu/usr.bin/groff/troff/TODO +++ b/gnu/usr.bin/groff/troff/TODO @@ -1,15 +1,12 @@ +Give a more helpful error message when the indent is set to a value +greater than the line-length. + Tracing. This is a pain to implement because requests are responsible for reading their own arguments. Possibly implement -s option (stop every N pages). This functionality would be more appropriate in a postprocessor. -Make it possible to have multilingual documents, by having a ``current -language'' with which hyphenation information (the pattern trie and -exception dictionary) is associated; the current language should be -associated with the environment. Get some pattern tries for other -languages (assuming ISO Latin-1). - Line breaking should be smarter. In particular, it should be possible to shrink spaces. Also avoid having a line that's been shrunk a lot next to a line that's been stretched a lot. The difficulty is to @@ -90,8 +87,6 @@ Make it possible to suppress hyphenation on a word-by-word basis. Possibly allow multiple simultaneous input line traps. -Paddable, unbreakable space escape sequence. - Unpaddable, breakable space escape sequence. Support hanging punctuation. @@ -117,5 +112,21 @@ Generalized ligatures. Provide some way for a macro to tell whether it was called with `'' or `.'. This would be useful for implementing a tracing macro packge. -Request to remove an environment. (Need to check it's not on the -environment stack). +Request to remove an environment. (Maintain a count of the references +to the environment from the environment table, environment dictionary +or environment stack.) + +Perhaps in the nr request a leading `-' should only be recognized as a +decrement when it's at the same input level as the request. + +Don't ever change a charinfo. Create new variants instead and chain +them together. + +Make it possible to tr characters onto \~. + +Unix troff appears to read the first character of a request name in +copy mode. Should we do the same? + +Number register giving name of end macro. + +More thorough range checking. diff --git a/gnu/usr.bin/groff/troff/charinfo.h b/gnu/usr.bin/groff/troff/charinfo.h index 7afe9203816..29a5b853d4b 100644 --- a/gnu/usr.bin/groff/troff/charinfo.h +++ b/gnu/usr.bin/groff/troff/charinfo.h @@ -1,12 +1,12 @@ // -*- C++ -*- -/* Copyright (C) 1989, 1990 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.uucp) +/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) This file is part of groff. groff is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 1, or (at your option) any later +Software Foundation; either version 2, or (at your option) any later version. groff is distributed in the hope that it will be useful, but WITHOUT ANY @@ -15,7 +15,7 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along -with groff; see the file LICENSE. If not, write to the Free Software +with groff; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ class macro; @@ -24,13 +24,15 @@ class charinfo { static int next_index; charinfo *translation; int index; + int number; macro *mac; unsigned char special_translation; unsigned char hyphenation_code; unsigned char flags; unsigned char ascii_code; - unsigned char number; char not_found; + char transparent_translate; // non-zero means translation applies to + // to transparent throughput public: enum { ENDS_SENTENCE = 1, @@ -39,12 +41,14 @@ public: OVERLAPS_HORIZONTALLY = 8, OVERLAPS_VERTICALLY = 16, TRANSPARENT = 32, - NUMBERED = 64, + NUMBERED = 64 }; enum { TRANSLATE_NONE, TRANSLATE_SPACE, TRANSLATE_DUMMY, + TRANSLATE_STRETCHABLE_SPACE, + TRANSLATE_HYPHEN_INDICATOR }; symbol nm; charinfo(symbol s); @@ -59,22 +63,22 @@ public: unsigned char get_ascii_code(); void set_hyphenation_code(unsigned char); void set_ascii_code(unsigned char); - charinfo *get_translation(); - void set_translation(charinfo *); + charinfo *get_translation(int = 0); + void set_translation(charinfo *, int); void set_flags(unsigned char); - void set_special_translation(int); - int get_special_translation(); + void set_special_translation(int, int); + int get_special_translation(int = 0); macro *set_macro(macro *); macro *get_macro(); int first_time_not_found(); - void set_number(unsigned char); + void set_number(int); int get_number(); int numbered(); }; charinfo *get_charinfo(symbol); extern charinfo *charset_table[]; -charinfo *get_charinfo_by_number(unsigned char); +charinfo *get_charinfo_by_number(int); inline int charinfo::overlaps_horizontally() { @@ -111,9 +115,11 @@ inline int charinfo::numbered() return flags & NUMBERED; } -inline charinfo *charinfo::get_translation() +inline charinfo *charinfo::get_translation(int transparent_throughput) { - return translation; + return (transparent_throughput && !transparent_translate + ? 0 + : translation); } inline unsigned char charinfo::get_hyphenation_code() @@ -136,9 +142,11 @@ inline int charinfo::get_index() return index; } -inline int charinfo::get_special_translation() +inline int charinfo::get_special_translation(int transparent_throughput) { - return special_translation; + return (transparent_throughput && !transparent_translate + ? TRANSLATE_NONE + : special_translation); } inline macro *charinfo::get_macro() diff --git a/gnu/usr.bin/groff/troff/column.cc b/gnu/usr.bin/groff/troff/column.cc index 2e19d4d187d..230e544e0d0 100644 --- a/gnu/usr.bin/groff/troff/column.cc +++ b/gnu/usr.bin/groff/troff/column.cc @@ -1,12 +1,12 @@ // -*- C++ -*- -/* Copyright (C) 1990, 1991 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.uucp) +/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) This file is part of groff. groff is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 1, or (at your option) any later +Software Foundation; either version 2, or (at your option) any later version. groff is distributed in the hope that it will be useful, but WITHOUT ANY @@ -15,12 +15,12 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along -with groff; see the file LICENSE. If not, write to the Free Software +with groff; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef COLUMN -#include "groff.h" +#include "troff.h" #include "symbol.h" #include "dictionary.h" #include "hvunits.h" @@ -464,8 +464,8 @@ justification_spec::justification_spec(vunits h) justification_spec::~justification_spec() { - delete type; - delete amount; + a_delete type; + a_delete amount; } void justification_spec::append(symbol t, vunits v) @@ -486,12 +486,12 @@ void justification_spec::append(symbol t, vunits v) int i; for (i = 0; i < n; i++) type[i] = old_type[i]; - delete old_type; + a_delete old_type; vunits *old_amount = amount; amount = new vunits[maxn]; for (i = 0; i < n; i++) amount[i] = old_amount[i]; - delete old_amount; + a_delete old_amount; } assert(n < maxn); type[n] = t; diff --git a/gnu/usr.bin/groff/troff/dictionary.cc b/gnu/usr.bin/groff/troff/dictionary.cc index 05984474595..5437a1a1ed3 100644 --- a/gnu/usr.bin/groff/troff/dictionary.cc +++ b/gnu/usr.bin/groff/troff/dictionary.cc @@ -1,12 +1,12 @@ // -*- C++ -*- -/* Copyright (C) 1989, 1990 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.uucp) +/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) This file is part of groff. groff is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 1, or (at your option) any later +Software Foundation; either version 2, or (at your option) any later version. groff is distributed in the hope that it will be useful, but WITHOUT ANY @@ -15,11 +15,11 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along -with groff; see the file LICENSE. If not, write to the Free Software +with groff; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "groff.h" +#include "troff.h" #include "symbol.h" #include "dictionary.h" @@ -49,7 +49,7 @@ dictionary::dictionary(int n) : threshold(0.5), factor(1.5), used(0), size(n) void *dictionary::lookup(symbol s, void *v) { - for (int i = s.hash() % size; + for (int i = int(s.hash() % size); table[i].v != 0; i == 0 ? i = size - 1: --i) if (s == table[i].s) { @@ -77,6 +77,7 @@ void *dictionary::lookup(symbol s, void *v) for (i = 0; i < old_size; i++) if (old_table[i].v != 0) (void)lookup(old_table[i].s, old_table[i].v); + a_delete old_table; } return 0; } @@ -95,7 +96,7 @@ void *dictionary::lookup(const char *p) void *dictionary::remove(symbol s) { // this relies on the fact that we are using linear probing - for (int i = s.hash() % size; + for (int i = int(s.hash() % size); table[i].v != 0 && s != table[i].s; i == 0 ? i = size - 1: --i) ; @@ -110,7 +111,7 @@ void *dictionary::remove(symbol s) i = size - 1; if (table[i].v == 0) break; - r = table[i].s.hash() % size; + r = int(table[i].s.hash() % size); } while ((i <= r && r < j) || (j < i && i <= r)); table[j] = table[i]; } diff --git a/gnu/usr.bin/groff/troff/dictionary.h b/gnu/usr.bin/groff/troff/dictionary.h index 5611d47aa00..47d6d59926e 100644 --- a/gnu/usr.bin/groff/troff/dictionary.h +++ b/gnu/usr.bin/groff/troff/dictionary.h @@ -1,12 +1,12 @@ // -*- C++ -*- -/* Copyright (C) 1989, 1990 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.uucp) +/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) This file is part of groff. groff is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 1, or (at your option) any later +Software Foundation; either version 2, or (at your option) any later version. groff is distributed in the hope that it will be useful, but WITHOUT ANY @@ -15,7 +15,7 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along -with groff; see the file LICENSE. If not, write to the Free Software +with groff; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ diff --git a/gnu/usr.bin/groff/troff/div.cc b/gnu/usr.bin/groff/troff/div.cc index 94b7d8e50f6..c30001f2ae8 100644 --- a/gnu/usr.bin/groff/troff/div.cc +++ b/gnu/usr.bin/groff/troff/div.cc @@ -1,12 +1,12 @@ // -*- C++ -*- -/* Copyright (C) 1989, 1990 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.uucp) +/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) This file is part of groff. groff is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 1, or (at your option) any later +Software Foundation; either version 2, or (at your option) any later version. groff is distributed in the hope that it will be useful, but WITHOUT ANY @@ -15,13 +15,13 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along -with groff; see the file LICENSE. If not, write to the Free Software +with groff; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ // diversions -#include "groff.h" +#include "troff.h" #include "symbol.h" #include "dictionary.h" #include "hvunits.h" @@ -32,6 +32,11 @@ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "div.h" #include "reg.h" +int exit_started = 0; // the exit process has started +int done_end_macro = 0; // the end macro (if any) has finished +int seen_last_page_ejector = 0; // seen the LAST_PAGE_EJECTOR cookie +static int began_page_in_end_macro = 0; // a new page was begun during the end macro + static int last_post_line_extra_space = 0; // needed for \n(.a static int nl_reg_contents = -1; static int dl_reg_contents = 0; @@ -59,7 +64,7 @@ vertical_size::vertical_size(vunits vs, int ls) post = V0; } -void node::set_vertical_size(vertical_size *v) +void node::set_vertical_size(vertical_size *) { } @@ -256,8 +261,8 @@ void macro_diversion::output(node *nd, int retain_size, mac->append(new vertical_size_node(v.post)); mac->append('\n'); vertical_position += x; - if (vertical_position > high_water_mark) - high_water_mark = vertical_position; + if (vertical_position - v.post > high_water_mark) + high_water_mark = vertical_position - v.post; } void macro_diversion::space(vunits n, int) @@ -273,8 +278,6 @@ void macro_diversion::space(vunits n, int) n = -vertical_position; mac->append(new diverted_space_node(n)); vertical_position += n; - if (vertical_position > high_water_mark) - high_water_mark = vertical_position; } void macro_diversion::copy_file(const char *filename) @@ -285,8 +288,8 @@ void macro_diversion::copy_file(const char *filename) top_level_diversion::top_level_diversion() : page_count(0), have_next_page_number(0), page_length(units_per_inch*11), page_offset(units_per_inch), prev_page_offset(units_per_inch), - ejecting_page(0), page_trap_list(0), first_page_begun(0), no_space_mode(0), - page_number(0) + ejecting_page(0), page_trap_list(0), before_first_page(1), no_space_mode(0), + page_number(0), last_page_count(-1) { } @@ -332,7 +335,7 @@ void top_level_diversion::output(node *nd, int retain_size, no_space_mode = 0; vunits next_trap_pos; trap *next_trap = find_next_trap(&next_trap_pos); - if (!first_page_begun && begin_page()) + if (before_first_page && begin_page()) fatal("sorry, I didn't manage to begin the first page in time: use an explicit .br request"); vertical_size v(vs, ls); for (node *tem = nd; tem != 0; tem = tem->next) @@ -348,14 +351,14 @@ void top_level_diversion::output(node *nd, int retain_size, the_output->print_line(page_offset, vertical_position, nd, v.pre + v.pre_extra, v.post_extra); vertical_position += v.post_extra; + if (vertical_position > high_water_mark) + high_water_mark = vertical_position; if (vertical_position_traps_flag && vertical_position >= page_length) begin_page(); else if (vertical_position_traps_flag && next_trap != 0 && vertical_position >= next_trap_pos) { nl_reg_contents = vertical_position.to_units(); truncated_space = v.post; - if (vertical_position > high_water_mark) - high_water_mark = vertical_position; spring_trap(next_trap->nm); } else if (v.post > V0) { @@ -365,28 +368,20 @@ void top_level_diversion::output(node *nd, int retain_size, truncated_space = vertical_position - next_trap_pos; vertical_position = next_trap_pos; nl_reg_contents = vertical_position.to_units(); - if (vertical_position > high_water_mark) - high_water_mark = vertical_position; spring_trap(next_trap->nm); } else if (vertical_position_traps_flag && vertical_position >= page_length) begin_page(); - else { + else nl_reg_contents = vertical_position.to_units(); - if (vertical_position > high_water_mark) - high_water_mark = vertical_position; - } } - else { + else nl_reg_contents = vertical_position.to_units(); - if (vertical_position > high_water_mark) - high_water_mark = vertical_position; - } } void top_level_diversion::transparent_output(unsigned char c) { - if (!first_page_begun && begin_page()) + if (before_first_page && begin_page()) // This can only happen with the transparent() request. fatal("sorry, I didn't manage to begin the first page in time: use an explicit .br request"); const char *s = asciify(c); @@ -401,7 +396,7 @@ void top_level_diversion::transparent_output(node * /*n*/) void top_level_diversion::copy_file(const char *filename) { - if (!first_page_begun && begin_page()) + if (before_first_page && begin_page()) fatal("sorry, I didn't manage to begin the first page in time: use an explicit .br request"); the_output->copy_file(page_offset, vertical_position, filename); } @@ -414,7 +409,7 @@ void top_level_diversion::space(vunits n, int forced) else no_space_mode = 0; } - if (!first_page_begun) { + if (before_first_page) { if (begin_page()) { // This happens if there's a top of page trap, and the first-page // transition is caused by `'sp'. @@ -429,8 +424,6 @@ void top_level_diversion::space(vunits n, int forced) vertical_position = next_trap_pos; nl_reg_contents = vertical_position.to_units(); truncated_space = y - vertical_position; - if (vertical_position > high_water_mark) - high_water_mark = vertical_position; spring_trap(next_trap->nm); } else if (y < V0) { @@ -442,8 +435,6 @@ void top_level_diversion::space(vunits n, int forced) else { vertical_position = y; nl_reg_contents = vertical_position.to_units(); - if (vertical_position > high_water_mark) - high_water_mark = vertical_position; } } @@ -456,12 +447,14 @@ void top_level_diversion::add_trap(symbol nm, vunits pos) { trap *first_free_slot = 0; for (trap **p = &page_trap_list; *p; p = &(*p)->next) { - if ((*p)->position == pos) { + if ((*p)->nm.is_null()) { + if (first_free_slot == 0) + first_free_slot = *p; + } + else if ((*p)->position == pos) { (*p)->nm = nm; return; } - else if ((*p)->nm.is_null() && first_free_slot == 0) - first_free_slot = *p; } if (first_free_slot) { first_free_slot->nm = nm; @@ -521,19 +514,25 @@ void end_diversions() NO_RETURN void cleanup_and_exit(int exit_code) { - if (the_output) + if (the_output) { + the_output->trailer(topdiv->get_page_length()); delete the_output; + } exit(exit_code); } -int exit_flag = 0; - // returns non-zero if it sprung a top of page trap int top_level_diversion::begin_page() { - if (exit_flag == 2 || (exit_flag == 1 && curenv->is_empty())) - cleanup_and_exit(0); + if (exit_started) { + if (page_count == last_page_count + ? curenv->is_empty() + : (done_end_macro && (seen_last_page_ejector || began_page_in_end_macro))) + cleanup_and_exit(0); + if (!done_end_macro) + began_page_in_end_macro = 1; + } if (!the_output) init_output(); ++page_count; @@ -541,6 +540,8 @@ int top_level_diversion::begin_page() page_number = next_page_number; have_next_page_number = 0; } + else if (before_first_page == 1) + page_number = 1; else page_number++; // spring the top of page trap if there is one @@ -548,9 +549,13 @@ int top_level_diversion::begin_page() vertical_position = -vresolution; trap *next_trap = find_next_trap(&next_trap_pos); vertical_position = V0; - first_page_begun = 1; + high_water_mark = V0; ejecting_page = 0; - the_output->begin_page(page_number, page_length); + // If before_first_page was 2, then the top of page transition was undone + // using eg .nr nl 0-1. See nl_reg::set_value. + if (before_first_page != 2) + the_output->begin_page(page_number, page_length); + before_first_page = 0; nl_reg_contents = vertical_position.to_units(); if (vertical_position_traps_flag && next_trap != 0 && next_trap_pos == V0) { truncated_space = V0; @@ -598,25 +603,20 @@ diversion::~diversion() void page_offset() { hunits n; - if (!has_arg()) { - hunits temp = topdiv->page_offset; - topdiv->page_offset = topdiv->prev_page_offset; - topdiv->prev_page_offset = temp; - } - else if (get_hunits(&n, 'v', topdiv->page_offset)) { - topdiv->prev_page_offset = topdiv->page_offset; - topdiv->page_offset = n; - } + if (!has_arg() || !get_hunits(&n, 'v', topdiv->page_offset)) + n = topdiv->prev_page_offset; + topdiv->prev_page_offset = topdiv->page_offset; + topdiv->page_offset = n; skip_line(); } void page_length() { vunits n; - if (!has_arg()) - topdiv->set_page_length(11*units_per_inch); - else if (get_vunits(&n, 'v', topdiv->get_page_length())) + if (has_arg() && get_vunits(&n, 'v', topdiv->get_page_length())) topdiv->set_page_length(n); + else + topdiv->set_page_length(11*units_per_inch); skip_line(); } @@ -642,10 +642,15 @@ void begin_page() while (!tok.newline() && !tok.eof()) tok.next(); if (curdiv == topdiv) { - if (!topdiv->first_page_begun) { - if (topdiv->no_space_mode && !got_arg) { - topdiv->begin_page(); + if (topdiv->before_first_page) { + if (!break_flag) { + if (got_arg) + topdiv->set_next_page_number(n); + if (got_arg || !topdiv->no_space_mode) + topdiv->begin_page(); } + else if (topdiv->no_space_mode && !got_arg) + topdiv->begin_page(); else { /* Given this @@ -712,23 +717,16 @@ void space_request() postpone_traps(); if (break_flag) curenv->do_break(); - int err = 0; vunits n; - if (!has_arg()) + if (!has_arg() || !get_vunits(&n, 'v')) n = curenv->get_vertical_spacing(); - else if (!get_vunits(&n, 'v')) - err = 1; while (!tok.newline() && !tok.eof()) tok.next(); - if (!unpostpone_traps()) { - if (!err) - curdiv->space(n); - } - else { + if (!unpostpone_traps()) + curdiv->space(n); + else // The line might have had line spacing that was truncated. - if (!err) - truncated_space += n; - } + truncated_space += n; tok.next(); } @@ -746,16 +744,12 @@ BEGIN_TRAP token is not skipped over. */ void need_space() { - int err = 0; vunits n; - if (!has_arg()) + if (!has_arg() || !get_vunits(&n, 'v')) n = curenv->get_vertical_spacing(); - else if (!get_vunits(&n, 'v')) - err = 1; while (!tok.newline() && !tok.eof()) tok.next(); - if (!err) - curdiv->need(n); + curdiv->need(n); tok.next(); } @@ -862,15 +856,18 @@ void mark() symbol s = get_name(); if (s.is_null()) curdiv->marked_place = curdiv->get_vertical_position(); + else if (curdiv == topdiv) + set_number_reg(s, nl_reg_contents); else set_number_reg(s, curdiv->get_vertical_position().to_units()); skip_line(); } +// This is truly bizarre. It is documented in the SQ manual. + void return_request() { - vunits dist = V0; - // This is truly bizarre. It is documented in the SQ manual. + vunits dist = curdiv->marked_place - curdiv->get_vertical_position(); if (has_arg()) { if (tok.ch() == '-') { tok.next(); @@ -880,12 +877,10 @@ void return_request() } else { vunits x; - if (get_vunits(&x, 'v') && x >= V0) - dist = x - curdiv->get_vertical_position(); + if (get_vunits(&x, 'v')) + dist = x >= V0 ? x - curdiv->get_vertical_position() : V0; } } - else - dist = curdiv->marked_place - curdiv->get_vertical_position(); if (dist < V0) curdiv->space(dist); skip_line(); @@ -894,10 +889,10 @@ void return_request() void vertical_position_traps() { int n; - if (!has_arg()) - vertical_position_traps_flag = 1; - else if (get_integer(&n)) + if (has_arg() && get_integer(&n)) vertical_position_traps_flag = (n != 0); + else + vertical_position_traps_flag = 1; skip_line(); } @@ -943,7 +938,7 @@ public: int vertical_position_reg::get_value(units *res) { - if (curdiv == topdiv && !topdiv->first_page_begun) + if (curdiv == topdiv && topdiv->before_first_page) *res = -1; else *res = curdiv->get_vertical_position().to_units(); @@ -952,7 +947,7 @@ int vertical_position_reg::get_value(units *res) const char *vertical_position_reg::get_string() { - if (curdiv == topdiv && !topdiv->first_page_begun) + if (curdiv == topdiv && topdiv->before_first_page) return "-1"; else return itoa(curdiv->get_vertical_position().to_units()); @@ -1060,6 +1055,30 @@ const char *constant_vunits_reg::get_string() return itoa(p->to_units()); } +class nl_reg : public variable_reg { +public: + nl_reg(); + void set_value(units); +}; + +nl_reg::nl_reg() : variable_reg(&nl_reg_contents) +{ +} + +void nl_reg::set_value(units n) +{ + variable_reg::set_value(n); + // Setting nl to a negative value when the vertical position in + // the top-level diversion is 0 undoes the top of page transition, + // so that the header macro will be called as if the top of page + // transition hasn't happened. This is used by Larry Wall's + // wrapman program. Setting before_first_page to 2 rather than 1, + // tells top_level_diversion::begin_page not to call + // output_file::begin_page again. + if (n < 0 && topdiv->get_vertical_position() == V0) + topdiv->before_first_page = 2; +} + void init_div_requests() { init_request("wh", when_request); @@ -1092,7 +1111,7 @@ void init_div_requests() number_reg_dictionary.define(".t", new distance_to_next_trap_reg); number_reg_dictionary.define("dl", new variable_reg(&dl_reg_contents)); number_reg_dictionary.define("dn", new variable_reg(&dn_reg_contents)); - number_reg_dictionary.define("nl", new variable_reg(&nl_reg_contents)); + number_reg_dictionary.define("nl", new nl_reg); number_reg_dictionary.define(".vpt", new constant_int_reg(&vertical_position_traps_flag)); number_reg_dictionary.define("%", new page_number_reg); diff --git a/gnu/usr.bin/groff/troff/div.h b/gnu/usr.bin/groff/troff/div.h index bb46421836c..dd275401333 100644 --- a/gnu/usr.bin/groff/troff/div.h +++ b/gnu/usr.bin/groff/troff/div.h @@ -1,12 +1,12 @@ // -*- C++ -*- -/* Copyright (C) 1989, 1990 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.uucp) +/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) This file is part of groff. groff is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 1, or (at your option) any later +Software Foundation; either version 2, or (at your option) any later version. groff is distributed in the hope that it will be useful, but WITHOUT ANY @@ -15,7 +15,7 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along -with groff; see the file LICENSE. If not, write to the Free Software +with groff; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ class diversion { @@ -82,6 +82,7 @@ struct output_file; class top_level_diversion : public diversion { int page_number; int page_count; + int last_page_count; vunits page_length; hunits prev_page_offset; hunits page_offset; @@ -91,7 +92,7 @@ class top_level_diversion : public diversion { int next_page_number; int ejecting_page; // Is the current page being ejected? public: - int first_page_begun; + int before_first_page; int no_space_mode; top_level_diversion(); void output(node *nd, int retain_size, vunits vs, int ls, hunits width); @@ -122,11 +123,16 @@ public: friend void page_offset(); void set_diversion_trap(symbol, vunits); void clear_diversion_trap(); + void set_last_page() { last_page_count = page_count; } }; extern top_level_diversion *topdiv; extern diversion *curdiv; +extern int exit_started; +extern int done_end_macro; +extern int seen_last_page_ejector; + void spring_trap(symbol); // implemented by input.c extern int trap_sprung_flag; void postpone_traps(); diff --git a/gnu/usr.bin/groff/troff/env.cc b/gnu/usr.bin/groff/troff/env.cc index 420ac0f3762..0d343ffc590 100644 --- a/gnu/usr.bin/groff/troff/env.cc +++ b/gnu/usr.bin/groff/troff/env.cc @@ -1,12 +1,12 @@ // -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.uucp) +/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) This file is part of groff. groff is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 1, or (at your option) any later +Software Foundation; either version 2, or (at your option) any later version. groff is distributed in the hope that it will be useful, but WITHOUT ANY @@ -15,10 +15,10 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along -with groff; see the file LICENSE. If not, write to the Free Software +with groff; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "groff.h" +#include "troff.h" #include "symbol.h" #include "dictionary.h" #include "hvunits.h" @@ -29,6 +29,8 @@ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "div.h" #include "reg.h" #include "charinfo.h" +#include "searchpath.h" +#include "macropath.h" #include <math.h> symbol default_family("T"); @@ -53,7 +55,7 @@ static int next_line_number = 0; charinfo *field_delimiter_char; charinfo *padding_indicator_char; - +int translate_space_to_dummy = 0; class pending_output_line { node *nd; @@ -175,11 +177,9 @@ void environment::mark_last_line() void widow_control_request() { - if (has_arg()) { - int n; - if (get_integer(&n)) - curenv->widow_control = n != 0; - } + int n; + if (has_arg() && get_integer(&n)) + curenv->widow_control = n != 0; else curenv->widow_control = 1; skip_line(); @@ -192,11 +192,15 @@ void widow_control_request() size_range *font_size::size_table = 0; int font_size::nranges = 0; -static int compare_ranges(void *p1, void *p2) +extern "C" { + +static int compare_ranges(const void *p1, const void *p2) { return ((size_range *)p1)->min - ((size_range *)p2)->min; } +} + void font_size::init_size_table(int *sizes) { nranges = 0; @@ -265,16 +269,8 @@ void environment::add_char(charinfo *ci) else start_field(); } - else if (current_field && ci == padding_indicator_char) { - if (current_tab) { - tab_contents = new space_node(H0, tab_contents); - tab_field_spaces++; - } - else { - line = new space_node(H0, line); - field_spaces++; - } - } + else if (current_field && ci == padding_indicator_char) + add_padding(); else if (current_tab) { if (tab_contents == 0) tab_contents = new line_start_node; @@ -314,6 +310,7 @@ void environment::add_node(node *n) else { if (line == 0) { if (discarding && n->discardable()) { + // XXX possibly: input_line_start -= n->width(); delete n; return; } @@ -372,40 +369,17 @@ void environment::add_italic_correction() line = line->add_italic_correction(&width_total); } -int environment::get_space_size() -{ - return space_size; -} - -int environment::get_sentence_space_size() -{ - return sentence_space_size; -} - -hunits environment::get_space_width() -{ - return scale(env_space_width(this), space_size, 12); -} - -hunits environment::get_narrow_space_width() -{ - return env_narrow_space_width(this); -} - -hunits environment::get_half_narrow_space_width() -{ - return env_half_narrow_space_width(this); -} - void environment::space_newline() { assert(!current_tab && !current_field); if (interrupted) return; - int ss = space_size; - if (node_list_ends_sentence(line) == 1) - ss += sentence_space_size; - hunits x = scale(env_space_width(this), ss, 12); + hunits x = H0; + if (!translate_space_to_dummy) { + x = env_space_width(this); + if (node_list_ends_sentence(line) == 1) + x += env_sentence_space_width(this); + } if (line != 0 && line->merge_space(x)) { width_total += x; return; @@ -420,18 +394,15 @@ void environment::space() if (interrupted) return; if (current_field && padding_indicator_char == 0) { - node **pp = current_tab ? &tab_contents : &line; - int *hp = current_tab ? &tab_field_spaces : &field_spaces; - *pp = new space_node(H0, *pp); - *hp += 1; + add_padding(); return; } - hunits x = scale(env_space_width(this), space_size, 12); + hunits x = translate_space_to_dummy ? H0 : env_space_width(this); node *p = current_tab ? tab_contents : line; hunits *tp = current_tab ? &tab_width : &width_total; if (p && p->nspaces() == 1 && p->width() == x && node_list_ends_sentence(p->next) == 1) { - hunits xx = scale(env_space_width(this), sentence_space_size, 12); + hunits xx = translate_space_to_dummy ? H0 : env_sentence_space_width(this); if (p->merge_space(xx)) { *tp += xx; return; @@ -582,6 +553,7 @@ environment::environment(symbol nm) tabs(units_per_inch/2, TAB_LEFT), current_tab(TAB_NONE), current_field(0), + margin_character_flags(0), margin_character_node(0), margin_character_distance(points_to_units(10)), numbering_nodes(0), @@ -600,7 +572,8 @@ environment::environment(symbol nm) hyphen_line_count(0), hyphen_line_max(-1), hyphenation_space(H0), - hyphenation_margin(H0) + hyphenation_margin(H0), + composite(0) { prev_family = family = lookup_family(default_family); prev_fontno = fontno = 1; @@ -655,6 +628,7 @@ environment::environment(const environment *e) tabs(e->tabs), current_tab(TAB_NONE), current_field(0), + margin_character_flags(e->margin_character_flags), margin_character_node(e->margin_character_node), margin_character_distance(e->margin_character_distance), numbering_nodes(0), @@ -677,7 +651,8 @@ environment::environment(const environment *e) hyphen_line_max(e->hyphen_line_max), hyphen_line_count(0), hyphenation_space(e->hyphenation_space), - hyphenation_margin(e->hyphenation_margin) + hyphenation_margin(e->hyphenation_margin), + composite(0) { } @@ -975,33 +950,13 @@ void family_change() skip_line(); } -#if 0 -void point_size() -{ - int n; - if (has_arg()) { - if (get_number(&n, 0, curenv->get_requested_point_size()/sizescale)) { - n *= sizescale; - if (n <= 0) - n = 1; - curenv->set_size(n); - } - } - else - curenv->set_size(0); - skip_line(); -} -#endif - void point_size() { int n; - if (has_arg()) { - if (get_number(&n, 'z', curenv->get_requested_point_size())) { - if (n <= 0) - n = 1; - curenv->set_size(n); - } + if (has_arg() && get_number(&n, 'z', curenv->get_requested_point_size())) { + if (n <= 0) + n = 1; + curenv->set_size(n); } else curenv->set_size(0); @@ -1013,10 +968,8 @@ void space_size() int n; if (get_integer(&n)) { curenv->space_size = n; - if (has_arg()) { - if (get_integer(&n)) - curenv->sentence_space_size = n; - } + if (has_arg() && get_integer(&n)) + curenv->sentence_space_size = n; else curenv->sentence_space_size = curenv->space_size; } @@ -1048,6 +1001,8 @@ void center() int n; if (!has_arg() || !get_integer(&n)) n = 1; + else if (n < 0) + n = 0; while (!tok.newline() && !tok.eof()) tok.next(); if (break_flag) @@ -1062,6 +1017,8 @@ void right_justify() int n; if (!has_arg() || !get_integer(&n)) n = 1; + else if (n < 0) + n = 0; while (!tok.newline() && !tok.eof()) tok.next(); if (break_flag) @@ -1074,102 +1031,85 @@ void right_justify() void line_length() { hunits temp; - if (!has_arg()) { - hunits temp = curenv->line_length; - curenv->line_length = curenv->prev_line_length; - curenv->prev_line_length = temp; - } - else if (get_hunits(&temp, 'm', curenv->line_length)) { + if (has_arg() && get_hunits(&temp, 'm', curenv->line_length)) { if (temp < H0) { warning(WARN_RANGE, "bad line length %1u", temp.to_units()); temp = H0; } - curenv->prev_line_length = curenv->line_length; - curenv->line_length = temp; } + else + temp = curenv->prev_line_length; + curenv->prev_line_length = curenv->line_length; + curenv->line_length = temp; skip_line(); } void title_length() { hunits temp; - if (!has_arg()) { - hunits temp = curenv->title_length; - curenv->title_length = curenv->prev_title_length; - curenv->prev_title_length = temp; - } - else if (get_hunits(&temp, 'm', curenv->title_length)) { + if (has_arg() && get_hunits(&temp, 'm', curenv->title_length)) { if (temp < H0) { warning(WARN_RANGE, "bad title length %1u", temp.to_units()); temp = H0; } - curenv->prev_title_length = curenv->title_length; - curenv->title_length = temp; } + else + temp = curenv->prev_title_length; + curenv->prev_title_length = curenv->title_length; + curenv->title_length = temp; skip_line(); } void vertical_spacing() { - if (!has_arg()) { - vunits temp = curenv->vertical_spacing; - curenv->vertical_spacing = curenv->prev_vertical_spacing; - curenv->prev_vertical_spacing = temp; - } - else { - vunits temp; - if (get_vunits(&temp, 'p', curenv->vertical_spacing)) { - if (temp <= V0) { - warning(WARN_RANGE, "vertical spacing must be greater than 0"); - temp = vresolution; - } - curenv->prev_vertical_spacing = curenv->vertical_spacing; - curenv->vertical_spacing = temp; + vunits temp; + if (has_arg() && get_vunits(&temp, 'p', curenv->vertical_spacing)) { + if (temp <= V0) { + warning(WARN_RANGE, "vertical spacing must be greater than 0"); + temp = vresolution; } } + else + temp = curenv->prev_vertical_spacing; + curenv->prev_vertical_spacing = curenv->vertical_spacing; + curenv->vertical_spacing = temp; skip_line(); } void line_spacing() { int temp; - if (!has_arg()) { - temp = curenv->line_spacing; - curenv->line_spacing = curenv->prev_line_spacing; - curenv->prev_line_spacing = temp; - } - else if (get_integer(&temp)) { + if (has_arg() && get_integer(&temp)) { if (temp < 1) { warning(WARN_RANGE, "value %1 out of range: interpreted as 1", temp); temp = 1; } - curenv->prev_line_spacing = curenv->line_spacing; - curenv->line_spacing = temp; } + else + temp = curenv->prev_line_spacing; + curenv->prev_line_spacing = curenv->line_spacing; + curenv->line_spacing = temp; skip_line(); } void indent() { hunits temp; - int err = 0; - if (!has_arg()) + if (has_arg() && get_hunits(&temp, 'm', curenv->indent)) { + if (temp < H0) { + warning(WARN_RANGE, "indent cannot be negative"); + temp = H0; + } + } + else temp = curenv->prev_indent; - else if (!get_hunits(&temp, 'm', curenv->indent)) - err = 1; while (!tok.newline() && !tok.eof()) tok.next(); if (break_flag) curenv->do_break(); - if (temp < H0) { - warning(WARN_RANGE, "indent cannot be negative"); - temp = H0; - } - if (!err) { - curenv->have_temporary_indent = 0; - curenv->prev_indent = curenv->indent; - curenv->indent = temp; - } + curenv->have_temporary_indent = 0; + curenv->prev_indent = curenv->indent; + curenv->indent = temp; tok.next(); } @@ -1196,11 +1136,9 @@ void temporary_indent() void underline() { - int n = 0; - if (!has_arg()) + int n; + if (!has_arg() || !get_integer(&n)) n = 1; - else if (!get_integer(&n)) - n = 0; if (n <= 0) { if (curenv->underline_lines > 0) { curenv->prev_fontno = curenv->fontno; @@ -1216,42 +1154,51 @@ void underline() skip_line(); } - void control_char() { - if (!has_arg()) - curenv->control_char = '.'; - else if (tok.ch() == 0) - error("bad control character"); - else - curenv->control_char = tok.ch(); + curenv->control_char = '.'; + if (has_arg()) { + if (tok.ch() == 0) + error("bad control character"); + else + curenv->control_char = tok.ch(); + } skip_line(); } void no_break_control_char() { - if (!has_arg()) - curenv->no_break_control_char = '\''; - else if (tok.ch() == 0) - error("bad control character"); - else - curenv->no_break_control_char = tok.ch(); + curenv->no_break_control_char = '\''; + if (has_arg()) { + if (tok.ch() == 0) + error("bad control character"); + else + curenv->no_break_control_char = tok.ch(); + } skip_line(); } - void margin_character() { - if (curenv->margin_character_node) { - delete curenv->margin_character_node; - curenv->margin_character_node = 0; - } charinfo *ci = get_optional_char(); if (ci) { - curenv->margin_character_node = curenv->make_char_node(ci); - hunits d; - if (curenv->margin_character_node && has_arg() && get_hunits(&d, 'm')) - curenv->margin_character_distance = d; + node *nd = curenv->make_char_node(ci); + if (nd) { + delete curenv->margin_character_node; + curenv->margin_character_node = nd; + curenv->margin_character_flags = (MARGIN_CHARACTER_ON + |MARGIN_CHARACTER_NEXT); + hunits d; + if (has_arg() && get_hunits(&d, 'm')) + curenv->margin_character_distance = d; + } + } + else { + curenv->margin_character_flags &= ~MARGIN_CHARACTER_ON; + if (curenv->margin_character_flags == 0) { + delete curenv->margin_character_node; + curenv->margin_character_node = 0; + } } skip_line(); } @@ -1260,13 +1207,7 @@ void number_lines() { delete_node_list(curenv->numbering_nodes); curenv->numbering_nodes = 0; - int n; - if (has_arg() && get_integer(&n, next_line_number)) { - next_line_number = n; - if (next_line_number < 0) { - warning(WARN_RANGE, "negative line number"); - next_line_number = 0; - } + if (has_arg()) { node *nd = 0; for (int i = '9'; i >= '0'; i--) { node *tem = make_node(charset_table[i], curenv); @@ -1279,6 +1220,19 @@ void number_lines() } curenv->numbering_nodes = nd; curenv->line_number_digit_width = env_digit_width(curenv); + int n; + if (!tok.delimiter()) { + if (get_integer(&n, next_line_number)) { + next_line_number = n; + if (next_line_number < 0) { + warning(WARN_RANGE, "negative line number"); + next_line_number = 0; + } + } + } + else + while (!tok.space() && !tok.newline() && !tok.eof()) + tok.next(); if (has_arg()) { if (!tok.delimiter()) { if (get_integer(&n)) { @@ -1310,11 +1264,9 @@ void number_lines() void no_number() { - if (has_arg()) { - int n; - if (get_integer(&n)) - curenv->no_number_count = n > 0 ? n : 0; - } + int n; + if (has_arg() && get_integer(&n)) + curenv->no_number_count = n > 0 ? n : 0; else curenv->no_number_count = 1; skip_line(); @@ -1329,10 +1281,8 @@ void no_hyphenate() void hyphenate_request() { int n; - if (has_arg()) { - if (get_integer(&n)) - curenv->hyphenation_flags = n; - } + if (has_arg() && get_integer(&n)) + curenv->hyphenation_flags = n; else curenv->hyphenation_flags = 1; skip_line(); @@ -1346,11 +1296,9 @@ void hyphen_char() void hyphen_line_max_request() { - if (has_arg()) { - int n; - if (get_integer(&n)) - curenv->hyphen_line_max = n; - } + int n; + if (has_arg() && get_integer(&n)) + curenv->hyphen_line_max = n; else curenv->hyphen_line_max = -1; skip_line(); @@ -1386,11 +1334,14 @@ void environment::newline() } node *to_be_output = 0; hunits to_be_output_width; - prev_line_interrupted = interrupted; + prev_line_interrupted = 0; if (dummy) space_newline(); - else if (interrupted) + else if (interrupted) { interrupted = 0; + // see environment::final_break + prev_line_interrupted = exit_started ? 2 : 1; + } else if (center_lines > 0) { --center_lines; hunits x = target_text_length - width_total; @@ -1430,13 +1381,20 @@ void environment::newline() void environment::output_line(node *n, hunits width) { prev_text_length = width; - if (margin_character_node) { + if (margin_character_flags) { hunits d = line_length + margin_character_distance - saved_indent - width; if (d > 0) { n = new hmotion_node(d, n); width += d; } - node *tem = margin_character_node->copy(); + margin_character_flags &= ~MARGIN_CHARACTER_NEXT; + node *tem; + if (!margin_character_flags) { + tem = margin_character_node; + margin_character_node = 0; + } + else + tem = margin_character_node->copy(); tem->next = n; n = tem; width += tem->width(); @@ -1628,15 +1586,15 @@ void environment::hyphenate_line() if (line == 0) return; hyphenation_type prev_type = line->get_hyphenation_type(); - for (node *tem = line->next; tem != 0; tem = tem->next) { - hyphenation_type this_type = tem->get_hyphenation_type(); + for (node **startp = &line->next; *startp != 0; startp = &(*startp)->next) { + hyphenation_type this_type = (*startp)->get_hyphenation_type(); if (prev_type == HYPHEN_BOUNDARY && this_type == HYPHEN_MIDDLE) break; prev_type = this_type; } - if (tem == 0) + if (*startp == 0) return; - node *start = tem; + node *tem = *startp; int i = 0; do { ++i; @@ -1645,7 +1603,7 @@ void environment::hyphenate_line() int inhibit = (tem != 0 && tem->get_hyphenation_type() == HYPHEN_INHIBIT); node *end = tem; hyphen_list *sl = 0; - tem = start; + tem = *startp; node *forward = 0; while (tem != end) { sl = tem->get_hyphen_list(sl); @@ -1654,13 +1612,15 @@ void environment::hyphenate_line() tem1->next = forward; forward = tem1; } - // this is for characters like hyphen and emdash - int prev_code = 0; - for (hyphen_list *h = sl; h; h = h->next) { - h->breakable = (prev_code != 0 - && h->next != 0 - && h->next->hyphenation_code != 0); - prev_code = h->hyphenation_code; + if (!inhibit) { + // this is for characters like hyphen and emdash + int prev_code = 0; + for (hyphen_list *h = sl; h; h = h->next) { + h->breakable = (prev_code != 0 + && h->next != 0 + && h->next->hyphenation_code != 0); + prev_code = h->hyphenation_code; + } } if (hyphenation_flags != 0 && !inhibit @@ -1675,10 +1635,7 @@ void environment::hyphenate_line() tem1->next = 0; tem = tem1->add_self(tem, &sl); } - node *new_start = tem; - for (tem = line; tem->next != start; tem = tem->next) - ; - tem->next = new_start; + *startp = tem; } static node *node_list_reverse(node *n) @@ -1694,18 +1651,17 @@ static node *node_list_reverse(node *n) } static void distribute_space(node *n, int nspaces, hunits desired_space, - int force_forward = 0) + int force_reverse = 0) { static int reverse = 0; - if (!force_forward && reverse) + if (force_reverse || reverse) n = node_list_reverse(n); for (node *tem = n; tem; tem = tem->next) tem->spread_space(&nspaces, &desired_space); - if (!force_forward) { - if (reverse) - (void)node_list_reverse(n); + if (force_reverse || reverse) + (void)node_list_reverse(n); + if (!force_reverse) reverse = !reverse; - } assert(desired_space.is_zero() && nspaces == 0); } @@ -1720,7 +1676,11 @@ void environment::possibly_break_line(int forced) // we'll find one eventually return; node *pre, *post; + node **ndp = &line; + while (*ndp != bp->nd) + ndp = &(*ndp)->next; bp->nd->split(bp->index, &pre, &post); + *ndp = post; hunits extra_space_width = H0; switch(adjust_mode) { case ADJUST_BOTH: @@ -1735,18 +1695,8 @@ void environment::possibly_break_line(int forced) break; } distribute_space(pre, bp->nspaces, extra_space_width); - node *tem = line; - line = 0; - output_line(pre, bp->width + extra_space_width); - line = tem; - input_line_start -= bp->width + extra_space_width; - if (line != bp->nd) { - for (tem = line; tem->next != bp->nd; tem = tem->next) - ; - tem->next = post; - } - else - line = post; + hunits output_width = bp->width + extra_space_width; + input_line_start -= output_width; if (bp->hyphenated) hyphen_line_count++; else @@ -1755,7 +1705,7 @@ void environment::possibly_break_line(int forced) space_total = 0; width_total = 0; node *first_non_discardable = 0; - for (tem = line; tem != 0; tem = tem->next) + for (node *tem = line; tem != 0; tem = tem->next) if (!tem->discardable()) first_non_discardable = tem; node *to_be_discarded; @@ -1773,6 +1723,9 @@ void environment::possibly_break_line(int forced) to_be_discarded = line; line = 0; } + // Do output_line() here so that line will be 0 iff the + // the environment will be empty. + output_line(pre, output_width); while (to_be_discarded != 0) { tem = to_be_discarded; to_be_discarded = to_be_discarded->next; @@ -1791,9 +1744,53 @@ void environment::possibly_break_line(int forced) } } +/* +Do the break at the end of input after the end macro (if any). + +Unix troff behaves as follows: if the last line is + +foo bar\c + +it will output foo on the current page, and bar on the next page; +if the last line is + +foo\c + +or + +foo bar + +everything will be output on the current page. This behaviour must be +considered a bug. + +The problem is that some macro packages rely on this. For example, +the ATK macros have an end macro that emits \c if it needs to print a +table of contents but doesn't do a 'bp in the end macro; instead the +'bp is done in the bottom of page trap. This works with Unix troff, +provided that the current environment is not empty at the end of the +input file. + +The following will make macro packages that do that sort of thing work +even if the current environment is empty at the end of the input file. +If the last input line used \c and this line occurred in the end macro, +then we'll force everything out on the current page, but we'll make +sure that the environment isn't empty so that we won't exit at the +bottom of this page. +*/ + +void environment::final_break() +{ + if (prev_line_interrupted == 2) { + do_break(); + add_node(new transparent_dummy_node); + } + else + do_break(); +} + void environment::do_break() { - if (curdiv == topdiv && !topdiv->first_page_begun) { + if (curdiv == topdiv && topdiv->before_first_page) { topdiv->begin_page(); return; } @@ -1829,6 +1826,7 @@ void environment::do_break() output_line(tem, width_total); hyphen_line_count = 0; } + prev_line_interrupted = 0; #ifdef WIDOW_CONTROL mark_last_line(); output_pending_lines(); @@ -1851,7 +1849,7 @@ void break_request() void title() { - if (curdiv == topdiv && !topdiv->first_page_begun) { + if (curdiv == topdiv && topdiv->before_first_page) { handle_initial_title(); return; } @@ -1906,9 +1904,8 @@ void title() void adjust() { - if (!has_arg()) - curenv->adjust_mode |= 1; - else + curenv->adjust_mode |= 1; + if (has_arg()) { switch (tok.ch()) { case 'l': curenv->adjust_mode = ADJUST_LEFT; @@ -1926,12 +1923,17 @@ void adjust() default: int n; if (get_integer(&n)) { - if (0 <= n && n <= 5) - curenv->adjust_mode = n; - else + if (n < 0) + warning(WARN_RANGE, "negative adjustment mode"); + else if (n > 5) { + curenv->adjust_mode = 5; warning(WARN_RANGE, "adjustment mode `%1' out of range", n); + } + else + curenv->adjust_mode = n; } } + } skip_line(); } @@ -1943,12 +1945,12 @@ void no_adjust() void input_trap() { + curenv->input_trap_count = 0; int n; - if (!has_arg()) - curenv->input_trap_count = 0; - else if (get_integer(&n)) { + if (has_arg() && get_integer(&n)) { if (n <= 0) - error("number of lines for input trap must be greater than zero"); + warning(WARN_RANGE, + "number of lines for input trap must be greater than zero"); else { symbol s = get_name(1); if (!s.is_null()) { @@ -1970,15 +1972,12 @@ struct tab { hunits pos; tab_type type; tab(hunits, tab_type); -#if 1 enum { BLOCK = 1024 }; static tab *free_list; void *operator new(size_t); void operator delete(void *); -#endif }; -#if 1 tab *tab::free_list = 0; void *tab::operator new(size_t n) @@ -2008,8 +2007,6 @@ void tab::operator delete(void *p) } } -#endif - tab::tab(hunits x, tab_type t) : next(0), pos(x), type(t) { } @@ -2064,7 +2061,7 @@ const char *tab_stops::to_string() int need = count*12 + 3; if (buf == 0 || need > buf_size) { if (buf) - delete buf; + a_delete buf; buf_size = need; buf = new char[buf_size]; } @@ -2181,6 +2178,7 @@ void set_tabs() { hunits pos; hunits prev_pos = 0; + int first = 1; int repeated = 0; tab_stops tabs; while (has_arg()) { @@ -2191,10 +2189,6 @@ void set_tabs() } if (!get_hunits(&pos, 'm', prev_pos)) break; - if (pos <= prev_pos) { - warning(WARN_RANGE, "positions of tab stops must be strictly increasing"); - continue; - } tab_type type = TAB_LEFT; if (tok.ch() == 'C') { tok.next(); @@ -2207,8 +2201,14 @@ void set_tabs() else if (tok.ch() == 'L') { tok.next(); } - tabs.add_tab(pos, type, repeated); - prev_pos = pos; + if (pos <= prev_pos && !first) + warning(WARN_RANGE, + "positions of tab stops must be strictly increasing"); + else { + tabs.add_tab(pos, type, repeated); + prev_pos = pos; + first = 0; + } } curenv->tabs = tabs; skip_line(); @@ -2279,8 +2279,8 @@ void environment::wrap_up_tab() tab_precedes_field = 0; } field_distance -= tab_amount; + field_spaces += tab_field_spaces; } - field_spaces += tab_field_spaces; if (tab_contents != 0) { for (node *tem = tab_contents; tem->next != 0; tem = tem->next) ; @@ -2347,7 +2347,10 @@ void environment::start_field() field_spaces = 0; tab_field_spaces = 0; for (node *p = line; p; p = p->next) - p->freeze_space(); + if (p->nspaces()) { + p->freeze_space(); + space_total--; + } tab_precedes_field = current_tab != TAB_NONE; } else @@ -2356,6 +2359,8 @@ void environment::start_field() void environment::wrap_up_field() { + if (!current_tab && field_spaces == 0) + add_padding(); hunits padding = field_distance - (get_text_length() - pre_field_width); if (current_tab && tab_field_spaces != 0) { hunits tab_padding = scale(padding, @@ -2400,6 +2405,20 @@ void environment::wrap_up_field() current_field = 0; } +void environment::add_padding() +{ + if (current_tab) { + tab_contents = new space_node(H0, tab_contents); + tab_field_spaces++; + } + else { + if (line == 0) + start_line(); + line = new space_node(H0, line); + field_spaces++; + } +} + typedef int (environment::*INT_FUNCP)(); typedef vunits (environment::*VUNITS_FUNCP)(); typedef hunits (environment::*HUNITS_FUNCP)(); @@ -2687,12 +2706,68 @@ void init_env_requests() // Hyphenation - TeX's hyphenation algorithm with a less fancy implementation. -const int WORD_MAX = 1024; +struct trie_node; + +class trie { + trie_node *tp; + virtual void do_match(int len, void *val) = 0; + virtual void do_delete(void *) = 0; + void delete_trie_node(trie_node *); +public: + trie() : tp(0) {} + virtual ~trie(); // virtual to shut up g++ + void insert(const char *, int, void *); + // find calls do_match for each match it finds + void find(const char *pat, int patlen); + void clear(); +}; + +class hyphen_trie : private trie { + int *h; + void do_match(int i, void *v); + void do_delete(void *v); + void insert_pattern(const char *pat, int patlen, int *num); +public: + hyphen_trie() {} + ~hyphen_trie() {} + void hyphenate(const char *word, int len, int *hyphens); + void read_patterns_file(const char *name); +}; + + +struct hyphenation_language { + symbol name; + dictionary exceptions; + hyphen_trie patterns; + hyphenation_language(symbol nm) : name(nm), exceptions(501) {} + ~hyphenation_language() { } +}; + +dictionary language_dictionary(5); +hyphenation_language *current_language = 0; -dictionary exception_dictionary(501); +static void set_hyphenation_language() +{ + symbol nm = get_name(1); + if (!nm.is_null()) { + current_language = (hyphenation_language *)language_dictionary.lookup(nm); + if (!current_language) { + current_language = new hyphenation_language(nm); + (void)language_dictionary.lookup(nm, (void *)current_language); + } + } + skip_line(); +} + +const int WORD_MAX = 1024; static void hyphen_word() { + if (!current_language) { + error("no current hyphenation language"); + skip_line(); + return; + } char buf[WORD_MAX + 1]; unsigned char pos[WORD_MAX + 2]; for (;;) { @@ -2724,60 +2799,52 @@ static void hyphen_word() buf[i] = 0; unsigned char *tem = new unsigned char[npos + 1]; memcpy(tem, pos, npos+1); - tem = (unsigned char *)exception_dictionary.lookup(symbol(buf), tem); + tem = (unsigned char *)current_language->exceptions.lookup(symbol(buf), + tem); if (tem) - delete tem; + a_delete tem; } } skip_line(); } -struct trie_node; - -class trie { - trie_node *tp; - virtual void do_match(int len, void *val) = 0; -public: - trie() : tp(0) {} - void insert(unsigned char *, int, void *); - // find calls do_match for each match it finds - void find(unsigned char *pat, int patlen); - void clear(); -}; - struct trie_node { - unsigned char c; + char c; trie_node *down; trie_node *right; void *val; - trie_node(unsigned char, trie_node *); - ~trie_node(); + trie_node(char, trie_node *); }; -trie_node::trie_node(unsigned char ch, trie_node *p) +trie_node::trie_node(char ch, trie_node *p) : c(ch), right(p), down(0), val(0) { } -trie_node::~trie_node() +trie::~trie() { - if (down) - delete down; - if (right) - delete right; - if (val) - delete val; + clear(); } void trie::clear() { - if (tp) { - delete tp; - tp = 0; + delete_trie_node(tp); + tp = 0; +} + + +void trie::delete_trie_node(trie_node *p) +{ + if (p) { + delete_trie_node(p->down); + delete_trie_node(p->right); + if (p->val) + do_delete(p->val); + delete p; } } -void trie::insert(unsigned char *pat, int patlen, void *val) +void trie::insert(const char *pat, int patlen, void *val) { trie_node **p = &tp; assert(patlen > 0 && pat != 0); @@ -2795,7 +2862,7 @@ void trie::insert(unsigned char *pat, int patlen, void *val) } } -void trie::find(unsigned char *pat, int patlen) +void trie::find(const char *pat, int patlen) { trie_node *p = tp; for (int i = 0; p != 0 && i < patlen; i++) { @@ -2811,16 +2878,6 @@ void trie::find(unsigned char *pat, int patlen) } } -class hyphen_trie : private trie { - int *h; - void do_match(int i, void *v); - void insert_pattern(unsigned char *pat, int patlen, int *num); -public: - hyphen_trie() {} - void hyphenate(unsigned char *word, int len, int *hyphens); - void read_patterns_file(const char *name); -}; - struct operation { operation *next; short distance; @@ -2833,7 +2890,7 @@ operation::operation(int i, int j, operation *op) { } -void hyphen_trie::insert_pattern(unsigned char *pat, int patlen, int *num) +void hyphen_trie::insert_pattern(const char *pat, int patlen, int *num) { operation *op = 0; for (int i = 0; i < patlen+1; i++) @@ -2842,7 +2899,7 @@ void hyphen_trie::insert_pattern(unsigned char *pat, int patlen, int *num) insert(pat, patlen, op); } -void hyphen_trie::hyphenate(unsigned char *word, int len, int *hyphens) +void hyphen_trie::hyphenate(const char *word, int len, int *hyphens) { for (int j = 0; j < len+1; j++) hyphens[j] = 0; @@ -2866,20 +2923,40 @@ void hyphen_trie::do_match(int i, void *v) } } - +void hyphen_trie::do_delete(void *v) +{ + operation *op = (operation *)v; + while (op) { + operation *tem = op; + op = tem->next; + delete tem; + } +} + void hyphen_trie::read_patterns_file(const char *name) { clear(); - unsigned char buf[WORD_MAX]; + char buf[WORD_MAX]; int num[WORD_MAX+1]; - FILE *fp = fopen(name, "r"); - if (fp == 0) - fatal("can't open hyphenation patterns file `%1': %2", - name, strerror(errno)); + errno = 0; + char *path = 0; + FILE *fp = macro_path.open_file(name, &path); + if (fp == 0) { + error("can't find hyphenation patterns file `%1'", name); + return; + } int c = getc(fp); for (;;) { - while (c != EOF && csspace(c)) + for (;;) { + if (c == '%') { + do { + c = getc(fp); + } while (c != EOF && c != '\n'); + } + if (c == EOF || !csspace(c)) + break; c = getc(fp); + } if (c == EOF) break; int i = 0; @@ -2892,16 +2969,18 @@ void hyphen_trie::read_patterns_file(const char *name) num[i] = 0; } c = getc(fp); - } while (i < WORD_MAX && c != EOF && !csspace(c)); + } while (i < WORD_MAX && c != EOF && !csspace(c) && c != '%'); insert_pattern(buf, i, num); } fclose(fp); + a_delete path; + return; } -hyphen_trie ht; - void hyphenate(hyphen_list *h, unsigned flags) { + if (!current_language) + return; while (h && h->hyphenation_code == 0) h = h->next; int len = 0; @@ -2915,7 +2994,7 @@ void hyphenate(hyphen_list *h, unsigned flags) } if (len > 2) { buf[len] = 0; - unsigned char *pos = (unsigned char *)exception_dictionary.lookup(buf); + unsigned char *pos = (unsigned char *)current_language->exceptions.lookup(buf); if (pos != 0) { int j = 0; int i = 1; @@ -2926,9 +3005,9 @@ void hyphenate(hyphen_list *h, unsigned flags) } } else { - hbuf[len+1] = '.'; + hbuf[0] = hbuf[len+1] = '.'; int num[WORD_MAX+3]; - ht.hyphenate((unsigned char *)hbuf, len+2, num); + current_language->patterns.hyphenate(hbuf, len+2, num); int i; num[2] = 0; if (flags & 8) @@ -2942,12 +3021,32 @@ void hyphenate(hyphen_list *h, unsigned flags) } } -void read_hyphen_file(const char *name) +static void hyphenation_patterns_file() +{ + symbol name = get_long_name(1); + if (!name.is_null()) { + if (!current_language) + error("no current hyphenation language"); + else + current_language->patterns.read_patterns_file(name.contents()); + } + skip_line(); +} + +class hyphenation_language_reg : public reg { +public: + const char *get_string(); +}; + +const char *hyphenation_language_reg::get_string() { - ht.read_patterns_file(name); + return current_language ? current_language->name.contents() : ""; } void init_hyphen_requests() { init_request("hw", hyphen_word); + init_request("hla", set_hyphenation_language); + init_request("hpf", hyphenation_patterns_file); + number_reg_dictionary.define(".hla", new hyphenation_language_reg); } diff --git a/gnu/usr.bin/groff/troff/env.h b/gnu/usr.bin/groff/troff/env.h index e8ca90dc9ea..14441e1f3ae 100644 --- a/gnu/usr.bin/groff/troff/env.h +++ b/gnu/usr.bin/groff/troff/env.h @@ -1,12 +1,12 @@ // -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.uucp) +/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) This file is part of groff. groff is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 1, or (at your option) any later +Software Foundation; either version 2, or (at your option) any later version. groff is distributed in the hope that it will be useful, but WITHOUT ANY @@ -15,7 +15,7 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along -with groff; see the file LICENSE. If not, write to the Free Software +with groff; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ struct size_range { @@ -62,6 +62,13 @@ inline int font_size::to_points() return p/sizescale; } +struct environment; + +hunits env_digit_width(environment *); +hunits env_space_width(environment *); +hunits env_sentence_space_width(environment *); +hunits env_narrow_space_width(environment *); +hunits env_half_narrow_space_width(environment *); struct tab; @@ -82,6 +89,9 @@ public: const char *to_string(); }; +const unsigned MARGIN_CHARACTER_ON = 1; +const unsigned MARGIN_CHARACTER_NEXT = 2; + struct charinfo; struct node; struct breakpoint; @@ -147,6 +157,7 @@ class environment { int tab_precedes_field; int discarding; int spread_flag; // set by \p + unsigned margin_character_flags; node *margin_character_node; hunits margin_character_distance; node *numbering_nodes; @@ -160,6 +171,7 @@ class environment { int hyphen_line_max; hunits hyphenation_space; hunits hyphenation_margin; + int composite; // used for construction of composite char? pending_output_line *pending_lines; #ifdef WIDOW_CONTROL int widow_control; @@ -179,6 +191,7 @@ class environment { void hyphenate_line(); void start_field(); void wrap_up_field(); + void add_padding(); node *make_tab_node(hunits d, node *next = 0); node *get_prev_char(); public: @@ -192,6 +205,8 @@ public: ~environment(); int is_dummy() { return dummy; } int is_empty(); + int is_composite() { return composite; } + void set_composite() { composite = 1; } vunits get_vertical_spacing(); // .v int get_line_spacing(); // .L int get_point_size() { return size.to_scaled_points(); } @@ -218,11 +233,12 @@ public: vunits get_prev_char_depth(); hunits get_text_length(); // .k hunits get_prev_text_length(); // .n - hunits get_space_width(); - int get_space_size(); // in ems/36 - int get_sentence_space_size(); - hunits get_narrow_space_width(); - hunits get_half_narrow_space_width(); + hunits get_space_width() { return env_space_width(this); } + int get_space_size() { return space_size; } // in ems/36 + int get_sentence_space_size() { return sentence_space_size; } + hunits get_narrow_space_width() { return env_narrow_space_width(this); } + hunits get_half_narrow_space_width() + { return env_half_narrow_space_width(this); } hunits get_input_line_position(); const char *get_tabs(); int get_hyphenation_flags(); @@ -247,6 +263,7 @@ public: void interrupt(); void spread() { spread_flag = 1; } void do_break(); // .br + void final_break(); void newline(); void handle_tab(int is_leader = 0); // do a tab or leader void add_node(node *); @@ -307,3 +324,4 @@ void read_hyphen_file(const char *name); extern int break_flag; extern symbol default_family; +extern int translate_space_to_dummy; diff --git a/gnu/usr.bin/groff/troff/hvunits.h b/gnu/usr.bin/groff/troff/hvunits.h index ccfde6835b9..4a1c5fd6d09 100644 --- a/gnu/usr.bin/groff/troff/hvunits.h +++ b/gnu/usr.bin/groff/troff/hvunits.h @@ -1,12 +1,12 @@ // -*- C++ -*- -/* Copyright (C) 1989, 1990 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.uucp) +/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) This file is part of groff. groff is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 1, or (at your option) any later +Software Foundation; either version 2, or (at your option) any later version. groff is distributed in the hope that it will be useful, but WITHOUT ANY @@ -15,7 +15,7 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along -with groff; see the file LICENSE. If not, write to the Free Software +with groff; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ @@ -28,21 +28,21 @@ public: int is_zero(); vunits& operator+=(const vunits&); vunits& operator-=(const vunits&); - friend vunits scale(vunits n, units x, units y); // scale n by x/y - friend vunits scale(vunits n, vunits x, vunits y); - friend vunits operator +(const vunits&, const vunits&); - friend vunits operator -(const vunits&, const vunits&); - friend vunits operator -(const vunits&); - friend int operator /(const vunits&, const vunits&); - friend vunits operator /(const vunits&, int); - friend vunits operator *(const vunits&, int); - friend vunits operator *(int, const vunits&); - friend int operator <(const vunits&, const vunits&); - friend int operator >(const vunits&, const vunits&); - friend int operator <=(const vunits&, const vunits&); - friend int operator >=(const vunits&, const vunits&); - friend int operator ==(const vunits&, const vunits&); - friend int operator !=(const vunits&, const vunits&); + friend inline vunits scale(vunits n, units x, units y); // scale n by x/y + friend inline vunits scale(vunits n, vunits x, vunits y); + friend inline vunits operator +(const vunits&, const vunits&); + friend inline vunits operator -(const vunits&, const vunits&); + friend inline vunits operator -(const vunits&); + friend inline int operator /(const vunits&, const vunits&); + friend inline vunits operator /(const vunits&, int); + friend inline vunits operator *(const vunits&, int); + friend inline vunits operator *(int, const vunits&); + friend inline int operator <(const vunits&, const vunits&); + friend inline int operator >(const vunits&, const vunits&); + friend inline int operator <=(const vunits&, const vunits&); + friend inline int operator >=(const vunits&, const vunits&); + friend inline int operator ==(const vunits&, const vunits&); + friend inline int operator !=(const vunits&, const vunits&); }; extern vunits V0; @@ -57,21 +57,21 @@ public: int is_zero(); hunits& operator+=(const hunits&); hunits& operator-=(const hunits&); - friend hunits scale(hunits n, units x, units y); // scale n by x/y - friend hunits scale(hunits n, double x); - friend hunits operator +(const hunits&, const hunits&); - friend hunits operator -(const hunits&, const hunits&); - friend hunits operator -(const hunits&); - friend int operator /(const hunits&, const hunits&); - friend hunits operator /(const hunits&, int); - friend hunits operator *(const hunits&, int); - friend hunits operator *(int, const hunits&); - friend int operator <(const hunits&, const hunits&); - friend int operator >(const hunits&, const hunits&); - friend int operator <=(const hunits&, const hunits&); - friend int operator >=(const hunits&, const hunits&); - friend int operator ==(const hunits&, const hunits&); - friend int operator !=(const hunits&, const hunits&); + friend inline hunits scale(hunits n, units x, units y); // scale n by x/y + friend inline hunits scale(hunits n, double x); + friend inline hunits operator +(const hunits&, const hunits&); + friend inline hunits operator -(const hunits&, const hunits&); + friend inline hunits operator -(const hunits&); + friend inline int operator /(const hunits&, const hunits&); + friend inline hunits operator /(const hunits&, int); + friend inline hunits operator *(const hunits&, int); + friend inline hunits operator *(int, const hunits&); + friend inline int operator <(const hunits&, const hunits&); + friend inline int operator >(const hunits&, const hunits&); + friend inline int operator <=(const hunits&, const hunits&); + friend inline int operator >=(const hunits&, const hunits&); + friend inline int operator ==(const hunits&, const hunits&); + friend inline int operator !=(const hunits&, const hunits&); }; extern hunits H0; diff --git a/gnu/usr.bin/groff/troff/hyphen.us b/gnu/usr.bin/groff/troff/hyphen.us new file mode 100644 index 00000000000..d86c3d58a7c --- /dev/null +++ b/gnu/usr.bin/groff/troff/hyphen.us @@ -0,0 +1,4449 @@ +% Hyphenation patterns for US English. +% These are the standard Plain TeX hyphenation patterns (in hyphen.tex). +.ach4 +.ad4der +.af1t +.al3t +.am5at +.an5c +.ang4 +.ani5m +.ant4 +.an3te +.anti5s +.ar5s +.ar4tie +.ar4ty +.as3c +.as1p +.as1s +.aster5 +.atom5 +.au1d +.av4i +.awn4 +.ba4g +.ba5na +.bas4e +.ber4 +.be5ra +.be3sm +.be5sto +.bri2 +.but4ti +.cam4pe +.can5c +.capa5b +.car5ol +.ca4t +.ce4la +.ch4 +.chill5i +.ci2 +.cit5r +.co3e +.co4r +.cor5ner +.de4moi +.de3o +.de3ra +.de3ri +.des4c +.dictio5 +.do4t +.du4c +.dumb5 +.earth5 +.eas3i +.eb4 +.eer4 +.eg2 +.el5d +.el3em +.enam3 +.en3g +.en3s +.eq5ui5t +.er4ri +.es3 +.eu3 +.eye5 +.fes3 +.for5mer +.ga2 +.ge2 +.gen3t4 +.ge5og +.gi5a +.gi4b +.go4r +.hand5i +.han5k +.he2 +.hero5i +.hes3 +.het3 +.hi3b +.hi3er +.hon5ey +.hon3o +.hov5 +.id4l +.idol3 +.im3m +.im5pin +.in1 +.in3ci +.ine2 +.in2k +.in3s +.ir5r +.is4i +.ju3r +.la4cy +.la4m +.lat5er +.lath5 +.le2 +.leg5e +.len4 +.lep5 +.lev1 +.li4g +.lig5a +.li2n +.li3o +.li4t +.mag5a5 +.mal5o +.man5a +.mar5ti +.me2 +.mer3c +.me5ter +.mis1 +.mist5i +.mon3e +.mo3ro +.mu5ta +.muta5b +.ni4c +.od2 +.odd5 +.of5te +.or5ato +.or3c +.or1d +.or3t +.os3 +.os4tl +.oth3 +.out3 +.ped5al +.pe5te +.pe5tit +.pi4e +.pio5n +.pi2t +.pre3m +.ra4c +.ran4t +.ratio5na +.ree2 +.re5mit +.res2 +.re5stat +.ri4g +.rit5u +.ro4q +.ros5t +.row5d +.ru4d +.sci3e +.self5 +.sell5 +.se2n +.se5rie +.sh2 +.si2 +.sing4 +.st4 +.sta5bl +.sy2 +.ta4 +.te4 +.ten5an +.th2 +.ti2 +.til4 +.tim5o5 +.ting4 +.tin5k +.ton4a +.to4p +.top5i +.tou5s +.trib5ut +.un1a +.un3ce +.under5 +.un1e +.un5k +.un5o +.un3u +.up3 +.ure3 +.us5a +.ven4de +.ve5ra +.wil5i +.ye4 +4ab. +a5bal +a5ban +abe2 +ab5erd +abi5a +ab5it5ab +ab5lat +ab5o5liz +4abr +ab5rog +ab3ul +a4car +ac5ard +ac5aro +a5ceou +ac1er +a5chet +4a2ci +a3cie +ac1in +a3cio +ac5rob +act5if +ac3ul +ac4um +a2d +ad4din +ad5er. +2adi +a3dia +ad3ica +adi4er +a3dio +a3dit +a5diu +ad4le +ad3ow +ad5ran +ad4su +4adu +a3duc +ad5um +ae4r +aeri4e +a2f +aff4 +a4gab +aga4n +ag5ell +age4o +4ageu +ag1i +4ag4l +ag1n +a2go +3agog +ag3oni +a5guer +ag5ul +a4gy +a3ha +a3he +ah4l +a3ho +ai2 +a5ia +a3ic. +ai5ly +a4i4n +ain5in +ain5o +ait5en +a1j +ak1en +al5ab +al3ad +a4lar +4aldi +2ale +al3end +a4lenti +a5le5o +al1i +al4ia. +ali4e +al5lev +4allic +4alm +a5log. +a4ly. +4alys +5a5lyst +5alyt +3alyz +4ama +am5ab +am3ag +ama5ra +am5asc +a4matis +a4m5ato +am5era +am3ic +am5if +am5ily +am1in +ami4no +a2mo +a5mon +amor5i +amp5en +a2n +an3age +3analy +a3nar +an3arc +anar4i +a3nati +4and +ande4s +an3dis +an1dl +an4dow +a5nee +a3nen +an5est. +a3neu +2ang +ang5ie +an1gl +a4n1ic +a3nies +an3i3f +an4ime +a5nimi +a5nine +an3io +a3nip +an3ish +an3it +a3niu +an4kli +5anniz +ano4 +an5ot +anoth5 +an2sa +an4sco +an4sn +an2sp +ans3po +an4st +an4sur +antal4 +an4tie +4anto +an2tr +an4tw +an3ua +an3ul +a5nur +4ao +apar4 +ap5at +ap5ero +a3pher +4aphi +a4pilla +ap5illar +ap3in +ap3ita +a3pitu +a2pl +apoc5 +ap5ola +apor5i +apos3t +aps5es +a3pu +aque5 +2a2r +ar3act +a5rade +ar5adis +ar3al +a5ramete +aran4g +ara3p +ar4at +a5ratio +ar5ativ +a5rau +ar5av4 +araw4 +arbal4 +ar4chan +ar5dine +ar4dr +ar5eas +a3ree +ar3ent +a5ress +ar4fi +ar4fl +ar1i +ar5ial +ar3ian +a3riet +ar4im +ar5inat +ar3io +ar2iz +ar2mi +ar5o5d +a5roni +a3roo +ar2p +ar3q +arre4 +ar4sa +ar2sh +4as. +as4ab +as3ant +ashi4 +a5sia. +a3sib +a3sic +5a5si4t +ask3i +as4l +a4soc +as5ph +as4sh +as3ten +as1tr +asur5a +a2ta +at3abl +at5ac +at3alo +at5ap +ate5c +at5ech +at3ego +at3en. +at3era +ater5n +a5terna +at3est +at5ev +4ath +ath5em +a5then +at4ho +ath5om +4ati. +a5tia +at5i5b +at1ic +at3if +ation5ar +at3itu +a4tog +a2tom +at5omiz +a4top +a4tos +a1tr +at5rop +at4sk +at4tag +at5te +at4th +a2tu +at5ua +at5ue +at3ul +at3ura +a2ty +au4b +augh3 +au3gu +au4l2 +aun5d +au3r +au5sib +aut5en +au1th +a2va +av3ag +a5van +ave4no +av3era +av5ern +av5ery +av1i +avi4er +av3ig +av5oc +a1vor +3away +aw3i +aw4ly +aws4 +ax4ic +ax4id +ay5al +aye4 +ays4 +azi4er +azz5i +5ba. +bad5ger +ba4ge +bal1a +ban5dag +ban4e +ban3i +barbi5 +bari4a +bas4si +1bat +ba4z +2b1b +b2be +b3ber +bbi4na +4b1d +4be. +beak4 +beat3 +4be2d +be3da +be3de +be3di +be3gi +be5gu +1bel +be1li +be3lo +4be5m +be5nig +be5nu +4bes4 +be3sp +be5str +3bet +bet5iz +be5tr +be3tw +be3w +be5yo +2bf +4b3h +bi2b +bi4d +3bie +bi5en +bi4er +2b3if +1bil +bi3liz +bina5r4 +bin4d +bi5net +bi3ogr +bi5ou +bi2t +3bi3tio +bi3tr +3bit5ua +b5itz +b1j +bk4 +b2l2 +blath5 +b4le. +blen4 +5blesp +b3lis +b4lo +blun4t +4b1m +4b3n +bne5g +3bod +bod3i +bo4e +bol3ic +bom4bi +bon4a +bon5at +3boo +5bor. +4b1ora +bor5d +5bore +5bori +5bos4 +b5ota +both5 +bo4to +bound3 +4bp +4brit +broth3 +2b5s2 +bsor4 +2bt +bt4l +b4to +b3tr +buf4fer +bu4ga +bu3li +bumi4 +bu4n +bunt4i +bu3re +bus5ie +buss4e +5bust +4buta +3butio +b5uto +b1v +4b5w +5by. +bys4 +1ca +cab3in +ca1bl +cach4 +ca5den +4cag4 +2c5ah +ca3lat +cal4la +call5in +4calo +can5d +can4e +can4ic +can5is +can3iz +can4ty +cany4 +ca5per +car5om +cast5er +cas5tig +4casy +ca4th +4cativ +cav5al +c3c +ccha5 +cci4a +ccompa5 +ccon4 +ccou3t +2ce. +4ced. +4ceden +3cei +5cel. +3cell +1cen +3cenc +2cen4e +4ceni +3cent +3cep +ce5ram +4cesa +3cessi +ces5si5b +ces5t +cet4 +c5e4ta +cew4 +2ch +4ch. +4ch3ab +5chanic +ch5a5nis +che2 +cheap3 +4ched +che5lo +3chemi +ch5ene +ch3er. +ch3ers +4ch1in +5chine. +ch5iness +5chini +5chio +3chit +chi2z +3cho2 +ch4ti +1ci +3cia +ci2a5b +cia5r +ci5c +4cier +5cific. +4cii +ci4la +3cili +2cim +2cin +c4ina +3cinat +cin3em +c1ing +c5ing. +5cino +cion4 +4cipe +ci3ph +4cipic +4cista +4cisti +2c1it +cit3iz +5ciz +ck1 +ck3i +1c4l4 +4clar +c5laratio +5clare +cle4m +4clic +clim4 +cly4 +c5n +1co +co5ag +coe2 +2cog +co4gr +coi4 +co3inc +col5i +5colo +col3or +com5er +con4a +c4one +con3g +con5t +co3pa +cop3ic +co4pl +4corb +coro3n +cos4e +cov1 +cove4 +cow5a +coz5e +co5zi +c1q +cras5t +5crat. +5cratic +cre3at +5cred +4c3reta +cre4v +cri2 +cri5f +c4rin +cris4 +5criti +cro4pl +crop5o +cros4e +cru4d +4c3s2 +2c1t +cta4b +ct5ang +c5tant +c2te +c3ter +c4ticu +ctim3i +ctu4r +c4tw +cud5 +c4uf +c4ui +cu5ity +5culi +cul4tis +3cultu +cu2ma +c3ume +cu4mi +3cun +cu3pi +cu5py +cur5a4b +cu5ria +1cus +cuss4i +3c4ut +cu4tie +4c5utiv +4cutr +1cy +cze4 +1d2a +5da. +2d3a4b +dach4 +4daf +2dag +da2m2 +dan3g +dard5 +dark5 +4dary +3dat +4dativ +4dato +5dav4 +dav5e +5day +d1b +d5c +d1d4 +2de. +deaf5 +deb5it +de4bon +decan4 +de4cil +de5com +2d1ed +4dee. +de5if +deli4e +del5i5q +de5lo +d4em +5dem. +3demic +dem5ic. +de5mil +de4mons +demor5 +1den +de4nar +de3no +denti5f +de3nu +de1p +de3pa +depi4 +de2pu +d3eq +d4erh +5derm +dern5iz +der5s +des2 +d2es. +de1sc +de2s5o +des3ti +de3str +de4su +de1t +de2to +de1v +dev3il +4dey +4d1f +d4ga +d3ge4t +dg1i +d2gy +d1h2 +5di. +1d4i3a +dia5b +di4cam +d4ice +3dict +3did +5di3en +d1if +di3ge +di4lato +d1in +1dina +3dine. +5dini +di5niz +1dio +dio5g +di4pl +dir2 +di1re +dirt5i +dis1 +5disi +d4is3t +d2iti +1di1v +d1j +d5k2 +4d5la +3dle. +3dled +3dles. +4dless +2d3lo +4d5lu +2dly +d1m +4d1n4 +1do +3do. +do5de +5doe +2d5of +d4og +do4la +doli4 +do5lor +dom5iz +do3nat +doni4 +doo3d +dop4p +d4or +3dos +4d5out +do4v +3dox +d1p +1dr +drag5on +4drai +dre4 +drea5r +5dren +dri4b +dril4 +dro4p +4drow +5drupli +4dry +2d1s2 +ds4p +d4sw +d4sy +d2th +1du +d1u1a +du2c +d1uca +duc5er +4duct. +4ducts +du5el +du4g +d3ule +dum4be +du4n +4dup +du4pe +d1v +d1w +d2y +5dyn +dy4se +dys5p +e1a4b +e3act +ead1 +ead5ie +ea4ge +ea5ger +ea4l +eal5er +eal3ou +eam3er +e5and +ear3a +ear4c +ear5es +ear4ic +ear4il +ear5k +ear2t +eart3e +ea5sp +e3ass +east3 +ea2t +eat5en +eath3i +e5atif +e4a3tu +ea2v +eav3en +eav5i +eav5o +2e1b +e4bel. +e4bels +e4ben +e4bit +e3br +e4cad +ecan5c +ecca5 +e1ce +ec5essa +ec2i +e4cib +ec5ificat +ec5ifie +ec5ify +ec3im +eci4t +e5cite +e4clam +e4clus +e2col +e4comm +e4compe +e4conc +e2cor +ec3ora +eco5ro +e1cr +e4crem +ec4tan +ec4te +e1cu +e4cul +ec3ula +2e2da +4ed3d +e4d1er +ede4s +4edi +e3dia +ed3ib +ed3ica +ed3im +ed1it +edi5z +4edo +e4dol +edon2 +e4dri +e4dul +ed5ulo +ee2c +eed3i +ee2f +eel3i +ee4ly +ee2m +ee4na +ee4p1 +ee2s4 +eest4 +ee4ty +e5ex +e1f +e4f3ere +1eff +e4fic +5efici +efil4 +e3fine +ef5i5nite +3efit +efor5es +e4fuse. +4egal +eger4 +eg5ib +eg4ic +eg5ing +e5git5 +eg5n +e4go. +e4gos +eg1ul +e5gur +5egy +e1h4 +eher4 +ei2 +e5ic +ei5d +eig2 +ei5gl +e3imb +e3inf +e1ing +e5inst +eir4d +eit3e +ei3th +e5ity +e1j +e4jud +ej5udi +eki4n +ek4la +e1la +e4la. +e4lac +elan4d +el5ativ +e4law +elaxa4 +e3lea +el5ebra +5elec +e4led +el3ega +e5len +e4l1er +e1les +el2f +el2i +e3libe +e4l5ic. +el3ica +e3lier +el5igib +e5lim +e4l3ing +e3lio +e2lis +el5ish +e3liv3 +4ella +el4lab +ello4 +e5loc +el5og +el3op. +el2sh +el4ta +e5lud +el5ug +e4mac +e4mag +e5man +em5ana +em5b +e1me +e2mel +e4met +em3ica +emi4e +em5igra +em1in2 +em5ine +em3i3ni +e4mis +em5ish +e5miss +em3iz +5emniz +emo4g +emoni5o +em3pi +e4mul +em5ula +emu3n +e3my +en5amo +e4nant +ench4er +en3dic +e5nea +e5nee +en3em +en5ero +en5esi +en5est +en3etr +e3new +en5ics +e5nie +e5nil +e3nio +en3ish +en3it +e5niu +5eniz +4enn +4eno +eno4g +e4nos +en3ov +en4sw +ent5age +4enthes +en3ua +en5uf +e3ny. +4en3z +e5of +eo2g +e4oi4 +e3ol +eop3ar +e1or +eo3re +eo5rol +eos4 +e4ot +eo4to +e5out +e5ow +e2pa +e3pai +ep5anc +e5pel +e3pent +ep5etitio +ephe4 +e4pli +e1po +e4prec +ep5reca +e4pred +ep3reh +e3pro +e4prob +ep4sh +ep5ti5b +e4put +ep5uta +e1q +equi3l +e4q3ui3s +er1a +era4b +4erand +er3ar +4erati. +2erb +er4bl +er3ch +er4che +2ere. +e3real +ere5co +ere3in +er5el. +er3emo +er5ena +er5ence +4erene +er3ent +ere4q +er5ess +er3est +eret4 +er1h +er1i +e1ria4 +5erick +e3rien +eri4er +er3ine +e1rio +4erit +er4iu +eri4v +e4riva +er3m4 +er4nis +4ernit +5erniz +er3no +2ero +er5ob +e5roc +ero4r +er1ou +er1s +er3set +ert3er +4ertl +er3tw +4eru +eru4t +5erwau +e1s4a +e4sage. +e4sages +es2c +e2sca +es5can +e3scr +es5cu +e1s2e +e2sec +es5ecr +es5enc +e4sert. +e4serts +e4serva +4esh +e3sha +esh5en +e1si +e2sic +e2sid +es5iden +es5igna +e2s5im +es4i4n +esis4te +esi4u +e5skin +es4mi +e2sol +es3olu +e2son +es5ona +e1sp +es3per +es5pira +es4pre +2ess +es4si4b +estan4 +es3tig +es5tim +4es2to +e3ston +2estr +e5stro +estruc5 +e2sur +es5urr +es4w +eta4b +eten4d +e3teo +ethod3 +et1ic +e5tide +etin4 +eti4no +e5tir +e5titio +et5itiv +4etn +et5ona +e3tra +e3tre +et3ric +et5rif +et3rog +et5ros +et3ua +et5ym +et5z +4eu +e5un +e3up +eu3ro +eus4 +eute4 +euti5l +eu5tr +eva2p5 +e2vas +ev5ast +e5vea +ev3ell +evel3o +e5veng +even4i +ev1er +e5verb +e1vi +ev3id +evi4l +e4vin +evi4v +e5voc +e5vu +e1wa +e4wag +e5wee +e3wh +ewil5 +ew3ing +e3wit +1exp +5eyc +5eye. +eys4 +1fa +fa3bl +fab3r +fa4ce +4fag +fain4 +fall5e +4fa4ma +fam5is +5far +far5th +fa3ta +fa3the +4fato +fault5 +4f5b +4fd +4fe. +feas4 +feath3 +fe4b +4feca +5fect +2fed +fe3li +fe4mo +fen2d +fend5e +fer1 +5ferr +fev4 +4f1f +f4fes +f4fie +f5fin. +f2f5is +f4fly +f2fy +4fh +1fi +fi3a +2f3ic. +4f3ical +f3ican +4ficate +f3icen +fi3cer +fic4i +5ficia +5ficie +4fics +fi3cu +fi5del +fight5 +fil5i +fill5in +4fily +2fin +5fina +fin2d5 +fi2ne +f1in3g +fin4n +fis4ti +f4l2 +f5less +flin4 +flo3re +f2ly5 +4fm +4fn +1fo +5fon +fon4de +fon4t +fo2r +fo5rat +for5ay +fore5t +for4i +fort5a +fos5 +4f5p +fra4t +f5rea +fres5c +fri2 +fril4 +frol5 +2f3s +2ft +f4to +f2ty +3fu +fu5el +4fug +fu4min +fu5ne +fu3ri +fusi4 +fus4s +4futa +1fy +1ga +gaf4 +5gal. +3gali +ga3lo +2gam +ga5met +g5amo +gan5is +ga3niz +gani5za +4gano +gar5n4 +gass4 +gath3 +4gativ +4gaz +g3b +gd4 +2ge. +2ged +geez4 +gel4in +ge5lis +ge5liz +4gely +1gen +ge4nat +ge5niz +4geno +4geny +1geo +ge3om +g4ery +5gesi +geth5 +4geto +ge4ty +ge4v +4g1g2 +g2ge +g3ger +gglu5 +ggo4 +gh3in +gh5out +gh4to +5gi. +1gi4a +gia5r +g1ic +5gicia +g4ico +gien5 +5gies. +gil4 +g3imen +3g4in. +gin5ge +5g4ins +5gio +3gir +gir4l +g3isl +gi4u +5giv +3giz +gl2 +gla4 +glad5i +5glas +1gle +gli4b +g3lig +3glo +glo3r +g1m +g4my +gn4a +g4na. +gnet4t +g1ni +g2nin +g4nio +g1no +g4non +1go +3go. +gob5 +5goe +3g4o4g +go3is +gon2 +4g3o3na +gondo5 +go3ni +5goo +go5riz +gor5ou +5gos. +gov1 +g3p +1gr +4grada +g4rai +gran2 +5graph. +g5rapher +5graphic +4graphy +4gray +gre4n +4gress. +4grit +g4ro +gruf4 +gs2 +g5ste +gth3 +gu4a +3guard +2gue +5gui5t +3gun +3gus +4gu4t +g3w +1gy +2g5y3n +gy5ra +h3ab4l +hach4 +hae4m +hae4t +h5agu +ha3la +hala3m +ha4m +han4ci +han4cy +5hand. +han4g +hang5er +hang5o +h5a5niz +han4k +han4te +hap3l +hap5t +ha3ran +ha5ras +har2d +hard3e +har4le +harp5en +har5ter +has5s +haun4 +5haz +haz3a +h1b +1head +3hear +he4can +h5ecat +h4ed +he5do5 +he3l4i +hel4lis +hel4ly +h5elo +hem4p +he2n +hena4 +hen5at +heo5r +hep5 +h4era +hera3p +her4ba +here5a +h3ern +h5erou +h3ery +h1es +he2s5p +he4t +het4ed +heu4 +h1f +h1h +hi5an +hi4co +high5 +h4il2 +himer4 +h4ina +hion4e +hi4p +hir4l +hi3ro +hir4p +hir4r +his3el +his4s +hith5er +hi2v +4hk +4h1l4 +hlan4 +h2lo +hlo3ri +4h1m +hmet4 +2h1n +h5odiz +h5ods +ho4g +hoge4 +hol5ar +3hol4e +ho4ma +home3 +hon4a +ho5ny +3hood +hoon4 +hor5at +ho5ris +hort3e +ho5ru +hos4e +ho5sen +hos1p +1hous +house3 +hov5el +4h5p +4hr4 +hree5 +hro5niz +hro3po +4h1s2 +h4sh +h4tar +ht1en +ht5es +h4ty +hu4g +hu4min +hun5ke +hun4t +hus3t4 +hu4t +h1w +h4wart +hy3pe +hy3ph +hy2s +2i1a +i2al +iam4 +iam5ete +i2an +4ianc +ian3i +4ian4t +ia5pe +iass4 +i4ativ +ia4tric +i4atu +ibe4 +ib3era +ib5ert +ib5ia +ib3in +ib5it. +ib5ite +i1bl +ib3li +i5bo +i1br +i2b5ri +i5bun +4icam +5icap +4icar +i4car. +i4cara +icas5 +i4cay +iccu4 +4iceo +4ich +2ici +i5cid +ic5ina +i2cip +ic3ipa +i4cly +i2c5oc +4i1cr +5icra +i4cry +ic4te +ictu2 +ic4t3ua +ic3ula +ic4um +ic5uo +i3cur +2id +i4dai +id5anc +id5d +ide3al +ide4s +i2di +id5ian +idi4ar +i5die +id3io +idi5ou +id1it +id5iu +i3dle +i4dom +id3ow +i4dr +i2du +id5uo +2ie4 +ied4e +5ie5ga +ield3 +ien5a4 +ien4e +i5enn +i3enti +i1er. +i3esc +i1est +i3et +4if. +if5ero +iff5en +if4fr +4ific. +i3fie +i3fl +4ift +2ig +iga5b +ig3era +ight3i +4igi +i3gib +ig3il +ig3in +ig3it +i4g4l +i2go +ig3or +ig5ot +i5gre +igu5i +ig1ur +i3h +4i5i4 +i3j +4ik +i1la +il3a4b +i4lade +i2l5am +ila5ra +i3leg +il1er +ilev4 +il5f +il1i +il3ia +il2ib +il3io +il4ist +2ilit +il2iz +ill5ab +4iln +il3oq +il4ty +il5ur +il3v +i4mag +im3age +ima5ry +imenta5r +4imet +im1i +im5ida +imi5le +i5mini +4imit +im4ni +i3mon +i2mu +im3ula +2in. +i4n3au +4inav +incel4 +in3cer +4ind +in5dling +2ine +i3nee +iner4ar +i5ness +4inga +4inge +in5gen +4ingi +in5gling +4ingo +4ingu +2ini +i5ni. +i4nia +in3io +in1is +i5nite. +5initio +in3ity +4ink +4inl +2inn +2i1no +i4no4c +ino4s +i4not +2ins +in3se +insur5a +2int. +2in4th +in1u +i5nus +4iny +2io +4io. +ioge4 +io2gr +i1ol +io4m +ion3at +ion4ery +ion3i +io5ph +ior3i +i4os +io5th +i5oti +io4to +i4our +2ip +ipe4 +iphras4 +ip3i +ip4ic +ip4re4 +ip3ul +i3qua +iq5uef +iq3uid +iq3ui3t +4ir +i1ra +ira4b +i4rac +ird5e +ire4de +i4ref +i4rel4 +i4res +ir5gi +ir1i +iri5de +ir4is +iri3tu +5i5r2iz +ir4min +iro4g +5iron. +ir5ul +2is. +is5ag +is3ar +isas5 +2is1c +is3ch +4ise +is3er +3isf +is5han +is3hon +ish5op +is3ib +isi4d +i5sis +is5itiv +4is4k +islan4 +4isms +i2so +iso5mer +is1p +is2pi +is4py +4is1s +is4sal +issen4 +is4ses +is4ta. +is1te +is1ti +ist4ly +4istral +i2su +is5us +4ita. +ita4bi +i4tag +4ita5m +i3tan +i3tat +2ite +it3era +i5teri +it4es +2ith +i1ti +4itia +4i2tic +it3ica +5i5tick +it3ig +it5ill +i2tim +2itio +4itis +i4tism +i2t5o5m +4iton +i4tram +it5ry +4itt +it3uat +i5tud +it3ul +4itz. +i1u +2iv +iv3ell +iv3en. +i4v3er. +i4vers. +iv5il. +iv5io +iv1it +i5vore +iv3o3ro +i4v3ot +4i5w +ix4o +4iy +4izar +izi4 +5izont +5ja +jac4q +ja4p +1je +jer5s +4jestie +4jesty +jew3 +jo4p +5judg +3ka. +k3ab +k5ag +kais4 +kal4 +k1b +k2ed +1kee +ke4g +ke5li +k3en4d +k1er +kes4 +k3est. +ke4ty +k3f +kh4 +k1i +5ki. +5k2ic +k4ill +kilo5 +k4im +k4in. +kin4de +k5iness +kin4g +ki4p +kis4 +k5ish +kk4 +k1l +4kley +4kly +k1m +k5nes +1k2no +ko5r +kosh4 +k3ou +kro5n +4k1s2 +k4sc +ks4l +k4sy +k5t +k1w +lab3ic +l4abo +laci4 +l4ade +la3dy +lag4n +lam3o +3land +lan4dl +lan5et +lan4te +lar4g +lar3i +las4e +la5tan +4lateli +4lativ +4lav +la4v4a +2l1b +lbin4 +4l1c2 +lce4 +l3ci +2ld +l2de +ld4ere +ld4eri +ldi4 +ld5is +l3dr +l4dri +le2a +le4bi +left5 +5leg. +5legg +le4mat +lem5atic +4len. +3lenc +5lene. +1lent +le3ph +le4pr +lera5b +ler4e +3lerg +3l4eri +l4ero +les2 +le5sco +5lesq +3less +5less. +l3eva +lev4er. +lev4era +lev4ers +3ley +4leye +2lf +l5fr +4l1g4 +l5ga +lgar3 +l4ges +lgo3 +2l3h +li4ag +li2am +liar5iz +li4as +li4ato +li5bi +5licio +li4cor +4lics +4lict. +l4icu +l3icy +l3ida +lid5er +3lidi +lif3er +l4iff +li4fl +5ligate +3ligh +li4gra +3lik +4l4i4l +lim4bl +lim3i +li4mo +l4im4p +l4ina +1l4ine +lin3ea +lin3i +link5er +li5og +4l4iq +lis4p +l1it +l2it. +5litica +l5i5tics +liv3er +l1iz +4lj +lka3 +l3kal +lka4t +l1l +l4law +l2le +l5lea +l3lec +l3leg +l3lel +l3le4n +l3le4t +ll2i +l2lin4 +l5lina +ll4o +lloqui5 +ll5out +l5low +2lm +l5met +lm3ing +l4mod +lmon4 +2l1n2 +3lo. +lob5al +lo4ci +4lof +3logic +l5ogo +3logu +lom3er +5long +lon4i +l3o3niz +lood5 +5lope. +lop3i +l3opm +lora4 +lo4rato +lo5rie +lor5ou +5los. +los5et +5losophiz +5losophy +los4t +lo4ta +loun5d +2lout +4lov +2lp +lpa5b +l3pha +l5phi +lp5ing +l3pit +l4pl +l5pr +4l1r +2l1s2 +l4sc +l2se +l4sie +4lt +lt5ag +ltane5 +l1te +lten4 +ltera4 +lth3i +l5ties. +ltis4 +l1tr +ltu2 +ltur3a +lu5a +lu3br +luch4 +lu3ci +lu3en +luf4 +lu5id +lu4ma +5lumi +l5umn. +5lumnia +lu3o +luo3r +4lup +luss4 +lus3te +1lut +l5ven +l5vet4 +2l1w +1ly +4lya +4lyb +ly5me +ly3no +2lys4 +l5yse +1ma +2mab +ma2ca +ma5chine +ma4cl +mag5in +5magn +2mah +maid5 +4mald +ma3lig +ma5lin +mal4li +mal4ty +5mania +man5is +man3iz +4map +ma5rine. +ma5riz +mar4ly +mar3v +ma5sce +mas4e +mas1t +5mate +math3 +ma3tis +4matiza +4m1b +mba4t5 +m5bil +m4b3ing +mbi4v +4m5c +4me. +2med +4med. +5media +me3die +m5e5dy +me2g +mel5on +mel4t +me2m +mem1o3 +1men +men4a +men5ac +men4de +4mene +men4i +mens4 +mensu5 +3ment +men4te +me5on +m5ersa +2mes +3mesti +me4ta +met3al +me1te +me5thi +m4etr +5metric +me5trie +me3try +me4v +4m1f +2mh +5mi. +mi3a +mid4a +mid4g +mig4 +3milia +m5i5lie +m4ill +min4a +3mind +m5inee +m4ingl +min5gli +m5ingly +min4t +m4inu +miot4 +m2is +mis4er. +mis5l +mis4ti +m5istry +4mith +m2iz +4mk +4m1l +m1m +mma5ry +4m1n +mn4a +m4nin +mn4o +1mo +4mocr +5mocratiz +mo2d1 +mo4go +mois2 +moi5se +4mok +mo5lest +mo3me +mon5et +mon5ge +moni3a +mon4ism +mon4ist +mo3niz +monol4 +mo3ny. +mo2r +4mora. +mos2 +mo5sey +mo3sp +moth3 +m5ouf +3mous +mo2v +4m1p +mpara5 +mpa5rab +mpar5i +m3pet +mphas4 +m2pi +mpi4a +mp5ies +m4p1in +m5pir +mp5is +mpo3ri +mpos5ite +m4pous +mpov5 +mp4tr +m2py +4m3r +4m1s2 +m4sh +m5si +4mt +1mu +mula5r4 +5mult +multi3 +3mum +mun2 +4mup +mu4u +4mw +1na +2n1a2b +n4abu +4nac. +na4ca +n5act +nag5er. +nak4 +na4li +na5lia +4nalt +na5mit +n2an +nanci4 +nan4it +nank4 +nar3c +4nare +nar3i +nar4l +n5arm +n4as +nas4c +nas5ti +n2at +na3tal +nato5miz +n2au +nau3se +3naut +nav4e +4n1b4 +ncar5 +n4ces. +n3cha +n5cheo +n5chil +n3chis +nc1in +nc4it +ncour5a +n1cr +n1cu +n4dai +n5dan +n1de +nd5est. +ndi4b +n5d2if +n1dit +n3diz +n5duc +ndu4r +nd2we +2ne. +n3ear +ne2b +neb3u +ne2c +5neck +2ned +ne4gat +neg5ativ +5nege +ne4la +nel5iz +ne5mi +ne4mo +1nen +4nene +3neo +ne4po +ne2q +n1er +nera5b +n4erar +n2ere +n4er5i +ner4r +1nes +2nes. +4nesp +2nest +4nesw +3netic +ne4v +n5eve +ne4w +n3f +n4gab +n3gel +nge4n4e +n5gere +n3geri +ng5ha +n3gib +ng1in +n5git +n4gla +ngov4 +ng5sh +n1gu +n4gum +n2gy +4n1h4 +nha4 +nhab3 +nhe4 +3n4ia +ni3an +ni4ap +ni3ba +ni4bl +ni4d +ni5di +ni4er +ni2fi +ni5ficat +n5igr +nik4 +n1im +ni3miz +n1in +5nine. +nin4g +ni4o +5nis. +nis4ta +n2it +n4ith +3nitio +n3itor +ni3tr +n1j +4nk2 +n5kero +n3ket +nk3in +n1kl +4n1l +n5m +nme4 +nmet4 +4n1n2 +nne4 +nni3al +nni4v +nob4l +no3ble +n5ocl +4n3o2d +3noe +4nog +noge4 +nois5i +no5l4i +5nologis +3nomic +n5o5miz +no4mo +no3my +no4n +non4ag +non5i +n5oniz +4nop +5nop5o5li +nor5ab +no4rary +4nosc +nos4e +nos5t +no5ta +1nou +3noun +nov3el3 +nowl3 +n1p4 +npi4 +npre4c +n1q +n1r +nru4 +2n1s2 +ns5ab +nsati4 +ns4c +n2se +n4s3es +nsid1 +nsig4 +n2sl +ns3m +n4soc +ns4pe +n5spi +nsta5bl +n1t +nta4b +nter3s +nt2i +n5tib +nti4er +nti2f +n3tine +n4t3ing +nti4p +ntrol5li +nt4s +ntu3me +nu1a +nu4d +nu5en +nuf4fe +n3uin +3nu3it +n4um +nu1me +n5umi +3nu4n +n3uo +nu3tr +n1v2 +n1w4 +nym4 +nyp4 +4nz +n3za +4oa +oad3 +o5a5les +oard3 +oas4e +oast5e +oat5i +ob3a3b +o5bar +obe4l +o1bi +o2bin +ob5ing +o3br +ob3ul +o1ce +och4 +o3chet +ocif3 +o4cil +o4clam +o4cod +oc3rac +oc5ratiz +ocre3 +5ocrit +octor5a +oc3ula +o5cure +od5ded +od3ic +odi3o +o2do4 +odor3 +od5uct. +od5ucts +o4el +o5eng +o3er +oe4ta +o3ev +o2fi +of5ite +ofit4t +o2g5a5r +og5ativ +o4gato +o1ge +o5gene +o5geo +o4ger +o3gie +1o1gis +og3it +o4gl +o5g2ly +3ogniz +o4gro +ogu5i +1ogy +2ogyn +o1h2 +ohab5 +oi2 +oic3es +oi3der +oiff4 +oig4 +oi5let +o3ing +oint5er +o5ism +oi5son +oist5en +oi3ter +o5j +2ok +o3ken +ok5ie +o1la +o4lan +olass4 +ol2d +old1e +ol3er +o3lesc +o3let +ol4fi +ol2i +o3lia +o3lice +ol5id. +o3li4f +o5lil +ol3ing +o5lio +o5lis. +ol3ish +o5lite +o5litio +o5liv +olli4e +ol5ogiz +olo4r +ol5pl +ol2t +ol3ub +ol3ume +ol3un +o5lus +ol2v +o2ly +om5ah +oma5l +om5atiz +om2be +om4bl +o2me +om3ena +om5erse +o4met +om5etry +o3mia +om3ic. +om3ica +o5mid +om1in +o5mini +5ommend +omo4ge +o4mon +om3pi +ompro5 +o2n +on1a +on4ac +o3nan +on1c +3oncil +2ond +on5do +o3nen +on5est +on4gu +on1ic +o3nio +on1is +o5niu +on3key +on4odi +on3omy +on3s +onspi4 +onspir5a +onsu4 +onten4 +on3t4i +ontif5 +on5um +onva5 +oo2 +ood5e +ood5i +oo4k +oop3i +o3ord +oost5 +o2pa +ope5d +op1er +3opera +4operag +2oph +o5phan +o5pher +op3ing +o3pit +o5pon +o4posi +o1pr +op1u +opy5 +o1q +o1ra +o5ra. +o4r3ag +or5aliz +or5ange +ore5a +o5real +or3ei +ore5sh +or5est. +orew4 +or4gu +4o5ria +or3ica +o5ril +or1in +o1rio +or3ity +o3riu +or2mi +orn2e +o5rof +or3oug +or5pe +3orrh +or4se +ors5en +orst4 +or3thi +or3thy +or4ty +o5rum +o1ry +os3al +os2c +os4ce +o3scop +4oscopi +o5scr +os4i4e +os5itiv +os3ito +os3ity +osi4u +os4l +o2so +os4pa +os4po +os2ta +o5stati +os5til +os5tit +o4tan +otele4g +ot3er. +ot5ers +o4tes +4oth +oth5esi +oth3i4 +ot3ic. +ot5ica +o3tice +o3tif +o3tis +oto5s +ou2 +ou3bl +ouch5i +ou5et +ou4l +ounc5er +oun2d +ou5v +ov4en +over4ne +over3s +ov4ert +o3vis +oviti4 +o5v4ol +ow3der +ow3el +ow5est +ow1i +own5i +o4wo +oy1a +1pa +pa4ca +pa4ce +pac4t +p4ad +5pagan +p3agat +p4ai +pain4 +p4al +pan4a +pan3el +pan4ty +pa3ny +pa1p +pa4pu +para5bl +par5age +par5di +3pare +par5el +p4a4ri +par4is +pa2te +pa5ter +5pathic +pa5thy +pa4tric +pav4 +3pay +4p1b +pd4 +4pe. +3pe4a +pear4l +pe2c +2p2ed +3pede +3pedi +pedia4 +ped4ic +p4ee +pee4d +pek4 +pe4la +peli4e +pe4nan +p4enc +pen4th +pe5on +p4era. +pera5bl +p4erag +p4eri +peri5st +per4mal +perme5 +p4ern +per3o +per3ti +pe5ru +per1v +pe2t +pe5ten +pe5tiz +4pf +4pg +4ph. +phar5i +phe3no +ph4er +ph4es. +ph1ic +5phie +ph5ing +5phisti +3phiz +ph2l +3phob +3phone +5phoni +pho4r +4phs +ph3t +5phu +1phy +pi3a +pian4 +pi4cie +pi4cy +p4id +p5ida +pi3de +5pidi +3piec +pi3en +pi4grap +pi3lo +pi2n +p4in. +pind4 +p4ino +3pi1o +pion4 +p3ith +pi5tha +pi2tu +2p3k2 +1p2l2 +3plan +plas5t +pli3a +pli5er +4plig +pli4n +ploi4 +plu4m +plum4b +4p1m +2p3n +po4c +5pod. +po5em +po3et5 +5po4g +poin2 +5point +poly5t +po4ni +po4p +1p4or +po4ry +1pos +pos1s +p4ot +po4ta +5poun +4p1p +ppa5ra +p2pe +p4ped +p5pel +p3pen +p3per +p3pet +ppo5site +pr2 +pray4e +5preci +pre5co +pre3em +pref5ac +pre4la +pre3r +p3rese +3press +pre5ten +pre3v +5pri4e +prin4t3 +pri4s +pris3o +p3roca +prof5it +pro3l +pros3e +pro1t +2p1s2 +p2se +ps4h +p4sib +2p1t +pt5a4b +p2te +p2th +pti3m +ptu4r +p4tw +pub3 +pue4 +puf4 +pul3c +pu4m +pu2n +pur4r +5pus +pu2t +5pute +put3er +pu3tr +put4ted +put4tin +p3w +qu2 +qua5v +2que. +3quer +3quet +2rab +ra3bi +rach4e +r5acl +raf5fi +raf4t +r2ai +ra4lo +ram3et +r2ami +rane5o +ran4ge +r4ani +ra5no +rap3er +3raphy +rar5c +rare4 +rar5ef +4raril +r2as +ration4 +rau4t +ra5vai +rav3el +ra5zie +r1b +r4bab +r4bag +rbi2 +rbi4f +r2bin +r5bine +rb5ing. +rb4o +r1c +r2ce +rcen4 +r3cha +rch4er +r4ci4b +rc4it +rcum3 +r4dal +rd2i +rdi4a +rdi4er +rdin4 +rd3ing +2re. +re1al +re3an +re5arr +5reav +re4aw +r5ebrat +rec5oll +rec5ompe +re4cre +2r2ed +re1de +re3dis +red5it +re4fac +re2fe +re5fer. +re3fi +re4fy +reg3is +re5it +re1li +re5lu +r4en4ta +ren4te +re1o +re5pin +re4posi +re1pu +r1er4 +r4eri +rero4 +re5ru +r4es. +re4spi +ress5ib +res2t +re5stal +re3str +re4ter +re4ti4z +re3tri +reu2 +re5uti +rev2 +re4val +rev3el +r5ev5er. +re5vers +re5vert +re5vil +rev5olu +re4wh +r1f +rfu4 +r4fy +rg2 +rg3er +r3get +r3gic +rgi4n +rg3ing +r5gis +r5git +r1gl +rgo4n +r3gu +rh4 +4rh. +4rhal +ri3a +ria4b +ri4ag +r4ib +rib3a +ric5as +r4ice +4rici +5ricid +ri4cie +r4ico +rid5er +ri3enc +ri3ent +ri1er +ri5et +rig5an +5rigi +ril3iz +5riman +rim5i +3rimo +rim4pe +r2ina +5rina. +rin4d +rin4e +rin4g +ri1o +5riph +riph5e +ri2pl +rip5lic +r4iq +r2is +r4is. +ris4c +r3ish +ris4p +ri3ta3b +r5ited. +rit5er. +rit5ers +rit3ic +ri2tu +rit5ur +riv5el +riv3et +riv3i +r3j +r3ket +rk4le +rk4lin +r1l +rle4 +r2led +r4lig +r4lis +rl5ish +r3lo4 +r1m +rma5c +r2me +r3men +rm5ers +rm3ing +r4ming. +r4mio +r3mit +r4my +r4nar +r3nel +r4ner +r5net +r3ney +r5nic +r1nis4 +r3nit +r3niv +rno4 +r4nou +r3nu +rob3l +r2oc +ro3cr +ro4e +ro1fe +ro5fil +rok2 +ro5ker +5role. +rom5ete +rom4i +rom4p +ron4al +ron4e +ro5n4is +ron4ta +1room +5root +ro3pel +rop3ic +ror3i +ro5ro +ros5per +ros4s +ro4the +ro4ty +ro4va +rov5el +rox5 +r1p +r4pea +r5pent +rp5er. +r3pet +rp4h4 +rp3ing +r3po +r1r4 +rre4c +rre4f +r4reo +rre4st +rri4o +rri4v +rron4 +rros4 +rrys4 +4rs2 +r1sa +rsa5ti +rs4c +r2se +r3sec +rse4cr +rs5er. +rs3es +rse5v2 +r1sh +r5sha +r1si +r4si4b +rson3 +r1sp +r5sw +rtach4 +r4tag +r3teb +rten4d +rte5o +r1ti +rt5ib +rti4d +r4tier +r3tig +rtil3i +rtil4l +r4tily +r4tist +r4tiv +r3tri +rtroph4 +rt4sh +ru3a +ru3e4l +ru3en +ru4gl +ru3in +rum3pl +ru2n +runk5 +run4ty +r5usc +ruti5n +rv4e +rvel4i +r3ven +rv5er. +r5vest +r3vey +r3vic +rvi4v +r3vo +r1w +ry4c +5rynge +ry3t +sa2 +2s1ab +5sack +sac3ri +s3act +5sai +salar4 +sal4m +sa5lo +sal4t +3sanc +san4de +s1ap +sa5ta +5sa3tio +sat3u +sau4 +sa5vor +5saw +4s5b +scan4t5 +sca4p +scav5 +s4ced +4scei +s4ces +sch2 +s4cho +3s4cie +5scin4d +scle5 +s4cli +scof4 +4scopy +scour5a +s1cu +4s5d +4se. +se4a +seas4 +sea5w +se2c3o +3sect +4s4ed +se4d4e +s5edl +se2g +seg3r +5sei +se1le +5self +5selv +4seme +se4mol +sen5at +4senc +sen4d +s5ened +sen5g +s5enin +4sentd +4sentl +sep3a3 +4s1er. +s4erl +ser4o +4servo +s1e4s +se5sh +ses5t +5se5um +5sev +sev3en +sew4i +5sex +4s3f +2s3g +s2h +2sh. +sh1er +5shev +sh1in +sh3io +3ship +shiv5 +sho4 +sh5old +shon3 +shor4 +short5 +4shw +si1b +s5icc +3side. +5sides +5sidi +si5diz +4signa +sil4e +4sily +2s1in +s2ina +5sine. +s3ing +1sio +5sion +sion5a +si2r +sir5a +1sis +3sitio +5siu +1siv +5siz +sk2 +4ske +s3ket +sk5ine +sk5ing +s1l2 +s3lat +s2le +slith5 +2s1m +s3ma +small3 +sman3 +smel4 +s5men +5smith +smol5d4 +s1n4 +1so +so4ce +soft3 +so4lab +sol3d2 +so3lic +5solv +3som +3s4on. +sona4 +son4g +s4op +5sophic +s5ophiz +s5ophy +sor5c +sor5d +4sov +so5vi +2spa +5spai +spa4n +spen4d +2s5peo +2sper +s2phe +3spher +spho5 +spil4 +sp5ing +4spio +s4ply +s4pon +spor4 +4spot +squal4l +s1r +2ss +s1sa +ssas3 +s2s5c +s3sel +s5seng +s4ses. +s5set +s1si +s4sie +ssi4er +ss5ily +s4sl +ss4li +s4sn +sspend4 +ss2t +ssur5a +ss5w +2st. +s2tag +s2tal +stam4i +5stand +s4ta4p +5stat. +s4ted +stern5i +s5tero +ste2w +stew5a +s3the +st2i +s4ti. +s5tia +s1tic +5stick +s4tie +s3tif +st3ing +5stir +s1tle +5stock +stom3a +5stone +s4top +3store +st4r +s4trad +5stratu +s4tray +s4trid +4stry +4st3w +s2ty +1su +su1al +su4b3 +su2g3 +su5is +suit3 +s4ul +su2m +sum3i +su2n +su2r +4sv +sw2 +4swo +s4y +4syc +3syl +syn5o +sy5rin +1ta +3ta. +2tab +ta5bles +5taboliz +4taci +ta5do +4taf4 +tai5lo +ta2l +ta5la +tal5en +tal3i +4talk +tal4lis +ta5log +ta5mo +tan4de +tanta3 +ta5per +ta5pl +tar4a +4tarc +4tare +ta3riz +tas4e +ta5sy +4tatic +ta4tur +taun4 +tav4 +2taw +tax4is +2t1b +4tc +t4ch +tch5et +4t1d +4te. +tead4i +4teat +tece4 +5tect +2t1ed +te5di +1tee +teg4 +te5ger +te5gi +3tel. +teli4 +5tels +te2ma2 +tem3at +3tenan +3tenc +3tend +4tenes +1tent +ten4tag +1teo +te4p +te5pe +ter3c +5ter3d +1teri +ter5ies +ter3is +teri5za +5ternit +ter5v +4tes. +4tess +t3ess. +teth5e +3teu +3tex +4tey +2t1f +4t1g +2th. +than4 +th2e +4thea +th3eas +the5at +the3is +3thet +th5ic. +th5ica +4thil +5think +4thl +th5ode +5thodic +4thoo +thor5it +tho5riz +2ths +1tia +ti4ab +ti4ato +2ti2b +4tick +t4ico +t4ic1u +5tidi +3tien +tif2 +ti5fy +2tig +5tigu +till5in +1tim +4timp +tim5ul +2t1in +t2ina +3tine. +3tini +1tio +ti5oc +tion5ee +5tiq +ti3sa +3tise +tis4m +ti5so +tis4p +5tistica +ti3tl +ti4u +1tiv +tiv4a +1tiz +ti3za +ti3zen +2tl +t5la +tlan4 +3tle. +3tled +3tles. +t5let. +t5lo +4t1m +tme4 +2t1n2 +1to +to3b +to5crat +4todo +2tof +to2gr +to5ic +to2ma +tom4b +to3my +ton4ali +to3nat +4tono +4tony +to2ra +to3rie +tor5iz +tos2 +5tour +4tout +to3war +4t1p +1tra +tra3b +tra5ch +traci4 +trac4it +trac4te +tras4 +tra5ven +trav5es5 +tre5f +tre4m +trem5i +5tria +tri5ces +5tricia +4trics +2trim +tri4v +tro5mi +tron5i +4trony +tro5phe +tro3sp +tro3v +tru5i +trus4 +4t1s2 +t4sc +tsh4 +t4sw +4t3t2 +t4tes +t5to +ttu4 +1tu +tu1a +tu3ar +tu4bi +tud2 +4tue +4tuf4 +5tu3i +3tum +tu4nis +2t3up. +3ture +5turi +tur3is +tur5o +tu5ry +3tus +4tv +tw4 +4t1wa +twis4 +4two +1ty +4tya +2tyl +type3 +ty5ph +4tz +tz4e +4uab +uac4 +ua5na +uan4i +uar5ant +uar2d +uar3i +uar3t +u1at +uav4 +ub4e +u4bel +u3ber +u4bero +u1b4i +u4b5ing +u3ble. +u3ca +uci4b +uc4it +ucle3 +u3cr +u3cu +u4cy +ud5d +ud3er +ud5est +udev4 +u1dic +ud3ied +ud3ies +ud5is +u5dit +u4don +ud4si +u4du +u4ene +uens4 +uen4te +uer4il +3ufa +u3fl +ugh3en +ug5in +2ui2 +uil5iz +ui4n +u1ing +uir4m +uita4 +uiv3 +uiv4er. +u5j +4uk +u1la +ula5b +u5lati +ulch4 +5ulche +ul3der +ul4e +u1len +ul4gi +ul2i +u5lia +ul3ing +ul5ish +ul4lar +ul4li4b +ul4lis +4ul3m +u1l4o +4uls +uls5es +ul1ti +ultra3 +4ultu +u3lu +ul5ul +ul5v +um5ab +um4bi +um4bly +u1mi +u4m3ing +umor5o +um2p +unat4 +u2ne +un4er +u1ni +un4im +u2nin +un5ish +uni3v +un3s4 +un4sw +unt3ab +un4ter. +un4tes +unu4 +un5y +un5z +u4ors +u5os +u1ou +u1pe +uper5s +u5pia +up3ing +u3pl +up3p +upport5 +upt5ib +uptu4 +u1ra +4ura. +u4rag +u4ras +ur4be +urc4 +ur1d +ure5at +ur4fer +ur4fr +u3rif +uri4fic +ur1in +u3rio +u1rit +ur3iz +ur2l +url5ing. +ur4no +uros4 +ur4pe +ur4pi +urs5er +ur5tes +ur3the +urti4 +ur4tie +u3ru +2us +u5sad +u5san +us4ap +usc2 +us3ci +use5a +u5sia +u3sic +us4lin +us1p +us5sl +us5tere +us1tr +u2su +usur4 +uta4b +u3tat +4ute. +4utel +4uten +uten4i +4u1t2i +uti5liz +u3tine +ut3ing +ution5a +u4tis +5u5tiz +u4t1l +ut5of +uto5g +uto5matic +u5ton +u4tou +uts4 +u3u +uu4m +u1v2 +uxu3 +uz4e +1va +5va. +2v1a4b +vac5il +vac3u +vag4 +va4ge +va5lie +val5o +val1u +va5mo +va5niz +va5pi +var5ied +3vat +4ve. +4ved +veg3 +v3el. +vel3li +ve4lo +v4ely +ven3om +v5enue +v4erd +5vere. +v4erel +v3eren +ver5enc +v4eres +ver3ie +vermi4n +3verse +ver3th +v4e2s +4ves. +ves4te +ve4te +vet3er +ve4ty +vi5ali +5vian +5vide. +5vided +4v3iden +5vides +5vidi +v3if +vi5gn +vik4 +2vil +5vilit +v3i3liz +v1in +4vi4na +v2inc +vin5d +4ving +vio3l +v3io4r +vi1ou +vi4p +vi5ro +vis3it +vi3so +vi3su +4viti +vit3r +4vity +3viv +5vo. +voi4 +3vok +vo4la +v5ole +5volt +3volv +vom5i +vor5ab +vori4 +vo4ry +vo4ta +4votee +4vv4 +v4y +w5abl +2wac +wa5ger +wag5o +wait5 +w5al. +wam4 +war4t +was4t +wa1te +wa5ver +w1b +wea5rie +weath3 +wed4n +weet3 +wee5v +wel4l +w1er +west3 +w3ev +whi4 +wi2 +wil2 +will5in +win4de +win4g +wir4 +3wise +with3 +wiz5 +w4k +wl4es +wl3in +w4no +1wo2 +wom1 +wo5ven +w5p +wra4 +wri4 +writa4 +w3sh +ws4l +ws4pe +w5s4t +4wt +wy4 +x1a +xac5e +x4ago +xam3 +x4ap +xas5 +x3c2 +x1e +xe4cuto +x2ed +xer4i +xe5ro +x1h +xhi2 +xhil5 +xhu4 +x3i +xi5a +xi5c +xi5di +x4ime +xi5miz +x3o +x4ob +x3p +xpan4d +xpecto5 +xpe3d +x1t2 +x3ti +x1u +xu3a +xx4 +y5ac +3yar4 +y5at +y1b +y1c +y2ce +yc5er +y3ch +ych4e +ycom4 +ycot4 +y1d +y5ee +y1er +y4erf +yes4 +ye4t +y5gi +4y3h +y1i +y3la +ylla5bl +y3lo +y5lu +ymbol5 +yme4 +ympa3 +yn3chr +yn5d +yn5g +yn5ic +5ynx +y1o4 +yo5d +y4o5g +yom4 +yo5net +y4ons +y4os +y4ped +yper5 +yp3i +y3po +y4poc +yp2ta +y5pu +yra5m +yr5ia +y3ro +yr4r +ys4c +y3s2e +ys3ica +ys3io +3ysis +y4so +yss4 +ys1t +ys3ta +ysur4 +y3thin +yt3ic +y1w +za1 +z5a2b +zar2 +4zb +2ze +ze4n +ze4p +z1er +ze3ro +zet4 +2z1i +z4il +z4is +5zl +4zm +1zo +zo4m +zo5ol +zte4 +4z1z2 +z4zy diff --git a/gnu/usr.bin/groff/troff/input.cc b/gnu/usr.bin/groff/troff/input.cc index 4dc6488bf0a..609ee78edf2 100644 --- a/gnu/usr.bin/groff/troff/input.cc +++ b/gnu/usr.bin/groff/troff/input.cc @@ -1,12 +1,12 @@ // -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.uucp) +/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) This file is part of groff. groff is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 1, or (at your option) any later +Software Foundation; either version 2, or (at your option) any later version. groff is distributed in the hope that it will be useful, but WITHOUT ANY @@ -15,32 +15,10 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along -with groff; see the file LICENSE. If not, write to the Free Software +with groff; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#ifndef MACROPATH -#define MACROPATH ".:/usr/local/lib/groff" -#endif - -#ifndef DEVICE -#define DEVICE "ps" -#endif - -#ifndef HYPHENFILE -#define HYPHENFILE "/usr/local/lib/groff/hyphen" -#endif - -#define MACROPATH_ENVVAR "GROFF_TMAC_PATH" - -#define DEFAULT_INPUT_STACK_LIMIT 1000 - -#ifndef DEFAULT_WARNING_MASK -// warnings that are enabled by default -#define DEFAULT_WARNING_MASK (WARN_CHAR|WARN_NUMBER|WARN_BREAK|WARN_SPACE) -#endif - -#include "groff.h" +#include "troff.h" #include "symbol.h" #include "dictionary.h" #include "hvunits.h" @@ -52,6 +30,23 @@ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "div.h" #include "charinfo.h" #include "font.h" +#include "searchpath.h" +#include "macropath.h" +#include "defs.h" + +// Needed for getpid(). +#include "posix.h" + +#define USAGE_EXIT_CODE 1 +#define MACRO_PREFIX "tmac." +#define STARTUP_FILE "troffrc" +#define DEFAULT_INPUT_STACK_LIMIT 1000 + +#ifndef DEFAULT_WARNING_MASK +// warnings that are enabled by default +#define DEFAULT_WARNING_MASK \ + (WARN_CHAR|WARN_NUMBER|WARN_BREAK|WARN_SPACE|WARN_FONT) +#endif // initial size of buffer for reading names; expanded as necessary #define ABUF_SIZE 16 @@ -62,6 +57,7 @@ void init_column_requests(); static node *read_draw_node(); void handle_first_page_transition(); +static void push_token(const token &); void copy_file(); #ifdef COLUMN void vjustify(); @@ -71,7 +67,6 @@ void transparent_file(); const char *program_name = 0; token tok; -const char *device = DEVICE; int break_flag = 0; static int backtrace_flag = 0; char *pipe_command = 0; @@ -97,6 +92,7 @@ static symbol read_escape_name(); static void interpolate_string(symbol); static void interpolate_macro(symbol); static void interpolate_number_format(symbol); +static void interpolate_environment_variable(symbol); static void interpolate_arg(symbol); static request_or_macro *lookup_request(symbol); @@ -111,7 +107,6 @@ struct input_iterator; input_iterator *make_temp_iterator(const char *); const char *input_char_description(int); -const int ESCAPE_RIGHT_PARENTHESIS = 014; const int ESCAPE_QUESTION = 015; const int BEGIN_TRAP = 016; const int END_TRAP = 017; @@ -139,15 +134,21 @@ const int TRANSPARENT_FILE_REQUEST = 0202; const int VJUSTIFY_REQUEST = 0203; #endif /* COLUMN */ const int ESCAPE_E = 0204; +const int LAST_PAGE_EJECTOR = 0205; +const int ESCAPE_RIGHT_PARENTHESIS = 0206; void set_escape_char() { - if (!has_arg()) - escape_char = '\\'; - else if (!tok.ch()) - error("bad escape character"); + if (has_arg()) { + if (tok.ch() == 0) { + error("bad escape character"); + escape_char = '\\'; + } + else + escape_char = tok.ch(); + } else - escape_char = tok.ch(); + escape_char = '\\'; skip_line(); } @@ -179,9 +180,10 @@ private: virtual int set_location(const char *, int) { return 0; } virtual int next_file(FILE *, const char *) { return 0; } - virtual void shift(int n) {} + virtual void shift(int) {} virtual int is_boundary(); virtual int internal_level() { return 0; } + virtual int is_file() { return 0; } }; input_iterator::input_iterator() @@ -235,6 +237,7 @@ public: void backtrace(); int set_location(const char *, int); int next_file(FILE *, const char *); + int is_file(); }; file_iterator::file_iterator(FILE *f, const char *fn) @@ -250,6 +253,11 @@ file_iterator::~file_iterator() clearerr(stdin); } +int file_iterator::is_file() +{ + return 1; +} + int file_iterator::next_file(FILE *f, const char *s) { if (fp != stdin) @@ -347,6 +355,7 @@ public: static void backtrace(); static void backtrace_all(); static void next_file(FILE *, const char *); + static void end_file(); static void shift(int n); static void add_boundary(); static void remove_boundary(); @@ -438,7 +447,7 @@ void input_stack::push(input_iterator *in) if (in == 0) return; if (++level > limit && limit > 0) - fatal("input stack limit exceeded"); + fatal("input stack limit exceeded (probable infinite loop)"); in->next = top; top = in; } @@ -479,7 +488,7 @@ int input_stack::get_location(int allow_macro, const char **filenamep, int *line void input_stack::backtrace() { - char *f; + const char *f; int n; // only backtrace down to (not including) the topmost file for (input_iterator *p = top; @@ -504,22 +513,41 @@ int input_stack::set_location(const char *filename, int lineno) void input_stack::next_file(FILE *fp, const char *s) { - for (input_iterator *p = top; p; p = p->next) - if (p->next_file(fp, s)) + for (input_iterator **pp = ⊤ *pp != &nil_iterator; pp = &(*pp)->next) + if ((*pp)->next_file(fp, s)) return; - for (input_iterator **pp = ⊤ *pp; pp = &(*pp)->next) - ; + if (++level > limit && limit > 0) + fatal("input stack limit exceeded"); *pp = new file_iterator(fp, s); + (*pp)->next = &nil_iterator; +} + +void input_stack::end_file() +{ + for (input_iterator **pp = ⊤ *pp != &nil_iterator; pp = &(*pp)->next) + if ((*pp)->is_file()) { + input_iterator *tem = *pp; + *pp = (*pp)->next; + delete tem; + level--; + return; + } } void input_stack::clear() { - while (!top->is_boundary() && top != &nil_iterator) { + int nboundaries = 0; + while (top != &nil_iterator) { + if (top->is_boundary()) + nboundaries++; input_iterator *tem = top; top = top->next; level--; delete tem; } + // Keep while_request happy. + for (; nboundaries > 0; --nboundaries) + add_boundary(); } void backtrace_request() @@ -531,10 +559,13 @@ void backtrace_request() void next_file() { - symbol nm = get_long_name(1); + symbol nm = get_long_name(0); while (!tok.newline() && !tok.eof()) tok.next(); - if (!nm.is_null()) { + if (nm.is_null()) + input_stack::end_file(); + else { + errno = 0; FILE *fp = fopen(nm.contents(), "r"); if (!fp) error("can't open `%1': %2", nm.contents(), strerror(errno)); @@ -546,9 +577,10 @@ void next_file() void shift() { - int n = 1; - if (!has_arg() || get_integer(&n)) - input_stack::shift(n); + int n; + if (!has_arg() || !get_integer(&n)) + n = 1; + input_stack::shift(n); skip_line(); } @@ -590,6 +622,7 @@ static symbol read_two_char_escape_name() static symbol read_long_escape_name() { + int start_level = input_stack::get_level(); char abuf[ABUF_SIZE]; char *buf = abuf; int buf_size = ABUF_SIZE; @@ -598,7 +631,7 @@ static symbol read_long_escape_name() int c = get_char_for_escape_name(); if (c == 0) { if (buf != abuf) - delete buf; + a_delete buf; return NULL_SYMBOL; } if (i + 2 > buf_size) { @@ -612,10 +645,10 @@ static symbol read_long_escape_name() buf = new char[buf_size*2]; memcpy(buf, old_buf, buf_size); buf_size *= 2; - delete old_buf; + a_delete old_buf; } } - if (c == ']') + if (c == ']' && input_stack::get_level() == start_level) break; buf[i++] = c; } @@ -629,7 +662,7 @@ static symbol read_long_escape_name() } else { symbol s(buf); - delete buf; + a_delete buf; return s; } } @@ -649,6 +682,36 @@ static symbol read_escape_name() return symbol(buf); } +static symbol read_increment_and_escape_name(int *incp) +{ + int c = get_char_for_escape_name(); + switch (c) { + case 0: + *incp = 0; + return NULL_SYMBOL; + case '(': + *incp = 0; + return read_two_char_escape_name(); + case '+': + *incp = 1; + return read_escape_name(); + case '-': + *incp = -1; + return read_escape_name(); + case '[': + if (!compatible_flag) { + *incp = 0; + return read_long_escape_name(); + } + break; + } + *incp = 0; + char buf[2]; + buf[0] = c; + buf[1] = '\0'; + return symbol(buf); +} + static int get_copy(node **nd, int defining) { for (;;) { @@ -671,6 +734,12 @@ static int get_copy(node **nd, int defining) while ((c = input_stack::get(NULL)) != '\n' && c != EOF) ; return c; + case '#': // Like \" but newline is ignored. + (void)input_stack::get(NULL); + while ((c = input_stack::get(NULL)) != '\n') + if (c == EOF) + return EOF; + break; case '$': { (void)input_stack::get(NULL); @@ -699,18 +768,10 @@ static int get_copy(node **nd, int defining) case 'n': { (void)input_stack::get(NULL); - int inc = 0; - symbol s = read_escape_name(); - const char *p = s.contents(); - if (p != 0) { - if ((p[0] == '+' || p[0] == '-') && p[1] == '\0') { - inc = p[0] == '+' ? 1 : -1; - s = read_escape_name(); - if (s.is_null()) - break; - } + int inc; + symbol s = read_increment_and_escape_name(&inc); + if (!s.is_null()) interpolate_number_reg(s, inc); - } break; } case 'g': @@ -724,6 +785,14 @@ static int get_copy(node **nd, int defining) case 't': (void)input_stack::get(NULL); return '\t'; + case 'V': + { + (void)input_stack::get(NULL); + symbol s = read_escape_name(); + if (!s.is_null()) + interpolate_environment_variable(s); + break; + } case '\n': (void)input_stack::get(NULL); if (defining) @@ -827,6 +896,7 @@ int non_interpreted_char_node::interpret(macro *mac) static void do_width(); static node *do_non_interpreted(); static node *do_special(); +static void do_register(); static node *do_overstrike() { @@ -839,15 +909,11 @@ static node *do_overstrike() warning(WARN_DELIM, "missing closing delimiter"); break; } - if (tok.changes_env()) - tok.process(); - else { - charinfo *ci = tok.get_char(1); - if (ci) { - node *n = curenv->make_char_node(ci); - if (n) - on->overstrike(n); - } + charinfo *ci = tok.get_char(1); + if (ci) { + node *n = curenv->make_char_node(ci); + if (n) + on->overstrike(n); } tok.next(); } @@ -870,15 +936,11 @@ static node *do_bracket() input_stack::push(make_temp_iterator("\n")); break; } - if (tok.changes_env()) - tok.process(); - else { - charinfo *ci = tok.get_char(1); - if (ci) { - node *n = curenv->make_char_node(ci); - if (n) - bn->bracket(n); - } + charinfo *ci = tok.get_char(1); + if (ci) { + node *n = curenv->make_char_node(ci); + if (n) + bn->bracket(n); } tok.next(); } @@ -890,7 +952,8 @@ static int do_name_test() token start; start.next(); int start_level = input_stack::get_level(); - int result = 1; + int bad_char = 0; + int some_char = 0; for (;;) { tok.next(); if (tok.newline() || tok.eof()) { @@ -901,9 +964,10 @@ static int do_name_test() && (compatible_flag || input_stack::get_level() == start_level)) break; if (!tok.ch()) - result = 0; + bad_char = 1; + some_char = 1; } - return result; + return some_char && !bad_char; } #if 0 @@ -1024,14 +1088,18 @@ token::~token() token::token(const token &t) : nm(t.nm), c(t.c), val(t.val), dim(t.dim), type(t.type) { - nd = t.nd ? t.nd->copy() : 0; + // Use two statements to work around bug in SGI C++. + node *tem = t.nd; + nd = tem ? tem->copy() : 0; } void token::operator=(const token &t) { delete nd; nm = t.nm; - nd = t.nd ? t.nd->copy() : 0; + // Use two statements to work around bug in SGI C++. + node *tem = t.nd; + nd = tem ? tem->copy() : 0; c = t.c; val = t.val; dim = t.dim; @@ -1092,6 +1160,9 @@ void token::next() case END_TRAP: type = TOKEN_END_TRAP; return; + case LAST_PAGE_EJECTOR: + seen_last_page_ejector = 1; + // fall through case PAGE_EJECTOR: type = TOKEN_PAGE_EJECTOR; return; @@ -1191,13 +1262,17 @@ void token::next() type = TOKEN_LEADER; return; case 0: - assert(n != 0); - token_node *tn = n->get_token_node(); - if (tn) - *this = tn->tk; - else { - nd = n; - type = TOKEN_NODE; + { + assert(n != 0); + token_node *tn = n->get_token_node(); + if (tn) { + *this = tn->tk; + delete tn; + } + else { + nd = n; + type = TOKEN_NODE; + } } return; default: @@ -1253,6 +1328,10 @@ void token::next() goto ESCAPE_BANG; case '?': goto ESCAPE_QUESTION; + case '~': + nd = new unbreakable_space_node(curenv->get_space_width()); + type = TOKEN_NODE; + return; case '"': while ((cc = input_stack::get(NULL)) != '\n' && cc != EOF) ; @@ -1261,6 +1340,13 @@ void token::next() else type = TOKEN_EOF; return; + case '#': // Like \" but newline is ignored. + while ((cc = input_stack::get(NULL)) != '\n') + if (cc == EOF) { + type = TOKEN_EOF; + return; + } + break; case '$': { symbol nm = read_escape_name(); @@ -1315,14 +1401,13 @@ void token::next() if (s.is_null()) break; for (const char *p = s.contents(); *p != '\0'; p++) - if (!csdigit(*p)) { - type = TOKEN_FONT_NAME; - nm = s; - return; - } - type = TOKEN_FONT_POSITION; - val = atoi(s.contents()); - return; + if (!csdigit(*p)) + break; + if (*p) + curenv->set_font(s); + else + curenv->set_font(atoi(s.contents())); + break; } case 'g': { @@ -1338,11 +1423,9 @@ void token::next() nd = new hmotion_node(x); return; case 'H': - if (!get_delim_number(&x, 'z', curenv->get_requested_point_size())) - break; - type = TOKEN_CHAR_HEIGHT; - val = x; - return; + if (get_delim_number(&x, 'z', curenv->get_requested_point_size())) + curenv->set_char_height(x); + break; case 'k': nm = read_escape_name(); if (nm.is_null()) @@ -1367,28 +1450,15 @@ void token::next() } case 'n': { - symbol nm = read_escape_name(); - if (nm.is_null()) - break; - int inc = 0; - const char *p = nm.contents(); - if (p != 0 && (p[0] == '+' || p[0] == '-') && p[1] == '\0') { - inc = p[0] == '+' ? 1 : -1; - nm = read_escape_name(); - if (nm.is_null()) - break; - } - interpolate_number_reg(nm, inc); + int inc; + symbol nm = read_increment_and_escape_name(&inc); + if (!nm.is_null()) + interpolate_number_reg(nm, inc); break; } case 'N': - if (!get_delim_number(&x, 0)) + if (!get_delim_number(&val, 0)) break; - if (x < 0 || x > 255) { - error("code %1 out of range", x); - break; - } - c = (unsigned char)x; type = TOKEN_NUMBERED_CHAR; return; case 'o': @@ -1402,18 +1472,17 @@ void token::next() type = TOKEN_NODE; nd = new vmotion_node(-curenv->get_size()); return; + case 'R': + do_register(); + break; case 's': - if (!read_size(&x)) - break; - type = TOKEN_SIZE; - val = x; - return; + if (read_size(&x)) + curenv->set_size(x); + break; case 'S': - if (!get_delim_number(&x, 0)) - break; - type = TOKEN_CHAR_SLANT; - val = x; - return; + if (get_delim_number(&x, 0)) + curenv->set_char_slant(x); + break; case 't': type = TOKEN_NODE; nd = new non_interpreted_char_node('\t'); @@ -1428,6 +1497,13 @@ void token::next() type = TOKEN_NODE; nd = new vmotion_node(x); return; + case 'V': + { + symbol nm = read_escape_name(); + if (!nm.is_null()) + interpolate_environment_variable(nm); + break; + } case 'w': do_width(); break; @@ -1451,7 +1527,7 @@ void token::next() request_or_macro *p = lookup_request(s); macro *m = p->to_macro(); if (!m) { - error("can transparently throughput a request"); + error("can't transparently throughput a request"); break; } nd = new special_node(*m); @@ -1461,14 +1537,18 @@ void token::next() case 'z': { next(); - charinfo *ci = get_char(1); - if (ci == 0) - break; - node *gn = curenv->make_char_node(ci); - if (gn == 0) - break; - nd = new zero_width_node(gn); - type = TOKEN_NODE; + if (type == TOKEN_NODE) + nd = new zero_width_node(nd); + else { + charinfo *ci = get_char(1); + if (ci == 0) + break; + node *gn = curenv->make_char_node(ci); + if (gn == 0) + break; + nd = new zero_width_node(gn); + type = TOKEN_NODE; + } return; } case 'Z': @@ -1508,10 +1588,11 @@ int token::operator==(const token &t) return 0; switch(type) { case TOKEN_CHAR: - case TOKEN_NUMBERED_CHAR: return c == t.c; case TOKEN_SPECIAL: return nm == t.nm; + case TOKEN_NUMBERED_CHAR: + return val == t.val; default: return 1; } @@ -1582,17 +1663,10 @@ const char *token::description() buf[2] = '\''; buf[3] = '\0'; return buf; - case TOKEN_CHAR_HEIGHT: - return "`\\H'"; - case TOKEN_CHAR_SLANT: - return "`\\S'"; case TOKEN_DUMMY: return "`\\&'"; case TOKEN_ESCAPE: return "`\\e'"; - case TOKEN_FONT_NAME: - case TOKEN_FONT_POSITION: - return "`\\f'"; case TOKEN_HYPHEN_INDICATOR: return "`\\%'"; case TOKEN_INTERRUPT: @@ -1613,8 +1687,6 @@ const char *token::description() return "`\\N'"; case TOKEN_RIGHT_BRACE: return "`\\}'"; - case TOKEN_SIZE: - return "`\\s'"; case TOKEN_SPACE: return "a space"; case TOKEN_SPECIAL: @@ -1646,14 +1718,13 @@ void skip_line() void compatible() { int n; - if (!has_arg()) - compatible_flag = 1; - else if (get_integer(&n)) + if (has_arg() && get_integer(&n)) compatible_flag = n != 0; + else + compatible_flag = 1; skip_line(); } - static void empty_name_warning(int required) { if (tok.newline() || tok.eof()) { @@ -1729,7 +1800,7 @@ symbol get_long_name(int required) buf = new char[buf_size*2]; memcpy(buf, old_buf, buf_size); buf_size *= 2; - delete old_buf; + a_delete old_buf; } } if ((buf[i] = tok.ch()) == 0) @@ -1746,43 +1817,52 @@ symbol get_long_name(int required) return symbol(buf); else { symbol s(buf); - delete buf; + a_delete buf; return s; } } -extern int exit_flag; - -NO_RETURN void exit_groff() +NO_RETURN void exit_troff() { - exit_flag = 1; + exit_started = 1; + topdiv->set_last_page(); if (!end_macro_name.is_null()) { spring_trap(end_macro_name); tok.next(); process_input_stack(); } - curenv->do_break(); + curenv->final_break(); tok.next(); process_input_stack(); end_diversions(); - exit_flag = 2; + done_end_macro = 1; + topdiv->set_ejecting(); + static unsigned char buf[2] = { LAST_PAGE_EJECTOR, '\0' }; + input_stack::push(make_temp_iterator((char *)buf)); + topdiv->space(topdiv->get_page_length(), 1); + tok.next(); + process_input_stack(); + seen_last_page_ejector = 1; // should be set already topdiv->set_ejecting(); push_page_ejector(); topdiv->space(topdiv->get_page_length(), 1); tok.next(); process_input_stack(); - // This will only be if a trap-invoked macro starts a diversion, + // This will only happen if a trap-invoked macro starts a diversion, // or if vertical position traps have been disabled. cleanup_and_exit(0); } // This implements .ex. The input stack must be cleared before calling -// exit_groff(). +// exit_troff(). -NO_RETURN void exit_request() +void exit_request() { input_stack::clear(); - exit_groff(); + if (exit_started) + tok.next(); + else + exit_troff(); } void end_macro() @@ -1791,9 +1871,21 @@ void end_macro() skip_line(); } +void do_request() +{ + int saved_compatible_flag = compatible_flag; + compatible_flag = 0; + symbol nm = get_name(); + if (nm.is_null()) + skip_line(); + else + interpolate_macro(nm); + compatible_flag = saved_compatible_flag; +} + inline int possibly_handle_first_page_transition() { - if (!topdiv->first_page_begun && curdiv == topdiv && !curenv->is_dummy()) { + if (topdiv->before_first_page && curdiv == topdiv && !curenv->is_dummy()) { handle_first_page_transition(); return 1; } @@ -1805,19 +1897,25 @@ static int transparent_translate(int cc) { if (!illegal_input_char(cc)) { charinfo *ci = charset_table[cc]; - if (ci->get_special_translation() == charinfo::TRANSLATE_SPACE) + switch (ci->get_special_translation(1)) { + case charinfo::TRANSLATE_SPACE: return ' '; - if (ci->get_special_translation() == charinfo::TRANSLATE_DUMMY) + case charinfo::TRANSLATE_DUMMY: return ESCAPE_AMPERSAND; -#if 0 - // This is just too ugly. - ci = ci->get_translation(); + case charinfo::TRANSLATE_HYPHEN_INDICATOR: + return ESCAPE_PERCENT; + } + // This is realy ugly. + ci = ci->get_translation(1); if (ci) { int c = ci->get_ascii_code(); if (c != '\0') return c; + error("can't translate %1 to special character `%2'" + " in transparent throughput", + input_char_description(cc), + ci->nm.contents()); } -#endif } return cc; } @@ -2001,7 +2099,6 @@ static void process_input_stack() if (possibly_handle_first_page_transition()) ; else if (bol && !curenv->get_prev_line_interrupted()) { - curenv->do_break(); int nspaces = 0; do { nspaces += tok.nspaces(); @@ -2010,8 +2107,9 @@ static void process_input_stack() if (tok.newline()) blank_line(); else { + push_token(tok); + curenv->do_break(); curenv->add_node(new hmotion_node(curenv->get_space_width()*nspaces)); - suppress_next = 1; bol = 0; } } @@ -2405,6 +2503,8 @@ string_iterator::string_iterator() ptr = eptr = 0; newline_flag = 0; how_invoked = 0; + lineno = 1; + count = 0; } int string_iterator::fill(node **np) @@ -2508,25 +2608,22 @@ temp_iterator::temp_iterator(const char *s, int len) temp_iterator::~temp_iterator() { - delete base; + a_delete base; } class small_temp_iterator : public input_iterator { private: small_temp_iterator(const char *, int); -#if 1 ~small_temp_iterator(); enum { BLOCK = 16 }; static small_temp_iterator *free_list; void *operator new(size_t); void operator delete(void *); -#endif enum { SIZE = 12 }; unsigned char buf[SIZE]; friend input_iterator *make_temp_iterator(const char *); }; -#if 1 small_temp_iterator *small_temp_iterator::free_list = 0; void *small_temp_iterator::operator new(size_t n) @@ -2559,7 +2656,6 @@ small_temp_iterator::~small_temp_iterator() { } -#endif #ifdef __GNUG__ inline @@ -2591,12 +2687,17 @@ struct arg_list { macro mac; arg_list *next; arg_list(const macro &); + ~arg_list(); }; arg_list::arg_list(const macro &m) : mac(m), next(0) { } +arg_list::~arg_list() +{ +} + class macro_iterator : public string_iterator { arg_list *args; int argc; @@ -2689,13 +2790,18 @@ static void interpolate_macro(symbol nm) int warned = 0; const char *s = nm.contents(); if (strlen(s) > 2) { + request_or_macro *r; char buf[3]; buf[0] = s[0]; buf[1] = s[1]; buf[2] = '\0'; - if (request_dictionary.lookup(symbol(buf)) != 0) - warned = warning(WARN_SPACE, - "space required between `%1' and argument", buf); + r = (request_or_macro *)request_dictionary.lookup(symbol(buf)); + if (r) { + macro *m = r->to_macro(); + if (!m || !m->empty()) + warned = warning(WARN_SPACE, + "space required between `%1' and argument", buf); + } } if (!warned) { warning(WARN_MAC, "`%1' not defined", nm.contents()); @@ -2765,6 +2871,11 @@ macro *macro::to_macro() return this; } +int macro::empty() +{ + return length == 0; +} + macro_iterator::macro_iterator(symbol s, macro &m) : string_iterator(m, "macro", s), args(0), argc(0) { @@ -2841,6 +2952,8 @@ void do_define_string(int append) } if (tok.newline()) c = '\n'; + else if (tok.tab()) + c = '\t'; else if (!tok.space()) { error("bad string definition"); skip_line(); @@ -2895,6 +3008,8 @@ void define_character() tok.next(); if (tok.newline()) c = '\n'; + else if (tok.tab()) + c = '\t'; else if (!tok.space()) { error("bad character definition"); skip_line(); @@ -2921,6 +3036,23 @@ void define_character() } +static void remove_character() +{ + tok.skip(); + while (!tok.newline() && !tok.eof()) { + if (!tok.space() && !tok.tab()) { + charinfo *ci = tok.get_char(1); + if (!ci) + break; + macro *m = ci->set_macro(0); + if (m) + delete m; + } + tok.next(); + } + skip_line(); +} + static void interpolate_string(symbol nm) { request_or_macro *p = lookup_request(nm); @@ -2984,17 +3116,22 @@ static void interpolate_arg(symbol nm) } } -/* We need to unget the current token; we fake this by wrapping it up -in a token_node, and wrapping that up in a string_iterator. */ - void handle_first_page_transition() { - macro mac; - mac.append(new token_node(tok)); - input_stack::push(new string_iterator(mac)); + push_token(tok); topdiv->begin_page(); } +// We push back a token by wrapping it up in a token_node, and +// wrapping that up in a string_iterator. + +static void push_token(const token &t) +{ + macro m; + m.append(new token_node(t)); + input_stack::push(new string_iterator(m)); +} + void push_page_ejector() { static char buf[2] = { PAGE_EJECTOR, '\0' }; @@ -3080,6 +3217,10 @@ void do_define_macro(define_mode mode) term = dot_symbol; while (!tok.newline() && !tok.eof()) tok.next(); + const char *start_filename; + int start_lineno; + int have_start_location = input_stack::get_location(0, &start_filename, + &start_lineno); node *n; // doing this here makes the line numbers come out right int c = get_copy(&n, 1); @@ -3100,18 +3241,13 @@ void do_define_macro(define_mode mode) mac.append(c); c = get_copy(&n, 1); } - if (c == EOF) { - error("end of file while defining macro"); - tok.next(); - return; - } if (bol && c == '.') { - const unsigned char *s = (const unsigned char *)term.contents(); - unsigned char d; + const char *s = term.contents(); + int d; // see if it matches term for (int i = 0; s[i] != 0; i++) { d = get_copy(&n); - if (s[i] != d) + if ((unsigned char)s[i] != d) break; } if (s[i] == 0 @@ -3142,6 +3278,25 @@ void do_define_macro(define_mode mode) } c = d; } + if (c == EOF) { + if (mode == DEFINE_NORMAL || mode == DEFINE_APPEND) { + if (have_start_location) + error_with_file_and_line(start_filename, start_lineno, + "end of file while defining macro `%1'", + nm.contents()); + else + error("end of file while defining macro `%1'", nm.contents()); + } + else { + if (have_start_location) + error_with_file_and_line(start_filename, start_lineno, + "end of file while ignoring input lines"); + else + error("end of file while ignoring input lines"); + } + tok.next(); + return; + } if (mode == DEFINE_NORMAL || mode == DEFINE_APPEND) { if (c == 0) mac.append(n); @@ -3246,6 +3401,13 @@ void asciify_macro() skip_line(); } +static void interpolate_environment_variable(symbol nm) +{ + const char *s = getenv(nm.contents()); + if (s && *s) + input_stack::push(make_temp_iterator(s)); +} + void interpolate_number_reg(symbol nm, int inc) { reg *r = lookup_number_reg(nm); @@ -3441,7 +3603,7 @@ static symbol get_delim_name() buf = new char[buf_size*2]; memcpy(buf, old_buf, buf_size); buf_size *= 2; - delete old_buf; + a_delete old_buf; } } tok.next(); @@ -3451,7 +3613,7 @@ static symbol get_delim_name() if ((buf[i] = tok.ch()) == 0) { error("missing delimiter (got %1)", tok.description()); if (buf != abuf) - delete buf; + a_delete buf; return NULL_SYMBOL; } i++; @@ -3467,11 +3629,41 @@ static symbol get_delim_name() } else { symbol s(buf); - delete buf; + a_delete buf; return s; } } + +// Implement \R + +static void do_register() +{ + token start; + start.next(); + if (!start.delimiter(1)) + return; + tok.next(); + symbol nm = get_long_name(1); + if (nm.is_null()) + return; + while (tok.space()) + tok.next(); + reg *r = (reg *)number_reg_dictionary.lookup(nm); + int prev_value; + if (!r || !r->get_value(&prev_value)) + prev_value = 0; + int val; + if (!get_number(&val, 'u', prev_value)) + return; + if (start != tok) + warning(WARN_DELIM, "closing delimiter does not match"); + if (r) + r->set_value(val); + else + set_number_reg(nm, val); +} + // this implements the \w escape sequence static void do_width() @@ -3484,10 +3676,15 @@ static void do_width() curenv = &env; for (;;) { tok.next(); - if (tok.newline() || tok.eof()) { + if (tok.eof()) { warning(WARN_DELIM, "missing closing delimiter"); break; } + if (tok.newline()) { + warning(WARN_DELIM, "missing closing delimiter"); + input_stack::push(make_temp_iterator("\n")); + break; + } if (tok == start && (compatible_flag || input_stack::get_level() == start_level)) break; @@ -3964,6 +4161,7 @@ void source() else { while (!tok.newline() && !tok.eof()) tok.next(); + errno = 0; FILE *fp = fopen(nm.contents(), "r"); if (fp) input_stack::push(new file_iterator(fp, nm.contents())); @@ -4080,11 +4278,13 @@ const char *input_char_description(int c) void terminal() { - int c; - while ((c = get_copy(NULL)) == ' ' || c == '\t') - ; - for (; c != '\n' && c != EOF; c = get_copy(NULL)) - fputs(asciify(c), stderr); + if (!tok.newline() && !tok.eof()) { + int c; + while ((c = get_copy(NULL)) == ' ' || c == '\t') + ; + for (; c != '\n' && c != EOF; c = get_copy(NULL)) + fputs(asciify(c), stderr); + } fputc('\n', stderr); fflush(stderr); tok.next(); @@ -4098,6 +4298,7 @@ void do_open(int append) if (!stream.is_null()) { symbol filename = get_long_name(1); if (!filename.is_null()) { + errno = 0; FILE *fp = fopen(filename.contents(), append ? "a" : "w"); if (!fp) { error("can't open `%1' for %2: %3", @@ -4159,6 +4360,7 @@ void write_request() for (; c != '\n' && c != EOF; c = get_copy(NULL)) fputs(asciify(c), fp); fputc('\n', fp); + fflush(fp); tok.next(); } @@ -4183,7 +4385,7 @@ static void init_charset_table() charset_table[']']->set_flags(charinfo::TRANSPARENT); charset_table['*']->set_flags(charinfo::TRANSPARENT); get_charinfo(symbol("dg"))->set_flags(charinfo::TRANSPARENT); - get_charinfo(symbol("hy"))->set_flags(charinfo::BREAK_AFTER); + get_charinfo(symbol("rq"))->set_flags(charinfo::TRANSPARENT); get_charinfo(symbol("em"))->set_flags(charinfo::BREAK_AFTER); get_charinfo(symbol("ul"))->set_flags(charinfo::OVERLAPS_HORIZONTALLY); get_charinfo(symbol("rn"))->set_flags(charinfo::OVERLAPS_HORIZONTALLY); @@ -4192,34 +4394,61 @@ static void init_charset_table() page_character = charset_table['%']; } -void translate() +static +void do_translate(int translate_transparent) { tok.skip(); while (!tok.newline() && !tok.eof()) { + if (tok.space()) { + // This is a really bizarre troff feature. + tok.next(); + translate_space_to_dummy = tok.dummy(); + if (tok.newline() || tok.eof()) + break; + tok.next(); + continue; + } charinfo *ci1 = tok.get_char(1); if (ci1 == 0) break; tok.next(); - if (tok.newline() || tok.space()) { - ci1->set_special_translation(charinfo::TRANSLATE_SPACE); + if (tok.newline() || tok.eof()) { + ci1->set_special_translation(charinfo::TRANSLATE_SPACE, + translate_transparent); break; } - if (tok.dummy()) - ci1->set_special_translation(charinfo::TRANSLATE_DUMMY); + if (tok.space()) + ci1->set_special_translation(charinfo::TRANSLATE_SPACE, + translate_transparent); + else if (tok.dummy()) + ci1->set_special_translation(charinfo::TRANSLATE_DUMMY, + translate_transparent); + else if (tok.hyphen_indicator()) + ci1->set_special_translation(charinfo::TRANSLATE_HYPHEN_INDICATOR, + translate_transparent); else { charinfo *ci2 = tok.get_char(1); if (ci2 == 0) break; if (ci1 == ci2) - ci1->set_translation(0); + ci1->set_translation(0, translate_transparent); else - ci1->set_translation(ci2); + ci1->set_translation(ci2, translate_transparent); } tok.next(); } skip_line(); } +void translate() +{ + do_translate(1); +} + +void translate_no_transparent() +{ + do_translate(0); +} void char_flags() { @@ -4269,7 +4498,15 @@ charinfo *token::get_char(int required) if (type == TOKEN_SPECIAL) return get_charinfo(nm); if (type == TOKEN_NUMBERED_CHAR) - return get_charinfo_by_number(c); + return get_charinfo_by_number(val); + if (type == TOKEN_ESCAPE) { + if (escape_char != 0) + return charset_table[escape_char]; + else { + error("`\\e' used while no current escape character"); + return 0; + } + } if (required) { if (type == TOKEN_EOF || type == TOKEN_NEWLINE) warning(WARN_MISSING, "missing normal or special character"); @@ -4303,12 +4540,6 @@ int token::add_to_node_list(node **pp) case TOKEN_CHAR: *pp = (*pp)->add_char(charset_table[c], curenv, &w); break; - case TOKEN_CHAR_HEIGHT: - curenv->set_char_height(val); - break; - case TOKEN_CHAR_SLANT: - curenv->set_char_slant(val); - break; case TOKEN_DUMMY: n = new dummy_node; break; @@ -4316,12 +4547,6 @@ int token::add_to_node_list(node **pp) if (escape_char != 0) *pp = (*pp)->add_char(charset_table[escape_char], curenv, &w); break; - case TOKEN_FONT_NAME: - curenv->set_font(nm); - break; - case TOKEN_FONT_POSITION: - curenv->set_font(val); - break; case TOKEN_HYPHEN_INDICATOR: *pp = (*pp)->add_discretionary_hyphen(); break; @@ -4338,13 +4563,10 @@ int token::add_to_node_list(node **pp) nd = 0; break; case TOKEN_NUMBERED_CHAR: - *pp = (*pp)->add_char(get_charinfo_by_number(c), curenv, &w); + *pp = (*pp)->add_char(get_charinfo_by_number(val), curenv, &w); break; case TOKEN_RIGHT_BRACE: break; - case TOKEN_SIZE: - curenv->set_size(val); - break; case TOKEN_SPACE: n = new hmotion_node(curenv->get_space_width()); break; @@ -4372,12 +4594,6 @@ void token::process() case TOKEN_CHAR: curenv->add_char(charset_table[c]); break; - case TOKEN_CHAR_HEIGHT: - curenv->set_char_height(val); - break; - case TOKEN_CHAR_SLANT: - curenv->set_char_slant(val); - break; case TOKEN_DUMMY: curenv->add_node(new dummy_node); break; @@ -4391,12 +4607,6 @@ void token::process() if (escape_char != 0) curenv->add_char(charset_table[escape_char]); break; - case TOKEN_FONT_NAME: - curenv->set_font(nm); - break; - case TOKEN_FONT_POSITION: - curenv->set_font(val); - break; case TOKEN_BEGIN_TRAP: case TOKEN_END_TRAP: case TOKEN_PAGE_EJECTOR: @@ -4427,16 +4637,13 @@ void token::process() nd = 0; break; case TOKEN_NUMBERED_CHAR: - curenv->add_char(get_charinfo_by_number(c)); + curenv->add_char(get_charinfo_by_number(val)); break; case TOKEN_REQUEST: // handled in process_input_stack break; case TOKEN_RIGHT_BRACE: break; - case TOKEN_SIZE: - curenv->set_size(val); - break; case TOKEN_SPACE: curenv->space(); break; @@ -4578,7 +4785,7 @@ char *read_string() s = new char[len*2]; memcpy(s, tem, len); len *= 2; - delete tem; + a_delete tem; } s[i++] = c; } @@ -4587,7 +4794,7 @@ char *read_string() s[i] = '\0'; tok.next(); if (i == 0) { - delete s; + a_delete s; return 0; } return s; @@ -4614,13 +4821,13 @@ void system_request() error("empty command"); else { system_status = system(command); - delete command; + a_delete command; } } void copy_file() { - if (curdiv == topdiv && !topdiv->first_page_begun) { + if (curdiv == topdiv && topdiv->before_first_page) { handle_initial_request(COPY_FILE_REQUEST); return; } @@ -4638,7 +4845,7 @@ void copy_file() void vjustify() { - if (curdiv == topdiv && !topdiv->first_page_begun) { + if (curdiv == topdiv && topdiv->before_first_page) { handle_initial_request(VJUSTIFY_REQUEST); return; } @@ -4652,7 +4859,7 @@ void vjustify() void transparent_file() { - if (curdiv == topdiv && !topdiv->first_page_begun) { + if (curdiv == topdiv && topdiv->before_first_page) { handle_initial_request(TRANSPARENT_FILE_REQUEST); return; } @@ -4662,6 +4869,7 @@ void transparent_file() if (break_flag) curenv->do_break(); if (!filename.is_null()) { + errno = 0; FILE *fp = fopen(filename.contents(), "r"); if (!fp) error("can't open `%1': %2", filename.contents(), strerror(errno)); @@ -4754,75 +4962,13 @@ static void parse_output_page_list(char *p) } } -struct string_list { - const char *s; - string_list *next; - string_list(const char *ss) : s(ss), next(0) {} -}; - -string_list *mac_dirs; -string_list *font_dirs; - -// open filename, searching in dirs and put the result in pathp - -static FILE *open_file(const char *filename, string_list *dirs, char **pathp) -{ - int fnlen = strlen(filename); - while (dirs) { - int dlen = 0; - int need_slash = 0; - if (dirs->s) { - dlen = strlen(dirs->s); - if (dlen && dirs->s[dlen-1] != '/') - need_slash = 1; - } - char *path = new char[dlen + need_slash + fnlen + 1]; - if (dirs->s) - strcpy(path, dirs->s); - else - path[0] = 0; - if (need_slash) - strcat(path, "/"); - strcat(path, filename); - FILE *fp = fopen(path, "r"); - if (fp) { - *pathp = path; - return fp; - } - delete path; - dirs = dirs->next; - } - return 0; -} - -static void add_string(const char *s, string_list **p) -{ - while (*p) - p = &((*p)->next); - *p = new string_list(s); -} - -static void init_dirs(const char *e, const char *standard, string_list **dirs) -{ - char *var = getenv(e); - if (!var) { - var = new char[strlen(standard)+1]; - strcpy(var, standard); - } - for (char *p = strtok(var, ":"); p; p = strtok(NULL, ":")) - add_string(p, dirs); -} - - -#define MACRO_PREFIX "tmac." - -FILE *open_mac_file(const char *mac, char **path) +static FILE *open_mac_file(const char *mac, char **path) { char *s = new char[strlen(mac)+strlen(MACRO_PREFIX)+1]; strcpy(s, MACRO_PREFIX); strcat(s, mac); - FILE *fp = open_file(s, mac_dirs, path); - delete s; + FILE *fp = macro_path.open_file(s, path); + a_delete s; return fp; } @@ -4833,12 +4979,44 @@ static void process_macro_file(const char *mac) if (!fp) fatal("can't find macro file %1", mac); const char *s = symbol(path).contents(); - delete path; + a_delete path; input_stack::push(new file_iterator(fp, s)); tok.next(); process_input_stack(); } +static void process_startup_file() +{ + char *path; + FILE *fp = macro_path.open_file(STARTUP_FILE, &path); + if (fp) { + input_stack::push(new file_iterator(fp, symbol(path).contents())); + a_delete path; + tok.next(); + process_input_stack(); + } +} + +void macro_source() +{ + symbol nm = get_long_name(1); + if (nm.is_null()) + skip_line(); + else { + while (!tok.newline() && !tok.eof()) + tok.next(); + char *path; + FILE *fp = macro_path.open_file(nm.contents(), &path); + if (fp) { + input_stack::push(new file_iterator(fp, symbol(path).contents())); + a_delete path; + } + else + error("can't find macro file `%1'", nm.contents()); + tok.next(); + } +} + static void process_input_file(const char *name) { FILE *fp; @@ -4847,6 +5025,7 @@ static void process_input_file(const char *name) fp = stdin; } else { + errno = 0; fp = fopen(name, "r"); if (!fp) fatal("can't open `%1': %2", name, strerror(errno)); @@ -4886,15 +5065,15 @@ static void do_register_assignment(const char *s) units n; if (evaluate_expression(p + 1, &n)) set_number_reg(buf, n); - delete buf; + a_delete buf; } } static void set_string(const char *name, const char *value) { macro *m = new macro; - for (const unsigned char *p = (const unsigned char *)value; *p; p++) - if (!illegal_input_char(*p)) + for (const char *p = value; *p; p++) + if (!illegal_input_char((unsigned char)*p)) m->append(*p); request_dictionary.define(name, m); } @@ -4914,28 +5093,33 @@ static void do_string_assignment(const char *s) memcpy(buf, s, p - s); buf[p - s] = 0; set_string(buf, p + 1); - delete buf; + a_delete buf; } } -#define USAGE_EXIT_CODE 1 +struct string_list { + const char *s; + string_list *next; + string_list(const char *ss) : s(ss), next(0) {} +}; + +static void add_string(const char *s, string_list **p) +{ + while (*p) + p = &((*p)->next); + *p = new string_list(s); +} void usage(const char *prog) { errprint( -"usage: %1 -abivzCE -wname -Wname -dcstring -mname -nN -olist -rcN\n" -" -Tname -Fdir -Mdir -Hfile [ files ]\n", +"usage: %1 -abivzCER -wname -Wname -dcstring -mname -nN -olist -rcN\n" +" -Tname -Fdir -Mdir [ files ]\n", prog); exit(USAGE_EXIT_CODE); } -int -#ifdef DUMP -normal_main -#else -main -#endif - (int argc, char **argv) +int main(int argc, char **argv) { program_name = argv[0]; static char stderr_buf[BUFSIZ]; @@ -4944,21 +5128,16 @@ main string_list *macros = 0; string_list *register_assignments = 0; string_list *string_assignments = 0; - const char *hyphen_file = HYPHENFILE; int iflag = 0; int tflag = 0; int fflag = 0; int nflag = 0; + int no_rc = 0; // don't process troffrc int next_page_number; opterr = 0; hresolution = vresolution = 1; - const char *tem = getenv("GROFF_TYPESETTER"); - if (tem) - device = tem; - tem = getenv("GROFF_HYPHEN"); - if (tem) - hyphen_file = tem; - while ((c = getopt(argc, argv, "abivw:W:zCEf:m:n:o:r:d:F:H:M:T:tqs:")) != EOF) + while ((c = getopt(argc, argv, "abivw:W:zCEf:m:n:o:r:d:F:M:T:tqs:R")) + != EOF) switch(c) { case 'v': { @@ -4975,20 +5154,20 @@ main compatible_flag = 1; break; case 'M': - add_string(optarg, &mac_dirs); + macro_path.command_line_dir(optarg); break; case 'F': font::command_line_font_dir(optarg); break; - case 'H': - hyphen_file = optarg; - break; case 'm': add_string(optarg, ¯os); break; case 'E': inhibit_errors = 1; break; + case 'R': + no_rc = 1; + break; case 'w': enable_warning(optarg); break; @@ -5043,9 +5222,7 @@ main assert(0); } set_string(".T", device); - init_dirs(MACROPATH_ENVVAR, MACROPATH, &mac_dirs); init_charset_table(); - font::set_device_name(device); if (!font::load_desc()) fatal("sorry, I can't continue"); units_per_inch = font::res; @@ -5062,8 +5239,11 @@ main for (i = 0; font::style_table[i]; i++) mount_style(j++, symbol(font::style_table[i])); } - for (i = 0; font::font_name_table[i]; i++) - mount_font(j++, symbol(font::font_name_table[i])); + for (i = 0; font::font_name_table[i]; i++, j++) + // In the DESC file a font name of 0 (zero) means leave this + // position empty. + if (strcmp(font::font_name_table[i], "0") != 0) + mount_font(j, symbol(font::font_name_table[i])); curdiv = topdiv = new top_level_diversion; if (nflag) topdiv->set_next_page_number(next_page_number); @@ -5077,7 +5257,6 @@ main number_reg_dictionary.define(".T", new constant_reg(tflag ? "1" : "0")); init_registers(); init_reg_requests(); - read_hyphen_file(hyphen_file); init_hyphen_requests(); init_environments(); while (string_assignments) { @@ -5092,6 +5271,8 @@ main register_assignments = register_assignments->next; delete tem; } + if (!no_rc) + process_startup_file(); while (macros) { process_macro_file(macros->s); string_list *tem = macros; @@ -5102,229 +5283,43 @@ main process_input_file(argv[i]); if (optind >= argc || iflag) process_input_file("-"); - exit_groff(); + exit_troff(); } -#ifdef DUMP - -int dumped_main(int argc, char **argv) -{ - program_name = argv[0]; - int c; - string_list *macros = 0; - string_list *register_assignments = 0; - string_list *string_assignments = 0; - int iflag = 0; - int nflag = 0; - int next_page_number; - opterr = 0; - while ((c = getopt(argc, argv, "abivw:W:zECf:m:n:o:r:d:F:H:M:T:tqs:")) != EOF) - switch(c) { - case 'v': - { - extern const char *version_string; - fprintf(stderr, "GNU troff version %s\n", version_string); - fflush(stderr); - break; - } - case 'f': - case 'H': - case 'T': - error("`-%1' option illegal when dumped", char(c)); - break; - case 'C': - compatible_flag = 1; - break; - case 'M': - add_string(optarg, &mac_dirs); - break; - case 'F': - font::command_line_font_dir(optarg); - break; - case 'm': - add_string(optarg, ¯os); - break; - case 'E': - inhibit_errors = 1; - break; - case 'w': - enable_warning(optarg); - break; - case 'W': - disable_warning(optarg); - break; - case 'i': - iflag = 1; - break; - case 'b': - backtrace_flag = 1; - break; - case 'a': - ascii_output_flag = 1; - break; - case 'z': - suppress_output_flag = 1; - break; - case 'n': - if (sscanf(optarg, "%d", &next_page_number) == 1) - nflag++; - else - error("bad page number"); - break; - case 'o': - parse_output_page_list(optarg); - break; - case 'd': - if (*optarg == '\0') - error("`-d' requires non-empty argument"); - else - add_string(optarg, &string_assignments); - break; - case 'r': - if (*optarg == '\0') - error("`-r' requires non-empty argument"); - else - add_string(optarg, ®ister_assignments); - break; - case 'q': - case 's': - case 't': - // silently ignore these - break; - case '?': - usage(argv[0]); - default: - assert(0); - } - init_dirs(MACROPATH_ENVVAR, MACROPATH, &mac_dirs); - init_registers(); - if (nflag) - topdiv->set_next_page_number(next_page_number); - while (string_assignments) { - do_string_assignment(string_assignments->s); - string_list *tem = string_assignments; - string_assignments = string_assignments->next; - delete tem; - } - while (register_assignments) { - do_register_assignment(register_assignments->s); - string_list *tem = register_assignments; - register_assignments = register_assignments->next; - delete tem; - } - while (macros) { - process_macro_file(macros->s); - string_list *tem = macros; - macros = macros->next; - delete tem; - } - int i; - for (i = optind; i < argc; i++) - process_input_file(argv[i]); - if (optind >= argc || iflag) - process_input_file("-"); - exit_groff(); -} - -static int dumped = 0; - -extern "C" { - -int unexec(const char *new_name, const char *a_name, unsigned data_start = 0, - unsigned bss_start = 0, unsigned entry_address = 0); - -#ifdef __GNUG__ -#define CPLUS_INIT_FUNC __main -#else -#define CPLUS_INIT_FUNC _main -#endif - -extern int CPLUS_INIT_FUNC(); - -int c_main(int argc, char **argv) -{ - if (dumped) - return dumped_main(argc, argv); - else { - CPLUS_INIT_FUNC(); - return normal_main(argc, argv); - } -} - -#define OPTIND_INITIAL_VALUE 1 - -} - -void dump_request() -{ - symbol new_name = get_long_name(1); - if (new_name.is_null()) { - skip_line(); - return; - } - symbol a_name = get_long_name(1); - if (a_name.is_null()) { - skip_line(); - return; - } - if (topdiv->first_page_begun) - fatal("can't dump after first page begun"); - while (input_stack::get(NULL) != EOF) - ; - suppress_output_flag = 0; - ascii_output_flag = 0; - dumped = 1; - optind = OPTIND_INITIAL_VALUE; - number_reg_dictionary.remove(".A"); - while (output_page_list) { - page_range *tem = output_page_list; - output_page_list = output_page_list->next; - delete tem; - } - while (mac_dirs) { - string_list *tem = mac_dirs; - mac_dirs = mac_dirs->next; - delete tem; - } - font::forget_command_line_font_dirs(); - fflush(stderr); - clearerr(stdin); - // clean up the diversion_stack - // clean up environment stack - if (unexec(new_name.contents(), a_name.contents()) < 0) - exit(1); - else - exit(0); -} - -#endif /* DUMP */ - void warn_request() { int n; - if (!has_arg()) - warning_mask = WARN_TOTAL; - else if (get_integer(&n)) { + if (has_arg() && get_integer(&n)) { if (n & ~WARN_TOTAL) { warning(WARN_RANGE, "warning mask must be between 0 and %1", WARN_TOTAL); n &= WARN_TOTAL; } warning_mask = n; } + else + warning_mask = WARN_TOTAL; skip_line(); } static void init_registers() { - long t; - time(&t); - tm *tt = localtime(&t); +#ifdef LONG_FOR_TIME_T + long +#else /* not LONG_FOR_TIME_T */ + time_t +#endif /* not LONG_FOR_TIME_T */ + t = time(0); + // Use struct here to work around misfeature in old versions of g++. + struct tm *tt = localtime(&t); set_number_reg("dw", int(tt->tm_wday + 1)); set_number_reg("dy", int(tt->tm_mday)); set_number_reg("mo", int(tt->tm_mon + 1)); set_number_reg("yr", int(tt->tm_year)); set_number_reg("$$", getpid()); - number_reg_dictionary.define(".A", new constant_reg(ascii_output_flag ? "1" : "0")); + number_reg_dictionary.define(".A", + new constant_reg(ascii_output_flag + ? "1" + : "0")); } void init_input_requests() @@ -5346,9 +5341,10 @@ void init_input_requests() init_request("ec", set_escape_char); init_request("pc", set_page_character); init_request("tm", terminal); - init_request("ex", REQUEST_FUNCP(exit_request)); + init_request("ex", exit_request); init_request("em", end_macro); init_request("tr", translate); + init_request("trnt", translate_no_transparent); init_request("ab", abort_request); init_request("pi", pipe_output); init_request("cf", copy_file); @@ -5359,6 +5355,7 @@ void init_input_requests() init_request("rd", read_request); init_request("cp", compatible); init_request("char", define_character); + init_request("rchar", remove_character); init_request("hcode", hyphenation_code); init_request("while", while_request); init_request("break", while_break_request); @@ -5368,9 +5365,6 @@ void init_input_requests() init_request("chop", chop_macro); init_request("asciify", asciify_macro); init_request("warn", warn_request); -#ifdef DUMP - init_request("dump", dump_request); -#endif init_request("open", open_request); init_request("opena", opena_request); init_request("close", close_request); @@ -5384,6 +5378,8 @@ void init_input_requests() #ifdef COLUMN init_request("vj", vjustify); #endif /* COLUMN */ + init_request("mso", macro_source); + init_request("do", do_request); number_reg_dictionary.define("systat", new variable_reg(&system_status)); number_reg_dictionary.define("slimit", new variable_reg(&input_stack::limit)); @@ -5423,19 +5419,24 @@ static request_or_macro *lookup_request(symbol nm) } -node *charinfo_to_node(charinfo *ci, const environment *envp) +node *charinfo_to_node_list(charinfo *ci, const environment *envp) { + // Don't interpret character definitions in compatible mode. + int old_compatible_flag = compatible_flag; + compatible_flag = 0; + int old_escape_char = escape_char; + escape_char = '\\'; macro *mac = ci->set_macro(0); assert(mac != 0); environment *oldenv = curenv; environment env(envp); curenv = &env; - font_size sz = env.get_font_size(); + curenv->set_composite(); token old_tok = tok; input_stack::add_boundary(); string_iterator *si = new string_iterator(*mac, "composite character", ci->nm); input_stack::push(si); - // we don't use process_input_stack, because we don't to recognise + // we don't use process_input_stack, because we don't want to recognise // requests for (;;) { tok.next(); @@ -5451,12 +5452,13 @@ node *charinfo_to_node(charinfo *ci, const environment *envp) tok.process(); } node *n = curenv->extract_output_line(); - composite_node *cn = new composite_node(n, ci, sz); input_stack::remove_boundary(); ci->set_macro(mac); tok = old_tok; curenv = oldenv; - return cn; + compatible_flag = old_compatible_flag; + escape_char = old_escape_char; + return n; } static node *read_draw_node() @@ -5488,7 +5490,7 @@ static node *read_draw_node() for (int j = 0; j < maxpoints; j++) point[j] = oldpoint[j]; maxpoints *= 2; - delete oldpoint; + a_delete oldpoint; } if (!get_hunits(&point[i].h, 'm')) { err = 1; @@ -5546,11 +5548,11 @@ static node *read_draw_node() } draw_node *dn = new draw_node(type, point, npoints, curenv->get_font_size()); - delete point; + a_delete point; return dn; } else { - delete point; + a_delete point; } } } @@ -5575,6 +5577,7 @@ static struct { "input", WARN_INPUT, "escape", WARN_ESCAPE, "space", WARN_SPACE, + "font", WARN_FONT, "di", WARN_DI, "mac", WARN_MAC, "reg", WARN_REG, @@ -5719,7 +5722,8 @@ int charinfo::next_index = 0; charinfo::charinfo(symbol s) : nm(s), hyphenation_code(0), translation(0), flags(0), ascii_code(0), - special_translation(TRANSLATE_NONE), mac(0), not_found(0) + special_translation(TRANSLATE_NONE), mac(0), not_found(0), + transparent_translate(1) { index = next_index++; } @@ -5729,16 +5733,18 @@ void charinfo::set_hyphenation_code(unsigned char c) hyphenation_code = c; } -void charinfo::set_translation(charinfo *ci) +void charinfo::set_translation(charinfo *ci, int tt) { translation = ci; special_translation = TRANSLATE_NONE; + transparent_translate = tt; } -void charinfo::set_special_translation(int c) +void charinfo::set_special_translation(int c, int tt) { special_translation = c; translation = 0; + transparent_translate = tt; } void charinfo::set_ascii_code(unsigned char c) @@ -5753,30 +5759,48 @@ macro *charinfo::set_macro(macro *m) return tem; } -void charinfo::set_number(unsigned char c) +void charinfo::set_number(int n) { - number = c; + number = n; flags |= NUMBERED; } int charinfo::get_number() { - return (flags & NUMBERED) ? int(number) : -1; + assert(flags & NUMBERED); + return number; } symbol UNNAMED_SYMBOL("---"); -charinfo *get_charinfo_by_number(unsigned char n) +// For numbered characters not between 0 and 255, we make a symbol out +// of the number and store them in this dictionary. + +dictionary numbered_charinfo_dictionary(11); + +charinfo *get_charinfo_by_number(int n) { static charinfo *number_table[256]; - charinfo *ci = number_table[n]; - if (!ci) { - ci = new charinfo(UNNAMED_SYMBOL); - ci->set_number(n); - number_table[n] = ci; + if (n >= 0 && n < 256) { + charinfo *ci = number_table[n]; + if (!ci) { + ci = new charinfo(UNNAMED_SYMBOL); + ci->set_number(n); + number_table[n] = ci; + } + return ci; + } + else { + symbol ns(itoa(n)); + charinfo *ci = (charinfo *)numbered_charinfo_dictionary.lookup(ns); + if (!ci) { + ci = new charinfo(UNNAMED_SYMBOL); + ci->set_number(n); + numbered_charinfo_dictionary.lookup(ns, ci); + } + return ci; } - return ci; } int font::name_to_index(const char *nm) @@ -5794,7 +5818,7 @@ int font::name_to_index(const char *nm) return ci->get_index(); } -int font::number_to_index(unsigned char c) +int font::number_to_index(int n) { - return get_charinfo_by_number(c)->get_index(); + return get_charinfo_by_number(n)->get_index(); } diff --git a/gnu/usr.bin/groff/troff/node.cc b/gnu/usr.bin/groff/troff/node.cc index 83b1457ec29..6d36519d751 100644 --- a/gnu/usr.bin/groff/troff/node.cc +++ b/gnu/usr.bin/groff/troff/node.cc @@ -1,12 +1,12 @@ // -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.uucp) +/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) This file is part of groff. groff is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 1, or (at your option) any later +Software Foundation; either version 2, or (at your option) any later version. groff is distributed in the hope that it will be useful, but WITHOUT ANY @@ -15,10 +15,10 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along -with groff; see the file LICENSE. If not, write to the Free Software +with groff; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "groff.h" +#include "troff.h" #include "symbol.h" #include "dictionary.h" #include "hvunits.h" @@ -30,8 +30,13 @@ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "font.h" #include "reg.h" +#define STORE_WIDTH 1 + symbol HYPHEN_SYMBOL("hy"); +// Character used when a hyphen is inserted at a line break. +static charinfo *soft_hyphen_char; + enum constant_space_type { CONSTANT_SPACE_NONE, CONSTANT_SPACE_RELATIVE, @@ -104,7 +109,7 @@ public: int is_named(symbol); symbol get_name(); tfont *get_tfont(font_size, int, int, int); - hunits get_space_width(font_size); + hunits get_space_width(font_size, int); hunits get_narrow_space_width(font_size); hunits get_half_narrow_space_width(font_size); int get_bold(hunits *); @@ -343,9 +348,16 @@ symbol font_info::get_name() return internal_name; } -hunits font_info::get_space_width(font_size fs) +hunits font_info::get_space_width(font_size fs, int space_size) { - return hunits(fm->get_space_width(fs.to_scaled_points())); + if (is_constant_spaced == CONSTANT_SPACE_NONE) + return scale(hunits(fm->get_space_width(fs.to_scaled_points())), + space_size, 12); + else if (is_constant_spaced == CONSTANT_SPACE_ABSOLUTE) + return constant_space; + else + return scale(constant_space*fs.to_scaled_points(), + units_per_inch, 36*72*sizescale); } hunits font_info::get_narrow_space_width(font_size fs) @@ -680,8 +692,8 @@ class troff_output_file : public real_output_file { char tbuf[TBUF_SIZE]; int tbuf_len; int tbuf_kern; + int begun_page; void do_motion(); - vunits page_length; void put(char c); void put(unsigned char c); void put(int i); @@ -691,6 +703,7 @@ class troff_output_file : public real_output_file { public: troff_output_file(); ~troff_output_file(); + void trailer(vunits page_length); void put_char(charinfo *ci, tfont *tf); void put_char_width(charinfo *ci, tfont *tf, hunits w, hunits k); void right(hunits); @@ -867,10 +880,9 @@ void troff_output_file::put_char_width(charinfo *ci, tfont *tf, hunits w, if (c == '\0') { flush_tbuf(); do_motion(); - int n = ci->get_number(); - if (n >= 0) { + if (ci->numbered()) { put('N'); - put(n); + put(ci->get_number()); } else { put('C'); @@ -927,10 +939,9 @@ void troff_output_file::put_char(charinfo *ci, tfont *tf) char c = ci->get_ascii_code(); if (c == '\0') { do_motion(); - int n = ci->get_number(); - if (n >= 0) { + if (ci->numbered()) { put('N'); - put(n); + put(ci->get_number()); } else { put('C'); @@ -982,7 +993,7 @@ void troff_output_file::set_font(tfont *tf) font_position = new symbol[nfont_positions]; memcpy(font_position, old_font_position, old_nfont_positions*sizeof(symbol)); - delete old_font_position; + a_delete old_font_position; } font_position[n] = nm; } @@ -1054,15 +1065,18 @@ void troff_output_file::draw(char code, hvpair *point, int npoints, put('\n'); } -void troff_output_file::really_begin_page(int pageno, vunits pl) +void troff_output_file::really_begin_page(int pageno, vunits page_length) { flush_tbuf(); - if (page_length > V0) { - put('V'); - put(page_length.to_units()); - put('\n'); + if (begun_page) { + if (page_length > V0) { + put('V'); + put(page_length.to_units()); + put('\n'); + } } - page_length = pl; + else + begun_page = 1; current_tfont = 0; current_font_number = -1; current_size = 0; @@ -1085,6 +1099,7 @@ void troff_output_file::really_copy_file(hunits x, vunits y, const char *filenam moveto(x, y); flush_tbuf(); do_motion(); + errno = 0; FILE *ifp = fopen(filename, "r"); if (ifp == 0) error("can't open `%1': %2", filename, strerror(errno)); @@ -1109,6 +1124,11 @@ void troff_output_file::really_transparent_char(unsigned char c) troff_output_file::~troff_output_file() { + a_delete font_position; +} + +void troff_output_file::trailer(vunits page_length) +{ flush_tbuf(); if (page_length > V0) { put("x trailer\n"); @@ -1117,11 +1137,11 @@ troff_output_file::~troff_output_file() put('\n'); } put("x stop\n"); - delete font_position; } troff_output_file::troff_output_file() -: current_height(0), current_slant(0), tbuf_len(0), nfont_positions(10) +: current_height(0), current_slant(0), tbuf_len(0), nfont_positions(10), + begun_page(0) { font_position = new symbol[nfont_positions]; put("x T "); @@ -1149,6 +1169,10 @@ output_file::~output_file() { } +void output_file::trailer(vunits) +{ +} + real_output_file::real_output_file() : printing(0) { @@ -1272,11 +1296,11 @@ void suppress_output_file::really_print_line(hunits, vunits, node *, vunits, vun { } -void suppress_output_file::really_begin_page(int pageno, vunits page_length) +void suppress_output_file::really_begin_page(int, vunits) { } -void suppress_output_file::really_transparent_char(unsigned char c) +void suppress_output_file::really_transparent_char(unsigned char) { } @@ -1717,14 +1741,13 @@ hunits kern_pair_node::subscript_correction() node *kern_pair_node::add_discretionary_hyphen() { - charinfo *hci = get_charinfo(HYPHEN_SYMBOL); tfont *tf = n2->get_tfont(); if (tf) { - if (tf->contains(hci)) { + if (tf->contains(soft_hyphen_char)) { node *next1 = next; next = 0; node *n = copy(); - glyph_node *gn = new glyph_node(hci, tf); + glyph_node *gn = new glyph_node(soft_hyphen_char, tf); node *nn = n->merge_glyph_node(gn); if (nn == 0) { gn->next = n; @@ -1852,12 +1875,11 @@ node *node::add_discretionary_hyphen() tfont *tf = get_tfont(); if (!tf) return new hyphen_inhibitor_node(this); - charinfo *hci = get_charinfo(HYPHEN_SYMBOL); - if (tf->contains(hci)) { + if (tf->contains(soft_hyphen_char)) { node *next1 = next; next = 0; node *n = copy(); - glyph_node *gn = new glyph_node(hci, tf); + glyph_node *gn = new glyph_node(soft_hyphen_char, tf); node *n1 = n->merge_glyph_node(gn); if (n1 == 0) { gn->next = n; @@ -2702,7 +2724,7 @@ void kern_pair_node::ascii_print(ascii_output_file *ascii) } -void node::ascii_print(ascii_output_file *ascii) +void node::ascii_print(ascii_output_file *) { } @@ -2773,17 +2795,6 @@ void ligature_node::asciify(macro *m) delete this; } -void composite_node::asciify(macro *m) -{ - unsigned char c = ci->get_ascii_code(); - if (c != 0) { - m->append(c); - delete this; - } - else - m->append(this); -} - void break_char_node::asciify(macro *m) { ch->asciify(m); @@ -3043,8 +3054,34 @@ void special_node::tprint_end(troff_output_file *out) /* composite_node */ -composite_node::composite_node(node *p, charinfo *c, font_size s, node *x) - : node(x), n(p), ci(c), sz(s) +class composite_node : public node { + charinfo *ci; + node *n; + tfont *tf; +public: + composite_node(node *, charinfo *, tfont *, node * = 0); + ~composite_node(); + node *copy(); + hunits width(); + node *last_char_node(); + units size(); + void tprint(troff_output_file *); + hyphenation_type get_hyphenation_type(); + int overlaps_horizontally(); + int overlaps_vertically(); + void ascii_print(ascii_output_file *); + void asciify(macro *); + hyphen_list *get_hyphen_list(hyphen_list *tail); + node *add_self(node *, hyphen_list **); + tfont *get_tfont(); + int same(node *); + const char *type(); + void vertical_extent(vunits *, vunits *); + vunits vertical_width(); +}; + +composite_node::composite_node(node *p, charinfo *c, tfont *t, node *x) +: node(x), n(p), ci(c), tf(t) { } @@ -3055,14 +3092,21 @@ composite_node::~composite_node() node *composite_node::copy() { - return new composite_node(copy_node_list(n), ci, sz); + return new composite_node(copy_node_list(n), ci, tf); } hunits composite_node::width() { - hunits x = H0; + hunits x; + if (tf->get_constant_space(&x)) + return x; + x = H0; for (node *tem = n; tem; tem = tem->next) x += tem->width(); + hunits offset; + if (tf->get_bold(&offset)) + x += offset; + x += tf->get_track_kern(); return x; } @@ -3081,7 +3125,7 @@ vunits composite_node::vertical_width() units composite_node::size() { - return sz.to_units(); + return tf->get_size().to_units(); } hyphenation_type composite_node::get_hyphenation_type() @@ -3099,6 +3143,17 @@ int composite_node::overlaps_vertically() return ci->overlaps_vertically(); } +void composite_node::asciify(macro *m) +{ + unsigned char c = ci->get_ascii_code(); + if (c != 0) { + m->append(c); + delete this; + } + else + m->append(this); +} + void composite_node::ascii_print(ascii_output_file *ascii) { unsigned char c = ci->get_ascii_code(); @@ -3130,10 +3185,7 @@ node *composite_node::add_self(node *nn, hyphen_list **p) tfont *composite_node::get_tfont() { - if (n) - return n->get_tfont(); - else - return 0; + return tf; } node *reverse_node_list(node *n) @@ -3175,6 +3227,41 @@ void word_space_node::tprint(troff_output_file *out) space_node::tprint(out); } +unbreakable_space_node::unbreakable_space_node(hunits d, node *x) +: word_space_node(d, x) +{ +} + +unbreakable_space_node::unbreakable_space_node(hunits d, int s, node *x) +: word_space_node(d, s, x) +{ +} + +node *unbreakable_space_node::copy() +{ + return new unbreakable_space_node(n, set); +} + +breakpoint *unbreakable_space_node::get_breakpoints(hunits, int, + breakpoint *rest, int) +{ + return rest; +} + +int unbreakable_space_node::nbreaks() +{ + return 0; +} + +void unbreakable_space_node::split(int, node **, node **) +{ + assert(0); +} + +int unbreakable_space_node::merge_space(hunits) +{ + return 0; +} hvpair::hvpair() { @@ -3207,7 +3294,7 @@ const char *draw_node::type() draw_node::~draw_node() { if (point) - delete point; + a_delete point; } hunits draw_node::width() @@ -3436,7 +3523,7 @@ void bracket_node::tprint(troff_output_file *out) ++npieces; vunits h = list->size(); vunits totalh = h*npieces; - vunits y = (totalh + h)/2; + vunits y = (totalh - h)/2; out->down(y); for (tem = list; tem; tem = tem->next) { tem->zero_width_tprint(out); @@ -3446,7 +3533,7 @@ void bracket_node::tprint(troff_output_file *out) out->down(totalh - y); } -void node::tprint(troff_output_file *out) +void node::tprint(troff_output_file *) { } @@ -3495,7 +3582,53 @@ void dbreak_node::tprint(troff_output_file *out) void composite_node::tprint(troff_output_file *out) { + hunits bold_offset; + int is_bold = tf->get_bold(&bold_offset); + hunits track_kern = tf->get_track_kern(); + hunits constant_space; + int is_constant_spaced = tf->get_constant_space(&constant_space); + hunits x = H0; + if (is_constant_spaced) { + x = constant_space; + for (node *tem = n; tem; tem = tem->next) + x -= tem->width(); + if (is_bold) + x -= bold_offset; + hunits x2 = x/2; + out->right(x2); + x -= x2; + } + if (is_bold) { + int hpos = out->get_hpos(); + int vpos = out->get_vpos(); + tprint_reverse_node_list(out, n); + out->moveto(hpos, vpos); + out->right(bold_offset); + } tprint_reverse_node_list(out, n); + if (is_constant_spaced) + out->right(x); + else + out->right(track_kern); +} + +node *make_composite_node(charinfo *s, environment *env) +{ + int fontno = env_definite_font(env); + if (fontno < 0) { + error("no current font"); + return 0; + } + assert(fontno < font_table_size && font_table[fontno] != 0); + node *n = charinfo_to_node_list(s, env); + font_size fs = env->get_font_size(); + int char_height = env->get_char_height(); + int char_slant = env->get_char_slant(); + tfont *tf = font_table[fontno]->get_tfont(fs, char_height, char_slant, + fontno); + if (env->is_composite()) + tf = tf->get_plain(); + return new composite_node(n, s, tf); } node *make_glyph_node(charinfo *s, environment *env, int no_error_message = 0) @@ -3565,6 +3698,8 @@ node *make_glyph_node(charinfo *s, environment *env, int no_error_message = 0) int char_height = env->get_char_height(); int char_slant = env->get_char_slant(); tfont *tf = font_table[fontno]->get_tfont(fs, char_height, char_slant, fn); + if (env->is_composite()) + tf = tf->get_plain(); return new glyph_node(s, tf); } @@ -3575,13 +3710,16 @@ node *make_node(charinfo *ci, environment *env) return new space_char_hmotion_node(env->get_space_width()); case charinfo::TRANSLATE_DUMMY: return new dummy_node; + case charinfo::TRANSLATE_HYPHEN_INDICATOR: + error("translation to \\% ignored in this context"); + break; } charinfo *tem = ci->get_translation(); if (tem) ci = tem; macro *mac = ci->get_macro(); if (mac) - return charinfo_to_node(ci, env); + return make_composite_node(ci, env); else return make_glyph_node(ci, env); } @@ -3613,13 +3751,15 @@ node *node::add_char(charinfo *ci, environment *env, hunits *widthp) return res; case charinfo::TRANSLATE_DUMMY: return new dummy_node(this); + case charinfo::TRANSLATE_HYPHEN_INDICATOR: + return add_discretionary_hyphen(); } charinfo *tem = ci->get_translation(); if (tem) ci = tem; macro *mac = ci->get_macro(); if (mac) { - res = charinfo_to_node(ci, env); + res = make_composite_node(ci, env); if (res) { res->next = this; *widthp += res->width(); @@ -4069,6 +4209,17 @@ const char *word_space_node::type() return "word_space_node"; } +int unbreakable_space_node::same(node *nd) +{ + return (n == ((unbreakable_space_node *)nd)->n + && set == ((unbreakable_space_node *)nd)->set); +} + +const char *unbreakable_space_node::type() +{ + return "unbreakable_space_node"; +} + int diverted_space_node::same(node *nd) { return n == ((diverted_space_node *)nd)->n; @@ -4103,6 +4254,7 @@ static void grow_font_table(int n) if (old_font_table_size) memcpy(font_table, old_font_table, old_font_table_size*sizeof(font_info *)); + a_delete old_font_table; for (int i = old_font_table_size; i < font_table_size; i++) font_table[i] = 0; } @@ -4126,15 +4278,20 @@ static int mount_font_no_translate(int n, symbol name, symbol external_name) font *fm = 0; void *p = font_dictionary.lookup(external_name); if (p == 0) { - fm = font::load_font(external_name.contents()); + int not_found; + fm = font::load_font(external_name.contents(), ¬_found); if (!fm) { + if (not_found) + warning(WARN_FONT, "can't find font `%1'", external_name.contents()); font_dictionary.lookup(external_name, &a_char); return 0; } font_dictionary.lookup(name, fm); } else if (p == &a_char) { +#if 0 error("invalid font `%1'", external_name.contents()); +#endif return 0; } else @@ -4222,7 +4379,7 @@ font_family::font_family(symbol s) font_family::~font_family() { - delete map; + a_delete map; } int font_family::make_definite(int i) @@ -4241,7 +4398,7 @@ int font_family::make_definite(int i) map_size = i + 10; map = new int[map_size]; memcpy(map, old_map, old_map_size*sizeof(int)); - delete old_map; + a_delete old_map; for (int j = old_map_size; j < map_size; j++) map[j] = -1; } @@ -4444,11 +4601,20 @@ hunits env_space_width(environment *env) int fn = env_definite_font(env); font_size fs = env->get_font_size(); if (fn < 0 || fn >= font_table_size || font_table[fn] == 0) - return fs.to_units()/3; + return scale(fs.to_units()/3, env->get_space_size(), 12); else - return font_table[fn]->get_space_width(fs); + return font_table[fn]->get_space_width(fs, env->get_space_size()); } +hunits env_sentence_space_width(environment *env) +{ + int fn = env_definite_font(env); + font_size fs = env->get_font_size(); + if (fn < 0 || fn >= font_table_size || font_table[fn] == 0) + return scale(fs.to_units()/3, env->get_sentence_space_size(), 12); + else + return font_table[fn]->get_space_width(fs, env->get_sentence_space_size()); +} hunits env_half_narrow_space_width(environment *env) { @@ -4478,27 +4644,19 @@ void bold_font() if (tok.delimiter()) { int f = get_fontno(); if (f >= 0) { - if (has_arg()) { - units offset; - if (get_number(&offset, 'u')) { - if (offset >= 1) - font_table[f]->set_conditional_bold(n, hunits(offset - 1)); - else - font_table[f]->conditional_unbold(n); - } - } + units offset; + if (has_arg() && get_number(&offset, 'u') && offset >= 1) + font_table[f]->set_conditional_bold(n, hunits(offset - 1)); else font_table[f]->conditional_unbold(n); } } else { units offset; - if (get_number(&offset, 'u')) { - if (offset >= 1) - font_table[n]->set_bold(hunits(offset - 1)); - else - font_table[n]->unbold(); - } + if (get_number(&offset, 'u') && offset >= 1) + font_table[n]->set_bold(hunits(offset - 1)); + else + font_table[n]->unbold(); } } else @@ -4564,18 +4722,15 @@ void track_kern() { int n = get_fontno(); if (n >= 0) { - if (has_arg()) { - int min_s, max_s; - hunits min_a, max_a; - if (!get_number(&min_s, 'z') - || !get_hunits(&min_a, 'p') - || !get_number(&max_s, 'z') - || !get_hunits(&max_a, 'p')) - error("bad arguments for track kerning"); - else { - track_kerning_function tk(min_s, min_a, max_s, max_a); - font_table[n]->set_track_kern(tk); - } + int min_s, max_s; + hunits min_a, max_a; + if (has_arg() + && get_number(&min_s, 'z') + && get_hunits(&min_a, 'p') + && get_number(&max_s, 'z') + && get_hunits(&max_a, 'p')) { + track_kerning_function tk(min_s, min_a, max_s, max_a); + font_table[n]->set_track_kern(tk); } else { track_kerning_function tk; @@ -4587,15 +4742,15 @@ void track_kern() void constant_space() { - int x, y; int n = get_fontno(); if (n >= 0) { - if (!has_arg()) + int x, y; + if (!has_arg() || !get_integer(&x)) font_table[n]->set_constant_space(CONSTANT_SPACE_NONE); - else if (get_integer(&x)) { - if (!has_arg()) + else { + if (!has_arg() || !get_number(&y, 'z')) font_table[n]->set_constant_space(CONSTANT_SPACE_RELATIVE, x); - else if (get_number(&y, 'z')) + else font_table[n]->set_constant_space(CONSTANT_SPACE_ABSOLUTE, scale(y*x, units_per_inch, @@ -4607,14 +4762,9 @@ void constant_space() void ligature() { - if (has_arg()) { - int lig; - if (get_integer(&lig)) { - if (lig > 2 || lig < 0) - lig = 1; - global_ligature_mode = lig; - } - } + int lig; + if (has_arg() && get_integer(&lig) && lig >= 0 && lig <= 2) + global_ligature_mode = lig; else global_ligature_mode = 1; skip_line(); @@ -4622,16 +4772,22 @@ void ligature() void kern_request() { - if (has_arg()) { - int k; - if (get_integer(&k)) - global_kern_mode = k != 0; - } + int k; + if (has_arg() && get_integer(&k)) + global_kern_mode = k != 0; else global_kern_mode = 1; skip_line(); } +void set_soft_hyphen_char() +{ + soft_hyphen_char = get_optional_char(); + if (!soft_hyphen_char) + soft_hyphen_char = get_charinfo(HYPHEN_SYMBOL); + skip_line(); +} + void init_output() { if (suppress_output_flag) @@ -4678,11 +4834,12 @@ void init_node_requests() init_request("special", special_request); init_request("fspecial", font_special_request); init_request("ftr", font_translate); + init_request("shc", set_soft_hyphen_char); number_reg_dictionary.define(".fp", new next_available_font_position_reg); number_reg_dictionary.define(".kern", new constant_int_reg(&global_kern_mode)); number_reg_dictionary.define(".lg", new constant_int_reg(&global_ligature_mode)); number_reg_dictionary.define(".P", new printing_reg); + soft_hyphen_char = get_charinfo(HYPHEN_SYMBOL); } - diff --git a/gnu/usr.bin/groff/troff/node.h b/gnu/usr.bin/groff/troff/node.h index e443b1e0c9b..02526e7c953 100644 --- a/gnu/usr.bin/groff/troff/node.h +++ b/gnu/usr.bin/groff/troff/node.h @@ -1,12 +1,12 @@ // -*- C++ -*- -/* Copyright (C) 1989, 1990 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.uucp) +/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) This file is part of groff. groff is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 1, or (at your option) any later +Software Foundation; either version 2, or (at your option) any later version. groff is distributed in the hope that it will be useful, but WITHOUT ANY @@ -15,7 +15,7 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along -with groff; see the file LICENSE. If not, write to the Free Software +with groff; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ @@ -170,6 +170,7 @@ public: }; class word_space_node : public space_node { +protected: word_space_node(hunits, int, node * = 0); public: word_space_node(hunits, node * = 0); @@ -179,7 +180,20 @@ public: const char *type(); }; - +class unbreakable_space_node : public word_space_node { + unbreakable_space_node(hunits, int, node * = 0); +public: + unbreakable_space_node(hunits, node * = 0); + node *copy(); + int same(node *); + const char *type(); + breakpoint *get_breakpoints(hunits width, int nspaces, breakpoint *rest = 0, + int is_inner = 0); + int nbreaks(); + void split(int, node **, node **); + int merge_space(hunits); +}; + class diverted_space_node : public node { public: vunits n; @@ -389,33 +403,6 @@ public: const char *type(); }; -class charinfo; - -class composite_node : public node { - charinfo *ci; - node *n; - font_size sz; -public: - composite_node(node *, charinfo *, font_size, node * = 0); - ~composite_node(); - node *copy(); - hunits width(); - node *last_char_node(); - units size(); - void tprint(troff_output_file *); - hyphenation_type get_hyphenation_type(); - int overlaps_horizontally(); - int overlaps_vertically(); - void ascii_print(ascii_output_file *); - void asciify(macro *); - hyphen_list *get_hyphen_list(hyphen_list *tail); - node *add_self(node *, hyphen_list **); - tfont *get_tfont(); - int same(node *); - const char *type(); - void vertical_extent(vunits *, vunits *); - vunits vertical_width(); -}; struct hvpair { hunits h; @@ -440,6 +427,7 @@ public: const char *type(); }; +class charinfo; node *make_node(charinfo *ci, environment *); int character_exists(charinfo *, environment *); @@ -448,10 +436,6 @@ node *reverse_node_list(node *n); void delete_node_list(node *); node *copy_node_list(node *); -hunits env_digit_width(environment *); -hunits env_space_width(environment *); -hunits env_narrow_space_width(environment *); -hunits env_half_narrow_space_width(environment *); int get_bold_fontno(int f); inline hyphen_list::hyphen_list(unsigned char code, hyphen_list *p) @@ -473,6 +457,7 @@ class output_file { public: output_file(); virtual ~output_file(); + virtual void trailer(vunits page_length); virtual void flush() = 0; virtual void transparent_char(unsigned char) = 0; virtual void print_line(hunits x, vunits y, node *n, diff --git a/gnu/usr.bin/groff/troff/number.cc b/gnu/usr.bin/groff/troff/number.cc index cbd8a285f96..3e695b527ac 100644 --- a/gnu/usr.bin/groff/troff/number.cc +++ b/gnu/usr.bin/groff/troff/number.cc @@ -1,12 +1,12 @@ // -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.uucp) +/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) This file is part of groff. groff is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 1, or (at your option) any later +Software Foundation; either version 2, or (at your option) any later version. groff is distributed in the hope that it will be useful, but WITHOUT ANY @@ -15,11 +15,11 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along -with groff; see the file LICENSE. If not, write to the Free Software +with groff; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "groff.h" +#include "troff.h" #include "symbol.h" #include "hvunits.h" #include "env.h" @@ -388,10 +388,6 @@ static int parse_term(units *v, int scale_indicator, int parenthesised) tok.next(); negative = !negative; } - else if (tok.is_size()) { - tok.process(); - tok.next(); - } else break; unsigned char c = tok.ch(); @@ -402,12 +398,21 @@ static int parse_term(units *v, int scale_indicator, int parenthesised) tok.next(); if (!parse_term(v, scale_indicator, parenthesised)) return 0; - int tem = (scale_indicator == 'v' - ? curdiv->get_vertical_position().to_units() - : curenv->get_input_line_position().to_units()); - if (*v < INT_MIN + tem) { - error("numeric overflow"); - return 0; + int tem; + tem = (scale_indicator == 'v' + ? curdiv->get_vertical_position().to_units() + : curenv->get_input_line_position().to_units()); + if (tem >= 0) { + if (*v < INT_MIN + tem) { + error("numeric overflow"); + return 0; + } + } + else { + if (*v > INT_MAX + tem) { + error("numeric overflow"); + return 0; + } } *v -= tem; if (negative) { @@ -434,7 +439,8 @@ static int parse_term(units *v, int scale_indicator, int parenthesised) scale_indicator = c; } else { - error("expected `;' after scale-indicator"); + error("expected `;' after scale-indicator (got %1)", + tok.description()); return 0; } } @@ -446,7 +452,7 @@ static int parse_term(units *v, int scale_indicator, int parenthesised) return 0; tok.skip(); if (tok.ch() != ')') { - warning(WARN_SYNTAX, "missing ')'"); + warning(WARN_SYNTAX, "missing `)' (got %1)", tok.description()); } else tok.next(); @@ -478,7 +484,7 @@ static int parse_term(units *v, int scale_indicator, int parenthesised) return 0; } *v *= 10; - if (*v > INT_MAX - (c - '0')) { + if (*v > INT_MAX - (int(c) - '0')) { error("numeric overflow"); return 0; } @@ -520,6 +526,7 @@ static int parse_term(units *v, int scale_indicator, int parenthesised) } } int si = scale_indicator; + int do_next = 0; if ((c = tok.ch()) != 0 && strchr(SCALE_INDICATOR_CHARS, c) != 0) { switch (scale_indicator) { case 'z': @@ -544,7 +551,9 @@ static int parse_term(units *v, int scale_indicator, int parenthesised) si = c; break; } - tok.next(); + // Don't do tok.next() here because the next token might be \s, which + // would affect the interpretation of m. + do_next = 1; } switch (si) { case 'i': @@ -600,10 +609,8 @@ static int parse_term(units *v, int scale_indicator, int parenthesised) default: assert(0); } - if (tok.is_size()) { - tok.process(); + if (do_next) tok.next(); - } if (negative) { if (*v == INT_MIN) { error("numeric overflow"); diff --git a/gnu/usr.bin/groff/troff/reg.cc b/gnu/usr.bin/groff/troff/reg.cc index 57c5440e8a8..cefeb87ed5f 100644 --- a/gnu/usr.bin/groff/troff/reg.cc +++ b/gnu/usr.bin/groff/troff/reg.cc @@ -1,12 +1,12 @@ // -*- C++ -*- -/* Copyright (C) 1989, 1990 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.uucp) +/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) This file is part of groff. groff is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 1, or (at your option) any later +Software Foundation; either version 2, or (at your option) any later version. groff is distributed in the hope that it will be useful, but WITHOUT ANY @@ -15,10 +15,10 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along -with groff; see the file LICENSE. If not, write to the Free Software +with groff; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "groff.h" +#include "troff.h" #include "symbol.h" #include "dictionary.h" #include "token.h" @@ -294,15 +294,15 @@ void define_number_reg() return; } reg *r = (reg *)number_reg_dictionary.lookup(nm); - if (r == 0) { - r = new number_reg; - number_reg_dictionary.define(nm, r); - } units v; units prev_value; - if (!r->get_value(&prev_value)) + if (!r || !r->get_value(&prev_value)) prev_value = 0; if (get_number(&v, 'u', prev_value)) { + if (r == 0) { + r = new number_reg; + number_reg_dictionary.define(nm, r); + } r->set_value(v); if (tok.space() && has_arg() && get_number(&v, 'u')) r->set_increment(v); diff --git a/gnu/usr.bin/groff/troff/reg.h b/gnu/usr.bin/groff/troff/reg.h index 2614f2824e1..4ecbc979601 100644 --- a/gnu/usr.bin/groff/troff/reg.h +++ b/gnu/usr.bin/groff/troff/reg.h @@ -1,12 +1,12 @@ // -*- C++ -*- -/* Copyright (C) 1989, 1990 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.uucp) +/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) This file is part of groff. groff is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 1, or (at your option) any later +Software Foundation; either version 2, or (at your option) any later version. groff is distributed in the hope that it will be useful, but WITHOUT ANY @@ -15,7 +15,7 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along -with groff; see the file LICENSE. If not, write to the Free Software +with groff; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ diff --git a/gnu/usr.bin/groff/troff/request.h b/gnu/usr.bin/groff/troff/request.h index 895d68c84e7..2de9fb7c773 100644 --- a/gnu/usr.bin/groff/troff/request.h +++ b/gnu/usr.bin/groff/troff/request.h @@ -1,12 +1,12 @@ // -*- C++ -*- -/* Copyright (C) 1989, 1990 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.uucp) +/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) This file is part of groff. groff is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 1, or (at your option) any later +Software Foundation; either version 2, or (at your option) any later version. groff is distributed in the hope that it will be useful, but WITHOUT ANY @@ -15,7 +15,7 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along -with groff; see the file LICENSE. If not, write to the Free Software +with groff; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ typedef void (*REQUEST_FUNCP)(); @@ -58,6 +58,7 @@ public: void invoke(symbol); macro *to_macro(); void print_size(); + int empty(); friend class string_iterator; friend void chop_macro(); friend int operator==(const macro &, const macro &); @@ -76,4 +77,4 @@ extern int no_break_flag; // indicates whether request was invoked with . or ' class charinfo; class environment; -node *charinfo_to_node(charinfo *, const environment *); +node *charinfo_to_node_list(charinfo *, const environment *); diff --git a/gnu/usr.bin/groff/troff/symbol.cc b/gnu/usr.bin/groff/troff/symbol.cc index e1aea00c6b1..eb816990d1e 100644 --- a/gnu/usr.bin/groff/troff/symbol.cc +++ b/gnu/usr.bin/groff/troff/symbol.cc @@ -1,12 +1,12 @@ // -*- C++ -*- -/* Copyright (C) 1989, 1990 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.uucp) +/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) This file is part of groff. groff is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 1, or (at your option) any later +Software Foundation; either version 2, or (at your option) any later version. groff is distributed in the hope that it will be useful, but WITHOUT ANY @@ -15,11 +15,11 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along -with groff; see the file LICENSE. If not, write to the Free Software +with groff; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "groff.h" +#include "troff.h" #include "symbol.h" const char **symbol::table = 0; @@ -30,6 +30,10 @@ int symbol::block_size = 0; const symbol NULL_SYMBOL; +#ifdef BLOCK_SIZE +#undef BLOCK_SIZE +#endif + const int BLOCK_SIZE = 1024; // the table will increase in size as necessary // the size will be chosen from the following array @@ -72,7 +76,7 @@ symbol::symbol(const char *p, int how) } if (table == 0) { table_size = table_sizes[0]; - table = new char*[table_size]; + table = (const char **)new char*[table_size]; for (int i = 0; i < table_size; i++) table[i] = 0; table_used = 0; @@ -97,7 +101,7 @@ symbol::symbol(const char *p, int how) fatal("too many symbols"); table_size = table_sizes[i]; table_used = 0; - table = new char*[table_size]; + table = (const char **)new char*[table_size]; for (i = 0; i < table_size; i++) table[i] = 0; for (pp = old_table + old_table_size - 1; @@ -105,7 +109,7 @@ symbol::symbol(const char *p, int how) --pp) { symbol temp(*pp, 1); /* insert it into the new table */ } - delete old_table; + a_delete old_table; for (pp = table + hc % table_size; *pp != 0; (pp == table ? pp = table + table_size - 1 : --pp)) @@ -134,7 +138,7 @@ symbol concat(symbol s1, symbol s2) strcpy(buf, s1.contents()); strcat(buf, s2.contents()); symbol res(buf); - delete buf; + a_delete buf; return res; } diff --git a/gnu/usr.bin/groff/troff/symbol.h b/gnu/usr.bin/groff/troff/symbol.h index d0420e96fb6..37916742de2 100644 --- a/gnu/usr.bin/groff/troff/symbol.h +++ b/gnu/usr.bin/groff/troff/symbol.h @@ -1,12 +1,12 @@ // -*- C++ -*- -/* Copyright (C) 1989, 1990 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.uucp) +/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) This file is part of groff. groff is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 1, or (at your option) any later +Software Foundation; either version 2, or (at your option) any later version. groff is distributed in the hope that it will be useful, but WITHOUT ANY @@ -15,7 +15,7 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along -with groff; see the file LICENSE. If not, write to the Free Software +with groff; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define DONT_STORE 1 @@ -31,7 +31,7 @@ class symbol { public: symbol(const char *p, int how = 0); symbol(); - int hash() const; + unsigned long hash() const; operator ==(symbol) const; operator !=(symbol) const; const char *contents() const; @@ -55,12 +55,9 @@ inline int symbol::operator!=(symbol p) const return s != p.s; } -// guaranteed to return a positive integer - -inline int symbol::hash() const +inline unsigned long symbol::hash() const { - int i = int(s); - return i < 0 ? -i : i; + return (unsigned long)s; } inline const char *symbol::contents() const diff --git a/gnu/usr.bin/groff/troff/token.h b/gnu/usr.bin/groff/troff/token.h index 6c09cf5785b..486c6eafde1 100644 --- a/gnu/usr.bin/groff/troff/token.h +++ b/gnu/usr.bin/groff/troff/token.h @@ -1,12 +1,12 @@ // -*- C++ -*- -/* Copyright (C) 1989, 1990 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.uucp) +/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) This file is part of groff. groff is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 1, or (at your option) any later +Software Foundation; either version 2, or (at your option) any later version. groff is distributed in the hope that it will be useful, but WITHOUT ANY @@ -15,7 +15,7 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along -with groff; see the file LICENSE. If not, write to the Free Software +with groff; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ @@ -36,14 +36,10 @@ class token { TOKEN_BACKSPACE, TOKEN_BEGIN_TRAP, TOKEN_CHAR, // a normal printing character - TOKEN_CHAR_HEIGHT, // \H - TOKEN_CHAR_SLANT, // \S TOKEN_DUMMY, TOKEN_EMPTY, // this is the initial value TOKEN_END_TRAP, TOKEN_ESCAPE, // \e - TOKEN_FONT_NAME, // \f followed by a name - TOKEN_FONT_POSITION, // \f followed by a digit TOKEN_HYPHEN_INDICATOR, TOKEN_INTERRUPT, // \c TOKEN_ITALIC_CORRECTION, // \/ @@ -56,7 +52,6 @@ class token { TOKEN_PAGE_EJECTOR, TOKEN_REQUEST, TOKEN_RIGHT_BRACE, - TOKEN_SIZE, // \s TOKEN_SPACE, // ` ' -- ordinary space TOKEN_SPECIAL, // a special character -- \' \` \- \(xx TOKEN_SPREAD, // \p -- break and spread output line @@ -81,19 +76,17 @@ public: int leader(); int backspace(); int delimiter(int warn = 0); // is it suitable for use as a delimiter? - symbol special(); int dummy(); int transparent(); int left_brace(); int right_brace(); int page_ejector(); + int hyphen_indicator(); int operator==(const token &); // need this for delimiters, and for conditions int operator!=(const token &); // ditto unsigned char ch(); charinfo *get_char(int required = 0); int add_to_node_list(node **); - int changes_env(); - int is_size(); int title(); void make_space(); void make_newline(); @@ -166,21 +159,11 @@ inline int token::eof() return type == TOKEN_EOF; } -inline symbol token::special() -{ - return type == TOKEN_SPECIAL ? nm : symbol(); -} - inline int token::dummy() { return type == TOKEN_DUMMY; } -inline int token::is_size() -{ - return type == TOKEN_SIZE; -} - inline int token::left_brace() { return type == TOKEN_LEFT_BRACE; @@ -191,15 +174,6 @@ inline int token::right_brace() return type == TOKEN_RIGHT_BRACE; } -inline int token::changes_env() -{ - return (type == TOKEN_CHAR_HEIGHT - || type == TOKEN_CHAR_SLANT - || type == TOKEN_FONT_NAME - || type == TOKEN_FONT_POSITION - || type == TOKEN_SIZE); -} - inline int token::tab() { return type == TOKEN_TAB; @@ -215,4 +189,9 @@ inline int token::backspace() return type == TOKEN_BACKSPACE; } +inline int token::hyphen_indicator() +{ + return type == TOKEN_HYPHEN_INDICATOR; +} + int has_arg(); diff --git a/gnu/usr.bin/groff/troff/troff.1 b/gnu/usr.bin/groff/troff/troff.1 index 165d4f67ab4..35184e817fb 100644 --- a/gnu/usr.bin/groff/troff/troff.1 +++ b/gnu/usr.bin/groff/troff/troff.1 @@ -7,20 +7,30 @@ .ns .TP \\$1 .. -.TH GTROFF 1 "19 October 1990" "Groff Version @VERSION@" +.\" Like TP, but if specified indent is more than half +.\" the current line-length - indent, use the default indent. +.de Tp +.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP +.el .TP "\\$1" +.. +.\" The BSD man macros can't handle " in arguments to font change macros, +.\" so use \(ts instead of ". +.tr \(ts" +.TH TROFF 1 "1 April 1993" "Groff Version 1.08" .SH NAME -gtroff \- format documents -.SH SYNOPIS +troff \- format documents +.SH SYNOPSIS +.nr a \n(.j .ad l .nr i \n(.i -.in +\w'\fBgtroff 'u +.in +\w'\fBtroff 'u .ti \niu -.B gtroff +.B troff .de OP .ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]" .el .RB "[\ " "\\$1" "\ ]" .. -.OP \-abivzCE +.OP \-abivzCER .OP \-w name .OP \-W name .OP \-d cs @@ -32,13 +42,14 @@ gtroff \- format documents .OP \-T name .OP \-F dir .OP \-M dir -.OP \-H file .RI "[\ " files\|.\|.\|. "\ ]" .br -.ad b +.ad \na .SH DESCRIPTION -gtroff is the central part of the groff document formatting system. -It is highly compatible with device-independent troff. +This manual page describes the GNU version of +.BR troff , +which is part of the groff document formatting system. +It is highly compatible with Unix troff. Usually it should be invoked using the groff command, which will also run preprocessors and postprocessors in the appropriate order and with the appropriate options. @@ -52,7 +63,7 @@ approximation of the typeset output. .B \-b Print a backtrace with each warning or error message. This backtrace should help track down the cause of the error. The line numbers given -in the backtrace may not always correct: gtroff's idea of line numbers +in the backtrace may not always correct: troff's idea of line numbers gets confused by .B as or @@ -111,7 +122,11 @@ as the default font family. .BI \-m name Read in the file .BI tmac. name\fR. -Normally this will be searched for in @MACRODIR@. +Normally this will be searched for in /usr/share/tmac. +.TP +.B \-R +Don't load +.BR troffrc . .TP .BI \-n num Number the first page @@ -130,7 +145,7 @@ means print every page between and .IR n , .BI \- n -mans print every page up to +means print every page up to .IR n , .IB n \- means print every page from @@ -148,13 +163,13 @@ to .I c must be a one character name; .I n -can be any gtroff numeric expression. +can be any troff numeric expression. .TP .BI \-T name Prepare output for device .IR name , rather than the default -.BR @DEVICE@ . +.BR ps . .TP .BI \-F dir Search @@ -166,21 +181,15 @@ is the name of the device) for the .B DESC file and font files before the normal -.BR @FONTDIR@ . -.TP -.BI \-H file -Read hyphenation patterns from -.IR file , -rather than the default -.BR @HYPHENFILE@ . +.BR /usr/share/groff_font . .TP .BI \-M dir Search directory .I dir for macro files before the normal -.BR @MACRODIR@ . +.BR /usr/share/tmac . .SH USAGE -Only the features not in device-independent troff are described here. +Only the features not in Unix troff are described here. .SS Long names The names of number registers, fonts, strings/macros/diversions, special characters can be of any length. In escape sequences, where @@ -217,7 +226,7 @@ file (1 by default.) There is a new scale indicator .B z which has the effect of multiplying by sizescale. -Requests and escape sequences in gtroff +Requests and escape sequences in troff interpret arguments that represent a pointsize as being in units of scaled points, but they evaluate each such argument using a default scale indicator of @@ -263,7 +272,7 @@ whose default scale indicator was neither nor .BR z , and so -.B gtroff +.B troff disallows this. Similarily it would make no sense to use a scaling indicator other than @@ -273,7 +282,7 @@ or in a numeric expression whose default scale indicator was .BR z , and so -.B gtroff +.B troff disallows this as well. .LP There is also new scale indicator @@ -319,6 +328,23 @@ is missing, ignore scaling indicators in the evaluation of .IR e . .SS New escape sequences .TP +.BI \eA' anything ' +This expands to +.B 1 +or +.B 0 +according as +.I anything +is or is not acceptable as the name of a string, macro, diversion, +number register, environment or font. +It will return +.B 0 +if +.I anything +is empty. +This is useful if you want to lookup user input in some sort of +associative table. +.TP .BI \eC' xxx ' Typeset character named .IR xxx . @@ -354,8 +380,9 @@ Typeset the character with code .I n in the current font. .I n -must be a decimal integer between 0 and 255. -If the current font does not contain the character, +can be any integer. +Most devices only have characters with codes between 0 and 255. +If the current font does not contain a character with that code, special fonts will .I not be searched. @@ -381,6 +408,13 @@ the .B \eN escape sequence is the only way to use these. .TP +.BI \eR' name\ \(+-n ' +This has the same effect as +.RS +.IP +.BI .nr\ name\ \(+-n +.RE +.TP .BI \es( nn .TQ .BI \es\(+-( nn @@ -404,6 +438,18 @@ scaled points; is a numeric expression with a default scale indicator of .BR z . .TP +.BI \eV x +.TQ +.BI \eV( xx +.TQ +.BI \eV[ xxx ] +Interpolate the contents of the environment variable +.I xxx , +as returned by +.BR getenv (3). +.B \eV +is interpreted in copy-mode. +.TP .BI \eY x .TQ .BI \eY( xx @@ -420,7 +466,7 @@ to have been defined as a macro and thus contain newlines (it is not permitted for the argument to .B \eX to contain newlines). -The inclusion of newlines requires an extension to the troff output +The inclusion of newlines requires an extension to the Unix troff output format, and will confuse drivers that do not know about this extension. .TP @@ -434,7 +480,7 @@ may not contain tabs or leaders. The name by which the current macro was invoked. The .B als -request can make a macro can have more than one name. +request can make a macro have more than one name. .TP .B \e$* In a macro, the concatenation of all the arguments separated by spaces. @@ -467,7 +513,7 @@ may not contain newlines; use .B \e! if you want to embed newlines in a diversion. The escape sequence -.B \e! +.B \e? is also recognised in copy mode and turned into a single internal code; it is this code that terminates .IR anything . @@ -538,6 +584,19 @@ Like except that it behaves like a character declared with the .B cflags request to be transparent for the purposes of end of sentence recognition. +.TP +.B \e~ +This produces an unbreakable space that stretches like a normal inter-word +space when a line is adjusted. +.TP +.B \e# +Everything up to and including the next newline is ignored. +This is interpreted in copy mode. +This is like +.B \e% +except that +.B \e% +does not ignore the terminating newline. .SS New requests .TP .BI .aln\ xx\ yy @@ -578,7 +637,7 @@ request; normally they modify the value of an existing object. .TP .BI .asciify\ xx This request only exists in order to make it possible -to make certain gross troff hacks work with gtroff. +to make certain gross hacks work with GNU troff. It `unformats' the diversion .I xx in such a way that @@ -671,7 +730,7 @@ the character is transparent for the purposes of end of sentence recognition; this is the same as having a zero space factor in \*(tx (initially characters -.B """')]*\e(dg" +.B \(ts')]*\e(dg\e(rq have this property). .RE .TP @@ -686,6 +745,15 @@ needs to be printed, .I string will be processed in a temporary environment and the result will be wrapped up into a single object. +Compatibility mode will be turned off +and the escape character will be set to +.B \e +while +.I string +is being processed. +Any emboldening, constant spacing or track kerning will be applied +to this object rather than to individual characters in +.IR string . A character defined by this request can be used just like a normal character provided by the output device. In particular other characters can be translated to it @@ -708,6 +776,9 @@ There is a special anti-recursion feature: use of character within the character's definition will be handled like normal characters not defined with .BR char . +A character definition can be removed with the +.B rchar +request. .TP .BI .chop\ xx Chop the last character off macro, string, or diversion @@ -742,6 +813,28 @@ disable it. In compatibility mode, long names are not recognised, and the incompatibilities caused by long names do not arise. .TP +.BI .do\ xxx +Interpret +.I .xxx +with compatibility mode disabled. +For example, +.RS +.IP +.B +\&.do fam T +.LP +would have the same effect as +.IP +.B +\&.fam T +.LP +except that it would work even if compatibility mode had been enabled. +Note that the previous compatibility mode is restored before any files +sourced by +.I xxx +are interpreted. +.RE +.TP .BI .fam\ xx Set the current font family to .IR xx . @@ -812,12 +905,23 @@ character (not a special character) other than a digit or a space. Initially each lower-case letter has a hyphenation code, which is itself, and each upper-case letter has a hyphenation code which is the lower case version of itself. -Hyphenation is controlled by a file of hyphenation patterns -(normally @HYPHENFILE@); -this file should have the same format as the argument to -the \epatterns primitive in \*(tx; -the letters appearing in this file are interpreted as hyphenation -codes. +See also the +.B hpf +request. +.TP +.BI .hla\ lang +Set the current hyphenation language to +.IR lang . +Hyphenation exceptions specified with the +.B hw +request and hyphenation patterns specified with the +.B hpf +request are both associated with the current hyphenation language. +The +.B hla +request is usually invoked by the +.B troffrc +file. .TP .BI .hlm\ n Set the maximum number of consecutive hyphenated lines to @@ -833,6 +937,33 @@ Hyphens resulting from .B \e% are counted; explicit hyphens are not. .TP +.BI .hpf\ file +Read hyphenation patterns from +.IR file ; +this will be searched for in the same way that +.BI tmac. name +is searched for when the +.BI \-m name +option is specified. +It should have the same format as the argument to +the \epatterns primitive in \*(tx; +the letters appearing in this file are interpreted as hyphenation +codes. +A +.B % +character in the patterns file introduces a comment that continues +to the end of the line. +The set of hyphenation patterns is associated with the current language +set by the +.B hla +request. +The +.B hpf +request +is usually invoked by the +.B troffrc +file. +.TP .BI .hym\ n Set the .I hyphenation margin @@ -874,6 +1005,17 @@ If .I n is non-zero or missing, enable pairwise kerning, otherwise disable it. .TP +.BI .mso\ file +The same as the +.B so +request except that +.I file +is searched for in the same way that +.BI tmac. name +is searched for when the +.BI \-m name +option is specified. +.TP .B .nroff Make the .B n @@ -914,6 +1056,14 @@ traps and diversion traps) on stderr. Empty slots in the page trap list are printed as well, because they can affect the priority of subsequently planted traps. .TP +.BI .rchar\ c1\ c2\|.\|.\|. +Remove the definitions of characters +.IR c1 , +.IR c2 ,\|.\|.\|. +This undoes the effect of a +.B char +request. +.TP .B .rj .TQ .BI .rj\ n @@ -937,6 +1087,27 @@ Rename number register to .IR yy . .TP +.BI .shc\ c +Set the soft hyphen character to +.IR c . +If +.I c +is omitted, +the soft hyphen character will be set to the default +.BR \e(hy . +The soft hyphen character is the character which will be inserted +when a word is hyphenated at a line break. +If the soft hyphen character does not exist in the font of the character +immediately preceding a potential break point, +then the line will not be broken at that point. +Neither definitions (specified with the +.B char +request) +nor translations (specified with the +.B tr +request) +are considered when finding the soft hyphen character. +.TP .BI .shift\ n In a macro, shift the arguments by .I n @@ -1010,7 +1181,7 @@ the width of every character will be increased by an amount between .I n1 and -.IR n2 : +.IR n2 ; when the current point size is less than or equal to .I s1 the width will be increased by @@ -1051,7 +1222,36 @@ Unlike with the request, the file cannot contain characters such as .SM NUL -that are not legal gtroff input characters. +that are not legal troff input characters. +.RE +.TP +.B .trnt abcd +This is the same as the +.B tr +request except that the translations do not apply to text that is +transparently throughput into a diversion with +.BR \e! . +For example, +.RS +.LP +.nf +.ft B +\&.tr ab +\&.di x +\e!.tm a +\&.di +\&.x +.fi +.ft +.LP +will print +.BR b ; +if +.B trnt +is used instead of +.B tr +it will print +.BR a . .RE .TP .B .troff @@ -1130,7 +1330,7 @@ request. .I anything is read in copy mode; a leading -.B """" +.B \(ts will be stripped. .SS Extended requests .TP @@ -1138,7 +1338,8 @@ will be stripped. When used in a diversion, this will embed in the diversion an object which, when reread, will cause the contents of .I filename -to be transparently copied through to the output. In troff, the +to be transparently copied through to the output. +In Unix troff, the contents of .I filename is immediately copied through to the output regardless of whether @@ -1163,7 +1364,7 @@ request has an optional third argument. This argument gives the external name of the font, which is used for finding the font description file. The second argument gives the internal name of the font -which is used to refer to the font in gtroff after it has been mounted. +which is used to refer to the font in troff after it has been mounted. If there is no third argument then the internal name will be used as the external name. This feature allows you to use fonts with long names in compatibility mode. @@ -1184,11 +1385,11 @@ if the end of a sentence occurs at the end of a line in fill mode, then both an inter-word space and a sentence space will be added; if two spaces follow the end of a sentence in the middle of a line, then the second space will be a sentence space. -Note that the behaviour of troff will be exactly -that exhibited by gtroff if a second argument is never given to the +Note that the behaviour of Unix troff will be exactly +that exhibited by GNU troff if a second argument is never given to the .B ss request. -In gtroff, as in troff, you should always +In GNU troff, as in Unix troff, you should always follow a sentence with either a newline or two spaces. .TP .BI .ta\ n1\ n2\|.\|.\|.nn \ T\ r1\ r2\|.\|.\|.\|rn @@ -1253,7 +1454,12 @@ The number of the next free font position. .B \en[.g] Always 1. Macros should use this to determine whether they are running -under gtroff. +under GNU troff. +.TP +.B \en[.hla] +The current hyphenation language as set by the +.B hla +request. .TP .B \en[.hlc] The number of immediately preceding consecutive hyphenated lines. @@ -1281,6 +1487,17 @@ request.) .B \en[.in] The indent that applies to the current output line. .TP +.B \en[.kern] +.B 1 +if pairwise kerning is enabled, +.B 0 +otherwise. +.TP +.B \en[.lg] +The current ligature mode (as set by the +.B lg +request.) +.TP .B \en[.ll] The line length that applies to the current output line. .TP @@ -1425,7 +1642,7 @@ which can be found in the .B \en[.fp] register; although -.B gtroff +.B troff does not enforce this strictly, it will not allow a font to be mounted at a position whose number is much greater than that of any currently used position. @@ -1467,6 +1684,11 @@ The implementation of ensures that the double quotes surrounding an argument will appear the same input level, which will be different to the input level of the argument itself. +In a long escape name +.B ] +will not be recognized as a closing delimiter except +when it occurs at the same input level as the opening +.BR ] . In compatibility mode, no attention is paid to the input-level. .LP There are some new types of condition: @@ -1498,7 +1720,7 @@ has been defined by the request. .SS Warnings The warnings that can be given by -.B gtroff +.B troff are divided into the following categories. The name associated with each warning is used by the .B \-w @@ -1594,9 +1816,11 @@ and the first two characters of the name make a defined name. The request or macro will not be invoked. When this warning is given, no macro is automatically defined. This is enabled by default. -.B mac -is given. This warning will never occur in compatibility mode. +.TP +.BR font \t131072 +Non-existent fonts. +This is enabled by default. .LP There are also names that can be used to refer to groups of warnings: .TP @@ -1614,7 +1838,7 @@ All warnings. .SS Incompatibilities .LP Long names cause some incompatibilities. -Troff will interpret +Unix troff will interpret .IP .B \&.dsabcd @@ -1623,19 +1847,19 @@ as defining a string .B ab with contents .BR cd . -Normally, gtroff will interpret this as a call of a macro named +Normally, GNU troff will interpret this as a call of a macro named .BR dsabcd . -Also troff will interpret +Also Unix troff will interpret .B \e*[ or .B \en[ as references to a string or number register called .BR [ . -In gtroff, however, this will normally be interpreted as the start +In GNU troff, however, this will normally be interpreted as the start of a long name. In .I compatibility mode -gtroff will interpret these things in the traditional way. +GNU troff will interpret these things in the traditional way. In compatibility mode, however, long names are not recognised. Compatibility mode can be turned on with the .B \-C @@ -1646,20 +1870,27 @@ The number register .B \en(.C is 1 if compatibility mode is on, 0 otherwise. .LP +GNU troff +does not allow the use of the escape sequences +.BR \\e\e|\e^\e&\e}\e{\e (space) \e'\e`\e-\e_\e!\e%\ec +in names of strings, macros, diversions, number registers, +fonts or environments; Unix troff does. +The +.B \eA +escape sequence may be helpful in avoiding use of these +escape sequences in names. +.LP Fractional pointsizes cause one noteworthy incompatibility. -In -.B troff -the +In Unix troff the .B ps request ignores scale indicators and so .IP .B .ps\ 10u .LP will set the pointsize to 10 points, whereas in -.B gtroff -it will set the pointsize to 10 scaled points. +GNU troff it will set the pointsize to 10 scaled points. .LP -In gtroff there is a fundamental difference between unformatted, +In GNU troff there is a fundamental difference between unformatted, input characters, and formatted, output characters. Everything that affects how an output character will be output is stored with the character; once an output @@ -1696,7 +1927,7 @@ For example, .LP will print .B \e\e -in gtroff; +in GNU troff; each pair of input .BR \e s is turned into one output @@ -1704,7 +1935,7 @@ is turned into one output and the resulting output .BR \e s are not interpreted as escape characters when they are reread. -Troff would interpret them as escape characters +Unix troff would interpret them as escape characters when they were reread and would end up printing one .BR \e . The correct way to obtain a printable @@ -1713,7 +1944,7 @@ is to use the .B \ee escape sequence: this will always print a single instance of the current escape character, regardless of whether or not it is used in a -diversion; it will also work in both gtroff and troff. +diversion; it will also work in both GNU troff and Unix troff. If you wish for some reason to store in a diversion an escape sequence that will be interpreted when the diversion is reread, you can either use the traditional @@ -1737,41 +1968,37 @@ Default device. A colon separated list of directories in which to search for the .BI dev name directory. -Gtroff will search in directories given in the +.B troff +will search in directories given in the .B \-F option before these, and in standard directories -.RB ( @FONTPATH@ ) +.RB ( /usr/share/groff_font ) after these. -.TP -.SM -.B GROFF_HYPHEN -File containing hyphenation patterns. .SH FILES -.TP \w'@FONTDIR@/devname/DESC'u+3n -.B @HYPHENFILE@ -Hyphenation patterns +.Tp \w'/usr/share/groff_font/devname/DESC'u+3n +.B /usr/share/tmac/troffrc +Initialization file .TP -.BI @MACRODIR@/tmac. name +.BI /usr/share/tmac/tmac. name Macro files .TP -.BI @FONTDIR@/dev name /DESC +.BI /usr/share/groff_font/dev name /DESC Device description file for device .IR name . .TP -.BI @FONTDIR@/dev name / F +.BI /usr/share/groff_font/dev name / F Font file for font .I F of device .IR name . .SH "SEE ALSO" -.BR groff (@MAN1EXT@) -.BR gtbl (@MAN1EXT@), -.BR gpic (@MAN1EXT@), -.BR geqn (@MAN1EXT@), -.BR grops (@MAN1EXT@), -.BR grodvi (@MAN1EXT@), -.BR grotty (@MAN1EXT@), -.BR groff_font (@MAN5EXT@), -.BR groff_out (@MAN5EXT@) -.br -.I "Groff Character Names" +.BR groff (1) +.BR tbl (1), +.BR pic (1), +.BR eqn (1), +.BR grops (1), +.BR grodvi (1), +.BR grotty (1), +.BR groff_font (5), +.BR groff_out (5), +.BR groff_char (7) diff --git a/gnu/usr.bin/groff/troff/troff.h b/gnu/usr.bin/groff/troff/troff.h new file mode 100644 index 00000000000..bfe89a0fa05 --- /dev/null +++ b/gnu/usr.bin/groff/troff/troff.h @@ -0,0 +1,88 @@ +// -*- C++ -*- +/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +This file is part of groff. + +groff is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. + +groff is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License along +with groff; see the file COPYING. If not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include <time.h> +#include <stddef.h> +#include <stdlib.h> +#include <errno.h> + +#include "lib.h" +#include "assert.h" +#include "device.h" + +#ifdef __GNUG__ +#define NO_RETURN volatile +#else +#define NO_RETURN +#endif + +NO_RETURN void cleanup_and_exit(int n); + +typedef int units; + +extern units scale(units n, units x, units y); // scale n by x/y + +extern units units_per_inch; + +extern int ascii_output_flag; +extern int suppress_output_flag; + +extern int tcommand_flag; +extern int vresolution; +extern int hresolution; +extern int sizescale; + +#include "cset.h" +#include "cmap.h" +#include "errarg.h" +#include "error.h" + +enum warning_type { + WARN_CHAR = 01, + WARN_NUMBER = 02, + WARN_BREAK = 04, + WARN_DELIM = 010, + WARN_EL = 020, + WARN_SCALE = 040, + WARN_RANGE = 0100, + WARN_SYNTAX = 0200, + WARN_DI = 0400, + WARN_MAC = 01000, + WARN_REG = 02000, + WARN_TAB = 04000, + WARN_RIGHT_BRACE = 010000, + WARN_MISSING = 020000, + WARN_INPUT = 040000, + WARN_ESCAPE = 0100000, + WARN_SPACE = 0200000, + WARN_FONT = 0400000 + // change WARN_TOTAL if you add more warning types +}; + +const int WARN_TOTAL = 0777777; + +int warning(warning_type, const char *, + const errarg & = empty_errarg, + const errarg & = empty_errarg, + const errarg & = empty_errarg); |
