📄 input.cc
字号:
{ unsigned char ch = tok.c; if (bol && (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; } 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 && !curenv->get_prev_line_interrupted()) blank_line(); else { curenv->newline(); bol = 1; } 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; break; } case token::TOKEN_SPACE: { if (possibly_handle_first_page_transition()) ; else if (bol && !curenv->get_prev_line_interrupted()) { int nspaces = 0; do { nspaces += tok.nspaces(); tok.next(); } while (tok.space()); if (tok.newline()) blank_line(); else { push_token(tok); curenv->do_break(); curenv->add_node(new hmotion_node(curenv->get_space_width()*nspaces)); 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; } 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; 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_CONTROLvoid 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); 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(): head(0), tail(0), ptr(0), len(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++;}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 { 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; } length = 0; p = 0;}macro::macro(const macro &m) : filename(m.filename), lineno(m.lineno), p(m.p), length(m.length){ 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; length = m.length; return *this;}void macro::append(unsigned char c){ assert(c != 0); if (p == 0) p = new macro_header; if (p->cl.length() != length) { macro_header *tem = p->copy(length); if (--(p->count) <= 0) delete p; p = tem; } p->cl.append(c); ++length;}void macro::append(node *n){ assert(n != 0); if (p == 0) p = new macro_header; if (p->cl.length() != length) { macro_header *tem = p->copy(length); if (--(p->count) <= 0) delete p; p = tem; } p->cl.append(0); p->nl.append(n); ++length;}void macro::print_size(){ errprint("%1", length);}// make a copy of the first n bytesmacro_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;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();};string_iterator::string_iterator(const macro &m, const char *p, symbol s) : lineno(1), mac(m), newline_flag(0), how_invoked(p), nm(s){ count = mac.length; 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 (count <= 0) return EOF; 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#endiftemp_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#endifvoid 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#endifsmall_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){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -