📄 command.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. */#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 = "<standard input>"; } 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 (illegal_input_char(c)) error_with_file_and_line(fn, lineno, "illegal 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 ""// \<newline> 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// \<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 wordint 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 *)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -