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

📄 groff.cc

📁 早期freebsd实现
💻 CC
字号:
// -*- 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. */// A front end for groff.#include <stdio.h>#include <string.h>#include <stdlib.h>#include <signal.h>#include <errno.h>#include "lib.h"#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 "defs.h"#define BSHELL "/bin/sh"#define GXDITVIEW "gxditview"// troff will be passed an argument of -rXREG=1 if the -X option is// specified#define XREG ".X"#ifndef STDLIB_H_DECLARES_PUTENVextern "C" {  int putenv(const char *);}#endif /* not STDLIB_H_DECLARES_PUTENV */const char *strsignal(int);const int SOELIM_INDEX = 0;const int REFER_INDEX = SOELIM_INDEX + 1;const int PIC_INDEX = REFER_INDEX + 1;const int TBL_INDEX = PIC_INDEX + 1;const int EQN_INDEX = TBL_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 clear_args();  char **get_argv();  void print(int is_last, FILE *fp);};int lflag = 0;char *spooler = 0;char *driver = 0;possible_command commands[NCOMMANDS];int run_commands();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 *basename(const char *);void usage();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 zflag = 0;  int iflag = 0;  int Xflag = 0;  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");  while ((opt = getopt(argc, argv,		       "itpeRszavVhblCENXZF:m:T:f:w:W:M:d:r:n:o:P:L:"))	 != EOF) {    char buf[3];    buf[0] = '-';    buf[1] = opt;    buf[2] = '\0';    switch (opt) {    case 'i':      iflag = 1;      break;    case 't':      commands[TBL_INDEX].set_name(command_prefix, "tbl");      break;    case 'p':      commands[PIC_INDEX].set_name(command_prefix, "pic");      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':    case 'C':      commands[SOELIM_INDEX].append_arg(buf);      commands[PIC_INDEX].append_arg(buf);      commands[TBL_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 'T':      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 += ':';	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[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();      break;    default:      assert(0);      break;    }  }  font::set_unknown_desc_command_handler(handle_unknown_desc_command);  if (!font::load_desc())    fatal("invalid device `%1'", device);  if (!driver)    fatal("no `postpro' command in DESC file for device `%1'", device);  const char *real_driver = 0;  if (Xflag) {    real_driver = driver;    driver = GXDITVIEW;    commands[TROFF_INDEX].append_arg("-r" XREG "=", "1");  }  if (driver)    commands[POST_INDEX].set_name(driver);  int gxditview_flag = driver && strcmp(basename(driver), 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("-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);  commands[EQN_INDEX].append_arg("-T", device);  for (int 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 += ':';      e += fontpath;    }    e += '\0';    if (putenv(strsave(e.contents())))      fatal("putenv failed");  }  if (Vflag) {    print_commands();    exit(0);  }  exit(run_commands());}const char *basename(const char *s){  if (!s)    return 0;  const char *p = strrchr(s, '/');  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, "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;	}      driver = strsave(arg);    }  }}void print_commands(){  for (int 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(){  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);}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::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 (argv[0] != 0 && strcmp(argv[0], BSHELL) == 0      && argv[1] != 0 && strcmp(argv[1], "-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;  for (const char *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(){  fprintf(stderr,"usage: %s [-abehilpstvzCENRVXZ] [-Fdir] [-mname] [-Tdev] [-ffam] [-wname]\n""       [-Wname] [ -Mdir] [-dcs] [-rcn] [-nnum] [-olist] [-Parg] [-Larg]\n""       [files...]\n",	  program_name);}void help(){  synopsis();  fputs("\n""-h\tprint this message\n""-t\tpreprocess with tbl\n""-p\tpreprocess with pic\n""-e\tpreprocess with eqn\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 directory 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\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""\n",	stderr);  exit(0);}void usage(){  synopsis();  fprintf(stderr, "%s -h gives more help\n", program_name);  exit(1);}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);}}

⌨️ 快捷键说明

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