/*****************************************************************************/
/*                                                                           */
/*				    main.c				     */
/*                                                                           */
/*	       Main program of the od65 object file dump utility	     */
/*                                                                           */
/*                                                                           */
/*                                                                           */
/* (C) 2000-2009, Ullrich von Bassewitz                                      */
/*                Roemerstrasse 52                                           */
/*                D-70794 Filderstadt                                        */
/* EMail:         uz@cc65.org                                                */
/*                                                                           */
/*                                                                           */
/* This software is provided 'as-is', without any expressed or implied       */
/* warranty.  In no event will the authors be held liable for any damages    */
/* arising from the use of this software.                                    */
/*                                                                           */
/* Permission is granted to anyone to use this software for any purpose,     */
/* including commercial applications, and to alter it and redistribute it    */
/* freely, subject to the following restrictions:                            */
/*                                                                           */
/* 1. The origin of this software must not be misrepresented; you must not   */
/*    claim that you wrote the original software. If you use this software   */
/*    in a product, an acknowledgment in the product documentation would be  */
/*    appreciated but is not required.                                       */
/* 2. Altered source versions must be plainly marked as such, and must not   */
/*    be misrepresented as being the original software.                      */
/* 3. This notice may not be removed or altered from any source              */
/*    distribution.                                                          */
/*                                                                           */
/*****************************************************************************/



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

/* common */
#include "cmdline.h"
#include "objdefs.h"
#include "version.h"

/* od65 */
#include "dump.h"
#include "error.h"
#include "fileio.h"
#include "global.h"



/*****************************************************************************/
/*     	       	     	       	     Data			  	     */
/*****************************************************************************/



static unsigned FilesProcessed = 0;



/*****************************************************************************/
/*     	       	     	       	     Code			  	     */
/*****************************************************************************/



static void Usage (void)
/* Print usage information and exit */
{
    fprintf (stderr,
    	     "Usage: %s [options] file [options] [file]\n"
    	     "Short options:\n"
       	     "  -h\t\t\tHelp (this text)\n"
       	     "  -H\t\t\tDump the object file header\n"
       	     "  -S\t\t\tDump segments sizes\n"
       	     "  -V\t\t\tPrint the version number and exit\n"
	     "\n"
	     "Long options:\n"
	     "  --dump-all\t\tDump all object file information\n"
	     "  --dump-dbgsyms\tDump debug symbols\n"
       	     "  --dump-exports\tDump exported symbols\n"
	     "  --dump-files\t\tDump the source files\n"
	     "  --dump-header\t\tDump the object file header\n"
	     "  --dump-imports\tDump imported symbols\n"
	     "  --dump-lineinfo\tDump line information\n"
	     "  --dump-options\tDump object file options\n"
	     "  --dump-segments\tDump the segments in the file\n"
       	     "  --dump-segsize\tDump segments sizes\n"
	     "  --help\t\tHelp (this text)\n"
       	     "  --version\t\tPrint the version number and exit\n",
    	     ProgName);
}



static void OptDumpAll (const char* Opt attribute ((unused)),
			const char* Arg attribute ((unused)))
/* Dump all object file information */
{
    What |= D_ALL;
}



static void OptDumpDbgSyms (const char* Opt attribute ((unused)),
			    const char* Arg attribute ((unused)))
/* Dump debug symbols contained in the object file */
{
    What |= D_DBGSYMS;
}



static void OptDumpExports (const char* Opt attribute ((unused)),
			    const char* Arg attribute ((unused)))
/* Dump the exported symbols */
{
    What |= D_EXPORTS;
}



static void OptDumpFiles (const char* Opt attribute ((unused)),
			  const char* Arg attribute ((unused)))
/* Dump the source files */
{
    What |= D_FILES;
}



static void OptDumpHeader (const char* Opt attribute ((unused)),
			   const char* Arg attribute ((unused)))
/* Dump the object file header */
{
    What |= D_HEADER;
}



static void OptDumpImports (const char* Opt attribute ((unused)),
			    const char* Arg attribute ((unused)))
/* Dump the imported symbols */
{
    What |= D_IMPORTS;
}



static void OptDumpLineInfo (const char* Opt attribute ((unused)),
			     const char* Arg attribute ((unused)))
/* Dump the line infos */
{
    What |= D_LINEINFO;
}



static void OptDumpOptions (const char* Opt attribute ((unused)),
			    const char* Arg attribute ((unused)))
/* Dump the object file options */
{
    What |= D_OPTIONS;
}



static void OptDumpSegments (const char* Opt attribute ((unused)),
			     const char* Arg attribute ((unused)))
/* Dump the segments in the object file */
{
    What |= D_SEGMENTS;
}



static void OptDumpSegSize (const char* Opt attribute ((unused)),
			    const char* Arg attribute ((unused)))
/* Dump the segments in the object file */
{
    What |= D_SEGSIZE;
}



static void OptHelp (const char* Opt attribute ((unused)),
		     const char* Arg attribute ((unused)))
/* Print usage information and exit */
{
    Usage ();
    exit (EXIT_SUCCESS);
}



static void OptVersion (const char* Opt attribute ((unused)),
			const char* Arg attribute ((unused)))
/* Print the assembler version */
{
    fprintf (stderr,
       	     "%s V%s - (C) Copyright 2000-2009, Ullrich von Bassewitz\n",
       	     ProgName, GetVersionAsString ());
}



static void DumpFile (const char* Name)
/* Dump information from the named file */
{
    unsigned long Magic;

    /* Try to open the file */
    FILE* F = fopen (Name, "rb");
    if (F == 0) {
	Error ("Cannot open `%s': %s", Name, strerror (errno));
    }

    /* Read the magic word */
    Magic = Read32 (F);

    /* Do we know this type of file? */
    if (Magic != OBJ_MAGIC) {

	/* Unknown format */
       	printf ("%s: (no xo65 object file)\n", Name);

    } else if (What == 0) {

	/* Special handling if no info was requested */
     	printf ("%s: (no information requested)\n", Name);

    } else {

     	/* Print the filename */
     	printf ("%s:\n", Name);

     	/* Check what to dump */
     	if (What & D_HEADER) {
     	    DumpObjHeader (F, 0);
     	}
	if (What & D_OPTIONS) {
	    DumpObjOptions (F, 0);
	}
	if (What & D_FILES) {
	    DumpObjFiles (F, 0);
	}
	if (What & D_SEGMENTS) {
	    DumpObjSegments (F, 0);
	}
	if (What & D_IMPORTS) {
	    DumpObjImports (F, 0);
	}
	if (What & D_EXPORTS) {
	    DumpObjExports (F, 0);
	}
	if (What & D_DBGSYMS) {
	    DumpObjDbgSyms (F, 0);
	}
	if (What & D_LINEINFO) {
	    DumpObjLineInfo (F, 0);
	}
	if (What & D_SEGSIZE) {
       	    DumpObjSegSize (F, 0);
	}
    }

    /* Close the file */
    fclose (F);
}



int main (int argc, char* argv [])
/* Assembler main program */
{
    /* Program long options */
    static const LongOpt OptTab[] = {
       	{ "--dump-all",	   	0,     	OptDumpAll		},
	{ "--dump-dbgsyms",	0,	OptDumpDbgSyms		},
	{ "--dump-exports",	0,	OptDumpExports		},
	{ "--dump-files", 	0,	OptDumpFiles		},
	{ "--dump-header",	0,	OptDumpHeader		},
	{ "--dump-imports",	0,	OptDumpImports		},
        { "--dump-lineinfo",    0,      OptDumpLineInfo         },
	{ "--dump-options",	0,	OptDumpOptions		},
	{ "--dump-segments",	0,	OptDumpSegments		},
       	{ "--dump-segsize",    	0,     	OptDumpSegSize          },
	{ "--help",    		0,	OptHelp			},
	{ "--version", 	       	0,	OptVersion		},
    };

    unsigned I;

    /* Initialize the cmdline module */
    InitCmdLine (&argc, &argv, "od65");

    /* Check the parameters */
    I = 1;
    while (I < ArgCount) {

       	/* Get the argument */
       	const char* Arg = ArgVec[I];

       	/* Check for an option */
       	if (Arg [0] == '-') {
       	    switch (Arg [1]) {

	 	case '-':
	 	    LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0]));
	 	    break;

	 	case 'h':
	 	    OptHelp (Arg, 0);
	 	    break;

	 	case 'H':
		    OptDumpHeader (Arg, 0);
		    break;

	 	case 'S':
		    OptDumpSegSize (Arg, 0);
		    break;

       	        case 'V':
    		    OptVersion (Arg, 0);
       		    break;

       	       	default:
       	       	    UnknownOption (Arg);
		    break;

     	    }
       	} else {
    	    /* Filename. Dump it. */
	    DumpFile (Arg);
	    ++FilesProcessed;
     	}

	/* Next argument */
	++I;
    }

    /* Print a message if we did not process any files */
    if (FilesProcessed == 0) {
	fprintf (stderr, "%s: No input files\n", ProgName);
    }

    /* Success */
    return EXIT_SUCCESS;
}



