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