summaryrefslogblamecommitdiffstatshomepage
path: root/src/tools/srcclean.c
blob: 3f6cda2e3bbbad177bec1a8e984daa6b06c16928 (plain) (tree)
1
2
3
4
5
6
7





                                                                            
                                                








































                                                                                           
                    





                                                    
         




























































                                                                                                                              
                                










                                                                     

                                        
                 













                                                                       



                                                          
                 
                                             

                              




























                                                                                 
/***************************************************************************

    srcclean.c

    Basic source code cleanear.

    Copyright Nicola Salmoria and the MAME Team.
    Visit http://mamedev.org for licensing and usage restrictions.

***************************************************************************/

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

#include "corestr.h"
#include "osdcore.h"


/***************************************************************************
    CONSTANTS & DEFINES
***************************************************************************/

#define MAX_FILE_SIZE	(10 * 1024 * 1024)



/***************************************************************************
    GLOBAL VARIABLES
***************************************************************************/

static UINT8 original[MAX_FILE_SIZE];
static UINT8 modified[MAX_FILE_SIZE];



/***************************************************************************
    MAIN
***************************************************************************/

int main(int argc, char *argv[])
{
	int removed_tabs = 0, removed_spaces = 0, fixed_mac_style = 0, fixed_nix_style = 0;
	int src = 0, dst = 0, in_c_comment = FALSE, in_cpp_comment = FALSE;
	int hichars = 0;
	int is_c_file;
	const char *ext;
	FILE *file;
	int bytes;
	int col = 0;

	/* print usage info */
	if (argc != 2)
	{
		printf("Usage:\nsrcclean <file>\n");
		return 0;
	}

	/* read the file */
	file = fopen(argv[1], "rb");
	if (file == NULL)
	{
		fprintf(stderr, "Can't open %s\n", argv[1]);
		return 1;
	}
	bytes = fread(original, 1, MAX_FILE_SIZE, file);
	fclose(file);

	/* determine if we are a C file */
	ext = strrchr(argv[1], '.');
	is_c_file = (ext && (core_stricmp(ext, ".c") == 0 || core_stricmp(ext, ".h") == 0 || core_stricmp(ext, ".cpp") == 0));

	/* rip through it */
	for (src = 0; src < bytes; )
	{
		UINT8 ch = original[src++];

		/* check for invalid upper-ASCII chars */
		if (ch != 13 && ch != 10 && ch != 9 && (ch > 127 || ch < 32))
		{
			ch = '?';
			hichars++;
		}

		/* track whether or not we are within a C-style comment */
		if (is_c_file && !in_cpp_comment)
		{
			if (!in_c_comment && ch == '/' && original[src] == '*')
				in_c_comment = TRUE;
			else if (in_c_comment && ch == '*' && original[src] == '/')
				in_c_comment = FALSE;
		}

		/* track whether or not we are within a C++-style comment */
		if (is_c_file && !in_c_comment && ch == '/' && original[src] == '/')
			in_cpp_comment = TRUE;

		/* if we hit a LF without a CR, back up and act like we hit a CR */
		if (ch == 0x0a)
		{
			src--;
			ch = 0x0d;
			fixed_nix_style = 1;
		}

		/* if we hit a CR, clean up from there */
		if (ch == 0x0d)
		{
			/* remove all extra spaces/tabs at the end */
			while (dst > 0 && (modified[dst-1] == ' ' || modified[dst-1] == 0x09))
			{
				removed_spaces++;
				dst--;
			}

			/* insert a proper CR/LF */
			modified[dst++] = 0x0d;
			modified[dst++] = 0x0a;
			col = 0;

			/* skip over any LF in the source file */
			if (original[src] == 0x0a)
				src++;
			else
				fixed_mac_style = 1;

			/* we are no longer in a C++-style comment */
			in_cpp_comment = FALSE;
		}

		/* if we hit a tab... */
		else if (ch == 0x09)
		{
			int spaces = 4 - col % 4;

			col += spaces;

			/* if inside a comment, expand it */
			if (in_c_comment || in_cpp_comment)
			{
				while (spaces--) modified[dst++] = ' ';
				removed_tabs++;
			}
			else
			{
				modified[dst++] = ch;
			}
		}

		/* otherwise, copy the source character */
		else
		{
			modified[dst++] = ch;
			col++;
		}
	}

	/* if we didn't find an end of comment, we screwed up */
	if (in_c_comment)
	{
		printf("Error: unmatched C-style comment (%s)!\n", argv[1]);
		return 1;
	}

	/* if the result == original, skip it */
	if (dst != bytes || memcmp(original, modified, bytes))
	{
		/* explain what we did */
		printf("Cleaned up %s:", argv[1]);
		if (removed_spaces) printf(" removed %d spaces", removed_spaces);
		if (removed_tabs) printf(" removed %d tabs", removed_tabs);
		if (hichars) printf(" fixed %d high-ASCII chars", hichars);
		if (fixed_nix_style) printf(" fixed *nix-style line-ends");
		if (fixed_mac_style) printf(" fixed Mac-style line-ends");
		printf("\n");

		/* write the file */
		file = fopen(argv[1], "wb");
		fwrite(modified, 1, dst, file);
		fclose(file);
	}

	return 0;
}