SECTION IV - Source Code #include "k:\develop\admp\admp.h" /***************************************************** ******************** admp PROGRAM: * PURPOSE: the purpose of this program is to generate documentation * for a given project. * ARGS: the following command line args can be used * admp [-rAI-rf filenamel-rF] [-g phrase] [-p pid] * * -rA refresh -* -- everything for a project if a pid is specified * -- everything for all projects if no pid is specified * -rf filename -- full path of file to refresh for this pid * -RF FILELIST -- refresh file list only for this pid * -g search all files in the project for a phrase if a pid is given * search all files if no pid is given * -p pid -- project identifier * *************************************************************************/ void main(int argc, char *argv[]) char *phrase=NULLi char *RefreshOption=NULLi int pid=O; int fid=Oi int rf=Oi int rA=Oi int rF=Oi int g=Oi int P=Oi int error=Oi int i = 1i int ReturnCode=SUCCESS_CODEi char server[20] = "server"i char database[20] = "admp"i char user[ll] = "sa"i char password[ll] = ""i if(! (argc>2)) //got some args { error++i else { while (i<argc) { i f (argv [i] [0] ==' -' ) { i f (argv[i] [l]=='r') { i f (argv [i] [2] ==' A' ) { rA++i } else i f (argv[i] [2]=='F') { rF++i } 1 else i f (argv [i) [2] ==' f') { rf++i i f ({i+l) <argc) { i f (argv [i+l] [0] ! =' - , ) { fid = atoi(argv[i+l])i i++i else error++j } else { error++i } else i f (argv[i] [1] =='g') { g++j i f ({i+l) <argc) { i f (argv [i+l] [0] ==' -' ) { error++j else phrase argv[i+l] j else error++j } } else i f {argv[i] [l]=='p') { P++i i f ((i+l) <argc) { i f (argv [i+l] [0] ! =' -') { pid = atoi{argv[i+l])i else { error++j } else error++j 2 else { Ilerror error++; } Ilif i++; Ilwhile if (error) { fprintf(stderr, "Error: invalid command line args.II); else { Ilgotta connect to the database DB_Connect (server, database, user,password); if (rA) Ilrefresh { i f (p) { RefreshProjectFileList(pid); RefreshAllFunctions(pid); } else { fprintf{stderr,"Not done yet. II ); else i f (rf) { i f (p) ReturnCode = RefreshProjectFile(pid, fid); if (ReturnCode != SUCCESS_CODE) { fprintf(stderr,"ERROR: II); else { fprintf(stderr,"ERROR: option with -r not valid."); else fprintf{stderr,"ERROR: option with -r not valid."); DB_Disconnect(); 3 4 #include "k:\develop\admp\admp.h" 1***************************************************** ************** All these will be elsewhere later ****************************************************** *************1 1* #define SUCCESS CODE 1 #define FAILURE CODE 2 #define NOTFOUND CODE 3 #define FALSE 0 #define TRUE 1 *1 1***************************************************** ********************** FUNCTION: * Connect PURPOSE: * connect to the database RETURNS: * none PARAMTERS: none * AUTHOR: * DWM ***************************************************************************/ /*void Connect() { EXEC SQL begin declare section; char database [40] ="danieljr.admp"; EXEC SQL end declare section; EXEC SQL CONNECT TO :database USER sa; /*************************************************************************** FUNCTION: * Disconnect PURPOSE: * disconnect from the database RETURNS: * none PARAMTERS: none * AUTHOR: * DWM ***************************************************************************/ I*void Disconnect() { EXEC SQL disconnect all; /*************************************************************************** FUNCTION: * BeginTransaction PURPOSE: * begin a transaction RETURNS: * none PARAMTERS: none * AUTHOR: * DWM ***************************************************************************/ /*void BeginTransaction() 1 { EXEC SQL begin transaction(); /*************************************************************************** * FUNCTION: CommitTransaction * PURPOSE: commit a transaction * RETURNS: none * PARAMTERS: none * AUTHOR: DWM ***************************************************************************/ /*void CommitTransaction() { EXEC SQL commit transaction(); /*************************************************************************** Rol IbackTransact ion FUNCTION: * rollback a transaction PURPOSE: * RETURNS: none * PARAMTERS: none * AUTHOR: DWM * ***************************************************************************/ /*void RollbackTransaction() { EXEC SQL rollback transaction(); } /*************************************************************** * FUNCTION: RTrim * PURPOSE: * * PARAMETERS: This function is passed a char * and removes all trailing spaces and \n's from the string. char *stringl * RETURN: pointer to the string * AUTHOR: DWM * NOTE: ****************************************************************/ /*char * RTrim (char *stringl) { int counter; //MOD DWM to trim '\n's too!!! counter = strlen(stringl); if (counter-- > 0) for ( ; (counter >= 0) && ((stringl[counter]==' ,) I I (stringl[counter]=='\n'» nter- -) stringl[counter] '\0' ; //MOD DWM return the string return stringl; /*************************************************************** * FUNCTION: LTrim 2 cou * PURPOSE: * * PARAMETERS: This function is passed a char * and removes all leading spaces and \t's from the string. char *stringl * RETURN: pointer to the string * AUTHOR: DWM * NOTE: ****************************************************************/ /*char * LTrim (char *stringl) { unsigned int counter= 0; if (counter < strlen(stringl» { for ( ; (counter <= strlen(stringl» ==' \t'» counter++) { //just run up the counter && ((stringl[counter]==' ') I I (stringl[counter] strncpy(stringl, stringl+counter, strlen(stringl)-counter+l); return stringl; /*************************************************************** * FUNCTION: StringToUpper * PURPOSE: * PARAMETERS: this function converts a string to upper case char *stringl * RETURN: pointer to the string * AUTHOR: DWM * NOTE: ****************************************************************/ /* char * StringToUpper(char *buffer) { char *ptr = NULL; ptr = buffer; while ( *ptr != '\0' { *ptr++ = toupper( *ptr ); return buffer; /*************************************************************************** FUNCTION: replaceCharOneWithCharTwo PURPOSE: replace all occurences of char one in string with char two RETURNS: the number of chars replaced PARAMTERS: string -- this is what we replace the chars in AUTHOR: DWM NOTE: * ***************************************************************************/ /*int replaceCharOneWithCharTwo(char *string, char one, char two) * * * * * 3 char *theQuote; int return code 0; while (1) { theQuote = strchr{string, one); if (theQuote != NULL) { //we found a quote ... make it a space *theQuote = two; return_code++; else { break; } / /while return return_code; /******************************************************************** *********************************************************************/ /*************************************************************** * FUNCTION: GetNextFileId * PURPOSE: This function get the next unique file identifier available for the given project. project_id -- the project for which we need a new file id file id -- the file id we find and pass back * * PARAMETERS: * * * RETURN: * SUCCESS CODE FAILURE CODE we got a new file id an error occured * AUTHOR: DWM * NOTE: ****************************************************** **********/ int GetNextFileId(int project_id, int *file_id) EXEC SQL begin declare section; int DBfile_id=O; int DBproject_id=O; EXEC SQL end declare section; //assume only one copy of this program running at once EXEC SQL select ISNULL(MAX(file_id),O)+l into :DBfile_id from cfg-project_files where project_id = : DBproject_id; if (SqlCode != SqlSuccessCode) return FAILURE_CODE; else { 4 *file_id = DBfile_id; return SUCCESS_CODE; 1***************************************************** ********** * FUNCTION: AddFileToProject * PURPOSE: * * * * PARAMETERS: * This function adds a file with pat~ file-path to the project identified by project_id. It does this by inserting into the cfg-project_files table. project_id -- the project we are adding a file to file-path -- the full path of the file * RETURN: SUCCESS CODE we got a new file id FAILURE CODE an error occured * * AUTHOR: DWM * NOTE: ****************************************************************/ int AddFileToProject(int project_id, char *file-path) EXEC SQL begin declare section; int DBproject_id=O; int DBfile_id=O; char DBfile-path[FILE_PATH_SIZE] ; char DBfile_type[FILE_TYPE_SIZE]; EXEC SQL end declare section; char drive [FILE_PATH_SIZE]=""; char dir[FILE_PATH_SIZE] =""; char fname[FILE_PATH_SIZE]="I; char ext [FILE_PATH_SIZE]=""; int ReturnCode = SUCCESS_CODE; DBproject_id = project_id; strcpy(DBfile-path, file-p ath ); //WARNING NT-specific function _splitpath(DBfile-path, drive, dir, fname, ext); if (strcmp(RTrim(StringToUpper(ext)), ".C")==O) { //straight C strcpy (DBfile_type, "C"); else if (strcmp(RTrim(StringToUpper(ext)),I.SQC")==O) { //C with embedded SQL strcpy(DBfile_type, "S"); else if (strcmp(RTrim(StringToUpper(ext)) ,".LIB")==O) { //include lib files, I won't ever do anything with them //but at least I can print out the fact that they are in the project strcpy (DBfile_type, ilL"); else ReturnCode NOTFOUND_CODE; 5 if (ReturnCode SUCCESS_CODE) { if (GetNextFileId {proj ect_id, &DBfile_id)==SUCCESS_CODE) { EXEC SQL insert into cfg-project_files{project_id, file_id, file-p ath , file_type, last_refresh_date) valu~s{:DBproject_id, :DBfile_id, :DBfile-path, :DBfile_type, getdate()); if (SqlCode != SqlSuccessCode) { ReturnCode FAILURE_CODE; } else { ReturnCode FAILURE_CODE; return ReturnCode; /***************************************************** ******* * FUNCTION: RefreshProjectFileList * PURPOSE: Given a particular project, refresh the file list * found in the cfg-project_files list. As we refresh, we delete files from our list that are no longer there, add * * files that are new, and update the last refresh time on * files we already new about. * PARAMETERS: project_id -- the project whose file list we should ~ refresh * RETURN: SUCCESS CODE it worked FAILURE CODE there was an error * * NOTES: * AUTHOR: DWM ****************************************************************/ int RefreshProjectFileList(int project_id) EXEC SQL begin declare section; int DBproject_id = 0; int DBfile_id =0; char DBstartDate [DATE_SIZE] =""; char DBmake_file [MAKE_FILE_SIZE] =""; char DBfile-path[FILE_PATH_SIZE]=""; EXEC SQL end declare section; FILE *MakeFilePtr = NULL; char buffer[BUFFER_SIZE] = "" ,. //a line of input from the .mak file char *TokenPosition = NULL; char SourceToken[lO]="SOURCE="; int NewSourceFileCount = 0; int TotalSourceFileCount = 0; int DeletedSourceFileCount = 0; int UnchangedSourceFileCount = 0; int ReturnCode = SUCCESS_CODE; 6 int CodeReturned = SUCCESS_CODEi char char char char char char char char drive [FILE_PATH_SIZE] =""i dir[FILE_PATH_SIZE]=""i fname [FILE_PATH_SIZE] =""i ext [FILE_PATH_SIZE]=""i project_drive [FILE_PATH_SIZE] =""i project_dir[FILE_PATH_SIZE]=""i project_fname[FILE_PATH_SIZE]=""i project_ext [FILE_PATH_SIZE]=""i Ilgrab the path of the .mak file EXEC SQL select make_file into :DBmake_file from cfg-project where project_id = :DBproject_idi //TODO: check sqlcode Ilopen the file i f ((MakeFilePtr = fopen (DBmake_file, "r")) == NULL) { fprintf(stderr, "ERROR: unable to open file: %s.\n",DBmake_file)i ReturnCode FAILURE_CODEi else /IWARNING: getdate is SQL-server specific Ilgrab the date for later use EXEC SQL select getdate() into :DBstartDatei II from cfg-project where project_id = :DBproject_idi Iistart a transaction ..... I wanna refresh everthing or nothing ... BeginTransaction()i Iithis loop will add files if needed and mark each one as I read it while (1) { Ilgrab line a line if (fgets(buffer,BUFFER_SIZE,MakeFilePtr) NULL) { breaki } else { Iisee if there is a source file on this line TokenPosition = strstr(buffer, SourceToken)i if (TokenPosition == NULL) { continuei TotalSourceFileCount++i Ilassume the file name with full path is less than FILE_PATH_SIZE-1 cha rs strncpy(DBfile-path,TokenPosition+strlen(SourceToken),FILE_PATH_SIZE-1) DBfile-path [FILE_PATH_SIZE-1]='\O'i RTrim(DBfile-path ) i 7 Iisometimes the makefile will contain relative paths .... II so if the directory is ".1" or ".\" then I should fill in II the full path for use later if (DBfile-path[O]=='. ') { EXEC SQL select make_file into :DBmake_file from cfg-project where project_id = :DBproject_id; IIWARNING NT-specific function _splitpath(DBfile-path, drive, dir, fname, ext); IIWARNING NT-specific function _splitpath(DBmake_file, project_drive, project_dir, project_fname, project_ext); sprintf(DBfile-path,"%s%s%s%s",project_dir,dir+2,fname,ext); replaceCharOneWithCharTwo(DBfile-path , '\\', 'I'); Ilcheck the database ... do we already know this file? IIWARNING getdate() is SQL-server specific EXEC SQL update cfg-project_files set last_refresh_date = getdate() where project_id = :DBproject_id and file-path = :DBfile-path ; if (SqlCode == SqlNotFoundCode) { Ilwe don't know this file ... lets add it CodeReturned = AddFileToProject(DBproject_id, DBfile-path); if (CodeReturned == NOTFOUND_CODE) { Iithis means that I didn't add the file because it II was a type of file I don't understand (e.g. a .lib file) else if (CodeReturned != SUCCESS_CODE) ReturnCode break; else { NewSourceFileCount++; else if (SqlCode != SqlSuccessCode) { Iisome sort of error fprintf(stderr, "ERROR: refreshing file %s.\n\tError Code , DBfile-path, SqICode); ReturnCode=FAILURE_CODE; break; } else { UnchangedSourceFileCount++; }llelse 8 %d. \n" }llwhile(l) Ilclose the file fclose(MakeFilePtr); if (ReturnCode==SUCCESS_CODE) { III have to commit here or I will walk on myself CommitTransaction(); Iinow delete all the files we had in the project before that we didn't just II find in the .mak file EXEC SQL declare DeleteProjectFileCurs cursor for select file id from cfg-project_files where project_id = :DBproject_id and last_refresh_date < :DBstartDate; EXEC SQL open DeleteprojectFileCurs; if (SqlCode == SqlSuccessCode) BeginTransaction(); while(l) { EXEC SQL fetch DeleteprojectFileCurs into :DBfile_id; if (SqlCode SqlNotFoundCode) { break; else if (SqlCode != SqlSuccessCode) { ReturnCode break; else { DeletedSourceFileCount++; III have to II before I IITODO: delete all of the records from the child tables can delete from the parent EXEC SQL delete from where project_id EXEC SQL delete from where project_id EXEC SQL delete from where project_id EXEC SQL delete from where project_id EXEC SQL delete from where project_id check slqcode after each of these cfg_function_refs = :DBproject_id and cfg_function_header = :DBproject_id and cfg_function_mods = :DBproject_id and cfg_table_refs = :DBproject_id and cfg_function_defs = :DBproject_id and file id file id file id file id file id } }I/while EXEC SQL close DeleteProjectFileCurs; EXEC SQL delete from cfg-project_files where project_id = :DBproject_id and last_refresh_date te; 9 < :DBstartDa if (SglCode != SqlSuccessCode) { ReturnCode=FAILURE_CODE; } else if (SqlCode != SqlNotFoundCode) { ReturnCode=FAILURE_CODE; if (ReturnCode == SUCCESS_CODE) { CommitTransaction(); printf("SUCCESS: %d files examined.\n",TotalSourceFileCount); printf (" %d files unchanged. \n", UnchangedSourceFileCount); printf(" %d files added to project.\n", NewSourceFileCount); printf(" %d files removed from project.\n", DeletedSourceFileCount ) ; else RollbackTransaction(); printf("FAILURE: project files not refreshed."); return ReturnCode; of function }llend 1***************************************************** ******************** * FUNCTION: GetNCNBlineCount * PURPOSE: Get the number of non-comment, non-blank lines in the function * which starts on the line before current position * in the open file refered to by fp * PARAMETERS: fp -- pointer to open file where function is * FirstLine -- the line of text above the current position in the * file * NCNBlineCount -- the count of NCNB lines that is returned * CommentLineCount -- the count of comment lines in the function that * is returned to the calling function * FunLen -- the total number of lines in the function that is returned * RETURN: SUCCESS CODE it worked * FAILURE CODE -- there was an error * NOTES: * AUTHOR: DWM ****************************************************** **********1 int GetNCNBlineCount(FILE *fp, int project_id, int file_id, int function_id, char *FirstLine, int *NCNBlineCount,int *CommentLineCount, long * FunLen) int ReturnCode = SUCCESS_CODE; int'InComments = FALSE; char *EndOfCommentsPtr = NULL; char *TokenPtr = NULL; char buffer[BUFFER_SIZE]=""; char buffer_temp [BUFFER_SIZE] =""; int testval=O; 10 int FoundCurly=O; //when I find my first curly brace, set this to true enum Tokens {BottomOfStack, LeftBrace}; int done = FALSE; unsigned int i = 0; int Linel=TRUE; /Ithis stack I will use for parsing PromptStack *TokenStack NULL; (*NCNBlineCount) = 0; (*FunLen) = 0; (*CommentLineCount) = 0; TokenStack = Base_PushPromptStack(TokenStack,BottomOfStack); while (! done) { //grab a line from the file i f (Linel) { strcpy(buffer, FirstLine); Linel=FALSE; } else { if (fgets (buffer,BUFFER_SIZE,fp) { break; } (*FunLen)++; NULL) strcpy(buffer_temp, buffer); if (InComments) { EndOfCommentsPtr = strstr(buffer, n*/n); (*CommentLineCount)++; if (EndOfCommentsPtr != NULL) //found the end { InComments = FALSE; } } else { LTrim (buffer) ; if (buffer[O]=='I') { if (buffer[l]=='/') { //whole line is comments (*CommentLineCount)++; continue; } else if (buffer[l]=='*') { InComments = TRUE; EndOfCommentsPtr = strstr(buffer, n*/n); (*CommentLineCount)++; if (EndOfCommentsPtr != NULL) { /Istarting comments InComments = TRUE; 11 else if (buffer[OJ=='\n') { continue; } else { //found an NCNB line (*NCNBlineCount)++; //look for braces for(i=O; ((i< (strlen(buffer))} && (!done}); i++) { if (buffer[i)==LEFT_BRACE) { TokenStack = Base_PushPromptStack(TokenStack,LeftBrace)i FoundCurlY++i else if (buffer[i)==RIGHT_BRACE) { if (TokenStack->state == LeftBrace) { TokenStack = Base_PopPromptStack(TokenStack)i else fprintf(stderr, "ERROR: invalid syntax in file.")i } if ((TokenStack->state == BottomOfStack}&&(FoundCurly» { done = TRUEi } }//for loop //look for sql statements FindTableRefs(fp, project_id, file_id, function_id,buffer); } //else //else //while TokenStack=Base_KillPromptStack(TokenStack) ; return ReturnCodei /************************************************************ * * * * * * * FuNcTION: SkipFunctionBody PURPOSE: Given a file pointer to an open file at the second line of a fuction definition fill in the non-comment, non-blank line counts for the function and advance the file pointer past the function PARAMETERS: fp -- the file pointer FirstLine -- the first of the function definition 12 project_id -- the project this file belongs to file id -- the identifier of the file function id -- the ID of this function which is unique within * * this project * FunctionLen -- the length of the function -1 in lines * RETURN: SUCCESS_CODE it worked FAILURE CODE there was an error * * NOTES: * AUTHOR: DWM ***************************************************!** **********1 int SkipFunctionBody(FILE *fp, char *FirstLine,int project_id, int file_id, int function id * * long *FunctionLen) EXEC SQL begin declare sectioni int DBncnb_line_count=Oi int DBcomment_line_count=Oi int DBproject_id = 0; int DBfile_id = 0; int DBfunction_id = 0; EXEC SQL end declare section; enum Tokens {LeftParen, RightParen, LeftBrace, RightBrace, LeftBracket, RightBracket}; Iithis stack I will use for parsing PromptStack *sPromptStack = NULL; int CodeReturned = SUCCESS_CODE; int ReturnCode DBproject_id = project_id; DBfile_id = file_id; DBfunction_id Ilget the LOC for the function and the total length in bytes for the II function (FunctionLen) CodeReturned = GetNCNBlineCount(fp,project_id, file_id, function id, FirstLine, &DBncnb_line_count,&DBcomment_line_count,FunctionLen) ; Ilupdate the function to show these line counts EXEC SQL update cfg_function_defs set ncnb_line_count = :DBncnb_line_count, comment_line_count = :DBcomment_line_count where project_id = :DBproject_id and file id :DBfile id and function id :DBfunction_id; IITODO check sqlcode Ilif this is a sql II tables between file -- file_type == 'S' -- then parse all the references to StartPos and StartPos + FunctionLen IIFind all function calls between StartPos and StartPos Ilfind all modification comments denoted by MODtoken return ReturnCode; 13 + FunctionLen 1***************************************************** ******* FUNCTION: FindTableRefs * PURPOSE: Check to see if the line we are on has an sql statement on it * if it does, fill in the cfg_table_refs table with the * project, file, function, table_name and whether it is * a select, an update, an insert or a delete * PARAMETERS: fp -the file pointer * buffer -the line of text we are looking at in the file * project_id -- the project this file belongs to file id -- the identifier of the file function id -- the ID of this function which is unique within this project * RETURN: SUCCESS_CODE -- it worked * FAILURE CODE -- there was an error * NOTFOUND CODE -- this is not a sql statement * NOTES: * AUTHOR: DWM * ****************************************************** **********1 int FindTableRefs(FILE *fp, int project_id,int file_id,int function_id,char *buffer} * * * char buffer_temp[BUFFER_SIZE]=""j long OrigFilePos=Oj char *SQLPtr=NULLi char *Tokenptr=NULL; int Line1=TRUEj int ReturnCode = NOTFOUND_CODEi char SQLstatement[BUFFER_SIZE*3]=""i char *SemiPtr=NULL; fgetpos(fp, &OrigFilePos)i strcpy(buffer_temp, buffer)i SQLPtr = strstr (StringToUpper (buffer_temp) ,"EXEC SQL"); if (SQLPtr != NULL) { //we have found an sql statement ... put it into a string while (1) { strcat(SQLstatement, buffer_temp); SemiPtr = strstr(buffer_temp, ,,;,,); if (SemiPtr == NULL) { //grab line a line if (fgets(buffer_temp,BUFFER_SIZE,fp) { break; else { break; } '} Ilwhile Iiset the file pointer back to where it was fsetpos(fp, &OrigFilePos); Ilmake sure its all upper case StringToUpper(SQLstatement); 14 NULL) if (InsertNewSelectStatement{project_id, file_id, function_id, SQLstatement)==SUCCE SS_CODE) { ReturnCode = SUCCESS_CODE; else if (InsertNewInsertStatement(project_id, file_id, function_id, SQLstatement)== SUCCESS_CODE) { ReturnCode = SUCCESS_CODE; else if (InsertNewUpdateStatement{project_id, file_id, function_id, SQLstatement)== SUCCESS_CODE) { ReturnCode = SUCCESS_CODE; else if (InsertNewDeleteStatement(project_id, file_id, function_id, SQLstatement)== SUCCESS_CODE) { ReturnCode SUCCESS_CODE; } else { ReturnCode }llif else { ReturnCode NOTFOUND_CODE; return ReturnCode; 1***************************************************** ******* FUNCTION: InsertNewSelectStatement * PURPOSE: Check to see if the SQLstatement is a select statement * if it iss, fill in the cfg_table_refs table with the * project, file, function, table_name and 'SELECT' * PARAMETERS: project_id -- the project this file belongs to * file_id -- the identifier of the file * function id -- the ID of this function which is unique within * this project * SQLstatement -- the sql statement we are dealing with * RETURN: SUCCESS CODE it worked * FAILURE CODE there was an error * * NOTES: * AUTHOR: DWM ****************************************************** **********1 int InsertNewSelectStatement(int project id,int file_id,int function_id,char *statement) EXEC SQL begin declare section; int DBproject_id = 0; int DBfile_id = 0; int DBfunction_id = 0; char DBtable_name[TABLE_NAME SIZE]=""; 15 char DBaction_id[ACTION_ID_SIZE)=""; EXEC SQL end declare section; char SQLstatement[BUFFER_SIZE*3)=""; char *TokenPtr=NULL; int state = 0; //state 0 --> looking for select //state 1 --> looking for from //state 2 --> grabbing table names int done=O; int ReturnCode SUCCESS_CODE; int FirstTime = TRUE; DBproject_id = project_id; DBfunction_id = function_id; DBfile_id = file_id; strcpy(SQLstatement, statement); StringToUpper(SQLstatement); Tokenptr = strtok (SQLstatement , II ,\n\t"); while (! done) { i f (! FirstTime) { Tokenptr = strtok(NULL, II ,\n\t"); FirstTime = FALSE; if (TokenPtr != NULL) { switch (state) { case 0: if (strcmp(TokenPtr, "SELECT") ==0) { state++; } break; case 1: if (strcmp(TokenPtr, "FROM") ==0) { state++; } break; case 2: if (strcrnp(TokenPtr, "WHERE") ==0) { done++; } else { strcpy(DBtable_name, TokenPtr); EXEC SQL insert into cfg_table_refs(project_id, file_id, function i d, table_name,action_id) values (:DBproject_id, :DBfile_id, :DBfunction_id, :DBtable_name, 'SELECT'); //TODO check sqlcode break; default: 16 ReturnCode break; FAILURE_CODE; else { ReturnCode break; return ReturnCode; /************************************************************ FUNCTION: InsertNewDeleteStatement * PURPOSE: Check to see if the SQLstatement is a delete statement * if it iss, fill in the cfg_table_refs table with the * project, file, function, table_name and 'DELETE' * PARAMETERS: project_id -- the project this file belongs to * file id -- the identifier of the file * function id -- the ID of this function which is unique within * this project * SQLstatement -- the sql statement we are dealing with * RETURN: SUCCESS CODE it worked FAILURE CODE there was an error * NOTES: * AUTHOR: DWM ****************************************************************/ int InsertNewDeleteStatement(int project_id,int file_id,int function_id,char *statement) * * EXEC SQL begin declare section; int DBproject_id = 0; int DBfile_id = 0; int DBfunction_id = 0; char DBtable_name[TABLE_NAME SIZE]=""; char DBaction_id[ACTION_ID_SIZE]=""; EXEC SQL end declare section; char SQLstatement[BUFFER_SIZE*3]=""; char *TokenPtr=NULL; //state 0 --> looking for select int state = 0; //state 1 --> looking for from //state 2 --> grabbing table names int done=O; int ReturnCode SUCCESS_CODE; int FirstTime = TRUE; DBproject_id = project_id; DBfuriction_id = function_id; DBfile_id = file_id; strcpy(SQLstatement, statement); StringToupper(SQLstatement); TokenPtr = strtok(SQLstatement," ,\n\t"); 17 ------------------------------............ 'r while ( ! done) { i f (! FirstTime) { TokenPtr = strtok(NULL, II ,\n\t"); FirstTime = FALSE; if (TokenPtr != NULL) { switch (state) { case 0: if (strcmp(TokenPtr, "DELETE") ==0) { state++; break; case 1: if (strcmp (TokenPtr, { state++; II FROM II ) ==0) break; case 2: if (strcmp(TokenPtr, "WHERE") ==0) { done++; ~ I else strcpy(DBtable_name, TokenPtr); EXEC SQL insert into cfg_table_refs(project_id, file_id, function i d, table_name,action_id) values (:DBproject_id, :DBfile_id, :DBfunction_id, :DBtable_name, 'DELETE'); //TODO check sqlcode 1 I break; default: ReturnCode break; J I I I FAILURE_CODE; } else { ReturnCode break; return ReturnCode; I /************************************************************ FUNCTION: InsertNewUpdateStatement * PURPOSE: Check to see if the SQLstatement is a update statement * if it iss, fill in the cfg_table_refs table with the * project, file, function, table_name and 'UPDATE' * 18 * * * * * * * * * PARAMETERS: project_id -- the project this file belongs to file id -- the identifier of the file function id -- the ID of this function which is unique within this project SQLstatement -- the sql statement we are dealing with RETURN: SUCCESS CODE FAILURE CODE NOTES: AUTHOR: DWM it worked there was an error ****************************************************************/ int InsertNewUpdateStatement(int project_id,int file_id,int function_id,char *statement) EXEC SQL begin declare sectionj int DBproject_id = OJ in~ DBfile_id = 0; int DBfunction_id = 0; char DBtable_name[TABLE_NAME SIZE]=""; char DBaction_id[ACTION_ID_SIZE]=""; EXEC SQL end declare section; char SQLstatement[BUFFER_SIZE*3]=""; char *TokenPtr=NULL; int state = 0; //state 0 --> looking for select //state 1 --> looking for from //state 2 --> grabbing table names int done=O; int ReturnCode SUCCESS_CODE; int FirstTime = TRUE; DBproject_id = project_id; DBfunction_id = function_id; DBfile_id = file_id; strcpy(SQLstatement, statement); StringToUpper(SQLstatement); TokenPtr = strtok(SQLstatement, " ,\n\t"); while (! done) { i f (! FirstTime) { TokenPtr = strtok(NULL, " ,\n\t"); FirstTime = FALSE; if (TokenPtr != NULL) { switch (state) { case 0: if (strcmp(TokenPtr, "UPDATE") ==0) { state++; } break; case 1: strcpy(DBtable_name, TokenPtr); EXEC SQL insert into cfg_table_refs(project_id, file_id, function_id, table_name,action_id) values (:DBproject_id, :DBfile_id, 19 ---------:DBfunction_id, :DBtable_name, 'UPDATE'); //TODO check sqlcode done++; break; default: ReturnCode break; } else { ReturnCode break; FAILURE_CODE; return ReturnCode; /************************************************************ InsertNewInsertStatement FUNCTION: * Check to see if the SQLstatement is a insert statement PURPOSE: * if it iss, fill in the cfg_table_refs table with the * project, file, function, table_name and 'INSERT' * PARAMETERS: project_id -- the project this file belongs to * file id -- the identifier of the file * function id -- the ID of this function which is unique within * this project * SQLstatement -- the sql statement we are dealing with * it worked RETURN: SUCCESS CODE there was an error FAILURE CODE * * NOTES: * AUTHOR: DWM ****************************************************************/ int InsertNewInsertStatement(int project_id,int file_id,int function_id,char *statement) * EXEC SQL begin declare section; int DBproject_id = 0; int DBfile_id = 0; int DBfunction_id = 0; char DBtable_name[TABLE_NAME SIZE]=""; char DBaction_id[ACTION_ID_SIZE]=""; EXEC SQL end declare section; char SQLstatement[BUFFER_SIZE*3]=""; char *TokenPtr=NULL; //state 0 --> looking for select int state = 0; //state 1 --> looking for from //state 2 --> grabbing table names int done=O; SUCCESS_CODE; int ReturnCode int FirstTime = TRUE; DBproject_id = project_id; DBfunction_id = function_id; DBfile_id = file id; strcpy(SQLstatement, statement); 20 StringToUpper(SQLstatement); TokenPtr = strtok(SQLstatement," ,\n\t(II); while ( ! done) { i f (! FirstTime) { TokenPtr = strtok(NULL," ,\n\t(II); } FirstTime = FALSE; if (TokenPtr != NULL) { switch (state) { case 0: if (strcmp(TokenPtr, "INSERT") ==0) { state++; break; case 1: if (strcmp(TokenPtr, "INTO") ==0) { state++; break; case 2: strcpy(DBtable_name, TokenPtr); EXEC SQL insert into cfg_table_refs(project_id, file_id, function_id, table_name,action_id) values (:DBproject_id, :DBfile_id, :DBfunction_id, :DBtable_name, 'INSERT'); //TODO check sqlcode done++; break; default: ReturnCode FAILURE_CODE; break; } else { ReturnCode break; return ReturnCode; 21 #include "k:\develop\admp\admp.h" j***************************************************** ******* FUNCTION: FindFunctionDefinition PURPOSE: Given a pointer to a file which is open to the second line of a function definition, extract the name of the function. PARAMETERS: fp -- the file pointer FirstLIne -- the first line of text of the function def function name -- the name of the function (this will be returned ) * NumOfLines -- the number of lines we have moved forward * in the file .... if we are successful this will be 0 * RETURN: SUCCESS CODE -- it worked * FAILURE CODE -- best guess is this isn't a function after all * NOTES: if we fail and don't think its a function, the file pointer will * be advanced past whatever it is. If we are successful the * file pointer will be left as it was to start with. * AUTHOR: DWM * * * * * * * * ****************************************************************/ int FindFunctionDefinition(FILE *fp, char *FirstLine,char *function_name, long * NumOf Lines) int ReturnCode = SUCCESS_CODE; char *token = NULL; char *prevToken = NULL; char buffer[BUFFER_SIZE]=""; char *SemiPtr=NULL; char *BracePtr=NULL; long OrigFilePos=O; int Linel=TRUE; //long FilePos=O; fgetpos(fp,&OrigFilePos); //fgetpos(fp,Filepos); //get the function definition .... try to see it at least could be valid strcpy(buffer, FirstLine); //with any luck I am sitting at a function definition token = strtok(FirstLine," \t\n"); //token should be a type .... I could validate it he re ..... if I wanted to .... token = strtok(NULL," \t\n("); (*NumOfLines) =0; I/might be a * sitting there by itself if (token == NULL) { return FAILURE_CODE; if (strcmp(token, "*")==0) token = strtok(NULL," \t\n("); if (token == NULL) { return FAILURE_CODE; //might be a * stuck to my function name if (token [0] == '*') strcpy(function_name, token+l); 1 else strcpy{function_name, token); Ilif I find a semi-colon before I find a brace then this is a prototype while (l) { i f (!Linel) { if (fgets{buffer,BUFFER_SIZE,fp) NULL) { break; } (*NumOfLines) ++; Linel=FALSE; SemiPtr = strchr{buffer, ';'); BracePtr = strchr{buffer, LEFT_BRACE); if «SemiPtr == NULL)&&(BracePtr == NULL» { continue; } else if {(SemiPtr NULL)&&{BracePtr != NULL» { break; Iisuccess else if «SemiPtr != NULL)&&(BracePtr != NULL)&&{SemiPtr>BracePtr» { break; Iisuccess else { ReturnCode break; if{ReturnCode == SUCCESS_CODE) { fsetpos{fp,&OrigFilePos) ; (*NumOfLines) = 0; return ReturnCode; 1***************************************************** ******* * FUNCTION: ctionId ' * PURPOSE: lookup the FunctionId for this function within the * given project * PARAMETERS: * RETURN: SUCCESS CODE -- it worked * FAILURE CODE -- there was an error * NOT FOUND CODE -- function not in the project 2 * NOTES: * AUTHOR: DWM ****************************************************************/ int GetFunctionId(int project_id, int file_id, char *function_name, int *function_id) EXEC SQL begin declare section; int DBproject_id=O; char DBfunction_name[FUNCTION_NAME SIZE]=""; int DBfunction_id=O; int DBfile_id=O; EXEC SQL end declare section; int ReturnCode = SUCCESS_CODE; DBproject_id = project_id; DBfile id=file_id; strcpy(DBfunction_name, function_name); EXEC SQL select function_id into :DBfunction id from cfg_function_defs where project_id = :DBproject_id and file id = :DBfile id and function name :DBfunction_name; if (SqlCode == SqlNotFoundCode) { ReturnCode NOTFOUND_CODE; else if (SqlCode != SqlSuccessCode) { ReturnCode=FAILURE_CODE; else { *function id DBfunction_id; return ReturnCode; 1***************************************************** ********** * FUNCTION: GetNextFunctionId * PURPOSE: This function gets the next unique function identifier available for the given project. project_id -- the project for which we need a new file id function id -- the file id we find and pass back * PARAMETERS: * * RETURN: SUCCESS CODE FAILURE CODE DWM we got a new file id an error occured * AUTHOR: * NOTE: ****************************************************************/ int GetNextFunctionId(int project_id, int *function_id) EXEC SQL begin declare section; int DBfunction_id=O; int DBproject_id=O; EXEC SQL end declare section; 3 //assume only one copy of this program running at once EXEC SQL select ISNULL(MAX(function_id),O)+l into :DBfunction id from cfg_function_defs where project_id = :DBproject_id; if (SqlCode != SqlSuccessCode) { return FAILURE_CODE; else { *function_id = DBfunction_id; return SUCCESS_CODE; /************************************************************ AddFunctionToProject * FUNCTION: This function adds a function to the project PURPOSE: * and returns its function id * * PARAMETERS: project_id -- the project to add the function to file id -- the file where the function is found * function name -- the name of the function * line id -- the line on which the function starts * function_id -- the unique function identifier assigned to this function and passed back to the calling function * RETURN: SUCCESS CODE it worked * FAILURE CODE -there was an error * NOTES: * AUTHOR: DWM * ****************************************************************/ int AddFunctionToProject(int project_id, int file_id, char *function_name, int line_id, int *function_id) EXEC SQL begin declare section; int DBproject_id=O; char DBfunction_name[FUNCTION_NAME SIZE]=""; int DBfunction_id=O; int DBfile_id=O; int DBline_id=O; EXEC SQL end declare section; int ReturnCode = SUCCESS_CODE; DBproject_id=project_id; strcpy(DBfunction_name, function_name); DBfile id file_id; DBline_id = line_id; if (GetNextFunctionId(project_id, &DBfunction_id)==SUCCESS_CODE) { EXEC SQL insert into cfg_function_defs(project_id, file_id, function_id, line_id,function_name) values (:DBproject_id, :DBfile_id, :DBfunction_id, :DBline_id, :DBfunction_name); if (SqlCode != SqlSuccessCode) { FAILURE_CODE; ReturnCode } else 4 ReturnCode FAILURE_CODE; *function_id = DBfunction_id; return ReturnCode; /************************************************************ * FUNCTION: RefreshFunctionHeader * PURPOSE: This function puts the function header found in * comment into the database * PARAMETERS: project_id -- the project we are dealing with * file id -- the file where the function is found * function id -- the id of the function comment -- the function header * Comment Len -- some unused argument * RETURN: SUCCESS CODE it worked * * FAILURE CODE -- there was an error * NOTES: AUTHOR: DWM * ****************************************************************/ int RefreshFunctionHeader(int project_id, int file_id, int function_id, char * comment , long CommentLen) EXEC SQL begin declare section; char DBcomment[COMMENT_SIZE]="I1; int DBproject_id=O; int DBfile_id=O; int DBfunction_id=O; EXEC SQL end declare section; FILE *fp = NULL; char *EndOfCommentsPtr NULL; int InComments = FALSE; long BytesRead = 0; char buffer [BUFFER_SIZE] =""; int ReturnCode = SUCCESS_CODE; /* DBproject_id = project_id; DBfile_id = file_id; DBfunction_id = function_id; strcpy(DBcomment,comment); //open the file i f ((fp = fopen (fileyath, "r") ) NULL) fprintf(stderr,"ERROR: unable to open file: ReturnCode = FAILURE_CODE; %s.\n",fileyath); else //file is open { 'if (fseek(fp, Startpos,SEEK_SET) !=O) fprintf(stderr,"ERROR: failure manipulating file.\n"); //get the function definition .... try to see it at least could be valid while (1) { //grab a line from the file if (fgets(buffer,BUFFER_SIZE,fp) NULL) 5 { ReturnCode=FAILURE_CODE; break; } else { if (InComments) { EndOfCommentsPtr = strstr(buffer, "*1"); if (EndOfCommentsPtr != NULL) Ilfound the end Iladjust my length by the amount left on the line II minus the length of my comment token InComments = FALSE; *I I I 1* strcat(DBcomment, buffer); else LTrim (buffer) ; if (buffer[O]=='I') { if (buffer[l]=='I') { Ilwhole line is comments strcat(DBcomment, buffer); continue; else if (buffer[l]=='*') { InComments = TRUE; strcat(DBcomment, buffer); EndOfCommentsPtr = strstr(buffer, "* I if (EndOfCommentsPtr != NULL) { Ilfound the end InComments = FALSE; } *1 II 1* else if (buffer[O]=='\n') { strcat{DBcomment, buffer); continue; else { Ilfound the end break; Ilwhile Iithese chars will mess me up .... *1 replaceCharOneWithCharTwo(DBcomment, ,\"', '&'); replaceCharOneWithCharTwo{DBcomment, '\' " '?'); replaceCharOneWithCharTwo(DBcomment, ,\t', , ,); / Iprintf (" %s ", DBcomment) ; III should have the comment so just insert it 6 II) ; EXEC SQL insert into cfg_function_header(project_id, file_id, function_id, identifier, comment) values (:DBproject_id, :DBfile_id, :DBfunction_id, 'HEADER', :DBcomrnent); strcpy(DBcomment, ""); jjTODO check sqlcode here II } return ReturnCode; 1***************************************************** ******* FUNCTION: GetCommentAndNumLines * PURPOSE: * This function grabs a comment block from the file * the file must open and the file pointer sitting * at the second line of the comment block. The first line of the comment block is passed in. * * The comment length in number of lines is passed back * PARAMETERS: fp -- the file pointer * FirstLine -- the firstline of the comment block * comment -- the comment block we found * * CommentLength -- the length of the block we found in lines RETURN: SUCCESS CODE it worked * FAILURE CODE * there was an error * NOTES: AUTHOR: DWM * ****************************************************** **********1 int GetCommentAndNumLines(FILE *fp, char *FirstLine,char *comment, long *CommentLength) { int ReturnCode = SUCCESS_CODE; int InComments = FALSE; char *EndOfCommentsPtr = NULL; char buffer[BUFFER_SIZE]=""; int NumOfLines=O; long FilePos = 0; int Line1 = TRUE; Ilopen the file 1* comment out for test i f ((fp = fopen (fileJlath, "r") ) NULL) { fprintf(stderr,"ERROR: unable to open file: %s.\n",fileJlath); ReturnCode FAILURE_CODE; else { II II if (fgets (buffer, BUFFER_SIZE, fp)==NULL) return ReturnCode; *CommentLength = 0; if (fseek(fp, CommentStartpos,SEEK_SET) !=O) fprintf(stderr,"ERROR: failure manipulating file.\n"); *1 while (1) { Ilget our position fgetpos(fp, &FilePos); Ilgrab a line from the file 7 i f (Linel) { strcpy(buffer, FirstLine); Linel = FALSE; else if(fgets(buffer,BUFFER_SIZE,fp) { break; NULL) NumOfLines++; if (InComments) { strcat(comment, buffer); EndOfCommentsPtr = strstr(buffer, "*/"); if (EndOfCommentsPtr != NULL) { InComments = FALSE; else { LTrim (buffer) ; if (buffer[D]=='/') { if (buffer[l]=='/') { //whole line is comments strcat(comment, buffer); continue; } else if (buffer[l]=='*') { InComments = TRUE; EndOfCommentsPtr = strstr(buffer, "*/"); if (EndOfCommentsPtr != NULL) { //found the end InComments = FALSE; strcat(comment, buffer); else if (buffer[D]=='\n') { continue; else { //found the end /II read an extra line that doesn't count i f (NumOfLines) NumOfLines--; //set the position of the file back to what it was before the //last read fsetpos(fp, &FilePos); break; 8 / /while (*CommentLength)=NumOfLines; II I I fclose (fp) i } comment out for testing return ReturnCode; /************************************************************ * * * * * * * * * 1< FUNCTION: RefreshProjectFile PURPOSE: Given a project and a file, refresh the function headers function definitions, function references, table references, and modification history for the functions found in that file PARAMETERS: project_id -- the project whose file list we should refresh RETURN: SUCCESS CODE it worked FAILURE CODE there was an error NOTES: AUTHOR: DWM ****************************************************************/ int RefreshProjectFile(int project_id, int file_id) EXEC SQL begin declare section; int DBproject_id = 0; int DBfile_id = 0; char DBfileyath[FILE_PATH_SIZE]="I; char DBfile_type[FILE_TYPE_SIZE] =""; EXEC SQL end declare section; int line_id = 0; char buffer [BUFFER_SIZE] =""; char buffer_temp [BUFFER_SIZE] =""; char function_name[FUNCTION_NAME_SIZE]=""; char comment [COMMENT_SIZE] ; int ReturnCode = SUCCESS_CODE; int CodeReturned = SUCCESS_CODE; int FoundComments = FALSE; int function_id = 0; FILE *SourceFilePtr = NULL; long FunctionHeaderFilePosition =0; long CommentLength=O; long FunctionDefinitionPosition =0; FILE *FunctionDefinitionFilePtr = NULL; long FunctionLength=O; long testval=O; long CurrentLine=O; long NumLines=O; DBproject_id = project_id; DBfile_id = file_id; EXEC SQL select fileyath, file_type into :DBfileyath, :DBfile_type from cfgyroject_files where project_id = :DBproject_id and file id 9 RTrim(DBfile-path ) i RTrim(DBfile_type) ; EXEC SQL delete from cfg_function_refs where project_id = :DBproject_id and file id :DBfile_id; EXEC SQL delete from cfg_function_header where project_id = :DBproject_id and file id :DBfile_id; EXEC SQL delete from cfg_function_mods where project_id = :DBproject_id and file id :DBfile_id; EXEC SQL delete from cfg_table_refs where project_id = :DBproject_id and file id :DBfile_id; EXEC SQL delete from cfg_function_defs where project_id = :DBproject_id and file id :DBfile_id; IITODO: check slqcode a if ((SqlCode == SqlSuccessCode) I I (SqlCode == SqlNotFoundCode» I lopen the file if ((SourceFilePtr = fopen (DBfile-path, "r"» == NULL) { fprintf(stderr,"ERROR: unable to open file: %s.\n",DBfile-p ath ); ReturnCode FAILURE_CODE; else while (1) { Ilgrab a line from the file fgetpos(SourceFilePtr, &testval); if (fgets(buffer,BUFFER_SIZE,SourceFilePtr) NULL) { break; } else { strcpy(buffer_temp, buffer); CurrentLine++; testval = strlen(buffer); fgetpos(SourceFilePtr, &testval); Ilif the line starts with a # sign then I don't need it i f (LTrim(buffer) [0]=='#') { III had found some comments, but apparently they were not II associated with a function if (FoundComments) { FoundComments = FALSE; strcpy(comment,""); } continue; } Ilif it's just a line feed, ignore it else i f (LTrim(buffer) [0] ==' \n' ) { continue; } Ilif this line is a comment, or begins with one then it is part of II the header else i f ((strncmp (LTrim(buffer) , "I I" ,2) ==0) II (strncmp (LTrim(buffer) , *",2)==0» 10 II I if (FoundComments) { fprintf(stderr,"ERROR: Found Unexpected Comments.\n"); } else { Ilget the file position of the beginning of the comments 1* Having trouble with this .... just pass the darn thing a line number fgetpos(SourceFilePtr,&FunctionHeaderFilePosition); FunctionHeaderFilePosition = FunctionHeaderFilePosition -strlen (buffer)-l; Ilbackup up to the beginning of the comments if (fseek(SourceFilePtr, FunctionHeaderFilePosition, SEEK_SET ) !=O fprintf(stderr,"ERROR: failure manipulating file.\n"); *1 GetCommentAndNumLines(SourceFilePtr, buffer, comment,&NumLines) IITODO check ret code CurrentLine = CurrentLine + NumLines; FoundComments=TRUE; Ilis this a prototype? or a function definition or something else? else if (strncmp(StringToUpper(LTrim(buffer_temp)), "EXEC SQL",8)==0) { Iisome sort of goofy sql statement III had found some comments, but apparently they were not associated with a function if (FoundComments) { II FoundComments = FALSE; strcpy(comment,""); continue; else { if (FindFunctionDefinition(SourceFilePtr, buffer, function_name, &N 'umLines)==SUCCESS_CODE) CurrentLine = CurrentLine + NumLines; Ilget the function_id for this function if it already exists CodeReturned = GetFunctionld (proj ect_id, file_id, function name I &function_id); if (CodeReturned == FAILURE_CODE) { fprintf(stderr, "ERROR: Failure getting function id.\n"); else { if (CodeReturned == NOTFOUND_CODE) { CodeReturned = AddFunctionToProject(project_id, file id 11 , function_name, CurrentLine, &function_id)i } if (CodeReturned == SUCCESS_CODE) { Ilfunction already exists Ilif we found comments previously then lets grab them if (FoundComments) { CodeReturned RefreshFunctionHeader(project_id, fi comment, CommentLength)i IITODO: check this return code FoundComments = FALSEi strcpy(comment,"")i CodeReturned Current Line SkipFunctionBody(SourceFilePtr, buffer, function_id, &FunctionLength)i Current Line + FunctionLengthi IITODO: check this return code Iladjust our position in the file so we are past this f unction else { fprintf(stderr,"ERROR: encountered really bad code.\n" ) i FoundComments = FALSEi strcpy(comment,"")i else lias near as I can tell it is not a function definition II so I don't care what it is FoundComments = FALSEi strcpy(comment,"")i CurrentLine Ilwhile fclose(SourceFilePtr)i Ilelse else { ReturnCode FAILURE_CODEi return ReturnCode; Ilend of function /************************************************************ 12 Current Line + NumLinesi * * * * * * * * * FUNCTION: RefreshAllFunctions PURPOSE: Given a project, refresh the function headers function definitions, function references, table references, and modification history for all functions found in the project PARAMETERS: project_id -- the project whose functions we should refresh RETURN: SUCCESS CODE it worked FAILURE CODE there was an error NOTES: AUTHOR: DWM * ****************************************************************/ int RefreshAllFunctions(int project_id) EXEC SQL begin declare section; int DBproject_id=O; int DBfile_id=O; char DBfileyath[FILE_PATH_SIZE]=""; char DBfile_type[FILE_TYPE_SIZE]=""; char DBfileyath_temp[FILE_PATH_SIZE]=""; int FileMatches = 0; EXEC SQL end declare section; char char char char drive [FILE_PATH_SIZE] =""; dir[FILE_PATH_SIZE]=""; fname[FILE_PATH_SIZE]=""; ext [FILE_PATH_SIZE]=""; int ReturnCode = SUCCESS_CODE; EXEC SQL declare GetFileCursor cursor for select file_id, fileyath, file_type from cfgyroject_files where project_id = :DBproject_id and file_type in ('S', 'C'); EXEC SQL open GetFileCursor; //TODO check sqlcode while(l) { EXEC SQL fetch GetFileCursor into :DBfile_id, if (SqlCode == SqlNotFoundCode) { ReturnCode break; SUCCESS_CODE; } else if (SqlCode != SqlSuccessCode) { ReturnCode break; FAILURE_CODE; else { if (strcmp(DBfile_type, "C")==O) { //WARNING NT-specific function 13 :DBfileyath, :DBfile_type; _splitpath(DBfile-path, drive, dir, fname, ext); StringToUpper(fname) ; sprintf(DBfile-path_temp, "!!rs!!rs.SQC", "!!r", fname); EXEC SQL select count(*) into :FileMatches from cfg-project_files where file-path like :DBfile-path_temp and file_type = 'S'; i f (FileMatches) { FileMatches o·, continue; ReturnCode RefreshProjectFile(DBproject_id,DBfile_id); EXEC SQL close GetFileCursor; return ReturnCode; 14 #include "k:\develop\adml\admlmss.h" #include "\develop\admp\varszs.h" #include "\develop\admp\admpsql.h" #define #define #define #define #define LEFT_BRACE ,{, RIGHT BRACE 'l' MODtoken MOD SQLtoken EXEC SQL BUFFER SIZE 1000 1 #define #define #define #define #define #define #define MAKE- FILE- SIZE 101 FILE PATH SIZE 151 FILE TYPE SIZE 2 FUNCTION- NAME- SIZE 51 COMMENT SIZE 100000 TABLE NAME SIZE 51 ACTION ID SIZE 21 "\ ..... c v #define DATE SIZE 20 1 int RefreshProjectFileList(int project_id); int RefreshAllFunctions(int project_id); void Connect(); void Disconnect(); void BeginTransaction() ; void CommitTransaction() ; void RollbackTransaction() ; char * RTrim (char *stringl); char * LTrim (char *stringl); char * StringToUpper(char *buffer); int replaceCharOneWithCharTwo(char *string, char one, char two); int GetNextFileld(int project_id, int *file_id); int AddFileToProject(int project_id, char *file-path); int RefreshProjectFileList(int project_id); int GetNCNBlineCount(FILE *fp, int project_id, int file_id, int function id, char *FirstLine, int *NCNBlineCount,int *CommentLineCount, long *FunLen); int SkipFunctionBody(FILE *fp, char *FirstLine,int project_id, int file_id, int function id long *FunctionLen) ; int FindFunctionDefinition(FILE *fp, char *FirstLine,char *function_name, long * NumOf Lines) int GetFunctionld(int project_id, int file_id, char *function_name, int *function_id); int GetNextFunctionld(int project_id, int *function_id); int AddFunctionToProject(int project_id, int file_id, char *function_name, int line_id, int *function_id); int RefreshFunctionHeader(int project_id, int file_id, int function id, char * comment , long CommentLen); int GetCommentAndNumLines(FILE *fp, char *FirstLine,char *comment, long *CommentLength); int int int int RefreshProjectFile(int project_id, int file_id) RefreshAllFunctions(int project_id); FindTableRefs(FILE *fp, int project_id,int file_id,int function id,char *buffer); InsertNewSelectStatement(int project_id,int file_id,int function_id,char *SQLstatement) int InsertNewUpdateStatement(int project_id,int file_id,int function_id,char *SQLstatement) int InsertNewDeleteStatement(int project_id,int file_id,int function_id,char *SQLstatement) int InsertNewlnsertStatement(int project_id,int file_id,int function_id,char *SQLstatement) 1 #ifndef B PROMPT #define B PROMPT 1 1* Define our prompt node structure type */ struct PStack { int statej struct PStack *linkj }; typedef struct PStack PromptStackj ===================================================== II Macro Definitions II Function Prototypes =================================================== PromptStack *Base_PushPromptStack( PromptStack *stack, int item )j PromptStack *Base_PopPromptStack( PromptStack *stack )j PromptStack *Base_KillPromptStack( PromptStack *stack )j II --- End of file b-Frompt.h -----------------------------------------------#endif 1 #include #include #include #include #include #include <stdio.h> <stdlib.h> <ctype.h> <string.h> <time.h> IIK:\develop\ahtl\ahtl.h ll /***************************************************** ************************ Function: Base_PushPromptStack Description: This function will push a prompt item onto the prompt stack. Do this operation when your program wishes to move forward through the prompt list. Arguments: stack item the existing prompt stack the item to push onto the stack Returns: SUCCESS CODE FAILURE CODE Exits: None. the push was successful Unsuccessful *****************************************************************************/ PromptStack *Base_pushPromptStack( PromptStack *stack, int item) { PromptStack *pNewNode; /* Create the new node. If failure, bailout and report error */ ( ( pNewNode ( PromptStack * )malloc( sizeof( PromptStack ) ) == NULL ) if /* If we couldn't allocate the memory required, return a NULL */ return NULL; /* Assign this node's prompt state */ pNewNode->state = item; /* Put it at the top of the stack */ pNewNode->link = stack; stack = pNewNode; return stack; /* Base_PushPromptStack */ /***************************************************************************** Function: Base_PopPromptStack Description: This function will pop a prompt item off the prompt stack. Do this operation when your program wishes to move forward through the prompt list. 1 Arguments: stack item the existing prompt stack the item popped off the stack Returns: SUCCESS CODE FAILURE CODE Exits: None. the pop was successful Unsuccessful ****************************************************~* ***********************1 PromptStack *Base_PopPromptStack( PromptStack *stack ) { PromptStack *pTmpPtr; i f ( stack == NULL { return NULL; } 1* Save old pointer *1 pTmpPtr = stack; 1* Restore the pointer *1 stack = stack->link; free ( ( PromptStack * )pTmpPtr ); return stack; 1* Base_PopPromptStack *1 /***************************************************************************** Function: Base_KillPromptStack Description: This function will delete the entire stack and recycle the memory used by it. Call this function when you are completely done with a prompt stack. Arguments: stack the existing prompt stack Returns: None. Exits: None. ****************************************************** ***********************1 PromptStack *Base_KiIIPromptStack( PromptStack *stack ) { PromptStack *pTmpPtr; 1* Traverse through the stack and pop all the elements off *1 pTmpPtr = stack; while ( pTmpPtr l= NULL { Base_PopPromptStack( pTmpPtr ); pTmpptr = pTmpPtr->link; 2 free( stack ); return NULL; /* Base_KillPromptStack */ 3