#include "file.h" int globalClassIndex = 0; struct file * file_new() { struct file * fileInstance = malloc( sizeof( struct file ) ); return fileInstance; } void file_parseMacros( struct file * fileInstance, struct array * files ) { file_removeComments( fileInstance ); char * filename = fileInstance->filename; printf("parse Macros: %s \n\n", filename); char * source = fileInstance->source; printf("%s\n\n", source); int includeCount = array_length( fileInstance->includes ); printf("add includes. %i \n", includeCount); for ( int k = 0; k < includeCount; ++k ) { struct include * includeInstance = array_get( fileInstance->includes, k ); char * currentInclude = includeInstance->path; char * includeFileName = file_getFileNameFromInclude( currentInclude ); char * includeFileBaseName = file_removeExtensionFromFileName( includeFileName ); struct file * includedFileInstance = file_getFileByFileName( files, includeFileBaseName ); if( includedFileInstance != NULL ) { printf("loaded %s.h \n\n", includedFileInstance->path ); } else { text * filePath = text_new("/usr/include/"); text_append( filePath, includeFileName ); text_append( filePath, ".h" ); if( fileSystem_exists( filePath->value ) ) { includedFileInstance = file_new(); includedFileInstance->filename = basename( text_copy( filePath->value ) ); includedFileInstance->dirname = dirname( text_copy( filePath->value ) ); includedFileInstance->path = filePath->value; printf("Created new file: %s\n\n", includedFileInstance->path); includedFileInstance->source = fileSystem_readFile( includedFileInstance->path ); //printf("%s\n\n", includedFileInstance->source); } } file_parseMacros( includedFileInstance, files ); } } void file_extendClasses( struct file * fileInstance ) { //printf( ANSI_COLOR_YELLOW "\n\n\n extend class.\n" ANSI_COLOR_RESET ); struct array * classes = fileInstance->classes; int classesCount = array_length( classes ); for (int i = 0; i < classesCount; ++i) { struct class * classInstance = array_get( classes, i ); classInstance->hasExtended = -1; } for (int i = 0; i < classesCount; ++i) { struct class * classInstance = array_get( classes, i ); class_extendClass( classInstance ); } } void file_extractTemplates( struct file * fileInstance ) { struct array * classes = fileInstance->classes; int classesCount = array_length( classes ); for (int i = 0; i < classesCount; ++i) { struct class * classInstance = array_get( classes, i ); int methodCount = array_length( classInstance->methods ); for ( int k = 0; k < methodCount; ++k ) { struct method * methodInstance = array_get( classInstance->methods, k ); methodInstance->bodyOriginal = method_extractTemplates( methodInstance->bodyOriginal ); } } struct array * functions = fileInstance->functions; int functionCount = array_length( functions ); for (int i = 0; i < functionCount; ++i) { struct functionLayout * functionInstance = array_get( functions, i ); functionInstance->bodyOriginal = method_extractTemplates( functionInstance->bodyOriginal ); } } char * class_createRegexSearchNeedle( char * name ) { char * replaceFromRegex = "\\b"; replaceFromRegex = text_concatenate( replaceFromRegex, name ); replaceFromRegex = text_concatenate( replaceFromRegex, "\\b" ); return replaceFromRegex; } void class_copyMethod( struct class * classInstance, struct method * methodInstance, struct class * classCopy, int * lineNumber, char * classNameRegex, char * templateAgumentRegex, char * firstTemplateArgument, char * firstTemplateArgumentValue ) { struct method * methodCopy = malloc( sizeof( struct method ) ); methodCopy->methodName = methodInstance->methodName; methodCopy->isSetter = methodInstance->isSetter; methodCopy->isGetter = methodInstance->isGetter; methodCopy->returnType = text_copy( methodInstance->returnType ); *lineNumber += text_countLineBreaks( methodInstance->bodyOriginal, -1 ) + 10; methodCopy->lineNumber = *lineNumber; methodCopy->arguments = array_new(); int argumentsCount = array_length( methodInstance->arguments ); for (int l = 0; l < argumentsCount; ++l) { char * currentArgument = array_get( methodInstance->arguments, l ); char * argumentCopy = text_copy( currentArgument ); if( l == 0 ) { argumentCopy = text_regexReplaceAll( argumentCopy, classNameRegex, classInstance->className, classCopy->className ); } array_add( methodCopy->arguments, argumentCopy ); } methodCopy->variables = array_new(); method_addThisVariableToVariables( classCopy, methodCopy->variables ); methodCopy->bodyOriginal = text_regexReplaceAll( methodInstance->bodyOriginal, templateAgumentRegex, firstTemplateArgument, firstTemplateArgumentValue );//methodInstance->bodyOriginal; for ( int h = 0; h < argumentsCount; ++h ) { char * currentArgument = array_get( methodCopy->arguments, h ); currentArgument = text_regexReplaceAll( currentArgument, templateAgumentRegex, firstTemplateArgument, firstTemplateArgumentValue ); array_set( methodCopy->arguments, h, currentArgument ); } methodCopy->returnType = text_regexReplaceAll( methodCopy->returnType, templateAgumentRegex, firstTemplateArgument, firstTemplateArgumentValue ); array_add( classCopy->methods, methodCopy ); } void class_copyMethods( struct class * classInstance, struct class * classCopy, char * firstTemplateArgument, char * firstTemplateArgumentValue, int * lineNumber ) { char * templateAgumentRegex = class_createRegexSearchNeedle( firstTemplateArgument ); char * classNameRegex = class_createRegexSearchNeedle( classInstance->className ); // "\\b TT \\b" int methodCount = array_length( classInstance->methods ); for (int k = 0; k < methodCount; ++k ) { struct method * methodInstance = array_get( classInstance->methods, k ); class_copyMethod( classInstance, methodInstance, classCopy, lineNumber, classNameRegex, templateAgumentRegex, firstTemplateArgument, firstTemplateArgumentValue ); } } void class_copyProperties( struct class * classInstance, struct class * classCopy, char * firstTemplateArgument, char * firstTemplateArgumentValue ) { char * replaceFromRegex = class_createRegexSearchNeedle( firstTemplateArgument ); int propertyCount = array_length( classInstance->properties ); for (int k = 0; k < propertyCount; ++k ) { struct property * propertyInstance = array_get( classInstance->properties, k ); struct property * propertyCopy = malloc( sizeof( struct property ) ); propertyCopy->propertyName = text_copy( propertyInstance->propertyName ); propertyCopy->datatype = text_copy( propertyInstance->datatype ); propertyCopy->decleration = text_copy( propertyInstance->decleration ); propertyCopy->value = text_copy( propertyInstance->value ); propertyCopy->isPointer = propertyInstance->isPointer; propertyCopy->type = text_copy( propertyInstance->type ); propertyCopy->hasValue = propertyInstance->hasValue; propertyCopy->decleration = text_regexReplaceAll( propertyCopy->decleration, replaceFromRegex, firstTemplateArgument, firstTemplateArgumentValue ); propertyCopy->datatype = text_regexReplaceAll( propertyCopy->datatype, replaceFromRegex, firstTemplateArgument, firstTemplateArgumentValue ); array_add( classCopy->properties, propertyCopy ); } } void class_instantiateTemplates( struct file * fileInstance, struct class * classInstance, int * lineNumber ) { struct template * currentTemplate = classInstance->template; array * intances = currentTemplate->instances; array * arguments = currentTemplate->arguments; printf("\n\n\n\n Creating %i templates for %s\n\n\n\n\n", array_length( intances ), classInstance->className ); int intancesCount = array_length( intances ); for ( int j = 0; j < intancesCount; ++j ) { struct templateInstance * currentTemplateInstance = array_get( intances, j ); char * firstTemplateArgumentValue = array_get( currentTemplateInstance->argumentValues, 0 ); // array * char * firstTemplateArgument = array_get( arguments, 0 ); // template struct class * classCopy = class_new(); classCopy->methods = array_new(); classCopy->properties = array_new(); classCopy->extends = array_new(); classCopy->classIndex = classInstance->classIndex; char * newClassName = text_copy( classInstance->className ); newClassName = text_concatenate( newClassName, "_" ); newClassName = text_concatenate( newClassName, firstTemplateArgumentValue ); newClassName = text_replaceAll( newClassName, "*", "_pointer" ); newClassName = text_removeAllWhiteSpaces( newClassName ); classCopy->className = newClassName; class_copyMethods( classInstance, classCopy, firstTemplateArgument, firstTemplateArgumentValue, lineNumber ); class_copyProperties( classInstance, classCopy, firstTemplateArgument, firstTemplateArgumentValue ); classCopy->hasReflection = classInstance->hasReflection; classCopy->usesTemplate = true; array_add( fileInstance->classes, classCopy ); array_add( allClasses, classCopy ); // printf("replacing replaceFrom: %s namespace: %s\n\n", firstTemplateArgument, firstTemplateArgumentValue); // printf("\n\n\n\n\n\n\nAdding class to allClasses: '%s'\n\n\n\n\n\n\n", classInstance->className); // array_add( fileInstance->classes, classCopy ); } } void file_instanciateTemplates( struct file * fileInstance ) { int lineNumber = 0; struct array * classes = fileInstance->classes; int classesCount = array_length( classes ); for (int i = 0; i < classesCount; ++i) { struct class * classInstance = array_get( classes, i ); if( classInstance->usesTemplate ) { class_instantiateTemplates( fileInstance, classInstance, &lineNumber ); } } } void file_composeHeaderMacros( struct file * fileInstance, struct text * classHeader ) { text_append( classHeader, "\n// Macros\n" ); int macroCount = array_length( fileInstance->macros ); for (int i = 0; i < macroCount; ++i) { char * currentMacro = array_get( fileInstance->macros, i ); text_append( classHeader, "\n" ); text_append( classHeader, currentMacro ); text_append( classHeader, "\n" ); } text_append( classHeader, "\n\n" ); } void file_compose( struct file * fileInstance, struct application * applicationInstance ) { char * filename = fileInstance->filename; struct text * classHeader = file_composeHeaderIncludes( fileInstance ); struct array * sourceArray = array_new(); struct array * classes = fileInstance->classes; int classesCount = array_length( classes ); for (int i = 0; i < classesCount; ++i) { struct class * classInstance = array_get( classes, i ); if( i == 0 ) { if( classInstance->usesTemplate ) { continue; } } class_composeHeader( classInstance, classHeader, filename ); class_composeMethods( classInstance, classHeader, sourceArray ); } file_composeFunctions( fileInstance->functions, sourceArray, classHeader ); file_writeAll( sourceArray, classHeader, fileInstance->path, fileInstance->classes, fileInstance->globals, fileInstance->path, applicationInstance ); } void file_addIncludesToHeader( struct text * classHeader, struct file * currentFile ) { text_append( classHeader, "\n" ); text_append( classHeader, "#include \"stdlib.h\"\n\n" ); //text_append( classHeader, "#include \"classConfiguration.h\"\n\n" ); text_append( classHeader, "extern char * __ClassNames[];\n\n" ); text_append( classHeader, "\n// Includes\n" ); int includesCount = array_length( currentFile->includes ); for (int i = 0; i < includesCount; ++i) { struct include * includeInstance = array_get( currentFile->includes, i ); char * currentInclude = includeInstance->path; if( includeInstance->enabled ) { text_append( classHeader, "\n" ); text_append( classHeader, currentInclude ); text_append( classHeader, "\n" ); } } text_append( classHeader, "\n\n" ); } void file_preventDoubleLoadingHeader( struct text * classHeader, char * filename ) { // . with _ filename = text_replaceChar( filename, 46, 95 ); text_append( classHeader, "#ifndef _" ); text_append( classHeader, filename ); text_append( classHeader, "\n\n#define _" ); text_append( classHeader, filename ); text_append( classHeader, "\n\n" ); } struct text * file_composeHeaderIncludes( struct file * currentFile ) { char * filename = ( currentFile->filename ); struct text * classHeader = text_new(""); file_preventDoubleLoadingHeader( classHeader, filename ); file_composeHeaderMacros( currentFile, classHeader ); file_addIncludesToHeader( classHeader, currentFile ); return classHeader; } void file_extractMethodsAndProperties( struct file * fileInstance ) { char * source = fileInstance->source; array * classesArray = array_new(); lexer * currentLexer = lexer_new(); fileInstance->functions = array_new(); lexer_getTokens( currentLexer, source ); lexer_sortKeys( currentLexer ); int count = lexer_length( currentLexer ); int bodyCloseIndex = -1; int depth = 0; for (int i = count - 1; i >= 0; --i) { char * token = lexer_getToken( currentLexer, i ); int key = lexer_getKey( currentLexer, i ); if ( strcmp( token, "{" ) == 0 ) { depth++; } if( depth == 0 ) { if ( strcmp( token, "class" ) == 0 ) { file_extractInnerClass( currentLexer, i, key, fileInstance, source, bodyCloseIndex ); } } if ( strcmp( token, "}" ) == 0 ) { depth--; } } } void file_extractFunctions( struct file * fileInstance ) { char * source = fileInstance->source; array * classesArray = array_new(); lexer * currentLexer = lexer_new(); fileInstance->functions = array_new(); lexer_getTokens( currentLexer, source ); lexer_sortKeys( currentLexer ); int count = lexer_length( currentLexer ); int bodyCloseIndex = -1; int depth = 0; for (int i = count - 1; i >= 0; --i) { char * token = lexer_getToken( currentLexer, i ); int key = lexer_getKey( currentLexer, i ); if ( strcmp( token, "{" ) == 0 ) { depth++; } if( depth == 0 ) { if ( strcmp( token, "(" ) == 0 ) { file_extractFunction( currentLexer, i, key, fileInstance, source, bodyCloseIndex, classesArray ); } } if ( strcmp( token, "}" ) == 0 ) { depth--; } } } void file_parseClassBody( lexer * currentLexer, int fromKey, int toIndex, char * source, struct file * fileInstance, struct class * classInstance ) { int depth = -1; int parsintMethod = -1; printf(" class %s{\n\n", classInstance->className); for (int i = fromKey; i < toIndex; ++i) { int key = lexer_getKey( currentLexer, i ); char * currentToken = lexer_getToken( currentLexer, i ); if ( strcmp( currentToken, "{" ) == 0 ) { depth++; } if( depth == 0 ) { //printf( "parseClassBody: %s : %i\n", currentToken, (int) key ); if ( strcmp( currentToken, ";" ) == 0 ) { class_extractProperty( currentLexer, key, i, source, classInstance ); } if ( strcmp( currentToken, "(" ) == 0 && parsintMethod == -1 ) { int argumentCloseIndex = text_findArgumentCloseIndex( source, key ); int firstNextCharacter = text_findFirstNextCharacterNotWhiteSpace( source, argumentCloseIndex ); int beforePrevious = lexer_getKey( currentLexer, i - 2 ); char * methodDecleration = text_removeWhiteSpaces( text_slice( source, beforePrevious, firstNextCharacter ) ); // () { if( source[firstNextCharacter] != 123 ) { continue; } class_extractMethod( currentLexer, source, i, classInstance, fileInstance->classes, fileInstance->functions ); parsintMethod = 1; } } if ( strcmp( currentToken, "}" ) == 0 ) { depth--; parsintMethod = -1; } } printf("\n"); } void file_extractInnerClass( lexer * currentLexer, int i, int key, struct file * fileInstance, char * source, int bodyCloseIndex ) { int bodyOpenIndex = lexer_findNextToken( currentLexer, i, "{" ); char * nextToken = lexer_getToken( currentLexer, i + 1 ); char * className; if( strcmp( nextToken, "extends" ) == 0 ) { int nextKey = lexer_getKey( currentLexer, i + 1 ); className = text_slice( source, key + 5, ( int ) nextKey - 1 ); bodyCloseIndex = lexer_findBodyCloseIndex( currentLexer, i + 2 ); } else { className = text_slice( source, key + 5, bodyOpenIndex - 1 ); bodyCloseIndex = lexer_findBodyCloseIndex( currentLexer, i + 1 ); } struct class * classInstance = application_getClassByClassName( fileInstance->classes, text_removeWhiteSpaces( className ) ); file_parseClassBody( currentLexer, i + 1, bodyCloseIndex, source, fileInstance, classInstance ); printf(" }\n\n"); } char * file_extractFunctionDecleration( lexer * currentLexer, int i, int key, char * source ) { int currentKey = lexer_getKey( currentLexer, i ); int previousKey = lexer_getKey( currentLexer, i - 1 ); int fromPreviousKey = ( int ) previousKey + 1; char * functionDeclaration = text_removeWhiteSpaces( text_slice( source, fromPreviousKey, key - 1 ) ); return functionDeclaration; } void file_extractFunction( lexer * currentLexer, int i, int key, struct file * fileInstance, char * source, int bodyCloseIndex, struct array * classesArray ) { struct functionLayout * functionInstance = malloc( sizeof( struct functionLayout ) ); functionInstance->variables = array_new(); char * functionSource = class_extractBodyFromSource( currentLexer, i, source, bodyCloseIndex ); char * functionDeclaration = file_extractFunctionDecleration( currentLexer, i, key, source ); struct array * functionDeclarationParts = text_split( functionDeclaration, " \t" ); struct array * argumentsArray = method_getArguments_new( currentLexer, key, i, source, functionInstance->variables ); int declarationLength = array_length( functionDeclarationParts ); char * functionName = ( char * ) array_get( functionDeclarationParts, declarationLength - 1 ); functionInstance->name = functionName; functionInstance->declarationText = functionDeclaration; functionInstance->bodyOriginal = functionSource; functionInstance->arguments = argumentsArray; functionInstance->isVariadic = method_methodIsVaradic( argumentsArray ); functionInstance->lineNumber = text_countLineBreaks( source, ( int ) key ); method_extractVariablesFromArguments( functionInstance->arguments, classesArray, functionInstance->variables ); array_add( allFunctions, functionInstance ); array_add( fileInstance->functions, functionInstance ); } char * file_removeSingleLineComment_new( lexer * currentLexer, int i, char * source ) { int nextLineIndex = lexer_findNextToken( currentLexer, i, "\n" ); int key = lexer_getKey( currentLexer, i ); int numberOfCharacters = nextLineIndex - ( int ) key; return text_replaceAt( ( int ) key, nextLineIndex, source, "" ); } char * file_removeArrayTypeDefinitions( char * source ) { lexer * currentLexer = lexer_new(); //lexer_setSource( source ); lexer_tokenize( currentLexer, source, "<"); lexer_tokenize( currentLexer, source, ">"); lexer_sortKeys( currentLexer ); int count = lexer_length( currentLexer ); for (int i = count - 1; i >= 0; --i) { char * token = lexer_getToken( currentLexer, i ); if ( strcmp( token, "<" ) == 0 ) { int closeTypeDefinition = lexer_findNextToken( currentLexer, i, ">" ); int key = lexer_getKey( currentLexer, i ); int previousKeyIndex = text_findFirstCharacterReverse( source, key ); char * wordBeforeKey = text_extractWordBeforeKey( source, key ); if ( strcmp( wordBeforeKey, "array" ) == 0 ) { for (int i = key; i < closeTypeDefinition + 1; ++i) { source[i] = 32; } printf("\n\n\n remove this array declaration: %s\n\n\n", wordBeforeKey); } } } return source; } char * file_removeSingleLineComments( char * source ) { lexer * currentLexer = lexer_new(); //lexer_setSource( source ); lexer_tokenize( currentLexer, source, "//"); lexer_tokenize( currentLexer, source, "\n"); lexer_sortKeys( currentLexer ); int count = lexer_length( currentLexer ); for (int i = count - 1; i >= 0; --i) { char * token = lexer_getToken( currentLexer, i ); if ( strcmp( token, "//" ) == 0 ) { source = file_removeSingleLineComment_new( currentLexer, i, source ); } } return source; } char * file_replaceMultiLineComment( lexer * currentLexer, int i, char * source ) { int key = lexer_getKey( currentLexer, i ); int closeCommentIndex = lexer_findNextToken( currentLexer, i, "*/" ) + 2; char * comment = text_slice( source, key, closeCommentIndex - 1 ); int numberOfLineBreaks = text_countLineBreaks( comment, -1 ); char * replacementText = malloc( numberOfLineBreaks + 1 ); replacementText[0] = 0; for ( int j = 0; j < numberOfLineBreaks; ++j ) { strcat( replacementText, "\n" ); } //printf("------------- open comment found: %s \n\n --%s-- \n\n %i \n", filename, comment, numberOfLineBreaks); return text_replaceAt( ( int ) key, closeCommentIndex , source, replacementText ); } char * file_removeMultiLineComments( char * source ) { lexer * currentLexer = lexer_new(); lexer_tokenize( currentLexer, source, "/*" ); lexer_tokenize( currentLexer, source, "*/" ); lexer_sortKeys( currentLexer ); int count = lexer_length( currentLexer ); for (int i = count - 1; i >= 0; --i) { char * token = lexer_getToken( currentLexer, i ); if ( strcmp( token, "/*" ) == 0 ) { source = file_replaceMultiLineComment( currentLexer, i, source ); } } return source; } void file_removeComments( struct file * fileInstance ) { char * filename = fileInstance->path; char * source = fileInstance->source; //source = file_removeArrayTypeDefinitions( source ); source = file_removeSingleLineComments( source ); source = file_removeMultiLineComments( source ); fileInstance->source = source; } void file_extractGlobalVariable( lexer * currentLexer, int key, int i, struct file * fileInstance, char * source ) { int semicolonIndex = lexer_findPreviousKeyByToken( currentLexer, i, ";" ); void * previousToken = lexer_getToken( currentLexer, i - 1 ); int previousKey = lexer_getKey( currentLexer, i - 1 ); char * globalDeclaration = text_removeWhiteSpaces( text_slice( source, semicolonIndex + 1, key ) ); struct variable * variableInstance = variabe_new(); struct array * ISParts = text_split( globalDeclaration, "=" ); char * beforeIS = array_get( ISParts, 0 ); struct array * semicolonParts = text_split( globalDeclaration, ";" ); char * beforeSemocolon = array_get( semicolonParts, 0 ); struct array * defineParts = text_split( beforeSemocolon, " \t" ); char * variableName = array_get( defineParts, array_length( defineParts ) - 1 ); variableInstance->variableName = variableName; variableInstance->isPointer = variable_isPointer( defineParts ); variableInstance->declaration = globalDeclaration; variableInstance->lineNumber = text_countLineBreaks( source, ( int ) key ); variableInstance->datatype = tools_findDatatype( defineParts ); array_add( fileInstance->globals, variableInstance ); //printf(" %i previous token: %s extract global: %s pointer: %i \n\n",semicolonIndex, previousToken, globalDeclaration, variableInstance->isPointer); } void file_extractClasses( struct file * fileInstance ) { printf("Extract classes from file: '%s' \n\n", fileInstance->filename); char * source = fileInstance->source; array * classesArray = array_new(); lexer * currentLexer = lexer_new(); lexer_getTokens( currentLexer, source ); lexer_sortKeys( currentLexer ); int count = lexer_length( currentLexer ); int bodyCloseIndex = 0; int depth = 0; for (int i = count - 1; i >= 0; --i) { char * token = lexer_getToken( currentLexer, i ); int key = lexer_getKey( currentLexer, i ); if ( strcmp( token, "{" ) == 0 ) { depth++; } if ( strcmp( token, "}" ) == 0 ) { depth--; } if( depth == 0 ) { if ( strcmp( token, ";" ) == 0 ) { file_extractGlobalVariable( currentLexer, key, i, fileInstance, source ); } } if ( strcmp( token, "class" ) == 0 ) { if( depth == 0 ) { file_extractClass( currentLexer, key, i, classesArray, depth, source ); } } } fileInstance->classes = classesArray; } void file_extractClass( lexer * currentLexer, int key, int i, struct array * classesArray, int depth, char * source ) { char * previousToken = lexer_getToken( currentLexer, i - 1 ); char * nextToken = lexer_getToken( currentLexer, i + 1 ); int bodyOpenIndex = lexer_findNextToken( currentLexer, i, "{" ); struct class * classInstance = class_new(); classInstance->hasReflection = false; if( i > 0 ) { if( strcmp( previousToken, "reflect" ) == 0 ) { printf("this class is using reflection\n\n"); classInstance->hasReflection = true; } if( strcmp( previousToken, ">" ) == 0 ) { char * templateName = lexer_getToken( currentLexer, i - 3 ); if( strcmp( templateName, "template" ) == 0 ) { int fromKey = lexer_getKey( currentLexer, i - 2 ) + 1; int toKey = lexer_getKey( currentLexer, i - 1 ) - 1; char * templateArguments = text_slice( source, fromKey, toKey ); classInstance->usesTemplate = true; classInstance->template = template_new(); template_add_arguments( classInstance->template, templateArguments ); printf("this class has a template: %s \n\n", templateArguments); } //classInstance->hasReflection = true; } } if( strcmp( nextToken, "extends" ) == 0 ) { int nextKey = lexer_getKey( currentLexer, i + 1 ); char * className = text_slice( source, key + 5, nextKey - 1 ); classInstance->className = text_removeWhiteSpaces( className ); char * extendsText = text_slice( source, nextKey + 7, bodyOpenIndex - 1 ); char * extendsTextCopy = text_copy( extendsText ); classInstance->extends = text_split( extendsTextCopy, "," ); } else { classInstance->extends = array_new(); char * className = text_slice( source, key + 5, bodyOpenIndex - 1 ); classInstance->className = text_removeWhiteSpaces( className ); } classInstance->properties = array_new(); classInstance->methods = array_new(); classInstance->classIndex = globalClassIndex++; printf( " class %s{}\n", classInstance->className ); array_add( classesArray, classInstance ); array_add( allClasses, classInstance ); } void file_composeFunctionArguments( struct functionLayout * currentFunction, struct text * methodSource, struct text * classHeader ) { struct array * arguments = currentFunction->arguments; int argumentCount = array_length( arguments ); for (int j = 0; j < argumentCount; ++j) { char * argumentText = (char *) array_get( currentFunction->arguments, j ); text_append( methodSource, argumentText ); text_append( classHeader, text_copy( argumentText ) ); if( j != argumentCount-1 ) { text_append( methodSource, ", " ); text_append( classHeader, ", " ); } } } void file_composeFunction( struct functionLayout * currentFunction, struct array * sourceArray, struct text * classHeader ) { struct codeBundle * code = malloc( sizeof( struct codeBundle ) ); struct text * methodSource = text_new( "" ); text_append( methodSource, currentFunction->declarationText ); text_append( classHeader, currentFunction->declarationText ); text_append( methodSource, "( "); text_append( classHeader, "( "); file_composeFunctionArguments( currentFunction, methodSource, classHeader ); text_append( classHeader, " );\n\n" ); text_append( methodSource, " ) {" ); text_append( methodSource, currentFunction->body ); text_append( methodSource, "}" ); code->lineNumber = currentFunction->lineNumber; code->sourceCode = methodSource->value; array_add( sourceArray, code ); } void file_composeFunctions( struct array * functions, struct array * sourceArray, struct text * classHeader ) { int functionCount = array_length( functions ); for (int i = 0; i < functionCount; ++i) { struct functionLayout * currentFunction = array_get( functions, i ); file_composeFunction( currentFunction, sourceArray, classHeader ); } int maxLineNumber = 0; int sourceCount = array_length( sourceArray ); // align undefined line numbers for added function for ( int i = 0; i < sourceCount; ++i ) { struct codeBundle * code = array_get( sourceArray, i ); int afterBodyLineNumber = code->lineNumber + text_countLineBreaks( code->sourceCode, -1 ); if( afterBodyLineNumber > maxLineNumber ) { maxLineNumber = afterBodyLineNumber; } } maxLineNumber += 2; for (int i = 0; i < sourceCount; ++i) { struct codeBundle * code = array_get( sourceArray, i ); if( code->lineNumber == -1 ) { code->lineNumber = maxLineNumber; maxLineNumber += text_countLineBreaks( code->sourceCode, -1 ); maxLineNumber += 2; } } maxLineNumber += 12; } // this need to be in a separate file void file_composeConfigInformation( struct array * files, struct application * applicationInstance ) { int fileCount = array_length( files ); struct text * configurationHeader = text_new( "" ); struct text * configurationSource = text_new( "" ); int classesCount = array_length( allClasses ); text_append( configurationHeader, "#ifndef __" ); text_append( configurationHeader, "classConfiguration\n\n" ); text_append( configurationHeader, "#define __classConfiguration\n\n" ); text_append( configurationHeader, "#include \n\n" ); for (int i = 0; i < fileCount; ++i) { struct file * fileInstance = array_get( files, i ); char * path = fileInstance->path; char * filename = fileInstance->filename; if( array_length( fileInstance->classes ) > 0 ) { text_append( configurationHeader, "#include <" ); text_append( configurationHeader, path ); //text_append( configurationHeader, filename ); text_append( configurationHeader, ".h>\n\n" ); } } text_append( configurationHeader, "#define TOTAL_CLASS_COUNT " ); text_append( configurationHeader, text_fromNumber(classesCount) ); text_append( configurationHeader, "\n\n" ); text_append( configurationSource, "#include \n\n" ); text_append( configurationHeader, "extern char * __ClassNames[TOTAL_CLASS_COUNT];\n"); text_append( configurationHeader, "extern int __ClassPropertyCount[TOTAL_CLASS_COUNT];\n"); text_append( configurationHeader, "extern char * __ClassPropertyNames[TOTAL_CLASS_COUNT][30];\n"); text_append( configurationHeader, "extern int __ClassPropertyOffsets[TOTAL_CLASS_COUNT][30];\n"); text_append( configurationHeader, "extern int __ClassPropertyOffsets[TOTAL_CLASS_COUNT][30];\n"); text_append( configurationSource, "char * __ClassNames[TOTAL_CLASS_COUNT] = { "); for (int i = 0; i < classesCount; ++i) { struct class * classInstance = array_get( allClasses, i ); if( i != 0 ) { text_append( configurationSource, ", " ); } text_append( configurationSource, "\"" ); text_append( configurationSource, classInstance->className ); text_append( configurationSource, "\"" ); } text_append( configurationSource, " };\n\n" ); text_append( configurationSource, "int __ClassMethodCount[TOTAL_CLASS_COUNT] = { "); for (int i = 0; i < classesCount; ++i) { struct class * classInstance = array_get( allClasses, i ); if( i != 0 ) { text_append( configurationSource, ", " ); } text_append( configurationSource, text_fromNumber( array_length( classInstance->methods ) ) ); } text_append( configurationSource, " };\n\n" ); text_append( configurationSource, "int __ClassPropertyCount[TOTAL_CLASS_COUNT] = { "); for (int i = 0; i < classesCount; ++i) { struct class * classInstance = array_get( allClasses, i ); if( i != 0 ) { text_append( configurationSource, ", " ); } text_append( configurationSource, text_fromNumber( array_length( classInstance->properties ) ) ); } text_append( configurationSource, " };\n\n" ); text_append( configurationSource, "char * __ClassPropertyNames[TOTAL_CLASS_COUNT][30] = {\n"); for (int i = 0; i < classesCount; ++i) { struct class * classInstance = array_get( allClasses, i ); if( i != 0 ) { text_append( configurationSource, ", \n" ); } struct array * properties = classInstance->properties; int propertyCount = array_length( properties ); text_append( configurationSource, "\t\t\t\t\t\t\t\t\t\t\t\t\t\t{"); if( propertyCount == 0 ) { text_append( configurationSource, " " ); } for (int j = 0; j < propertyCount; ++j) { struct property * currentProperty = array_get( properties, j ); if( j != 0 ) { text_append( configurationSource, ", " ); } text_append( configurationSource, " \"" ); text_append( configurationSource, currentProperty->propertyName ); text_append( configurationSource, "\" " ); } text_append( configurationSource, "}"); } text_append( configurationSource, "\n\t\t\t\t\t\t\t\t\t\t\t\t\t};\n\n" ); text_append( configurationSource, "char * __ClassMethodNames[TOTAL_CLASS_COUNT][30] = {\n"); for (int i = 0; i < classesCount; ++i) { struct class * classInstance = array_get( allClasses, i ); if( i != 0 ) { text_append( configurationSource, ", \n" ); } struct array * methods = classInstance->methods; int methodCount = array_length( methods ); text_append( configurationSource, "\t\t\t\t\t\t\t\t\t\t\t\t\t\t{"); if( methodCount == 0 ) { text_append( configurationSource, " " ); } for (int j = 0; j < methodCount; ++j) { struct method * currentMethod = array_get( methods, j ); if( j != 0 ) { text_append( configurationSource, ", " ); } text_append( configurationSource, " \"" ); text_append( configurationSource, currentMethod->methodName ); text_append( configurationSource, "\" " ); } text_append( configurationSource, "}"); } text_append( configurationSource, "\n\t\t\t\t\t\t\t\t\t\t\t\t\t};\n\n" ); text_append( configurationSource, "int __ClassPropertyOffsets[TOTAL_CLASS_COUNT][30] = {\n"); int index = 0; for (int i = 0; i < classesCount; ++i) { struct class * classInstance = array_get( allClasses, i ); if( classInstance->usesTemplate ) { continue; } char * className = classInstance->className; if( index != 0 ) { text_append( configurationSource, ", \n" ); } index++; struct array * properties = classInstance->properties; int propertyCount = array_length( properties ); text_append( configurationSource, "\t\t\t\t\t\t\t\t\t\t\t\t\t\t{"); if( propertyCount == 0 ) { text_append( configurationSource, " " ); } for (int j = 0; j < propertyCount; ++j) { struct property * currentProperty = array_get( properties, j ); if( strcmp( currentProperty->type, "function" ) == 0 ) { continue; } if( j != 0 ) { text_append( configurationSource, ", " ); } text_append( configurationSource, " offsetof( "); text_append( configurationSource, className); text_append( configurationSource, ", " ); text_append( configurationSource, currentProperty->propertyName ); text_append( configurationSource, " )" ); text_append( configurationSource, " " ); } text_append( configurationSource, "}"); } text_append( configurationSource, "\n\t\t\t\t\t\t\t\t\t\t\t\t\t};\n\n" ); text_append( configurationSource, "int __ClassPropertyDatatypeIndices[TOTAL_CLASS_COUNT][30] = {\n"); for (int i = 0; i < classesCount; ++i) { struct class * classInstance = array_get( allClasses, i ); char * className = classInstance->className; if( i != 0 ) { text_append( configurationSource, ", \n" ); } struct array * properties = classInstance->properties; int propertyCount = array_length( properties ); text_append( configurationSource, "\t\t\t\t\t\t\t\t\t\t\t\t\t\t{"); if( propertyCount == 0 ) { text_append( configurationSource, " " ); } for (int j = 0; j < propertyCount; ++j) { struct property * currentProperty = array_get( properties, j ); if( j != 0 ) { text_append( configurationSource, ", " ); } //text_append( configurationSource, "\""); /* * char : -3 * char * : -2 * short : -4 * int : -5 * long : -6 */ if( strcmp( currentProperty->datatype, "char" ) == 0 ) { if( currentProperty->isPointer == 1 ) { text_append( configurationSource, text_fromNumber( -3 ) ); } else { text_append( configurationSource, text_fromNumber( -2 ) ); } } else if( strcmp( currentProperty->datatype, "short" ) == 0 ) { text_append( configurationSource, text_fromNumber( -4 ) ); } else if( strcmp( currentProperty->datatype, "int" ) == 0 ) { text_append( configurationSource, text_fromNumber( -5 ) ); } else if( strcmp( currentProperty->datatype, "long" ) == 0 ) { text_append( configurationSource, text_fromNumber( -6 ) ); } else { struct class * datatypeClass = application_getClassByClassName( allClasses, currentProperty->datatype ); if( datatypeClass != NULL ) { //printf("-------------------------- classIndex: %i\n" ,datatypeClass->classIndex); text_append( configurationSource, text_fromNumber( datatypeClass->classIndex ) ); } else { text_append( configurationSource, text_fromNumber( 1 ) ); } //text_append( configurationSource, currentProperty->datatype );//text_fromNumber( datatypeClass->classIndex ) ); } //text_append( configurationSource, "\"" ); //text_append( configurationSource, currentProperty->propertyName ); //text_append( configurationSource, " )" ); text_append( configurationSource, " " ); } text_append( configurationSource, "}"); } text_append( configurationSource, "\n\t\t\t\t\t\t\t\t\t\t\t\t\t};\n\n" ); text_append( configurationSource, "void getArrayByClassIndex( int size, void * * voidArray, int * structByteSize, int classIndex ) {\n\n" ); //text_append( configurationSource, " struct user * array;\n\n" ); text_append( configurationSource, " switch( classIndex ) {\n\n" ); for (int i = 0; i < classesCount; ++i) { struct class * classInstance = array_get( allClasses, i ); if( classInstance->usesTemplate ) { continue; } char * className = classInstance->className; if( strcmp( className, "char") == 0 ) { continue; } if( strcmp( className, "int") == 0 ) { continue; } int classIndex = classInstance->classIndex; text_append( configurationSource, " case " ); text_append( configurationSource, text_fromNumber( classIndex ) ); text_append( configurationSource, ":\n\n" ); text_append( configurationSource, " voidArray = ( void ** ) ( struct " ); text_append( configurationSource, className ); text_append( configurationSource, " * ) malloc( sizeof( struct " ); text_append( configurationSource, className ); text_append( configurationSource, " ) * size );\n\n" ); text_append( configurationSource, " *structByteSize = sizeof( struct " ); text_append( configurationSource, className ); text_append( configurationSource, " );\n\n" ); text_append( configurationSource, " break;\n\n" ); } text_append( configurationSource, " }\n\n" ); //text_append( configurationSource, " voidArray = ( void ** ) array;\n\n" ); text_append( configurationSource, "}\n\n" ); text_append( configurationSource, "void callMethodOfClass( int classIndex, int methodIndex, void * object ) {\n\n" ); //text_append( configurationSource, " struct user * array;\n\n" ); text_append( configurationSource, " switch( classIndex ) {\n\n" ); for (int i = 0; i < classesCount; ++i) { struct class * classInstance = array_get( allClasses, i ); if( classInstance->usesTemplate ) { continue; } char * className = classInstance->className; if( strcmp( className, "char") == 0 ) { continue; } if( strcmp( className, "int") == 0 ) { continue; } int classIndex = classInstance->classIndex; text_append( configurationSource, " case " ); text_append( configurationSource, text_fromNumber( classIndex ) ); text_append( configurationSource, ":\n\n" ); text_append( configurationSource, " switch( methodIndex ) {\n\n" ); array * methods = classInstance->methods; int methodsCount = array_length( methods ); if( methodsCount > 0 ) { for (int methodIndex = 0; methodIndex < methodsCount; ++methodIndex) { struct method * currentMethod = array_get( methods, methodIndex ); if( array_length( currentMethod->arguments ) == 1 ) { text_append( configurationSource, " case " ); text_append( configurationSource, text_fromNumber( methodIndex ) ); text_append( configurationSource, ":\n\n" ); text_append( configurationSource, " " ); text_append( configurationSource, className ); text_append( configurationSource, "_" ); text_append( configurationSource, currentMethod->methodName ); text_append( configurationSource, "( object );\n\n" ); text_append( configurationSource, " break;\n\n " ); } } } text_append( configurationSource, " }\n\n" ); text_append( configurationSource, " break;\n\n" ); } text_append( configurationSource, " }\n\n" ); //text_append( configurationSource, " voidArray = ( void ** ) array;\n\n" ); text_append( configurationSource, "}\n\n" ); /* int __ClassPropertyCount[4] = { 4, 6 }; */ //text_append( configurationHeader, "int"); for (int i = 0; i < fileCount; ++i) { struct file * fileInstance = array_get( files, i ); char * filename = fileInstance->filename; char * source = fileInstance->source; struct array * classesArray = fileInstance->classes; } char * header = fileSystem_readFile( "../source/configuration.h" ); text_append( configurationHeader, header ); text_append( configurationHeader, "#endif\n" ); char * filePath = file_composePath( applicationInstance->output, "classConfiguration", "h" ); fileSystem_writeFile( filePath, configurationHeader->value ); char * functions = fileSystem_readFile( "../source/configuration.c" ); filePath = file_composePath( applicationInstance->output, "classConfiguration", "c" ); text_append( configurationSource, functions ); fileSystem_writeFile( filePath, configurationSource->value ); } // end char * file_composePath( char * path, char * filename, char * extension ) { char * filePath = malloc(1000); filePath[0] = 0; strcat( filePath, path ); strcat( filePath, filename ); strcat( filePath, "." ); strcat( filePath, extension ); return filePath; } void file_composeNewPointerFunction( struct text * finalSourceCode, int hasConstructor, struct array * constructorArguments, struct class * classInstance ) { //char * contructorArgumentsText = text_join( constructorArguments, "," ); text_append( finalSourceCode, classInstance->className ); text_append( finalSourceCode, " * " ); text_append( finalSourceCode, classInstance->className ); text_append( finalSourceCode, "_newPointer(" ); //text_append( finalSourceCode, contructorArgumentsText ); int count = array_length( constructorArguments ); for (int i = 1; i < count; ++i) { char * argument = text_removeWhiteSpaces( array_get( constructorArguments, i ) ); if( i > 1 ) { text_append( finalSourceCode, ", " ); } text_append( finalSourceCode, argument ); } text_append( finalSourceCode, ") {\n\n" ); text_append( finalSourceCode, " struct " ); text_append( finalSourceCode, classInstance->className ); text_append( finalSourceCode, " * pointer = malloc( sizeof ( struct " ); text_append( finalSourceCode, classInstance->className ); text_append( finalSourceCode, " ) );\n\n" ); file_composePropertieInitiations( finalSourceCode, 1, classInstance ); if( hasConstructor == 1 ) { file_composeConstructorCall( finalSourceCode, classInstance->className, constructorArguments, -1 ); } text_append( finalSourceCode, " return pointer;\n\n" ); text_append( finalSourceCode, "}\n\n" ); } void file_composeConstructorCall( struct text * finalSourceCode, char * className, struct array * constructorArguments, int usePointer ) { text_append( finalSourceCode, " " ); text_append( finalSourceCode, className ); if( usePointer == 1 ) { text_append( finalSourceCode, "_constructor( &instance" ); } else { text_append( finalSourceCode, "_constructor( pointer " ); } int argumentCount = array_length( constructorArguments ); for (int j = 1; j < argumentCount; ++j) { char * argumentText = ( char * ) array_get( constructorArguments, j ); struct array * argumentParts = text_split( argumentText, " \t" ); text_append( finalSourceCode, ", " ); text_append( finalSourceCode, array_get( argumentParts, array_length( argumentParts ) - 1 ) ); } text_append( finalSourceCode, ");\n\n" ); } void file_composePropertieInitiations( struct text * finalSourceCode, int usePointers, struct class * classInstance ) { char * className = classInstance->className; struct array * properties = classInstance->properties; int classIndex = classInstance->classIndex; int propertyLength = array_length( properties ); if( classInstance->hasReflection == true ) { if( strcmp( className, "Hints" ) != 0 ) { if( usePointers == 1 ) { text_append( finalSourceCode, " pointer->__classIndex = " ); } else { text_append( finalSourceCode, " instance.__classIndex = " ); } text_append( finalSourceCode, text_fromNumber( classIndex ) ); text_append( finalSourceCode, ";\n\n" ); } } for (int i = 0; i < propertyLength; ++i) { struct property * currentProperty = array_get( properties, i ); if( currentProperty->hasValue == 1 ) { char * propertyName = currentProperty->propertyName; char * propertyValue = currentProperty->value; if( usePointers == 1 ) { text_append( finalSourceCode, " pointer->" ); } else { text_append( finalSourceCode, " instance." ); } text_append( finalSourceCode, propertyName ); text_append( finalSourceCode, " = " ); text_append( finalSourceCode, currentProperty->value ); text_append( finalSourceCode, ";\n\n" ); } } } void file_composeNewFunction( struct text * finalSourceCode, int hasConstructor, struct array * constructorArguments, struct class * classInstance ) { array * argumentsWithoutFirst = array_new(); int argumentCount = array_length( constructorArguments ); for (int i = 1; i < argumentCount; ++i) { char * constructorArgument = array_get( constructorArguments, i ); array_add( argumentsWithoutFirst, constructorArgument ); } char * contructorArgumentsText = text_join( argumentsWithoutFirst, ", " ); text_append( finalSourceCode, classInstance->className ); text_append( finalSourceCode, " " ); text_append( finalSourceCode, classInstance->className ); text_append( finalSourceCode, "_new(" ); int count = array_length( constructorArguments ); for (int i = 1; i < count; ++i) { char * argument = text_removeWhiteSpaces( array_get( constructorArguments, i ) ); if( i > 1 ) { text_append( finalSourceCode, ", " ); } text_append( finalSourceCode, argument ); } text_append( finalSourceCode, ") {\n\n" ); text_append( finalSourceCode, " " ); text_append( finalSourceCode, classInstance->className ); text_append( finalSourceCode, " instance;\n\n" ); file_composePropertieInitiations( finalSourceCode, -1, classInstance ); if( hasConstructor == 1 ) { file_composeConstructorCall( finalSourceCode, classInstance->className, constructorArguments, 1 ); } text_append( finalSourceCode, " return instance;\n\n" ); text_append( finalSourceCode, "}\n\n" ); } void file_composeNewFunctions( struct text * finalSourceCode, struct class * classInstance, int hasConstructor, struct array * constructorArguments ) { char * className = classInstance->className; struct array * properties = classInstance->properties; int classIndex = classInstance->classIndex; file_composeNewFunction( finalSourceCode, hasConstructor, constructorArguments, classInstance ); file_composeNewPointerFunction( finalSourceCode, hasConstructor, constructorArguments, classInstance ); } void file_composeNewHeaderDeclerations( struct text * classHeader, char * className, struct array * contructorArguments ) { text_append( classHeader, className ); text_append( classHeader, " " ); text_append( classHeader, className ); text_append( classHeader, "_new( " ); int count = array_length( contructorArguments ); for (int i = 1; i < count; ++i) { char * argument = text_removeWhiteSpaces( array_get( contructorArguments, i ) ); if( i > 1 ) { text_append( classHeader, ", " ); } text_append( classHeader, argument ); } //text_append( classHeader, ( contructorArgumentsText ) ); text_append( classHeader, " );\n\n" ); text_append( classHeader, className ); text_append( classHeader, " * " ); text_append( classHeader, className ); text_append( classHeader, "_newPointer( " ); for (int i = 1; i < count; ++i) { char * argument = text_removeWhiteSpaces( array_get( contructorArguments, i ) ); if( i > 1 ) { text_append( classHeader, ", " ); } text_append( classHeader, argument ); } //text_append( classHeader, text_copy( contructorArgumentsText ) ); text_append( classHeader, " );\n\n" ); } struct array * file_getConstructorArguments( struct class * classInstance, int * hasConstructor ) { struct array * constructorArguments = array_new(); int length = array_length( classInstance->methods ); for ( int j = 0; j < length; ++j ) { struct method * currentMethod = ( struct method * ) array_get( classInstance->methods, j ); char * methodName = currentMethod->methodName; if( strcmp( methodName, "constructor" ) == 0 ) { constructorArguments = currentMethod->arguments; *hasConstructor = 1; } } return constructorArguments; } void file_composeClass( struct class * classInstance, struct text * classHeader, struct text * finalSourceCode ) { char * className = classInstance->className; int hasConstructor = -1; int length = array_length( classInstance->methods ); struct array * constructorArguments = file_getConstructorArguments( classInstance, &hasConstructor ); //char * contructorArgumentsText = text_join( constructorArguments, "," ); //if( array_length( constructorArguments ) == 0 ) { //contructorArgumentsText = " "; //} if( strcmp( className, "char" ) == 0 || strcmp( className, "int" ) == 0 ) { return; } file_composeNewHeaderDeclerations( classHeader, className, constructorArguments ); file_composeNewFunctions( finalSourceCode, classInstance, hasConstructor, constructorArguments ); } void file_addLineBreaks( struct text * finalSourceCode, struct array * sourceArray ) { int count = array_length( sourceArray ); for ( int i = 0; i < count; ++i ) { struct codeBundle * code = array_get( sourceArray, i ); int currentLineBreaks = text_countLineBreaks( finalSourceCode->value, -1 ); int addingLinebreaks = code->lineNumber - currentLineBreaks; //printf("adding linebreaks: %i\n", addingLinebreaks); for (int j = 0; j < addingLinebreaks; ++j) { text_append( finalSourceCode, "\n" ); } text_append( finalSourceCode, code->sourceCode ); } text_append( finalSourceCode, "\n\n" ); } void file_composeSourceHeader( struct text * finalSourceCode, char * filename ) { text_append( finalSourceCode, "/* \n * This file is automaticaly generated, Please dont edit this file! \n */\n" ); text_append( finalSourceCode, "#include <" ); text_append( finalSourceCode, filename ); text_append( finalSourceCode, ".h> \n\n" ); } void file_writeAll( struct array * sourceArray, struct text * classHeader, char * filename, array * classesArray, array * globals, char * relativePath, struct application * applicationInstance ) { struct text * finalSourceCode = text_new( "" ); int globalCount = array_length( globals ); for (int i = 0; i < globalCount; ++i) { struct variable * variableInstance = array_get( globals, i ); struct array * sourceParts = text_split( text_copy( variableInstance->declaration ), " " ); struct text * declarationWithoutExtern = text_new( "" ); int sourcePartsLength = array_length( sourceParts ); for (int j = 0; j < sourcePartsLength; ++j) { char * sourceCodePart = text_removeWhiteSpaces( ( char * ) array_get( sourceParts, j ) ); if( strcmp( sourceCodePart, "extern" ) != 0 ) { text_append( declarationWithoutExtern, sourceCodePart ); text_append( declarationWithoutExtern, " " ); } } struct codeBundle * sourceCodeBundle = malloc( sizeof( struct codeBundle ) ); sourceCodeBundle->sourceCode = declarationWithoutExtern->value; sourceCodeBundle->lineNumber = variableInstance->lineNumber; array_add( sourceArray, sourceCodeBundle ); //struct text * declarationBeforeIS = text_new(); for (int j = 0; j < sourcePartsLength; ++j) { char * sourceCodePart = text_removeWhiteSpaces( ( char * ) array_get( sourceParts, j ) ); if( strcmp( sourceCodePart, "=" ) == 0 ) { text_append( classHeader, ";" ); break; } text_append( classHeader, sourceCodePart ); text_append( classHeader, " " ); } text_append( classHeader, "\n\n" ); } method_sortLineNumbers( sourceArray ); file_composeSourceHeader( finalSourceCode, filename ); file_addLineBreaks( finalSourceCode, sourceArray ); int classesCount = array_length( classesArray ); for (int i = 0; i < classesCount; ++i) { struct class * classInstance = array_get( classesArray, i ); if( i == 0 ) { if( classInstance->usesTemplate ) { continue; } } file_composeClass( classInstance, classHeader, finalSourceCode ); } text_append( classHeader, "#endif\n" ); for (int i = 0; i < classesCount; ++i) { struct class * classInstance = array_get( classesArray, i ); char * className = classInstance->className; if( strcmp( className, "char" ) != 0 && strcmp( className, "int" ) != 0 && strcmp( className, "void" ) != 0 ) { class_composeTypedefStruct( classInstance, classHeader ); } } //char * path = "../application/target/"; char * filePath = file_composePath( applicationInstance->output, text_copy( relativePath ), "c" ); //printf("relativePath: '%s'\n", text_copy( filePath )); fileSystem_ensureDirectory( text_copy( filePath ) ); fileSystem_writeFile( filePath, finalSourceCode->value ); printf(" writing source file: %s\n", filePath); char * headerFilePath = file_composePath( applicationInstance->output, text_copy( relativePath ), "h" ); printf(" writing header file: %s\n\n", headerFilePath); //classHeader->value[classHeader->length] = 0; fileSystem_writeFile( headerFilePath, text_copy( classHeader->value ) ); text_free( classHeader ); } void file_parseFunctions( struct file * fileInstance, array * files ) { struct array * functions = fileInstance->functions; int functionsCount = array_length( functions ); for (int i = 0; i < functionsCount; ++i) { struct functionLayout * functionInstance = array_get( functions, i ); printf(" %s() {\n\n", functionInstance->name); int includeCount = array_length( fileInstance->includes ); for ( int k = 0; k < includeCount; ++k ) { struct include * includeInstance = array_get( fileInstance->includes, k ); char * currentInclude = includeInstance->path; char * includeFileName = text_removeSlashFromStart( file_getFileNameFromInclude( currentInclude ) ); struct file * includedFile = file_getFileByFileName( files, includeFileName ); if( includedFile != NULL ) { //printf(" ?? %s.c \n\n", includedFile->filename); file_addVariablesFromFile( includedFile, functionInstance->variables ); } } int globalCount = array_length( fileInstance->globals ); for (int k = 0; k < globalCount; ++k) { struct variable * globalVariableInstance = array_get( fileInstance->globals, k ); array_add( functionInstance->variables, globalVariableInstance ); } functionInstance->body = method_parse( functionInstance->bodyOriginal, functionInstance->variables, fileInstance->functions ); printf(" }\n\n"); } } void file_parseMethods( struct file * fileInstance, array * files ) { struct array * fileClasses = fileInstance->classes; int classesCount = array_length( fileClasses ); for (int i = 0; i < classesCount; ++i) { struct class * classInstance = array_get( fileClasses, i ); printf(" class %s{\n\n", classInstance->className ); struct array * methods = classInstance->methods; int methodsCount = array_length( methods ); for (int j = 0; j < methodsCount; ++j) { struct method * methodInstance = array_get( methods, j ); printf(" %s() {\n\n", methodInstance->methodName); int includeCount = array_length( fileInstance->includes ); for ( int k = 0; k < includeCount; ++k ) { struct include * includeInstance = array_get( fileInstance->includes, k ); char * currentInclude = includeInstance->path; char * includeFileName = text_removeSlashFromStart( file_getFileNameFromInclude( currentInclude ) ); struct file * includedFile = file_getFileByFileName( files, includeFileName ); if( includedFile != NULL ) { //printf(" %s.c \n\n", includedFile->filename); file_addVariablesFromFile( includedFile, methodInstance->variables ); } } printf("\n\n"); file_addVariablesFromFile( fileInstance, methodInstance->variables ); //methodInstance->body = methodInstance->bodyOriginal; //if( !classInstance->usesTemplate ) { methodInstance->body = method_parse( methodInstance->bodyOriginal, methodInstance->variables, fileInstance->functions ); //} printf(" }\n\n"); } printf(" }\n\n" ); } } void file_addVariablesFromFile( struct file * fileInstance, struct array * variables ) { int globalCount = array_length( fileInstance->globals ); //printf("add variables from file %i\n\n\n", globalCount); for (int k = 0; k < globalCount; ++k) { struct variable * globalVariableInstance = array_get( fileInstance->globals, k ); //printf(" - Adding variable from file: '%s' \n", globalVariableInstance->variableName ); array_add( variables, globalVariableInstance ); } } char * file_getBaseNameFromFileName( char * filename ) { struct array * fileParts = text_split( filename, "." ); return array_get( fileParts, 0 ); } char * file_getPathFrom( char * filename ) { struct array * fileParts = text_split( filename, "." ); return array_get( fileParts, 0 ); } int libcFileCount = 293; char * libcFileNames[293] = {"stdlib","stdlib","math","time","time","math","assert","math","math","stdlib","stdlib","stdlib","stdlib","nwchar","stdlib","nl_types","nl_types","nl_types","math","stdio","time","math","math","time","time","time","time","time","time","stdlib","math","io","math","stdlib","math","math","stdio","stdio","stdio","stdio","stdio","stdio","stdio","stdio","nwchar","nwchar","stdio","math","math","stdio","stdio","stdio","stdio","stdio","stdio","stdio","stdlib","stdio","math","stdio","stdio","stdio","stdio","nwchar","nwchar","stdio","nwchar","math","stdio","stdio","stdlib","stdio","nwchar","wchar","time","time","time","time","math","ctype","ctype","ctype","ctype","ctype","ctype","ctype","ctype","ctype","ctype","ctype","ctype","wctype","wctype","wctype","wctype","wctype","wctype","wctype","wctype","wctype","wctype","wctype","wctype","wctype","wctype","math","math","math","stdlib","math","stdlib","locale","time","time","time","time","math","math","setjmp","stdlib","stdlib","wchar","wchar","wchar","wchar","stdlib","stdlib","string","string","string","string","string","time","time","math","math","math","math","math","langinfo","stdio","math","stdio","stdio","stdio","stdlib","stdio","nwchar","wchar","stdlib","math","math","math","math","math","math","math","math","math","signal","stdlib","stdlib","stdlib","regex","regex","regex","regex","stdio","stdio","stdio","stdio","stdio","setjmp","locale","stdio","signal","math","math","stdio","stdio","math","stdlib","stdio","strings","string","string","string","string","string","string","string","wchar","time","string","strings","string","string","string","string","time","string","string","string","stdlib","stdlib","stdlib","stdlib","stdlib","string","string","stdlib","stdlib","stdlib","string","wchar","wchar","stdlib","math","math","time","time","stdio","stdio","ctype","ctype","ctype","wctype","wctype","wctype","stdio","stdio","stdarg","stdarg","stdarg","stdarg","stdio stdarg","stdio stdarg ","nwchar","stdio stdarg ","stdio stdarg","stdio stdarg ","stdio stdarg","stdio","stdio stdarg ","nwchar","stdio wchar ","nwchar","stdio wchar ","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","locale","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","stdlib","wchar","wchar","nwchar","stdlib","wctype","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","wchar","math","math","math"}; int file_isLibCFileName( char * baseName ) { for (int i = 0; i < 293; ++i) { char * libcFileName = libcFileNames[i] ; char * libcBaseName = libcFileName; if( strcmp( baseName, libcBaseName ) == 0 ) { //printf("skip libc file: %s\n\n", libcBaseName); return 1.0; } } return 0; } int file_hasLoadedFileName( char * fileName, struct array * loadedFileNames ) { int loadedFileNamesCount = array_length( loadedFileNames ); for (int i = 0; i < loadedFileNamesCount; ++i) { char * currentLoadedFileName = array_get( loadedFileNames, i ); if ( strcmp( currentLoadedFileName, fileName ) == 0 ) { return 1; } } return 0; } char * file_getFileNameFromInclude( char * include ) { int openIndex = text_indexOff( include, "<", -1 ); int closeIndex = -1; if( openIndex > 0 ) { closeIndex = text_indexOff( include, ">", -1 ); } else { openIndex = text_indexOff( include, "\"", -1 ); closeIndex = text_indexOff( include, "\"", openIndex + 1 ); } char * fileName = text_slice( include, openIndex + 1, closeIndex - 1 ); struct array * fileNameParts = text_split( text_copy( fileName ), "." ); return array_get( fileNameParts, 0 ); } struct file * file_getFileByFileName( struct array * files, char * includeFileName ) { int fileCount = array_length( files ); for (int i = 0; i < fileCount; ++i) { struct file * fileInstance = array_get( files, i ); //printf("searching for file: %s \n\n", includeFileName); if( strcmp( fileInstance->filename, includeFileName ) == 0 ) { return fileInstance; } } return NULL; } char * file_extractInclude( struct file * fileInstance, char * source, lexer * currentLexer, int key, int i ) { int nextKey = lexer_getKey( currentLexer, i + 2 ); int keyAfterWord = text_extractIndexAfterWord( source, key + 8 ); char * includeFileName = text_slice( source, key, keyAfterWord + 2); struct include * includeInstance = include_new(); includeInstance->path = includeFileName; includeInstance->enabled = true; array_add( fileInstance->includes, includeInstance ); // printf("Add include: %s\n", includeInstance->path); int numberOfCharacters = ( keyAfterWord + 2 ) - key; struct text * includeReplacement = text_new( "" ); for ( int i = 0; i < numberOfCharacters + 1; ++i ) { text_append( includeReplacement, " " ); } return text_replaceAt( key, keyAfterWord + 3, source, includeReplacement->value ); } char * file_eraseDefine( char * source, int key, int lineBreakIndex ) { for (int i = key; i < lineBreakIndex; ++i) { source[i] = ( char ) 32; } return source; } char * file_extractDefine( struct file * fileInstance, char * source, int key, int i ) { int lineBreakIndex = text_findNextLineBreak( source, key ); char * macro = text_slice( source, key, lineBreakIndex ); int numberOfCharacters = ( lineBreakIndex + 2 ) - key; array_add( fileInstance->macros, macro ); source = file_eraseDefine( source, key, lineBreakIndex ); return source; } void file_extractMacros( struct file * fileInstance ) { char * source = fileInstance->source; fileInstance->includes = array_new(); fileInstance->globals = array_new(); fileInstance->macros = array_new(); lexer * currentLexer = lexer_new(); //printf("Source: %s\n", source); lexer_getTokens( currentLexer, source ); lexer_sortKeys( currentLexer ); int count = lexer_length( currentLexer ); int bodyCloseIndex = -1; int depth = 0; for (int i = count - 1; i >= 0; --i) { char * token = lexer_getToken( currentLexer, i ); int key = lexer_getKey( currentLexer, i ); //printf("Token: %s\n", token); if ( strcmp( token, "{" ) == 0 ) { depth++; } if ( strcmp( token, "}" ) == 0 ) { depth--; } if( depth == 0 ) { if ( strcmp( token, "#" ) == 0 ) { // #macroname int keyAfterMethod = text_extractIndexAfterWord( source, key ); char * macroName = text_removeWhiteSpaces( text_slice( source, (int) key +1 ,keyAfterMethod - 1) ); //printf( "%s: %i:", token, (int)key ); //printf("macro: %s \n", macroName); if ( strcmp( macroName, "include" ) == 0 ) { source = file_extractInclude( fileInstance, source, currentLexer, key, i ); } if ( strcmp( macroName, "define" ) == 0 ) { source = file_extractDefine( fileInstance, source, key, i ); } } } } fileInstance->source = source; } char * file_getSource( char * filename ) { char sourceFilePath[200] = ""; strcat( sourceFilePath, "../application/source/" ); strcat( sourceFilePath, filename); strcat( sourceFilePath, ".c" ); char * source = fileSystem_readFile( sourceFilePath ); return source; } char * file_removeExtensionFromFileName( char * path ) { /* struct array * fileParts = text_split( text_copy( path ), "." ); int count = array_length( fileParts ); if( count > 1 ) { array_delete( fileParts, count-1 ); } */ char * pathWithoutExtension = ""; char * base = basename( text_copy( path ) ); char * dir = dirname( text_copy( path ) ); pathWithoutExtension = text_concatenate( pathWithoutExtension, dir ); pathWithoutExtension = text_concatenate( pathWithoutExtension, "/" ); pathWithoutExtension = text_concatenate( pathWithoutExtension, base ); if( pathWithoutExtension[0] == '.' && pathWithoutExtension[1] == '/' ) { // shift pointer pathWithoutExtension += 2; } int count = strlen( pathWithoutExtension ); for (int i = 0; i < count; ++i) { if( pathWithoutExtension[count - i ] == 46 ) { pathWithoutExtension[ count - i ] = 0; break; } if( pathWithoutExtension[count - i ] == 47 ) { break; } } return pathWithoutExtension; } char * file_getFileNameFromIncludeFixed( char * include ) { int openIndex = text_indexOff( include, "<", -1 ); int closeIndex = -1; if( openIndex > 0 ) { closeIndex = text_indexOff( include, ">", -1 ); } else { openIndex = text_indexOff( include, "\"", -1 ); closeIndex = text_indexOff( include, "\"", openIndex + 1 ); } char * fileName = text_slice( include, openIndex + 1, closeIndex - 1 ); return fileName; } char * resolve( char * path ) { struct array * pathParts = text_split( path, "/" ); int partsCount = array_length( pathParts ); array * validParts = array_new(); for (int i = 0; i < partsCount; ++i) { char * currentPart = array_get( pathParts, i ); if( strcmp( currentPart, ".." ) == NULL ) { array_pop( validParts ); continue; } if( strcmp( currentPart, "." ) == NULL ) { continue; } array_add( validParts, currentPart ); //printf("currentPart: %s\n", currentPart); } char * joinedText = text_join( validParts, "/" ); int lastCharacterIndex = strlen( path ) - 1; text * finalPath = text_new(""); if( path[ 0 ] == 47 ) { text_append( finalPath, "/" ); } text_append( finalPath, joinedText ); if( path[ lastCharacterIndex ] == 47 ) { text_append( finalPath, "/" ); } return finalPath->value; } void file_loadUnloadedFiles( struct array * unloadedFileNames, struct array * loadedFileNames, char * path ) { char * parentPath = dirname( text_copy( path ) ); struct file * fileInstance = malloc( sizeof( struct file ) ); fileInstance->path = file_removeExtensionFromFileName( path ); fileInstance->source = file_getSource(fileInstance->path ); printf(":: %s\n", fileInstance->path ); if( array_length( loadedFileNames ) == 0 ) { array_add( loadedFileNames, fileInstance->path ); } file_extractMacros( fileInstance ); int includeCount = array_length( fileInstance->includes ); //printf("include count: %i\n", includeCount); for ( int k = 0; k < includeCount; ++k ) { struct include * includeInstance = array_get( fileInstance->includes, k ); char * currentInclude = includeInstance->path; char * includeFileName = file_getFileNameFromIncludeFixed( currentInclude ); char * includeFileBaseName = file_removeExtensionFromFileName( includeFileName ); if( file_isLibCFileName( includeFileBaseName ) ) { continue; } int charCount = strlen( includeFileBaseName ); //printf("includeFileBaseName: %s\n", includeFileBaseName); struct text * pathFromApplication = text_new( "" ); text_append( pathFromApplication, parentPath ); text_append( pathFromApplication, "/" ); text_append( pathFromApplication, includeFileBaseName ); struct text * relativeFilePath = text_new( "../application/source/" ); text_append( relativeFilePath, resolve( pathFromApplication->value ) ); text_append( relativeFilePath, ".c" ); char * absolutePath = realpath( relativeFilePath->value, NULL ); //printf("relativeFromWorkingDirectory: %s %s\n", absolutePath, relativeFilePath->value); if( absolutePath == NULL ) { continue; } char * relativeFromWorkingDirectory = resolve( pathFromApplication->value ); if( file_hasLoadedFileName( relativeFromWorkingDirectory, loadedFileNames ) == 1 ) { continue; } if( fileSystem_exists( relativeFilePath->value ) ) { array_add( loadedFileNames, relativeFromWorkingDirectory ); file_loadUnloadedFiles( unloadedFileNames, loadedFileNames, resolve( pathFromApplication->value ) ); //printf("file exists\n\n"); } /* struct text * testText = text_new( "../application/source/" ); char * relativePath = dirname( text_copy( includeFileBaseName ) ); text_append( testText, ".c" ); char * absolutePath = realpath( "../application/source/", NULL ); struct text * test2 = text_new( "../application/source/" ); text_append( test2, parentPath ); text_append( test2, "/" ); //text_append( test2, relativePath ); char * realTest = realpath( test2->value, NULL ); printf(" --- '%s' '%s' \n", text_copy( includeFileBaseName ),realTest); if( fileSystem_exists( realTest ) ) { struct text * currentFullFileName = text_new( realTest ); text_append( currentFullFileName, "/" ); text_append( currentFullFileName, includeFileBaseName ); text_append( currentFullFileName, ".c" ); char * goodAbsoluteFilePath = realpath( currentFullFileName->value, NULL ); printf(" currentFullFileName: %s \n", goodAbsoluteFilePath ); file_loadUnloadedFiles( unloadedFileNames, loadedFileNames, goodAbsoluteFilePath ); } else { printf("\nthis file does not exists %s\n\n", testText->value); } */ } }