From 738919c0391b99947b758d85f6a8636be1886fbb Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Wed, 7 Jun 2017 23:00:34 +0000 Subject: Remove groff from base All manpages in base are now compatible with mandoc(1), all roff documentation will be relocated in the doc tree. man(1) can now use groff from the ports tree if it needs. Also remove checknr(1) and colcrt(1) which are only useful with groff. Approved by: (no objections on the mailing lists) --- contrib/groff/src/preproc/eqn/Makefile.sub | 60 - contrib/groff/src/preproc/eqn/TODO | 49 - contrib/groff/src/preproc/eqn/box.cpp | 612 ------ contrib/groff/src/preproc/eqn/box.h | 280 --- contrib/groff/src/preproc/eqn/delim.cpp | 401 ---- contrib/groff/src/preproc/eqn/eqn.h | 50 - contrib/groff/src/preproc/eqn/eqn.man | 1160 ----------- contrib/groff/src/preproc/eqn/eqn.y | 330 --- contrib/groff/src/preproc/eqn/lex.cpp | 1172 ----------- contrib/groff/src/preproc/eqn/limit.cpp | 195 -- contrib/groff/src/preproc/eqn/list.cpp | 237 --- contrib/groff/src/preproc/eqn/main.cpp | 395 ---- contrib/groff/src/preproc/eqn/mark.cpp | 121 -- contrib/groff/src/preproc/eqn/neqn.man | 43 - contrib/groff/src/preproc/eqn/neqn.sh | 25 - contrib/groff/src/preproc/eqn/other.cpp | 601 ------ contrib/groff/src/preproc/eqn/over.cpp | 197 -- contrib/groff/src/preproc/eqn/pbox.h | 141 -- contrib/groff/src/preproc/eqn/pile.cpp | 293 --- contrib/groff/src/preproc/eqn/script.cpp | 222 -- contrib/groff/src/preproc/eqn/special.cpp | 115 - contrib/groff/src/preproc/eqn/sqrt.cpp | 180 -- contrib/groff/src/preproc/eqn/text.cpp | 528 ----- contrib/groff/src/preproc/grn/Makefile.sub | 17 - contrib/groff/src/preproc/grn/README | 68 - contrib/groff/src/preproc/grn/gprint.h | 86 - contrib/groff/src/preproc/grn/grn.man | 652 ------ contrib/groff/src/preproc/grn/hdb.cpp | 346 --- contrib/groff/src/preproc/grn/hgraph.cpp | 1048 ---------- contrib/groff/src/preproc/grn/hpoint.cpp | 49 - contrib/groff/src/preproc/grn/main.cpp | 907 -------- contrib/groff/src/preproc/html/Makefile.sub | 7 - contrib/groff/src/preproc/html/pre-html.cpp | 1779 ---------------- contrib/groff/src/preproc/html/pre-html.h | 37 - contrib/groff/src/preproc/html/pushback.cpp | 329 --- contrib/groff/src/preproc/html/pushback.h | 54 - contrib/groff/src/preproc/pic/Makefile.sub | 31 - contrib/groff/src/preproc/pic/TODO | 35 - contrib/groff/src/preproc/pic/common.cpp | 647 ------ contrib/groff/src/preproc/pic/common.h | 80 - contrib/groff/src/preproc/pic/lex.cpp | 2001 ------------------ contrib/groff/src/preproc/pic/main.cpp | 642 ------ contrib/groff/src/preproc/pic/object.cpp | 2017 ------------------ contrib/groff/src/preproc/pic/object.h | 225 -- contrib/groff/src/preproc/pic/output.h | 83 - contrib/groff/src/preproc/pic/pic.h | 123 -- contrib/groff/src/preproc/pic/pic.man | 1109 ---------- contrib/groff/src/preproc/pic/pic.y | 1898 ----------------- contrib/groff/src/preproc/pic/position.h | 47 - contrib/groff/src/preproc/pic/tex.cpp | 459 ---- contrib/groff/src/preproc/pic/text.h | 28 - contrib/groff/src/preproc/pic/troff.cpp | 567 ----- contrib/groff/src/preproc/refer/Makefile.sub | 23 - contrib/groff/src/preproc/refer/TODO | 124 -- contrib/groff/src/preproc/refer/command.cpp | 809 ------- contrib/groff/src/preproc/refer/command.h | 36 - contrib/groff/src/preproc/refer/label.y | 1193 ----------- contrib/groff/src/preproc/refer/ref.cpp | 1160 ----------- contrib/groff/src/preproc/refer/ref.h | 128 -- contrib/groff/src/preproc/refer/refer.cpp | 1242 ----------- contrib/groff/src/preproc/refer/refer.h | 78 - contrib/groff/src/preproc/refer/refer.man | 1492 ------------- contrib/groff/src/preproc/refer/token.cpp | 378 ---- contrib/groff/src/preproc/refer/token.h | 88 - contrib/groff/src/preproc/soelim/Makefile.sub | 7 - contrib/groff/src/preproc/soelim/TODO | 1 - contrib/groff/src/preproc/soelim/soelim.cpp | 308 --- contrib/groff/src/preproc/soelim/soelim.man | 216 -- contrib/groff/src/preproc/tbl/Makefile.sub | 13 - contrib/groff/src/preproc/tbl/main.cpp | 1590 -------------- contrib/groff/src/preproc/tbl/table.cpp | 2778 ------------------------- contrib/groff/src/preproc/tbl/table.h | 165 -- contrib/groff/src/preproc/tbl/tbl.man | 493 ----- 73 files changed, 35100 deletions(-) delete mode 100644 contrib/groff/src/preproc/eqn/Makefile.sub delete mode 100644 contrib/groff/src/preproc/eqn/TODO delete mode 100644 contrib/groff/src/preproc/eqn/box.cpp delete mode 100644 contrib/groff/src/preproc/eqn/box.h delete mode 100644 contrib/groff/src/preproc/eqn/delim.cpp delete mode 100644 contrib/groff/src/preproc/eqn/eqn.h delete mode 100644 contrib/groff/src/preproc/eqn/eqn.man delete mode 100644 contrib/groff/src/preproc/eqn/eqn.y delete mode 100644 contrib/groff/src/preproc/eqn/lex.cpp delete mode 100644 contrib/groff/src/preproc/eqn/limit.cpp delete mode 100644 contrib/groff/src/preproc/eqn/list.cpp delete mode 100644 contrib/groff/src/preproc/eqn/main.cpp delete mode 100644 contrib/groff/src/preproc/eqn/mark.cpp delete mode 100644 contrib/groff/src/preproc/eqn/neqn.man delete mode 100644 contrib/groff/src/preproc/eqn/neqn.sh delete mode 100644 contrib/groff/src/preproc/eqn/other.cpp delete mode 100644 contrib/groff/src/preproc/eqn/over.cpp delete mode 100644 contrib/groff/src/preproc/eqn/pbox.h delete mode 100644 contrib/groff/src/preproc/eqn/pile.cpp delete mode 100644 contrib/groff/src/preproc/eqn/script.cpp delete mode 100644 contrib/groff/src/preproc/eqn/special.cpp delete mode 100644 contrib/groff/src/preproc/eqn/sqrt.cpp delete mode 100644 contrib/groff/src/preproc/eqn/text.cpp delete mode 100644 contrib/groff/src/preproc/grn/Makefile.sub delete mode 100644 contrib/groff/src/preproc/grn/README delete mode 100644 contrib/groff/src/preproc/grn/gprint.h delete mode 100644 contrib/groff/src/preproc/grn/grn.man delete mode 100644 contrib/groff/src/preproc/grn/hdb.cpp delete mode 100644 contrib/groff/src/preproc/grn/hgraph.cpp delete mode 100644 contrib/groff/src/preproc/grn/hpoint.cpp delete mode 100644 contrib/groff/src/preproc/grn/main.cpp delete mode 100644 contrib/groff/src/preproc/html/Makefile.sub delete mode 100644 contrib/groff/src/preproc/html/pre-html.cpp delete mode 100644 contrib/groff/src/preproc/html/pre-html.h delete mode 100644 contrib/groff/src/preproc/html/pushback.cpp delete mode 100644 contrib/groff/src/preproc/html/pushback.h delete mode 100644 contrib/groff/src/preproc/pic/Makefile.sub delete mode 100644 contrib/groff/src/preproc/pic/TODO delete mode 100644 contrib/groff/src/preproc/pic/common.cpp delete mode 100644 contrib/groff/src/preproc/pic/common.h delete mode 100644 contrib/groff/src/preproc/pic/lex.cpp delete mode 100644 contrib/groff/src/preproc/pic/main.cpp delete mode 100644 contrib/groff/src/preproc/pic/object.cpp delete mode 100644 contrib/groff/src/preproc/pic/object.h delete mode 100644 contrib/groff/src/preproc/pic/output.h delete mode 100644 contrib/groff/src/preproc/pic/pic.h delete mode 100644 contrib/groff/src/preproc/pic/pic.man delete mode 100644 contrib/groff/src/preproc/pic/pic.y delete mode 100644 contrib/groff/src/preproc/pic/position.h delete mode 100644 contrib/groff/src/preproc/pic/tex.cpp delete mode 100644 contrib/groff/src/preproc/pic/text.h delete mode 100644 contrib/groff/src/preproc/pic/troff.cpp delete mode 100644 contrib/groff/src/preproc/refer/Makefile.sub delete mode 100644 contrib/groff/src/preproc/refer/TODO delete mode 100644 contrib/groff/src/preproc/refer/command.cpp delete mode 100644 contrib/groff/src/preproc/refer/command.h delete mode 100644 contrib/groff/src/preproc/refer/label.y delete mode 100644 contrib/groff/src/preproc/refer/ref.cpp delete mode 100644 contrib/groff/src/preproc/refer/ref.h delete mode 100644 contrib/groff/src/preproc/refer/refer.cpp delete mode 100644 contrib/groff/src/preproc/refer/refer.h delete mode 100644 contrib/groff/src/preproc/refer/refer.man delete mode 100644 contrib/groff/src/preproc/refer/token.cpp delete mode 100644 contrib/groff/src/preproc/refer/token.h delete mode 100644 contrib/groff/src/preproc/soelim/Makefile.sub delete mode 100644 contrib/groff/src/preproc/soelim/TODO delete mode 100644 contrib/groff/src/preproc/soelim/soelim.cpp delete mode 100644 contrib/groff/src/preproc/soelim/soelim.man delete mode 100644 contrib/groff/src/preproc/tbl/Makefile.sub delete mode 100644 contrib/groff/src/preproc/tbl/main.cpp delete mode 100644 contrib/groff/src/preproc/tbl/table.cpp delete mode 100644 contrib/groff/src/preproc/tbl/table.h delete mode 100644 contrib/groff/src/preproc/tbl/tbl.man (limited to 'contrib/groff/src/preproc') diff --git a/contrib/groff/src/preproc/eqn/Makefile.sub b/contrib/groff/src/preproc/eqn/Makefile.sub deleted file mode 100644 index 9028f94c8895..000000000000 --- a/contrib/groff/src/preproc/eqn/Makefile.sub +++ /dev/null @@ -1,60 +0,0 @@ -PROG=eqn$(EXEEXT) -MAN1=eqn.n neqn.n -XLIBS=$(LIBGROFF) -MLIB=$(LIBM) -OBJS=\ - eqn.$(OBJEXT) \ - main.$(OBJEXT) \ - lex.$(OBJEXT) \ - box.$(OBJEXT) \ - limit.$(OBJEXT) \ - list.$(OBJEXT) \ - over.$(OBJEXT) \ - text.$(OBJEXT) \ - script.$(OBJEXT) \ - mark.$(OBJEXT) \ - other.$(OBJEXT) \ - delim.$(OBJEXT) \ - sqrt.$(OBJEXT) \ - pile.$(OBJEXT) \ - special.$(OBJEXT) -CCSRCS=\ - $(srcdir)/main.cpp \ - $(srcdir)/lex.cpp \ - $(srcdir)/box.cpp \ - $(srcdir)/limit.cpp \ - $(srcdir)/list.cpp \ - $(srcdir)/over.cpp \ - $(srcdir)/text.cpp \ - $(srcdir)/script.cpp \ - $(srcdir)/mark.cpp \ - $(srcdir)/other.cpp \ - $(srcdir)/delim.cpp \ - $(srcdir)/sqrt.cpp \ - $(srcdir)/pile.cpp \ - $(srcdir)/special.cpp -HDRS=\ - $(srcdir)/box.h \ - $(srcdir)/eqn.h \ - $(srcdir)/pbox.h -GRAM=$(srcdir)/eqn.y -YTABC=eqn.cpp -YTABH=eqn_tab.h -NAMEPREFIX=$(g) -CLEANADD=neqn - -all: neqn - -neqn: neqn.sh $(SH_DEPS_SED_SCRIPT) - -rm -f $@ - sed -e 's/@g@/$(g)/g' \ - -f $(SH_DEPS_SED_SCRIPT) \ - -e $(SH_SCRIPT_SED_CMD) $(srcdir)/neqn.sh >$@ - chmod +x $@ - -install_data: neqn - -rm -f $(bindir)/$(NAMEPREFIX)neqn - $(INSTALL_SCRIPT) neqn $(bindir)/$(NAMEPREFIX)neqn - -uninstall_sub: - -rm -f $(bindir)/$(NAMEPREFIX)neqn diff --git a/contrib/groff/src/preproc/eqn/TODO b/contrib/groff/src/preproc/eqn/TODO deleted file mode 100644 index 210d0ab06e4d..000000000000 --- a/contrib/groff/src/preproc/eqn/TODO +++ /dev/null @@ -1,49 +0,0 @@ -Use the same size increases for sum prod int as eqn does. - -Perhaps chartype should be renamed. - -TeX makes {sub,super}script on a single character with an accent -into an accent onto the (character with the script). Should we do this? - -Implement mark and lineups within scripts, matrices and piles, and accents. -(Why would this be useful?) - -Perhaps push hmotions down through lists to avoid upsetting spacing -adjustments. - -Possibly generate .lf commands during compute_metrics phase. - -Consider whether there should be extra space at the side of piles. - -Provide scriptstyle displaystyle etc. - -Provide a nicer matrix syntax, eg -matrix ccc { -a then b then c above -e then f then g above -h then i then k -} - -Perhaps generate syntax error messages using the style of gpic. - -Wide accents. - -More use of \Z. - -Extensible square roots. - -Vphantom - -Smash. - -Provide a variant of vec that extends over the length of the accentee. - -Support vertical arrow delimiters. - -Make the following work: -.EQ -delim @@ -.EN -.EQ @<-@ -some equation -.EN diff --git a/contrib/groff/src/preproc/eqn/box.cpp b/contrib/groff/src/preproc/eqn/box.cpp deleted file mode 100644 index 953218a68da0..000000000000 --- a/contrib/groff/src/preproc/eqn/box.cpp +++ /dev/null @@ -1,612 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2002, 2004 - 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "eqn.h" -#include "pbox.h" - -const char *current_roman_font; - -char *gfont = 0; -char *grfont = 0; -char *gbfont = 0; -int gsize = 0; - -int script_size_reduction = -1; // negative means reduce by a percentage - -int positive_space = -1; -int negative_space = -1; - -int minimum_size = 5; - -int fat_offset = 4; -int body_height = 85; -int body_depth = 35; - -int over_hang = 0; -int accent_width = 31; -int delimiter_factor = 900; -int delimiter_shortfall = 50; - -int null_delimiter_space = 12; -int script_space = 5; -int thin_space = 17; -int medium_space = 22; -int thick_space = 28; - -int num1 = 70; -int num2 = 40; -// we don't use num3, because we don't have \atop -int denom1 = 70; -int denom2 = 36; -int axis_height = 26; // in 100ths of an em -int sup1 = 42; -int sup2 = 37; -int sup3 = 28; -int default_rule_thickness = 4; -int sub1 = 20; -int sub2 = 23; -int sup_drop = 38; -int sub_drop = 5; -int x_height = 45; -int big_op_spacing1 = 11; -int big_op_spacing2 = 17; -int big_op_spacing3 = 20; -int big_op_spacing4 = 60; -int big_op_spacing5 = 10; - -// These are for piles and matrices. - -int baseline_sep = 140; // = num1 + denom1 -int shift_down = 26; // = axis_height -int column_sep = 100; // = em space -int matrix_side_sep = 17; // = thin space - -int nroff = 0; // should we grok ndefine or tdefine? - -struct S { - const char *name; - int *ptr; -} param_table[] = { - { "fat_offset", &fat_offset }, - { "over_hang", &over_hang }, - { "accent_width", &accent_width }, - { "delimiter_factor", &delimiter_factor }, - { "delimiter_shortfall", &delimiter_shortfall }, - { "null_delimiter_space", &null_delimiter_space }, - { "script_space", &script_space }, - { "thin_space", &thin_space }, - { "medium_space", &medium_space }, - { "thick_space", &thick_space }, - { "num1", &num1 }, - { "num2", &num2 }, - { "denom1", &denom1 }, - { "denom2", &denom2 }, - { "axis_height", &axis_height }, - { "sup1", ¹ }, - { "sup2", ² }, - { "sup3", ³ }, - { "default_rule_thickness", &default_rule_thickness }, - { "sub1", &sub1 }, - { "sub2", &sub2 }, - { "sup_drop", &sup_drop }, - { "sub_drop", &sub_drop }, - { "x_height", &x_height }, - { "big_op_spacing1", &big_op_spacing1 }, - { "big_op_spacing2", &big_op_spacing2 }, - { "big_op_spacing3", &big_op_spacing3 }, - { "big_op_spacing4", &big_op_spacing4 }, - { "big_op_spacing5", &big_op_spacing5 }, - { "minimum_size", &minimum_size }, - { "baseline_sep", &baseline_sep }, - { "shift_down", &shift_down }, - { "column_sep", &column_sep }, - { "matrix_side_sep", &matrix_side_sep }, - { "draw_lines", &draw_flag }, - { "body_height", &body_height }, - { "body_depth", &body_depth }, - { "nroff", &nroff }, - { 0, 0 } -}; - -void set_param(const char *name, int value) -{ - for (int i = 0; param_table[i].name != 0; i++) - if (strcmp(param_table[i].name, name) == 0) { - *param_table[i].ptr = value; - return; - } - error("unrecognised parameter `%1'", name); -} - -int script_style(int style) -{ - return style > SCRIPT_STYLE ? style - 2 : style; -} - -int cramped_style(int style) -{ - return (style & 1) ? style - 1 : style; -} - -void set_space(int n) -{ - if (n < 0) - negative_space = -n; - else - positive_space = n; -} - -// Return 0 if the specified size is bad. -// The caller is responsible for giving the error message. - -int set_gsize(const char *s) -{ - const char *p = (*s == '+' || *s == '-') ? s + 1 : s; - char *end; - long n = strtol(p, &end, 10); - if (n <= 0 || *end != '\0' || n > INT_MAX) - return 0; - if (p > s) { - if (!gsize) - gsize = 10; - if (*s == '+') { - if (gsize > INT_MAX - n) - return 0; - gsize += int(n); - } - else { - if (gsize - n <= 0) - return 0; - gsize -= int(n); - } - } - else - gsize = int(n); - return 1; -} - -void set_script_reduction(int n) -{ - script_size_reduction = n; -} - -const char *get_gfont() -{ - return gfont ? gfont : "I"; -} - -const char *get_grfont() -{ - return grfont ? grfont : "R"; -} - -const char *get_gbfont() -{ - return gbfont ? gbfont : "B"; -} - -void set_gfont(const char *s) -{ - a_delete gfont; - gfont = strsave(s); -} - -void set_grfont(const char *s) -{ - a_delete grfont; - grfont = strsave(s); -} - -void set_gbfont(const char *s) -{ - a_delete gbfont; - gbfont = strsave(s); -} - -// this must be precisely 2 characters in length -#define COMPATIBLE_REG "0C" - -void start_string() -{ - printf(".nr " COMPATIBLE_REG " \\n(.C\n"); - printf(".cp 0\n"); - printf(".ds " LINE_STRING "\n"); -} - -void output_string() -{ - printf("\\*(" LINE_STRING "\n"); -} - -void restore_compatibility() -{ - printf(".cp \\n(" COMPATIBLE_REG "\n"); -} - -void do_text(const char *s) -{ - printf(".eo\n"); - printf(".as " LINE_STRING " \"%s\n", s); - printf(".ec\n"); -} - -void set_minimum_size(int n) -{ - minimum_size = n; -} - -void set_script_size() -{ - if (minimum_size < 0) - minimum_size = 0; - if (script_size_reduction >= 0) - printf(".ps \\n[.s]-%d>?%d\n", script_size_reduction, minimum_size); - else - printf(".ps (u;\\n[.ps]*7+5/10>?%d)\n", minimum_size); -} - -int box::next_uid = 0; - -box::box() : spacing_type(ORDINARY_TYPE), uid(next_uid++) -{ -} - -box::~box() -{ -} - -void box::top_level() -{ - // debug_print(); - // putc('\n', stderr); - box *b = this; - printf(".nr " SAVED_FONT_REG " \\n[.f]\n"); - printf(".ft\n"); - printf(".nr " SAVED_PREV_FONT_REG " \\n[.f]\n"); - printf(".ft %s\n", get_gfont()); - printf(".nr " SAVED_SIZE_REG " \\n[.ps]\n"); - if (gsize > 0) { - char buf[INT_DIGITS + 1]; - sprintf(buf, "%d", gsize); - b = new size_box(strsave(buf), b); - } - current_roman_font = get_grfont(); - // This catches tabs used within \Z (which aren't allowed). - b->check_tabs(0); - int r = b->compute_metrics(DISPLAY_STYLE); - printf(".ft \\n[" SAVED_PREV_FONT_REG "]\n"); - printf(".ft \\n[" SAVED_FONT_REG "]\n"); - printf(".nr " MARK_OR_LINEUP_FLAG_REG " %d\n", r); - if (r == FOUND_MARK) { - printf(".nr " SAVED_MARK_REG " \\n[" MARK_REG "]\n"); - printf(".nr " MARK_WIDTH_REG " 0\\n[" WIDTH_FORMAT "]\n", b->uid); - } - else if (r == FOUND_LINEUP) - printf(".if r" SAVED_MARK_REG " .as1 " LINE_STRING " \\h'\\n[" - SAVED_MARK_REG "]u-\\n[" MARK_REG "]u'\n"); - else - assert(r == FOUND_NOTHING); - // The problem here is that the argument to \f is read in copy mode, - // so we cannot use \E there; so we hide it in a string instead. - // Another problem is that if we use \R directly, then the space will - // prevent it working in a macro argument. - printf(".ds " SAVE_FONT_STRING " " - "\\R'" SAVED_INLINE_FONT_REG " \\\\n[.f]'" - "\\fP" - "\\R'" SAVED_INLINE_PREV_FONT_REG " \\\\n[.f]'" - "\\R'" SAVED_INLINE_SIZE_REG " \\\\n[.ps]'" - "\\s0" - "\\R'" SAVED_INLINE_PREV_SIZE_REG " \\\\n[.ps]'" - "\n" - ".ds " RESTORE_FONT_STRING " " - "\\f[\\\\n[" SAVED_INLINE_PREV_FONT_REG "]]" - "\\f[\\\\n[" SAVED_INLINE_FONT_REG "]]" - "\\s'\\\\n[" SAVED_INLINE_PREV_SIZE_REG "]u'" - "\\s'\\\\n[" SAVED_INLINE_SIZE_REG "]u'" - "\n"); - printf(".as1 " LINE_STRING " \\&\\E*[" SAVE_FONT_STRING "]"); - printf("\\f[%s]", get_gfont()); - printf("\\s'\\En[" SAVED_SIZE_REG "]u'"); - current_roman_font = get_grfont(); - b->output(); - printf("\\E*[" RESTORE_FONT_STRING "]\n"); - if (r == FOUND_LINEUP) - printf(".if r" SAVED_MARK_REG " .as1 " LINE_STRING " \\h'\\n[" - MARK_WIDTH_REG "]u-\\n[" SAVED_MARK_REG "]u-(\\n[" - WIDTH_FORMAT "]u-\\n[" MARK_REG "]u)'\n", - b->uid); - b->extra_space(); - if (!inline_flag) - printf(".ne \\n[" HEIGHT_FORMAT "]u-%dM>?0+(\\n[" - DEPTH_FORMAT "]u-%dM>?0)\n", - b->uid, body_height, b->uid, body_depth); - delete b; - next_uid = 0; -} - -// gpic defines this register so as to make geqn not produce `\x's -#define EQN_NO_EXTRA_SPACE_REG "0x" - -void box::extra_space() -{ - printf(".if !r" EQN_NO_EXTRA_SPACE_REG " " - ".nr " EQN_NO_EXTRA_SPACE_REG " 0\n"); - if (positive_space >= 0 || negative_space >= 0) { - if (positive_space > 0) - printf(".if !\\n[" EQN_NO_EXTRA_SPACE_REG "] " - ".as1 " LINE_STRING " \\x'-%dM'\n", positive_space); - if (negative_space > 0) - printf(".if !\\n[" EQN_NO_EXTRA_SPACE_REG "] " - ".as1 " LINE_STRING " \\x'%dM'\n", negative_space); - positive_space = negative_space = -1; - } - else { - printf(".if !\\n[" EQN_NO_EXTRA_SPACE_REG "] " - ".if \\n[" HEIGHT_FORMAT "]>%dM .as1 " LINE_STRING - " \\x'-(\\n[" HEIGHT_FORMAT - "]u-%dM)'\n", - uid, body_height, uid, body_height); - printf(".if !\\n[" EQN_NO_EXTRA_SPACE_REG "] " - ".if \\n[" DEPTH_FORMAT "]>%dM .as1 " LINE_STRING - " \\x'\\n[" DEPTH_FORMAT - "]u-%dM'\n", - uid, body_depth, uid, body_depth); - } -} - -int box::compute_metrics(int) -{ - printf(".nr " WIDTH_FORMAT " 0\n", uid); - printf(".nr " HEIGHT_FORMAT " 0\n", uid); - printf(".nr " DEPTH_FORMAT " 0\n", uid); - return FOUND_NOTHING; -} - -void box::compute_subscript_kern() -{ - printf(".nr " SUB_KERN_FORMAT " 0\n", uid); -} - -void box::compute_skew() -{ - printf(".nr " SKEW_FORMAT " 0\n", uid); -} - -void box::output() -{ -} - -void box::check_tabs(int) -{ -} - -int box::is_char() -{ - return 0; -} - -int box::left_is_italic() -{ - return 0; -} - -int box::right_is_italic() -{ - return 0; -} - -void box::hint(unsigned) -{ -} - -void box::handle_char_type(int, int) -{ -} - - -box_list::box_list(box *pp) -{ - p = new box*[10]; - for (int i = 0; i < 10; i++) - p[i] = 0; - maxlen = 10; - len = 1; - p[0] = pp; -} - -void box_list::append(box *pp) -{ - if (len + 1 > maxlen) { - box **oldp = p; - maxlen *= 2; - p = new box*[maxlen]; - memcpy(p, oldp, sizeof(box*)*len); - a_delete oldp; - } - p[len++] = pp; -} - -box_list::~box_list() -{ - for (int i = 0; i < len; i++) - delete p[i]; - a_delete p; -} - -void box_list::list_check_tabs(int level) -{ - for (int i = 0; i < len; i++) - p[i]->check_tabs(level); -} - - -pointer_box::pointer_box(box *pp) : p(pp) -{ - spacing_type = p->spacing_type; -} - -pointer_box::~pointer_box() -{ - delete p; -} - -int pointer_box::compute_metrics(int style) -{ - int r = p->compute_metrics(style); - printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid); - printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid); - printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid); - return r; -} - -void pointer_box::compute_subscript_kern() -{ - p->compute_subscript_kern(); - printf(".nr " SUB_KERN_FORMAT " \\n[" SUB_KERN_FORMAT "]\n", uid, p->uid); -} - -void pointer_box::compute_skew() -{ - p->compute_skew(); - printf(".nr " SKEW_FORMAT " 0\\n[" SKEW_FORMAT "]\n", - uid, p->uid); -} - -void pointer_box::check_tabs(int level) -{ - p->check_tabs(level); -} - -int simple_box::compute_metrics(int) -{ - printf(".nr " WIDTH_FORMAT " 0\\w" DELIMITER_CHAR, uid); - output(); - printf(DELIMITER_CHAR "\n"); - printf(".nr " HEIGHT_FORMAT " 0>?\\n[rst]\n", uid); - printf(".nr " DEPTH_FORMAT " 0-\\n[rsb]>?0\n", uid); - printf(".nr " SUB_KERN_FORMAT " 0-\\n[ssc]>?0\n", uid); - printf(".nr " SKEW_FORMAT " 0\\n[skw]\n", uid); - return FOUND_NOTHING; -} - -void simple_box::compute_subscript_kern() -{ - // do nothing, we already computed it in do_metrics -} - -void simple_box::compute_skew() -{ - // do nothing, we already computed it in do_metrics -} - -int box::is_simple() -{ - return 0; -} - -int simple_box::is_simple() -{ - return 1; -} - -quoted_text_box::quoted_text_box(char *s) : text(s) -{ -} - -quoted_text_box::~quoted_text_box() -{ - a_delete text; -} - -void quoted_text_box::output() -{ - if (text) - fputs(text, stdout); -} - -tab_box::tab_box() : disabled(0) -{ -} - -// We treat a tab_box as having width 0 for width computations. - -void tab_box::output() -{ - if (!disabled) - printf("\\t"); -} - -void tab_box::check_tabs(int level) -{ - if (level > 0) { - error("tabs allowed only at outermost level"); - disabled = 1; - } -} - -space_box::space_box() -{ - spacing_type = SUPPRESS_TYPE; -} - -void space_box::output() -{ - printf("\\h'%dM'", thick_space); -} - -half_space_box::half_space_box() -{ - spacing_type = SUPPRESS_TYPE; -} - -void half_space_box::output() -{ - printf("\\h'%dM'", thin_space); -} - -void box_list::list_debug_print(const char *sep) -{ - p[0]->debug_print(); - for (int i = 1; i < len; i++) { - fprintf(stderr, "%s", sep); - p[i]->debug_print(); - } -} - -void quoted_text_box::debug_print() -{ - fprintf(stderr, "\"%s\"", (text ? text : "")); -} - -void half_space_box::debug_print() -{ - fprintf(stderr, "^"); -} - -void space_box::debug_print() -{ - fprintf(stderr, "~"); -} - -void tab_box::debug_print() -{ - fprintf(stderr, ""); -} diff --git a/contrib/groff/src/preproc/eqn/box.h b/contrib/groff/src/preproc/eqn/box.h deleted file mode 100644 index 94842077039a..000000000000 --- a/contrib/groff/src/preproc/eqn/box.h +++ /dev/null @@ -1,280 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2004, 2005 - 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -class list_box; - -class box { -private: - static int next_uid; -public: - int spacing_type; - const int uid; - box(); - virtual void debug_print() = 0; - virtual ~box(); - void top_level(); - virtual int compute_metrics(int); - virtual void compute_subscript_kern(); - virtual void compute_skew(); - virtual void output(); - void extra_space(); - virtual list_box *to_list_box(); - virtual int is_simple(); - virtual int is_char(); - virtual int left_is_italic(); - virtual int right_is_italic(); - virtual void handle_char_type(int, int); - enum { FOUND_NOTHING = 0, FOUND_MARK = 1, FOUND_LINEUP = 2 }; - void set_spacing_type(char *type); - virtual void hint(unsigned); - virtual void check_tabs(int); -}; - -class box_list { -private: - int maxlen; -public: - box **p; - int len; - - box_list(box *); - ~box_list(); - void append(box *); - void list_check_tabs(int); - void list_debug_print(const char *sep); - friend class list_box; -}; - -// declarations to avoid friend name injection problems -box *make_script_box(box *, box *, box *); -box *make_mark_box(box *); -box *make_lineup_box(box *); - -class list_box : public box { - int is_script; - box_list list; - int sty; -public: - list_box(box *); - void debug_print(); - int compute_metrics(int); - void compute_subscript_kern(); - void output(); - void check_tabs(int); - void append(box *); - list_box *to_list_box(); - void handle_char_type(int, int); - void compute_sublist_width(int n); - friend box *make_script_box(box *, box *, box *); - friend box *make_mark_box(box *); - friend box *make_lineup_box(box *); -}; - -enum alignment { LEFT_ALIGN, RIGHT_ALIGN, CENTER_ALIGN }; - -class column : public box_list { - alignment align; - int space; -public: - column(box *); - void set_alignment(alignment); - void set_space(int); - void debug_print(const char *); - - friend class matrix_box; - friend class pile_box; -}; - -class pile_box : public box { - column col; -public: - pile_box(box *); - int compute_metrics(int); - void output(); - void debug_print(); - void check_tabs(int); - void set_alignment(alignment a) { col.set_alignment(a); } - void set_space(int n) { col.set_space(n); } - void append(box *p) { col.append(p); } -}; - -class matrix_box : public box { -private: - int len; - int maxlen; - column **p; -public: - matrix_box(column *); - ~matrix_box(); - void append(column *); - int compute_metrics(int); - void output(); - void check_tabs(int); - void debug_print(); -}; - -class pointer_box : public box { -protected: - box *p; -public: - pointer_box(box *); - ~pointer_box(); - int compute_metrics(int); - void compute_subscript_kern(); - void compute_skew(); - void debug_print() = 0; - void check_tabs(int); -}; - -class vcenter_box : public pointer_box { -public: - vcenter_box(box *); - int compute_metrics(int); - void output(); - void debug_print(); -}; - -class simple_box : public box { -public: - int compute_metrics(int); - void compute_subscript_kern(); - void compute_skew(); - void output() = 0; - void debug_print() = 0; - int is_simple(); -}; - -class quoted_text_box : public simple_box { - char *text; -public: - quoted_text_box(char *); - ~quoted_text_box(); - void debug_print(); - void output(); -}; - -class half_space_box : public simple_box { -public: - half_space_box(); - void output(); - void debug_print(); -}; - -class space_box : public simple_box { -public: - space_box(); - void output(); - void debug_print(); -}; - -class tab_box : public box { - int disabled; -public: - tab_box(); - void output(); - void debug_print(); - void check_tabs(int); -}; - -class size_box : public pointer_box { -private: - char *size; -public: - size_box(char *, box *); - ~size_box(); - int compute_metrics(int); - void output(); - void debug_print(); -}; - -class font_box : public pointer_box { -private: - char *f; -public: - font_box(char *, box *); - ~font_box(); - int compute_metrics(int); - void output(); - void debug_print(); -}; - -class fat_box : public pointer_box { -public: - fat_box(box *); - int compute_metrics(int); - void output(); - void debug_print(); -}; - -class vmotion_box : public pointer_box { -private: - int n; // up is >= 0 -public: - vmotion_box(int, box *); - int compute_metrics(int); - void output(); - void debug_print(); -}; - -class hmotion_box : public pointer_box { - int n; -public: - hmotion_box(int, box *); - int compute_metrics(int); - void output(); - void debug_print(); -}; - -box *split_text(char *); -box *make_delim_box(char *, box *, char *); -box *make_sqrt_box(box *); -box *make_prime_box(box *); -box *make_over_box(box *, box *); -box *make_small_over_box(box *, box *); -box *make_limit_box(box *, box *, box *); -box *make_accent_box(box *, box *); -box *make_uaccent_box(box *, box *); -box *make_overline_box(box *); -box *make_underline_box(box *); -box *make_special_box(char *, box *); - -void set_space(int); -int set_gsize(const char *); -void set_gfont(const char *); -void set_grfont(const char *); -void set_gbfont(const char *); -const char *get_gfont(); -const char *get_grfont(); -const char *get_gbfont(); -void start_string(); -void output_string(); -void do_text(const char *); -void restore_compatibility(); -void set_script_reduction(int n); -void set_minimum_size(int n); -void set_param(const char *name, int value); - -void set_char_type(const char *type, char *ch); - -void init_char_table(); -void init_extensible(); -void define_extensible(const char *name, const char *ext, const char *top = 0, - const char *mid = 0, const char *bot = 0); diff --git a/contrib/groff/src/preproc/eqn/delim.cpp b/contrib/groff/src/preproc/eqn/delim.cpp deleted file mode 100644 index 9bb7c9b982c4..000000000000 --- a/contrib/groff/src/preproc/eqn/delim.cpp +++ /dev/null @@ -1,401 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2003 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "eqn.h" -#include "pbox.h" - -enum left_or_right_t { LEFT_DELIM = 01, RIGHT_DELIM = 02 }; - -// Small must be none-zero and must exist in each device. -// Small will be put in the roman font, others are assumed to be -// on the special font (so no font change will be necessary.) - -struct delimiter { - const char *name; - int flags; - const char *small; - const char *chain_format; - const char *ext; - const char *top; - const char *mid; - const char *bot; -} delim_table[] = { - { - "(", LEFT_DELIM|RIGHT_DELIM, "(", "\\[parenleft%s]", - "\\[parenleftex]", - "\\[parenlefttp]", - 0, - "\\[parenleftbt]", - }, - { - ")", LEFT_DELIM|RIGHT_DELIM, ")", "\\[parenright%s]", - "\\[parenrightex]", - "\\[parenrighttp]", - 0, - "\\[parenrightbt]", - }, - { - "[", LEFT_DELIM|RIGHT_DELIM, "[", "\\[bracketleft%s]", - "\\[bracketleftex]", - "\\[bracketlefttp]", - 0, - "\\[bracketleftbt]", - }, - { - "]", LEFT_DELIM|RIGHT_DELIM, "]", "\\[bracketright%s]", - "\\[bracketrightex]", - "\\[bracketrighttp]", - 0, - "\\[bracketrightbt]", - }, - { - "{", LEFT_DELIM|RIGHT_DELIM, "{", "\\[braceleft%s]", - "\\[braceleftex]", - "\\[bracelefttp]", - "\\[braceleftmid]", - "\\[braceleftbt]", - }, - { - "}", LEFT_DELIM|RIGHT_DELIM, "}", "\\[braceright%s]", - "\\[bracerightex]", - "\\[bracerighttp]", - "\\[bracerightmid]", - "\\[bracerightbt]", - }, - { - "|", LEFT_DELIM|RIGHT_DELIM, "|", "\\[bar%s]", - "\\[barex]", - 0, - 0, - 0, - }, - { - "floor", LEFT_DELIM, "\\(lf", "\\[floorleft%s]", - "\\[bracketleftex]", - 0, - 0, - "\\[bracketleftbt]", - }, - { - "floor", RIGHT_DELIM, "\\(rf", "\\[floorright%s]", - "\\[bracketrightex]", - 0, - 0, - "\\[bracketrightbt]", - }, - { - "ceiling", LEFT_DELIM, "\\(lc", "\\[ceilingleft%s]", - "\\[bracketleftex]", - "\\[bracketlefttp]", - 0, - 0, - }, - { - "ceiling", RIGHT_DELIM, "\\(rc", "\\[ceilingright%s]", - "\\[bracketrightex]", - "\\[bracketrighttp]", - 0, - 0, - }, - { - "||", LEFT_DELIM|RIGHT_DELIM, "|", "\\[bar%s]", - "\\[bardblex]", - 0, - 0, - 0, - }, - { - "<", LEFT_DELIM|RIGHT_DELIM, "\\(la", "\\[angleleft%s]", - 0, - 0, - 0, - 0, - }, - { - ">", LEFT_DELIM|RIGHT_DELIM, "\\(ra", "\\[angleright%s]", - 0, - 0, - 0, - 0, - }, - { - "uparrow", LEFT_DELIM|RIGHT_DELIM, "\\(ua", "\\[arrowup%s]", - "\\[arrowvertex]", - "\\[arrowverttp]", - 0, - 0, - }, - { - "downarrow", LEFT_DELIM|RIGHT_DELIM, "\\(da", "\\[arrowdown%s]", - "\\[arrowvertex]", - 0, - 0, - "\\[arrowvertbt]", - }, - { - "updownarrow", LEFT_DELIM|RIGHT_DELIM, "\\(va", "\\[arrowupdown%s]", - "\\[arrowvertex]", - "\\[arrowverttp]", - 0, - "\\[arrowvertbt]", - }, -}; - -const int DELIM_TABLE_SIZE = int(sizeof(delim_table)/sizeof(delim_table[0])); - -class delim_box : public box { -private: - char *left; - char *right; - box *p; -public: - delim_box(char *, box *, char *); - ~delim_box(); - int compute_metrics(int); - void output(); - void check_tabs(int); - void debug_print(); -}; - -box *make_delim_box(char *l, box *pp, char *r) -{ - if (l != 0 && *l == '\0') { - a_delete l; - l = 0; - } - if (r != 0 && *r == '\0') { - a_delete r; - r = 0; - } - return new delim_box(l, pp, r); -} - -delim_box::delim_box(char *l, box *pp, char *r) -: left(l), right(r), p(pp) -{ -} - -delim_box::~delim_box() -{ - a_delete left; - a_delete right; - delete p; -} - -static void build_extensible(const char *ext, const char *top, const char *mid, - const char *bot) -{ - assert(ext != 0); - printf(".nr " DELIM_WIDTH_REG " 0\\w" DELIMITER_CHAR "%s" DELIMITER_CHAR "\n", - ext); - printf(".nr " EXT_HEIGHT_REG " 0\\n[rst]\n"); - printf(".nr " EXT_DEPTH_REG " 0-\\n[rsb]\n"); - if (top) { - printf(".nr " DELIM_WIDTH_REG " 0\\n[" DELIM_WIDTH_REG "]" - ">?\\w" DELIMITER_CHAR "%s" DELIMITER_CHAR "\n", - top); - printf(".nr " TOP_HEIGHT_REG " 0\\n[rst]\n"); - printf(".nr " TOP_DEPTH_REG " 0-\\n[rsb]\n"); - } - if (mid) { - printf(".nr " DELIM_WIDTH_REG " 0\\n[" DELIM_WIDTH_REG "]" - ">?\\w" DELIMITER_CHAR "%s" DELIMITER_CHAR "\n", - mid); - printf(".nr " MID_HEIGHT_REG " 0\\n[rst]\n"); - printf(".nr " MID_DEPTH_REG " 0-\\n[rsb]\n"); - } - if (bot) { - printf(".nr " DELIM_WIDTH_REG " 0\\n[" DELIM_WIDTH_REG "]" - ">?\\w" DELIMITER_CHAR "%s" DELIMITER_CHAR "\n", - bot); - printf(".nr " BOT_HEIGHT_REG " 0\\n[rst]\n"); - printf(".nr " BOT_DEPTH_REG " 0-\\n[rsb]\n"); - } - printf(".nr " TOTAL_HEIGHT_REG " 0"); - if (top) - printf("+\\n[" TOP_HEIGHT_REG "]+\\n[" TOP_DEPTH_REG "]"); - if (bot) - printf("+\\n[" BOT_HEIGHT_REG "]+\\n[" BOT_DEPTH_REG "]"); - if (mid) - printf("+\\n[" MID_HEIGHT_REG "]+\\n[" MID_DEPTH_REG "]"); - printf("\n"); - // determine how many extensible characters we need - printf(".nr " TEMP_REG " \\n[" DELTA_REG "]-\\n[" TOTAL_HEIGHT_REG "]"); - if (mid) - printf("/2"); - printf(">?0+\\n[" EXT_HEIGHT_REG "]+\\n[" EXT_DEPTH_REG "]-1/(\\n[" - EXT_HEIGHT_REG "]+\\n[" EXT_DEPTH_REG "])\n"); - - printf(".nr " TOTAL_HEIGHT_REG " +(\\n[" EXT_HEIGHT_REG "]+\\n[" - EXT_DEPTH_REG "]*\\n[" TEMP_REG "]"); - if (mid) - printf("*2"); - printf(")\n"); - printf(".ds " DELIM_STRING " \\Z" DELIMITER_CHAR - "\\v'-%dM-(\\n[" TOTAL_HEIGHT_REG "]u/2u)'\n", - axis_height); - if (top) - printf(".as " DELIM_STRING " \\v'\\n[" TOP_HEIGHT_REG "]u'" - "\\Z" DELIMITER_CHAR "%s" DELIMITER_CHAR - "\\v'\\n[" TOP_DEPTH_REG "]u'\n", - top); - - // this macro appends $2 copies of $3 to string $1 - printf(".de " REPEAT_APPEND_STRING_MACRO "\n" - ".if \\\\$2 \\{.as \\\\$1 \"\\\\$3\n" - "." REPEAT_APPEND_STRING_MACRO " \\\\$1 \\\\$2-1 \"\\\\$3\"\n" - ".\\}\n" - "..\n"); - - printf("." REPEAT_APPEND_STRING_MACRO " " DELIM_STRING " \\n[" TEMP_REG "] " - "\\v'\\n[" EXT_HEIGHT_REG "]u'" - "\\Z" DELIMITER_CHAR "%s" DELIMITER_CHAR - "\\v'\\n[" EXT_DEPTH_REG "]u'\n", - ext); - - if (mid) { - printf(".as " DELIM_STRING " \\v'\\n[" MID_HEIGHT_REG "]u'" - "\\Z" DELIMITER_CHAR "%s" DELIMITER_CHAR - "\\v'\\n[" MID_DEPTH_REG "]u'\n", - mid); - printf("." REPEAT_APPEND_STRING_MACRO " " DELIM_STRING - " \\n[" TEMP_REG "] " - "\\v'\\n[" EXT_HEIGHT_REG "]u'" - "\\Z" DELIMITER_CHAR "%s" DELIMITER_CHAR - "\\v'\\n[" EXT_DEPTH_REG "]u'\n", - ext); - } - if (bot) - printf(".as " DELIM_STRING " \\v'\\n[" BOT_HEIGHT_REG "]u'" - "\\Z" DELIMITER_CHAR "%s" DELIMITER_CHAR - "\\v'\\n[" BOT_DEPTH_REG "]u'\n", - bot); - printf(".as " DELIM_STRING " " DELIMITER_CHAR "\n"); -} - -static void define_extensible_string(char *delim, int uid, - left_or_right_t left_or_right) -{ - printf(".ds " DELIM_STRING "\n"); - delimiter *d = delim_table; - int delim_len = strlen(delim); - int i; - for (i = 0; i < DELIM_TABLE_SIZE; i++, d++) - if (strncmp(delim, d->name, delim_len) == 0 - && (left_or_right & d->flags) != 0) - break; - if (i >= DELIM_TABLE_SIZE) { - error("there is no `%1' delimiter", delim); - printf(".nr " DELIM_WIDTH_REG " 0\n"); - return; - } - - printf(".nr " DELIM_WIDTH_REG " 0\\w" DELIMITER_CHAR "\\f[%s]%s\\fP" DELIMITER_CHAR "\n" - ".ds " DELIM_STRING " \\Z" DELIMITER_CHAR - "\\v'\\n[rsb]u+\\n[rst]u/2u-%dM'\\f[%s]%s\\fP" DELIMITER_CHAR "\n" - ".nr " TOTAL_HEIGHT_REG " \\n[rst]-\\n[rsb]\n" - ".if \\n[" TOTAL_HEIGHT_REG "]<\\n[" DELTA_REG "] " - "\\{", - current_roman_font, d->small, axis_height, - current_roman_font, d->small); - - char buf[256]; - sprintf(buf, d->chain_format, "\\\\n[" INDEX_REG "]"); - printf(".nr " INDEX_REG " 0\n" - ".de " TEMP_MACRO "\n" - ".ie c%s \\{\\\n" - ".nr " DELIM_WIDTH_REG " 0\\w" DELIMITER_CHAR "%s" DELIMITER_CHAR "\n" - ".ds " DELIM_STRING " \\Z" DELIMITER_CHAR - "\\v'\\\\n[rsb]u+\\\\n[rst]u/2u-%dM'%s" DELIMITER_CHAR "\n" - ".nr " TOTAL_HEIGHT_REG " \\\\n[rst]-\\\\n[rsb]\n" - ".if \\\\n[" TOTAL_HEIGHT_REG "]<\\n[" DELTA_REG "] " - "\\{.nr " INDEX_REG " +1\n" - "." TEMP_MACRO "\n" - ".\\}\\}\n" - ".el .nr " INDEX_REG " 0-1\n" - "..\n" - "." TEMP_MACRO "\n", - buf, buf, axis_height, buf); - if (d->ext) { - printf(".if \\n[" INDEX_REG "]<0 \\{.if c%s \\{\\\n", d->ext); - build_extensible(d->ext, d->top, d->mid, d->bot); - printf(".\\}\\}\n"); - } - printf(".\\}\n"); - printf(".as " DELIM_STRING " \\h'\\n[" DELIM_WIDTH_REG "]u'\n"); - printf(".nr " WIDTH_FORMAT " +\\n[" DELIM_WIDTH_REG "]\n", uid); - printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]" - ">?(\\n[" TOTAL_HEIGHT_REG "]/2+%dM)\n", - uid, uid, axis_height); - printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]" - ">?(\\n[" TOTAL_HEIGHT_REG "]/2-%dM)\n", - uid, uid, axis_height); -} - -int delim_box::compute_metrics(int style) -{ - int r = p->compute_metrics(style); - printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid); - printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid); - printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid); - printf(".nr " DELTA_REG " \\n[" HEIGHT_FORMAT "]-%dM" - ">?(\\n[" DEPTH_FORMAT "]+%dM)\n", - p->uid, axis_height, p->uid, axis_height); - printf(".nr " DELTA_REG " 0\\n[" DELTA_REG "]*%d/500" - ">?(\\n[" DELTA_REG "]*2-%dM)\n", - delimiter_factor, delimiter_shortfall); - if (left) { - define_extensible_string(left, uid, LEFT_DELIM); - printf(".rn " DELIM_STRING " " LEFT_DELIM_STRING_FORMAT "\n", - uid); - if (r) - printf(".nr " MARK_REG " +\\n[" DELIM_WIDTH_REG "]\n"); - } - if (right) { - define_extensible_string(right, uid, RIGHT_DELIM); - printf(".rn " DELIM_STRING " " RIGHT_DELIM_STRING_FORMAT "\n", - uid); - } - return r; -} - -void delim_box::output() -{ - if (left) - printf("\\*[" LEFT_DELIM_STRING_FORMAT "]", uid); - p->output(); - if (right) - printf("\\*[" RIGHT_DELIM_STRING_FORMAT "]", uid); -} - -void delim_box::check_tabs(int level) -{ - p->check_tabs(level); -} - -void delim_box::debug_print() -{ - fprintf(stderr, "left \"%s\" { ", left ? left : ""); - p->debug_print(); - fprintf(stderr, " }"); - if (right) - fprintf(stderr, " right \"%s\"", right); -} - diff --git a/contrib/groff/src/preproc/eqn/eqn.h b/contrib/groff/src/preproc/eqn/eqn.h deleted file mode 100644 index fca3e9793a38..000000000000 --- a/contrib/groff/src/preproc/eqn/eqn.h +++ /dev/null @@ -1,50 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2001 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "lib.h" - -#include -#include -#include -#include "cset.h" -#include "errarg.h" -#include "error.h" - -#include "box.h" - -extern char start_delim; -extern char end_delim; -extern int non_empty_flag; -extern int inline_flag; -extern int draw_flag; -extern int one_size_reduction_flag; -extern int compatible_flag; -extern int nroff; - -void init_lex(const char *str, const char *filename, int lineno); -void lex_error(const char *message, - const errarg &arg1 = empty_errarg, - const errarg &arg2 = empty_errarg, - const errarg &arg3 = empty_errarg); - -void init_table(const char *device); - -// prefix for all registers, strings, macros -#define PREFIX "0" diff --git a/contrib/groff/src/preproc/eqn/eqn.man b/contrib/groff/src/preproc/eqn/eqn.man deleted file mode 100644 index 0f47771c2392..000000000000 --- a/contrib/groff/src/preproc/eqn/eqn.man +++ /dev/null @@ -1,1160 +0,0 @@ -.ig -Copyright (C) 1989-2000, 2001, 2004, 2005 Free Software Foundation, Inc. - -Permission is granted to make and distribute verbatim copies of -this manual provided the copyright notice and this permission notice -are preserved on all copies. - -Permission is granted to copy and distribute modified versions of this -manual under the conditions for verbatim copying, provided that the -entire resulting derived work is distributed under the terms of a -permission notice identical to this one. - -Permission is granted to copy and distribute translations of this -manual into another language, under the above conditions for modified -versions, except that this permission notice may be included in -translations approved by the Free Software Foundation instead of in -the original English. -.. -. -. -.ie \n(.V<\n(.v \ -. 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" -.. -. -. -.de TQ -. br -. ns -. TP \\$1 -.. -. -. -.\" The BSD man macros can't handle " in arguments to font change macros, -.\" so use \(ts instead of ". -.tr \(ts" -. -. -.TH @G@EQN @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@" -. -. -.SH NAME -@g@eqn \- format equations for troff -. -. -.SH SYNOPSIS -.nr a \n(.j -.ad l -.nr i \n(.i -.in +\w'\fB@g@eqn 'u -.ti \niu -.B @g@eqn -.de OP -. ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]" -. el .RB "[\ " "\\$1" "\ ]" -.. -.OP \-rvCNR -.OP \-d xy -.OP \-T name -.OP \-M dir -.OP \-f F -.OP \-s n -.OP \-p n -.OP \-m n -.RI "[\ " files\|.\|.\|. "\ ]" -.br -.ad \na -. -.LP -It is possible to have whitespace between a command line option and its -parameter. -. -. -.SH DESCRIPTION -This manual page describes the GNU version of -.BR eqn , -which is part of the groff document formatting system. -.B eqn -compiles descriptions of equations embedded within -.B troff -input files into commands that are understood by -.BR troff . -Normally, it should be invoked using the -.B \-e -option of -.BR groff . -The syntax is quite compatible with Unix eqn. -The output of GNU -.B eqn -cannot be processed with Unix troff; -it must be processed with GNU troff. -If no files are given on the command line, the standard input -will be read. -A filename of -.B \- -will cause the standard input to be read. -. -.LP -.B eqn -searches for the file -.B eqnrc -in the directories given with the -.B \-M -option first, then in -.BR @SYSTEMMACRODIR@ , -.BR @LOCALMACRODIR@ , -and finally in the standard macro directory -.BR @MACRODIR@ . -If it exists, -.B eqn -will process it before the other input files. -The -.B \-R -option prevents this. -. -.LP -GNU -.B eqn -does not provide the functionality of neqn: -it does not support low-resolution, typewriter-like devices -(although it may work adequately for very simple input). -. -. -.SH OPTIONS -.TP -.BI \-d xy -Specify delimiters -.I x -and\~\c -.I y -for the left and right end, respectively, of in-line equations. -Any -.B delim -statements in the source file overrides this. -. -.TP -.B \-C -Recognize -.B .EQ -and -.B .EN -even when followed by a character other than space or newline. -.TP -.B \-N -Don't allow newlines within delimiters. -This option allows -.B eqn -to recover better from missing closing delimiters. -. -.TP -.B \-v -Print the version number. -. -.TP -.B \-r -Only one size reduction. -. -.TP -.BI \-m n -The minimum point-size is\~\c -.IR n . -.B eqn -will not reduce the size of subscripts or superscripts to -a smaller size than\~\c -.IR n . -. -.TP -.BI \-T name -The output is for device -.IR name . -The only effect of this is to define a macro -.I name -with a value of\~\c -.BR 1 . -Typically -.B eqnrc -will use this to provide definitions appropriate for the output device. -The default output device is -.BR @DEVICE@ . -. -.TP -.BI \-M dir -Search -.I dir -for -.B eqnrc -before the default directories. -. -.TP -.B \-R -Don't load -.BR eqnrc . -. -.TP -.BI \-f F -This is equivalent to a -.BI gfont\ F -command. -. -.TP -.BI \-s n -This is equivalent to a -.BI gsize\ n -command. -This option is deprecated. -.B eqn -will normally set equations at whatever the current point size -is when the equation is encountered. -. -.TP -.BI \-p n -This says that subscripts and superscripts should be -.I n\~\c -points smaller than the surrounding text. -This option is deprecated. -Normally -.B eqn -makes sets subscripts and superscripts at 70% -of the size of the surrounding text. -. -. -.SH USAGE -Only the differences between GNU -.B eqn -and Unix eqn are described here. -. -.LP -Most of the new features of GNU -.B eqn -are based on \*(tx. -There are some references to the differences between \*(tx and GNU -.B eqn -below; -these may safely be ignored if you do not know \*(tx. -. -.SS Automatic spacing -.B eqn -gives each component of an equation a type, and adjusts the spacing -between components using that type. -Possible types are: -. -.RS -.TP \w'punctuation'u+2n -ordinary -an ordinary character such as `1' or `\c -.IR x '; -. -.TP -operator -a large operator such as -.ds Su `\s+5\(*S\s0' -.if \n(.g .if !c\(*S .ds Su the summation operator -\*(Su; -. -.TP -binary -a binary operator such as `\(pl'; -. -.TP -relation -a relation such as `='; -. -.TP -opening -a opening bracket such as `('; -. -.TP -closing -a closing bracket such as `)'; -. -.TP -punctuation -a punctuation character such as `,'; -. -.TP -inner -a subformula contained within brackets; -.TP -suppress -spacing that suppresses automatic spacing adjustment. -.RE -. -.LP -Components of an equation get a type in one of two ways. -. -.TP -.BI type\ t\ e -This yields an equation component that contains\~\c -.I e -but that has type\~\c -.IR t , -where -.I t -is one of the types mentioned above. -For example, -.B times -is defined as -. -.RS -.IP -.B -type "binary" \e(mu -.RE -. -.IP -The name of the type doesn't have to be quoted, but quoting protects -from macro expansion. -. -.TP -.BI chartype\ t\ text -Unquoted groups of characters are split up into individual characters, -and the type of each character is looked up; -this changes the type that is stored for each character; -it says that the characters in -.I text -from now on have type\~\c -.IR t . -For example, -. -.RS -.IP -.B -chartype "punctuation" .,;: -.RE -. -.IP -would make the characters `.,;:' have type punctuation -whenever they subsequently appeared in an equation. -The type\~\c -.I t -can also be -.B letter -or -.BR digit ; -in these cases -.B chartype -changes the font type of the characters. -See the -.B Fonts -subsection. -. -.SS New primitives -.TP -.IB e1\ smallover\ e2 -This is similar to -.BR over ; -.B smallover -reduces the size of -.I e1 -and -.IR e2 ; -it also puts less vertical space between -.I e1 -or -.I e2 -and the fraction bar. -The -.B over -primitive corresponds to the \*(tx -.B \eover -primitive in display styles; -.B smallover -corresponds to -.B \eover -in non-display styles. -. -.TP -.BI vcenter\ e -This vertically centers -.I e -about the math axis. -The math axis is the vertical position about which characters -such as `\(pl' and `\(mi' are centered; also it is the vertical position -used for the bar of fractions. -For example, -.B sum -is defined as -. -.RS -.IP -.B -{ type "operator" vcenter size +5 \e(*S } -.RE -. -.TP -.IB e1\ accent\ e2 -This sets -.I e2 -as an accent over -.IR e1 . -.I e2 -is assumed to be at the correct height for a lowercase letter; -.I e2 -will be moved down according if -.I e1 -is taller or shorter than a lowercase letter. -For example, -.B hat -is defined as -. -.RS -.IP -.B -accent { "^" } -.RE -. -.IP -.BR dotdot , -.BR dot , -.BR tilde , -.BR vec , -and -.B dyad -are also defined using the -.B accent -primitive. -. -.TP -.IB e1\ uaccent\ e2 -This sets -.I e2 -as an accent under -.IR e1 . -.I e2 -is assumed to be at the correct height for a character without a descender; -.I e2 -will be moved down if -.I e1 -has a descender. -.B utilde -is pre-defined using -.B uaccent -as a tilde accent below the baseline. -. -.TP -.BI split\ \(ts text \(ts -This has the same effect as simply -. -.RS -.IP -.I text -.RE -. -.IP -but -.I text -is not subject to macro expansion because it is quoted; -.I text -will be split up and the spacing between individual characters -will be adjusted. -. -.TP -.BI nosplit\ text -This has the same effect as -. -.RS -.IP -.BI \(ts text \(ts -.RE -. -.IP -but because -.I text -is not quoted it will be subject to macro expansion; -.I text -will not be split up -and the spacing between individual characters will not be adjusted. -. -.TP -.IB e\ opprime -This is a variant of -.B prime -that acts as an operator on\~\c -.IR e . -It produces a different result from -.B prime -in a case such as -.BR A\ opprime\ sub\ 1 : -with -.B opprime -the\~\c -.B 1 -will be tucked under the prime as a subscript to the\~\c -.B A -(as is conventional in mathematical typesetting), -whereas with -.B prime -the\~\c -.B 1 -will be a subscript to the prime character. -The precedence of -.B opprime -is the same as that of -.B bar -and -.BR under , -which is higher than that of everything except -.B accent -and -.BR uaccent . -In unquoted text a\~\c -.B ' -that is not the first character will be treated like -.BR opprime . -. -.TP -.BI special\ text\ e -This constructs a new object from\~\c -.I e -using a -.BR @g@troff (@MAN1EXT@) -macro named -.IR text . -When the macro is called, -the string -.B 0s -will contain the output for\~\c -.IR e , -and the number registers -.BR 0w , -.BR 0h , -.BR 0d , -.BR 0skern , -and -.BR 0skew -will contain the width, height, depth, subscript kern, and skew of\~\c -.IR e . -(The -.I "subscript kern" -of an object says how much a subscript on that object should be tucked in; -the -.I skew -of an object says how far to the right of the center of the object an -accent over the object should be placed.) -The macro must modify -.B 0s -so that it will output the desired result with its origin at the current -point, and increase the current horizontal position by the width -of the object. -The number registers must also be modified so that they correspond to the -result. -. -.IP -For example, suppose you wanted a construct that `cancels' an expression -by drawing a diagonal line through it. -. -.RS -.IP -.ft B -.if t .ne 6+\n(.Vu -.br -\&.EQ -.br -define cancel 'special Ca' -.br -\&.EN -.br -\&.de Ca -.br -\&.\ \ ds 0s \e -.br -\eZ'\e\e*(0s'\e -.br -\ev'\e\en(0du'\e -.br -\eD'l \e\en(0wu -\e\en(0hu-\e\en(0du'\e -.br -\ev'\e\en(0hu' -.br -\&.. -.ft -.RE -. -.IP -Then you could cancel an expression\~\c -.I e -with -.BI \%cancel\ {\ e\ } -. -.IP -Here's a more complicated construct that draws a box round an expression: -. -.RS -.IP -.ft B -.if t .ne 11+\n(.Vu -\&.EQ -.br -define box 'special Bx' -.br -\&.EN -.br -\&.de Bx -.br -\&.\ \ ds 0s \e -.br -\eZ'\eh'1n'\e\e*(0s'\e -.br -\eZ'\e -.br -\ev'\e\en(0du+1n'\e -.br -\eD'l \e\en(0wu+2n 0'\e -.br -\eD'l 0 -\e\en(0hu-\e\en(0du-2n'\e -.br -\eD'l -\e\en(0wu-2n 0'\e -.br -\eD'l 0 \e\en(0hu+\e\en(0du+2n'\e -.br -\&'\e -.br -\eh'\e\en(0wu+2n' -.br -\&.\ \ nr 0w +2n -.br -\&.\ \ nr 0d +1n -.br -\&.\ \ nr 0h +1n -.br -\&.. -.ft -.RE -. -.TP -.BI space\ n -A positive value of the integer\~\c -.I n -(in hundredths of an em) sets the vertical spacing before the equation, -a negative value sets the spacing after the equation, replacing the -default values. -This primitive provides an interface to -.BR groff 's -.B \ex -escape (but with opposite sign). -. -.IP -This keyword has no effect if the equation is part of a -.B pic -picture. -. -.SS Extended primitives -.TP -.BI col\ n\ {\ .\|.\|.\ } -.TQ -.BI ccol\ n\ {\ .\|.\|.\ } -.TQ -.BI lcol\ n\ {\ .\|.\|.\ } -.TQ -.BI rcol\ n\ {\ .\|.\|.\ } -.TQ -.BI pile\ n\ {\ .\|.\|.\ } -.TQ -.BI cpile\ n\ {\ .\|.\|.\ } -.TQ -.BI lpile\ n\ {\ .\|.\|.\ } -.TQ -.BI rpile\ n\ {\ .\|.\|.\ } -The integer value\~\c -.I n -(in hundredths of an em) increases the vertical spacing between rows, -using -.BR groff 's -.B \ex -escape. -Negative values are possible but have no effect. -If there is more than a single value given in a matrix, the biggest one -is used. -. -.SS Customization -The appearance of equations is controlled by a large number of parameters. -These can be set using -the -.B set -command. -. -.TP -.BI set\ p\ n -This sets parameter\~\c -.I p -to value\~\c -.IR n ; -.I n\~\c -is an integer. -For example, -. -.RS -.IP -.B -set x_height 45 -.RE -. -.IP -says that -.B eqn -should assume an x\~height of 0.45\~ems. -. -.RS -.LP -Possible parameters are as follows. -Values are in units of hundredths of an em unless otherwise stated. -These descriptions are intended to be expository rather than -definitive. -. -.ie t \ -. TP \w'\fBdefault_rule_thickness'u+2n -.el \ -. TP -.B minimum_size -.B eqn -will not set anything at a smaller point-size than this. -The value is in points. -. -.TP -.B fat_offset -The -.B fat -primitive emboldens an equation -by overprinting two copies of the equation -horizontally offset by this amount. -. -.TP -.B over_hang -A fraction bar will be longer by twice this amount than -the maximum of the widths of the numerator and denominator; -in other words, it will overhang the numerator and -denominator by at least this amount. -. -.TP -.B accent_width -When -.B bar -or -.B under -is applied to a single character, -the line will be this long. -Normally, -.B bar -or -.B under -produces a line whose length is the width of the object to which it applies; -in the case of a single character, -this tends to produce a line that looks too long. -. -.TP -.B delimiter_factor -Extensible delimiters produced with the -.B left -and -.B right -primitives will have a combined height and depth of at least this many -thousandths of twice the maximum amount by which the sub-equation that -the delimiters enclose extends away from the axis. -. -.TP -.B delimiter_shortfall -Extensible delimiters produced with the -.B left -and -.B right -primitives will have a combined height and depth -not less than the difference of -twice the maximum amount by which the sub-equation that -the delimiters enclose extends away from the axis -and this amount. -. -.TP -.B null_delimiter_space -This much horizontal space is inserted -on each side of a fraction. -. -.TP -.B script_space -The width of subscripts and superscripts is increased by this amount. -. -.TP -.B thin_space -This amount of space is automatically inserted after punctuation -characters. -. -.TP -.B medium_space -This amount of space is automatically inserted on either side -of binary operators. -. -.TP -.B thick_space -This amount of space is automatically inserted on either side of -relations. -. -.TP -.B x_height -The height of lowercase letters without ascenders such as `x'. -. -.TP -.B axis_height -The height above the baseline of the center of characters -such as `\(pl' and `\(mi'. -It is important that this value is correct for the font -you are using. -. -.TP -.B default_rule_thickness -This should set to the thickness of the -.B \e(ru -character, or the thickness of horizontal lines produced with the -.B \eD -escape sequence. -. -.TP -.B num1 -The -.B over -command will shift up the numerator by at least this amount. -. -.TP -.B num2 -The -.B smallover -command will shift up the numerator by at least this amount. -. -.TP -.B denom1 -The -.B over -command will shift down the denominator by at least this amount. -. -.TP -.B denom2 -The -.B smallover -command will shift down the denominator by at least this amount. -. -.TP -.B sup1 -Normally superscripts will be shifted up by at least this amount. -. -.TP -.B sup2 -Superscripts within superscripts or upper limits -or numerators of -.B smallover -fractions -will be shifted up by at least this amount. -This is usually less than sup1. -. -.TP -.B sup3 -Superscripts within denominators or square roots -or subscripts or lower limits will be shifted up by at least -this amount. -This is usually less than sup2. -. -.TP -.B sub1 -Subscripts will normally be shifted down by at least this amount. -. -.TP -.B sub2 -When there is both a subscript and a superscript, the subscript -will be shifted down by at least this amount. -. -.TP -.B sup_drop -The baseline of a superscript will be no more -than this much amount below the top of the object on -which the superscript is set. -. -.TP -.B sub_drop -The baseline of a subscript will be at least this much below -the bottom of the object on which the subscript is set. -. -.TP -.B big_op_spacing1 -The baseline of an upper limit will be at least this -much above the top of the object on which the limit is set. -. -.TP -.B big_op_spacing2 -The baseline of a lower limit will be at least this -much below the bottom of the object on which the limit is set. -. -.TP -.B big_op_spacing3 -The bottom of an upper limit will be at least this much above the -top of the object on which the limit is set. -. -.TP -.B big_op_spacing4 -The top of a lower limit will be at least this much below -the bottom of the object on which the limit is set. -. -.TP -.B big_op_spacing5 -This much vertical space will be added above and below limits. -. -.TP -.B baseline_sep -The baselines of the rows in a pile or matrix will normally be -this far apart. -In most cases this should be equal to the sum of -.B num1 -and -.BR denom1 . -. -.TP -.B shift_down -The midpoint between the top baseline and the bottom baseline -in a matrix or pile will be shifted down by this much from the axis. -In most cases this should be equal to -.BR axis_height . -. -.TP -.B column_sep -This much space will be added between columns in a matrix. -. -.TP -.B matrix_side_sep -This much space will be added at each side of a matrix. -. -.TP -.B draw_lines -If this is non-zero, lines will be drawn using the -.B \eD -escape sequence, rather than with the -.B \el -escape sequence and the -.B \e(ru -character. -. -.TP -.B body_height -The amount by which the height of the equation exceeds this -will be added as extra space before the line containing the equation -(using -.BR \ex ). -The default value is 85. -. -.TP -.B body_depth -The amount by which the depth of the equation exceeds this -will be added as extra space after the line containing the equation -(using -.BR \ex ). -The default value is 35. -. -.TP -.B nroff -If this is non-zero, -then -.B ndefine -will behave like -.B define -and -.B tdefine -will be ignored, -otherwise -.B tdefine -will behave like -.B define -and -.B ndefine -will be ignored. -The default value is\~0 -(This is typically changed to\~1 by the -.B eqnrc -file for the -.BR ascii , -.BR latin1 , -.BR utf8 , -and -.B cp1047 -devices.) -. -.LP -A more precise description of the role of many of these -parameters can be found in Appendix\~H of -.IR "The \*(txbook" . -.RE -. -.SS Macros -Macros can take arguments. -In a macro body, -.BI $ n -where -.I n -is between 1 and\~9, -will be replaced by the -.IR n-th -argument if the macro is called with arguments; -if there are fewer than -.I n\~\c -arguments, it will be replaced by nothing. -A word containing a left parenthesis where the part of the word -before the left parenthesis has been defined using the -.B define -command -will be recognized as a macro call with arguments; -characters following the left parenthesis -up to a matching right parenthesis will be treated as comma-separated -arguments; -commas inside nested parentheses do not terminate an argument. -. -.TP -.BI sdefine\ name\ X\ anything\ X -This is like the -.B define -command, but -.I name -will not be recognized if called with arguments. -. -.TP -.BI include\ \(ts file \(ts -.TQ -.BI copy\ \(ts file \(ts -Include the contents of -.I file -.RB ( include -and -.B copy -are synonyms). -Lines of -.I file -beginning with -.B .EQ -or -.B .EN -will be ignored. -. -.TP -.BI ifdef\ name\ X\ anything\ X -If -.I name -has been defined by -.B define -(or has been automatically defined because -.I name -is the output device) -process -.IR anything ; -otherwise ignore -.IR anything . -.I X -can be any character not appearing in -.IR anything . -. -.TP -.BI undef\ name -Remove definition of -.IR name , -making it undefined. -. -.LP -Besides the macros mentioned above, the following definitions are available: -.BR Alpha , -.BR Beta , -\&.\|.\|., -.B Omega -(this is the same as -.BR ALPHA , -.BR BETA , -\&.\|.\|., -.BR OMEGA ), -.B ldots -(three dots on the base line), -and -.BR dollar . -. -.SS Fonts -.B eqn -normally uses at least two fonts to set an equation: -an italic font for letters, -and a roman font for everything else. -The existing -.B gfont -command -changes the font that is used as the italic font. -By default this is\~\c -.BR I . -The font that is used as the roman font can be changed -using the new -.B grfont -command. -. -.TP -.BI grfont\ f -Set the roman font to\~\c -.IR f . -. -.LP -The -.B italic -primitive uses the current italic font set by -.BR gfont ; -the -.B roman -primitive uses the current roman font set by -.BR grfont . -There is also a new -.B gbfont -command, which changes the font used by the -.B bold -primitive. -If you only use the -.BR roman , -.B italic -and -.B bold -primitives to changes fonts within an equation, -you can change all the fonts used by your equations -just by using -.BR gfont , -.B grfont -and -.B gbfont -commands. -. -.LP -You can control which characters are treated as letters -(and therefore set in italics) by using the -.B chartype -command described above. -A type of -.B letter -will cause a character to be set in italic type. -A type of -.B digit -will cause a character to be set in roman type. -. -. -.SH FILES -.Tp \w'\fB@MACRODIR@/eqnrc'u+2n -.B @MACRODIR@/eqnrc -Initialization file. -. -. -.SH BUGS -Inline equations will be set at the point size that is current at the -beginning of the input line. -. -. -.SH "SEE ALSO" -.BR groff (@MAN1EXT@), -.BR @g@troff (@MAN1EXT@), -.BR @g@pic (@MAN1EXT@), -.BR groff_font (@MAN5EXT@), -.I The\ \*(txbook -. -.\" Local Variables: -.\" mode: nroff -.\" End: diff --git a/contrib/groff/src/preproc/eqn/eqn.y b/contrib/groff/src/preproc/eqn/eqn.y deleted file mode 100644 index 85157d6fce4b..000000000000 --- a/contrib/groff/src/preproc/eqn/eqn.y +++ /dev/null @@ -1,330 +0,0 @@ -/* Copyright (C) 1989, 1990, 1991, 1992, 2004 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ -%{ -#include -#include -#include - -#include "lib.h" -#include "box.h" -extern int non_empty_flag; -int yylex(); -void yyerror(const char *); -%} - -%union { - char *str; - box *b; - pile_box *pb; - matrix_box *mb; - int n; - column *col; -} - -%token OVER -%token SMALLOVER -%token SQRT -%token SUB -%token SUP -%token LPILE -%token RPILE -%token CPILE -%token PILE -%token LEFT -%token RIGHT -%token TO -%token FROM -%token SIZE -%token FONT -%token ROMAN -%token BOLD -%token ITALIC -%token FAT -%token ACCENT -%token BAR -%token UNDER -%token ABOVE -%token TEXT -%token QUOTED_TEXT -%token FWD -%token BACK -%token DOWN -%token UP -%token MATRIX -%token COL -%token LCOL -%token RCOL -%token CCOL -%token MARK -%token LINEUP -%token TYPE -%token VCENTER -%token PRIME -%token SPLIT -%token NOSPLIT -%token UACCENT -%token SPECIAL - -/* these are handled in the lexer */ -%token SPACE -%token GFONT -%token GSIZE -%token DEFINE -%token NDEFINE -%token TDEFINE -%token SDEFINE -%token UNDEF -%token IFDEF -%token INCLUDE -%token DELIM -%token CHARTYPE -%token SET -%token GRFONT -%token GBFONT - -/* The original eqn manual says that `left' is right associative. It's lying. -Consider `left ( ~ left ( ~ right ) right )'. */ - -%right LEFT -%left RIGHT -%right LPILE RPILE CPILE PILE TEXT QUOTED_TEXT MATRIX MARK LINEUP '^' '~' '\t' '{' SPLIT NOSPLIT -%right FROM TO -%left SQRT OVER SMALLOVER -%right SUB SUP -%right ROMAN BOLD ITALIC FAT FONT SIZE FWD BACK DOWN UP TYPE VCENTER SPECIAL -%right BAR UNDER PRIME -%left ACCENT UACCENT - -%type mark from_to sqrt_over script simple equation nonsup -%type number -%type text delim -%type pile_element_list pile_arg -%type column_list -%type column column_arg column_element_list - -%% -top: - /* empty */ - | equation - { $1->top_level(); non_empty_flag = 1; } - ; - -equation: - mark - { $$ = $1; } - | equation mark - { - list_box *lb = $1->to_list_box(); - if (!lb) - lb = new list_box($1); - lb->append($2); - $$ = lb; - } - ; - -mark: - from_to - { $$ = $1; } - | MARK mark - { $$ = make_mark_box($2); } - | LINEUP mark - { $$ = make_lineup_box($2); } - ; - -from_to: - sqrt_over %prec FROM - { $$ = $1; } - | sqrt_over TO from_to - { $$ = make_limit_box($1, 0, $3); } - | sqrt_over FROM sqrt_over - { $$ = make_limit_box($1, $3, 0); } - | sqrt_over FROM sqrt_over TO from_to - { $$ = make_limit_box($1, $3, $5); } - | sqrt_over FROM sqrt_over FROM from_to - { $$ = make_limit_box($1, make_limit_box($3, $5, 0), 0); } - ; - -sqrt_over: - script - { $$ = $1; } - | SQRT sqrt_over - { $$ = make_sqrt_box($2); } - | sqrt_over OVER sqrt_over - { $$ = make_over_box($1, $3); } - | sqrt_over SMALLOVER sqrt_over - { $$ = make_small_over_box($1, $3); } - ; - -script: - nonsup - { $$ = $1; } - | simple SUP script - { $$ = make_script_box($1, 0, $3); } - ; - -nonsup: - simple %prec SUP - { $$ = $1; } - | simple SUB nonsup - { $$ = make_script_box($1, $3, 0); } - | simple SUB simple SUP script - { $$ = make_script_box($1, $3, $5); } - ; - -simple: - TEXT - { $$ = split_text($1); } - | QUOTED_TEXT - { $$ = new quoted_text_box($1); } - | SPLIT QUOTED_TEXT - { $$ = split_text($2); } - | NOSPLIT TEXT - { $$ = new quoted_text_box($2); } - | '^' - { $$ = new half_space_box; } - | '~' - { $$ = new space_box; } - | '\t' - { $$ = new tab_box; } - | '{' equation '}' - { $$ = $2; } - | PILE pile_arg - { $2->set_alignment(CENTER_ALIGN); $$ = $2; } - | LPILE pile_arg - { $2->set_alignment(LEFT_ALIGN); $$ = $2; } - | RPILE pile_arg - { $2->set_alignment(RIGHT_ALIGN); $$ = $2; } - | CPILE pile_arg - { $2->set_alignment(CENTER_ALIGN); $$ = $2; } - | MATRIX '{' column_list '}' - { $$ = $3; } - | LEFT delim equation RIGHT delim - { $$ = make_delim_box($2, $3, $5); } - | LEFT delim equation - { $$ = make_delim_box($2, $3, 0); } - | simple BAR - { $$ = make_overline_box($1); } - | simple UNDER - { $$ = make_underline_box($1); } - | simple PRIME - { $$ = make_prime_box($1); } - | simple ACCENT simple - { $$ = make_accent_box($1, $3); } - | simple UACCENT simple - { $$ = make_uaccent_box($1, $3); } - | ROMAN simple - { $$ = new font_box(strsave(get_grfont()), $2); } - | BOLD simple - { $$ = new font_box(strsave(get_gbfont()), $2); } - | ITALIC simple - { $$ = new font_box(strsave(get_gfont()), $2); } - | FAT simple - { $$ = new fat_box($2); } - | FONT text simple - { $$ = new font_box($2, $3); } - | SIZE text simple - { $$ = new size_box($2, $3); } - | FWD number simple - { $$ = new hmotion_box($2, $3); } - | BACK number simple - { $$ = new hmotion_box(-$2, $3); } - | UP number simple - { $$ = new vmotion_box($2, $3); } - | DOWN number simple - { $$ = new vmotion_box(-$2, $3); } - | TYPE text simple - { $3->set_spacing_type($2); $$ = $3; } - | VCENTER simple - { $$ = new vcenter_box($2); } - | SPECIAL text simple - { $$ = make_special_box($2, $3); } - ; - -number: - text - { - int n; - if (sscanf($1, "%d", &n) == 1) - $$ = n; - a_delete $1; - } - ; - -pile_element_list: - equation - { $$ = new pile_box($1); } - | pile_element_list ABOVE equation - { $1->append($3); $$ = $1; } - ; - -pile_arg: - '{' pile_element_list '}' - { $$ = $2; } - | number '{' pile_element_list '}' - { $3->set_space($1); $$ = $3; } - ; - -column_list: - column - { $$ = new matrix_box($1); } - | column_list column - { $1->append($2); $$ = $1; } - ; - -column_element_list: - equation - { $$ = new column($1); } - | column_element_list ABOVE equation - { $1->append($3); $$ = $1; } - ; - -column_arg: - '{' column_element_list '}' - { $$ = $2; } - | number '{' column_element_list '}' - { $3->set_space($1); $$ = $3; } - ; - -column: - COL column_arg - { $2->set_alignment(CENTER_ALIGN); $$ = $2; } - | LCOL column_arg - { $2->set_alignment(LEFT_ALIGN); $$ = $2; } - | RCOL column_arg - { $2->set_alignment(RIGHT_ALIGN); $$ = $2; } - | CCOL column_arg - { $2->set_alignment(CENTER_ALIGN); $$ = $2; } - ; - -text: TEXT - { $$ = $1; } - | QUOTED_TEXT - { $$ = $1; } - ; - -delim: - text - { $$ = $1; } - | '{' - { $$ = strsave("{"); } - | '}' - { $$ = strsave("}"); } - ; - -%% diff --git a/contrib/groff/src/preproc/eqn/lex.cpp b/contrib/groff/src/preproc/eqn/lex.cpp deleted file mode 100644 index 6aa494dbf0d8..000000000000 --- a/contrib/groff/src/preproc/eqn/lex.cpp +++ /dev/null @@ -1,1172 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003, 2005 - 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "eqn.h" -#include "eqn_tab.h" -#include "stringclass.h" -#include "ptable.h" - - -// declarations to avoid friend name injection problems -int get_char(); -int peek_char(); -int get_location(char **, int *); - -struct definition { - char is_macro; - char is_simple; - union { - int tok; - char *contents; - }; - definition(); - ~definition(); -}; - -definition::definition() : is_macro(1), is_simple(0) -{ - contents = 0; -} - -definition::~definition() -{ - if (is_macro) - a_delete contents; -} - -declare_ptable(definition) -implement_ptable(definition) - -PTABLE(definition) macro_table; - -static struct { - const char *name; - int token; -} token_table[] = { - { "over", OVER }, - { "smallover", SMALLOVER }, - { "sqrt", SQRT }, - { "sub", SUB }, - { "sup", SUP }, - { "lpile", LPILE }, - { "rpile", RPILE }, - { "cpile", CPILE }, - { "pile", PILE }, - { "left", LEFT }, - { "right", RIGHT }, - { "to", TO }, - { "from", FROM }, - { "size", SIZE }, - { "font", FONT }, - { "roman", ROMAN }, - { "bold", BOLD }, - { "italic", ITALIC }, - { "fat", FAT }, - { "bar", BAR }, - { "under", UNDER }, - { "accent", ACCENT }, - { "uaccent", UACCENT }, - { "above", ABOVE }, - { "fwd", FWD }, - { "back", BACK }, - { "down", DOWN }, - { "up", UP }, - { "matrix", MATRIX }, - { "col", COL }, - { "lcol", LCOL }, - { "rcol", RCOL }, - { "ccol", CCOL }, - { "mark", MARK }, - { "lineup", LINEUP }, - { "space", SPACE }, - { "gfont", GFONT }, - { "gsize", GSIZE }, - { "define", DEFINE }, - { "sdefine", SDEFINE }, - { "ndefine", NDEFINE }, - { "tdefine", TDEFINE }, - { "undef", UNDEF }, - { "ifdef", IFDEF }, - { "include", INCLUDE }, - { "copy", INCLUDE }, - { "delim", DELIM }, - { "chartype", CHARTYPE }, - { "type", TYPE }, - { "vcenter", VCENTER }, - { "set", SET }, - { "opprime", PRIME }, - { "grfont", GRFONT }, - { "gbfont", GBFONT }, - { "split", SPLIT }, - { "nosplit", NOSPLIT }, - { "special", SPECIAL }, -}; - -static struct { - const char *name; - const char *def; -} def_table[] = { - { "ALPHA", "\\(*A" }, - { "BETA", "\\(*B" }, - { "CHI", "\\(*X" }, - { "DELTA", "\\(*D" }, - { "EPSILON", "\\(*E" }, - { "ETA", "\\(*Y" }, - { "GAMMA", "\\(*G" }, - { "IOTA", "\\(*I" }, - { "KAPPA", "\\(*K" }, - { "LAMBDA", "\\(*L" }, - { "MU", "\\(*M" }, - { "NU", "\\(*N" }, - { "OMEGA", "\\(*W" }, - { "OMICRON", "\\(*O" }, - { "PHI", "\\(*F" }, - { "PI", "\\(*P" }, - { "PSI", "\\(*Q" }, - { "RHO", "\\(*R" }, - { "SIGMA", "\\(*S" }, - { "TAU", "\\(*T" }, - { "THETA", "\\(*H" }, - { "UPSILON", "\\(*U" }, - { "XI", "\\(*C" }, - { "ZETA", "\\(*Z" }, - { "Alpha", "\\(*A" }, - { "Beta", "\\(*B" }, - { "Chi", "\\(*X" }, - { "Delta", "\\(*D" }, - { "Epsilon", "\\(*E" }, - { "Eta", "\\(*Y" }, - { "Gamma", "\\(*G" }, - { "Iota", "\\(*I" }, - { "Kappa", "\\(*K" }, - { "Lambda", "\\(*L" }, - { "Mu", "\\(*M" }, - { "Nu", "\\(*N" }, - { "Omega", "\\(*W" }, - { "Omicron", "\\(*O" }, - { "Phi", "\\(*F" }, - { "Pi", "\\(*P" }, - { "Psi", "\\(*Q" }, - { "Rho", "\\(*R" }, - { "Sigma", "\\(*S" }, - { "Tau", "\\(*T" }, - { "Theta", "\\(*H" }, - { "Upsilon", "\\(*U" }, - { "Xi", "\\(*C" }, - { "Zeta", "\\(*Z" }, - { "alpha", "\\(*a" }, - { "beta", "\\(*b" }, - { "chi", "\\(*x" }, - { "delta", "\\(*d" }, - { "epsilon", "\\(*e" }, - { "eta", "\\(*y" }, - { "gamma", "\\(*g" }, - { "iota", "\\(*i" }, - { "kappa", "\\(*k" }, - { "lambda", "\\(*l" }, - { "mu", "\\(*m" }, - { "nu", "\\(*n" }, - { "omega", "\\(*w" }, - { "omicron", "\\(*o" }, - { "phi", "\\(*f" }, - { "pi", "\\(*p" }, - { "psi", "\\(*q" }, - { "rho", "\\(*r" }, - { "sigma", "\\(*s" }, - { "tau", "\\(*t" }, - { "theta", "\\(*h" }, - { "upsilon", "\\(*u" }, - { "xi", "\\(*c" }, - { "zeta", "\\(*z" }, - { "max", "{type \"operator\" roman \"max\"}" }, - { "min", "{type \"operator\" roman \"min\"}" }, - { "lim", "{type \"operator\" roman \"lim\"}" }, - { "sin", "{type \"operator\" roman \"sin\"}" }, - { "cos", "{type \"operator\" roman \"cos\"}" }, - { "tan", "{type \"operator\" roman \"tan\"}" }, - { "sinh", "{type \"operator\" roman \"sinh\"}" }, - { "cosh", "{type \"operator\" roman \"cosh\"}" }, - { "tanh", "{type \"operator\" roman \"tanh\"}" }, - { "arc", "{type \"operator\" roman \"arc\"}" }, - { "log", "{type \"operator\" roman \"log\"}" }, - { "ln", "{type \"operator\" roman \"ln\"}" }, - { "exp", "{type \"operator\" roman \"exp\"}" }, - { "Re", "{type \"operator\" roman \"Re\"}" }, - { "Im", "{type \"operator\" roman \"Im\"}" }, - { "det", "{type \"operator\" roman \"det\"}" }, - { "and", "{roman \"and\"}" }, - { "if", "{roman \"if\"}" }, - { "for", "{roman \"for\"}" }, - { "sum", "{type \"operator\" vcenter size +5 \\(*S}" }, - { "prod", "{type \"operator\" vcenter size +5 \\(*P}" }, - { "int", "{type \"operator\" vcenter size +8 \\(is}" }, - { "union", "{type \"operator\" vcenter size +5 \\(cu}" }, - { "inter", "{type \"operator\" vcenter size +5 \\(ca}" }, - { "times", "type \"binary\" \\(mu" }, - { "ldots", "type \"inner\" { . . . }" }, - { "inf", "\\(if" }, - { "partial", "\\(pd" }, - { "nothing", "\"\"" }, - { "half", "{1 smallover 2}" }, - { "hat_def", "roman \"^\"" }, - { "hat", "accent { hat_def }" }, - { "dot_def", "back 15 \"\\v'-52M'.\\v'52M'\"" }, - { "dot", "accent { dot_def }" }, - { "dotdot_def", "back 25 \"\\v'-52M'..\\v'52M'\"" }, - { "dotdot", "accent { dotdot_def }" }, - { "tilde_def", "\"~\"" }, - { "tilde", "accent { tilde_def }" }, - { "utilde_def", "\"\\v'75M'~\\v'-75M'\"" }, - { "utilde", "uaccent { utilde_def }" }, - { "vec_def", "up 52 size -5 \\(->" }, - { "vec", "accent { vec_def }" }, - { "dyad_def", "up 52 size -5 {\\(<- back 60 \\(->}" }, - { "dyad", "accent { dyad_def }" }, - { "==", "type \"relation\" \\(==" }, - { "!=", "type \"relation\" \\(!=" }, - { "+-", "type \"binary\" \\(+-" }, - { "->", "type \"relation\" \\(->" }, - { "<-", "type \"relation\" \\(<-" }, - { "<<", "{ < back 20 < }" }, - { ">>", "{ > back 20 > }" }, - { "...", "type \"inner\" vcenter { . . . }" }, - { "prime", "'" }, - { "approx", "type \"relation\" \"\\(~=\"" }, - { "grad", "\\(gr" }, - { "del", "\\(gr" }, - { "cdot", "type \"binary\" vcenter ." }, - { "dollar", "$" }, -}; - -void init_table(const char *device) -{ - unsigned int i; - for (i = 0; i < sizeof(token_table)/sizeof(token_table[0]); i++) { - definition *def = new definition[1]; - def->is_macro = 0; - def->tok = token_table[i].token; - macro_table.define(token_table[i].name, def); - } - for (i = 0; i < sizeof(def_table)/sizeof(def_table[0]); i++) { - definition *def = new definition[1]; - def->is_macro = 1; - def->contents = strsave(def_table[i].def); - def->is_simple = 1; - macro_table.define(def_table[i].name, def); - } - definition *def = new definition[1]; - def->is_macro = 1; - def->contents = strsave("1"); - macro_table.define(device, def); -} - -class input { - input *next; -public: - input(input *p); - virtual ~input(); - virtual int get() = 0; - virtual int peek() = 0; - virtual int get_location(char **, int *); - - friend int get_char(); - friend int peek_char(); - friend int get_location(char **, int *); - friend void init_lex(const char *str, const char *filename, int lineno); -}; - -class file_input : public input { - FILE *fp; - char *filename; - int lineno; - string line; - const char *ptr; - int read_line(); -public: - file_input(FILE *, const char *, input *); - ~file_input(); - int get(); - int peek(); - int get_location(char **, int *); -}; - - -class macro_input : public input { - char *s; - char *p; -public: - macro_input(const char *, input *); - ~macro_input(); - int get(); - int peek(); -}; - -class top_input : public macro_input { - char *filename; - int lineno; - public: - top_input(const char *, const char *, int, input *); - ~top_input(); - int get(); - int get_location(char **, int *); -}; - -class argument_macro_input: public input { - char *s; - char *p; - char *ap; - int argc; - char *argv[9]; -public: - argument_macro_input(const char *, int, char **, input *); - ~argument_macro_input(); - int get(); - int peek(); -}; - -input::input(input *x) : next(x) -{ -} - -input::~input() -{ -} - -int input::get_location(char **, int *) -{ - return 0; -} - -file_input::file_input(FILE *f, const char *fn, input *p) -: input(p), lineno(0), ptr("") -{ - fp = f; - filename = strsave(fn); -} - -file_input::~file_input() -{ - a_delete filename; - fclose(fp); -} - -int file_input::read_line() -{ - for (;;) { - line.clear(); - lineno++; - for (;;) { - int c = getc(fp); - if (c == EOF) - break; - else if (invalid_input_char(c)) - lex_error("invalid input character code %1", c); - else { - line += char(c); - if (c == '\n') - break; - } - } - if (line.length() == 0) - return 0; - if (!(line.length() >= 3 && line[0] == '.' && line[1] == 'E' - && (line[2] == 'Q' || line[2] == 'N') - && (line.length() == 3 || line[3] == ' ' || line[3] == '\n' - || compatible_flag))) { - line += '\0'; - ptr = line.contents(); - return 1; - } - } -} - -int file_input::get() -{ - if (*ptr != '\0' || read_line()) - return *ptr++ & 0377; - else - return EOF; -} - -int file_input::peek() -{ - if (*ptr != '\0' || read_line()) - return *ptr; - else - return EOF; -} - -int file_input::get_location(char **fnp, int *lnp) -{ - *fnp = filename; - *lnp = lineno; - return 1; -} - -macro_input::macro_input(const char *str, input *x) : input(x) -{ - p = s = strsave(str); -} - -macro_input::~macro_input() -{ - a_delete s; -} - -int macro_input::get() -{ - if (p == 0 || *p == '\0') - return EOF; - else - return *p++ & 0377; -} - -int macro_input::peek() -{ - if (p == 0 || *p == '\0') - return EOF; - else - return *p & 0377; -} - -top_input::top_input(const char *str, const char *fn, int ln, input *x) -: macro_input(str, x), lineno(ln) -{ - filename = strsave(fn); -} - -top_input::~top_input() -{ - a_delete filename; -} - -int top_input::get() -{ - int c = macro_input::get(); - if (c == '\n') - lineno++; - return c; -} - -int top_input::get_location(char **fnp, int *lnp) -{ - *fnp = filename; - *lnp = lineno; - return 1; -} - -// Character representing $1. Must be invalid input character. -#define ARG1 14 - -argument_macro_input::argument_macro_input(const char *body, int ac, - char **av, input *x) -: input(x), ap(0), argc(ac) -{ - int i; - for (i = 0; i < argc; i++) - argv[i] = av[i]; - p = s = strsave(body); - int j = 0; - for (i = 0; s[i] != '\0'; i++) - if (s[i] == '$' && s[i+1] >= '0' && s[i+1] <= '9') { - if (s[i+1] != '0') - s[j++] = ARG1 + s[++i] - '1'; - } - else - s[j++] = s[i]; - s[j] = '\0'; -} - - -argument_macro_input::~argument_macro_input() -{ - for (int i = 0; i < argc; i++) - a_delete argv[i]; - a_delete s; -} - -int argument_macro_input::get() -{ - if (ap) { - if (*ap != '\0') - return *ap++ & 0377; - ap = 0; - } - if (p == 0) - return EOF; - while (*p >= ARG1 && *p <= ARG1 + 8) { - int i = *p++ - ARG1; - if (i < argc && argv[i] != 0 && argv[i][0] != '\0') { - ap = argv[i]; - return *ap++ & 0377; - } - } - if (*p == '\0') - return EOF; - return *p++ & 0377; -} - -int argument_macro_input::peek() -{ - if (ap) { - if (*ap != '\0') - return *ap & 0377; - ap = 0; - } - if (p == 0) - return EOF; - while (*p >= ARG1 && *p <= ARG1 + 8) { - int i = *p++ - ARG1; - if (i < argc && argv[i] != 0 && argv[i][0] != '\0') { - ap = argv[i]; - return *ap & 0377; - } - } - if (*p == '\0') - return EOF; - return *p & 0377; -} - -static input *current_input = 0; - -/* we insert a newline between input from different levels */ - -int get_char() -{ - if (current_input == 0) - return EOF; - else { - int c = current_input->get(); - if (c != EOF) - return c; - else { - input *tem = current_input; - current_input = current_input->next; - delete tem; - return '\n'; - } - } -} - -int peek_char() -{ - if (current_input == 0) - return EOF; - else { - int c = current_input->peek(); - if (c != EOF) - return c; - else - return '\n'; - } -} - -int get_location(char **fnp, int *lnp) -{ - for (input *p = current_input; p; p = p->next) - if (p->get_location(fnp, lnp)) - return 1; - return 0; -} - -string token_buffer; -const int NCONTEXT = 4; -string context_ring[NCONTEXT]; -int context_index = 0; - -void flush_context() -{ - for (int i = 0; i < NCONTEXT; i++) - context_ring[i] = ""; - context_index = 0; -} - -void show_context() -{ - int i = context_index; - fputs(" context is\n\t", stderr); - for (;;) { - int j = (i + 1) % NCONTEXT; - if (j == context_index) { - fputs(">>> ", stderr); - put_string(context_ring[i], stderr); - fputs(" <<<", stderr); - break; - } - else if (context_ring[i].length() > 0) { - put_string(context_ring[i], stderr); - putc(' ', stderr); - } - i = j; - } - putc('\n', stderr); -} - -void add_context(const string &s) -{ - context_ring[context_index] = s; - context_index = (context_index + 1) % NCONTEXT; -} - -void add_context(char c) -{ - context_ring[context_index] = c; - context_index = (context_index + 1) % NCONTEXT; -} - -void add_quoted_context(const string &s) -{ - string &r = context_ring[context_index]; - r = '"'; - for (int i = 0; i < s.length(); i++) - if (s[i] == '"') - r += "\\\""; - else - r += s[i]; - r += '"'; - context_index = (context_index + 1) % NCONTEXT; -} - -void init_lex(const char *str, const char *filename, int lineno) -{ - while (current_input != 0) { - input *tem = current_input; - current_input = current_input->next; - delete tem; - } - current_input = new top_input(str, filename, lineno, 0); - flush_context(); -} - - -void get_delimited_text() -{ - char *filename; - int lineno; - int got_location = get_location(&filename, &lineno); - int start = get_char(); - while (start == ' ' || start == '\t' || start == '\n') - start = get_char(); - token_buffer.clear(); - if (start == EOF) { - if (got_location) - error_with_file_and_line(filename, lineno, - "end of input while defining macro"); - else - error("end of input while defining macro"); - return; - } - for (;;) { - int c = get_char(); - if (c == EOF) { - if (got_location) - error_with_file_and_line(filename, lineno, - "end of input while defining macro"); - else - error("end of input while defining macro"); - add_context(start + token_buffer); - return; - } - if (c == start) - break; - token_buffer += char(c); - } - add_context(start + token_buffer + start); -} - -void interpolate_macro_with_args(const char *body) -{ - char *argv[9]; - int argc = 0; - int i; - for (i = 0; i < 9; i++) - argv[i] = 0; - int level = 0; - int c; - do { - token_buffer.clear(); - for (;;) { - c = get_char(); - if (c == EOF) { - lex_error("end of input while scanning macro arguments"); - break; - } - if (level == 0 && (c == ',' || c == ')')) { - if (token_buffer.length() > 0) { - token_buffer += '\0'; - argv[argc] = strsave(token_buffer.contents()); - } - // for `foo()', argc = 0 - if (argc > 0 || c != ')' || i > 0) - argc++; - break; - } - token_buffer += char(c); - if (c == '(') - level++; - else if (c == ')') - level--; - } - } while (c != ')' && c != EOF); - current_input = new argument_macro_input(body, argc, argv, current_input); -} - -/* If lookup flag is non-zero the token will be looked up to see -if it is macro. If it's 1, it will looked up to see if it's a token. -*/ - -int get_token(int lookup_flag = 0) -{ - for (;;) { - int c = get_char(); - while (c == ' ' || c == '\n') - c = get_char(); - switch (c) { - case EOF: - { - add_context("end of input"); - } - return 0; - case '"': - { - int quoted = 0; - token_buffer.clear(); - for (;;) { - c = get_char(); - if (c == EOF) { - lex_error("missing \""); - break; - } - else if (c == '\n') { - lex_error("newline before end of quoted text"); - break; - } - else if (c == '"') { - if (!quoted) - break; - token_buffer[token_buffer.length() - 1] = '"'; - quoted = 0; - } - else { - token_buffer += c; - quoted = quoted ? 0 : c == '\\'; - } - } - } - add_quoted_context(token_buffer); - return QUOTED_TEXT; - case '{': - case '}': - case '^': - case '~': - case '\t': - add_context(c); - return c; - default: - { - int break_flag = 0; - int quoted = 0; - token_buffer.clear(); - if (c == '\\') - quoted = 1; - else - token_buffer += c; - int done = 0; - while (!done) { - c = peek_char(); - if (!quoted && lookup_flag != 0 && c == '(') { - token_buffer += '\0'; - definition *def = macro_table.lookup(token_buffer.contents()); - if (def && def->is_macro && !def->is_simple) { - (void)get_char(); // skip initial '(' - interpolate_macro_with_args(def->contents); - break_flag = 1; - break; - } - token_buffer.set_length(token_buffer.length() - 1); - } - if (quoted) { - quoted = 0; - switch (c) { - case EOF: - lex_error("`\\' ignored at end of equation"); - done = 1; - break; - case '\n': - lex_error("`\\' ignored because followed by newline"); - done = 1; - break; - case '\t': - lex_error("`\\' ignored because followed by tab"); - done = 1; - break; - case '"': - (void)get_char(); - token_buffer += '"'; - break; - default: - (void)get_char(); - token_buffer += '\\'; - token_buffer += c; - break; - } - } - else { - switch (c) { - case EOF: - case '{': - case '}': - case '^': - case '~': - case '"': - case ' ': - case '\t': - case '\n': - done = 1; - break; - case '\\': - (void)get_char(); - quoted = 1; - break; - default: - (void)get_char(); - token_buffer += char(c); - break; - } - } - } - if (break_flag || token_buffer.length() == 0) - break; - if (lookup_flag != 0) { - token_buffer += '\0'; - definition *def = macro_table.lookup(token_buffer.contents()); - token_buffer.set_length(token_buffer.length() - 1); - if (def) { - if (def->is_macro) { - current_input = new macro_input(def->contents, current_input); - break; - } - else if (lookup_flag == 1) { - add_context(token_buffer); - return def->tok; - } - } - } - add_context(token_buffer); - return TEXT; - } - } - } -} - -void do_include() -{ - int t = get_token(2); - if (t != TEXT && t != QUOTED_TEXT) { - lex_error("bad filename for include"); - return; - } - token_buffer += '\0'; - const char *filename = token_buffer.contents(); - errno = 0; - FILE *fp = fopen(filename, "r"); - if (fp == 0) { - lex_error("can't open included file `%1'", filename); - return; - } - current_input = new file_input(fp, filename, current_input); -} - -void ignore_definition() -{ - int t = get_token(); - if (t != TEXT) { - lex_error("bad definition"); - return; - } - get_delimited_text(); -} - -void do_definition(int is_simple) -{ - int t = get_token(); - if (t != TEXT) { - lex_error("bad definition"); - return; - } - token_buffer += '\0'; - const char *name = token_buffer.contents(); - definition *def = macro_table.lookup(name); - if (def == 0) { - def = new definition[1]; - macro_table.define(name, def); - } - else if (def->is_macro) { - a_delete def->contents; - } - get_delimited_text(); - token_buffer += '\0'; - def->is_macro = 1; - def->contents = strsave(token_buffer.contents()); - def->is_simple = is_simple; -} - -void do_undef() -{ - int t = get_token(); - if (t != TEXT) { - lex_error("bad undef command"); - return; - } - token_buffer += '\0'; - macro_table.define(token_buffer.contents(), 0); -} - -void do_gsize() -{ - int t = get_token(2); - if (t != TEXT && t != QUOTED_TEXT) { - lex_error("bad argument to gsize command"); - return; - } - token_buffer += '\0'; - if (!set_gsize(token_buffer.contents())) - lex_error("invalid size `%1'", token_buffer.contents()); -} - -void do_gfont() -{ - int t = get_token(2); - if (t != TEXT && t != QUOTED_TEXT) { - lex_error("bad argument to gfont command"); - return; - } - token_buffer += '\0'; - set_gfont(token_buffer.contents()); -} - -void do_grfont() -{ - int t = get_token(2); - if (t != TEXT && t != QUOTED_TEXT) { - lex_error("bad argument to grfont command"); - return; - } - token_buffer += '\0'; - set_grfont(token_buffer.contents()); -} - -void do_gbfont() -{ - int t = get_token(2); - if (t != TEXT && t != QUOTED_TEXT) { - lex_error("bad argument to gbfont command"); - return; - } - token_buffer += '\0'; - set_gbfont(token_buffer.contents()); -} - -void do_space() -{ - int t = get_token(2); - if (t != TEXT && t != QUOTED_TEXT) { - lex_error("bad argument to space command"); - return; - } - token_buffer += '\0'; - char *ptr; - long n = strtol(token_buffer.contents(), &ptr, 10); - if (n == 0 && ptr == token_buffer.contents()) - lex_error("bad argument `%1' to space command", token_buffer.contents()); - else - set_space(int(n)); -} - -void do_ifdef() -{ - int t = get_token(); - if (t != TEXT) { - lex_error("bad ifdef"); - return; - } - token_buffer += '\0'; - definition *def = macro_table.lookup(token_buffer.contents()); - int result = def && def->is_macro && !def->is_simple; - get_delimited_text(); - if (result) { - token_buffer += '\0'; - current_input = new macro_input(token_buffer.contents(), current_input); - } -} - -void do_delim() -{ - int c = get_char(); - while (c == ' ' || c == '\n') - c = get_char(); - int d; - if (c == EOF || (d = get_char()) == EOF) - lex_error("end of file while reading argument to `delim'"); - else { - if (c == 'o' && d == 'f' && peek_char() == 'f') { - (void)get_char(); - start_delim = end_delim = '\0'; - } - else { - start_delim = c; - end_delim = d; - } - } -} - -void do_chartype() -{ - int t = get_token(2); - if (t != TEXT && t != QUOTED_TEXT) { - lex_error("bad chartype"); - return; - } - token_buffer += '\0'; - string type = token_buffer; - t = get_token(); - if (t != TEXT && t != QUOTED_TEXT) { - lex_error("bad chartype"); - return; - } - token_buffer += '\0'; - set_char_type(type.contents(), strsave(token_buffer.contents())); -} - -void do_set() -{ - int t = get_token(2); - if (t != TEXT && t != QUOTED_TEXT) { - lex_error("bad set"); - return; - } - token_buffer += '\0'; - string param = token_buffer; - t = get_token(); - if (t != TEXT && t != QUOTED_TEXT) { - lex_error("bad set"); - return; - } - token_buffer += '\0'; - int n; - if (sscanf(&token_buffer[0], "%d", &n) != 1) { - lex_error("bad number `%1'", token_buffer.contents()); - return; - } - set_param(param.contents(), n); -} - -int yylex() -{ - for (;;) { - int tk = get_token(1); - switch(tk) { - case UNDEF: - do_undef(); - break; - case SDEFINE: - do_definition(1); - break; - case DEFINE: - do_definition(0); - break; - case TDEFINE: - if (!nroff) - do_definition(0); - else - ignore_definition(); - break; - case NDEFINE: - if (nroff) - do_definition(0); - else - ignore_definition(); - break; - case GSIZE: - do_gsize(); - break; - case GFONT: - do_gfont(); - break; - case GRFONT: - do_grfont(); - break; - case GBFONT: - do_gbfont(); - break; - case SPACE: - do_space(); - break; - case INCLUDE: - do_include(); - break; - case IFDEF: - do_ifdef(); - break; - case DELIM: - do_delim(); - break; - case CHARTYPE: - do_chartype(); - break; - case SET: - do_set(); - break; - case QUOTED_TEXT: - case TEXT: - token_buffer += '\0'; - yylval.str = strsave(token_buffer.contents()); - // fall through - default: - return tk; - } - } -} - -void lex_error(const char *message, - const errarg &arg1, - const errarg &arg2, - const errarg &arg3) -{ - char *filename; - int lineno; - if (!get_location(&filename, &lineno)) - error(message, arg1, arg2, arg3); - else - error_with_file_and_line(filename, lineno, message, arg1, arg2, arg3); -} - -void yyerror(const char *s) -{ - char *filename; - int lineno; - if (!get_location(&filename, &lineno)) - error(s); - else - error_with_file_and_line(filename, lineno, s); - show_context(); -} - diff --git a/contrib/groff/src/preproc/eqn/limit.cpp b/contrib/groff/src/preproc/eqn/limit.cpp deleted file mode 100644 index b9f35f97efc5..000000000000 --- a/contrib/groff/src/preproc/eqn/limit.cpp +++ /dev/null @@ -1,195 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2002 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "eqn.h" -#include "pbox.h" - -class limit_box : public box { -private: - box *p; - box *from; - box *to; -public: - limit_box(box *, box *, box *); - ~limit_box(); - int compute_metrics(int); - void output(); - void debug_print(); - void check_tabs(int); -}; - -box *make_limit_box(box *pp, box *qq, box *rr) -{ - return new limit_box(pp, qq, rr); -} - -limit_box::limit_box(box *pp, box *qq, box *rr) -: p(pp), from(qq), to(rr) -{ - spacing_type = p->spacing_type; -} - -limit_box::~limit_box() -{ - delete p; - delete from; - delete to; -} - -int limit_box::compute_metrics(int style) -{ - printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid); - if (!(style <= SCRIPT_STYLE && one_size_reduction_flag)) - set_script_size(); - printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid); - int res = 0; - int mark_uid = -1; - if (from != 0) { - res = from->compute_metrics(cramped_style(script_style(style))); - if (res) - mark_uid = from->uid; - } - if (to != 0) { - int r = to->compute_metrics(script_style(style)); - if (res && r) - error("multiple marks and lineups"); - else { - mark_uid = to->uid; - res = r; - } - } - printf(".ps \\n[" SIZE_FORMAT "]u\n", uid); - int r = p->compute_metrics(style); - p->compute_subscript_kern(); - if (res && r) - error("multiple marks and lineups"); - else { - mark_uid = p->uid; - res = r; - } - printf(".nr " LEFT_WIDTH_FORMAT " " - "0\\n[" WIDTH_FORMAT "]", - uid, p->uid); - if (from != 0) - printf(">?(\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])", - p->uid, from->uid); - if (to != 0) - printf(">?(-\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])", - p->uid, to->uid); - printf("/2\n"); - printf(".nr " WIDTH_FORMAT " " - "0\\n[" WIDTH_FORMAT "]", - uid, p->uid); - if (from != 0) - printf(">?(-\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])", - p->uid, from->uid); - if (to != 0) - printf(">?(\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])", - p->uid, to->uid); - printf("/2+\\n[" LEFT_WIDTH_FORMAT "]\n", uid); - printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]", uid, p->uid); - if (to != 0) - printf(">?\\n[" WIDTH_FORMAT "]", to->uid); - if (from != 0) - printf(">?\\n[" WIDTH_FORMAT "]", from->uid); - printf("\n"); - if (res) - printf(".nr " MARK_REG " +(\\n[" LEFT_WIDTH_FORMAT "]" - "-(\\n[" WIDTH_FORMAT "]/2))\n", - uid, mark_uid); - if (to != 0) { - printf(".nr " SUP_RAISE_FORMAT " %dM+\\n[" DEPTH_FORMAT - "]>?%dM+\\n[" HEIGHT_FORMAT "]\n", - uid, big_op_spacing1, to->uid, big_op_spacing3, p->uid); - printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n[" - HEIGHT_FORMAT "]+%dM\n", - uid, uid, to->uid, big_op_spacing5); - } - else - printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid); - if (from != 0) { - printf(".nr " SUB_LOWER_FORMAT " %dM+\\n[" HEIGHT_FORMAT - "]>?%dM+\\n[" DEPTH_FORMAT "]\n", - uid, big_op_spacing2, from->uid, big_op_spacing4, p->uid); - printf(".nr " DEPTH_FORMAT " \\n[" SUB_LOWER_FORMAT "]+\\n[" - DEPTH_FORMAT "]+%dM\n", - uid, uid, from->uid, big_op_spacing5); - } - else - printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid); - return res; -} - -void limit_box::output() -{ - printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid); - if (to != 0) { - printf("\\Z" DELIMITER_CHAR); - printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); - printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u" - "+(-\\n[" WIDTH_FORMAT "]u+\\n[" SUB_KERN_FORMAT "]u/2u)'", - uid, to->uid, p->uid); - to->output(); - printf(DELIMITER_CHAR); - } - if (from != 0) { - printf("\\Z" DELIMITER_CHAR); - printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid); - printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u" - "+(-\\n[" SUB_KERN_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'", - uid, p->uid, from->uid); - from->output(); - printf(DELIMITER_CHAR); - } - printf("\\s[\\n[" SIZE_FORMAT "]u]", uid); - printf("\\Z" DELIMITER_CHAR); - printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u" - "-(\\n[" WIDTH_FORMAT "]u/2u)'", - uid, p->uid); - p->output(); - printf(DELIMITER_CHAR); - printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid); -} - -void limit_box::debug_print() -{ - fprintf(stderr, "{ "); - p->debug_print(); - fprintf(stderr, " }"); - if (from) { - fprintf(stderr, " from { "); - from->debug_print(); - fprintf(stderr, " }"); - } - if (to) { - fprintf(stderr, " to { "); - to->debug_print(); - fprintf(stderr, " }"); - } -} - -void limit_box::check_tabs(int level) -{ - if (to) - to->check_tabs(level + 1); - if (from) - from->check_tabs(level + 1); - p->check_tabs(level + 1); -} diff --git a/contrib/groff/src/preproc/eqn/list.cpp b/contrib/groff/src/preproc/eqn/list.cpp deleted file mode 100644 index 003562afa501..000000000000 --- a/contrib/groff/src/preproc/eqn/list.cpp +++ /dev/null @@ -1,237 +0,0 @@ -// -*- 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "eqn.h" -#include "pbox.h" - -list_box *box::to_list_box() -{ - return 0; -} - -list_box *list_box::to_list_box() -{ - return this; -} - -void list_box::append(box *pp) -{ - list_box *q = pp->to_list_box(); - if (q == 0) - list.append(pp); - else { - for (int i = 0; i < q->list.len; i++) { - list.append(q->list.p[i]); - q->list.p[i] = 0; - } - q->list.len = 0; - delete q; - } -} - -list_box::list_box(box *pp) : list(pp), sty(-1) -{ - list_box *q = pp->to_list_box(); - if (q != 0) { - // flatten it - list.p[0] = q->list.p[0]; - for (int i = 1; i < q->list.len; i++) { - list.append(q->list.p[i]); - q->list.p[i] = 0; - } - q->list.len = 0; - delete q; - } -} - -static int compute_spacing(int is_script, int left, int right) -{ - if (left == SUPPRESS_TYPE || right == SUPPRESS_TYPE) - return 0; - if (left == PUNCTUATION_TYPE) - return is_script ? 0 : thin_space; - if (left == OPENING_TYPE || right == CLOSING_TYPE) - return 0; - if (right == BINARY_TYPE || left == BINARY_TYPE) - return is_script ? 0 : medium_space; - if (right == RELATION_TYPE) { - if (left == RELATION_TYPE) - return 0; - else - return is_script ? 0 : thick_space; - } - if (left == RELATION_TYPE) - return is_script ? 0 : thick_space; - if (right == OPERATOR_TYPE) - return thin_space; - if (left == INNER_TYPE || right == INNER_TYPE) - return is_script ? 0 : thin_space; - if (left == OPERATOR_TYPE && right == ORDINARY_TYPE) - return thin_space; - return 0; -} - -int list_box::compute_metrics(int style) -{ - sty = style; - int i; - for (i = 0; i < list.len; i++) { - int t = list.p[i]->spacing_type; - // 5 - if (t == BINARY_TYPE) { - int prevt; - if (i == 0 - || (prevt = list.p[i-1]->spacing_type) == BINARY_TYPE - || prevt == OPERATOR_TYPE - || prevt == RELATION_TYPE - || prevt == OPENING_TYPE - || prevt == PUNCTUATION_TYPE) - list.p[i]->spacing_type = ORDINARY_TYPE; - } - // 7 - else if ((t == RELATION_TYPE || t == CLOSING_TYPE - || t == PUNCTUATION_TYPE) - && i > 0 && list.p[i-1]->spacing_type == BINARY_TYPE) - list.p[i-1]->spacing_type = ORDINARY_TYPE; - } - for (i = 0; i < list.len; i++) { - unsigned flags = 0; - if (i - 1 >= 0 && list.p[i - 1]->right_is_italic()) - flags |= HINT_PREV_IS_ITALIC; - if (i + 1 < list.len && list.p[i + 1]->left_is_italic()) - flags |= HINT_NEXT_IS_ITALIC; - if (flags) - list.p[i]->hint(flags); - } - is_script = (style <= SCRIPT_STYLE); - int total_spacing = 0; - for (i = 1; i < list.len; i++) - total_spacing += compute_spacing(is_script, list.p[i-1]->spacing_type, - list.p[i]->spacing_type); - int res = 0; - for (i = 0; i < list.len; i++) - if (!list.p[i]->is_simple()) { - int r = list.p[i]->compute_metrics(style); - if (r) { - if (res) - error("multiple marks and lineups"); - else { - compute_sublist_width(i); - printf(".nr " MARK_REG " +\\n[" TEMP_REG"]\n"); - res = r; - } - } - } - printf(".nr " WIDTH_FORMAT " %dM", uid, total_spacing); - for (i = 0; i < list.len; i++) - if (!list.p[i]->is_simple()) - printf("+\\n[" WIDTH_FORMAT "]", list.p[i]->uid); - printf("\n"); - printf(".nr " HEIGHT_FORMAT " 0", uid); - for (i = 0; i < list.len; i++) - if (!list.p[i]->is_simple()) - printf(">?\\n[" HEIGHT_FORMAT "]", list.p[i]->uid); - printf("\n"); - printf(".nr " DEPTH_FORMAT " 0", uid); - for (i = 0; i < list.len; i++) - if (!list.p[i]->is_simple()) - printf(">?\\n[" DEPTH_FORMAT "]", list.p[i]->uid); - printf("\n"); - int have_simple = 0; - for (i = 0; i < list.len && !have_simple; i++) - have_simple = list.p[i]->is_simple(); - if (have_simple) { - printf(".nr " WIDTH_FORMAT " +\\w" DELIMITER_CHAR, uid); - for (i = 0; i < list.len; i++) - if (list.p[i]->is_simple()) - list.p[i]->output(); - printf(DELIMITER_CHAR "\n"); - printf(".nr " HEIGHT_FORMAT " \\n[rst]>?\\n[" HEIGHT_FORMAT "]\n", - uid, uid); - printf(".nr " DEPTH_FORMAT " 0-\\n[rsb]>?\\n[" DEPTH_FORMAT "]\n", - uid, uid); - } - return res; -} - -void list_box::compute_sublist_width(int n) -{ - int total_spacing = 0; - int i; - for (i = 1; i < n + 1 && i < list.len; i++) - total_spacing += compute_spacing(is_script, list.p[i-1]->spacing_type, - list.p[i]->spacing_type); - printf(".nr " TEMP_REG " %dM", total_spacing); - for (i = 0; i < n; i++) - if (!list.p[i]->is_simple()) - printf("+\\n[" WIDTH_FORMAT "]", list.p[i]->uid); - int have_simple = 0; - for (i = 0; i < n && !have_simple; i++) - have_simple = list.p[i]->is_simple(); - if (have_simple) { - printf("+\\w" DELIMITER_CHAR); - for (i = 0; i < n; i++) - if (list.p[i]->is_simple()) - list.p[i]->output(); - printf(DELIMITER_CHAR); - } - printf("\n"); -} - -void list_box::compute_subscript_kern() -{ - // We can only call compute_subscript_kern if we have called - // compute_metrics first. - if (list.p[list.len-1]->is_simple()) - list.p[list.len-1]->compute_metrics(sty); - list.p[list.len-1]->compute_subscript_kern(); - printf(".nr " SUB_KERN_FORMAT " \\n[" SUB_KERN_FORMAT "]\n", - uid, list.p[list.len-1]->uid); -} - -void list_box::output() -{ - for (int i = 0; i < list.len; i++) { - if (i > 0) { - int n = compute_spacing(is_script, - list.p[i-1]->spacing_type, - list.p[i]->spacing_type); - if (n > 0) - printf("\\h'%dM'", n); - } - list.p[i]->output(); - } -} - -void list_box::handle_char_type(int st, int ft) -{ - for (int i = 0; i < list.len; i++) - list.p[i]->handle_char_type(st, ft); -} - -void list_box::debug_print() -{ - list.list_debug_print(" "); -} - -void list_box::check_tabs(int level) -{ - list.list_check_tabs(level); -} diff --git a/contrib/groff/src/preproc/eqn/main.cpp b/contrib/groff/src/preproc/eqn/main.cpp deleted file mode 100644 index 7971e2c2dc3c..000000000000 --- a/contrib/groff/src/preproc/eqn/main.cpp +++ /dev/null @@ -1,395 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002 - 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "eqn.h" -#include "stringclass.h" -#include "device.h" -#include "searchpath.h" -#include "macropath.h" -#include "htmlhint.h" -#include "pbox.h" -#include "ctype.h" - -#define STARTUP_FILE "eqnrc" - -extern int yyparse(); -extern "C" const char *Version_string; - -static char *delim_search (char *, int); -static int inline_equation (FILE *, string &, string &); - -char start_delim = '\0'; -char end_delim = '\0'; -int non_empty_flag; -int inline_flag; -int draw_flag = 0; -int one_size_reduction_flag = 0; -int compatible_flag = 0; -int no_newline_in_delim_flag = 0; -int html = 0; - - -int read_line(FILE *fp, string *p) -{ - p->clear(); - int c = -1; - while ((c = getc(fp)) != EOF) { - if (!invalid_input_char(c)) - *p += char(c); - else - error("invalid input character code `%1'", c); - if (c == '\n') - break; - } - current_lineno++; - return p->length() > 0; -} - -void do_file(FILE *fp, const char *filename) -{ - string linebuf; - string str; - printf(".lf 1 %s\n", filename); - current_filename = filename; - current_lineno = 0; - while (read_line(fp, &linebuf)) { - if (linebuf.length() >= 4 - && linebuf[0] == '.' && linebuf[1] == 'l' && linebuf[2] == 'f' - && (linebuf[3] == ' ' || linebuf[3] == '\n' || compatible_flag)) { - put_string(linebuf, stdout); - linebuf += '\0'; - if (interpret_lf_args(linebuf.contents() + 3)) - current_lineno--; - } - else if (linebuf.length() >= 4 - && linebuf[0] == '.' - && linebuf[1] == 'E' - && linebuf[2] == 'Q' - && (linebuf[3] == ' ' || linebuf[3] == '\n' - || compatible_flag)) { - put_string(linebuf, stdout); - int start_lineno = current_lineno + 1; - str.clear(); - for (;;) { - if (!read_line(fp, &linebuf)) - fatal("end of file before .EN"); - if (linebuf.length() >= 3 && linebuf[0] == '.' && linebuf[1] == 'E') { - if (linebuf[2] == 'N' - && (linebuf.length() == 3 || linebuf[3] == ' ' - || linebuf[3] == '\n' || compatible_flag)) - break; - else if (linebuf[2] == 'Q' && linebuf.length() > 3 - && (linebuf[3] == ' ' || linebuf[3] == '\n' - || compatible_flag)) - fatal("nested .EQ"); - } - str += linebuf; - } - str += '\0'; - start_string(); - init_lex(str.contents(), current_filename, start_lineno); - non_empty_flag = 0; - inline_flag = 0; - yyparse(); - restore_compatibility(); - if (non_empty_flag) { - printf(".lf %d\n", current_lineno - 1); - output_string(); - } - printf(".lf %d\n", current_lineno); - put_string(linebuf, stdout); - } - else if (start_delim != '\0' && linebuf.search(start_delim) >= 0 - && inline_equation(fp, linebuf, str)) - ; - else - put_string(linebuf, stdout); - } - current_filename = 0; - current_lineno = 0; -} - -// Handle an inline equation. Return 1 if it was an inline equation, -// otherwise. -static int inline_equation(FILE *fp, string &linebuf, string &str) -{ - linebuf += '\0'; - char *ptr = &linebuf[0]; - char *start = delim_search(ptr, start_delim); - if (!start) { - // It wasn't a delimiter after all. - linebuf.set_length(linebuf.length() - 1); // strip the '\0' - return 0; - } - start_string(); - inline_flag = 1; - for (;;) { - if (no_newline_in_delim_flag && strchr(start + 1, end_delim) == 0) { - error("missing `%1'", end_delim); - char *nl = strchr(start + 1, '\n'); - if (nl != 0) - *nl = '\0'; - do_text(ptr); - break; - } - int start_lineno = current_lineno; - *start = '\0'; - do_text(ptr); - ptr = start + 1; - str.clear(); - for (;;) { - char *end = strchr(ptr, end_delim); - if (end != 0) { - *end = '\0'; - str += ptr; - ptr = end + 1; - break; - } - str += ptr; - if (!read_line(fp, &linebuf)) - fatal("unterminated `%1' at line %2, looking for `%3'", - start_delim, start_lineno, end_delim); - linebuf += '\0'; - ptr = &linebuf[0]; - } - str += '\0'; - if (html) { - printf(".as1 %s ", LINE_STRING); - html_begin_suppress(); - printf("\n"); - } - init_lex(str.contents(), current_filename, start_lineno); - yyparse(); - if (html) { - printf(".as1 %s ", LINE_STRING); - html_end_suppress(); - printf("\n"); - } - start = delim_search(ptr, start_delim); - if (start == 0) { - char *nl = strchr(ptr, '\n'); - if (nl != 0) - *nl = '\0'; - do_text(ptr); - break; - } - } - restore_compatibility(); - printf(".lf %d\n", current_lineno); - output_string(); - printf(".lf %d\n", current_lineno + 1); - return 1; -} - -/* Search for delim. Skip over number register and string names etc. */ - -static char *delim_search(char *ptr, int delim) -{ - while (*ptr) { - if (*ptr == delim) - return ptr; - if (*ptr++ == '\\') { - switch (*ptr) { - case 'n': - case '*': - case 'f': - case 'g': - case 'k': - switch (*++ptr) { - case '\0': - case '\\': - break; - case '(': - if (*++ptr != '\\' && *ptr != '\0' - && *++ptr != '\\' && *ptr != '\0') - ptr++; - break; - case '[': - while (*++ptr != '\0') - if (*ptr == ']') { - ptr++; - break; - } - break; - default: - ptr++; - break; - } - break; - case '\\': - case '\0': - break; - default: - ptr++; - break; - } - } - } - return 0; -} - -void usage(FILE *stream) -{ - fprintf(stream, - "usage: %s [ -rvDCNR ] -dxx -fn -sn -pn -mn -Mdir -Ts [ files ... ]\n", - program_name); -} - -int main(int argc, char **argv) -{ - program_name = argv[0]; - static char stderr_buf[BUFSIZ]; - setbuf(stderr, stderr_buf); - int opt; - int load_startup_file = 1; - static const struct option long_options[] = { - { "help", no_argument, 0, CHAR_MAX + 1 }, - { "version", no_argument, 0, 'v' }, - { NULL, 0, 0, 0 } - }; - while ((opt = getopt_long(argc, argv, "DCRvd:f:p:s:m:T:M:rN", long_options, - NULL)) - != EOF) - switch (opt) { - case 'C': - compatible_flag = 1; - break; - case 'R': // don't load eqnrc - load_startup_file = 0; - break; - case 'M': - config_macro_path.command_line_dir(optarg); - break; - case 'v': - { - printf("GNU eqn (groff) version %s\n", Version_string); - exit(0); - break; - } - case 'd': - if (optarg[0] == '\0' || optarg[1] == '\0') - error("-d requires two character argument"); - else if (invalid_input_char(optarg[0])) - error("bad delimiter `%1'", optarg[0]); - else if (invalid_input_char(optarg[1])) - error("bad delimiter `%1'", optarg[1]); - else { - start_delim = optarg[0]; - end_delim = optarg[1]; - } - break; - case 'f': - set_gfont(optarg); - break; - case 'T': - device = optarg; - if (strcmp(device, "ps:html") == 0) { - device = "ps"; - html = 1; - } - break; - case 's': - if (!set_gsize(optarg)) - error("invalid size `%1'", optarg); - break; - case 'p': - { - int n; - if (sscanf(optarg, "%d", &n) == 1) - set_script_reduction(n); - else - error("bad size `%1'", optarg); - } - break; - case 'm': - { - int n; - if (sscanf(optarg, "%d", &n) == 1) - set_minimum_size(n); - else - error("bad size `%1'", optarg); - } - break; - case 'r': - one_size_reduction_flag = 1; - break; - case 'D': - warning("-D option is obsolete: use `set draw_lines 1' instead"); - draw_flag = 1; - break; - case 'N': - no_newline_in_delim_flag = 1; - break; - case CHAR_MAX + 1: // --help - usage(stdout); - exit(0); - break; - case '?': - usage(stderr); - exit(1); - break; - default: - assert(0); - } - init_table(device); - init_char_table(); - printf(".if !'\\*(.T'%s' " - ".if !'\\*(.T'html' " // the html device uses `-Tps' to render - // equations as images - ".tm warning: %s should have been given a `-T\\*(.T' option\n", - device, program_name); - printf(".if '\\*(.T'html' " - ".if !'%s'ps' " - ".tm warning: %s should have been given a `-Tps' option\n", - device, program_name); - printf(".if '\\*(.T'html' " - ".if !'%s'ps' " - ".tm warning: (it is advisable to invoke groff via: groff -Thtml -e)\n", - device); - if (load_startup_file) { - char *path; - FILE *fp = config_macro_path.open_file(STARTUP_FILE, &path); - if (fp) { - do_file(fp, path); - fclose(fp); - a_delete path; - } - } - if (optind >= argc) - do_file(stdin, "-"); - else - for (int i = optind; i < argc; i++) - if (strcmp(argv[i], "-") == 0) - do_file(stdin, "-"); - else { - errno = 0; - FILE *fp = fopen(argv[i], "r"); - if (!fp) - fatal("can't open `%1': %2", argv[i], strerror(errno)); - else { - do_file(fp, argv[i]); - fclose(fp); - } - } - if (ferror(stdout) || fflush(stdout) < 0) - fatal("output error"); - return 0; -} diff --git a/contrib/groff/src/preproc/eqn/mark.cpp b/contrib/groff/src/preproc/eqn/mark.cpp deleted file mode 100644 index 9fa65790c6f1..000000000000 --- a/contrib/groff/src/preproc/eqn/mark.cpp +++ /dev/null @@ -1,121 +0,0 @@ -// -*- 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "eqn.h" -#include "pbox.h" - -class mark_box : public pointer_box { -public: - mark_box(box *); - int compute_metrics(int); - void output(); - void debug_print(); -}; - -// we push down marks so that they don't interfere with spacing - -box *make_mark_box(box *p) -{ - list_box *b = p->to_list_box(); - if (b != 0) { - b->list.p[0] = make_mark_box(b->list.p[0]); - return b; - } - else - return new mark_box(p); -} - -mark_box::mark_box(box *pp) : pointer_box(pp) -{ -} - -void mark_box::output() -{ - p->output(); -} - -int mark_box::compute_metrics(int style) -{ - int res = p->compute_metrics(style); - if (res) - error("multiple marks and lineups"); - printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid); - printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid); - printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid); - printf(".nr " MARK_REG " 0\n"); - return FOUND_MARK; -} - -void mark_box::debug_print() -{ - fprintf(stderr, "mark { "); - p->debug_print(); - fprintf(stderr, " }"); -} - - -class lineup_box : public pointer_box { -public: - lineup_box(box *); - void output(); - int compute_metrics(int style); - void debug_print(); -}; - -// we push down lineups so that they don't interfere with spacing - -box *make_lineup_box(box *p) -{ - list_box *b = p->to_list_box(); - if (b != 0) { - b->list.p[0] = make_lineup_box(b->list.p[0]); - return b; - } - else - return new lineup_box(p); -} - -lineup_box::lineup_box(box *pp) : pointer_box(pp) -{ -} - -void lineup_box::output() -{ - p->output(); -} - -int lineup_box::compute_metrics(int style) -{ - int res = p->compute_metrics(style); - if (res) - error("multiple marks and lineups"); - printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid); - printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid); - printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid); - printf(".nr " MARK_REG " 0\n"); - return FOUND_LINEUP; -} - -void lineup_box::debug_print() -{ - fprintf(stderr, "lineup { "); - p->debug_print(); - fprintf(stderr, " }"); -} diff --git a/contrib/groff/src/preproc/eqn/neqn.man b/contrib/groff/src/preproc/eqn/neqn.man deleted file mode 100644 index 27261c419ccd..000000000000 --- a/contrib/groff/src/preproc/eqn/neqn.man +++ /dev/null @@ -1,43 +0,0 @@ -.ig -Copyright (C) 2001 Free Software Foundation, Inc. - -Permission is granted to make and distribute verbatim copies of -this manual provided the copyright notice and this permission notice -are preserved on all copies. - -Permission is granted to copy and distribute modified versions of this -manual under the conditions for verbatim copying, provided that the -entire resulting derived work is distributed under the terms of a -permission notice identical to this one. - -Permission is granted to copy and distribute translations of this -manual into another language, under the above conditions for modified -versions, except that this permission notice may be included in -translations approved by the Free Software Foundation instead of in -the original English. -.. -.TH @G@NEQN @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@" -.SH NAME -@g@neqn \- format equations for ascii output -.SH SYNOPSIS -.B @g@neqn -[@g@eqn options] -.SH DESCRIPTION -The -.B @g@neqn -program is actually just a shell script which invokes the -.BR @g@eqn (@MAN1EXT@) -command with the -.B ascii -output device. -.LP -Note that -.B @g@eqn -does not support low-resolution, typewriter-like devices (although it may -work adequately for very simple input). -.SH "SEE ALSO" -.BR @g@eqn (@MAN1EXT@) -. -.\" Local Variables: -.\" mode: nroff -.\" End: diff --git a/contrib/groff/src/preproc/eqn/neqn.sh b/contrib/groff/src/preproc/eqn/neqn.sh deleted file mode 100644 index 5390bba6c9ad..000000000000 --- a/contrib/groff/src/preproc/eqn/neqn.sh +++ /dev/null @@ -1,25 +0,0 @@ -#! /bin/sh -# Provision of this shell script should not be taken to imply that use of -# GNU eqn with groff -Tascii|-Tlatin1|-Tkoi8-r|-Tutf8|-Tcp1047 is supported. -# $FreeBSD$ - -# Default device. -case "${LC_ALL-${LC_CTYPE-${LANG}}}" in - *.UTF-8) - T=utf8 ;; - iso_8859_1 | *.ISO*8859-1 | *.ISO*8859-15) - T=latin1 ;; - *.IBM-1047) - T=cp1047 ;; - *.KOI8-R) - T=koi8-r ;; - *) - T=ascii ;; -esac - -@GROFF_BIN_PATH_SETUP@ -PATH="$GROFF_RUNTIME$PATH" -export PATH -exec @g@eqn -T${T} ${1+"$@"} - -# eof diff --git a/contrib/groff/src/preproc/eqn/other.cpp b/contrib/groff/src/preproc/eqn/other.cpp deleted file mode 100644 index 9f360df67912..000000000000 --- a/contrib/groff/src/preproc/eqn/other.cpp +++ /dev/null @@ -1,601 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2002 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "eqn.h" -#include "pbox.h" - -class accent_box : public pointer_box { -private: - box *ab; -public: - accent_box(box *, box *); - ~accent_box(); - int compute_metrics(int); - void output(); - void debug_print(); - void check_tabs(int); -}; - -box *make_accent_box(box *p, box *q) -{ - return new accent_box(p, q); -} - -accent_box::accent_box(box *pp, box *qq) : pointer_box(pp), ab(qq) -{ -} - -accent_box::~accent_box() -{ - delete ab; -} - -#if 0 -int accent_box::compute_metrics(int style) -{ - int r = p->compute_metrics(style); - p->compute_skew(); - ab->compute_metrics(style); - printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid); - printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid); - printf(".nr " SUP_RAISE_FORMAT " \\n[" HEIGHT_FORMAT "]-%dM>?0\n", - uid, p->uid, x_height); - printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+\\n[" - SUP_RAISE_FORMAT "]\n", - uid, ab->uid, uid); - return r; -} - -void accent_box::output() -{ - printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u+\\n[" - SKEW_FORMAT "]u'", - p->uid, ab->uid, p->uid); - printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); - ab->output(); - printf("\\h'-\\n[" WIDTH_FORMAT "]u'", ab->uid); - printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid); - printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u+\\n[" - SKEW_FORMAT "]u)'", - p->uid, ab->uid, p->uid); - p->output(); -} -#endif - -/* This version copes with the possibility of an accent's being wider -than its accentee. LEFT_WIDTH_FORMAT gives the distance from the -left edge of the resulting box to the middle of the accentee's box.*/ - -int accent_box::compute_metrics(int style) -{ - int r = p->compute_metrics(style); - p->compute_skew(); - ab->compute_metrics(style); - printf(".nr " LEFT_WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2" - ">?(\\n[" WIDTH_FORMAT "]/2-\\n[" SKEW_FORMAT "])\n", - uid, p->uid, ab->uid, p->uid); - printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2" - ">?(\\n[" WIDTH_FORMAT "]/2+\\n[" SKEW_FORMAT "])" - "+\\n[" LEFT_WIDTH_FORMAT "]\n", - uid, p->uid, ab->uid, p->uid, uid); - printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid); - printf(".nr " SUP_RAISE_FORMAT " \\n[" HEIGHT_FORMAT "]-%dM>?0\n", - uid, p->uid, x_height); - printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+\\n[" - SUP_RAISE_FORMAT "]\n", - uid, ab->uid, uid); - if (r) - printf(".nr " MARK_REG " +\\n[" LEFT_WIDTH_FORMAT "]" - "-(\\n[" WIDTH_FORMAT "]/2)'\n", - uid, p->uid); - return r; -} - -void accent_box::output() -{ - printf("\\Z" DELIMITER_CHAR); - printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u+\\n[" SKEW_FORMAT "]u" - "-(\\n[" WIDTH_FORMAT "]u/2u)'", - uid, p->uid, ab->uid); - printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); - ab->output(); - printf(DELIMITER_CHAR); - printf("\\Z" DELIMITER_CHAR); - printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'", - uid, p->uid); - p->output(); - printf(DELIMITER_CHAR); - printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid); -} - -void accent_box::check_tabs(int level) -{ - ab->check_tabs(level + 1); - p->check_tabs(level + 1); -} - -void accent_box::debug_print() -{ - fprintf(stderr, "{ "); - p->debug_print(); - fprintf(stderr, " } accent { "); - ab->debug_print(); - fprintf(stderr, " }"); -} - -class overline_char_box : public simple_box { -public: - overline_char_box(); - void output(); - void debug_print(); -}; - -overline_char_box::overline_char_box() -{ -} - -void overline_char_box::output() -{ - printf("\\v'-%dM/2u-%dM'", 7*default_rule_thickness, x_height); - printf((draw_flag ? "\\D'l%dM 0'" : "\\l'%dM\\&\\(ru'"), - accent_width); - printf("\\v'%dM/2u+%dM'", 7*default_rule_thickness, x_height); -} - -void overline_char_box::debug_print() -{ - fprintf(stderr, ""); -} - -class overline_box : public pointer_box { -public: - overline_box(box *); - int compute_metrics(int); - void output(); - void debug_print(); -}; - -box *make_overline_box(box *p) -{ - if (p->is_char()) - return new accent_box(p, new overline_char_box); - else - return new overline_box(p); -} - -overline_box::overline_box(box *pp) : pointer_box(pp) -{ -} - -int overline_box::compute_metrics(int style) -{ - int r = p->compute_metrics(cramped_style(style)); - // 9 - printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+%dM\n", - uid, p->uid, default_rule_thickness*5); - printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid); - printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid); - return r; -} - -void overline_box::output() -{ - // 9 - printf("\\Z" DELIMITER_CHAR); - printf("\\v'-\\n[" HEIGHT_FORMAT "]u-(%dM/2u)'", - p->uid, 7*default_rule_thickness); - if (draw_flag) - printf("\\D'l\\n[" WIDTH_FORMAT "]u 0'", p->uid); - else - printf("\\l'\\n[" WIDTH_FORMAT "]u\\&\\(ru'", p->uid); - printf(DELIMITER_CHAR); - p->output(); -} - -void overline_box::debug_print() -{ - fprintf(stderr, "{ "); - p->debug_print(); - fprintf(stderr, " } bar"); -} - -class uaccent_box : public pointer_box { - box *ab; -public: - uaccent_box(box *, box *); - ~uaccent_box(); - int compute_metrics(int); - void output(); - void compute_subscript_kern(); - void check_tabs(int); - void debug_print(); -}; - -box *make_uaccent_box(box *p, box *q) -{ - return new uaccent_box(p, q); -} - -uaccent_box::uaccent_box(box *pp, box *qq) -: pointer_box(pp), ab(qq) -{ -} - -uaccent_box::~uaccent_box() -{ - delete ab; -} - -int uaccent_box::compute_metrics(int style) -{ - int r = p->compute_metrics(style); - ab->compute_metrics(style); - printf(".nr " LEFT_WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2" - ">?(\\n[" WIDTH_FORMAT "]/2)\n", - uid, p->uid, ab->uid); - printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2" - ">?(\\n[" WIDTH_FORMAT "]/2)" - "+\\n[" LEFT_WIDTH_FORMAT "]\n", - uid, p->uid, ab->uid, uid); - printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid); - printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]" - "+\\n[" DEPTH_FORMAT "]\n", - uid, p->uid, ab->uid); - if (r) - printf(".nr " MARK_REG " +\\n[" LEFT_WIDTH_FORMAT "]" - "-(\\n[" WIDTH_FORMAT "]/2)'\n", - uid, p->uid); - return r; -} - -void uaccent_box::output() -{ - printf("\\Z" DELIMITER_CHAR); - printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'", - uid, ab->uid); - printf("\\v'\\n[" DEPTH_FORMAT "]u'", p->uid); - ab->output(); - printf(DELIMITER_CHAR); - printf("\\Z" DELIMITER_CHAR); - printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'", - uid, p->uid); - p->output(); - printf(DELIMITER_CHAR); - printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid); -} - -void uaccent_box::check_tabs(int level) -{ - ab->check_tabs(level + 1); - p->check_tabs(level + 1); -} - -void uaccent_box::compute_subscript_kern() -{ - box::compute_subscript_kern(); // want 0 subscript kern -} - -void uaccent_box::debug_print() -{ - fprintf(stderr, "{ "); - p->debug_print(); - fprintf(stderr, " } uaccent { "); - ab->debug_print(); - fprintf(stderr, " }"); -} - -class underline_char_box : public simple_box { -public: - underline_char_box(); - void output(); - void debug_print(); -}; - -underline_char_box::underline_char_box() -{ -} - -void underline_char_box::output() -{ - printf("\\v'%dM/2u'", 7*default_rule_thickness); - printf((draw_flag ? "\\D'l%dM 0'" : "\\l'%dM\\&\\(ru'"), - accent_width); - printf("\\v'-%dM/2u'", 7*default_rule_thickness); -} - -void underline_char_box::debug_print() -{ - fprintf(stderr, ""); -} - - -class underline_box : public pointer_box { -public: - underline_box(box *); - int compute_metrics(int); - void output(); - void compute_subscript_kern(); - void debug_print(); -}; - -box *make_underline_box(box *p) -{ - if (p->is_char()) - return new uaccent_box(p, new underline_char_box); - else - return new underline_box(p); -} - -underline_box::underline_box(box *pp) : pointer_box(pp) -{ -} - -int underline_box::compute_metrics(int style) -{ - int r = p->compute_metrics(style); - // 10 - printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]+%dM\n", - uid, p->uid, default_rule_thickness*5); - printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid); - printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid); - return r; -} - -void underline_box::output() -{ - // 10 - printf("\\Z" DELIMITER_CHAR); - printf("\\v'\\n[" DEPTH_FORMAT "]u+(%dM/2u)'", - p->uid, 7*default_rule_thickness); - if (draw_flag) - printf("\\D'l\\n[" WIDTH_FORMAT "]u 0'", p->uid); - else - printf("\\l'\\n[" WIDTH_FORMAT "]u\\&\\(ru'", p->uid); - printf(DELIMITER_CHAR); - p->output(); -} - -// we want an underline box to have 0 subscript kern - -void underline_box::compute_subscript_kern() -{ - box::compute_subscript_kern(); -} - -void underline_box::debug_print() -{ - fprintf(stderr, "{ "); - p->debug_print(); - fprintf(stderr, " } under"); -} - -size_box::size_box(char *s, box *pp) : pointer_box(pp), size(s) -{ -} - -int size_box::compute_metrics(int style) -{ - printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid); - printf(".ps %s\n", size); - printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid); - int r = p->compute_metrics(style); - printf(".ps \\n[" SIZE_FORMAT "]u\n", uid); - printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid); - printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid); - printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid); - return r; -} - -void size_box::output() -{ - printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid); - p->output(); - printf("\\s[\\n[" SIZE_FORMAT "]u]", uid); -} - -size_box::~size_box() -{ - a_delete size; -} - -void size_box::debug_print() -{ - fprintf(stderr, "size %s { ", size); - p->debug_print(); - fprintf(stderr, " }"); -} - - -font_box::font_box(char *s, box *pp) : pointer_box(pp), f(s) -{ -} - -font_box::~font_box() -{ - a_delete f; -} - -int font_box::compute_metrics(int style) -{ - const char *old_roman_font = current_roman_font; - current_roman_font = f; - printf(".nr " FONT_FORMAT " \\n[.f]\n", uid); - printf(".ft %s\n", f); - int r = p->compute_metrics(style); - current_roman_font = old_roman_font; - printf(".ft \\n[" FONT_FORMAT "]\n", uid); - printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid); - printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid); - printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid); - return r; -} - -void font_box::output() -{ - printf("\\f[%s]", f); - const char *old_roman_font = current_roman_font; - current_roman_font = f; - p->output(); - current_roman_font = old_roman_font; - printf("\\f[\\n[" FONT_FORMAT "]]", uid); -} - -void font_box::debug_print() -{ - fprintf(stderr, "font %s { ", f); - p->debug_print(); - fprintf(stderr, " }"); -} - -fat_box::fat_box(box *pp) : pointer_box(pp) -{ -} - -int fat_box::compute_metrics(int style) -{ - int r = p->compute_metrics(style); - printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]+%dM\n", - uid, p->uid, fat_offset); - printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid); - printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid); - return r; -} - -void fat_box::output() -{ - p->output(); - printf("\\h'-\\n[" WIDTH_FORMAT "]u'", p->uid); - printf("\\h'%dM'", fat_offset); - p->output(); -} - - -void fat_box::debug_print() -{ - fprintf(stderr, "fat { "); - p->debug_print(); - fprintf(stderr, " }"); -} - - -vmotion_box::vmotion_box(int i, box *pp) : pointer_box(pp), n(i) -{ -} - -int vmotion_box::compute_metrics(int style) -{ - int r = p->compute_metrics(style); - printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid); - if (n > 0) { - printf(".nr " HEIGHT_FORMAT " %dM+\\n[" HEIGHT_FORMAT "]\n", - uid, n, p->uid); - printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid); - } - else { - printf(".nr " DEPTH_FORMAT " %dM+\\n[" DEPTH_FORMAT "]>?0\n", - uid, -n, p->uid); - printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", - uid, p->uid); - } - return r; -} - -void vmotion_box::output() -{ - printf("\\v'%dM'", -n); - p->output(); - printf("\\v'%dM'", n); -} - -void vmotion_box::debug_print() -{ - if (n >= 0) - fprintf(stderr, "up %d { ", n); - else - fprintf(stderr, "down %d { ", -n); - p->debug_print(); - fprintf(stderr, " }"); -} - -hmotion_box::hmotion_box(int i, box *pp) : pointer_box(pp), n(i) -{ -} - -int hmotion_box::compute_metrics(int style) -{ - int r = p->compute_metrics(style); - printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]+%dM\n", - uid, p->uid, n); - printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid); - printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid); - if (r) - printf(".nr " MARK_REG " +%dM\n", n); - return r; -} - -void hmotion_box::output() -{ - printf("\\h'%dM'", n); - p->output(); -} - -void hmotion_box::debug_print() -{ - if (n >= 0) - fprintf(stderr, "fwd %d { ", n); - else - fprintf(stderr, "back %d { ", -n); - p->debug_print(); - fprintf(stderr, " }"); -} - -vcenter_box::vcenter_box(box *pp) : pointer_box(pp) -{ -} - -int vcenter_box::compute_metrics(int style) -{ - int r = p->compute_metrics(style); - printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid); - printf(".nr " SUP_RAISE_FORMAT " \\n[" DEPTH_FORMAT "]-\\n[" - HEIGHT_FORMAT "]/2+%dM\n", - uid, p->uid, p->uid, axis_height); - printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+\\n[" - SUP_RAISE_FORMAT "]>?0\n", uid, p->uid, uid); - printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]-\\n[" - SUP_RAISE_FORMAT "]>?0\n", uid, p->uid, uid); - - return r; -} - -void vcenter_box::output() -{ - printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); - p->output(); - printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid); -} - -void vcenter_box::debug_print() -{ - fprintf(stderr, "vcenter { "); - p->debug_print(); - fprintf(stderr, " }"); -} - diff --git a/contrib/groff/src/preproc/eqn/over.cpp b/contrib/groff/src/preproc/eqn/over.cpp deleted file mode 100644 index 302c5b5d50c0..000000000000 --- a/contrib/groff/src/preproc/eqn/over.cpp +++ /dev/null @@ -1,197 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002 - 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "eqn.h" -#include "pbox.h" - -class over_box : public box { -private: - int reduce_size; - box *num; - box *den; -public: - over_box(int small, box *, box *); - ~over_box(); - void debug_print(); - int compute_metrics(int); - void output(); - void check_tabs(int); -}; - -box *make_over_box(box *pp, box *qq) -{ - return new over_box(0, pp, qq); -} - -box *make_small_over_box(box *pp, box *qq) -{ - return new over_box(1, pp, qq); -} - -over_box::over_box(int is_small, box *pp, box *qq) -: reduce_size(is_small), num(pp), den(qq) -{ - spacing_type = INNER_TYPE; -} - -over_box::~over_box() -{ - delete num; - delete den; -} - -int over_box::compute_metrics(int style) -{ - if (reduce_size) { - style = script_style(style); - printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid); - set_script_size(); - printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid); - } - int mark_uid = 0; - int res = num->compute_metrics(style); - if (res) - mark_uid = num->uid; - int r = den->compute_metrics(cramped_style(style)); - if (r && res) - error("multiple marks and lineups"); - else { - mark_uid = den->uid; - res = r; - } - if (reduce_size) - printf(".ps \\n[" SIZE_FORMAT "]u\n", uid); - printf(".nr " WIDTH_FORMAT " (\\n[" WIDTH_FORMAT "]>?\\n[" WIDTH_FORMAT "]", - uid, num->uid, den->uid); - // allow for \(ru being wider than both the numerator and denominator - if (!draw_flag) - fputs(">?\\w" DELIMITER_CHAR "\\(ru" DELIMITER_CHAR, stdout); - printf(")+%dM\n", null_delimiter_space*2 + over_hang*2); - // 15b - printf(".nr " SUP_RAISE_FORMAT " %dM\n", - uid, (reduce_size ? num2 : num1)); - printf(".nr " SUB_LOWER_FORMAT " %dM\n", - uid, (reduce_size ? denom2 : denom1)); - - // 15d - printf(".nr " SUP_RAISE_FORMAT " +(\\n[" DEPTH_FORMAT - "]-\\n[" SUP_RAISE_FORMAT "]+%dM+(%dM/2)+%dM)>?0\n", - uid, num->uid, uid, axis_height, default_rule_thickness, - default_rule_thickness*(reduce_size ? 1 : 3)); - printf(".nr " SUB_LOWER_FORMAT " +(\\n[" HEIGHT_FORMAT - "]-\\n[" SUB_LOWER_FORMAT "]-%dM+(%dM/2)+%dM)>?0\n", - uid, den->uid, uid, axis_height, default_rule_thickness, - default_rule_thickness*(reduce_size ? 1 : 3)); - - - printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n[" - HEIGHT_FORMAT "]\n", - uid, uid, num->uid); - printf(".nr " DEPTH_FORMAT " \\n[" SUB_LOWER_FORMAT "]+\\n[" - DEPTH_FORMAT "]\n", - uid, uid, den->uid); - if (res) - printf(".nr " MARK_REG " +(\\n[" WIDTH_FORMAT "]-\\n[" - WIDTH_FORMAT "]/2)\n", uid, mark_uid); - return res; -} - -#define USE_Z - -void over_box::output() -{ - if (reduce_size) - printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid); -#ifdef USE_Z - printf("\\Z" DELIMITER_CHAR); -#endif - // move up to the numerator baseline - printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); - // move across so that it's centered - printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", - uid, num->uid); - - // print the numerator - num->output(); - -#ifdef USE_Z - printf(DELIMITER_CHAR); -#else - // back again - printf("\\h'-\\n[" WIDTH_FORMAT "]u'", num->uid); - printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'", - uid, num->uid); - // down again - printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid); -#endif -#ifdef USE_Z - printf("\\Z" DELIMITER_CHAR); -#endif - // move down to the denominator baseline - printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid); - - // move across so that it's centered - printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", - uid, den->uid); - - // print the the denominator - den->output(); - -#ifdef USE_Z - printf(DELIMITER_CHAR); -#else - // back again - printf("\\h'-\\n[" WIDTH_FORMAT "]u'", den->uid); - printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'", - uid, den->uid); - // up again - printf("\\v'-\\n[" SUB_LOWER_FORMAT "]u'", uid); -#endif - if (reduce_size) - printf("\\s[\\n[" SIZE_FORMAT "]u]", uid); - // draw the line - printf("\\h'%dM'", null_delimiter_space); - printf("\\v'-%dM'", axis_height); - fputs(draw_flag ? "\\D'l" : "\\l'", stdout); - printf("\\n[" WIDTH_FORMAT "]u-%dM", - uid, 2*null_delimiter_space); - fputs(draw_flag ? " 0'" : "\\&\\(ru'", stdout); - printf("\\v'%dM'", axis_height); - printf("\\h'%dM'", null_delimiter_space); -} - -void over_box::debug_print() -{ - fprintf(stderr, "{ "); - num->debug_print(); - if (reduce_size) - fprintf(stderr, " } smallover { "); - else - fprintf(stderr, " } over { "); - den->debug_print(); - fprintf(stderr, " }"); -} - -void over_box::check_tabs(int level) -{ - num->check_tabs(level + 1); - den->check_tabs(level + 1); -} diff --git a/contrib/groff/src/preproc/eqn/pbox.h b/contrib/groff/src/preproc/eqn/pbox.h deleted file mode 100644 index f100f2165662..000000000000 --- a/contrib/groff/src/preproc/eqn/pbox.h +++ /dev/null @@ -1,141 +0,0 @@ -// -*- 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -extern int fat_offset; - -extern int over_hang; -extern int accent_width; - -extern int delimiter_factor; -extern int delimiter_shortfall; - -extern int null_delimiter_space; -extern int script_space; -extern int thin_space; -extern int medium_space; -extern int thick_space; - -extern int num1; -extern int num2; -// we don't use num3, because we don't have \atop -extern int denom1; -extern int denom2; -extern int axis_height; -extern int sup1; -extern int sup2; -extern int sup3; -extern int default_rule_thickness; -extern int sub1; -extern int sub2; -extern int sup_drop; -extern int sub_drop; -extern int x_height; -extern int big_op_spacing1; -extern int big_op_spacing2; -extern int big_op_spacing3; -extern int big_op_spacing4; -extern int big_op_spacing5; - -extern int baseline_sep; -extern int shift_down; -extern int column_sep; -extern int matrix_side_sep; - -// ms.eqn relies on this! - -#define LINE_STRING "10" -#define MARK_OR_LINEUP_FLAG_REG "MK" - -#define WIDTH_FORMAT PREFIX "w%d" -#define HEIGHT_FORMAT PREFIX "h%d" -#define DEPTH_FORMAT PREFIX "d%d" -#define TOTAL_FORMAT PREFIX "t%d" -#define SIZE_FORMAT PREFIX "z%d" -#define SMALL_SIZE_FORMAT PREFIX "Z%d" -#define SUP_RAISE_FORMAT PREFIX "p%d" -#define SUB_LOWER_FORMAT PREFIX "b%d" -#define SUB_KERN_FORMAT PREFIX "k%d" -#define FONT_FORMAT PREFIX "f%d" -#define SKEW_FORMAT PREFIX "s%d" -#define LEFT_WIDTH_FORMAT PREFIX "lw%d" -#define LEFT_DELIM_STRING_FORMAT PREFIX "l%d" -#define RIGHT_DELIM_STRING_FORMAT PREFIX "r%d" -#define SQRT_STRING_FORMAT PREFIX "sqr%d" -#define SQRT_WIDTH_FORMAT PREFIX "sq%d" -#define BASELINE_SEP_FORMAT PREFIX "bs%d" -// this needs two parameters, the uid and the column index -#define COLUMN_WIDTH_FORMAT PREFIX "cw%d,%d" - -#define BAR_STRING PREFIX "sqb" -#define TEMP_REG PREFIX "temp" -#define MARK_REG PREFIX "mark" -#define MARK_WIDTH_REG PREFIX "mwidth" -#define SAVED_MARK_REG PREFIX "smark" -#define MAX_SIZE_REG PREFIX "mxsz" -#define REPEAT_APPEND_STRING_MACRO PREFIX "ras" -#define TOP_HEIGHT_REG PREFIX "th" -#define TOP_DEPTH_REG PREFIX "td" -#define MID_HEIGHT_REG PREFIX "mh" -#define MID_DEPTH_REG PREFIX "md" -#define BOT_HEIGHT_REG PREFIX "bh" -#define BOT_DEPTH_REG PREFIX "bd" -#define EXT_HEIGHT_REG PREFIX "eh" -#define EXT_DEPTH_REG PREFIX "ed" -#define TOTAL_HEIGHT_REG PREFIX "tot" -#define DELTA_REG PREFIX "delta" -#define DELIM_STRING PREFIX "delim" -#define DELIM_WIDTH_REG PREFIX "dwidth" -#define SAVED_FONT_REG PREFIX "sfont" -#define SAVED_PREV_FONT_REG PREFIX "spfont" -#define SAVED_INLINE_FONT_REG PREFIX "sifont" -#define SAVED_INLINE_PREV_FONT_REG PREFIX "sipfont" -#define SAVED_SIZE_REG PREFIX "ssize" -#define SAVED_INLINE_SIZE_REG PREFIX "sisize" -#define SAVED_INLINE_PREV_SIZE_REG PREFIX "sipsize" -#define SAVE_FONT_STRING PREFIX "sfont" -#define RESTORE_FONT_STRING PREFIX "rfont" -#define INDEX_REG PREFIX "i" -#define TEMP_MACRO PREFIX "tempmac" - -#define DELIMITER_CHAR "\\(EQ" - -const int CRAMPED_SCRIPT_STYLE = 0; -const int SCRIPT_STYLE = 1; -const int CRAMPED_DISPLAY_STYLE = 2; -const int DISPLAY_STYLE = 3; - -extern int script_style(int); -extern int cramped_style(int); - -const int ORDINARY_TYPE = 0; -const int OPERATOR_TYPE = 1; -const int BINARY_TYPE = 2; -const int RELATION_TYPE = 3; -const int OPENING_TYPE = 4; -const int CLOSING_TYPE = 5; -const int PUNCTUATION_TYPE = 6; -const int INNER_TYPE = 7; -const int SUPPRESS_TYPE = 8; - -void set_script_size(); - -enum { HINT_PREV_IS_ITALIC = 01, HINT_NEXT_IS_ITALIC = 02 }; - -extern const char *current_roman_font; diff --git a/contrib/groff/src/preproc/eqn/pile.cpp b/contrib/groff/src/preproc/eqn/pile.cpp deleted file mode 100644 index 10d1708809af..000000000000 --- a/contrib/groff/src/preproc/eqn/pile.cpp +++ /dev/null @@ -1,293 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2004 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ -// piles and matrices - -#include "eqn.h" -#include "pbox.h" - -// SUP_RAISE_FORMAT gives the first baseline -// BASELINE_SEP_FORMAT gives the separation between baselines - -int pile_box::compute_metrics(int style) -{ - int i; - for (i = 0; i < col.len; i++) - col.p[i]->compute_metrics(style); - printf(".nr " WIDTH_FORMAT " 0", uid); - for (i = 0; i < col.len; i++) - printf(">?\\n[" WIDTH_FORMAT "]", col.p[i]->uid); - printf("\n"); - printf(".nr " BASELINE_SEP_FORMAT " %dM", - uid, baseline_sep+col.space); - for (i = 1; i < col.len; i++) - printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)", - col.p[i-1]->uid, col.p[i]->uid, default_rule_thickness*5); - // round it so that it's a multiple of the vertical resolution - printf("/\\n(.V+(\\n(.V/2)*\\n(.V\n"); - - printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2" - "+%dM\n", - uid, uid, col.len-1, axis_height - shift_down); - printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n[" - HEIGHT_FORMAT "]\n", - uid, uid, col.p[0]->uid); - printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d+\\n[" - DEPTH_FORMAT "]-\\n[" SUP_RAISE_FORMAT "]\n", - uid, uid, col.len-1, col.p[col.len-1]->uid, uid); - return FOUND_NOTHING; -} - -void pile_box::output() -{ - int i; - printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); - for (i = 0; i < col.len; i++) { - switch (col.align) { - case LEFT_ALIGN: - break; - case CENTER_ALIGN: - printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", - uid, col.p[i]->uid); - break; - case RIGHT_ALIGN: - printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'", - uid, col.p[i]->uid); - break; - default: - assert(0); - } - col.p[i]->output(); - printf("\\h'-\\n[" WIDTH_FORMAT "]u'", col.p[i]->uid); - switch (col.align) { - case LEFT_ALIGN: - break; - case CENTER_ALIGN: - printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", - col.p[i]->uid, uid); - break; - case RIGHT_ALIGN: - printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'", - col.p[i]->uid, uid); - break; - default: - assert(0); - } - if (i != col.len - 1) - printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid); - } - printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid); - printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", col.len - 1, uid); - printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid); -} - -pile_box::pile_box(box *pp) : col(pp) -{ -} - -void pile_box::check_tabs(int level) -{ - col.list_check_tabs(level); -} - -void pile_box::debug_print() -{ - col.debug_print("pile"); -} - -int matrix_box::compute_metrics(int style) -{ - int i, j; - int max_len = 0; - int space = 0; - for (i = 0; i < len; i++) { - for (j = 0; j < p[i]->len; j++) - p[i]->p[j]->compute_metrics(style); - if (p[i]->len > max_len) - max_len = p[i]->len; - if (p[i]->space > space) - space = p[i]->space; - } - for (i = 0; i < len; i++) { - printf(".nr " COLUMN_WIDTH_FORMAT " 0", uid, i); - for (j = 0; j < p[i]->len; j++) - printf(">?\\n[" WIDTH_FORMAT "]", p[i]->p[j]->uid); - printf("\n"); - } - printf(".nr " WIDTH_FORMAT " %dM", - uid, column_sep*(len-1)+2*matrix_side_sep); - for (i = 0; i < len; i++) - printf("+\\n[" COLUMN_WIDTH_FORMAT "]", uid, i); - printf("\n"); - printf(".nr " BASELINE_SEP_FORMAT " %dM", - uid, baseline_sep+space); - for (i = 0; i < len; i++) - for (j = 1; j < p[i]->len; j++) - printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)", - p[i]->p[j-1]->uid, p[i]->p[j]->uid, default_rule_thickness*5); - // round it so that it's a multiple of the vertical resolution - printf("/\\n(.V+(\\n(.V/2)*\\n(.V\n"); - printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2" - "+%dM\n", - uid, uid, max_len-1, axis_height - shift_down); - printf(".nr " HEIGHT_FORMAT " 0\\n[" SUP_RAISE_FORMAT "]+(0", - uid, uid); - for (i = 0; i < len; i++) - printf(">?\\n[" HEIGHT_FORMAT "]", p[i]->p[0]->uid); - printf(")>?0\n"); - printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d-\\n[" - SUP_RAISE_FORMAT "]+(0", - uid, uid, max_len-1, uid); - for (i = 0; i < len; i++) - if (p[i]->len == max_len) - printf(">?\\n[" DEPTH_FORMAT "]", p[i]->p[max_len-1]->uid); - printf(")>?0\n"); - return FOUND_NOTHING; -} - -void matrix_box::output() -{ - printf("\\h'%dM'", matrix_side_sep); - for (int i = 0; i < len; i++) { - int j; - printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); - for (j = 0; j < p[i]->len; j++) { - switch (p[i]->align) { - case LEFT_ALIGN: - break; - case CENTER_ALIGN: - printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", - uid, i, p[i]->p[j]->uid); - break; - case RIGHT_ALIGN: - printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'", - uid, i, p[i]->p[j]->uid); - break; - default: - assert(0); - } - p[i]->p[j]->output(); - printf("\\h'-\\n[" WIDTH_FORMAT "]u'", p[i]->p[j]->uid); - switch (p[i]->align) { - case LEFT_ALIGN: - break; - case CENTER_ALIGN: - printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u/2u'", - p[i]->p[j]->uid, uid, i); - break; - case RIGHT_ALIGN: - printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u'", - p[i]->p[j]->uid, uid, i); - break; - default: - assert(0); - } - if (j != p[i]->len - 1) - printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid); - } - printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid); - printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", p[i]->len - 1, uid); - printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u'", uid, i); - if (i != len - 1) - printf("\\h'%dM'", column_sep); - } - printf("\\h'%dM'", matrix_side_sep); -} - -matrix_box::matrix_box(column *pp) -{ - p = new column*[10]; - for (int i = 0; i < 10; i++) - p[i] = 0; - maxlen = 10; - len = 1; - p[0] = pp; -} - -matrix_box::~matrix_box() -{ - for (int i = 0; i < len; i++) - delete p[i]; - a_delete p; -} - -void matrix_box::append(column *pp) -{ - if (len + 1 > maxlen) { - column **oldp = p; - maxlen *= 2; - p = new column*[maxlen]; - memcpy(p, oldp, sizeof(column*)*len); - a_delete oldp; - } - p[len++] = pp; -} - -void matrix_box::check_tabs(int level) -{ - for (int i = 0; i < len; i++) - p[i]->list_check_tabs(level); -} - -void matrix_box::debug_print() -{ - fprintf(stderr, "matrix { "); - p[0]->debug_print("col"); - for (int i = 1; i < len; i++) { - fprintf(stderr, " "); - p[i]->debug_print("col"); - } - fprintf(stderr, " }"); -} - -column::column(box *pp) : box_list(pp), align(CENTER_ALIGN), space(0) -{ -} - -void column::set_alignment(alignment a) -{ - align = a; -} - -void column::set_space(int n) -{ - space = n; -} - -void column::debug_print(const char *s) -{ - char c = '\0'; // shut up -Wall - switch (align) { - case LEFT_ALIGN: - c = 'l'; - break; - case RIGHT_ALIGN: - c = 'r'; - break; - case CENTER_ALIGN: - c = 'c'; - break; - default: - assert(0); - } - fprintf(stderr, "%c%s %d { ", c, s, space); - list_debug_print(" above "); - fprintf(stderr, " }"); -} - diff --git a/contrib/groff/src/preproc/eqn/script.cpp b/contrib/groff/src/preproc/eqn/script.cpp deleted file mode 100644 index a9de7428718b..000000000000 --- a/contrib/groff/src/preproc/eqn/script.cpp +++ /dev/null @@ -1,222 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2002, 2004 - 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "eqn.h" -#include "pbox.h" - -class script_box : public pointer_box { -private: - box *sub; - box *sup; -public: - script_box(box *, box *, box *); - ~script_box(); - int compute_metrics(int); - void output(); - void debug_print(); - int left_is_italic(); - void hint(unsigned); - void check_tabs(int); -}; - -/* The idea is that the script should attach to the rightmost box -of a list. For example, given `2x sup 3', the superscript should -attach to `x' rather than `2x'. */ - -box *make_script_box(box *nuc, box *sub, box *sup) -{ - list_box *b = nuc->to_list_box(); - if (b != 0) { - b->list.p[b->list.len-1] = make_script_box(b->list.p[b->list.len - 1], - sub, - sup); - return b; - } - else - return new script_box(nuc, sub, sup); -} - -script_box::script_box(box *pp, box *qq, box *rr) -: pointer_box(pp), sub(qq), sup(rr) -{ -} - -script_box::~script_box() -{ - delete sub; - delete sup; -} - -int script_box::left_is_italic() -{ - return p->left_is_italic(); -} - -int script_box::compute_metrics(int style) -{ - int res = p->compute_metrics(style); - p->compute_subscript_kern(); - printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid); - if (!(style <= SCRIPT_STYLE && one_size_reduction_flag)) - set_script_size(); - printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid); - if (sub != 0) - sub->compute_metrics(cramped_style(script_style(style))); - if (sup != 0) - sup->compute_metrics(script_style(style)); - // 18a - if (p->is_char()) { - printf(".nr " SUP_RAISE_FORMAT " 0\n", uid); - printf(".nr " SUB_LOWER_FORMAT " 0\n", uid); - } - else { - printf(".nr " SUP_RAISE_FORMAT " \\n[" HEIGHT_FORMAT "]-%dM>?0\n", - uid, p->uid, sup_drop); - printf(".nr " SUB_LOWER_FORMAT " \\n[" DEPTH_FORMAT "]+%dM\n", - uid, p->uid, sub_drop); - } - printf(".ps \\n[" SIZE_FORMAT "]u\n", uid); - if (sup == 0) { - assert(sub != 0); - // 18b - printf(".nr " SUB_LOWER_FORMAT " \\n[" SUB_LOWER_FORMAT "]>?%dM>?(\\n[" - HEIGHT_FORMAT "]-(%dM*4/5))\n", - uid, uid, sub1, sub->uid, x_height); - } - else { - // sup != 0 - // 18c - int pos; - if (style == DISPLAY_STYLE) - pos = sup1; - else if (style & 1) // not cramped - pos = sup2; - else - pos = sup3; - printf(".nr " SUP_RAISE_FORMAT " \\n[" SUP_RAISE_FORMAT - "]>?%dM>?(\\n[" DEPTH_FORMAT "]+(%dM/4))\n", - uid, uid, pos, sup->uid, x_height); - // 18d - if (sub != 0) { - printf(".nr " SUB_LOWER_FORMAT " \\n[" SUB_LOWER_FORMAT "]>?%dM\n", - uid, uid, sub2); - // 18e - printf(".nr " TEMP_REG " \\n[" DEPTH_FORMAT "]-\\n[" - SUP_RAISE_FORMAT "]+\\n[" HEIGHT_FORMAT "]-\\n[" - SUB_LOWER_FORMAT "]+(4*%dM)\n", - sup->uid, uid, sub->uid, uid, default_rule_thickness); - printf(".if \\n[" TEMP_REG "] \\{"); - printf(".nr " SUB_LOWER_FORMAT " +\\n[" TEMP_REG "]\n", uid); - printf(".nr " TEMP_REG " (%dM*4/5)-\\n[" SUP_RAISE_FORMAT - "]+\\n[" DEPTH_FORMAT "]>?0\n", - x_height, uid, sup->uid); - printf(".nr " SUP_RAISE_FORMAT " +\\n[" TEMP_REG "]\n", uid); - printf(".nr " SUB_LOWER_FORMAT " -\\n[" TEMP_REG "]\n", uid); - printf(".\\}\n"); - } - } - printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]", uid, p->uid); - if (sub != 0 && sup != 0) - printf("+((\\n[" WIDTH_FORMAT "]-\\n[" SUB_KERN_FORMAT "]>?\\n[" - WIDTH_FORMAT "])+%dM)>?0\n", - sub->uid, p->uid, sup->uid, script_space); - else if (sub != 0) - printf("+(\\n[" WIDTH_FORMAT "]-\\n[" SUB_KERN_FORMAT "]+%dM)>?0\n", - sub->uid, p->uid, script_space); - else if (sup != 0) - printf("+(\\n[" WIDTH_FORMAT "]+%dM)>?0\n", sup->uid, script_space); - else - printf("\n"); - printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]", - uid, p->uid); - if (sup != 0) - printf(">?(\\n[" SUP_RAISE_FORMAT "]+\\n[" HEIGHT_FORMAT "])", - uid, sup->uid); - if (sub != 0) - printf(">?(-\\n[" SUB_LOWER_FORMAT "]+\\n[" HEIGHT_FORMAT "])", - uid, sub->uid); - printf("\n"); - printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]", - uid, p->uid); - if (sub != 0) - printf(">?(\\n[" SUB_LOWER_FORMAT "]+\\n[" DEPTH_FORMAT "])", - uid, sub->uid); - if (sup != 0) - printf(">?(-\\n[" SUP_RAISE_FORMAT "]+\\n[" DEPTH_FORMAT "])", - uid, sup->uid); - printf("\n"); - return res; -} - -void script_box::output() -{ - p->output(); - if (sup != 0) { - printf("\\Z" DELIMITER_CHAR); - printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); - printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid); - sup->output(); - printf("\\s[\\n[" SIZE_FORMAT "]u]", uid); - printf(DELIMITER_CHAR); - } - if (sub != 0) { - printf("\\Z" DELIMITER_CHAR); - printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid); - printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid); - printf("\\h'-\\n[" SUB_KERN_FORMAT "]u'", p->uid); - sub->output(); - printf("\\s[\\n[" SIZE_FORMAT "]u]", uid); - printf(DELIMITER_CHAR); - } - printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'", - uid, p->uid); -} - -void script_box::hint(unsigned flags) -{ - p->hint(flags & ~HINT_NEXT_IS_ITALIC); -} - -void script_box::debug_print() -{ - fprintf(stderr, "{ "); - p->debug_print(); - fprintf(stderr, " }"); - if (sub) { - fprintf(stderr, " sub { "); - sub->debug_print(); - fprintf(stderr, " }"); - } - if (sup) { - fprintf(stderr, " sup { "); - sup->debug_print(); - fprintf(stderr, " }"); - } -} - -void script_box::check_tabs(int level) -{ - if (sup) - sup->check_tabs(level + 1); - if (sub) - sub->check_tabs(level + 1); - p->check_tabs(level); -} diff --git a/contrib/groff/src/preproc/eqn/special.cpp b/contrib/groff/src/preproc/eqn/special.cpp deleted file mode 100644 index 172686a505b5..000000000000 --- a/contrib/groff/src/preproc/eqn/special.cpp +++ /dev/null @@ -1,115 +0,0 @@ -// -*- 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "eqn.h" -#include "pbox.h" - -#define STRING_FORMAT PREFIX "str%d" - -#define SPECIAL_STRING "0s" -#define SPECIAL_WIDTH_REG "0w" -#define SPECIAL_HEIGHT_REG "0h" -#define SPECIAL_DEPTH_REG "0d" -#define SPECIAL_SUB_KERN_REG "0skern" -#define SPECIAL_SKEW_REG "0skew" - -/* -For example: - -.de Cl -.ds 0s \Z'\\*[0s]'\v'\\n(0du'\D'l \\n(0wu -\\n(0hu-\\n(0du'\v'\\n(0hu' -.. -.EQ -define cancel 'special Cl' -.EN -*/ - - -class special_box : public pointer_box { - char *macro_name; -public: - special_box(char *, box *); - ~special_box(); - int compute_metrics(int); - void compute_subscript_kern(); - void compute_skew(); - void output(); - void debug_print(); -}; - -box *make_special_box(char *s, box *p) -{ - return new special_box(s, p); -} - -special_box::special_box(char *s, box *pp) : pointer_box(pp), macro_name(s) -{ -} - -special_box::~special_box() -{ - a_delete macro_name; -} - -int special_box::compute_metrics(int style) -{ - int r = p->compute_metrics(style); - p->compute_subscript_kern(); - p->compute_skew(); - printf(".ds " SPECIAL_STRING " \""); - p->output(); - printf("\n"); - printf(".nr " SPECIAL_WIDTH_REG " 0\\n[" WIDTH_FORMAT "]\n", p->uid); - printf(".nr " SPECIAL_HEIGHT_REG " \\n[" HEIGHT_FORMAT "]\n", p->uid); - printf(".nr " SPECIAL_DEPTH_REG " \\n[" DEPTH_FORMAT "]\n", p->uid); - printf(".nr " SPECIAL_SUB_KERN_REG " \\n[" SUB_KERN_FORMAT "]\n", p->uid); - printf(".nr " SPECIAL_SKEW_REG " 0\\n[" SKEW_FORMAT "]\n", p->uid); - printf(".%s\n", macro_name); - printf(".rn " SPECIAL_STRING " " STRING_FORMAT "\n", uid); - printf(".nr " WIDTH_FORMAT " 0\\n[" SPECIAL_WIDTH_REG "]\n", uid); - printf(".nr " HEIGHT_FORMAT " 0>?\\n[" SPECIAL_HEIGHT_REG "]\n", uid); - printf(".nr " DEPTH_FORMAT " 0>?\\n[" SPECIAL_DEPTH_REG "]\n", uid); - printf(".nr " SUB_KERN_FORMAT " 0>?\\n[" SPECIAL_SUB_KERN_REG "]\n", uid); - printf(".nr " SKEW_FORMAT " 0\\n[" SPECIAL_SKEW_REG "]\n", uid); - // User will have to change MARK_REG if appropriate. - return r; -} - -void special_box::compute_subscript_kern() -{ - // Already computed in compute_metrics(), so do nothing. -} - -void special_box::compute_skew() -{ - // Already computed in compute_metrics(), so do nothing. -} - -void special_box::output() -{ - printf("\\*[" STRING_FORMAT "]", uid); -} - -void special_box::debug_print() -{ - fprintf(stderr, "special %s { ", macro_name); - p->debug_print(); - fprintf(stderr, " }"); -} diff --git a/contrib/groff/src/preproc/eqn/sqrt.cpp b/contrib/groff/src/preproc/eqn/sqrt.cpp deleted file mode 100644 index 8f3373ff9cad..000000000000 --- a/contrib/groff/src/preproc/eqn/sqrt.cpp +++ /dev/null @@ -1,180 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2002, 2003 - 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "eqn.h" -#include "pbox.h" - - -class sqrt_box : public pointer_box { -public: - sqrt_box(box *); - int compute_metrics(int style); - void output(); - void debug_print(); - void check_tabs(int); -}; - -box *make_sqrt_box(box *pp) -{ - return new sqrt_box(pp); -} - -sqrt_box::sqrt_box(box *pp) : pointer_box(pp) -{ -} - -#define SQRT_CHAR "\\[sqrt]" -#define RADICAL_EXTENSION_CHAR "\\[sqrtex]" - -#define SQRT_CHAIN "\\[sqrt\\\\n[" INDEX_REG "]]" -#define BAR_CHAIN "\\[sqrtex\\\\n[" INDEX_REG "]]" - -int sqrt_box::compute_metrics(int style) -{ - // 11 - int r = p->compute_metrics(cramped_style(style)); - printf(".nr " TEMP_REG " \\n[" HEIGHT_FORMAT "]+\\n[" DEPTH_FORMAT - "]+%dM+(%dM/4)\n", - p->uid, p->uid, default_rule_thickness, - (style > SCRIPT_STYLE ? x_height : default_rule_thickness)); - printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid); - printf(".ds " SQRT_STRING_FORMAT " " SQRT_CHAR "\n", uid); - printf(".ds " BAR_STRING " " RADICAL_EXTENSION_CHAR "\n"); - printf(".nr " SQRT_WIDTH_FORMAT - " 0\\w" DELIMITER_CHAR SQRT_CHAR DELIMITER_CHAR "\n", - uid); - printf(".if \\n[rst]-\\n[rsb]-%dM<\\n[" TEMP_REG "] \\{", - default_rule_thickness); - - printf(".nr " INDEX_REG " 0\n" - ".de " TEMP_MACRO "\n" - ".ie c" SQRT_CHAIN " \\{" - ".ds " SQRT_STRING_FORMAT " " SQRT_CHAIN "\n" - ".ie c" BAR_CHAIN " .ds " BAR_STRING " " BAR_CHAIN "\n" - ".el .ds " BAR_STRING " " RADICAL_EXTENSION_CHAR "\n" - ".nr " SQRT_WIDTH_FORMAT - " 0\\w" DELIMITER_CHAR SQRT_CHAIN DELIMITER_CHAR "\n" - ".if \\\\n[rst]-\\\\n[rsb]-%dM<\\n[" TEMP_REG "] \\{" - ".nr " INDEX_REG " +1\n" - "." TEMP_MACRO "\n" - ".\\}\\}\n" - ".el .nr " INDEX_REG " 0-1\n" - "..\n" - "." TEMP_MACRO "\n", - uid, uid, default_rule_thickness); - - printf(".if \\n[" INDEX_REG "]<0 \\{"); - - // Determine the maximum point size - printf(".ps 1000\n"); - printf(".nr " MAX_SIZE_REG " \\n[.ps]\n"); - printf(".ps \\n[" SIZE_FORMAT "]u\n", uid); - // We define a macro that will increase the current point size - // until we get a radical sign that's tall enough or we reach - // the maximum point size. - printf(".de " TEMP_MACRO "\n" - ".nr " SQRT_WIDTH_FORMAT - " 0\\w" DELIMITER_CHAR "\\*[" SQRT_STRING_FORMAT "]" DELIMITER_CHAR "\n" - ".if \\\\n[rst]-\\\\n[rsb]-%dM<\\n[" TEMP_REG "]" - "&(\\\\n[.ps]<\\n[" MAX_SIZE_REG "]) \\{" - ".ps +1\n" - "." TEMP_MACRO "\n" - ".\\}\n" - "..\n" - "." TEMP_MACRO "\n", - uid, uid, default_rule_thickness); - - printf(".\\}\\}\n"); - - printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid); - // set TEMP_REG to the amount by which the radical sign is too big - printf(".nr " TEMP_REG " \\n[rst]-\\n[rsb]-%dM-\\n[" TEMP_REG "]\n", - default_rule_thickness); - // If TEMP_REG is negative, the bottom of the radical sign should - // be -TEMP_REG above the bottom of p. If it's positive, the bottom - // of the radical sign should be TEMP_REG/2 below the bottom of p. - // This calculates the amount by which the baseline of the radical - // should be raised. - printf(".nr " SUP_RAISE_FORMAT " (-\\n[" TEMP_REG "]>?(-\\n[" TEMP_REG "]/2))" - "-\\n[rsb]-\\n[" DEPTH_FORMAT "]\n", uid, p->uid); - printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]" - ">?(\\n[" SUP_RAISE_FORMAT "]+\\n[rst])\n", - uid, p->uid, uid); - printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]" - ">?(-\\n[" SUP_RAISE_FORMAT "]-\\n[rsb])\n", - uid, p->uid, uid); - // Do this last, so we don't lose height and depth information on - // the radical sign. - // Remember that the width of the bar might be greater than the width of p. - - printf(".nr " TEMP_REG " " - "\\n[" WIDTH_FORMAT "]" - ">?\\w" DELIMITER_CHAR "\\*[" BAR_STRING "]" DELIMITER_CHAR "\n", - p->uid); - printf(".as " SQRT_STRING_FORMAT " " - "\\l'\\n[" TEMP_REG "]u\\&\\*[" BAR_STRING "]'\n", - uid); - printf(".nr " WIDTH_FORMAT " \\n[" TEMP_REG "]" - "+\\n[" SQRT_WIDTH_FORMAT "]\n", - uid, uid); - - if (r) - printf(".nr " MARK_REG " +\\n[" SQRT_WIDTH_FORMAT "]\n", uid); - // the top of the bar might be higher than the top of the radical sign - printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]" - ">?(\\n[" SUP_RAISE_FORMAT "]+\\n[rst])\n", - uid, p->uid, uid); - // put a bit of extra space above the bar - printf(".nr " HEIGHT_FORMAT " +%dM\n", uid, default_rule_thickness); - printf(".ps \\n[" SIZE_FORMAT "]u\n", uid); - return r; -} - -void sqrt_box::output() -{ - printf("\\Z" DELIMITER_CHAR); - printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid); - printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); - printf("\\*[" SQRT_STRING_FORMAT "]", uid); - printf("\\s[\\n[" SIZE_FORMAT "]u]", uid); - printf(DELIMITER_CHAR); - - printf("\\Z" DELIMITER_CHAR); - printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u" - "+\\n[" SQRT_WIDTH_FORMAT "]u/2u'", - uid, p->uid, uid); - p->output(); - printf(DELIMITER_CHAR); - - printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid); -} - -void sqrt_box::debug_print() -{ - fprintf(stderr, "sqrt { "); - p->debug_print(); - fprintf(stderr, " }"); -} - -void sqrt_box::check_tabs(int level) -{ - p->check_tabs(level + 1); -} diff --git a/contrib/groff/src/preproc/eqn/text.cpp b/contrib/groff/src/preproc/eqn/text.cpp deleted file mode 100644 index e39221276b58..000000000000 --- a/contrib/groff/src/preproc/eqn/text.cpp +++ /dev/null @@ -1,528 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2003 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "eqn.h" -#include "pbox.h" -#include "ptable.h" - -class char_box : public simple_box { - unsigned char c; - char next_is_italic; - char prev_is_italic; -public: - char_box(unsigned char); - void debug_print(); - void output(); - int is_char(); - int left_is_italic(); - int right_is_italic(); - void hint(unsigned); - void handle_char_type(int, int); -}; - -class special_char_box : public simple_box { - char *s; -public: - special_char_box(const char *); - ~special_char_box(); - void output(); - void debug_print(); - int is_char(); - void handle_char_type(int, int); -}; - -const char *spacing_type_table[] = { - "ordinary", - "operator", - "binary", - "relation", - "opening", - "closing", - "punctuation", - "inner", - "suppress", - 0, -}; - -const int DIGIT_TYPE = 0; -const int LETTER_TYPE = 1; - -const char *font_type_table[] = { - "digit", - "letter", - 0, -}; - -struct char_info { - int spacing_type; - int font_type; - char_info(); -}; - -char_info::char_info() -: spacing_type(ORDINARY_TYPE), font_type(DIGIT_TYPE) -{ -} - -static char_info char_table[256]; - -declare_ptable(char_info) -implement_ptable(char_info) - -PTABLE(char_info) special_char_table; - -static int get_special_char_spacing_type(const char *ch) -{ - char_info *p = special_char_table.lookup(ch); - return p ? p->spacing_type : ORDINARY_TYPE; -} - -static int get_special_char_font_type(const char *ch) -{ - char_info *p = special_char_table.lookup(ch); - return p ? p->font_type : DIGIT_TYPE; -} - -static void set_special_char_type(const char *ch, int st, int ft) -{ - char_info *p = special_char_table.lookup(ch); - if (!p) { - p = new char_info[1]; - special_char_table.define(ch, p); - } - if (st >= 0) - p->spacing_type = st; - if (ft >= 0) - p->font_type = ft; -} - -void init_char_table() -{ - set_special_char_type("pl", 2, -1); // binary - set_special_char_type("mi", 2, -1); - set_special_char_type("eq", 3, -1); // relation - set_special_char_type("<=", 3, -1); - set_special_char_type(">=", 3, -1); - char_table['}'].spacing_type = 5; // closing - char_table[')'].spacing_type = 5; - char_table[']'].spacing_type = 5; - char_table['{'].spacing_type = 4; // opening - char_table['('].spacing_type = 4; - char_table['['].spacing_type = 4; - char_table[','].spacing_type = 6; // punctuation - char_table[';'].spacing_type = 6; - char_table[':'].spacing_type = 6; - char_table['.'].spacing_type = 6; - char_table['>'].spacing_type = 3; - char_table['<'].spacing_type = 3; - char_table['*'].spacing_type = 2; // binary - for (int i = 0; i < 256; i++) - if (csalpha(i)) - char_table[i].font_type = LETTER_TYPE; -} - -static int lookup_spacing_type(const char *type) -{ - for (int i = 0; spacing_type_table[i] != 0; i++) - if (strcmp(spacing_type_table[i], type) == 0) - return i; - return -1; -} - -static int lookup_font_type(const char *type) -{ - for (int i = 0; font_type_table[i] != 0; i++) - if (strcmp(font_type_table[i], type) == 0) - return i; - return -1; -} - -void box::set_spacing_type(char *type) -{ - int t = lookup_spacing_type(type); - if (t < 0) - error("unrecognised type `%1'", type); - else - spacing_type = t; - a_delete type; -} - -char_box::char_box(unsigned char cc) -: c(cc), next_is_italic(0), prev_is_italic(0) -{ - spacing_type = char_table[c].spacing_type; -} - -void char_box::hint(unsigned flags) -{ - if (flags & HINT_PREV_IS_ITALIC) - prev_is_italic = 1; - if (flags & HINT_NEXT_IS_ITALIC) - next_is_italic = 1; -} - -void char_box::output() -{ - int font_type = char_table[c].font_type; - if (font_type != LETTER_TYPE) - printf("\\f[%s]", current_roman_font); - if (!prev_is_italic) - fputs("\\,", stdout); - if (c == '\\') - fputs("\\e", stdout); - else - putchar(c); - if (!next_is_italic) - fputs("\\/", stdout); - else - fputs("\\&", stdout); // suppress ligaturing and kerning - if (font_type != LETTER_TYPE) - fputs("\\fP", stdout); -} - -int char_box::left_is_italic() -{ - int font_type = char_table[c].font_type; - return font_type == LETTER_TYPE; -} - -int char_box::right_is_italic() -{ - int font_type = char_table[c].font_type; - return font_type == LETTER_TYPE; -} - -int char_box::is_char() -{ - return 1; -} - -void char_box::debug_print() -{ - if (c == '\\') { - putc('\\', stderr); - putc('\\', stderr); - } - else - putc(c, stderr); -} - -special_char_box::special_char_box(const char *t) -{ - s = strsave(t); - spacing_type = get_special_char_spacing_type(s); -} - -special_char_box::~special_char_box() -{ - a_delete s; -} - -void special_char_box::output() -{ - int font_type = get_special_char_font_type(s); - if (font_type != LETTER_TYPE) - printf("\\f[%s]", current_roman_font); - printf("\\,\\[%s]\\/", s); - if (font_type != LETTER_TYPE) - printf("\\fP"); -} - -int special_char_box::is_char() -{ - return 1; -} - -void special_char_box::debug_print() -{ - fprintf(stderr, "\\[%s]", s); -} - - -void char_box::handle_char_type(int st, int ft) -{ - if (st >= 0) - char_table[c].spacing_type = st; - if (ft >= 0) - char_table[c].font_type = ft; -} - -void special_char_box::handle_char_type(int st, int ft) -{ - set_special_char_type(s, st, ft); -} - -void set_char_type(const char *type, char *ch) -{ - assert(ch != 0); - int st = lookup_spacing_type(type); - int ft = lookup_font_type(type); - if (st < 0 && ft < 0) { - error("bad character type `%1'", type); - a_delete ch; - return; - } - box *b = split_text(ch); - b->handle_char_type(st, ft); - delete b; -} - -/* We give primes special treatment so that in ``x' sub 2'', the ``2'' -will be tucked under the prime */ - -class prime_box : public pointer_box { - box *pb; -public: - prime_box(box *); - ~prime_box(); - int compute_metrics(int style); - void output(); - void compute_subscript_kern(); - void debug_print(); - void handle_char_type(int, int); -}; - -box *make_prime_box(box *pp) -{ - return new prime_box(pp); -} - -prime_box::prime_box(box *pp) : pointer_box(pp) -{ - pb = new special_char_box("fm"); -} - -prime_box::~prime_box() -{ - delete pb; -} - -int prime_box::compute_metrics(int style) -{ - int res = p->compute_metrics(style); - pb->compute_metrics(style); - printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]" - "+\\n[" WIDTH_FORMAT "]\n", - uid, p->uid, pb->uid); - printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]" - ">?\\n[" HEIGHT_FORMAT "]\n", - uid, p->uid, pb->uid); - printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]" - ">?\\n[" DEPTH_FORMAT "]\n", - uid, p->uid, pb->uid); - return res; -} - -void prime_box::compute_subscript_kern() -{ - p->compute_subscript_kern(); - printf(".nr " SUB_KERN_FORMAT " 0\\n[" WIDTH_FORMAT "]" - "+\\n[" SUB_KERN_FORMAT "]>?0\n", - uid, pb->uid, p->uid); -} - -void prime_box::output() -{ - p->output(); - pb->output(); -} - -void prime_box::handle_char_type(int st, int ft) -{ - p->handle_char_type(st, ft); - pb->handle_char_type(st, ft); -} - -void prime_box::debug_print() -{ - p->debug_print(); - putc('\'', stderr); -} - -box *split_text(char *text) -{ - list_box *lb = 0; - box *fb = 0; - char *s = text; - while (*s != '\0') { - char c = *s++; - box *b = 0; - switch (c) { - case '+': - b = new special_char_box("pl"); - break; - case '-': - b = new special_char_box("mi"); - break; - case '=': - b = new special_char_box("eq"); - break; - case '\'': - b = new special_char_box("fm"); - break; - case '<': - if (*s == '=') { - b = new special_char_box("<="); - s++; - break; - } - goto normal_char; - case '>': - if (*s == '=') { - b = new special_char_box(">="); - s++; - break; - } - goto normal_char; - case '\\': - if (*s == '\0') { - lex_error("bad escape"); - break; - } - c = *s++; - switch (c) { - case '(': - { - char buf[3]; - if (*s != '\0') { - buf[0] = *s++; - if (*s != '\0') { - buf[1] = *s++; - buf[2] = '\0'; - b = new special_char_box(buf); - } - else { - lex_error("bad escape"); - } - } - else { - lex_error("bad escape"); - } - } - break; - case '[': - { - char *ch = s; - while (*s != ']' && *s != '\0') - s++; - if (*s == '\0') - lex_error("bad escape"); - else { - *s++ = '\0'; - b = new special_char_box(ch); - } - } - break; - case 'f': - case 'g': - case 'k': - case 'n': - case '*': - { - char *escape_start = s - 2; - switch (*s) { - case '(': - if (*++s != '\0') - ++s; - break; - case '[': - for (++s; *s != '\0' && *s != ']'; s++) - ; - break; - } - if (*s == '\0') - lex_error("bad escape"); - else { - ++s; - char *buf = new char[s - escape_start + 1]; - memcpy(buf, escape_start, s - escape_start); - buf[s - escape_start] = '\0'; - b = new quoted_text_box(buf); - } - } - break; - case '-': - case '_': - { - char buf[2]; - buf[0] = c; - buf[1] = '\0'; - b = new special_char_box(buf); - } - break; - case '`': - b = new special_char_box("ga"); - break; - case '\'': - b = new special_char_box("aa"); - break; - case 'e': - case '\\': - b = new char_box('\\'); - break; - case '^': - case '|': - case '0': - { - char buf[3]; - buf[0] = '\\'; - buf[1] = c; - buf[2] = '\0'; - b = new quoted_text_box(strsave(buf)); - break; - } - default: - lex_error("unquoted escape"); - b = new quoted_text_box(strsave(s - 2)); - s = strchr(s, '\0'); - break; - } - break; - default: - normal_char: - b = new char_box(c); - break; - } - while (*s == '\'') { - if (b == 0) - b = new quoted_text_box(0); - b = new prime_box(b); - s++; - } - if (b != 0) { - if (lb != 0) - lb->append(b); - else if (fb != 0) { - lb = new list_box(fb); - lb->append(b); - } - else - fb = b; - } - } - a_delete text; - if (lb != 0) - return lb; - else if (fb != 0) - return fb; - else - return new quoted_text_box(0); -} - diff --git a/contrib/groff/src/preproc/grn/Makefile.sub b/contrib/groff/src/preproc/grn/Makefile.sub deleted file mode 100644 index c28db477ffa6..000000000000 --- a/contrib/groff/src/preproc/grn/Makefile.sub +++ /dev/null @@ -1,17 +0,0 @@ -PROG=grn$(EXEEXT) -MAN1=grn.n -MLIB=$(LIBM) -XLIBS=$(LIBGROFF) -OBJS=\ - hdb.$(OBJEXT) \ - hpoint.$(OBJEXT) \ - hgraph.$(OBJEXT) \ - main.$(OBJEXT) -CCSRCS=\ - $(srcdir)/hdb.cpp \ - $(srcdir)/hpoint.cpp \ - $(srcdir)/hgraph.cpp \ - $(srcdir)/main.cpp -HDRS=\ - $(srcdir)/gprint.h -NAMEPREFIX=$(g) diff --git a/contrib/groff/src/preproc/grn/README b/contrib/groff/src/preproc/grn/README deleted file mode 100644 index 124103bacab8..000000000000 --- a/contrib/groff/src/preproc/grn/README +++ /dev/null @@ -1,68 +0,0 @@ -This is grn from the Berkeley ditroff distribution. It has no -AT&T code and is therefore freely distributable. - -Tim Theisen - -===================================================================== - -This is the modified code for the groff. It uses the different -devxxx format that is ascii rather than binary as in the -Berkeley distribution. Since groff does not have the \Ds option -for line drawing (dotted, dashed, etc.), this version includes -the routines for drawing curves and arcs, so it does not use the -\D~, \Da nor \Dc. Although also included in here is a routine -for drawing the optional gremlin style curves, it is not used -because the gremlin editor uses the conventional spline -algorithm. The Berkeley grn has the choice of different -stipples. Here, only different shades of gray will be painted -depending on the gremlin file. It is possible to upgrade this at -a later time. (Daniel Senderowicz 12/28/99) - -===================================================================== - -Gremlin produces three types of curves: B-Splines, interpolated -curves and Bezier. As the original Berkeley grn, now groff grn -will honor B-Splines and interpolated curves. Bezier curves will -be printed as B-Splines. (Daniel Senderowicz -10/04/02) - -===================================================================== - -It has been further modified by Werner Lemberg to fit -better into the groff package. - - . Replaced Makefile with Makefile.sub. - - . Removed dev.h since it is unused. - - . Renamed grn.1 to grn.man; this man page has been extensively - revised. - - . Used error() and fatal() from libgroff for all source files. - - . Renamed *.c to *.cpp; updates as needed for C++ (prototypes, proper - casts, standard header files etc). Heavy formatting. - - . main.cpp: - - Using groff's default values instead of DEVDIR, DEFAULTDEV, PRINTER, - TYPESETTER, and GREMLIB. - - `res' is now an integer. - - Added `-C' command flag (for compatibility mode) as with other - preprocessors. - - Added `-F' and `-v' option (similar to troff). - - Renamed `-L' option to `-M' for consistence. - - Removed `-P' option. - - Using font::load_desc() for scanning DESC files. - - Removed SYSV-specific code. - - Using macro_path.open_file() for getting gremlin graphic files. - - Added usage(). diff --git a/contrib/groff/src/preproc/grn/gprint.h b/contrib/groff/src/preproc/grn/gprint.h deleted file mode 100644 index ad3be443015d..000000000000 --- a/contrib/groff/src/preproc/grn/gprint.h +++ /dev/null @@ -1,86 +0,0 @@ -/* Last non-groff version: gprint.h 1.1 84/10/08 - * - * This file contains standard definitions used by the gprint program. - */ - -#include -#include - - -#define xorn(x,y) (x) - /* was 512 */ -#define yorn(x,y) (511 - (y)) /* switch direction for */ - /* y-coordinates */ - -#define STYLES 6 -#define SIZES 4 -#define FONTS 4 -#define SOLID -1 -#define DOTTED 004 /* 014 */ -#define DASHED 020 /* 034 */ -#define DOTDASHED 024 /* 054 */ -#define LONGDASHED 074 - -#define DEFTHICK -1 /* default thicknes */ -#define DEFSTYLE SOLID /* default line style */ - -#define TRUE 1 -#define FALSE 0 - -#define nullelt -1 -#define nullpt -1 -#define nullun NULL - -#define BOTLEFT 0 -#define BOTRIGHT 1 -#define CENTCENT 2 -#define VECTOR 3 -#define ARC 4 -#define CURVE 5 -#define POLYGON 6 -#define BSPLINE 7 -#define BEZIER 8 -#define TOPLEFT 10 -#define TOPCENT 11 -#define TOPRIGHT 12 -#define CENTLEFT 13 -#define CENTRIGHT 14 -#define BOTCENT 15 -#define TEXT(t) ( (t <= CENTCENT) || (t >= TOPLEFT) ) - -/* WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING - * The above (TEXT) test is dependent on the relative values of the - * constants and will have to change if these values change or if new - * commands are added with value greater than BOTCENT - */ - -#define NUSER 4 -#define NFONTS 4 -#define NBRUSHES 6 -#define NSIZES 4 -#define NJUSTS 9 -#define NSTIPPLES 16 - -#define ADD 1 -#define DELETE 2 -#define MOD 3 - -typedef struct point { - double x, y; - struct point *nextpt; -} POINT; - -typedef struct elmt { - int type, brushf, size, textlength; - char *textpt; - POINT *ptlist; - struct elmt *nextelt, *setnext; -} ELT; - -#define DBNextElt(elt) (elt->nextelt) -#define DBNextofSet(elt) (elt->setnext) -#define DBNullelt(elt) (elt == NULL) -#define Nullpoint(pt) ((pt) == (POINT *) NULL) -#define PTNextPoint(pt) (pt->nextpt) - -/* EOF */ diff --git a/contrib/groff/src/preproc/grn/grn.man b/contrib/groff/src/preproc/grn/grn.man deleted file mode 100644 index 575b4ee70c77..000000000000 --- a/contrib/groff/src/preproc/grn/grn.man +++ /dev/null @@ -1,652 +0,0 @@ -'\" t -.ig -Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. - -Permission is granted to make and distribute verbatim copies of -this manual provided the copyright notice and this permission notice -are preserved on all copies. - -Permission is granted to copy and distribute modified versions of this -manual under the conditions for verbatim copying, provided that the -entire resulting derived work is distributed under the terms of a -permission notice identical to this one. - -Permission is granted to copy and distribute translations of this -manual into another language, under the above conditions for modified -versions, except that this permission notice may be included in -translations approved by the Free Software Foundation instead of in -the original English. -.. -. -.do nr grn_C \n[.C] -.cp 0 -. -.de TQ -. br -. ns -. TP \\$1 -.. -. -.\" 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 @G@GRN @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@" -.SH NAME -@g@grn \- groff preprocessor for gremlin files -.SH SYNOPSIS -.BR @g@grn -[ -.B \-Cv -] -[ -.BI \-T dev -] -[ -.BI \-M dir -] -[ -.BI \-F dir -] -[ -.IR file\.\.\.\& -] -.PP -It is possible to have whitespace between a command line option and its -parameter. -.SH DESCRIPTION -.I @g@grn -is a preprocessor for including -.I gremlin -pictures in -.I groff -input. -.I @g@grn -writes to standard output, processing only input lines between two that -start with -.B .GS -and -.BR .GE. -Those lines must contain -.I @g@grn -commands (see below). -These commands request a -.I gremlin -file, and the picture in that file is -converted and placed in the -.I @g@troff -input stream. -The -.B .GS -request may be followed by a C, L, or R to center, left, or right -justify the whole -.I gremlin -picture (default justification is center). -If no -.I file -is mentioned, the standard input is read. -At the end of the picture, the position on the page is the bottom of the -.I gremlin -picture. -If the -.I @g@grn -entry is ended with -.B .GF -instead of -.BR .GE , -the position is left at the top of the picture. -.PP -Please note that currently only the \-me macro package has support for -.BR .GS , -.BR .GE , -and -.BR .GF . -.PP -The following command-line options are understood: -.TP -.BI \-T dev -Prepare output for printer -.IR dev . -The default device is -.BR @DEVICE@ . -See -.BR groff (@MAN1EXT@) -for acceptable devices. -.TP -.BI \-M dir -Prepend -.I dir -to the default search path for -.I gremlin -files. -The default path is (in that order) the current directory, the home -directory, -.BR @SYSTEMMACRODIR@ , -.BR @LOCALMACRODIR@ , -and -.BR @MACRODIR@ . -.TP -.BI \-F dir -Search -.I dir -for subdirectories -.BI dev name -.RI ( name -is the name of the device) for the -.B DESC -file before the default font directories -.BR @LOCALFONTDIR@ , -.BR @FONTDIR@ , -and -.BR @LEGACYFONTDIR@ . -.TP -.B \-C -Recognize -.B .GS -and -.B .GE -(and -.BR .GF ) -even when followed by a character other than space or newline. -.\".TP -.\".B \-s -.\"This switch causes the picture to be traversed twice: -.\"The first time, only the interiors of filled polygons (as borderless -.\"polygons) are printed. -.\"The second time, the outline is printed as a series of line segments. -.\"This way, postprocessors that overwrite rather than merge picture elements -.\"(such as Postscript) can still have text and graphics on a shaded -.\"background. -.TP -.B \-v -Print the version number. -.SH GRN COMMANDS -Each input line between -.B .GS -and -.B .GE -may have one -.I @g@grn -command. -Commands consist of one or two strings separated by white space, the first -string being the command and the second its operand. -Commands may be upper or lower case and abbreviated down to one character. -.PP -Commands that affect a picture's environment (those listed before -.BR default , -see below) are only in effect for the current picture: -The environment is reinitialized to the defaults at the start of the next -picture. -The commands are as follows: -.TP -.BI 1\ N -.TQ -.BI 2\ N -.TQ -.BI 3\ N -.TQ -.BI 4\ N -Set -.IR gremlin 's -text size number 1 (2, 3, or 4) to -.I N -points. -The default is 12 (16, 24, and 36, respectively). -.TP -.BI roman\ f -.TQ -.BI italics\ f -.TQ -.BI bold\ f -.TQ -.BI special\ f -Set the roman (italics, bold, or special) font to -.IR @g@troff 's -font -.I f -(either a name or number). -The default is R (I, B, and S, respectively). -.TP -.BI l\ f -.TQ -.BI stipple\ f -Set the stipple font to -.IR @g@troff 's -stipple font -.I f -(name or number). -The command -.B stipple -may be abbreviated down as far as `st' (to avoid -confusion with -.BR special ). -There is -.I no -default for stipples (unless one is set by the default command), and it is -invalid to include a -.I gremlin -picture with polygons without specifying a -stipple font. -.TP -.BI x\ N -.TQ -.BI scale\ N -Magnify the picture (in addition to any default magnification) by -.IR N , -a floating point number larger than zero. -The command -.B scale -may be abbreviated down to `sc'. -.TP -.BI narrow\ N -.TQ -.BI medium\ N -.TQ -.BI thick\ N -Set the thickness of -.IR gremlin 's -narrow (medium and thick, respectively) lines to -.I N -times 0.15pt (this value can be changed at compile time). -The default is 1.0 (3.0 and 5.0, respectively), which corresponds to 0.15pt -(0.45pt and 0.75pt, respectively). -A thickness value of zero selects the smallest available line thickness. -Negative values cause the line thickness to be proportional to the current -point size. -.TP -.BI pointscale\ -Scale text to match the picture. -Gremlin text is usually printed in the point size specified with the -commands -.BR 1 , -.BR 2 , -.BR 3 , -.RB or\~ 4 , -regardless of any scaling factors in the picture. -Setting -.B pointscale -will cause the point sizes to scale with the picture (within -.IR @g@troff 's -limitations, of course). -An operand of anything but -.I off -will turn text scaling on. -.TP -.B default -Reset the picture environment defaults to the settings in the current -picture. -This is meant to be used as a global parameter setting mechanism at the -beginning of the -.I @g@troff -input file, but can be used at any time to reset the -default settings. -.TP -.BI width\ N -Forces the picture to be -.I N -inches wide. -This overrides any scaling factors present in the same picture. -.RB ` width -.IR 0 ' -is ignored. -.TP -.BI height\ N -Forces picture to be -.I N -inches high, overriding other scaling factors. -If both `width' and `height' are specified the tighter constraint will -determine the scale of the picture. -.B Height -and -.B width -commands are not saved with a -.B default -command. -They will, however, affect point size scaling if that option is set. -.TP -.BI file\ name -Get picture from -.I gremlin -file -.I name -located the current directory (or in the library directory; see the -.B \-M -option above). -If two -.B file -commands are given, the second one overrides the first. -If -.I name -doesn't exist, an error message is reported and processing continues from -the -.B .GE -line. -.SH NOTES ABOUT GROFF -Since -.I @g@grn -is a preprocessor, it doesn't know about current indents, point sizes, -margins, number registers, etc. -Consequently, no -.I @g@troff -input can be placed between the -.B .GS -and -.B .GE -requests. -However, -.I gremlin -text is now processed by -.IR @g@troff , -so anything legal in a single line of -.I @g@troff -input is legal in a line of -.I gremlin -text (barring `.' directives at the beginning of a line). -Thus, it is possible to have equations within a -.I gremlin -figure by including in the -.I gremlin -file -.I eqn -expressions enclosed by previously defined delimiters (e.g. -.IR $$ ). -.PP -When using -.I @g@grn -along with other preprocessors, it is best to run -.I tbl -before -.IR @g@grn , -.IR pic , -and/or -.I ideal -to avoid overworking -.IR tbl . -.I Eqn -should always be run last. -.PP -A picture is considered an entity, but that doesn't stop -.I @g@troff -from trying to break it up if it falls off the end of a page. -Placing the picture between `keeps' in \-me macros will ensure proper -placement. -.PP -.I @g@grn -uses -.IR @g@troff 's -number registers -.B g1 -through -.B g9 -and sets registers -.B g1 -and -.B g2 -to the width and height of the -.I gremlin -figure (in device units) before entering the -.B .GS -request (this is for those who want to rewrite these macros). -.SH GREMLIN FILE FORMAT -There exist two distinct -.I gremlin -file formats, the original format from the -.I AED -graphic terminal version, and the -.I SUN -or -.I X11 -version. -An extension to the -.IR SUN / X11 -version allowing reference points with negative coordinates is -.B not -compatible with the -.I AED -version. -As long as a -.I gremlin -file does not contain negative coordinates, either format will be read -correctly by either version of -.I gremlin -or -.IR @g@grn . -The other difference to the -.IR SUN / X11 -format is the use of names for picture objects (e.g., POLYGON, CURVE) -instead of numbers. -Files representing the same picture are shown in Table 1 in each format. -.sp -.TS -center, tab(@); -l lw(0.1i) l. -sungremlinfile@@gremlinfile -0 240.00 128.00@@0 240.00 128.00 -CENTCENT@@2 -240.00 128.00@@240.00 128.00 -185.00 120.00@@185.00 120.00 -240.00 120.00@@240.00 120.00 -296.00 120.00@@296.00 120.00 -*@@-1.00 -1.00 -2 3@@2 3 -10 A Triangle@@10 A Triangle -POLYGON@@6 -224.00 416.00@@224.00 416.00 -96.00 160.00@@96.00 160.00 -384.00 160.00@@384.00 160.00 -*@@-1.00 -1.00 -5 1@@5 1 -0@@0 --1@@-1 -.T& -css. -.sp -Table 1. File examples -.TE -.sp -.IP \(bu -The first line of each -.I gremlin -file contains either the string -.B gremlinfile -.RI ( AED -version) or -.B sungremlinfile -.RI ( SUN / X11 ) -.IP \(bu -The second line of the file contains an orientation, and -.B x -and -.B y -values for a positioning point, separated by spaces. -The orientation, either -.B 0 -or -.BR 1 , -is ignored by the -.IR SUN / X11 -version. -.B 0 -means that -.I gremlin -will display things in horizontal format (drawing area wider than it is -tall, with menu across top). -.B 1 -means that -.I gremlin -will display things in vertical format (drawing area taller than it is wide, -with menu on left side). -.B x -and -.B y -are floating point values giving a positioning point to be used when this -file is read into another file. -The stuff on this line really isn't all that important; a value of ``1 0.00 -0.00'' is suggested. -.IP \(bu -The rest of the file consists of zero or more element specifications. -After the last element specification is a line containing the string ``-1''. -.IP \(bu -Lines longer than 127 characters are chopped to this limit. -.SH ELEMENT SPECIFICATIONS -.IP \(bu -The first line of each element contains a single decimal number giving the -type of the element -.RI ( AED -version) or its ASCII name -.RI ( SUN / X11 -version). -See Table 2. -.sp -.TS -center, tab(@); -css -ccc -nll. -\fIgremlin\fP File Format \(mi Object Type Specification -.sp -\fIAED\fP Number@\fISUN\fP/\fIX11\fP Name@Description -0@BOTLEFT@bottom-left-justified text -1@BOTRIGHT@bottom-right-justified text -2@CENTCENT@center-justified text -3@VECTOR@vector -4@ARC@arc -5@CURVE@curve -6@POLYGON@polygon -7@BSPLINE@b-spline -8@BEZIER@B\['e]zier -10@TOPLEFT@top-left-justified text -11@TOPCENT@top-center-justified text -12@TOPRIGHT@top-right-justified text -13@CENTLEFT@left-center-justified text -14@CENTRIGHT@right-center-justified text -15@BOTCENT@bottom-center-justified text -.T& -css. -.sp -Table 2. -Type Specifications in \fIgremlin\fP Files -.TE -.sp -.IP \(bu -After the object type comes a variable number of lines, each specifying a -point used to display the element. -Each line contains an x-coordinate and a y-coordinate in floating point -format, separated by spaces. -The list of points is terminated by a line containing the string ``-1.0 --1.0'' -.RI ( AED -version) or a single asterisk, ``*'' -.RI ( SUN / X11 -version). -.IP \(bu -After the points comes a line containing two decimal values, giving the -brush and size for the element. -The brush determines the style in which things are drawn. -For vectors, arcs, and curves there are six legal brush values: -.sp -.TS -center, tab(@); -ncw(0.1i)l. -1 \(mi@@thin dotted lines -2 \(mi@@thin dot-dashed lines -3 \(mi@@thick solid lines -4 \(mi@@thin dashed lines -5 \(mi@@thin solid lines -6 \(mi@@medium solid lines -.TE -.sp -For polygons, one more value, 0, is legal. -It specifies a polygon with an invisible border. -For text, the brush selects a font as follows: -.sp -.TS -center, tab(@); -ncw(0.1i)l. -1 \(mi@@roman (R font in groff) -2 \(mi@@italics (I font in groff) -3 \(mi@@bold (B font in groff) -4 \(mi@@special (S font in groff) -.TE -.sp -If you're using -.I @g@grn -to run your pictures through -.IR groff , -the font is really just a starting font: -The text string can contain formatting sequences like -``\efI'' -or -``\ed'' -which may change the font (as well as do many other things). -For text, the size field is a decimal value between 1 and 4. -It selects the size of the font in which the text will be drawn. -For polygons, this size field is interpreted as a stipple number to fill the -polygon with. -The number is used to index into a stipple font at print time. -.IP \(bu -The last line of each element contains a decimal number and a string of -characters, separated by a single space. -The number is a count of the number of characters in the string. -This information is only used for text elements, and contains the text -string. -There can be spaces inside the text. -For arcs, curves, and vectors, this line of the element contains the string -``0''. -.SH NOTES ON COORDINATES -.I gremlin -was designed for -.IR AED s, -and its coordinates reflect the -.I AED -coordinate space. -For vertical pictures, x-values range 116 to 511, and y-values from 0 to -483. -For horizontal pictures, x-values range from 0 to 511 and y-values range -from 0 to 367. -Although you needn't absolutely stick to this range, you'll get best results -if you at least stay in this vicinity. -Also, point lists are terminated by a point of (-1, -1), so you shouldn't -ever use negative coordinates. -.I gremlin -writes out coordinates using format ``%f1.2''; it's probably a good idea to -use the same format if you want to modify the -.I @g@grn -code. -.SH NOTES ON SUN/X11 COORDINATES -There is no longer a restriction on the range of coordinates used to create -objects in the -.IR SUN / X11 -version of -.IR gremlin . -However, files with negative coordinates -.B will -cause problems if displayed on the -.IR AED . -.SH FILES -.Tp \w'@FONTDIR@/devname/DESC'u+3n -.BI @FONTDIR@/dev name /DESC -Device description file for device -.IR name . -.SH SEE ALSO -.BR gremlin (1), -.BR groff (@MAN1EXT@), -.BR @g@pic (@MAN1EXT@), -.BR ideal (1) -.SH HISTORY -.PP -David Slattengren and Barry Roitblat wrote the original Berkeley -.IR @g@grn . -.PP -Daniel Senderowicz and Werner Lemberg modified it for -.IR groff . -. -.cp \n[grn_C] -. -.\" Local Variables: -.\" mode: nroff -.\" End: diff --git a/contrib/groff/src/preproc/grn/hdb.cpp b/contrib/groff/src/preproc/grn/hdb.cpp deleted file mode 100644 index 5f54040dd5c5..000000000000 --- a/contrib/groff/src/preproc/grn/hdb.cpp +++ /dev/null @@ -1,346 +0,0 @@ - /* Last non-groff version: hdb.c 1.8 (Berkeley) 84/10/20 - * - * Copyright -C- 1982 Barry S. Roitblat - * - * This file contains database routines for the hard copy programs of the - * gremlin picture editor. - */ - -#include "gprint.h" -#include -#include -#include - -#include "errarg.h" -#include "error.h" - -#define MAXSTRING 128 -#define MAXSTRING_S "127" - -/* imports from main.cpp */ - -extern int linenum; /* current line number in input file */ -extern char gremlinfile[]; /* name of file currently reading */ -extern int SUNFILE; /* TRUE if SUN gremlin file */ -extern int compatibility_flag; /* TRUE if in compatibility mode */ -extern void savebounds(double x, double y); - -/* imports from hpoint.cpp */ - -extern POINT *PTInit(); -extern POINT *PTMakePoint(double x, double y, POINT ** pplist); - - -int DBGetType(register char *s); - - -/* - * This routine returns a pointer to an initialized database element which - * would be the only element in an empty list. - */ -ELT * -DBInit() -{ - return ((ELT *) NULL); -} /* end DBInit */ - - -/* - * This routine creates a new element with the specified attributes and - * links it into database. - */ -ELT * -DBCreateElt(int type, - POINT * pointlist, - int brush, - int size, - char *text, - ELT **db) -{ - register ELT *temp; - - temp = (ELT *) malloc(sizeof(ELT)); - temp->nextelt = *db; - temp->type = type; - temp->ptlist = pointlist; - temp->brushf = brush; - temp->size = size; - temp->textpt = text; - *db = temp; - return (temp); -} /* end CreateElt */ - - -/* - * This routine reads the specified file into a database and returns a - * pointer to that database. - */ -ELT * -DBRead(register FILE *file) -{ - register int i; - register int done; /* flag for input exhausted */ - register double nx; /* x holder so x is not set before orienting */ - int type; /* element type */ - ELT *elist; /* pointer to the file's elements */ - POINT *plist; /* pointer for reading in points */ - char string[MAXSTRING], *txt; - double x, y; /* x and y are read in point coords */ - int len, brush, size; - int lastpoint; - - SUNFILE = FALSE; - elist = DBInit(); - (void) fscanf(file, "%" MAXSTRING_S "s%*[^\n]\n", string); - if (strcmp(string, "gremlinfile")) { - if (strcmp(string, "sungremlinfile")) { - error("`%1' is not a gremlin file", gremlinfile); - return (elist); - } - SUNFILE = TRUE; - } - - (void) fscanf(file, "%d%lf%lf\n", &size, &x, &y); - /* ignore orientation and file positioning point */ - - done = FALSE; - while (!done) { - /* if (fscanf(file,"%" MAXSTRING_S "s\n", string) == EOF) */ - /* I changed the scanf format because the element */ - /* can have two words (e.g. CURVE SPLINE) */ - if (fscanf(file, "\n%" MAXSTRING_S "[^\n]%*[^\n]\n", string) == EOF) { - error("`%1', error in file format", gremlinfile); - return (elist); - } - - type = DBGetType(string); /* interpret element type */ - if (type < 0) { /* no more data */ - done = TRUE; - } else { -#ifdef UW_FASTSCAN - (void) xscanf(file, &x, &y); /* always one point */ -#else - (void) fscanf(file, "%lf%lf\n", &x, &y); /* always one point */ -#endif /* UW_FASTSCAN */ - plist = PTInit(); /* NULL point list */ - - /* - * Files created on the SUN have point lists terminated by a line - * containing only an asterik ('*'). Files created on the AED have - * point lists terminated by the coordinate pair (-1.00 -1.00). - */ - if (TEXT(type)) { /* read only first point for TEXT elements */ - nx = xorn(x, y); - y = yorn(x, y); - (void) PTMakePoint(nx, y, &plist); - savebounds(nx, y); - -#ifdef UW_FASTSCAN - while (xscanf(file, &x, &y)); -#else - lastpoint = FALSE; - do { - fgets(string, MAXSTRING, file); - if (string[0] == '*') { /* SUN gremlin file */ - lastpoint = TRUE; - } else { - (void) sscanf(string, "%lf%lf", &x, &y); - if ((x == -1.00 && y == -1.00) && (!SUNFILE)) - lastpoint = TRUE; - else { - if (compatibility_flag) - savebounds(xorn(x, y), yorn(x, y)); - } - } - } while (!lastpoint); -#endif /* UW_FASTSCAN */ - } else { /* not TEXT element */ -#ifdef UW_FASTSCAN - do { - nx = xorn(x, y); - y = yorn(x, y); - (void) PTMakePoint(nx, y, &plist); - savebounds(nx, y); - } while (xscanf(file, &x, &y)); -#else - lastpoint = FALSE; - while (!lastpoint) { - nx = xorn(x, y); - y = yorn(x, y); - (void) PTMakePoint(nx, y, &plist); - savebounds(nx, y); - - fgets(string, MAXSTRING, file); - if (string[0] == '*') { /* SUN gremlin file */ - lastpoint = TRUE; - } else { - (void) sscanf(string, "%lf%lf", &x, &y); - if ((x == -1.00 && y == -1.00) && (!SUNFILE)) - lastpoint = TRUE; - } - } -#endif /* UW_FASTSCAN */ - } - (void) fscanf(file, "%d%d\n", &brush, &size); - (void) fscanf(file, "%d", &len); /* text length */ - (void) getc(file); /* eat blank */ - txt = (char *) malloc((unsigned) len + 1); - for (i = 0; i < len; ++i) { /* read text */ - int c = getc(file); - if (c == EOF) - break; - txt[i] = c; - } - txt[len] = '\0'; - (void) DBCreateElt(type, plist, brush, size, txt, &elist); - } /* end else */ - } /* end while not done */ ; - return (elist); -} /* end DBRead */ - - -/* - * Interpret element type in string s. - * Old file format consisted of integer element types. - * New file format has literal names for element types. - */ -int -DBGetType(register char *s) -{ - if (isdigit(s[0]) || (s[0] == '-')) /* old element format or EOF */ - return (atoi(s)); - - switch (s[0]) { - case 'P': - return (POLYGON); - case 'V': - return (VECTOR); - case 'A': - return (ARC); - case 'C': - if (s[1] == 'U') { - if (s[5] == '\n') - return (CURVE); - switch (s[7]) { - case 'S': - return(BSPLINE); - case 'E': - fprintf(stderr, - "Warning: Bezier Curves will be printed as B-Splines\n"); - return(BSPLINE); - default: - return(CURVE); - } - } - switch (s[4]) { - case 'L': - return (CENTLEFT); - case 'C': - return (CENTCENT); - case 'R': - return (CENTRIGHT); - default: - fatal("unknown element type"); - } - case 'B': - switch (s[3]) { - case 'L': - return (BOTLEFT); - case 'C': - return (BOTCENT); - case 'R': - return (BOTRIGHT); - default: - fatal("unknown element type"); - } - case 'T': - switch (s[3]) { - case 'L': - return (TOPLEFT); - case 'C': - return (TOPCENT); - case 'R': - return (TOPRIGHT); - default: - fatal("unknown element type"); - } - default: - fatal("unknown element type"); - } - - return 0; /* never reached */ -} - -#ifdef UW_FASTSCAN -/* - * Optimization hack added by solomon@crys.wisc.edu, 12/2/86. - * A huge fraction of the time was spent reading floating point numbers from - * the input file, but the numbers always have the format 'ddd.dd'. Thus - * the following special-purpose version of fscanf. - * - * xscanf(f,xp,yp) does roughly what fscanf(f,"%f%f",xp,yp) does except: - * -the next piece of input must be of the form - * * *'.'* * *'.'* - * -xscanf eats the character following the second number - * -xscanf returns 0 for "end-of-data" indication, 1 otherwise, where - * end-of-data is signalled by a '*' [in which case the rest of the - * line is gobbled], or by '-1.00 -1.00' [but only if !SUNFILE]. - */ -int -xscanf(FILE *f, - double *xp, - double *yp) -{ - register int c, i, j, m, frac; - int iscale = 1, jscale = 1; /* x = i/scale, y=j/jscale */ - - while ((c = getc(f)) == ' '); - if (c == '*') { - while ((c = getc(f)) != '\n'); - return 0; - } - i = m = frac = 0; - while (isdigit(c) || c == '.' || c == '-') { - if (c == '-') { - m++; - c = getc(f); - continue; - } - if (c == '.') - frac = 1; - else { - if (frac) - iscale *= 10; - i = 10 * i + c - '0'; - } - c = getc(f); - } - if (m) - i = -i; - *xp = (double) i / (double) iscale; - - while ((c = getc(f)) == ' '); - j = m = frac = 0; - while (isdigit(c) || c == '.' || c == '-') { - if (c == '-') { - m++; - c = getc(f); - continue; - } - if (c == '.') - frac = 1; - else { - if (frac) - jscale *= 10; - j = 10 * j + c - '0'; - } - c = getc(f); - } - if (m) - j = -j; - *yp = (double) j / (double) jscale; - return (SUNFILE || i != -iscale || j != -jscale); -} -#endif /* UW_FASTSCAN */ - -/* EOF */ diff --git a/contrib/groff/src/preproc/grn/hgraph.cpp b/contrib/groff/src/preproc/grn/hgraph.cpp deleted file mode 100644 index 01208951f28f..000000000000 --- a/contrib/groff/src/preproc/grn/hgraph.cpp +++ /dev/null @@ -1,1048 +0,0 @@ -/* Last non-groff version: hgraph.c 1.14 (Berkeley) 84/11/27 - * - * This file contains the graphics routines for converting gremlin pictures - * to troff input. - */ - -#include "lib.h" - -#include "gprint.h" - -#define MAXVECT 40 -#define MAXPOINTS 200 -#define LINELENGTH 1 -#define PointsPerInterval 64 -#define pi 3.14159265358979324 -#define twopi (2.0 * pi) -#define len(a, b) groff_hypot((double)(b.x-a.x), (double)(b.y-a.y)) - - -extern int dotshifter; /* for the length of dotted curves */ - -extern int style[]; /* line and character styles */ -extern double thick[]; -extern char *tfont[]; -extern int tsize[]; -extern int stipple_index[]; /* stipple font index for stipples 0 - 16 */ -extern char *stipple; /* stipple type (cf or ug) */ - - -extern double troffscale; /* imports from main.c */ -extern double linethickness; -extern int linmod; -extern int lastx; -extern int lasty; -extern int lastyline; -extern int ytop; -extern int ybottom; -extern int xleft; -extern int xright; -extern enum E { - OUTLINE, FILL, BOTH -} polyfill; - -extern double adj1; -extern double adj2; -extern double adj3; -extern double adj4; -extern int res; - -void HGSetFont(int font, int size); -void HGPutText(int justify, POINT pnt, register char *string); -void HGSetBrush(int mode); -void tmove2(int px, int py); -void doarc(POINT cp, POINT sp, int angle); -void tmove(POINT * ptr); -void cr(); -void drawwig(POINT * ptr, int type); -void HGtline(int x1, int y1); -void deltax(double x); -void deltay(double y); -void HGArc(register int cx, register int cy, int px, int py, int angle); -void picurve(register int *x, register int *y, int npts); -void HGCurve(int *x, int *y, int numpoints); -void Paramaterize(int x[], int y[], double h[], int n); -void PeriodicSpline(double h[], int z[], - double dz[], double d2z[], double d3z[], - int npoints); -void NaturalEndSpline(double h[], int z[], - double dz[], double d2z[], double d3z[], - int npoints); - - - -/*----------------------------------------------------------------------------* - | Routine: HGPrintElt (element_pointer, baseline) - | - | Results: Examines a picture element and calls the appropriate - | routine(s) to print them according to their type. After the - | picture is drawn, current position is (lastx, lasty). - *----------------------------------------------------------------------------*/ - -void -HGPrintElt(ELT *element, - int /* baseline */) -{ - register POINT *p1; - register POINT *p2; - register int length; - register int graylevel; - - if (!DBNullelt(element) && !Nullpoint((p1 = element->ptlist))) { - /* p1 always has first point */ - if (TEXT(element->type)) { - HGSetFont(element->brushf, element->size); - switch (element->size) { - case 1: - p1->y += adj1; - break; - case 2: - p1->y += adj2; - break; - case 3: - p1->y += adj3; - break; - case 4: - p1->y += adj4; - break; - default: - break; - } - HGPutText(element->type, *p1, element->textpt); - } else { - if (element->brushf) /* if there is a brush, the */ - HGSetBrush(element->brushf); /* graphics need it set */ - - switch (element->type) { - - case ARC: - p2 = PTNextPoint(p1); - tmove(p2); - doarc(*p1, *p2, element->size); - cr(); - break; - - case CURVE: - length = 0; /* keep track of line length */ - drawwig(p1, CURVE); - cr(); - break; - - case BSPLINE: - length = 0; /* keep track of line length */ - drawwig(p1, BSPLINE); - cr(); - break; - - case VECTOR: - length = 0; /* keep track of line length so */ - tmove(p1); /* single lines don't get long */ - while (!Nullpoint((p1 = PTNextPoint(p1)))) { - HGtline((int) (p1->x * troffscale), - (int) (p1->y * troffscale)); - if (length++ > LINELENGTH) { - length = 0; - printf("\\\n"); - } - } /* end while */ - cr(); - break; - - case POLYGON: - { - /* brushf = style of outline; size = color of fill: - * on first pass (polyfill=FILL), do the interior using 'P' - * unless size=0 - * on second pass (polyfill=OUTLINE), do the outline using a series - * of vectors. It might make more sense to use \D'p ...', - * but there is no uniform way to specify a 'fill character' - * that prints as 'no fill' on all output devices (and - * stipple fonts). - * If polyfill=BOTH, just use the \D'p ...' command. - */ - double firstx = p1->x; - double firsty = p1->y; - - length = 0; /* keep track of line length so */ - /* single lines don't get long */ - - if (polyfill == FILL || polyfill == BOTH) { - /* do the interior */ - char command = (polyfill == BOTH && element->brushf) ? 'p' : 'P'; - - /* include outline, if there is one and */ - /* the -p flag was set */ - - /* switch based on what gremlin gives */ - switch (element->size) { - case 1: - graylevel = 1; - break; - case 3: - graylevel = 2; - break; - case 12: - graylevel = 3; - break; - case 14: - graylevel = 4; - break; - case 16: - graylevel = 5; - break; - case 19: - graylevel = 6; - break; - case 21: - graylevel = 7; - break; - case 23: - graylevel = 8; - break; - default: /* who's giving something else? */ - graylevel = NSTIPPLES; - break; - } - /* int graylevel = element->size; */ - - if (graylevel < 0) - break; - if (graylevel > NSTIPPLES) - graylevel = NSTIPPLES; - printf("\\D'Fg %.3f'", - double(1000 - stipple_index[graylevel]) / 1000.0); - cr(); - tmove(p1); - printf("\\D'%c", command); - - while (!Nullpoint((PTNextPoint(p1)))) { - p1 = PTNextPoint(p1); - deltax((double) p1->x); - deltay((double) p1->y); - if (length++ > LINELENGTH) { - length = 0; - printf("\\\n"); - } - } /* end while */ - - /* close polygon if not done so by user */ - if ((firstx != p1->x) || (firsty != p1->y)) { - deltax((double) firstx); - deltay((double) firsty); - } - putchar('\''); - cr(); - break; - } - /* else polyfill == OUTLINE; only draw the outline */ - if (!(element->brushf)) - break; - length = 0; /* keep track of line length */ - tmove(p1); - - while (!Nullpoint((PTNextPoint(p1)))) { - p1 = PTNextPoint(p1); - HGtline((int) (p1->x * troffscale), - (int) (p1->y * troffscale)); - if (length++ > LINELENGTH) { - length = 0; - printf("\\\n"); - } - } /* end while */ - - /* close polygon if not done so by user */ - if ((firstx != p1->x) || (firsty != p1->y)) { - HGtline((int) (firstx * troffscale), - (int) (firsty * troffscale)); - } - cr(); - break; - } /* end case POLYGON */ - } /* end switch */ - } /* end else Text */ - } /* end if */ -} /* end PrintElt */ - - -/*----------------------------------------------------------------------------* - | Routine: HGPutText (justification, position_point, string) - | - | Results: Given the justification, a point to position with, and a - | string to put, HGPutText first sends the string into a - | diversion, moves to the positioning point, then outputs - | local vertical and horizontal motions as needed to justify - | the text. After all motions are done, the diversion is - | printed out. - *----------------------------------------------------------------------------*/ - -void -HGPutText(int justify, - POINT pnt, - register char *string) -{ - int savelasty = lasty; /* vertical motion for text is to be */ - /* ignored. Save current y here */ - - printf(".nr g8 \\n(.d\n"); /* save current vertical position. */ - printf(".ds g9 \""); /* define string containing the text. */ - while (*string) { /* put out the string */ - if (*string == '\\' && - *(string + 1) == '\\') { /* one character at a */ - printf("\\\\\\"); /* time replacing // */ - string++; /* by //// to prevent */ - } /* interpretation at */ - printf("%c", *(string++)); /* printout time */ - } - printf("\n"); - - tmove(&pnt); /* move to positioning point */ - - switch (justify) { - /* local vertical motions */ - /* (the numbers here are used to be somewhat compatible with gprint) */ - case CENTLEFT: - case CENTCENT: - case CENTRIGHT: - printf("\\v'0.85n'"); /* down half */ - break; - - case TOPLEFT: - case TOPCENT: - case TOPRIGHT: - printf("\\v'1.7n'"); /* down whole */ - } - - switch (justify) { - /* local horizontal motions */ - case BOTCENT: - case CENTCENT: - case TOPCENT: - printf("\\h'-\\w'\\*(g9'u/2u'"); /* back half */ - break; - - case BOTRIGHT: - case CENTRIGHT: - case TOPRIGHT: - printf("\\h'-\\w'\\*(g9'u'"); /* back whole */ - } - - printf("\\&\\*(g9\n"); /* now print the text. */ - printf(".sp |\\n(g8u\n"); /* restore vertical position */ - lasty = savelasty; /* vertical position restored to where it */ - lastx = xleft; /* was before text, also horizontal is at */ - /* left */ -} /* end HGPutText */ - - -/*----------------------------------------------------------------------------* - | Routine: doarc (center_point, start_point, angle) - | - | Results: Produces either drawarc command or a drawcircle command - | depending on the angle needed to draw through. - *----------------------------------------------------------------------------*/ - -void -doarc(POINT cp, - POINT sp, - int angle) -{ - if (angle) /* arc with angle */ - HGArc((int) (cp.x * troffscale), (int) (cp.y * troffscale), - (int) (sp.x * troffscale), (int) (sp.y * troffscale), angle); - else /* a full circle (angle == 0) */ - HGArc((int) (cp.x * troffscale), (int) (cp.y * troffscale), - (int) (sp.x * troffscale), (int) (sp.y * troffscale), 0); -} - - -/*----------------------------------------------------------------------------* - | Routine: HGSetFont (font_number, Point_size) - | - | Results: ALWAYS outputs a .ft and .ps directive to troff. This is - | done because someone may change stuff inside a text string. - | Changes thickness back to default thickness. Default - | thickness depends on font and pointsize. - *----------------------------------------------------------------------------*/ - -void -HGSetFont(int font, - int size) -{ - printf(".ft %s\n" - ".ps %d\n", tfont[font - 1], tsize[size - 1]); - linethickness = DEFTHICK; -} - - -/*----------------------------------------------------------------------------* - | Routine: HGSetBrush (line_mode) - | - | Results: Generates the troff commands to set up the line width and - | style of subsequent lines. Does nothing if no change is - | needed. - | - | Side Efct: Sets `linmode' and `linethicknes'. - *----------------------------------------------------------------------------*/ - -void -HGSetBrush(int mode) -{ - register int printed = 0; - - if (linmod != style[--mode]) { - /* Groff doesn't understand \Ds, so we take it out */ - /* printf ("\\D's %du'", linmod = style[mode]); */ - linmod = style[mode]; - printed = 1; - } - if (linethickness != thick[mode]) { - linethickness = thick[mode]; - printf("\\h'-%.2fp'\\D't %.2fp'", linethickness, linethickness); - printed = 1; - } - if (printed) - cr(); -} - - -/*----------------------------------------------------------------------------* - | Routine: deltax (x_destination) - | - | Results: Scales and outputs a number for delta x (with a leading - | space) given `lastx' and x_destination. - | - | Side Efct: Resets `lastx' to x_destination. - *----------------------------------------------------------------------------*/ - -void -deltax(double x) -{ - register int ix = (int) (x * troffscale); - - printf(" %du", ix - lastx); - lastx = ix; -} - - -/*----------------------------------------------------------------------------* - | Routine: deltay (y_destination) - | - | Results: Scales and outputs a number for delta y (with a leading - | space) given `lastyline' and y_destination. - | - | Side Efct: Resets `lastyline' to y_destination. Since `line' vertical - | motions don't affect `page' ones, `lasty' isn't updated. - *----------------------------------------------------------------------------*/ - -void -deltay(double y) -{ - register int iy = (int) (y * troffscale); - - printf(" %du", iy - lastyline); - lastyline = iy; -} - - -/*----------------------------------------------------------------------------* - | Routine: tmove2 (px, py) - | - | Results: Produces horizontal and vertical moves for troff given the - | pair of points to move to and knowing the current position. - | Also puts out a horizontal move to start the line. This is - | a variation without the .sp command. - *----------------------------------------------------------------------------*/ - -void -tmove2(int px, - int py) -{ - register int dx; - register int dy; - - if ((dy = py - lasty)) { - printf("\\v'%du'", dy); - } - lastyline = lasty = py; /* lasty is always set to current */ - if ((dx = px - lastx)) { - printf("\\h'%du'", dx); - lastx = px; - } -} - - -/*----------------------------------------------------------------------------* - | Routine: tmove (point_pointer) - | - | Results: Produces horizontal and vertical moves for troff given the - | pointer of a point to move to and knowing the current - | position. Also puts out a horizontal move to start the - | line. - *----------------------------------------------------------------------------*/ - -void -tmove(POINT * ptr) -{ - register int ix = (int) (ptr->x * troffscale); - register int iy = (int) (ptr->y * troffscale); - register int dx; - register int dy; - - if ((dy = iy - lasty)) { - printf(".sp %du\n", dy); - } - lastyline = lasty = iy; /* lasty is always set to current */ - if ((dx = ix - lastx)) { - printf("\\h'%du'", dx); - lastx = ix; - } -} - - -/*----------------------------------------------------------------------------* - | Routine: cr ( ) - | - | Results: Ends off an input line. `.sp -1' is also added to counteract - | the vertical move done at the end of text lines. - | - | Side Efct: Sets `lastx' to `xleft' for troff's return to left margin. - *----------------------------------------------------------------------------*/ - -void -cr() -{ - printf("\n.sp -1\n"); - lastx = xleft; -} - - -/*----------------------------------------------------------------------------* - | Routine: line ( ) - | - | Results: Draws a single solid line to (x,y). - *----------------------------------------------------------------------------*/ - -void -line(int px, - int py) -{ - printf("\\D'l"); - printf(" %du", px - lastx); - printf(" %du'", py - lastyline); - lastx = px; - lastyline = lasty = py; -} - - -/*---------------------------------------------------------------------------- - | Routine: drawwig (ptr, type) - | - | Results: The point sequence found in the structure pointed by ptr is - | placed in integer arrays for further manipulation by the - | existing routing. With the corresponding type parameter, - | either picurve or HGCurve are called. - *----------------------------------------------------------------------------*/ - -void -drawwig(POINT * ptr, - int type) -{ - register int npts; /* point list index */ - int x[MAXPOINTS], y[MAXPOINTS]; /* point list */ - - for (npts = 1; !Nullpoint(ptr); ptr = PTNextPoint(ptr), npts++) { - x[npts] = (int) (ptr->x * troffscale); - y[npts] = (int) (ptr->y * troffscale); - } - if (--npts) { - if (type == CURVE) /* Use the 2 different types of curves */ - HGCurve(&x[0], &y[0], npts); - else - picurve(&x[0], &y[0], npts); - } -} - - -/*---------------------------------------------------------------------------- - | Routine: HGArc (xcenter, ycenter, xstart, ystart, angle) - | - | Results: This routine plots an arc centered about (cx, cy) counter - | clockwise starting from the point (px, py) through `angle' - | degrees. If angle is 0, a full circle is drawn. It does so - | by creating a draw-path around the arc whose density of - | points depends on the size of the arc. - *----------------------------------------------------------------------------*/ - -void -HGArc(register int cx, - register int cy, - int px, - int py, - int angle) -{ - double xs, ys, resolution, fullcircle; - int m; - register int mask; - register int extent; - register int nx; - register int ny; - register int length; - register double epsilon; - - xs = px - cx; - ys = py - cy; - - length = 0; - - resolution = (1.0 + groff_hypot(xs, ys) / res) * PointsPerInterval; - /* mask = (1 << (int) log10(resolution + 1.0)) - 1; */ - (void) frexp(resolution, &m); /* A bit more elegant than log10 */ - for (mask = 1; mask < m; mask = mask << 1); - mask -= 1; - - epsilon = 1.0 / resolution; - fullcircle = (2.0 * pi) * resolution; - if (angle == 0) - extent = (int) fullcircle; - else - extent = (int) (angle * fullcircle / 360.0); - - HGtline(px, py); - while (--extent >= 0) { - xs += epsilon * ys; - nx = cx + (int) (xs + 0.5); - ys -= epsilon * xs; - ny = cy + (int) (ys + 0.5); - if (!(extent & mask)) { - HGtline(nx, ny); /* put out a point on circle */ - if (length++ > LINELENGTH) { - length = 0; - printf("\\\n"); - } - } - } /* end for */ -} /* end HGArc */ - - -/*---------------------------------------------------------------------------- - | Routine: picurve (xpoints, ypoints, num_of_points) - | - | Results: Draws a curve delimited by (not through) the line segments - | traced by (xpoints, ypoints) point list. This is the `Pic' - | style curve. - *----------------------------------------------------------------------------*/ - -void -picurve(register int *x, - register int *y, - int npts) -{ - register int nseg; /* effective resolution for each curve */ - register int xp; /* current point (and temporary) */ - register int yp; - int pxp, pyp; /* previous point (to make lines from) */ - int i; /* inner curve segment traverser */ - int length = 0; - double w; /* position factor */ - double t1, t2, t3; /* calculation temps */ - - if (x[1] == x[npts] && y[1] == y[npts]) { - x[0] = x[npts - 1]; /* if the lines' ends meet, make */ - y[0] = y[npts - 1]; /* sure the curve meets */ - x[npts + 1] = x[2]; - y[npts + 1] = y[2]; - } else { /* otherwise, make the ends of the */ - x[0] = x[1]; /* curve touch the ending points of */ - y[0] = y[1]; /* the line segments */ - x[npts + 1] = x[npts]; - y[npts + 1] = y[npts]; - } - - pxp = (x[0] + x[1]) / 2; /* make the last point pointers */ - pyp = (y[0] + y[1]) / 2; /* point to the start of the 1st line */ - tmove2(pxp, pyp); - - for (; npts--; x++, y++) { /* traverse the line segments */ - xp = x[0] - x[1]; - yp = y[0] - y[1]; - nseg = (int) groff_hypot((double) xp, (double) yp); - xp = x[1] - x[2]; - yp = y[1] - y[2]; - /* `nseg' is the number of line */ - /* segments that will be drawn for */ - /* each curve segment. */ - nseg = (int) ((double) (nseg + (int) groff_hypot((double) xp, (double) yp)) / - res * PointsPerInterval); - - for (i = 1; i < nseg; i++) { - w = (double) i / (double) nseg; - t1 = w * w; - t3 = t1 + 1.0 - (w + w); - t2 = 2.0 - (t3 + t1); - xp = (((int) (t1 * x[2] + t2 * x[1] + t3 * x[0])) + 1) / 2; - yp = (((int) (t1 * y[2] + t2 * y[1] + t3 * y[0])) + 1) / 2; - - HGtline(xp, yp); - if (length++ > LINELENGTH) { - length = 0; - printf("\\\n"); - } - } - } -} - - -/*---------------------------------------------------------------------------- - | Routine: HGCurve(xpoints, ypoints, num_points) - | - | Results: This routine generates a smooth curve through a set of - | points. The method used is the parametric spline curve on - | unit knot mesh described in `Spline Curve Techniques' by - | Patrick Baudelaire, Robert Flegal, and Robert Sproull -- - | Xerox Parc. - *----------------------------------------------------------------------------*/ - -void -HGCurve(int *x, - int *y, - int numpoints) -{ - double h[MAXPOINTS], dx[MAXPOINTS], dy[MAXPOINTS]; - double d2x[MAXPOINTS], d2y[MAXPOINTS], d3x[MAXPOINTS], d3y[MAXPOINTS]; - double t, t2, t3; - register int j; - register int k; - register int nx; - register int ny; - int lx, ly; - int length = 0; - - lx = x[1]; - ly = y[1]; - tmove2(lx, ly); - - /* - * Solve for derivatives of the curve at each point separately for x and y - * (parametric). - */ - Paramaterize(x, y, h, numpoints); - - /* closed curve */ - if ((x[1] == x[numpoints]) && (y[1] == y[numpoints])) { - PeriodicSpline(h, x, dx, d2x, d3x, numpoints); - PeriodicSpline(h, y, dy, d2y, d3y, numpoints); - } else { - NaturalEndSpline(h, x, dx, d2x, d3x, numpoints); - NaturalEndSpline(h, y, dy, d2y, d3y, numpoints); - } - - /* - * generate the curve using the above information and PointsPerInterval - * vectors between each specified knot. - */ - - for (j = 1; j < numpoints; ++j) { - if ((x[j] == x[j + 1]) && (y[j] == y[j + 1])) - continue; - for (k = 0; k <= PointsPerInterval; ++k) { - t = (double) k *h[j] / (double) PointsPerInterval; - t2 = t * t; - t3 = t * t * t; - nx = x[j] + (int) (t * dx[j] + t2 * d2x[j] / 2 + t3 * d3x[j] / 6); - ny = y[j] + (int) (t * dy[j] + t2 * d2y[j] / 2 + t3 * d3y[j] / 6); - HGtline(nx, ny); - if (length++ > LINELENGTH) { - length = 0; - printf("\\\n"); - } - } /* end for k */ - } /* end for j */ -} /* end HGCurve */ - - -/*---------------------------------------------------------------------------- - | Routine: Paramaterize (xpoints, ypoints, hparams, num_points) - | - | Results: This routine calculates parameteric values for use in - | calculating curves. The parametric values are returned - | in the array h. The values are an approximation of - | cumulative arc lengths of the curve (uses cord length). - | For additional information, see paper cited below. - *----------------------------------------------------------------------------*/ - -void -Paramaterize(int x[], - int y[], - double h[], - int n) -{ - register int dx; - register int dy; - register int i; - register int j; - double u[MAXPOINTS]; - - for (i = 1; i <= n; ++i) { - u[i] = 0; - for (j = 1; j < i; j++) { - dx = x[j + 1] - x[j]; - dy = y[j + 1] - y[j]; - /* Here was overflowing, so I changed it. */ - /* u[i] += sqrt ((double) (dx * dx + dy * dy)); */ - u[i] += groff_hypot((double) dx, (double) dy); - } - } - for (i = 1; i < n; ++i) - h[i] = u[i + 1] - u[i]; -} /* end Paramaterize */ - - -/*---------------------------------------------------------------------------- - | Routine: PeriodicSpline (h, z, dz, d2z, d3z, npoints) - | - | Results: This routine solves for the cubic polynomial to fit a spline - | curve to the the points specified by the list of values. - | The Curve generated is periodic. The algorithms for this - | curve are from the `Spline Curve Techniques' paper cited - | above. - *----------------------------------------------------------------------------*/ - -void -PeriodicSpline(double h[], /* paramaterization */ - int z[], /* point list */ - double dz[], /* to return the 1st derivative */ - double d2z[], /* 2nd derivative */ - double d3z[], /* 3rd derivative */ - int npoints) /* number of valid points */ -{ - double d[MAXPOINTS]; - double deltaz[MAXPOINTS], a[MAXPOINTS], b[MAXPOINTS]; - double c[MAXPOINTS], r[MAXPOINTS], s[MAXPOINTS]; - int i; - - /* step 1 */ - for (i = 1; i < npoints; ++i) { - deltaz[i] = h[i] ? ((double) (z[i + 1] - z[i])) / h[i] : 0; - } - h[0] = h[npoints - 1]; - deltaz[0] = deltaz[npoints - 1]; - - /* step 2 */ - for (i = 1; i < npoints - 1; ++i) { - d[i] = deltaz[i + 1] - deltaz[i]; - } - d[0] = deltaz[1] - deltaz[0]; - - /* step 3a */ - a[1] = 2 * (h[0] + h[1]); - b[1] = d[0]; - c[1] = h[0]; - for (i = 2; i < npoints - 1; ++i) { - a[i] = 2 * (h[i - 1] + h[i]) - - pow((double) h[i - 1], (double) 2.0) / a[i - 1]; - b[i] = d[i - 1] - h[i - 1] * b[i - 1] / a[i - 1]; - c[i] = -h[i - 1] * c[i - 1] / a[i - 1]; - } - - /* step 3b */ - r[npoints - 1] = 1; - s[npoints - 1] = 0; - for (i = npoints - 2; i > 0; --i) { - r[i] = -(h[i] * r[i + 1] + c[i]) / a[i]; - s[i] = (6 * b[i] - h[i] * s[i + 1]) / a[i]; - } - - /* step 4 */ - d2z[npoints - 1] = (6 * d[npoints - 2] - h[0] * s[1] - - h[npoints - 1] * s[npoints - 2]) - / (h[0] * r[1] + h[npoints - 1] * r[npoints - 2] - + 2 * (h[npoints - 2] + h[0])); - for (i = 1; i < npoints - 1; ++i) { - d2z[i] = r[i] * d2z[npoints - 1] + s[i]; - } - d2z[npoints] = d2z[1]; - - /* step 5 */ - for (i = 1; i < npoints; ++i) { - dz[i] = deltaz[i] - h[i] * (2 * d2z[i] + d2z[i + 1]) / 6; - d3z[i] = h[i] ? (d2z[i + 1] - d2z[i]) / h[i] : 0; - } -} /* end PeriodicSpline */ - - -/*---------------------------------------------------------------------------- - | Routine: NaturalEndSpline (h, z, dz, d2z, d3z, npoints) - | - | Results: This routine solves for the cubic polynomial to fit a spline - | curve the the points specified by the list of values. The - | alogrithms for this curve are from the `Spline Curve - | Techniques' paper cited above. - *----------------------------------------------------------------------------*/ - -void -NaturalEndSpline(double h[], /* parameterization */ - int z[], /* Point list */ - double dz[], /* to return the 1st derivative */ - double d2z[], /* 2nd derivative */ - double d3z[], /* 3rd derivative */ - int npoints) /* number of valid points */ -{ - double d[MAXPOINTS]; - double deltaz[MAXPOINTS], a[MAXPOINTS], b[MAXPOINTS]; - int i; - - /* step 1 */ - for (i = 1; i < npoints; ++i) { - deltaz[i] = h[i] ? ((double) (z[i + 1] - z[i])) / h[i] : 0; - } - deltaz[0] = deltaz[npoints - 1]; - - /* step 2 */ - for (i = 1; i < npoints - 1; ++i) { - d[i] = deltaz[i + 1] - deltaz[i]; - } - d[0] = deltaz[1] - deltaz[0]; - - /* step 3 */ - a[0] = 2 * (h[2] + h[1]); - b[0] = d[1]; - for (i = 1; i < npoints - 2; ++i) { - a[i] = 2 * (h[i + 1] + h[i + 2]) - - pow((double) h[i + 1], (double) 2.0) / a[i - 1]; - b[i] = d[i + 1] - h[i + 1] * b[i - 1] / a[i - 1]; - } - - /* step 4 */ - d2z[npoints] = d2z[1] = 0; - for (i = npoints - 1; i > 1; --i) { - d2z[i] = (6 * b[i - 2] - h[i] * d2z[i + 1]) / a[i - 2]; - } - - /* step 5 */ - for (i = 1; i < npoints; ++i) { - dz[i] = deltaz[i] - h[i] * (2 * d2z[i] + d2z[i + 1]) / 6; - d3z[i] = h[i] ? (d2z[i + 1] - d2z[i]) / h[i] : 0; - } -} /* end NaturalEndSpline */ - - -/*----------------------------------------------------------------------------* - | Routine: change (x_position, y_position, visible_flag) - | - | Results: As HGtline passes from the invisible to visible (or vice - | versa) portion of a line, change is called to either draw - | the line, or initialize the beginning of the next one. - | Change calls line to draw segments if visible_flag is set - | (which means we're leaving a visible area). - *----------------------------------------------------------------------------*/ - -void -change(register int x, - register int y, - register int vis) -{ - static int length = 0; - - if (vis) { /* leaving a visible area, draw it. */ - line(x, y); - if (length++ > LINELENGTH) { - length = 0; - printf("\\\n"); - } - } else { /* otherwise, we're entering one, remember */ - /* beginning */ - tmove2(x, y); - } -} - - -/*---------------------------------------------------------------------------- - | Routine: HGtline (xstart, ystart, xend, yend) - | - | Results: Draws a line from current position to (x1,y1) using line(x1, - | y1) to place individual segments of dotted or dashed lines. - *----------------------------------------------------------------------------*/ - -void -HGtline(int x_1, - int y_1) -{ - register int x_0 = lastx; - register int y_0 = lasty; - register int dx; - register int dy; - register int oldcoord; - register int res1; - register int visible; - register int res2; - register int xinc; - register int yinc; - register int dotcounter; - - if (linmod == SOLID) { - line(x_1, y_1); - return; - } - - /* for handling different resolutions */ - dotcounter = linmod << dotshifter; - - xinc = 1; - yinc = 1; - if ((dx = x_1 - x_0) < 0) { - xinc = -xinc; - dx = -dx; - } - if ((dy = y_1 - y_0) < 0) { - yinc = -yinc; - dy = -dy; - } - res1 = 0; - res2 = 0; - visible = 0; - if (dx >= dy) { - oldcoord = y_0; - while (x_0 != x_1) { - if ((x_0 & dotcounter) && !visible) { - change(x_0, y_0, 0); - visible = 1; - } else if (visible && !(x_0 & dotcounter)) { - change(x_0 - xinc, oldcoord, 1); - visible = 0; - } - if (res1 > res2) { - oldcoord = y_0; - res2 += dx - res1; - res1 = 0; - y_0 += yinc; - } - res1 += dy; - x_0 += xinc; - } - } else { - oldcoord = x_0; - while (y_0 != y_1) { - if ((y_0 & dotcounter) && !visible) { - change(x_0, y_0, 0); - visible = 1; - } else if (visible && !(y_0 & dotcounter)) { - change(oldcoord, y_0 - yinc, 1); - visible = 0; - } - if (res1 > res2) { - oldcoord = x_0; - res2 += dy - res1; - res1 = 0; - x_0 += xinc; - } - res1 += dx; - y_0 += yinc; - } - } - if (visible) - change(x_1, y_1, 1); - else - change(x_1, y_1, 0); -} - -/* EOF */ diff --git a/contrib/groff/src/preproc/grn/hpoint.cpp b/contrib/groff/src/preproc/grn/hpoint.cpp deleted file mode 100644 index fa24dca7fd47..000000000000 --- a/contrib/groff/src/preproc/grn/hpoint.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* Last non-groff version: hpoint.c 1.1 84/10/08 */ - -/* - * This file contains routines for manipulating the point data structures - * for the gremlin picture editor. - */ - -#include -#include "gprint.h" - - -/* - * Return pointer to empty point list. - */ -POINT * -PTInit() -{ - return ((POINT *) NULL); -} - - -/* - * This routine creates a new point with coordinates x and y and links it - * into the pointlist. - */ -POINT * -PTMakePoint(double x, - double y, - POINT **pplist) -{ - register POINT *pt; - - if (Nullpoint(pt = *pplist)) { /* empty list */ - *pplist = (POINT *) malloc(sizeof(POINT)); - pt = *pplist; - } else { - while (!Nullpoint(pt->nextpt)) - pt = pt->nextpt; - pt->nextpt = (POINT *) malloc(sizeof(POINT)); - pt = pt->nextpt; - } - - pt->x = x; - pt->y = y; - pt->nextpt = PTInit(); - return (pt); -} /* end PTMakePoint */ - -/* EOF */ diff --git a/contrib/groff/src/preproc/grn/main.cpp b/contrib/groff/src/preproc/grn/main.cpp deleted file mode 100644 index c939647f2c9b..000000000000 --- a/contrib/groff/src/preproc/grn/main.cpp +++ /dev/null @@ -1,907 +0,0 @@ -/* Last non-groff version: main.c 1.23 (Berkeley) 85/08/05 - * - * Adapted to GNU troff by Daniel Senderowicz 99/12/29. - * - * Further refinements by Werner Lemberg 00/02/20. - * - * - * This file contains the main and file system dependent routines for - * processing gremlin files into troff input. The program watches input go - * by to standard output, only interpreting things between .GS and .GE - * lines. Default values (font, size, scale, thickness) may be overridden - * with a `default' command and are further overridden by commands in the - * input. - * - * Inside the GS and GE, commands are accepted to reconfigure the picture. - * At most one command may reside on each line, and each command is followed - * by a parameter separated by white space. The commands are as follows, - * and may be abbreviated down to one character (with exception of `scale' - * and `stipple' down to "sc" and "st") and may be upper or lower case. - * - * default - Make all settings in the current - * .GS/.GE the global defaults. Height, - * width and file are NOT saved. - * 1, 2, 3, 4 - Set size 1, 2, 3, or 4 (followed by an - * integer point size). - * roman, italics, bold, special - Set gremlin's fonts to any other troff - * font (one or two characters). - * stipple, l - Use a stipple font for polygons. Arg - * is troff font name. No Default. Can - * use only one stipple font per picture. - * (See below for stipple font index.) - * scale, x - Scale is IN ADDITION to the global - * scale factor from the default. - * pointscale - Turn on scaling point sizes to match - * `scale' commands. (Optional operand - * `off' to turn it off.) - * narrow, medium, thick - Set widths of lines. - * file - Set the file name to read the gremlin - * picture from. If the file isn't in - * the current directory, the gremlin - * library is tried. - * width, height - These two commands override any - * scaling factor that is in effect, and - * forces the picture to fit into either - * the height or width specified, - * whichever makes the picture smaller. - * The operand for these two commands is - * a floating-point number in units of - * inches. - * l (integer ) - Set association between stipple - * and a stipple `character'. must - * be in the range 0 to NSTIPPLES (16) - * inclusive. The integer operand is an - * index in the stipple font selected. - * Valid cf (cifplot) indices are 1-32 - * (although 24 is not defined), valid ug - * (unigrafix) indices are 1-14, and - * valid gs (gray scale) indices are - * 0-16. Nonetheless, any number between - * 0 and 255 is accepted since new - * stipple fonts may be added. An - * integer operand is required. - * - * Troff number registers used: g1 through g9. g1 is the width of the - * picture, and g2 is the height. g3, and g4, save information, g8 and g9 - * are used for text processing and g5-g7 are reserved. - */ - - -#include "lib.h" - -#include -#include -#include "gprint.h" - -#include "device.h" -#include "font.h" -#include "searchpath.h" -#include "macropath.h" - -#include "errarg.h" -#include "error.h" -#include "defs.h" - -extern "C" const char *Version_string; - -/* database imports */ - -extern void HGPrintElt(ELT *element, int baseline); -extern ELT *DBInit(); -extern ELT *DBRead(register FILE *file); -extern POINT *PTInit(); -extern POINT *PTMakePoint(double x, double y, POINT **pplist); - - -#define SUN_SCALEFACTOR 0.70 - -/* #define DEFSTIPPLE "gs" */ -#define DEFSTIPPLE "cf" - -#define MAXINLINE 100 /* input line length */ - -#define SCREENtoINCH 0.02 /* scaling factor, screen to inches */ - -#define BIG 999999999999.0 /* unweildly large floating number */ - - -static char sccsid[] = "@(#) (Berkeley) 8/5/85, 12/28/99"; - -int res; /* the printer's resolution goes here */ - -int dotshifter; /* for the length of dotted curves */ - -double linethickness; /* brush styles */ -int linmod; -int lastx; /* point registers for printing elements */ -int lasty; -int lastyline; /* A line's vertical position is NOT the */ - /* same after that line is over, so for a */ - /* line of drawing commands, vertical */ - /* spacing is kept in lastyline */ - -/* These are the default fonts, sizes, line styles, */ -/* and thicknesses. They can be modified from a */ -/* `default' command and are reset each time the */ -/* start of a picture (.GS) is found. */ - -const char *deffont[] = -{"R", "I", "B", "S"}; -int defsize[] = -{10, 16, 24, 36}; -/* #define BASE_THICKNESS 1.0 */ -#define BASE_THICKNESS 0.15 -double defthick[STYLES] = -{1 * BASE_THICKNESS, - 1 * BASE_THICKNESS, - 5 * BASE_THICKNESS, - 1 * BASE_THICKNESS, - 1 * BASE_THICKNESS, - 3 * BASE_THICKNESS}; - -/* int cf_stipple_index[NSTIPPLES + 1] = */ -/* {0, 1, 3, 12, 14, 16, 19, 21, 23}; */ -/* a logarithmic scale looks better than a linear one for the gray shades */ -/* */ -/* int other_stipple_index[NSTIPPLES + 1] = */ -/* {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; */ - -int cf_stipple_index[NSTIPPLES + 1] = -{0, 18, 32, 56, 100, 178, 316, 562, 1000}; /* only 1-8 used */ -int other_stipple_index[NSTIPPLES + 1] = -{0, 62, 125, 187, 250, 312, 375, 437, 500, - 562, 625, 687, 750, 812, 875, 937, 1000}; - -/* int *defstipple_index = other_stipple_index; */ -int *defstipple_index = cf_stipple_index; - -int style[STYLES] = -{DOTTED, DOTDASHED, SOLID, DASHED, SOLID, SOLID}; -double scale = 1.0; /* no scaling, default */ -int defpoint = 0; /* flag for pointsize scaling */ -char *defstipple = (char *) 0; -enum E { - OUTLINE, FILL, BOTH -} polyfill; - -/* flag to controll filling of polygons */ - -double adj1 = 0.0; -double adj2 = 0.0; -double adj3 = 0.0; -double adj4 = 0.0; - -double thick[STYLES]; /* thicknesses set by defaults, then by */ - /* commands */ -char *tfont[FONTS]; /* fonts originally set to deffont values, */ - /* then */ -int tsize[SIZES]; /* optionally changed by commands inside */ - /* grn */ -int stipple_index[NSTIPPLES + 1]; /* stipple font file indices */ -char *stipple; - -double xscale; /* scaling factor from individual pictures */ -double troffscale; /* scaling factor at output time */ - -double width; /* user-request maximum width for picture */ - /* (in inches) */ -double height; /* user-request height */ -int pointscale; /* flag for pointsize scaling */ -int setdefault; /* flag for a .GS/.GE to remember all */ - /* settings */ -int sflag; /* -s flag: sort order (do polyfill first) */ - -double toppoint; /* remember the picture */ -double bottompoint; /* bounds in these variables */ -double leftpoint; -double rightpoint; - -int ytop; /* these are integer versions of the above */ -int ybottom; /* so not to convert each time they're used */ -int xleft; -int xright; - -int linenum = 0; /* line number of input file */ -char inputline[MAXINLINE]; /* spot to filter through the file */ -char *c1 = inputline; /* c1, c2, and c3 will be used to */ -char *c2 = inputline + 1; /* hunt for lines that begin with */ -char *c3 = inputline + 2; /* ".GS" by looking individually */ -char *c4 = inputline + 3; /* needed for compatibility mode */ -char GScommand[MAXINLINE]; /* put user's ".GS" command line here */ -char gremlinfile[MAXINLINE]; /* filename to use for a picture */ -int SUNFILE = FALSE; /* TRUE if SUN gremlin file */ -int compatibility_flag = FALSE; /* TRUE if in compatibility mode */ - - -void getres(); -int doinput(FILE *fp); -void conv(register FILE *fp, int baseline); -void savestate(); -int has_polygon(register ELT *elist); -void interpret(char *line); - - -void -usage(FILE *stream) -{ - fprintf(stream, - "usage: %s [ -vCs ] [ -M dir ] [ -F dir ] [ -T dev ] [ file ]\n", - program_name); -} - - -/*----------------------------------------------------------------------------* - | Routine: main (argument_count, argument_pointer) - | - | Results: Parses the command line, accumulating input file names, then - | reads the inputs, passing it directly to output until a `.GS' - | line is read. Main then passes control to `conv' to do the - | gremlin file conversions. - *----------------------------------------------------------------------------*/ - -int -main(int argc, - char **argv) -{ - setlocale(LC_NUMERIC, "C"); - program_name = argv[0]; - register FILE *fp; - register int k; - register char c; - register int gfil = 0; - char *file[50]; - char *operand(int *argcp, char ***argvp); - - while (--argc) { - if (**++argv != '-') - file[gfil++] = *argv; - else - switch (c = (*argv)[1]) { - - case 0: - file[gfil++] = NULL; - break; - - case 'C': /* compatibility mode */ - compatibility_flag = TRUE; - break; - - case 'F': /* font path to find DESC */ - font::command_line_font_dir(operand(&argc, &argv)); - break; - - case 'T': /* final output typesetter name */ - device = operand(&argc, &argv); - break; - - case 'M': /* set library directory */ - macro_path.command_line_dir(operand(&argc, &argv)); - break; - - case 's': /* preserve order of elements */ - sflag = 1; - break; - - case '-': - if (strcmp(*argv,"--version")==0) { - case 'v': - printf("GNU grn (groff) version %s\n", Version_string); - exit(0); - break; - } - if (strcmp(*argv,"--help")==0) { - case '?': - usage(stdout); - exit(0); - break; - } - // fallthrough - default: - error("unknown switch: %1", c); - usage(stderr); - exit(1); - } - } - - getres(); /* set the resolution for an output device */ - - if (gfil == 0) { /* no filename, use standard input */ - file[0] = NULL; - gfil++; - } - - for (k = 0; k < gfil; k++) { - if (file[k] != NULL) { - if ((fp = fopen(file[k], "r")) == NULL) - fatal("can't open %1", file[k]); - } else - fp = stdin; - - while (doinput(fp)) { - if (*c1 == '.' && *c2 == 'G' && *c3 == 'S') { - if (compatibility_flag || - *c4 == '\n' || *c4 == ' ' || *c4 == '\0') - conv(fp, linenum); - else - fputs(inputline, stdout); - } else - fputs(inputline, stdout); - } - } - - return 0; -} - - -/*----------------------------------------------------------------------------* - | Routine: char * operand (& argc, & argv) - | - | Results: Returns address of the operand given with a command-line - | option. It uses either `-Xoperand' or `-X operand', whichever - | is present. The program is terminated if no option is - | present. - | - | Side Efct: argc and argv are updated as necessary. - *----------------------------------------------------------------------------*/ - -char * -operand(int *argcp, - char ***argvp) -{ - if ((**argvp)[2]) - return (**argvp + 2); /* operand immediately follows */ - if ((--*argcp) <= 0) { /* no operand */ - error("command-line option operand missing."); - exit(8); - } - return (*(++(*argvp))); /* operand is next word */ -} - - -/*----------------------------------------------------------------------------* - | Routine: getres () - | - | Results: Sets `res' to the resolution of the output device. - *----------------------------------------------------------------------------*/ - -void -getres() -{ - int linepiece; - - if (!font::load_desc()) - fatal("sorry, I can't continue"); - - res = font::res; - - /* Correct the brush thicknesses based on res */ - /* if (res >= 256) { - defthick[0] = res >> 8; - defthick[1] = res >> 8; - defthick[2] = res >> 4; - defthick[3] = res >> 8; - defthick[4] = res >> 8; - defthick[5] = res >> 6; - } */ - - linepiece = res >> 9; - for (dotshifter = 0; linepiece; dotshifter++) - linepiece = linepiece >> 1; -} - - -/*----------------------------------------------------------------------------* - | Routine: int doinput (file_pointer) - | - | Results: A line of input is read into `inputline'. - | - | Side Efct: "linenum" is incremented. - | - | Bugs: Lines longer than MAXINLINE are NOT checked, except for - | updating `linenum'. - *----------------------------------------------------------------------------*/ - -int -doinput(FILE *fp) -{ - if (fgets(inputline, MAXINLINE, fp) == NULL) - return 0; - if (strchr(inputline, '\n')) /* ++ only if it's a complete line */ - linenum++; - return 1; -} - - -/*----------------------------------------------------------------------------* - | Routine: initpic ( ) - | - | Results: Sets all parameters to the normal defaults, possibly - | overridden by a setdefault command. Initialize the picture - | variables, and output the startup commands to troff to begin - | the picture. - *----------------------------------------------------------------------------*/ - -void -initpic() -{ - register int i; - - for (i = 0; i < STYLES; i++) { /* line thickness defaults */ - thick[i] = defthick[i]; - } - for (i = 0; i < FONTS; i++) { /* font name defaults */ - tfont[i] = (char *)deffont[i]; - } - for (i = 0; i < SIZES; i++) { /* font size defaults */ - tsize[i] = defsize[i]; - } - for (i = 0; i <= NSTIPPLES; i++) { /* stipple font file default indices */ - stipple_index[i] = defstipple_index[i]; - } - stipple = defstipple; - - gremlinfile[0] = 0; /* filename is `null' */ - setdefault = 0; /* this is not the default settings (yet) */ - - toppoint = BIG; /* set the picture bounds out */ - bottompoint = -BIG; /* of range so they'll be set */ - leftpoint = BIG; /* by `savebounds' on input */ - rightpoint = -BIG; - - pointscale = defpoint; /* flag for scaling point sizes default */ - xscale = scale; /* default scale of individual pictures */ - width = 0.0; /* size specifications input by user */ - height = 0.0; - - linethickness = DEFTHICK; /* brush styles */ - linmod = DEFSTYLE; -} - - -/*----------------------------------------------------------------------------* - | Routine: conv (file_pointer, starting_line) - | - | Results: At this point, we just passed a `.GS' line in the input - | file. conv reads the input and calls `interpret' to process - | commands, gathering up information until a `.GE' line is - | found. It then calls `HGPrint' to do the translation of the - | gremlin file to troff commands. - *----------------------------------------------------------------------------*/ - -void -conv(register FILE *fp, - int baseline) -{ - register FILE *gfp = NULL; /* input file pointer */ - register int done = 0; /* flag to remember if finished */ - register ELT *e; /* current element pointer */ - ELT *PICTURE; /* whole picture data base pointer */ - double temp; /* temporary calculating area */ - /* POINT ptr; */ /* coordinates of a point to pass to `mov' */ - /* routine */ - int flyback; /* flag `want to end up at the top of the */ - /* picture?' */ - int compat; /* test character after .GE or .GF */ - - - initpic(); /* set defaults, ranges, etc. */ - strcpy(GScommand, inputline); /* save `.GS' line for later */ - - do { - done = !doinput(fp); /* test for EOF */ - flyback = (*c3 == 'F'); /* and .GE or .GF */ - compat = (compatibility_flag || - *c4 == '\n' || *c4 == ' ' || *c4 == '\0'); - done |= (*c1 == '.' && *c2 == 'G' && (*c3 == 'E' || flyback) && - compat); - - if (done) { - if (setdefault) - savestate(); - - if (!gremlinfile[0]) { - if (!setdefault) - error("at line %1: no picture filename.\n", baseline); - return; - } - char *path; - gfp = macro_path.open_file(gremlinfile, &path); - if (!gfp) - return; - PICTURE = DBRead(gfp); /* read picture file */ - fclose(gfp); - a_delete path; - if (DBNullelt(PICTURE)) - return; /* If a request is made to make the */ - /* picture fit into a specific area, */ - /* set the scale to do that. */ - - if (stipple == (char *) NULL) /* if user forgot stipple */ - if (has_polygon(PICTURE)) /* and picture has a polygon */ - stipple = (char *)DEFSTIPPLE; /* then set the default */ - - if ((temp = bottompoint - toppoint) < 0.1) - temp = 0.1; - temp = (height != 0.0) ? height / (temp * SCREENtoINCH) : BIG; - if ((troffscale = rightpoint - leftpoint) < 0.1) - troffscale = 0.1; - troffscale = (width != 0.0) ? - width / (troffscale * SCREENtoINCH) : BIG; - if (temp == BIG && troffscale == BIG) - troffscale = xscale; - else { - if (temp < troffscale) - troffscale = temp; - } /* here, troffscale is the */ - /* picture's scaling factor */ - if (pointscale) { - register int i; /* do pointscaling here, when */ - /* scale is known, before output */ - for (i = 0; i < SIZES; i++) - tsize[i] = (int) (troffscale * (double) tsize[i] + 0.5); - } - - /* change to device units */ - troffscale *= SCREENtoINCH * res; /* from screen units */ - - ytop = (int) (toppoint * troffscale); /* calculate integer */ - ybottom = (int) (bottompoint * troffscale); /* versions of the */ - xleft = (int) (leftpoint * troffscale); /* picture limits */ - xright = (int) (rightpoint * troffscale); - - /* save stuff in number registers, */ - /* register g1 = picture width and */ - /* register g2 = picture height, */ - /* set vertical spacing, no fill, */ - /* and break (to make sure picture */ - /* starts on left), and put out the */ - /* user's `.GS' line. */ - printf(".br\n" - ".nr g1 %du\n" - ".nr g2 %du\n" - "%s" - ".nr g3 \\n(.f\n" - ".nr g4 \\n(.s\n" - "\\0\n" - ".sp -1\n", - xright - xleft, ybottom - ytop, GScommand); - - if (stipple) /* stipple requested for this picture */ - printf(".st %s\n", stipple); - lastx = xleft; /* note where we are (upper left */ - lastyline = lasty = ytop; /* corner of the picture) */ - - /* Just dump everything in the order it appears. - * - * If -s command-line option, traverse picture twice: First time, - * print only the interiors of filled polygons (as borderless - * polygons). Second time, print the outline as series of line - * segments. This way, postprocessors that overwrite rather than - * merge picture elements (such as Postscript) can still have text and - * graphics on a shaded background. - */ - /* if (sflag) */ - if (!sflag) { /* changing the default for filled polygons */ - e = PICTURE; - polyfill = FILL; - while (!DBNullelt(e)) { - printf(".mk\n"); - if (e->type == POLYGON) - HGPrintElt(e, baseline); - printf(".rt\n"); - lastx = xleft; - lastyline = lasty = ytop; - e = DBNextElt(e); - } - } - e = PICTURE; - - /* polyfill = !sflag ? BOTH : OUTLINE; */ - polyfill = sflag ? BOTH : OUTLINE; /* changing the default */ - while (!DBNullelt(e)) { - printf(".mk\n"); - HGPrintElt(e, baseline); - printf(".rt\n"); - lastx = xleft; - lastyline = lasty = ytop; - e = DBNextElt(e); - } - - /* decide where to end picture */ - - /* I changed everything here. I always use the combination .mk and */ - /* .rt so once finished I just space down the heigth of the picture */ - /* that is \n(g2u */ - if (flyback) { /* end picture at upper left */ - /* ptr.x = leftpoint; - ptr.y = toppoint; */ - } else { /* end picture at lower left */ - /* ptr.x = leftpoint; - ptr.y = bottompoint; */ - printf(".sp \\n(g2u\n"); - } - - /* tmove(&ptr); */ /* restore default line parameters */ - - /* restore everything to the way it was before the .GS, then put */ - /* out the `.GE' line from user */ - - /* printf("\\D't %du'\\D's %du'\n", DEFTHICK, DEFSTYLE); */ - /* groff doesn't understand the \Ds command */ - - printf("\\D't %du'\n", DEFTHICK); - if (flyback) /* make sure we end up at top of */ - printf(".sp -1\n"); /* picture if `flying back' */ - if (stipple) /* restore stipple to previous */ - printf(".st\n"); - printf(".br\n" - ".ft \\n(g3\n" - ".ps \\n(g4\n" - "%s", inputline); - } else - interpret(inputline); /* take commands from the input file */ - } while (!done); -} - - -/*----------------------------------------------------------------------------* - | Routine: savestate ( ) - | - | Results: all the current scaling / font size / font name / thickness - | / pointscale settings are saved to be the defaults. Scaled - | point sizes are NOT saved. The scaling is done each time a - | new picture is started. - | - | Side Efct: scale, and def* are modified. - *----------------------------------------------------------------------------*/ - -void -savestate() -{ - register int i; - - for (i = 0; i < STYLES; i++) /* line thickness defaults */ - defthick[i] = thick[i]; - for (i = 0; i < FONTS; i++) /* font name defaults */ - deffont[i] = tfont[i]; - for (i = 0; i < SIZES; i++) /* font size defaults */ - defsize[i] = tsize[i]; - for (i = 0; i <= NSTIPPLES; i++) /* stipple font file default indices */ - defstipple_index[i] = stipple_index[i]; - - defstipple = stipple; /* if stipple has been set, it's remembered */ - scale *= xscale; /* default scale of individual pictures */ - defpoint = pointscale; /* flag for scaling pointsizes from x factors */ -} - - -/*----------------------------------------------------------------------------* - | Routine: savebounds (x_coordinate, y_coordinate) - | - | Results: Keeps track of the maximum and minimum extent of a picture - | in the global variables: left-, right-, top- and - | bottompoint. `savebounds' assumes that the points have been - | oriented to the correct direction. No scaling has taken - | place, though. - *----------------------------------------------------------------------------*/ - -void -savebounds(double x, - double y) -{ - if (x < leftpoint) - leftpoint = x; - if (x > rightpoint) - rightpoint = x; - if (y < toppoint) - toppoint = y; - if (y > bottompoint) - bottompoint = y; -} - - -/*----------------------------------------------------------------------------* - | Routine: interpret (character_string) - | - | Results: Commands are taken from the input string and performed. - | Commands are separated by the endofline, and are of the - | format: - | string1 string2 - | - | where string1 is the command and string2 is the argument. - | - | Side Efct: Font and size strings, plus the gremlin file name and the - | width and height variables are set by this routine. - *----------------------------------------------------------------------------*/ - -void -interpret(char *line) -{ - char str1[MAXINLINE]; - char str2[MAXINLINE]; - register char *chr; - register int i; - double par; - - str2[0] = '\0'; - sscanf(line, "%80s%80s", &str1[0], &str2[0]); - for (chr = &str1[0]; *chr; chr++) /* convert command to */ - if (isupper(*chr)) - *chr = tolower(*chr); /* lower case */ - - switch (str1[0]) { - - case '1': - case '2': /* font sizes */ - case '3': - case '4': - i = atoi(str2); - if (i > 0 && i < 1000) - tsize[str1[0] - '1'] = i; - else - error("bad font size value at line %1", linenum); - break; - - case 'r': /* roman */ - if (str2[0] < '0') - goto nofont; - tfont[0] = (char *) malloc(strlen(str2) + 1); - strcpy(tfont[0], str2); - break; - - case 'i': /* italics */ - if (str2[0] < '0') - goto nofont; - tfont[1] = (char *) malloc(strlen(str2) + 1); - strcpy(tfont[1], str2); - break; - - case 'b': /* bold */ - if (str2[0] < '0') - goto nofont; - tfont[2] = (char *) malloc(strlen(str2) + 1); - strcpy(tfont[2], str2); - break; - - case 's': /* special */ - if (str1[1] == 'c') - goto scalecommand; /* or scale */ - - if (str2[0] < '0') { - nofont: - error("no fontname specified in line %1", linenum); - break; - } - if (str1[1] == 't') - goto stipplecommand; /* or stipple */ - - tfont[3] = (char *) malloc(strlen(str2) + 1); - strcpy(tfont[3], str2); - break; - - case 'l': /* l */ - if (isdigit(str1[1])) { /* set stipple index */ - int idx = atoi(str1 + 1), val; - - if (idx < 0 || idx > NSTIPPLES) { - error("bad stipple number %1 at line %2", idx, linenum); - break; - } - if (!defstipple_index) - defstipple_index = other_stipple_index; - val = atoi(str2); - if (val >= 0 && val < 256) - stipple_index[idx] = val; - else - error("bad stipple index value at line %1", linenum); - break; - } - - stipplecommand: /* set stipple name */ - stipple = (char *) malloc(strlen(str2) + 1); - strcpy(stipple, str2); - /* if its a `known' font (currently only `cf'), set indicies */ - if (strcmp(stipple, "cf") == 0) - defstipple_index = cf_stipple_index; - else - defstipple_index = other_stipple_index; - for (i = 0; i <= NSTIPPLES; i++) - stipple_index[i] = defstipple_index[i]; - break; - - case 'a': /* text adjust */ - par = atof(str2); - switch (str1[1]) { - case '1': - adj1 = par; - break; - case '2': - adj2 = par; - break; - case '3': - adj3 = par; - break; - case '4': - adj4 = par; - break; - default: - error("bad adjust command at line %1", linenum); - break; - } - break; - - case 't': /* thick */ - thick[2] = defthick[0] * atof(str2); - break; - - case 'm': /* medium */ - thick[5] = defthick[0] * atof(str2); - break; - - case 'n': /* narrow */ - thick[0] = thick[1] = thick[3] = thick[4] = - defthick[0] * atof(str2); - break; - - case 'x': /* x */ - scalecommand: /* scale */ - par = atof(str2); - if (par > 0.0) - xscale *= par; - else - error("invalid scale value on line %1", linenum); - break; - - case 'f': /* file */ - strcpy(gremlinfile, str2); - break; - - case 'w': /* width */ - width = atof(str2); - if (width < 0.0) - width = -width; - break; - - case 'h': /* height */ - height = atof(str2); - if (height < 0.0) - height = -height; - break; - - case 'd': /* defaults */ - setdefault = 1; - break; - - case 'p': /* pointscale */ - if (strcmp("off", str2)) - pointscale = 1; - else - pointscale = 0; - break; - - default: - error("unknown command `%1' on line %2", str1, linenum); - exit(8); - break; - }; -} - - -/* - * return TRUE if picture contains a polygon - * otherwise FALSE - */ - -int -has_polygon(register ELT *elist) -{ - while (!DBNullelt(elist)) { - if (elist->type == POLYGON) - return (1); - elist = DBNextElt(elist); - } - - return (0); -} - -/* EOF */ diff --git a/contrib/groff/src/preproc/html/Makefile.sub b/contrib/groff/src/preproc/html/Makefile.sub deleted file mode 100644 index 0763537a94e6..000000000000 --- a/contrib/groff/src/preproc/html/Makefile.sub +++ /dev/null @@ -1,7 +0,0 @@ -PROG=pre-grohtml$(EXEEXT) -# MAN1=pre-grohtml.n -MAN1= -XLIBS=$(LIBGROFF) -MLIB=$(LIBM) -OBJS=pre-html.$(OBJEXT) pushback.$(OBJEXT) -CCSRCS=$(srcdir)/pre-html.cpp $(srcdir)/pushback.cpp diff --git a/contrib/groff/src/preproc/html/pre-html.cpp b/contrib/groff/src/preproc/html/pre-html.cpp deleted file mode 100644 index 6f8a46aee0fc..000000000000 --- a/contrib/groff/src/preproc/html/pre-html.cpp +++ /dev/null @@ -1,1779 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. - Written by Gaius Mulley (gaius@glam.ac.uk). - -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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#define PREHTMLC - -#include "lib.h" - -#include -#include -#include -#include -#include -#include "errarg.h" -#include "error.h" -#include "stringclass.h" -#include "posix.h" -#include "defs.h" -#include "searchpath.h" -#include "paper.h" -#include "device.h" -#include "font.h" - -#include -#include -#ifdef HAVE_UNISTD_H -# include -#endif - -#ifdef _POSIX_VERSION -# include -# define PID_T pid_t -#else /* not _POSIX_VERSION */ -# define PID_T int -#endif /* not _POSIX_VERSION */ - -#include - -#include "nonposix.h" - -/* Establish some definitions to facilitate discrimination between - differing runtime environments. */ - -#undef MAY_FORK_CHILD_PROCESS -#undef MAY_SPAWN_ASYNCHRONOUS_CHILD - -#if defined(__MSDOS__) || defined(_WIN32) - -// Most MS-DOS and Win32 environments will be missing the `fork' capability -// (some like Cygwin have it, but it is best avoided). - -# define MAY_FORK_CHILD_PROCESS 0 - -// On these systems, we use `spawn...', instead of `fork' ... `exec...'. -# include // for `spawn...' -# include // for attributes of pipes - -# if defined(__CYGWIN__) || defined(_UWIN) || defined(_WIN32) - -// These Win32 implementations allow parent and `spawn...'ed child to -// multitask asynchronously. - -# define MAY_SPAWN_ASYNCHRONOUS_CHILD 1 - -# else - -// Others may adopt MS-DOS behaviour where parent must sleep, -// from `spawn...' until child terminates. - -# define MAY_SPAWN_ASYNCHRONOUS_CHILD 0 - -# endif /* not defined __CYGWIN__, _UWIN, or _WIN32 */ - -# if defined(DEBUGGING) && !defined(DEBUG_FILE_DIR) -/* When we are building a DEBUGGING version we need to tell pre-grohtml - where to put intermediate files (the DEBUGGING version will preserve - these on exit). - - On a UNIX host, we might simply use `/tmp', but MS-DOS and Win32 will - probably not have this on all disk drives, so default to using - `c:/temp' instead. (Note that user may choose to override this by - supplying a definition such as - - -DDEBUG_FILE_DIR=d:/path/to/debug/files - - in the CPPFLAGS to `make'.) */ - -# define DEBUG_FILE_DIR c:/temp -# endif - -#else /* not __MSDOS__ or _WIN32 */ - -// For non-Microsoft environments assume UNIX conventions, -// so `fork' is required and child processes are asynchronous. -# define MAY_FORK_CHILD_PROCESS 1 -# define MAY_SPAWN_ASYNCHRONOUS_CHILD 1 - -# if defined(DEBUGGING) && !defined(DEBUG_FILE_DIR) -/* For a DEBUGGING version, on the UNIX host, we can also usually rely - on being able to use `/tmp' for temporary file storage. (Note that, - as in the __MSDOS__ or _WIN32 case above, the user may override this - by defining - - -DDEBUG_FILE_DIR=/path/to/debug/files - - in the CPPFLAGS.) */ - -# define DEBUG_FILE_DIR /tmp -# endif - -#endif /* not __MSDOS__ or _WIN32 */ - -#ifdef DEBUGGING -// For a DEBUGGING version, we need some additional macros, -// to direct the captured debug mode output to appropriately named files -// in the specified DEBUG_FILE_DIR. - -# define DEBUG_TEXT(text) #text -# define DEBUG_NAME(text) DEBUG_TEXT(text) -# define DEBUG_FILE(name) DEBUG_NAME(DEBUG_FILE_DIR) "/" name -#endif - -extern "C" const char *Version_string; - -#include "pre-html.h" -#include "pushback.h" -#include "html-strings.h" - -#define DEFAULT_LINE_LENGTH 7 // inches wide -#define DEFAULT_IMAGE_RES 100 // number of pixels per inch resolution -#define IMAGE_BOARDER_PIXELS 0 -#define INLINE_LEADER_CHAR '\\' - -// Don't use colour names here! Otherwise there is a dependency on -// a file called `rgb.txt' which maps names to colours. -#define TRANSPARENT "-background rgb:f/f/f -transparent rgb:f/f/f" -#define MIN_ALPHA_BITS 0 -#define MAX_ALPHA_BITS 4 - -#define PAGE_TEMPLATE_SHORT "pg" -#define PAGE_TEMPLATE_LONG "-page-" -#define PS_TEMPLATE_SHORT "ps" -#define PS_TEMPLATE_LONG "-ps-" -#define REGION_TEMPLATE_SHORT "rg" -#define REGION_TEMPLATE_LONG "-regions-" - -#if 0 -# define DEBUGGING -#endif - -#if !defined(TRUE) -# define TRUE (1==1) -#endif -#if !defined(FALSE) -# define FALSE (1==0) -#endif - -typedef enum { - CENTERED, LEFT, RIGHT, INLINE -} IMAGE_ALIGNMENT; - -static int postscriptRes = -1; // postscript resolution, - // dots per inch -static int stdoutfd = 1; // output file descriptor - - // normally 1 but might move - // -1 means closed -static char *psFileName = NULL; // name of postscript file -static char *psPageName = NULL; // name of file containing - // postscript current page -static char *regionFileName = NULL; // name of file containing all - // image regions -static char *imagePageName = NULL; // name of bitmap image containing - // current page -static const char *image_device = "pnmraw"; -static int image_res = DEFAULT_IMAGE_RES; -static int vertical_offset = 0; -static char *image_template = NULL; // image template filename -static char *macroset_template= NULL; // image template passed to troff - // by -D -static int troff_arg = 0; // troff arg index -static char *image_dir = NULL; // user specified image directory -static int textAlphaBits = MAX_ALPHA_BITS; -static int graphicAlphaBits = MAX_ALPHA_BITS; -static char *antiAlias = NULL; // antialias arguments we pass to gs -static int show_progress = FALSE; // should we display page numbers as - // they are processed? -static int currentPageNo = -1; // current image page number -#if defined(DEBUGGING) -static int debug = FALSE; -static char *troffFileName = NULL; // output of pre-html output which - // is sent to troff -Tps -static char *htmlFileName = NULL; // output of pre-html output which - // is sent to troff -Thtml -#endif - -static char *linebuf = NULL; // for scanning devps/DESC -static int linebufsize = 0; -static const char *image_gen = NULL; // the `gs' program - -const char *const FONT_ENV_VAR = "GROFF_FONT_PATH"; -static search_path font_path(FONT_ENV_VAR, FONTPATH, 0, 0); - - -/* - * Images are generated via postscript, gs, and the pnm utilities. - */ -#define IMAGE_DEVICE "-Tps" - - -static int do_file(const char *filename); - - -/* - * sys_fatal - Write a fatal error message. - * Taken from src/roff/groff/pipeline.c. - */ - -void sys_fatal(const char *s) -{ - fatal("%1: %2", s, strerror(errno)); -} - -/* - * get_line - Copy a line (w/o newline) from a file to the - * global line buffer. - */ - -int get_line(FILE *f) -{ - if (f == 0) - return 0; - if (linebuf == 0) { - linebuf = new char[128]; - linebufsize = 128; - } - int i = 0; - // skip leading whitespace - for (;;) { - int c = getc(f); - if (c == EOF) - return 0; - if (c != ' ' && c != '\t') { - ungetc(c, f); - break; - } - } - for (;;) { - int c = getc(f); - if (c == EOF) - break; - if (i + 1 >= linebufsize) { - char *old_linebuf = linebuf; - linebuf = new char[linebufsize * 2]; - memcpy(linebuf, old_linebuf, linebufsize); - a_delete old_linebuf; - linebufsize *= 2; - } - linebuf[i++] = c; - if (c == '\n') { - i--; - break; - } - } - linebuf[i] = '\0'; - return 1; -} - -/* - * get_resolution - Return the postscript resolution from devps/DESC. - */ - -static unsigned int get_resolution(void) -{ - char *pathp; - FILE *f; - unsigned int res; - f = font_path.open_file("devps/DESC", &pathp); - a_delete pathp; - if (f == 0) - fatal("can't open devps/DESC"); - while (get_line(f)) { - int n = sscanf(linebuf, "res %u", &res); - if (n >= 1) { - fclose(f); - return res; - } - } - fatal("can't find `res' keyword in devps/DESC"); - return 0; -} - -/* - * html_system - A wrapper for system(). - */ - -void html_system(const char *s, int redirect_stdout) -{ - // Redirect standard error to the null device. This is more - // portable than using "2> /dev/null", since it doesn't require a - // Unixy shell. - int save_stderr = dup(2); - int save_stdout = dup(1); - int fdnull = open(NULL_DEV, O_WRONLY|O_BINARY, 0666); - if (save_stderr > 2 && fdnull > 2) - dup2(fdnull, 2); - if (redirect_stdout && save_stdout > 1 && fdnull > 1) - dup2(fdnull, 1); - if (fdnull >= 0) - close(fdnull); - int status = system(s); - dup2(save_stderr, 2); - if (redirect_stdout) - dup2(save_stdout, 1); - if (status == -1) - fprintf(stderr, "Calling `%s' failed\n", s); - else if (status) - fprintf(stderr, "Calling `%s' returned status %d\n", s, status); - close(save_stderr); - close(save_stdout); -} - -/* - * make_message - Create a string via malloc and place the result of the - * va args into string. Finally the new string is returned. - * Taken from man page of printf(3). - */ - -char *make_message(const char *fmt, ...) -{ - /* Guess we need no more than 100 bytes. */ - int n, size = 100; - char *p; - char *np; - va_list ap; - if ((p = (char *)malloc(size)) == NULL) - return NULL; - while (1) { - /* Try to print in the allocated space. */ - va_start(ap, fmt); - n = vsnprintf(p, size, fmt, ap); - va_end(ap); - /* If that worked, return the string. */ - if (n > -1 && n < size - 1) { /* glibc 2.1 and pre-ANSI C 99 */ - if (size > n + 1) { - np = strsave(p); - free(p); - return np; - } - return p; - } - /* Else try again with more space. */ - else /* glibc 2.0 */ - size *= 2; /* twice the old size */ - if ((np = (char *)realloc(p, size)) == NULL) { - free(p); /* realloc failed, free old, p. */ - return NULL; - } - p = np; /* use realloc'ed, p */ - } -} - -/* - * the class and methods for retaining ascii text - */ - -struct char_block { - enum { SIZE = 256 }; - char buffer[SIZE]; - int used; - char_block *next; - - char_block(); -}; - -/* - * char_block - Constructor. Set the, used, and, next, fields to zero. - */ - -char_block::char_block() -: used(0), next(0) -{ - for (int i = 0; i < SIZE; i++) - buffer[i] = 0; -} - -class char_buffer { -public: - char_buffer(); - ~char_buffer(); - int read_file(FILE *fp); - int do_html(int argc, char *argv[]); - int do_image(int argc, char *argv[]); - void emit_troff_output(int device_format_selector); - void write_upto_newline(char_block **t, int *i, int is_html); - int can_see(char_block **t, int *i, const char *string); - int skip_spaces(char_block **t, int *i); - void skip_until_newline(char_block **t, int *i); -private: - char_block *head; - char_block *tail; - int run_output_filter(int device_format_selector, int argc, char *argv[]); -}; - -/* - * char_buffer - Constructor. - */ - -char_buffer::char_buffer() -: head(0), tail(0) -{ -} - -/* - * char_buffer - Destructor. Throw away the whole buffer list. - */ - -char_buffer::~char_buffer() -{ - while (head != NULL) { - char_block *temp = head; - head = head->next; - delete temp; - } -} - -/* - * read_file - Read in a complete file, fp, placing the contents inside - * char_blocks. - */ - -int char_buffer::read_file(FILE *fp) -{ - int n; - while (!feof(fp)) { - if (tail == NULL) { - tail = new char_block; - head = tail; - } - else { - if (tail->used == char_block::SIZE) { - tail->next = new char_block; - tail = tail->next; - } - } - // at this point we have a tail which is ready for the next SIZE - // bytes of the file - n = fread(tail->buffer, sizeof(char), char_block::SIZE-tail->used, fp); - if (n <= 0) - // error - return 0; - else - tail->used += n * sizeof(char); - } - return 1; -} - -/* - * writeNbytes - Write n bytes to stdout. - */ - -static void writeNbytes(const char *s, int l) -{ - int n = 0; - int r; - - while (n < l) { - r = write(stdoutfd, s, l - n); - if (r < 0) - sys_fatal("write"); - n += r; - s += r; - } -} - -/* - * writeString - Write a string to stdout. - */ - -static void writeString(const char *s) -{ - writeNbytes(s, strlen(s)); -} - -/* - * makeFileName - Create the image filename template - * and the macroset image template. - */ - -static void makeFileName(void) -{ - if ((image_dir != NULL) && (strchr(image_dir, '%') != NULL)) { - error("cannot use a `%%' within the image directory name"); - exit(1); - } - - if ((image_template != NULL) && (strchr(image_template, '%') != NULL)) { - error("cannot use a `%%' within the image template"); - exit(1); - } - - if (image_dir == NULL) - image_dir = (char *)""; - else if (strlen(image_dir) > 0 - && image_dir[strlen(image_dir) - 1] != '/') { - image_dir = make_message("%s/", image_dir); - if (image_dir == NULL) - sys_fatal("make_message"); - } - - if (image_template == NULL) - macroset_template = make_message("%sgrohtml-%d", image_dir, - (int)getpid()); - else - macroset_template = make_message("%s%s", image_dir, image_template); - - if (macroset_template == NULL) - sys_fatal("make_message"); - - image_template = - (char *)malloc(strlen("-%d") + strlen(macroset_template) + 1); - if (image_template == NULL) - sys_fatal("malloc"); - strcpy(image_template, macroset_template); - strcat(image_template, "-%d"); -} - -/* - * setupAntiAlias - Set up the antialias string, used when we call gs. - */ - -static void setupAntiAlias(void) -{ - if (textAlphaBits == 0 && graphicAlphaBits == 0) - antiAlias = make_message(" "); - else if (textAlphaBits == 0) - antiAlias = make_message("-dGraphicsAlphaBits=%d ", graphicAlphaBits); - else if (graphicAlphaBits == 0) - antiAlias = make_message("-dTextAlphaBits=%d ", textAlphaBits); - else - antiAlias = make_message("-dTextAlphaBits=%d -dGraphicsAlphaBits=%d ", - textAlphaBits, graphicAlphaBits); -} - -/* - * checkImageDir - Check whether the image directory is available. - */ - -static void checkImageDir(void) -{ - if (image_dir != NULL && strcmp(image_dir, "") != 0) - if (!(mkdir(image_dir, 0777) == 0 || errno == EEXIST)) { - error("cannot create directory `%1'", image_dir); - exit(1); - } -} - -/* - * write_end_image - End the image. Write out the image extents if we - * are using -Tps. - */ - -static void write_end_image(int is_html) -{ - /* - * if we are producing html then these - * emit image name and enable output - * else - * we are producing images - * in which case these generate image - * boundaries - */ - writeString("\\O[4]\\O[2]"); - if (is_html) - writeString("\\O[1]"); - else - writeString("\\O[0]"); -} - -/* - * write_start_image - Write troff code which will: - * - * (i) disable html output for the following image - * (ii) reset the max/min x/y registers during postscript - * rendering. - */ - -static void write_start_image(IMAGE_ALIGNMENT pos, int is_html) -{ - writeString("\\O[5"); - switch (pos) { - case INLINE: - writeString("i"); - break; - case LEFT: - writeString("l"); - break; - case RIGHT: - writeString("r"); - break; - case CENTERED: - default: - writeString("c"); - break; - } - writeString(image_template); - writeString(".png]"); - if (is_html) - writeString("\\O[0]\\O[3]"); - else - // reset min/max registers - writeString("\\O[1]\\O[3]"); -} - -/* - * write_upto_newline - Write the contents of the buffer until a newline - * is seen. Check for HTML_IMAGE_INLINE_BEGIN and - * HTML_IMAGE_INLINE_END; process them if they are - * present. - */ - -void char_buffer::write_upto_newline(char_block **t, int *i, int is_html) -{ - int j = *i; - - if (*t) { - while (j < (*t)->used - && (*t)->buffer[j] != '\n' - && (*t)->buffer[j] != INLINE_LEADER_CHAR) - j++; - if (j < (*t)->used - && (*t)->buffer[j] == '\n') - j++; - writeNbytes((*t)->buffer + (*i), j - (*i)); - if ((*t)->buffer[j] == INLINE_LEADER_CHAR) { - if (can_see(t, &j, HTML_IMAGE_INLINE_BEGIN)) - write_start_image(INLINE, is_html); - else if (can_see(t, &j, HTML_IMAGE_INLINE_END)) - write_end_image(is_html); - else { - if (j < (*t)->used) { - *i = j; - j++; - writeNbytes((*t)->buffer + (*i), j - (*i)); - } - } - } - if (j == (*t)->used) { - *i = 0; - *t = (*t)->next; - if (*t && (*t)->buffer[j - 1] != '\n') - write_upto_newline(t, i, is_html); - } - else - // newline was seen - *i = j; - } -} - -/* - * can_see - Return TRUE if we can see string in t->buffer[i] onwards. - */ - -int char_buffer::can_see(char_block **t, int *i, const char *str) -{ - int j = 0; - int l = strlen(str); - int k = *i; - char_block *s = *t; - - while (s) { - while (k < s->used && j < l && s->buffer[k] == str[j]) { - j++; - k++; - } - if (j == l) { - *i = k; - *t = s; - return TRUE; - } - else if (k < s->used && s->buffer[k] != str[j]) - return( FALSE ); - s = s->next; - k = 0; - } - return FALSE; -} - -/* - * skip_spaces - Return TRUE if we have not run out of data. - * Consume spaces also. - */ - -int char_buffer::skip_spaces(char_block **t, int *i) -{ - char_block *s = *t; - int k = *i; - - while (s) { - while (k < s->used && isspace(s->buffer[k])) - k++; - if (k == s->used) { - k = 0; - s = s->next; - } - else { - *i = k; - return TRUE; - } - } - return FALSE; -} - -/* - * skip_until_newline - Skip all characters until a newline is seen. - * The newline is not consumed. - */ - -void char_buffer::skip_until_newline(char_block **t, int *i) -{ - int j = *i; - - if (*t) { - while (j < (*t)->used && (*t)->buffer[j] != '\n') - j++; - if (j == (*t)->used) { - *i = 0; - *t = (*t)->next; - skip_until_newline(t, i); - } - else - // newline was seen - *i = j; - } -} - -#define DEVICE_FORMAT(filter) (filter == HTML_OUTPUT_FILTER) -#define HTML_OUTPUT_FILTER 0 -#define IMAGE_OUTPUT_FILTER 1 -#define OUTPUT_STREAM(name) creat((name), S_IWUSR | S_IRUSR) -#define PS_OUTPUT_STREAM OUTPUT_STREAM(psFileName) -#define REGION_OUTPUT_STREAM OUTPUT_STREAM(regionFileName) - -/* - * emit_troff_output - Write formatted buffer content to the troff - * post-processor data pipeline. - */ - -void char_buffer::emit_troff_output(int device_format_selector) -{ - // Handle output for BOTH html and image device formats - // if `device_format_selector' is passed as - // - // HTML_FORMAT(HTML_OUTPUT_FILTER) - // Buffer data is written to the output stream - // with template image names translated to actual image names. - // - // HTML_FORMAT(IMAGE_OUTPUT_FILTER) - // Buffer data is written to the output stream - // with no translation, for image file creation in the post-processor. - - int idx = 0; - char_block *element = head; - - while (element != NULL) - write_upto_newline(&element, &idx, device_format_selector); - -#if 0 - if (close(stdoutfd) < 0) - sys_fatal ("close"); - - // now we grab fd=1 so that the next pipe cannot use fd=1 - if (stdoutfd == 1) { - if (dup(2) != stdoutfd) - sys_fatal ("dup failed to use fd=1"); - } -#endif /* 0 */ -} - -/* - * The image class remembers the position of all images in the - * postscript file and assigns names for each image. - */ - -struct imageItem { - imageItem *next; - int X1; - int Y1; - int X2; - int Y2; - char *imageName; - int resolution; - int maxx; - int pageNo; - - imageItem(int x1, int y1, int x2, int y2, - int page, int res, int max_width, char *name); - ~imageItem(); -}; - -/* - * imageItem - Constructor. - */ - -imageItem::imageItem(int x1, int y1, int x2, int y2, - int page, int res, int max_width, char *name) -{ - X1 = x1; - Y1 = y1; - X2 = x2; - Y2 = y2; - pageNo = page; - resolution = res; - maxx = max_width; - imageName = name; - next = NULL; -} - -/* - * imageItem - Destructor. - */ - -imageItem::~imageItem() -{ - if (imageName) - free(imageName); -} - -/* - * imageList - A class containing a list of imageItems. - */ - -class imageList { -private: - imageItem *head; - imageItem *tail; - int count; -public: - imageList(); - ~imageList(); - void add(int x1, int y1, int x2, int y2, - int page, int res, int maxx, char *name); - void createImages(void); - int createPage(int pageno); - void createImage(imageItem *i); - int getMaxX(int pageno); -}; - -/* - * imageList - Constructor. - */ - -imageList::imageList() -: head(0), tail(0), count(0) -{ -} - -/* - * imageList - Destructor. - */ - -imageList::~imageList() -{ - while (head != NULL) { - imageItem *i = head; - head = head->next; - delete i; - } -} - -/* - * createPage - Create one image of, page pageno, from the postscript file. - */ - -int imageList::createPage(int pageno) -{ - char *s; - - if (currentPageNo == pageno) - return 0; - - if (currentPageNo >= 1) { - /* - * We need to unlink the files which change each time a new page is - * processed. The final unlink is done by xtmpfile when pre-grohtml - * exits. - */ - unlink(imagePageName); - unlink(psPageName); - } - - if (show_progress) { - fprintf(stderr, "[%d] ", pageno); - fflush(stderr); - } - -#if defined(DEBUGGING) - if (debug) - fprintf(stderr, "creating page %d\n", pageno); -#endif - - s = make_message("psselect -q -p%d %s %s\n", - pageno, psFileName, psPageName); - - if (s == NULL) - sys_fatal("make_message"); -#if defined(DEBUGGING) - if (debug) { - fwrite(s, sizeof(char), strlen(s), stderr); - fflush(stderr); - } -#endif - html_system(s, 1); - - s = make_message("echo showpage | " - "%s%s -q -dBATCH -dSAFER " - "-dDEVICEHEIGHTPOINTS=792 " - "-dDEVICEWIDTHPOINTS=%d -dFIXEDMEDIA=true " - "-sDEVICE=%s -r%d %s " - "-sOutputFile=%s %s -\n", - image_gen, - EXE_EXT, - (getMaxX(pageno) * image_res) / postscriptRes, - image_device, - image_res, - antiAlias, - imagePageName, - psPageName); - if (s == NULL) - sys_fatal("make_message"); -#if defined(DEBUGGING) - if (debug) { - fwrite(s, sizeof(char), strlen(s), stderr); - fflush(stderr); - } -#endif - html_system(s, 1); - free(s); - currentPageNo = pageno; - return 0; -} - -/* - * min - Return the minimum of two numbers. - */ - -int min(int x, int y) -{ - if (x < y) - return x; - else - return y; -} - -/* - * max - Return the maximum of two numbers. - */ - -int max(int x, int y) -{ - if (x > y) - return x; - else - return y; -} - -/* - * getMaxX - Return the largest right-hand position for any image - * on, pageno. - */ - -int imageList::getMaxX(int pageno) -{ - imageItem *h = head; - int x = postscriptRes * DEFAULT_LINE_LENGTH; - - while (h != NULL) { - if (h->pageNo == pageno) - x = max(h->X2, x); - h = h->next; - } - return x; -} - -/* - * createImage - Generate a minimal png file from the set of page images. - */ - -void imageList::createImage(imageItem *i) -{ - if (i->X1 != -1) { - char *s; - int x1 = max(min(i->X1, i->X2) * image_res / postscriptRes - - IMAGE_BOARDER_PIXELS, - 0); - int y1 = max(image_res * vertical_offset / 72 - + min(i->Y1, i->Y2) * image_res / postscriptRes - - IMAGE_BOARDER_PIXELS, - 0); - int x2 = max(i->X1, i->X2) * image_res / postscriptRes - + IMAGE_BOARDER_PIXELS; - int y2 = image_res * vertical_offset / 72 - + max(i->Y1, i->Y2) * image_res / postscriptRes - + 1 + IMAGE_BOARDER_PIXELS; - if (createPage(i->pageNo) == 0) { - s = make_message("pnmcut%s %d %d %d %d < %s " - "| pnmcrop -quiet | pnmtopng%s %s > %s\n", - EXE_EXT, - x1, y1, x2 - x1 + 1, y2 - y1 + 1, - imagePageName, - EXE_EXT, - TRANSPARENT, - i->imageName); - if (s == NULL) - sys_fatal("make_message"); - -#if defined(DEBUGGING) - if (debug) { - fprintf(stderr, s); - fflush(stderr); - } -#endif - html_system(s, 0); - free(s); - } - else { - fprintf(stderr, "failed to generate image of page %d\n", i->pageNo); - fflush(stderr); - } -#if defined(DEBUGGING) - } - else { - if (debug) { - fprintf(stderr, "ignoring image as x1 coord is -1\n"); - fflush(stderr); - } -#endif - } -} - -/* - * add - Add an image description to the imageList. - */ - -void imageList::add(int x1, int y1, int x2, int y2, - int page, int res, int maxx, char *name) -{ - imageItem *i = new imageItem(x1, y1, x2, y2, page, res, maxx, name); - - if (head == NULL) { - head = i; - tail = i; - } - else { - tail->next = i; - tail = i; - } -} - -/* - * createImages - For each image descriptor on the imageList, - * create the actual image. - */ - -void imageList::createImages(void) -{ - imageItem *h = head; - - while (h != NULL) { - createImage(h); - h = h->next; - } -} - -static imageList listOfImages; // List of images defined by the region file. - -/* - * generateImages - Parse the region file and generate images - * from the postscript file. The region file - * contains the x1,y1--x2,y2 extents of each - * image. - */ - -static void generateImages(char *region_file_name) -{ - pushBackBuffer *f=new pushBackBuffer(region_file_name); - - while (f->putPB(f->getPB()) != eof) { - if (f->isString("grohtml-info:page")) { - int page = f->readInt(); - int x1 = f->readInt(); - int y1 = f->readInt(); - int x2 = f->readInt(); - int y2 = f->readInt(); - int maxx = f->readInt(); - char *name = f->readString(); - int res = postscriptRes; - listOfImages.add(x1, y1, x2, y2, page, res, maxx, name); - while (f->putPB(f->getPB()) != '\n' - && f->putPB(f->getPB()) != eof) - (void)f->getPB(); - if (f->putPB(f->getPB()) == '\n') - (void)f->getPB(); - } - else { - /* Write any error messages out to the user. */ - fputc(f->getPB(), stderr); - } - } - - listOfImages.createImages(); - if (show_progress) { - fprintf(stderr, "done\n"); - fflush(stderr); - } - delete f; -} - -/* - * set_redirection - Set up I/O Redirection for handle, was, to refer to - * stream on handle, willbe. - */ - -static void set_redirection(int was, int willbe) -{ - // Nothing to do if `was' and `willbe' already have same handle. - if (was != willbe) { - // Otherwise attempt the specified redirection. - if (dup2 (willbe, was) < 0) { - // Redirection failed, so issue diagnostic and bail out. - fprintf(stderr, "failed to replace fd=%d with %d\n", was, willbe); - if (willbe == STDOUT_FILENO) - fprintf(stderr, - "likely that stdout should be opened before %d\n", was); - sys_fatal("dup2"); - } - - // When redirection has been successfully completed assume redundant - // handle `willbe' is no longer required, so close it. - if (close(willbe) < 0) - // Issue diagnostic if `close' fails. - sys_fatal("close"); - } -} - -/* - * save_and_redirect - Get duplicate handle for stream, was, then - * redirect, was, to refer to, willbe. - */ - -static int save_and_redirect(int was, int willbe) -{ - if (was == willbe) - // No redirection specified so don't do anything but silently bailing out. - return (was); - - // Proceeding with redirection so first save and verify our duplicate - // handle for `was'. - int saved = dup(was); - if (saved < 0) { - fprintf(stderr, "unable to get duplicate handle for %d\n", was); - sys_fatal("dup"); - } - - // Duplicate handle safely established so complete redirection. - set_redirection(was, willbe); - - // Finally return the saved duplicate descriptor for the - // original `was' stream. - return saved; -} - -/* - * alterDeviceTo - If, toImage, is set - * the argument list is altered to include - * IMAGE_DEVICE and we invoke groff rather than troff. - * Else - * set -Thtml and groff. - */ - -static void alterDeviceTo(int argc, char *argv[], int toImage) -{ - int i = 0; - - if (toImage) { - while (i < argc) { - if (strcmp(argv[i], "-Thtml") == 0) - argv[i] = (char *)IMAGE_DEVICE; - i++; - } - argv[troff_arg] = (char *)"groff"; /* rather than troff */ - } - else { - while (i < argc) { - if (strcmp(argv[i], IMAGE_DEVICE) == 0) - argv[i] = (char *)"-Thtml"; - i++; - } - argv[troff_arg] = (char *)"groff"; /* use groff -Z */ - } -} - -/* - * addZ - Append -Z onto the command list for groff. - */ - -char **addZ(int argc, char *argv[]) -{ - char **new_argv = (char **)malloc((argc + 2) * sizeof(char *)); - int i = 0; - - if (new_argv == NULL) - sys_fatal("malloc"); - - if (argc > 0) { - new_argv[i] = argv[i]; - i++; - } - new_argv[i] = (char *)"-Z"; - while (i < argc) { - new_argv[i + 1] = argv[i]; - i++; - } - argc++; - new_argv[argc] = NULL; - return new_argv; -} - -/* - * addRegDef - Append a defined register or string onto the command - * list for troff. - */ - -char **addRegDef(int argc, char *argv[], const char *numReg) -{ - char **new_argv = (char **)malloc((argc + 2) * sizeof(char *)); - int i = 0; - - if (new_argv == NULL) - sys_fatal("malloc"); - - while (i < argc) { - new_argv[i] = argv[i]; - i++; - } - new_argv[argc] = strsave(numReg); - argc++; - new_argv[argc] = NULL; - return new_argv; -} - -/* - * dump_args - Display the argument list. - */ - -void dump_args(int argc, char *argv[]) -{ - fprintf(stderr, " %d arguments:", argc); - for (int i = 0; i < argc; i++) - fprintf(stderr, " %s", argv[i]); - fprintf(stderr, "\n"); -} - -int char_buffer::run_output_filter(int filter, int /* argc */, char **argv) -{ - int pipedes[2]; - PID_T child_pid; - int status; - - if (pipe(pipedes) < 0) - sys_fatal("pipe"); - -#if MAY_FORK_CHILD_PROCESS - // This is the UNIX process model. To invoke our post-processor, - // we must `fork' the current process. - - if ((child_pid = fork()) < 0) - sys_fatal("fork"); - - else if (child_pid == 0) { - // This is the child process fork. We redirect its `stdin' stream - // to read data emerging from our pipe. There is no point in saving, - // since we won't be able to restore later! - - set_redirection(STDIN_FILENO, pipedes[0]); - - // The parent process will be writing this data, so we should release - // the child's writeable handle on the pipe, since we have no use for it. - - if (close(pipedes[1]) < 0) - sys_fatal("close"); - - // The IMAGE_OUTPUT_FILTER needs special output redirection... - - if (filter == IMAGE_OUTPUT_FILTER) { - // with BOTH `stdout' AND `stderr' diverted to files. - - set_redirection(STDOUT_FILENO, PS_OUTPUT_STREAM); - set_redirection(STDERR_FILENO, REGION_OUTPUT_STREAM); - } - - // Now we are ready to launch the output filter. - - execvp(argv[0], argv); - - // If we get to here then the `exec...' request for the output filter - // failed. Diagnose it and bail out. - - error("couldn't exec %1: %2", argv[0], strerror(errno), ((char *)0)); - fflush(stderr); // just in case error() didn't - exit(1); - } - - else { - // This is the parent process fork. We will be writing data to the - // filter pipeline, and the child will be reading it. We have no further - // use for our read handle on the pipe, and should close it. - - if (close(pipedes[0]) < 0) - sys_fatal("close"); - - // Now we redirect the `stdout' stream to the inlet end of the pipe, - // and push out the appropiately formatted data to the filter. - - pipedes[1] = save_and_redirect(STDOUT_FILENO, pipedes[1]); - emit_troff_output(DEVICE_FORMAT(filter)); - - // After emitting all the data we close our connection to the inlet - // end of the pipe so the child process will detect end of data. - - set_redirection(STDOUT_FILENO, pipedes[1]); - - // Finally, we must wait for the child process to complete. - - if (WAIT(&status, child_pid, _WAIT_CHILD) != child_pid) - sys_fatal("wait"); - } - -#elif MAY_SPAWN_ASYNCHRONOUS_CHILD - - // We do not have `fork', (or we prefer not to use it), - // but asynchronous processes are allowed, passing data through pipes. - // This should be ok for most Win32 systems and is preferred to `fork' - // for starting child processes under Cygwin. - - // Before we start the post-processor we bind its inherited `stdin' - // stream to the readable end of our pipe, saving our own `stdin' stream - // in `pipedes[0]'. - - pipedes[0] = save_and_redirect(STDIN_FILENO, pipedes[0]); - - // for the Win32 model, - // we need special provision for saving BOTH `stdout' and `stderr'. - - int saved_stdout = dup(STDOUT_FILENO); - int saved_stderr = STDERR_FILENO; - - // The IMAGE_OUTPUT_FILTER needs special output redirection... - - if (filter == IMAGE_OUTPUT_FILTER) { - // with BOTH `stdout' AND `stderr' diverted to files while saving a - // duplicate handle for `stderr'. - - set_redirection(STDOUT_FILENO, PS_OUTPUT_STREAM); - saved_stderr = save_and_redirect(STDERR_FILENO, REGION_OUTPUT_STREAM); - } - - // We then use an asynchronous spawn request to start the post-processor. - - if ((child_pid = spawnvp(_P_NOWAIT, argv[0], argv)) < 0) { - // Should the spawn request fail we issue a diagnostic and bail out. - - error("cannot spawn %1: %2", argv[0], strerror(errno), ((char *)0)); - exit(1); - } - - // Once the post-processor has been started we revert our `stdin' - // to its original saved source, which also closes the readable handle - // for the pipe. - - set_redirection(STDIN_FILENO, pipedes[0]); - - // if we redirected `stderr', for use by the image post-processor, - // then we also need to reinstate its original assignment. - - if (filter == IMAGE_OUTPUT_FILTER) - set_redirection(STDERR_FILENO, saved_stderr); - - // Now we redirect the `stdout' stream to the inlet end of the pipe, - // and push out the appropiately formatted data to the filter. - - set_redirection(STDOUT_FILENO, pipedes[1]); - emit_troff_output(DEVICE_FORMAT(filter)); - - // After emitting all the data we close our connection to the inlet - // end of the pipe so the child process will detect end of data. - - set_redirection(STDOUT_FILENO, saved_stdout); - - // And finally, we must wait for the child process to complete. - - if (WAIT(&status, child_pid, _WAIT_CHILD) != child_pid) - sys_fatal("wait"); - -#else /* can't do asynchronous pipes! */ - - // TODO: code to support an MS-DOS style process model - // should go here - -#endif /* MAY_FORK_CHILD_PROCESS or MAY_SPAWN_ASYNCHRONOUS_CHILD */ - - return 0; -} - -/* - * do_html - Set the troff number htmlflip and - * write out the buffer to troff -Thtml. - */ - -int char_buffer::do_html(int argc, char *argv[]) -{ - string s; - - alterDeviceTo(argc, argv, 0); - argv += troff_arg; // skip all arguments up to groff - argc -= troff_arg; - argv = addZ(argc, argv); - argc++; - - s = "-dwww-image-template="; - s += macroset_template; // do not combine these statements, - // otherwise they will not work - s += '\0'; // the trailing `\0' is ignored - argv = addRegDef(argc, argv, s.contents()); - argc++; - -#if defined(DEBUGGING) -# define HTML_DEBUG_STREAM OUTPUT_STREAM(htmlFileName) - // slight security risk so only enabled if compiled with defined(DEBUGGING) - if (debug) { - int saved_stdout = save_and_redirect(STDOUT_FILENO, HTML_DEBUG_STREAM); - emit_troff_output(DEVICE_FORMAT(HTML_OUTPUT_FILTER)); - set_redirection(STDOUT_FILENO, saved_stdout); - } -#endif - - return run_output_filter(HTML_OUTPUT_FILTER, argc, argv); -} - -/* - * do_image - Write out the buffer to troff -Tps. - */ - -int char_buffer::do_image(int argc, char *argv[]) -{ - string s; - - alterDeviceTo(argc, argv, 1); - argv += troff_arg; // skip all arguments up to troff/groff - argc -= troff_arg; - argv = addRegDef(argc, argv, "-rps4html=1"); - argc++; - - s = "-dwww-image-template="; - s += macroset_template; - s += '\0'; - argv = addRegDef(argc, argv, s.contents()); - argc++; - - // override local settings and produce a page size letter postscript file - argv = addRegDef(argc, argv, "-P-pletter"); - argc++; - -#if defined(DEBUGGING) -# define IMAGE_DEBUG_STREAM OUTPUT_STREAM(troffFileName) - // slight security risk so only enabled if compiled with defined(DEBUGGING) - if (debug) { - int saved_stdout = save_and_redirect(STDOUT_FILENO, IMAGE_DEBUG_STREAM); - emit_troff_output(DEVICE_FORMAT(IMAGE_OUTPUT_FILTER)); - set_redirection(STDOUT_FILENO, saved_stdout); - } -#endif - - return run_output_filter(IMAGE_OUTPUT_FILTER, argc, argv); -} - -static char_buffer inputFile; - -/* - * usage - Emit usage arguments. - */ - -static void usage(FILE *stream) -{ - fprintf(stream, - "usage: %s troffname [-Iimage_name] [-Dimage_directory]\n" - " [-P-o vertical_image_offset] [-P-i image_resolution]\n" - " [troff flags]\n", - program_name); - fprintf(stream, - " vertical_image_offset (default %d/72 of an inch)\n", - vertical_offset); - fprintf(stream, - " image_resolution (default %d) pixels per inch\n", - image_res); - fprintf(stream, - " image_name is the name of the stem for all images\n" - " (default is grohtml-)\n"); - fprintf(stream, - " place all png files into image_directory\n"); -} - -/* - * scanArguments - Scan for all arguments including -P-i, -P-o, -P-D, - * and -P-I. Return the argument index of the first - * non-option. - */ - -static int scanArguments(int argc, char **argv) -{ - const char *command_prefix = getenv("GROFF_COMMAND_PREFIX"); - if (!command_prefix) - command_prefix = PROG_PREFIX; - char *troff_name = new char[strlen(command_prefix) + strlen("troff") + 1]; - strcpy(troff_name, command_prefix); - strcat(troff_name, "troff"); - int c, i; - static const struct option long_options[] = { - { "help", no_argument, 0, CHAR_MAX + 1 }, - { "version", no_argument, 0, 'v' }, - { NULL, 0, 0, 0 } - }; - while ((c = getopt_long(argc, argv, "+a:bdD:F:g:hi:I:j:lno:prs:S:v", - long_options, NULL)) - != EOF) - switch(c) { - case 'a': - textAlphaBits = min(max(MIN_ALPHA_BITS, atoi(optarg)), - MAX_ALPHA_BITS); - if (textAlphaBits == 3) { - error("cannot use 3 bits of antialiasing information"); - exit(1); - } - break; - case 'b': - // handled by post-grohtml (set background color to white) - break; - case 'd': -#if defined(DEBUGGING) - debug = TRUE; -#endif - break; - case 'D': - image_dir = optarg; - break; - case 'F': - font_path.command_line_dir(optarg); - break; - case 'g': - graphicAlphaBits = min(max(MIN_ALPHA_BITS, atoi(optarg)), - MAX_ALPHA_BITS); - if (graphicAlphaBits == 3) { - error("cannot use 3 bits of antialiasing information"); - exit(1); - } - break; - case 'h': - // handled by post-grohtml - break; - case 'i': - image_res = atoi(optarg); - break; - case 'I': - image_template = optarg; - break; - case 'j': - // handled by post-grohtml (set job name for multiple file output) - break; - case 'l': - // handled by post-grohtml (no automatic section links) - break; - case 'n': - // handled by post-grohtml (generate simple heading anchors) - break; - case 'o': - vertical_offset = atoi(optarg); - break; - case 'p': - show_progress = TRUE; - break; - case 'r': - // handled by post-grohtml (no header and footer lines) - break; - case 's': - // handled by post-grohtml (use font size n as the html base font size) - break; - case 'S': - // handled by post-grohtml (set file split level) - break; - case 'v': - printf("GNU pre-grohtml (groff) version %s\n", Version_string); - exit(0); - case CHAR_MAX + 1: // --help - usage(stdout); - exit(0); - break; - case '?': - usage(stderr); - exit(1); - break; - default: - break; - } - - i = optind; - while (i < argc) { - if (strcmp(argv[i], troff_name) == 0) - troff_arg = i; - else if (argv[i][0] != '-') - return i; - i++; - } - a_delete troff_name; - - return argc; -} - -/* - * makeTempFiles - Name the temporary files. - */ - -static int makeTempFiles(void) -{ -#if defined(DEBUGGING) - psFileName = DEBUG_FILE("prehtml-ps"); - regionFileName = DEBUG_FILE("prehtml-region"); - imagePageName = DEBUG_FILE("prehtml-page"); - psPageName = DEBUG_FILE("prehtml-psn"); - troffFileName = DEBUG_FILE("prehtml-troff"); - htmlFileName = DEBUG_FILE("prehtml-html"); -#else /* not DEBUGGING */ - FILE *f; - - /* psPageName contains a single page of postscript */ - f = xtmpfile(&psPageName, - PS_TEMPLATE_LONG, PS_TEMPLATE_SHORT, - TRUE); - if (f == NULL) { - sys_fatal("xtmpfile"); - return -1; - } - fclose(f); - - /* imagePageName contains a bitmap image of the single postscript page */ - f = xtmpfile(&imagePageName, - PAGE_TEMPLATE_LONG, PAGE_TEMPLATE_SHORT, - TRUE); - if (f == NULL) { - sys_fatal("xtmpfile"); - return -1; - } - fclose(f); - - /* psFileName contains a postscript file of the complete document */ - f = xtmpfile(&psFileName, - PS_TEMPLATE_LONG, PS_TEMPLATE_SHORT, - TRUE); - if (f == NULL) { - sys_fatal("xtmpfile"); - return -1; - } - fclose(f); - - /* regionFileName contains a list of the images and their boxed coordinates */ - f = xtmpfile(®ionFileName, - REGION_TEMPLATE_LONG, REGION_TEMPLATE_SHORT, - TRUE); - if (f == NULL) { - sys_fatal("xtmpfile"); - return -1; - } - fclose(f); - -#endif /* not DEBUGGING */ - return 0; -} - -int main(int argc, char **argv) -{ - program_name = argv[0]; - int i; - int found = 0; - int ok = 1; - -#ifdef CAPTURE_MODE - FILE *dump; - fprintf(stderr, "%s: invoked with %d arguments ...\n", argv[0], argc); - for (i = 0; i < argc; i++) - fprintf(stderr, "%2d: %s\n", i, argv[i]); - if ((dump = fopen(DEBUG_FILE("pre-html-data"), "wb")) != NULL) { - while((i = fgetc(stdin)) >= 0) - fputc(i, dump); - fclose(dump); - } - exit(1); -#endif /* CAPTURE_MODE */ - device = "html"; - if (!font::load_desc()) - fatal("cannot find devhtml/DESC exiting"); - image_gen = font::image_generator; - if (image_gen == NULL || (strcmp(image_gen, "") == 0)) - fatal("devhtml/DESC must set the image_generator field, exiting"); - postscriptRes = get_resolution(); - i = scanArguments(argc, argv); - setupAntiAlias(); - checkImageDir(); - makeFileName(); - while (i < argc) { - if (argv[i][0] != '-') { - /* found source file */ - ok = do_file(argv[i]); - if (!ok) - return 0; - found = 1; - } - i++; - } - - if (!found) - do_file("-"); - if (makeTempFiles()) - return 1; - ok = inputFile.do_image(argc, argv); - if (ok == 0) { - generateImages(regionFileName); - ok = inputFile.do_html(argc, argv); - } - return ok; -} - -static int do_file(const char *filename) -{ - FILE *fp; - - current_filename = filename; - if (strcmp(filename, "-") == 0) - fp = stdin; - else { - fp = fopen(filename, "r"); - if (fp == 0) { - error("can't open `%1': %2", filename, strerror(errno)); - return 0; - } - } - - if (inputFile.read_file(fp)) { - // XXX - } - - if (fp != stdin) - fclose(fp); - current_filename = NULL; - return 1; -} diff --git a/contrib/groff/src/preproc/html/pre-html.h b/contrib/groff/src/preproc/html/pre-html.h deleted file mode 100644 index 3eedb21c72bb..000000000000 --- a/contrib/groff/src/preproc/html/pre-html.h +++ /dev/null @@ -1,37 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 2000, 2001 Free Software Foundation, Inc. - Written by Gaius Mulley (gaius@glam.ac.uk). - -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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* - * defines functions implemented within pre-html.c - */ - -#if !defined(PREHTMLH) -# define PREHTMLH -# if defined(PREHTMLC) -# define EXTERN -# else -# define EXTERN extern -# endif - - -extern void sys_fatal (const char *s); - -#undef EXTERN -#endif diff --git a/contrib/groff/src/preproc/html/pushback.cpp b/contrib/groff/src/preproc/html/pushback.cpp deleted file mode 100644 index b71558783508..000000000000 --- a/contrib/groff/src/preproc/html/pushback.cpp +++ /dev/null @@ -1,329 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc. - Written by Gaius Mulley (gaius@glam.ac.uk). - -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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "lib.h" - -#include -#include -#include -#include -#include -#include "errarg.h" -#include "error.h" -#include "stringclass.h" -#include "posix.h" -#include "nonposix.h" - -#include -#include -#ifdef HAVE_UNISTD_H -#include -#endif - -#include "pushback.h" -#include "pre-html.h" - -#if !defined(TRUE) -# define TRUE (1==1) -#endif - -#if !defined(FALSE) -# define FALSE (1==0) -#endif - -# define ERROR(X) (void)(fprintf(stderr, "%s:%d error %s\n", __FILE__, __LINE__, X) && \ - (fflush(stderr)) && localexit(1)) - - -#define MAXPUSHBACKSTACK 4096 /* maximum number of character that can be pushed back */ - - -/* - * constructor for pushBackBuffer - */ - -pushBackBuffer::pushBackBuffer (char *filename) -{ - charStack = (char *)malloc(MAXPUSHBACKSTACK); - if (charStack == 0) { - sys_fatal("malloc"); - } - stackPtr = 0; /* index to push back stack */ - debug = 0; - verbose = 0; - eofFound = FALSE; - lineNo = 1; - if (strcmp(filename, "") != 0) { - stdIn = dup(0); - close(0); - if (open(filename, O_RDONLY) != 0) { - sys_fatal("when trying to open file"); - } else { - fileName = filename; - } - } -} - -pushBackBuffer::~pushBackBuffer () -{ - if (charStack != 0) { - free(charStack); - } - close(0); - /* restore stdin in file descriptor 0 */ - dup(stdIn); - close(stdIn); -} - -/* - * localexit - wraps exit with a return code to aid the ERROR macro. - */ - -int localexit (int i) -{ - exit(i); - return( 1 ); -} - -/* - * getPB - returns a character, possibly a pushed back character. - */ - -char pushBackBuffer::getPB (void) -{ - if (stackPtr>0) { - stackPtr--; - return( charStack[stackPtr] ); - } else { - char ch; - - if (read(0, &ch, 1) == 1) { - if (verbose) { - printf("%c", ch); - } - if (ch == '\n') { - lineNo++; - } - return( ch ); - } else { - eofFound = TRUE; - return( eof ); - } - } -} - -/* - * putPB - pushes a character onto the push back stack. - * The same character is returned. - */ - -char pushBackBuffer::putPB (char ch) -{ - if (stackPtr=0) { - if (putPB(s[i]) != s[i]) { - ERROR("assert failed"); - } - i--; - } - } - return( FALSE ); -} - -/* - * isDigit - returns TRUE if the character, ch, is a digit. - */ - -static int isDigit (char ch) -{ - return( ((ch>='0') && (ch<='9')) ); -} - -/* - * isHexDigit - returns TRUE if the character, ch, is a hex digit. - */ - -#if 0 -static int isHexDigit (char ch) -{ - return( (isDigit(ch)) || ((ch>='a') && (ch<='f')) ); -} -#endif - -/* - * readInt - returns an integer from the input stream. - */ - -int pushBackBuffer::readInt (void) -{ - int c =0; - int i =0; - int s =1; - char ch=getPB(); - - while (isWhite(ch)) { - ch=getPB(); - } - // now read integer - - if (ch == '-') { - s = -1; - ch = getPB(); - } - while (isDigit(ch)) { - i *= 10; - if ((ch>='0') && (ch<='9')) { - i += (int)(ch-'0'); - } - ch = getPB(); - c++; - } - if (ch != putPB(ch)) { - ERROR("assert failed"); - } - return( i*s ); -} - -/* - * convertToFloat - converts integers, a and b into a.b - */ - -static double convertToFloat (int a, int b) -{ - int c=10; - double f; - - while (b>c) { - c *= 10; - } - f = ((double)a) + (((double)b)/((double)c)); - return( f ); -} - -/* - * readNumber - returns a float representing the word just read. - */ - -double pushBackBuffer::readNumber (void) -{ - int i; - char ch; - - i = readInt(); - if ((ch = getPB()) == '.') { - return convertToFloat(i, readInt()); - } - putPB(ch); - return (double)i; -} - -/* - * readString - reads a string terminated by white space - * and returns a malloced area of memory containing - * a copy of the characters. - */ - -char *pushBackBuffer::readString (void) -{ - char buffer[MAXPUSHBACKSTACK]; - char *str = 0; - int i=0; - char ch=getPB(); - - while (isWhite(ch)) { - ch=getPB(); - } - while ((i < MAXPUSHBACKSTACK) && (! isWhite(ch)) && (! eofFound)) { - buffer[i] = ch; - i++; - ch = getPB(); - } - if (i < MAXPUSHBACKSTACK) { - buffer[i] = (char)0; - str = (char *)malloc(strlen(buffer)+1); - strcpy(str, buffer); - } - return( str ); -} diff --git a/contrib/groff/src/preproc/html/pushback.h b/contrib/groff/src/preproc/html/pushback.h deleted file mode 100644 index 3fddad66f11d..000000000000 --- a/contrib/groff/src/preproc/html/pushback.h +++ /dev/null @@ -1,54 +0,0 @@ -// -*- C -*- -/* Copyright (C) 2000, 2001, 2003, 2004 Free Software Foundation, Inc. - Written by Gaius Mulley (gaius@glam.ac.uk). - -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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - - -#define eof (char)-1 - - -/* - * defines the class and methods implemented within pushback.cpp - */ - -class pushBackBuffer -{ - private: - char *charStack; - int stackPtr; /* index to push back stack */ - int debug; - int verbose; - int eofFound; - char *fileName; - int lineNo; - int stdIn; - - public: - pushBackBuffer (char *); - ~ pushBackBuffer (); - char getPB (void); - char putPB (char ch); - void skipUntilToken (void); - void skipToNewline (void); - double readNumber (void); - int readInt (void); - char *readString (void); - int isString (const char *string); -}; - - diff --git a/contrib/groff/src/preproc/pic/Makefile.sub b/contrib/groff/src/preproc/pic/Makefile.sub deleted file mode 100644 index 94b41fee92b7..000000000000 --- a/contrib/groff/src/preproc/pic/Makefile.sub +++ /dev/null @@ -1,31 +0,0 @@ -PROG=pic$(EXEEXT) -MAN1=pic.n -XLIBS=$(LIBGROFF) -MLIB=$(LIBM) -OBJS=\ - pic.$(OBJEXT) \ - lex.$(OBJEXT) \ - main.$(OBJEXT) \ - object.$(OBJEXT) \ - common.$(OBJEXT) \ - troff.$(OBJEXT) \ - tex.$(OBJEXT) - # fig.$(OBJEXT) -CCSRCS=\ - $(srcdir)/lex.cpp \ - $(srcdir)/main.cpp \ - $(srcdir)/object.cpp \ - $(srcdir)/common.cpp \ - $(srcdir)/troff.cpp \ - $(srcdir)/tex.cpp -HDRS=\ - $(srcdir)/common.h \ - $(srcdir)/object.h \ - $(srcdir)/output.h \ - $(srcdir)/pic.h \ - $(srcdir)/position.h \ - $(srcdir)/text.h -GRAM=$(srcdir)/pic.y -YTABC=pic.cpp -YTABH=pic_tab.h -NAMEPREFIX=$(g) diff --git a/contrib/groff/src/preproc/pic/TODO b/contrib/groff/src/preproc/pic/TODO deleted file mode 100644 index a1d7554d4529..000000000000 --- a/contrib/groff/src/preproc/pic/TODO +++ /dev/null @@ -1,35 +0,0 @@ -In troff mode, dotted and dashed splines. - -Make DELIMITED have type lstr; this would allow us to give better -error messages for problems within the body of for and if constructs. - -In troff mode without -x, fake \D't' with .ps commands. - -Perhaps an option to set command char. - -Add an output class for dumb line printers. It wouldn't be pretty but -it would be better than nothing. Integrate it with texinfo. Useful -for groff -Tascii as well. - -Option to allow better positioning of arrowheads on arcs. - -Perhaps add PostScript output mode. - -Change the interface to the output class so that output devices have -the opportunity to handle arrowheads themselves. - -Consider whether the line thickness should scale. - -Consider whether the test in a for loop should be fuzzy (as it -apparently is in grap). - -Possibly change fillval so that zero is black. - -Provide a way of getting text blocks (positioned with `.in' rather -than \h), into pic. Should be possible to use block of diverted text -in pic. Possibly something similar to T{ and T} in tbl. - -Option to provide macro backtraces. - -Have a path that is searched by `copy' statement. Set by environment -variable or command line option. diff --git a/contrib/groff/src/preproc/pic/common.cpp b/contrib/groff/src/preproc/pic/common.cpp deleted file mode 100644 index 47a23cd920ef..000000000000 --- a/contrib/groff/src/preproc/pic/common.cpp +++ /dev/null @@ -1,647 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2003 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "pic.h" -#include "common.h" - -// output a dashed circle as a series of arcs - -void common_output::dashed_circle(const position ¢, double rad, - const line_type <) -{ - assert(lt.type == line_type::dashed); - line_type slt = lt; - slt.type = line_type::solid; - double dash_angle = lt.dash_width/rad; - int ndashes; - double gap_angle; - if (dash_angle >= M_PI/4.0) { - if (dash_angle < M_PI/2.0) { - gap_angle = M_PI/2.0 - dash_angle; - ndashes = 4; - } - else if (dash_angle < M_PI) { - gap_angle = M_PI - dash_angle; - ndashes = 2; - } - else { - circle(cent, rad, slt, -1.0); - return; - } - } - else { - ndashes = 4*int(ceil(M_PI/(4.0*dash_angle))); - gap_angle = (M_PI*2.0)/ndashes - dash_angle; - } - for (int i = 0; i < ndashes; i++) { - double start_angle = i*(dash_angle+gap_angle) - dash_angle/2.0; - solid_arc(cent, rad, start_angle, start_angle + dash_angle, lt); - } -} - -// output a dotted circle as a series of dots - -void common_output::dotted_circle(const position ¢, double rad, - const line_type <) -{ - assert(lt.type == line_type::dotted); - double gap_angle = lt.dash_width/rad; - int ndots; - if (gap_angle >= M_PI/2.0) { - // always have at least 2 dots - gap_angle = M_PI; - ndots = 2; - } - else { - ndots = 4*int(M_PI/(2.0*gap_angle)); - gap_angle = (M_PI*2.0)/ndots; - } - double ang = 0.0; - for (int i = 0; i < ndots; i++, ang += gap_angle) - dot(cent + position(cos(ang), sin(ang))*rad, lt); -} - -// recursive function for dash drawing, used by dashed_ellipse - -void common_output::ellipse_arc(const position ¢, - const position &z0, const position &z1, - const distance &dim, const line_type <) -{ - assert(lt.type == line_type::solid); - assert(dim.x != 0 && dim.y != 0); - double eps = 0.0001; - position zml = (z0 + z1) / 2; - // apply affine transformation (from ellipse to circle) to compute angle - // of new position, then invert transformation to get exact position - double psi = atan2(zml.y / dim.y, zml.x / dim.x); - position zm = position(dim.x * cos(psi), dim.y * sin(psi)); - // to approximate the ellipse arc with one or more circle arcs, we - // first compute the radius of curvature in zm - double a_2 = dim.x * dim.x; - double a_4 = a_2 * a_2; - double b_2 = dim.y * dim.y; - double b_4 = b_2 * b_2; - double e_2 = a_2 - b_2; - double temp = a_4 * zm.y * zm.y + b_4 * zm.x * zm.x; - double rho = sqrt(temp / a_4 / b_4 * temp / a_4 / b_4 * temp); - // compute center of curvature circle - position M = position(e_2 * zm.x / a_2 * zm.x / a_2 * zm.x, - -e_2 * zm.y / b_2 * zm.y / b_2 * zm.y); - // compute distance between circle and ellipse arc at start and end - double phi0 = atan2(z0.y - M.y, z0.x - M.x); - double phi1 = atan2(z1.y - M.y, z1.x - M.x); - position M0 = position(rho * cos(phi0), rho * sin(phi0)) + M; - position M1 = position(rho * cos(phi1), rho * sin(phi1)) + M; - double dist0 = hypot(z0 - M0) / sqrt(z0 * z0); - double dist1 = hypot(z1 - M1) / sqrt(z1 * z1); - if (dist0 < eps && dist1 < eps) - solid_arc(M + cent, rho, phi0, phi1, lt); - else { - ellipse_arc(cent, z0, zm, dim, lt); - ellipse_arc(cent, zm, z1, dim, lt); - } -} - -// output a dashed ellipse as a series of arcs - -void common_output::dashed_ellipse(const position ¢, const distance &dim, - const line_type <) -{ - assert(lt.type == line_type::dashed); - double dim_x = dim.x / 2; - double dim_y = dim.y / 2; - line_type slt = lt; - slt.type = line_type::solid; - double dw = lt.dash_width; - // we use an approximation to compute the ellipse length (found in: - // Bronstein, Semendjajew, Taschenbuch der Mathematik) - double lambda = (dim.x - dim.y) / (dim.x + dim.y); - double le = M_PI / 2 * (dim.x + dim.y) - * ((64 - 3 * lambda * lambda * lambda * lambda ) - / (64 - 16 * lambda * lambda)); - // for symmetry we make nmax a multiple of 8 - int nmax = 8 * int(le / dw / 8 + 0.5); - if (nmax < 8) { - nmax = 8; - dw = le / 8; - } - int ndash = nmax / 2; - double gapwidth = (le - dw * ndash) / ndash; - double l = 0; - position z = position(dim_x, 0); - position zdot = z; - int j = 0; - int jmax = int(10 / lt.dash_width); - for (int i = 0; i <= nmax; i++) { - position zold = z; - position zpre = zdot; - double ld = (int(i / 2) + 0.5) * dw + int((i + 1) / 2) * gapwidth; - double lold = 0; - double dl = 1; - // find next position for fixed arc length - while (l < ld) { - j++; - lold = l; - zold = z; - double phi = j * 2 * M_PI / jmax; - z = position(dim_x * cos(phi), dim_y * sin(phi)); - dl = hypot(z - zold); - l += dl; - } - // interpolate linearly between the last two points, - // using the length difference as the scaling factor - double delta = (ld - lold) / dl; - zdot = zold + (z - zold) * delta; - // compute angle of new position on the affine circle - // and use it to get the exact value on the ellipse - double psi = atan2(zdot.y / dim_y, zdot.x / dim_x); - zdot = position(dim_x * cos(psi), dim_y * sin(psi)); - if ((i % 2 == 0) && (i > 1)) - ellipse_arc(cent, zpre, zdot, dim / 2, slt); - } -} - -// output a dotted ellipse as a series of dots - -void common_output::dotted_ellipse(const position ¢, const distance &dim, - const line_type <) -{ - assert(lt.type == line_type::dotted); - double dim_x = dim.x / 2; - double dim_y = dim.y / 2; - line_type slt = lt; - slt.type = line_type::solid; - // we use an approximation to compute the ellipse length (found in: - // Bronstein, Semendjajew, Taschenbuch der Mathematik) - double lambda = (dim.x - dim.y) / (dim.x + dim.y); - double le = M_PI / 2 * (dim.x + dim.y) - * ((64 - 3 * lambda * lambda * lambda * lambda ) - / (64 - 16 * lambda * lambda)); - // for symmetry we make nmax a multiple of 4 - int ndots = 4 * int(le / lt.dash_width / 4 + 0.5); - if (ndots < 4) - ndots = 4; - double l = 0; - position z = position(dim_x, 0); - int j = 0; - int jmax = int(10 / lt.dash_width); - for (int i = 1; i <= ndots; i++) { - position zold = z; - double lold = l; - double ld = i * le / ndots; - double dl = 1; - // find next position for fixed arc length - while (l < ld) { - j++; - lold = l; - zold = z; - double phi = j * 2 * M_PI / jmax; - z = position(dim_x * cos(phi), dim_y * sin(phi)); - dl = hypot(z - zold); - l += dl; - } - // interpolate linearly between the last two points, - // using the length difference as the scaling factor - double delta = (ld - lold) / dl; - position zdot = zold + (z - zold) * delta; - // compute angle of new position on the affine circle - // and use it to get the exact value on the ellipse - double psi = atan2(zdot.y / dim_y, zdot.x / dim_x); - zdot = position(dim_x * cos(psi), dim_y * sin(psi)); - dot(cent + zdot, slt); - } -} - -// return non-zero iff we can compute a center - -int compute_arc_center(const position &start, const position ¢, - const position &end, position *result) -{ - // This finds the point along the vector from start to cent that - // is equidistant between start and end. - distance c = cent - start; - distance e = end - start; - double n = c*e; - if (n == 0.0) - return 0; - *result = start + c*((e*e)/(2.0*n)); - return 1; -} - -// output a dashed arc as a series of arcs - -void common_output::dashed_arc(const position &start, const position ¢, - const position &end, const line_type <) -{ - assert(lt.type == line_type::dashed); - position c; - if (!compute_arc_center(start, cent, end, &c)) { - line(start, &end, 1, lt); - return; - } - distance start_offset = start - c; - distance end_offset = end - c; - double start_angle = atan2(start_offset.y, start_offset.x); - double end_angle = atan2(end_offset.y, end_offset.x); - double rad = hypot(c - start); - double dash_angle = lt.dash_width/rad; - double total_angle = end_angle - start_angle; - while (total_angle < 0) - total_angle += M_PI + M_PI; - if (total_angle <= dash_angle*2.0) { - solid_arc(cent, rad, start_angle, end_angle, lt); - return; - } - int ndashes = int((total_angle - dash_angle)/(dash_angle*2.0) + .5); - double dash_and_gap_angle = (total_angle - dash_angle)/ndashes; - for (int i = 0; i <= ndashes; i++) - solid_arc(cent, rad, start_angle + i*dash_and_gap_angle, - start_angle + i*dash_and_gap_angle + dash_angle, lt); -} - -// output a dotted arc as a series of dots - -void common_output::dotted_arc(const position &start, const position ¢, - const position &end, const line_type <) -{ - assert(lt.type == line_type::dotted); - position c; - if (!compute_arc_center(start, cent, end, &c)) { - line(start, &end, 1, lt); - return; - } - distance start_offset = start - c; - distance end_offset = end - c; - double start_angle = atan2(start_offset.y, start_offset.x); - double total_angle = atan2(end_offset.y, end_offset.x) - start_angle; - while (total_angle < 0) - total_angle += M_PI + M_PI; - double rad = hypot(c - start); - int ndots = int(total_angle/(lt.dash_width/rad) + .5); - if (ndots == 0) - dot(start, lt); - else { - for (int i = 0; i <= ndots; i++) { - double a = start_angle + (total_angle*i)/ndots; - dot(cent + position(cos(a), sin(a))*rad, lt); - } - } -} - -void common_output::solid_arc(const position ¢, double rad, - double start_angle, double end_angle, - const line_type <) -{ - line_type slt = lt; - slt.type = line_type::solid; - arc(cent + position(cos(start_angle), sin(start_angle))*rad, - cent, - cent + position(cos(end_angle), sin(end_angle))*rad, - slt); -} - - -void common_output::rounded_box(const position ¢, const distance &dim, - double rad, const line_type <, double fill) -{ - if (fill >= 0.0) - filled_rounded_box(cent, dim, rad, fill); - switch (lt.type) { - case line_type::invisible: - break; - case line_type::dashed: - dashed_rounded_box(cent, dim, rad, lt); - break; - case line_type::dotted: - dotted_rounded_box(cent, dim, rad, lt); - break; - case line_type::solid: - solid_rounded_box(cent, dim, rad, lt); - break; - default: - assert(0); - } -} - - -void common_output::dashed_rounded_box(const position ¢, - const distance &dim, double rad, - const line_type <) -{ - line_type slt = lt; - slt.type = line_type::solid; - - double hor_length = dim.x + (M_PI/2.0 - 2.0)*rad; - int n_hor_dashes = int(hor_length/(lt.dash_width*2.0) + .5); - double hor_gap_width = (n_hor_dashes != 0 - ? hor_length/n_hor_dashes - lt.dash_width - : 0.0); - - double vert_length = dim.y + (M_PI/2.0 - 2.0)*rad; - int n_vert_dashes = int(vert_length/(lt.dash_width*2.0) + .5); - double vert_gap_width = (n_vert_dashes != 0 - ? vert_length/n_vert_dashes - lt.dash_width - : 0.0); - // Note that each corner arc has to be split into two for dashing, - // because one part is dashed using vert_gap_width, and the other - // using hor_gap_width. - double offset = lt.dash_width/2.0; - dash_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad, - -M_PI/4.0, 0, slt, lt.dash_width, vert_gap_width, &offset); - dash_line(cent + position(dim.x/2.0, -dim.y/2.0 + rad), - cent + position(dim.x/2.0, dim.y/2.0 - rad), - slt, lt.dash_width, vert_gap_width, &offset); - dash_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad, - 0, M_PI/4.0, slt, lt.dash_width, vert_gap_width, &offset); - - offset = lt.dash_width/2.0; - dash_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad, - M_PI/4.0, M_PI/2, slt, lt.dash_width, hor_gap_width, &offset); - dash_line(cent + position(dim.x/2.0 - rad, dim.y/2.0), - cent + position(-dim.x/2.0 + rad, dim.y/2.0), - slt, lt.dash_width, hor_gap_width, &offset); - dash_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad, - M_PI/2, 3*M_PI/4.0, slt, lt.dash_width, hor_gap_width, &offset); - - offset = lt.dash_width/2.0; - dash_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad, - 3.0*M_PI/4.0, M_PI, slt, lt.dash_width, vert_gap_width, &offset); - dash_line(cent + position(-dim.x/2.0, dim.y/2.0 - rad), - cent + position(-dim.x/2.0, -dim.y/2.0 + rad), - slt, lt.dash_width, vert_gap_width, &offset); - dash_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad, - M_PI, 5.0*M_PI/4.0, slt, lt.dash_width, vert_gap_width, &offset); - - offset = lt.dash_width/2.0; - dash_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad, - 5*M_PI/4.0, 3*M_PI/2.0, slt, lt.dash_width, hor_gap_width, &offset); - dash_line(cent + position(-dim.x/2.0 + rad, -dim.y/2.0), - cent + position(dim.x/2.0 - rad, -dim.y/2.0), - slt, lt.dash_width, hor_gap_width, &offset); - dash_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad, - 3*M_PI/2, 7*M_PI/4, slt, lt.dash_width, hor_gap_width, &offset); -} - -// Used by dashed_rounded_box. - -void common_output::dash_arc(const position ¢, double rad, - double start_angle, double end_angle, - const line_type <, - double dash_width, double gap_width, - double *offsetp) -{ - double length = (end_angle - start_angle)*rad; - double pos = 0.0; - for (;;) { - if (*offsetp >= dash_width) { - double rem = dash_width + gap_width - *offsetp; - if (pos + rem > length) { - *offsetp += length - pos; - break; - } - else { - pos += rem; - *offsetp = 0.0; - } - } - else { - double rem = dash_width - *offsetp; - if (pos + rem > length) { - solid_arc(cent, rad, start_angle + pos/rad, end_angle, lt); - *offsetp += length - pos; - break; - } - else { - solid_arc(cent, rad, start_angle + pos/rad, - start_angle + (pos + rem)/rad, lt); - pos += rem; - *offsetp = dash_width; - } - } - } -} - -// Used by dashed_rounded_box. - -void common_output::dash_line(const position &start, const position &end, - const line_type <, - double dash_width, double gap_width, - double *offsetp) -{ - distance dist = end - start; - double length = hypot(dist); - if (length == 0.0) - return; - double pos = 0.0; - for (;;) { - if (*offsetp >= dash_width) { - double rem = dash_width + gap_width - *offsetp; - if (pos + rem > length) { - *offsetp += length - pos; - break; - } - else { - pos += rem; - *offsetp = 0.0; - } - } - else { - double rem = dash_width - *offsetp; - if (pos + rem > length) { - line(start + dist*(pos/length), &end, 1, lt); - *offsetp += length - pos; - break; - } - else { - position p(start + dist*((pos + rem)/length)); - line(start + dist*(pos/length), &p, 1, lt); - pos += rem; - *offsetp = dash_width; - } - } - } -} - -void common_output::dotted_rounded_box(const position ¢, - const distance &dim, double rad, - const line_type <) -{ - line_type slt = lt; - slt.type = line_type::solid; - - double hor_length = dim.x + (M_PI/2.0 - 2.0)*rad; - int n_hor_dots = int(hor_length/lt.dash_width + .5); - double hor_gap_width = (n_hor_dots != 0 - ? hor_length/n_hor_dots - : lt.dash_width); - - double vert_length = dim.y + (M_PI/2.0 - 2.0)*rad; - int n_vert_dots = int(vert_length/lt.dash_width + .5); - double vert_gap_width = (n_vert_dots != 0 - ? vert_length/n_vert_dots - : lt.dash_width); - double epsilon = lt.dash_width/(rad*100.0); - - double offset = 0.0; - dot_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad, - -M_PI/4.0, 0, slt, vert_gap_width, &offset); - dot_line(cent + position(dim.x/2.0, -dim.y/2.0 + rad), - cent + position(dim.x/2.0, dim.y/2.0 - rad), - slt, vert_gap_width, &offset); - dot_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad, - 0, M_PI/4.0 - epsilon, slt, vert_gap_width, &offset); - - offset = 0.0; - dot_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad, - M_PI/4.0, M_PI/2, slt, hor_gap_width, &offset); - dot_line(cent + position(dim.x/2.0 - rad, dim.y/2.0), - cent + position(-dim.x/2.0 + rad, dim.y/2.0), - slt, hor_gap_width, &offset); - dot_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad, - M_PI/2, 3*M_PI/4.0 - epsilon, slt, hor_gap_width, &offset); - - offset = 0.0; - dot_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad, - 3.0*M_PI/4.0, M_PI, slt, vert_gap_width, &offset); - dot_line(cent + position(-dim.x/2.0, dim.y/2.0 - rad), - cent + position(-dim.x/2.0, -dim.y/2.0 + rad), - slt, vert_gap_width, &offset); - dot_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad, - M_PI, 5.0*M_PI/4.0 - epsilon, slt, vert_gap_width, &offset); - - offset = 0.0; - dot_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad, - 5*M_PI/4.0, 3*M_PI/2.0, slt, hor_gap_width, &offset); - dot_line(cent + position(-dim.x/2.0 + rad, -dim.y/2.0), - cent + position(dim.x/2.0 - rad, -dim.y/2.0), - slt, hor_gap_width, &offset); - dot_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad, - 3*M_PI/2, 7*M_PI/4 - epsilon, slt, hor_gap_width, &offset); -} - -// Used by dotted_rounded_box. - -void common_output::dot_arc(const position ¢, double rad, - double start_angle, double end_angle, - const line_type <, double gap_width, - double *offsetp) -{ - double length = (end_angle - start_angle)*rad; - double pos = 0.0; - for (;;) { - if (*offsetp == 0.0) { - double ang = start_angle + pos/rad; - dot(cent + position(cos(ang), sin(ang))*rad, lt); - } - double rem = gap_width - *offsetp; - if (pos + rem > length) { - *offsetp += length - pos; - break; - } - else { - pos += rem; - *offsetp = 0.0; - } - } -} - -// Used by dotted_rounded_box. - -void common_output::dot_line(const position &start, const position &end, - const line_type <, double gap_width, - double *offsetp) -{ - distance dist = end - start; - double length = hypot(dist); - if (length == 0.0) - return; - double pos = 0.0; - for (;;) { - if (*offsetp == 0.0) - dot(start + dist*(pos/length), lt); - double rem = gap_width - *offsetp; - if (pos + rem > length) { - *offsetp += length - pos; - break; - } - else { - pos += rem; - *offsetp = 0.0; - } - } -} - -void common_output::solid_rounded_box(const position ¢, - const distance &dim, double rad, - const line_type <) -{ - position tem = cent - dim/2.0; - arc(tem + position(0.0, rad), - tem + position(rad, rad), - tem + position(rad, 0.0), - lt); - tem = cent + position(-dim.x/2.0, dim.y/2.0); - arc(tem + position(rad, 0.0), - tem + position(rad, -rad), - tem + position(0.0, -rad), - lt); - tem = cent + dim/2.0; - arc(tem + position(0.0, -rad), - tem + position(-rad, -rad), - tem + position(-rad, 0.0), - lt); - tem = cent + position(dim.x/2.0, -dim.y/2.0); - arc(tem + position(-rad, 0.0), - tem + position(-rad, rad), - tem + position(0.0, rad), - lt); - position end; - end = cent + position(-dim.x/2.0, dim.y/2.0 - rad); - line(cent - dim/2.0 + position(0.0, rad), &end, 1, lt); - end = cent + position(dim.x/2.0 - rad, dim.y/2.0); - line(cent + position(-dim.x/2.0 + rad, dim.y/2.0), &end, 1, lt); - end = cent + position(dim.x/2.0, -dim.y/2.0 + rad); - line(cent + position(dim.x/2.0, dim.y/2.0 - rad), &end, 1, lt); - end = cent + position(-dim.x/2.0 + rad, -dim.y/2.0); - line(cent + position(dim.x/2.0 - rad, -dim.y/2.0), &end, 1, lt); -} - -void common_output::filled_rounded_box(const position ¢, - const distance &dim, double rad, - double fill) -{ - line_type ilt; - ilt.type = line_type::invisible; - circle(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad, ilt, fill); - circle(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad, ilt, fill); - circle(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad, ilt, fill); - circle(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad, ilt, fill); - position vec[4]; - vec[0] = cent + position(dim.x/2.0, dim.y/2.0 - rad); - vec[1] = cent + position(-dim.x/2.0, dim.y/2.0 - rad); - vec[2] = cent + position(-dim.x/2.0, -dim.y/2.0 + rad); - vec[3] = cent + position(dim.x/2.0, -dim.y/2.0 + rad); - polygon(vec, 4, ilt, fill); - vec[0] = cent + position(dim.x/2.0 - rad, dim.y/2.0); - vec[1] = cent + position(-dim.x/2.0 + rad, dim.y/2.0); - vec[2] = cent + position(-dim.x/2.0 + rad, -dim.y/2.0); - vec[3] = cent + position(dim.x/2.0 - rad, -dim.y/2.0); - polygon(vec, 4, ilt, fill); -} diff --git a/contrib/groff/src/preproc/pic/common.h b/contrib/groff/src/preproc/pic/common.h deleted file mode 100644 index 50238344d8a4..000000000000 --- a/contrib/groff/src/preproc/pic/common.h +++ /dev/null @@ -1,80 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 1993, 2003 - 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -class common_output : public output { -private: - void dash_line(const position &start, const position &end, - const line_type <, double dash_width, double gap_width, - double *offsetp); - void dash_arc(const position ¢, double rad, - double start_angle, double end_angle, const line_type <, - double dash_width, double gap_width, double *offsetp); - void dot_line(const position &start, const position &end, - const line_type <, double gap_width, double *offsetp); - void dot_arc(const position ¢, double rad, - double start_angle, double end_angle, const line_type <, - double gap_width, double *offsetp); -protected: - virtual void dot(const position &, const line_type &) = 0; - void ellipse_arc(const position &, const position &, - const position &, const distance &, - const line_type &); - void dashed_circle(const position &, double rad, const line_type &); - void dotted_circle(const position &, double rad, const line_type &); - void dashed_ellipse(const position &, const distance &, const line_type &); - void dotted_ellipse(const position &, const distance &, const line_type &); - void dashed_arc(const position &, const position &, const position &, - const line_type &); - void dotted_arc(const position &, const position &, const position &, - const line_type &); - virtual void solid_arc(const position ¢, double rad, double start_angle, - double end_angle, const line_type <); - void dashed_rounded_box(const position &, const distance &, double, - const line_type &); - void dotted_rounded_box(const position &, const distance &, double, - const line_type &); - void solid_rounded_box(const position &, const distance &, double, - const line_type &); - void filled_rounded_box(const position &, const distance &, double, double); -public: - void start_picture(double sc, const position &ll, const position &ur) = 0; - void finish_picture() = 0; - void circle(const position &, double rad, const line_type &, double) = 0; - void text(const position &, text_piece *, int, double) = 0; - void line(const position &, const position *, int n, const line_type &) = 0; - void polygon(const position *, int n, const line_type &, double) = 0; - void spline(const position &, const position *, int n, - const line_type &) = 0; - void arc(const position &, const position &, const position &, - const line_type &) = 0; - void ellipse(const position &, const distance &, - const line_type &, double) = 0; - void rounded_box(const position &, const distance &, double, - const line_type &, double); - void set_color(char *, char *) = 0; - void reset_color() = 0; - char *get_last_filled() = 0; - char *get_outline_color() = 0; -}; - -int compute_arc_center(const position &start, const position ¢, - const position &end, position *result); - diff --git a/contrib/groff/src/preproc/pic/lex.cpp b/contrib/groff/src/preproc/pic/lex.cpp deleted file mode 100644 index ceca36854648..000000000000 --- a/contrib/groff/src/preproc/pic/lex.cpp +++ /dev/null @@ -1,2001 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2002, 2003, 2004 - 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "pic.h" -#include "ptable.h" -#include "object.h" -#include "pic_tab.h" - -declare_ptable(char) -implement_ptable(char) - -PTABLE(char) macro_table; - -class macro_input : public input { - char *s; - char *p; -public: - macro_input(const char *); - ~macro_input(); - int get(); - int peek(); -}; - -class argument_macro_input : public input { - char *s; - char *p; - char *ap; - int argc; - char *argv[9]; -public: - argument_macro_input(const char *, int, char **); - ~argument_macro_input(); - int get(); - int peek(); -}; - -input::input() : next(0) -{ -} - -input::~input() -{ -} - -int input::get_location(const char **, int *) -{ - return 0; -} - -file_input::file_input(FILE *f, const char *fn) -: fp(f), filename(fn), lineno(0), ptr("") -{ -} - -file_input::~file_input() -{ - fclose(fp); -} - -int file_input::read_line() -{ - for (;;) { - line.clear(); - lineno++; - for (;;) { - int c = getc(fp); - if (c == EOF) - break; - else if (invalid_input_char(c)) - lex_error("invalid input character code %1", c); - else { - line += char(c); - if (c == '\n') - break; - } - } - if (line.length() == 0) - return 0; - if (!(line.length() >= 3 && line[0] == '.' && line[1] == 'P' - && (line[2] == 'S' || line[2] == 'E' || line[2] == 'F') - && (line.length() == 3 || line[3] == ' ' || line[3] == '\n' - || compatible_flag))) { - line += '\0'; - ptr = line.contents(); - return 1; - } - } -} - -int file_input::get() -{ - if (*ptr != '\0' || read_line()) - return (unsigned char)*ptr++; - else - return EOF; -} - -int file_input::peek() -{ - if (*ptr != '\0' || read_line()) - return (unsigned char)*ptr; - else - return EOF; -} - -int file_input::get_location(const char **fnp, int *lnp) -{ - *fnp = filename; - *lnp = lineno; - return 1; -} - -macro_input::macro_input(const char *str) -{ - p = s = strsave(str); -} - -macro_input::~macro_input() -{ - a_delete s; -} - -int macro_input::get() -{ - if (p == 0 || *p == '\0') - return EOF; - else - return (unsigned char)*p++; -} - -int macro_input::peek() -{ - if (p == 0 || *p == '\0') - return EOF; - else - return (unsigned char)*p; -} - -// Character representing $1. Must be invalid input character. -#define ARG1 14 - -char *process_body(const char *body) -{ - char *s = strsave(body); - int j = 0; - for (int i = 0; s[i] != '\0'; i++) - if (s[i] == '$' && s[i+1] >= '0' && s[i+1] <= '9') { - if (s[i+1] != '0') - s[j++] = ARG1 + s[++i] - '1'; - } - else - s[j++] = s[i]; - s[j] = '\0'; - return s; -} - - -argument_macro_input::argument_macro_input(const char *body, int ac, char **av) -: ap(0), argc(ac) -{ - for (int i = 0; i < argc; i++) - argv[i] = av[i]; - p = s = process_body(body); -} - - -argument_macro_input::~argument_macro_input() -{ - for (int i = 0; i < argc; i++) - a_delete argv[i]; - a_delete s; -} - -int argument_macro_input::get() -{ - if (ap) { - if (*ap != '\0') - return (unsigned char)*ap++; - ap = 0; - } - if (p == 0) - return EOF; - while (*p >= ARG1 && *p <= ARG1 + 8) { - int i = *p++ - ARG1; - if (i < argc && argv[i] != 0 && argv[i][0] != '\0') { - ap = argv[i]; - return (unsigned char)*ap++; - } - } - if (*p == '\0') - return EOF; - return (unsigned char)*p++; -} - -int argument_macro_input::peek() -{ - if (ap) { - if (*ap != '\0') - return (unsigned char)*ap; - ap = 0; - } - if (p == 0) - return EOF; - while (*p >= ARG1 && *p <= ARG1 + 8) { - int i = *p++ - ARG1; - if (i < argc && argv[i] != 0 && argv[i][0] != '\0') { - ap = argv[i]; - return (unsigned char)*ap; - } - } - if (*p == '\0') - return EOF; - return (unsigned char)*p; -} - -class input_stack { - static input *current_input; - static int bol_flag; -public: - static void push(input *); - static void clear(); - static int get_char(); - static int peek_char(); - static int get_location(const char **fnp, int *lnp); - static void push_back(unsigned char c, int was_bol = 0); - static int bol(); -}; - -input *input_stack::current_input = 0; -int input_stack::bol_flag = 0; - -inline int input_stack::bol() -{ - return bol_flag; -} - -void input_stack::clear() -{ - while (current_input != 0) { - input *tem = current_input; - current_input = current_input->next; - delete tem; - } - bol_flag = 1; -} - -void input_stack::push(input *in) -{ - in->next = current_input; - current_input = in; -} - -void lex_init(input *top) -{ - input_stack::clear(); - input_stack::push(top); -} - -void lex_cleanup() -{ - while (input_stack::get_char() != EOF) - ; -} - -int input_stack::get_char() -{ - while (current_input != 0) { - int c = current_input->get(); - if (c != EOF) { - bol_flag = c == '\n'; - return c; - } - // don't pop the top-level input off the stack - if (current_input->next == 0) - return EOF; - input *tem = current_input; - current_input = current_input->next; - delete tem; - } - return EOF; -} - -int input_stack::peek_char() -{ - while (current_input != 0) { - int c = current_input->peek(); - if (c != EOF) - return c; - if (current_input->next == 0) - return EOF; - input *tem = current_input; - current_input = current_input->next; - delete tem; - } - return EOF; -} - -class char_input : public input { - int c; -public: - char_input(int); - int get(); - int peek(); -}; - -char_input::char_input(int n) : c((unsigned char)n) -{ -} - -int char_input::get() -{ - int n = c; - c = EOF; - return n; -} - -int char_input::peek() -{ - return c; -} - -void input_stack::push_back(unsigned char c, int was_bol) -{ - push(new char_input(c)); - bol_flag = was_bol; -} - -int input_stack::get_location(const char **fnp, int *lnp) -{ - for (input *p = current_input; p; p = p->next) - if (p->get_location(fnp, lnp)) - return 1; - return 0; -} - -string context_buffer; - -string token_buffer; -double token_double; -int token_int; - -void interpolate_macro_with_args(const char *body) -{ - char *argv[9]; - int argc = 0; - int i; - for (i = 0; i < 9; i++) - argv[i] = 0; - int level = 0; - int c; - enum { NORMAL, IN_STRING, IN_STRING_QUOTED } state = NORMAL; - do { - token_buffer.clear(); - for (;;) { - c = input_stack::get_char(); - if (c == EOF) { - lex_error("end of input while scanning macro arguments"); - break; - } - if (state == NORMAL && level == 0 && (c == ',' || c == ')')) { - if (token_buffer.length() > 0) { - token_buffer += '\0'; - argv[argc] = strsave(token_buffer.contents()); - } - // for `foo()', argc = 0 - if (argc > 0 || c != ')' || i > 0) - argc++; - break; - } - token_buffer += char(c); - switch (state) { - case NORMAL: - if (c == '"') - state = IN_STRING; - else if (c == '(') - level++; - else if (c == ')') - level--; - break; - case IN_STRING: - if (c == '"') - state = NORMAL; - else if (c == '\\') - state = IN_STRING_QUOTED; - break; - case IN_STRING_QUOTED: - state = IN_STRING; - break; - } - } - } while (c != ')' && c != EOF); - input_stack::push(new argument_macro_input(body, argc, argv)); -} - -static int docmp(const char *s1, int n1, const char *s2, int n2) -{ - if (n1 < n2) { - int r = memcmp(s1, s2, n1); - return r ? r : -1; - } - else if (n1 > n2) { - int r = memcmp(s1, s2, n2); - return r ? r : 1; - } - else - return memcmp(s1, s2, n1); -} - -int lookup_keyword(const char *str, int len) -{ - static struct keyword { - const char *name; - int token; - } table[] = { - { "Here", HERE }, - { "above", ABOVE }, - { "aligned", ALIGNED }, - { "and", AND }, - { "arc", ARC }, - { "arrow", ARROW }, - { "at", AT }, - { "atan2", ATAN2 }, - { "below", BELOW }, - { "between", BETWEEN }, - { "bottom", BOTTOM }, - { "box", BOX }, - { "by", BY }, - { "ccw", CCW }, - { "center", CENTER }, - { "chop", CHOP }, - { "circle", CIRCLE }, - { "color", COLORED }, - { "colored", COLORED }, - { "colour", COLORED }, - { "coloured", COLORED }, - { "command", COMMAND }, - { "copy", COPY }, - { "cos", COS }, - { "cw", CW }, - { "dashed", DASHED }, - { "define", DEFINE }, - { "diam", DIAMETER }, - { "diameter", DIAMETER }, - { "do", DO }, - { "dotted", DOTTED }, - { "down", DOWN }, - { "east", EAST }, - { "ellipse", ELLIPSE }, - { "else", ELSE }, - { "end", END }, - { "exp", EXP }, - { "figname", FIGNAME }, - { "fill", FILL }, - { "filled", FILL }, - { "for", FOR }, - { "from", FROM }, - { "height", HEIGHT }, - { "ht", HEIGHT }, - { "if", IF }, - { "int", INT }, - { "invis", INVISIBLE }, - { "invisible", INVISIBLE }, - { "last", LAST }, - { "left", LEFT }, - { "line", LINE }, - { "ljust", LJUST }, - { "log", LOG }, - { "lower", LOWER }, - { "max", K_MAX }, - { "min", K_MIN }, - { "move", MOVE }, - { "north", NORTH }, - { "of", OF }, - { "outline", OUTLINED }, - { "outlined", OUTLINED }, - { "plot", PLOT }, - { "print", PRINT }, - { "rad", RADIUS }, - { "radius", RADIUS }, - { "rand", RAND }, - { "reset", RESET }, - { "right", RIGHT }, - { "rjust", RJUST }, - { "same", SAME }, - { "sh", SH }, - { "shaded", SHADED }, - { "sin", SIN }, - { "solid", SOLID }, - { "south", SOUTH }, - { "spline", SPLINE }, - { "sprintf", SPRINTF }, - { "sqrt", SQRT }, - { "srand", SRAND }, - { "start", START }, - { "the", THE }, - { "then", THEN }, - { "thick", THICKNESS }, - { "thickness", THICKNESS }, - { "thru", THRU }, - { "to", TO }, - { "top", TOP }, - { "undef", UNDEF }, - { "until", UNTIL }, - { "up", UP }, - { "upper", UPPER }, - { "way", WAY }, - { "west", WEST }, - { "wid", WIDTH }, - { "width", WIDTH }, - { "with", WITH }, - }; - - const keyword *start = table; - const keyword *end = table + sizeof(table)/sizeof(table[0]); - while (start < end) { - // start <= target < end - const keyword *mid = start + (end - start)/2; - - int cmp = docmp(str, len, mid->name, strlen(mid->name)); - if (cmp == 0) - return mid->token; - if (cmp < 0) - end = mid; - else - start = mid + 1; - } - return 0; -} - -int get_token_after_dot(int c) -{ - // get_token deals with the case where c is a digit - switch (c) { - case 'h': - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 't') { - input_stack::get_char(); - context_buffer = ".ht"; - return DOT_HT; - } - else if (c == 'e') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'i') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'g') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'h') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 't') { - input_stack::get_char(); - context_buffer = ".height"; - return DOT_HT; - } - input_stack::push_back('h'); - } - input_stack::push_back('g'); - } - input_stack::push_back('i'); - } - input_stack::push_back('e'); - } - input_stack::push_back('h'); - return '.'; - case 'x': - input_stack::get_char(); - context_buffer = ".x"; - return DOT_X; - case 'y': - input_stack::get_char(); - context_buffer = ".y"; - return DOT_Y; - case 'c': - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'e') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'n') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 't') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'e') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'r') { - input_stack::get_char(); - context_buffer = ".center"; - return DOT_C; - } - input_stack::push_back('e'); - } - input_stack::push_back('t'); - } - input_stack::push_back('n'); - } - input_stack::push_back('e'); - } - context_buffer = ".c"; - return DOT_C; - case 'n': - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'e') { - input_stack::get_char(); - context_buffer = ".ne"; - return DOT_NE; - } - else if (c == 'w') { - input_stack::get_char(); - context_buffer = ".nw"; - return DOT_NW; - } - else { - context_buffer = ".n"; - return DOT_N; - } - break; - case 'e': - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'n') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'd') { - input_stack::get_char(); - context_buffer = ".end"; - return DOT_END; - } - input_stack::push_back('n'); - context_buffer = ".e"; - return DOT_E; - } - context_buffer = ".e"; - return DOT_E; - case 'w': - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'i') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'd') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 't') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'h') { - input_stack::get_char(); - context_buffer = ".width"; - return DOT_WID; - } - input_stack::push_back('t'); - } - context_buffer = ".wid"; - return DOT_WID; - } - input_stack::push_back('i'); - } - context_buffer = ".w"; - return DOT_W; - case 's': - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'e') { - input_stack::get_char(); - context_buffer = ".se"; - return DOT_SE; - } - else if (c == 'w') { - input_stack::get_char(); - context_buffer = ".sw"; - return DOT_SW; - } - else { - if (c == 't') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'a') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'r') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 't') { - input_stack::get_char(); - context_buffer = ".start"; - return DOT_START; - } - input_stack::push_back('r'); - } - input_stack::push_back('a'); - } - input_stack::push_back('t'); - } - context_buffer = ".s"; - return DOT_S; - } - break; - case 't': - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'o') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'p') { - input_stack::get_char(); - context_buffer = ".top"; - return DOT_N; - } - input_stack::push_back('o'); - } - context_buffer = ".t"; - return DOT_N; - case 'l': - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'e') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'f') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 't') { - input_stack::get_char(); - context_buffer = ".left"; - return DOT_W; - } - input_stack::push_back('f'); - } - input_stack::push_back('e'); - } - context_buffer = ".l"; - return DOT_W; - case 'r': - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'a') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'd') { - input_stack::get_char(); - context_buffer = ".rad"; - return DOT_RAD; - } - input_stack::push_back('a'); - } - else if (c == 'i') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'g') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'h') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 't') { - input_stack::get_char(); - context_buffer = ".right"; - return DOT_E; - } - input_stack::push_back('h'); - } - input_stack::push_back('g'); - } - input_stack::push_back('i'); - } - context_buffer = ".r"; - return DOT_E; - case 'b': - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'o') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 't') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 't') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'o') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'm') { - input_stack::get_char(); - context_buffer = ".bottom"; - return DOT_S; - } - input_stack::push_back('o'); - } - input_stack::push_back('t'); - } - context_buffer = ".bot"; - return DOT_S; - } - input_stack::push_back('o'); - } - context_buffer = ".b"; - return DOT_S; - default: - context_buffer = '.'; - return '.'; - } -} - -int get_token(int lookup_flag) -{ - context_buffer.clear(); - for (;;) { - int n = 0; - int bol = input_stack::bol(); - int c = input_stack::get_char(); - if (bol && c == command_char) { - token_buffer.clear(); - token_buffer += c; - // the newline is not part of the token - for (;;) { - c = input_stack::peek_char(); - if (c == EOF || c == '\n') - break; - input_stack::get_char(); - token_buffer += char(c); - } - context_buffer = token_buffer; - return COMMAND_LINE; - } - switch (c) { - case EOF: - return EOF; - case ' ': - case '\t': - break; - case '\\': - { - int d = input_stack::peek_char(); - if (d != '\n') { - context_buffer = '\\'; - return '\\'; - } - input_stack::get_char(); - break; - } - case '#': - do { - c = input_stack::get_char(); - } while (c != '\n' && c != EOF); - if (c == '\n') - context_buffer = '\n'; - return c; - case '"': - context_buffer = '"'; - token_buffer.clear(); - for (;;) { - c = input_stack::get_char(); - if (c == '\\') { - context_buffer += '\\'; - c = input_stack::peek_char(); - if (c == '"') { - input_stack::get_char(); - token_buffer += '"'; - context_buffer += '"'; - } - else - token_buffer += '\\'; - } - else if (c == '\n') { - error("newline in string"); - break; - } - else if (c == EOF) { - error("missing `\"'"); - break; - } - else if (c == '"') { - context_buffer += '"'; - break; - } - else { - context_buffer += char(c); - token_buffer += char(c); - } - } - return TEXT; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - int overflow = 0; - n = 0; - for (;;) { - if (n > (INT_MAX - 9)/10) { - overflow = 1; - break; - } - n *= 10; - n += c - '0'; - context_buffer += char(c); - c = input_stack::peek_char(); - if (c == EOF || !csdigit(c)) - break; - c = input_stack::get_char(); - } - token_double = n; - if (overflow) { - for (;;) { - token_double *= 10.0; - token_double += c - '0'; - context_buffer += char(c); - c = input_stack::peek_char(); - if (c == EOF || !csdigit(c)) - break; - c = input_stack::get_char(); - } - // if somebody asks for 1000000000000th, we will silently - // give them INT_MAXth - double temp = token_double; // work around gas 1.34/sparc bug - if (token_double > INT_MAX) - n = INT_MAX; - else - n = int(temp); - } - } - switch (c) { - case 'i': - case 'I': - context_buffer += char(c); - input_stack::get_char(); - return NUMBER; - case '.': - { - context_buffer += '.'; - input_stack::get_char(); - got_dot: - double factor = 1.0; - for (;;) { - c = input_stack::peek_char(); - if (c == EOF || !csdigit(c)) - break; - input_stack::get_char(); - context_buffer += char(c); - factor /= 10.0; - if (c != '0') - token_double += factor*(c - '0'); - } - if (c != 'e' && c != 'E') { - if (c == 'i' || c == 'I') { - context_buffer += char(c); - input_stack::get_char(); - } - return NUMBER; - } - } - // fall through - case 'e': - case 'E': - { - int echar = c; - input_stack::get_char(); - c = input_stack::peek_char(); - int sign = '+'; - if (c == '+' || c == '-') { - sign = c; - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == EOF || !csdigit(c)) { - input_stack::push_back(sign); - input_stack::push_back(echar); - return NUMBER; - } - context_buffer += char(echar); - context_buffer += char(sign); - } - else { - if (c == EOF || !csdigit(c)) { - input_stack::push_back(echar); - return NUMBER; - } - context_buffer += char(echar); - } - input_stack::get_char(); - context_buffer += char(c); - n = c - '0'; - for (;;) { - c = input_stack::peek_char(); - if (c == EOF || !csdigit(c)) - break; - input_stack::get_char(); - context_buffer += char(c); - n = n*10 + (c - '0'); - } - if (sign == '-') - n = -n; - if (c == 'i' || c == 'I') { - context_buffer += char(c); - input_stack::get_char(); - } - token_double *= pow(10.0, n); - return NUMBER; - } - case 'n': - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'd') { - input_stack::get_char(); - token_int = n; - context_buffer += "nd"; - return ORDINAL; - } - input_stack::push_back('n'); - return NUMBER; - case 'r': - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'd') { - input_stack::get_char(); - token_int = n; - context_buffer += "rd"; - return ORDINAL; - } - input_stack::push_back('r'); - return NUMBER; - case 't': - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'h') { - input_stack::get_char(); - token_int = n; - context_buffer += "th"; - return ORDINAL; - } - input_stack::push_back('t'); - return NUMBER; - case 's': - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 't') { - input_stack::get_char(); - token_int = n; - context_buffer += "st"; - return ORDINAL; - } - input_stack::push_back('s'); - return NUMBER; - default: - return NUMBER; - } - break; - case '\'': - { - c = input_stack::peek_char(); - if (c == 't') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == 'h') { - input_stack::get_char(); - context_buffer = "'th"; - return TH; - } - else - input_stack::push_back('t'); - } - context_buffer = "'"; - return '\''; - } - case '.': - { - c = input_stack::peek_char(); - if (c != EOF && csdigit(c)) { - n = 0; - token_double = 0.0; - context_buffer = '.'; - goto got_dot; - } - return get_token_after_dot(c); - } - case '<': - c = input_stack::peek_char(); - if (c == '-') { - input_stack::get_char(); - c = input_stack::peek_char(); - if (c == '>') { - input_stack::get_char(); - context_buffer = "<->"; - return DOUBLE_ARROW_HEAD; - } - context_buffer = "<-"; - return LEFT_ARROW_HEAD; - } - else if (c == '=') { - input_stack::get_char(); - context_buffer = "<="; - return LESSEQUAL; - } - context_buffer = "<"; - return '<'; - case '-': - c = input_stack::peek_char(); - if (c == '>') { - input_stack::get_char(); - context_buffer = "->"; - return RIGHT_ARROW_HEAD; - } - context_buffer = "-"; - return '-'; - case '!': - c = input_stack::peek_char(); - if (c == '=') { - input_stack::get_char(); - context_buffer = "!="; - return NOTEQUAL; - } - context_buffer = "!"; - return '!'; - case '>': - c = input_stack::peek_char(); - if (c == '=') { - input_stack::get_char(); - context_buffer = ">="; - return GREATEREQUAL; - } - context_buffer = ">"; - return '>'; - case '=': - c = input_stack::peek_char(); - if (c == '=') { - input_stack::get_char(); - context_buffer = "=="; - return EQUALEQUAL; - } - context_buffer = "="; - return '='; - case '&': - c = input_stack::peek_char(); - if (c == '&') { - input_stack::get_char(); - context_buffer = "&&"; - return ANDAND; - } - context_buffer = "&"; - return '&'; - case '|': - c = input_stack::peek_char(); - if (c == '|') { - input_stack::get_char(); - context_buffer = "||"; - return OROR; - } - context_buffer = "|"; - return '|'; - default: - if (c != EOF && csalpha(c)) { - token_buffer.clear(); - token_buffer = c; - for (;;) { - c = input_stack::peek_char(); - if (c == EOF || (!csalnum(c) && c != '_')) - break; - input_stack::get_char(); - token_buffer += char(c); - } - int tok = lookup_keyword(token_buffer.contents(), - token_buffer.length()); - if (tok != 0) { - context_buffer = token_buffer; - return tok; - } - char *def = 0; - if (lookup_flag) { - token_buffer += '\0'; - def = macro_table.lookup(token_buffer.contents()); - token_buffer.set_length(token_buffer.length() - 1); - if (def) { - if (c == '(') { - input_stack::get_char(); - interpolate_macro_with_args(def); - } - else - input_stack::push(new macro_input(def)); - } - } - if (!def) { - context_buffer = token_buffer; - if (csupper(token_buffer[0])) - return LABEL; - else - return VARIABLE; - } - } - else { - context_buffer = char(c); - return (unsigned char)c; - } - break; - } - } -} - -int get_delimited() -{ - token_buffer.clear(); - int c = input_stack::get_char(); - while (c == ' ' || c == '\t' || c == '\n') - c = input_stack::get_char(); - if (c == EOF) { - lex_error("missing delimiter"); - return 0; - } - context_buffer = char(c); - int had_newline = 0; - int start = c; - int level = 0; - enum { NORMAL, IN_STRING, IN_STRING_QUOTED, DELIM_END } state = NORMAL; - for (;;) { - c = input_stack::get_char(); - if (c == EOF) { - lex_error("missing closing delimiter"); - return 0; - } - if (c == '\n') - had_newline = 1; - else if (!had_newline) - context_buffer += char(c); - switch (state) { - case NORMAL: - if (start == '{') { - if (c == '{') { - level++; - break; - } - if (c == '}') { - if (--level < 0) - state = DELIM_END; - break; - } - } - else { - if (c == start) { - state = DELIM_END; - break; - } - } - if (c == '"') - state = IN_STRING; - break; - case IN_STRING_QUOTED: - if (c == '\n') - state = NORMAL; - else - state = IN_STRING; - break; - case IN_STRING: - if (c == '"' || c == '\n') - state = NORMAL; - else if (c == '\\') - state = IN_STRING_QUOTED; - break; - case DELIM_END: - // This case it just to shut cfront 2.0 up. - default: - assert(0); - } - if (state == DELIM_END) - break; - token_buffer += c; - } - return 1; -} - -void do_define() -{ - int t = get_token(0); // do not expand what we are defining - if (t != VARIABLE && t != LABEL) { - lex_error("can only define variable or placename"); - return; - } - token_buffer += '\0'; - string nm = token_buffer; - const char *name = nm.contents(); - if (!get_delimited()) - return; - token_buffer += '\0'; - macro_table.define(name, strsave(token_buffer.contents())); -} - -void do_undef() -{ - int t = get_token(0); // do not expand what we are undefining - if (t != VARIABLE && t != LABEL) { - lex_error("can only define variable or placename"); - return; - } - token_buffer += '\0'; - macro_table.define(token_buffer.contents(), 0); -} - - -class for_input : public input { - char *var; - char *body; - double from; - double to; - int by_is_multiplicative; - double by; - const char *p; - int done_newline; -public: - for_input(char *, double, double, int, double, char *); - ~for_input(); - int get(); - int peek(); -}; - -for_input::for_input(char *vr, double f, double t, - int bim, double b, char *bd) -: var(vr), body(bd), from(f), to(t), by_is_multiplicative(bim), by(b), - p(body), done_newline(0) -{ -} - -for_input::~for_input() -{ - a_delete var; - a_delete body; -} - -int for_input::get() -{ - if (p == 0) - return EOF; - for (;;) { - if (*p != '\0') - return (unsigned char)*p++; - if (!done_newline) { - done_newline = 1; - return '\n'; - } - double val; - if (!lookup_variable(var, &val)) { - lex_error("body of `for' terminated enclosing block"); - return EOF; - } - if (by_is_multiplicative) - val *= by; - else - val += by; - define_variable(var, val); - if ((from <= to && val > to) - || (from >= to && val < to)) { - p = 0; - return EOF; - } - p = body; - done_newline = 0; - } -} - -int for_input::peek() -{ - if (p == 0) - return EOF; - if (*p != '\0') - return (unsigned char)*p; - if (!done_newline) - return '\n'; - double val; - if (!lookup_variable(var, &val)) - return EOF; - if (by_is_multiplicative) { - if (val * by > to) - return EOF; - } - else { - if ((from <= to && val + by > to) - || (from >= to && val + by < to)) - return EOF; - } - if (*body == '\0') - return EOF; - return (unsigned char)*body; -} - -void do_for(char *var, double from, double to, int by_is_multiplicative, - double by, char *body) -{ - define_variable(var, from); - if ((by_is_multiplicative && by <= 0) - || (by > 0 && from > to) - || (by < 0 && from < to)) - return; - input_stack::push(new for_input(var, from, to, - by_is_multiplicative, by, body)); -} - - -void do_copy(const char *filename) -{ - errno = 0; - FILE *fp = fopen(filename, "r"); - if (fp == 0) { - lex_error("can't open `%1': %2", filename, strerror(errno)); - return; - } - input_stack::push(new file_input(fp, filename)); -} - -class copy_thru_input : public input { - int done; - char *body; - char *until; - const char *p; - const char *ap; - int argv[9]; - int argc; - string line; - int get_line(); - virtual int inget() = 0; -public: - copy_thru_input(const char *b, const char *u); - ~copy_thru_input(); - int get(); - int peek(); -}; - -class copy_file_thru_input : public copy_thru_input { - input *in; -public: - copy_file_thru_input(input *, const char *b, const char *u); - ~copy_file_thru_input(); - int inget(); -}; - -copy_file_thru_input::copy_file_thru_input(input *i, const char *b, - const char *u) -: copy_thru_input(b, u), in(i) -{ -} - -copy_file_thru_input::~copy_file_thru_input() -{ - delete in; -} - -int copy_file_thru_input::inget() -{ - if (!in) - return EOF; - else - return in->get(); -} - -class copy_rest_thru_input : public copy_thru_input { -public: - copy_rest_thru_input(const char *, const char *u); - int inget(); -}; - -copy_rest_thru_input::copy_rest_thru_input(const char *b, const char *u) -: copy_thru_input(b, u) -{ -} - -int copy_rest_thru_input::inget() -{ - while (next != 0) { - int c = next->get(); - if (c != EOF) - return c; - if (next->next == 0) - return EOF; - input *tem = next; - next = next->next; - delete tem; - } - return EOF; - -} - -copy_thru_input::copy_thru_input(const char *b, const char *u) -: done(0) -{ - ap = 0; - body = process_body(b); - p = 0; - until = strsave(u); -} - - -copy_thru_input::~copy_thru_input() -{ - a_delete body; - a_delete until; -} - -int copy_thru_input::get() -{ - if (ap) { - if (*ap != '\0') - return (unsigned char)*ap++; - ap = 0; - } - for (;;) { - if (p == 0) { - if (!get_line()) - break; - p = body; - } - if (*p == '\0') { - p = 0; - return '\n'; - } - while (*p >= ARG1 && *p <= ARG1 + 8) { - int i = *p++ - ARG1; - if (i < argc && line[argv[i]] != '\0') { - ap = line.contents() + argv[i]; - return (unsigned char)*ap++; - } - } - if (*p != '\0') - return (unsigned char)*p++; - } - return EOF; -} - -int copy_thru_input::peek() -{ - if (ap) { - if (*ap != '\0') - return (unsigned char)*ap; - ap = 0; - } - for (;;) { - if (p == 0) { - if (!get_line()) - break; - p = body; - } - if (*p == '\0') - return '\n'; - while (*p >= ARG1 && *p <= ARG1 + 8) { - int i = *p++ - ARG1; - if (i < argc && line[argv[i]] != '\0') { - ap = line.contents() + argv[i]; - return (unsigned char)*ap; - } - } - if (*p != '\0') - return (unsigned char)*p; - } - return EOF; -} - -int copy_thru_input::get_line() -{ - if (done) - return 0; - line.clear(); - argc = 0; - int c = inget(); - for (;;) { - while (c == ' ') - c = inget(); - if (c == EOF || c == '\n') - break; - if (argc == 9) { - do { - c = inget(); - } while (c != '\n' && c != EOF); - break; - } - argv[argc++] = line.length(); - do { - line += char(c); - c = inget(); - } while (c != ' ' && c != '\n'); - line += '\0'; - } - if (until != 0 && argc > 0 && strcmp(&line[argv[0]], until) == 0) { - done = 1; - return 0; - } - return argc > 0 || c == '\n'; -} - -class simple_file_input : public input { - const char *filename; - int lineno; - FILE *fp; -public: - simple_file_input(FILE *, const char *); - ~simple_file_input(); - int get(); - int peek(); - int get_location(const char **, int *); -}; - -simple_file_input::simple_file_input(FILE *p, const char *s) -: filename(s), lineno(1), fp(p) -{ -} - -simple_file_input::~simple_file_input() -{ - // don't delete the filename - fclose(fp); -} - -int simple_file_input::get() -{ - int c = getc(fp); - while (invalid_input_char(c)) { - error("invalid input character code %1", c); - c = getc(fp); - } - if (c == '\n') - lineno++; - return c; -} - -int simple_file_input::peek() -{ - int c = getc(fp); - while (invalid_input_char(c)) { - error("invalid input character code %1", c); - c = getc(fp); - } - if (c != EOF) - ungetc(c, fp); - return c; -} - -int simple_file_input::get_location(const char **fnp, int *lnp) -{ - *fnp = filename; - *lnp = lineno; - return 1; -} - - -void copy_file_thru(const char *filename, const char *body, const char *until) -{ - errno = 0; - FILE *fp = fopen(filename, "r"); - if (fp == 0) { - lex_error("can't open `%1': %2", filename, strerror(errno)); - return; - } - input *in = new copy_file_thru_input(new simple_file_input(fp, filename), - body, until); - input_stack::push(in); -} - -void copy_rest_thru(const char *body, const char *until) -{ - input_stack::push(new copy_rest_thru_input(body, until)); -} - -void push_body(const char *s) -{ - input_stack::push(new char_input('\n')); - input_stack::push(new macro_input(s)); -} - -int delim_flag = 0; - -char *get_thru_arg() -{ - int c = input_stack::peek_char(); - while (c == ' ') { - input_stack::get_char(); - c = input_stack::peek_char(); - } - if (c != EOF && csalpha(c)) { - // looks like a macro - input_stack::get_char(); - token_buffer = c; - for (;;) { - c = input_stack::peek_char(); - if (c == EOF || (!csalnum(c) && c != '_')) - break; - input_stack::get_char(); - token_buffer += char(c); - } - context_buffer = token_buffer; - token_buffer += '\0'; - char *def = macro_table.lookup(token_buffer.contents()); - if (def) - return strsave(def); - // I guess it wasn't a macro after all; so push the macro name back. - // -2 because we added a '\0' - for (int i = token_buffer.length() - 2; i >= 0; i--) - input_stack::push_back(token_buffer[i]); - } - if (get_delimited()) { - token_buffer += '\0'; - return strsave(token_buffer.contents()); - } - else - return 0; -} - -int lookahead_token = -1; -string old_context_buffer; - -void do_lookahead() -{ - if (lookahead_token == -1) { - old_context_buffer = context_buffer; - lookahead_token = get_token(1); - } -} - -int yylex() -{ - if (delim_flag) { - assert(lookahead_token == -1); - if (delim_flag == 2) { - if ((yylval.str = get_thru_arg()) != 0) - return DELIMITED; - else - return 0; - } - else { - if (get_delimited()) { - token_buffer += '\0'; - yylval.str = strsave(token_buffer.contents()); - return DELIMITED; - } - else - return 0; - } - } - for (;;) { - int t; - if (lookahead_token >= 0) { - t = lookahead_token; - lookahead_token = -1; - } - else - t = get_token(1); - switch (t) { - case '\n': - return ';'; - case EOF: - return 0; - case DEFINE: - do_define(); - break; - case UNDEF: - do_undef(); - break; - case ORDINAL: - yylval.n = token_int; - return t; - case NUMBER: - yylval.x = token_double; - return t; - case COMMAND_LINE: - case TEXT: - token_buffer += '\0'; - if (!input_stack::get_location(&yylval.lstr.filename, - &yylval.lstr.lineno)) { - yylval.lstr.filename = 0; - yylval.lstr.lineno = -1; - } - yylval.lstr.str = strsave(token_buffer.contents()); - return t; - case LABEL: - case VARIABLE: - token_buffer += '\0'; - yylval.str = strsave(token_buffer.contents()); - return t; - case LEFT: - // change LEFT to LEFT_CORNER when followed by OF - old_context_buffer = context_buffer; - lookahead_token = get_token(1); - if (lookahead_token == OF) - return LEFT_CORNER; - else - return t; - case RIGHT: - // change RIGHT to RIGHT_CORNER when followed by OF - old_context_buffer = context_buffer; - lookahead_token = get_token(1); - if (lookahead_token == OF) - return RIGHT_CORNER; - else - return t; - case UPPER: - // recognise UPPER only before LEFT or RIGHT - old_context_buffer = context_buffer; - lookahead_token = get_token(1); - if (lookahead_token != LEFT && lookahead_token != RIGHT) { - yylval.str = strsave("upper"); - return VARIABLE; - } - else - return t; - case LOWER: - // recognise LOWER only before LEFT or RIGHT - old_context_buffer = context_buffer; - lookahead_token = get_token(1); - if (lookahead_token != LEFT && lookahead_token != RIGHT) { - yylval.str = strsave("lower"); - return VARIABLE; - } - else - return t; - case NORTH: - // recognise NORTH only before OF - old_context_buffer = context_buffer; - lookahead_token = get_token(1); - if (lookahead_token != OF) { - yylval.str = strsave("north"); - return VARIABLE; - } - else - return t; - case SOUTH: - // recognise SOUTH only before OF - old_context_buffer = context_buffer; - lookahead_token = get_token(1); - if (lookahead_token != OF) { - yylval.str = strsave("south"); - return VARIABLE; - } - else - return t; - case EAST: - // recognise EAST only before OF - old_context_buffer = context_buffer; - lookahead_token = get_token(1); - if (lookahead_token != OF) { - yylval.str = strsave("east"); - return VARIABLE; - } - else - return t; - case WEST: - // recognise WEST only before OF - old_context_buffer = context_buffer; - lookahead_token = get_token(1); - if (lookahead_token != OF) { - yylval.str = strsave("west"); - return VARIABLE; - } - else - return t; - case TOP: - // recognise TOP only before OF - old_context_buffer = context_buffer; - lookahead_token = get_token(1); - if (lookahead_token != OF) { - yylval.str = strsave("top"); - return VARIABLE; - } - else - return t; - case BOTTOM: - // recognise BOTTOM only before OF - old_context_buffer = context_buffer; - lookahead_token = get_token(1); - if (lookahead_token != OF) { - yylval.str = strsave("bottom"); - return VARIABLE; - } - else - return t; - case CENTER: - // recognise CENTER only before OF - old_context_buffer = context_buffer; - lookahead_token = get_token(1); - if (lookahead_token != OF) { - yylval.str = strsave("center"); - return VARIABLE; - } - else - return t; - case START: - // recognise START only before OF - old_context_buffer = context_buffer; - lookahead_token = get_token(1); - if (lookahead_token != OF) { - yylval.str = strsave("start"); - return VARIABLE; - } - else - return t; - case END: - // recognise END only before OF - old_context_buffer = context_buffer; - lookahead_token = get_token(1); - if (lookahead_token != OF) { - yylval.str = strsave("end"); - return VARIABLE; - } - else - return t; - default: - return t; - } - } -} - -void lex_error(const char *message, - const errarg &arg1, - const errarg &arg2, - const errarg &arg3) -{ - const char *filename; - int lineno; - if (!input_stack::get_location(&filename, &lineno)) - error(message, arg1, arg2, arg3); - else - error_with_file_and_line(filename, lineno, message, arg1, arg2, arg3); -} - -void lex_warning(const char *message, - const errarg &arg1, - const errarg &arg2, - const errarg &arg3) -{ - const char *filename; - int lineno; - if (!input_stack::get_location(&filename, &lineno)) - warning(message, arg1, arg2, arg3); - else - warning_with_file_and_line(filename, lineno, message, arg1, arg2, arg3); -} - -void yyerror(const char *s) -{ - const char *filename; - int lineno; - const char *context = 0; - if (lookahead_token == -1) { - if (context_buffer.length() > 0) { - context_buffer += '\0'; - context = context_buffer.contents(); - } - } - else { - if (old_context_buffer.length() > 0) { - old_context_buffer += '\0'; - context = old_context_buffer.contents(); - } - } - if (!input_stack::get_location(&filename, &lineno)) { - if (context) { - if (context[0] == '\n' && context[1] == '\0') - error("%1 before newline", s); - else - error("%1 before `%2'", s, context); - } - else - error("%1 at end of picture", s); - } - else { - if (context) { - if (context[0] == '\n' && context[1] == '\0') - error_with_file_and_line(filename, lineno, "%1 before newline", s); - else - error_with_file_and_line(filename, lineno, "%1 before `%2'", - s, context); - } - else - error_with_file_and_line(filename, lineno, "%1 at end of picture", s); - } -} - diff --git a/contrib/groff/src/preproc/pic/main.cpp b/contrib/groff/src/preproc/pic/main.cpp deleted file mode 100644 index 0e05f77cd280..000000000000 --- a/contrib/groff/src/preproc/pic/main.cpp +++ /dev/null @@ -1,642 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989-1992, 2000, 2001, 2002, 2003 - 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "pic.h" - -extern int yyparse(); -extern "C" const char *Version_string; - -output *out; -char *graphname; // the picture box name in TeX mode - -int flyback_flag; -int zero_length_line_flag = 0; -// Non-zero means we're using a groff driver. -int driver_extension_flag = 1; -int compatible_flag = 0; -int safer_flag = 1; -int command_char = '.'; // the character that introduces lines - // that should be passed through tranparently -static int lf_flag = 1; // non-zero if we should attempt to understand - // lines beginning with `.lf' - -// Non-zero means a parse error was encountered. -static int had_parse_error = 0; - -void do_file(const char *filename); - -class top_input : public input { - FILE *fp; - int bol; - int eof; - int push_back[3]; - int start_lineno; -public: - top_input(FILE *); - int get(); - int peek(); - int get_location(const char **, int *); -}; - -top_input::top_input(FILE *p) : fp(p), bol(1), eof(0) -{ - push_back[0] = push_back[1] = push_back[2] = EOF; - start_lineno = current_lineno; -} - -int top_input::get() -{ - if (eof) - return EOF; - if (push_back[2] != EOF) { - int c = push_back[2]; - push_back[2] = EOF; - return c; - } - else if (push_back[1] != EOF) { - int c = push_back[1]; - push_back[1] = EOF; - return c; - } - else if (push_back[0] != EOF) { - int c = push_back[0]; - push_back[0] = EOF; - return c; - } - int c = getc(fp); - while (invalid_input_char(c)) { - error("invalid input character code %1", int(c)); - c = getc(fp); - bol = 0; - } - if (bol && c == '.') { - c = getc(fp); - if (c == 'P') { - c = getc(fp); - if (c == 'F' || c == 'E') { - int d = getc(fp); - if (d != EOF) - ungetc(d, fp); - if (d == EOF || d == ' ' || d == '\n' || compatible_flag) { - eof = 1; - flyback_flag = c == 'F'; - return EOF; - } - push_back[0] = c; - push_back[1] = 'P'; - return '.'; - } - if (c == 'S') { - c = getc(fp); - if (c != EOF) - ungetc(c, fp); - if (c == EOF || c == ' ' || c == '\n' || compatible_flag) { - error("nested .PS"); - eof = 1; - return EOF; - } - push_back[0] = 'S'; - push_back[1] = 'P'; - return '.'; - } - if (c != EOF) - ungetc(c, fp); - push_back[0] = 'P'; - return '.'; - } - else { - if (c != EOF) - ungetc(c, fp); - return '.'; - } - } - if (c == '\n') { - bol = 1; - current_lineno++; - return '\n'; - } - bol = 0; - if (c == EOF) { - eof = 1; - error("end of file before .PE or .PF"); - error_with_file_and_line(current_filename, start_lineno - 1, - ".PS was here"); - } - return c; -} - -int top_input::peek() -{ - if (eof) - return EOF; - if (push_back[2] != EOF) - return push_back[2]; - if (push_back[1] != EOF) - return push_back[1]; - if (push_back[0] != EOF) - return push_back[0]; - int c = getc(fp); - while (invalid_input_char(c)) { - error("invalid input character code %1", int(c)); - c = getc(fp); - bol = 0; - } - if (bol && c == '.') { - c = getc(fp); - if (c == 'P') { - c = getc(fp); - if (c == 'F' || c == 'E') { - int d = getc(fp); - if (d != EOF) - ungetc(d, fp); - if (d == EOF || d == ' ' || d == '\n' || compatible_flag) { - eof = 1; - flyback_flag = c == 'F'; - return EOF; - } - push_back[0] = c; - push_back[1] = 'P'; - push_back[2] = '.'; - return '.'; - } - if (c == 'S') { - c = getc(fp); - if (c != EOF) - ungetc(c, fp); - if (c == EOF || c == ' ' || c == '\n' || compatible_flag) { - error("nested .PS"); - eof = 1; - return EOF; - } - push_back[0] = 'S'; - push_back[1] = 'P'; - push_back[2] = '.'; - return '.'; - } - if (c != EOF) - ungetc(c, fp); - push_back[0] = 'P'; - push_back[1] = '.'; - return '.'; - } - else { - if (c != EOF) - ungetc(c, fp); - push_back[0] = '.'; - return '.'; - } - } - if (c != EOF) - ungetc(c, fp); - if (c == '\n') - return '\n'; - return c; -} - -int top_input::get_location(const char **filenamep, int *linenop) -{ - *filenamep = current_filename; - *linenop = current_lineno; - return 1; -} - -void do_picture(FILE *fp) -{ - flyback_flag = 0; - int c; - a_delete graphname; - graphname = strsave("graph"); // default picture name in TeX mode - while ((c = getc(fp)) == ' ') - ; - if (c == '<') { - string filename; - while ((c = getc(fp)) == ' ') - ; - while (c != EOF && c != ' ' && c != '\n') { - filename += char(c); - c = getc(fp); - } - if (c == ' ') { - do { - c = getc(fp); - } while (c != EOF && c != '\n'); - } - if (c == '\n') - current_lineno++; - if (filename.length() == 0) - error("missing filename after `<'"); - else { - filename += '\0'; - const char *old_filename = current_filename; - int old_lineno = current_lineno; - // filenames must be permanent - do_file(strsave(filename.contents())); - current_filename = old_filename; - current_lineno = old_lineno; - } - out->set_location(current_filename, current_lineno); - } - else { - out->set_location(current_filename, current_lineno); - string start_line; - while (c != EOF) { - if (c == '\n') { - current_lineno++; - break; - } - start_line += c; - c = getc(fp); - } - if (c == EOF) - return; - start_line += '\0'; - double wid, ht; - switch (sscanf(&start_line[0], "%lf %lf", &wid, &ht)) { - case 1: - ht = 0.0; - break; - case 2: - break; - default: - ht = wid = 0.0; - break; - } - out->set_desired_width_height(wid, ht); - out->set_args(start_line.contents()); - lex_init(new top_input(fp)); - if (yyparse()) { - had_parse_error = 1; - lex_error("giving up on this picture"); - } - parse_cleanup(); - lex_cleanup(); - - // skip the rest of the .PF/.PE line - while ((c = getc(fp)) != EOF && c != '\n') - ; - if (c == '\n') - current_lineno++; - out->set_location(current_filename, current_lineno); - } -} - -void do_file(const char *filename) -{ - FILE *fp; - if (strcmp(filename, "-") == 0) - fp = stdin; - else { - errno = 0; - fp = fopen(filename, "r"); - if (fp == 0) { - delete out; - fatal("can't open `%1': %2", filename, strerror(errno)); - } - } - out->set_location(filename, 1); - current_filename = filename; - current_lineno = 1; - enum { START, MIDDLE, HAD_DOT, HAD_P, HAD_PS, HAD_l, HAD_lf } state = START; - for (;;) { - int c = getc(fp); - if (c == EOF) - break; - switch (state) { - case START: - if (c == '.') - state = HAD_DOT; - else { - putchar(c); - if (c == '\n') { - current_lineno++; - state = START; - } - else - state = MIDDLE; - } - break; - case MIDDLE: - putchar(c); - if (c == '\n') { - current_lineno++; - state = START; - } - break; - case HAD_DOT: - if (c == 'P') - state = HAD_P; - else if (lf_flag && c == 'l') - state = HAD_l; - else { - putchar('.'); - putchar(c); - if (c == '\n') { - current_lineno++; - state = START; - } - else - state = MIDDLE; - } - break; - case HAD_P: - if (c == 'S') - state = HAD_PS; - else { - putchar('.'); - putchar('P'); - putchar(c); - if (c == '\n') { - current_lineno++; - state = START; - } - else - state = MIDDLE; - } - break; - case HAD_PS: - if (c == ' ' || c == '\n' || compatible_flag) { - ungetc(c, fp); - do_picture(fp); - state = START; - } - else { - fputs(".PS", stdout); - putchar(c); - state = MIDDLE; - } - break; - case HAD_l: - if (c == 'f') - state = HAD_lf; - else { - putchar('.'); - putchar('l'); - putchar(c); - if (c == '\n') { - current_lineno++; - state = START; - } - else - state = MIDDLE; - } - break; - case HAD_lf: - if (c == ' ' || c == '\n' || compatible_flag) { - string line; - while (c != EOF) { - line += c; - if (c == '\n') { - current_lineno++; - break; - } - c = getc(fp); - } - line += '\0'; - interpret_lf_args(line.contents()); - printf(".lf%s", line.contents()); - state = START; - } - else { - fputs(".lf", stdout); - putchar(c); - state = MIDDLE; - } - break; - default: - assert(0); - } - } - switch (state) { - case START: - break; - case MIDDLE: - putchar('\n'); - break; - case HAD_DOT: - fputs(".\n", stdout); - break; - case HAD_P: - fputs(".P\n", stdout); - break; - case HAD_PS: - fputs(".PS\n", stdout); - break; - case HAD_l: - fputs(".l\n", stdout); - break; - case HAD_lf: - fputs(".lf\n", stdout); - break; - } - if (fp != stdin) - fclose(fp); -} - -#ifdef FIG_SUPPORT -void do_whole_file(const char *filename) -{ - // Do not set current_filename. - FILE *fp; - if (strcmp(filename, "-") == 0) - fp = stdin; - else { - errno = 0; - fp = fopen(filename, "r"); - if (fp == 0) - fatal("can't open `%1': %2", filename, strerror(errno)); - } - lex_init(new file_input(fp, filename)); - if (yyparse()) - had_parse_error = 1; - parse_cleanup(); - lex_cleanup(); -} -#endif - -void usage(FILE *stream) -{ - fprintf(stream, "usage: %s [ -nvC ] [ filename ... ]\n", program_name); -#ifdef TEX_SUPPORT - fprintf(stream, " %s -t [ -cvzC ] [ filename ... ]\n", program_name); -#endif -#ifdef FIG_SUPPORT - fprintf(stream, " %s -f [ -v ] [ filename ]\n", program_name); -#endif -} - -#if defined(__MSDOS__) || defined(__EMX__) -static char *fix_program_name(char *arg, char *dflt) -{ - if (!arg) - return dflt; - char *prog = strchr(arg, '\0'); - for (;;) { - if (prog == arg) - break; - --prog; - if (strchr("\\/:", *prog)) { - prog++; - break; - } - } - char *ext = strchr(prog, '.'); - if (ext) - *ext = '\0'; - for (char *p = prog; *p; p++) - if ('A' <= *p && *p <= 'Z') - *p = 'a' + (*p - 'A'); - return prog; -} -#endif /* __MSDOS__ || __EMX__ */ - -int main(int argc, char **argv) -{ - setlocale(LC_NUMERIC, "C"); -#if defined(__MSDOS__) || defined(__EMX__) - argv[0] = fix_program_name(argv[0], "pic"); -#endif /* __MSDOS__ || __EMX__ */ - program_name = argv[0]; - static char stderr_buf[BUFSIZ]; - setbuf(stderr, stderr_buf); - int opt; -#ifdef TEX_SUPPORT - int tex_flag = 0; - int tpic_flag = 0; -#endif -#ifdef FIG_SUPPORT - int whole_file_flag = 0; - int fig_flag = 0; -#endif - static const struct option long_options[] = { - { "help", no_argument, 0, CHAR_MAX + 1 }, - { "version", no_argument, 0, 'v' }, - { NULL, 0, 0, 0 } - }; - while ((opt = getopt_long(argc, argv, "T:CDSUtcvnxzpf", long_options, NULL)) - != EOF) - switch (opt) { - case 'C': - compatible_flag = 1; - break; - case 'D': - case 'T': - break; - case 'S': - safer_flag = 1; - break; - case 'U': - safer_flag = 0; - break; - case 'f': -#ifdef FIG_SUPPORT - whole_file_flag++; - fig_flag++; -#else - fatal("fig support not included"); -#endif - break; - case 'n': - driver_extension_flag = 0; - break; - case 'p': - case 'x': - warning("-%1 option is obsolete", char(opt)); - break; - case 't': -#ifdef TEX_SUPPORT - tex_flag++; -#else - fatal("TeX support not included"); -#endif - break; - case 'c': -#ifdef TEX_SUPPORT - tpic_flag++; -#else - fatal("TeX support not included"); -#endif - break; - case 'v': - { - printf("GNU pic (groff) version %s\n", Version_string); - exit(0); - break; - } - case 'z': - // zero length lines will be printed as dots - zero_length_line_flag++; - break; - case CHAR_MAX + 1: // --help - usage(stdout); - exit(0); - break; - case '?': - usage(stderr); - exit(1); - break; - default: - assert(0); - } - parse_init(); -#ifdef TEX_SUPPORT - if (tpic_flag) { - out = make_tpic_output(); - lf_flag = 0; - } - else if (tex_flag) { - out = make_tex_output(); - command_char = '\\'; - lf_flag = 0; - } - else -#endif -#ifdef FIG_SUPPORT - if (fig_flag) - out = make_fig_output(); - else -#endif - out = make_troff_output(); -#ifdef FIG_SUPPORT - if (whole_file_flag) { - if (optind >= argc) - do_whole_file("-"); - else if (argc - optind > 1) { - usage(stderr); - exit(1); - } else - do_whole_file(argv[optind]); - } - else { -#endif - if (optind >= argc) - do_file("-"); - else - for (int i = optind; i < argc; i++) - do_file(argv[i]); -#ifdef FIG_SUPPORT - } -#endif - delete out; - if (ferror(stdout) || fflush(stdout) < 0) - fatal("output error"); - return had_parse_error; -} - diff --git a/contrib/groff/src/preproc/pic/object.cpp b/contrib/groff/src/preproc/pic/object.cpp deleted file mode 100644 index aefbd45e3940..000000000000 --- a/contrib/groff/src/preproc/pic/object.cpp +++ /dev/null @@ -1,2017 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002, 2003, 2004, 2005 - 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "pic.h" -#include "ptable.h" -#include "object.h" - -void print_object_list(object *); - -line_type::line_type() -: type(solid), thickness(1.0) -{ -} - -output::output() : args(0), desired_height(0.0), desired_width(0.0) -{ -} - -output::~output() -{ - a_delete args; -} - -void output::set_desired_width_height(double wid, double ht) -{ - desired_width = wid; - desired_height = ht; -} - -void output::set_args(const char *s) -{ - a_delete args; - if (s == 0 || *s == '\0') - args = 0; - else - args = strsave(s); -} - -int output::supports_filled_polygons() -{ - return 0; -} - -void output::begin_block(const position &, const position &) -{ -} - -void output::end_block() -{ -} - -double output::compute_scale(double sc, const position &ll, const position &ur) -{ - distance dim = ur - ll; - if (desired_width != 0.0 || desired_height != 0.0) { - sc = 0.0; - if (desired_width != 0.0) { - if (dim.x == 0.0) - error("width specified for picture with zero width"); - else - sc = dim.x/desired_width; - } - if (desired_height != 0.0) { - if (dim.y == 0.0) - error("height specified for picture with zero height"); - else { - double tem = dim.y/desired_height; - if (tem > sc) - sc = tem; - } - } - return sc == 0.0 ? 1.0 : sc; - } - else { - if (sc <= 0.0) - sc = 1.0; - distance sdim = dim/sc; - double max_width = 0.0; - lookup_variable("maxpswid", &max_width); - double max_height = 0.0; - lookup_variable("maxpsht", &max_height); - if ((max_width > 0.0 && sdim.x > max_width) - || (max_height > 0.0 && sdim.y > max_height)) { - double xscale = dim.x/max_width; - double yscale = dim.y/max_height; - return xscale > yscale ? xscale : yscale; - } - else - return sc; - } -} - -position::position(const place &pl) -{ - if (pl.obj != 0) { - // Use two statements to work around bug in SGI C++. - object *tem = pl.obj; - *this = tem->origin(); - } - else { - x = pl.x; - y = pl.y; - } -} - -position::position() : x(0.0), y(0.0) -{ -} - -position::position(double a, double b) : x(a), y(b) -{ -} - - -int operator==(const position &a, const position &b) -{ - return a.x == b.x && a.y == b.y; -} - -int operator!=(const position &a, const position &b) -{ - return a.x != b.x || a.y != b.y; -} - -position &position::operator+=(const position &a) -{ - x += a.x; - y += a.y; - return *this; -} - -position &position::operator-=(const position &a) -{ - x -= a.x; - y -= a.y; - return *this; -} - -position &position::operator*=(double a) -{ - x *= a; - y *= a; - return *this; -} - -position &position::operator/=(double a) -{ - x /= a; - y /= a; - return *this; -} - -position operator-(const position &a) -{ - return position(-a.x, -a.y); -} - -position operator+(const position &a, const position &b) -{ - return position(a.x + b.x, a.y + b.y); -} - -position operator-(const position &a, const position &b) -{ - return position(a.x - b.x, a.y - b.y); -} - -position operator/(const position &a, double n) -{ - return position(a.x/n, a.y/n); -} - -position operator*(const position &a, double n) -{ - return position(a.x*n, a.y*n); -} - -// dot product - -double operator*(const position &a, const position &b) -{ - return a.x*b.x + a.y*b.y; -} - -double hypot(const position &a) -{ - return groff_hypot(a.x, a.y); -} - -struct arrow_head_type { - double height; - double width; - int solid; -}; - -void draw_arrow(const position &pos, const distance &dir, - const arrow_head_type &aht, const line_type <, - char *outline_color_for_fill) -{ - double hyp = hypot(dir); - if (hyp == 0.0) { - error("cannot draw arrow on object with zero length"); - return; - } - position base = -dir; - base *= aht.height/hyp; - position n(dir.y, -dir.x); - n *= aht.width/(hyp*2.0); - line_type slt = lt; - slt.type = line_type::solid; - if (aht.solid && out->supports_filled_polygons()) { - position v[3]; - v[0] = pos; - v[1] = pos + base + n; - v[2] = pos + base - n; - // fill with outline color - out->set_color(outline_color_for_fill, outline_color_for_fill); - // make stroke thin to avoid arrow sticking - slt.thickness = 0.1; - out->polygon(v, 3, slt, 1); - } - else { - // use two line segments to avoid arrow sticking - out->line(pos + base - n, &pos, 1, slt); - out->line(pos + base + n, &pos, 1, slt); - } -} - -object::object() : prev(0), next(0) -{ -} - -object::~object() -{ -} - -void object::move_by(const position &) -{ -} - -void object::print() -{ -} - -void object::print_text() -{ -} - -int object::blank() -{ - return 0; -} - -struct bounding_box { - int blank; - position ll; - position ur; - - bounding_box(); - void encompass(const position &); -}; - -bounding_box::bounding_box() -: blank(1) -{ -} - -void bounding_box::encompass(const position &pos) -{ - if (blank) { - ll = pos; - ur = pos; - blank = 0; - } - else { - if (pos.x < ll.x) - ll.x = pos.x; - if (pos.y < ll.y) - ll.y = pos.y; - if (pos.x > ur.x) - ur.x = pos.x; - if (pos.y > ur.y) - ur.y = pos.y; - } -} - -void object::update_bounding_box(bounding_box *) -{ -} - -position object::origin() -{ - return position(0.0,0.0); -} - -position object::north() -{ - return origin(); -} - -position object::south() -{ - return origin(); -} - -position object::east() -{ - return origin(); -} - -position object::west() -{ - return origin(); -} - -position object::north_east() -{ - return origin(); -} - -position object::north_west() -{ - return origin(); -} - -position object::south_east() -{ - return origin(); -} - -position object::south_west() -{ - return origin(); -} - -position object::start() -{ - return origin(); -} - -position object::end() -{ - return origin(); -} - -position object::center() -{ - return origin(); -} - -double object::width() -{ - return 0.0; -} - -double object::radius() -{ - return 0.0; -} - -double object::height() -{ - return 0.0; -} - -place *object::find_label(const char *) -{ - return 0; -} - -segment::segment(const position &a, int n, segment *p) -: is_absolute(n), pos(a), next(p) -{ -} - -text_item::text_item(char *t, const char *fn, int ln) -: next(0), text(t), filename(fn), lineno(ln) -{ - adj.h = CENTER_ADJUST; - adj.v = NONE_ADJUST; -} - -text_item::~text_item() -{ - a_delete text; -} - -object_spec::object_spec(object_type t) : type(t) -{ - flags = 0; - tbl = 0; - segment_list = 0; - segment_width = segment_height = 0.0; - segment_is_absolute = 0; - text = 0; - shaded = 0; - outlined = 0; - with = 0; - dir = RIGHT_DIRECTION; -} - -object_spec::~object_spec() -{ - delete tbl; - while (segment_list != 0) { - segment *tem = segment_list; - segment_list = segment_list->next; - delete tem; - } - object *p = oblist.head; - while (p != 0) { - object *tem = p; - p = p->next; - delete tem; - } - while (text != 0) { - text_item *tem = text; - text = text->next; - delete tem; - } - delete with; - a_delete shaded; - a_delete outlined; -} - -class command_object : public object { - char *s; - const char *filename; - int lineno; -public: - command_object(char *, const char *, int); - ~command_object(); - object_type type() { return OTHER_OBJECT; } - void print(); -}; - -command_object::command_object(char *p, const char *fn, int ln) -: s(p), filename(fn), lineno(ln) -{ -} - -command_object::~command_object() -{ - a_delete s; -} - -void command_object::print() -{ - out->command(s, filename, lineno); -} - -object *make_command_object(char *s, const char *fn, int ln) -{ - return new command_object(s, fn, ln); -} - -class mark_object : public object { -public: - mark_object(); - object_type type(); -}; - -object *make_mark_object() -{ - return new mark_object(); -} - -mark_object::mark_object() -{ -} - -object_type mark_object::type() -{ - return MARK_OBJECT; -} - -object_list::object_list() : head(0), tail(0) -{ -} - -void object_list::append(object *obj) -{ - if (tail == 0) { - obj->next = obj->prev = 0; - head = tail = obj; - } - else { - obj->prev = tail; - obj->next = 0; - tail->next = obj; - tail = obj; - } -} - -void object_list::wrap_up_block(object_list *ol) -{ - object *p; - for (p = tail; p && p->type() != MARK_OBJECT; p = p->prev) - ; - assert(p != 0); - ol->head = p->next; - if (ol->head) { - ol->tail = tail; - ol->head->prev = 0; - } - else - ol->tail = 0; - tail = p->prev; - if (tail) - tail->next = 0; - else - head = 0; - delete p; -} - -text_piece::text_piece() -: text(0), filename(0), lineno(-1) -{ - adj.h = CENTER_ADJUST; - adj.v = NONE_ADJUST; -} - -text_piece::~text_piece() -{ - a_delete text; -} - -class graphic_object : public object { - int ntext; - text_piece *text; - int aligned; -protected: - line_type lt; - char *outline_color; - char *color_fill; -public: - graphic_object(); - ~graphic_object(); - object_type type() = 0; - void print_text(); - void add_text(text_item *, int); - void set_dotted(double); - void set_dashed(double); - void set_thickness(double); - void set_invisible(); - void set_outline_color(char *); - char *get_outline_color(); - virtual void set_fill(double); - virtual void set_fill_color(char *); -}; - -graphic_object::graphic_object() -: ntext(0), text(0), aligned(0), outline_color(0), color_fill(0) -{ -} - -void graphic_object::set_dotted(double wid) -{ - lt.type = line_type::dotted; - lt.dash_width = wid; -} - -void graphic_object::set_dashed(double wid) -{ - lt.type = line_type::dashed; - lt.dash_width = wid; -} - -void graphic_object::set_thickness(double th) -{ - lt.thickness = th; -} - -void graphic_object::set_fill(double) -{ -} - -void graphic_object::set_fill_color(char *c) -{ - color_fill = strsave(c); -} - -void graphic_object::set_outline_color(char *c) -{ - outline_color = strsave(c); -} - -char *graphic_object::get_outline_color() -{ - return outline_color; -} - -void graphic_object::set_invisible() -{ - lt.type = line_type::invisible; -} - -void graphic_object::add_text(text_item *t, int a) -{ - aligned = a; - int len = 0; - text_item *p; - for (p = t; p; p = p->next) - len++; - if (len == 0) - text = 0; - else { - text = new text_piece[len]; - for (p = t, len = 0; p; p = p->next, len++) { - text[len].text = p->text; - p->text = 0; - text[len].adj = p->adj; - text[len].filename = p->filename; - text[len].lineno = p->lineno; - } - } - ntext = len; -} - -void graphic_object::print_text() -{ - double angle = 0.0; - if (aligned) { - position d(end() - start()); - if (d.x != 0.0 || d.y != 0.0) - angle = atan2(d.y, d.x); - } - if (text != 0) { - out->set_color(color_fill, get_outline_color()); - out->text(center(), text, ntext, angle); - out->reset_color(); - } -} - -graphic_object::~graphic_object() -{ - if (text) - ad_delete(ntext) text; -} - -class rectangle_object : public graphic_object { -protected: - position cent; - position dim; -public: - rectangle_object(const position &); - double width() { return dim.x; } - double height() { return dim.y; } - position origin() { return cent; } - position center() { return cent; } - position north() { return position(cent.x, cent.y + dim.y/2.0); } - position south() { return position(cent.x, cent.y - dim.y/2.0); } - position east() { return position(cent.x + dim.x/2.0, cent.y); } - position west() { return position(cent.x - dim.x/2.0, cent.y); } - position north_east() { return position(cent.x + dim.x/2.0, cent.y + dim.y/2.0); } - position north_west() { return position(cent.x - dim.x/2.0, cent.y + dim.y/2.0); } - position south_east() { return position(cent.x + dim.x/2.0, cent.y - dim.y/2.0); } - position south_west() { return position(cent.x - dim.x/2.0, cent.y - dim.y/2.0); } - object_type type() = 0; - void update_bounding_box(bounding_box *); - void move_by(const position &); -}; - -rectangle_object::rectangle_object(const position &d) -: dim(d) -{ -} - -void rectangle_object::update_bounding_box(bounding_box *p) -{ - p->encompass(cent - dim/2.0); - p->encompass(cent + dim/2.0); -} - -void rectangle_object::move_by(const position &a) -{ - cent += a; -} - -class closed_object : public rectangle_object { -public: - closed_object(const position &); - object_type type() = 0; - void set_fill(double); - void set_fill_color(char *fill); -protected: - double fill; // < 0 if not filled - char *color_fill; // = 0 if not colored -}; - -closed_object::closed_object(const position &pos) -: rectangle_object(pos), fill(-1.0), color_fill(0) -{ -} - -void closed_object::set_fill(double f) -{ - assert(f >= 0.0); - fill = f; -} - -void closed_object::set_fill_color(char *f) -{ - color_fill = strsave(f); -} - -class box_object : public closed_object { - double xrad; - double yrad; -public: - box_object(const position &, double); - object_type type() { return BOX_OBJECT; } - void print(); - position north_east(); - position north_west(); - position south_east(); - position south_west(); -}; - -box_object::box_object(const position &pos, double r) -: closed_object(pos), xrad(dim.x > 0 ? r : -r), yrad(dim.y > 0 ? r : -r) -{ -} - -const double CHOP_FACTOR = 1.0 - 1.0/M_SQRT2; - -position box_object::north_east() -{ - return position(cent.x + dim.x/2.0 - CHOP_FACTOR*xrad, - cent.y + dim.y/2.0 - CHOP_FACTOR*yrad); -} - -position box_object::north_west() -{ - return position(cent.x - dim.x/2.0 + CHOP_FACTOR*xrad, - cent.y + dim.y/2.0 - CHOP_FACTOR*yrad); -} - -position box_object::south_east() -{ - return position(cent.x + dim.x/2.0 - CHOP_FACTOR*xrad, - cent.y - dim.y/2.0 + CHOP_FACTOR*yrad); -} - -position box_object::south_west() -{ - return position(cent.x - dim.x/2.0 + CHOP_FACTOR*xrad, - cent.y - dim.y/2.0 + CHOP_FACTOR*yrad); -} - -void box_object::print() -{ - if (lt.type == line_type::invisible && fill < 0.0 && color_fill == 0) - return; - out->set_color(color_fill, graphic_object::get_outline_color()); - if (xrad == 0.0) { - distance dim2 = dim/2.0; - position vec[4]; - vec[0] = cent + position(dim2.x, -dim2.y); - vec[1] = cent + position(dim2.x, dim2.y); - vec[2] = cent + position(-dim2.x, dim2.y); - vec[3] = cent + position(-dim2.x, -dim2.y); - out->polygon(vec, 4, lt, fill); - } - else { - distance abs_dim(fabs(dim.x), fabs(dim.y)); - out->rounded_box(cent, abs_dim, fabs(xrad), lt, fill); - } - out->reset_color(); -} - -graphic_object *object_spec::make_box(position *curpos, direction *dirp) -{ - static double last_box_height; - static double last_box_width; - static double last_box_radius; - static int have_last_box = 0; - if (!(flags & HAS_HEIGHT)) { - if ((flags & IS_SAME) && have_last_box) - height = last_box_height; - else - lookup_variable("boxht", &height); - } - if (!(flags & HAS_WIDTH)) { - if ((flags & IS_SAME) && have_last_box) - width = last_box_width; - else - lookup_variable("boxwid", &width); - } - if (!(flags & HAS_RADIUS)) { - if ((flags & IS_SAME) && have_last_box) - radius = last_box_radius; - else - lookup_variable("boxrad", &radius); - } - last_box_width = width; - last_box_height = height; - last_box_radius = radius; - have_last_box = 1; - radius = fabs(radius); - if (radius*2.0 > fabs(width)) - radius = fabs(width/2.0); - if (radius*2.0 > fabs(height)) - radius = fabs(height/2.0); - box_object *p = new box_object(position(width, height), radius); - if (!position_rectangle(p, curpos, dirp)) { - delete p; - p = 0; - } - return p; -} - -// return non-zero for success - -int object_spec::position_rectangle(rectangle_object *p, - position *curpos, direction *dirp) -{ - position pos; - dir = *dirp; // ignore any direction in attribute list - position motion; - switch (dir) { - case UP_DIRECTION: - motion.y = p->height()/2.0; - break; - case DOWN_DIRECTION: - motion.y = -p->height()/2.0; - break; - case LEFT_DIRECTION: - motion.x = -p->width()/2.0; - break; - case RIGHT_DIRECTION: - motion.x = p->width()/2.0; - break; - default: - assert(0); - } - if (flags & HAS_AT) { - pos = at; - if (flags & HAS_WITH) { - place offset; - place here; - here.obj = p; - if (!with->follow(here, &offset)) - return 0; - pos -= offset; - } - } - else { - pos = *curpos; - pos += motion; - } - p->move_by(pos); - pos += motion; - *curpos = pos; - return 1; -} - -class block_object : public rectangle_object { - object_list oblist; - PTABLE(place) *tbl; -public: - block_object(const position &, const object_list &ol, PTABLE(place) *t); - ~block_object(); - place *find_label(const char *); - object_type type(); - void move_by(const position &); - void print(); -}; - -block_object::block_object(const position &d, const object_list &ol, - PTABLE(place) *t) -: rectangle_object(d), oblist(ol), tbl(t) -{ -} - -block_object::~block_object() -{ - delete tbl; - object *p = oblist.head; - while (p != 0) { - object *tem = p; - p = p->next; - delete tem; - } -} - -void block_object::print() -{ - out->begin_block(south_west(), north_east()); - print_object_list(oblist.head); - out->end_block(); -} - -static void adjust_objectless_places(PTABLE(place) *tbl, const position &a) -{ - // Adjust all the labels that aren't attached to objects. - PTABLE_ITERATOR(place) iter(tbl); - const char *key; - place *pl; - while (iter.next(&key, &pl)) - if (key && csupper(key[0]) && pl->obj == 0) { - pl->x += a.x; - pl->y += a.y; - } -} - -void block_object::move_by(const position &a) -{ - cent += a; - for (object *p = oblist.head; p; p = p->next) - p->move_by(a); - adjust_objectless_places(tbl, a); -} - - -place *block_object::find_label(const char *name) -{ - return tbl->lookup(name); -} - -object_type block_object::type() -{ - return BLOCK_OBJECT; -} - -graphic_object *object_spec::make_block(position *curpos, direction *dirp) -{ - bounding_box bb; - for (object *p = oblist.head; p; p = p->next) - p->update_bounding_box(&bb); - position dim; - if (!bb.blank) { - position m = -(bb.ll + bb.ur)/2.0; - for (object *p = oblist.head; p; p = p->next) - p->move_by(m); - adjust_objectless_places(tbl, m); - dim = bb.ur - bb.ll; - } - if (flags & HAS_WIDTH) - dim.x = width; - if (flags & HAS_HEIGHT) - dim.y = height; - block_object *block = new block_object(dim, oblist, tbl); - if (!position_rectangle(block, curpos, dirp)) { - delete block; - block = 0; - } - tbl = 0; - oblist.head = oblist.tail = 0; - return block; -} - -class text_object : public rectangle_object { -public: - text_object(const position &); - object_type type() { return TEXT_OBJECT; } -}; - -text_object::text_object(const position &d) -: rectangle_object(d) -{ -} - -graphic_object *object_spec::make_text(position *curpos, direction *dirp) -{ - if (!(flags & HAS_HEIGHT)) { - lookup_variable("textht", &height); - int nitems = 0; - for (text_item *t = text; t; t = t->next) - nitems++; - height *= nitems; - } - if (!(flags & HAS_WIDTH)) - lookup_variable("textwid", &width); - text_object *p = new text_object(position(width, height)); - if (!position_rectangle(p, curpos, dirp)) { - delete p; - p = 0; - } - return p; -} - - -class ellipse_object : public closed_object { -public: - ellipse_object(const position &); - position north_east() { return position(cent.x + dim.x/(M_SQRT2*2.0), - cent.y + dim.y/(M_SQRT2*2.0)); } - position north_west() { return position(cent.x - dim.x/(M_SQRT2*2.0), - cent.y + dim.y/(M_SQRT2*2.0)); } - position south_east() { return position(cent.x + dim.x/(M_SQRT2*2.0), - cent.y - dim.y/(M_SQRT2*2.0)); } - position south_west() { return position(cent.x - dim.x/(M_SQRT2*2.0), - cent.y - dim.y/(M_SQRT2*2.0)); } - double radius() { return dim.x/2.0; } - object_type type() { return ELLIPSE_OBJECT; } - void print(); -}; - -ellipse_object::ellipse_object(const position &d) -: closed_object(d) -{ -} - -void ellipse_object::print() -{ - if (lt.type == line_type::invisible && fill < 0.0 && color_fill == 0) - return; - out->set_color(color_fill, graphic_object::get_outline_color()); - out->ellipse(cent, dim, lt, fill); - out->reset_color(); -} - -graphic_object *object_spec::make_ellipse(position *curpos, direction *dirp) -{ - static double last_ellipse_height; - static double last_ellipse_width; - static int have_last_ellipse = 0; - if (!(flags & HAS_HEIGHT)) { - if ((flags & IS_SAME) && have_last_ellipse) - height = last_ellipse_height; - else - lookup_variable("ellipseht", &height); - } - if (!(flags & HAS_WIDTH)) { - if ((flags & IS_SAME) && have_last_ellipse) - width = last_ellipse_width; - else - lookup_variable("ellipsewid", &width); - } - last_ellipse_width = width; - last_ellipse_height = height; - have_last_ellipse = 1; - ellipse_object *p = new ellipse_object(position(width, height)); - if (!position_rectangle(p, curpos, dirp)) { - delete p; - return 0; - } - return p; -} - -class circle_object : public ellipse_object { -public: - circle_object(double); - object_type type() { return CIRCLE_OBJECT; } - void print(); -}; - -circle_object::circle_object(double diam) -: ellipse_object(position(diam, diam)) -{ -} - -void circle_object::print() -{ - if (lt.type == line_type::invisible && fill < 0.0 && color_fill == 0) - return; - out->set_color(color_fill, graphic_object::get_outline_color()); - out->circle(cent, dim.x/2.0, lt, fill); - out->reset_color(); -} - -graphic_object *object_spec::make_circle(position *curpos, direction *dirp) -{ - static double last_circle_radius; - static int have_last_circle = 0; - if (!(flags & HAS_RADIUS)) { - if ((flags & IS_SAME) && have_last_circle) - radius = last_circle_radius; - else - lookup_variable("circlerad", &radius); - } - last_circle_radius = radius; - have_last_circle = 1; - circle_object *p = new circle_object(radius*2.0); - if (!position_rectangle(p, curpos, dirp)) { - delete p; - return 0; - } - return p; -} - -class move_object : public graphic_object { - position strt; - position en; -public: - move_object(const position &s, const position &e); - position origin() { return en; } - object_type type() { return MOVE_OBJECT; } - void update_bounding_box(bounding_box *); - void move_by(const position &); -}; - -move_object::move_object(const position &s, const position &e) -: strt(s), en(e) -{ -} - -void move_object::update_bounding_box(bounding_box *p) -{ - p->encompass(strt); - p->encompass(en); -} - -void move_object::move_by(const position &a) -{ - strt += a; - en += a; -} - -graphic_object *object_spec::make_move(position *curpos, direction *dirp) -{ - static position last_move; - static int have_last_move = 0; - *dirp = dir; - // No need to look at at since `at' attribute sets `from' attribute. - position startpos = (flags & HAS_FROM) ? from : *curpos; - if (!(flags & HAS_SEGMENT)) { - if ((flags & IS_SAME) && have_last_move) - segment_pos = last_move; - else { - switch (dir) { - case UP_DIRECTION: - segment_pos.y = segment_height; - break; - case DOWN_DIRECTION: - segment_pos.y = -segment_height; - break; - case LEFT_DIRECTION: - segment_pos.x = -segment_width; - break; - case RIGHT_DIRECTION: - segment_pos.x = segment_width; - break; - default: - assert(0); - } - } - } - segment_list = new segment(segment_pos, segment_is_absolute, segment_list); - // Reverse the segment_list so that it's in forward order. - segment *old = segment_list; - segment_list = 0; - while (old != 0) { - segment *tem = old->next; - old->next = segment_list; - segment_list = old; - old = tem; - } - // Compute the end position. - position endpos = startpos; - for (segment *s = segment_list; s; s = s->next) - if (s->is_absolute) - endpos = s->pos; - else - endpos += s->pos; - have_last_move = 1; - last_move = endpos - startpos; - move_object *p = new move_object(startpos, endpos); - *curpos = endpos; - return p; -} - -class linear_object : public graphic_object { -protected: - char arrow_at_start; - char arrow_at_end; - arrow_head_type aht; - position strt; - position en; -public: - linear_object(const position &s, const position &e); - position start() { return strt; } - position end() { return en; } - void move_by(const position &); - void update_bounding_box(bounding_box *) = 0; - object_type type() = 0; - void add_arrows(int at_start, int at_end, const arrow_head_type &); -}; - -class line_object : public linear_object { -protected: - position *v; - int n; -public: - line_object(const position &s, const position &e, position *, int); - ~line_object(); - position origin() { return strt; } - position center() { return (strt + en)/2.0; } - position north() { return (en.y - strt.y) > 0 ? en : strt; } - position south() { return (en.y - strt.y) < 0 ? en : strt; } - position east() { return (en.x - strt.x) > 0 ? en : strt; } - position west() { return (en.x - strt.x) < 0 ? en : strt; } - object_type type() { return LINE_OBJECT; } - void update_bounding_box(bounding_box *); - void print(); - void move_by(const position &); -}; - -class arrow_object : public line_object { -public: - arrow_object(const position &, const position &, position *, int); - object_type type() { return ARROW_OBJECT; } -}; - -class spline_object : public line_object { -public: - spline_object(const position &, const position &, position *, int); - object_type type() { return SPLINE_OBJECT; } - void print(); - void update_bounding_box(bounding_box *); -}; - -linear_object::linear_object(const position &s, const position &e) -: arrow_at_start(0), arrow_at_end(0), strt(s), en(e) -{ -} - -void linear_object::move_by(const position &a) -{ - strt += a; - en += a; -} - -void linear_object::add_arrows(int at_start, int at_end, - const arrow_head_type &a) -{ - arrow_at_start = at_start; - arrow_at_end = at_end; - aht = a; -} - -line_object::line_object(const position &s, const position &e, - position *p, int i) -: linear_object(s, e), v(p), n(i) -{ -} - -void line_object::print() -{ - if (lt.type == line_type::invisible) - return; - out->set_color(0, graphic_object::get_outline_color()); - // shorten line length to avoid arrow sticking. - position sp = strt; - if (arrow_at_start) { - position base = v[0] - strt; - double hyp = hypot(base); - if (hyp == 0.0) { - error("cannot draw arrow on object with zero length"); - return; - } - if (aht.solid && out->supports_filled_polygons()) { - base *= aht.height / hyp; - draw_arrow(strt, strt - v[0], aht, lt, - graphic_object::get_outline_color()); - sp = strt + base; - } else { - base *= fabs(lt.thickness) / hyp / 72 / 4; - sp = strt + base; - draw_arrow(sp, sp - v[0], aht, lt, - graphic_object::get_outline_color()); - } - } - if (arrow_at_end) { - position base = v[n-1] - (n > 1 ? v[n-2] : strt); - double hyp = hypot(base); - if (hyp == 0.0) { - error("cannot draw arrow on object with zero length"); - return; - } - if (aht.solid && out->supports_filled_polygons()) { - base *= aht.height / hyp; - draw_arrow(en, v[n-1] - (n > 1 ? v[n-2] : strt), aht, lt, - graphic_object::get_outline_color()); - v[n-1] = en - base; - } else { - base *= fabs(lt.thickness) / hyp / 72 / 4; - v[n-1] = en - base; - draw_arrow(v[n-1], v[n-1] - (n > 1 ? v[n-2] : strt), aht, lt, - graphic_object::get_outline_color()); - } - } - out->line(sp, v, n, lt); - out->reset_color(); -} - -void line_object::update_bounding_box(bounding_box *p) -{ - p->encompass(strt); - for (int i = 0; i < n; i++) - p->encompass(v[i]); -} - -void line_object::move_by(const position &pos) -{ - linear_object::move_by(pos); - for (int i = 0; i < n; i++) - v[i] += pos; -} - -void spline_object::update_bounding_box(bounding_box *p) -{ - p->encompass(strt); - p->encompass(en); - /* - - If - - p1 = q1/2 + q2/2 - p2 = q1/6 + q2*5/6 - p3 = q2*5/6 + q3/6 - p4 = q2/2 + q3/2 - [ the points for the Bezier cubic ] - - and - - t = .5 - - then - - (1-t)^3*p1 + 3*t*(t - 1)^2*p2 + 3*t^2*(1-t)*p3 + t^3*p4 - [ the equation for the Bezier cubic ] - - = .125*q1 + .75*q2 + .125*q3 - - */ - for (int i = 1; i < n; i++) - p->encompass((i == 1 ? strt : v[i-2])*.125 + v[i-1]*.75 + v[i]*.125); -} - -arrow_object::arrow_object(const position &s, const position &e, - position *p, int i) -: line_object(s, e, p, i) -{ -} - -spline_object::spline_object(const position &s, const position &e, - position *p, int i) -: line_object(s, e, p, i) -{ -} - -void spline_object::print() -{ - if (lt.type == line_type::invisible) - return; - out->set_color(0, graphic_object::get_outline_color()); - // shorten line length for spline to avoid arrow sticking - position sp = strt; - if (arrow_at_start) { - position base = v[0] - strt; - double hyp = hypot(base); - if (hyp == 0.0) { - error("cannot draw arrow on object with zero length"); - return; - } - if (aht.solid && out->supports_filled_polygons()) { - base *= aht.height / hyp; - draw_arrow(strt, strt - v[0], aht, lt, - graphic_object::get_outline_color()); - sp = strt + base*0.1; // to reserve spline shape - } else { - base *= fabs(lt.thickness) / hyp / 72 / 4; - sp = strt + base; - draw_arrow(sp, sp - v[0], aht, lt, - graphic_object::get_outline_color()); - } - } - if (arrow_at_end) { - position base = v[n-1] - (n > 1 ? v[n-2] : strt); - double hyp = hypot(base); - if (hyp == 0.0) { - error("cannot draw arrow on object with zero length"); - return; - } - if (aht.solid && out->supports_filled_polygons()) { - base *= aht.height / hyp; - draw_arrow(en, v[n-1] - (n > 1 ? v[n-2] : strt), aht, lt, - graphic_object::get_outline_color()); - v[n-1] = en - base*0.1; // to reserve spline shape - } else { - base *= fabs(lt.thickness) / hyp / 72 / 4; - v[n-1] = en - base; - draw_arrow(v[n-1], v[n-1] - (n > 1 ? v[n-2] : strt), aht, lt, - graphic_object::get_outline_color()); - } - } - out->spline(sp, v, n, lt); - out->reset_color(); -} - -line_object::~line_object() -{ - a_delete v; -} - -linear_object *object_spec::make_line(position *curpos, direction *dirp) -{ - static position last_line; - static int have_last_line = 0; - *dirp = dir; - // No need to look at at since `at' attribute sets `from' attribute. - position startpos = (flags & HAS_FROM) ? from : *curpos; - if (!(flags & HAS_SEGMENT)) { - if ((flags & IS_SAME) && (type == LINE_OBJECT || type == ARROW_OBJECT) - && have_last_line) - segment_pos = last_line; - else - switch (dir) { - case UP_DIRECTION: - segment_pos.y = segment_height; - break; - case DOWN_DIRECTION: - segment_pos.y = -segment_height; - break; - case LEFT_DIRECTION: - segment_pos.x = -segment_width; - break; - case RIGHT_DIRECTION: - segment_pos.x = segment_width; - break; - default: - assert(0); - } - } - segment_list = new segment(segment_pos, segment_is_absolute, segment_list); - // reverse the segment_list so that it's in forward order - segment *old = segment_list; - segment_list = 0; - while (old != 0) { - segment *tem = old->next; - old->next = segment_list; - segment_list = old; - old = tem; - } - // Absolutise all movements - position endpos = startpos; - int nsegments = 0; - segment *s; - for (s = segment_list; s; s = s->next, nsegments++) - if (s->is_absolute) - endpos = s->pos; - else { - endpos += s->pos; - s->pos = endpos; - s->is_absolute = 1; // to avoid confusion - } - // handle chop - line_object *p = 0; - position *v = new position[nsegments]; - int i = 0; - for (s = segment_list; s; s = s->next, i++) - v[i] = s->pos; - if (flags & IS_DEFAULT_CHOPPED) { - lookup_variable("circlerad", &start_chop); - end_chop = start_chop; - flags |= IS_CHOPPED; - } - if (flags & IS_CHOPPED) { - position start_chop_vec, end_chop_vec; - if (start_chop != 0.0) { - start_chop_vec = v[0] - startpos; - start_chop_vec *= start_chop / hypot(start_chop_vec); - } - if (end_chop != 0.0) { - end_chop_vec = (v[nsegments - 1] - - (nsegments > 1 ? v[nsegments - 2] : startpos)); - end_chop_vec *= end_chop / hypot(end_chop_vec); - } - startpos += start_chop_vec; - v[nsegments - 1] -= end_chop_vec; - endpos -= end_chop_vec; - } - switch (type) { - case SPLINE_OBJECT: - p = new spline_object(startpos, endpos, v, nsegments); - break; - case ARROW_OBJECT: - p = new arrow_object(startpos, endpos, v, nsegments); - break; - case LINE_OBJECT: - p = new line_object(startpos, endpos, v, nsegments); - break; - default: - assert(0); - } - have_last_line = 1; - last_line = endpos - startpos; - *curpos = endpos; - return p; -} - -class arc_object : public linear_object { - int clockwise; - position cent; - double rad; -public: - arc_object(int, const position &, const position &, const position &); - position origin() { return cent; } - position center() { return cent; } - double radius() { return rad; } - position north(); - position south(); - position east(); - position west(); - position north_east(); - position north_west(); - position south_east(); - position south_west(); - void update_bounding_box(bounding_box *); - object_type type() { return ARC_OBJECT; } - void print(); - void move_by(const position &pos); -}; - -arc_object::arc_object(int cw, const position &s, const position &e, - const position &c) -: linear_object(s, e), clockwise(cw), cent(c) -{ - rad = hypot(c - s); -} - -void arc_object::move_by(const position &pos) -{ - linear_object::move_by(pos); - cent += pos; -} - -// we get arc corners from the corresponding circle - -position arc_object::north() -{ - position result(cent); - result.y += rad; - return result; -} - -position arc_object::south() -{ - position result(cent); - result.y -= rad; - return result; -} - -position arc_object::east() -{ - position result(cent); - result.x += rad; - return result; -} - -position arc_object::west() -{ - position result(cent); - result.x -= rad; - return result; -} - -position arc_object::north_east() -{ - position result(cent); - result.x += rad/M_SQRT2; - result.y += rad/M_SQRT2; - return result; -} - -position arc_object::north_west() -{ - position result(cent); - result.x -= rad/M_SQRT2; - result.y += rad/M_SQRT2; - return result; -} - -position arc_object::south_east() -{ - position result(cent); - result.x += rad/M_SQRT2; - result.y -= rad/M_SQRT2; - return result; -} - -position arc_object::south_west() -{ - position result(cent); - result.x -= rad/M_SQRT2; - result.y -= rad/M_SQRT2; - return result; -} - - -void arc_object::print() -{ - if (lt.type == line_type::invisible) - return; - out->set_color(0, graphic_object::get_outline_color()); - // handle arrow direction; make shorter line for arc - position sp, ep, b; - if (clockwise) { - sp = en; - ep = strt; - } else { - sp = strt; - ep = en; - } - if (arrow_at_start) { - double theta = aht.height / rad; - if (clockwise) - theta = - theta; - b = strt - cent; - b = position(b.x*cos(theta) - b.y*sin(theta), - b.x*sin(theta) + b.y*cos(theta)) + cent; - if (clockwise) - ep = b; - else - sp = b; - if (aht.solid && out->supports_filled_polygons()) { - draw_arrow(strt, strt - b, aht, lt, - graphic_object::get_outline_color()); - } else { - position v = b; - theta = fabs(lt.thickness) / 72 / 4 / rad; - if (clockwise) - theta = - theta; - b = strt - cent; - b = position(b.x*cos(theta) - b.y*sin(theta), - b.x*sin(theta) + b.y*cos(theta)) + cent; - draw_arrow(b, b - v, aht, lt, - graphic_object::get_outline_color()); - out->line(b, &v, 1, lt); - } - } - if (arrow_at_end) { - double theta = aht.height / rad; - if (!clockwise) - theta = - theta; - b = en - cent; - b = position(b.x*cos(theta) - b.y*sin(theta), - b.x*sin(theta) + b.y*cos(theta)) + cent; - if (clockwise) - sp = b; - else - ep = b; - if (aht.solid && out->supports_filled_polygons()) { - draw_arrow(en, en - b, aht, lt, - graphic_object::get_outline_color()); - } else { - position v = b; - theta = fabs(lt.thickness) / 72 / 4 / rad; - if (!clockwise) - theta = - theta; - b = en - cent; - b = position(b.x*cos(theta) - b.y*sin(theta), - b.x*sin(theta) + b.y*cos(theta)) + cent; - draw_arrow(b, b - v, aht, lt, - graphic_object::get_outline_color()); - out->line(b, &v, 1, lt); - } - } - out->arc(sp, cent, ep, lt); - out->reset_color(); -} - -inline double max(double a, double b) -{ - return a > b ? a : b; -} - -void arc_object::update_bounding_box(bounding_box *p) -{ - p->encompass(strt); - p->encompass(en); - position start_offset = strt - cent; - if (start_offset.x == 0.0 && start_offset.y == 0.0) - return; - position end_offset = en - cent; - if (end_offset.x == 0.0 && end_offset.y == 0.0) - return; - double start_quad = atan2(start_offset.y, start_offset.x)/(M_PI/2.0); - double end_quad = atan2(end_offset.y, end_offset.x)/(M_PI/2.0); - if (clockwise) { - double temp = start_quad; - start_quad = end_quad; - end_quad = temp; - } - if (start_quad < 0.0) - start_quad += 4.0; - while (end_quad <= start_quad) - end_quad += 4.0; - double r = max(hypot(start_offset), hypot(end_offset)); - for (int q = int(start_quad) + 1; q < end_quad; q++) { - position offset; - switch (q % 4) { - case 0: - offset.x = r; - break; - case 1: - offset.y = r; - break; - case 2: - offset.x = -r; - break; - case 3: - offset.y = -r; - break; - } - p->encompass(cent + offset); - } -} - -// We ignore the with attribute. The at attribute always refers to the center. - -linear_object *object_spec::make_arc(position *curpos, direction *dirp) -{ - *dirp = dir; - int cw = (flags & IS_CLOCKWISE) != 0; - // compute the start - position startpos; - if (flags & HAS_FROM) - startpos = from; - else - startpos = *curpos; - if (!(flags & HAS_RADIUS)) - lookup_variable("arcrad", &radius); - // compute the end - position endpos; - if (flags & HAS_TO) - endpos = to; - else { - position m(radius, radius); - // Adjust the signs. - if (cw) { - if (dir == DOWN_DIRECTION || dir == LEFT_DIRECTION) - m.x = -m.x; - if (dir == DOWN_DIRECTION || dir == RIGHT_DIRECTION) - m.y = -m.y; - *dirp = direction((dir + 3) % 4); - } - else { - if (dir == UP_DIRECTION || dir == LEFT_DIRECTION) - m.x = -m.x; - if (dir == DOWN_DIRECTION || dir == LEFT_DIRECTION) - m.y = -m.y; - *dirp = direction((dir + 1) % 4); - } - endpos = startpos + m; - } - // compute the center - position centerpos; - if (flags & HAS_AT) - centerpos = at; - else if (startpos == endpos) - centerpos = startpos; - else { - position h = (endpos - startpos)/2.0; - double d = hypot(h); - if (radius <= 0) - radius = .25; - // make the radius big enough - while (radius < d) - radius *= 2.0; - double alpha = acos(d/radius); - double theta = atan2(h.y, h.x); - if (cw) - theta -= alpha; - else - theta += alpha; - centerpos = position(cos(theta), sin(theta))*radius + startpos; - } - arc_object *p = new arc_object(cw, startpos, endpos, centerpos); - *curpos = endpos; - return p; -} - -graphic_object *object_spec::make_linear(position *curpos, direction *dirp) -{ - linear_object *obj; - if (type == ARC_OBJECT) - obj = make_arc(curpos, dirp); - else - obj = make_line(curpos, dirp); - if (type == ARROW_OBJECT - && (flags & (HAS_LEFT_ARROW_HEAD|HAS_RIGHT_ARROW_HEAD)) == 0) - flags |= HAS_RIGHT_ARROW_HEAD; - if (obj && (flags & (HAS_LEFT_ARROW_HEAD|HAS_RIGHT_ARROW_HEAD))) { - arrow_head_type a; - int at_start = (flags & HAS_LEFT_ARROW_HEAD) != 0; - int at_end = (flags & HAS_RIGHT_ARROW_HEAD) != 0; - if (flags & HAS_HEIGHT) - a.height = height; - else - lookup_variable("arrowht", &a.height); - if (flags & HAS_WIDTH) - a.width = width; - else - lookup_variable("arrowwid", &a.width); - double solid; - lookup_variable("arrowhead", &solid); - a.solid = solid != 0.0; - obj->add_arrows(at_start, at_end, a); - } - return obj; -} - -object *object_spec::make_object(position *curpos, direction *dirp) -{ - graphic_object *obj = 0; - switch (type) { - case BLOCK_OBJECT: - obj = make_block(curpos, dirp); - break; - case BOX_OBJECT: - obj = make_box(curpos, dirp); - break; - case TEXT_OBJECT: - obj = make_text(curpos, dirp); - break; - case ELLIPSE_OBJECT: - obj = make_ellipse(curpos, dirp); - break; - case CIRCLE_OBJECT: - obj = make_circle(curpos, dirp); - break; - case MOVE_OBJECT: - obj = make_move(curpos, dirp); - break; - case ARC_OBJECT: - case LINE_OBJECT: - case SPLINE_OBJECT: - case ARROW_OBJECT: - obj = make_linear(curpos, dirp); - break; - case MARK_OBJECT: - case OTHER_OBJECT: - default: - assert(0); - break; - } - if (obj) { - if (flags & IS_INVISIBLE) - obj->set_invisible(); - if (text != 0) - obj->add_text(text, (flags & IS_ALIGNED) != 0); - if (flags & IS_DOTTED) - obj->set_dotted(dash_width); - else if (flags & IS_DASHED) - obj->set_dashed(dash_width); - double th; - if (flags & HAS_THICKNESS) - th = thickness; - else - lookup_variable("linethick", &th); - obj->set_thickness(th); - if (flags & IS_OUTLINED) - obj->set_outline_color(outlined); - if (flags & (IS_DEFAULT_FILLED | IS_FILLED)) { - if (flags & IS_SHADED) - obj->set_fill_color(shaded); - else { - if (flags & IS_DEFAULT_FILLED) - lookup_variable("fillval", &fill); - if (fill < 0.0) - error("bad fill value %1", fill); - else - obj->set_fill(fill); - } - } - } - return obj; -} - -struct string_list { - string_list *next; - char *str; - string_list(char *); - ~string_list(); -}; - -string_list::string_list(char *s) -: next(0), str(s) -{ -} - -string_list::~string_list() -{ - a_delete str; -} - -/* A path is used to hold the argument to the `with' attribute. For - example, `.nw' or `.A.s' or `.A'. The major operation on a path is to - take a place and follow the path through the place to place within the - place. Note that `.A.B.C.sw' will work. - - For compatibility with DWB pic, `with' accepts positions also (this - is incorrectly documented in CSTR 116). */ - -path::path(corner c) -: crn(c), label_list(0), ypath(0), is_position(0) -{ -} - -path::path(position p) -: crn(0), label_list(0), ypath(0), is_position(1) -{ - pos.x = p.x; - pos.y = p.y; -} - -path::path(char *l, corner c) -: crn(c), ypath(0), is_position(0) -{ - label_list = new string_list(l); -} - -path::~path() -{ - while (label_list) { - string_list *tem = label_list; - label_list = label_list->next; - delete tem; - } - delete ypath; -} - -void path::append(corner c) -{ - assert(crn == 0); - crn = c; -} - -void path::append(char *s) -{ - string_list **p; - for (p = &label_list; *p; p = &(*p)->next) - ; - *p = new string_list(s); -} - -void path::set_ypath(path *p) -{ - ypath = p; -} - -// return non-zero for success - -int path::follow(const place &pl, place *result) const -{ - if (is_position) { - result->x = pos.x; - result->y = pos.y; - result->obj = 0; - return 1; - } - const place *p = &pl; - for (string_list *lb = label_list; lb; lb = lb->next) - if (p->obj == 0 || (p = p->obj->find_label(lb->str)) == 0) { - lex_error("object does not contain a place `%1'", lb->str); - return 0; - } - if (crn == 0 || p->obj == 0) - *result = *p; - else { - position ps = ((p->obj)->*(crn))(); - result->x = ps.x; - result->y = ps.y; - result->obj = 0; - } - if (ypath) { - place tem; - if (!ypath->follow(pl, &tem)) - return 0; - result->y = tem.y; - if (result->obj != tem.obj) - result->obj = 0; - } - return 1; -} - -void print_object_list(object *p) -{ - for (; p; p = p->next) { - p->print(); - p->print_text(); - } -} - -void print_picture(object *obj) -{ - bounding_box bb; - for (object *p = obj; p; p = p->next) - p->update_bounding_box(&bb); - double scale; - lookup_variable("scale", &scale); - out->start_picture(scale, bb.ll, bb.ur); - print_object_list(obj); - out->finish_picture(); -} - diff --git a/contrib/groff/src/preproc/pic/object.h b/contrib/groff/src/preproc/pic/object.h deleted file mode 100644 index 9f7f4bc33708..000000000000 --- a/contrib/groff/src/preproc/pic/object.h +++ /dev/null @@ -1,225 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2002, 2004 - 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -struct place; - -enum object_type { - OTHER_OBJECT, - BOX_OBJECT, - CIRCLE_OBJECT, - ELLIPSE_OBJECT, - ARC_OBJECT, - SPLINE_OBJECT, - LINE_OBJECT, - ARROW_OBJECT, - MOVE_OBJECT, - TEXT_OBJECT, - BLOCK_OBJECT, - MARK_OBJECT - }; - -struct bounding_box; - -struct object { - object *prev; - object *next; - object(); - virtual ~object(); - virtual position origin(); - virtual double width(); - virtual double radius(); - virtual double height(); - virtual position north(); - virtual position south(); - virtual position east(); - virtual position west(); - virtual position north_east(); - virtual position north_west(); - virtual position south_east(); - virtual position south_west(); - virtual position start(); - virtual position end(); - virtual position center(); - virtual place *find_label(const char *); - virtual void move_by(const position &); - virtual int blank(); - virtual void update_bounding_box(bounding_box *); - virtual object_type type() = 0; - virtual void print(); - virtual void print_text(); -}; - -typedef position (object::*corner)(); - -struct place { - object *obj; - double x, y; -}; - -struct string_list; - -class path { - position pos; - corner crn; - string_list *label_list; - path *ypath; - int is_position; -public: - path(corner = 0); - path(position); - path(char *, corner = 0); - ~path(); - void append(corner); - void append(char *); - void set_ypath(path *); - int follow(const place &, place *) const; -}; - -struct object_list { - object *head; - object *tail; - object_list(); - void append(object *); - void wrap_up_block(object_list *); -}; - -declare_ptable(place) - -// these go counterclockwise -enum direction { - RIGHT_DIRECTION, - UP_DIRECTION, - LEFT_DIRECTION, - DOWN_DIRECTION - }; - -struct graphics_state { - double x, y; - direction dir; -}; - -struct saved_state : public graphics_state { - saved_state *prev; - PTABLE(place) *tbl; -}; - - -struct text_item { - text_item *next; - char *text; - adjustment adj; - const char *filename; - int lineno; - - text_item(char *, const char *, int); - ~text_item(); -}; - -const unsigned long IS_DOTTED = 01; -const unsigned long IS_DASHED = 02; -const unsigned long IS_CLOCKWISE = 04; -const unsigned long IS_INVISIBLE = 020; -const unsigned long HAS_LEFT_ARROW_HEAD = 040; -const unsigned long HAS_RIGHT_ARROW_HEAD = 0100; -const unsigned long HAS_SEGMENT = 0200; -const unsigned long IS_SAME = 0400; -const unsigned long HAS_FROM = 01000; -const unsigned long HAS_AT = 02000; -const unsigned long HAS_WITH = 04000; -const unsigned long HAS_HEIGHT = 010000; -const unsigned long HAS_WIDTH = 020000; -const unsigned long HAS_RADIUS = 040000; -const unsigned long HAS_TO = 0100000; -const unsigned long IS_CHOPPED = 0200000; -const unsigned long IS_DEFAULT_CHOPPED = 0400000; -const unsigned long HAS_THICKNESS = 01000000; -const unsigned long IS_FILLED = 02000000; -const unsigned long IS_DEFAULT_FILLED = 04000000; -const unsigned long IS_ALIGNED = 010000000; -const unsigned long IS_SHADED = 020000000; -const unsigned long IS_OUTLINED = 040000000; - -struct segment { - int is_absolute; - position pos; - segment *next; - segment(const position &, int, segment *); -}; - -class rectangle_object; -class graphic_object; -class linear_object; - -struct object_spec { - unsigned long flags; - object_type type; - object_list oblist; - PTABLE(place) *tbl; - double dash_width; - position from; - position to; - position at; - position by; - path *with; - text_item *text; - double height; - double radius; - double width; - double segment_width; - double segment_height; - double start_chop; - double end_chop; - double thickness; - double fill; - char *shaded; - char *outlined; - direction dir; - segment *segment_list; - position segment_pos; - int segment_is_absolute; - - object_spec(object_type); - ~object_spec(); - object *make_object(position *, direction *); - graphic_object *make_box(position *, direction *); - graphic_object *make_block(position *, direction *); - graphic_object *make_text(position *, direction *); - graphic_object *make_ellipse(position *, direction *); - graphic_object *make_circle(position *, direction *); - linear_object *make_line(position *, direction *); - linear_object *make_arc(position *, direction *); - graphic_object *make_linear(position *, direction *); - graphic_object *make_move(position *, direction *); - int position_rectangle(rectangle_object *p, position *curpos, - direction *dirp); -}; - - -object *make_object(object_spec *, position *, direction *); - -object *make_mark_object(); -object *make_command_object(char *, const char *, int); - -int lookup_variable(const char *name, double *val); -void define_variable(const char *name, double val); - -void print_picture(object *); - diff --git a/contrib/groff/src/preproc/pic/output.h b/contrib/groff/src/preproc/pic/output.h deleted file mode 100644 index aa03e776bb00..000000000000 --- a/contrib/groff/src/preproc/pic/output.h +++ /dev/null @@ -1,83 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2001 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -struct line_type { - enum { invisible, solid, dotted, dashed } type; - double dash_width; - double thickness; // the thickness is in points - - line_type(); -}; - - -class output { -protected: - char *args; - double desired_height; // zero if no height specified - double desired_width; // zero if no depth specified - double compute_scale(double, const position &, const position &); -public: - output(); - virtual ~output(); - void set_desired_width_height(double wid, double ht); - void set_args(const char *); - virtual void start_picture(double sc, const position &ll, const position &ur) = 0; - virtual void finish_picture() = 0; - virtual void circle(const position &, double rad, - const line_type &, double) = 0; - virtual void text(const position &, text_piece *, int, double) = 0; - virtual void line(const position &, const position *, int n, - const line_type &) = 0; - virtual void polygon(const position *, int n, - const line_type &, double) = 0; - virtual void spline(const position &, const position *, int n, - const line_type &) = 0; - virtual void arc(const position &, const position &, const position &, - const line_type &) = 0; - virtual void ellipse(const position &, const distance &, - const line_type &, double) = 0; - virtual void rounded_box(const position &, const distance &, double, - const line_type &, double) = 0; - virtual void command(const char *, const char *, int) = 0; - virtual void set_location(const char *, int) {} - virtual void set_color(char *, char *) = 0; - virtual void reset_color() = 0; - virtual char *get_last_filled() = 0; - virtual char *get_outline_color() = 0; - virtual int supports_filled_polygons(); - virtual void begin_block(const position &ll, const position &ur); - virtual void end_block(); -}; - -extern output *out; - -/* #define FIG_SUPPORT 1 */ -#define TEX_SUPPORT 1 - -output *make_troff_output(); - -#ifdef TEX_SUPPORT -output *make_tex_output(); -output *make_tpic_output(); -#endif /* TEX_SUPPORT */ - -#ifdef FIG_SUPPORT -output *make_fig_output(); -#endif /* FIG_SUPPORT */ diff --git a/contrib/groff/src/preproc/pic/pic.h b/contrib/groff/src/preproc/pic/pic.h deleted file mode 100644 index e3b850a96ef0..000000000000 --- a/contrib/groff/src/preproc/pic/pic.h +++ /dev/null @@ -1,123 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2003, 2005 - 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "lib.h" - -#include -#include -#include - -#ifdef NEED_DECLARATION_RAND -#undef rand -extern "C" { - int rand(); -} -#endif /* NEED_DECLARATION_RAND */ - -#ifdef NEED_DECLARATION_SRAND -#undef srand -extern "C" { -#ifdef RET_TYPE_SRAND_IS_VOID - void srand(unsigned int); -#else - int srand(unsigned int); -#endif -} -#endif /* NEED_DECLARATION_SRAND */ - -#ifndef HAVE_FMOD -extern "C" { - double fmod(double, double); -} -#endif - -#include "assert.h" -#include "cset.h" -#include "stringclass.h" -#include "errarg.h" -#include "error.h" -#include "position.h" -#include "text.h" -#include "output.h" - -#ifndef M_SQRT2 -#define M_SQRT2 1.41421356237309504880 -#endif - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -class input { - input *next; -public: - input(); - virtual ~input(); - virtual int get() = 0; - virtual int peek() = 0; - virtual int get_location(const char **, int *); - friend class input_stack; - friend class copy_rest_thru_input; -}; - -class file_input : public input { - FILE *fp; - const char *filename; - int lineno; - string line; - const char *ptr; - int read_line(); -public: - file_input(FILE *, const char *); - ~file_input(); - int get(); - int peek(); - int get_location(const char **, int *); -}; - -void lex_init(input *); -int get_location(char **, int *); - -void do_copy(const char *file); -void parse_init(); -void parse_cleanup(); - -void lex_error(const char *message, - const errarg &arg1 = empty_errarg, - const errarg &arg2 = empty_errarg, - const errarg &arg3 = empty_errarg); - -void lex_warning(const char *message, - const errarg &arg1 = empty_errarg, - const errarg &arg2 = empty_errarg, - const errarg &arg3 = empty_errarg); - -void lex_cleanup(); - -extern int flyback_flag; -extern int command_char; -// zero_length_line_flag is non-zero if zero-length lines are drawn -// as dots by the output device -extern int zero_length_line_flag; -extern int driver_extension_flag; -extern int compatible_flag; -extern int safer_flag; -extern char *graphname; diff --git a/contrib/groff/src/preproc/pic/pic.man b/contrib/groff/src/preproc/pic/pic.man deleted file mode 100644 index c54cfbef5911..000000000000 --- a/contrib/groff/src/preproc/pic/pic.man +++ /dev/null @@ -1,1109 +0,0 @@ -.ig -Copyright (C) 1989-2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. - -Permission is granted to make and distribute verbatim copies of -this manual provided the copyright notice and this permission notice -are preserved on all copies. - -Permission is granted to copy and distribute modified versions of this -manual under the conditions for verbatim copying, provided that the -entire resulting derived work is distributed under the terms of a -permission notice identical to this one. - -Permission is granted to copy and distribute translations of this -manual into another language, under the above conditions for modified -versions, except that this permission notice may be included in -translations approved by the Free Software Foundation instead of in -the original English. -.. -. -. -.\" 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" -.. -. -.ie t \{\ -. ds tx T\h'-.1667m'\v'.224m'E\v'-.224m'\h'-.125m'X -. ds lx L\h'-0.36m'\v'-0.22v'\s-2A\s0\h'-0.15m'\v'0.22v'\*(tx -.\} -.el \{\ -. ds tx TeX -. ds lx LaTeX -.\} -. -.ie \n(.g .ds ic \/ -.el .ds ic \^ -. -.\" The BSD man macros can't handle " in arguments to font change macros, -.\" so use \(ts instead of ". -.tr \(ts" -. -. -.TH @G@PIC @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@" -. -. -.SH NAME -. -@g@pic \- compile pictures for troff or TeX -. -. -.SH SYNOPSIS -. -.B @g@pic -[ -.B \-nvCSU -] -[ -.I filename -\&.\|.\|.\& -] -.br -.B @g@pic -.B \-t -[ -.B \-cvzCSU -] -[ -.I filename -\&.\|.\|.\& -] -. -. -.SH DESCRIPTION -. -This manual page describes the GNU version of -.BR pic , -which is part of the groff document formatting system. -.B pic -compiles descriptions of pictures embedded within -.B troff -or \*(tx input files into commands that are understood by \*(tx or -.BR troff . -Each picture starts with a line beginning with -.B .PS -and ends with a line beginning with -.BR .PE . -Anything outside of -.B .PS -and -.B .PE -is passed through without change. -.LP -It is the user's responsibility to provide appropriate definitions of the -.B PS -and -.B PE -macros. -When the macro package being used does not supply such definitions -(for example, old versions of \-ms), -appropriate definitions can be obtained with -.BR \-mpic : -These will center each picture. -. -. -.SH OPTIONS -. -Options that do not take arguments may be grouped behind a single -.BR \- . -The special option -.B \-\^\- -can be used to mark the end of the options. -A filename of -.B \- -refers to the standard input. -. -.TP -.B \-C -Recognize -.B .PS -and -.B .PE -even when followed by a character other than space or newline. -. -.TP -.B \-S -Safer mode; do not execute -.B sh -commands. -This can be useful when operating on untrustworthy input. -(enabled by default) -. -.TP -.B \-U -Unsafe mode; revert the default option -.BR \-S . -. -.TP -.B \-n -Don't use the groff extensions to the troff drawing commands. -You should use this if you are using a postprocessor that doesn't support -these extensions. -The extensions are described in -.BR groff_out (@MAN5EXT@). -The -.B \-n -option also causes -.B pic -not to use zero-length lines to draw dots in troff mode. -. -.TP -.B \-t -\*(tx mode. -. -.TP -.B \-c -Be more compatible with -.BR tpic . -Implies -.BR \-t . -Lines beginning with -.B \e -are not passed through transparently. -Lines beginning with -.B . -are passed through with the initial -.B . -changed to -.BR \e . -A line beginning with -.B .ps -is given special treatment: -it takes an optional integer argument specifying -the line thickness (pen size) in milliinches; -a missing argument restores the previous line thickness; -the default line thickness is 8 milliinches. -The line thickness thus specified takes effect only -when a non-negative line thickness has not been -specified by use of the -.B thickness -attribute or by setting the -.B linethick -variable. -. -.TP -.B \-v -Print the version number. -. -.TP -.B \-z -In \*(tx mode draw dots using zero-length lines. -. -.LP -The following options supported by other versions of -.B pic -are ignored: -. -.TP -.B \-D -Draw all lines using the \eD escape sequence. -.B pic -always does this. -. -.TP -.BI \-T \ dev -Generate output for the -.B troff -device -.IR dev . -This is unnecessary because the -.B troff -output generated by -.B pic -is device-independent. -. -. -.SH USAGE -. -This section describes only the differences between GNU -.B pic -and the original version of -.BR pic . -Many of these differences also apply to newer versions of Unix -.BR pic . -A complete documentation is available in the file -.LP -.RS -.B @DOCDIR@/pic.ms -.RE -. -.SS \*(tx mode -. -\*(tx mode is enabled by the -.B \-t -option. -In \*(tx mode, -.B pic -will define a vbox called -.B \egraph -for each picture. -Use the -.B figname -command to change the name of the vbox. -You must yourself print that vbox using, for example, the command -.RS -.LP -.B -\ecenterline{\ebox\egraph} -.RE -.LP -Actually, since the vbox has a height of zero (it is defined with -\evtop) this will produce slightly more vertical space above the -picture than below it; -.RS -.LP -.B -\ecenterline{\eraise 1em\ebox\egraph} -.RE -.LP -would avoid this. -.LP -To make the vbox having a positive height and a depth of zero -(as used e.g.\& by \*(lx's -.BR \%graphics.sty ), -define the following macro in your document: -.RS -.LP -.B \edef\egpicbox#1{% -.br -.B " \evbox{\eunvbox\ecsname #1\eendcsname\ekern 0pt}}" -.RE -.LP -Now you can simply say -.B \egpicbox{graph} -instead of \ebox\egraph. -.LP -You must use a \*(tx driver that supports the -.B tpic -specials, version 2. -.LP -Lines beginning with -.B \e -are passed through transparently; a -.B % -is added to the end of the line to avoid unwanted spaces. -You can safely use this feature to change fonts or to -change the value of -.BR \ebaselineskip . -Anything else may well produce undesirable results; use at your own risk. -Lines beginning with a period are not given any special treatment. -. -.SS Commands -. -.TP -\fBfor\fR \fIvariable\fR \fB=\fR \fIexpr1\fR \fBto\fR \fIexpr2\fR \ -[\fBby\fR [\fB*\fR]\fIexpr3\fR] \fBdo\fR \fIX\fR \fIbody\fR \fIX\fR -Set -.I variable -to -.IR expr1 . -While the value of -.I variable -is less than or equal to -.IR expr2 , -do -.I body -and increment -.I variable -by -.IR expr3 ; -if -.B by -is not given, increment -.I variable -by 1. -If -.I expr3 -is prefixed by -.B * -then -.I variable -will instead be multiplied by -.IR expr3 . -The value of -.I expr3 -can be negative for the additive case; -.I variable -is then tested whether it is greater than or equal to -.IR expr2 . -For the multiplicative case, -.I expr3 -must be greater than zero. -If the constraints aren't met, the loop isn't executed. -.I X -can be any character not occurring in -.IR body . -. -.TP -\fBif\fR \fIexpr\fR \fBthen\fR \fIX\fR \fIif-true\fR \fIX\fR \ -[\fBelse\fR \fIY\fR \fIif-false\fR \fIY\fR] -Evaluate -.IR expr ; -if it is non-zero then do -.IR if-true , -otherwise do -.IR if-false . -.I X -can be any character not occurring in -.IR if-true . -.I Y -can be any character not occurring in -.IR if-false . -. -.TP -\fBprint\fR \fIarg\fR\|.\|.\|. -Concatenate the arguments and print as a line on stderr. -Each -.I arg -must be an expression, a position, or text. -This is useful for debugging. -. -.TP -\fBcommand\fR \fIarg\fR\|.\|.\|. -Concatenate the arguments -and pass them through as a line to troff or \*(tx. -Each -.I arg -must be an expression, a position, or text. -This has a similar effect to a line beginning with -.B .\& -or -.BR \e , -but allows the values of variables to be passed through. -For example, -.RS -.IP -.ft B -.nf -\&.PS -x = 14 -command ".ds string x is " x "." -\&.PE -\e*[string] -.ft -.fi -.RE -.IP -prints -.RS -.IP -.B x is 14. -.RE -. -.TP -\fBsh\fR \fIX\fR \fIcommand\fR \fIX\fR -Pass -.I command -to a shell. -.I X -can be any character not occurring in -.IR command . -. -.TP -\fBcopy\fR \fB"\fIfilename\fB"\fR -Include -.I filename -at this point in the file. -. -.TP -\fBcopy\fR [\fB"\fIfilename\fB"\fR] \fBthru\fR \fIX\fR \fIbody\fR \fIX\fR \ -[\fBuntil\fR \fB"\fIword\*(ic\fB"\fR] -.ns -.TP -\fBcopy\fR [\fB"\fIfilename\fB"\fR] \fBthru\fR \fImacro\fR \ -[\fBuntil\fR \fB"\fIword\*(ic\fB"\fR] -This construct does -.I body -once for each line of -.IR filename ; -the line is split into blank-delimited words, -and occurrences of -.BI $ i -in -.IR body , -for -.I i -between 1 and 9, -are replaced by the -.IR i -th -word of the line. -If -.I filename -is not given, lines are taken from the current input up to -.BR .PE . -If an -.B until -clause is specified, -lines will be read only until a line the first word of which is -.IR word ; -that line will then be discarded. -.I X -can be any character not occurring in -.IR body . -For example, -.RS -.IP -.ft B -.nf -\&.PS -copy thru % circle at ($1,$2) % until "END" -1 2 -3 4 -5 6 -END -box -\&.PE -.ft -.fi -.RE -.IP -is equivalent to -.RS -.IP -.ft B -.nf -\&.PS -circle at (1,2) -circle at (3,4) -circle at (5,6) -box -\&.PE -.ft -.fi -.RE -.IP -The commands to be performed for each line can also be taken -from a macro defined earlier by giving the name of the macro -as the argument to -.BR thru . -. -.LP -.B reset -.br -.ns -.TP -\fBreset\fI variable1\fR[\fB,\fR]\fI variable2 .\^.\^. -Reset pre-defined variables -.IR variable1 , -.I variable2 -\&.\^.\^. to their default values. -If no arguments are given, reset all pre-defined variables -to their default values. -Note that assigning a value to -.B scale -also causes all pre-defined variables that control dimensions -to be reset to their default values times the new value of scale. -. -.TP -\fBplot\fR \fIexpr\fR [\fB"\fItext\*(ic\fB"\fR] -This is a text object which is constructed by using -.I text -as a format string for sprintf -with an argument of -.IR expr . -If -.I text -is omitted a format string of -.B "\(ts%g\(ts" -is used. -Attributes can be specified in the same way as for a normal text -object. -Be very careful that you specify an appropriate format string; -.B pic -does only very limited checking of the string. -This is deprecated in favour of -.BR sprintf . -. -.TP -.IB variable\ := \ expr -This is similar to -.B = -except -.I variable -must already be defined, -and -.I expr -will be assigned to -.I variable -without creating a variable local to the current block. -(By contrast, -.B = -defines the variable in the current block if it is not already defined there, -and then changes the value in the current block only.) -For example, the following: -.RS -.IP -.ft B -.nf -\&.PS -x = 3 -y = 3 -[ - x := 5 - y = 5 -] -print x " " y -\&.PE -.ft -.fi -.RE -.IP -prints -.RS -.IP -.B 5 3 -.RE -. -.LP -Arguments of the form -.IP -.I X anything X -.LP -are also allowed to be of the form -.IP -.BI {\ anything\ } -.LP -In this case -.I anything -can contain balanced occurrences of -.B { -and -.BR } . -Strings may contain -.I X -or imbalanced occurrences of -.B { -and -.BR } . -. -.SS Expressions -. -The syntax for expressions has been significantly extended: -. -.LP -.IB x\ ^\ y -(exponentiation) -.br -.BI sin( x ) -.br -.BI cos( x ) -.br -.BI atan2( y , \ x ) -.br -.BI log( x ) -(base 10) -.br -.BI exp( x ) -(base 10, ie -.ie t 10\v'-.4m'\fIx\*(ic\fR\v'.4m') -.el 10^\fIx\fR) -.br -.BI sqrt( x ) -.br -.BI int( x ) -.br -.B rand() -(return a random number between 0 and 1) -.br -.BI rand( x ) -(return a random number between 1 and -.IR x ; -deprecated) -.br -.BI srand( x ) -(set the random number seed) -.br -.BI max( e1 , \ e2 ) -.br -.BI min( e1 , \ e2 ) -.br -.BI ! e -.br -\fIe1\fB && \fIe2\fR -.br -\fIe1\fB || \fIe2\fR -.br -\fIe1\fB == \fIe2\fR -.br -\fIe1\fB != \fIe2\fR -.br -\fIe1\fB >= \fIe2\fR -.br -\fIe1\fB > \fIe2\fR -.br -\fIe1\fB <= \fIe2\fR -.br -\fIe1\fB < \fIe2\fR -.br -\fB"\fIstr1\*(ic\fB" == "\fIstr2\*(ic\fB"\fR -.br -\fB"\fIstr1\*(ic\fB" != "\fIstr2\*(ic\fB"\fR -.br -. -.LP -String comparison expressions must be parenthesised in some contexts -to avoid ambiguity. -. -.SS Other Changes -. -A bare expression, -.IR expr , -is acceptable as an attribute; -it is equivalent to -.IR dir\ expr , -where -.I dir -is the current direction. -For example -.LP -.RS -.B line 2i -.RE -.LP -means draw a line 2\ inches long in the current direction. -The `i' (or `I') character is ignored; to use another measurement unit, -set the -.I scale -variable to an appropriate value. -. -.LP -The maximum width and height of the picture are taken from the variables -.B maxpswid -and -.BR maxpsht . -Initially these have values 8.5 and 11. -. -.LP -Scientific notation is allowed for numbers. -For example -.RS -.LP -.B -x = 5e\-2 -.RE -. -.LP -Text attributes can be compounded. -For example, -.RS -.LP -.B -"foo" above ljust -.RE -.LP -is valid. -. -.LP -There is no limit to the depth to which blocks can be examined. -For example, -.RS -.LP -.B -[A: [B: [C: box ]]] with .A.B.C.sw at 1,2 -.br -.B -circle at last [\^].A.B.C -.RE -.LP -is acceptable. -. -.LP -Arcs now have compass points -determined by the circle of which the arc is a part. -. -.LP -Circles, ellipses, and arcs can be dotted or dashed. -In \*(tx mode splines can be dotted or dashed also. -. -.LP -Boxes can have rounded corners. -The -.B rad -attribute specifies the radius of the quarter-circles at each corner. -If no -.B rad -or -.B diam -attribute is given, a radius of -.B boxrad -is used. -Initially, -.B boxrad -has a value of\ 0. -A box with rounded corners can be dotted or dashed. -. -.LP -The -.B .PS -line can have a second argument specifying a maximum height for -the picture. -If the width of zero is specified the width will be ignored in computing -the scaling factor for the picture. -Note that GNU -.B pic -will always scale a picture by the same amount vertically as well as -horizontally. -This is different from the -.SM DWB -2.0 -.B pic -which may scale a picture by a different amount vertically than -horizontally if a height is specified. -. -.LP -Each text object has an invisible box associated with it. -The compass points of a text object are determined by this box. -The implicit motion associated with the object is also determined -by this box. -The dimensions of this box are taken from the width and height attributes; -if the width attribute is not supplied then the width will be taken to be -.BR textwid ; -if the height attribute is not supplied then the height will be taken to be -the number of text strings associated with the object -times -.BR textht . -Initially -.B textwid -and -.B textht -have a value of 0. -. -.LP -In (almost all) places where a quoted text string can be used, -an expression of the form -.IP -.BI sprintf(\(ts format \(ts,\ arg ,\fR.\|.\|.\fB) -.LP -can also be used; -this will produce the arguments formatted according to -.IR format , -which should be a string as described in -.BR printf (3) -appropriate for the number of arguments supplied. -. -.LP -The thickness of the lines used to draw objects is controlled by the -.B linethick -variable. -This gives the thickness of lines in points. -A negative value means use the default thickness: -in \*(tx output mode, this means use a thickness of 8 milliinches; -in \*(tx output mode with the -.B -c -option, this means use the line thickness specified by -.B .ps -lines; -in troff output mode, this means use a thickness proportional -to the pointsize. -A zero value means draw the thinnest possible line supported by -the output device. -Initially it has a value of -1. -There is also a -.BR thick [ ness ] -attribute. -For example, -.RS -.LP -.B circle thickness 1.5 -.RE -.LP -would draw a circle using a line with a thickness of 1.5 points. -The thickness of lines is not affected by the -value of the -.B scale -variable, nor by the width or height given in the -.B .PS -line. -. -.LP -Boxes (including boxes with rounded corners), -circles and ellipses can be filled by giving them an attribute of -.BR fill [ ed ]. -This takes an optional argument of an expression with a value between -0 and 1; 0 will fill it with white, 1 with black, values in between -with a proportionally gray shade. -A value greater than 1 can also be used: -this means fill with the -shade of gray that is currently being used for text and lines. -Normally this will be black, but output devices may provide -a mechanism for changing this. -Without an argument, then the value of the variable -.B fillval -will be used. -Initially this has a value of 0.5. -The invisible attribute does not affect the filling of objects. -Any text associated with a filled object will be added after the -object has been filled, so that the text will not be obscured -by the filling. -. -.LP -Three additional modifiers are available to specify colored objects: -.BR outline [ d ] -sets the color of the outline, -.B shaded -the fill color, and -.B colo\fR[\fPu\fR]\fPr\fR[\fPed\fR] -sets both. -All three keywords expect a suffix specifying the color, for example -.RS -.LP -.B circle shaded """green""" outline """black""" -.RE -.LP -Currently, color support isn't available in \*(tx mode. -Predefined color names for -.B groff -are in the device macro files, for example -.BR ps.tmac ; -additional colors can be defined with the -.B .defcolor -request (see the manual page of -.BR @g@troff (@MAN1EXT@) -for more details). -.LP -To change the name of the vbox in \*(tx mode, set the pseudo-variable -.B figname -(which is actually a specially parsed command) within a picture. -Example: -.RS -.LP -.B .PS -.br -.B figname = foobar; -.br -.B ... -.br -.B .PE -.RE -.LP -The picture is then available in the box -.BR \efoobar . -.LP -.B pic -assumes that at the beginning of a picture both glyph and fill color are -set to the default value. -. -.LP -Arrow heads will be drawn as solid triangles if the variable -.B arrowhead -is non-zero and either \*(tx mode is enabled or the -.B \-n -option has not been given. -Initially -.B arrowhead -has a value of\ 1. -Note that solid arrow heads are always filled with the current outline -color. -. -.LP -The troff output of -.B pic -is device-independent. -The -.B \-T -option is therefore redundant. -All numbers are taken to be in inches; numbers are never interpreted -to be in troff machine units. -. -.LP -Objects can have an -.B aligned -attribute. -This will only work if the postprocessor is -.BR grops . -Any text associated with an object having the -.B aligned -attribute will be rotated about the center of the object -so that it is aligned in the direction from the start point -to the end point of the object. -Note that this attribute will have no effect for objects whose start and -end points are coincident. -. -.LP -In places where -.IB n th -is allowed -.BI ` expr 'th -is also allowed. -Note that -.B 'th -is a single token: no space is allowed between the -.B ' -and the -.BR th . -For example, -.IP -.ft B -.nf -for i = 1 to 4 do { - line from `i'th box.nw to `i+1'th box.se -} -.ft -.fi -. -. -.SH CONVERSION -. -To obtain a stand-alone picture from a -.B pic -file, enclose your -.B pic -code with -.B .PS -and -.B .PE -requests; -.B roff -configuration commands may be added at the beginning of the file, but no -.B roff -text. -. -.LP -It is necessary to feed this file into -.B groff -without adding any page information, so you must check which -.B .PS -and -.B .PE -requests are actually called. -For example, the mm macro package adds a page number, which is very -annoying. -At the moment, calling standard -.B groff -without any macro package works. -Alternatively, you can define your own requests, e.g. to do nothing: -.LP -.RS -.nf -.ft B -\&.de PS -\&.. -\&.de PE -\&.. -.ft -.fi -.RE -. -.LP -.B groff -itself does not provide direct conversion into other graphics file -formats. -But there are lots of possibilities if you first transform your picture -into PostScript\*R format using the -.B groff -option -.BR -Tps . -Since this -.IR ps -file -lacks BoundingBox information it is not very useful by itself, but it -may be fed into other conversion programs, usually named -.BI ps2 other -or -.BI psto other -or the like. -Moreover, the PostScript interpreter -.B ghostscript -.RB ( gs ) -has built-in graphics conversion devices that are called with the option -.LP -.RS -.BI "gs -sDEVICE=" -.RE -.LP -Call -.LP -.RS -.B gs --help -.RE -.LP -for a list of the available devices. -. -.LP -As the Encapsulated PostScript File Format -.B EPS -is getting more and more important, and the conversion wasn't regarded -trivial in the past you might be interested to know that there is a -conversion tool named -.B ps2eps -which does the right job. -It is much better than the tool -.B ps2epsi -packaged with -.BR gs . -.LP -For bitmapped graphic formats, you should use -.BR pstopnm ; -the resulting (intermediate) -.B PNM -file can be then converted to virtually any graphics format using the tools -of the -.B netpbm -package . -. -. -.SH FILES -. -.Tp \w'\fB@MACRODIR@/pic.tmac'u+3n -.B -@MACRODIR@/pic.tmac -Example definitions of the -.B PS -and -.B PE -macros. -. -. -.SH "SEE ALSO" -. -.BR @g@troff (@MAN1EXT@), -.BR groff_out (@MAN5EXT@), -.BR tex (1), -.BR gs (1), -.BR ps2eps (1), -.BR pstopnm (1), -.BR ps2epsi (1), -.BR pnm (5) -.LP -Tpic: Pic for \*(tx -.LP -Brian W. Kernighan, -PIC \(em A Graphics Language for Typesetting (User Manual). -AT&T Bell Laboratories, Computing Science Technical Report No.\ 116 - -(revised May, 1991). -.LP -.B ps2eps -is available from CTAN mirrors, e.g. -.br - -.LP -W. Richard Stevens - Turning PIC Into HTML -.br - -.LP -W. Richard Stevens - Examples of picMacros -.br - -. -. -.SH BUGS -. -Input characters that are invalid for -.B groff -(i.e., those with -.SM ASCII -code 0, or 013 octal, or between 015 and 037 octal, or between 0200 and 0237 -octal) are rejected even in \*(tx mode. -.LP -The interpretation of -.B fillval -is incompatible with the pic in 10th edition Unix, -which interprets 0 as black and 1 as white. -.LP -PostScript\*R is a registered trademark of Adobe Systems Incorporation. -. -.\" Local Variables: -.\" mode: nroff -.\" End: diff --git a/contrib/groff/src/preproc/pic/pic.y b/contrib/groff/src/preproc/pic/pic.y deleted file mode 100644 index 83d0fe0222ad..000000000000 --- a/contrib/groff/src/preproc/pic/pic.y +++ /dev/null @@ -1,1898 +0,0 @@ -/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003, 2004, 2005 - 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ -%{ -#include "pic.h" -#include "ptable.h" -#include "object.h" - -extern int delim_flag; -extern void copy_rest_thru(const char *, const char *); -extern void copy_file_thru(const char *, const char *, const char *); -extern void push_body(const char *); -extern void do_for(char *var, double from, double to, - int by_is_multiplicative, double by, char *body); -extern void do_lookahead(); - -/* Maximum number of characters produced by printf("%g") */ -#define GDIGITS 14 - -int yylex(); -void yyerror(const char *); - -void reset(const char *nm); -void reset_all(); - -place *lookup_label(const char *); -void define_label(const char *label, const place *pl); - -direction current_direction; -position current_position; - -implement_ptable(place) - -PTABLE(place) top_table; - -PTABLE(place) *current_table = &top_table; -saved_state *current_saved_state = 0; - -object_list olist; - -const char *ordinal_postfix(int n); -const char *object_type_name(object_type type); -char *format_number(const char *form, double n); -char *do_sprintf(const char *form, const double *v, int nv); - -%} - - -%union { - char *str; - int n; - double x; - struct { double x, y; } pair; - struct { double x; char *body; } if_data; - struct { char *str; const char *filename; int lineno; } lstr; - struct { double *v; int nv; int maxv; } dv; - struct { double val; int is_multiplicative; } by; - place pl; - object *obj; - corner crn; - path *pth; - object_spec *spec; - saved_state *pstate; - graphics_state state; - object_type obtype; -} - -%token LABEL -%token VARIABLE -%token NUMBER -%token TEXT -%token COMMAND_LINE -%token DELIMITED -%token ORDINAL -%token TH -%token LEFT_ARROW_HEAD -%token RIGHT_ARROW_HEAD -%token DOUBLE_ARROW_HEAD -%token LAST -%token UP -%token DOWN -%token LEFT -%token RIGHT -%token BOX -%token CIRCLE -%token ELLIPSE -%token ARC -%token LINE -%token ARROW -%token MOVE -%token SPLINE -%token HEIGHT -%token RADIUS -%token FIGNAME -%token WIDTH -%token DIAMETER -%token UP -%token DOWN -%token RIGHT -%token LEFT -%token FROM -%token TO -%token AT -%token WITH -%token BY -%token THEN -%token SOLID -%token DOTTED -%token DASHED -%token CHOP -%token SAME -%token INVISIBLE -%token LJUST -%token RJUST -%token ABOVE -%token BELOW -%token OF -%token THE -%token WAY -%token BETWEEN -%token AND -%token HERE -%token DOT_N -%token DOT_E -%token DOT_W -%token DOT_S -%token DOT_NE -%token DOT_SE -%token DOT_NW -%token DOT_SW -%token DOT_C -%token DOT_START -%token DOT_END -%token DOT_X -%token DOT_Y -%token DOT_HT -%token DOT_WID -%token DOT_RAD -%token SIN -%token COS -%token ATAN2 -%token LOG -%token EXP -%token SQRT -%token K_MAX -%token K_MIN -%token INT -%token RAND -%token SRAND -%token COPY -%token THRU -%token TOP -%token BOTTOM -%token UPPER -%token LOWER -%token SH -%token PRINT -%token CW -%token CCW -%token FOR -%token DO -%token IF -%token ELSE -%token ANDAND -%token OROR -%token NOTEQUAL -%token EQUALEQUAL -%token LESSEQUAL -%token GREATEREQUAL -%token LEFT_CORNER -%token RIGHT_CORNER -%token NORTH -%token SOUTH -%token EAST -%token WEST -%token CENTER -%token END -%token START -%token RESET -%token UNTIL -%token PLOT -%token THICKNESS -%token FILL -%token COLORED -%token OUTLINED -%token SHADED -%token ALIGNED -%token SPRINTF -%token COMMAND - -%token DEFINE -%token UNDEF - -%left '.' - -/* this ensures that plot 17 "%g" parses as (plot 17 "%g") */ -%left PLOT -%left TEXT SPRINTF - -/* give text adjustments higher precedence than TEXT, so that -box "foo" above ljust == box ("foo" above ljust) -*/ - -%left LJUST RJUST ABOVE BELOW - -%left LEFT RIGHT -/* Give attributes that take an optional expression a higher -precedence than left and right, so that eg `line chop left' -parses properly. */ -%left CHOP SOLID DASHED DOTTED UP DOWN FILL COLORED OUTLINED -%left LABEL - -%left VARIABLE NUMBER '(' SIN COS ATAN2 LOG EXP SQRT K_MAX K_MIN INT RAND SRAND LAST -%left ORDINAL HERE '`' - -%left BOX CIRCLE ELLIPSE ARC LINE ARROW SPLINE '[' - -/* these need to be lower than '-' */ -%left HEIGHT RADIUS WIDTH DIAMETER FROM TO AT THICKNESS - -/* these must have higher precedence than CHOP so that `label %prec CHOP' -works */ -%left DOT_N DOT_E DOT_W DOT_S DOT_NE DOT_SE DOT_NW DOT_SW DOT_C -%left DOT_START DOT_END TOP BOTTOM LEFT_CORNER RIGHT_CORNER -%left UPPER LOWER NORTH SOUTH EAST WEST CENTER START END - -%left ',' -%left OROR -%left ANDAND -%left EQUALEQUAL NOTEQUAL -%left '<' '>' LESSEQUAL GREATEREQUAL - -%left BETWEEN OF -%left AND - -%left '+' '-' -%left '*' '/' '%' -%right '!' -%right '^' - -%type expr any_expr text_expr -%type optional_by -%type expr_pair position_not_place -%type simple_if -%type nth_primitive -%type corner -%type path label_path relative_path -%type place label element element_list middle_element_list -%type object_spec -%type position -%type object_type -%type optional_ordinal_last ordinal -%type macro_name until -%type sprintf_args -%type text print_args print_arg - -%% - -top: - optional_separator - | element_list - { - if (olist.head) - print_picture(olist.head); - } - ; - - -element_list: - optional_separator middle_element_list optional_separator - { $$ = $2; } - ; - -middle_element_list: - element - { $$ = $1; } - | middle_element_list separator element - { $$ = $1; } - ; - -optional_separator: - /* empty */ - | separator - ; - -separator: - ';' - | separator ';' - ; - -placeless_element: - FIGNAME '=' macro_name - { - a_delete graphname; - graphname = new char[strlen($3) + 1]; - strcpy(graphname, $3); - a_delete $3; - } - | - VARIABLE '=' any_expr - { - define_variable($1, $3); - a_delete $1; - } - | VARIABLE ':' '=' any_expr - { - place *p = lookup_label($1); - if (!p) { - lex_error("variable `%1' not defined", $1); - YYABORT; - } - p->obj = 0; - p->x = $4; - p->y = 0.0; - a_delete $1; - } - | UP - { current_direction = UP_DIRECTION; } - | DOWN - { current_direction = DOWN_DIRECTION; } - | LEFT - { current_direction = LEFT_DIRECTION; } - | RIGHT - { current_direction = RIGHT_DIRECTION; } - | COMMAND_LINE - { - olist.append(make_command_object($1.str, $1.filename, - $1.lineno)); - } - | COMMAND print_args - { - olist.append(make_command_object($2.str, $2.filename, - $2.lineno)); - } - | PRINT print_args - { - fprintf(stderr, "%s\n", $2.str); - a_delete $2.str; - fflush(stderr); - } - | SH - { delim_flag = 1; } - DELIMITED - { - delim_flag = 0; - if (safer_flag) - lex_error("unsafe to run command `%1'", $3); - else - system($3); - a_delete $3; - } - | COPY TEXT - { - if (yychar < 0) - do_lookahead(); - do_copy($2.str); - // do not delete the filename - } - | COPY TEXT THRU - { delim_flag = 2; } - DELIMITED - { delim_flag = 0; } - until - { - if (yychar < 0) - do_lookahead(); - copy_file_thru($2.str, $5, $7); - // do not delete the filename - a_delete $5; - a_delete $7; - } - | COPY THRU - { delim_flag = 2; } - DELIMITED - { delim_flag = 0; } - until - { - if (yychar < 0) - do_lookahead(); - copy_rest_thru($4, $6); - a_delete $4; - a_delete $6; - } - | FOR VARIABLE '=' expr TO expr optional_by DO - { delim_flag = 1; } - DELIMITED - { - delim_flag = 0; - if (yychar < 0) - do_lookahead(); - do_for($2, $4, $6, $7.is_multiplicative, $7.val, $10); - } - | simple_if - { - if (yychar < 0) - do_lookahead(); - if ($1.x != 0.0) - push_body($1.body); - a_delete $1.body; - } - | simple_if ELSE - { delim_flag = 1; } - DELIMITED - { - delim_flag = 0; - if (yychar < 0) - do_lookahead(); - if ($1.x != 0.0) - push_body($1.body); - else - push_body($4); - a_delete $1.body; - a_delete $4; - } - | reset_variables - | RESET - { define_variable("scale", 1.0); } - ; - -macro_name: - VARIABLE - | LABEL - ; - -reset_variables: - RESET VARIABLE - { - reset($2); - a_delete $2; - } - | reset_variables VARIABLE - { - reset($2); - a_delete $2; - } - | reset_variables ',' VARIABLE - { - reset($3); - a_delete $3; - } - ; - -print_args: - print_arg - { $$ = $1; } - | print_args print_arg - { - $$.str = new char[strlen($1.str) + strlen($2.str) + 1]; - strcpy($$.str, $1.str); - strcat($$.str, $2.str); - a_delete $1.str; - a_delete $2.str; - if ($1.filename) { - $$.filename = $1.filename; - $$.lineno = $1.lineno; - } - else if ($2.filename) { - $$.filename = $2.filename; - $$.lineno = $2.lineno; - } - } - ; - -print_arg: - expr %prec ',' - { - $$.str = new char[GDIGITS + 1]; - sprintf($$.str, "%g", $1); - $$.filename = 0; - $$.lineno = 0; - } - | text - { $$ = $1; } - | position %prec ',' - { - $$.str = new char[GDIGITS + 2 + GDIGITS + 1]; - sprintf($$.str, "%g, %g", $1.x, $1.y); - $$.filename = 0; - $$.lineno = 0; - } - ; - -simple_if: - IF any_expr THEN - { delim_flag = 1; } - DELIMITED - { - delim_flag = 0; - $$.x = $2; - $$.body = $5; - } - ; - -until: - /* empty */ - { $$ = 0; } - | UNTIL TEXT - { $$ = $2.str; } - ; - -any_expr: - expr - { $$ = $1; } - | text_expr - { $$ = $1; } - ; - -text_expr: - text EQUALEQUAL text - { - $$ = strcmp($1.str, $3.str) == 0; - a_delete $1.str; - a_delete $3.str; - } - | text NOTEQUAL text - { - $$ = strcmp($1.str, $3.str) != 0; - a_delete $1.str; - a_delete $3.str; - } - | text_expr ANDAND text_expr - { $$ = ($1 != 0.0 && $3 != 0.0); } - | text_expr ANDAND expr - { $$ = ($1 != 0.0 && $3 != 0.0); } - | expr ANDAND text_expr - { $$ = ($1 != 0.0 && $3 != 0.0); } - | text_expr OROR text_expr - { $$ = ($1 != 0.0 || $3 != 0.0); } - | text_expr OROR expr - { $$ = ($1 != 0.0 || $3 != 0.0); } - | expr OROR text_expr - { $$ = ($1 != 0.0 || $3 != 0.0); } - | '!' text_expr - { $$ = ($2 == 0.0); } - ; - - -optional_by: - /* empty */ - { - $$.val = 1.0; - $$.is_multiplicative = 0; - } - | BY expr - { - $$.val = $2; - $$.is_multiplicative = 0; - } - | BY '*' expr - { - $$.val = $3; - $$.is_multiplicative = 1; - } - ; - -element: - object_spec - { - $$.obj = $1->make_object(¤t_position, - ¤t_direction); - if ($$.obj == 0) - YYABORT; - delete $1; - if ($$.obj) - olist.append($$.obj); - else { - $$.x = current_position.x; - $$.y = current_position.y; - } - } - | LABEL ':' optional_separator element - { - $$ = $4; - define_label($1, & $$); - a_delete $1; - } - | LABEL ':' optional_separator position_not_place - { - $$.obj = 0; - $$.x = $4.x; - $$.y = $4.y; - define_label($1, & $$); - a_delete $1; - } - | LABEL ':' optional_separator place - { - $$ = $4; - define_label($1, & $$); - a_delete $1; - } - | '{' - { - $$.x = current_position.x; - $$.y = current_position.y; - $$.dir = current_direction; - } - element_list '}' - { - current_position.x = $2.x; - current_position.y = $2.y; - current_direction = $2.dir; - } - optional_element - { - $$ = $3; - } - | placeless_element - { - $$.obj = 0; - $$.x = current_position.x; - $$.y = current_position.y; - } - ; - -optional_element: - /* empty */ - {} - | element - {} - ; - -object_spec: - BOX - { $$ = new object_spec(BOX_OBJECT); } - | CIRCLE - { $$ = new object_spec(CIRCLE_OBJECT); } - | ELLIPSE - { $$ = new object_spec(ELLIPSE_OBJECT); } - | ARC - { - $$ = new object_spec(ARC_OBJECT); - $$->dir = current_direction; - } - | LINE - { - $$ = new object_spec(LINE_OBJECT); - lookup_variable("lineht", & $$->segment_height); - lookup_variable("linewid", & $$->segment_width); - $$->dir = current_direction; - } - | ARROW - { - $$ = new object_spec(ARROW_OBJECT); - lookup_variable("lineht", & $$->segment_height); - lookup_variable("linewid", & $$->segment_width); - $$->dir = current_direction; - } - | MOVE - { - $$ = new object_spec(MOVE_OBJECT); - lookup_variable("moveht", & $$->segment_height); - lookup_variable("movewid", & $$->segment_width); - $$->dir = current_direction; - } - | SPLINE - { - $$ = new object_spec(SPLINE_OBJECT); - lookup_variable("lineht", & $$->segment_height); - lookup_variable("linewid", & $$->segment_width); - $$->dir = current_direction; - } - | text %prec TEXT - { - $$ = new object_spec(TEXT_OBJECT); - $$->text = new text_item($1.str, $1.filename, $1.lineno); - } - | PLOT expr - { - $$ = new object_spec(TEXT_OBJECT); - $$->text = new text_item(format_number(0, $2), 0, -1); - } - | PLOT expr text - { - $$ = new object_spec(TEXT_OBJECT); - $$->text = new text_item(format_number($3.str, $2), - $3.filename, $3.lineno); - a_delete $3.str; - } - | '[' - { - saved_state *p = new saved_state; - $$ = p; - p->x = current_position.x; - p->y = current_position.y; - p->dir = current_direction; - p->tbl = current_table; - p->prev = current_saved_state; - current_position.x = 0.0; - current_position.y = 0.0; - current_table = new PTABLE(place); - current_saved_state = p; - olist.append(make_mark_object()); - } - element_list ']' - { - current_position.x = $2->x; - current_position.y = $2->y; - current_direction = $2->dir; - $$ = new object_spec(BLOCK_OBJECT); - olist.wrap_up_block(& $$->oblist); - $$->tbl = current_table; - current_table = $2->tbl; - current_saved_state = $2->prev; - delete $2; - } - | object_spec HEIGHT expr - { - $$ = $1; - $$->height = $3; - $$->flags |= HAS_HEIGHT; - } - | object_spec RADIUS expr - { - $$ = $1; - $$->radius = $3; - $$->flags |= HAS_RADIUS; - } - | object_spec WIDTH expr - { - $$ = $1; - $$->width = $3; - $$->flags |= HAS_WIDTH; - } - | object_spec DIAMETER expr - { - $$ = $1; - $$->radius = $3/2.0; - $$->flags |= HAS_RADIUS; - } - | object_spec expr %prec HEIGHT - { - $$ = $1; - $$->flags |= HAS_SEGMENT; - switch ($$->dir) { - case UP_DIRECTION: - $$->segment_pos.y += $2; - break; - case DOWN_DIRECTION: - $$->segment_pos.y -= $2; - break; - case RIGHT_DIRECTION: - $$->segment_pos.x += $2; - break; - case LEFT_DIRECTION: - $$->segment_pos.x -= $2; - break; - } - } - | object_spec UP - { - $$ = $1; - $$->dir = UP_DIRECTION; - $$->flags |= HAS_SEGMENT; - $$->segment_pos.y += $$->segment_height; - } - | object_spec UP expr - { - $$ = $1; - $$->dir = UP_DIRECTION; - $$->flags |= HAS_SEGMENT; - $$->segment_pos.y += $3; - } - | object_spec DOWN - { - $$ = $1; - $$->dir = DOWN_DIRECTION; - $$->flags |= HAS_SEGMENT; - $$->segment_pos.y -= $$->segment_height; - } - | object_spec DOWN expr - { - $$ = $1; - $$->dir = DOWN_DIRECTION; - $$->flags |= HAS_SEGMENT; - $$->segment_pos.y -= $3; - } - | object_spec RIGHT - { - $$ = $1; - $$->dir = RIGHT_DIRECTION; - $$->flags |= HAS_SEGMENT; - $$->segment_pos.x += $$->segment_width; - } - | object_spec RIGHT expr - { - $$ = $1; - $$->dir = RIGHT_DIRECTION; - $$->flags |= HAS_SEGMENT; - $$->segment_pos.x += $3; - } - | object_spec LEFT - { - $$ = $1; - $$->dir = LEFT_DIRECTION; - $$->flags |= HAS_SEGMENT; - $$->segment_pos.x -= $$->segment_width; - } - | object_spec LEFT expr - { - $$ = $1; - $$->dir = LEFT_DIRECTION; - $$->flags |= HAS_SEGMENT; - $$->segment_pos.x -= $3; - } - | object_spec FROM position - { - $$ = $1; - $$->flags |= HAS_FROM; - $$->from.x = $3.x; - $$->from.y = $3.y; - } - | object_spec TO position - { - $$ = $1; - if ($$->flags & HAS_SEGMENT) - $$->segment_list = new segment($$->segment_pos, - $$->segment_is_absolute, - $$->segment_list); - $$->flags |= HAS_SEGMENT; - $$->segment_pos.x = $3.x; - $$->segment_pos.y = $3.y; - $$->segment_is_absolute = 1; - $$->flags |= HAS_TO; - $$->to.x = $3.x; - $$->to.y = $3.y; - } - | object_spec AT position - { - $$ = $1; - $$->flags |= HAS_AT; - $$->at.x = $3.x; - $$->at.y = $3.y; - if ($$->type != ARC_OBJECT) { - $$->flags |= HAS_FROM; - $$->from.x = $3.x; - $$->from.y = $3.y; - } - } - | object_spec WITH path - { - $$ = $1; - $$->flags |= HAS_WITH; - $$->with = $3; - } - | object_spec WITH position %prec ',' - { - $$ = $1; - $$->flags |= HAS_WITH; - position pos; - pos.x = $3.x; - pos.y = $3.y; - $$->with = new path(pos); - } - | object_spec BY expr_pair - { - $$ = $1; - $$->flags |= HAS_SEGMENT; - $$->segment_pos.x += $3.x; - $$->segment_pos.y += $3.y; - } - | object_spec THEN - { - $$ = $1; - if ($$->flags & HAS_SEGMENT) { - $$->segment_list = new segment($$->segment_pos, - $$->segment_is_absolute, - $$->segment_list); - $$->flags &= ~HAS_SEGMENT; - $$->segment_pos.x = $$->segment_pos.y = 0.0; - $$->segment_is_absolute = 0; - } - } - | object_spec SOLID - { - $$ = $1; // nothing - } - | object_spec DOTTED - { - $$ = $1; - $$->flags |= IS_DOTTED; - lookup_variable("dashwid", & $$->dash_width); - } - | object_spec DOTTED expr - { - $$ = $1; - $$->flags |= IS_DOTTED; - $$->dash_width = $3; - } - | object_spec DASHED - { - $$ = $1; - $$->flags |= IS_DASHED; - lookup_variable("dashwid", & $$->dash_width); - } - | object_spec DASHED expr - { - $$ = $1; - $$->flags |= IS_DASHED; - $$->dash_width = $3; - } - | object_spec FILL - { - $$ = $1; - $$->flags |= IS_DEFAULT_FILLED; - } - | object_spec FILL expr - { - $$ = $1; - $$->flags |= IS_FILLED; - $$->fill = $3; - } - | object_spec SHADED text - { - $$ = $1; - $$->flags |= (IS_SHADED | IS_FILLED); - $$->shaded = new char[strlen($3.str)+1]; - strcpy($$->shaded, $3.str); - } - | object_spec COLORED text - { - $$ = $1; - $$->flags |= (IS_SHADED | IS_OUTLINED | IS_FILLED); - $$->shaded = new char[strlen($3.str)+1]; - strcpy($$->shaded, $3.str); - $$->outlined = new char[strlen($3.str)+1]; - strcpy($$->outlined, $3.str); - } - | object_spec OUTLINED text - { - $$ = $1; - $$->flags |= IS_OUTLINED; - $$->outlined = new char[strlen($3.str)+1]; - strcpy($$->outlined, $3.str); - } - | object_spec CHOP - { - $$ = $1; - // line chop chop means line chop 0 chop 0 - if ($$->flags & IS_DEFAULT_CHOPPED) { - $$->flags |= IS_CHOPPED; - $$->flags &= ~IS_DEFAULT_CHOPPED; - $$->start_chop = $$->end_chop = 0.0; - } - else if ($$->flags & IS_CHOPPED) { - $$->end_chop = 0.0; - } - else { - $$->flags |= IS_DEFAULT_CHOPPED; - } - } - | object_spec CHOP expr - { - $$ = $1; - if ($$->flags & IS_DEFAULT_CHOPPED) { - $$->flags |= IS_CHOPPED; - $$->flags &= ~IS_DEFAULT_CHOPPED; - $$->start_chop = 0.0; - $$->end_chop = $3; - } - else if ($$->flags & IS_CHOPPED) { - $$->end_chop = $3; - } - else { - $$->start_chop = $$->end_chop = $3; - $$->flags |= IS_CHOPPED; - } - } - | object_spec SAME - { - $$ = $1; - $$->flags |= IS_SAME; - } - | object_spec INVISIBLE - { - $$ = $1; - $$->flags |= IS_INVISIBLE; - } - | object_spec LEFT_ARROW_HEAD - { - $$ = $1; - $$->flags |= HAS_LEFT_ARROW_HEAD; - } - | object_spec RIGHT_ARROW_HEAD - { - $$ = $1; - $$->flags |= HAS_RIGHT_ARROW_HEAD; - } - | object_spec DOUBLE_ARROW_HEAD - { - $$ = $1; - $$->flags |= (HAS_LEFT_ARROW_HEAD|HAS_RIGHT_ARROW_HEAD); - } - | object_spec CW - { - $$ = $1; - $$->flags |= IS_CLOCKWISE; - } - | object_spec CCW - { - $$ = $1; - $$->flags &= ~IS_CLOCKWISE; - } - | object_spec text %prec TEXT - { - $$ = $1; - text_item **p; - for (p = & $$->text; *p; p = &(*p)->next) - ; - *p = new text_item($2.str, $2.filename, $2.lineno); - } - | object_spec LJUST - { - $$ = $1; - if ($$->text) { - text_item *p; - for (p = $$->text; p->next; p = p->next) - ; - p->adj.h = LEFT_ADJUST; - } - } - | object_spec RJUST - { - $$ = $1; - if ($$->text) { - text_item *p; - for (p = $$->text; p->next; p = p->next) - ; - p->adj.h = RIGHT_ADJUST; - } - } - | object_spec ABOVE - { - $$ = $1; - if ($$->text) { - text_item *p; - for (p = $$->text; p->next; p = p->next) - ; - p->adj.v = ABOVE_ADJUST; - } - } - | object_spec BELOW - { - $$ = $1; - if ($$->text) { - text_item *p; - for (p = $$->text; p->next; p = p->next) - ; - p->adj.v = BELOW_ADJUST; - } - } - | object_spec THICKNESS expr - { - $$ = $1; - $$->flags |= HAS_THICKNESS; - $$->thickness = $3; - } - | object_spec ALIGNED - { - $$ = $1; - $$->flags |= IS_ALIGNED; - } - ; - -text: - TEXT - { $$ = $1; } - | SPRINTF '(' TEXT sprintf_args ')' - { - $$.filename = $3.filename; - $$.lineno = $3.lineno; - $$.str = do_sprintf($3.str, $4.v, $4.nv); - a_delete $4.v; - a_delete $3.str; - } - ; - -sprintf_args: - /* empty */ - { - $$.v = 0; - $$.nv = 0; - $$.maxv = 0; - } - | sprintf_args ',' expr - { - $$ = $1; - if ($$.nv >= $$.maxv) { - if ($$.nv == 0) { - $$.v = new double[4]; - $$.maxv = 4; - } - else { - double *oldv = $$.v; - $$.maxv *= 2; -#if 0 - $$.v = new double[$$.maxv]; - memcpy($$.v, oldv, $$.nv*sizeof(double)); -#else - // workaround for bug in Compaq C++ V6.5-033 - // for Compaq Tru64 UNIX V5.1A (Rev. 1885) - double *foo = new double[$$.maxv]; - memcpy(foo, oldv, $$.nv*sizeof(double)); - $$.v = foo; -#endif - a_delete oldv; - } - } - $$.v[$$.nv] = $3; - $$.nv += 1; - } - ; - -position: - position_not_place - { $$ = $1; } - | place - { - position pos = $1; - $$.x = pos.x; - $$.y = pos.y; - } - | '(' place ')' - { - position pos = $2; - $$.x = pos.x; - $$.y = pos.y; - } - ; - -position_not_place: - expr_pair - { $$ = $1; } - | position '+' expr_pair - { - $$.x = $1.x + $3.x; - $$.y = $1.y + $3.y; - } - | '(' position '+' expr_pair ')' - { - $$.x = $2.x + $4.x; - $$.y = $2.y + $4.y; - } - | position '-' expr_pair - { - $$.x = $1.x - $3.x; - $$.y = $1.y - $3.y; - } - | '(' position '-' expr_pair ')' - { - $$.x = $2.x - $4.x; - $$.y = $2.y - $4.y; - } - | '(' position ',' position ')' - { - $$.x = $2.x; - $$.y = $4.y; - } - | expr between position AND position - { - $$.x = (1.0 - $1)*$3.x + $1*$5.x; - $$.y = (1.0 - $1)*$3.y + $1*$5.y; - } - | '(' expr between position AND position ')' - { - $$.x = (1.0 - $2)*$4.x + $2*$6.x; - $$.y = (1.0 - $2)*$4.y + $2*$6.y; - } - | expr '<' position ',' position '>' - { - $$.x = (1.0 - $1)*$3.x + $1*$5.x; - $$.y = (1.0 - $1)*$3.y + $1*$5.y; - } - | '(' expr '<' position ',' position '>' ')' - { - $$.x = (1.0 - $2)*$4.x + $2*$6.x; - $$.y = (1.0 - $2)*$4.y + $2*$6.y; - } - ; - -between: - BETWEEN - | OF THE WAY BETWEEN - ; - -expr_pair: - expr ',' expr - { - $$.x = $1; - $$.y = $3; - } - | '(' expr_pair ')' - { $$ = $2; } - ; - -place: - /* line at A left == line (at A) left */ - label %prec CHOP - { $$ = $1; } - | label corner - { - path pth($2); - if (!pth.follow($1, & $$)) - YYABORT; - } - | corner label - { - path pth($1); - if (!pth.follow($2, & $$)) - YYABORT; - } - | corner OF label - { - path pth($1); - if (!pth.follow($3, & $$)) - YYABORT; - } - | HERE - { - $$.x = current_position.x; - $$.y = current_position.y; - $$.obj = 0; - } - ; - -label: - LABEL - { - place *p = lookup_label($1); - if (!p) { - lex_error("there is no place `%1'", $1); - YYABORT; - } - $$ = *p; - a_delete $1; - } - | nth_primitive - { $$.obj = $1; } - | label '.' LABEL - { - path pth($3); - if (!pth.follow($1, & $$)) - YYABORT; - } - ; - -ordinal: - ORDINAL - { $$ = $1; } - | '`' any_expr TH - { - // XXX Check for overflow (and non-integers?). - $$ = (int)$2; - } - ; - -optional_ordinal_last: - LAST - { $$ = 1; } - | ordinal LAST - { $$ = $1; } - ; - -nth_primitive: - ordinal object_type - { - int count = 0; - object *p; - for (p = olist.head; p != 0; p = p->next) - if (p->type() == $2 && ++count == $1) { - $$ = p; - break; - } - if (p == 0) { - lex_error("there is no %1%2 %3", $1, ordinal_postfix($1), - object_type_name($2)); - YYABORT; - } - } - | optional_ordinal_last object_type - { - int count = 0; - object *p; - for (p = olist.tail; p != 0; p = p->prev) - if (p->type() == $2 && ++count == $1) { - $$ = p; - break; - } - if (p == 0) { - lex_error("there is no %1%2 last %3", $1, - ordinal_postfix($1), object_type_name($2)); - YYABORT; - } - } - ; - -object_type: - BOX - { $$ = BOX_OBJECT; } - | CIRCLE - { $$ = CIRCLE_OBJECT; } - | ELLIPSE - { $$ = ELLIPSE_OBJECT; } - | ARC - { $$ = ARC_OBJECT; } - | LINE - { $$ = LINE_OBJECT; } - | ARROW - { $$ = ARROW_OBJECT; } - | SPLINE - { $$ = SPLINE_OBJECT; } - | '[' ']' - { $$ = BLOCK_OBJECT; } - | TEXT - { $$ = TEXT_OBJECT; } - ; - -label_path: - '.' LABEL - { $$ = new path($2); } - | label_path '.' LABEL - { - $$ = $1; - $$->append($3); - } - ; - -relative_path: - corner %prec CHOP - { $$ = new path($1); } - /* give this a lower precedence than LEFT and RIGHT so that - [A: box] with .A left == [A: box] with (.A left) */ - | label_path %prec TEXT - { $$ = $1; } - | label_path corner - { - $$ = $1; - $$->append($2); - } - ; - -path: - relative_path - { $$ = $1; } - | '(' relative_path ',' relative_path ')' - { - $$ = $2; - $$->set_ypath($4); - } - /* The rest of these rules are a compatibility sop. */ - | ORDINAL LAST object_type relative_path - { - lex_warning("`%1%2 last %3' in `with' argument ignored", - $1, ordinal_postfix($1), object_type_name($3)); - $$ = $4; - } - | LAST object_type relative_path - { - lex_warning("`last %1' in `with' argument ignored", - object_type_name($2)); - $$ = $3; - } - | ORDINAL object_type relative_path - { - lex_warning("`%1%2 %3' in `with' argument ignored", - $1, ordinal_postfix($1), object_type_name($2)); - $$ = $3; - } - | LABEL relative_path - { - lex_warning("initial `%1' in `with' argument ignored", $1); - a_delete $1; - $$ = $2; - } - ; - -corner: - DOT_N - { $$ = &object::north; } - | DOT_E - { $$ = &object::east; } - | DOT_W - { $$ = &object::west; } - | DOT_S - { $$ = &object::south; } - | DOT_NE - { $$ = &object::north_east; } - | DOT_SE - { $$ = &object:: south_east; } - | DOT_NW - { $$ = &object::north_west; } - | DOT_SW - { $$ = &object::south_west; } - | DOT_C - { $$ = &object::center; } - | DOT_START - { $$ = &object::start; } - | DOT_END - { $$ = &object::end; } - | TOP - { $$ = &object::north; } - | BOTTOM - { $$ = &object::south; } - | LEFT - { $$ = &object::west; } - | RIGHT - { $$ = &object::east; } - | UPPER LEFT - { $$ = &object::north_west; } - | LOWER LEFT - { $$ = &object::south_west; } - | UPPER RIGHT - { $$ = &object::north_east; } - | LOWER RIGHT - { $$ = &object::south_east; } - | LEFT_CORNER - { $$ = &object::west; } - | RIGHT_CORNER - { $$ = &object::east; } - | UPPER LEFT_CORNER - { $$ = &object::north_west; } - | LOWER LEFT_CORNER - { $$ = &object::south_west; } - | UPPER RIGHT_CORNER - { $$ = &object::north_east; } - | LOWER RIGHT_CORNER - { $$ = &object::south_east; } - | NORTH - { $$ = &object::north; } - | SOUTH - { $$ = &object::south; } - | EAST - { $$ = &object::east; } - | WEST - { $$ = &object::west; } - | CENTER - { $$ = &object::center; } - | START - { $$ = &object::start; } - | END - { $$ = &object::end; } - ; - -expr: - VARIABLE - { - if (!lookup_variable($1, & $$)) { - lex_error("there is no variable `%1'", $1); - YYABORT; - } - a_delete $1; - } - | NUMBER - { $$ = $1; } - | place DOT_X - { - if ($1.obj != 0) - $$ = $1.obj->origin().x; - else - $$ = $1.x; - } - | place DOT_Y - { - if ($1.obj != 0) - $$ = $1.obj->origin().y; - else - $$ = $1.y; - } - | place DOT_HT - { - if ($1.obj != 0) - $$ = $1.obj->height(); - else - $$ = 0.0; - } - | place DOT_WID - { - if ($1.obj != 0) - $$ = $1.obj->width(); - else - $$ = 0.0; - } - | place DOT_RAD - { - if ($1.obj != 0) - $$ = $1.obj->radius(); - else - $$ = 0.0; - } - | expr '+' expr - { $$ = $1 + $3; } - | expr '-' expr - { $$ = $1 - $3; } - | expr '*' expr - { $$ = $1 * $3; } - | expr '/' expr - { - if ($3 == 0.0) { - lex_error("division by zero"); - YYABORT; - } - $$ = $1/$3; - } - | expr '%' expr - { - if ($3 == 0.0) { - lex_error("modulus by zero"); - YYABORT; - } - $$ = fmod($1, $3); - } - | expr '^' expr - { - errno = 0; - $$ = pow($1, $3); - if (errno == EDOM) { - lex_error("arguments to `^' operator out of domain"); - YYABORT; - } - if (errno == ERANGE) { - lex_error("result of `^' operator out of range"); - YYABORT; - } - } - | '-' expr %prec '!' - { $$ = -$2; } - | '(' any_expr ')' - { $$ = $2; } - | SIN '(' any_expr ')' - { - errno = 0; - $$ = sin($3); - if (errno == ERANGE) { - lex_error("sin result out of range"); - YYABORT; - } - } - | COS '(' any_expr ')' - { - errno = 0; - $$ = cos($3); - if (errno == ERANGE) { - lex_error("cos result out of range"); - YYABORT; - } - } - | ATAN2 '(' any_expr ',' any_expr ')' - { - errno = 0; - $$ = atan2($3, $5); - if (errno == EDOM) { - lex_error("atan2 argument out of domain"); - YYABORT; - } - if (errno == ERANGE) { - lex_error("atan2 result out of range"); - YYABORT; - } - } - | LOG '(' any_expr ')' - { - errno = 0; - $$ = log10($3); - if (errno == ERANGE) { - lex_error("log result out of range"); - YYABORT; - } - } - | EXP '(' any_expr ')' - { - errno = 0; - $$ = pow(10.0, $3); - if (errno == ERANGE) { - lex_error("exp result out of range"); - YYABORT; - } - } - | SQRT '(' any_expr ')' - { - errno = 0; - $$ = sqrt($3); - if (errno == EDOM) { - lex_error("sqrt argument out of domain"); - YYABORT; - } - } - | K_MAX '(' any_expr ',' any_expr ')' - { $$ = $3 > $5 ? $3 : $5; } - | K_MIN '(' any_expr ',' any_expr ')' - { $$ = $3 < $5 ? $3 : $5; } - | INT '(' any_expr ')' - { $$ = floor($3); } - | RAND '(' any_expr ')' - { $$ = 1.0 + floor(((rand()&0x7fff)/double(0x7fff))*$3); } - | RAND '(' ')' - { - /* return a random number in the range [0,1) */ - /* portable, but not very random */ - $$ = (rand() & 0x7fff) / double(0x8000); - } - | SRAND '(' any_expr ')' - { - $$ = 0; - srand((unsigned int)$3); - } - | expr '<' expr - { $$ = ($1 < $3); } - | expr LESSEQUAL expr - { $$ = ($1 <= $3); } - | expr '>' expr - { $$ = ($1 > $3); } - | expr GREATEREQUAL expr - { $$ = ($1 >= $3); } - | expr EQUALEQUAL expr - { $$ = ($1 == $3); } - | expr NOTEQUAL expr - { $$ = ($1 != $3); } - | expr ANDAND expr - { $$ = ($1 != 0.0 && $3 != 0.0); } - | expr OROR expr - { $$ = ($1 != 0.0 || $3 != 0.0); } - | '!' expr - { $$ = ($2 == 0.0); } - - ; - -%% - -/* bison defines const to be empty unless __STDC__ is defined, which it -isn't under cfront */ - -#ifdef const -#undef const -#endif - -static struct { - const char *name; - double val; - int scaled; // non-zero if val should be multiplied by scale -} defaults_table[] = { - { "arcrad", .25, 1 }, - { "arrowht", .1, 1 }, - { "arrowwid", .05, 1 }, - { "circlerad", .25, 1 }, - { "boxht", .5, 1 }, - { "boxwid", .75, 1 }, - { "boxrad", 0.0, 1 }, - { "dashwid", .05, 1 }, - { "ellipseht", .5, 1 }, - { "ellipsewid", .75, 1 }, - { "moveht", .5, 1 }, - { "movewid", .5, 1 }, - { "lineht", .5, 1 }, - { "linewid", .5, 1 }, - { "textht", 0.0, 1 }, - { "textwid", 0.0, 1 }, - { "scale", 1.0, 0 }, - { "linethick", -1.0, 0 }, // in points - { "fillval", .5, 0 }, - { "arrowhead", 1.0, 0 }, - { "maxpswid", 8.5, 0 }, - { "maxpsht", 11.0, 0 }, -}; - -place *lookup_label(const char *label) -{ - saved_state *state = current_saved_state; - PTABLE(place) *tbl = current_table; - for (;;) { - place *pl = tbl->lookup(label); - if (pl) - return pl; - if (!state) - return 0; - tbl = state->tbl; - state = state->prev; - } -} - -void define_label(const char *label, const place *pl) -{ - place *p = new place[1]; - *p = *pl; - current_table->define(label, p); -} - -int lookup_variable(const char *name, double *val) -{ - place *pl = lookup_label(name); - if (pl) { - *val = pl->x; - return 1; - } - return 0; -} - -void define_variable(const char *name, double val) -{ - place *p = new place[1]; - p->obj = 0; - p->x = val; - p->y = 0.0; - current_table->define(name, p); - if (strcmp(name, "scale") == 0) { - // When the scale changes, reset all scaled pre-defined variables to - // their default values. - for (unsigned int i = 0; - i < sizeof(defaults_table)/sizeof(defaults_table[0]); i++) - if (defaults_table[i].scaled) - define_variable(defaults_table[i].name, val*defaults_table[i].val); - } -} - -// called once only (not once per parse) - -void parse_init() -{ - current_direction = RIGHT_DIRECTION; - current_position.x = 0.0; - current_position.y = 0.0; - // This resets everything to its default value. - reset_all(); -} - -void reset(const char *nm) -{ - for (unsigned int i = 0; - i < sizeof(defaults_table)/sizeof(defaults_table[0]); i++) - if (strcmp(nm, defaults_table[i].name) == 0) { - double val = defaults_table[i].val; - if (defaults_table[i].scaled) { - double scale; - lookup_variable("scale", &scale); - val *= scale; - } - define_variable(defaults_table[i].name, val); - return; - } - lex_error("`%1' is not a predefined variable", nm); -} - -void reset_all() -{ - // We only have to explicitly reset the pre-defined variables that - // aren't scaled because `scale' is not scaled, and changing the - // value of `scale' will reset all the pre-defined variables that - // are scaled. - for (unsigned int i = 0; - i < sizeof(defaults_table)/sizeof(defaults_table[0]); i++) - if (!defaults_table[i].scaled) - define_variable(defaults_table[i].name, defaults_table[i].val); -} - -// called after each parse - -void parse_cleanup() -{ - while (current_saved_state != 0) { - delete current_table; - current_table = current_saved_state->tbl; - saved_state *tem = current_saved_state; - current_saved_state = current_saved_state->prev; - delete tem; - } - assert(current_table == &top_table); - PTABLE_ITERATOR(place) iter(current_table); - const char *key; - place *pl; - while (iter.next(&key, &pl)) - if (pl->obj != 0) { - position pos = pl->obj->origin(); - pl->obj = 0; - pl->x = pos.x; - pl->y = pos.y; - } - while (olist.head != 0) { - object *tem = olist.head; - olist.head = olist.head->next; - delete tem; - } - olist.tail = 0; - current_direction = RIGHT_DIRECTION; - current_position.x = 0.0; - current_position.y = 0.0; -} - -const char *ordinal_postfix(int n) -{ - if (n < 10 || n > 20) - switch (n % 10) { - case 1: - return "st"; - case 2: - return "nd"; - case 3: - return "rd"; - } - return "th"; -} - -const char *object_type_name(object_type type) -{ - switch (type) { - case BOX_OBJECT: - return "box"; - case CIRCLE_OBJECT: - return "circle"; - case ELLIPSE_OBJECT: - return "ellipse"; - case ARC_OBJECT: - return "arc"; - case SPLINE_OBJECT: - return "spline"; - case LINE_OBJECT: - return "line"; - case ARROW_OBJECT: - return "arrow"; - case MOVE_OBJECT: - return "move"; - case TEXT_OBJECT: - return "\"\""; - case BLOCK_OBJECT: - return "[]"; - case OTHER_OBJECT: - case MARK_OBJECT: - default: - break; - } - return "object"; -} - -static char sprintf_buf[1024]; - -char *format_number(const char *form, double n) -{ - if (form == 0) - form = "%g"; - return do_sprintf(form, &n, 1); -} - -char *do_sprintf(const char *form, const double *v, int nv) -{ - string result; - int i = 0; - string one_format; - while (*form) { - if (*form == '%') { - one_format += *form++; - for (; *form != '\0' && strchr("#-+ 0123456789.", *form) != 0; form++) - one_format += *form; - if (*form == '\0' || strchr("eEfgG%", *form) == 0) { - lex_error("bad sprintf format"); - result += one_format; - result += form; - break; - } - if (*form == '%') { - one_format += *form++; - one_format += '\0'; - snprintf(sprintf_buf, sizeof(sprintf_buf), - "%s", one_format.contents()); - } - else { - if (i >= nv) { - lex_error("too few arguments to snprintf"); - result += one_format; - result += form; - break; - } - one_format += *form++; - one_format += '\0'; - snprintf(sprintf_buf, sizeof(sprintf_buf), - one_format.contents(), v[i++]); - } - one_format.clear(); - result += sprintf_buf; - } - else - result += *form++; - } - result += '\0'; - return strsave(result.contents()); -} diff --git a/contrib/groff/src/preproc/pic/position.h b/contrib/groff/src/preproc/pic/position.h deleted file mode 100644 index c62e3e7bd0da..000000000000 --- a/contrib/groff/src/preproc/pic/position.h +++ /dev/null @@ -1,47 +0,0 @@ -// -*- 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -struct place; -struct position { - double x; - double y; - position(double, double ); - position(); - position(const place &); - position &operator+=(const position &); - position &operator-=(const position &); - position &operator*=(double); - position &operator/=(double); -}; - -position operator-(const position &); -position operator+(const position &, const position &); -position operator-(const position &, const position &); -position operator/(const position &, double); -position operator*(const position &, double); -// dot product -double operator*(const position &, const position &); -int operator==(const position &, const position &); -int operator!=(const position &, const position &); - -double hypot(const position &a); - -typedef position distance; - diff --git a/contrib/groff/src/preproc/pic/tex.cpp b/contrib/groff/src/preproc/pic/tex.cpp deleted file mode 100644 index f997b868d687..000000000000 --- a/contrib/groff/src/preproc/pic/tex.cpp +++ /dev/null @@ -1,459 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2003 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "pic.h" - -#ifdef TEX_SUPPORT - -#include "common.h" - -class tex_output : public common_output { -public: - tex_output(); - ~tex_output(); - void start_picture(double, const position &ll, const position &ur); - void finish_picture(); - void text(const position &, text_piece *, int, double); - void line(const position &, const position *, int n, - const line_type &); - void polygon(const position *, int n, - const line_type &, double); - void spline(const position &, const position *, int n, - const line_type &); - void arc(const position &, const position &, const position &, - const line_type &); - void circle(const position &, double rad, const line_type &, double); - void ellipse(const position &, const distance &, const line_type &, double); - void command(const char *, const char *, int); - void set_color(char *, char *); - void reset_color(); - char *get_last_filled(); - char *get_outline_color(); - int supports_filled_polygons(); -private: - position upper_left; - double height; - double width; - double scale; - double pen_size; - - void point(const position &); - void dot(const position &, const line_type &); - void solid_arc(const position ¢, double rad, double start_angle, - double end_angle, const line_type <); - position transform(const position &); -protected: - virtual void set_pen_size(double ps); -}; - -// convert inches to milliinches - -inline int milliinches(double x) -{ - return int(x*1000.0 + .5); -} - -inline position tex_output::transform(const position &pos) -{ - return position((pos.x - upper_left.x)/scale, - (upper_left.y - pos.y)/scale); -} - -output *make_tex_output() -{ - return new tex_output; -} - -tex_output::tex_output() -{ -} - -tex_output::~tex_output() -{ -} - -const int DEFAULT_PEN_SIZE = 8; - -void tex_output::set_pen_size(double ps) -{ - if (ps < 0.0) - ps = -1.0; - if (ps != pen_size) { - pen_size = ps; - printf(" \\special{pn %d}%%\n", - ps < 0.0 ? DEFAULT_PEN_SIZE : int(ps*(1000.0/72.0) + .5)); - } -} - -void tex_output::start_picture(double sc, const position &ll, - const position &ur) -{ - upper_left.x = ll.x; - upper_left.y = ur.y; - scale = compute_scale(sc, ll, ur); - height = (ur.y - ll.y)/scale; - width = (ur.x - ll.x)/scale; - /* The point of \vskip 0pt is to ensure that the vtop gets - a height of 0 rather than the height of the hbox; this - might be non-zero if text from text attributes lies outside pic's - idea of the bounding box of the picture. */ - /* \newbox and \newdimen are defined with \outer in plain.tex and can't - be used directly in an \if clause. */ - printf("\\expandafter\\ifx\\csname %s\\endcsname\\relax\n" - " \\csname newbox\\expandafter\\endcsname\\csname %s\\endcsname\n" - "\\fi\n" - "\\ifx\\graphtemp\\undefined\n" - " \\csname newdimen\\endcsname\\graphtemp\n" - "\\fi\n" - "\\expandafter\\setbox\\csname %s\\endcsname\n" - " =\\vtop{\\vskip 0pt\\hbox{%%\n", - graphname, graphname, graphname); - pen_size = -2.0; -} - -void tex_output::finish_picture() -{ - printf(" \\hbox{\\vrule depth%.3fin width0pt height 0pt}%%\n" - " \\kern %.3fin\n" - " }%%\n" - "}%%\n", - height, width); -} - -void tex_output::text(const position ¢er, text_piece *v, int n, double) -{ - position c = transform(center); - for (int i = 0; i < n; i++) - if (v[i].text != 0 && *v[i].text != '\0') { - int j = 2*i - n + 1; - if (v[i].adj.v == ABOVE_ADJUST) - j--; - else if (v[i].adj.v == BELOW_ADJUST) - j++; - if (j == 0) { - printf(" \\graphtemp=.5ex\n" - " \\advance\\graphtemp by %.3fin\n", c.y); - } - else { - printf(" \\graphtemp=\\baselineskip\n" - " \\multiply\\graphtemp by %d\n" - " \\divide\\graphtemp by 2\n" - " \\advance\\graphtemp by .5ex\n" - " \\advance\\graphtemp by %.3fin\n", - j, c.y); - } - printf(" \\rlap{\\kern %.3fin\\lower\\graphtemp", c.x); - fputs("\\hbox to 0pt{", stdout); - if (v[i].adj.h != LEFT_ADJUST) - fputs("\\hss ", stdout); - fputs(v[i].text, stdout); - if (v[i].adj.h != RIGHT_ADJUST) - fputs("\\hss", stdout); - fputs("}}%\n", stdout); - } -} - -void tex_output::point(const position &pos) -{ - position p = transform(pos); - printf(" \\special{pa %d %d}%%\n", milliinches(p.x), milliinches(p.y)); -} - -void tex_output::line(const position &start, const position *v, int n, - const line_type <) -{ - set_pen_size(lt.thickness); - point(start); - for (int i = 0; i < n; i++) - point(v[i]); - fputs(" \\special{", stdout); - switch(lt.type) { - case line_type::invisible: - fputs("ip", stdout); - break; - case line_type::solid: - fputs("fp", stdout); - break; - case line_type::dotted: - printf("dt %.3f", lt.dash_width/scale); - break; - case line_type::dashed: - printf("da %.3f", lt.dash_width/scale); - break; - } - fputs("}%\n", stdout); -} - -void tex_output::polygon(const position *v, int n, - const line_type <, double fill) -{ - if (fill >= 0.0) { - if (fill > 1.0) - fill = 1.0; - printf(" \\special{sh %.3f}%%\n", fill); - } - line(v[n-1], v, n, lt); -} - -void tex_output::spline(const position &start, const position *v, int n, - const line_type <) -{ - if (lt.type == line_type::invisible) - return; - set_pen_size(lt.thickness); - point(start); - for (int i = 0; i < n; i++) - point(v[i]); - fputs(" \\special{sp", stdout); - switch(lt.type) { - case line_type::solid: - break; - case line_type::dotted: - printf(" %.3f", -lt.dash_width/scale); - break; - case line_type::dashed: - printf(" %.3f", lt.dash_width/scale); - break; - case line_type::invisible: - assert(0); - } - fputs("}%\n", stdout); -} - -void tex_output::solid_arc(const position ¢, double rad, - double start_angle, double end_angle, - const line_type <) -{ - set_pen_size(lt.thickness); - position c = transform(cent); - printf(" \\special{ar %d %d %d %d %f %f}%%\n", - milliinches(c.x), - milliinches(c.y), - milliinches(rad/scale), - milliinches(rad/scale), - -end_angle, - (-end_angle > -start_angle) ? (double)M_PI * 2 - start_angle - : -start_angle); -} - -void tex_output::arc(const position &start, const position ¢, - const position &end, const line_type <) -{ - switch (lt.type) { - case line_type::invisible: - break; - case line_type::dashed: - dashed_arc(start, cent, end, lt); - break; - case line_type::dotted: - dotted_arc(start, cent, end, lt); - break; - case line_type::solid: - { - position c; - if (!compute_arc_center(start, cent, end, &c)) { - line(start, &end, 1, lt); - break; - } - solid_arc(c, - hypot(cent - start), - atan2(start.y - c.y, start.x - c.x), - atan2(end.y - c.y, end.x - c.x), - lt); - break; - } - } -} - -void tex_output::circle(const position ¢, double rad, - const line_type <, double fill) -{ - if (fill >= 0.0 && lt.type != line_type::solid) { - if (fill > 1.0) - fill = 1.0; - line_type ilt; - ilt.type = line_type::invisible; - ellipse(cent, position(rad*2.0, rad*2.0), ilt, fill); - } - switch (lt.type) { - case line_type::dashed: - dashed_circle(cent, rad, lt); - break; - case line_type::invisible: - break; - case line_type::solid: - ellipse(cent, position(rad*2.0,rad*2.0), lt, fill); - break; - case line_type::dotted: - dotted_circle(cent, rad, lt); - break; - default: - assert(0); - } -} - -void tex_output::ellipse(const position ¢, const distance &dim, - const line_type <, double fill) -{ - if (lt.type == line_type::invisible) { - if (fill < 0.0) - return; - } - else - set_pen_size(lt.thickness); - if (fill >= 0.0) { - if (fill > 1.0) - fill = 1.0; - printf(" \\special{sh %.3f}%%\n", fill); - } - position c = transform(cent); - switch (lt.type) { - case line_type::solid: - case line_type::invisible: - printf(" \\special{%s %d %d %d %d 0 6.28319}%%\n", - (lt.type == line_type::invisible ? "ia" : "ar"), - milliinches(c.x), - milliinches(c.y), - milliinches(dim.x/(2.0*scale)), - milliinches(dim.y/(2.0*scale))); - break; - case line_type::dashed: - dashed_ellipse(cent, dim / scale, lt); - break; - case line_type::dotted: - dotted_ellipse(cent, dim / scale, lt); - break; - default: - assert(0); - } -} - -void tex_output::command(const char *s, const char *, int) -{ - fputs(s, stdout); - putchar('%'); // avoid unwanted spaces - putchar('\n'); -} - -int tex_output::supports_filled_polygons() -{ - return 1; -} - -void tex_output::dot(const position &pos, const line_type <) -{ - if (zero_length_line_flag) { - line_type slt = lt; - slt.type = line_type::solid; - line(pos, &pos, 1, slt); - } - else { - int dot_rad = int(lt.thickness*(1000.0/(72.0*2)) + .5); - if (dot_rad == 0) - dot_rad = 1; - position p = transform(pos); - printf(" \\special{sh 1}%%\n" - " \\special{ia %d %d %d %d 0 6.28319}%%\n", - milliinches(p.x), milliinches(p.y), dot_rad, dot_rad); - } -} - -void tex_output::set_color(char *, char *) -{ - /* not implemented yet */ -} - -void tex_output::reset_color() -{ - /* not implemented yet */ -} - -char *tex_output::get_last_filled() -{ - /* not implemented yet */ - return NULL; -} - -char *tex_output::get_outline_color() -{ - /* not implemented yet */ - return NULL; -} - -class tpic_output : public tex_output { -public: - tpic_output(); - void command(const char *, const char *, int); -private: - void set_pen_size(double ps); - int default_pen_size; - int prev_default_pen_size; -}; - -tpic_output::tpic_output() -: default_pen_size(DEFAULT_PEN_SIZE), prev_default_pen_size(DEFAULT_PEN_SIZE) -{ -} - -void tpic_output::command(const char *s, const char *filename, int lineno) -{ - assert(s[0] == '.'); - if (s[1] == 'p' && s[2] == 's' && (s[3] == '\0' || !csalpha(s[3]))) { - const char *p = s + 3; - while (csspace(*p)) - p++; - if (*p == '\0') { - int temp = default_pen_size; - default_pen_size = prev_default_pen_size; - prev_default_pen_size = temp; - } - else { - char *ptr; - int temp = (int)strtol(p, &ptr, 10); - if (temp == 0 && ptr == p) - error_with_file_and_line(filename, lineno, - "argument to `.ps' not an integer"); - else if (temp < 0) - error_with_file_and_line(filename, lineno, - "negative pen size"); - else { - prev_default_pen_size = default_pen_size; - default_pen_size = temp; - } - } - } - else - printf("\\%s%%\n", s + 1); -} - -void tpic_output::set_pen_size(double ps) -{ - if (ps < 0.0) - printf(" \\special{pn %d}%%\n", default_pen_size); - else - tex_output::set_pen_size(ps); -} - -output *make_tpic_output() -{ - return new tpic_output; -} - -#endif diff --git a/contrib/groff/src/preproc/pic/text.h b/contrib/groff/src/preproc/pic/text.h deleted file mode 100644 index f9d34875075f..000000000000 --- a/contrib/groff/src/preproc/pic/text.h +++ /dev/null @@ -1,28 +0,0 @@ -// -*- C++ -*- - -enum hadjustment { - CENTER_ADJUST, - LEFT_ADJUST, - RIGHT_ADJUST - }; - -enum vadjustment { - NONE_ADJUST, - ABOVE_ADJUST, - BELOW_ADJUST - }; - -struct adjustment { - hadjustment h; - vadjustment v; -}; - -struct text_piece { - char *text; - adjustment adj; - const char *filename; - int lineno; - - text_piece(); - ~text_piece(); -}; diff --git a/contrib/groff/src/preproc/pic/troff.cpp b/contrib/groff/src/preproc/pic/troff.cpp deleted file mode 100644 index 688ca47b9c47..000000000000 --- a/contrib/groff/src/preproc/pic/troff.cpp +++ /dev/null @@ -1,567 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003, 2005 - 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "pic.h" -#include "common.h" - - -const double RELATIVE_THICKNESS = -1.0; -const double BAD_THICKNESS = -2.0; - -class simple_output : public common_output { - virtual void simple_line(const position &, const position &) = 0; - virtual void simple_spline(const position &, const position *, int n) = 0; - virtual void simple_arc(const position &, const position &, - const position &) = 0; - virtual void simple_circle(int, const position &, double rad) = 0; - virtual void simple_ellipse(int, const position &, const distance &) = 0; - virtual void simple_polygon(int, const position *, int) = 0; - virtual void line_thickness(double) = 0; - virtual void set_fill(double) = 0; - virtual void set_color(char *, char *) = 0; - virtual void reset_color() = 0; - virtual char *get_last_filled() = 0; - void dot(const position &, const line_type &) = 0; -public: - void start_picture(double sc, const position &ll, const position &ur) = 0; - void finish_picture() = 0; - void text(const position &, text_piece *, int, double) = 0; - void line(const position &, const position *, int n, - const line_type &); - void polygon(const position *, int n, - const line_type &, double); - void spline(const position &, const position *, int n, - const line_type &); - void arc(const position &, const position &, const position &, - const line_type &); - void circle(const position &, double rad, const line_type &, double); - void ellipse(const position &, const distance &, const line_type &, double); - int supports_filled_polygons(); -}; - -int simple_output::supports_filled_polygons() -{ - return driver_extension_flag != 0; -} - -void simple_output::arc(const position &start, const position ¢, - const position &end, const line_type <) -{ - switch (lt.type) { - case line_type::solid: - line_thickness(lt.thickness); - simple_arc(start, cent, end); - break; - case line_type::invisible: - break; - case line_type::dashed: - dashed_arc(start, cent, end, lt); - break; - case line_type::dotted: - dotted_arc(start, cent, end, lt); - break; - } -} - -void simple_output::line(const position &start, const position *v, int n, - const line_type <) -{ - position pos = start; - line_thickness(lt.thickness); - for (int i = 0; i < n; i++) { - switch (lt.type) { - case line_type::solid: - simple_line(pos, v[i]); - break; - case line_type::dotted: - { - distance vec(v[i] - pos); - double dist = hypot(vec); - int ndots = int(dist/lt.dash_width + .5); - if (ndots == 0) - dot(pos, lt); - else { - vec /= double(ndots); - for (int j = 0; j <= ndots; j++) - dot(pos + vec*j, lt); - } - } - break; - case line_type::dashed: - { - distance vec(v[i] - pos); - double dist = hypot(vec); - if (dist <= lt.dash_width*2.0) - simple_line(pos, v[i]); - else { - int ndashes = int((dist - lt.dash_width)/(lt.dash_width*2.0) + .5); - distance dash_vec = vec*(lt.dash_width/dist); - double dash_gap = (dist - lt.dash_width)/ndashes; - distance dash_gap_vec = vec*(dash_gap/dist); - for (int j = 0; j <= ndashes; j++) { - position s(pos + dash_gap_vec*j); - simple_line(s, s + dash_vec); - } - } - } - break; - case line_type::invisible: - break; - default: - assert(0); - } - pos = v[i]; - } -} - -void simple_output::spline(const position &start, const position *v, int n, - const line_type <) -{ - line_thickness(lt.thickness); - simple_spline(start, v, n); -} - -void simple_output::polygon(const position *v, int n, - const line_type <, double fill) -{ - if (driver_extension_flag && ((fill >= 0.0) || (get_last_filled() != 0))) { - if (get_last_filled() == 0) - set_fill(fill); - simple_polygon(1, v, n); - } - if (lt.type == line_type::solid && driver_extension_flag) { - line_thickness(lt.thickness); - simple_polygon(0, v, n); - } - else if (lt.type != line_type::invisible) { - line_thickness(lt.thickness); - line(v[n - 1], v, n, lt); - } -} - -void simple_output::circle(const position ¢, double rad, - const line_type <, double fill) -{ - if (driver_extension_flag && ((fill >= 0.0) || (get_last_filled() != 0))) { - if (get_last_filled() == 0) - set_fill(fill); - simple_circle(1, cent, rad); - } - line_thickness(lt.thickness); - switch (lt.type) { - case line_type::invisible: - break; - case line_type::dashed: - dashed_circle(cent, rad, lt); - break; - case line_type::dotted: - dotted_circle(cent, rad, lt); - break; - case line_type::solid: - simple_circle(0, cent, rad); - break; - default: - assert(0); - } -} - -void simple_output::ellipse(const position ¢, const distance &dim, - const line_type <, double fill) -{ - if (driver_extension_flag && ((fill >= 0.0) || (get_last_filled() != 0))) { - if (get_last_filled() == 0) - set_fill(fill); - simple_ellipse(1, cent, dim); - } - if (lt.type != line_type::invisible) - line_thickness(lt.thickness); - switch (lt.type) { - case line_type::invisible: - break; - case line_type::dotted: - dotted_ellipse(cent, dim, lt); - break; - case line_type::dashed: - dashed_ellipse(cent, dim, lt); - break; - case line_type::solid: - simple_ellipse(0, cent, dim); - break; - default: - assert(0); - } -} - -class troff_output : public simple_output { - const char *last_filename; - position upper_left; - double height; - double scale; - double last_line_thickness; - double last_fill; - char *last_filled; // color - char *last_outlined; // color -public: - troff_output(); - ~troff_output(); - void start_picture(double, const position &ll, const position &ur); - void finish_picture(); - void text(const position &, text_piece *, int, double); - void dot(const position &, const line_type &); - void command(const char *, const char *, int); - void set_location(const char *, int); - void simple_line(const position &, const position &); - void simple_spline(const position &, const position *, int n); - void simple_arc(const position &, const position &, const position &); - void simple_circle(int, const position &, double rad); - void simple_ellipse(int, const position &, const distance &); - void simple_polygon(int, const position *, int); - void line_thickness(double p); - void set_fill(double); - void set_color(char *, char *); - void reset_color(); - char *get_last_filled(); - char *get_outline_color(); - position transform(const position &); -}; - -output *make_troff_output() -{ - return new troff_output; -} - -troff_output::troff_output() -: last_filename(0), last_line_thickness(BAD_THICKNESS), - last_fill(-1.0), last_filled(0), last_outlined(0) -{ -} - -troff_output::~troff_output() -{ -} - -inline position troff_output::transform(const position &pos) -{ - return position((pos.x - upper_left.x)/scale, - (upper_left.y - pos.y)/scale); -} - -#define FILL_REG "00" - -// If this register > 0, then pic will generate \X'ps: ...' commands -// if the aligned attribute is used. -#define GROPS_REG "0p" - -// If this register is defined, geqn won't produce `\x's. -#define EQN_NO_EXTRA_SPACE_REG "0x" - -void troff_output::start_picture(double sc, - const position &ll, const position &ur) -{ - upper_left.x = ll.x; - upper_left.y = ur.y; - scale = compute_scale(sc, ll, ur); - height = (ur.y - ll.y)/scale; - double width = (ur.x - ll.x)/scale; - printf(".PS %.3fi %.3fi", height, width); - if (args) - printf(" %s\n", args); - else - putchar('\n'); - printf(".\\\" %g %g %g %g\n", ll.x, ll.y, ur.x, ur.y); - printf(".\\\" %.3fi %.3fi %.3fi %.3fi\n", 0.0, height, width, 0.0); - printf(".nr " FILL_REG " \\n(.u\n.nf\n"); - printf(".nr " EQN_NO_EXTRA_SPACE_REG " 1\n"); - // This guarantees that if the picture is used in a diversion it will - // have the right width. - printf("\\h'%.3fi'\n.sp -1\n", width); -} - -void troff_output::finish_picture() -{ - line_thickness(BAD_THICKNESS); - last_fill = -1.0; // force it to be reset for each picture - reset_color(); - if (!flyback_flag) - printf(".sp %.3fi+1\n", height); - printf(".if \\n(" FILL_REG " .fi\n"); - printf(".br\n"); - printf(".nr " EQN_NO_EXTRA_SPACE_REG " 0\n"); - // this is a little gross - set_location(current_filename, current_lineno); - fputs(flyback_flag ? ".PF\n" : ".PE\n", stdout); -} - -void troff_output::command(const char *s, - const char *filename, int lineno) -{ - if (filename != 0) - set_location(filename, lineno); - fputs(s, stdout); - putchar('\n'); -} - -void troff_output::simple_circle(int filled, const position ¢, double rad) -{ - position c = transform(cent); - printf("\\h'%.3fi'" - "\\v'%.3fi'" - "\\D'%c %.3fi'" - "\n.sp -1\n", - c.x - rad/scale, - c.y, - (filled ? 'C' : 'c'), - rad*2.0/scale); -} - -void troff_output::simple_ellipse(int filled, const position ¢, - const distance &dim) -{ - position c = transform(cent); - printf("\\h'%.3fi'" - "\\v'%.3fi'" - "\\D'%c %.3fi %.3fi'" - "\n.sp -1\n", - c.x - dim.x/(2.0*scale), - c.y, - (filled ? 'E' : 'e'), - dim.x/scale, dim.y/scale); -} - -void troff_output::simple_arc(const position &start, const distance ¢, - const distance &end) -{ - position s = transform(start); - position c = transform(cent); - distance cv = c - s; - distance ev = transform(end) - c; - printf("\\h'%.3fi'" - "\\v'%.3fi'" - "\\D'a %.3fi %.3fi %.3fi %.3fi'" - "\n.sp -1\n", - s.x, s.y, cv.x, cv.y, ev.x, ev.y); -} - -void troff_output::simple_line(const position &start, const position &end) -{ - position s = transform(start); - distance ev = transform(end) - s; - printf("\\h'%.3fi'" - "\\v'%.3fi'" - "\\D'l %.3fi %.3fi'" - "\n.sp -1\n", - s.x, s.y, ev.x, ev.y); -} - -void troff_output::simple_spline(const position &start, - const position *v, int n) -{ - position pos = transform(start); - printf("\\h'%.3fi'" - "\\v'%.3fi'", - pos.x, pos.y); - fputs("\\D'~ ", stdout); - for (int i = 0; i < n; i++) { - position temp = transform(v[i]); - distance d = temp - pos; - pos = temp; - if (i != 0) - putchar(' '); - printf("%.3fi %.3fi", d.x, d.y); - } - printf("'\n.sp -1\n"); -} - -// a solid polygon - -void troff_output::simple_polygon(int filled, const position *v, int n) -{ - position pos = transform(v[0]); - printf("\\h'%.3fi'" - "\\v'%.3fi'", - pos.x, pos.y); - printf("\\D'%c ", (filled ? 'P' : 'p')); - for (int i = 1; i < n; i++) { - position temp = transform(v[i]); - distance d = temp - pos; - pos = temp; - if (i != 1) - putchar(' '); - printf("%.3fi %.3fi", d.x, d.y); - } - printf("'\n.sp -1\n"); -} - -const double TEXT_AXIS = 0.22; // in ems - -static const char *choose_delimiter(const char *text) -{ - if (strchr(text, '\'') == 0) - return "'"; - else - return "\\(ts"; -} - -void troff_output::text(const position ¢er, text_piece *v, int n, - double ang) -{ - line_thickness(BAD_THICKNESS); // the text might use lines (eg in equations) - int rotate_flag = 0; - if (driver_extension_flag && ang != 0.0) { - rotate_flag = 1; - position c = transform(center); - printf(".if \\n(" GROPS_REG " \\{\\\n" - "\\h'%.3fi'" - "\\v'%.3fi'" - "\\X'ps: exec gsave currentpoint 2 copy translate %.4f rotate neg exch neg exch translate'" - "\n.sp -1\n" - ".\\}\n", - c.x, c.y, -ang*180.0/M_PI); - } - for (int i = 0; i < n; i++) - if (v[i].text != 0 && *v[i].text != '\0') { - position c = transform(center); - if (v[i].filename != 0) - set_location(v[i].filename, v[i].lineno); - printf("\\h'%.3fi", c.x); - const char *delim = choose_delimiter(v[i].text); - if (v[i].adj.h == RIGHT_ADJUST) - printf("-\\w%s%s%su", delim, v[i].text, delim); - else if (v[i].adj.h != LEFT_ADJUST) - printf("-(\\w%s%s%su/2u)", delim, v[i].text, delim); - putchar('\''); - printf("\\v'%.3fi-(%dv/2u)+%dv+%.2fm", - c.y, - n - 1, - i, - TEXT_AXIS); - if (v[i].adj.v == ABOVE_ADJUST) - printf("-.5v"); - else if (v[i].adj.v == BELOW_ADJUST) - printf("+.5v"); - putchar('\''); - fputs(v[i].text, stdout); - fputs("\n.sp -1\n", stdout); - } - if (rotate_flag) - printf(".if '\\*(.T'ps' \\{\\\n" - "\\X'ps: exec grestore'\n.sp -1\n" - ".\\}\n"); -} - -void troff_output::line_thickness(double p) -{ - if (p < 0.0) - p = RELATIVE_THICKNESS; - if (driver_extension_flag && p != last_line_thickness) { - printf("\\D't %.3fp'\\h'%.3fp'\n.sp -1\n", p, -p); - last_line_thickness = p; - } -} - -void troff_output::set_fill(double f) -{ - if (driver_extension_flag && f != last_fill) { - // \D'Fg ...' emits a node only in compatibility mode, - // thus we add a dummy node - printf("\\&\\D'Fg %.3f'\n.sp -1\n", 1.0 - f); - last_fill = f; - } - if (last_filled) { - free(last_filled); - last_filled = 0; - printf(".fcolor\n"); - } -} - -void troff_output::set_color(char *color_fill, char *color_outlined) -{ - if (driver_extension_flag) { - if (last_filled || last_outlined) { - reset_color(); - } - // .gcolor and .fcolor emit a node in compatibility mode only, - // but that won't work anyway - if (color_fill) { - printf(".fcolor %s\n", color_fill); - last_filled = strsave(color_fill); - } - if (color_outlined) { - printf(".gcolor %s\n", color_outlined); - last_outlined = strsave(color_outlined); - } - } -} - -void troff_output::reset_color() -{ - if (driver_extension_flag) { - if (last_filled) { - printf(".fcolor\n"); - a_delete last_filled; - last_filled = 0; - } - if (last_outlined) { - printf(".gcolor\n"); - a_delete last_outlined; - last_outlined = 0; - } - } -} - -char *troff_output::get_last_filled() -{ - return last_filled; -} - -char *troff_output::get_outline_color() -{ - return last_outlined; -} - -const double DOT_AXIS = .044; - -void troff_output::dot(const position ¢, const line_type <) -{ - if (driver_extension_flag) { - line_thickness(lt.thickness); - simple_line(cent, cent); - } - else { - position c = transform(cent); - printf("\\h'%.3fi-(\\w'.'u/2u)'" - "\\v'%.3fi+%.2fm'" - ".\n.sp -1\n", - c.x, - c.y, - DOT_AXIS); - } -} - -void troff_output::set_location(const char *s, int n) -{ - if (last_filename != 0 && strcmp(s, last_filename) == 0) - printf(".lf %d\n", n); - else { - printf(".lf %d %s\n", n, s); - last_filename = s; - } -} diff --git a/contrib/groff/src/preproc/refer/Makefile.sub b/contrib/groff/src/preproc/refer/Makefile.sub deleted file mode 100644 index 2e22a3a77909..000000000000 --- a/contrib/groff/src/preproc/refer/Makefile.sub +++ /dev/null @@ -1,23 +0,0 @@ -PROG=refer$(EXEEXT) -MAN1=refer.n -XLIBS=$(LIBBIB) $(LIBGROFF) -MLIB=$(LIBM) -OBJS=\ - command.$(OBJEXT) \ - label.$(OBJEXT) \ - ref.$(OBJEXT) \ - refer.$(OBJEXT) \ - token.$(OBJEXT) -CCSRCS=\ - $(srcdir)/command.cpp \ - $(srcdir)/ref.cpp \ - $(srcdir)/refer.cpp \ - $(srcdir)/token.cpp -HDRS=\ - $(srcdir)/refer.h \ - $(srcdir)/token.h \ - $(srcdir)/command.h \ - $(srcdir)/ref.h -GRAM=$(srcdir)/label.y -YTABC=label.cpp -NAMEPREFIX=$(g) diff --git a/contrib/groff/src/preproc/refer/TODO b/contrib/groff/src/preproc/refer/TODO deleted file mode 100644 index 5bbd9bff1e8c..000000000000 --- a/contrib/groff/src/preproc/refer/TODO +++ /dev/null @@ -1,124 +0,0 @@ -inline references - -Some sort of macro/subroutine that can cover several references. - -move-punctuation should ignore multiple punctuation characters. - -Make the index files machine independent. - -Allow search keys to be negated (with !) to indicate that the -reference should not contain the key. Ignore negated keys during -indexed searching. - -Provide an option with lkbib and lookbib that prints the location -(filename, position) of each reference. Need to map filename_id's -back to filenames. - -Rename join-authors to join-fields. Have a separate label-join-fields -command used by @ and #. - -Have some sort of quantifier: eg $.n#A means execute `$.n' for each -instance of an A field, setting $ to that field, and then join the -results using the join-authors command. - -no-text-in-bracket command which says not to allow post_text and -pre_text when the [] flags has been given. Useful for superscripted -footnotes. - -Make it possible to translate - to \(en in page ranges. - -Trim eign a bit. - -In indexed searching discard all numeric keys except dates. - -Allow `\ ' to separate article from first word. - -%also - -Option automatically to supply [] flags in every reference. - -See if we can avoid requiring a comma before jr. and so on -in find_last_name(). - -Cache sortified authors in authors string during tentative evaluation of -label specification. - -Possibly don't allow * and % expressions in the first part of ?:, | or -& expressions. - -Handle better the case where <> occurs inside functions and in the -first operand of ~. Or perhaps implement <> using some magic character -in the string. - -Should special treatment be given to lines beginning with . in -references? (Unix refer seems to treat them like `%'). - -Add global flag to control whether all files should be stat-ed after -loading, and whether they should be stat-ed before each search. -Perhaps make this dependent on the number of files there are. - -Option to truncate keys to truncate_len in linear searching. - -Allow multiple -f options in indxbib. - -In indxbib, possibly store common words rather than common words -filename. In this case store only words that are actually present in -the file. - -Perhaps we should put out an obnoxious copyright message when lookbib -starts up. - -Provide an option that writes a file containing just the references -actually used. Useful if you want to distribute a document. - -Have a magic token such that -%A -will print as though it were -%A -but sort as though it were -%A -Do we need this if we can specify author alternatives for sorting? -No, provided we have separate alternatives for @. - -In consider_authors when last names are ambiguous we might be able to -use just the first name and not Jr. bit. Or we might be able to -abbreviate the author. - -It ought to be possible to specify an alternative field to sort on -instead of date. (ie if there's a field giving the type of document -- -these references should sort after any years) - -Provide a way to execute a command using a command-line option. - -Option to set the label-spec as a command-line option (-L). - -Command to to specify which fields can occur multiple times: -multiple AE - -Command to specify how various fields sort: -aort-as-name A -sort-as-date D -sort-as-title T -sort-as-other O - -Command to specify which fields are author fields: -# if we don't have A use field Q -author-fields AQ - -Commands to set properties of tokens. -sortify-token \(ae ae -uppercase-token \[ae] \[AE] - -Command to set the names of months: -months january february march april may ... - -Perhaps provide some sort of macro capability: -# perhaps a macro capability -defmacro foo -annotation-field $1 -endef - -Command to control strings used in capitalization -capitalize-start \s+2 -capitalize-end \s-2 -(perhaps make these arguments to the capitalize command.) diff --git a/contrib/groff/src/preproc/refer/command.cpp b/contrib/groff/src/preproc/refer/command.cpp deleted file mode 100644 index 441f9534e154..000000000000 --- a/contrib/groff/src/preproc/refer/command.cpp +++ /dev/null @@ -1,809 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002, 2004 - 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "refer.h" -#include "refid.h" -#include "search.h" -#include "command.h" - -cset cs_field_name = csalpha; - -class input_item { - input_item *next; - char *filename; - int first_lineno; - string buffer; - const char *ptr; - const char *end; -public: - input_item(string &, const char *, int = 1); - ~input_item(); - int get_char(); - int peek_char(); - void skip_char(); - int get_location(const char **, int *); - - friend class input_stack; -}; - -input_item::input_item(string &s, const char *fn, int ln) -: filename(strsave(fn)), first_lineno(ln) -{ - buffer.move(s); - ptr = buffer.contents(); - end = ptr + buffer.length(); -} - -input_item::~input_item() -{ - a_delete filename; -} - -inline int input_item::peek_char() -{ - if (ptr >= end) - return EOF; - else - return (unsigned char)*ptr; -} - -inline int input_item::get_char() -{ - if (ptr >= end) - return EOF; - else - return (unsigned char)*ptr++; -} - -inline void input_item::skip_char() -{ - ptr++; -} - -int input_item::get_location(const char **filenamep, int *linenop) -{ - *filenamep = filename; - if (ptr == buffer.contents()) - *linenop = first_lineno; - else { - int ln = first_lineno; - const char *e = ptr - 1; - for (const char *p = buffer.contents(); p < e; p++) - if (*p == '\n') - ln++; - *linenop = ln; - } - return 1; -} - -class input_stack { - static input_item *top; -public: - static void init(); - static int get_char(); - static int peek_char(); - static void skip_char() { top->skip_char(); } - static void push_file(const char *); - static void push_string(string &, const char *, int); - static void error(const char *format, - const errarg &arg1 = empty_errarg, - const errarg &arg2 = empty_errarg, - const errarg &arg3 = empty_errarg); -}; - -input_item *input_stack::top = 0; - -void input_stack::init() -{ - while (top) { - input_item *tem = top; - top = top->next; - delete tem; - } -} - -int input_stack::get_char() -{ - while (top) { - int c = top->get_char(); - if (c >= 0) - return c; - input_item *tem = top; - top = top->next; - delete tem; - } - return -1; -} - -int input_stack::peek_char() -{ - while (top) { - int c = top->peek_char(); - if (c >= 0) - return c; - input_item *tem = top; - top = top->next; - delete tem; - } - return -1; -} - -void input_stack::push_file(const char *fn) -{ - FILE *fp; - if (strcmp(fn, "-") == 0) { - fp = stdin; - fn = ""; - } - else { - errno = 0; - fp = fopen(fn, "r"); - if (fp == 0) { - error("can't open `%1': %2", fn, strerror(errno)); - return; - } - } - string buf; - int bol = 1; - int lineno = 1; - for (;;) { - int c = getc(fp); - if (bol && c == '.') { - // replace lines beginning with .R1 or .R2 with a blank line - c = getc(fp); - if (c == 'R') { - c = getc(fp); - if (c == '1' || c == '2') { - int cc = c; - c = getc(fp); - if (compatible_flag || c == ' ' || c == '\n' || c == EOF) { - while (c != '\n' && c != EOF) - c = getc(fp); - } - else { - buf += '.'; - buf += 'R'; - buf += cc; - } - } - else { - buf += '.'; - buf += 'R'; - } - } - else - buf += '.'; - } - if (c == EOF) - break; - if (invalid_input_char(c)) - error_with_file_and_line(fn, lineno, - "invalid input character code %1", int(c)); - else { - buf += c; - if (c == '\n') { - bol = 1; - lineno++; - } - else - bol = 0; - } - } - if (fp != stdin) - fclose(fp); - if (buf.length() > 0 && buf[buf.length() - 1] != '\n') - buf += '\n'; - input_item *it = new input_item(buf, fn); - it->next = top; - top = it; -} - -void input_stack::push_string(string &s, const char *filename, int lineno) -{ - input_item *it = new input_item(s, filename, lineno); - it->next = top; - top = it; -} - -void input_stack::error(const char *format, const errarg &arg1, - const errarg &arg2, const errarg &arg3) -{ - const char *filename; - int lineno; - for (input_item *it = top; it; it = it->next) - if (it->get_location(&filename, &lineno)) { - error_with_file_and_line(filename, lineno, format, arg1, arg2, arg3); - return; - } - ::error(format, arg1, arg2, arg3); -} - -void command_error(const char *format, const errarg &arg1, - const errarg &arg2, const errarg &arg3) -{ - input_stack::error(format, arg1, arg2, arg3); -} - -// # not recognized in "" -// \ is recognized in "" -// # does not conceal newline -// if missing closing quote, word extends to end of line -// no special treatment of \ other than before newline -// \ not recognized after # -// ; allowed as alternative to newline -// ; not recognized in "" -// don't clear word_buffer; just append on -// return -1 for EOF, 0 for newline, 1 for word - -int get_word(string &word_buffer) -{ - int c = input_stack::get_char(); - for (;;) { - if (c == '#') { - do { - c = input_stack::get_char(); - } while (c != '\n' && c != EOF); - break; - } - if (c == '\\' && input_stack::peek_char() == '\n') - input_stack::skip_char(); - else if (c != ' ' && c != '\t') - break; - c = input_stack::get_char(); - } - if (c == EOF) - return -1; - if (c == '\n' || c == ';') - return 0; - if (c == '"') { - for (;;) { - c = input_stack::peek_char(); - if (c == EOF || c == '\n') - break; - input_stack::skip_char(); - if (c == '"') { - int d = input_stack::peek_char(); - if (d == '"') - input_stack::skip_char(); - else - break; - } - else if (c == '\\') { - int d = input_stack::peek_char(); - if (d == '\n') - input_stack::skip_char(); - else - word_buffer += '\\'; - } - else - word_buffer += c; - } - return 1; - } - word_buffer += c; - for (;;) { - c = input_stack::peek_char(); - if (c == ' ' || c == '\t' || c == '\n' || c == '#' || c == ';') - break; - input_stack::skip_char(); - if (c == '\\') { - int d = input_stack::peek_char(); - if (d == '\n') - input_stack::skip_char(); - else - word_buffer += '\\'; - } - else - word_buffer += c; - } - return 1; -} - -union argument { - const char *s; - int n; -}; - -// This is for debugging. - -static void echo_command(int argc, argument *argv) -{ - for (int i = 0; i < argc; i++) - fprintf(stderr, "%s\n", argv[i].s); -} - -static void include_command(int argc, argument *argv) -{ - assert(argc == 1); - input_stack::push_file(argv[0].s); -} - -static void capitalize_command(int argc, argument *argv) -{ - if (argc > 0) - capitalize_fields = argv[0].s; - else - capitalize_fields.clear(); -} - -static void accumulate_command(int, argument *) -{ - accumulate = 1; -} - -static void no_accumulate_command(int, argument *) -{ - accumulate = 0; -} - -static void move_punctuation_command(int, argument *) -{ - move_punctuation = 1; -} - -static void no_move_punctuation_command(int, argument *) -{ - move_punctuation = 0; -} - -static void sort_command(int argc, argument *argv) -{ - if (argc == 0) - sort_fields = "AD"; - else - sort_fields = argv[0].s; - accumulate = 1; -} - -static void no_sort_command(int, argument *) -{ - sort_fields.clear(); -} - -static void articles_command(int argc, argument *argv) -{ - articles.clear(); - int i; - for (i = 0; i < argc; i++) { - articles += argv[i].s; - articles += '\0'; - } - int len = articles.length(); - for (i = 0; i < len; i++) - articles[i] = cmlower(articles[i]); -} - -static void database_command(int argc, argument *argv) -{ - for (int i = 0; i < argc; i++) - database_list.add_file(argv[i].s); -} - -static void default_database_command(int, argument *) -{ - search_default = 1; -} - -static void no_default_database_command(int, argument *) -{ - search_default = 0; -} - -static void bibliography_command(int argc, argument *argv) -{ - const char *saved_filename = current_filename; - int saved_lineno = current_lineno; - int saved_label_in_text = label_in_text; - label_in_text = 0; - if (!accumulate) - fputs(".]<\n", stdout); - for (int i = 0; i < argc; i++) - do_bib(argv[i].s); - if (accumulate) - output_references(); - else - fputs(".]>\n", stdout); - current_filename = saved_filename; - current_lineno = saved_lineno; - label_in_text = saved_label_in_text; -} - -static void annotate_command(int argc, argument *argv) -{ - if (argc > 0) - annotation_field = argv[0].s[0]; - else - annotation_field = 'X'; - if (argc == 2) - annotation_macro = argv[1].s; - else - annotation_macro = "AP"; -} - -static void no_annotate_command(int, argument *) -{ - annotation_macro.clear(); - annotation_field = -1; -} - -static void reverse_command(int, argument *argv) -{ - reverse_fields = argv[0].s; -} - -static void no_reverse_command(int, argument *) -{ - reverse_fields.clear(); -} - -static void abbreviate_command(int argc, argument *argv) -{ - abbreviate_fields = argv[0].s; - period_before_initial = argc > 1 ? argv[1].s : ". "; - period_before_last_name = argc > 2 ? argv[2].s : ". "; - period_before_other = argc > 3 ? argv[3].s : ". "; - period_before_hyphen = argc > 4 ? argv[4].s : "."; -} - -static void no_abbreviate_command(int, argument *) -{ - abbreviate_fields.clear(); -} - -string search_ignore_fields; - -static void search_ignore_command(int argc, argument *argv) -{ - if (argc > 0) - search_ignore_fields = argv[0].s; - else - search_ignore_fields = "XYZ"; - search_ignore_fields += '\0'; - linear_ignore_fields = search_ignore_fields.contents(); -} - -static void no_search_ignore_command(int, argument *) -{ - linear_ignore_fields = ""; -} - -static void search_truncate_command(int argc, argument *argv) -{ - if (argc > 0) - linear_truncate_len = argv[0].n; - else - linear_truncate_len = 6; -} - -static void no_search_truncate_command(int, argument *) -{ - linear_truncate_len = -1; -} - -static void discard_command(int argc, argument *argv) -{ - if (argc == 0) - discard_fields = "XYZ"; - else - discard_fields = argv[0].s; - accumulate = 1; -} - -static void no_discard_command(int, argument *) -{ - discard_fields.clear(); -} - -static void label_command(int, argument *argv) -{ - set_label_spec(argv[0].s); -} - -static void abbreviate_label_ranges_command(int argc, argument *argv) -{ - abbreviate_label_ranges = 1; - label_range_indicator = argc > 0 ? argv[0].s : "-"; -} - -static void no_abbreviate_label_ranges_command(int, argument *) -{ - abbreviate_label_ranges = 0; -} - -static void label_in_reference_command(int, argument *) -{ - label_in_reference = 1; -} - -static void no_label_in_reference_command(int, argument *) -{ - label_in_reference = 0; -} - -static void label_in_text_command(int, argument *) -{ - label_in_text = 1; -} - -static void no_label_in_text_command(int, argument *) -{ - label_in_text = 0; -} - -static void sort_adjacent_labels_command(int, argument *) -{ - sort_adjacent_labels = 1; -} - -static void no_sort_adjacent_labels_command(int, argument *) -{ - sort_adjacent_labels = 0; -} - -static void date_as_label_command(int argc, argument *argv) -{ - if (set_date_label_spec(argc > 0 ? argv[0].s : "D%a*")) - date_as_label = 1; -} - -static void no_date_as_label_command(int, argument *) -{ - date_as_label = 0; -} - -static void short_label_command(int, argument *argv) -{ - if (set_short_label_spec(argv[0].s)) - short_label_flag = 1; -} - -static void no_short_label_command(int, argument *) -{ - short_label_flag = 0; -} - -static void compatible_command(int, argument *) -{ - compatible_flag = 1; -} - -static void no_compatible_command(int, argument *) -{ - compatible_flag = 0; -} - -static void join_authors_command(int argc, argument *argv) -{ - join_authors_exactly_two = argv[0].s; - join_authors_default = argc > 1 ? argv[1].s : argv[0].s; - join_authors_last_two = argc == 3 ? argv[2].s : argv[0].s; -} - -static void bracket_label_command(int, argument *argv) -{ - pre_label = argv[0].s; - post_label = argv[1].s; - sep_label = argv[2].s; -} - -static void separate_label_second_parts_command(int, argument *argv) -{ - separate_label_second_parts = argv[0].s; -} - -static void et_al_command(int argc, argument *argv) -{ - et_al = argv[0].s; - et_al_min_elide = argv[1].n; - if (et_al_min_elide < 1) - et_al_min_elide = 1; - et_al_min_total = argc >= 3 ? argv[2].n : 0; -} - -static void no_et_al_command(int, argument *) -{ - et_al.clear(); - et_al_min_elide = 0; -} - -typedef void (*command_t)(int, argument *); - -/* arg_types is a string describing the numbers and types of arguments. -s means a string, i means an integer, f is a list of fields, F is -a single field, -? means that the previous argument is optional, * means that the -previous argument can occur any number of times. */ - -struct S { - const char *name; - command_t func; - const char *arg_types; -} command_table[] = { - { "include", include_command, "s" }, - { "echo", echo_command, "s*" }, - { "capitalize", capitalize_command, "f?" }, - { "accumulate", accumulate_command, "" }, - { "no-accumulate", no_accumulate_command, "" }, - { "move-punctuation", move_punctuation_command, "" }, - { "no-move-punctuation", no_move_punctuation_command, "" }, - { "sort", sort_command, "s?" }, - { "no-sort", no_sort_command, "" }, - { "articles", articles_command, "s*" }, - { "database", database_command, "ss*" }, - { "default-database", default_database_command, "" }, - { "no-default-database", no_default_database_command, "" }, - { "bibliography", bibliography_command, "ss*" }, - { "annotate", annotate_command, "F?s?" }, - { "no-annotate", no_annotate_command, "" }, - { "reverse", reverse_command, "s" }, - { "no-reverse", no_reverse_command, "" }, - { "abbreviate", abbreviate_command, "ss?s?s?s?" }, - { "no-abbreviate", no_abbreviate_command, "" }, - { "search-ignore", search_ignore_command, "f?" }, - { "no-search-ignore", no_search_ignore_command, "" }, - { "search-truncate", search_truncate_command, "i?" }, - { "no-search-truncate", no_search_truncate_command, "" }, - { "discard", discard_command, "f?" }, - { "no-discard", no_discard_command, "" }, - { "label", label_command, "s" }, - { "abbreviate-label-ranges", abbreviate_label_ranges_command, "s?" }, - { "no-abbreviate-label-ranges", no_abbreviate_label_ranges_command, "" }, - { "label-in-reference", label_in_reference_command, "" }, - { "no-label-in-reference", no_label_in_reference_command, "" }, - { "label-in-text", label_in_text_command, "" }, - { "no-label-in-text", no_label_in_text_command, "" }, - { "sort-adjacent-labels", sort_adjacent_labels_command, "" }, - { "no-sort-adjacent-labels", no_sort_adjacent_labels_command, "" }, - { "date-as-label", date_as_label_command, "s?" }, - { "no-date-as-label", no_date_as_label_command, "" }, - { "short-label", short_label_command, "s" }, - { "no-short-label", no_short_label_command, "" }, - { "compatible", compatible_command, "" }, - { "no-compatible", no_compatible_command, "" }, - { "join-authors", join_authors_command, "sss?" }, - { "bracket-label", bracket_label_command, "sss" }, - { "separate-label-second-parts", separate_label_second_parts_command, "s" }, - { "et-al", et_al_command, "sii?" }, - { "no-et-al", no_et_al_command, "" }, -}; - -static int check_args(const char *types, const char *name, - int argc, argument *argv) -{ - int argno = 0; - while (*types) { - if (argc == 0) { - if (types[1] == '?') - break; - else if (types[1] == '*') { - assert(types[2] == '\0'); - break; - } - else { - input_stack::error("missing argument for command `%1'", name); - return 0; - } - } - switch (*types) { - case 's': - break; - case 'i': - { - char *ptr; - long n = strtol(argv->s, &ptr, 10); - if ((n == 0 && ptr == argv->s) - || *ptr != '\0') { - input_stack::error("argument %1 for command `%2' must be an integer", - argno + 1, name); - return 0; - } - argv->n = (int)n; - break; - } - case 'f': - { - for (const char *ptr = argv->s; *ptr != '\0'; ptr++) - if (!cs_field_name(*ptr)) { - input_stack::error("argument %1 for command `%2' must be a list of fields", - argno + 1, name); - return 0; - } - break; - } - case 'F': - if (argv->s[0] == '\0' || argv->s[1] != '\0' - || !cs_field_name(argv->s[0])) { - input_stack::error("argument %1 for command `%2' must be a field name", - argno + 1, name); - return 0; - } - break; - default: - assert(0); - } - if (types[1] == '?') - types += 2; - else if (types[1] != '*') - types += 1; - --argc; - ++argv; - ++argno; - } - if (argc > 0) { - input_stack::error("too many arguments for command `%1'", name); - return 0; - } - return 1; -} - -static void execute_command(const char *name, int argc, argument *argv) -{ - for (unsigned int i = 0; - i < sizeof(command_table)/sizeof(command_table[0]); i++) - if (strcmp(name, command_table[i].name) == 0) { - if (check_args(command_table[i].arg_types, name, argc, argv)) - (*command_table[i].func)(argc, argv); - return; - } - input_stack::error("unknown command `%1'", name); -} - -static void command_loop() -{ - string command; - for (;;) { - command.clear(); - int res = get_word(command); - if (res != 1) { - if (res == 0) - continue; - break; - } - int argc = 0; - command += '\0'; - while ((res = get_word(command)) == 1) { - argc++; - command += '\0'; - } - argument *argv = new argument[argc]; - const char *ptr = command.contents(); - for (int i = 0; i < argc; i++) - argv[i].s = ptr = strchr(ptr, '\0') + 1; - execute_command(command.contents(), argc, argv); - a_delete argv; - if (res == -1) - break; - } -} - -void process_commands(const char *file) -{ - input_stack::init(); - input_stack::push_file(file); - command_loop(); -} - -void process_commands(string &s, const char *file, int lineno) -{ - input_stack::init(); - input_stack::push_string(s, file, lineno); - command_loop(); -} diff --git a/contrib/groff/src/preproc/refer/command.h b/contrib/groff/src/preproc/refer/command.h deleted file mode 100644 index f0472ac8b6a7..000000000000 --- a/contrib/groff/src/preproc/refer/command.h +++ /dev/null @@ -1,36 +0,0 @@ -// -*- 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -void process_commands(const char *file); -void process_commands(string &s, const char *file, int lineno); - -extern int accumulate; -extern int move_punctuation; -extern int search_default; -extern search_list database_list; -extern int label_in_text; -extern int label_in_reference; -extern int sort_adjacent_labels; -extern string pre_label; -extern string post_label; -extern string sep_label; - -extern void do_bib(const char *); -extern void output_references(); diff --git a/contrib/groff/src/preproc/refer/label.y b/contrib/groff/src/preproc/refer/label.y deleted file mode 100644 index d76f95ef3c33..000000000000 --- a/contrib/groff/src/preproc/refer/label.y +++ /dev/null @@ -1,1193 +0,0 @@ -/* -*- C++ -*- - Copyright (C) 1989, 1990, 1991, 1992, 2000, 2004 - 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -%{ - -#include "refer.h" -#include "refid.h" -#include "ref.h" -#include "token.h" - -int yylex(); -void yyerror(const char *); -int yyparse(); - -static const char *format_serial(char c, int n); - -struct label_info { - int start; - int length; - int count; - int total; - label_info(const string &); -}; - -label_info *lookup_label(const string &label); - -struct expression { - enum { - // Does the tentative label depend on the reference? - CONTAINS_VARIABLE = 01, - CONTAINS_STAR = 02, - CONTAINS_FORMAT = 04, - CONTAINS_AT = 010 - }; - virtual ~expression() { } - virtual void evaluate(int, const reference &, string &, - substring_position &) = 0; - virtual unsigned analyze() { return 0; } -}; - -class at_expr : public expression { -public: - at_expr() { } - void evaluate(int, const reference &, string &, substring_position &); - unsigned analyze() { return CONTAINS_VARIABLE|CONTAINS_AT; } -}; - -class format_expr : public expression { - char type; - int width; - int first_number; -public: - format_expr(char c, int w = 0, int f = 1) - : type(c), width(w), first_number(f) { } - void evaluate(int, const reference &, string &, substring_position &); - unsigned analyze() { return CONTAINS_FORMAT; } -}; - -class field_expr : public expression { - int number; - char name; -public: - field_expr(char nm, int num) : number(num), name(nm) { } - void evaluate(int, const reference &, string &, substring_position &); - unsigned analyze() { return CONTAINS_VARIABLE; } -}; - -class literal_expr : public expression { - string s; -public: - literal_expr(const char *ptr, int len) : s(ptr, len) { } - void evaluate(int, const reference &, string &, substring_position &); -}; - -class unary_expr : public expression { -protected: - expression *expr; -public: - unary_expr(expression *e) : expr(e) { } - ~unary_expr() { delete expr; } - void evaluate(int, const reference &, string &, substring_position &) = 0; - unsigned analyze() { return expr ? expr->analyze() : 0; } -}; - -// This caches the analysis of an expression. - -class analyzed_expr : public unary_expr { - unsigned flags; -public: - analyzed_expr(expression *); - void evaluate(int, const reference &, string &, substring_position &); - unsigned analyze() { return flags; } -}; - -class star_expr : public unary_expr { -public: - star_expr(expression *e) : unary_expr(e) { } - void evaluate(int, const reference &, string &, substring_position &); - unsigned analyze() { - return ((expr ? (expr->analyze() & ~CONTAINS_VARIABLE) : 0) - | CONTAINS_STAR); - } -}; - -typedef void map_func(const char *, const char *, string &); - -class map_expr : public unary_expr { - map_func *func; -public: - map_expr(expression *e, map_func *f) : unary_expr(e), func(f) { } - void evaluate(int, const reference &, string &, substring_position &); -}; - -typedef const char *extractor_func(const char *, const char *, const char **); - -class extractor_expr : public unary_expr { - int part; - extractor_func *func; -public: - enum { BEFORE = +1, MATCH = 0, AFTER = -1 }; - extractor_expr(expression *e, extractor_func *f, int pt) - : unary_expr(e), part(pt), func(f) { } - void evaluate(int, const reference &, string &, substring_position &); -}; - -class truncate_expr : public unary_expr { - int n; -public: - truncate_expr(expression *e, int i) : unary_expr(e), n(i) { } - void evaluate(int, const reference &, string &, substring_position &); -}; - -class separator_expr : public unary_expr { -public: - separator_expr(expression *e) : unary_expr(e) { } - void evaluate(int, const reference &, string &, substring_position &); -}; - -class binary_expr : public expression { -protected: - expression *expr1; - expression *expr2; -public: - binary_expr(expression *e1, expression *e2) : expr1(e1), expr2(e2) { } - ~binary_expr() { delete expr1; delete expr2; } - void evaluate(int, const reference &, string &, substring_position &) = 0; - unsigned analyze() { - return (expr1 ? expr1->analyze() : 0) | (expr2 ? expr2->analyze() : 0); - } -}; - -class alternative_expr : public binary_expr { -public: - alternative_expr(expression *e1, expression *e2) : binary_expr(e1, e2) { } - void evaluate(int, const reference &, string &, substring_position &); -}; - -class list_expr : public binary_expr { -public: - list_expr(expression *e1, expression *e2) : binary_expr(e1, e2) { } - void evaluate(int, const reference &, string &, substring_position &); -}; - -class substitute_expr : public binary_expr { -public: - substitute_expr(expression *e1, expression *e2) : binary_expr(e1, e2) { } - void evaluate(int, const reference &, string &, substring_position &); -}; - -class ternary_expr : public expression { -protected: - expression *expr1; - expression *expr2; - expression *expr3; -public: - ternary_expr(expression *e1, expression *e2, expression *e3) - : expr1(e1), expr2(e2), expr3(e3) { } - ~ternary_expr() { delete expr1; delete expr2; delete expr3; } - void evaluate(int, const reference &, string &, substring_position &) = 0; - unsigned analyze() { - return ((expr1 ? expr1->analyze() : 0) - | (expr2 ? expr2->analyze() : 0) - | (expr3 ? expr3->analyze() : 0)); - } -}; - -class conditional_expr : public ternary_expr { -public: - conditional_expr(expression *e1, expression *e2, expression *e3) - : ternary_expr(e1, e2, e3) { } - void evaluate(int, const reference &, string &, substring_position &); -}; - -static expression *parsed_label = 0; -static expression *parsed_date_label = 0; -static expression *parsed_short_label = 0; - -static expression *parse_result; - -string literals; - -%} - -%union { - int num; - expression *expr; - struct { int ndigits; int val; } dig; - struct { int start; int len; } str; -} - -/* uppercase or lowercase letter */ -%token TOKEN_LETTER -/* literal characters */ -%token TOKEN_LITERAL -/* digit */ -%token TOKEN_DIGIT - -%type conditional -%type alternative -%type list -%type string -%type substitute -%type optional_conditional -%type number -%type digits -%type optional_number -%type flag - -%% - -expr: - optional_conditional - { parse_result = ($1 ? new analyzed_expr($1) : 0); } - ; - -conditional: - alternative - { $$ = $1; } - | alternative '?' optional_conditional ':' conditional - { $$ = new conditional_expr($1, $3, $5); } - ; - -optional_conditional: - /* empty */ - { $$ = 0; } - | conditional - { $$ = $1; } - ; - -alternative: - list - { $$ = $1; } - | alternative '|' list - { $$ = new alternative_expr($1, $3); } - | alternative '&' list - { $$ = new conditional_expr($1, $3, 0); } - ; - -list: - substitute - { $$ = $1; } - | list substitute - { $$ = new list_expr($1, $2); } - ; - -substitute: - string - { $$ = $1; } - | substitute '~' string - { $$ = new substitute_expr($1, $3); } - ; - -string: - '@' - { $$ = new at_expr; } - | TOKEN_LITERAL - { - $$ = new literal_expr(literals.contents() + $1.start, - $1.len); - } - | TOKEN_LETTER - { $$ = new field_expr($1, 0); } - | TOKEN_LETTER number - { $$ = new field_expr($1, $2 - 1); } - | '%' TOKEN_LETTER - { - switch ($2) { - case 'I': - case 'i': - case 'A': - case 'a': - $$ = new format_expr($2); - break; - default: - command_error("unrecognized format `%1'", char($2)); - $$ = new format_expr('a'); - break; - } - } - - | '%' digits - { - $$ = new format_expr('0', $2.ndigits, $2.val); - } - | string '.' flag TOKEN_LETTER optional_number - { - switch ($4) { - case 'l': - $$ = new map_expr($1, lowercase); - break; - case 'u': - $$ = new map_expr($1, uppercase); - break; - case 'c': - $$ = new map_expr($1, capitalize); - break; - case 'r': - $$ = new map_expr($1, reverse_name); - break; - case 'a': - $$ = new map_expr($1, abbreviate_name); - break; - case 'y': - $$ = new extractor_expr($1, find_year, $3); - break; - case 'n': - $$ = new extractor_expr($1, find_last_name, $3); - break; - default: - $$ = $1; - command_error("unknown function `%1'", char($4)); - break; - } - } - - | string '+' number - { $$ = new truncate_expr($1, $3); } - | string '-' number - { $$ = new truncate_expr($1, -$3); } - | string '*' - { $$ = new star_expr($1); } - | '(' optional_conditional ')' - { $$ = $2; } - | '<' optional_conditional '>' - { $$ = new separator_expr($2); } - ; - -optional_number: - /* empty */ - { $$ = -1; } - | number - { $$ = $1; } - ; - -number: - TOKEN_DIGIT - { $$ = $1; } - | number TOKEN_DIGIT - { $$ = $1*10 + $2; } - ; - -digits: - TOKEN_DIGIT - { $$.ndigits = 1; $$.val = $1; } - | digits TOKEN_DIGIT - { $$.ndigits = $1.ndigits + 1; $$.val = $1.val*10 + $2; } - ; - - -flag: - /* empty */ - { $$ = 0; } - | '+' - { $$ = 1; } - | '-' - { $$ = -1; } - ; - -%% - -/* bison defines const to be empty unless __STDC__ is defined, which it -isn't under cfront */ - -#ifdef const -#undef const -#endif - -const char *spec_ptr; -const char *spec_end; -const char *spec_cur; - -static char uppercase_array[] = { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', -}; - -static char lowercase_array[] = { - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', - 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', - 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', - 'y', 'z', -}; - -int yylex() -{ - while (spec_ptr < spec_end && csspace(*spec_ptr)) - spec_ptr++; - spec_cur = spec_ptr; - if (spec_ptr >= spec_end) - return 0; - unsigned char c = *spec_ptr++; - if (csalpha(c)) { - yylval.num = c; - return TOKEN_LETTER; - } - if (csdigit(c)) { - yylval.num = c - '0'; - return TOKEN_DIGIT; - } - if (c == '\'') { - yylval.str.start = literals.length(); - for (; spec_ptr < spec_end; spec_ptr++) { - if (*spec_ptr == '\'') { - if (++spec_ptr < spec_end && *spec_ptr == '\'') - literals += '\''; - else { - yylval.str.len = literals.length() - yylval.str.start; - return TOKEN_LITERAL; - } - } - else - literals += *spec_ptr; - } - yylval.str.len = literals.length() - yylval.str.start; - return TOKEN_LITERAL; - } - return c; -} - -int set_label_spec(const char *label_spec) -{ - spec_cur = spec_ptr = label_spec; - spec_end = strchr(label_spec, '\0'); - literals.clear(); - if (yyparse()) - return 0; - delete parsed_label; - parsed_label = parse_result; - return 1; -} - -int set_date_label_spec(const char *label_spec) -{ - spec_cur = spec_ptr = label_spec; - spec_end = strchr(label_spec, '\0'); - literals.clear(); - if (yyparse()) - return 0; - delete parsed_date_label; - parsed_date_label = parse_result; - return 1; -} - -int set_short_label_spec(const char *label_spec) -{ - spec_cur = spec_ptr = label_spec; - spec_end = strchr(label_spec, '\0'); - literals.clear(); - if (yyparse()) - return 0; - delete parsed_short_label; - parsed_short_label = parse_result; - return 1; -} - -void yyerror(const char *message) -{ - if (spec_cur < spec_end) - command_error("label specification %1 before `%2'", message, spec_cur); - else - command_error("label specification %1 at end of string", - message, spec_cur); -} - -void at_expr::evaluate(int tentative, const reference &ref, - string &result, substring_position &) -{ - if (tentative) - ref.canonicalize_authors(result); - else { - const char *end, *start = ref.get_authors(&end); - if (start) - result.append(start, end - start); - } -} - -void format_expr::evaluate(int tentative, const reference &ref, - string &result, substring_position &) -{ - if (tentative) - return; - const label_info *lp = ref.get_label_ptr(); - int num = lp == 0 ? ref.get_number() : lp->count; - if (type != '0') - result += format_serial(type, num + 1); - else { - const char *ptr = i_to_a(num + first_number); - int pad = width - strlen(ptr); - while (--pad >= 0) - result += '0'; - result += ptr; - } -} - -static const char *format_serial(char c, int n) -{ - assert(n > 0); - static char buf[128]; // more than enough. - switch (c) { - case 'i': - case 'I': - { - char *p = buf; - // troff uses z and w to represent 10000 and 5000 in Roman - // numerals; I can find no historical basis for this usage - const char *s = c == 'i' ? "zwmdclxvi" : "ZWMDCLXVI"; - if (n >= 40000) - return i_to_a(n); - while (n >= 10000) { - *p++ = s[0]; - n -= 10000; - } - for (int i = 1000; i > 0; i /= 10, s += 2) { - int m = n/i; - n -= m*i; - switch (m) { - case 3: - *p++ = s[2]; - /* falls through */ - case 2: - *p++ = s[2]; - /* falls through */ - case 1: - *p++ = s[2]; - break; - case 4: - *p++ = s[2]; - *p++ = s[1]; - break; - case 8: - *p++ = s[1]; - *p++ = s[2]; - *p++ = s[2]; - *p++ = s[2]; - break; - case 7: - *p++ = s[1]; - *p++ = s[2]; - *p++ = s[2]; - break; - case 6: - *p++ = s[1]; - *p++ = s[2]; - break; - case 5: - *p++ = s[1]; - break; - case 9: - *p++ = s[2]; - *p++ = s[0]; - } - } - *p = 0; - break; - } - case 'a': - case 'A': - { - char *p = buf; - // this is derived from troff/reg.c - while (n > 0) { - int d = n % 26; - if (d == 0) - d = 26; - n -= d; - n /= 26; - *p++ = c == 'a' ? lowercase_array[d - 1] : - uppercase_array[d - 1]; - } - *p-- = 0; - // Reverse it. - char *q = buf; - while (q < p) { - char temp = *q; - *q = *p; - *p = temp; - --p; - ++q; - } - break; - } - default: - assert(0); - } - return buf; -} - -void field_expr::evaluate(int, const reference &ref, - string &result, substring_position &) -{ - const char *end; - const char *start = ref.get_field(name, &end); - if (start) { - start = nth_field(number, start, &end); - if (start) - result.append(start, end - start); - } -} - -void literal_expr::evaluate(int, const reference &, - string &result, substring_position &) -{ - result += s; -} - -analyzed_expr::analyzed_expr(expression *e) -: unary_expr(e), flags(e ? e->analyze() : 0) -{ -} - -void analyzed_expr::evaluate(int tentative, const reference &ref, - string &result, substring_position &pos) -{ - if (expr) - expr->evaluate(tentative, ref, result, pos); -} - -void star_expr::evaluate(int tentative, const reference &ref, - string &result, substring_position &pos) -{ - const label_info *lp = ref.get_label_ptr(); - if (!tentative - && (lp == 0 || lp->total > 1) - && expr) - expr->evaluate(tentative, ref, result, pos); -} - -void separator_expr::evaluate(int tentative, const reference &ref, - string &result, substring_position &pos) -{ - int start_length = result.length(); - int is_first = pos.start < 0; - if (expr) - expr->evaluate(tentative, ref, result, pos); - if (is_first) { - pos.start = start_length; - pos.length = result.length() - start_length; - } -} - -void map_expr::evaluate(int tentative, const reference &ref, - string &result, substring_position &) -{ - if (expr) { - string temp; - substring_position temp_pos; - expr->evaluate(tentative, ref, temp, temp_pos); - (*func)(temp.contents(), temp.contents() + temp.length(), result); - } -} - -void extractor_expr::evaluate(int tentative, const reference &ref, - string &result, substring_position &) -{ - if (expr) { - string temp; - substring_position temp_pos; - expr->evaluate(tentative, ref, temp, temp_pos); - const char *end, *start = (*func)(temp.contents(), - temp.contents() + temp.length(), - &end); - switch (part) { - case BEFORE: - if (start) - result.append(temp.contents(), start - temp.contents()); - else - result += temp; - break; - case MATCH: - if (start) - result.append(start, end - start); - break; - case AFTER: - if (start) - result.append(end, temp.contents() + temp.length() - end); - break; - default: - assert(0); - } - } -} - -static void first_part(int len, const char *ptr, const char *end, - string &result) -{ - for (;;) { - const char *token_start = ptr; - if (!get_token(&ptr, end)) - break; - const token_info *ti = lookup_token(token_start, ptr); - int counts = ti->sortify_non_empty(token_start, ptr); - if (counts && --len < 0) - break; - if (counts || ti->is_accent()) - result.append(token_start, ptr - token_start); - } -} - -static void last_part(int len, const char *ptr, const char *end, - string &result) -{ - const char *start = ptr; - int count = 0; - for (;;) { - const char *token_start = ptr; - if (!get_token(&ptr, end)) - break; - const token_info *ti = lookup_token(token_start, ptr); - if (ti->sortify_non_empty(token_start, ptr)) - count++; - } - ptr = start; - int skip = count - len; - if (skip > 0) { - for (;;) { - const char *token_start = ptr; - if (!get_token(&ptr, end)) - assert(0); - const token_info *ti = lookup_token(token_start, ptr); - if (ti->sortify_non_empty(token_start, ptr) && --skip < 0) { - ptr = token_start; - break; - } - } - } - first_part(len, ptr, end, result); -} - -void truncate_expr::evaluate(int tentative, const reference &ref, - string &result, substring_position &) -{ - if (expr) { - string temp; - substring_position temp_pos; - expr->evaluate(tentative, ref, temp, temp_pos); - const char *start = temp.contents(); - const char *end = start + temp.length(); - if (n > 0) - first_part(n, start, end, result); - else if (n < 0) - last_part(-n, start, end, result); - } -} - -void alternative_expr::evaluate(int tentative, const reference &ref, - string &result, substring_position &pos) -{ - int start_length = result.length(); - if (expr1) - expr1->evaluate(tentative, ref, result, pos); - if (result.length() == start_length && expr2) - expr2->evaluate(tentative, ref, result, pos); -} - -void list_expr::evaluate(int tentative, const reference &ref, - string &result, substring_position &pos) -{ - if (expr1) - expr1->evaluate(tentative, ref, result, pos); - if (expr2) - expr2->evaluate(tentative, ref, result, pos); -} - -void substitute_expr::evaluate(int tentative, const reference &ref, - string &result, substring_position &pos) -{ - int start_length = result.length(); - if (expr1) - expr1->evaluate(tentative, ref, result, pos); - if (result.length() > start_length && result[result.length() - 1] == '-') { - // ought to see if pos covers the - - result.set_length(result.length() - 1); - if (expr2) - expr2->evaluate(tentative, ref, result, pos); - } -} - -void conditional_expr::evaluate(int tentative, const reference &ref, - string &result, substring_position &pos) -{ - string temp; - substring_position temp_pos; - if (expr1) - expr1->evaluate(tentative, ref, temp, temp_pos); - if (temp.length() > 0) { - if (expr2) - expr2->evaluate(tentative, ref, result, pos); - } - else { - if (expr3) - expr3->evaluate(tentative, ref, result, pos); - } -} - -void reference::pre_compute_label() -{ - if (parsed_label != 0 - && (parsed_label->analyze() & expression::CONTAINS_VARIABLE)) { - label.clear(); - substring_position temp_pos; - parsed_label->evaluate(1, *this, label, temp_pos); - label_ptr = lookup_label(label); - } -} - -void reference::compute_label() -{ - label.clear(); - if (parsed_label) - parsed_label->evaluate(0, *this, label, separator_pos); - if (short_label_flag && parsed_short_label) - parsed_short_label->evaluate(0, *this, short_label, short_separator_pos); - if (date_as_label) { - string new_date; - if (parsed_date_label) { - substring_position temp_pos; - parsed_date_label->evaluate(0, *this, new_date, temp_pos); - } - set_date(new_date); - } - if (label_ptr) - label_ptr->count += 1; -} - -void reference::immediate_compute_label() -{ - if (label_ptr) - label_ptr->total = 2; // force use of disambiguator - compute_label(); -} - -int reference::merge_labels(reference **v, int n, label_type type, - string &result) -{ - if (abbreviate_label_ranges) - return merge_labels_by_number(v, n, type, result); - else - return merge_labels_by_parts(v, n, type, result); -} - -int reference::merge_labels_by_number(reference **v, int n, label_type type, - string &result) -{ - if (n <= 1) - return 0; - int num = get_number(); - // Only merge three or more labels. - if (v[0]->get_number() != num + 1 - || v[1]->get_number() != num + 2) - return 0; - int i; - for (i = 2; i < n; i++) - if (v[i]->get_number() != num + i + 1) - break; - result = get_label(type); - result += label_range_indicator; - result += v[i - 1]->get_label(type); - return i; -} - -const substring_position &reference::get_separator_pos(label_type type) const -{ - if (type == SHORT_LABEL && short_label_flag) - return short_separator_pos; - else - return separator_pos; -} - -const string &reference::get_label(label_type type) const -{ - if (type == SHORT_LABEL && short_label_flag) - return short_label; - else - return label; -} - -int reference::merge_labels_by_parts(reference **v, int n, label_type type, - string &result) -{ - if (n <= 0) - return 0; - const string &lb = get_label(type); - const substring_position &sp = get_separator_pos(type); - if (sp.start < 0 - || sp.start != v[0]->get_separator_pos(type).start - || memcmp(lb.contents(), v[0]->get_label(type).contents(), - sp.start) != 0) - return 0; - result = lb; - int i = 0; - do { - result += separate_label_second_parts; - const substring_position &s = v[i]->get_separator_pos(type); - int sep_end_pos = s.start + s.length; - result.append(v[i]->get_label(type).contents() + sep_end_pos, - v[i]->get_label(type).length() - sep_end_pos); - } while (++i < n - && sp.start == v[i]->get_separator_pos(type).start - && memcmp(lb.contents(), v[i]->get_label(type).contents(), - sp.start) == 0); - return i; -} - -string label_pool; - -label_info::label_info(const string &s) -: start(label_pool.length()), length(s.length()), count(0), total(1) -{ - label_pool += s; -} - -static label_info **label_table = 0; -static int label_table_size = 0; -static int label_table_used = 0; - -label_info *lookup_label(const string &label) -{ - if (label_table == 0) { - label_table = new label_info *[17]; - label_table_size = 17; - for (int i = 0; i < 17; i++) - label_table[i] = 0; - } - unsigned h = hash_string(label.contents(), label.length()) % label_table_size; - label_info **ptr; - for (ptr = label_table + h; - *ptr != 0; - (ptr == label_table) - ? (ptr = label_table + label_table_size - 1) - : ptr--) - if ((*ptr)->length == label.length() - && memcmp(label_pool.contents() + (*ptr)->start, label.contents(), - label.length()) == 0) { - (*ptr)->total += 1; - return *ptr; - } - label_info *result = *ptr = new label_info(label); - if (++label_table_used * 2 > label_table_size) { - // Rehash the table. - label_info **old_table = label_table; - int old_size = label_table_size; - label_table_size = next_size(label_table_size); - label_table = new label_info *[label_table_size]; - int i; - for (i = 0; i < label_table_size; i++) - label_table[i] = 0; - for (i = 0; i < old_size; i++) - if (old_table[i]) { - h = hash_string(label_pool.contents() + old_table[i]->start, - old_table[i]->length); - label_info **p; - for (p = label_table + (h % label_table_size); - *p != 0; - (p == label_table) - ? (p = label_table + label_table_size - 1) - : --p) - ; - *p = old_table[i]; - } - a_delete old_table; - } - return result; -} - -void clear_labels() -{ - for (int i = 0; i < label_table_size; i++) { - delete label_table[i]; - label_table[i] = 0; - } - label_table_used = 0; - label_pool.clear(); -} - -static void consider_authors(reference **start, reference **end, int i); - -void compute_labels(reference **v, int n) -{ - if (parsed_label - && (parsed_label->analyze() & expression::CONTAINS_AT) - && sort_fields.length() >= 2 - && sort_fields[0] == 'A' - && sort_fields[1] == '+') - consider_authors(v, v + n, 0); - for (int i = 0; i < n; i++) - v[i]->compute_label(); -} - - -/* A reference with a list of authors _needs_ author i -where 0 <= i <= N if there exists a reference with a list of authors - such that != and M >= i -and Aj = Bj for 0 <= j < i. In this case if we can't say ``A0, -A1,...,A(i-1) et al'' because this would match both and -. If a reference needs author i we only have to call -need_author(j) for some j >= i such that the reference also needs -author j. */ - -/* This function handles 2 tasks: -determine which authors are needed (cannot be elided with et al.); -determine which authors can have only last names in the labels. - -References >= start and < end have the same first i author names. -Also they're sorted by A+. */ - -static void consider_authors(reference **start, reference **end, int i) -{ - if (start >= end) - return; - reference **p = start; - if (i >= (*p)->get_nauthors()) { - for (++p; p < end && i >= (*p)->get_nauthors(); p++) - ; - if (p < end && i > 0) { - // If we have an author list and an author list , - // then both lists need C. - for (reference **q = start; q < end; q++) - (*q)->need_author(i - 1); - } - start = p; - } - while (p < end) { - reference **last_name_start = p; - reference **name_start = p; - for (++p; - p < end && i < (*p)->get_nauthors() - && same_author_last_name(**last_name_start, **p, i); - p++) { - if (!same_author_name(**name_start, **p, i)) { - consider_authors(name_start, p, i + 1); - name_start = p; - } - } - consider_authors(name_start, p, i + 1); - if (last_name_start == name_start) { - for (reference **q = last_name_start; q < p; q++) - (*q)->set_last_name_unambiguous(i); - } - // If we have an author list and , then the lists - // need author D and E respectively. - if (name_start > start || p < end) { - for (reference **q = last_name_start; q < p; q++) - (*q)->need_author(i); - } - } -} - -int same_author_last_name(const reference &r1, const reference &r2, int n) -{ - const char *ae1; - const char *as1 = r1.get_sort_field(0, n, 0, &ae1); - const char *ae2; - const char *as2 = r2.get_sort_field(0, n, 0, &ae2); - if (!as1 && !as2) return 1; // they are the same - if (!as1 || !as2) return 0; - return ae1 - as1 == ae2 - as2 && memcmp(as1, as2, ae1 - as1) == 0; -} - -int same_author_name(const reference &r1, const reference &r2, int n) -{ - const char *ae1; - const char *as1 = r1.get_sort_field(0, n, -1, &ae1); - const char *ae2; - const char *as2 = r2.get_sort_field(0, n, -1, &ae2); - if (!as1 && !as2) return 1; // they are the same - if (!as1 || !as2) return 0; - return ae1 - as1 == ae2 - as2 && memcmp(as1, as2, ae1 - as1) == 0; -} - - -void int_set::set(int i) -{ - assert(i >= 0); - int bytei = i >> 3; - if (bytei >= v.length()) { - int old_length = v.length(); - v.set_length(bytei + 1); - for (int j = old_length; j <= bytei; j++) - v[j] = 0; - } - v[bytei] |= 1 << (i & 7); -} - -int int_set::get(int i) const -{ - assert(i >= 0); - int bytei = i >> 3; - return bytei >= v.length() ? 0 : (v[bytei] & (1 << (i & 7))) != 0; -} - -void reference::set_last_name_unambiguous(int i) -{ - last_name_unambiguous.set(i); -} - -void reference::need_author(int n) -{ - if (n > last_needed_author) - last_needed_author = n; -} - -const char *reference::get_authors(const char **end) const -{ - if (!computed_authors) { - ((reference *)this)->computed_authors = 1; - string &result = ((reference *)this)->authors; - int na = get_nauthors(); - result.clear(); - for (int i = 0; i < na; i++) { - if (last_name_unambiguous.get(i)) { - const char *e, *start = get_author_last_name(i, &e); - assert(start != 0); - result.append(start, e - start); - } - else { - const char *e, *start = get_author(i, &e); - assert(start != 0); - result.append(start, e - start); - } - if (i == last_needed_author - && et_al.length() > 0 - && et_al_min_elide > 0 - && last_needed_author + et_al_min_elide < na - && na >= et_al_min_total) { - result += et_al; - break; - } - if (i < na - 1) { - if (na == 2) - result += join_authors_exactly_two; - else if (i < na - 2) - result += join_authors_default; - else - result += join_authors_last_two; - } - } - } - const char *start = authors.contents(); - *end = start + authors.length(); - return start; -} - -int reference::get_nauthors() const -{ - if (nauthors < 0) { - const char *dummy; - int na; - for (na = 0; get_author(na, &dummy) != 0; na++) - ; - ((reference *)this)->nauthors = na; - } - return nauthors; -} diff --git a/contrib/groff/src/preproc/refer/ref.cpp b/contrib/groff/src/preproc/refer/ref.cpp deleted file mode 100644 index 59c69d52b616..000000000000 --- a/contrib/groff/src/preproc/refer/ref.cpp +++ /dev/null @@ -1,1160 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2003 - 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "refer.h" -#include "refid.h" -#include "ref.h" -#include "token.h" - -static const char *find_day(const char *, const char *, const char **); -static int find_month(const char *start, const char *end); -static void abbreviate_names(string &); - -#define DEFAULT_ARTICLES "the\000a\000an" - -string articles(DEFAULT_ARTICLES, sizeof(DEFAULT_ARTICLES)); - -// Multiple occurrences of fields are separated by FIELD_SEPARATOR. -const char FIELD_SEPARATOR = '\0'; - -const char MULTI_FIELD_NAMES[] = "AE"; -const char *AUTHOR_FIELDS = "AQ"; - -enum { OTHER, JOURNAL_ARTICLE, BOOK, ARTICLE_IN_BOOK, TECH_REPORT, BELL_TM }; - -const char *reference_types[] = { - "other", - "journal-article", - "book", - "article-in-book", - "tech-report", - "bell-tm", -}; - -static string temp_fields[256]; - -reference::reference(const char *start, int len, reference_id *ridp) -: h(0), merged(0), no(-1), field(0), nfields(0), label_ptr(0), - computed_authors(0), last_needed_author(-1), nauthors(-1) -{ - int i; - for (i = 0; i < 256; i++) - field_index[i] = NULL_FIELD_INDEX; - if (ridp) - rid = *ridp; - if (start == 0) - return; - if (len <= 0) - return; - const char *end = start + len; - const char *ptr = start; - assert(*ptr == '%'); - while (ptr < end) { - if (ptr + 1 < end && ptr[1] != '\0' - && ((ptr[1] != '%' && ptr[1] == annotation_field) - || (ptr + 2 < end && ptr[1] == '%' && ptr[2] != '\0' - && discard_fields.search(ptr[2]) < 0))) { - if (ptr[1] == '%') - ptr++; - string &f = temp_fields[(unsigned char)ptr[1]]; - ptr += 2; - while (ptr < end && csspace(*ptr)) - ptr++; - for (;;) { - for (;;) { - if (ptr >= end) { - f += '\n'; - break; - } - f += *ptr; - if (*ptr++ == '\n') - break; - } - if (ptr >= end || *ptr == '%') - break; - } - } - else if (ptr + 1 < end && ptr[1] != '\0' && ptr[1] != '%' - && discard_fields.search(ptr[1]) < 0) { - string &f = temp_fields[(unsigned char)ptr[1]]; - if (f.length() > 0) { - if (strchr(MULTI_FIELD_NAMES, ptr[1]) != 0) - f += FIELD_SEPARATOR; - else - f.clear(); - } - ptr += 2; - if (ptr < end) { - if (*ptr == ' ') - ptr++; - for (;;) { - const char *p = ptr; - while (ptr < end && *ptr != '\n') - ptr++; - // strip trailing white space - const char *q = ptr; - while (q > p && q[-1] != '\n' && csspace(q[-1])) - q--; - while (p < q) - f += *p++; - if (ptr >= end) - break; - ptr++; - if (ptr >= end) - break; - if (*ptr == '%') - break; - f += ' '; - } - } - } - else { - // skip this field - for (;;) { - while (ptr < end && *ptr++ != '\n') - ; - if (ptr >= end || *ptr == '%') - break; - } - } - } - for (i = 0; i < 256; i++) - if (temp_fields[i].length() > 0) - nfields++; - field = new string[nfields]; - int j = 0; - for (i = 0; i < 256; i++) - if (temp_fields[i].length() > 0) { - field[j].move(temp_fields[i]); - if (abbreviate_fields.search(i) >= 0) - abbreviate_names(field[j]); - field_index[i] = j; - j++; - } -} - -reference::~reference() -{ - if (nfields > 0) - ad_delete(nfields) field; -} - -// ref is the inline, this is the database ref - -void reference::merge(reference &ref) -{ - int i; - for (i = 0; i < 256; i++) - if (field_index[i] != NULL_FIELD_INDEX) - temp_fields[i].move(field[field_index[i]]); - for (i = 0; i < 256; i++) - if (ref.field_index[i] != NULL_FIELD_INDEX) - temp_fields[i].move(ref.field[ref.field_index[i]]); - for (i = 0; i < 256; i++) - field_index[i] = NULL_FIELD_INDEX; - int old_nfields = nfields; - nfields = 0; - for (i = 0; i < 256; i++) - if (temp_fields[i].length() > 0) - nfields++; - if (nfields != old_nfields) { - if (old_nfields > 0) - ad_delete(old_nfields) field; - field = new string[nfields]; - } - int j = 0; - for (i = 0; i < 256; i++) - if (temp_fields[i].length() > 0) { - field[j].move(temp_fields[i]); - field_index[i] = j; - j++; - } - merged = 1; -} - -void reference::insert_field(unsigned char c, string &s) -{ - assert(s.length() > 0); - if (field_index[c] != NULL_FIELD_INDEX) { - field[field_index[c]].move(s); - return; - } - assert(field_index[c] == NULL_FIELD_INDEX); - string *old_field = field; - field = new string[nfields + 1]; - int pos = 0; - int i; - for (i = 0; i < int(c); i++) - if (field_index[i] != NULL_FIELD_INDEX) - pos++; - for (i = 0; i < pos; i++) - field[i].move(old_field[i]); - field[pos].move(s); - for (i = pos; i < nfields; i++) - field[i + 1].move(old_field[i]); - if (nfields > 0) - ad_delete(nfields) old_field; - nfields++; - field_index[c] = pos; - for (i = c + 1; i < 256; i++) - if (field_index[i] != NULL_FIELD_INDEX) - field_index[i] += 1; -} - -void reference::delete_field(unsigned char c) -{ - if (field_index[c] == NULL_FIELD_INDEX) - return; - string *old_field = field; - field = new string[nfields - 1]; - int i; - for (i = 0; i < int(field_index[c]); i++) - field[i].move(old_field[i]); - for (i = field_index[c]; i < nfields - 1; i++) - field[i].move(old_field[i + 1]); - if (nfields > 0) - ad_delete(nfields) old_field; - nfields--; - field_index[c] = NULL_FIELD_INDEX; - for (i = c + 1; i < 256; i++) - if (field_index[i] != NULL_FIELD_INDEX) - field_index[i] -= 1; -} - -void reference::compute_hash_code() -{ - if (!rid.is_null()) - h = rid.hash(); - else { - h = 0; - for (int i = 0; i < nfields; i++) - if (field[i].length() > 0) { - h <<= 4; - h ^= hash_string(field[i].contents(), field[i].length()); - } - } -} - -void reference::set_number(int n) -{ - no = n; -} - -const char SORT_SEP = '\001'; -const char SORT_SUB_SEP = '\002'; -const char SORT_SUB_SUB_SEP = '\003'; - -// sep specifies additional word separators - -void sortify_words(const char *s, const char *end, const char *sep, - string &result) -{ - int non_empty = 0; - int need_separator = 0; - for (;;) { - const char *token_start = s; - if (!get_token(&s, end)) - break; - if ((s - token_start == 1 - && (*token_start == ' ' - || *token_start == '\n' - || (sep && *token_start != '\0' - && strchr(sep, *token_start) != 0))) - || (s - token_start == 2 - && token_start[0] == '\\' && token_start[1] == ' ')) { - if (non_empty) - need_separator = 1; - } - else { - const token_info *ti = lookup_token(token_start, s); - if (ti->sortify_non_empty(token_start, s)) { - if (need_separator) { - result += ' '; - need_separator = 0; - } - ti->sortify(token_start, s, result); - non_empty = 1; - } - } - } -} - -void sortify_word(const char *s, const char *end, string &result) -{ - for (;;) { - const char *token_start = s; - if (!get_token(&s, end)) - break; - const token_info *ti = lookup_token(token_start, s); - ti->sortify(token_start, s, result); - } -} - -void sortify_other(const char *s, int len, string &key) -{ - sortify_words(s, s + len, 0, key); -} - -void sortify_title(const char *s, int len, string &key) -{ - const char *end = s + len; - for (; s < end && (*s == ' ' || *s == '\n'); s++) - ; - const char *ptr = s; - for (;;) { - const char *token_start = ptr; - if (!get_token(&ptr, end)) - break; - if (ptr - token_start == 1 - && (*token_start == ' ' || *token_start == '\n')) - break; - } - if (ptr < end) { - unsigned int first_word_len = ptr - s - 1; - const char *ae = articles.contents() + articles.length(); - for (const char *a = articles.contents(); - a < ae; - a = strchr(a, '\0') + 1) - if (first_word_len == strlen(a)) { - unsigned int j; - for (j = 0; j < first_word_len; j++) - if (a[j] != cmlower(s[j])) - break; - if (j >= first_word_len) { - s = ptr; - for (; s < end && (*s == ' ' || *s == '\n'); s++) - ; - break; - } - } - } - sortify_words(s, end, 0, key); -} - -void sortify_name(const char *s, int len, string &key) -{ - const char *last_name_end; - const char *last_name = find_last_name(s, s + len, &last_name_end); - sortify_word(last_name, last_name_end, key); - key += SORT_SUB_SUB_SEP; - if (last_name > s) - sortify_words(s, last_name, ".", key); - key += SORT_SUB_SUB_SEP; - if (last_name_end < s + len) - sortify_words(last_name_end, s + len, ".,", key); -} - -void sortify_date(const char *s, int len, string &key) -{ - const char *year_end; - const char *year_start = find_year(s, s + len, &year_end); - if (!year_start) { - // Things without years are often `forthcoming', so it makes sense - // that they sort after things with explicit years. - key += 'A'; - sortify_words(s, s + len, 0, key); - return; - } - int n = year_end - year_start; - while (n < 4) { - key += '0'; - n++; - } - while (year_start < year_end) - key += *year_start++; - int m = find_month(s, s + len); - if (m < 0) - return; - key += 'A' + m; - const char *day_end; - const char *day_start = find_day(s, s + len, &day_end); - if (!day_start) - return; - if (day_end - day_start == 1) - key += '0'; - while (day_start < day_end) - key += *day_start++; -} - -// SORT_{SUB,SUB_SUB}_SEP can creep in from use of @ in label specification. - -void sortify_label(const char *s, int len, string &key) -{ - const char *end = s + len; - for (;;) { - const char *ptr; - for (ptr = s; - ptr < end && *ptr != SORT_SUB_SEP && *ptr != SORT_SUB_SUB_SEP; - ptr++) - ; - if (ptr > s) - sortify_words(s, ptr, 0, key); - s = ptr; - if (s >= end) - break; - key += *s++; - } -} - -void reference::compute_sort_key() -{ - if (sort_fields.length() == 0) - return; - sort_fields += '\0'; - const char *sf = sort_fields.contents(); - while (*sf != '\0') { - sort_key += SORT_SEP; - char f = *sf++; - int n = 1; - if (*sf == '+') { - n = INT_MAX; - sf++; - } - else if (csdigit(*sf)) { - char *ptr; - long l = strtol(sf, &ptr, 10); - if (l == 0 && ptr == sf) - ; - else { - sf = ptr; - if (l < 0) { - n = 1; - } - else { - n = int(l); - } - } - } - if (f == '.') - sortify_label(label.contents(), label.length(), sort_key); - else if (f == AUTHOR_FIELDS[0]) - sortify_authors(n, sort_key); - else - sortify_field(f, n, sort_key); - } - sort_fields.set_length(sort_fields.length() - 1); -} - -void reference::sortify_authors(int n, string &result) const -{ - for (const char *p = AUTHOR_FIELDS; *p != '\0'; p++) - if (contains_field(*p)) { - sortify_field(*p, n, result); - return; - } - sortify_field(AUTHOR_FIELDS[0], n, result); -} - -void reference::canonicalize_authors(string &result) const -{ - int len = result.length(); - sortify_authors(INT_MAX, result); - if (result.length() > len) - result += SORT_SUB_SEP; -} - -void reference::sortify_field(unsigned char f, int n, string &result) const -{ - typedef void (*sortify_t)(const char *, int, string &); - sortify_t sortifier = sortify_other; - switch (f) { - case 'A': - case 'E': - sortifier = sortify_name; - break; - case 'D': - sortifier = sortify_date; - break; - case 'B': - case 'J': - case 'T': - sortifier = sortify_title; - break; - } - int fi = field_index[(unsigned char)f]; - if (fi != NULL_FIELD_INDEX) { - string &str = field[fi]; - const char *start = str.contents(); - const char *end = start + str.length(); - for (int i = 0; i < n && start < end; i++) { - const char *p = start; - while (start < end && *start != FIELD_SEPARATOR) - start++; - if (i > 0) - result += SORT_SUB_SEP; - (*sortifier)(p, start - p, result); - if (start < end) - start++; - } - } -} - -int compare_reference(const reference &r1, const reference &r2) -{ - assert(r1.no >= 0); - assert(r2.no >= 0); - const char *s1 = r1.sort_key.contents(); - int n1 = r1.sort_key.length(); - const char *s2 = r2.sort_key.contents(); - int n2 = r2.sort_key.length(); - for (; n1 > 0 && n2 > 0; --n1, --n2, ++s1, ++s2) - if (*s1 != *s2) - return (int)(unsigned char)*s1 - (int)(unsigned char)*s2; - if (n2 > 0) - return -1; - if (n1 > 0) - return 1; - return r1.no - r2.no; -} - -int same_reference(const reference &r1, const reference &r2) -{ - if (!r1.rid.is_null() && r1.rid == r2.rid) - return 1; - if (r1.h != r2.h) - return 0; - if (r1.nfields != r2.nfields) - return 0; - int i = 0; - for (i = 0; i < 256; i++) - if (r1.field_index != r2.field_index) - return 0; - for (i = 0; i < r1.nfields; i++) - if (r1.field[i] != r2.field[i]) - return 0; - return 1; -} - -const char *find_last_name(const char *start, const char *end, - const char **endp) -{ - const char *ptr = start; - const char *last_word = start; - for (;;) { - const char *token_start = ptr; - if (!get_token(&ptr, end)) - break; - if (ptr - token_start == 1) { - if (*token_start == ',') { - *endp = token_start; - return last_word; - } - else if (*token_start == ' ' || *token_start == '\n') { - if (ptr < end && *ptr != ' ' && *ptr != '\n') - last_word = ptr; - } - } - } - *endp = end; - return last_word; -} - -void abbreviate_name(const char *ptr, const char *end, string &result) -{ - const char *last_name_end; - const char *last_name_start = find_last_name(ptr, end, &last_name_end); - int need_period = 0; - for (;;) { - const char *token_start = ptr; - if (!get_token(&ptr, last_name_start)) - break; - const token_info *ti = lookup_token(token_start, ptr); - if (need_period) { - if ((ptr - token_start == 1 && *token_start == ' ') - || (ptr - token_start == 2 && token_start[0] == '\\' - && token_start[1] == ' ')) - continue; - if (ti->is_upper()) - result += period_before_initial; - else - result += period_before_other; - need_period = 0; - } - result.append(token_start, ptr - token_start); - if (ti->is_upper()) { - const char *lower_ptr = ptr; - int first_token = 1; - for (;;) { - token_start = ptr; - if (!get_token(&ptr, last_name_start)) - break; - if ((ptr - token_start == 1 && *token_start == ' ') - || (ptr - token_start == 2 && token_start[0] == '\\' - && token_start[1] == ' ')) - break; - ti = lookup_token(token_start, ptr); - if (ti->is_hyphen()) { - const char *ptr1 = ptr; - if (get_token(&ptr1, last_name_start)) { - ti = lookup_token(ptr, ptr1); - if (ti->is_upper()) { - result += period_before_hyphen; - result.append(token_start, ptr1 - token_start); - ptr = ptr1; - } - } - } - else if (ti->is_upper()) { - // MacDougal -> MacD. - result.append(lower_ptr, ptr - lower_ptr); - lower_ptr = ptr; - first_token = 1; - } - else if (first_token && ti->is_accent()) { - result.append(token_start, ptr - token_start); - lower_ptr = ptr; - } - first_token = 0; - } - need_period = 1; - } - } - if (need_period) - result += period_before_last_name; - result.append(last_name_start, end - last_name_start); -} - -static void abbreviate_names(string &result) -{ - string str; - str.move(result); - const char *ptr = str.contents(); - const char *end = ptr + str.length(); - while (ptr < end) { - const char *name_end = (char *)memchr(ptr, FIELD_SEPARATOR, end - ptr); - if (name_end == 0) - name_end = end; - abbreviate_name(ptr, name_end, result); - if (name_end >= end) - break; - ptr = name_end + 1; - result += FIELD_SEPARATOR; - } -} - -void reverse_name(const char *ptr, const char *name_end, string &result) -{ - const char *last_name_end; - const char *last_name_start = find_last_name(ptr, name_end, &last_name_end); - result.append(last_name_start, last_name_end - last_name_start); - while (last_name_start > ptr - && (last_name_start[-1] == ' ' || last_name_start[-1] == '\n')) - last_name_start--; - if (last_name_start > ptr) { - result += ", "; - result.append(ptr, last_name_start - ptr); - } - if (last_name_end < name_end) - result.append(last_name_end, name_end - last_name_end); -} - -void reverse_names(string &result, int n) -{ - if (n <= 0) - return; - string str; - str.move(result); - const char *ptr = str.contents(); - const char *end = ptr + str.length(); - while (ptr < end) { - if (--n < 0) { - result.append(ptr, end - ptr); - break; - } - const char *name_end = (char *)memchr(ptr, FIELD_SEPARATOR, end - ptr); - if (name_end == 0) - name_end = end; - reverse_name(ptr, name_end, result); - if (name_end >= end) - break; - ptr = name_end + 1; - result += FIELD_SEPARATOR; - } -} - -// Return number of field separators. - -int join_fields(string &f) -{ - const char *ptr = f.contents(); - int len = f.length(); - int nfield_seps = 0; - int j; - for (j = 0; j < len; j++) - if (ptr[j] == FIELD_SEPARATOR) - nfield_seps++; - if (nfield_seps == 0) - return 0; - string temp; - int field_seps_left = nfield_seps; - for (j = 0; j < len; j++) { - if (ptr[j] == FIELD_SEPARATOR) { - if (nfield_seps == 1) - temp += join_authors_exactly_two; - else if (--field_seps_left == 0) - temp += join_authors_last_two; - else - temp += join_authors_default; - } - else - temp += ptr[j]; - } - f = temp; - return nfield_seps; -} - -void uppercase(const char *start, const char *end, string &result) -{ - for (;;) { - const char *token_start = start; - if (!get_token(&start, end)) - break; - const token_info *ti = lookup_token(token_start, start); - ti->upper_case(token_start, start, result); - } -} - -void lowercase(const char *start, const char *end, string &result) -{ - for (;;) { - const char *token_start = start; - if (!get_token(&start, end)) - break; - const token_info *ti = lookup_token(token_start, start); - ti->lower_case(token_start, start, result); - } -} - -void capitalize(const char *ptr, const char *end, string &result) -{ - int in_small_point_size = 0; - for (;;) { - const char *start = ptr; - if (!get_token(&ptr, end)) - break; - const token_info *ti = lookup_token(start, ptr); - const char *char_end = ptr; - int is_lower = ti->is_lower(); - if ((is_lower || ti->is_upper()) && get_token(&ptr, end)) { - const token_info *ti2 = lookup_token(char_end, ptr); - if (!ti2->is_accent()) - ptr = char_end; - } - if (is_lower) { - if (!in_small_point_size) { - result += "\\s-2"; - in_small_point_size = 1; - } - ti->upper_case(start, char_end, result); - result.append(char_end, ptr - char_end); - } - else { - if (in_small_point_size) { - result += "\\s+2"; - in_small_point_size = 0; - } - result.append(start, ptr - start); - } - } - if (in_small_point_size) - result += "\\s+2"; -} - -void capitalize_field(string &str) -{ - string temp; - capitalize(str.contents(), str.contents() + str.length(), temp); - str.move(temp); -} - -int is_terminated(const char *ptr, const char *end) -{ - const char *last_token = end; - for (;;) { - const char *p = ptr; - if (!get_token(&ptr, end)) - break; - last_token = p; - } - return end - last_token == 1 - && (*last_token == '.' || *last_token == '!' || *last_token == '?'); -} - -void reference::output(FILE *fp) -{ - fputs(".]-\n", fp); - for (int i = 0; i < 256; i++) - if (field_index[i] != NULL_FIELD_INDEX && i != annotation_field) { - string &f = field[field_index[i]]; - if (!csdigit(i)) { - int j = reverse_fields.search(i); - if (j >= 0) { - int n; - int len = reverse_fields.length(); - if (++j < len && csdigit(reverse_fields[j])) { - n = reverse_fields[j] - '0'; - for (++j; j < len && csdigit(reverse_fields[j]); j++) - // should check for overflow - n = n*10 + reverse_fields[j] - '0'; - } - else - n = INT_MAX; - reverse_names(f, n); - } - } - int is_multiple = join_fields(f) > 0; - if (capitalize_fields.search(i) >= 0) - capitalize_field(f); - if (memchr(f.contents(), '\n', f.length()) == 0) { - fprintf(fp, ".ds [%c ", i); - if (f[0] == ' ' || f[0] == '\\' || f[0] == '"') - putc('"', fp); - put_string(f, fp); - putc('\n', fp); - } - else { - fprintf(fp, ".de [%c\n", i); - put_string(f, fp); - fputs("..\n", fp); - } - if (i == 'P') { - int multiple_pages = 0; - const char *s = f.contents(); - const char *end = f.contents() + f.length(); - for (;;) { - const char *token_start = s; - if (!get_token(&s, end)) - break; - const token_info *ti = lookup_token(token_start, s); - if (ti->is_hyphen() || ti->is_range_sep()) { - multiple_pages = 1; - break; - } - } - fprintf(fp, ".nr [P %d\n", multiple_pages); - } - else if (i == 'E') - fprintf(fp, ".nr [E %d\n", is_multiple); - } - for (const char *p = "TAO"; *p; p++) { - int fi = field_index[(unsigned char)*p]; - if (fi != NULL_FIELD_INDEX) { - string &f = field[fi]; - fprintf(fp, ".nr [%c %d\n", *p, - is_terminated(f.contents(), f.contents() + f.length())); - } - } - int t = classify(); - fprintf(fp, ".][ %d %s\n", t, reference_types[t]); - if (annotation_macro.length() > 0 && annotation_field >= 0 - && field_index[annotation_field] != NULL_FIELD_INDEX) { - putc('.', fp); - put_string(annotation_macro, fp); - putc('\n', fp); - put_string(field[field_index[annotation_field]], fp); - } -} - -void reference::print_sort_key_comment(FILE *fp) -{ - fputs(".\\\"", fp); - put_string(sort_key, fp); - putc('\n', fp); -} - -const char *find_year(const char *start, const char *end, const char **endp) -{ - for (;;) { - while (start < end && !csdigit(*start)) - start++; - const char *ptr = start; - if (start == end) - break; - while (ptr < end && csdigit(*ptr)) - ptr++; - if (ptr - start == 4 || ptr - start == 3 - || (ptr - start == 2 - && (start[0] >= '4' || (start[0] == '3' && start[1] >= '2')))) { - *endp = ptr; - return start; - } - start = ptr; - } - return 0; -} - -static const char *find_day(const char *start, const char *end, - const char **endp) -{ - for (;;) { - while (start < end && !csdigit(*start)) - start++; - const char *ptr = start; - if (start == end) - break; - while (ptr < end && csdigit(*ptr)) - ptr++; - if ((ptr - start == 1 && start[0] != '0') - || (ptr - start == 2 && - (start[0] == '1' - || start[0] == '2' - || (start[0] == '3' && start[1] <= '1') - || (start[0] == '0' && start[1] != '0')))) { - *endp = ptr; - return start; - } - start = ptr; - } - return 0; -} - -static int find_month(const char *start, const char *end) -{ - static const char *months[] = { - "january", - "february", - "march", - "april", - "may", - "june", - "july", - "august", - "september", - "october", - "november", - "december", - }; - for (;;) { - while (start < end && !csalpha(*start)) - start++; - const char *ptr = start; - if (start == end) - break; - while (ptr < end && csalpha(*ptr)) - ptr++; - if (ptr - start >= 3) { - for (unsigned int i = 0; i < sizeof(months)/sizeof(months[0]); i++) { - const char *q = months[i]; - const char *p = start; - for (; p < ptr; p++, q++) - if (cmlower(*p) != *q) - break; - if (p >= ptr) - return i; - } - } - start = ptr; - } - return -1; -} - -int reference::contains_field(char c) const -{ - return field_index[(unsigned char)c] != NULL_FIELD_INDEX; -} - -int reference::classify() -{ - if (contains_field('J')) - return JOURNAL_ARTICLE; - if (contains_field('B')) - return ARTICLE_IN_BOOK; - if (contains_field('G')) - return TECH_REPORT; - if (contains_field('R')) - return TECH_REPORT; - if (contains_field('I')) - return BOOK; - if (contains_field('M')) - return BELL_TM; - return OTHER; -} - -const char *reference::get_year(const char **endp) const -{ - if (field_index['D'] != NULL_FIELD_INDEX) { - string &date = field[field_index['D']]; - const char *start = date.contents(); - const char *end = start + date.length(); - return find_year(start, end, endp); - } - else - return 0; -} - -const char *reference::get_field(unsigned char c, const char **endp) const -{ - if (field_index[c] != NULL_FIELD_INDEX) { - string &f = field[field_index[c]]; - const char *start = f.contents(); - *endp = start + f.length(); - return start; - } - else - return 0; -} - -const char *reference::get_date(const char **endp) const -{ - return get_field('D', endp); -} - -const char *nth_field(int i, const char *start, const char **endp) -{ - while (--i >= 0) { - start = (char *)memchr(start, FIELD_SEPARATOR, *endp - start); - if (!start) - return 0; - start++; - } - const char *e = (char *)memchr(start, FIELD_SEPARATOR, *endp - start); - if (e) - *endp = e; - return start; -} - -const char *reference::get_author(int i, const char **endp) const -{ - for (const char *f = AUTHOR_FIELDS; *f != '\0'; f++) { - const char *start = get_field(*f, endp); - if (start) { - if (strchr(MULTI_FIELD_NAMES, *f) != 0) - return nth_field(i, start, endp); - else if (i == 0) - return start; - else - return 0; - } - } - return 0; -} - -const char *reference::get_author_last_name(int i, const char **endp) const -{ - for (const char *f = AUTHOR_FIELDS; *f != '\0'; f++) { - const char *start = get_field(*f, endp); - if (start) { - if (strchr(MULTI_FIELD_NAMES, *f) != 0) { - start = nth_field(i, start, endp); - if (!start) - return 0; - } - if (*f == 'A') - return find_last_name(start, *endp, endp); - else - return start; - } - } - return 0; -} - -void reference::set_date(string &d) -{ - if (d.length() == 0) - delete_field('D'); - else - insert_field('D', d); -} - -int same_year(const reference &r1, const reference &r2) -{ - const char *ye1; - const char *ys1 = r1.get_year(&ye1); - const char *ye2; - const char *ys2 = r2.get_year(&ye2); - if (ys1 == 0) { - if (ys2 == 0) - return same_date(r1, r2); - else - return 0; - } - else if (ys2 == 0) - return 0; - else if (ye1 - ys1 != ye2 - ys2) - return 0; - else - return memcmp(ys1, ys2, ye1 - ys1) == 0; -} - -int same_date(const reference &r1, const reference &r2) -{ - const char *e1; - const char *s1 = r1.get_date(&e1); - const char *e2; - const char *s2 = r2.get_date(&e2); - if (s1 == 0) - return s2 == 0; - else if (s2 == 0) - return 0; - else if (e1 - s1 != e2 - s2) - return 0; - else - return memcmp(s1, s2, e1 - s1) == 0; -} - -const char *reference::get_sort_field(int i, int si, int ssi, - const char **endp) const -{ - const char *start = sort_key.contents(); - const char *end = start + sort_key.length(); - if (i < 0) { - *endp = end; - return start; - } - while (--i >= 0) { - start = (char *)memchr(start, SORT_SEP, end - start); - if (!start) - return 0; - start++; - } - const char *e = (char *)memchr(start, SORT_SEP, end - start); - if (e) - end = e; - if (si < 0) { - *endp = end; - return start; - } - while (--si >= 0) { - start = (char *)memchr(start, SORT_SUB_SEP, end - start); - if (!start) - return 0; - start++; - } - e = (char *)memchr(start, SORT_SUB_SEP, end - start); - if (e) - end = e; - if (ssi < 0) { - *endp = end; - return start; - } - while (--ssi >= 0) { - start = (char *)memchr(start, SORT_SUB_SUB_SEP, end - start); - if (!start) - return 0; - start++; - } - e = (char *)memchr(start, SORT_SUB_SUB_SEP, end - start); - if (e) - end = e; - *endp = end; - return start; -} - diff --git a/contrib/groff/src/preproc/refer/ref.h b/contrib/groff/src/preproc/refer/ref.h deleted file mode 100644 index ffb81ac86986..000000000000 --- a/contrib/groff/src/preproc/refer/ref.h +++ /dev/null @@ -1,128 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2005 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -// declarations to avoid friend name injection problems -int compare_reference(const reference &, const reference &); -int same_reference(const reference &, const reference &); -int same_year(const reference &, const reference &); -int same_date(const reference &, const reference &); -int same_author_last_name(const reference &, const reference &, int); -int same_author_name(const reference &, const reference &, int); - -struct label_info; - -enum label_type { NORMAL_LABEL, SHORT_LABEL }; -const int N_LABEL_TYPES = 2; - -struct substring_position { - int start; - int length; - substring_position() : start(-1) { } -}; - -class int_set { - string v; -public: - int_set() { } - void set(int i); - int get(int i) const; -}; - -class reference { -private: - unsigned h; - reference_id rid; - int merged; - string sort_key; - int no; - string *field; - int nfields; - unsigned char field_index[256]; - enum { NULL_FIELD_INDEX = 255 }; - string label; - substring_position separator_pos; - string short_label; - substring_position short_separator_pos; - label_info *label_ptr; - string authors; - int computed_authors; - int last_needed_author; - int nauthors; - int_set last_name_unambiguous; - - int contains_field(char) const; - void insert_field(unsigned char, string &s); - void delete_field(unsigned char); - void set_date(string &); - const char *get_sort_field(int i, int si, int ssi, const char **endp) const; - int merge_labels_by_parts(reference **, int, label_type, string &); - int merge_labels_by_number(reference **, int, label_type, string &); -public: - reference(const char * = 0, int = -1, reference_id * = 0); - ~reference(); - void output(FILE *); - void print_sort_key_comment(FILE *); - void set_number(int); - int get_number() const { return no; } - unsigned hash() const { return h; } - const string &get_label(label_type type) const; - const substring_position &get_separator_pos(label_type) const; - int is_merged() const { return merged; } - void compute_sort_key(); - void compute_hash_code(); - void pre_compute_label(); - void compute_label(); - void immediate_compute_label(); - int classify(); - void merge(reference &); - int merge_labels(reference **, int, label_type, string &); - int get_nauthors() const; - void need_author(int); - void set_last_name_unambiguous(int); - void sortify_authors(int, string &) const; - void canonicalize_authors(string &) const; - void sortify_field(unsigned char, int, string &) const; - const char *get_author(int, const char **) const; - const char *get_author_last_name(int, const char **) const; - const char *get_date(const char **) const; - const char *get_year(const char **) const; - const char *get_field(unsigned char, const char **) const; - const label_info *get_label_ptr() const { return label_ptr; } - const char *get_authors(const char **) const; - // for sorting - friend int compare_reference(const reference &r1, const reference &r2); - // for merging - friend int same_reference(const reference &, const reference &); - friend int same_year(const reference &, const reference &); - friend int same_date(const reference &, const reference &); - friend int same_author_last_name(const reference &, const reference &, int); - friend int same_author_name(const reference &, const reference &, int); -}; - -const char *find_year(const char *, const char *, const char **); -const char *find_last_name(const char *, const char *, const char **); - -const char *nth_field(int i, const char *start, const char **endp); - -void capitalize(const char *ptr, const char *end, string &result); -void reverse_name(const char *ptr, const char *end, string &result); -void uppercase(const char *ptr, const char *end, string &result); -void lowercase(const char *ptr, const char *end, string &result); -void abbreviate_name(const char *ptr, const char *end, string &result); diff --git a/contrib/groff/src/preproc/refer/refer.cpp b/contrib/groff/src/preproc/refer/refer.cpp deleted file mode 100644 index 66afa4b385c3..000000000000 --- a/contrib/groff/src/preproc/refer/refer.cpp +++ /dev/null @@ -1,1242 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989-1992, 2000, 2001, 2002, 2004 - 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "refer.h" -#include "refid.h" -#include "ref.h" -#include "token.h" -#include "search.h" -#include "command.h" - -extern "C" const char *Version_string; - -const char PRE_LABEL_MARKER = '\013'; -const char POST_LABEL_MARKER = '\014'; -const char LABEL_MARKER = '\015'; // label_type is added on - -#define FORCE_LEFT_BRACKET 04 -#define FORCE_RIGHT_BRACKET 010 - -static FILE *outfp = stdout; - -string capitalize_fields; -string reverse_fields; -string abbreviate_fields; -string period_before_last_name = ". "; -string period_before_initial = "."; -string period_before_hyphen = ""; -string period_before_other = ". "; -string sort_fields; -int annotation_field = -1; -string annotation_macro; -string discard_fields = "XYZ"; -string pre_label = "\\*([."; -string post_label = "\\*(.]"; -string sep_label = ", "; -int accumulate = 0; -int move_punctuation = 0; -int abbreviate_label_ranges = 0; -string label_range_indicator; -int label_in_text = 1; -int label_in_reference = 1; -int date_as_label = 0; -int sort_adjacent_labels = 0; -// Join exactly two authors with this. -string join_authors_exactly_two = " and "; -// When there are more than two authors join the last two with this. -string join_authors_last_two = ", and "; -// Otherwise join authors with this. -string join_authors_default = ", "; -string separate_label_second_parts = ", "; -// Use this string to represent that there are other authors. -string et_al = " et al"; -// Use et al only if it can replace at least this many authors. -int et_al_min_elide = 2; -// Use et al only if the total number of authors is at least this. -int et_al_min_total = 3; - - -int compatible_flag = 0; - -int short_label_flag = 0; - -static int recognize_R1_R2 = 1; - -search_list database_list; -int search_default = 1; -static int default_database_loaded = 0; - -static reference **citation = 0; -static int ncitations = 0; -static int citation_max = 0; - -static reference **reference_hash_table = 0; -static int hash_table_size; -static int nreferences = 0; - -static int need_syncing = 0; -string pending_line; -string pending_lf_lines; - -static void output_pending_line(); -static unsigned immediately_handle_reference(const string &); -static void immediately_output_references(); -static unsigned store_reference(const string &); -static void divert_to_temporary_file(); -static reference *make_reference(const string &, unsigned *); -static void usage(FILE *stream); -static void do_file(const char *); -static void split_punct(string &line, string &punct); -static void output_citation_group(reference **v, int n, label_type, FILE *fp); -static void possibly_load_default_database(); - -int main(int argc, char **argv) -{ - program_name = argv[0]; - static char stderr_buf[BUFSIZ]; - setbuf(stderr, stderr_buf); - outfp = stdout; - int finished_options = 0; - int bib_flag = 0; - int done_spec = 0; - - for (--argc, ++argv; - !finished_options && argc > 0 && argv[0][0] == '-' - && argv[0][1] != '\0'; - argv++, argc--) { - const char *opt = argv[0] + 1; - while (opt != 0 && *opt != '\0') { - switch (*opt) { - case 'C': - compatible_flag = 1; - opt++; - break; - case 'B': - bib_flag = 1; - label_in_reference = 0; - label_in_text = 0; - ++opt; - if (*opt == '\0') { - annotation_field = 'X'; - annotation_macro = "AP"; - } - else if (csalnum(opt[0]) && opt[1] == '.' && opt[2] != '\0') { - annotation_field = opt[0]; - annotation_macro = opt + 2; - } - opt = 0; - break; - case 'P': - move_punctuation = 1; - opt++; - break; - case 'R': - recognize_R1_R2 = 0; - opt++; - break; - case 'S': - // Not a very useful spec. - set_label_spec("(A.n|Q)', '(D.y|D)"); - done_spec = 1; - pre_label = " ("; - post_label = ")"; - sep_label = "; "; - opt++; - break; - case 'V': - verify_flag = 1; - opt++; - break; - case 'f': - { - const char *num = 0; - if (*++opt == '\0') { - if (argc > 1) { - num = *++argv; - --argc; - } - else { - error("option `f' requires an argument"); - usage(stderr); - exit(1); - } - } - else { - num = opt; - opt = 0; - } - const char *ptr; - for (ptr = num; *ptr; ptr++) - if (!csdigit(*ptr)) { - error("bad character `%1' in argument to -f option", *ptr); - break; - } - if (*ptr == '\0') { - string spec; - spec = '%'; - spec += num; - spec += '\0'; - set_label_spec(spec.contents()); - done_spec = 1; - } - break; - } - case 'b': - label_in_text = 0; - label_in_reference = 0; - opt++; - break; - case 'e': - accumulate = 1; - opt++; - break; - case 'c': - capitalize_fields = ++opt; - opt = 0; - break; - case 'k': - { - char buf[5]; - if (csalpha(*++opt)) - buf[0] = *opt++; - else { - if (*opt != '\0') - error("bad field name `%1'", *opt++); - buf[0] = 'L'; - } - buf[1] = '~'; - buf[2] = '%'; - buf[3] = 'a'; - buf[4] = '\0'; - set_label_spec(buf); - done_spec = 1; - } - break; - case 'a': - { - const char *ptr; - for (ptr = ++opt; *ptr; ptr++) - if (!csdigit(*ptr)) { - error("argument to `a' option not a number"); - break; - } - if (*ptr == '\0') { - reverse_fields = 'A'; - reverse_fields += opt; - } - opt = 0; - } - break; - case 'i': - linear_ignore_fields = ++opt; - opt = 0; - break; - case 'l': - { - char buf[INT_DIGITS*2 + 11]; // A.n+2D.y-3%a - strcpy(buf, "A.n"); - if (*++opt != '\0' && *opt != ',') { - char *ptr; - long n = strtol(opt, &ptr, 10); - if (n == 0 && ptr == opt) { - error("bad integer `%1' in `l' option", opt); - opt = 0; - break; - } - if (n < 0) - n = 0; - opt = ptr; - sprintf(strchr(buf, '\0'), "+%ld", n); - } - strcat(buf, "D.y"); - if (*opt == ',') - opt++; - if (*opt != '\0') { - char *ptr; - long n = strtol(opt, &ptr, 10); - if (n == 0 && ptr == opt) { - error("bad integer `%1' in `l' option", opt); - opt = 0; - break; - } - if (n < 0) - n = 0; - sprintf(strchr(buf, '\0'), "-%ld", n); - opt = ptr; - if (*opt != '\0') - error("argument to `l' option not of form `m,n'"); - } - strcat(buf, "%a"); - if (!set_label_spec(buf)) - assert(0); - done_spec = 1; - } - break; - case 'n': - search_default = 0; - opt++; - break; - case 'p': - { - const char *filename = 0; - if (*++opt == '\0') { - if (argc > 1) { - filename = *++argv; - argc--; - } - else { - error("option `p' requires an argument"); - usage(stderr); - exit(1); - } - } - else { - filename = opt; - opt = 0; - } - database_list.add_file(filename); - } - break; - case 's': - if (*++opt == '\0') - sort_fields = "AD"; - else { - sort_fields = opt; - opt = 0; - } - accumulate = 1; - break; - case 't': - { - char *ptr; - long n = strtol(opt, &ptr, 10); - if (n == 0 && ptr == opt) { - error("bad integer `%1' in `t' option", opt); - opt = 0; - break; - } - if (n < 1) - n = 1; - linear_truncate_len = int(n); - opt = ptr; - break; - } - case '-': - if (opt[1] == '\0') { - finished_options = 1; - opt++; - break; - } - if (strcmp(opt,"-version")==0) { - case 'v': - printf("GNU refer (groff) version %s\n", Version_string); - exit(0); - break; - } - if (strcmp(opt,"-help")==0) { - usage(stdout); - exit(0); - break; - } - // fall through - default: - error("unrecognized option `%1'", *opt); - usage(stderr); - exit(1); - break; - } - } - } - if (!done_spec) - set_label_spec("%1"); - if (argc <= 0) { - if (bib_flag) - do_bib("-"); - else - do_file("-"); - } - else { - for (int i = 0; i < argc; i++) { - if (bib_flag) - do_bib(argv[i]); - else - do_file(argv[i]); - } - } - if (accumulate) - output_references(); - if (fflush(stdout) < 0) - fatal("output error"); - return 0; -} - -static void usage(FILE *stream) -{ - fprintf(stream, -"usage: %s [-benvCPRS] [-aN] [-cXYZ] [-fN] [-iXYZ] [-kX] [-lM,N] [-p file]\n" -" [-sXYZ] [-tN] [-BL.M] [files ...]\n", - program_name); -} - -static void possibly_load_default_database() -{ - if (search_default && !default_database_loaded) { - char *filename = getenv("REFER"); - if (filename) - database_list.add_file(filename); - else - database_list.add_file(DEFAULT_INDEX, 1); - default_database_loaded = 1; - } -} - -static int is_list(const string &str) -{ - const char *start = str.contents(); - const char *end = start + str.length(); - while (end > start && csspace(end[-1])) - end--; - while (start < end && csspace(*start)) - start++; - return end - start == 6 && memcmp(start, "$LIST$", 6) == 0; -} - -static void do_file(const char *filename) -{ - FILE *fp; - if (strcmp(filename, "-") == 0) { - fp = stdin; - } - else { - errno = 0; - fp = fopen(filename, "r"); - if (fp == 0) { - error("can't open `%1': %2", filename, strerror(errno)); - return; - } - } - current_filename = filename; - fprintf(outfp, ".lf 1 %s\n", filename); - string line; - current_lineno = 0; - for (;;) { - line.clear(); - for (;;) { - int c = getc(fp); - if (c == EOF) { - if (line.length() > 0) - line += '\n'; - break; - } - if (invalid_input_char(c)) - error("invalid input character code %1", c); - else { - line += c; - if (c == '\n') - break; - } - } - int len = line.length(); - if (len == 0) - break; - current_lineno++; - if (len >= 2 && line[0] == '.' && line[1] == '[') { - int start_lineno = current_lineno; - int start_of_line = 1; - string str; - string post; - string pre(line.contents() + 2, line.length() - 3); - for (;;) { - int c = getc(fp); - if (c == EOF) { - error_with_file_and_line(current_filename, start_lineno, - "missing `.]' line"); - break; - } - if (start_of_line) - current_lineno++; - if (start_of_line && c == '.') { - int d = getc(fp); - if (d == ']') { - while ((d = getc(fp)) != '\n' && d != EOF) { - if (invalid_input_char(d)) - error("invalid input character code %1", d); - else - post += d; - } - break; - } - if (d != EOF) - ungetc(d, fp); - } - if (invalid_input_char(c)) - error("invalid input character code %1", c); - else - str += c; - start_of_line = (c == '\n'); - } - if (is_list(str)) { - output_pending_line(); - if (accumulate) - output_references(); - else - error("found `$LIST$' but not accumulating references"); - } - else { - unsigned flags = (accumulate - ? store_reference(str) - : immediately_handle_reference(str)); - if (label_in_text) { - if (accumulate && outfp == stdout) - divert_to_temporary_file(); - if (pending_line.length() == 0) { - warning("can't attach citation to previous line"); - } - else - pending_line.set_length(pending_line.length() - 1); - string punct; - if (move_punctuation) - split_punct(pending_line, punct); - int have_text = pre.length() > 0 || post.length() > 0; - label_type lt = label_type(flags & ~(FORCE_LEFT_BRACKET - |FORCE_RIGHT_BRACKET)); - if ((flags & FORCE_LEFT_BRACKET) || !have_text) - pending_line += PRE_LABEL_MARKER; - pending_line += pre; - char lm = LABEL_MARKER + (int)lt; - pending_line += lm; - pending_line += post; - if ((flags & FORCE_RIGHT_BRACKET) || !have_text) - pending_line += POST_LABEL_MARKER; - pending_line += punct; - pending_line += '\n'; - } - } - need_syncing = 1; - } - else if (len >= 4 - && line[0] == '.' && line[1] == 'l' && line[2] == 'f' - && (compatible_flag || line[3] == '\n' || line[3] == ' ')) { - pending_lf_lines += line; - line += '\0'; - if (interpret_lf_args(line.contents() + 3)) - current_lineno--; - } - else if (recognize_R1_R2 - && len >= 4 - && line[0] == '.' && line[1] == 'R' && line[2] == '1' - && (compatible_flag || line[3] == '\n' || line[3] == ' ')) { - line.clear(); - int start_of_line = 1; - int start_lineno = current_lineno; - for (;;) { - int c = getc(fp); - if (c != EOF && start_of_line) - current_lineno++; - if (start_of_line && c == '.') { - c = getc(fp); - if (c == 'R') { - c = getc(fp); - if (c == '2') { - c = getc(fp); - if (compatible_flag || c == ' ' || c == '\n' || c == EOF) { - while (c != EOF && c != '\n') - c = getc(fp); - break; - } - else { - line += '.'; - line += 'R'; - line += '2'; - } - } - else { - line += '.'; - line += 'R'; - } - } - else - line += '.'; - } - if (c == EOF) { - error_with_file_and_line(current_filename, start_lineno, - "missing `.R2' line"); - break; - } - if (invalid_input_char(c)) - error("invalid input character code %1", int(c)); - else { - line += c; - start_of_line = c == '\n'; - } - } - output_pending_line(); - if (accumulate) - output_references(); - else - nreferences = 0; - process_commands(line, current_filename, start_lineno + 1); - need_syncing = 1; - } - else { - output_pending_line(); - pending_line = line; - } - } - need_syncing = 0; - output_pending_line(); - if (fp != stdin) - fclose(fp); -} - -class label_processing_state { - enum { - NORMAL, - PENDING_LABEL, - PENDING_LABEL_POST, - PENDING_LABEL_POST_PRE, - PENDING_POST - } state; - label_type type; // type of pending labels - int count; // number of pending labels - reference **rptr; // pointer to next reference - int rcount; // number of references left - FILE *fp; - int handle_pending(int c); -public: - label_processing_state(reference **, int, FILE *); - ~label_processing_state(); - void process(int c); -}; - -static void output_pending_line() -{ - if (label_in_text && !accumulate && ncitations > 0) { - label_processing_state state(citation, ncitations, outfp); - int len = pending_line.length(); - for (int i = 0; i < len; i++) - state.process((unsigned char)(pending_line[i])); - } - else - put_string(pending_line, outfp); - pending_line.clear(); - if (pending_lf_lines.length() > 0) { - put_string(pending_lf_lines, outfp); - pending_lf_lines.clear(); - } - if (!accumulate) - immediately_output_references(); - if (need_syncing) { - fprintf(outfp, ".lf %d %s\n", current_lineno, current_filename); - need_syncing = 0; - } -} - -static void split_punct(string &line, string &punct) -{ - const char *start = line.contents(); - const char *end = start + line.length(); - const char *ptr = start; - const char *last_token_start = 0; - for (;;) { - if (ptr >= end) - break; - last_token_start = ptr; - if (*ptr == PRE_LABEL_MARKER || *ptr == POST_LABEL_MARKER - || (*ptr >= LABEL_MARKER && *ptr < LABEL_MARKER + N_LABEL_TYPES)) - ptr++; - else if (!get_token(&ptr, end)) - break; - } - if (last_token_start) { - const token_info *ti = lookup_token(last_token_start, end); - if (ti->is_punct()) { - punct.append(last_token_start, end - last_token_start); - line.set_length(last_token_start - start); - } - } -} - -static void divert_to_temporary_file() -{ - outfp = xtmpfile(); -} - -static void store_citation(reference *ref) -{ - if (ncitations >= citation_max) { - if (citation == 0) - citation = new reference*[citation_max = 100]; - else { - reference **old_citation = citation; - citation_max *= 2; - citation = new reference *[citation_max]; - memcpy(citation, old_citation, ncitations*sizeof(reference *)); - a_delete old_citation; - } - } - citation[ncitations++] = ref; -} - -static unsigned store_reference(const string &str) -{ - if (reference_hash_table == 0) { - reference_hash_table = new reference *[17]; - hash_table_size = 17; - for (int i = 0; i < hash_table_size; i++) - reference_hash_table[i] = 0; - } - unsigned flags; - reference *ref = make_reference(str, &flags); - ref->compute_hash_code(); - unsigned h = ref->hash(); - reference **ptr; - for (ptr = reference_hash_table + (h % hash_table_size); - *ptr != 0; - ((ptr == reference_hash_table) - ? (ptr = reference_hash_table + hash_table_size - 1) - : --ptr)) - if (same_reference(**ptr, *ref)) - break; - if (*ptr != 0) { - if (ref->is_merged()) - warning("fields ignored because reference already used"); - delete ref; - ref = *ptr; - } - else { - *ptr = ref; - ref->set_number(nreferences); - nreferences++; - ref->pre_compute_label(); - ref->compute_sort_key(); - if (nreferences*2 >= hash_table_size) { - // Rehash it. - reference **old_table = reference_hash_table; - int old_size = hash_table_size; - hash_table_size = next_size(hash_table_size); - reference_hash_table = new reference*[hash_table_size]; - int i; - for (i = 0; i < hash_table_size; i++) - reference_hash_table[i] = 0; - for (i = 0; i < old_size; i++) - if (old_table[i]) { - reference **p; - for (p = (reference_hash_table - + (old_table[i]->hash() % hash_table_size)); - *p; - ((p == reference_hash_table) - ? (p = reference_hash_table + hash_table_size - 1) - : --p)) - ; - *p = old_table[i]; - } - a_delete old_table; - } - } - if (label_in_text) - store_citation(ref); - return flags; -} - -unsigned immediately_handle_reference(const string &str) -{ - unsigned flags; - reference *ref = make_reference(str, &flags); - ref->set_number(nreferences); - if (label_in_text || label_in_reference) { - ref->pre_compute_label(); - ref->immediate_compute_label(); - } - nreferences++; - store_citation(ref); - return flags; -} - -static void immediately_output_references() -{ - for (int i = 0; i < ncitations; i++) { - reference *ref = citation[i]; - if (label_in_reference) { - fputs(".ds [F ", outfp); - const string &label = ref->get_label(NORMAL_LABEL); - if (label.length() > 0 - && (label[0] == ' ' || label[0] == '\\' || label[0] == '"')) - putc('"', outfp); - put_string(label, outfp); - putc('\n', outfp); - } - ref->output(outfp); - delete ref; - } - ncitations = 0; -} - -static void output_citation_group(reference **v, int n, label_type type, - FILE *fp) -{ - if (sort_adjacent_labels) { - // Do an insertion sort. Usually n will be very small. - for (int i = 1; i < n; i++) { - int num = v[i]->get_number(); - reference *temp = v[i]; - int j; - for (j = i - 1; j >= 0 && v[j]->get_number() > num; j--) - v[j + 1] = v[j]; - v[j + 1] = temp; - } - } - // This messes up if !accumulate. - if (accumulate && n > 1) { - // remove duplicates - int j = 1; - for (int i = 1; i < n; i++) - if (v[i]->get_label(type) != v[i - 1]->get_label(type)) - v[j++] = v[i]; - n = j; - } - string merged_label; - for (int i = 0; i < n; i++) { - int nmerged = v[i]->merge_labels(v + i + 1, n - i - 1, type, merged_label); - if (nmerged > 0) { - put_string(merged_label, fp); - i += nmerged; - } - else - put_string(v[i]->get_label(type), fp); - if (i < n - 1) - put_string(sep_label, fp); - } -} - - -label_processing_state::label_processing_state(reference **p, int n, FILE *f) -: state(NORMAL), count(0), rptr(p), rcount(n), fp(f) -{ -} - -label_processing_state::~label_processing_state() -{ - int handled = handle_pending(EOF); - assert(!handled); - assert(rcount == 0); -} - -int label_processing_state::handle_pending(int c) -{ - switch (state) { - case NORMAL: - break; - case PENDING_LABEL: - if (c == POST_LABEL_MARKER) { - state = PENDING_LABEL_POST; - return 1; - } - else { - output_citation_group(rptr, count, type, fp); - rptr += count ; - rcount -= count; - state = NORMAL; - } - break; - case PENDING_LABEL_POST: - if (c == PRE_LABEL_MARKER) { - state = PENDING_LABEL_POST_PRE; - return 1; - } - else { - output_citation_group(rptr, count, type, fp); - rptr += count; - rcount -= count; - put_string(post_label, fp); - state = NORMAL; - } - break; - case PENDING_LABEL_POST_PRE: - if (c >= LABEL_MARKER - && c < LABEL_MARKER + N_LABEL_TYPES - && c - LABEL_MARKER == type) { - count += 1; - state = PENDING_LABEL; - return 1; - } - else { - output_citation_group(rptr, count, type, fp); - rptr += count; - rcount -= count; - put_string(sep_label, fp); - state = NORMAL; - } - break; - case PENDING_POST: - if (c == PRE_LABEL_MARKER) { - put_string(sep_label, fp); - state = NORMAL; - return 1; - } - else { - put_string(post_label, fp); - state = NORMAL; - } - break; - } - return 0; -} - -void label_processing_state::process(int c) -{ - if (handle_pending(c)) - return; - assert(state == NORMAL); - switch (c) { - case PRE_LABEL_MARKER: - put_string(pre_label, fp); - state = NORMAL; - break; - case POST_LABEL_MARKER: - state = PENDING_POST; - break; - case LABEL_MARKER: - case LABEL_MARKER + 1: - count = 1; - state = PENDING_LABEL; - type = label_type(c - LABEL_MARKER); - break; - default: - state = NORMAL; - putc(c, fp); - break; - } -} - -extern "C" { - -int rcompare(const void *p1, const void *p2) -{ - return compare_reference(**(reference **)p1, **(reference **)p2); -} - -} - -void output_references() -{ - assert(accumulate); - if (!hash_table_size) { - error("nothing to reference (probably `bibliography' before `sort')"); - accumulate = 0; - nreferences = 0; - return; - } - if (nreferences > 0) { - int j = 0; - int i; - for (i = 0; i < hash_table_size; i++) - if (reference_hash_table[i] != 0) - reference_hash_table[j++] = reference_hash_table[i]; - assert(j == nreferences); - for (; j < hash_table_size; j++) - reference_hash_table[j] = 0; - qsort(reference_hash_table, nreferences, sizeof(reference*), rcompare); - for (i = 0; i < nreferences; i++) - reference_hash_table[i]->set_number(i); - compute_labels(reference_hash_table, nreferences); - } - if (outfp != stdout) { - rewind(outfp); - { - label_processing_state state(citation, ncitations, stdout); - int c; - while ((c = getc(outfp)) != EOF) - state.process(c); - } - ncitations = 0; - fclose(outfp); - outfp = stdout; - } - if (nreferences > 0) { - fputs(".]<\n", outfp); - for (int i = 0; i < nreferences; i++) { - if (sort_fields.length() > 0) - reference_hash_table[i]->print_sort_key_comment(outfp); - if (label_in_reference) { - fputs(".ds [F ", outfp); - const string &label = reference_hash_table[i]->get_label(NORMAL_LABEL); - if (label.length() > 0 - && (label[0] == ' ' || label[0] == '\\' || label[0] == '"')) - putc('"', outfp); - put_string(label, outfp); - putc('\n', outfp); - } - reference_hash_table[i]->output(outfp); - delete reference_hash_table[i]; - reference_hash_table[i] = 0; - } - fputs(".]>\n", outfp); - nreferences = 0; - } - clear_labels(); -} - -static reference *find_reference(const char *query, int query_len) -{ - // This is so that error messages look better. - while (query_len > 0 && csspace(query[query_len - 1])) - query_len--; - string str; - for (int i = 0; i < query_len; i++) - str += query[i] == '\n' ? ' ' : query[i]; - str += '\0'; - possibly_load_default_database(); - search_list_iterator iter(&database_list, str.contents()); - reference_id rid; - const char *start; - int len; - if (!iter.next(&start, &len, &rid)) { - error("no matches for `%1'", str.contents()); - return 0; - } - const char *end = start + len; - while (start < end) { - if (*start == '%') - break; - while (start < end && *start++ != '\n') - ; - } - if (start >= end) { - error("found a reference for `%1' but it didn't contain any fields", - str.contents()); - return 0; - } - reference *result = new reference(start, end - start, &rid); - if (iter.next(&start, &len, &rid)) - warning("multiple matches for `%1'", str.contents()); - return result; -} - -static reference *make_reference(const string &str, unsigned *flagsp) -{ - const char *start = str.contents(); - const char *end = start + str.length(); - const char *ptr = start; - while (ptr < end) { - if (*ptr == '%') - break; - while (ptr < end && *ptr++ != '\n') - ; - } - *flagsp = 0; - for (; start < ptr; start++) { - if (*start == '#') - *flagsp = (SHORT_LABEL | (*flagsp & (FORCE_RIGHT_BRACKET - | FORCE_LEFT_BRACKET))); - else if (*start == '[') - *flagsp |= FORCE_LEFT_BRACKET; - else if (*start == ']') - *flagsp |= FORCE_RIGHT_BRACKET; - else if (!csspace(*start)) - break; - } - if (start >= end) { - error("empty reference"); - return new reference; - } - reference *database_ref = 0; - if (start < ptr) - database_ref = find_reference(start, ptr - start); - reference *inline_ref = 0; - if (ptr < end) - inline_ref = new reference(ptr, end - ptr); - if (inline_ref) { - if (database_ref) { - database_ref->merge(*inline_ref); - delete inline_ref; - return database_ref; - } - else - return inline_ref; - } - else if (database_ref) - return database_ref; - else - return new reference; -} - -static void do_ref(const string &str) -{ - if (accumulate) - (void)store_reference(str); - else { - (void)immediately_handle_reference(str); - immediately_output_references(); - } -} - -static void trim_blanks(string &str) -{ - const char *start = str.contents(); - const char *end = start + str.length(); - while (end > start && end[-1] != '\n' && csspace(end[-1])) - --end; - str.set_length(end - start); -} - -void do_bib(const char *filename) -{ - FILE *fp; - if (strcmp(filename, "-") == 0) - fp = stdin; - else { - errno = 0; - fp = fopen(filename, "r"); - if (fp == 0) { - error("can't open `%1': %2", filename, strerror(errno)); - return; - } - current_filename = filename; - } - enum { - START, MIDDLE, BODY, BODY_START, BODY_BLANK, BODY_DOT - } state = START; - string body; - for (;;) { - int c = getc(fp); - if (c == EOF) - break; - if (invalid_input_char(c)) { - error("invalid input character code %1", c); - continue; - } - switch (state) { - case START: - if (c == '%') { - body = c; - state = BODY; - } - else if (c != '\n') - state = MIDDLE; - break; - case MIDDLE: - if (c == '\n') - state = START; - break; - case BODY: - body += c; - if (c == '\n') - state = BODY_START; - break; - case BODY_START: - if (c == '\n') { - do_ref(body); - state = START; - } - else if (c == '.') - state = BODY_DOT; - else if (csspace(c)) { - state = BODY_BLANK; - body += c; - } - else { - body += c; - state = BODY; - } - break; - case BODY_BLANK: - if (c == '\n') { - trim_blanks(body); - do_ref(body); - state = START; - } - else if (csspace(c)) - body += c; - else { - body += c; - state = BODY; - } - break; - case BODY_DOT: - if (c == ']') { - do_ref(body); - state = MIDDLE; - } - else { - body += '.'; - body += c; - state = c == '\n' ? BODY_START : BODY; - } - break; - default: - assert(0); - } - if (c == '\n') - current_lineno++; - } - switch (state) { - case START: - case MIDDLE: - break; - case BODY: - body += '\n'; - do_ref(body); - break; - case BODY_DOT: - case BODY_START: - do_ref(body); - break; - case BODY_BLANK: - trim_blanks(body); - do_ref(body); - break; - } - fclose(fp); -} - -// from the Dragon Book - -unsigned hash_string(const char *s, int len) -{ - const char *end = s + len; - unsigned h = 0, g; - while (s < end) { - h <<= 4; - h += *s++; - if ((g = h & 0xf0000000) != 0) { - h ^= g >> 24; - h ^= g; - } - } - return h; -} - -int next_size(int n) -{ - static const int table_sizes[] = { - 101, 503, 1009, 2003, 3001, 4001, 5003, 10007, 20011, 40009, - 80021, 160001, 500009, 1000003, 2000003, 4000037, 8000009, - 16000057, 32000011, 64000031, 128000003, 0 - }; - - const int *p; - for (p = table_sizes; *p <= n && *p != 0; p++) - ; - assert(*p != 0); - return *p; -} - diff --git a/contrib/groff/src/preproc/refer/refer.h b/contrib/groff/src/preproc/refer/refer.h deleted file mode 100644 index ac871cfae76d..000000000000 --- a/contrib/groff/src/preproc/refer/refer.h +++ /dev/null @@ -1,78 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2004 - 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "lib.h" - -#include -#include -#include - -#include "errarg.h" -#include "error.h" -#include "stringclass.h" -#include "cset.h" -#include "cmap.h" - -#include "defs.h" - -unsigned hash_string(const char *, int); -int next_size(int); - -extern string capitalize_fields; -extern string reverse_fields; -extern string abbreviate_fields; -extern string period_before_last_name; -extern string period_before_initial; -extern string period_before_hyphen; -extern string period_before_other; -extern string sort_fields; -extern int annotation_field; -extern string annotation_macro; -extern string discard_fields; -extern string articles; -extern int abbreviate_label_ranges; -extern string label_range_indicator; -extern int date_as_label; -extern string join_authors_exactly_two; -extern string join_authors_last_two; -extern string join_authors_default; -extern string separate_label_second_parts; -extern string et_al; -extern int et_al_min_elide; -extern int et_al_min_total; - -extern int compatible_flag; - -extern int set_label_spec(const char *); -extern int set_date_label_spec(const char *); -extern int set_short_label_spec(const char *); - -extern int short_label_flag; - -void clear_labels(); -void command_error(const char *, - const errarg &arg1 = empty_errarg, - const errarg &arg2 = empty_errarg, - const errarg &arg3 = empty_errarg); - -class reference; - -void compute_labels(reference **, int); diff --git a/contrib/groff/src/preproc/refer/refer.man b/contrib/groff/src/preproc/refer/refer.man deleted file mode 100644 index 0881657d4044..000000000000 --- a/contrib/groff/src/preproc/refer/refer.man +++ /dev/null @@ -1,1492 +0,0 @@ -.ig -Copyright (C) 1989-2000, 2001, 2002, 2003, 2004, 2005 - Free Software Foundation, Inc. - -Permission is granted to make and distribute verbatim copies of -this manual provided the copyright notice and this permission notice -are preserved on all copies. - -Permission is granted to copy and distribute modified versions of this -manual under the conditions for verbatim copying, provided that the -entire resulting derived work is distributed under the terms of a -permission notice identical to this one. - -Permission is granted to copy and distribute translations of this -manual into another language, under the above conditions for modified -versions, except that this permission notice may be included in -translations approved by the Free Software Foundation instead of in -the original English. -.. -. -. -.de TQ -. br -. ns -. TP \\$1 -.. -. -. -.\" 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 @G@REFER @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@" -. -. -. -.SH NAME -@g@refer \- preprocess bibliographic references for groff -. -. -. -.SH SYNOPSIS -.nr a \n(.j -.ad l -.nr i \n(.i -.in +\w'\fB@g@refer 'u -.ti \niu -.B @g@refer -. -.de OP -. ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]" -. el .RB "[\ " "\\$1" "\ ]" -.. -. -.OP \-benvCPRS -.OP \-a n -.OP \-c fields -.OP \-f n -.OP \-i fields -.OP \-k field -.OP \-l m,n -.OP \-p \%filename -.OP \-s fields -.OP \-t n -.OP \-B field.macro -.RI [\ \%filename \|.\|.\|.\ ] -.br -.ad \na -. -.LP -It is possible to have whitespace between a command line option and its -parameter. -. -. -. -.SH DESCRIPTION -This file documents the GNU version of -.BR refer , -which is part of the groff document formatting system. -.B refer -copies the contents of -.IR filename \|.\|.\|.\& -to the standard output, -except that lines between -.B .[ -and -.B .]\& -are interpreted as citations, -and lines between -.B .R1 -and -.B .R2 -are interpreted as commands about how citations are to be processed. -. -.LP -Each citation specifies a reference. -The citation can specify a reference that is contained in -a bibliographic database by giving a set of keywords -that only that reference contains. -Alternatively it can specify a reference by supplying a database -record in the citation. -A combination of these alternatives is also possible. -. -.LP -For each citation, -.B refer -can produce a mark in the text. -This mark consists of some label which can be separated from -the text and from other labels in various ways. -For each reference it also outputs -.B groff -commands that can be used by a macro package to produce a formatted -reference for each citation. -The output of -.B refer -must therefore be processed using a suitable macro package. -The -.B \-ms -and -.B \-me -macros are both suitable. -The commands to format a citation's reference can be output immediately after -the citation, -or the references may be accumulated, -and the commands output at some later point. -If the references are accumulated, then multiple citations of the same -reference will produce a single formatted reference. -. -.LP -The interpretation of lines between -.B .R1 -and -.B .R2 -as commands is a new feature of GNU -.BR refer . -Documents making use of this feature can still be processed by -Unix refer just by adding the lines -. -.RS -.LP -.nf -.ft B -\&.de R1 -\&.ig R2 -\&.. -.ft -.fi -.RE -. -to the beginning of the document. -This will cause -.B troff -to ignore everything between -.B .R1 -and -.BR .R2 . -The effect of some commands can also be achieved by options. -These options are supported mainly for compatibility with Unix refer. -It is usually more convenient to use commands. -. -.LP -.B refer -generates -.B .lf -lines so that filenames and line numbers in messages produced -by commands that read -.B refer -output will be correct; -it also interprets lines beginning with -.B .lf -so that filenames and line numbers in the messages and -.B .lf -lines that it produces will be accurate even if the input has been -preprocessed by a command such as -.BR @g@soelim (@MAN1EXT@). -. -. -. -.SH OPTIONS -. -.LP -Most options are equivalent to commands -(for a description of these commands see the -.B Commands -subsection): -. -.nr a \n(.j -.ad l -.TP -.B \-b -.B "no-label-in-text; no-label-in-reference" -. -.TP -.B \-e -.B accumulate -. -.TP -.B \-n -.B no-default-database -. -.TP -.B \-C -.B compatible -. -.TP -.B \-P -.B move-punctuation -. -.TP -.B \-S -.B -label\ "(A.n|Q)\ ',\ '\ (D.y|D)"; \%bracket-label\ "\ ("\ )\ ";\ " -. -.TP -.BI \-a n -.B reverse -.BI A n -. -.TP -.BI \-c fields -.B capitalize -.I fields -. -.TP -.BI \-f n -.B label -.BI % n -. -.TP -.BI \-i fields -.B search-ignore -.I fields -. -.TP -.B \-k -.B label -.B L\(ti%a -. -.TP -.BI \-k field -.B label -.IB field \(ti%a -. -.TP -.B \-l -.B label -.BI A.nD.y%a -. -.TP -.BI \-l m -.B label -.BI A.n+ m D.y%a -. -.TP -.BI \-l, n -.B label -.BI A.nD.y\- n %a -. -.TP -.BI \-l m , n -.B label -.BI A.n+ m D.y\- n %a -. -.TP -.BI \-p filename -.B database -.I filename -. -.TP -.BI \-s spec -.B sort -.I spec -. -.TP -.BI \-t n -.B search-truncate -.I n -.ad \na -. -.LP -These options are equivalent to the following commands with the -addition that the filenames specified on the command line are -processed as if they were arguments to the -.B bibliography -command instead of in the normal way: -. -.TP -.B \-B -.B "annotate X AP; no-label-in-reference" -. -.TP -.BI \-B field . macro -.B annotate -.I field -.IB macro ; -.B no-label-in-reference -. -.LP -The following options have no equivalent commands: -. -.TP -.B \-v -Print the version number. -. -.TP -.B \-R -Don't recognize lines beginning with -.BR .R1 / .R2 . -. -. -. -.SH USAGE -. -. -.SS Bibliographic databases -The bibliographic database is a text file consisting of records -separated by one or more blank lines. -Within each record fields start with a -.B % -at the beginning of a line. -Each field has a one character name that immediately follows the -.BR % . -It is best to use only upper and lower case letters for the names -of fields. -The name of the field should be followed by exactly one space, -and then by the contents of the field. -Empty fields are ignored. -The conventional meaning of each field is as follows: -. -.TP -.B A -The name of an author. -If the name contains a title such as -.B Jr.\& -at the end, -it should be separated from the last name by a comma. -There can be multiple occurrences of the -.B A -field. -The order is significant. -It is a good idea always to supply an -.B A -field or a -.B Q -field. -. -.TP -.B B -For an article that is part of a book, the title of the book. -. -.TP -.B C -The place (city) of publication. -. -.TP -.B D -The date of publication. -The year should be specified in full. -If the month is specified, the name rather than the number of the month -should be used, but only the first three letters are required. -It is a good idea always to supply a -.B D -field; -if the date is unknown, a value such as -.B in press -or -.B unknown -can be used. -. -.TP -.B E -For an article that is part of a book, the name of an editor of the book. -Where the work has editors and no authors, -the names of the editors should be given as -.B A -fields and -.B ,\ (ed) -or -.B ,\ (eds) -should be appended to the last author. -. -.TP -.B G -US Government ordering number. -. -.TP -.B I -The publisher (issuer). -. -.TP -.B J -For an article in a journal, the name of the journal. -. -.TP -.B K -Keywords to be used for searching. -. -.TP -.B L -Label. -. -.TP -.B N -Journal issue number. -. -.TP -.B O -Other information. -This is usually printed at the end of the reference. -. -.TP -.B P -Page number. -A range of pages can be specified as -.IB m \- n\fR. -. -.TP -.B Q -The name of the author, if the author is not a person. -This will only be used if there are no -.B A -fields. -There can only be one -.B Q -field. -. -.TP -.B R -Technical report number. -. -.TP -.B S -Series name. -. -.TP -.B T -Title. -For an article in a book or journal, -this should be the title of the article. -. -.TP -.B V -Volume number of the journal or book. -. -.TP -.B X -Annotation. -. -.LP -For all fields except -.B A -and -.BR E , -if there is more than one occurrence of a particular field in a record, -only the last such field will be used. -. -.LP -If accent strings are used, they should follow the character to be accented. -This means that the -.B AM -macro must be used with the -.B \-ms -macros. -Accent strings should not be quoted: -use one -.B \e -rather than two. -. -. -.SS Citations -The format of a citation is -. -.RS -.BI .[ opening-text -.br -.I "flags keywords" -.br -.I fields -.br -.BI .] closing-text -.RE -. -.LP -The -.IR opening-text , -.IR closing-text -and -.I flags -components are optional. -Only one of the -.I keywords -and -.I fields -components need be specified. -. -.LP -The -.I keywords -component says to search the bibliographic databases for a reference -that contains all the words in -.IR keywords . -It is an error if more than one reference if found. -. -.LP -The -.I fields -components specifies additional fields to replace or supplement -those specified in the reference. -When references are being accumulated and the -.I keywords -component is non-empty, -then additional fields should be specified only on the first -occasion that a particular reference is cited, -and will apply to all citations of that reference. -. -.LP -The -.I opening-text -and -.I closing-text -component specifies strings to be used to bracket the label instead -of the strings specified in the -.B bracket-label -command. -If either of these components is non-empty, -the strings specified in the -.B bracket-label -command will not be used; -this behaviour can be altered using the -.B [ -and -.B ] -flags. -Note that leading and trailing spaces are significant for these components. -. -.LP -The -.I flags -component is a list of -non-alphanumeric characters each of which modifies the treatment -of this particular citation. -Unix refer will treat these flags as part of the keywords and -so will ignore them since they are non-alphanumeric. -The following flags are currently recognized: -. -.TP -.B # -This says to use the label specified by the -.B short-label -command, -instead of that specified by the -.B label -command. -If no short label has been specified, the normal label will be used. -Typically the short label is used with author-date labels -and consists of only the date and possibly a disambiguating letter; -the -.B # -is supposed to be suggestive of a numeric type of label. -. -.TP -.B [ -Precede -.I opening-text -with the first string specified in the -.B bracket-label -command. -. -.TP -.B ] -Follow -.I closing-text -with the second string specified in the -.B bracket-label -command. -. -.LP -One advantages of using the -.B [ -and -.B ] -flags rather than including the brackets in -.I opening-text -and -.I closing-text -is that -you can change the style of bracket used in the document just by changing the -.B bracket-label -command. -Another advantage is that sorting and merging of citations -will not necessarily be inhibited if the flags are used. -. -.LP -If a label is to be inserted into the text, -it will be attached to the line preceding the -.B .[ -line. -If there is no such line, then an extra line will be inserted before the -.B .[ -line and a warning will be given. -. -.LP -There is no special notation for making a citation to multiple references. -Just use a sequence of citations, one for each reference. -Don't put anything between the citations. -The labels for all the citations will be attached to the line preceding -the first citation. -The labels may also be sorted or merged. -See the description of the -.B <> -label expression, and of the -.B sort-adjacent-labels -and -.B abbreviate-label-ranges -command. -A label will not be merged if its citation has a non-empty -.I opening-text -or -.IR closing-text . -However, the labels for a citation using the -.B ] -flag and without any -.I closing-text -immediately followed by a citation using the -.B [ -flag and without any -.I opening-text -may be sorted and merged -even though the first citation's -.I opening-text -or the second citation's -.I closing-text -is non-empty. -(If you wish to prevent this just make the first citation's -.I closing-text -.BR \e& .) -. -. -.SS Commands -Commands are contained between lines starting with -.B .R1 -and -.BR .R2 . -Recognition of these lines can be prevented by the -.B \-R -option. -When a -.B .R1 -line is recognized any accumulated references are flushed out. -Neither -.B .R1 -nor -.B .R2 -lines, -nor anything between them -is output. -. -.LP -Commands are separated by newlines or -.BR ; s. -.B # -introduces a comment that extends to the end of the line -(but does not conceal the newline). -Each command is broken up into words. -Words are separated by spaces or tabs. -A word that begins with -.B \(ts -extends to the next -.B \(ts -that is not followed by another -.BR \(ts . -If there is no such -.B \(ts -the word extends to the end of the line. -Pairs of -.B \(ts -in a word beginning with -.B \(ts -collapse to a single -.BR \(ts . -Neither -.B # -nor -.B ; -are recognized inside -.BR \(ts s. -A line can be continued by ending it with -.BR \e ; -this works everywhere except after a -.BR # . -. -.LP -.ds n \fR* -Each command -.I name -that is marked with \*n has an associated negative command -.BI no- name -that undoes the effect of -.IR name . -For example, the -.B no-sort -command specifies that references should not be sorted. -The negative commands take no arguments. -. -.LP -In the following description each argument must be a single word; -.I field -is used for a single upper or lower case letter naming a field; -.I fields -is used for a sequence of such letters; -.I m -and -.I n -are used for a non-negative numbers; -.I string -is used for an arbitrary string; -.I filename -is used for the name of a file. -. -.Tp \w'\fBabbreviate-label-ranges'u+2n -.BI abbreviate\*n\ fields\ string1\ string2\ string3\ string4 -Abbreviate the first names of -.IR fields . -An initial letter will be separated from another initial letter by -.IR string1 , -from the last name by -.IR string2 , -and from anything else -(such as a -.B von -or -.BR de ) -by -.IR string3 . -These default to a period followed by a space. -In a hyphenated first name, -the initial of the first part of the name will be separated from the hyphen by -.IR string4 ; -this defaults to a period. -No attempt is made to handle any ambiguities that might -result from abbreviation. -Names are abbreviated before sorting and before -label construction. -. -.TP -.BI abbreviate-label-ranges\*n\ string -Three or more adjacent labels that refer to consecutive references -will be abbreviated to a label consisting -of the first label, followed by -.I string -followed by the last label. -This is mainly useful with numeric labels. -If -.I string -is omitted it defaults to -.BR \- . -. -.TP -.B accumulate\*n -Accumulate references instead of writing out each reference -as it is encountered. -Accumulated references will be written out whenever a reference -of the form -. -.RS -.IP -.B .[ -.br -.B $LIST$ -.br -.B .] -. -.LP -is encountered, -after all input files hve been processed, -and whenever -.B .R1 -line is recognized. -.RE -. -.TP -.BI annotate\*n\ field\ string -.I field -is an annotation; -print it at the end of the reference as a paragraph preceded by the line -. -.RS -.IP -.BI . string -. -.LP -If -.I macro -is omitted it will default to -.BR AP ; -if -.I field -is also omitted it will default to -.BR X . -Only one field can be an annotation. -.RE -. -.TP -.BI articles\ string \fR\|.\|.\|. -.IR string \|.\|.\|.\& -are definite or indefinite articles, and should be ignored at the beginning of -.B T -fields when sorting. -Initially, -.BR the , -.B a -and -.B an -are recognized as articles. -. -.TP -.BI bibliography\ filename \fR\|.\|.\|. -Write out all the references contained in the bibliographic databases -.IR filename \|.\|.\|. -This command should come last in a -.BR .R1 / .R2 -block. -. -.TP -.BI bracket-label\ string1\ string2\ string3 -In the text, bracket each label -with -.I string1 -and -.IR string2 . -An occurrence of -.I string2 -immediately followed by -.I string1 -will be turned into -.IR string3 . -The default behaviour is -. -.RS -.IP -.B -bracket-label \e*([. \e*(.] ", " -.RE -. -.TP -.BI capitalize\ fields -Convert -.I fields -to caps and small caps. -. -.TP -.B compatible\*n -Recognize -.B .R1 -and -.B .R2 -even when followed by a character other than space or newline. -. -.TP -.BI database\ filename \fR\|.\|.\|. -Search the bibliographic databases -.IR filename \|.\|.\|. -For each -.I filename -if an index -.IB filename @INDEX_SUFFIX@ -created by -.BR @g@indxbib (@MAN1EXT@) -exists, then it will be searched instead; -each index can cover multiple databases. -. -.TP -.BI date-as-label\*n\ string -.I string -is a label expression that specifies a string with which to replace the -.B D -field after constructing the label. -See the -.B "Label expressions" -subsection for a description of label expressions. -This command is useful if you do not want explicit labels in the -reference list, but instead want to handle any necessary -disambiguation by qualifying the date in some way. -The label used in the text would typically be some combination of the -author and date. -In most cases you should also use the -.B no-label-in-reference -command. -For example, -. -.RS -.IP -.B "date-as-label D.+yD.y%a*D.-y" -. -.LP -would attach a disambiguating letter to the year part of the -.B D -field in the reference. -.RE -. -.TP -.B default-database\*n -The default database should be searched. -This is the default behaviour, so the negative version of -this command is more useful. -.B refer -determines whether the default database should be searched -on the first occasion that it needs to do a search. -Thus a -.B no-default-database -command must be given before then, -in order to be effective. -. -.TP -.BI discard\*n\ fields -When the reference is read, -.I fields -should be discarded; -no string definitions for -.I fields -will be output. -Initially, -.I fields -are -.BR XYZ . -. -.TP -.BI et-al\*n\ string\ m\ n -Control use of -.B "et al" -in the evaluation of -.B @ -expressions in label expressions. -If the number of authors needed to make the author sequence -unambiguous is -.I u -and the total number of authors is -.I t -then the last -.IR t \|\-\| u -authors will be replaced by -.I string -provided that -.IR t \|\-\| u -is not less than -.I m -and -.I t -is not less than -.IR n . -The default behaviour is -. -.RS -.IP -.B -et-al " et al" 2 3 -.RE -. -.TP -.BI include\ filename -Include -.I filename -and interpret the contents as commands. -. -.TP -.BI join-authors\ string1\ string2\ string3 -This says how authors should be joined together. -When there are exactly two authors, they will be joined with -.IR string1 . -When there are more than two authors, all but the last two will -be joined with -.IR string2 , -and the last two authors will be joined with -.IR string3 . -If -.I string3 -is omitted, -it will default to -.IR string1 ; -if -.I string2 -is also omitted it will also default to -.IR string1 . -For example, -. -.RS -.IP -.B -join-authors " and " ", " ", and " -. -.LP -will restore the default method for joining authors. -.RE -. -.TP -.B label-in-reference\*n -When outputting the reference, -define the string -.B [F -to be the reference's label. -This is the default behaviour; so the negative version -of this command is more useful. -. -.TP -.B label-in-text\*n -For each reference output a label in the text. -The label will be separated from the surrounding text as described in the -.B bracket-label -command. -This is the default behaviour; so the negative version -of this command is more useful. -. -.TP -.BI label\ string -.I string -is a label expression describing how to label each reference. -. -.TP -.BI separate-label-second-parts\ string -When merging two-part labels, separate the second part of the second -label from the first label with -.IR string . -See the description of the -.B <> -label expression. -. -.TP -.B move-punctuation\*n -In the text, move any punctuation at the end of line past the label. -It is usually a good idea to give this command unless you are using -superscripted numbers as labels. -. -.TP -.BI reverse\*n\ string -Reverse the fields whose names -are in -.IR string . -Each field name can be followed by a number which says -how many such fields should be reversed. -If no number is given for a field, all such fields will be reversed. -. -.TP -.BI search-ignore\*n\ fields -While searching for keys in databases for which no index exists, -ignore the contents of -.IR fields . -Initially, fields -.B XYZ -are ignored. -. -.TP -.BI search-truncate\*n\ n -Only require the first -.I n -characters of keys to be given. -In effect when searching for a given key -words in the database are truncated to the maximum of -.I n -and the length of the key. -Initially -.I n -is\ 6. -. -.TP -.BI short-label\*n\ string -.I string -is a label expression that specifies an alternative (usually shorter) -style of label. -This is used when the -.B # -flag is given in the citation. -When using author-date style labels, the identity of the author -or authors is sometimes clear from the context, and so it -may be desirable to omit the author or authors from the label. -The -.B short-label -command will typically be used to specify a label containing just -a date and possibly a disambiguating letter. -. -.TP -.BI sort\*n\ string -Sort references according to -.BR string . -References will automatically be accumulated. -.I string -should be a list of field names, each followed by a number, -indicating how many fields with the name should be used for sorting. -.B + -can be used to indicate that all the fields with the name should be used. -Also -.B .\& -can be used to indicate the references should be sorted using the -(tentative) label. -(The -.B "Label expressions" -subsection describes the concept of a tentative label.) -. -.TP -.B sort-adjacent-labels\*n -Sort labels that are adjacent in the text according to their -position in the reference list. -This command should usually be given if the -.B abbreviate-label-ranges -command has been given, -or if the label expression contains a -.B <> -expression. -This will have no effect unless references are being accumulated. -. -. -.SS Label expressions -. -.LP -Label expressions can be evaluated both normally and tentatively. -The result of normal evaluation is used for output. -The result of tentative evaluation, called the -.IR "tentative label" , -is used to gather the information -that normal evaluation needs to disambiguate the label. -Label expressions specified by the -.B date-as-label -and -.B short-label -commands are not evaluated tentatively. -Normal and tentative evaluation are the same for all types -of expression other than -.BR @ , -.BR * , -and -.B % -expressions. -The description below applies to normal evaluation, -except where otherwise specified. -. -.TP -.I field -.TQ -.I field\ n -The -.IR n -th -part of -.IR field . -If -.I n -is omitted, it defaults to\ 1. -. -.TP -.BI ' string ' -The characters in -.I string -literally. -. -.TP -.B @ -All the authors joined as specified by the -.B join-authors -command. -The whole of each author's name will be used. -However, if the references are sorted by author -(that is the sort specification starts with -.BR A+ ), -then authors' last names will be used instead, provided that this does -not introduce ambiguity, -and also an initial subsequence of the authors may be used -instead of all the authors, again provided that this does not -introduce ambiguity. -The use of only the last name for the -.IR i -th -author of some reference -is considered to be ambiguous if -there is some other reference, -such that the first -.IR i \|-\|1 -authors of the references are the same, -the -.IR i -th -authors are not the same, -but the -.IR i -th -authors' last names are the same. -A proper initial subsequence of the sequence -of authors for some reference is considered to be ambiguous if there is -a reference with some other sequence of authors which also has -that subsequence as a proper initial subsequence. -When an initial subsequence of authors is used, the remaining -authors are replaced by the string specified by the -.B et-al -command; -this command may also specify additional requirements that must be -met before an initial subsequence can be used. -.B @ -tentatively evaluates to a canonical representation of the authors, -such that authors that compare equally for sorting purpose -will have the same representation. -. -.TP -.BI % n -.TQ -.B %a -.TQ -.B %A -.TQ -.B %i -.TQ -.B %I -The serial number of the reference formatted according to the character -following the -.BR % . -The serial number of a reference is\ 1 plus the number of earlier references -with same tentative label as this reference. -These expressions tentatively evaluate to an empty string. -. -.TP -.IB expr * -If there is another reference with the same tentative label as -this reference, then -.IR expr , -otherwise an empty string. -It tentatively evaluates to an empty string. -. -.TP -.IB expr + n -.TQ -.IB expr \- n -The first -.RB ( + ) -or last -.RB ( \- ) -.I n -upper or lower case letters or digits of -.IR expr . -Troff special characters (such as -.BR \e('a ) -count as a single letter. -Accent strings are retained but do not count towards the total. -. -.TP -.IB expr .l -.I expr -converted to lowercase. -. -.TP -.IB expr .u -.I expr -converted to uppercase. -. -.TP -.IB expr .c -.I expr -converted to caps and small caps. -. -.TP -.IB expr .r -.I expr -reversed so that the last name is first. -. -.TP -.IB expr .a -.I expr -with first names abbreviated. -Note that fields specified in the -.B abbreviate -command are abbreviated before any labels are evaluated. -Thus -.B .a -is useful only when you want a field to be abbreviated in a label -but not in a reference. -. -.TP -.IB expr .y -The year part of -.IR expr . -. -.TP -.IB expr .+y -The part of -.I expr -before the year, or the whole of -.I expr -if it does not contain a year. -. -.TP -.IB expr .\-y -The part of -.I expr -after the year, or an empty string if -.I expr -does not contain a year. -. -.TP -.IB expr .n -The last name part of -.IR expr . -. -.TP -.IB expr1 \(ti expr2 -.I expr1 -except that if the last character of -.I expr1 -is -.B \- -then it will be replaced by -.IR expr2 . -. -.TP -.I expr1\ expr2 -The concatenation of -.I expr1 -and -.IR expr2 . -. -.TP -.IB expr1 | expr2 -If -.I expr1 -is non-empty then -.I expr1 -otherwise -.IR expr2 . -. -.TP -.IB expr1 & expr2 -If -.I expr1 -is non-empty -then -.I expr2 -otherwise an empty string. -. -.TP -.IB expr1 ? expr2 : expr3 -If -.I expr1 -is non-empty -then -.I expr2 -otherwise -.IR expr3 . -. -.TP -.BI < expr > -The label is in two parts, which are separated by -.IR expr . -Two adjacent two-part labels which have the same first part will be -merged by appending the second part of the second label onto the first -label separated by the string specified in the -.B separate-label-second-parts -command (initially, a comma followed by a space); the resulting label -will also be a two-part label with the same first part as before -merging, and so additional labels can be merged into it. -Note that it is permissible for the first part to be empty; -this maybe desirable for expressions used in the -.B short-label -command. -. -.TP -.BI ( expr ) -The same as -.IR expr . -Used for grouping. -. -.LP -The above expressions are listed in order of precedence -(highest first); -.B & -and -.B | -have the same precedence. -. -. -.SS Macro interface -Each reference starts with a call to the macro -.BR ]- . -The string -.B [F -will be defined to be the label for this reference, -unless the -.B no-label-in-reference -command has been given. -There then follows a series of string definitions, -one for each field: -string -.BI [ X -corresponds to field -.IR X . -The number register -.B [P -is set to\ 1 if the -.B P -field contains a range of pages. -The -.BR [T , -.B [A -and -.B [O -number registers are set to\ 1 according as the -.BR T , -.B A -and -.B O -fields end with one of the characters -.BR .?! . -The -.B [E -number register will be set to\ 1 if the -.B [E -string contains more than one name. -The reference is followed by a call to the -.B ][ -macro. -The first argument to this macro gives a number representing -the type of the reference. -If a reference contains a -.B J -field, it will be classified as type\ 1, -otherwise if it contains a -.B B -field, it will type\ 3, -otherwise if it contains a -.B G -or -.B R -field it will be type\ 4, -otherwise if contains a -.B I -field it will be type\ 2, -otherwise it will be type\ 0. -The second argument is a symbolic name for the type: -.BR other , -.BR journal-article , -.BR book , -.B article-in-book -or -.BR tech-report . -Groups of references that have been accumulated -or are produced by the -.B bibliography -command are preceded by a call to the -.B ]< -macro and followed by a call to the -.B ]> -macro. -. -. -. -.SH FILES -. -.Tp \w'\fB@DEFAULT_INDEX@'u+2n -.B @DEFAULT_INDEX@ -Default database. -. -.TP -.IB file @INDEX_SUFFIX@ -Index files. -. -. -. -.SH ENVIRONMENT -. -.Tp \w'\fBREFER'u+2n -.B REFER -If set, overrides the default database. -. -. -. -.SH "SEE ALSO" -.BR @g@indxbib (@MAN1EXT@), -.BR @g@lookbib (@MAN1EXT@), -.BR lkbib (@MAN1EXT@) -.br -. -. -. -.SH BUGS -In label expressions, -.B <> -expressions are ignored inside -.BI . char -expressions. -. -.\" Local Variables: -.\" mode: nroff -.\" End: diff --git a/contrib/groff/src/preproc/refer/token.cpp b/contrib/groff/src/preproc/refer/token.cpp deleted file mode 100644 index 1eb30062f8a3..000000000000 --- a/contrib/groff/src/preproc/refer/token.cpp +++ /dev/null @@ -1,378 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2001 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "refer.h" -#include "token.h" - -#define TOKEN_TABLE_SIZE 1009 -// I believe in Icelandic thorn sorts after z. -#define THORN_SORT_KEY "{" - -struct token_table_entry { - const char *tok; - token_info ti; - token_table_entry(); -}; - -token_table_entry token_table[TOKEN_TABLE_SIZE]; -int ntokens = 0; - -static void skip_name(const char **ptr, const char *end) -{ - if (*ptr < end) { - switch (*(*ptr)++) { - case '(': - if (*ptr < end) { - *ptr += 1; - if (*ptr < end) - *ptr += 1; - } - break; - case '[': - while (*ptr < end) - if (*(*ptr)++ == ']') - break; - break; - } - } -} - -int get_token(const char **ptr, const char *end) -{ - if (*ptr >= end) - return 0; - char c = *(*ptr)++; - if (c == '\\' && *ptr < end) { - switch (**ptr) { - default: - *ptr += 1; - break; - case '(': - case '[': - skip_name(ptr, end); - break; - case '*': - case 'f': - *ptr += 1; - skip_name(ptr, end); - break; - } - } - return 1; -} - -token_info::token_info() -: type(TOKEN_OTHER), sort_key(0), other_case(0) -{ -} - -void token_info::set(token_type t, const char *sk, const char *oc) -{ - assert(oc == 0 || t == TOKEN_UPPER || t == TOKEN_LOWER); - type = t; - sort_key = sk; - other_case = oc; -} - -void token_info::sortify(const char *start, const char *end, string &result) - const -{ - if (sort_key) - result += sort_key; - else if (type == TOKEN_UPPER || type == TOKEN_LOWER) { - for (; start < end; start++) - if (csalpha(*start)) - result += cmlower(*start); - } -} - -int token_info::sortify_non_empty(const char *start, const char *end) const -{ - if (sort_key) - return *sort_key != '\0'; - if (type != TOKEN_UPPER && type != TOKEN_LOWER) - return 0; - for (; start < end; start++) - if (csalpha(*start)) - return 1; - return 0; -} - - -void token_info::lower_case(const char *start, const char *end, - string &result) const -{ - if (type != TOKEN_UPPER) { - while (start < end) - result += *start++; - } - else if (other_case) - result += other_case; - else { - while (start < end) - result += cmlower(*start++); - } -} - -void token_info::upper_case(const char *start, const char *end, - string &result) const -{ - if (type != TOKEN_LOWER) { - while (start < end) - result += *start++; - } - else if (other_case) - result += other_case; - else { - while (start < end) - result += cmupper(*start++); - } -} - -token_table_entry::token_table_entry() -: tok(0) -{ -} - -static void store_token(const char *tok, token_type typ, - const char *sk = 0, const char *oc = 0) -{ - unsigned n = hash_string(tok, strlen(tok)) % TOKEN_TABLE_SIZE; - for (;;) { - if (token_table[n].tok == 0) { - if (++ntokens == TOKEN_TABLE_SIZE) - assert(0); - token_table[n].tok = tok; - break; - } - if (strcmp(tok, token_table[n].tok) == 0) - break; - if (n == 0) - n = TOKEN_TABLE_SIZE - 1; - else - --n; - } - token_table[n].ti.set(typ, sk, oc); -} - - -token_info default_token_info; - -const token_info *lookup_token(const char *start, const char *end) -{ - unsigned n = hash_string(start, end - start) % TOKEN_TABLE_SIZE; - for (;;) { - if (token_table[n].tok == 0) - break; - if (strlen(token_table[n].tok) == size_t(end - start) - && memcmp(token_table[n].tok, start, end - start) == 0) - return &(token_table[n].ti); - if (n == 0) - n = TOKEN_TABLE_SIZE - 1; - else - --n; - } - return &default_token_info; -} - -static void init_ascii() -{ - const char *p; - for (p = "abcdefghijklmnopqrstuvwxyz"; *p; p++) { - char buf[2]; - buf[0] = *p; - buf[1] = '\0'; - store_token(strsave(buf), TOKEN_LOWER); - buf[0] = cmupper(buf[0]); - store_token(strsave(buf), TOKEN_UPPER); - } - for (p = "0123456789"; *p; p++) { - char buf[2]; - buf[0] = *p; - buf[1] = '\0'; - const char *s = strsave(buf); - store_token(s, TOKEN_OTHER, s); - } - for (p = ".,:;?!"; *p; p++) { - char buf[2]; - buf[0] = *p; - buf[1] = '\0'; - store_token(strsave(buf), TOKEN_PUNCT); - } - store_token("-", TOKEN_HYPHEN); -} - -static void store_letter(const char *lower, const char *upper, - const char *sort_key = 0) -{ - store_token(lower, TOKEN_LOWER, sort_key, upper); - store_token(upper, TOKEN_UPPER, sort_key, lower); -} - -static void init_letter(unsigned char uc_code, unsigned char lc_code, - const char *sort_key) -{ - char lbuf[2]; - lbuf[0] = lc_code; - lbuf[1] = 0; - char ubuf[2]; - ubuf[0] = uc_code; - ubuf[1] = 0; - store_letter(strsave(lbuf), strsave(ubuf), sort_key); -} - -static void init_latin1() -{ - init_letter(0xc0, 0xe0, "a"); - init_letter(0xc1, 0xe1, "a"); - init_letter(0xc2, 0xe2, "a"); - init_letter(0xc3, 0xe3, "a"); - init_letter(0xc4, 0xe4, "a"); - init_letter(0xc5, 0xe5, "a"); - init_letter(0xc6, 0xe6, "ae"); - init_letter(0xc7, 0xe7, "c"); - init_letter(0xc8, 0xe8, "e"); - init_letter(0xc9, 0xe9, "e"); - init_letter(0xca, 0xea, "e"); - init_letter(0xcb, 0xeb, "e"); - init_letter(0xcc, 0xec, "i"); - init_letter(0xcd, 0xed, "i"); - init_letter(0xce, 0xee, "i"); - init_letter(0xcf, 0xef, "i"); - - init_letter(0xd0, 0xf0, "d"); - init_letter(0xd1, 0xf1, "n"); - init_letter(0xd2, 0xf2, "o"); - init_letter(0xd3, 0xf3, "o"); - init_letter(0xd4, 0xf4, "o"); - init_letter(0xd5, 0xf5, "o"); - init_letter(0xd6, 0xf6, "o"); - init_letter(0xd8, 0xf8, "o"); - init_letter(0xd9, 0xf9, "u"); - init_letter(0xda, 0xfa, "u"); - init_letter(0xdb, 0xfb, "u"); - init_letter(0xdc, 0xfc, "u"); - init_letter(0xdd, 0xfd, "y"); - init_letter(0xde, 0xfe, THORN_SORT_KEY); - - store_token("\337", TOKEN_LOWER, "ss", "SS"); - store_token("\377", TOKEN_LOWER, "y", "Y"); -} - -static void init_two_char_letter(char l1, char l2, char u1, char u2, - const char *sk = 0) -{ - char buf[6]; - buf[0] = '\\'; - buf[1] = '('; - buf[2] = l1; - buf[3] = l2; - buf[4] = '\0'; - const char *p = strsave(buf); - buf[2] = u1; - buf[3] = u2; - store_letter(p, strsave(buf), sk); - buf[1] = '['; - buf[4] = ']'; - buf[5] = '\0'; - p = strsave(buf); - buf[2] = l1; - buf[3] = l2; - store_letter(strsave(buf), p, sk); - -} - -static void init_special_chars() -{ - const char *p; - for (p = "':^`~"; *p; p++) - for (const char *q = "aeiouy"; *q; q++) { - // Use a variable to work around bug in gcc 2.0 - char c = cmupper(*q); - init_two_char_letter(*p, *q, *p, c); - } - for (p = "/l/o~n,coeaeij"; *p; p += 2) { - // Use variables to work around bug in gcc 2.0 - char c0 = cmupper(p[0]); - char c1 = cmupper(p[1]); - init_two_char_letter(p[0], p[1], c0, c1); - } - init_two_char_letter('v', 's', 'v', 'S', "s"); - init_two_char_letter('v', 'z', 'v', 'Z', "z"); - init_two_char_letter('o', 'a', 'o', 'A', "a"); - init_two_char_letter('T', 'p', 'T', 'P', THORN_SORT_KEY); - init_two_char_letter('-', 'd', '-', 'D'); - - store_token("\\(ss", TOKEN_LOWER, 0, "SS"); - store_token("\\[ss]", TOKEN_LOWER, 0, "SS"); - - store_token("\\(Sd", TOKEN_LOWER, "d", "\\(-D"); - store_token("\\[Sd]", TOKEN_LOWER, "d", "\\[-D]"); - store_token("\\(hy", TOKEN_HYPHEN); - store_token("\\[hy]", TOKEN_HYPHEN); - store_token("\\(en", TOKEN_RANGE_SEP); - store_token("\\[en]", TOKEN_RANGE_SEP); -} - -static void init_strings() -{ - char buf[6]; - buf[0] = '\\'; - buf[1] = '*'; - for (const char *p = "'`^^,:~v_o./;"; *p; p++) { - buf[2] = *p; - buf[3] = '\0'; - store_token(strsave(buf), TOKEN_ACCENT); - buf[2] = '['; - buf[3] = *p; - buf[4] = ']'; - buf[5] = '\0'; - store_token(strsave(buf), TOKEN_ACCENT); - } - - // -ms special letters - store_letter("\\*(th", "\\*(Th", THORN_SORT_KEY); - store_letter("\\*[th]", "\\*[Th]", THORN_SORT_KEY); - store_letter("\\*(d-", "\\*(D-"); - store_letter("\\*[d-]", "\\*[D-]"); - store_letter("\\*(ae", "\\*(Ae", "ae"); - store_letter("\\*[ae]", "\\*[Ae]", "ae"); - store_letter("\\*(oe", "\\*(Oe", "oe"); - store_letter("\\*[oe]", "\\*[Oe]", "oe"); - - store_token("\\*3", TOKEN_LOWER, "y", "Y"); - store_token("\\*8", TOKEN_LOWER, "ss", "SS"); - store_token("\\*q", TOKEN_LOWER, "o", "O"); -} - -struct token_initer { - token_initer(); -}; - -static token_initer the_token_initer; - -token_initer::token_initer() -{ - init_ascii(); - init_latin1(); - init_special_chars(); - init_strings(); - default_token_info.set(TOKEN_OTHER); -} diff --git a/contrib/groff/src/preproc/refer/token.h b/contrib/groff/src/preproc/refer/token.h deleted file mode 100644 index 7d3404942fa7..000000000000 --- a/contrib/groff/src/preproc/refer/token.h +++ /dev/null @@ -1,88 +0,0 @@ -// -*- 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -enum token_type { - TOKEN_OTHER, - TOKEN_UPPER, - TOKEN_LOWER, - TOKEN_ACCENT, - TOKEN_PUNCT, - TOKEN_HYPHEN, - TOKEN_RANGE_SEP -}; - -class token_info { -private: - token_type type; - const char *sort_key; - const char *other_case; -public: - token_info(); - void set(token_type, const char *sk = 0, const char *oc = 0); - void lower_case(const char *start, const char *end, string &result) const; - void upper_case(const char *start, const char *end, string &result) const; - void sortify(const char *start, const char *end, string &result) const; - int sortify_non_empty(const char *start, const char *end) const; - int is_upper() const; - int is_lower() const; - int is_accent() const; - int is_other() const; - int is_punct() const; - int is_hyphen() const; - int is_range_sep() const; -}; - -inline int token_info::is_upper() const -{ - return type == TOKEN_UPPER; -} - -inline int token_info::is_lower() const -{ - return type == TOKEN_LOWER; -} - -inline int token_info::is_accent() const -{ - return type == TOKEN_ACCENT; -} - -inline int token_info::is_other() const -{ - return type == TOKEN_OTHER; -} - -inline int token_info::is_punct() const -{ - return type == TOKEN_PUNCT; -} - -inline int token_info::is_hyphen() const -{ - return type == TOKEN_HYPHEN; -} - -inline int token_info::is_range_sep() const -{ - return type == TOKEN_RANGE_SEP; -} - -int get_token(const char **ptr, const char *end); -const token_info *lookup_token(const char *start, const char *end); diff --git a/contrib/groff/src/preproc/soelim/Makefile.sub b/contrib/groff/src/preproc/soelim/Makefile.sub deleted file mode 100644 index 2e15c0086e82..000000000000 --- a/contrib/groff/src/preproc/soelim/Makefile.sub +++ /dev/null @@ -1,7 +0,0 @@ -PROG=soelim$(EXEEXT) -MAN1=soelim.n -XLIBS=$(LIBGROFF) -MLIB=$(LIBM) -OBJS=soelim.$(OBJEXT) -CCSRCS=$(srcdir)/soelim.cpp -NAMEPREFIX=$(g) diff --git a/contrib/groff/src/preproc/soelim/TODO b/contrib/groff/src/preproc/soelim/TODO deleted file mode 100644 index f2a3924ef89f..000000000000 --- a/contrib/groff/src/preproc/soelim/TODO +++ /dev/null @@ -1 +0,0 @@ -Understand .pso. diff --git a/contrib/groff/src/preproc/soelim/soelim.cpp b/contrib/groff/src/preproc/soelim/soelim.cpp deleted file mode 100644 index 235dfe664430..000000000000 --- a/contrib/groff/src/preproc/soelim/soelim.cpp +++ /dev/null @@ -1,308 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989-1992, 2000, 2001, 2003, 2004, 2005 - 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "lib.h" - -#include -#include -#include -#include -#include "errarg.h" -#include "error.h" -#include "stringclass.h" -#include "nonposix.h" -#include "searchpath.h" - -// The include search path initially contains only the current directory. -static search_path include_search_path(0, 0, 0, 1); - -int compatible_flag = 0; -int raw_flag = 0; -int tex_flag = 0; - -extern "C" const char *Version_string; - -int do_file(const char *filename); - - -void usage(FILE *stream) -{ - fprintf(stream, "usage: %s [ -Crtv ] [ -I file ] [ files ]\n", program_name); -} - -int main(int argc, char **argv) -{ - program_name = argv[0]; - int opt; - static const struct option long_options[] = { - { "help", no_argument, 0, CHAR_MAX + 1 }, - { "version", no_argument, 0, 'v' }, - { NULL, 0, 0, 0 } - }; - while ((opt = getopt_long(argc, argv, "CI:rtv", long_options, NULL)) != EOF) - switch (opt) { - case 'v': - { - printf("GNU soelim (groff) version %s\n", Version_string); - exit(0); - break; - } - case 'C': - compatible_flag = 1; - break; - case 'I': - include_search_path.command_line_dir(optarg); - break; - case 'r': - raw_flag = 1; - break; - case 't': - tex_flag = 1; - break; - case CHAR_MAX + 1: // --help - usage(stdout); - exit(0); - break; - case '?': - usage(stderr); - exit(1); - break; - default: - assert(0); - } - int nbad = 0; - if (optind >= argc) - nbad += !do_file("-"); - else - for (int i = optind; i < argc; i++) - nbad += !do_file(argv[i]); - if (ferror(stdout) || fflush(stdout) < 0) - fatal("output error"); - return nbad != 0; -} - -void set_location() -{ - if(!raw_flag) { - if(!tex_flag) - printf(".lf %d %s\n", current_lineno, current_filename); - else - printf("%% file %s, line %d\n", current_filename, current_lineno); - } -} - -void do_so(const char *line) -{ - const char *p = line; - while (*p == ' ') - p++; - string filename; - int success = 1; - for (const char *q = p; - success && *q != '\0' && *q != '\n' && *q != ' '; - q++) - if (*q == '\\') { - switch (*++q) { - case 'e': - case '\\': - filename += '\\'; - break; - case ' ': - filename += ' '; - break; - default: - success = 0; - break; - } - } - else - filename += char(*q); - if (success && filename.length() > 0) { - filename += '\0'; - const char *fn = current_filename; - int ln = current_lineno; - current_lineno--; - if (do_file(filename.contents())) { - current_filename = fn; - current_lineno = ln; - set_location(); - return; - } - current_lineno++; - } - fputs(".so", stdout); - fputs(line, stdout); -} - -int do_file(const char *filename) -{ - char *file_name_in_path = 0; - FILE *fp = include_search_path.open_file_cautious(filename, - &file_name_in_path); - int err = errno; - string whole_filename(file_name_in_path ? file_name_in_path : filename); - whole_filename += '\0'; - a_delete file_name_in_path; - if (fp == 0) { - error("can't open `%1': %2", whole_filename.contents(), strerror(err)); - return 0; - } - current_filename = whole_filename.contents(); - current_lineno = 1; - set_location(); - enum { START, MIDDLE, HAD_DOT, HAD_s, HAD_so, HAD_l, HAD_lf } state = START; - for (;;) { - int c = getc(fp); - if (c == EOF) - break; - switch (state) { - case START: - if (c == '.') - state = HAD_DOT; - else { - putchar(c); - if (c == '\n') { - current_lineno++; - state = START; - } - else - state = MIDDLE; - } - break; - case MIDDLE: - putchar(c); - if (c == '\n') { - current_lineno++; - state = START; - } - break; - case HAD_DOT: - if (c == 's') - state = HAD_s; - else if (c == 'l') - state = HAD_l; - else { - putchar('.'); - putchar(c); - if (c == '\n') { - current_lineno++; - state = START; - } - else - state = MIDDLE; - } - break; - case HAD_s: - if (c == 'o') - state = HAD_so; - else { - putchar('.'); - putchar('s'); - putchar(c); - if (c == '\n') { - current_lineno++; - state = START; - } - else - state = MIDDLE; - } - break; - case HAD_so: - if (c == ' ' || c == '\n' || compatible_flag) { - string line; - for (; c != EOF && c != '\n'; c = getc(fp)) - line += c; - current_lineno++; - line += '\n'; - line += '\0'; - do_so(line.contents()); - state = START; - } - else { - fputs(".so", stdout); - putchar(c); - state = MIDDLE; - } - break; - case HAD_l: - if (c == 'f') - state = HAD_lf; - else { - putchar('.'); - putchar('l'); - putchar(c); - if (c == '\n') { - current_lineno++; - state = START; - } - else - state = MIDDLE; - } - break; - case HAD_lf: - if (c == ' ' || c == '\n' || compatible_flag) { - string line; - for (; c != EOF && c != '\n'; c = getc(fp)) - line += c; - current_lineno++; - line += '\n'; - line += '\0'; - interpret_lf_args(line.contents()); - printf(".lf%s", line.contents()); - state = START; - } - else { - fputs(".lf", stdout); - putchar(c); - state = MIDDLE; - } - break; - default: - assert(0); - } - } - switch (state) { - case HAD_DOT: - fputs(".\n", stdout); - break; - case HAD_l: - fputs(".l\n", stdout); - break; - case HAD_s: - fputs(".s\n", stdout); - break; - case HAD_lf: - fputs(".lf\n", stdout); - break; - case HAD_so: - fputs(".so\n", stdout); - break; - case MIDDLE: - putc('\n', stdout); - break; - case START: - break; - } - if (fp != stdin) - fclose(fp); - current_filename = 0; - return 1; -} diff --git a/contrib/groff/src/preproc/soelim/soelim.man b/contrib/groff/src/preproc/soelim/soelim.man deleted file mode 100644 index fb17e3644fca..000000000000 --- a/contrib/groff/src/preproc/soelim/soelim.man +++ /dev/null @@ -1,216 +0,0 @@ -'\" p -.ig -Copyright (C) 1989-2000, 2001, 2003, 2004 Free Software Foundation, Inc. - -Permission is granted to make and distribute verbatim copies of -this manual provided the copyright notice and this permission notice -are preserved on all copies. - -Permission is granted to copy and distribute modified versions of this -manual under the conditions for verbatim copying, provided that the -entire resulting derived work is distributed under the terms of a -permission notice identical to this one. - -Permission is granted to copy and distribute translations of this -manual into another language, under the above conditions for modified -versions, except that this permission notice may be included in -translations approved by the Free Software Foundation instead of in -the original English. -.. -. -.mso pic.tmac -. -.TH @G@SOELIM @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@" -. -.SH NAME -@g@soelim \- interpret .so requests in groff input -. -.SH SYNOPSIS -.B @g@soelim -[ -.B \-Crtv -] -[ -.BI \-I dir -] -[ -.IR files \|.\|.\|.\| -] -. -.PP -It is possible to have whitespace between the -.B \-I -command line option and its parameter. -. -.SH DESCRIPTION -.B @g@soelim -reads -.I files -and replaces lines of the form -.IP -.BI .so\ file -.LP -by the contents of -.IR file . -It is useful if files included with -.B so -need to be preprocessed. -Normally, -.B @g@soelim -should be invoked with the -.B \-s -option of -.BR groff . -. -.PP -Note that there must be no whitespace between the leading dot and -the two characters `s' and `o'. Otherwise, only -.B groff -interprets the -.B .so -request (and -.B soelim -ignores it). -. -.SH OPTIONS -.TP -.B \-C -Recognize -.B .so -even when followed by a character other than space or newline. -. -.TP -.BI \-I dir -This option may be used to specify a directory to search for -files (both those on the command line and those named in -.B \&.so -requests). -The current directory is always searched first. -This option may be specified more than once, -the directories will be searched in the order specified. -No directory search is performed for files specified using an absolute path. -. -.TP -.B \-r -Do not add .lf requests (for general use, with non-groff files). -. -.TP -.B \-t -Don't emit .lf requests but TeX comment lines (starting with `%') giving -the current file and line number. -. -.TP -.B \-v -Print the version number. -. -.SH USAGE -The normal processing sequence of groff is this: -. -.PP -.ie t \{\ -.PS -box invisible width 0.5 height 0.4 "input" "file"; -move to last box .bottom; -down; -arrow 0.3; -box invisible width 0.8 height 0.2 "preprocessor"; -move to last box .right -right; -arrow 0.3; -A: box invisible width 0.35 height 0.2 "troff"; -move to last box .top; -up; -move 0.3; -box invisible width 0.6 height 0.4 "sourced" "file"; -line <- up 0.3 from A.top; -move to A.right; -right; -arrow 0.3; -box invisible width 0.85 height 0.2 "postprocessor"; -move to last box .bottom; -down; -arrow 0.3; -box invisible width 0.5 height 0.4 "output" "file" -.PE -.\} -.el \{\ -.nf - input sourced - file file - | | - v v - preprocessor -> troff -> postprocessor - | - v - output - file -.fi -.\} -.PP -. -That is, files sourced with -.B .so -are normally read -.I only -by -.B troff -(the actual formatter). -.B soelim -is -.I not -required for -.B troff -to source files. -. -.PP -If a file to be sourced should also be preprocessed, it must -already be read -.I before -the input file passes through the preprocessor. -This is handled by -.BR soelim : -. -.PP -.ie t \{\ -.PS -box invisible width 0.5 height 0.4 "input" "file"; -move to last box .bottom; -down; -arrow 0.3; -A: box invisible width 0.5 height 0.2 "soelim"; -line <- 0.3; -box invisible width 0.5 height 0.4 "sourced" "file"; -move to A.right; -right; -arrow 0.3; -box invisible width 0.8 height 0.2 "preprocessor"; -arrow 0.3; -box invisible width 0.35 height 0.2 "troff"; -arrow 0.3 -box invisible width 0.85 height 0.2 "postprocessor"; -move to last box .bottom; -down; -arrow 0.3; -box invisible width 0.5 height 0.4 "output" "file" -.PE -.\} -.el \{\ -.nf - input - file - | - v - soelim -> preprocessor -> troff -> postprocessor - ^ | - | v - sourced output - file file -.fi -.\} -. -.SH "SEE ALSO" -.BR groff (@MAN1EXT@) -. -.\" Local Variables: -.\" mode: nroff -.\" End: diff --git a/contrib/groff/src/preproc/tbl/Makefile.sub b/contrib/groff/src/preproc/tbl/Makefile.sub deleted file mode 100644 index bea28b35164d..000000000000 --- a/contrib/groff/src/preproc/tbl/Makefile.sub +++ /dev/null @@ -1,13 +0,0 @@ -PROG=tbl$(EXEEXT) -MAN1=tbl.n -XLIBS=$(LIBGROFF) -MLIB=$(LIBM) -OBJS=\ - main.$(OBJEXT) \ - table.$(OBJEXT) -CCSRCS=\ - $(srcdir)/main.cpp \ - $(srcdir)/table.cpp -HDRS=\ - $(srcdir)/table.h -NAMEPREFIX=$(g) diff --git a/contrib/groff/src/preproc/tbl/main.cpp b/contrib/groff/src/preproc/tbl/main.cpp deleted file mode 100644 index d79adb0bf831..000000000000 --- a/contrib/groff/src/preproc/tbl/main.cpp +++ /dev/null @@ -1,1590 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003, 2004, 2005 - 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "table.h" - -#define MAX_POINT_SIZE 99 -#define MAX_VERTICAL_SPACING 72 - -extern "C" const char *Version_string; - -int compatible_flag = 0; - -class table_input { - FILE *fp; - enum { START, MIDDLE, - REREAD_T, REREAD_TE, REREAD_E, - LEADER_1, LEADER_2, LEADER_3, LEADER_4, - END, ERROR } state; - string unget_stack; -public: - table_input(FILE *); - int get(); - int ended() { return unget_stack.empty() && state == END; } - void unget(char); -}; - -table_input::table_input(FILE *p) -: fp(p), state(START) -{ -} - -void table_input::unget(char c) -{ - assert(c != '\0'); - unget_stack += c; - if (c == '\n') - current_lineno--; -} - -int table_input::get() -{ - int len = unget_stack.length(); - if (len != 0) { - unsigned char c = unget_stack[len - 1]; - unget_stack.set_length(len - 1); - if (c == '\n') - current_lineno++; - return c; - } - int c; - for (;;) { - switch (state) { - case START: - if ((c = getc(fp)) == '.') { - if ((c = getc(fp)) == 'T') { - if ((c = getc(fp)) == 'E') { - if (compatible_flag) { - state = END; - return EOF; - } - else { - c = getc(fp); - if (c != EOF) - ungetc(c, fp); - if (c == EOF || c == ' ' || c == '\n') { - state = END; - return EOF; - } - state = REREAD_TE; - return '.'; - } - } - else { - if (c != EOF) - ungetc(c, fp); - state = REREAD_T; - return '.'; - } - } - else { - if (c != EOF) - ungetc(c, fp); - state = MIDDLE; - return '.'; - } - } - else if (c == EOF) { - state = ERROR; - return EOF; - } - else { - if (c == '\n') - current_lineno++; - else { - state = MIDDLE; - if (c == '\0') { - error("invalid input character code 0"); - break; - } - } - return c; - } - break; - case MIDDLE: - // handle line continuation and uninterpreted leader character - if ((c = getc(fp)) == '\\') { - c = getc(fp); - if (c == '\n') - c = getc(fp); // perhaps state ought to be START now - else if (c == 'a' && compatible_flag) { - state = LEADER_1; - return '\\'; - } - else { - if (c != EOF) - ungetc(c, fp); - c = '\\'; - } - } - if (c == EOF) { - state = ERROR; - return EOF; - } - else { - if (c == '\n') { - state = START; - current_lineno++; - } - else if (c == '\0') { - error("invalid input character code 0"); - break; - } - return c; - } - case REREAD_T: - state = MIDDLE; - return 'T'; - case REREAD_TE: - state = REREAD_E; - return 'T'; - case REREAD_E: - state = MIDDLE; - return 'E'; - case LEADER_1: - state = LEADER_2; - return '*'; - case LEADER_2: - state = LEADER_3; - return '('; - case LEADER_3: - state = LEADER_4; - return PREFIX_CHAR; - case LEADER_4: - state = MIDDLE; - return LEADER_CHAR; - case END: - case ERROR: - return EOF; - } - } -} - -void process_input_file(FILE *); -void process_table(table_input &in); - -void process_input_file(FILE *fp) -{ - enum { START, MIDDLE, HAD_DOT, HAD_T, HAD_TS, HAD_l, HAD_lf } state; - state = START; - int c; - while ((c = getc(fp)) != EOF) - switch (state) { - case START: - if (c == '.') - state = HAD_DOT; - else { - if (c == '\n') - current_lineno++; - else - state = MIDDLE; - putchar(c); - } - break; - case MIDDLE: - if (c == '\n') { - current_lineno++; - state = START; - } - putchar(c); - break; - case HAD_DOT: - if (c == 'T') - state = HAD_T; - else if (c == 'l') - state = HAD_l; - else { - putchar('.'); - putchar(c); - if (c == '\n') { - current_lineno++; - state = START; - } - else - state = MIDDLE; - } - break; - case HAD_T: - if (c == 'S') - state = HAD_TS; - else { - putchar('.'); - putchar('T'); - putchar(c); - if (c == '\n') { - current_lineno++; - state = START; - } - else - state = MIDDLE; - } - break; - case HAD_TS: - if (c == ' ' || c == '\n' || compatible_flag) { - putchar('.'); - putchar('T'); - putchar('S'); - while (c != '\n') { - if (c == EOF) { - error("end of file at beginning of table"); - return; - } - putchar(c); - c = getc(fp); - } - putchar('\n'); - current_lineno++; - { - table_input input(fp); - process_table(input); - set_troff_location(current_filename, current_lineno); - if (input.ended()) { - fputs(".TE", stdout); - while ((c = getc(fp)) != '\n') { - if (c == EOF) { - putchar('\n'); - return; - } - putchar(c); - } - putchar('\n'); - current_lineno++; - } - } - state = START; - } - else { - fputs(".TS", stdout); - putchar(c); - state = MIDDLE; - } - break; - case HAD_l: - if (c == 'f') - state = HAD_lf; - else { - putchar('.'); - putchar('l'); - putchar(c); - if (c == '\n') { - current_lineno++; - state = START; - } - else - state = MIDDLE; - } - break; - case HAD_lf: - if (c == ' ' || c == '\n' || compatible_flag) { - string line; - while (c != EOF) { - line += c; - if (c == '\n') { - current_lineno++; - break; - } - c = getc(fp); - } - line += '\0'; - interpret_lf_args(line.contents()); - printf(".lf%s", line.contents()); - state = START; - } - else { - fputs(".lf", stdout); - putchar(c); - state = MIDDLE; - } - break; - default: - assert(0); - } - switch(state) { - case START: - break; - case MIDDLE: - putchar('\n'); - break; - case HAD_DOT: - fputs(".\n", stdout); - break; - case HAD_l: - fputs(".l\n", stdout); - break; - case HAD_T: - fputs(".T\n", stdout); - break; - case HAD_lf: - fputs(".lf\n", stdout); - break; - case HAD_TS: - fputs(".TS\n", stdout); - break; - } - if (fp != stdin) - fclose(fp); -} - -struct options { - unsigned flags; - int linesize; - char delim[2]; - char tab_char; - char decimal_point_char; - - options(); -}; - -options::options() -: flags(0), linesize(0), tab_char('\t'), decimal_point_char('.') -{ - delim[0] = delim[1] = '\0'; -} - -// Return non-zero if p and q are the same ignoring case. - -int strieq(const char *p, const char *q) -{ - for (; cmlower(*p) == cmlower(*q); p++, q++) - if (*p == '\0') - return 1; - return 0; -} - -// return 0 if we should give up in this table - -options *process_options(table_input &in) -{ - options *opt = new options; - string line; - int level = 0; - for (;;) { - int c = in.get(); - if (c == EOF) { - int i = line.length(); - while (--i >= 0) - in.unget(line[i]); - return opt; - } - if (c == '\n') { - in.unget(c); - int i = line.length(); - while (--i >= 0) - in.unget(line[i]); - return opt; - } - else if (c == '(') - level++; - else if (c == ')') - level--; - else if (c == ';' && level == 0) { - line += '\0'; - break; - } - line += c; - } - if (line.empty()) - return opt; - char *p = &line[0]; - for (;;) { - while (!csalpha(*p) && *p != '\0') - p++; - if (*p == '\0') - break; - char *q = p; - while (csalpha(*q)) - q++; - char *arg = 0; - if (*q != '(' && *q != '\0') - *q++ = '\0'; - while (csspace(*q)) - q++; - if (*q == '(') { - *q++ = '\0'; - arg = q; - while (*q != ')' && *q != '\0') - q++; - if (*q == '\0') - error("missing `)'"); - else - *q++ = '\0'; - } - if (*p == '\0') { - if (arg) - error("argument without option"); - } - else if (strieq(p, "tab")) { - if (!arg) - error("`tab' option requires argument in parentheses"); - else { - if (arg[0] == '\0' || arg[1] != '\0') - error("argument to `tab' option must be a single character"); - else - opt->tab_char = arg[0]; - } - } - else if (strieq(p, "linesize")) { - if (!arg) - error("`linesize' option requires argument in parentheses"); - else { - if (sscanf(arg, "%d", &opt->linesize) != 1) - error("bad linesize `%s'", arg); - else if (opt->linesize <= 0) { - error("linesize must be positive"); - opt->linesize = 0; - } - } - } - else if (strieq(p, "delim")) { - if (!arg) - error("`delim' option requires argument in parentheses"); - else if (arg[0] == '\0' || arg[1] == '\0' || arg[2] != '\0') - error("argument to `delim' option must be two characters"); - else { - opt->delim[0] = arg[0]; - opt->delim[1] = arg[1]; - } - } - else if (strieq(p, "center") || strieq(p, "centre")) { - if (arg) - error("`center' option does not take an argument"); - opt->flags |= table::CENTER; - } - else if (strieq(p, "expand")) { - if (arg) - error("`expand' option does not take an argument"); - opt->flags |= table::EXPAND; - } - else if (strieq(p, "box") || strieq(p, "frame")) { - if (arg) - error("`box' option does not take an argument"); - opt->flags |= table::BOX; - } - else if (strieq(p, "doublebox") || strieq(p, "doubleframe")) { - if (arg) - error("`doublebox' option does not take an argument"); - opt->flags |= table::DOUBLEBOX; - } - else if (strieq(p, "allbox")) { - if (arg) - error("`allbox' option does not take an argument"); - opt->flags |= table::ALLBOX; - } - else if (strieq(p, "nokeep")) { - if (arg) - error("`nokeep' option does not take an argument"); - opt->flags |= table::NOKEEP; - } - else if (strieq(p, "nospaces")) { - if (arg) - error("`nospaces' option does not take an argument"); - opt->flags |= table::NOSPACES; - } - else if (strieq(p, "decimalpoint")) { - if (!arg) - error("`decimalpoint' option requires argument in parentheses"); - else { - if (arg[0] == '\0' || arg[1] != '\0') - error("argument to `decimalpoint' option must be a single character"); - else - opt->decimal_point_char = arg[0]; - } - } - else { - error("unrecognised global option `%1'", p); - // delete opt; - // return 0; - } - p = q; - } - return opt; -} - -entry_modifier::entry_modifier() -: vertical_alignment(CENTER), zero_width(0), stagger(0) -{ - vertical_spacing.inc = vertical_spacing.val = 0; - point_size.inc = point_size.val = 0; -} - -entry_modifier::~entry_modifier() -{ -} - -entry_format::entry_format() : type(FORMAT_LEFT) -{ -} - -entry_format::entry_format(format_type t) : type(t) -{ -} - -void entry_format::debug_print() const -{ - switch (type) { - case FORMAT_LEFT: - putc('l', stderr); - break; - case FORMAT_CENTER: - putc('c', stderr); - break; - case FORMAT_RIGHT: - putc('r', stderr); - break; - case FORMAT_NUMERIC: - putc('n', stderr); - break; - case FORMAT_ALPHABETIC: - putc('a', stderr); - break; - case FORMAT_SPAN: - putc('s', stderr); - break; - case FORMAT_VSPAN: - putc('^', stderr); - break; - case FORMAT_HLINE: - putc('_', stderr); - break; - case FORMAT_DOUBLE_HLINE: - putc('=', stderr); - break; - default: - assert(0); - break; - } - if (point_size.val != 0) { - putc('p', stderr); - if (point_size.inc > 0) - putc('+', stderr); - else if (point_size.inc < 0) - putc('-', stderr); - fprintf(stderr, "%d ", point_size.val); - } - if (vertical_spacing.val != 0) { - putc('v', stderr); - if (vertical_spacing.inc > 0) - putc('+', stderr); - else if (vertical_spacing.inc < 0) - putc('-', stderr); - fprintf(stderr, "%d ", vertical_spacing.val); - } - if (!font.empty()) { - putc('f', stderr); - put_string(font, stderr); - putc(' ', stderr); - } - if (!macro.empty()) { - putc('m', stderr); - put_string(macro, stderr); - putc(' ', stderr); - } - switch (vertical_alignment) { - case entry_modifier::CENTER: - break; - case entry_modifier::TOP: - putc('t', stderr); - break; - case entry_modifier::BOTTOM: - putc('d', stderr); - break; - } - if (zero_width) - putc('z', stderr); - if (stagger) - putc('u', stderr); -} - -struct format { - int nrows; - int ncolumns; - int *separation; - string *width; - char *equal; - entry_format **entry; - char **vline; - - format(int nr, int nc); - ~format(); - void add_rows(int n); -}; - -format::format(int nr, int nc) : nrows(nr), ncolumns(nc) -{ - int i; - separation = ncolumns > 1 ? new int[ncolumns - 1] : 0; - for (i = 0; i < ncolumns-1; i++) - separation[i] = -1; - width = new string[ncolumns]; - equal = new char[ncolumns]; - for (i = 0; i < ncolumns; i++) - equal[i] = 0; - entry = new entry_format *[nrows]; - for (i = 0; i < nrows; i++) - entry[i] = new entry_format[ncolumns]; - vline = new char*[nrows]; - for (i = 0; i < nrows; i++) { - vline[i] = new char[ncolumns+1]; - for (int j = 0; j < ncolumns+1; j++) - vline[i][j] = 0; - } -} - -void format::add_rows(int n) -{ - int i; - char **old_vline = vline; - vline = new char*[nrows + n]; - for (i = 0; i < nrows; i++) - vline[i] = old_vline[i]; - a_delete old_vline; - for (i = 0; i < n; i++) { - vline[nrows + i] = new char[ncolumns + 1]; - for (int j = 0; j < ncolumns + 1; j++) - vline[nrows + i][j] = 0; - } - entry_format **old_entry = entry; - entry = new entry_format *[nrows + n]; - for (i = 0; i < nrows; i++) - entry[i] = old_entry[i]; - a_delete old_entry; - for (i = 0; i < n; i++) - entry[nrows + i] = new entry_format[ncolumns]; - nrows += n; -} - -format::~format() -{ - a_delete separation; - ad_delete(ncolumns) width; - a_delete equal; - for (int i = 0; i < nrows; i++) { - a_delete vline[i]; - ad_delete(ncolumns) entry[i]; - } - a_delete vline; - a_delete entry; -} - -struct input_entry_format : public entry_format { - input_entry_format *next; - string width; - int separation; - int vline; - int pre_vline; - int last_column; - int equal; - input_entry_format(format_type, input_entry_format * = 0); - ~input_entry_format(); - void debug_print(); -}; - -input_entry_format::input_entry_format(format_type t, input_entry_format *p) -: entry_format(t), next(p) -{ - separation = -1; - last_column = 0; - vline = 0; - pre_vline = 0; - equal = 0; -} - -input_entry_format::~input_entry_format() -{ -} - -void free_input_entry_format_list(input_entry_format *list) -{ - while (list) { - input_entry_format *tem = list; - list = list->next; - delete tem; - } -} - -void input_entry_format::debug_print() -{ - int i; - for (i = 0; i < pre_vline; i++) - putc('|', stderr); - entry_format::debug_print(); - if (!width.empty()) { - putc('w', stderr); - putc('(', stderr); - put_string(width, stderr); - putc(')', stderr); - } - if (equal) - putc('e', stderr); - if (separation >= 0) - fprintf(stderr, "%d", separation); - for (i = 0; i < vline; i++) - putc('|', stderr); - if (last_column) - putc(',', stderr); -} - -// Return zero if we should give up on this table. -// If this is a continuation format line, current_format will be the current -// format line. - -format *process_format(table_input &in, options *opt, - format *current_format = 0) -{ - input_entry_format *list = 0; - int c = in.get(); - for (;;) { - int pre_vline = 0; - int got_format = 0; - int got_period = 0; - format_type t = FORMAT_LEFT; - for (;;) { - if (c == EOF) { - error("end of input while processing format"); - free_input_entry_format_list(list); - return 0; - } - switch (c) { - case 'n': - case 'N': - t = FORMAT_NUMERIC; - got_format = 1; - break; - case 'a': - case 'A': - got_format = 1; - t = FORMAT_ALPHABETIC; - break; - case 'c': - case 'C': - got_format = 1; - t = FORMAT_CENTER; - break; - case 'l': - case 'L': - got_format = 1; - t = FORMAT_LEFT; - break; - case 'r': - case 'R': - got_format = 1; - t = FORMAT_RIGHT; - break; - case 's': - case 'S': - got_format = 1; - t = FORMAT_SPAN; - break; - case '^': - got_format = 1; - t = FORMAT_VSPAN; - break; - case '_': - case '-': // tbl also accepts this - got_format = 1; - t = FORMAT_HLINE; - break; - case '=': - got_format = 1; - t = FORMAT_DOUBLE_HLINE; - break; - case '.': - got_period = 1; - break; - case '|': - pre_vline++; - break; - case ' ': - case '\t': - case '\n': - break; - default: - if (c == opt->tab_char) - break; - error("unrecognised format `%1'", char(c)); - free_input_entry_format_list(list); - return 0; - } - if (got_period) - break; - c = in.get(); - if (got_format) - break; - } - if (got_period) - break; - list = new input_entry_format(t, list); - if (pre_vline) - list->pre_vline = pre_vline; - int success = 1; - do { - switch (c) { - case 't': - case 'T': - c = in.get(); - list->vertical_alignment = entry_modifier::TOP; - break; - case 'd': - case 'D': - c = in.get(); - list->vertical_alignment = entry_modifier::BOTTOM; - break; - case 'u': - case 'U': - c = in.get(); - list->stagger = 1; - break; - case 'z': - case 'Z': - c = in.get(); - list->zero_width = 1; - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - int w = 0; - do { - w = w*10 + (c - '0'); - c = in.get(); - } while (c != EOF && csdigit(c)); - list->separation = w; - } - break; - case 'f': - case 'F': - do { - c = in.get(); - } while (c == ' ' || c == '\t'); - if (c == EOF) { - error("missing font name"); - break; - } - if (c == '(') { - for (;;) { - c = in.get(); - if (c == EOF || c == ' ' || c == '\t') { - error("missing `)'"); - break; - } - if (c == ')') { - c = in.get(); - break; - } - list->font += char(c); - } - } - else { - list->font = c; - char cc = c; - c = in.get(); - if (!csdigit(cc) - && c != EOF && c != ' ' && c != '\t' && c != '.' && c != '\n') { - list->font += char(c); - c = in.get(); - } - } - break; - case 'x': - case 'X': - do { - c = in.get(); - } while (c == ' ' || c == '\t'); - if (c == EOF) { - error("missing macro name"); - break; - } - if (c == '(') { - for (;;) { - c = in.get(); - if (c == EOF || c == ' ' || c == '\t') { - error("missing `)'"); - break; - } - if (c == ')') { - c = in.get(); - break; - } - list->macro += char(c); - } - } - else { - list->macro = c; - char cc = c; - c = in.get(); - if (!csdigit(cc) - && c != EOF && c != ' ' && c != '\t' && c != '.' && c != '\n') { - list->macro += char(c); - c = in.get(); - } - } - break; - case 'v': - case 'V': - c = in.get(); - list->vertical_spacing.val = 0; - list->vertical_spacing.inc = 0; - if (c == '+' || c == '-') { - list->vertical_spacing.inc = (c == '+' ? 1 : -1); - c = in.get(); - } - if (c == EOF || !csdigit(c)) { - error("`v' modifier must be followed by number"); - list->vertical_spacing.inc = 0; - } - else { - do { - list->vertical_spacing.val *= 10; - list->vertical_spacing.val += c - '0'; - c = in.get(); - } while (c != EOF && csdigit(c)); - } - if (list->vertical_spacing.val > MAX_VERTICAL_SPACING - || list->vertical_spacing.val < -MAX_VERTICAL_SPACING) { - error("unreasonable vertical spacing"); - list->vertical_spacing.val = 0; - list->vertical_spacing.inc = 0; - } - break; - case 'p': - case 'P': - c = in.get(); - list->point_size.val = 0; - list->point_size.inc = 0; - if (c == '+' || c == '-') { - list->point_size.inc = (c == '+' ? 1 : -1); - c = in.get(); - } - if (c == EOF || !csdigit(c)) { - error("`p' modifier must be followed by number"); - list->point_size.inc = 0; - } - else { - do { - list->point_size.val *= 10; - list->point_size.val += c - '0'; - c = in.get(); - } while (c != EOF && csdigit(c)); - } - if (list->point_size.val > MAX_POINT_SIZE - || list->point_size.val < -MAX_POINT_SIZE) { - error("unreasonable point size"); - list->point_size.val = 0; - list->point_size.inc = 0; - } - break; - case 'w': - case 'W': - c = in.get(); - while (c == ' ' || c == '\t') - c = in.get(); - if (c == '(') { - list->width = ""; - c = in.get(); - while (c != ')') { - if (c == EOF || c == '\n') { - error("missing `)'"); - free_input_entry_format_list(list); - return 0; - } - list->width += c; - c = in.get(); - } - c = in.get(); - } - else { - if (c == '+' || c == '-') { - list->width = char(c); - c = in.get(); - } - else - list->width = ""; - if (c == EOF || !csdigit(c)) - error("bad argument for `w' modifier"); - else { - do { - list->width += char(c); - c = in.get(); - } while (c != EOF && csdigit(c)); - } - } - break; - case 'e': - case 'E': - c = in.get(); - list->equal++; - break; - case '|': - c = in.get(); - list->vline++; - break; - case 'B': - case 'b': - c = in.get(); - list->font = "B"; - break; - case 'I': - case 'i': - c = in.get(); - list->font = "I"; - break; - case ' ': - case '\t': - c = in.get(); - break; - default: - if (c == opt->tab_char) - c = in.get(); - else - success = 0; - break; - } - } while (success); - if (list->vline > 2) { - list->vline = 2; - error("more than 2 vertical bars between key letters"); - } - if (c == '\n' || c == ',') { - c = in.get(); - list->last_column = 1; - } - } - if (c == '.') { - do { - c = in.get(); - } while (c == ' ' || c == '\t'); - if (c != '\n') { - error("`.' not last character on line"); - free_input_entry_format_list(list); - return 0; - } - } - if (!list) { - error("no format"); - free_input_entry_format_list(list); - return 0; - } - list->last_column = 1; - // now reverse the list so that the first row is at the beginning - input_entry_format *rev = 0; - while (list != 0) { - input_entry_format *tem = list->next; - list->next = rev; - rev = list; - list = tem; - } - list = rev; - input_entry_format *tem; - -#if 0 - for (tem = list; tem; tem = tem->next) - tem->debug_print(); - putc('\n', stderr); -#endif - // compute number of columns and rows - int ncolumns = 0; - int nrows = 0; - int col = 0; - for (tem = list; tem; tem = tem->next) { - if (tem->last_column) { - if (col >= ncolumns) - ncolumns = col + 1; - col = 0; - nrows++; - } - else - col++; - } - int row; - format *f; - if (current_format) { - if (ncolumns > current_format->ncolumns) { - error("cannot increase the number of columns in a continued format"); - free_input_entry_format_list(list); - return 0; - } - f = current_format; - row = f->nrows; - f->add_rows(nrows); - } - else { - f = new format(nrows, ncolumns); - row = 0; - } - col = 0; - for (tem = list; tem; tem = tem->next) { - f->entry[row][col] = *tem; - if (col < ncolumns-1) { - // use the greatest separation - if (tem->separation > f->separation[col]) { - if (current_format) - error("cannot change column separation in continued format"); - else - f->separation[col] = tem->separation; - } - } - else if (tem->separation >= 0) - error("column separation specified for last column"); - if (tem->equal && !f->equal[col]) { - if (current_format) - error("cannot change which columns are equal in continued format"); - else - f->equal[col] = 1; - } - if (!tem->width.empty()) { - // use the last width - if (!f->width[col].empty() && f->width[col] != tem->width) - error("multiple widths for column %1", col+1); - f->width[col] = tem->width; - } - if (tem->pre_vline) { - assert(col == 0); - f->vline[row][col] = tem->pre_vline; - } - f->vline[row][col+1] = tem->vline; - if (tem->last_column) { - row++; - col = 0; - } - else - col++; - } - free_input_entry_format_list(list); - for (col = 0; col < ncolumns; col++) { - entry_format *e = f->entry[f->nrows-1] + col; - if (e->type != FORMAT_HLINE - && e->type != FORMAT_DOUBLE_HLINE - && e->type != FORMAT_SPAN) - break; - } - if (col >= ncolumns) { - error("last row of format is all lines"); - delete f; - return 0; - } - return f; -} - -table *process_data(table_input &in, format *f, options *opt) -{ - char tab_char = opt->tab_char; - int ncolumns = f->ncolumns; - int current_row = 0; - int format_index = 0; - int give_up = 0; - enum { DATA_INPUT_LINE, TROFF_INPUT_LINE, SINGLE_HLINE, DOUBLE_HLINE } type; - table *tbl = new table(ncolumns, opt->flags, opt->linesize, - opt->decimal_point_char); - if (opt->delim[0] != '\0') - tbl->set_delim(opt->delim[0], opt->delim[1]); - for (;;) { - // first determine what type of line this is - int c = in.get(); - if (c == EOF) - break; - if (c == '.') { - int d = in.get(); - if (d != EOF && csdigit(d)) { - in.unget(d); - type = DATA_INPUT_LINE; - } - else { - in.unget(d); - type = TROFF_INPUT_LINE; - } - } - else if (c == '_' || c == '=') { - int d = in.get(); - if (d == '\n') { - if (c == '_') - type = SINGLE_HLINE; - else - type = DOUBLE_HLINE; - } - else { - in.unget(d); - type = DATA_INPUT_LINE; - } - } - else { - type = DATA_INPUT_LINE; - } - switch (type) { - case DATA_INPUT_LINE: - { - string input_entry; - if (format_index >= f->nrows) - format_index = f->nrows - 1; - // A format row that is all lines doesn't use up a data line. - while (format_index < f->nrows - 1) { - int cnt; - for (cnt = 0; cnt < ncolumns; cnt++) { - entry_format *e = f->entry[format_index] + cnt; - if (e->type != FORMAT_HLINE - && e->type != FORMAT_DOUBLE_HLINE - // Unfortunately tbl treats a span as needing data. - // && e->type != FORMAT_SPAN - ) - break; - } - if (cnt < ncolumns) - break; - for (cnt = 0; cnt < ncolumns; cnt++) - tbl->add_entry(current_row, cnt, input_entry, - f->entry[format_index] + cnt, current_filename, - current_lineno); - tbl->add_vlines(current_row, f->vline[format_index]); - format_index++; - current_row++; - } - entry_format *line_format = f->entry[format_index]; - int col = 0; - int row_comment = 0; - for (;;) { - if (c == tab_char || c == '\n') { - int ln = current_lineno; - if (c == '\n') - --ln; - if ((opt->flags & table::NOSPACES)) - input_entry.remove_spaces(); - while (col < ncolumns - && line_format[col].type == FORMAT_SPAN) { - tbl->add_entry(current_row, col, "", &line_format[col], - current_filename, ln); - col++; - } - if (c == '\n' && input_entry.length() == 2 - && input_entry[0] == 'T' && input_entry[1] == '{') { - input_entry = ""; - ln++; - enum { - START, MIDDLE, GOT_T, GOT_RIGHT_BRACE, GOT_DOT, - GOT_l, GOT_lf, END - } state = START; - while (state != END) { - c = in.get(); - if (c == EOF) - break; - switch (state) { - case START: - if (c == 'T') - state = GOT_T; - else if (c == '.') - state = GOT_DOT; - else { - input_entry += c; - if (c != '\n') - state = MIDDLE; - } - break; - case GOT_T: - if (c == '}') - state = GOT_RIGHT_BRACE; - else { - input_entry += 'T'; - input_entry += c; - state = c == '\n' ? START : MIDDLE; - } - break; - case GOT_DOT: - if (c == 'l') - state = GOT_l; - else { - input_entry += '.'; - input_entry += c; - state = c == '\n' ? START : MIDDLE; - } - break; - case GOT_l: - if (c == 'f') - state = GOT_lf; - else { - input_entry += ".l"; - input_entry += c; - state = c == '\n' ? START : MIDDLE; - } - break; - case GOT_lf: - if (c == ' ' || c == '\n' || compatible_flag) { - string args; - input_entry += ".lf"; - while (c != EOF) { - args += c; - if (c == '\n') - break; - c = in.get(); - } - args += '\0'; - interpret_lf_args(args.contents()); - // remove the '\0' - args.set_length(args.length() - 1); - input_entry += args; - state = START; - } - else { - input_entry += ".lf"; - input_entry += c; - state = MIDDLE; - } - break; - case GOT_RIGHT_BRACE: - if ((opt->flags & table::NOSPACES)) { - while (c == ' ') - c = in.get(); - if (c == EOF) - break; - } - if (c == '\n' || c == tab_char) - state = END; - else { - input_entry += 'T'; - input_entry += '}'; - input_entry += c; - state = MIDDLE; - } - break; - case MIDDLE: - if (c == '\n') - state = START; - input_entry += c; - break; - case END: - default: - assert(0); - } - } - if (c == EOF) { - error("end of data in middle of text block"); - give_up = 1; - break; - } - } - if (col >= ncolumns) { - if (!input_entry.empty()) { - if (input_entry.length() >= 2 - && input_entry[0] == '\\' - && input_entry[1] == '"') - row_comment = 1; - else if (!row_comment) { - if (c == '\n') - in.unget(c); - input_entry += '\0'; - error("excess data entry `%1' discarded", - input_entry.contents()); - if (c == '\n') - (void)in.get(); - } - } - } - else - tbl->add_entry(current_row, col, input_entry, - &line_format[col], current_filename, ln); - col++; - if (c == '\n') - break; - input_entry = ""; - } - else - input_entry += c; - c = in.get(); - if (c == EOF) - break; - } - if (give_up) - break; - input_entry = ""; - for (; col < ncolumns; col++) - tbl->add_entry(current_row, col, input_entry, &line_format[col], - current_filename, current_lineno - 1); - tbl->add_vlines(current_row, f->vline[format_index]); - current_row++; - format_index++; - } - break; - case TROFF_INPUT_LINE: - { - string line; - int ln = current_lineno; - for (;;) { - line += c; - if (c == '\n') - break; - c = in.get(); - if (c == EOF) { - break; - } - } - tbl->add_text_line(current_row, line, current_filename, ln); - if (line.length() >= 4 - && line[0] == '.' && line[1] == 'T' && line[2] == '&') { - format *newf = process_format(in, opt, f); - if (newf == 0) - give_up = 1; - else - f = newf; - } - if (line.length() >= 3 - && line[0] == '.' && line[1] == 'l' && line[2] == 'f') { - line += '\0'; - interpret_lf_args(line.contents() + 3); - } - } - break; - case SINGLE_HLINE: - tbl->add_single_hline(current_row); - break; - case DOUBLE_HLINE: - tbl->add_double_hline(current_row); - break; - default: - assert(0); - } - if (give_up) - break; - } - if (!give_up && current_row == 0) { - error("no real data"); - give_up = 1; - } - if (give_up) { - delete tbl; - return 0; - } - // Do this here rather than at the beginning in case continued formats - // change it. - int i; - for (i = 0; i < ncolumns - 1; i++) - if (f->separation[i] >= 0) - tbl->set_column_separation(i, f->separation[i]); - for (i = 0; i < ncolumns; i++) - if (!f->width[i].empty()) - tbl->set_minimum_width(i, f->width[i]); - for (i = 0; i < ncolumns; i++) - if (f->equal[i]) - tbl->set_equal_column(i); - return tbl; -} - -void process_table(table_input &in) -{ - options *opt = 0; - format *form = 0; - table *tbl = 0; - if ((opt = process_options(in)) != 0 - && (form = process_format(in, opt)) != 0 - && (tbl = process_data(in, form, opt)) != 0) { - tbl->print(); - delete tbl; - } - else { - error("giving up on this table"); - while (in.get() != EOF) - ; - } - delete opt; - delete form; - if (!in.ended()) - error("premature end of file"); -} - -static void usage(FILE *stream) -{ - fprintf(stream, "usage: %s [ -vC ] [ files... ]\n", program_name); -} - -int main(int argc, char **argv) -{ - program_name = argv[0]; - static char stderr_buf[BUFSIZ]; - setbuf(stderr, stderr_buf); - int opt; - static const struct option long_options[] = { - { "help", no_argument, 0, CHAR_MAX + 1 }, - { "version", no_argument, 0, 'v' }, - { NULL, 0, 0, 0 } - }; - while ((opt = getopt_long(argc, argv, "vCT:", long_options, NULL)) != EOF) - switch (opt) { - case 'C': - compatible_flag = 1; - break; - case 'v': - { - printf("GNU tbl (groff) version %s\n", Version_string); - exit(0); - break; - } - case 'T': - // I'm sick of getting bug reports from IRIX users - break; - case CHAR_MAX + 1: // --help - usage(stdout); - exit(0); - break; - case '?': - usage(stderr); - exit(1); - break; - default: - assert(0); - } - printf(".if !\\n(.g .ab GNU tbl requires GNU troff.\n" - ".if !dTS .ds TS\n" - ".if !dTE .ds TE\n"); - if (argc > optind) { - for (int i = optind; i < argc; i++) - if (argv[i][0] == '-' && argv[i][1] == '\0') { - current_filename = "-"; - current_lineno = 1; - printf(".lf 1 -\n"); - process_input_file(stdin); - } - else { - errno = 0; - FILE *fp = fopen(argv[i], "r"); - if (fp == 0) - fatal("can't open `%1': %2", argv[i], strerror(errno)); - else { - current_lineno = 1; - current_filename = argv[i]; - printf(".lf 1 %s\n", current_filename); - process_input_file(fp); - } - } - } - else { - current_filename = "-"; - current_lineno = 1; - printf(".lf 1 -\n"); - process_input_file(stdin); - } - if (ferror(stdout) || fflush(stdout) < 0) - fatal("output error"); - return 0; -} - diff --git a/contrib/groff/src/preproc/tbl/table.cpp b/contrib/groff/src/preproc/tbl/table.cpp deleted file mode 100644 index 8312386aafee..000000000000 --- a/contrib/groff/src/preproc/tbl/table.cpp +++ /dev/null @@ -1,2778 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2003, 2004 - 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "table.h" - -#define BAR_HEIGHT ".25m" -#define DOUBLE_LINE_SEP "2p" -#define HALF_DOUBLE_LINE_SEP "1p" -#define LINE_SEP "2p" -#define BODY_DEPTH ".25m" - -const int DEFAULT_COLUMN_SEPARATION = 3; - -#define DELIMITER_CHAR "\\[tbl]" -#define SEPARATION_FACTOR_REG PREFIX "sep" -#define BOTTOM_REG PREFIX "bot" -#define RESET_MACRO_NAME PREFIX "init" -#define LINESIZE_REG PREFIX "lps" -#define TOP_REG PREFIX "top" -#define CURRENT_ROW_REG PREFIX "crow" -#define LAST_PASSED_ROW_REG PREFIX "passed" -#define TRANSPARENT_STRING_NAME PREFIX "trans" -#define QUOTE_STRING_NAME PREFIX "quote" -#define SECTION_DIVERSION_NAME PREFIX "section" -#define SECTION_DIVERSION_FLAG_REG PREFIX "sflag" -#define SAVED_VERTICAL_POS_REG PREFIX "vert" -#define NEED_BOTTOM_RULE_REG PREFIX "brule" -#define KEEP_MACRO_NAME PREFIX "keep" -#define RELEASE_MACRO_NAME PREFIX "release" -#define SAVED_FONT_REG PREFIX "fnt" -#define SAVED_SIZE_REG PREFIX "sz" -#define SAVED_FILL_REG PREFIX "fll" -#define SAVED_INDENT_REG PREFIX "ind" -#define SAVED_CENTER_REG PREFIX "cent" -#define TABLE_DIVERSION_NAME PREFIX "table" -#define TABLE_DIVERSION_FLAG_REG PREFIX "tflag" -#define TABLE_KEEP_MACRO_NAME PREFIX "tkeep" -#define TABLE_RELEASE_MACRO_NAME PREFIX "trelease" -#define NEEDED_REG PREFIX "needed" -#define REPEATED_MARK_MACRO PREFIX "rmk" -#define REPEATED_VPT_MACRO PREFIX "rvpt" -#define SUPPRESS_BOTTOM_REG PREFIX "supbot" -#define SAVED_DN_REG PREFIX "dn" - -// this must be one character -#define COMPATIBLE_REG PREFIX "c" - -#define LEADER_REG PREFIX LEADER - -#define BLOCK_WIDTH_PREFIX PREFIX "tbw" -#define BLOCK_DIVERSION_PREFIX PREFIX "tbd" -#define BLOCK_HEIGHT_PREFIX PREFIX "tbh" -#define SPAN_WIDTH_PREFIX PREFIX "w" -#define SPAN_LEFT_NUMERIC_WIDTH_PREFIX PREFIX "lnw" -#define SPAN_RIGHT_NUMERIC_WIDTH_PREFIX PREFIX "rnw" -#define SPAN_ALPHABETIC_WIDTH_PREFIX PREFIX "aw" -#define COLUMN_SEPARATION_PREFIX PREFIX "cs" -#define ROW_START_PREFIX PREFIX "rs" -#define COLUMN_START_PREFIX PREFIX "cl" -#define COLUMN_END_PREFIX PREFIX "ce" -#define COLUMN_DIVIDE_PREFIX PREFIX "cd" -#define ROW_TOP_PREFIX PREFIX "rt" - -string block_width_reg(int r, int c); -string block_diversion_name(int r, int c); -string block_height_reg(int r, int c); -string span_width_reg(int start_col, int end_col); -string span_left_numeric_width_reg(int start_col, int end_col); -string span_right_numeric_width_reg(int start_col, int end_col); -string span_alphabetic_width_reg(int start_col, int end_col); -string column_separation_reg(int col); -string row_start_reg(int r); -string column_start_reg(int c); -string column_end_reg(int c); -string column_divide_reg(int c); -string row_top_reg(int r); - -void set_inline_modifier(const entry_modifier *); -void restore_inline_modifier(const entry_modifier *m); -void set_modifier(const entry_modifier *); -int find_decimal_point(const char *s, char decimal_point_char, - const char *delim); - -string an_empty_string; -int location_force_filename = 0; - -void printfs(const char *, - const string &arg1 = an_empty_string, - const string &arg2 = an_empty_string, - const string &arg3 = an_empty_string, - const string &arg4 = an_empty_string, - const string &arg5 = an_empty_string); - -void prints(const string &); - -inline void prints(char c) -{ - putchar(c); -} - -inline void prints(const char *s) -{ - fputs(s, stdout); -} - -void prints(const string &s) -{ - if (!s.empty()) - fwrite(s.contents(), 1, s.length(), stdout); -} - -struct horizontal_span { - horizontal_span *next; - int start_col; - int end_col; - horizontal_span(int, int, horizontal_span *); -}; - -class single_line_entry; -class double_line_entry; -class simple_entry; - -class table_entry { -friend class table; - table_entry *next; - int input_lineno; - const char *input_filename; -protected: - int start_row; - int end_row; - int start_col; - int end_col; - const entry_modifier *mod; -public: - void set_location(); - table_entry(const entry_modifier *); - virtual ~table_entry(); - virtual int divert(int ncols, const string *mw, int *sep); - virtual void do_width(); - virtual void do_depth(); - virtual void print() = 0; - virtual void position_vertically() = 0; - virtual single_line_entry *to_single_line_entry(); - virtual double_line_entry *to_double_line_entry(); - virtual simple_entry *to_simple_entry(); - virtual int line_type(); - virtual void note_double_vrule_on_right(int); - virtual void note_double_vrule_on_left(int); -}; - -class simple_entry : public table_entry { -public: - simple_entry(const entry_modifier *); - void print(); - void position_vertically(); - simple_entry *to_simple_entry(); - virtual void add_tab(); - virtual void simple_print(int); -}; - -class empty_entry : public simple_entry { -public: - empty_entry(const entry_modifier *); - int line_type(); -}; - -class text_entry : public simple_entry { -protected: - char *contents; - void print_contents(); -public: - text_entry(char *, const entry_modifier *); - ~text_entry(); -}; - -void text_entry::print_contents() -{ - set_inline_modifier(mod); - prints(contents); - restore_inline_modifier(mod); -} - -class repeated_char_entry : public text_entry { -public: - repeated_char_entry(char *s, const entry_modifier *m); - void simple_print(int); -}; - -class simple_text_entry : public text_entry { -public: - simple_text_entry(char *s, const entry_modifier *m); - void do_width(); -}; - -class left_text_entry : public simple_text_entry { -public: - left_text_entry(char *s, const entry_modifier *m); - void simple_print(int); - void add_tab(); -}; - -class right_text_entry : public simple_text_entry { -public: - right_text_entry(char *s, const entry_modifier *m); - void simple_print(int); - void add_tab(); -}; - -class center_text_entry : public simple_text_entry { -public: - center_text_entry(char *s, const entry_modifier *m); - void simple_print(int); - void add_tab(); -}; - -class numeric_text_entry : public text_entry { - int dot_pos; -public: - numeric_text_entry(char *s, const entry_modifier *m, int pos); - void do_width(); - void simple_print(int); -}; - -class alphabetic_text_entry : public text_entry { -public: - alphabetic_text_entry(char *s, const entry_modifier *m); - void do_width(); - void simple_print(int); - void add_tab(); -}; - -class line_entry : public simple_entry { -protected: - char double_vrule_on_right; - char double_vrule_on_left; -public: - line_entry(const entry_modifier *); - void note_double_vrule_on_right(int); - void note_double_vrule_on_left(int); - void simple_print(int) = 0; -}; - -class single_line_entry : public line_entry { -public: - single_line_entry(const entry_modifier *m); - void simple_print(int); - single_line_entry *to_single_line_entry(); - int line_type(); -}; - -class double_line_entry : public line_entry { -public: - double_line_entry(const entry_modifier *m); - void simple_print(int); - double_line_entry *to_double_line_entry(); - int line_type(); -}; - -class short_line_entry : public simple_entry { -public: - short_line_entry(const entry_modifier *m); - void simple_print(int); - int line_type(); -}; - -class short_double_line_entry : public simple_entry { -public: - short_double_line_entry(const entry_modifier *m); - void simple_print(int); - int line_type(); -}; - -class block_entry : public table_entry { - char *contents; -protected: - void do_divert(int alphabetic, int ncols, const string *mw, int *sep); -public: - block_entry(char *s, const entry_modifier *m); - ~block_entry(); - int divert(int ncols, const string *mw, int *sep); - void do_width(); - void do_depth(); - void position_vertically(); - void print() = 0; -}; - -class left_block_entry : public block_entry { -public: - left_block_entry(char *s, const entry_modifier *m); - void print(); -}; - -class right_block_entry : public block_entry { -public: - right_block_entry(char *s, const entry_modifier *m); - void print(); -}; - -class center_block_entry : public block_entry { -public: - center_block_entry(char *s, const entry_modifier *m); - void print(); -}; - -class alphabetic_block_entry : public block_entry { -public: - alphabetic_block_entry(char *s, const entry_modifier *m); - void print(); - int divert(int ncols, const string *mw, int *sep); -}; - -table_entry::table_entry(const entry_modifier *m) -: next(0), input_lineno(-1), input_filename(0), - start_row(-1), end_row(-1), start_col(-1), end_col(-1), mod(m) -{ -} - -table_entry::~table_entry() -{ -} - -int table_entry::divert(int, const string *, int *) -{ - return 0; -} - -void table_entry::do_width() -{ -} - -single_line_entry *table_entry::to_single_line_entry() -{ - return 0; -} - -double_line_entry *table_entry::to_double_line_entry() -{ - return 0; -} - -simple_entry *table_entry::to_simple_entry() -{ - return 0; -} - -void table_entry::do_depth() -{ -} - -void table_entry::set_location() -{ - set_troff_location(input_filename, input_lineno); -} - -int table_entry::line_type() -{ - return -1; -} - -void table_entry::note_double_vrule_on_right(int) -{ -} - -void table_entry::note_double_vrule_on_left(int) -{ -} - -simple_entry::simple_entry(const entry_modifier *m) : table_entry(m) -{ -} - -void simple_entry::add_tab() -{ - // do nothing -} - -void simple_entry::simple_print(int) -{ - // do nothing -} - -void simple_entry::position_vertically() -{ - if (start_row != end_row) - switch (mod->vertical_alignment) { - case entry_modifier::TOP: - printfs(".sp |\\n[%1]u\n", row_start_reg(start_row)); - break; - case entry_modifier::CENTER: - // Peform the motion in two stages so that the center is rounded - // vertically upwards even if net vertical motion is upwards. - printfs(".sp |\\n[%1]u\n", row_start_reg(start_row)); - printfs(".sp \\n[" BOTTOM_REG "]u-\\n[%1]u-1v/2u\n", - row_start_reg(start_row)); - break; - case entry_modifier::BOTTOM: - printfs(".sp |\\n[%1]u+\\n[" BOTTOM_REG "]u-\\n[%1]u-1v\n", - row_start_reg(start_row)); - break; - default: - assert(0); - } -} - -void simple_entry::print() -{ - prints(".ta"); - add_tab(); - prints('\n'); - set_location(); - prints("\\&"); - simple_print(0); - prints('\n'); -} - -simple_entry *simple_entry::to_simple_entry() -{ - return this; -} - -empty_entry::empty_entry(const entry_modifier *m) -: simple_entry(m) -{ -} - -int empty_entry::line_type() -{ - return 0; -} - -text_entry::text_entry(char *s, const entry_modifier *m) -: simple_entry(m), contents(s) -{ -} - -text_entry::~text_entry() -{ - a_delete contents; -} - -repeated_char_entry::repeated_char_entry(char *s, const entry_modifier *m) -: text_entry(s, m) -{ -} - -void repeated_char_entry::simple_print(int) -{ - printfs("\\h'|\\n[%1]u'", column_start_reg(start_col)); - set_inline_modifier(mod); - printfs("\\l" DELIMITER_CHAR "\\n[%1]u\\&", - span_width_reg(start_col, end_col)); - prints(contents); - prints(DELIMITER_CHAR); - restore_inline_modifier(mod); -} - -simple_text_entry::simple_text_entry(char *s, const entry_modifier *m) -: text_entry(s, m) -{ -} - -void simple_text_entry::do_width() -{ - set_location(); - printfs(".nr %1 \\n[%1]>?\\w" DELIMITER_CHAR, - span_width_reg(start_col, end_col)); - print_contents(); - prints(DELIMITER_CHAR "\n"); -} - -left_text_entry::left_text_entry(char *s, const entry_modifier *m) -: simple_text_entry(s, m) -{ -} - -void left_text_entry::simple_print(int) -{ - printfs("\\h'|\\n[%1]u'", column_start_reg(start_col)); - print_contents(); -} - -// The only point of this is to make `\a' ``work'' as in Unix tbl. Grrr. - -void left_text_entry::add_tab() -{ - printfs(" \\n[%1]u", column_end_reg(end_col)); -} - -right_text_entry::right_text_entry(char *s, const entry_modifier *m) -: simple_text_entry(s, m) -{ -} - -void right_text_entry::simple_print(int) -{ - printfs("\\h'|\\n[%1]u'", column_start_reg(start_col)); - prints("\002\003"); - print_contents(); - prints("\002"); -} - -void right_text_entry::add_tab() -{ - printfs(" \\n[%1]u", column_end_reg(end_col)); -} - -center_text_entry::center_text_entry(char *s, const entry_modifier *m) -: simple_text_entry(s, m) -{ -} - -void center_text_entry::simple_print(int) -{ - printfs("\\h'|\\n[%1]u'", column_start_reg(start_col)); - prints("\002\003"); - print_contents(); - prints("\003\002"); -} - -void center_text_entry::add_tab() -{ - printfs(" \\n[%1]u", column_end_reg(end_col)); -} - -numeric_text_entry::numeric_text_entry(char *s, const entry_modifier *m, int pos) -: text_entry(s, m), dot_pos(pos) -{ -} - -void numeric_text_entry::do_width() -{ - if (dot_pos != 0) { - set_location(); - printfs(".nr %1 0\\w" DELIMITER_CHAR, - block_width_reg(start_row, start_col)); - set_inline_modifier(mod); - for (int i = 0; i < dot_pos; i++) - prints(contents[i]); - restore_inline_modifier(mod); - prints(DELIMITER_CHAR "\n"); - printfs(".nr %1 \\n[%1]>?\\n[%2]\n", - span_left_numeric_width_reg(start_col, end_col), - block_width_reg(start_row, start_col)); - } - else - printfs(".nr %1 0\n", block_width_reg(start_row, start_col)); - if (contents[dot_pos] != '\0') { - set_location(); - printfs(".nr %1 \\n[%1]>?\\w" DELIMITER_CHAR, - span_right_numeric_width_reg(start_col, end_col)); - set_inline_modifier(mod); - prints(contents + dot_pos); - restore_inline_modifier(mod); - prints(DELIMITER_CHAR "\n"); - } -} - -void numeric_text_entry::simple_print(int) -{ - printfs("\\h'|(\\n[%1]u-\\n[%2]u-\\n[%3]u/2u+\\n[%2]u+\\n[%4]u-\\n[%5]u)'", - span_width_reg(start_col, end_col), - span_left_numeric_width_reg(start_col, end_col), - span_right_numeric_width_reg(start_col, end_col), - column_start_reg(start_col), - block_width_reg(start_row, start_col)); - print_contents(); -} - -alphabetic_text_entry::alphabetic_text_entry(char *s, const entry_modifier *m) -: text_entry(s, m) -{ -} - -void alphabetic_text_entry::do_width() -{ - set_location(); - printfs(".nr %1 \\n[%1]>?\\w" DELIMITER_CHAR, - span_alphabetic_width_reg(start_col, end_col)); - print_contents(); - prints(DELIMITER_CHAR "\n"); -} - -void alphabetic_text_entry::simple_print(int) -{ - printfs("\\h'|\\n[%1]u'", column_start_reg(start_col)); - printfs("\\h'\\n[%1]u-\\n[%2]u/2u'", - span_width_reg(start_col, end_col), - span_alphabetic_width_reg(start_col, end_col)); - print_contents(); -} - -// The only point of this is to make `\a' ``work'' as in Unix tbl. Grrr. - -void alphabetic_text_entry::add_tab() -{ - printfs(" \\n[%1]u", column_end_reg(end_col)); -} - -block_entry::block_entry(char *s, const entry_modifier *m) -: table_entry(m), contents(s) -{ -} - -block_entry::~block_entry() -{ - a_delete contents; -} - -void block_entry::position_vertically() -{ - if (start_row != end_row) - switch(mod->vertical_alignment) { - case entry_modifier::TOP: - printfs(".sp |\\n[%1]u\n", row_start_reg(start_row)); - break; - case entry_modifier::CENTER: - // Peform the motion in two stages so that the center is rounded - // vertically upwards even if net vertical motion is upwards. - printfs(".sp |\\n[%1]u\n", row_start_reg(start_row)); - printfs(".sp \\n[" BOTTOM_REG "]u-\\n[%1]u-\\n[%2]u/2u\n", - row_start_reg(start_row), - block_height_reg(start_row, start_col)); - break; - case entry_modifier::BOTTOM: - printfs(".sp |\\n[%1]u+\\n[" BOTTOM_REG "]u-\\n[%1]u-\\n[%2]u\n", - row_start_reg(start_row), - block_height_reg(start_row, start_col)); - break; - default: - assert(0); - } - if (mod->stagger) - prints(".sp -.5v\n"); -} - -int block_entry::divert(int ncols, const string *mw, int *sep) -{ - do_divert(0, ncols, mw, sep); - return 1; -} - -void block_entry::do_divert(int alphabetic, int ncols, const string *mw, - int *sep) -{ - printfs(".di %1\n", block_diversion_name(start_row, start_col)); - prints(".if \\n[" SAVED_FILL_REG "] .fi\n" - ".in 0\n"); - prints(".ll "); - int i; - for (i = start_col; i <= end_col; i++) - if (mw[i].empty()) - break; - if (i > end_col) { - // Every column spanned by this entry has a minimum width. - for (int j = start_col; j <= end_col; j++) { - if (j > start_col) { - if (sep) - printfs("+%1n", as_string(sep[j - 1])); - prints('+'); - } - printfs("(n;%1)", mw[j]); - } - printfs(">?\\n[%1]u", span_width_reg(start_col, end_col)); - } - else - printfs("(u;\\n[%1]>?(\\n[.l]*%2/%3))", - span_width_reg(start_col, end_col), - as_string(end_col - start_col + 1), - as_string(ncols + 1)); - if (alphabetic) - prints("-2n"); - prints("\n"); - prints(".cp \\n(" COMPATIBLE_REG "\n"); - set_modifier(mod); - set_location(); - prints(contents); - prints(".br\n.di\n.cp 0\n"); - if (!mod->zero_width) { - if (alphabetic) { - printfs(".nr %1 \\n[%1]>?(\\n[dl]+2n)\n", - span_width_reg(start_col, end_col)); - printfs(".nr %1 \\n[%1]>?\\n[dl]\n", - span_alphabetic_width_reg(start_col, end_col)); - } - else - printfs(".nr %1 \\n[%1]>?\\n[dl]\n", span_width_reg(start_col, end_col)); - } - printfs(".nr %1 \\n[dn]\n", block_height_reg(start_row, start_col)); - printfs(".nr %1 \\n[dl]\n", block_width_reg(start_row, start_col)); - prints("." RESET_MACRO_NAME "\n" - ".in \\n[" SAVED_INDENT_REG "]u\n" - ".nf\n"); - // the block might have contained .lf commands - location_force_filename = 1; -} - -void block_entry::do_width() -{ - // do nothing; the action happens in divert -} - -void block_entry::do_depth() -{ - printfs(".nr " BOTTOM_REG " \\n[" BOTTOM_REG "]>?(\\n[%1]+\\n[%2])\n", - row_start_reg(start_row), - block_height_reg(start_row, start_col)); -} - -left_block_entry::left_block_entry(char *s, const entry_modifier *m) -: block_entry(s, m) -{ -} - -void left_block_entry::print() -{ - printfs(".in +\\n[%1]u\n", column_start_reg(start_col)); - printfs(".%1\n", block_diversion_name(start_row, start_col)); - prints(".in\n"); -} - -right_block_entry::right_block_entry(char *s, const entry_modifier *m) -: block_entry(s, m) -{ -} - -void right_block_entry::print() -{ - printfs(".in +\\n[%1]u+\\n[%2]u-\\n[%3]u\n", - column_start_reg(start_col), - span_width_reg(start_col, end_col), - block_width_reg(start_row, start_col)); - printfs(".%1\n", block_diversion_name(start_row, start_col)); - prints(".in\n"); -} - -center_block_entry::center_block_entry(char *s, const entry_modifier *m) -: block_entry(s, m) -{ -} - -void center_block_entry::print() -{ - printfs(".in +\\n[%1]u+(\\n[%2]u-\\n[%3]u/2u)\n", - column_start_reg(start_col), - span_width_reg(start_col, end_col), - block_width_reg(start_row, start_col)); - printfs(".%1\n", block_diversion_name(start_row, start_col)); - prints(".in\n"); -} - -alphabetic_block_entry::alphabetic_block_entry(char *s, - const entry_modifier *m) -: block_entry(s, m) -{ -} - -int alphabetic_block_entry::divert(int ncols, const string *mw, int *sep) -{ - do_divert(1, ncols, mw, sep); - return 1; -} - -void alphabetic_block_entry::print() -{ - printfs(".in +\\n[%1]u+(\\n[%2]u-\\n[%3]u/2u)\n", - column_start_reg(start_col), - span_width_reg(start_col, end_col), - span_alphabetic_width_reg(start_col, end_col)); - printfs(".%1\n", block_diversion_name(start_row, start_col)); - prints(".in\n"); -} - -line_entry::line_entry(const entry_modifier *m) -: simple_entry(m), double_vrule_on_right(0), double_vrule_on_left(0) -{ -} - -void line_entry::note_double_vrule_on_right(int is_corner) -{ - double_vrule_on_right = is_corner ? 1 : 2; -} - -void line_entry::note_double_vrule_on_left(int is_corner) -{ - double_vrule_on_left = is_corner ? 1 : 2; -} - -single_line_entry::single_line_entry(const entry_modifier *m) -: line_entry(m) -{ -} - -int single_line_entry::line_type() -{ - return 1; -} - -void single_line_entry::simple_print(int dont_move) -{ - printfs("\\h'|\\n[%1]u", - column_divide_reg(start_col)); - if (double_vrule_on_left) { - prints(double_vrule_on_left == 1 ? "-" : "+"); - prints(HALF_DOUBLE_LINE_SEP); - } - prints("'"); - if (!dont_move) - prints("\\v'-" BAR_HEIGHT "'"); - printfs("\\s[\\n[" LINESIZE_REG "]]" "\\D'l |\\n[%1]u", - column_divide_reg(end_col+1)); - if (double_vrule_on_right) { - prints(double_vrule_on_left == 1 ? "+" : "-"); - prints(HALF_DOUBLE_LINE_SEP); - } - prints("0'\\s0"); - if (!dont_move) - prints("\\v'" BAR_HEIGHT "'"); -} - -single_line_entry *single_line_entry::to_single_line_entry() -{ - return this; -} - -double_line_entry::double_line_entry(const entry_modifier *m) -: line_entry(m) -{ -} - -int double_line_entry::line_type() -{ - return 2; -} - -void double_line_entry::simple_print(int dont_move) -{ - if (!dont_move) - prints("\\v'-" BAR_HEIGHT "'"); - printfs("\\h'|\\n[%1]u", - column_divide_reg(start_col)); - if (double_vrule_on_left) { - prints(double_vrule_on_left == 1 ? "-" : "+"); - prints(HALF_DOUBLE_LINE_SEP); - } - prints("'"); - printfs("\\v'-" HALF_DOUBLE_LINE_SEP "'" - "\\s[\\n[" LINESIZE_REG "]]" - "\\D'l |\\n[%1]u", - column_divide_reg(end_col+1)); - if (double_vrule_on_right) - prints("-" HALF_DOUBLE_LINE_SEP); - prints(" 0'"); - printfs("\\v'" DOUBLE_LINE_SEP "'" - "\\D'l |\\n[%1]u", - column_divide_reg(start_col)); - if (double_vrule_on_right) { - prints(double_vrule_on_left == 1 ? "+" : "-"); - prints(HALF_DOUBLE_LINE_SEP); - } - prints(" 0'"); - prints("\\s0" - "\\v'-" HALF_DOUBLE_LINE_SEP "'"); - if (!dont_move) - prints("\\v'" BAR_HEIGHT "'"); -} - -double_line_entry *double_line_entry::to_double_line_entry() -{ - return this; -} - -short_line_entry::short_line_entry(const entry_modifier *m) -: simple_entry(m) -{ -} - -int short_line_entry::line_type() -{ - return 1; -} - -void short_line_entry::simple_print(int dont_move) -{ - if (mod->stagger) - prints("\\v'-.5v'"); - if (!dont_move) - prints("\\v'-" BAR_HEIGHT "'"); - printfs("\\h'|\\n[%1]u'", column_start_reg(start_col)); - printfs("\\s[\\n[" LINESIZE_REG "]]" - "\\D'l \\n[%1]u 0'" - "\\s0", - span_width_reg(start_col, end_col)); - if (!dont_move) - prints("\\v'" BAR_HEIGHT "'"); - if (mod->stagger) - prints("\\v'.5v'"); -} - -short_double_line_entry::short_double_line_entry(const entry_modifier *m) -: simple_entry(m) -{ -} - -int short_double_line_entry::line_type() -{ - return 2; -} - -void short_double_line_entry::simple_print(int dont_move) -{ - if (mod->stagger) - prints("\\v'-.5v'"); - if (!dont_move) - prints("\\v'-" BAR_HEIGHT "'"); - printfs("\\h'|\\n[%2]u'" - "\\v'-" HALF_DOUBLE_LINE_SEP "'" - "\\s[\\n[" LINESIZE_REG "]]" - "\\D'l \\n[%1]u 0'" - "\\v'" DOUBLE_LINE_SEP "'" - "\\D'l |\\n[%2]u 0'" - "\\s0" - "\\v'-" HALF_DOUBLE_LINE_SEP "'", - span_width_reg(start_col, end_col), - column_start_reg(start_col)); - if (!dont_move) - prints("\\v'" BAR_HEIGHT "'"); - if (mod->stagger) - prints("\\v'.5v'"); -} - -void set_modifier(const entry_modifier *m) -{ - if (!m->font.empty()) - printfs(".ft %1\n", m->font); - if (m->point_size.val != 0) { - prints(".ps "); - if (m->point_size.inc > 0) - prints('+'); - else if (m->point_size.inc < 0) - prints('-'); - printfs("%1\n", as_string(m->point_size.val)); - } - if (m->vertical_spacing.val != 0) { - prints(".vs "); - if (m->vertical_spacing.inc > 0) - prints('+'); - else if (m->vertical_spacing.inc < 0) - prints('-'); - printfs("%1\n", as_string(m->vertical_spacing.val)); - } - if (!m->macro.empty()) - printfs(".%1\n", m->macro); -} - -void set_inline_modifier(const entry_modifier *m) -{ - if (!m->font.empty()) - printfs("\\f[%1]", m->font); - if (m->point_size.val != 0) { - prints("\\s["); - if (m->point_size.inc > 0) - prints('+'); - else if (m->point_size.inc < 0) - prints('-'); - printfs("%1]", as_string(m->point_size.val)); - } - if (m->stagger) - prints("\\v'-.5v'"); -} - -void restore_inline_modifier(const entry_modifier *m) -{ - if (!m->font.empty()) - prints("\\f[\\n[" SAVED_FONT_REG "]]"); - if (m->point_size.val != 0) - prints("\\s[\\n[" SAVED_SIZE_REG "]]"); - if (m->stagger) - prints("\\v'.5v'"); -} - -struct stuff { - stuff *next; - int row; // occurs before row `row' - char printed; // has it been printed? - - stuff(int); - virtual void print(table *) = 0; - virtual ~stuff(); - virtual int is_single_line() { return 0; }; - virtual int is_double_line() { return 0; }; -}; - -stuff::stuff(int r) : next(0), row(r), printed(0) -{ -} - -stuff::~stuff() -{ -} - -struct text_stuff : public stuff { - string contents; - const char *filename; - int lineno; - - text_stuff(const string &, int r, const char *fn, int ln); - ~text_stuff(); - void print(table *); -}; - -text_stuff::text_stuff(const string &s, int r, const char *fn, int ln) -: stuff(r), contents(s), filename(fn), lineno(ln) -{ -} - -text_stuff::~text_stuff() -{ -} - -void text_stuff::print(table *) -{ - printed = 1; - prints(".cp \\n(" COMPATIBLE_REG "\n"); - set_troff_location(filename, lineno); - prints(contents); - prints(".cp 0\n"); - location_force_filename = 1; // it might have been a .lf command -} - -struct single_hline_stuff : public stuff { - single_hline_stuff(int r); - void print(table *); - int is_single_line(); -}; - -single_hline_stuff::single_hline_stuff(int r) : stuff(r) -{ -} - -void single_hline_stuff::print(table *tbl) -{ - printed = 1; - tbl->print_single_hline(row); -} - -int single_hline_stuff::is_single_line() -{ - return 1; -} - -struct double_hline_stuff : stuff { - double_hline_stuff(int r); - void print(table *); - int is_double_line(); -}; - -double_hline_stuff::double_hline_stuff(int r) : stuff(r) -{ -} - -void double_hline_stuff::print(table *tbl) -{ - printed = 1; - tbl->print_double_hline(row); -} - -int double_hline_stuff::is_double_line() -{ - return 1; -} - -struct vertical_rule { - vertical_rule *next; - int start_row; - int end_row; - int col; - char is_double; - string top_adjust; - string bot_adjust; - - vertical_rule(int sr, int er, int c, int dbl, vertical_rule *); - ~vertical_rule(); - void contribute_to_bottom_macro(table *); - void print(); -}; - -vertical_rule::vertical_rule(int sr, int er, int c, int dbl, vertical_rule *p) -: next(p), start_row(sr), end_row(er), col(c), is_double(dbl) -{ -} - -vertical_rule::~vertical_rule() -{ -} - -void vertical_rule::contribute_to_bottom_macro(table *tbl) -{ - printfs(".if \\n[" CURRENT_ROW_REG "]>=%1", - as_string(start_row)); - if (end_row != tbl->get_nrows() - 1) - printfs("&(\\n[" CURRENT_ROW_REG "]<%1)", - as_string(end_row)); - prints(" \\{"); - printfs(".if %1<=\\n[" LAST_PASSED_ROW_REG "] .nr %2 \\n[#T]\n", - as_string(start_row), - row_top_reg(start_row)); - const char *offset_table[3]; - if (is_double) { - offset_table[0] = "-" HALF_DOUBLE_LINE_SEP; - offset_table[1] = "+" HALF_DOUBLE_LINE_SEP; - offset_table[2] = 0; - } - else { - offset_table[0] = ""; - offset_table[1] = 0; - } - for (const char **offsetp = offset_table; *offsetp; offsetp++) { - prints(".sp -1\n" - "\\v'" BODY_DEPTH); - if (!bot_adjust.empty()) - printfs("+%1", bot_adjust); - prints("'"); - printfs("\\h'\\n[%1]u%3'\\s[\\n[" LINESIZE_REG "]]\\D'l 0 |\\n[%2]u-1v", - column_divide_reg(col), - row_top_reg(start_row), - *offsetp); - if (!bot_adjust.empty()) - printfs("-(%1)", bot_adjust); - // don't perform the top adjustment if the top is actually #T - if (!top_adjust.empty()) - printfs("+((%1)*(%2>\\n[" LAST_PASSED_ROW_REG "]))", - top_adjust, - as_string(start_row)); - prints("'\\s0\n"); - } - prints(".\\}\n"); -} - -void vertical_rule::print() -{ - printfs("\\*[" TRANSPARENT_STRING_NAME "]" - ".if %1<=\\*[" QUOTE_STRING_NAME "]\\n[" LAST_PASSED_ROW_REG "] " - ".nr %2 \\*[" QUOTE_STRING_NAME "]\\n[#T]\n", - as_string(start_row), - row_top_reg(start_row)); - const char *offset_table[3]; - if (is_double) { - offset_table[0] = "-" HALF_DOUBLE_LINE_SEP; - offset_table[1] = "+" HALF_DOUBLE_LINE_SEP; - offset_table[2] = 0; - } - else { - offset_table[0] = ""; - offset_table[1] = 0; - } - for (const char **offsetp = offset_table; *offsetp; offsetp++) { - prints("\\*[" TRANSPARENT_STRING_NAME "].sp -1\n" - "\\*[" TRANSPARENT_STRING_NAME "]\\v'" BODY_DEPTH); - if (!bot_adjust.empty()) - printfs("+%1", bot_adjust); - prints("'"); - printfs("\\h'\\n[%1]u%3'" - "\\s[\\n[" LINESIZE_REG "]]" - "\\D'l 0 |\\*[" QUOTE_STRING_NAME "]\\n[%2]u-1v", - column_divide_reg(col), - row_top_reg(start_row), - *offsetp); - if (!bot_adjust.empty()) - printfs("-(%1)", bot_adjust); - // don't perform the top adjustment if the top is actually #T - if (!top_adjust.empty()) - printfs("+((%1)*(%2>\\*[" QUOTE_STRING_NAME "]\\n[" - LAST_PASSED_ROW_REG "]))", - top_adjust, - as_string(start_row)); - prints("'" - "\\s0\n"); - } -} - -table::table(int nc, unsigned f, int ls, char dpc) -: flags(f), nrows(0), ncolumns(nc), linesize(ls), decimal_point_char(dpc), - vrule_list(0), stuff_list(0), span_list(0), - entry_list(0), entry_list_tailp(&entry_list), entry(0), - vline(0), row_is_all_lines(0), left_separation(0), right_separation(0), - allocated_rows(0) -{ - minimum_width = new string[ncolumns]; - column_separation = ncolumns > 1 ? new int[ncolumns - 1] : 0; - equal = new char[ncolumns]; - int i; - for (i = 0; i < ncolumns; i++) - equal[i] = 0; - for (i = 0; i < ncolumns-1; i++) - column_separation[i] = DEFAULT_COLUMN_SEPARATION; - delim[0] = delim[1] = '\0'; -} - -table::~table() -{ - for (int i = 0; i < nrows; i++) { - a_delete entry[i]; - a_delete vline[i]; - } - a_delete entry; - a_delete vline; - while (entry_list) { - table_entry *tem = entry_list; - entry_list = entry_list->next; - delete tem; - } - ad_delete(ncolumns) minimum_width; - a_delete column_separation; - a_delete equal; - while (stuff_list) { - stuff *tem = stuff_list; - stuff_list = stuff_list->next; - delete tem; - } - while (vrule_list) { - vertical_rule *tem = vrule_list; - vrule_list = vrule_list->next; - delete tem; - } - a_delete row_is_all_lines; - while (span_list) { - horizontal_span *tem = span_list; - span_list = span_list->next; - delete tem; - } -} - -void table::set_delim(char c1, char c2) -{ - delim[0] = c1; - delim[1] = c2; -} - -void table::set_minimum_width(int c, const string &w) -{ - assert(c >= 0 && c < ncolumns); - minimum_width[c] = w; -} - -void table::set_column_separation(int c, int n) -{ - assert(c >= 0 && c < ncolumns - 1); - column_separation[c] = n; -} - -void table::set_equal_column(int c) -{ - assert(c >= 0 && c < ncolumns); - equal[c] = 1; -} - -void table::add_stuff(stuff *p) -{ - stuff **pp; - for (pp = &stuff_list; *pp; pp = &(*pp)->next) - ; - *pp = p; -} - -void table::add_text_line(int r, const string &s, const char *filename, int lineno) -{ - add_stuff(new text_stuff(s, r, filename, lineno)); -} - -void table::add_single_hline(int r) -{ - add_stuff(new single_hline_stuff(r)); -} - -void table::add_double_hline(int r) -{ - add_stuff(new double_hline_stuff(r)); -} - -void table::allocate(int r) -{ - if (r >= nrows) { - typedef table_entry **PPtable_entry; // work around g++ 1.36.1 bug - if (r >= allocated_rows) { - if (allocated_rows == 0) { - allocated_rows = 16; - if (allocated_rows <= r) - allocated_rows = r + 1; - entry = new PPtable_entry[allocated_rows]; - vline = new char*[allocated_rows]; - } - else { - table_entry ***old_entry = entry; - int old_allocated_rows = allocated_rows; - allocated_rows *= 2; - if (allocated_rows <= r) - allocated_rows = r + 1; - entry = new PPtable_entry[allocated_rows]; - memcpy(entry, old_entry, sizeof(table_entry**)*old_allocated_rows); - a_delete old_entry; - char **old_vline = vline; - vline = new char*[allocated_rows]; - memcpy(vline, old_vline, sizeof(char*)*old_allocated_rows); - a_delete old_vline; - } - } - assert(allocated_rows > r); - while (nrows <= r) { - entry[nrows] = new table_entry*[ncolumns]; - int i; - for (i = 0; i < ncolumns; i++) - entry[nrows][i] = 0; - vline[nrows] = new char[ncolumns+1]; - for (i = 0; i < ncolumns+1; i++) - vline[nrows][i] = 0; - nrows++; - } - } -} - -void table::do_hspan(int r, int c) -{ - assert(r >= 0 && c >= 0 && r < nrows && c < ncolumns); - if (c == 0) { - error("first column cannot be horizontally spanned"); - return; - } - table_entry *e = entry[r][c]; - if (e) { - assert(e->start_row <= r && r <= e->end_row - && e->start_col <= c && c <= e->end_col - && e->end_row - e->start_row > 0 - && e->end_col - e->start_col > 0); - return; - } - e = entry[r][c-1]; - // e can be 0 if we had an empty entry or an error - if (e == 0) - return; - if (e->start_row != r) { - /* - l l - ^ s */ - error("impossible horizontal span at row %1, column %2", r + 1, c + 1); - } - else { - e->end_col = c; - entry[r][c] = e; - } -} - -void table::do_vspan(int r, int c) -{ - assert(r >= 0 && c >= 0 && r < nrows && c < ncolumns); - if (r == 0) { - error("first row cannot be vertically spanned"); - return; - } - table_entry *e = entry[r][c]; - if (e) { - assert(e->start_row <= r && r <= e->end_row - && e->start_col <= c && c <= e->end_col - && e->end_row - e->start_row > 0 - && e->end_col - e->start_col > 0); - return; - } - e = entry[r-1][c]; - // e can be 0 if we had an empty entry or an error - if (e == 0) - return; - if (e->start_col != c) { - /* l s - l ^ */ - error("impossible vertical span at row %1, column %2", r + 1, c + 1); - } - else { - for (int i = c; i <= e->end_col; i++) { - assert(entry[r][i] == 0); - entry[r][i] = e; - } - e->end_row = r; - } -} - -int find_decimal_point(const char *s, char decimal_point_char, - const char *delim) -{ - if (s == 0 || *s == '\0') - return -1; - const char *p; - int in_delim = 0; // is p within eqn delimiters? - // tbl recognises \& even within eqn delimiters; I don't - for (p = s; *p; p++) - if (in_delim) { - if (*p == delim[1]) - in_delim = 0; - } - else if (*p == delim[0]) - in_delim = 1; - else if (p[0] == '\\' && p[1] == '&') - return p - s; - int possible_pos = -1; - in_delim = 0; - for (p = s; *p; p++) - if (in_delim) { - if (*p == delim[1]) - in_delim = 0; - } - else if (*p == delim[0]) - in_delim = 1; - else if (p[0] == decimal_point_char && csdigit(p[1])) - possible_pos = p - s; - if (possible_pos >= 0) - return possible_pos; - in_delim = 0; - for (p = s; *p; p++) - if (in_delim) { - if (*p == delim[1]) - in_delim = 0; - } - else if (*p == delim[0]) - in_delim = 1; - else if (csdigit(*p)) - possible_pos = p + 1 - s; - return possible_pos; -} - -void table::add_entry(int r, int c, const string &str, const entry_format *f, - const char *fn, int ln) -{ - allocate(r); - table_entry *e = 0; - if (str == "\\_") { - e = new short_line_entry(f); - } - else if (str == "\\=") { - e = new short_double_line_entry(f); - } - else if (str == "_") { - single_line_entry *lefte; - if (c > 0 && entry[r][c-1] != 0 && - (lefte = entry[r][c-1]->to_single_line_entry()) != 0 - && lefte->start_row == r - && lefte->mod->stagger == f->stagger) { - lefte->end_col = c; - entry[r][c] = lefte; - } - else - e = new single_line_entry(f); - } - else if (str == "=") { - double_line_entry *lefte; - if (c > 0 && entry[r][c-1] != 0 && - (lefte = entry[r][c-1]->to_double_line_entry()) != 0 - && lefte->start_row == r - && lefte->mod->stagger == f->stagger) { - lefte->end_col = c; - entry[r][c] = lefte; - } - else - e = new double_line_entry(f); - } - else if (str == "\\^") { - do_vspan(r, c); - } - else if (str.length() > 2 && str[0] == '\\' && str[1] == 'R') { - if (str.search('\n') >= 0) - error_with_file_and_line(fn, ln, "bad repeated character"); - else { - char *s = str.substring(2, str.length() - 2).extract(); - e = new repeated_char_entry(s, f); - } - } - else { - int is_block = str.search('\n') >= 0; - char *s; - switch (f->type) { - case FORMAT_SPAN: - assert(str.empty()); - do_hspan(r, c); - break; - case FORMAT_LEFT: - if (!str.empty()) { - s = str.extract(); - if (is_block) - e = new left_block_entry(s, f); - else - e = new left_text_entry(s, f); - } - else - e = new empty_entry(f); - break; - case FORMAT_CENTER: - if (!str.empty()) { - s = str.extract(); - if (is_block) - e = new center_block_entry(s, f); - else - e = new center_text_entry(s, f); - } - else - e = new empty_entry(f); - break; - case FORMAT_RIGHT: - if (!str.empty()) { - s = str.extract(); - if (is_block) - e = new right_block_entry(s, f); - else - e = new right_text_entry(s, f); - } - else - e = new empty_entry(f); - break; - case FORMAT_NUMERIC: - if (!str.empty()) { - s = str.extract(); - if (is_block) { - error_with_file_and_line(fn, ln, "can't have numeric text block"); - e = new left_block_entry(s, f); - } - else { - int pos = find_decimal_point(s, decimal_point_char, delim); - if (pos < 0) - e = new center_text_entry(s, f); - else - e = new numeric_text_entry(s, f, pos); - } - } - else - e = new empty_entry(f); - break; - case FORMAT_ALPHABETIC: - if (!str.empty()) { - s = str.extract(); - if (is_block) - e = new alphabetic_block_entry(s, f); - else - e = new alphabetic_text_entry(s, f); - } - else - e = new empty_entry(f); - break; - case FORMAT_VSPAN: - do_vspan(r, c); - break; - case FORMAT_HLINE: - if (str.length() != 0) - error_with_file_and_line(fn, ln, - "non-empty data entry for `_' format ignored"); - e = new single_line_entry(f); - break; - case FORMAT_DOUBLE_HLINE: - if (str.length() != 0) - error_with_file_and_line(fn, ln, - "non-empty data entry for `=' format ignored"); - e = new double_line_entry(f); - break; - default: - assert(0); - } - } - if (e) { - table_entry *preve = entry[r][c]; - if (preve) { - /* c s - ^ l */ - error_with_file_and_line(fn, ln, "row %1, column %2 already spanned", - r + 1, c + 1); - delete e; - } - else { - e->input_lineno = ln; - e->input_filename = fn; - e->start_row = e->end_row = r; - e->start_col = e->end_col = c; - *entry_list_tailp = e; - entry_list_tailp = &e->next; - entry[r][c] = e; - } - } -} - -// add vertical lines for row r - -void table::add_vlines(int r, const char *v) -{ - allocate(r); - for (int i = 0; i < ncolumns+1; i++) - vline[r][i] = v[i]; -} - -void table::check() -{ - table_entry *p = entry_list; - int i, j; - while (p) { - for (i = p->start_row; i <= p->end_row; i++) - for (j = p->start_col; j <= p->end_col; j++) - assert(entry[i][j] == p); - p = p->next; - } -} - -void table::print() -{ - location_force_filename = 1; - check(); - init_output(); - determine_row_type(); - compute_widths(); - if (!(flags & CENTER)) - prints(".if \\n[" SAVED_CENTER_REG "] \\{"); - prints(".in +(u;\\n[.l]-\\n[.i]-\\n[TW]/2>?-\\n[.i])\n" - ".nr " SAVED_INDENT_REG " \\n[.i]\n"); - if (!(flags & CENTER)) - prints(".\\}\n"); - build_vrule_list(); - define_bottom_macro(); - do_top(); - for (int i = 0; i < nrows; i++) - do_row(i); - do_bottom(); -} - -void table::determine_row_type() -{ - row_is_all_lines = new char[nrows]; - for (int i = 0; i < nrows; i++) { - int had_single = 0; - int had_double = 0; - int had_non_line = 0; - for (int c = 0; c < ncolumns; c++) { - table_entry *e = entry[i][c]; - if (e != 0) { - if (e->start_row == e->end_row) { - int t = e->line_type(); - switch (t) { - case -1: - had_non_line = 1; - break; - case 0: - // empty - break; - case 1: - had_single = 1; - break; - case 2: - had_double = 1; - break; - default: - assert(0); - } - if (had_non_line) - break; - } - c = e->end_col; - } - } - if (had_non_line) - row_is_all_lines[i] = 0; - else if (had_double) - row_is_all_lines[i] = 2; - else if (had_single) - row_is_all_lines[i] = 1; - else - row_is_all_lines[i] = 0; - } -} - -void table::init_output() -{ - prints(".nr " COMPATIBLE_REG " \\n(.C\n" - ".cp 0\n"); - if (linesize > 0) - printfs(".nr " LINESIZE_REG " %1\n", as_string(linesize)); - else - prints(".nr " LINESIZE_REG " \\n[.s]\n"); - if (!(flags & CENTER)) - prints(".nr " SAVED_CENTER_REG " \\n[.ce]\n"); - if (compatible_flag) - prints(".ds " LEADER_REG " \\a\n"); - prints(".de " RESET_MACRO_NAME "\n" - ".ft \\n[.f]\n" - ".ps \\n[.s]\n" - ".vs \\n[.v]u\n" - ".in \\n[.i]u\n" - ".ll \\n[.l]u\n" - ".ls \\n[.L]\n" - ".ad \\n[.j]\n" - ".ie \\n[.u] .fi\n" - ".el .nf\n" - ".ce \\n[.ce]\n" - "..\n" - ".nr " SAVED_INDENT_REG " \\n[.i]\n" - ".nr " SAVED_FONT_REG " \\n[.f]\n" - ".nr " SAVED_SIZE_REG " \\n[.s]\n" - ".nr " SAVED_FILL_REG " \\n[.u]\n" - ".nr T. 0\n" - ".nr " CURRENT_ROW_REG " 0-1\n" - ".nr " LAST_PASSED_ROW_REG " 0-1\n" - ".nr " SECTION_DIVERSION_FLAG_REG " 0\n" - ".ds " TRANSPARENT_STRING_NAME "\n" - ".ds " QUOTE_STRING_NAME "\n" - ".nr " NEED_BOTTOM_RULE_REG " 1\n" - ".nr " SUPPRESS_BOTTOM_REG " 0\n" - ".eo\n" - ".de " REPEATED_MARK_MACRO "\n" - ".mk \\$1\n" - ".if !'\\n(.z'' \\!." REPEATED_MARK_MACRO " \"\\$1\"\n" - "..\n" - ".de " REPEATED_VPT_MACRO "\n" - ".vpt \\$1\n" - ".if !'\\n(.z'' \\!." REPEATED_VPT_MACRO " \"\\$1\"\n" - "..\n"); - if (!(flags & NOKEEP)) - prints(".de " KEEP_MACRO_NAME "\n" - ".if '\\n[.z]'' \\{.ds " QUOTE_STRING_NAME " \\\\\n" - ".ds " TRANSPARENT_STRING_NAME " \\!\n" - ".di " SECTION_DIVERSION_NAME "\n" - ".nr " SECTION_DIVERSION_FLAG_REG " 1\n" - ".in 0\n" - ".\\}\n" - "..\n" - ".de " RELEASE_MACRO_NAME "\n" - ".if \\n[" SECTION_DIVERSION_FLAG_REG "] \\{" - ".di\n" - ".in \\n[" SAVED_INDENT_REG "]u\n" - ".nr " SAVED_DN_REG " \\n[dn]\n" - ".ds " QUOTE_STRING_NAME "\n" - ".ds " TRANSPARENT_STRING_NAME "\n" - ".nr " SECTION_DIVERSION_FLAG_REG " 0\n" - ".if \\n[.t]<=\\n[dn] \\{" - ".nr T. 1\n" - ".T#\n" - ".nr " SUPPRESS_BOTTOM_REG " 1\n" - ".sp \\n[.t]u\n" - ".nr " SUPPRESS_BOTTOM_REG " 0\n" - ".mk #T\n" - ".\\}\n" - ".if \\n[.t]<=\\n[" SAVED_DN_REG "] " - /* Since we turn off traps, it won't get into an infinite loop - when we try and print it; it will just go off the bottom of the - page. */ - ".tm warning: page \\n%: table text block will not fit on one page\n" - ".nf\n" - ".ls 1\n" - "." SECTION_DIVERSION_NAME "\n" - ".ls\n" - ".rm " SECTION_DIVERSION_NAME "\n" - ".\\}\n" - "..\n" - ".nr " TABLE_DIVERSION_FLAG_REG " 0\n" - ".de " TABLE_KEEP_MACRO_NAME "\n" - ".if '\\n[.z]'' \\{" - ".di " TABLE_DIVERSION_NAME "\n" - ".nr " TABLE_DIVERSION_FLAG_REG " 1\n" - ".\\}\n" - "..\n" - ".de " TABLE_RELEASE_MACRO_NAME "\n" - ".if \\n[" TABLE_DIVERSION_FLAG_REG "] \\{.br\n" - ".di\n" - ".nr " SAVED_DN_REG " \\n[dn]\n" - ".ne \\n[dn]u+\\n[.V]u\n" - ".ie \\n[.t]<=\\n[" SAVED_DN_REG "] " - ".tm error: page \\n%: table will not fit on one page; use .TS H/.TH with a supporting macro package\n" - ".el \\{" - ".in 0\n" - ".ls 1\n" - ".nf\n" - "." TABLE_DIVERSION_NAME "\n" - ".\\}\n" - ".rm " TABLE_DIVERSION_NAME "\n" - ".\\}\n" - "..\n"); - prints(".ec\n" - ".ce 0\n" - ".nf\n"); -} - -string block_width_reg(int r, int c) -{ - static char name[sizeof(BLOCK_WIDTH_PREFIX)+INT_DIGITS+1+INT_DIGITS]; - sprintf(name, BLOCK_WIDTH_PREFIX "%d,%d", r, c); - return string(name); -} - -string block_diversion_name(int r, int c) -{ - static char name[sizeof(BLOCK_DIVERSION_PREFIX)+INT_DIGITS+1+INT_DIGITS]; - sprintf(name, BLOCK_DIVERSION_PREFIX "%d,%d", r, c); - return string(name); -} - -string block_height_reg(int r, int c) -{ - static char name[sizeof(BLOCK_HEIGHT_PREFIX)+INT_DIGITS+1+INT_DIGITS]; - sprintf(name, BLOCK_HEIGHT_PREFIX "%d,%d", r, c); - return string(name); -} - -string span_width_reg(int start_col, int end_col) -{ - static char name[sizeof(SPAN_WIDTH_PREFIX)+INT_DIGITS+1+INT_DIGITS]; - sprintf(name, SPAN_WIDTH_PREFIX "%d", start_col); - if (end_col != start_col) - sprintf(strchr(name, '\0'), ",%d", end_col); - return string(name); -} - -string span_left_numeric_width_reg(int start_col, int end_col) -{ - static char name[sizeof(SPAN_LEFT_NUMERIC_WIDTH_PREFIX)+INT_DIGITS+1+INT_DIGITS]; - sprintf(name, SPAN_LEFT_NUMERIC_WIDTH_PREFIX "%d", start_col); - if (end_col != start_col) - sprintf(strchr(name, '\0'), ",%d", end_col); - return string(name); -} - -string span_right_numeric_width_reg(int start_col, int end_col) -{ - static char name[sizeof(SPAN_RIGHT_NUMERIC_WIDTH_PREFIX)+INT_DIGITS+1+INT_DIGITS]; - sprintf(name, SPAN_RIGHT_NUMERIC_WIDTH_PREFIX "%d", start_col); - if (end_col != start_col) - sprintf(strchr(name, '\0'), ",%d", end_col); - return string(name); -} - -string span_alphabetic_width_reg(int start_col, int end_col) -{ - static char name[sizeof(SPAN_ALPHABETIC_WIDTH_PREFIX)+INT_DIGITS+1+INT_DIGITS]; - sprintf(name, SPAN_ALPHABETIC_WIDTH_PREFIX "%d", start_col); - if (end_col != start_col) - sprintf(strchr(name, '\0'), ",%d", end_col); - return string(name); -} - -string column_separation_reg(int col) -{ - static char name[sizeof(COLUMN_SEPARATION_PREFIX)+INT_DIGITS]; - sprintf(name, COLUMN_SEPARATION_PREFIX "%d", col); - return string(name); -} - -string row_start_reg(int row) -{ - static char name[sizeof(ROW_START_PREFIX)+INT_DIGITS]; - sprintf(name, ROW_START_PREFIX "%d", row); - return string(name); -} - -string column_start_reg(int col) -{ - static char name[sizeof(COLUMN_START_PREFIX)+INT_DIGITS]; - sprintf(name, COLUMN_START_PREFIX "%d", col); - return string(name); -} - -string column_end_reg(int col) -{ - static char name[sizeof(COLUMN_END_PREFIX)+INT_DIGITS]; - sprintf(name, COLUMN_END_PREFIX "%d", col); - return string(name); -} - -string column_divide_reg(int col) -{ - static char name[sizeof(COLUMN_DIVIDE_PREFIX)+INT_DIGITS]; - sprintf(name, COLUMN_DIVIDE_PREFIX "%d", col); - return string(name); -} - -string row_top_reg(int row) -{ - static char name[sizeof(ROW_TOP_PREFIX)+INT_DIGITS]; - sprintf(name, ROW_TOP_PREFIX "%d", row); - return string(name); -} - -void init_span_reg(int start_col, int end_col) -{ - printfs(".nr %1 \\n(.H\n.nr %2 0\n.nr %3 0\n.nr %4 0\n", - span_width_reg(start_col, end_col), - span_alphabetic_width_reg(start_col, end_col), - span_left_numeric_width_reg(start_col, end_col), - span_right_numeric_width_reg(start_col, end_col)); -} - -void compute_span_width(int start_col, int end_col) -{ - printfs(".nr %1 \\n[%1]>?(\\n[%2]+\\n[%3])\n" - ".if \\n[%4] .nr %1 \\n[%1]>?(\\n[%4]+2n)\n", - span_width_reg(start_col, end_col), - span_left_numeric_width_reg(start_col, end_col), - span_right_numeric_width_reg(start_col, end_col), - span_alphabetic_width_reg(start_col, end_col)); -} - -// Increase the widths of columns so that the width of any spanning entry -// is not greater than the sum of the widths of the columns that it spans. -// Ensure that the widths of columns remain equal. - -void table::divide_span(int start_col, int end_col) -{ - assert(end_col > start_col); - printfs(".nr " NEEDED_REG " \\n[%1]-(\\n[%2]", - span_width_reg(start_col, end_col), - span_width_reg(start_col, start_col)); - int i; - for (i = start_col + 1; i <= end_col; i++) { - // The column separation may shrink with the expand option. - if (!(flags & EXPAND)) - printfs("+%1n", as_string(column_separation[i - 1])); - printfs("+\\n[%1]", span_width_reg(i, i)); - } - prints(")\n"); - printfs(".nr " NEEDED_REG " \\n[" NEEDED_REG "]/%1\n", - as_string(end_col - start_col + 1)); - prints(".if \\n[" NEEDED_REG "] \\{"); - for (i = start_col; i <= end_col; i++) - printfs(".nr %1 +\\n[" NEEDED_REG "]\n", - span_width_reg(i, i)); - int equal_flag = 0; - for (i = start_col; i <= end_col && !equal_flag; i++) - if (equal[i]) - equal_flag = 1; - if (equal_flag) { - for (i = 0; i < ncolumns; i++) - if (i < start_col || i > end_col) - printfs(".nr %1 +\\n[" NEEDED_REG "]\n", - span_width_reg(i, i)); - } - prints(".\\}\n"); -} - -void table::sum_columns(int start_col, int end_col) -{ - assert(end_col > start_col); - printfs(".nr %1 \\n[%2]", - span_width_reg(start_col, end_col), - span_width_reg(start_col, start_col)); - for (int i = start_col + 1; i <= end_col; i++) - printfs("+(%1*\\n[" SEPARATION_FACTOR_REG "])+\\n[%2]", - as_string(column_separation[i - 1]), - span_width_reg(i, i)); - prints('\n'); -} - -horizontal_span::horizontal_span(int sc, int ec, horizontal_span *p) -: next(p), start_col(sc), end_col(ec) -{ -} - -void table::build_span_list() -{ - span_list = 0; - table_entry *p = entry_list; - while (p) { - if (p->end_col != p->start_col) { - horizontal_span *q; - for (q = span_list; q; q = q->next) - if (q->start_col == p->start_col - && q->end_col == p->end_col) - break; - if (!q) - span_list = new horizontal_span(p->start_col, p->end_col, span_list); - } - p = p->next; - } - // Now sort span_list primarily by order of end_row, and secondarily - // by reverse order of start_row. This ensures that if we divide - // spans using the order in span_list, we will get reasonable results. - horizontal_span *unsorted = span_list; - span_list = 0; - while (unsorted) { - horizontal_span **pp; - for (pp = &span_list; *pp; pp = &(*pp)->next) - if (unsorted->end_col < (*pp)->end_col - || (unsorted->end_col == (*pp)->end_col - && (unsorted->start_col > (*pp)->start_col))) - break; - horizontal_span *tem = unsorted->next; - unsorted->next = *pp; - *pp = unsorted; - unsorted = tem; - } -} - -void table::compute_separation_factor() -{ - if (flags & (ALLBOX|BOX|DOUBLEBOX)) - left_separation = right_separation = 1; - else { - for (int i = 0; i < nrows; i++) { - if (vline[i][0] > 0) - left_separation = 1; - if (vline[i][ncolumns] > 0) - right_separation = 1; - } - } - if (flags & EXPAND) { - int total_sep = left_separation + right_separation; - int i; - for (i = 0; i < ncolumns - 1; i++) - total_sep += column_separation[i]; - if (total_sep != 0) { - // Don't let the separation factor be negative. - prints(".nr " SEPARATION_FACTOR_REG " \\n[.l]-\\n[.i]"); - for (i = 0; i < ncolumns; i++) - printfs("-\\n[%1]", span_width_reg(i, i)); - printfs("/%1>?0\n", as_string(total_sep)); - } - } -} - -void table::compute_column_positions() -{ - printfs(".nr %1 0\n", column_divide_reg(0)); - printfs(".nr %1 %2*\\n[" SEPARATION_FACTOR_REG "]\n", - column_start_reg(0), - as_string(left_separation)); - int i; - for (i = 1;; i++) { - printfs(".nr %1 \\n[%2]+\\n[%3]\n", - column_end_reg(i-1), - column_start_reg(i-1), - span_width_reg(i-1, i-1)); - if (i >= ncolumns) - break; - printfs(".nr %1 \\n[%2]+(%3*\\n[" SEPARATION_FACTOR_REG "])\n", - column_start_reg(i), - column_end_reg(i-1), - as_string(column_separation[i-1])); - printfs(".nr %1 \\n[%2]+\\n[%3]/2\n", - column_divide_reg(i), - column_end_reg(i-1), - column_start_reg(i)); - } - printfs(".nr %1 \\n[%2]+(%3*\\n[" SEPARATION_FACTOR_REG "])\n", - column_divide_reg(ncolumns), - column_end_reg(i-1), - as_string(right_separation)); - printfs(".nr TW \\n[%1]\n", - column_divide_reg(ncolumns)); - if (flags & DOUBLEBOX) { - printfs(".nr %1 +" DOUBLE_LINE_SEP "\n", column_divide_reg(0)); - printfs(".nr %1 -" DOUBLE_LINE_SEP "\n", column_divide_reg(ncolumns)); - } -} - -void table::make_columns_equal() -{ - int first = -1; // index of first equal column - int i; - for (i = 0; i < ncolumns; i++) - if (equal[i]) { - if (first < 0) { - printfs(".nr %1 \\n[%1]", span_width_reg(i, i)); - first = i; - } - else - printfs(">?\\n[%1]", span_width_reg(i, i)); - } - if (first >= 0) { - prints('\n'); - for (i = first + 1; i < ncolumns; i++) - if (equal[i]) - printfs(".nr %1 \\n[%2]\n", - span_width_reg(i, i), - span_width_reg(first, first)); - } -} - -void table::compute_widths() -{ - build_span_list(); - int i; - horizontal_span *p; - prints(".nr " SEPARATION_FACTOR_REG " 1n\n"); - for (i = 0; i < ncolumns; i++) { - init_span_reg(i, i); - if (!minimum_width[i].empty()) - printfs(".nr %1 %2\n", span_width_reg(i, i), minimum_width[i]); - } - for (p = span_list; p; p = p->next) - init_span_reg(p->start_col, p->end_col); - table_entry *q; - for (q = entry_list; q; q = q->next) - if (!q->mod->zero_width) - q->do_width(); - for (i = 0; i < ncolumns; i++) - compute_span_width(i, i); - for (p = span_list; p; p = p->next) - compute_span_width(p->start_col, p->end_col); - make_columns_equal(); - // Note that divide_span keeps equal width columns equal. - for (p = span_list; p; p = p->next) - divide_span(p->start_col, p->end_col); - for (p = span_list; p; p = p->next) - sum_columns(p->start_col, p->end_col); - int had_spanning_block = 0; - int had_equal_block = 0; - for (q = entry_list; q; q = q->next) - if (q->divert(ncolumns, minimum_width, - (flags & EXPAND) ? column_separation : 0)) { - if (q->end_col > q->start_col) - had_spanning_block = 1; - for (i = q->start_col; i <= q->end_col && !had_equal_block; i++) - if (equal[i]) - had_equal_block = 1; - } - if (had_equal_block) - make_columns_equal(); - if (had_spanning_block) - for (p = span_list; p; p = p->next) - divide_span(p->start_col, p->end_col); - compute_separation_factor(); - for (p = span_list; p; p = p->next) - sum_columns(p->start_col, p->end_col); - compute_column_positions(); -} - -void table::print_single_hline(int r) -{ - prints(".vs " LINE_SEP ">?\\n[.V]u\n" - ".ls 1\n" - "\\v'" BODY_DEPTH "'" - "\\s[\\n[" LINESIZE_REG "]]"); - if (r > nrows - 1) - prints("\\D'l |\\n[TW]u 0'"); - else { - int start_col = 0; - for (;;) { - while (start_col < ncolumns - && entry[r][start_col] != 0 - && entry[r][start_col]->start_row != r) - start_col++; - int end_col; - for (end_col = start_col; - end_col < ncolumns - && (entry[r][end_col] == 0 - || entry[r][end_col]->start_row == r); - end_col++) - ; - if (end_col <= start_col) - break; - printfs("\\h'|\\n[%1]u", - column_divide_reg(start_col)); - if ((r > 0 && vline[r-1][start_col] == 2) - || (r < nrows && vline[r][start_col] == 2)) - prints("-" HALF_DOUBLE_LINE_SEP); - prints("'"); - printfs("\\D'l |\\n[%1]u", - column_divide_reg(end_col)); - if ((r > 0 && vline[r-1][end_col] == 2) - || (r < nrows && vline[r][end_col] == 2)) - prints("+" HALF_DOUBLE_LINE_SEP); - prints(" 0'"); - start_col = end_col; - } - } - prints("\\s0\n"); - prints(".ls\n" - ".vs\n"); -} - -void table::print_double_hline(int r) -{ - prints(".vs " LINE_SEP "+" DOUBLE_LINE_SEP - ">?\\n[.V]u\n" - ".ls 1\n" - "\\v'" BODY_DEPTH "'" - "\\s[\\n[" LINESIZE_REG "]]"); - if (r > nrows - 1) - prints("\\v'-" DOUBLE_LINE_SEP "'" - "\\D'l |\\n[TW]u 0'" - "\\v'" DOUBLE_LINE_SEP "'" - "\\h'|0'" - "\\D'l |\\n[TW]u 0'"); - else { - int start_col = 0; - for (;;) { - while (start_col < ncolumns - && entry[r][start_col] != 0 - && entry[r][start_col]->start_row != r) - start_col++; - int end_col; - for (end_col = start_col; - end_col < ncolumns - && (entry[r][end_col] == 0 - || entry[r][end_col]->start_row == r); - end_col++) - ; - if (end_col <= start_col) - break; - const char *left_adjust = 0; - if ((r > 0 && vline[r-1][start_col] == 2) - || (r < nrows && vline[r][start_col] == 2)) - left_adjust = "-" HALF_DOUBLE_LINE_SEP; - const char *right_adjust = 0; - if ((r > 0 && vline[r-1][end_col] == 2) - || (r < nrows && vline[r][end_col] == 2)) - right_adjust = "+" HALF_DOUBLE_LINE_SEP; - printfs("\\v'-" DOUBLE_LINE_SEP "'" - "\\h'|\\n[%1]u", - column_divide_reg(start_col)); - if (left_adjust) - prints(left_adjust); - prints("'"); - printfs("\\D'l |\\n[%1]u", - column_divide_reg(end_col)); - if (right_adjust) - prints(right_adjust); - prints(" 0'"); - printfs("\\v'" DOUBLE_LINE_SEP "'" - "\\h'|\\n[%1]u", - column_divide_reg(start_col)); - if (left_adjust) - prints(left_adjust); - prints("'"); - printfs("\\D'l |\\n[%1]u", - column_divide_reg(end_col)); - if (right_adjust) - prints(right_adjust); - prints(" 0'"); - start_col = end_col; - } - } - prints("\\s0\n" - ".ls\n" - ".vs\n"); -} - -void table::compute_vrule_top_adjust(int start_row, int col, string &result) -{ - if (row_is_all_lines[start_row] && start_row < nrows - 1) { - if (row_is_all_lines[start_row] == 2) - result = LINE_SEP ">?\\n[.V]u" "+" DOUBLE_LINE_SEP; - else - result = LINE_SEP ">?\\n[.V]u"; - start_row++; - } - else { - result = ""; - if (start_row == 0) - return; - for (stuff *p = stuff_list; p && p->row <= start_row; p = p->next) - if (p->row == start_row - && (p->is_single_line() || p->is_double_line())) - return; - } - int left = 0; - if (col > 0) { - table_entry *e = entry[start_row-1][col-1]; - if (e && e->start_row == e->end_row) { - if (e->to_double_line_entry() != 0) - left = 2; - else if (e->to_single_line_entry() != 0) - left = 1; - } - } - int right = 0; - if (col < ncolumns) { - table_entry *e = entry[start_row-1][col]; - if (e && e->start_row == e->end_row) { - if (e->to_double_line_entry() != 0) - right = 2; - else if (e->to_single_line_entry() != 0) - right = 1; - } - } - if (row_is_all_lines[start_row-1] == 0) { - if (left > 0 || right > 0) { - result += "-" BODY_DEPTH "-" BAR_HEIGHT; - if ((left == 2 && right != 2) || (right == 2 && left != 2)) - result += "-" HALF_DOUBLE_LINE_SEP; - else if (left == 2 && right == 2) - result += "+" HALF_DOUBLE_LINE_SEP; - } - } - else if (row_is_all_lines[start_row-1] == 2) { - if ((left == 2 && right != 2) || (right == 2 && left != 2)) - result += "-" DOUBLE_LINE_SEP; - else if (left == 1 || right == 1) - result += "-" HALF_DOUBLE_LINE_SEP; - } -} - -void table::compute_vrule_bot_adjust(int end_row, int col, string &result) -{ - if (row_is_all_lines[end_row] && end_row > 0) { - end_row--; - result = ""; - } - else { - stuff *p; - for (p = stuff_list; p && p->row < end_row + 1; p = p->next) - ; - if (p && p->row == end_row + 1 && p->is_double_line()) { - result = "-" DOUBLE_LINE_SEP; - return; - } - if ((p != 0 && p->row == end_row + 1) - || end_row == nrows - 1) { - result = ""; - return; - } - if (row_is_all_lines[end_row+1] == 1) - result = LINE_SEP; - else if (row_is_all_lines[end_row+1] == 2) - result = LINE_SEP "+" DOUBLE_LINE_SEP; - else - result = ""; - } - int left = 0; - if (col > 0) { - table_entry *e = entry[end_row+1][col-1]; - if (e && e->start_row == e->end_row) { - if (e->to_double_line_entry() != 0) - left = 2; - else if (e->to_single_line_entry() != 0) - left = 1; - } - } - int right = 0; - if (col < ncolumns) { - table_entry *e = entry[end_row+1][col]; - if (e && e->start_row == e->end_row) { - if (e->to_double_line_entry() != 0) - right = 2; - else if (e->to_single_line_entry() != 0) - right = 1; - } - } - if (row_is_all_lines[end_row+1] == 0) { - if (left > 0 || right > 0) { - result = "1v-" BODY_DEPTH "-" BAR_HEIGHT; - if ((left == 2 && right != 2) || (right == 2 && left != 2)) - result += "+" HALF_DOUBLE_LINE_SEP; - else if (left == 2 && right == 2) - result += "-" HALF_DOUBLE_LINE_SEP; - } - } - else if (row_is_all_lines[end_row+1] == 2) { - if (left == 2 && right == 2) - result += "-" DOUBLE_LINE_SEP; - else if (left != 2 && right != 2 && (left == 1 || right == 1)) - result += "-" HALF_DOUBLE_LINE_SEP; - } -} - -void table::add_vertical_rule(int start_row, int end_row, int col, int is_double) -{ - vrule_list = new vertical_rule(start_row, end_row, col, is_double, - vrule_list); - compute_vrule_top_adjust(start_row, col, vrule_list->top_adjust); - compute_vrule_bot_adjust(end_row, col, vrule_list->bot_adjust); -} - -void table::build_vrule_list() -{ - int col; - if (flags & ALLBOX) { - for (col = 1; col < ncolumns; col++) { - int start_row = 0; - for (;;) { - while (start_row < nrows && vline_spanned(start_row, col)) - start_row++; - if (start_row >= nrows) - break; - int end_row = start_row; - while (end_row < nrows && !vline_spanned(end_row, col)) - end_row++; - end_row--; - add_vertical_rule(start_row, end_row, col, 0); - start_row = end_row + 1; - } - } - } - if (flags & (BOX|ALLBOX|DOUBLEBOX)) { - add_vertical_rule(0, nrows - 1, 0, 0); - add_vertical_rule(0, nrows - 1, ncolumns, 0); - } - for (int end_row = 0; end_row < nrows; end_row++) - for (col = 0; col < ncolumns+1; col++) - if (vline[end_row][col] > 0 - && !vline_spanned(end_row, col) - && (end_row == nrows - 1 - || vline[end_row+1][col] != vline[end_row][col] - || vline_spanned(end_row+1, col))) { - int start_row; - for (start_row = end_row - 1; - start_row >= 0 - && vline[start_row][col] == vline[end_row][col] - && !vline_spanned(start_row, col); - start_row--) - ; - start_row++; - add_vertical_rule(start_row, end_row, col, vline[end_row][col] > 1); - } - for (vertical_rule *p = vrule_list; p; p = p->next) - if (p->is_double) - for (int r = p->start_row; r <= p->end_row; r++) { - if (p->col > 0 && entry[r][p->col-1] != 0 - && entry[r][p->col-1]->end_col == p->col-1) { - int is_corner = r == p->start_row || r == p->end_row; - entry[r][p->col-1]->note_double_vrule_on_right(is_corner); - } - if (p->col < ncolumns && entry[r][p->col] != 0 - && entry[r][p->col]->start_col == p->col) { - int is_corner = r == p->start_row || r == p->end_row; - entry[r][p->col]->note_double_vrule_on_left(is_corner); - } - } -} - -void table::define_bottom_macro() -{ - prints(".eo\n" - ".de T#\n" - ".if !\\n[" SUPPRESS_BOTTOM_REG "] \\{" - "." REPEATED_VPT_MACRO " 0\n" - ".mk " SAVED_VERTICAL_POS_REG "\n"); - if (flags & (BOX|ALLBOX|DOUBLEBOX)) { - prints(".if \\n[T.]&\\n[" NEED_BOTTOM_RULE_REG "] \\{"); - print_single_hline(0); - prints(".\\}\n"); - } - prints(".ls 1\n"); - for (vertical_rule *p = vrule_list; p; p = p->next) - p->contribute_to_bottom_macro(this); - if (flags & DOUBLEBOX) - prints(".if \\n[T.] \\{.vs " DOUBLE_LINE_SEP ">?\\n[.V]u\n" - "\\v'" BODY_DEPTH "'\\s[\\n[" LINESIZE_REG "]]" - "\\D'l \\n[TW]u 0'\\s0\n" - ".vs\n" - ".\\}\n" - ".if \\n[" LAST_PASSED_ROW_REG "]>=0 " - ".nr " TOP_REG " \\n[#T]-" DOUBLE_LINE_SEP "\n" - ".sp -1\n" - "\\v'" BODY_DEPTH "'\\s[\\n[" LINESIZE_REG "]]" - "\\D'l 0 |\\n[" TOP_REG "]u-1v'\\s0\n" - ".sp -1\n" - "\\v'" BODY_DEPTH "'\\h'|\\n[TW]u'\\s[\\n[" LINESIZE_REG "]]" - "\\D'l 0 |\\n[" TOP_REG "]u-1v'\\s0\n"); - prints(".ls\n"); - prints(".nr " LAST_PASSED_ROW_REG " \\n[" CURRENT_ROW_REG "]\n" - ".sp |\\n[" SAVED_VERTICAL_POS_REG "]u\n" - "." REPEATED_VPT_MACRO " 1\n" - ".\\}\n" - "..\n" - ".ec\n"); -} - -// is the vertical line before column c in row r horizontally spanned? - -int table::vline_spanned(int r, int c) -{ - assert(r >= 0 && r < nrows && c >= 0 && c < ncolumns + 1); - return (c != 0 && c != ncolumns && entry[r][c] != 0 - && entry[r][c]->start_col != c - // horizontally spanning lines don't count - && entry[r][c]->to_double_line_entry() == 0 - && entry[r][c]->to_single_line_entry() == 0); -} - -int table::row_begins_section(int r) -{ - assert(r >= 0 && r < nrows); - for (int i = 0; i < ncolumns; i++) - if (entry[r][i] && entry[r][i]->start_row != r) - return 0; - return 1; -} - -int table::row_ends_section(int r) -{ - assert(r >= 0 && r < nrows); - for (int i = 0; i < ncolumns; i++) - if (entry[r][i] && entry[r][i]->end_row != r) - return 0; - return 1; -} - -void table::do_row(int r) -{ - if (!(flags & NOKEEP) && row_begins_section(r)) - prints("." KEEP_MACRO_NAME "\n"); - int had_line = 0; - stuff *p; - for (p = stuff_list; p && p->row < r; p = p->next) - ; - for (stuff *p1 = p; p1 && p1->row == r; p1 = p1->next) - if (!p1->printed && (p1->is_single_line() || p1->is_double_line())) { - had_line = 1; - break; - } - if (!had_line && !row_is_all_lines[r]) - printfs("." REPEATED_MARK_MACRO " %1\n", row_top_reg(r)); - had_line = 0; - for (; p && p->row == r; p = p->next) - if (!p->printed) { - p->print(this); - if (!had_line && (p->is_single_line() || p->is_double_line())) { - printfs("." REPEATED_MARK_MACRO " %1\n", row_top_reg(r)); - had_line = 1; - } - } - // Change the row *after* printing the stuff list (which might contain .TH). - printfs("\\*[" TRANSPARENT_STRING_NAME "].nr " CURRENT_ROW_REG " %1\n", - as_string(r)); - if (!had_line && row_is_all_lines[r]) - printfs("." REPEATED_MARK_MACRO " %1\n", row_top_reg(r)); - // we might have had a .TH, for example, since we last tried - if (!(flags & NOKEEP) && row_begins_section(r)) - prints("." KEEP_MACRO_NAME "\n"); - printfs(".mk %1\n", row_start_reg(r)); - prints(".mk " BOTTOM_REG "\n" - "." REPEATED_VPT_MACRO " 0\n"); - int c; - int row_is_blank = 1; - int first_start_row = r; - for (c = 0; c < ncolumns; c++) { - table_entry *e = entry[r][c]; - if (e) { - if (e->end_row == r) { - e->do_depth(); - if (e->start_row < first_start_row) - first_start_row = e->start_row; - row_is_blank = 0; - } - c = e->end_col; - } - } - if (row_is_blank) - prints(".nr " BOTTOM_REG " +1v\n"); - if (row_is_all_lines[r]) { - prints(".vs " LINE_SEP); - if (row_is_all_lines[r] == 2) - prints("+" DOUBLE_LINE_SEP); - prints(">?\\n[.V]u\n.ls 1\n"); - prints("\\&"); - prints("\\v'" BODY_DEPTH); - if (row_is_all_lines[r] == 2) - prints("-" HALF_DOUBLE_LINE_SEP); - prints("'"); - for (c = 0; c < ncolumns; c++) { - table_entry *e = entry[r][c]; - if (e) { - if (e->end_row == e->start_row) - e->to_simple_entry()->simple_print(1); - c = e->end_col; - } - } - prints("\n"); - prints(".ls\n" - ".vs\n"); - prints(".nr " BOTTOM_REG " \\n[" BOTTOM_REG "]>?\\n[.d]\n"); - printfs(".sp |\\n[%1]u\n", row_start_reg(r)); - } - for (int i = row_is_all_lines[r] ? r - 1 : r; - i >= first_start_row; - i--) { - simple_entry *first = 0; - for (c = 0; c < ncolumns; c++) { - table_entry *e = entry[r][c]; - if (e) { - if (e->end_row == r && e->start_row == i) { - simple_entry *simple = e->to_simple_entry(); - if (simple) { - if (!first) { - prints(".ta"); - first = simple; - } - simple->add_tab(); - } - } - c = e->end_col; - } - } - if (first) { - prints('\n'); - first->position_vertically(); - first->set_location(); - prints("\\&"); - first->simple_print(0); - for (c = first->end_col + 1; c < ncolumns; c++) { - table_entry *e = entry[r][c]; - if (e) { - if (e->end_row == r && e->start_row == i) { - simple_entry *simple = e->to_simple_entry(); - if (simple) { - if (e->end_row != e->start_row) { - prints('\n'); - simple->position_vertically(); - prints("\\&"); - } - simple->simple_print(0); - } - } - c = e->end_col; - } - } - prints('\n'); - prints(".nr " BOTTOM_REG " \\n[" BOTTOM_REG "]>?\\n[.d]\n"); - printfs(".sp |\\n[%1]u\n", row_start_reg(r)); - } - } - for (c = 0; c < ncolumns; c++) { - table_entry *e = entry[r][c]; - if (e) { - if (e->end_row == r && e->to_simple_entry() == 0) { - e->position_vertically(); - e->print(); - prints(".nr " BOTTOM_REG " \\n[" BOTTOM_REG "]>?\\n[.d]\n"); - printfs(".sp |\\n[%1]u\n", row_start_reg(r)); - } - c = e->end_col; - } - } - prints("." REPEATED_VPT_MACRO " 1\n" - ".sp |\\n[" BOTTOM_REG "]u\n" - "\\*[" TRANSPARENT_STRING_NAME "].nr " NEED_BOTTOM_RULE_REG " 1\n"); - if (r != nrows - 1 && (flags & ALLBOX)) { - print_single_hline(r + 1); - prints("\\*[" TRANSPARENT_STRING_NAME "].nr " NEED_BOTTOM_RULE_REG " 0\n"); - } - if (r != nrows - 1) { - if (p && p->row == r + 1 - && (p->is_single_line() || p->is_double_line())) { - p->print(this); - prints("\\*[" TRANSPARENT_STRING_NAME "].nr " NEED_BOTTOM_RULE_REG - " 0\n"); - } - int printed_one = 0; - for (vertical_rule *vr = vrule_list; vr; vr = vr->next) - if (vr->end_row == r) { - if (!printed_one) { - prints("." REPEATED_VPT_MACRO " 0\n"); - printed_one = 1; - } - vr->print(); - } - if (printed_one) - prints("." REPEATED_VPT_MACRO " 1\n"); - if (!(flags & NOKEEP) && row_ends_section(r)) - prints("." RELEASE_MACRO_NAME "\n"); - } -} - -void table::do_top() -{ - prints(".fc \002\003\n"); - if (!(flags & NOKEEP) && (flags & (BOX|DOUBLEBOX|ALLBOX))) - prints("." TABLE_KEEP_MACRO_NAME "\n"); - if (flags & DOUBLEBOX) { - prints(".ls 1\n" - ".vs " LINE_SEP ">?\\n[.V]u\n" - "\\v'" BODY_DEPTH "'\\s[\\n[" LINESIZE_REG "]]\\D'l \\n[TW]u 0'\\s0\n" - ".vs\n" - "." REPEATED_MARK_MACRO " " TOP_REG "\n" - ".vs " DOUBLE_LINE_SEP ">?\\n[.V]u\n"); - printfs("\\v'" BODY_DEPTH "'" - "\\s[\\n[" LINESIZE_REG "]]" - "\\h'\\n[%1]u'" - "\\D'l |\\n[%2]u 0'" - "\\s0" - "\n", - column_divide_reg(0), - column_divide_reg(ncolumns)); - prints(".ls\n" - ".vs\n"); - } - else if (flags & (ALLBOX|BOX)) { - print_single_hline(0); - } - //printfs(".mk %1\n", row_top_reg(0)); -} - -void table::do_bottom() -{ - // print stuff after last row - for (stuff *p = stuff_list; p; p = p->next) - if (p->row > nrows - 1) - p->print(this); - if (!(flags & NOKEEP)) - prints("." RELEASE_MACRO_NAME "\n"); - printfs(".mk %1\n", row_top_reg(nrows)); - prints(".nr " NEED_BOTTOM_RULE_REG " 1\n" - ".nr T. 1\n" - ".T#\n"); - if (!(flags & NOKEEP) && (flags & (BOX|DOUBLEBOX|ALLBOX))) - prints("." TABLE_RELEASE_MACRO_NAME "\n"); - if (flags & DOUBLEBOX) - prints(".sp " DOUBLE_LINE_SEP "\n"); - prints("." RESET_MACRO_NAME "\n" - ".fc\n" - ".cp \\n(" COMPATIBLE_REG "\n"); -} - -int table::get_nrows() -{ - return nrows; -} - -const char *last_filename = 0; - -void set_troff_location(const char *fn, int ln) -{ - if (!location_force_filename && last_filename != 0 - && strcmp(fn, last_filename) == 0) - printfs(".lf %1\n", as_string(ln)); - else { - printfs(".lf %1 %2\n", as_string(ln), fn); - last_filename = fn; - location_force_filename = 0; - } -} - -void printfs(const char *s, const string &arg1, const string &arg2, - const string &arg3, const string &arg4, const string &arg5) -{ - if (s) { - char c; - while ((c = *s++) != '\0') { - if (c == '%') { - switch (*s++) { - case '1': - prints(arg1); - break; - case '2': - prints(arg2); - break; - case '3': - prints(arg3); - break; - case '4': - prints(arg4); - break; - case '5': - prints(arg5); - break; - case '6': - case '7': - case '8': - case '9': - break; - case '%': - prints('%'); - break; - default: - assert(0); - } - } - else - prints(c); - } - } -} - diff --git a/contrib/groff/src/preproc/tbl/table.h b/contrib/groff/src/preproc/tbl/table.h deleted file mode 100644 index 4b2497e2158e..000000000000 --- a/contrib/groff/src/preproc/tbl/table.h +++ /dev/null @@ -1,165 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002, 2003, 2004 - 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "lib.h" - -#include -#include -#include -#include - -#include "cset.h" -#include "cmap.h" -#include "stringclass.h" -#include "errarg.h" -#include "error.h" - -// PREFIX and PREFIX_CHAR must be the same. -#define PREFIX "3" -#define PREFIX_CHAR '3' - -// LEADER and LEADER_CHAR must be the same. -#define LEADER "a" -#define LEADER_CHAR 'a' - -struct inc_number { - short inc; - short val; -}; - -struct entry_modifier { - inc_number point_size; - inc_number vertical_spacing; - string font; - string macro; - enum { CENTER, TOP, BOTTOM } vertical_alignment; - char zero_width; - char stagger; - - entry_modifier(); - ~entry_modifier(); -}; - -enum format_type { - FORMAT_LEFT, - FORMAT_CENTER, - FORMAT_RIGHT, - FORMAT_NUMERIC, - FORMAT_ALPHABETIC, - FORMAT_SPAN, - FORMAT_VSPAN, - FORMAT_HLINE, - FORMAT_DOUBLE_HLINE -}; - -struct entry_format : public entry_modifier { - format_type type; - - entry_format(format_type); - entry_format(); - void debug_print() const; -}; - -class table_entry; -struct horizontal_span; -struct stuff; -struct vertical_rule; - -class table { - unsigned flags; - int nrows; - int ncolumns; - int linesize; - char delim[2]; - char decimal_point_char; - vertical_rule *vrule_list; - stuff *stuff_list; - horizontal_span *span_list; - table_entry *entry_list; - table_entry **entry_list_tailp; - table_entry ***entry; - char **vline; - char *row_is_all_lines; - string *minimum_width; - int *column_separation; - char *equal; - int left_separation; - int right_separation; - int allocated_rows; - void build_span_list(); - void do_hspan(int r, int c); - void do_vspan(int r, int c); - void allocate(int r); - void compute_widths(); - void divide_span(int, int); - void sum_columns(int, int); - void compute_separation_factor(); - void compute_column_positions(); - void do_row(int); - void init_output(); - void add_stuff(stuff *); - void do_top(); - void do_bottom(); - void do_vertical_rules(); - void build_vrule_list(); - void add_vertical_rule(int, int, int, int); - void define_bottom_macro(); - int vline_spanned(int r, int c); - int row_begins_section(int); - int row_ends_section(int); - void make_columns_equal(); - void compute_vrule_top_adjust(int, int, string &); - void compute_vrule_bot_adjust(int, int, string &); - void determine_row_type(); -public: - /* used by flags */ - enum { - CENTER = 01, - EXPAND = 02, - BOX = 04, - ALLBOX = 010, - DOUBLEBOX = 020, - NOKEEP = 040, - NOSPACES = 0100 - }; - table(int nc, unsigned flags, int linesize, char decimal_point_char); - ~table(); - - void add_text_line(int r, const string &, const char *, int); - void add_single_hline(int r); - void add_double_hline(int r); - void add_entry(int r, int c, const string &, const entry_format *, - const char *, int lineno); - void add_vlines(int r, const char *); - void check(); - void print(); - void set_minimum_width(int c, const string &w); - void set_column_separation(int c, int n); - void set_equal_column(int c); - void set_delim(char c1, char c2); - void print_single_hline(int r); - void print_double_hline(int r); - int get_nrows(); -}; - -void set_troff_location(const char *, int); - -extern int compatible_flag; diff --git a/contrib/groff/src/preproc/tbl/tbl.man b/contrib/groff/src/preproc/tbl/tbl.man deleted file mode 100644 index 00dfe4f83009..000000000000 --- a/contrib/groff/src/preproc/tbl/tbl.man +++ /dev/null @@ -1,493 +0,0 @@ -.ig -Copyright (C) 1989-1995, 2001, 2002, 2003, 2004 - Free Software Foundation, Inc. - -Permission is granted to make and distribute verbatim copies of -this manual provided the copyright notice and this permission notice -are preserved on all copies. - -Permission is granted to copy and distribute modified versions of this -manual under the conditions for verbatim copying, provided that the -entire resulting derived work is distributed under the terms of a -permission notice identical to this one. - -Permission is granted to copy and distribute translations of this -manual into another language, under the above conditions for modified -versions, except that this permission notice may be included in -translations approved by the Free Software Foundation instead of in -the original English. -.. -.TH @G@TBL @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@" -.SH NAME -@g@tbl \- format tables for troff -. -. -.SH SYNOPSIS -.B @g@tbl -[ -.B \-Cv -] -[ -.IR files \|.\|.\|.\& -] -. -. -.SH DESCRIPTION -This manual page describes the GNU version of -.BR tbl , -which is part of the groff document formatting system. -.B tbl -compiles descriptions of tables embedded within -.B troff -input files into commands that are understood by -.BR troff . -Normally, it should be invoked using the -.B \-t -option of -.B groff. -It is highly compatible with Unix -.BR tbl . -The output generated by GNU -.B tbl -cannot be processed with Unix -.BR troff ; -it must be processed with GNU -.BR troff . -If no files are given on the command line, the standard input -will be read. -A filename of -.B \- -will cause the standard input to be read. -. -. -.SH OPTIONS -.TP -.B \-C -Enable compatibility mode to -recognize -.B .TS -and -.B .TE -even when followed by a character other than space or newline. -Leader characters (\[rs]a) are handled as interpreted. -.TP -.B \-v -Print the version number. -. -. -.SH USAGE -.B tbl -expects to find table descriptions wrapped in the -.B .TS -(table start) and -.B .TE -(table end) macros. -The line immediately following the -.B .TS -macro may contain any of the following global options (ignoring the case -of characters -- Unix tbl only accepts options with all characters lowercase -or all characters uppercase): -. -.TP -.B center -Centers the table (default is left-justified). -The alternative keyword name -.B centre -is also recognized (this is a GNU tbl extension). -. -.TP -.BI delim( xy ) -Use -.I x -and -.I y -as start and end delimiters for -.BR @g@eqn (@MAN1EXT@). -. -.TP -.B expand -Makes the table as wide as the current line length. -. -.TP -.B box -Encloses the table in a box. -. -.TP -.B doublebox -Encloses the table in a double box. -. -.TP -.B allbox -Encloses each item of the table in a box. -. -.TP -.B frame -Same as box (GNU tbl only). -. -.TP -.B doubleframe -Same as doublebox (GNU tbl only). -. -.TP -.BI tab( x ) -Uses the character -.I x -instead of a tab to separate items in a line of input data. -. -.TP -.BI linesize( n ) -Sets lines or rules (e.g. from -.BR box ) -in -.IR n -point -type. -. -.TP -.B nokeep -Don't use diversions to prevent page breaks (GNU tbl only). -Normally -.B tbl -attempts to prevent undesirable breaks in the table by using diversions. -This can sometimes interact badly with macro packages' own use of -diversions, when footnotes, for example, are used. -. -.TP -.BI decimalpoint( c ) -Set the character to be recognized as the decimal point in numeric -columns (GNU tbl only). -. -.TP -.B nospaces -Ignore leading and trailing spaces in data items (GNU tbl only). -. -.LP -The global options must end with a semicolon. -There might be whitespace after an option and its argument in parentheses. -.LP -After global options come lines describing the format of each line of -the table. -Each such format line describes one line of the table itself, except that -the last format line (which you must end with a period) describes all -remaining lines of the table. -A single key character describes each column of each line of the table. -You may run format specs for multiple lines together on the same line by -separating them with commas. -.LP -You may follow each key character with specifiers that determine the font -and point size of the corresponding item, that determine column width, -inter-column spacing, etc. -.LP -The longest format line defines the number of columns in the table; missing -format descriptors at the end of format lines are assumed to be `L'. -Extra columns in the data (which have no corresponding format entry) are -ignored. -.LP -The available key characters are: -. -.TP -c,C -Centers item within the column. -. -.TP -r,R -Right-justifies item within the column. -. -.TP -l,L -Left-justifies item within the column. -. -.TP -n,N -Numerically justifies item in the column: Units positions of numbers are -aligned vertically. -. -.TP -s,S -Spans previous item on the left into this column. -. -.TP -a,A -Centers longest line in this column and then left-justifies all other lines -in this column with respect to that centered line. -. -.TP -^ -Spans down entry from previous row in this column. -. -.TP -_,- -Replaces this entry with a horizontal line. -. -.TP -= -. -Replaces this entry with a double horizontal line. -. -.TP -| -The corresponding column becomes a vertical rule (if two of these are -adjacent, a double vertical rule). -. -.LP -A vertical bar to the left of the first key-letter or to the right of the -last one produces a line at the edge of the table. -.LP -Here are the specifiers that can appear in suffixes to column key letters: -. -.TP -b,B -Short form of fB (make affected entries bold). -. -.TP -i,I -Short form of fI (make affected entries italic). -. -.TP -t,T -Start an item vertically spanning rows at the top of its range rather than -vertically centering it. -. -.TP -d,D -Start an item vertically spanning rows at the bottom of its range rather -than vertically centering it (GNU tbl only). -. -.TP -v,V -Followed by a number, this indicates the vertical line spacing to be used in -a multi-line table entry. -If signed, the current vertical line spacing is incremented or decremented -(using a signed number instead of a signed digit is a GNU tbl extension). -A vertical line spacing specifier followed by a column separation number -must be separated by one or more blanks. -No effect if the corresponding table entry isn't a text block. -. -.TP -f,F -Either of these specifiers may be followed by a font name (either one or two -characters long), font number (a single digit), or long name in parentheses -(the last form is a GNU tbl extension). -A one-letter font name must be separated by one or more blanks from whatever -follows. -. -.TP -p,P -Followed by a number, this does a point size change for the affected fields. -If signed, the current point size is incremented or decremented (using a -signed number instead of a signed digit is a GNU tbl extension). -A point size specifier followed by a column separation number must be -separated by one or more blanks. -. -.TP -w,W -Minimal column width value. -Must be followed either by a -.BR @g@troff (@MAN1EXT@) -width expression in parentheses or a unitless integer. -If no unit is given, en units are used. -Also used as the default line length for included text blocks. -If used multiple times to specify the width for a particular column, -the last entry takes effect. -. -.TP -x,X -This is a GNU tbl extension. -Either of these specifiers may be followed by a macro name -(either one or two characters long), -or long name in parentheses. -A one-letter macro name must be separated by one or more blanks -from whatever follows. -The macro which name can be specified here -must be defined before creating the table. -It is called just before the table's cell text is output. -As implemented currently, this macro is only called if block input is used, -that is, text between `T{' and `T}'. -The macro should contain only simple -.B troff -requests to change the text block formatting, like text adjustment, -hyphenation, size, or font. -The macro is called -.I after -other cell modifications like -.BR b , -.B f -or -.B v -are output. -Thus the macro can overwrite other modification specifiers. -. -.TP -e,E -Make equally-spaced columns. -. -.TP -u,U -Move the corresponding column up one half-line. -. -.TP -z,Z -Ignore the corresponding column for width-calculation purposes. -. -.LP -A number suffix on a key character is interpreted as a column -separation in ens (multiplied in proportion if the -.B expand -option is on). -Default separation is 3n. -.LP -The format lines are followed by lines containing the actual data for the -table, followed finally by -.BR .TE . -Within such data lines, items are normally separated by tab characters (or -the character specified with the -.B tab -option). -Long input lines can be broken across multiple lines if the last character -on the line is `\e' (which vanishes after concatenation). -.LP -A dot starting a line, followed by anything but a digit is handled as a -troff command, passed through without changes. -The table position is unchanged in this case. -.LP -If a data line consists of only `_' or `=', a single or double line, -respectively, is drawn across the table at that point; if a single item in a -data line consists of only `_' or `=', then that item is replaced by a -single or double line, joining its neighbours. -If a data item consists only of `\e_' or `\e=', a single or double line, -respectively, is drawn across the field at that point which does not join -its neighbours. -.LP -A data item consisting only of `\eRx' (`x' any character) is replaced by -repetitions of character `x' as wide as the column (not joining its -neighbours). -.LP -A data item consisting only of `\e^' indicates that the field immediately -above spans downward over this row. -.LP -A text block can be used to enter data as a single entry which would be -too long as a simple string between tabs. -It is started with `T{' and closed with `T}'. -The former must end a line, and the latter must start a line, probably -followed by other data columns (separated with tabs). -By default, the text block is formatted with the settings which were -active before entering the table, possibly overridden by the -.B v -and -.B w -tbl specifiers. -For example, to make all text blocks ragged-right, insert -.B .na -right before the starting -.B .TS -(and -.B .ad -after the table). -.LP -To change the data format within a table, use the -.B .T& -command (at the start of a line). -It is followed by format and data lines (but no global options) similar to -the -.B .TS -request. -. -. -.SH "INTERACTION WITH @G@EQN" -.BR @g@tbl (@MAN1EXT@) -should always be called before -.BR @g@eqn (@MAN1EXT@) -.RB ( groff (@MAN1EXT@) -automatically takes care of the correct order of preprocessors). -. -. -.SH "GNU TBL ENHANCEMENTS" -There is no limit on the number of columns in a table, nor any limit on the -number of text blocks. -All the lines of a table are considered in deciding column widths, not just -the first 200. -Table continuation -.RB ( .T& ) -lines are not restricted to the first 200 lines. -.LP -Numeric and alphabetic items may appear in the same column. -.LP -Numeric and alphabetic items may span horizontally. -.LP -.B @g@tbl -uses register, string, macro and diversion names beginning with the digit\~\c -.BR 3 . -When using -.B @g@tbl -you should avoid using any names beginning with a\~\c -.BR 3 . -. -. -.SH BUGS -You should use -.BR .TS\ H / .TH -in conjunction with a supporting macro package for -.I all -multi-page boxed tables. -If there is no header that you wish to appear at the top of each page -of the table, place the -.B .TH -line immediately after the format section. -Do not enclose a multi-page table within keep/release macros, -or divert it in any other way. -.LP -A text block within a table must be able to fit on one page. -.LP -The -.B bp -request cannot be used to force a page-break in a multi-page table. -Instead, define -.B BP -as follows -.IP -.B .de BP -.br -.B .ie '\e\en(.z'' .bp \e\e$1 -.br -.B .el \e!.BP \e\e$1 -.br -.B .. -.br -.LP -and use -.B BP -instead of -.BR bp . -.LP -Using \ea directly in a table to get leaders will not work (except in -compatibility mode). -This is correct behaviour: \ea is an -.B uninterpreted -leader. -To get leaders use a real leader, either by using a control A or like -this: -.IP -.nf -.ft B -\&.ds a \ea -\&.TS -tab(;); -lw(1i) l. -A\e*a;B -\&.TE -.ft -.fi -. -. -.SH REFERENCE -Lesk, M.E.: "TBL -- A Program to Format Tables". -For copyright reasons it cannot be included in the groff distribution, -but copies can be found with a title search on the World Wide Web. -. -. -.SH "SEE ALSO" -.BR groff (@MAN1EXT@), -.BR @g@troff (@MAN1EXT@) -. -.\" Local Variables: -.\" mode: nroff -.\" End: -- cgit v1.2.3