/*
 * tex to m4 utility
 *
 * au: vitas
 * cp: gpl
 *
 */

/*
 * prevadi definovana makra \makro --> _makro()
 *
 * pr: 
 *
 * \def\a #1|#2{kuk#1#2}   define({_a}, {kuk$1$2})
 * \a ahoj|bhoj            _a(ahoj,b)hoj
 *
 * pro nepreveditelne kusy je mozno pouzit:
 *
 * %!{
 *  zde bude vsechno pri prevodu ignorovano
 * %}  <--- az po 
 *
 * %! zde bude vse bez %! vyproceseno
 *
 */

/*
 * 
 * v se bere znak za znakem ze vstupu a hazi se na vystup.
 * sem tam vyjimky:  $, \, %, {
 *
 * $ zjisti se zda jde o disp math nebo obyc disp
 *   precte se blok az po $  (v pripade disp se jeste zjisti zda je
 *   tam druhy '$'
 *
 * { zanori se rekurze, precte se blok az po '}' pak se pokracuje dal.
 *
 * % se zmeni za dnl
 *
 * %! se vhodi beze zmeny az do konce radku
 *
 * \ precte se zbytek tokenu, (kdyz nenasleduje pismeno, je token
 *   jednopismeny a pokusi se prelozit do pismenne zkratky)
 *
 *   pokud je ve slovniku (a neni to \def): \makro
 *
 *   vytiskne se  _makro(
 *
 *   kontroluje se maska makra a prevadi se do seznamu argumetu makra
 *   v m4. tj. 
 *
 *   #1:  zpracuje se  blok az po ':'  
 *   #1#2 pokud je znak '{' zpracuje blok az po '}' 
 *   v pripade jinych znaku se pouze kontroluje maska.
 *   po kazdem neposlednim argumentu se vytiskne ", ", po poslednim
 *   ")"
 *
 *   jeden hack:
 *   pokud je maska "#0":
 *   precte se blok az po '}' vytiskne se ")", ale '}' se vrati.
 *   
 *   to je pro makra jejihz plantnost konci koncem bloku. (typicky
 *   \it)
 *   {\it ahoj \bf mano} --> _it(ahoj _bf(mano))
 *  
 *   
 *   pokud jede o token \def
 *
 *   nacte se nazev makra (pismena nebo jeden znak),
 *   a maska (vse az po '{')
 *
 *   vypise se "define({_makro}, {", a zpracuje se vse az po '}'
 *   a vypise "})"
 *
 * ~, _, ^, &, #
 *   tyto aktivni znaky se prevedou na pripad \~, \^, \_ pak se
 *   postupuje jak popsano vyse, ale pouze mimo definici
 *
 * # se meni na $1 (ma byt: jen v definicich, but not implemented yet)
 *
 *   kdyz bude vice nez jeden bily radek, vytiskne se "_par"
 *
 */

 /*
  * zoologie fci:
  *
  * tm_read_block         zpracovava blok az po `eoblok'
  *   tm_read_block
  *   tm_read_comment     komentar
  *   tm_read_active      aktivni znak
  *   tm_read_tok         token (\makro)
  *   tm_read_math        matematika ($)
  *   tm_read_eol         konec radku (pro \par)
  *
  * tm_read_tok
  *   tm_read_def
  *   tm_read_tok_name    do `tok_name' precte meno tokenu
  *   tm_read_mac_params  cti parametry a zpracuj
  *
  * tm_read_mac_params
  *   tm_read_mac_to_eblock \it   ... }
  *   tm_read_mac_arg     v zpracuj #1
  *   tm_read_mac_check   v konroluj odpovidanisi masce
  *
  * tm_read_mac_arg
  *   tm_read_block
  *   tm_read_tok_name  
  *
  */

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include <unistd.h>

#include "ttm.h"

#define TOK_LEN 50
#define DEF_LEN 50
#define MASK_LEN 50

#define DEF_FILENAMES_SIZ 50

char **toks = NULL;
char **defs = NULL;
int toks_siz;
int toks_top;
int tm_line = 1;
int tm_quiet = 0;
int want_generate_par = 1;
int want_augen_warninig = 0;
int def_level = 0;
int blok_level = 0;
char *fin_name;

FILE *fin;
FILE *fout;

void tm_read_block(int eobchar);
void tm_read_skip_spc();
void tm_read_skip_spc_or_eof();

void
tm_init()
{
	assert(toks == NULL);
	assert(defs == NULL);

	toks_siz = 100;
	toks_top = 0;

	toks = (char**) malloc( sizeof(char*) * toks_siz);
	defs = (char**) malloc( sizeof(char*) * toks_siz);

	assert(toks);
	assert(defs);
	
} /* tm_init */


void
tm_war(char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);

	
	fprintf(stderr, "%s:%i:warning:", fin_name, tm_line);

	vfprintf(stderr, fmt, ap);

	fprintf(stderr, "\n");

	va_end(ap);

} /* tm_err */
void
tm_err(char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);

	fprintf(stderr, "%s:%i:", fin_name, tm_line);
	vfprintf(stderr, fmt, ap);
	fprintf(stderr, "\n");

	exit(-1);

	va_end(ap);

} /* tm_err */

int
tm_isalpha(char s)
{
	return isalpha(s) || s == '_';
} /* tm_isspace */
	
/*
 * pridej do slovniku,
 *
 */
void
tm_add(char *tok, char *def)
{

	//assert(*tok == '\\');

	if( toks_siz <= toks_top )
	{
		toks_siz *= 2;
		toks = (char**) realloc(toks, toks_siz * sizeof(char*));
		defs = (char**) realloc(defs, toks_siz * sizeof(char*));
	}

	assert(toks);
	assert(defs);

	toks[toks_top] = strdup(tok);

#if 0
	obsolete ...
	if( 0 == strcmp(def, ".") )
	{ /* FIXME: pro prazdne makro se musi dat jak maska '.' */
		def = "";
	}
#endif
	
	if( 0 == strcmp(def, "#1\\n")	)
	{ /* hack: pro vskipy a podobne nacitam vse do konce radku */
		def = "#1\n";
	}
 

	defs[toks_top] = strdup(def);

	toks_top++;
	
} /* tm_add */


char *tok_found;

char *
tm_find(char *tok)
{
	int i;

	for(i=toks_top - 1; i >= 0; i--)
	{
		if( 0 == strcmp(tok, toks[i]) )
		{
			tok_found = toks[i];
			return defs[i]; 
		}
	}
	return NULL;
} /* tm_find */
void tm_puts(char *s);
void tm_putf(char *fmt,...);


void
tm_print_toks()
{
	int i;
	tm_puts("<slovnik>\n");
	for(i=0; i< toks_top;i++)
	{
		tm_putf("\\%s{%s}\n", toks[i], defs[i]);
	}
	tm_puts("</slovnik>\n");

} /* tm_print_toks */
/****************************/

int tm_is_space = 1;

int
tm_getc()
{
	int ret;
	ret = fgetc(fin);
	if(ret == '\n') 
	{
		tm_line++;
	}
	return ret;
} /* tm_getc */

void
tm_ungetc(int c)
{
	int ret;
	if( c == '\n' )
	{
		tm_line--;
	}
	if( c != EOF)
	{
		ret = ungetc(c, fin);
		assert(ret != EOF);
	}
} /* tm_ungetc */


void
tm_space_check(int c)
{
	/* FIXME: checkovani ceskych znaku je silly */
	tm_is_space =	! (
			isalpha(c) ||
			isdigit(c) ||
			c == '_' ||
			c > 0x80 ||
		       	c < 0);
} /* tm_isspace */

void
tm_putc(char c)
{
	tm_space_check(c);
	if( ! tm_quiet )
	{
		fputc(c, fout);
	}
} /* tm_putc */


void
tm_puts(char *s)
{
	char last = s[strlen(s) - 1];

	tm_space_check(last);
	
	if( ! tm_quiet )
	{
		fprintf(fout, "%s", s);
	}
} /* tm_puts */

void
tm_putf(char *fmt, ...)
{
	int rt;
	va_list ap;
#define PUTF_BUF_SIZ 500
	char buff[PUTF_BUF_SIZ];

	va_start(ap, fmt);

	rt = vsnprintf(buff, PUTF_BUF_SIZ, fmt, ap);

	if( -1 == rt)
	{
		tm_err("tm_putf: to long text to print (more than %ib)", 
			PUTF_BUF_SIZ);
	}

	tm_puts(buff);
	va_end(ap);

} /* tm_putf */



void
tm_put_underscore()
{
	if(!tm_is_space) 
	{
		tm_puts("{}");
	}
	tm_putc('_');
		
} /* tm_put_underscore */

void tm_read_tok();
void tm_read_math();
void tm_read_special_char(int z);
/*
 * bylo precteno '%!'
 */
void
tm_m4_specific()
{
	int z;
	z = tm_getc();

	if( z != '{' ) 
	{ /* zbytek bude proste predhozen  */
		tm_ungetc(z);
		return;
	}
	/* '%!{' znamena ignoruj vse az do '%}' */


	do{
		z = tm_getc();
		if( z != '%' )
		{
			continue;
		}
		z = tm_getc();
		if( z == '}') 
		{
			return;
		}
		tm_ungetc(z);
	} while (z != -1);
	
	
} /* tm_m4_specific */

/*
 * bylo precteno '%'
 */
void
tm_read_comment(int eobchar)
{
	int z;

	if(def_level)
	{
		tm_putc('%');
		return;
	}
	//tm_put_underscore();
	if(!tm_is_space) 
	{
		tm_puts("{}");
	}

	z = tm_getc();

	if( z == '!' )
	{ /* tak trosku hack: kdyz je v texu "%!" tak zbytek
	   * radky se hodi bez komentare, to aby se do tex'oveho 
	   * zdojaku daly dopsat, m4 specific.
	   *
	   * tetno zbytek se zpracuje
	   */
		tm_m4_specific();
		return;
	}
	else
	{ /* jinak je to komentar: */
		tm_puts("dnl ");
	}

	for(; z !=  '\n'; z = tm_getc())
	{
		 if( z == EOF)
		 {
			tm_err( "Error EOF in block (comment)"
				"(may end by `%c')\n",
				eobchar);
			return;
		 }
		 tm_putc(z);
	} 
	tm_puts("\n");
} /* tm_read_comment */


/*
 * cti aktivni znak,
 * to se provede fintou jako by to byl \z 
 */
void
tm_read_active(int z)
{
	if( def_level )
	{ /* kdyz jsme v definici, tak na to kasli */
		tm_putc(z);
		return;
	}
	tm_puts("{}");
	tm_ungetc(z);
	tm_read_tok();
} /* tm_read_active */

/*
 * pri narazeni na konec radku musime detekovat jestli nahodou nejdo o
 * \par
 */
void
tm_read_eol()
{
	int z;
	int eols;

	tm_putc('\n');

	if( ! want_generate_par )
	{
		return;
	}

	for(eols=0; '\n' == (z = tm_getc()); eols++)
	{
		tm_putc(z);
	}
	if( eols && z != EOF)
	{
		tm_puts("_par\n");
	}
	tm_ungetc(z);
} /* tm_read_eol */

void
tm_read_group()
{
#if 1
	if( def_level )
	{
		tm_putc('{');
 		tm_read_block('}');
		tm_putc('}');
	}
	else
	{
		tm_put_underscore();
		tm_puts("gr(");
 		tm_read_block('}');
		tm_putc(')');
	}
#else
	if(blok_level > 1)
	{ /* ve vetsich hloubkach kresli i slozene  */
		tm_putc('{');
		tm_read_block('}');
		tm_putc('}');
	}
	else
	{
		tm_read_block('}');
	}
#endif
	
} /* tm_read_group */
void
tm_read_block(int eobchar)
{
	
	int z;
	int block_start_line;


	blok_level++;
	block_start_line = tm_line;

	while( eobchar !=	(z = tm_getc()) )
	{
		switch(z) 
		{
		case '{':
			tm_read_group();
			break;
		case '%':
			tm_read_comment(eobchar);
			break;

		case ',':
		case '^':
		case '_':
		case '~': /* tak trosku hack: jako bych nacet \~ */
			tm_read_active(z);
			break;
		case '\\':
			tm_read_tok();
			break;
		case '&':
		case '#':
			tm_read_special_char(z);
			break;
		case '$':
			tm_read_math();
			break;
		case '\n':
			tm_read_eol();
			break;
		case -1:
			tm_err("tm_read_block:unex EOF in block "
				"started at line %i (i want '%c')",
				block_start_line,
				eobchar);
			return;
		default:

			tm_putc(z);
		}
	}
		
	blok_level--;
} /* tm_read_block */

char codeNNN[50];

char *
tm_onecharname(char c)
{
	
	switch(c)
	{
	case '\'': return "apostrof";
	case '>': return "gt";
	case '<': return "lt";
	case ',': return "comma";
	case ';': return "semicolon";
	case '.': return "tilda";
	case '|': return "bar";
	case '/': return "tilda";
	case ' ': return "tilda";
	case '~': return "tilda";
	case '!': return "exclaim";
	case '@': return "at";
	case '*': return "ast";
	case '%': return "percent";
	case '^': return "sup";
	case '_': return "sub";
	case '=': return "eq";
	case '-': return "minus";
	case '{': return "lbrace";
	case '}': return "rbrace";
	case '\\': return "bbackslash";
	case '\n': return "bbackslash";
	default:
#if 0 
		tm_war("tm_onecharname: unsuported escaped char '%c'", c);
#endif
		sprintf(codeNNN, "code%i", (int)((unsigned char)c));
		return codeNNN;
	}
} /* tm_onecharname */ 

char tok_name[TOK_LEN + 1];
char tok_mask[MASK_LEN + 1];

void
tm_read_tok_name()
{
	int i;
	int z;

	z = tm_getc();

	if( isalpha(z) )
	{
		/* read tok */
		for(i = 0;tm_isalpha(z); i++)
		{
			assert(i < TOK_LEN);
		
			tok_name[i] = z;
		
			z = tm_getc();
		}
		tm_ungetc(z);

		tok_name[i] = '\0';
	}
	else
	{
		/* pouze jednoznakovy tok */
		strcpy(tok_name, tm_onecharname(z));
	}
	
 
} /* tm_read_tok_name */

/*
 * ocheckuje jestli dalsi znak, ktery ma prijit je stejny s maskou
 */
void
tm_read_mac_check(char *tok, char *mask)
{
	int z;

	z = tm_getc();

	if( z != *mask )

	{
		tm_err( "tm_read_mac_check: Error parsing \\%s args"
			"(i want `%c' but `%c' found in mask '%s'.\n",
			 tok, *mask, z, mask);
	}
} /* tm_read_mac_check */

/*
 * pro spinave tokeny jako \vskip
 *
 * precte vse az do cm nebo mm nebo pt a tak
 */

void
tm_read_mac_metric()
{
#define MET(a, b)  ((a) + 256 * (b))

	int start_line;
	int z;
	char met[3];

	start_line = tm_line;

	met[2] = '\0';

	z = tm_getc();

	if( EOF == z )
	{
		tm_err("tm_read_mac_metric: EOF in reading metric");
	}

	met[0] = z;

	while(1)
	{
		z = tm_getc();

		if( EOF == z )
		{
			tm_err("tm_read_mac_metric: EOF int reading metric"
				"start at line %i", start_line);
		}
		met[1] = z;

		switch( MET(met[0], met[1]) )
		{
		case MET('p','t'):
		case MET('p','c'):
		case MET('b','p'):
		case MET('d','d'):
		case MET('c','c'):
		case MET('i','n'):
		case MET('c','m'):
		case MET('m','m'):
		case MET('s','p'):
		case MET('e','m'):
		case MET('e','x'):
			tm_putf("%s", met);
			return;
		}
		tm_putc(met[0]);

		met[0] = met[1];
	}
} /* tm_read_mac_metric */

/*
 * v `mask' se narzilo na #1 podle 
 *
 * #1#2 nebo #1(konec masky) -- jen jeden znak nebo cely {...} blok
 * #1: -- nacti vse az po ':'
 *
 */ 

int
tm_read_mac_arg(char *mask)
{
	int mask_shift;
	int z;

	tm_putc('{');
	assert('#' == mask[0] );
	assert(isdigit(mask[1]) || mask[1] == '#');

	if( mask[1] == '#' )
	{ /* spinava makra typu \vskip zerou nelogicky parametry */
		tm_read_mac_metric();
		return 1;
	}

	z = tm_getc();

	if( EOF == z )
	{
		tm_err("tm_read_mac_arg:EOF reading mask(%s)", mask);
	}

	if( mask[2] == '#' || mask[2] == '\0' )
	{ /*nacti pouze jeden 'znak' typu: #1#2 */
		if( z == '\n' )
		{ /* je to konec radku vezmeme prvni znak z dalsiho radku */
			tm_read_skip_spc_or_eof();
			z = tm_getc();
		}
		if( z == '{' )
		{ /* je to cely blok */
			tm_read_block('}');
		}
		else if( z == '\\' )
		{ /* je to jeden token */
			tm_read_tok_name();
			tm_putf("_%s", tok_name);
		}
		else if( z != EOF )
		{ /* tento jeden znak vytiskni */	
			tm_putc(z);
		}
		/* skip arg num */
		mask_shift = 1;
	}
	else 
	{ /* zarazka	typu #1: */
		tm_putc(z);
		tm_read_block(mask[2]);
		/* skip argnum a zarazku */
		mask_shift = 2;
	}

	return mask_shift;

} /* tm_read_mac_arg */

/*
 * {\it blok} preved na _it({blok})
 * 
 * (a posledni } vrat (ceka na ni ta prvni '{' )
 */
void
tm_read_mac_to_eblock()
{
	tm_putc('{');
	tm_read_block('}');
	tm_puts("})");
	tm_ungetc('}');

} /* tm_read_mac_to_eblock */

/*
 * bylo nacteno makro a nalezeno ve slovniku,
 * v `tok_name' je jmeno makra v `mask' je maska
 * nyni je potreba zpracovat argument
 * (nejdrive se preskoci mezery) a pote se pokracuje dle 
 * `mask'
 */
void
tm_read_mac_params(char *tok, char *mask)
{
	int i;

	int fst_arg;

	tm_put_underscore();

	tm_putf("%s(", tok);
	


	if( 0 == strcmp(mask, "#0") )
	{ /* 
	   * hack: kdyz je maska #0 nacti to makro az po konec bloku
	   */
		tm_read_mac_to_eblock();
		return;
	}

	fst_arg = 1;


	for(i = 0; mask[i]; i++) 
	{

		if( mask[i] == '#' )
		{ /* argument */
			if( fst_arg )
			{ /* prvni arg mus preskocit mezery */
				/* preskoc mezery */
				tm_read_skip_spc(); 
			}
			else
			{ /* dalsi arg, zase musi odelovat argsy */
				tm_puts("}, ");
			}


			i += tm_read_mac_arg(&mask[i]);
			fst_arg = 0;
		}
		else
		{ /*kontroluj jestli odpovida maskce */
			tm_read_mac_check(tok, &mask[i]);
		}
	}

	if( !fst_arg )
	{ /* bylli alespon jeden arg musi tento uzavrit */
		tm_putc('}');
	}

	tm_putc(')');

	//tm_ungetc(z);

	if( i > 0 && mask[i-1] == '\n' )
	{
		/*
		 * hack: kdyz je zarazka \n
		 * (pouzev pripade ze def bylo
		 * #1\n
		 */
		tm_ungetc('\n');
	}
} /* tm_read_mac_params */

/*
 * zacina maska, precti az po '{' do `tok_mask'
 */
void
tm_read_def_mask()
{
	int i;
	int z;

	int kam0; /* kam prijde \0: neboli preskoc posledni mezery */ 

	kam0 = 0;

	for(i=0; i < DEF_LEN; i++ )
	{
		z = tm_getc();

		if( z == EOF )
		{
			tm_err("tm_read_def_mask: EOF in mask");
		}

		if( z == '{')
		{ /* konec masky zacina definice */

			tok_mask[kam0] = '\0';
			return;
		}
		if( z != ' ' && z != '\t')
		{ /* jestli to jsou mezery tak je neber vazne */
			kam0 = i + 1;
		}
		tok_mask[i] = z;
	}

	/* uz nemam misto v `tok_mask' */

	tm_err("tm_read_def_mask:too long mask (%i)", i);

} /* tm_read_def_mask */

void
tm_read_skip_spc_or_eof()
{
	int z;

	for( z = tm_getc(); z == ' ' || z == '\t' ; z = tm_getc() );

	if( z != EOF )
	{
		tm_ungetc(z);
	}

} /* tm_read_skip_spc */

void
tm_read_skip_spc()
{
	int z;

	for( z = tm_getc(); z == ' ' || z == '\t' ; z = tm_getc() );

	if( z == EOF )
	{
		tm_err("tm_read_skip_spc: EOF in spaces");
	}

	tm_ungetc(z);

} /* tm_read_skip_spc */

/*
 * je nacteno \def takze se musi nacist
 * \def\makro  #1masku#2{a  definici}
 */
void
tm_read_def()
{
	int z;

	/* nacti \makro */

	def_level++;

	tm_read_skip_spc();


	if( '\\' == (z = tm_getc()) )
	{ /* za def neni definice \makra */
		/* cti znova makro */
		tm_read_tok_name();
	}
	else
	{ /* FIXME:
	   * jednopismena definice (asi precatcodovane pismenko)
	   * vznikne nepouzitelna defince _*
	   */

		tok_name[0] = z;
		tok_name[1] = '\0';
	}


	/* precti masku */
	tm_read_skip_spc();
	tm_read_def_mask();

	/* pridej do slovniku */
	tm_add(tok_name, tok_mask);

	/* preved \def\makro{co} na "define({_makro}, {co})" */
	tm_putf("define({_%s}, {", tok_name);

	tm_read_block('}');

	tm_puts("})");

	def_level--;

} /* tm_read_def */

void
tm_read_tok()
{
	char *mask;
	char *tok;

	tm_read_tok_name();

	if( 0 == strcmp(tok_name, "def") )
	{ /* je to \def to se dela uplne jinak */
		tm_read_def();
		return;
	}
#if 1

	if( 0 == strcmp(tok_name, "ttmdict") )
	{ /* pro ladeni: vytiskni slovnik */
		tm_print_toks();
		return;
	}
#endif

	mask = tm_find(tok_name);

	if(mask == NULL)
	{ /* neni ve slovniku tak to jen prekopiruj (pro poradek) */
		tm_putf("\\%s ", tok_name);
		tm_war("unprocesed token '\\%s'.", tok_name);
		return;
	}

	/*FIXME:dirty */
	tok = tok_found;

	tm_read_mac_params(tok, mask);
	
		
} /* tm_read_tok */

/*
 *  proz naky # &
 */

void
tm_read_special_char(int z)
{
	if( def_level )
	{

		switch(z)
		{
		case '#':
			tm_putc('$');
			break;

		case '&':
			tm_putc('&');
			break;
		}
		return;
	}
	switch(z)
	{
	case '#':
		tm_putc('$');
		break;
	case '&':
		tm_putc('$');
		break;
	}
} /* tm_read_special_char */

void
tm_read_math()
{
	int z;
	int is_display = 0;

#if 0
	if( def_level )
	{ /* v definici se na to vykasleme */
		tm_putc('$');
		return;
	}
#endif

	z = tm_getc(); 

	if( z == '$' )
	{
		is_display = 1;
		z = tm_getc();
		tm_puts("_dm(");
	}
	else
	{
		tm_puts("_m(");
	}


	tm_ungetc(z);
	tm_read_block('$');

	if( is_display )
	{
		z = tm_getc();
		if( z != '$' )
		{
			 tm_err("tm_read_math:loking for '$$', "
				"but '$' found only");
		}
	}

	tm_puts(")");
} /* tm_read_tok */



char *def_filenames[DEF_FILENAMES_SIZ];
int def_filenames_top = 0;

void
add_def_file(char *file)
{
	if( def_filenames_top >= DEF_FILENAMES_SIZ)
	{
		tm_err( "add_def_file: to much input files (%i), "
			"recompile with bigger DEF_FILENAMES_SIZ", 
			def_filenames_top);
	}

	def_filenames[def_filenames_top++] = strdup(file);
} /* add_input_file */


void
proces_file(char *filename)
{
	def_level = 0;
	blok_level = 0;
	tm_line = 1;

	if( !filename )
	{
		fin_name = "stdin";
		fin = stdin;
	}
	else
	{
		fin = fopen(filename, "rt");
		if( !fin)
		{
			tm_err("proces_file: cannt fopen(%s)",
				filename);
		}
		fin_name = filename;
	}

	tm_read_block(-1);

	assert(def_level == 0);

} /* proces_file */

void
def_file_proces()
{
	int i;
	tm_quiet = 1;
	for(i = 0; i < def_filenames_top;i++)
	{
		proces_file(def_filenames[i]);
	}
	tm_quiet = 0;
} /* def_file_proces */


void
usage()
{
	printf(
"usage: ttm [-s] [-d def.m4] file.tex [-o file.m4]\n"
"       -o ouput file [stdout]\n"
"	-s print voceblurary\n"
"	-p suppres generating _par's\n"
"	-w print warninig \"autamtickly generated file\"to output\n"
"	-d def.tex read but not print (for process \\def)\n\n");
} /* usage */

int
main(int argc, char *argv[])
{
	int c;
	int want_print_slovnik = 0;
	char *fout_name = NULL;

	
	fin = stdin;
	fout = stdout;
 
	
	while ( -1 != (c = getopt(argc, argv, "wpd:o:sh")) )
	{
		switch(c)
		{
		case 'w':
			want_augen_warninig = 1;
		case 'p':
			want_generate_par = 0;
		case 's':
			want_print_slovnik = 1;
			break;
		case 'o':
			fout_name = optarg;
			break;
		case 'd':
			add_def_file(optarg);
			break;
			
		default:
			 usage(); return 0;
		}
	}
	if(fout_name)
	{
		if( ! (fout = fopen(fout_name, "wt")) )
		{
			tm_err("cannt fopen(%s, \"w\").", fout_name);
		}
	}
	if( want_augen_warninig )
	{
		tm_puts("dnl WARNING: automaticly generated, "
			"do NOT modify (changes will be lost) !!!\n\n");
	}
		 
	argc -= optind;
	argv += optind;

	tm_init();

	def_file_proces();

	if( argc == 0 )
	{
		proces_file(NULL);
		return 0;
	}

	for(;argc--;argv++)
	{
		proces_file(argv[0]);
	}

	return 0;
} /* ahoj */

