From: karl@ds1.cs.umb.edu (Karl Berry)
Subject: decstation cc1plus: fatal signal
Reply-To: karl@cs.umb.edu
Organization: GNUs Not Usenet
Distribution: gnu
Date: Wed, 9 Sep 1992 13:51:59 GMT

gcc 2.2.2 -g -O on a DECstation 3100 running Ultrix 4.2a (configured as
`decstation') gets a fatal signal on the following input. 

gcc -v -O -g -c temp.cc
Reading specs from /usr/local/gnu/lib/gcc-lib/decstation/2.2.2/specs
gcc version 2.2.2
 /usr/local/gnu/lib/gcc-lib/decstation/2.2.2/cpp -lang-c++ -v -undef -D__GNUC__=2 -D__GNUG__=2 -D__cplusplus -D__ANSI_COMPAT -DMIPSEL -DR3000 -DSYSTYPE_BSD -D_SYSTYPE_BSD -Dbsd4_2 -Dhost_mips -Dmips -Dultrix -Dunix -D__ANSI_COMPAT -D__MIPSEL__ -D__R3000__ -D__SYSTYPE_BSD__ -D___SYSTYPE_BSD__ -D__bsd4_2__ -D__host_mips__ -D__mips__ -D__ultrix__ -D__unix__ -D__ANSI_COMPAT -D__MIPSEL -D__R3000 -D__SYSTYPE_BSD -D___SYSTYPE_BSD -D__bsd4_2 -D__host_mips -D__mips -D__ultrix -D__unix -D__OPTIMIZE__ -g -D__LANGUAGE
_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS -D__LANGUAGE_C__ -D__LANGUAGE_C -DLANGUAGE_C temp.cc /tmp/cca04127.i
GNU CPP version 2.2.2 [AL 1.1, MM 19] DECstation running ultrix
 /usr/local/gnu/lib/gcc-lib/decstation/2.2.2/cc1plus /tmp/cca04127.i -mgpopt -quiet -dumpbase temp.cc -g -O -version -o /tmp/cca04127.s
GNU C++ version 2.2.2 [AL 1.1, MM 19] DECstation running ultrix compiled by GNU C version 2.2.1.
gcc: Internal compiler error: program cc1plus got fatal signal 11


# 1 "main.cc"
 
 


















# 1 "table.h" 1
 
 


















# 1 "/usr/local/gnu/lib/g++-include/stdio.h" 1 3
 
 


















#pragma interface







 
 
 

# 1 "/usr/local/gnu/lib/g++-include/_G_config.h" 1 3
  





















 


















 
 

# 33 "/usr/local/gnu/lib/g++-include/stdio.h" 2 3


extern "C" {

































# 1 "/usr/include/stdio.h" 1 3
 
 


























 



























































# 1 "/usr/include/ansi_compat.h" 1 3
 



 





















 

















# 116 "/usr/include/ansi_compat.h" 3

# 89 "/usr/include/stdio.h" 2 3



typedef unsigned int	size_t;		 









			 




extern	struct	_iobuf {
	int	_cnt;
	char	*_ptr;
	char	*_base;
	int	_bufsiz;
	short	_flag;
	short	_file;
} _iob[3 ];
typedef	struct _iobuf	FILE;

typedef	long	fpos_t;

















 







 



extern int 	getc( FILE *__stream );
extern int	getchar( void );
extern int	putc( int __c, FILE *__stream);
extern int	putchar( int __c);
extern int	feof( FILE *__stream );
extern int	ferror( FILE *__stream );
extern int	fileno( FILE *__stream );
extern int	_filbuf( FILE *p);
extern int	__hide__flsbuf ( unsigned char x , FILE *p);
















typedef char *va_list;

 



extern void	clearerr( FILE *__stream); 
extern int	fclose( FILE *__stream );
extern FILE *	__hide_fdopen ( int __filedes, char *__type );
extern int	fflush( FILE *__stream );
extern int	fgetc( FILE *__stream );
extern int	fgetpos( FILE *__stream, fpos_t *__pos );
extern char *	fgets( char *__s, int __n, FILE *__stream );
extern FILE *	__hide_fopen ( const char *__filename, const char *__type );
extern int	__hide_fprintf ( FILE *__stream, const char *__format, ... );
extern int	fputc( int __c, FILE *__stream );
extern int	__hide_fputs ( const char *__s, FILE *__stream );
extern size_t	__hide_fread ( void *__ptr, size_t __size,
			size_t __nitems, FILE *__stream ); 
extern FILE *	__hide_freopen ( const char *__filename, const char *__type,
			FILE *__stream );
extern int	__hide_fscanf ( FILE *__stream, const char *__format, ... );
extern int	fseek( FILE *__stream, long __offset, int __ptrname );
extern int	fsetpos( FILE *__stream, const fpos_t *__pos );
extern long	__hide_ftell ( FILE *__stream );
extern size_t	__hide_fwrite ( const void *__ptr, size_t __size,
			size_t __nitems, FILE *__stream );
extern char *	gets( char *__s );	
extern void	__hide_perror ( const char *__s );
extern FILE  *	__hide_popen (const char *__command, const char *__type );
extern int	__hide_printf ( const char *__format, ... );	
extern int	__hide_puts ( const char *__s );	
extern int	remove( const char *__filename );
extern int	rename( const char *__from, const char *__to );
extern void	__hide_rewind ( FILE *__stream );
extern int	__hide_scanf ( const char *__format, ... );	
extern void	__hide_setbuf ( FILE *__stream, char *__buf );
extern int	__hide_setvbuf ( FILE *__stream, char *__buf,
			int __type, size_t __size );
extern int	__hide_sscanf ( const char *__s, const char *__format, ... );
extern FILE *	tmpfile( void );	
extern char *	tmpnam( char *__s );
extern int	ungetc( int __c, FILE *__stream );
extern int	__hide_vfprintf ( FILE *__stream, const char *__format, va_list __ap );
extern int	__hide_vprintf ( const char *__format, va_list __ap );
extern int	__hide_vsprintf ( char *__s, const char *__format, va_list __ap);


extern char *	__hide_tempnam ( const char *__dir, const char *__pfx);
extern int	__hide_putw ( int __w, FILE *__stream );
extern int	getw(FILE *__stream);
extern int	pclose( FILE *__stream );


# 298 "/usr/include/stdio.h" 3



 
extern int	__hide_sprintf ( char *__s, const char *__format, ... );



















# 69 "/usr/local/gnu/lib/g++-include/stdio.h" 2 3







































}

extern "C" {

int    fclose(FILE*);
FILE*  fdopen(int, const char*);
int    fflush(FILE*);
int    fgetc(FILE*);
char*  fgets(char*, int, FILE *);
FILE*  fopen(const char*, const char*);
int    fprintf(FILE*, const char* ...);
int    fputc(int, FILE*);
int    fputs(const char*, FILE*);
unsigned int   fread(void*, unsigned int  , unsigned int  , FILE*);



FILE*  freopen(const char*, const char*, FILE*);

int    fscanf(FILE*, const char* ...);
int    fseek(FILE*, long, int);
long   ftell(FILE *);
unsigned int   fwrite(const void*, unsigned int  , unsigned int  , FILE*);
char*  gets(char*);
int    getw(FILE*);
int    pclose(FILE*);
void   perror(const char*);
FILE*  popen(const char*, const char*);
int    printf(const char* ...);
int    puts(const char*);
int    putw(int, FILE*);
int    rewind(FILE*);
int    scanf(const char* ...);
void   setbuf(FILE*, char*);
void   setbuffer(FILE*, char*, int);
int    setlinebuf(FILE*);
int    setvbuf(FILE*, char*, int, unsigned int  );
int    sscanf(char*, const char* ...);
FILE*  tmpfile();
int    ungetc(int, FILE*);
int    vfprintf (...) ;
int    vprintf (...) ;
int  sprintf (...) ;
int  vsprintf (...) ;

extern int _filbuf (...) ;
extern int _flsbuf (...) ;

}


















# 21 "table.h" 2

# 1 "/usr/local/gnu/lib/g++-include/stdlib.h" 1 3





# 1 "/usr/local/gnu/lib/g++-include/stddef.h" 1 3


extern "C" {



# 1 "/usr/local/gnu/lib/gcc-lib/decstation/2.2.2/include/stddef.h" 1 3



 









 


 





 


















 


typedef long int ptrdiff_t;









 


 





# 87 "/usr/local/gnu/lib/gcc-lib/decstation/2.2.2/include/stddef.h" 3








 





















 


typedef int wchar_t;












 









 






# 7 "/usr/local/gnu/lib/g++-include/stddef.h" 2 3




}

# 6 "/usr/local/gnu/lib/g++-include/stdlib.h" 2 3


extern "C" {

int       abs(int);


void volatile abort(void);




double    atof(const char*);
int       atoi(const char*);
long      atol(const char*);

int       atexit(auto void (*p) (void));
int       bsearch (const void *, const void *, unsigned int  , 
                   unsigned int  , auto int (*ptf)(const void*, const void*));
void*     calloc(unsigned int  , unsigned int  );
void      cfree(void*);


void volatile exit(int);




char*     fcvt(double, int, int*, int*);
void      free(void*);
char*     getenv(const char*);
int       getopt(int, char * const *, const char*);
int       getpw(int, char*);
char*     gcvt(double, int, char*);
char*     ecvt(double, int, int*, int*);
extern char**   environ;

long      labs(long);
void*     malloc(unsigned int  );
unsigned int      malloc_usable_size(void*);
int       putenv(const char*);
extern char*    optarg;
extern int      opterr;
extern int      optind;
void      qsort(void*, unsigned int  , unsigned int  , auto int (*ptf)(void*,void*));
int       rand(void);
void*     realloc(void*, unsigned int  );
int       setkey(const char*);
int       srand(unsigned int);
double    strtod(const char*, char**);
long      strtol(const char*, char**, int);
unsigned long stroul(const char**, int);
int       system(const char*);

long      random(void);
void      srandom(int);
char*     setstate(char*);
char*     initstate(unsigned, char*, int);

double    drand48(void);
void      lcong48(short*);
long      jrand48(short*);
long      lrand48(void);
long      mrand48(void);
long      nrand48(short*);
short*    seed48(short*);
void      srand48(long);

char*     ctermid(char*);
char*     cuserid(char*);
char*     tempnam(const char*, const char*);
char*     tmpnam(char*);

}

# 22 "table.h" 2

# 1 "../include/assert.h" 1 3
 
 





















volatile

void assertion_failed(int, const char *);

inline void do_assert(int expr, int line, const char *file)
{
  if (!expr)
    assertion_failed(line, file);
}









# 23 "table.h" 2

# 1 "/usr/local/gnu/lib/g++-include/ctype.h" 1 3

extern "C" {
# 1 "/usr/include/ctype.h" 1 3
 




 


























 







































extern	unsigned short *_pctype;
extern  unsigned short _ctype__[];


 



int	isalnum( int __c );
int	isalpha( int __c );
int	isascii( int __c );
int	iscntrl( int __c );
int	isdigit( int __c );
int	isgraph( int __c );
int	islower( int __c );
int	isprint( int __c );
int	ispunct( int __c );
int	isspace( int __c );
int	isupper( int __c );
int	isxdigit( int __c );
int	toascii( int __c );
int	_tolower( int __c );
int	_toupper( int __c );
int	tolower( int __c );
int	toupper( int __c );























# 3 "/usr/local/gnu/lib/g++-include/ctype.h" 2 3


extern int toupper (...) ;


extern int tolower (...) ;

}
# 24 "table.h" 2

# 1 "/usr/local/gnu/lib/g++-include/errno.h" 1 3


extern "C" {





# 1 "/usr/include/errno.h" 1 3
 

 


























 























 




































 



 



 

	 













	 













	 



 




 




 



 




 


 



 




 
















 


extern int errno;

# 9 "/usr/local/gnu/lib/g++-include/errno.h" 2 3




extern char*    sys_errlist[];
extern int      sys_nerr;

extern int      errno;

void      perror(const char*);
char*     strerr(int);


}


# 25 "table.h" 2


# 1 "../include/cset.h" 1
 
 



















# 1 "/usr/local/gnu/lib/gcc-lib/decstation/2.2.2/include/limits.h" 1 3
 


# 1 "/usr/include/limits.h" 1 3
 
 


























 










































































 


















# 1 "/usr/include/ansi_compat.h" 1 3
 



 





















 

















# 116 "/usr/include/ansi_compat.h" 3

# 123 "/usr/include/limits.h" 2 3































					 









































 




# 228 "/usr/include/limits.h" 3


















 





























 







































 






 

















 



 








					 

					 
					 





 



				 



				 








				 
				 








				 
				 
				 


 









				 

				 


				 

				 


				 
				 

# 4 "/usr/local/gnu/lib/gcc-lib/decstation/2.2.2/include/limits.h" 2 3





 



 



 



 





 



 












 





 



 





 



 






 




 





 






# 22 "../include/cset.h" 2







enum cset_builtin { CSET_BUILTIN };

class cset {
public:
  cset();
  cset(cset_builtin);
  cset(const char *);
  cset(const unsigned char *);
  int operator()(unsigned char) const;

  cset &operator|=(const cset &);
  cset &operator|=(unsigned char);

  friend class cset_init;
private:
  char v[255 +1];
  void clear();
};

inline int cset::operator()(unsigned char c) const
{
  return v[c];
}

inline cset &cset::operator|=(unsigned char c)
{
  v[c] = 1;
  return *this;
}

extern cset csalpha;
extern cset csupper;
extern cset cslower;
extern cset csdigit;
extern cset csxdigit;
extern cset csspace;
extern cset cspunct;
extern cset csalnum;
extern cset csprint;
extern cset csgraph;
extern cset cscntrl;

static class cset_init {
  static int initialised;
public:
  cset_init();
} _cset_init;
# 27 "table.h" 2

# 1 "../include/cmap.h" 1
 
 






















enum cmap_builtin { CMAP_BUILTIN };

class cmap {
public:
  cmap();
  cmap(cmap_builtin);
  int operator()(unsigned char) const;
  unsigned char &operator[](unsigned char);

  friend class cmap_init;
private:
  unsigned char v[255 +1];
};

inline int cmap::operator()(unsigned char c) const
{
  return v[c];
}

inline unsigned char &cmap::operator[](unsigned char c)
{
  return v[c];
}

extern cmap cmlower;
extern cmap cmupper;

static class cmap_init {
  static int initialised;
public:
  cmap_init();
} _cmap_init;
# 28 "table.h" 2

# 1 "../include/stringclass.h" 1
 
 


















# 1 "/usr/local/gnu/lib/g++-include/string.h" 1 3














extern "C" {

char*     strcat(char*, const char*);
char*     strchr(const char*, int);
int       strcmp(const char*, const char*);
int       strcoll(const char*, const char*);
char*     strcpy(char*, const char*);
unsigned int      strcspn(const char*, const char*);
char*     strdup(const char*);
 
 
 
 
unsigned int      strlen(const char*);
char*     strncat(char*, const char*, unsigned int  );
int       strncmp(const char*, const char*, unsigned int  );
char*     strncpy(char*, const char*, unsigned int  );
char*     strpbrk(const char*, const char*);
char*     strrchr(const char*, int);
unsigned int      strspn(const char*, const char*);
char*     strstr(const char*, const char *);
char*     strtok(char*, const char*);
unsigned int      strxfrm(char*, const char*, unsigned int  );

char*     index(const char*, int);
char*     rindex(const char*, int);
}

# 1 "/usr/local/gnu/lib/g++-include/memory.h" 1 3







extern "C" {

void*     memalign (...) ;
void*     memccpy (...) ;
void*     memchr (...) ;
int       memcmp (...) ;
void*     memcpy (...) ;
void*     memmove (...) ;
void*     memset (...) ;
int       ffs (...) ;
unsigned int     getpagesize (...) ;
void*     valloc (...) ;

void      bcopy (...) ;
int       bcmp (...) ;
void      bzero (...) ;
}














# 43 "/usr/local/gnu/lib/g++-include/string.h" 2 3



# 21 "../include/stringclass.h" 2

# 1 "/usr/local/gnu/lib/g++-include/stdio.h" 1 3
 
 
















# 174 "/usr/local/gnu/lib/g++-include/stdio.h" 3

# 22 "../include/stringclass.h" 2

# 1 "../include/assert.h" 1 3
 
 


















# 33 "../include/assert.h" 3









# 23 "../include/stringclass.h" 2


class string {
public:
  string();
  string(const string &);
  string(const char *);
  string(const char *, int);
  string(char);

  ~string();
  
  string &operator=(const string &);
  string &operator=(const char *);
  string &operator=(char);

  string &operator+=(const string &);
  string &operator+=(const char *);
  string &operator+=(char);
  void append(const char *, int);
  
  int length() const;
  int empty() const;
  int operator*() const;

  string substring(int i, int n) const;

  char &operator[](int);
  char operator[](int) const;

  void set_length(int i);
  const char *contents() const;
  int search(char) const;
  char *extract() const;
  void clear();
  void move(string &);

  friend string operator+(const string &, const string &);
  friend string operator+(const string &, const char *);
  friend string operator+(const char *, const string &);
  friend string operator+(const string &, char);
  friend string operator+(char, const string &);

  friend int operator==(const string &, const string &);
  friend int operator!=(const string &, const string &);
  friend int operator<=(const string &, const string &);
  friend int operator<(const string &, const string &);
  friend int operator>=(const string &, const string &);
  friend int operator>(const string &, const string &);

private:
  char *ptr;
  int len;
  int sz;

  string(const char *, int, const char *, int);	 
  void grow1();
};


inline char &string::operator[](int i)
{
  do_assert(i >= 0 && i < len, 85, "../include/stringclass.h") ;
  return ptr[i];
}

inline char string::operator[](int i) const
{
  do_assert(i >= 0 && i < len, 91, "../include/stringclass.h") ;
  return ptr[i];
}

inline int string::length() const
{
  return len;
}

inline int string::empty() const
{
  return len == 0;
}

inline int string::operator*() const
{
  return len;
}

inline const char *string::contents() const
{
  return  ptr;
}

inline string operator+(const string &s1, const string &s2)
{
  return string(s1.ptr, s1.len, s2.ptr, s2.len);
}

inline string operator+(const string &s1, const char *s2)
{
  if (s2 == 0)
    return s1;
  else
    return string(s1.ptr, s1.len, s2, strlen(s2));
}

inline string operator+(const char *s1, const string &s2)
{
  if (s1 == 0)
    return s2;
  else
    return string(s1, strlen(s1), s2.ptr, s2.len);
}

inline string operator+(const string &s, char c)
{
  return string(s.ptr, s.len, &c, 1);
}

inline string operator+(char c, const string &s)
{
  return string(&c, 1, s.ptr, s.len);
}

inline int operator==(const string &s1, const string &s2)
{
  return (s1.len == s2.len 
	  && (s1.len == 0 || memcmp(s1.ptr, s2.ptr, s1.len) == 0));
}

inline int operator!=(const string &s1, const string &s2)
{
  return (s1.len != s2.len 
	  || (s1.len != 0 && memcmp(s1.ptr, s2.ptr, s1.len) != 0));
}

inline string string::substring(int i, int n) const
{
  do_assert(i >= 0 && i + n <= len, 160, "../include/stringclass.h") ;
  return string(ptr + i, n);
}

inline string &string::operator+=(char c)
{
  if (len >= sz)
    grow1();
  ptr[len++] = c;
  return *this;
}

void put_string(const string &, FILE *);

string as_string(int);
# 29 "table.h" 2

# 1 "../include/errarg.h" 1
 
 


















class errarg {
  enum { EMPTY, STRING, CHAR, INTEGER, DOUBLE } type;
  union {
    const char *s;
    int n;
    char c;
    double d;
  };
 public:
  errarg();
  errarg(const char *);
  errarg(char);
  errarg(unsigned char);
  errarg(int);
  errarg(double);
  int empty() const;
  void print() const;
};

extern errarg empty_errarg;

extern void errprint(const char *,
		     const errarg &arg1 = empty_errarg,
		     const errarg &arg2 = empty_errarg,
		     const errarg &arg3 = empty_errarg);

# 30 "table.h" 2

# 1 "../include/error.h" 1
 
 


















extern void fatal_with_file_and_line(const char *filename, int lineno,
				     const char *format,
				     const errarg &arg1 = empty_errarg,
				     const errarg &arg2 = empty_errarg,
				     const errarg &arg3 = empty_errarg);

extern void error_with_file_and_line(const char *filename, int lineno,
				     const char *format,
				     const errarg &arg1 = empty_errarg,
				     const errarg &arg2 = empty_errarg,
				     const errarg &arg3 = empty_errarg);

extern void warning_with_file_and_line(const char *filename, int lineno,
				     const char *format,
				     const errarg &arg1 = empty_errarg,
				     const errarg &arg2 = empty_errarg,
				     const errarg &arg3 = empty_errarg);

extern void fatal(const char *,
		  const errarg &arg1 = empty_errarg,
		  const errarg &arg2 = empty_errarg,
		  const errarg &arg3 = empty_errarg);

extern void error(const char *,
		  const errarg &arg1 = empty_errarg,
		  const errarg &arg2 = empty_errarg,
		  const errarg &arg3 = empty_errarg);

extern void warning(const char *,
		    const errarg &arg1 = empty_errarg,
		    const errarg &arg2 = empty_errarg,
		    const errarg &arg3 = empty_errarg);


extern const char *program_name;
extern int current_lineno;
extern const char *current_filename;

# 31 "table.h" 2

# 1 "../include/lib.h" 1
 
 


















extern "C" {
  char *strerror(int);

  const char *itoa(int);
  const char *iftoa(int, int);

};










char *strsave(const char *s);
int is_prime(unsigned);

# 1 "/usr/local/gnu/lib/g++-include/stdio.h" 1 3
 
 
















# 174 "/usr/local/gnu/lib/g++-include/stdio.h" 3

# 41 "../include/lib.h" 2


FILE *xtmpfile();

int interpret_lf_args(const char *p);

extern char illegal_char_table[];

inline int illegal_input_char(int c)
{
  return c >= 0 && illegal_char_table[c];
}


# 1 "/usr/local/gnu/lib/gcc-lib/decstation/2.2.2/include/limits.h" 1 3
 




# 88 "/usr/local/gnu/lib/gcc-lib/decstation/2.2.2/include/limits.h" 3

# 55 "../include/lib.h" 2





 

















 




 







 



# 32 "table.h" 2


struct inc_number {
  short inc;
  short val;
};

struct entry_modifier {
  inc_number point_size;
  inc_number vertical_spacing;
  string font;
  enum { CENTER, TOP, BOTTOM } vertical_alignment;
  char zero_width;
  char stagger;

  entry_modifier();
  ~entry_modifier();
};

enum format_type {
  FORMAT_LEFT, 
  FORMAT_CENTER, 
  FORMAT_RIGHT, 
  FORMAT_NUMERIC,
  FORMAT_ALPHABETIC,
  FORMAT_SPAN, 
  FORMAT_VSPAN,
  FORMAT_HLINE,
  FORMAT_DOUBLE_HLINE
};

struct entry_format : entry_modifier {
  format_type type;

  entry_format(format_type);
  entry_format();
  void debug_print() const;
};

struct table_entry;
struct horizontal_span;
struct stuff;
struct vertical_rule;

class table {
  unsigned flags;
  int nrows;
  int ncolumns;
  int linesize;
  char delim[2];
  vertical_rule *vrule_list;
  stuff *stuff_list;
  horizontal_span *span_list;
  table_entry *entry_list;
  table_entry ***entry;
  char **vline;
  char *row_is_all_lines;
  string *minimum_width;
  int *column_separation;
  char *equal;
  int left_separation;
  int right_separation;
  int allocated_rows;
  void build_span_list();
  void do_hspan(int r, int c);
  void do_vspan(int r, int c);
  void allocate(int r);
  void compute_widths();
  void divide_span(int, int);
  void sum_columns(int, int);
  void compute_separation_factor();
  void compute_column_positions();
  void do_row(int);
  void init_output();
  void add_stuff(stuff *);
  void do_top();
  void do_bottom();
  void do_vertical_rules();
  void build_vrule_list();
  void add_vertical_rule(int, int, int, int);
  void define_bottom_macro();
  int vline_spanned(int r, int c);
  int row_begins_section(int);
  int row_ends_section(int);
  void make_columns_equal();
  void compute_vrule_top_adjust(int, int, string &);
  void compute_vrule_bot_adjust(int, int, string &);
  void determine_row_type();
public:
   
  enum {
    CENTER = 01,
    EXPAND = 02,
    BOX = 04,
    ALLBOX = 010,
    DOUBLEBOX = 020
    };
  table(int nc, unsigned flags, int linesize);
  ~table();

  void add_text_line(int r, const string &, const char *, int);
  void add_single_hline(int r);
  void add_double_hline(int r);
  void add_entry(int r, int c, const string &, const entry_format *,
		 const char *, int lineno);
  void add_vlines(int r, const char *);
  void check();
  void print();
  void set_minimum_width(int c, const string &w);
  void set_column_separation(int c, int n);
  void set_equal_column(int c);
  void set_delim(char c1, char c2);
  void print_single_hline(int r);
  void print_double_hline(int r);
  int get_nrows();
};

void set_troff_location(const char *, int);
# 21 "main.cc" 2





static int compatible_flag = 0;

class table_input {
  FILE *fp;
  enum { START, MIDDLE, REREAD_T, REREAD_TE, REREAD_E, END, ERROR } state;
  string unget_stack;
public:
  table_input(FILE *);
  int get();
  int ended() { return unget_stack.empty() && state == END; }
  void unget(char);
};

table_input::table_input(FILE *p)
: fp(p), state(START)
{
}

void table_input::unget(char c)
{
  do_assert(c != '\0', 46, "main.cc") ;
  unget_stack += c;
  if (c == '\n')
    current_lineno--;
}

int table_input::get()
{
  int len = unget_stack.length();
  if (len != 0) {
    unsigned char c = unget_stack[len - 1];
    unget_stack.set_length(len - 1);
    if (c == '\n')
      current_lineno++;
    return c;
  }
  int c;
  for (;;) {
    switch (state) {
    case START:
      if ((c = 	(--(fp)->_cnt>=0? *(fp)->_ptr++&0377:_filbuf(fp)) ) == '.') {
	if ((c = 	(--(fp)->_cnt>=0? *(fp)->_ptr++&0377:_filbuf(fp)) ) == 'T') {
	  if ((c = 	(--(fp)->_cnt>=0? *(fp)->_ptr++&0377:_filbuf(fp)) ) == 'E') {
	    if (compatible_flag) {
	      state = END;
	      return (-1) ;
	    }
	    else {
	      c = 	(--(fp)->_cnt>=0? *(fp)->_ptr++&0377:_filbuf(fp)) ;
	      if (c != (-1) )
		ungetc(c, fp);
	      if (c == (-1)  || c == ' ' || c == '\n') {
		state = END;
		return (-1) ;
	      }
	      state = REREAD_TE;
	      return '.';
	    }
	  }
	  else {
	    if (c != (-1) )
	      ungetc(c, fp);
	    state = REREAD_T;
	    return '.';
	  }
	}
	else {
	  if (c != (-1) )
	    ungetc(c, fp);
	  state = MIDDLE;
	  return '.';
	}
      }
      else if (c == (-1) ) {
	state = ERROR;
	return (-1) ;
      }
      else {
	if (c == '\n')
	  current_lineno++;
	else {
	  state = MIDDLE;
	  if (c == '\0') {
	    error("illegal input character code 0");
	    break;
	  }
	}
	return c;
      }
      break;
    case MIDDLE:
       
      if ((c = 	(--(fp)->_cnt>=0? *(fp)->_ptr++&0377:_filbuf(fp)) ) == '\\') {
	c = 	(--(fp)->_cnt>=0? *(fp)->_ptr++&0377:_filbuf(fp)) ;
	if (c == '\n')
	  c = 	(--(fp)->_cnt>=0? *(fp)->_ptr++&0377:_filbuf(fp)) ;		 
	else {
	  if (c != (-1) )
	    ungetc(c, fp);
	  c = '\\';
	}
      }
      if (c == (-1) ) {
	state = ERROR;
	return (-1) ;
      }
      else {
	if (c == '\n') {
	  state = START;
	  current_lineno++;
	}
	else if (c == '\0') {
	  error("illegal input character code 0");
	  break;
	}
	return c;
      }
    case REREAD_T:
      state = MIDDLE;
      return 'T';
    case REREAD_TE:
      state = REREAD_E;
      return 'T';
    case REREAD_E:
      state = MIDDLE;
      return 'E';
    case END:
    case ERROR:
      return (-1) ;
    }
  }
}

void process_input_file(FILE *);
void process_table(table_input &in);

void process_input_file(FILE *fp)
{
  enum { START, MIDDLE, HAD_DOT, HAD_T, HAD_TS, HAD_l, HAD_lf } state;
  state = START;
  int c;
  while ((c = 	(--(fp)->_cnt>=0? *(fp)->_ptr++&0377:_filbuf(fp)) ) != (-1) )
    switch (state) {
    case START:
      if (c == '.')
	state = HAD_DOT;
      else {
	if (c == '\n')
	  current_lineno++;
	else
	  state = MIDDLE;
	(--((&_iob[1]) )->_cnt>=0? ((int)(*(unsigned char *)((&_iob[1]) )->_ptr++=(c))):	_flsbuf((unsigned char)(c),(&_iob[1]) ))  ;
      }
      break;
    case MIDDLE:
      if (c == '\n') {
	current_lineno++;
	state = START;
      }
      (--((&_iob[1]) )->_cnt>=0? ((int)(*(unsigned char *)((&_iob[1]) )->_ptr++=(c))):	_flsbuf((unsigned char)(c),(&_iob[1]) ))  ;
      break;
    case HAD_DOT:
      if (c == 'T')
	state = HAD_T;
      else if (c == 'l')
	state = HAD_l;
      else {
	(--((&_iob[1]) )->_cnt>=0? ((int)(*(unsigned char *)((&_iob[1]) )->_ptr++=('.'))):	_flsbuf((unsigned char)('.'),(&_iob[1]) ))  ;
	(--((&_iob[1]) )->_cnt>=0? ((int)(*(unsigned char *)((&_iob[1]) )->_ptr++=(c))):	_flsbuf((unsigned char)(c),(&_iob[1]) ))  ;
	if (c == '\n') {
	  current_lineno++;
	  state = START;
	}
	else
	  state = MIDDLE;
      }
      break;
    case HAD_T:
      if (c == 'S')
	state = HAD_TS;
      else {
	(--((&_iob[1]) )->_cnt>=0? ((int)(*(unsigned char *)((&_iob[1]) )->_ptr++=('.'))):	_flsbuf((unsigned char)('.'),(&_iob[1]) ))  ;
	(--((&_iob[1]) )->_cnt>=0? ((int)(*(unsigned char *)((&_iob[1]) )->_ptr++=('T'))):	_flsbuf((unsigned char)('T'),(&_iob[1]) ))  ;
	(--((&_iob[1]) )->_cnt>=0? ((int)(*(unsigned char *)((&_iob[1]) )->_ptr++=(c))):	_flsbuf((unsigned char)(c),(&_iob[1]) ))  ;
	if (c == '\n') {
 	  current_lineno++;
	  state = START;
	}
	else
	  state = MIDDLE;
      }
      break;
    case HAD_TS:
      if (c == ' ' || c == '\n' || compatible_flag) {
	(--((&_iob[1]) )->_cnt>=0? ((int)(*(unsigned char *)((&_iob[1]) )->_ptr++=('.'))):	_flsbuf((unsigned char)('.'),(&_iob[1]) ))  ;
	(--((&_iob[1]) )->_cnt>=0? ((int)(*(unsigned char *)((&_iob[1]) )->_ptr++=('T'))):	_flsbuf((unsigned char)('T'),(&_iob[1]) ))  ;
	(--((&_iob[1]) )->_cnt>=0? ((int)(*(unsigned char *)((&_iob[1]) )->_ptr++=('S'))):	_flsbuf((unsigned char)('S'),(&_iob[1]) ))  ;
	while (c != '\n') {
	  if (c == (-1) ) {
	    error("end of file at beginning of table");
	    return;
	  }
	  (--((&_iob[1]) )->_cnt>=0? ((int)(*(unsigned char *)((&_iob[1]) )->_ptr++=(c))):	_flsbuf((unsigned char)(c),(&_iob[1]) ))  ;
	  c = 	(--(fp)->_cnt>=0? *(fp)->_ptr++&0377:_filbuf(fp)) ;
	}
	(--((&_iob[1]) )->_cnt>=0? ((int)(*(unsigned char *)((&_iob[1]) )->_ptr++=('\n'))):	_flsbuf((unsigned char)('\n'),(&_iob[1]) ))  ;
	current_lineno++;
	{
	  table_input input(fp);
	  process_table(input);
	  set_troff_location(current_filename, current_lineno);
	  if (input.ended()) {
	    fputs(".TE", (&_iob[1]) );
	    while ((c = 	(--(fp)->_cnt>=0? *(fp)->_ptr++&0377:_filbuf(fp)) ) != '\n') {
	      if (c == (-1) ) {
		(--((&_iob[1]) )->_cnt>=0? ((int)(*(unsigned char *)((&_iob[1]) )->_ptr++=('\n'))):	_flsbuf((unsigned char)('\n'),(&_iob[1]) ))  ;
		return;
	      }
	      (--((&_iob[1]) )->_cnt>=0? ((int)(*(unsigned char *)((&_iob[1]) )->_ptr++=(c))):	_flsbuf((unsigned char)(c),(&_iob[1]) ))  ;
	    }
	    (--((&_iob[1]) )->_cnt>=0? ((int)(*(unsigned char *)((&_iob[1]) )->_ptr++=('\n'))):	_flsbuf((unsigned char)('\n'),(&_iob[1]) ))  ;
	    current_lineno++;
	  }
	}
	state = START;
      }
      else {
	fputs(".TS", (&_iob[1]) );
	(--((&_iob[1]) )->_cnt>=0? ((int)(*(unsigned char *)((&_iob[1]) )->_ptr++=(c))):	_flsbuf((unsigned char)(c),(&_iob[1]) ))  ;
	state = MIDDLE;
      }
      break;
    case HAD_l:
      if (c == 'f')
	state = HAD_lf;
      else {
	(--((&_iob[1]) )->_cnt>=0? ((int)(*(unsigned char *)((&_iob[1]) )->_ptr++=('.'))):	_flsbuf((unsigned char)('.'),(&_iob[1]) ))  ;
	(--((&_iob[1]) )->_cnt>=0? ((int)(*(unsigned char *)((&_iob[1]) )->_ptr++=('l'))):	_flsbuf((unsigned char)('l'),(&_iob[1]) ))  ;
	(--((&_iob[1]) )->_cnt>=0? ((int)(*(unsigned char *)((&_iob[1]) )->_ptr++=(c))):	_flsbuf((unsigned char)(c),(&_iob[1]) ))  ;
	if (c == '\n') {
 	  current_lineno++;
	  state = START;
	}
	else
	  state = MIDDLE;
      }
      break;
    case HAD_lf:
      if (c == ' ' || c == '\n' || compatible_flag) {
	string line;
	while (c != (-1) ) {
	  line += c;
	  if (c == '\n') {
	    current_lineno++;
	    break;
	  }
	  c = 	(--(fp)->_cnt>=0? *(fp)->_ptr++&0377:_filbuf(fp)) ;
	}
	line += '\0';
	interpret_lf_args(line.contents());
	printf(".lf%s", line.contents());
	state = START;
      }
      else {
	fputs(".lf", (&_iob[1]) );
	(--((&_iob[1]) )->_cnt>=0? ((int)(*(unsigned char *)((&_iob[1]) )->_ptr++=(c))):	_flsbuf((unsigned char)(c),(&_iob[1]) ))  ;
	state = MIDDLE;
      }
      break;
    default:
      do_assert(0, 296, "main.cc") ;
    }
  switch(state) {
  case START:
    break;
  case MIDDLE:
    (--((&_iob[1]) )->_cnt>=0? ((int)(*(unsigned char *)((&_iob[1]) )->_ptr++=('\n'))):	_flsbuf((unsigned char)('\n'),(&_iob[1]) ))  ;
    break;
  case HAD_DOT:
    fputs(".\n", (&_iob[1]) );
    break;
  case HAD_l:
    fputs(".l\n", (&_iob[1]) );
    break;
  case HAD_T:
    fputs(".T\n", (&_iob[1]) );
    break;
  case HAD_lf:
    fputs(".lf\n", (&_iob[1]) );
    break;
  case HAD_TS:
    fputs(".TS\n", (&_iob[1]) );
    break;
  }
  if (fp != (&_iob[0]) )
    fclose(fp);
}

struct options {
  unsigned flags;
  int linesize;
  char delim[2];
  char tab_char;

  options();
};

options::options()
: flags(0), tab_char('\t'), linesize(0)
{
  delim[0] = delim[1] = '\0';
}

 

int strieq(const char *p, const char *q)
{
  for (; cmlower(*p) == cmlower(*q); p++, q++)
    if (*p == '\0')
      return 1;
  return 0;
}

 

options *process_options(table_input &in)
{
  options *opt = new options;
  string line;
  int level = 0;
  for (;;) {
    int c = in.get();
    if (c == (-1) ) {
      int i = line.length();
      while (--i >= 0)
	in.unget(line[i]);
      return opt;
    }
    if (c == '\n') {
      in.unget(c);
      int i = line.length();
      while (--i >= 0)
	in.unget(line[i]);
      return opt;
    }
    else if (c == '(')
      level++;
    else if (c == ')')
      level--;
    else if (c == ';' && level == 0) {
      line += '\0';
      break;
    }
    line += c;
  }
  if (line.empty())
    return opt;
  char *p = &line[0];
  for (;;) {
    while (csspace(*p) || *p == ',')
      p++;
    if (*p == '\0')
      break;
    char *q = p;
    while (*q != ' ' && *q != '\0' && *q != '\t' && *q != ',' && *q != '(')
      q++;
    char *arg = 0;
    if (*q != '(' && *q != '\0')
      *q++ = '\0';
    while (csspace(*q))
      q++;
    if (*q == '(') {
      *q++ = '\0';
      arg = q;
      while (*q != ')' && *q != '\0')
	q++;
      if (*q == '\0')
	error("missing `)'");
      else
	*q++ = '\0';
    }
    if (*p == '\0') {
      if (arg)
	error("argument without option");
    }
    else if (strieq(p, "tab")) {
      if (!arg)
	error("`tab' option requires argument in parentheses");
      else {
	if (arg[0] == '\0' || arg[1] != '\0')
	  error("argument to `tab' option must be a single character");
	else
	  opt->tab_char = arg[0];
      }
    }
    else if (strieq(p, "linesize")) {
      if (!arg)
	error("`linesize' option requires argument in parentheses");
      else {
	if (sscanf(arg, "%d", &opt->linesize) != 1)
	  error("bad linesize `%s'", arg);
	else if (opt->linesize <= 0) {
	  error("linesize must be positive");
	  opt->linesize = 0;
	}
      }
    }
    else if (strieq(p, "delim")) {
      if (!arg)
	error("`delim' option requires argument in parentheses");
      else if (arg[0] == '\0' || arg[1] == '\0' || arg[2] != '\0')
	error("argument to `delim' option must be two characters");
      else {
	opt->delim[0] = arg[0];
	opt->delim[1] = arg[1];
      }
    }
    else if (strieq(p, "center") || strieq(p, "centre")) {
      if (arg)
	error("`center' option does not take a argument");
      opt->flags |= table::CENTER;
    }
    else if (strieq(p, "expand")) {
      if (arg)
	error("`expand' option does not take a argument");
      opt->flags |= table::EXPAND;
    }
    else if (strieq(p, "box") || strieq(p, "frame")) {
      if (arg)
	error("`box' option does not take a argument");
      opt->flags |= table::BOX;
    }
    else if (strieq(p, "doublebox") || strieq(p, "doubleframe")) {
      if (arg)
	error("`doublebox' option does not take a argument");
      opt->flags |= table::DOUBLEBOX;
    }
    else if (strieq(p, "allbox")) {
      if (arg)
	error("`allbox' option does not take a argument");
      opt->flags |= table::ALLBOX;
    }
    else {
      error("unrecognised global option `%1'", p);
       
       
    }
    p = q;
  }
  return opt;
}

entry_modifier::entry_modifier()
: vertical_alignment(CENTER), zero_width(0), stagger(0)
{
  vertical_spacing.inc = vertical_spacing.val = 0;
  point_size.inc = point_size.val = 0;
}

entry_modifier::~entry_modifier()
{
}

entry_format::entry_format() : type(FORMAT_LEFT)
{
}

entry_format::entry_format(format_type t) : type(t)
{
}

void entry_format::debug_print() const
{
  switch (type) {
  case FORMAT_LEFT:
    (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=('l'))):	_flsbuf((unsigned char)('l'), (&_iob[2]) )) ;
    break;
  case FORMAT_CENTER:
    (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=('c'))):	_flsbuf((unsigned char)('c'), (&_iob[2]) )) ;
    break;
  case FORMAT_RIGHT:
    (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=('r'))):	_flsbuf((unsigned char)('r'), (&_iob[2]) )) ;
    break;
  case FORMAT_NUMERIC:
    (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=('n'))):	_flsbuf((unsigned char)('n'), (&_iob[2]) )) ;
    break;
  case FORMAT_ALPHABETIC:
    (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=('a'))):	_flsbuf((unsigned char)('a'), (&_iob[2]) )) ;
    break;
  case FORMAT_SPAN:
    (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=('s'))):	_flsbuf((unsigned char)('s'), (&_iob[2]) )) ;
    break;
  case FORMAT_VSPAN:
    (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=('^'))):	_flsbuf((unsigned char)('^'), (&_iob[2]) )) ;
    break;
  case FORMAT_HLINE:
    (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=('_'))):	_flsbuf((unsigned char)('_'), (&_iob[2]) )) ;
    break;
  case FORMAT_DOUBLE_HLINE:
    (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=('='))):	_flsbuf((unsigned char)('='), (&_iob[2]) )) ;
    break;
  default:
    do_assert(0, 528, "main.cc") ;
    break;
  }
  if (point_size.val != 0) {
    (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=('p'))):	_flsbuf((unsigned char)('p'), (&_iob[2]) )) ;
    if (point_size.inc > 0)
      (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=('+'))):	_flsbuf((unsigned char)('+'), (&_iob[2]) )) ;
    else if (point_size.inc < 0)
      (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=('-'))):	_flsbuf((unsigned char)('-'), (&_iob[2]) )) ;
    fprintf((&_iob[2]) , "%d ", point_size.val);
  }
  if (vertical_spacing.val != 0) {
    (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=('v'))):	_flsbuf((unsigned char)('v'), (&_iob[2]) )) ;
    if (vertical_spacing.inc > 0)
      (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=('+'))):	_flsbuf((unsigned char)('+'), (&_iob[2]) )) ;
    else if (vertical_spacing.inc < 0)
      (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=('-'))):	_flsbuf((unsigned char)('-'), (&_iob[2]) )) ;
    fprintf((&_iob[2]) , "%d ", vertical_spacing.val);
  }
  if (!font.empty()) {
    (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=('f'))):	_flsbuf((unsigned char)('f'), (&_iob[2]) )) ;
    put_string(font, (&_iob[2]) );
    (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=(' '))):	_flsbuf((unsigned char)(' '), (&_iob[2]) )) ;
  }
  switch (vertical_alignment) {
  case entry_modifier::CENTER:
    break;
  case entry_modifier::TOP:
    (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=('t'))):	_flsbuf((unsigned char)('t'), (&_iob[2]) )) ;
    break;
  case entry_modifier::BOTTOM:
    (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=('d'))):	_flsbuf((unsigned char)('d'), (&_iob[2]) )) ;
    break;
  }
  if (zero_width)
    (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=('z'))):	_flsbuf((unsigned char)('z'), (&_iob[2]) )) ;
  if (stagger)
    (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=('u'))):	_flsbuf((unsigned char)('u'), (&_iob[2]) )) ;
}

struct format {
  int nrows;
  int ncolumns;
  int *separation;
  string *width;
  char *equal;
  entry_format **entry;
  char **vline;

  format(int nr, int nc);
  ~format();
  void add_rows(int n);
};

format::format(int nr, int nc) : nrows(nr), ncolumns(nc)
{
  int i;
  separation = new int[ncolumns - 1];
  for (i = 0; i < ncolumns-1; i++)
    separation[i] = -1;
  width = new string[ncolumns];
  equal = new char[ncolumns];
  for (i = 0; i < ncolumns; i++)
    equal[i] = 0;
  entry = new entry_format *[nrows];
  for (i = 0; i < nrows; i++)
    entry[i] = new entry_format[ncolumns];
  vline = new char*[nrows];
  for (i = 0; i < nrows; i++) {
    vline[i] = new char[ncolumns+1];
    for (int j = 0; j < ncolumns+1; j++)
      vline[i][j] = 0;
  }
}

void format::add_rows(int n)
{
  int i;
  char **old_vline = vline;
  vline = new char*[nrows + n];
  for (i = 0; i < nrows; i++)
    vline[i] = old_vline[i];
  delete []  old_vline;
  for (i = 0; i < n; i++) {
    vline[nrows + i] = new char[ncolumns + 1];
    for (int j = 0; j < ncolumns + 1; j++)
      vline[nrows + i][j] = 0;
  }
  entry_format **old_entry = entry;
  entry = new entry_format *[nrows + n];
  for (i = 0; i < nrows; i++)
    entry[i] = old_entry[i];
  delete []  old_entry;
  for (i = 0; i < n; i++)
    entry[nrows + i] = new entry_format[ncolumns];
  nrows += n;
}

format::~format()
{
  delete []  separation;
  delete []  width;
  delete []  equal;
  for (int i = 0; i < nrows; i++) {
    delete []  vline[i];
    delete []  entry[i];
  }
  delete []  vline;
  delete []  entry;
}

struct input_entry_format : entry_format {
  input_entry_format *next;
  string width;
  int separation;
  int vline;
  int pre_vline;
  int last_column;
  int equal;
  input_entry_format(format_type, input_entry_format * = 0);
  ~input_entry_format();
  void debug_print();
};

input_entry_format::input_entry_format(format_type t, input_entry_format *p)
: entry_format(t), next(p)
{
  separation = -1;
  last_column = 0;
  vline = 0;
  pre_vline = 0;
  equal = 0;
}

input_entry_format::~input_entry_format()
{
}

void free_input_entry_format_list(input_entry_format *list)
{
  while (list) {
    input_entry_format *tem = list;
    list = list->next;
    delete tem;
  }
}

void input_entry_format::debug_print()
{
  for (int i = 0; i < pre_vline; i++)
    (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=('|'))):	_flsbuf((unsigned char)('|'), (&_iob[2]) )) ;
  entry_format::debug_print();
  if (!width.empty()) {
    (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=('w'))):	_flsbuf((unsigned char)('w'), (&_iob[2]) )) ;
    (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=('('))):	_flsbuf((unsigned char)('('), (&_iob[2]) )) ;
    put_string(width, (&_iob[2]) );
    (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=(')'))):	_flsbuf((unsigned char)(')'), (&_iob[2]) )) ;
  }
  if (equal)
    (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=('e'))):	_flsbuf((unsigned char)('e'), (&_iob[2]) )) ;
  if (separation >= 0)
    fprintf((&_iob[2]) , "%d", separation); 
  for (i = 0; i < vline; i++)
    (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=('|'))):	_flsbuf((unsigned char)('|'), (&_iob[2]) )) ;
  if (last_column)
    (--( (&_iob[2]) )->_cnt>=0? ((int)(*(unsigned char *)( (&_iob[2]) )->_ptr++=(','))):	_flsbuf((unsigned char)(','), (&_iob[2]) )) ;
}

 
 
 

format *process_format(table_input &in, options *opt,
		       format *current_format = 0)
{
  input_entry_format *list = 0;
  int c = in.get();
  for (;;) {
    int pre_vline = 0;
    int got_format = 0;
    int got_period = 0;
    format_type t;
    for (;;) {
      if (c == (-1) ) {
	error("end of input while processing format");
	free_input_entry_format_list(list);
	return 0;
      }
      switch (c) {
      case 'n':
      case 'N':
	t = FORMAT_NUMERIC;
	got_format = 1;
	break;
      case 'a':
      case 'A':
	got_format = 1;
	t = FORMAT_ALPHABETIC;
	break;
      case 'c':
      case 'C':
	got_format = 1;
	t = FORMAT_CENTER;
	break;
      case 'l':
      case 'L':
	got_format = 1;
	t = FORMAT_LEFT;
	break;
      case 'r':
      case 'R':
	got_format = 1;
	t = FORMAT_RIGHT;
	break;
      case 's':
      case 'S':
	got_format = 1;
	t = FORMAT_SPAN;
	break;
      case '^':
	got_format = 1;
	t = FORMAT_VSPAN;
	break;
      case '_':
	got_format = 1;
	t = FORMAT_HLINE;
	break;
      case '=':
	got_format = 1;
	t = FORMAT_DOUBLE_HLINE;
	break;
      case '.':
	got_period = 1;
	break;
      case '|':
	pre_vline++;
	break;
      case ' ':
      case '\t':
      case '\n':
	break;
      default:
	if (c == opt->tab_char)
	  break;
	error("unrecognised format `%1'", char(c));
	free_input_entry_format_list(list);
	return 0;
      }
      if (got_period)
	break;
      c = in.get();
      if (got_format)
	break;
    }
    if (got_period)
      break;
    list = new input_entry_format(t, list);
    if (pre_vline)
      list->pre_vline = pre_vline;
    int success = 1;
    do {
      switch (c) {
      case 't':
      case 'T':
	c = in.get();
	list->vertical_alignment = entry_modifier::TOP;
	break;
      case 'd':
      case 'D':
	c = in.get();
	list->vertical_alignment = entry_modifier::BOTTOM;
	break;
      case 'u':
      case 'U':
	c = in.get();
	list->stagger = 1;
	break;
      case 'z':
      case 'Z':
	c = in.get();
	list->zero_width = 1;
	break;
      case '0':
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9':
	{
	  int w = 0;
	  do {
	    w = w*10 + (c - '0');
	    c = in.get();
	  } while (c != (-1)  && csdigit(c));
	  list->separation = w;
	}
	break;
      case 'f':
      case 'F':
	do {
	  c = in.get();
	} while (c == ' ' || c == '\t');
	if (c == (-1) ) {
	  error("missing font name");
	  break;
	}
	if (c == '(') {
	  for (;;) {
	    c = in.get();
	    if (c == (-1)  || c == ' ' || c == '\t') {
	      error("missing `)'");
	      break;
	    }
	    if (c == ')') {
	      c = in.get();
	      break;
	    }
	    list->font += char(c);
	  }
	}
	else {
	  list->font = c;
	  char cc = c;
	  c = in.get();
	  if (!csdigit(cc)
	      && c != (-1)  && c != ' ' && c != '\t' && c != '.' && c != '\n') {
	    list->font += char(c);
	    c = in.get();
	  }
	}
	break;
      case 'v':
      case 'V':
	c = in.get();
	list->vertical_spacing.val = 0;
	list->vertical_spacing.inc = 0;
	if (c == '+' || c == '-') {
	  list->vertical_spacing.inc = (c == '+' ? 1 : -1);
	  c = in.get();
	}
	if (c == (-1)  || !csdigit(c)) {
	  error("`v' modifier must be followed by number");
	  list->vertical_spacing.inc = 0;
	}
	else {
	  do {
	    list->vertical_spacing.val *= 10;
	    list->vertical_spacing.val += c - '0';
	    c = in.get();
	  } while (c != (-1)  && csdigit(c));
	}
	if (list->vertical_spacing.val > 72 
	    || list->vertical_spacing.val < -72 ) {
	  error("unreasonable point size");
	  list->vertical_spacing.val = 0;
	  list->vertical_spacing.inc = 0;
	}
	break;
      case 'p':
      case 'P':
	c = in.get();
	list->point_size.val = 0;
	list->point_size.inc = 0;
	if (c == '+' || c == '-') {
	  list->point_size.inc = (c == '+' ? 1 : -1);
	  c = in.get();
	}
	if (c == (-1)  || !csdigit(c)) {
	  error("`p' modifier must be followed by number");
	  list->point_size.inc = 0;
	}
	else {
	  do {
	    list->point_size.val *= 10;
	    list->point_size.val += c - '0';
	    c = in.get();
	  } while (c != (-1)  && csdigit(c));
	}
	if (list->point_size.val > 99 
	    || list->point_size.val < -99 ) {
	  error("unreasonable point size");
	  list->point_size.val = 0;
	  list->point_size.inc = 0;
	}
	break;
      case 'w':
      case 'W':
	c = in.get();
	while (c == ' ' || c == '\t')
	  c = in.get();
	if (c == '(') {
	  list->width = "";
	  c = in.get();
	  while (c != ')') {
	    if (c == (-1)  || c == '\n') {
	      error("missing `)'");
	      free_input_entry_format_list(list);
	      return 0;
	    }
	    list->width += c;
	    c = in.get();
	  }
	  c = in.get();
	}
	else {
	  if (c == '+' || c == '-') {
	    list->width = char(c);
	    c = in.get();
	  }
	  else
	    list->width = "";
	  if (c == (-1)  || !csdigit(c))
	    error("bad argument for `w' modifier");
	  else {
	    do {
	      list->width += char(c);
	      c = in.get();
	    } while (c != (-1)  && csdigit(c));
	  }
	}
	break;
      case 'e':
      case 'E':
	c = in.get();
	list->equal++;
	break;
      case '|':
	c = in.get();
	list->vline++;
	break;
      case 'B':
      case 'b':
	c = in.get();
	list->font = "B";
	break;
      case 'I':
      case 'i':
	c = in.get();
	list->font = "I";
	break;
      case ' ':
      case '\t':
	c = in.get();
	break;
      default:
	if (c == opt->tab_char)
	  c = in.get();
	else
	  success = 0;
	break;
      }
    } while (success);
    if (list->vline > 2) {
      list->vline = 2;
      error("more than 2 vertical bars between key letters");
    }
    if (c == '\n' || c == ',') {
      c = in.get();
      list->last_column = 1;
    }
  }
  if (c == '.') {
    do {
      c = in.get();
    } while (c == ' ' || c == '\t');
    if (c != '\n') {
      error("`.' not last character on line");
      free_input_entry_format_list(list);
      return 0;
    }
  }
  if (!list) {
    error("no format");
    free_input_entry_format_list(list);
    return 0;
  }
  list->last_column = 1;
   
  input_entry_format *rev = 0;
  while (list != 0) {
    input_entry_format *tem = list->next;
    list->next = rev;
    rev = list;
    list = tem;
  }
  list = rev;
  input_entry_format *tem;






   
  int ncolumns = 0;
  int nrows = 0;
  int col = 0;
  for (tem = list; tem; tem = tem->next) {
    if (tem->last_column) {
      if (col >= ncolumns)
	ncolumns = col + 1;
      col = 0;
      nrows++;
    }
    else
      col++;
  }
  int row;
  format *f;
  if (current_format) {
    if (ncolumns > current_format->ncolumns) {
      error("cannot increase the number of columns in a continued format");
      free_input_entry_format_list(list);
      return 0;
    }
    f = current_format;
    row = f->nrows;
    f->add_rows(nrows);
  }
  else {
    f = new format(nrows, ncolumns);
    row = 0;
  }
  col = 0;
  for (tem = list; tem; tem = tem->next) {
    f->entry[row][col] = *tem;
    if (col < ncolumns-1) {
       
      if (tem->separation > f->separation[col]) {
	if (current_format)
	  error("cannot change column separation in continued format");
	else
	  f->separation[col] = tem->separation;
      }
    }
    else if (tem->separation >= 0)
      error("column separation specified for last column");
    if (tem->equal && !f->equal[col]) {
      if (current_format)
	error("cannot change which columns are equal in continued format");
      else
	f->equal[col] = 1;
    }
    if (!tem->width.empty()) {
       
      if (!f->width[col].empty() && f->width[col] != tem->width)
	error("multiple widths for column %1", col+1);
      f->width[col] = tem->width;
    }
    if (tem->pre_vline) {
      do_assert(col == 0, 1082, "main.cc") ;
      f->vline[row][col] = tem->pre_vline;
    }
    f->vline[row][col+1] = tem->vline;
    if (tem->last_column) {
      row++;
      col = 0;
    }
    else
      col++;
  }
  free_input_entry_format_list(list);
  for (col = 0; col < ncolumns; col++) {
    entry_format *e = f->entry[f->nrows-1] + col;
    if (e->type != FORMAT_HLINE
	&& e->type != FORMAT_DOUBLE_HLINE
	&& e->type != FORMAT_SPAN)
      break;
  }
  if (col >= ncolumns) {
    error("last row of format is all lines");
    delete f;
    return 0;
  }
  return f;
}

table *process_data(table_input &in, format *f, options *opt)
{
  char tab_char = opt->tab_char;
  int ncolumns = f->ncolumns;
  int current_row = 0;
  int format_index = 0;
  int give_up = 0;
  enum { DATA_INPUT_LINE, TROFF_INPUT_LINE, SINGLE_HLINE, DOUBLE_HLINE } type;
  table *tbl = new table(ncolumns, opt->flags, opt->linesize);
  if (opt->delim[0] != '\0')
    tbl->set_delim(opt->delim[0], opt->delim[1]);
  for (;;) {
     
    int c = in.get();
    if (c == (-1) )
      break;
    if (c == '.') {
      int d = in.get();
      if (d != (-1)  && csdigit(d)) {
	in.unget(d);
	type = DATA_INPUT_LINE;
      }
      else {
	in.unget(d);
	type = TROFF_INPUT_LINE;
      }
    }
    else if (c == '_' || c == '=') {
      int d = in.get();
      if (d == '\n') {
	if (c == '_')
	  type = SINGLE_HLINE;
	else
	  type = DOUBLE_HLINE;
      }
      else {
	in.unget(d);
	type = DATA_INPUT_LINE;
      }
    }
    else {
      type = DATA_INPUT_LINE;
    }
    switch (type) {
    case DATA_INPUT_LINE:
      {
	string input_entry;
	if (format_index >= f->nrows)
	  format_index = f->nrows - 1;
	 
	while (format_index < f->nrows - 1) {
	  for (int c = 0; c < ncolumns; c++) {
	    entry_format *e = f->entry[format_index] + c;
	    if (e->type != FORMAT_HLINE
		&& e->type != FORMAT_DOUBLE_HLINE
		 
		 
		)
	      break;
	  }
	  if (c < ncolumns)
	    break;
	  for (c = 0; c < ncolumns; c++)
	    tbl->add_entry(current_row, c, input_entry,
			   f->entry[format_index] + c, current_filename,
			   current_lineno);
	  tbl->add_vlines(current_row, f->vline[format_index]);
	  format_index++;
	  current_row++;
	}
	entry_format *line_format = f->entry[format_index];
	int col = 0;
	for (;;) {
	  if (c == tab_char || c == '\n') {
	    int ln = current_lineno;
	    if (c == '\n')
	      --ln;
	    while (col < ncolumns
		   && line_format[col].type == FORMAT_SPAN) {
	      tbl->add_entry(current_row, col, "", &line_format[col],
			     current_filename, ln);
	      col++;
	    }
	    if (c == '\n' && input_entry.length() == 2
		&& input_entry[0] == 'T' && input_entry[1] == '{') {
	      input_entry = "";
	      ln++;
	      enum {
		START, MIDDLE, GOT_T, GOT_RIGHT_BRACE, GOT_DOT,
		GOT_l, GOT_lf, END
	      } state = START;
	      while (state != END) {
		c = in.get();
		if (c == (-1) )
		  break;
		switch (state) {
		case START:
		  if (c == 'T')
		    state = GOT_T;
		  else if (c == '.')
		    state = GOT_DOT;
		  else {
		    input_entry += c;
		    if (c != '\n')
		      state = MIDDLE;
		  }
		  break;
		case GOT_T:
		  if (c == '}')
		    state = GOT_RIGHT_BRACE;
		  else {
		    input_entry += 'T';
		    input_entry += c;
		    state = c == '\n' ? START : MIDDLE;
		  }
		  break;
		case GOT_DOT:
		  if (c == 'l')
		    state = GOT_l;
		  else {
		    input_entry += '.';
		    input_entry += c;
		    state = c == '\n' ? START : MIDDLE;
		  }
		  break;
		case GOT_l:
		  if (c == 'f')
		    state = GOT_lf;
		  else {
		    input_entry += ".l";
		    input_entry += c;
		    state = c == '\n' ? START : MIDDLE;
		  }
		  break;
		case GOT_lf:
		  if (c == ' ' || c == '\n' || compatible_flag) {
		    string args;
		    input_entry += ".lf";
		    while (c != (-1) ) {
		      args += c;
		      if (c == '\n')
			break;
		      c = in.get();
		    }
		    args += '\0';
		    interpret_lf_args(args.contents());
		     
		    args.set_length(args.length() - 1);
		    input_entry += args;
		    state = START;
		  }
		  else {
		    input_entry += ".lf";
		    input_entry += c;
		    state = MIDDLE;
		  }
		  break;
		case GOT_RIGHT_BRACE:
		  if (c == '\n' || c == tab_char)
		    state = END;
		  else {
		    input_entry += 'T';
		    input_entry += '}';
		    input_entry += c;
		    state = c == '\n' ? START : MIDDLE;
		  }
		  break;
		case MIDDLE:
		  if (c == '\n')
		    state = START;
		  input_entry += c;
		  break;
		case END:
		default:
		  do_assert(0, 1283, "main.cc") ;
		}
	      }
	      if (c == (-1) ) {
		error("end of data in middle of text block");
		give_up = 1;
		break;
	      }
	    }
	    if (col >= ncolumns) {
	      if (!input_entry.empty()) {
		if (c == '\n')
		  in.unget(c);
		input_entry += '\0';
		error("excess data entry `%1' discarded",
		      input_entry.contents());
		if (c == '\n')
		  (void)in.get();
	      }
	    }
	    else
	      tbl->add_entry(current_row, col, input_entry,
			     &line_format[col], current_filename, ln);
	    col++;
	    if (c == '\n')
	      break;
	    input_entry = "";
	  }
	  else
	    input_entry += c;
	  c = in.get();
	  if (c == (-1) )
	    break;
	}
	if (give_up)
	  break;
	input_entry = "";
	for (; col < ncolumns; col++)
	  tbl->add_entry(current_row, col, input_entry, &line_format[col],
			 current_filename, current_lineno - 1);
	tbl->add_vlines(current_row, f->vline[format_index]);
	current_row++;
	format_index++;
      }
      break;
    case TROFF_INPUT_LINE:
      {
	string line;
	int ln = current_lineno;
	for (;;) {
	  line += c;
	  if (c == '\n')
	    break;
	  c = in.get();
	  if (c == (-1) ) {
	    break;
	  }
	}
	tbl->add_text_line(current_row, line, current_filename, ln);
	if (line.length() >= 4 
	    && line[0] == '.' && line[1] == 'T' && line[2] == '&') {
	  format *newf = process_format(in, opt, f);
	  if (newf == 0)
	    give_up = 1;
	  else
	    f = newf;
	}
	if (line.length() >= 3
	    && line[0] == '.' && line[1] == 'f' && line[2] == 'f') {
	  line += '\0';
	  interpret_lf_args(line.contents() + 3);
	}
      }
      break;
    case SINGLE_HLINE:
      tbl->add_single_hline(current_row);
      break;
    case DOUBLE_HLINE:
      tbl->add_double_hline(current_row);
      break;
    default:
      do_assert(0, 1364, "main.cc") ;
    }
    if (give_up)
      break;
  }
  if (!give_up && current_row == 0) {
    error("no real data");
    give_up = 1;
  }
  if (give_up) {
    delete tbl;
    return 0;
  }
   
   
  for (int i = 0; i < ncolumns - 1; i++)
    if (f->separation[i] >= 0)
      tbl->set_column_separation(i, f->separation[i]);
  for (i = 0; i < ncolumns; i++)
    if (!f->width[i].empty())
      tbl->set_minimum_width(i, f->width[i]);
  for (i = 0; i < ncolumns; i++)
    if (f->equal[i])
      tbl->set_equal_column(i);
  return tbl;
}

void process_table(table_input &in)
{
  int c;
  options *opt = 0;
  format *form = 0;
  table *tbl = 0;
  if ((opt = process_options(in)) != 0 
      && (form = process_format(in, opt)) != 0
      && (tbl = process_data(in, form, opt)) != 0) {
    tbl->print();
    delete tbl;
  }
  else {
    error("giving up on this table");
    while ((c = in.get()) != (-1) )
      ;
  }
  delete opt;
  delete form;
  if (!in.ended())
    error("premature end of file");
}

static void usage()
{
  fprintf((&_iob[2]) , "usage: %s [ -vC ] [ files... ]\n", program_name);
  exit(1);
}

int main(int argc, char **argv)
{
  program_name = argv[0];
  static char stderr_buf[1024 ];
  setbuf((&_iob[2]) , stderr_buf);
  int opt;
  while ((opt = getopt(argc, argv, "vC")) != (-1) )
    switch (opt) {
    case 'C':
      compatible_flag = 1;
      break;
    case 'v':
      {
	extern const char *version_string;
	fprintf((&_iob[2]) , "GNU tbl version %s\n", version_string);
	fflush((&_iob[2]) );
	break;
      }
    case '?':
      usage();
      break;
    default:
      do_assert(0, 1442, "main.cc") ;
    }
  printf(".if !\\n(.g .ab GNU tbl requires GNU troff.\n"
	 ".if !dTS .ds TS\n"
	 ".if !dTE .ds TE\n");
  if (argc > optind) {
    for (int i = optind; i < argc; i++) 
      if (argv[i][0] == '-' && argv[i][1] == '\0') {
	current_filename = "-";
	current_lineno = 1;
	printf(".lf 1 -\n");
	process_input_file((&_iob[0]) );
      }
      else {
	errno = 0;
	FILE *fp = fopen(argv[i], "r");
	if (fp == 0) {
	  current_lineno = -1;
	  error("can't open `%1': %2", argv[i], strerror(errno));
	}
	else {
	  current_lineno = 1;
	  current_filename = argv[i];
	  printf(".lf 1 %s\n", current_filename);
	  process_input_file(fp);
	}
      }
  }
  else {
    current_filename = "-";
    current_lineno = 1;
    printf(".lf 1 -\n");
    process_input_file((&_iob[0]) );
  }
  if (((((&_iob[1]) )->_flag&	00040 )!=0)  || fflush((&_iob[1]) ) < 0)
    fatal("output error");
  exit(0);
}


Newsgroups: gnu.g++.bug