main.cc

    /*
     * 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 ) ;
    }