允许在旧式嵌入式 c/c++ 代码上使用现代代码分析工具
Enable usage of modern code analysis tools on old-ish embedded c/c++ code
如何在老式嵌入式 c/c++ 源代码上使用现代代码分析工具,例如 SourceTrail,最初用于编译器,例如 Hi-Tech C、PIC C、IAR Workbench 适用于许多微控制器,不仅限于 Microchip 的 PIC、PIC16 和 PIC18 系列。
为了支持微型微控制器的有限架构,嵌入式编译器的供应商不得不提出 c/c++ 语言的扩展,这些语言已经(或尚未)在c语言规范.
这导致微控制器特定的头文件包含如下内容:
// Register: ANSELA
extern volatile unsigned char ANSELA @ 0xF38;
#ifndef _LIB_BUILD
asm("ANSELA equ 0F38h");
#endif
typedef union {
struct {
unsigned ANSB0 :1;
unsigned ANSB1 :1;
unsigned ANSB2 :1;
unsigned ANSB3 :1;
unsigned ANSB4 :1;
unsigned ANSB5 :1;
};
} ANSELBbits_t;
extern volatile ANSELBbits_t ANSELBbits @ 0xF39;
extern volatile unsigned short long TBLPTR @ 0xFF6;
extern volatile __bit ABDEN1 @ (((unsigned) &BAUDCON1)*8) + 0;
代码文件包括如下内容:
void interrupt high_priority InterruptVectorHigh(void)
{
}
void interrupt low_priority InterruptVectorLow(void)
{
}
用现代工具支持此源代码,同时确保源代码仍可用于原始编译器的最简单方法是什么?
编辑:
下面提供了答案。
下面的修复将使任何支持 C18 或 C2x 规范的编译器都能理解 c 代码。我(还)没有机会使用 C++ 进行测试,因此它们可能不完全符合任何 C++ 规范。
感谢@Antti Haapala、@Clifford 和@anastaciu 等人回答了我的相关问题 here and here 并启用了这个更完整的答案。
short long
类型
首先,24 位 short long
类型是个问题,因为 c-specifications 中不存在等价物,而且该类型的两个字无法用 [=16] 寻址=].起初,我使用 Perl 简单地将字符串 short long
修改为所有 vendor-specific header 文件的 long
,如下所示:
perl -pi -e "s/(short long)/long/g" .h
Note, for the Microchip MPLAB CX8 compiler on Windows the header files are located in the following folder and sub-folders: c:\Program Files (x86)\Microchip\xc8\v1.33\include
但后来我意识到 short
类型从来没有单独使用过,所以我决定使用 #define short
简单地删除 short
部分。请注意,这会影响使用 short
的所有内容,因此我在此答案中保留了这两种方法。
用@
定义的寄存器位和字节地址
@-signs 是一个特定的问题,因为它们不能使用 #define
重新定义,所以 perl 再次来拯救,这次使用两次传递来解决两种不同的语法:
perl -pi -e "s/@\s*([0-9a-fA-FxX]+)/AT()/g" .h
perl -pi -e "s/[@] ?+([^;]*)/AT()/g" .h
这些本质上是将 AT()
中 @
之后的任何内容包装起来,允许对其进行正常定义操作。
额外的关键字
最后一步是在编译器供应商提供的每个 header 文件中插入一个宏 header。我最终得到了以下宏 header:
// Hack to allow SourceTrail to be used on this source
#if defined __XC8
#define AT(address) @ address
#else
#define AT(address)
#define __bit _Bool
#define asm(assembly)
#define interrupt
#define short
#define high_priority
#define low_priority
#endif
可以看出,任何 non-standard 都被简单地删除了,除非 header 文件被 MPLAB XC8 编译器使用。唯一的例外是 __bit
类型,它被重新定义为 _Bool
类型 - 它似乎可以工作。
在 windows
上对 运行 的批处理脚本的完整修复
因为我 运行 在 windows 上完成所有这些,Perl one-liners 并没有像在 Linux 上那样工作,所以为了处理每个每个 header 文件,我都必须将 Perl 命令包装在批处理 for-loop 中,这非常慢。为了弥补这一点,我将所有内容组合在一个名为 fix.cmd
的批次中,该批次位于 include 文件夹中(参见上面的路径):
:: Fix to allow SourceTrail to analyze MPLAB CX8 source code.
@echo off
setlocal enabledelayedexpansion
:: Run in the folder where the script exists.
pushd "%~dp0"
echo:Fixing MPLAB global include files to be used by SourceTrail and other analysis tools.
:: Loop each directory recrusively
set DirCounter=0
set FileCounter=0
for /r %%d in (.) do (
set /A DirCounter=DirCounter+1
pushd %%d
echo | set /p=Processing:
cd
for %%f in (*.h) do (
set /A FileCounter=FileCounter+1
set /A ModValue=FileCounter%%25
if !ModValue!==0 ( echo | set /p=* )
call :ProcessFile %%f
)
popd
echo *
)
echo:Processed %FileCounter% files in %DirCounter% folders.
echo Done
exit /b 0
:ProcessFile
:: filename is in %1
:: Remove short from short long. (Done with a define instead)
:: perl -pi -e "s/(short long)/long/g" %1
:: Replace the simple @ lines with AT().
perl -pi -e "s/@\s*([0-9a-fA-FxX]+)/AT()/g" %1
:: Exchange @ and wrap in parenthesis for any substring starting with @ and ending with ; in each header file.
perl -pi -e "s/[@] ?+([^;]*)/AT()/g" %1
:: Insert defines before first line in each header files:
perl -pi -e "print \"// Hack to allow SourceTrail to be used on this source\n#if defined __XC8\n #define AT(address) @ address\n#else\n #define AT(address)\n #define __bit _Bool\n #define asm(assembly)\n #define interrupt\n #define short\n#define high_priority\n #define low_priority\n#endif\n\n\" if $. == 1" %1
::Exit subroutine
exit /b
要执行修改,请打开提升的提示符,cd 到包含文件,然后执行 fix.cmd
先决条件
必须在 Windows 计算机上安装 Perl。我使用 StrawberryPerl
编辑:
主要是固定错别字。
阐明了如何处理 short long
有两个选项
如何在老式嵌入式 c/c++ 源代码上使用现代代码分析工具,例如 SourceTrail,最初用于编译器,例如 Hi-Tech C、PIC C、IAR Workbench 适用于许多微控制器,不仅限于 Microchip 的 PIC、PIC16 和 PIC18 系列。
为了支持微型微控制器的有限架构,嵌入式编译器的供应商不得不提出 c/c++ 语言的扩展,这些语言已经(或尚未)在c语言规范.
这导致微控制器特定的头文件包含如下内容:
// Register: ANSELA
extern volatile unsigned char ANSELA @ 0xF38;
#ifndef _LIB_BUILD
asm("ANSELA equ 0F38h");
#endif
typedef union {
struct {
unsigned ANSB0 :1;
unsigned ANSB1 :1;
unsigned ANSB2 :1;
unsigned ANSB3 :1;
unsigned ANSB4 :1;
unsigned ANSB5 :1;
};
} ANSELBbits_t;
extern volatile ANSELBbits_t ANSELBbits @ 0xF39;
extern volatile unsigned short long TBLPTR @ 0xFF6;
extern volatile __bit ABDEN1 @ (((unsigned) &BAUDCON1)*8) + 0;
代码文件包括如下内容:
void interrupt high_priority InterruptVectorHigh(void)
{
}
void interrupt low_priority InterruptVectorLow(void)
{
}
用现代工具支持此源代码,同时确保源代码仍可用于原始编译器的最简单方法是什么?
编辑:
下面提供了答案。
下面的修复将使任何支持 C18 或 C2x 规范的编译器都能理解 c 代码。我(还)没有机会使用 C++ 进行测试,因此它们可能不完全符合任何 C++ 规范。
感谢@Antti Haapala、@Clifford 和@anastaciu 等人回答了我的相关问题 here and here 并启用了这个更完整的答案。
short long
类型
首先,24 位 short long
类型是个问题,因为 c-specifications 中不存在等价物,而且该类型的两个字无法用 [=16] 寻址=].起初,我使用 Perl 简单地将字符串 short long
修改为所有 vendor-specific header 文件的 long
,如下所示:
perl -pi -e "s/(short long)/long/g" .h
Note, for the Microchip MPLAB CX8 compiler on Windows the header files are located in the following folder and sub-folders: c:\Program Files (x86)\Microchip\xc8\v1.33\include
但后来我意识到 short
类型从来没有单独使用过,所以我决定使用 #define short
简单地删除 short
部分。请注意,这会影响使用 short
的所有内容,因此我在此答案中保留了这两种方法。
用@
定义的寄存器位和字节地址@-signs 是一个特定的问题,因为它们不能使用 #define
重新定义,所以 perl 再次来拯救,这次使用两次传递来解决两种不同的语法:
perl -pi -e "s/@\s*([0-9a-fA-FxX]+)/AT()/g" .h
perl -pi -e "s/[@] ?+([^;]*)/AT()/g" .h
这些本质上是将 AT()
中 @
之后的任何内容包装起来,允许对其进行正常定义操作。
额外的关键字
最后一步是在编译器供应商提供的每个 header 文件中插入一个宏 header。我最终得到了以下宏 header:
// Hack to allow SourceTrail to be used on this source
#if defined __XC8
#define AT(address) @ address
#else
#define AT(address)
#define __bit _Bool
#define asm(assembly)
#define interrupt
#define short
#define high_priority
#define low_priority
#endif
可以看出,任何 non-standard 都被简单地删除了,除非 header 文件被 MPLAB XC8 编译器使用。唯一的例外是 __bit
类型,它被重新定义为 _Bool
类型 - 它似乎可以工作。
在 windows
上对 运行 的批处理脚本的完整修复因为我 运行 在 windows 上完成所有这些,Perl one-liners 并没有像在 Linux 上那样工作,所以为了处理每个每个 header 文件,我都必须将 Perl 命令包装在批处理 for-loop 中,这非常慢。为了弥补这一点,我将所有内容组合在一个名为 fix.cmd
的批次中,该批次位于 include 文件夹中(参见上面的路径):
:: Fix to allow SourceTrail to analyze MPLAB CX8 source code.
@echo off
setlocal enabledelayedexpansion
:: Run in the folder where the script exists.
pushd "%~dp0"
echo:Fixing MPLAB global include files to be used by SourceTrail and other analysis tools.
:: Loop each directory recrusively
set DirCounter=0
set FileCounter=0
for /r %%d in (.) do (
set /A DirCounter=DirCounter+1
pushd %%d
echo | set /p=Processing:
cd
for %%f in (*.h) do (
set /A FileCounter=FileCounter+1
set /A ModValue=FileCounter%%25
if !ModValue!==0 ( echo | set /p=* )
call :ProcessFile %%f
)
popd
echo *
)
echo:Processed %FileCounter% files in %DirCounter% folders.
echo Done
exit /b 0
:ProcessFile
:: filename is in %1
:: Remove short from short long. (Done with a define instead)
:: perl -pi -e "s/(short long)/long/g" %1
:: Replace the simple @ lines with AT().
perl -pi -e "s/@\s*([0-9a-fA-FxX]+)/AT()/g" %1
:: Exchange @ and wrap in parenthesis for any substring starting with @ and ending with ; in each header file.
perl -pi -e "s/[@] ?+([^;]*)/AT()/g" %1
:: Insert defines before first line in each header files:
perl -pi -e "print \"// Hack to allow SourceTrail to be used on this source\n#if defined __XC8\n #define AT(address) @ address\n#else\n #define AT(address)\n #define __bit _Bool\n #define asm(assembly)\n #define interrupt\n #define short\n#define high_priority\n #define low_priority\n#endif\n\n\" if $. == 1" %1
::Exit subroutine
exit /b
要执行修改,请打开提升的提示符,cd 到包含文件,然后执行 fix.cmd
先决条件
必须在 Windows 计算机上安装 Perl。我使用 StrawberryPerl
编辑:
主要是固定错别字。
阐明了如何处理 short long