📄 input.cc
字号:
static symbol read_escape_name(){ 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(); 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(NULL); while ((c = input_stack::get(NULL)) != '\n' && c != EOF) ; return c; case '#': // Like \" but newline is ignored. (void)input_stack::get(NULL); while ((c = input_stack::get(NULL)) != '\n') if (c == EOF) return EOF; break; case '$': { (void)input_stack::get(NULL); symbol s = read_escape_name(); if (!s.is_null()) interpolate_arg(s); break; } case '*': { (void)input_stack::get(NULL); symbol s = read_escape_name(); if (!s.is_null()) interpolate_string(s); break; } case 'a': (void)input_stack::get(NULL); return '\001'; case 'e': (void)input_stack::get(NULL); return ESCAPE_e; case 'E': (void)input_stack::get(NULL); return ESCAPE_E; case 'n': { (void)input_stack::get(NULL); int inc; symbol s = read_increment_and_escape_name(&inc); if (!s.is_null()) interpolate_number_reg(s, inc); break; } case 'g': { (void)input_stack::get(NULL); symbol s = read_escape_name(); if (!s.is_null()) interpolate_number_format(s); break; } case 't': (void)input_stack::get(NULL); return '\t'; case 'V': { (void)input_stack::get(NULL); symbol s = read_escape_name(); if (!s.is_null()) interpolate_environment_variable(s); break; } case '\n': (void)input_stack::get(NULL); if (defining) return ESCAPE_NEWLINE; break; case ' ': (void)input_stack::get(NULL); return ESCAPE_SPACE; case '|': (void)input_stack::get(NULL); return ESCAPE_BAR; case '^': (void)input_stack::get(NULL); return ESCAPE_CIRCUMFLEX; case '{': (void)input_stack::get(NULL); return ESCAPE_LEFT_BRACE; case '}': (void)input_stack::get(NULL); return ESCAPE_RIGHT_BRACE; case '`': (void)input_stack::get(NULL); return ESCAPE_LEFT_QUOTE; case '\'': (void)input_stack::get(NULL); return ESCAPE_RIGHT_QUOTE; case '-': (void)input_stack::get(NULL); return ESCAPE_HYPHEN; case '_': (void)input_stack::get(NULL); return ESCAPE_UNDERSCORE; case 'c': (void)input_stack::get(NULL); return ESCAPE_c; case '!': (void)input_stack::get(NULL); return ESCAPE_BANG; case '?': (void)input_stack::get(NULL); return ESCAPE_QUESTION; case '&': (void)input_stack::get(NULL); return ESCAPE_AMPERSAND; case ')': (void)input_stack::get(NULL); return ESCAPE_RIGHT_PARENTHESIS; case '.': (void)input_stack::get(NULL); return c; case '%': (void)input_stack::get(NULL); return ESCAPE_PERCENT; default: if (c == escape_char) { (void)input_stack::get(NULL); 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 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";}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 void do_register();static node *do_overstrike(){ token start; overstrike_node *on = new overstrike_node; start.next(); tok.next(); while (tok != start) { if (tok.newline() || tok.eof()) { warning(WARN_DELIM, "missing closing delimiter"); break; } charinfo *ci = tok.get_char(1); if (ci) { node *n = curenv->make_char_node(ci); if (n) on->overstrike(n); } tok.next(); } return on;}static node *do_bracket(){ token start; bracket_node *bn = new bracket_node; start.next(); tok.next(); while (tok != start) { 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; } charinfo *ci = tok.get_char(1); if (ci) { node *n = curenv->make_char_node(ci); if (n) bn->bracket(n); } tok.next(); } 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;}#if 0static 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("illegal 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);}#endiftoken_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();};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";}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 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_NODE; nd = new space_char_hmotion_node(curenv->get_space_width()); 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()); return; case ESCAPE_CIRCUMFLEX: ESCAPE_CIRCUMFLEX: type = TOKEN_NODE; nd = new hmotion_node(curenv->get_half_narrow_space_width()); 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_NODE; nd = new transparent_dummy_node; 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(NULL); 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()); 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 '~': nd = new unbreakable_space_node(curenv->get_space_width()); type = TOKEN_NODE; return; case '"': while ((cc = input_stack::get(NULL)) != '\n' && cc != EOF)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -