diff --git a/CHANGELOG.md b/CHANGELOG.md index 115de48..eb63d19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,18 @@ All notable version changes will be recorded in this file. *** +### [v3.21.1] revision + +**New**: + - `Map View`: Support show `map.view` file for SDCC and KEIL_C51 toolchain. + - `Scatter File Highlight`: Support a simple arm scatter file (`.sct`) language support. + +**Fix**: + - `Program Matcher`: Sometimes armcc problem matcher missed matchs. + - `CMSIS Config Wizard`: Missed skip value for `<e>` tag. + +*** + ### [v3.21.0] update **New**: diff --git a/lang/syntax/sct.language-configuration.json b/lang/syntax/sct.language-configuration.json new file mode 100644 index 0000000..b8fe471 --- /dev/null +++ b/lang/syntax/sct.language-configuration.json @@ -0,0 +1,23 @@ +{ + "comments": { + "lineComment": ";", + "blockComment": ["/*", "*/"], + }, + "brackets": [ + ["{", "}"], + ["[", "]"], + ["(", ")"] + ], + "autoClosingPairs": [ + { "open": "{", "close": "}" }, + { "open": "[", "close": "]" }, + { "open": "(", "close": ")" }, + { "open": "'", "close": "'", "notIn": ["string", "comment"] }, + { "open": "\"", "close": "\"", "notIn": ["string"] }, + { "open": "/**", "close": " */", "notIn": ["string"] } + ], + "indentationRules": { + "increaseIndentPattern": "^\\s*{", + "decreaseIndentPattern": "^\\s*}" + } +} \ No newline at end of file diff --git a/lang/syntax/sct.tmLanguage.json b/lang/syntax/sct.tmLanguage.json new file mode 100644 index 0000000..c644294 --- /dev/null +++ b/lang/syntax/sct.tmLanguage.json @@ -0,0 +1,108 @@ +{ + "information_for_contributors": [ + "arm scatter file" + ], + "version": "1.0.0", + "name": "sct", + "scopeName": "source.arm.sct", + "patterns": [ + { + "include": "#commandline" + }, + { + "include": "#line_comment" + }, + { + "include": "#block_comment" + }, + { + "include": "#string" + }, + { + "include": "#number" + }, + { + "include": "#operators" + }, + { + "include": "#preprocessor" + }, + { + "include": "#keyword.load_region" + }, + { + "include": "#keyword.exec_region" + } + ], + "repository": { + "commandline": { + "match": "^#!.*$", + "captures": { + "0": { + "name": "markup.italic" + } + } + }, + "line_comment": { + "match": "(;|\\/\\/).*", + "captures": { + "0": { + "name": "comment.line" + } + } + }, + "block_comment": { + "begin": "\\/\\*", + "end" : "\\*\\/", + "name": "comment.block" + }, + "string": { + "match": "\"([^\"\\\\]*(\\\\.[^\"\\\\]*)*)\"", + "captures": { + "0": { + "name": "string.quoted.double" + } + } + }, + "number": { + "match": "(?i)\\b([0-9]+|0x[0-9a-f]+)\\b", + "captures": { + "1": { + "name": "constant.numeric" + } + } + }, + "operators": { + "match": "\\+|-|\\*|\\/(?!\\/)|\\+=|-=|=|==|<=|>=|!=", + "captures": { + "0": { + "name": "keyword.operator" + } + } + }, + "preprocessor": { + "match": "^\\s*(#define|#undef|#include|#if|#ifdef|#ifndef|#elif|#else|#endif)", + "captures": { + "1": { + "name": "keyword.control.define" + } + } + }, + "keyword.load_region": { + "match": "\\b(ABSOLUTE|ALIGN|NOCOMPRESS|OVERLAY|PI|PROTECTED|RELOC)\\b", + "captures": { + "1": { + "name": "keyword" + } + } + }, + "keyword.exec_region": { + "match": "\\b(ABSOLUTE|ALIGN|NOCOMPRESS|OVERLAY|PI|ALIGNALL|ANY_SIZE|EMPTY|FILL|FIXED|PADVALUE|SORTTYPE|UNINIT|ZEROPAD)\\b", + "captures": { + "1": { + "name": "keyword" + } + } + } + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 2031532..e8ef1ef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "eide", - "version": "3.21.0", + "version": "3.21.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "eide", - "version": "3.21.0", + "version": "3.21.1", "license": "MIT", "dependencies": { "iconv-lite": "^0.5.0", diff --git a/package.json b/package.json index 89b1d1d..78bc73d 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "homepage": "https://em-ide.com", "license": "MIT", "description": "A mcu development environment for 8051/AVR/STM8/Cortex-M/MIPS/RISC-V", - "version": "3.21.0", + "version": "3.21.1", "preview": false, "engines": { "vscode": "^1.67.0" @@ -1748,6 +1748,19 @@ "**/*.lkf" ], "configuration": "./lang/syntax/lkf.language-configuration.json" + }, + { + "id": "sct", + "aliases": [ + "ARM Scatter File" + ], + "extensions": [ + ".sct" + ], + "filenamePatterns": [ + "**/*.sct" + ], + "configuration": "./lang/syntax/sct.language-configuration.json" } ], "jsonValidation": [ @@ -1829,6 +1842,11 @@ "language": "lkf", "scopeName": "source.cosmic.lkf", "path": "./lang/syntax/lkf.tmLanguage.json" + }, + { + "language": "sct", + "scopeName": "source.arm.sct", + "path": "./lang/syntax/sct.tmLanguage.json" } ], "taskDefinitions": [ diff --git a/res/tools/darwin/unify_builder/arm64/unify_builder.deps.json b/res/tools/darwin/unify_builder/arm64/unify_builder.deps.json index a02f1b7..6e0cadd 100644 --- a/res/tools/darwin/unify_builder/arm64/unify_builder.deps.json +++ b/res/tools/darwin/unify_builder/arm64/unify_builder.deps.json @@ -7,7 +7,7 @@ "targets": { ".NETCoreApp,Version=v6.0": {}, ".NETCoreApp,Version=v6.0/osx-arm64": { - "unify_builder/3.9.1": { + "unify_builder/3.9.2": { "dependencies": { "CommandLineParser": "2.9.1", "ConsoleTableExt": "3.1.9", @@ -60,7 +60,7 @@ } }, "libraries": { - "unify_builder/3.9.1": { + "unify_builder/3.9.2": { "type": "project", "serviceable": false, "sha512": "" diff --git a/res/tools/darwin/unify_builder/arm64/unify_builder.dll b/res/tools/darwin/unify_builder/arm64/unify_builder.dll index 3dbb77f..7226e82 100644 Binary files a/res/tools/darwin/unify_builder/arm64/unify_builder.dll and b/res/tools/darwin/unify_builder/arm64/unify_builder.dll differ diff --git a/res/tools/darwin/unify_builder/x86_64/unify_builder.deps.json b/res/tools/darwin/unify_builder/x86_64/unify_builder.deps.json index ab9385a..61cffe7 100644 --- a/res/tools/darwin/unify_builder/x86_64/unify_builder.deps.json +++ b/res/tools/darwin/unify_builder/x86_64/unify_builder.deps.json @@ -7,7 +7,7 @@ "targets": { ".NETCoreApp,Version=v6.0": {}, ".NETCoreApp,Version=v6.0/osx-x64": { - "unify_builder/3.9.1": { + "unify_builder/3.9.2": { "dependencies": { "CommandLineParser": "2.9.1", "ConsoleTableExt": "3.1.9", @@ -60,7 +60,7 @@ } }, "libraries": { - "unify_builder/3.9.1": { + "unify_builder/3.9.2": { "type": "project", "serviceable": false, "sha512": "" diff --git a/res/tools/darwin/unify_builder/x86_64/unify_builder.dll b/res/tools/darwin/unify_builder/x86_64/unify_builder.dll index 21d0d54..bcc5c01 100644 Binary files a/res/tools/darwin/unify_builder/x86_64/unify_builder.dll and b/res/tools/darwin/unify_builder/x86_64/unify_builder.dll differ diff --git a/res/tools/linux/unify_builder/unify_builder.deps.json b/res/tools/linux/unify_builder/unify_builder.deps.json index 38f8a50..a571e3a 100644 --- a/res/tools/linux/unify_builder/unify_builder.deps.json +++ b/res/tools/linux/unify_builder/unify_builder.deps.json @@ -7,7 +7,7 @@ "targets": { ".NETCoreApp,Version=v6.0": {}, ".NETCoreApp,Version=v6.0/linux-x64": { - "unify_builder/3.9.1": { + "unify_builder/3.9.2": { "dependencies": { "CommandLineParser": "2.9.1", "ConsoleTableExt": "3.1.9", @@ -60,7 +60,7 @@ } }, "libraries": { - "unify_builder/3.9.1": { + "unify_builder/3.9.2": { "type": "project", "serviceable": false, "sha512": "" diff --git a/res/tools/linux/unify_builder/unify_builder.dll b/res/tools/linux/unify_builder/unify_builder.dll index 21d0d54..bcc5c01 100644 Binary files a/res/tools/linux/unify_builder/unify_builder.dll and b/res/tools/linux/unify_builder/unify_builder.dll differ diff --git a/res/tools/win32/unify_builder/unify_builder.deps.json b/res/tools/win32/unify_builder/unify_builder.deps.json index d474f12..faa8b45 100644 --- a/res/tools/win32/unify_builder/unify_builder.deps.json +++ b/res/tools/win32/unify_builder/unify_builder.deps.json @@ -7,7 +7,7 @@ "targets": { ".NETCoreApp,Version=v6.0": {}, ".NETCoreApp,Version=v6.0/win-x64": { - "unify_builder/3.9.1": { + "unify_builder/3.9.2": { "dependencies": { "CommandLineParser": "2.9.1", "ConsoleTableExt": "3.1.9", @@ -60,7 +60,7 @@ } }, "libraries": { - "unify_builder/3.9.1": { + "unify_builder/3.9.2": { "type": "project", "serviceable": false, "sha512": "" diff --git a/res/tools/win32/unify_builder/unify_builder.dll b/res/tools/win32/unify_builder/unify_builder.dll index eababf8..16fa202 100644 Binary files a/res/tools/win32/unify_builder/unify_builder.dll and b/res/tools/win32/unify_builder/unify_builder.dll differ diff --git a/res/tools/win32/unify_builder/unify_builder.exe b/res/tools/win32/unify_builder/unify_builder.exe index 191b714..dcdb832 100644 Binary files a/res/tools/win32/unify_builder/unify_builder.exe and b/res/tools/win32/unify_builder/unify_builder.exe differ diff --git a/src/CmsisConfigParser.ts b/src/CmsisConfigParser.ts index ecbfd09..0756561 100644 --- a/src/CmsisConfigParser.ts +++ b/src/CmsisConfigParser.ts @@ -401,7 +401,7 @@ interface ParserContext { const fieldMatcher: TagMatcher = { 'group': { start: /^\/\/\s*<h>\s*(?<name>.+)/, end: /^\/\/\s*<\/h>/ }, - 'section': { start: /^\/\/\s*<e(?:\.(?<var_mod_bit_s>[\d]+))?(?: (?<var_name>\w+))?>\s*(?<name>.+?)(?<desc>(?:\s+[-]+\s*.*)?)$/, end: /^\/\/\s*<\/e>/ }, + 'section': { start: /^\/\/\s*<e(?<var_skip_val>\d+)?(?:\.(?<var_mod_bit_s>[\d]+))?(?: (?<var_name>\w+))?>\s*(?<name>.+?)(?<desc>(?:\s+[-]+\s*.*)?)$/, end: /^\/\/\s*<\/e>/ }, 'tooltip': { start: /^\/\/\s*<i>\s*(?<detail>.+)\s*$/ }, 'defval': { start: /^\/\/\s*<d>\s*(?<var_def_val>.+)\s*$/ }, 'code': { start: /^\/\/\s*<!?c(?<var_skip_val>\d+)?>\s*(?<name>.+?)(?<desc>(?:\s+[-]+\s*.*)?)$/, end: /^\/\/\s*<\/[!]?c>/ }, diff --git a/src/CodeBuilder.ts b/src/CodeBuilder.ts index aa67585..19ef1c0 100644 --- a/src/CodeBuilder.ts +++ b/src/CodeBuilder.ts @@ -128,7 +128,7 @@ export abstract class CodeBuilder { this._event.emit(event, arg); } - protected genSourceInfo(prevBuilderParams: BuilderParams | undefined): { + protected genSourceInfo(): { sources: string[], params?: { [name: string]: string; } } { @@ -175,18 +175,6 @@ export abstract class CodeBuilder { const parttenInfo = options?.files; matcher(parttenInfo, 'path'); } - - // if src options is modified to null but old is not null, - // we need make source recompile - if (prevBuilderParams) { - const oldSrcParams = prevBuilderParams.sourceParams; - for (const path in oldSrcParams) { - if (srcParams[path] == undefined && oldSrcParams[path] != undefined && - oldSrcParams[path] != '') { - srcParams[path] = ""; // make it empty to trigger recompile - } - } - } } } catch (err) { @@ -375,9 +363,7 @@ export abstract class CodeBuilder { const paramsPath = this.project.ToAbsolutePath(outDir + File.sep + this.paramsFileName); const compileOptions: BuilderOptions = this.project.GetConfiguration().compileConfigModel.getOptions(); const memMaxSize = this.getMcuMemorySize(); - const oldParamsPath = `${paramsPath}.old`; - const prevParams: BuilderParams | undefined = File.IsFile(oldParamsPath) ? JSON.parse(fs.readFileSync(oldParamsPath, 'utf8')) : undefined; - const sourceInfo = this.genSourceInfo(prevParams); + const sourceInfo = this.genSourceInfo(); const builderModeList: string[] = []; // build mode const builderOptions: BuilderParams = { @@ -497,37 +483,6 @@ export abstract class CodeBuilder { // set build mode { - /** -------------------------------------------------------------- - * @note After unify_builder v3.9.0, this function is deprecated - * because we have built-in it in the latest unify_builder - * --------------------------------------------------------------- - */ - // // generate hash for compiler options - // builderOptions.sha = this.genHashFromCompilerOptions(builderOptions); - // // check whether need rebuild project - // if (this.isRebuild() == false && prevParams) { - // try { - // // not found hash from old params file - // if (prevParams.sha == undefined) { - // this.enableRebuild(); - // } - - // // check hash obj by specifies keys - // else { - // const keyList = ['global', 'c/cpp-defines', 'c/cpp-compiler', 'asm-compiler']; - // for (const key of keyList) { - // if (!this.compareHashObj(key, prevParams.sha, builderOptions.sha)) { - // this.enableRebuild(); - // break; - // } - // } - // } - // } catch (error) { - // this.enableRebuild(); // make rebuild - // GlobalEvent.emit('msg', ExceptionToMessage(error, 'Hidden')); - // } - // } - if (config.toolchain === 'Keil_C51') { builderModeList.push('normal'); // disable increment build for Keil C51 } else { diff --git a/src/EIDEProject.ts b/src/EIDEProject.ts index 7d7be20..2db107f 100644 --- a/src/EIDEProject.ts +++ b/src/EIDEProject.ts @@ -2877,12 +2877,20 @@ $(OUT_DIR): } } } catch (error) { + GlobalEvent.log_warn(<Error>error); const msg = [ `${toolchain.getToolchainPrefix()}gcc not avaliable:\n${(<Error>error).message}`, `Please check your package.json and run 'xpm install' to install xpack dependences.` ].join(os.EOL); - GlobalEvent.emit('msg', newMessage('Error', msg)); - GlobalEvent.log_warn(<Error>error); + vscode.window.showErrorMessage(msg, 'Install', 'Later') + .then((value) => { + if (value == 'Install') { + runShellCommand('xpm install', 'xpm install', { + useTerminal: true, + cwd: this.getRootDir().path + }); + } + }); return false } } diff --git a/src/ProblemMatcher.ts b/src/ProblemMatcher.ts index b0a4787..c970557 100644 --- a/src/ProblemMatcher.ts +++ b/src/ProblemMatcher.ts @@ -103,38 +103,53 @@ export type CompilerDiagnostics = { [path: string]: vscode.Diagnostic[]; } export function parseArmccCompilerLog(projApi: ProjectBaseApi, logFile: File): CompilerDiagnostics { - const pattern = { - "regexp": "^\"([^\"]+)\", line (\\d+): (Error|Warning):\\s+#([^\\s]+):\\s+(.+)$", - "file": 1, - "line": 2, - "severity": 3, - "code": 4, - "message": 5 - }; + /* examples: + ".\source\main.c", line 68: Error: At end of source: #67: expected a "}" + */ + const patterns = [ + { + "groupLen": 5, + "regexp": /^"([^"]+)", line (\d+): (Error|Warning):\s+#([^\s]+):\s+(.+)$/i, + "file": 1, + "line": 2, + "severity": 3, + "code": 4, + "message": 5 + }, + { + "groupLen": 4, + "regexp": /^"([^"]+)", line (\d+): (Error|Warning|\w+):\s+(.+)$/i, + "file": 1, + "line": 2, + "severity": 3, + "message": 4 + } + ]; - const matcher = new RegExp(pattern.regexp, 'i'); const result: { [path: string]: vscode.Diagnostic[] } = {}; const ccLogLines = parseLogLines(logFile); for (let idx = 0; idx < ccLogLines.length; idx++) { const line = ccLogLines[idx]; - const m = matcher.exec(line); - if (m && m.length > 5) { - - const fspath = projApi.toAbsolutePath(m[pattern.file]); - const line = parseInt(m[pattern.line]); - const severity = m[pattern.severity]; - const errCode = m[pattern.code].trim(); - const message = m[pattern.message].trim(); - - const diags = result[fspath] || []; - if (result[fspath] == undefined) result[fspath] = diags; - - const vscDiag = new vscode.Diagnostic( - newVscFileRange(line, 0, 10), message, toVscServerity(severity)); - vscDiag.code = errCode; - vscDiag.source = 'armcc'; - diags.push(vscDiag); + for (const pattern of patterns) { + const m = pattern.regexp.exec(line); + if (m && m.length > pattern.groupLen) { + const fspath = projApi.toAbsolutePath(m[pattern.file]); + const line = parseInt(m[pattern.line]); + const severity = m[pattern.severity]; + const errCode = pattern.code ? m[pattern.code].trim() : undefined; + const message = m[pattern.message].trim(); + + const diags = result[fspath] || []; + if (result[fspath] == undefined) result[fspath] = diags; + + const vscDiag = new vscode.Diagnostic( + newVscFileRange(line, 0, 10), message, toVscServerity(severity)); + vscDiag.code = errCode; + vscDiag.source = 'armcc'; + diags.push(vscDiag); + break; + } } } diff --git a/src/ToolchainManager.ts b/src/ToolchainManager.ts index 327367b..52ece6b 100644 --- a/src/ToolchainManager.ts +++ b/src/ToolchainManager.ts @@ -40,6 +40,7 @@ import * as os from 'os'; import { ArmBaseBuilderConfigData, ArmBaseCompileData } from "./EIDEProjectModules"; import * as utility from "./utility"; +//! 名称应该是大写,但由于历史因素,其中 'Keil_C51' 大小写暂时无法更正(避免旧的项目出现问题) export type ToolchainName = 'SDCC' | 'Keil_C51' | 'IAR_STM8' | 'GNU_SDCC_STM8' | 'COSMIC_STM8' | 'AC5' | 'AC6' | 'GCC' | 'IAR_ARM' | @@ -223,21 +224,21 @@ export class ToolchainManager { switch (prjType) { case 'RISC-V': - res = this.toolchainMap.get('RISCV_GCC'); + res = this.getToolchainByName('RISCV_GCC'); break; case 'ANY-GCC': - res = this.toolchainMap.get('ANY_GCC'); + res = this.getToolchainByName('ANY_GCC'); break; case 'ARM': switch (toolchainName) { case 'None': - res = this.toolchainMap.get('AC5'); + res = this.getToolchainByName('AC5'); break; default: if (this.toolchainNames['ARM'].includes(toolchainName)) { - res = this.toolchainMap.get(toolchainName); + res = this.getToolchainByName(toolchainName); } else { - res = this.toolchainMap.get('AC5'); + res = this.getToolchainByName('AC5'); GlobalEvent.emit('msg', newMessage('Warning', 'Invalid toolchain name \'' + toolchainName + '\' !, use default toolchain.')); } @@ -246,21 +247,21 @@ export class ToolchainManager { case 'C51': switch (toolchainName) { case 'None': - res = this.toolchainMap.get('Keil_C51'); + res = this.getToolchainByName('Keil_C51'); break; default: if (this.toolchainNames['C51'].includes(toolchainName)) { - res = this.toolchainMap.get(toolchainName); + res = this.getToolchainByName(toolchainName); } else { - res = this.toolchainMap.get('Keil_C51'); + res = this.getToolchainByName('Keil_C51'); GlobalEvent.emit('msg', newMessage('Warning', 'Invalid toolchain name \'' + toolchainName + '\' !, use default toolchain.')); } } break; case 'MIPS': - res = this.toolchainMap.get('MTI_GCC'); + res = this.getToolchainByName('MTI_GCC'); break; default: throw new Error('Invalid project type \'' + prjType + '\''); @@ -274,6 +275,9 @@ export class ToolchainManager { } getToolchainByName(name: ToolchainName): IToolchian | undefined { + //! 'Keil_C51' 大小写问题的补丁 + if (name.toLowerCase() == 'keil_c51') + return this.toolchainMap.get('Keil_C51'); return this.toolchainMap.get(name); } @@ -426,7 +430,7 @@ export class ToolchainManager { } getToolchainPrefix(toolchainName: ToolchainName): string | undefined { - const toolchain = this.toolchainMap.get(toolchainName); + const toolchain = this.getToolchainByName(toolchainName); if (toolchain && toolchain.getToolchainPrefix) { return toolchain.getToolchainPrefix(); } @@ -532,6 +536,121 @@ class KeilC51 implements IToolchian { } } + /* + Program Size: data=82.4 xdata=0 const=19 code=1644 + */ + private _parseMap(mapPath: string): { + sections: string[], + objDic: { + [name: string]: { [section: string]: number } + }, + } { + + const objDic: any = {}; + const secList: string[] = [ 'Size' ]; + + const lines = fs.readFileSync(mapPath).toString().split(/\r\n|\n/); + for (const line of lines) { + const m = /Program Size: data=(?<data>[\d+\.]+) xdata=(?<xdata>\d+) const=(?<const>\d+) code=(?<code>\d+)/.exec(line); + if (m && m.groups) { + for (const key in m.groups) { + const val = m.groups[key]; + const size = val.includes('.') ? parseFloat(val) : parseInt(val); + if (!objDic[key]) objDic[key] = {}; + objDic[key]['Size'] = size; + } + break; + } + } + + return { + sections: secList, + objDic: objDic + }; + }; + + parseMapFile(mapPath: string): string[] | Error { + + if (!File.IsFile(mapPath)) + return new Error(`No such file: ${mapPath}`); + + const mapInfo = this._parseMap(mapPath); + const secList = mapInfo.sections; + const objDic = mapInfo.objDic; + + let oldObjDic: any = {}; + if (File.IsFile(mapPath + '.old')) { + const inf = this._parseMap(mapPath + '.old'); + oldObjDic = inf.objDic; + } + + const tableRows: string[][] = []; + + // push header + let header: string[] = []; + header.push('Section'); + header = header.concat(secList); + tableRows.push(header); + + let objTotalSize: any = { new: 0, old: 0 }; + let secTotalSize: any = {}; + for (const objpath in objDic) { + + const objInfo = objDic[objpath]; + const row: string[] = [objpath]; + + let totalSize = 0; + for (const key in objInfo) { + totalSize += objInfo[key]; + } + + let oldInfo: any = {}; + if (oldObjDic[objpath]) { + oldInfo = oldObjDic[objpath]; + } + + let oldTotalSize = 0; + for (const key in oldInfo) { + oldTotalSize += oldInfo[key]; + } + + objTotalSize.new += totalSize; + objTotalSize.old += oldTotalSize; + + for (const sec of secList) { + + const oldSecSize = oldInfo[sec] ? oldInfo[sec] : 0; + const nowSecSize = objInfo[sec] ? objInfo[sec] : 0; + + const diffSize = nowSecSize - oldSecSize; + if (diffSize.toString().indexOf(".") != -1) { + row.push(nowSecSize.toString() + `(${diffSize > 0 ? '+' : ''}${diffSize.toFixed(1)})`); + } else { + row.push(nowSecSize.toString() + `(${diffSize > 0 ? '+' : ''}${diffSize.toString()})`); + } + + if (secTotalSize[sec] == undefined) { + secTotalSize[sec] = { + new: 0, + old: 0 + }; + }; + + secTotalSize[sec].new += nowSecSize; + secTotalSize[sec].old += oldSecSize; + } + + tableRows.push(row); + } + + const tableLines = utility.makeTextTable(tableRows); + if (tableLines == undefined) { + return new Error(`Nothing for this map: ${mapPath} !`); + } + + return tableLines; + } + getInternalDefines<T extends BuilderConfigData>(builderCfg: T, builderOpts: BuilderOptions): string[] { return []; } @@ -706,6 +825,135 @@ class SDCC implements IToolchian { options["asm-compiler"]['$toolName'] = asmName; } + /* + Area Addr Size Decimal Bytes (Attributes) + -------------------------------- ---- ---- ------- ----- ------------ + GSINIT0 00000006 00000003 = 3. bytes (REL,CON,CODE) + + Value Global Global Defined In Module + ----- -------------------------------- ------------------------ + C: 00000006 __sdcc_gsinit_startup + */ + private _parseMap(mapPath: string): { + sections: string[], + objDic: { + [name: string]: { [section: string]: number } + }, + } { + + const objDic: any = {}; + const secList: string[] = [ 'Size' ]; + + const lines = fs.readFileSync(mapPath).toString().split(/\r\n|\n/); + let counter = 0; + for (const line of lines) { + if (counter == 2) { + const m = /^\s*(?<name>\w+)\s+(?<addr>(?:0x)?[a-f\d]+)\s+(?<size>(?:0x)?[a-f\d]+)\s+=\s+(?<size_dec>\d+)\./i.exec(line); + if (m && m.groups) { + const name = m.groups['name']; + const size_dec = m.groups['size_dec']; + if (size_dec) { + if (!objDic[name]) objDic[name] = {}; + objDic[name]['Size'] = parseInt(size_dec); + } + } + counter = 0; + } else if (counter == 1) { + if (/^\s*----/.test(line)) + counter = 2; + else + counter = 0; + } else { + if (/^\s*Area\s+Addr/.test(line)) + counter = 1; + else + counter = 0; + } + } + + return { + sections: secList, + objDic: objDic + }; + }; + + parseMapFile(mapPath: string): string[] | Error { + + if (!File.IsFile(mapPath)) + return new Error(`No such file: ${mapPath}`); + + const mapInfo = this._parseMap(mapPath); + const secList = mapInfo.sections; + const objDic = mapInfo.objDic; + + let oldObjDic: any = {}; + if (File.IsFile(mapPath + '.old')) { + const inf = this._parseMap(mapPath + '.old'); + oldObjDic = inf.objDic; + } + + const tableRows: string[][] = []; + + // push header + let header: string[] = []; + header.push('Section'); + header = header.concat(secList); + tableRows.push(header); + + let objTotalSize: any = { new: 0, old: 0 }; + let secTotalSize: any = {}; + for (const objpath in objDic) { + + const objInfo = objDic[objpath]; + const row: string[] = [objpath]; + + let totalSize = 0; + for (const key in objInfo) { + totalSize += objInfo[key]; + } + + let oldInfo: any = {}; + if (oldObjDic[objpath]) { + oldInfo = oldObjDic[objpath]; + } + + let oldTotalSize = 0; + for (const key in oldInfo) { + oldTotalSize += oldInfo[key]; + } + + objTotalSize.new += totalSize; + objTotalSize.old += oldTotalSize; + + for (const sec of secList) { + + const oldSecSize = oldInfo[sec] ? oldInfo[sec] : 0; + const nowSecSize = objInfo[sec] ? objInfo[sec] : 0; + const diffSize = nowSecSize - oldSecSize; + row.push(nowSecSize.toString() + `(${diffSize > 0 ? '+' : ''}${diffSize.toString()})`); + + if (secTotalSize[sec] == undefined) { + secTotalSize[sec] = { + new: 0, + old: 0 + }; + }; + + secTotalSize[sec].new += nowSecSize; + secTotalSize[sec].old += oldSecSize; + } + + tableRows.push(row); + } + + const tableLines = utility.makeTextTable(tableRows); + if (tableLines == undefined) { + return new Error(`Nothing for this map: ${mapPath} !`); + } + + return tableLines; + } + private parseCodeModel(conf: string): string | undefined { const mType = /\s*--model-(\w+)\s*/i.exec(conf); if (mType && mType.length > 1) { diff --git a/src/extension.ts b/src/extension.ts index 95a0e0a..cd24e07 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1728,8 +1728,10 @@ class MapViewEditorProvider implements vscode.CustomTextEditorProvider { for (let index = 0; index < lines.length; index++) { const line = lines[index]; lines[index] = line - .replace(/\((\+[^0]\d*)\)/g, `(<span class="success">$1</span>)`) - .replace(/\((\-[^0]\d*)\)/g, `(<span class="error">$1</span>)`) + .replace(/\((\+[^0][\d\.]*)\)/g, `(<span class="success">$1</span>)`) + .replace(/\((\-[^0][\d\.]*)\)/g, `(<span class="error">$1</span>)`) + .replace(/\((\+0\.\d+)\)/g, `(<span class="success">$1</span>)`) + .replace(/\((\-0\.\d+)\)/g, `(<span class="error">$1</span>)`) .replace(/^(\s*\|\s*)(Subtotals)/, `$1<span class="info">$2</span>`) .replace(/^(\s*Total)/, `\n$1`); }