Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

flatex.C - flatten latex files

19 views
Skip to first unread message

Har-Peled Sariel

unread,
Aug 25, 1996, 3:00:00 AM8/25/96
to

/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
* flatex.C -
* Flatten a latex file into a single file, by explicitly including
* the files inclued by \include and \input commands. Also, if bibtex is
* beeing used, then includes the .bbl file into the resulting file. Thus,
* creating a stand alone latex file that can be emailed to someone else.
*
* Compile : gcc -o flatex flatex.C
* Tested on : Linux + gcc
* By : Sariel Har-Peled
* Email : sar...@math.tau.ac.il
* WEB Page : http://www.math.tau.ac.il/~sariel/flatex.html
* Status : You can do whatever you like with this program. please
* email me bugs & suggestions.
*
* To do : Add support to the includeonly command.
*-----------------------------------------------------------------------
* FLATEX 1.20, 1994, 1996, by Sariel Har-Peled.
*
* flatex - create a single latex file with no include/inputs
*
* flatex [-v] [-x FileName] [files]
* -v Verbose, display file structure.
* -x Unflatex: extract files from archive
* -q Quiet mode. Cleaner output but -x can not be used.
* -b Do not insert bibiliography file(.bbl)
*
* Flatex page: http://www.math.tau.ac.il/~sariel/flatex.html
\*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <ctype.h>


/*======================================================================
* Static constants.
\*======================================================================*/
#define LINE_SIZE 1000
#define FALSE 0
#define TRUE 1
#define USE_ARGUMENT( X ) ((void)X)


/*======================================================================
* Types
\*======================================================================*/
typedef struct {
char verbose;
char fBibInsert, fQuiet;
int cSpecialInputLevel;
char szFullName[ LINE_SIZE ];
} structFlags;


/*======================================================================
* Static prototypes.
\*======================================================================*/
static void flatIt( FILE * flOut,
char * szInName,
int level,
structFlags * pFlags );
static void replaceExt( char * str, char * ext );


/*======================================================================
* Start of Code
\*======================================================================*/


static void spacesByLevel( int level )
{
while ( level > 0 ) {
printf( " " );
level--;
}
}


static void printHelp( void )
{
printf( "flatex - create a single latex file with no include/inputs\n" );
printf( "\n\tflatex [-v] [-x FileName] [files]\n" );
printf( "\t\t-v\tVerbose, display file structure.\n" );
printf( "\t\t-x\tUnflatex: extract files from archive\n" );
printf( "\t\t-q\tQuiet mode. Cleaner output but -x can not be used.\n" );
printf( "\t\t-b\tDo not insert bibiliography file(.bbl)\n" );
printf( "\nFlatex page: http://www.math.tau.ac.il/~sariel/flatex.html\n" );
printf( "\n" );
}


static void * myMalloc( unsigned int size )
{
void * ptr;

ptr = malloc( size );
if ( ptr == NULL ) {
fprintf( stderr, "Not enough memory" );
exit( -1 );
}

return ptr;
}


static void handleIncludeCommand( char * line,
char * lpszInclude,
FILE * flOut,
int level,
structFlags * pFlags )
{
char * lpszBrace, * lpszName, * lpszEndBrace;
char ch, fInput = 0;

lpszBrace = NULL;

if ( strncmp( lpszInclude, "\\input", 6 ) == 0 ) {
lpszBrace = lpszInclude + 6;
fInput = 1;
} else
if ( strncmp( lpszInclude, "\\include", 8 ) == 0 ) {
lpszBrace = lpszInclude + 8;
}

ch = *lpszInclude;
*lpszInclude = 0;
fputs( line, flOut );
*lpszInclude = ch;

lpszEndBrace = strchr( lpszBrace, '}' );
if ( *lpszBrace != '{' || lpszEndBrace == NULL ) {
fprintf( stderr, "ERROR: Expected brace not found.\n\n\tline:%s\n",
line );
exit( -1 );
}

*lpszEndBrace = 0;
lpszName = (char *)myMalloc( LINE_SIZE );
strcpy( lpszName, lpszBrace + 1 );
if ( ! fInput )
replaceExt( lpszName, ".tex" );

flatIt( flOut, lpszName, level + 1, pFlags );

lpszEndBrace++;
while ( *lpszEndBrace ) {
*line++ = *lpszEndBrace++;
}
*line = 0;

free( lpszName );
}


static char isBefore( char * lpszA, char * lpszB )
{
if ( lpszB == NULL )
return TRUE;
if ( lpszA == NULL )
return FALSE;

if ( (int)( lpszA -lpszB ) < 0 ) {
return TRUE;
}
return FALSE;
}


static FILE * fopenTex( char * file,
char * mode )
{
FILE * fl;

fl = fopen( file, mode );
if ( fl != NULL )
return fl;

replaceExt( file, ".tex" );
fl = fopen( file, mode );

return fl;
}


static char isTexFileExists( char * file )
{
FILE * fl;

fl = fopenTex( file, "rt" );
if ( fl != NULL ) {
fclose( fl );
return 1;
}

return 0;
}


static void addTexExt( char * file )
{
FILE * fl;

fl = fopenTex( file, "rt");
if ( fl != NULL )
fclose( fl );
}


static void flatIt( FILE * flOut,
char * pSzInName,
int level,
structFlags * pFlags )
{
FILE * flIn;
char * str, * lpszInput, * lpszInclude, * line, * lpszRem, *inc;
char * lpszLine, * lpszRemark, * lpszBib, * lpszBibStyle;
char * lpszNewCommand, * lpszName;
char cont;
char repFlag;
char szInName[ 100 ];
char fInclude;

strcpy( szInName, pSzInName );

addTexExt( szInName );
if ( ! pFlags->fQuiet )
fprintf( flOut, "%%%cflatex input: [%s]\n",
pFlags->cSpecialInputLevel > 0? '*' : ' ',
szInName );
if ( pFlags->verbose ) {
printf( "\t" );
spacesByLevel( level );
printf( "%s\n", szInName );
}

line = (char *)myMalloc( LINE_SIZE );
lpszLine = (char *)myMalloc( LINE_SIZE );
lpszRemark = (char *)myMalloc( LINE_SIZE );

flIn = fopenTex( szInName, "rt" );
if ( flIn == NULL ) {
fprintf( stderr, "Unable to open file: %s\n", szInName );
exit( -1 );
}

*lpszRemark = 0;
while ( ! feof( flIn ) ) {
str = fgets( line, LINE_SIZE, flIn );
if ( str == NULL )
break;

fInclude = FALSE;

strcpy( lpszLine, line );

lpszRem = strchr( line, '%' );
if ( lpszRem != NULL ) {
strcpy( lpszRemark, lpszRem );
*lpszRem = 0;
}

do {
cont = 0;
lpszInput = strstr( line, "\\input" );

lpszBib = strstr( line, "\\bibliography" );
lpszBibStyle = strstr( line, "\\bibliographystyle" );

if ( pFlags->fBibInsert &&
( lpszBib != NULL || lpszBibStyle != NULL ) ) {
lpszName = (char *)myMalloc( LINE_SIZE );

strcpy( lpszName, lpszLine );
strcpy( lpszLine, pFlags->fQuiet? "%" : "%FLATEX-REM:" );
strcat( lpszLine, lpszName );

if ( lpszBibStyle != NULL ) {
strcpy( lpszName, pFlags->szFullName );
replaceExt( lpszName, ".bbl" );

pFlags->cSpecialInputLevel++;
flatIt( flOut, lpszName, level + 1, pFlags );
pFlags->cSpecialInputLevel--;

if ( pFlags->verbose ) {
printf( "\t" );
spacesByLevel( level + 1 );
printf( "(Bibiliography)\n" );
}
}
break;
}

inc = line;
do {
repFlag = 0;
lpszInclude = strstr( inc, "\\include" );
if ( lpszInclude != NULL &&
strncmp( lpszInclude, "\\includeonly", 12 ) == 0 ) {
fprintf( stderr, "WARNING: \"\\includeonly\" command "
"ignored\n" );
inc = lpszInclude + 1;
repFlag = 1;
}
} while ( repFlag );

if ( isBefore( lpszInput, lpszInclude ) )
lpszInclude = lpszInput;

if ( lpszInclude != NULL ) {
lpszNewCommand = strstr( line, "\\newcommand" );
if ( lpszNewCommand == NULL ) {
handleIncludeCommand( line, lpszInclude, flOut, level,
pFlags );
cont = 1;
fInclude = TRUE;
}
}
} while ( cont );
if ( fInclude ) {
strcat( line, lpszRemark );
fputs( line, flOut );
} else
fputs( lpszLine, flOut );
}

fclose( flIn );
fputs( "\n", flOut );

if ( ! pFlags->fQuiet )
fprintf( flOut, "%% flatex input end: [%s]\n", szInName );

free( line );
free( lpszLine );
free( lpszRemark );
}


static void replaceExt( char * str, char * ext )
{
int len, ind;

len = strlen( str );
ind = len - 1;
while ( ind >= 0 && str[ ind ] != '.' && str[ ind ] != '\\' &&
str[ ind ] != '/' )
ind--;

if ( ind >= 0 && str[ ind ] == '.' ) {
str[ ind ] = 0;
}

strcat( str, ext );
}

static char strCmpPrefixAndCopy( char * line,
char * str,
char * outName )
{
char * pos, * pPreLine;

pPreLine = line;

pos = strstr( line, str );
if ( pos == NULL )
return 0;

line = pos + strlen( str );
strcpy( outName, line );
pos = strchr( outName, ']' );

if ( pos == NULL ) {
fprintf( stderr, "Error encountered in line: [%s]", pPreLine );
exit( -1 );
}
*pos = 0;

return 1;
}


static void writeFile( FILE * flIn,
char * pOutName,
int level )
{
FILE * flOut;
char * lpszLine;
char line[ LINE_SIZE ], outName[ LINE_SIZE ];
char flag;

outName[ 0 ] = 0;

if ( pOutName == NULL ) {
flOut = NULL;
printf( "Scanning for flatex archive start...\n" );
} else {
flOut = fopen( pOutName, "wt" );
if ( flOut == NULL ) {
fprintf( stderr, "Unable to open file: %s", pOutName );
exit( -1 );
}
spacesByLevel( level );
printf( "[%s]\n", pOutName );
}

do {
lpszLine = fgets( line, LINE_SIZE, flIn );
if ( lpszLine == NULL )
break;

flag = strCmpPrefixAndCopy( line, "% flatex input end: [", outName );
if ( flag ) {
if ( flOut == NULL ) {
fprintf( stderr, "Something is wrong!!!!\n" );
exit( -1 );
}
//spacesByLevel( level );
// printf( "/\n" );
//printf( "Writing [%s] done\n", outName );
break;
}

flag = strCmpPrefixAndCopy( line, "% flatex input: [", outName );
if ( flag ) {
writeFile( flIn, outName, level + 1 );
if ( flOut != NULL )
fprintf( flOut, "\\input{%s}\n", outName );
} else {
flag = strCmpPrefixAndCopy( line, "%*flatex input: [", outName );
if ( flag ) {
writeFile( flIn, outName, level + 1 );
} else {
if ( flOut != NULL ) {
if ( strncmp( line, "%FLATEX-REM:", 12 ) == 0 )
fputs( line + 12, flOut );
else
fputs( line, flOut );
}
}
}
} while ( ! feof( flIn ) );

if ( flOut != NULL )
fclose( flOut );
}


static void flatOutFile( char * fileName,
structFlags * pFlags )
{
FILE * flIn;

USE_ARGUMENT( pFlags );

flIn = fopen( fileName, "rt" );
if ( flIn == NULL ) {
fprintf( stderr, "Unable to open file: %s", fileName );
exit( -1 );
}

writeFile( flIn, NULL, 0 );

fclose( flIn );
}


static void flatFile( char * fileName,
structFlags * pFlags )
{
char * szInName, * szOutName;
int inLen;
FILE * flOut;

szInName = (char *)myMalloc( LINE_SIZE );
szOutName = (char *)myMalloc( LINE_SIZE );

strcpy( szInName, fileName );
if ( ! isTexFileExists( szInName ) ) {
fprintf( stderr, "--Unable to open file: [%s]\n", fileName );
exit( -1 );
}

inLen = strlen( szInName );
if ( inLen < 4 || ( szInName[ inLen ] != '.' &&
strcmp( szInName + inLen - 4, ".tex" ) != 0 ) ) {
strcat( szInName, ".tex" );
}

printf( "input file: [%s]\n", szInName );

strcpy( pFlags->szFullName, szInName );

strcpy( szOutName, szInName );
replaceExt( szOutName, ".flt" );

flOut = fopen( szOutName, "wt" );
if ( flOut == NULL ) {
fprintf( stderr, "Unable to open file: %s", szOutName );
exit( -1 );
}

flatIt( flOut, szInName, 0, pFlags );

fclose( flOut );

printf( "\n\tFile: \"%s\" generated\n", szOutName );
}


static char isFlag( char * str, char ch )
{
if ( str[ 0 ] == '-' &&
( str[ 1 ] == ch || str[ 1 ] == toupper( ch ) )
&& ( str[ 2 ] == 0 ) )
return TRUE;

return FALSE;
}


int main( int argc, char * argv[] )
{
int ind;
structFlags sFlags;

printf( "FLATEX 1.20, 1994, 1996, by Sariel Har-Peled.\n\n" );
if ( argc == 1 )
printHelp();

sFlags.verbose = FALSE;
sFlags.fBibInsert = TRUE;
sFlags.cSpecialInputLevel = 0;
*sFlags.szFullName = 0;
sFlags.fQuiet = FALSE;

for ( ind = 1; ind < argc; ind++ ) {
if ( isFlag( argv[ ind ], 'v' ) ) {
sFlags.verbose = TRUE;
continue;
}
if ( isFlag( argv[ ind ], 'b' ) ) {
sFlags.fBibInsert = FALSE;
continue;
}
if ( isFlag( argv[ ind ], 'q' ) ) {
sFlags.fQuiet = TRUE;
continue;
}
if ( isFlag( argv[ ind ], 'x' ) ) {
flatOutFile( argv[ ind + 1 ], &sFlags );
ind++;
continue;
}

flatFile( argv[ ind ], &sFlags );
}
return 0;
}

/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
*
* flatex.C - End of File
\*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/


0 new messages