arg1); break;
- case BREAK_TAG: break;
- case COLOR_TAG: issue_color_begin(&t->col); break;
-
- default:
- error("unrecognised tag");
- }
-}
-
-/*
- * flush_text - flushes html tags which are outstanding on the html stack.
- */
-
-void html_text::flush_text (void)
-{
- int notext=TRUE;
- tag_definition *p=stackptr;
-
- while (stackptr != 0) {
- notext = (notext && (! stackptr->text_emitted));
- if (! notext) {
- end_tag(stackptr);
- }
- p = stackptr;
- stackptr = stackptr->next;
- free(p);
- }
- lastptr = NULL;
-}
-
-/*
- * is_present - returns TRUE if tag is already present on the stack.
- */
-
-int html_text::is_present (HTML_TAG t)
-{
- tag_definition *p=stackptr;
-
- while (p != NULL) {
- if (t == p->type)
- return TRUE;
- p = p->next;
- }
- return FALSE;
-}
-
-extern void stop();
-
-/*
- * do_push - places, tag_definition, p, onto the stack
- */
-
-void html_text::do_push (tag_definition *p)
-{
- HTML_TAG t = p->type;
-
-#if defined(DEBUGGING)
- if (t == PRE_TAG)
- stop();
- debugStack = TRUE;
- fprintf(stderr, "\nentering do_push (");
- dump_stack_element(p);
- fprintf(stderr, ")\n");
- dump_stack();
- fprintf(stderr, ")\n");
- fflush(stderr);
-#endif
-
- /*
- * if t is a P_TAG or PRE_TAG make sure it goes on the end of the stack.
- */
-
- if (((t == P_TAG) || (t == PRE_TAG)) && (lastptr != NULL)) {
- /*
- * store, p, at the end
- */
- lastptr->next = p;
- lastptr = p;
- p->next = NULL;
- } else {
- p->next = stackptr;
- if (stackptr == NULL)
- lastptr = p;
- stackptr = p;
- }
-
-#if defined(DEBUGGING)
- dump_stack();
- fprintf(stderr, "exiting do_push\n");
-#endif
-}
-
-/*
- * push_para - adds a new entry onto the html paragraph stack.
- */
-
-void html_text::push_para (HTML_TAG t, void *arg, html_indent *in)
-{
- tag_definition *p=(tag_definition *)malloc(sizeof(tag_definition));
-
- p->type = t;
- p->arg1 = arg;
- p->text_emitted = FALSE;
- p->indent = in;
-
- if (t == PRE_TAG && is_present(PRE_TAG))
- fatal("cannot have multiple PRE_TAGs");
-
- do_push(p);
-}
-
-void html_text::push_para (HTML_TAG t)
-{
- push_para(t, (void *)"", NULL);
-}
-
-void html_text::push_para (color *c)
-{
- tag_definition *p=(tag_definition *)malloc(sizeof(tag_definition));
-
- p->type = COLOR_TAG;
- p->arg1 = NULL;
- p->col = *c;
- p->text_emitted = FALSE;
- p->indent = NULL;
-
- do_push(p);
-}
-
-/*
- * do_italic - changes to italic
- */
-
-void html_text::do_italic (void)
-{
- if (! is_present(I_TAG))
- push_para(I_TAG);
-}
-
-/*
- * do_bold - changes to bold.
- */
-
-void html_text::do_bold (void)
-{
- if (! is_present(B_TAG))
- push_para(B_TAG);
-}
-
-/*
- * do_tt - changes to teletype.
- */
-
-void html_text::do_tt (void)
-{
- if ((! is_present(TT_TAG)) && (! is_present(PRE_TAG)))
- push_para(TT_TAG);
-}
-
-/*
- * do_pre - changes to preformated text.
- */
-
-void html_text::do_pre (void)
-{
- done_tt();
- if (is_present(P_TAG)) {
- html_indent *i = remove_indent(P_TAG);
- (void)done_para();
- if (! is_present(PRE_TAG))
- push_para(PRE_TAG, NULL, i);
- } else if (! is_present(PRE_TAG))
- push_para(PRE_TAG, NULL, NULL);
- dump_stack();
-}
-
-/*
- * is_in_pre - returns TRUE if we are currently within a preformatted
- * block.
- */
-
-int html_text::is_in_pre (void)
-{
- return is_present(PRE_TAG);
-}
-
-/*
- * do_color - initiates a new color tag.
- */
-
-void html_text::do_color (color *c)
-{
- shutdown(COLOR_TAG); // shutdown a previous color tag, if present
- push_para(c);
-}
-
-/*
- * done_color - shutdown an outstanding color tag, if it exists.
- */
-
-void html_text::done_color (void)
-{
- shutdown(COLOR_TAG);
-}
-
-/*
- * shutdown - shuts down an html tag.
- */
-
-char *html_text::shutdown (HTML_TAG t)
-{
- char *arg=NULL;
-
- if (is_present(t)) {
- tag_definition *p =stackptr;
- tag_definition *temp =NULL;
- int notext =TRUE;
-
- dump_stack();
- while ((stackptr != NULL) && (stackptr->type != t)) {
- notext = (notext && (! stackptr->text_emitted));
- if (! notext) {
- end_tag(stackptr);
- }
-
- /*
- * pop tag
- */
- p = stackptr;
- stackptr = stackptr->next;
- if (stackptr == NULL)
- lastptr = NULL;
-
- /*
- * push tag onto temp stack
- */
- p->next = temp;
- temp = p;
- }
-
- /*
- * and examine stackptr
- */
- if ((stackptr != NULL) && (stackptr->type == t)) {
- if (stackptr->text_emitted) {
- end_tag(stackptr);
- }
- if (t == P_TAG) {
- arg = (char *)stackptr->arg1;
- }
- p = stackptr;
- stackptr = stackptr->next;
- if (stackptr == NULL)
- lastptr = NULL;
- if (p->indent != NULL)
- delete p->indent;
- free(p);
- }
-
- /*
- * and restore unaffected tags
- */
- while (temp != NULL) {
- if (temp->type == COLOR_TAG)
- push_para(&temp->col);
- else
- push_para(temp->type, temp->arg1, temp->indent);
- p = temp;
- temp = temp->next;
- free(p);
- }
- }
- return arg;
-}
-
-/*
- * done_bold - shuts downs a bold tag.
- */
-
-void html_text::done_bold (void)
-{
- shutdown(B_TAG);
-}
-
-/*
- * done_italic - shuts downs an italic tag.
- */
-
-void html_text::done_italic (void)
-{
- shutdown(I_TAG);
-}
-
-/*
- * done_sup - shuts downs a sup tag.
- */
-
-void html_text::done_sup (void)
-{
- shutdown(SUP_TAG);
-}
-
-/*
- * done_sub - shuts downs a sub tag.
- */
-
-void html_text::done_sub (void)
-{
- shutdown(SUB_TAG);
-}
-
-/*
- * done_tt - shuts downs a tt tag.
- */
-
-void html_text::done_tt (void)
-{
- shutdown(TT_TAG);
-}
-
-/*
- * done_pre - shuts downs a pre tag.
- */
-
-void html_text::done_pre (void)
-{
- shutdown(PRE_TAG);
-}
-
-/*
- * done_small - shuts downs a small tag.
- */
-
-void html_text::done_small (void)
-{
- shutdown(SMALL_TAG);
-}
-
-/*
- * done_big - shuts downs a big tag.
- */
-
-void html_text::done_big (void)
-{
- shutdown(BIG_TAG);
-}
-
-/*
- * check_emit_text - ensures that all previous tags have been emitted (in order)
- * before the text is written.
- */
-
-void html_text::check_emit_text (tag_definition *t)
-{
- if ((t != NULL) && (! t->text_emitted)) {
- check_emit_text(t->next);
- t->text_emitted = TRUE;
- start_tag(t);
- }
-}
-
-/*
- * do_emittext - tells the class that text was written during the current tag.
- */
-
-void html_text::do_emittext (const char *s, int length)
-{
- if ((! is_present(P_TAG)) && (! is_present(PRE_TAG)))
- do_para("");
-
- if (is_present(BREAK_TAG)) {
- int text = remove_break();
- check_emit_text(stackptr);
- if (text) {
- if (is_present(PRE_TAG)) {
- out->nl();
- } else {
- out->put_string("
").nl();
- }
- }
- } else {
- check_emit_text(stackptr);
- }
- out->put_string(s, length);
- space_emitted = FALSE;
- blank_para = FALSE;
-}
-
-/*
- * do_para - starts a new paragraph
- */
-
-void html_text::do_para (const char *arg, html_indent *in)
-{
- if (! is_present(P_TAG)) {
- if (is_present(PRE_TAG)) {
- html_indent *i = remove_indent(PRE_TAG);
- done_pre();
- if (i == in || in == NULL)
- in = i;
- else
- delete i;
- }
- remove_sub_sup();
- push_para(P_TAG, (void *)arg, in);
- space_emitted = TRUE;
- }
-}
-
-void html_text::do_para (const char *arg)
-{
- do_para(arg, NULL);
-}
-
-void html_text::do_para (simple_output *op, const char *arg1,
- int indentation, int pageoffset, int linelength)
-{
- html_indent *indent;
-
- if (indentation == 0)
- indent = NULL;
- else
- indent = new html_indent(op, indentation, pageoffset, linelength);
- do_para(arg1, indent);
-}
-
-/*
- * done_para - shuts down a paragraph tag.
- */
-
-char *html_text::done_para (void)
-{
- space_emitted = TRUE;
- return shutdown(P_TAG);
-}
-
-/*
- * remove_indent - returns the indent associated with, tag.
- * The indent associated with tag is set to NULL.
- */
-
-html_indent *html_text::remove_indent (HTML_TAG tag)
-{
- tag_definition *p=stackptr;
-
- while (p != NULL) {
- if (tag == p->type) {
- html_indent *i = p->indent;
- p->indent = NULL;
- return i;
- }
- p = p->next;
- }
- return NULL;
-}
-
-/*
- * do_space - issues an end of paragraph
- */
-
-void html_text::do_space (void)
-{
- if (is_in_pre()) {
- if (blank_para)
- start_space = TRUE;
- else {
- do_emittext("", 0);
- out->nl();
- }
- } else {
- html_indent *i = remove_indent(P_TAG);
-
- do_para(done_para(), i);
- space_emitted = TRUE;
- start_space = TRUE;
- }
-}
-
-/*
- * do_break - issue a break tag.
- */
-
-void html_text::do_break (void)
-{
- if (! is_present(PRE_TAG)) {
- if (emitted_text()) {
- if (! is_present(BREAK_TAG)) {
- push_para(BREAK_TAG);
- }
- }
- }
- space_emitted = TRUE;
-}
-
-/*
- * do_newline - issue a newline providing that we are inside a tag.
- */
-
-void html_text::do_newline (void)
-{
- if (is_present(PRE_TAG)) {
- do_emittext("\n", 1);
- space_emitted = TRUE;
- }
-}
-
-/*
- * emitted_text - returns FALSE if white space has just been written.
- */
-
-int html_text::emitted_text (void)
-{
- return !space_emitted;
-}
-
-/*
- * ever_emitted_text - returns TRUE if we have ever emitted text in this paragraph.
- */
-
-int html_text::ever_emitted_text (void)
-{
- return !blank_para;
-}
-
-/*
- * starts_with_space - returns TRUE if we have start this paragraph with a .sp
- */
-
-int html_text::starts_with_space (void)
-{
- return start_space;
-}
-
-/*
- * emit_space - writes a space providing that text was written beforehand.
- */
-
-void html_text::emit_space (void)
-{
- if (space_emitted) {
- if (is_present(PRE_TAG)) {
- do_emittext(" ", 1);
- }
- } else {
- out->space_or_newline();
- space_emitted = TRUE;
- }
-}
-
-/*
- * remove_def - removes a definition, t, from the stack.
- */
-
-void html_text::remove_def (tag_definition *t)
-{
- tag_definition *p = stackptr;
- tag_definition *l = 0;
- tag_definition *q = 0;
-
- while ((p != 0) && (p != t)) {
- l = p;
- p = p->next;
- }
- if ((p != 0) && (p == t)) {
- if (p == stackptr) {
- stackptr = stackptr->next;
- if (stackptr == NULL)
- lastptr = NULL;
- q = stackptr;
- } else if (l == 0) {
- error("stack list pointers are wrong");
- } else {
- l->next = p->next;
- q = p->next;
- if (l->next == NULL)
- lastptr = l;
- }
- free(p);
- }
-}
-
-/*
- * remove_tag - removes a tag from the stack.
- */
-
-void html_text::remove_tag (HTML_TAG tag)
-{
- tag_definition *p = stackptr;
-
- while ((p != 0) && (p->type != tag)) {
- p = p->next;
- }
- if ((p != 0) && (p->type == tag))
- remove_def(p);
-}
-
-/*
- * remove_sub_sup - removes a sub or sup tag, should either exist on the stack.
- */
-
-void html_text::remove_sub_sup (void)
-{
- if (is_present(SUB_TAG)) {
- remove_tag(SUB_TAG);
- }
- if (is_present(SUP_TAG)) {
- remove_tag(SUP_TAG);
- }
- if (is_present(PRE_TAG)) {
- remove_tag(PRE_TAG);
- }
-}
-
-/*
- * remove_break - break tags are not balanced thus remove it once it has been emitted.
- * It returns TRUE if text was emitted before the
was issued.
- */
-
-int html_text::remove_break (void)
-{
- tag_definition *p = stackptr;
- tag_definition *l = 0;
- tag_definition *q = 0;
-
- while ((p != 0) && (p->type != BREAK_TAG)) {
- l = p;
- p = p->next;
- }
- if ((p != 0) && (p->type == BREAK_TAG)) {
- if (p == stackptr) {
- stackptr = stackptr->next;
- if (stackptr == NULL)
- lastptr = NULL;
- q = stackptr;
- } else if (l == 0)
- error("stack list pointers are wrong");
- else {
- l->next = p->next;
- q = p->next;
- if (l->next == NULL)
- lastptr = l;
- }
- free(p);
- }
- /*
- * now determine whether text was issued before
- */
- while (q != 0) {
- if (q->text_emitted)
- return TRUE;
- else
- q = q->next;
- }
- return FALSE;
-}
-
-/*
- * remove_para_align - removes a paragraph which has a text
- * argument. If the paragraph has no text
- * argument then it is left alone.
- */
-
-void html_text::remove_para_align (void)
-{
- if (is_present(P_TAG)) {
- tag_definition *p=stackptr;
-
- while (p != NULL) {
- if (p->type == P_TAG && p->arg1 != NULL) {
- html_indent *i = remove_indent(P_TAG);
- done_para();
- do_para("", i);
- return;
- }
- p = p->next;
- }
- }
-}
-
-/*
- * do_small - potentially inserts a tag into the html stream.
- * However we check for a tag, if present then we terminate it.
- * Otherwise a tag is inserted.
- */
-
-void html_text::do_small (void)
-{
- if (is_present(BIG_TAG))
- done_big();
- else
- push_para(SMALL_TAG);
-}
-
-/*
- * do_big - is the mirror image of do_small.
- */
-
-void html_text::do_big (void)
-{
- if (is_present(SMALL_TAG))
- done_small();
- else
- push_para(BIG_TAG);
-}
-
-/*
- * do_sup - save a superscript tag on the stack of tags.
- */
-
-void html_text::do_sup (void)
-{
- push_para(SUP_TAG);
-}
-
-/*
- * do_sub - save a subscript tag on the stack of tags.
- */
-
-void html_text::do_sub (void)
-{
- push_para(SUB_TAG);
-}
-
diff --git a/contrib/groff/src/devices/grohtml/output.cc b/contrib/groff/src/devices/grohtml/output.cc
deleted file mode 100644
index 67d5874..0000000
--- a/contrib/groff/src/devices/grohtml/output.cc
+++ /dev/null
@@ -1,356 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
- *
- * Gaius Mulley (gaius@glam.ac.uk) wrote output.cc
- * but it owes a huge amount of ideas and raw code from
- * James Clark (jjc@jclark.com) grops/ps.cc.
- *
- * output.cc
- *
- * provide the simple low level output routines needed by html.cc
- */
-
-/*
-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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "driver.h"
-#include "stringclass.h"
-#include "cset.h"
-
-#include
-#include "html.h"
-
-#ifdef HAVE_UNISTD_H
-#include
-#endif
-
-#undef DEBUGGING
-// #define DEBUGGING
-
-#if !defined(TRUE)
-# define TRUE (1==1)
-#endif
-#if !defined(FALSE)
-# define FALSE (1==0)
-#endif
-
-
-#if defined(DEBUGGING)
-# define FPUTC(X,Y) do { fputc((X),(Y)); fputc((X), stderr); fflush(stderr); } while (0)
-# define FPUTS(X,Y) do { fputs((X),(Y)); fputs((X), stderr); fflush(stderr); } while (0)
-# define PUTC(X,Y) do { putc((X),(Y)); putc((X), stderr); fflush(stderr); } while (0)
-#else
-# define FPUTC(X,Y) do { fputc((X),(Y)); } while (0)
-# define FPUTS(X,Y) do { fputs((X),(Y)); } while (0)
-# define PUTC(X,Y) do { putc((X),(Y)); } while (0)
-#endif
-
-
-/*
- * word - initialise a word and set next to NULL
- */
-
-word::word (const char *w, int n)
- : next(0)
-{
- s = (char *)malloc(n+1);
- strncpy(s, w, n);
- s[n] = (char)0;
-}
-
-/*
- * destroy word and the string copy.
- */
-
-word::~word ()
-{
- free(s);
-}
-
-/*
- * word_list - create an empty word list.
- */
-
-word_list::word_list ()
- : length(0), head(0), tail(0)
-{
-}
-
-/*
- * flush - flush a word list to a FILE, f, and return the
- * length of the buffered string.
- */
-
-int word_list::flush (FILE *f)
-{
- word *t;
- int len=length;
-
- while (head != 0) {
- t = head;
- head = head->next;
- FPUTS(t->s, f);
- delete t;
- }
- head = 0;
- tail = 0;
- length = 0;
-#if defined(DEBUGGING)
- fflush(f); // just for testing
-#endif
- return( len );
-}
-
-/*
- * add_word - adds a word to the outstanding word list.
- */
-
-void word_list::add_word (const char *s, int n)
-{
- if (head == 0) {
- head = new word(s, n);
- tail = head;
- } else {
- tail->next = new word(s, n);
- tail = tail->next;
- }
- length += n;
-}
-
-/*
- * get_length - returns the number of characters buffered
- */
-
-int word_list::get_length (void)
-{
- return( length );
-}
-
-/*
- * the classes and methods for simple_output manipulation
- */
-
-simple_output::simple_output(FILE *f, int n)
-: fp(f), max_line_length(n), col(0), fixed_point(0), newlines(0)
-{
-}
-
-simple_output &simple_output::set_file(FILE *f)
-{
- if (fp)
- fflush(fp);
- fp = f;
- return *this;
-}
-
-simple_output &simple_output::copy_file(FILE *infp)
-{
- int c;
- while ((c = getc(infp)) != EOF)
- PUTC(c, fp);
- return *this;
-}
-
-simple_output &simple_output::end_line()
-{
- flush_last_word();
- if (col != 0) {
- PUTC('\n', fp);
- col = 0;
- }
- return *this;
-}
-
-simple_output &simple_output::special(const char *s)
-{
- return *this;
-}
-
-simple_output &simple_output::simple_comment(const char *s)
-{
- flush_last_word();
- if (col != 0)
- PUTC('\n', fp);
- FPUTS("\n", fp);
- col = 0;
- return *this;
-}
-
-simple_output &simple_output::begin_comment(const char *s)
-{
- flush_last_word();
- if (col != 0)
- PUTC('\n', fp);
- col = 0;
- put_string("").nl();
- return *this;
-}
-
-/*
- * check_newline - checks to see whether we are able to issue
- * a newline and that one is needed.
- */
-
-simple_output &simple_output::check_newline(int n)
-{
- if ((col + n + last_word.get_length() + 1 > max_line_length) && (newlines)) {
- FPUTC('\n', fp);
- col = last_word.flush(fp);
- }
- return *this;
-}
-
-/*
- * space_or_newline - will emit a newline or a space later on
- * depending upon the current column.
- */
-
-simple_output &simple_output::space_or_newline (void)
-{
- if ((col + last_word.get_length() + 1 > max_line_length) && (newlines)) {
- FPUTC('\n', fp);
- if (last_word.get_length() > 0) {
- col = last_word.flush(fp);
- } else {
- col = 0;
- }
- } else {
- if (last_word.get_length() != 0) {
- if (col > 0) {
- FPUTC(' ', fp);
- col++;
- }
- col += last_word.flush(fp);
- }
- }
- return *this;
-}
-
-/*
- * nl - writes a newline providing that we
- * are not in the first column.
- */
-
-simple_output &simple_output::nl (void)
-{
- space_or_newline();
- col += last_word.flush(fp);
- if (col != 0) {
- FPUTC('\n', fp);
- col = 0;
- }
- return *this ;
-}
-
-simple_output &simple_output::set_fixed_point(int n)
-{
- assert(n >= 0 && n <= 10);
- fixed_point = n;
- return *this;
-}
-
-simple_output &simple_output::put_raw_char(char c)
-{
- col += last_word.flush(fp);
- PUTC(c, fp);
- col++;
- return *this;
-}
-
-simple_output &simple_output::put_string(const char *s, int n)
-{
- last_word.add_word(s, n);
- return *this;
-}
-
-simple_output &simple_output::put_string(const char *s)
-{
- last_word.add_word(s, strlen(s));
- return *this;
-}
-
-simple_output &simple_output::put_string(const string &s)
-{
- last_word.add_word(s.contents(), s.length());
- return *this;
-}
-
-simple_output &simple_output::put_number(int n)
-{
- char buf[1 + INT_DIGITS + 1];
- sprintf(buf, "%d", n);
- put_string(buf);
- return *this;
-}
-
-simple_output &simple_output::put_float(double d)
-{
- char buf[128];
-
- sprintf(buf, "%.4f", d);
- put_string(buf);
- return *this;
-}
-
-simple_output &simple_output::enable_newlines (int auto_newlines)
-{
- check_newline(0);
- newlines = auto_newlines;
- check_newline(0);
- return *this;
-}
-
-/*
- * flush_last_word - flushes the last word and adjusts the
- * col position. It will insert a newline
- * before the last word if allowed and if
- * necessary.
- */
-
-void simple_output::flush_last_word (void)
-{
- int len=last_word.get_length();
-
- if (len > 0) {
- if (newlines) {
- if (col + len + 1 > max_line_length) {
- FPUTS("\n", fp);
- col = 0;
- } else {
- FPUTS(" ", fp);
- col++;
- }
- len += last_word.flush(fp);
- } else {
- FPUTS(" ", fp);
- col++;
- col += last_word.flush(fp);
- }
- }
-}
diff --git a/contrib/groff/src/devices/grohtml/post-html.cc b/contrib/groff/src/devices/grohtml/post-html.cc
deleted file mode 100644
index 4431f17..0000000
--- a/contrib/groff/src/devices/grohtml/post-html.cc
+++ /dev/null
@@ -1,3745 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
- *
- * Gaius Mulley (gaius@glam.ac.uk) wrote post-html.cc
- * but it owes a huge amount of ideas and raw code from
- * James Clark (jjc@jclark.com) grops/ps.cc.
- */
-
-/*
-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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "driver.h"
-#include "stringclass.h"
-#include "cset.h"
-#include "html.h"
-#include "html-text.h"
-#include "html-table.h"
-
-#include
-
-#ifdef HAVE_UNISTD_H
-#include
-#endif
-
-#include
-#include
-
-extern "C" const char *Version_string;
-
-#if !defined(TRUE)
-# define TRUE (1==1)
-#endif
-#if !defined(FALSE)
-# define FALSE (1==0)
-#endif
-
-#define MAX_LINE_LENGTH 60 /* maximum characters we want in a line */
-#define SIZE_INCREMENT 2 /* font size increment = +2 */
-#define BASE_POINT_SIZE 10 /* 10 points is the base size ie html size 3 */
-#define CENTER_TOLERANCE 2 /* how many pixels off center will we still */
-#define ANCHOR_TEMPLATE "heading" /* if simple anchor is set we use this */
-#define UNICODE_DESC_START 0x80 /* all character entities above this are */
- /* either encoded by their glyph names or if */
- /* there is no name then we use nnn; */
-typedef enum {CENTERED, LEFT, RIGHT, INLINE} TAG_ALIGNMENT;
-typedef enum {col_tag, tab_tag, tab0_tag, none} colType;
-
-#undef DEBUG_TABLES
-
-
-/*
- * prototypes
- */
-
-char *get_html_translation (font *f, const string &name);
-int char_translate_to_html (font *f, char *buf, int buflen, unsigned char ch, int b, int and_single);
-
-
-static int auto_links = TRUE; /* by default we enable automatic links at */
- /* top of the document. */
-static int auto_rule = TRUE; /* by default we enable an automatic rule */
- /* at the top and bottom of the document */
-static int simple_anchors = FALSE; /* default to anchors with heading text */
-static int manufacture_headings = FALSE; /* default is to use the Hn html headings, */
- /* rather than manufacture our own. */
-static color *default_background = NULL; /* has user requested initial bg color? */
-
-
-/*
- * start with a few favorites
- */
-
-void stop () {}
-
-static int min (int a, int b)
-{
- if (a < b)
- return a;
- else
- return b;
-}
-
-static int max (int a, int b)
-{
- if (a > b)
- return a;
- else
- return b;
-}
-
-/*
- * is_intersection - returns TRUE if range a1..a2 intersects with b1..b2
- */
-
-static int is_intersection (int a1, int a2, int b1, int b2)
-{
- // easier to prove NOT outside limits
- return( ! ((a1 > b2) || (a2 < b1)) );
-}
-
-/*
- * is_digit - returns TRUE if character, ch, is a digit.
- */
-
-static int is_digit (char ch)
-{
- return( (ch >= '0') && (ch <= '9') );
-}
-
-/*
- * the classes and methods for maintaining a list of files.
- */
-
-struct file {
- FILE *fp;
- file *next;
-
- file (FILE *f);
-};
-
-/*
- * file - initialize all fields to NULL
- */
-
-file::file (FILE *f)
- : fp(f), next(0)
-{
-}
-
-class files {
-public:
- files ();
- FILE *get_file (void);
- void start_of_list (void);
- void move_next (void);
- void add_new_file (FILE *f);
-private:
- file *head;
- file *tail;
- file *ptr;
-};
-
-/*
- * files - create an empty list of files.
- */
-
-files::files ()
- : head(0), tail(0), ptr(0)
-{
-}
-
-/*
- * get_file - returns the FILE associated with ptr.
- */
-
-FILE *files::get_file (void)
-{
- if (ptr) {
- return( ptr->fp );
- } else {
- return( 0 );
- }
-}
-
-/*
- * start_of_list - reset the ptr to the start of the list.
- */
-
-void files::start_of_list (void)
-{
- ptr = head;
-}
-
-/*
- * move_next - moves the ptr to the next element on the list.
- */
-
-void files::move_next (void)
-{
- if (ptr != 0)
- ptr = ptr->next;
-}
-
-/*
- * add_new_file - adds a new file, f, to the list.
- */
-
-void files::add_new_file (FILE *f)
-{
- if (head == 0) {
- head = new file(f);
- tail = head;
- } else {
- tail->next = new file(f);
- tail = tail->next;
- }
- ptr = tail;
-}
-
-/*
- * the class and methods for styles
- */
-
-struct style {
- font *f;
- int point_size;
- int font_no;
- int height;
- int slant;
- color col;
- style ();
- style (font *, int, int, int, int, color);
- int operator == (const style &) const;
- int operator != (const style &) const;
-};
-
-style::style()
- : f(0)
-{
-}
-
-style::style(font *p, int sz, int h, int sl, int no, color c)
- : f(p), point_size(sz), font_no(no), height(h), slant(sl), col(c)
-{
-}
-
-int style::operator==(const style &s) const
-{
- return (f == s.f && point_size == s.point_size
- && height == s.height && slant == s.slant && col == s.col);
-}
-
-int style::operator!=(const style &s) const
-{
- return !(*this == s);
-}
-
-/*
- * the class and methods for retaining ascii text
- */
-
-struct char_block {
- enum { SIZE = 256 };
- char *buffer;
- int used;
- char_block *next;
-
- char_block();
- char_block::char_block(int length);
-};
-
-char_block::char_block()
-: buffer(NULL), used(0), next(0)
-{
-}
-
-char_block::char_block(int length)
-: used(0), next(0)
-{
- buffer = (char *)malloc(max(length, char_block::SIZE));
- if (buffer == NULL)
- fatal("out of memory error");
-}
-
-class char_buffer {
-public:
- char_buffer();
- ~char_buffer();
- char *add_string(const char *, unsigned int);
- char *add_string(const string &);
-private:
- char_block *head;
- char_block *tail;
-};
-
-char_buffer::char_buffer()
-: head(0), tail(0)
-{
-}
-
-char_buffer::~char_buffer()
-{
- while (head != 0) {
- char_block *temp = head;
- head = head->next;
- delete temp;
- }
-}
-
-char *char_buffer::add_string (const char *s, unsigned int length)
-{
- int i=0;
- unsigned int old_used;
-
- if (s == NULL || length == 0)
- return NULL;
-
- if (tail == 0) {
- tail = new char_block(length+1);
- head = tail;
- } else {
- if (tail->used + length+1 > char_block::SIZE) {
- tail->next = new char_block(length+1);
- tail = tail->next;
- }
- }
-
- old_used = tail->used;
- do {
- tail->buffer[tail->used] = s[i];
- tail->used++;
- i++;
- length--;
- } while (length>0);
-
- // add terminating nul character
-
- tail->buffer[tail->used] = '\0';
- tail->used++;
-
- // and return start of new string
-
- return( &tail->buffer[old_used] );
-}
-
-char *char_buffer::add_string (const string &s)
-{
- return add_string(s.contents(), s.length());
-}
-
-/*
- * the classes and methods for maintaining glyph positions.
- */
-
-class text_glob {
-public:
- void text_glob_html (style *s, char *str, int length,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal);
- void text_glob_special (style *s, char *str, int length,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal);
- void text_glob_line (style *s,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal,
- int thickness);
- void text_glob_auto_image(style *s, char *str, int length,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal);
- void text_glob_tag (style *s, char *str, int length,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal);
-
- text_glob (void);
- ~text_glob (void);
- int is_a_line (void);
- int is_a_tag (void);
- int is_eol (void);
- int is_auto_img (void);
- int is_br (void);
- int is_in (void);
- int is_po (void);
- int is_ti (void);
- int is_ce (void);
- int is_eol_ce (void);
- int is_col (void);
- int is_tab (void);
- int is_tab0 (void);
- int is_ta (void);
- int is_tab_ts (void);
- int is_tab_te (void);
- int is_nf (void);
- int is_fi (void);
- int get_arg (void);
- int get_tab_args (char *align);
-
- void remember_table (html_table *t);
- html_table *get_table (void);
-
- style text_style;
- const char *text_string;
- unsigned int text_length;
- int minv, minh, maxv, maxh;
- int is_tag; // is this a .br, .sp, .tl etc
- int is_img_auto; // image created by eqn delim
- int is_special; // text has come via 'x X html:'
- int is_line; // is the command a ?
- int thickness; // the thickness of a line
- html_table *tab; // table description
-
-private:
- text_glob (style *s, char *str, int length,
- int min_vertical , int min_horizontal,
- int max_vertical , int max_horizontal,
- bool is_troff_command,
- bool is_auto_image, bool is_special_command,
- bool is_a_line , int thickness);
-};
-
-text_glob::text_glob (style *s, char *str, int length,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal,
- bool is_troff_command,
- bool is_auto_image, bool is_special_command,
- bool is_a_line, int line_thickness)
- : text_style(*s), text_string(str), text_length(length),
- minv(min_vertical), minh(min_horizontal), maxv(max_vertical), maxh(max_horizontal),
- is_tag(is_troff_command), is_img_auto(is_auto_image), is_special(is_special_command),
- is_line(is_a_line), thickness(line_thickness), tab(NULL)
-{
-}
-
-text_glob::text_glob ()
- : text_string(0), text_length(0), minv(-1), minh(-1), maxv(-1), maxh(-1),
- is_tag(FALSE), is_special(FALSE), is_line(FALSE), thickness(0), tab(NULL)
-{
-}
-
-text_glob::~text_glob ()
-{
- if (tab != NULL)
- delete tab;
-}
-
-/*
- * text_glob_html - used to place html text into the glob buffer.
- */
-
-void text_glob::text_glob_html (style *s, char *str, int length,
- int min_vertical , int min_horizontal,
- int max_vertical , int max_horizontal)
-{
- text_glob *g = new text_glob(s, str, length,
- min_vertical, min_horizontal, max_vertical, max_horizontal,
- FALSE, FALSE, FALSE, FALSE, 0);
- *this = *g;
-}
-
-/*
- * text_glob_html - used to place html specials into the glob buffer.
- * This text is essentially html commands coming through
- * from the macro sets, with special designated sequences of
- * characters translated into html. See add_and_encode.
- */
-
-void text_glob::text_glob_special (style *s, char *str, int length,
- int min_vertical , int min_horizontal,
- int max_vertical , int max_horizontal)
-{
- text_glob *g = new text_glob(s, str, length,
- min_vertical, min_horizontal, max_vertical, max_horizontal,
- FALSE, FALSE, TRUE, FALSE, 0);
- *this = *g;
-}
-
-/*
- * text_glob_line - record horizontal draw line commands.
- */
-
-void text_glob::text_glob_line (style *s,
- int min_vertical , int min_horizontal,
- int max_vertical , int max_horizontal,
- int thickness)
-{
- text_glob *g = new text_glob(s, "", 0,
- min_vertical, min_horizontal, max_vertical, max_horizontal,
- FALSE, FALSE, FALSE, TRUE, thickness);
- *this = *g;
-}
-
-/*
- * text_glob_auto_image - record the presence of a .auto-image tag command.
- * Used to mark that an image has been created automatically
- * by a preprocessor and (pre-grohtml/troff) combination.
- * Under some circumstances images may not be created.
- * (consider .EQ
- * delim $$
- * .EN
- * .TS
- * tab(!), center;
- * l!l.
- * $1 over x$!recripical of x
- * .TE
- *
- * the first auto-image marker is created via .EQ/.EN pair
- * and no image is created.
- * The second auto-image marker occurs at $1 over x$
- * Currently this image will not be created
- * as the whole of the table is created as an image.
- * (Once html tables are handled by grohtml this will change.
- * Shortly this will be the case).
- */
-
-void text_glob::text_glob_auto_image(style *s, char *str, int length,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal)
-{
- text_glob *g = new text_glob(s, str, length,
- min_vertical, min_horizontal, max_vertical, max_horizontal,
- TRUE, TRUE, FALSE, FALSE, 0);
- *this = *g;
-}
-
-/*
- * text_glob_tag - records a troff tag.
- */
-
-void text_glob::text_glob_tag (style *s, char *str, int length,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal)
-{
- text_glob *g = new text_glob(s, str, length,
- min_vertical, min_horizontal, max_vertical, max_horizontal,
- TRUE, FALSE, FALSE, FALSE, 0);
- *this = *g;
-}
-
-/*
- * is_a_line - returns TRUE if glob should be converted into an
- */
-
-int text_glob::is_a_line (void)
-{
- return is_line;
-}
-
-/*
- * is_a_tag - returns TRUE if glob contains a troff directive.
- */
-
-int text_glob::is_a_tag (void)
-{
- return is_tag;
-}
-
-/*
- * is_eol - returns TRUE if glob contains the tag eol
- */
-
-int text_glob::is_eol (void)
-{
- return( is_tag && (strcmp(text_string, "html-tag:eol") == 0) );
-}
-
-/*
- * is_eol_ce - returns TRUE if glob contains the tag eol.ce
- */
-
-int text_glob::is_eol_ce (void)
-{
- return( is_tag && (strcmp(text_string, "html-tag:eol.ce") == 0) );
-}
-
-
-/*
- * is_nf - returns TRUE if glob contains the tag .nf
- */
-
-int text_glob::is_nf (void)
-{
- return( is_tag && (strcmp(text_string, "html-tag:.nf") == 0) );
-}
-
-/*
- * is_fi - returns TRUE if glob contains the tag .fi
- */
-
-int text_glob::is_fi (void)
-{
- return( is_tag && (strcmp(text_string, "html-tag:.fi") == 0) );
-}
-
-/*
- * is_ce - returns TRUE if glob contains the tag .ce
- */
-
-int text_glob::is_ce (void)
-{
- return( is_tag && (strcmp(text_string, "html-tag:.ce") == 0) );
-}
-
-/*
- * is_in - returns TRUE if glob contains the tag .in
- */
-
-int text_glob::is_in (void)
-{
- return( is_tag && (strncmp(text_string, "html-tag:.in ", strlen("html-tag:.in ")) == 0) );
-}
-
-/*
- * is_po - returns TRUE if glob contains the tag .po
- */
-
-int text_glob::is_po (void)
-{
- return( is_tag && (strncmp(text_string, "html-tag:.po ", strlen("html-tag:.po ")) == 0) );
-}
-
-/*
- * is_ti - returns TRUE if glob contains the tag .ti
- */
-
-int text_glob::is_ti (void)
-{
- return( is_tag && (strncmp(text_string, "html-tag:.ti ", strlen("html-tag:.ti ")) == 0) );
-}
-
-/*
- * is_col - returns TRUE if glob contains the tag .col
- */
-
-int text_glob::is_col (void)
-{
- return( is_tag && (strncmp(text_string, "html-tag:.col", strlen("html-tag:.col")) == 0) );
-}
-
-/*
- * is_tab_ts - returns TRUE if glob contains the tag .tab_ts
- */
-
-int text_glob::is_tab_ts (void)
-{
- return( is_tag && (strcmp(text_string, "html-tag:.tab-ts") == 0) );
-}
-
-/*
- * is_tab_te - returns TRUE if glob contains the tag .tab_te
- */
-
-int text_glob::is_tab_te (void)
-{
- return( is_tag && (strcmp(text_string, "html-tag:.tab-te") == 0) );
-}
-
-/*
- * is_ta - returns TRUE if glob contains the tag .ta
- */
-
-int text_glob::is_ta (void)
-{
- return( is_tag && (strncmp(text_string, "html-tag:.ta ", strlen("html-tag:.ta ")) == 0) );
-}
-
-/*
- * is_tab - returns TRUE if glob contains the tag tab
- */
-
-int text_glob::is_tab (void)
-{
- return( is_tag && (strncmp(text_string, "html-tag:tab ", strlen("html-tag:tab ")) == 0) );
-}
-
-/*
- * is_tab0 - returns TRUE if glob contains the tag tab0
- */
-
-int text_glob::is_tab0 (void)
-{
- return( is_tag && (strncmp(text_string, "html-tag:tab0", strlen("html-tag:tab0")) == 0) );
-}
-
-/*
- * is_auto_img - returns TRUE if the glob contains an automatically
- * generated image.
- */
-
-int text_glob::is_auto_img (void)
-{
- return is_img_auto;
-}
-
-/*
- * is_br - returns TRUE if the glob is a tag containing a .br
- * or an implied .br. Note that we do not include .nf or .fi
- * as grohtml will place a .br after these commands if they
- * should break the line.
- */
-
-int text_glob::is_br (void)
-{
- return( is_a_tag() && ((strcmp ("html-tag:.br", text_string) == 0) ||
- (strncmp("html-tag:.sp", text_string, 11) == 0) ||
- (strcmp ("html-tag:.ce", text_string) == 0)) );
-}
-
-int text_glob::get_arg (void)
-{
- if (strncmp("html-tag:", text_string, strlen("html-tag:")) == 0) {
- const char *p = text_string;
-
- while ((*p != (char)0) && (!isspace(*p)))
- p++;
- while ((*p != (char)0) && (isspace(*p)))
- p++;
- if (*p == (char)0)
- return -1;
- return atoi(p);
- }
- return -1;
-}
-
-/*
- * get_tab_args - returns the tab position and alignment of the tab tag
- */
-
-int text_glob::get_tab_args (char *align)
-{
- if (strncmp("html-tag:", text_string, strlen("html-tag:")) == 0) {
- const char *p = text_string;
-
- // firstly the alignment C|R|L
- while ((*p != (char)0) && (!isspace(*p)))
- p++;
- while ((*p != (char)0) && (isspace(*p)))
- p++;
- *align = *p;
- // now the int value
- while ((*p != (char)0) && (!isspace(*p)))
- p++;
- while ((*p != (char)0) && (isspace(*p)))
- p++;
- if (*p == (char)0)
- return -1;
- return atoi(p);
- }
- return -1;
-}
-
-/*
- * remember_table - saves table, t, in the text_glob.
- */
-
-void text_glob::remember_table (html_table *t)
-{
- tab = t;
-}
-
-/*
- * get_table - returns the stored table description.
- */
-
-html_table *text_glob::get_table (void)
-{
- return tab;
-}
-
-/*
- * the class and methods used to construct ordered double linked lists.
- * In a previous implementation we used templates via #include "ordered-list.h",
- * but this does assume that all C++ compilers can handle this feature. Pragmatically
- * it is safer to assume this is not the case.
- */
-
-struct element_list {
- element_list *right;
- element_list *left;
- text_glob *datum;
- int lineno;
- int minv, minh, maxv, maxh;
-
- element_list (text_glob *d,
- int line_number,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal);
- element_list ();
-};
-
-element_list::element_list ()
- : right(0), left(0), datum(0), lineno(0), minv(-1), minh(-1), maxv(-1), maxh(-1)
-{
-}
-
-/*
- * element_list - create a list element assigning the datum and region parameters.
- */
-
-element_list::element_list (text_glob *in,
- int line_number,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal)
- : right(0), left(0), datum(in), lineno(line_number),
- minv(min_vertical), minh(min_horizontal), maxv(max_vertical), maxh(max_horizontal)
-{
-}
-
-class list {
-public:
- list ();
- ~list ();
- int is_less (element_list *a, element_list *b);
- void add (text_glob *in,
- int line_number,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal);
- void sub_move_right (void);
- void move_right (void);
- void move_left (void);
- int is_empty (void);
- int is_equal_to_tail (void);
- int is_equal_to_head (void);
- void start_from_head (void);
- void start_from_tail (void);
- void insert (text_glob *in);
- void move_to (text_glob *in);
- text_glob *move_right_get_data (void);
- text_glob *move_left_get_data (void);
- text_glob *get_data (void);
-private:
- element_list *head;
- element_list *tail;
- element_list *ptr;
-};
-
-/*
- * list - construct an empty list.
- */
-
-list::list ()
- : head(0), tail(0), ptr(0)
-{
-}
-
-/*
- * ~list - destroy a complete list.
- */
-
-list::~list()
-{
- element_list *temp=head;
-
- do {
- temp = head;
- if (temp != 0) {
- head = head->right;
- delete temp;
- }
- } while ((head != 0) && (head != tail));
-}
-
-/*
- * is_less - returns TRUE if a is left of b if on the same line or
- * if a is higher up the page than b.
- */
-
-int list::is_less (element_list *a, element_list *b)
-{
- // was if (is_intersection(a->minv+1, a->maxv-1, b->minv+1, b->maxv-1)) {
- if (a->lineno < b->lineno) {
- return( TRUE );
- } else if (a->lineno > b->lineno) {
- return( FALSE );
- } else if (is_intersection(a->minv, a->maxv, b->minv, b->maxv)) {
- return( a->minh < b->minh );
- } else {
- return( a->maxv < b->maxv );
- }
-}
-
-/*
- * add - adds a datum to the list in the order specified by the region position.
- */
-
-void list::add (text_glob *in, int line_number, int min_vertical, int min_horizontal, int max_vertical, int max_horizontal)
-{
- // create a new list element with datum and position fields initialized
- element_list *t = new element_list(in, line_number, min_vertical, min_horizontal, max_vertical, max_horizontal);
- element_list *last;
-
- if (head == 0) {
- head = t;
- tail = t;
- ptr = t;
- t->left = t;
- t->right = t;
- } else {
- last = tail;
-
- while ((last != head) && (is_less(t, last))) {
- last = last->left;
- }
-
- if (is_less(t, last)) {
- t->right = last;
- last->left->right = t;
- t->left = last->left;
- last->left = t;
- // now check for a new head
- if (last == head) {
- head = t;
- }
- } else {
- // add t beyond last
- t->right = last->right;
- t->left = last;
- last->right->left = t;
- last->right = t;
- // now check for a new tail
- if (last == tail) {
- tail = t;
- }
- }
- }
-}
-
-/*
- * sub_move_right - removes the element which is currently pointed to by ptr
- * from the list and moves ptr to the right.
- */
-
-void list::sub_move_right (void)
-{
- element_list *t=ptr->right;
-
- if (head == tail) {
- head = 0;
- if (tail != 0) {
- delete tail;
- }
- tail = 0;
- ptr = 0;
- } else {
- if (head == ptr) {
- head = head->right;
- }
- if (tail == ptr) {
- tail = tail->left;
- }
- ptr->left->right = ptr->right;
- ptr->right->left = ptr->left;
- ptr=t;
- }
-}
-
-/*
- * start_from_head - assigns ptr to the head.
- */
-
-void list::start_from_head (void)
-{
- ptr = head;
-}
-
-/*
- * start_from_tail - assigns ptr to the tail.
- */
-
-void list::start_from_tail (void)
-{
- ptr = tail;
-}
-
-/*
- * is_empty - returns TRUE if the list has no elements.
- */
-
-int list::is_empty (void)
-{
- return( head == 0 );
-}
-
-/*
- * is_equal_to_tail - returns TRUE if the ptr equals the tail.
- */
-
-int list::is_equal_to_tail (void)
-{
- return( ptr == tail );
-}
-
-/*
- * is_equal_to_head - returns TRUE if the ptr equals the head.
- */
-
-int list::is_equal_to_head (void)
-{
- return( ptr == head );
-}
-
-/*
- * move_left - moves the ptr left.
- */
-
-void list::move_left (void)
-{
- ptr = ptr->left;
-}
-
-/*
- * move_right - moves the ptr right.
- */
-
-void list::move_right (void)
-{
- ptr = ptr->right;
-}
-
-/*
- * get_datum - returns the datum referenced via ptr.
- */
-
-text_glob* list::get_data (void)
-{
- return( ptr->datum );
-}
-
-/*
- * move_right_get_data - returns the datum referenced via ptr and moves
- * ptr right.
- */
-
-text_glob* list::move_right_get_data (void)
-{
- ptr = ptr->right;
- if (ptr == head) {
- return( 0 );
- } else {
- return( ptr->datum );
- }
-}
-
-/*
- * move_left_get_data - returns the datum referenced via ptr and moves
- * ptr right.
- */
-
-text_glob* list::move_left_get_data (void)
-{
- ptr = ptr->left;
- if (ptr == tail) {
- return( 0 );
- } else {
- return( ptr->datum );
- }
-}
-
-/*
- * insert - inserts data after the current position.
- */
-
-void list::insert (text_glob *in)
-{
- if (is_empty())
- fatal("list must not be empty if we are inserting data");
- else {
- if (ptr == 0)
- ptr = head;
-
- element_list *t = new element_list(in, ptr->lineno, ptr->minv, ptr->minh, ptr->maxv, ptr->maxh);
- if (ptr == tail)
- tail = t;
- ptr->right->left = t;
- t->right = ptr->right;
- ptr->right = t;
- t->left = ptr;
- }
-}
-
-/*
- * move_to - moves the current position to the point where data, in, exists.
- * This is an expensive method and should be used sparingly.
- */
-
-void list::move_to (text_glob *in)
-{
- ptr = head;
- while (ptr != tail && ptr->datum != in)
- ptr = ptr->right;
-}
-
-/*
- * page class and methods
- */
-
-class page {
-public:
- page (void);
- void add (style *s, const string &str,
- int line_number,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal);
- void add_tag (style *s, const string &str,
- int line_number,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal);
- void add_and_encode (style *s, const string &str,
- int line_number,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal);
- void add_line (style *s,
- int line_number,
- int x1, int y1, int x2, int y2,
- int thickness);
- void insert_tag (const string &str);
- void dump_page (void); // debugging method
-
- // and the data
-
- list glyphs; // position of glyphs and specials on page
- char_buffer buffer; // all characters for this page
-};
-
-page::page()
-{
-}
-
-/*
- * insert_tag - inserts a tag after the current position.
- */
-
-void page::insert_tag (const string &str)
-{
- if (str.length() > 0) {
- text_glob *g=new text_glob();
- text_glob *f=glyphs.get_data();
- g->text_glob_tag(&f->text_style, buffer.add_string(str), str.length(),
- f->minv, f->minh, f->maxv, f->maxh);
- glyphs.insert(g);
- }
-}
-
-/*
- * add - add html text to the list of glyphs.
- */
-
-void page::add (style *s, const string &str,
- int line_number,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal)
-{
- if (str.length() > 0) {
- text_glob *g=new text_glob();
- g->text_glob_html(s, buffer.add_string(str), str.length(),
- min_vertical, min_horizontal, max_vertical, max_horizontal);
- glyphs.add(g, line_number, min_vertical, min_horizontal, max_vertical, max_horizontal);
- }
-}
-
-/*
- * add_tag - adds a troff tag, for example: .tl .sp .br
- */
-
-void page::add_tag (style *s, const string &str,
- int line_number,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal)
-{
- if (str.length() > 0) {
- text_glob *g;
-
- if (strncmp((str+'\0').contents(), "html-tag:.auto-image", 20) == 0) {
- g = new text_glob();
- g->text_glob_auto_image(s, buffer.add_string(str), str.length(),
- min_vertical, min_horizontal, max_vertical, max_horizontal);
- } else {
- g = new text_glob();
- g->text_glob_tag(s, buffer.add_string(str), str.length(),
- min_vertical, min_horizontal, max_vertical, max_horizontal);
- }
- glyphs.add(g, line_number, min_vertical, min_horizontal, max_vertical, max_horizontal);
- }
-}
-
-/*
- * add_line - adds the primitive providing that y1==y2
- */
-
-void page::add_line (style *s,
- int line_number,
- int x1, int y1, int x2, int y2,
- int thickness)
-{
- if (y1 == y2) {
- text_glob *g = new text_glob();
- g->text_glob_line(s,
- min(y1, y2), min(x1, y2), max(y1, y2), max(x1, x2),
- thickness);
- glyphs.add(g, line_number, min(y1, y2), min(x1, y2), max(y1, y2), max(x1, x2));
- }
-}
-
-/*
- * to_unicode - returns a unicode translation of int, ch.
- */
-
-static char *to_unicode (unsigned int ch)
-{
- static char buf[30];
-
- sprintf(buf, "%u;", ch);
- return buf;
-}
-
-/*
- * add_and_encode - adds a special string to the page, it translates the string
- * into html glyphs. The special string will have come from x X html:
- * and can contain troff character encodings which appear as
- * \(char\). A sequence of \\ represents \.
- * So for example we can write:
- * "cost = \(Po\)3.00 file = \\foo\\bar"
- * which is translated into:
- * "cost = £3.00 file = \foo\bar"
- */
-
-void page::add_and_encode (style *s, const string &str,
- int line_number,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal)
-{
- string html_string;
- char *html_glyph;
- int i=0;
-
- if (s->f == NULL)
- return;
- while (i < str.length()) {
- if ((i+1 0) {
- string troff_charname = str.substring(a, n-a);
- html_glyph = get_html_translation(s->f, troff_charname);
- if (html_glyph)
- html_string += html_glyph;
- else {
- int index=s->f->name_to_index((troff_charname + '\0').contents());
-
- if (s->f->contains(index) && (index != 0))
- html_string += s->f->get_code(index);
- }
- }
- } else
- html_string += str[i];
- i++;
- }
- if (html_string.length() > 0) {
- text_glob *g=new text_glob();
- g->text_glob_special(s, buffer.add_string(html_string), html_string.length(),
- min_vertical, min_horizontal, max_vertical, max_horizontal);
- glyphs.add(g, line_number, min_vertical, min_horizontal, max_vertical, max_horizontal);
- }
-}
-
-/*
- * dump_page - dump the page contents for debugging purposes.
- */
-
-void page::dump_page(void)
-{
-#if defined(DEBUG_TABLES)
- text_glob *old_pos = glyphs.get_data();
- text_glob *g;
-
- printf("\n\n");
- fflush(stdout);
-#endif
-}
-
-/*
- * font classes and methods
- */
-
-class html_font : public font {
- html_font(const char *);
-public:
- int encoding_index;
- char *encoding;
- char *reencoded_name;
- ~html_font();
- static html_font *load_html_font(const char *);
-};
-
-html_font *html_font::load_html_font(const char *s)
-{
- html_font *f = new html_font(s);
- if (!f->load()) {
- delete f;
- return 0;
- }
- return f;
-}
-
-html_font::html_font(const char *nm)
-: font(nm)
-{
-}
-
-html_font::~html_font()
-{
-}
-
-/*
- * a simple class to contain the header to this document
- */
-
-class title_desc {
-public:
- title_desc ();
- ~title_desc ();
-
- int has_been_written;
- int has_been_found;
- int with_h1;
- string text;
-};
-
-
-title_desc::title_desc ()
- : has_been_written(FALSE), has_been_found(FALSE), with_h1(FALSE)
-{
-}
-
-title_desc::~title_desc ()
-{
-}
-
-class header_desc {
-public:
- header_desc ();
- ~header_desc ();
-
- int no_of_headings; // how many headings have we found?
- char_buffer headings; // all the headings used in the document
- list headers; // list of headers built from .NH and .SH
- int header_level; // current header level
- int written_header; // have we written the header yet?
- string header_buffer; // current header text
-
- void write_headings (FILE *f, int force);
-};
-
-header_desc::header_desc ()
- : no_of_headings(0), header_level(2), written_header(0)
-{
-}
-
-header_desc::~header_desc ()
-{
-}
-
-/*
- * write_headings - emits a list of links for the headings in this document
- */
-
-void header_desc::write_headings (FILE *f, int force)
-{
- text_glob *g;
-
- if (auto_links || force) {
- if (! headers.is_empty()) {
- int h=1;
-
- headers.start_from_head();
- do {
- g = headers.get_data();
- fputs("text_string, f);
- h++;
- fputs("\">", f);
- fputs(g->text_string, f);
- fputs("
\n", f);
- headers.move_right();
- } while (! headers.is_equal_to_head());
- fputs("\n", f);
- }
- }
-}
-
-class html_printer : public printer {
- files file_list;
- simple_output html;
- int res;
- int space_char_index;
- int space_width;
- int no_of_printed_pages;
- int paper_length;
- string sbuf;
- int sbuf_start_hpos;
- int sbuf_vpos;
- int sbuf_end_hpos;
- int sbuf_prev_hpos;
- int sbuf_kern;
- style sbuf_style;
- int last_sbuf_length;
- int overstrike_detected;
- style output_style;
- int output_hpos;
- int output_vpos;
- int output_vpos_max;
- int output_draw_point_size;
- int line_thickness;
- int output_line_thickness;
- unsigned char output_space_code;
- char *inside_font_style;
- int page_number;
- title_desc title;
- header_desc header;
- int header_indent;
- int supress_sub_sup;
- int cutoff_heading;
- page *page_contents;
- html_text *current_paragraph;
- html_indent *indent;
- html_table *table;
- int end_center;
- int end_tempindent;
- TAG_ALIGNMENT next_tag;
- int fill_on;
- int max_linelength;
- int linelength;
- int pageoffset;
- int indentation;
- int prev_indent;
- int pointsize;
- int vertical_spacing;
- int line_number;
- color *background;
-
- void flush_sbuf ();
- void set_style (const style &);
- void set_space_code (unsigned char c);
- void do_exec (char *, const environment *);
- void do_import (char *, const environment *);
- void do_def (char *, const environment *);
- void do_mdef (char *, const environment *);
- void do_file (char *, const environment *);
- void set_line_thickness (const environment *);
- void terminate_current_font (void);
- void flush_font (void);
- void add_to_sbuf (int index, const string &s);
- void write_title (int in_head);
- int sbuf_continuation (int index, const char *name, const environment *env, int w);
- void flush_page (void);
- void troff_tag (text_glob *g);
- void flush_globs (void);
- void emit_line (text_glob *g);
- void emit_raw (text_glob *g);
- void emit_html (text_glob *g);
- void determine_space (text_glob *g);
- void start_font (const char *name);
- void end_font (const char *name);
- int is_font_courier (font *f);
- int is_courier_until_eol (void);
- void start_size (int from, int to);
- void do_font (text_glob *g);
- void do_center (char *arg);
- void do_break (void);
- void do_eol (void);
- void do_eol_ce (void);
- void do_title (void);
- void do_fill (int on);
- void do_heading (char *arg);
- void write_header (void);
- void determine_header_level (int level);
- void do_linelength (char *arg);
- void do_pageoffset (char *arg);
- void do_indentation (char *arg);
- void do_tempindent (char *arg);
- void do_indentedparagraph (void);
- void do_verticalspacing (char *arg);
- void do_pointsize (char *arg);
- void do_centered_image (void);
- void do_left_image (void);
- void do_right_image (void);
- void do_auto_image (text_glob *g, const char *filename);
- void do_links (void);
- void do_flush (void);
- int is_in_middle (int left, int right);
- void do_sup_or_sub (text_glob *g);
- int start_subscript (text_glob *g);
- int end_subscript (text_glob *g);
- int start_superscript (text_glob *g);
- int end_superscript (text_glob *g);
- void outstanding_eol (int n);
- int is_bold (font *f);
- font *make_bold (font *f);
- int overstrike (int index, const char *name, const environment *env, int w);
- void do_body (void);
- int next_horiz_pos (text_glob *g, int nf);
- void lookahead_for_tables (void);
- void insert_tab_te (void);
- text_glob *insert_tab_ts (text_glob *where);
- void insert_tab0_foreach_tab (void);
- void insert_tab_0 (text_glob *where);
- void do_indent (int in, int pageoff, int linelen);
- void shutdown_table (void);
- void do_tab_ts (text_glob *g);
- void do_tab_te (void);
- void do_col (char *s);
- void do_tab (char *s);
- void do_tab0 (void);
- int calc_nf (text_glob *g, int nf);
- void calc_po_in (text_glob *g, int nf);
- void remove_tabs (void);
- void remove_courier_tabs (void);
- void update_min_max (colType type_of_col, int *minimum, int *maximum, text_glob *g);
- void add_table_end (char *debug_string);
- // ADD HERE
-
-public:
- html_printer ();
- ~html_printer ();
- void set_char (int i, font *f, const environment *env, int w, const char *name);
- void draw (int code, int *p, int np, const environment *env);
- void begin_page (int);
- void end_page (int);
- void special (char *arg, const environment *env, char type);
- font *make_font (const char *);
- void end_of_line ();
-};
-
-printer *make_printer()
-{
- return new html_printer;
-}
-
-static void usage(FILE *stream);
-
-void html_printer::set_style(const style &sty)
-{
- const char *fontname = sty.f->get_name();
- if (fontname == NULL)
- fatal("no internalname specified for font");
-
-#if 0
- change_font(fontname, (font::res/(72*font::sizescale))*sty.point_size);
-#endif
-}
-
-/*
- * is_bold - returns TRUE if font, f, is bold.
- */
-
-int html_printer::is_bold (font *f)
-{
- const char *fontname = f->get_name();
- return (strcmp(fontname, "B") == 0) || (strcmp(fontname, "BI") == 0);
-}
-
-/*
- * make_bold - if a bold font of, f, exists then return it.
- */
-
-font *html_printer::make_bold (font *f)
-{
- const char *fontname = f->get_name();
-
- if (strcmp(fontname, "B") == 0)
- return f;
- if (strcmp(fontname, "I") == 0)
- return font::load_font("BI");
- if (strcmp(fontname, "BI") == 0)
- return f;
- return NULL;
-}
-
-void html_printer::end_of_line()
-{
- flush_sbuf();
- line_number++;
-}
-
-/*
- * emit_line - writes out a horizontal rule.
- */
-
-void html_printer::emit_line (text_glob *g)
-{
- // --fixme-- needs to know the length in percentage
- html.put_string("
");
-}
-
-/*
- * emit_raw - writes the raw html information directly to the device.
- */
-
-void html_printer::emit_raw (text_glob *g)
-{
- do_font(g);
- if (next_tag == INLINE) {
- determine_space(g);
- current_paragraph->do_emittext(g->text_string, g->text_length);
- } else {
- current_paragraph->done_para();
- switch (next_tag) {
-
- case CENTERED:
- current_paragraph->do_para("align=center");
- break;
- case LEFT:
- current_paragraph->do_para(&html, "align=left", indentation, pageoffset, linelength);
- break;
- case RIGHT:
- current_paragraph->do_para(&html, "align=right", indentation, pageoffset, linelength);
- break;
- default:
- fatal("unknown enumeration");
- }
- current_paragraph->do_emittext(g->text_string, g->text_length);
- current_paragraph->done_para();
- next_tag = INLINE;
- supress_sub_sup = TRUE;
- if (indentation > 0) {
- /*
- * restore indentation
- */
- int newin = indentation;
- indentation = 0;
- do_indent(newin, pageoffset, linelength);
- }
- }
-}
-
-/*
- * do_center - handle the .ce commands from troff.
- */
-
-void html_printer::do_center (char *arg)
-{
- int n = atoi(arg);
- current_paragraph->do_break();
-
- if (n > 0) {
- current_paragraph->done_para();
- supress_sub_sup = TRUE;
- current_paragraph->do_para("align=center");
- end_center += n;
- } else {
- end_center = 0;
- current_paragraph->remove_para_align();
- }
-}
-
-/*
- * do_centered_image - set a flag such that the next html-tag is
- * placed inside a centered paragraph.
- */
-
-void html_printer::do_centered_image (void)
-{
- next_tag = CENTERED;
-}
-
-/*
- * do_right_image - set a flag such that the next html-tag is
- * placed inside a right aligned paragraph.
- */
-
-void html_printer::do_right_image (void)
-{
- next_tag = RIGHT;
-}
-
-/*
- * do_left_image - set a flag such that the next html-tag is
- * placed inside a left aligned paragraph.
- */
-
-void html_printer::do_left_image (void)
-{
- next_tag = LEFT;
-}
-
-/*
- * exists - returns TRUE if filename exists.
- */
-
-static int exists (const char *filename)
-{
- FILE *fp = fopen(filename, "r");
-
- if (fp == 0) {
- return( FALSE );
- } else {
- fclose(fp);
- return( TRUE );
- }
-}
-
-/*
- * generate_img_src - returns a html image tag for the filename
- * providing that the image exists.
- */
-
-static string &generate_img_src (const char *filename)
-{
- string *s = new string("");
-
- while (filename && (filename[0] == ' ')) {
- filename++;
- }
- if (exists(filename))
- *s += string("";
- return *s;
-}
-
-/*
- * do_auto_image - tests whether the image, indicated by filename,
- * is present, if so then it emits an html image tag.
- * An image tag may be passed through from pic, eqn
- * but the corresponding image might not be created.
- * Consider .EQ delim $$ .EN or an empty .PS .PE.
- */
-
-void html_printer::do_auto_image (text_glob *g, const char *filename)
-{
- string buffer = generate_img_src(filename);
-
- if (! buffer.empty()) {
- /*
- * utilize emit_raw by creating a new text_glob.
- */
- text_glob h = *g;
-
- h.text_string = buffer.contents();
- h.text_length = buffer.length();
- emit_raw(&h);
- } else
- next_tag = INLINE;
-}
-
-/*
- * outstanding_eol - call do_eol, n, times.
- */
-
-void html_printer::outstanding_eol (int n)
-{
- while (n > 0) {
- do_eol();
- n--;
- }
-}
-
-/*
- * do_title - handle the .tl commands from troff.
- */
-
-void html_printer::do_title (void)
-{
- text_glob *t;
- int removed_from_head;
- int eol_ce = 0;
-
- if (page_number == 1) {
- int found_title_start = FALSE;
- if (! page_contents->glyphs.is_empty()) {
- page_contents->glyphs.sub_move_right(); /* move onto next word */
- do {
- t = page_contents->glyphs.get_data();
- removed_from_head = FALSE;
- if (t->is_auto_img()) {
- string img = generate_img_src((char *)(t->text_string + 20));
-
- if (! img.empty()) {
- if (found_title_start)
- title.text += " ";
- found_title_start = TRUE;
- title.has_been_found = TRUE;
- title.text += img;
- }
- page_contents->glyphs.sub_move_right(); /* move onto next word */
- removed_from_head = ((!page_contents->glyphs.is_empty()) &&
- (page_contents->glyphs.is_equal_to_head()));
- } else if (t->is_eol_ce()) {
- /* process the eol associated with .ce
- */
- eol_ce++;
- page_contents->glyphs.sub_move_right(); /* move onto next word */
- } else if (t->is_eol()) {
- /* end of title found
- */
- title.has_been_found = TRUE;
- outstanding_eol(eol_ce);
- return;
- } else if (t->is_a_tag()) {
- /* end of title found, but move back so that we read this tag and process it
- */
- page_contents->glyphs.move_left(); /* move backwards to last word */
- title.has_been_found = TRUE;
- outstanding_eol(eol_ce);
- return;
- } else if (found_title_start) {
- title.text += " " + string(t->text_string, t->text_length);
- page_contents->glyphs.sub_move_right(); /* move onto next word */
- removed_from_head = ((!page_contents->glyphs.is_empty()) &&
- (page_contents->glyphs.is_equal_to_head()));
- } else {
- title.text += string(t->text_string, t->text_length);
- found_title_start = TRUE;
- title.has_been_found = TRUE;
- page_contents->glyphs.sub_move_right(); /* move onto next word */
- removed_from_head = ((!page_contents->glyphs.is_empty()) &&
- (page_contents->glyphs.is_equal_to_head()));
- }
- } while ((! page_contents->glyphs.is_equal_to_head()) || (removed_from_head));
- }
- outstanding_eol(eol_ce);
- }
-}
-
-void html_printer::write_header (void)
-{
- if (! header.header_buffer.empty()) {
- if (header.header_level > 7) {
- header.header_level = 7;
- }
-
- // firstly we must terminate any font and type faces
- current_paragraph->done_para();
- supress_sub_sup = TRUE;
-
- if (cutoff_heading+2 > header.header_level) {
- // now we save the header so we can issue a list of links
- header.no_of_headings++;
- style st;
-
- text_glob *h=new text_glob();
- h->text_glob_html(&st,
- header.headings.add_string(header.header_buffer),
- header.header_buffer.length(),
- header.no_of_headings, header.header_level,
- header.no_of_headings, header.header_level);
-
- header.headers.add(h,
- header.no_of_headings,
- header.no_of_headings, header.no_of_headings,
- header.no_of_headings, header.no_of_headings); // and add this header to the header list
-
- // lastly we generate a tag
-
- html.nl().put_string("").nl();
- }
-
- if (manufacture_headings) {
- // line break before a header
- if (!current_paragraph->emitted_text())
- current_paragraph->do_space();
- // user wants manufactured headings which look better than
- if (header.header_level<4) {
- html.put_string("");
- html.put_string(header.header_buffer);
- html.put_string("").nl();
- }
- else {
- html.put_string("");
- html.put_string(header.header_buffer);
- html.put_string("").nl();
- }
- }
- else {
- // and now we issue the real header
- html.put_string("");
- html.put_string(header.header_buffer);
- html.put_string("").nl();
- }
-
- current_paragraph->do_para(&html, "", indentation, pageoffset, linelength);
- }
-}
-
-void html_printer::determine_header_level (int level)
-{
- if (level == 0) {
- int i;
-
- for (i=0; ((iglyphs.move_right();
- if (! page_contents->glyphs.is_equal_to_head()) {
- g = page_contents->glyphs.get_data();
- do {
- if (g->is_auto_img()) {
- string img=generate_img_src((char *)(g->text_string + 20));
-
- if (! img.empty()) {
- simple_anchors = TRUE; // we cannot use full heading anchors with images
- if (l != 0)
- header.header_buffer += " ";
-
- l = g;
- header.header_buffer += img;
- }
- } else if (! (g->is_a_line() || g->is_a_tag())) {
- /*
- * we ignore tags commands when constructing a heading
- */
- if (l != 0)
- header.header_buffer += " ";
- l = g;
-
- header.header_buffer += string(g->text_string, g->text_length);
- }
- page_contents->glyphs.move_right();
- g = page_contents->glyphs.get_data();
- } while ((! page_contents->glyphs.is_equal_to_head()) &&
- (! g->is_br()));
- }
-
- determine_header_level(level);
- write_header();
-
- // finally set the output to neutral for after the header
- g = page_contents->glyphs.get_data();
- page_contents->glyphs.move_left(); // so that next time we use old g
-}
-
-/*
- * is_courier_until_eol - returns TRUE if we can see a whole line which is courier
- */
-
-int html_printer::is_courier_until_eol (void)
-{
- text_glob *orig = page_contents->glyphs.get_data();
- int result = TRUE;
- text_glob *g;
-
- if (! page_contents->glyphs.is_equal_to_tail()) {
- page_contents->glyphs.move_right();
- do {
- g = page_contents->glyphs.get_data();
- if (! g->is_a_tag() && (! is_font_courier(g->text_style.f)))
- result = FALSE;
- page_contents->glyphs.move_right();
- } while (result &&
- (! page_contents->glyphs.is_equal_to_head()) &&
- (! g->is_fi()) && (! g->is_eol()));
-
- /*
- * now restore our previous position.
- */
- while (page_contents->glyphs.get_data() != orig)
- page_contents->glyphs.move_left();
- }
- return result;
-}
-
-/*
- * do_linelength - handle the .ll command from troff.
- */
-
-void html_printer::do_linelength (char *arg)
-{
- if (max_linelength == -1)
- max_linelength = atoi(arg);
-
- if (fill_on)
- do_indent(indentation, pageoffset, atoi(arg));
-}
-
-/*
- * do_pageoffset - handle the .po command from troff.
- */
-
-void html_printer::do_pageoffset (char *arg)
-{
- if (fill_on)
- do_indent(indentation, atoi(arg), linelength);
-}
-
-/*
- * do_indentation - handle the .in command from troff.
- */
-
-void html_printer::do_indentation (char *arg)
-{
- if (fill_on)
- do_indent(atoi(arg), pageoffset, linelength);
-}
-
-/*
- * do_tempindent - handle the .ti command from troff.
- */
-
-void html_printer::do_tempindent (char *arg)
-{
- if (fill_on) {
- end_tempindent = 1;
- prev_indent = indentation;
- do_indent(atoi(arg), pageoffset, linelength);
- }
-}
-
-/*
- * shutdown_table - shuts down the current table.
- */
-
-void html_printer::shutdown_table (void)
-{
- if (table != NULL) {
- current_paragraph->done_para();
- table->emit_finish_table();
- // dont delete this table as it will be deleted when we destroy the text_glob
- table = NULL;
- }
-}
-
-/*
- * do_indent - remember the indent parameters and if
- * indent is > pageoff and indent has changed
- * then we start a html table to implement the indentation.
- */
-
-void html_printer::do_indent (int in, int pageoff, int linelen)
-{
- if ((indentation != -1) &&
- (pageoffset+indentation != in+pageoff)) {
-
- current_paragraph->done_para();
-
- indentation = in;
- pageoffset = pageoff;
- if (linelen <= max_linelength)
- linelength = linelen;
-
- current_paragraph->do_para(&html, "", indentation, pageoffset, max_linelength);
- }
-}
-
-/*
- * do_verticalspacing - handle the .vs command from troff.
- */
-
-void html_printer::do_verticalspacing (char *arg)
-{
- vertical_spacing = atoi(arg);
-}
-
-/*
- * do_pointsize - handle the .ps command from troff.
- */
-
-void html_printer::do_pointsize (char *arg)
-{
- pointsize = atoi(arg);
-}
-
-/*
- * do_fill - records whether troff has requested that text be filled.
- */
-
-void html_printer::do_fill (int on)
-{
- current_paragraph->do_break();
- output_hpos = indentation+pageoffset;
- supress_sub_sup = TRUE;
-
- if (fill_on != on) {
- if (on)
- current_paragraph->do_para("");
- else
- current_paragraph->do_pre();
- fill_on = on;
- }
-}
-
-/*
- * do_eol - handle the end of line
- */
-
-void html_printer::do_eol (void)
-{
- if (! fill_on) {
- if (current_paragraph->ever_emitted_text()) {
- current_paragraph->do_newline();
- current_paragraph->do_break();
- }
- }
- output_hpos = indentation+pageoffset;
-}
-
-/*
- * do_eol_ce - handle end of line specifically for a .ce
- */
-
-void html_printer::do_eol_ce (void)
-{
- if (end_center > 0) {
- if (end_center > 1)
- if (current_paragraph->emitted_text())
- current_paragraph->do_break();
-
- end_center--;
- if (end_center == 0) {
- current_paragraph->done_para();
- supress_sub_sup = TRUE;
- }
- }
-}
-
-/*
- * do_flush - flushes all output and tags.
- */
-
-void html_printer::do_flush (void)
-{
- current_paragraph->done_para();
-}
-
-/*
- * do_links - moves onto a new temporary file and sets auto_links to FALSE.
- */
-
-void html_printer::do_links (void)
-{
- current_paragraph->done_para();
- auto_links = FALSE; /* from now on only emit under user request */
- file_list.add_new_file(xtmpfile());
- html.set_file(file_list.get_file());
-}
-
-/*
- * do_break - handles the ".br" request and also
- * undoes an outstanding ".ti" command.
- */
-
-void html_printer::do_break (void)
-{
- current_paragraph->do_break();
- if (end_tempindent > 0) {
- end_tempindent--;
- if (end_tempindent == 0)
- do_indent(prev_indent, pageoffset, linelength);
- }
- output_hpos = indentation+pageoffset;
- supress_sub_sup = TRUE;
-}
-
-/*
- * do_tab_ts - start a table, which will have already been defined.
- */
-
-void html_printer::do_tab_ts (text_glob *g)
-{
- html_table *t = g->get_table();
-
- if (t != NULL) {
- current_paragraph->done_pre();
- current_paragraph->done_para();
-
- html.simple_comment("TABS");
-
- t->set_linelength(max_linelength);
- t->add_indent(pageoffset);
- t->emit_table_header(FALSE);
- }
-
- table = t;
-}
-
-/*
- * do_tab_te - finish a table.
- */
-
-void html_printer::do_tab_te (void)
-{
- if (table) {
- current_paragraph->done_para();
- table->emit_finish_table();
- }
-
- table = NULL;
-
- if (indentation > 0) {
- /*
- * restore indentation
- */
- int newin = indentation;
- indentation = 0;
- do_indent(newin, pageoffset, linelength);
- }
-}
-
-/*
- * do_tab - handle the "html-tag:tab" tag
- */
-
-void html_printer::do_tab (char *s)
-{
- if (table) {
- while (isspace(*s))
- s++;
- s++;
- int col = table->find_column(atoi(s) + pageoffset + indentation);
- if (col > 0) {
- current_paragraph->done_para();
- table->emit_col(col);
- }
- }
-}
-
-/*
- * do_tab0 - handle the "html-tag:tab0" tag
- */
-
-void html_printer::do_tab0 (void)
-{
- if (table) {
- int col = table->find_column(pageoffset+indentation);
- if (col > 0) {
- current_paragraph->done_para();
- table->emit_col(col);
- }
- }
-}
-
-/*
- * do_col - start column, s.
- */
-
-void html_printer::do_col (char *s)
-{
- if (table) {
- current_paragraph->done_para();
- table->emit_col(atoi(s));
- }
-}
-
-/*
- * troff_tag - processes the troff tag and manipulates the troff state machine.
- */
-
-void html_printer::troff_tag (text_glob *g)
-{
- /*
- * firstly skip over html-tag:
- */
- char *t=(char *)g->text_string+9;
-
- if (g->is_eol()) {
- do_eol();
- } else if (g->is_eol_ce()) {
- do_eol_ce();
- } else if (strncmp(t, ".sp", 3) == 0) {
- if (g->get_arg() > 0)
- current_paragraph->do_space();
- else
- current_paragraph->do_break();
- supress_sub_sup = TRUE;
- } else if (strncmp(t, ".br", 3) == 0) {
- do_break();
- } else if (strcmp(t, ".centered-image") == 0) {
- do_centered_image();
- } else if (strcmp(t, ".right-image") == 0) {
- do_right_image();
- } else if (strcmp(t, ".left-image") == 0) {
- do_left_image();
- } else if (strncmp(t, ".auto-image", 11) == 0) {
- char *a = (char *)t+11;
- do_auto_image(g, a);
- } else if (strncmp(t, ".ce", 3) == 0) {
- char *a = (char *)t+3;
- supress_sub_sup = TRUE;
- do_center(a);
- } else if (strncmp(t, ".tl", 3) == 0) {
- supress_sub_sup = TRUE;
- title.with_h1 = TRUE;
- do_title();
- } else if (strncmp(t, ".html-tl", 8) == 0) {
- supress_sub_sup = TRUE;
- title.with_h1 = FALSE;
- do_title();
- } else if (strncmp(t, ".fi", 3) == 0) {
- do_fill(TRUE);
- } else if (strncmp(t, ".nf", 3) == 0) {
- do_fill(FALSE);
- } else if ((strncmp(t, ".SH", 3) == 0) || (strncmp(t, ".NH", 3) == 0)) {
- char *a = (char *)t+3;
- do_heading(a);
- } else if (strncmp(t, ".ll", 3) == 0) {
- char *a = (char *)t+3;
- do_linelength(a);
- } else if (strncmp(t, ".po", 3) == 0) {
- char *a = (char *)t+3;
- do_pageoffset(a);
- } else if (strncmp(t, ".in", 3) == 0) {
- char *a = (char *)t+3;
- do_indentation(a);
- } else if (strncmp(t, ".ti", 3) == 0) {
- char *a = (char *)t+3;
- do_tempindent(a);
- } else if (strncmp(t, ".vs", 3) == 0) {
- char *a = (char *)t+3;
- do_verticalspacing(a);
- } else if (strncmp(t, ".ps", 3) == 0) {
- char *a = (char *)t+3;
- do_pointsize(a);
- } else if (strcmp(t, ".links") == 0) {
- do_links();
- } else if (strcmp(t, ".no-auto-rule") == 0) {
- auto_rule = FALSE;
- } else if (strcmp(t, ".tab-ts") == 0) {
- do_tab_ts(g);
- } else if (strcmp(t, ".tab-te") == 0) {
- do_tab_te();
- } else if (strncmp(t, ".col ", 5) == 0) {
- char *a = (char *)t+4;
- do_col(a);
- } else if (strncmp(t, "tab ", 4) == 0) {
- char *a = (char *)t+3;
- do_tab(a);
- } else if (strncmp(t, "tab0", 4) == 0) {
- do_tab0();
- }
-}
-
-/*
- * is_in_middle - returns TRUE if the positions left..right are in the center of the page.
- */
-
-int html_printer::is_in_middle (int left, int right)
-{
- return( abs(abs(left-pageoffset) - abs(pageoffset+linelength-right)) <= CENTER_TOLERANCE );
-}
-
-/*
- * flush_globs - runs through the text glob list and emits html.
- */
-
-void html_printer::flush_globs (void)
-{
- text_glob *g;
-
- if (! page_contents->glyphs.is_empty()) {
- page_contents->glyphs.start_from_head();
- do {
- g = page_contents->glyphs.get_data();
-
- if (strcmp(g->text_string, "XXXXXXX") == 0)
- stop();
-
- if (g->is_a_tag()) {
- troff_tag(g);
- } else if (g->is_a_line()) {
- emit_line(g);
- } else {
- emit_html(g);
- }
- /*
- * after processing the title (and removing it) the glyph list might be empty
- */
- if (! page_contents->glyphs.is_empty()) {
- page_contents->glyphs.move_right();
- }
- } while (! page_contents->glyphs.is_equal_to_head());
- }
-}
-
-/*
- * calc_nf - calculates the _no_ format flag, given the
- * text glob, g.
- */
-
-int html_printer::calc_nf (text_glob *g, int nf)
-{
- if (g != NULL) {
- if (g->is_fi())
- return FALSE;
- if (g->is_nf())
- return TRUE;
- }
- return nf;
-}
-
-/*
- * calc_po_in - calculates the, in, po, registers
- */
-
-void html_printer::calc_po_in (text_glob *g, int nf)
-{
- if (g->is_in())
- indentation = g->get_arg();
- else if (g->is_po())
- pageoffset = g->get_arg();
- else if (g->is_ti()) {
- prev_indent = indentation;
- indentation = g->get_arg();
- end_tempindent = 1;
- } else if (g->is_br() && ((end_tempindent > 0) || (nf && g->is_eol()))) {
- end_tempindent = 0;
- indentation = prev_indent;
- }
-}
-
-/*
- * next_horiz_pos - returns the next horiz position.
- * -1 is returned if it doesn't exist.
- */
-
-int html_printer::next_horiz_pos (text_glob *g, int nf)
-{
- int next = -1;
-
- if ((g != NULL) && (g->is_br() || (nf && g->is_eol())))
- if (! page_contents->glyphs.is_empty()) {
- page_contents->glyphs.move_right_get_data();
- if (g == NULL)
- page_contents->glyphs.start_from_head();
- else {
- next = g->minh;
- page_contents->glyphs.move_left();
- }
- }
- return next;
-}
-
-/*
- * insert_tab_ts - inserts a tab-ts before, where.
- */
-
-text_glob *html_printer::insert_tab_ts (text_glob *where)
-{
- text_glob *start_of_table;
- text_glob *old_pos = page_contents->glyphs.get_data();
-
- page_contents->glyphs.move_to(where);
- page_contents->glyphs.move_left();
- page_contents->insert_tag(string("html-tag:.tab-ts")); // tab table start
- page_contents->glyphs.move_right();
- start_of_table = page_contents->glyphs.get_data();
- page_contents->glyphs.move_to(old_pos);
- return start_of_table;
-}
-
-/*
- * insert_tab_te - inserts a tab-te before the current position
- * (it skips backwards over .sp/.br)
- */
-
-void html_printer::insert_tab_te (void)
-{
- text_glob *g = page_contents->glyphs.get_data();
- page_contents->dump_page();
-
- while (page_contents->glyphs.get_data()->is_a_tag())
- page_contents->glyphs.move_left();
-
- page_contents->insert_tag(string("html-tag:.tab-te")); // tab table end
- while (g != page_contents->glyphs.get_data())
- page_contents->glyphs.move_right();
- page_contents->dump_page();
-}
-
-/*
- * insert_tab_0 - inserts a tab0 before, where.
- */
-
-void html_printer::insert_tab_0 (text_glob *where)
-{
- text_glob *old_pos = page_contents->glyphs.get_data();
-
- page_contents->glyphs.move_to(where);
- page_contents->glyphs.move_left();
- page_contents->insert_tag(string("html-tag:tab0")); // tab0 start of line
- page_contents->glyphs.move_right();
- page_contents->glyphs.move_to(old_pos);
-}
-
-/*
- * remove_tabs - removes the tabs tags on this line.
- */
-
-void html_printer::remove_tabs (void)
-{
- text_glob *orig = page_contents->glyphs.get_data();
- text_glob *g;
-
- if (! page_contents->glyphs.is_equal_to_tail()) {
- do {
- g = page_contents->glyphs.get_data();
- if (g->is_tab()) {
- page_contents->glyphs.sub_move_right();
- if (g == orig)
- orig = page_contents->glyphs.get_data();
- } else
- page_contents->glyphs.move_right();
- } while ((! page_contents->glyphs.is_equal_to_head()) &&
- (! g->is_eol()));
-
- /*
- * now restore our previous position.
- */
- while (page_contents->glyphs.get_data() != orig)
- page_contents->glyphs.move_left();
- }
-}
-
-void html_printer::remove_courier_tabs (void)
-{
- text_glob *g;
- int line_start = TRUE;
- int nf = FALSE;
-
- if (! page_contents->glyphs.is_empty()) {
- page_contents->glyphs.start_from_head();
- line_start = TRUE;
- do {
- g = page_contents->glyphs.get_data();
-
- nf = calc_nf(g, nf);
-
- if (line_start) {
- if (line_start && nf && is_courier_until_eol()) {
- remove_tabs();
- g = page_contents->glyphs.get_data();
- }
- }
-
- line_start = g->is_br() || g->is_nf() || g->is_fi() || (nf && g->is_eol());
- page_contents->glyphs.move_right();
- } while (! page_contents->glyphs.is_equal_to_head());
- }
-}
-
-void html_printer::insert_tab0_foreach_tab (void)
-{
- text_glob *start_of_line = NULL;
- text_glob *g = NULL;
- int seen_tab = FALSE;
- int seen_col = FALSE;
- int nf = FALSE;
-
- if (! page_contents->glyphs.is_empty()) {
- page_contents->glyphs.start_from_head();
- start_of_line = page_contents->glyphs.get_data();
- do {
- g = page_contents->glyphs.get_data();
-
- nf = calc_nf(g, nf);
-
- if (g->is_tab())
- seen_tab = TRUE;
-
- if (g->is_col())
- seen_col = TRUE;
-
- if (g->is_br() || (nf && g->is_eol())) {
- do {
- page_contents->glyphs.move_right();
- g = page_contents->glyphs.get_data();
- nf = calc_nf(g, nf);
- if (page_contents->glyphs.is_equal_to_head()) {
- if (seen_tab && !seen_col)
- insert_tab_0(start_of_line);
- return;
- }
- } while (g->is_br() || (nf && g->is_eol()) || g->is_ta());
- // printf("\nstart_of_line is: %s\n", g->text_string);
- if (seen_tab && !seen_col) {
- insert_tab_0(start_of_line);
- page_contents->glyphs.move_to(g);
- }
-
- seen_tab = FALSE;
- seen_col = FALSE;
- start_of_line = g;
- }
- page_contents->glyphs.move_right();
- } while (! page_contents->glyphs.is_equal_to_head());
- if (seen_tab && !seen_col)
- insert_tab_0(start_of_line);
-
- }
-}
-
-/*
- * update_min_max - updates the extent of a column, given the left and right
- * extents of a glyph, g.
- */
-
-void html_printer::update_min_max (colType type_of_col, int *minimum, int *maximum, text_glob *g)
-{
- switch (type_of_col) {
-
- case tab_tag:
- break;
- case tab0_tag:
- *minimum = g->minh;
- break;
- case col_tag:
- *minimum = g->minh;
- *maximum = g->maxh;
- break;
- default:
- break;
- }
-}
-
-/*
- * add_table_end - moves left one glyph, adds a table end tag and adds a
- * debugging string.
- */
-
-void html_printer::add_table_end (char *debug_string)
-{
- page_contents->glyphs.move_left();
- insert_tab_te();
-#if defined(DEBUG_TABLES)
- page_contents->insert_tag(string(debug_string));
-#endif
-}
-
-/*
- * lookahead_for_tables - checks for .col tags and inserts table start/end tags
- */
-
-void html_printer::lookahead_for_tables (void)
-{
- text_glob *g;
- text_glob *start_of_line = NULL;
- text_glob *start_of_table = NULL;
- text_glob *last = NULL;
- colType type_of_col = none;
- int left = 0;
- int found_col = FALSE;
- int seen_text = FALSE;
- int ncol = 0;
- int colmin;
- int colmax;
- html_table *table = new html_table(&html, -1);
- const char *tab_defs = NULL;
- char align = 'L';
- int nf = FALSE;
- int old_pageoffset = pageoffset;
-
- remove_courier_tabs();
- page_contents->dump_page();
- insert_tab0_foreach_tab();
- page_contents->dump_page();
- if (! page_contents->glyphs.is_empty()) {
- page_contents->glyphs.start_from_head();
- g = page_contents->glyphs.get_data();
- do {
-#if defined(DEBUG_TABLES)
- fprintf(stderr, " [") ;
- fprintf(stderr, g->text_string) ;
- fprintf(stderr, "] ") ;
- fflush(stderr);
- if (strcmp(g->text_string, "XXXXXXX") == 0)
- stop();
-#endif
-
- nf = calc_nf(g, nf);
- calc_po_in(g, nf);
- if (g->is_col()) {
- if (type_of_col == tab_tag && start_of_table != NULL) {
- page_contents->glyphs.move_left();
- insert_tab_te();
- start_of_table->remember_table(table);
- table = new html_table(&html, -1);
- page_contents->insert_tag(string("*** TAB -> COL ***"));
- if (tab_defs != NULL)
- table->tab_stops->init(tab_defs);
- start_of_table = NULL;
- last = NULL;
- }
- type_of_col = col_tag;
- found_col = TRUE;
- ncol = g->get_arg();
- align = 'L';
- colmin = 0;
- colmax = 0;
- } else if (g->is_tab()) {
- type_of_col = tab_tag;
- colmin = g->get_tab_args(&align);
- align = 'L'; // for now as 'C' and 'R' are broken
- ncol = table->find_tab_column(colmin);
- colmin += pageoffset + indentation;
- colmax = table->get_tab_pos(ncol+1);
- if (colmax > 0)
- colmax += pageoffset + indentation;
- } else if (g->is_tab0()) {
- if (type_of_col == col_tag && start_of_table != NULL) {
- page_contents->glyphs.move_left();
- insert_tab_te();
- start_of_table->remember_table(table);
- table = new html_table(&html, -1);
- page_contents->insert_tag(string("*** COL -> TAB ***"));
- start_of_table = NULL;
- last = NULL;
- }
- if (tab_defs != NULL)
- table->tab_stops->init(tab_defs);
-
- type_of_col = tab0_tag;
- ncol = 1;
- colmin = 0;
- colmax = table->get_tab_pos(2) + pageoffset + indentation;
- } else if (! g->is_a_tag())
- update_min_max(type_of_col, &colmin, &colmax, g);
-
- if ((! g->is_a_tag()) || g->is_tab())
- seen_text = TRUE;
-
- if ((g->is_col() || g->is_tab() || g->is_tab0())
- && (start_of_line != NULL) && (start_of_table == NULL)) {
- start_of_table = insert_tab_ts(start_of_line);
- start_of_line = NULL;
- seen_text = FALSE;
- } else if (g->is_ce() && (start_of_table != NULL)) {
- add_table_end("*** CE ***");
- start_of_table->remember_table(table);
- start_of_table = NULL;
- last = NULL;
- } else if (g->is_ta()) {
- tab_defs = g->text_string;
- if (!table->tab_stops->compatible(tab_defs)) {
- if (start_of_table != NULL) {
- add_table_end("*** TABS ***");
- start_of_table->remember_table(table);
- table = new html_table(&html, -1);
- start_of_table = NULL;
- type_of_col = none;
- last = NULL;
- }
- table->tab_stops->init(tab_defs);
- }
- }
-
- if (((! g->is_a_tag()) || g->is_tab()) && (start_of_table != NULL)) {
- // we are in a table and have a glyph
- if ((ncol == 0) || (! table->add_column(ncol, colmin, colmax, align))) {
- if (ncol == 0)
- add_table_end("*** NCOL == 0 ***");
- else
- add_table_end("*** CROSSED COLS ***");
-
- start_of_table->remember_table(table);
- table = new html_table(&html, -1);
- start_of_table = NULL;
- type_of_col = none;
- last = NULL;
- }
- }
-
- /*
- * move onto next glob, check whether we are starting a new line
- */
- g = page_contents->glyphs.move_right_get_data();
-
- if (g == NULL) {
- if (found_col) {
- page_contents->glyphs.start_from_head();
- last = g;
- found_col = FALSE;
- }
- } else if (g->is_br() || (nf && g->is_eol())) {
- do {
- g = page_contents->glyphs.move_right_get_data();
- nf = calc_nf(g, nf);
- } while ((g != NULL) && (g->is_br() || (nf && g->is_eol())));
- start_of_line = g;
- seen_text = FALSE;
- ncol = 0;
- left = next_horiz_pos(g, nf);
- if (found_col)
- last = g;
- found_col = FALSE;
- }
- } while ((g != NULL) && (! page_contents->glyphs.is_equal_to_head()));
-
-#if defined(DEBUG_TABLES)
- fprintf(stderr, "finished scanning for tables\n");
-#endif
-
- page_contents->glyphs.start_from_head();
- if (start_of_table != NULL) {
- if (last != NULL)
- while (last != page_contents->glyphs.get_data())
- page_contents->glyphs.move_left();
-
- insert_tab_te();
- start_of_table->remember_table(table);
- table = NULL;
- page_contents->insert_tag(string("*** LAST ***"));
- }
- }
- if (table != NULL)
- delete table;
-
- // and reset the registers
- pageoffset = old_pageoffset;
- indentation = 0;
- prev_indent = 0;
- end_tempindent = 0;
-}
-
-void html_printer::flush_page (void)
-{
- supress_sub_sup = TRUE;
- flush_sbuf();
- page_contents->dump_page();
- lookahead_for_tables();
- page_contents->dump_page();
-
- flush_globs();
- current_paragraph->done_para();
-
- // move onto a new page
- delete page_contents;
-#if defined(DEBUG_TABLES)
- fprintf(stderr, "\n\n*** flushed page ***\n\n");
-
- html.simple_comment("new page called");
-#endif
- page_contents = new page;
-}
-
-/*
- * determine_space - works out whether we need to write a space.
- * If last glyph is ajoining then no space emitted.
- */
-
-void html_printer::determine_space (text_glob *g)
-{
- if (current_paragraph->is_in_pre()) {
- /*
- * .nf has been specified
- */
- while (output_hpos < g->minh) {
- output_hpos += space_width;
- current_paragraph->emit_space();
- }
- } else {
- if ((output_vpos != g->minv) || (output_hpos < g->minh)) {
- current_paragraph->emit_space();
- }
- }
-}
-
-/*
- * is_font_courier - returns TRUE if the font, f, is courier.
- */
-
-int html_printer::is_font_courier (font *f)
-{
- if (f != 0) {
- const char *fontname = f->get_name();
-
- return( (fontname != 0) && (fontname[0] == 'C') );
- }
- return( FALSE );
-}
-
-/*
- * end_font - shuts down the font corresponding to fontname.
- */
-
-void html_printer::end_font (const char *fontname)
-{
- if (strcmp(fontname, "B") == 0) {
- current_paragraph->done_bold();
- } else if (strcmp(fontname, "I") == 0) {
- current_paragraph->done_italic();
- } else if (strcmp(fontname, "BI") == 0) {
- current_paragraph->done_bold();
- current_paragraph->done_italic();
- } else if (strcmp(fontname, "CR") == 0) {
- current_paragraph->done_tt();
- } else if (strcmp(fontname, "CI") == 0) {
- current_paragraph->done_italic();
- current_paragraph->done_tt();
- } else if (strcmp(fontname, "CB") == 0) {
- current_paragraph->done_bold();
- current_paragraph->done_tt();
- } else if (strcmp(fontname, "CBI") == 0) {
- current_paragraph->done_bold();
- current_paragraph->done_italic();
- current_paragraph->done_tt();
- }
-}
-
-/*
- * start_font - starts the font corresponding to name.
- */
-
-void html_printer::start_font (const char *fontname)
-{
- if (strcmp(fontname, "R") == 0) {
- current_paragraph->done_bold();
- current_paragraph->done_italic();
- current_paragraph->done_tt();
- } else if (strcmp(fontname, "B") == 0) {
- current_paragraph->do_bold();
- } else if (strcmp(fontname, "I") == 0) {
- current_paragraph->do_italic();
- } else if (strcmp(fontname, "BI") == 0) {
- current_paragraph->do_bold();
- current_paragraph->do_italic();
- } else if (strcmp(fontname, "CR") == 0) {
- if ((! fill_on) && (is_courier_until_eol())) {
- current_paragraph->do_pre();
- }
- current_paragraph->do_tt();
- } else if (strcmp(fontname, "CI") == 0) {
- if ((! fill_on) && (is_courier_until_eol())) {
- current_paragraph->do_pre();
- }
- current_paragraph->do_tt();
- current_paragraph->do_italic();
- } else if (strcmp(fontname, "CB") == 0) {
- if ((! fill_on) && (is_courier_until_eol())) {
- current_paragraph->do_pre();
- }
- current_paragraph->do_tt();
- current_paragraph->do_bold();
- } else if (strcmp(fontname, "CBI") == 0) {
- if ((! fill_on) && (is_courier_until_eol())) {
- current_paragraph->do_pre();
- }
- current_paragraph->do_tt();
- current_paragraph->do_italic();
- current_paragraph->do_bold();
- }
-}
-
-/*
- * start_size - from is old font size, to is the new font size.
- * The html increase and decrease alters the
- * font size by 20%. We try and map these onto glyph sizes.
- */
-
-void html_printer::start_size (int from, int to)
-{
- if (from < to) {
- while (from < to) {
- current_paragraph->do_big();
- from += SIZE_INCREMENT;
- }
- } else if (from > to) {
- while (from > to) {
- current_paragraph->do_small();
- from -= SIZE_INCREMENT;
- }
- }
-}
-
-/*
- * do_font - checks to see whether we need to alter the html font.
- */
-
-void html_printer::do_font (text_glob *g)
-{
- /*
- * check if the output_style.point_size has not been set yet
- * this allow users to place .ps at the top of their troff files
- * and grohtml can then treat the .ps value as the base font size (3)
- */
- if (output_style.point_size == -1) {
- output_style.point_size = pointsize;
- }
-
- if (g->text_style.f != output_style.f) {
- if (output_style.f != 0) {
- end_font(output_style.f->get_name());
- }
- output_style.f = g->text_style.f;
- if (output_style.f != 0) {
- start_font(output_style.f->get_name());
- }
- }
- if (output_style.point_size != g->text_style.point_size) {
- do_sup_or_sub(g);
- if ((output_style.point_size > 0) &&
- (g->text_style.point_size > 0)) {
- start_size(output_style.point_size, g->text_style.point_size);
- }
- if (g->text_style.point_size > 0) {
- output_style.point_size = g->text_style.point_size;
- }
- }
- if (output_style.col != g->text_style.col) {
- current_paragraph->done_color();
- output_style.col = g->text_style.col;
- current_paragraph->do_color(&output_style.col);
- }
-}
-
-/*
- * start_subscript - returns TRUE if, g, looks like a subscript start.
- */
-
-int html_printer::start_subscript (text_glob *g)
-{
- int r = font::res;
- int height = output_style.point_size*r/72;
-
- return( (output_style.point_size != 0) &&
- (output_vpos < g->minv) &&
- (output_vpos-height > g->maxv) &&
- (output_style.point_size > g->text_style.point_size) );
-}
-
-/*
- * start_superscript - returns TRUE if, g, looks like a superscript start.
- */
-
-int html_printer::start_superscript (text_glob *g)
-{
- int r = font::res;
- int height = output_style.point_size*r/72;
-
- return( (output_style.point_size != 0) &&
- (output_vpos > g->minv) &&
- (output_vpos-height < g->maxv) &&
- (output_style.point_size > g->text_style.point_size) );
-}
-
-/*
- * end_subscript - returns TRUE if, g, looks like the end of a subscript.
- */
-
-int html_printer::end_subscript (text_glob *g)
-{
- int r = font::res;
- int height = output_style.point_size*r/72;
-
- return( (output_style.point_size != 0) &&
- (g->minv < output_vpos) &&
- (output_vpos-height > g->maxv) &&
- (output_style.point_size < g->text_style.point_size) );
-}
-
-/*
- * end_superscript - returns TRUE if, g, looks like the end of a superscript.
- */
-
-int html_printer::end_superscript (text_glob *g)
-{
- int r = font::res;
- int height = output_style.point_size*r/72;
-
- return( (output_style.point_size != 0) &&
- (g->minv > output_vpos) &&
- (output_vpos-height < g->maxv) &&
- (output_style.point_size < g->text_style.point_size) );
-}
-
-/*
- * do_sup_or_sub - checks to see whether the next glyph is a subscript/superscript
- * start/end and it calls the services of html-text to issue the
- * appropriate tags.
- */
-
-void html_printer::do_sup_or_sub (text_glob *g)
-{
- if (! supress_sub_sup) {
- if (start_subscript(g)) {
- current_paragraph->do_sub();
- } else if (start_superscript(g)) {
- current_paragraph->do_sup();
- } else if (end_subscript(g)) {
- current_paragraph->done_sub();
- } else if (end_superscript(g)) {
- current_paragraph->done_sup();
- }
- }
-}
-
-/*
- * emit_html - write out the html text
- */
-
-void html_printer::emit_html (text_glob *g)
-{
- do_font(g);
- determine_space(g);
- current_paragraph->do_emittext(g->text_string, g->text_length);
- output_vpos = g->minv;
- output_hpos = g->maxh;
- output_vpos_max = g->maxv;
- supress_sub_sup = FALSE;
-}
-
-/*
- * flush_sbuf - flushes the current sbuf into the list of glyphs.
- */
-
-void html_printer::flush_sbuf()
-{
- if (sbuf.length() > 0) {
- int r=font::res; // resolution of the device
- set_style(sbuf_style);
- if (overstrike_detected && (! is_bold(sbuf_style.f))) {
- font *bold_font = make_bold(sbuf_style.f);
- if (bold_font != NULL)
- sbuf_style.f = bold_font;
- }
-
- page_contents->add(&sbuf_style, sbuf,
- line_number,
- sbuf_vpos-sbuf_style.point_size*r/72, sbuf_start_hpos,
- sbuf_vpos , sbuf_end_hpos);
-
- output_hpos = sbuf_end_hpos;
- output_vpos = sbuf_vpos;
- last_sbuf_length = 0;
- sbuf_prev_hpos = sbuf_end_hpos;
- overstrike_detected = FALSE;
- sbuf.clear();
- }
-}
-
-void html_printer::set_line_thickness(const environment *env)
-{
- line_thickness = env->size;
-}
-
-void html_printer::draw(int code, int *p, int np, const environment *env)
-{
- switch (code) {
-
- case 'l':
-# if 0
- if (np == 2) {
- page_contents->add_line(&sbuf_style,
- line_number,
- env->hpos, env->vpos, env->hpos+p[0], env->vpos+p[1], line_thickness);
- } else {
- error("2 arguments required for line");
- }
-# endif
- break;
- case 't':
- {
- if (np == 0) {
- line_thickness = -1;
- } else {
- // troff gratuitously adds an extra 0
- if (np != 1 && np != 2) {
- error("0 or 1 argument required for thickness");
- break;
- }
- line_thickness = p[0];
- }
- break;
- }
-
- case 'P':
- break;
- case 'p':
- break;
- case 'E':
- break;
- case 'e':
- break;
- case 'C':
- break;
- case 'c':
- break;
- case 'a':
- break;
- case '~':
- break;
- case 'f':
- break;
- case 'F':
- // fill with color env->fill
- if (background != NULL)
- delete background;
- background = new color;
- *background = *env->fill;
- break;
-
- default:
- error("unrecognised drawing command `%1'", char(code));
- break;
- }
-}
-
-html_printer::html_printer()
-: html(0, MAX_LINE_LENGTH),
- no_of_printed_pages(0),
- last_sbuf_length(0),
- overstrike_detected(FALSE),
- output_hpos(-1),
- output_vpos(-1),
- output_vpos_max(-1),
- line_thickness(-1),
- inside_font_style(0),
- page_number(0),
- header_indent(-1),
- supress_sub_sup(TRUE),
- cutoff_heading(100),
- indent(NULL),
- table(NULL),
- end_center(0),
- end_tempindent(0),
- next_tag(INLINE),
- fill_on(TRUE),
- max_linelength(-1),
- linelength(0),
- pageoffset(0),
- indentation(0),
- prev_indent(0),
- pointsize(0),
- line_number(0),
- background(default_background)
-{
- file_list.add_new_file(xtmpfile());
- html.set_file(file_list.get_file());
- if (font::hor != 24)
- fatal("horizontal resolution must be 24");
- if (font::vert != 40)
- fatal("vertical resolution must be 40");
-#if 0
- // should be sorted html..
- if (font::res % (font::sizescale*72) != 0)
- fatal("res must be a multiple of 72*sizescale");
-#endif
- int r = font::res;
- int point = 0;
- while (r % 10 == 0) {
- r /= 10;
- point++;
- }
- res = r;
- html.set_fixed_point(point);
- space_char_index = font::name_to_index("space");
- space_width = font::hor;
- paper_length = font::paperlength;
- linelength = font::res*13/2;
- if (paper_length == 0)
- paper_length = 11*font::res;
-
- page_contents = new page();
-}
-
-/*
- * add_to_sbuf - adds character code or name to the sbuf.
- */
-
-void html_printer::add_to_sbuf (int index, const string &s)
-{
- if (sbuf_style.f == NULL)
- return;
-
- char *html_glyph = NULL;
- unsigned int code = sbuf_style.f->get_code(index);
-
- if (s.empty()) {
- if (sbuf_style.f->contains(index))
- html_glyph = (char *)sbuf_style.f->get_special_device_encoding(index);
- else
- html_glyph = NULL;
-
- if ((html_glyph == NULL) && (code >= UNICODE_DESC_START))
- html_glyph = to_unicode(code);
- } else
- html_glyph = get_html_translation(sbuf_style.f, s);
-
- last_sbuf_length = sbuf.length();
- if (html_glyph == NULL)
- sbuf += ((char)code);
- else
- sbuf += html_glyph;
-}
-
-int html_printer::sbuf_continuation (int index, const char *name,
- const environment *env, int w)
-{
- /*
- * lets see whether the glyph is closer to the end of sbuf
- */
- if ((sbuf_end_hpos == env->hpos)
- || ((sbuf_prev_hpos < sbuf_end_hpos)
- && (env->hpos < sbuf_end_hpos)
- && ((sbuf_end_hpos-env->hpos < env->hpos-sbuf_prev_hpos)))) {
- add_to_sbuf(index, name);
- sbuf_prev_hpos = sbuf_end_hpos;
- sbuf_end_hpos += w + sbuf_kern;
- return TRUE;
- } else {
- if ((env->hpos >= sbuf_end_hpos) &&
- ((sbuf_kern == 0) || (sbuf_end_hpos - sbuf_kern != env->hpos))) {
- /*
- * lets see whether a space is needed or not
- */
-
- if (env->hpos-sbuf_end_hpos < space_width) {
- add_to_sbuf(index, name);
- sbuf_prev_hpos = sbuf_end_hpos;
- sbuf_end_hpos = env->hpos + w;
- return TRUE;
- }
- }
- }
- return FALSE ;
-}
-
-/*
- * get_html_translation - given the position of the character and its name
- * return the device encoding for such character.
- */
-
-char *get_html_translation (font *f, const string &name)
-{
- int index;
-
- if ((f == 0) || name.empty())
- return NULL;
- else {
- index = f->name_to_index((char *)(name + '\0').contents());
- if (index == 0) {
- error("character `%s' not found", (name + '\0').contents());
- return NULL;
- } else
- if (f->contains(index))
- return (char *)f->get_special_device_encoding(index);
- else
- return NULL;
- }
-}
-
-/*
- * overstrike - returns TRUE if the glyph (i, name) is going to overstrike
- * a previous glyph in sbuf.
- * If TRUE the font is changed to bold and the previous sbuf
- * is flushed.
- */
-
-int html_printer::overstrike(int index, const char *name, const environment *env, int w)
-{
- if ((env->hpos < sbuf_end_hpos)
- || ((sbuf_kern != 0) && (sbuf_end_hpos - sbuf_kern < env->hpos))) {
- /*
- * at this point we have detected an overlap
- */
- if (overstrike_detected) {
- /* already detected, remove previous glyph and use this glyph */
- sbuf.set_length(last_sbuf_length);
- add_to_sbuf(index, name);
- sbuf_end_hpos = env->hpos + w;
- return TRUE;
- } else {
- /* first time we have detected an overstrike in the sbuf */
- sbuf.set_length(last_sbuf_length); /* remove previous glyph */
- if (! is_bold(sbuf_style.f))
- flush_sbuf();
- overstrike_detected = TRUE;
- add_to_sbuf(index, name);
- sbuf_end_hpos = env->hpos + w;
- return TRUE;
- }
- }
- return FALSE ;
-}
-
-/*
- * set_char - adds a character into the sbuf if it is a continuation with the previous
- * word otherwise flush the current sbuf and add character anew.
- */
-
-void html_printer::set_char(int i, font *f, const environment *env, int w, const char *name)
-{
- style sty(f, env->size, env->height, env->slant, env->fontno, *env->col);
- if (sty.slant != 0) {
- if (sty.slant > 80 || sty.slant < -80) {
- error("silly slant `%1' degrees", sty.slant);
- sty.slant = 0;
- }
- }
- if (((! sbuf.empty()) && (sty == sbuf_style) && (sbuf_vpos == env->vpos))
- && (sbuf_continuation(i, name, env, w) || overstrike(i, name, env, w)))
- return;
-
- flush_sbuf();
- add_to_sbuf(i, name);
- sbuf_end_hpos = env->hpos + w;
- sbuf_start_hpos = env->hpos;
- sbuf_prev_hpos = env->hpos;
- sbuf_vpos = env->vpos;
- sbuf_style = sty;
- sbuf_kern = 0;
-}
-
-/*
- * write_title - writes the title to this document
- */
-
-void html_printer::write_title (int in_head)
-{
- if (title.has_been_found) {
- if (in_head) {
- html.put_string("");
- html.put_string(title.text);
- html.put_string("").nl().nl();
- } else {
- title.has_been_written = TRUE;
- if (title.with_h1) {
- html.put_string("");
- html.put_string(title.text);
- html.put_string("
").nl().nl();
- }
- }
- } else if (in_head) {
- // place empty title tags to help conform to `tidy'
- html.put_string("").nl();
- }
-}
-
-/*
- * write_rule - emits a html rule tag, if the auto_rule boolean is true.
- */
-
-static void write_rule (void)
-{
- if (auto_rule)
- fputs("
\n", stdout);
-}
-
-void html_printer::begin_page(int n)
-{
- page_number = n;
-#if defined(DEBUGGING)
- html.begin_comment("Page: ").put_string(i_to_a(page_number)).end_comment();;
-#endif
- no_of_printed_pages++;
-
- output_style.f = 0;
- output_style.point_size= -1;
- output_space_code = 32;
- output_draw_point_size = -1;
- output_line_thickness = -1;
- output_hpos = -1;
- output_vpos = -1;
- output_vpos_max = -1;
- current_paragraph = new html_text(&html);
- do_indent(indentation, pageoffset, linelength);
- current_paragraph->do_para("");
-}
-
-void html_printer::end_page(int)
-{
- flush_sbuf();
- flush_page();
-}
-
-font *html_printer::make_font(const char *nm)
-{
- return html_font::load_html_font(nm);
-}
-
-void html_printer::do_body (void)
-{
- if (background == NULL)
- fputs("\n\n", stdout);
- else {
- unsigned int r, g, b;
- char buf[6+1];
-
- background->get_rgb(&r, &g, &b);
- // we have to scale 0..0xFFFF to 0..0xFF
- sprintf(buf, "%.2X%.2X%.2X", r/0x101, g/0x101, b/0x101);
-
- fputs("\n\n", stdout);
- }
-}
-
-html_printer::~html_printer()
-{
-#ifdef LONG_FOR_TIME_T
- long t;
-#else
- time_t t;
-#endif
-
- current_paragraph->flush_text();
- html.end_line();
- html.set_file(stdout);
- html.begin_comment("Creator : ")
- .put_string("groff ")
- .put_string("version ")
- .put_string(Version_string)
- .end_comment();
-
- t = time(0);
- html.begin_comment("CreationDate: ")
- .put_string(ctime(&t), strlen(ctime(&t))-1)
- .end_comment();
-
- /*
- * 'HTML: The definitive guide', O'Reilly, p47. advises against specifying
- * the dtd.
- */
- // fputs("\n", stdout);
- fputs("\n", stdout);
- fputs("\n", stdout);
- fputs("\n", stdout);
- fputs("\n", stdout);
- write_title(TRUE);
- fputs("\n", stdout);
- do_body();
-
- write_title(FALSE);
- header.write_headings(stdout, FALSE);
- write_rule();
-#if defined(DEBUGGING)
- html.begin_comment("Total number of pages: ").put_string(i_to_a(no_of_printed_pages)).end_comment();
-#endif
- html.end_line();
- html.end_line();
- /*
- * now run through the file list copying each temporary file in turn and emitting the links.
- */
- file_list.start_of_list();
- while (file_list.get_file() != 0) {
- if (fseek(file_list.get_file(), 0L, 0) < 0)
- fatal("fseek on temporary file failed");
- html.copy_file(file_list.get_file());
- fclose(file_list.get_file());
- file_list.move_next();
- if (file_list.get_file() != 0)
- header.write_headings(stdout, TRUE);
- }
- write_rule();
- fputs("\n", stdout);
- fputs("\n", stdout);
-}
-
-/*
- * special - handle all x X requests from troff. For post-html they allow users
- * to pass raw html commands, turn auto linked headings off/on and
- * also allow troff to emit tags to indicate when a: .br, .sp etc occurs.
- */
-
-void html_printer::special(char *s, const environment *env, char type)
-{
- if (type != 'p')
- return;
- if (s != 0) {
- flush_sbuf();
- if (env->fontno >= 0) {
- style sty(get_font_from_index(env->fontno), env->size, env->height,
- env->slant, env->fontno, *env->col);
- sbuf_style = sty;
- }
-
- if (strncmp(s, "html:", 5) == 0) {
- int r=font::res; /* resolution of the device */
- font *f=sbuf_style.f;
-
- if (f == NULL) {
- int found=FALSE;
-
- f = font::load_font("TR", &found);
- }
-
- /*
- * need to pass rest of string through to html output during flush
- */
- page_contents->add_and_encode(&sbuf_style, string(&s[5]),
- line_number,
- env->vpos-env->size*r/72, env->hpos,
- env->vpos , env->hpos);
-
- /*
- * assume that the html command has no width, if it does then hopefully troff
- * will have fudged this in a macro by requesting that the formatting move right by
- * the appropriate amount.
- */
- } else if (strncmp(s, "index:", 6) == 0) {
- cutoff_heading = atoi(&s[6]);
- } else if (strncmp(s, "html-tag:", 9) == 0) {
- int r=font::res; /* resolution of the device */
-
- page_contents->add_tag(&sbuf_style, string(s),
- line_number,
- env->vpos-env->size*r/72, env->hpos,
- env->vpos , env->hpos);
- }
- }
-}
-
-int main(int argc, char **argv)
-{
- program_name = argv[0];
- static char stderr_buf[BUFSIZ];
- setbuf(stderr, stderr_buf);
- int c;
- 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:g:o:i:I:D:F:vbdhlrnp", long_options, NULL))
- != EOF)
- switch(c) {
- case 'v':
- printf("GNU post-grohtml (groff) version %s\n", Version_string);
- exit(0);
- break;
- case 'a':
- /* text antialiasing bits - handled by pre-html */
- break;
- case 'g':
- /* graphic antialiasing bits - handled by pre-html */
- break;
- case 'b':
- // set background color to white
- default_background = new color;
- default_background->set_gray(color::MAX_COLOR_VAL);
- break;
- case 'F':
- font::command_line_font_dir(optarg);
- break;
- case 'l':
- auto_links = FALSE;
- break;
- case 'r':
- auto_rule = FALSE;
- break;
- case 'd':
- /* handled by pre-html */
- break;
- case 'h':
- /* do not use the Hn headings of html, but manufacture our own */
- manufacture_headings = TRUE;
- break;
- case 'o':
- /* handled by pre-html */
- break;
- case 'p':
- /* handled by pre-html */
- break;
- case 'i':
- /* handled by pre-html */
- break;
- case 'I':
- /* handled by pre-html */
- break;
- case 'D':
- /* handled by pre-html */
- break;
- case 'n':
- simple_anchors = TRUE;
- break;
- case CHAR_MAX + 1: // --help
- usage(stdout);
- exit(0);
- break;
- case '?':
- usage(stderr);
- exit(1);
- break;
- default:
- assert(0);
- }
- if (optind >= argc) {
- do_file("-");
- } else {
- for (int i = optind; i < argc; i++)
- do_file(argv[i]);
- }
- delete pr;
- return 0;
-}
-
-static void usage(FILE *stream)
-{
- fprintf(stream, "usage: %s [-vblnh] [-D dir] [-I image_stem] [-F dir] [files ...]\n",
- program_name);
-}
diff --git a/contrib/groff/src/devices/grolbp/lbp.cc b/contrib/groff/src/devices/grolbp/lbp.cc
deleted file mode 100644
index 76db32a..0000000
--- a/contrib/groff/src/devices/grolbp/lbp.cc
+++ /dev/null
@@ -1,740 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1994, 2000, 2001, 2002 Free Software Foundation, Inc.
- Written by Francisco Andrés Verdú with many ideas
- taken from the other groff drivers.
-
-
-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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-/*
-TODO
-
- - Add X command to include bitmaps
-*/
-#define _GNU_SOURCE
-
-#include "driver.h"
-#include "lbp.h"
-#include "charset.h"
-#include "paper.h"
-
-#include "nonposix.h"
-
-extern "C" const char *Version_string;
-
-static int user_papersize = -1; // papersize
-static int orientation = -1; // orientation
-static double user_paperlength = 0; // Custom Paper size
-static double user_paperwidth = 0;
-static int ncopies = 1; // Number of copies
-
-#define DEFAULT_LINEWIDTH_FACTOR 40 // 0.04em
-static int linewidth_factor = DEFAULT_LINEWIDTH_FACTOR;
-
-static int set_papersize(const char *paperformat);
-
-class lbp_font : public font {
-public:
- ~lbp_font();
- void handle_unknown_font_command(const char *command, const char *arg,
- const char *filename, int lineno);
- static lbp_font *load_lbp_font(const char *);
- char *lbpname;
- char is_scalable;
-private:
- lbp_font(const char *);
-};
-
-class lbp_printer : public printer {
-public:
- lbp_printer(int, double, double);
- ~lbp_printer();
- void set_char(int, font *, const environment *, int, const char *name);
- void draw(int code, int *p, int np, const environment *env);
- void begin_page(int);
- void end_page(int page_length);
- font *make_font(const char *);
- void end_of_line();
-private:
- void set_line_thickness(int size,const environment *env);
- void vdmstart();
- void vdmflush(); // the name vdmend was already used in lbp.h
- void setfillmode(int mode);
- void polygon( int hpos,int vpos,int np,int *p);
- char *font_name(const lbp_font *f, const int siz);
-
- int fill_pattern;
- int fill_mode;
- int cur_hpos;
- int cur_vpos;
- lbp_font *cur_font;
- int cur_size;
- unsigned short cur_symbol_set;
- int line_thickness;
- int req_linethickness; // requested line thickness
- int papersize;
- int paperlength; // custom paper size
- int paperwidth;
-};
-
-// Compatibility section.
-//
-// Here we define some functions not present in some of the targets
-// platforms
-#ifndef HAVE_STRSEP
-// Solaris 8 doesn't have the strsep function
-static char *strsep(char **pcadena, const char *delim)
-{
- char *p;
- p = strtok(*pcadena, delim);
- *pcadena = strtok(NULL, delim);
- return p;
-}
-#endif
-
-lbp_font::lbp_font(const char *nm)
-: font(nm)
-{
-}
-
-lbp_font::~lbp_font()
-{
-}
-
-lbp_font *lbp_font::load_lbp_font(const char *s)
-{
- lbp_font *f = new lbp_font(s);
- f->lbpname = NULL;
- f->is_scalable = 1; // Default is that fonts are scalable
- if (!f->load()) {
- delete f;
- return 0;
- }
- return f;
-}
-
-
-void lbp_font::handle_unknown_font_command(const char *command,
- const char *arg,
- const char *filename, int lineno)
-{
- if (strcmp(command, "lbpname") == 0) {
- if (arg == 0)
- fatal_with_file_and_line(filename, lineno,
- "`%1' command requires an argument",
- command);
- this->lbpname = new char[strlen(arg) + 1];
- strcpy(this->lbpname, arg);
- // we recognize bitmapped fonts by the first character of its name
- if (arg[0] == 'N')
- this->is_scalable = 0;
- // fprintf(stderr, "Loading font \"%s\" \n", arg);
- }
- // fprintf(stderr, "Loading font %s \"%s\" in %s at %d\n",
- // command, arg, filename, lineno);
-}
-
-static void wp54charset()
-{
- unsigned int i;
- lbpputs("\033[714;100;29;0;32;120.}");
- for (i = 0; i < sizeof(symset); i++)
- lbpputc(symset[i]);
- lbpputs("\033[100;0 D");
- return;
-}
-
-lbp_printer::lbp_printer(int ps, double pw, double pl)
-: fill_pattern(1),
- fill_mode(0),
- cur_hpos(-1),
- cur_font(0),
- cur_size(0),
- cur_symbol_set(0),
- req_linethickness(-1)
-{
-#ifdef SET_BINARY
- SET_BINARY(fileno(stdout));
-#endif
- lbpinit(stdout);
- lbpputs("\033c\033;\033[2&z\033[7 I\033[?32h\033[?33h\033[11h");
- wp54charset(); // Define the new symbol set
- lbpputs("\033[7 I\033[?32h\033[?33h\033[11h");
- // Paper size handling
- if (orientation < 0)
- orientation = 0; // Default orientation is portrait
- papersize = 14; // Default paper size is A4
- if (font::papersize) {
- papersize = set_papersize(font::papersize);
- paperlength = font::paperlength;
- paperwidth = font::paperwidth;
- }
- if (ps >= 0) {
- papersize = ps;
- paperlength = int(pl * font::res + 0.5);
- paperwidth = int(pw * font::res + 0.5);
- }
- if (papersize < 80) // standard paper
- lbpprintf("\033[%dp", (papersize | orientation));
- else // Custom paper
- lbpprintf("\033[%d;%d;%dp", (papersize | orientation),
- paperlength, paperwidth);
- // Number of copies
- lbpprintf("\033[%dv\n", ncopies);
- lbpputs("\033[0u\033[1u\033P1y Grolbp\033\\");
- lbpmoveabs(0, 0);
- lbpputs("\033[0t\033[2t");
- lbpputs("\033('$2\033)' 1"); // Primary symbol set IBML
- // Secondary symbol set IBMR1
- cur_symbol_set = 0;
-}
-
-lbp_printer::~lbp_printer()
-{
- lbpputs("\033P1y\033\\");
- lbpputs("\033c\033<");
-}
-
-void lbp_printer::begin_page(int)
-{
-}
-
-void lbp_printer::end_page(int)
-{
- if (vdminited())
- vdmflush();
- lbpputc('\f');
- cur_hpos = -1;
-}
-
-void lbp_printer::end_of_line()
-{
- cur_hpos = -1; // force absolute motion
-}
-
-char *lbp_printer::font_name(const lbp_font *f, const int siz)
-{
- static char bfont_name[255]; // The resulting font name
- char type, // Italic, Roman, Bold
- ori, // Normal or Rotated
- *nam; // The font name without other data.
- int cpi; // The font size in characters per inch
- // (bitmapped fonts are monospaced).
- /* Bitmap font selection is ugly in this printer, so don't expect
- this function to be elegant. */
- bfont_name[0] = 0x00;
- if (orientation) // Landscape
- ori = 'R';
- else // Portrait
- ori = 'N';
- type = f->lbpname[strlen(f->lbpname) - 1];
- nam = new char[strlen(f->lbpname) - 2];
- strncpy(nam, &(f->lbpname[1]), strlen(f->lbpname) - 2);
- nam[strlen(f->lbpname) - 2] = 0x00;
- // fprintf(stderr, "Bitmap font '%s' %d %c %c \n", nam, siz, type, ori);
- /* Since these fonts are available only at certain sizes,
- 10 and 17 cpi for courier, 12 and 17 cpi for elite,
- we adjust the resulting size. */
- cpi = 17;
- // Fortunately there are only two bitmapped fonts shipped with the printer.
- if (!strcasecmp(nam, "courier")) {
- // Courier font
- if (siz >= 12)
- cpi = 10;
- else cpi = 17;
- }
- if (!strcasecmp(nam, "elite")) {
- if (siz >= 10)
- cpi = 12;
- else cpi = 17;
- }
- // Now that we have all the data, let's generate the font name.
- if ((type != 'B') && (type != 'I')) // Roman font
- sprintf(bfont_name, "%c%s%d", ori, nam, cpi);
- else
- sprintf(bfont_name, "%c%s%d%c", ori, nam, cpi, type);
- return bfont_name;
-}
-
-void lbp_printer::set_char(int index, font *f, const environment *env,
- int w, const char *name)
-{
- int code = f->get_code(index);
- unsigned char ch = code & 0xff;
- unsigned short symbol_set = code >> 8;
- if (f != cur_font) {
- lbp_font *psf = (lbp_font *)f;
- // fprintf(stderr, "Loading font %s \"%d\" \n", psf->lbpname, env->size);
- if (psf->is_scalable) {
- // Scalable font selection is different from bitmaped
- lbpprintf("\033Pz%s.IBML\033\\\033[%d C", psf->lbpname,
- (int)((env->size * font::res) / 72));
- }
- else
- // bitmapped font
- lbpprintf("\033Pz%s.IBML\033\\\n", font_name(psf, env->size));
- lbpputs("\033)' 1"); // Select IBML and IBMR1 symbol set
- cur_font = psf;
- cur_symbol_set = 0;
- // Update the line thickness if needed
- if ((req_linethickness < 0 ) && (env->size != cur_size))
- set_line_thickness(req_linethickness,env);
- cur_size = env->size;
- }
- if (symbol_set != cur_symbol_set) {
- if (cur_symbol_set == 3)
- // if current symbol set is Symbol we must restore the font
- lbpprintf("\033Pz%s.IBML\033\\\033[%d C", cur_font->lbpname,
- (int)((env->size * font::res) / 72));
- switch (symbol_set) {
- case 0:
- lbpputs("\033('$2\033)' 1"); // Select IBML and IBMR1 symbol sets
- break;
- case 1:
- lbpputs("\033(d\033)' 1"); // Select wp54 symbol set
- break;
- case 2:
- lbpputs("\033('$2\033)'!0"); // Select IBMP symbol set
- break;
- case 3:
- lbpprintf("\033PzSymbol.SYML\033\\\033[%d C",
- (int)((env->size * font::res) / 72));
- lbpputs("\033(\"!!0\033)\"!!1"); // Select symbol font
- break;
- case 4:
- lbpputs("\033)\"! 1\033(\"!$2"); // Select PS symbol set
- break;
- }
- cur_symbol_set = symbol_set;
- }
- if (env->size != cur_size) {
- if (!cur_font->is_scalable)
- lbpprintf("\033Pz%s.IBML\033\\\n", font_name(cur_font, env->size));
- else
- lbpprintf("\033[%d C", (int)((env->size * font::res) / 72));
- cur_size = env->size;
- // Update the line thickness if needed
- if (req_linethickness < 0 )
- set_line_thickness(req_linethickness,env);
- }
- if ((env->hpos != cur_hpos) || (env->vpos != cur_vpos)) {
- // lbpmoveabs(env->hpos - ((5 * 300) / 16), env->vpos);
- lbpmoveabs(env->hpos - 64, env->vpos - 64);
- cur_vpos = env->vpos;
- cur_hpos = env->hpos;
- }
- if ((ch & 0x7F) < 32)
- lbpputs("\033[1.v");
- lbpputc(ch);
- cur_hpos += w;
-}
-
-void lbp_printer::vdmstart()
-{
- FILE *f;
- static int changed_origin = 0;
- errno = 0;
- f = tmpfile();
- // f = fopen("/tmp/gtmp","w+");
- if (f == NULL)
- perror("Opening temporary file");
- vdminit(f);
- if (!changed_origin) { // we should change the origin only one time
- changed_origin = 1;
- vdmorigin(-63, 0);
- }
- vdmlinewidth(line_thickness);
-}
-
-void
-lbp_printer::vdmflush()
-{
- char buffer[1024];
- int bytes_read = 1;
- vdmend();
- fflush(lbpoutput);
- /* let's copy the vdm code to the output */
- rewind(vdmoutput);
- do {
- bytes_read = fread(buffer, 1, sizeof(buffer), vdmoutput);
- bytes_read = fwrite(buffer, 1, bytes_read, lbpoutput);
- } while (bytes_read == sizeof(buffer));
- fclose(vdmoutput); // This will also delete the file,
- // since it is created by tmpfile()
- vdmoutput = NULL;
-}
-
-inline void lbp_printer::setfillmode(int mode)
-{
- if (mode != fill_mode) {
- if (mode != 1)
- vdmsetfillmode(mode, 1, 0);
- else
- vdmsetfillmode(mode, 1, 1); // To get black we must use white
- // inverted
- fill_mode = mode;
- }
-}
-
-inline void lbp_printer::polygon(int hpos, int vpos, int np, int *p)
-{
- int *points, i;
- points = new int[np + 2];
- points[0] = hpos;
- points[1] = vpos;
- // fprintf(stderr, "Poligon (%d,%d) ", points[0], points[1]);
- for (i = 0; i < np; i++)
- points[i + 2] = p[i];
- // for (i = 0; i < np; i++) fprintf(stderr, " %d ", p[i]);
- // fprintf(stderr, "\n");
- vdmpolygon((np /2) + 1, points);
-}
-
-inline void lbp_printer::set_line_thickness(int size,const environment *env)
-{
- if (size == 0)
- line_thickness = 1;
- else {
- if (size < 0)
- // line_thickness =
- // (env->size * (font::res/72)) * (linewidth_factor/1000)
- // we ought to check for overflow
- line_thickness =
- env->size * linewidth_factor * font::res / 72000;
- else // size > 0
- line_thickness = size;
- } // else from if (size == 0)
- if (line_thickness < 1)
- line_thickness = 1;
- if (vdminited())
- vdmlinewidth(line_thickness);
- req_linethickness = size; // an size requested
- /* fprintf(stderr, "thickness: %d == %d, size %d, %d \n",
- size, line_thickness, env->size,req_linethickness); */
- return;
-}; // lbp_printer::set_line_thickness
-
-void lbp_printer::draw(int code, int *p, int np, const environment *env)
-{
- if ((req_linethickness < 0 ) && (env->size != cur_size))
- set_line_thickness(req_linethickness,env);
-
- switch (code) {
- case 't':
- if (np == 0)
- line_thickness = 1;
- else { // troff gratuitously adds an extra 0
- if (np != 1 && np != 2) {
- error("0 or 1 argument required for thickness");
- break;
- };
- set_line_thickness(p[0],env);
- };
- break;
- case 'l': // Line
- if (np != 2) {
- error("2 arguments required for line");
- break;
- }
- if (!vdminited())
- vdmstart();
- vdmline(env->hpos, env->vpos, p[0], p[1]);
-/* fprintf(stderr, "\nline: %d,%d - %d,%d thickness %d == %d\n",
- env->hpos - 64,env->vpos -64, env->hpos - 64 + p[0],
- env->vpos -64 + p[1], env->size, line_thickness);*/
- break;
- case 'R': // Rule
- if (np != 2) {
- error("2 arguments required for Rule");
- break;
- }
- if (vdminited()) {
- setfillmode(fill_pattern); // Solid Rule
- vdmrectangle(env->hpos, env->vpos, p[0], p[1]);
- }
- else {
- lbpruleabs(env->hpos - 64, env->vpos -64, p[0], p[1]);
- cur_vpos = p[1];
- cur_hpos = p[0];
- }
- // fprintf(stderr, "\nrule: thickness %d == %d\n",
- // env->size, line_thickness);
- break;
- case 'P': // Filled Polygon
- if (!vdminited())
- vdmstart();
- setfillmode(fill_pattern);
- polygon(env->hpos, env->vpos, np, p);
- break;
- case 'p': // Empty Polygon
- if (!vdminited())
- vdmstart();
- setfillmode(0);
- polygon(env->hpos, env->vpos, np, p);
- break;
- case 'C': // Filled Circle
- if (!vdminited())
- vdmstart();
- // fprintf(stderr, "Circle (%d,%d) Fill %d\n",
- // env->hpos, env->vpos, fill_pattern);
- setfillmode(fill_pattern);
- vdmcircle(env->hpos + (p[0]/2), env->vpos, p[0]/2);
- break;
- case 'c': // Empty Circle
- if (!vdminited())
- vdmstart();
- setfillmode(0);
- vdmcircle(env->hpos + (p[0]/2), env->vpos, p[0]/2);
- break;
- case 'E': // Filled Ellipse
- if (!vdminited())
- vdmstart();
- setfillmode(fill_pattern);
- vdmellipse(env->hpos + (p[0]/2), env->vpos, p[0]/2, p[1]/2, 0);
- break;
- case 'e': // Empty Ellipse
- if (!vdminited())
- vdmstart();
- setfillmode(0);
- vdmellipse(env->hpos + (p[0]/2), env->vpos, p[0]/2, p[1]/2, 0);
- break;
- case 'a': // Arc
- if (!vdminited())
- vdmstart();
- setfillmode(0);
- // VDM draws arcs clockwise and pic counterclockwise
- // We must compensate for that, exchanging the starting and
- // ending points
- vdmvarc(env->hpos + p[0], env->vpos+p[1],
- int(sqrt(double((p[0]*p[0]) + (p[1]*p[1])))),
- p[2], p[3],
- (-p[0]), (-p[1]), 1, 2);
- break;
- case '~': // Spline
- if (!vdminited())
- vdmstart();
- setfillmode(0);
- vdmspline(np/2, env->hpos, env->vpos, p);
- break;
- case 'f':
- if (np != 1 && np != 2) {
- error("1 argument required for fill");
- break;
- }
- // fprintf(stderr, "Fill %d\n", p[0]);
- if ((p[0] == 1) || (p[0] >= 1000)) { // Black
- fill_pattern = 1;
- break;
- }
- if (p[0] == 0) { // White
- fill_pattern = 0;
- break;
- }
- if ((p[0] > 1) && (p[0] < 1000))
- {
- if (p[0] >= 990) fill_pattern = -23;
- else if (p[0] >= 700) fill_pattern = -28;
- else if (p[0] >= 500) fill_pattern = -27;
- else if (p[0] >= 400) fill_pattern = -26;
- else if (p[0] >= 300) fill_pattern = -25;
- else if (p[0] >= 200) fill_pattern = -22;
- else if (p[0] >= 100) fill_pattern = -24;
- else fill_pattern = -21;
- }
- break;
- case 'F':
- // not implemented yet
- break;
- default:
- error("unrecognised drawing command `%1'", char(code));
- break;
- }
- return;
-}
-
-font *lbp_printer::make_font(const char *nm)
-{
- return lbp_font::load_lbp_font(nm);
-}
-
-printer *make_printer()
-{
- return new lbp_printer(user_papersize, user_paperwidth, user_paperlength);
-}
-
-static struct {
- const char *name;
- int code;
-} lbp_papersizes[] =
- {{ "A4", 14 },
- { "letter", 30 },
- { "legal", 32 },
- { "executive", 40 },
- };
-
-static int set_papersize(const char *paperformat)
-{
- unsigned int i;
- // First test for a standard (i.e. supported directly by the printer)
- // paper size
- for (i = 0 ; i < sizeof(lbp_papersizes) / sizeof(lbp_papersizes[0]); i++)
- {
- if (strcasecmp(lbp_papersizes[i].name,paperformat) == 0)
- return lbp_papersizes[i].code;
- }
- // Otherwise, we assume a custom paper size
- return 82;
-}
-
-static void handle_unknown_desc_command(const char *command, const char *arg,
- const char *filename, int lineno)
-{
- // orientation command
- if (strcasecmp(command, "orientation") == 0) {
- // We give priority to command line options
- if (orientation > 0)
- return;
- if (arg == 0)
- error_with_file_and_line(filename, lineno,
- "`orientation' command requires an argument");
- else {
- if (strcasecmp(arg, "portrait") == 0)
- orientation = 0;
- else {
- if (strcasecmp(arg, "landscape") == 0)
- orientation = 1;
- else
- error_with_file_and_line(filename, lineno,
- "invalid argument to `orientation' command");
- }
- }
- }
-}
-
-static struct option long_options[] = {
- { "orientation", required_argument, NULL, 'o' },
- { "version", no_argument, NULL, 'v' },
- { "copies", required_argument, NULL, 'c' },
- { "landscape", no_argument, NULL, 'l' },
- { "papersize", required_argument, NULL, 'p' },
- { "linewidth", required_argument, NULL, 'w' },
- { "fontdir", required_argument, NULL, 'F' },
- { "help", no_argument, NULL, 'h' },
- { NULL, 0, 0, 0 }
-};
-
-static void usage(FILE *stream)
-{
- fprintf(stream,
- "usage: %s [-lvh] [-c n] [-p paper_size] [-F dir] [-o or]\n"
- " [-w width] [files ...]\n"
- "\n"
- " -o --orientation=[portrait|landscape]\n"
- " -v --version\n"
- " -c --copies=numcopies\n"
- " -l --landscape\n"
- " -p --papersize=paper_size\n"
- " -w --linewidth=width\n"
- " -F --fontdir=dir\n"
- " -h --help\n",
- program_name);
-}
-
-int main(int argc, char **argv)
-{
- if (program_name == NULL)
- program_name = strsave(argv[0]);
- font::set_unknown_desc_command_handler(handle_unknown_desc_command);
- // command line parsing
- int c = 0;
- int option_index = 0;
- while (c >= 0) {
- c = getopt_long (argc, argv, "F:p:lvo:c:hw:",
- long_options, &option_index);
- switch (c) {
- case 'F':
- font::command_line_font_dir(optarg);
- break;
- case 'p':
- {
- const char *s;
- if (!font::scan_papersize(optarg, &s,
- &user_paperlength, &user_paperwidth))
- error("invalid paper size `%1' ignored", optarg);
- else
- user_papersize = set_papersize(s);
- break;
- }
- case 'l':
- orientation = 1;
- break;
- case 'v':
- printf("GNU grolbp (groff) version %s\n", Version_string);
- exit(0);
- break;
- case 'o':
- if (strcasecmp(optarg, "portrait") == 0)
- orientation = 0;
- else {
- if (strcasecmp(optarg, "landscape") == 0)
- orientation = 1;
- else
- error("unknown orientation '%1'", optarg);
- };
- break;
- case 'c':
- {
- char *ptr;
- long n = strtol(optarg, &ptr, 10);
- if ((n <= 0) && (ptr == optarg))
- error("argument for -c must be a positive integer");
- else if (n <= 0 || n > 32767)
- error("out of range argument for -c");
- else
- ncopies = unsigned(n);
- break;
- }
- case 'w':
- {
- char *ptr;
- long n = strtol(optarg, &ptr, 10);
- if (n == 0 && ptr == optarg)
- error("argument for -w must be a non-negative integer");
- else if (n < 0 || n > INT_MAX)
- error("out of range argument for -w");
- else
- linewidth_factor = int(n);
- break;
- }
- case 'h':
- usage(stdout);
- exit(0);
- break;
- case '?':
- usage(stderr);
- exit(1);
- break;
- }
- }
- if (optind >= argc)
- do_file("-");
- while (optind < argc)
- do_file(argv[optind++]);
- lbpputs("\033c\033<");
- delete pr;
- return 0;
-}
diff --git a/contrib/groff/src/devices/grolj4/lj4.cc b/contrib/groff/src/devices/grolj4/lj4.cc
deleted file mode 100644
index 0c3150d..0000000
--- a/contrib/groff/src/devices/grolj4/lj4.cc
+++ /dev/null
@@ -1,708 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1994, 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-/*
-TODO
-
-option to use beziers for circle/ellipse/arc
-option to use lines for spline (for LJ3)
-left/top offset registration
-output bin selection option
-paper source option
-output non-integer parameters using fixed point numbers
-X command to insert contents of file
-X command to specify inline escape sequence (how to specify unprintable chars?)
-X command to include bitmap graphics
-*/
-
-#include "driver.h"
-#include "nonposix.h"
-
-extern "C" const char *Version_string;
-
-static struct {
- const char *name;
- int code;
- // at 300dpi
- int x_offset_portrait;
- int x_offset_landscape;
-} paper_table[] = {
- { "letter", 2, 75, 60 },
- { "legal", 3, 75, 60 },
- { "executive", 1, 75, 60 },
- { "a4", 26, 71, 59 },
- { "com10", 81, 75, 60 },
- { "monarch", 80, 75, 60 },
- { "c5", 91, 71, 59 },
- { "b5", 100, 71, 59 },
- { "dl", 90, 71, 59 },
-};
-
-static int user_paper_size = -1;
-static int landscape_flag = 0;
-static int duplex_flag = 0;
-
-// An upper limit on the paper size in centipoints,
-// used for setting HPGL picture frame.
-#define MAX_PAPER_WIDTH (12*720)
-#define MAX_PAPER_HEIGHT (17*720)
-
-// Dotted lines that are thinner than this don't work right.
-#define MIN_DOT_PEN_WIDTH .351
-
-#ifndef DEFAULT_LINE_WIDTH_FACTOR
-// in ems/1000
-#define DEFAULT_LINE_WIDTH_FACTOR 40
-#endif
-
-const int DEFAULT_HPGL_UNITS = 1016;
-int line_width_factor = DEFAULT_LINE_WIDTH_FACTOR;
-unsigned ncopies = 0; // 0 means don't send ncopies command
-
-static int lookup_paper_size(const char *);
-
-class lj4_font : public font {
-public:
- ~lj4_font();
- void handle_unknown_font_command(const char *command, const char *arg,
- const char *filename, int lineno);
- static lj4_font *load_lj4_font(const char *);
- int weight;
- int style;
- int proportional;
- int typeface;
-private:
- lj4_font(const char *);
-};
-
-lj4_font::lj4_font(const char *nm)
-: font(nm), weight(0), style(0), proportional(0), typeface(0)
-{
-}
-
-lj4_font::~lj4_font()
-{
-}
-
-lj4_font *lj4_font::load_lj4_font(const char *s)
-{
- lj4_font *f = new lj4_font(s);
- if (!f->load()) {
- delete f;
- return 0;
- }
- return f;
-}
-
-static struct {
- const char *s;
- int lj4_font::*ptr;
- int min;
- int max;
-} command_table[] = {
- { "pclweight", &lj4_font::weight, -7, 7 },
- { "pclstyle", &lj4_font::style, 0, 32767 },
- { "pclproportional", &lj4_font::proportional, 0, 1 },
- { "pcltypeface", &lj4_font::typeface, 0, 65535 },
-};
-
-void lj4_font::handle_unknown_font_command(const char *command,
- const char *arg,
- const char *filename, int lineno)
-{
- for (unsigned int i = 0;
- i < sizeof(command_table)/sizeof(command_table[0]); i++) {
- if (strcmp(command, command_table[i].s) == 0) {
- if (arg == 0)
- fatal_with_file_and_line(filename, lineno,
- "`%1' command requires an argument",
- command);
- char *ptr;
- long n = strtol(arg, &ptr, 10);
- if (n == 0 && ptr == arg)
- fatal_with_file_and_line(filename, lineno,
- "`%1' command requires numeric argument",
- command);
- if (n < command_table[i].min) {
- error_with_file_and_line(filename, lineno,
- "argument for `%1' command must not be less than %2",
- command, command_table[i].min);
- n = command_table[i].min;
- }
- else if (n > command_table[i].max) {
- error_with_file_and_line(filename, lineno,
- "argument for `%1' command must not be greater than %2",
- command, command_table[i].max);
- n = command_table[i].max;
- }
- this->*command_table[i].ptr = int(n);
- break;
- }
- }
-}
-
-class lj4_printer : public printer {
-public:
- lj4_printer(int);
- ~lj4_printer();
- void set_char(int, font *, const environment *, int, const char *name);
- void draw(int code, int *p, int np, const environment *env);
- void begin_page(int);
- void end_page(int page_length);
- font *make_font(const char *);
- void end_of_line();
-private:
- void set_line_thickness(int size, int dot = 0);
- void hpgl_init();
- void hpgl_start();
- void hpgl_end();
- int moveto(int hpos, int vpos);
- int moveto1(int hpos, int vpos);
-
- int cur_hpos;
- int cur_vpos;
- lj4_font *cur_font;
- int cur_size;
- unsigned short cur_symbol_set;
- int x_offset;
- int line_thickness;
- double pen_width;
- double hpgl_scale;
- int hpgl_inited;
- int paper_size;
-};
-
-inline
-int lj4_printer::moveto(int hpos, int vpos)
-{
- if (cur_hpos != hpos || cur_vpos != vpos || cur_hpos < 0)
- return moveto1(hpos, vpos);
- else
- return 1;
-}
-
-inline
-void lj4_printer::hpgl_start()
-{
- fputs("\033%1B", stdout);
-}
-
-inline
-void lj4_printer::hpgl_end()
-{
- fputs(";\033%0A", stdout);
-}
-
-lj4_printer::lj4_printer(int ps)
-: cur_hpos(-1),
- cur_font(0),
- cur_size(0),
- cur_symbol_set(0),
- line_thickness(-1),
- pen_width(-1.0),
- hpgl_inited(0)
-{
- if (7200 % font::res != 0)
- fatal("invalid resolution %1: resolution must be a factor of 7200",
- font::res);
- fputs("\033E", stdout); // reset
- if (font::res != 300)
- printf("\033&u%dD", font::res); // unit of measure
- if (ncopies > 0)
- printf("\033&l%uX", ncopies);
- paper_size = 0; // default to letter
- if (font::papersize) {
- int n = lookup_paper_size(font::papersize);
- if (n < 0)
- error("unknown paper size `%1'", font::papersize);
- else
- paper_size = n;
- }
- if (ps >= 0)
- paper_size = ps;
- printf("\033&l%dA" // paper size
- "\033&l%dO" // orientation
- "\033&l0E", // no top margin
- paper_table[paper_size].code,
- landscape_flag != 0);
- if (landscape_flag)
- x_offset = paper_table[paper_size].x_offset_landscape;
- else
- x_offset = paper_table[paper_size].x_offset_portrait;
- x_offset = (x_offset * font::res) / 300;
- if (duplex_flag)
- printf("\033&l%dS", duplex_flag);
-}
-
-lj4_printer::~lj4_printer()
-{
- fputs("\033E", stdout);
-}
-
-void lj4_printer::begin_page(int)
-{
-}
-
-void lj4_printer::end_page(int)
-{
- putchar('\f');
- cur_hpos = -1;
-}
-
-void lj4_printer::end_of_line()
-{
- cur_hpos = -1; // force absolute motion
-}
-
-inline
-int is_unprintable(unsigned char c)
-{
- return c < 32 && (c == 0 || (7 <= c && c <= 15) || c == 27);
-}
-
-void lj4_printer::set_char(int index, font *f, const environment *env,
- int w, const char *name)
-{
- int code = f->get_code(index);
-
- unsigned char ch = code & 0xff;
- unsigned short symbol_set = code >> 8;
- if (symbol_set != cur_symbol_set) {
- printf("\033(%d%c", symbol_set/32, (symbol_set & 31) + 64);
- cur_symbol_set = symbol_set;
- }
- if (f != cur_font) {
- lj4_font *psf = (lj4_font *)f;
- // FIXME only output those that are needed
- printf("\033(s%dp%ds%db%dT",
- psf->proportional,
- psf->style,
- psf->weight,
- psf->typeface);
- if (!psf->proportional || !cur_font || !cur_font->proportional)
- cur_size = 0;
- cur_font = psf;
- }
- if (env->size != cur_size) {
- if (cur_font->proportional) {
- static const char *quarters[] = { "", ".25", ".5", ".75" };
- printf("\033(s%d%sV", env->size/4, quarters[env->size & 3]);
- }
- else {
- double pitch = double(font::res)/w;
- // PCL uses the next largest pitch, so round it down.
- pitch = floor(pitch*100.0)/100.0;
- printf("\033(s%.2fH", pitch);
- }
- cur_size = env->size;
- }
- if (!moveto(env->hpos, env->vpos))
- return;
- if (is_unprintable(ch))
- fputs("\033&p1X", stdout);
- putchar(ch);
- cur_hpos += w;
-}
-
-int lj4_printer::moveto1(int hpos, int vpos)
-{
- if (hpos < x_offset || vpos < 0)
- return 0;
- fputs("\033*p", stdout);
- if (cur_hpos < 0)
- printf("%dx%dY", hpos - x_offset, vpos);
- else {
- if (cur_hpos != hpos)
- printf("%s%d%c", hpos > cur_hpos ? "+" : "",
- hpos - cur_hpos, vpos == cur_vpos ? 'X' : 'x');
- if (cur_vpos != vpos)
- printf("%s%dY", vpos > cur_vpos ? "+" : "", vpos - cur_vpos);
- }
- cur_hpos = hpos;
- cur_vpos = vpos;
- return 1;
-}
-
-void lj4_printer::draw(int code, int *p, int np, const environment *env)
-{
- switch (code) {
- case 'R':
- {
- if (np != 2) {
- error("2 arguments required for rule");
- break;
- }
- int hpos = env->hpos;
- int vpos = env->vpos;
- int hsize = p[0];
- int vsize = p[1];
- if (hsize < 0) {
- hpos += hsize;
- hsize = -hsize;
- }
- if (vsize < 0) {
- vpos += vsize;
- vsize = -vsize;
- }
- if (!moveto(hpos, vpos))
- return;
- printf("\033*c%da%db0P", hsize, vsize);
- break;
- }
- case 'l':
- if (np != 2) {
- error("2 arguments required for line");
- break;
- }
- hpgl_init();
- if (!moveto(env->hpos, env->vpos))
- return;
- hpgl_start();
- set_line_thickness(env->size, p[0] == 0 && p[1] == 0);
- printf("PD%d,%d", p[0], p[1]);
- hpgl_end();
- break;
- case 'p':
- case 'P':
- {
- if (np & 1) {
- error("even number of arguments required for polygon");
- break;
- }
- if (np == 0) {
- error("no arguments for polygon");
- break;
- }
- hpgl_init();
- if (!moveto(env->hpos, env->vpos))
- return;
- hpgl_start();
- if (code == 'p')
- set_line_thickness(env->size);
- printf("PMPD%d", p[0]);
- for (int i = 1; i < np; i++)
- printf(",%d", p[i]);
- printf("PM2%cP", code == 'p' ? 'E' : 'F');
- hpgl_end();
- break;
- }
- case '~':
- {
- if (np & 1) {
- error("even number of arguments required for spline");
- break;
- }
- if (np == 0) {
- error("no arguments for spline");
- break;
- }
- hpgl_init();
- if (!moveto(env->hpos, env->vpos))
- return;
- hpgl_start();
- set_line_thickness(env->size);
- printf("PD%d,%d", p[0]/2, p[1]/2);
- const int tnum = 2;
- const int tden = 3;
- if (np > 2) {
- fputs("BR", stdout);
- for (int i = 0; i < np - 2; i += 2) {
- if (i != 0)
- putchar(',');
- printf("%d,%d,%d,%d,%d,%d",
- (p[i]*tnum)/(2*tden),
- (p[i + 1]*tnum)/(2*tden),
- p[i]/2 + (p[i + 2]*(tden - tnum))/(2*tden),
- p[i + 1]/2 + (p[i + 3]*(tden - tnum))/(2*tden),
- (p[i] - p[i]/2) + p[i + 2]/2,
- (p[i + 1] - p[i + 1]/2) + p[i + 3]/2);
- }
- }
- printf("PR%d,%d", p[np - 2] - p[np - 2]/2, p[np - 1] - p[np - 1]/2);
- hpgl_end();
- break;
- }
- case 'c':
- case 'C':
- // troff adds an extra argument to C
- if (np != 1 && !(code == 'C' && np == 2)) {
- error("1 argument required for circle");
- break;
- }
- hpgl_init();
- if (!moveto(env->hpos + p[0]/2, env->vpos))
- return;
- hpgl_start();
- if (code == 'c') {
- set_line_thickness(env->size);
- printf("CI%d", p[0]/2);
- }
- else
- printf("WG%d,0,360", p[0]/2);
- hpgl_end();
- break;
- case 'e':
- case 'E':
- if (np != 2) {
- error("2 arguments required for ellipse");
- break;
- }
- hpgl_init();
- if (!moveto(env->hpos + p[0]/2, env->vpos))
- return;
- hpgl_start();
- printf("SC0,%.4f,0,-%.4f,2", hpgl_scale * double(p[0])/p[1], hpgl_scale);
- if (code == 'e') {
- set_line_thickness(env->size);
- printf("CI%d", p[1]/2);
- }
- else
- printf("WG%d,0,360", p[1]/2);
- printf("SC0,%.4f,0,-%.4f,2", hpgl_scale, hpgl_scale);
- hpgl_end();
- break;
- case 'a':
- {
- if (np != 4) {
- error("4 arguments required for arc");
- break;
- }
- hpgl_init();
- if (!moveto(env->hpos, env->vpos))
- return;
- hpgl_start();
- set_line_thickness(env->size);
- double c[2];
- if (adjust_arc_center(p, c)) {
- double sweep = ((atan2(p[1] + p[3] - c[1], p[0] + p[2] - c[0])
- - atan2(-c[1], -c[0]))
- * 180.0/PI);
- if (sweep > 0.0)
- sweep -= 360.0;
- printf("PDAR%d,%d,%f", int(c[0]), int(c[1]), sweep);
- }
- else
- printf("PD%d,%d", p[0] + p[2], p[1] + p[3]);
- hpgl_end();
- }
- break;
- case 'f':
- if (np != 1 && np != 2) {
- error("1 argument required for fill");
- break;
- }
- hpgl_init();
- hpgl_start();
- if (p[0] >= 0 && p[0] <= 1000)
- printf("FT10,%d", p[0]/10);
- hpgl_end();
- break;
- case 'F':
- // not implemented yet
- break;
- case 't':
- {
- if (np == 0) {
- line_thickness = -1;
- }
- else {
- // troff gratuitously adds an extra 0
- if (np != 1 && np != 2) {
- error("0 or 1 argument required for thickness");
- break;
- }
- line_thickness = p[0];
- }
- break;
- }
- default:
- error("unrecognised drawing command `%1'", char(code));
- break;
- }
-}
-
-void lj4_printer::hpgl_init()
-{
- if (hpgl_inited)
- return;
- hpgl_inited = 1;
- hpgl_scale = double(DEFAULT_HPGL_UNITS)/font::res;
- printf("\033&f0S" // push position
- "\033*p0x0Y" // move to 0,0
- "\033*c%dx%dy0T" // establish picture frame
- "\033%%1B" // switch to HPGL
- "SP1SC0,%.4f,0,-%.4f,2IR0,100,0,100" // set up scaling
- "LA1,4,2,4" // round line ends and joins
- "PR" // relative plotting
- "TR0" // opaque
- ";\033%%1A" // back to PCL
- "\033&f1S", // pop position
- MAX_PAPER_WIDTH, MAX_PAPER_HEIGHT,
- hpgl_scale, hpgl_scale);
-}
-
-void lj4_printer::set_line_thickness(int size, int dot)
-{
- double pw;
- if (line_thickness < 0)
- pw = (size * (line_width_factor * 25.4))/(font::sizescale * 72000.0);
- else
- pw = line_thickness*25.4/font::res;
- if (dot && pw < MIN_DOT_PEN_WIDTH)
- pw = MIN_DOT_PEN_WIDTH;
- if (pw != pen_width) {
- printf("PW%f", pw);
- pen_width = pw;
- }
-}
-
-font *lj4_printer::make_font(const char *nm)
-{
- return lj4_font::load_lj4_font(nm);
-}
-
-printer *make_printer()
-{
- return new lj4_printer(user_paper_size);
-}
-
-static
-int lookup_paper_size(const char *s)
-{
- for (unsigned int i = 0;
- i < sizeof(paper_table)/sizeof(paper_table[0]); i++) {
- // FIXME Perhaps allow unique prefix.
- if (strcasecmp(s, paper_table[i].name) == 0)
- return i;
- }
- return -1;
-}
-
-static void usage(FILE *stream);
-
-extern "C" int optopt, optind;
-
-int main(int argc, char **argv)
-{
- program_name = argv[0];
- static char stderr_buf[BUFSIZ];
- setbuf(stderr, stderr_buf);
- int c;
- 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, ":F:p:d:lvw:c:", long_options, NULL))
- != EOF)
- switch(c) {
- case 'l':
- landscape_flag = 1;
- break;
- case ':':
- if (optopt == 'd') {
- fprintf(stderr, "duplex assumed to be long-side\n");
- duplex_flag = 1;
- } else
- fprintf(stderr, "option -%c requires an operand\n", optopt);
- fflush(stderr);
- break;
- case 'd':
- if (!isdigit(*optarg)) // this ugly hack prevents -d without
- optind--; // args from messing up the arg list
- duplex_flag = atoi(optarg);
- if (duplex_flag != 1 && duplex_flag != 2) {
- fprintf(stderr, "odd value for duplex; assumed to be long-side\n");
- duplex_flag = 1;
- }
- break;
- case 'p':
- {
- int n = lookup_paper_size(optarg);
- if (n < 0)
- error("unknown paper size `%1'", optarg);
- else
- user_paper_size = n;
- break;
- }
- case 'v':
- {
- printf("GNU grolj4 (groff) version %s\n", Version_string);
- exit(0);
- break;
- }
- case 'F':
- font::command_line_font_dir(optarg);
- break;
- case 'c':
- {
- char *ptr;
- long n = strtol(optarg, &ptr, 10);
- if (n == 0 && ptr == optarg)
- error("argument for -c must be a positive integer");
- else if (n <= 0 || n > 32767)
- error("out of range argument for -c");
- else
- ncopies = unsigned(n);
- break;
- }
- case 'w':
- {
- char *ptr;
- long n = strtol(optarg, &ptr, 10);
- if (n == 0 && ptr == optarg)
- error("argument for -w must be a non-negative integer");
- else if (n < 0 || n > INT_MAX)
- error("out of range argument for -w");
- else
- line_width_factor = int(n);
- break;
- }
- case CHAR_MAX + 1: // --help
- usage(stdout);
- exit(0);
- break;
- case '?':
- usage(stderr);
- exit(1);
- break;
- default:
- assert(0);
- }
-#ifdef SET_BINARY
- SET_BINARY(fileno(stdout));
-#endif
- if (optind >= argc)
- do_file("-");
- else {
- for (int i = optind; i < argc; i++)
- do_file(argv[i]);
- }
- delete pr;
- return 0;
-}
-
-static void usage(FILE *stream)
-{
- fprintf(stream,
- "usage: %s [-lv] [-d [n]] [-c n] [-p paper_size]\n"
- " [-w n] [-F dir] [files ...]\n",
- program_name);
-}
diff --git a/contrib/groff/src/devices/grops/ps.cc b/contrib/groff/src/devices/grops/ps.cc
deleted file mode 100644
index 47d1f65..0000000
--- a/contrib/groff/src/devices/grops/ps.cc
+++ /dev/null
@@ -1,1642 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "driver.h"
-#include "stringclass.h"
-#include "cset.h"
-#include "nonposix.h"
-#include "paper.h"
-
-#include "ps.h"
-#include
-
-#ifdef NEED_DECLARATION_PUTENV
-extern "C" {
- int putenv(const char *);
-}
-#endif /* NEED_DECLARATION_PUTENV */
-
-extern "C" const char *Version_string;
-
-static int landscape_flag = 0;
-static int manual_feed_flag = 0;
-static int ncopies = 1;
-static int linewidth = -1;
-// Non-zero means generate PostScript code that guesses the paper
-// length using the imageable area.
-static int guess_flag = 0;
-static double user_paper_length = 0;
-
-// Non-zero if -b was specified on the command line.
-static int bflag = 0;
-unsigned broken_flags = 0;
-
-#define DEFAULT_LINEWIDTH 40 /* in ems/1000 */
-#define MAX_LINE_LENGTH 72
-#define FILL_MAX 1000
-
-const char *const dict_name = "grops";
-const char *const defs_dict_name = "DEFS";
-const int DEFS_DICT_SPARE = 50;
-
-double degrees(double r)
-{
- return r*180.0/PI;
-}
-
-double radians(double d)
-{
- return d*PI/180.0;
-}
-
-inline double transform_fill(int fill)
-{
- return 1 - fill/double(FILL_MAX);
-}
-
-// This is used for testing whether a character should be output in the
-// PostScript file using \nnn, so we really want the character to be
-// less than 0200.
-
-inline int is_ascii(char c)
-{
- return (unsigned char)c < 0200;
-}
-
-ps_output::ps_output(FILE *f, int n)
-: fp(f), col(0), max_line_length(n), need_space(0), fixed_point(0)
-{
-}
-
-ps_output &ps_output::set_file(FILE *f)
-{
- fp = f;
- col = 0;
- return *this;
-}
-
-ps_output &ps_output::copy_file(FILE *infp)
-{
- int c;
- while ((c = getc(infp)) != EOF)
- putc(c, fp);
- return *this;
-}
-
-ps_output &ps_output::end_line()
-{
- if (col != 0) {
- putc('\n', fp);
- col = 0;
- need_space = 0;
- }
- return *this;
-}
-
-ps_output &ps_output::special(const char *s)
-{
- if (s == 0 || *s == '\0')
- return *this;
- if (col != 0) {
- putc('\n', fp);
- col = 0;
- }
- fputs(s, fp);
- if (strchr(s, '\0')[-1] != '\n')
- putc('\n', fp);
- need_space = 0;
- return *this;
-}
-
-ps_output &ps_output::simple_comment(const char *s)
-{
- if (col != 0)
- putc('\n', fp);
- putc('%', fp);
- putc('%', fp);
- fputs(s, fp);
- putc('\n', fp);
- col = 0;
- need_space = 0;
- return *this;
-}
-
-ps_output &ps_output::begin_comment(const char *s)
-{
- if (col != 0)
- putc('\n', fp);
- putc('%', fp);
- putc('%', fp);
- fputs(s, fp);
- col = 2 + strlen(s);
- return *this;
-}
-
-ps_output &ps_output::end_comment()
-{
- if (col != 0) {
- putc('\n', fp);
- col = 0;
- }
- need_space = 0;
- return *this;
-}
-
-ps_output &ps_output::comment_arg(const char *s)
-{
- int len = strlen(s);
- if (col + len + 1 > max_line_length) {
- putc('\n', fp);
- fputs("%%+", fp);
- col = 3;
- }
- putc(' ', fp);
- fputs(s, fp);
- col += len + 1;
- return *this;
-}
-
-ps_output &ps_output::set_fixed_point(int n)
-{
- assert(n >= 0 && n <= 10);
- fixed_point = n;
- return *this;
-}
-
-ps_output &ps_output::put_delimiter(char c)
-{
- if (col + 1 > max_line_length) {
- putc('\n', fp);
- col = 0;
- }
- putc(c, fp);
- col++;
- need_space = 0;
- return *this;
-}
-
-ps_output &ps_output::put_string(const char *s, int n)
-{
- int len = 0;
- int i;
- for (i = 0; i < n; i++) {
- char c = s[i];
- if (is_ascii(c) && csprint(c)) {
- if (c == '(' || c == ')' || c == '\\')
- len += 2;
- else
- len += 1;
- }
- else
- len += 4;
- }
- if (len > n*2) {
- if (col + n*2 + 2 > max_line_length && n*2 + 2 <= max_line_length) {
- putc('\n', fp);
- col = 0;
- }
- if (col + 1 > max_line_length) {
- putc('\n', fp);
- col = 0;
- }
- putc('<', fp);
- col++;
- for (i = 0; i < n; i++) {
- if (col + 2 > max_line_length) {
- putc('\n', fp);
- col = 0;
- }
- fprintf(fp, "%02x", s[i] & 0377);
- col += 2;
- }
- putc('>', fp);
- col++;
- }
- else {
- if (col + len + 2 > max_line_length && len + 2 <= max_line_length) {
- putc('\n', fp);
- col = 0;
- }
- if (col + 2 > max_line_length) {
- putc('\n', fp);
- col = 0;
- }
- putc('(', fp);
- col++;
- for (i = 0; i < n; i++) {
- char c = s[i];
- if (is_ascii(c) && csprint(c)) {
- if (c == '(' || c == ')' || c == '\\')
- len = 2;
- else
- len = 1;
- }
- else
- len = 4;
- if (col + len + 1 > max_line_length) {
- putc('\\', fp);
- putc('\n', fp);
- col = 0;
- }
- switch (len) {
- case 1:
- putc(c, fp);
- break;
- case 2:
- putc('\\', fp);
- putc(c, fp);
- break;
- case 4:
- fprintf(fp, "\\%03o", c & 0377);
- break;
- default:
- assert(0);
- }
- col += len;
- }
- putc(')', fp);
- col++;
- }
- need_space = 0;
- return *this;
-}
-
-ps_output &ps_output::put_number(int n)
-{
- char buf[1 + INT_DIGITS + 1];
- sprintf(buf, "%d", n);
- int len = strlen(buf);
- if (col > 0 && col + len + need_space > max_line_length) {
- putc('\n', fp);
- col = 0;
- need_space = 0;
- }
- if (need_space) {
- putc(' ', fp);
- col++;
- }
- fputs(buf, fp);
- col += len;
- need_space = 1;
- return *this;
-}
-
-ps_output &ps_output::put_fix_number(int i)
-{
- const char *p = if_to_a(i, fixed_point);
- int len = strlen(p);
- if (col > 0 && col + len + need_space > max_line_length) {
- putc('\n', fp);
- col = 0;
- need_space = 0;
- }
- if (need_space) {
- putc(' ', fp);
- col++;
- }
- fputs(p, fp);
- col += len;
- need_space = 1;
- return *this;
-}
-
-ps_output &ps_output::put_float(double d)
-{
- char buf[128];
- sprintf(buf, "%.3g", d);
- int len = strlen(buf);
- if (col > 0 && col + len + need_space > max_line_length) {
- putc('\n', fp);
- col = 0;
- need_space = 0;
- }
- if (need_space) {
- putc(' ', fp);
- col++;
- }
- fputs(buf, fp);
- col += len;
- need_space = 1;
- return *this;
-}
-
-ps_output &ps_output::put_symbol(const char *s)
-{
- int len = strlen(s);
- if (col > 0 && col + len + need_space > max_line_length) {
- putc('\n', fp);
- col = 0;
- need_space = 0;
- }
- if (need_space) {
- putc(' ', fp);
- col++;
- }
- fputs(s, fp);
- col += len;
- need_space = 1;
- return *this;
-}
-
-ps_output &ps_output::put_color(unsigned int c)
-{
- char buf[128];
- sprintf(buf, "%.3g", double(c) / color::MAX_COLOR_VAL);
- int len = strlen(buf);
- if (col > 0 && col + len + need_space > max_line_length) {
- putc('\n', fp);
- col = 0;
- need_space = 0;
- }
- if (need_space) {
- putc(' ', fp);
- col++;
- }
- fputs(buf, fp);
- col += len;
- need_space = 1;
- return *this;
-}
-
-ps_output &ps_output::put_literal_symbol(const char *s)
-{
- int len = strlen(s);
- if (col > 0 && col + len + 1 > max_line_length) {
- putc('\n', fp);
- col = 0;
- }
- putc('/', fp);
- fputs(s, fp);
- col += len + 1;
- need_space = 1;
- return *this;
-}
-
-class ps_font : public font {
- ps_font(const char *);
-public:
- int encoding_index;
- char *encoding;
- char *reencoded_name;
- ~ps_font();
- void handle_unknown_font_command(const char *command, const char *arg,
- const char *filename, int lineno);
- static ps_font *load_ps_font(const char *);
-};
-
-ps_font *ps_font::load_ps_font(const char *s)
-{
- ps_font *f = new ps_font(s);
- if (!f->load()) {
- delete f;
- return 0;
- }
- return f;
-}
-
-ps_font::ps_font(const char *nm)
-: font(nm), encoding_index(-1), encoding(0), reencoded_name(0)
-{
-}
-
-ps_font::~ps_font()
-{
- a_delete encoding;
- a_delete reencoded_name;
-}
-
-void ps_font::handle_unknown_font_command(const char *command, const char *arg,
- const char *filename, int lineno)
-{
- if (strcmp(command, "encoding") == 0) {
- if (arg == 0)
- error_with_file_and_line(filename, lineno,
- "`encoding' command requires an argument");
- else
- encoding = strsave(arg);
- }
-}
-
-static void handle_unknown_desc_command(const char *command, const char *arg,
- const char *filename, int lineno)
-{
- if (strcmp(command, "broken") == 0) {
- if (arg == 0)
- error_with_file_and_line(filename, lineno,
- "`broken' command requires an argument");
- else if (!bflag)
- broken_flags = atoi(arg);
- }
-}
-
-struct style {
- font *f;
- int point_size;
- int height;
- int slant;
- style();
- style(font *, int, int, int);
- int operator==(const style &) const;
- int operator!=(const style &) const;
-};
-
-style::style() : f(0)
-{
-}
-
-style::style(font *p, int sz, int h, int sl)
-: f(p), point_size(sz), height(h), slant(sl)
-{
-}
-
-int style::operator==(const style &s) const
-{
- return (f == s.f && point_size == s.point_size
- && height == s.height && slant == s.slant);
-}
-
-int style::operator!=(const style &s) const
-{
- return !(*this == s);
-}
-
-class ps_printer : public printer {
- FILE *tempfp;
- ps_output out;
- int res;
- int space_char_index;
- int pages_output;
- int paper_length;
- int equalise_spaces;
- enum { SBUF_SIZE = 256 };
- char sbuf[SBUF_SIZE];
- int sbuf_len;
- int sbuf_start_hpos;
- int sbuf_vpos;
- int sbuf_end_hpos;
- int sbuf_space_width;
- int sbuf_space_count;
- int sbuf_space_diff_count;
- int sbuf_space_code;
- int sbuf_kern;
- style sbuf_style;
- color sbuf_color; // the current PS color
- style output_style;
- int output_hpos;
- int output_vpos;
- int output_draw_point_size;
- int line_thickness;
- int output_line_thickness;
- unsigned char output_space_code;
- enum { MAX_DEFINED_STYLES = 50 };
- style defined_styles[MAX_DEFINED_STYLES];
- int ndefined_styles;
- int next_encoding_index;
- string defs;
- int ndefs;
- resource_manager rm;
- int invis_count;
-
- void flush_sbuf();
- void set_style(const style &);
- void set_space_code(unsigned char c);
- int set_encoding_index(ps_font *);
- void do_exec(char *, const environment *);
- void do_import(char *, const environment *);
- void do_def(char *, const environment *);
- void do_mdef(char *, const environment *);
- void do_file(char *, const environment *);
- void do_invis(char *, const environment *);
- void do_endinvis(char *, const environment *);
- void set_line_thickness_and_color(const environment *);
- void fill_path(const environment *);
- void encode_fonts();
- void define_encoding(const char *, int);
- void reencode_font(ps_font *);
- void set_color(color *c, int fill = 0);
-
-public:
- ps_printer(double);
- ~ps_printer();
- void set_char(int i, font *f, const environment *env, int w, const char *name);
- void draw(int code, int *p, int np, const environment *env);
- void begin_page(int);
- void end_page(int);
- void special(char *arg, const environment *env, char type);
- font *make_font(const char *);
- void end_of_line();
-};
-
-// `pl' is in inches
-ps_printer::ps_printer(double pl)
-: out(0, MAX_LINE_LENGTH),
- pages_output(0),
- sbuf_len(0),
- output_hpos(-1),
- output_vpos(-1),
- line_thickness(-1),
- ndefined_styles(0),
- next_encoding_index(0),
- ndefs(0),
- invis_count(0)
-{
- tempfp = xtmpfile();
- out.set_file(tempfp);
- if (linewidth < 0)
- linewidth = DEFAULT_LINEWIDTH;
- if (font::hor != 1)
- fatal("horizontal resolution must be 1");
- if (font::vert != 1)
- fatal("vertical resolution must be 1");
- if (font::res % (font::sizescale*72) != 0)
- fatal("res must be a multiple of 72*sizescale");
- int r = font::res;
- int point = 0;
- while (r % 10 == 0) {
- r /= 10;
- point++;
- }
- res = r;
- out.set_fixed_point(point);
- space_char_index = font::name_to_index("space");
- if (pl == 0)
- paper_length = font::paperlength;
- else
- paper_length = int(pl * font::res + 0.5);
- if (paper_length == 0)
- paper_length = 11 * font::res;
- equalise_spaces = font::res >= 72000;
-}
-
-int ps_printer::set_encoding_index(ps_font *f)
-{
- if (f->encoding_index >= 0)
- return f->encoding_index;
- for (font_pointer_list *p = font_list; p; p = p->next)
- if (p->p != f) {
- char *encoding = ((ps_font *)p->p)->encoding;
- int encoding_index = ((ps_font *)p->p)->encoding_index;
- if (encoding != 0 && encoding_index >= 0
- && strcmp(f->encoding, encoding) == 0) {
- return f->encoding_index = encoding_index;
- }
- }
- return f->encoding_index = next_encoding_index++;
-}
-
-void ps_printer::set_char(int i, font *f, const environment *env, int w, const char *name)
-{
- if (i == space_char_index || invis_count > 0)
- return;
- unsigned char code = f->get_code(i);
- style sty(f, env->size, env->height, env->slant);
- if (sty.slant != 0) {
- if (sty.slant > 80 || sty.slant < -80) {
- error("silly slant `%1' degrees", sty.slant);
- sty.slant = 0;
- }
- }
- if (sbuf_len > 0) {
- if (sbuf_len < SBUF_SIZE
- && sty == sbuf_style
- && sbuf_vpos == env->vpos
- && sbuf_color == *env->col) {
- if (sbuf_end_hpos == env->hpos) {
- sbuf[sbuf_len++] = code;
- sbuf_end_hpos += w + sbuf_kern;
- return;
- }
- if (sbuf_len == 1 && sbuf_kern == 0) {
- sbuf_kern = env->hpos - sbuf_end_hpos;
- sbuf_end_hpos = env->hpos + sbuf_kern + w;
- sbuf[sbuf_len++] = code;
- return;
- }
- /* If sbuf_end_hpos - sbuf_kern == env->hpos, we are better off
- starting a new string. */
- if (sbuf_len < SBUF_SIZE - 1 && env->hpos >= sbuf_end_hpos
- && (sbuf_kern == 0 || sbuf_end_hpos - sbuf_kern != env->hpos)) {
- if (sbuf_space_code < 0) {
- if (f->contains(space_char_index)) {
- sbuf_space_code = f->get_code(space_char_index);
- sbuf_space_width = env->hpos - sbuf_end_hpos;
- sbuf_end_hpos = env->hpos + w + sbuf_kern;
- sbuf[sbuf_len++] = sbuf_space_code;
- sbuf[sbuf_len++] = code;
- sbuf_space_count++;
- return;
- }
- }
- else {
- int diff = env->hpos - sbuf_end_hpos - sbuf_space_width;
- if (diff == 0 || (equalise_spaces && (diff == 1 || diff == -1))) {
- sbuf_end_hpos = env->hpos + w + sbuf_kern;
- sbuf[sbuf_len++] = sbuf_space_code;
- sbuf[sbuf_len++] = code;
- sbuf_space_count++;
- if (diff == 1)
- sbuf_space_diff_count++;
- else if (diff == -1)
- sbuf_space_diff_count--;
- return;
- }
- }
- }
- }
- flush_sbuf();
- }
- sbuf_len = 1;
- sbuf[0] = code;
- sbuf_end_hpos = env->hpos + w;
- sbuf_start_hpos = env->hpos;
- sbuf_vpos = env->vpos;
- sbuf_style = sty;
- sbuf_space_code = -1;
- sbuf_space_width = 0;
- sbuf_space_count = sbuf_space_diff_count = 0;
- sbuf_kern = 0;
- if (sbuf_color != *env->col)
- set_color(env->col);
-}
-
-static char *make_encoding_name(int encoding_index)
-{
- static char buf[3 + INT_DIGITS + 1];
- sprintf(buf, "ENC%d", encoding_index);
- return buf;
-}
-
-const char *const WS = " \t\n\r";
-
-void ps_printer::define_encoding(const char *encoding, int encoding_index)
-{
- char *vec[256];
- int i;
- for (i = 0; i < 256; i++)
- vec[i] = 0;
- char *path;
- FILE *fp = font::open_file(encoding, &path);
- if (fp == 0)
- fatal("can't open encoding file `%1'", encoding);
- int lineno = 1;
- char buf[256];
- while (fgets(buf, 512, fp) != 0) {
- char *p = buf;
- while (csspace(*p))
- p++;
- if (*p != '#' && *p != '\0' && (p = strtok(buf, WS)) != 0) {
- char *q = strtok(0, WS);
- int n;
- if (q == 0 || sscanf(q, "%d", &n) != 1 || n < 0 || n >= 256)
- fatal_with_file_and_line(path, lineno, "bad second field");
- vec[n] = new char[strlen(p) + 1];
- strcpy(vec[n], p);
- }
- lineno++;
- }
- a_delete path;
- out.put_literal_symbol(make_encoding_name(encoding_index));
- out.put_delimiter('[');
- for (i = 0; i < 256; i++) {
- if (vec[i] == 0)
- out.put_literal_symbol(".notdef");
- else {
- out.put_literal_symbol(vec[i]);
- a_delete vec[i];
- }
- }
- out.put_delimiter(']')
- .put_symbol("def");
-}
-
-void ps_printer::reencode_font(ps_font *f)
-{
- out.put_literal_symbol(f->reencoded_name)
- .put_symbol(make_encoding_name(f->encoding_index))
- .put_literal_symbol(f->get_internal_name())
- .put_symbol("RE");
-}
-
-void ps_printer::encode_fonts()
-{
- if (next_encoding_index == 0)
- return;
- char *done_encoding = new char[next_encoding_index];
- for (int i = 0; i < next_encoding_index; i++)
- done_encoding[i] = 0;
- for (font_pointer_list *f = font_list; f; f = f->next) {
- int encoding_index = ((ps_font *)f->p)->encoding_index;
- if (encoding_index >= 0) {
- assert(encoding_index < next_encoding_index);
- if (!done_encoding[encoding_index]) {
- done_encoding[encoding_index] = 1;
- define_encoding(((ps_font *)f->p)->encoding, encoding_index);
- }
- reencode_font((ps_font *)f->p);
- }
- }
- a_delete done_encoding;
-}
-
-void ps_printer::set_style(const style &sty)
-{
- char buf[1 + INT_DIGITS + 1];
- for (int i = 0; i < ndefined_styles; i++)
- if (sty == defined_styles[i]) {
- sprintf(buf, "F%d", i);
- out.put_symbol(buf);
- return;
- }
- if (ndefined_styles >= MAX_DEFINED_STYLES)
- ndefined_styles = 0;
- sprintf(buf, "F%d", ndefined_styles);
- out.put_literal_symbol(buf);
- const char *psname = sty.f->get_internal_name();
- if (psname == 0)
- fatal("no internalname specified for font `%1'", sty.f->get_name());
- char *encoding = ((ps_font *)sty.f)->encoding;
- if (encoding != 0) {
- char *s = ((ps_font *)sty.f)->reencoded_name;
- if (s == 0) {
- int ei = set_encoding_index((ps_font *)sty.f);
- char *tem = new char[strlen(psname) + 1 + INT_DIGITS + 1];
- sprintf(tem, "%s@%d", psname, ei);
- psname = tem;
- ((ps_font *)sty.f)->reencoded_name = tem;
- }
- else
- psname = s;
- }
- out.put_fix_number((font::res/(72*font::sizescale))*sty.point_size);
- if (sty.height != 0 || sty.slant != 0) {
- int h = sty.height == 0 ? sty.point_size : sty.height;
- h *= font::res/(72*font::sizescale);
- int c = int(h*tan(radians(sty.slant)) + .5);
- out.put_fix_number(c)
- .put_fix_number(h)
- .put_literal_symbol(psname)
- .put_symbol("MF");
- }
- else {
- out.put_literal_symbol(psname)
- .put_symbol("SF");
- }
- defined_styles[ndefined_styles++] = sty;
-}
-
-void ps_printer::set_color(color *col, int fill)
-{
- sbuf_color = *col;
- unsigned int components[4];
- char s[3];
- color_scheme cs = col->get_components(components);
- s[0] = fill ? 'F' : 'C';
- s[2] = 0;
- switch (cs) {
- case DEFAULT: // black
- out.put_symbol("0");
- s[1] = 'g';
- break;
- case RGB:
- out.put_color(Red)
- .put_color(Green)
- .put_color(Blue);
- s[1] = 'r';
- break;
- case CMY:
- col->get_cmyk(&Cyan, &Magenta, &Yellow, &Black);
- // fall through
- case CMYK:
- out.put_color(Cyan)
- .put_color(Magenta)
- .put_color(Yellow)
- .put_color(Black);
- s[1] = 'k';
- break;
- case GRAY:
- out.put_color(Gray);
- s[1] = 'g';
- break;
- }
- out.put_symbol(s);
-}
-
-void ps_printer::set_space_code(unsigned char c)
-{
- out.put_literal_symbol("SC")
- .put_number(c)
- .put_symbol("def");
-}
-
-void ps_printer::end_of_line()
-{
- flush_sbuf();
- // this ensures that we do an absolute motion to the beginning of a line
- output_vpos = output_hpos = -1;
-}
-
-void ps_printer::flush_sbuf()
-{
- enum {
- NONE,
- RELATIVE_H,
- RELATIVE_V,
- RELATIVE_HV,
- ABSOLUTE
- } motion = NONE;
- int space_flag = 0;
- if (sbuf_len == 0)
- return;
- if (output_style != sbuf_style) {
- set_style(sbuf_style);
- output_style = sbuf_style;
- }
- int extra_space = 0;
- if (output_hpos < 0 || output_vpos < 0)
- motion = ABSOLUTE;
- else {
- if (output_hpos != sbuf_start_hpos)
- motion = RELATIVE_H;
- if (output_vpos != sbuf_vpos) {
- if (motion != NONE)
- motion = RELATIVE_HV;
- else
- motion = RELATIVE_V;
- }
- }
- if (sbuf_space_code >= 0) {
- int w = sbuf_style.f->get_width(space_char_index, sbuf_style.point_size);
- if (w + sbuf_kern != sbuf_space_width) {
- if (sbuf_space_code != output_space_code) {
- set_space_code(sbuf_space_code);
- output_space_code = sbuf_space_code;
- }
- space_flag = 1;
- extra_space = sbuf_space_width - w - sbuf_kern;
- if (sbuf_space_diff_count > sbuf_space_count/2)
- extra_space++;
- else if (sbuf_space_diff_count < -(sbuf_space_count/2))
- extra_space--;
- }
- }
- if (space_flag)
- out.put_fix_number(extra_space);
- if (sbuf_kern != 0)
- out.put_fix_number(sbuf_kern);
- out.put_string(sbuf, sbuf_len);
- char command_array[] = {'A', 'B', 'C', 'D',
- 'E', 'F', 'G', 'H',
- 'I', 'J', 'K', 'L',
- 'M', 'N', 'O', 'P',
- 'Q', 'R', 'S', 'T'};
- char sym[2];
- sym[0] = command_array[motion*4 + space_flag + 2*(sbuf_kern != 0)];
- sym[1] = '\0';
- switch (motion) {
- case NONE:
- break;
- case ABSOLUTE:
- out.put_fix_number(sbuf_start_hpos)
- .put_fix_number(sbuf_vpos);
- break;
- case RELATIVE_H:
- out.put_fix_number(sbuf_start_hpos - output_hpos);
- break;
- case RELATIVE_V:
- out.put_fix_number(sbuf_vpos - output_vpos);
- break;
- case RELATIVE_HV:
- out.put_fix_number(sbuf_start_hpos - output_hpos)
- .put_fix_number(sbuf_vpos - output_vpos);
- break;
- default:
- assert(0);
- }
- out.put_symbol(sym);
- output_hpos = sbuf_end_hpos;
- output_vpos = sbuf_vpos;
- sbuf_len = 0;
-}
-
-void ps_printer::set_line_thickness_and_color(const environment *env)
-{
- if (line_thickness < 0) {
- if (output_draw_point_size != env->size) {
- // we ought to check for overflow here
- int lw = ((font::res/(72*font::sizescale))*linewidth*env->size)/1000;
- out.put_fix_number(lw)
- .put_symbol("LW");
- output_draw_point_size = env->size;
- output_line_thickness = -1;
- }
- }
- else {
- if (output_line_thickness != line_thickness) {
- out.put_fix_number(line_thickness)
- .put_symbol("LW");
- output_line_thickness = line_thickness;
- output_draw_point_size = -1;
- }
- }
- if (sbuf_color != *env->col)
- set_color(env->col);
-}
-
-void ps_printer::fill_path(const environment *env)
-{
- if (sbuf_color == *env->fill)
- out.put_symbol("FL");
- else
- set_color(env->fill, 1);
-}
-
-void ps_printer::draw(int code, int *p, int np, const environment *env)
-{
- if (invis_count > 0)
- return;
- flush_sbuf();
- int fill_flag = 0;
- switch (code) {
- case 'C':
- fill_flag = 1;
- // fall through
- case 'c':
- // troff adds an extra argument to C
- if (np != 1 && !(code == 'C' && np == 2)) {
- error("1 argument required for circle");
- break;
- }
- out.put_fix_number(env->hpos + p[0]/2)
- .put_fix_number(env->vpos)
- .put_fix_number(p[0]/2)
- .put_symbol("DC");
- if (fill_flag)
- fill_path(env);
- else {
- set_line_thickness_and_color(env);
- out.put_symbol("ST");
- }
- break;
- case 'l':
- if (np != 2) {
- error("2 arguments required for line");
- break;
- }
- set_line_thickness_and_color(env);
- out.put_fix_number(p[0] + env->hpos)
- .put_fix_number(p[1] + env->vpos)
- .put_fix_number(env->hpos)
- .put_fix_number(env->vpos)
- .put_symbol("DL");
- break;
- case 'E':
- fill_flag = 1;
- // fall through
- case 'e':
- if (np != 2) {
- error("2 arguments required for ellipse");
- break;
- }
- out.put_fix_number(p[0])
- .put_fix_number(p[1])
- .put_fix_number(env->hpos + p[0]/2)
- .put_fix_number(env->vpos)
- .put_symbol("DE");
- if (fill_flag)
- fill_path(env);
- else {
- set_line_thickness_and_color(env);
- out.put_symbol("ST");
- }
- break;
- case 'P':
- fill_flag = 1;
- // fall through
- case 'p':
- {
- if (np & 1) {
- error("even number of arguments required for polygon");
- break;
- }
- if (np == 0) {
- error("no arguments for polygon");
- break;
- }
- out.put_fix_number(env->hpos)
- .put_fix_number(env->vpos)
- .put_symbol("MT");
- for (int i = 0; i < np; i += 2)
- out.put_fix_number(p[i])
- .put_fix_number(p[i+1])
- .put_symbol("RL");
- out.put_symbol("CL");
- if (fill_flag)
- fill_path(env);
- else {
- set_line_thickness_and_color(env);
- out.put_symbol("ST");
- }
- break;
- }
- case '~':
- {
- if (np & 1) {
- error("even number of arguments required for spline");
- break;
- }
- if (np == 0) {
- error("no arguments for spline");
- break;
- }
- out.put_fix_number(env->hpos)
- .put_fix_number(env->vpos)
- .put_symbol("MT");
- out.put_fix_number(p[0]/2)
- .put_fix_number(p[1]/2)
- .put_symbol("RL");
- /* tnum/tden should be between 0 and 1; the closer it is to 1
- the tighter the curve will be to the guiding lines; 2/3
- is the standard value */
- const int tnum = 2;
- const int tden = 3;
- for (int i = 0; i < np - 2; i += 2) {
- out.put_fix_number((p[i]*tnum)/(2*tden))
- .put_fix_number((p[i + 1]*tnum)/(2*tden))
- .put_fix_number(p[i]/2 + (p[i + 2]*(tden - tnum))/(2*tden))
- .put_fix_number(p[i + 1]/2 + (p[i + 3]*(tden - tnum))/(2*tden))
- .put_fix_number((p[i] - p[i]/2) + p[i + 2]/2)
- .put_fix_number((p[i + 1] - p[i + 1]/2) + p[i + 3]/2)
- .put_symbol("RC");
- }
- out.put_fix_number(p[np - 2] - p[np - 2]/2)
- .put_fix_number(p[np - 1] - p[np - 1]/2)
- .put_symbol("RL");
- set_line_thickness_and_color(env);
- out.put_symbol("ST");
- }
- break;
- case 'a':
- {
- if (np != 4) {
- error("4 arguments required for arc");
- break;
- }
- set_line_thickness_and_color(env);
- double c[2];
- if (adjust_arc_center(p, c))
- out.put_fix_number(env->hpos + int(c[0]))
- .put_fix_number(env->vpos + int(c[1]))
- .put_fix_number(int(sqrt(c[0]*c[0] + c[1]*c[1])))
- .put_float(degrees(atan2(-c[1], -c[0])))
- .put_float(degrees(atan2(p[1] + p[3] - c[1], p[0] + p[2] - c[0])))
- .put_symbol("DA");
- else
- out.put_fix_number(p[0] + p[2] + env->hpos)
- .put_fix_number(p[1] + p[3] + env->vpos)
- .put_fix_number(env->hpos)
- .put_fix_number(env->vpos)
- .put_symbol("DL");
- }
- break;
- case 't':
- if (np == 0)
- line_thickness = -1;
- else {
- // troff gratuitously adds an extra 0
- if (np != 1 && np != 2) {
- error("0 or 1 argument required for thickness");
- break;
- }
- line_thickness = p[0];
- }
- break;
- default:
- error("unrecognised drawing command `%1'", char(code));
- break;
- }
- output_hpos = output_vpos = -1;
-}
-
-void ps_printer::begin_page(int n)
-{
- out.begin_comment("Page:")
- .comment_arg(i_to_a(n));
- out.comment_arg(i_to_a(++pages_output))
- .end_comment();
- output_style.f = 0;
- output_space_code = 32;
- output_draw_point_size = -1;
- output_line_thickness = -1;
- output_hpos = output_vpos = -1;
- ndefined_styles = 0;
- out.simple_comment("BeginPageSetup")
- .put_symbol("BP")
- .simple_comment("EndPageSetup");
- if (sbuf_color != default_color)
- set_color(&sbuf_color);
-}
-
-void ps_printer::end_page(int)
-{
- flush_sbuf();
- set_color(&default_color);
- out.put_symbol("EP");
- if (invis_count != 0) {
- error("missing `endinvis' command");
- invis_count = 0;
- }
-}
-
-font *ps_printer::make_font(const char *nm)
-{
- return ps_font::load_ps_font(nm);
-}
-
-ps_printer::~ps_printer()
-{
- out.simple_comment("Trailer")
- .put_symbol("end")
- .simple_comment("EOF");
- if (fseek(tempfp, 0L, 0) < 0)
- fatal("fseek on temporary file failed");
- fputs("%!PS-Adobe-", stdout);
- fputs((broken_flags & USE_PS_ADOBE_2_0) ? "2.0" : "3.0", stdout);
- putchar('\n');
- out.set_file(stdout);
- {
- out.begin_comment("Creator:")
- .comment_arg("groff")
- .comment_arg("version")
- .comment_arg(Version_string)
- .end_comment();
- }
- {
- fputs("%%CreationDate: ", out.get_file());
-#ifdef LONG_FOR_TIME_T
- long
-#else
- time_t
-#endif
- t = time(0);
- fputs(ctime(&t), out.get_file());
- }
- for (font_pointer_list *f = font_list; f; f = f->next) {
- ps_font *psf = (ps_font *)(f->p);
- rm.need_font(psf->get_internal_name());
- }
- rm.print_header_comments(out);
- out.begin_comment("Pages:")
- .comment_arg(i_to_a(pages_output))
- .end_comment();
- out.begin_comment("PageOrder:")
- .comment_arg("Ascend")
- .end_comment();
-#if 0
- fprintf(out.get_file(), "%%%%DocumentMedia: () %g %g 0 () ()\n",
- font::paperwidth*72.0/font::res,
- paper_length*72.0/font::res);
-#endif
- out.begin_comment("Orientation:")
- .comment_arg(landscape_flag ? "Landscape" : "Portrait")
- .end_comment();
- if (ncopies != 1) {
- out.end_line();
- fprintf(out.get_file(), "%%%%Requirements: numcopies(%d)\n", ncopies);
- }
- out.simple_comment("EndComments");
- out.simple_comment("BeginProlog");
- rm.output_prolog(out);
- if (!(broken_flags & NO_SETUP_SECTION)) {
- out.simple_comment("EndProlog");
- out.simple_comment("BeginSetup");
- }
- rm.document_setup(out);
- out.put_symbol(dict_name)
- .put_symbol("begin");
- if (ndefs > 0)
- ndefs += DEFS_DICT_SPARE;
- out.put_literal_symbol(defs_dict_name)
- .put_number(ndefs + 1)
- .put_symbol("dict")
- .put_symbol("def");
- out.put_symbol(defs_dict_name)
- .put_symbol("begin");
- out.put_literal_symbol("u")
- .put_delimiter('{')
- .put_fix_number(1)
- .put_symbol("mul")
- .put_delimiter('}')
- .put_symbol("bind")
- .put_symbol("def");
- defs += '\0';
- out.special(defs.contents());
- out.put_symbol("end");
- if (ncopies != 1)
- out.put_literal_symbol("#copies")
- .put_number(ncopies)
- .put_symbol("def");
- out.put_literal_symbol("RES")
- .put_number(res)
- .put_symbol("def");
- out.put_literal_symbol("PL");
- if (guess_flag)
- out.put_symbol("PLG");
- else
- out.put_fix_number(paper_length);
- out.put_symbol("def");
- out.put_literal_symbol("LS")
- .put_symbol(landscape_flag ? "true" : "false")
- .put_symbol("def");
- if (manual_feed_flag) {
- out.begin_comment("BeginFeature:")
- .comment_arg("*ManualFeed")
- .comment_arg("True")
- .end_comment()
- .put_symbol("MANUAL")
- .simple_comment("EndFeature");
- }
- encode_fonts();
- out.simple_comment((broken_flags & NO_SETUP_SECTION)
- ? "EndProlog"
- : "EndSetup");
- out.end_line();
- out.copy_file(tempfp);
- fclose(tempfp);
-}
-
-void ps_printer::special(char *arg, const environment *env, char type)
-{
- if (type != 'p')
- return;
- typedef void (ps_printer::*SPECIAL_PROCP)(char *, const environment *);
- static struct {
- const char *name;
- SPECIAL_PROCP proc;
- } proc_table[] = {
- { "exec", &ps_printer::do_exec },
- { "def", &ps_printer::do_def },
- { "mdef", &ps_printer::do_mdef },
- { "import", &ps_printer::do_import },
- { "file", &ps_printer::do_file },
- { "invis", &ps_printer::do_invis },
- { "endinvis", &ps_printer::do_endinvis },
- };
- char *p;
- for (p = arg; *p == ' ' || *p == '\n'; p++)
- ;
- char *tag = p;
- for (; *p != '\0' && *p != ':' && *p != ' ' && *p != '\n'; p++)
- ;
- if (*p == '\0' || strncmp(tag, "ps", p - tag) != 0) {
- error("X command without `ps:' tag ignored");
- return;
- }
- p++;
- for (; *p == ' ' || *p == '\n'; p++)
- ;
- char *command = p;
- for (; *p != '\0' && *p != ' ' && *p != '\n'; p++)
- ;
- if (*command == '\0') {
- error("empty X command ignored");
- return;
- }
- for (unsigned int i = 0; i < sizeof(proc_table)/sizeof(proc_table[0]); i++)
- if (strncmp(command, proc_table[i].name, p - command) == 0) {
- (this->*(proc_table[i].proc))(p, env);
- return;
- }
- error("X command `%1' not recognised", command);
-}
-
-// A conforming PostScript document must not have lines longer
-// than 255 characters (excluding line termination characters).
-
-static int check_line_lengths(const char *p)
-{
- for (;;) {
- const char *end = strchr(p, '\n');
- if (end == 0)
- end = strchr(p, '\0');
- if (end - p > 255)
- return 0;
- if (*end == '\0')
- break;
- p = end + 1;
- }
- return 1;
-}
-
-void ps_printer::do_exec(char *arg, const environment *env)
-{
- flush_sbuf();
- while (csspace(*arg))
- arg++;
- if (*arg == '\0') {
- error("missing argument to X exec command");
- return;
- }
- if (!check_line_lengths(arg)) {
- error("lines in X exec command must not be more than 255 characters long");
- return;
- }
- out.put_fix_number(env->hpos)
- .put_fix_number(env->vpos)
- .put_symbol("EBEGIN")
- .special(arg)
- .put_symbol("EEND");
- output_hpos = output_vpos = -1;
- output_style.f = 0;
- output_draw_point_size = -1;
- output_line_thickness = -1;
- ndefined_styles = 0;
- if (!ndefs)
- ndefs = 1;
-}
-
-void ps_printer::do_file(char *arg, const environment *env)
-{
- flush_sbuf();
- while (csspace(*arg))
- arg++;
- if (*arg == '\0') {
- error("missing argument to X file command");
- return;
- }
- const char *filename = arg;
- do {
- ++arg;
- } while (*arg != '\0' && *arg != ' ' && *arg != '\n');
- out.put_fix_number(env->hpos)
- .put_fix_number(env->vpos)
- .put_symbol("EBEGIN");
- rm.import_file(filename, out);
- out.put_symbol("EEND");
- output_hpos = output_vpos = -1;
- output_style.f = 0;
- output_draw_point_size = -1;
- output_line_thickness = -1;
- ndefined_styles = 0;
- if (!ndefs)
- ndefs = 1;
-}
-
-void ps_printer::do_def(char *arg, const environment *)
-{
- flush_sbuf();
- while (csspace(*arg))
- arg++;
- if (!check_line_lengths(arg)) {
- error("lines in X def command must not be more than 255 characters long");
- return;
- }
- defs += arg;
- if (*arg != '\0' && strchr(arg, '\0')[-1] != '\n')
- defs += '\n';
- ndefs++;
-}
-
-// Like def, but the first argument says how many definitions it contains.
-
-void ps_printer::do_mdef(char *arg, const environment *)
-{
- flush_sbuf();
- char *p;
- int n = (int)strtol(arg, &p, 10);
- if (n == 0 && p == arg) {
- error("first argument to X mdef must be an integer");
- return;
- }
- if (n < 0) {
- error("out of range argument `%1' to X mdef command", int(n));
- return;
- }
- arg = p;
- while (csspace(*arg))
- arg++;
- if (!check_line_lengths(arg)) {
- error("lines in X mdef command must not be more than 255 characters long");
- return;
- }
- defs += arg;
- if (*arg != '\0' && strchr(arg, '\0')[-1] != '\n')
- defs += '\n';
- ndefs += n;
-}
-
-void ps_printer::do_import(char *arg, const environment *env)
-{
- flush_sbuf();
- while (*arg == ' ' || *arg == '\n')
- arg++;
- char *p;
- for (p = arg; *p != '\0' && *p != ' ' && *p != '\n'; p++)
- ;
- if (*p != '\0')
- *p++ = '\0';
- int parms[6];
- int nparms = 0;
- while (nparms < 6) {
- char *end;
- long n = strtol(p, &end, 10);
- if (n == 0 && end == p)
- break;
- parms[nparms++] = int(n);
- p = end;
- }
- if (csalpha(*p) && (p[1] == '\0' || p[1] == ' ' || p[1] == '\n')) {
- error("scaling indicators not allowed in arguments for X import command");
- return;
- }
- while (*p == ' ' || *p == '\n')
- p++;
- if (nparms < 5) {
- if (*p == '\0')
- error("too few arguments for X import command");
- else
- error("invalid argument `%1' for X import command", p);
- return;
- }
- if (*p != '\0') {
- error("superflous argument `%1' for X import command", p);
- return;
- }
- int llx = parms[0];
- int lly = parms[1];
- int urx = parms[2];
- int ury = parms[3];
- int desired_width = parms[4];
- int desired_height = parms[5];
- if (desired_width <= 0) {
- error("bad width argument `%1' for X import command: must be > 0",
- desired_width);
- return;
- }
- if (nparms == 6 && desired_height <= 0) {
- error("bad height argument `%1' for X import command: must be > 0",
- desired_height);
- return;
- }
- if (llx == urx) {
- error("llx and urx arguments for X import command must not be equal");
- return;
- }
- if (lly == ury) {
- error("lly and ury arguments for X import command must not be equal");
- return;
- }
- if (nparms == 5) {
- int old_wid = urx - llx;
- int old_ht = ury - lly;
- if (old_wid < 0)
- old_wid = -old_wid;
- if (old_ht < 0)
- old_ht = -old_ht;
- desired_height = int(desired_width*(double(old_ht)/double(old_wid)) + .5);
- }
- if (env->vpos - desired_height < 0)
- warning("top of imported graphic is above the top of the page");
- out.put_number(llx)
- .put_number(lly)
- .put_fix_number(desired_width)
- .put_number(urx - llx)
- .put_fix_number(-desired_height)
- .put_number(ury - lly)
- .put_fix_number(env->hpos)
- .put_fix_number(env->vpos)
- .put_symbol("PBEGIN");
- rm.import_file(arg, out);
- // do this here just in case application defines PEND
- out.put_symbol("end");
- out.put_symbol("PEND");
-}
-
-void ps_printer::do_invis(char *, const environment *)
-{
- invis_count++;
-}
-
-void ps_printer::do_endinvis(char *, const environment *)
-{
- if (invis_count == 0)
- error("unbalanced `endinvis' command");
- else
- --invis_count;
-}
-
-printer *make_printer()
-{
- return new ps_printer(user_paper_length);
-}
-
-static void usage(FILE *stream);
-
-int main(int argc, char **argv)
-{
- program_name = argv[0];
- string env;
- static char stderr_buf[BUFSIZ];
- setbuf(stderr, stderr_buf);
- int c;
- 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, "b:c:F:glmp:P:vw:", long_options, NULL))
- != EOF)
- switch(c) {
- case 'b':
- // XXX check this
- broken_flags = atoi(optarg);
- bflag = 1;
- break;
- case 'c':
- if (sscanf(optarg, "%d", &ncopies) != 1 || ncopies <= 0) {
- error("bad number of copies `%s'", optarg);
- ncopies = 1;
- }
- break;
- case 'F':
- font::command_line_font_dir(optarg);
- break;
- case 'g':
- guess_flag = 1;
- break;
- case 'l':
- landscape_flag = 1;
- break;
- case 'm':
- manual_feed_flag = 1;
- break;
- case 'p':
- if (!font::scan_papersize(optarg, 0, &user_paper_length, 0))
- error("invalid custom paper size `%1' ignored", optarg);
- break;
- case 'P':
- env = "GROPS_PROLOGUE";
- env += '=';
- env += optarg;
- env += '\0';
- if (putenv(strsave(env.contents())))
- fatal("putenv failed");
- break;
- case 'v':
- printf("GNU grops (groff) version %s\n", Version_string);
- exit(0);
- break;
- case 'w':
- if (sscanf(optarg, "%d", &linewidth) != 1 || linewidth < 0) {
- error("bad linewidth `%1'", optarg);
- linewidth = -1;
- }
- break;
- case CHAR_MAX + 1: // --help
- usage(stdout);
- exit(0);
- break;
- case '?':
- usage(stderr);
- exit(1);
- break;
- default:
- assert(0);
- }
- font::set_unknown_desc_command_handler(handle_unknown_desc_command);
-#ifdef SET_BINARY
- SET_BINARY(fileno(stdout));
-#endif
- if (optind >= argc)
- do_file("-");
- else {
- for (int i = optind; i < argc; i++)
- do_file(argv[i]);
- }
- delete pr;
- return 0;
-}
-
-static void usage(FILE *stream)
-{
- fprintf(stream,
- "usage: %s [-glmv] [-b n] [-c n] [-w n] [-P prologue] [-F dir] [files ...]\n",
- program_name);
-}
diff --git a/contrib/groff/src/devices/grops/psrm.cc b/contrib/groff/src/devices/grops/psrm.cc
deleted file mode 100644
index f2177da..0000000
--- a/contrib/groff/src/devices/grops/psrm.cc
+++ /dev/null
@@ -1,1147 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "driver.h"
-#include "stringclass.h"
-#include "cset.h"
-
-#include "ps.h"
-
-#ifdef NEED_DECLARATION_PUTENV
-extern "C" {
- int putenv(const char *);
-}
-#endif /* NEED_DECLARATION_PUTENV */
-
-#define GROPS_PROLOGUE "prologue"
-
-static void print_ps_string(const string &s, FILE *outfp);
-
-cset white_space("\n\r \t");
-string an_empty_string;
-
-const char *extension_table[] = {
- "DPS",
- "CMYK",
- "Composite",
- "FileSystem",
-};
-
-const int NEXTENSIONS = sizeof(extension_table)/sizeof(extension_table[0]);
-
-const char *resource_table[] = {
- "font",
- "procset",
- "file",
- "encoding",
- "form",
- "pattern",
-};
-
-const int NRESOURCES = sizeof(resource_table)/sizeof(resource_table[0]);
-
-static int read_uint_arg(const char **pp, unsigned *res)
-{
- while (white_space(**pp))
- *pp += 1;
- if (**pp == '\0') {
- error("missing argument");
- return 0;
- }
- const char *start = *pp;
- // XXX use strtoul
- long n = strtol(start, (char **)pp, 10);
- if (n == 0 && *pp == start) {
- error("not an integer");
- return 0;
- }
- if (n < 0) {
- error("argument must not be negative");
- return 0;
- }
- *res = unsigned(n);
- return 1;
-}
-
-struct resource {
- resource *next;
- resource_type type;
- string name;
- enum { NEEDED = 01, SUPPLIED = 02, FONT_NEEDED = 04, BUSY = 010 };
- unsigned flags;
- string version;
- unsigned revision;
- char *filename;
- int rank;
- resource(resource_type, string &, string & = an_empty_string, unsigned = 0);
- ~resource();
- void print_type_and_name(FILE *outfp);
-};
-
-resource::resource(resource_type t, string &n, string &v, unsigned r)
-: next(0), type(t), flags(0), revision(r), filename(0), rank(-1)
-{
- name.move(n);
- version.move(v);
- if (type == RESOURCE_FILE) {
- if (name.search('\0') >= 0)
- error("filename contains a character with code 0");
- filename = name.extract();
- }
-}
-
-resource::~resource()
-{
- a_delete filename;
-}
-
-void resource::print_type_and_name(FILE *outfp)
-{
- fputs(resource_table[type], outfp);
- putc(' ', outfp);
- print_ps_string(name, outfp);
- if (type == RESOURCE_PROCSET) {
- putc(' ', outfp);
- print_ps_string(version, outfp);
- fprintf(outfp, " %u", revision);
- }
-}
-
-resource_manager::resource_manager()
-: extensions(0), language_level(0), resource_list(0)
-{
- read_download_file();
- string procset_name("grops");
- extern const char *version_string;
- extern const char *revision_string;
- unsigned revision_uint;
- if ( !read_uint_arg( &revision_string, &revision_uint) )
- revision_uint = 0;
- string procset_version(version_string);
- procset_resource = lookup_resource(RESOURCE_PROCSET, procset_name,
- procset_version, revision_uint);
- procset_resource->flags |= resource::SUPPLIED;
-}
-
-resource_manager::~resource_manager()
-{
- while (resource_list) {
- resource *tem = resource_list;
- resource_list = resource_list->next;
- delete tem;
- }
-}
-
-resource *resource_manager::lookup_resource(resource_type type,
- string &name,
- string &version,
- unsigned revision)
-{
- resource *r;
- for (r = resource_list; r; r = r->next)
- if (r->type == type
- && r->name == name
- && r->version == version
- && r->revision == revision)
- return r;
- r = new resource(type, name, version, revision);
- r->next = resource_list;
- resource_list = r;
- return r;
-}
-
-// Just a specialized version of lookup_resource().
-
-resource *resource_manager::lookup_font(const char *name)
-{
- resource *r;
- for (r = resource_list; r; r = r->next)
- if (r->type == RESOURCE_FONT
- && strlen(name) == (size_t)r->name.length()
- && memcmp(name, r->name.contents(), r->name.length()) == 0)
- return r;
- string s(name);
- r = new resource(RESOURCE_FONT, s);
- r->next = resource_list;
- resource_list = r;
- return r;
-}
-
-void resource_manager::need_font(const char *name)
-{
- lookup_font(name)->flags |= resource::FONT_NEEDED;
-}
-
-typedef resource *Presource; // Work around g++ bug.
-
-void resource_manager::document_setup(ps_output &out)
-{
- int nranks = 0;
- resource *r;
- for (r = resource_list; r; r = r->next)
- if (r->rank >= nranks)
- nranks = r->rank + 1;
- if (nranks > 0) {
- // Sort resource_list in reverse order of rank.
- Presource *head = new Presource[nranks + 1];
- Presource **tail = new Presource *[nranks + 1];
- int i;
- for (i = 0; i < nranks + 1; i++) {
- head[i] = 0;
- tail[i] = &head[i];
- }
- for (r = resource_list; r; r = r->next) {
- i = r->rank < 0 ? 0 : r->rank + 1;
- *tail[i] = r;
- tail[i] = &(*tail[i])->next;
- }
- resource_list = 0;
- for (i = 0; i < nranks + 1; i++)
- if (head[i]) {
- *tail[i] = resource_list;
- resource_list = head[i];
- }
- a_delete head;
- a_delete tail;
- // check it
- for (r = resource_list; r; r = r->next)
- if (r->next)
- assert(r->rank >= r->next->rank);
- for (r = resource_list; r; r = r->next)
- if (r->type == RESOURCE_FONT && r->rank >= 0)
- supply_resource(r, -1, out.get_file());
- }
-}
-
-void resource_manager::print_resources_comment(unsigned flag, FILE *outfp)
-{
- int continued = 0;
- for (resource *r = resource_list; r; r = r->next)
- if (r->flags & flag) {
- if (continued)
- fputs("%%+ ", outfp);
- else {
- fputs(flag == resource::NEEDED
- ? "%%DocumentNeededResources: "
- : "%%DocumentSuppliedResources: ",
- outfp);
- continued = 1;
- }
- r->print_type_and_name(outfp);
- putc('\n', outfp);
- }
-}
-
-void resource_manager::print_header_comments(ps_output &out)
-{
- for (resource *r = resource_list; r; r = r->next)
- if (r->type == RESOURCE_FONT && (r->flags & resource::FONT_NEEDED))
- supply_resource(r, 0, 0);
- print_resources_comment(resource::NEEDED, out.get_file());
- print_resources_comment(resource::SUPPLIED, out.get_file());
- print_language_level_comment(out.get_file());
- print_extensions_comment(out.get_file());
-}
-
-void resource_manager::output_prolog(ps_output &out)
-{
- FILE *outfp = out.get_file();
- out.end_line();
- char *path;
- if (!getenv("GROPS_PROLOGUE")) {
- string e = "GROPS_PROLOGUE";
- e += '=';
- e += GROPS_PROLOGUE;
- e += '\0';
- if (putenv(strsave(e.contents())))
- fatal("putenv failed");
- }
- char *prologue = getenv("GROPS_PROLOGUE");
- FILE *fp = font::open_file(prologue, &path);
- if (!fp)
- fatal("can't find `%1'", prologue);
- fputs("%%BeginResource: ", outfp);
- procset_resource->print_type_and_name(outfp);
- putc('\n', outfp);
- process_file(-1, fp, path, outfp);
- fclose(fp);
- a_delete path;
- fputs("%%EndResource\n", outfp);
-}
-
-void resource_manager::import_file(const char *filename, ps_output &out)
-{
- out.end_line();
- string name(filename);
- resource *r = lookup_resource(RESOURCE_FILE, name);
- supply_resource(r, -1, out.get_file(), 1);
-}
-
-void resource_manager::supply_resource(resource *r, int rank, FILE *outfp,
- int is_document)
-{
- if (r->flags & resource::BUSY) {
- r->name += '\0';
- fatal("loop detected in dependency graph for %1 `%2'",
- resource_table[r->type],
- r->name.contents());
- }
- r->flags |= resource::BUSY;
- if (rank > r->rank)
- r->rank = rank;
- char *path;
- FILE *fp = 0;
- if (r->filename != 0) {
- if (r->type == RESOURCE_FONT) {
- fp = font::open_file(r->filename, &path);
- if (!fp) {
- error("can't find `%1'", r->filename);
- a_delete r->filename;
- r->filename = 0;
- }
- }
- else {
- errno = 0;
- fp = fopen(r->filename, "r");
- if (!fp) {
- error("can't open `%1': %2", r->filename, strerror(errno));
- a_delete r->filename;
- r->filename = 0;
- }
- else
- path = r->filename;
- }
- }
- if (fp) {
- if (outfp) {
- if (r->type == RESOURCE_FILE && is_document) {
- fputs("%%BeginDocument: ", outfp);
- print_ps_string(r->name, outfp);
- putc('\n', outfp);
- }
- else {
- fputs("%%BeginResource: ", outfp);
- r->print_type_and_name(outfp);
- putc('\n', outfp);
- }
- }
- process_file(rank, fp, path, outfp);
- fclose(fp);
- if (r->type == RESOURCE_FONT)
- a_delete path;
- if (outfp) {
- if (r->type == RESOURCE_FILE && is_document)
- fputs("%%EndDocument\n", outfp);
- else
- fputs("%%EndResource\n", outfp);
- }
- r->flags |= resource::SUPPLIED;
- }
- else {
- if (outfp) {
- if (r->type == RESOURCE_FILE && is_document) {
- fputs("%%IncludeDocument: ", outfp);
- print_ps_string(r->name, outfp);
- putc('\n', outfp);
- }
- else {
- fputs("%%IncludeResource: ", outfp);
- r->print_type_and_name(outfp);
- putc('\n', outfp);
- }
- }
- r->flags |= resource::NEEDED;
- }
- r->flags &= ~resource::BUSY;
-}
-
-
-#define PS_LINE_MAX 255
-#define PS_MAGIC "%!PS-Adobe-"
-
-static int ps_get_line(char *buf, FILE *fp)
-{
- int c = getc(fp);
- if (c == EOF) {
- buf[0] = '\0';
- return 0;
- }
- current_lineno++;
- int i = 0;
- int err = 0;
- while (c != '\r' && c != '\n' && c != EOF) {
- if ((c < 0x1b && !white_space(c)) || c == 0x7f)
- error("invalid input character code %1", int(c));
- else if (i < PS_LINE_MAX)
- buf[i++] = c;
- else if (!err) {
- err = 1;
- error("PostScript file non-conforming "
- "because length of line exceeds 255");
- }
- c = getc(fp);
- }
- buf[i++] = '\n';
- buf[i] = '\0';
- if (c == '\r') {
- c = getc(fp);
- if (c != EOF && c != '\n')
- ungetc(c, fp);
- }
- return 1;
-}
-
-static int read_text_arg(const char **pp, string &res)
-{
- res.clear();
- while (white_space(**pp))
- *pp += 1;
- if (**pp == '\0') {
- error("missing argument");
- return 0;
- }
- if (**pp != '(') {
- for (; **pp != '\0' && !white_space(**pp); *pp += 1)
- res += **pp;
- return 1;
- }
- *pp += 1;
- res.clear();
- int level = 0;
- for (;;) {
- if (**pp == '\0' || **pp == '\r' || **pp == '\n') {
- error("missing ')'");
- return 0;
- }
- if (**pp == ')') {
- if (level == 0) {
- *pp += 1;
- break;
- }
- res += **pp;
- level--;
- }
- else if (**pp == '(') {
- level++;
- res += **pp;
- }
- else if (**pp == '\\') {
- *pp += 1;
- switch (**pp) {
- case 'n':
- res += '\n';
- break;
- case 'r':
- res += '\n';
- break;
- case 't':
- res += '\t';
- break;
- case 'b':
- res += '\b';
- break;
- case 'f':
- res += '\f';
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- {
- int val = **pp - '0';
- if ((*pp)[1] >= '0' && (*pp)[1] <= '7') {
- *pp += 1;
- val = val*8 + (**pp - '0');
- if ((*pp)[1] >= '0' && (*pp)[1] <= '7') {
- *pp += 1;
- val = val*8 + (**pp - '0');
- }
- }
- }
- break;
- default:
- res += **pp;
- break;
- }
- }
- else
- res += **pp;
- *pp += 1;
- }
- return 1;
-}
-
-resource *resource_manager::read_file_arg(const char **ptr)
-{
- string arg;
- if (!read_text_arg(ptr, arg))
- return 0;
- return lookup_resource(RESOURCE_FILE, arg);
-}
-
-resource *resource_manager::read_font_arg(const char **ptr)
-{
- string arg;
- if (!read_text_arg(ptr, arg))
- return 0;
- return lookup_resource(RESOURCE_FONT, arg);
-}
-
-resource *resource_manager::read_procset_arg(const char **ptr)
-{
- string arg;
- if (!read_text_arg(ptr, arg))
- return 0;
- string version;
- if (!read_text_arg(ptr, version))
- return 0;
- unsigned revision;
- if (!read_uint_arg(ptr, &revision))
- return 0;
- return lookup_resource(RESOURCE_PROCSET, arg, version, revision);
-}
-
-resource *resource_manager::read_resource_arg(const char **ptr)
-{
- while (white_space(**ptr))
- *ptr += 1;
- const char *name = *ptr;
- while (**ptr != '\0' && !white_space(**ptr))
- *ptr += 1;
- if (name == *ptr) {
- error("missing resource type");
- return 0;
- }
- int ri;
- for (ri = 0; ri < NRESOURCES; ri++)
- if (strlen(resource_table[ri]) == size_t(*ptr - name)
- && memcmp(resource_table[ri], name, *ptr - name) == 0)
- break;
- if (ri >= NRESOURCES) {
- error("unknown resource type");
- return 0;
- }
- if (ri == RESOURCE_PROCSET)
- return read_procset_arg(ptr);
- string arg;
- if (!read_text_arg(ptr, arg))
- return 0;
- return lookup_resource(resource_type(ri), arg);
-}
-
-static const char *matches_comment(const char *buf, const char *comment)
-{
- if (buf[0] != '%' || buf[1] != '%')
- return 0;
- for (buf += 2; *comment; comment++, buf++)
- if (*buf != *comment)
- return 0;
- if (comment[-1] == ':')
- return buf;
- if (*buf == '\0' || white_space(*buf))
- return buf;
- return 0;
-}
-
-// Return 1 if the line should be copied out.
-
-int resource_manager::do_begin_resource(const char *ptr, int, FILE *,
- FILE *)
-{
- resource *r = read_resource_arg(&ptr);
- if (r)
- r->flags |= resource::SUPPLIED;
- return 1;
-}
-
-int resource_manager::do_include_resource(const char *ptr, int rank, FILE *,
- FILE *outfp)
-{
- resource *r = read_resource_arg(&ptr);
- if (r) {
- if (r->type == RESOURCE_FONT) {
- if (rank >= 0)
- supply_resource(r, rank + 1, outfp);
- else
- r->flags |= resource::FONT_NEEDED;
- }
- else
- supply_resource(r, rank, outfp);
- }
- return 0;
-}
-
-int resource_manager::do_begin_document(const char *ptr, int, FILE *,
- FILE *)
-{
- resource *r = read_file_arg(&ptr);
- if (r)
- r->flags |= resource::SUPPLIED;
- return 1;
-}
-
-int resource_manager::do_include_document(const char *ptr, int rank, FILE *,
- FILE *outfp)
-{
- resource *r = read_file_arg(&ptr);
- if (r)
- supply_resource(r, rank, outfp, 1);
- return 0;
-}
-
-int resource_manager::do_begin_procset(const char *ptr, int, FILE *,
- FILE *outfp)
-{
- resource *r = read_procset_arg(&ptr);
- if (r) {
- r->flags |= resource::SUPPLIED;
- if (outfp) {
- fputs("%%BeginResource: ", outfp);
- r->print_type_and_name(outfp);
- putc('\n', outfp);
- }
- }
- return 0;
-}
-
-int resource_manager::do_include_procset(const char *ptr, int rank, FILE *,
- FILE *outfp)
-{
- resource *r = read_procset_arg(&ptr);
- if (r)
- supply_resource(r, rank, outfp);
- return 0;
-}
-
-int resource_manager::do_begin_file(const char *ptr, int, FILE *,
- FILE *outfp)
-{
- resource *r = read_file_arg(&ptr);
- if (r) {
- r->flags |= resource::SUPPLIED;
- if (outfp) {
- fputs("%%BeginResource: ", outfp);
- r->print_type_and_name(outfp);
- putc('\n', outfp);
- }
- }
- return 0;
-}
-
-int resource_manager::do_include_file(const char *ptr, int rank, FILE *,
- FILE *outfp)
-{
- resource *r = read_file_arg(&ptr);
- if (r)
- supply_resource(r, rank, outfp);
- return 0;
-}
-
-int resource_manager::do_begin_font(const char *ptr, int, FILE *,
- FILE *outfp)
-{
- resource *r = read_font_arg(&ptr);
- if (r) {
- r->flags |= resource::SUPPLIED;
- if (outfp) {
- fputs("%%BeginResource: ", outfp);
- r->print_type_and_name(outfp);
- putc('\n', outfp);
- }
- }
- return 0;
-}
-
-int resource_manager::do_include_font(const char *ptr, int rank, FILE *,
- FILE *outfp)
-{
- resource *r = read_font_arg(&ptr);
- if (r) {
- if (rank >= 0)
- supply_resource(r, rank + 1, outfp);
- else
- r->flags |= resource::FONT_NEEDED;
- }
- return 0;
-}
-
-int resource_manager::change_to_end_resource(const char *, int, FILE *,
- FILE *outfp)
-{
- if (outfp)
- fputs("%%EndResource\n", outfp);
- return 0;
-}
-
-int resource_manager::do_begin_preview(const char *, int, FILE *fp, FILE *)
-{
- char buf[PS_LINE_MAX + 2];
- do {
- if (!ps_get_line(buf, fp)) {
- error("end of file in preview section");
- break;
- }
- } while (!matches_comment(buf, "EndPreview"));
- return 0;
-}
-
-int read_one_of(const char **ptr, const char **s, int n)
-{
- while (white_space(**ptr))
- *ptr += 1;
- if (**ptr == '\0')
- return -1;
- const char *start = *ptr;
- do {
- ++(*ptr);
- } while (**ptr != '\0' && !white_space(**ptr));
- for (int i = 0; i < n; i++)
- if (strlen(s[i]) == size_t(*ptr - start)
- && memcmp(s[i], start, *ptr - start) == 0)
- return i;
- return -1;
-}
-
-void skip_possible_newline(const char *ptr, FILE *fp, FILE *outfp)
-{
- int c = getc(fp);
- if (c == '\r') {
- current_lineno++;
- if (outfp)
- putc(c, outfp);
- int cc = getc(fp);
- if (cc != '\n') {
- if (cc != EOF)
- ungetc(cc, fp);
- }
- else {
- if (outfp)
- putc(cc, outfp);
- }
- }
- else if (c == '\n') {
- current_lineno++;
- if (outfp)
- putc(c, outfp);
- }
- else if (c != EOF)
- ungetc(c, fp);
-}
-
-int resource_manager::do_begin_data(const char *ptr, int, FILE *fp,
- FILE *outfp)
-{
- while (white_space(*ptr))
- ptr++;
- const char *start = ptr;
- unsigned numberof;
- if (!read_uint_arg(&ptr, &numberof))
- return 0;
- static const char *types[] = { "Binary", "Hex", "ASCII" };
- const int Binary = 0;
- int type = 0;
- static const char *units[] = { "Bytes", "Lines" };
- const int Bytes = 0;
- int unit = Bytes;
- while (white_space(*ptr))
- ptr++;
- if (*ptr != '\0') {
- type = read_one_of(&ptr, types, 3);
- if (type < 0) {
- error("bad data type");
- return 0;
- }
- while (white_space(*ptr))
- ptr++;
- if (*ptr != '\0') {
- unit = read_one_of(&ptr, units, 2);
- if (unit < 0) {
- error("expected `Bytes' or `Lines'");
- return 0;
- }
- }
- }
- if (type != Binary)
- return 1;
- if (outfp) {
- fputs("%%BeginData: ", outfp);
- fputs(start, outfp);
- }
- if (numberof > 0) {
- unsigned bytecount = 0;
- unsigned linecount = 0;
- do {
- int c = getc(fp);
- if (c == EOF) {
- error("end of file within data section");
- return 0;
- }
- if (outfp)
- putc(c, outfp);
- bytecount++;
- if (c == '\r') {
- int cc = getc(fp);
- if (cc != '\n') {
- linecount++;
- current_lineno++;
- }
- if (cc != EOF)
- ungetc(c, fp);
- }
- else if (c == '\n') {
- linecount++;
- current_lineno++;
- }
- } while ((unit == Bytes ? bytecount : linecount) < numberof);
- }
- skip_possible_newline(ptr, fp, outfp);
- char buf[PS_LINE_MAX + 2];
- if (!ps_get_line(buf, fp)) {
- error("missing %%%%EndData line");
- return 0;
- }
- if (!matches_comment(buf, "EndData"))
- error("bad %%%%EndData line");
- if (outfp)
- fputs(buf, outfp);
- return 0;
-}
-
-int resource_manager::do_begin_binary(const char *ptr, int, FILE *fp,
- FILE *outfp)
-{
- if (!outfp)
- return 0;
- unsigned count;
- if (!read_uint_arg(&ptr, &count))
- return 0;
- if (outfp)
- fprintf(outfp, "%%%%BeginData: %u Binary Bytes\n", count);
- while (count != 0) {
- int c = getc(fp);
- if (c == EOF) {
- error("end of file within binary section");
- return 0;
- }
- if (outfp)
- putc(c, outfp);
- --count;
- if (c == '\r') {
- int cc = getc(fp);
- if (cc != '\n')
- current_lineno++;
- if (cc != EOF)
- ungetc(cc, fp);
- }
- else if (c == '\n')
- current_lineno++;
- }
- skip_possible_newline(ptr, fp, outfp);
- char buf[PS_LINE_MAX + 2];
- if (!ps_get_line(buf, fp)) {
- error("missing %%%%EndBinary line");
- return 0;
- }
- if (!matches_comment(buf, "EndBinary")) {
- error("bad %%%%EndBinary line");
- if (outfp)
- fputs(buf, outfp);
- }
- else if (outfp)
- fputs("%%EndData\n", outfp);
- return 0;
-}
-
-static unsigned parse_extensions(const char *ptr)
-{
- unsigned flags = 0;
- for (;;) {
- while (white_space(*ptr))
- ptr++;
- if (*ptr == '\0')
- break;
- const char *name = ptr;
- do {
- ++ptr;
- } while (*ptr != '\0' && !white_space(*ptr));
- int i;
- for (i = 0; i < NEXTENSIONS; i++)
- if (strlen(extension_table[i]) == size_t(ptr - name)
- && memcmp(extension_table[i], name, ptr - name) == 0) {
- flags |= (1 << i);
- break;
- }
- if (i >= NEXTENSIONS) {
- string s(name, ptr - name);
- s += '\0';
- error("unknown extension `%1'", s.contents());
- }
- }
- return flags;
-}
-
-// XXX if it has not been surrounded with {Begin,End}Document need to strip
-// out Page: Trailer {Begin,End}Prolog {Begin,End}Setup sections.
-
-// XXX Perhaps the decision whether to use BeginDocument or
-// BeginResource: file should be postponed till we have seen
-// the first line of the file.
-
-void resource_manager::process_file(int rank, FILE *fp, const char *filename,
- FILE *outfp)
-{
- // If none of these comments appear in the header section, and we are
- // just analyzing the file (ie outfp is 0), then we can return immediately.
- static const char *header_comment_table[] = {
- "DocumentNeededResources:",
- "DocumentSuppliedResources:",
- "DocumentNeededFonts:",
- "DocumentSuppliedFonts:",
- "DocumentNeededProcSets:",
- "DocumentSuppliedProcSets:",
- "DocumentNeededFiles:",
- "DocumentSuppliedFiles:",
- };
-
- const int NHEADER_COMMENTS = (sizeof(header_comment_table)
- / sizeof(header_comment_table[0]));
- struct comment_info {
- const char *name;
- int (resource_manager::*proc)(const char *, int, FILE *, FILE *);
- };
-
- static comment_info comment_table[] = {
- { "BeginResource:", &resource_manager::do_begin_resource },
- { "IncludeResource:", &resource_manager::do_include_resource },
- { "BeginDocument:", &resource_manager::do_begin_document },
- { "IncludeDocument:", &resource_manager::do_include_document },
- { "BeginProcSet:", &resource_manager::do_begin_procset },
- { "IncludeProcSet:", &resource_manager::do_include_procset },
- { "BeginFont:", &resource_manager::do_begin_font },
- { "IncludeFont:", &resource_manager::do_include_font },
- { "BeginFile:", &resource_manager::do_begin_file },
- { "IncludeFile:", &resource_manager::do_include_file },
- { "EndProcSet", &resource_manager::change_to_end_resource },
- { "EndFont", &resource_manager::change_to_end_resource },
- { "EndFile", &resource_manager::change_to_end_resource },
- { "BeginPreview:", &resource_manager::do_begin_preview },
- { "BeginData:", &resource_manager::do_begin_data },
- { "BeginBinary:", &resource_manager::do_begin_binary },
- };
-
- const int NCOMMENTS = sizeof(comment_table)/sizeof(comment_table[0]);
- char buf[PS_LINE_MAX + 2];
- int saved_lineno = current_lineno;
- const char *saved_filename = current_filename;
- current_filename = filename;
- current_lineno = 0;
- if (!ps_get_line(buf, fp)) {
- current_filename = saved_filename;
- current_lineno = saved_lineno;
- return;
- }
- if (strlen(buf) < sizeof(PS_MAGIC) - 1
- || memcmp(buf, PS_MAGIC, sizeof(PS_MAGIC) - 1) != 0) {
- if (outfp) {
- do {
- if (!(broken_flags & STRIP_PERCENT_BANG)
- || buf[0] != '%' || buf[1] != '!')
- fputs(buf, outfp);
- } while (ps_get_line(buf, fp));
- }
- }
- else {
- if (!(broken_flags & STRIP_PERCENT_BANG) && outfp)
- fputs(buf, outfp);
- int in_header = 1;
- int interesting = 0;
- int had_extensions_comment = 0;
- int had_language_level_comment = 0;
- for (;;) {
- if (!ps_get_line(buf, fp))
- break;
- int copy_this_line = 1;
- if (buf[0] == '%') {
- if (buf[1] == '%') {
- const char *ptr;
- int i;
- for (i = 0; i < NCOMMENTS; i++)
- if ((ptr = matches_comment(buf, comment_table[i].name))) {
- copy_this_line
- = (this->*(comment_table[i].proc))(ptr, rank, fp, outfp);
- break;
- }
- if (i >= NCOMMENTS && in_header) {
- if ((ptr = matches_comment(buf, "EndComments")))
- in_header = 0;
- else if (!had_extensions_comment
- && (ptr = matches_comment(buf, "Extensions:"))) {
- extensions |= parse_extensions(ptr);
- // XXX handle possibility that next line is %%+
- had_extensions_comment = 1;
- }
- else if (!had_language_level_comment
- && (ptr = matches_comment(buf, "LanguageLevel:"))) {
- unsigned ll;
- if (read_uint_arg(&ptr, &ll) && ll > language_level)
- language_level = ll;
- had_language_level_comment = 1;
- }
- else {
- for (i = 0; i < NHEADER_COMMENTS; i++)
- if (matches_comment(buf, header_comment_table[i])) {
- interesting = 1;
- break;
- }
- }
- }
- if ((broken_flags & STRIP_STRUCTURE_COMMENTS)
- && (matches_comment(buf, "EndProlog")
- || matches_comment(buf, "Page:")
- || matches_comment(buf, "Trailer")))
- copy_this_line = 0;
- }
- else if (buf[1] == '!') {
- if (broken_flags & STRIP_PERCENT_BANG)
- copy_this_line = 0;
- }
- }
- else
- in_header = 0;
- if (!outfp && !in_header && !interesting)
- break;
- if (copy_this_line && outfp)
- fputs(buf, outfp);
- }
- }
- current_filename = saved_filename;
- current_lineno = saved_lineno;
-}
-
-void resource_manager::read_download_file()
-{
- char *path = 0;
- FILE *fp = font::open_file("download", &path);
- if (!fp)
- fatal("can't find `download'");
- char buf[512];
- int lineno = 0;
- while (fgets(buf, sizeof(buf), fp)) {
- lineno++;
- char *p = strtok(buf, " \t\r\n");
- if (p == 0 || *p == '#')
- continue;
- char *q = strtok(0, " \t\r\n");
- if (!q)
- fatal_with_file_and_line(path, lineno, "missing filename");
- lookup_font(p)->filename = strsave(q);
- }
- a_delete path;
- fclose(fp);
-}
-
-// XXX Can we share some code with ps_output::put_string()?
-
-static void print_ps_string(const string &s, FILE *outfp)
-{
- int len = s.length();
- const char *str = s.contents();
- int funny = 0;
- if (str[0] == '(')
- funny = 1;
- else {
- for (int i = 0; i < len; i++)
- if (str[i] <= 040 || str[i] > 0176) {
- funny = 1;
- break;
- }
- }
- if (!funny) {
- put_string(s, outfp);
- return;
- }
- int level = 0;
- int i;
- for (i = 0; i < len; i++)
- if (str[i] == '(')
- level++;
- else if (str[i] == ')' && --level < 0)
- break;
- putc('(', outfp);
- for (i = 0; i < len; i++)
- switch (str[i]) {
- case '(':
- case ')':
- if (level != 0)
- putc('\\', outfp);
- putc(str[i], outfp);
- break;
- case '\\':
- fputs("\\\\", outfp);
- break;
- case '\n':
- fputs("\\n", outfp);
- break;
- case '\r':
- fputs("\\r", outfp);
- break;
- case '\t':
- fputs("\\t", outfp);
- break;
- case '\b':
- fputs("\\b", outfp);
- break;
- case '\f':
- fputs("\\f", outfp);
- break;
- default:
- if (str[i] < 040 || str[i] > 0176)
- fprintf(outfp, "\\%03o", str[i] & 0377);
- else
- putc(str[i], outfp);
- break;
- }
- putc(')', outfp);
-}
-
-void resource_manager::print_extensions_comment(FILE *outfp)
-{
- if (extensions) {
- fputs("%%Extensions:", outfp);
- for (int i = 0; i < NEXTENSIONS; i++)
- if (extensions & (1 << i)) {
- putc(' ', outfp);
- fputs(extension_table[i], outfp);
- }
- putc('\n', outfp);
- }
-}
-
-void resource_manager::print_language_level_comment(FILE *outfp)
-{
- if (language_level)
- fprintf(outfp, "%%%%LanguageLevel: %u\n", language_level);
-}
-
diff --git a/contrib/groff/src/devices/grotty/tty.cc b/contrib/groff/src/devices/grotty/tty.cc
deleted file mode 100644
index 7cfb658..0000000
--- a/contrib/groff/src/devices/grotty/tty.cc
+++ /dev/null
@@ -1,776 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1989-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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "driver.h"
-#include "device.h"
-
-extern "C" const char *Version_string;
-
-#define putstring(s) fputs(s, stdout)
-
-#ifndef SHRT_MIN
-#define SHRT_MIN (-32768)
-#endif
-
-#ifndef SHRT_MAX
-#define SHRT_MAX 32767
-#endif
-
-#define TAB_WIDTH 8
-
-static int horizontal_tab_flag = 0;
-static int form_feed_flag = 0;
-static int bold_flag = 1;
-static int underline_flag = 1;
-static int overstrike_flag = 1;
-static int draw_flag = 1;
-static int italic_flag = 0;
-static int reverse_flag = 0;
-static int old_drawing_scheme = 0;
-
-enum {
- UNDERLINE_MODE = 0x01,
- BOLD_MODE = 0x02,
- VDRAW_MODE = 0x04,
- HDRAW_MODE = 0x08,
- CU_MODE = 0x10,
- COLOR_CHANGE = 0x20
-};
-
-// Mode to use for bold-underlining.
-static unsigned char bold_underline_mode = BOLD_MODE|UNDERLINE_MODE;
-
-#ifndef IS_EBCDIC_HOST
-#define CSI "\033["
-#else
-#define CSI "\047["
-#endif
-
-// SGR handling (ISO 6429)
-#define SGR_BOLD CSI "1m"
-#define SGR_NO_BOLD CSI "22m"
-#define SGR_ITALIC CSI "3m"
-#define SGR_NO_ITALIC CSI "23m"
-#define SGR_UNDERLINE CSI "4m"
-#define SGR_NO_UNDERLINE CSI "24m"
-#define SGR_REVERSE CSI "7m"
-#define SGR_NO_REVERSE CSI "27m"
-// many terminals can't handle `CSI 39 m' and `CSI 49 m' to reset
-// the foreground and bachground color, respectively; thus we use
-// `CSI 0 m' exclusively
-#define SGR_DEFAULT CSI "0m"
-
-#define TTY_MAX_COLORS 8
-#define DEFAULT_COLOR_IDX TTY_MAX_COLORS
-
-class tty_font : public font {
- tty_font(const char *);
- unsigned char mode;
-public:
- ~tty_font();
- unsigned char get_mode() { return mode; }
-#if 0
- void handle_x_command(int argc, const char **argv);
-#endif
- static tty_font *load_tty_font(const char *);
-};
-
-tty_font *tty_font::load_tty_font(const char *s)
-{
- tty_font *f = new tty_font(s);
- if (!f->load()) {
- delete f;
- return 0;
- }
- const char *num = f->get_internal_name();
- long n;
- if (num != 0 && (n = strtol(num, 0, 0)) != 0)
- f->mode = int(n & (BOLD_MODE|UNDERLINE_MODE));
- if (!underline_flag)
- f->mode &= ~UNDERLINE_MODE;
- if (!bold_flag)
- f->mode &= ~BOLD_MODE;
- if ((f->mode & (BOLD_MODE|UNDERLINE_MODE)) == (BOLD_MODE|UNDERLINE_MODE))
- f->mode = (f->mode & ~(BOLD_MODE|UNDERLINE_MODE)) | bold_underline_mode;
- return f;
-}
-
-tty_font::tty_font(const char *nm)
-: font(nm), mode(0)
-{
-}
-
-tty_font::~tty_font()
-{
-}
-
-#if 0
-void tty_font::handle_x_command(int argc, const char **argv)
-{
- if (argc >= 1 && strcmp(argv[0], "bold") == 0)
- mode |= BOLD_MODE;
- else if (argc >= 1 && strcmp(argv[0], "underline") == 0)
- mode |= UNDERLINE_MODE;
-}
-#endif
-
-class glyph {
- static glyph *free_list;
-public:
- glyph *next;
- short hpos;
- unsigned int code;
- unsigned char mode;
- unsigned char back_color_idx;
- unsigned char fore_color_idx;
- void *operator new(size_t);
- void operator delete(void *);
- inline int draw_mode() { return mode & (VDRAW_MODE|HDRAW_MODE); }
- inline int order() {
- return mode & (VDRAW_MODE|HDRAW_MODE|CU_MODE|COLOR_CHANGE); }
-};
-
-glyph *glyph::free_list = 0;
-
-void *glyph::operator new(size_t)
-{
- if (!free_list) {
- const int BLOCK = 1024;
- free_list = (glyph *)new char[sizeof(glyph) * BLOCK];
- for (int i = 0; i < BLOCK - 1; i++)
- free_list[i].next = free_list + i + 1;
- free_list[BLOCK - 1].next = 0;
- }
- glyph *p = free_list;
- free_list = free_list->next;
- p->next = 0;
- return p;
-}
-
-void glyph::operator delete(void *p)
-{
- if (p) {
- ((glyph *)p)->next = free_list;
- free_list = (glyph *)p;
- }
-}
-
-class tty_printer : public printer {
- int is_utf8;
- glyph **lines;
- int nlines;
- int cached_v;
- int cached_vpos;
- unsigned char curr_fore_idx;
- unsigned char curr_back_idx;
- int is_underline;
- int is_bold;
- int cu_flag;
- color tty_colors[TTY_MAX_COLORS];
- void make_underline();
- void make_bold(unsigned int);
- unsigned char color_to_idx(color *col);
- void add_char(unsigned int, int, int, color *, color *, unsigned char);
-public:
- tty_printer(const char *device);
- ~tty_printer();
- void set_char(int, font *, const environment *, int, const char *name);
- void draw(int code, int *p, int np, const environment *env);
- void special(char *arg, const environment *env, char type);
- void change_color(const environment *env);
- void change_fill_color(const environment *env);
- void put_char(unsigned int);
- void put_color(unsigned char, int);
- void begin_page(int) { }
- void end_page(int page_length);
- font *make_font(const char *);
-};
-
-tty_printer::tty_printer(const char *device) : cached_v(0)
-{
- is_utf8 = !strcmp(device, "utf8");
- tty_colors[0].set_rgb(0, // black
- 0,
- 0);
- tty_colors[1].set_rgb(color::MAX_COLOR_VAL, // red
- 0,
- 0);
- tty_colors[2].set_rgb(0, // green
- color::MAX_COLOR_VAL,
- 0);
- tty_colors[3].set_rgb(color::MAX_COLOR_VAL, // yellow
- color::MAX_COLOR_VAL,
- 0);
- tty_colors[4].set_rgb(0, // blue
- 0,
- color::MAX_COLOR_VAL);
- tty_colors[5].set_rgb(color::MAX_COLOR_VAL, // magenta
- 0,
- color::MAX_COLOR_VAL);
- tty_colors[6].set_rgb(0, // cyan
- color::MAX_COLOR_VAL,
- color::MAX_COLOR_VAL);
- tty_colors[7].set_rgb(color::MAX_COLOR_VAL, // white
- color::MAX_COLOR_VAL,
- color::MAX_COLOR_VAL);
- nlines = 66;
- lines = new glyph *[nlines];
- for (int i = 0; i < nlines; i++)
- lines[i] = 0;
- cu_flag = 0;
-}
-
-tty_printer::~tty_printer()
-{
- a_delete lines;
-}
-
-void tty_printer::make_underline()
-{
- if (old_drawing_scheme) {
- putchar('_');
- putchar('\b');
- }
- else {
- if (!is_underline) {
- if (italic_flag)
- putstring(SGR_ITALIC);
- else if (reverse_flag)
- putstring(SGR_REVERSE);
- else
- putstring(SGR_UNDERLINE);
- }
- is_underline = 1;
- }
-}
-
-void tty_printer::make_bold(unsigned int c)
-{
- if (old_drawing_scheme) {
- put_char(c);
- putchar('\b');
- }
- else {
- if (!is_bold)
- putstring(SGR_BOLD);
- is_bold = 1;
- }
-}
-
-unsigned char tty_printer::color_to_idx(color *col)
-{
- if (col->is_default())
- return DEFAULT_COLOR_IDX;
- for (int i = 0; i < TTY_MAX_COLORS; i++)
- if (*col == tty_colors[i])
- return (unsigned char)i;
- unsigned r, g, b;
- col->get_rgb(&r, &g, &b);
- error("Unknown color (%1, %2, %3) mapped to default", r, g, b);
- return DEFAULT_COLOR_IDX;
-}
-
-void tty_printer::set_char(int i, font *f, const environment *env,
- int w, const char *name)
-{
- if (w != font::hor)
- fatal("width of character not equal to horizontal resolution");
- add_char(f->get_code(i),
- env->hpos, env->vpos,
- env->col, env->fill,
- ((tty_font *)f)->get_mode());
-}
-
-void tty_printer::add_char(unsigned int c,
- int h, int v,
- color *fore, color *back,
- unsigned char mode)
-{
-#if 0
- // This is too expensive.
- if (h % font::hor != 0)
- fatal("horizontal position not a multiple of horizontal resolution");
-#endif
- int hpos = h / font::hor;
- if (hpos < SHRT_MIN || hpos > SHRT_MAX) {
- error("character with ridiculous horizontal position discarded");
- return;
- }
- int vpos;
- if (v == cached_v && cached_v != 0)
- vpos = cached_vpos;
- else {
- if (v % font::vert != 0)
- fatal("vertical position not a multiple of vertical resolution");
- vpos = v / font::vert;
- if (vpos > nlines) {
- glyph **old_lines = lines;
- lines = new glyph *[vpos + 1];
- memcpy(lines, old_lines, nlines * sizeof(glyph *));
- for (int i = nlines; i <= vpos; i++)
- lines[i] = 0;
- a_delete old_lines;
- nlines = vpos + 1;
- }
- // Note that the first output line corresponds to groff
- // position font::vert.
- if (vpos <= 0) {
- error("character above first line discarded");
- return;
- }
- cached_v = v;
- cached_vpos = vpos;
- }
- glyph *g = new glyph;
- g->hpos = hpos;
- g->code = c;
- g->fore_color_idx = color_to_idx(fore);
- g->back_color_idx = color_to_idx(back);
- g->mode = mode;
-
- // The list will be reversed later. After reversal, it must be in
- // increasing order of hpos, with COLOR_CHANGE and CU specials before
- // HDRAW characters before VDRAW characters before normal characters
- // at each hpos, and otherwise in order of occurrence.
-
- glyph **pp;
- for (pp = lines + (vpos - 1); *pp; pp = &(*pp)->next)
- if ((*pp)->hpos < hpos
- || ((*pp)->hpos == hpos && (*pp)->order() >= g->order()))
- break;
- g->next = *pp;
- *pp = g;
-}
-
-void tty_printer::special(char *arg, const environment *env, char type)
-{
- if (type == 'u') {
- add_char(*arg - '0', env->hpos, env->vpos, env->col, env->fill, CU_MODE);
- return;
- }
- if (type != 'p')
- return;
- char *p;
- for (p = arg; *p == ' ' || *p == '\n'; p++)
- ;
- char *tag = p;
- for (; *p != '\0' && *p != ':' && *p != ' ' && *p != '\n'; p++)
- ;
- if (*p == '\0' || strncmp(tag, "tty", p - tag) != 0) {
- error("X command without `tty:' tag ignored");
- return;
- }
- p++;
- for (; *p == ' ' || *p == '\n'; p++)
- ;
- char *command = p;
- for (; *p != '\0' && *p != ' ' && *p != '\n'; p++)
- ;
- if (*command == '\0') {
- error("empty X command ignored");
- return;
- }
- if (strncmp(command, "sgr", p - command) == 0) {
- for (; *p == ' ' || *p == '\n'; p++)
- ;
- int n;
- if (*p != '\0' && sscanf(p, "%d", &n) == 1 && n == 0)
- old_drawing_scheme = 1;
- else
- old_drawing_scheme = 0;
- }
-}
-
-void tty_printer::change_color(const environment *env)
-{
- add_char(0, env->hpos, env->vpos, env->col, env->fill, COLOR_CHANGE);
-}
-
-void tty_printer::change_fill_color(const environment *env)
-{
- add_char(0, env->hpos, env->vpos, env->col, env->fill, COLOR_CHANGE);
-}
-
-void tty_printer::draw(int code, int *p, int np, const environment *env)
-{
- if (code != 'l' || !draw_flag)
- return;
- if (np != 2) {
- error("2 arguments required for line");
- return;
- }
- if (p[0] == 0) {
- // vertical line
- int v = env->vpos;
- int len = p[1];
- if (len < 0) {
- v += len;
- len = -len;
- }
- while (len >= 0) {
- add_char('|', env->hpos, v, env->col, env->fill, VDRAW_MODE);
- len -= font::vert;
- v += font::vert;
- }
- }
- if (p[1] == 0) {
- // horizontal line
- int h = env->hpos;
- int len = p[0];
- if (len < 0) {
- h += len;
- len = -len;
- }
- while (len >= 0) {
- add_char('-', h, env->vpos, env->col, env->fill, HDRAW_MODE);
- len -= font::hor;
- h += font::hor;
- }
- }
-}
-
-void tty_printer::put_char(unsigned int wc)
-{
- if (is_utf8 && wc >= 0x80) {
- char buf[6 + 1];
- int count;
- char *p = buf;
- if (wc < 0x800)
- count = 1, *p = (unsigned char)((wc >> 6) | 0xc0);
- else if (wc < 0x10000)
- count = 2, *p = (unsigned char)((wc >> 12) | 0xe0);
- else if (wc < 0x200000)
- count = 3, *p = (unsigned char)((wc >> 18) | 0xf0);
- else if (wc < 0x4000000)
- count = 4, *p = (unsigned char)((wc >> 24) | 0xf8);
- else if (wc <= 0x7fffffff)
- count = 5, *p = (unsigned char)((wc >> 30) | 0xfC);
- else
- return;
- do *++p = (unsigned char)(((wc >> (6 * --count)) & 0x3f) | 0x80);
- while (count > 0);
- *++p = '\0';
- putstring(buf);
- }
- else
- putchar(wc);
-}
-
-void tty_printer::put_color(unsigned char color_index, int back)
-{
- if (color_index == DEFAULT_COLOR_IDX) {
- putstring(SGR_DEFAULT);
- // set bold and underline again
- if (is_bold)
- putstring(SGR_BOLD);
- if (is_underline) {
- if (italic_flag)
- putstring(SGR_ITALIC);
- else if (reverse_flag)
- putstring(SGR_REVERSE);
- else
- putstring(SGR_UNDERLINE);
- }
- // set other color again
- back = !back;
- color_index = back ? curr_back_idx : curr_fore_idx;
- }
- putstring(CSI);
- if (back)
- putchar('4');
- else
- putchar('3');
- putchar(color_index + '0');
- putchar('m');
-}
-
-void tty_printer::end_page(int page_length)
-{
- if (page_length % font::vert != 0)
- error("vertical position at end of page not multiple of vertical resolution");
- int lines_per_page = page_length / font::vert;
- int last_line;
- for (last_line = nlines; last_line > 0; last_line--)
- if (lines[last_line - 1])
- break;
-#if 0
- if (last_line > lines_per_page) {
- error("characters past last line discarded");
- do {
- --last_line;
- while (lines[last_line]) {
- glyph *tem = lines[last_line];
- lines[last_line] = tem->next;
- delete tem;
- }
- } while (last_line > lines_per_page);
- }
-#endif
- for (int i = 0; i < last_line; i++) {
- glyph *p = lines[i];
- lines[i] = 0;
- glyph *g = 0;
- while (p) {
- glyph *tem = p->next;
- p->next = g;
- g = p;
- p = tem;
- }
- int hpos = 0;
- glyph *nextp;
- curr_fore_idx = DEFAULT_COLOR_IDX;
- curr_back_idx = DEFAULT_COLOR_IDX;
- is_underline = 0;
- is_bold = 0;
- for (p = g; p; delete p, p = nextp) {
- nextp = p->next;
- if (p->mode & CU_MODE) {
- cu_flag = p->code;
- continue;
- }
- if (nextp && p->hpos == nextp->hpos) {
- if (p->draw_mode() == HDRAW_MODE &&
- nextp->draw_mode() == VDRAW_MODE) {
- nextp->code = '+';
- continue;
- }
- if (p->draw_mode() != 0 && p->draw_mode() == nextp->draw_mode()) {
- nextp->code = p->code;
- continue;
- }
- if (!overstrike_flag)
- continue;
- }
- if (hpos > p->hpos) {
- do {
- putchar('\b');
- hpos--;
- } while (hpos > p->hpos);
- }
- else {
- if (horizontal_tab_flag) {
- for (;;) {
- int next_tab_pos = ((hpos + TAB_WIDTH) / TAB_WIDTH) * TAB_WIDTH;
- if (next_tab_pos > p->hpos)
- break;
- if (cu_flag)
- make_underline();
- else if (!old_drawing_scheme && is_underline) {
- if (italic_flag)
- putstring(SGR_NO_ITALIC);
- else if (reverse_flag)
- putstring(SGR_NO_REVERSE);
- else
- putstring(SGR_NO_UNDERLINE);
- is_underline = 0;
- }
- putchar('\t');
- hpos = next_tab_pos;
- }
- }
- for (; hpos < p->hpos; hpos++) {
- if (cu_flag)
- make_underline();
- else if (!old_drawing_scheme && is_underline) {
- if (italic_flag)
- putstring(SGR_NO_ITALIC);
- else if (reverse_flag)
- putstring(SGR_NO_REVERSE);
- else
- putstring(SGR_NO_UNDERLINE);
- is_underline = 0;
- }
- putchar(' ');
- }
- }
- assert(hpos == p->hpos);
- if (p->mode & COLOR_CHANGE) {
- if (!old_drawing_scheme) {
- if (p->fore_color_idx != curr_fore_idx) {
- put_color(p->fore_color_idx, 0);
- curr_fore_idx = p->fore_color_idx;
- }
- if (p->back_color_idx != curr_back_idx) {
- put_color(p->back_color_idx, 1);
- curr_back_idx = p->back_color_idx;
- }
- }
- continue;
- }
- if (p->mode & UNDERLINE_MODE)
- make_underline();
- else if (!old_drawing_scheme && is_underline) {
- if (italic_flag)
- putstring(SGR_NO_ITALIC);
- else if (reverse_flag)
- putstring(SGR_NO_REVERSE);
- else
- putstring(SGR_NO_UNDERLINE);
- is_underline = 0;
- }
- if (p->mode & BOLD_MODE)
- make_bold(p->code);
- else if (!old_drawing_scheme && is_bold) {
- putstring(SGR_NO_BOLD);
- is_bold = 0;
- }
- if (!old_drawing_scheme) {
- if (p->fore_color_idx != curr_fore_idx) {
- put_color(p->fore_color_idx, 0);
- curr_fore_idx = p->fore_color_idx;
- }
- if (p->back_color_idx != curr_back_idx) {
- put_color(p->back_color_idx, 1);
- curr_back_idx = p->back_color_idx;
- }
- }
- put_char(p->code);
- hpos++;
- }
- if (!old_drawing_scheme
- && (is_bold || is_underline
- || curr_fore_idx != DEFAULT_COLOR_IDX
- || curr_back_idx != DEFAULT_COLOR_IDX))
- putstring(SGR_DEFAULT);
- putchar('\n');
- }
- if (form_feed_flag) {
- if (last_line < lines_per_page)
- putchar('\f');
- }
- else {
- for (; last_line < lines_per_page; last_line++)
- putchar('\n');
- }
-}
-
-font *tty_printer::make_font(const char *nm)
-{
- return tty_font::load_tty_font(nm);
-}
-
-printer *make_printer()
-{
- return new tty_printer(device);
-}
-
-static void usage(FILE *stream);
-
-int main(int argc, char **argv)
-{
- program_name = argv[0];
- static char stderr_buf[BUFSIZ];
- if (getenv("GROFF_NO_SGR"))
- old_drawing_scheme = 1;
- setbuf(stderr, stderr_buf);
- int c;
- 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, "bBcdfF:hioruUv", long_options, NULL))
- != EOF)
- switch(c) {
- case 'v':
- printf("GNU grotty (groff) version %s\n", Version_string);
- exit(0);
- break;
- case 'i':
- // Use italic font instead of underlining.
- italic_flag = 1;
- break;
- case 'b':
- // Do not embolden by overstriking.
- bold_flag = 0;
- break;
- case 'c':
- // Use old scheme for emboldening and underline.
- old_drawing_scheme = 1;
- break;
- case 'u':
- // Do not underline.
- underline_flag = 0;
- break;
- case 'o':
- // Do not overstrike (other than emboldening and underlining).
- overstrike_flag = 0;
- break;
- case 'r':
- // Use reverse mode instead of underlining.
- reverse_flag = 1;
- break;
- case 'B':
- // Do bold-underlining as bold.
- bold_underline_mode = BOLD_MODE;
- break;
- case 'U':
- // Do bold-underlining as underlining.
- bold_underline_mode = UNDERLINE_MODE;
- break;
- case 'h':
- // Use horizontal tabs.
- horizontal_tab_flag = 1;
- break;
- case 'f':
- form_feed_flag = 1;
- break;
- case 'F':
- font::command_line_font_dir(optarg);
- break;
- case 'd':
- // Ignore \D commands.
- draw_flag = 0;
- break;
- case CHAR_MAX + 1: // --help
- usage(stdout);
- exit(0);
- break;
- case '?':
- usage(stderr);
- exit(1);
- break;
- default:
- assert(0);
- }
- if (old_drawing_scheme) {
- italic_flag = 0;
- reverse_flag = 0;
- }
- else {
- bold_underline_mode = BOLD_MODE|UNDERLINE_MODE;
- bold_flag = 1;
- underline_flag = 1;
- }
- if (optind >= argc)
- do_file("-");
- else {
- for (int i = optind; i < argc; i++)
- do_file(argv[i]);
- }
- delete pr;
- return 0;
-}
-
-static void usage(FILE *stream)
-{
- fprintf(stream, "usage: %s [-bBcdfhioruUv] [-F dir] [files ...]\n",
- program_name);
-}
diff --git a/contrib/groff/src/libs/libbib/common.cc b/contrib/groff/src/libs/libbib/common.cc
deleted file mode 100644
index 4b2bcca..0000000
--- a/contrib/groff/src/libs/libbib/common.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-/* 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-unsigned hash(const char *s, int len)
-{
-#if 0
- unsigned h = 0, g;
- while (*s != '\0') {
- h <<= 4;
- h += *s++;
- if ((g = h & 0xf0000000) != 0) {
- h ^= g >> 24;
- h ^= g;
- }
- }
-#endif
- unsigned h = 0;
- while (--len >= 0)
- h = *s++ + 65587*h;
- return h;
-}
-
diff --git a/contrib/groff/src/libs/libbib/index.cc b/contrib/groff/src/libs/libbib/index.cc
deleted file mode 100644
index 3633df1..0000000
--- a/contrib/groff/src/libs/libbib/index.cc
+++ /dev/null
@@ -1,640 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "lib.h"
-
-#include
-#include
-
-#include "posix.h"
-#include "cset.h"
-#include "cmap.h"
-#include "errarg.h"
-#include "error.h"
-
-#include "refid.h"
-#include "search.h"
-#include "index.h"
-#include "defs.h"
-
-#include "nonposix.h"
-
-// Interface to mmap.
-extern "C" {
- void *mapread(int fd, int len);
- int unmap(void *, int len);
-}
-
-#if 0
-const
-#endif
-int minus_one = -1;
-
-int verify_flag = 0;
-
-struct word_list;
-
-class index_search_item : public search_item {
- search_item *out_of_date_files;
- index_header header;
- char *buffer;
- void *map_addr;
- int map_len;
- tag *tags;
- int *table;
- int *lists;
- char *pool;
- char *key_buffer;
- char *filename_buffer;
- int filename_buflen;
- char **common_words_table;
- int common_words_table_size;
- const char *ignore_fields;
- time_t mtime;
-
- const char *do_verify();
- const int *search1(const char **pp, const char *end);
- const int *search(const char *ptr, int length, int **temp_listp);
- const char *munge_filename(const char *);
- void read_common_words_file();
- void add_out_of_date_file(int fd, const char *filename, int fid);
-public:
- index_search_item(const char *, int);
- ~index_search_item();
- int load(int fd);
- search_item_iterator *make_search_item_iterator(const char *);
- int verify();
- void check_files();
- int next_filename_id() const;
- friend class index_search_item_iterator;
-};
-
-class index_search_item_iterator : public search_item_iterator {
- index_search_item *indx;
- search_item_iterator *out_of_date_files_iter;
- search_item *next_out_of_date_file;
- const int *found_list;
- int *temp_list;
- char *buf;
- int buflen;
- linear_searcher searcher;
- char *query;
- int get_tag(int tagno, const linear_searcher &, const char **, int *,
- reference_id *);
-public:
- index_search_item_iterator(index_search_item *, const char *);
- ~index_search_item_iterator();
- int next(const linear_searcher &, const char **, int *, reference_id *);
-};
-
-
-index_search_item::index_search_item(const char *filename, int fid)
-: search_item(filename, fid), out_of_date_files(0), buffer(0), map_addr(0),
- map_len(0), key_buffer(0), filename_buffer(0), filename_buflen(0),
- common_words_table(0)
-{
-}
-
-index_search_item::~index_search_item()
-{
- if (buffer)
- free(buffer);
- if (map_addr) {
- if (unmap(map_addr, map_len) < 0)
- error("unmap: %1", strerror(errno));
- }
- while (out_of_date_files) {
- search_item *tem = out_of_date_files;
- out_of_date_files = out_of_date_files->next;
- delete tem;
- }
- a_delete filename_buffer;
- a_delete key_buffer;
- if (common_words_table) {
- for (int i = 0; i < common_words_table_size; i++)
- a_delete common_words_table[i];
- a_delete common_words_table;
- }
-}
-
-class file_closer {
- int *fdp;
-public:
- file_closer(int &fd) : fdp(&fd) { }
- ~file_closer() { close(*fdp); }
-};
-
-// Tell the compiler that a variable is intentionally unused.
-inline void unused(void *) { }
-
-int index_search_item::load(int fd)
-{
- file_closer fd_closer(fd); // close fd on return
- unused(&fd_closer);
- struct stat sb;
- if (fstat(fd, &sb) < 0) {
- error("can't fstat `%1': %2", name, strerror(errno));
- return 0;
- }
- if (!S_ISREG(sb.st_mode)) {
- error("`%1' is not a regular file", name);
- return 0;
- }
- mtime = sb.st_mtime;
- int size = int(sb.st_size);
- char *addr;
- map_addr = mapread(fd, size);
- if (map_addr) {
- addr = (char *)map_addr;
- map_len = size;
- }
- else {
- addr = buffer = (char *)malloc(size);
- if (buffer == 0) {
- error("can't allocate buffer for `%1'", name);
- return 0;
- }
- char *ptr = buffer;
- int bytes_to_read = size;
- while (bytes_to_read > 0) {
- int nread = read(fd, ptr, bytes_to_read);
- if (nread == 0) {
- error("unexpected EOF on `%1'", name);
- return 0;
- }
- if (nread < 0) {
- error("read error on `%1': %2", name, strerror(errno));
- return 0;
- }
- bytes_to_read -= nread;
- ptr += nread;
- }
- }
- header = *(index_header *)addr;
- if (header.magic != INDEX_MAGIC) {
- error("`%1' is not an index file: wrong magic number", name);
- return 0;
- }
- if (header.version != INDEX_VERSION) {
- error("version number in `%1' is wrong: was %2, should be %3",
- name, header.version, INDEX_VERSION);
- return 0;
- }
- int sz = (header.tags_size * sizeof(tag)
- + header.lists_size * sizeof(int)
- + header.table_size * sizeof(int)
- + header.strings_size
- + sizeof(header));
- if (sz != size) {
- error("size of `%1' is wrong: was %2, should be %3",
- name, size, sz);
- return 0;
- }
- tags = (tag *)(addr + sizeof(header));
- lists = (int *)(tags + header.tags_size);
- table = (int *)(lists + header.lists_size);
- pool = (char *)(table + header.table_size);
- ignore_fields = strchr(strchr(pool, '\0') + 1, '\0') + 1;
- key_buffer = new char[header.truncate];
- read_common_words_file();
- return 1;
-}
-
-const char *index_search_item::do_verify()
-{
- if (tags == 0)
- return "not loaded";
- if (lists[header.lists_size - 1] >= 0)
- return "last list element not negative";
- int i;
- for (i = 0; i < header.table_size; i++) {
- int li = table[i];
- if (li >= header.lists_size)
- return "bad list index";
- if (li >= 0) {
- for (int *ptr = lists + li; *ptr >= 0; ptr++) {
- if (*ptr >= header.tags_size)
- return "bad tag index";
- if (*ptr >= ptr[1] && ptr[1] >= 0)
- return "list not ordered";
- }
- }
- }
- for (i = 0; i < header.tags_size; i++) {
- if (tags[i].filename_index >= header.strings_size)
- return "bad index in tags";
- if (tags[i].length < 0)
- return "bad length in tags";
- if (tags[i].start < 0)
- return "bad start in tags";
- }
- if (pool[header.strings_size - 1] != '\0')
- return "last character in pool not nul";
- return 0;
-}
-
-int index_search_item::verify()
-{
- const char *reason = do_verify();
- if (!reason)
- return 1;
- error("`%1' is bad: %2", name, reason);
- return 0;
-}
-
-int index_search_item::next_filename_id() const
-{
- return filename_id + header.strings_size + 1;
-}
-
-search_item_iterator *index_search_item::make_search_item_iterator(
- const char *query)
-{
- return new index_search_item_iterator(this, query);
-}
-
-search_item *make_index_search_item(const char *filename, int fid)
-{
- char *index_filename = new char[strlen(filename) + sizeof(INDEX_SUFFIX)];
- strcpy(index_filename, filename);
- strcat(index_filename, INDEX_SUFFIX);
- int fd = open(index_filename, O_RDONLY | O_BINARY);
- if (fd < 0)
- return 0;
- index_search_item *item = new index_search_item(index_filename, fid);
- a_delete index_filename;
- if (!item->load(fd)) {
- close(fd);
- delete item;
- return 0;
- }
- else if (verify_flag && !item->verify()) {
- delete item;
- return 0;
- }
- else {
- item->check_files();
- return item;
- }
-}
-
-
-index_search_item_iterator::index_search_item_iterator(index_search_item *ind,
- const char *q)
-: indx(ind), out_of_date_files_iter(0), next_out_of_date_file(0), temp_list(0),
- buf(0), buflen(0),
- searcher(q, strlen(q), ind->ignore_fields, ind->header.truncate),
- query(strsave(q))
-{
- found_list = indx->search(q, strlen(q), &temp_list);
- if (!found_list) {
- found_list = &minus_one;
- warning("all keys would have been discarded in constructing index `%1'",
- indx->name);
- }
-}
-
-index_search_item_iterator::~index_search_item_iterator()
-{
- a_delete temp_list;
- a_delete buf;
- a_delete query;
- delete out_of_date_files_iter;
-}
-
-int index_search_item_iterator::next(const linear_searcher &,
- const char **pp, int *lenp,
- reference_id *ridp)
-{
- if (found_list) {
- for (;;) {
- int tagno = *found_list;
- if (tagno == -1)
- break;
- found_list++;
- if (get_tag(tagno, searcher, pp, lenp, ridp))
- return 1;
- }
- found_list = 0;
- next_out_of_date_file = indx->out_of_date_files;
- }
- while (next_out_of_date_file) {
- if (out_of_date_files_iter == 0)
- out_of_date_files_iter
- = next_out_of_date_file->make_search_item_iterator(query);
- if (out_of_date_files_iter->next(searcher, pp, lenp, ridp))
- return 1;
- delete out_of_date_files_iter;
- out_of_date_files_iter = 0;
- next_out_of_date_file = next_out_of_date_file->next;
- }
- return 0;
-}
-
-int index_search_item_iterator::get_tag(int tagno,
- const linear_searcher &searcher,
- const char **pp, int *lenp,
- reference_id *ridp)
-{
- if (tagno < 0 || tagno >= indx->header.tags_size) {
- error("bad tag number");
- return 0;
- }
- tag *tp = indx->tags + tagno;
- const char *filename = indx->munge_filename(indx->pool + tp->filename_index);
- int fd = open(filename, O_RDONLY | O_BINARY);
- if (fd < 0) {
- error("can't open `%1': %2", filename, strerror(errno));
- return 0;
- }
- struct stat sb;
- if (fstat(fd, &sb) < 0) {
- error("can't fstat: %1", strerror(errno));
- close(fd);
- return 0;
- }
- time_t mtime = sb.st_mtime;
- if (mtime > indx->mtime) {
- indx->add_out_of_date_file(fd, filename,
- indx->filename_id + tp->filename_index);
- return 0;
- }
- int res = 0;
- FILE *fp = fdopen(fd, FOPEN_RB);
- if (!fp) {
- error("fdopen failed");
- close(fd);
- return 0;
- }
- if (tp->start != 0 && fseek(fp, long(tp->start), 0) < 0)
- error("can't seek on `%1': %2", filename, strerror(errno));
- else {
- int length = tp->length;
- int err = 0;
- if (length == 0) {
- struct stat sb;
- if (fstat(fileno(fp), &sb) < 0) {
- error("can't stat `%1': %2", filename, strerror(errno));
- err = 1;
- }
- else if (!S_ISREG(sb.st_mode)) {
- error("`%1' is not a regular file", filename);
- err = 1;
- }
- else
- length = int(sb.st_size);
- }
- if (!err) {
- if (length + 2 > buflen) {
- a_delete buf;
- buflen = length + 2;
- buf = new char[buflen];
- }
- if (fread(buf + 1, 1, length, fp) != (size_t)length)
- error("fread on `%1' failed: %2", filename, strerror(errno));
- else {
- buf[0] = '\n';
- // Remove the CR characters from CRLF pairs.
- int sidx = 1, didx = 1;
- for ( ; sidx < length + 1; sidx++, didx++)
- {
- if (buf[sidx] == '\r')
- {
- if (buf[++sidx] != '\n')
- buf[didx++] = '\r';
- else
- length--;
- }
- if (sidx != didx)
- buf[didx] = buf[sidx];
- }
- buf[length + 1] = '\n';
- res = searcher.search(buf + 1, buf + 2 + length, pp, lenp);
- if (res && ridp)
- *ridp = reference_id(indx->filename_id + tp->filename_index,
- tp->start);
- }
- }
- }
- fclose(fp);
- return res;
-}
-
-const char *index_search_item::munge_filename(const char *filename)
-{
- if (IS_ABSOLUTE(filename))
- return filename;
- const char *cwd = pool;
- int need_slash = (cwd[0] != 0
- && strchr(DIR_SEPS, strchr(cwd, '\0')[-1]) == 0);
- int len = strlen(cwd) + strlen(filename) + need_slash + 1;
- if (len > filename_buflen) {
- a_delete filename_buffer;
- filename_buflen = len;
- filename_buffer = new char[len];
- }
- strcpy(filename_buffer, cwd);
- if (need_slash)
- strcat(filename_buffer, "/");
- strcat(filename_buffer, filename);
- return filename_buffer;
-}
-
-const int *index_search_item::search1(const char **pp, const char *end)
-{
- while (*pp < end && !csalnum(**pp))
- *pp += 1;
- if (*pp >= end)
- return 0;
- const char *start = *pp;
- while (*pp < end && csalnum(**pp))
- *pp += 1;
- int len = *pp - start;
- if (len < header.shortest)
- return 0;
- if (len > header.truncate)
- len = header.truncate;
- int is_number = 1;
- for (int i = 0; i < len; i++)
- if (csdigit(start[i]))
- key_buffer[i] = start[i];
- else {
- key_buffer[i] = cmlower(start[i]);
- is_number = 0;
- }
- if (is_number && !(len == 4 && start[0] == '1' && start[1] == '9'))
- return 0;
- unsigned hc = hash(key_buffer, len);
- if (common_words_table) {
- for (int h = hc % common_words_table_size;
- common_words_table[h];
- --h) {
- if (strlen(common_words_table[h]) == (size_t)len
- && memcmp(common_words_table[h], key_buffer, len) == 0)
- return 0;
- if (h == 0)
- h = common_words_table_size;
- }
- }
- int li = table[int(hc % header.table_size)];
- return li < 0 ? &minus_one : lists + li;
-}
-
-static void merge(int *result, const int *s1, const int *s2)
-{
- for (; *s1 >= 0; s1++) {
- while (*s2 >= 0 && *s2 < *s1)
- s2++;
- if (*s2 == *s1)
- *result++ = *s2;
- }
- *result++ = -1;
-}
-
-const int *index_search_item::search(const char *ptr, int length,
- int **temp_listp)
-{
- const char *end = ptr + length;
- if (*temp_listp) {
- a_delete *temp_listp;
- *temp_listp = 0;
- }
- const int *first_list = 0;
- while (ptr < end && (first_list = search1(&ptr, end)) == 0)
- ;
- if (!first_list)
- return 0;
- if (*first_list < 0)
- return first_list;
- const int *second_list = 0;
- while (ptr < end && (second_list = search1(&ptr, end)) == 0)
- ;
- if (!second_list)
- return first_list;
- if (*second_list < 0)
- return second_list;
- const int *p;
- for (p = first_list; *p >= 0; p++)
- ;
- int len = p - first_list;
- for (p = second_list; *p >= 0; p++)
- ;
- if (p - second_list < len)
- len = p - second_list;
- int *matches = new int[len + 1];
- merge(matches, first_list, second_list);
- while (ptr < end) {
- const int *list = search1(&ptr, end);
- if (list != 0) {
- if (*list < 0) {
- a_delete matches;
- return list;
- }
- merge(matches, matches, list);
- if (*matches < 0) {
- a_delete matches;
- return &minus_one;
- }
- }
- }
- *temp_listp = matches;
- return matches;
-}
-
-void index_search_item::read_common_words_file()
-{
- if (header.common <= 0)
- return;
- const char *common_words_file = munge_filename(strchr(pool, '\0') + 1);
- errno = 0;
- FILE *fp = fopen(common_words_file, "r");
- if (!fp) {
- error("can't open `%1': %2", common_words_file, strerror(errno));
- return;
- }
- common_words_table_size = 2*header.common + 1;
- while (!is_prime(common_words_table_size))
- common_words_table_size++;
- common_words_table = new char *[common_words_table_size];
- for (int i = 0; i < common_words_table_size; i++)
- common_words_table[i] = 0;
- int count = 0;
- int key_len = 0;
- for (;;) {
- int c = getc(fp);
- while (c != EOF && !csalnum(c))
- c = getc(fp);
- if (c == EOF)
- break;
- do {
- if (key_len < header.truncate)
- key_buffer[key_len++] = cmlower(c);
- c = getc(fp);
- } while (c != EOF && csalnum(c));
- if (key_len >= header.shortest) {
- int h = hash(key_buffer, key_len) % common_words_table_size;
- while (common_words_table[h]) {
- if (h == 0)
- h = common_words_table_size;
- --h;
- }
- common_words_table[h] = new char[key_len + 1];
- memcpy(common_words_table[h], key_buffer, key_len);
- common_words_table[h][key_len] = '\0';
- }
- if (++count >= header.common)
- break;
- key_len = 0;
- if (c == EOF)
- break;
- }
- fclose(fp);
-}
-
-void index_search_item::add_out_of_date_file(int fd, const char *filename,
- int fid)
-{
- search_item **pp;
- for (pp = &out_of_date_files; *pp; pp = &(*pp)->next)
- if ((*pp)->is_named(filename))
- return;
- *pp = make_linear_search_item(fd, filename, fid);
- warning("`%1' modified since `%2' created", filename, name);
-}
-
-void index_search_item::check_files()
-{
- const char *pool_end = pool + header.strings_size;
- for (const char *ptr = strchr(ignore_fields, '\0') + 1;
- ptr < pool_end;
- ptr = strchr(ptr, '\0') + 1) {
- const char *path = munge_filename(ptr);
- struct stat sb;
- if (stat(path, &sb) < 0)
- error("can't stat `%1': %2", path, strerror(errno));
- else if (sb.st_mtime > mtime) {
- int fd = open(path, O_RDONLY | O_BINARY);
- if (fd < 0)
- error("can't open `%1': %2", path, strerror(errno));
- else
- add_out_of_date_file(fd, path, filename_id + (ptr - pool));
- }
- }
-}
diff --git a/contrib/groff/src/libs/libbib/linear.cc b/contrib/groff/src/libs/libbib/linear.cc
deleted file mode 100644
index 1dd902b..0000000
--- a/contrib/groff/src/libs/libbib/linear.cc
+++ /dev/null
@@ -1,503 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "lib.h"
-
-#include
-#include
-#include
-
-#include "posix.h"
-#include "errarg.h"
-#include "error.h"
-#include "cset.h"
-#include "cmap.h"
-#include "nonposix.h"
-
-#include "refid.h"
-#include "search.h"
-
-class file_buffer {
- char *buffer;
- char *bufend;
-public:
- file_buffer();
- ~file_buffer();
- int load(int fd, const char *filename);
- const char *get_start() const;
- const char *get_end() const;
-};
-
-typedef unsigned char uchar;
-
-static uchar map[256];
-static uchar inv_map[256][3];
-
-struct map_init {
- map_init();
-};
-
-static map_init the_map_init;
-
-map_init::map_init()
-{
- int i;
- for (i = 0; i < 256; i++)
- map[i] = csalnum(i) ? cmlower(i) : '\0';
- for (i = 0; i < 256; i++) {
- if (cslower(i)) {
- inv_map[i][0] = i;
- inv_map[i][1] = cmupper(i);
- inv_map[i][2] = '\0';
- }
- else if (csdigit(i)) {
- inv_map[i][0] = i;
- inv_map[i][1] = 0;
- }
- else
- inv_map[i][0] = '\0';
- }
-}
-
-
-class bmpattern {
- char *pat;
- int len;
- int delta[256];
-public:
- bmpattern(const char *pattern, int pattern_length);
- ~bmpattern();
- const char *search(const char *p, const char *end) const;
- int length() const;
-};
-
-bmpattern::bmpattern(const char *pattern, int pattern_length)
-: len(pattern_length)
-{
- pat = new char[len];
- int i;
- for (i = 0; i < len; i++)
- pat[i] = map[uchar(pattern[i])];
- for (i = 0; i < 256; i++)
- delta[i] = len;
- for (i = 0; i < len; i++)
- for (const unsigned char *inv = inv_map[uchar(pat[i])]; *inv; inv++)
- delta[*inv] = len - i - 1;
-}
-
-const char *bmpattern::search(const char *buf, const char *end) const
-{
- int buflen = end - buf;
- if (len > buflen)
- return 0;
- const char *strend;
- if (buflen > len*4)
- strend = end - len*4;
- else
- strend = buf;
- const char *k = buf + len - 1;
- const int *del = delta;
- const char *pattern = pat;
- for (;;) {
- while (k < strend) {
- int t = del[uchar(*k)];
- if (!t)
- break;
- k += t;
- k += del[uchar(*k)];
- k += del[uchar(*k)];
- }
- while (k < end && del[uchar(*k)] != 0)
- k++;
- if (k == end)
- break;
- int j = len - 1;
- const char *s = k;
- for (;;) {
- if (j == 0)
- return s;
- if (map[uchar(*--s)] != uchar(pattern[--j]))
- break;
- }
- k++;
- }
- return 0;
-}
-
-bmpattern::~bmpattern()
-{
- a_delete pat;
-}
-
-inline int bmpattern::length() const
-{
- return len;
-}
-
-
-static const char *find_end(const char *bufend, const char *p);
-
-const char *linear_searcher::search_and_check(const bmpattern *key,
- const char *buf, const char *bufend, const char **start) const
-{
- assert(buf[-1] == '\n');
- assert(bufend[-1] == '\n');
- const char *ptr = buf;
- for (;;) {
- const char *found = key->search(ptr, bufend);
- if (!found)
- break;
- if (check_match(buf, bufend, found, key->length(), &ptr, start))
- return found;
- }
- return 0;
-}
-
-static const char *skip_field(const char *end, const char *p)
-{
- for (;;)
- if (*p++ == '\n') {
- if (p == end || *p == '%')
- break;
- const char *q;
- for (q = p; *q == ' ' || *q == '\t'; q++)
- ;
- if (*q == '\n')
- break;
- p = q + 1;
- }
- return p;
-}
-
-static const char *find_end(const char *bufend, const char *p)
-{
- for (;;)
- if (*p++ == '\n') {
- if (p == bufend)
- break;
- const char *q;
- for (q = p; *q == ' ' || *q == '\t'; q++)
- ;
- if (*q == '\n')
- break;
- p = q + 1;
- }
- return p;
-}
-
-
-int linear_searcher::check_match(const char *buf, const char *bufend,
- const char *match, int matchlen,
- const char **cont, const char **start) const
-{
- *cont = match + 1;
- // The user is required to supply only the first truncate_len characters
- // of the key. If truncate_len <= 0, he must supply all the key.
- if ((truncate_len <= 0 || matchlen < truncate_len)
- && map[uchar(match[matchlen])] != '\0')
- return 0;
-
- // The character before the match must not be an alphanumeric
- // character (unless the alphanumeric character follows one or two
- // percent characters at the beginning of the line), nor must it be
- // a percent character at the beginning of a line, nor a percent
- // character following a percent character at the beginning of a
- // line.
-
- switch (match - buf) {
- case 0:
- break;
- case 1:
- if (match[-1] == '%' || map[uchar(match[-1])] != '\0')
- return 0;
- break;
- case 2:
- if (map[uchar(match[-1])] != '\0' && match[-2] != '%')
- return 0;
- if (match[-1] == '%'
- && (match[-2] == '\n' || match[-2] == '%'))
- return 0;
- break;
- default:
- if (map[uchar(match[-1])] != '\0'
- && !(match[-2] == '%'
- && (match[-3] == '\n'
- || (match[-3] == '%' && match[-4] == '\n'))))
- return 0;
- if (match[-1] == '%'
- && (match[-2] == '\n'
- || (match[-2] == '%' && match[-3] == '\n')))
- return 0;
- }
-
- const char *p = match;
- int had_percent = 0;
- for (;;) {
- if (*p == '\n') {
- if (!had_percent && p[1] == '%') {
- if (p[2] != '\0' && strchr(ignore_fields, p[2]) != 0) {
- *cont = skip_field(bufend, match + matchlen);
- return 0;
- }
- if (!start)
- break;
- had_percent = 1;
- }
- if (p <= buf) {
- if (start)
- *start = p + 1;
- return 1;
- }
- const char *q;
- for (q = p - 1; *q == ' ' || *q == '\t'; q--)
- ;
- if (*q == '\n') {
- if (start)
- *start = p + 1;
- break;
- }
- p = q;
- }
- p--;
- }
- return 1;
-}
-
-file_buffer::file_buffer()
-: buffer(0), bufend(0)
-{
-}
-
-file_buffer::~file_buffer()
-{
- a_delete buffer;
-}
-
-const char *file_buffer::get_start() const
-{
- return buffer ? buffer + 4 : 0;
-}
-
-const char *file_buffer::get_end() const
-{
- return bufend;
-}
-
-int file_buffer::load(int fd, const char *filename)
-{
- struct stat sb;
- if (fstat(fd, &sb) < 0)
- error("can't fstat `%1': %2", filename, strerror(errno));
- else if (!S_ISREG(sb.st_mode))
- error("`%1' is not a regular file", filename);
- else {
- // We need one character extra at the beginning for an additional newline
- // used as a sentinel. We get 4 instead so that the read buffer will be
- // word-aligned. This seems to make the read slightly faster. We also
- // need one character at the end also for an additional newline used as a
- // sentinel.
- int size = int(sb.st_size);
- buffer = new char[size + 4 + 1];
- int nread = read(fd, buffer + 4, size);
- if (nread < 0)
- error("error reading `%1': %2", filename, strerror(errno));
- else if (nread != size)
- error("size of `%1' decreased", filename);
- else {
- char c;
- nread = read(fd, &c, 1);
- if (nread != 0)
- error("size of `%1' increased", filename);
- else if (memchr(buffer + 4, '\0', size < 1024 ? size : 1024) != 0)
- error("database `%1' is a binary file", filename);
- else {
- close(fd);
- buffer[3] = '\n';
- int sidx = 4, didx = 4;
- for ( ; sidx < size + 4; sidx++, didx++)
- {
- if (buffer[sidx] == '\r')
- {
- if (buffer[++sidx] != '\n')
- buffer[didx++] = '\r';
- else
- size--;
- }
- if (sidx != didx)
- buffer[didx] = buffer[sidx];
- }
- bufend = buffer + 4 + size;
- if (bufend[-1] != '\n')
- *bufend++ = '\n';
- return 1;
- }
- }
- a_delete buffer;
- buffer = 0;
- }
- close(fd);
- return 0;
-}
-
-linear_searcher::linear_searcher(const char *query, int query_len,
- const char *ign, int trunc)
-: ignore_fields(ign), truncate_len(trunc), keys(0), nkeys(0)
-{
- const char *query_end = query + query_len;
- int nk = 0;
- const char *p;
- for (p = query; p < query_end; p++)
- if (map[uchar(*p)] != '\0'
- && (p[1] == '\0' || map[uchar(p[1])] == '\0'))
- nk++;
- if (nk == 0)
- return;
- keys = new bmpattern*[nk];
- p = query;
- for (;;) {
- while (p < query_end && map[uchar(*p)] == '\0')
- p++;
- if (p == query_end)
- break;
- const char *start = p;
- while (p < query_end && map[uchar(*p)] != '\0')
- p++;
- keys[nkeys++] = new bmpattern(start, p - start);
- }
- assert(nkeys <= nk);
- if (nkeys == 0) {
- a_delete keys;
- keys = 0;
- }
-}
-
-linear_searcher::~linear_searcher()
-{
- for (int i = 0; i < nkeys; i++)
- delete keys[i];
- a_delete keys;
-}
-
-int linear_searcher::search(const char *buffer, const char *bufend,
- const char **startp, int *lengthp) const
-{
- assert(bufend - buffer > 0);
- assert(buffer[-1] == '\n');
- assert(bufend[-1] == '\n');
- if (nkeys == 0)
- return 0;
- for (;;) {
- const char *refstart;
- const char *found = search_and_check(keys[0], buffer, bufend, &refstart);
- if (!found)
- break;
- const char *refend = find_end(bufend, found + keys[0]->length());
- int i;
- for (i = 1; i < nkeys; i++)
- if (!search_and_check(keys[i], refstart, refend))
- break;
- if (i >= nkeys) {
- *startp = refstart;
- *lengthp = refend - refstart;
- return 1;
- }
- buffer = refend;
- }
- return 0;
-}
-
-class linear_search_item : public search_item {
- file_buffer fbuf;
-public:
- linear_search_item(const char *filename, int fid);
- ~linear_search_item();
- int load(int fd);
- search_item_iterator *make_search_item_iterator(const char *);
- friend class linear_search_item_iterator;
-};
-
-class linear_search_item_iterator : public search_item_iterator {
- linear_search_item *lsi;
- int pos;
-public:
- linear_search_item_iterator(linear_search_item *, const char *query);
- ~linear_search_item_iterator();
- int next(const linear_searcher &, const char **ptr, int *lenp,
- reference_id *ridp);
-};
-
-search_item *make_linear_search_item(int fd, const char *filename, int fid)
-{
- linear_search_item *item = new linear_search_item(filename, fid);
- if (!item->load(fd)) {
- delete item;
- return 0;
- }
- else
- return item;
-}
-
-linear_search_item::linear_search_item(const char *filename, int fid)
-: search_item(filename, fid)
-{
-}
-
-linear_search_item::~linear_search_item()
-{
-}
-
-int linear_search_item::load(int fd)
-{
- return fbuf.load(fd, name);
-}
-
-search_item_iterator *linear_search_item::make_search_item_iterator(
- const char *query)
-{
- return new linear_search_item_iterator(this, query);
-}
-
-linear_search_item_iterator::linear_search_item_iterator(
- linear_search_item *p, const char *)
-: lsi(p), pos(0)
-{
-}
-
-linear_search_item_iterator::~linear_search_item_iterator()
-{
-}
-
-int linear_search_item_iterator::next(const linear_searcher &searcher,
- const char **startp, int *lengthp,
- reference_id *ridp)
-{
- const char *bufstart = lsi->fbuf.get_start();
- const char *bufend = lsi->fbuf.get_end();
- const char *ptr = bufstart + pos;
- if (ptr < bufend && searcher.search(ptr, bufend, startp, lengthp)) {
- pos = *startp + *lengthp - bufstart;
- if (ridp)
- *ridp = reference_id(lsi->filename_id, *startp - bufstart);
- return 1;
- }
- else
- return 0;
-}
diff --git a/contrib/groff/src/libs/libbib/search.cc b/contrib/groff/src/libs/libbib/search.cc
deleted file mode 100644
index 2223fb6..0000000
--- a/contrib/groff/src/libs/libbib/search.cc
+++ /dev/null
@@ -1,133 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "lib.h"
-
-#include
-#include
-#include
-
-#include "posix.h"
-#include "errarg.h"
-#include "error.h"
-#include "nonposix.h"
-
-#include "refid.h"
-#include "search.h"
-
-int linear_truncate_len = 6;
-const char *linear_ignore_fields = "XYZ";
-
-search_list::search_list()
-: list(0), niterators(0), next_fid(1)
-{
-}
-
-search_list::~search_list()
-{
- assert(niterators == 0);
- while (list) {
- search_item *tem = list->next;
- delete list;
- list = tem;
- }
-}
-
-void search_list::add_file(const char *filename, int silent)
-{
- search_item *p = make_index_search_item(filename, next_fid);
- if (!p) {
- int fd = open(filename, O_RDONLY | O_BINARY);
- if (fd < 0) {
- if (!silent)
- error("can't open `%1': %2", filename, strerror(errno));
- }
- else
- p = make_linear_search_item(fd, filename, next_fid);
- }
- if (p) {
- search_item **pp;
- for (pp = &list; *pp; pp = &(*pp)->next)
- ;
- *pp = p;
- next_fid = p->next_filename_id();
- }
-}
-
-int search_list::nfiles() const
-{
- int n = 0;
- for (search_item *ptr = list; ptr; ptr = ptr->next)
- n++;
- return n;
-}
-
-search_list_iterator::search_list_iterator(search_list *p, const char *q)
-: list(p), ptr(p->list), iter(0), query(strsave(q)),
- searcher(q, strlen(q), linear_ignore_fields, linear_truncate_len)
-{
- list->niterators += 1;
-}
-
-search_list_iterator::~search_list_iterator()
-{
- list->niterators -= 1;
- a_delete query;
- delete iter;
-}
-
-int search_list_iterator::next(const char **pp, int *lenp, reference_id *ridp)
-{
- while (ptr) {
- if (iter == 0)
- iter = ptr->make_search_item_iterator(query);
- if (iter->next(searcher, pp, lenp, ridp))
- return 1;
- delete iter;
- iter = 0;
- ptr = ptr->next;
- }
- return 0;
-}
-
-search_item::search_item(const char *nm, int fid)
-: name(strsave(nm)), filename_id(fid), next(0)
-{
-}
-
-search_item::~search_item()
-{
- a_delete name;
-}
-
-int search_item::is_named(const char *nm) const
-{
- return strcmp(name, nm) == 0;
-}
-
-int search_item::next_filename_id() const
-{
- return filename_id + 1;
-}
-
-search_item_iterator::~search_item_iterator()
-{
-}
diff --git a/contrib/groff/src/libs/libdriver/input.cc b/contrib/groff/src/libs/libdriver/input.cc
deleted file mode 100644
index a02c139..0000000
--- a/contrib/groff/src/libs/libdriver/input.cc
+++ /dev/null
@@ -1,1814 +0,0 @@
-// -*- C++ -*-
-
-// /src/libs/libdriver/input.cc
-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002
- Free Software Foundation, Inc.
-
- Written by James Clark (jjc@jclark.com)
- Major rewrite 2001 by Bernd Warken (bwarken@mayn.de)
-
- Last update: 12 Apr 2002
-
- This file is part of groff, the GNU roff text processing system.
-
- 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, 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
-*/
-
-/* Description
-
- This file implements the parser for the intermediate groff output,
- see groff_out(5), and does the printout for the given device.
-
- All parsed information is processed within the function do_file() by
- using the global object `pr' of class `printer'. So a device
- postprocessor just needs to fill in the methods for the class
- `printer' without having to worry about the syntax of the
- intermediate output format. Consequently, the programming of groff
- postprocessors is similar to the development of device-drivers.
-
- The prototyping for this file is done in driver.h (and error.h).
-
- Postprocessor programs must deallocate the global variables `pr' and
- `device' using `delete', and `current_filename' using
- `free((char *))'.
-*/
-
-/* Changes of the 2001 rewrite of this file.
-
- The interface to the outside and the handling of the global
- variables was not changed, but internally many necessary changes
- were performed.
-
- The main aim for this rewrite is to provide a first step towards
- making groff fully compatible with classical troff without pain.
-
- Bugs fixed
- - Unknown subcommands of `D' and `x' are now ignored like in the
- classical case, but a warning is issued. This was also
- implemented for the other commands.
- - A warning is emitted if `x stop' is missing.
- - `DC' and `DE' commands didn't position to the right end after
- drawing (now they do), see discussion below.
- - So far, `x stop' was ignored. Now it terminates the processing
- of the current intermediate output file like the classical troff.
- - The command `c' didn't check correctly on white-space.
- - The environment stack wasn't suitable for the color extensions
- (replaced by a class).
- - The old groff parser could only handle a prologue with the first
- 3 lines having a fixed structure, while classical troff specified
- the sequence of the first 3 commands without further
- restrictions. Now the parser is smart about additional
- white space, comments, and empty lines in the prologue.
- - The old parser allowed space characters only as syntactical
- separators, while classical troff had tab characters as well.
- Now any sequence of tabs and/or spaces is a syntactical
- separator between commands and/or arguments.
- - Range checks for numbers implemented.
-
- New and improved features
- - The color commands `m' and `DF' are added.
- - The old color command `Df' is now converted and delegated to `DFg'.
- - The command `F' is implemented as `use intended file name'. It
- checks whether its argument agrees with the file name used so far,
- otherwise a warning is issued. Then the new name is remembered
- and used for the following error messages.
- - For the positioning after drawing commands, an alternative, easier
- scheme is provided, but not yet activated; it can be chosen by
- undefining the preprocessor macro STUPID_DRAWING_POSITIONING.
- It extends the rule of the classical troff output language in a
- logical way instead of the rather strange actual positioning.
- For details, see the discussion below.
- - For the `D' commands that only set the environment, the calling of
- pr->send_draw() was removed because this doesn't make sense for
- the `DF' commands; the (changed) environment is sent with the
- next command anyway.
- - Error handling was clearly separated into warnings and fatal.
- - The error behavior on additional arguments for `D' and `x'
- commands with a fixed number of arguments was changed from being
- ignored (former groff) to issue a warning and ignore (now), see
- skip_line_x(). No fatal was chosen because both string and
- integer arguments can occur.
- - The gtroff program issues a trailing dummy integer argument for
- some drawing commands with an odd number of arguments to make the
- number of arguments even, e.g. the DC and Dt commands; this is
- honored now.
- - All D commands with a variable number of args expect an even
- number of trailing integer arguments, so fatal on error was
- implemented.
- - Disable environment stack and the commands `{' and `}' by making
- them conditional on macro USE_ENV_STACK; actually, this is
- undefined by default. There isn't any known application for these
- features.
-
- Cosmetics
- - Nested `switch' commands are avoided by using more functions.
- Dangerous 'fall-through's avoided.
- - Commands and functions are sorted alphabetically (where possible).
- - Dynamic arrays/buffers are now implemented as container classes.
- - Some functions had an ugly return structure; this has been
- streamlined by using classes.
- - Use standard C math functions for number handling, so getting rid
- of differences to '0'.
- - The macro `IntArg' has been created for an easier transition
- to guaranteed 32 bits integers (`int' is enough for GNU, while
- ANSI only guarantees `long int' to have a length of 32 bits).
- - The many usages of type `int' are differentiated by using `Char',
- `bool', and `IntArg' where appropriate.
- - To ease the calls of the local utility functions, the parser
- variables `current_file', `npages', and `current_env'
- (formerly env) were made global to the file (formerly they were
- local to the do_file() function)
- - Various comments were added.
-
- TODO
- - Get rid of the stupid drawing positioning.
- - Can the `Dt' command be completely handled by setting environment
- within do_file() instead of sending to pr?
- - Integer arguments must be >= 32 bits, use conditional #define.
- - Add scaling facility for classical device independence and
- non-groff devices. Classical troff output had a quasi device
- independence by scaling the intermediate output to the resolution
- of the postprocessor device if different from the one specified
- with `x T', groff have not. So implement full quasi device
- indepedence, including the mapping of the strange classical
- devices to the postprocessor device (seems to be reasonably
- easy).
- - The external, global pointer variables are not optimally handled.
- - `pr' isn't used outside besides initialization and deletion.
- So it could be replaced by a static local variable. For
- example, a wrapper class `Postprocessor' for class `printer' with
- internal make_printer() and automatic clean-up would make sense.
- - The global variables `current_filename' and `current_lineno' are
- only used for error reporting. So implement a static class
- `Error' (`::' calls).
- - The global `device' is the name used during the formatting
- process; there should be a new variable for the device name used
- during the postprocessing.
- - Implement the B-spline drawing `D~' for all graphical devices.
- - Make `environment' a class with an overflow check for its members
- and a delete method to get rid of delete_current_env().
- - Implement the `EnvStack' to use `new' instead of `malloc'.
- - The class definitions of this document could go into a new file.
- - The comments in this section should go to a `Changelog' or some
- `README' file in this directory.
-*/
-
-/*
- Discussion of the positioning by drawing commands
-
- There was some confusion about the positioning of the graphical
- pointer at the printout after having executed a `D' command.
- The classical troff manual of Osanna & Kernighan specified,
-
- `The position after a graphical object has been drawn is
- at its end; for circles and ellipses, the "end" is at the
- right side.'
-
- From this, it follows that
- - all open figures (args, splines, and lines) should position at their
- final point.
- - all circles and ellipses should position at their right-most point
- (as if 2 halves had been drawn).
- - all closed figures apart from circles and ellipses shouldn't change
- the position because they return to their origin.
- - all setting commands should not change position because they do not
- draw any graphical object.
-
- In the case of the open figures, this means that the horizontal
- displacement is the sum of all odd arguments and the vertical offset
- the sum of all even arguments, called the alternate arguments sum
- displacement in the following.
-
- Unfortunately, groff did not implement this simple rule. The former
- documentation in groff_out(5) differed from the source code, and
- neither of them is compatible with the classical rule.
-
- The former groff_out(5) specified to use the alternative arguments
- sum displacement for calculating the drawing positioning of
- non-classical commands, including the `Dt' command (setting-only)
- and closed polygons. Applying this to the new groff color commands
- will lead to disaster. For their arguments can take large values (>
- 65000). On low resolution devices, the displacement of such large
- values will corrupt the display or kill the printer. So the
- nonsense specification has come to a natural end anyway.
-
- The groff source code, however, had no positioning for the
- setting-only commands (esp. `Dt'), the right-end positioning for
- outlined circles and ellipses, and the alternative argument sum
- displacement for all other commands (including filled circles and
- ellipses).
-
- The reason why no one seems to have suffered from this mayhem so
- far is that the graphical objects are usually generated by
- preprocessors like pic that do not depend on the automatic
- positioning. When using the low level `\D' escape sequences or `D'
- output commands, the strange positionings can be circumvented by
- absolute positionings or by tricks like `\Z'.
-
- So doing an exorcism on the strange, incompatible displacements might
- not harm any existing documents, but will make the usage of the
- graphical escape sequences and commands natural.
-
- That's why the rewrite of this file returned to the reasonable,
- classical specification with its clear end-of-drawing rule that is
- suitable for all cases. But a macro STUPID_DRAWING_POSITIONING is
- provided for testing the funny former behavior.
-
- The new rule implies the following behavior.
- - Setting commands (`Dt', `Df', `DF') and polygons (`Dp' and `DP')
- do not change position now.
- - Filled circles and ellipses (`DC' and `DE') position at their
- most right point (outlined ones `Dc' and `De' did this anyway).
- - As before, all open graphical objects position to their final
- drawing point (alternate sum of the command arguments).
-
-*/
-
-#ifndef STUPID_DRAWING_POSITIONING
-// uncomment next line if all non-classical D commands shall position
-// to the strange alternate sum of args displacement
-#define STUPID_DRAWING_POSITIONING
-#endif
-
-// Decide whether the commands `{' and `}' for different environments
-// should be used.
-#undef USE_ENV_STACK
-
-#include "driver.h"
-#include "device.h"
-
-#include
-#include
-#include
-#include
-
-
-/**********************************************************************
- local types
- **********************************************************************/
-
-// integer type used in the fields of struct environment (see printer.h)
-typedef int EnvInt;
-
-// integer arguments of groff_out commands, must be >= 32 bits
-typedef int IntArg;
-
-// color components of groff_out color commands, must be >= 32 bits
-typedef unsigned int ColorArg;
-
-// Array for IntArg values.
-class IntArray {
- size_t num_allocated;
- size_t num_stored;
- IntArg *data;
-public:
- IntArray(void);
- IntArray(const size_t);
- ~IntArray(void);
- const IntArg operator[](const size_t i) const
- {
- if (i >= num_stored || i < 0)
- fatal("index out of range");
- return (const IntArg) data[i];
- }
- void append(IntArg);
- const IntArg * const
- get_data(void) const { return (const IntArg * const) data; }
- const size_t len(void) const { return num_stored; }
-};
-
-// Characters read from the input queue.
-class Char {
- int data;
-public:
- Char(void) : data('\0') {}
- Char(const int c) : data(c) {}
- bool operator==(char c) const { return (data == c) ? true : false; }
- bool operator==(int c) const { return (data == c) ? true : false; }
- bool operator==(const Char c) const
- { return (data == c.data) ? true : false; }
- bool operator!=(char c) const { return !(*this == c); }
- bool operator!=(int c) const { return !(*this == c); }
- bool operator!=(const Char c) const { return !(*this == c); }
- operator int() const { return (int) data; }
- operator unsigned char() const { return (unsigned char) data; }
- operator char() const { return (char) data; }
-};
-
-// Buffer for string arguments (Char, not char).
-class StringBuf {
- size_t num_allocated;
- size_t num_stored;
- Char *data; // not terminated by '\0'
-public:
- StringBuf(void); // allocate without storing
- ~StringBuf(void);
- void append(const Char); // append character to `data'
- char *make_string(void); // return new copy of `data' with '\0'
- bool is_empty(void) { // true if none stored
- return (num_stored > 0) ? false : true;
- }
- void reset(void); // set `num_stored' to 0
-};
-
-#ifdef USE_ENV_STACK
-class EnvStack {
- environment **data;
- size_t num_allocated;
- size_t num_stored;
-public:
- EnvStack(void);
- ~EnvStack(void);
- environment *pop(void);
- void push(environment *e);
-};
-#endif // USE_ENV_STACK
-
-
-/**********************************************************************
- external variables
- **********************************************************************/
-
-// exported as extern by error.h (called from driver.h)
-// needed for error messages (see ../libgroff/error.cc)
-const char *current_filename = 0; // printable name of the current file
-int current_lineno = 0; // current line number of printout
-
-// exported as extern by device.h;
-const char *device = 0; // cancel former init with literal
-
-// from driver.h; pr is kept between several runs of do_file()
-// extern printer *pr;
-
-// Note:
-//
-// We rely on an implementation of the `new' operator which aborts
-// gracefully if it can't allocate memory (e.g. from libgroff/new.cc).
-
-
-/**********************************************************************
- static local variables
- **********************************************************************/
-
-FILE *current_file = 0; // current input stream for parser
-
-// npages: number of pages processed so far (including current page),
-// _not_ the page number in the printout (can be set with `p').
-int npages = 0;
-
-const ColorArg
-COLORARG_MAX = (ColorArg) 65536U; // == 0xFFFF + 1 == 0x10000
-
-const IntArg
-INTARG_MAX = (IntArg) 0x7FFFFFFF; // maximal signed 32 bits number
-
-// parser environment, created and deleted by each run of do_file()
-environment *current_env = 0;
-
-#ifdef USE_ENV_STACK
-const size_t
-envp_size = sizeof(environment *);
-#endif // USE_ENV_STACK
-
-
-/**********************************************************************
- function declarations
- **********************************************************************/
-
-// utility functions
-ColorArg color_from_Df_command(IntArg);
- // transform old color into new
-void delete_current_env(void); // delete global var current_env
-void fatal_command(char); // abort for invalid command
-inline Char get_char(void); // read next character from input stream
-ColorArg get_color_arg(void); // read in argument for new color cmds
-IntArray *get_D_fixed_args(const size_t);
- // read in fixed number of integer
- // arguments
-IntArray *get_D_fixed_args_odd_dummy(const size_t);
- // read in a fixed number of integer
- // arguments plus optional dummy
-IntArray *get_D_variable_args(void);
- // variable, even number of int args
-char *get_extended_arg(void); // argument for `x X' (several lines)
-IntArg get_integer_arg(void); // read in next integer argument
-IntArray *get_possibly_integer_args();
- // 0 or more integer arguments
-char *get_string_arg(void); // read in next string arg, ended by WS
-inline bool is_space_or_tab(const Char);
- // test on space/tab char
-Char next_arg_begin(void); // skip white space on current line
-Char next_command(void); // go to next command, evt. diff. line
-inline bool odd(const int); // test if integer is odd
-void position_to_end_of_args(const IntArray * const);
- // positioning after drawing
-void remember_filename(const char *);
- // set global current_filename
-void send_draw(const Char, const IntArray * const);
- // call pr->draw
-void skip_line(void); // unconditionally skip to next line
-bool skip_line_checked(void); // skip line, false if args are left
-void skip_line_fatal(void); // skip line, fatal if args are left
-void skip_line_warn(void); // skip line, warn if args are left
-void skip_line_D(void); // skip line in D commands
-void skip_line_x(void); // skip line in x commands
-void skip_to_end_of_line(void); // skip to the end of the current line
-inline void unget_char(const Char);
- // restore character onto input
-
-// parser subcommands
-void parse_color_command(color *);
- // color sub(sub)commands m and DF
-void parse_D_command(void); // graphical subcommands
-bool parse_x_command(void); // device controller subcommands
-
-
-/**********************************************************************
- class methods
- **********************************************************************/
-
-#ifdef USE_ENV_STACK
-EnvStack::EnvStack(void)
-{
- num_allocated = 4;
- // allocate pointer to array of num_allocated pointers to environment
- data = (environment **) malloc(envp_size * num_allocated);
- if (data == 0)
- fatal("could not allocate environment data");
- num_stored = 0;
-}
-
-EnvStack::~EnvStack(void)
-{
- for (size_t i = 0; i < num_stored; i++)
- delete data[i];
- free(data);
-}
-
-// return top element from stack and decrease stack pointer
-//
-// the calling function must take care of properly deleting the result
-environment *
-EnvStack::pop(void)
-{
- num_stored--;
- environment *result = data[num_stored];
- data[num_stored] = 0;
- return result;
-}
-
-// copy argument and push this onto the stack
-void
-EnvStack::push(environment *e)
-{
- environment *e_copy = new environment;
- if (num_stored >= num_allocated) {
- environment **old_data = data;
- num_allocated *= 2;
- data = (environment **) malloc(envp_size * num_allocated);
- if (data == 0)
- fatal("could not allocate data");
- for (size_t i = 0; i < num_stored; i++)
- data[i] = old_data[i];
- free(old_data);
- }
- e_copy->col = new color;
- e_copy->fill = new color;
- *e_copy->col = *e->col;
- *e_copy->fill = *e->fill;
- e_copy->fontno = e->fontno;
- e_copy->height = e->height;
- e_copy->hpos = e->hpos;
- e_copy->size = e->size;
- e_copy->slant = e->slant;
- e_copy->vpos = e->vpos;
- data[num_stored] = e_copy;
- num_stored++;
-}
-#endif // USE_ENV_STACK
-
-IntArray::IntArray(void)
-{
- num_allocated = 4;
- data = new IntArg[num_allocated];
- num_stored = 0;
-}
-
-IntArray::IntArray(const size_t n)
-{
- if (n <= 0)
- fatal("number of integers to be allocated must be > 0");
- num_allocated = n;
- data = new IntArg[num_allocated];
- num_stored = 0;
-}
-
-IntArray::~IntArray(void)
-{
- a_delete data;
-}
-
-void
-IntArray::append(IntArg x)
-{
- if (num_stored >= num_allocated) {
- IntArg *old_data = data;
- num_allocated *= 2;
- data = new IntArg[num_allocated];
- for (size_t i = 0; i < num_stored; i++)
- data[i] = old_data[i];
- a_delete old_data;
- }
- data[num_stored] = x;
- num_stored++;
-}
-
-StringBuf::StringBuf(void)
-{
- num_stored = 0;
- num_allocated = 128;
- data = new Char[num_allocated];
-}
-
-StringBuf::~StringBuf(void)
-{
- a_delete data;
-}
-
-void
-StringBuf::append(const Char c)
-{
- if (num_stored >= num_allocated) {
- Char *old_data = data;
- num_allocated *= 2;
- data = new Char[num_allocated];
- for (size_t i = 0; i < num_stored; i++)
- data[i] = old_data[i];
- a_delete old_data;
- }
- data[num_stored] = c;
- num_stored++;
-}
-
-char *
-StringBuf::make_string(void)
-{
- char *result = new char[num_stored + 1];
- for (size_t i = 0; i < num_stored; i++)
- result[i] = (char) data[i];
- result[num_stored] = '\0';
- return result;
-}
-
-void
-StringBuf::reset(void)
-{
- num_stored = 0;
-}
-
-/**********************************************************************
- utility functions
- **********************************************************************/
-
-//////////////////////////////////////////////////////////////////////
-/* color_from_Df_command:
- Process the gray shade setting command Df.
-
- Transform Df style color into DF style color.
- Df color: 0-1000, 0 is white
- DF color: 0-65536, 0 is black
-
- The Df command is obsoleted by command DFg, but kept for
- compatibility.
-
- XXX: Add proper handling for values < 0 or > 1000 as documented in
- groff_out(5).
-*/
-ColorArg
-color_from_Df_command(IntArg Df_gray)
-{
- if (Df_gray <= 0)
- return COLORARG_MAX;
- if (Df_gray >= 1000)
- return 0;
- return ColorArg((1000-Df_gray) * COLORARG_MAX / 1000); // scaling
-}
-
-//////////////////////////////////////////////////////////////////////
-/* delete_current_env():
- Delete global variable current_env and its pointer members.
-
- This should be a class method of environment.
-*/
-void delete_current_env(void)
-{
- delete current_env->col;
- delete current_env->fill;
- delete current_env;
-}
-
-//////////////////////////////////////////////////////////////////////
-/* fatal_command():
- Emit error message about invalid command and abort.
-*/
-void
-fatal_command(char command)
-{
- fatal("`%1' command invalid before first `p' command", command);
-}
-
-//////////////////////////////////////////////////////////////////////
-/* get_char():
- Retrieve the next character from the input queue.
-
- Return: The retrieved character (incl. EOF), converted to Char.
-*/
-inline Char
-get_char(void)
-{
- return (Char) getc(current_file);
-}
-
-//////////////////////////////////////////////////////////////////////
-/* get_color_arg():
- Retrieve an argument suitable for the color commands m and DF.
-
- Return: The retrieved color argument.
-*/
-ColorArg
-get_color_arg(void)
-{
- IntArg x = get_integer_arg();
- if (x < 0 || x > (IntArg)COLORARG_MAX) {
- error("color component argument out of range");
- x = 0;
- }
- return (ColorArg) x;
-}
-
-//////////////////////////////////////////////////////////////////////
-/* get_D_fixed_args():
- Get a fixed number of integer arguments for D commands.
-
- Fatal if wrong number of arguments.
- Too many arguments on the line raise a warning.
- A line skip is done.
-
- number: In-parameter, the number of arguments to be retrieved.
- ignore: In-parameter, ignore next argument -- GNU troff always emits
- pairs of parameters for `D' extensions added by groff.
- Default is `false'.
-
- Return: New IntArray containing the arguments.
-*/
-IntArray *
-get_D_fixed_args(const size_t number)
-{
- if (number <= 0)
- fatal("requested number of arguments must be > 0");
- IntArray *args = new IntArray(number);
- for (size_t i = 0; i < number; i++)
- args->append(get_integer_arg());
- skip_line_D();
- return args;
-}
-
-//////////////////////////////////////////////////////////////////////
-/* get_D_fixed_args_odd_dummy():
- Get a fixed number of integer arguments for D commands and optionally
- ignore a dummy integer argument if the requested number is odd.
-
- The gtroff program adds a dummy argument to some commands to get
- an even number of arguments.
- Error if the number of arguments differs from the scheme above.
- A line skip is done.
-
- number: In-parameter, the number of arguments to be retrieved.
-
- Return: New IntArray containing the arguments.
-*/
-IntArray *
-get_D_fixed_args_odd_dummy(const size_t number)
-{
- if (number <= 0)
- fatal("requested number of arguments must be > 0");
- IntArray *args = new IntArray(number);
- for (size_t i = 0; i < number; i++)
- args->append(get_integer_arg());
- if (odd(number)) {
- IntArray *a = get_possibly_integer_args();
- if (a->len() > 1)
- error("too many arguments");
- delete a;
- }
- skip_line_D();
- return args;
-}
-
-//////////////////////////////////////////////////////////////////////
-/* get_D_variable_args():
- Get a variable even number of integer arguments for D commands.
-
- Get as many integer arguments as possible from the rest of the
- current line.
- - The arguments are separated by an arbitrary sequence of space or
- tab characters.
- - A comment, a newline, or EOF indicates the end of processing.
- - Error on non-digit characters different from these.
- - A final line skip is performed (except for EOF).
-
- Return: New IntArray of the retrieved arguments.
-*/
-IntArray *
-get_D_variable_args()
-{
- IntArray *args = get_possibly_integer_args();
- size_t n = args->len();
- if (n <= 0)
- error("no arguments found");
- if (odd(n))
- error("even number of arguments expected");
- skip_line_D();
- return args;
-}
-
-//////////////////////////////////////////////////////////////////////
-/* get_extended_arg():
- Retrieve extended arg for `x X' command.
-
- - Skip leading spaces and tabs, error on EOL or newline.
- - Return everything before the next NL or EOF ('#' is not a comment);
- as long as the following line starts with '+' this is returned
- as well, with the '+' replaced by a newline.
- - Final line skip is always performed.
-
- Return: Allocated (new) string of retrieved text argument.
-*/
-char *
-get_extended_arg(void)
-{
- StringBuf buf = StringBuf();
- Char c = next_arg_begin();
- while ((int) c != EOF) {
- if ((int) c == '\n') {
- current_lineno++;
- c = get_char();
- if ((int) c == '+')
- buf.append((Char) '\n');
- else {
- unget_char(c); // first character of next line
- break;
- }
- }
- else
- buf.append(c);
- c = get_char();
- }
- return buf.make_string();
-}
-
-//////////////////////////////////////////////////////////////////////
-/* get_integer_arg(): Retrieve integer argument.
-
- Skip leading spaces and tabs, collect an optional '-' and all
- following decimal digits (at least one) up to the next non-digit,
- which is restored onto the input queue.
-
- Fatal error on all other situations.
-
- Return: Retrieved integer.
-*/
-IntArg
-get_integer_arg(void)
-{
- StringBuf buf = StringBuf();
- Char c = next_arg_begin();
- if ((int) c == '-') {
- buf.append(c);
- c = get_char();
- }
- if (!isdigit((int) c))
- error("integer argument expected");
- while (isdigit((int) c)) {
- buf.append(c);
- c = get_char();
- }
- // c is not a digit
- unget_char(c);
- char *s = buf.make_string();
- errno = 0;
- long int number = strtol(s, 0, 10);
- if (errno != 0
- || number > INTARG_MAX || number < -INTARG_MAX) {
- error("integer argument too large");
- number = 0;
- }
- delete s;
- return (IntArg) number;
-}
-
-//////////////////////////////////////////////////////////////////////
-/* get_possibly_integer_args():
- Parse the rest of the input line as a list of integer arguments.
-
- Get as many integer arguments as possible from the rest of the
- current line, even none.
- - The arguments are separated by an arbitrary sequence of space or
- tab characters.
- - A comment, a newline, or EOF indicates the end of processing.
- - Error on non-digit characters different from these.
- - No line skip is performed.
-
- Return: New IntArray of the retrieved arguments.
-*/
-IntArray *
-get_possibly_integer_args()
-{
- bool done = false;
- StringBuf buf = StringBuf();
- Char c = get_char();
- IntArray *args = new IntArray();
- while (!done) {
- buf.reset();
- while (is_space_or_tab(c))
- c = get_char();
- if (c == '-') {
- Char c1 = get_char();
- if (isdigit((int) c1)) {
- buf.append(c);
- c = c1;
- }
- else
- unget_char(c1);
- }
- while (isdigit((int) c)) {
- buf.append(c);
- c = get_char();
- }
- if (!buf.is_empty()) {
- char *s = buf.make_string();
- errno = 0;
- long int x = strtol(s, 0, 10);
- if (errno
- || x > INTARG_MAX || x < -INTARG_MAX) {
- error("invalid integer argument, set to 0");
- x = 0;
- }
- args->append((IntArg) x);
- delete s;
- }
- // Here, c is not a digit.
- // Terminate on comment, end of line, or end of file, while
- // space or tab indicate continuation; otherwise error.
- switch((int) c) {
- case '#':
- skip_to_end_of_line();
- done = true;
- break;
- case '\n':
- done = true;
- unget_char(c);
- break;
- case EOF:
- done = true;
- break;
- case ' ':
- case '\t':
- break;
- default:
- error("integer argument expected");
- break;
- }
- }
- return args;
-}
-
-//////////////////////////////////////////////////////////////////////
-/* get_string_arg():
- Retrieve string arg.
-
- - Skip leading spaces and tabs; error on EOL or newline.
- - Return all following characters before the next space, tab,
- newline, or EOF character (in-word '#' is not a comment character).
- - The terminating space, tab, newline, or EOF character is restored
- onto the input queue, so no line skip.
-
- Return: Retrieved string as char *, allocated by 'new'.
-*/
-char *
-get_string_arg(void)
-{
- StringBuf buf = StringBuf();
- Char c = next_arg_begin();
- while (!is_space_or_tab(c)
- && c != Char('\n') && c != Char(EOF)) {
- buf.append(c);
- c = get_char();
- }
- unget_char(c); // restore white space
- return buf.make_string();
-}
-
-//////////////////////////////////////////////////////////////////////
-/* is_space_or_tab():
- Test a character if it is a space or tab.
-
- c: In-parameter, character to be tested.
-
- Return: True, if c is a space or tab character, false otherwise.
-*/
-inline bool
-is_space_or_tab(const Char c)
-{
- return (c == Char(' ') || c == Char('\t')) ? true : false;
-}
-
-//////////////////////////////////////////////////////////////////////
-/* next_arg_begin():
- Return first character of next argument.
-
- Skip space and tab characters; error on newline or EOF.
-
- Return: The first character different from these (including '#').
-*/
-Char
-next_arg_begin(void)
-{
- Char c;
- while (1) {
- c = get_char();
- switch ((int) c) {
- case ' ':
- case '\t':
- break;
- case '\n':
- case EOF:
- error("missing argument");
- break;
- default: // first essential character
- return c;
- }
- }
-}
-
-//////////////////////////////////////////////////////////////////////
-/* next_command():
- Find the first character of the next command.
-
- Skip spaces, tabs, comments (introduced by #), and newlines.
-
- Return: The first character different from these (including EOF).
-*/
-Char
-next_command(void)
-{
- Char c;
- while (1) {
- c = get_char();
- switch ((int) c) {
- case ' ':
- case '\t':
- break;
- case '\n':
- current_lineno++;
- break;
- case '#': // comment
- skip_line();
- break;
- default: // EOF or first essential character
- return c;
- }
- }
-}
-
-//////////////////////////////////////////////////////////////////////
-/* odd():
- Test whether argument is an odd number.
-
- n: In-parameter, the integer to be tested.
-
- Return: True if odd, false otherwise.
-*/
-inline bool
-odd(const int n)
-{
- return (n & 1 == 1) ? true : false;
-}
-
-//////////////////////////////////////////////////////////////////////
-/* position_to_end_of_args():
- Move graphical pointer to end of drawn figure.
-
- This is used by the D commands that draw open geometrical figures.
- The algorithm simply sums up all horizontal displacements (arguments
- with even number) for the horizontal component. Similarly, the
- vertical component is the sum of the odd arguments.
-
- args: In-parameter, the arguments of a former drawing command.
-*/
-void
-position_to_end_of_args(const IntArray * const args)
-{
- size_t i;
- const size_t n = args->len();
- for (i = 0; i < n; i += 2)
- current_env->hpos += (*args)[i];
- for (i = 1; i < n; i += 2)
- current_env->vpos += (*args)[i];
-}
-
-//////////////////////////////////////////////////////////////////////
-/* remember_filename():
- Set global variable current_filename.
-
- The actual filename is stored in current_filename. This is used by
- the postprocessors, expecting the name "" for stdin.
-
- filename: In-out-parameter; is changed to the new value also.
-*/
-void
-remember_filename(const char *filename)
-{
- char *fname;
- if (strcmp(filename, "-") == 0)
- fname = "";
- else
- fname = (char *) filename;
- size_t len = strlen(fname) + 1;
- if (current_filename != 0)
- free((char *)current_filename);
- current_filename = (const char *) malloc(len);
- if (current_filename == 0)
- fatal("can't malloc space for filename");
- strncpy((char *)current_filename, (char *)fname, len);
-}
-
-//////////////////////////////////////////////////////////////////////
-/* send_draw():
- Call draw method of printer class.
-
- subcmd: Letter of actual D subcommand.
- args: Array of integer arguments of actual D subcommand.
-*/
-void
-send_draw(const Char subcmd, const IntArray * const args)
-{
- EnvInt n = (EnvInt) args->len();
- pr->draw((int) subcmd, (IntArg *) args->get_data(), n, current_env);
-}
-
-//////////////////////////////////////////////////////////////////////
-/* skip_line():
- Go to next line within the input queue.
-
- Skip the rest of the current line, including the newline character.
- The global variable current_lineno is adjusted.
- No errors are raised.
-*/
-void
-skip_line(void)
-{
- Char c = get_char();
- while (1) {
- if (c == '\n') {
- current_lineno++;
- break;
- }
- if (c == EOF)
- break;
- c = get_char();
- }
-}
-
-//////////////////////////////////////////////////////////////////////
-/* skip_line_checked ():
- Check that there aren't any arguments left on the rest of the line,
- then skip line.
-
- Spaces, tabs, and a comment are allowed before newline or EOF.
- All other characters raise an error.
-*/
-bool
-skip_line_checked(void)
-{
- bool ok = true;
- Char c = get_char();
- while (is_space_or_tab(c))
- c = get_char();
- switch((int) c) {
- case '#': // comment
- skip_line();
- break;
- case '\n':
- current_lineno++;
- break;
- case EOF:
- break;
- default:
- ok = false;
- skip_line();
- break;
- }
- return ok;
-}
-
-//////////////////////////////////////////////////////////////////////
-/* skip_line_fatal ():
- Fatal error if arguments left, otherwise skip line.
-
- Spaces, tabs, and a comment are allowed before newline or EOF.
- All other characters trigger the error.
-*/
-void
-skip_line_fatal(void)
-{
- bool ok = skip_line_checked();
- if (!ok) {
- current_lineno--;
- error("too many arguments");
- current_lineno++;
- }
-}
-
-//////////////////////////////////////////////////////////////////////
-/* skip_line_warn ():
- Skip line, but warn if arguments are left on actual line.
-
- Spaces, tabs, and a comment are allowed before newline or EOF.
- All other characters raise a warning
-*/
-void
-skip_line_warn(void)
-{
- bool ok = skip_line_checked();
- if (!ok) {
- current_lineno--;
- warning("too many arguments on current line");
- current_lineno++;
- }
-}
-
-//////////////////////////////////////////////////////////////////////
-/* skip_line_D ():
- Skip line in `D' commands.
-
- Decide whether in case of an additional argument a fatal error is
- raised (the documented classical behavior), only a warning is
- issued, or the line is just skipped (former groff behavior).
- Actually decided for the warning.
-*/
-void
-skip_line_D(void)
-{
- skip_line_warn();
- // or: skip_line_fatal();
- // or: skip_line();
-}
-
-//////////////////////////////////////////////////////////////////////
-/* skip_line_x ():
- Skip line in `x' commands.
-
- Decide whether in case of an additional argument a fatal error is
- raised (the documented classical behavior), only a warning is
- issued, or the line is just skipped (former groff behavior).
- Actually decided for the warning.
-*/
-void
-skip_line_x(void)
-{
- skip_line_warn();
- // or: skip_line_fatal();
- // or: skip_line();
-}
-
-//////////////////////////////////////////////////////////////////////
-/* skip_to_end_of_line():
- Go to the end of the current line.
-
- Skip the rest of the current line, excluding the newline character.
- The global variable current_lineno is not changed.
- No errors are raised.
-*/
-void
-skip_to_end_of_line(void)
-{
- Char c = get_char();
- while (1) {
- if (c == '\n') {
- unget_char(c);
- return;
- }
- if (c == EOF)
- return;
- c = get_char();
- }
-}
-
-//////////////////////////////////////////////////////////////////////
-/* unget_char(c):
- Restore character c onto input queue.
-
- Write a character back onto the input stream.
- EOF is gracefully handled.
-
- c: In-parameter; character to be pushed onto the input queue.
-*/
-inline void
-unget_char(const Char c)
-{
- if (c != EOF) {
- int ch = (int) c;
- if (ungetc(ch, current_file) == EOF)
- fatal("could not unget character");
- }
-}
-
-
-/**********************************************************************
- parser subcommands
- **********************************************************************/
-
-//////////////////////////////////////////////////////////////////////
-/* parse_color_command:
- Process the commands m and DF, but not Df.
-
- col: In-out-parameter; the color object to be set, must have
- been initialized before.
-*/
-void
-parse_color_command(color *col)
-{
- ColorArg gray = 0;
- ColorArg red = 0, green = 0, blue = 0;
- ColorArg cyan = 0, magenta = 0, yellow = 0, black = 0;
- Char subcmd = next_arg_begin();
- switch((int) subcmd) {
- case 'c': // DFc or mc: CMY
- cyan = get_color_arg();
- magenta = get_color_arg();
- yellow = get_color_arg();
- col->set_cmy(cyan, magenta, yellow);
- break;
- case 'd': // DFd or md: set default color
- col->set_default();
- break;
- case 'g': // DFg or mg: gray
- gray = get_color_arg();
- col->set_gray(gray);
- break;
- case 'k': // DFk or mk: CMYK
- cyan = get_color_arg();
- magenta = get_color_arg();
- yellow = get_color_arg();
- black = get_color_arg();
- col->set_cmyk(cyan, magenta, yellow, black);
- break;
- case 'r': // DFr or mr: RGB
- red = get_color_arg();
- green = get_color_arg();
- blue = get_color_arg();
- col->set_rgb(red, green, blue);
- break;
- default:
- error("invalid color scheme `%1'", (int) subcmd);
- break;
- } // end of color subcommands
-}
-
-//////////////////////////////////////////////////////////////////////
-/* parse_D_command():
- Parse the subcommands of graphical command D.
-
- This is the part of the do_file() parser that scans the graphical
- subcommands.
- - Error on lacking or wrong arguments.
- - Warning on too many arguments.
- - Line is always skipped.
-*/
-void
-parse_D_command()
-{
- Char subcmd = next_arg_begin();
- switch((int) subcmd) {
- case '~': // D~: draw B-spline
- // actually, this isn't available for some postprocessors
- // fall through
- default: // unknown options are passed to device
- {
- IntArray *args = get_D_variable_args();
- send_draw(subcmd, args);
- position_to_end_of_args(args);
- delete args;
- break;
- }
- case 'a': // Da: draw arc
- {
- IntArray *args = get_D_fixed_args(4);
- send_draw(subcmd, args);
- position_to_end_of_args(args);
- delete args;
- break;
- }
- case 'c': // Dc: draw circle line
- {
- IntArray *args = get_D_fixed_args(1);
- send_draw(subcmd, args);
- // move to right end
- current_env->hpos += (*args)[0];
- delete args;
- break;
- }
- case 'C': // DC: draw solid circle
- {
- IntArray *args = get_D_fixed_args_odd_dummy(1);
- send_draw(subcmd, args);
- // move to right end
- current_env->hpos += (*args)[0];
- delete args;
- break;
- }
- case 'e': // De: draw ellipse line
- case 'E': // DE: draw solid ellipse
- {
- IntArray *args = get_D_fixed_args(2);
- send_draw(subcmd, args);
- // move to right end
- current_env->hpos += (*args)[0];
- delete args;
- break;
- }
- case 'f': // Df: set fill gray; obsoleted by DFg
- {
- IntArg arg = get_integer_arg();
- if ((arg >= 0) && (arg <= 1000)) {
- // convert arg and treat it like DFg
- ColorArg gray = color_from_Df_command(arg);
- current_env->fill->set_gray(gray);
- }
- else {
- // set fill color to the same value as the current outline color
- delete current_env->fill;
- current_env->fill = new color(current_env->col);
- }
- pr->change_fill_color(current_env);
- // skip unused `vertical' component (\D'...' always emits pairs)
- (void) get_integer_arg();
- // no positioning
- skip_line_x();
- break;
- }
- case 'F': // DF: set fill color, several formats
- parse_color_command(current_env->fill);
- pr->change_fill_color(current_env);
- // no positioning (setting-only command)
- skip_line_x();
- break;
- case 'l': // Dl: draw line
- {
- IntArray *args = get_D_fixed_args(2);
- send_draw(subcmd, args);
- position_to_end_of_args(args);
- delete args;
- break;
- }
- case 'p': // Dp: draw closed polygon line
- case 'P': // DP: draw solid closed polygon
- {
- IntArray *args = get_D_variable_args();
- send_draw(subcmd, args);
-# ifdef STUPID_DRAWING_POSITIONING
- // final args positioning
- position_to_end_of_args(args);
-# endif
- delete args;
- break;
- }
- case 't': // Dt: set line thickness
- {
- IntArray *args = get_D_fixed_args_odd_dummy(1);
- send_draw(subcmd, args);
-# ifdef STUPID_DRAWING_POSITIONING
- // final args positioning
- position_to_end_of_args(args);
-# endif
- // no positioning?
- delete args;
- break;
- }
- } // end of D subcommands
-}
-
-//////////////////////////////////////////////////////////////////////
-/* parse_x_command():
- Parse subcommands of the device control command x.
-
- This is the part of the do_file() parser that scans the device
- controlling commands.
- - Error on duplicate prologue commands.
- - Error on wrong or lacking arguments.
- - Warning on too many arguments.
- - Line is always skipped.
-
- Globals:
- - current_env: is set by many subcommands.
- - npages: page counting variable
-
- Return: boolean in the meaning of `stopped'
- - true if parsing should be stopped (`x stop').
- - false if parsing should continue.
-*/
-bool
-parse_x_command(void)
-{
- bool stopped = false;
- char *subcmd_str = get_string_arg();
- char subcmd = subcmd_str[0];
- switch (subcmd) {
- case 'f': // x font: mount font
- {
- IntArg n = get_integer_arg();
- char *name = get_string_arg();
- pr->load_font(n, name);
- delete name;
- skip_line_x();
- break;
- }
- case 'F': // x Filename: set filename for errors
- {
- char *str_arg = get_string_arg();
- if (str_arg == 0)
- warning("empty argument for `x F' command");
- else {
- remember_filename(str_arg);
- delete str_arg;
- }
- break;
- }
- case 'H': // x Height: set character height
- current_env->height = get_integer_arg();
- if (current_env->height == current_env->size)
- current_env->height = 0;
- skip_line_x();
- break;
- case 'i': // x init: initialize device
- error("duplicate `x init' command");
- skip_line_x();
- break;
- case 'p': // x pause: pause device
- skip_line_x();
- break;
- case 'r': // x res: set resolution
- error("duplicate `x res' command");
- skip_line_x();
- break;
- case 's': // x stop: stop device
- stopped = true;
- skip_line_x();
- break;
- case 'S': // x Slant: set slant
- current_env->slant = get_integer_arg();
- skip_line_x();
- break;
- case 't': // x trailer: generate trailer info
- skip_line_x();
- break;
- case 'T': // x Typesetter: set typesetter
- error("duplicate `x T' command");
- skip_line();
- break;
- case 'u': // x underline: from .cu
- {
- char *str_arg = get_string_arg();
- pr->special(str_arg, current_env, 'u');
- delete str_arg;
- skip_line_x();
- break;
- }
- case 'X': // x X: send uninterpretedly to device
- {
- char *str_arg = get_extended_arg(); // includes line skip
- if (npages <= 0)
- error("`x X' command invalid before first `p' command");
- else
- pr->special(str_arg, current_env);
- delete str_arg;
- break;
- }
- default: // ignore unknown x commands, but warn
- warning("unknown command `x %1'", subcmd);
- skip_line();
- }
- delete subcmd_str;
- return stopped;
-}
-
-
-/**********************************************************************
- exported part (by driver.h)
- **********************************************************************/
-
-////////////////////////////////////////////////////////////////////////
-/* do_file():
- Parse and postprocess groff intermediate output.
-
- filename: "-" for standard input, normal file name otherwise
-*/
-void
-do_file(const char *filename)
-{
- Char command;
- bool stopped = false; // terminating condition
-
-#ifdef USE_ENV_STACK
- EnvStack env_stack = EnvStack();
-#endif // USE_ENV_STACK
-
- // setup of global variables
- npages = 0;
- current_lineno = 1;
- // `pr' is initialized after the prologue.
- // `device' is set by the 1st prologue command.
-
- if (filename[0] == '-' && filename[1] == '\0')
- current_file = stdin;
- else {
- errno = 0;
- current_file = fopen(filename, "r");
- if (errno != 0 || current_file == 0) {
- error("can't open file `%1'", filename);
- return;
- }
- }
- remember_filename(filename);
-
- if (current_env != 0)
- delete_current_env();
- current_env = new environment;
- current_env->col = new color;
- current_env->fill = new color;
- current_env->fontno = -1;
- current_env->height = 0;
- current_env->hpos = -1;
- current_env->slant = 0;
- current_env->size = 0;
- current_env->vpos = -1;
-
- // parsing of prologue (first 3 commands)
- {
- char *str_arg;
- IntArg int_arg;
-
- // 1st command `x T'
- command = next_command();
- if ((int) command == EOF)
- return;
- if ((int) command != 'x')
- fatal("the first command must be `x T'");
- str_arg = get_string_arg();
- if (str_arg[0] != 'T')
- fatal("the first command must be `x T'");
- delete str_arg;
- char *tmp_dev = get_string_arg();
- if (pr == 0) { // note: `pr' initialized after prologue
- device = tmp_dev;
- if (!font::load_desc())
- fatal("couldn't load DESC file, can't continue");
- }
- else {
- if (device == 0 || strcmp(device, tmp_dev) != 0)
- fatal("all files must use the same device");
- delete tmp_dev;
- }
- skip_line_x(); // ignore further arguments
- current_env->size = 10 * font::sizescale;
-
- // 2nd command `x res'
- command = next_command();
- if ((int) command != 'x')
- fatal("the second command must be `x res'");
- str_arg = get_string_arg();
- if (str_arg[0] != 'r')
- fatal("the second command must be `x res'");
- delete str_arg;
- int_arg = get_integer_arg();
- EnvInt font_res = font::res;
- if (int_arg != font_res)
- fatal("resolution does not match");
- int_arg = get_integer_arg();
- if (int_arg != font::hor)
- fatal("minimum horizontal motion does not match");
- int_arg = get_integer_arg();
- if (int_arg != font::vert)
- fatal("minimum vertical motion does not match");
- skip_line_x(); // ignore further arguments
-
- // 3rd command `x init'
- command = next_command();
- if (command != 'x')
- fatal("the third command must be `x init'");
- str_arg = get_string_arg();
- if (str_arg[0] != 'i')
- fatal("the third command must be `x init'");
- delete str_arg;
- skip_line_x();
- }
-
- // parsing of body
- if (pr == 0)
- pr = make_printer();
- while (!stopped) {
- command = next_command();
- if (command == EOF)
- break;
- // spaces, tabs, comments, and newlines are skipped here
- switch ((int) command) {
- case '#': // #: comment, ignore up to end of line
- skip_line();
- break;
-#ifdef USE_ENV_STACK
- case '{': // {: start a new environment (a copy)
- env_stack.push(current_env);
- break;
- case '}': // }: pop previous env from stack
- delete_current_env();
- current_env = env_stack.pop();
- break;
-#endif // USE_ENV_STACK
- case '0': // ddc: obsolete jump and print command
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- { // expect 2 digits and a character
- char s[3];
- Char c = next_arg_begin();
- if (npages <= 0)
- fatal_command(command);
- if (!isdigit((int) c)) {
- error("digit expected");
- c = 0;
- }
- s[0] = (char) command;
- s[1] = (char) c;
- s[2] = '\0';
- errno = 0;
- long int x = strtol(s, 0, 10);
- if (errno != 0)
- error("couldn't convert 2 digits");
- EnvInt hor_pos = (EnvInt) x;
- current_env->hpos += hor_pos;
- c = next_arg_begin();
- if ((int) c == '\n' || (int) c == EOF)
- error("character argument expected");
- else
- pr->set_ascii_char((unsigned char) c, current_env);
- break;
- }
- case 'c': // c: print ascii char without moving
- {
- if (npages <= 0)
- fatal_command(command);
- Char c = next_arg_begin();
- if (c == '\n' || c == EOF)
- error("missing argument to `c' command");
- else
- pr->set_ascii_char((unsigned char) c, current_env);
- break;
- }
- case 'C': // C: print named special character
- {
- if (npages <= 0)
- fatal_command(command);
- char *str_arg = get_string_arg();
- pr->set_special_char(str_arg, current_env);
- delete str_arg;
- break;
- }
- case 'D': // drawing commands
- if (npages <= 0)
- fatal_command(command);
- parse_D_command();
- break;
- case 'f': // f: set font to number
- current_env->fontno = get_integer_arg();
- break;
- case 'F': // F: obsolete, replaced by `x F'
- {
- char *str_arg = get_string_arg();
- remember_filename(str_arg);
- delete str_arg;
- break;
- }
- case 'h': // h: relative horizontal move
- current_env->hpos += (EnvInt) get_integer_arg();
- break;
- case 'H': // H: absolute horizontal positioning
- current_env->hpos = (EnvInt) get_integer_arg();
- break;
- case 'm': // m: glyph color
- parse_color_command(current_env->col);
- pr->change_color(current_env);
- break;
- case 'n': // n: print end of line
- // ignore two arguments (historically)
- if (npages <= 0)
- fatal_command(command);
- pr->end_of_line();
- (void) get_integer_arg();
- (void) get_integer_arg();
- break;
- case 'N': // N: print char with given int code
- if (npages <= 0)
- fatal_command(command);
- pr->set_numbered_char(get_integer_arg(), current_env);
- break;
- case 'p': // p: start new page with given number
- if (npages > 0)
- pr->end_page(current_env->vpos);
- npages++; // increment # of processed pages
- pr->begin_page(get_integer_arg());
- current_env->vpos = 0;
- break;
- case 's': // s: set point size
- current_env->size = get_integer_arg();
- if (current_env->height == current_env->size)
- current_env->height = 0;
- break;
- case 't': // t: print a text word
- {
- char c;
- if (npages <= 0)
- fatal_command(command);
- char *str_arg = get_string_arg();
- size_t i = 0;
- while ((c = str_arg[i++]) != '\0') {
- EnvInt w;
- pr->set_ascii_char((unsigned char) c, current_env, &w);
- current_env->hpos += w;
- }
- delete str_arg;
- break;
- }
- case 'u': // u: print spaced word
- {
- char c;
- if (npages <= 0)
- fatal_command(command);
- EnvInt kern = (EnvInt) get_integer_arg();
- char *str_arg = get_string_arg();
- size_t i = 0;
- while ((c = str_arg[i++]) != '\0') {
- EnvInt w;
- pr->set_ascii_char((unsigned char) c, current_env, &w);
- current_env->hpos += w + kern;
- }
- delete str_arg;
- break;
- }
- case 'v': // v: relative vertical move
- current_env->vpos += (EnvInt) get_integer_arg();
- break;
- case 'V': // V: absolute vertical positioning
- current_env->vpos = (EnvInt) get_integer_arg();
- break;
- case 'w': // w: inform about paddable space
- break;
- case 'x': // device controlling commands
- stopped = parse_x_command();
- break;
- default:
- warning("unrecognized command `%1'", (unsigned char) command);
- skip_line();
- break;
- } // end of switch
- } // end of while
-
- // end of file reached
- if (npages > 0)
- pr->end_page(current_env->vpos);
- fclose(current_file);
- // If `stopped' is not `true' here then there wasn't any `x stop'.
- if (!stopped)
- warning("no final `x stop' command");
- delete_current_env();
-}
diff --git a/contrib/groff/src/libs/libdriver/printer.cc b/contrib/groff/src/libs/libdriver/printer.cc
deleted file mode 100644
index c97e2ce..0000000
--- a/contrib/groff/src/libs/libdriver/printer.cc
+++ /dev/null
@@ -1,216 +0,0 @@
-// -*- C++ -*-
-
-// /src/libs/libdriver/printer.cc
-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002
- Free Software Foundation, Inc.
- Written by James Clark (jjc@jclark.com)
-
- Last update: 12 Apr 2002
-
- 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, 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
-*/
-
-#include "driver.h"
-
-printer *pr = 0;
-
-font_pointer_list::font_pointer_list(font *f, font_pointer_list *fp)
-: p(f), next(fp)
-{
-}
-
-printer::printer()
-: font_list(0), font_table(0), nfonts(0)
-{
-}
-
-printer::~printer()
-{
- a_delete font_table;
- while (font_list) {
- font_pointer_list *tem = font_list;
- font_list = font_list->next;
- delete tem->p;
- delete tem;
- }
- if (ferror(stdout) || fflush(stdout) < 0)
- fatal("output error");
-}
-
-void printer::load_font(int n, const char *nm)
-{
- assert(n >= 0);
- if (n >= nfonts) {
- if (nfonts == 0) {
- nfonts = 10;
- if (nfonts <= n)
- nfonts = n + 1;
- font_table = new font *[nfonts];
- for (int i = 0; i < nfonts; i++)
- font_table[i] = 0;
- }
- else {
- font **old_font_table = font_table;
- int old_nfonts = nfonts;
- nfonts *= 2;
- if (n >= nfonts)
- nfonts = n + 1;
- font_table = new font *[nfonts];
- int i;
- for (i = 0; i < old_nfonts; i++)
- font_table[i] = old_font_table[i];
- for (i = old_nfonts; i < nfonts; i++)
- font_table[i] = 0;
- a_delete old_font_table;
- }
- }
- font *f = find_font(nm);
- font_table[n] = f;
-}
-
-font *printer::find_font(const char *nm)
-{
- for (font_pointer_list *p = font_list; p; p = p->next)
- if (strcmp(p->p->get_name(), nm) == 0)
- return p->p;
- font *f = make_font(nm);
- if (!f)
- fatal("sorry, I can't continue");
- font_list = new font_pointer_list(f, font_list);
- return f;
-}
-
-font *printer::make_font(const char *nm)
-{
- return font::load_font(nm);
-}
-
-void printer::end_of_line()
-{
-}
-
-void printer::special(char *, const environment *, char)
-{
-}
-
-void printer::draw(int, int *, int, const environment *)
-{
-}
-
-void printer::change_color(const environment *)
-{
-}
-
-void printer::change_fill_color(const environment *)
-{
-}
-
-void printer::set_ascii_char(unsigned char c, const environment *env,
- int *widthp)
-{
- char buf[2];
- int w;
- font *f;
-
- buf[0] = c;
- buf[1] = '\0';
-
- int i = set_char_and_width(buf, env, &w, &f);
- set_char(i, f, env, w, 0);
- if (widthp) {
- *widthp = w;
- }
-}
-
-void printer::set_special_char(const char *nm, const environment *env,
- int *widthp)
-{
- font *f;
- int w;
- int i = set_char_and_width(nm, env, &w, &f);
- if (i != -1) {
- set_char(i, f, env, w, nm);
- if (widthp)
- *widthp = w;
- }
-}
-
-int printer::set_char_and_width(const char *nm, const environment *env,
- int *widthp, font **f)
-{
- int i = font::name_to_index(nm);
- int fn = env->fontno;
- if (fn < 0 || fn >= nfonts) {
- error("bad font position `%1'", fn);
- return(-1);
- }
- *f = font_table[fn];
- if (*f == 0) {
- error("no font mounted at `%1'", fn);
- return(-1);
- }
- if (!(*f)->contains(i)) {
- if (nm[0] != '\0' && nm[1] == '\0')
- error("font `%1' does not contain ascii character `%2'",
- (*f)->get_name(),
- nm[0]);
- else
- error("font `%1' does not contain special character `%2'",
- (*f)->get_name(),
- nm);
- return(-1);
- }
- int w = (*f)->get_width(i, env->size);
- if (widthp)
- *widthp = w;
- return( i );
-}
-
-void printer::set_numbered_char(int num, const environment *env, int *widthp)
-{
- int i = font::number_to_index(num);
- int fn = env->fontno;
- if (fn < 0 || fn >= nfonts) {
- error("bad font position `%1'", fn);
- return;
- }
- font *f = font_table[fn];
- if (f == 0) {
- error("no font mounted at `%1'", fn);
- return;
- }
- if (!f->contains(i)) {
- error("font `%1' does not contain numbered character %2",
- f->get_name(),
- num);
- return;
- }
- int w = f->get_width(i, env->size);
- if (widthp)
- *widthp = w;
- set_char(i, f, env, w, 0);
-}
-
-font *printer::get_font_from_index(int fontno)
-{
- if ((fontno >= 0) && (fontno < nfonts))
- return(font_table[fontno]);
- else
- return(0);
-}
diff --git a/contrib/groff/src/libs/libgroff/assert.cc b/contrib/groff/src/libs/libgroff/assert.cc
deleted file mode 100644
index 89742e3..0000000
--- a/contrib/groff/src/libs/libgroff/assert.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-/* 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include
-#include
-#include "assert.h"
-
-extern const char *program_name;
-
-void assertion_failed(int lineno, const char *filename)
-{
- if (program_name != 0)
- fprintf(stderr, "%s: ", program_name);
- fprintf(stderr, "Failed assertion at line %d, file `%s'.\n",
- lineno, filename);
- fflush(stderr);
- abort();
-}
diff --git a/contrib/groff/src/libs/libgroff/change_lf.cc b/contrib/groff/src/libs/libgroff/change_lf.cc
deleted file mode 100644
index 2e44af1..0000000
--- a/contrib/groff/src/libs/libgroff/change_lf.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-/* 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include
-
-extern char *strsave(const char *);
-
-extern const char *current_filename;
-extern int current_lineno;
-
-void change_filename(const char *f)
-{
- if (current_filename != 0 && strcmp(current_filename, f) == 0)
- return;
- current_filename = strsave(f);
-}
-
-void change_lineno(int ln)
-{
- current_lineno = ln;
-}
diff --git a/contrib/groff/src/libs/libgroff/color.cc b/contrib/groff/src/libs/libgroff/color.cc
deleted file mode 100644
index 68e604c..0000000
--- a/contrib/groff/src/libs/libgroff/color.cc
+++ /dev/null
@@ -1,363 +0,0 @@
-// -*- C++ -*-
-
-/* /src/libs/libgroff/color.cc
-
-Last update: 10 Apr 2002
-
-Copyright (C) 2001, 2002 Free Software Foundation, Inc.
- Written by Gaius Mulley
-
-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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "color.h"
-#include "cset.h"
-#ifdef HAVE_UNISTD_H
-#include
-#endif
-
-#include
-#include
-#include
-#include
-#include "errarg.h"
-#include "error.h"
-
-static inline unsigned int
-min(const unsigned int a, const unsigned int b)
-{
- if (a < b)
- return a;
- else
- return b;
-}
-
-color::color(const color * const c)
-{
- scheme = c->scheme;
- components[0] = c->components[0];
- components[1] = c->components[1];
- components[2] = c->components[2];
- components[3] = c->components[3];
-}
-
-int color::operator==(const color & c) const
-{
- if (scheme != c.scheme)
- return 0;
- switch (scheme) {
- case DEFAULT:
- break;
- case RGB:
- if (Red != c.Red || Green != c.Green || Blue != c.Blue)
- return 0;
- break;
- case CMYK:
- if (Cyan != c.Cyan || Magenta != c.Magenta
- || Yellow != c.Yellow || Black != c.Black)
- return 0;
- break;
- case GRAY:
- if (Gray != c.Gray)
- return 0;
- break;
- case CMY:
- if (Cyan != c.Cyan || Magenta != c.Magenta || Yellow != c.Yellow)
- return 0;
- break;
- }
- return 1;
-}
-
-int color::operator!=(const color & c) const
-{
- return !(*this == c);
-}
-
-color_scheme color::get_components(unsigned int *c) const
-{
-#if 0
- if (sizeof (c) < sizeof (unsigned int) * 4)
- fatal("argument is not big enough to store 4 color components");
-#endif
- c[0] = components[0];
- c[1] = components[1];
- c[2] = components[2];
- c[3] = components[3];
- return scheme;
-}
-
-void color::set_default()
-{
- scheme = DEFAULT;
-}
-
-// (0, 0, 0) is black
-
-void color::set_rgb(const unsigned int r, const unsigned int g,
- const unsigned int b)
-{
- scheme = RGB;
- Red = min(MAX_COLOR_VAL, r);
- Green = min(MAX_COLOR_VAL, g);
- Blue = min(MAX_COLOR_VAL, b);
-}
-
-// (0, 0, 0) is white
-
-void color::set_cmy(const unsigned int c, const unsigned int m,
- const unsigned int y)
-{
- scheme = CMY;
- Cyan = min(MAX_COLOR_VAL, c);
- Magenta = min(MAX_COLOR_VAL, m);
- Yellow = min(MAX_COLOR_VAL, y);
-}
-
-// (0, 0, 0, 0) is white
-
-void color::set_cmyk(const unsigned int c, const unsigned int m,
- const unsigned int y, const unsigned int k)
-{
- scheme = CMYK;
- Cyan = min(MAX_COLOR_VAL, c);
- Magenta = min(MAX_COLOR_VAL, m);
- Yellow = min(MAX_COLOR_VAL, y);
- Black = min(MAX_COLOR_VAL, k);
-}
-
-// (0) is black
-
-void color::set_gray(const unsigned int g)
-{
- scheme = GRAY;
- Gray = min(MAX_COLOR_VAL, g);
-}
-
-/*
- * atoh - computes the decimal value of a hexadecimal number string.
- * `length' characters of `s' are read. Returns 1 if successful.
- */
-
-static int atoh(unsigned int *result,
- const char * const s, const size_t length)
-{
- size_t i = 0;
- unsigned int val = 0;
- while ((i < length) && csxdigit(s[i])) {
- if (csdigit(s[i]))
- val = val*0x10 + (s[i]-'0');
- else if (csupper(s[i]))
- val = val*0x10 + (s[i]-'A') + 10;
- else
- val = val*0x10 + (s[i]-'a') + 10;
- i++;
- }
- if (i != length)
- return 0;
- *result = val;
- return 1;
-}
-
-/*
- * read_encoding - set color from a hexadecimal color string.
- *
- * Use color scheme `cs' to parse `n' color components from string `s'.
- * Returns 1 if successful.
- */
-
-int color::read_encoding(const color_scheme cs, const char * const s,
- const size_t n)
-{
- size_t hex_length = 2;
- scheme = cs;
- char *p = (char *) s;
- p++;
- if (*p == '#') {
- hex_length = 4;
- p++;
- }
- for (size_t i = 0; i < n; i++) {
- if (!atoh(&(components[i]), p, hex_length))
- return 0;
- if (hex_length == 2)
- components[i] *= 0x101; // scale up -- 0xff should become 0xffff
- p += hex_length;
- }
- return 1;
-}
-
-int color::read_rgb(const char * const s)
-{
- return read_encoding(RGB, s, 3);
-}
-
-int color::read_cmy(const char * const s)
-{
- return read_encoding(CMY, s, 3);
-}
-
-int color::read_cmyk(const char * const s)
-{
- return read_encoding(CMYK, s, 4);
-}
-
-int color::read_gray(const char * const s)
-{
- return read_encoding(GRAY, s, 1);
-}
-
-void
-color::get_rgb(unsigned int *r, unsigned int *g, unsigned int *b) const
-{
- switch (scheme) {
- case RGB:
- *r = Red;
- *g = Green;
- *b = Blue;
- break;
- case CMY:
- *r = MAX_COLOR_VAL - Cyan;
- *g = MAX_COLOR_VAL - Magenta;
- *b = MAX_COLOR_VAL - Yellow;
- break;
- case CMYK:
- *r = MAX_COLOR_VAL
- - min(MAX_COLOR_VAL,
- Cyan * (MAX_COLOR_VAL - Black) / MAX_COLOR_VAL + Black);
- *g = MAX_COLOR_VAL
- - min(MAX_COLOR_VAL,
- Magenta * (MAX_COLOR_VAL - Black) / MAX_COLOR_VAL + Black);
- *b = MAX_COLOR_VAL
- - min(MAX_COLOR_VAL,
- Yellow * (MAX_COLOR_VAL - Black) / MAX_COLOR_VAL + Black);
- break;
- case GRAY:
- *r = *g = *b = Gray;
- break;
- default:
- assert(0);
- break;
- }
-}
-
-void
-color::get_cmy(unsigned int *c, unsigned int *m, unsigned int *y) const
-{
- switch (scheme) {
- case RGB:
- *c = MAX_COLOR_VAL - Red;
- *m = MAX_COLOR_VAL - Green;
- *y = MAX_COLOR_VAL - Blue;
- break;
- case CMY:
- *c = Cyan;
- *m = Magenta;
- *y = Yellow;
- break;
- case CMYK:
- *c = min(MAX_COLOR_VAL,
- Cyan * (MAX_COLOR_VAL - Black) / MAX_COLOR_VAL + Black);
- *m = min(MAX_COLOR_VAL,
- Magenta * (MAX_COLOR_VAL - Black) / MAX_COLOR_VAL + Black);
- *y = min(MAX_COLOR_VAL,
- Yellow * (MAX_COLOR_VAL - Black) / MAX_COLOR_VAL + Black);
- break;
- case GRAY:
- *c = *m = *y = MAX_COLOR_VAL - Gray;
- break;
- default:
- assert(0);
- break;
- }
-}
-
-void color::get_cmyk(unsigned int *c, unsigned int *m,
- unsigned int *y, unsigned int *k) const
-{
- switch (scheme) {
- case RGB:
- *k = min(MAX_COLOR_VAL - Red,
- min(MAX_COLOR_VAL - Green, MAX_COLOR_VAL - Blue));
- if (MAX_COLOR_VAL == *k) {
- *c = MAX_COLOR_VAL;
- *m = MAX_COLOR_VAL;
- *y = MAX_COLOR_VAL;
- }
- else {
- *c = (MAX_COLOR_VAL * (MAX_COLOR_VAL - Red - *k))
- / (MAX_COLOR_VAL - *k);
- *m = (MAX_COLOR_VAL * (MAX_COLOR_VAL - Green - *k))
- / (MAX_COLOR_VAL - *k);
- *y = (MAX_COLOR_VAL * (MAX_COLOR_VAL - Blue - *k))
- / (MAX_COLOR_VAL - *k);
- }
- break;
- case CMY:
- *k = min(Cyan, min(Magenta, Yellow));
- if (MAX_COLOR_VAL == *k) {
- *c = MAX_COLOR_VAL;
- *m = MAX_COLOR_VAL;
- *y = MAX_COLOR_VAL;
- }
- else {
- *c = (MAX_COLOR_VAL * (Cyan - *k)) / (MAX_COLOR_VAL - *k);
- *m = (MAX_COLOR_VAL * (Magenta - *k)) / (MAX_COLOR_VAL - *k);
- *y = (MAX_COLOR_VAL * (Yellow - *k)) / (MAX_COLOR_VAL - *k);
- }
- break;
- case CMYK:
- *c = Cyan;
- *m = Magenta;
- *y = Yellow;
- *k = Black;
- break;
- case GRAY:
- *c = *m = *y = 0;
- *k = MAX_COLOR_VAL - Gray;
- break;
- default:
- assert(0);
- break;
- }
-}
-
-// we use `0.222r + 0.707g + 0.071b' (this is the ITU standard)
-// as an approximation for gray
-
-void color::get_gray(unsigned int *g) const
-{
- switch (scheme) {
- case RGB:
- *g = (222*Red + 707*Green + 71*Blue) / 1000;
- break;
- case CMY:
- *g = MAX_COLOR_VAL - (222*Cyan + 707*Magenta + 71*Yellow) / 1000;
- break;
- case CMYK:
- *g = (MAX_COLOR_VAL - (222*Cyan + 707*Magenta + 71*Yellow) / 1000)
- * (MAX_COLOR_VAL - Black);
- break;
- case GRAY:
- *g = Gray;
- break;
- default:
- assert(0);
- break;
- }
-}
-
-color default_color;
diff --git a/contrib/groff/src/libs/libgroff/device.cc b/contrib/groff/src/libs/libgroff/device.cc
deleted file mode 100644
index 7efbfef..0000000
--- a/contrib/groff/src/libs/libgroff/device.cc
+++ /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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include
-#include "device.h"
-#include "defs.h"
-
-const char *device = DEVICE;
-
-struct device_init {
- device_init();
-} _device_init;
-
-device_init::device_init()
-{
- char *tem = getenv("GROFF_TYPESETTER");
- if (tem)
- device = tem;
-}
diff --git a/contrib/groff/src/libs/libgroff/errarg.cc b/contrib/groff/src/libs/libgroff/errarg.cc
deleted file mode 100644
index 2ddc0cc..0000000
--- a/contrib/groff/src/libs/libgroff/errarg.cc
+++ /dev/null
@@ -1,128 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include
-#include "assert.h"
-#include "errarg.h"
-
-errarg::errarg(const char *p) : type(STRING)
-{
- s = p ? p : "(null)";
-}
-
-errarg::errarg() : type(EMPTY)
-{
-}
-
-errarg::errarg(int nn) : type(INTEGER)
-{
- n = nn;
-}
-
-errarg::errarg(unsigned int uu) : type(UNSIGNED_INTEGER)
-{
- u = uu;
-}
-
-errarg::errarg(char cc) : type(CHAR)
-{
- c = cc;
-}
-
-errarg::errarg(unsigned char cc) : type(CHAR)
-{
- c = cc;
-}
-
-errarg::errarg(double dd) : type(DOUBLE)
-{
- d = dd;
-}
-
-int errarg::empty() const
-{
- return type == EMPTY;
-}
-
-extern "C" {
- const char *i_to_a(int);
- const char *ui_to_a(unsigned int);
-}
-
-void errarg::print() const
-{
- switch (type) {
- case INTEGER:
- fputs(i_to_a(n), stderr);
- break;
- case UNSIGNED_INTEGER:
- fputs(ui_to_a(u), stderr);
- break;
- case CHAR:
- putc(c, stderr);
- break;
- case STRING:
- fputs(s, stderr);
- break;
- case DOUBLE:
- fprintf(stderr, "%g", d);
- break;
- case EMPTY:
- break;
- }
-}
-
-errarg empty_errarg;
-
-void errprint(const char *format,
- const errarg &arg1,
- const errarg &arg2,
- const errarg &arg3)
-{
- assert(format != 0);
- char c;
- while ((c = *format++) != '\0') {
- if (c == '%') {
- c = *format++;
- switch(c) {
- case '%':
- fputc('%', stderr);
- break;
- case '1':
- assert(!arg1.empty());
- arg1.print();
- break;
- case '2':
- assert(!arg2.empty());
- arg2.print();
- break;
- case '3':
- assert(!arg3.empty());
- arg3.print();
- break;
- default:
- assert(0);
- }
- }
- else
- putc(c, stderr);
- }
-}
diff --git a/contrib/groff/src/libs/libgroff/error.cc b/contrib/groff/src/libs/libgroff/error.cc
deleted file mode 100644
index 53fd629..0000000
--- a/contrib/groff/src/libs/libgroff/error.cc
+++ /dev/null
@@ -1,137 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include
-#include
-#include
-#include "errarg.h"
-#include "error.h"
-
-extern void fatal_error_exit();
-
-enum error_type { WARNING, ERROR, FATAL };
-
-static void do_error_with_file_and_line(const char *filename, int lineno,
- error_type type,
- const char *format,
- const errarg &arg1,
- const errarg &arg2,
- const errarg &arg3)
-{
- int need_space = 0;
- if (program_name) {
- fprintf(stderr, "%s:", program_name);
- need_space = 1;
- }
- if (lineno >= 0 && filename != 0) {
- if (strcmp(filename, "-") == 0)
- filename = "";
- fprintf(stderr, "%s:%d:", filename, lineno);
- need_space = 1;
- }
- switch (type) {
- case FATAL:
- fputs("fatal error:", stderr);
- need_space = 1;
- break;
- case ERROR:
- break;
- case WARNING:
- fputs("warning:", stderr);
- need_space = 1;
- break;
- }
- if (need_space)
- fputc(' ', stderr);
- errprint(format, arg1, arg2, arg3);
- fputc('\n', stderr);
- fflush(stderr);
- if (type == FATAL)
- fatal_error_exit();
-}
-
-
-static void do_error(error_type type,
- const char *format,
- const errarg &arg1,
- const errarg &arg2,
- const errarg &arg3)
-{
- do_error_with_file_and_line(current_filename, current_lineno,
- type, format, arg1, arg2, arg3);
-}
-
-
-void error(const char *format,
- const errarg &arg1,
- const errarg &arg2,
- const errarg &arg3)
-{
- do_error(ERROR, format, arg1, arg2, arg3);
-}
-
-void warning(const char *format,
- const errarg &arg1,
- const errarg &arg2,
- const errarg &arg3)
-{
- do_error(WARNING, format, arg1, arg2, arg3);
-}
-
-void fatal(const char *format,
- const errarg &arg1,
- const errarg &arg2,
- const errarg &arg3)
-{
- do_error(FATAL, format, arg1, arg2, arg3);
-}
-
-void error_with_file_and_line(const char *filename,
- int lineno,
- const char *format,
- const errarg &arg1,
- const errarg &arg2,
- const errarg &arg3)
-{
- do_error_with_file_and_line(filename, lineno,
- ERROR, format, arg1, arg2, arg3);
-}
-
-void warning_with_file_and_line(const char *filename,
- int lineno,
- const char *format,
- const errarg &arg1,
- const errarg &arg2,
- const errarg &arg3)
-{
- do_error_with_file_and_line(filename, lineno,
- WARNING, format, arg1, arg2, arg3);
-}
-
-void fatal_with_file_and_line(const char *filename,
- int lineno,
- const char *format,
- const errarg &arg1,
- const errarg &arg2,
- const errarg &arg3)
-{
- do_error_with_file_and_line(filename, lineno,
- FATAL, format, arg1, arg2, arg3);
-}
diff --git a/contrib/groff/src/libs/libgroff/fatal.cc b/contrib/groff/src/libs/libgroff/fatal.cc
deleted file mode 100644
index 42560dc..0000000
--- a/contrib/groff/src/libs/libgroff/fatal.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-/* 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include
-
-#define FATAL_ERROR_EXIT_CODE 3
-
-void fatal_error_exit()
-{
- exit(FATAL_ERROR_EXIT_CODE);
-}
diff --git a/contrib/groff/src/libs/libgroff/filename.cc b/contrib/groff/src/libs/libgroff/filename.cc
deleted file mode 100644
index 1cbaa93..0000000
--- a/contrib/groff/src/libs/libgroff/filename.cc
+++ /dev/null
@@ -1 +0,0 @@
-const char *current_filename = 0;
diff --git a/contrib/groff/src/libs/libgroff/font.cc b/contrib/groff/src/libs/libgroff/font.cc
deleted file mode 100644
index 69e46e1..0000000
--- a/contrib/groff/src/libs/libgroff/font.cc
+++ /dev/null
@@ -1,1035 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "lib.h"
-
-#include
-#include
-#include
-#include
-#include "errarg.h"
-#include "error.h"
-#include "cset.h"
-#include "font.h"
-#include "paper.h"
-
-const char *const WS = " \t\n\r";
-
-struct font_char_metric {
- char type;
- int code;
- int width;
- int height;
- int depth;
- int pre_math_space;
- int italic_correction;
- int subscript_correction;
- char *special_device_coding;
-};
-
-struct font_kern_list {
- int i1;
- int i2;
- int amount;
- font_kern_list *next;
-
- font_kern_list(int, int, int, font_kern_list * = 0);
-};
-
-struct font_widths_cache {
- font_widths_cache *next;
- int point_size;
- int *width;
-
- font_widths_cache(int, int, font_widths_cache * = 0);
- ~font_widths_cache();
-};
-
-/* text_file */
-
-struct text_file {
- FILE *fp;
- char *path;
- int lineno;
- int size;
- int skip_comments;
- char *buf;
- text_file(FILE *fp, char *p);
- ~text_file();
- int next();
- void error(const char *format,
- const errarg &arg1 = empty_errarg,
- const errarg &arg2 = empty_errarg,
- const errarg &arg3 = empty_errarg);
-};
-
-text_file::text_file(FILE *p, char *s)
-: fp(p), path(s), lineno(0), size(0), skip_comments(1), buf(0)
-{
-}
-
-text_file::~text_file()
-{
- a_delete buf;
- a_delete path;
- if (fp)
- fclose(fp);
-}
-
-int text_file::next()
-{
- if (fp == 0)
- return 0;
- if (buf == 0) {
- buf = new char[128];
- size = 128;
- }
- for (;;) {
- int i = 0;
- for (;;) {
- int c = getc(fp);
- if (c == EOF)
- break;
- if (invalid_input_char(c))
- error("invalid input character code `%1'", int(c));
- else {
- if (i + 1 >= size) {
- char *old_buf = buf;
- buf = new char[size*2];
- memcpy(buf, old_buf, size);
- a_delete old_buf;
- size *= 2;
- }
- buf[i++] = c;
- if (c == '\n')
- break;
- }
- }
- if (i == 0)
- break;
- buf[i] = '\0';
- lineno++;
- char *ptr = buf;
- while (csspace(*ptr))
- ptr++;
- if (*ptr != 0 && (!skip_comments || *ptr != '#'))
- return 1;
- }
- return 0;
-}
-
-void text_file::error(const char *format,
- const errarg &arg1,
- const errarg &arg2,
- const errarg &arg3)
-{
- error_with_file_and_line(path, lineno, format, arg1, arg2, arg3);
-}
-
-
-/* font functions */
-
-font::font(const char *s)
-: ligatures(0), kern_hash_table(0), space_width(0), ch_index(0), nindices(0),
- ch(0), ch_used(0), ch_size(0), special(0), widths_cache(0)
-{
- name = new char[strlen(s) + 1];
- strcpy(name, s);
- internalname = 0;
- slant = 0.0;
- // load(); // for testing
-}
-
-font::~font()
-{
- for (int i = 0; i < ch_used; i++)
- if (ch[i].special_device_coding)
- a_delete ch[i].special_device_coding;
- a_delete ch;
- a_delete ch_index;
- if (kern_hash_table) {
- for (int i = 0; i < KERN_HASH_TABLE_SIZE; i++) {
- font_kern_list *kerns = kern_hash_table[i];
- while (kerns) {
- font_kern_list *tem = kerns;
- kerns = kerns->next;
- delete tem;
- }
- }
- a_delete kern_hash_table;
- }
- a_delete name;
- a_delete internalname;
- while (widths_cache) {
- font_widths_cache *tem = widths_cache;
- widths_cache = widths_cache->next;
- delete tem;
- }
-}
-
-static int scale_round(int n, int x, int y)
-{
- assert(x >= 0 && y > 0);
- int y2 = y/2;
- if (x == 0)
- return 0;
- if (n >= 0) {
- if (n <= (INT_MAX - y2)/x)
- return (n*x + y2)/y;
- return int(n*double(x)/double(y) + .5);
- }
- else {
- if (-(unsigned)n <= (-(unsigned)INT_MIN - y2)/x)
- return (n*x - y2)/y;
- return int(n*double(x)/double(y) - .5);
- }
-}
-
-inline int font::scale(int w, int sz)
-{
- return sz == unitwidth ? w : scale_round(w, sz, unitwidth);
-}
-
-int font::unit_scale(double *value, char unit)
-{
- // we scale everything to inch
- double divisor = 0;
- switch (unit) {
- case 'i':
- divisor = 1;
- break;
- case 'p':
- divisor = 72;
- break;
- case 'P':
- divisor = 6;
- break;
- case 'c':
- divisor = 2.54;
- break;
- default:
- assert(0);
- break;
- }
- if (divisor) {
- *value /= divisor;
- return 1;
- }
- return 0;
-}
-
-int font::get_skew(int c, int point_size, int sl)
-{
- int h = get_height(c, point_size);
- return int(h*tan((slant+sl)*PI/180.0) + .5);
-}
-
-int font::contains(int c)
-{
- return c >= 0 && c < nindices && ch_index[c] >= 0;
-}
-
-int font::is_special()
-{
- return special;
-}
-
-font_widths_cache::font_widths_cache(int ps, int ch_size,
- font_widths_cache *p)
-: next(p), point_size(ps)
-{
- width = new int[ch_size];
- for (int i = 0; i < ch_size; i++)
- width[i] = -1;
-}
-
-font_widths_cache::~font_widths_cache()
-{
- a_delete width;
-}
-
-int font::get_width(int c, int point_size)
-{
- assert(c >= 0 && c < nindices);
- int i = ch_index[c];
- assert(i >= 0);
-
- if (point_size == unitwidth)
- return ch[i].width;
-
- if (!widths_cache)
- widths_cache = new font_widths_cache(point_size, ch_size);
- else if (widths_cache->point_size != point_size) {
- font_widths_cache **p;
- for (p = &widths_cache; *p; p = &(*p)->next)
- if ((*p)->point_size == point_size)
- break;
- if (*p) {
- font_widths_cache *tem = *p;
- *p = (*p)->next;
- tem->next = widths_cache;
- widths_cache = tem;
- }
- else
- widths_cache = new font_widths_cache(point_size, ch_size, widths_cache);
- }
- int &w = widths_cache->width[i];
- if (w < 0)
- w = scale(ch[i].width, point_size);
- return w;
-}
-
-int font::get_height(int c, int point_size)
-{
- assert(c >= 0 && c < nindices && ch_index[c] >= 0);
- return scale(ch[ch_index[c]].height, point_size);
-}
-
-int font::get_depth(int c, int point_size)
-{
- assert(c >= 0 && c < nindices && ch_index[c] >= 0);
- return scale(ch[ch_index[c]].depth, point_size);
-}
-
-int font::get_italic_correction(int c, int point_size)
-{
- assert(c >= 0 && c < nindices && ch_index[c] >= 0);
- return scale(ch[ch_index[c]].italic_correction, point_size);
-}
-
-int font::get_left_italic_correction(int c, int point_size)
-{
- assert(c >= 0 && c < nindices && ch_index[c] >= 0);
- return scale(ch[ch_index[c]].pre_math_space, point_size);
-}
-
-int font::get_subscript_correction(int c, int point_size)
-{
- assert(c >= 0 && c < nindices && ch_index[c] >= 0);
- return scale(ch[ch_index[c]].subscript_correction, point_size);
-}
-
-int font::get_space_width(int point_size)
-{
- return scale(space_width, point_size);
-}
-
-font_kern_list::font_kern_list(int c1, int c2, int n, font_kern_list *p)
-: i1(c1), i2(c2), amount(n), next(p)
-{
-}
-
-inline int font::hash_kern(int i1, int i2)
-{
- int n = ((i1 << 10) + i2) % KERN_HASH_TABLE_SIZE;
- return n < 0 ? -n : n;
-}
-
-void font::add_kern(int i1, int i2, int amount)
-{
- if (!kern_hash_table) {
- kern_hash_table = new font_kern_list *[KERN_HASH_TABLE_SIZE];
- for (int i = 0; i < KERN_HASH_TABLE_SIZE; i++)
- kern_hash_table[i] = 0;
- }
- font_kern_list **p = kern_hash_table + hash_kern(i1, i2);
- *p = new font_kern_list(i1, i2, amount, *p);
-}
-
-int font::get_kern(int i1, int i2, int point_size)
-{
- if (kern_hash_table) {
- for (font_kern_list *p = kern_hash_table[hash_kern(i1, i2)]; p; p = p->next)
- if (i1 == p->i1 && i2 == p->i2)
- return scale(p->amount, point_size);
- }
- return 0;
-}
-
-int font::has_ligature(int mask)
-{
- return mask & ligatures;
-}
-
-int font::get_character_type(int c)
-{
- assert(c >= 0 && c < nindices && ch_index[c] >= 0);
- return ch[ch_index[c]].type;
-}
-
-int font::get_code(int c)
-{
- assert(c >= 0 && c < nindices && ch_index[c] >= 0);
- return ch[ch_index[c]].code;
-}
-
-const char *font::get_name()
-{
- return name;
-}
-
-const char *font::get_internal_name()
-{
- return internalname;
-}
-
-const char *font::get_special_device_encoding(int c)
-{
- assert(c >= 0 && c < nindices && ch_index[c] >= 0);
- return( ch[ch_index[c]].special_device_coding );
-}
-
-void font::alloc_ch_index(int index)
-{
- if (nindices == 0) {
- nindices = 128;
- if (index >= nindices)
- nindices = index + 10;
- ch_index = new short[nindices];
- for (int i = 0; i < nindices; i++)
- ch_index[i] = -1;
- }
- else {
- int old_nindices = nindices;
- nindices *= 2;
- if (index >= nindices)
- nindices = index + 10;
- short *old_ch_index = ch_index;
- ch_index = new short[nindices];
- memcpy(ch_index, old_ch_index, sizeof(short)*old_nindices);
- for (int i = old_nindices; i < nindices; i++)
- ch_index[i] = -1;
- a_delete old_ch_index;
- }
-}
-
-void font::extend_ch()
-{
- if (ch == 0)
- ch = new font_char_metric[ch_size = 16];
- else {
- int old_ch_size = ch_size;
- ch_size *= 2;
- font_char_metric *old_ch = ch;
- ch = new font_char_metric[ch_size];
- memcpy(ch, old_ch, old_ch_size*sizeof(font_char_metric));
- a_delete old_ch;
- }
-}
-
-void font::compact()
-{
- int i;
- for (i = nindices - 1; i >= 0; i--)
- if (ch_index[i] >= 0)
- break;
- i++;
- if (i < nindices) {
- short *old_ch_index = ch_index;
- ch_index = new short[i];
- memcpy(ch_index, old_ch_index, i*sizeof(short));
- a_delete old_ch_index;
- nindices = i;
- }
- if (ch_used < ch_size) {
- font_char_metric *old_ch = ch;
- ch = new font_char_metric[ch_used];
- memcpy(ch, old_ch, ch_used*sizeof(font_char_metric));
- a_delete old_ch;
- ch_size = ch_used;
- }
-}
-
-void font::add_entry(int index, const font_char_metric &metric)
-{
- assert(index >= 0);
- if (index >= nindices)
- alloc_ch_index(index);
- assert(index < nindices);
- if (ch_used + 1 >= ch_size)
- extend_ch();
- assert(ch_used + 1 < ch_size);
- ch_index[index] = ch_used;
- ch[ch_used++] = metric;
-}
-
-void font::copy_entry(int new_index, int old_index)
-{
- assert(new_index >= 0 && old_index >= 0 && old_index < nindices);
- if (new_index >= nindices)
- alloc_ch_index(new_index);
- ch_index[new_index] = ch_index[old_index];
-}
-
-font *font::load_font(const char *s, int *not_found)
-{
- font *f = new font(s);
- if (!f->load(not_found)) {
- delete f;
- return 0;
- }
- return f;
-}
-
-static char *trim_arg(char *p)
-{
- if (!p)
- return 0;
- while (csspace(*p))
- p++;
- char *q = strchr(p, '\0');
- while (q > p && csspace(q[-1]))
- q--;
- *q = '\0';
- return p;
-}
-
-int font::scan_papersize(const char *p,
- const char **size, double *length, double *width)
-{
- double l, w;
- char lu[2], wu[2];
- const char *pp = p;
- int test_file = 1;
- char line[255];
-again:
- if (csdigit(*pp)) {
- if (sscanf(pp, "%lf%1[ipPc],%lf%1[ipPc]", &l, lu, &w, wu) == 4
- && l > 0 && w > 0
- && unit_scale(&l, lu[0]) && unit_scale(&w, wu[0])) {
- if (length)
- *length = l;
- if (width)
- *width = w;
- if (size)
- *size = "custom";
- return 1;
- }
- }
- else {
- int i;
- for (i = 0; i < NUM_PAPERSIZES; i++)
- if (strcasecmp(papersizes[i].name, pp) == 0) {
- if (length)
- *length = papersizes[i].length;
- if (width)
- *width = papersizes[i].width;
- if (size)
- *size = papersizes[i].name;
- return 1;
- }
- if (test_file) {
- FILE *f = fopen(p, "r");
- if (f) {
- fgets(line, 254, f);
- fclose(f);
- test_file = 0;
- char *linep = strchr(line, '\0');
- // skip final newline, if any
- if (*(--linep) == '\n')
- *linep = '\0';
- pp = line;
- goto again;
- }
- }
- }
- return 0;
-}
-
-// If the font can't be found, then if not_found is non-NULL, it will be set
-// to 1 otherwise a message will be printed.
-
-int font::load(int *not_found)
-{
- char *path;
- FILE *fp;
- if ((fp = open_file(name, &path)) == NULL) {
- if (not_found)
- *not_found = 1;
- else
- error("can't find font file `%1'", name);
- return 0;
- }
- text_file t(fp, path);
- t.skip_comments = 1;
- char *p;
- for (;;) {
- if (!t.next()) {
- t.error("missing charset command");
- return 0;
- }
- p = strtok(t.buf, WS);
- if (strcmp(p, "name") == 0) {
- }
- else if (strcmp(p, "spacewidth") == 0) {
- p = strtok(0, WS);
- int n;
- if (p == 0 || sscanf(p, "%d", &n) != 1 || n <= 0) {
- t.error("bad argument for spacewidth command");
- return 0;
- }
- space_width = n;
- }
- else if (strcmp(p, "slant") == 0) {
- p = strtok(0, WS);
- double n;
- if (p == 0 || sscanf(p, "%lf", &n) != 1 || n >= 90.0 || n <= -90.0) {
- t.error("bad argument for slant command", p);
- return 0;
- }
- slant = n;
- }
- else if (strcmp(p, "ligatures") == 0) {
- for (;;) {
- p = strtok(0, WS);
- if (p == 0 || strcmp(p, "0") == 0)
- break;
- if (strcmp(p, "ff") == 0)
- ligatures |= LIG_ff;
- else if (strcmp(p, "fi") == 0)
- ligatures |= LIG_fi;
- else if (strcmp(p, "fl") == 0)
- ligatures |= LIG_fl;
- else if (strcmp(p, "ffi") == 0)
- ligatures |= LIG_ffi;
- else if (strcmp(p, "ffl") == 0)
- ligatures |= LIG_ffl;
- else {
- t.error("unrecognised ligature `%1'", p);
- return 0;
- }
- }
- }
- else if (strcmp(p, "internalname") == 0) {
- p = strtok(0, WS);
- if (!p) {
- t.error("`internalname command requires argument");
- return 0;
- }
- internalname = new char[strlen(p) + 1];
- strcpy(internalname, p);
- }
- else if (strcmp(p, "special") == 0) {
- special = 1;
- }
- else if (strcmp(p, "kernpairs") != 0 && strcmp(p, "charset") != 0) {
- char *command = p;
- p = strtok(0, "\n");
- handle_unknown_font_command(command, trim_arg(p), t.path, t.lineno);
- }
- else
- break;
- }
- char *command = p;
- int had_charset = 0;
- t.skip_comments = 0;
- while (command) {
- if (strcmp(command, "kernpairs") == 0) {
- for (;;) {
- if (!t.next()) {
- command = 0;
- break;
- }
- char *c1 = strtok(t.buf, WS);
- if (c1 == 0)
- continue;
- char *c2 = strtok(0, WS);
- if (c2 == 0) {
- command = c1;
- break;
- }
- p = strtok(0, WS);
- if (p == 0) {
- t.error("missing kern amount");
- return 0;
- }
- int n;
- if (sscanf(p, "%d", &n) != 1) {
- t.error("bad kern amount `%1'", p);
- return 0;
- }
- int i1 = name_to_index(c1);
- if (i1 < 0) {
- t.error("invalid character `%1'", c1);
- return 0;
- }
- int i2 = name_to_index(c2);
- if (i2 < 0) {
- t.error("invalid character `%1'", c2);
- return 0;
- }
- add_kern(i1, i2, n);
- }
- }
- else if (strcmp(command, "charset") == 0) {
- had_charset = 1;
- int last_index = -1;
- for (;;) {
- if (!t.next()) {
- command = 0;
- break;
- }
- char *nm = strtok(t.buf, WS);
- if (nm == 0)
- continue; // I dont think this should happen
- p = strtok(0, WS);
- if (p == 0) {
- command = nm;
- break;
- }
- if (p[0] == '"') {
- if (last_index == -1) {
- t.error("first charset entry is duplicate");
- return 0;
- }
- if (strcmp(nm, "---") == 0) {
- t.error("unnamed character cannot be duplicate");
- return 0;
- }
- int index = name_to_index(nm);
- if (index < 0) {
- t.error("invalid character `%1'", nm);
- return 0;
- }
- copy_entry(index, last_index);
- }
- else {
- font_char_metric metric;
- metric.height = 0;
- metric.depth = 0;
- metric.pre_math_space = 0;
- metric.italic_correction = 0;
- metric.subscript_correction = 0;
- int nparms = sscanf(p, "%d,%d,%d,%d,%d,%d",
- &metric.width, &metric.height, &metric.depth,
- &metric.italic_correction,
- &metric.pre_math_space,
- &metric.subscript_correction);
- if (nparms < 1) {
- t.error("bad width for `%1'", nm);
- return 0;
- }
- p = strtok(0, WS);
- if (p == 0) {
- t.error("missing character type for `%1'", nm);
- return 0;
- }
- int type;
- if (sscanf(p, "%d", &type) != 1) {
- t.error("bad character type for `%1'", nm);
- return 0;
- }
- if (type < 0 || type > 255) {
- t.error("character code `%1' out of range", type);
- return 0;
- }
- metric.type = type;
- p = strtok(0, WS);
- if (p == 0) {
- t.error("missing code for `%1'", nm);
- return 0;
- }
- char *ptr;
- metric.code = (int)strtol(p, &ptr, 0);
- if (metric.code == 0 && ptr == p) {
- t.error("bad code `%1' for character `%2'", p, nm);
- return 0;
- }
- p = strtok(0, WS);
- if ((p == NULL) || (strcmp(p, "--") == 0)) {
- metric.special_device_coding = NULL;
- }
- else {
- char *name = new char[strlen(p) + 1];
- strcpy(name, p);
- metric.special_device_coding = name;
- }
- if (strcmp(nm, "---") == 0) {
- last_index = number_to_index(metric.code);
- add_entry(last_index, metric);
- }
- else {
- last_index = name_to_index(nm);
- if (last_index < 0) {
- t.error("invalid character `%1'", nm);
- return 0;
- }
- add_entry(last_index, metric);
- copy_entry(number_to_index(metric.code), last_index);
- }
- }
- }
- if (last_index == -1) {
- t.error("I didn't seem to find any characters");
- return 0;
- }
- }
- else {
- t.error("unrecognised command `%1' after `kernpairs' or `charset' command", command);
- return 0;
- }
- }
- if (!had_charset) {
- t.error("missing charset command");
- return 0;
- }
- if (space_width == 0)
- space_width = scale_round(unitwidth, res, 72*3*sizescale);
- compact();
- return 1;
-}
-
-static struct {
- const char *command;
- int *ptr;
-} table[] = {
- { "res", &font::res },
- { "hor", &font::hor },
- { "vert", &font::vert },
- { "unitwidth", &font::unitwidth },
- { "paperwidth", &font::paperwidth },
- { "paperlength", &font::paperlength },
- { "spare1", &font::biggestfont },
- { "biggestfont", &font::biggestfont },
- { "spare2", &font::spare2 },
- { "sizescale", &font::sizescale }
- };
-
-int font::load_desc()
-{
- int nfonts = 0;
- FILE *fp;
- char *path;
- if ((fp = open_file("DESC", &path)) == 0) {
- error("can't find `DESC' file");
- return 0;
- }
- text_file t(fp, path);
- t.skip_comments = 1;
- res = 0;
- while (t.next()) {
- char *p = strtok(t.buf, WS);
- int found = 0;
- unsigned int idx;
- for (idx = 0; !found && idx < sizeof(table)/sizeof(table[0]); idx++)
- if (strcmp(table[idx].command, p) == 0)
- found = 1;
- if (found) {
- char *q = strtok(0, WS);
- if (!q) {
- t.error("missing value for command `%1'", p);
- return 0;
- }
- //int *ptr = &(this->*(table[idx-1].ptr));
- int *ptr = table[idx-1].ptr;
- if (sscanf(q, "%d", ptr) != 1) {
- t.error("bad number `%1'", q);
- return 0;
- }
- }
- else if (strcmp("family", p) == 0) {
- p = strtok(0, WS);
- if (!p) {
- t.error("family command requires an argument");
- return 0;
- }
- char *tem = new char[strlen(p)+1];
- strcpy(tem, p);
- family = tem;
- }
- else if (strcmp("fonts", p) == 0) {
- p = strtok(0, WS);
- if (!p || sscanf(p, "%d", &nfonts) != 1 || nfonts <= 0) {
- t.error("bad number of fonts `%1'", p);
- return 0;
- }
- font_name_table = (const char **)new char *[nfonts+1];
- for (int i = 0; i < nfonts; i++) {
- p = strtok(0, WS);
- while (p == 0) {
- if (!t.next()) {
- t.error("end of file while reading list of fonts");
- return 0;
- }
- p = strtok(t.buf, WS);
- }
- char *temp = new char[strlen(p)+1];
- strcpy(temp, p);
- font_name_table[i] = temp;
- }
- p = strtok(0, WS);
- if (p != 0) {
- t.error("font count does not match number of fonts");
- return 0;
- }
- font_name_table[nfonts] = 0;
- }
- else if (strcmp("papersize", p) == 0) {
- p = strtok(0, WS);
- if (!p) {
- t.error("papersize command requires an argument");
- return 0;
- }
- int found_paper = 0;
- while (p) {
- double unscaled_paperwidth, unscaled_paperlength;
- if (scan_papersize(p, &papersize, &unscaled_paperlength,
- &unscaled_paperwidth)) {
- paperwidth = int(unscaled_paperwidth * res + 0.5);
- paperlength = int(unscaled_paperlength * res + 0.5);
- found_paper = 1;
- break;
- }
- p = strtok(0, WS);
- }
- if (!found_paper) {
- t.error("bad paper size");
- return 0;
- }
- }
- else if (strcmp("pass_filenames", p) == 0)
- pass_filenames = 1;
- else if (strcmp("sizes", p) == 0) {
- int n = 16;
- sizes = new int[n];
- int i = 0;
- for (;;) {
- p = strtok(0, WS);
- while (p == 0) {
- if (!t.next()) {
- t.error("list of sizes must be terminated by `0'");
- return 0;
- }
- p = strtok(t.buf, WS);
- }
- int lower, upper;
- switch (sscanf(p, "%d-%d", &lower, &upper)) {
- case 1:
- upper = lower;
- // fall through
- case 2:
- if (lower <= upper && lower >= 0)
- break;
- // fall through
- default:
- t.error("bad size range `%1'", p);
- return 0;
- }
- if (i + 2 > n) {
- int *old_sizes = sizes;
- sizes = new int[n*2];
- memcpy(sizes, old_sizes, n*sizeof(int));
- n *= 2;
- a_delete old_sizes;
- }
- sizes[i++] = lower;
- if (lower == 0)
- break;
- sizes[i++] = upper;
- }
- if (i == 1) {
- t.error("must have some sizes");
- return 0;
- }
- }
- else if (strcmp("styles", p) == 0) {
- int style_table_size = 5;
- style_table = (const char **)new char *[style_table_size];
- int j;
- for (j = 0; j < style_table_size; j++)
- style_table[j] = 0;
- int i = 0;
- for (;;) {
- p = strtok(0, WS);
- if (p == 0)
- break;
- // leave room for terminating 0
- if (i + 1 >= style_table_size) {
- const char **old_style_table = style_table;
- style_table_size *= 2;
- style_table = (const char **)new char*[style_table_size];
- for (j = 0; j < i; j++)
- style_table[j] = old_style_table[j];
- for (; j < style_table_size; j++)
- style_table[j] = 0;
- a_delete old_style_table;
- }
- char *tem = new char[strlen(p) + 1];
- strcpy(tem, p);
- style_table[i++] = tem;
- }
- }
- else if (strcmp("tcommand", p) == 0)
- tcommand = 1;
- else if (strcmp("use_charnames_in_special", p) == 0)
- use_charnames_in_special = 1;
- else if (strcmp("charset", p) == 0)
- break;
- else if (unknown_desc_command_handler) {
- char *command = p;
- p = strtok(0, "\n");
- (*unknown_desc_command_handler)(command, trim_arg(p), t.path, t.lineno);
- }
- }
- if (res == 0) {
- t.error("missing `res' command");
- return 0;
- }
- if (unitwidth == 0) {
- t.error("missing `unitwidth' command");
- return 0;
- }
- if (font_name_table == 0) {
- t.error("missing `fonts' command");
- return 0;
- }
- if (sizes == 0) {
- t.error("missing `sizes' command");
- return 0;
- }
- if (sizescale < 1) {
- t.error("bad `sizescale' value");
- return 0;
- }
- if (hor < 1) {
- t.error("bad `hor' value");
- return 0;
- }
- if (vert < 1) {
- t.error("bad `vert' value");
- return 0;
- }
- return 1;
-}
-
-void font::handle_unknown_font_command(const char *, const char *,
- const char *, int)
-{
-}
-
-FONT_COMMAND_HANDLER
-font::set_unknown_desc_command_handler(FONT_COMMAND_HANDLER func)
-{
- FONT_COMMAND_HANDLER prev = unknown_desc_command_handler;
- unknown_desc_command_handler = func;
- return prev;
-}
-
diff --git a/contrib/groff/src/libs/libgroff/fontfile.cc b/contrib/groff/src/libs/libgroff/fontfile.cc
deleted file mode 100644
index 8502d12..0000000
--- a/contrib/groff/src/libs/libgroff/fontfile.cc
+++ /dev/null
@@ -1,67 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "lib.h"
-
-#include
-#include
-#include
-#include "font.h"
-#include "searchpath.h"
-#include "device.h"
-#include "defs.h"
-
-const char *const FONT_ENV_VAR = "GROFF_FONT_PATH";
-
-static search_path font_path(FONT_ENV_VAR, FONTPATH, 0, 0);
-
-int font::res = 0;
-int font::hor = 1;
-int font::vert = 1;
-int font::unitwidth = 0;
-int font::paperwidth = 0;
-int font::paperlength = 0;
-const char *font::papersize = 0;
-int font::biggestfont = 0;
-int font::spare2 = 0;
-int font::sizescale = 1;
-int font::tcommand = 0;
-int font::pass_filenames = 0;
-int font::use_charnames_in_special = 0;
-const char **font::font_name_table = 0;
-int *font::sizes = 0;
-const char *font::family = 0;
-const char **font::style_table = 0;
-FONT_COMMAND_HANDLER font::unknown_desc_command_handler = 0;
-
-void font::command_line_font_dir(const char *dir)
-{
- font_path.command_line_dir(dir);
-}
-
-FILE *font::open_file(const char *name, char **pathp)
-{
- char *filename = new char[strlen(name) + strlen(device) + 5];
- sprintf(filename, "dev%s/%s", device, name);
- FILE *fp = font_path.open_file(filename, pathp);
- a_delete filename;
- return fp;
-}
diff --git a/contrib/groff/src/libs/libgroff/geometry.cc b/contrib/groff/src/libs/libgroff/geometry.cc
deleted file mode 100644
index 58a94a4..0000000
--- a/contrib/groff/src/libs/libgroff/geometry.cc
+++ /dev/null
@@ -1,286 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
- Free Software Foundation, Inc.
- Written by Gaius Mulley
- using adjust_arc_center() from printer.cc, written by James Clark.
-
-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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-
-#include
-#include
-
-#undef MAX
-#define MAX(a, b) (((a) > (b)) ? (a) : (b))
-
-#undef MIN
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-
-
-// This utility function adjusts the specified center of the
-// arc so that it is equidistant between the specified start
-// and end points. (p[0], p[1]) is a vector from the current
-// point to the center; (p[2], p[3]) is a vector from the
-// center to the end point. If the center can be adjusted,
-// a vector from the current point to the adjusted center is
-// stored in c[0], c[1] and 1 is returned. Otherwise 0 is
-// returned.
-
-#if 1
-int adjust_arc_center(const int *p, double *c)
-{
- // We move the center along a line parallel to the line between
- // the specified start point and end point so that the center
- // is equidistant between the start and end point.
- // It can be proved (using Lagrange multipliers) that this will
- // give the point nearest to the specified center that is equidistant
- // between the start and end point.
-
- double x = p[0] + p[2]; // (x, y) is the end point
- double y = p[1] + p[3];
- double n = x*x + y*y;
- if (n != 0) {
- c[0]= double(p[0]);
- c[1] = double(p[1]);
- double k = .5 - (c[0]*x + c[1]*y)/n;
- c[0] += k*x;
- c[1] += k*y;
- return 1;
- }
- else
- return 0;
-}
-#else
-int printer::adjust_arc_center(const int *p, double *c)
-{
- int x = p[0] + p[2]; // (x, y) is the end point
- int y = p[1] + p[3];
- // Start at the current point; go in the direction of the specified
- // center point until we reach a point that is equidistant between
- // the specified starting point and the specified end point. Place
- // the center of the arc there.
- double n = p[0]*double(x) + p[1]*double(y);
- if (n > 0) {
- double k = (double(x)*x + double(y)*y)/(2.0*n);
- // (cx, cy) is our chosen center
- c[0] = k*p[0];
- c[1] = k*p[1];
- return 1;
- }
- else {
- // We would never reach such a point. So instead start at the
- // specified end point of the arc. Go towards the specified
- // center point until we reach a point that is equidistant between
- // the specified start point and specified end point. Place
- // the center of the arc there.
- n = p[2]*double(x) + p[3]*double(y);
- if (n > 0) {
- double k = 1 - (double(x)*x + double(y)*y)/(2.0*n);
- // (c[0], c[1]) is our chosen center
- c[0] = p[0] + k*p[2];
- c[1] = p[1] + k*p[3];
- return 1;
- }
- else
- return 0;
- }
-}
-#endif
-
-
-/*
- * check_output_arc_limits - works out the smallest box that will encompass
- * an arc defined by an origin (x, y) and two
- * vectors (p0, p1) and (p2, p3).
- * (x1, y1) -> start of arc
- * (x1, y1) + (xv1, yv1) -> center of circle
- * (x1, y1) + (xv1, yv1) + (xv2, yv2) -> end of arc
- *
- * Works out in which quadrant the arc starts and
- * stops, and from this it determines the x, y
- * max/min limits. The arc is drawn clockwise.
- *
- * [I'm sure there is a better way to do this, but
- * I don't know how. Please can someone let me
- * know or "improve" this function.]
- */
-
-void check_output_arc_limits(int x1, int y1,
- int xv1, int yv1,
- int xv2, int yv2,
- double c0, double c1,
- int *minx, int *maxx,
- int *miny, int *maxy)
-{
- int radius = (int)sqrt(c0*c0 + c1*c1);
- int x2 = x1 + xv1 + xv2; // end of arc is (x2, y2)
- int y2 = y1 + yv1 + yv2;
-
- // firstly lets use the `circle' limitation
- *minx = x1 + xv1 - radius;
- *maxx = x1 + xv1 + radius;
- *miny = y1 + yv1 - radius;
- *maxy = y1 + yv1 + radius;
-
- /* now to see which min/max can be reduced and increased for the limits of
- * the arc
- *
- * Q2 | Q1
- * -----+-----
- * Q3 | Q4
- *
- *
- * NB. (x1+xv1, y1+yv1) is at the origin
- *
- * below we ask a nested question
- * (i) from which quadrant does the first vector start?
- * (ii) into which quadrant does the second vector go?
- * from the 16 possible answers we determine the limits of the arc
- */
- if (xv1 > 0 && yv1 > 0) {
- // first vector in Q3
- if (xv2 >= 0 && yv2 >= 0 ) {
- // second in Q1
- *maxx = x2;
- *miny = y1;
- }
- else if (xv2 < 0 && yv2 >= 0) {
- // second in Q2
- *maxx = x2;
- *miny = y1;
- }
- else if (xv2 >= 0 && yv2 < 0) {
- // second in Q4
- *miny = MIN(y1, y2);
- }
- else if (xv2 < 0 && yv2 < 0) {
- // second in Q3
- if (x1 >= x2) {
- *minx = x2;
- *maxx = x1;
- *miny = MIN(y1, y2);
- *maxy = MAX(y1, y2);
- }
- else {
- // xv2, yv2 could all be zero?
- }
- }
- }
- else if (xv1 > 0 && yv1 < 0) {
- // first vector in Q2
- if (xv2 >= 0 && yv2 >= 0) {
- // second in Q1
- *maxx = MAX(x1, x2);
- *minx = MIN(x1, x2);
- *miny = y1;
- }
- else if (xv2 < 0 && yv2 >= 0) {
- // second in Q2
- if (x1 < x2) {
- *maxx = x2;
- *minx = x1;
- *miny = MIN(y1, y2);
- *maxy = MAX(y1, y2);
- }
- else {
- // otherwise almost full circle anyway
- }
- }
- else if (xv2 >= 0 && yv2 < 0) {
- // second in Q4
- *miny = y2;
- *minx = x1;
- }
- else if (xv2 < 0 && yv2 < 0) {
- // second in Q3
- *minx = MIN(x1, x2);
- }
- }
- else if (xv1 <= 0 && yv1 <= 0) {
- // first vector in Q1
- if (xv2 >= 0 && yv2 >= 0) {
- // second in Q1
- if (x1 < x2) {
- *minx = x1;
- *maxx = x2;
- *miny = MIN(y1, y2);
- *maxy = MAX(y1, y2);
- }
- else {
- // nearly full circle
- }
- }
- else if (xv2 < 0 && yv2 >= 0) {
- // second in Q2
- *maxy = MAX(y1, y2);
- }
- else if (xv2 >= 0 && yv2 < 0) {
- // second in Q4
- *miny = MIN(y1, y2);
- *maxy = MAX(y1, y2);
- *minx = MIN(x1, x2);
- }
- else if (xv2 < 0 && yv2 < 0) {
- // second in Q3
- *minx = x2;
- *maxy = y1;
- }
- }
- else if (xv1 <= 0 && yv1 > 0) {
- // first vector in Q4
- if (xv2 >= 0 && yv2 >= 0) {
- // second in Q1
- *maxx = MAX(x1, x2);
- }
- else if (xv2 < 0 && yv2 >= 0) {
- // second in Q2
- *maxy = MAX(y1, y2);
- *maxx = MAX(x1, x2);
- }
- else if (xv2 >= 0 && yv2 < 0) {
- // second in Q4
- if (x1 >= x2) {
- *miny = MIN(y1, y2);
- *maxy = MAX(y1, y2);
- *minx = MIN(x1, x2);
- *maxx = MAX(x2, x2);
- }
- else {
- // nearly full circle
- }
- }
- else if (xv2 < 0 && yv2 < 0) {
- // second in Q3
- *maxy = MAX(y1, y2);
- *minx = MIN(x1, x2);
- *maxx = MAX(x1, x2);
- }
- }
-
- // this should *never* happen but if it does it means a case above is wrong
- // this code is only present for safety sake
- if (*maxx < *minx) {
- fprintf(stderr, "assert failed *minx > *maxx\n");
- fflush(stderr);
- *maxx = *minx;
- }
- if (*maxy < *miny) {
- fprintf(stderr, "assert failed *miny > *maxy\n");
- fflush(stderr);
- *maxy = *miny;
- }
-}
diff --git a/contrib/groff/src/libs/libgroff/htmlhint.cc b/contrib/groff/src/libs/libgroff/htmlhint.cc
deleted file mode 100644
index 3015767..0000000
--- a/contrib/groff/src/libs/libgroff/htmlhint.cc
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Copyright (C) 2000, 2001, 2002 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "lib.h"
-
-#include
-#include
-
-#include "nonposix.h"
-#include "stringclass.h"
-#include "html-strings.h"
-
-/*
- * This file contains a very simple set of routines which might
- * be shared by preprocessors. It allows a preprocessor to indicate
- * when an inline image should be created.
- * This string is intercepted by pre-grohtml and substituted for
- * the image name and suppression escapes.
- *
- * pre-html runs troff twice, once with -Thtml and once with -Tps.
- * troff -Thtml device driver emits a tag
- * and the postscript device driver works out the min/max limits
- * of the graphic region. These region limits are read by pre-html
- * and an image is generated via troff -Tps -> gs -> png
- */
-
-/*
- * html_begin_suppress - emit a start of image tag which will be seen
- * by pre-html.
- */
-void html_begin_suppress()
-{
- put_string(HTML_IMAGE_INLINE_BEGIN, stdout);
-}
-
-/*
- * html_end_suppress - emit an end of image tag which will be seen
- * by pre-html.
- */
-void html_end_suppress()
-{
- put_string(HTML_IMAGE_INLINE_END, stdout);
-}
diff --git a/contrib/groff/src/libs/libgroff/lf.cc b/contrib/groff/src/libs/libgroff/lf.cc
deleted file mode 100644
index 34272c7..0000000
--- a/contrib/groff/src/libs/libgroff/lf.cc
+++ /dev/null
@@ -1,62 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include
-#include
-#include "cset.h"
-#include "stringclass.h"
-
-extern void change_filename(const char *);
-extern void change_lineno(int);
-
-int interpret_lf_args(const char *p)
-{
- while (*p == ' ')
- p++;
- if (!csdigit(*p))
- return 0;
- int ln = 0;
- do {
- ln *= 10;
- ln += *p++ - '0';
- } while (csdigit(*p));
- if (*p != ' ' && *p != '\n' && *p != '\0')
- return 0;
- while (*p == ' ')
- p++;
- if (*p == '\0' || *p == '\n') {
- change_lineno(ln);
- return 1;
- }
- const char *q;
- for (q = p;
- *q != '\0' && *q != ' ' && *q != '\n' && *q != '\\';
- q++)
- ;
- string tem(p, q - p);
- while (*q == ' ')
- q++;
- if (*q != '\n' && *q != '\0')
- return 0;
- tem += '\0';
- change_filename(tem.contents());
- change_lineno(ln);
- return 1;
-}
diff --git a/contrib/groff/src/libs/libgroff/lineno.cc b/contrib/groff/src/libs/libgroff/lineno.cc
deleted file mode 100644
index f7138db..0000000
--- a/contrib/groff/src/libs/libgroff/lineno.cc
+++ /dev/null
@@ -1 +0,0 @@
-int current_lineno = 0;
diff --git a/contrib/groff/src/libs/libgroff/macropath.cc b/contrib/groff/src/libs/libgroff/macropath.cc
deleted file mode 100644
index 03c04cb..0000000
--- a/contrib/groff/src/libs/libgroff/macropath.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "lib.h"
-#include "searchpath.h"
-#include "macropath.h"
-#include "defs.h"
-
-#define MACROPATH_ENVVAR "GROFF_TMAC_PATH"
-
-search_path macro_path(MACROPATH_ENVVAR, MACROPATH, 1, 1);
-search_path safer_macro_path(MACROPATH_ENVVAR, MACROPATH, 1, 0);
-search_path config_macro_path(MACROPATH_ENVVAR, MACROPATH, 0, 0);
diff --git a/contrib/groff/src/libs/libgroff/maxfilename.cc b/contrib/groff/src/libs/libgroff/maxfilename.cc
deleted file mode 100644
index 341cf92..0000000
--- a/contrib/groff/src/libs/libgroff/maxfilename.cc
+++ /dev/null
@@ -1,69 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-/* file_name_max(dir) does the same as pathconf(dir, _PC_NAME_MAX) */
-
-#include "lib.h"
-
-#include
-
-#ifdef HAVE_UNISTD_H
-#include
-#endif /* HAVE_UNISTD_H */
-
-#ifdef _POSIX_VERSION
-
-size_t file_name_max(const char *fname)
-{
- return pathconf(fname, _PC_NAME_MAX);
-}
-
-#else /* not _POSIX_VERSION */
-
-#ifdef HAVE_LIMITS_H
-#include
-#endif /* HAVE_LIMITS_H */
-
-#ifdef HAVE_DIRENT_H
-#include
-#else /* not HAVE_DIRENT_H */
-#ifdef HAVE_SYS_DIR_H
-#include
-#endif /* HAVE_SYS_DIR_H */
-#endif /* not HAVE_DIRENT_H */
-
-#ifndef NAME_MAX
-#ifdef MAXNAMLEN
-#define NAME_MAX MAXNAMLEN
-#else /* !MAXNAMLEN */
-#ifdef MAXNAMELEN
-#define NAME_MAX MAXNAMELEN
-#else /* !MAXNAMELEN */
-#define NAME_MAX 14
-#endif /* !MAXNAMELEN */
-#endif /* !MAXNAMLEN */
-#endif /* !NAME_MAX */
-
-size_t file_name_max(const char *)
-{
- return NAME_MAX;
-}
-
-#endif /* not _POSIX_VERSION */
diff --git a/contrib/groff/src/libs/libgroff/mksdir.cc b/contrib/groff/src/libs/libgroff/mksdir.cc
deleted file mode 100644
index bf4d300..0000000
--- a/contrib/groff/src/libs/libgroff/mksdir.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
- Written by Werner Lemberg (wl@gnu.org)
-
-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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-
-/* This file is heavily based on the file mkstemp.c which is part of the
- fileutils package. */
-
-
-extern int gen_tempname(char *, int = 0);
-
-/* Generate a unique temporary directory name from TEMPLATE.
- The last six characters of TEMPLATE must be "XXXXXX";
- they are replaced with a string that makes the filename unique.
- Then open the directory and return a fd. */
-int mksdir(char *tmpl)
-{
- return gen_tempname(tmpl, 1);
-}
diff --git a/contrib/groff/src/libs/libgroff/mkstemp.cc b/contrib/groff/src/libs/libgroff/mkstemp.cc
deleted file mode 100644
index cd2717c..0000000
--- a/contrib/groff/src/libs/libgroff/mkstemp.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
- Written by Werner Lemberg (wl@gnu.org)
-
-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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-
-/* This file is heavily based on the file mkstemp.c which is part of the
- fileutils package. */
-
-
-extern int gen_tempname(char *, int);
-
-/* Generate a unique temporary file name from TEMPLATE.
- The last six characters of TEMPLATE must be "XXXXXX";
- they are replaced with a string that makes the filename unique.
- Then open the file and return a fd. */
-int mkstemp(char *tmpl)
-{
- return gen_tempname(tmpl, 0);
-}
diff --git a/contrib/groff/src/libs/libgroff/nametoindex.cc b/contrib/groff/src/libs/libgroff/nametoindex.cc
deleted file mode 100644
index 7c94b25..0000000
--- a/contrib/groff/src/libs/libgroff/nametoindex.cc
+++ /dev/null
@@ -1,117 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "lib.h"
-
-#include
-#include
-#include
-#include "errarg.h"
-#include "error.h"
-#include "font.h"
-#include "ptable.h"
-
-declare_ptable(int)
-implement_ptable(int)
-
-class character_indexer {
-public:
- character_indexer();
- ~character_indexer();
- int ascii_char_index(unsigned char);
- int named_char_index(const char *);
- int numbered_char_index(int);
-private:
- enum { NSMALL = 256 };
- int next_index;
- int ascii_index[256];
- int small_number_index[NSMALL];
- PTABLE(int) table;
-};
-
-character_indexer::character_indexer()
-: next_index(0)
-{
- int i;
- for (i = 0; i < 256; i++)
- ascii_index[i] = -1;
- for (i = 0; i < NSMALL; i++)
- small_number_index[i] = -1;
-}
-
-character_indexer::~character_indexer()
-{
-}
-
-int character_indexer::ascii_char_index(unsigned char c)
-{
- if (ascii_index[c] < 0)
- ascii_index[c] = next_index++;
- return ascii_index[c];
-}
-
-int character_indexer::numbered_char_index(int n)
-{
- if (n >= 0 && n < NSMALL) {
- if (small_number_index[n] < 0)
- small_number_index[n] = next_index++;
- return small_number_index[n];
- }
- // Not the most efficient possible implementation.
- char buf[INT_DIGITS + 3];
- buf[0] = ' ';
- strcpy(buf + 1, i_to_a(n));
- return named_char_index(buf);
-}
-
-int character_indexer::named_char_index(const char *s)
-{
- int *np = table.lookup(s);
- if (!np) {
- np = new int;
- *np = next_index++;
- table.define(s, np);
- }
- return *np;
-}
-
-static character_indexer indexer;
-
-int font::number_to_index(int n)
-{
- return indexer.numbered_char_index(n);
-}
-
-int font::name_to_index(const char *s)
-{
- assert(s != 0 && s[0] != '\0' && s[0] != ' ');
- if (s[1] == '\0')
- return indexer.ascii_char_index(s[0]);
- /* char128 and \200 are synonyms */
- if (s[0] == 'c' && s[1] == 'h' && s[2] == 'a' && s[3] == 'r') {
- char *res;
- long n = strtol(s + 4, &res, 10);
- if (res != s + 4 && *res == '\0' && n >= 0 && n < 256)
- return indexer.ascii_char_index((unsigned char)n);
- }
- return indexer.named_char_index(s);
-}
-
diff --git a/contrib/groff/src/libs/libgroff/new.cc b/contrib/groff/src/libs/libgroff/new.cc
deleted file mode 100644
index 4975149..0000000
--- a/contrib/groff/src/libs/libgroff/new.cc
+++ /dev/null
@@ -1,69 +0,0 @@
-/* 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "lib.h"
-
-#include
-#include
-
-#include "posix.h"
-#include "nonposix.h"
-
-extern const char *program_name;
-
-static void ewrite(const char *s)
-{
- write(2, s, strlen(s));
-}
-
-void *operator new(size_t size)
-{
- // Avoid relying on the behaviour of malloc(0).
- if (size == 0)
- size++;
-#ifdef COOKIE_BUG
- char *p = (char *)malloc(unsigned(size + 8));
-#else /* not COOKIE_BUG */
- char *p = (char *)malloc(unsigned(size));
-#endif /* not COOKIE_BUG */
- if (p == 0) {
- if (program_name) {
- ewrite(program_name);
- ewrite(": ");
- }
- ewrite("out of memory\n");
- _exit(-1);
- }
-#ifdef COOKIE_BUG
- ((unsigned *)p)[1] = 0;
- return p + 8;
-#else /* not COOKIE_BUG */
- return p;
-#endif /* not COOKIE_BUG */
-}
-
-#ifdef COOKIE_BUG
-
-void operator delete(void *p)
-{
- if (p)
- free((void *)((char *)p - 8));
-}
-
-#endif /* COOKIE_BUG */
diff --git a/contrib/groff/src/libs/libgroff/paper.cc b/contrib/groff/src/libs/libgroff/paper.cc
deleted file mode 100644
index d79733e..0000000
--- a/contrib/groff/src/libs/libgroff/paper.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 2002
- Free Software Foundation, Inc.
- Written by Werner Lemberg (wl@gnu.org)
-
-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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "lib.h"
-#include "paper.h"
-
-paper papersizes[NUM_PAPERSIZES];
-
-// length and width in mm
-static void add_iso_paper(char series, int offset,
- int start_length, int start_width)
-{
- int length = start_length;
- int width = start_width;
- for (int i = 0; i < 8; i++)
- {
- char *p = new char[3];
- p[0] = series;
- p[1] = '0' + i;
- p[2] = '\0';
- papersizes[offset + i].name = p;
- // convert mm to inch
- papersizes[offset + i].length = (double)length / 25.4;
- papersizes[offset + i].width = (double)width / 25.4;
- // after division by two, values must be rounded down to the next
- // integer (as specified by ISO)
- int tmp = width;
- width = length;
- length = tmp / 2;
- }
-}
-
-// length and width in inch
-static void add_american_paper(const char *name, int index,
- double length, double width )
-{
- char *p = new char[strlen(name) + 1];
- strcpy(p, name);
- papersizes[index].name = p;
- papersizes[index].length = length;
- papersizes[index].width = width;
-}
-
-int papersize_init::initialised = 0;
-
-papersize_init::papersize_init()
-{
- if (initialised)
- return;
- initialised = 1;
- add_iso_paper('a', 0, 1189, 841);
- add_iso_paper('b', 8, 1414, 1000);
- add_iso_paper('c', 16, 1297, 917);
- add_iso_paper('d', 24, 1090, 771);
- add_american_paper("letter", 32, 11, 8.5);
- add_american_paper("legal", 33, 14, 8.5);
- add_american_paper("tabloid", 34, 17, 11);
- add_american_paper("ledger", 35, 11, 17);
- add_american_paper("statement", 36, 8.5, 5.5);
- add_american_paper("executive", 37, 10, 7.5);
- // the next three entries are for grolj4
- add_american_paper("com10", 38, 9.5, 4.125);
- add_american_paper("monarch", 39, 7.5, 3.875);
- // this is an ISO format, but it easier to use add_american_paper
- add_american_paper("dl", 40, 220/25.4, 110/25.4);
-}
diff --git a/contrib/groff/src/libs/libgroff/prime.cc b/contrib/groff/src/libs/libgroff/prime.cc
deleted file mode 100644
index f0b1ead..0000000
--- a/contrib/groff/src/libs/libgroff/prime.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-#include
-
-int is_prime(unsigned n)
-{
- if (n <= 3)
- return 1;
- if (!(n & 1))
- return 0;
- if (n % 3 == 0)
- return 0;
- unsigned lim = unsigned(sqrt((double)n));
- unsigned d = 5;
- for (;;) {
- if (d > lim)
- break;
- if (n % d == 0)
- return 0;
- d += 2;
- if (d > lim)
- break;
- if (n % d == 0)
- return 0;
- d += 4;
- }
- return 1;
-}
diff --git a/contrib/groff/src/libs/libgroff/progname.cc b/contrib/groff/src/libs/libgroff/progname.cc
deleted file mode 100644
index a70e341..0000000
--- a/contrib/groff/src/libs/libgroff/progname.cc
+++ /dev/null
@@ -1 +0,0 @@
-const char *program_name = 0;
diff --git a/contrib/groff/src/libs/libgroff/ptable.cc b/contrib/groff/src/libs/libgroff/ptable.cc
deleted file mode 100644
index 76735c2..0000000
--- a/contrib/groff/src/libs/libgroff/ptable.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-/* 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "ptable.h"
-#include "errarg.h"
-#include "error.h"
-
-unsigned long hash_string(const char *s)
-{
- assert(s != 0);
- unsigned long h = 0, g;
- while (*s != 0) {
- h <<= 4;
- h += *s++;
- if ((g = h & 0xf0000000) != 0) {
- h ^= g >> 24;
- h ^= g;
- }
- }
- return h;
-}
-
-static const unsigned table_sizes[] = {
-101, 503, 1009, 2003, 3001, 4001, 5003, 10007, 20011, 40009,
-80021, 160001, 500009, 1000003, 2000003, 4000037, 8000009,
-16000057, 32000011, 64000031, 128000003, 0
-};
-
-unsigned next_ptable_size(unsigned n)
-{
- const unsigned *p;
- for (p = table_sizes; *p <= n; p++)
- if (*p == 0)
- fatal("cannot expand table");
- return *p;
-}
diff --git a/contrib/groff/src/libs/libgroff/searchpath.cc b/contrib/groff/src/libs/libgroff/searchpath.cc
deleted file mode 100644
index 1f8b233..0000000
--- a/contrib/groff/src/libs/libgroff/searchpath.cc
+++ /dev/null
@@ -1,132 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "lib.h"
-
-#include
-#include
-
-#include "searchpath.h"
-#include "nonposix.h"
-
-search_path::search_path(const char *envvar, const char *standard,
- int add_home, int add_current)
-{
- char *home = 0;
- if (add_home)
- home = getenv("HOME");
- char *e = 0;
- if (envvar)
- e = getenv(envvar);
- dirs = new char[((e && *e) ? strlen(e) + 1 : 0)
- + (add_current ? 1 + 1 : 0)
- + ((home && *home) ? strlen(home) + 1 : 0)
- + ((standard && *standard) ? strlen(standard) : 0)
- + 1];
- *dirs = '\0';
- if (e && *e) {
- strcat(dirs, e);
- strcat(dirs, PATH_SEP);
- }
- if (add_current) {
- strcat(dirs, ".");
- strcat(dirs, PATH_SEP);
- }
- if (home && *home) {
- strcat(dirs, home);
- strcat(dirs, PATH_SEP);
- }
- if (standard && *standard)
- strcat(dirs, standard);
- init_len = strlen(dirs);
-}
-
-search_path::~search_path()
-{
- // dirs is always allocated
- a_delete dirs;
-}
-
-void search_path::command_line_dir(const char *s)
-{
- char *old = dirs;
- unsigned old_len = strlen(old);
- unsigned slen = strlen(s);
- dirs = new char[old_len + 1 + slen + 1];
- memcpy(dirs, old, old_len - init_len);
- char *p = dirs;
- p += old_len - init_len;
- if (init_len == 0)
- *p++ = PATH_SEP[0];
- memcpy(p, s, slen);
- p += slen;
- if (init_len > 0) {
- *p++ = PATH_SEP[0];
- memcpy(p, old + old_len - init_len, init_len);
- p += init_len;
- }
- *p++ = '\0';
- a_delete old;
-}
-
-FILE *search_path::open_file(const char *name, char **pathp)
-{
- assert(name != 0);
- if (IS_ABSOLUTE(name) || *dirs == '\0') {
- FILE *fp = fopen(name, "r");
- if (fp) {
- if (pathp)
- *pathp = strsave(name);
- return fp;
- }
- else
- return 0;
- }
- unsigned namelen = strlen(name);
- char *p = dirs;
- for (;;) {
- char *end = strchr(p, PATH_SEP[0]);
- if (!end)
- end = strchr(p, '\0');
- int need_slash = end > p && strchr(DIR_SEPS, end[-1]) == 0;
- char *path = new char[(end - p) + need_slash + namelen + 1];
- memcpy(path, p, end - p);
- if (need_slash)
- path[end - p] = '/';
- strcpy(path + (end - p) + need_slash, name);
-#if 0
- fprintf(stderr, "trying `%s'\n", path);
-#endif
- FILE *fp = fopen(path, "r");
- if (fp) {
- if (pathp)
- *pathp = path;
- else
- a_delete path;
- return fp;
- }
- a_delete path;
- if (*end == '\0')
- break;
- p = end + 1;
- }
- return 0;
-}
diff --git a/contrib/groff/src/libs/libgroff/string.cc b/contrib/groff/src/libs/libgroff/string.cc
deleted file mode 100644
index 2ef547e..0000000
--- a/contrib/groff/src/libs/libgroff/string.cc
+++ /dev/null
@@ -1,341 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "lib.h"
-
-#include "stringclass.h"
-
-static char *salloc(int len, int *sizep);
-static void sfree(char *ptr, int size);
-static char *sfree_alloc(char *ptr, int size, int len, int *sizep);
-static char *srealloc(char *ptr, int size, int oldlen, int newlen, int *sizep);
-
-static char *salloc(int len, int *sizep)
-{
- if (len == 0) {
- *sizep = 0;
- return 0;
- }
- else
- return new char[*sizep = len*2];
-}
-
-static void sfree(char *ptr, int)
-{
- a_delete ptr;
-}
-
-static char *sfree_alloc(char *ptr, int oldsz, int len, int *sizep)
-{
- if (oldsz >= len) {
- *sizep = oldsz;
- return ptr;
- }
- a_delete ptr;
- if (len == 0) {
- *sizep = 0;
- return 0;
- }
- else
- return new char[*sizep = len*2];
-}
-
-static char *srealloc(char *ptr, int oldsz, int oldlen, int newlen, int *sizep)
-{
- if (oldsz >= newlen) {
- *sizep = oldsz;
- return ptr;
- }
- if (newlen == 0) {
- a_delete ptr;
- *sizep = 0;
- return 0;
- }
- else {
- char *p = new char[*sizep = newlen*2];
- if (oldlen < newlen && oldlen != 0)
- memcpy(p, ptr, oldlen);
- a_delete ptr;
- return p;
- }
-}
-
-string::string() : ptr(0), len(0), sz(0)
-{
-}
-
-string::string(const char *p, int n) : len(n)
-{
- assert(n >= 0);
- ptr = salloc(n, &sz);
- if (n != 0)
- memcpy(ptr, p, n);
-}
-
-string::string(const char *p)
-{
- if (p == 0) {
- len = 0;
- ptr = 0;
- sz = 0;
- }
- else {
- len = strlen(p);
- ptr = salloc(len, &sz);
- memcpy(ptr, p, len);
- }
-}
-
-string::string(char c) : len(1)
-{
- ptr = salloc(1, &sz);
- *ptr = c;
-}
-
-string::string(const string &s) : len(s.len)
-{
- ptr = salloc(len, &sz);
- if (len != 0)
- memcpy(ptr, s.ptr, len);
-}
-
-string::~string()
-{
- sfree(ptr, sz);
-}
-
-string &string::operator=(const string &s)
-{
- ptr = sfree_alloc(ptr, sz, s.len, &sz);
- len = s.len;
- if (len != 0)
- memcpy(ptr, s.ptr, len);
- return *this;
-}
-
-string &string::operator=(const char *p)
-{
- if (p == 0) {
- sfree(ptr, len);
- len = 0;
- ptr = 0;
- sz = 0;
- }
- else {
- int slen = strlen(p);
- ptr = sfree_alloc(ptr, sz, slen, &sz);
- len = slen;
- memcpy(ptr, p, len);
- }
- return *this;
-}
-
-string &string::operator=(char c)
-{
- ptr = sfree_alloc(ptr, sz, 1, &sz);
- len = 1;
- *ptr = c;
- return *this;
-}
-
-void string::move(string &s)
-{
- sfree(ptr, sz);
- ptr = s.ptr;
- len = s.len;
- sz = s.sz;
- s.ptr = 0;
- s.len = 0;
- s.sz = 0;
-}
-
-void string::grow1()
-{
- ptr = srealloc(ptr, sz, len, len + 1, &sz);
-}
-
-string &string::operator+=(const char *p)
-{
- if (p != 0) {
- int n = strlen(p);
- int newlen = len + n;
- if (newlen > sz)
- ptr = srealloc(ptr, sz, len, newlen, &sz);
- memcpy(ptr + len, p, n);
- len = newlen;
- }
- return *this;
-}
-
-string &string::operator+=(const string &s)
-{
- if (s.len != 0) {
- int newlen = len + s.len;
- if (newlen > sz)
- ptr = srealloc(ptr, sz, len, newlen, &sz);
- memcpy(ptr + len, s.ptr, s.len);
- len = newlen;
- }
- return *this;
-}
-
-void string::append(const char *p, int n)
-{
- if (n > 0) {
- int newlen = len + n;
- if (newlen > sz)
- ptr = srealloc(ptr, sz, len, newlen, &sz);
- memcpy(ptr + len, p, n);
- len = newlen;
- }
-}
-
-string::string(const char *s1, int n1, const char *s2, int n2)
-{
- assert(n1 >= 0 && n2 >= 0);
- len = n1 + n2;
- if (len == 0) {
- sz = 0;
- ptr = 0;
- }
- else {
- ptr = salloc(len, &sz);
- if (n1 == 0)
- memcpy(ptr, s2, n2);
- else {
- memcpy(ptr, s1, n1);
- if (n2 != 0)
- memcpy(ptr + n1, s2, n2);
- }
- }
-}
-
-int operator<=(const string &s1, const string &s2)
-{
- return (s1.len <= s2.len
- ? s1.len == 0 || memcmp(s1.ptr, s2.ptr, s1.len) <= 0
- : s2.len != 0 && memcmp(s1.ptr, s2.ptr, s2.len) < 0);
-}
-
-int operator<(const string &s1, const string &s2)
-{
- return (s1.len < s2.len
- ? s1.len == 0 || memcmp(s1.ptr, s2.ptr, s1.len) <= 0
- : s2.len != 0 && memcmp(s1.ptr, s2.ptr, s2.len) < 0);
-}
-
-int operator>=(const string &s1, const string &s2)
-{
- return (s1.len >= s2.len
- ? s2.len == 0 || memcmp(s1.ptr, s2.ptr, s2.len) >= 0
- : s1.len != 0 && memcmp(s1.ptr, s2.ptr, s1.len) > 0);
-}
-
-int operator>(const string &s1, const string &s2)
-{
- return (s1.len > s2.len
- ? s2.len == 0 || memcmp(s1.ptr, s2.ptr, s2.len) >= 0
- : s1.len != 0 && memcmp(s1.ptr, s2.ptr, s1.len) > 0);
-}
-
-void string::set_length(int i)
-{
- assert(i >= 0);
- if (i > sz)
- ptr = srealloc(ptr, sz, len, i, &sz);
- len = i;
-}
-
-void string::clear()
-{
- len = 0;
-}
-
-int string::search(char c) const
-{
- char *p = ptr ? (char *)memchr(ptr, c, len) : NULL;
- return p ? p - ptr : -1;
-}
-
-// we silently strip nuls
-
-char *string::extract() const
-{
- char *p = ptr;
- int n = len;
- int nnuls = 0;
- int i;
- for (i = 0; i < n; i++)
- if (p[i] == '\0')
- nnuls++;
- char *q = new char[n + 1 - nnuls];
- char *r = q;
- for (i = 0; i < n; i++)
- if (p[i] != '\0')
- *r++ = p[i];
- *r = '\0';
- return q;
-}
-
-void string::remove_spaces()
-{
- int l = len - 1;
- while (l >= 0 && ptr[l] == ' ')
- l--;
- char *p = ptr;
- if (l > 0)
- while (*p == ' ') {
- p++;
- l--;
- }
- if (len - 1 != l) {
- if (l >= 0) {
- len = l + 1;
- char *tmp = new char[len];
- memcpy(tmp, p, len);
- a_delete ptr;
- ptr = tmp;
- }
- else {
- len = 0;
- if (ptr) {
- a_delete ptr;
- ptr = 0;
- }
- }
- }
-}
-
-void put_string(const string &s, FILE *fp)
-{
- int len = s.length();
- const char *ptr = s.contents();
- for (int i = 0; i < len; i++)
- putc(ptr[i], fp);
-}
-
-string as_string(int i)
-{
- static char buf[INT_DIGITS + 2];
- sprintf(buf, "%d", i);
- return string(buf);
-}
-
diff --git a/contrib/groff/src/libs/libgroff/strsave.cc b/contrib/groff/src/libs/libgroff/strsave.cc
deleted file mode 100644
index dfd2b6f..0000000
--- a/contrib/groff/src/libs/libgroff/strsave.cc
+++ /dev/null
@@ -1,31 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include
-
-char *strsave(const char *s)
-{
- if (s == 0)
- return 0;
- char *p = new char[strlen(s) + 1];
- strcpy(p, s);
- return p;
-}
-
diff --git a/contrib/groff/src/libs/libgroff/tmpfile.cc b/contrib/groff/src/libs/libgroff/tmpfile.cc
deleted file mode 100644
index 41b7f06..0000000
--- a/contrib/groff/src/libs/libgroff/tmpfile.cc
+++ /dev/null
@@ -1,172 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "lib.h"
-
-#include
-#include
-
-#include "posix.h"
-#include "errarg.h"
-#include "error.h"
-#include "nonposix.h"
-
-// If this is set, create temporary files there
-#define GROFF_TMPDIR_ENVVAR "GROFF_TMPDIR"
-// otherwise if this is set, create temporary files there
-#define TMPDIR_ENVVAR "TMPDIR"
-// otherwise if P_tmpdir is defined, create temporary files there
-#ifdef P_tmpdir
-# define DEFAULT_TMPDIR P_tmpdir
-#else
-// otherwise create temporary files here.
-# define DEFAULT_TMPDIR "/tmp"
-#endif
-// Use this as the prefix for temporary filenames.
-#define TMPFILE_PREFIX_SHORT ""
-#define TMPFILE_PREFIX_LONG "groff"
-
-char *tmpfile_prefix;
-size_t tmpfile_prefix_len;
-int use_short_postfix = 0;
-
-struct temp_init {
- temp_init();
- ~temp_init();
-} _temp_init;
-
-temp_init::temp_init()
-{
- const char *tem = getenv(GROFF_TMPDIR_ENVVAR);
- if (!tem) {
- tem = getenv(TMPDIR_ENVVAR);
- if (!tem)
- tem = DEFAULT_TMPDIR;
- }
- size_t tem_len = strlen(tem);
- const char *tem_end = tem + tem_len - 1;
- int need_slash = strchr(DIR_SEPS, *tem_end) == NULL ? 1 : 0;
- char *tem2 = new char[tem_len + need_slash + 1];
- strcpy(tem2, tem);
- if (need_slash)
- strcat(tem2, "/");
- const char *tem3 = TMPFILE_PREFIX_LONG;
- if (file_name_max(tem2) <= 14) {
- tem3 = TMPFILE_PREFIX_SHORT;
- use_short_postfix = 1;
- }
- tmpfile_prefix_len = tem_len + need_slash + strlen(tem3);
- tmpfile_prefix = new char[tmpfile_prefix_len + 1];
- strcpy(tmpfile_prefix, tem2);
- strcat(tmpfile_prefix, tem3);
- a_delete tem2;
-}
-
-temp_init::~temp_init()
-{
- a_delete tmpfile_prefix;
-}
-
-/*
- * Generate a temporary name template with a postfix
- * immediately after the TMPFILE_PREFIX.
- * It uses the groff preferences for a temporary directory.
- * Note that no file name is either created or opened,
- * only the *template* is returned.
- */
-
-char *xtmptemplate(const char *postfix_long, const char *postfix_short)
-{
- const char *postfix = use_short_postfix ? postfix_short : postfix_long;
- int postlen = 0;
- if (postfix)
- postlen = strlen(postfix);
- char *templ = new char[tmpfile_prefix_len + postlen + 6 + 1];
- strcpy(templ, tmpfile_prefix);
- if (postlen > 0)
- strcat(templ, postfix);
- strcat(templ, "XXXXXX");
- return templ;
-}
-
-// The trick with unlinking the temporary file while it is still in
-// use is not portable, it will fail on MS-DOS and most MS-Windows
-// filesystems. So it cannot be used on non-Posix systems.
-// Instead, we maintain a list of files to be deleted on exit.
-// This should be portable to all platforms.
-
-struct xtmpfile_list {
- char *fname;
- xtmpfile_list *next;
- xtmpfile_list(char *fn) : fname(fn), next(0) {}
-};
-
-xtmpfile_list *xtmpfiles_to_delete = 0;
-
-struct xtmpfile_list_init {
- ~xtmpfile_list_init();
-} _xtmpfile_list_init;
-
-xtmpfile_list_init::~xtmpfile_list_init()
-{
- xtmpfile_list *x = xtmpfiles_to_delete;
- while (x != 0) {
- if (unlink(x->fname) < 0)
- error("cannot unlink `%1': %2", x->fname, strerror(errno));
- xtmpfile_list *tmp = x;
- x = x->next;
- a_delete tmp->fname;
- delete tmp;
- }
-}
-
-static void add_tmp_file(const char *name)
-{
- char *s = new char[strlen(name)+1];
- strcpy(s, name);
- xtmpfile_list *x = new xtmpfile_list(s);
- x->next = xtmpfiles_to_delete;
- xtmpfiles_to_delete = x;
-}
-
-// Open a temporary file and with fatal error on failure.
-
-FILE *xtmpfile(char **namep,
- const char *postfix_long, const char *postfix_short,
- int do_unlink)
-{
- char *templ = xtmptemplate(postfix_long, postfix_short);
- errno = 0;
- int fd = mkstemp(templ);
- if (fd < 0)
- fatal("cannot create temporary file: %1", strerror(errno));
- errno = 0;
- FILE *fp = fdopen(fd, FOPEN_RWB); // many callers of xtmpfile use binary I/O
- if (!fp)
- fatal("fdopen: %1", strerror(errno));
- if (do_unlink)
- add_tmp_file(templ);
- if (namep)
- *namep = templ;
- else
- a_delete templ;
- return fp;
-}
diff --git a/contrib/groff/src/libs/libgroff/tmpname.cc b/contrib/groff/src/libs/libgroff/tmpname.cc
deleted file mode 100644
index 213b0ee..0000000
--- a/contrib/groff/src/libs/libgroff/tmpname.cc
+++ /dev/null
@@ -1,116 +0,0 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
- Written by Werner Lemberg (wl@gnu.org)
-
-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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-
-/* This file is heavily based on the function __gen_tempname() in the
- file tempname.c which is part of the fileutils package. */
-
-
-#include "lib.h"
-
-#include
-#include
-#include
-#include
-
-#include "posix.h"
-#include "nonposix.h"
-
-#ifndef TMP_MAX
-# define TMP_MAX 238328
-#endif
-
-#if HAVE_SYS_TIME_H
-# include
-#endif
-
-#ifdef HAVE_GETTIMEOFDAY
-#ifdef NEED_DECLARATION_GETTIMEOFDAY
-extern "C" {
- int gettimeofday(struct timeval *, void *);
-}
-#endif
-#endif
-
-#if HAVE_STDINT_H
-# include
-#endif
-
-/* Use the widest available unsigned type if uint64_t is not
- available. The algorithm below extracts a number less than 62**6
- (approximately 2**35.725) from uint64_t, so ancient hosts where
- uintmax_t is only 32 bits lose about 3.725 bits of randomness,
- which is better than not having mkstemp at all. */
-#if !defined UINT64_MAX && !defined uint64_t
-# define uint64_t uintmax_t
-#endif
-
-/* These are the characters used in temporary filenames. */
-static const char letters[] =
-"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
-
-int gen_tempname(char *tmpl, int dir)
-{
- static uint64_t value;
-
- size_t len = strlen(tmpl);
- if (len < 6 || strcmp(&tmpl[len - 6], "XXXXXX"))
- return -1; /* EINVAL */
-
- /* This is where the Xs start. */
- char *XXXXXX = &tmpl[len - 6];
-
- /* Get some more or less random data. */
-#if HAVE_GETTIMEOFDAY
- timeval tv;
- gettimeofday(&tv, NULL);
- uint64_t random_time_bits = ((uint64_t)tv.tv_usec << 16) ^ tv.tv_sec;
-#else
- uint64_t random_time_bits = time(NULL);
-#endif
- value += random_time_bits ^ getpid();
-
- for (int count = 0; count < TMP_MAX; value += 7777, ++count) {
- uint64_t v = value;
-
- /* Fill in the random bits. */
- XXXXXX[0] = letters[v % 62];
- v /= 62;
- XXXXXX[1] = letters[v % 62];
- v /= 62;
- XXXXXX[2] = letters[v % 62];
- v /= 62;
- XXXXXX[3] = letters[v % 62];
- v /= 62;
- XXXXXX[4] = letters[v % 62];
- v /= 62;
- XXXXXX[5] = letters[v % 62];
-
- int fd = dir ? mkdir(tmpl, S_IRUSR | S_IWUSR | S_IXUSR)
- : open(tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
-
- if (fd >= 0)
- return fd;
- else if (errno != EEXIST)
- return -1;
- }
-
- /* We got out of the loop because we ran out of combinations to try. */
- return -1; /* EEXIST */
-}
diff --git a/contrib/groff/src/preproc/eqn/box.cc b/contrib/groff/src/preproc/eqn/box.cc
deleted file mode 100644
index 41d8dff..0000000
--- a/contrib/groff/src/preproc/eqn/box.cc
+++ /dev/null
@@ -1,611 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 {
- 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/delim.cc b/contrib/groff/src/preproc/eqn/delim.cc
deleted file mode 100644
index 29deded..0000000
--- a/contrib/groff/src/preproc/eqn/delim.cc
+++ /dev/null
@@ -1,381 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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]",
- },
- {
- "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]",
- },
- {
- "ceiling", RIGHT_DELIM, "\\(rc", "\\[ceilingright%s]",
- "\\[bracketrightex]",
- "\\[bracketrighttp]",
- },
- {
- "||", LEFT_DELIM|RIGHT_DELIM, "|", "\\[bar%s]",
- "\\[bardblex]",
- },
- {
- "<", LEFT_DELIM|RIGHT_DELIM, "\\(la", "\\[angleleft%s]",
- },
- {
- ">", LEFT_DELIM|RIGHT_DELIM, "\\(ra", "\\[angleright%s]",
- },
- {
- "uparrow", LEFT_DELIM|RIGHT_DELIM, "\\(ua", "\\[arrowup%s]",
- "\\[arrowvertex]",
- "\\[arrowverttp]",
- },
- {
- "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/lex.cc b/contrib/groff/src/preproc/eqn/lex.cc
deleted file mode 100644
index 4e62f86..0000000
--- a/contrib/groff/src/preproc/eqn/lex.cc
+++ /dev/null
@@ -1,1166 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "eqn.h"
-#include "eqn_tab.h"
-#include "stringclass.h"
-#include "ptable.h"
-
-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;
- 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;
- 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;
- 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;
- 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.cc b/contrib/groff/src/preproc/eqn/limit.cc
deleted file mode 100644
index c8b5587..0000000
--- a/contrib/groff/src/preproc/eqn/limit.cc
+++ /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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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.cc b/contrib/groff/src/preproc/eqn/list.cc
deleted file mode 100644
index 1118fa1..0000000
--- a/contrib/groff/src/preproc/eqn/list.cc
+++ /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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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.cc b/contrib/groff/src/preproc/eqn/main.cc
deleted file mode 100644
index dabac5f..0000000
--- a/contrib/groff/src/preproc/eqn/main.cc
+++ /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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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.cc b/contrib/groff/src/preproc/eqn/mark.cc
deleted file mode 100644
index 99d1b75..0000000
--- a/contrib/groff/src/preproc/eqn/mark.cc
+++ /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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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/other.cc b/contrib/groff/src/preproc/eqn/other.cc
deleted file mode 100644
index c052f52..0000000
--- a/contrib/groff/src/preproc/eqn/other.cc
+++ /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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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.cc b/contrib/groff/src/preproc/eqn/over.cc
deleted file mode 100644
index 279efc8..0000000
--- a/contrib/groff/src/preproc/eqn/over.cc
+++ /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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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/pile.cc b/contrib/groff/src/preproc/eqn/pile.cc
deleted file mode 100644
index 0df5241..0000000
--- a/contrib/groff/src/preproc/eqn/pile.cc
+++ /dev/null
@@ -1,293 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 maxlen = 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 > maxlen)
- maxlen = 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, maxlen-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, maxlen-1, uid);
- for (i = 0; i < len; i++)
- if (p[i]->len == maxlen)
- printf(">?\\n[" DEPTH_FORMAT "]", p[i]->p[maxlen-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.cc b/contrib/groff/src/preproc/eqn/script.cc
deleted file mode 100644
index 62a05b4..0000000
--- a/contrib/groff/src/preproc/eqn/script.cc
+++ /dev/null
@@ -1,221 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 p;
- if (style == DISPLAY_STYLE)
- p = sup1;
- else if (style & 1) // not cramped
- p = sup2;
- else
- p = sup3;
- printf(".nr " SUP_RAISE_FORMAT " \\n[" SUP_RAISE_FORMAT
- "]>?%dM>?(\\n[" DEPTH_FORMAT "]+(%dM/4))\n",
- uid, uid, p, 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.cc b/contrib/groff/src/preproc/eqn/special.cc
deleted file mode 100644
index 310261a..0000000
--- a/contrib/groff/src/preproc/eqn/special.cc
+++ /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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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.cc b/contrib/groff/src/preproc/eqn/sqrt.cc
deleted file mode 100644
index bffa4f2..0000000
--- a/contrib/groff/src/preproc/eqn/sqrt.cc
+++ /dev/null
@@ -1,179 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "\\(sr"
-#define RADICAL_EXTENSION_CHAR "\\[radicalex]"
-
-#define SQRT_CHAIN "\\[sr\\\\n[" INDEX_REG "]]"
-#define BAR_CHAIN "\\[radicalex\\\\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.cc b/contrib/groff/src/preproc/eqn/text.cc
deleted file mode 100644
index b0f1700..0000000
--- a/contrib/groff/src/preproc/eqn/text.cc
+++ /dev/null
@@ -1,528 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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;
- 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;
- }
- }
- 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/hdb.cc b/contrib/groff/src/preproc/grn/hdb.cc
deleted file mode 100644
index 648a535..0000000
--- a/contrib/groff/src/preproc/grn/hdb.cc
+++ /dev/null
@@ -1,339 +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.cc */
-
-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 void savebounds(float x, float y);
-
-/* imports from hpoint.cc */
-
-extern POINT *PTInit();
-extern POINT *PTMakePoint(float x, float 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 float 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;
- float 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%f%f\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;
- (void) fclose(file);
- } else {
-#ifdef UW_FASTSCAN
- (void) xscanf(file, &x, &y); /* always one point */
-#else
- (void) fscanf(file, "%f%f\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, "%f%f", &x, &y);
- if ((x == -1.00 && y == -1.00) && (!SUNFILE))
- lastpoint = TRUE;
- }
- } 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, "%f%f", &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 */
- txt[i] = getc(file);
- }
- 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,
- float *xp,
- float *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.cc b/contrib/groff/src/preproc/grn/hgraph.cc
deleted file mode 100644
index d307faa..0000000
--- a/contrib/groff/src/preproc/grn/hgraph.cc
+++ /dev/null
@@ -1,1055 +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"
-
-#ifdef NEED_DECLARATION_HYPOT
-extern "C" {
- double hypot(double, double);
-}
-#endif /* NEED_DECLARATION_HYPOT */
-
-#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) 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 {
- 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 dx(double x);
-void dy(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[], float h[], int n);
-void PeriodicSpline(float h[], int z[],
- float dz[], float d2z[], float d3z[],
- int npoints);
-void NaturalEndSpline(float h[], int z[],
- float dz[], float d2z[], float 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.
- */
- float firstx = p1->x;
- float 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("\\h'-%du'\\D'f %du'",
- stipple_index[graylevel],
- stipple_index[graylevel]);
- cr();
- tmove(p1);
- printf("\\D'%c", command);
-
- while (!Nullpoint((PTNextPoint(p1)))) {
- p1 = PTNextPoint(p1);
- dx((double) p1->x);
- dy((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)) {
- dx((double) firstx);
- dy((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: dx (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
-dx(double x)
-{
- register int ix = (int) (x * troffscale);
-
- printf(" %du", ix - lastx);
- lastx = ix;
-}
-
-
-/*----------------------------------------------------------------------------*
- | Routine: dy (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
-dy(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 + 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) 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) 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)
-{
- float h[MAXPOINTS], dx[MAXPOINTS], dy[MAXPOINTS];
- float d2x[MAXPOINTS], d2y[MAXPOINTS], d3x[MAXPOINTS], d3y[MAXPOINTS];
- float 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 = (float) k *h[j] / (float) 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[],
- float h[],
- int n)
-{
- register int dx;
- register int dy;
- register int i;
- register int j;
- float 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] += 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(float h[], /* paramaterization */
- int z[], /* point list */
- float dz[], /* to return the 1st derivative */
- float d2z[], /* 2nd derivative */
- float d3z[], /* 3rd derivative */
- int npoints) /* number of valid points */
-{
- float d[MAXPOINTS];
- float deltaz[MAXPOINTS], a[MAXPOINTS], b[MAXPOINTS];
- float 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(float h[], /* parameterization */
- int z[], /* Point list */
- float dz[], /* to return the 1st derivative */
- float d2z[], /* 2nd derivative */
- float d3z[], /* 3rd derivative */
- int npoints) /* number of valid points */
-{
- float d[MAXPOINTS];
- float 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 x1,
- int y1)
-{
- register int x0 = lastx;
- register int y0 = 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(x1, y1);
- return;
- }
-
- /* for handling different resolutions */
- dotcounter = linmod << dotshifter;
-
- xinc = 1;
- yinc = 1;
- if ((dx = x1 - x0) < 0) {
- xinc = -xinc;
- dx = -dx;
- }
- if ((dy = y1 - y0) < 0) {
- yinc = -yinc;
- dy = -dy;
- }
- res1 = 0;
- res2 = 0;
- visible = 0;
- if (dx >= dy) {
- oldcoord = y0;
- while (x0 != x1) {
- if ((x0 & dotcounter) && !visible) {
- change(x0, y0, 0);
- visible = 1;
- } else if (visible && !(x0 & dotcounter)) {
- change(x0 - xinc, oldcoord, 1);
- visible = 0;
- }
- if (res1 > res2) {
- oldcoord = y0;
- res2 += dx - res1;
- res1 = 0;
- y0 += yinc;
- }
- res1 += dy;
- x0 += xinc;
- }
- } else {
- oldcoord = x0;
- while (y0 != y1) {
- if ((y0 & dotcounter) && !visible) {
- change(x0, y0, 0);
- visible = 1;
- } else if (visible && !(y0 & dotcounter)) {
- change(oldcoord, y0 - yinc, 1);
- visible = 0;
- }
- if (res1 > res2) {
- oldcoord = x0;
- res2 += dy - res1;
- res1 = 0;
- x0 += xinc;
- }
- res1 += dx;
- y0 += yinc;
- }
- }
- if (visible)
- change(x1, y1, 1);
- else
- change(x1, y1, 0);
-}
-
-/* EOF */
diff --git a/contrib/groff/src/preproc/grn/hpoint.cc b/contrib/groff/src/preproc/grn/hpoint.cc
deleted file mode 100644
index f4e1ca8..0000000
--- a/contrib/groff/src/preproc/grn/hpoint.cc
+++ /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(float x,
- float y,
- POINT **pplist)
-{
- register POINT *point;
-
- if (Nullpoint(point = *pplist)) { /* empty list */
- *pplist = (POINT *) malloc(sizeof(POINT));
- point = *pplist;
- } else {
- while (!Nullpoint(point->nextpt))
- point = point->nextpt;
- point->nextpt = (POINT *) malloc(sizeof(POINT));
- point = point->nextpt;
- }
-
- point->x = x;
- point->y = y;
- point->nextpt = PTInit();
- return (point);
-} /* end PTMakePoint */
-
-/* EOF */
diff --git a/contrib/groff/src/preproc/grn/main.cc b/contrib/groff/src/preproc/grn/main.cc
deleted file mode 100644
index 9b09ea6..0000000
--- a/contrib/groff/src/preproc/grn/main.cc
+++ /dev/null
@@ -1,906 +0,0 @@
-/* Last non-groff version: main.cc 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(float x, float 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. */
-
-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 {
- 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();
-char *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)
-{
- 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) != NULL) {
- 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);
- }
- }
-}
-
-
-/*----------------------------------------------------------------------------*
- | 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: char * 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'.
- *----------------------------------------------------------------------------*/
-
-char *
-doinput(FILE *fp)
-{
- char *k;
-
- if ((k = fgets(inputline, MAXINLINE, fp)) == NULL)
- return k;
- if (strchr(inputline, '\n')) /* ++ only if it's a complete line */
- linenum++;
- return (char *) !NULL;
-}
-
-
-/*----------------------------------------------------------------------------*
- | 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] = 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) == NULL); /* 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 = 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(float x,
- float 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 index = atoi(str1 + 1), val;
-
- if (index < 0 || index > NSTIPPLES) {
- error("bad stipple number %1 at line %2", index, linenum);
- break;
- }
- if (!defstipple_index)
- defstipple_index = other_stipple_index;
- val = atoi(str2);
- if (val >= 0 && val < 256)
- stipple_index[index] = 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/pre-html.cc b/contrib/groff/src/preproc/html/pre-html.cc
deleted file mode 100644
index e7364dd..0000000
--- a/contrib/groff/src/preproc/html/pre-html.cc
+++ /dev/null
@@ -1,1525 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 2000, 2001, 2002 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "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"
-
-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 '\\'
-
-#define TRANSPARENT "-background white -transparent white"
-#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 int copyofstdoutfd =-1; // a copy of stdout, so we can restore stdout when
- // writing to post-html
-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 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;
-
-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"
-
-/*
- * prototypes
- */
-static int do_file(const char *filename);
-
-/*
- * sys_fatal - writes 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 - copies 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 - returns 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);
- 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 - taken from man printf(3), creates a string via malloc
- * and places the result of the va args into string.
- * Finally the new string is returned.
- */
-
-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) {
- if (size > n+1) {
- np = strsave(p);
- free(p);
- return np;
- }
- return p;
- }
- /* Else try again with more space. */
- if (n > -1) /* glibc 2.1 */
- size = n+1; /* precisely what is needed */
- 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, sets the, used, and, next, fields to zero.
- */
-
-char_block::char_block()
-: used(0), next(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 write_file_html(void);
- void write_file_troff(void);
- void write_upto_newline (char_block **t, int *i, int is_html);
- int can_see(char_block **t, int *i, 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;
-};
-
-/*
- * char_buffer - constructor
- */
-
-char_buffer::char_buffer()
-: head(0), tail(0)
-{
-}
-
-/*
- * char_buffer - deconstructor, throws aways 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 - writes n bytes to stdout.
- */
-
-static void writeNbytes (char *s, int l)
-{
- int n=0;
- int r;
-
- while (n0) && (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 - sets 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 - checks to see 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 - ends the image. It writes 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 - writes the troff 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 - writes the contents of the buffer until a newline is seen.
- * It checks for HTML_IMAGE_INLINE_BEGIN and HTML_IMAGE_INLINE_END
- * and if they are present it processes them.
- */
-
-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;
- if ((*t)->buffer[j-1] == '\n') {
- *t = (*t)->next;
- } else {
- *t = (*t)->next;
- write_upto_newline(t, i, is_html);
- }
- } else {
- // newline was seen
- *i = j;
- }
- }
-}
-
-/*
- * can_see - returns TRUE if we can see string in t->buffer[i] onwards
- */
-
-int char_buffer::can_see (char_block **t, int *i, char *string)
-{
- int j = 0;
- int l = strlen(string);
- int k = *i;
- char_block *s = *t;
-
- while (s) {
- while ((kused) && (jbuffer[k] == string[j])) {
- j++;
- k++;
- }
- if (j == l) {
- *i = k;
- *t = s;
- return( TRUE );
- } else if ((kused) && (s->buffer[k] != string[j])) {
- return( FALSE );
- }
- s = s->next;
- k = 0;
- }
- return( FALSE );
-}
-
-/*
- * skip_spaces - returns TRUE if we have not run out of data.
- * It also consumes spaces.
- */
-
-int char_buffer::skip_spaces(char_block **t, int *i)
-{
- char_block *s = *t;
- int k = *i;
-
- while (s) {
- while ((kused) && (isspace(s->buffer[k]))) {
- k++;
- }
- if (k == s->used) {
- k = 0;
- s = s->next;
- } else {
- *i = k;
- return( TRUE );
- }
- }
- return( FALSE );
-}
-
-/*
- * skip_until_newline - skips 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;
- }
- }
-}
-
-/*
- * write_file_troff - writes the buffer to stdout (troff).
- */
-
-void char_buffer::write_file_troff (void)
-{
- char_block *t=head;
- int i=0;
-
- if (t != NULL) {
- do {
- write_upto_newline(&t, &i, FALSE);
- } while (t != NULL);
- }
- 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");
- }
- }
-}
-
-/*
- * 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 - deconstructor
- */
-
-imageItem::~imageItem ()
-{
-}
-
-/*
- * imageList - 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 - deconstructor.
- */
-
-imageList::~imageList ()
-{
- while (head != NULL) {
- imageItem *i = head;
- head = head->next;
- delete i;
- }
-}
-
-/*
- * createPage - creates 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 | "
- "gs%s -q -dBATCH -dSAFER "
- "-dDEVICEHEIGHTPOINTS=792 "
- "-dDEVICEWIDTHPOINTS=%d -dFIXEDMEDIA=true "
- "-sDEVICE=%s -r%d %s "
- "-sOutputFile=%s %s -\n",
- 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);
- a_delete s;
- currentPageNo = pageno;
- return 0;
-}
-
-/*
- * min - returns the minimum of two numbers.
- */
-
-int min (int x, int y)
-{
- if (x < y) {
- return( x );
- } else {
- return( y );
- }
-}
-
-/*
- * max - returns the maximum of two numbers.
- */
-
-int max (int x, int y)
-{
- if (x > y) {
- return( x );
- } else {
- return( y );
- }
-}
-
-/*
- * getMaxX - returns 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 - generates 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-1*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+1*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);
- a_delete 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 - 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 - foreach 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.
-
-/*
- * write_file_html - writes the buffer to stdout (troff).
- * It writes out the file replacing template image names with
- * actual image names.
- */
-
-void char_buffer::write_file_html (void)
-{
- char_block *t=head;
- int i=0;
-
- if (t != NULL) {
- do {
- write_upto_newline(&t, &i, TRUE);
- } while (t != NULL);
- }
- 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");
- }
- }
-}
-
-/*
- * generateImages - parses the region file and generates images
- * from the postscript file. The region file
- * contains the x1,y1 x2,y2 extents of each
- * image.
- */
-
-static void generateImages (char *regionFileName)
-{
- pushBackBuffer *f=new pushBackBuffer(regionFileName);
-
- 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;
-}
-
-/*
- * replaceFd - replace a file descriptor, was, with, willbe.
- */
-
-static void replaceFd (int was, int willbe)
-{
- int dupres;
-
- if (was != willbe) {
- if (close(was)<0) {
- sys_fatal("close");
- }
- dupres = dup(willbe);
- if (dupres != was) {
- sys_fatal("dup");
- fprintf(stderr, "trying to replace fd=%d with %d dup used %d\n", was, willbe, dupres);
- if (willbe == 1) {
- fprintf(stderr, "likely that stdout should be opened before %d\n", was);
- }
- exit(1);
- }
- if (close(willbe) < 0) {
- sys_fatal("close");
- }
- }
-}
-
-/*
- * waitForChild - waits for child, pid, to exit.
- */
-
-static void waitForChild (PID_T pid)
-{
- PID_T waitpd;
- int status;
-
- waitpd = WAIT(&status, pid, _WAIT_CHILD);
- if (waitpd != pid)
- sys_fatal("wait");
-}
-
-/*
- * alterDeviceTo - if toImage is set then the arg 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] = IMAGE_DEVICE;
- }
- i++;
- }
- argv[troff_arg] = "groff"; /* rather than troff */
- } else {
- while (i < argc) {
- if (strcmp(argv[i], IMAGE_DEVICE) == 0) {
- argv[i] = "-Thtml";
- }
- i++;
- }
- argv[troff_arg] = "groff"; /* use groff -Z */
- }
-}
-
-/*
- * addZ - appends -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] = "-Z";
- while (i)\n");
- fprintf(stream, " place all png files into image_directory\n");
-}
-
-/*
- * scanArguments - scans for all arguments including -P-i, -P-o, -P-D and -P-I. It returns
- * the argument index of the first non option.
- */
-
-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:g:o:i:I:D:F:vbdhlrnp", long_options, NULL))
- != EOF)
- switch(c) {
- case 'v':
- printf("GNU pre-grohtml (groff) version %s\n", Version_string);
- exit(0);
- 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 '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 'b':
- // handled by post-grohtml (set background color to white)
- break;
- case 'D':
- image_dir = optarg;
- break;
- case 'I':
- image_template = optarg;
- break;
- case 'i':
- image_res = atoi(optarg);
- break;
- case 'F':
- font_path.command_line_dir(optarg);
- break;
- case 'o':
- vertical_offset = atoi(optarg);
- break;
- case 'p':
- show_progress = TRUE;
- break;
- case 'd':
-#if defined(DEBUGGING)
- debug = TRUE;
-#endif
- break;
- case 'h':
- // handled by post-grohtml
- break;
- 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 = "/tmp/prehtml-ps";
- regionFileName = "/tmp/prehtml-region";
- imagePageName = "/tmp/prehtml-page";
- psPageName = "/tmp/prehtml-psn";
- troffFileName = "/tmp/prehtml-troff";
- htmlFileName = "/tmp/prehtml-html";
-#else
- 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
- return 0;
-}
-
-int main(int argc, char **argv)
-{
- program_name = argv[0];
- int i;
- int found=0;
- int ok=1;
-
- 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++;
- }
-
- copyofstdoutfd=dup(stdoutfd);
-
- 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)) {
- }
-
- if (fp != stdin)
- fclose(fp);
- current_filename = NULL;
- return 1;
-}
diff --git a/contrib/groff/src/preproc/html/pushback.cc b/contrib/groff/src/preproc/html/pushback.cc
deleted file mode 100644
index d18c5e2..0000000
--- a/contrib/groff/src/preproc/html/pushback.cc
+++ /dev/null
@@ -1,333 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 ()
-{
- int old;
-
- if (charStack != 0) {
- free(charStack);
- }
- close(0);
- /* restore stdin in file descriptor 0 */
- old = 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 float convertToFloat (int a, int b)
-{
- int c=10;
- float f;
-
- while (b>c) {
- c *= 10;
- }
- f = ((float)a) + (((float)b)/((float)c));
- return( f );
-}
-
-/*
- * readNumber - returns a float representing the word just read.
- */
-
-float pushBackBuffer::readNumber (void)
-{
- int i;
- char ch;
-
- i = readInt();
- if ((ch = getPB()) == '.') {
- return convertToFloat(i, readInt());
- }
- putPB(ch);
- return (float)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 *string = 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;
- string = (char *)malloc(strlen(buffer)+1);
- strcpy(string, buffer);
- }
- return( string );
-}
diff --git a/contrib/groff/src/preproc/pic/common.cc b/contrib/groff/src/preproc/pic/common.cc
deleted file mode 100644
index 5075e93..0000000
--- a/contrib/groff/src/preproc/pic/common.cc
+++ /dev/null
@@ -1,496 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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);
-}
-
-// 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/lex.cc b/contrib/groff/src/preproc/pic/lex.cc
deleted file mode 100644
index 14a4cc3..0000000
--- a/contrib/groff/src/preproc/pic/lex.cc
+++ /dev/null
@@ -1,1992 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 },
- { "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 to;
- int by_is_multiplicative;
- double by;
- const char *p;
- int done_newline;
-public:
- for_input(char *, double, int, double, char *);
- ~for_input();
- int get();
- int peek();
-};
-
-for_input::for_input(char *vr, double t, int bim, double b, char *bd)
-: var(vr), body(bd), 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 (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 (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 (from <= to)
- input_stack::push(new for_input(var, 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.cc b/contrib/groff/src/preproc/pic/main.cc
deleted file mode 100644
index 124cbd5..0000000
--- a/contrib/groff/src/preproc/pic/main.cc
+++ /dev/null
@@ -1,635 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1989-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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "pic.h"
-
-extern int yyparse();
-extern "C" const char *Version_string;
-
-output *out;
-
-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;
- 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)
- 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)
-{
-#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.cc b/contrib/groff/src/preproc/pic/object.cc
deleted file mode 100644
index fd25371..0000000
--- a/contrib/groff/src/preproc/pic/object.cc
+++ /dev/null
@@ -1,1894 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 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);
- out->polygon(v, 3, slt, 1);
- }
- else {
- position v[2];
- v[0] = pos;
- v[1] = pos + base + n;
- out->line(pos + base - n, v, 2, 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;
- 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;
-}
-
-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 = c;
-}
-
-void graphic_object::set_outline_color(char *c)
-{
- outline_color = 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 *fill)
-{
- color_fill = fill;
-}
-
-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());
- out->line(strt, v, n, lt);
- if (arrow_at_start)
- draw_arrow(strt, strt-v[0], aht, lt, graphic_object::get_outline_color());
- if (arrow_at_end)
- draw_arrow(en, v[n-1] - (n > 1 ? v[n - 2] : strt), aht, lt,
- graphic_object::get_outline_color());
- 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());
- out->spline(strt, v, n, lt);
- if (arrow_at_start)
- draw_arrow(strt, strt-v[0], aht, lt, graphic_object::get_outline_color());
- if (arrow_at_end)
- draw_arrow(en, v[n-1] - (n > 1 ? v[n - 2] : strt), aht, lt,
- graphic_object::get_outline_color());
- 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());
- if (clockwise)
- out->arc(en, cent, strt, lt);
- else
- out->arc(strt, cent, en, lt);
- if (arrow_at_start) {
- position c = cent - strt;
- draw_arrow(strt,
- (clockwise ? position(c.y, -c.x) : position(-c.y, c.x)),
- aht, lt, graphic_object::get_outline_color());
- }
- if (arrow_at_end) {
- position e = en - cent;
- draw_arrow(en,
- (clockwise ? position(e.y, -e.x) : position(-e.y, e.x)),
- aht, lt, graphic_object::get_outline_color());
- }
- 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 radius = 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 = radius;
- break;
- case 1:
- offset.y = radius;
- break;
- case 2:
- offset.x = -radius;
- break;
- case 3:
- offset.y = -radius;
- 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/tex.cc b/contrib/groff/src/preproc/pic/tex.cc
deleted file mode 100644
index a9192ac..0000000
--- a/contrib/groff/src/preproc/pic/tex.cc
+++ /dev/null
@@ -1,438 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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. */
- fputs("\\expandafter\\ifx\\csname graph\\endcsname\\relax \\csname newbox\\endcsname\\graph\\fi\n"
- "\\expandafter\\ifx\\csname graphtemp\\endcsname\\relax \\csname newdimen\\endcsname\\graphtemp\\fi\n"
- "\\setbox\\graph=\\vtop{\\vskip 0pt\\hbox{%\n",
- stdout);
- 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\\advance\\graphtemp by %.3fin\n", c.y);
- }
- else {
- printf(" \\graphtemp=\\baselineskip"
- "\\multiply\\graphtemp by %d"
- "\\divide\\graphtemp by 2\n"
- " \\advance\\graphtemp by .5ex"
- "\\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);
- 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)));
-}
-
-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/troff.cc b/contrib/groff/src/preproc/pic/troff.cc
deleted file mode 100644
index 7ee7293..0000000
--- a/contrib/groff/src/preproc/pic/troff.cc
+++ /dev/null
@@ -1,561 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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:
- case line_type::dashed:
- case line_type::solid:
- simple_ellipse(0, cent, dim);
- break;
- default:
- assert(0);
- }
-}
-
-#define FILL_MAX 1000
-
-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) {
- printf("\\D'f %du'\\h'%du'\n.sp -1\n", int(f*FILL_MAX), -int(f*FILL_MAX));
- last_fill = f;
- }
- if (last_filled) {
- free(last_filled);
- last_filled = 0;
- printf("\\M[]\n.sp -1\n");
- }
-}
-
-void troff_output::set_color(char *color_fill, char *color_outlined)
-{
- if (driver_extension_flag) {
- if (last_filled || last_outlined) {
- reset_color();
- }
- if (color_fill) {
- printf("\\M[%s]\n.sp -1\n", color_fill);
- last_filled = strdup(color_fill);
- }
- if (color_outlined) {
- printf("\\m[%s]\n.sp -1\n", color_outlined);
- last_outlined = strdup(color_outlined);
- }
- }
-}
-
-void troff_output::reset_color()
-{
- if (driver_extension_flag) {
- if (last_filled) {
- printf("\\M[]\n.sp -1\n");
- free(last_filled);
- last_filled = 0;
- }
- if (last_outlined) {
- printf("\\m[]\n.sp -1\n");
- free(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/command.cc b/contrib/groff/src/preproc/refer/command.cc
deleted file mode 100644
index a7c6bfb..0000000
--- a/contrib/groff/src/preproc/refer/command.cc
+++ /dev/null
@@ -1,809 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 {
- 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/ref.cc b/contrib/groff/src/preproc/refer/ref.cc
deleted file mode 100644
index 9c04078..0000000
--- a/contrib/groff/src/preproc/refer/ref.cc
+++ /dev/null
@@ -1,1160 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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') {
- if (sf > sort_fields)
- 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/refer.cc b/contrib/groff/src/preproc/refer/refer.cc
deleted file mode 100644
index 33df35c..0000000
--- a/contrib/groff/src/preproc/refer/refer.cc
+++ /dev/null
@@ -1,1235 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1989-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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 (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/token.cc b/contrib/groff/src/preproc/refer/token.cc
deleted file mode 100644
index e9fac5d..0000000
--- a/contrib/groff/src/preproc/refer/token.cc
+++ /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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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/soelim/soelim.cc b/contrib/groff/src/preproc/soelim/soelim.cc
deleted file mode 100644
index 006b04a..0000000
--- a/contrib/groff/src/preproc/soelim/soelim.cc
+++ /dev/null
@@ -1,346 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1989-1992, 2000, 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "lib.h"
-
-#include
-#include
-#include
-#include
-#include "errarg.h"
-#include "error.h"
-#include "stringclass.h"
-#include "nonposix.h"
-
-static size_t include_list_length;
-static char **include_list;
-
-int compatible_flag = 0;
-
-extern int interpret_lf_args(const char *);
-extern "C" const char *Version_string;
-
-int do_file(const char *filename);
-
-
-static void
-include_path_append(char *path)
-{
- ++include_list_length;
- size_t nbytes = include_list_length * sizeof(char *);
- if (include_list)
- include_list = (char **)realloc((void *)include_list, nbytes);
- else
- include_list = (char **)malloc(nbytes);
- if (include_list == NULL)
- {
- fprintf(stderr, "%s: out of memory\n", program_name);
- exit(2);
- }
- include_list[include_list_length - 1] = path;
-}
-
-
-void usage(FILE *stream)
-{
- fprintf(stream, "usage: %s [ -vC ] [ -I file ] [ files ]\n", program_name);
-}
-
-int main(int argc, char **argv)
-{
- program_name = argv[0];
- include_path_append(".");
- 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:v", 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_path_append(optarg);
- 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()
-{
- printf(".lf %d %s\n", current_lineno, current_filename);
-}
-
-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)
-{
- FILE *fp;
- string whole_filename;
- if (strcmp(filename, "-") == 0) {
- fp = stdin;
- whole_filename = filename;
- whole_filename += '\0';
- }
- else if (IS_ABSOLUTE(filename)) {
- whole_filename = filename;
- whole_filename += '\0';
- errno = 0;
- fp = fopen(filename, "r");
- if (fp == 0) {
- error("can't open `%1': %2", filename, strerror(errno));
- return 0;
- }
- }
- else {
- size_t j;
- for (j = 0; j < include_list_length; ++j)
- {
- char *path = include_list[j];
- if (0 == strcmp(path, "."))
- whole_filename = filename;
- else
- whole_filename = string(path) + "/" + filename;
- whole_filename += '\0';
- errno = 0;
- fp = fopen(whole_filename.contents(), "r");
- if (fp != 0)
- break;
- if (errno != ENOENT) {
- error("can't open `%1': %2",
- whole_filename.contents(), strerror(errno));
- return 0;
- }
- }
- if (j >= include_list_length)
- {
- errno = ENOENT;
- error("can't open `%1': %2", filename, strerror(errno));
- 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/tbl/main.cc b/contrib/groff/src/preproc/tbl/main.cc
deleted file mode 100644
index dc0bdce..0000000
--- a/contrib/groff/src/preproc/tbl/main.cc
+++ /dev/null
@@ -1,1529 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "table.h"
-
-#define MAX_POINT_SIZE 99
-#define MAX_VERTICAL_SPACING 72
-
-extern "C" const char *Version_string;
-
-static int compatible_flag = 0;
-
-class table_input {
- FILE *fp;
- enum { START, MIDDLE, REREAD_T, REREAD_TE, REREAD_E, 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
- if ((c = getc(fp)) == '\\') {
- c = getc(fp);
- if (c == '\n')
- c = getc(fp); // perhaps state ought to be START now
- 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 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);
- }
- 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 '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 point size");
- 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 c;
- for (c = 0; c < ncolumns; c++) {
- entry_format *e = f->entry[format_index] + c;
- if (e->type != FORMAT_HLINE
- && e->type != FORMAT_DOUBLE_HLINE
- // Unfortunately tbl treats a span as needing data.
- // && e->type != FORMAT_SPAN
- )
- break;
- }
- if (c < ncolumns)
- break;
- for (c = 0; c < ncolumns; c++)
- tbl->add_entry(current_row, c, input_entry,
- f->entry[format_index] + c, 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 (c == '\n' || c == tab_char)
- state = END;
- else {
- input_entry += 'T';
- input_entry += '}';
- input_entry += c;
- state = c == '\n' ? START : 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)
-{
- int c;
- 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 ((c = 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) {
- current_lineno = -1;
- error("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.cc b/contrib/groff/src/preproc/tbl/table.cc
deleted file mode 100644
index c7f96cd..0000000
--- a/contrib/groff/src/preproc/tbl/table.cc
+++ /dev/null
@@ -1,2778 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 PREFIX "3"
-#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 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;
- short start_col;
- short end_col;
- horizontal_span(int, int, horizontal_span *);
-};
-
-struct single_line_entry;
-struct double_line_entry;
-struct 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;
- short start_col;
- short 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");
- set_modifier(mod);
- prints(".cp \\n(" COMPATIBLE_REG "\n");
- 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));
- }
-}
-
-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;
- short 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");
- 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 no 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)
- 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/roff/groff/groff.cc b/contrib/groff/src/roff/groff/groff.cc
deleted file mode 100644
index 49104b2..0000000
--- a/contrib/groff/src/roff/groff/groff.cc
+++ /dev/null
@@ -1,753 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1989-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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-// A front end for groff.
-
-#include "lib.h"
-
-#include
-#include
-#include
-
-#include "assert.h"
-#include "errarg.h"
-#include "error.h"
-#include "stringclass.h"
-#include "cset.h"
-#include "font.h"
-#include "device.h"
-#include "pipeline.h"
-#include "nonposix.h"
-#include "defs.h"
-
-#define GXDITVIEW "gxditview"
-
-// troff will be passed an argument of -rXREG=1 if the -X option is
-// specified
-#define XREG ".X"
-
-#ifdef NEED_DECLARATION_PUTENV
-extern "C" {
- int putenv(const char *);
-}
-#endif /* NEED_DECLARATION_PUTENV */
-
-// The number of commands must be in sync with MAX_COMMANDS in pipeline.h
-const int SOELIM_INDEX = 0;
-const int REFER_INDEX = SOELIM_INDEX + 1;
-const int GRAP_INDEX = REFER_INDEX + 1;
-const int PIC_INDEX = GRAP_INDEX + 1;
-const int TBL_INDEX = PIC_INDEX + 1;
-const int GRN_INDEX = TBL_INDEX + 1;
-const int EQN_INDEX = GRN_INDEX + 1;
-const int TROFF_INDEX = EQN_INDEX + 1;
-const int POST_INDEX = TROFF_INDEX + 1;
-const int SPOOL_INDEX = POST_INDEX + 1;
-
-const int NCOMMANDS = SPOOL_INDEX + 1;
-
-class possible_command {
- char *name;
- string args;
- char **argv;
-
- void build_argv();
-public:
- possible_command();
- ~possible_command();
- void set_name(const char *);
- void set_name(const char *, const char *);
- const char *get_name();
- void append_arg(const char *, const char * = 0);
- void insert_arg(const char *);
- void insert_args(string s);
- void clear_args();
- char **get_argv();
- void print(int is_last, FILE *fp);
-};
-
-extern "C" const char *Version_string;
-
-int lflag = 0;
-char *spooler = 0;
-char *postdriver = 0;
-char *predriver = 0;
-
-possible_command commands[NCOMMANDS];
-
-int run_commands(int no_pipe);
-void print_commands();
-void append_arg_to_string(const char *arg, string &str);
-void handle_unknown_desc_command(const char *command, const char *arg,
- const char *filename, int lineno);
-const char *xbasename(const char *);
-
-void usage(FILE *stream);
-void help();
-
-int main(int argc, char **argv)
-{
- program_name = argv[0];
- static char stderr_buf[BUFSIZ];
- setbuf(stderr, stderr_buf);
- assert(NCOMMANDS <= MAX_COMMANDS);
- string Pargs, Largs, Fargs;
- int vflag = 0;
- int Vflag = 0;
- int zflag = 0;
- int iflag = 0;
- int Xflag = 0;
- int safer_flag = 1;
- int opt;
- const char *command_prefix = getenv("GROFF_COMMAND_PREFIX");
- if (!command_prefix)
- command_prefix = PROG_PREFIX;
- commands[TROFF_INDEX].set_name(command_prefix, "troff");
- static const struct option long_options[] = {
- { "help", no_argument, 0, 'h' },
- { "version", no_argument, 0, 'v' },
- { NULL, 0, 0, 0 }
- };
- while ((opt = getopt_long(argc, argv,
- "abcCd:eEf:F:gGhiI:lL:m:M:n:No:pP:r:RsStT:UvVw:W:XzZ",
- long_options, NULL))
- != EOF) {
- char buf[3];
- buf[0] = '-';
- buf[1] = opt;
- buf[2] = '\0';
- switch (opt) {
- case 'i':
- iflag = 1;
- break;
- case 'I':
- commands[SOELIM_INDEX].set_name(command_prefix, "soelim");
- commands[SOELIM_INDEX].append_arg(buf, optarg);
- break;
- case 't':
- commands[TBL_INDEX].set_name(command_prefix, "tbl");
- break;
- case 'p':
- commands[PIC_INDEX].set_name(command_prefix, "pic");
- break;
- case 'g':
- commands[GRN_INDEX].set_name(command_prefix, "grn");
- break;
- case 'G':
- commands[GRAP_INDEX].set_name(command_prefix, "grap");
- break;
- case 'e':
- commands[EQN_INDEX].set_name(command_prefix, "eqn");
- break;
- case 's':
- commands[SOELIM_INDEX].set_name(command_prefix, "soelim");
- break;
- case 'R':
- commands[REFER_INDEX].set_name(command_prefix, "refer");
- break;
- case 'z':
- case 'a':
- commands[TROFF_INDEX].append_arg(buf);
- // fall through
- case 'Z':
- zflag++;
- break;
- case 'l':
- lflag++;
- break;
- case 'V':
- Vflag++;
- break;
- case 'v':
- vflag = 1;
- {
- printf("GNU groff version %s\n", Version_string);
- printf("Copyright (C) 2002 Free Software Foundation, Inc.\n"
- "GNU groff comes with ABSOLUTELY NO WARRANTY.\n"
- "You may redistribute copies of groff and its subprograms\n"
- "under the terms of the GNU General Public License.\n"
- "For more information about these matters, see the file named COPYING.\n");
- printf("\ncalled subprograms:\n\n");
- fflush(stdout);
- }
- commands[POST_INDEX].append_arg(buf);
- // fall through
- case 'C':
- commands[SOELIM_INDEX].append_arg(buf);
- commands[REFER_INDEX].append_arg(buf);
- commands[PIC_INDEX].append_arg(buf);
- commands[GRAP_INDEX].append_arg(buf);
- commands[TBL_INDEX].append_arg(buf);
- commands[GRN_INDEX].append_arg(buf);
- commands[EQN_INDEX].append_arg(buf);
- commands[TROFF_INDEX].append_arg(buf);
- break;
- case 'N':
- commands[EQN_INDEX].append_arg(buf);
- break;
- case 'h':
- help();
- break;
- case 'E':
- case 'b':
- commands[TROFF_INDEX].append_arg(buf);
- break;
- case 'c':
- commands[TROFF_INDEX].append_arg(buf);
- break;
- case 'S':
- safer_flag = 1;
- break;
- case 'U':
- safer_flag = 0;
- break;
- case 'T':
- if (strcmp(optarg, "html") == 0) {
- // force soelim to aid the html preprocessor
- commands[SOELIM_INDEX].set_name(command_prefix, "soelim");
- }
- if (strcmp(optarg, "Xps") == 0) {
- warning("-TXps option is obsolete: use -X -Tps instead");
- device = "ps";
- Xflag++;
- }
- else
- device = optarg;
- break;
- case 'F':
- font::command_line_font_dir(optarg);
- if (Fargs.length() > 0) {
- Fargs += PATH_SEP[0];
- Fargs += optarg;
- }
- else
- Fargs = optarg;
- break;
- case 'f':
- case 'o':
- case 'm':
- case 'r':
- case 'd':
- case 'n':
- case 'w':
- case 'W':
- commands[TROFF_INDEX].append_arg(buf, optarg);
- break;
- case 'M':
- commands[EQN_INDEX].append_arg(buf, optarg);
- commands[GRAP_INDEX].append_arg(buf, optarg);
- commands[GRN_INDEX].append_arg(buf, optarg);
- commands[TROFF_INDEX].append_arg(buf, optarg);
- break;
- case 'P':
- Pargs += optarg;
- Pargs += '\0';
- break;
- case 'L':
- append_arg_to_string(optarg, Largs);
- break;
- case 'X':
- Xflag++;
- break;
- case '?':
- usage(stderr);
- exit(1);
- break;
- default:
- assert(0);
- break;
- }
- }
- if (safer_flag)
- commands[PIC_INDEX].append_arg("-S");
- else
- commands[TROFF_INDEX].insert_arg("-U");
- font::set_unknown_desc_command_handler(handle_unknown_desc_command);
- if (!font::load_desc())
- fatal("invalid device `%1'", device);
- if (!postdriver)
- fatal("no `postpro' command in DESC file for device `%1'", device);
- if (predriver && !zflag) {
- commands[TROFF_INDEX].insert_arg(commands[TROFF_INDEX].get_name());
- commands[TROFF_INDEX].set_name(predriver);
- // pass the device arguments to the predrivers as well
- commands[TROFF_INDEX].insert_args(Pargs);
- if (vflag)
- commands[TROFF_INDEX].insert_arg("-v");
- }
- const char *real_driver = 0;
- if (Xflag) {
- real_driver = postdriver;
- postdriver = GXDITVIEW;
- commands[TROFF_INDEX].append_arg("-r" XREG "=", "1");
- }
- if (postdriver)
- commands[POST_INDEX].set_name(postdriver);
- int gxditview_flag = postdriver && strcmp(xbasename(postdriver), GXDITVIEW) == 0;
- if (gxditview_flag && argc - optind == 1) {
- commands[POST_INDEX].append_arg("-title");
- commands[POST_INDEX].append_arg(argv[optind]);
- commands[POST_INDEX].append_arg("-xrm");
- commands[POST_INDEX].append_arg("*iconName:", argv[optind]);
- string filename_string("|");
- append_arg_to_string(argv[0], filename_string);
- append_arg_to_string("-Z", filename_string);
- for (int i = 1; i < argc; i++)
- append_arg_to_string(argv[i], filename_string);
- filename_string += '\0';
- commands[POST_INDEX].append_arg("-filename");
- commands[POST_INDEX].append_arg(filename_string.contents());
- }
- if (gxditview_flag && Xflag) {
- string print_string(real_driver);
- if (spooler) {
- print_string += " | ";
- print_string += spooler;
- print_string += Largs;
- }
- print_string += '\0';
- commands[POST_INDEX].append_arg("-printCommand");
- commands[POST_INDEX].append_arg(print_string.contents());
- }
- const char *p = Pargs.contents();
- const char *end = p + Pargs.length();
- while (p < end) {
- commands[POST_INDEX].append_arg(p);
- p = strchr(p, '\0') + 1;
- }
- if (gxditview_flag)
- commands[POST_INDEX].append_arg("-");
- if (lflag && !Xflag && spooler) {
- commands[SPOOL_INDEX].set_name(BSHELL);
- commands[SPOOL_INDEX].append_arg(BSHELL_DASH_C);
- Largs += '\0';
- Largs = spooler + Largs;
- commands[SPOOL_INDEX].append_arg(Largs.contents());
- }
- if (zflag) {
- commands[POST_INDEX].set_name(0);
- commands[SPOOL_INDEX].set_name(0);
- }
- commands[TROFF_INDEX].append_arg("-T", device);
- // html renders equations as images via ps
- if (strcmp(device, "html") == 0)
- commands[EQN_INDEX].append_arg("-Tps:html");
- else
- commands[EQN_INDEX].append_arg("-T", device);
-
- commands[GRN_INDEX].append_arg("-T", device);
-
- int first_index;
- for (first_index = 0; first_index < TROFF_INDEX; first_index++)
- if (commands[first_index].get_name() != 0)
- break;
- if (optind < argc) {
- if (argv[optind][0] == '-' && argv[optind][1] != '\0')
- commands[first_index].append_arg("--");
- for (int i = optind; i < argc; i++)
- commands[first_index].append_arg(argv[i]);
- if (iflag)
- commands[first_index].append_arg("-");
- }
- if (Fargs.length() > 0) {
- string e = "GROFF_FONT_PATH";
- e += '=';
- e += Fargs;
- char *fontpath = getenv("GROFF_FONT_PATH");
- if (fontpath && *fontpath) {
- e += PATH_SEP[0];
- e += fontpath;
- }
- e += '\0';
- if (putenv(strsave(e.contents())))
- fatal("putenv failed");
- }
- {
- // we save the original path in GROFF_PATH__ and put it into the
- // environment -- troff will pick it up later.
- char *path = getenv("PATH");
- string e = "GROFF_PATH__";
- e += '=';
- if (path && *path)
- e += path;
- e += '\0';
- if (putenv(strsave(e.contents())))
- fatal("putenv failed");
- char *binpath = getenv("GROFF_BIN_PATH");
- string f = "PATH";
- f += '=';
- if (binpath && *binpath)
- f += binpath;
- else
- f += BINPATH;
- if (path && *path) {
- f += PATH_SEP[0];
- f += path;
- }
- f += '\0';
- if (putenv(strsave(f.contents())))
- fatal("putenv failed");
- }
- if (Vflag) {
- print_commands();
- exit(0);
- }
- return run_commands(vflag);
-}
-
-const char *xbasename(const char *s)
-{
- if (!s)
- return 0;
- // DIR_SEPS[] are possible directory separator characters, see nonposix.h
- // We want the rightmost separator of all possible ones.
- // Example: d:/foo\\bar.
- const char *p = strrchr(s, DIR_SEPS[0]), *p1;
- const char *sep = &DIR_SEPS[1];
-
- while (*sep)
- {
- p1 = strrchr(s, *sep);
- if (p1 && (!p || p1 > p))
- p = p1;
- sep++;
- }
- return p ? p + 1 : s;
-}
-
-void handle_unknown_desc_command(const char *command, const char *arg,
- const char *filename, int lineno)
-{
- if (strcmp(command, "print") == 0) {
- if (arg == 0)
- error_with_file_and_line(filename, lineno,
- "`print' command requires an argument");
- else
- spooler = strsave(arg);
- }
- if (strcmp(command, "prepro") == 0) {
- if (arg == 0)
- error_with_file_and_line(filename, lineno,
- "`prepro' command requires an argument");
- else {
- for (const char *p = arg; *p; p++)
- if (csspace(*p)) {
- error_with_file_and_line(filename, lineno,
- "invalid `prepro' argument `%1'"
- ": program name required", arg);
- return;
- }
- predriver = strsave(arg);
- }
- }
- if (strcmp(command, "postpro") == 0) {
- if (arg == 0)
- error_with_file_and_line(filename, lineno,
- "`postpro' command requires an argument");
- else {
- for (const char *p = arg; *p; p++)
- if (csspace(*p)) {
- error_with_file_and_line(filename, lineno,
- "invalid `postpro' argument `%1'"
- ": program name required", arg);
- return;
- }
- postdriver = strsave(arg);
- }
- }
-}
-
-void print_commands()
-{
- int last;
- for (last = SPOOL_INDEX; last >= 0; last--)
- if (commands[last].get_name() != 0)
- break;
- for (int i = 0; i <= last; i++)
- if (commands[i].get_name() != 0)
- commands[i].print(i == last, stdout);
-}
-
-// Run the commands. Return the code with which to exit.
-
-int run_commands(int no_pipe)
-{
- char **v[NCOMMANDS];
- int j = 0;
- for (int i = 0; i < NCOMMANDS; i++)
- if (commands[i].get_name() != 0)
- v[j++] = commands[i].get_argv();
- return run_pipeline(j, v, no_pipe);
-}
-
-possible_command::possible_command()
-: name(0), argv(0)
-{
-}
-
-possible_command::~possible_command()
-{
- a_delete name;
- a_delete argv;
-}
-
-void possible_command::set_name(const char *s)
-{
- a_delete name;
- name = strsave(s);
-}
-
-void possible_command::set_name(const char *s1, const char *s2)
-{
- a_delete name;
- name = new char[strlen(s1) + strlen(s2) + 1];
- strcpy(name, s1);
- strcat(name, s2);
-}
-
-const char *possible_command::get_name()
-{
- return name;
-}
-
-void possible_command::clear_args()
-{
- args.clear();
-}
-
-void possible_command::append_arg(const char *s, const char *t)
-{
- args += s;
- if (t)
- args += t;
- args += '\0';
-}
-
-void possible_command::insert_arg(const char *s)
-{
- string str(s);
- str += '\0';
- str += args;
- args = str;
-}
-
-void possible_command::insert_args(string s)
-{
- const char *p = s.contents();
- const char *end = p + s.length();
- int l = 0;
- if (p >= end)
- return;
- // find the total number of arguments in our string
- do {
- l++;
- p = strchr(p, '\0') + 1;
- } while (p < end);
- // now insert each argument preserving the order
- for (int i = l - 1; i >= 0; i--) {
- p = s.contents();
- for (int j = 0; j < i; j++)
- p = strchr(p, '\0') + 1;
- insert_arg(p);
- }
-}
-
-void possible_command::build_argv()
-{
- if (argv)
- return;
- // Count the number of arguments.
- int len = args.length();
- int argc = 1;
- char *p = 0;
- if (len > 0) {
- p = &args[0];
- for (int i = 0; i < len; i++)
- if (p[i] == '\0')
- argc++;
- }
- // Build an argument vector.
- argv = new char *[argc + 1];
- argv[0] = name;
- for (int i = 1; i < argc; i++) {
- argv[i] = p;
- p = strchr(p, '\0') + 1;
- }
- argv[argc] = 0;
-}
-
-void possible_command::print(int is_last, FILE *fp)
-{
- build_argv();
- if (IS_BSHELL(argv[0])
- && argv[1] != 0 && strcmp(argv[1], BSHELL_DASH_C) == 0
- && argv[2] != 0 && argv[3] == 0)
- fputs(argv[2], fp);
- else {
- fputs(argv[0], fp);
- string str;
- for (int i = 1; argv[i] != 0; i++) {
- str.clear();
- append_arg_to_string(argv[i], str);
- put_string(str, fp);
- }
- }
- if (is_last)
- putc('\n', fp);
- else
- fputs(" | ", fp);
-}
-
-void append_arg_to_string(const char *arg, string &str)
-{
- str += ' ';
- int needs_quoting = 0;
- int contains_single_quote = 0;
- const char*p;
- for (p = arg; *p != '\0'; p++)
- switch (*p) {
- case ';':
- case '&':
- case '(':
- case ')':
- case '|':
- case '^':
- case '<':
- case '>':
- case '\n':
- case ' ':
- case '\t':
- case '\\':
- case '"':
- case '$':
- case '?':
- case '*':
- needs_quoting = 1;
- break;
- case '\'':
- contains_single_quote = 1;
- break;
- }
- if (contains_single_quote || arg[0] == '\0') {
- str += '"';
- for (p = arg; *p != '\0'; p++)
- switch (*p) {
- case '"':
- case '\\':
- case '$':
- str += '\\';
- // fall through
- default:
- str += *p;
- break;
- }
- str += '"';
- }
- else if (needs_quoting) {
- str += '\'';
- str += arg;
- str += '\'';
- }
- else
- str += arg;
-}
-
-char **possible_command::get_argv()
-{
- build_argv();
- return argv;
-}
-
-void synopsis(FILE *stream)
-{
- fprintf(stream,
-"usage: %s [-abceghilpstvzCENRSUVXZ] [-Fdir] [-mname] [-Tdev] [-ffam]\n"
-" [-wname] [-Wname] [-Mdir] [-dcs] [-rcn] [-nnum] [-olist] [-Parg]\n"
-" [-Larg] [-Idir] [files...]\n",
- program_name);
-}
-
-void help()
-{
- synopsis(stdout);
- fputs("\n"
-"-h\tprint this message\n"
-"-t\tpreprocess with tbl\n"
-"-p\tpreprocess with pic\n"
-"-e\tpreprocess with eqn\n"
-"-g\tpreprocess with grn\n"
-"-G\tpreprocess with grap\n"
-"-s\tpreprocess with soelim\n"
-"-R\tpreprocess with refer\n"
-"-Tdev\tuse device dev\n"
-"-X\tuse X11 previewer rather than usual postprocessor\n"
-"-mname\tread macros tmac.name\n"
-"-dcs\tdefine a string c as s\n"
-"-rcn\tdefine a number register c as n\n"
-"-nnum\tnumber first page n\n"
-"-olist\toutput only pages in list\n"
-"-ffam\tuse fam as the default font family\n"
-"-Fdir\tsearch dir for device directories\n"
-"-Mdir\tsearch dir for macro files\n"
-"-v\tprint version number\n"
-"-z\tsuppress formatted output\n"
-"-Z\tdon't postprocess\n"
-"-a\tproduce ASCII description of output\n"
-"-i\tread standard input after named input files\n"
-"-wname\tenable warning name\n"
-"-Wname\tinhibit warning name\n"
-"-E\tinhibit all errors\n"
-"-b\tprint backtraces with errors or warnings\n"
-"-l\tspool the output\n"
-"-c\tdisable color output\n"
-"-C\tenable compatibility mode\n"
-"-V\tprint commands on stdout instead of running them\n"
-"-Parg\tpass arg to the postprocessor\n"
-"-Larg\tpass arg to the spooler\n"
-"-N\tdon't allow newlines within eqn delimiters\n"
-"-S\tenable safer mode (the default)\n"
-"-U\tenable unsafe mode\n"
-"-Idir\tsearch dir for soelim. Implies -s\n"
-"\n",
- stdout);
- exit(0);
-}
-
-void usage(FILE *stream)
-{
- synopsis(stream);
- fprintf(stream, "%s -h gives more help\n", program_name);
-}
-
-extern "C" {
-
-void c_error(const char *format, const char *arg1, const char *arg2,
- const char *arg3)
-{
- error(format, arg1, arg2, arg3);
-}
-
-void c_fatal(const char *format, const char *arg1, const char *arg2,
- const char *arg3)
-{
- fatal(format, arg1, arg2, arg3);
-}
-
-}
diff --git a/contrib/groff/src/roff/troff/column.cc b/contrib/groff/src/roff/troff/column.cc
deleted file mode 100644
index 8d6a6eb..0000000
--- a/contrib/groff/src/roff/troff/column.cc
+++ /dev/null
@@ -1,732 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#ifdef COLUMN
-
-#include "troff.h"
-#include "symbol.h"
-#include "dictionary.h"
-#include "hvunits.h"
-#include "env.h"
-#include "request.h"
-#include "node.h"
-#include "token.h"
-#include "div.h"
-#include "reg.h"
-#include "stringclass.h"
-
-void output_file::vjustify(vunits, symbol)
-{
- // do nothing
-}
-
-struct justification_spec;
-struct output_line;
-
-class column : public output_file {
-private:
- output_file *out;
- vunits bottom;
- output_line *col;
- output_line **tail;
- void add_output_line(output_line *);
- void begin_page(int pageno, vunits page_length);
- void flush();
- void print_line(hunits, vunits, node *, vunits, vunits);
- void vjustify(vunits, symbol);
- void transparent_char(unsigned char c);
- void copy_file(hunits, vunits, const char *);
- int is_printing();
- void check_bottom();
-public:
- column();
- ~column();
- void start();
- void output();
- void justify(const justification_spec &);
- void trim();
- void reset();
- vunits get_bottom();
- vunits get_last_extra_space();
- int is_active() { return out != 0; }
-};
-
-column *the_column = 0;
-
-struct transparent_output_line;
-struct vjustify_output_line;
-
-class output_line {
- output_line *next;
-public:
- output_line();
- virtual ~output_line();
- virtual void output(output_file *, vunits);
- virtual transparent_output_line *as_transparent_output_line();
- virtual vjustify_output_line *as_vjustify_output_line();
- virtual vunits distance();
- virtual vunits height();
- virtual void reset();
- virtual vunits extra_space(); // post line
- friend class column;
- friend class justification_spec;
-};
-
-class position_output_line : public output_line {
- vunits dist;
-public:
- position_output_line(vunits);
- vunits distance();
-};
-
-class node_output_line : public position_output_line {
- node *nd;
- hunits page_offset;
- vunits before;
- vunits after;
-public:
- node_output_line(vunits, node *, hunits, vunits, vunits);
- ~node_output_line();
- void output(output_file *, vunits);
- vunits height();
- vunits extra_space();
-};
-
-class vjustify_output_line : public position_output_line {
- vunits current;
- symbol typ;
-public:
- vjustify_output_line(vunits dist, symbol);
- vunits height();
- vjustify_output_line *as_vjustify_output_line();
- void vary(vunits amount);
- void reset();
- symbol type();
-};
-
-inline symbol vjustify_output_line::type()
-{
- return typ;
-}
-
-class copy_file_output_line : public position_output_line {
- symbol filename;
- hunits hpos;
-public:
- copy_file_output_line(vunits, const char *, hunits);
- void output(output_file *, vunits);
-};
-
-class transparent_output_line : public output_line {
- string buf;
-public:
- transparent_output_line();
- void output(output_file *, vunits);
- void append_char(unsigned char c);
- transparent_output_line *as_transparent_output_line();
-};
-
-output_line::output_line() : next(0)
-{
-}
-
-output_line::~output_line()
-{
-}
-
-void output_line::reset()
-{
-}
-
-transparent_output_line *output_line::as_transparent_output_line()
-{
- return 0;
-}
-
-vjustify_output_line *output_line::as_vjustify_output_line()
-{
- return 0;
-}
-
-void output_line::output(output_file *, vunits)
-{
-}
-
-vunits output_line::distance()
-{
- return V0;
-}
-
-vunits output_line::height()
-{
- return V0;
-}
-
-vunits output_line::extra_space()
-{
- return V0;
-}
-
-position_output_line::position_output_line(vunits d)
-: dist(d)
-{
-}
-
-vunits position_output_line::distance()
-{
- return dist;
-}
-
-node_output_line::node_output_line(vunits d, node *n, hunits po, vunits b, vunits a)
-: position_output_line(d), nd(n), page_offset(po), before(b), after(a)
-{
-}
-
-node_output_line::~node_output_line()
-{
- delete_node_list(nd);
-}
-
-void node_output_line::output(output_file *out, vunits pos)
-{
- out->print_line(page_offset, pos, nd, before, after);
- nd = 0;
-}
-
-vunits node_output_line::height()
-{
- return after;
-}
-
-vunits node_output_line::extra_space()
-{
- return after;
-}
-
-vjustify_output_line::vjustify_output_line(vunits d, symbol t)
-: position_output_line(d), typ(t)
-{
-}
-
-void vjustify_output_line::reset()
-{
- current = V0;
-}
-
-vunits vjustify_output_line::height()
-{
- return current;
-}
-
-vjustify_output_line *vjustify_output_line::as_vjustify_output_line()
-{
- return this;
-}
-
-inline void vjustify_output_line::vary(vunits amount)
-{
- current += amount;
-}
-
-transparent_output_line::transparent_output_line()
-{
-}
-
-transparent_output_line *transparent_output_line::as_transparent_output_line()
-{
- return this;
-}
-
-void transparent_output_line::append_char(unsigned char c)
-{
- assert(c != 0);
- buf += c;
-}
-
-void transparent_output_line::output(output_file *out, vunits)
-{
- int len = buf.length();
- for (int i = 0; i < len; i++)
- out->transparent_char(buf[i]);
-}
-
-copy_file_output_line::copy_file_output_line(vunits d, const char *f, hunits h)
-: position_output_line(d), hpos(h), filename(f)
-{
-}
-
-void copy_file_output_line::output(output_file *out, vunits pos)
-{
- out->copy_file(hpos, pos, filename.contents());
-}
-
-column::column()
-: bottom(V0), col(0), tail(&col), out(0)
-{
-}
-
-column::~column()
-{
- assert(out != 0);
- error("automatically outputting column before exiting");
- output();
- delete the_output;
-}
-
-void column::start()
-{
- assert(out == 0);
- if (!the_output)
- init_output();
- assert(the_output != 0);
- out = the_output;
- the_output = this;
-}
-
-void column::begin_page(int pageno, vunits page_length)
-{
- assert(out != 0);
- if (col) {
- error("automatically outputting column before beginning next page");
- output();
- the_output->begin_page(pageno, page_length);
- }
- else
- out->begin_page(pageno, page_length);
-
-}
-
-void column::flush()
-{
- assert(out != 0);
- out->flush();
-}
-
-int column::is_printing()
-{
- assert(out != 0);
- return out->is_printing();
-}
-
-vunits column::get_bottom()
-{
- return bottom;
-}
-
-void column::add_output_line(output_line *ln)
-{
- *tail = ln;
- bottom += ln->distance();
- bottom += ln->height();
- ln->next = 0;
- tail = &(*tail)->next;
-}
-
-void column::print_line(hunits page_offset, vunits pos, node *nd,
- vunits before, vunits after)
-{
- assert(out != 0);
- add_output_line(new node_output_line(pos - bottom, nd, page_offset, before, after));
-}
-
-void column::vjustify(vunits pos, symbol typ)
-{
- assert(out != 0);
- add_output_line(new vjustify_output_line(pos - bottom, typ));
-}
-
-void column::transparent_char(unsigned char c)
-{
- assert(out != 0);
- transparent_output_line *tl = 0;
- if (*tail)
- tl = (*tail)->as_transparent_output_line();
- if (!tl) {
- tl = new transparent_output_line;
- add_output_line(tl);
- }
- tl->append_char(c);
-}
-
-void column::copy_file(hunits page_offset, vunits pos, const char *filename)
-{
- assert(out != 0);
- add_output_line(new copy_file_output_line(pos - bottom, filename, page_offset));
-}
-
-void column::trim()
-{
- output_line **spp = 0;
- for (output_line **pp = &col; *pp; pp = &(*pp)->next)
- if ((*pp)->as_vjustify_output_line() == 0)
- spp = 0;
- else if (!spp)
- spp = pp;
- if (spp) {
- output_line *ln = *spp;
- *spp = 0;
- tail = spp;
- while (ln) {
- output_line *tem = ln->next;
- bottom -= ln->distance();
- bottom -= ln->height();
- delete ln;
- ln = tem;
- }
- }
-}
-
-void column::reset()
-{
- bottom = V0;
- for (output_line *ln = col; ln; ln = ln->next) {
- bottom += ln->distance();
- ln->reset();
- bottom += ln->height();
- }
-}
-
-void column::check_bottom()
-{
- vunits b;
- for (output_line *ln = col; ln; ln = ln->next) {
- b += ln->distance();
- b += ln->height();
- }
- assert(b == bottom);
-}
-
-void column::output()
-{
- assert(out != 0);
- vunits vpos(V0);
- output_line *ln = col;
- while (ln) {
- vpos += ln->distance();
- ln->output(out, vpos);
- vpos += ln->height();
- output_line *tem = ln->next;
- delete ln;
- ln = tem;
- }
- tail = &col;
- bottom = V0;
- col = 0;
- the_output = out;
- out = 0;
-}
-
-vunits column::get_last_extra_space()
-{
- if (!col)
- return V0;
- for (output_line *p = col; p->next; p = p->next)
- ;
- return p->extra_space();
-}
-
-class justification_spec {
- vunits height;
- symbol *type;
- vunits *amount;
- int n;
- int maxn;
-public:
- justification_spec(vunits);
- ~justification_spec();
- void append(symbol t, vunits v);
- void justify(output_line *, vunits *bottomp) const;
-};
-
-justification_spec::justification_spec(vunits h)
-: height(h), n(0), maxn(10)
-{
- type = new symbol[maxn];
- amount = new vunits[maxn];
-}
-
-justification_spec::~justification_spec()
-{
- a_delete type;
- a_delete amount;
-}
-
-void justification_spec::append(symbol t, vunits v)
-{
- if (v <= V0) {
- if (v < V0)
- warning(WARN_RANGE,
- "maximum space for vertical justification must not be negative");
- else
- warning(WARN_RANGE,
- "maximum space for vertical justification must not be zero");
- return;
- }
- if (n >= maxn) {
- maxn *= 2;
- symbol *old_type = type;
- type = new symbol[maxn];
- int i;
- for (i = 0; i < n; i++)
- type[i] = old_type[i];
- a_delete old_type;
- vunits *old_amount = amount;
- amount = new vunits[maxn];
- for (i = 0; i < n; i++)
- amount[i] = old_amount[i];
- a_delete old_amount;
- }
- assert(n < maxn);
- type[n] = t;
- amount[n] = v;
- n++;
-}
-
-void justification_spec::justify(output_line *col, vunits *bottomp) const
-{
- if (*bottomp >= height)
- return;
- vunits total;
- output_line *p;
- for (p = col; p; p = p->next) {
- vjustify_output_line *sp = p->as_vjustify_output_line();
- if (sp) {
- symbol t = sp->type();
- for (int i = 0; i < n; i++) {
- if (t == type[i])
- total += amount[i];
- }
- }
- }
- vunits gap = height - *bottomp;
- for (p = col; p; p = p->next) {
- vjustify_output_line *sp = p->as_vjustify_output_line();
- if (sp) {
- symbol t = sp->type();
- for (int i = 0; i < n; i++) {
- if (t == type[i]) {
- if (total <= gap) {
- sp->vary(amount[i]);
- gap -= amount[i];
- }
- else {
- // gap < total
- vunits v = scale(amount[i], gap, total);
- sp->vary(v);
- gap -= v;
- }
- total -= amount[i];
- }
- }
- }
- }
- assert(total == V0);
- *bottomp = height - gap;
-}
-
-void column::justify(const justification_spec &js)
-{
- check_bottom();
- js.justify(col, &bottom);
- check_bottom();
-}
-
-void column_justify()
-{
- vunits height;
- if (!the_column->is_active())
- error("can't justify column - column not active");
- else if (get_vunits(&height, 'v')) {
- justification_spec js(height);
- symbol nm = get_long_name(1);
- if (!nm.is_null()) {
- vunits v;
- if (get_vunits(&v, 'v')) {
- js.append(nm, v);
- int err = 0;
- while (has_arg()) {
- nm = get_long_name(1);
- if (nm.is_null()) {
- err = 1;
- break;
- }
- if (!get_vunits(&v, 'v')) {
- err = 1;
- break;
- }
- js.append(nm, v);
- }
- if (!err)
- the_column->justify(js);
- }
- }
- }
- skip_line();
-}
-
-void column_start()
-{
- if (the_column->is_active())
- error("can't start column - column already active");
- else
- the_column->start();
- skip_line();
-}
-
-void column_output()
-{
- if (!the_column->is_active())
- error("can't output column - column not active");
- else
- the_column->output();
- skip_line();
-}
-
-void column_trim()
-{
- if (!the_column->is_active())
- error("can't trim column - column not active");
- else
- the_column->trim();
- skip_line();
-}
-
-void column_reset()
-{
- if (!the_column->is_active())
- error("can't reset column - column not active");
- else
- the_column->reset();
- skip_line();
-}
-
-class column_bottom_reg : public reg {
-public:
- const char *get_string();
-};
-
-const char *column_bottom_reg::get_string()
-{
- return i_to_a(the_column->get_bottom().to_units());
-}
-
-class column_extra_space_reg : public reg {
-public:
- const char *get_string();
-};
-
-const char *column_extra_space_reg::get_string()
-{
- return i_to_a(the_column->get_last_extra_space().to_units());
-}
-
-class column_active_reg : public reg {
-public:
- const char *get_string();
-};
-
-const char *column_active_reg::get_string()
-{
- return the_column->is_active() ? "1" : "0";
-}
-
-static int no_vjustify_mode = 0;
-
-class vjustify_node : public node {
- symbol typ;
-public:
- vjustify_node(symbol);
- int reread(int *);
- const char *type();
- int same(node *);
- node *copy();
-};
-
-vjustify_node::vjustify_node(symbol t)
-: typ(t)
-{
-}
-
-node *vjustify_node::copy()
-{
- return new vjustify_node(typ);
-}
-
-const char *vjustify_node::type()
-{
- return "vjustify_node";
-}
-
-int vjustify_node::same(node *nd)
-{
- return typ == ((vjustify_node *)nd)->typ;
-}
-
-int vjustify_node::reread(int *bolp)
-{
- curdiv->vjustify(typ);
- *bolp = 1;
- return 1;
-}
-
-void macro_diversion::vjustify(symbol type)
-{
- if (!no_vjustify_mode)
- mac->append(new vjustify_node(type));
-}
-
-void top_level_diversion::vjustify(symbol type)
-{
- if (no_space_mode || no_vjustify_mode)
- return;
- assert(first_page_begun); // I'm not sure about this.
- the_output->vjustify(vertical_position, type);
-}
-
-void no_vjustify()
-{
- skip_line();
- no_vjustify_mode = 1;
-}
-
-void restore_vjustify()
-{
- skip_line();
- no_vjustify_mode = 0;
-}
-
-void init_column_requests()
-{
- the_column = new column;
- init_request("cols", column_start);
- init_request("colo", column_output);
- init_request("colj", column_justify);
- init_request("colr", column_reset);
- init_request("colt", column_trim);
- init_request("nvj", no_vjustify);
- init_request("rvj", restore_vjustify);
- number_reg_dictionary.define(".colb", new column_bottom_reg);
- number_reg_dictionary.define(".colx", new column_extra_space_reg);
- number_reg_dictionary.define(".cola", new column_active_reg);
- number_reg_dictionary.define(".nvj",
- new constant_int_reg(&no_vjustify_mode));
-}
-
-#endif /* COLUMN */
diff --git a/contrib/groff/src/roff/troff/dictionary.cc b/contrib/groff/src/roff/troff/dictionary.cc
deleted file mode 100644
index a70ebb0..0000000
--- a/contrib/groff/src/roff/troff/dictionary.cc
+++ /dev/null
@@ -1,212 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-
-#include "troff.h"
-#include "symbol.h"
-#include "dictionary.h"
-
-// is `p' a good size for a hash table
-
-static int is_good_size(unsigned int p)
-{
- const unsigned int SMALL = 10;
- unsigned int i;
- for (i = 2; i <= p/2; i++)
- if (p % i == 0)
- return 0;
- for (i = 0x100; i != 0; i <<= 8)
- if (i % p <= SMALL || i % p > p - SMALL)
- return 0;
- return 1;
-}
-
-dictionary::dictionary(int n) : size(n), used(0), threshold(0.5), factor(1.5)
-{
- table = new association[n];
-}
-
-// see Knuth, Sorting and Searching, p518, Algorithm L
-// we can't use double-hashing because we want a remove function
-
-void *dictionary::lookup(symbol s, void *v)
-{
- int i;
- for (i = int(s.hash() % size);
- table[i].v != 0;
- i == 0 ? i = size - 1: --i)
- if (s == table[i].s) {
- if (v != 0) {
- void *temp = table[i].v;
- table[i].v = v;
- return temp;
- }
- else
- return table[i].v;
- }
- if (v == 0)
- return 0;
- ++used;
- table[i].v = v;
- table[i].s = s;
- if ((double)used/(double)size >= threshold || used + 1 >= size) {
- int old_size = size;
- size = int(size*factor);
- while (!is_good_size(size))
- ++size;
- association *old_table = table;
- table = new association[size];
- used = 0;
- for (i = 0; i < old_size; i++)
- if (old_table[i].v != 0)
- (void)lookup(old_table[i].s, old_table[i].v);
- a_delete old_table;
- }
- return 0;
-}
-
-void *dictionary::lookup(const char *p)
-{
- symbol s(p, MUST_ALREADY_EXIST);
- if (s.is_null())
- return 0;
- else
- return lookup(s);
-}
-
-// see Knuth, Sorting and Searching, p527, Algorithm R
-
-void *dictionary::remove(symbol s)
-{
- // this relies on the fact that we are using linear probing
- int i;
- for (i = int(s.hash() % size);
- table[i].v != 0 && s != table[i].s;
- i == 0 ? i = size - 1: --i)
- ;
- void *p = table[i].v;
- while (table[i].v != 0) {
- table[i].v = 0;
- int j = i;
- int r;
- do {
- --i;
- if (i < 0)
- i = size - 1;
- if (table[i].v == 0)
- break;
- r = int(table[i].s.hash() % size);
- } while ((i <= r && r < j) || (r < j && j < i) || (j < i && i <= r));
- table[j] = table[i];
- }
- if (p != 0)
- --used;
- return p;
-}
-
-dictionary_iterator::dictionary_iterator(dictionary &d) : dict(&d), i(0)
-{
-}
-
-int dictionary_iterator::get(symbol *sp, void **vp)
-{
- for (; i < dict->size; i++)
- if (dict->table[i].v) {
- *sp = dict->table[i].s;
- *vp = dict->table[i].v;
- i++;
- return 1;
- }
- return 0;
-}
-
-object_dictionary_iterator::object_dictionary_iterator(object_dictionary &od)
-: di(od.d)
-{
-}
-
-object::object() : rcount(0)
-{
-}
-
-object::~object()
-{
-}
-
-void object::add_reference()
-{
- rcount += 1;
-}
-
-void object::remove_reference()
-{
- if (--rcount == 0)
- delete this;
-}
-
-object_dictionary::object_dictionary(int n) : d(n)
-{
-}
-
-object *object_dictionary::lookup(symbol nm)
-{
- return (object *)d.lookup(nm);
-}
-
-void object_dictionary::define(symbol nm, object *obj)
-{
- obj->add_reference();
- obj = (object *)d.lookup(nm, obj);
- if (obj)
- obj->remove_reference();
-}
-
-void object_dictionary::rename(symbol oldnm, symbol newnm)
-{
- object *obj = (object *)d.remove(oldnm);
- if (obj) {
- obj = (object *)d.lookup(newnm, obj);
- if (obj)
- obj->remove_reference();
- }
-}
-
-void object_dictionary::remove(symbol nm)
-{
- object *obj = (object *)d.remove(nm);
- if (obj)
- obj->remove_reference();
-}
-
-// Return non-zero if oldnm was defined.
-
-int object_dictionary::alias(symbol newnm, symbol oldnm)
-{
- object *obj = (object *)d.lookup(oldnm);
- if (obj) {
- obj->add_reference();
- obj = (object *)d.lookup(newnm, obj);
- if (obj)
- obj->remove_reference();
- return 1;
- }
- return 0;
-}
-
diff --git a/contrib/groff/src/roff/troff/div.cc b/contrib/groff/src/roff/troff/div.cc
deleted file mode 100644
index 14c7399..0000000
--- a/contrib/groff/src/roff/troff/div.cc
+++ /dev/null
@@ -1,1185 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-
-// diversions
-
-#include "troff.h"
-#include "symbol.h"
-#include "dictionary.h"
-#include "hvunits.h"
-#include "env.h"
-#include "request.h"
-#include "node.h"
-#include "token.h"
-#include "div.h"
-#include "reg.h"
-
-int exit_started = 0; // the exit process has started
-int done_end_macro = 0; // the end macro (if any) has finished
-int seen_last_page_ejector = 0; // seen the LAST_PAGE_EJECTOR cookie
-int last_page_number = 0; // if > 0, the number of the last page
- // specified with -o
-static int began_page_in_end_macro = 0; // a new page was begun during the end macro
-
-static int last_post_line_extra_space = 0; // needed for \n(.a
-static int nl_reg_contents = -1;
-static int dl_reg_contents = 0;
-static int dn_reg_contents = 0;
-static int vertical_position_traps_flag = 1;
-static vunits truncated_space;
-static vunits needed_space;
-
-diversion::diversion(symbol s)
-: prev(0), nm(s), vertical_position(V0), high_water_mark(V0),
- no_space_mode(0), marked_place(V0)
-{
-}
-
-struct vertical_size {
- vunits pre_extra, post_extra, pre, post;
- vertical_size(vunits vs, vunits post_vs);
-};
-
-vertical_size::vertical_size(vunits vs, vunits post_vs)
-: pre_extra(V0), post_extra(V0), pre(vs), post(post_vs)
-{
-}
-
-void node::set_vertical_size(vertical_size *)
-{
-}
-
-void extra_size_node::set_vertical_size(vertical_size *v)
-{
- if (n < V0) {
- if (-n > v->pre_extra)
- v->pre_extra = -n;
- }
- else if (n > v->post_extra)
- v->post_extra = n;
-}
-
-void vertical_size_node::set_vertical_size(vertical_size *v)
-{
- if (n < V0)
- v->pre = -n;
- else
- v->post = n;
-}
-
-top_level_diversion *topdiv;
-
-diversion *curdiv;
-
-void do_divert(int append, int boxing)
-{
- tok.skip();
- symbol nm = get_name();
- if (nm.is_null()) {
- if (curdiv->prev) {
- if (boxing) {
- curenv->line = curdiv->saved_line;
- curenv->width_total = curdiv->saved_width_total;
- curenv->space_total = curdiv->saved_space_total;
- curenv->saved_indent = curdiv->saved_saved_indent;
- curenv->target_text_length = curdiv->saved_target_text_length;
- curenv->prev_line_interrupted = curdiv->saved_prev_line_interrupted;
- }
- diversion *temp = curdiv;
- curdiv = curdiv->prev;
- delete temp;
- }
- else
- warning(WARN_DI, "diversion stack underflow");
- }
- else {
- macro_diversion *md = new macro_diversion(nm, append);
- md->prev = curdiv;
- curdiv = md;
- if (boxing) {
- curdiv->saved_line = curenv->line;
- curdiv->saved_width_total = curenv->width_total;
- curdiv->saved_space_total = curenv->space_total;
- curdiv->saved_saved_indent = curenv->saved_indent;
- curdiv->saved_target_text_length = curenv->target_text_length;
- curdiv->saved_prev_line_interrupted = curenv->prev_line_interrupted;
- curenv->line = 0;
- curenv->start_line();
- }
- }
- skip_line();
-}
-
-void divert()
-{
- do_divert(0, 0);
-}
-
-void divert_append()
-{
- do_divert(1, 0);
-}
-
-void box()
-{
- do_divert(0, 1);
-}
-
-void box_append()
-{
- do_divert(1, 1);
-}
-
-void diversion::need(vunits n)
-{
- vunits d = distance_to_next_trap();
- if (d < n) {
- space(d, 1);
- truncated_space = -d;
- needed_space = n;
- }
-}
-
-macro_diversion::macro_diversion(symbol s, int append)
-: diversion(s), max_width(H0)
-{
-#if 0
- if (append) {
- /* We don't allow recursive appends eg:
-
- .da a
- .a
- .di
-
- This causes an infinite loop in troff anyway.
- This is because the user could do
-
- .as a foo
-
- in the diversion, and this would mess things up royally,
- since there would be two things appending to the same
- macro_header.
- To make it work, we would have to copy the _contents_
- of the macro into which we were diverting; this doesn't
- strike me as worthwhile.
- However,
-
- .di a
- .a
- .a
- .di
-
- will work and will make `a' contain two copies of what it contained
- before; in troff, `a' would contain nothing. */
- request_or_macro *rm
- = (request_or_macro *)request_dictionary.remove(s);
- if (!rm || (mac = rm->to_macro()) == 0)
- mac = new macro;
- }
- else
- mac = new macro;
-#endif
- // We can now catch the situation described above by comparing
- // the length of the charlist in the macro_header with the length
- // stored in the macro. When we detect this, we copy the contents.
- mac = new macro;
- if (append) {
- request_or_macro *rm
- = (request_or_macro *)request_dictionary.lookup(s);
- if (rm) {
- macro *m = rm->to_macro();
- if (m)
- *mac = *m;
- }
- }
-}
-
-macro_diversion::~macro_diversion()
-{
- request_or_macro *rm = (request_or_macro *)request_dictionary.lookup(nm);
- macro *m = rm ? rm->to_macro() : 0;
- if (m) {
- *m = *mac;
- delete mac;
- }
- else
- request_dictionary.define(nm, mac);
- mac = 0;
- dl_reg_contents = max_width.to_units();
- dn_reg_contents = vertical_position.to_units();
-}
-
-vunits macro_diversion::distance_to_next_trap()
-{
- if (!diversion_trap.is_null() && diversion_trap_pos > vertical_position)
- return diversion_trap_pos - vertical_position;
- else
- // Substract vresolution so that vunits::vunits does not overflow.
- return vunits(INT_MAX - vresolution);
-}
-
-void macro_diversion::transparent_output(unsigned char c)
-{
- mac->append(c);
-}
-
-void macro_diversion::transparent_output(node *n)
-{
- mac->append(n);
-}
-
-void macro_diversion::output(node *nd, int retain_size,
- vunits vs, vunits post_vs, hunits width)
-{
- no_space_mode = 0;
- vertical_size v(vs, post_vs);
- while (nd != 0) {
- nd->set_vertical_size(&v);
- node *temp = nd;
- nd = nd->next;
- if (temp->interpret(mac)) {
- delete temp;
- }
- else {
-#if 1
- temp->freeze_space();
-#endif
- mac->append(temp);
- }
- }
- last_post_line_extra_space = v.post_extra.to_units();
- if (!retain_size) {
- v.pre = vs;
- v.post = post_vs;
- }
- if (width > max_width)
- max_width = width;
- vunits x = v.pre + v.pre_extra + v.post + v.post_extra;
- if (vertical_position_traps_flag
- && !diversion_trap.is_null() && diversion_trap_pos > vertical_position
- && diversion_trap_pos <= vertical_position + x) {
- vunits trunc = vertical_position + x - diversion_trap_pos;
- if (trunc > v.post)
- trunc = v.post;
- v.post -= trunc;
- x -= trunc;
- truncated_space = trunc;
- spring_trap(diversion_trap);
- }
- mac->append(new vertical_size_node(-v.pre));
- mac->append(new vertical_size_node(v.post));
- mac->append('\n');
- vertical_position += x;
- if (vertical_position - v.post > high_water_mark)
- high_water_mark = vertical_position - v.post;
-}
-
-void macro_diversion::space(vunits n, int)
-{
- if (vertical_position_traps_flag
- && !diversion_trap.is_null() && diversion_trap_pos > vertical_position
- && diversion_trap_pos <= vertical_position + n) {
- truncated_space = vertical_position + n - diversion_trap_pos;
- n = diversion_trap_pos - vertical_position;
- spring_trap(diversion_trap);
- }
- else if (n + vertical_position < V0)
- n = -vertical_position;
- mac->append(new diverted_space_node(n));
- vertical_position += n;
-}
-
-void macro_diversion::copy_file(const char *filename)
-{
- mac->append(new diverted_copy_file_node(filename));
-}
-
-top_level_diversion::top_level_diversion()
-: page_number(0), page_count(0), last_page_count(-1),
- page_length(units_per_inch*11),
- prev_page_offset(units_per_inch), page_offset(units_per_inch),
- page_trap_list(0), have_next_page_number(0),
- ejecting_page(0), before_first_page(1)
-{
-}
-
-// find the next trap after pos
-
-trap *top_level_diversion::find_next_trap(vunits *next_trap_pos)
-{
- trap *next_trap = 0;
- for (trap *pt = page_trap_list; pt != 0; pt = pt->next)
- if (!pt->nm.is_null()) {
- if (pt->position >= V0) {
- if (pt->position > vertical_position
- && pt->position < page_length
- && (next_trap == 0 || pt->position < *next_trap_pos)) {
- next_trap = pt;
- *next_trap_pos = pt->position;
- }
- }
- else {
- vunits pos = pt->position;
- pos += page_length;
- if (pos > 0 && pos > vertical_position && (next_trap == 0 || pos < *next_trap_pos)) {
- next_trap = pt;
- *next_trap_pos = pos;
- }
- }
- }
- return next_trap;
-}
-
-vunits top_level_diversion::distance_to_next_trap()
-{
- vunits d;
- if (!find_next_trap(&d))
- return page_length - vertical_position;
- else
- return d - vertical_position;
-}
-
-void top_level_diversion::output(node *nd, int retain_size,
- vunits vs, vunits post_vs, hunits width)
-{
- no_space_mode = 0;
- vunits next_trap_pos;
- trap *next_trap = find_next_trap(&next_trap_pos);
- if (before_first_page && begin_page())
- fatal("sorry, I didn't manage to begin the first page in time: use an explicit .br request");
- vertical_size v(vs, post_vs);
- for (node *tem = nd; tem != 0; tem = tem->next)
- tem->set_vertical_size(&v);
- last_post_line_extra_space = v.post_extra.to_units();
- if (!retain_size) {
- v.pre = vs;
- v.post = post_vs;
- }
- vertical_position += v.pre;
- vertical_position += v.pre_extra;
- the_output->print_line(page_offset, vertical_position, nd,
- v.pre + v.pre_extra, v.post_extra, width);
- vertical_position += v.post_extra;
- if (vertical_position > high_water_mark)
- high_water_mark = vertical_position;
- if (vertical_position_traps_flag && vertical_position >= page_length)
- begin_page();
- else if (vertical_position_traps_flag
- && next_trap != 0 && vertical_position >= next_trap_pos) {
- nl_reg_contents = vertical_position.to_units();
- truncated_space = v.post;
- spring_trap(next_trap->nm);
- }
- else if (v.post > V0) {
- vertical_position += v.post;
- if (vertical_position_traps_flag
- && next_trap != 0 && vertical_position >= next_trap_pos) {
- truncated_space = vertical_position - next_trap_pos;
- vertical_position = next_trap_pos;
- nl_reg_contents = vertical_position.to_units();
- spring_trap(next_trap->nm);
- }
- else if (vertical_position_traps_flag && vertical_position >= page_length)
- begin_page();
- else
- nl_reg_contents = vertical_position.to_units();
- }
- else
- nl_reg_contents = vertical_position.to_units();
-}
-
-void top_level_diversion::transparent_output(unsigned char c)
-{
- if (before_first_page && begin_page())
- // This can only happen with the .output request.
- fatal("sorry, I didn't manage to begin the first page in time: use an explicit .br request");
- const char *s = asciify(c);
- while (*s)
- the_output->transparent_char(*s++);
-}
-
-void top_level_diversion::transparent_output(node * /*n*/)
-{
- error("can't transparently output node at top level");
-}
-
-void top_level_diversion::copy_file(const char *filename)
-{
- if (before_first_page && begin_page())
- fatal("sorry, I didn't manage to begin the first page in time: use an explicit .br request");
- the_output->copy_file(page_offset, vertical_position, filename);
-}
-
-void top_level_diversion::space(vunits n, int forced)
-{
- if (no_space_mode) {
- if (!forced)
- return;
- else
- no_space_mode = 0;
- }
- if (before_first_page) {
- if (begin_page()) {
- // This happens if there's a top of page trap, and the first-page
- // transition is caused by `'sp'.
- truncated_space = n > V0 ? n : V0;
- return;
- }
- }
- vunits next_trap_pos;
- trap *next_trap = find_next_trap(&next_trap_pos);
- vunits y = vertical_position + n;
- if (vertical_position_traps_flag && next_trap != 0 && y >= next_trap_pos) {
- vertical_position = next_trap_pos;
- nl_reg_contents = vertical_position.to_units();
- truncated_space = y - vertical_position;
- spring_trap(next_trap->nm);
- }
- else if (y < V0) {
- vertical_position = V0;
- nl_reg_contents = vertical_position.to_units();
- }
- else if (vertical_position_traps_flag && y >= page_length && n >= V0)
- begin_page();
- else {
- vertical_position = y;
- nl_reg_contents = vertical_position.to_units();
- }
-}
-
-trap::trap(symbol s, vunits n, trap *p)
-: next(p), position(n), nm(s)
-{
-}
-
-void top_level_diversion::add_trap(symbol nm, vunits pos)
-{
- trap *first_free_slot = 0;
- trap **p;
- for (p = &page_trap_list; *p; p = &(*p)->next) {
- if ((*p)->nm.is_null()) {
- if (first_free_slot == 0)
- first_free_slot = *p;
- }
- else if ((*p)->position == pos) {
- (*p)->nm = nm;
- return;
- }
- }
- if (first_free_slot) {
- first_free_slot->nm = nm;
- first_free_slot->position = pos;
- }
- else
- *p = new trap(nm, pos, 0);
-}
-
-void top_level_diversion::remove_trap(symbol nm)
-{
- for (trap *p = page_trap_list; p; p = p->next)
- if (p->nm == nm) {
- p->nm = NULL_SYMBOL;
- return;
- }
-}
-
-void top_level_diversion::remove_trap_at(vunits pos)
-{
- for (trap *p = page_trap_list; p; p = p->next)
- if (p->position == pos) {
- p->nm = NULL_SYMBOL;
- return;
- }
-}
-
-void top_level_diversion::change_trap(symbol nm, vunits pos)
-{
- for (trap *p = page_trap_list; p; p = p->next)
- if (p->nm == nm) {
- p->position = pos;
- return;
- }
-}
-
-void top_level_diversion::print_traps()
-{
- for (trap *p = page_trap_list; p; p = p->next)
- if (p->nm.is_null())
- fprintf(stderr, " empty\n");
- else
- fprintf(stderr, "%s\t%d\n", p->nm.contents(), p->position.to_units());
- fflush(stderr);
-}
-
-void end_diversions()
-{
- while (curdiv != topdiv) {
- error("automatically ending diversion `%1' on exit",
- curdiv->nm.contents());
- diversion *tem = curdiv;
- curdiv = curdiv->prev;
- delete tem;
- }
-}
-
-void cleanup_and_exit(int exit_code)
-{
- if (the_output) {
- the_output->trailer(topdiv->get_page_length());
- delete the_output;
- }
- exit(exit_code);
-}
-
-// returns non-zero if it sprung a top of page trap
-
-int top_level_diversion::begin_page()
-{
- if (exit_started) {
- if (page_count == last_page_count
- ? curenv->is_empty()
- : (done_end_macro && (seen_last_page_ejector || began_page_in_end_macro)))
- cleanup_and_exit(0);
- if (!done_end_macro)
- began_page_in_end_macro = 1;
- }
- if (last_page_number > 0 && page_number == last_page_number)
- cleanup_and_exit(0);
- if (!the_output)
- init_output();
- ++page_count;
- if (have_next_page_number) {
- page_number = next_page_number;
- have_next_page_number = 0;
- }
- else if (before_first_page == 1)
- page_number = 1;
- else
- page_number++;
- // spring the top of page trap if there is one
- vunits next_trap_pos;
- vertical_position = -vresolution;
- trap *next_trap = find_next_trap(&next_trap_pos);
- vertical_position = V0;
- high_water_mark = V0;
- ejecting_page = 0;
- // If before_first_page was 2, then the top of page transition was undone
- // using eg .nr nl 0-1. See nl_reg::set_value.
- if (before_first_page != 2)
- the_output->begin_page(page_number, page_length);
- before_first_page = 0;
- nl_reg_contents = vertical_position.to_units();
- if (vertical_position_traps_flag && next_trap != 0 && next_trap_pos == V0) {
- truncated_space = V0;
- spring_trap(next_trap->nm);
- return 1;
- }
- else
- return 0;
-}
-
-void continue_page_eject()
-{
- if (topdiv->get_ejecting()) {
- if (curdiv != topdiv)
- error("can't continue page ejection because of current diversion");
- else if (!vertical_position_traps_flag)
- error("can't continue page ejection because vertical position traps disabled");
- else {
- push_page_ejector();
- topdiv->space(topdiv->get_page_length(), 1);
- }
- }
-}
-
-void top_level_diversion::set_next_page_number(int n)
-{
- next_page_number= n;
- have_next_page_number = 1;
-}
-
-int top_level_diversion::get_next_page_number()
-{
- return have_next_page_number ? next_page_number : page_number + 1;
-}
-
-void top_level_diversion::set_page_length(vunits n)
-{
- page_length = n;
-}
-
-diversion::~diversion()
-{
-}
-
-void page_offset()
-{
- hunits n;
- // The troff manual says that the default scaling indicator is v,
- // but it is in fact m: v wouldn't make sense for a horizontally
- // oriented request.
- if (!has_arg() || !get_hunits(&n, 'm', topdiv->page_offset))
- n = topdiv->prev_page_offset;
- topdiv->prev_page_offset = topdiv->page_offset;
- topdiv->page_offset = n;
- curenv->add_html_tag(0, ".po", n.to_units());
- skip_line();
-}
-
-void page_length()
-{
- vunits n;
- if (has_arg() && get_vunits(&n, 'v', topdiv->get_page_length()))
- topdiv->set_page_length(n);
- else
- topdiv->set_page_length(11*units_per_inch);
- skip_line();
-}
-
-void when_request()
-{
- vunits n;
- if (get_vunits(&n, 'v')) {
- symbol s = get_name();
- if (s.is_null())
- topdiv->remove_trap_at(n);
- else
- topdiv->add_trap(s, n);
- }
- skip_line();
-}
-
-void begin_page()
-{
- int got_arg = 0;
- int n;
- if (has_arg() && get_integer(&n, topdiv->get_page_number()))
- got_arg = 1;
- while (!tok.newline() && !tok.eof())
- tok.next();
- if (curdiv == topdiv) {
- if (topdiv->before_first_page) {
- if (!break_flag) {
- if (got_arg)
- topdiv->set_next_page_number(n);
- if (got_arg || !topdiv->no_space_mode)
- topdiv->begin_page();
- }
- else if (topdiv->no_space_mode && !got_arg)
- topdiv->begin_page();
- else {
- /* Given this
-
- .wh 0 x
- .de x
- .tm \\n%
- ..
- .bp 3
-
- troff prints
-
- 1
- 3
-
- This code makes groff do the same. */
-
- push_page_ejector();
- topdiv->begin_page();
- if (got_arg)
- topdiv->set_next_page_number(n);
- topdiv->set_ejecting();
- }
- }
- else {
- push_page_ejector();
- if (break_flag)
- curenv->do_break();
- if (got_arg)
- topdiv->set_next_page_number(n);
- if (!(topdiv->no_space_mode && !got_arg))
- topdiv->set_ejecting();
- }
- }
- tok.next();
-}
-
-void no_space()
-{
- curdiv->no_space_mode = 1;
- skip_line();
-}
-
-void restore_spacing()
-{
- curdiv->no_space_mode = 0;
- skip_line();
-}
-
-/* It is necessary to generate a break before before reading the argument,
-because otherwise arguments using | will be wrong. But if we just
-generate a break as usual, then the line forced out may spring a trap
-and thus push a macro onto the input stack before we have had a chance
-to read the argument to the sp request. We resolve this dilemma by
-setting, before generating the break, a flag which will postpone the
-actual pushing of the macro associated with the trap sprung by the
-outputting of the line forced out by the break till after we have read
-the argument to the request. If the break did cause a trap to be
-sprung, then we don't actually do the space. */
-
-void space_request()
-{
- postpone_traps();
- if (break_flag)
- curenv->do_break();
- vunits n;
- if (!has_arg() || !get_vunits(&n, 'v'))
- n = curenv->get_vertical_spacing();
- while (!tok.newline() && !tok.eof())
- tok.next();
- if (!unpostpone_traps() && !curdiv->no_space_mode)
- curdiv->space(n);
- else
- // The line might have had line spacing that was truncated.
- truncated_space += n;
- curenv->add_html_tag(1, ".sp", n.to_units());
- tok.next();
-}
-
-void blank_line()
-{
- curenv->do_break();
- if (!trap_sprung_flag && !curdiv->no_space_mode) {
- curdiv->space(curenv->get_vertical_spacing());
- curenv->add_html_tag(1, ".sp", 1);
- } else
- truncated_space += curenv->get_vertical_spacing();
-}
-
-/* need_space might spring a trap and so we must be careful that the
-BEGIN_TRAP token is not skipped over. */
-
-void need_space()
-{
- vunits n;
- if (!has_arg() || !get_vunits(&n, 'v'))
- n = curenv->get_vertical_spacing();
- while (!tok.newline() && !tok.eof())
- tok.next();
- curdiv->need(n);
- tok.next();
-}
-
-void page_number()
-{
- int n;
-
- // the ps4html register is set if we are using -Tps
- // to generate images for html
- reg *r = (reg *)number_reg_dictionary.lookup("ps4html");
- if (r == NULL)
- if (has_arg() && get_integer(&n, topdiv->get_page_number()))
- topdiv->set_next_page_number(n);
- skip_line();
-}
-
-vunits saved_space;
-
-void save_vertical_space()
-{
- vunits x;
- if (!has_arg() || !get_vunits(&x, 'v'))
- x = curenv->get_vertical_spacing();
- if (curdiv->distance_to_next_trap() > x)
- curdiv->space(x, 1);
- else
- saved_space = x;
- skip_line();
-}
-
-void output_saved_vertical_space()
-{
- while (!tok.newline() && !tok.eof())
- tok.next();
- if (saved_space > V0)
- curdiv->space(saved_space, 1);
- saved_space = V0;
- tok.next();
-}
-
-void flush_output()
-{
- while (!tok.newline() && !tok.eof())
- tok.next();
- if (break_flag)
- curenv->do_break();
- if (the_output)
- the_output->flush();
- curenv->add_html_tag(1, ".fl");
- tok.next();
-}
-
-void macro_diversion::set_diversion_trap(symbol s, vunits n)
-{
- diversion_trap = s;
- diversion_trap_pos = n;
-}
-
-void macro_diversion::clear_diversion_trap()
-{
- diversion_trap = NULL_SYMBOL;
-}
-
-void top_level_diversion::set_diversion_trap(symbol, vunits)
-{
- error("can't set diversion trap when no current diversion");
-}
-
-void top_level_diversion::clear_diversion_trap()
-{
- error("can't set diversion trap when no current diversion");
-}
-
-void diversion_trap()
-{
- vunits n;
- if (has_arg() && get_vunits(&n, 'v')) {
- symbol s = get_name();
- if (!s.is_null())
- curdiv->set_diversion_trap(s, n);
- else
- curdiv->clear_diversion_trap();
- }
- else
- curdiv->clear_diversion_trap();
- skip_line();
-}
-
-void change_trap()
-{
- symbol s = get_name(1);
- if (!s.is_null()) {
- vunits x;
- if (has_arg() && get_vunits(&x, 'v'))
- topdiv->change_trap(s, x);
- else
- topdiv->remove_trap(s);
- }
- skip_line();
-}
-
-void print_traps()
-{
- topdiv->print_traps();
- skip_line();
-}
-
-void mark()
-{
- symbol s = get_name();
- if (s.is_null())
- curdiv->marked_place = curdiv->get_vertical_position();
- else if (curdiv == topdiv)
- set_number_reg(s, nl_reg_contents);
- else
- set_number_reg(s, curdiv->get_vertical_position().to_units());
- skip_line();
-}
-
-// This is truly bizarre. It is documented in the SQ manual.
-
-void return_request()
-{
- vunits dist = curdiv->marked_place - curdiv->get_vertical_position();
- if (has_arg()) {
- if (tok.ch() == '-') {
- tok.next();
- vunits x;
- if (get_vunits(&x, 'v'))
- dist = -x;
- }
- else {
- vunits x;
- if (get_vunits(&x, 'v'))
- dist = x >= V0 ? x - curdiv->get_vertical_position() : V0;
- }
- }
- if (dist < V0)
- curdiv->space(dist);
- skip_line();
-}
-
-void vertical_position_traps()
-{
- int n;
- if (has_arg() && get_integer(&n))
- vertical_position_traps_flag = (n != 0);
- else
- vertical_position_traps_flag = 1;
- skip_line();
-}
-
-class page_offset_reg : public reg {
-public:
- int get_value(units *);
- const char *get_string();
-};
-
-int page_offset_reg::get_value(units *res)
-{
- *res = topdiv->get_page_offset().to_units();
- return 1;
-}
-
-const char *page_offset_reg::get_string()
-{
- return i_to_a(topdiv->get_page_offset().to_units());
-}
-
-class page_length_reg : public reg {
-public:
- int get_value(units *);
- const char *get_string();
-};
-
-int page_length_reg::get_value(units *res)
-{
- *res = topdiv->get_page_length().to_units();
- return 1;
-}
-
-const char *page_length_reg::get_string()
-{
- return i_to_a(topdiv->get_page_length().to_units());
-}
-
-class vertical_position_reg : public reg {
-public:
- int get_value(units *);
- const char *get_string();
-};
-
-int vertical_position_reg::get_value(units *res)
-{
- if (curdiv == topdiv && topdiv->before_first_page)
- *res = -1;
- else
- *res = curdiv->get_vertical_position().to_units();
- return 1;
-}
-
-const char *vertical_position_reg::get_string()
-{
- if (curdiv == topdiv && topdiv->before_first_page)
- return "-1";
- else
- return i_to_a(curdiv->get_vertical_position().to_units());
-}
-
-class high_water_mark_reg : public reg {
-public:
- int get_value(units *);
- const char *get_string();
-};
-
-int high_water_mark_reg::get_value(units *res)
-{
- *res = curdiv->get_high_water_mark().to_units();
- return 1;
-}
-
-const char *high_water_mark_reg::get_string()
-{
- return i_to_a(curdiv->get_high_water_mark().to_units());
-}
-
-class distance_to_next_trap_reg : public reg {
-public:
- int get_value(units *);
- const char *get_string();
-};
-
-int distance_to_next_trap_reg::get_value(units *res)
-{
- *res = curdiv->distance_to_next_trap().to_units();
- return 1;
-}
-
-const char *distance_to_next_trap_reg::get_string()
-{
- return i_to_a(curdiv->distance_to_next_trap().to_units());
-}
-
-class diversion_name_reg : public reg {
-public:
- const char *get_string();
-};
-
-const char *diversion_name_reg::get_string()
-{
- return curdiv->get_diversion_name();
-}
-
-class page_number_reg : public general_reg {
-public:
- page_number_reg();
- int get_value(units *);
- void set_value(units);
-};
-
-page_number_reg::page_number_reg()
-{
-}
-
-void page_number_reg::set_value(units n)
-{
- topdiv->set_page_number(n);
-}
-
-int page_number_reg::get_value(units *res)
-{
- *res = topdiv->get_page_number();
- return 1;
-}
-
-class next_page_number_reg : public reg {
-public:
- const char *get_string();
-};
-
-const char *next_page_number_reg::get_string()
-{
- return i_to_a(topdiv->get_next_page_number());
-}
-
-class page_ejecting_reg : public reg {
-public:
- const char *get_string();
-};
-
-const char *page_ejecting_reg::get_string()
-{
- return i_to_a(topdiv->get_ejecting());
-}
-
-class constant_vunits_reg : public reg {
- vunits *p;
-public:
- constant_vunits_reg(vunits *);
- const char *get_string();
-};
-
-constant_vunits_reg::constant_vunits_reg(vunits *q) : p(q)
-{
-}
-
-const char *constant_vunits_reg::get_string()
-{
- return i_to_a(p->to_units());
-}
-
-class nl_reg : public variable_reg {
-public:
- nl_reg();
- void set_value(units);
-};
-
-nl_reg::nl_reg() : variable_reg(&nl_reg_contents)
-{
-}
-
-void nl_reg::set_value(units n)
-{
- variable_reg::set_value(n);
- // Setting nl to a negative value when the vertical position in
- // the top-level diversion is 0 undoes the top of page transition,
- // so that the header macro will be called as if the top of page
- // transition hasn't happened. This is used by Larry Wall's
- // wrapman program. Setting before_first_page to 2 rather than 1,
- // tells top_level_diversion::begin_page not to call
- // output_file::begin_page again.
- if (n < 0 && topdiv->get_vertical_position() == V0)
- topdiv->before_first_page = 2;
-}
-
-class no_space_mode_reg : public reg {
-public:
- int get_value(units *);
- const char *get_string();
-};
-
-int no_space_mode_reg::get_value(units *val)
-{
- *val = curdiv->no_space_mode;
- return 1;
-}
-
-const char *no_space_mode_reg::get_string()
-{
- return curdiv->no_space_mode ? "1" : "0";
-}
-
-void init_div_requests()
-{
- init_request("wh", when_request);
- init_request("ch", change_trap);
- init_request("pl", page_length);
- init_request("po", page_offset);
- init_request("rs", restore_spacing);
- init_request("ns", no_space);
- init_request("sp", space_request);
- init_request("di", divert);
- init_request("da", divert_append);
- init_request("box", box);
- init_request("boxa", box_append);
- init_request("bp", begin_page);
- init_request("ne", need_space);
- init_request("pn", page_number);
- init_request("dt", diversion_trap);
- init_request("rt", return_request);
- init_request("mk", mark);
- init_request("sv", save_vertical_space);
- init_request("os", output_saved_vertical_space);
- init_request("fl", flush_output);
- init_request("vpt", vertical_position_traps);
- init_request("ptr", print_traps);
- number_reg_dictionary.define(".a",
- new constant_int_reg(&last_post_line_extra_space));
- number_reg_dictionary.define(".z", new diversion_name_reg);
- number_reg_dictionary.define(".o", new page_offset_reg);
- number_reg_dictionary.define(".p", new page_length_reg);
- number_reg_dictionary.define(".ns", new no_space_mode_reg);
- number_reg_dictionary.define(".d", new vertical_position_reg);
- number_reg_dictionary.define(".h", new high_water_mark_reg);
- number_reg_dictionary.define(".t", new distance_to_next_trap_reg);
- number_reg_dictionary.define("dl", new variable_reg(&dl_reg_contents));
- number_reg_dictionary.define("dn", new variable_reg(&dn_reg_contents));
- number_reg_dictionary.define("nl", new nl_reg);
- number_reg_dictionary.define(".vpt",
- new constant_int_reg(&vertical_position_traps_flag));
- number_reg_dictionary.define("%", new page_number_reg);
- number_reg_dictionary.define(".pn", new next_page_number_reg);
- number_reg_dictionary.define(".trunc",
- new constant_vunits_reg(&truncated_space));
- number_reg_dictionary.define(".ne",
- new constant_vunits_reg(&needed_space));
- number_reg_dictionary.define(".pe", new page_ejecting_reg);
-}
diff --git a/contrib/groff/src/roff/troff/env.cc b/contrib/groff/src/roff/troff/env.cc
deleted file mode 100644
index b14ffb6..0000000
--- a/contrib/groff/src/roff/troff/env.cc
+++ /dev/null
@@ -1,3829 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "troff.h"
-#include "symbol.h"
-#include "dictionary.h"
-#include "hvunits.h"
-#include "env.h"
-#include "request.h"
-#include "node.h"
-#include "token.h"
-#include "div.h"
-#include "reg.h"
-#include "charinfo.h"
-#include "macropath.h"
-#include "input.h"
-#include
-
-symbol default_family("T");
-
-enum { ADJUST_LEFT = 0, ADJUST_BOTH = 1, ADJUST_CENTER = 3, ADJUST_RIGHT = 5 };
-
-enum { HYPHEN_LAST_LINE = 2, HYPHEN_LAST_CHARS = 4, HYPHEN_FIRST_CHARS = 8 };
-
-struct env_list {
- environment *env;
- env_list *next;
- env_list(environment *e, env_list *p) : env(e), next(p) {}
-};
-
-env_list *env_stack;
-const int NENVIRONMENTS = 10;
-environment *env_table[NENVIRONMENTS];
-dictionary env_dictionary(10);
-environment *curenv;
-static int next_line_number = 0;
-
-charinfo *field_delimiter_char;
-charinfo *padding_indicator_char;
-
-int translate_space_to_dummy = 0;
-
-class pending_output_line {
- node *nd;
- int no_fill;
- vunits vs;
- vunits post_vs;
- hunits width;
-#ifdef WIDOW_CONTROL
- int last_line; // Is it the last line of the paragraph?
-#endif /* WIDOW_CONTROL */
-public:
- pending_output_line *next;
-
- pending_output_line(node *, int, vunits, vunits, hunits,
- pending_output_line * = 0);
- ~pending_output_line();
- int output();
-
-#ifdef WIDOW_CONTROL
- friend void environment::mark_last_line();
- friend void environment::output(node *, int, vunits, vunits, hunits);
-#endif /* WIDOW_CONTROL */
-};
-
-pending_output_line::pending_output_line(node *n, int nf, vunits v, vunits pv,
- hunits w, pending_output_line *p)
-: nd(n), no_fill(nf), vs(v), post_vs(pv), width(w),
-#ifdef WIDOW_CONTROL
- last_line(0),
-#endif /* WIDOW_CONTROL */
- next(p)
-{
-}
-
-pending_output_line::~pending_output_line()
-{
- delete_node_list(nd);
-}
-
-int pending_output_line::output()
-{
- if (trap_sprung_flag)
- return 0;
-#ifdef WIDOW_CONTROL
- if (next && next->last_line && !no_fill) {
- curdiv->need(vs + post_vs + vunits(vresolution));
- if (trap_sprung_flag) {
- next->last_line = 0; // Try to avoid infinite loops.
- return 0;
- }
- }
-#endif
- curdiv->output(nd, no_fill, vs, post_vs, width);
- nd = 0;
- return 1;
-}
-
-void environment::output(node *nd, int no_fill, vunits vs, vunits post_vs,
- hunits width)
-{
-#ifdef WIDOW_CONTROL
- while (pending_lines) {
- if (widow_control && !pending_lines->no_fill && !pending_lines->next)
- break;
- if (!pending_lines->output())
- break;
- pending_output_line *tem = pending_lines;
- pending_lines = pending_lines->next;
- delete tem;
- }
-#else /* WIDOW_CONTROL */
- output_pending_lines();
-#endif /* WIDOW_CONTROL */
- if (!trap_sprung_flag && !pending_lines
-#ifdef WIDOW_CONTROL
- && (!widow_control || no_fill)
-#endif /* WIDOW_CONTROL */
- ) {
- curdiv->output(nd, no_fill, vs, post_vs, width);
- emitted_node = 1;
- } else {
- pending_output_line **p;
- for (p = &pending_lines; *p; p = &(*p)->next)
- ;
- *p = new pending_output_line(nd, no_fill, vs, post_vs, width);
- }
-}
-
-// a line from .tl goes at the head of the queue
-
-void environment::output_title(node *nd, int no_fill, vunits vs,
- vunits post_vs, hunits width)
-{
- if (!trap_sprung_flag)
- curdiv->output(nd, no_fill, vs, post_vs, width);
- else
- pending_lines = new pending_output_line(nd, no_fill, vs, post_vs, width,
- pending_lines);
-}
-
-void environment::output_pending_lines()
-{
- while (pending_lines && pending_lines->output()) {
- pending_output_line *tem = pending_lines;
- pending_lines = pending_lines->next;
- delete tem;
- }
-}
-
-#ifdef WIDOW_CONTROL
-
-void environment::mark_last_line()
-{
- if (!widow_control || !pending_lines)
- return;
- for (pending_output_line *p = pending_lines; p->next; p = p->next)
- ;
- if (!p->no_fill)
- p->last_line = 1;
-}
-
-void widow_control_request()
-{
- int n;
- if (has_arg() && get_integer(&n))
- curenv->widow_control = n != 0;
- else
- curenv->widow_control = 1;
- skip_line();
-}
-
-#endif /* WIDOW_CONTROL */
-
-/* font_size functions */
-
-size_range *font_size::size_table = 0;
-int font_size::nranges = 0;
-
-extern "C" {
-
-int compare_ranges(const void *p1, const void *p2)
-{
- return ((size_range *)p1)->min - ((size_range *)p2)->min;
-}
-
-}
-
-void font_size::init_size_table(int *sizes)
-{
- nranges = 0;
- while (sizes[nranges*2] != 0)
- nranges++;
- assert(nranges > 0);
- size_table = new size_range[nranges];
- for (int i = 0; i < nranges; i++) {
- size_table[i].min = sizes[i*2];
- size_table[i].max = sizes[i*2 + 1];
- }
- qsort(size_table, nranges, sizeof(size_range), compare_ranges);
-}
-
-font_size::font_size(int sp)
-{
- for (int i = 0; i < nranges; i++) {
- if (sp < size_table[i].min) {
- if (i > 0 && size_table[i].min - sp >= sp - size_table[i - 1].max)
- p = size_table[i - 1].max;
- else
- p = size_table[i].min;
- return;
- }
- if (sp <= size_table[i].max) {
- p = sp;
- return;
- }
- }
- p = size_table[nranges - 1].max;
-}
-
-int font_size::to_units()
-{
- return scale(p, units_per_inch, sizescale*72);
-}
-
-// we can't do this in a static constructor because various dictionaries
-// have to get initialized first
-
-void init_environments()
-{
- curenv = env_table[0] = new environment("0");
-}
-
-void tab_character()
-{
- curenv->tab_char = get_optional_char();
- skip_line();
-}
-
-void leader_character()
-{
- curenv->leader_char = get_optional_char();
- skip_line();
-}
-
-void environment::add_char(charinfo *ci)
-{
- int s;
- if (interrupted)
- ;
- // don't allow fields in dummy environments
- else if (ci == field_delimiter_char && !dummy) {
- if (current_field)
- wrap_up_field();
- else
- start_field();
- }
- else if (current_field && ci == padding_indicator_char)
- add_padding();
- else if (current_tab) {
- if (tab_contents == 0)
- tab_contents = new line_start_node;
- if (ci != hyphen_indicator_char)
- tab_contents = tab_contents->add_char(ci, this, &tab_width, &s);
- else
- tab_contents = tab_contents->add_discretionary_hyphen();
- }
- else {
- if (line == 0)
- start_line();
- if (ci != hyphen_indicator_char)
- line = line->add_char(ci, this, &width_total, &space_total);
- else
- line = line->add_discretionary_hyphen();
- }
-}
-
-node *environment::make_char_node(charinfo *ci)
-{
- return make_node(ci, this);
-}
-
-void environment::add_node(node *n)
-{
- if (n == 0)
- return;
- if (current_tab || current_field)
- n->freeze_space();
- if (interrupted) {
- delete n;
- }
- else if (current_tab) {
- n->next = tab_contents;
- tab_contents = n;
- tab_width += n->width();
- }
- else {
- if (line == 0) {
- if (discarding && n->discardable()) {
- // XXX possibly: input_line_start -= n->width();
- delete n;
- return;
- }
- start_line();
- }
- width_total += n->width();
- space_total += n->nspaces();
- n->next = line;
- line = n;
- }
-}
-
-
-void environment::add_hyphen_indicator()
-{
- if (current_tab || interrupted || current_field
- || hyphen_indicator_char != 0)
- return;
- if (line == 0)
- start_line();
- line = line->add_discretionary_hyphen();
-}
-
-int environment::get_hyphenation_flags()
-{
- return hyphenation_flags;
-}
-
-int environment::get_hyphen_line_max()
-{
- return hyphen_line_max;
-}
-
-int environment::get_hyphen_line_count()
-{
- return hyphen_line_count;
-}
-
-int environment::get_center_lines()
-{
- return center_lines;
-}
-
-int environment::get_right_justify_lines()
-{
- return right_justify_lines;
-}
-
-void environment::add_italic_correction()
-{
- if (current_tab) {
- if (tab_contents)
- tab_contents = tab_contents->add_italic_correction(&tab_width);
- }
- else if (line)
- line = line->add_italic_correction(&width_total);
-}
-
-void environment::space_newline()
-{
- assert(!current_tab && !current_field);
- if (interrupted)
- return;
- hunits x = H0;
- hunits sw = env_space_width(this);
- hunits ssw = env_sentence_space_width(this);
- if (!translate_space_to_dummy) {
- x = sw;
- if (node_list_ends_sentence(line) == 1)
- x += ssw;
- }
- width_list *w = new width_list(sw, ssw);
- if (node_list_ends_sentence(line) == 1)
- w->next = new width_list(sw, ssw);
- if (line != 0 && line->merge_space(x, sw, ssw)) {
- width_total += x;
- return;
- }
- add_node(new word_space_node(x, get_fill_color(), w));
- possibly_break_line(0, spread_flag);
- spread_flag = 0;
-}
-
-void environment::space()
-{
- space(env_space_width(this), env_sentence_space_width(this));
-}
-
-void environment::space(hunits space_width, hunits sentence_space_width)
-{
- if (interrupted)
- return;
- if (current_field && padding_indicator_char == 0) {
- add_padding();
- return;
- }
- hunits x = translate_space_to_dummy ? H0 : space_width;
- node *p = current_tab ? tab_contents : line;
- hunits *tp = current_tab ? &tab_width : &width_total;
- if (p && p->nspaces() == 1 && p->width() == x
- && node_list_ends_sentence(p->next) == 1) {
- hunits xx = translate_space_to_dummy ? H0 : sentence_space_width;
- if (p->merge_space(xx, space_width, sentence_space_width)) {
- *tp += xx;
- return;
- }
- }
- if (p && p->merge_space(x, space_width, sentence_space_width)) {
- *tp += x;
- return;
- }
- add_node(new word_space_node(x,
- get_fill_color(),
- new width_list(space_width,
- sentence_space_width)));
- possibly_break_line(0, spread_flag);
- spread_flag = 0;
-}
-
-node *do_underline_special(int);
-
-void environment::set_font(symbol nm)
-{
- if (interrupted)
- return;
- if (nm == symbol("P") || nm.is_empty()) {
- if (family->make_definite(prev_fontno) < 0)
- return;
- int tem = fontno;
- fontno = prev_fontno;
- prev_fontno = tem;
- }
- else {
- prev_fontno = fontno;
- int n = symbol_fontno(nm);
- if (n < 0) {
- n = next_available_font_position();
- if (!mount_font(n, nm))
- return;
- }
- if (family->make_definite(n) < 0)
- return;
- fontno = n;
- }
- if (underline_spaces && fontno != prev_fontno) {
- if (fontno == get_underline_fontno())
- add_node(do_underline_special(1));
- if (prev_fontno == get_underline_fontno())
- add_node(do_underline_special(0));
- }
-}
-
-void environment::set_font(int n)
-{
- if (interrupted)
- return;
- if (is_good_fontno(n)) {
- prev_fontno = fontno;
- fontno = n;
- }
- else
- warning(WARN_FONT, "bad font number");
-}
-
-void environment::set_family(symbol fam)
-{
- if (interrupted)
- return;
- if (fam.is_null() || fam.is_empty()) {
- if (prev_family->make_definite(fontno) < 0)
- return;
- font_family *tem = family;
- family = prev_family;
- prev_family = tem;
- }
- else {
- font_family *f = lookup_family(fam);
- if (f->make_definite(fontno) < 0)
- return;
- prev_family = family;
- family = f;
- }
-}
-
-void environment::set_size(int n)
-{
- if (interrupted)
- return;
- if (n == 0) {
- font_size temp = prev_size;
- prev_size = size;
- size = temp;
- int temp2 = prev_requested_size;
- prev_requested_size = requested_size;
- requested_size = temp2;
- }
- else {
- prev_size = size;
- size = font_size(n);
- prev_requested_size = requested_size;
- requested_size = n;
- }
-}
-
-void environment::set_char_height(int n)
-{
- if (interrupted)
- return;
- if (n == requested_size || n <= 0)
- char_height = 0;
- else
- char_height = n;
-}
-
-void environment::set_char_slant(int n)
-{
- if (interrupted)
- return;
- char_slant = n;
-}
-
-color *environment::get_prev_glyph_color()
-{
- return prev_glyph_color;
-}
-
-color *environment::get_glyph_color()
-{
- return glyph_color;
-}
-
-color *environment::get_prev_fill_color()
-{
- return prev_fill_color;
-}
-
-color *environment::get_fill_color()
-{
- return fill_color;
-}
-
-void environment::set_glyph_color(color *c)
-{
- if (interrupted)
- return;
- curenv->prev_glyph_color = curenv->glyph_color;
- curenv->glyph_color = c;
-}
-
-void environment::set_fill_color(color *c)
-{
- if (interrupted)
- return;
- curenv->prev_fill_color = curenv->fill_color;
- curenv->fill_color = c;
-}
-
-environment::environment(symbol nm)
-: dummy(0),
- prev_line_length((units_per_inch*13)/2),
- line_length((units_per_inch*13)/2),
- prev_title_length((units_per_inch*13)/2),
- title_length((units_per_inch*13)/2),
- prev_size(sizescale*10),
- size(sizescale*10),
- requested_size(sizescale*10),
- prev_requested_size(sizescale*10),
- char_height(0),
- char_slant(0),
- space_size(12),
- sentence_space_size(12),
- adjust_mode(ADJUST_BOTH),
- fill(1),
- interrupted(0),
- prev_line_interrupted(0),
- center_lines(0),
- right_justify_lines(0),
- prev_vertical_spacing(points_to_units(12)),
- vertical_spacing(points_to_units(12)),
- prev_post_vertical_spacing(0),
- post_vertical_spacing(0),
- prev_line_spacing(1),
- line_spacing(1),
- prev_indent(0),
- indent(0),
- temporary_indent(0),
- have_temporary_indent(0),
- underline_lines(0),
- underline_spaces(0),
- input_trap_count(0),
- continued_input_trap(0),
- line(0),
- prev_text_length(0),
- width_total(0),
- space_total(0),
- input_line_start(0),
- tabs(units_per_inch/2, TAB_LEFT),
- line_tabs(0),
- current_tab(TAB_NONE),
- leader_node(0),
- tab_char(0),
- leader_char(charset_table['.']),
- current_field(0),
- discarding(0),
- spread_flag(0),
- margin_character_flags(0),
- margin_character_node(0),
- margin_character_distance(points_to_units(10)),
- numbering_nodes(0),
- number_text_separation(1),
- line_number_indent(0),
- line_number_multiple(1),
- no_number_count(0),
- hyphenation_flags(1),
- hyphen_line_count(0),
- hyphen_line_max(-1),
- hyphenation_space(H0),
- hyphenation_margin(H0),
- composite(0),
- pending_lines(0),
-#ifdef WIDOW_CONTROL
- widow_control(0),
-#endif /* WIDOW_CONTROL */
- ignore_next_eol(0),
- emitted_node(0),
- glyph_color(&default_color),
- prev_glyph_color(&default_color),
- fill_color(&default_color),
- prev_fill_color(&default_color),
- name(nm),
- control_char('.'),
- no_break_control_char('\''),
- hyphen_indicator_char(0)
-{
- prev_family = family = lookup_family(default_family);
- prev_fontno = fontno = 1;
- if (!is_good_fontno(1))
- fatal("font number 1 not a valid font");
- if (family->make_definite(1) < 0)
- fatal("invalid default family `%1'", default_family.contents());
- prev_fontno = fontno;
-}
-
-environment::environment(const environment *e)
-: dummy(1),
- prev_line_length(e->prev_line_length),
- line_length(e->line_length),
- prev_title_length(e->prev_title_length),
- title_length(e->title_length),
- prev_size(e->prev_size),
- size(e->size),
- requested_size(e->requested_size),
- prev_requested_size(e->prev_requested_size),
- char_height(e->char_height),
- char_slant(e->char_slant),
- prev_fontno(e->prev_fontno),
- fontno(e->fontno),
- prev_family(e->prev_family),
- family(e->family),
- space_size(e->space_size),
- sentence_space_size(e->sentence_space_size),
- adjust_mode(e->adjust_mode),
- fill(e->fill),
- interrupted(0),
- prev_line_interrupted(0),
- center_lines(0),
- right_justify_lines(0),
- prev_vertical_spacing(e->prev_vertical_spacing),
- vertical_spacing(e->vertical_spacing),
- prev_post_vertical_spacing(e->prev_post_vertical_spacing),
- post_vertical_spacing(e->post_vertical_spacing),
- prev_line_spacing(e->prev_line_spacing),
- line_spacing(e->line_spacing),
- prev_indent(e->prev_indent),
- indent(e->indent),
- temporary_indent(0),
- have_temporary_indent(0),
- underline_lines(0),
- underline_spaces(0),
- input_trap_count(0),
- continued_input_trap(0),
- line(0),
- prev_text_length(e->prev_text_length),
- width_total(0),
- space_total(0),
- input_line_start(0),
- tabs(e->tabs),
- line_tabs(e->line_tabs),
- current_tab(TAB_NONE),
- leader_node(0),
- tab_char(e->tab_char),
- leader_char(e->leader_char),
- current_field(0),
- discarding(0),
- spread_flag(0),
- margin_character_flags(e->margin_character_flags),
- margin_character_node(e->margin_character_node),
- margin_character_distance(e->margin_character_distance),
- numbering_nodes(0),
- number_text_separation(e->number_text_separation),
- line_number_indent(e->line_number_indent),
- line_number_multiple(e->line_number_multiple),
- no_number_count(e->no_number_count),
- hyphenation_flags(e->hyphenation_flags),
- hyphen_line_count(0),
- hyphen_line_max(e->hyphen_line_max),
- hyphenation_space(e->hyphenation_space),
- hyphenation_margin(e->hyphenation_margin),
- composite(0),
- pending_lines(0),
-#ifdef WIDOW_CONTROL
- widow_control(e->widow_control),
-#endif /* WIDOW_CONTROL */
- ignore_next_eol(0),
- emitted_node(0),
- glyph_color(e->glyph_color),
- prev_glyph_color(e->prev_glyph_color),
- fill_color(e->fill_color),
- prev_fill_color(e->prev_fill_color),
- name(e->name), // so that eg `.if "\n[.ev]"0"' works
- control_char(e->control_char),
- no_break_control_char(e->no_break_control_char),
- hyphen_indicator_char(e->hyphen_indicator_char)
-{
-}
-
-void environment::copy(const environment *e)
-{
- prev_line_length = e->prev_line_length;
- line_length = e->line_length;
- prev_title_length = e->prev_title_length;
- title_length = e->title_length;
- prev_size = e->prev_size;
- size = e->size;
- prev_requested_size = e->prev_requested_size;
- requested_size = e->requested_size;
- char_height = e->char_height;
- char_slant = e->char_slant;
- space_size = e->space_size;
- sentence_space_size = e->sentence_space_size;
- adjust_mode = e->adjust_mode;
- fill = e->fill;
- interrupted = 0;
- prev_line_interrupted = 0;
- center_lines = 0;
- right_justify_lines = 0;
- prev_vertical_spacing = e->prev_vertical_spacing;
- vertical_spacing = e->vertical_spacing;
- prev_post_vertical_spacing = e->prev_post_vertical_spacing,
- post_vertical_spacing = e->post_vertical_spacing,
- prev_line_spacing = e->prev_line_spacing;
- line_spacing = e->line_spacing;
- prev_indent = e->prev_indent;
- indent = e->indent;
- have_temporary_indent = 0;
- temporary_indent = 0;
- underline_lines = 0;
- underline_spaces = 0;
- input_trap_count = 0;
- continued_input_trap = 0;
- prev_text_length = e->prev_text_length;
- width_total = 0;
- space_total = 0;
- input_line_start = 0;
- control_char = e->control_char;
- no_break_control_char = e->no_break_control_char;
- hyphen_indicator_char = e->hyphen_indicator_char;
- spread_flag = 0;
- line = 0;
- pending_lines = 0;
- discarding = 0;
- tabs = e->tabs;
- line_tabs = e->line_tabs;
- current_tab = TAB_NONE;
- current_field = 0;
- margin_character_flags = e->margin_character_flags;
- margin_character_node = e->margin_character_node;
- margin_character_distance = e->margin_character_distance;
- numbering_nodes = 0;
- number_text_separation = e->number_text_separation;
- line_number_multiple = e->line_number_multiple;
- line_number_indent = e->line_number_indent;
- no_number_count = e->no_number_count;
- tab_char = e->tab_char;
- leader_char = e->leader_char;
- hyphenation_flags = e->hyphenation_flags;
- fontno = e->fontno;
- prev_fontno = e->prev_fontno;
- dummy = e->dummy;
- family = e->family;
- prev_family = e->prev_family;
- leader_node = 0;
-#ifdef WIDOW_CONTROL
- widow_control = e->widow_control;
-#endif /* WIDOW_CONTROL */
- hyphen_line_max = e->hyphen_line_max;
- hyphen_line_count = 0;
- hyphenation_space = e->hyphenation_space;
- hyphenation_margin = e->hyphenation_margin;
- composite = 0;
- ignore_next_eol = e->ignore_next_eol;
- emitted_node = e->emitted_node;
- glyph_color= e->glyph_color;
- prev_glyph_color = e->prev_glyph_color;
- fill_color = e->fill_color;
- prev_fill_color = e->prev_fill_color;
-}
-
-environment::~environment()
-{
- delete leader_node;
- delete_node_list(line);
- delete_node_list(numbering_nodes);
-}
-
-hunits environment::get_input_line_position()
-{
- hunits n;
- if (line == 0)
- n = -input_line_start;
- else
- n = width_total - input_line_start;
- if (current_tab)
- n += tab_width;
- return n;
-}
-
-void environment::set_input_line_position(hunits n)
-{
- input_line_start = line == 0 ? -n : width_total - n;
- if (current_tab)
- input_line_start += tab_width;
-}
-
-hunits environment::get_line_length()
-{
- return line_length;
-}
-
-hunits environment::get_saved_line_length()
-{
- if (line)
- return target_text_length + saved_indent;
- else
- return line_length;
-}
-
-vunits environment::get_vertical_spacing()
-{
- return vertical_spacing;
-}
-
-vunits environment::get_post_vertical_spacing()
-{
- return post_vertical_spacing;
-}
-
-int environment::get_line_spacing()
-{
- return line_spacing;
-}
-
-vunits environment::total_post_vertical_spacing()
-{
- vunits tem(post_vertical_spacing);
- if (line_spacing > 1)
- tem += (line_spacing - 1)*vertical_spacing;
- return tem;
-}
-
-int environment::get_bold()
-{
- return get_bold_fontno(fontno);
-}
-
-hunits environment::get_digit_width()
-{
- return env_digit_width(this);
-}
-
-int environment::get_adjust_mode()
-{
- return adjust_mode;
-}
-
-int environment::get_fill()
-{
- return fill;
-}
-
-hunits environment::get_indent()
-{
- return indent;
-}
-
-hunits environment::get_saved_indent()
-{
- if (line)
- return saved_indent;
- else if (have_temporary_indent)
- return temporary_indent;
- else
- return indent;
-}
-
-hunits environment::get_temporary_indent()
-{
- return temporary_indent;
-}
-
-hunits environment::get_title_length()
-{
- return title_length;
-}
-
-node *environment::get_prev_char()
-{
- for (node *n = current_tab ? tab_contents : line; n; n = n->next) {
- node *last = n->last_char_node();
- if (last)
- return last;
- }
- return 0;
-}
-
-hunits environment::get_prev_char_width()
-{
- node *last = get_prev_char();
- if (!last)
- return H0;
- return last->width();
-}
-
-hunits environment::get_prev_char_skew()
-{
- node *last = get_prev_char();
- if (!last)
- return H0;
- return last->skew();
-}
-
-vunits environment::get_prev_char_height()
-{
- node *last = get_prev_char();
- if (!last)
- return V0;
- vunits min, max;
- last->vertical_extent(&min, &max);
- return -min;
-}
-
-vunits environment::get_prev_char_depth()
-{
- node *last = get_prev_char();
- if (!last)
- return V0;
- vunits min, max;
- last->vertical_extent(&min, &max);
- return max;
-}
-
-hunits environment::get_text_length()
-{
- hunits n = line == 0 ? H0 : width_total;
- if (current_tab)
- n += tab_width;
- return n;
-}
-
-hunits environment::get_prev_text_length()
-{
- return prev_text_length;
-}
-
-
-static int sb_reg_contents = 0;
-static int st_reg_contents = 0;
-static int ct_reg_contents = 0;
-static int rsb_reg_contents = 0;
-static int rst_reg_contents = 0;
-static int skw_reg_contents = 0;
-static int ssc_reg_contents = 0;
-
-void environment::width_registers()
-{
- // this is used to implement \w; it sets the st, sb, ct registers
- vunits min = 0, max = 0, cur = 0;
- int character_type = 0;
- ssc_reg_contents = line ? line->subscript_correction().to_units() : 0;
- skw_reg_contents = line ? line->skew().to_units() : 0;
- line = reverse_node_list(line);
- vunits real_min = V0;
- vunits real_max = V0;
- vunits v1, v2;
- for (node *tem = line; tem; tem = tem->next) {
- tem->vertical_extent(&v1, &v2);
- v1 += cur;
- if (v1 < real_min)
- real_min = v1;
- v2 += cur;
- if (v2 > real_max)
- real_max = v2;
- if ((cur += tem->vertical_width()) < min)
- min = cur;
- else if (cur > max)
- max = cur;
- character_type |= tem->character_type();
- }
- line = reverse_node_list(line);
- st_reg_contents = -min.to_units();
- sb_reg_contents = -max.to_units();
- rst_reg_contents = -real_min.to_units();
- rsb_reg_contents = -real_max.to_units();
- ct_reg_contents = character_type;
-}
-
-node *environment::extract_output_line()
-{
- if (current_tab)
- wrap_up_tab();
- node *n = line;
- line = 0;
- return n;
-}
-
-/* environment related requests */
-
-void environment_switch()
-{
- int pop = 0; // 1 means pop, 2 means pop but no error message on underflow
- if (curenv->is_dummy())
- error("can't switch environments when current environment is dummy");
- else if (!has_arg())
- pop = 1;
- else {
- symbol nm;
- if (!tok.delimiter()) {
- // It looks like a number.
- int n;
- if (get_integer(&n)) {
- if (n >= 0 && n < NENVIRONMENTS) {
- env_stack = new env_list(curenv, env_stack);
- if (env_table[n] == 0)
- env_table[n] = new environment(i_to_a(n));
- curenv = env_table[n];
- }
- else
- nm = i_to_a(n);
- }
- else
- pop = 2;
- }
- else {
- nm = get_long_name(1);
- if (nm.is_null())
- pop = 2;
- }
- if (!nm.is_null()) {
- environment *e = (environment *)env_dictionary.lookup(nm);
- if (!e) {
- e = new environment(nm);
- (void)env_dictionary.lookup(nm, e);
- }
- env_stack = new env_list(curenv, env_stack);
- curenv = e;
- }
- }
- if (pop) {
- if (env_stack == 0) {
- if (pop == 1)
- error("environment stack underflow");
- }
- else {
- curenv = env_stack->env;
- env_list *tem = env_stack;
- env_stack = env_stack->next;
- delete tem;
- }
- }
- skip_line();
-}
-
-void environment_copy()
-{
- symbol nm;
- environment *e=0;
- tok.skip();
- if (!tok.delimiter()) {
- // It looks like a number.
- int n;
- if (get_integer(&n)) {
- if (n >= 0 && n < NENVIRONMENTS)
- e = env_table[n];
- else
- nm = i_to_a(n);
- }
- }
- else
- nm = get_long_name(1);
- if (!e && !nm.is_null())
- e = (environment *)env_dictionary.lookup(nm);
- if (e == 0) {
- error("No environment to copy from");
- return;
- }
- else
- curenv->copy(e);
- skip_line();
-}
-
-static symbol P_symbol("P");
-
-void font_change()
-{
- symbol s = get_name();
- int is_number = 1;
- if (s.is_null() || s == P_symbol) {
- s = P_symbol;
- is_number = 0;
- }
- else {
- for (const char *p = s.contents(); p != 0 && *p != 0; p++)
- if (!csdigit(*p)) {
- is_number = 0;
- break;
- }
- }
- if (is_number)
- curenv->set_font(atoi(s.contents()));
- else
- curenv->set_font(s);
- skip_line();
-}
-
-void family_change()
-{
- symbol s = get_name();
- curenv->set_family(s);
- skip_line();
-}
-
-void point_size()
-{
- int n;
- if (has_arg() && get_number(&n, 'z', curenv->get_requested_point_size())) {
- if (n <= 0)
- n = 1;
- curenv->set_size(n);
- curenv->add_html_tag(1, ".ps", n);
- }
- else
- curenv->set_size(0);
- skip_line();
-}
-
-void override_sizes()
-{
- int n = 16;
- int *sizes = new int[n];
- int i = 0;
- char *buf = read_string();
- if (!buf)
- return;
- char *p = strtok(buf, " \t");
- for (;;) {
- if (!p)
- break;
- int lower, upper;
- switch (sscanf(p, "%d-%d", &lower, &upper)) {
- case 1:
- upper = lower;
- // fall through
- case 2:
- if (lower <= upper && lower >= 0)
- break;
- // fall through
- default:
- warning(WARN_RANGE, "bad size range `%1'", p);
- return;
- }
- if (i + 2 > n) {
- int *old_sizes = sizes;
- sizes = new int[n*2];
- memcpy(sizes, old_sizes, n*sizeof(int));
- n *= 2;
- a_delete old_sizes;
- }
- sizes[i++] = lower;
- if (lower == 0)
- break;
- sizes[i++] = upper;
- p = strtok(0, " \t");
- }
- font_size::init_size_table(sizes);
-}
-
-void space_size()
-{
- int n;
- if (get_integer(&n)) {
- curenv->space_size = n;
- if (has_arg() && get_integer(&n))
- curenv->sentence_space_size = n;
- else
- curenv->sentence_space_size = curenv->space_size;
- }
- skip_line();
-}
-
-void fill()
-{
- while (!tok.newline() && !tok.eof())
- tok.next();
- if (break_flag)
- curenv->do_break();
- curenv->fill = 1;
- curenv->add_html_tag(1, ".fi");
- curenv->add_html_tag(0, ".br");
- tok.next();
-}
-
-void no_fill()
-{
- while (!tok.newline() && !tok.eof())
- tok.next();
- if (break_flag)
- curenv->do_break();
- curenv->fill = 0;
- curenv->add_html_tag(1, ".nf");
- curenv->add_html_tag(0, ".br");
- curenv->add_html_tag(0, ".po", topdiv->get_page_offset().to_units());
- tok.next();
-}
-
-void center()
-{
- int n;
- if (!has_arg() || !get_integer(&n))
- n = 1;
- else if (n < 0)
- n = 0;
- while (!tok.newline() && !tok.eof())
- tok.next();
- if (break_flag)
- curenv->do_break();
- curenv->right_justify_lines = 0;
- curenv->center_lines = n;
- curenv->add_html_tag(1, ".ce", n);
- tok.next();
-}
-
-void right_justify()
-{
- int n;
- if (!has_arg() || !get_integer(&n))
- n = 1;
- else if (n < 0)
- n = 0;
- while (!tok.newline() && !tok.eof())
- tok.next();
- if (break_flag)
- curenv->do_break();
- curenv->center_lines = 0;
- curenv->right_justify_lines = n;
- curenv->add_html_tag(1, ".rj", n);
- tok.next();
-}
-
-void line_length()
-{
- hunits temp;
- if (has_arg() && get_hunits(&temp, 'm', curenv->line_length)) {
- if (temp < H0) {
- warning(WARN_RANGE, "bad line length %1u", temp.to_units());
- temp = H0;
- }
- }
- else
- temp = curenv->prev_line_length;
- curenv->prev_line_length = curenv->line_length;
- curenv->line_length = temp;
- curenv->add_html_tag(1, ".ll", temp.to_units());
- skip_line();
-}
-
-void title_length()
-{
- hunits temp;
- if (has_arg() && get_hunits(&temp, 'm', curenv->title_length)) {
- if (temp < H0) {
- warning(WARN_RANGE, "bad title length %1u", temp.to_units());
- temp = H0;
- }
- }
- else
- temp = curenv->prev_title_length;
- curenv->prev_title_length = curenv->title_length;
- curenv->title_length = temp;
- skip_line();
-}
-
-void vertical_spacing()
-{
- vunits temp;
- if (has_arg() && get_vunits(&temp, 'p', curenv->vertical_spacing)) {
- if (temp <= V0) {
- warning(WARN_RANGE, "vertical spacing must be greater than 0");
- temp = vresolution;
- }
- }
- else
- temp = curenv->prev_vertical_spacing;
- curenv->prev_vertical_spacing = curenv->vertical_spacing;
- curenv->vertical_spacing = temp;
- skip_line();
-}
-
-void post_vertical_spacing()
-{
- vunits temp;
- if (has_arg() && get_vunits(&temp, 'p', curenv->post_vertical_spacing)) {
- if (temp < V0) {
- warning(WARN_RANGE,
- "post vertical spacing must be greater than or equal to 0");
- temp = V0;
- }
- }
- else
- temp = curenv->prev_post_vertical_spacing;
- curenv->prev_post_vertical_spacing = curenv->post_vertical_spacing;
- curenv->post_vertical_spacing = temp;
- skip_line();
-}
-
-void line_spacing()
-{
- int temp;
- if (has_arg() && get_integer(&temp)) {
- if (temp < 1) {
- warning(WARN_RANGE, "value %1 out of range: interpreted as 1", temp);
- temp = 1;
- }
- }
- else
- temp = curenv->prev_line_spacing;
- curenv->prev_line_spacing = curenv->line_spacing;
- curenv->line_spacing = temp;
- skip_line();
-}
-
-void indent()
-{
- hunits temp;
- if (has_arg() && get_hunits(&temp, 'm', curenv->indent)) {
- if (temp < H0) {
- warning(WARN_RANGE, "indent cannot be negative");
- temp = H0;
- }
- }
- else
- temp = curenv->prev_indent;
- while (!tok.newline() && !tok.eof())
- tok.next();
- if (break_flag)
- curenv->do_break();
- curenv->have_temporary_indent = 0;
- curenv->prev_indent = curenv->indent;
- curenv->indent = temp;
- if (break_flag)
- curenv->add_html_tag(1, ".in", temp.to_units());
- tok.next();
-}
-
-void temporary_indent()
-{
- int err = 0;
- hunits temp;
- if (!get_hunits(&temp, 'm', curenv->get_indent()))
- err = 1;
- while (!tok.newline() && !tok.eof())
- tok.next();
- if (break_flag)
- curenv->do_break();
- if (temp < H0) {
- warning(WARN_RANGE, "total indent cannot be negative");
- temp = H0;
- }
- if (!err) {
- curenv->temporary_indent = temp;
- curenv->have_temporary_indent = 1;
- curenv->add_html_tag(1, ".ti", temp.to_units());
- }
- tok.next();
-}
-
-node *do_underline_special(int underline_spaces)
-{
- macro m;
- m.append_str("x u ");
- m.append(underline_spaces + '0');
- return new special_node(m, 1);
-}
-
-void do_underline(int underline_spaces)
-{
- int n;
- if (!has_arg() || !get_integer(&n))
- n = 1;
- if (n <= 0) {
- if (curenv->underline_lines > 0) {
- curenv->prev_fontno = curenv->fontno;
- curenv->fontno = curenv->pre_underline_fontno;
- if (underline_spaces) {
- curenv->underline_spaces = 0;
- curenv->add_node(do_underline_special(0));
- }
- }
- curenv->underline_lines = 0;
- }
- else {
- curenv->underline_lines = n;
- curenv->pre_underline_fontno = curenv->fontno;
- curenv->fontno = get_underline_fontno();
- if (underline_spaces) {
- curenv->underline_spaces = 1;
- curenv->add_node(do_underline_special(1));
- }
- }
- skip_line();
-}
-
-void continuous_underline()
-{
- do_underline(1);
-}
-
-void underline()
-{
- do_underline(0);
-}
-
-void control_char()
-{
- curenv->control_char = '.';
- if (has_arg()) {
- if (tok.ch() == 0)
- error("bad control character");
- else
- curenv->control_char = tok.ch();
- }
- skip_line();
-}
-
-void no_break_control_char()
-{
- curenv->no_break_control_char = '\'';
- if (has_arg()) {
- if (tok.ch() == 0)
- error("bad control character");
- else
- curenv->no_break_control_char = tok.ch();
- }
- skip_line();
-}
-
-void margin_character()
-{
- while (tok.space())
- tok.next();
- charinfo *ci = tok.get_char();
- if (ci) {
- // Call tok.next() only after making the node so that
- // .mc \s+9\(br\s0 works.
- node *nd = curenv->make_char_node(ci);
- tok.next();
- if (nd) {
- delete curenv->margin_character_node;
- curenv->margin_character_node = nd;
- curenv->margin_character_flags = (MARGIN_CHARACTER_ON
- |MARGIN_CHARACTER_NEXT);
- hunits d;
- if (has_arg() && get_hunits(&d, 'm'))
- curenv->margin_character_distance = d;
- }
- }
- else {
- check_missing_character();
- curenv->margin_character_flags &= ~MARGIN_CHARACTER_ON;
- if (curenv->margin_character_flags == 0) {
- delete curenv->margin_character_node;
- curenv->margin_character_node = 0;
- }
- }
- skip_line();
-}
-
-void number_lines()
-{
- delete_node_list(curenv->numbering_nodes);
- curenv->numbering_nodes = 0;
- if (has_arg()) {
- node *nd = 0;
- for (int i = '9'; i >= '0'; i--) {
- node *tem = make_node(charset_table[i], curenv);
- if (!tem) {
- skip_line();
- return;
- }
- tem->next = nd;
- nd = tem;
- }
- curenv->numbering_nodes = nd;
- curenv->line_number_digit_width = env_digit_width(curenv);
- int n;
- if (!tok.delimiter()) {
- if (get_integer(&n, next_line_number)) {
- next_line_number = n;
- if (next_line_number < 0) {
- warning(WARN_RANGE, "negative line number");
- next_line_number = 0;
- }
- }
- }
- else
- while (!tok.space() && !tok.newline() && !tok.eof())
- tok.next();
- if (has_arg()) {
- if (!tok.delimiter()) {
- if (get_integer(&n)) {
- if (n <= 0) {
- warning(WARN_RANGE, "negative or zero line number multiple");
- }
- else
- curenv->line_number_multiple = n;
- }
- }
- else
- while (!tok.space() && !tok.newline() && !tok.eof())
- tok.next();
- if (has_arg()) {
- if (!tok.delimiter()) {
- if (get_integer(&n))
- curenv->number_text_separation = n;
- }
- else
- while (!tok.space() && !tok.newline() && !tok.eof())
- tok.next();
- if (has_arg() && !tok.delimiter() && get_integer(&n))
- curenv->line_number_indent = n;
- }
- }
- }
- skip_line();
-}
-
-void no_number()
-{
- int n;
- if (has_arg() && get_integer(&n))
- curenv->no_number_count = n > 0 ? n : 0;
- else
- curenv->no_number_count = 1;
- skip_line();
-}
-
-void no_hyphenate()
-{
- curenv->hyphenation_flags = 0;
- skip_line();
-}
-
-void hyphenate_request()
-{
- int n;
- if (has_arg() && get_integer(&n))
- curenv->hyphenation_flags = n;
- else
- curenv->hyphenation_flags = 1;
- skip_line();
-}
-
-void hyphen_char()
-{
- curenv->hyphen_indicator_char = get_optional_char();
- skip_line();
-}
-
-void hyphen_line_max_request()
-{
- int n;
- if (has_arg() && get_integer(&n))
- curenv->hyphen_line_max = n;
- else
- curenv->hyphen_line_max = -1;
- skip_line();
-}
-
-void environment::interrupt()
-{
- if (!dummy) {
- add_node(new transparent_dummy_node);
- interrupted = 1;
- }
-}
-
-void environment::newline()
-{
- if (underline_lines > 0) {
- if (--underline_lines == 0) {
- prev_fontno = fontno;
- fontno = pre_underline_fontno;
- if (underline_spaces) {
- underline_spaces = 0;
- add_node(do_underline_special(0));
- }
- }
- }
- if (current_field)
- wrap_up_field();
- if (current_tab)
- wrap_up_tab();
- // strip trailing spaces
- while (line != 0 && line->discardable()) {
- width_total -= line->width();
- space_total -= line->nspaces();
- node *tem = line;
- line = line->next;
- delete tem;
- }
- node *to_be_output = 0;
- hunits to_be_output_width;
- prev_line_interrupted = 0;
- if (dummy)
- space_newline();
- else if (interrupted) {
- interrupted = 0;
- // see environment::final_break
- prev_line_interrupted = exit_started ? 2 : 1;
- }
- else if (center_lines > 0) {
- --center_lines;
- hunits x = target_text_length - width_total;
- if (x > H0)
- saved_indent += x/2;
- to_be_output = line;
- if (is_html) {
- node *n = make_html_tag("eol.ce");
- n->next = to_be_output;
- to_be_output = n;
- }
- to_be_output_width = width_total;
- line = 0;
- }
- else if (right_justify_lines > 0) {
- --right_justify_lines;
- hunits x = target_text_length - width_total;
- if (x > H0)
- saved_indent += x;
- to_be_output = line;
- to_be_output_width = width_total;
- line = 0;
- }
- else if (fill)
- space_newline();
- else {
- to_be_output = line;
- to_be_output_width = width_total;
- line = 0;
- }
- input_line_start = line == 0 ? H0 : width_total;
- if (to_be_output) {
- if (is_html && !fill) {
- if (curdiv == topdiv) {
- node *n = make_html_tag("eol");
-
- n->next = to_be_output;
- to_be_output = n;
- }
- }
- output_line(to_be_output, to_be_output_width);
- hyphen_line_count = 0;
- }
- if (input_trap_count > 0) {
- if (!(continued_input_trap && prev_line_interrupted))
- if (--input_trap_count == 0)
- spring_trap(input_trap);
- }
-}
-
-void environment::output_line(node *n, hunits width)
-{
- prev_text_length = width;
- if (margin_character_flags) {
- hunits d = line_length + margin_character_distance - saved_indent - width;
- if (d > 0) {
- n = new hmotion_node(d, get_fill_color(), n);
- width += d;
- }
- margin_character_flags &= ~MARGIN_CHARACTER_NEXT;
- node *tem;
- if (!margin_character_flags) {
- tem = margin_character_node;
- margin_character_node = 0;
- }
- else
- tem = margin_character_node->copy();
- tem->next = n;
- n = tem;
- width += tem->width();
- }
- node *nn = 0;
- while (n != 0) {
- node *tem = n->next;
- n->next = nn;
- nn = n;
- n = tem;
- }
- if (!saved_indent.is_zero())
- nn = new hmotion_node(saved_indent, get_fill_color(), nn);
- width += saved_indent;
- if (no_number_count > 0)
- --no_number_count;
- else if (numbering_nodes) {
- hunits w = (line_number_digit_width
- *(3+line_number_indent+number_text_separation));
- if (next_line_number % line_number_multiple != 0)
- nn = new hmotion_node(w, get_fill_color(), nn);
- else {
- hunits x = w;
- nn = new hmotion_node(number_text_separation * line_number_digit_width,
- get_fill_color(), nn);
- x -= number_text_separation*line_number_digit_width;
- char buf[30];
- sprintf(buf, "%3d", next_line_number);
- for (char *p = strchr(buf, '\0') - 1; p >= buf && *p != ' '; --p) {
- node *gn = numbering_nodes;
- for (int count = *p - '0'; count > 0; count--)
- gn = gn->next;
- gn = gn->copy();
- x -= gn->width();
- gn->next = nn;
- nn = gn;
- }
- nn = new hmotion_node(x, get_fill_color(), nn);
- }
- width += w;
- ++next_line_number;
- }
- output(nn, !fill, vertical_spacing, total_post_vertical_spacing(), width);
-}
-
-void environment::start_line()
-{
- assert(line == 0);
- discarding = 0;
- line = new line_start_node;
- if (have_temporary_indent) {
- saved_indent = temporary_indent;
- have_temporary_indent = 0;
- }
- else
- saved_indent = indent;
- target_text_length = line_length - saved_indent;
- width_total = H0;
- space_total = 0;
-}
-
-hunits environment::get_hyphenation_space()
-{
- return hyphenation_space;
-}
-
-void hyphenation_space_request()
-{
- hunits n;
- if (get_hunits(&n, 'm')) {
- if (n < H0) {
- warning(WARN_RANGE, "hyphenation space cannot be negative");
- n = H0;
- }
- curenv->hyphenation_space = n;
- }
- skip_line();
-}
-
-hunits environment::get_hyphenation_margin()
-{
- return hyphenation_margin;
-}
-
-void hyphenation_margin_request()
-{
- hunits n;
- if (get_hunits(&n, 'm')) {
- if (n < H0) {
- warning(WARN_RANGE, "hyphenation margin cannot be negative");
- n = H0;
- }
- curenv->hyphenation_margin = n;
- }
- skip_line();
-}
-
-breakpoint *environment::choose_breakpoint()
-{
- hunits x = width_total;
- int s = space_total;
- node *n = line;
- breakpoint *best_bp = 0; // the best breakpoint so far
- int best_bp_fits = 0;
- while (n != 0) {
- x -= n->width();
- s -= n->nspaces();
- breakpoint *bp = n->get_breakpoints(x, s);
- while (bp != 0) {
- if (bp->width <= target_text_length) {
- if (!bp->hyphenated) {
- breakpoint *tem = bp->next;
- bp->next = 0;
- while (tem != 0) {
- breakpoint *tem1 = tem;
- tem = tem->next;
- delete tem1;
- }
- if (best_bp_fits
- // Decide whether to use the hyphenated breakpoint.
- && (hyphen_line_max < 0
- // Only choose the hyphenated breakpoint if it would not
- // exceed the maximum number of consecutive hyphenated
- // lines.
- || hyphen_line_count + 1 <= hyphen_line_max)
- && !(adjust_mode == ADJUST_BOTH
- // Don't choose the hyphenated breakpoint if the line
- // can be justified by adding no more than
- // hyphenation_space to any word space.
- ? (bp->nspaces > 0
- && (((target_text_length - bp->width
- + (bp->nspaces - 1)*hresolution)/bp->nspaces)
- <= hyphenation_space))
- // Don't choose the hyphenated breakpoint if the line
- // is no more than hyphenation_margin short.
- : target_text_length - bp->width <= hyphenation_margin)) {
- delete bp;
- return best_bp;
- }
- if (best_bp)
- delete best_bp;
- return bp;
- }
- else {
- if ((adjust_mode == ADJUST_BOTH
- ? hyphenation_space == H0
- : hyphenation_margin == H0)
- && (hyphen_line_max < 0
- || hyphen_line_count + 1 <= hyphen_line_max)) {
- // No need to consider a non-hyphenated breakpoint.
- if (best_bp)
- delete best_bp;
- return bp;
- }
- // It fits but it's hyphenated.
- if (!best_bp_fits) {
- if (best_bp)
- delete best_bp;
- best_bp = bp;
- bp = bp->next;
- best_bp_fits = 1;
- }
- else {
- breakpoint *tem = bp;
- bp = bp->next;
- delete tem;
- }
- }
- }
- else {
- if (best_bp)
- delete best_bp;
- best_bp = bp;
- bp = bp->next;
- }
- }
- n = n->next;
- }
- if (best_bp) {
- if (!best_bp_fits)
- output_warning(WARN_BREAK, "can't break line");
- return best_bp;
- }
- return 0;
-}
-
-void environment::hyphenate_line(int start_here)
-{
- if (line == 0)
- return;
- hyphenation_type prev_type = line->get_hyphenation_type();
- node **startp;
- if (start_here)
- startp = &line;
- else
- for (startp = &line->next; *startp != 0; startp = &(*startp)->next) {
- hyphenation_type this_type = (*startp)->get_hyphenation_type();
- if (prev_type == HYPHEN_BOUNDARY && this_type == HYPHEN_MIDDLE)
- break;
- prev_type = this_type;
- }
- if (*startp == 0)
- return;
- node *tem = *startp;
- int i = 0;
- do {
- ++i;
- tem = tem->next;
- } while (tem != 0 && tem->get_hyphenation_type() == HYPHEN_MIDDLE);
- int inhibit = (tem != 0 && tem->get_hyphenation_type() == HYPHEN_INHIBIT);
- node *end = tem;
- hyphen_list *sl = 0;
- tem = *startp;
- node *forward = 0;
- while (tem != end) {
- sl = tem->get_hyphen_list(sl);
- node *tem1 = tem;
- tem = tem->next;
- tem1->next = forward;
- forward = tem1;
- }
- if (!inhibit) {
- // this is for characters like hyphen and emdash
- int prev_code = 0;
- for (hyphen_list *h = sl; h; h = h->next) {
- h->breakable = (prev_code != 0
- && h->next != 0
- && h->next->hyphenation_code != 0);
- prev_code = h->hyphenation_code;
- }
- }
- if (hyphenation_flags != 0
- && !inhibit
- // this may not be right if we have extra space on this line
- && !((hyphenation_flags & HYPHEN_LAST_LINE)
- && (curdiv->distance_to_next_trap()
- <= vertical_spacing + total_post_vertical_spacing()))
- && i >= 4)
- hyphenate(sl, hyphenation_flags);
- while (forward != 0) {
- node *tem1 = forward;
- forward = forward->next;
- tem1->next = 0;
- tem = tem1->add_self(tem, &sl);
- }
- *startp = tem;
-}
-
-static node *node_list_reverse(node *n)
-{
- node *res = 0;
- while (n) {
- node *tem = n;
- n = n->next;
- tem->next = res;
- res = tem;
- }
- return res;
-}
-
-static void distribute_space(node *n, int nspaces, hunits desired_space,
- int force_reverse = 0)
-{
- static int reverse = 0;
- if (force_reverse || reverse)
- n = node_list_reverse(n);
- if (!force_reverse && nspaces > 0 && spread_limit >= 0
- && desired_space.to_units() > 0) {
- hunits em = curenv->get_size();
- double Ems = (double)desired_space.to_units() / nspaces
- / (em.is_zero() ? hresolution : em.to_units());
- if (Ems > spread_limit)
- output_warning(WARN_BREAK, "spreading %1m per space", Ems);
- }
- for (node *tem = n; tem; tem = tem->next)
- tem->spread_space(&nspaces, &desired_space);
- if (force_reverse || reverse)
- (void)node_list_reverse(n);
- if (!force_reverse)
- reverse = !reverse;
- assert(desired_space.is_zero() && nspaces == 0);
-}
-
-void environment::possibly_break_line(int start_here, int forced)
-{
- if (!fill || current_tab || current_field || dummy)
- return;
- while (line != 0
- && (forced
- // When a macro follows a paragraph in fill mode, the
- // current line should not be empty.
- || (width_total - line->width()) > target_text_length)) {
- hyphenate_line(start_here);
- breakpoint *bp = choose_breakpoint();
- if (bp == 0)
- // we'll find one eventually
- return;
- node *pre, *post;
- node **ndp = &line;
- while (*ndp != bp->nd)
- ndp = &(*ndp)->next;
- bp->nd->split(bp->index, &pre, &post);
- *ndp = post;
- hunits extra_space_width = H0;
- switch(adjust_mode) {
- case ADJUST_BOTH:
- if (bp->nspaces != 0)
- extra_space_width = target_text_length - bp->width;
- else if (bp->width > 0 && target_text_length > 0
- && target_text_length > bp->width)
- output_warning(WARN_BREAK, "cannot adjust line");
- break;
- case ADJUST_CENTER:
- saved_indent += (target_text_length - bp->width)/2;
- break;
- case ADJUST_RIGHT:
- saved_indent += target_text_length - bp->width;
- break;
- }
- distribute_space(pre, bp->nspaces, extra_space_width);
- hunits output_width = bp->width + extra_space_width;
- input_line_start -= output_width;
- if (bp->hyphenated)
- hyphen_line_count++;
- else
- hyphen_line_count = 0;
- delete bp;
- space_total = 0;
- width_total = 0;
- node *first_non_discardable = 0;
- node *tem;
- for (tem = line; tem != 0; tem = tem->next)
- if (!tem->discardable())
- first_non_discardable = tem;
- node *to_be_discarded;
- if (first_non_discardable) {
- to_be_discarded = first_non_discardable->next;
- first_non_discardable->next = 0;
- for (tem = line; tem != 0; tem = tem->next) {
- width_total += tem->width();
- space_total += tem->nspaces();
- }
- discarding = 0;
- }
- else {
- discarding = 1;
- to_be_discarded = line;
- line = 0;
- }
- // Do output_line() here so that line will be 0 iff the
- // the environment will be empty.
- output_line(pre, output_width);
- while (to_be_discarded != 0) {
- tem = to_be_discarded;
- to_be_discarded = to_be_discarded->next;
- input_line_start -= tem->width();
- delete tem;
- }
- if (line != 0) {
- if (have_temporary_indent) {
- saved_indent = temporary_indent;
- have_temporary_indent = 0;
- }
- else
- saved_indent = indent;
- target_text_length = line_length - saved_indent;
- }
- }
-}
-
-/*
-Do the break at the end of input after the end macro (if any).
-
-Unix troff behaves as follows: if the last line is
-
-foo bar\c
-
-it will output foo on the current page, and bar on the next page;
-if the last line is
-
-foo\c
-
-or
-
-foo bar
-
-everything will be output on the current page. This behaviour must be
-considered a bug.
-
-The problem is that some macro packages rely on this. For example,
-the ATK macros have an end macro that emits \c if it needs to print a
-table of contents but doesn't do a 'bp in the end macro; instead the
-'bp is done in the bottom of page trap. This works with Unix troff,
-provided that the current environment is not empty at the end of the
-input file.
-
-The following will make macro packages that do that sort of thing work
-even if the current environment is empty at the end of the input file.
-If the last input line used \c and this line occurred in the end macro,
-then we'll force everything out on the current page, but we'll make
-sure that the environment isn't empty so that we won't exit at the
-bottom of this page.
-*/
-
-void environment::final_break()
-{
- if (prev_line_interrupted == 2) {
- do_break();
- add_node(new transparent_dummy_node);
- }
- else
- do_break();
-}
-
-/*
- * add_html_tag - emits a special html-tag: to help post-grohtml understand
- * the key troff commands
- */
-
-void environment::add_html_tag(int force, const char *name)
-{
- if (!force && (curdiv != topdiv))
- return;
-
- if (is_html) {
- /*
- * need to emit tag for post-grohtml
- * but we check to see whether we can emit specials
- */
- if (curdiv == topdiv && topdiv->before_first_page)
- topdiv->begin_page();
- macro *m = new macro;
- m->append_str("html-tag:");
- for (const char *p = name; *p; p++)
- if (!invalid_input_char((unsigned char)*p))
- m->append(*p);
- curdiv->output(new special_node(*m), 1, 0, 0, 0);
- if (strcmp(name, ".nf") == 0)
- curenv->ignore_next_eol = 1;
- }
-}
-
-/*
- * add_html_tag - emits a special html-tag: to help post-grohtml understand
- * the key troff commands, it appends a string representation
- * of i.
- */
-
-void environment::add_html_tag(int force, const char *name, int i)
-{
- if (!force && (curdiv != topdiv))
- return;
-
- if (is_html) {
- /*
- * need to emit tag for post-grohtml
- * but we check to see whether we can emit specials
- */
- if (curdiv == topdiv && topdiv->before_first_page)
- topdiv->begin_page();
- macro *m = new macro;
- m->append_str("html-tag:");
- for (const char *p = name; *p; p++)
- if (!invalid_input_char((unsigned char)*p))
- m->append(*p);
- m->append(' ');
- m->append_int(i);
- node *n = new special_node(*m);
- curdiv->output(n, 1, 0, 0, 0);
- }
-}
-
-/*
- * add_html_tag_tabs - emits the tab settings for post-grohtml
- */
-
-void environment::add_html_tag_tabs(int force)
-{
- if (!force && (curdiv != topdiv))
- return;
-
- if (is_html) {
- /*
- * need to emit tag for post-grohtml
- * but we check to see whether we can emit specials
- */
- if (curdiv == topdiv && topdiv->before_first_page)
- topdiv->begin_page();
- macro *m = new macro;
- hunits d, l;
- enum tab_type t;
- m->append_str("html-tag:.ta ");
- do {
- t = curenv->tabs.distance_to_next_tab(l, &d);
- l += d;
- switch (t) {
- case TAB_LEFT:
- m->append_str(" L ");
- m->append_int(l.to_units());
- break;
- case TAB_CENTER:
- m->append_str(" C ");
- m->append_int(l.to_units());
- break;
- case TAB_RIGHT:
- m->append_str(" R ");
- m->append_int(l.to_units());
- break;
- case TAB_NONE:
- break;
- }
- } while ((t != TAB_NONE) && (l < get_line_length()));
- curdiv->output(new special_node(*m), 1, 0, 0, 0);
- }
-}
-
-node *environment::make_html_tag(const char *name, int i)
-{
- if (is_html) {
- /*
- * need to emit tag for post-grohtml
- * but we check to see whether we can emit specials
- */
- if (curdiv == topdiv && topdiv->before_first_page)
- topdiv->begin_page();
- macro *m = new macro;
- m->append_str("html-tag:");
- for (const char *p = name; *p; p++)
- if (!invalid_input_char((unsigned char)*p))
- m->append(*p);
- m->append(' ');
- m->append_int(i);
- return new special_node(*m);
- }
- return 0;
-}
-
-node *environment::make_html_tag(const char *name)
-{
- if (is_html) {
- /*
- * need to emit tag for post-grohtml
- * but we check to see whether we can emit specials
- */
- if (curdiv == topdiv && topdiv->before_first_page)
- topdiv->begin_page();
- macro *m = new macro;
- m->append_str("html-tag:");
- for (const char *p = name; *p; p++)
- if (!invalid_input_char((unsigned char)*p))
- m->append(*p);
- return new special_node(*m);
- }
- return 0;
-}
-
-void environment::do_break(int spread)
-{
- if (curdiv == topdiv && topdiv->before_first_page) {
- topdiv->begin_page();
- return;
- }
- if (current_tab)
- wrap_up_tab();
- if (line) {
- // this is so that hyphenation works
- line = new space_node(H0, get_fill_color(), line);
- space_total++;
- possibly_break_line(0, spread);
- }
- while (line != 0 && line->discardable()) {
- width_total -= line->width();
- space_total -= line->nspaces();
- node *tem = line;
- line = line->next;
- delete tem;
- }
- discarding = 0;
- input_line_start = H0;
- if (line != 0) {
- if (fill) {
- switch (adjust_mode) {
- case ADJUST_CENTER:
- saved_indent += (target_text_length - width_total)/2;
- break;
- case ADJUST_RIGHT:
- saved_indent += target_text_length - width_total;
- break;
- }
- }
- node *tem = line;
- line = 0;
- output_line(tem, width_total);
- hyphen_line_count = 0;
- }
- prev_line_interrupted = 0;
-#ifdef WIDOW_CONTROL
- mark_last_line();
- output_pending_lines();
-#endif /* WIDOW_CONTROL */
-}
-
-int environment::is_empty()
-{
- return !current_tab && line == 0 && pending_lines == 0;
-}
-
-void do_break_request(int spread)
-{
- while (!tok.newline() && !tok.eof())
- tok.next();
- if (break_flag) {
- curenv->do_break(spread);
- curenv->add_html_tag(0, ".br");
- }
- tok.next();
-}
-
-void break_request()
-{
- do_break_request(0);
-}
-
-void break_spread_request()
-{
- do_break_request(1);
-}
-
-void title()
-{
- if (curdiv == topdiv && topdiv->before_first_page) {
- handle_initial_title();
- return;
- }
- node *part[3];
- hunits part_width[3];
- part[0] = part[1] = part[2] = 0;
- environment env(curenv);
- environment *oldenv = curenv;
- curenv = &env;
- read_title_parts(part, part_width);
- curenv = oldenv;
- curenv->size = env.size;
- curenv->prev_size = env.prev_size;
- curenv->requested_size = env.requested_size;
- curenv->prev_requested_size = env.prev_requested_size;
- curenv->char_height = env.char_height;
- curenv->char_slant = env.char_slant;
- curenv->fontno = env.fontno;
- curenv->prev_fontno = env.prev_fontno;
- curenv->glyph_color = env.glyph_color;
- curenv->prev_glyph_color = env.prev_glyph_color;
- curenv->fill_color = env.fill_color;
- curenv->prev_fill_color = env.prev_fill_color;
- node *n = 0;
- node *p = part[2];
- while (p != 0) {
- node *tem = p;
- p = p->next;
- tem->next = n;
- n = tem;
- }
- hunits title_length(curenv->title_length);
- hunits f = title_length - part_width[1];
- hunits f2 = f/2;
- n = new hmotion_node(f2 - part_width[2], curenv->get_fill_color(), n);
- p = part[1];
- while (p != 0) {
- node *tem = p;
- p = p->next;
- tem->next = n;
- n = tem;
- }
- n = new hmotion_node(f - f2 - part_width[0], curenv->get_fill_color(), n);
- p = part[0];
- while (p != 0) {
- node *tem = p;
- p = p->next;
- tem->next = n;
- n = tem;
- }
- curenv->output_title(n, !curenv->fill, curenv->vertical_spacing,
- curenv->total_post_vertical_spacing(), title_length);
- curenv->hyphen_line_count = 0;
- tok.next();
-}
-
-void adjust()
-{
- curenv->adjust_mode |= 1;
- if (has_arg()) {
- switch (tok.ch()) {
- case 'l':
- curenv->adjust_mode = ADJUST_LEFT;
- break;
- case 'r':
- curenv->adjust_mode = ADJUST_RIGHT;
- break;
- case 'c':
- curenv->adjust_mode = ADJUST_CENTER;
- break;
- case 'b':
- case 'n':
- curenv->adjust_mode = ADJUST_BOTH;
- break;
- default:
- int n;
- if (get_integer(&n)) {
- if (n < 0)
- warning(WARN_RANGE, "negative adjustment mode");
- else if (n > 5) {
- curenv->adjust_mode = 5;
- warning(WARN_RANGE, "adjustment mode `%1' out of range", n);
- }
- else
- curenv->adjust_mode = n;
- }
- }
- }
- skip_line();
-}
-
-void no_adjust()
-{
- curenv->adjust_mode &= ~1;
- skip_line();
-}
-
-void do_input_trap(int continued)
-{
- curenv->input_trap_count = 0;
- if (continued)
- curenv->continued_input_trap = 1;
- int n;
- if (has_arg() && get_integer(&n)) {
- if (n <= 0)
- warning(WARN_RANGE,
- "number of lines for input trap must be greater than zero");
- else {
- symbol s = get_name(1);
- if (!s.is_null()) {
- curenv->input_trap_count = n;
- curenv->input_trap = s;
- }
- }
- }
- skip_line();
-}
-
-void input_trap()
-{
- do_input_trap(0);
-}
-
-void input_trap_continued()
-{
- do_input_trap(1);
-}
-
-/* tabs */
-
-// must not be R or C or L or a legitimate part of a number expression
-const char TAB_REPEAT_CHAR = 'T';
-
-struct tab {
- tab *next;
- hunits pos;
- tab_type type;
- tab(hunits, tab_type);
- enum { BLOCK = 1024 };
- static tab *free_list;
- void *operator new(size_t);
- void operator delete(void *);
-};
-
-tab *tab::free_list = 0;
-
-void *tab::operator new(size_t n)
-{
- assert(n == sizeof(tab));
- if (!free_list) {
- free_list = (tab *)new char[sizeof(tab)*BLOCK];
- for (int i = 0; i < BLOCK - 1; i++)
- free_list[i].next = free_list + i + 1;
- free_list[BLOCK-1].next = 0;
- }
- tab *p = free_list;
- free_list = (tab *)(free_list->next);
- p->next = 0;
- return p;
-}
-
-#ifdef __GNUG__
-/* cfront can't cope with this. */
-inline
-#endif
-void tab::operator delete(void *p)
-{
- if (p) {
- ((tab *)p)->next = free_list;
- free_list = (tab *)p;
- }
-}
-
-tab::tab(hunits x, tab_type t) : next(0), pos(x), type(t)
-{
-}
-
-tab_stops::tab_stops(hunits distance, tab_type type)
-: initial_list(0)
-{
- repeated_list = new tab(distance, type);
-}
-
-tab_stops::~tab_stops()
-{
- clear();
-}
-
-tab_type tab_stops::distance_to_next_tab(hunits curpos, hunits *distance)
-{
- hunits nextpos;
-
- return distance_to_next_tab(curpos, distance, &nextpos);
-}
-
-tab_type tab_stops::distance_to_next_tab(hunits curpos, hunits *distance,
- hunits *nextpos)
-{
- hunits lastpos = 0;
- tab *tem;
- for (tem = initial_list; tem && tem->pos <= curpos; tem = tem->next)
- lastpos = tem->pos;
- if (tem) {
- *distance = tem->pos - curpos;
- *nextpos = tem->pos;
- return tem->type;
- }
- if (repeated_list == 0)
- return TAB_NONE;
- hunits base = lastpos;
- for (;;) {
- for (tem = repeated_list; tem && tem->pos + base <= curpos; tem = tem->next)
- lastpos = tem->pos;
- if (tem) {
- *distance = tem->pos + base - curpos;
- *nextpos = tem->pos + base;
- return tem->type;
- }
- assert(lastpos > 0);
- base += lastpos;
- }
- return TAB_NONE;
-}
-
-const char *tab_stops::to_string()
-{
- static char *buf = 0;
- static int buf_size = 0;
- // figure out a maximum on the amount of space we can need
- int count = 0;
- tab *p;
- for (p = initial_list; p; p = p->next)
- ++count;
- for (p = repeated_list; p; p = p->next)
- ++count;
- // (10 for digits + 1 for u + 1 for 'C' or 'R') + 2 for ' &' + 1 for '\0'
- int need = count*12 + 3;
- if (buf == 0 || need > buf_size) {
- if (buf)
- a_delete buf;
- buf_size = need;
- buf = new char[buf_size];
- }
- char *ptr = buf;
- for (p = initial_list; p; p = p->next) {
- strcpy(ptr, i_to_a(p->pos.to_units()));
- ptr = strchr(ptr, '\0');
- *ptr++ = 'u';
- *ptr = '\0';
- switch (p->type) {
- case TAB_LEFT:
- break;
- case TAB_RIGHT:
- *ptr++ = 'R';
- break;
- case TAB_CENTER:
- *ptr++ = 'C';
- break;
- case TAB_NONE:
- default:
- assert(0);
- }
- }
- if (repeated_list)
- *ptr++ = TAB_REPEAT_CHAR;
- for (p = repeated_list; p; p = p->next) {
- strcpy(ptr, i_to_a(p->pos.to_units()));
- ptr = strchr(ptr, '\0');
- *ptr++ = 'u';
- *ptr = '\0';
- switch (p->type) {
- case TAB_LEFT:
- break;
- case TAB_RIGHT:
- *ptr++ = 'R';
- break;
- case TAB_CENTER:
- *ptr++ = 'C';
- break;
- case TAB_NONE:
- default:
- assert(0);
- }
- }
- *ptr++ = '\0';
- return buf;
-}
-
-tab_stops::tab_stops() : initial_list(0), repeated_list(0)
-{
-}
-
-tab_stops::tab_stops(const tab_stops &ts)
-: initial_list(0), repeated_list(0)
-{
- tab **p = &initial_list;
- tab *t = ts.initial_list;
- while (t) {
- *p = new tab(t->pos, t->type);
- t = t->next;
- p = &(*p)->next;
- }
- p = &repeated_list;
- t = ts.repeated_list;
- while (t) {
- *p = new tab(t->pos, t->type);
- t = t->next;
- p = &(*p)->next;
- }
-}
-
-void tab_stops::clear()
-{
- while (initial_list) {
- tab *tem = initial_list;
- initial_list = initial_list->next;
- delete tem;
- }
- while (repeated_list) {
- tab *tem = repeated_list;
- repeated_list = repeated_list->next;
- delete tem;
- }
-}
-
-void tab_stops::add_tab(hunits pos, tab_type type, int repeated)
-{
- tab **p;
- for (p = repeated ? &repeated_list : &initial_list; *p; p = &(*p)->next)
- ;
- *p = new tab(pos, type);
-}
-
-
-void tab_stops::operator=(const tab_stops &ts)
-{
- clear();
- tab **p = &initial_list;
- tab *t = ts.initial_list;
- while (t) {
- *p = new tab(t->pos, t->type);
- t = t->next;
- p = &(*p)->next;
- }
- p = &repeated_list;
- t = ts.repeated_list;
- while (t) {
- *p = new tab(t->pos, t->type);
- t = t->next;
- p = &(*p)->next;
- }
-}
-
-void set_tabs()
-{
- hunits pos;
- hunits prev_pos = 0;
- int first = 1;
- int repeated = 0;
- tab_stops tabs;
- while (has_arg()) {
- if (tok.ch() == TAB_REPEAT_CHAR) {
- tok.next();
- repeated = 1;
- prev_pos = 0;
- }
- if (!get_hunits(&pos, 'm', prev_pos))
- break;
- tab_type type = TAB_LEFT;
- if (tok.ch() == 'C') {
- tok.next();
- type = TAB_CENTER;
- }
- else if (tok.ch() == 'R') {
- tok.next();
- type = TAB_RIGHT;
- }
- else if (tok.ch() == 'L') {
- tok.next();
- }
- if (pos <= prev_pos && !first)
- warning(WARN_RANGE,
- "positions of tab stops must be strictly increasing");
- else {
- tabs.add_tab(pos, type, repeated);
- prev_pos = pos;
- first = 0;
- }
- }
- curenv->tabs = tabs;
- curenv->add_html_tag_tabs(1);
- skip_line();
-}
-
-const char *environment::get_tabs()
-{
- return tabs.to_string();
-}
-
-#if 0
-tab_stops saved_tabs;
-
-void tabs_save()
-{
- saved_tabs = curenv->tabs;
- skip_line();
-}
-
-void tabs_restore()
-{
- curenv->tabs = saved_tabs;
- skip_line();
-}
-#endif
-
-tab_type environment::distance_to_next_tab(hunits *distance)
-{
- return line_tabs
- ? curenv->tabs.distance_to_next_tab(get_text_length(), distance)
- : curenv->tabs.distance_to_next_tab(get_input_line_position(), distance);
-}
-
-tab_type environment::distance_to_next_tab(hunits *distance, hunits *leftpos)
-{
- return line_tabs
- ? curenv->tabs.distance_to_next_tab(get_text_length(), distance, leftpos)
- : curenv->tabs.distance_to_next_tab(get_input_line_position(), distance,
- leftpos);
-}
-
-void field_characters()
-{
- field_delimiter_char = get_optional_char();
- if (field_delimiter_char)
- padding_indicator_char = get_optional_char();
- else
- padding_indicator_char = 0;
- skip_line();
-}
-
-void line_tabs_request()
-{
- int n;
- if (has_arg() && get_integer(&n))
- curenv->line_tabs = n != 0;
- else
- curenv->line_tabs = 1;
- skip_line();
-}
-
-int environment::get_line_tabs()
-{
- return line_tabs;
-}
-
-void environment::wrap_up_tab()
-{
- if (!current_tab)
- return;
- if (line == 0)
- start_line();
- hunits tab_amount;
- switch (current_tab) {
- case TAB_RIGHT:
- tab_amount = tab_distance - tab_width;
- line = make_tab_node(tab_amount, line);
- break;
- case TAB_CENTER:
- tab_amount = tab_distance - tab_width/2;
- line = make_tab_node(tab_amount, line);
- break;
- case TAB_NONE:
- case TAB_LEFT:
- default:
- assert(0);
- }
- width_total += tab_amount;
- width_total += tab_width;
- if (current_field) {
- if (tab_precedes_field) {
- pre_field_width += tab_amount;
- tab_precedes_field = 0;
- }
- field_distance -= tab_amount;
- field_spaces += tab_field_spaces;
- }
- if (tab_contents != 0) {
- node *tem;
- for (tem = tab_contents; tem->next != 0; tem = tem->next)
- ;
- tem->next = line;
- line = tab_contents;
- }
- tab_field_spaces = 0;
- tab_contents = 0;
- tab_width = H0;
- tab_distance = H0;
- current_tab = TAB_NONE;
-}
-
-node *environment::make_tab_node(hunits d, node *next)
-{
- if (leader_node != 0 && d < 0) {
- error("motion generated by leader cannot be negative");
- delete leader_node;
- leader_node = 0;
- }
- if (!leader_node)
- return new hmotion_node(d, 1, 0, get_fill_color(), next);
- node *n = new hline_node(d, leader_node, next);
- leader_node = 0;
- return n;
-}
-
-void environment::handle_tab(int is_leader)
-{
- hunits d;
- hunits abs;
- if (current_tab)
- wrap_up_tab();
- charinfo *ci = is_leader ? leader_char : tab_char;
- delete leader_node;
- leader_node = ci ? make_char_node(ci) : 0;
- tab_type t = distance_to_next_tab(&d, &abs);
- switch (t) {
- case TAB_NONE:
- return;
- case TAB_LEFT:
- add_node(make_tab_node(d));
- add_node(make_html_tag("tab L", abs.to_units()));
- return;
- case TAB_RIGHT:
- add_node(make_html_tag("tab R", abs.to_units()));
- break;
- case TAB_CENTER:
- add_node(make_html_tag("tab C", abs.to_units()));
- break;
- default:
- assert(0);
- }
- tab_width = 0;
- tab_distance = d;
- tab_contents = 0;
- current_tab = t;
- tab_field_spaces = 0;
-}
-
-void environment::start_field()
-{
- assert(!current_field);
- hunits d;
- if (distance_to_next_tab(&d) != TAB_NONE) {
- pre_field_width = get_text_length();
- field_distance = d;
- current_field = 1;
- field_spaces = 0;
- tab_field_spaces = 0;
- for (node *p = line; p; p = p->next)
- if (p->nspaces()) {
- p->freeze_space();
- space_total--;
- }
- tab_precedes_field = current_tab != TAB_NONE;
- }
- else
- error("zero field width");
-}
-
-void environment::wrap_up_field()
-{
- if (!current_tab && field_spaces == 0)
- add_padding();
- hunits padding = field_distance - (get_text_length() - pre_field_width);
- if (current_tab && tab_field_spaces != 0) {
- hunits tab_padding = scale(padding,
- tab_field_spaces,
- field_spaces + tab_field_spaces);
- padding -= tab_padding;
- distribute_space(tab_contents, tab_field_spaces, tab_padding, 1);
- tab_field_spaces = 0;
- tab_width += tab_padding;
- }
- if (field_spaces != 0) {
- distribute_space(line, field_spaces, padding, 1);
- width_total += padding;
- if (current_tab) {
- // the start of the tab has been moved to the right by padding, so
- tab_distance -= padding;
- if (tab_distance <= H0) {
- // use the next tab stop instead
- current_tab = tabs.distance_to_next_tab(get_input_line_position()
- - tab_width,
- &tab_distance);
- if (current_tab == TAB_NONE || current_tab == TAB_LEFT) {
- width_total += tab_width;
- if (current_tab == TAB_LEFT) {
- line = make_tab_node(tab_distance, line);
- width_total += tab_distance;
- current_tab = TAB_NONE;
- }
- if (tab_contents != 0) {
- node *tem;
- for (tem = tab_contents; tem->next != 0; tem = tem->next)
- ;
- tem->next = line;
- line = tab_contents;
- tab_contents = 0;
- }
- tab_width = H0;
- tab_distance = H0;
- }
- }
- }
- }
- current_field = 0;
-}
-
-void environment::add_padding()
-{
- if (current_tab) {
- tab_contents = new space_node(H0, get_fill_color(), tab_contents);
- tab_field_spaces++;
- }
- else {
- if (line == 0)
- start_line();
- line = new space_node(H0, get_fill_color(), line);
- field_spaces++;
- }
-}
-
-typedef int (environment::*INT_FUNCP)();
-typedef vunits (environment::*VUNITS_FUNCP)();
-typedef hunits (environment::*HUNITS_FUNCP)();
-typedef const char *(environment::*STRING_FUNCP)();
-
-class int_env_reg : public reg {
- INT_FUNCP func;
- public:
- int_env_reg(INT_FUNCP);
- const char *get_string();
- int get_value(units *val);
-};
-
-class vunits_env_reg : public reg {
- VUNITS_FUNCP func;
- public:
- vunits_env_reg(VUNITS_FUNCP f);
- const char *get_string();
- int get_value(units *val);
-};
-
-
-class hunits_env_reg : public reg {
- HUNITS_FUNCP func;
- public:
- hunits_env_reg(HUNITS_FUNCP f);
- const char *get_string();
- int get_value(units *val);
-};
-
-class string_env_reg : public reg {
- STRING_FUNCP func;
-public:
- string_env_reg(STRING_FUNCP);
- const char *get_string();
-};
-
-int_env_reg::int_env_reg(INT_FUNCP f) : func(f)
-{
-}
-
-int int_env_reg::get_value(units *val)
-{
- *val = (curenv->*func)();
- return 1;
-}
-
-const char *int_env_reg::get_string()
-{
- return i_to_a((curenv->*func)());
-}
-
-vunits_env_reg::vunits_env_reg(VUNITS_FUNCP f) : func(f)
-{
-}
-
-int vunits_env_reg::get_value(units *val)
-{
- *val = (curenv->*func)().to_units();
- return 1;
-}
-
-const char *vunits_env_reg::get_string()
-{
- return i_to_a((curenv->*func)().to_units());
-}
-
-hunits_env_reg::hunits_env_reg(HUNITS_FUNCP f) : func(f)
-{
-}
-
-int hunits_env_reg::get_value(units *val)
-{
- *val = (curenv->*func)().to_units();
- return 1;
-}
-
-const char *hunits_env_reg::get_string()
-{
- return i_to_a((curenv->*func)().to_units());
-}
-
-string_env_reg::string_env_reg(STRING_FUNCP f) : func(f)
-{
-}
-
-const char *string_env_reg::get_string()
-{
- return (curenv->*func)();
-}
-
-class horizontal_place_reg : public general_reg {
-public:
- horizontal_place_reg();
- int get_value(units *);
- void set_value(units);
-};
-
-horizontal_place_reg::horizontal_place_reg()
-{
-}
-
-int horizontal_place_reg::get_value(units *res)
-{
- *res = curenv->get_input_line_position().to_units();
- return 1;
-}
-
-void horizontal_place_reg::set_value(units n)
-{
- curenv->set_input_line_position(hunits(n));
-}
-
-const char *environment::get_font_family_string()
-{
- return family->nm.contents();
-}
-
-const char *environment::get_font_name_string()
-{
- symbol f = get_font_name(fontno, this);
- return f.contents();
-}
-
-const char *environment::get_name_string()
-{
- return name.contents();
-}
-
-// Convert a quantity in scaled points to ascii decimal fraction.
-
-const char *sptoa(int sp)
-{
- assert(sp > 0);
- assert(sizescale > 0);
- if (sizescale == 1)
- return i_to_a(sp);
- if (sp % sizescale == 0)
- return i_to_a(sp/sizescale);
- // See if 1/sizescale is exactly representable as a decimal fraction,
- // ie its only prime factors are 2 and 5.
- int n = sizescale;
- int power2 = 0;
- while ((n & 1) == 0) {
- n >>= 1;
- power2++;
- }
- int power5 = 0;
- while ((n % 5) == 0) {
- n /= 5;
- power5++;
- }
- if (n == 1) {
- int decimal_point = power5 > power2 ? power5 : power2;
- if (decimal_point <= 10) {
- int factor = 1;
- int t;
- for (t = decimal_point - power2; --t >= 0;)
- factor *= 2;
- for (t = decimal_point - power5; --t >= 0;)
- factor *= 5;
- if (factor == 1 || sp <= INT_MAX/factor)
- return if_to_a(sp*factor, decimal_point);
- }
- }
- double s = double(sp)/double(sizescale);
- double factor = 10.0;
- double val = s;
- int decimal_point = 0;
- do {
- double v = ceil(s*factor);
- if (v > INT_MAX)
- break;
- val = v;
- factor *= 10.0;
- } while (++decimal_point < 10);
- return if_to_a(int(val), decimal_point);
-}
-
-const char *environment::get_point_size_string()
-{
- return sptoa(curenv->get_point_size());
-}
-
-const char *environment::get_requested_point_size_string()
-{
- return sptoa(curenv->get_requested_point_size());
-}
-
-#define init_int_env_reg(name, func) \
- number_reg_dictionary.define(name, new int_env_reg(&environment::func))
-
-#define init_vunits_env_reg(name, func) \
- number_reg_dictionary.define(name, new vunits_env_reg(&environment::func))
-
-#define init_hunits_env_reg(name, func) \
- number_reg_dictionary.define(name, new hunits_env_reg(&environment::func))
-
-#define init_string_env_reg(name, func) \
- number_reg_dictionary.define(name, new string_env_reg(&environment::func))
-
-void init_env_requests()
-{
- init_request("it", input_trap);
- init_request("itc", input_trap_continued);
- init_request("ad", adjust);
- init_request("na", no_adjust);
- init_request("ev", environment_switch);
- init_request("evc", environment_copy);
- init_request("lt", title_length);
- init_request("ps", point_size);
- init_request("sizes", override_sizes);
- init_request("ft", font_change);
- init_request("fam", family_change);
- init_request("ss", space_size);
- init_request("fi", fill);
- init_request("nf", no_fill);
- init_request("ce", center);
- init_request("rj", right_justify);
- init_request("vs", vertical_spacing);
- init_request("ls", line_spacing);
- init_request("ll", line_length);
- init_request("in", indent);
- init_request("ti", temporary_indent);
- init_request("ul", underline);
- init_request("cu", continuous_underline);
- init_request("cc", control_char);
- init_request("c2", no_break_control_char);
- init_request("br", break_request);
- init_request("brp", break_spread_request);
- init_request("tl", title);
- init_request("ta", set_tabs);
- init_request("linetabs", line_tabs_request);
- init_request("fc", field_characters);
- init_request("mc", margin_character);
- init_request("nn", no_number);
- init_request("nm", number_lines);
- init_request("tc", tab_character);
- init_request("lc", leader_character);
- init_request("hy", hyphenate_request);
- init_request("hc", hyphen_char);
- init_request("nh", no_hyphenate);
- init_request("hlm", hyphen_line_max_request);
-#ifdef WIDOW_CONTROL
- init_request("wdc", widow_control_request);
-#endif /* WIDOW_CONTROL */
-#if 0
- init_request("tas", tabs_save);
- init_request("tar", tabs_restore);
-#endif
- init_request("hys", hyphenation_space_request);
- init_request("hym", hyphenation_margin_request);
- init_request("pvs", post_vertical_spacing);
- init_int_env_reg(".f", get_font);
- init_int_env_reg(".b", get_bold);
- init_hunits_env_reg(".i", get_indent);
- init_hunits_env_reg(".in", get_saved_indent);
- init_int_env_reg(".int", get_prev_line_interrupted);
- init_int_env_reg(".j", get_adjust_mode);
- init_hunits_env_reg(".k", get_text_length);
- init_hunits_env_reg(".l", get_line_length);
- init_hunits_env_reg(".ll", get_saved_line_length);
- init_int_env_reg(".L", get_line_spacing);
- init_hunits_env_reg(".n", get_prev_text_length);
- init_string_env_reg(".s", get_point_size_string);
- init_string_env_reg(".sr", get_requested_point_size_string);
- init_int_env_reg(".ps", get_point_size);
- init_int_env_reg(".psr", get_requested_point_size);
- init_int_env_reg(".u", get_fill);
- init_vunits_env_reg(".v", get_vertical_spacing);
- init_vunits_env_reg(".pvs", get_post_vertical_spacing);
- init_hunits_env_reg(".w", get_prev_char_width);
- init_int_env_reg(".ss", get_space_size);
- init_int_env_reg(".sss", get_sentence_space_size);
- init_string_env_reg(".fam", get_font_family_string);
- init_string_env_reg(".fn", get_font_name_string);
- init_string_env_reg(".ev", get_name_string);
- init_int_env_reg(".hy", get_hyphenation_flags);
- init_int_env_reg(".hlm", get_hyphen_line_max);
- init_int_env_reg(".hlc", get_hyphen_line_count);
- init_hunits_env_reg(".lt", get_title_length);
- init_string_env_reg(".tabs", get_tabs);
- init_int_env_reg(".linetabs", get_line_tabs);
- init_hunits_env_reg(".csk", get_prev_char_skew);
- init_vunits_env_reg(".cht", get_prev_char_height);
- init_vunits_env_reg(".cdp", get_prev_char_depth);
- init_int_env_reg(".ce", get_center_lines);
- init_int_env_reg(".rj", get_right_justify_lines);
- init_hunits_env_reg(".hys", get_hyphenation_space);
- init_hunits_env_reg(".hym", get_hyphenation_margin);
- number_reg_dictionary.define("ln", new variable_reg(&next_line_number));
- number_reg_dictionary.define("ct", new variable_reg(&ct_reg_contents));
- number_reg_dictionary.define("sb", new variable_reg(&sb_reg_contents));
- number_reg_dictionary.define("st", new variable_reg(&st_reg_contents));
- number_reg_dictionary.define("rsb", new variable_reg(&rsb_reg_contents));
- number_reg_dictionary.define("rst", new variable_reg(&rst_reg_contents));
- number_reg_dictionary.define("ssc", new variable_reg(&ssc_reg_contents));
- number_reg_dictionary.define("skw", new variable_reg(&skw_reg_contents));
- number_reg_dictionary.define("hp", new horizontal_place_reg);
-}
-
-// Hyphenation - TeX's hyphenation algorithm with a less fancy implementation.
-
-struct trie_node;
-
-class trie {
- trie_node *tp;
- virtual void do_match(int len, void *val) = 0;
- virtual void do_delete(void *) = 0;
- void delete_trie_node(trie_node *);
-public:
- trie() : tp(0) {}
- virtual ~trie(); // virtual to shut up g++
- void insert(const char *, int, void *);
- // find calls do_match for each match it finds
- void find(const char *pat, int patlen);
- void clear();
-};
-
-class hyphen_trie : private trie {
- int *h;
- void do_match(int i, void *v);
- void do_delete(void *v);
- void insert_pattern(const char *pat, int patlen, int *num);
- void insert_hyphenation(dictionary ex, const char *pat, int patlen);
- int hpf_getc(FILE *f);
-public:
- hyphen_trie() {}
- ~hyphen_trie() {}
- void hyphenate(const char *word, int len, int *hyphens);
- void read_patterns_file(const char *name, int append, dictionary ex);
-};
-
-struct hyphenation_language {
- symbol name;
- dictionary exceptions;
- hyphen_trie patterns;
- hyphenation_language(symbol nm) : name(nm), exceptions(501) {}
- ~hyphenation_language() { }
-};
-
-dictionary language_dictionary(5);
-hyphenation_language *current_language = 0;
-
-static void set_hyphenation_language()
-{
- symbol nm = get_name(1);
- if (!nm.is_null()) {
- current_language = (hyphenation_language *)language_dictionary.lookup(nm);
- if (!current_language) {
- current_language = new hyphenation_language(nm);
- (void)language_dictionary.lookup(nm, (void *)current_language);
- }
- }
- skip_line();
-}
-
-const int WORD_MAX = 256; // we use unsigned char for offsets in
- // hyphenation exceptions
-
-static void hyphen_word()
-{
- if (!current_language) {
- error("no current hyphenation language");
- skip_line();
- return;
- }
- char buf[WORD_MAX + 1];
- unsigned char pos[WORD_MAX + 2];
- for (;;) {
- tok.skip();
- if (tok.newline() || tok.eof())
- break;
- int i = 0;
- int npos = 0;
- while (i < WORD_MAX && !tok.space() && !tok.newline() && !tok.eof()) {
- charinfo *ci = tok.get_char(1);
- if (ci == 0) {
- skip_line();
- return;
- }
- tok.next();
- if (ci->get_ascii_code() == '-') {
- if (i > 0 && (npos == 0 || pos[npos - 1] != i))
- pos[npos++] = i;
- }
- else {
- int c = ci->get_hyphenation_code();
- if (c == 0)
- break;
- buf[i++] = c;
- }
- }
- if (i > 0) {
- pos[npos] = 0;
- buf[i] = 0;
- unsigned char *tem = new unsigned char[npos + 1];
- memcpy(tem, pos, npos + 1);
- tem = (unsigned char *)current_language->exceptions.lookup(symbol(buf),
- tem);
- if (tem)
- a_delete tem;
- }
- }
- skip_line();
-}
-
-struct trie_node {
- char c;
- trie_node *down;
- trie_node *right;
- void *val;
- trie_node(char, trie_node *);
-};
-
-trie_node::trie_node(char ch, trie_node *p)
-: c(ch), down(0), right(p), val(0)
-{
-}
-
-trie::~trie()
-{
- clear();
-}
-
-void trie::clear()
-{
- delete_trie_node(tp);
- tp = 0;
-}
-
-
-void trie::delete_trie_node(trie_node *p)
-{
- if (p) {
- delete_trie_node(p->down);
- delete_trie_node(p->right);
- if (p->val)
- do_delete(p->val);
- delete p;
- }
-}
-
-void trie::insert(const char *pat, int patlen, void *val)
-{
- trie_node **p = &tp;
- assert(patlen > 0 && pat != 0);
- for (;;) {
- while (*p != 0 && (*p)->c < pat[0])
- p = &((*p)->right);
- if (*p == 0 || (*p)->c != pat[0])
- *p = new trie_node(pat[0], *p);
- if (--patlen == 0) {
- (*p)->val = val;
- break;
- }
- ++pat;
- p = &((*p)->down);
- }
-}
-
-void trie::find(const char *pat, int patlen)
-{
- trie_node *p = tp;
- for (int i = 0; p != 0 && i < patlen; i++) {
- while (p != 0 && p->c < pat[i])
- p = p->right;
- if (p != 0 && p->c == pat[i]) {
- if (p->val != 0)
- do_match(i+1, p->val);
- p = p->down;
- }
- else
- break;
- }
-}
-
-struct operation {
- operation *next;
- short distance;
- short num;
- operation(int, int, operation *);
-};
-
-operation::operation(int i, int j, operation *op)
-: next(op), distance(j), num(i)
-{
-}
-
-void hyphen_trie::insert_pattern(const char *pat, int patlen, int *num)
-{
- operation *op = 0;
- for (int i = 0; i < patlen+1; i++)
- if (num[i] != 0)
- op = new operation(num[i], patlen - i, op);
- insert(pat, patlen, op);
-}
-
-void hyphen_trie::insert_hyphenation(dictionary ex, const char *pat,
- int patlen)
-{
- char buf[WORD_MAX + 1];
- unsigned char pos[WORD_MAX + 2];
- int i = 0, j = 0;
- int npos = 0;
- while (j < patlen) {
- unsigned char c = pat[j++];
- if (c == '-') {
- if (i > 0 && (npos == 0 || pos[npos - 1] != i))
- pos[npos++] = i;
- }
- else
- buf[i++] = hpf_code_table[c];
- }
- if (i > 0) {
- pos[npos] = 0;
- buf[i] = 0;
- unsigned char *tem = new unsigned char[npos + 1];
- memcpy(tem, pos, npos + 1);
- tem = (unsigned char *)ex.lookup(symbol(buf), tem);
- if (tem)
- a_delete tem;
- }
-}
-
-void hyphen_trie::hyphenate(const char *word, int len, int *hyphens)
-{
- int j;
- for (j = 0; j < len + 1; j++)
- hyphens[j] = 0;
- for (j = 0; j < len - 1; j++) {
- h = hyphens + j;
- find(word + j, len - j);
- }
-}
-
-inline int max(int m, int n)
-{
- return m > n ? m : n;
-}
-
-void hyphen_trie::do_match(int i, void *v)
-{
- operation *op = (operation *)v;
- while (op != 0) {
- h[i - op->distance] = max(h[i - op->distance], op->num);
- op = op->next;
- }
-}
-
-void hyphen_trie::do_delete(void *v)
-{
- operation *op = (operation *)v;
- while (op) {
- operation *tem = op;
- op = tem->next;
- delete tem;
- }
-}
-
-/* We use very simple rules to parse TeX's hyphenation patterns.
-
- . `%' starts a comment even if preceded by `\'.
-
- . No support for digraphs and like `\$'.
-
- . `^^xx' (`x' is 0-9 or a-f), and `^^x' (character code of `x' in the
- range 0-127) are recognized; other use of `^' causes an error.
-
- . No macro expansion.
-
- . We check for the expression `\patterns{...}' (possibly with
- whitespace before and after the braces). Everything between the
- braces is taken as hyphenation patterns. Consequently, `{' and `}'
- are not allowed in patterns.
-
- . Similarly, `\hyphenation{...}' gives a list of hyphenation
- exceptions.
-
- . `\endinput' is recognized also.
-
- . For backwards compatibility, if `\patterns' is missing, the
- whole file is treated as a list of hyphenation patterns (only
- recognizing `%' as the start of a comment.
-
-*/
-
-int hyphen_trie::hpf_getc(FILE *f)
-{
- int c = getc(f);
- int c1;
- int cc = 0;
- if (c != '^')
- return c;
- c = getc(f);
- if (c != '^')
- goto fail;
- c = getc(f);
- c1 = getc(f);
- if (((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'))
- && ((c1 >= '0' && c1 <= '9') || (c1 >= 'a' && c1 <= 'f'))) {
- if (c >= '0' && c <= '9')
- c -= '0';
- else
- c = c - 'a' + 10;
- if (c1 >= '0' && c1 <= '9')
- c1 -= '0';
- else
- c1 = c1 - 'a' + 10;
- cc = c * 16 + c1;
- }
- else {
- ungetc(c1, f);
- if (c >= 0 && c <= 63)
- cc = c + 64;
- else if (c >= 64 && c <= 127)
- cc = c - 64;
- else
- goto fail;
- }
- return cc;
-fail:
- error("invalid ^, ^^x, or ^^xx character in hyphenation patterns file");
- return c;
-}
-
-void hyphen_trie::read_patterns_file(const char *name, int append,
- dictionary ex)
-{
- if (!append)
- clear();
- char buf[WORD_MAX];
- int num[WORD_MAX+1];
- errno = 0;
- char *path = 0;
- FILE *fp = mac_path->open_file(name, &path);
- if (fp == 0) {
- error("can't find hyphenation patterns file `%1'", name);
- return;
- }
- int c = hpf_getc(fp);
- int have_patterns = 0; // we've seen \patterns
- int final_pattern = 0; // 1 if we have a trailing closing brace
- int have_hyphenation = 0; // we've seen \hyphenation
- int final_hyphenation = 0; // 1 if we have a trailing closing brace
- int have_keyword = 0; // we've seen either \patterns or \hyphenation
- int traditional = 0; // don't handle \patterns
- for (;;) {
- for (;;) {
- if (c == '%') { // skip comments
- do {
- c = getc(fp);
- } while (c != EOF && c != '\n');
- }
- if (c == EOF || !csspace(c))
- break;
- c = hpf_getc(fp);
- }
- if (c == EOF) {
- if (have_keyword || traditional) // we are done
- break;
- else { // rescan file in `traditional' mode
- rewind(fp);
- traditional = 1;
- c = hpf_getc(fp);
- continue;
- }
- }
- int i = 0;
- num[0] = 0;
- if (!(c == '{' || c == '}')) { // skip braces at line start
- do { // scan patterns
- if (csdigit(c))
- num[i] = c - '0';
- else {
- buf[i++] = c;
- num[i] = 0;
- }
- c = hpf_getc(fp);
- } while (i < WORD_MAX && c != EOF && !csspace(c)
- && c != '%' && c != '{' && c != '}');
- }
- if (!traditional) {
- if (i >= 9 && !strncmp(buf + i - 9, "\\patterns", 9)) {
- while (csspace(c))
- c = hpf_getc(fp);
- if (c == '{') {
- if (have_patterns || have_hyphenation)
- error("`{' not allowed inside of \\patterns or \\hyphenation");
- else {
- have_patterns = 1;
- have_keyword = 1;
- }
- c = hpf_getc(fp);
- continue;
- }
- }
- else if (i >= 12 && !strncmp(buf + i - 12, "\\hyphenation", 12)) {
- while (csspace(c))
- c = hpf_getc(fp);
- if (c == '{') {
- if (have_patterns || have_hyphenation)
- error("`{' not allowed inside of \\patterns or \\hyphenation");
- else {
- have_hyphenation = 1;
- have_keyword = 1;
- }
- c = hpf_getc(fp);
- continue;
- }
- }
- else if (strstr(buf, "\\endinput")) {
- if (have_patterns || have_hyphenation)
- error("found \\endinput inside of %1 group",
- have_patterns ? "\\patterns" : "\\hyphenation");
- break;
- }
- else if (c == '}') {
- if (have_patterns) {
- have_patterns = 0;
- if (i > 0)
- final_pattern = 1;
- }
- else if (have_hyphenation) {
- have_hyphenation = 0;
- if (i > 0)
- final_hyphenation = 1;
- }
- c = hpf_getc(fp);
- }
- else if (c == '{') // skipped if not starting \patterns
- c = hpf_getc(fp); // or \hyphenation
- }
- if (i > 0) {
- if (have_patterns || final_pattern || traditional) {
- for (int j = 0; j < i; j++)
- buf[j] = hpf_code_table[(unsigned char)buf[j]];
- insert_pattern(buf, i, num);
- final_pattern = 0;
- }
- else if (have_hyphenation || final_hyphenation) {
- insert_hyphenation(ex, buf, i);
- final_hyphenation = 0;
- }
- }
- }
- fclose(fp);
- a_delete path;
- return;
-}
-
-void hyphenate(hyphen_list *h, unsigned flags)
-{
- if (!current_language)
- return;
- while (h) {
- while (h && h->hyphenation_code == 0)
- h = h->next;
- int len = 0;
- char hbuf[WORD_MAX+2];
- char *buf = hbuf + 1;
- hyphen_list *tem;
- for (tem = h; tem && len < WORD_MAX; tem = tem->next) {
- if (tem->hyphenation_code != 0)
- buf[len++] = tem->hyphenation_code;
- else
- break;
- }
- hyphen_list *nexth = tem;
- if (len > 2) {
- buf[len] = 0;
- unsigned char *pos
- = (unsigned char *)current_language->exceptions.lookup(buf);
- if (pos != 0) {
- int j = 0;
- int i = 1;
- for (tem = h; tem != 0; tem = tem->next, i++)
- if (pos[j] == i) {
- tem->hyphen = 1;
- j++;
- }
- }
- else {
- hbuf[0] = hbuf[len+1] = '.';
- int num[WORD_MAX+3];
- current_language->patterns.hyphenate(hbuf, len+2, num);
- int i;
- num[2] = 0;
- if (flags & 8)
- num[3] = 0;
- if (flags & 4)
- --len;
- for (i = 2, tem = h; i < len && tem; tem = tem->next, i++)
- if (num[i] & 1)
- tem->hyphen = 1;
- }
- }
- h = nexth;
- }
-}
-
-static void do_hyphenation_patterns_file(int append)
-{
- symbol name = get_long_name(1);
- if (!name.is_null()) {
- if (!current_language)
- error("no current hyphenation language");
- else
- current_language->patterns.read_patterns_file(
- name.contents(), append,
- current_language->exceptions);
- }
- skip_line();
-}
-
-static void hyphenation_patterns_file()
-{
- do_hyphenation_patterns_file(0);
-}
-
-static void hyphenation_patterns_file_append()
-{
- do_hyphenation_patterns_file(1);
-}
-
-class hyphenation_language_reg : public reg {
-public:
- const char *get_string();
-};
-
-const char *hyphenation_language_reg::get_string()
-{
- return current_language ? current_language->name.contents() : "";
-}
-
-void init_hyphen_requests()
-{
- init_request("hw", hyphen_word);
- init_request("hla", set_hyphenation_language);
- init_request("hpf", hyphenation_patterns_file);
- init_request("hpfa", hyphenation_patterns_file_append);
- number_reg_dictionary.define(".hla", new hyphenation_language_reg);
-}
diff --git a/contrib/groff/src/roff/troff/input.cc b/contrib/groff/src/roff/troff/input.cc
deleted file mode 100644
index 7a90e4b..0000000
--- a/contrib/groff/src/roff/troff/input.cc
+++ /dev/null
@@ -1,7665 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "troff.h"
-#include "symbol.h"
-#include "dictionary.h"
-#include "hvunits.h"
-#include "env.h"
-#include "request.h"
-#include "node.h"
-#include "reg.h"
-#include "token.h"
-#include "div.h"
-#include "charinfo.h"
-#include "stringclass.h"
-#include "font.h"
-#include "macropath.h"
-#include "defs.h"
-#include "input.h"
-
-// Needed for getpid() and isatty()
-#include "posix.h"
-
-#include "nonposix.h"
-
-#ifdef NEED_DECLARATION_PUTENV
-extern "C" {
- int putenv(const char *);
-}
-#endif /* NEED_DECLARATION_PUTENV */
-
-#define MACRO_PREFIX "tmac."
-#define MACRO_POSTFIX ".tmac"
-#define INITIAL_STARTUP_FILE "troffrc"
-#define FINAL_STARTUP_FILE "troffrc-end"
-#define DEFAULT_INPUT_STACK_LIMIT 1000
-
-#ifndef DEFAULT_WARNING_MASK
-// warnings that are enabled by default
-#define DEFAULT_WARNING_MASK \
- (WARN_CHAR|WARN_NUMBER|WARN_BREAK|WARN_SPACE|WARN_FONT)
-#endif
-
-// initial size of buffer for reading names; expanded as necessary
-#define ABUF_SIZE 16
-
-extern "C" const char *Version_string;
-
-#ifdef COLUMN
-void init_column_requests();
-#endif /* COLUMN */
-
-static node *read_draw_node();
-void handle_first_page_transition();
-static void push_token(const token &);
-void copy_file();
-#ifdef COLUMN
-void vjustify();
-#endif /* COLUMN */
-void transparent_file();
-void process_input_stack();
-
-const char *program_name = 0;
-token tok;
-int break_flag = 0;
-int color_flag = 1; // colors are on by default
-static int backtrace_flag = 0;
-#ifndef POPEN_MISSING
-char *pipe_command = 0;
-#endif
-charinfo *charset_table[256];
-unsigned char hpf_code_table[256];
-
-static int warning_mask = DEFAULT_WARNING_MASK;
-static int inhibit_errors = 0;
-static int ignoring = 0;
-
-static void enable_warning(const char *);
-static void disable_warning(const char *);
-
-static int escape_char = '\\';
-static symbol end_macro_name;
-static symbol blank_line_macro_name;
-static int compatible_flag = 0;
-int ascii_output_flag = 0;
-int suppress_output_flag = 0;
-int is_html = 0;
-int begin_level = 0; // number of nested .begin requests
-
-int have_input = 0; // whether \f, \H, \R, \s, or \S has
- // been processed in token::next()
-int tcommand_flag = 0;
-int safer_flag = 1; // safer by default
-
-int have_string_arg = 0; // whether we have \*[foo bar...]
-
-double spread_limit = -3.0 - 1.0; // negative means deactivated
-
-double warn_scale;
-char warn_scaling_indicator;
-
-search_path *mac_path = &safer_macro_path;
-
-static int get_copy(node**, int = 0);
-static void copy_mode_error(const char *,
- const errarg & = empty_errarg,
- const errarg & = empty_errarg,
- const errarg & = empty_errarg);
-
-enum read_mode { ALLOW_EMPTY, WITH_ARGS, NO_ARGS };
-static symbol read_escape_name(read_mode mode = NO_ARGS);
-static symbol read_long_escape_name(read_mode mode = NO_ARGS);
-static void interpolate_string(symbol);
-static void interpolate_string_with_args(symbol);
-static void interpolate_macro(symbol);
-static void interpolate_number_format(symbol);
-static void interpolate_environment_variable(symbol);
-
-static void interpolate_arg(symbol);
-static request_or_macro *lookup_request(symbol);
-static int get_delim_number(units *, int);
-static int get_delim_number(units *, int, units);
-static int get_line_arg(units *res, int si, charinfo **cp);
-static int read_size(int *);
-static symbol get_delim_name();
-static void init_registers();
-static void trapping_blank_line();
-
-struct input_iterator;
-input_iterator *make_temp_iterator(const char *);
-const char *input_char_description(int);
-
-
-void set_escape_char()
-{
- if (has_arg()) {
- if (tok.ch() == 0) {
- error("bad escape character");
- escape_char = '\\';
- }
- else
- escape_char = tok.ch();
- }
- else
- escape_char = '\\';
- skip_line();
-}
-
-void escape_off()
-{
- escape_char = 0;
- skip_line();
-}
-
-static int saved_escape_char = '\\';
-
-void save_escape_char()
-{
- saved_escape_char = escape_char;
- skip_line();
-}
-
-void restore_escape_char()
-{
- escape_char = saved_escape_char;
- skip_line();
-}
-
-class input_iterator {
-public:
- input_iterator();
- virtual ~input_iterator() {}
- int get(node **);
- friend class input_stack;
-protected:
- const unsigned char *ptr;
- const unsigned char *eptr;
- input_iterator *next;
-private:
- virtual int fill(node **);
- virtual int peek();
- virtual int has_args() { return 0; }
- virtual int nargs() { return 0; }
- virtual input_iterator *get_arg(int) { return 0; }
- virtual int get_location(int, const char **, int *) { return 0; }
- virtual void backtrace() {}
- virtual int set_location(const char *, int) { return 0; }
- virtual int next_file(FILE *, const char *) { return 0; }
- virtual void shift(int) {}
- virtual int is_boundary() {return 0; }
- virtual int internal_level() { return 0; }
- virtual int is_file() { return 0; }
- virtual int is_macro() { return 0; }
- virtual void save_compatible_flag(int) {}
- virtual int get_compatible_flag() { return 0; }
-};
-
-input_iterator::input_iterator()
-: ptr(0), eptr(0)
-{
-}
-
-int input_iterator::fill(node **)
-{
- return EOF;
-}
-
-int input_iterator::peek()
-{
- return EOF;
-}
-
-inline int input_iterator::get(node **p)
-{
- return ptr < eptr ? *ptr++ : fill(p);
-}
-
-class input_boundary : public input_iterator {
-public:
- int is_boundary() { return 1; }
-};
-
-class input_return_boundary : public input_iterator {
-public:
- int is_boundary() { return 2; }
-};
-
-class file_iterator : public input_iterator {
- FILE *fp;
- int lineno;
- const char *filename;
- int popened;
- int newline_flag;
- int seen_escape;
- enum { BUF_SIZE = 512 };
- unsigned char buf[BUF_SIZE];
- void close();
-public:
- file_iterator(FILE *, const char *, int = 0);
- ~file_iterator();
- int fill(node **);
- int peek();
- int get_location(int, const char **, int *);
- void backtrace();
- int set_location(const char *, int);
- int next_file(FILE *, const char *);
- int is_file();
-};
-
-file_iterator::file_iterator(FILE *f, const char *fn, int po)
-: fp(f), lineno(1), filename(fn), popened(po),
- newline_flag(0), seen_escape(0)
-{
- if ((font::use_charnames_in_special) && (fn != 0)) {
- if (!the_output)
- init_output();
- the_output->put_filename(fn);
- }
-}
-
-file_iterator::~file_iterator()
-{
- close();
-}
-
-void file_iterator::close()
-{
- if (fp == stdin)
- clearerr(stdin);
-#ifndef POPEN_MISSING
- else if (popened)
- pclose(fp);
-#endif /* not POPEN_MISSING */
- else
- fclose(fp);
-}
-
-int file_iterator::is_file()
-{
- return 1;
-}
-
-int file_iterator::next_file(FILE *f, const char *s)
-{
- close();
- filename = s;
- fp = f;
- lineno = 1;
- newline_flag = 0;
- seen_escape = 0;
- popened = 0;
- ptr = 0;
- eptr = 0;
- return 1;
-}
-
-int file_iterator::fill(node **)
-{
- if (newline_flag)
- lineno++;
- newline_flag = 0;
- unsigned char *p = buf;
- ptr = p;
- unsigned char *e = p + BUF_SIZE;
- while (p < e) {
- int c = getc(fp);
- if (c == EOF)
- break;
- if (invalid_input_char(c))
- warning(WARN_INPUT, "invalid input character code %1", int(c));
- else {
- *p++ = c;
- if (c == '\n') {
- seen_escape = 0;
- newline_flag = 1;
- break;
- }
- seen_escape = (c == '\\');
- }
- }
- if (p > buf) {
- eptr = p;
- return *ptr++;
- }
- else {
- eptr = p;
- return EOF;
- }
-}
-
-int file_iterator::peek()
-{
- int c = getc(fp);
- while (invalid_input_char(c)) {
- warning(WARN_INPUT, "invalid input character code %1", int(c));
- c = getc(fp);
- }
- if (c != EOF)
- ungetc(c, fp);
- return c;
-}
-
-int file_iterator::get_location(int /*allow_macro*/,
- const char **filenamep, int *linenop)
-{
- *linenop = lineno;
- if (filename != 0 && strcmp(filename, "-") == 0)
- *filenamep = "";
- else
- *filenamep = filename;
- return 1;
-}
-
-void file_iterator::backtrace()
-{
- errprint("%1:%2: backtrace: %3 `%1'\n", filename, lineno,
- popened ? "process" : "file");
-}
-
-int file_iterator::set_location(const char *f, int ln)
-{
- if (f) {
- filename = f;
- if (!the_output)
- init_output();
- the_output->put_filename(f);
- }
- lineno = ln;
- return 1;
-}
-
-input_iterator nil_iterator;
-
-class input_stack {
-public:
- static int get(node **);
- static int peek();
- static void push(input_iterator *);
- static input_iterator *get_arg(int);
- static int nargs();
- static int get_location(int, const char **, int *);
- static int set_location(const char *, int);
- static void backtrace();
- static void backtrace_all();
- static void next_file(FILE *, const char *);
- static void end_file();
- static void shift(int n);
- static void add_boundary();
- static void add_return_boundary();
- static int is_return_boundary();
- static void remove_boundary();
- static int get_level();
- static void clear();
- static void pop_macro();
- static void save_compatible_flag(int);
- static int get_compatible_flag();
-
- static int limit;
-private:
- static input_iterator *top;
- static int level;
-
- static int finish_get(node **);
- static int finish_peek();
-};
-
-input_iterator *input_stack::top = &nil_iterator;
-int input_stack::level = 0;
-int input_stack::limit = DEFAULT_INPUT_STACK_LIMIT;
-
-inline int input_stack::get_level()
-{
- return level + top->internal_level();
-}
-
-inline int input_stack::get(node **np)
-{
- return (top->ptr < top->eptr) ? *top->ptr++ : finish_get(np);
-}
-
-int input_stack::finish_get(node **np)
-{
- for (;;) {
- int c = top->fill(np);
- if (c != EOF || top->is_boundary())
- return c;
- if (top == &nil_iterator)
- break;
- input_iterator *tem = top;
- top = top->next;
- level--;
- delete tem;
- if (top->ptr < top->eptr)
- return *top->ptr++;
- }
- assert(level == 0);
- return EOF;
-}
-
-inline int input_stack::peek()
-{
- return (top->ptr < top->eptr) ? *top->ptr : finish_peek();
-}
-
-int input_stack::finish_peek()
-{
- for (;;) {
- int c = top->peek();
- if (c != EOF || top->is_boundary())
- return c;
- if (top == &nil_iterator)
- break;
- input_iterator *tem = top;
- top = top->next;
- level--;
- delete tem;
- if (top->ptr < top->eptr)
- return *top->ptr;
- }
- assert(level == 0);
- return EOF;
-}
-
-void input_stack::add_boundary()
-{
- push(new input_boundary);
-}
-
-void input_stack::add_return_boundary()
-{
- push(new input_return_boundary);
-}
-
-int input_stack::is_return_boundary()
-{
- return top->is_boundary() == 2;
-}
-
-void input_stack::remove_boundary()
-{
- assert(top->is_boundary());
- input_iterator *temp = top->next;
- delete top;
- top = temp;
- level--;
-}
-
-void input_stack::push(input_iterator *in)
-{
- if (in == 0)
- return;
- if (++level > limit && limit > 0)
- fatal("input stack limit exceeded (probable infinite loop)");
- in->next = top;
- top = in;
-}
-
-input_iterator *input_stack::get_arg(int i)
-{
- input_iterator *p;
- for (p = top; p != 0; p = p->next)
- if (p->has_args())
- return p->get_arg(i);
- return 0;
-}
-
-void input_stack::shift(int n)
-{
- for (input_iterator *p = top; p; p = p->next)
- if (p->has_args()) {
- p->shift(n);
- return;
- }
-}
-
-int input_stack::nargs()
-{
- for (input_iterator *p =top; p != 0; p = p->next)
- if (p->has_args())
- return p->nargs();
- return 0;
-}
-
-int input_stack::get_location(int allow_macro, const char **filenamep, int *linenop)
-{
- for (input_iterator *p = top; p; p = p->next)
- if (p->get_location(allow_macro, filenamep, linenop))
- return 1;
- return 0;
-}
-
-void input_stack::backtrace()
-{
- const char *f;
- int n;
- // only backtrace down to (not including) the topmost file
- for (input_iterator *p = top;
- p && !p->get_location(0, &f, &n);
- p = p->next)
- p->backtrace();
-}
-
-void input_stack::backtrace_all()
-{
- for (input_iterator *p = top; p; p = p->next)
- p->backtrace();
-}
-
-int input_stack::set_location(const char *filename, int lineno)
-{
- for (input_iterator *p = top; p; p = p->next)
- if (p->set_location(filename, lineno))
- return 1;
- return 0;
-}
-
-void input_stack::next_file(FILE *fp, const char *s)
-{
- input_iterator **pp;
- for (pp = ⊤ *pp != &nil_iterator; pp = &(*pp)->next)
- if ((*pp)->next_file(fp, s))
- return;
- if (++level > limit && limit > 0)
- fatal("input stack limit exceeded");
- *pp = new file_iterator(fp, s);
- (*pp)->next = &nil_iterator;
-}
-
-void input_stack::end_file()
-{
- for (input_iterator **pp = ⊤ *pp != &nil_iterator; pp = &(*pp)->next)
- if ((*pp)->is_file()) {
- input_iterator *tem = *pp;
- *pp = (*pp)->next;
- delete tem;
- level--;
- return;
- }
-}
-
-void input_stack::clear()
-{
- int nboundaries = 0;
- while (top != &nil_iterator) {
- if (top->is_boundary())
- nboundaries++;
- input_iterator *tem = top;
- top = top->next;
- level--;
- delete tem;
- }
- // Keep while_request happy.
- for (; nboundaries > 0; --nboundaries)
- add_return_boundary();
-}
-
-void input_stack::pop_macro()
-{
- int nboundaries = 0;
- int is_macro = 0;
- do {
- if (top->next == &nil_iterator)
- break;
- if (top->is_boundary())
- nboundaries++;
- is_macro = top->is_macro();
- input_iterator *tem = top;
- top = top->next;
- level--;
- delete tem;
- } while (!is_macro);
- // Keep while_request happy.
- for (; nboundaries > 0; --nboundaries)
- add_return_boundary();
-}
-
-inline void input_stack::save_compatible_flag(int f)
-{
- top->save_compatible_flag(f);
-}
-
-inline int input_stack::get_compatible_flag()
-{
- return top->get_compatible_flag();
-}
-
-void backtrace_request()
-{
- input_stack::backtrace_all();
- fflush(stderr);
- skip_line();
-}
-
-void next_file()
-{
- symbol nm = get_long_name(0);
- while (!tok.newline() && !tok.eof())
- tok.next();
- if (nm.is_null())
- input_stack::end_file();
- else {
- errno = 0;
- FILE *fp = fopen(nm.contents(), "r");
- if (!fp)
- error("can't open `%1': %2", nm.contents(), strerror(errno));
- else
- input_stack::next_file(fp, nm.contents());
- }
- tok.next();
-}
-
-void shift()
-{
- int n;
- if (!has_arg() || !get_integer(&n))
- n = 1;
- input_stack::shift(n);
- skip_line();
-}
-
-static int get_char_for_escape_name(int allow_space = 0)
-{
- int c = get_copy(0);
- switch (c) {
- case EOF:
- copy_mode_error("end of input in escape name");
- return '\0';
- default:
- if (!invalid_input_char(c))
- break;
- // fall through
- case '\n':
- if (c == '\n')
- input_stack::push(make_temp_iterator("\n"));
- // fall through
- case ' ':
- if (c == ' ' && allow_space)
- break;
- // fall through
- case '\t':
- case '\001':
- case '\b':
- copy_mode_error("%1 is not allowed in an escape name",
- input_char_description(c));
- return '\0';
- }
- return c;
-}
-
-static symbol read_two_char_escape_name()
-{
- char buf[3];
- buf[0] = get_char_for_escape_name();
- if (buf[0] != '\0') {
- buf[1] = get_char_for_escape_name();
- if (buf[1] == '\0')
- buf[0] = 0;
- else
- buf[2] = 0;
- }
- return symbol(buf);
-}
-
-static symbol read_long_escape_name(read_mode mode)
-{
- int start_level = input_stack::get_level();
- char abuf[ABUF_SIZE];
- char *buf = abuf;
- int buf_size = ABUF_SIZE;
- int i = 0;
- int c;
- int have_char = 0;
- for (;;) {
- c = get_char_for_escape_name(have_char && mode == WITH_ARGS);
- if (c == 0) {
- if (buf != abuf)
- a_delete buf;
- return NULL_SYMBOL;
- }
- have_char = 1;
- if (mode == WITH_ARGS && c == ' ')
- break;
- if (i + 2 > buf_size) {
- if (buf == abuf) {
- buf = new char[ABUF_SIZE*2];
- memcpy(buf, abuf, buf_size);
- buf_size = ABUF_SIZE*2;
- }
- else {
- char *old_buf = buf;
- buf = new char[buf_size*2];
- memcpy(buf, old_buf, buf_size);
- buf_size *= 2;
- a_delete old_buf;
- }
- }
- if (c == ']' && input_stack::get_level() == start_level)
- break;
- buf[i++] = c;
- }
- buf[i] = 0;
- if (c == ' ')
- have_string_arg = 1;
- if (buf == abuf) {
- if (i == 0) {
- if (mode != ALLOW_EMPTY)
- copy_mode_error("empty escape name");
- return EMPTY_SYMBOL;
- }
- return symbol(abuf);
- }
- else {
- symbol s(buf);
- a_delete buf;
- return s;
- }
-}
-
-static symbol read_escape_name(read_mode mode)
-{
- int c = get_char_for_escape_name();
- if (c == 0)
- return NULL_SYMBOL;
- if (c == '(')
- return read_two_char_escape_name();
- if (c == '[' && !compatible_flag)
- return read_long_escape_name(mode);
- char buf[2];
- buf[0] = c;
- buf[1] = '\0';
- return symbol(buf);
-}
-
-static symbol read_increment_and_escape_name(int *incp)
-{
- int c = get_char_for_escape_name();
- switch (c) {
- case 0:
- *incp = 0;
- return NULL_SYMBOL;
- case '(':
- *incp = 0;
- return read_two_char_escape_name();
- case '+':
- *incp = 1;
- return read_escape_name();
- case '-':
- *incp = -1;
- return read_escape_name();
- case '[':
- if (!compatible_flag) {
- *incp = 0;
- return read_long_escape_name();
- }
- break;
- }
- *incp = 0;
- char buf[2];
- buf[0] = c;
- buf[1] = '\0';
- return symbol(buf);
-}
-
-static int get_copy(node **nd, int defining)
-{
- for (;;) {
- int c = input_stack::get(nd);
- if (c == ESCAPE_NEWLINE) {
- if (defining)
- return c;
- do {
- c = input_stack::get(nd);
- } while (c == ESCAPE_NEWLINE);
- }
- if (c != escape_char || escape_char <= 0)
- return c;
- c = input_stack::peek();
- switch(c) {
- case 0:
- return escape_char;
- case '"':
- (void)input_stack::get(0);
- while ((c = input_stack::get(0)) != '\n' && c != EOF)
- ;
- return c;
- case '#': // Like \" but newline is ignored.
- (void)input_stack::get(0);
- while ((c = input_stack::get(0)) != '\n')
- if (c == EOF)
- return EOF;
- break;
- case '$':
- {
- (void)input_stack::get(0);
- symbol s = read_escape_name();
- if (!(s.is_null() || s.is_empty()))
- interpolate_arg(s);
- break;
- }
- case '*':
- {
- (void)input_stack::get(0);
- symbol s = read_escape_name(WITH_ARGS);
- if (!(s.is_null() || s.is_empty())) {
- if (have_string_arg) {
- have_string_arg = 0;
- interpolate_string_with_args(s);
- }
- else
- interpolate_string(s);
- }
- break;
- }
- case 'a':
- (void)input_stack::get(0);
- return '\001';
- case 'e':
- (void)input_stack::get(0);
- return ESCAPE_e;
- case 'E':
- (void)input_stack::get(0);
- return ESCAPE_E;
- case 'n':
- {
- (void)input_stack::get(0);
- int inc;
- symbol s = read_increment_and_escape_name(&inc);
- if (!(s.is_null() || s.is_empty()))
- interpolate_number_reg(s, inc);
- break;
- }
- case 'g':
- {
- (void)input_stack::get(0);
- symbol s = read_escape_name();
- if (!(s.is_null() || s.is_empty()))
- interpolate_number_format(s);
- break;
- }
- case 't':
- (void)input_stack::get(0);
- return '\t';
- case 'V':
- {
- (void)input_stack::get(0);
- symbol s = read_escape_name();
- if (!(s.is_null() || s.is_empty()))
- interpolate_environment_variable(s);
- break;
- }
- case '\n':
- (void)input_stack::get(0);
- if (defining)
- return ESCAPE_NEWLINE;
- break;
- case ' ':
- (void)input_stack::get(0);
- return ESCAPE_SPACE;
- case '~':
- (void)input_stack::get(0);
- return ESCAPE_TILDE;
- case ':':
- (void)input_stack::get(0);
- return ESCAPE_COLON;
- case '|':
- (void)input_stack::get(0);
- return ESCAPE_BAR;
- case '^':
- (void)input_stack::get(0);
- return ESCAPE_CIRCUMFLEX;
- case '{':
- (void)input_stack::get(0);
- return ESCAPE_LEFT_BRACE;
- case '}':
- (void)input_stack::get(0);
- return ESCAPE_RIGHT_BRACE;
- case '`':
- (void)input_stack::get(0);
- return ESCAPE_LEFT_QUOTE;
- case '\'':
- (void)input_stack::get(0);
- return ESCAPE_RIGHT_QUOTE;
- case '-':
- (void)input_stack::get(0);
- return ESCAPE_HYPHEN;
- case '_':
- (void)input_stack::get(0);
- return ESCAPE_UNDERSCORE;
- case 'c':
- (void)input_stack::get(0);
- return ESCAPE_c;
- case '!':
- (void)input_stack::get(0);
- return ESCAPE_BANG;
- case '?':
- (void)input_stack::get(0);
- return ESCAPE_QUESTION;
- case '&':
- (void)input_stack::get(0);
- return ESCAPE_AMPERSAND;
- case ')':
- (void)input_stack::get(0);
- return ESCAPE_RIGHT_PARENTHESIS;
- case '.':
- (void)input_stack::get(0);
- return c;
- case '%':
- (void)input_stack::get(0);
- return ESCAPE_PERCENT;
- default:
- if (c == escape_char) {
- (void)input_stack::get(0);
- return c;
- }
- else
- return escape_char;
- }
- }
-}
-
-class non_interpreted_char_node : public node {
- unsigned char c;
-public:
- non_interpreted_char_node(unsigned char);
- node *copy();
- int interpret(macro *);
- int same(node *);
- const char *type();
- int force_tprint();
-};
-
-int non_interpreted_char_node::same(node *nd)
-{
- return c == ((non_interpreted_char_node *)nd)->c;
-}
-
-const char *non_interpreted_char_node::type()
-{
- return "non_interpreted_char_node";
-}
-
-int non_interpreted_char_node::force_tprint()
-{
- return 0;
-}
-
-non_interpreted_char_node::non_interpreted_char_node(unsigned char n) : c(n)
-{
- assert(n != 0);
-}
-
-node *non_interpreted_char_node::copy()
-{
- return new non_interpreted_char_node(c);
-}
-
-int non_interpreted_char_node::interpret(macro *mac)
-{
- mac->append(c);
- return 1;
-}
-
-static void do_width();
-static node *do_non_interpreted();
-static node *do_special();
-static node *do_suppress(symbol nm);
-static void do_register();
-
-dictionary color_dictionary(501);
-static symbol default_symbol("default");
-
-static color *lookup_color(symbol nm)
-{
- assert(!nm.is_null());
- if (nm == default_symbol)
- return &default_color;
- color *c = (color *)color_dictionary.lookup(nm);
- if (c == 0)
- warning(WARN_COLOR, "`%1' not defined", nm.contents());
- return c;
-}
-
-void do_glyph_color(symbol nm)
-{
- if (nm.is_null())
- return;
- if (nm.is_empty())
- curenv->set_glyph_color(curenv->get_prev_glyph_color());
- else {
- color *tem = lookup_color(nm);
- if (tem)
- curenv->set_glyph_color(tem);
- else
- (void)color_dictionary.lookup(nm, new color);
- }
-}
-
-void do_fill_color(symbol nm)
-{
- if (nm.is_null())
- return;
- if (nm.is_empty())
- curenv->set_fill_color(curenv->get_prev_fill_color());
- else {
- color *tem = lookup_color(nm);
- if (tem)
- curenv->set_fill_color(tem);
- else
- (void)color_dictionary.lookup(nm, new color);
- }
-}
-
-static unsigned int get_color_element(const char *scheme, const char *col)
-{
- units val;
- if (!get_number(&val, 'f')) {
- warning(WARN_COLOR, "%1 in %2 definition set to 0", col, scheme);
- tok.next();
- return 0;
- }
- if (val < 0) {
- warning(WARN_RANGE, "%1 cannot be negative: set to 0", col);
- return 0;
- }
- if (val > color::MAX_COLOR_VAL+1) {
- warning(WARN_RANGE, "%1 cannot be greater than 1", col);
- // we change 0x10000 to 0xffff
- return color::MAX_COLOR_VAL;
- }
- return (unsigned int)val;
-}
-
-static color *read_rgb()
-{
- symbol component = get_long_name(0);
- if (component.is_null()) {
- warning(WARN_COLOR, "missing rgb color values");
- return 0;
- }
- const char *s = component.contents();
- color *col = new color;
- if (*s == '#') {
- if (!col->read_rgb(s)) {
- warning(WARN_COLOR, "expecting rgb color definition not `%1'", s);
- delete col;
- return 0;
- }
- }
- else {
- input_stack::push(make_temp_iterator(" "));
- input_stack::push(make_temp_iterator(s));
- tok.next();
- unsigned int r = get_color_element("rgb color", "red component");
- unsigned int g = get_color_element("rgb color", "green component");
- unsigned int b = get_color_element("rgb color", "blue component");
- col->set_rgb(r, g, b);
- }
- return col;
-}
-
-static color *read_cmy()
-{
- symbol component = get_long_name(0);
- if (component.is_null()) {
- warning(WARN_COLOR, "missing cmy color values");
- return 0;
- }
- const char *s = component.contents();
- color *col = new color;
- if (*s == '#') {
- if (!col->read_cmy(s)) {
- warning(WARN_COLOR, "expecting cmy color definition not `%1'", s);
- delete col;
- return 0;
- }
- }
- else {
- input_stack::push(make_temp_iterator(" "));
- input_stack::push(make_temp_iterator(s));
- tok.next();
- unsigned int c = get_color_element("cmy color", "cyan component");
- unsigned int m = get_color_element("cmy color", "magenta component");
- unsigned int y = get_color_element("cmy color", "yellow component");
- col->set_cmy(c, m, y);
- }
- return col;
-}
-
-static color *read_cmyk()
-{
- symbol component = get_long_name(0);
- if (component.is_null()) {
- warning(WARN_COLOR, "missing cmyk color values");
- return 0;
- }
- const char *s = component.contents();
- color *col = new color;
- if (*s == '#') {
- if (!col->read_cmyk(s)) {
- warning(WARN_COLOR, "`expecting a cmyk color definition not `%1'", s);
- delete col;
- return 0;
- }
- }
- else {
- input_stack::push(make_temp_iterator(" "));
- input_stack::push(make_temp_iterator(s));
- tok.next();
- unsigned int c = get_color_element("cmyk color", "cyan component");
- unsigned int m = get_color_element("cmyk color", "magenta component");
- unsigned int y = get_color_element("cmyk color", "yellow component");
- unsigned int k = get_color_element("cmyk color", "black component");
- col->set_cmyk(c, m, y, k);
- }
- return col;
-}
-
-static color *read_gray()
-{
- symbol component = get_long_name(0);
- if (component.is_null()) {
- warning(WARN_COLOR, "missing gray values");
- return 0;
- }
- const char *s = component.contents();
- color *col = new color;
- if (*s == '#') {
- if (!col->read_gray(s)) {
- warning(WARN_COLOR, "`expecting a gray definition not `%1'", s);
- delete col;
- return 0;
- }
- }
- else {
- input_stack::push(make_temp_iterator("\n"));
- input_stack::push(make_temp_iterator(s));
- tok.next();
- unsigned int g = get_color_element("gray", "gray value");
- col->set_gray(g);
- }
- return col;
-}
-
-static void activate_color()
-{
- int n;
- if (has_arg() && get_integer(&n))
- color_flag = n != 0;
- else
- color_flag = 1;
- skip_line();
-}
-
-static void define_color()
-{
- symbol color_name = get_long_name(1);
- if (color_name.is_null()) {
- skip_line();
- return;
- }
- if (color_name == default_symbol) {
- warning(WARN_COLOR, "default color can't be redefined");
- skip_line();
- return;
- }
- symbol style = get_long_name(1);
- if (style.is_null()) {
- skip_line();
- return;
- }
- color *col;
- if (strcmp(style.contents(), "rgb") == 0)
- col = read_rgb();
- else if (strcmp(style.contents(), "cmyk") == 0)
- col = read_cmyk();
- else if (strcmp(style.contents(), "gray") == 0)
- col = read_gray();
- else if (strcmp(style.contents(), "grey") == 0)
- col = read_gray();
- else if (strcmp(style.contents(), "cmy") == 0)
- col = read_cmy();
- else {
- warning(WARN_COLOR,
- "unknown color space `%1'; use rgb, cmyk, gray or cmy",
- style.contents());
- skip_line();
- return;
- }
- if (col)
- (void)color_dictionary.lookup(color_name, col);
- skip_line();
-}
-
-static node *do_overstrike()
-{
- token start;
- overstrike_node *on = new overstrike_node;
- int start_level = input_stack::get_level();
- start.next();
- for (;;) {
- tok.next();
- if (tok.newline() || tok.eof()) {
- warning(WARN_DELIM, "missing closing delimiter");
- break;
- }
- if (tok == start
- && (compatible_flag || input_stack::get_level() == start_level))
- break;
- charinfo *ci = tok.get_char(1);
- if (ci) {
- node *n = curenv->make_char_node(ci);
- if (n)
- on->overstrike(n);
- }
- }
- return on;
-}
-
-static node *do_bracket()
-{
- token start;
- bracket_node *bn = new bracket_node;
- start.next();
- int start_level = input_stack::get_level();
- for (;;) {
- tok.next();
- if (tok.eof()) {
- warning(WARN_DELIM, "missing closing delimiter");
- break;
- }
- if (tok.newline()) {
- warning(WARN_DELIM, "missing closing delimiter");
- input_stack::push(make_temp_iterator("\n"));
- break;
- }
- if (tok == start
- && (compatible_flag || input_stack::get_level() == start_level))
- break;
- charinfo *ci = tok.get_char(1);
- if (ci) {
- node *n = curenv->make_char_node(ci);
- if (n)
- bn->bracket(n);
- }
- }
- return bn;
-}
-
-static int do_name_test()
-{
- token start;
- start.next();
- int start_level = input_stack::get_level();
- int bad_char = 0;
- int some_char = 0;
- for (;;) {
- tok.next();
- if (tok.newline() || tok.eof()) {
- warning(WARN_DELIM, "missing closing delimiter");
- break;
- }
- if (tok == start
- && (compatible_flag || input_stack::get_level() == start_level))
- break;
- if (!tok.ch())
- bad_char = 1;
- some_char = 1;
- }
- return some_char && !bad_char;
-}
-
-static int do_expr_test()
-{
- token start;
- start.next();
- int start_level = input_stack::get_level();
- if (!start.delimiter(1))
- return 0;
- tok.next();
- // disable all warning and error messages temporarily
- int saved_warning_mask = warning_mask;
- int saved_inhibit_errors = inhibit_errors;
- warning_mask = 0;
- inhibit_errors = 1;
- int dummy;
- int result = get_number_rigidly(&dummy, 'u');
- warning_mask = saved_warning_mask;
- inhibit_errors = saved_inhibit_errors;
- if (tok == start && input_stack::get_level() == start_level)
- return result;
- // ignore everything up to the delimiter in case we aren't right there
- for (;;) {
- tok.next();
- if (tok.newline() || tok.eof()) {
- warning(WARN_DELIM, "missing closing delimiter");
- break;
- }
- if (tok == start && input_stack::get_level() == start_level)
- break;
- }
- return 0;
-}
-
-#if 0
-static node *do_zero_width()
-{
- token start;
- start.next();
- int start_level = input_stack::get_level();
- environment env(curenv);
- environment *oldenv = curenv;
- curenv = &env;
- for (;;) {
- tok.next();
- if (tok.newline() || tok.eof()) {
- error("missing closing delimiter");
- break;
- }
- if (tok == start
- && (compatible_flag || input_stack::get_level() == start_level))
- break;
- tok.process();
- }
- curenv = oldenv;
- node *rev = env.extract_output_line();
- node *n = 0;
- while (rev) {
- node *tem = rev;
- rev = rev->next;
- tem->next = n;
- n = tem;
- }
- return new zero_width_node(n);
-}
-
-#else
-
-// It's undesirable for \Z to change environments, because then
-// \n(.w won't work as expected.
-
-static node *do_zero_width()
-{
- node *rev = new dummy_node;
- token start;
- start.next();
- int start_level = input_stack::get_level();
- for (;;) {
- tok.next();
- if (tok.newline() || tok.eof()) {
- warning(WARN_DELIM, "missing closing delimiter");
- break;
- }
- if (tok == start
- && (compatible_flag || input_stack::get_level() == start_level))
- break;
- if (!tok.add_to_node_list(&rev))
- error("invalid token in argument to \\Z");
- }
- node *n = 0;
- while (rev) {
- node *tem = rev;
- rev = rev->next;
- tem->next = n;
- n = tem;
- }
- return new zero_width_node(n);
-}
-
-#endif
-
-token_node *node::get_token_node()
-{
- return 0;
-}
-
-class token_node : public node {
-public:
- token tk;
- token_node(const token &t);
- node *copy();
- token_node *get_token_node();
- int same(node *);
- const char *type();
- int force_tprint();
-};
-
-token_node::token_node(const token &t) : tk(t)
-{
-}
-
-node *token_node::copy()
-{
- return new token_node(tk);
-}
-
-token_node *token_node::get_token_node()
-{
- return this;
-}
-
-int token_node::same(node *nd)
-{
- return tk == ((token_node *)nd)->tk;
-}
-
-const char *token_node::type()
-{
- return "token_node";
-}
-
-int token_node::force_tprint()
-{
- return 0;
-}
-
-token::token() : nd(0), type(TOKEN_EMPTY)
-{
-}
-
-token::~token()
-{
- delete nd;
-}
-
-token::token(const token &t)
-: nm(t.nm), c(t.c), val(t.val), dim(t.dim), type(t.type)
-{
- // Use two statements to work around bug in SGI C++.
- node *tem = t.nd;
- nd = tem ? tem->copy() : 0;
-}
-
-void token::operator=(const token &t)
-{
- delete nd;
- nm = t.nm;
- // Use two statements to work around bug in SGI C++.
- node *tem = t.nd;
- nd = tem ? tem->copy() : 0;
- c = t.c;
- val = t.val;
- dim = t.dim;
- type = t.type;
-}
-
-void token::skip()
-{
- while (space())
- next();
-}
-
-int has_arg()
-{
- while (tok.space())
- tok.next();
- return !tok.newline();
-}
-
-void token::make_space()
-{
- type = TOKEN_SPACE;
-}
-
-void token::make_newline()
-{
- type = TOKEN_NEWLINE;
-}
-
-void token::next()
-{
- if (nd) {
- delete nd;
- nd = 0;
- }
- units x;
- for (;;) {
- node *n;
- int cc = input_stack::get(&n);
- if (cc != escape_char || escape_char == 0) {
- handle_normal_char:
- switch(cc) {
- case COMPATIBLE_SAVE:
- input_stack::save_compatible_flag(compatible_flag);
- compatible_flag = 0;
- continue;
- case COMPATIBLE_RESTORE:
- compatible_flag = input_stack::get_compatible_flag();
- continue;
- case EOF:
- type = TOKEN_EOF;
- return;
- case TRANSPARENT_FILE_REQUEST:
- case TITLE_REQUEST:
- case COPY_FILE_REQUEST:
-#ifdef COLUMN
- case VJUSTIFY_REQUEST:
-#endif /* COLUMN */
- type = TOKEN_REQUEST;
- c = cc;
- return;
- case BEGIN_TRAP:
- type = TOKEN_BEGIN_TRAP;
- return;
- case END_TRAP:
- type = TOKEN_END_TRAP;
- return;
- case LAST_PAGE_EJECTOR:
- seen_last_page_ejector = 1;
- // fall through
- case PAGE_EJECTOR:
- type = TOKEN_PAGE_EJECTOR;
- return;
- case ESCAPE_PERCENT:
- ESCAPE_PERCENT:
- type = TOKEN_HYPHEN_INDICATOR;
- return;
- case ESCAPE_SPACE:
- ESCAPE_SPACE:
- type = TOKEN_UNSTRETCHABLE_SPACE;
- return;
- case ESCAPE_TILDE:
- ESCAPE_TILDE:
- type = TOKEN_STRETCHABLE_SPACE;
- return;
- case ESCAPE_COLON:
- ESCAPE_COLON:
- type = TOKEN_ZERO_WIDTH_BREAK;
- return;
- case ESCAPE_e:
- ESCAPE_e:
- type = TOKEN_ESCAPE;
- return;
- case ESCAPE_E:
- goto handle_escape_char;
- case ESCAPE_BAR:
- ESCAPE_BAR:
- type = TOKEN_NODE;
- nd = new hmotion_node(curenv->get_narrow_space_width(),
- curenv->get_fill_color());
- return;
- case ESCAPE_CIRCUMFLEX:
- ESCAPE_CIRCUMFLEX:
- type = TOKEN_NODE;
- nd = new hmotion_node(curenv->get_half_narrow_space_width(),
- curenv->get_fill_color());
- return;
- case ESCAPE_NEWLINE:
- break;
- case ESCAPE_LEFT_BRACE:
- ESCAPE_LEFT_BRACE:
- type = TOKEN_LEFT_BRACE;
- return;
- case ESCAPE_RIGHT_BRACE:
- ESCAPE_RIGHT_BRACE:
- type = TOKEN_RIGHT_BRACE;
- return;
- case ESCAPE_LEFT_QUOTE:
- ESCAPE_LEFT_QUOTE:
- type = TOKEN_SPECIAL;
- nm = symbol("ga");
- return;
- case ESCAPE_RIGHT_QUOTE:
- ESCAPE_RIGHT_QUOTE:
- type = TOKEN_SPECIAL;
- nm = symbol("aa");
- return;
- case ESCAPE_HYPHEN:
- ESCAPE_HYPHEN:
- type = TOKEN_SPECIAL;
- nm = symbol("-");
- return;
- case ESCAPE_UNDERSCORE:
- ESCAPE_UNDERSCORE:
- type = TOKEN_SPECIAL;
- nm = symbol("ul");
- return;
- case ESCAPE_c:
- ESCAPE_c:
- type = TOKEN_INTERRUPT;
- return;
- case ESCAPE_BANG:
- ESCAPE_BANG:
- type = TOKEN_TRANSPARENT;
- return;
- case ESCAPE_QUESTION:
- ESCAPE_QUESTION:
- nd = do_non_interpreted();
- if (nd) {
- type = TOKEN_NODE;
- return;
- }
- break;
- case ESCAPE_AMPERSAND:
- ESCAPE_AMPERSAND:
- type = TOKEN_DUMMY;
- return;
- case ESCAPE_RIGHT_PARENTHESIS:
- ESCAPE_RIGHT_PARENTHESIS:
- type = TOKEN_TRANSPARENT_DUMMY;
- return;
- case '\b':
- type = TOKEN_BACKSPACE;
- return;
- case ' ':
- type = TOKEN_SPACE;
- return;
- case '\t':
- type = TOKEN_TAB;
- return;
- case '\n':
- type = TOKEN_NEWLINE;
- return;
- case '\001':
- type = TOKEN_LEADER;
- return;
- case 0:
- {
- assert(n != 0);
- token_node *tn = n->get_token_node();
- if (tn) {
- *this = tn->tk;
- delete tn;
- }
- else {
- nd = n;
- type = TOKEN_NODE;
- }
- }
- return;
- default:
- type = TOKEN_CHAR;
- c = cc;
- return;
- }
- }
- else {
- handle_escape_char:
- cc = input_stack::get(0);
- switch(cc) {
- case '(':
- nm = read_two_char_escape_name();
- type = TOKEN_SPECIAL;
- return;
- case EOF:
- type = TOKEN_EOF;
- error("end of input after escape character");
- return;
- case '`':
- goto ESCAPE_LEFT_QUOTE;
- case '\'':
- goto ESCAPE_RIGHT_QUOTE;
- case '-':
- goto ESCAPE_HYPHEN;
- case '_':
- goto ESCAPE_UNDERSCORE;
- case '%':
- goto ESCAPE_PERCENT;
- case ' ':
- goto ESCAPE_SPACE;
- case '0':
- nd = new hmotion_node(curenv->get_digit_width(),
- curenv->get_fill_color());
- type = TOKEN_NODE;
- return;
- case '|':
- goto ESCAPE_BAR;
- case '^':
- goto ESCAPE_CIRCUMFLEX;
- case '/':
- type = TOKEN_ITALIC_CORRECTION;
- return;
- case ',':
- type = TOKEN_NODE;
- nd = new left_italic_corrected_node;
- return;
- case '&':
- goto ESCAPE_AMPERSAND;
- case ')':
- goto ESCAPE_RIGHT_PARENTHESIS;
- case '!':
- goto ESCAPE_BANG;
- case '?':
- goto ESCAPE_QUESTION;
- case '~':
- goto ESCAPE_TILDE;
- case ':':
- goto ESCAPE_COLON;
- case '"':
- while ((cc = input_stack::get(0)) != '\n' && cc != EOF)
- ;
- if (cc == '\n')
- type = TOKEN_NEWLINE;
- else
- type = TOKEN_EOF;
- return;
- case '#': // Like \" but newline is ignored.
- while ((cc = input_stack::get(0)) != '\n')
- if (cc == EOF) {
- type = TOKEN_EOF;
- return;
- }
- break;
- case '$':
- {
- symbol nm = read_escape_name();
- if (!(nm.is_null() || nm.is_empty()))
- interpolate_arg(nm);
- break;
- }
- case '*':
- {
- symbol nm = read_escape_name(WITH_ARGS);
- if (!(nm.is_null() || nm.is_empty())) {
- if (have_string_arg) {
- have_string_arg = 0;
- interpolate_string_with_args(nm);
- }
- else
- interpolate_string(nm);
- }
- break;
- }
- case 'a':
- nd = new non_interpreted_char_node('\001');
- type = TOKEN_NODE;
- return;
- case 'A':
- c = '0' + do_name_test();
- type = TOKEN_CHAR;
- return;
- case 'b':
- nd = do_bracket();
- type = TOKEN_NODE;
- return;
- case 'B':
- c = '0' + do_expr_test();
- type = TOKEN_CHAR;
- return;
- case 'c':
- goto ESCAPE_c;
- case 'C':
- nm = get_delim_name();
- if (nm.is_null())
- break;
- type = TOKEN_SPECIAL;
- return;
- case 'd':
- type = TOKEN_NODE;
- nd = new vmotion_node(curenv->get_size() / 2,
- curenv->get_fill_color());
- return;
- case 'D':
- nd = read_draw_node();
- if (!nd)
- break;
- type = TOKEN_NODE;
- return;
- case 'e':
- goto ESCAPE_e;
- case 'E':
- goto handle_escape_char;
- case 'f':
- {
- symbol s = read_escape_name(ALLOW_EMPTY);
- if (s.is_null())
- break;
- const char *p;
- for (p = s.contents(); *p != '\0'; p++)
- if (!csdigit(*p))
- break;
- if (*p || s.is_empty())
- curenv->set_font(s);
- else
- curenv->set_font(atoi(s.contents()));
- if (!compatible_flag)
- have_input = 1;
- break;
- }
- case 'F':
- {
- symbol s = read_escape_name(ALLOW_EMPTY);
- if (s.is_null())
- break;
- curenv->set_family(s);
- break;
- }
- case 'g':
- {
- symbol s = read_escape_name();
- if (!(s.is_null() || s.is_empty()))
- interpolate_number_format(s);
- break;
- }
- case 'h':
- if (!get_delim_number(&x, 'm'))
- break;
- type = TOKEN_NODE;
- nd = new hmotion_node(x, curenv->get_fill_color());
- return;
- case 'H':
- // don't take height increments relative to previous height if
- // in compatibility mode
- if (!compatible_flag && curenv->get_char_height())
- {
- if (get_delim_number(&x, 'z', curenv->get_char_height()))
- curenv->set_char_height(x);
- }
- else
- {
- if (get_delim_number(&x, 'z', curenv->get_requested_point_size()))
- curenv->set_char_height(x);
- }
- if (!compatible_flag)
- have_input = 1;
- break;
- case 'k':
- nm = read_escape_name();
- if (nm.is_null() || nm.is_empty())
- break;
- type = TOKEN_MARK_INPUT;
- return;
- case 'l':
- case 'L':
- {
- charinfo *s = 0;
- if (!get_line_arg(&x, (cc == 'l' ? 'm': 'v'), &s))
- break;
- if (s == 0)
- s = get_charinfo(cc == 'l' ? "ru" : "br");
- type = TOKEN_NODE;
- node *n = curenv->make_char_node(s);
- if (cc == 'l')
- nd = new hline_node(x, n);
- else
- nd = new vline_node(x, n);
- return;
- }
- case 'm':
- do_glyph_color(read_escape_name(ALLOW_EMPTY));
- if (!compatible_flag)
- have_input = 1;
- break;
- case 'M':
- do_fill_color(read_escape_name(ALLOW_EMPTY));
- if (!compatible_flag)
- have_input = 1;
- break;
- case 'n':
- {
- int inc;
- symbol nm = read_increment_and_escape_name(&inc);
- if (!(nm.is_null() || nm.is_empty()))
- interpolate_number_reg(nm, inc);
- break;
- }
- case 'N':
- if (!get_delim_number(&val, 0))
- break;
- type = TOKEN_NUMBERED_CHAR;
- return;
- case 'o':
- nd = do_overstrike();
- type = TOKEN_NODE;
- return;
- case 'O':
- nd = do_suppress(read_escape_name());
- if (!nd)
- break;
- type = TOKEN_NODE;
- return;
- case 'p':
- type = TOKEN_SPREAD;
- return;
- case 'r':
- type = TOKEN_NODE;
- nd = new vmotion_node(-curenv->get_size(), curenv->get_fill_color());
- return;
- case 'R':
- do_register();
- if (!compatible_flag)
- have_input = 1;
- break;
- case 's':
- if (read_size(&x))
- curenv->set_size(x);
- if (!compatible_flag)
- have_input = 1;
- break;
- case 'S':
- if (get_delim_number(&x, 0))
- curenv->set_char_slant(x);
- if (!compatible_flag)
- have_input = 1;
- break;
- case 't':
- type = TOKEN_NODE;
- nd = new non_interpreted_char_node('\t');
- return;
- case 'u':
- type = TOKEN_NODE;
- nd = new vmotion_node(-curenv->get_size() / 2,
- curenv->get_fill_color());
- return;
- case 'v':
- if (!get_delim_number(&x, 'v'))
- break;
- type = TOKEN_NODE;
- nd = new vmotion_node(x, curenv->get_fill_color());
- return;
- case 'V':
- {
- symbol nm = read_escape_name();
- if (!(nm.is_null() || nm.is_empty()))
- interpolate_environment_variable(nm);
- break;
- }
- case 'w':
- do_width();
- break;
- case 'x':
- if (!get_delim_number(&x, 'v'))
- break;
- type = TOKEN_NODE;
- nd = new extra_size_node(x);
- return;
- case 'X':
- nd = do_special();
- if (!nd)
- break;
- type = TOKEN_NODE;
- return;
- case 'Y':
- {
- symbol s = read_escape_name();
- if (s.is_null() || s.is_empty())
- break;
- request_or_macro *p = lookup_request(s);
- macro *m = p->to_macro();
- if (!m) {
- error("can't transparently throughput a request");
- break;
- }
- nd = new special_node(*m);
- type = TOKEN_NODE;
- return;
- }
- case 'z':
- {
- next();
- if (type == TOKEN_NODE)
- nd = new zero_width_node(nd);
- else {
- charinfo *ci = get_char(1);
- if (ci == 0)
- break;
- node *gn = curenv->make_char_node(ci);
- if (gn == 0)
- break;
- nd = new zero_width_node(gn);
- type = TOKEN_NODE;
- }
- return;
- }
- case 'Z':
- nd = do_zero_width();
- if (nd == 0)
- break;
- type = TOKEN_NODE;
- return;
- case '{':
- goto ESCAPE_LEFT_BRACE;
- case '}':
- goto ESCAPE_RIGHT_BRACE;
- case '\n':
- break;
- case '[':
- if (!compatible_flag) {
- nm = read_long_escape_name();
- if (nm.is_null() || nm.is_empty())
- break;
- type = TOKEN_SPECIAL;
- return;
- }
- goto handle_normal_char;
- default:
- if (cc != escape_char && cc != '.')
- warning(WARN_ESCAPE, "escape character ignored before %1",
- input_char_description(cc));
- goto handle_normal_char;
- }
- }
- }
-}
-
-int token::operator==(const token &t)
-{
- if (type != t.type)
- return 0;
- switch(type) {
- case TOKEN_CHAR:
- return c == t.c;
- case TOKEN_SPECIAL:
- return nm == t.nm;
- case TOKEN_NUMBERED_CHAR:
- return val == t.val;
- default:
- return 1;
- }
-}
-
-int token::operator!=(const token &t)
-{
- return !(*this == t);
-}
-
-// is token a suitable delimiter (like ')?
-
-int token::delimiter(int err)
-{
- switch(type) {
- case TOKEN_CHAR:
- switch(c) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case '+':
- case '-':
- case '/':
- case '*':
- case '%':
- case '<':
- case '>':
- case '=':
- case '&':
- case ':':
- case '(':
- case ')':
- case '.':
- if (err)
- error("cannot use character `%1' as a starting delimiter", char(c));
- return 0;
- default:
- return 1;
- }
- case TOKEN_NODE:
- case TOKEN_SPACE:
- case TOKEN_STRETCHABLE_SPACE:
- case TOKEN_UNSTRETCHABLE_SPACE:
- case TOKEN_TAB:
- case TOKEN_NEWLINE:
- if (err)
- error("cannot use %1 as a starting delimiter", description());
- return 0;
- default:
- return 1;
- }
-}
-
-const char *token::description()
-{
- static char buf[4];
- switch (type) {
- case TOKEN_BACKSPACE:
- return "a backspace character";
- case TOKEN_CHAR:
- buf[0] = '`';
- buf[1] = c;
- buf[2] = '\'';
- buf[3] = '\0';
- return buf;
- case TOKEN_DUMMY:
- return "`\\&'";
- case TOKEN_ESCAPE:
- return "`\\e'";
- case TOKEN_HYPHEN_INDICATOR:
- return "`\\%'";
- case TOKEN_INTERRUPT:
- return "`\\c'";
- case TOKEN_ITALIC_CORRECTION:
- return "`\\/'";
- case TOKEN_LEADER:
- return "a leader character";
- case TOKEN_LEFT_BRACE:
- return "`\\{'";
- case TOKEN_MARK_INPUT:
- return "`\\k'";
- case TOKEN_NEWLINE:
- return "newline";
- case TOKEN_NODE:
- return "a node";
- case TOKEN_NUMBERED_CHAR:
- return "`\\N'";
- case TOKEN_RIGHT_BRACE:
- return "`\\}'";
- case TOKEN_SPACE:
- return "a space";
- case TOKEN_SPECIAL:
- return "a special character";
- case TOKEN_SPREAD:
- return "`\\p'";
- case TOKEN_STRETCHABLE_SPACE:
- return "`\\~'";
- case TOKEN_UNSTRETCHABLE_SPACE:
- return "`\\ '";
- case TOKEN_TAB:
- return "a tab character";
- case TOKEN_TRANSPARENT:
- return "`\\!'";
- case TOKEN_TRANSPARENT_DUMMY:
- return "`\\)'";
- case TOKEN_ZERO_WIDTH_BREAK:
- return "`\\:'";
- case TOKEN_EOF:
- return "end of input";
- default:
- break;
- }
- return "a magic token";
-}
-
-void skip_line()
-{
- while (!tok.newline())
- if (tok.eof())
- return;
- else
- tok.next();
- tok.next();
-}
-
-void compatible()
-{
- int n;
- if (has_arg() && get_integer(&n))
- compatible_flag = n != 0;
- else
- compatible_flag = 1;
- skip_line();
-}
-
-static void empty_name_warning(int required)
-{
- if (tok.newline() || tok.eof()) {
- if (required)
- warning(WARN_MISSING, "missing name");
- }
- else if (tok.right_brace() || tok.tab()) {
- const char *start = tok.description();
- do {
- tok.next();
- } while (tok.space() || tok.right_brace() || tok.tab());
- if (!tok.newline() && !tok.eof())
- error("%1 is not allowed before an argument", start);
- else if (required)
- warning(WARN_MISSING, "missing name");
- }
- else if (required)
- error("name expected (got %1)", tok.description());
- else
- error("name expected (got %1): treated as missing", tok.description());
-}
-
-static void non_empty_name_warning()
-{
- if (!tok.newline() && !tok.eof() && !tok.space() && !tok.tab()
- && !tok.right_brace()
- // We don't want to give a warning for .el\{
- && !tok.left_brace())
- error("%1 is not allowed in a name", tok.description());
-}
-
-symbol get_name(int required)
-{
- if (compatible_flag) {
- char buf[3];
- tok.skip();
- if ((buf[0] = tok.ch()) != 0) {
- tok.next();
- if ((buf[1] = tok.ch()) != 0) {
- buf[2] = 0;
- tok.make_space();
- }
- else
- non_empty_name_warning();
- return symbol(buf);
- }
- else {
- empty_name_warning(required);
- return NULL_SYMBOL;
- }
- }
- else
- return get_long_name(required);
-}
-
-symbol get_long_name(int required)
-{
- while (tok.space())
- tok.next();
- char abuf[ABUF_SIZE];
- char *buf = abuf;
- int buf_size = ABUF_SIZE;
- int i = 0;
- for (;;) {
- if (i + 1 > buf_size) {
- if (buf == abuf) {
- buf = new char[ABUF_SIZE*2];
- memcpy(buf, abuf, buf_size);
- buf_size = ABUF_SIZE*2;
- }
- else {
- char *old_buf = buf;
- buf = new char[buf_size*2];
- memcpy(buf, old_buf, buf_size);
- buf_size *= 2;
- a_delete old_buf;
- }
- }
- if ((buf[i] = tok.ch()) == 0)
- break;
- i++;
- tok.next();
- }
- if (i == 0) {
- empty_name_warning(required);
- return NULL_SYMBOL;
- }
- non_empty_name_warning();
- if (buf == abuf)
- return symbol(buf);
- else {
- symbol s(buf);
- a_delete buf;
- return s;
- }
-}
-
-void exit_troff()
-{
- exit_started = 1;
- topdiv->set_last_page();
- if (!end_macro_name.is_null()) {
- spring_trap(end_macro_name);
- tok.next();
- process_input_stack();
- }
- curenv->final_break();
- tok.next();
- process_input_stack();
- end_diversions();
- if (topdiv->get_page_length() > 0) {
- done_end_macro = 1;
- topdiv->set_ejecting();
- static unsigned char buf[2] = { LAST_PAGE_EJECTOR, '\0' };
- input_stack::push(make_temp_iterator((char *)buf));
- topdiv->space(topdiv->get_page_length(), 1);
- tok.next();
- process_input_stack();
- seen_last_page_ejector = 1; // should be set already
- topdiv->set_ejecting();
- push_page_ejector();
- topdiv->space(topdiv->get_page_length(), 1);
- tok.next();
- process_input_stack();
- }
- // This will only happen if a trap-invoked macro starts a diversion,
- // or if vertical position traps have been disabled.
- cleanup_and_exit(0);
-}
-
-// This implements .ex. The input stack must be cleared before calling
-// exit_troff().
-
-void exit_request()
-{
- input_stack::clear();
- if (exit_started)
- tok.next();
- else
- exit_troff();
-}
-
-void return_macro_request()
-{
- input_stack::pop_macro();
- tok.next();
-}
-
-void end_macro()
-{
- end_macro_name = get_name();
- skip_line();
-}
-
-void blank_line_macro()
-{
- blank_line_macro_name = get_name();
- skip_line();
-}
-
-static void trapping_blank_line()
-{
- if (!blank_line_macro_name.is_null())
- spring_trap(blank_line_macro_name);
- else
- blank_line();
-}
-
-void do_request()
-{
- int old_compatible_flag = compatible_flag;
- compatible_flag = 0;
- symbol nm = get_name();
- if (nm.is_null())
- skip_line();
- else
- interpolate_macro(nm);
- compatible_flag = old_compatible_flag;
-}
-
-inline int possibly_handle_first_page_transition()
-{
- if (topdiv->before_first_page && curdiv == topdiv && !curenv->is_dummy()) {
- handle_first_page_transition();
- return 1;
- }
- else
- return 0;
-}
-
-static int transparent_translate(int cc)
-{
- if (!invalid_input_char(cc)) {
- charinfo *ci = charset_table[cc];
- switch (ci->get_special_translation(1)) {
- case charinfo::TRANSLATE_SPACE:
- return ' ';
- case charinfo::TRANSLATE_STRETCHABLE_SPACE:
- return ESCAPE_TILDE;
- case charinfo::TRANSLATE_DUMMY:
- return ESCAPE_AMPERSAND;
- case charinfo::TRANSLATE_HYPHEN_INDICATOR:
- return ESCAPE_PERCENT;
- }
- // This is really ugly.
- ci = ci->get_translation(1);
- if (ci) {
- int c = ci->get_ascii_code();
- if (c != '\0')
- return c;
- error("can't translate %1 to special character `%2'"
- " in transparent throughput",
- input_char_description(cc),
- ci->nm.contents());
- }
- }
- return cc;
-}
-
-class int_stack {
- struct int_stack_element {
- int n;
- int_stack_element *next;
- } *top;
-public:
- int_stack();
- ~int_stack();
- void push(int);
- int is_empty();
- int pop();
-};
-
-int_stack::int_stack()
-{
- top = 0;
-}
-
-int_stack::~int_stack()
-{
- while (top != 0) {
- int_stack_element *temp = top;
- top = top->next;
- delete temp;
- }
-}
-
-int int_stack::is_empty()
-{
- return top == 0;
-}
-
-void int_stack::push(int n)
-{
- int_stack_element *p = new int_stack_element;
- p->next = top;
- p->n = n;
- top = p;
-}
-
-int int_stack::pop()
-{
- assert(top != 0);
- int_stack_element *p = top;
- top = top->next;
- int n = p->n;
- delete p;
- return n;
-}
-
-int node::reread(int *)
-{
- return 0;
-}
-
-int diverted_space_node::reread(int *bolp)
-{
- if (curenv->get_fill())
- trapping_blank_line();
- else
- curdiv->space(n);
- *bolp = 1;
- return 1;
-}
-
-int diverted_copy_file_node::reread(int *bolp)
-{
- curdiv->copy_file(filename.contents());
- *bolp = 1;
- return 1;
-}
-
-int word_space_node::reread(int *bolp)
-{
- if (unformat) {
- for (width_list *w = orig_width; w; w = w->next)
- curenv->space(w->width, w->sentence_width);
- unformat = 0;
- return 1;
- }
- return 0;
-}
-
-int unbreakable_space_node::reread(int *)
-{
- return 0;
-}
-
-int hmotion_node::reread(int *bolp)
-{
- if (unformat && was_tab) {
- curenv->handle_tab(0);
- unformat = 0;
- return 1;
- }
- return 0;
-}
-
-void process_input_stack()
-{
- int_stack trap_bol_stack;
- int bol = 1;
- for (;;) {
- int suppress_next = 0;
- switch (tok.type) {
- case token::TOKEN_CHAR:
- {
- unsigned char ch = tok.c;
- if (bol && !have_input
- && (ch == curenv->control_char
- || ch == curenv->no_break_control_char)) {
- break_flag = ch == curenv->control_char;
- // skip tabs as well as spaces here
- do {
- tok.next();
- } while (tok.white_space());
- symbol nm = get_name();
- if (nm.is_null())
- skip_line();
- else
- interpolate_macro(nm);
- suppress_next = 1;
- have_input = 0;
- }
- else {
- if (possibly_handle_first_page_transition())
- ;
- else {
- for (;;) {
- curenv->add_char(charset_table[ch]);
- tok.next();
- if (tok.type != token::TOKEN_CHAR)
- break;
- ch = tok.c;
- }
- suppress_next = 1;
- bol = 0;
- }
- }
- break;
- }
- case token::TOKEN_TRANSPARENT:
- {
- if (bol) {
- if (possibly_handle_first_page_transition())
- ;
- else {
- int cc;
- do {
- node *n;
- cc = get_copy(&n);
- if (cc != EOF)
- if (cc != '\0')
- curdiv->transparent_output(transparent_translate(cc));
- else
- curdiv->transparent_output(n);
- } while (cc != '\n' && cc != EOF);
- if (cc == EOF)
- curdiv->transparent_output('\n');
- }
- }
- break;
- }
- case token::TOKEN_NEWLINE:
- {
- if (bol && !have_input
- && !curenv->get_prev_line_interrupted())
- trapping_blank_line();
- else {
- curenv->newline();
- bol = 1;
- have_input = 0;
- }
- break;
- }
- case token::TOKEN_REQUEST:
- {
- int request_code = tok.c;
- tok.next();
- switch (request_code) {
- case TITLE_REQUEST:
- title();
- break;
- case COPY_FILE_REQUEST:
- copy_file();
- break;
- case TRANSPARENT_FILE_REQUEST:
- transparent_file();
- break;
-#ifdef COLUMN
- case VJUSTIFY_REQUEST:
- vjustify();
- break;
-#endif /* COLUMN */
- default:
- assert(0);
- break;
- }
- suppress_next = 1;
- have_input = 0;
- break;
- }
- case token::TOKEN_SPACE:
- {
- if (possibly_handle_first_page_transition())
- ;
- else if (bol && !curenv->get_prev_line_interrupted()) {
- int nspaces = 0;
- // save space_width now so that it isn't changed by \f or \s
- // which we wouldn't notice here
- hunits space_width = curenv->get_space_width();
- do {
- nspaces += tok.nspaces();
- tok.next();
- } while (tok.space());
- if (tok.newline())
- trapping_blank_line();
- else {
- push_token(tok);
- curenv->do_break();
- curenv->add_node(new hmotion_node(space_width * nspaces,
- curenv->get_fill_color()));
- bol = 0;
- }
- }
- else {
- curenv->space();
- bol = 0;
- }
- break;
- }
- case token::TOKEN_EOF:
- return;
- case token::TOKEN_NODE:
- {
- if (possibly_handle_first_page_transition())
- ;
- else if (tok.nd->reread(&bol)) {
- delete tok.nd;
- tok.nd = 0;
- }
- else {
- curenv->add_node(tok.nd);
- tok.nd = 0;
- bol = 0;
- curenv->possibly_break_line(1);
- }
- break;
- }
- case token::TOKEN_PAGE_EJECTOR:
- {
- continue_page_eject();
- // I think we just want to preserve bol.
- // bol = 1;
- break;
- }
- case token::TOKEN_BEGIN_TRAP:
- {
- trap_bol_stack.push(bol);
- bol = 1;
- have_input = 0;
- break;
- }
- case token::TOKEN_END_TRAP:
- {
- if (trap_bol_stack.is_empty())
- error("spurious end trap token detected!");
- else
- bol = trap_bol_stack.pop();
-
- /* I'm not totally happy about this. But I can't think of any other
- way to do it. Doing an output_pending_lines() whenever a
- TOKEN_END_TRAP is detected doesn't work: for example,
-
- .wh -1i x
- .de x
- 'bp
- ..
- .wh -.5i y
- .de y
- .tl ''-%-''
- ..
- .br
- .ll .5i
- .sp |\n(.pu-1i-.5v
- a\%very\%very\%long\%word
-
- will print all but the first lines from the word immediately
- after the footer, rather than on the next page. */
-
- if (trap_bol_stack.is_empty())
- curenv->output_pending_lines();
- break;
- }
- default:
- {
- bol = 0;
- tok.process();
- break;
- }
- }
- if (!suppress_next)
- tok.next();
- trap_sprung_flag = 0;
- }
-}
-
-#ifdef WIDOW_CONTROL
-
-void flush_pending_lines()
-{
- while (!tok.newline() && !tok.eof())
- tok.next();
- curenv->output_pending_lines();
- tok.next();
-}
-
-#endif /* WIDOW_CONTROL */
-
-request_or_macro::request_or_macro()
-{
-}
-
-macro *request_or_macro::to_macro()
-{
- return 0;
-}
-
-request::request(REQUEST_FUNCP pp) : p(pp)
-{
-}
-
-void request::invoke(symbol)
-{
- (*p)();
-}
-
-struct char_block {
- enum { SIZE = 128 };
- unsigned char s[SIZE];
- char_block *next;
- char_block();
-};
-
-char_block::char_block()
-: next(0)
-{
-}
-
-class char_list {
-public:
- char_list();
- ~char_list();
- void append(unsigned char);
- void set(unsigned char, int);
- unsigned char get(int);
- int length();
-private:
- unsigned char *ptr;
- int len;
- char_block *head;
- char_block *tail;
- friend class macro_header;
- friend class string_iterator;
-};
-
-char_list::char_list()
-: ptr(0), len(0), head(0), tail(0)
-{
-}
-
-char_list::~char_list()
-{
- while (head != 0) {
- char_block *tem = head;
- head = head->next;
- delete tem;
- }
-}
-
-int char_list::length()
-{
- return len;
-}
-
-void char_list::append(unsigned char c)
-{
- if (tail == 0) {
- head = tail = new char_block;
- ptr = tail->s;
- }
- else {
- if (ptr >= tail->s + char_block::SIZE) {
- tail->next = new char_block;
- tail = tail->next;
- ptr = tail->s;
- }
- }
- *ptr++ = c;
- len++;
-}
-
-void char_list::set(unsigned char c, int offset)
-{
- assert(len > offset);
- // optimization for access at the end
- int boundary = len - len % char_block::SIZE;
- if (offset >= boundary) {
- *(tail->s + offset - boundary) = c;
- return;
- }
- char_block *tem = head;
- int l = 0;
- for (;;) {
- l += char_block::SIZE;
- if (l > offset) {
- *(tem->s + offset % char_block::SIZE) = c;
- return;
- }
- tem = tem->next;
- }
-}
-
-unsigned char char_list::get(int offset)
-{
- assert(len > offset);
- // optimization for access at the end
- int boundary = len - len % char_block::SIZE;
- if (offset >= boundary)
- return *(tail->s + offset - boundary);
- char_block *tem = head;
- int l = 0;
- for (;;) {
- l += char_block::SIZE;
- if (l > offset)
- return *(tem->s + offset % char_block::SIZE);
- tem = tem->next;
- }
-}
-
-class node_list {
- node *head;
- node *tail;
-public:
- node_list();
- ~node_list();
- void append(node *);
- int length();
- node *extract();
-
- friend class macro_header;
- friend class string_iterator;
-};
-
-void node_list::append(node *n)
-{
- if (head == 0) {
- n->next = 0;
- head = tail = n;
- }
- else {
- n->next = 0;
- tail = tail->next = n;
- }
-}
-
-int node_list::length()
-{
- int total = 0;
- for (node *n = head; n != 0; n = n->next)
- ++total;
- return total;
-}
-
-node_list::node_list()
-{
- head = tail = 0;
-}
-
-node *node_list::extract()
-{
- node *temp = head;
- head = tail = 0;
- return temp;
-}
-
-node_list::~node_list()
-{
- delete_node_list(head);
-}
-
-struct macro_header {
-public:
- int count;
- char_list cl;
- node_list nl;
- macro_header() { count = 1; }
- macro_header *copy(int);
-};
-
-macro::~macro()
-{
- if (p != 0 && --(p->count) <= 0)
- delete p;
-}
-
-macro::macro()
-{
- if (!input_stack::get_location(1, &filename, &lineno)) {
- filename = 0;
- lineno = 0;
- }
- len = 0;
- empty_macro = 1;
- p = 0;
-}
-
-macro::macro(const macro &m)
-: p(m.p), filename(m.filename), lineno(m.lineno), len(m.len),
- empty_macro(m.empty_macro)
-{
- if (p != 0)
- p->count++;
-}
-
-macro ¯o::operator=(const macro &m)
-{
- // don't assign object
- if (m.p != 0)
- m.p->count++;
- if (p != 0 && --(p->count) <= 0)
- delete p;
- p = m.p;
- filename = m.filename;
- lineno = m.lineno;
- len = m.len;
- empty_macro = m.empty_macro;
- return *this;
-}
-
-void macro::append(unsigned char c)
-{
- assert(c != 0);
- if (p == 0)
- p = new macro_header;
- if (p->cl.length() != len) {
- macro_header *tem = p->copy(len);
- if (--(p->count) <= 0)
- delete p;
- p = tem;
- }
- p->cl.append(c);
- ++len;
- if (c != COMPATIBLE_SAVE && c != COMPATIBLE_RESTORE)
- empty_macro = 0;
-}
-
-void macro::set(unsigned char c, int offset)
-{
- assert(p != 0);
- assert(c != 0);
- p->cl.set(c, offset);
-}
-
-unsigned char macro::get(int offset)
-{
- assert(p != 0);
- return p->cl.get(offset);
-}
-
-int macro::length()
-{
- return len;
-}
-
-void macro::append_str(const char *s)
-{
- int i = 0;
-
- if (s) {
- while (s[i] != (char)0) {
- append(s[i]);
- i++;
- }
- }
-}
-
-void macro::append(node *n)
-{
- assert(n != 0);
- if (p == 0)
- p = new macro_header;
- if (p->cl.length() != len) {
- macro_header *tem = p->copy(len);
- if (--(p->count) <= 0)
- delete p;
- p = tem;
- }
- p->cl.append(0);
- p->nl.append(n);
- ++len;
- empty_macro = 0;
-}
-
-void macro::append_unsigned(unsigned int i)
-{
- unsigned int j = i / 10;
- if (j != 0)
- append_unsigned(j);
- append(((unsigned char)(((int)'0') + i % 10)));
-}
-
-void macro::append_int(int i)
-{
- if (i < 0) {
- append('-');
- i = -i;
- }
- append_unsigned((unsigned int)i);
-}
-
-void macro::print_size()
-{
- errprint("%1", len);
-}
-
-// make a copy of the first n bytes
-
-macro_header *macro_header::copy(int n)
-{
- macro_header *p = new macro_header;
- char_block *bp = cl.head;
- unsigned char *ptr = bp->s;
- node *nd = nl.head;
- while (--n >= 0) {
- if (ptr >= bp->s + char_block::SIZE) {
- bp = bp->next;
- ptr = bp->s;
- }
- int c = *ptr++;
- p->cl.append(c);
- if (c == 0) {
- p->nl.append(nd->copy());
- nd = nd->next;
- }
- }
- return p;
-}
-
-void print_macros()
-{
- object_dictionary_iterator iter(request_dictionary);
- request_or_macro *rm;
- symbol s;
- while (iter.get(&s, (object **)&rm)) {
- assert(!s.is_null());
- macro *m = rm->to_macro();
- if (m) {
- errprint("%1\t", s.contents());
- m->print_size();
- errprint("\n");
- }
- }
- fflush(stderr);
- skip_line();
-}
-
-class string_iterator : public input_iterator {
- macro mac;
- const char *how_invoked;
- int newline_flag;
- int lineno;
- char_block *bp;
- int count; // of characters remaining
- node *nd;
- int saved_compatible_flag;
-protected:
- symbol nm;
- string_iterator();
-public:
- string_iterator(const macro &m, const char *p = 0, symbol s = NULL_SYMBOL);
- int fill(node **);
- int peek();
- int get_location(int, const char **, int *);
- void backtrace();
- void save_compatible_flag(int f) { saved_compatible_flag = f; }
- int get_compatible_flag() { return saved_compatible_flag; }
-};
-
-string_iterator::string_iterator(const macro &m, const char *p, symbol s)
-: mac(m), how_invoked(p),
- newline_flag(0), lineno(1), nm(s)
-{
- count = mac.len;
- if (count != 0) {
- bp = mac.p->cl.head;
- nd = mac.p->nl.head;
- ptr = eptr = bp->s;
- }
- else {
- bp = 0;
- nd = 0;
- ptr = eptr = 0;
- }
-}
-
-string_iterator::string_iterator()
-{
- bp = 0;
- nd = 0;
- ptr = eptr = 0;
- newline_flag = 0;
- how_invoked = 0;
- lineno = 1;
- count = 0;
-}
-
-int string_iterator::fill(node **np)
-{
- if (newline_flag)
- lineno++;
- newline_flag = 0;
- if (count <= 0)
- return EOF;
- const unsigned char *p = eptr;
- if (p >= bp->s + char_block::SIZE) {
- bp = bp->next;
- p = bp->s;
- }
- if (*p == '\0') {
- if (np)
- *np = nd->copy();
- nd = nd->next;
- eptr = ptr = p + 1;
- count--;
- return 0;
- }
- const unsigned char *e = bp->s + char_block::SIZE;
- if (e - p > count)
- e = p + count;
- ptr = p;
- while (p < e) {
- unsigned char c = *p;
- if (c == '\n' || c == ESCAPE_NEWLINE) {
- newline_flag = 1;
- p++;
- break;
- }
- if (c == '\0')
- break;
- p++;
- }
- eptr = p;
- count -= p - ptr;
- return *ptr++;
-}
-
-int string_iterator::peek()
-{
- if (count <= 0)
- return EOF;
- const unsigned char *p = eptr;
- if (p >= bp->s + char_block::SIZE) {
- p = bp->next->s;
- }
- return *p;
-}
-
-int string_iterator::get_location(int allow_macro,
- const char **filep, int *linep)
-{
- if (!allow_macro)
- return 0;
- if (mac.filename == 0)
- return 0;
- *filep = mac.filename;
- *linep = mac.lineno + lineno - 1;
- return 1;
-}
-
-void string_iterator::backtrace()
-{
- if (mac.filename) {
- errprint("%1:%2: backtrace", mac.filename, mac.lineno + lineno - 1);
- if (how_invoked) {
- if (!nm.is_null())
- errprint(": %1 `%2'\n", how_invoked, nm.contents());
- else
- errprint(": %1\n", how_invoked);
- }
- else
- errprint("\n");
- }
-}
-
-class temp_iterator : public input_iterator {
- unsigned char *base;
- temp_iterator(const char *, int len);
-public:
- ~temp_iterator();
- friend input_iterator *make_temp_iterator(const char *);
-};
-
-#ifdef __GNUG__
-inline
-#endif
-temp_iterator::temp_iterator(const char *s, int len)
-{
- base = new unsigned char[len];
- memcpy(base, s, len);
- ptr = base;
- eptr = base + len;
-}
-
-temp_iterator::~temp_iterator()
-{
- a_delete base;
-}
-
-class small_temp_iterator : public input_iterator {
-private:
- small_temp_iterator(const char *, int);
- ~small_temp_iterator();
- enum { BLOCK = 16 };
- static small_temp_iterator *free_list;
- void *operator new(size_t);
- void operator delete(void *);
- enum { SIZE = 12 };
- unsigned char buf[SIZE];
- friend input_iterator *make_temp_iterator(const char *);
-};
-
-small_temp_iterator *small_temp_iterator::free_list = 0;
-
-void *small_temp_iterator::operator new(size_t n)
-{
- assert(n == sizeof(small_temp_iterator));
- if (!free_list) {
- free_list =
- (small_temp_iterator *)new char[sizeof(small_temp_iterator)*BLOCK];
- for (int i = 0; i < BLOCK - 1; i++)
- free_list[i].next = free_list + i + 1;
- free_list[BLOCK-1].next = 0;
- }
- small_temp_iterator *p = free_list;
- free_list = (small_temp_iterator *)(free_list->next);
- p->next = 0;
- return p;
-}
-
-#ifdef __GNUG__
-inline
-#endif
-void small_temp_iterator::operator delete(void *p)
-{
- if (p) {
- ((small_temp_iterator *)p)->next = free_list;
- free_list = (small_temp_iterator *)p;
- }
-}
-
-small_temp_iterator::~small_temp_iterator()
-{
-}
-
-#ifdef __GNUG__
-inline
-#endif
-small_temp_iterator::small_temp_iterator(const char *s, int len)
-{
- for (int i = 0; i < len; i++)
- buf[i] = s[i];
- ptr = buf;
- eptr = buf + len;
-}
-
-input_iterator *make_temp_iterator(const char *s)
-{
- if (s == 0)
- return new small_temp_iterator(s, 0);
- else {
- int n = strlen(s);
- if (n <= small_temp_iterator::SIZE)
- return new small_temp_iterator(s, n);
- else
- return new temp_iterator(s, n);
- }
-}
-
-// this is used when macros with arguments are interpolated
-
-struct arg_list {
- macro mac;
- arg_list *next;
- arg_list(const macro &);
- ~arg_list();
-};
-
-arg_list::arg_list(const macro &m) : mac(m), next(0)
-{
-}
-
-arg_list::~arg_list()
-{
-}
-
-class macro_iterator : public string_iterator {
- arg_list *args;
- int argc;
-public:
- macro_iterator(symbol, macro &, const char *how_invoked = "macro");
- macro_iterator();
- ~macro_iterator();
- int has_args() { return 1; }
- input_iterator *get_arg(int i);
- int nargs() { return argc; }
- void add_arg(const macro &m);
- void shift(int n);
- int is_macro() { return 1; }
-};
-
-input_iterator *macro_iterator::get_arg(int i)
-{
- if (i == 0)
- return make_temp_iterator(nm.contents());
- if (i > 0 && i <= argc) {
- arg_list *p = args;
- for (int j = 1; j < i; j++) {
- assert(p != 0);
- p = p->next;
- }
- return new string_iterator(p->mac);
- }
- else
- return 0;
-}
-
-void macro_iterator::add_arg(const macro &m)
-{
- arg_list **p;
- for (p = &args; *p; p = &((*p)->next))
- ;
- *p = new arg_list(m);
- ++argc;
-}
-
-void macro_iterator::shift(int n)
-{
- while (n > 0 && argc > 0) {
- arg_list *tem = args;
- args = args->next;
- delete tem;
- --argc;
- --n;
- }
-}
-
-// This gets used by eg .if '\?xxx\?''.
-
-int operator==(const macro &m1, const macro &m2)
-{
- if (m1.len != m2.len)
- return 0;
- string_iterator iter1(m1);
- string_iterator iter2(m2);
- int n = m1.len;
- while (--n >= 0) {
- node *nd1 = 0;
- int c1 = iter1.get(&nd1);
- assert(c1 != EOF);
- node *nd2 = 0;
- int c2 = iter2.get(&nd2);
- assert(c2 != EOF);
- if (c1 != c2) {
- if (c1 == 0)
- delete nd1;
- else if (c2 == 0)
- delete nd2;
- return 0;
- }
- if (c1 == 0) {
- assert(nd1 != 0);
- assert(nd2 != 0);
- int are_same = nd1->type() == nd2->type() && nd1->same(nd2);
- delete nd1;
- delete nd2;
- if (!are_same)
- return 0;
- }
- }
- return 1;
-}
-
-static void interpolate_macro(symbol nm)
-{
- request_or_macro *p = (request_or_macro *)request_dictionary.lookup(nm);
- if (p == 0) {
- int warned = 0;
- const char *s = nm.contents();
- if (strlen(s) > 2) {
- request_or_macro *r;
- char buf[3];
- buf[0] = s[0];
- buf[1] = s[1];
- buf[2] = '\0';
- r = (request_or_macro *)request_dictionary.lookup(symbol(buf));
- if (r) {
- macro *m = r->to_macro();
- if (!m || !m->empty())
- warned = warning(WARN_SPACE,
- "`%1' not defined (probable missing space after `%2')",
- nm.contents(), buf);
- }
- }
- if (!warned) {
- warning(WARN_MAC, "`%1' not defined", nm.contents());
- p = new macro;
- request_dictionary.define(nm, p);
- }
- }
- if (p)
- p->invoke(nm);
- else {
- skip_line();
- return;
- }
-}
-
-static void decode_args(macro_iterator *mi)
-{
- if (!tok.newline() && !tok.eof()) {
- node *n;
- int c = get_copy(&n);
- for (;;) {
- while (c == ' ')
- c = get_copy(&n);
- if (c == '\n' || c == EOF)
- break;
- macro arg;
- int quote_input_level = 0;
- int done_tab_warning = 0;
- if (c == '\"') {
- quote_input_level = input_stack::get_level();
- c = get_copy(&n);
- }
- while (c != EOF && c != '\n' && !(c == ' ' && quote_input_level == 0)) {
- if (quote_input_level > 0 && c == '\"'
- && (compatible_flag
- || input_stack::get_level() == quote_input_level)) {
- c = get_copy(&n);
- if (c == '"') {
- arg.append(c);
- c = get_copy(&n);
- }
- else
- break;
- }
- else {
- if (c == 0)
- arg.append(n);
- else {
- if (c == '\t' && quote_input_level == 0 && !done_tab_warning) {
- warning(WARN_TAB, "tab character in unquoted macro argument");
- done_tab_warning = 1;
- }
- arg.append(c);
- }
- c = get_copy(&n);
- }
- }
- mi->add_arg(arg);
- }
- }
-}
-
-static void decode_string_args(macro_iterator *mi)
-{
- node *n;
- int c = get_copy(&n);
- for (;;) {
- while (c == ' ')
- c = get_copy(&n);
- if (c == '\n' || c == EOF) {
- error("missing `]'");
- break;
- }
- if (c == ']')
- break;
- macro arg;
- int quote_input_level = 0;
- int done_tab_warning = 0;
- if (c == '\"') {
- quote_input_level = input_stack::get_level();
- c = get_copy(&n);
- }
- while (c != EOF && c != '\n'
- && !(c == ']' && quote_input_level == 0)
- && !(c == ' ' && quote_input_level == 0)) {
- if (quote_input_level > 0 && c == '\"'
- && input_stack::get_level() == quote_input_level) {
- c = get_copy(&n);
- if (c == '"') {
- arg.append(c);
- c = get_copy(&n);
- }
- else
- break;
- }
- else {
- if (c == 0)
- arg.append(n);
- else {
- if (c == '\t' && quote_input_level == 0 && !done_tab_warning) {
- warning(WARN_TAB, "tab character in unquoted string argument");
- done_tab_warning = 1;
- }
- arg.append(c);
- }
- c = get_copy(&n);
- }
- }
- mi->add_arg(arg);
- }
-}
-
-void macro::invoke(symbol nm)
-{
- macro_iterator *mi = new macro_iterator(nm, *this);
- decode_args(mi);
- input_stack::push(mi);
- tok.next();
-}
-
-macro *macro::to_macro()
-{
- return this;
-}
-
-int macro::empty()
-{
- return empty_macro == 1;
-}
-
-macro_iterator::macro_iterator(symbol s, macro &m, const char *how_invoked)
-: string_iterator(m, how_invoked, s), args(0), argc(0)
-{
-}
-
-macro_iterator::macro_iterator() : args(0), argc(0)
-{
-}
-
-macro_iterator::~macro_iterator()
-{
- while (args != 0) {
- arg_list *tem = args;
- args = args->next;
- delete tem;
- }
-}
-
-int trap_sprung_flag = 0;
-int postpone_traps_flag = 0;
-symbol postponed_trap;
-
-void spring_trap(symbol nm)
-{
- assert(!nm.is_null());
- trap_sprung_flag = 1;
- if (postpone_traps_flag) {
- postponed_trap = nm;
- return;
- }
- static char buf[2] = { BEGIN_TRAP, 0 };
- static char buf2[2] = { END_TRAP, '\0' };
- input_stack::push(make_temp_iterator(buf2));
- request_or_macro *p = lookup_request(nm);
- macro *m = p->to_macro();
- if (m)
- input_stack::push(new macro_iterator(nm, *m, "trap-invoked macro"));
- else
- error("you can't invoke a request with a trap");
- input_stack::push(make_temp_iterator(buf));
-}
-
-void postpone_traps()
-{
- postpone_traps_flag = 1;
-}
-
-int unpostpone_traps()
-{
- postpone_traps_flag = 0;
- if (!postponed_trap.is_null()) {
- spring_trap(postponed_trap);
- postponed_trap = NULL_SYMBOL;
- return 1;
- }
- else
- return 0;
-}
-
-void read_request()
-{
- macro_iterator *mi = new macro_iterator;
- int reading_from_terminal = isatty(fileno(stdin));
- int had_prompt = 0;
- if (!tok.newline() && !tok.eof()) {
- int c = get_copy(0);
- while (c == ' ')
- c = get_copy(0);
- while (c != EOF && c != '\n' && c != ' ') {
- if (!invalid_input_char(c)) {
- if (reading_from_terminal)
- fputc(c, stderr);
- had_prompt = 1;
- }
- c = get_copy(0);
- }
- if (c == ' ') {
- tok.make_space();
- decode_args(mi);
- }
- }
- if (reading_from_terminal) {
- fputc(had_prompt ? ':' : '\a', stderr);
- fflush(stderr);
- }
- input_stack::push(mi);
- macro mac;
- int nl = 0;
- int c;
- while ((c = getchar()) != EOF) {
- if (invalid_input_char(c))
- warning(WARN_INPUT, "invalid input character code %1", int(c));
- else {
- if (c == '\n') {
- if (nl)
- break;
- else
- nl = 1;
- }
- else
- nl = 0;
- mac.append(c);
- }
- }
- if (reading_from_terminal)
- clearerr(stdin);
- input_stack::push(new string_iterator(mac));
- tok.next();
-}
-
-enum define_mode { DEFINE_NORMAL, DEFINE_APPEND, DEFINE_IGNORE };
-enum calling_mode { CALLING_NORMAL, CALLING_INDIRECT, CALLING_DISABLE_COMP };
-
-void do_define_string(define_mode mode, calling_mode calling)
-{
- symbol nm;
- node *n;
- int c;
- nm = get_name(1);
- if (nm.is_null()) {
- skip_line();
- return;
- }
- if (tok.newline())
- c = '\n';
- else if (tok.tab())
- c = '\t';
- else if (!tok.space()) {
- error("bad string definition");
- skip_line();
- return;
- }
- else
- c = get_copy(&n);
- while (c == ' ')
- c = get_copy(&n);
- if (c == '"')
- c = get_copy(&n);
- macro mac;
- request_or_macro *rm = (request_or_macro *)request_dictionary.lookup(nm);
- macro *mm = rm ? rm->to_macro() : 0;
- if (mode == DEFINE_APPEND && mm)
- mac = *mm;
- if (calling == CALLING_DISABLE_COMP)
- mac.append(COMPATIBLE_SAVE);
- while (c != '\n' && c != EOF) {
- if (c == 0)
- mac.append(n);
- else
- mac.append((unsigned char)c);
- c = get_copy(&n);
- }
- if (!mm) {
- mm = new macro;
- request_dictionary.define(nm, mm);
- }
- if (calling == CALLING_DISABLE_COMP)
- mac.append(COMPATIBLE_RESTORE);
- *mm = mac;
- tok.next();
-}
-
-void define_string()
-{
- do_define_string(DEFINE_NORMAL, CALLING_NORMAL);
-}
-
-void define_nocomp_string()
-{
- do_define_string(DEFINE_NORMAL, CALLING_DISABLE_COMP);
-}
-
-void append_string()
-{
- do_define_string(DEFINE_APPEND, CALLING_NORMAL);
-}
-
-void append_nocomp_string()
-{
- do_define_string(DEFINE_APPEND, CALLING_DISABLE_COMP);
-}
-
-void do_define_character(int fallback)
-{
- node *n;
- int c;
- tok.skip();
- charinfo *ci = tok.get_char(1);
- if (ci == 0) {
- skip_line();
- return;
- }
- tok.next();
- if (tok.newline())
- c = '\n';
- else if (tok.tab())
- c = '\t';
- else if (!tok.space()) {
- error("bad character definition");
- skip_line();
- return;
- }
- else
- c = get_copy(&n);
- while (c == ' ' || c == '\t')
- c = get_copy(&n);
- if (c == '"')
- c = get_copy(&n);
- macro *m = new macro;
- while (c != '\n' && c != EOF) {
- if (c == 0)
- m->append(n);
- else
- m->append((unsigned char)c);
- c = get_copy(&n);
- }
- m = ci->set_macro(m, fallback);
- if (m)
- delete m;
- tok.next();
-}
-
-void define_character()
-{
- do_define_character(0);
-}
-
-void define_fallback_character()
-{
- do_define_character(1);
-}
-
-static void remove_character()
-{
- tok.skip();
- while (!tok.newline() && !tok.eof()) {
- if (!tok.space() && !tok.tab()) {
- charinfo *ci = tok.get_char(1);
- if (!ci)
- break;
- macro *m = ci->set_macro(0);
- if (m)
- delete m;
- }
- tok.next();
- }
- skip_line();
-}
-
-static void interpolate_string(symbol nm)
-{
- request_or_macro *p = lookup_request(nm);
- macro *m = p->to_macro();
- if (!m)
- error("you can only invoke a string or macro using \\*");
- else {
- string_iterator *si = new string_iterator(*m, "string", nm);
- input_stack::push(si);
- }
-}
-
-static void interpolate_string_with_args(symbol s)
-{
- request_or_macro *p = lookup_request(s);
- macro *m = p->to_macro();
- if (!m)
- error("you can only invoke a string or macro using \\*");
- else {
- macro_iterator *mi = new macro_iterator(s, *m);
- decode_string_args(mi);
- input_stack::push(mi);
- }
-}
-
-/* This class is used for the implementation of \$@. It is used for
-each of the closing double quotes. It artificially increases the
-input level by 2, so that the closing double quote will appear to have
-the same input level as the opening quote. */
-
-class end_quote_iterator : public input_iterator {
- unsigned char buf[1];
-public:
- end_quote_iterator();
- ~end_quote_iterator() { }
- int internal_level() { return 2; }
-};
-
-end_quote_iterator::end_quote_iterator()
-{
- buf[0] = '"';
- ptr = buf;
- eptr = buf + 1;
-}
-
-static void interpolate_arg(symbol nm)
-{
- const char *s = nm.contents();
- if (!s || *s == '\0')
- copy_mode_error("missing argument name");
- else if (s[1] == 0 && csdigit(s[0]))
- input_stack::push(input_stack::get_arg(s[0] - '0'));
- else if (s[0] == '*' && s[1] == '\0') {
- for (int i = input_stack::nargs(); i > 0; i--) {
- input_stack::push(input_stack::get_arg(i));
- if (i != 1)
- input_stack::push(make_temp_iterator(" "));
- }
- }
- else if (s[0] == '@' && s[1] == '\0') {
- for (int i = input_stack::nargs(); i > 0; i--) {
- input_stack::push(new end_quote_iterator);
- input_stack::push(input_stack::get_arg(i));
- input_stack::push(make_temp_iterator(i == 1 ? "\"" : " \""));
- }
- }
- else {
- const char *p;
- for (p = s; *p && csdigit(*p); p++)
- ;
- if (*p)
- copy_mode_error("bad argument name `%1'", s);
- else
- input_stack::push(input_stack::get_arg(atoi(s)));
- }
-}
-
-void handle_first_page_transition()
-{
- push_token(tok);
- topdiv->begin_page();
-}
-
-// We push back a token by wrapping it up in a token_node, and
-// wrapping that up in a string_iterator.
-
-static void push_token(const token &t)
-{
- macro m;
- m.append(new token_node(t));
- input_stack::push(new string_iterator(m));
-}
-
-void push_page_ejector()
-{
- static char buf[2] = { PAGE_EJECTOR, '\0' };
- input_stack::push(make_temp_iterator(buf));
-}
-
-void handle_initial_request(unsigned char code)
-{
- char buf[2];
- buf[0] = code;
- buf[1] = '\0';
- macro mac;
- mac.append(new token_node(tok));
- input_stack::push(new string_iterator(mac));
- input_stack::push(make_temp_iterator(buf));
- topdiv->begin_page();
- tok.next();
-}
-
-void handle_initial_title()
-{
- handle_initial_request(TITLE_REQUEST);
-}
-
-// this should be local to define_macro, but cfront 1.2 doesn't support that
-static symbol dot_symbol(".");
-
-void do_define_macro(define_mode mode, calling_mode calling)
-{
- symbol nm, term;
- if (calling == CALLING_INDIRECT) {
- symbol temp1 = get_name(1);
- if (temp1.is_null()) {
- skip_line();
- return;
- }
- symbol temp2 = get_name();
- input_stack::push(make_temp_iterator("\n"));
- if (!temp2.is_null()) {
- interpolate_string(temp2);
- input_stack::push(make_temp_iterator(" "));
- }
- interpolate_string(temp1);
- input_stack::push(make_temp_iterator(" "));
- tok.next();
- }
- if (mode == DEFINE_NORMAL || mode == DEFINE_APPEND) {
- nm = get_name(1);
- if (nm.is_null()) {
- skip_line();
- return;
- }
- }
- term = get_name(); // the request that terminates the definition
- if (term.is_null())
- term = dot_symbol;
- while (!tok.newline() && !tok.eof())
- tok.next();
- const char *start_filename;
- int start_lineno;
- int have_start_location = input_stack::get_location(0, &start_filename,
- &start_lineno);
- node *n;
- // doing this here makes the line numbers come out right
- int c = get_copy(&n, 1);
- macro mac;
- macro *mm = 0;
- if (mode == DEFINE_NORMAL || mode == DEFINE_APPEND) {
- request_or_macro *rm =
- (request_or_macro *)request_dictionary.lookup(nm);
- if (rm)
- mm = rm->to_macro();
- if (mm && mode == DEFINE_APPEND)
- mac = *mm;
- }
- int bol = 1;
- if (calling == CALLING_DISABLE_COMP)
- mac.append(COMPATIBLE_SAVE);
- for (;;) {
- while (c == ESCAPE_NEWLINE) {
- if (mode == DEFINE_NORMAL || mode == DEFINE_APPEND)
- mac.append(c);
- c = get_copy(&n, 1);
- }
- if (bol && c == '.') {
- const char *s = term.contents();
- int d = 0;
- // see if it matches term
- int i = 0;
- if (s[0] != 0) {
- while ((d = get_copy(&n)) == ' ' || d == '\t')
- ;
- if ((unsigned char)s[0] == d) {
- for (i = 1; s[i] != 0; i++) {
- d = get_copy(&n);
- if ((unsigned char)s[i] != d)
- break;
- }
- }
- }
- if (s[i] == 0
- && ((i == 2 && compatible_flag)
- || (d = get_copy(&n)) == ' '
- || d == '\n')) { // we found it
- if (d == '\n')
- tok.make_newline();
- else
- tok.make_space();
- if (mode == DEFINE_APPEND || mode == DEFINE_NORMAL) {
- if (!mm) {
- mm = new macro;
- request_dictionary.define(nm, mm);
- }
- if (calling == CALLING_DISABLE_COMP)
- mac.append(COMPATIBLE_RESTORE);
- *mm = mac;
- }
- if (term != dot_symbol) {
- ignoring = 0;
- interpolate_macro(term);
- }
- else
- skip_line();
- return;
- }
- if (mode == DEFINE_APPEND || mode == DEFINE_NORMAL) {
- mac.append(c);
- for (int j = 0; j < i; j++)
- mac.append(s[j]);
- }
- c = d;
- }
- if (c == EOF) {
- if (mode == DEFINE_NORMAL || mode == DEFINE_APPEND) {
- if (have_start_location)
- error_with_file_and_line(start_filename, start_lineno,
- "end of file while defining macro `%1'",
- nm.contents());
- else
- error("end of file while defining macro `%1'", nm.contents());
- }
- else {
- if (have_start_location)
- error_with_file_and_line(start_filename, start_lineno,
- "end of file while ignoring input lines");
- else
- error("end of file while ignoring input lines");
- }
- tok.next();
- return;
- }
- if (mode == DEFINE_NORMAL || mode == DEFINE_APPEND) {
- if (c == 0)
- mac.append(n);
- else
- mac.append(c);
- }
- bol = (c == '\n');
- c = get_copy(&n, 1);
- }
-}
-
-void define_macro()
-{
- do_define_macro(DEFINE_NORMAL, CALLING_NORMAL);
-}
-
-void define_nocomp_macro()
-{
- do_define_macro(DEFINE_NORMAL, CALLING_DISABLE_COMP);
-}
-
-void define_indirect_macro()
-{
- do_define_macro(DEFINE_NORMAL, CALLING_INDIRECT);
-}
-
-void append_macro()
-{
- do_define_macro(DEFINE_APPEND, CALLING_NORMAL);
-}
-
-void append_indirect_macro()
-{
- do_define_macro(DEFINE_APPEND, CALLING_INDIRECT);
-}
-
-void append_nocomp_macro()
-{
- do_define_macro(DEFINE_APPEND, CALLING_DISABLE_COMP);
-}
-
-void ignore()
-{
- ignoring = 1;
- do_define_macro(DEFINE_IGNORE, CALLING_NORMAL);
- ignoring = 0;
-}
-
-void remove_macro()
-{
- for (;;) {
- symbol s = get_name();
- if (s.is_null())
- break;
- request_dictionary.remove(s);
- }
- skip_line();
-}
-
-void rename_macro()
-{
- symbol s1 = get_name(1);
- if (!s1.is_null()) {
- symbol s2 = get_name(1);
- if (!s2.is_null())
- request_dictionary.rename(s1, s2);
- }
- skip_line();
-}
-
-void alias_macro()
-{
- symbol s1 = get_name(1);
- if (!s1.is_null()) {
- symbol s2 = get_name(1);
- if (!s2.is_null()) {
- if (!request_dictionary.alias(s1, s2))
- warning(WARN_MAC, "`%1' not defined", s2.contents());
- }
- }
- skip_line();
-}
-
-void chop_macro()
-{
- symbol s = get_name(1);
- if (!s.is_null()) {
- request_or_macro *p = lookup_request(s);
- macro *m = p->to_macro();
- if (!m)
- error("cannot chop request");
- else if (m->empty())
- error("cannot chop empty macro");
- else {
- int have_restore = 0;
- // we have to check for additional save/restore pairs which could be
- // there due to empty am1 requests.
- for (;;) {
- if (m->get(m->len - 1) != COMPATIBLE_RESTORE)
- break;
- have_restore = 1;
- m->len -= 1;
- if (m->get(m->len - 1) != COMPATIBLE_SAVE)
- break;
- have_restore = 0;
- m->len -= 1;
- if (m->len == 0)
- break;
- }
- if (m->len == 0)
- error("cannot chop empty macro");
- else {
- if (have_restore)
- m->set(COMPATIBLE_RESTORE, m->len - 1);
- else
- m->len -= 1;
- }
- }
- }
- skip_line();
-}
-
-void substring_request()
-{
- int start; // 0, 1, ..., n-1 or -1, -2, ...
- symbol s = get_name(1);
- if (!s.is_null() && get_integer(&start)) {
- request_or_macro *p = lookup_request(s);
- macro *m = p->to_macro();
- if (!m)
- error("cannot apply `substring' on a request");
- else {
- int end = -1;
- if (!has_arg() || get_integer(&end)) {
- int real_length = 0; // 1, 2, ..., n
- string_iterator iter1(*m);
- for (int l = 0; l < m->len; l++) {
- int c = iter1.get(0);
- if (c == COMPATIBLE_SAVE || c == COMPATIBLE_RESTORE)
- continue;
- if (c == EOF)
- break;
- real_length++;
- }
- if (start < 0)
- start += real_length;
- if (end < 0)
- end += real_length;
- if (start > end) {
- int tem = start;
- start = end;
- end = tem;
- }
- if (start >= real_length || end < 0) {
- warning(WARN_RANGE,
- "start and end index of substring out of range");
- m->len = 0;
- if (m->p) {
- if (--(m->p->count) <= 0)
- delete m->p;
- m->p = 0;
- }
- skip_line();
- return;
- }
- if (start < 0) {
- warning(WARN_RANGE,
- "start index of substring out of range, set to 0");
- start = 0;
- }
- if (end >= real_length) {
- warning(WARN_RANGE,
- "end index of substring out of range, set to string length");
- end = real_length - 1;
- }
- // now extract the substring
- string_iterator iter(*m);
- int i;
- for (i = 0; i < start; i++) {
- int c = iter.get(0);
- while (c == COMPATIBLE_SAVE || c == COMPATIBLE_RESTORE)
- c = iter.get(0);
- if (c == EOF)
- break;
- }
- macro mac;
- for (; i <= end; i++) {
- node *nd;
- int c = iter.get(&nd);
- while (c == COMPATIBLE_SAVE || c == COMPATIBLE_RESTORE)
- c = iter.get(0);
- if (c == EOF)
- break;
- if (c == 0)
- mac.append(nd);
- else
- mac.append((unsigned char)c);
- }
- *m = mac;
- }
- }
- }
- skip_line();
-}
-
-void length_request()
-{
- symbol ret;
- ret = get_name(1);
- if (ret.is_null()) {
- skip_line();
- return;
- }
- int c;
- node *n;
- if (tok.newline())
- c = '\n';
- else if (tok.tab())
- c = '\t';
- else if (!tok.space()) {
- error("bad string definition");
- skip_line();
- return;
- }
- else
- c = get_copy(&n);
- while (c == ' ')
- c = get_copy(&n);
- if (c == '"')
- c = get_copy(&n);
- int len = 0;
- while (c != '\n' && c != EOF) {
- ++len;
- c = get_copy(&n);
- }
- reg *r = (reg*)number_reg_dictionary.lookup(ret);
- if (r)
- r->set_value(len);
- else
- set_number_reg(ret, len);
- tok.next();
-}
-
-void asciify_macro()
-{
- symbol s = get_name(1);
- if (!s.is_null()) {
- request_or_macro *p = lookup_request(s);
- macro *m = p->to_macro();
- if (!m)
- error("cannot asciify request");
- else {
- macro am;
- string_iterator iter(*m);
- for (;;) {
- node *nd;
- int c = iter.get(&nd);
- if (c == EOF)
- break;
- if (c != 0)
- am.append(c);
- else
- nd->asciify(&am);
- }
- *m = am;
- }
- }
- skip_line();
-}
-
-void unformat_macro()
-{
- symbol s = get_name(1);
- if (!s.is_null()) {
- request_or_macro *p = lookup_request(s);
- macro *m = p->to_macro();
- if (!m)
- error("cannot unformat request");
- else {
- macro am;
- string_iterator iter(*m);
- for (;;) {
- node *nd;
- int c = iter.get(&nd);
- if (c == EOF)
- break;
- if (c != 0)
- am.append(c);
- else {
- if (nd->set_unformat_flag())
- am.append(nd);
- }
- }
- *m = am;
- }
- }
- skip_line();
-}
-
-static void interpolate_environment_variable(symbol nm)
-{
- const char *s = getenv(nm.contents());
- if (s && *s)
- input_stack::push(make_temp_iterator(s));
-}
-
-void interpolate_number_reg(symbol nm, int inc)
-{
- reg *r = lookup_number_reg(nm);
- if (inc < 0)
- r->decrement();
- else if (inc > 0)
- r->increment();
- input_stack::push(make_temp_iterator(r->get_string()));
-}
-
-static void interpolate_number_format(symbol nm)
-{
- reg *r = (reg *)number_reg_dictionary.lookup(nm);
- if (r)
- input_stack::push(make_temp_iterator(r->get_format()));
-}
-
-static int get_delim_number(units *n, int si, int prev_value)
-{
- token start;
- start.next();
- if (start.delimiter(1)) {
- tok.next();
- if (get_number(n, si, prev_value)) {
- if (start != tok)
- warning(WARN_DELIM, "closing delimiter does not match");
- return 1;
- }
- }
- return 0;
-}
-
-static int get_delim_number(units *n, int si)
-{
- token start;
- start.next();
- if (start.delimiter(1)) {
- tok.next();
- if (get_number(n, si)) {
- if (start != tok)
- warning(WARN_DELIM, "closing delimiter does not match");
- return 1;
- }
- }
- return 0;
-}
-
-static int get_line_arg(units *n, int si, charinfo **cp)
-{
- token start;
- start.next();
- int start_level = input_stack::get_level();
- if (!start.delimiter(1))
- return 0;
- tok.next();
- if (get_number(n, si)) {
- if (tok.dummy() || tok.transparent_dummy())
- tok.next();
- if (!(start == tok && input_stack::get_level() == start_level)) {
- *cp = tok.get_char(1);
- tok.next();
- }
- if (!(start == tok && input_stack::get_level() == start_level))
- warning(WARN_DELIM, "closing delimiter does not match");
- return 1;
- }
- return 0;
-}
-
-static int read_size(int *x)
-{
- tok.next();
- int c = tok.ch();
- int inc = 0;
- if (c == '-') {
- inc = -1;
- tok.next();
- c = tok.ch();
- }
- else if (c == '+') {
- inc = 1;
- tok.next();
- c = tok.ch();
- }
- int val;
- int bad = 0;
- if (c == '(') {
- tok.next();
- c = tok.ch();
- if (!inc) {
- // allow an increment either before or after the left parenthesis
- if (c == '-') {
- inc = -1;
- tok.next();
- c = tok.ch();
- }
- else if (c == '+') {
- inc = 1;
- tok.next();
- c = tok.ch();
- }
- }
- if (!csdigit(c))
- bad = 1;
- else {
- val = c - '0';
- tok.next();
- c = tok.ch();
- if (!csdigit(c))
- bad = 1;
- else {
- val = val*10 + (c - '0');
- val *= sizescale;
- }
- }
- }
- else if (csdigit(c)) {
- val = c - '0';
- if (!inc && c != '0' && c < '4') {
- tok.next();
- c = tok.ch();
- if (!csdigit(c))
- bad = 1;
- else
- val = val*10 + (c - '0');
- }
- val *= sizescale;
- }
- else if (!tok.delimiter(1))
- return 0;
- else {
- token start(tok);
- tok.next();
- if (!(inc
- ? get_number(&val, 'z')
- : get_number(&val, 'z', curenv->get_requested_point_size())))
- return 0;
- if (!(start.ch() == '[' && tok.ch() == ']') && start != tok) {
- if (start.ch() == '[')
- error("missing `]'");
- else
- error("missing closing delimiter");
- return 0;
- }
- }
- if (!bad) {
- switch (inc) {
- case 0:
- if (val == 0) {
- // special case -- \s[0] and \s0 means to revert to previous size
- *x = 0;
- return 1;
- }
- *x = val;
- break;
- case 1:
- *x = curenv->get_requested_point_size() + val;
- break;
- case -1:
- *x = curenv->get_requested_point_size() - val;
- break;
- default:
- assert(0);
- }
- if (*x <= 0) {
- warning(WARN_RANGE,
- "\\s request results in non-positive point size; set to 1");
- *x = 1;
- }
- return 1;
- }
- else {
- error("bad digit in point size");
- return 0;
- }
-}
-
-static symbol get_delim_name()
-{
- token start;
- start.next();
- if (start.eof()) {
- error("end of input at start of delimited name");
- return NULL_SYMBOL;
- }
- if (start.newline()) {
- error("can't delimit name with a newline");
- return NULL_SYMBOL;
- }
- int start_level = input_stack::get_level();
- char abuf[ABUF_SIZE];
- char *buf = abuf;
- int buf_size = ABUF_SIZE;
- int i = 0;
- for (;;) {
- if (i + 1 > buf_size) {
- if (buf == abuf) {
- buf = new char[ABUF_SIZE*2];
- memcpy(buf, abuf, buf_size);
- buf_size = ABUF_SIZE*2;
- }
- else {
- char *old_buf = buf;
- buf = new char[buf_size*2];
- memcpy(buf, old_buf, buf_size);
- buf_size *= 2;
- a_delete old_buf;
- }
- }
- tok.next();
- if (tok == start
- && (compatible_flag || input_stack::get_level() == start_level))
- break;
- if ((buf[i] = tok.ch()) == 0) {
- error("missing delimiter (got %1)", tok.description());
- if (buf != abuf)
- a_delete buf;
- return NULL_SYMBOL;
- }
- i++;
- }
- buf[i] = '\0';
- if (buf == abuf) {
- if (i == 0) {
- error("empty delimited name");
- return NULL_SYMBOL;
- }
- else
- return symbol(buf);
- }
- else {
- symbol s(buf);
- a_delete buf;
- return s;
- }
-}
-
-// Implement \R
-
-static void do_register()
-{
- token start;
- start.next();
- if (!start.delimiter(1))
- return;
- tok.next();
- symbol nm = get_long_name(1);
- if (nm.is_null())
- return;
- while (tok.space())
- tok.next();
- reg *r = (reg *)number_reg_dictionary.lookup(nm);
- int prev_value;
- if (!r || !r->get_value(&prev_value))
- prev_value = 0;
- int val;
- if (!get_number(&val, 'u', prev_value))
- return;
- if (start != tok)
- warning(WARN_DELIM, "closing delimiter does not match");
- if (r)
- r->set_value(val);
- else
- set_number_reg(nm, val);
-}
-
-// this implements the \w escape sequence
-
-static void do_width()
-{
- token start;
- start.next();
- int start_level = input_stack::get_level();
- environment env(curenv);
- environment *oldenv = curenv;
- curenv = &env;
- for (;;) {
- tok.next();
- if (tok.eof()) {
- warning(WARN_DELIM, "missing closing delimiter");
- break;
- }
- if (tok.newline()) {
- warning(WARN_DELIM, "missing closing delimiter");
- input_stack::push(make_temp_iterator("\n"));
- break;
- }
- if (tok == start
- && (compatible_flag || input_stack::get_level() == start_level))
- break;
- tok.process();
- }
- env.wrap_up_tab();
- units x = env.get_input_line_position().to_units();
- input_stack::push(make_temp_iterator(i_to_a(x)));
- env.width_registers();
- curenv = oldenv;
-}
-
-charinfo *page_character;
-
-void set_page_character()
-{
- page_character = get_optional_char();
- skip_line();
-}
-
-static const symbol percent_symbol("%");
-
-void read_title_parts(node **part, hunits *part_width)
-{
- tok.skip();
- if (tok.newline() || tok.eof())
- return;
- token start(tok);
- int start_level = input_stack::get_level();
- tok.next();
- for (int i = 0; i < 3; i++) {
- while (!tok.newline() && !tok.eof()) {
- if (tok == start
- && (compatible_flag || input_stack::get_level() == start_level)) {
- tok.next();
- break;
- }
- if (page_character != 0 && tok.get_char() == page_character)
- interpolate_number_reg(percent_symbol, 0);
- else
- tok.process();
- tok.next();
- }
- curenv->wrap_up_tab();
- part_width[i] = curenv->get_input_line_position();
- part[i] = curenv->extract_output_line();
- }
- while (!tok.newline() && !tok.eof())
- tok.next();
-}
-
-class non_interpreted_node : public node {
- macro mac;
-public:
- non_interpreted_node(const macro &);
- int interpret(macro *);
- node *copy();
- int same(node *);
- const char *type();
- int force_tprint();
-};
-
-non_interpreted_node::non_interpreted_node(const macro &m) : mac(m)
-{
-}
-
-int non_interpreted_node::same(node *nd)
-{
- return mac == ((non_interpreted_node *)nd)->mac;
-}
-
-const char *non_interpreted_node::type()
-{
- return "non_interpreted_node";
-}
-
-int non_interpreted_node::force_tprint()
-{
- return 0;
-}
-
-node *non_interpreted_node::copy()
-{
- return new non_interpreted_node(mac);
-}
-
-int non_interpreted_node::interpret(macro *m)
-{
- string_iterator si(mac);
- node *n;
- for (;;) {
- int c = si.get(&n);
- if (c == EOF)
- break;
- if (c == 0)
- m->append(n);
- else
- m->append(c);
- }
- return 1;
-}
-
-static node *do_non_interpreted()
-{
- node *n;
- int c;
- macro mac;
- while ((c = get_copy(&n)) != ESCAPE_QUESTION && c != EOF && c != '\n')
- if (c == 0)
- mac.append(n);
- else
- mac.append(c);
- if (c == EOF || c == '\n') {
- error("missing \\?");
- return 0;
- }
- return new non_interpreted_node(mac);
-}
-
-static void encode_char(macro *mac, char c)
-{
- if (c == '\0') {
- if ((font::use_charnames_in_special) && tok.special()) {
- charinfo *ci = tok.get_char(1);
- const char *s = ci->get_symbol()->contents();
- if (s[0] != (char)0) {
- mac->append('\\');
- mac->append('(');
- int i = 0;
- while (s[i] != (char)0) {
- mac->append(s[i]);
- i++;
- }
- mac->append('\\');
- mac->append(')');
- }
- }
- else if (tok.stretchable_space()
- || tok.unstretchable_space())
- mac->append(' ');
- else if (!(tok.hyphen_indicator()
- || tok.dummy()
- || tok.transparent_dummy()
- || tok.zero_width_break()))
- error("%1 is invalid within \\X", tok.description());
- }
- else {
- if ((font::use_charnames_in_special) && (c == '\\')) {
- /*
- * add escape escape sequence
- */
- mac->append(c);
- }
- mac->append(c);
- }
-}
-
-node *do_special()
-{
- token start;
- start.next();
- int start_level = input_stack::get_level();
- macro mac;
- for (tok.next();
- tok != start || input_stack::get_level() != start_level;
- tok.next()) {
- if (tok.eof()) {
- warning(WARN_DELIM, "missing closing delimiter");
- return 0;
- }
- if (tok.newline()) {
- input_stack::push(make_temp_iterator("\n"));
- warning(WARN_DELIM, "missing closing delimiter");
- break;
- }
- unsigned char c;
- if (tok.space())
- c = ' ';
- else if (tok.tab())
- c = '\t';
- else if (tok.leader())
- c = '\001';
- else if (tok.backspace())
- c = '\b';
- else
- c = tok.ch();
- encode_char(&mac, c);
- }
- return new special_node(mac);
-}
-
-void output_request()
-{
- if (!tok.newline() && !tok.eof()) {
- int c;
- for (;;) {
- c = get_copy(0);
- if (c == '"') {
- c = get_copy(0);
- break;
- }
- if (c != ' ' && c != '\t')
- break;
- }
- for (; c != '\n' && c != EOF; c = get_copy(0))
- topdiv->transparent_output(c);
- topdiv->transparent_output('\n');
- }
- tok.next();
-}
-
-extern int image_no; // from node.cc
-
-static node *do_suppress(symbol nm)
-{
- if (nm.is_null() || nm.is_empty()) {
- error("expecting an argument to escape \\O");
- return 0;
- }
- const char *s = nm.contents();
- switch (*s) {
- case '0':
- if (begin_level == 0)
- // suppress generation of glyphs
- return new suppress_node(0, 0);
- break;
- case '1':
- if (begin_level == 0)
- // enable generation of glyphs
- return new suppress_node(1, 0);
- break;
- case '2':
- if (begin_level == 0)
- return new suppress_node(1, 1);
- break;
- case '3':
- begin_level++;
- break;
- case '4':
- begin_level--;
- break;
- case '5':
- {
- s++; // move over '5'
- char position = *s;
- if (*s == (char)0) {
- error("missing position and filename in \\O");
- return 0;
- }
- if (!(position == 'l'
- || position == 'r'
- || position == 'c'
- || position == 'i')) {
- error("l, r, c, or i position expected (got %1 in \\O)", position);
- return 0;
- }
- s++; // onto image name
- if (s == (char *)0) {
- error("missing image name for \\O");
- return 0;
- }
- image_no++;
- if (begin_level == 0)
- return new suppress_node(symbol(s), position, image_no);
- }
- break;
- default:
- error("`%1' is an invalid argument to \\O", *s);
- }
- return 0;
-}
-
-void special_node::tprint(troff_output_file *out)
-{
- tprint_start(out);
- string_iterator iter(mac);
- for (;;) {
- int c = iter.get(0);
- if (c == EOF)
- break;
- for (const char *s = ::asciify(c); *s; s++)
- tprint_char(out, *s);
- }
- tprint_end(out);
-}
-
-int get_file_line(const char **filename, int *lineno)
-{
- return input_stack::get_location(0, filename, lineno);
-}
-
-void line_file()
-{
- int n;
- if (get_integer(&n)) {
- const char *filename = 0;
- if (has_arg()) {
- symbol s = get_long_name();
- filename = s.contents();
- }
- (void)input_stack::set_location(filename, n-1);
- }
- skip_line();
-}
-
-static int nroff_mode = 0;
-
-static void nroff_request()
-{
- nroff_mode = 1;
- skip_line();
-}
-
-static void troff_request()
-{
- nroff_mode = 0;
- skip_line();
-}
-
-static void skip_alternative()
-{
- int level = 0;
- // ensure that ``.if 0\{'' works as expected
- if (tok.left_brace())
- level++;
- int c;
- for (;;) {
- c = input_stack::get(0);
- if (c == EOF)
- break;
- if (c == ESCAPE_LEFT_BRACE)
- ++level;
- else if (c == ESCAPE_RIGHT_BRACE)
- --level;
- else if (c == escape_char && escape_char > 0)
- switch(input_stack::get(0)) {
- case '{':
- ++level;
- break;
- case '}':
- --level;
- break;
- case '"':
- while ((c = input_stack::get(0)) != '\n' && c != EOF)
- ;
- }
- /*
- Note that the level can properly be < 0, eg
-
- .if 1 \{\
- .if 0 \{\
- .\}\}
-
- So don't give an error message in this case.
- */
- if (level <= 0 && c == '\n')
- break;
- }
- tok.next();
-}
-
-static void begin_alternative()
-{
- while (tok.space() || tok.left_brace())
- tok.next();
-}
-
-void nop_request()
-{
- while (tok.space())
- tok.next();
-}
-
-static int_stack if_else_stack;
-
-int do_if_request()
-{
- int invert = 0;
- while (tok.space())
- tok.next();
- while (tok.ch() == '!') {
- tok.next();
- invert = !invert;
- }
- int result;
- unsigned char c = tok.ch();
- if (c == 't') {
- tok.next();
- result = !nroff_mode;
- }
- else if (c == 'n') {
- tok.next();
- result = nroff_mode;
- }
- else if (c == 'v') {
- tok.next();
- result = 0;
- }
- else if (c == 'o') {
- result = (topdiv->get_page_number() & 1);
- tok.next();
- }
- else if (c == 'e') {
- result = !(topdiv->get_page_number() & 1);
- tok.next();
- }
- else if (c == 'd' || c == 'r') {
- tok.next();
- symbol nm = get_name(1);
- if (nm.is_null()) {
- skip_alternative();
- return 0;
- }
- result = (c == 'd'
- ? request_dictionary.lookup(nm) != 0
- : number_reg_dictionary.lookup(nm) != 0);
- }
- else if (c == 'm') {
- tok.next();
- symbol nm = get_long_name(1);
- if (nm.is_null()) {
- skip_alternative();
- return 0;
- }
- result = (nm == default_symbol
- || color_dictionary.lookup(nm) != 0);
- }
- else if (c == 'c') {
- tok.next();
- tok.skip();
- charinfo *ci = tok.get_char(1);
- if (ci == 0) {
- skip_alternative();
- return 0;
- }
- result = character_exists(ci, curenv);
- tok.next();
- }
- else if (tok.space())
- result = 0;
- else if (tok.delimiter()) {
- token delim = tok;
- int delim_level = input_stack::get_level();
- environment env1(curenv);
- environment env2(curenv);
- environment *oldenv = curenv;
- curenv = &env1;
- for (int i = 0; i < 2; i++) {
- for (;;) {
- tok.next();
- if (tok.newline() || tok.eof()) {
- warning(WARN_DELIM, "missing closing delimiter");
- tok.next();
- curenv = oldenv;
- return 0;
- }
- if (tok == delim
- && (compatible_flag || input_stack::get_level() == delim_level))
- break;
- tok.process();
- }
- curenv = &env2;
- }
- node *n1 = env1.extract_output_line();
- node *n2 = env2.extract_output_line();
- result = same_node_list(n1, n2);
- delete_node_list(n1);
- delete_node_list(n2);
- curenv = oldenv;
- tok.next();
- }
- else {
- units n;
- if (!get_number(&n, 'u')) {
- skip_alternative();
- return 0;
- }
- else
- result = n > 0;
- }
- if (invert)
- result = !result;
- if (result)
- begin_alternative();
- else
- skip_alternative();
- return result;
-}
-
-void if_else_request()
-{
- if_else_stack.push(do_if_request());
-}
-
-void if_request()
-{
- do_if_request();
-}
-
-void else_request()
-{
- if (if_else_stack.is_empty()) {
- warning(WARN_EL, "unbalanced .el request");
- skip_alternative();
- }
- else {
- if (if_else_stack.pop())
- skip_alternative();
- else
- begin_alternative();
- }
-}
-
-static int while_depth = 0;
-static int while_break_flag = 0;
-
-void while_request()
-{
- macro mac;
- int escaped = 0;
- int level = 0;
- mac.append(new token_node(tok));
- for (;;) {
- node *n;
- int c = input_stack::get(&n);
- if (c == EOF)
- break;
- if (c == 0) {
- escaped = 0;
- mac.append(n);
- }
- else if (escaped) {
- if (c == '{')
- level += 1;
- else if (c == '}')
- level -= 1;
- escaped = 0;
- mac.append(c);
- }
- else {
- if (c == ESCAPE_LEFT_BRACE)
- level += 1;
- else if (c == ESCAPE_RIGHT_BRACE)
- level -= 1;
- else if (c == escape_char)
- escaped = 1;
- mac.append(c);
- if (c == '\n' && level <= 0)
- break;
- }
- }
- if (level != 0)
- error("unbalanced \\{ \\}");
- else {
- while_depth++;
- input_stack::add_boundary();
- for (;;) {
- input_stack::push(new string_iterator(mac, "while loop"));
- tok.next();
- if (!do_if_request()) {
- while (input_stack::get(0) != EOF)
- ;
- break;
- }
- process_input_stack();
- if (while_break_flag || input_stack::is_return_boundary()) {
- while_break_flag = 0;
- break;
- }
- }
- input_stack::remove_boundary();
- while_depth--;
- }
- tok.next();
-}
-
-void while_break_request()
-{
- if (!while_depth) {
- error("no while loop");
- skip_line();
- }
- else {
- while_break_flag = 1;
- while (input_stack::get(0) != EOF)
- ;
- tok.next();
- }
-}
-
-void while_continue_request()
-{
- if (!while_depth) {
- error("no while loop");
- skip_line();
- }
- else {
- while (input_stack::get(0) != EOF)
- ;
- tok.next();
- }
-}
-
-// .so
-
-void source()
-{
- symbol nm = get_long_name(1);
- if (nm.is_null())
- skip_line();
- else {
- while (!tok.newline() && !tok.eof())
- tok.next();
- errno = 0;
- FILE *fp = fopen(nm.contents(), "r");
- if (fp)
- input_stack::push(new file_iterator(fp, nm.contents()));
- else
- error("can't open `%1': %2", nm.contents(), strerror(errno));
- tok.next();
- }
-}
-
-// like .so but use popen()
-
-void pipe_source()
-{
- if (safer_flag) {
- error(".pso request not allowed in safer mode");
- skip_line();
- }
- else {
-#ifdef POPEN_MISSING
- error("pipes not available on this system");
- skip_line();
-#else /* not POPEN_MISSING */
- if (tok.newline() || tok.eof())
- error("missing command");
- else {
- int c;
- while ((c = get_copy(0)) == ' ' || c == '\t')
- ;
- int buf_size = 24;
- char *buf = new char[buf_size];
- int buf_used = 0;
- for (; c != '\n' && c != EOF; c = get_copy(0)) {
- const char *s = asciify(c);
- int slen = strlen(s);
- if (buf_used + slen + 1> buf_size) {
- char *old_buf = buf;
- int old_buf_size = buf_size;
- buf_size *= 2;
- buf = new char[buf_size];
- memcpy(buf, old_buf, old_buf_size);
- a_delete old_buf;
- }
- strcpy(buf + buf_used, s);
- buf_used += slen;
- }
- buf[buf_used] = '\0';
- errno = 0;
- FILE *fp = popen(buf, POPEN_RT);
- if (fp)
- input_stack::push(new file_iterator(fp, symbol(buf).contents(), 1));
- else
- error("can't open pipe to process `%1': %2", buf, strerror(errno));
- a_delete buf;
- }
- tok.next();
-#endif /* not POPEN_MISSING */
- }
-}
-
-// .psbb
-
-static int llx_reg_contents = 0;
-static int lly_reg_contents = 0;
-static int urx_reg_contents = 0;
-static int ury_reg_contents = 0;
-
-struct bounding_box {
- int llx, lly, urx, ury;
-};
-
-/* Parse the argument to a %%BoundingBox comment. Return 1 if it
-contains 4 numbers, 2 if it contains (atend), 0 otherwise. */
-
-int parse_bounding_box(char *p, bounding_box *bb)
-{
- if (sscanf(p, "%d %d %d %d",
- &bb->llx, &bb->lly, &bb->urx, &bb->ury) == 4)
- return 1;
- else {
- /* The Document Structuring Conventions say that the numbers
- should be integers. Unfortunately some broken applications
- get this wrong. */
- double x1, x2, x3, x4;
- if (sscanf(p, "%lf %lf %lf %lf", &x1, &x2, &x3, &x4) == 4) {
- bb->llx = (int)x1;
- bb->lly = (int)x2;
- bb->urx = (int)x3;
- bb->ury = (int)x4;
- return 1;
- }
- else {
- for (; *p == ' ' || *p == '\t'; p++)
- ;
- if (strncmp(p, "(atend)", 7) == 0) {
- return 2;
- }
- }
- }
- bb->llx = bb->lly = bb->urx = bb->ury = 0;
- return 0;
-}
-
-// This version is taken from psrm.cc
-
-#define PS_LINE_MAX 255
-cset white_space("\n\r \t");
-
-int ps_get_line(char *buf, FILE *fp, const char* filename)
-{
- int c = getc(fp);
- if (c == EOF) {
- buf[0] = '\0';
- return 0;
- }
- int i = 0;
- int err = 0;
- while (c != '\r' && c != '\n' && c != EOF) {
- if ((c < 0x1b && !white_space(c)) || c == 0x7f)
- error("invalid input character code %1 in `%2'", int(c), filename);
- else if (i < PS_LINE_MAX)
- buf[i++] = c;
- else if (!err) {
- err = 1;
- error("PostScript file `%1' is non-conforming "
- "because length of line exceeds 255", filename);
- }
- c = getc(fp);
- }
- buf[i++] = '\n';
- buf[i] = '\0';
- if (c == '\r') {
- c = getc(fp);
- if (c != EOF && c != '\n')
- ungetc(c, fp);
- }
- return 1;
-}
-
-inline void assign_registers(int llx, int lly, int urx, int ury)
-{
- llx_reg_contents = llx;
- lly_reg_contents = lly;
- urx_reg_contents = urx;
- ury_reg_contents = ury;
-}
-
-void do_ps_file(FILE *fp, const char* filename)
-{
- bounding_box bb;
- int bb_at_end = 0;
- char buf[PS_LINE_MAX];
- llx_reg_contents = lly_reg_contents =
- urx_reg_contents = ury_reg_contents = 0;
- if (!ps_get_line(buf, fp, filename)) {
- error("`%1' is empty", filename);
- return;
- }
- if (strncmp("%!PS-Adobe-", buf, 11) != 0) {
- error("`%1' is not conforming to the Document Structuring Conventions",
- filename);
- return;
- }
- while (ps_get_line(buf, fp, filename) != 0) {
- if (buf[0] != '%' || buf[1] != '%'
- || strncmp(buf + 2, "EndComments", 11) == 0)
- break;
- if (strncmp(buf + 2, "BoundingBox:", 12) == 0) {
- int res = parse_bounding_box(buf + 14, &bb);
- if (res == 1) {
- assign_registers(bb.llx, bb.lly, bb.urx, bb.ury);
- return;
- }
- else if (res == 2) {
- bb_at_end = 1;
- break;
- }
- else {
- error("the arguments to the %%%%BoundingBox comment in `%1' are bad",
- filename);
- return;
- }
- }
- }
- if (bb_at_end) {
- long offset;
- int last_try = 0;
- /* in the trailer, the last BoundingBox comment is significant */
- for (offset = 512; !last_try; offset *= 2) {
- int had_trailer = 0;
- int got_bb = 0;
- if (offset > 32768 || fseek(fp, -offset, 2) == -1) {
- last_try = 1;
- if (fseek(fp, 0L, 0) == -1)
- break;
- }
- while (ps_get_line(buf, fp, filename) != 0) {
- if (buf[0] == '%' && buf[1] == '%') {
- if (!had_trailer) {
- if (strncmp(buf + 2, "Trailer", 7) == 0)
- had_trailer = 1;
- }
- else {
- if (strncmp(buf + 2, "BoundingBox:", 12) == 0) {
- int res = parse_bounding_box(buf + 14, &bb);
- if (res == 1)
- got_bb = 1;
- else if (res == 2) {
- error("`(atend)' not allowed in trailer of `%1'", filename);
- return;
- }
- else {
- error("the arguments to the %%%%BoundingBox comment in `%1' are bad",
- filename);
- return;
- }
- }
- }
- }
- }
- if (got_bb) {
- assign_registers(bb.llx, bb.lly, bb.urx, bb.ury);
- return;
- }
- }
- }
- error("%%%%BoundingBox comment not found in `%1'", filename);
-}
-
-void ps_bbox_request()
-{
- symbol nm = get_long_name(1);
- if (nm.is_null())
- skip_line();
- else {
- while (!tok.newline() && !tok.eof())
- tok.next();
- errno = 0;
- // PS files might contain non-printable characters, such as ^Z
- // and CRs not followed by an LF, so open them in binary mode.
- FILE *fp = fopen(nm.contents(), FOPEN_RB);
- if (fp) {
- do_ps_file(fp, nm.contents());
- fclose(fp);
- }
- else
- error("can't open `%1': %2", nm.contents(), strerror(errno));
- tok.next();
- }
-}
-
-const char *asciify(int c)
-{
- static char buf[3];
- buf[0] = escape_char == '\0' ? '\\' : escape_char;
- buf[1] = buf[2] = '\0';
- switch (c) {
- case ESCAPE_QUESTION:
- buf[1] = '?';
- break;
- case ESCAPE_AMPERSAND:
- buf[1] = '&';
- break;
- case ESCAPE_RIGHT_PARENTHESIS:
- buf[1] = ')';
- break;
- case ESCAPE_UNDERSCORE:
- buf[1] = '_';
- break;
- case ESCAPE_BAR:
- buf[1] = '|';
- break;
- case ESCAPE_CIRCUMFLEX:
- buf[1] = '^';
- break;
- case ESCAPE_LEFT_BRACE:
- buf[1] = '{';
- break;
- case ESCAPE_RIGHT_BRACE:
- buf[1] = '}';
- break;
- case ESCAPE_LEFT_QUOTE:
- buf[1] = '`';
- break;
- case ESCAPE_RIGHT_QUOTE:
- buf[1] = '\'';
- break;
- case ESCAPE_HYPHEN:
- buf[1] = '-';
- break;
- case ESCAPE_BANG:
- buf[1] = '!';
- break;
- case ESCAPE_c:
- buf[1] = 'c';
- break;
- case ESCAPE_e:
- buf[1] = 'e';
- break;
- case ESCAPE_E:
- buf[1] = 'E';
- break;
- case ESCAPE_PERCENT:
- buf[1] = '%';
- break;
- case ESCAPE_SPACE:
- buf[1] = ' ';
- break;
- case ESCAPE_TILDE:
- buf[1] = '~';
- break;
- case ESCAPE_COLON:
- buf[1] = ':';
- break;
- case COMPATIBLE_SAVE:
- case COMPATIBLE_RESTORE:
- buf[0] = '\0';
- break;
- default:
- if (invalid_input_char(c))
- buf[0] = '\0';
- else
- buf[0] = c;
- break;
- }
- return buf;
-}
-
-const char *input_char_description(int c)
-{
- switch (c) {
- case '\n':
- return "a newline character";
- case '\b':
- return "a backspace character";
- case '\001':
- return "a leader character";
- case '\t':
- return "a tab character";
- case ' ':
- return "a space character";
- case '\0':
- return "a node";
- }
- static char buf[sizeof("magic character code ") + 1 + INT_DIGITS];
- if (invalid_input_char(c)) {
- const char *s = asciify(c);
- if (*s) {
- buf[0] = '`';
- strcpy(buf + 1, s);
- strcat(buf, "'");
- return buf;
- }
- sprintf(buf, "magic character code %d", c);
- return buf;
- }
- if (csprint(c)) {
- buf[0] = '`';
- buf[1] = c;
- buf[2] = '\'';
- return buf;
- }
- sprintf(buf, "character code %d", c);
- return buf;
-}
-
-// .tm, .tm1, and .tmc
-
-void do_terminal(int newline, int string_like)
-{
- if (!tok.newline() && !tok.eof()) {
- int c;
- for (;;) {
- c = get_copy(0);
- if (string_like && c == '"') {
- c = get_copy(0);
- break;
- }
- if (c != ' ' && c != '\t')
- break;
- }
- for (; c != '\n' && c != EOF; c = get_copy(0))
- fputs(asciify(c), stderr);
- }
- if (newline)
- fputc('\n', stderr);
- fflush(stderr);
- tok.next();
-}
-
-void terminal()
-{
- do_terminal(1, 0);
-}
-
-void terminal1()
-{
- do_terminal(1, 1);
-}
-
-void terminal_continue()
-{
- do_terminal(0, 1);
-}
-
-dictionary stream_dictionary(20);
-
-void do_open(int append)
-{
- symbol stream = get_name(1);
- if (!stream.is_null()) {
- symbol filename = get_long_name(1);
- if (!filename.is_null()) {
- errno = 0;
- FILE *fp = fopen(filename.contents(), append ? "a" : "w");
- if (!fp) {
- error("can't open `%1' for %2: %3",
- filename.contents(),
- append ? "appending" : "writing",
- strerror(errno));
- fp = (FILE *)stream_dictionary.remove(stream);
- }
- else
- fp = (FILE *)stream_dictionary.lookup(stream, fp);
- if (fp)
- fclose(fp);
- }
- }
- skip_line();
-}
-
-void open_request()
-{
- if (safer_flag) {
- error(".open request not allowed in safer mode");
- skip_line();
- }
- else
- do_open(0);
-}
-
-void opena_request()
-{
- if (safer_flag) {
- error(".opena request not allowed in safer mode");
- skip_line();
- }
- else
- do_open(1);
-}
-
-void close_request()
-{
- symbol stream = get_name(1);
- if (!stream.is_null()) {
- FILE *fp = (FILE *)stream_dictionary.remove(stream);
- if (!fp)
- error("no stream named `%1'", stream.contents());
- else
- fclose(fp);
- }
- skip_line();
-}
-
-// .write and .writec
-
-void do_write_request(int newline)
-{
- symbol stream = get_name(1);
- if (stream.is_null()) {
- skip_line();
- return;
- }
- FILE *fp = (FILE *)stream_dictionary.lookup(stream);
- if (!fp) {
- error("no stream named `%1'", stream.contents());
- skip_line();
- return;
- }
- int c;
- while ((c = get_copy(0)) == ' ')
- ;
- if (c == '"')
- c = get_copy(0);
- for (; c != '\n' && c != EOF; c = get_copy(0))
- fputs(asciify(c), fp);
- if (newline)
- fputc('\n', fp);
- fflush(fp);
- tok.next();
-}
-
-void write_request()
-{
- do_write_request(1);
-}
-
-void write_request_continue()
-{
- do_write_request(0);
-}
-
-void write_macro_request()
-{
- symbol stream = get_name(1);
- if (stream.is_null()) {
- skip_line();
- return;
- }
- FILE *fp = (FILE *)stream_dictionary.lookup(stream);
- if (!fp) {
- error("no stream named `%1'", stream.contents());
- skip_line();
- return;
- }
- symbol s = get_name(1);
- if (s.is_null()) {
- skip_line();
- return;
- }
- request_or_macro *p = lookup_request(s);
- macro *m = p->to_macro();
- if (!m)
- error("cannot write request");
- else {
- string_iterator iter(*m);
- for (;;) {
- int c = iter.get(0);
- if (c == EOF)
- break;
- fputs(asciify(c), fp);
- }
- fflush(fp);
- }
- skip_line();
-}
-
-void warnscale_request()
-{
- if (has_arg()) {
- char c = tok.ch();
- if (c == 'u')
- warn_scale = 1.0;
- else if (c == 'i')
- warn_scale = (double)units_per_inch;
- else if (c == 'c')
- warn_scale = (double)units_per_inch / 2.54;
- else if (c == 'p')
- warn_scale = (double)units_per_inch / 72.0;
- else if (c == 'P')
- warn_scale = (double)units_per_inch / 6.0;
- else {
- warning(WARN_SCALE,
- "invalid scaling indicator `%1', using `i' instead", c);
- c = 'i';
- }
- warn_scaling_indicator = c;
- }
- skip_line();
-}
-
-void spreadwarn_request()
-{
- hunits n;
- if (has_arg() && get_hunits(&n, 'm')) {
- if (n < 0)
- n = 0;
- hunits em = curenv->get_size();
- spread_limit = (double)n.to_units()
- / (em.is_zero() ? hresolution : em.to_units());
- }
- else
- spread_limit = -spread_limit - 1; // no arg toggles on/off without
- // changing value; we mirror at
- // -0.5 to make zero a valid value
- skip_line();
-}
-
-static void init_charset_table()
-{
- char buf[16];
- strcpy(buf, "char");
- for (int i = 0; i < 256; i++) {
- strcpy(buf + 4, i_to_a(i));
- charset_table[i] = get_charinfo(symbol(buf));
- charset_table[i]->set_ascii_code(i);
- if (csalpha(i))
- charset_table[i]->set_hyphenation_code(cmlower(i));
- }
- charset_table['.']->set_flags(charinfo::ENDS_SENTENCE);
- charset_table['?']->set_flags(charinfo::ENDS_SENTENCE);
- charset_table['!']->set_flags(charinfo::ENDS_SENTENCE);
- charset_table['-']->set_flags(charinfo::BREAK_AFTER);
- charset_table['"']->set_flags(charinfo::TRANSPARENT);
- charset_table['\'']->set_flags(charinfo::TRANSPARENT);
- charset_table[')']->set_flags(charinfo::TRANSPARENT);
- charset_table[']']->set_flags(charinfo::TRANSPARENT);
- charset_table['*']->set_flags(charinfo::TRANSPARENT);
- get_charinfo(symbol("dg"))->set_flags(charinfo::TRANSPARENT);
- get_charinfo(symbol("rq"))->set_flags(charinfo::TRANSPARENT);
- get_charinfo(symbol("em"))->set_flags(charinfo::BREAK_AFTER);
- get_charinfo(symbol("ul"))->set_flags(charinfo::OVERLAPS_HORIZONTALLY);
- get_charinfo(symbol("rn"))->set_flags(charinfo::OVERLAPS_HORIZONTALLY);
- get_charinfo(symbol("radicalex"))->set_flags(charinfo::OVERLAPS_HORIZONTALLY);
- get_charinfo(symbol("ru"))->set_flags(charinfo::OVERLAPS_HORIZONTALLY);
- get_charinfo(symbol("br"))->set_flags(charinfo::OVERLAPS_VERTICALLY);
- page_character = charset_table['%'];
-}
-
-static void init_hpf_code_table()
-{
- for (int i = 0; i < 256; i++)
- hpf_code_table[i] = i;
-}
-
-static void do_translate(int translate_transparent, int translate_input)
-{
- tok.skip();
- while (!tok.newline() && !tok.eof()) {
- if (tok.space()) {
- // This is a really bizarre troff feature.
- tok.next();
- translate_space_to_dummy = tok.dummy();
- if (tok.newline() || tok.eof())
- break;
- tok.next();
- continue;
- }
- charinfo *ci1 = tok.get_char(1);
- if (ci1 == 0)
- break;
- tok.next();
- if (tok.newline() || tok.eof()) {
- ci1->set_special_translation(charinfo::TRANSLATE_SPACE,
- translate_transparent);
- break;
- }
- if (tok.space())
- ci1->set_special_translation(charinfo::TRANSLATE_SPACE,
- translate_transparent);
- else if (tok.stretchable_space())
- ci1->set_special_translation(charinfo::TRANSLATE_STRETCHABLE_SPACE,
- translate_transparent);
- else if (tok.dummy())
- ci1->set_special_translation(charinfo::TRANSLATE_DUMMY,
- translate_transparent);
- else if (tok.hyphen_indicator())
- ci1->set_special_translation(charinfo::TRANSLATE_HYPHEN_INDICATOR,
- translate_transparent);
- else {
- charinfo *ci2 = tok.get_char(1);
- if (ci2 == 0)
- break;
- if (ci1 == ci2)
- ci1->set_translation(0, translate_transparent, translate_input);
- else
- ci1->set_translation(ci2, translate_transparent, translate_input);
- }
- tok.next();
- }
- skip_line();
-}
-
-void translate()
-{
- do_translate(1, 0);
-}
-
-void translate_no_transparent()
-{
- do_translate(0, 0);
-}
-
-void translate_input()
-{
- do_translate(1, 1);
-}
-
-void char_flags()
-{
- int flags;
- if (get_integer(&flags))
- while (has_arg()) {
- charinfo *ci = tok.get_char(1);
- if (ci) {
- charinfo *tem = ci->get_translation();
- if (tem)
- ci = tem;
- ci->set_flags(flags);
- }
- tok.next();
- }
- skip_line();
-}
-
-void hyphenation_code()
-{
- tok.skip();
- while (!tok.newline() && !tok.eof()) {
- charinfo *ci = tok.get_char(1);
- if (ci == 0)
- break;
- tok.next();
- tok.skip();
- unsigned char c = tok.ch();
- if (c == 0) {
- error("hyphenation code must be ordinary character");
- break;
- }
- if (csdigit(c)) {
- error("hyphenation code cannot be digit");
- break;
- }
- ci->set_hyphenation_code(c);
- if (ci->get_translation()
- && ci->get_translation()->get_translation_input())
- ci->get_translation()->set_hyphenation_code(c);
- tok.next();
- tok.skip();
- }
- skip_line();
-}
-
-void hyphenation_patterns_file_code()
-{
- tok.skip();
- while (!tok.newline() && !tok.eof()) {
- int n1, n2;
- if (get_integer(&n1) && (0 <= n1 && n1 <= 255)) {
- if (!has_arg()) {
- error("missing output hyphenation code");
- break;
- }
- if (get_integer(&n2) && (0 <= n2 && n2 <= 255)) {
- hpf_code_table[n1] = n2;
- tok.skip();
- }
- else {
- error("output hyphenation code must be integer in the range 0..255");
- break;
- }
- }
- else {
- error("input hyphenation code must be integer in the range 0..255");
- break;
- }
- }
- skip_line();
-}
-
-charinfo *token::get_char(int required)
-{
- if (type == TOKEN_CHAR)
- return charset_table[c];
- if (type == TOKEN_SPECIAL)
- return get_charinfo(nm);
- if (type == TOKEN_NUMBERED_CHAR)
- return get_charinfo_by_number(val);
- if (type == TOKEN_ESCAPE) {
- if (escape_char != 0)
- return charset_table[escape_char];
- else {
- error("`\\e' used while no current escape character");
- return 0;
- }
- }
- if (required) {
- if (type == TOKEN_EOF || type == TOKEN_NEWLINE)
- warning(WARN_MISSING, "missing normal or special character");
- else
- error("normal or special character expected (got %1)", description());
- }
- return 0;
-}
-
-charinfo *get_optional_char()
-{
- while (tok.space())
- tok.next();
- charinfo *ci = tok.get_char();
- if (!ci)
- check_missing_character();
- else
- tok.next();
- return ci;
-}
-
-void check_missing_character()
-{
- if (!tok.newline() && !tok.eof() && !tok.right_brace() && !tok.tab())
- error("normal or special character expected (got %1): "
- "treated as missing",
- tok.description());
-}
-
-// this is for \Z
-
-int token::add_to_node_list(node **pp)
-{
- hunits w;
- int s;
- node *n = 0;
- switch (type) {
- case TOKEN_CHAR:
- *pp = (*pp)->add_char(charset_table[c], curenv, &w, &s);
- break;
- case TOKEN_DUMMY:
- n = new dummy_node;
- break;
- case TOKEN_ESCAPE:
- if (escape_char != 0)
- *pp = (*pp)->add_char(charset_table[escape_char], curenv, &w, &s);
- break;
- case TOKEN_HYPHEN_INDICATOR:
- *pp = (*pp)->add_discretionary_hyphen();
- break;
- case TOKEN_ITALIC_CORRECTION:
- *pp = (*pp)->add_italic_correction(&w);
- break;
- case TOKEN_LEFT_BRACE:
- break;
- case TOKEN_MARK_INPUT:
- set_number_reg(nm, curenv->get_input_line_position().to_units());
- break;
- case TOKEN_NODE:
- n = nd;
- nd = 0;
- break;
- case TOKEN_NUMBERED_CHAR:
- *pp = (*pp)->add_char(get_charinfo_by_number(val), curenv, &w, &s);
- break;
- case TOKEN_RIGHT_BRACE:
- break;
- case TOKEN_SPACE:
- n = new hmotion_node(curenv->get_space_width(),
- curenv->get_fill_color());
- break;
- case TOKEN_SPECIAL:
- *pp = (*pp)->add_char(get_charinfo(nm), curenv, &w, &s);
- break;
- case TOKEN_STRETCHABLE_SPACE:
- n = new unbreakable_space_node(curenv->get_space_width(),
- curenv->get_fill_color());
- break;
- case TOKEN_UNSTRETCHABLE_SPACE:
- n = new space_char_hmotion_node(curenv->get_space_width(),
- curenv->get_fill_color());
- break;
- case TOKEN_TRANSPARENT_DUMMY:
- n = new transparent_dummy_node;
- break;
- case TOKEN_ZERO_WIDTH_BREAK:
- n = new space_node(H0, curenv->get_fill_color());
- n->freeze_space();
- n->is_escape_colon();
- break;
- default:
- return 0;
- }
- if (n) {
- n->next = *pp;
- *pp = n;
- }
- return 1;
-}
-
-void token::process()
-{
- if (possibly_handle_first_page_transition())
- return;
- switch (type) {
- case TOKEN_BACKSPACE:
- curenv->add_node(new hmotion_node(-curenv->get_space_width(),
- curenv->get_fill_color()));
- break;
- case TOKEN_CHAR:
- curenv->add_char(charset_table[c]);
- break;
- case TOKEN_DUMMY:
- curenv->add_node(new dummy_node);
- break;
- case TOKEN_EMPTY:
- assert(0);
- break;
- case TOKEN_EOF:
- assert(0);
- break;
- case TOKEN_ESCAPE:
- if (escape_char != 0)
- curenv->add_char(charset_table[escape_char]);
- break;
- case TOKEN_BEGIN_TRAP:
- case TOKEN_END_TRAP:
- case TOKEN_PAGE_EJECTOR:
- // these are all handled in process_input_stack()
- break;
- case TOKEN_HYPHEN_INDICATOR:
- curenv->add_hyphen_indicator();
- break;
- case TOKEN_INTERRUPT:
- curenv->interrupt();
- break;
- case TOKEN_ITALIC_CORRECTION:
- curenv->add_italic_correction();
- break;
- case TOKEN_LEADER:
- curenv->handle_tab(1);
- break;
- case TOKEN_LEFT_BRACE:
- break;
- case TOKEN_MARK_INPUT:
- set_number_reg(nm, curenv->get_input_line_position().to_units());
- break;
- case TOKEN_NEWLINE:
- curenv->newline();
- break;
- case TOKEN_NODE:
- curenv->add_node(nd);
- nd = 0;
- break;
- case TOKEN_NUMBERED_CHAR:
- curenv->add_char(get_charinfo_by_number(val));
- break;
- case TOKEN_REQUEST:
- // handled in process_input_stack()
- break;
- case TOKEN_RIGHT_BRACE:
- break;
- case TOKEN_SPACE:
- curenv->space();
- break;
- case TOKEN_SPECIAL:
- curenv->add_char(get_charinfo(nm));
- break;
- case TOKEN_SPREAD:
- curenv->spread();
- break;
- case TOKEN_STRETCHABLE_SPACE:
- curenv->add_node(new unbreakable_space_node(curenv->get_space_width(),
- curenv->get_fill_color()));
- break;
- case TOKEN_UNSTRETCHABLE_SPACE:
- curenv->add_node(new space_char_hmotion_node(curenv->get_space_width(),
- curenv->get_fill_color()));
- break;
- case TOKEN_TAB:
- curenv->handle_tab(0);
- break;
- case TOKEN_TRANSPARENT:
- break;
- case TOKEN_TRANSPARENT_DUMMY:
- curenv->add_node(new transparent_dummy_node);
- break;
- case TOKEN_ZERO_WIDTH_BREAK:
- {
- node *tmp = new space_node(H0, curenv->get_fill_color());
- tmp->freeze_space();
- tmp->is_escape_colon();
- curenv->add_node(tmp);
- break;
- }
- default:
- assert(0);
- }
-}
-
-class nargs_reg : public reg {
-public:
- const char *get_string();
-};
-
-const char *nargs_reg::get_string()
-{
- return i_to_a(input_stack::nargs());
-}
-
-class lineno_reg : public reg {
-public:
- const char *get_string();
-};
-
-const char *lineno_reg::get_string()
-{
- int line;
- const char *file;
- if (!input_stack::get_location(0, &file, &line))
- line = 0;
- return i_to_a(line);
-}
-
-class writable_lineno_reg : public general_reg {
-public:
- writable_lineno_reg();
- void set_value(units);
- int get_value(units *);
-};
-
-writable_lineno_reg::writable_lineno_reg()
-{
-}
-
-int writable_lineno_reg::get_value(units *res)
-{
- int line;
- const char *file;
- if (!input_stack::get_location(0, &file, &line))
- return 0;
- *res = line;
- return 1;
-}
-
-void writable_lineno_reg::set_value(units n)
-{
- input_stack::set_location(0, n);
-}
-
-class filename_reg : public reg {
-public:
- const char *get_string();
-};
-
-const char *filename_reg::get_string()
-{
- int line;
- const char *file;
- if (input_stack::get_location(0, &file, &line))
- return file;
- else
- return 0;
-}
-
-class constant_reg : public reg {
- const char *s;
-public:
- constant_reg(const char *);
- const char *get_string();
-};
-
-constant_reg::constant_reg(const char *p) : s(p)
-{
-}
-
-const char *constant_reg::get_string()
-{
- return s;
-}
-
-constant_int_reg::constant_int_reg(int *q) : p(q)
-{
-}
-
-const char *constant_int_reg::get_string()
-{
- return i_to_a(*p);
-}
-
-void abort_request()
-{
- int c;
- if (tok.eof())
- c = EOF;
- else if (tok.newline())
- c = '\n';
- else {
- while ((c = get_copy(0)) == ' ')
- ;
- }
- if (c == EOF || c == '\n')
- fputs("User Abort.", stderr);
- else {
- for (; c != '\n' && c != EOF; c = get_copy(0))
- fputs(asciify(c), stderr);
- }
- fputc('\n', stderr);
- cleanup_and_exit(1);
-}
-
-char *read_string()
-{
- int len = 256;
- char *s = new char[len];
- int c;
- while ((c = get_copy(0)) == ' ')
- ;
- int i = 0;
- while (c != '\n' && c != EOF) {
- if (!invalid_input_char(c)) {
- if (i + 2 > len) {
- char *tem = s;
- s = new char[len*2];
- memcpy(s, tem, len);
- len *= 2;
- a_delete tem;
- }
- s[i++] = c;
- }
- c = get_copy(0);
- }
- s[i] = '\0';
- tok.next();
- if (i == 0) {
- a_delete s;
- return 0;
- }
- return s;
-}
-
-void pipe_output()
-{
- if (safer_flag) {
- error(".pi request not allowed in safer mode");
- skip_line();
- }
- else {
-#ifdef POPEN_MISSING
- error("pipes not available on this system");
- skip_line();
-#else /* not POPEN_MISSING */
- if (the_output) {
- error("can't pipe: output already started");
- skip_line();
- }
- else {
- char *pc;
- if ((pc = read_string()) == 0)
- error("can't pipe to empty command");
- if (pipe_command) {
- char *s = new char[strlen(pipe_command) + strlen(pc) + 1 + 1];
- strcpy(s, pipe_command);
- strcat(s, "|");
- strcat(s, pc);
- a_delete pipe_command;
- a_delete pc;
- pipe_command = s;
- }
- else
- pipe_command = pc;
- }
-#endif /* not POPEN_MISSING */
- }
-}
-
-static int system_status;
-
-void system_request()
-{
- if (safer_flag) {
- error(".sy request not allowed in safer mode");
- skip_line();
- }
- else {
- char *command = read_string();
- if (!command)
- error("empty command");
- else {
- system_status = system(command);
- a_delete command;
- }
- }
-}
-
-void copy_file()
-{
- if (curdiv == topdiv && topdiv->before_first_page) {
- handle_initial_request(COPY_FILE_REQUEST);
- return;
- }
- symbol filename = get_long_name(1);
- while (!tok.newline() && !tok.eof())
- tok.next();
- if (break_flag)
- curenv->do_break();
- if (!filename.is_null())
- curdiv->copy_file(filename.contents());
- tok.next();
-}
-
-#ifdef COLUMN
-
-void vjustify()
-{
- if (curdiv == topdiv && topdiv->before_first_page) {
- handle_initial_request(VJUSTIFY_REQUEST);
- return;
- }
- symbol type = get_long_name(1);
- if (!type.is_null())
- curdiv->vjustify(type);
- skip_line();
-}
-
-#endif /* COLUMN */
-
-void transparent_file()
-{
- if (curdiv == topdiv && topdiv->before_first_page) {
- handle_initial_request(TRANSPARENT_FILE_REQUEST);
- return;
- }
- symbol filename = get_long_name(1);
- while (!tok.newline() && !tok.eof())
- tok.next();
- if (break_flag)
- curenv->do_break();
- if (!filename.is_null()) {
- errno = 0;
- FILE *fp = fopen(filename.contents(), "r");
- if (!fp)
- error("can't open `%1': %2", filename.contents(), strerror(errno));
- else {
- int bol = 1;
- for (;;) {
- int c = getc(fp);
- if (c == EOF)
- break;
- if (invalid_input_char(c))
- warning(WARN_INPUT, "invalid input character code %1", int(c));
- else {
- curdiv->transparent_output(c);
- bol = c == '\n';
- }
- }
- if (!bol)
- curdiv->transparent_output('\n');
- fclose(fp);
- }
- }
- tok.next();
-}
-
-class page_range {
- int first;
- int last;
-public:
- page_range *next;
- page_range(int, int, page_range *);
- int contains(int n);
-};
-
-page_range::page_range(int i, int j, page_range *p)
-: first(i), last(j), next(p)
-{
-}
-
-int page_range::contains(int n)
-{
- return n >= first && (last <= 0 || n <= last);
-}
-
-page_range *output_page_list = 0;
-
-int in_output_page_list(int n)
-{
- if (!output_page_list)
- return 1;
- for (page_range *p = output_page_list; p; p = p->next)
- if (p->contains(n))
- return 1;
- return 0;
-}
-
-static void parse_output_page_list(char *p)
-{
- for (;;) {
- int i;
- if (*p == '-')
- i = 1;
- else if (csdigit(*p)) {
- i = 0;
- do
- i = i*10 + *p++ - '0';
- while (csdigit(*p));
- }
- else
- break;
- int j;
- if (*p == '-') {
- p++;
- j = 0;
- if (csdigit(*p)) {
- do
- j = j*10 + *p++ - '0';
- while (csdigit(*p));
- }
- }
- else
- j = i;
- if (j == 0)
- last_page_number = -1;
- else if (last_page_number >= 0 && j > last_page_number)
- last_page_number = j;
- output_page_list = new page_range(i, j, output_page_list);
- if (*p != ',')
- break;
- ++p;
- }
- if (*p != '\0') {
- error("bad output page list");
- output_page_list = 0;
- }
-}
-
-static FILE *open_mac_file(const char *mac, char **path)
-{
- // Try first FOOBAR.tmac, then tmac.FOOBAR
- char *s1 = new char[strlen(mac)+strlen(MACRO_POSTFIX)+1];
- strcpy(s1, mac);
- strcat(s1, MACRO_POSTFIX);
- FILE *fp = mac_path->open_file(s1, path);
- a_delete s1;
- if (!fp) {
- char *s2 = new char[strlen(mac)+strlen(MACRO_PREFIX)+1];
- strcpy(s2, MACRO_PREFIX);
- strcat(s2, mac);
- fp = mac_path->open_file(s2, path);
- a_delete s2;
- }
- return fp;
-}
-
-static void process_macro_file(const char *mac)
-{
- char *path;
- FILE *fp = open_mac_file(mac, &path);
- if (!fp)
- fatal("can't find macro file %1", mac);
- const char *s = symbol(path).contents();
- a_delete path;
- input_stack::push(new file_iterator(fp, s));
- tok.next();
- process_input_stack();
-}
-
-static void process_startup_file(char *filename)
-{
- char *path;
- search_path *orig_mac_path = mac_path;
- mac_path = &config_macro_path;
- FILE *fp = mac_path->open_file(filename, &path);
- if (fp) {
- input_stack::push(new file_iterator(fp, symbol(path).contents()));
- a_delete path;
- tok.next();
- process_input_stack();
- }
- mac_path = orig_mac_path;
-}
-
-void macro_source()
-{
- symbol nm = get_long_name(1);
- if (nm.is_null())
- skip_line();
- else {
- while (!tok.newline() && !tok.eof())
- tok.next();
- char *path;
- FILE *fp = mac_path->open_file(nm.contents(), &path);
- // .mso doesn't (and cannot) go through open_mac_file, so we
- // need to do it here manually: If we have tmac.FOOBAR, try
- // FOOBAR.tmac and vice versa
- if (!fp) {
- const char *fn = nm.contents();
- if (strncasecmp(fn, MACRO_PREFIX, sizeof(MACRO_PREFIX) - 1) == 0) {
- char *s = new char[strlen(fn) + sizeof(MACRO_POSTFIX)];
- strcpy(s, fn + sizeof(MACRO_PREFIX) - 1);
- strcat(s, MACRO_POSTFIX);
- fp = mac_path->open_file(s, &path);
- a_delete s;
- }
- if (!fp) {
- if (strncasecmp(fn + strlen(fn) - sizeof(MACRO_POSTFIX) + 1,
- MACRO_POSTFIX, sizeof(MACRO_POSTFIX) - 1) == 0) {
- char *s = new char[strlen(fn) + sizeof(MACRO_PREFIX)];
- strcpy(s, MACRO_PREFIX);
- strncat(s, fn, strlen(fn) - sizeof(MACRO_POSTFIX) + 1);
- fp = mac_path->open_file(s, &path);
- a_delete s;
- }
- }
- }
- if (fp) {
- input_stack::push(new file_iterator(fp, symbol(path).contents()));
- a_delete path;
- }
- else
- error("can't find macro file `%1'", nm.contents());
- tok.next();
- }
-}
-
-static void process_input_file(const char *name)
-{
- FILE *fp;
- if (strcmp(name, "-") == 0) {
- clearerr(stdin);
- fp = stdin;
- }
- else {
- errno = 0;
- fp = fopen(name, "r");
- if (!fp)
- fatal("can't open `%1': %2", name, strerror(errno));
- }
- input_stack::push(new file_iterator(fp, name));
- tok.next();
- process_input_stack();
-}
-
-// make sure the_input is empty before calling this
-
-static int evaluate_expression(const char *expr, units *res)
-{
- input_stack::push(make_temp_iterator(expr));
- tok.next();
- int success = get_number(res, 'u');
- while (input_stack::get(0) != EOF)
- ;
- return success;
-}
-
-static void do_register_assignment(const char *s)
-{
- const char *p = strchr(s, '=');
- if (!p) {
- char buf[2];
- buf[0] = s[0];
- buf[1] = 0;
- units n;
- if (evaluate_expression(s + 1, &n))
- set_number_reg(buf, n);
- }
- else {
- char *buf = new char[p - s + 1];
- memcpy(buf, s, p - s);
- buf[p - s] = 0;
- units n;
- if (evaluate_expression(p + 1, &n))
- set_number_reg(buf, n);
- a_delete buf;
- }
-}
-
-static void set_string(const char *name, const char *value)
-{
- macro *m = new macro;
- for (const char *p = value; *p; p++)
- if (!invalid_input_char((unsigned char)*p))
- m->append(*p);
- request_dictionary.define(name, m);
-}
-
-static void do_string_assignment(const char *s)
-{
- const char *p = strchr(s, '=');
- if (!p) {
- char buf[2];
- buf[0] = s[0];
- buf[1] = 0;
- set_string(buf, s + 1);
- }
- else {
- char *buf = new char[p - s + 1];
- memcpy(buf, s, p - s);
- buf[p - s] = 0;
- set_string(buf, p + 1);
- a_delete buf;
- }
-}
-
-struct string_list {
- const char *s;
- string_list *next;
- string_list(const char *ss) : s(ss), next(0) {}
-};
-
-#if 0
-static void prepend_string(const char *s, string_list **p)
-{
- string_list *l = new string_list(s);
- l->next = *p;
- *p = l;
-}
-#endif
-
-static void add_string(const char *s, string_list **p)
-{
- while (*p)
- p = &((*p)->next);
- *p = new string_list(s);
-}
-
-void usage(FILE *stream, const char *prog)
-{
- fprintf(stream,
-"usage: %s -abcivzCERU -wname -Wname -dcs -ffam -mname -nnum -olist\n"
-" -rcn -Tname -Fdir -Mdir [files...]\n",
- prog);
-}
-
-int main(int argc, char **argv)
-{
- program_name = argv[0];
- static char stderr_buf[BUFSIZ];
- setbuf(stderr, stderr_buf);
- int c;
- string_list *macros = 0;
- string_list *register_assignments = 0;
- string_list *string_assignments = 0;
- int iflag = 0;
- int tflag = 0;
- int fflag = 0;
- int nflag = 0;
- int no_rc = 0; // don't process troffrc and troffrc-end
- int next_page_number;
- opterr = 0;
- hresolution = vresolution = 1;
- // restore $PATH if called from groff
- char* groff_path = getenv("GROFF_PATH__");
- if (groff_path) {
- string e = "PATH";
- e += '=';
- if (*groff_path)
- e += groff_path;
- e += '\0';
- if (putenv(strsave(e.contents())))
- fatal("putenv failed");
- }
- static const struct option long_options[] = {
- { "help", no_argument, 0, CHAR_MAX + 1 },
- { "version", no_argument, 0, 'v' },
- { 0, 0, 0, 0 }
- };
- while ((c = getopt_long(argc, argv, "abcivw:W:zCEf:m:n:o:r:d:F:M:T:tqs:RU",
- long_options, 0))
- != EOF)
- switch(c) {
- case 'v':
- {
- printf("GNU troff (groff) version %s\n", Version_string);
- exit(0);
- break;
- }
- case 'T':
- device = optarg;
- tflag = 1;
- is_html = (strcmp(device, "html") == 0);
- break;
- case 'C':
- compatible_flag = 1;
- // fall through
- case 'c':
- color_flag = 0;
- break;
- case 'M':
- macro_path.command_line_dir(optarg);
- safer_macro_path.command_line_dir(optarg);
- config_macro_path.command_line_dir(optarg);
- break;
- case 'F':
- font::command_line_font_dir(optarg);
- break;
- case 'm':
- add_string(optarg, ¯os);
- break;
- case 'E':
- inhibit_errors = 1;
- break;
- case 'R':
- no_rc = 1;
- break;
- case 'w':
- enable_warning(optarg);
- break;
- case 'W':
- disable_warning(optarg);
- break;
- case 'i':
- iflag = 1;
- break;
- case 'b':
- backtrace_flag = 1;
- break;
- case 'a':
- ascii_output_flag = 1;
- break;
- case 'z':
- suppress_output_flag = 1;
- break;
- case 'n':
- if (sscanf(optarg, "%d", &next_page_number) == 1)
- nflag++;
- else
- error("bad page number");
- break;
- case 'o':
- parse_output_page_list(optarg);
- break;
- case 'd':
- if (*optarg == '\0')
- error("`-d' requires non-empty argument");
- else
- add_string(optarg, &string_assignments);
- break;
- case 'r':
- if (*optarg == '\0')
- error("`-r' requires non-empty argument");
- else
- add_string(optarg, ®ister_assignments);
- break;
- case 'f':
- default_family = symbol(optarg);
- fflag = 1;
- break;
- case 'q':
- case 's':
- case 't':
- // silently ignore these
- break;
- case 'U':
- safer_flag = 0; // unsafe behaviour
- break;
- case CHAR_MAX + 1: // --help
- usage(stdout, argv[0]);
- exit(0);
- break;
- case '?':
- usage(stderr, argv[0]);
- exit(1);
- break; // never reached
- default:
- assert(0);
- }
- if (!safer_flag)
- mac_path = ¯o_path;
- set_string(".T", device);
- init_charset_table();
- init_hpf_code_table();
- if (!font::load_desc())
- fatal("sorry, I can't continue");
- units_per_inch = font::res;
- hresolution = font::hor;
- vresolution = font::vert;
- sizescale = font::sizescale;
- tcommand_flag = font::tcommand;
- warn_scale = (double)units_per_inch;
- warn_scaling_indicator = 'i';
- if (!fflag && font::family != 0 && *font::family != '\0')
- default_family = symbol(font::family);
- font_size::init_size_table(font::sizes);
- int i;
- int j = 1;
- if (font::style_table) {
- for (i = 0; font::style_table[i]; i++)
- mount_style(j++, symbol(font::style_table[i]));
- }
- for (i = 0; font::font_name_table[i]; i++, j++)
- // In the DESC file a font name of 0 (zero) means leave this
- // position empty.
- if (strcmp(font::font_name_table[i], "0") != 0)
- mount_font(j, symbol(font::font_name_table[i]));
- curdiv = topdiv = new top_level_diversion;
- if (nflag)
- topdiv->set_next_page_number(next_page_number);
- init_input_requests();
- init_env_requests();
- init_div_requests();
-#ifdef COLUMN
- init_column_requests();
-#endif /* COLUMN */
- init_node_requests();
- number_reg_dictionary.define(".T", new constant_reg(tflag ? "1" : "0"));
- init_registers();
- init_reg_requests();
- init_hyphen_requests();
- init_environments();
- while (string_assignments) {
- do_string_assignment(string_assignments->s);
- string_list *tem = string_assignments;
- string_assignments = string_assignments->next;
- delete tem;
- }
- while (register_assignments) {
- do_register_assignment(register_assignments->s);
- string_list *tem = register_assignments;
- register_assignments = register_assignments->next;
- delete tem;
- }
- if (!no_rc)
- process_startup_file(INITIAL_STARTUP_FILE);
- while (macros) {
- process_macro_file(macros->s);
- string_list *tem = macros;
- macros = macros->next;
- delete tem;
- }
- if (!no_rc)
- process_startup_file(FINAL_STARTUP_FILE);
- for (i = optind; i < argc; i++)
- process_input_file(argv[i]);
- if (optind >= argc || iflag)
- process_input_file("-");
- exit_troff();
- return 0; // not reached
-}
-
-void warn_request()
-{
- int n;
- if (has_arg() && get_integer(&n)) {
- if (n & ~WARN_TOTAL) {
- warning(WARN_RANGE, "warning mask must be between 0 and %1", WARN_TOTAL);
- n &= WARN_TOTAL;
- }
- warning_mask = n;
- }
- else
- warning_mask = WARN_TOTAL;
- skip_line();
-}
-
-static void init_registers()
-{
-#ifdef LONG_FOR_TIME_T
- long
-#else /* not LONG_FOR_TIME_T */
- time_t
-#endif /* not LONG_FOR_TIME_T */
- t = time(0);
- // Use struct here to work around misfeature in old versions of g++.
- struct tm *tt = localtime(&t);
- set_number_reg("seconds", int(tt->tm_sec));
- set_number_reg("minutes", int(tt->tm_min));
- set_number_reg("hours", int(tt->tm_hour));
- set_number_reg("dw", int(tt->tm_wday + 1));
- set_number_reg("dy", int(tt->tm_mday));
- set_number_reg("mo", int(tt->tm_mon + 1));
- set_number_reg("year", int(1900 + tt->tm_year));
- set_number_reg("yr", int(tt->tm_year));
- set_number_reg("$$", getpid());
- number_reg_dictionary.define(".A",
- new constant_reg(ascii_output_flag
- ? "1"
- : "0"));
-}
-
-/*
- * registers associated with \O
- */
-
-static int output_reg_minx_contents = -1;
-static int output_reg_miny_contents = -1;
-static int output_reg_maxx_contents = -1;
-static int output_reg_maxy_contents = -1;
-
-void check_output_limits(int x, int y)
-{
- if ((output_reg_minx_contents == -1) || (x < output_reg_minx_contents))
- output_reg_minx_contents = x;
- if (x > output_reg_maxx_contents)
- output_reg_maxx_contents = x;
- if ((output_reg_miny_contents == -1) || (y < output_reg_miny_contents))
- output_reg_miny_contents = y;
- if (y > output_reg_maxy_contents)
- output_reg_maxy_contents = y;
-}
-
-void reset_output_registers(int miny)
-{
- // fprintf(stderr, "reset_output_registers\n");
- output_reg_minx_contents = -1;
- output_reg_miny_contents = -1;
- output_reg_maxx_contents = -1;
- output_reg_maxy_contents = -1;
-}
-
-void get_output_registers(int *minx, int *miny, int *maxx, int *maxy)
-{
- *minx = output_reg_minx_contents;
- *miny = output_reg_miny_contents;
- *maxx = output_reg_maxx_contents;
- *maxy = output_reg_maxy_contents;
-}
-
-void init_input_requests()
-{
- init_request("ab", abort_request);
- init_request("als", alias_macro);
- init_request("am", append_macro);
- init_request("am1", append_nocomp_macro);
- init_request("ami", append_indirect_macro);
- init_request("as", append_string);
- init_request("as1", append_nocomp_string);
- init_request("asciify", asciify_macro);
- init_request("backtrace", backtrace_request);
- init_request("blm", blank_line_macro);
- init_request("break", while_break_request);
- init_request("cf", copy_file);
- init_request("cflags", char_flags);
- init_request("char", define_character);
- init_request("chop", chop_macro);
- init_request("close", close_request);
- init_request("color", activate_color);
- init_request("continue", while_continue_request);
- init_request("cp", compatible);
- init_request("de", define_macro);
- init_request("de1", define_nocomp_macro);
- init_request("defcolor", define_color);
- init_request("dei", define_indirect_macro);
- init_request("do", do_request);
- init_request("ds", define_string);
- init_request("ds1", define_nocomp_string);
- init_request("ec", set_escape_char);
- init_request("ecr", restore_escape_char);
- init_request("ecs", save_escape_char);
- init_request("el", else_request);
- init_request("em", end_macro);
- init_request("eo", escape_off);
- init_request("ex", exit_request);
- init_request("fchar", define_fallback_character);
-#ifdef WIDOW_CONTROL
- init_request("fpl", flush_pending_lines);
-#endif /* WIDOW_CONTROL */
- init_request("hcode", hyphenation_code);
- init_request("hpfcode", hyphenation_patterns_file_code);
- init_request("ie", if_else_request);
- init_request("if", if_request);
- init_request("ig", ignore);
- init_request("length", length_request);
- init_request("lf", line_file);
- init_request("mso", macro_source);
- init_request("nop", nop_request);
- init_request("nx", next_file);
- init_request("open", open_request);
- init_request("opena", opena_request);
- init_request("output", output_request);
- init_request("pc", set_page_character);
- init_request("pi", pipe_output);
- init_request("pm", print_macros);
- init_request("psbb", ps_bbox_request);
-#ifndef POPEN_MISSING
- init_request("pso", pipe_source);
-#endif /* not POPEN_MISSING */
- init_request("rchar", remove_character);
- init_request("rd", read_request);
- init_request("return", return_macro_request);
- init_request("rm", remove_macro);
- init_request("rn", rename_macro);
- init_request("shift", shift);
- init_request("so", source);
- init_request("spreadwarn", spreadwarn_request);
- init_request("substring", substring_request);
- init_request("sy", system_request);
- init_request("tm", terminal);
- init_request("tm1", terminal1);
- init_request("tmc", terminal_continue);
- init_request("tr", translate);
- init_request("trf", transparent_file);
- init_request("trin", translate_input);
- init_request("trnt", translate_no_transparent);
- init_request("unformat", unformat_macro);
- init_request("warn", warn_request);
- init_request("while", while_request);
- init_request("write", write_request);
- init_request("writec", write_request_continue);
- init_request("writem", write_macro_request);
- init_request("nroff", nroff_request);
- init_request("troff", troff_request);
-#ifdef COLUMN
- init_request("vj", vjustify);
-#endif /* COLUMN */
- init_request("warnscale", warnscale_request);
- number_reg_dictionary.define(".$", new nargs_reg);
- number_reg_dictionary.define(".C", new constant_int_reg(&compatible_flag));
- number_reg_dictionary.define(".F", new filename_reg);
- number_reg_dictionary.define(".H", new constant_int_reg(&hresolution));
- number_reg_dictionary.define(".R", new constant_reg("10000"));
- number_reg_dictionary.define(".V", new constant_int_reg(&vresolution));
- extern const char *revision;
- number_reg_dictionary.define(".Y", new constant_reg(revision));
- number_reg_dictionary.define(".c", new lineno_reg);
- number_reg_dictionary.define(".g", new constant_reg("1"));
- number_reg_dictionary.define(".color", new constant_int_reg(&color_flag));
- number_reg_dictionary.define(".warn", new constant_int_reg(&warning_mask));
- extern const char *major_version;
- number_reg_dictionary.define(".x", new constant_reg(major_version));
- extern const char *minor_version;
- number_reg_dictionary.define(".y", new constant_reg(minor_version));
- number_reg_dictionary.define("c.", new writable_lineno_reg);
- number_reg_dictionary.define("llx", new variable_reg(&llx_reg_contents));
- number_reg_dictionary.define("lly", new variable_reg(&lly_reg_contents));
- number_reg_dictionary.define("opmaxx",
- new variable_reg(&output_reg_maxx_contents));
- number_reg_dictionary.define("opmaxy",
- new variable_reg(&output_reg_maxy_contents));
- number_reg_dictionary.define("opminx",
- new variable_reg(&output_reg_minx_contents));
- number_reg_dictionary.define("opminy",
- new variable_reg(&output_reg_miny_contents));
- number_reg_dictionary.define("slimit",
- new variable_reg(&input_stack::limit));
- number_reg_dictionary.define("systat", new variable_reg(&system_status));
- number_reg_dictionary.define("urx", new variable_reg(&urx_reg_contents));
- number_reg_dictionary.define("ury", new variable_reg(&ury_reg_contents));
-}
-
-object_dictionary request_dictionary(501);
-
-void init_request(const char *s, REQUEST_FUNCP f)
-{
- request_dictionary.define(s, new request(f));
-}
-
-static request_or_macro *lookup_request(symbol nm)
-{
- assert(!nm.is_null());
- request_or_macro *p = (request_or_macro *)request_dictionary.lookup(nm);
- if (p == 0) {
- warning(WARN_MAC, "`%1' not defined", nm.contents());
- p = new macro;
- request_dictionary.define(nm, p);
- }
- return p;
-}
-
-node *charinfo_to_node_list(charinfo *ci, const environment *envp)
-{
- // Don't interpret character definitions in compatible mode.
- int old_compatible_flag = compatible_flag;
- compatible_flag = 0;
- int old_escape_char = escape_char;
- escape_char = '\\';
- macro *mac = ci->set_macro(0);
- assert(mac != 0);
- environment *oldenv = curenv;
- environment env(envp);
- curenv = &env;
- curenv->set_composite();
- token old_tok = tok;
- input_stack::add_boundary();
- string_iterator *si =
- new string_iterator(*mac, "composite character", ci->nm);
- input_stack::push(si);
- // we don't use process_input_stack, because we don't want to recognise
- // requests
- for (;;) {
- tok.next();
- if (tok.eof())
- break;
- if (tok.newline()) {
- error("composite character mustn't contain newline");
- while (!tok.eof())
- tok.next();
- break;
- }
- else
- tok.process();
- }
- node *n = curenv->extract_output_line();
- input_stack::remove_boundary();
- ci->set_macro(mac);
- tok = old_tok;
- curenv = oldenv;
- compatible_flag = old_compatible_flag;
- escape_char = old_escape_char;
- return n;
-}
-
-static node *read_draw_node()
-{
- token start;
- start.next();
- if (!start.delimiter(1)){
- do {
- tok.next();
- } while (tok != start && !tok.newline() && !tok.eof());
- }
- else {
- tok.next();
- if (tok == start)
- error("missing argument");
- else {
- unsigned char type = tok.ch();
- tok.next();
- int maxpoints = 10;
- hvpair *point = new hvpair[maxpoints];
- int npoints = 0;
- int no_last_v = 0;
- int err = 0;
- int i;
- for (i = 0; tok != start; i++) {
- if (i == maxpoints) {
- hvpair *oldpoint = point;
- point = new hvpair[maxpoints*2];
- for (int j = 0; j < maxpoints; j++)
- point[j] = oldpoint[j];
- maxpoints *= 2;
- a_delete oldpoint;
- }
- if (!get_hunits(&point[i].h,
- type == 'f' || type == 't' ? 'u' : 'm')) {
- err = 1;
- break;
- }
- ++npoints;
- tok.skip();
- point[i].v = V0;
- if (tok == start) {
- no_last_v = 1;
- break;
- }
- if (!get_vunits(&point[i].v, 'v')) {
- err = 1;
- break;
- }
- tok.skip();
- }
- while (tok != start && !tok.newline() && !tok.eof())
- tok.next();
- if (!err) {
- switch (type) {
- case 'l':
- if (npoints != 1 || no_last_v) {
- error("two arguments needed for line");
- npoints = 1;
- }
- break;
- case 'c':
- if (npoints != 1 || !no_last_v) {
- error("one argument needed for circle");
- npoints = 1;
- point[0].v = V0;
- }
- break;
- case 'e':
- if (npoints != 1 || no_last_v) {
- error("two arguments needed for ellipse");
- npoints = 1;
- }
- break;
- case 'a':
- if (npoints != 2 || no_last_v) {
- error("four arguments needed for arc");
- npoints = 2;
- }
- break;
- case '~':
- if (no_last_v)
- error("even number of arguments needed for spline");
- break;
- case 'f':
- if (npoints != 1 || !no_last_v) {
- error("one argument needed for gray shade");
- npoints = 1;
- point[0].v = V0;
- }
- default:
- // silently pass it through
- break;
- }
- draw_node *dn = new draw_node(type, point, npoints,
- curenv->get_font_size(),
- curenv->get_glyph_color(),
- curenv->get_fill_color());
- a_delete point;
- return dn;
- }
- else {
- a_delete point;
- }
- }
- }
- return 0;
-}
-
-static struct {
- const char *name;
- int mask;
-} warning_table[] = {
- { "char", WARN_CHAR },
- { "range", WARN_RANGE },
- { "break", WARN_BREAK },
- { "delim", WARN_DELIM },
- { "el", WARN_EL },
- { "scale", WARN_SCALE },
- { "number", WARN_NUMBER },
- { "syntax", WARN_SYNTAX },
- { "tab", WARN_TAB },
- { "right-brace", WARN_RIGHT_BRACE },
- { "missing", WARN_MISSING },
- { "input", WARN_INPUT },
- { "escape", WARN_ESCAPE },
- { "space", WARN_SPACE },
- { "font", WARN_FONT },
- { "di", WARN_DI },
- { "mac", WARN_MAC },
- { "reg", WARN_REG },
- { "ig", WARN_IG },
- { "color", WARN_COLOR },
- { "all", WARN_TOTAL & ~(WARN_DI | WARN_MAC | WARN_REG) },
- { "w", WARN_TOTAL },
- { "default", DEFAULT_WARNING_MASK },
-};
-
-static int lookup_warning(const char *name)
-{
- for (unsigned int i = 0;
- i < sizeof(warning_table)/sizeof(warning_table[0]);
- i++)
- if (strcmp(name, warning_table[i].name) == 0)
- return warning_table[i].mask;
- return 0;
-}
-
-static void enable_warning(const char *name)
-{
- int mask = lookup_warning(name);
- if (mask)
- warning_mask |= mask;
- else
- error("unknown warning `%1'", name);
-}
-
-static void disable_warning(const char *name)
-{
- int mask = lookup_warning(name);
- if (mask)
- warning_mask &= ~mask;
- else
- error("unknown warning `%1'", name);
-}
-
-static void copy_mode_error(const char *format,
- const errarg &arg1,
- const errarg &arg2,
- const errarg &arg3)
-{
- if (ignoring) {
- static const char prefix[] = "(in ignored input) ";
- char *s = new char[sizeof(prefix) + strlen(format)];
- strcpy(s, prefix);
- strcat(s, format);
- warning(WARN_IG, s, arg1, arg2, arg3);
- a_delete s;
- }
- else
- error(format, arg1, arg2, arg3);
-}
-
-enum error_type { WARNING, OUTPUT_WARNING, ERROR, FATAL };
-
-static void do_error(error_type type,
- const char *format,
- const errarg &arg1,
- const errarg &arg2,
- const errarg &arg3)
-{
- const char *filename;
- int lineno;
- if (inhibit_errors && type < FATAL)
- return;
- if (backtrace_flag)
- input_stack::backtrace();
- if (!get_file_line(&filename, &lineno))
- filename = 0;
- if (filename)
- errprint("%1:%2: ", filename, lineno);
- else if (program_name)
- fprintf(stderr, "%s: ", program_name);
- switch (type) {
- case FATAL:
- fputs("fatal error: ", stderr);
- break;
- case ERROR:
- break;
- case WARNING:
- fputs("warning: ", stderr);
- break;
- case OUTPUT_WARNING:
- double fromtop = topdiv->get_vertical_position().to_units() / warn_scale;
- fprintf(stderr, "warning [p %d, %.1f%c",
- topdiv->get_page_number(), fromtop, warn_scaling_indicator);
- if (topdiv != curdiv) {
- double fromtop1 = curdiv->get_vertical_position().to_units()
- / warn_scale;
- fprintf(stderr, ", div `%s', %.1f%c",
- curdiv->get_diversion_name(), fromtop1, warn_scaling_indicator);
- }
- fprintf(stderr, "]: ");
- break;
- }
- errprint(format, arg1, arg2, arg3);
- fputc('\n', stderr);
- fflush(stderr);
- if (type == FATAL)
- cleanup_and_exit(1);
-}
-
-int warning(warning_type t,
- const char *format,
- const errarg &arg1,
- const errarg &arg2,
- const errarg &arg3)
-{
- if ((t & warning_mask) != 0) {
- do_error(WARNING, format, arg1, arg2, arg3);
- return 1;
- }
- else
- return 0;
-}
-
-int output_warning(warning_type t,
- const char *format,
- const errarg &arg1,
- const errarg &arg2,
- const errarg &arg3)
-{
- if ((t & warning_mask) != 0) {
- do_error(OUTPUT_WARNING, format, arg1, arg2, arg3);
- return 1;
- }
- else
- return 0;
-}
-
-void error(const char *format,
- const errarg &arg1,
- const errarg &arg2,
- const errarg &arg3)
-{
- do_error(ERROR, format, arg1, arg2, arg3);
-}
-
-void fatal(const char *format,
- const errarg &arg1,
- const errarg &arg2,
- const errarg &arg3)
-{
- do_error(FATAL, format, arg1, arg2, arg3);
-}
-
-void fatal_with_file_and_line(const char *filename, int lineno,
- const char *format,
- const errarg &arg1,
- const errarg &arg2,
- const errarg &arg3)
-{
- fprintf(stderr, "%s:%d: fatal error: ", filename, lineno);
- errprint(format, arg1, arg2, arg3);
- fputc('\n', stderr);
- fflush(stderr);
- cleanup_and_exit(1);
-}
-
-void error_with_file_and_line(const char *filename, int lineno,
- const char *format,
- const errarg &arg1,
- const errarg &arg2,
- const errarg &arg3)
-{
- fprintf(stderr, "%s:%d: error: ", filename, lineno);
- errprint(format, arg1, arg2, arg3);
- fputc('\n', stderr);
- fflush(stderr);
-}
-
-dictionary charinfo_dictionary(501);
-
-charinfo *get_charinfo(symbol nm)
-{
- void *p = charinfo_dictionary.lookup(nm);
- if (p != 0)
- return (charinfo *)p;
- charinfo *cp = new charinfo(nm);
- (void)charinfo_dictionary.lookup(nm, cp);
- return cp;
-}
-
-int charinfo::next_index = 0;
-
-charinfo::charinfo(symbol s)
-: translation(0), mac(0), special_translation(TRANSLATE_NONE),
- hyphenation_code(0), flags(0), ascii_code(0), asciify_code(0),
- not_found(0), transparent_translate(1), translate_input(0),
- fallback(0), nm(s)
-{
- index = next_index++;
-}
-
-void charinfo::set_hyphenation_code(unsigned char c)
-{
- hyphenation_code = c;
-}
-
-void charinfo::set_translation(charinfo *ci, int tt, int ti)
-{
- translation = ci;
- if (ci && ti) {
- if (hyphenation_code != 0)
- ci->set_hyphenation_code(hyphenation_code);
- if (asciify_code != 0)
- ci->set_asciify_code(asciify_code);
- else if (ascii_code != 0)
- ci->set_asciify_code(ascii_code);
- ci->set_translation_input();
- }
- special_translation = TRANSLATE_NONE;
- transparent_translate = tt;
-}
-
-void charinfo::set_special_translation(int c, int tt)
-{
- special_translation = c;
- translation = 0;
- transparent_translate = tt;
-}
-
-void charinfo::set_ascii_code(unsigned char c)
-{
- ascii_code = c;
-}
-
-void charinfo::set_asciify_code(unsigned char c)
-{
- asciify_code = c;
-}
-
-macro *charinfo::set_macro(macro *m, int f)
-{
- macro *tem = mac;
- mac = m;
- fallback = f;
- return tem;
-}
-
-void charinfo::set_number(int n)
-{
- number = n;
- flags |= NUMBERED;
-}
-
-int charinfo::get_number()
-{
- assert(flags & NUMBERED);
- return number;
-}
-
-symbol UNNAMED_SYMBOL("---");
-
-// For numbered characters not between 0 and 255, we make a symbol out
-// of the number and store them in this dictionary.
-
-dictionary numbered_charinfo_dictionary(11);
-
-charinfo *get_charinfo_by_number(int n)
-{
- static charinfo *number_table[256];
-
- if (n >= 0 && n < 256) {
- charinfo *ci = number_table[n];
- if (!ci) {
- ci = new charinfo(UNNAMED_SYMBOL);
- ci->set_number(n);
- number_table[n] = ci;
- }
- return ci;
- }
- else {
- symbol ns(i_to_a(n));
- charinfo *ci = (charinfo *)numbered_charinfo_dictionary.lookup(ns);
- if (!ci) {
- ci = new charinfo(UNNAMED_SYMBOL);
- ci->set_number(n);
- numbered_charinfo_dictionary.lookup(ns, ci);
- }
- return ci;
- }
-}
-
-int font::name_to_index(const char *nm)
-{
- charinfo *ci;
- if (nm[1] == 0)
- ci = charset_table[nm[0] & 0xff];
- else if (nm[0] == '\\' && nm[2] == 0)
- ci = get_charinfo(symbol(nm + 1));
- else
- ci = get_charinfo(symbol(nm));
- if (ci == 0)
- return -1;
- else
- return ci->get_index();
-}
-
-int font::number_to_index(int n)
-{
- return get_charinfo_by_number(n)->get_index();
-}
diff --git a/contrib/groff/src/roff/troff/node.cc b/contrib/groff/src/roff/troff/node.cc
deleted file mode 100644
index 58a3cd8..0000000
--- a/contrib/groff/src/roff/troff/node.cc
+++ /dev/null
@@ -1,5888 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "troff.h"
-
-#ifdef HAVE_UNISTD_H
-#include
-#endif
-
-#include "symbol.h"
-#include "dictionary.h"
-#include "hvunits.h"
-#include "env.h"
-#include "request.h"
-#include "node.h"
-#include "token.h"
-#include "charinfo.h"
-#include "font.h"
-#include "reg.h"
-#include "input.h"
-#include "div.h"
-#include "geometry.h"
-
-#include "nonposix.h"
-
-#ifdef _POSIX_VERSION
-
-#include
-
-#else /* not _POSIX_VERSION */
-
-/* traditional Unix */
-
-#define WIFEXITED(s) (((s) & 0377) == 0)
-#define WEXITSTATUS(s) (((s) >> 8) & 0377)
-#define WTERMSIG(s) ((s) & 0177)
-#define WIFSTOPPED(s) (((s) & 0377) == 0177)
-#define WSTOPSIG(s) (((s) >> 8) & 0377)
-#define WIFSIGNALED(s) (((s) & 0377) != 0 && (((s) & 0377) != 0177))
-
-#endif /* not _POSIX_VERSION */
-
-/*
- * how many boundaries of images have been written? Useful for
- * debugging grohtml
- */
-
-int image_no = 0;
-static int suppress_start_page = 0;
-
-#define STORE_WIDTH 1
-
-symbol HYPHEN_SYMBOL("hy");
-
-// Character used when a hyphen is inserted at a line break.
-static charinfo *soft_hyphen_char;
-
-enum constant_space_type {
- CONSTANT_SPACE_NONE,
- CONSTANT_SPACE_RELATIVE,
- CONSTANT_SPACE_ABSOLUTE
- };
-
-struct special_font_list {
- int n;
- special_font_list *next;
-};
-
-special_font_list *global_special_fonts;
-static int global_ligature_mode = 1;
-static int global_kern_mode = 1;
-
-class track_kerning_function {
- int non_zero;
- units min_size;
- hunits min_amount;
- units max_size;
- hunits max_amount;
-public:
- track_kerning_function();
- track_kerning_function(units, hunits, units, hunits);
- int operator==(const track_kerning_function &);
- int operator!=(const track_kerning_function &);
- hunits compute(int point_size);
-};
-
-// embolden fontno when this is the current font
-
-struct conditional_bold {
- conditional_bold *next;
- int fontno;
- hunits offset;
- conditional_bold(int, hunits, conditional_bold * = 0);
-};
-
-struct tfont;
-
-class font_info {
- tfont *last_tfont;
- int number;
- font_size last_size;
- int last_height;
- int last_slant;
- symbol internal_name;
- symbol external_name;
- font *fm;
- char is_bold;
- hunits bold_offset;
- track_kerning_function track_kern;
- constant_space_type is_constant_spaced;
- units constant_space;
- int last_ligature_mode;
- int last_kern_mode;
- conditional_bold *cond_bold_list;
- void flush();
-public:
- special_font_list *sf;
- font_info(symbol nm, int n, symbol enm, font *f);
- int contains(charinfo *);
- void set_bold(hunits);
- void unbold();
- void set_conditional_bold(int, hunits);
- void conditional_unbold(int);
- void set_track_kern(track_kerning_function &);
- void set_constant_space(constant_space_type, units = 0);
- int is_named(symbol);
- symbol get_name();
- tfont *get_tfont(font_size, int, int, int);
- hunits get_space_width(font_size, int);
- hunits get_narrow_space_width(font_size);
- hunits get_half_narrow_space_width(font_size);
- int get_bold(hunits *);
- int is_special();
- int is_style();
- friend symbol get_font_name(int, environment *);
-};
-
-class tfont_spec {
-protected:
- symbol name;
- int input_position;
- font *fm;
- font_size size;
- char is_bold;
- char is_constant_spaced;
- int ligature_mode;
- int kern_mode;
- hunits bold_offset;
- hunits track_kern; // add this to the width
- hunits constant_space_width;
- int height;
- int slant;
-public:
- tfont_spec(symbol nm, int pos, font *, font_size, int, int);
- tfont_spec(const tfont_spec &spec) { *this = spec; }
- tfont_spec plain();
- int operator==(const tfont_spec &);
- friend tfont *font_info::get_tfont(font_size fs, int, int, int);
-};
-
-class tfont : public tfont_spec {
- static tfont *tfont_list;
- tfont *next;
- tfont *plain_version;
-public:
- tfont(tfont_spec &);
- int contains(charinfo *);
- hunits get_width(charinfo *c);
- int get_bold(hunits *);
- int get_constant_space(hunits *);
- hunits get_track_kern();
- tfont *get_plain();
- font_size get_size();
- symbol get_name();
- charinfo *get_lig(charinfo *c1, charinfo *c2);
- int get_kern(charinfo *c1, charinfo *c2, hunits *res);
- int get_input_position();
- int get_character_type(charinfo *);
- int get_height();
- int get_slant();
- vunits get_char_height(charinfo *);
- vunits get_char_depth(charinfo *);
- hunits get_char_skew(charinfo *);
- hunits get_italic_correction(charinfo *);
- hunits get_left_italic_correction(charinfo *);
- hunits get_subscript_correction(charinfo *);
- friend tfont *make_tfont(tfont_spec &);
-};
-
-inline int env_definite_font(environment *env)
-{
- return env->get_family()->make_definite(env->get_font());
-}
-
-/* font_info functions */
-
-static font_info **font_table = 0;
-static int font_table_size = 0;
-
-font_info::font_info(symbol nm, int n, symbol enm, font *f)
-: last_tfont(0), number(n), last_size(0),
- internal_name(nm), external_name(enm), fm(f),
- is_bold(0), is_constant_spaced(CONSTANT_SPACE_NONE), last_ligature_mode(1),
- last_kern_mode(1), cond_bold_list(0), sf(0)
-{
-}
-
-inline int font_info::contains(charinfo *ci)
-{
- return fm != 0 && fm->contains(ci->get_index());
-}
-
-inline int font_info::is_special()
-{
- return fm != 0 && fm->is_special();
-}
-
-inline int font_info::is_style()
-{
- return fm == 0;
-}
-
-tfont *make_tfont(tfont_spec &spec)
-{
- for (tfont *p = tfont::tfont_list; p; p = p->next)
- if (*p == spec)
- return p;
- return new tfont(spec);
-}
-
-// this is the current_font, fontno is where we found the character,
-// presumably a special font
-
-tfont *font_info::get_tfont(font_size fs, int height, int slant, int fontno)
-{
- if (last_tfont == 0 || fs != last_size
- || height != last_height || slant != last_slant
- || global_ligature_mode != last_ligature_mode
- || global_kern_mode != last_kern_mode
- || fontno != number) {
- font_info *f = font_table[fontno];
- tfont_spec spec(f->external_name, f->number, f->fm, fs, height, slant);
- for (conditional_bold *p = cond_bold_list; p; p = p->next)
- if (p->fontno == fontno) {
- spec.is_bold = 1;
- spec.bold_offset = p->offset;
- break;
- }
- if (!spec.is_bold && is_bold) {
- spec.is_bold = 1;
- spec.bold_offset = bold_offset;
- }
- spec.track_kern = track_kern.compute(fs.to_scaled_points());
- spec.ligature_mode = global_ligature_mode;
- spec.kern_mode = global_kern_mode;
- switch (is_constant_spaced) {
- case CONSTANT_SPACE_NONE:
- break;
- case CONSTANT_SPACE_ABSOLUTE:
- spec.is_constant_spaced = 1;
- spec.constant_space_width = constant_space;
- break;
- case CONSTANT_SPACE_RELATIVE:
- spec.is_constant_spaced = 1;
- spec.constant_space_width
- = scale(constant_space*fs.to_scaled_points(),
- units_per_inch,
- 36*72*sizescale);
- break;
- default:
- assert(0);
- }
- if (fontno != number)
- return make_tfont(spec);
- last_tfont = make_tfont(spec);
- last_size = fs;
- last_height = height;
- last_slant = slant;
- last_ligature_mode = global_ligature_mode;
- last_kern_mode = global_kern_mode;
- }
- return last_tfont;
-}
-
-int font_info::get_bold(hunits *res)
-{
- if (is_bold) {
- *res = bold_offset;
- return 1;
- }
- else
- return 0;
-}
-
-void font_info::unbold()
-{
- if (is_bold) {
- is_bold = 0;
- flush();
- }
-}
-
-void font_info::set_bold(hunits offset)
-{
- if (!is_bold || offset != bold_offset) {
- is_bold = 1;
- bold_offset = offset;
- flush();
- }
-}
-
-void font_info::set_conditional_bold(int fontno, hunits offset)
-{
- for (conditional_bold *p = cond_bold_list; p; p = p->next)
- if (p->fontno == fontno) {
- if (offset != p->offset) {
- p->offset = offset;
- flush();
- }
- return;
- }
- cond_bold_list = new conditional_bold(fontno, offset, cond_bold_list);
-}
-
-conditional_bold::conditional_bold(int f, hunits h, conditional_bold *x)
-: next(x), fontno(f), offset(h)
-{
-}
-
-void font_info::conditional_unbold(int fontno)
-{
- for (conditional_bold **p = &cond_bold_list; *p; p = &(*p)->next)
- if ((*p)->fontno == fontno) {
- conditional_bold *tem = *p;
- *p = (*p)->next;
- delete tem;
- flush();
- return;
- }
-}
-
-void font_info::set_constant_space(constant_space_type type, units x)
-{
- if (type != is_constant_spaced
- || (type != CONSTANT_SPACE_NONE && x != constant_space)) {
- flush();
- is_constant_spaced = type;
- constant_space = x;
- }
-}
-
-void font_info::set_track_kern(track_kerning_function &tk)
-{
- if (track_kern != tk) {
- track_kern = tk;
- flush();
- }
-}
-
-void font_info::flush()
-{
- last_tfont = 0;
-}
-
-int font_info::is_named(symbol s)
-{
- return internal_name == s;
-}
-
-symbol font_info::get_name()
-{
- return internal_name;
-}
-
-symbol get_font_name(int fontno, environment *env)
-{
- symbol f = font_table[fontno]->get_name();
- if (font_table[fontno]->is_style()) {
- return concat(env->get_family()->nm, f);
- }
- return f;
-}
-
-hunits font_info::get_space_width(font_size fs, int space_size)
-{
- if (is_constant_spaced == CONSTANT_SPACE_NONE)
- return scale(hunits(fm->get_space_width(fs.to_scaled_points())),
- space_size, 12);
- else if (is_constant_spaced == CONSTANT_SPACE_ABSOLUTE)
- return constant_space;
- else
- return scale(constant_space*fs.to_scaled_points(),
- units_per_inch, 36*72*sizescale);
-}
-
-hunits font_info::get_narrow_space_width(font_size fs)
-{
- charinfo *ci = get_charinfo(symbol("|"));
- if (fm->contains(ci->get_index()))
- return hunits(fm->get_width(ci->get_index(), fs.to_scaled_points()));
- else
- return hunits(fs.to_units()/6);
-}
-
-hunits font_info::get_half_narrow_space_width(font_size fs)
-{
- charinfo *ci = get_charinfo(symbol("^"));
- if (fm->contains(ci->get_index()))
- return hunits(fm->get_width(ci->get_index(), fs.to_scaled_points()));
- else
- return hunits(fs.to_units()/12);
-}
-
-/* tfont */
-
-tfont_spec::tfont_spec(symbol nm, int n, font *f,
- font_size s, int h, int sl)
-: name(nm), input_position(n), fm(f), size(s),
- is_bold(0), is_constant_spaced(0), ligature_mode(1), kern_mode(1),
- height(h), slant(sl)
-{
- if (height == size.to_scaled_points())
- height = 0;
-}
-
-int tfont_spec::operator==(const tfont_spec &spec)
-{
- if (fm == spec.fm
- && size == spec.size
- && input_position == spec.input_position
- && name == spec.name
- && height == spec.height
- && slant == spec.slant
- && (is_bold
- ? (spec.is_bold && bold_offset == spec.bold_offset)
- : !spec.is_bold)
- && track_kern == spec.track_kern
- && (is_constant_spaced
- ? (spec.is_constant_spaced
- && constant_space_width == spec.constant_space_width)
- : !spec.is_constant_spaced)
- && ligature_mode == spec.ligature_mode
- && kern_mode == spec.kern_mode)
- return 1;
- else
- return 0;
-}
-
-tfont_spec tfont_spec::plain()
-{
- return tfont_spec(name, input_position, fm, size, height, slant);
-}
-
-hunits tfont::get_width(charinfo *c)
-{
- if (is_constant_spaced)
- return constant_space_width;
- else if (is_bold)
- return (hunits(fm->get_width(c->get_index(), size.to_scaled_points()))
- + track_kern + bold_offset);
- else
- return (hunits(fm->get_width(c->get_index(), size.to_scaled_points()))
- + track_kern);
-}
-
-vunits tfont::get_char_height(charinfo *c)
-{
- vunits v = fm->get_height(c->get_index(), size.to_scaled_points());
- if (height != 0 && height != size.to_scaled_points())
- return scale(v, height, size.to_scaled_points());
- else
- return v;
-}
-
-vunits tfont::get_char_depth(charinfo *c)
-{
- vunits v = fm->get_depth(c->get_index(), size.to_scaled_points());
- if (height != 0 && height != size.to_scaled_points())
- return scale(v, height, size.to_scaled_points());
- else
- return v;
-}
-
-hunits tfont::get_char_skew(charinfo *c)
-{
- return hunits(fm->get_skew(c->get_index(), size.to_scaled_points(), slant));
-}
-
-hunits tfont::get_italic_correction(charinfo *c)
-{
- return hunits(fm->get_italic_correction(c->get_index(), size.to_scaled_points()));
-}
-
-hunits tfont::get_left_italic_correction(charinfo *c)
-{
- return hunits(fm->get_left_italic_correction(c->get_index(),
- size.to_scaled_points()));
-}
-
-hunits tfont::get_subscript_correction(charinfo *c)
-{
- return hunits(fm->get_subscript_correction(c->get_index(),
- size.to_scaled_points()));
-}
-
-inline int tfont::get_input_position()
-{
- return input_position;
-}
-
-inline int tfont::contains(charinfo *ci)
-{
- return fm->contains(ci->get_index());
-}
-
-inline int tfont::get_character_type(charinfo *ci)
-{
- return fm->get_character_type(ci->get_index());
-}
-
-inline int tfont::get_bold(hunits *res)
-{
- if (is_bold) {
- *res = bold_offset;
- return 1;
- }
- else
- return 0;
-}
-
-inline int tfont::get_constant_space(hunits *res)
-{
- if (is_constant_spaced) {
- *res = constant_space_width;
- return 1;
- }
- else
- return 0;
-}
-
-inline hunits tfont::get_track_kern()
-{
- return track_kern;
-}
-
-inline tfont *tfont::get_plain()
-{
- return plain_version;
-}
-
-inline font_size tfont::get_size()
-{
- return size;
-}
-
-inline symbol tfont::get_name()
-{
- return name;
-}
-
-inline int tfont::get_height()
-{
- return height;
-}
-
-inline int tfont::get_slant()
-{
- return slant;
-}
-
-symbol SYMBOL_ff("ff");
-symbol SYMBOL_fi("fi");
-symbol SYMBOL_fl("fl");
-symbol SYMBOL_Fi("Fi");
-symbol SYMBOL_Fl("Fl");
-
-charinfo *tfont::get_lig(charinfo *c1, charinfo *c2)
-{
- if (ligature_mode == 0)
- return 0;
- charinfo *ci = 0;
- if (c1->get_ascii_code() == 'f') {
- switch (c2->get_ascii_code()) {
- case 'f':
- if (fm->has_ligature(font::LIG_ff))
- ci = get_charinfo(SYMBOL_ff);
- break;
- case 'i':
- if (fm->has_ligature(font::LIG_fi))
- ci = get_charinfo(SYMBOL_fi);
- break;
- case 'l':
- if (fm->has_ligature(font::LIG_fl))
- ci = get_charinfo(SYMBOL_fl);
- break;
- }
- }
- else if (ligature_mode != 2 && c1->nm == SYMBOL_ff) {
- switch (c2->get_ascii_code()) {
- case 'i':
- if (fm->has_ligature(font::LIG_ffi))
- ci = get_charinfo(SYMBOL_Fi);
- break;
- case 'l':
- if (fm->has_ligature(font::LIG_ffl))
- ci = get_charinfo(SYMBOL_Fl);
- break;
- }
- }
- if (ci != 0 && fm->contains(ci->get_index()))
- return ci;
- return 0;
-}
-
-inline int tfont::get_kern(charinfo *c1, charinfo *c2, hunits *res)
-{
- if (kern_mode == 0)
- return 0;
- else {
- int n = fm->get_kern(c1->get_index(),
- c2->get_index(),
- size.to_scaled_points());
- if (n) {
- *res = hunits(n);
- return 1;
- }
- else
- return 0;
- }
-}
-
-tfont *tfont::tfont_list = 0;
-
-tfont::tfont(tfont_spec &spec) : tfont_spec(spec)
-{
- next = tfont_list;
- tfont_list = this;
- tfont_spec plain_spec = plain();
- tfont *p;
- for (p = tfont_list; p; p = p->next)
- if (*p == plain_spec) {
- plain_version = p;
- break;
- }
- if (!p)
- plain_version = new tfont(plain_spec);
-}
-
-/* output_file */
-
-class real_output_file : public output_file {
-#ifndef POPEN_MISSING
- int piped;
-#endif
- int printing; // decision via optional page list
- int output_on; // \O[0] or \O[1] escape calls
- virtual void really_transparent_char(unsigned char) = 0;
- virtual void really_print_line(hunits x, vunits y, node *n,
- vunits before, vunits after, hunits width) = 0;
- virtual void really_begin_page(int pageno, vunits page_length) = 0;
- virtual void really_copy_file(hunits x, vunits y, const char *filename);
- virtual void really_put_filename(const char *filename);
- virtual void really_on();
- virtual void really_off();
-protected:
- FILE *fp;
-public:
- real_output_file();
- ~real_output_file();
- void flush();
- void transparent_char(unsigned char);
- void print_line(hunits x, vunits y, node *n, vunits before, vunits after, hunits width);
- void begin_page(int pageno, vunits page_length);
- void put_filename(const char *filename);
- void on();
- void off();
- int is_on();
- int is_printing();
- void copy_file(hunits x, vunits y, const char *filename);
-};
-
-class suppress_output_file : public real_output_file {
-public:
- suppress_output_file();
- void really_transparent_char(unsigned char);
- void really_print_line(hunits x, vunits y, node *n, vunits, vunits, hunits width);
- void really_begin_page(int pageno, vunits page_length);
-};
-
-class ascii_output_file : public real_output_file {
-public:
- ascii_output_file();
- void really_transparent_char(unsigned char);
- void really_print_line(hunits x, vunits y, node *n, vunits, vunits, hunits width);
- void really_begin_page(int pageno, vunits page_length);
- void outc(unsigned char c);
- void outs(const char *s);
-};
-
-void ascii_output_file::outc(unsigned char c)
-{
- fputc(c, fp);
-}
-
-void ascii_output_file::outs(const char *s)
-{
- fputc('<', fp);
- if (s)
- fputs(s, fp);
- fputc('>', fp);
-}
-
-struct hvpair;
-
-class troff_output_file : public real_output_file {
- units hpos;
- units vpos;
- units output_vpos;
- units output_hpos;
- int force_motion;
- int current_size;
- int current_slant;
- int current_height;
- tfont *current_tfont;
- color *current_fill_color;
- color *current_glyph_color;
- int current_font_number;
- symbol *font_position;
- int nfont_positions;
- enum { TBUF_SIZE = 256 };
- char tbuf[TBUF_SIZE];
- int tbuf_len;
- int tbuf_kern;
- int begun_page;
- void do_motion();
- void put(char c);
- void put(unsigned char c);
- void put(int i);
- void put(unsigned int i);
- void put(const char *s);
- void set_font(tfont *tf);
- void flush_tbuf();
-public:
- troff_output_file();
- ~troff_output_file();
- void trailer(vunits page_length);
- void put_char(charinfo *, tfont *, color *, color *);
- void put_char_width(charinfo *, tfont *, color *, color *, hunits, hunits);
- void right(hunits);
- void down(vunits);
- void moveto(hunits, vunits);
- void start_special(tfont *, color *, color *, int = 0);
- void start_special();
- void special_char(unsigned char c);
- void end_special();
- void word_marker();
- void really_transparent_char(unsigned char c);
- void really_print_line(hunits x, vunits y, node *n, vunits before, vunits after, hunits width);
- void really_begin_page(int pageno, vunits page_length);
- void really_copy_file(hunits x, vunits y, const char *filename);
- void really_put_filename(const char *filename);
- void really_on();
- void really_off();
- void draw(char, hvpair *, int, font_size, color *, color *);
- void determine_line_limits (char code, hvpair *point, int npoints);
- void check_charinfo(tfont *tf, charinfo *ci);
- void glyph_color(color *c);
- void fill_color(color *c);
- int get_hpos() { return hpos; }
- int get_vpos() { return vpos; }
-};
-
-static void put_string(const char *s, FILE *fp)
-{
- for (; *s != '\0'; ++s)
- putc(*s, fp);
-}
-
-inline void troff_output_file::put(char c)
-{
- putc(c, fp);
-}
-
-inline void troff_output_file::put(unsigned char c)
-{
- putc(c, fp);
-}
-
-inline void troff_output_file::put(const char *s)
-{
- put_string(s, fp);
-}
-
-inline void troff_output_file::put(int i)
-{
- put_string(i_to_a(i), fp);
-}
-
-inline void troff_output_file::put(unsigned int i)
-{
- put_string(ui_to_a(i), fp);
-}
-
-void troff_output_file::start_special(tfont *tf, color *gcol, color *fcol,
- int no_init_string)
-{
- flush_tbuf();
- do_motion();
- if (tf != current_tfont)
- set_font(tf);
- glyph_color(gcol);
- fill_color(fcol);
- if (!no_init_string)
- put("x X ");
-}
-
-void troff_output_file::start_special()
-{
- flush_tbuf();
- do_motion();
- put("x X ");
-}
-
-void troff_output_file::special_char(unsigned char c)
-{
- put(c);
- if (c == '\n')
- put('+');
-}
-
-void troff_output_file::end_special()
-{
- put('\n');
-}
-
-inline void troff_output_file::moveto(hunits h, vunits v)
-{
- hpos = h.to_units();
- vpos = v.to_units();
-}
-
-void troff_output_file::really_print_line(hunits x, vunits y, node *n,
- vunits before, vunits after, hunits width)
-{
- moveto(x, y);
- while (n != 0) {
- n->tprint(this);
- n = n->next;
- }
- flush_tbuf();
- // This ensures that transparent throughput will have a more predictable
- // position.
- do_motion();
- force_motion = 1;
- hpos = 0;
- put('n');
- put(before.to_units());
- put(' ');
- put(after.to_units());
- put('\n');
-}
-
-inline void troff_output_file::word_marker()
-{
- flush_tbuf();
- if (is_on())
- put('w');
-}
-
-inline void troff_output_file::right(hunits n)
-{
- hpos += n.to_units();
-}
-
-inline void troff_output_file::down(vunits n)
-{
- vpos += n.to_units();
-}
-
-void troff_output_file::do_motion()
-{
- if (force_motion) {
- put('V');
- put(vpos);
- put('\n');
- put('H');
- put(hpos);
- put('\n');
- }
- else {
- if (hpos != output_hpos) {
- units n = hpos - output_hpos;
- if (n > 0 && n < hpos) {
- put('h');
- put(n);
- }
- else {
- put('H');
- put(hpos);
- }
- put('\n');
- }
- if (vpos != output_vpos) {
- units n = vpos - output_vpos;
- if (n > 0 && n < vpos) {
- put('v');
- put(n);
- }
- else {
- put('V');
- put(vpos);
- }
- put('\n');
- }
- }
- output_vpos = vpos;
- output_hpos = hpos;
- force_motion = 0;
-}
-
-void troff_output_file::flush_tbuf()
-{
- if (!is_on()) {
- tbuf_len = 0;
- return;
- }
-
- if (tbuf_len == 0)
- return;
- if (tbuf_kern == 0)
- put('t');
- else {
- put('u');
- put(tbuf_kern);
- put(' ');
- }
- check_output_limits(hpos, vpos);
- check_output_limits(hpos, vpos - current_size);
-
- for (int i = 0; i < tbuf_len; i++)
- put(tbuf[i]);
- put('\n');
- tbuf_len = 0;
-}
-
-void troff_output_file::check_charinfo(tfont *tf, charinfo *ci)
-{
- if (!is_on())
- return;
-
- int height = tf->get_char_height(ci).to_units();
- int width = tf->get_width(ci).to_units()
- + tf->get_italic_correction(ci).to_units();
- int depth = tf->get_char_depth(ci).to_units();
- check_output_limits(output_hpos, output_vpos - height);
- check_output_limits(output_hpos + width, output_vpos + depth);
-}
-
-void troff_output_file::put_char_width(charinfo *ci, tfont *tf,
- color *gcol, color *fcol,
- hunits w, hunits k)
-{
- int kk = k.to_units();
- if (!is_on()) {
- flush_tbuf();
- hpos += w.to_units() + kk;
- return;
- }
- if (tf != current_tfont) {
- flush_tbuf();
- set_font(tf);
- }
- char c = ci->get_ascii_code();
- if (c == '\0') {
- flush_tbuf();
- do_motion();
- glyph_color(gcol);
- fill_color(fcol);
- check_charinfo(tf, ci);
- if (ci->numbered()) {
- put('N');
- put(ci->get_number());
- }
- else {
- put('C');
- const char *s = ci->nm.contents();
- if (s[1] == 0) {
- put('\\');
- put(s[0]);
- }
- else
- put(s);
- }
- put('\n');
- hpos += w.to_units() + kk;
- }
- else if (tcommand_flag) {
- if (tbuf_len > 0 && hpos == output_hpos && vpos == output_vpos
- && (!gcol || gcol == current_glyph_color)
- && (!fcol || fcol == current_fill_color)
- && kk == tbuf_kern
- && tbuf_len < TBUF_SIZE) {
- check_charinfo(tf, ci);
- tbuf[tbuf_len++] = c;
- output_hpos += w.to_units() + kk;
- hpos = output_hpos;
- return;
- }
- flush_tbuf();
- do_motion();
- glyph_color(gcol);
- fill_color(fcol);
- check_charinfo(tf, ci);
- tbuf[tbuf_len++] = c;
- output_hpos += w.to_units() + kk;
- tbuf_kern = kk;
- hpos = output_hpos;
- }
- else {
- // flush_tbuf();
- int n = hpos - output_hpos;
- check_charinfo(tf, ci);
- // check_output_limits(output_hpos, output_vpos);
- if (vpos == output_vpos
- && (!gcol || gcol == current_glyph_color)
- && (!fcol || fcol == current_fill_color)
- && n > 0 && n < 100 && !force_motion) {
- put(char(n/10 + '0'));
- put(char(n%10 + '0'));
- put(c);
- output_hpos = hpos;
- }
- else {
- do_motion();
- put('c');
- put(c);
- }
- hpos += w.to_units() + kk;
- }
-}
-
-void troff_output_file::put_char(charinfo *ci, tfont *tf,
- color *gcol, color *fcol)
-{
- flush_tbuf();
- if (!is_on())
- return;
- if (tf != current_tfont)
- set_font(tf);
- char c = ci->get_ascii_code();
- if (c == '\0') {
- do_motion();
- glyph_color(gcol);
- fill_color(fcol);
- if (ci->numbered()) {
- put('N');
- put(ci->get_number());
- }
- else {
- put('C');
- const char *s = ci->nm.contents();
- if (s[1] == 0) {
- put('\\');
- put(s[0]);
- }
- else
- put(s);
- }
- put('\n');
- }
- else {
- int n = hpos - output_hpos;
- if (vpos == output_vpos
- && (!gcol || gcol == current_glyph_color)
- && (!fcol || fcol == current_fill_color)
- && n > 0 && n < 100) {
- put(char(n/10 + '0'));
- put(char(n%10 + '0'));
- put(c);
- output_hpos = hpos;
- }
- else {
- do_motion();
- glyph_color(gcol);
- fill_color(fcol);
- put('c');
- put(c);
- }
- }
-}
-
-void troff_output_file::set_font(tfont *tf)
-{
- if (current_tfont == tf)
- return;
- int n = tf->get_input_position();
- symbol nm = tf->get_name();
- if (n >= nfont_positions || font_position[n] != nm) {
- put("x font ");
- put(n);
- put(' ');
- put(nm.contents());
- put('\n');
- if (n >= nfont_positions) {
- int old_nfont_positions = nfont_positions;
- symbol *old_font_position = font_position;
- nfont_positions *= 3;
- nfont_positions /= 2;
- if (nfont_positions <= n)
- nfont_positions = n + 10;
- font_position = new symbol[nfont_positions];
- memcpy(font_position, old_font_position,
- old_nfont_positions*sizeof(symbol));
- a_delete old_font_position;
- }
- font_position[n] = nm;
- }
- if (current_font_number != n) {
- put('f');
- put(n);
- put('\n');
- current_font_number = n;
- }
- int size = tf->get_size().to_scaled_points();
- if (current_size != size) {
- put('s');
- put(size);
- put('\n');
- current_size = size;
- }
- int slant = tf->get_slant();
- if (current_slant != slant) {
- put("x Slant ");
- put(slant);
- put('\n');
- current_slant = slant;
- }
- int height = tf->get_height();
- if (current_height != height) {
- put("x Height ");
- put(height == 0 ? current_size : height);
- put('\n');
- current_height = height;
- }
- current_tfont = tf;
-}
-
-void troff_output_file::fill_color(color *col)
-{
- if (!col || current_fill_color == col || !color_flag)
- return;
- flush_tbuf();
- put("DF");
- unsigned int components[4];
- color_scheme cs;
- cs = col->get_components(components);
- switch (cs) {
- case DEFAULT:
- put('d');
- break;
- case RGB:
- put("r ");
- put(Red);
- put(' ');
- put(Green);
- put(' ');
- put(Blue);
- break;
- case CMY:
- put("c ");
- put(Cyan);
- put(' ');
- put(Magenta);
- put(' ');
- put(Yellow);
- break;
- case CMYK:
- put("k ");
- put(Cyan);
- put(' ');
- put(Magenta);
- put(' ');
- put(Yellow);
- put(' ');
- put(Black);
- break;
- case GRAY:
- put("g ");
- put(Gray);
- break;
- }
- put('\n');
- current_fill_color = col;
-}
-
-void troff_output_file::glyph_color(color *col)
-{
- if (!col || current_glyph_color == col || !color_flag)
- return;
- flush_tbuf();
- put("m");
- unsigned int components[4];
- color_scheme cs;
- cs = col->get_components(components);
- switch (cs) {
- case DEFAULT:
- put('d');
- break;
- case RGB:
- put("r ");
- put(Red);
- put(' ');
- put(Green);
- put(' ');
- put(Blue);
- break;
- case CMY:
- put("c ");
- put(Cyan);
- put(' ');
- put(Magenta);
- put(' ');
- put(Yellow);
- break;
- case CMYK:
- put("k ");
- put(Cyan);
- put(' ');
- put(Magenta);
- put(' ');
- put(Yellow);
- put(' ');
- put(Black);
- break;
- case GRAY:
- put("g ");
- put(Gray);
- break;
- }
- put('\n');
- current_glyph_color = col;
-}
-
-// determine_line_limits - works out the smallest box which will contain
-// the entity, code, built from the point array.
-void troff_output_file::determine_line_limits(char code, hvpair *point,
- int npoints)
-{
- int i, x, y;
-
- if (!is_on())
- return;
-
- switch (code) {
- case 'c':
- case 'C':
- // only the h field is used when defining a circle
- check_output_limits(output_hpos,
- output_vpos - point[0].h.to_units()/2);
- check_output_limits(output_hpos + point[0].h.to_units(),
- output_vpos + point[0].h.to_units()/2);
- break;
- case 'E':
- case 'e':
- check_output_limits(output_hpos,
- output_vpos - point[0].v.to_units()/2);
- check_output_limits(output_hpos + point[0].h.to_units(),
- output_vpos + point[0].v.to_units()/2);
- break;
- case 'P':
- case 'p':
- x = output_hpos;
- y = output_vpos;
- check_output_limits(x, y);
- for (i = 0; i < npoints; i++) {
- x += point[i].h.to_units();
- y += point[i].v.to_units();
- check_output_limits(x, y);
- }
- break;
- case 't':
- x = output_hpos;
- y = output_vpos;
- for (i = 0; i < npoints; i++) {
- x += point[i].h.to_units();
- y += point[i].v.to_units();
- check_output_limits(x, y);
- }
- break;
- case 'a':
- double c[2];
- int p[4];
- int minx, miny, maxx, maxy;
- x = output_hpos;
- y = output_vpos;
- p[0] = point[0].h.to_units();
- p[1] = point[0].v.to_units();
- p[2] = point[1].h.to_units();
- p[3] = point[1].v.to_units();
- if (adjust_arc_center(p, c)) {
- check_output_arc_limits(x, y,
- p[0], p[1], p[2], p[3],
- c[0], c[1],
- &minx, &maxx, &miny, &maxy);
- check_output_limits(minx, miny);
- check_output_limits(maxx, maxy);
- break;
- }
- // fall through
- case 'l':
- x = output_hpos;
- y = output_vpos;
- check_output_limits(x, y);
- for (i = 0; i < npoints; i++) {
- x += point[i].h.to_units();
- y += point[i].v.to_units();
- check_output_limits(x, y);
- }
- break;
- default:
- x = output_hpos;
- y = output_vpos;
- for (i = 0; i < npoints; i++) {
- x += point[i].h.to_units();
- y += point[i].v.to_units();
- check_output_limits(x, y);
- }
- }
-}
-
-void troff_output_file::draw(char code, hvpair *point, int npoints,
- font_size fsize, color *gcol, color *fcol)
-{
- int i;
- flush_tbuf();
- do_motion();
- glyph_color(gcol);
- fill_color(fcol);
- if (is_on()) {
- int size = fsize.to_scaled_points();
- if (current_size != size) {
- put('s');
- put(size);
- put('\n');
- current_size = size;
- current_tfont = 0;
- }
- put('D');
- put(code);
- if (code == 'c') {
- put(' ');
- put(point[0].h.to_units());
- }
- else
- for (i = 0; i < npoints; i++) {
- put(' ');
- put(point[i].h.to_units());
- put(' ');
- put(point[i].v.to_units());
- }
- determine_line_limits(code, point, npoints);
- }
-
- for (i = 0; i < npoints; i++)
- output_hpos += point[i].h.to_units();
- hpos = output_hpos;
- if (code != 'e') {
- for (i = 0; i < npoints; i++)
- output_vpos += point[i].v.to_units();
- vpos = output_vpos;
- }
- if (is_on())
- put('\n');
-}
-
-void troff_output_file::really_on()
-{
- flush_tbuf();
- force_motion = 1;
- do_motion();
-}
-
-void troff_output_file::really_off()
-{
- flush_tbuf();
-}
-
-void troff_output_file::really_put_filename(const char *filename)
-{
- flush_tbuf();
- put("F ");
- put(filename);
- put('\n');
-}
-
-void troff_output_file::really_begin_page(int pageno, vunits page_length)
-{
- flush_tbuf();
- if (begun_page) {
- if (page_length > V0) {
- put('V');
- put(page_length.to_units());
- put('\n');
- }
- }
- else
- begun_page = 1;
- current_tfont = 0;
- current_font_number = -1;
- current_size = 0;
- // current_height = 0;
- // current_slant = 0;
- hpos = 0;
- vpos = 0;
- output_hpos = 0;
- output_vpos = 0;
- force_motion = 1;
- for (int i = 0; i < nfont_positions; i++)
- font_position[i] = NULL_SYMBOL;
- put('p');
- put(pageno);
- put('\n');
-}
-
-void troff_output_file::really_copy_file(hunits x, vunits y, const char *filename)
-{
- moveto(x, y);
- flush_tbuf();
- do_motion();
- errno = 0;
- FILE *ifp = fopen(filename, "r");
- if (ifp == 0)
- error("can't open `%1': %2", filename, strerror(errno));
- else {
- int c;
- while ((c = getc(ifp)) != EOF)
- put(char(c));
- fclose(ifp);
- }
- force_motion = 1;
- current_size = 0;
- current_tfont = 0;
- current_font_number = -1;
- for (int i = 0; i < nfont_positions; i++)
- font_position[i] = NULL_SYMBOL;
-}
-
-void troff_output_file::really_transparent_char(unsigned char c)
-{
- put(c);
-}
-
-troff_output_file::~troff_output_file()
-{
- a_delete font_position;
-}
-
-void troff_output_file::trailer(vunits page_length)
-{
- flush_tbuf();
- if (page_length > V0) {
- put("x trailer\n");
- put('V');
- put(page_length.to_units());
- put('\n');
- }
- put("x stop\n");
-}
-
-troff_output_file::troff_output_file()
-: current_slant(0), current_height(0), nfont_positions(10), tbuf_len(0),
- begun_page(0)
-{
- font_position = new symbol[nfont_positions];
- put("x T ");
- put(device);
- put('\n');
- put("x res ");
- put(units_per_inch);
- put(' ');
- put(hresolution);
- put(' ');
- put(vresolution);
- put('\n');
- put("x init\n");
-}
-
-/* output_file */
-
-output_file *the_output = 0;
-
-output_file::output_file()
-{
-}
-
-output_file::~output_file()
-{
-}
-
-void output_file::trailer(vunits)
-{
-}
-
-void output_file::put_filename(const char *filename)
-{
-}
-
-void output_file::on()
-{
-}
-
-void output_file::off()
-{
-}
-
-real_output_file::real_output_file()
-: printing(0), output_on(1)
-{
-#ifndef POPEN_MISSING
- if (pipe_command) {
- if ((fp = popen(pipe_command, POPEN_WT)) != 0) {
- piped = 1;
- return;
- }
- error("pipe open failed: %1", strerror(errno));
- }
- piped = 0;
-#endif /* not POPEN_MISSING */
- fp = stdout;
-}
-
-real_output_file::~real_output_file()
-{
- if (!fp)
- return;
- // To avoid looping, set fp to 0 before calling fatal().
- if (ferror(fp) || fflush(fp) < 0) {
- fp = 0;
- fatal("error writing output file");
- }
-#ifndef POPEN_MISSING
- if (piped) {
- int result = pclose(fp);
- fp = 0;
- if (result < 0)
- fatal("pclose failed");
- if (!WIFEXITED(result))
- error("output process `%1' got fatal signal %2",
- pipe_command,
- WIFSIGNALED(result) ? WTERMSIG(result) : WSTOPSIG(result));
- else {
- int exit_status = WEXITSTATUS(result);
- if (exit_status != 0)
- error("output process `%1' exited with status %2",
- pipe_command, exit_status);
- }
- }
- else
-#endif /* not POPEN MISSING */
- if (fclose(fp) < 0) {
- fp = 0;
- fatal("error closing output file");
- }
-}
-
-void real_output_file::flush()
-{
- if (fflush(fp) < 0)
- fatal("error writing output file");
-}
-
-int real_output_file::is_printing()
-{
- return printing;
-}
-
-void real_output_file::begin_page(int pageno, vunits page_length)
-{
- printing = in_output_page_list(pageno);
- if (printing)
- really_begin_page(pageno, page_length);
-}
-
-void real_output_file::copy_file(hunits x, vunits y, const char *filename)
-{
- if (printing && output_on)
- really_copy_file(x, y, filename);
- check_output_limits(x.to_units(), y.to_units());
-}
-
-void real_output_file::transparent_char(unsigned char c)
-{
- if (printing && output_on)
- really_transparent_char(c);
-}
-
-void real_output_file::print_line(hunits x, vunits y, node *n,
- vunits before, vunits after, hunits width)
-{
- if (printing)
- really_print_line(x, y, n, before, after, width);
- delete_node_list(n);
-}
-
-void real_output_file::really_copy_file(hunits, vunits, const char *)
-{
- // do nothing
-}
-
-void real_output_file::put_filename(const char *filename)
-{
- really_put_filename(filename);
-}
-
-void real_output_file::really_put_filename(const char *filename)
-{
-}
-
-void real_output_file::on()
-{
- really_on();
- if (output_on == 0)
- output_on = 1;
-}
-
-void real_output_file::off()
-{
- really_off();
- output_on = 0;
-}
-
-int real_output_file::is_on()
-{
- return output_on;
-}
-
-void real_output_file::really_on()
-{
-}
-
-void real_output_file::really_off()
-{
-}
-
-/* ascii_output_file */
-
-void ascii_output_file::really_transparent_char(unsigned char c)
-{
- putc(c, fp);
-}
-
-void ascii_output_file::really_print_line(hunits, vunits, node *n, vunits, vunits, hunits width)
-{
- while (n != 0) {
- n->ascii_print(this);
- n = n->next;
- }
- fputc('\n', fp);
-}
-
-void ascii_output_file::really_begin_page(int /*pageno*/, vunits /*page_length*/)
-{
- fputs("\n", fp);
-}
-
-ascii_output_file::ascii_output_file()
-{
-}
-
-/* suppress_output_file */
-
-suppress_output_file::suppress_output_file()
-{
-}
-
-void suppress_output_file::really_print_line(hunits, vunits, node *, vunits, vunits, hunits)
-{
-}
-
-void suppress_output_file::really_begin_page(int, vunits)
-{
-}
-
-void suppress_output_file::really_transparent_char(unsigned char)
-{
-}
-
-/* glyphs, ligatures, kerns, discretionary breaks */
-
-class charinfo_node : public node {
-protected:
- charinfo *ci;
-public:
- charinfo_node(charinfo *, node * = 0);
- int ends_sentence();
- int overlaps_vertically();
- int overlaps_horizontally();
-};
-
-charinfo_node::charinfo_node(charinfo *c, node *x)
-: node(x), ci(c)
-{
-}
-
-int charinfo_node::ends_sentence()
-{
- if (ci->ends_sentence())
- return 1;
- else if (ci->transparent())
- return 2;
- else
- return 0;
-}
-
-int charinfo_node::overlaps_horizontally()
-{
- return ci->overlaps_horizontally();
-}
-
-int charinfo_node::overlaps_vertically()
-{
- return ci->overlaps_vertically();
-}
-
-class glyph_node : public charinfo_node {
- static glyph_node *free_list;
-protected:
- tfont *tf;
- color *gcol;
- color *fcol; /* this is needed for grotty */
-#ifdef STORE_WIDTH
- hunits wid;
- glyph_node(charinfo *, tfont *, color *, color *, hunits, node * = 0);
-#endif
-public:
- void *operator new(size_t);
- void operator delete(void *);
- glyph_node(charinfo *, tfont *, color *, color *, node * = 0);
- ~glyph_node() {}
- node *copy();
- node *merge_glyph_node(glyph_node *);
- node *merge_self(node *);
- hunits width();
- node *last_char_node();
- units size();
- void vertical_extent(vunits *, vunits *);
- hunits subscript_correction();
- hunits italic_correction();
- hunits left_italic_correction();
- hunits skew();
- hyphenation_type get_hyphenation_type();
- tfont *get_tfont();
- color *get_glyph_color();
- color *get_fill_color();
- void tprint(troff_output_file *);
- void zero_width_tprint(troff_output_file *);
- hyphen_list *get_hyphen_list(hyphen_list *ss = 0);
- node *add_self(node *, hyphen_list **);
- void ascii_print(ascii_output_file *);
- void asciify(macro *);
- int character_type();
- int same(node *);
- const char *type();
- int force_tprint();
-};
-
-glyph_node *glyph_node::free_list = 0;
-
-class ligature_node : public glyph_node {
- node *n1;
- node *n2;
-#ifdef STORE_WIDTH
- ligature_node(charinfo *, tfont *, color *, color *, hunits,
- node *, node *, node * = 0);
-#endif
-public:
- void *operator new(size_t);
- void operator delete(void *);
- ligature_node(charinfo *, tfont *, color *, color *,
- node *, node *, node * = 0);
- ~ligature_node();
- node *copy();
- node *add_self(node *, hyphen_list **);
- hyphen_list *get_hyphen_list(hyphen_list *ss = 0);
- void ascii_print(ascii_output_file *);
- void asciify(macro *);
- int same(node *);
- const char *type();
- int force_tprint();
-};
-
-class kern_pair_node : public node {
- hunits amount;
- node *n1;
- node *n2;
-public:
- kern_pair_node(hunits n, node *first, node *second, node *x = 0);
- ~kern_pair_node();
- node *copy();
- node *merge_glyph_node(glyph_node *);
- node *add_self(node *, hyphen_list **);
- hyphen_list *get_hyphen_list(hyphen_list *ss = 0);
- node *add_discretionary_hyphen();
- hunits width();
- node *last_char_node();
- hunits italic_correction();
- hunits subscript_correction();
- void tprint(troff_output_file *);
- hyphenation_type get_hyphenation_type();
- int ends_sentence();
- void ascii_print(ascii_output_file *);
- void asciify(macro *);
- int same(node *);
- const char *type();
- int force_tprint();
- void vertical_extent(vunits *, vunits *);
-};
-
-class dbreak_node : public node {
- node *none;
- node *pre;
- node *post;
-public:
- dbreak_node(node *n, node *p, node *x = 0);
- ~dbreak_node();
- node *copy();
- node *merge_glyph_node(glyph_node *);
- node *add_discretionary_hyphen();
- hunits width();
- node *last_char_node();
- hunits italic_correction();
- hunits subscript_correction();
- void tprint(troff_output_file *);
- breakpoint *get_breakpoints(hunits width, int ns, breakpoint *rest = 0,
- int is_inner = 0);
- int nbreaks();
- int ends_sentence();
- void split(int, node **, node **);
- hyphenation_type get_hyphenation_type();
- void ascii_print(ascii_output_file *);
- void asciify(macro *);
- int same(node *);
- const char *type();
- int force_tprint();
-};
-
-void *glyph_node::operator new(size_t n)
-{
- assert(n == sizeof(glyph_node));
- if (!free_list) {
- const int BLOCK = 1024;
- free_list = (glyph_node *)new char[sizeof(glyph_node)*BLOCK];
- for (int i = 0; i < BLOCK - 1; i++)
- free_list[i].next = free_list + i + 1;
- free_list[BLOCK-1].next = 0;
- }
- glyph_node *p = free_list;
- free_list = (glyph_node *)(free_list->next);
- p->next = 0;
- return p;
-}
-
-void *ligature_node::operator new(size_t n)
-{
- return new char[n];
-}
-
-void glyph_node::operator delete(void *p)
-{
- if (p) {
- ((glyph_node *)p)->next = free_list;
- free_list = (glyph_node *)p;
- }
-}
-
-void ligature_node::operator delete(void *p)
-{
- delete[] (char *)p;
-}
-
-glyph_node::glyph_node(charinfo *c, tfont *t, color *gc, color *fc, node *x)
-: charinfo_node(c, x), tf(t), gcol(gc), fcol(fc)
-{
-#ifdef STORE_WIDTH
- wid = tf->get_width(ci);
-#endif
-}
-
-#ifdef STORE_WIDTH
-glyph_node::glyph_node(charinfo *c, tfont *t,
- color *gc, color *fc, hunits w, node *x)
-: charinfo_node(c, x), tf(t), gcol(gc), fcol(fc), wid(w)
-{
-}
-#endif
-
-node *glyph_node::copy()
-{
-#ifdef STORE_WIDTH
- return new glyph_node(ci, tf, gcol, fcol, wid);
-#else
- return new glyph_node(ci, tf, gcol, fcol);
-#endif
-}
-
-node *glyph_node::merge_self(node *nd)
-{
- return nd->merge_glyph_node(this);
-}
-
-int glyph_node::character_type()
-{
- return tf->get_character_type(ci);
-}
-
-node *glyph_node::add_self(node *n, hyphen_list **p)
-{
- assert(ci->get_hyphenation_code() == (*p)->hyphenation_code);
- next = 0;
- node *nn;
- if (n == 0 || (nn = n->merge_glyph_node(this)) == 0) {
- next = n;
- nn = this;
- }
- if ((*p)->hyphen)
- nn = nn->add_discretionary_hyphen();
- hyphen_list *pp = *p;
- *p = (*p)->next;
- delete pp;
- return nn;
-}
-
-units glyph_node::size()
-{
- return tf->get_size().to_units();
-}
-
-hyphen_list *glyph_node::get_hyphen_list(hyphen_list *tail)
-{
- return new hyphen_list(ci->get_hyphenation_code(), tail);
-}
-
-tfont *node::get_tfont()
-{
- return 0;
-}
-
-tfont *glyph_node::get_tfont()
-{
- return tf;
-}
-
-color *node::get_glyph_color()
-{
- return 0;
-}
-
-color *glyph_node::get_glyph_color()
-{
- return gcol;
-}
-
-color *node::get_fill_color()
-{
- return 0;
-}
-
-color *glyph_node::get_fill_color()
-{
- return fcol;
-}
-
-node *node::merge_glyph_node(glyph_node * /*gn*/)
-{
- return 0;
-}
-
-node *glyph_node::merge_glyph_node(glyph_node *gn)
-{
- if (tf == gn->tf && gcol == gn->gcol && fcol == gn->fcol) {
- charinfo *lig;
- if ((lig = tf->get_lig(ci, gn->ci)) != 0) {
- node *next1 = next;
- next = 0;
- return new ligature_node(lig, tf, gcol, fcol, this, gn, next1);
- }
- hunits kern;
- if (tf->get_kern(ci, gn->ci, &kern)) {
- node *next1 = next;
- next = 0;
- return new kern_pair_node(kern, this, gn, next1);
- }
- }
- return 0;
-}
-
-#ifdef STORE_WIDTH
-inline
-#endif
-hunits glyph_node::width()
-{
-#ifdef STORE_WIDTH
- return wid;
-#else
- return tf->get_width(ci);
-#endif
-}
-
-node *glyph_node::last_char_node()
-{
- return this;
-}
-
-void glyph_node::vertical_extent(vunits *min, vunits *max)
-{
- *min = -tf->get_char_height(ci);
- *max = tf->get_char_depth(ci);
-}
-
-hunits glyph_node::skew()
-{
- return tf->get_char_skew(ci);
-}
-
-hunits glyph_node::subscript_correction()
-{
- return tf->get_subscript_correction(ci);
-}
-
-hunits glyph_node::italic_correction()
-{
- return tf->get_italic_correction(ci);
-}
-
-hunits glyph_node::left_italic_correction()
-{
- return tf->get_left_italic_correction(ci);
-}
-
-hyphenation_type glyph_node::get_hyphenation_type()
-{
- return HYPHEN_MIDDLE;
-}
-
-void glyph_node::ascii_print(ascii_output_file *ascii)
-{
- unsigned char c = ci->get_ascii_code();
- if (c != 0)
- ascii->outc(c);
- else
- ascii->outs(ci->nm.contents());
-}
-
-ligature_node::ligature_node(charinfo *c, tfont *t, color *gc, color *fc,
- node *gn1, node *gn2, node *x)
-: glyph_node(c, t, gc, fc, x), n1(gn1), n2(gn2)
-{
-}
-
-#ifdef STORE_WIDTH
-ligature_node::ligature_node(charinfo *c, tfont *t, color *gc, color *fc,
- hunits w, node *gn1, node *gn2, node *x)
-: glyph_node(c, t, gc, fc, w, x), n1(gn1), n2(gn2)
-{
-}
-#endif
-
-ligature_node::~ligature_node()
-{
- delete n1;
- delete n2;
-}
-
-node *ligature_node::copy()
-{
-#ifdef STORE_WIDTH
- return new ligature_node(ci, tf, gcol, fcol, wid, n1->copy(), n2->copy());
-#else
- return new ligature_node(ci, tf, gcol, fcol, n1->copy(), n2->copy());
-#endif
-}
-
-void ligature_node::ascii_print(ascii_output_file *ascii)
-{
- n1->ascii_print(ascii);
- n2->ascii_print(ascii);
-}
-
-hyphen_list *ligature_node::get_hyphen_list(hyphen_list *tail)
-{
- return n1->get_hyphen_list(n2->get_hyphen_list(tail));
-}
-
-node *ligature_node::add_self(node *n, hyphen_list **p)
-{
- n = n1->add_self(n, p);
- n = n2->add_self(n, p);
- n1 = n2 = 0;
- delete this;
- return n;
-}
-
-kern_pair_node::kern_pair_node(hunits n, node *first, node *second, node *x)
-: node(x), amount(n), n1(first), n2(second)
-{
-}
-
-dbreak_node::dbreak_node(node *n, node *p, node *x)
-: node(x), none(n), pre(p), post(0)
-{
-}
-
-node *dbreak_node::merge_glyph_node(glyph_node *gn)
-{
- glyph_node *gn2 = (glyph_node *)gn->copy();
- node *new_none = none ? none->merge_glyph_node(gn) : 0;
- node *new_post = post ? post->merge_glyph_node(gn2) : 0;
- if (new_none == 0 && new_post == 0) {
- delete gn2;
- return 0;
- }
- if (new_none != 0)
- none = new_none;
- else {
- gn->next = none;
- none = gn;
- }
- if (new_post != 0)
- post = new_post;
- else {
- gn2->next = post;
- post = gn2;
- }
- return this;
-}
-
-node *kern_pair_node::merge_glyph_node(glyph_node *gn)
-{
- node *nd = n2->merge_glyph_node(gn);
- if (nd == 0)
- return 0;
- n2 = nd;
- nd = n2->merge_self(n1);
- if (nd) {
- nd->next = next;
- n1 = 0;
- n2 = 0;
- delete this;
- return nd;
- }
- return this;
-}
-
-hunits kern_pair_node::italic_correction()
-{
- return n2->italic_correction();
-}
-
-hunits kern_pair_node::subscript_correction()
-{
- return n2->subscript_correction();
-}
-
-void kern_pair_node::vertical_extent(vunits *min, vunits *max)
-{
- n1->vertical_extent(min, max);
- vunits min2, max2;
- n2->vertical_extent(&min2, &max2);
- if (min2 < *min)
- *min = min2;
- if (max2 > *max)
- *max = max2;
-}
-
-node *kern_pair_node::add_discretionary_hyphen()
-{
- tfont *tf = n2->get_tfont();
- if (tf) {
- if (tf->contains(soft_hyphen_char)) {
- color *gcol = n2->get_glyph_color();
- color *fcol = n2->get_fill_color();
- node *next1 = next;
- next = 0;
- node *n = copy();
- glyph_node *gn = new glyph_node(soft_hyphen_char, tf, gcol, fcol);
- node *nn = n->merge_glyph_node(gn);
- if (nn == 0) {
- gn->next = n;
- nn = gn;
- }
- return new dbreak_node(this, nn, next1);
- }
- }
- return this;
-}
-
-kern_pair_node::~kern_pair_node()
-{
- if (n1 != 0)
- delete n1;
- if (n2 != 0)
- delete n2;
-}
-
-dbreak_node::~dbreak_node()
-{
- delete_node_list(pre);
- delete_node_list(post);
- delete_node_list(none);
-}
-
-node *kern_pair_node::copy()
-{
- return new kern_pair_node(amount, n1->copy(), n2->copy());
-}
-
-node *copy_node_list(node *n)
-{
- node *p = 0;
- while (n != 0) {
- node *nn = n->copy();
- nn->next = p;
- p = nn;
- n = n->next;
- }
- while (p != 0) {
- node *pp = p->next;
- p->next = n;
- n = p;
- p = pp;
- }
- return n;
-}
-
-void delete_node_list(node *n)
-{
- while (n != 0) {
- node *tem = n;
- n = n->next;
- delete tem;
- }
-}
-
-node *dbreak_node::copy()
-{
- dbreak_node *p = new dbreak_node(copy_node_list(none), copy_node_list(pre));
- p->post = copy_node_list(post);
- return p;
-}
-
-hyphen_list *node::get_hyphen_list(hyphen_list *tail)
-{
- return tail;
-}
-
-hyphen_list *kern_pair_node::get_hyphen_list(hyphen_list *tail)
-{
- return n1->get_hyphen_list(n2->get_hyphen_list(tail));
-}
-
-class hyphen_inhibitor_node : public node {
-public:
- hyphen_inhibitor_node(node *nd = 0);
- node *copy();
- int same(node *);
- const char *type();
- int force_tprint();
- hyphenation_type get_hyphenation_type();
-};
-
-hyphen_inhibitor_node::hyphen_inhibitor_node(node *nd) : node(nd)
-{
-}
-
-node *hyphen_inhibitor_node::copy()
-{
- return new hyphen_inhibitor_node;
-}
-
-int hyphen_inhibitor_node::same(node *)
-{
- return 1;
-}
-
-const char *hyphen_inhibitor_node::type()
-{
- return "hyphen_inhibitor_node";
-}
-
-int hyphen_inhibitor_node::force_tprint()
-{
- return 0;
-}
-
-hyphenation_type hyphen_inhibitor_node::get_hyphenation_type()
-{
- return HYPHEN_INHIBIT;
-}
-
-/* add_discretionary_hyphen methods */
-
-node *dbreak_node::add_discretionary_hyphen()
-{
- if (post)
- post = post->add_discretionary_hyphen();
- if (none)
- none = none->add_discretionary_hyphen();
- return this;
-}
-
-node *node::add_discretionary_hyphen()
-{
- tfont *tf = get_tfont();
- if (!tf)
- return new hyphen_inhibitor_node(this);
- if (tf->contains(soft_hyphen_char)) {
- color *gcol = get_glyph_color();
- color *fcol = get_fill_color();
- node *next1 = next;
- next = 0;
- node *n = copy();
- glyph_node *gn = new glyph_node(soft_hyphen_char, tf, gcol, fcol);
- node *n1 = n->merge_glyph_node(gn);
- if (n1 == 0) {
- gn->next = n;
- n1 = gn;
- }
- return new dbreak_node(this, n1, next1);
- }
- return this;
-}
-
-node *node::merge_self(node *)
-{
- return 0;
-}
-
-node *node::add_self(node *n, hyphen_list ** /*p*/)
-{
- next = n;
- return this;
-}
-
-node *kern_pair_node::add_self(node *n, hyphen_list **p)
-{
- n = n1->add_self(n, p);
- n = n2->add_self(n, p);
- n1 = n2 = 0;
- delete this;
- return n;
-}
-
-hunits node::width()
-{
- return H0;
-}
-
-node *node::last_char_node()
-{
- return 0;
-}
-
-int node::force_tprint()
-{
- return 0;
-}
-
-hunits hmotion_node::width()
-{
- return n;
-}
-
-units node::size()
-{
- return points_to_units(10);
-}
-
-hunits kern_pair_node::width()
-{
- return n1->width() + n2->width() + amount;
-}
-
-node *kern_pair_node::last_char_node()
-{
- node *nd = n2->last_char_node();
- if (nd)
- return nd;
- return n1->last_char_node();
-}
-
-hunits dbreak_node::width()
-{
- hunits x = H0;
- for (node *n = none; n != 0; n = n->next)
- x += n->width();
- return x;
-}
-
-node *dbreak_node::last_char_node()
-{
- for (node *n = none; n; n = n->next) {
- node *last = n->last_char_node();
- if (last)
- return last;
- }
- return 0;
-}
-
-hunits dbreak_node::italic_correction()
-{
- return none ? none->italic_correction() : H0;
-}
-
-hunits dbreak_node::subscript_correction()
-{
- return none ? none->subscript_correction() : H0;
-}
-
-class italic_corrected_node : public node {
- node *n;
- hunits x;
-public:
- italic_corrected_node(node *, hunits, node * = 0);
- ~italic_corrected_node();
- node *copy();
- void ascii_print(ascii_output_file *);
- void asciify(macro *);
- hunits width();
- node *last_char_node();
- void vertical_extent(vunits *, vunits *);
- int ends_sentence();
- int overlaps_horizontally();
- int overlaps_vertically();
- int same(node *);
- hyphenation_type get_hyphenation_type();
- tfont *get_tfont();
- hyphen_list *get_hyphen_list(hyphen_list *ss = 0);
- int character_type();
- void tprint(troff_output_file *);
- hunits subscript_correction();
- hunits skew();
- node *add_self(node *, hyphen_list **);
- const char *type();
- int force_tprint();
-};
-
-node *node::add_italic_correction(hunits *width)
-{
- hunits ic = italic_correction();
- if (ic.is_zero())
- return this;
- else {
- node *next1 = next;
- next = 0;
- *width += ic;
- return new italic_corrected_node(this, ic, next1);
- }
-}
-
-italic_corrected_node::italic_corrected_node(node *nn, hunits xx, node *p)
-: node(p), n(nn), x(xx)
-{
- assert(n != 0);
-}
-
-italic_corrected_node::~italic_corrected_node()
-{
- delete n;
-}
-
-node *italic_corrected_node::copy()
-{
- return new italic_corrected_node(n->copy(), x);
-}
-
-hunits italic_corrected_node::width()
-{
- return n->width() + x;
-}
-
-void italic_corrected_node::vertical_extent(vunits *min, vunits *max)
-{
- n->vertical_extent(min, max);
-}
-
-void italic_corrected_node::tprint(troff_output_file *out)
-{
- n->tprint(out);
- out->right(x);
-}
-
-hunits italic_corrected_node::skew()
-{
- return n->skew() - x/2;
-}
-
-hunits italic_corrected_node::subscript_correction()
-{
- return n->subscript_correction() - x;
-}
-
-void italic_corrected_node::ascii_print(ascii_output_file *out)
-{
- n->ascii_print(out);
-}
-
-int italic_corrected_node::ends_sentence()
-{
- return n->ends_sentence();
-}
-
-int italic_corrected_node::overlaps_horizontally()
-{
- return n->overlaps_horizontally();
-}
-
-int italic_corrected_node::overlaps_vertically()
-{
- return n->overlaps_vertically();
-}
-
-node *italic_corrected_node::last_char_node()
-{
- return n->last_char_node();
-}
-
-tfont *italic_corrected_node::get_tfont()
-{
- return n->get_tfont();
-}
-
-hyphenation_type italic_corrected_node::get_hyphenation_type()
-{
- return n->get_hyphenation_type();
-}
-
-node *italic_corrected_node::add_self(node *nd, hyphen_list **p)
-{
- nd = n->add_self(nd, p);
- hunits not_interested;
- nd = nd->add_italic_correction(¬_interested);
- n = 0;
- delete this;
- return nd;
-}
-
-hyphen_list *italic_corrected_node::get_hyphen_list(hyphen_list *tail)
-{
- return n->get_hyphen_list(tail);
-}
-
-int italic_corrected_node::character_type()
-{
- return n->character_type();
-}
-
-class break_char_node : public node {
- node *ch;
- char break_code;
- color *col;
-public:
- break_char_node(node *, int, color *, node * = 0);
- ~break_char_node();
- node *copy();
- hunits width();
- vunits vertical_width();
- node *last_char_node();
- int character_type();
- int ends_sentence();
- node *add_self(node *, hyphen_list **);
- hyphen_list *get_hyphen_list(hyphen_list *s = 0);
- void tprint(troff_output_file *);
- void zero_width_tprint(troff_output_file *);
- void ascii_print(ascii_output_file *);
- void asciify(macro *);
- hyphenation_type get_hyphenation_type();
- int overlaps_vertically();
- int overlaps_horizontally();
- units size();
- tfont *get_tfont();
- int same(node *);
- const char *type();
- int force_tprint();
-};
-
-break_char_node::break_char_node(node *n, int bc, color *c, node *x)
-: node(x), ch(n), break_code(bc), col(c)
-{
-}
-
-break_char_node::~break_char_node()
-{
- delete ch;
-}
-
-node *break_char_node::copy()
-{
- return new break_char_node(ch->copy(), break_code, col);
-}
-
-hunits break_char_node::width()
-{
- return ch->width();
-}
-
-vunits break_char_node::vertical_width()
-{
- return ch->vertical_width();
-}
-
-node *break_char_node::last_char_node()
-{
- return ch->last_char_node();
-}
-
-int break_char_node::character_type()
-{
- return ch->character_type();
-}
-
-int break_char_node::ends_sentence()
-{
- return ch->ends_sentence();
-}
-
-node *break_char_node::add_self(node *n, hyphen_list **p)
-{
- assert((*p)->hyphenation_code == 0);
- if ((*p)->breakable && (break_code & 1)) {
- n = new space_node(H0, col, n);
- n->freeze_space();
- }
- next = n;
- n = this;
- if ((*p)->breakable && (break_code & 2)) {
- n = new space_node(H0, col, n);
- n->freeze_space();
- }
- hyphen_list *pp = *p;
- *p = (*p)->next;
- delete pp;
- return n;
-}
-
-hyphen_list *break_char_node::get_hyphen_list(hyphen_list *tail)
-{
- return new hyphen_list(0, tail);
-}
-
-hyphenation_type break_char_node::get_hyphenation_type()
-{
- return HYPHEN_MIDDLE;
-}
-
-void break_char_node::ascii_print(ascii_output_file *ascii)
-{
- ch->ascii_print(ascii);
-}
-
-int break_char_node::overlaps_vertically()
-{
- return ch->overlaps_vertically();
-}
-
-int break_char_node::overlaps_horizontally()
-{
- return ch->overlaps_horizontally();
-}
-
-units break_char_node::size()
-{
- return ch->size();
-}
-
-tfont *break_char_node::get_tfont()
-{
- return ch->get_tfont();
-}
-
-node *extra_size_node::copy()
-{
- return new extra_size_node(n);
-}
-
-node *vertical_size_node::copy()
-{
- return new vertical_size_node(n);
-}
-
-node *hmotion_node::copy()
-{
- return new hmotion_node(n, was_tab, unformat, col);
-}
-
-node *space_char_hmotion_node::copy()
-{
- return new space_char_hmotion_node(n, col);
-}
-
-node *vmotion_node::copy()
-{
- return new vmotion_node(n, col);
-}
-
-node *dummy_node::copy()
-{
- return new dummy_node;
-}
-
-node *transparent_dummy_node::copy()
-{
- return new transparent_dummy_node;
-}
-
-hline_node::~hline_node()
-{
- if (n)
- delete n;
-}
-
-node *hline_node::copy()
-{
- return new hline_node(x, n ? n->copy() : 0);
-}
-
-hunits hline_node::width()
-{
- return x < H0 ? H0 : x;
-}
-
-vline_node::~vline_node()
-{
- if (n)
- delete n;
-}
-
-node *vline_node::copy()
-{
- return new vline_node(x, n ? n->copy() : 0);
-}
-
-hunits vline_node::width()
-{
- return n == 0 ? H0 : n->width();
-}
-
-zero_width_node::zero_width_node(node *nd) : n(nd)
-{
-}
-
-zero_width_node::~zero_width_node()
-{
- delete_node_list(n);
-}
-
-node *zero_width_node::copy()
-{
- return new zero_width_node(copy_node_list(n));
-}
-
-int node_list_character_type(node *p)
-{
- int t = 0;
- for (; p; p = p->next)
- t |= p->character_type();
- return t;
-}
-
-int zero_width_node::character_type()
-{
- return node_list_character_type(n);
-}
-
-void node_list_vertical_extent(node *p, vunits *min, vunits *max)
-{
- *min = V0;
- *max = V0;
- vunits cur_vpos = V0;
- vunits v1, v2;
- for (; p; p = p->next) {
- p->vertical_extent(&v1, &v2);
- v1 += cur_vpos;
- if (v1 < *min)
- *min = v1;
- v2 += cur_vpos;
- if (v2 > *max)
- *max = v2;
- cur_vpos += p->vertical_width();
- }
-}
-
-void zero_width_node::vertical_extent(vunits *min, vunits *max)
-{
- node_list_vertical_extent(n, min, max);
-}
-
-overstrike_node::overstrike_node() : list(0), max_width(H0)
-{
-}
-
-overstrike_node::~overstrike_node()
-{
- delete_node_list(list);
-}
-
-node *overstrike_node::copy()
-{
- overstrike_node *on = new overstrike_node;
- for (node *tem = list; tem; tem = tem->next)
- on->overstrike(tem->copy());
- return on;
-}
-
-void overstrike_node::overstrike(node *n)
-{
- if (n == 0)
- return;
- hunits w = n->width();
- if (w > max_width)
- max_width = w;
- node **p;
- for (p = &list; *p; p = &(*p)->next)
- ;
- n->next = 0;
- *p = n;
-}
-
-hunits overstrike_node::width()
-{
- return max_width;
-}
-
-bracket_node::bracket_node() : list(0), max_width(H0)
-{
-}
-
-bracket_node::~bracket_node()
-{
- delete_node_list(list);
-}
-
-node *bracket_node::copy()
-{
- bracket_node *on = new bracket_node;
- node *last = 0;
- node *tem;
- if (list)
- list->last = 0;
- for (tem = list; tem; tem = tem->next) {
- if (tem->next)
- tem->next->last = tem;
- last = tem;
- }
- for (tem = last; tem; tem = tem->last)
- on->bracket(tem->copy());
- return on;
-}
-
-void bracket_node::bracket(node *n)
-{
- if (n == 0)
- return;
- hunits w = n->width();
- if (w > max_width)
- max_width = w;
- n->next = list;
- list = n;
-}
-
-hunits bracket_node::width()
-{
- return max_width;
-}
-
-int node::nspaces()
-{
- return 0;
-}
-
-int node::merge_space(hunits, hunits, hunits)
-{
- return 0;
-}
-
-#if 0
-space_node *space_node::free_list = 0;
-
-void *space_node::operator new(size_t n)
-{
- assert(n == sizeof(space_node));
- if (!free_list) {
- free_list = (space_node *)new char[sizeof(space_node)*BLOCK];
- for (int i = 0; i < BLOCK - 1; i++)
- free_list[i].next = free_list + i + 1;
- free_list[BLOCK-1].next = 0;
- }
- space_node *p = free_list;
- free_list = (space_node *)(free_list->next);
- p->next = 0;
- return p;
-}
-
-inline void space_node::operator delete(void *p)
-{
- if (p) {
- ((space_node *)p)->next = free_list;
- free_list = (space_node *)p;
- }
-}
-#endif
-
-space_node::space_node(hunits nn, color *c, node *p)
-: node(p), n(nn), set(0), was_escape_colon(0), col(c)
-{
-}
-
-space_node::space_node(hunits nn, int s, int flag, color *c, node *p)
-: node(p), n(nn), set(s), was_escape_colon(flag), col(c)
-{
-}
-
-#if 0
-space_node::~space_node()
-{
-}
-#endif
-
-node *space_node::copy()
-{
- return new space_node(n, set, was_escape_colon, col);
-}
-
-int space_node::force_tprint()
-{
- return 0;
-}
-
-int space_node::nspaces()
-{
- return set ? 0 : 1;
-}
-
-int space_node::merge_space(hunits h, hunits, hunits)
-{
- n += h;
- return 1;
-}
-
-hunits space_node::width()
-{
- return n;
-}
-
-void node::spread_space(int*, hunits*)
-{
-}
-
-void space_node::spread_space(int *nspaces, hunits *desired_space)
-{
- if (!set) {
- assert(*nspaces > 0);
- if (*nspaces == 1) {
- n += *desired_space;
- *desired_space = H0;
- }
- else {
- hunits extra = *desired_space / *nspaces;
- *desired_space -= extra;
- n += extra;
- }
- *nspaces -= 1;
- set = 1;
- }
-}
-
-void node::freeze_space()
-{
-}
-
-void space_node::freeze_space()
-{
- set = 1;
-}
-
-void node::is_escape_colon()
-{
-}
-
-void space_node::is_escape_colon()
-{
- was_escape_colon = 1;
-}
-
-diverted_space_node::diverted_space_node(vunits d, node *p)
-: node(p), n(d)
-{
-}
-
-node *diverted_space_node::copy()
-{
- return new diverted_space_node(n);
-}
-
-diverted_copy_file_node::diverted_copy_file_node(symbol s, node *p)
-: node(p), filename(s)
-{
-}
-
-node *diverted_copy_file_node::copy()
-{
- return new diverted_copy_file_node(filename);
-}
-
-int node::ends_sentence()
-{
- return 0;
-}
-
-int kern_pair_node::ends_sentence()
-{
- switch (n2->ends_sentence()) {
- case 0:
- return 0;
- case 1:
- return 1;
- case 2:
- break;
- default:
- assert(0);
- }
- return n1->ends_sentence();
-}
-
-int node_list_ends_sentence(node *n)
-{
- for (; n != 0; n = n->next)
- switch (n->ends_sentence()) {
- case 0:
- return 0;
- case 1:
- return 1;
- case 2:
- break;
- default:
- assert(0);
- }
- return 2;
-}
-
-int dbreak_node::ends_sentence()
-{
- return node_list_ends_sentence(none);
-}
-
-int node::overlaps_horizontally()
-{
- return 0;
-}
-
-int node::overlaps_vertically()
-{
- return 0;
-}
-
-int node::discardable()
-{
- return 0;
-}
-
-int space_node::discardable()
-{
- return set ? 0 : 1;
-}
-
-vunits node::vertical_width()
-{
- return V0;
-}
-
-vunits vline_node::vertical_width()
-{
- return x;
-}
-
-vunits vmotion_node::vertical_width()
-{
- return n;
-}
-
-int node::set_unformat_flag()
-{
- return 1;
-}
-
-int node::character_type()
-{
- return 0;
-}
-
-hunits node::subscript_correction()
-{
- return H0;
-}
-
-hunits node::italic_correction()
-{
- return H0;
-}
-
-hunits node::left_italic_correction()
-{
- return H0;
-}
-
-hunits node::skew()
-{
- return H0;
-}
-
-/* vertical_extent methods */
-
-void node::vertical_extent(vunits *min, vunits *max)
-{
- vunits v = vertical_width();
- if (v < V0) {
- *min = v;
- *max = V0;
- }
- else {
- *max = v;
- *min = V0;
- }
-}
-
-void vline_node::vertical_extent(vunits *min, vunits *max)
-{
- if (n == 0)
- node::vertical_extent(min, max);
- else {
- vunits cmin, cmax;
- n->vertical_extent(&cmin, &cmax);
- vunits h = n->size();
- if (x < V0) {
- if (-x < h) {
- *min = x;
- *max = V0;
- }
- else {
- // we print the first character and then move up, so
- *max = cmax;
- // we print the last character and then move up h
- *min = cmin + h;
- if (*min > V0)
- *min = V0;
- *min += x;
- }
- }
- else {
- if (x < h) {
- *max = x;
- *min = V0;
- }
- else {
- // we move down by h and then print the first character, so
- *min = cmin + h;
- if (*min > V0)
- *min = V0;
- *max = x + cmax;
- }
- }
- }
-}
-
-/* ascii_print methods */
-
-static void ascii_print_reverse_node_list(ascii_output_file *ascii, node *n)
-{
- if (n == 0)
- return;
- ascii_print_reverse_node_list(ascii, n->next);
- n->ascii_print(ascii);
-}
-
-void dbreak_node::ascii_print(ascii_output_file *ascii)
-{
- ascii_print_reverse_node_list(ascii, none);
-}
-
-void kern_pair_node::ascii_print(ascii_output_file *ascii)
-{
- n1->ascii_print(ascii);
- n2->ascii_print(ascii);
-}
-
-void node::ascii_print(ascii_output_file *)
-{
-}
-
-void space_node::ascii_print(ascii_output_file *ascii)
-{
- if (!n.is_zero())
- ascii->outc(' ');
-}
-
-void hmotion_node::ascii_print(ascii_output_file *ascii)
-{
- // this is pretty arbitrary
- if (n >= points_to_units(2))
- ascii->outc(' ');
-}
-
-void space_char_hmotion_node::ascii_print(ascii_output_file *ascii)
-{
- ascii->outc(' ');
-}
-
-/* asciify methods */
-
-void node::asciify(macro *m)
-{
- m->append(this);
-}
-
-void glyph_node::asciify(macro *m)
-{
- unsigned char c = ci->get_asciify_code();
- if (c == 0)
- c = ci->get_ascii_code();
- if (c != 0) {
- m->append(c);
- delete this;
- }
- else
- m->append(this);
-}
-
-void kern_pair_node::asciify(macro *m)
-{
- n1->asciify(m);
- n2->asciify(m);
- n1 = n2 = 0;
- delete this;
-}
-
-static void asciify_reverse_node_list(macro *m, node *n)
-{
- if (n == 0)
- return;
- asciify_reverse_node_list(m, n->next);
- n->asciify(m);
-}
-
-void dbreak_node::asciify(macro *m)
-{
- asciify_reverse_node_list(m, none);
- none = 0;
- delete this;
-}
-
-void ligature_node::asciify(macro *m)
-{
- n1->asciify(m);
- n2->asciify(m);
- n1 = n2 = 0;
- delete this;
-}
-
-void break_char_node::asciify(macro *m)
-{
- ch->asciify(m);
- ch = 0;
- delete this;
-}
-
-void italic_corrected_node::asciify(macro *m)
-{
- n->asciify(m);
- n = 0;
- delete this;
-}
-
-void left_italic_corrected_node::asciify(macro *m)
-{
- if (n) {
- n->asciify(m);
- n = 0;
- }
- delete this;
-}
-
-void hmotion_node::asciify(macro *m)
-{
- if (was_tab) {
- m->append('\t');
- delete this;
- }
- else
- m->append(this);
-}
-
-space_char_hmotion_node::space_char_hmotion_node(hunits i, color *c,
- node *next)
-: hmotion_node(i, c, next)
-{
-}
-
-void space_char_hmotion_node::asciify(macro *m)
-{
- m->append(ESCAPE_SPACE);
- delete this;
-}
-
-void space_node::asciify(macro *m)
-{
- if (was_escape_colon) {
- m->append(ESCAPE_COLON);
- delete this;
- }
- else
- m->append(this);
-}
-
-void word_space_node::asciify(macro *m)
-{
- for (width_list *w = orig_width; w; w = w->next)
- m->append(' ');
- delete this;
-}
-
-void unbreakable_space_node::asciify(macro *m)
-{
- m->append(ESCAPE_TILDE);
- delete this;
-}
-
-void line_start_node::asciify(macro *)
-{
- delete this;
-}
-
-void vertical_size_node::asciify(macro *)
-{
- delete this;
-}
-
-breakpoint *node::get_breakpoints(hunits /*width*/, int /*nspaces*/,
- breakpoint *rest, int /*is_inner*/)
-{
- return rest;
-}
-
-int node::nbreaks()
-{
- return 0;
-}
-
-breakpoint *space_node::get_breakpoints(hunits width, int ns,
- breakpoint *rest, int is_inner)
-{
- if (next->discardable())
- return rest;
- breakpoint *bp = new breakpoint;
- bp->next = rest;
- bp->width = width;
- bp->nspaces = ns;
- bp->hyphenated = 0;
- if (is_inner) {
- assert(rest != 0);
- bp->index = rest->index + 1;
- bp->nd = rest->nd;
- }
- else {
- bp->nd = this;
- bp->index = 0;
- }
- return bp;
-}
-
-int space_node::nbreaks()
-{
- if (next->discardable())
- return 0;
- else
- return 1;
-}
-
-static breakpoint *node_list_get_breakpoints(node *p, hunits *widthp,
- int ns, breakpoint *rest)
-{
- if (p != 0) {
- rest = p->get_breakpoints(*widthp,
- ns,
- node_list_get_breakpoints(p->next, widthp, ns,
- rest),
- 1);
- *widthp += p->width();
- }
- return rest;
-}
-
-breakpoint *dbreak_node::get_breakpoints(hunits width, int ns,
- breakpoint *rest, int is_inner)
-{
- breakpoint *bp = new breakpoint;
- bp->next = rest;
- bp->width = width;
- for (node *tem = pre; tem != 0; tem = tem->next)
- bp->width += tem->width();
- bp->nspaces = ns;
- bp->hyphenated = 1;
- if (is_inner) {
- assert(rest != 0);
- bp->index = rest->index + 1;
- bp->nd = rest->nd;
- }
- else {
- bp->nd = this;
- bp->index = 0;
- }
- return node_list_get_breakpoints(none, &width, ns, bp);
-}
-
-int dbreak_node::nbreaks()
-{
- int i = 1;
- for (node *tem = none; tem != 0; tem = tem->next)
- i += tem->nbreaks();
- return i;
-}
-
-void node::split(int /*where*/, node ** /*prep*/, node ** /*postp*/)
-{
- assert(0);
-}
-
-void space_node::split(int where, node **pre, node **post)
-{
- assert(where == 0);
- *pre = next;
- *post = 0;
- delete this;
-}
-
-static void node_list_split(node *p, int *wherep, node **prep, node **postp)
-{
- if (p == 0)
- return;
- int nb = p->nbreaks();
- node_list_split(p->next, wherep, prep, postp);
- if (*wherep < 0) {
- p->next = *postp;
- *postp = p;
- }
- else if (*wherep < nb) {
- p->next = *prep;
- p->split(*wherep, prep, postp);
- }
- else {
- p->next = *prep;
- *prep = p;
- }
- *wherep -= nb;
-}
-
-void dbreak_node::split(int where, node **prep, node **postp)
-{
- assert(where >= 0);
- if (where == 0) {
- *postp = post;
- post = 0;
- if (pre == 0)
- *prep = next;
- else {
- node *tem;
- for (tem = pre; tem->next != 0; tem = tem->next)
- ;
- tem->next = next;
- *prep = pre;
- }
- pre = 0;
- delete this;
- }
- else {
- *prep = next;
- where -= 1;
- node_list_split(none, &where, prep, postp);
- none = 0;
- delete this;
- }
-}
-
-hyphenation_type node::get_hyphenation_type()
-{
- return HYPHEN_BOUNDARY;
-}
-
-hyphenation_type dbreak_node::get_hyphenation_type()
-{
- return HYPHEN_INHIBIT;
-}
-
-hyphenation_type kern_pair_node::get_hyphenation_type()
-{
- return HYPHEN_MIDDLE;
-}
-
-hyphenation_type dummy_node::get_hyphenation_type()
-{
- return HYPHEN_MIDDLE;
-}
-
-hyphenation_type transparent_dummy_node::get_hyphenation_type()
-{
- return HYPHEN_MIDDLE;
-}
-
-hyphenation_type hmotion_node::get_hyphenation_type()
-{
- return HYPHEN_MIDDLE;
-}
-
-hyphenation_type space_char_hmotion_node::get_hyphenation_type()
-{
- return HYPHEN_MIDDLE;
-}
-
-hyphenation_type overstrike_node::get_hyphenation_type()
-{
- return HYPHEN_MIDDLE;
-}
-
-hyphenation_type space_node::get_hyphenation_type()
-{
- if (was_escape_colon)
- return HYPHEN_MIDDLE;
- return HYPHEN_BOUNDARY;
-}
-
-hyphenation_type unbreakable_space_node::get_hyphenation_type()
-{
- return HYPHEN_MIDDLE;
-}
-
-int node::interpret(macro *)
-{
- return 0;
-}
-
-special_node::special_node(const macro &m, int n)
-: mac(m), no_init_string(n)
-{
- font_size fs = curenv->get_font_size();
- int char_height = curenv->get_char_height();
- int char_slant = curenv->get_char_slant();
- int fontno = env_definite_font(curenv);
- tf = font_table[fontno]->get_tfont(fs, char_height, char_slant, fontno);
- if (curenv->is_composite())
- tf = tf->get_plain();
- gcol = curenv->get_glyph_color();
- fcol = curenv->get_fill_color();
-}
-
-special_node::special_node(const macro &m, tfont *t,
- color *gc, color *fc, int n)
-: mac(m), tf(t), gcol(gc), fcol(fc), no_init_string(n)
-{
-}
-
-int special_node::same(node *n)
-{
- return mac == ((special_node *)n)->mac
- && tf == ((special_node *)n)->tf
- && gcol == ((special_node *)n)->gcol
- && fcol == ((special_node *)n)->fcol
- && no_init_string == ((special_node *)n)->no_init_string;
-}
-
-const char *special_node::type()
-{
- return "special_node";
-}
-
-int special_node::ends_sentence()
-{
- return 2;
-}
-
-int special_node::force_tprint()
-{
- return 0;
-}
-
-node *special_node::copy()
-{
- return new special_node(mac, tf, gcol, fcol, no_init_string);
-}
-
-void special_node::tprint_start(troff_output_file *out)
-{
- out->start_special(tf, gcol, fcol, no_init_string);
-}
-
-void special_node::tprint_char(troff_output_file *out, unsigned char c)
-{
- out->special_char(c);
-}
-
-void special_node::tprint_end(troff_output_file *out)
-{
- out->end_special();
-}
-
-tfont *special_node::get_tfont()
-{
- return tf;
-}
-
-/* suppress_node */
-
-suppress_node::suppress_node(int on_or_off, int issue_limits)
-: is_on(on_or_off), emit_limits(issue_limits),
- filename(0), position(0), image_id(0)
-{
-}
-
-suppress_node::suppress_node(symbol f, char p, int id)
-: is_on(2), emit_limits(0), filename(f), position(p), image_id(id)
-{
-}
-
-suppress_node::suppress_node(int issue_limits, int on_or_off,
- symbol f, char p, int id)
-: is_on(on_or_off), emit_limits(issue_limits),
- filename(f), position(p), image_id(id)
-{
-}
-
-int suppress_node::same(node *n)
-{
- return ((is_on == ((suppress_node *)n)->is_on)
- && (emit_limits == ((suppress_node *)n)->emit_limits)
- && (filename == ((suppress_node *)n)->filename)
- && (position == ((suppress_node *)n)->position)
- && (image_id == ((suppress_node *)n)->image_id));
-}
-
-const char *suppress_node::type()
-{
- return "suppress_node";
-}
-
-node *suppress_node::copy()
-{
- return new suppress_node(emit_limits, is_on, filename, position, image_id);
-}
-
-int get_reg_int(const char *p)
-{
- reg *r = (reg *)number_reg_dictionary.lookup(p);
- units prev_value;
- if (r && (r->get_value(&prev_value)))
- return (int)prev_value;
- else
- warning(WARN_REG, "number register `%1' not defined", p);
- return 0;
-}
-
-const char *get_reg_str(const char *p)
-{
- reg *r = (reg *)number_reg_dictionary.lookup(p);
- if (r)
- return r->get_string();
- else
- warning(WARN_REG, "register `%1' not defined", p);
- return 0;
-}
-
-void suppress_node::put(troff_output_file *out, const char *s)
-{
- int i = 0;
- while (s[i] != (char)0) {
- out->special_char(s[i]);
- i++;
- }
-}
-
-/*
- * We need to remember the start of the image and its name.
- */
-
-static char last_position = 0;
-static const char *last_image_filename = 0;
-static int last_image_id = 0;
-
-inline int min(int a, int b)
-{
- return a < b ? a : b;
-}
-
-/*
- * tprint - if (is_on == 2)
- * remember current position (l, r, c, i) and filename
- * else
- * if (emit_limits)
- * if (html)
- * emit image tag
- * else
- * emit postscript bounds for image
- * else
- * if (suppress boolean differs from current state)
- * alter state
- * reset registers
- * record current page
- * set low water mark.
- */
-
-void suppress_node::tprint(troff_output_file *out)
-{
- int current_page = topdiv->get_page_number();
- // firstly check to see whether this suppress node contains
- // an image filename & position.
- if (is_on == 2) {
- // remember position and filename
- last_position = position;
- last_image_filename = strdup(filename.contents());
- last_image_id = image_id;
- // printf("start of image and page = %d\n", current_page);
- }
- else {
- // now check whether the suppress node requires us to issue limits.
- if (emit_limits) {
- char name[8192];
- // remember that the filename will contain a %d in which the
- // last_image_id is placed
- sprintf(name, last_image_filename, last_image_id);
- if (is_html) {
- switch (last_position) {
- case 'c':
- out->start_special();
- put(out, "html-tag:.centered-image");
- break;
- case 'r':
- out->start_special();
- put(out, "html-tag:.right-image");
- break;
- case 'l':
- out->start_special();
- put(out, "html-tag:.left-image");
- break;
- case 'i':
- ;
- default:
- ;
- }
- out->end_special();
- out->start_special();
- put(out, "html-tag:.auto-image ");
- put(out, name);
- out->end_special();
- }
- else {
- // postscript (or other device)
- if (suppress_start_page > 0 && current_page != suppress_start_page)
- error("suppression limit registers span more than one page;\n"
- "image description %1 will be wrong", image_no);
- // if (topdiv->get_page_number() != suppress_start_page)
- // fprintf(stderr, "end of image and topdiv page = %d and suppress_start_page = %d\n",
- // topdiv->get_page_number(), suppress_start_page);
-
- // remember that the filename will contain a %d in which the
- // image_no is placed
- fprintf(stderr,
- "grohtml-info:page %d %d %d %d %d %d %s %d %d %s\n",
- topdiv->get_page_number(),
- get_reg_int("opminx"), get_reg_int("opminy"),
- get_reg_int("opmaxx"), get_reg_int("opmaxy"),
- // page offset + line length
- get_reg_int(".o") + get_reg_int(".l"),
- name, hresolution, vresolution, get_reg_str(".F"));
- fflush(stderr);
- }
- }
- else {
- if (is_on) {
- out->on();
- // lastly we reset the output registers
- reset_output_registers(out->get_vpos());
- }
- else
- out->off();
- suppress_start_page = current_page;
- }
- }
-}
-
-int suppress_node::force_tprint()
-{
- return is_on;
-}
-
-hunits suppress_node::width()
-{
- return H0;
-}
-
-/* composite_node */
-
-class composite_node : public charinfo_node {
- node *n;
- tfont *tf;
-public:
- composite_node(node *, charinfo *, tfont *, node * = 0);
- ~composite_node();
- node *copy();
- hunits width();
- node *last_char_node();
- units size();
- void tprint(troff_output_file *);
- hyphenation_type get_hyphenation_type();
- void ascii_print(ascii_output_file *);
- void asciify(macro *);
- hyphen_list *get_hyphen_list(hyphen_list *tail);
- node *add_self(node *, hyphen_list **);
- tfont *get_tfont();
- int same(node *);
- const char *type();
- int force_tprint();
- void vertical_extent(vunits *, vunits *);
- vunits vertical_width();
-};
-
-composite_node::composite_node(node *p, charinfo *c, tfont *t, node *x)
-: charinfo_node(c, x), n(p), tf(t)
-{
-}
-
-composite_node::~composite_node()
-{
- delete_node_list(n);
-}
-
-node *composite_node::copy()
-{
- return new composite_node(copy_node_list(n), ci, tf);
-}
-
-hunits composite_node::width()
-{
- hunits x;
- if (tf->get_constant_space(&x))
- return x;
- x = H0;
- for (node *tem = n; tem; tem = tem->next)
- x += tem->width();
- hunits offset;
- if (tf->get_bold(&offset))
- x += offset;
- x += tf->get_track_kern();
- return x;
-}
-
-node *composite_node::last_char_node()
-{
- return this;
-}
-
-vunits composite_node::vertical_width()
-{
- vunits v = V0;
- for (node *tem = n; tem; tem = tem->next)
- v += tem->vertical_width();
- return v;
-}
-
-units composite_node::size()
-{
- return tf->get_size().to_units();
-}
-
-hyphenation_type composite_node::get_hyphenation_type()
-{
- return HYPHEN_MIDDLE;
-}
-
-void composite_node::asciify(macro *m)
-{
- unsigned char c = ci->get_asciify_code();
- if (c == 0)
- c = ci->get_ascii_code();
- if (c != 0) {
- m->append(c);
- delete this;
- }
- else
- m->append(this);
-}
-
-void composite_node::ascii_print(ascii_output_file *ascii)
-{
- unsigned char c = ci->get_ascii_code();
- if (c != 0)
- ascii->outc(c);
- else
- ascii->outs(ci->nm.contents());
-
-}
-
-hyphen_list *composite_node::get_hyphen_list(hyphen_list *tail)
-{
- return new hyphen_list(ci->get_hyphenation_code(), tail);
-}
-
-node *composite_node::add_self(node *nn, hyphen_list **p)
-{
- assert(ci->get_hyphenation_code() == (*p)->hyphenation_code);
- next = nn;
- nn = this;
- if ((*p)->hyphen)
- nn = nn->add_discretionary_hyphen();
- hyphen_list *pp = *p;
- *p = (*p)->next;
- delete pp;
- return nn;
-}
-
-tfont *composite_node::get_tfont()
-{
- return tf;
-}
-
-node *reverse_node_list(node *n)
-{
- node *r = 0;
- while (n) {
- node *tem = n;
- n = n->next;
- tem->next = r;
- r = tem;
- }
- return r;
-}
-
-void composite_node::vertical_extent(vunits *min, vunits *max)
-{
- n = reverse_node_list(n);
- node_list_vertical_extent(n, min, max);
- n = reverse_node_list(n);
-}
-
-width_list::width_list(hunits w, hunits s)
-: width(w), sentence_width(s), next(0)
-{
-}
-
-width_list::width_list(width_list *w)
-: width(w->width), sentence_width(w->sentence_width), next(0)
-{
-}
-
-word_space_node::word_space_node(hunits d, color *c, width_list *w, node *x)
-: space_node(d, c, x), orig_width(w), unformat(0)
-{
-}
-
-word_space_node::word_space_node(hunits d, int s, color *c, width_list *w,
- int flag, node *x)
-: space_node(d, s, 0, c, x), orig_width(w), unformat(flag)
-{
-}
-
-word_space_node::~word_space_node()
-{
- width_list *w = orig_width;
- while (w != 0) {
- width_list *tmp = w;
- w = w->next;
- delete tmp;
- }
-}
-
-node *word_space_node::copy()
-{
- assert(orig_width != 0);
- width_list *w_old_curr = orig_width;
- width_list *w_new_curr = new width_list(w_old_curr);
- width_list *w_new = w_new_curr;
- w_old_curr = w_old_curr->next;
- while (w_old_curr != 0) {
- w_new_curr->next = new width_list(w_old_curr);
- w_new_curr = w_new_curr->next;
- w_old_curr = w_old_curr->next;
- }
- return new word_space_node(n, set, col, w_new, unformat);
-}
-
-int word_space_node::set_unformat_flag()
-{
- unformat = 1;
- return 1;
-}
-
-void word_space_node::tprint(troff_output_file *out)
-{
- out->fill_color(col);
- out->word_marker();
- out->right(n);
-}
-
-int word_space_node::merge_space(hunits h, hunits sw, hunits ssw)
-{
- n += h;
- assert(orig_width != 0);
- width_list *w = orig_width;
- for (; w->next; w = w->next)
- ;
- w->next = new width_list(sw, ssw);
- return 1;
-}
-
-unbreakable_space_node::unbreakable_space_node(hunits d, color *c, node *x)
-: word_space_node(d, c, 0, x)
-{
-}
-
-unbreakable_space_node::unbreakable_space_node(hunits d, int s,
- color *c, node *x)
-: word_space_node(d, s, c, 0, 0, x)
-{
-}
-
-node *unbreakable_space_node::copy()
-{
- return new unbreakable_space_node(n, set, col);
-}
-
-int unbreakable_space_node::force_tprint()
-{
- return 0;
-}
-
-breakpoint *unbreakable_space_node::get_breakpoints(hunits, int,
- breakpoint *rest, int)
-{
- return rest;
-}
-
-int unbreakable_space_node::nbreaks()
-{
- return 0;
-}
-
-void unbreakable_space_node::split(int, node **, node **)
-{
- assert(0);
-}
-
-int unbreakable_space_node::merge_space(hunits, hunits, hunits)
-{
- return 0;
-}
-
-hvpair::hvpair()
-{
-}
-
-draw_node::draw_node(char c, hvpair *p, int np, font_size s,
- color *gc, color *fc)
-: npoints(np), sz(s), gcol(gc), fcol(fc), code(c)
-{
- point = new hvpair[npoints];
- for (int i = 0; i < npoints; i++)
- point[i] = p[i];
-}
-
-int draw_node::same(node *n)
-{
- draw_node *nd = (draw_node *)n;
- if (code != nd->code || npoints != nd->npoints || sz != nd->sz
- || gcol != nd->gcol || fcol != nd->fcol)
- return 0;
- for (int i = 0; i < npoints; i++)
- if (point[i].h != nd->point[i].h || point[i].v != nd->point[i].v)
- return 0;
- return 1;
-}
-
-const char *draw_node::type()
-{
- return "draw_node";
-}
-
-int draw_node::force_tprint()
-{
- return 0;
-}
-
-draw_node::~draw_node()
-{
- if (point)
- a_delete point;
-}
-
-hunits draw_node::width()
-{
- hunits x = H0;
- for (int i = 0; i < npoints; i++)
- x += point[i].h;
- return x;
-}
-
-vunits draw_node::vertical_width()
-{
- if (code == 'e')
- return V0;
- vunits x = V0;
- for (int i = 0; i < npoints; i++)
- x += point[i].v;
- return x;
-}
-
-node *draw_node::copy()
-{
- return new draw_node(code, point, npoints, sz, gcol, fcol);
-}
-
-void draw_node::tprint(troff_output_file *out)
-{
- out->draw(code, point, npoints, sz, gcol, fcol);
-}
-
-/* tprint methods */
-
-void glyph_node::tprint(troff_output_file *out)
-{
- tfont *ptf = tf->get_plain();
- if (ptf == tf)
- out->put_char_width(ci, ptf, gcol, fcol, width(), H0);
- else {
- hunits offset;
- int bold = tf->get_bold(&offset);
- hunits w = ptf->get_width(ci);
- hunits k = H0;
- hunits x;
- int cs = tf->get_constant_space(&x);
- if (cs) {
- x -= w;
- if (bold)
- x -= offset;
- hunits x2 = x/2;
- out->right(x2);
- k = x - x2;
- }
- else
- k = tf->get_track_kern();
- if (bold) {
- out->put_char(ci, ptf, gcol, fcol);
- out->right(offset);
- }
- out->put_char_width(ci, ptf, gcol, fcol, w, k);
- }
-}
-
-void glyph_node::zero_width_tprint(troff_output_file *out)
-{
- tfont *ptf = tf->get_plain();
- hunits offset;
- int bold = tf->get_bold(&offset);
- hunits x;
- int cs = tf->get_constant_space(&x);
- if (cs) {
- x -= ptf->get_width(ci);
- if (bold)
- x -= offset;
- x = x/2;
- out->right(x);
- }
- out->put_char(ci, ptf, gcol, fcol);
- if (bold) {
- out->right(offset);
- out->put_char(ci, ptf, gcol, fcol);
- out->right(-offset);
- }
- if (cs)
- out->right(-x);
-}
-
-void break_char_node::tprint(troff_output_file *t)
-{
- ch->tprint(t);
-}
-
-void break_char_node::zero_width_tprint(troff_output_file *t)
-{
- ch->zero_width_tprint(t);
-}
-
-void hline_node::tprint(troff_output_file *out)
-{
- if (x < H0) {
- out->right(x);
- x = -x;
- }
- if (n == 0) {
- out->right(x);
- return;
- }
- hunits w = n->width();
- if (w <= H0) {
- error("horizontal line drawing character must have positive width");
- out->right(x);
- return;
- }
- int i = int(x/w);
- if (i == 0) {
- hunits xx = x - w;
- hunits xx2 = xx/2;
- out->right(xx2);
- if (out->is_on())
- n->tprint(out);
- out->right(xx - xx2);
- }
- else {
- hunits rem = x - w*i;
- if (rem > H0)
- if (n->overlaps_horizontally()) {
- if (out->is_on())
- n->tprint(out);
- out->right(rem - w);
- }
- else
- out->right(rem);
- while (--i >= 0)
- if (out->is_on())
- n->tprint(out);
- }
-}
-
-void vline_node::tprint(troff_output_file *out)
-{
- if (n == 0) {
- out->down(x);
- return;
- }
- vunits h = n->size();
- int overlaps = n->overlaps_vertically();
- vunits y = x;
- if (y < V0) {
- y = -y;
- int i = y / h;
- vunits rem = y - i*h;
- if (i == 0) {
- out->right(n->width());
- out->down(-rem);
- }
- else {
- while (--i > 0) {
- n->zero_width_tprint(out);
- out->down(-h);
- }
- if (overlaps) {
- n->zero_width_tprint(out);
- out->down(-rem);
- if (out->is_on())
- n->tprint(out);
- out->down(-h);
- }
- else {
- if (out->is_on())
- n->tprint(out);
- out->down(-h - rem);
- }
- }
- }
- else {
- int i = y / h;
- vunits rem = y - i*h;
- if (i == 0) {
- out->down(rem);
- out->right(n->width());
- }
- else {
- out->down(h);
- if (overlaps)
- n->zero_width_tprint(out);
- out->down(rem);
- while (--i > 0) {
- n->zero_width_tprint(out);
- out->down(h);
- }
- if (out->is_on())
- n->tprint(out);
- }
- }
-}
-
-void zero_width_node::tprint(troff_output_file *out)
-{
- if (!n)
- return;
- if (!n->next) {
- n->zero_width_tprint(out);
- return;
- }
- int hpos = out->get_hpos();
- int vpos = out->get_vpos();
- node *tem = n;
- while (tem) {
- tem->tprint(out);
- tem = tem->next;
- }
- out->moveto(hpos, vpos);
-}
-
-void overstrike_node::tprint(troff_output_file *out)
-{
- hunits pos = H0;
- for (node *tem = list; tem; tem = tem->next) {
- hunits x = (max_width - tem->width())/2;
- out->right(x - pos);
- pos = x;
- tem->zero_width_tprint(out);
- }
- out->right(max_width - pos);
-}
-
-void bracket_node::tprint(troff_output_file *out)
-{
- if (list == 0)
- return;
- int npieces = 0;
- node *tem;
- for (tem = list; tem; tem = tem->next)
- ++npieces;
- vunits h = list->size();
- vunits totalh = h*npieces;
- vunits y = (totalh - h)/2;
- out->down(y);
- for (tem = list; tem; tem = tem->next) {
- tem->zero_width_tprint(out);
- out->down(-h);
- }
- out->right(max_width);
- out->down(totalh - y);
-}
-
-void node::tprint(troff_output_file *)
-{
-}
-
-void node::zero_width_tprint(troff_output_file *out)
-{
- int hpos = out->get_hpos();
- int vpos = out->get_vpos();
- tprint(out);
- out->moveto(hpos, vpos);
-}
-
-void space_node::tprint(troff_output_file *out)
-{
- out->fill_color(col);
- out->right(n);
-}
-
-void hmotion_node::tprint(troff_output_file *out)
-{
- out->fill_color(col);
- out->right(n);
-}
-
-void vmotion_node::tprint(troff_output_file *out)
-{
- out->fill_color(col);
- out->down(n);
-}
-
-void kern_pair_node::tprint(troff_output_file *out)
-{
- n1->tprint(out);
- out->right(amount);
- n2->tprint(out);
-}
-
-static void tprint_reverse_node_list(troff_output_file *out, node *n)
-{
- if (n == 0)
- return;
- tprint_reverse_node_list(out, n->next);
- n->tprint(out);
-}
-
-void dbreak_node::tprint(troff_output_file *out)
-{
- tprint_reverse_node_list(out, none);
-}
-
-void composite_node::tprint(troff_output_file *out)
-{
- hunits bold_offset;
- int is_bold = tf->get_bold(&bold_offset);
- hunits track_kern = tf->get_track_kern();
- hunits constant_space;
- int is_constant_spaced = tf->get_constant_space(&constant_space);
- hunits x = H0;
- if (is_constant_spaced) {
- x = constant_space;
- for (node *tem = n; tem; tem = tem->next)
- x -= tem->width();
- if (is_bold)
- x -= bold_offset;
- hunits x2 = x/2;
- out->right(x2);
- x -= x2;
- }
- if (is_bold) {
- int hpos = out->get_hpos();
- int vpos = out->get_vpos();
- tprint_reverse_node_list(out, n);
- out->moveto(hpos, vpos);
- out->right(bold_offset);
- }
- tprint_reverse_node_list(out, n);
- if (is_constant_spaced)
- out->right(x);
- else
- out->right(track_kern);
-}
-
-node *make_composite_node(charinfo *s, environment *env)
-{
- int fontno = env_definite_font(env);
- if (fontno < 0) {
- error("no current font");
- return 0;
- }
- assert(fontno < font_table_size && font_table[fontno] != 0);
- node *n = charinfo_to_node_list(s, env);
- font_size fs = env->get_font_size();
- int char_height = env->get_char_height();
- int char_slant = env->get_char_slant();
- tfont *tf = font_table[fontno]->get_tfont(fs, char_height, char_slant,
- fontno);
- if (env->is_composite())
- tf = tf->get_plain();
- return new composite_node(n, s, tf);
-}
-
-node *make_glyph_node(charinfo *s, environment *env, int no_error_message = 0)
-{
- int fontno = env_definite_font(env);
- if (fontno < 0) {
- error("no current font");
- return 0;
- }
- assert(fontno < font_table_size && font_table[fontno] != 0);
- int fn = fontno;
- int found = font_table[fontno]->contains(s);
- if (!found) {
- if (s->is_fallback())
- return make_composite_node(s, env);
- if (s->numbered()) {
- if (!no_error_message)
- warning(WARN_CHAR, "can't find numbered character %1",
- s->get_number());
- return 0;
- }
- special_font_list *sf = font_table[fontno]->sf;
- while (sf != 0 && !found) {
- fn = sf->n;
- if (font_table[fn])
- found = font_table[fn]->contains(s);
- sf = sf->next;
- }
- if (!found) {
- sf = global_special_fonts;
- while (sf != 0 && !found) {
- fn = sf->n;
- if (font_table[fn])
- found = font_table[fn]->contains(s);
- sf = sf->next;
- }
- }
- if (!found
-#if 0
- && global_special_fonts == 0 && font_table[fontno]->sf == 0
-#endif
- ) {
- for (fn = 0; fn < font_table_size; fn++)
- if (font_table[fn]
- && font_table[fn]->is_special()
- && font_table[fn]->contains(s)) {
- found = 1;
- break;
- }
- }
- if (!found) {
- if (!no_error_message && s->first_time_not_found()) {
- unsigned char input_code = s->get_ascii_code();
- if (input_code != 0) {
- if (csgraph(input_code))
- warning(WARN_CHAR, "can't find character `%1'", input_code);
- else
- warning(WARN_CHAR, "can't find character with input code %1",
- int(input_code));
- }
- else if (s->nm.contents())
- warning(WARN_CHAR, "can't find special character `%1'",
- s->nm.contents());
- }
- return 0;
- }
- }
- font_size fs = env->get_font_size();
- int char_height = env->get_char_height();
- int char_slant = env->get_char_slant();
- tfont *tf = font_table[fontno]->get_tfont(fs, char_height, char_slant, fn);
- if (env->is_composite())
- tf = tf->get_plain();
- color *gcol = env->get_glyph_color();
- color *fcol = env->get_fill_color();
- return new glyph_node(s, tf, gcol, fcol);
-}
-
-node *make_node(charinfo *ci, environment *env)
-{
- switch (ci->get_special_translation()) {
- case charinfo::TRANSLATE_SPACE:
- return new space_char_hmotion_node(env->get_space_width(),
- env->get_fill_color());
- case charinfo::TRANSLATE_STRETCHABLE_SPACE:
- return new unbreakable_space_node(env->get_space_width(),
- env->get_fill_color());
- case charinfo::TRANSLATE_DUMMY:
- return new dummy_node;
- case charinfo::TRANSLATE_HYPHEN_INDICATOR:
- error("translation to \\% ignored in this context");
- break;
- }
- charinfo *tem = ci->get_translation();
- if (tem)
- ci = tem;
- macro *mac = ci->get_macro();
- if (mac && !ci->is_fallback())
- return make_composite_node(ci, env);
- else
- return make_glyph_node(ci, env);
-}
-
-int character_exists(charinfo *ci, environment *env)
-{
- if (ci->get_special_translation() != charinfo::TRANSLATE_NONE)
- return 1;
- charinfo *tem = ci->get_translation();
- if (tem)
- ci = tem;
- if (ci->get_macro())
- return 1;
- node *nd = make_glyph_node(ci, env, 1);
- if (nd) {
- delete nd;
- return 1;
- }
- return 0;
-}
-
-node *node::add_char(charinfo *ci, environment *env,
- hunits *widthp, int *spacep)
-{
- node *res;
- switch (ci->get_special_translation()) {
- case charinfo::TRANSLATE_SPACE:
- res = new space_char_hmotion_node(env->get_space_width(),
- env->get_fill_color(), this);
- *widthp += res->width();
- return res;
- case charinfo::TRANSLATE_STRETCHABLE_SPACE:
- res = new unbreakable_space_node(env->get_space_width(),
- env->get_fill_color(), this);
- res->freeze_space();
- *widthp += res->width();
- *spacep += res->nspaces();
- return res;
- case charinfo::TRANSLATE_DUMMY:
- return new dummy_node(this);
- case charinfo::TRANSLATE_HYPHEN_INDICATOR:
- return add_discretionary_hyphen();
- }
- charinfo *tem = ci->get_translation();
- if (tem)
- ci = tem;
- macro *mac = ci->get_macro();
- if (mac && !ci->is_fallback()) {
- res = make_composite_node(ci, env);
- if (res) {
- res->next = this;
- *widthp += res->width();
- }
- else
- return this;
- }
- else {
- node *gn = make_glyph_node(ci, env);
- if (gn == 0)
- return this;
- else {
- hunits old_width = width();
- node *p = gn->merge_self(this);
- if (p == 0) {
- *widthp += gn->width();
- gn->next = this;
- res = gn;
- }
- else {
- *widthp += p->width() - old_width;
- res = p;
- }
- }
- }
- int break_code = 0;
- if (ci->can_break_before())
- break_code = 1;
- if (ci->can_break_after())
- break_code |= 2;
- if (break_code) {
- node *next1 = res->next;
- res->next = 0;
- res = new break_char_node(res, break_code, env->get_fill_color(), next1);
- }
- return res;
-}
-
-#ifdef __GNUG__
-inline
-#endif
-int same_node(node *n1, node *n2)
-{
- if (n1 != 0) {
- if (n2 != 0)
- return n1->type() == n2->type() && n1->same(n2);
- else
- return 0;
- }
- else
- return n2 == 0;
-}
-
-int same_node_list(node *n1, node *n2)
-{
- while (n1 && n2) {
- if (n1->type() != n2->type() || !n1->same(n2))
- return 0;
- n1 = n1->next;
- n2 = n2->next;
- }
- return !n1 && !n2;
-}
-
-int extra_size_node::same(node *nd)
-{
- return n == ((extra_size_node *)nd)->n;
-}
-
-const char *extra_size_node::type()
-{
- return "extra_size_node";
-}
-
-int extra_size_node::force_tprint()
-{
- return 0;
-}
-
-int vertical_size_node::same(node *nd)
-{
- return n == ((vertical_size_node *)nd)->n;
-}
-
-const char *vertical_size_node::type()
-{
- return "vertical_size_node";
-}
-
-int vertical_size_node::set_unformat_flag()
-{
- return 0;
-}
-
-int vertical_size_node::force_tprint()
-{
- return 0;
-}
-
-int hmotion_node::same(node *nd)
-{
- return n == ((hmotion_node *)nd)->n
- && col == ((hmotion_node *)nd)->col;
-}
-
-const char *hmotion_node::type()
-{
- return "hmotion_node";
-}
-
-int hmotion_node::set_unformat_flag()
-{
- unformat = 1;
- return 1;
-}
-
-int hmotion_node::force_tprint()
-{
- return 0;
-}
-
-node *hmotion_node::add_self(node *n, hyphen_list **p)
-{
- next = n;
- hyphen_list *pp = *p;
- *p = (*p)->next;
- delete pp;
- return this;
-}
-
-hyphen_list *hmotion_node::get_hyphen_list(hyphen_list *tail)
-{
- return new hyphen_list(0, tail);
-}
-
-int space_char_hmotion_node::same(node *nd)
-{
- return n == ((space_char_hmotion_node *)nd)->n
- && col == ((space_char_hmotion_node *)nd)->col;
-}
-
-const char *space_char_hmotion_node::type()
-{
- return "space_char_hmotion_node";
-}
-
-int space_char_hmotion_node::force_tprint()
-{
- return 0;
-}
-
-node *space_char_hmotion_node::add_self(node *n, hyphen_list **p)
-{
- next = n;
- hyphen_list *pp = *p;
- *p = (*p)->next;
- delete pp;
- return this;
-}
-
-hyphen_list *space_char_hmotion_node::get_hyphen_list(hyphen_list *tail)
-{
- return new hyphen_list(0, tail);
-}
-
-int vmotion_node::same(node *nd)
-{
- return n == ((vmotion_node *)nd)->n
- && col == ((vmotion_node *)nd)->col;
-}
-
-const char *vmotion_node::type()
-{
- return "vmotion_node";
-}
-
-int vmotion_node::force_tprint()
-{
- return 0;
-}
-
-int hline_node::same(node *nd)
-{
- return x == ((hline_node *)nd)->x && same_node(n, ((hline_node *)nd)->n);
-}
-
-const char *hline_node::type()
-{
- return "hline_node";
-}
-
-int hline_node::force_tprint()
-{
- return 0;
-}
-
-int vline_node::same(node *nd)
-{
- return x == ((vline_node *)nd)->x && same_node(n, ((vline_node *)nd)->n);
-}
-
-const char *vline_node::type()
-{
- return "vline_node";
-}
-
-int vline_node::force_tprint()
-{
- return 0;
-}
-
-int dummy_node::same(node * /*nd*/)
-{
- return 1;
-}
-
-const char *dummy_node::type()
-{
- return "dummy_node";
-}
-
-int dummy_node::force_tprint()
-{
- return 0;
-}
-
-int transparent_dummy_node::same(node * /*nd*/)
-{
- return 1;
-}
-
-const char *transparent_dummy_node::type()
-{
- return "transparent_dummy_node";
-}
-
-int transparent_dummy_node::force_tprint()
-{
- return 0;
-}
-
-int transparent_dummy_node::ends_sentence()
-{
- return 2;
-}
-
-int zero_width_node::same(node *nd)
-{
- return same_node_list(n, ((zero_width_node *)nd)->n);
-}
-
-const char *zero_width_node::type()
-{
- return "zero_width_node";
-}
-
-int zero_width_node::force_tprint()
-{
- return 0;
-}
-
-int italic_corrected_node::same(node *nd)
-{
- return (x == ((italic_corrected_node *)nd)->x
- && same_node(n, ((italic_corrected_node *)nd)->n));
-}
-
-const char *italic_corrected_node::type()
-{
- return "italic_corrected_node";
-}
-
-int italic_corrected_node::force_tprint()
-{
- return 0;
-}
-
-left_italic_corrected_node::left_italic_corrected_node(node *x)
-: node(x), n(0)
-{
-}
-
-left_italic_corrected_node::~left_italic_corrected_node()
-{
- delete n;
-}
-
-node *left_italic_corrected_node::merge_glyph_node(glyph_node *gn)
-{
- if (n == 0) {
- hunits lic = gn->left_italic_correction();
- if (!lic.is_zero()) {
- x = lic;
- n = gn;
- return this;
- }
- }
- else {
- node *nd = n->merge_glyph_node(gn);
- if (nd) {
- n = nd;
- x = n->left_italic_correction();
- return this;
- }
- }
- return 0;
-}
-
-node *left_italic_corrected_node::copy()
-{
- left_italic_corrected_node *nd = new left_italic_corrected_node;
- if (n) {
- nd->n = n->copy();
- nd->x = x;
- }
- return nd;
-}
-
-void left_italic_corrected_node::tprint(troff_output_file *out)
-{
- if (n) {
- out->right(x);
- n->tprint(out);
- }
-}
-
-const char *left_italic_corrected_node::type()
-{
- return "left_italic_corrected_node";
-}
-
-int left_italic_corrected_node::force_tprint()
-{
- return 0;
-}
-
-int left_italic_corrected_node::same(node *nd)
-{
- return (x == ((left_italic_corrected_node *)nd)->x
- && same_node(n, ((left_italic_corrected_node *)nd)->n));
-}
-
-void left_italic_corrected_node::ascii_print(ascii_output_file *out)
-{
- if (n)
- n->ascii_print(out);
-}
-
-hunits left_italic_corrected_node::width()
-{
- return n ? n->width() + x : H0;
-}
-
-void left_italic_corrected_node::vertical_extent(vunits *min, vunits *max)
-{
- if (n)
- n->vertical_extent(min, max);
- else
- node::vertical_extent(min, max);
-}
-
-hunits left_italic_corrected_node::skew()
-{
- return n ? n->skew() + x/2 : H0;
-}
-
-hunits left_italic_corrected_node::subscript_correction()
-{
- return n ? n->subscript_correction() : H0;
-}
-
-hunits left_italic_corrected_node::italic_correction()
-{
- return n ? n->italic_correction() : H0;
-}
-
-int left_italic_corrected_node::ends_sentence()
-{
- return n ? n->ends_sentence() : 0;
-}
-
-int left_italic_corrected_node::overlaps_horizontally()
-{
- return n ? n->overlaps_horizontally() : 0;
-}
-
-int left_italic_corrected_node::overlaps_vertically()
-{
- return n ? n->overlaps_vertically() : 0;
-}
-
-node *left_italic_corrected_node::last_char_node()
-{
- return n ? n->last_char_node() : 0;
-}
-
-tfont *left_italic_corrected_node::get_tfont()
-{
- return n ? n->get_tfont() : 0;
-}
-
-hyphenation_type left_italic_corrected_node::get_hyphenation_type()
-{
- if (n)
- return n->get_hyphenation_type();
- else
- return HYPHEN_MIDDLE;
-}
-
-hyphen_list *left_italic_corrected_node::get_hyphen_list(hyphen_list *tail)
-{
- return n ? n->get_hyphen_list(tail) : tail;
-}
-
-node *left_italic_corrected_node::add_self(node *nd, hyphen_list **p)
-{
- if (n) {
- nd = new left_italic_corrected_node(nd);
- nd = n->add_self(nd, p);
- n = 0;
- delete this;
- }
- return nd;
-}
-
-int left_italic_corrected_node::character_type()
-{
- return n ? n->character_type() : 0;
-}
-
-int overstrike_node::same(node *nd)
-{
- return same_node_list(list, ((overstrike_node *)nd)->list);
-}
-
-const char *overstrike_node::type()
-{
- return "overstrike_node";
-}
-
-int overstrike_node::force_tprint()
-{
- return 0;
-}
-
-node *overstrike_node::add_self(node *n, hyphen_list **p)
-{
- next = n;
- hyphen_list *pp = *p;
- *p = (*p)->next;
- delete pp;
- return this;
-}
-
-hyphen_list *overstrike_node::get_hyphen_list(hyphen_list *tail)
-{
- return new hyphen_list(0, tail);
-}
-
-int bracket_node::same(node *nd)
-{
- return same_node_list(list, ((bracket_node *)nd)->list);
-}
-
-const char *bracket_node::type()
-{
- return "bracket_node";
-}
-
-int bracket_node::force_tprint()
-{
- return 0;
-}
-
-int composite_node::same(node *nd)
-{
- return ci == ((composite_node *)nd)->ci
- && same_node_list(n, ((composite_node *)nd)->n);
-}
-
-const char *composite_node::type()
-{
- return "composite_node";
-}
-
-int composite_node::force_tprint()
-{
- return 0;
-}
-
-int glyph_node::same(node *nd)
-{
- return ci == ((glyph_node *)nd)->ci
- && tf == ((glyph_node *)nd)->tf
- && gcol == ((glyph_node *)nd)->gcol
- && fcol == ((glyph_node *)nd)->fcol;
-}
-
-const char *glyph_node::type()
-{
- return "glyph_node";
-}
-
-int glyph_node::force_tprint()
-{
- return 0;
-}
-
-int ligature_node::same(node *nd)
-{
- return (same_node(n1, ((ligature_node *)nd)->n1)
- && same_node(n2, ((ligature_node *)nd)->n2)
- && glyph_node::same(nd));
-}
-
-const char *ligature_node::type()
-{
- return "ligature_node";
-}
-
-int ligature_node::force_tprint()
-{
- return 0;
-}
-
-int kern_pair_node::same(node *nd)
-{
- return (amount == ((kern_pair_node *)nd)->amount
- && same_node(n1, ((kern_pair_node *)nd)->n1)
- && same_node(n2, ((kern_pair_node *)nd)->n2));
-}
-
-const char *kern_pair_node::type()
-{
- return "kern_pair_node";
-}
-
-int kern_pair_node::force_tprint()
-{
- return 0;
-}
-
-int dbreak_node::same(node *nd)
-{
- return (same_node_list(none, ((dbreak_node *)nd)->none)
- && same_node_list(pre, ((dbreak_node *)nd)->pre)
- && same_node_list(post, ((dbreak_node *)nd)->post));
-}
-
-const char *dbreak_node::type()
-{
- return "dbreak_node";
-}
-
-int dbreak_node::force_tprint()
-{
- return 0;
-}
-
-int break_char_node::same(node *nd)
-{
- return break_code == ((break_char_node *)nd)->break_code
- && col == ((break_char_node *)nd)->col
- && same_node(ch, ((break_char_node *)nd)->ch);
-}
-
-const char *break_char_node::type()
-{
- return "break_char_node";
-}
-
-int break_char_node::force_tprint()
-{
- return 0;
-}
-
-int line_start_node::same(node * /*nd*/)
-{
- return 1;
-}
-
-const char *line_start_node::type()
-{
- return "line_start_node";
-}
-
-int line_start_node::force_tprint()
-{
- return 0;
-}
-
-int space_node::same(node *nd)
-{
- return n == ((space_node *)nd)->n
- && set == ((space_node *)nd)->set
- && col == ((space_node *)nd)->col;
-}
-
-const char *space_node::type()
-{
- return "space_node";
-}
-
-int word_space_node::same(node *nd)
-{
- return n == ((word_space_node *)nd)->n
- && set == ((word_space_node *)nd)->set
- && col == ((word_space_node *)nd)->col;
-}
-
-const char *word_space_node::type()
-{
- return "word_space_node";
-}
-
-int word_space_node::force_tprint()
-{
- return 0;
-}
-
-int unbreakable_space_node::same(node *nd)
-{
- return n == ((unbreakable_space_node *)nd)->n
- && set == ((unbreakable_space_node *)nd)->set
- && col == ((unbreakable_space_node *)nd)->col;
-}
-
-const char *unbreakable_space_node::type()
-{
- return "unbreakable_space_node";
-}
-
-node *unbreakable_space_node::add_self(node *n, hyphen_list **p)
-{
- next = n;
- hyphen_list *pp = *p;
- *p = (*p)->next;
- delete pp;
- return this;
-}
-
-hyphen_list *unbreakable_space_node::get_hyphen_list(hyphen_list *tail)
-{
- return new hyphen_list(0, tail);
-}
-
-int diverted_space_node::same(node *nd)
-{
- return n == ((diverted_space_node *)nd)->n;
-}
-
-const char *diverted_space_node::type()
-{
- return "diverted_space_node";
-}
-
-int diverted_space_node::force_tprint()
-{
- return 0;
-}
-
-int diverted_copy_file_node::same(node *nd)
-{
- return filename == ((diverted_copy_file_node *)nd)->filename;
-}
-
-const char *diverted_copy_file_node::type()
-{
- return "diverted_copy_file_node";
-}
-
-int diverted_copy_file_node::force_tprint()
-{
- return 0;
-}
-
-// Grow the font_table so that its size is > n.
-
-static void grow_font_table(int n)
-{
- assert(n >= font_table_size);
- font_info **old_font_table = font_table;
- int old_font_table_size = font_table_size;
- font_table_size = font_table_size ? (font_table_size*3)/2 : 10;
- if (font_table_size <= n)
- font_table_size = n + 10;
- font_table = new font_info *[font_table_size];
- if (old_font_table_size)
- memcpy(font_table, old_font_table,
- old_font_table_size*sizeof(font_info *));
- a_delete old_font_table;
- for (int i = old_font_table_size; i < font_table_size; i++)
- font_table[i] = 0;
-}
-
-dictionary font_translation_dictionary(17);
-
-static symbol get_font_translation(symbol nm)
-{
- void *p = font_translation_dictionary.lookup(nm);
- return p ? symbol((char *)p) : nm;
-}
-
-dictionary font_dictionary(50);
-
-static int mount_font_no_translate(int n, symbol name, symbol external_name)
-{
- assert(n >= 0);
- // We store the address of this char in font_dictionary to indicate
- // that we've previously tried to mount the font and failed.
- static char a_char;
- font *fm = 0;
- void *p = font_dictionary.lookup(external_name);
- if (p == 0) {
- int not_found;
- fm = font::load_font(external_name.contents(), ¬_found);
- if (!fm) {
- if (not_found)
- warning(WARN_FONT, "can't find font `%1'", external_name.contents());
- font_dictionary.lookup(external_name, &a_char);
- return 0;
- }
- font_dictionary.lookup(name, fm);
- }
- else if (p == &a_char) {
-#if 0
- error("invalid font `%1'", external_name.contents());
-#endif
- return 0;
- }
- else
- fm = (font*)p;
- if (n >= font_table_size) {
- if (n - font_table_size > 1000) {
- error("font position too much larger than first unused position");
- return 0;
- }
- grow_font_table(n);
- }
- else if (font_table[n] != 0)
- delete font_table[n];
- font_table[n] = new font_info(name, n, external_name, fm);
- font_family::invalidate_fontno(n);
- return 1;
-}
-
-int mount_font(int n, symbol name, symbol external_name)
-{
- assert(n >= 0);
- name = get_font_translation(name);
- if (external_name.is_null())
- external_name = name;
- else
- external_name = get_font_translation(external_name);
- return mount_font_no_translate(n, name, external_name);
-}
-
-void mount_style(int n, symbol name)
-{
- assert(n >= 0);
- if (n >= font_table_size) {
- if (n - font_table_size > 1000) {
- error("font position too much larger than first unused position");
- return;
- }
- grow_font_table(n);
- }
- else if (font_table[n] != 0)
- delete font_table[n];
- font_table[n] = new font_info(get_font_translation(name), n, NULL_SYMBOL, 0);
- font_family::invalidate_fontno(n);
-}
-
-/* global functions */
-
-void font_translate()
-{
- symbol from = get_name(1);
- if (!from.is_null()) {
- symbol to = get_name();
- if (to.is_null() || from == to)
- font_translation_dictionary.remove(from);
- else
- font_translation_dictionary.lookup(from, (void *)to.contents());
- }
- skip_line();
-}
-
-void font_position()
-{
- int n;
- if (get_integer(&n)) {
- if (n < 0)
- error("negative font position");
- else {
- symbol internal_name = get_name(1);
- if (!internal_name.is_null()) {
- symbol external_name = get_long_name(0);
- mount_font(n, internal_name, external_name); // ignore error
- }
- }
- }
- skip_line();
-}
-
-font_family::font_family(symbol s)
-: map_size(10), nm(s)
-{
- map = new int[map_size];
- for (int i = 0; i < map_size; i++)
- map[i] = -1;
-}
-
-font_family::~font_family()
-{
- a_delete map;
-}
-
-int font_family::make_definite(int i)
-{
- if (i >= 0) {
- if (i < map_size && map[i] >= 0)
- return map[i];
- else {
- if (i < font_table_size && font_table[i] != 0) {
- if (i >= map_size) {
- int old_map_size = map_size;
- int *old_map = map;
- map_size *= 3;
- map_size /= 2;
- if (i >= map_size)
- map_size = i + 10;
- map = new int[map_size];
- memcpy(map, old_map, old_map_size*sizeof(int));
- a_delete old_map;
- for (int j = old_map_size; j < map_size; j++)
- map[j] = -1;
- }
- if (font_table[i]->is_style()) {
- symbol sty = font_table[i]->get_name();
- symbol f = concat(nm, sty);
- int n;
- // don't use symbol_fontno, because that might return a style
- // and because we don't want to translate the name
- for (n = 0; n < font_table_size; n++)
- if (font_table[n] != 0 && font_table[n]->is_named(f)
- && !font_table[n]->is_style())
- break;
- if (n >= font_table_size) {
- n = next_available_font_position();
- if (!mount_font_no_translate(n, f, f))
- return -1;
- }
- return map[i] = n;
- }
- else
- return map[i] = i;
- }
- else
- return -1;
- }
- }
- else
- return -1;
-}
-
-dictionary family_dictionary(5);
-
-font_family *lookup_family(symbol nm)
-{
- font_family *f = (font_family *)family_dictionary.lookup(nm);
- if (!f) {
- f = new font_family(nm);
- (void)family_dictionary.lookup(nm, f);
- }
- return f;
-}
-
-void font_family::invalidate_fontno(int n)
-{
- assert(n >= 0 && n < font_table_size);
- dictionary_iterator iter(family_dictionary);
- symbol nm;
- font_family *fam;
- while (iter.get(&nm, (void **)&fam)) {
- int map_size = fam->map_size;
- if (n < map_size)
- fam->map[n] = -1;
- for (int i = 0; i < map_size; i++)
- if (fam->map[i] == n)
- fam->map[i] = -1;
- }
-}
-
-void style()
-{
- int n;
- if (get_integer(&n)) {
- if (n < 0)
- error("negative font position");
- else {
- symbol internal_name = get_name(1);
- if (!internal_name.is_null())
- mount_style(n, internal_name);
- }
- }
- skip_line();
-}
-
-static int get_fontno()
-{
- int n;
- tok.skip();
- if (tok.delimiter()) {
- symbol s = get_name(1);
- if (!s.is_null()) {
- n = symbol_fontno(s);
- if (n < 0) {
- n = next_available_font_position();
- if (!mount_font(n, s))
- return -1;
- }
- return curenv->get_family()->make_definite(n);
- }
- }
- else if (get_integer(&n)) {
- if (n < 0 || n >= font_table_size || font_table[n] == 0)
- error("bad font number");
- else
- return curenv->get_family()->make_definite(n);
- }
- return -1;
-}
-
-static int underline_fontno = 2;
-
-void underline_font()
-{
- int n = get_fontno();
- if (n >= 0)
- underline_fontno = n;
- skip_line();
-}
-
-int get_underline_fontno()
-{
- return underline_fontno;
-}
-
-static void read_special_fonts(special_font_list **sp)
-{
- special_font_list *s = *sp;
- *sp = 0;
- while (s != 0) {
- special_font_list *tem = s;
- s = s->next;
- delete tem;
- }
- special_font_list **p = sp;
- while (has_arg()) {
- int i = get_fontno();
- if (i >= 0) {
- special_font_list *tem = new special_font_list;
- tem->n = i;
- tem->next = 0;
- *p = tem;
- p = &(tem->next);
- }
- }
-}
-
-void font_special_request()
-{
- int n = get_fontno();
- if (n >= 0)
- read_special_fonts(&font_table[n]->sf);
- skip_line();
-}
-
-void special_request()
-{
- read_special_fonts(&global_special_fonts);
- skip_line();
-}
-
-int next_available_font_position()
-{
- int i;
- for (i = 1; i < font_table_size && font_table[i] != 0; i++)
- ;
- return i;
-}
-
-int symbol_fontno(symbol s)
-{
- s = get_font_translation(s);
- for (int i = 0; i < font_table_size; i++)
- if (font_table[i] != 0 && font_table[i]->is_named(s))
- return i;
- return -1;
-}
-
-int is_good_fontno(int n)
-{
- return n >= 0 && n < font_table_size && font_table[n] != 0;
-}
-
-int get_bold_fontno(int n)
-{
- if (n >= 0 && n < font_table_size && font_table[n] != 0) {
- hunits offset;
- if (font_table[n]->get_bold(&offset))
- return offset.to_units() + 1;
- else
- return 0;
- }
- else
- return 0;
-}
-
-hunits env_digit_width(environment *env)
-{
- node *n = make_glyph_node(charset_table['0'], env);
- if (n) {
- hunits x = n->width();
- delete n;
- return x;
- }
- else
- return H0;
-}
-
-hunits env_space_width(environment *env)
-{
- int fn = env_definite_font(env);
- font_size fs = env->get_font_size();
- if (fn < 0 || fn >= font_table_size || font_table[fn] == 0)
- return scale(fs.to_units()/3, env->get_space_size(), 12);
- else
- return font_table[fn]->get_space_width(fs, env->get_space_size());
-}
-
-hunits env_sentence_space_width(environment *env)
-{
- int fn = env_definite_font(env);
- font_size fs = env->get_font_size();
- if (fn < 0 || fn >= font_table_size || font_table[fn] == 0)
- return scale(fs.to_units()/3, env->get_sentence_space_size(), 12);
- else
- return font_table[fn]->get_space_width(fs, env->get_sentence_space_size());
-}
-
-hunits env_half_narrow_space_width(environment *env)
-{
- int fn = env_definite_font(env);
- font_size fs = env->get_font_size();
- if (fn < 0 || fn >= font_table_size || font_table[fn] == 0)
- return 0;
- else
- return font_table[fn]->get_half_narrow_space_width(fs);
-}
-
-hunits env_narrow_space_width(environment *env)
-{
- int fn = env_definite_font(env);
- font_size fs = env->get_font_size();
- if (fn < 0 || fn >= font_table_size || font_table[fn] == 0)
- return 0;
- else
- return font_table[fn]->get_narrow_space_width(fs);
-}
-
-void bold_font()
-{
- int n = get_fontno();
- if (n >= 0) {
- if (has_arg()) {
- if (tok.delimiter()) {
- int f = get_fontno();
- if (f >= 0) {
- units offset;
- if (has_arg() && get_number(&offset, 'u') && offset >= 1)
- font_table[f]->set_conditional_bold(n, hunits(offset - 1));
- else
- font_table[f]->conditional_unbold(n);
- }
- }
- else {
- units offset;
- if (get_number(&offset, 'u') && offset >= 1)
- font_table[n]->set_bold(hunits(offset - 1));
- else
- font_table[n]->unbold();
- }
- }
- else
- font_table[n]->unbold();
- }
- skip_line();
-}
-
-track_kerning_function::track_kerning_function() : non_zero(0)
-{
-}
-
-track_kerning_function::track_kerning_function(int min_s, hunits min_a,
- int max_s, hunits max_a)
-: non_zero(1), min_size(min_s), min_amount(min_a), max_size(max_s),
- max_amount(max_a)
-{
-}
-
-int track_kerning_function::operator==(const track_kerning_function &tk)
-{
- if (non_zero)
- return (tk.non_zero
- && min_size == tk.min_size
- && min_amount == tk.min_amount
- && max_size == tk.max_size
- && max_amount == tk.max_amount);
- else
- return !tk.non_zero;
-}
-
-int track_kerning_function::operator!=(const track_kerning_function &tk)
-{
- if (non_zero)
- return (!tk.non_zero
- || min_size != tk.min_size
- || min_amount != tk.min_amount
- || max_size != tk.max_size
- || max_amount != tk.max_amount);
- else
- return tk.non_zero;
-}
-
-hunits track_kerning_function::compute(int size)
-{
- if (non_zero) {
- if (max_size <= min_size)
- return min_amount;
- else if (size <= min_size)
- return min_amount;
- else if (size >= max_size)
- return max_amount;
- else
- return (scale(max_amount, size - min_size, max_size - min_size)
- + scale(min_amount, max_size - size, max_size - min_size));
- }
- else
- return H0;
-}
-
-void track_kern()
-{
- int n = get_fontno();
- if (n >= 0) {
- int min_s, max_s;
- hunits min_a, max_a;
- if (has_arg()
- && get_number(&min_s, 'z')
- && get_hunits(&min_a, 'p')
- && get_number(&max_s, 'z')
- && get_hunits(&max_a, 'p')) {
- track_kerning_function tk(min_s, min_a, max_s, max_a);
- font_table[n]->set_track_kern(tk);
- }
- else {
- track_kerning_function tk;
- font_table[n]->set_track_kern(tk);
- }
- }
- skip_line();
-}
-
-void constant_space()
-{
- int n = get_fontno();
- if (n >= 0) {
- int x, y;
- if (!has_arg() || !get_integer(&x))
- font_table[n]->set_constant_space(CONSTANT_SPACE_NONE);
- else {
- if (!has_arg() || !get_number(&y, 'z'))
- font_table[n]->set_constant_space(CONSTANT_SPACE_RELATIVE, x);
- else
- font_table[n]->set_constant_space(CONSTANT_SPACE_ABSOLUTE,
- scale(y*x,
- units_per_inch,
- 36*72*sizescale));
- }
- }
- skip_line();
-}
-
-void ligature()
-{
- int lig;
- if (has_arg() && get_integer(&lig) && lig >= 0 && lig <= 2)
- global_ligature_mode = lig;
- else
- global_ligature_mode = 1;
- skip_line();
-}
-
-void kern_request()
-{
- int k;
- if (has_arg() && get_integer(&k))
- global_kern_mode = k != 0;
- else
- global_kern_mode = 1;
- skip_line();
-}
-
-void set_soft_hyphen_char()
-{
- soft_hyphen_char = get_optional_char();
- if (!soft_hyphen_char)
- soft_hyphen_char = get_charinfo(HYPHEN_SYMBOL);
- skip_line();
-}
-
-void init_output()
-{
- if (suppress_output_flag)
- the_output = new suppress_output_file;
- else if (ascii_output_flag)
- the_output = new ascii_output_file;
- else
- the_output = new troff_output_file;
-}
-
-class next_available_font_position_reg : public reg {
-public:
- const char *get_string();
-};
-
-const char *next_available_font_position_reg::get_string()
-{
- return i_to_a(next_available_font_position());
-}
-
-class printing_reg : public reg {
-public:
- const char *get_string();
-};
-
-const char *printing_reg::get_string()
-{
- if (the_output)
- return the_output->is_printing() ? "1" : "0";
- else
- return "0";
-}
-
-void init_node_requests()
-{
- init_request("fp", font_position);
- init_request("sty", style);
- init_request("cs", constant_space);
- init_request("bd", bold_font);
- init_request("uf", underline_font);
- init_request("lg", ligature);
- init_request("kern", kern_request);
- init_request("tkf", track_kern);
- init_request("special", special_request);
- init_request("fspecial", font_special_request);
- init_request("ftr", font_translate);
- init_request("shc", set_soft_hyphen_char);
- number_reg_dictionary.define(".fp", new next_available_font_position_reg);
- number_reg_dictionary.define(".kern",
- new constant_int_reg(&global_kern_mode));
- number_reg_dictionary.define(".lg",
- new constant_int_reg(&global_ligature_mode));
- number_reg_dictionary.define(".P", new printing_reg);
- soft_hyphen_char = get_charinfo(HYPHEN_SYMBOL);
-}
diff --git a/contrib/groff/src/roff/troff/number.cc b/contrib/groff/src/roff/troff/number.cc
deleted file mode 100644
index 8fed342..0000000
--- a/contrib/groff/src/roff/troff/number.cc
+++ /dev/null
@@ -1,697 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-
-#include "troff.h"
-#include "symbol.h"
-#include "hvunits.h"
-#include "env.h"
-#include "token.h"
-#include "div.h"
-
-vunits V0;
-hunits H0;
-
-int hresolution = 1;
-int vresolution = 1;
-int units_per_inch;
-int sizescale;
-
-static int parse_expr(units *v, int scale_indicator,
- int parenthesised, int rigid = 0);
-static int start_number();
-
-int get_vunits(vunits *res, unsigned char si)
-{
- if (!start_number())
- return 0;
- units x;
- if (parse_expr(&x, si, 0)) {
- *res = vunits(x);
- return 1;
- }
- else
- return 0;
-}
-
-int get_hunits(hunits *res, unsigned char si)
-{
- if (!start_number())
- return 0;
- units x;
- if (parse_expr(&x, si, 0)) {
- *res = hunits(x);
- return 1;
- }
- else
- return 0;
-}
-
-// for \B
-
-int get_number_rigidly(units *res, unsigned char si)
-{
- if (!start_number())
- return 0;
- units x;
- if (parse_expr(&x, si, 0, 1)) {
- *res = x;
- return 1;
- }
- else
- return 0;
-}
-
-int get_number(units *res, unsigned char si)
-{
- if (!start_number())
- return 0;
- units x;
- if (parse_expr(&x, si, 0)) {
- *res = x;
- return 1;
- }
- else
- return 0;
-}
-
-int get_integer(int *res)
-{
- if (!start_number())
- return 0;
- units x;
- if (parse_expr(&x, 0, 0)) {
- *res = x;
- return 1;
- }
- else
- return 0;
-}
-
-enum incr_number_result { BAD, ABSOLUTE, INCREMENT, DECREMENT };
-
-static incr_number_result get_incr_number(units *res, unsigned char);
-
-int get_vunits(vunits *res, unsigned char si, vunits prev_value)
-{
- units v;
- switch (get_incr_number(&v, si)) {
- case BAD:
- return 0;
- case ABSOLUTE:
- *res = v;
- break;
- case INCREMENT:
- *res = prev_value + v;
- break;
- case DECREMENT:
- *res = prev_value - v;
- break;
- default:
- assert(0);
- }
- return 1;
-}
-
-int get_hunits(hunits *res, unsigned char si, hunits prev_value)
-{
- units v;
- switch (get_incr_number(&v, si)) {
- case BAD:
- return 0;
- case ABSOLUTE:
- *res = v;
- break;
- case INCREMENT:
- *res = prev_value + v;
- break;
- case DECREMENT:
- *res = prev_value - v;
- break;
- default:
- assert(0);
- }
- return 1;
-}
-
-int get_number(units *res, unsigned char si, units prev_value)
-{
- units v;
- switch (get_incr_number(&v, si)) {
- case BAD:
- return 0;
- case ABSOLUTE:
- *res = v;
- break;
- case INCREMENT:
- *res = prev_value + v;
- break;
- case DECREMENT:
- *res = prev_value - v;
- break;
- default:
- assert(0);
- }
- return 1;
-}
-
-int get_integer(int *res, int prev_value)
-{
- units v;
- switch (get_incr_number(&v, 0)) {
- case BAD:
- return 0;
- case ABSOLUTE:
- *res = v;
- break;
- case INCREMENT:
- *res = prev_value + int(v);
- break;
- case DECREMENT:
- *res = prev_value - int(v);
- break;
- default:
- assert(0);
- }
- return 1;
-}
-
-
-static incr_number_result get_incr_number(units *res, unsigned char si)
-{
- if (!start_number())
- return BAD;
- incr_number_result result = ABSOLUTE;
- if (tok.ch() == '+') {
- tok.next();
- result = INCREMENT;
- }
- else if (tok.ch() == '-') {
- tok.next();
- result = DECREMENT;
- }
- if (parse_expr(res, si, 0))
- return result;
- else
- return BAD;
-}
-
-static int start_number()
-{
- while (tok.space())
- tok.next();
- if (tok.newline()) {
- warning(WARN_MISSING, "missing number");
- return 0;
- }
- if (tok.tab()) {
- warning(WARN_TAB, "tab character where number expected");
- return 0;
- }
- if (tok.right_brace()) {
- warning(WARN_RIGHT_BRACE, "`\\}' where number expected");
- return 0;
- }
- return 1;
-}
-
-enum { OP_LEQ = 'L', OP_GEQ = 'G', OP_MAX = 'X', OP_MIN = 'N' };
-
-#define SCALE_INDICATOR_CHARS "icfPmnpuvMsz"
-
-static int parse_term(units *v, int scale_indicator,
- int parenthesised, int rigid);
-
-static int parse_expr(units *v, int scale_indicator,
- int parenthesised, int rigid)
-{
- int result = parse_term(v, scale_indicator, parenthesised, rigid);
- while (result) {
- if (parenthesised)
- tok.skip();
- int op = tok.ch();
- switch (op) {
- case '+':
- case '-':
- case '/':
- case '*':
- case '%':
- case ':':
- case '&':
- tok.next();
- break;
- case '>':
- tok.next();
- if (tok.ch() == '=') {
- tok.next();
- op = OP_GEQ;
- }
- else if (tok.ch() == '?') {
- tok.next();
- op = OP_MAX;
- }
- break;
- case '<':
- tok.next();
- if (tok.ch() == '=') {
- tok.next();
- op = OP_LEQ;
- }
- else if (tok.ch() == '?') {
- tok.next();
- op = OP_MIN;
- }
- break;
- case '=':
- tok.next();
- if (tok.ch() == '=')
- tok.next();
- break;
- default:
- return result;
- }
- units v2;
- if (!parse_term(&v2, scale_indicator, parenthesised, rigid))
- return 0;
- int overflow = 0;
- switch (op) {
- case '<':
- *v = *v < v2;
- break;
- case '>':
- *v = *v > v2;
- break;
- case OP_LEQ:
- *v = *v <= v2;
- break;
- case OP_GEQ:
- *v = *v >= v2;
- break;
- case OP_MIN:
- if (*v > v2)
- *v = v2;
- break;
- case OP_MAX:
- if (*v < v2)
- *v = v2;
- break;
- case '=':
- *v = *v == v2;
- break;
- case '&':
- *v = *v > 0 && v2 > 0;
- break;
- case ':':
- *v = *v > 0 || v2 > 0;
- break;
- case '+':
- if (v2 < 0) {
- if (*v < INT_MIN - v2)
- overflow = 1;
- }
- else if (v2 > 0) {
- if (*v > INT_MAX - v2)
- overflow = 1;
- }
- if (overflow) {
- error("addition overflow");
- return 0;
- }
- *v += v2;
- break;
- case '-':
- if (v2 < 0) {
- if (*v > INT_MAX + v2)
- overflow = 1;
- }
- else if (v2 > 0) {
- if (*v < INT_MIN + v2)
- overflow = 1;
- }
- if (overflow) {
- error("subtraction overflow");
- return 0;
- }
- *v -= v2;
- break;
- case '*':
- if (v2 < 0) {
- if (*v > 0) {
- if (*v > -(unsigned)INT_MIN / -(unsigned)v2)
- overflow = 1;
- }
- else if (-(unsigned)*v > INT_MAX / -(unsigned)v2)
- overflow = 1;
- }
- else if (v2 > 0) {
- if (*v > 0) {
- if (*v > INT_MAX / v2)
- overflow = 1;
- }
- else if (-(unsigned)*v > -(unsigned)INT_MIN / v2)
- overflow = 1;
- }
- if (overflow) {
- error("multiplication overflow");
- return 0;
- }
- *v *= v2;
- break;
- case '/':
- if (v2 == 0) {
- error("division by zero");
- return 0;
- }
- *v /= v2;
- break;
- case '%':
- if (v2 == 0) {
- error("modulus by zero");
- return 0;
- }
- *v %= v2;
- break;
- default:
- assert(0);
- }
- }
- return result;
-}
-
-static int parse_term(units *v, int scale_indicator,
- int parenthesised, int rigid)
-{
- int negative = 0;
- for (;;)
- if (parenthesised && tok.space())
- tok.next();
- else if (tok.ch() == '+')
- tok.next();
- else if (tok.ch() == '-') {
- tok.next();
- negative = !negative;
- }
- else
- break;
- unsigned char c = tok.ch();
- switch (c) {
- case '|':
- // | is not restricted to the outermost level
- // tbl uses this
- tok.next();
- if (!parse_term(v, scale_indicator, parenthesised, rigid))
- return 0;
- int tem;
- tem = (scale_indicator == 'v'
- ? curdiv->get_vertical_position().to_units()
- : curenv->get_input_line_position().to_units());
- if (tem >= 0) {
- if (*v < INT_MIN + tem) {
- error("numeric overflow");
- return 0;
- }
- }
- else {
- if (*v > INT_MAX + tem) {
- error("numeric overflow");
- return 0;
- }
- }
- *v -= tem;
- if (negative) {
- if (*v == INT_MIN) {
- error("numeric overflow");
- return 0;
- }
- *v = -*v;
- }
- return 1;
- case '(':
- tok.next();
- c = tok.ch();
- if (c == ')') {
- if (rigid)
- return 0;
- warning(WARN_SYNTAX, "empty parentheses");
- tok.next();
- *v = 0;
- return 1;
- }
- else if (c != 0 && strchr(SCALE_INDICATOR_CHARS, c) != 0) {
- tok.next();
- if (tok.ch() == ';') {
- tok.next();
- scale_indicator = c;
- }
- else {
- error("expected `;' after scale-indicator (got %1)",
- tok.description());
- return 0;
- }
- }
- else if (c == ';') {
- scale_indicator = 0;
- tok.next();
- }
- if (!parse_expr(v, scale_indicator, 1, rigid))
- return 0;
- tok.skip();
- if (tok.ch() != ')') {
- if (rigid)
- return 0;
- warning(WARN_SYNTAX, "missing `)' (got %1)", tok.description());
- }
- else
- tok.next();
- if (negative) {
- if (*v == INT_MIN) {
- error("numeric overflow");
- return 0;
- }
- *v = -*v;
- }
- return 1;
- case '.':
- *v = 0;
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- *v = 0;
- do {
- if (*v > INT_MAX/10) {
- error("numeric overflow");
- return 0;
- }
- *v *= 10;
- if (*v > INT_MAX - (int(c) - '0')) {
- error("numeric overflow");
- return 0;
- }
- *v += c - '0';
- tok.next();
- c = tok.ch();
- } while (csdigit(c));
- break;
- case '/':
- case '*':
- case '%':
- case ':':
- case '&':
- case '>':
- case '<':
- case '=':
- warning(WARN_SYNTAX, "empty left operand");
- *v = 0;
- return rigid ? 0 : 1;
- default:
- warning(WARN_NUMBER, "numeric expression expected (got %1)",
- tok.description());
- return 0;
- }
- int divisor = 1;
- if (tok.ch() == '.') {
- tok.next();
- for (;;) {
- c = tok.ch();
- if (!csdigit(c))
- break;
- // we may multiply the divisor by 254 later on
- if (divisor <= INT_MAX/2540 && *v <= (INT_MAX - 9)/10) {
- *v *= 10;
- *v += c - '0';
- divisor *= 10;
- }
- tok.next();
- }
- }
- int si = scale_indicator;
- int do_next = 0;
- if ((c = tok.ch()) != 0 && strchr(SCALE_INDICATOR_CHARS, c) != 0) {
- switch (scale_indicator) {
- case 'z':
- if (c != 'u' && c != 'z') {
- warning(WARN_SCALE,
- "only `z' and `u' scale indicators valid in this context");
- break;
- }
- si = c;
- break;
- case 0:
- warning(WARN_SCALE, "scale indicator invalid in this context");
- break;
- case 'u':
- si = c;
- break;
- default:
- if (c == 'z') {
- warning(WARN_SCALE, "`z' scale indicator invalid in this context");
- break;
- }
- si = c;
- break;
- }
- // Don't do tok.next() here because the next token might be \s, which
- // would affect the interpretation of m.
- do_next = 1;
- }
- switch (si) {
- case 'i':
- *v = scale(*v, units_per_inch, divisor);
- break;
- case 'c':
- *v = scale(*v, units_per_inch*100, divisor*254);
- break;
- case 0:
- case 'u':
- if (divisor != 1)
- *v /= divisor;
- break;
- case 'f':
- *v = scale(*v, 65536, divisor);
- break;
- case 'p':
- *v = scale(*v, units_per_inch, divisor*72);
- break;
- case 'P':
- *v = scale(*v, units_per_inch, divisor*6);
- break;
- case 'm':
- {
- // Convert to hunits so that with -Tascii `m' behaves as in nroff.
- hunits em = curenv->get_size();
- *v = scale(*v, em.is_zero() ? hresolution : em.to_units(), divisor);
- }
- break;
- case 'M':
- {
- hunits em = curenv->get_size();
- *v = scale(*v, em.is_zero() ? hresolution : em.to_units(), divisor*100);
- }
- break;
- case 'n':
- {
- // Convert to hunits so that with -Tascii `n' behaves as in nroff.
- hunits en = curenv->get_size()/2;
- *v = scale(*v, en.is_zero() ? hresolution : en.to_units(), divisor);
- }
- break;
- case 'v':
- *v = scale(*v, curenv->get_vertical_spacing().to_units(), divisor);
- break;
- case 's':
- while (divisor > INT_MAX/(sizescale*72)) {
- divisor /= 10;
- *v /= 10;
- }
- *v = scale(*v, units_per_inch, divisor*sizescale*72);
- break;
- case 'z':
- *v = scale(*v, sizescale, divisor);
- break;
- default:
- assert(0);
- }
- if (do_next)
- tok.next();
- if (negative) {
- if (*v == INT_MIN) {
- error("numeric overflow");
- return 0;
- }
- *v = -*v;
- }
- return 1;
-}
-
-units scale(units n, units x, units y)
-{
- assert(x >= 0 && y > 0);
- if (x == 0)
- return 0;
- if (n >= 0) {
- if (n <= INT_MAX/x)
- return (n*x)/y;
- }
- else {
- if (-(unsigned)n <= -(unsigned)INT_MIN/x)
- return (n*x)/y;
- }
- double res = n*double(x)/double(y);
- if (res > INT_MAX) {
- error("numeric overflow");
- return INT_MAX;
- }
- else if (res < INT_MIN) {
- error("numeric overflow");
- return INT_MIN;
- }
- return int(res);
-}
-
-vunits::vunits(units x)
-{
- // don't depend on the rounding direction for division of negative integers
- if (vresolution == 1)
- n = x;
- else
- n = (x < 0
- ? -((-x + vresolution/2 - 1)/vresolution)
- : (x + vresolution/2 - 1)/vresolution);
-}
-
-hunits::hunits(units x)
-{
- // don't depend on the rounding direction for division of negative integers
- if (hresolution == 1)
- n = x;
- else
- n = (x < 0
- ? -((-x + hresolution/2 - 1)/hresolution)
- : (x + hresolution/2 - 1)/hresolution);
-}
diff --git a/contrib/groff/src/roff/troff/reg.cc b/contrib/groff/src/roff/troff/reg.cc
deleted file mode 100644
index 8ac20c9..0000000
--- a/contrib/groff/src/roff/troff/reg.cc
+++ /dev/null
@@ -1,474 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "troff.h"
-#include "symbol.h"
-#include "dictionary.h"
-#include "token.h"
-#include "request.h"
-#include "reg.h"
-
-object_dictionary number_reg_dictionary(101);
-
-int reg::get_value(units * /*d*/)
-{
- return 0;
-}
-
-void reg::increment()
-{
- error("can't increment read-only register");
-}
-
-void reg::decrement()
-{
- error("can't decrement read-only register");
-}
-
-void reg::set_increment(units /*n*/)
-{
- error("can't auto increment read-only register");
-}
-
-void reg::alter_format(char /*f*/, int /*w*/)
-{
- error("can't alter format of read-only register");
-}
-
-const char *reg::get_format()
-{
- return "0";
-}
-
-void reg::set_value(units /*n*/)
-{
- error("can't write read-only register");
-}
-
-general_reg::general_reg() : format('1'), width(0), inc(0)
-{
-}
-
-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',
-};
-
-static const char *number_value_to_ascii(int value, char format, int width)
-{
- static char buf[128]; // must be at least 21
- switch(format) {
- case '1':
- if (width <= 0)
- return i_to_a(value);
- else if (width > int(sizeof(buf) - 2))
- sprintf(buf, "%.*d", int(sizeof(buf) - 2), int(value));
- else
- sprintf(buf, "%.*d", width, int(value));
- break;
- 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 = format == 'i' ? "zwmdclxvi" : "ZWMDCLXVI";
- int n = int(value);
- if (n >= 40000 || n <= -40000) {
- error("magnitude of `%1' too big for i or I format", n);
- return i_to_a(n);
- }
- if (n == 0) {
- *p++ = '0';
- *p = 0;
- break;
- }
- if (n < 0) {
- *p++ = '-';
- n = -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':
- {
- int n = value;
- char *p = buf;
- if (n == 0) {
- *p++ = '0';
- *p = 0;
- }
- else {
- if (n < 0) {
- n = -n;
- *p++ = '-';
- }
- // this is a bit tricky
- while (n > 0) {
- int d = n % 26;
- if (d == 0)
- d = 26;
- n -= d;
- n /= 26;
- *p++ = format == 'a' ? lowercase_array[d - 1] :
- uppercase_array[d - 1];
- }
- *p-- = 0;
- char *q = buf[0] == '-' ? buf + 1 : buf;
- while (q < p) {
- char temp = *q;
- *q = *p;
- *p = temp;
- --p;
- ++q;
- }
- }
- break;
- }
- default:
- assert(0);
- break;
- }
- return buf;
-}
-
-const char *general_reg::get_string()
-{
- units n;
- if (!get_value(&n))
- return "";
- return number_value_to_ascii(n, format, width);
-}
-
-
-void general_reg::increment()
-{
- int n;
- if (get_value(&n))
- set_value(n + inc);
-}
-
-void general_reg::decrement()
-{
- int n;
- if (get_value(&n))
- set_value(n - inc);
-}
-
-void general_reg::set_increment(units n)
-{
- inc = n;
-}
-
-void general_reg::alter_format(char f, int w)
-{
- format = f;
- width = w;
-}
-
-static const char *number_format_to_ascii(char format, int width)
-{
- static char buf[24];
- if (format == '1') {
- if (width > 0) {
- int n = width;
- if (n > int(sizeof(buf)) - 1)
- n = int(sizeof(buf)) - 1;
- sprintf(buf, "%.*d", n, 0);
- return buf;
- }
- else
- return "0";
- }
- else {
- buf[0] = format;
- buf[1] = '\0';
- return buf;
- }
-}
-
-const char *general_reg::get_format()
-{
- return number_format_to_ascii(format, width);
-}
-
-class number_reg : public general_reg {
- units value;
-public:
- number_reg();
- int get_value(units *);
- void set_value(units);
-};
-
-number_reg::number_reg() : value(0)
-{
-}
-
-int number_reg::get_value(units *res)
-{
- *res = value;
- return 1;
-}
-
-void number_reg::set_value(units n)
-{
- value = n;
-}
-
-variable_reg::variable_reg(units *p) : ptr(p)
-{
-}
-
-void variable_reg::set_value(units n)
-{
- *ptr = n;
-}
-
-int variable_reg::get_value(units *res)
-{
- *res = *ptr;
- return 1;
-}
-
-void define_number_reg()
-{
- symbol nm = get_name(1);
- if (nm.is_null()) {
- skip_line();
- return;
- }
- reg *r = (reg *)number_reg_dictionary.lookup(nm);
- units v;
- units prev_value;
- if (!r || !r->get_value(&prev_value))
- prev_value = 0;
- if (get_number(&v, 'u', prev_value)) {
- if (r == 0) {
- r = new number_reg;
- number_reg_dictionary.define(nm, r);
- }
- r->set_value(v);
- if (tok.space() && has_arg() && get_number(&v, 'u'))
- r->set_increment(v);
- }
- skip_line();
-}
-
-#if 0
-void inline_define_reg()
-{
- token start;
- start.next();
- if (!start.delimiter(1))
- return;
- tok.next();
- symbol nm = get_name(1);
- if (nm.is_null())
- return;
- reg *r = (reg *)number_reg_dictionary.lookup(nm);
- if (r == 0) {
- r = new number_reg;
- number_reg_dictionary.define(nm, r);
- }
- units v;
- units prev_value;
- if (!r->get_value(&prev_value))
- prev_value = 0;
- if (get_number(&v, 'u', prev_value)) {
- r->set_value(v);
- if (start != tok) {
- if (get_number(&v, 'u')) {
- r->set_increment(v);
- if (start != tok)
- warning(WARN_DELIM, "closing delimiter does not match");
- }
- }
- }
-}
-#endif
-
-void set_number_reg(symbol nm, units n)
-{
- reg *r = (reg *)number_reg_dictionary.lookup(nm);
- if (r == 0) {
- r = new number_reg;
- number_reg_dictionary.define(nm, r);
- }
- r->set_value(n);
-}
-
-reg *lookup_number_reg(symbol nm)
-{
- reg *r = (reg *)number_reg_dictionary.lookup(nm);
- if (r == 0) {
- warning(WARN_REG, "number register `%1' not defined", nm.contents());
- r = new number_reg;
- number_reg_dictionary.define(nm, r);
- }
- return r;
-}
-
-void alter_format()
-{
- symbol nm = get_name(1);
- if (nm.is_null()) {
- skip_line();
- return;
- }
- reg *r = (reg *)number_reg_dictionary.lookup(nm);
- if (r == 0) {
- r = new number_reg;
- number_reg_dictionary.define(nm, r);
- }
- tok.skip();
- char c = tok.ch();
- if (csdigit(c)) {
- int n = 0;
- do {
- ++n;
- tok.next();
- } while (csdigit(tok.ch()));
- r->alter_format('1', n);
- }
- else if (c == 'i' || c == 'I' || c == 'a' || c == 'A')
- r->alter_format(c);
- else if (tok.newline() || tok.eof())
- warning(WARN_MISSING, "missing number register format");
- else
- error("bad number register format (got %1)", tok.description());
- skip_line();
-}
-
-void remove_reg()
-{
- for (;;) {
- symbol s = get_name();
- if (s.is_null())
- break;
- number_reg_dictionary.remove(s);
- }
- skip_line();
-}
-
-void alias_reg()
-{
- symbol s1 = get_name(1);
- if (!s1.is_null()) {
- symbol s2 = get_name(1);
- if (!s2.is_null()) {
- if (!number_reg_dictionary.alias(s1, s2))
- warning(WARN_REG, "number register `%1' not defined", s2.contents());
- }
- }
- skip_line();
-}
-
-void rename_reg()
-{
- symbol s1 = get_name(1);
- if (!s1.is_null()) {
- symbol s2 = get_name(1);
- if (!s2.is_null())
- number_reg_dictionary.rename(s1, s2);
- }
- skip_line();
-}
-
-void print_number_regs()
-{
- object_dictionary_iterator iter(number_reg_dictionary);
- reg *r;
- symbol s;
- while (iter.get(&s, (object **)&r)) {
- assert(!s.is_null());
- errprint("%1\t", s.contents());
- const char *p = r->get_string();
- if (p)
- errprint(p);
- errprint("\n");
- }
- fflush(stderr);
- skip_line();
-}
-
-void init_reg_requests()
-{
- init_request("rr", remove_reg);
- init_request("nr", define_number_reg);
- init_request("af", alter_format);
- init_request("aln", alias_reg);
- init_request("rnn", rename_reg);
- init_request("pnr", print_number_regs);
-}
diff --git a/contrib/groff/src/roff/troff/symbol.cc b/contrib/groff/src/roff/troff/symbol.cc
deleted file mode 100644
index 09f4c98..0000000
--- a/contrib/groff/src/roff/troff/symbol.cc
+++ /dev/null
@@ -1,154 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-
-#include "troff.h"
-#include "symbol.h"
-
-const char **symbol::table = 0;
-int symbol::table_used = 0;
-int symbol::table_size = 0;
-char *symbol::block = 0;
-int symbol::block_size = 0;
-
-const symbol NULL_SYMBOL;
-const symbol EMPTY_SYMBOL("");
-
-#ifdef BLOCK_SIZE
-#undef BLOCK_SIZE
-#endif
-
-const int BLOCK_SIZE = 1024;
-// the table will increase in size as necessary
-// the size will be chosen from the following array
-// add some more if you want
-static const unsigned int table_sizes[] = {
- 101, 503, 1009, 2003, 3001, 4001, 5003, 10007, 20011, 40009, 80021,
- 160001, 500009, 1000003, 1500007, 2000003, 0
-};
-const double FULL_MAX = 0.3; // don't let the table get more than this full
-
-static unsigned int hash_string(const char *p)
-{
- // compute a hash code; this assumes 32-bit unsigned ints
- // see p436 of Compilers by Aho, Sethi & Ullman
- // give special treatment to two-character names
- unsigned int hc = 0, g;
- if (*p != 0) {
- hc = *p++;
- if (*p != 0) {
- hc <<= 7;
- hc += *p++;
- for (; *p != 0; p++) {
- hc <<= 4;
- hc += *p;
- if ((g = (hc & 0xf0000000)) == 0) {
- hc ^= g >> 24;
- hc ^= g;
- }
- }
- }
- }
- return hc;
-}
-
-// Tell compiler that a variable is intentionally unused.
-inline void unused(void *) { }
-
-symbol::symbol(const char *p, int how)
-{
- if (p == 0) {
- s = 0;
- return;
- }
- if (*p == 0) {
- s = "";
- return;
- }
- if (table == 0) {
- table_size = table_sizes[0];
- table = (const char **)new char*[table_size];
- for (int i = 0; i < table_size; i++)
- table[i] = 0;
- table_used = 0;
- }
- unsigned int hc = hash_string(p);
- const char **pp;
- for (pp = table + hc % table_size;
- *pp != 0;
- (pp == table ? pp = table + table_size - 1 : --pp))
- if (strcmp(p, *pp) == 0) {
- s = *pp;
- return;
- }
- if (how == MUST_ALREADY_EXIST) {
- s = 0;
- return;
- }
- if (table_used >= table_size - 1 || table_used >= table_size*FULL_MAX) {
- const char **old_table = table;
- unsigned int old_table_size = table_size;
- int i;
- for (i = 1; table_sizes[i] <= old_table_size; i++)
- if (table_sizes[i] == 0)
- fatal("too many symbols");
- table_size = table_sizes[i];
- table_used = 0;
- table = (const char **)new char*[table_size];
- for (i = 0; i < table_size; i++)
- table[i] = 0;
- for (pp = old_table + old_table_size - 1;
- pp >= old_table;
- --pp) {
- symbol temp(*pp, 1); /* insert it into the new table */
- unused(&temp);
- }
- a_delete old_table;
- for (pp = table + hc % table_size;
- *pp != 0;
- (pp == table ? pp = table + table_size - 1 : --pp))
- ;
- }
- ++table_used;
- if (how == DONT_STORE) {
- s = *pp = p;
- }
- else {
- int len = strlen(p)+1;
- if (block == 0 || block_size < len) {
- block_size = len > BLOCK_SIZE ? len : BLOCK_SIZE;
- block = new char [block_size];
- }
- (void)strcpy(block, p);
- s = *pp = block;
- block += len;
- block_size -= len;
- }
-}
-
-symbol concat(symbol s1, symbol s2)
-{
- char *buf = new char [strlen(s1.contents()) + strlen(s2.contents()) + 1];
- strcpy(buf, s1.contents());
- strcat(buf, s2.contents());
- symbol res(buf);
- a_delete buf;
- return res;
-}
diff --git a/contrib/groff/src/utils/addftinfo/addftinfo.cc b/contrib/groff/src/utils/addftinfo/addftinfo.cc
deleted file mode 100644
index 931d836..0000000
--- a/contrib/groff/src/utils/addftinfo/addftinfo.cc
+++ /dev/null
@@ -1,218 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1989-1992, 2000, 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "lib.h"
-
-#include
-#include
-#include
-#include
-#include "errarg.h"
-#include "error.h"
-#include "stringclass.h"
-#include "cset.h"
-#include "guess.h"
-
-extern "C" const char *Version_string;
-
-static void usage(FILE *stream);
-static void usage();
-static void version();
-static void convert_font(const font_params &, FILE *, FILE *);
-
-typedef int font_params::*param_t;
-
-static struct {
- const char *name;
- param_t par;
-} param_table[] = {
- { "x-height", &font_params::x_height },
- { "fig-height", &font_params::fig_height },
- { "asc-height", &font_params::asc_height },
- { "body-height", &font_params::body_height },
- { "cap-height", &font_params::cap_height },
- { "comma-depth", &font_params::comma_depth },
- { "desc-depth", &font_params::desc_depth },
- { "body-depth", &font_params::body_depth },
-};
-
-// These are all in thousandths of an em.
-// These values are correct for PostScript Times Roman.
-
-#define DEFAULT_X_HEIGHT 448
-#define DEFAULT_FIG_HEIGHT 676
-#define DEFAULT_ASC_HEIGHT 682
-#define DEFAULT_BODY_HEIGHT 676
-#define DEFAULT_CAP_HEIGHT 662
-#define DEFAULT_COMMA_DEPTH 143
-#define DEFAULT_DESC_DEPTH 217
-#define DEFAULT_BODY_DEPTH 177
-
-int main(int argc, char **argv)
-{
- program_name = argv[0];
- int i;
- for (i = 1; i < argc; i++) {
- if (!strcmp(argv[i], "-v") || !strcmp(argv[i],"--version"))
- version();
- if (!strcmp(argv[i],"--help")) {
- usage(stdout);
- exit(0);
- }
- }
- if (argc < 4)
- usage();
- int resolution;
- if (sscanf(argv[argc-3], "%d", &resolution) != 1)
- usage();
- if (resolution <= 0)
- fatal("resolution must be > 0");
- int unitwidth;
- if (sscanf(argv[argc-2], "%d", &unitwidth) != 1)
- usage();
- if (unitwidth <= 0)
- fatal("unitwidth must be > 0");
- font_params param;
- const char *font = argv[argc-1];
- param.italic = (font[0] != '\0' && strchr(font, '\0')[-1] == 'I');
- param.em = (resolution*unitwidth)/72;
- param.x_height = DEFAULT_X_HEIGHT;
- param.fig_height = DEFAULT_FIG_HEIGHT;
- param.asc_height = DEFAULT_ASC_HEIGHT;
- param.body_height = DEFAULT_BODY_HEIGHT;
- param.cap_height = DEFAULT_CAP_HEIGHT;
- param.comma_depth = DEFAULT_COMMA_DEPTH;
- param.desc_depth = DEFAULT_DESC_DEPTH;
- param.body_depth = DEFAULT_BODY_DEPTH;
- for (i = 1; i < argc && argv[i][0] == '-'; i++) {
- if (argv[i][1] == '-' && argv[i][2] == '\0') {
- i++;
- break;
- }
- if (i + 1 >= argc)
- usage();
- size_t j;
- for (j = 0;; j++) {
- if (j >= sizeof(param_table)/sizeof(param_table[0]))
- fatal("parameter `%1' not recognized", argv[i] + 1);
- if (strcmp(param_table[j].name, argv[i] + 1) == 0)
- break;
- }
- if (sscanf(argv[i+1], "%d", &(param.*(param_table[j].par))) != 1)
- fatal("invalid argument `%1'", argv[i+1]);
- i++;
- }
- if (argc - i != 3)
- usage();
- errno = 0;
- FILE *infp = fopen(font, "r");
- if (infp == 0)
- fatal("can't open `%1': %2", font, strerror(errno));
- convert_font(param, infp, stdout);
- return 0;
-}
-
-static void usage(FILE *stream)
-{
- fprintf(stream, "usage: %s [-v] [-param value] ... "
- "resolution unitwidth font\n",
- program_name);
-}
-static void usage()
-{
- usage(stderr);
- exit(1);
-}
-
-static void version()
-{
- printf("GNU addftinfo (groff) version %s\n", Version_string);
- exit(0);
-}
-
-static int get_line(FILE *fp, string *p)
-{
- int c;
- p->clear();
- while ((c = getc(fp)) != EOF) {
- *p += char(c);
- if (c == '\n')
- break;
- }
- return p->length() > 0;
-}
-
-static void convert_font(const font_params ¶m, FILE *infp, FILE *outfp)
-{
- string s;
- while (get_line(infp, &s)) {
- put_string(s, outfp);
- if (s.length() >= 8
- && strncmp(&s[0], "charset", 7))
- break;
- }
- while (get_line(infp, &s)) {
- s += '\0';
- string name;
- const char *p = s.contents();
- while (csspace(*p))
- p++;
- while (*p != '\0' && !csspace(*p))
- name += *p++;
- while (csspace(*p))
- p++;
- for (const char *q = s.contents(); q < p; q++)
- putc(*q, outfp);
- char *next;
- char_metric metric;
- metric.width = (int)strtol(p, &next, 10);
- if (next != p) {
- printf("%d", metric.width);
- p = next;
- metric.type = (int)strtol(p, &next, 10);
- if (next != p) {
- name += '\0';
- guess(name.contents(), param, &metric);
- if (metric.sk == 0) {
- if (metric.left_ic == 0) {
- if (metric.ic == 0) {
- if (metric.depth == 0) {
- if (metric.height != 0)
- printf(",%d", metric.height);
- }
- else
- printf(",%d,%d", metric.height, metric.depth);
- }
- else
- printf(",%d,%d,%d", metric.height, metric.depth, metric.ic);
- }
- else
- printf(",%d,%d,%d,%d", metric.height, metric.depth, metric.ic,
- metric.left_ic);
- }
- else
- printf(",%d,%d,%d,%d,%d", metric.height, metric.depth, metric.ic,
- metric.left_ic, metric.sk);
- }
- }
- fputs(p, outfp);
- }
-}
-
diff --git a/contrib/groff/src/utils/addftinfo/guess.cc b/contrib/groff/src/utils/addftinfo/guess.cc
deleted file mode 100644
index dcfd4c9..0000000
--- a/contrib/groff/src/utils/addftinfo/guess.cc
+++ /dev/null
@@ -1,490 +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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "guess.h"
-
-void guess(const char *s, const font_params ¶m, char_metric *metric)
-{
- int &height = metric->height;
- int &depth = metric->depth;
-
- metric->ic = 0;
- metric->left_ic = 0;
- metric->sk = 0;
- height = 0;
- depth = 0;
- if (s[0] == '\0' || (s[1] != '\0' && s[2] != '\0'))
- goto do_default;
-#define HASH(c1, c2) (((unsigned char)(c1) << 8) | (unsigned char)(c2))
- switch (HASH(s[0], s[1])) {
- default:
- do_default:
- if (metric->type & 01)
- depth = param.desc_depth;
- if (metric->type & 02)
- height = param.asc_height;
- else
- height = param.x_height;
- break;
- case HASH('\\', '|'):
- case HASH('\\', '^'):
- case HASH('\\', '&'):
- // these have zero height and depth
- break;
- case HASH('f', 0):
- height = param.asc_height;
- if (param.italic)
- depth = param.desc_depth;
- break;
- case HASH('a', 0):
- case HASH('c', 0):
- case HASH('e', 0):
- case HASH('m', 0):
- case HASH('n', 0):
- case HASH('o', 0):
- case HASH('r', 0):
- case HASH('s', 0):
- case HASH('u', 0):
- case HASH('v', 0):
- case HASH('w', 0):
- case HASH('x', 0):
- case HASH('z', 0):
- height = param.x_height;
- break;
- case HASH('i', 0):
- height = param.x_height;
- break;
- case HASH('b', 0):
- case HASH('d', 0):
- case HASH('h', 0):
- case HASH('k', 0):
- case HASH('l', 0):
- case HASH('F', 'i'):
- case HASH('F', 'l'):
- case HASH('f', 'f'):
- case HASH('f', 'i'):
- case HASH('f', 'l'):
- height = param.asc_height;
- break;
- case HASH('t', 0):
- height = param.asc_height;
- break;
- case HASH('g', 0):
- case HASH('p', 0):
- case HASH('q', 0):
- case HASH('y', 0):
- height = param.x_height;
- depth = param.desc_depth;
- break;
- case HASH('j', 0):
- height = param.x_height;
- depth = param.desc_depth;
- break;
- case HASH('A', 0):
- case HASH('B', 0):
- case HASH('C', 0):
- case HASH('D', 0):
- case HASH('E', 0):
- case HASH('F', 0):
- case HASH('G', 0):
- case HASH('H', 0):
- case HASH('I', 0):
- case HASH('J', 0):
- case HASH('K', 0):
- case HASH('L', 0):
- case HASH('M', 0):
- case HASH('N', 0):
- case HASH('O', 0):
- case HASH('P', 0):
- case HASH('Q', 0):
- case HASH('R', 0):
- case HASH('S', 0):
- case HASH('T', 0):
- case HASH('U', 0):
- case HASH('V', 0):
- case HASH('W', 0):
- case HASH('X', 0):
- case HASH('Y', 0):
- case HASH('Z', 0):
- height = param.cap_height;
- break;
- case HASH('*', 'A'):
- case HASH('*', 'B'):
- case HASH('*', 'C'):
- case HASH('*', 'D'):
- case HASH('*', 'E'):
- case HASH('*', 'F'):
- case HASH('*', 'G'):
- case HASH('*', 'H'):
- case HASH('*', 'I'):
- case HASH('*', 'K'):
- case HASH('*', 'L'):
- case HASH('*', 'M'):
- case HASH('*', 'N'):
- case HASH('*', 'O'):
- case HASH('*', 'P'):
- case HASH('*', 'Q'):
- case HASH('*', 'R'):
- case HASH('*', 'S'):
- case HASH('*', 'T'):
- case HASH('*', 'U'):
- case HASH('*', 'W'):
- case HASH('*', 'X'):
- case HASH('*', 'Y'):
- case HASH('*', 'Z'):
- height = param.cap_height;
- break;
- case HASH('0', 0):
- case HASH('1', 0):
- case HASH('2', 0):
- case HASH('3', 0):
- case HASH('4', 0):
- case HASH('5', 0):
- case HASH('6', 0):
- case HASH('7', 0):
- case HASH('8', 0):
- case HASH('9', 0):
- case HASH('1', '2'):
- case HASH('1', '4'):
- case HASH('3', '4'):
- height = param.fig_height;
- break;
- case HASH('(', 0):
- case HASH(')', 0):
- case HASH('[', 0):
- case HASH(']', 0):
- case HASH('{', 0):
- case HASH('}', 0):
- height = param.body_height;
- depth = param.body_depth;
- break;
- case HASH('i', 's'):
- height = (param.em*3)/4;
- depth = param.em/4;
- break;
- case HASH('*', 'a'):
- case HASH('*', 'e'):
- case HASH('*', 'i'):
- case HASH('*', 'k'):
- case HASH('*', 'n'):
- case HASH('*', 'o'):
- case HASH('*', 'p'):
- case HASH('*', 's'):
- case HASH('*', 't'):
- case HASH('*', 'u'):
- case HASH('*', 'w'):
- height = param.x_height;
- break;
- case HASH('*', 'd'):
- case HASH('*', 'l'):
- height = param.asc_height;
- break;
- case HASH('*', 'g'):
- case HASH('*', 'h'):
- case HASH('*', 'm'):
- case HASH('*', 'r'):
- case HASH('*', 'x'):
- case HASH('*', 'y'):
- height = param.x_height;
- depth = param.desc_depth;
- break;
- case HASH('*', 'b'):
- case HASH('*', 'c'):
- case HASH('*', 'f'):
- case HASH('*', 'q'):
- case HASH('*', 'z'):
- height = param.asc_height;
- depth = param.desc_depth;
- break;
- case HASH('t', 's'):
- height = param.x_height;
- depth = param.desc_depth;
- break;
- case HASH('!', 0):
- case HASH('?', 0):
- case HASH('"', 0):
- case HASH('#', 0):
- case HASH('$', 0):
- case HASH('%', 0):
- case HASH('&', 0):
- case HASH('*', 0):
- case HASH('+', 0):
- height = param.asc_height;
- break;
- case HASH('`', 0):
- case HASH('\'', 0):
- height = param.asc_height;
- break;
- case HASH('~', 0):
- case HASH('^', 0):
- case HASH('a', 'a'):
- case HASH('g', 'a'):
- height = param.asc_height;
- break;
- case HASH('r', 'u'):
- case HASH('.', 0):
- break;
- case HASH(',', 0):
- depth = param.comma_depth;
- break;
- case HASH('m', 'i'):
- case HASH('-', 0):
- case HASH('h', 'y'):
- case HASH('e', 'm'):
- height = param.x_height;
- break;
- case HASH(':', 0):
- height = param.x_height;
- break;
- case HASH(';', 0):
- height = param.x_height;
- depth = param.comma_depth;
- break;
- case HASH('=', 0):
- case HASH('e', 'q'):
- height = param.x_height;
- break;
- case HASH('<', 0):
- case HASH('>', 0):
- case HASH('>', '='):
- case HASH('<', '='):
- case HASH('@', 0):
- case HASH('/', 0):
- case HASH('|', 0):
- case HASH('\\', 0):
- height = param.asc_height;
- break;
- case HASH('_', 0):
- case HASH('u', 'l'):
- case HASH('\\', '_'):
- depth = param.em/4;
- break;
- case HASH('r', 'n'):
- height = (param.em*3)/4;
- break;
- case HASH('s', 'r'):
- height = (param.em*3)/4;
- depth = param.em/4;
- break;
- case HASH('b', 'u'):
- case HASH('s', 'q'):
- case HASH('d', 'e'):
- case HASH('d', 'g'):
- case HASH('f', 'm'):
- case HASH('c', 't'):
- case HASH('r', 'g'):
- case HASH('c', 'o'):
- case HASH('p', 'l'):
- case HASH('*', '*'):
- case HASH('s', 'c'):
- case HASH('s', 'l'):
- case HASH('=', '='):
- case HASH('~', '='):
- case HASH('a', 'p'):
- case HASH('!', '='):
- case HASH('-', '>'):
- case HASH('<', '-'):
- case HASH('u', 'a'):
- case HASH('d', 'a'):
- case HASH('m', 'u'):
- case HASH('d', 'i'):
- case HASH('+', '-'):
- case HASH('c', 'u'):
- case HASH('c', 'a'):
- case HASH('s', 'b'):
- case HASH('s', 'p'):
- case HASH('i', 'b'):
- case HASH('i', 'p'):
- case HASH('i', 'f'):
- case HASH('p', 'd'):
- case HASH('g', 'r'):
- case HASH('n', 'o'):
- case HASH('p', 't'):
- case HASH('e', 's'):
- case HASH('m', 'o'):
- case HASH('b', 'r'):
- case HASH('d', 'd'):
- case HASH('r', 'h'):
- case HASH('l', 'h'):
- case HASH('o', 'r'):
- case HASH('c', 'i'):
- height = param.asc_height;
- break;
- case HASH('l', 't'):
- case HASH('l', 'b'):
- case HASH('r', 't'):
- case HASH('r', 'b'):
- case HASH('l', 'k'):
- case HASH('r', 'k'):
- case HASH('b', 'v'):
- case HASH('l', 'f'):
- case HASH('r', 'f'):
- case HASH('l', 'c'):
- case HASH('r', 'c'):
- height = (param.em*3)/4;
- depth = param.em/4;
- break;
-#if 0
- case HASH('%', '0'):
- case HASH('-', '+'):
- case HASH('-', 'D'):
- case HASH('-', 'd'):
- case HASH('-', 'd'):
- case HASH('-', 'h'):
- case HASH('.', 'i'):
- case HASH('.', 'j'):
- case HASH('/', 'L'):
- case HASH('/', 'O'):
- case HASH('/', 'l'):
- case HASH('/', 'o'):
- case HASH('=', '~'):
- case HASH('A', 'E'):
- case HASH('A', 'h'):
- case HASH('A', 'N'):
- case HASH('C', 's'):
- case HASH('D', 'o'):
- case HASH('F', 'c'):
- case HASH('F', 'o'):
- case HASH('I', 'J'):
- case HASH('I', 'm'):
- case HASH('O', 'E'):
- case HASH('O', 'f'):
- case HASH('O', 'K'):
- case HASH('O', 'm'):
- case HASH('O', 'R'):
- case HASH('P', 'o'):
- case HASH('R', 'e'):
- case HASH('S', '1'):
- case HASH('S', '2'):
- case HASH('S', '3'):
- case HASH('T', 'P'):
- case HASH('T', 'p'):
- case HASH('Y', 'e'):
- case HASH('\\', '-'):
- case HASH('a', '"'):
- case HASH('a', '-'):
- case HASH('a', '.'):
- case HASH('a', '^'):
- case HASH('a', 'b'):
- case HASH('a', 'c'):
- case HASH('a', 'd'):
- case HASH('a', 'e'):
- case HASH('a', 'h'):
- case HASH('a', 'o'):
- case HASH('a', 't'):
- case HASH('a', '~'):
- case HASH('b', 'a'):
- case HASH('b', 'b'):
- case HASH('b', 's'):
- case HASH('c', '*'):
- case HASH('c', '+'):
- case HASH('f', '/'):
- case HASH('f', 'a'):
- case HASH('f', 'c'):
- case HASH('f', 'o'):
- case HASH('h', 'a'):
- case HASH('h', 'o'):
- case HASH('i', 'j'):
- case HASH('l', 'A'):
- case HASH('l', 'B'):
- case HASH('l', 'C'):
- case HASH('m', 'd'):
- case HASH('n', 'c'):
- case HASH('n', 'e'):
- case HASH('n', 'm'):
- case HASH('o', 'A'):
- case HASH('o', 'a'):
- case HASH('o', 'e'):
- case HASH('o', 'q'):
- case HASH('p', 'l'):
- case HASH('p', 'p'):
- case HASH('p', 's'):
- case HASH('r', '!'):
- case HASH('r', '?'):
- case HASH('r', 'A'):
- case HASH('r', 'B'):
- case HASH('r', 'C'):
- case HASH('r', 's'):
- case HASH('s', 'h'):
- case HASH('s', 's'):
- case HASH('t', 'e'):
- case HASH('t', 'f'):
- case HASH('t', 'i'):
- case HASH('t', 'm'):
- case HASH('~', '~'):
- case HASH('v', 'S'):
- case HASH('v', 'Z'):
- case HASH('v', 's'):
- case HASH('v', 'z'):
- case HASH('^', 'A'):
- case HASH('^', 'E'):
- case HASH('^', 'I'):
- case HASH('^', 'O'):
- case HASH('^', 'U'):
- case HASH('^', 'a'):
- case HASH('^', 'e'):
- case HASH('^', 'i'):
- case HASH('^', 'o'):
- case HASH('^', 'u'):
- case HASH('`', 'A'):
- case HASH('`', 'E'):
- case HASH('`', 'I'):
- case HASH('`', 'O'):
- case HASH('`', 'U'):
- case HASH('`', 'a'):
- case HASH('`', 'e'):
- case HASH('`', 'i'):
- case HASH('`', 'o'):
- case HASH('`', 'u'):
- case HASH('~', 'A'):
- case HASH('~', 'N'):
- case HASH('~', 'O'):
- case HASH('~', 'a'):
- case HASH('~', 'n'):
- case HASH('~', 'o'):
- case HASH('\'', 'A'):
- case HASH('\'', 'C'):
- case HASH('\'', 'E'):
- case HASH('\'', 'I'):
- case HASH('\'', 'O'):
- case HASH('\'', 'U'):
- case HASH('\'', 'a'):
- case HASH('\'', 'c'):
- case HASH('\'', 'e'):
- case HASH('\'', 'i'):
- case HASH('\'', 'o'):
- case HASH('\'', 'u')
- case HASH(':', 'A'):
- case HASH(':', 'E'):
- case HASH(':', 'I'):
- case HASH(':', 'O'):
- case HASH(':', 'U'):
- case HASH(':', 'Y'):
- case HASH(':', 'a'):
- case HASH(':', 'e'):
- case HASH(':', 'i'):
- case HASH(':', 'o'):
- case HASH(':', 'u'):
- case HASH(':', 'y'):
- case HASH(',', 'C'):
- case HASH(',', 'c'):
-#endif
- }
-}
diff --git a/contrib/groff/src/utils/hpftodit/hpftodit.cc b/contrib/groff/src/utils/hpftodit/hpftodit.cc
deleted file mode 100644
index ecbc8a8..0000000
--- a/contrib/groff/src/utils/hpftodit/hpftodit.cc
+++ /dev/null
@@ -1,809 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1994, 2000, 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-/*
-TODO
-put human readable font name in device file
-devise new names for useful characters
-use --- for unnamed characters
-option to specify symbol sets to look in
-make it work with TrueType fonts
-put filename in error messages (or fix lib)
-*/
-
-#include "lib.h"
-
-#include
-#include
-#include
-#include "assert.h"
-#include "posix.h"
-#include "errarg.h"
-#include "error.h"
-#include "cset.h"
-#include "nonposix.h"
-
-extern "C" const char *Version_string;
-
-#define SIZEOF(v) (sizeof(v)/sizeof(v[0]))
-
-const int MULTIPLIER = 3;
-
-inline
-int scale(int n)
-{
- return n * MULTIPLIER;
-}
-
-// tags in TFM file
-
-enum tag_type {
- min_tag = 400,
- type_tag = 400,
- symbol_set_tag = 404,
- msl_tag = 403,
- inches_per_point_tag = 406,
- design_units_per_em_tag = 408,
- posture_tag = 409,
- stroke_weight_tag = 411,
- spacing_tag = 412,
- slant_tag = 413,
- appearance_width_tag = 414,
- word_spacing_tag = 421,
- x_height_tag = 424,
- lower_ascent_tag = 427,
- lower_descent_tag = 428,
- width_tag = 433,
- left_extent_tag = 435,
- right_extent_tag = 436,
- ascent_tag = 437,
- descent_tag = 438,
- pair_kern_tag = 439,
- typeface_tag = 442,
- max_tag = 443
- };
-
-// types in TFM file
-
-enum {
- ENUM_TYPE = 1,
- BYTE_TYPE = 2,
- USHORT_TYPE = 3,
- FLOAT_TYPE = 5,
- SIGNED_SHORT_TYPE = 17
- };
-
-
-typedef unsigned char byte;
-typedef unsigned short uint16;
-typedef short int16;
-typedef unsigned int uint32;
-
-class File {
-public:
- File(const char *);
- void skip(int n);
- byte get_byte();
- uint16 get_uint16();
- uint32 get_uint32();
- void seek(uint32 n);
-private:
- unsigned char *buf_;
- const unsigned char *ptr_;
- const unsigned char *end_;
-};
-
-struct entry {
- char present;
- uint16 type;
- uint32 count;
- uint32 value;
- entry() : present(0) { }
-};
-
-struct char_info {
- uint16 msl;
- uint16 width;
- uint16 ascent;
- int16 descent;
- int16 left_extent;
- uint16 right_extent;
- uint16 symbol_set;
- unsigned char code;
-};
-
-const uint16 NO_SYMBOL_SET = 0;
-
-struct name_list {
- char *name;
- name_list *next;
- name_list(const char *s, name_list *p) : name(strsave(s)), next(p) { }
- ~name_list() { a_delete name; }
-};
-
-struct symbol_set {
- uint16 select;
- uint16 index[256];
-};
-
-#define SYMBOL_SET(n, c) ((n) * 32 + ((c) - 64))
-
-uint16 text_symbol_sets[] = {
- SYMBOL_SET(0, 'N'), // Latin 1
- SYMBOL_SET(6, 'J'), // Microsoft Publishing
- SYMBOL_SET(2, 'N'), // Latin 2
- 0
- };
-
-uint16 special_symbol_sets[] = {
- SYMBOL_SET(8, 'M'),
- SYMBOL_SET(5, 'M'),
- SYMBOL_SET(15, 'U'),
- 0
- };
-
-entry tags[max_tag + 1 - min_tag];
-
-char_info *char_table;
-uint32 nchars;
-
-unsigned int msl_name_table_size = 0;
-name_list **msl_name_table = 0;
-
-unsigned int n_symbol_sets;
-symbol_set *symbol_set_table;
-
-static int special_flag = 0;
-static int italic_flag = 0;
-static int italic_sep;
-
-static void usage(FILE *stream);
-static void usage();
-static const char *xbasename(const char *);
-static void read_tags(File &);
-static void check_type();
-static void check_units(File &);
-static int read_map(const char *);
-static void require_tag(tag_type);
-static void dump_tags(File &f);
-static void output_spacewidth();
-static void output_pclweight();
-static void output_pclproportional();
-static void read_and_output_pcltypeface(File &);
-static void output_pclstyle();
-static void output_slant();
-static void output_ligatures();
-static void read_symbol_sets(File &);
-static void read_and_output_kernpairs(File &);
-static void output_charset();
-static void read_char_table(File &f);
-
-inline
-entry &tag_info(tag_type t)
-{
- return tags[t - min_tag];
-}
-
-int main(int argc, char **argv)
-{
- program_name = argv[0];
-
- int opt;
- int debug_flag = 0;
-
- 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, "dsvi:", long_options, NULL)) != EOF) {
- switch (opt) {
- case 'd':
- debug_flag = 1;
- break;
- case 's':
- special_flag = 1;
- break;
- case 'i':
- italic_flag = 1;
- italic_sep = atoi(optarg);
- break;
- case 'v':
- {
- printf("GNU hpftodit (groff) version %s\n", Version_string);
- exit(0);
- }
- break;
- case CHAR_MAX + 1: // --help
- usage(stdout);
- exit(0);
- break;
- case '?':
- usage();
- break;
- default:
- assert(0);
- }
- }
- if (argc - optind != 3)
- usage();
- File f(argv[optind]);
- if (!read_map(argv[optind + 1]))
- exit(1);
- current_filename = 0;
- current_lineno = -1; // no line numbers
- if (freopen(argv[optind + 2], "w", stdout) == 0)
- fatal("cannot open `%1': %2", argv[optind + 2], strerror(errno));
- current_filename = argv[optind];
- printf("name %s\n", xbasename(argv[optind + 2]));
- if (special_flag)
- printf("special\n");
- read_tags(f);
- check_type();
- check_units(f);
- if (debug_flag)
- dump_tags(f);
- read_char_table(f);
- output_spacewidth();
- output_slant();
- read_and_output_pcltypeface(f);
- output_pclproportional();
- output_pclweight();
- output_pclstyle();
- read_symbol_sets(f);
- output_ligatures();
- read_and_output_kernpairs(f);
- output_charset();
- return 0;
-}
-
-static
-void usage(FILE *stream)
-{
- fprintf(stream, "usage: %s [-s] [-i n] tfm_file map_file output_font\n",
- program_name);
-}
-static
-void usage()
-{
- usage(stderr);
- exit(1);
-}
-
-File::File(const char *s)
-{
- // We need to read the file in binary mode because hpftodit relies
- // on byte counts.
- int fd = open(s, O_RDONLY | O_BINARY);
- if (fd < 0)
- fatal("cannot open `%1': %2", s, strerror(errno));
- current_filename = s;
- struct stat sb;
- if (fstat(fd, &sb) < 0)
- fatal("cannot stat: %1", strerror(errno));
- if (!S_ISREG(sb.st_mode))
- fatal("not a regular file");
- buf_ = new unsigned char[sb.st_size];
- long nread = read(fd, buf_, sb.st_size);
- if (nread < 0)
- fatal("read error: %1", strerror(errno));
- if (nread != sb.st_size)
- fatal("read unexpected number of bytes");
- ptr_ = buf_;
- end_ = buf_ + sb.st_size;
-}
-
-void File::skip(int n)
-{
- if (end_ - ptr_ < n)
- fatal("unexpected end of file");
- ptr_ += n;
-}
-
-void File::seek(uint32 n)
-{
- if ((uint32)(end_ - buf_) < n)
- fatal("unexpected end of file");
- ptr_ = buf_ + n;
-}
-
-byte File::get_byte()
-{
- if (ptr_ >= end_)
- fatal("unexpected end of file");
- return *ptr_++;
-}
-
-uint16 File::get_uint16()
-{
- if (end_ - ptr_ < 2)
- fatal("unexpected end of file");
- uint16 n = *ptr_++;
- return n + (*ptr_++ << 8);
-}
-
-uint32 File::get_uint32()
-{
- if (end_ - ptr_ < 4)
- fatal("unexpected end of file");
- uint32 n = *ptr_++;
- for (int i = 0; i < 3; i++)
- n += *ptr_++ << (i + 1)*8;
- return n;
-}
-
-static
-void read_tags(File &f)
-{
- if (f.get_byte() != 'I' || f.get_byte() != 'I')
- fatal("not an Intel format TFM file");
- f.skip(6);
- uint16 ntags = f.get_uint16();
- entry dummy;
- for (uint16 i = 0; i < ntags; i++) {
- uint16 tag = f.get_uint16();
- entry *p;
- if (min_tag <= tag && tag <= max_tag)
- p = tags + (tag - min_tag);
- else
- p = &dummy;
- p->present = 1;
- p->type = f.get_uint16();
- p->count = f.get_uint32();
- p->value = f.get_uint32();
- }
-}
-
-static
-void check_type()
-{
- require_tag(type_tag);
- if (tag_info(type_tag).value != 0) {
- if (tag_info(type_tag).value == 2)
- fatal("cannot handle TrueType tfm files");
- fatal("unknown type tag %1", int(tag_info(type_tag).value));
- }
-}
-
-static
-void check_units(File &f)
-{
- require_tag(design_units_per_em_tag);
- f.seek(tag_info(design_units_per_em_tag).value);
- uint32 num = f.get_uint32();
- uint32 den = f.get_uint32();
- if (num != 8782 || den != 1)
- fatal("design units per em != 8782/1");
- require_tag(inches_per_point_tag);
- f.seek(tag_info(inches_per_point_tag).value);
- num = f.get_uint32();
- den = f.get_uint32();
- if (num != 100 || den != 7231)
- fatal("inches per point not 100/7231");
-}
-
-static
-void require_tag(tag_type t)
-{
- if (!tag_info(t).present)
- fatal("tag %1 missing", int(t));
-}
-
-static
-void output_spacewidth()
-{
- require_tag(word_spacing_tag);
- printf("spacewidth %d\n", scale(tag_info(word_spacing_tag).value));
-}
-
-static
-void read_symbol_sets(File &f)
-{
- uint32 symbol_set_dir_length = tag_info(symbol_set_tag).count;
- n_symbol_sets = symbol_set_dir_length/14;
- symbol_set_table = new symbol_set[n_symbol_sets];
- unsigned int i;
- for (i = 0; i < n_symbol_sets; i++) {
- f.seek(tag_info(symbol_set_tag).value + i*14);
- (void)f.get_uint32();
- uint32 off1 = f.get_uint32();
- uint32 off2 = f.get_uint32();
- (void)f.get_uint16(); // what's this for?
- f.seek(off1);
- unsigned int j;
- uint16 kind = 0;
- for (j = 0; j < off2 - off1; j++) {
- unsigned char c = f.get_byte();
- if ('0' <= c && c <= '9')
- kind = kind*10 + (c - '0');
- else if ('A' <= c && c <= 'Z')
- kind = kind*32 + (c - 64);
- }
- symbol_set_table[i].select = kind;
- for (j = 0; j < 256; j++)
- symbol_set_table[i].index[j] = f.get_uint16();
- }
- for (i = 0; i < nchars; i++)
- char_table[i].symbol_set = NO_SYMBOL_SET;
-
- uint16 *symbol_set_selectors = (special_flag
- ? special_symbol_sets
- : text_symbol_sets);
- for (i = 0; symbol_set_selectors[i] != 0; i++) {
- unsigned int j;
- for (j = 0; j < n_symbol_sets; j++)
- if (symbol_set_table[j].select == symbol_set_selectors[i])
- break;
- if (j < n_symbol_sets) {
- for (int k = 0; k < 256; k++) {
- uint16 index = symbol_set_table[j].index[k];
- if (index != 0xffff
- && char_table[index].symbol_set == NO_SYMBOL_SET) {
- char_table[index].symbol_set = symbol_set_table[j].select;
- char_table[index].code = k;
- }
- }
- }
- }
-}
-
-static
-void read_char_table(File &f)
-{
- require_tag(msl_tag);
- nchars = tag_info(msl_tag).count;
- char_table = new char_info[nchars];
-
- f.seek(tag_info(msl_tag).value);
- uint32 i;
- for (i = 0; i < nchars; i++)
- char_table[i].msl = f.get_uint16();
-
- require_tag(width_tag);
- f.seek(tag_info(width_tag).value);
- for (i = 0; i < nchars; i++)
- char_table[i].width = f.get_uint16();
-
- require_tag(ascent_tag);
- f.seek(tag_info(ascent_tag).value);
- for (i = 0; i < nchars; i++) {
- char_table[i].ascent = f.get_uint16();
- }
-
- require_tag(descent_tag);
- f.seek(tag_info(descent_tag).value);
- for (i = 0; i < nchars; i++) {
- char_table[i].descent = f.get_uint16();
- if (char_table[i].descent > 0)
- char_table[i].descent = 0;
- }
-
- require_tag(left_extent_tag);
- f.seek(tag_info(left_extent_tag).value);
- for (i = 0; i < nchars; i++)
- char_table[i].left_extent = int16(f.get_uint16());
-
- require_tag(right_extent_tag);
- f.seek(tag_info(right_extent_tag).value);
- for (i = 0; i < nchars; i++)
- char_table[i].right_extent = f.get_uint16();
-}
-
-static
-void output_pclweight()
-{
- require_tag(stroke_weight_tag);
- int stroke_weight = tag_info(stroke_weight_tag).value;
- int pcl_stroke_weight;
- if (stroke_weight < 128)
- pcl_stroke_weight = -3;
- else if (stroke_weight == 128)
- pcl_stroke_weight = 0;
- else if (stroke_weight <= 145)
- pcl_stroke_weight = 1;
- else if (stroke_weight <= 179)
- pcl_stroke_weight = 3;
- else
- pcl_stroke_weight = 4;
- printf("pclweight %d\n", pcl_stroke_weight);
-}
-
-static
-void output_pclproportional()
-{
- require_tag(spacing_tag);
- printf("pclproportional %d\n", tag_info(spacing_tag).value == 0);
-}
-
-static
-void read_and_output_pcltypeface(File &f)
-{
- printf("pcltypeface ");
- require_tag(typeface_tag);
- f.seek(tag_info(typeface_tag).value);
- for (uint32 i = 0; i < tag_info(typeface_tag).count; i++) {
- unsigned char c = f.get_byte();
- if (c == '\0')
- break;
- putchar(c);
- }
- printf("\n");
-}
-
-static
-void output_pclstyle()
-{
- unsigned pcl_style = 0;
- // older tfms don't have the posture tag
- if (tag_info(posture_tag).present) {
- if (tag_info(posture_tag).value)
- pcl_style |= 1;
- }
- else {
- require_tag(slant_tag);
- if (tag_info(slant_tag).value != 0)
- pcl_style |= 1;
- }
- require_tag(appearance_width_tag);
- if (tag_info(appearance_width_tag).value < 100) // guess
- pcl_style |= 4;
- printf("pclstyle %d\n", pcl_style);
-}
-
-static
-void output_slant()
-{
- require_tag(slant_tag);
- int slant = int16(tag_info(slant_tag).value);
- if (slant != 0)
- printf("slant %f\n", slant/100.0);
-}
-
-static
-void output_ligatures()
-{
- // don't use ligatures for fixed space font
- require_tag(spacing_tag);
- if (tag_info(spacing_tag).value != 0)
- return;
- static const char *ligature_names[] = {
- "fi", "fl", "ff", "ffi", "ffl"
- };
-
- static const char *ligature_chars[] = {
- "fi", "fl", "ff", "Fi", "Fl"
- };
-
- unsigned ligature_mask = 0;
- unsigned int i;
- for (i = 0; i < nchars; i++) {
- uint16 msl = char_table[i].msl;
- if (msl < msl_name_table_size
- && char_table[i].symbol_set != NO_SYMBOL_SET) {
- for (name_list *p = msl_name_table[msl]; p; p = p->next)
- for (unsigned int j = 0; j < SIZEOF(ligature_chars); j++)
- if (strcmp(p->name, ligature_chars[j]) == 0) {
- ligature_mask |= 1 << j;
- break;
- }
- }
- }
- if (ligature_mask) {
- printf("ligatures");
- for (i = 0; i < SIZEOF(ligature_names); i++)
- if (ligature_mask & (1 << i))
- printf(" %s", ligature_names[i]);
- printf(" 0\n");
- }
-}
-
-static
-void read_and_output_kernpairs(File &f)
-{
- if (tag_info(pair_kern_tag).present) {
- printf("kernpairs\n");
- f.seek(tag_info(pair_kern_tag).value);
- uint16 n_pairs = f.get_uint16();
- for (int i = 0; i < n_pairs; i++) {
- uint16 i1 = f.get_uint16();
- uint16 i2 = f.get_uint16();
- int16 val = int16(f.get_uint16());
- if (char_table[i1].symbol_set != NO_SYMBOL_SET
- && char_table[i2].symbol_set != NO_SYMBOL_SET
- && char_table[i1].msl < msl_name_table_size
- && char_table[i2].msl < msl_name_table_size) {
- for (name_list *p = msl_name_table[char_table[i1].msl];
- p;
- p = p->next)
- for (name_list *q = msl_name_table[char_table[i2].msl];
- q;
- q = q->next)
- printf("%s %s %d\n", p->name, q->name, scale(val));
- }
- }
- }
-}
-
-static
-void output_charset()
-{
- require_tag(slant_tag);
- double slant_angle = int16(tag_info(slant_tag).value)*PI/18000.0;
- double slant = sin(slant_angle)/cos(slant_angle);
-
- require_tag(x_height_tag);
- require_tag(lower_ascent_tag);
- require_tag(lower_descent_tag);
-
- printf("charset\n");
- unsigned int i;
- for (i = 0; i < nchars; i++) {
- uint16 msl = char_table[i].msl;
- if (msl < msl_name_table_size
- && msl_name_table[msl]) {
- if (char_table[i].symbol_set != NO_SYMBOL_SET) {
- printf("%s\t%d,%d",
- msl_name_table[msl]->name,
- scale(char_table[i].width),
- scale(char_table[i].ascent));
- int depth = scale(- char_table[i].descent);
- if (depth < 0)
- depth = 0;
- int italic_correction = 0;
- int left_italic_correction = 0;
- int subscript_correction = 0;
- if (italic_flag) {
- italic_correction = scale(char_table[i].right_extent
- - char_table[i].width
- + italic_sep);
- if (italic_correction < 0)
- italic_correction = 0;
- subscript_correction = int((tag_info(x_height_tag).value
- * slant * .8) + .5);
- if (subscript_correction > italic_correction)
- subscript_correction = italic_correction;
- left_italic_correction = scale(italic_sep
- - char_table[i].left_extent);
- }
- if (subscript_correction != 0)
- printf(",%d,%d,%d,%d",
- depth, italic_correction, left_italic_correction,
- subscript_correction);
- else if (left_italic_correction != 0)
- printf(",%d,%d,%d", depth, italic_correction, left_italic_correction);
- else if (italic_correction != 0)
- printf(",%d,%d", depth, italic_correction);
- else if (depth != 0)
- printf(",%d", depth);
- // This is fairly arbitrary. Fortunately it doesn't much matter.
- unsigned type = 0;
- if (char_table[i].ascent > (tag_info(lower_ascent_tag).value*9)/10)
- type |= 2;
- if (char_table[i].descent < (int16(tag_info(lower_descent_tag).value)*9)/10)
- type |= 1;
- printf("\t%d\t%d\n",
- type,
- char_table[i].symbol_set*256 + char_table[i].code);
- for (name_list *p = msl_name_table[msl]->next; p; p = p->next)
- printf("%s\t\"\n", p->name);
- }
- else
- warning("MSL %1 not in any of the searched symbol sets", msl);
- }
- }
-}
-
-static
-void dump_tags(File &f)
-{
- int i;
- for (i = min_tag; i <= max_tag; i++) {
- enum tag_type t = tag_type(i);
- if (tag_info(t).present) {
- fprintf(stderr,
- "%d %d %d %d\n", i, tag_info(t).type, tag_info(t).count,
- tag_info(t).value);
- if (tag_info(t).type == FLOAT_TYPE
- && tag_info(t).count == 1) {
- f.seek(tag_info(t).value);
- uint32 num = f.get_uint32();
- uint32 den = f.get_uint32();
- fprintf(stderr, "(%u/%u = %g)\n", num, den, (double)num/den);
- }
- }
- }
-}
-
-static
-int read_map(const char *file)
-{
- errno = 0;
- FILE *fp = fopen(file, "r");
- if (!fp) {
- error("can't open `%1': %2", file, strerror(errno));
- return 0;
- }
- current_filename = file;
- char buf[512];
- current_lineno = 0;
- while (fgets(buf, int(sizeof(buf)), fp)) {
- current_lineno++;
- char *ptr = buf;
- while (csspace(*ptr))
- ptr++;
- if (*ptr == '\0' || *ptr == '#')
- continue;
- ptr = strtok(ptr, " \n\t");
- if (!ptr)
- continue;
- int n;
- if (sscanf(ptr, "%d", &n) != 1) {
- error("bad map file");
- fclose(fp);
- return 0;
- }
- if (n < 0) {
- error("negative code");
- fclose(fp);
- return 0;
- }
- if ((size_t)n >= msl_name_table_size) {
- size_t old_size = msl_name_table_size;
- name_list **old_table = msl_name_table;
- msl_name_table_size = n + 256;
- msl_name_table = new name_list *[msl_name_table_size];
- if (old_table) {
- memcpy(msl_name_table, old_table, old_size*sizeof(name_list *));
- a_delete old_table;
- }
- for (size_t i = old_size; i < msl_name_table_size; i++)
- msl_name_table[i] = 0;
- }
- ptr = strtok(0, " \n\t");
- if (!ptr) {
- error("missing names");
- fclose(fp);
- return 0;
- }
- for (; ptr; ptr = strtok(0, " \n\t"))
- msl_name_table[n] = new name_list(ptr, msl_name_table[n]);
- }
- fclose(fp);
- return 1;
-}
-
-static
-const char *xbasename(const char *s)
-{
- // DIR_SEPS[] are possible directory separator characters, see
- // nonposix.h. We want the rightmost separator of all possible
- // ones. Example: d:/foo\\bar.
- const char *b = strrchr(s, DIR_SEPS[0]), *b1;
- const char *sep = &DIR_SEPS[1];
-
- while (*sep)
- {
- b1 = strrchr(s, *sep);
- if (b1 && (!b || b1 > b))
- b = b1;
- sep++;
- }
- return b ? b + 1 : s;
-}
diff --git a/contrib/groff/src/utils/indxbib/indxbib.cc b/contrib/groff/src/utils/indxbib/indxbib.cc
deleted file mode 100644
index 9fced93..0000000
--- a/contrib/groff/src/utils/indxbib/indxbib.cc
+++ /dev/null
@@ -1,789 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1989-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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "lib.h"
-
-#include
-#include
-#include
-
-#include "posix.h"
-#include "errarg.h"
-#include "error.h"
-#include "stringclass.h"
-#include "cset.h"
-#include "cmap.h"
-
-#include "defs.h"
-#include "index.h"
-
-#include "nonposix.h"
-
-extern "C" const char *Version_string;
-
-#define DEFAULT_HASH_TABLE_SIZE 997
-#define TEMP_INDEX_TEMPLATE "indxbibXXXXXX"
-
-// (2^n - MALLOC_OVERHEAD) should be a good argument for malloc().
-
-#define MALLOC_OVERHEAD 16
-
-#ifdef BLOCK_SIZE
-#undef BLOCK_SIZE
-#endif
-
-const int BLOCK_SIZE = ((1024 - MALLOC_OVERHEAD - sizeof(struct block *)
- - sizeof(int)) / sizeof(int));
-struct block {
- block *next;
- int used;
- int v[BLOCK_SIZE];
-
- block(block *p = 0) : next(p), used(0) { }
-};
-
-struct block;
-
-union table_entry {
- block *ptr;
- int count;
-};
-
-struct word_list {
- word_list *next;
- char *str;
- int len;
- word_list(const char *, int, word_list *);
-};
-
-table_entry *hash_table;
-int hash_table_size = DEFAULT_HASH_TABLE_SIZE;
-// We make this the same size as hash_table so we only have to do one
-// mod per key.
-static word_list **common_words_table = 0;
-char *key_buffer;
-
-FILE *indxfp;
-int ntags = 0;
-string filenames;
-char *temp_index_file = 0;
-
-const char *ignore_fields = "XYZ";
-const char *common_words_file = COMMON_WORDS_FILE;
-int n_ignore_words = 100;
-int truncate_len = 6;
-int shortest_len = 3;
-int max_keys_per_item = 100;
-
-static void usage(FILE *stream);
-static void write_hash_table();
-static void init_hash_table();
-static void read_common_words_file();
-static int store_key(char *s, int len);
-static void possibly_store_key(char *s, int len);
-static int do_whole_file(const char *filename);
-static int do_file(const char *filename);
-static void store_reference(int filename_index, int pos, int len);
-static void check_integer_arg(char opt, const char *arg, int min, int *res);
-static void store_filename(const char *);
-static void fwrite_or_die(const void *ptr, int size, int nitems, FILE *fp);
-static char *get_cwd();
-
-extern "C" {
- void cleanup();
- void catch_fatal_signals();
- void ignore_fatal_signals();
-}
-
-int main(int argc, char **argv)
-{
- program_name = argv[0];
- static char stderr_buf[BUFSIZ];
- setbuf(stderr, stderr_buf);
-
- const char *basename = 0;
- typedef int (*parser_t)(const char *);
- parser_t parser = do_file;
- const char *directory = 0;
- const char *foption = 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, "c:o:h:i:k:l:t:n:c:d:f:vw",
- long_options, NULL))
- != EOF)
- switch (opt) {
- case 'c':
- common_words_file = optarg;
- break;
- case 'd':
- directory = optarg;
- break;
- case 'f':
- foption = optarg;
- break;
- case 'h':
- check_integer_arg('h', optarg, 1, &hash_table_size);
- if (!is_prime(hash_table_size)) {
- while (!is_prime(++hash_table_size))
- ;
- warning("%1 not prime: using %2 instead", optarg, hash_table_size);
- }
- break;
- case 'i':
- ignore_fields = optarg;
- break;
- case 'k':
- check_integer_arg('k', optarg, 1, &max_keys_per_item);
- break;
- case 'l':
- check_integer_arg('l', optarg, 0, &shortest_len);
- break;
- case 'n':
- check_integer_arg('n', optarg, 0, &n_ignore_words);
- break;
- case 'o':
- basename = optarg;
- break;
- case 't':
- check_integer_arg('t', optarg, 1, &truncate_len);
- break;
- case 'w':
- parser = do_whole_file;
- break;
- case 'v':
- printf("GNU indxbib (groff) version %s\n", Version_string);
- exit(0);
- break;
- case CHAR_MAX + 1: // --help
- usage(stdout);
- exit(0);
- break;
- case '?':
- usage(stderr);
- exit(1);
- break;
- default:
- assert(0);
- break;
- }
- if (optind >= argc && foption == 0)
- fatal("no files and no -f option");
- if (!directory) {
- char *path = get_cwd();
- store_filename(path);
- a_delete path;
- }
- else
- store_filename(directory);
- init_hash_table();
- store_filename(common_words_file);
- store_filename(ignore_fields);
- key_buffer = new char[truncate_len];
- read_common_words_file();
- if (!basename)
- basename = optind < argc ? argv[optind] : DEFAULT_INDEX_NAME;
- const char *p = strrchr(basename, DIR_SEPS[0]), *p1;
- const char *sep = &DIR_SEPS[1];
- while (*sep) {
- p1 = strrchr(basename, *sep);
- if (p1 && (!p || p1 > p))
- p = p1;
- sep++;
- }
- size_t name_max;
- if (p) {
- char *dir = strsave(basename);
- dir[p - basename] = '\0';
- name_max = file_name_max(dir);
- a_delete dir;
- }
- else
- name_max = file_name_max(".");
- const char *filename = p ? p + 1 : basename;
- if (name_max >= 0 &&
- (strlen(filename) + sizeof(INDEX_SUFFIX) - 1) > name_max)
- fatal("`%1.%2' is too long for a filename", filename, INDEX_SUFFIX);
- if (p) {
- p++;
- temp_index_file = new char[p - basename + sizeof(TEMP_INDEX_TEMPLATE)];
- memcpy(temp_index_file, basename, p - basename);
- strcpy(temp_index_file + (p - basename), TEMP_INDEX_TEMPLATE);
- }
- else {
- temp_index_file = strsave(TEMP_INDEX_TEMPLATE);
- }
- catch_fatal_signals();
- int fd = mkstemp(temp_index_file);
- if (fd < 0)
- fatal("can't create temporary index file: %1", strerror(errno));
- indxfp = fdopen(fd, FOPEN_WB);
- if (indxfp == 0)
- fatal("fdopen failed");
- if (fseek(indxfp, sizeof(index_header), 0) < 0)
- fatal("can't seek past index header: %1", strerror(errno));
- int failed = 0;
- if (foption) {
- FILE *fp = stdin;
- if (strcmp(foption, "-") != 0) {
- errno = 0;
- fp = fopen(foption, "r");
- if (!fp)
- fatal("can't open `%1': %2", foption, strerror(errno));
- }
- string path;
- int lineno = 1;
- for (;;) {
- int c;
- for (c = getc(fp); c != '\n' && c != EOF; c = getc(fp)) {
- if (c == '\0')
- error_with_file_and_line(foption, lineno,
- "nul character in pathname ignored");
- else
- path += c;
- }
- if (path.length() > 0) {
- path += '\0';
- if (!(*parser)(path.contents()))
- failed = 1;
- path.clear();
- }
- if (c == EOF)
- break;
- lineno++;
- }
- if (fp != stdin)
- fclose(fp);
- }
- for (int i = optind; i < argc; i++)
- if (!(*parser)(argv[i]))
- failed = 1;
- write_hash_table();
- if (fclose(indxfp) < 0)
- fatal("error closing temporary index file: %1", strerror(errno));
- char *index_file = new char[strlen(basename) + sizeof(INDEX_SUFFIX)];
- strcpy(index_file, basename);
- strcat(index_file, INDEX_SUFFIX);
-#ifdef HAVE_RENAME
-#ifdef __EMX__
- unline(index_file);
-#endif /* __EMX__ */
- if (rename(temp_index_file, index_file) < 0) {
-#ifdef __MSDOS__
- // RENAME could fail on plain MSDOS filesystems because
- // INDEX_FILE is an invalid filename, e.g. it has multiple dots.
- char *fname = p ? index_file + (p - basename) : 0;
- char *dot = 0;
-
- // Replace the dot with an underscore and try again.
- if (fname
- && (dot = strchr(fname, '.')) != 0
- && strcmp(dot, INDEX_SUFFIX) != 0)
- *dot = '_';
- if (rename(temp_index_file, index_file) < 0)
-#endif
- fatal("can't rename temporary index file: %1", strerror(errno));
- }
-#else /* not HAVE_RENAME */
- ignore_fatal_signals();
- if (unlink(index_file) < 0) {
- if (errno != ENOENT)
- fatal("can't unlink `%1': %2", index_file, strerror(errno));
- }
- if (link(temp_index_file, index_file) < 0)
- fatal("can't link temporary index file: %1", strerror(errno));
- if (unlink(temp_index_file) < 0)
- fatal("can't unlink temporary index file: %1", strerror(errno));
-#endif /* not HAVE_RENAME */
- temp_index_file = 0;
- return failed;
-}
-
-static void usage(FILE *stream)
-{
- fprintf(stream,
-"usage: %s [-vw] [-c file] [-d dir] [-f file] [-h n] [-i XYZ] [-k n]\n"
-" [-l n] [-n n] [-o base] [-t n] [files...]\n",
- program_name);
-}
-
-static void check_integer_arg(char opt, const char *arg, int min, int *res)
-{
- char *ptr;
- long n = strtol(arg, &ptr, 10);
- if (n == 0 && ptr == arg)
- error("argument to -%1 not an integer", opt);
- else if (n < min)
- error("argument to -%1 must not be less than %2", opt, min);
- else {
- if (n > INT_MAX)
- error("argument to -%1 greater than maximum integer", opt);
- else if (*ptr != '\0')
- error("junk after integer argument to -%1", opt);
- *res = int(n);
- }
-}
-
-static char *get_cwd()
-{
- char *buf;
- int size = 12;
-
- for (;;) {
- buf = new char[size];
- if (getcwd(buf, size))
- break;
- if (errno != ERANGE)
- fatal("cannot get current working directory: %1", strerror(errno));
- a_delete buf;
- if (size == INT_MAX)
- fatal("current working directory longer than INT_MAX");
- if (size > INT_MAX/2)
- size = INT_MAX;
- else
- size *= 2;
- }
- return buf;
-}
-
-word_list::word_list(const char *s, int n, word_list *p)
-: next(p), len(n)
-{
- str = new char[n];
- memcpy(str, s, n);
-}
-
-static void read_common_words_file()
-{
- if (n_ignore_words <= 0)
- return;
- errno = 0;
- FILE *fp = fopen(common_words_file, "r");
- if (!fp)
- fatal("can't open `%1': %2", common_words_file, strerror(errno));
- common_words_table = new word_list * [hash_table_size];
- for (int i = 0; i < hash_table_size; i++)
- common_words_table[i] = 0;
- int count = 0;
- int key_len = 0;
- for (;;) {
- int c = getc(fp);
- while (c != EOF && !csalnum(c))
- c = getc(fp);
- if (c == EOF)
- break;
- do {
- if (key_len < truncate_len)
- key_buffer[key_len++] = cmlower(c);
- c = getc(fp);
- } while (c != EOF && csalnum(c));
- if (key_len >= shortest_len) {
- int h = hash(key_buffer, key_len) % hash_table_size;
- common_words_table[h] = new word_list(key_buffer, key_len,
- common_words_table[h]);
- }
- if (++count >= n_ignore_words)
- break;
- key_len = 0;
- if (c == EOF)
- break;
- }
- n_ignore_words = count;
- fclose(fp);
-}
-
-static int do_whole_file(const char *filename)
-{
- errno = 0;
- FILE *fp = fopen(filename, "r");
- if (!fp) {
- error("can't open `%1': %2", filename, strerror(errno));
- return 0;
- }
- int count = 0;
- int key_len = 0;
- int c;
- while ((c = getc(fp)) != EOF) {
- if (csalnum(c)) {
- key_len = 1;
- key_buffer[0] = c;
- while ((c = getc(fp)) != EOF) {
- if (!csalnum(c))
- break;
- if (key_len < truncate_len)
- key_buffer[key_len++] = c;
- }
- if (store_key(key_buffer, key_len)) {
- if (++count >= max_keys_per_item)
- break;
- }
- if (c == EOF)
- break;
- }
- }
- store_reference(filenames.length(), 0, 0);
- store_filename(filename);
- fclose(fp);
- return 1;
-}
-
-static int do_file(const char *filename)
-{
- errno = 0;
- // Need binary I/O for MS-DOS/MS-Windows, because indxbib relies on
- // byte counts to be consistent with fseek.
- FILE *fp = fopen(filename, FOPEN_RB);
- if (fp == 0) {
- error("can't open `%1': %2", filename, strerror(errno));
- return 0;
- }
- int filename_index = filenames.length();
- store_filename(filename);
-
- enum {
- START, // at the start of the file; also in between references
- BOL, // in the middle of a reference, at the beginning of the line
- PERCENT, // seen a percent at the beginning of the line
- IGNORE, // ignoring a field
- IGNORE_BOL, // at the beginning of a line ignoring a field
- KEY, // in the middle of a key
- DISCARD, // after truncate_len bytes of a key
- MIDDLE // in between keys
- } state = START;
-
- // In states START, BOL, IGNORE_BOL, space_count how many spaces at
- // the beginning have been seen. In states PERCENT, IGNORE, KEY,
- // MIDDLE space_count must be 0.
- int space_count = 0;
- int byte_count = 0; // bytes read
- int key_len = 0;
- int ref_start = -1; // position of start of current reference
- for (;;) {
- int c = getc(fp);
- if (c == EOF)
- break;
- // We opened the file in binary mode, so we need to skip
- // every CR character before a Newline.
- if (c == '\r') {
- int peek = getc(fp);
- if (peek == '\n') {
- byte_count++;
- c = peek;
- }
- else
- ungetc(peek, fp);
- }
-#if defined(__MSDOS__) || defined(_MSC_VER)
- else if (c == 0x1a) // ^Z means EOF in text files
- break;
-#endif
- byte_count++;
- switch (state) {
- case START:
- if (c == ' ' || c == '\t') {
- space_count++;
- break;
- }
- if (c == '\n') {
- space_count = 0;
- break;
- }
- ref_start = byte_count - space_count - 1;
- space_count = 0;
- if (c == '%')
- state = PERCENT;
- else if (csalnum(c)) {
- state = KEY;
- key_buffer[0] = c;
- key_len = 1;
- }
- else
- state = MIDDLE;
- break;
- case BOL:
- switch (c) {
- case '%':
- if (space_count > 0) {
- space_count = 0;
- state = MIDDLE;
- }
- else
- state = PERCENT;
- break;
- case ' ':
- case '\t':
- space_count++;
- break;
- case '\n':
- store_reference(filename_index, ref_start,
- byte_count - 1 - space_count - ref_start);
- state = START;
- space_count = 0;
- break;
- default:
- space_count = 0;
- if (csalnum(c)) {
- state = KEY;
- key_buffer[0] = c;
- key_len = 1;
- }
- else
- state = MIDDLE;
- }
- break;
- case PERCENT:
- if (strchr(ignore_fields, c) != 0)
- state = IGNORE;
- else if (c == '\n')
- state = BOL;
- else
- state = MIDDLE;
- break;
- case IGNORE:
- if (c == '\n')
- state = IGNORE_BOL;
- break;
- case IGNORE_BOL:
- switch (c) {
- case '%':
- if (space_count > 0) {
- state = IGNORE;
- space_count = 0;
- }
- else
- state = PERCENT;
- break;
- case ' ':
- case '\t':
- space_count++;
- break;
- case '\n':
- store_reference(filename_index, ref_start,
- byte_count - 1 - space_count - ref_start);
- state = START;
- space_count = 0;
- break;
- default:
- space_count = 0;
- state = IGNORE;
- }
- break;
- case KEY:
- if (csalnum(c)) {
- if (key_len < truncate_len)
- key_buffer[key_len++] = c;
- else
- state = DISCARD;
- }
- else {
- possibly_store_key(key_buffer, key_len);
- key_len = 0;
- if (c == '\n')
- state = BOL;
- else
- state = MIDDLE;
- }
- break;
- case DISCARD:
- if (!csalnum(c)) {
- possibly_store_key(key_buffer, key_len);
- key_len = 0;
- if (c == '\n')
- state = BOL;
- else
- state = MIDDLE;
- }
- break;
- case MIDDLE:
- if (csalnum(c)) {
- state = KEY;
- key_buffer[0] = c;
- key_len = 1;
- }
- else if (c == '\n')
- state = BOL;
- break;
- default:
- assert(0);
- }
- }
- switch (state) {
- case START:
- break;
- case DISCARD:
- case KEY:
- possibly_store_key(key_buffer, key_len);
- // fall through
- case BOL:
- case PERCENT:
- case IGNORE_BOL:
- case IGNORE:
- case MIDDLE:
- store_reference(filename_index, ref_start,
- byte_count - ref_start - space_count);
- break;
- default:
- assert(0);
- }
- fclose(fp);
- return 1;
-}
-
-static void store_reference(int filename_index, int pos, int len)
-{
- tag t;
- t.filename_index = filename_index;
- t.start = pos;
- t.length = len;
- fwrite_or_die(&t, sizeof(t), 1, indxfp);
- ntags++;
-}
-
-static void store_filename(const char *fn)
-{
- filenames += fn;
- filenames += '\0';
-}
-
-static void init_hash_table()
-{
- hash_table = new table_entry[hash_table_size];
- for (int i = 0; i < hash_table_size; i++)
- hash_table[i].ptr = 0;
-}
-
-static void possibly_store_key(char *s, int len)
-{
- static int last_tagno = -1;
- static int key_count;
- if (last_tagno != ntags) {
- last_tagno = ntags;
- key_count = 0;
- }
- if (key_count < max_keys_per_item) {
- if (store_key(s, len))
- key_count++;
- }
-}
-
-static int store_key(char *s, int len)
-{
- if (len < shortest_len)
- return 0;
- int is_number = 1;
- for (int i = 0; i < len; i++)
- if (!csdigit(s[i])) {
- is_number = 0;
- s[i] = cmlower(s[i]);
- }
- if (is_number && !(len == 4 && s[0] == '1' && s[1] == '9'))
- return 0;
- int h = hash(s, len) % hash_table_size;
- if (common_words_table) {
- for (word_list *ptr = common_words_table[h]; ptr; ptr = ptr->next)
- if (len == ptr->len && memcmp(s, ptr->str, len) == 0)
- return 0;
- }
- table_entry *pp = hash_table + h;
- if (!pp->ptr)
- pp->ptr = new block;
- else if (pp->ptr->v[pp->ptr->used - 1] == ntags)
- return 1;
- else if (pp->ptr->used >= BLOCK_SIZE)
- pp->ptr = new block(pp->ptr);
- pp->ptr->v[(pp->ptr->used)++] = ntags;
- return 1;
-}
-
-static void write_hash_table()
-{
- const int minus_one = -1;
- int li = 0;
- for (int i = 0; i < hash_table_size; i++) {
- block *ptr = hash_table[i].ptr;
- if (!ptr)
- hash_table[i].count = -1;
- else {
- hash_table[i].count = li;
- block *rev = 0;
- while (ptr) {
- block *tem = ptr;
- ptr = ptr->next;
- tem->next = rev;
- rev = tem;
- }
- while (rev) {
- fwrite_or_die(rev->v, sizeof(int), rev->used, indxfp);
- li += rev->used;
- block *tem = rev;
- rev = rev->next;
- delete tem;
- }
- fwrite_or_die(&minus_one, sizeof(int), 1, indxfp);
- li += 1;
- }
- }
- if (sizeof(table_entry) == sizeof(int))
- fwrite_or_die(hash_table, sizeof(int), hash_table_size, indxfp);
- else {
- // write it out word by word
- for (int i = 0; i < hash_table_size; i++)
- fwrite_or_die(&hash_table[i].count, sizeof(int), 1, indxfp);
- }
- fwrite_or_die(filenames.contents(), 1, filenames.length(), indxfp);
- if (fseek(indxfp, 0, 0) < 0)
- fatal("error seeking on index file: %1", strerror(errno));
- index_header h;
- h.magic = INDEX_MAGIC;
- h.version = INDEX_VERSION;
- h.tags_size = ntags;
- h.lists_size = li;
- h.table_size = hash_table_size;
- h.strings_size = filenames.length();
- h.truncate = truncate_len;
- h.shortest = shortest_len;
- h.common = n_ignore_words;
- fwrite_or_die(&h, sizeof(h), 1, indxfp);
-}
-
-static void fwrite_or_die(const void *ptr, int size, int nitems, FILE *fp)
-{
- if (fwrite(ptr, size, nitems, fp) != (size_t)nitems)
- fatal("fwrite failed: %1", strerror(errno));
-}
-
-void fatal_error_exit()
-{
- cleanup();
- exit(3);
-}
-
-extern "C" {
-
-void cleanup()
-{
- if (temp_index_file)
- unlink(temp_index_file);
-}
-
-}
diff --git a/contrib/groff/src/utils/lkbib/lkbib.cc b/contrib/groff/src/utils/lkbib/lkbib.cc
deleted file mode 100644
index 42156ea..0000000
--- a/contrib/groff/src/utils/lkbib/lkbib.cc
+++ /dev/null
@@ -1,137 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1989-1992, 2000, 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "lib.h"
-
-#include
-#include
-#include
-
-#include "errarg.h"
-#include "error.h"
-
-#include "defs.h"
-#include "refid.h"
-#include "search.h"
-
-extern "C" const char *Version_string;
-
-static void usage(FILE *stream)
-{
- fprintf(stream, "usage: %s [-nv] [-p database] [-i XYZ] [-t N] keys ...\n",
- program_name);
-}
-
-int main(int argc, char **argv)
-{
- program_name = argv[0];
- static char stderr_buf[BUFSIZ];
- setbuf(stderr, stderr_buf);
- int search_default = 1;
- search_list list;
- 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, "nvVi:t:p:", long_options, NULL))
- != EOF)
- switch (opt) {
- case 'V':
- verify_flag = 1;
- break;
- case 'n':
- search_default = 0;
- break;
- case 'i':
- linear_ignore_fields = optarg;
- break;
- case 't':
- {
- char *ptr;
- long n = strtol(optarg, &ptr, 10);
- if (n == 0 && ptr == optarg) {
- error("bad integer `%1' in `t' option", optarg);
- break;
- }
- if (n < 1)
- n = 1;
- linear_truncate_len = int(n);
- break;
- }
- case 'v':
- {
- printf("GNU lkbib (groff) version %s\n", Version_string);
- exit(0);
- break;
- }
- case 'p':
- list.add_file(optarg);
- break;
- case CHAR_MAX + 1: // --help
- usage(stdout);
- exit(0);
- break;
- case '?':
- usage(stderr);
- exit(1);
- break;
- default:
- assert(0);
- }
- if (optind >= argc) {
- usage(stderr);
- exit(1);
- }
- char *filename = getenv("REFER");
- if (filename)
- list.add_file(filename);
- else if (search_default)
- list.add_file(DEFAULT_INDEX, 1);
- if (list.nfiles() == 0)
- fatal("no databases");
- int total_len = 0;
- int i;
- for (i = optind; i < argc; i++)
- total_len += strlen(argv[i]);
- total_len += argc - optind - 1 + 1; // for spaces and '\0'
- char *buffer = new char[total_len];
- char *ptr = buffer;
- for (i = optind; i < argc; i++) {
- if (i > optind)
- *ptr++ = ' ';
- strcpy(ptr, argv[i]);
- ptr = strchr(ptr, '\0');
- }
- search_list_iterator iter(&list, buffer);
- const char *start;
- int len;
- int count;
- for (count = 0; iter.next(&start, &len); count++) {
- if (fwrite(start, 1, len, stdout) != (size_t)len)
- fatal("write error on stdout: %1", strerror(errno));
- // Can happen for last reference in file.
- if (start[len - 1] != '\n')
- putchar('\n');
- putchar('\n');
- }
- return !count;
-}
diff --git a/contrib/groff/src/utils/lookbib/lookbib.cc b/contrib/groff/src/utils/lookbib/lookbib.cc
deleted file mode 100644
index 65e89bc..0000000
--- a/contrib/groff/src/utils/lookbib/lookbib.cc
+++ /dev/null
@@ -1,141 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1989-1992, 2000, 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "lib.h"
-
-#include
-#include
-#include
-
-#include "errarg.h"
-#include "error.h"
-#include "cset.h"
-
-#include "refid.h"
-#include "search.h"
-
-/* for isatty() */
-#include "posix.h"
-
-extern "C" {
- const char *Version_string;
-}
-
-static void usage(FILE *stream)
-{
- fprintf(stream, "usage: %s [-v] [-i XYZ] [-t N] database ...\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, "vVi:t:", long_options, NULL)) != EOF)
- switch (opt) {
- case 'V':
- verify_flag = 1;
- break;
- case 'i':
- linear_ignore_fields = optarg;
- break;
- case 't':
- {
- char *ptr;
- long n = strtol(optarg, &ptr, 10);
- if (n == 0 && ptr == optarg) {
- error("bad integer `%1' in `t' option", optarg);
- break;
- }
- if (n < 1)
- n = 1;
- linear_truncate_len = int(n);
- break;
- }
- case 'v':
- {
- printf("GNU lookbib (groff) version %s\n", Version_string);
- exit(0);
- break;
- }
- case CHAR_MAX + 1: // --help
- usage(stdout);
- exit(0);
- break;
- case '?':
- usage(stderr);
- exit(1);
- break;
- default:
- assert(0);
- }
- if (optind >= argc) {
- usage(stderr);
- exit(1);
- }
- search_list list;
- for (int i = optind; i < argc; i++)
- list.add_file(argv[i]);
- if (list.nfiles() == 0)
- fatal("no databases");
- char line[1024];
- int interactive = isatty(fileno(stdin));
- for (;;) {
- if (interactive) {
- fputs("> ", stderr);
- fflush(stderr);
- }
- if (!fgets(line, sizeof(line), stdin))
- break;
- char *ptr = line;
- while (csspace(*ptr))
- ptr++;
- if (*ptr == '\0')
- continue;
- search_list_iterator iter(&list, line);
- const char *start;
- int len;
- int count;
- for (count = 0; iter.next(&start, &len); count++) {
- if (fwrite(start, 1, len, stdout) != (size_t)len)
- fatal("write error on stdout: %1", strerror(errno));
- // Can happen for last reference in file.
- if (start[len - 1] != '\n')
- putchar('\n');
- putchar('\n');
- }
- fflush(stdout);
- if (interactive) {
- fprintf(stderr, "%d found\n", count);
- fflush(stderr);
- }
- }
- if (interactive)
- putc('\n', stderr);
- return 0;
-}
-
diff --git a/contrib/groff/src/utils/tfmtodit/tfmtodit.cc b/contrib/groff/src/utils/tfmtodit/tfmtodit.cc
deleted file mode 100644
index 9fbbe25..0000000
--- a/contrib/groff/src/utils/tfmtodit/tfmtodit.cc
+++ /dev/null
@@ -1,874 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1989-1992, 2000, 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-/* I have tried to incorporate the changes needed for TeX 3.0 tfm files,
-but I haven't tested them. */
-
-/* Groff requires more font metric information than TeX. The reason
-for this is that TeX has separate Math Italic fonts, whereas groff
-uses normal italic fonts for math. The two additional pieces of
-information required by groff correspond to the two arguments to the
-math_fit() macro in the Metafont programs for the CM fonts. In the
-case of a font for which math_fitting is false, these two arguments
-are normally ignored by Metafont. We need to get hold of these two
-parameters and put them in the groff font file.
-
-We do this by loading this definition after cmbase when creating cm.base.
-
-def ignore_math_fit(expr left_adjustment,right_adjustment) =
- special "adjustment";
- numspecial left_adjustment*16/designsize;
- numspecial right_adjustment*16/designsize;
- enddef;
-
-This puts the two arguments to the math_fit macro into the gf file.
-(They will appear in the gf file immediately before the character to
-which they apply.) We then create a gf file using this cm.base. Then
-we run tfmtodit and specify this gf file with the -g option.
-
-This need only be done for a font for which math_fitting is false;
-When it's true, the left_correction and subscript_correction should
-both be zero. */
-
-#include "lib.h"
-
-#include
-#include
-#include
-#include "errarg.h"
-#include "error.h"
-#include "assert.h"
-#include "cset.h"
-#include "nonposix.h"
-
-extern "C" const char *Version_string;
-
-/* Values in the tfm file should be multiplied by this. */
-
-#define MULTIPLIER 1
-
-struct char_info_word {
- unsigned char width_index;
- char height_index;
- char depth_index;
- char italic_index;
- char tag;
- unsigned char remainder;
-};
-
-struct lig_kern_command {
- unsigned char skip_byte;
- unsigned char next_char;
- unsigned char op_byte;
- unsigned char remainder;
-};
-
-class tfm {
- int bc;
- int ec;
- int nw;
- int nh;
- int nd;
- int ni;
- int nl;
- int nk;
- int np;
- int cs;
- int ds;
- char_info_word *char_info;
- int *width;
- int *height;
- int *depth;
- int *italic;
- lig_kern_command *lig_kern;
- int *kern;
- int *param;
-public:
- tfm();
- ~tfm();
- int load(const char *);
- int contains(int);
- int get_width(int);
- int get_height(int);
- int get_depth(int);
- int get_italic(int);
- int get_param(int, int *);
- int get_checksum();
- int get_design_size();
- int get_lig(unsigned char, unsigned char, unsigned char *);
- friend class kern_iterator;
-};
-
-class kern_iterator {
- tfm *t;
- int c;
- int i;
-public:
- kern_iterator(tfm *);
- int next(unsigned char *c1, unsigned char *c2, int *k);
-};
-
-
-kern_iterator::kern_iterator(tfm *p)
-: t(p), c(t->bc), i(-1)
-{
-}
-
-int kern_iterator::next(unsigned char *c1, unsigned char *c2, int *k)
-{
- for (; c <= t->ec; c++)
- if (t->char_info[c - t->bc].tag == 1) {
- if (i < 0) {
- i = t->char_info[c - t->bc].remainder;
- if (t->lig_kern[i].skip_byte > 128)
- i = (256*t->lig_kern[i].op_byte
- + t->lig_kern[i].remainder);
- }
- for (;;) {
- int skip = t->lig_kern[i].skip_byte;
- if (skip <= 128 && t->lig_kern[i].op_byte >= 128) {
- *c1 = c;
- *c2 = t->lig_kern[i].next_char;
- *k = t->kern[256*(t->lig_kern[i].op_byte - 128)
- + t->lig_kern[i].remainder];
- if (skip == 128) {
- c++;
- i = -1;
- }
- else
- i += skip + 1;
- return 1;
- }
- if (skip >= 128)
- break;
- i += skip + 1;
- }
- i = -1;
- }
- return 0;
-}
-
-tfm::tfm()
-: char_info(0), width(0), height(0), depth(0), italic(0), lig_kern(0),
- kern(0), param(0)
-{
-}
-
-int tfm::get_lig(unsigned char c1, unsigned char c2, unsigned char *cp)
-{
- if (contains(c1) && char_info[c1 - bc].tag == 1) {
- int i = char_info[c1 - bc].remainder;
- if (lig_kern[i].skip_byte > 128)
- i = 256*lig_kern[i].op_byte + lig_kern[i].remainder;
- for (;;) {
- int skip = lig_kern[i].skip_byte;
- if (skip > 128)
- break;
- // We are only interested in normal ligatures, for which
- // op_byte == 0.
- if (lig_kern[i].op_byte == 0
- && lig_kern[i].next_char == c2) {
- *cp = lig_kern[i].remainder;
- return 1;
- }
- if (skip == 128)
- break;
- i += skip + 1;
- }
- }
- return 0;
-}
-
-int tfm::contains(int i)
-{
- return i >= bc && i <= ec && char_info[i - bc].width_index != 0;
-}
-
-int tfm::get_width(int i)
-{
- return width[char_info[i - bc].width_index];
-}
-
-int tfm::get_height(int i)
-{
- return height[char_info[i - bc].height_index];
-}
-
-int tfm::get_depth(int i)
-{
- return depth[char_info[i - bc].depth_index];
-}
-
-int tfm::get_italic(int i)
-{
- return italic[char_info[i - bc].italic_index];
-}
-
-int tfm::get_param(int i, int *p)
-{
- if (i <= 0 || i > np)
- return 0;
- else {
- *p = param[i - 1];
- return 1;
- }
-}
-
-int tfm::get_checksum()
-{
- return cs;
-}
-
-int tfm::get_design_size()
-{
- return ds;
-}
-
-tfm::~tfm()
-{
- a_delete char_info;
- a_delete width;
- a_delete height;
- a_delete depth;
- a_delete italic;
- a_delete lig_kern;
- a_delete kern;
- a_delete param;
-}
-
-int read2(unsigned char *&s)
-{
- int n;
- n = *s++ << 8;
- n |= *s++;
- return n;
-}
-
-int read4(unsigned char *&s)
-{
- int n;
- n = *s++ << 24;
- n |= *s++ << 16;
- n |= *s++ << 8;
- n |= *s++;
- return n;
-}
-
-
-int tfm::load(const char *file)
-{
- errno = 0;
- FILE *fp = fopen(file, FOPEN_RB);
- if (!fp) {
- error("can't open `%1': %2", file, strerror(errno));
- return 0;
- }
- int c1 = getc(fp);
- int c2 = getc(fp);
- if (c1 == EOF || c2 == EOF) {
- fclose(fp);
- error("unexpected end of file on `%1'", file);
- return 0;
- }
- int lf = (c1 << 8) + c2;
- int toread = lf*4 - 2;
- unsigned char *buf = new unsigned char[toread];
- if (fread(buf, 1, toread, fp) != (size_t)toread) {
- if (feof(fp))
- error("unexpected end of file on `%1'", file);
- else
- error("error on file `%1'", file);
- a_delete buf;
- fclose(fp);
- return 0;
- }
- fclose(fp);
- if (lf < 6) {
- error("bad tfm file `%1': impossibly short", file);
- a_delete buf;
- return 0;
- }
- unsigned char *ptr = buf;
- int lh = read2(ptr);
- bc = read2(ptr);
- ec = read2(ptr);
- nw = read2(ptr);
- nh = read2(ptr);
- nd = read2(ptr);
- ni = read2(ptr);
- nl = read2(ptr);
- nk = read2(ptr);
- int ne = read2(ptr);
- np = read2(ptr);
- if (6 + lh + (ec - bc + 1) + nw + nh + nd + ni + nl + nk + ne + np != lf) {
- error("bad tfm file `%1': lengths do not sum", file);
- a_delete buf;
- return 0;
- }
- if (lh < 2) {
- error("bad tfm file `%1': header too short", file);
- a_delete buf;
- return 0;
- }
- char_info = new char_info_word[ec - bc + 1];
- width = new int[nw];
- height = new int[nh];
- depth = new int[nd];
- italic = new int[ni];
- lig_kern = new lig_kern_command[nl];
- kern = new int[nk];
- param = new int[np];
- int i;
- cs = read4(ptr);
- ds = read4(ptr);
- ptr += (lh-2)*4;
- for (i = 0; i < ec - bc + 1; i++) {
- char_info[i].width_index = *ptr++;
- unsigned char tem = *ptr++;
- char_info[i].depth_index = tem & 0xf;
- char_info[i].height_index = tem >> 4;
- tem = *ptr++;
- char_info[i].italic_index = tem >> 2;
- char_info[i].tag = tem & 3;
- char_info[i].remainder = *ptr++;
- }
- for (i = 0; i < nw; i++)
- width[i] = read4(ptr);
- for (i = 0; i < nh; i++)
- height[i] = read4(ptr);
- for (i = 0; i < nd; i++)
- depth[i] = read4(ptr);
- for (i = 0; i < ni; i++)
- italic[i] = read4(ptr);
- for (i = 0; i < nl; i++) {
- lig_kern[i].skip_byte = *ptr++;
- lig_kern[i].next_char = *ptr++;
- lig_kern[i].op_byte = *ptr++;
- lig_kern[i].remainder = *ptr++;
- }
- for (i = 0; i < nk; i++)
- kern[i] = read4(ptr);
- ptr += ne*4;
- for (i = 0; i < np; i++)
- param[i] = read4(ptr);
- assert(ptr == buf + lf*4 - 2);
- a_delete buf;
- return 1;
-}
-
-class gf {
- int left[256];
- int right[256];
- static int sread4(int *p, FILE *fp);
- static int uread3(int *p, FILE *fp);
- static int uread2(int *p, FILE *fp);
- static int skip(int n, FILE *fp);
-public:
- gf();
- int load(const char *file);
- int get_left_adjustment(int i) { return left[i]; }
- int get_right_adjustment(int i) { return right[i]; }
-};
-
-gf::gf()
-{
- for (int i = 0; i < 256; i++)
- left[i] = right[i] = 0;
-}
-
-int gf::load(const char *file)
-{
- enum {
- paint_0 = 0,
- paint1 = 64,
- boc = 67,
- boc1 = 68,
- eoc = 69,
- skip0 = 70,
- skip1 = 71,
- new_row_0 = 74,
- xxx1 = 239,
- yyy = 243,
- no_op = 244,
- pre = 247,
- post = 248
- };
- int got_an_adjustment = 0;
- int pending_adjustment = 0;
- int left_adj, right_adj;
- const int gf_id_byte = 131;
- errno = 0;
- FILE *fp = fopen(file, FOPEN_RB);
- if (!fp) {
- error("can't open `%1': %2", file, strerror(errno));
- return 0;
- }
- if (getc(fp) != pre || getc(fp) != gf_id_byte) {
- error("bad gf file");
- return 0;
- }
- int n = getc(fp);
- if (n == EOF)
- goto eof;
- if (!skip(n, fp))
- goto eof;
- for (;;) {
- int op = getc(fp);
- if (op == EOF)
- goto eof;
- if (op == post)
- break;
- if ((op >= paint_0 && op <= paint_0 + 63)
- || (op >= new_row_0 && op <= new_row_0 + 164))
- continue;
- switch (op) {
- case no_op:
- case eoc:
- case skip0:
- break;
- case paint1:
- case skip1:
- if (!skip(1, fp))
- goto eof;
- break;
- case paint1 + 1:
- case skip1 + 1:
- if (!skip(2, fp))
- goto eof;
- break;
- case paint1 + 2:
- case skip1 + 2:
- if (!skip(3, fp))
- goto eof;
- break;
- case boc:
- {
- int code;
- if (!sread4(&code, fp))
- goto eof;
- if (pending_adjustment) {
- pending_adjustment = 0;
- left[code & 0377] = left_adj;
- right[code & 0377] = right_adj;
- }
- if (!skip(20, fp))
- goto eof;
- break;
- }
- case boc1:
- {
- int code = getc(fp);
- if (code == EOF)
- goto eof;
- if (pending_adjustment) {
- pending_adjustment = 0;
- left[code] = left_adj;
- right[code] = right_adj;
- }
- if (!skip(4, fp))
- goto eof;
- break;
- }
- case xxx1:
- {
- int len = getc(fp);
- if (len == EOF)
- goto eof;
- char buf[256];
- if (fread(buf, 1, len, fp) != (size_t)len)
- goto eof;
- if (len == 10 /* strlen("adjustment") */
- && memcmp(buf, "adjustment", len) == 0) {
- int c = getc(fp);
- if (c != yyy) {
- if (c != EOF)
- ungetc(c, fp);
- break;
- }
- if (!sread4(&left_adj, fp))
- goto eof;
- c = getc(fp);
- if (c != yyy) {
- if (c != EOF)
- ungetc(c, fp);
- break;
- }
- if (!sread4(&right_adj, fp))
- goto eof;
- got_an_adjustment = 1;
- pending_adjustment = 1;
- }
- break;
- }
- case xxx1 + 1:
- if (!uread2(&n, fp) || !skip(n, fp))
- goto eof;
- break;
- case xxx1 + 2:
- if (!uread3(&n, fp) || !skip(n, fp))
- goto eof;
- break;
- case xxx1 + 3:
- if (!sread4(&n, fp) || !skip(n, fp))
- goto eof;
- break;
- case yyy:
- if (!skip(4, fp))
- goto eof;
- break;
- default:
- fatal("unrecognized opcode `%1'", op);
- break;
- }
- }
- if (!got_an_adjustment)
- warning("no adjustment specials found in gf file");
- return 1;
- eof:
- error("unexpected end of file");
- return 0;
-}
-
-int gf::sread4(int *p, FILE *fp)
-{
- *p = getc(fp);
- if (*p >= 128)
- *p -= 256;
- *p <<= 8;
- *p |= getc(fp);
- *p <<= 8;
- *p |= getc(fp);
- *p <<= 8;
- *p |= getc(fp);
- return !ferror(fp) && !feof(fp);
-}
-
-int gf::uread3(int *p, FILE *fp)
-{
- *p = getc(fp);
- *p <<= 8;
- *p |= getc(fp);
- *p <<= 8;
- *p |= getc(fp);
- return !ferror(fp) && !feof(fp);
-}
-
-int gf::uread2(int *p, FILE *fp)
-{
- *p = getc(fp);
- *p <<= 8;
- *p |= getc(fp);
- return !ferror(fp) && !feof(fp);
-}
-
-int gf::skip(int n, FILE *fp)
-{
- while (--n >= 0)
- if (getc(fp) == EOF)
- return 0;
- return 1;
-}
-
-
-struct char_list {
- char *ch;
- char_list *next;
- char_list(const char *, char_list * = 0);
-};
-
-char_list::char_list(const char *s, char_list *p) : ch(strsave(s)), next(p)
-{
-}
-
-
-int read_map(const char *file, char_list **table)
-{
- errno = 0;
- FILE *fp = fopen(file, "r");
- if (!fp) {
- error("can't open `%1': %2", file, strerror(errno));
- return 0;
- }
- for (int i = 0; i < 256; i++)
- table[i] = 0;
- char buf[512];
- int lineno = 0;
- while (fgets(buf, int(sizeof(buf)), fp)) {
- lineno++;
- char *ptr = buf;
- while (csspace(*ptr))
- ptr++;
- if (*ptr == '\0' || *ptr == '#')
- continue;
- ptr = strtok(ptr, " \n\t");
- if (!ptr)
- continue;
- int n;
- if (sscanf(ptr, "%d", &n) != 1) {
- error("%1:%2: bad map file", file, lineno);
- fclose(fp);
- return 0;
- }
- if (n < 0 || n > 255) {
- error("%1:%2: code out of range", file, lineno);
- fclose(fp);
- return 0;
- }
- ptr = strtok(0, " \n\t");
- if (!ptr) {
- error("%1:%2: missing names", file, lineno);
- fclose(fp);
- return 0;
- }
- for (; ptr; ptr = strtok(0, " \n\t"))
- table[n] = new char_list(ptr, table[n]);
- }
- fclose(fp);
- return 1;
-}
-
-
-/* Every character that can participate in a ligature appears in the
-lig_chars table. `ch' gives the full-name of the character, `name'
-gives the groff name of the character, `i' gives its index in
-the encoding, which is filled in later (-1 if it does not appear). */
-
-struct {
- const char *ch;
- int i;
-} lig_chars[] = {
- { "f", -1 },
- { "i", -1 },
- { "l", -1 },
- { "ff", -1 },
- { "fi", -1 },
- { "fl", -1 },
- { "Fi", -1 },
- { "Fl", -1 },
-};
-
-// Indices into lig_chars[].
-
-enum { CH_f, CH_i, CH_l, CH_ff, CH_fi, CH_fl, CH_ffi, CH_ffl };
-
-// Each possible ligature appears in this table.
-
-struct {
- unsigned char c1, c2, res;
- const char *ch;
-} lig_table[] = {
- { CH_f, CH_f, CH_ff, "ff" },
- { CH_f, CH_i, CH_fi, "fi" },
- { CH_f, CH_l, CH_fl, "fl" },
- { CH_ff, CH_i, CH_ffi, "ffi" },
- { CH_ff, CH_l, CH_ffl, "ffl" },
- };
-
-static void usage(FILE *stream);
-
-int main(int argc, char **argv)
-{
- program_name = argv[0];
- int special_flag = 0;
- int skewchar = -1;
- int opt;
- const char *gf_file = 0;
- 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, "svg:k:", long_options, NULL)) != EOF)
- switch (opt) {
- case 'g':
- gf_file = optarg;
- break;
- case 's':
- special_flag = 1;
- break;
- case 'k':
- {
- char *ptr;
- long n = strtol(optarg, &ptr, 0);
- if ((n == 0 && ptr == optarg)
- || *ptr != '\0'
- || n < 0
- || n > UCHAR_MAX)
- error("invalid skewchar");
- else
- skewchar = (int)n;
- break;
- }
- case 'v':
- {
- printf("GNU tfmtodit (groff) version %s\n", Version_string);
- exit(0);
- break;
- }
- case CHAR_MAX + 1: // --help
- usage(stdout);
- exit(0);
- break;
- case '?':
- usage(stderr);
- exit(1);
- break;
- case EOF:
- assert(0);
- }
- if (argc - optind != 3) {
- usage(stderr);
- exit(1);
- }
- gf g;
- if (gf_file) {
- if (!g.load(gf_file))
- return 1;
- }
- const char *tfm_file = argv[optind];
- const char *map_file = argv[optind + 1];
- const char *font_file = argv[optind + 2];
- tfm t;
- if (!t.load(tfm_file))
- return 1;
- char_list *table[256];
- if (!read_map(map_file, table))
- return 1;
- errno = 0;
- if (!freopen(font_file, "w", stdout)) {
- error("can't open `%1' for writing: %2", font_file, strerror(errno));
- return 1;
- }
- printf("name %s\n", font_file);
- if (special_flag)
- fputs("special\n", stdout);
- char *internal_name = strsave(argv[optind]);
- int len = strlen(internal_name);
- if (len > 4 && strcmp(internal_name + len - 4, ".tfm") == 0)
- internal_name[len - 4] = '\0';
- // DIR_SEPS[] are possible directory separator characters, see nonposix.h.
- // We want the rightmost separator of all possible ones.
- // Example: d:/foo\\bar.
- const char *s = strrchr(internal_name, DIR_SEPS[0]), *s1;
- const char *sep = &DIR_SEPS[1];
- while (*sep)
- {
- s1 = strrchr(internal_name, *sep);
- if (s1 && (!s || s1 > s))
- s = s1;
- sep++;
- }
- printf("internalname %s\n", s ? s + 1 : internal_name);
- int n;
- if (t.get_param(2, &n)) {
- if (n > 0)
- printf("spacewidth %d\n", n*MULTIPLIER);
- }
- if (t.get_param(1, &n) && n != 0)
- printf("slant %f\n", atan2(n/double(1<<20), 1.0)*180.0/PI);
- int xheight;
- if (!t.get_param(5, &xheight))
- xheight = 0;
- unsigned int i;
- // Print the list of ligatures.
- // First find the indices of each character that can participate in
- // a ligature.
- for (i = 0; i < 256; i++)
- for (unsigned int j = 0; j < sizeof(lig_chars)/sizeof(lig_chars[0]); j++)
- for (char_list *p = table[i]; p; p = p->next)
- if (strcmp(lig_chars[j].ch, p->ch) == 0)
- lig_chars[j].i = i;
- // For each possible ligature, if its participants all exist,
- // and it appears as a ligature in the tfm file, include in
- // the list of ligatures.
- int started = 0;
- for (i = 0; i < sizeof(lig_table)/sizeof(lig_table[0]); i++) {
- int i1 = lig_chars[lig_table[i].c1].i;
- int i2 = lig_chars[lig_table[i].c2].i;
- int r = lig_chars[lig_table[i].res].i;
- if (i1 >= 0 && i2 >= 0 && r >= 0) {
- unsigned char c;
- if (t.get_lig(i1, i2, &c) && c == r) {
- if (!started) {
- started = 1;
- fputs("ligatures", stdout);
- }
- printf(" %s", lig_table[i].ch);
- }
- }
- }
- if (started)
- fputs(" 0\n", stdout);
- printf("checksum %d\n", t.get_checksum());
- printf("designsize %d\n", t.get_design_size());
- // Now print out the kerning information.
- int had_kern = 0;
- kern_iterator iter(&t);
- unsigned char c1, c2;
- int k;
- while (iter.next(&c1, &c2, &k))
- if (c2 != skewchar) {
- k *= MULTIPLIER;
- char_list *q = table[c2];
- for (char_list *p1 = table[c1]; p1; p1 = p1->next)
- for (char_list *p2 = q; p2; p2 = p2->next) {
- if (!had_kern) {
- printf("kernpairs\n");
- had_kern = 1;
- }
- printf("%s %s %d\n", p1->ch, p2->ch, k);
- }
- }
- printf("charset\n");
- char_list unnamed("---");
- for (i = 0; i < 256; i++)
- if (t.contains(i)) {
- char_list *p = table[i] ? table[i] : &unnamed;
- int m[6];
- m[0] = t.get_width(i);
- m[1] = t.get_height(i);
- m[2] = t.get_depth(i);
- m[3] = t.get_italic(i);
- m[4] = g.get_left_adjustment(i);
- m[5] = g.get_right_adjustment(i);
- printf("%s\t%d", p->ch, m[0]*MULTIPLIER);
- int j;
- for (j = int(sizeof(m)/sizeof(m[0])) - 1; j > 0; j--)
- if (m[j] != 0)
- break;
- for (k = 1; k <= j; k++)
- printf(",%d", m[k]*MULTIPLIER);
- int type = 0;
- if (m[2] > 0)
- type = 1;
- if (m[1] > xheight)
- type += 2;
- printf("\t%d\t%04o\n", type, i);
- for (p = p->next; p; p = p->next)
- printf("%s\t\"\n", p->ch);
- }
- return 0;
-}
-
-static void usage(FILE *stream)
-{
- fprintf(stream, "usage: %s [-sv] [-g gf_file] [-k skewchar] tfm_file map_file font\n",
- program_name);
-}
diff --git a/contrib/groff/win32-diffs b/contrib/groff/win32-diffs
deleted file mode 100644
index d68b497..0000000
--- a/contrib/groff/win32-diffs
+++ /dev/null
@@ -1,2708 +0,0 @@
-diff -aruN groff-1.18/Makefile.msc groff-1.18.win32/Makefile.msc
---- groff-1.18/Makefile.msc Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/Makefile.msc Mon Jul 8 06:47:51 2002
-@@ -0,0 +1,36 @@
-+
-+
-+MAKECMD = $(MAKE) -nologo -f makefile.msc
-+
-+
-+all:
-+ cd src\libs\libdriver
-+ $(MAKECMD)
-+ cd ..\libgroff
-+ $(MAKECMD)
-+ cd ..\..\roff\troff
-+ $(MAKECMD)
-+ cd ..\..\preproc\eqn
-+ $(MAKECMD)
-+ cd ..\pic
-+ $(MAKECMD)
-+ cd ..\tbl
-+ $(MAKECMD)
-+ cd ..\..\devices\grolj4
-+ $(MAKECMD)
-+ cd ..\grotty
-+ $(MAKECMD)
-+ cd ..\grops
-+ $(MAKECMD)
-+ cd ..\grodvi
-+ $(MAKECMD)
-+ cd ..\..\..
-+ -del bin\*.orig
-+ copy src\devices\grodvi\grodvi.exe bin
-+ copy src\devices\grolj4\grolj4.exe bin
-+ copy src\devices\grops\grops.exe bin
-+ copy src\devices\grotty\grotty.exe bin
-+ copy src\preproc\eqn\eqn.exe bin
-+ copy src\preproc\pic\pic.exe bin
-+ copy src\preproc\tbl\tbl.exe bin
-+ copy src\roff\troff\troff.exe bin
-diff -aruN groff-1.18/bin/gs.cmd groff-1.18.win32/bin/gs.cmd
---- groff-1.18/bin/gs.cmd Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/bin/gs.cmd Mon Jul 8 06:47:51 2002
-@@ -0,0 +1,2 @@
-+@echo off
-+gswin32c -sDEVICE=ljet3 -sOutputFile=%1.jep -q -dNOPAUSE %1.ps 24 0 0076
-+ra "
-+fc "
-+? 24 0 0077
-+@ 24 0 0100
-+at "
-+A 24 0 0101
-+*A "
-+B 24 0 0102
-+*B "
-+C 24 0 0103
-+D 24 0 0104
-+E 24 0 0105
-+*E "
-+F 24 0 0106
-+G 24 0 0107
-+H 24 0 0110
-+*Y "
-+I 24 0 0111
-+*I "
-+J 24 0 0112
-+K 24 0 0113
-+*K "
-+L 24 0 0114
-+M 24 0 0115
-+*M "
-+N 24 0 0116
-+*N "
-+O 24 0 0117
-+ci "
-+*O "
-+P 24 0 0120
-+*R "
-+Q 24 0 0121
-+R 24 0 0122
-+S 24 0 0123
-+T 24 0 0124
-+*T "
-+U 24 0 0125
-+V 24 0 0126
-+W 24 0 0127
-+X 24 0 0130
-+*X "
-+Y 24 0 0131
-+*U "
-+Z 24 0 0132
-+*Z "
-+[ 24 0 0133
-+lB "
-+\ 24 0 0134
-+rs "
-+] 24 0 0135
-+rB "
-+a^ 24 0 0136
-+^ "
-+ha "
-+_ 24 0 0137
-+ru "
-+ul "
-+` 24 0 0140
-+oq "
-+ga "
-+a 24 0 0141
-+b 24 0 0142
-+c 24 0 0143
-+d 24 0 0144
-+e 24 0 0145
-+f 24 0 0146
-+g 24 0 0147
-+h 24 0 0150
-+i 24 0 0151
-+.i "
-+j 24 0 0152
-+k 24 0 0153
-+l 24 0 0154
-+m 24 0 0155
-+n 24 0 0156
-+o 24 0 0157
-+*o "
-+p 24 0 0160
-+q 24 0 0161
-+r 24 0 0162
-+s 24 0 0163
-+t 24 0 0164
-+u 24 0 0165
-+v 24 0 0166
-+w 24 0 0167
-+x 24 0 0170
-+mu "
-+tmu "
-+y 24 0 0171
-+z 24 0 0172
-+lC 24 0 0173
-+{ "
-+ba 24 0 0174
-+or "
-+bv "
-+br "
-+| "
-+lb "
-+lc "
-+lf "
-+lk "
-+lt "
-+rb "
-+rc "
-+rf "
-+rk "
-+rt "
-+rC 24 0 0175
-+} "
-+a~ 24 0 0176
-+~ "
-+ap "
-+ti "
-diff -aruN groff-1.18/font/devascii/BI groff-1.18.win32/font/devascii/BI
---- groff-1.18/font/devascii/BI Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/font/devascii/BI Fri Jul 5 16:06:31 2002
-@@ -0,0 +1,168 @@
-+name BI
-+internalname 3
-+spacewidth 24
-+charset
-+! 24 0 0041
-+" 24 0 0042
-+dq "
-+lq "
-+rq "
-+# 24 0 0043
-+sh "
-+$ 24 0 0044
-+Do "
-+% 24 0 0045
-+& 24 0 0046
-+' 24 0 0047
-+aa "
-+fm "
-+aq "
-+cq "
-+( 24 0 0050
-+) 24 0 0051
-+* 24 0 0052
-+** "
-++ 24 0 0053
-+pl "
-+, 24 0 0054
-+\- 24 0 0055
-+hy "
-+- "
-+mi "
-+en "
-+. 24 0 0056
-+/ 24 0 0057
-+sl "
-+f/ "
-+0 24 0 0060
-+1 24 0 0061
-+2 24 0 0062
-+3 24 0 0063
-+4 24 0 0064
-+5 24 0 0065
-+6 24 0 0066
-+7 24 0 0067
-+8 24 0 0070
-+9 24 0 0071
-+: 24 0 0072
-+; 24 0 0073
-+< 24 0 0074
-+la "
-+fo "
-+= 24 0 0075
-+eq "
-+> 24 0 0076
-+ra "
-+fc "
-+? 24 0 0077
-+@ 24 0 0100
-+at "
-+A 24 0 0101
-+*A "
-+B 24 0 0102
-+*B "
-+C 24 0 0103
-+D 24 0 0104
-+E 24 0 0105
-+*E "
-+F 24 0 0106
-+G 24 0 0107
-+H 24 0 0110
-+*Y "
-+I 24 0 0111
-+*I "
-+J 24 0 0112
-+K 24 0 0113
-+*K "
-+L 24 0 0114
-+M 24 0 0115
-+*M "
-+N 24 0 0116
-+*N "
-+O 24 0 0117
-+ci "
-+*O "
-+P 24 0 0120
-+*R "
-+Q 24 0 0121
-+R 24 0 0122
-+S 24 0 0123
-+T 24 0 0124
-+*T "
-+U 24 0 0125
-+V 24 0 0126
-+W 24 0 0127
-+X 24 0 0130
-+*X "
-+Y 24 0 0131
-+*U "
-+Z 24 0 0132
-+*Z "
-+[ 24 0 0133
-+lB "
-+\ 24 0 0134
-+rs "
-+] 24 0 0135
-+rB "
-+a^ 24 0 0136
-+^ "
-+ha "
-+_ 24 0 0137
-+ru "
-+ul "
-+` 24 0 0140
-+oq "
-+ga "
-+a 24 0 0141
-+b 24 0 0142
-+c 24 0 0143
-+d 24 0 0144
-+e 24 0 0145
-+f 24 0 0146
-+g 24 0 0147
-+h 24 0 0150
-+i 24 0 0151
-+.i "
-+j 24 0 0152
-+k 24 0 0153
-+l 24 0 0154
-+m 24 0 0155
-+n 24 0 0156
-+o 24 0 0157
-+*o "
-+p 24 0 0160
-+q 24 0 0161
-+r 24 0 0162
-+s 24 0 0163
-+t 24 0 0164
-+u 24 0 0165
-+v 24 0 0166
-+w 24 0 0167
-+x 24 0 0170
-+mu "
-+tmu "
-+y 24 0 0171
-+z 24 0 0172
-+lC 24 0 0173
-+{ "
-+ba 24 0 0174
-+or "
-+bv "
-+br "
-+| "
-+lb "
-+lc "
-+lf "
-+lk "
-+lt "
-+rb "
-+rc "
-+rf "
-+rk "
-+rt "
-+rC 24 0 0175
-+} "
-+a~ 24 0 0176
-+~ "
-+ap "
-+ti "
-diff -aruN groff-1.18/font/devascii/DESC groff-1.18.win32/font/devascii/DESC
---- groff-1.18/font/devascii/DESC Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/font/devascii/DESC Mon Jul 8 06:47:51 2002
-@@ -0,0 +1,8 @@
-+res 240
-+hor 24
-+vert 40
-+unitwidth 10
-+sizes 10 0
-+fonts 4 R I B BI
-+tcommand
-+postpro grotty
-diff -aruN groff-1.18/font/devascii/I groff-1.18.win32/font/devascii/I
---- groff-1.18/font/devascii/I Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/font/devascii/I Fri Jul 5 16:06:31 2002
-@@ -0,0 +1,168 @@
-+name I
-+internalname 1
-+spacewidth 24
-+charset
-+! 24 0 0041
-+" 24 0 0042
-+dq "
-+lq "
-+rq "
-+# 24 0 0043
-+sh "
-+$ 24 0 0044
-+Do "
-+% 24 0 0045
-+& 24 0 0046
-+' 24 0 0047
-+aa "
-+fm "
-+aq "
-+cq "
-+( 24 0 0050
-+) 24 0 0051
-+* 24 0 0052
-+** "
-++ 24 0 0053
-+pl "
-+, 24 0 0054
-+\- 24 0 0055
-+hy "
-+- "
-+mi "
-+en "
-+. 24 0 0056
-+/ 24 0 0057
-+sl "
-+f/ "
-+0 24 0 0060
-+1 24 0 0061
-+2 24 0 0062
-+3 24 0 0063
-+4 24 0 0064
-+5 24 0 0065
-+6 24 0 0066
-+7 24 0 0067
-+8 24 0 0070
-+9 24 0 0071
-+: 24 0 0072
-+; 24 0 0073
-+< 24 0 0074
-+la "
-+fo "
-+= 24 0 0075
-+eq "
-+> 24 0 0076
-+ra "
-+fc "
-+? 24 0 0077
-+@ 24 0 0100
-+at "
-+A 24 0 0101
-+*A "
-+B 24 0 0102
-+*B "
-+C 24 0 0103
-+D 24 0 0104
-+E 24 0 0105
-+*E "
-+F 24 0 0106
-+G 24 0 0107
-+H 24 0 0110
-+*Y "
-+I 24 0 0111
-+*I "
-+J 24 0 0112
-+K 24 0 0113
-+*K "
-+L 24 0 0114
-+M 24 0 0115
-+*M "
-+N 24 0 0116
-+*N "
-+O 24 0 0117
-+ci "
-+*O "
-+P 24 0 0120
-+*R "
-+Q 24 0 0121
-+R 24 0 0122
-+S 24 0 0123
-+T 24 0 0124
-+*T "
-+U 24 0 0125
-+V 24 0 0126
-+W 24 0 0127
-+X 24 0 0130
-+*X "
-+Y 24 0 0131
-+*U "
-+Z 24 0 0132
-+*Z "
-+[ 24 0 0133
-+lB "
-+\ 24 0 0134
-+rs "
-+] 24 0 0135
-+rB "
-+a^ 24 0 0136
-+^ "
-+ha "
-+_ 24 0 0137
-+ru "
-+ul "
-+` 24 0 0140
-+oq "
-+ga "
-+a 24 0 0141
-+b 24 0 0142
-+c 24 0 0143
-+d 24 0 0144
-+e 24 0 0145
-+f 24 0 0146
-+g 24 0 0147
-+h 24 0 0150
-+i 24 0 0151
-+.i "
-+j 24 0 0152
-+k 24 0 0153
-+l 24 0 0154
-+m 24 0 0155
-+n 24 0 0156
-+o 24 0 0157
-+*o "
-+p 24 0 0160
-+q 24 0 0161
-+r 24 0 0162
-+s 24 0 0163
-+t 24 0 0164
-+u 24 0 0165
-+v 24 0 0166
-+w 24 0 0167
-+x 24 0 0170
-+mu "
-+tmu "
-+y 24 0 0171
-+z 24 0 0172
-+lC 24 0 0173
-+{ "
-+ba 24 0 0174
-+or "
-+bv "
-+br "
-+| "
-+lb "
-+lc "
-+lf "
-+lk "
-+lt "
-+rb "
-+rc "
-+rf "
-+rk "
-+rt "
-+rC 24 0 0175
-+} "
-+a~ 24 0 0176
-+~ "
-+ap "
-+ti "
-diff -aruN groff-1.18/font/devascii/R groff-1.18.win32/font/devascii/R
---- groff-1.18/font/devascii/R Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/font/devascii/R Fri Jul 5 16:06:31 2002
-@@ -0,0 +1,167 @@
-+name R
-+spacewidth 24
-+charset
-+! 24 0 0041
-+" 24 0 0042
-+dq "
-+lq "
-+rq "
-+# 24 0 0043
-+sh "
-+$ 24 0 0044
-+Do "
-+% 24 0 0045
-+& 24 0 0046
-+' 24 0 0047
-+aa "
-+fm "
-+aq "
-+cq "
-+( 24 0 0050
-+) 24 0 0051
-+* 24 0 0052
-+** "
-++ 24 0 0053
-+pl "
-+, 24 0 0054
-+\- 24 0 0055
-+hy "
-+- "
-+mi "
-+en "
-+. 24 0 0056
-+/ 24 0 0057
-+sl "
-+f/ "
-+0 24 0 0060
-+1 24 0 0061
-+2 24 0 0062
-+3 24 0 0063
-+4 24 0 0064
-+5 24 0 0065
-+6 24 0 0066
-+7 24 0 0067
-+8 24 0 0070
-+9 24 0 0071
-+: 24 0 0072
-+; 24 0 0073
-+< 24 0 0074
-+la "
-+fo "
-+= 24 0 0075
-+eq "
-+> 24 0 0076
-+ra "
-+fc "
-+? 24 0 0077
-+@ 24 0 0100
-+at "
-+A 24 0 0101
-+*A "
-+B 24 0 0102
-+*B "
-+C 24 0 0103
-+D 24 0 0104
-+E 24 0 0105
-+*E "
-+F 24 0 0106
-+G 24 0 0107
-+H 24 0 0110
-+*Y "
-+I 24 0 0111
-+*I "
-+J 24 0 0112
-+K 24 0 0113
-+*K "
-+L 24 0 0114
-+M 24 0 0115
-+*M "
-+N 24 0 0116
-+*N "
-+O 24 0 0117
-+ci "
-+*O "
-+P 24 0 0120
-+*R "
-+Q 24 0 0121
-+R 24 0 0122
-+S 24 0 0123
-+T 24 0 0124
-+*T "
-+U 24 0 0125
-+V 24 0 0126
-+W 24 0 0127
-+X 24 0 0130
-+*X "
-+Y 24 0 0131
-+*U "
-+Z 24 0 0132
-+*Z "
-+[ 24 0 0133
-+lB "
-+\ 24 0 0134
-+rs "
-+] 24 0 0135
-+rB "
-+a^ 24 0 0136
-+^ "
-+ha "
-+_ 24 0 0137
-+ru "
-+ul "
-+` 24 0 0140
-+oq "
-+ga "
-+a 24 0 0141
-+b 24 0 0142
-+c 24 0 0143
-+d 24 0 0144
-+e 24 0 0145
-+f 24 0 0146
-+g 24 0 0147
-+h 24 0 0150
-+i 24 0 0151
-+.i "
-+j 24 0 0152
-+k 24 0 0153
-+l 24 0 0154
-+m 24 0 0155
-+n 24 0 0156
-+o 24 0 0157
-+*o "
-+p 24 0 0160
-+q 24 0 0161
-+r 24 0 0162
-+s 24 0 0163
-+t 24 0 0164
-+u 24 0 0165
-+v 24 0 0166
-+w 24 0 0167
-+x 24 0 0170
-+mu "
-+tmu "
-+y 24 0 0171
-+z 24 0 0172
-+lC 24 0 0173
-+{ "
-+ba 24 0 0174
-+or "
-+bv "
-+br "
-+| "
-+lb "
-+lc "
-+lf "
-+lk "
-+lt "
-+rb "
-+rc "
-+rf "
-+rk "
-+rt "
-+rC 24 0 0175
-+} "
-+a~ 24 0 0176
-+~ "
-+ap "
-+ti "
-diff -aruN groff-1.18/font/devdvi/DESC groff-1.18.win32/font/devdvi/DESC
---- groff-1.18/font/devdvi/DESC Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/font/devdvi/DESC Mon Jul 8 08:42:17 2002
-@@ -0,0 +1,11 @@
-+sizescale 100
-+unitwidth 131072
-+res 57816
-+hor 1
-+vert 1
-+sizes 500-1000000 0
-+styles R I B BI
-+family T
-+fonts 13 0 0 0 0 0 0 0 0 0 MI S EX CW
-+tcommand
-+postpro grodvi
-diff -aruN groff-1.18/font/devlatin1/B groff-1.18.win32/font/devlatin1/B
---- groff-1.18/font/devlatin1/B Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/font/devlatin1/B Fri Jul 5 16:06:31 2002
-@@ -0,0 +1,266 @@
-+name B
-+internalname 2
-+spacewidth 24
-+charset
-+! 24 0 0041
-+" 24 0 0042
-+dq "
-+lq "
-+rq "
-+# 24 0 0043
-+sh "
-+$ 24 0 0044
-+Do "
-+% 24 0 0045
-+& 24 0 0046
-+' 24 0 0047
-+fm "
-+aq "
-+cq "
-+( 24 0 0050
-+) 24 0 0051
-+* 24 0 0052
-+** "
-++ 24 0 0053
-+pl "
-+, 24 0 0054
-+\- 24 0 0055
-+mi "
-+- "
-+hy "
-+en "
-+. 24 0 0056
-+/ 24 0 0057
-+sl "
-+f/ "
-+0 24 0 0060
-+1 24 0 0061
-+2 24 0 0062
-+3 24 0 0063
-+4 24 0 0064
-+5 24 0 0065
-+6 24 0 0066
-+7 24 0 0067
-+8 24 0 0070
-+9 24 0 0071
-+: 24 0 0072
-+; 24 0 0073
-+< 24 0 0074
-+la "
-+fo "
-+= 24 0 0075
-+eq "
-+> 24 0 0076
-+ra "
-+fc "
-+? 24 0 0077
-+@ 24 0 0100
-+at "
-+A 24 0 0101
-+*A "
-+B 24 0 0102
-+*B "
-+C 24 0 0103
-+D 24 0 0104
-+E 24 0 0105
-+*E "
-+F 24 0 0106
-+G 24 0 0107
-+H 24 0 0110
-+*Y "
-+I 24 0 0111
-+*I "
-+J 24 0 0112
-+K 24 0 0113
-+*K "
-+L 24 0 0114
-+M 24 0 0115
-+*M "
-+N 24 0 0116
-+*N "
-+O 24 0 0117
-+ci "
-+*O "
-+P 24 0 0120
-+*R "
-+Q 24 0 0121
-+R 24 0 0122
-+S 24 0 0123
-+T 24 0 0124
-+*T "
-+U 24 0 0125
-+V 24 0 0126
-+W 24 0 0127
-+X 24 0 0130
-+*X "
-+Y 24 0 0131
-+*U "
-+Z 24 0 0132
-+*Z "
-+[ 24 0 0133
-+lB "
-+\ 24 0 0134
-+rs "
-+] 24 0 0135
-+rB "
-+a^ 24 0 0136
-+^ "
-+ha "
-+_ 24 0 0137
-+ru "
-+ul "
-+` 24 0 0140
-+oq "
-+ga "
-+a 24 0 0141
-+b 24 0 0142
-+c 24 0 0143
-+d 24 0 0144
-+e 24 0 0145
-+f 24 0 0146
-+g 24 0 0147
-+h 24 0 0150
-+i 24 0 0151
-+.i "
-+j 24 0 0152
-+k 24 0 0153
-+l 24 0 0154
-+m 24 0 0155
-+n 24 0 0156
-+o 24 0 0157
-+*o "
-+p 24 0 0160
-+q 24 0 0161
-+r 24 0 0162
-+s 24 0 0163
-+t 24 0 0164
-+u 24 0 0165
-+v 24 0 0166
-+w 24 0 0167
-+x 24 0 0170
-+y 24 0 0171
-+z 24 0 0172
-+lC 24 0 0173
-+{ "
-+ba 24 0 0174
-+or "
-+bv "
-+br "
-+| "
-+lb "
-+lc "
-+lf "
-+lk "
-+lt "
-+rb "
-+rc "
-+rf "
-+rk "
-+rt "
-+rC 24 0 0175
-+} "
-+a~ 24 0 0176
-+~ "
-+ap "
-+ti "
-+r! 24 0 0241
-+ct 24 0 0242
-+Po 24 0 0243
-+Cs 24 0 0244
-+Ye 24 0 0245
-+bb 24 0 0246
-+sc 24 0 0247
-+ad 24 0 0250
-+co 24 0 0251
-+Of 24 0 0252
-+Fo 24 0 0253
-+no 24 0 0254
-+shc 24 0 0255
-+rg 24 0 0256
-+a- 24 0 0257
-+de 24 0 0260
-+ao "
-++- 24 0 0261
-+t+- "
-+S2 24 0 0262
-+S3 24 0 0263
-+aa 24 0 0264
-+*m 24 0 0265
-+mc "
-+ps 24 0 0266
-+pc 24 0 0267
-+md "
-+ac 24 0 0270
-+S1 24 0 0271
-+Om 24 0 0272
-+Fc 24 0 0273
-+14 24 0 0274
-+12 24 0 0275
-+34 24 0 0276
-+r? 24 0 0277
-+`A 24 0 0300
-+'A 24 0 0301
-+^A 24 0 0302
-+~A 24 0 0303
-+:A 24 0 0304
-+oA 24 0 0305
-+AE 24 0 0306
-+,C 24 0 0307
-+`E 24 0 0310
-+'E 24 0 0311
-+^E 24 0 0312
-+:E 24 0 0313
-+`I 24 0 0314
-+'I 24 0 0315
-+^I 24 0 0316
-+:I 24 0 0317
-+-D 24 0 0320
-+~N 24 0 0321
-+`O 24 0 0322
-+'O 24 0 0323
-+^O 24 0 0324
-+~O 24 0 0325
-+:O 24 0 0326
-+mu 24 0 0327
-+tmu "
-+/O 24 0 0330
-+`U 24 0 0331
-+'U 24 0 0332
-+^U 24 0 0333
-+:U 24 0 0334
-+'Y 24 0 0335
-+TP 24 0 0336
-+ss 24 0 0337
-+`a 24 0 0340
-+'a 24 0 0341
-+^a 24 0 0342
-+~a 24 0 0343
-+:a 24 0 0344
-+oa 24 0 0345
-+ae 24 0 0346
-+,c 24 0 0347
-+`e 24 0 0350
-+'e 24 0 0351
-+^e 24 0 0352
-+:e 24 0 0353
-+`i 24 0 0354
-+'i 24 0 0355
-+^i 24 0 0356
-+:i 24 0 0357
-+Sd 24 0 0360
-+~n 24 0 0361
-+`o 24 0 0362
-+'o 24 0 0363
-+^o 24 0 0364
-+~o 24 0 0365
-+:o 24 0 0366
-+di 24 0 0367
-+tdi "
-+/o 24 0 0370
-+`u 24 0 0371
-+'u 24 0 0372
-+^u 24 0 0373
-+:u 24 0 0374
-+'y 24 0 0375
-+Tp 24 0 0376
-+:y 24 0 0377
-diff -aruN groff-1.18/font/devlatin1/BI groff-1.18.win32/font/devlatin1/BI
---- groff-1.18/font/devlatin1/BI Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/font/devlatin1/BI Fri Jul 5 16:06:31 2002
-@@ -0,0 +1,266 @@
-+name BI
-+internalname 3
-+spacewidth 24
-+charset
-+! 24 0 0041
-+" 24 0 0042
-+dq "
-+lq "
-+rq "
-+# 24 0 0043
-+sh "
-+$ 24 0 0044
-+Do "
-+% 24 0 0045
-+& 24 0 0046
-+' 24 0 0047
-+fm "
-+aq "
-+cq "
-+( 24 0 0050
-+) 24 0 0051
-+* 24 0 0052
-+** "
-++ 24 0 0053
-+pl "
-+, 24 0 0054
-+\- 24 0 0055
-+mi "
-+- "
-+hy "
-+en "
-+. 24 0 0056
-+/ 24 0 0057
-+sl "
-+f/ "
-+0 24 0 0060
-+1 24 0 0061
-+2 24 0 0062
-+3 24 0 0063
-+4 24 0 0064
-+5 24 0 0065
-+6 24 0 0066
-+7 24 0 0067
-+8 24 0 0070
-+9 24 0 0071
-+: 24 0 0072
-+; 24 0 0073
-+< 24 0 0074
-+la "
-+fo "
-+= 24 0 0075
-+eq "
-+> 24 0 0076
-+ra "
-+fc "
-+? 24 0 0077
-+@ 24 0 0100
-+at "
-+A 24 0 0101
-+*A "
-+B 24 0 0102
-+*B "
-+C 24 0 0103
-+D 24 0 0104
-+E 24 0 0105
-+*E "
-+F 24 0 0106
-+G 24 0 0107
-+H 24 0 0110
-+*Y "
-+I 24 0 0111
-+*I "
-+J 24 0 0112
-+K 24 0 0113
-+*K "
-+L 24 0 0114
-+M 24 0 0115
-+*M "
-+N 24 0 0116
-+*N "
-+O 24 0 0117
-+ci "
-+*O "
-+P 24 0 0120
-+*R "
-+Q 24 0 0121
-+R 24 0 0122
-+S 24 0 0123
-+T 24 0 0124
-+*T "
-+U 24 0 0125
-+V 24 0 0126
-+W 24 0 0127
-+X 24 0 0130
-+*X "
-+Y 24 0 0131
-+*U "
-+Z 24 0 0132
-+*Z "
-+[ 24 0 0133
-+lB "
-+\ 24 0 0134
-+rs "
-+] 24 0 0135
-+rB "
-+a^ 24 0 0136
-+^ "
-+ha "
-+_ 24 0 0137
-+ru "
-+ul "
-+` 24 0 0140
-+oq "
-+ga "
-+a 24 0 0141
-+b 24 0 0142
-+c 24 0 0143
-+d 24 0 0144
-+e 24 0 0145
-+f 24 0 0146
-+g 24 0 0147
-+h 24 0 0150
-+i 24 0 0151
-+.i "
-+j 24 0 0152
-+k 24 0 0153
-+l 24 0 0154
-+m 24 0 0155
-+n 24 0 0156
-+o 24 0 0157
-+*o "
-+p 24 0 0160
-+q 24 0 0161
-+r 24 0 0162
-+s 24 0 0163
-+t 24 0 0164
-+u 24 0 0165
-+v 24 0 0166
-+w 24 0 0167
-+x 24 0 0170
-+y 24 0 0171
-+z 24 0 0172
-+lC 24 0 0173
-+{ "
-+ba 24 0 0174
-+or "
-+bv "
-+br "
-+| "
-+lb "
-+lc "
-+lf "
-+lk "
-+lt "
-+rb "
-+rc "
-+rf "
-+rk "
-+rt "
-+rC 24 0 0175
-+} "
-+a~ 24 0 0176
-+~ "
-+ap "
-+ti "
-+r! 24 0 0241
-+ct 24 0 0242
-+Po 24 0 0243
-+Cs 24 0 0244
-+Ye 24 0 0245
-+bb 24 0 0246
-+sc 24 0 0247
-+ad 24 0 0250
-+co 24 0 0251
-+Of 24 0 0252
-+Fo 24 0 0253
-+no 24 0 0254
-+shc 24 0 0255
-+rg 24 0 0256
-+a- 24 0 0257
-+de 24 0 0260
-+ao "
-++- 24 0 0261
-+t+- "
-+S2 24 0 0262
-+S3 24 0 0263
-+aa 24 0 0264
-+*m 24 0 0265
-+mc "
-+ps 24 0 0266
-+pc 24 0 0267
-+md "
-+ac 24 0 0270
-+S1 24 0 0271
-+Om 24 0 0272
-+Fc 24 0 0273
-+14 24 0 0274
-+12 24 0 0275
-+34 24 0 0276
-+r? 24 0 0277
-+`A 24 0 0300
-+'A 24 0 0301
-+^A 24 0 0302
-+~A 24 0 0303
-+:A 24 0 0304
-+oA 24 0 0305
-+AE 24 0 0306
-+,C 24 0 0307
-+`E 24 0 0310
-+'E 24 0 0311
-+^E 24 0 0312
-+:E 24 0 0313
-+`I 24 0 0314
-+'I 24 0 0315
-+^I 24 0 0316
-+:I 24 0 0317
-+-D 24 0 0320
-+~N 24 0 0321
-+`O 24 0 0322
-+'O 24 0 0323
-+^O 24 0 0324
-+~O 24 0 0325
-+:O 24 0 0326
-+mu 24 0 0327
-+tmu "
-+/O 24 0 0330
-+`U 24 0 0331
-+'U 24 0 0332
-+^U 24 0 0333
-+:U 24 0 0334
-+'Y 24 0 0335
-+TP 24 0 0336
-+ss 24 0 0337
-+`a 24 0 0340
-+'a 24 0 0341
-+^a 24 0 0342
-+~a 24 0 0343
-+:a 24 0 0344
-+oa 24 0 0345
-+ae 24 0 0346
-+,c 24 0 0347
-+`e 24 0 0350
-+'e 24 0 0351
-+^e 24 0 0352
-+:e 24 0 0353
-+`i 24 0 0354
-+'i 24 0 0355
-+^i 24 0 0356
-+:i 24 0 0357
-+Sd 24 0 0360
-+~n 24 0 0361
-+`o 24 0 0362
-+'o 24 0 0363
-+^o 24 0 0364
-+~o 24 0 0365
-+:o 24 0 0366
-+di 24 0 0367
-+tdi "
-+/o 24 0 0370
-+`u 24 0 0371
-+'u 24 0 0372
-+^u 24 0 0373
-+:u 24 0 0374
-+'y 24 0 0375
-+Tp 24 0 0376
-+:y 24 0 0377
-diff -aruN groff-1.18/font/devlatin1/DESC groff-1.18.win32/font/devlatin1/DESC
---- groff-1.18/font/devlatin1/DESC Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/font/devlatin1/DESC Mon Jul 8 06:47:51 2002
-@@ -0,0 +1,8 @@
-+res 240
-+hor 24
-+vert 40
-+unitwidth 10
-+sizes 10 0
-+fonts 4 R I B BI
-+tcommand
-+postpro grotty
-diff -aruN groff-1.18/font/devlatin1/I groff-1.18.win32/font/devlatin1/I
---- groff-1.18/font/devlatin1/I Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/font/devlatin1/I Fri Jul 5 16:06:31 2002
-@@ -0,0 +1,266 @@
-+name I
-+internalname 1
-+spacewidth 24
-+charset
-+! 24 0 0041
-+" 24 0 0042
-+dq "
-+lq "
-+rq "
-+# 24 0 0043
-+sh "
-+$ 24 0 0044
-+Do "
-+% 24 0 0045
-+& 24 0 0046
-+' 24 0 0047
-+fm "
-+aq "
-+cq "
-+( 24 0 0050
-+) 24 0 0051
-+* 24 0 0052
-+** "
-++ 24 0 0053
-+pl "
-+, 24 0 0054
-+\- 24 0 0055
-+mi "
-+- "
-+hy "
-+en "
-+. 24 0 0056
-+/ 24 0 0057
-+sl "
-+f/ "
-+0 24 0 0060
-+1 24 0 0061
-+2 24 0 0062
-+3 24 0 0063
-+4 24 0 0064
-+5 24 0 0065
-+6 24 0 0066
-+7 24 0 0067
-+8 24 0 0070
-+9 24 0 0071
-+: 24 0 0072
-+; 24 0 0073
-+< 24 0 0074
-+la "
-+fo "
-+= 24 0 0075
-+eq "
-+> 24 0 0076
-+ra "
-+fc "
-+? 24 0 0077
-+@ 24 0 0100
-+at "
-+A 24 0 0101
-+*A "
-+B 24 0 0102
-+*B "
-+C 24 0 0103
-+D 24 0 0104
-+E 24 0 0105
-+*E "
-+F 24 0 0106
-+G 24 0 0107
-+H 24 0 0110
-+*Y "
-+I 24 0 0111
-+*I "
-+J 24 0 0112
-+K 24 0 0113
-+*K "
-+L 24 0 0114
-+M 24 0 0115
-+*M "
-+N 24 0 0116
-+*N "
-+O 24 0 0117
-+ci "
-+*O "
-+P 24 0 0120
-+*R "
-+Q 24 0 0121
-+R 24 0 0122
-+S 24 0 0123
-+T 24 0 0124
-+*T "
-+U 24 0 0125
-+V 24 0 0126
-+W 24 0 0127
-+X 24 0 0130
-+*X "
-+Y 24 0 0131
-+*U "
-+Z 24 0 0132
-+*Z "
-+[ 24 0 0133
-+lB "
-+\ 24 0 0134
-+rs "
-+] 24 0 0135
-+rB "
-+a^ 24 0 0136
-+^ "
-+ha "
-+_ 24 0 0137
-+ru "
-+ul "
-+` 24 0 0140
-+oq "
-+ga "
-+a 24 0 0141
-+b 24 0 0142
-+c 24 0 0143
-+d 24 0 0144
-+e 24 0 0145
-+f 24 0 0146
-+g 24 0 0147
-+h 24 0 0150
-+i 24 0 0151
-+.i "
-+j 24 0 0152
-+k 24 0 0153
-+l 24 0 0154
-+m 24 0 0155
-+n 24 0 0156
-+o 24 0 0157
-+*o "
-+p 24 0 0160
-+q 24 0 0161
-+r 24 0 0162
-+s 24 0 0163
-+t 24 0 0164
-+u 24 0 0165
-+v 24 0 0166
-+w 24 0 0167
-+x 24 0 0170
-+y 24 0 0171
-+z 24 0 0172
-+lC 24 0 0173
-+{ "
-+ba 24 0 0174
-+or "
-+bv "
-+br "
-+| "
-+lb "
-+lc "
-+lf "
-+lk "
-+lt "
-+rb "
-+rc "
-+rf "
-+rk "
-+rt "
-+rC 24 0 0175
-+} "
-+a~ 24 0 0176
-+~ "
-+ap "
-+ti "
-+r! 24 0 0241
-+ct 24 0 0242
-+Po 24 0 0243
-+Cs 24 0 0244
-+Ye 24 0 0245
-+bb 24 0 0246
-+sc 24 0 0247
-+ad 24 0 0250
-+co 24 0 0251
-+Of 24 0 0252
-+Fo 24 0 0253
-+no 24 0 0254
-+shc 24 0 0255
-+rg 24 0 0256
-+a- 24 0 0257
-+de 24 0 0260
-+ao "
-++- 24 0 0261
-+t+- "
-+S2 24 0 0262
-+S3 24 0 0263
-+aa 24 0 0264
-+*m 24 0 0265
-+mc "
-+ps 24 0 0266
-+pc 24 0 0267
-+md "
-+ac 24 0 0270
-+S1 24 0 0271
-+Om 24 0 0272
-+Fc 24 0 0273
-+14 24 0 0274
-+12 24 0 0275
-+34 24 0 0276
-+r? 24 0 0277
-+`A 24 0 0300
-+'A 24 0 0301
-+^A 24 0 0302
-+~A 24 0 0303
-+:A 24 0 0304
-+oA 24 0 0305
-+AE 24 0 0306
-+,C 24 0 0307
-+`E 24 0 0310
-+'E 24 0 0311
-+^E 24 0 0312
-+:E 24 0 0313
-+`I 24 0 0314
-+'I 24 0 0315
-+^I 24 0 0316
-+:I 24 0 0317
-+-D 24 0 0320
-+~N 24 0 0321
-+`O 24 0 0322
-+'O 24 0 0323
-+^O 24 0 0324
-+~O 24 0 0325
-+:O 24 0 0326
-+mu 24 0 0327
-+tmu "
-+/O 24 0 0330
-+`U 24 0 0331
-+'U 24 0 0332
-+^U 24 0 0333
-+:U 24 0 0334
-+'Y 24 0 0335
-+TP 24 0 0336
-+ss 24 0 0337
-+`a 24 0 0340
-+'a 24 0 0341
-+^a 24 0 0342
-+~a 24 0 0343
-+:a 24 0 0344
-+oa 24 0 0345
-+ae 24 0 0346
-+,c 24 0 0347
-+`e 24 0 0350
-+'e 24 0 0351
-+^e 24 0 0352
-+:e 24 0 0353
-+`i 24 0 0354
-+'i 24 0 0355
-+^i 24 0 0356
-+:i 24 0 0357
-+Sd 24 0 0360
-+~n 24 0 0361
-+`o 24 0 0362
-+'o 24 0 0363
-+^o 24 0 0364
-+~o 24 0 0365
-+:o 24 0 0366
-+di 24 0 0367
-+tdi "
-+/o 24 0 0370
-+`u 24 0 0371
-+'u 24 0 0372
-+^u 24 0 0373
-+:u 24 0 0374
-+'y 24 0 0375
-+Tp 24 0 0376
-+:y 24 0 0377
-diff -aruN groff-1.18/font/devlatin1/R groff-1.18.win32/font/devlatin1/R
---- groff-1.18/font/devlatin1/R Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/font/devlatin1/R Fri Jul 5 16:06:31 2002
-@@ -0,0 +1,265 @@
-+name R
-+spacewidth 24
-+charset
-+! 24 0 0041
-+" 24 0 0042
-+dq "
-+lq "
-+rq "
-+# 24 0 0043
-+sh "
-+$ 24 0 0044
-+Do "
-+% 24 0 0045
-+& 24 0 0046
-+' 24 0 0047
-+fm "
-+aq "
-+cq "
-+( 24 0 0050
-+) 24 0 0051
-+* 24 0 0052
-+** "
-++ 24 0 0053
-+pl "
-+, 24 0 0054
-+\- 24 0 0055
-+mi "
-+- "
-+hy "
-+en "
-+. 24 0 0056
-+/ 24 0 0057
-+sl "
-+f/ "
-+0 24 0 0060
-+1 24 0 0061
-+2 24 0 0062
-+3 24 0 0063
-+4 24 0 0064
-+5 24 0 0065
-+6 24 0 0066
-+7 24 0 0067
-+8 24 0 0070
-+9 24 0 0071
-+: 24 0 0072
-+; 24 0 0073
-+< 24 0 0074
-+la "
-+fo "
-+= 24 0 0075
-+eq "
-+> 24 0 0076
-+ra "
-+fc "
-+? 24 0 0077
-+@ 24 0 0100
-+at "
-+A 24 0 0101
-+*A "
-+B 24 0 0102
-+*B "
-+C 24 0 0103
-+D 24 0 0104
-+E 24 0 0105
-+*E "
-+F 24 0 0106
-+G 24 0 0107
-+H 24 0 0110
-+*Y "
-+I 24 0 0111
-+*I "
-+J 24 0 0112
-+K 24 0 0113
-+*K "
-+L 24 0 0114
-+M 24 0 0115
-+*M "
-+N 24 0 0116
-+*N "
-+O 24 0 0117
-+ci "
-+*O "
-+P 24 0 0120
-+*R "
-+Q 24 0 0121
-+R 24 0 0122
-+S 24 0 0123
-+T 24 0 0124
-+*T "
-+U 24 0 0125
-+V 24 0 0126
-+W 24 0 0127
-+X 24 0 0130
-+*X "
-+Y 24 0 0131
-+*U "
-+Z 24 0 0132
-+*Z "
-+[ 24 0 0133
-+lB "
-+\ 24 0 0134
-+rs "
-+] 24 0 0135
-+rB "
-+a^ 24 0 0136
-+^ "
-+ha "
-+_ 24 0 0137
-+ru "
-+ul "
-+` 24 0 0140
-+oq "
-+ga "
-+a 24 0 0141
-+b 24 0 0142
-+c 24 0 0143
-+d 24 0 0144
-+e 24 0 0145
-+f 24 0 0146
-+g 24 0 0147
-+h 24 0 0150
-+i 24 0 0151
-+.i "
-+j 24 0 0152
-+k 24 0 0153
-+l 24 0 0154
-+m 24 0 0155
-+n 24 0 0156
-+o 24 0 0157
-+*o "
-+p 24 0 0160
-+q 24 0 0161
-+r 24 0 0162
-+s 24 0 0163
-+t 24 0 0164
-+u 24 0 0165
-+v 24 0 0166
-+w 24 0 0167
-+x 24 0 0170
-+y 24 0 0171
-+z 24 0 0172
-+lC 24 0 0173
-+{ "
-+ba 24 0 0174
-+or "
-+bv "
-+br "
-+| "
-+lb "
-+lc "
-+lf "
-+lk "
-+lt "
-+rb "
-+rc "
-+rf "
-+rk "
-+rt "
-+rC 24 0 0175
-+} "
-+a~ 24 0 0176
-+~ "
-+ap "
-+ti "
-+r! 24 0 0241
-+ct 24 0 0242
-+Po 24 0 0243
-+Cs 24 0 0244
-+Ye 24 0 0245
-+bb 24 0 0246
-+sc 24 0 0247
-+ad 24 0 0250
-+co 24 0 0251
-+Of 24 0 0252
-+Fo 24 0 0253
-+no 24 0 0254
-+shc 24 0 0255
-+rg 24 0 0256
-+a- 24 0 0257
-+de 24 0 0260
-+ao "
-++- 24 0 0261
-+t+- "
-+S2 24 0 0262
-+S3 24 0 0263
-+aa 24 0 0264
-+*m 24 0 0265
-+mc "
-+ps 24 0 0266
-+pc 24 0 0267
-+md "
-+ac 24 0 0270
-+S1 24 0 0271
-+Om 24 0 0272
-+Fc 24 0 0273
-+14 24 0 0274
-+12 24 0 0275
-+34 24 0 0276
-+r? 24 0 0277
-+`A 24 0 0300
-+'A 24 0 0301
-+^A 24 0 0302
-+~A 24 0 0303
-+:A 24 0 0304
-+oA 24 0 0305
-+AE 24 0 0306
-+,C 24 0 0307
-+`E 24 0 0310
-+'E 24 0 0311
-+^E 24 0 0312
-+:E 24 0 0313
-+`I 24 0 0314
-+'I 24 0 0315
-+^I 24 0 0316
-+:I 24 0 0317
-+-D 24 0 0320
-+~N 24 0 0321
-+`O 24 0 0322
-+'O 24 0 0323
-+^O 24 0 0324
-+~O 24 0 0325
-+:O 24 0 0326
-+mu 24 0 0327
-+tmu "
-+/O 24 0 0330
-+`U 24 0 0331
-+'U 24 0 0332
-+^U 24 0 0333
-+:U 24 0 0334
-+'Y 24 0 0335
-+TP 24 0 0336
-+ss 24 0 0337
-+`a 24 0 0340
-+'a 24 0 0341
-+^a 24 0 0342
-+~a 24 0 0343
-+:a 24 0 0344
-+oa 24 0 0345
-+ae 24 0 0346
-+,c 24 0 0347
-+`e 24 0 0350
-+'e 24 0 0351
-+^e 24 0 0352
-+:e 24 0 0353
-+`i 24 0 0354
-+'i 24 0 0355
-+^i 24 0 0356
-+:i 24 0 0357
-+Sd 24 0 0360
-+~n 24 0 0361
-+`o 24 0 0362
-+'o 24 0 0363
-+^o 24 0 0364
-+~o 24 0 0365
-+:o 24 0 0366
-+di 24 0 0367
-+tdi "
-+/o 24 0 0370
-+`u 24 0 0371
-+'u 24 0 0372
-+^u 24 0 0373
-+:u 24 0 0374
-+'y 24 0 0375
-+Tp 24 0 0376
-+:y 24 0 0377
-diff -aruN groff-1.18/font/devlj4/DESC groff-1.18.win32/font/devlj4/DESC
---- groff-1.18/font/devlj4/DESC Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/font/devlj4/DESC Mon Jul 8 06:47:51 2002
-@@ -0,0 +1,12 @@
-+res 600
-+unitwidth 12700
-+hor 1
-+vert 1
-+sizescale 4
-+sizes 1-3999 0
-+styles R I B BI
-+fonts 6 0 0 0 0 0 S
-+family T
-+tcommand
-+postpro grolj4
-+papersize letter
-diff -aruN groff-1.18/font/devps/DESC groff-1.18.win32/font/devps/DESC
---- groff-1.18/font/devps/DESC Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/font/devps/DESC Mon Jul 8 06:52:35 2002
-@@ -0,0 +1,13 @@
-+res 72000
-+hor 1
-+vert 1
-+sizescale 1000
-+unitwidth 1000
-+sizes 1000-10000000 0
-+styles R I B BI
-+family T
-+fonts 9 0 0 0 0 0 SS S ZD ZDR
-+tcommand
-+postpro grops
-+broken 7
-+papersize letter
-diff -aruN groff-1.18/font/devps/prologue groff-1.18.win32/font/devps/prologue
---- groff-1.18/font/devps/prologue Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/font/devps/prologue Fri Jul 5 16:06:29 2002
-@@ -0,0 +1,164 @@
-+%!PS-Adobe-3.0 Resource-ProcSet
-+/setpacking where{
-+pop
-+currentpacking
-+true setpacking
-+}if
-+/grops 120 dict dup begin
-+/SC 32 def
-+/A/show load def
-+/B{0 SC 3 -1 roll widthshow}bind def
-+/C{0 exch ashow}bind def
-+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
-+/E{0 rmoveto show}bind def
-+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
-+/G{0 rmoveto 0 exch ashow}bind def
-+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
-+/I{0 exch rmoveto show}bind def
-+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
-+/K{0 exch rmoveto 0 exch ashow}bind def
-+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
-+/M{rmoveto show}bind def
-+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
-+/O{rmoveto 0 exch ashow}bind def
-+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
-+/Q{moveto show}bind def
-+/R{moveto 0 SC 3 -1 roll widthshow}bind def
-+/S{moveto 0 exch ashow}bind def
-+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
-+/SF{
-+findfont exch
-+[exch dup 0 exch 0 exch neg 0 0]makefont
-+dup setfont
-+[exch/setfont cvx]cvx bind def
-+}bind def
-+/MF{
-+findfont
-+[5 2 roll
-+0 3 1 roll
-+neg 0 0]makefont
-+dup setfont
-+[exch/setfont cvx]cvx bind def
-+}bind def
-+/level0 0 def
-+/RES 0 def
-+/PL 0 def
-+/LS 0 def
-+/MANUAL{
-+statusdict begin/manualfeed true store end
-+}bind def
-+/PLG{
-+gsave newpath clippath pathbbox grestore
-+exch pop add exch pop
-+}bind def
-+/BP{
-+/level0 save def
-+1 setlinecap
-+1 setlinejoin
-+72 RES div dup scale
-+LS{
-+90 rotate
-+}{
-+0 PL translate
-+}ifelse
-+1 -1 scale
-+}bind def
-+/EP{
-+level0 restore
-+showpage
-+}bind def
-+/DA{
-+newpath arcn stroke
-+}bind def
-+/SN{
-+transform
-+.25 sub exch .25 sub exch
-+round .25 add exch round .25 add exch
-+itransform
-+}bind def
-+/DL{
-+SN
-+moveto
-+SN
-+lineto stroke
-+}bind def
-+/DC{
-+newpath 0 360 arc closepath
-+}bind def
-+/TM matrix def
-+/DE{
-+TM currentmatrix pop
-+translate scale newpath 0 0 .5 0 360 arc closepath
-+TM setmatrix
-+}bind def
-+/RC/rcurveto load def
-+/RL/rlineto load def
-+/ST/stroke load def
-+/MT/moveto load def
-+/CL/closepath load def
-+/Fr{
-+setrgbcolor fill
-+}bind def
-+/Fk{
-+setcmykcolor fill
-+}bind def
-+/Fg{
-+setgray fill
-+}bind def
-+/FL/fill load def
-+/LW/setlinewidth load def
-+/Cr/setrgbcolor load def
-+/Ck/setcmykcolor load def
-+/Cg/setgray load def
-+/RE{
-+findfont
-+dup maxlength 1 index/FontName known not{1 add}if dict begin
-+{
-+1 index/FID ne{def}{pop pop}ifelse
-+}forall
-+/Encoding exch def
-+dup/FontName exch def
-+currentdict end definefont pop
-+}bind def
-+/DEFS 0 def
-+/EBEGIN{
-+moveto
-+DEFS begin
-+}bind def
-+/EEND/end load def
-+/CNT 0 def
-+/level1 0 def
-+/PBEGIN{
-+/level1 save def
-+translate
-+div 3 1 roll div exch scale
-+neg exch neg exch translate
-+0 setgray
-+0 setlinecap
-+1 setlinewidth
-+0 setlinejoin
-+10 setmiterlimit
-+[]0 setdash
-+/setstrokeadjust where{
-+pop
-+false setstrokeadjust
-+}if
-+/setoverprint where{
-+pop
-+false setoverprint
-+}if
-+newpath
-+/CNT countdictstack def
-+userdict begin
-+/showpage{}def
-+}bind def
-+/PEND{
-+clear
-+countdictstack CNT sub{end}repeat
-+level1 restore
-+}bind def
-+end def
-+/setpacking where{
-+pop
-+setpacking
-+}if
-diff -aruN groff-1.18/font/devps/symbolsl.pfa groff-1.18.win32/font/devps/symbolsl.pfa
---- groff-1.18/font/devps/symbolsl.pfa Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/font/devps/symbolsl.pfa Mon Jul 8 06:47:51 2002
-@@ -0,0 +1,29 @@
-+%!PS-Adobe-3.0 Resource-Font
-+%%DocumentNeededResources: font Symbol
-+/MakeTransformedFont{
-+findfont dup maxlength dict begin
-+{
-+exch dup dup/FID ne exch/UniqueID ne and{
-+exch def
-+}{
-+pop pop
-+}ifelse
-+}forall
-+/FontBBox
-+currentdict/FontBBox get
-+4 array copy def
-+FontBBox aload pop
-+4 index transform 4 2 roll
-+4 index transform 4 2 roll
-+FontBBox astore pop
-+FontMatrix exch matrix concatmatrix
-+/FontMatrix exch def
-+dup/FontName exch def
-+currentdict end
-+definefont pop
-+}bind def
-+%%IncludeResource: font Symbol
-+/Symbol-Slanted
-+[.89 0.0 15.5 dup sin exch cos div .89 0.0 0.0]
-+/Symbol
-+MakeTransformedFont
-diff -aruN groff-1.18/font/devps/zapfdr.pfa groff-1.18.win32/font/devps/zapfdr.pfa
---- groff-1.18/font/devps/zapfdr.pfa Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/font/devps/zapfdr.pfa Mon Jul 8 06:47:51 2002
-@@ -0,0 +1,218 @@
-+%!PS-Adobe-3.0 Resource-Font
-+%%DocumentNeededResources: font ZapfDingbats
-+%%IncludeResource: font ZapfDingbats
-+/ZapfDingbats findfont[-1 0 0 1 0 0]makefont
-+dup length 1 add dict begin
-+{
-+exch dup dup/FID ne exch/UniqueID ne and{
-+exch def
-+}{
-+pop pop
-+}ifelse
-+}forall
-+/FontName/ZapfDingbats-Reverse def
-+/Metrics 202 dict dup begin
-+/space[0 -278]def
-+/a1[-939 -974]def
-+/a2[-926 -961]def
-+/a202[-939 -974]def
-+/a3[-945 -980]def
-+/a4[-685 -719]def
-+/a5[-754 -789]def
-+/a119[-755 -790]def
-+/a118[-756 -791]def
-+/a117[-655 -690]def
-+/a11[-925 -960]def
-+/a12[-904 -939]def
-+/a13[-520 -549]def
-+/a14[-821 -855]def
-+/a15[-876 -911]def
-+/a16[-898 -933]def
-+/a105[-876 -911]def
-+/a17[-910 -945]def
-+/a18[-939 -974]def
-+/a19[-721 -755]def
-+/a20[-811 -846]def
-+/a21[-727 -762]def
-+/a22[-726 -761]def
-+/a23[-572 -571]def
-+/a24[-641 -677]def
-+/a25[-728 -763]def
-+/a26[-725 -760]def
-+/a27[-724 -759]def
-+/a28[-719 -754]def
-+/a6[-459 -494]def
-+/a7[-517 -552]def
-+/a8[-502 -537]def
-+/a9[-542 -577]def
-+/a10[-657 -692]def
-+/a29[-751 -786]def
-+/a30[-753 -788]def
-+/a31[-753 -788]def
-+/a32[-755 -790]def
-+/a33[-758 -793]def
-+/a34[-759 -794]def
-+/a35[-781 -816]def
-+/a36[-788 -823]def
-+/a37[-754 -789]def
-+/a38[-806 -841]def
-+/a39[-788 -823]def
-+/a40[-798 -833]def
-+/a41[-781 -816]def
-+/a42[-796 -831]def
-+/a43[-888 -923]def
-+/a44[-709 -744]def
-+/a45[-688 -723]def
-+/a46[-714 -749]def
-+/a47[-756 -790]def
-+/a48[-757 -792]def
-+/a49[-660 -695]def
-+/a50[-741 -776]def
-+/a51[-733 -768]def
-+/a52[-757 -792]def
-+/a53[-724 -759]def
-+/a54[-672 -707]def
-+/a55[-673 -708]def
-+/a56[-647 -682]def
-+/a57[-666 -701]def
-+/a58[-791 -826]def
-+/a59[-780 -815]def
-+/a60[-754 -789]def
-+/a61[-754 -789]def
-+/a62[-673 -707]def
-+/a63[-651 -687]def
-+/a64[-661 -696]def
-+/a65[-654 -689]def
-+/a66[-752 -786]def
-+/a67[-752 -787]def
-+/a68[-678 -713]def
-+/a69[-756 -791]def
-+/a70[-749 -785]def
-+/a71[-756 -791]def
-+/a72[-838 -873]def
-+/a73[-726 -761]def
-+/a74[-727 -762]def
-+/a203[-727 -762]def
-+/a75[-724 -759]def
-+/a204[-724 -759]def
-+/a76[-857 -892]def
-+/a77[-857 -892]def
-+/a78[-753 -788]def
-+/a79[-749 -784]def
-+/a81[-403 -438]def
-+/a82[-103 -138]def
-+/a83[-242 -277]def
-+/a84[-380 -415]def
-+/a97[-357 -392]def
-+/a98[-358 -392]def
-+/a99[-633 -668]def
-+/a100[-632 -668]def
-+/a101[-697 -732]def
-+/a102[-488 -544]def
-+/a103[-510 -544]def
-+/a104[-875 -910]def
-+/a106[-632 -667]def
-+/a107[-725 -760]def
-+/a108[-760 -760]def
-+/a112[-741 -776]def
-+/a111[-561 -595]def
-+/a110[-659 -694]def
-+/a109[-592 -626]def
-+/a120[-753 -788]def
-+/a121[-753 -788]def
-+/a122[-753 -788]def
-+/a123[-753 -788]def
-+/a124[-753 -788]def
-+/a125[-753 -788]def
-+/a126[-753 -788]def
-+/a127[-753 -788]def
-+/a128[-753 -788]def
-+/a129[-753 -788]def
-+/a130[-753 -788]def
-+/a131[-753 -788]def
-+/a132[-753 -788]def
-+/a133[-753 -788]def
-+/a134[-753 -788]def
-+/a135[-753 -788]def
-+/a136[-753 -788]def
-+/a137[-753 -788]def
-+/a138[-753 -788]def
-+/a139[-753 -788]def
-+/a140[-753 -788]def
-+/a141[-753 -788]def
-+/a142[-753 -788]def
-+/a143[-753 -788]def
-+/a144[-753 -788]def
-+/a145[-753 -788]def
-+/a146[-753 -788]def
-+/a147[-753 -788]def
-+/a148[-753 -788]def
-+/a149[-753 -788]def
-+/a150[-753 -788]def
-+/a151[-753 -788]def
-+/a152[-753 -788]def
-+/a153[-753 -788]def
-+/a154[-753 -788]def
-+/a155[-753 -788]def
-+/a156[-753 -788]def
-+/a157[-753 -788]def
-+/a158[-753 -788]def
-+/a159[-753 -788]def
-+/a160[-859 -894]def
-+/a161[-803 -838]def
-+/a163[-982 -1016]def
-+/a164[-423 -458]def
-+/a196[-713 -748]def
-+/a165[-889 -924]def
-+/a192[-713 -748]def
-+/a166[-883 -918]def
-+/a167[-892 -927]def
-+/a168[-893 -928]def
-+/a169[-893 -928]def
-+/a170[-799 -834]def
-+/a171[-838 -873]def
-+/a172[-793 -828]def
-+/a173[-889 -924]def
-+/a162[-889 -924]def
-+/a174[-882 -917]def
-+/a175[-895 -930]def
-+/a176[-896 -931]def
-+/a177[-428 -463]def
-+/a178[-848 -883]def
-+/a179[-801 -836]def
-+/a193[-801 -836]def
-+/a180[-832 -867]def
-+/a199[-832 -867]def
-+/a181[-661 -696]def
-+/a200[-661 -696]def
-+/a182[-839 -874]def
-+/a201[-839 -874]def
-+/a183[-725 -760]def
-+/a184[-911 -946]def
-+/a197[-737 -771]def
-+/a185[-830 -865]def
-+/a194[-737 -771]def
-+/a198[-854 -888]def
-+/a186[-932 -967]def
-+/a195[-854 -888]def
-+/a187[-796 -831]def
-+/a188[-837 -873]def
-+/a189[-892 -927]def
-+/a190[-935 -970]def
-+/a191[-884 -918]def
-+/a205[-474 -509]def
-+/a206[-375 -410]def
-+/a85[-474 -509]def
-+/a86[-375 -410]def
-+/a87[-199 -234]def
-+/a88[-199 -234]def
-+/a89[-355 -390]def
-+/a90[-355 -390]def
-+/a91[-241 -276]def
-+/a92[-241 -276]def
-+/a93[-282 -317]def
-+/a94[-282 -317]def
-+/a95[-299 -334]def
-+/a96[-299 -334]def
-+end def
-+/ZapfDingbats-Reverse currentdict end definefont pop
-diff -aruN groff-1.18/src/devices/grodvi/Makefile.msc groff-1.18.win32/src/devices/grodvi/Makefile.msc
---- groff-1.18/src/devices/grodvi/Makefile.msc Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/src/devices/grodvi/Makefile.msc Mon Jul 8 06:47:51 2002
-@@ -0,0 +1,21 @@
-+
-+# Makefile for Microsoft Visual C++ 6.0
-+# by Blake McBride (blake@florida-software.com)
-+
-+
-+.SUFFIXES : .cc
-+
-+.cc.obj:
-+ cl -c -nologo -I../../include -Tp$<
-+
-+.c.obj:
-+ cl -c -nologo -I../../include $<
-+
-+OBJS = dvi.obj
-+
-+
-+grodvi.exe : $(OBJS)
-+ cl -nologo -Fe$@ *.obj ..\..\libs\libdriver\libdriver.lib ..\..\libs\libgroff\libgroff.lib
-+
-+
-+
-diff -aruN groff-1.18/src/devices/grolj4/Makefile.msc groff-1.18.win32/src/devices/grolj4/Makefile.msc
---- groff-1.18/src/devices/grolj4/Makefile.msc Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/src/devices/grolj4/Makefile.msc Mon Jul 8 06:47:51 2002
-@@ -0,0 +1,22 @@
-+
-+# Makefile for Microsoft Visual C++ 6.0
-+# by Blake McBride (blake@florida-software.com)
-+
-+
-+.SUFFIXES : .cc
-+
-+.cc.obj:
-+ cl -c -nologo -I../../include -Tp$<
-+
-+.c.obj:
-+ cl -c -nologo -I../../include $<
-+
-+OBJS = \
-+ lj4.obj
-+
-+
-+grolj4.exe : $(OBJS)
-+ cl -nologo -Fe$@ *.obj ..\..\libs\libdriver\libdriver.lib ..\..\libs\libgroff\libgroff.lib
-+
-+
-+
-diff -aruN groff-1.18/src/devices/grops/Makefile.msc groff-1.18.win32/src/devices/grops/Makefile.msc
---- groff-1.18/src/devices/grops/Makefile.msc Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/src/devices/grops/Makefile.msc Mon Jul 8 06:47:51 2002
-@@ -0,0 +1,23 @@
-+
-+# Makefile for Microsoft Visual C++ 6.0
-+# by Blake McBride (blake@florida-software.com)
-+
-+
-+.SUFFIXES : .cc
-+
-+.cc.obj:
-+ cl -c -nologo -I../../include -Tp$<
-+
-+.c.obj:
-+ cl -c -nologo -I../../include $<
-+
-+OBJS = \
-+ ps.obj \
-+ psrm.obj
-+
-+
-+grops.exe : $(OBJS)
-+ cl -nologo -Fe$@ *.obj ..\..\libs\libdriver\libdriver.lib ..\..\libs\libgroff\libgroff.lib
-+
-+
-+
-diff -aruN groff-1.18/src/devices/grotty/Makefile.msc groff-1.18.win32/src/devices/grotty/Makefile.msc
---- groff-1.18/src/devices/grotty/Makefile.msc Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/src/devices/grotty/Makefile.msc Mon Jul 8 06:47:51 2002
-@@ -0,0 +1,22 @@
-+
-+# Makefile for Microsoft Visual C++ 6.0
-+# by Blake McBride (blake@florida-software.com)
-+
-+
-+.SUFFIXES : .cc
-+
-+.cc.obj:
-+ cl -c -nologo -I../../include -Tp$<
-+
-+.c.obj:
-+ cl -c -nologo -I../../include $<
-+
-+OBJS = \
-+ tty.obj
-+
-+
-+grotty.exe : $(OBJS)
-+ cl -nologo -Fe$@ *.obj ..\..\libs\libdriver\libdriver.lib ..\..\libs\libgroff\libgroff.lib
-+
-+
-+
-diff -aruN groff-1.18/src/include/defs.h groff-1.18.win32/src/include/defs.h
---- groff-1.18/src/include/defs.h Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/src/include/defs.h Mon Jul 8 08:32:01 2002
-@@ -0,0 +1,8 @@
-+
-+#define FONTPATH "c:/groff/font"
-+
-+#define MACROPATH "c:/groff/tmac;c:/groff/mm"
-+
-+#define DEVICE "ps"
-+
-+#define PROG_PREFIX ""
-diff -aruN groff-1.18/src/include/getopt.h groff-1.18.win32/src/include/getopt.h
---- groff-1.18/src/include/getopt.h Sat Aug 25 01:37:49 2001
-+++ groff-1.18.win32/src/include/getopt.h Mon Jul 8 06:47:51 2002
-@@ -162,7 +162,7 @@
- int __long_only);
- # endif
- #else /* not __STDC__ */
--extern int getopt ();
-+extern int getopt (int a, char **b, char *c);
- # ifndef __need_getopt
- extern int getopt_long ();
- extern int getopt_long_only ();
-diff -aruN groff-1.18/src/libs/libdriver/Makefile.msc groff-1.18.win32/src/libs/libdriver/Makefile.msc
---- groff-1.18/src/libs/libdriver/Makefile.msc Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/src/libs/libdriver/Makefile.msc Mon Jul 8 06:47:51 2002
-@@ -0,0 +1,22 @@
-+
-+# Makefile for Microsoft Visual C++ 6.0
-+# by Blake McBride (blake@florida-software.com)
-+
-+
-+.SUFFIXES : .cc
-+
-+.cc.obj:
-+ cl -c -nologo -I../../include -Tp$<
-+
-+.c.obj:
-+ cl -c -nologo -I../../include $<
-+
-+OBJS = \
-+ input.obj \
-+ printer.obj
-+
-+
-+libdriver.lib : $(OBJS)
-+ rm -zq $@
-+ lib /NOLOGO /OUT:$@ *.obj
-+
-diff -aruN groff-1.18/src/libs/libgroff/Makefile.msc groff-1.18.win32/src/libs/libgroff/Makefile.msc
---- groff-1.18/src/libs/libgroff/Makefile.msc Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/src/libs/libgroff/Makefile.msc Mon Jul 8 06:47:51 2002
-@@ -0,0 +1,59 @@
-+
-+# Makefile for Microsoft Visual C++ 6.0
-+# by Blake McBride (blake@florida-software.com)
-+
-+
-+#CFLAGS = -nologo -I../../include -GF -Zi -Yd -DHAVE_STRING_H=1
-+CFLAGS = -nologo -I../../include -GF -Ox -DHAVE_STRING_H=1
-+
-+
-+.SUFFIXES : .cc
-+
-+
-+.cc.obj:
-+ cl -c $(CFLAGS) -Tp$<
-+
-+.c.obj:
-+ cl -c $(CFLAGS) $<
-+
-+
-+OBJS = \
-+ assert.obj \
-+ change_lf.obj \
-+ cmap.obj \
-+ color.obj \
-+ cset.obj \
-+ device.obj \
-+ errarg.obj \
-+ error.obj \
-+ fatal.obj \
-+ filename.obj \
-+ font.obj \
-+ fontfile.obj \
-+ getopt.obj \
-+ geometry.obj \
-+ htmlhint.obj \
-+ iftoa.obj \
-+ invalid.obj \
-+ itoa.obj \
-+ lf.obj \
-+ lineno.obj \
-+ macropath.obj \
-+ mkstemp.obj \
-+ mksdir.obj \
-+ nametoindex.obj \
-+ paper.obj \
-+ progname.obj \
-+ ptable.obj \
-+ searchpath.obj \
-+ string.obj \
-+ strsave.obj \
-+ tmpfile.obj \
-+ tmpname.obj \
-+ version.obj
-+
-+
-+libgroff.lib : $(OBJS)
-+ rm -zq $@
-+ lib /NOLOGO /OUT:$@ *.obj
-+
-diff -aruN groff-1.18/src/libs/libgroff/version.cc groff-1.18.win32/src/libs/libgroff/version.cc
---- groff-1.18/src/libs/libgroff/version.cc Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/src/libs/libgroff/version.cc Mon Jul 8 06:47:51 2002
-@@ -0,0 +1,3 @@
-+const char *version_string = "1.18";
-+const char *revision_string = "0";
-+extern "C" const char *Version_string = "1.18";
-diff -aruN groff-1.18/src/preproc/eqn/Makefile.msc groff-1.18.win32/src/preproc/eqn/Makefile.msc
---- groff-1.18/src/preproc/eqn/Makefile.msc Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/src/preproc/eqn/Makefile.msc Mon Jul 8 06:47:51 2002
-@@ -0,0 +1,39 @@
-+
-+# Makefile for Microsoft Visual C++ 6.0
-+# by Blake McBride (blake@florida-software.com)
-+
-+
-+#CFLAGS = -nologo -I../../include -GF -Zi -Yd
-+CFLAGS = -nologo -I../../include -GF -Ox
-+
-+.SUFFIXES : .cc
-+
-+.cc.obj:
-+ cl -c $(CFLAGS) -Tp$<
-+
-+.c.obj:
-+ cl -c $(CFLAGS) $<
-+
-+OBJS = \
-+ box.obj \
-+ delim.obj \
-+ eqn.obj \
-+ lex.obj \
-+ limit.obj \
-+ list.obj \
-+ main.obj \
-+ mark.obj \
-+ other.obj \
-+ over.obj \
-+ pile.obj \
-+ script.obj \
-+ special.obj \
-+ sqrt.obj \
-+ text.obj
-+
-+
-+eqn.exe : $(OBJS)
-+ cl $(CFLAGS) -Fe$@ *.obj ..\..\libs\libgroff\libgroff.lib
-+
-+
-+
-diff -aruN groff-1.18/src/preproc/pic/Makefile.msc groff-1.18.win32/src/preproc/pic/Makefile.msc
---- groff-1.18/src/preproc/pic/Makefile.msc Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/src/preproc/pic/Makefile.msc Mon Jul 8 06:47:51 2002
-@@ -0,0 +1,31 @@
-+
-+# Makefile for Microsoft Visual C++ 6.0
-+# by Blake McBride (blake@florida-software.com)
-+
-+
-+#CFLAGS = -nologo -I../../include -GF -Zi -Yd -DRET_TYPE_SRAND_IS_VOID
-+CFLAGS = -nologo -I../../include -GF -Ox -DRET_TYPE_SRAND_IS_VOID
-+
-+.SUFFIXES : .cc
-+
-+.cc.obj:
-+ cl -c $(CFLAGS) -Tp$<
-+
-+.c.obj:
-+ cl -c $(CFLAGS) $<
-+
-+OBJS = \
-+ common.obj \
-+ lex.obj \
-+ main.obj \
-+ object.obj \
-+ pic.obj \
-+ tex.obj \
-+ troff.obj
-+
-+
-+pic.exe : $(OBJS)
-+ cl $(CFLAGS) -Fe$@ *.obj ..\..\libs\libgroff\libgroff.lib
-+
-+
-+
-diff -aruN groff-1.18/src/preproc/tbl/Makefile.msc groff-1.18.win32/src/preproc/tbl/Makefile.msc
---- groff-1.18/src/preproc/tbl/Makefile.msc Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/src/preproc/tbl/Makefile.msc Mon Jul 8 06:47:51 2002
-@@ -0,0 +1,26 @@
-+
-+# Makefile for Microsoft Visual C++ 6.0
-+# by Blake McBride (blake@florida-software.com)
-+
-+
-+#CFLAGS = -nologo -I../../include -GF -Zi -Yd
-+CFLAGS = -nologo -I../../include -GF -Ox
-+
-+.SUFFIXES : .cc
-+
-+.cc.obj:
-+ cl -c $(CFLAGS) -Tp$<
-+
-+.c.obj:
-+ cl -c $(CFLAGS) $<
-+
-+OBJS = \
-+ main.obj \
-+ table.obj
-+
-+
-+tbl.exe : $(OBJS)
-+ cl $(CFLAGS) -Fe$@ *.obj ..\..\libs\libgroff\libgroff.lib
-+
-+
-+
-diff -aruN groff-1.18/src/roff/troff/Makefile.msc groff-1.18.win32/src/roff/troff/Makefile.msc
---- groff-1.18/src/roff/troff/Makefile.msc Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/src/roff/troff/Makefile.msc Mon Jul 8 06:47:51 2002
-@@ -0,0 +1,34 @@
-+
-+# Makefile for Microsoft Visual C++ 6.0
-+# by Blake McBride (blake@florida-software.com)
-+
-+
-+#CFLAGS = -nologo -I../../include -GF -Zi -Yd
-+CFLAGS = -nologo -I../../include -GF -Ox
-+
-+.SUFFIXES : .cc
-+
-+.cc.obj:
-+ cl -c $(CFLAGS) -Tp$<
-+
-+.c.obj:
-+ cl -c $(CFLAGS) $<
-+
-+OBJS = \
-+ column.obj \
-+ dictionary.obj \
-+ div.obj \
-+ env.obj \
-+ input.obj \
-+ node.obj \
-+ number.obj \
-+ reg.obj \
-+ symbol.obj \
-+ majorminor.obj
-+
-+
-+troff.exe : $(OBJS)
-+ cl $(CFLAGS) -Fe$@ *.obj ..\..\libs\libgroff\libgroff.lib -link -map
-+
-+
-+
-diff -aruN groff-1.18/src/roff/troff/majorminor.cc groff-1.18.win32/src/roff/troff/majorminor.cc
---- groff-1.18/src/roff/troff/majorminor.cc Thu Jan 1 01:00:00 1970
-+++ groff-1.18.win32/src/roff/troff/majorminor.cc Mon Jul 8 06:47:51 2002
-@@ -0,0 +1,3 @@
-+const char *major_version = "1";
-+const char *minor_version = "18";
-+const char *revision = "0";
--
cgit v1.1