/*
* Copyright (C) 1999, 2000 Lorenzo Bettini, lorenzo.bettini@penteres.it
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <stdio.h>
#include <string.h>
#include <iostream.h>
#include <fstream.h>
#include "version.h"
#include "main.h"
#include "colors.h"
#include "tags.h"
#include "keys.h"
#include "textgen.h"
#include "decorators.h"
#include "generators.h"
#include "messages.h"
#include "cmdline.h"
#include "copyright.h"
#define OUTPUT_EXTENSION ".html"
/* global symbols */
char *inputFileName, *outputFileName ; /* what we're reading */
ostream* sout ;
int tabSpaces = 0 ; // space to substitue to tabs
int entire_doc = 0 ; // we want a real html doc
int otherArgs ;
short verbose = 0 ;
char *cssUrl = 0 ;
int use_css = 0 ; // Use CSS instead of font-tags
char *programName = 0 ;
char *programVersion = 0 ;
extern int yylex() ;
extern int parseTags() ;
static char *read_file(char *fileName);
static void file_error(const char *error, char *fileName);
static void internal_error(const char *error);
int
main( int argc, char * argv[] )
{
char *docTitle;
char *docHeader; // the buffer with the header
char *docFooter; // the buffer with the footer
char *header_fileName = 0;
char *footer_fileName = 0;
gengetopt_args_info args_info ; // command line structure
unsigned i;
int v;
if((v = cmdline_parser(argc, argv, &args_info)) != 0)
// calls cmdline parser. The user gived bag args if it doesn't return -1
return 1;
programName = PACKAGE ;
programVersion = VERSION ;
/* initialization of global symbols */
inputFileName = outputFileName = 0 ;
sout = 0 ;
docTitle = 0 ;
docHeader = 0 ;
docFooter = 0 ;
// adjust flags for command line parameters
otherArgs = 1;
docTitle = args_info.title_arg ;
header_fileName = args_info.header_arg ;
footer_fileName = args_info.footer_arg ;
verbose = args_info.verbose_given ;
if ( args_info.tab_given > 0 )
tabSpaces = args_info.tab_arg ;
if (header_fileName)
docHeader = read_file (header_fileName);
if (footer_fileName)
docFooter = read_file (footer_fileName);
cssUrl = args_info.css_arg ;
use_css = ( cssUrl != 0 ) ;
entire_doc = ( args_info.doc_given || (docTitle != 0) || use_css ) ;
inputFileName = args_info.input_arg ;
if ( inputFileName ) {
outputFileName = args_info.output_arg ;
if ( ! outputFileName ) {
outputFileName = createOutputFileName( inputFileName ) ;
}
}
if ( verbose )
setMessager( new DefaultMessages ) ;
printMessage( PACKAGE " " VERSION ) ;
parseTags() ;
if( use_css ) {
createGeneratorsForCSS() ;
}
else {
createGenerators() ;
}
// let's start the translation :-)
// first the --input file
if ( ! args_info.inputs_num )
processFile( inputFileName, outputFileName, docTitle, docHeader, docFooter ) ;
// let's process other files, if there are any
if ( args_info.inputs_num ) {
for ( i = 0 ; i < (args_info.inputs_num) ; ++i ) {
processFile( args_info.inputs[i],
createOutputFileName( args_info.inputs[i] ),
docTitle, docHeader, docFooter ) ;
cerr << "Processed " << args_info.inputs[i] << endl ;
}
}
return (0 );
}
char *
read_file(char *fileName)
{
FILE *file;
char *buffer = 0;
long int char_count;
// we open it as binary otherwise we may experience problems under
// Windows system: when we fread, the number of char read can be
// less then char_count, and thus we'd get an error...
if ( (file = fopen(fileName,"rb") ) == 0 ) // The file does not exist :(
file_error ("Error operning", fileName);
else
{
// let's go to the end of the file...
if (fseek (file, 0, SEEK_END) != 0)
file_error ("Error positioning", fileName);
// ...to read the dimension
char_count = ftell (file);
if (char_count < 0)
file_error ("Error reading position", fileName);
buffer = (char *) malloc (char_count +1);
if (! buffer)
internal_error ("Memory allocation failed");
// let's go back to the start
rewind (file);
if (fread ((void *) buffer, 1, char_count, file) < (size_t) char_count)
file_error ("read error", fileName);
buffer[char_count] = '\0';
fclose (file);
}
return buffer;
}
void
file_error(const char *error, char *file)
{
fprintf (stderr, "%s: %s, file %s\n", PACKAGE, error, file);
exit (1);
}
void
internal_error(const char *error)
{
fprintf (stderr, "%s: Internal error: %s\n", PACKAGE, error);
exit (1);
}
// output file name = input file name + ".html"
char *createOutputFileName( char *inputFileName ) {
char *outputFileName = new char[ strlen(inputFileName) +
strlen(OUTPUT_EXTENSION) + 1 ] ;
strcpy( outputFileName, inputFileName ) ;
strcat( outputFileName, OUTPUT_EXTENSION ) ;
return outputFileName ;
}
void processFile( char *inputFileName, char *outputFileName, char *docTitle,
const char *docHeader, const char *docFooter) {
FILE *in = 0;
short deleteOStream = 1 ;
if ( outputFileName ) {
sout = new ofstream(outputFileName) ;
if ( ! sout ) {
cerr << "Error in creating " << outputFileName << " for output" << endl ;
exit(1) ;
}
}
if ( inputFileName ) {
in = freopen (inputFileName, "r", stdin);
if (!in) {
cerr << "Error in opening " << inputFileName
<< " for input" << endl ;
exit(1) ;
}
}
/*
* Use default values for any options not provided
*/
if (sout == 0) {
sout = &cout;
deleteOStream = 0 ; // we can't delete cout !!!
}
if (in == 0) {
; /* Well stdin already points to stdin so, .... */
}
if (docTitle == 0) {
docTitle = inputFileName; /* inputFileName may also be 0,
this is OK. */
}
if ( entire_doc ) {
print_top( docTitle, cssUrl, docHeader );
}
printMessage( "translating source code... ", cerr ) ;
generateln( "<pre>" ) ;
generateln( "<tt>" ) ;
yylex() ;
generateln( "</tt>" ) ;
generateln( "</pre>" ) ;
printMessage( "done !", cerr ) ;
if ( entire_doc )
print_bottom( docFooter ) ;
if ( deleteOStream )
delete sout ;
}
void
print_top( char *docTitle, char *cssUrl , const char *docHeader)
{
if( cssUrl == 0 ) {
generateln( "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">" ) ;
}
else {
generateln( "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\"");
generateln( " \"http://www.w3.org/TR/REC-html40/strict.dtd\">");
}
generateln( "<html>" ) ;
generateln( "<head>" ) ;
generateln( "<meta http-equiv=\"Content-Type\"" ) ;
generateln( "content=\"text/html; charset=iso-8859-1\">" ) ;
generate( "<meta name=\"GENERATOR\" content=\"" ) ;
generate( PACKAGE " " VERSION ) ;
generate( "\nby Lorenzo Bettini, bettini@gnu.org" ) ;
generate( "\nhttp://w3.newnet.it/bettini" ) ;
generate( "\nhttp://www.gnu.org/software/" PACKAGE "/" PACKAGE ".html" ) ;
generateln( "\">" ) ;
generate( "<title>" ) ;
generate( ( docTitle ? docTitle :
( inputFileName ? inputFileName : "source file" ) ) ) ;
generateln( "</title>" ) ;
if( cssUrl != 0 ) {
generate( "<link rel=\"stylesheet\" href=\"" );
generate( cssUrl );
generateln( "\" type=\"text/css\">");
}
generateln( "</head>" ) ;
if( cssUrl == 0 && docHeader == 0) {
generate ("<body bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#0000EE\" ");
generateln ( "vlink=\"#551A8B\" alink=\"#FF0000\">" );
}
else {
generateln( "<body>" ) ;
}
if (docHeader)
generateln (docHeader) ;
}
void print_bottom( const char *docFooter) {
if ( docFooter ) generateln( docFooter ) ;
generateln( "</body>" ) ;
generateln( "</html>" ) ;
}
void generate( const char *s ) {
GlobalGenerator->generate(s) ;
}
void
generate( const char *s, int start, int end )
{
GlobalGenerator->generate(s, start, end) ;
}
void generateln( const char *s ) {
GlobalGenerator->generateln(s) ;
}
void generateNewLine() {
generateln( "" ) ;
}
void generateTab() {
if ( tabSpaces )
for ( register int i = 0 ; i < tabSpaces ; ++i )
generate( SPACE_CHAR ) ;
else
generate( "\t" ) ;
}
void startComment( const char *s )
{
CommentGenerator->beginText(s) ;
}
void endComment( const char *s )
{
CommentGenerator->endText(s) ;
}
void generateComment( const char *s ) {
CommentGenerator->generateEntire(s) ;
}
void startString( const char *s )
{
StringGenerator->beginText(s) ;
}
void endString( const char *s )
{
StringGenerator->endText(s) ;
}
void generateString( const char *s ) {
StringGenerator->generateEntire(s) ;
}
void generateKeyWord( const char *s ) {
KeywordGenerator->generateEntire(s) ;
}
void generateBaseType( const char *s ) {
TypeGenerator->generateEntire(s) ;
}
void generateNumber( const char *s ) {
NumberGenerator->generateEntire(s) ;
}
void startTAG( const char *tag, const char *attr, const char *val ) {
(*sout) << "<" << tag ;
if ( attr && val )
(*sout) << " " << attr << "=" << val ;
(*sout) << ">" ;
}
void endTAG( const char *tag ) {
(*sout) << "</" << tag << ">" ;
}
void startColor( const char *color ) {
startTAG( FONT_TAG, COLOR_TAG, color ) ;
}
void endColor() {
endTAG( FONT_TAG ) ;
}