⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 input.cc

📁 早期freebsd实现
💻 CC
📖 第 1 页 / 共 5 页
字号:
// -*- 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 underthe terms of the GNU General Public License as published by the FreeSoftware Foundation; either version 2, or (at your option) any laterversion.groff is distributed in the hope that it will be useful, but WITHOUT ANYWARRANTY; without even the implied warranty of MERCHANTABILITY orFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public Licensefor more details.You should have received a copy of the GNU General Public License alongwith groff; see the file COPYING.  If not, write to the Free SoftwareFoundation, 675 Mass Ave, Cambridge, MA 02139, 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 "font.h"#include "searchpath.h"#include "macropath.h"#include "defs.h"// Needed for getpid().#include "posix.h"#define USAGE_EXIT_CODE 1#define MACRO_PREFIX "tmac."#define STARTUP_FILE "troffrc"#define DEFAULT_INPUT_STACK_LIMIT 1000#ifndef DEFAULT_WARNING_MASK// warnings that are enabled by default#define DEFAULT_WARNING_MASK \     (WARN_CHAR|WARN_NUMBER|WARN_BREAK|WARN_SPACE|WARN_FONT)#endif// initial size of buffer for reading names; expanded as necessary#define ABUF_SIZE 16#ifdef COLUMNvoid 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 COLUMNvoid vjustify();#endif /* COLUMN */void transparent();void transparent_file();const char *program_name = 0;token tok;int break_flag = 0;static int backtrace_flag = 0;char *pipe_command = 0;charinfo *charset_table[256];static int warning_mask = DEFAULT_WARNING_MASK;static int inhibit_errors = 0;static void enable_warning(const char *);static void disable_warning(const char *);static int escape_char = '\\';static symbol end_macro_name;static int compatible_flag = 0;static void process_input_stack();int ascii_output_flag = 0;int suppress_output_flag = 0;int tcommand_flag = 0;static int get_copy(node**, int = 0);static symbol read_escape_name();static void interpolate_string(symbol);static void interpolate_macro(symbol);static void interpolate_number_format(symbol);static void interpolate_environment_variable(symbol);static void interpolate_arg(symbol);static request_or_macro *lookup_request(symbol);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();struct input_iterator;input_iterator *make_temp_iterator(const char *);const char *input_char_description(int);const int ESCAPE_QUESTION = 015;const int BEGIN_TRAP = 016;const int END_TRAP = 017;const int PAGE_EJECTOR = 020;const int ESCAPE_NEWLINE = 021;const int ESCAPE_AMPERSAND = 022;const int ESCAPE_UNDERSCORE = 023;const int ESCAPE_BAR = 024;const int ESCAPE_CIRCUMFLEX = 025;const int ESCAPE_LEFT_BRACE = 026;const int ESCAPE_RIGHT_BRACE = 027;const int ESCAPE_LEFT_QUOTE = 030;const int ESCAPE_RIGHT_QUOTE = 031;const int ESCAPE_HYPHEN = 032;const int ESCAPE_BANG = 033;const int ESCAPE_c = 034;const int ESCAPE_e = 035;const int ESCAPE_PERCENT = 036;const int ESCAPE_SPACE = 037;const int TITLE_REQUEST = 0200;const int COPY_FILE_REQUEST = 0201;const int TRANSPARENT_FILE_REQUEST = 0202;#ifdef COLUMNconst int VJUSTIFY_REQUEST = 0203;#endif /* COLUMN */const int ESCAPE_E = 0204;const int LAST_PAGE_EJECTOR = 0205;const int ESCAPE_RIGHT_PARENTHESIS = 0206;void set_escape_char(){  if (has_arg()) {    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();}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 NULL; }  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();  virtual int internal_level() { return 0; }  virtual int is_file() { return 0; }};input_iterator::input_iterator(): ptr(0), eptr(0){}input_iterator::~input_iterator(){}int input_iterator::fill(node **){  return EOF;}int input_iterator::peek(){  return EOF;}int input_iterator::is_boundary(){  return 0;}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 file_iterator : public input_iterator {  FILE *fp;  int lineno;  const char *filename;  int newline_flag;  enum { BUF_SIZE = 512 };  unsigned char buf[BUF_SIZE];public:  file_iterator(FILE *, const char *);  ~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): fp(f), filename(fn), lineno(1), newline_flag(0){}file_iterator::~file_iterator(){  if (fp != stdin)    fclose(fp);  else    clearerr(stdin);}int file_iterator::is_file(){  return 1;}int file_iterator::next_file(FILE *f, const char *s){  if (fp != stdin)    fclose(fp);  else    clearerr(stdin);  filename = s;  fp = f;  lineno = 1;  newline_flag = 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 (illegal_input_char(c))      warning(WARN_INPUT, "illegal input character code %1", int(c));    else {      *p++ = c;      if (c == '\n') {	newline_flag = 1;	break;      }    }  }  if (p > buf) {    eptr = p;    return *ptr++;  }  else {    eptr = p;    return EOF;  }}int file_iterator::peek(){  int c = getc(fp);  while (illegal_input_char(c)) {    warning(WARN_INPUT, "illegal 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 = "<standard input>";  else    *filenamep = filename;  return 1;}void file_iterator::backtrace(){  errprint("%1:%2: backtrace: file `%1'\n", filename, lineno);}int file_iterator::set_location(const char *f, int ln){  if (f)    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 remove_boundary();  static int get_level();  static void clear();  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::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 != NULL; 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){  for (input_iterator **pp = &top; *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 = &top; *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_boundary();}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 c = get_copy(NULL);  switch (c) {  case EOF:    error("end of input in escape name");    return '\0';  default:    if (!illegal_input_char(c))      break;    // fall through  case ' ':  case '\n':  case '\t':  case '\001':  case '\b':    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(){  int start_level = input_stack::get_level();  char abuf[ABUF_SIZE];  char *buf = abuf;  int buf_size = ABUF_SIZE;  int i = 0;  for (;;) {    int c = get_char_for_escape_name();    if (c == 0) {      if (buf != abuf)	a_delete buf;      return NULL_SYMBOL;    }    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 (buf == abuf) {    if (i == 0) {      error("empty escape name");      return NULL_SYMBOL;    }    return symbol(abuf);  }  else {    symbol s(buf);    a_delete buf;    return s;  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -