| home | contents | previous | next page | send comment | send link | add bookmark |

xref.cpp

/*
**  C/C++ cross-reference utility
**
**  Usage:  xref filename.ext { filename.ext } [ -filelist.ext ]
**
**  By: Stephen R. Schmitt
*/

#include "stdafx.h"                             // generated by Visual C++ ver.6
#include <ctype.h>
#include <fstream.h>
#include <stdlib.h>
#include "symtab.h"
#include "scanner.h"

/*
**  declarations for xref class
*/
class xref : public symtab, public scanner
{
public:
    int  file_count;

    xref(){ file_count = 0; }
    void files( char * );

private:
    void get_file( char * );
    void get_list_files( char * );
    void build_table( char * );
    void assemble( char *, int );
    long file_length( ifstream * );
};

/*---------------------------------------------------------------------------*
**  "put_message" displays a message on usage of this program
**
**  returns:  nothing
*/
void put_message( char *buf )
{
    cout << endl;
    cout << "C/C++ cross reference utility.\n\n";
    cout << "Usage: xref [-]filename.ext { [-]filename.ext }\n\n";
    cout << "       - indicates file is a list of files\n";
    cout << "       output is file named \"xref.out\"\n" << endl;
    cout << "file: ";
    cin  >> buf;
    cout << endl;
}

/*---------------------------------------------------------------------------*
**  "main" program entry point
**
**  returns:  nothing
*/
void main( int argc,                            // number of files + 1
           char *argv[] )                       // file names
{
    int  n;                                     // counter
    char buffer[_MAX_PATH];                     // for file names
    xref x;                                     // cross refererence

    if( argc < 2 )                              // user dialog needed
    {
        put_message( buffer );
        x.files( buffer );                      // the truth is out there
    }
    else                                        // get command line input
    {
        n = 1;
        while( n < argc  )
        {
            strcpy( buffer, argv[n++] );
            x.files( buffer );                  // trust no one
        }
    }

    if( x.file_count )                          // at least one file was read
        x.output();
    else
        cout << "No files were processed " << endl;
}


/*
**  definitions for xref class
*/

#define MAXLINE 256

/*---------------------------------------------------------------------------*
**  "files" processes command line arguments.
**
**  returns:  nothing
*/
void xref::files( char *buffer )                // file name
{
    ifstream is;                                // input stream
    long length;                                // length of file to read
    char *text;                                 // of list file
    
    if( buffer[0] == '-' )                      // is a list of file names
    {
        is.open( &buffer[1], ios::binary | ios::nocreate );
        if( ! is )
        {
            cout << "Can't open " << &buffer[1] << endl;
            return;
        }

        length = file_length( &is );            // allocate memory for file
        text = new char[length + 1];
        if( ! text )
        {
            cout << "Out of memory" << endl;
            is.close();
            return;
        }

        is.read( text, length );                // read entire list of files
        text[length] = 0;
        is.close();
        get_list_files( text );                 // process files in list
        delete text;
    }
    else                                        // process a single file
        get_file( buffer );
}

/*---------------------------------------------------------------------------*
**  "get_list_files" processes files from a list.
**
**  returns: nothing
*/
void xref::get_list_files( char *list )         // names of file to process
{
    long i, j;                                  // counters
    char filename[_MAX_PATH];                   // listed file

    i = 0;
    while( 1 )                                  // extract file names
    {
        while( isspace( list[i] ) )
            i++;

        if( ! list[i] )                         // end of list file
            break;

        j = 0;
        while( !isspace( list[i] ) )            // copy file name to buffer
            filename[j++] = list[i++];

        filename[j] = 0;
        get_file( filename );                   // process a file
    }
}

/*---------------------------------------------------------------------------*
**  "get_file" opens a file and starts the word counting process.
**
**  returns: nothing
*/
void xref::get_file( char *srce_name )          // name of file to process
{
    ifstream is;                                // input stream
    long length;                                // length of file to read
    char *text;                                 // of file

    is.open( srce_name, ios::binary | ios::nocreate );
    if( ! is )
    {
        cout << "Can't open " << srce_name << endl;
        return;
    }

    length = file_length( &is );                // allocate memory for file
    text = new char[length + 1];
    if( ! text )
    {
        cout << "Out of memory" << endl;
        is.close();
        return;
    }

    is.read( text, length );                    // read entire file
    text[length] = 0;
    is.close();

    start( text );                              // do the processing
    build_table( srce_name );

    cout << "Processed " << srce_name << endl;
    file_count++;

    delete text;                                // free memory
}

/*---------------------------------------------------------------------------*
**  "file_length" determines the length of a file in bytes
**
**  returns: the length
*/
long xref::file_length( ifstream *in )          // the file
{
    long beg, end;                              // file pointer indices

    in->seekg( 0, ios::end );                   // get ending value 
    end = in->tellg();
    in->seekg( 0 );                             // get beginning value
    beg = in->tellg();

    return end - beg;                           // result
}

/*---------------------------------------------------------------------------*
**  "build_table" builds the cross reference table
**
**  returns:  nothing
*/
void xref::build_table( char *filename )        // of next file
{
    node *idp;                                  // identifiers
    node *fp;                                   // file names
    char word[MAXLINE];

    get_token();

    while( code != END_OF_FILE )
    {
        if( code == ID_TOKEN )
        {
            assemble( word, MAXLINE );

            // add word to table
            idp = search( word, Symbol_root );
            if( !idp )
                idp = enter( word, &Symbol_root );

            if( !idp )   
                return;

            // add file name
            fp = search( filename, idp->files ); 
            if( !fp )
                fp = enter( filename, &idp->files );

            if( !fp ) 
                return;

            // add line number
            add_instance( on_line, &fp->lines ); 
        }
        else
            get_token();
    }
}

/*---------------------------------------------------------------------------*
**  "assemble" joins identifiers of structure elements into
**  a single identifier.
**
**  returns:  nothing
*/
void xref::assemble( char *buffer,              // for table entry 
                     int   n )                  // length of buffer 
{
    memset( buffer, '\0', n );

    while( code == ID_TOKEN )
    {
        strcat( buffer, lexeme );
        get_token();

        if( ( code == ARROW ) || ( code == PERIOD ) )
        {
            strcat( buffer, lexeme );
            get_token();
        }
        else
            break;
    }
}

| home | contents | previous | next page | send comment | send link | add bookmark |

Copyright © 2004, Stephen R. Schmitt