From bb4775241d149dec9775b9c6243a8d961e7366d3 Mon Sep 17 00:00:00 2001 From: Rejean Loyer Date: Fri, 4 Dec 2015 21:07:02 -0500 Subject: [PATCH 1/1] documentor: new econ-based documentation format. add ear-to-econ-ecdoc tool to migrate existing documentation. --- documentor/src/Documentor.ec | 962 +++++++++++++++++++++++++++------ documentor/tools/ear-to-econ-ecdoc.ec | 733 +++++++++++++++++++++++++ documentor/tools/ear-to-econ-ecdoc.epj | 45 ++ 3 files changed, 1579 insertions(+), 161 deletions(-) create mode 100644 documentor/tools/ear-to-econ-ecdoc.ec create mode 100644 documentor/tools/ear-to-econ-ecdoc.epj diff --git a/documentor/src/Documentor.ec b/documentor/src/Documentor.ec index 3d1a72c..f9dd351 100644 --- a/documentor/src/Documentor.ec +++ b/documentor/src/Documentor.ec @@ -1,4 +1,5 @@ import "ecere" +#if !defined(EAR_TO_ECON_ECDOC) import "ec" import "HTMLView" import "IDESettings" @@ -471,6 +472,7 @@ public: enum DocumentationType { + unset, nameSpaceDoc, classDoc, functionDoc, @@ -479,6 +481,7 @@ enum DocumentationType enum DocumentationItem { + unset, description, usage, remarks, @@ -495,14 +498,60 @@ enum DocumentationItem static void FigureFileName(char * fileName, Module module, DocumentationType type, void * object, DocumentationItem item, void * data) { + char hex[20]; + fileName[0] = 0; + sprintf(hex, "%p", module); + strcat(fileName, hex); + strcat(fileName, "/"); + sprintf(hex, "%p", object); + strcat(fileName, hex); + strcat(fileName, "/"); + sprintf(hex, "%p", data); + strcat(fileName, hex); + strcat(fileName, "/"); + if(type == nameSpaceDoc) + strcat(fileName, "namespace"); + else if(type == functionDoc) + strcat(fileName, "function"); + else if(type == classDoc) + strcat(fileName, "class"); + else if(type == methodDoc) + strcat(fileName, "method"); + strcat(fileName, "/"); + if(item == description) + strcat(fileName, "description"); + else if(item == usage) + strcat(fileName, "usage"); + else if(item == remarks) + strcat(fileName, "remarks"); + else if(item == example) + strcat(fileName, "example"); + else if(item == seeAlso) + strcat(fileName, "seeAlso"); + else if(item == enumerationValue) + strcat(fileName, "enumerationValue"); + else if(item == definition) + strcat(fileName, "definition"); + else if(item == conversion) + strcat(fileName, "conversion"); + else if(item == memberDescription) + strcat(fileName, "memberDescription"); + else if(item == propertyDescription) + strcat(fileName, "propertyDescription"); + else if(item == parameter) + strcat(fileName, "parameter"); + else if(item == returnValue) + strcat(fileName, "returnValue"); +} + +static void FigureFilePath(char * path, Module module, DocumentationType type, void * object, DocumentationItem item, void * data) +{ + char docPath[MAX_LOCATION]; NameSpace * nameSpace, * ns; Class cl = null; Method method = null; GlobalFunction function = null; char nsName[1024], temp[1024]; - char docFile[1024]; - - switch(type) { case nameSpaceDoc: nameSpace = object; break; @@ -512,126 +561,262 @@ static void FigureFileName(char * fileName, Module module, DocumentationType typ } nsName[0] = 0; + temp[0] = 0; ns = nameSpace; while(ns && ns->name) { - strcpy(temp, "namespaces/"); - strcat(temp, ns->name); + strcpy(temp, ns->name); strcat(temp, "/"); strcat(temp, nsName); strcpy(nsName, temp); ns = ns->parent; } - sprintf(docFile, "%s.eCdoc", (!module || !module.name || !strcmp(nsName, "namespaces/ecere/namespaces/com")) ? "ecereCOM" : module.name); - if(strchr(docFile, DIR_SEP)) - { - GetLastDirectory(docFile, temp); - strcpy(docFile, temp); - } - - sprintf(fileName, "<%s/%s>", settings.docDir, docFile); // Note that in the ecereIDE.ini file, there can be no quotes around the path, and there needs to be the final backslash. Otherwise this does not work. - strcat(fileName, nsName); + docPath[0] = 0; + PathCatSlash(docPath, (!module || !module.name || !strcmp(nsName, "namespaces/ecere/namespaces/com")) ? "ecereCOM" : module.name); + //ChangeExtension(docPath, "eCdoc", docPath); + PathCatSlash(docPath, nsName); if(cl) { - strcat(fileName, "classes/"); - strcat(fileName, cl.name); - strcat(fileName, "/"); - } - - if(method) - { - strcat(fileName, "methods/"); - strcat(fileName, method.name); - strcat(fileName, "/"); - } - else if(function) - { - const char * name = RSearchString(function.name, "::", strlen(function.name), true, false); - if(name) name += 2; else name = function.name; - strcat(fileName, "functions/"); - strcat(fileName, name); - strcat(fileName, "/"); - } - - switch(item) - { - case description: strcat(fileName, "description"); break; - case usage: strcat(fileName, "usage"); break; - case remarks: strcat(fileName, "remarks"); break; - case example: strcat(fileName, "example"); break; - case seeAlso: strcat(fileName, "seeAlso"); break; - case returnValue: strcat(fileName, "returnValue"); break; - case enumerationValue: - strcat(fileName, "enumeration values/"); - strcat(fileName, ((NamedLink)data).name); - break; - case definition: - strcat(fileName, "definitions/"); - strcat(fileName, ((Definition)data).name); - break; - case conversion: - { - const char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false); - if(name) name += 2; else name = ((Property)data).name; - strcat(fileName, "conversions/"); - strcat(fileName, name); - break; - } - case memberDescription: - strcat(fileName, "data members/"); - strcat(fileName, ((DataMember)data).name); - break; - case propertyDescription: - strcat(fileName, "properties/"); - strcat(fileName, ((Property)data).name); - break; - case parameter: - { - int count; - char name[1024]; - Type prev; - strcat(fileName, "parameters/"); - for(prev = data, count = 0; prev; prev = prev.prev, count++); - sprintf(name, "%s.%d", ((Type)data).name, count); - strcat(fileName, name); - break; - } + char * name = getDocFileNameFromTypeName(cl.name); + PathCatSlash(docPath, name); + delete name; } + else + PathCatSlash(docPath, "_global-defs"); + ChangeExtension(docPath, "econ", docPath); + + path[0] = 0; + strcpy(path, settings.docDir); + PathCatSlash(path, docPath); } static char * ReadDoc(Module module, DocumentationType type, void * object, DocumentationItem item, void * data) { - char fileName[MAX_LOCATION]; String contents = null; - File file; + bool docRetrieved = false; + NamespaceDoc nsDoc = null; + ClassDoc clDoc = null; + FunctionDoc fnDoc = null; + MethodDoc mdDoc = null; + String s = null; + char filePath[MAX_LOCATION]; + Method method = null; + GlobalFunction function = null; - FigureFileName(fileName, module, type, object, item, data); - file = FileOpen(fileName, read); - if(file) + ItemDoc doc = getDoc(filePath, module, type, object, item, data, false); + + switch(type) { - uint len; - if((len = file.GetSize())) + case functionDoc: function = object; break; + case methodDoc: method = object; break; + } + + if(doc) + { + if(eClass_IsDerived(doc._class, class(ClassDoc))) { - contents = new char[len+1]; - file.Read(contents, 1, len); - contents[len] = '\0'; + clDoc = (ClassDoc)doc; + docRetrieved = true; + } + else if(eClass_IsDerived(doc._class, class(NamespaceDoc))) + { + nsDoc = (NamespaceDoc)doc; + docRetrieved = true; } - delete file; } - if(contents) + + if(docRetrieved) { - int c; - for(c = 0; contents[c]; c++) - if(!isspace(contents[c])) break; - if(!contents[c]) - delete contents; + ItemDoc itDoc = null; + if(type == functionDoc) + { + MapIterator it { map = nsDoc.functions }; + const char * name = RSearchString(function.name, "::", strlen(function.name), true, false); + if(name) name += 2; else name = function.name; + if(it.Index(name, false)) + fnDoc = it.data; + } + else if(type == methodDoc) + { + MapIterator it { map = clDoc.methods }; + if(it.Index(method.name, false)) + mdDoc = it.data; + } + + switch(item) + { + case description: s = type == methodDoc ? mdDoc.description : type == functionDoc ? fnDoc.description : type == classDoc ? clDoc.description : nsDoc.description; break; + case usage: s = type == methodDoc ? mdDoc.usage : type == functionDoc ? fnDoc.usage : type == classDoc ? clDoc.usage : null; break; + case remarks: s = type == methodDoc ? mdDoc.remarks : type == functionDoc ? fnDoc.remarks : type == classDoc ? clDoc.remarks : null; break; + case example: s = type == methodDoc ? mdDoc.example : type == functionDoc ? fnDoc.example : type == classDoc ? clDoc.example : null; break; + case seeAlso: s = type == methodDoc ? mdDoc.also : type == functionDoc ? fnDoc.also : type == classDoc ? clDoc.also : null; break; + case returnValue: s = type == methodDoc ? mdDoc.returnValue : type == functionDoc ? fnDoc.returnValue : null; break; + case enumerationValue: + if(clDoc && clDoc.values) + { + itDoc = clDoc.values[((NamedLink)data).name]; + if(itDoc) s = itDoc.description; + } + break; + case definition: + if(nsDoc && nsDoc.defines) + { + itDoc = nsDoc.defines[((Definition)data).name]; + if(itDoc) s = itDoc.description; + } + break; + case conversion: + if(clDoc && clDoc.conversions) + { + const char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false); + if(name) name += 2; else name = ((Property)data).name; + itDoc = clDoc.conversions[name]; + if(itDoc) s = itDoc.description; + } + break; + case memberDescription: + if(clDoc && clDoc.fields) + { + itDoc = clDoc.fields[((DataMember)data).name]; + if(itDoc) s = itDoc.description; + } + break; + case propertyDescription: + if(clDoc && clDoc.properties) + { + itDoc = clDoc.properties[((Property)data).name]; + if(itDoc) s = itDoc.description; + } + break; + case parameter: + if((type == functionDoc && fnDoc && fnDoc.parameters) || (type == methodDoc && mdDoc && mdDoc.parameters)) + { + Type prev; + char * name; + for(prev = data; prev; prev = prev.prev); + name = ((Type)data).name; + if(type == functionDoc) + { + itDoc = fnDoc.parameters[name]; + if(itDoc) s = itDoc.description; + } + else if(type == methodDoc) + { + itDoc = mdDoc.parameters[name]; + if(itDoc) s = itDoc.description; + } + } + break; + } + if(s) + contents = CopyString(s); } if(editing && !contents && !readOnly) contents = CopyString($"[Add Text]"); return contents; } +ItemDoc getDoc(char * filePath, Module module, DocumentationType type, void * object, DocumentationItem item, void * data, bool create) +{ + ItemDoc doc = null; + bool docRetrieved = false; + File f; + NamespaceDoc nsDoc = null; + ClassDoc clDoc = null; + + char docPath[MAX_LOCATION]; + Class cl = null; + Method method = null; + + switch(type) + { + case classDoc: cl = (Class)object; break; + case methodDoc: method = object; cl = method._class; break; + } + + FigureFilePath(filePath, module, type, object, item, data); + + if(docCache[filePath]) + { + DocCacheEntry entry = docCache[docPath]; + if(cl && eClass_IsDerived(entry.doc._class, class(ClassDoc))) + { + clDoc = (ClassDoc)entry.doc; + docRetrieved = true; + } + else if(!cl && eClass_IsDerived(entry.doc._class, class(NamespaceDoc))) + { + nsDoc = (NamespaceDoc)entry.doc; + docRetrieved = true; + } + } + + if(!docRetrieved) + { + f = FileOpen(filePath, read); + if(f) + { + JSONParser parser { f = f, eCON = true }; + JSONResult jsonResult; + jsonResult = parser.GetObject(cl ? class(ClassDoc) : class(NamespaceDoc), cl ? &clDoc : &nsDoc); + delete parser; + delete f; + + if(jsonResult == success) + { + docRetrieved = true; + docCache[docPath] = { added = GetTime(), doc = cl ? clDoc : nsDoc }; + } + else + { + PrintLn("error: problem parsing file: ", filePath); + delete clDoc; + delete nsDoc; + } + } + } + + if(!docRetrieved) + { + if(cl) + clDoc = { }; + else + nsDoc = { }; + doc = cl ? clDoc : nsDoc; + docCache[docPath] = { added = GetTime(), doc = cl ? clDoc : nsDoc }; + docRetrieved = true; + } + else + { + doc = cl ? clDoc : nsDoc; + } + + //void pruneDocCache() + { + MapIterator it { map = docCache }; + Array toRemove { }; + Time now = GetTime(); + for(entry : docCache) + { + Time diff = now - entry.added; + if(diff > 60*0.5) + toRemove.Add(&entry); + } + while(toRemove.count) + { + if(it.Index(toRemove.lastIterator.data, false)) + { + delete it.data; + it.Remove(); + } + toRemove.Remove(toRemove.lastIterator.pointer); + } + delete toRemove; + } + return doc; +} + class APIPageNameSpace : APIPage { NameSpace * nameSpace; @@ -2486,31 +2671,27 @@ class HelpView : HTMLView { // Writability test { - char docFile[MAX_LOCATION]; - Archive archive; - Module module = page ? page.GetModule() : null; - NameSpace * ns = page ? page.GetNameSpace() : null; - - sprintf(docFile, "%s/%s.eCdoc", settings.docDir, (!module || !module.name || (ns && ns->name && !strcmp(ns->name, "namespaces/ecere/namespaces/com"))) ? "ecereCOM" : module.name); - if(FileExists(docFile)) - { - archive = ArchiveOpen(docFile, { true } ); - readOnly = archive == null; - delete archive; - } - else + char docDir[MAX_LOCATION]; + readOnly = true; + strcpy(docDir, settings.docDir); + if(FileExists(docDir).isDirectory) { - readOnly = true; - archive = ArchiveOpen(docFile, { true } ); - if(archive) + PathCatSlash(docDir, "___docWriteTest"); + if(FileExists(docDir).isDirectory) + { + RemoveDir(docDir); + if(!FileExists(docDir)) + readOnly = false; + } + else { - // Must create root directory on archive creation - ArchiveDir dir = archive.OpenDirectory("", null, replace); - if(dir) + MakeDir(docDir); + if(FileExists(docDir).isDirectory) + { readOnly = false; - delete dir; + RemoveDir(docDir); + } } - delete archive; } } @@ -2531,72 +2712,338 @@ class HelpView : HTMLView void SaveEdit() { - char archiveFile[MAX_LOCATION]; - char fileName[MAX_FILENAME]; - char directory[MAX_LOCATION]; - const char * location; - Archive archive = null; - if(SplitArchivePath(editString, archiveFile, &location)) + Block block; + bool empty = true; + String contents = null; + uint len; + TempFile f { }; + for(block = textBlock.parent.subBlocks.first; block; block = block.next) { - GetLastDirectory(location, fileName); - StripLastDirectory(location, directory); - archive = ArchiveOpen(archiveFile, { true } ); + if(block.type == TEXT && block.textLen) + { + empty = false; + break; + } } + if(!empty) { - TempFile f { }; - Block block; - bool empty = true; for(block = textBlock.parent.subBlocks.first; block; block = block.next) { - if(block.type == TEXT && block.textLen) - { - empty = false; - break; - } + if(block.type == BR) + f.Puts("
"); + else if(block.type == TEXT) + f.Write(block.text, 1, block.textLen); } - if(!empty) + } + f.Seek(0, start); + if((len = f.GetSize())) + { + contents = new char[len+1]; + f.Read(contents, 1, len); + contents[len] = '\0'; + } + if(!empty && contents) + { + char temp[MAX_LOCATION]; + char part[MAX_FILENAME]; + Module module; + void * object; + void * data; + DocumentationType type; + DocumentationItem item; + ItemDoc doc; + bool docRetrieved = false; + NamespaceDoc nsDoc = null; + ClassDoc clDoc = null; + FunctionDoc fnDoc = null; + MethodDoc mdDoc = null; + //char filePath[MAX_LOCATION]; + Class cl = null; + Method method = null; + GlobalFunction function = null; + + strcpy(temp, editString); + SplitDirectory(temp, part, temp); + module = (Module)strtoull(part, null, 16); + SplitDirectory(temp, part, temp); + object = (void *)strtoull(part, null, 16); + SplitDirectory(temp, part, temp); + data = (void *)strtoull(part, null, 16); + SplitDirectory(temp, part, temp); + if(!strcmp(part, "namespace")) + type = nameSpaceDoc; + else if(!strcmp(part, "function")) + type = functionDoc; + else if(!strcmp(part, "class")) + type = classDoc; + else if(!strcmp(part, "method")) + type = methodDoc; + SplitDirectory(temp, part, temp); + if(!strcmp(part, "description")) + item = description; + else if(!strcmp(part, "usage")) + item = usage; + else if(!strcmp(part, "remarks")) + item = remarks; + else if(!strcmp(part, "example")) + item = example; + else if(!strcmp(part, "seeAlso")) + item = seeAlso; + else if(!strcmp(part, "enumerationValue")) + item = enumerationValue; + else if(!strcmp(part, "definition")) + item = definition; + else if(!strcmp(part, "conversion")) + item = conversion; + else if(!strcmp(part, "memberDescription")) + item = memberDescription; + else if(!strcmp(part, "propertyDescription")) + item = propertyDescription; + else if(!strcmp(part, "parameter")) + item = parameter; + else if(!strcmp(part, "returnValue")) + item = returnValue; + + doc = getDoc(temp, module, type, object, item, data, true); + { - for(block = textBlock.parent.subBlocks.first; block; block = block.next) + MapIterator it { map = docCache }; + if(it.Index(temp, false)) { - if(block.type == BR) - f.Puts("
"); - else if(block.type == TEXT) - f.Write(block.text, 1, block.textLen); + it.data.doc = null; + delete it.data; + it.Remove(); } } - f.Seek(0, start); - if(!empty || archive.FileExists(location)) + switch(type) { - ArchiveDir dir = archive ? archive.OpenDirectory(directory, null, replace) : null; - if(dir) - dir.AddFromFile(fileName, f, null, replace, 0, null, null); - delete dir; + case classDoc: cl = (Class)object; break; + case functionDoc: function = object; break; + case methodDoc: method = object; cl = method._class; break; } - delete archive; - delete f; - if(empty) + + if(eClass_IsDerived(doc._class, class(ClassDoc))) + { + clDoc = (ClassDoc)doc; + docRetrieved = true; + } + else if(eClass_IsDerived(doc._class, class(NamespaceDoc))) { - Block parent = textBlock.parent; - while((block = parent.subBlocks.first)) + nsDoc = (NamespaceDoc)doc; + docRetrieved = true; + } + + if(docRetrieved) + { + if(type == functionDoc) + { + const char * name = RSearchString(function.name, "::", strlen(function.name), true, false); + if(name) name += 2; else name = function.name; + if(!nsDoc.functions) nsDoc.functions = { }; + fnDoc = nsDoc.functions[name]; + if(!fnDoc) + { + fnDoc = { }; + nsDoc.functions[name] = fnDoc; + } + } + else if(type == methodDoc) { - parent.subBlocks.Remove(block); - delete block; + if(!clDoc.methods) clDoc.methods = { }; + mdDoc = clDoc.methods[method.name]; + if(!mdDoc) + { + mdDoc = { }; + clDoc.methods[method.name] = mdDoc; + } + } + + switch(item) + { + case description: + if(type == methodDoc) { mdDoc.description = contents; contents = null; } + else if(type == functionDoc) { fnDoc.description = contents; contents = null; } + else if(type == classDoc) { clDoc.description = contents; contents = null; } + else { nsDoc.description = contents; contents = null; } + break; + case usage: + if(type == methodDoc) { mdDoc.usage = contents; contents = null; } + else if(type == functionDoc) { fnDoc.usage = contents; contents = null; } + else if(type == classDoc) { clDoc.usage = contents; contents = null; } + break; + case remarks: + if(type == methodDoc) { mdDoc.remarks = contents; contents = null; } + else if(type == functionDoc) { fnDoc.remarks = contents; contents = null; } + else if(type == classDoc) { clDoc.remarks = contents; contents = null; } + break; + case example: + if(type == methodDoc) { mdDoc.example = contents; contents = null; } + else if(type == functionDoc) { fnDoc.example = contents; contents = null; } + else if(type == classDoc) { clDoc.example = contents; contents = null; } + break; + case seeAlso: + if(type == methodDoc) { mdDoc.also = contents; contents = null; } + else if(type == functionDoc) { fnDoc.also = contents; contents = null; } + else if(type == classDoc) { clDoc.also = contents; contents = null; } + break; + case returnValue: + if(type == methodDoc) { mdDoc.returnValue = contents; contents = null; } + else if(type == functionDoc) { fnDoc.returnValue = contents; contents = null; } + break; + case enumerationValue: + { + ValueDoc itDoc; + if(!clDoc.values) clDoc.values = { }; + itDoc = clDoc.values[((NamedLink)data).name]; + if(!itDoc) + { + itDoc = { }; + clDoc.values[((NamedLink)data).name] = itDoc; + } + itDoc.description = contents; contents = null; + break; + } + case definition: + { + DefineDoc itDoc; + if(!nsDoc.defines) nsDoc.defines = { }; + itDoc = nsDoc.defines[((Definition)data).name]; + if(!itDoc) + { + itDoc = { }; + nsDoc.defines[((Definition)data).name] = itDoc; + } + itDoc.description = contents; contents = null; + break; + } + case conversion: + { + ConversionDoc itDoc; + const char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false); + if(name) name += 2; else name = ((Property)data).name; + if(!clDoc.conversions) clDoc.conversions = { }; + itDoc = clDoc.conversions[name]; + if(!itDoc) + { + itDoc = { }; + clDoc.conversions[name] = itDoc; + } + itDoc.description = contents; contents = null; + break; + } + case memberDescription: + { + FieldDoc itDoc; + if(!clDoc.fields) clDoc.fields = { }; + itDoc = clDoc.fields[((DataMember)data).name]; + if(!itDoc) + { + itDoc = { }; + clDoc.fields[((DataMember)data).name] = itDoc; + } + itDoc.description = contents; contents = null; + break; + } + case propertyDescription: + { + PropertyDoc itDoc; + if(!clDoc.properties) clDoc.properties = { }; + itDoc = clDoc.properties[((Property)data).name]; + if(!itDoc) + { + itDoc = { }; + clDoc.properties[((Property)data).name] = itDoc; + } + itDoc.description = contents; contents = null; + break; + } + case parameter: + { + ParameterDoc itDoc; + char * name; + Type prev; + for(prev = data; prev; prev = prev.prev); + name = ((Type)data).name; + if(type == functionDoc) + { + if(!fnDoc.parameters) fnDoc.parameters = { }; + itDoc = fnDoc.parameters[name]; + if(!itDoc) + { + itDoc = { }; + fnDoc.parameters[name] = itDoc; + } + itDoc.description = contents; contents = null; + } + else if(type == methodDoc) + { + if(!mdDoc.parameters) mdDoc.parameters = { }; + itDoc = mdDoc.parameters[name]; + if(!itDoc) + { + itDoc = { }; + mdDoc.parameters[name] = itDoc; + } + itDoc.description = contents; contents = null; + } + break; + } } - textBlock = Block { type = TEXT, parent = parent, font = parent.font }; - textBlock.text = CopyString($"[Add Text]"); - textBlock.textLen = strlen(textBlock.text); - parent.subBlocks.Add(textBlock); } - edit = false; - if(created) { - ComputeMinSizes(); - ComputeSizes(); - PositionCaret(true); - Update(null); + File f; + char filePath[MAX_LOCATION]; + char dirPath[MAX_LOCATION]; + strcpy(filePath, temp); + StripLastDirectory(filePath, dirPath); + if(FileExists(filePath)) + DeleteFile(filePath); + if(cl ? !clDoc.isEmpty : !nsDoc.isEmpty) + { + if(!FileExists(dirPath)) + MakeDir(dirPath); + f = FileOpen(filePath, write); + if(f) + { + if(cl) + WriteJSONObject(f, class(ClassDoc), clDoc, 0, true); + else + WriteJSONObject(f, class(NamespaceDoc), nsDoc, 0, true); + delete f; + } + else + { + PrintLn("error: writeClassDocFile -- problem opening file: ", filePath); + } + } + } + delete doc; + delete contents; + } + + if(empty) + { + Block parent = textBlock.parent; + while((block = parent.subBlocks.first)) + { + parent.subBlocks.Remove(block); + delete block; } + textBlock = Block { type = TEXT, parent = parent, font = parent.font }; + textBlock.text = CopyString($"[Add Text]"); + textBlock.textLen = strlen(textBlock.text); + parent.subBlocks.Add(textBlock); + } + + edit = false; + if(created) + { + ComputeMinSizes(); + ComputeSizes(); + PositionCaret(true); + Update(null); } } @@ -3990,3 +4437,196 @@ Thread commandThread return 0; } }; +#endif // !defined(EAR_TO_ECON_ECDOC) + +class ItemDoc +{ +public: + property String name { get { return this ? name : null; } set { delete name; name = CopyString(value); } isset { return name && *name; } } + property String description { get { return this ? description : null; } set { delete description; description = CopyString(value); } isset { return description && *description; } } +private: + char * name; + char * description; + property bool isEmpty + { + get + { + return !( + (name && *name) || + (description && *description)); + } + } + ~ItemDoc() + { + delete name; + delete description; + } +} + +class MoreDoc : ItemDoc +{ +public: + property String usage { get { return this ? usage : null; } set { delete usage; usage = CopyString(value); } isset { return usage && *usage; } } + property String example { get { return this ? example : null; } set { delete example; example = CopyString(value); } isset { return example && *example; } } + property String remarks { get { return this ? remarks : null; } set { delete remarks; remarks = CopyString(value); } isset { return remarks && *remarks; } } + property String also { get { return this ? also : null; } set { delete also; also = CopyString(value); } isset { return also && *also; } } +private: + char * usage; + char * example; + char * remarks; + char * also; + property bool isEmpty + { + get + { + return !( + (usage && *usage) || + (example && *example) || + (remarks && *remarks) || + (also && *also) || + !ItemDoc::isEmpty); + } + } + ~MoreDoc() + { + delete usage; + delete example; + delete remarks; + delete also; + } +} + +class NamespaceDoc : ItemDoc +{ +public: + Map defines; + Map functions; +private: + property bool isEmpty + { + get + { + return !( + (defines && defines.count) || + (functions && functions.count) || + !ItemDoc::isEmpty); + } + } + ~NamespaceDoc() + { + delete defines; + delete functions; + } +} + +class DefineDoc : ItemDoc { } + +class FunctionDoc : MoreDoc +{ +public: + Map parameters; + property String returnValue { get { return this ? returnValue : null; } set { delete returnValue; returnValue = CopyString(value); } isset { return returnValue && *returnValue; } } +private: + char * returnValue; + property bool isEmpty + { + get + { + return !( + (parameters && parameters.count) || + (returnValue && *returnValue) || + !MoreDoc::isEmpty); + } + } + ~FunctionDoc() + { + delete parameters; + delete returnValue; + } +} + +class ParameterDoc : ItemDoc +{ +public: + uint position; +} + +class ClassDoc : MoreDoc +{ +public: + Map values; + Map fields; + Map properties; + Map conversions; + Map methods; +private: + property bool isEmpty + { + get + { + return !( + (values && values.count) || + (fields && fields.count) || + (properties && properties.count) || + (conversions && conversions.count) || + (methods && methods.count) || + !MoreDoc::isEmpty); + } + } + ~ClassDoc() + { + delete values; + delete fields; + delete properties; + delete conversions; + delete methods; + } +} + +class ValueDoc : ItemDoc { } + +class FieldDoc : ItemDoc { } + +class PropertyDoc : ItemDoc { } + +class ConversionDoc : ItemDoc { } + +class MethodDoc : FunctionDoc { } + +char * getDocFileNameFromTypeName(const char * typeName) +{ + char * docFileName = new char[MAX_FILENAME]; + const char * swap = "pointer"; + const char * s = typeName; + char * d = docFileName; + const char * end = s + strlen(typeName); + int swapLen = strlen(swap); + for(; s < end; s++) + { + if(*s == ' ') + *d = '-'; + else if(*s == '*') + { + strcpy(d, swap); + d += swapLen; + } + else + *d = *s; + d++; + } + *d = '\0'; + return docFileName; +} + +class DocCacheEntry +{ + Time added; + ItemDoc doc; + + ~DocCacheEntry() + { + delete doc; + } +} + +Map docCache { }; diff --git a/documentor/tools/ear-to-econ-ecdoc.ec b/documentor/tools/ear-to-econ-ecdoc.ec new file mode 100644 index 0000000..8921ea2 --- /dev/null +++ b/documentor/tools/ear-to-econ-ecdoc.ec @@ -0,0 +1,733 @@ +import "ecere" +import "ec" +import "Documentor.ec" + +#define sflnprintln(...) PrintLn(__FILE__, ":", __LINE__, ": ", ##__VA_ARGS__) + +static Context globalContext { }; +static OldList defines { }; +static OldList imports { }; +static NameSpace globalData; +static OldList excludedSymbols { offset = (uint)(uintptr)&((Symbol)0).left }; + +define app = (Convertor)__thisModule.application; + +#define UTF8_NUM_BYTES(x) (__extension__({ byte b = x; (b & 0x80 && b & 0x40) ? ((b & 0x20) ? ((b & 0x10) ? 4 : 3) : 2) : 1; })) + +default: +/*extern */int __ecereVMethodID_class_OnGetString; +private: + + +static __attribute__((unused)) void Dummy() +{ + int a; + a.OnGetString(null, null, null); +} + +static String ConvertReadDoc(const char * filePath) +{ + uint len; + String contents = null; + File f; + f = FileOpen(filePath, read); + if(f) + { + if((len = f.GetSize())) + { + contents = new char[len+1]; + f.Read(contents, 1, len); + contents[len] = '\0'; + } + delete f; + } + if(contents) + { + char * s; + for(s = contents; *s; s++) + if(!isspace(*s)) break; + if(!*s) + delete contents; + } + if(contents) + { + String buffer = new char[len+1]; + char * i, * o = buffer; + for(i = contents; *i; i++) + { + if(i[0] == '<' && (i[1] == 'b' || i[1] == 'B') && (i[2] == 'r' || i[2] == 'R') && i[3] == '>' && i[4] == '\n') + i += 3; + else + { + *o = *i; + o++; + } + } + *o = 0; + delete contents; + contents = buffer; + } + return contents; +} + +void ConvertModuleDoc(Module module, bool isDll) +{ + SubModule m; + bool readOnly = true; + char oldDocFilePath[MAX_LOCATION]; + char docFilePath[MAX_LOCATION]; + NameSpace * nameSpace = null; + if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM"))) + nameSpace = &module.application.systemNameSpace; + if(module.name && strcmp(module.name, "ecereCOM")) + nameSpace = &module.publicNameSpace; +#ifdef _DEBUG + getDocFilePath(oldDocFilePath, null, module, nameSpace, false, true); + getDocFilePath(docFilePath, null, module, nameSpace, false, false); + PrintLn("ConvertModuleDoc:", + " convertDocDir(", app.convertDocDir, ")", + " outputDocDir(", app.outputDocDir, ")", + " oldDocFile(", oldDocFilePath, ")", + " docFile(", docFilePath, ")"); +#endif // def _DEBUG + getDocFilePath(oldDocFilePath, app.convertDocDir, module, nameSpace, true, true); + getDocFilePath(docFilePath, app.outputDocDir, module, nameSpace, true, false); + + if(FileExists(oldDocFilePath)) + { + if(FileExists(docFilePath).isDirectory) + { + char writeTestFilePath[MAX_LOCATION]; + File f; + sprintf(writeTestFilePath, "%s/_", docFilePath); + f = FileOpen(writeTestFilePath, write); + PrintLn("Info: Directory exists for eCdoc in eCon format. Conversion is not required. Proceeding anyway."); + if(f) + { + delete f; + DeleteFile(writeTestFilePath); + readOnly = false; + } + else + { + readOnly = true; + PrintLn("Error: Directory for eCdoc in eCon format is not writable."); + } + } + else + { + MakeDir(docFilePath); + if(FileExists(docFilePath).isDirectory) + { + readOnly = false; + } + else + { + readOnly = true; + PrintLn("Error: Unable to create directory for eCdoc conversion to eCon."); + } + } + + if(!readOnly) + { + char fileName[MAX_LOCATION]; + DocConvertIterator fsi + { + bool onFolder(const char * folderPath, const char * folderName) + { + DocConvertLocType type = typeStack.lastIterator.data; + if(getNext) + { + if(type == namespaces) + { + PathCatSlash(nsDir, folderName); + namespaces.Add((ns = { namespaceDoc = { name = CopyString(folderName) }, nsPath = CopyString(nsDir) })); + nsStack.Add(ns); + } + else if(type == functions) + { + functionDoc = FunctionDoc { }; + if(!ns.namespaceDoc.functions) + ns.namespaceDoc.functions = { }; + ns.namespaceDoc.functions[folderName] = functionDoc; + } + else if(type == classes) + { + classDoc = ClassDoc { name = CopyString(folderName) }; + ns.classes.Add(classDoc); + } + else if(type == methods) + { + methodDoc = MethodDoc { }; + if(!classDoc.methods) + classDoc.methods = { }; + classDoc.methods[folderName] = methodDoc; + } + else + sflnprintln("what?"); + nameStack.Add(CopyString(folderName)); + getNext = false; + if(!strcmp(folderName, "namespaces")) + sflnprintln("what?"); + else if(!strcmp(folderName, "functions")) + sflnprintln("what?"); + else if(!strcmp(folderName, "parameters")) + sflnprintln("what?"); + else if(!strcmp(folderName, "classes")) + sflnprintln("what?"); + else if(!strcmp(folderName, "enumeration values")) + sflnprintln("what?"); + else if(!strcmp(folderName, "data members")) + sflnprintln("what?"); + else if(!strcmp(folderName, "properties")) + sflnprintln("what?"); + else if(!strcmp(folderName, "conversions")) + sflnprintln("what?"); + else if(!strcmp(folderName, "methods")) + sflnprintln("what?"); + } + else if((type == root || type == namespaces) && !strcmp(folderName, "namespaces")) + addType(namespaces); + else if((type == root || type == namespaces) && !strcmp(folderName, "functions")) + addType(functions); + else if((type == functions || type == methods) && !strcmp(folderName, "parameters")) + addType(parameters); + else if((type == root || type == namespaces) && !strcmp(folderName, "classes")) + addType(classes); + else if(type == classes && !strcmp(folderName, "enumeration values")) + addType(values); + else if(type == classes && !strcmp(folderName, "data members")) + addType(fields); + else if(type == classes && !strcmp(folderName, "properties")) + addType(properties); + else if(type == classes && !strcmp(folderName, "conversions")) + addType(conversions); + else if(type == classes && !strcmp(folderName, "methods")) + addType(methods); + return true; + } + + void outFolder(const char * folderPath, const char * folderName, bool isRoot) + { + DocConvertLocType type = typeStack.lastIterator.data; + if(!isRoot) + { + if(!strcmp(folderName, "namespaces")) + exitType(); + else if(!strcmp(folderName, "functions")) + exitType(); + else if(!strcmp(folderName, "parameters")) + exitType(); + else if(!strcmp(folderName, "classes")) + exitType(); + else if(!strcmp(folderName, "enumeration values")) + exitType(); + else if(!strcmp(folderName, "data members")) + exitType(); + else if(!strcmp(folderName, "properties")) + exitType(); + else if(!strcmp(folderName, "conversions")) + exitType(); + else if(!strcmp(folderName, "methods")) + exitType(); + else if(!strcmp(folderName, nameStack.lastIterator.data)) + { + if(type == namespaces) + { + StripLastDirectory(nsDir, nsDir); + nsStack.Remove(nsStack.lastIterator.pointer); + ns = nsStack.lastIterator.data; + } + delete nameStack.lastIterator.data; + nameStack.Remove(nameStack.lastIterator.pointer); + getNext = true; + } + } + } + + bool onFile(const char * filePath, const char * fileName) + { + DocConvertLocType type = typeStack.lastIterator.data; + if(!strstr(fileName, ".eCdoc")) + { + String doc = ConvertReadDoc(filePath); + if((type == root || type == namespaces || type == classes || type == methods || type == functions) && !strcmp(fileName, "description")) + { + if(type == root || type == namespaces) { ns.namespaceDoc.description = doc; doc = null; } + else if(type == classes) { classDoc.description = doc; doc = null; } + else if(type == methods) { methodDoc.description = doc; doc = null; } + else if(type == functions) { functionDoc.description = doc; doc = null; } + } + else if((type == classes || type == methods || type == functions) && !strcmp(fileName, "usage")) + { + if(type == classes) { classDoc.usage = doc; doc = null; } + else if(type == methods) { methodDoc.usage = doc; doc = null; } + else if(type == functions) { functionDoc.usage = doc; doc = null; } + } + else if((type == classes || type == methods || type == functions) && !strcmp(fileName, "example")) + { + if(type == classes) { classDoc.example = doc; doc = null; } + else if(type == methods) { methodDoc.example = doc; doc = null; } + else if(type == functions) { functionDoc.example = doc; doc = null; } + } + else if((type == classes || type == methods || type == functions) && !strcmp(fileName, "remarks")) + { + if(type == classes) { classDoc.remarks = doc; doc = null; } + else if(type == methods) { methodDoc.remarks = doc; doc = null; } + else if(type == functions) { functionDoc.remarks = doc; doc = null; } + } + else if((type == classes || type == methods || type == functions) && !strcmp(fileName, "seeAlso")) + { + if(type == classes) { classDoc.also = doc; doc = null; } + else if(type == methods) { methodDoc.also = doc; doc = null; } + else if(type == functions) { functionDoc.also = doc; doc = null; } + } + else if((type == methods || type == functions) && !strcmp(fileName, "returnValue")) + { + if(type == methods) { methodDoc.returnValue = doc; doc = null; } + else if(type == functions) { functionDoc.returnValue = doc; doc = null; } + } + else + { + if(type == parameters) + { + uint pos; + char * s; + char name[MAX_FILENAME]; + ParameterDoc parameterDoc; + DocConvertLocType parentType = typeStack[typeStack.count-2]; + strcpy(name, fileName); + s = strstr(name, "."); + if(s) + { + *s = 0; + s++; + pos = atoi(s); + } + else + sflnprintln("what?"); + if(parentType == functions) + { + parameterDoc = ParameterDoc { description = doc, position = pos }; + doc = null; + if(!functionDoc.parameters) + functionDoc.parameters = { }; + functionDoc.parameters[name] = parameterDoc; + } + else if(parentType == methods) + { + parameterDoc = ParameterDoc { description = doc, position = pos }; + doc = null; + if(!methodDoc.parameters) + methodDoc.parameters = { }; + methodDoc.parameters[name] = parameterDoc; + } + else + sflnprintln("what?"); + } + else if(type == values) + { + ValueDoc valueDoc { description = doc }; + doc = null; + if(!classDoc.values) + classDoc.values = { }; + classDoc.values[fileName] = valueDoc; + } + else if(type == fields) + { + FieldDoc fieldDoc { description = doc }; + doc = null; + if(!classDoc.fields) + classDoc.fields = { }; + classDoc.fields[fileName] = fieldDoc; + } + else if(type == properties) + { + PropertyDoc propertyDoc { description = doc }; + doc = null; + if(!classDoc.properties) + classDoc.properties = { }; + classDoc.properties[fileName] = propertyDoc; + } + else if(type == conversions) + { + ConversionDoc conversionDoc { description = doc }; + doc = null; + if(!classDoc.conversions) + classDoc.conversions = { }; + classDoc.conversions[fileName] = conversionDoc; + } + else + sflnprintln("what?"); + } + delete doc; + } + return true; + } + }; + fsi.nsDir[0] = '\0'; + PathCatSlash(fsi.nsDir, docFilePath); + fsi.typeStack.Add(root); + fsi.namespaces.Add((fsi.ns = { namespaceDoc = { }, nsPath = CopyString(fsi.nsDir) })); + fsi.nsStack.Add(fsi.ns); + sprintf(fileName, "<%s>", oldDocFilePath); + fsi.iterate(fileName); + for(ns : fsi.namespaces) + { + writeNamespaceDocFile(ns.namespaceDoc, ns.nsPath); + for(c : ns.classes) + { + writeClassDocFile(c, ns.nsPath); + } + } + } + } + else + { + PrintLn("Info: old eCdoc format file (", oldDocFilePath, ") does not exist."); + } + + for(m = module.modules.first; m; m = m.next) + { + if(m.importMode == publicAccess || !isDll) + ConvertModuleDoc(m.module, true); + } +} + +void getDocFilePath(char * docFilePath, char * docDir, Module module, NameSpace * ns, bool includeDir, bool old) +{ + sprintf(docFilePath, old ? "%s%s%s.eCdoc" : "%s%s%s", includeDir ? docDir : "", includeDir ? "/" : "", + (!module || !module.name || + (ns && ns->name && !strcmp(ns->name, "namespaces/ecere/namespaces/com"))) ? "ecereCOM" : module.name); +} + +static void writeNamespaceDocFile(NamespaceDoc namespaceDoc, const char * path) +{ + if(!namespaceDoc.isEmpty) + { + char * filePath = new char[MAX_LOCATION]; + File f; + strcpy(filePath, path); + PathCatSlash(filePath, "_global-defs"); + ChangeExtension(filePath, "econ", filePath); + MakeDir(path); + DeleteFile(filePath); + f = FileOpen(filePath, write); + if(f) + { + WriteJSONObject(f, class(NamespaceDoc), namespaceDoc, 0, true); + delete f; + } + else + { + PrintLn("error: writeNamespaceDocFile -- problem opening file: ", filePath); + } + delete filePath; + } +} + +static void writeClassDocFile(ClassDoc classDoc, const char * path) +{ + if(!classDoc.isEmpty) + { + char * name = getDocFileNameFromTypeName(classDoc.name); + char * filePath = new char[MAX_LOCATION]; + File f; + strcpy(filePath, path); + PathCatSlash(filePath, name); + ChangeExtension(filePath, "econ", filePath); + DeleteFile(filePath); + f = FileOpen(filePath, write); + if(f) + { + WriteJSONObject(f, class(ClassDoc), classDoc, 0, true); + delete f; + } + else + { + PrintLn("error: writeClassDocFile -- problem opening file: ", filePath); + } + delete name; + delete filePath; + } +} + +Application componentsApp; + +class Convertor : Application +{ + char * moduleName;; + char * convertDocDir; + char * outputDocDir; + + bool Init() + { + SetGlobalContext(globalContext); + SetExcludedSymbols(&excludedSymbols); + SetDefines(&::defines); + SetImports(&imports); + SetInDocumentor(true); + + SetGlobalData(globalData); + + if(argc == 3 || argc == 4) + { + convertDocDir = CopyString(argv[1]); + outputDocDir = CopyString(argv[2]); + if(argc == 4) + moduleName = CopyString(argv[3]); + else + moduleName = CopyString("ecere"); + return true; + } + return false; + } + + void Main() + { + if(Init()) + { + OpenModule(moduleName); + } + else + { + PrintLn($"Syntax: exename []"); + } + system("pause"); + } + + void Terminate() + { + delete moduleName; + delete convertDocDir; + delete outputDocDir; + + FreeContext(globalContext); + FreeExcludedSymbols(excludedSymbols); + ::defines.Free(FreeModuleDefine); + imports.Free(FreeModuleImport); + + FreeGlobalData(globalData); + FreeTypeData(componentsApp); + FreeIncludeFiles(); + delete componentsApp; + } + + void OpenModule(const char * filePath) + { + char moduleName[MAX_LOCATION]; + char extension[MAX_EXTENSION]; + Module module = null; + static char symbolsDir[MAX_LOCATION]; + + FreeContext(globalContext); + FreeExcludedSymbols(excludedSymbols); + ::defines.Free(FreeModuleDefine); + imports.Free(FreeModuleImport); + + FreeGlobalData(globalData); + FreeIncludeFiles(); + if(componentsApp) + { + FreeTypeData(componentsApp); + delete componentsApp; + } + + componentsApp = __ecere_COM_Initialize(false, 1, null); + SetPrivateModule(componentsApp); + + StripLastDirectory(filePath, symbolsDir); + SetSymbolsDir(symbolsDir); + + GetExtension(filePath, extension); + + ImportModule(filePath, normalImport, publicAccess, false); + + if(extension[0] && strcmpi(extension, "so") && strcmpi(extension, "dll") && strcmpi(extension, "dylib")) + componentsApp.name = CopyString(filePath); + + for(module = componentsApp.allModules.first; module; module = module.next) + { + if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM"))) + break; + } + if(!module) + eModule_LoadStrict(componentsApp, "ecereCOM", publicAccess /*privateAccess*/); + + GetLastDirectory(filePath, moduleName); + // Extension, path and lib prefix get removed in Module::name + if(extension[0]) + { + StripExtension(moduleName); + if((!strcmpi(extension, "so") || !strcmpi(extension, "dylib")) && strstr(moduleName, "lib") == moduleName) + { + int len = strlen(moduleName) - 3; + memmove(moduleName, moduleName + 3, len); + moduleName[len] = 0; + } + } + + ConvertModuleDoc(componentsApp, false); + } +} + +class DocConvertNamespaceStackFrame +{ + NamespaceDoc namespaceDoc { }; + Array classes { }; + char * nsPath; +} + +enum DocConvertLocType { root, namespaces, functions, parameters, classes, values, fields, properties, conversions, methods }; + +class DocConvertIterator : NormalFileSystemIterator +{ + char * nsDir; + + bool getNext; + Array nameStack { }; + Array typeStack { }; + Array nsStack { }; + Array namespaces { }; + DocConvertNamespaceStackFrame ns; + DefineDoc defineDoc; + FunctionDoc functionDoc; + ClassDoc classDoc; + MethodDoc methodDoc; + + void addType(DocConvertLocType type) + { + typeStack.Add(type); + getNext = true; + } + void exitType() + { + typeStack.Remove(typeStack.lastIterator.pointer); + getNext = false; + } + + DocConvertIterator() + { + nsDir = new char[MAX_LOCATION]; + } + ~DocConvertIterator() + { + delete nsDir; + } +} + +public class NormalFileSystemIterator : FileSystemIterator +{ +public: + Array stack { }; + + char * extensions; + property char * extensions { set { delete extensions; if(value) extensions = CopyString(value); } } + + ~NormalFileSystemIterator() + { + delete extensions; + } + + void iterate(const char * startPath) + { + StackFrame frame; + char startName[MAX_FILENAME]; + startName[0] = '\0'; + GetLastDirectory(startPath, startName); + + onInit(startPath, startName); + { + frame = StackFrame { }; + stack.Add(frame); + frame.path = CopyString(startPath); + frame.listing = FileListing { startPath, extensions = extensions }; + } + + if(iterateStartPath) + { + FileAttribs attribs = FileExists(startPath); + if(attribs.isDrive) + onVolume(startPath); + else + { + if(attribs.isDirectory) + onFolder(startPath, startName); + else if(attribs.isFile) + onFile(startPath, startName); + } + } + + while(stack.count) + { + if(frame.listing.Find()) + { + bool peek = frame.listing.stats.attribs.isDirectory && onFolder(frame.listing.path, frame.listing.name); + if(!frame.listing.stats.attribs.isDirectory) + { + onFile(frame.listing.path, frame.listing.name); + } + else if(peek) + { + StackFrame newFrame { }; + stack.Add(newFrame); + newFrame.path = CopyString(frame.listing.path); + newFrame.listing = FileListing { newFrame.path, extensions = frame.listing.extensions }; + frame = newFrame; + } + } + else + { + StackFrame parentFrame = stack.count > 1 ? stack[stack.count - 2] : null; + outFolder(parentFrame ? parentFrame.listing.path : startPath, parentFrame ? parentFrame.listing.name : startName, !parentFrame); + stack.lastIterator.Remove(); + if(stack.count) + frame = stack.lastIterator.data; + else + frame = null; + } + } + } +} + +public class FileSystemIterator +{ +public: + bool iterateStartPath; + + virtual bool onInit(const char * startPath, const char * startName) + { + return false; + } + + virtual bool onFile(const char * filePath, const char * fileName) + { + return true; + } + + virtual bool onFolder(const char * folderPath, const char * folderName) + { + return true; + } + + virtual bool onVolume(const char * volumePath) + { + return true; + } + + virtual void outFolder(const char * folderPath, const char * folderName, bool isRoot) + { + } +} + +public class StackFrame +{ + int tag; + char * path; + FileListing listing; + + ~StackFrame() + { + delete path; + } +}; diff --git a/documentor/tools/ear-to-econ-ecdoc.epj b/documentor/tools/ear-to-econ-ecdoc.epj new file mode 100644 index 0000000..3f523d1 --- /dev/null +++ b/documentor/tools/ear-to-econ-ecdoc.epj @@ -0,0 +1,45 @@ +{ + "Version" : 0.2, + "ModuleName" : "ear-to-econ-ecdoc", + "Options" : { + "Warnings" : "All", + "PreprocessorDefinitions" : [ + "EAR_TO_ECON_ECDOC" + ], + "TargetType" : "Executable", + "TargetFileName" : "ear-to-econ-ecdoc", + "Libraries" : [ + "ecere" + ], + "Console" : true + }, + "Configurations" : [ + { + "Name" : "Debug", + "Options" : { + "Debug" : true, + "Optimization" : "None", + "PreprocessorDefinitions" : [ + "_DEBUG" + ], + "FastMath" : false + } + }, + { + "Name" : "Release", + "Options" : { + "Debug" : false, + "Optimization" : "Speed", + "FastMath" : true + } + } + ], + "Files" : [ + "ear-to-econ-ecdoc.ec", + "../src/Documentor.ec" + ], + "ResourcesPath" : "", + "Resources" : [ + + ] +} -- 1.8.3.1