Linux下格式化代码的小工具

/**
 * Li Feng
 * 2011/09/12
 * */

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>

#define FLEN 1024	// file name length
#define LINELEN 1024 	// line length
#define FLAG_ON 1
#define FLAG_OFF 0
#define DEPTH 128	// stack depth
 
typedef enum { 
	_IF, 
	_WHILE, 
	_DO, 
	_FOR, 
	_ELSE, 
	_SWITCH,	// before switch these keywords can be repalced by '{'
	_CASE,   
	_DEFAULT,
	KEYWORDCNT,	// stand for the number of keywords
	_LS,		// stands for '('
	_LB,		// stands for '{'
	_RS,		// stands for ')'
	_RB,		// stands for '}'
	_SEMICOLON	// stands for ';'
} mykey_t;		// these are all domains except KEYWORDCNT

typedef struct
{
	mykey_t type;	// domain type
	int nexttabs;	// next line ahead tabs
	int currtabs;	// current line ahead tabs
	int isself;	// when isself == FLAG_ON use currtabs otherwise nexttabs 
	int linenum;	// linenum
	int issub;	// only used in situation of xxx = {.....    next line }
} domain_t;

typedef struct
{
	mykey_t type;	// keyword type
	int offset;	// keyword's offset in the line
} keyword_t;

char *keywords[KEYWORDCNT] = { "if", "while", "do", "for", 
				"else", "switch", "case", "default" };
typedef enum{
	_CMT,	// comment line
	_BLK,	// blank line
	_NOR,	// normal line
}linetype_t;

/* read every line in the file and adjust the format*/
void adjfmt( char* line, char* buf, int* sflag, int* cflag, 
		int* domaintop, domain_t** domainS, int linenum );
/* when domain is '}',')'or';' popout domains*/
void popdomain( mykey_t domainkey, int* domaintopp, domain_t** domainS, int linenum );
void pushdomain( mykey_t domainkey, int* domaintopp, domain_t** domainS, int linenum );
void myinsertSort( keyword_t** tosort, int start, int end );
void myquickSort( keyword_t** tosort, int start, int end );
/* sort keywords by offset*/
void sortorigbyoffset( keyword_t** origkeywordS, int origtop );
/* get keywords in the line*/
void getorigkeywords(char* line, int* origtop, keyword_t** origkeywordS );
/* push keywords into the keywords stack*/
void pushorig(int offset, mykey_t type, int* origtopp, keyword_t** origkeywordS);
/* check is keywords or domains in the string*/
void checkstr( char* line, int index ,int *flag);
/* do prasefile in the file stack*/
void execS( char** fileS, int* filetop );
/* put files into the file stack*/
void Sfile( char* fname, char** fileS, int* filetop );
/* count souce*/
void cntsource( char* line, int* sflag, int* cflag, linetype_t* linetype );
/* do adjust to the file*/
int prasefile(char* _fname);
/* check domains' right*/
int checkright(char r, mykey_t type);
/* check domains' left*/
int checkleft(char l, mykey_t type);
/* prase directory*/
int prasedir(char* _fname, char** fileS, int* filetop);
/* check is keywords in comment*/
int checkcomment( char* line, int index, int* flag);
/* quick sort get mid*/
int getmid( keyword_t** tosort, int start, int end );
/* quicksort partion*/
int mypartion( keyword_t** tosort, int start, int end );
/* rule out keywords*/
mykey_t ruleoutkeywords(int offset, int* origtopp, keyword_t** origkeywordS );
/* not used*/
keyword_t* poporig(int* origtopp, keyword_t** origkeywordS);

static int mlcc1 =0, frc1 = 0;	// malloc and free counter for keyword
static int mlcc2 =0, frc2 = 0;	// malloc and free counter for domain
static int mlcc3 =0, frc3 = 0;	// malloc and free counter for fname
/* flag reverse*/
static const char *shortoptions = "bcfnr";
static int isrecursive = FLAG_OFF;
static int isformat = FLAG_OFF;
static int iscount = FLAG_OFF;
static int isrollback = FLAG_OFF;
static int isbackup = FLAG_ON;
static int cmtline = 0, blkline = 0, norline = 0;

inline static void printusg()
{
	printf( "Usage:blktotab < [ [-b] or [ [-f] [-c] ] ] > [-r] [-n] < [directory] [file]... > \n" );
	printf( "\t-b: roll back formated source\n");
	printf( "\t-c: count how many blank, comment and normal lines in the file\n" );
	printf( "\t-f: format the source code\n");
	printf( "\t\tyou can only choose one from -b and -f\n");
	printf( "\t-n: no back up(have effect only when -f option is specified)\n");
	printf( "\t\tWith *.bttbak files you can roll back by use ./blktotab -b -r [dir or file]\n");
	printf( "\t-r: recursive\n");
	printf( "In command line you can specify up to 128 files or directorys, and at least 1\n");
	printf( "Ex:./blktotab -f -c -r dir1 file1\n");
}

inline static void perr(char* errstr)
{
	printf("%s err\n", errstr);
}

int main( int argc, char* argv[] )
{
	int ret = 0, filetop = 0;
	char fnames[DEPTH][FLEN] = { {0} };
	char fname[FLEN] = { 0 };
	//char fname[FLEN] = "aa.c";
	struct stat buf = { 0 };
	char* fileS[DEPTH] = { 0 };
	int optcnt = 1, filecnt = 0;
	int opt = 0;
	if( 2 > argc )
	{
		printusg();
		exit( -1 );
	}
	while ((opt = getopt(argc, argv, shortoptions)) != EOF)
	{
		switch(opt)
		{
			case 'b':
				isrollback = FLAG_ON;
				break;
			case 'r':
				isrecursive = FLAG_ON;
				break;
			case 'c':
				iscount = FLAG_ON;
				break;
			case 'f':
				isformat = FLAG_ON;
				break;
			case 'n':
				isbackup = FLAG_OFF;
				break;
			default:
				printusg( );
				exit( 0 );
				break;
		}
	}
	
	if( FLAG_OFF == iscount && FLAG_OFF == isformat && FLAG_OFF == isrollback )
	{
		printusg();
		exit( 0 );
	}
	
	if( ( FLAG_ON == isformat || FLAG_ON == iscount ) && FLAG_ON == isrollback )
	{
		printusg();
		exit( 0 );
	}

	while( optcnt < argc )
	{
		if( argv[optcnt][0] != '-' )
		{
			if( DEPTH > filecnt )
			{
				strncpy( fnames[filecnt], argv[optcnt], strlen( argv[optcnt] ) );
				//printf("%s\n", fnames[filecnt]);
				++filecnt;
			}else perr("too much file on command line\n");
		}
		++optcnt;
	}

	optcnt = 0;
	
	while( optcnt < filecnt )
	{
		strncpy( fname, fnames[optcnt], strlen( fnames[optcnt] ) );
		++optcnt;
		ret = access( fname, R_OK );
		if( ret < 0 )
		{
			perr("access");
			exit( -1 );
		}
		ret = lstat( fname, &buf );
		if( ret < 0 )
		{
			perr("lstat");
			exit( -1 );
		}
		if( S_ISREG( buf.st_mode ) )
		{
			char* temp = NULL;
			temp = strrchr( fname, '.' );
			if( temp != NULL )
			{
				int len = strlen( temp );
				if( ( 2 == len && ( strncmp( temp, ".c", 2 ) == 0 || strncmp( temp, ".h", 2) == 0 ) ) ||
					( 3 == len && strncmp( temp, ".cc", 3 ) == 0 ) ||
					( 4 == len && ( strncmp( temp, ".cxx", 4 ) == 0 || strncmp( temp, ".cpp", 4 ) == 0 ) ) || 
					( 5 == len && strncmp( temp, ".java", 5 ) == 0 ) ) 
				{
					ret = prasefile( fname );
					if( 0 != ret )
						perr("prasefile");
				}else if( FLAG_ON == isrollback && 7 == len && strncmp( temp, ".bttbak", 7 ) == 0 )
				{
					char rollbackname[FLEN] = { 0 };
					strncpy( rollbackname, fname, strlen( fname ) );
					temp = strrchr( rollbackname, '.' );
					*temp = '\0';
					unlink(rollbackname);
					ret = rename( fname, rollbackname );
					if( 0 != ret )
					{
						perr( "rename" );
						return ret;
					}
				}
			}else{ }
		}else if( S_ISDIR( buf.st_mode ) )
		{
			//printf( "directory\n" );
			ret = prasedir( fname, fileS, &filetop );
			if( 0 != ret)
				perr("prasedir");
			execS( fileS, &filetop );
		}else{
			printf( "other type of file, do nothing\n" );
			printusg();
			exit(0);
		}
		memset( fname, 0, FLEN );
	}
	
	if( 0 == optcnt )
	{
		printusg( );
		exit( 0 );
	}

	if( FLAG_ON == iscount ){
		printf("In all prased files have %d normal lines, %d comment lines, %d blank lines\n", 
			norline, cmtline, blkline );
	}
	if( FLAG_ON == isformat ){
		printf( "At end [mlcc1:%d,frc1:%d] [mlcc2:%d,frc2:%d] [mlcc3:%d,frc3:%d]\n",
			mlcc1, frc1, mlcc2, frc2, mlcc3, frc3 );	
	}
	return ret;
}

void execS( char** fileS, int* filetopp )
{
	//printf("%d:%s start\n",__LINE__,__FUNCTION__);
	int filetop = *filetopp;
	while( filetop > 0 )
	{
		prasefile( fileS[--filetop] );
		free( fileS[filetop] );
		frc3++;
	}
	*filetopp = filetop;
	//printf("%d:%s end\n",__LINE__,__FUNCTION__);
}

void Sfile( char* fname, char** fileS, int* filetopp )
{
	//printf("%d:%s start\n",__LINE__,__FUNCTION__);
	fileS[(*filetopp)++] = fname;
	//printf("%d:%s end\n",__LINE__,__FUNCTION__);
}

int prasedir(char* dirname, char** fileS, int* filetop)
{
	//printf("%d:%s start\n",__LINE__,__FUNCTION__);
	DIR *dp = NULL;
	int ret = 0;
	struct dirent *dirp = NULL;
	struct stat buf = { 0 };

	if( (dp = opendir( dirname )) == NULL )
		perr("opendir");
	while( (dirp = readdir(dp)) != NULL )
	{
		char *d_name = dirp->d_name;
		if( strcmp( d_name, ".." ) == 0 || strcmp( d_name, "." ) == 0 || 
			strcmp( d_name, ".svn" ) == 0 ) continue;
		char* fname = ( char * )malloc(FLEN);
		mlcc3++;
		sprintf( fname, "%s/%s", dirname, d_name );
		ret = lstat( fname, &buf );
		if( ret < 0 )
		{
			perr("lstat");
			free(fname);
			frc3++;
			exit( -1 );
		}
		if( S_ISREG( buf.st_mode ) )
		{
			char* temp = NULL;
			temp = strrchr( d_name, '.' );
			if( temp != NULL )
			{
				int len = strlen( temp );
				if( ( 2 == len && ( strncmp( temp, ".c", 2 ) == 0 || strncmp( temp, ".h", 2) == 0 ) ) ||
					( 3 == len && strncmp( temp, ".cc", 3 ) == 0 ) ||
					( 4 == len && ( strncmp( temp, ".cxx", 4 ) == 0 || strncmp( temp, ".cpp", 4 ) == 0 ) ) || 
					( 5 == len && strncmp( temp, ".java", 5 ) == 0 ) ) 
				{
					if( DEPTH  == *filetop )
						execS(fileS, filetop );
					Sfile( fname, fileS, filetop );
				}else if( FLAG_ON == isrollback && 7 == len && strncmp( temp, ".bttbak", 7 ) == 0 ){
					char rollbackname[FLEN] = { 0 };
					
					strncpy( rollbackname, fname, strlen( fname ) );
					temp = strrchr( rollbackname, '.' );
					*temp = '\0';
					unlink(rollbackname);
					ret = rename( fname, rollbackname );
					if( 0 != ret )
					{
						perr( "rename" );
						return ret;
					}

					free(fname);
					frc3++;
				}else{
					free(fname);
					frc3++;
				}
			}else{
				free(fname);
				frc3++;
			}
		}else if( S_ISDIR( buf.st_mode ) )
		{
			//printf( "directory\n" );
			if( FLAG_ON == isrecursive ){
				ret = prasedir( fname, fileS, filetop );
				if( 0 != ret)
				{
					free(fname);
					frc3++;
					perr("prasedir");
				}
			}
			free(fname);
			frc3++;
		}else {
			free(fname);
			frc3++;
		}
	}
	closedir(dp);
	//printf("%d:%s end\n",__LINE__,__FUNCTION__);
	return 0;
}

int prasefile(char* _fname)
{
	//printf("%d:%s start\n",__LINE__,__FUNCTION__);
	printf( "start prase file:%s\n", _fname );

	int ret = 0;
	FILE *infd = NULL, *outfd = NULL;
	int strflagforfmt = FLAG_OFF, strflagforcnt = FLAG_OFF;
	int cmtflagforfmt = FLAG_OFF, cmtflagforcnt = FLAG_OFF;
	char bakname[FLEN] = { 0 };
	char rdbuf[LINELEN] = { 0 };
	char rtnbuf[LINELEN] = { 0 };
	int domaintop = 0;	
	domain_t* domainS[DEPTH] = { 0 };


	int lcmtline = 0, lblkline = 0, lnorline = 0;
	linetype_t linetype = _BLK;

	
	if( FLAG_ON == isformat )
	{
		strncpy( bakname, _fname, strlen( _fname ) );
		strncat( bakname, ".bttbak", 7 );
		ret = rename( _fname, bakname );
		if( 0 != ret )
		{
			perr( "rename" );
			return ret;
		}

		infd = fopen( bakname, "r+" );
		if( NULL == infd )
		{
			perr( "fopen infd");
			return -1;
		}
		outfd = fopen( _fname, "w+" );
		if( NULL == outfd )
		{
			perr( "fopen outfd");
			fclose( infd );
			return -1;
		}
	}else{
		infd = fopen( _fname, "r+" );
		if( NULL == infd )
		{
			perr( "fopen infd");
			return -1;
		}
	}
	int linenum = 0;
	while( NULL != fgets( rdbuf, LINELEN, infd ) )
	{
		if( FLAG_ON == isformat )
		{
			//printf("in line %d\n", ++linenum);
			adjfmt( rdbuf, rtnbuf, &strflagforfmt, &cmtflagforfmt, &domaintop, domainS, ++linenum );
			fwrite( rtnbuf, strlen(rtnbuf), 1, outfd ); 
			memset( rtnbuf, 0x00, LINELEN );
		}
		if( FLAG_ON == iscount )
		{
			cntsource( rdbuf, &strflagforcnt, &cmtflagforcnt, &linetype );
			switch(linetype)
			{
				case _BLK:
					++lblkline;
					break;
				case _CMT:
					++lcmtline;
					break;
				case _NOR:
					++lnorline;
					break;
			}
		}
	}
	if( FLAG_ON == isformat ){
		//printf("at end domaintop is %d\n", domaintop);
		while(domaintop > 0)
		{
			free( domainS[--domaintop] );
			frc2++;
		}
		fflush( outfd );	
		fclose( outfd );
	}
	if( FLAG_ON == iscount )
	{
		printf("file %s has %d normal lines, %d comment lines, %d blank lines\n", 
			_fname, lnorline, lcmtline, lblkline );
		norline += lnorline;
		cmtline += lcmtline;
		blkline += lblkline;
	}
	fclose( infd );

	if( FLAG_ON == isformat && FLAG_OFF == isbackup )
	{
		unlink( bakname );
	}
	//printf("%d:%s end\n",__LINE__,__FUNCTION__);
	printf( "end prase file:%s\n", _fname );
	return ret;
}

void cntsource( char* line, int* sflag, int* cflag, linetype_t* linetype )
{
	//printf("%d:%s start\n",__LINE__,__FUNCTION__);
	
	int i = 0, startclm = 0;
	*linetype = _BLK;
	for( startclm = 0; startclm < strlen( line ); startclm++ )
	{
		if( '\t' != line[startclm] && ' ' != line[startclm] 
			&& '\n' != line[startclm] && '\r' != line[startclm] )
			break;
	}
	for( i = startclm; i < strlen( line ); i++ )
	{
		if( *linetype == _BLK ) *linetype = _CMT;

		if( FLAG_OFF == *sflag )
		{
			if( FLAG_ON == checkcomment( line, i, cflag ) )
				break;
		}

		if( FLAG_OFF == *cflag )
		{
			*linetype = _NOR;
			checkstr( line, i, sflag);
		}

	}//for( i = 0; i < strlen( line ); i++ )
}

void adjfmt( char* line, char* buf, int* sflag, int* cflag, 
	int* domaintop, domain_t** domainS, int linenum)
{
	//printf("%d:%s start\n",__LINE__,__FUNCTION__);
	
	int i = 0, startclm = 0;
	char *linestart = 0;
	int origtop = 0;
	keyword_t* origkeywordS[DEPTH+1] = { 0 };
	domain_t* localdom = NULL;
	

	getorigkeywords( line, &origtop, origkeywordS );
	sortorigbyoffset( origkeywordS, origtop );

	for( startclm = 0; startclm < strlen( line ); startclm++ )
	{
		if( '\t' != line[startclm] && ' ' != line[startclm] && '\r' != line[startclm] )
			break;
	}
	linestart = line + startclm;
	
	for( i = startclm; i < strlen( line ); i++ )
	{

		if( FLAG_OFF == *sflag )
		{
			if( FLAG_ON == checkcomment( line, i, cflag ) )
				break;
		}

		if( FLAG_OFF == *cflag )
		{
			checkstr( line, i, sflag);
		}

		if( FLAG_OFF == *cflag && FLAG_OFF == *sflag )
		{
			mykey_t domainkey = ruleoutkeywords( i, &origtop, origkeywordS );
			if( KEYWORDCNT != domainkey )
			{
				pushdomain( domainkey, domaintop, domainS, linenum );
				continue;
			}
			if( i > 0 && i < strlen(line) - 1 && '\'' == line[i-1] && '\'' == line[i+1] )
				continue;
			
			switch(line[i]) 
			{
				case '{':
					pushdomain( _LB, domaintop, domainS, linenum );
					localdom = domainS[*domaintop-1];
					int j = i - 1;
					while( j >= 0 )
                                       	{
                                               	if( '\t' == line[j] || ' ' == line[j])
                                               	{
                                                       	--j;
                                                       	continue;
                                               	}else{
                                                       	if( '=' == line[j] )
                                                               	localdom->issub = FLAG_OFF;
							break;
                                                }
                                        }
					if( FLAG_OFF == localdom->issub )
						localdom->nexttabs = localdom->nexttabs + ( i - startclm ) / 8;
					localdom = NULL;
					break;
				case '(':
					pushdomain( _LS, domaintop, domainS, linenum );
					localdom = domainS[*domaintop-1];
					localdom->nexttabs = localdom->nexttabs + ( i - startclm ) / 8;
					localdom = NULL;
					break;
				case '}':
					popdomain( _RB, domaintop, domainS, linenum );
					localdom = domainS[*domaintop-1];
					if( i > startclm && localdom->linenum < linenum )
						localdom->currtabs = localdom->nexttabs;
					else if( FLAG_OFF == localdom->issub && localdom->linenum < linenum )
						localdom->currtabs = localdom->nexttabs - 1;
					localdom = NULL;
					break;
				case ')':
					popdomain( _RS, domaintop, domainS, linenum );
					break;
				case ';':
					popdomain( _SEMICOLON, domaintop, domainS, linenum );
					break;
			}
		}//if( FLAG_OFF == *cflag && FLAG_OFF == *sflag )
	}//for( i = 0; i < strlen( line ); i++ )
	
	while( origtop > 0 ){
		free( origkeywordS[--origtop] );
		frc1++;
	}
	int currtabs = 0;
	if( 0 < *domaintop )
	{
		localdom = domainS[*domaintop-1];
		mykey_t localtype = localdom->type;
		if( localdom->isself == FLAG_ON )
		{
			localdom->isself = FLAG_OFF;
			currtabs = localdom->currtabs;
		}else{
			currtabs = localdom->nexttabs;
		}
		
		if( _CASE == localtype || _DEFAULT == localtype 
			|| _RS == localtype || _RB == localtype || _SEMICOLON == localtype )
		{
			free(localdom);
			frc2++;
			localtype = KEYWORDCNT;
			localdom = NULL;
			domainS[--*domaintop] = 0;
		}
	}

	i = 0;
	while( i < currtabs )
		buf[i++] = '\t';

	strncat( buf, linestart, strlen( linestart ) );

	//printf("%d:%s end\n",__LINE__,__FUNCTION__);
}

void popdomain( mykey_t domainkey, int* domaintopp, domain_t** domainS, int linenum )
{
	//printf("%d:%s start\n",__LINE__,__FUNCTION__);
	int domaintop = 0;
	mykey_t prevtype = KEYWORDCNT;
	domain_t* prevdom = NULL;
	
	domaintop = *domaintopp;

	if( domaintop == 0 )
	{
		if( _SEMICOLON != domainkey )
			perr( "domainS empty" );
	}

	if( 0 < domaintop )
	{
		prevdom = domainS[domaintop-1];
		prevtype = prevdom->type;

		if( _CASE == prevtype || _DEFAULT == prevtype || _SEMICOLON == prevtype )
		{
			free(domainS[--domaintop]);
			frc2++;
			prevtype = KEYWORDCNT;
			prevdom = NULL;
			domainS[domaintop] = 0;
		}else if( _RS == prevtype || _RB == prevtype )
		{
			if( _SEMICOLON == domainkey ) 
			{
				if( domaintop > 1 && domainS[domaintop-2]->type < _SWITCH )
				{
					domainS[domaintop-2]->nexttabs = prevdom->currtabs;
					free(domainS[--domaintop]);
					frc2++;
					prevtype = KEYWORDCNT;
					prevdom = NULL;
					domainS[domaintop] = 0;
				}else{
					prevdom->type = _SEMICOLON;	
				}
			}else{
				free(domainS[--domaintop]);
				frc2++;
				prevtype = KEYWORDCNT;
				prevdom = NULL;
				domainS[domaintop] = 0;
			}
		}
		if( prevdom == NULL && 0 < domaintop )
		{
			prevdom = domainS[domaintop-1];
			prevtype = prevdom->type;
		}
	}
	switch( domainkey )
	{
		case _RS:
			if( prevtype == _LS )
			{
				prevdom->type = _RS;
				if( prevdom->linenum < linenum )
				{
					prevdom->linenum = linenum;
					prevdom->isself = FLAG_ON;
					prevdom->currtabs = prevdom->nexttabs;
				}else
					prevdom->currtabs = prevdom->currtabs;
			}else{ printf("too much _RS,linenum %d\n", linenum);}
			break;
		case _RB:
			if( prevtype == _LB )
			{
				prevdom->type = _RB;
				if( prevdom->linenum < linenum )
				{
					//prevdom->linenum = linenum;
					prevdom->isself = FLAG_ON;
				}
			}else{ printf("too much _RB,linenum %d\n", linenum);}
			break;
		case _SEMICOLON:
			if( prevtype < _SWITCH )
			{
				prevdom->type = _SEMICOLON;
				if( prevdom->linenum < linenum )
				{
					prevdom->linenum = linenum;
					prevdom->isself = FLAG_ON;
					prevdom->currtabs = prevdom->nexttabs;
				}else
					prevdom->currtabs = prevdom->currtabs;
			}
			break;
		default:
			break;
	}
	*domaintopp = domaintop;
	//printf("%d:%s end\n",__LINE__,__FUNCTION__);
}

void pushdomain( mykey_t domainkey, int* domaintopp, domain_t** domainS, int linenum )
{
	//printf("%d:%s start\n",__LINE__,__FUNCTION__);
	int domaintop = 0;
	mykey_t prevtype = KEYWORDCNT;
	domain_t* prevdom = NULL;
	domain_t* currdomain = NULL;
	
	domaintop = *domaintopp;

	if( domaintop == DEPTH )
		perr("domainS full");
	
	if( 0 < domaintop )
	{
		prevdom = domainS[domaintop-1];
		prevtype = prevdom->type;
		if( _CASE == prevtype || _DEFAULT == prevtype 
			|| _RS == prevtype || _RB == prevtype || _SEMICOLON == prevtype)
		{
			free(domainS[--domaintop]);
			frc2++;
			prevtype = KEYWORDCNT;
			prevdom = NULL;
			domainS[domaintop] = 0;
		}
		
		if( prevdom == NULL && 0 < domaintop )
		{
			prevdom = domainS[domaintop-1];
			prevtype = prevdom->type;
		}
	}
	//printf( "prevtype is %d\n", prevtype );
	//domain_t* currdomain = (domain_t *)malloc( sizeof( domain_t ) );
	switch( domainkey )
	{
		case _IF:
			if( prevtype == _ELSE )
			{
				prevdom->type = _IF;
				if( prevdom->linenum < linenum )
				{
					prevdom->isself = FLAG_ON;
					prevdom->linenum = linenum;
				}
			}else if( prevtype < _ELSE )
			{
				prevdom->type = _IF;
				prevdom->nexttabs = prevdom->nexttabs + 1;
				if( prevdom->linenum < linenum )
				{
					prevdom->currtabs = prevdom->currtabs + 1;
					prevdom->isself = FLAG_ON;
					prevdom->linenum = linenum;
				}
			}else{
				currdomain = (domain_t *)malloc( sizeof( domain_t ) );
				mlcc2++;	
				currdomain->type = _IF;
				currdomain->isself = FLAG_ON;
				currdomain->linenum = linenum;
				// lines below
				if( prevdom->linenum < linenum )
					currdomain->currtabs = prevdom->nexttabs;
				else
					currdomain->currtabs = prevdom->currtabs;
				currdomain->nexttabs = currdomain->currtabs + 1;
				domainS[domaintop++] = currdomain;
			}
			break;
		case _WHILE:
			if( prevtype < _ELSE )
			{
				prevdom->type = _WHILE;
				prevdom->nexttabs = prevdom->nexttabs + 1;
				if( prevdom->linenum < linenum )
				{
					prevdom->currtabs = prevdom->currtabs + 1;
					prevdom->isself = FLAG_ON;
					prevdom->linenum = linenum;
				}
			}else{
				currdomain = (domain_t *)malloc( sizeof( domain_t ) );
				mlcc2++;
				currdomain->type = _WHILE;
				currdomain->isself = FLAG_ON;
				currdomain->linenum = linenum;
				if( prevdom->linenum < linenum )
					currdomain->currtabs = prevdom->nexttabs;
				else
					currdomain->currtabs = prevdom->currtabs;
				currdomain->nexttabs = currdomain->currtabs + 1;
				domainS[domaintop++] = currdomain;
			}
			break;
		case _DO:
			if( prevtype < _ELSE )
			{
				prevdom->type = _DO;
				prevdom->nexttabs = prevdom->nexttabs + 1;
				if( prevdom->linenum < linenum )
				{
					prevdom->currtabs = prevdom->currtabs + 1;
					prevdom->isself = FLAG_ON;
					prevdom->linenum = linenum;
				}
			}else{
				currdomain = (domain_t *)malloc( sizeof( domain_t ) );
				mlcc2++;
				currdomain->type = _DO;
				currdomain->isself = FLAG_ON;
				currdomain->linenum = linenum;
				if( prevdom->linenum < linenum )
					currdomain->currtabs = prevdom->nexttabs;
				else
					currdomain->currtabs = prevdom->currtabs;
				currdomain->nexttabs = currdomain->currtabs + 1;
				domainS[domaintop++] = currdomain;
			}
			break;
		case _FOR:
			if( prevtype < _ELSE )
			{
				prevdom->type = _FOR;
				prevdom->nexttabs = prevdom->nexttabs + 1;
				if( prevdom->linenum < linenum )
				{
					prevdom->currtabs = prevdom->currtabs + 1;
					prevdom->isself = FLAG_ON;
					prevdom->linenum = linenum;
				}
			}else{
				currdomain = (domain_t *)malloc( sizeof( domain_t ) );
				mlcc2++;
				currdomain->type = _DO;
				currdomain->isself = FLAG_ON;
				currdomain->linenum = linenum;
				if( prevdom->linenum < linenum )
					currdomain->currtabs = prevdom->nexttabs;
				else
					currdomain->currtabs = prevdom->currtabs;
				currdomain->nexttabs = currdomain->currtabs + 1;
				domainS[domaintop++] = currdomain;
			}
			break;
		case _ELSE:
			currdomain = (domain_t *)malloc( sizeof( domain_t ) );
			mlcc2++;
			currdomain->type = _ELSE;
			currdomain->isself = FLAG_ON;
			currdomain->linenum = linenum;
			if( prevdom != NULL){
				if( prevdom->linenum < linenum )
					currdomain->currtabs = prevdom->nexttabs;
				else
					currdomain->currtabs = prevdom->currtabs;
			}else{ }
			currdomain->nexttabs = currdomain->currtabs + 1;
			domainS[domaintop++] = currdomain;
			break;
		case _SWITCH:
			currdomain = (domain_t *)malloc( sizeof( domain_t ) );
			mlcc2++;
			currdomain->type = _SWITCH;
			currdomain->isself = FLAG_ON;
			currdomain->linenum = linenum;
			if( prevdom != NULL){
				if( prevdom->linenum < linenum )
					currdomain->currtabs = prevdom->nexttabs;
				else
					currdomain->currtabs = prevdom->currtabs;
			}else{ }
			currdomain->nexttabs = currdomain->currtabs + 2;
			domainS[domaintop++] = currdomain;
			break;
		case _CASE:
			currdomain = (domain_t *)malloc( sizeof( domain_t ) );
			mlcc2++;
			currdomain->type = _CASE;
			currdomain->isself = FLAG_ON;
			currdomain->linenum = linenum;
			if( prevdom != NULL){
				if( prevdom->linenum < linenum )
					currdomain->currtabs = prevdom->nexttabs - 1;
				else
					currdomain->currtabs = prevdom->currtabs;
			}else{ }
			domainS[domaintop++] = currdomain;
			break;
		case _DEFAULT:
			currdomain = (domain_t *)malloc( sizeof( domain_t ) );
			mlcc2++;
			currdomain->type = _DEFAULT;
			currdomain->isself = FLAG_ON;
			currdomain->linenum = linenum;
			if( prevdom != NULL){
				if( prevdom->linenum < linenum )
					currdomain->currtabs = prevdom->nexttabs - 1;
				else
					currdomain->currtabs = prevdom->currtabs;
			}else{ }
			domainS[domaintop++] = currdomain;
			break;
		case _LS:
			currdomain = (domain_t *)malloc( sizeof( domain_t ) );
			mlcc2++;
			currdomain->type = _LS;
			currdomain->isself = FLAG_ON;
			currdomain->linenum = linenum;
			if(prevdom != NULL){
				if( prevdom->linenum < linenum ){
					currdomain->currtabs = prevdom->nexttabs;
				}else
					currdomain->currtabs = prevdom->currtabs;
			}else{
				currdomain->currtabs = 0;	
			}
			currdomain->nexttabs = currdomain->currtabs + 1;
			domainS[domaintop++] = currdomain;
			break;
		case _LB:
			if( prevtype < _CASE )// while do if for else swith
			{
				prevdom->type = _LB;
				prevdom->issub = FLAG_ON;
				if( prevdom->linenum < linenum )
				{
					prevdom->isself = FLAG_ON;
					prevdom->linenum = linenum;
				}
			}else{
				currdomain = (domain_t *)malloc( sizeof( domain_t ) );
				mlcc2++;
				currdomain->type = _LB;
				currdomain->isself = FLAG_ON;
				currdomain->issub = FLAG_ON;
				currdomain->linenum = linenum;
				if(prevdom != NULL){
					if( prevdom->linenum < linenum )
						currdomain->currtabs = prevdom->nexttabs;
					else
						currdomain->currtabs = prevdom->currtabs;
				}else
					currdomain->currtabs = 0;
				currdomain->nexttabs = currdomain->currtabs + 1;
				domainS[domaintop++] = currdomain;
			}
			break;
		default:
			perr("domain");
			break;
	}
	*domaintopp = domaintop;
	//printf("%d:%s end\n",__LINE__,__FUNCTION__);
}


mykey_t ruleoutkeywords(int offset, int* origtopp, keyword_t** origkeywordS )
{
	//printf("%d:%s start\n",__LINE__,__FUNCTION__);
	int origtop = *origtopp;
	mykey_t domainkey = KEYWORDCNT;
	while( origtop > 0 )
	{
		if( origkeywordS[origtop-1]->offset < offset )
		{
			free(origkeywordS[--origtop]);
			frc1++;
			origkeywordS[origtop] = 0;
		}else if( origkeywordS[origtop-1]->offset == offset )
		{
			domainkey = origkeywordS[--origtop]->type;
			free(origkeywordS[origtop]);
			frc1++;
			origkeywordS[origtop] = 0;
		}else break;
	}
	*origtopp = origtop;
	//printf("%d:%s end\n",__LINE__,__FUNCTION__);
	return domainkey;
}

int getmid( keyword_t** tosort, int start, int end )
{
	//printf("%d:%s start\n",__LINE__,__FUNCTION__);
	int mid = ( start + end ) / 2;
	
	tosort[DEPTH] = tosort[start];
	if( tosort[end]->offset > tosort[start]->offset )
	{
		tosort[start] = tosort[end];
		tosort[end] = tosort[DEPTH];
	}
	
	tosort[DEPTH] = tosort[start];
	if( tosort[mid]->offset > tosort[start]->offset )
	{
		tosort[start] = tosort[mid];
		tosort[mid] = tosort[DEPTH];
	}
	
	tosort[DEPTH] = tosort[mid];
	if( tosort[end]->offset < tosort[mid]->offset )
	{
		tosort[mid] = tosort[end];
		tosort[end] = tosort[DEPTH];
	}
	
	tosort[DEPTH] = tosort[end];
	//printf("%d:%s end\n",__LINE__,__FUNCTION__);
	return tosort[end]->offset;
}

int mypartion( keyword_t** tosort, int start, int end )
{
	//printf("%d:%s start\n",__LINE__,__FUNCTION__);
	int pivot = getmid( tosort, start, end );
	while( start < end )
	{
		while( start < end && pivot <= tosort[start]->offset )
			++start;
		tosort[end] = tosort[start];
		while(start < end && pivot >= tosort[end]->offset )
			--end;
		tosort[start] = tosort[end];
	}
	tosort[start] = tosort[DEPTH];
	//printf("%d:%s end\n",__LINE__,__FUNCTION__);
	return start;
}

void myinsertSort( keyword_t** tosort, int start, int end )
{
	//printf("%d:%s start\n",__LINE__,__FUNCTION__);
	int i, j;
	keyword_t* temp = NULL;
	for( i = start + 1; i <= end; i++ )
	{
		temp = tosort[i];
		for( j = i; j > start && temp->offset > tosort[j-1]->offset; j-- )
		{
			tosort[j] = tosort[j-1];
		}
		tosort[j] = temp;
	}
	//printf("%d:%s end\n",__LINE__,__FUNCTION__);
}

void myquickSort( keyword_t** tosort, int start, int end )
{	
	//printf("%d:%s start\n",__LINE__,__FUNCTION__);
	int pivot = 0;
	if( end - start >= 7 )
	{
		while( start < end ){
			pivot = mypartion( tosort, start, end );
			myquickSort( tosort, start, pivot - 1 );
			start = pivot + 1;
		}
	}else
		myinsertSort( tosort, start, end );
	//printf("%d:%s end\n",__LINE__,__FUNCTION__);
}

void sortorigbyoffset( keyword_t** origkeywordS, int origtop )
{
	//printf("%d:%s start\n",__LINE__,__FUNCTION__);
	if( 1 < origtop && origtop <= 8 )
	{
		myinsertSort( origkeywordS, 0, origtop - 1 );
	}else if( origtop > 8 && origtop < DEPTH)
	{
		myquickSort( origkeywordS, 0, origtop - 1 );
	}
	//printf("%d:%s end\n",__LINE__,__FUNCTION__);
}

int checkright(char r, mykey_t type)
{
	//printf("%d:%s start\n",__LINE__,__FUNCTION__);
	int ret = 0;
	if( ' ' == r || '\n' == r || '\t' == r )
		return 1;
	switch(type)
	{
		case _DO://do
		case _ELSE://else
			break;
		case _WHILE://while
		case _IF://if
		case _FOR://for
		case _SWITCH://switch
			if( '(' == r )
				ret = 1;
			break;
		case _DEFAULT:
			if( ':' == r )
				ret = 1;
			break;
		case _CASE://case
			if( '\'' == r )
				ret = 1;
			break;
		default:
			perr("unknow keyword type");
			break;
	} 
	//printf("%d:%s end\n",__LINE__,__FUNCTION__);
	return ret;
}

int checkleft(char l, mykey_t type)
{
	//printf("%d:%s start\n",__LINE__,__FUNCTION__);
	int ret = 0;
	if( '\t' == l || ' ' == l || '}' == l )
		ret = 1;
	if( '#' == l && ( _IF == type || _ELSE == type ) )
		ret = 0;
	//printf("%d:%s end\n",__LINE__,__FUNCTION__);
	return ret;
}

void getorigkeywords(char* line, int* origtop, keyword_t** origkeywordS )
{
	//printf("%d:%s start\n",__LINE__,__FUNCTION__);
	int i = 0;
	int linelen = strlen(line);
	while( KEYWORDCNT > i )
	{
		char* word = keywords[i];
		int wordlen = strlen(word);
		char* temp = line;
		while(1)
		{
			temp = strstr( temp, word );			
			if( temp != NULL )
			{
				int offset = temp - line;
				if( temp == line && linelen > 1 )
				{
					char r = *( temp + wordlen );
					if( checkright( r, i ) )
						pushorig( offset, i, origtop, origkeywordS );
				}else if( temp == line + linelen - wordlen && linelen > wordlen )
				{
					char l = *( temp - 1 );
					if( checkleft( l, i ) )
						pushorig( offset, i, origtop, origkeywordS );
				}else{
					char r = *( temp + wordlen );
					char l = *( temp - 1 );
					//printf("outer....key word is %s offset is %d, type is %s, r is %c,l is %c\n\n", temp, offset, word, r ,l);
					if( checkright( r, i ) && checkleft( l, i ) )
					{
						//printf("key word is %s offset is %d, type is %s, in line %d\n\n", temp, offset, word, linecounter);
						pushorig( offset, i, origtop, origkeywordS );
					}
				}
				temp = temp + wordlen;
			}else break;
		}
		++i;
	}
	//printf("%d:%s end\n",__LINE__,__FUNCTION__);
}

void pushorig(int offset, mykey_t type, int* origtopp, keyword_t** origkeywordS)
{
	//printf("%d:%s start\n",__LINE__,__FUNCTION__);
	int origtop = *origtopp;
	if( origtop < DEPTH )
	{
		keyword_t *elemt = ( keyword_t * )malloc( sizeof( keyword_t ) );
		mlcc1++;
		if( elemt == NULL ) 
		{
			perr("malloc");
		}
		elemt->offset = offset;
		elemt->type = type;
		//printf("in pushorig, origtop is %d\n", origtop);
		origkeywordS[origtop++] = elemt;
	}else perr("too much origkeywords");
	*origtopp = origtop;
	//printf("%d:%s end\n",__LINE__,__FUNCTION__);
}

keyword_t* poporig(int* origtopp, keyword_t** origkeywordS)
{
	//printf("%d:%s start\n",__LINE__,__FUNCTION__);
	int origtop = *origtopp;
	if( origtop > 0)
	{	
		printf("in poporig, origtop is %d\n", origtop);
		return	origkeywordS[--origtop];
	}else perr("no elem in origkeywordS");
	*origtopp = origtop;
	//printf("%d:%s end\n",__LINE__,__FUNCTION__);
	return NULL;
}

int checkcomment( char* line, int index, int* flag)
{
	//printf("%d:%s start\n",__LINE__,__FUNCTION__);
	if( strlen(line) > index + 1 ){
		if( '/' == line[index] )
		{
			if( '/' == line[index+1] ) return FLAG_ON;
			else if( '*' == line[index+1] )
				*flag = FLAG_ON;
		}
		if( FLAG_ON == *flag && '*' == line[index] && '/' == line[index+1] )
			*flag = FLAG_OFF;
	}
	//printf("%d:%s end\n",__LINE__,__FUNCTION__);
	return 0;
}

void checkstr( char* line, int index ,int *flag)
{
	//printf("%d:%s start\n",__LINE__,__FUNCTION__);

	if( '\"' == line[index] && ( 0 == index || '\\' != line[index-1] ) )
	{
		*flag = *flag == FLAG_OFF ? FLAG_ON : FLAG_OFF;
	}
	//printf("%d:%s end\n",__LINE__,__FUNCTION__);
}

你可能感兴趣的:(c,算法)