/[groff]/groff/src/roff/troff/input.cpp
ViewVC logotype

Diff of /groff/src/roff/troff/input.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.19 by wl, Mon Sep 27 06:09:40 2004 UTC revision 1.20 by wl, Sun Oct 10 19:08:03 2004 UTC
# Line 19  You should have received a copy of the G Line 19  You should have received a copy of the G
19  with groff; see the file COPYING.  If not, write to the Free Software  with groff; see the file COPYING.  If not, write to the Free Software
20  Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */  Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21    
22    #define DEBUGGING
23    
24  #include "troff.h"  #include "troff.h"
25  #include "dictionary.h"  #include "dictionary.h"
26  #include "hvunits.h"  #include "hvunits.h"
# Line 29  Foundation, 59 Temple Place - Suite 330, Line 31  Foundation, 59 Temple Place - Suite 330,
31  #include "token.h"  #include "token.h"
32  #include "div.h"  #include "div.h"
33  #include "charinfo.h"  #include "charinfo.h"
 #include "stringclass.h"  
34  #include "font.h"  #include "font.h"
35  #include "macropath.h"  #include "macropath.h"
36  #include "defs.h"  #include "defs.h"
# Line 117  double spread_limit = -3.0 - 1.0;      // neg Line 118  double spread_limit = -3.0 - 1.0;      // neg
118    
119  double warn_scale;  double warn_scale;
120  char warn_scaling_indicator;  char warn_scaling_indicator;
121    int debug_state = 0;            // turns on debugging of the html troff state
122    
123  search_path *mac_path = &safer_macro_path;  search_path *mac_path = &safer_macro_path;
124    
# Line 195  void restore_escape_char() Line 197  void restore_escape_char()
197  class input_iterator {  class input_iterator {
198  public:  public:
199    input_iterator();    input_iterator();
200      input_iterator(int is_div);
201    virtual ~input_iterator() {}    virtual ~input_iterator() {}
202    int get(node **);    int get(node **);
203    friend class input_stack;    friend class input_stack;
204      int is_diversion;
205      statem *diversion_state;
206  protected:  protected:
207    const unsigned char *ptr;    const unsigned char *ptr;
208    const unsigned char *eptr;    const unsigned char *eptr;
# Line 221  private: Line 226  private:
226  };  };
227    
228  input_iterator::input_iterator()  input_iterator::input_iterator()
229  : ptr(0), eptr(0)  : ptr(0), eptr(0), is_diversion(0)
230    {
231    }
232    
233    input_iterator::input_iterator(int is_div)
234    : ptr(0), eptr(0), is_diversion(is_div)
235  {  {
236  }  }
237    
# Line 415  public: Line 425  public:
425    static int is_return_boundary();    static int is_return_boundary();
426    static void remove_boundary();    static void remove_boundary();
427    static int get_level();    static int get_level();
428      static int get_div_level();
429    static void increase_level();    static void increase_level();
430    static void decrease_level();    static void decrease_level();
431    static void clear();    static void clear();
432    static void pop_macro();    static void pop_macro();
433    static void save_compatible_flag(int);    static void save_compatible_flag(int);
434    static int get_compatible_flag();    static int get_compatible_flag();
435      static statem *get_diversion_state();
436      static void check_end_diversion(input_iterator *t);
437    static int limit;    static int limit;
438      static int div_level;
439      static statem *diversion_state;
440  private:  private:
441    static input_iterator *top;    static input_iterator *top;
442    static int level;    static int level;
   
443    static int finish_get(node **);    static int finish_get(node **);
444    static int finish_peek();    static int finish_peek();
445  };  };
# Line 434  private: Line 447  private:
447  input_iterator *input_stack::top = &nil_iterator;  input_iterator *input_stack::top = &nil_iterator;
448  int input_stack::level = 0;  int input_stack::level = 0;
449  int input_stack::limit = DEFAULT_INPUT_STACK_LIMIT;  int input_stack::limit = DEFAULT_INPUT_STACK_LIMIT;
450    int input_stack::div_level = 0;
451    statem *input_stack::diversion_state = NULL;
452    int suppress_push=0;
453    
454    
455  inline int input_stack::get_level()  inline int input_stack::get_level()
456  {  {
# Line 450  inline void input_stack::decrease_level( Line 467  inline void input_stack::decrease_level(
467    level--;    level--;
468  }  }
469    
470    inline int input_stack::get_div_level()
471    {
472      return div_level;
473    }
474    
475  inline int input_stack::get(node **np)  inline int input_stack::get(node **np)
476  {  {
477    int res = (top->ptr < top->eptr) ? *top->ptr++ : finish_get(np);    int res = (top->ptr < top->eptr) ? *top->ptr++ : finish_get(np);
# Line 469  int input_stack::finish_get(node **np) Line 491  int input_stack::finish_get(node **np)
491      if (top == &nil_iterator)      if (top == &nil_iterator)
492        break;        break;
493      input_iterator *tem = top;      input_iterator *tem = top;
494        check_end_diversion(tem);
495    #if defined(DEBUGGING)
496      if (debug_state)
497        if (tem->is_diversion)
498          fprintf(stderr, "in diversion level = %d\n", input_stack::get_div_level());
499    #endif
500      top = top->next;      top = top->next;
501      level--;      level--;
502      delete tem;      delete tem;
# Line 484  inline int input_stack::peek() Line 512  inline int input_stack::peek()
512    return (top->ptr < top->eptr) ? *top->ptr : finish_peek();    return (top->ptr < top->eptr) ? *top->ptr : finish_peek();
513  }  }
514    
515    void input_stack::check_end_diversion(input_iterator *t)
516    {
517      if (t->is_diversion) {
518        div_level--;
519        diversion_state = t->diversion_state;
520      }
521    }
522    
523  int input_stack::finish_peek()  int input_stack::finish_peek()
524  {  {
525    for (;;) {    for (;;) {
# Line 493  int input_stack::finish_peek() Line 529  int input_stack::finish_peek()
529      if (top == &nil_iterator)      if (top == &nil_iterator)
530        break;        break;
531      input_iterator *tem = top;      input_iterator *tem = top;
532        check_end_diversion(tem);
533      top = top->next;      top = top->next;
534      level--;      level--;
535      delete tem;      delete tem;
# Line 522  void input_stack::remove_boundary() Line 559  void input_stack::remove_boundary()
559  {  {
560    assert(top->is_boundary());    assert(top->is_boundary());
561    input_iterator *temp = top->next;    input_iterator *temp = top->next;
562      check_end_diversion(top);
563    
564    delete top;    delete top;
565    top = temp;    top = temp;
566    level--;    level--;
# Line 535  void input_stack::push(input_iterator *i Line 574  void input_stack::push(input_iterator *i
574      fatal("input stack limit exceeded (probable infinite loop)");      fatal("input stack limit exceeded (probable infinite loop)");
575    in->next = top;    in->next = top;
576    top = in;    top = in;
577      if (top->is_diversion) {
578        div_level++;
579        in->diversion_state = diversion_state;
580        diversion_state = curenv->construct_state(0);
581    #if defined(DEBUGGING)
582        if (debug_state) {
583          curenv->dump_troff_state();
584          fflush(stderr);
585        }
586    #endif
587      }
588    #if defined(DEBUGGING)
589      if (debug_state)
590        if (top->is_diversion) {
591          fprintf(stderr, "in diversion level = %d\n", input_stack::get_div_level());
592          fflush(stderr);
593        }
594    #endif
595    }
596    
597    statem *get_diversion_state()
598    {
599      return input_stack::get_diversion_state();
600    }
601    
602    statem *input_stack::get_diversion_state()
603    {
604      if (diversion_state == NULL)
605        return NULL;
606      else
607        return new statem(diversion_state);
608  }  }
609    
610  input_iterator *input_stack::get_arg(int i)  input_iterator *input_stack::get_arg(int i)
# Line 613  void input_stack::end_file() Line 683  void input_stack::end_file()
683    for (input_iterator **pp = &top; *pp != &nil_iterator; pp = &(*pp)->next)    for (input_iterator **pp = &top; *pp != &nil_iterator; pp = &(*pp)->next)
684      if ((*pp)->is_file()) {      if ((*pp)->is_file()) {
685        input_iterator *tem = *pp;        input_iterator *tem = *pp;
686          check_end_diversion(tem);
687        *pp = (*pp)->next;        *pp = (*pp)->next;
688        delete tem;        delete tem;
689        level--;        level--;
# Line 627  void input_stack::clear() Line 698  void input_stack::clear()
698      if (top->is_boundary())      if (top->is_boundary())
699        nboundaries++;        nboundaries++;
700      input_iterator *tem = top;      input_iterator *tem = top;
701        check_end_diversion(tem);
702      top = top->next;      top = top->next;
703      level--;      level--;
704      delete tem;      delete tem;
# Line 647  void input_stack::pop_macro() Line 719  void input_stack::pop_macro()
719        nboundaries++;        nboundaries++;
720      is_macro = top->is_macro();      is_macro = top->is_macro();
721      input_iterator *tem = top;      input_iterator *tem = top;
722        check_end_diversion(tem);
723      top = top->next;      top = top->next;
724      level--;      level--;
725      delete tem;      delete tem;
# Line 1031  public: Line 1104  public:
1104    int same(node *);    int same(node *);
1105    const char *type();    const char *type();
1106    int force_tprint();    int force_tprint();
1107      int is_tag();
1108  };  };
1109    
1110  int non_interpreted_char_node::same(node *nd)  int non_interpreted_char_node::same(node *nd)
# Line 1048  int non_interpreted_char_node::force_tpr Line 1122  int non_interpreted_char_node::force_tpr
1122    return 0;    return 0;
1123  }  }
1124    
1125    int non_interpreted_char_node::is_tag()
1126    {
1127      return 0;
1128    }
1129    
1130  non_interpreted_char_node::non_interpreted_char_node(unsigned char n) : c(n)  non_interpreted_char_node::non_interpreted_char_node(unsigned char n) : c(n)
1131  {  {
1132    assert(n != 0);    assert(n != 0);
# Line 1495  public: Line 1574  public:
1574    int same(node *);    int same(node *);
1575    const char *type();    const char *type();
1576    int force_tprint();    int force_tprint();
1577      int is_tag();
1578  };  };
1579    
1580  token_node::token_node(const token &t) : tk(t)  token_node::token_node(const token &t) : tk(t)
# Line 1526  int token_node::force_tprint() Line 1606  int token_node::force_tprint()
1606    return 0;    return 0;
1607  }  }
1608    
1609    int token_node::is_tag()
1610    {
1611      return 0;
1612    }
1613    
1614  token::token() : nd(0), type(TOKEN_EMPTY)  token::token() : nd(0), type(TOKEN_EMPTY)
1615  {  {
1616  }  }
# Line 2579  int node::reread(int *) Line 2664  int node::reread(int *)
2664    return 0;    return 0;
2665  }  }
2666    
2667    int global_diverted_space = 0;
2668    
2669  int diverted_space_node::reread(int *bolp)  int diverted_space_node::reread(int *bolp)
2670  {  {
2671      global_diverted_space = 1;
2672    if (curenv->get_fill())    if (curenv->get_fill())
2673      trapping_blank_line();      trapping_blank_line();
2674    else    else
2675      curdiv->space(n);      curdiv->space(n);
2676      global_diverted_space = 0;
2677    *bolp = 1;    *bolp = 1;
2678    return 1;    return 1;
2679  }  }
# Line 2641  void process_input_stack() Line 2730  void process_input_stack()
2730              tok.next();              tok.next();
2731            } while (tok.white_space());            } while (tok.white_space());
2732            symbol nm = get_name();            symbol nm = get_name();
2733    #if defined(DEBUGGING)
2734              if (debug_state) {
2735                if (! nm.is_null()) {
2736                  if (strcmp(nm.contents(), "test") == 0) {
2737                    fprintf(stderr, "found it!\n");
2738                    fflush(stderr);
2739                  }
2740                  fprintf(stderr, "interpreting [%s]", nm.contents());
2741                  if (strcmp(nm.contents(), "di") == 0 && topdiv != curdiv)
2742                    fprintf(stderr, " currently in diversion: %s",
2743                            curdiv->get_diversion_name());
2744                  fprintf(stderr, "\n");
2745                  fflush(stderr);
2746                }
2747              }
2748    #endif
2749            if (nm.is_null())            if (nm.is_null())
2750              skip_line();              skip_line();
2751            else            else {
2752              interpolate_macro(nm);              interpolate_macro(nm);
2753    #if defined(DEBUGGING)
2754                if (debug_state) {
2755                  fprintf(stderr, "finished interpreting [%s] and environment state is\n", nm.contents());
2756                  curenv->dump_troff_state();
2757                }
2758    #endif
2759              }
2760            suppress_next = 1;            suppress_next = 1;
2761          }          }
2762          else {          else {
# Line 2652  void process_input_stack() Line 2764  void process_input_stack()
2764              ;              ;
2765            else {            else {
2766              for (;;) {              for (;;) {
2767    #if defined(DEBUGGING)
2768                  if (debug_state) {
2769                    fprintf(stderr, "found [%c]\n", ch); fflush(stderr);
2770                  }
2771    #endif
2772                curenv->add_char(charset_table[ch]);                curenv->add_char(charset_table[ch]);
2773                tok.next();                tok.next();
2774                if (tok.type != token::TOKEN_CHAR)                if (tok.type != token::TOKEN_CHAR)
# Line 3029  macro::~macro() Line 3146  macro::~macro()
3146  }  }
3147    
3148  macro::macro()  macro::macro()
3149    : is_a_diversion(0)
3150  {  {
3151    if (!input_stack::get_location(1, &filename, &lineno)) {    if (!input_stack::get_location(1, &filename, &lineno)) {
3152      filename = 0;      filename = 0;
# Line 3041  macro::macro() Line 3159  macro::macro()
3159    
3160  macro::macro(const macro &m)  macro::macro(const macro &m)
3161  : p(m.p), filename(m.filename), lineno(m.lineno), len(m.len),  : p(m.p), filename(m.filename), lineno(m.lineno), len(m.len),
3162    empty_macro(m.empty_macro)    empty_macro(m.empty_macro), is_a_diversion(m.is_a_diversion)
3163  {  {
3164    if (p != 0)    if (p != 0)
3165      p->count++;      p->count++;
3166  }  }
3167    
3168    macro::macro(int is_div)
3169      : is_a_diversion(is_div)
3170    {
3171      if (!input_stack::get_location(1, &filename, &lineno)) {
3172        filename = 0;
3173        lineno = 0;
3174      }
3175      len = 0;
3176      empty_macro = 1;
3177      p = 0;
3178    }
3179    
3180    int macro::is_diversion()
3181    {
3182      return is_a_diversion;
3183    }
3184    
3185  macro &macro::operator=(const macro &m)  macro &macro::operator=(const macro &m)
3186  {  {
3187    // don't assign object    // don't assign object
# Line 3059  macro &macro::operator=(const macro &m) Line 3194  macro &macro::operator=(const macro &m)
3194    lineno = m.lineno;    lineno = m.lineno;
3195    len = m.len;    len = m.len;
3196    empty_macro = m.empty_macro;    empty_macro = m.empty_macro;
3197      is_a_diversion = m.is_a_diversion;
3198    return *this;    return *this;
3199  }  }
3200    
# Line 3209  public: Line 3345  public:
3345    void backtrace();    void backtrace();
3346    void save_compatible_flag(int f) { saved_compatible_flag = f; }    void save_compatible_flag(int f) { saved_compatible_flag = f; }
3347    int get_compatible_flag() { return saved_compatible_flag; }    int get_compatible_flag() { return saved_compatible_flag; }
3348      int is_diversion();
3349  };  };
3350    
3351  string_iterator::string_iterator(const macro &m, const char *p, symbol s)  string_iterator::string_iterator(const macro &m, const char *p, symbol s)
3352  : mac(m), how_invoked(p),  : input_iterator(m.is_a_diversion), mac(m), how_invoked(p), newline_flag(0),
3353    newline_flag(0), lineno(1), nm(s)    lineno(1), nm(s)
3354  {  {
3355    count = mac.len;    count = mac.len;
3356    if (count != 0) {    if (count != 0) {
# Line 3239  string_iterator::string_iterator() Line 3376  string_iterator::string_iterator()
3376    count = 0;    count = 0;
3377  }  }
3378    
3379    int string_iterator::is_diversion()
3380    {
3381      return mac.is_diversion();
3382    }
3383    
3384  int string_iterator::fill(node **np)  int string_iterator::fill(node **np)
3385  {  {
3386    if (newline_flag)    if (newline_flag)
# Line 3254  int string_iterator::fill(node **np) Line 3396  int string_iterator::fill(node **np)
3396    if (*p == '\0') {    if (*p == '\0') {
3397      if (np)      if (np)
3398        *np = nd->copy();        *np = nd->copy();
3399        if (is_diversion())
3400          (*np)->div_nest_level = input_stack::get_div_level();
3401        else
3402          (*np)->div_nest_level = 0;
3403      nd = nd->next;      nd = nd->next;
3404      eptr = ptr = p + 1;      eptr = ptr = p + 1;
3405      count--;      count--;
# Line 3441  public: Line 3587  public:
3587    void add_arg(const macro &m);    void add_arg(const macro &m);
3588    void shift(int n);    void shift(int n);
3589    int is_macro() { return 1; }    int is_macro() { return 1; }
3590      int is_diversion();
3591  };  };
3592    
3593  input_iterator *macro_iterator::get_arg(int i)  input_iterator *macro_iterator::get_arg(int i)
# Line 4953  public: Line 5100  public:
5100    int same(node *);    int same(node *);
5101    const char *type();    const char *type();
5102    int force_tprint();    int force_tprint();
5103      int is_tag();
5104  };  };
5105    
5106  non_interpreted_node::non_interpreted_node(const macro &m) : mac(m)  non_interpreted_node::non_interpreted_node(const macro &m) : mac(m)
# Line 4979  int non_interpreted_node::force_tprint() Line 5127  int non_interpreted_node::force_tprint()
5127    return 0;    return 0;
5128  }  }
5129    
5130    int non_interpreted_node::is_tag()
5131    {
5132      return 0;
5133    }
5134    
5135  node *non_interpreted_node::copy()  node *non_interpreted_node::copy()
5136  {  {
5137    return new non_interpreted_node(mac);    return new non_interpreted_node(mac);
# Line 5363  int do_if_request() Line 5516  int do_if_request()
5516      environment env2(curenv);      environment env2(curenv);
5517      environment *oldenv = curenv;      environment *oldenv = curenv;
5518      curenv = &env1;      curenv = &env1;
5519        suppress_push = 1;
5520      for (int i = 0; i < 2; i++) {      for (int i = 0; i < 2; i++) {
5521        for (;;) {        for (;;) {
5522          tok.next();          tok.next();
# Line 5386  int do_if_request() Line 5540  int do_if_request()
5540      delete_node_list(n2);      delete_node_list(n2);
5541      curenv = oldenv;      curenv = oldenv;
5542      have_input = 0;      have_input = 0;
5543        suppress_push = 0;
5544      tok.next();      tok.next();
5545    }    }
5546    else {    else {
# Line 5898  const char *input_char_description(int c Line 6053  const char *input_char_description(int c
6053    return buf;    return buf;
6054  }  }
6055    
6056    void tag()
6057    {
6058      if (!tok.newline() && !tok.eof()) {
6059        string s;
6060        int c;
6061        for (;;) {
6062          c = get_copy(0);
6063          if (c == '"') {
6064            c = get_copy(0);
6065            break;
6066          }
6067          if (c != ' ' && c != '\t')
6068            break;
6069        }
6070        s = "x X ";
6071        for (; c != '\n' && c != EOF; c = get_copy(0))
6072          s += (char)c;
6073        s += '\n';
6074        if (is_html)
6075          curenv->add_node(new tag_node(s, 0));
6076      }
6077      tok.next();
6078    }
6079    
6080    void taga()
6081    {
6082      if (!tok.newline() && !tok.eof()) {
6083        string s;
6084        int c;
6085        for (;;) {
6086          c = get_copy(0);
6087          if (c == '"') {
6088            c = get_copy(0);
6089            break;
6090          }
6091          if (c != ' ' && c != '\t')
6092            break;
6093        }
6094        s = "x X ";
6095        for (; c != '\n' && c != EOF; c = get_copy(0))
6096          s += (char)c;
6097        s += '\n';
6098        if (is_html)
6099          curenv->add_node(new tag_node(s, 1));
6100      }
6101      tok.next();
6102    }
6103    
6104  // .tm, .tm1, and .tmc  // .tm, .tm1, and .tmc
6105    
6106  void do_terminal(int newline, int string_like)  void do_terminal(int newline, int string_like)
# Line 7066  int main(int argc, char **argv) Line 7269  int main(int argc, char **argv)
7269      { "version", no_argument, 0, 'v' },      { "version", no_argument, 0, 'v' },
7270      { 0, 0, 0, 0 }      { 0, 0, 0, 0 }
7271    };    };
7272    while ((c = getopt_long(argc, argv, "abciI:vw:W:zCEf:m:n:o:r:d:F:M:T:tqs:RU",  #if defined(DEBUGGING)
7273                            long_options, 0))  #define DEBUG_OPTION "D"
7274    #endif
7275      while ((c = getopt_long(argc, argv,
7276                              "abciI:vw:W:zCEf:m:n:o:r:d:F:M:T:tqs:RU"
7277                              DEBUG_OPTION, long_options, 0))
7278           != EOF)           != EOF)
7279      switch(c) {      switch(c) {
7280      case 'v':      case 'v':
# Line 7160  int main(int argc, char **argv) Line 7367  int main(int argc, char **argv)
7367      case 'U':      case 'U':
7368        safer_flag = 0;   // unsafe behaviour        safer_flag = 0;   // unsafe behaviour
7369        break;        break;
7370    #if defined(DEBUGGING)
7371        case 'D':
7372          debug_state = 1;
7373          break;
7374    #endif
7375      case CHAR_MAX + 1: // --help      case CHAR_MAX + 1: // --help
7376        usage(stdout, argv[0]);        usage(stdout, argv[0]);
7377        exit(0);        exit(0);
# Line 7395  void init_input_requests() Line 7607  void init_input_requests()
7607    init_request("spreadwarn", spreadwarn_request);    init_request("spreadwarn", spreadwarn_request);
7608    init_request("substring", substring_request);    init_request("substring", substring_request);
7609    init_request("sy", system_request);    init_request("sy", system_request);
7610      init_request("tag", tag);
7611      init_request("taga", taga);
7612    init_request("tm", terminal);    init_request("tm", terminal);
7613    init_request("tm1", terminal1);    init_request("tm1", terminal1);
7614    init_request("tmc", terminal_continue);    init_request("tmc", terminal_continue);

Legend:
Removed from v.1.19  
changed lines
  Added in v.1.20

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26