问题描述
如何在较旧的嵌入式c / c ++源代码上使用现代代码分析工具(例如SourceTrail),该工具最初用于诸如Micro-Controller的Hi-Tech C,PIC C,IAR Workbench之类的编译器,仅限于microchip的PIC,PIC16和PIC18系列。
为了支持微型微控制器的有限体系结构,嵌入式编译器的供应商不得不提出对c / c ++语言的扩展,这些扩展已经(或尚未采用)c语言规范。 / p>
// 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和here,并提供了更完整的答案。
short long
类型
首先,24位short long
类型是一个问题,因为在c规范中不存在等效项,并且因为该类型的两个字不能用#define
寻址。最初,我使用Perl将字符串short long
修改为所有特定于供应商的头文件的long
,如下所示:
perl -pi -e "s/(short long)/long/g" .h
注意,对于Windows上的Microchip MPLAB CX8编译器,头文件位于以下文件夹和子文件夹中:c:\ Program Files(x86)\ Microchip \ xc8 \ v1.33 \ include
但是后来我意识到永远不会单独使用short
类型,因此我决定使用short
来简单地删除#define short
部分。请注意,这将影响使用short
的所有内容,因此我在此答案中保留了这两种方法。
用@
定义的寄存器位和字节地址 @符号是一个特殊的问题,因为无法使用#define
重新定义它们,因此再次进行救援,这次使用两次通过处理两种不同的语法:
perl -pi -e "s/@\s*([0-9a-fA-FxX]+)/AT($1)/g" .h
perl -pi -e "s/[@] ?+([^;]*)/AT($1)/g" .h
这些方法实际上将@
中AT()
之后的所有内容包装起来,从而允许对其进行常规定义。
额外的关键字
最后一步是在编译器供应商提供的每个头文件中插入一个宏头。我最终得到了以下宏标头:
// 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
可以看出,只要MPLAB XC8编译器使用了头文件,所有非标准的东西都会被删除。唯一的例外是__bit
类型,它被重新定义为_Bool
类型-似乎可行。
完整的批处理脚本,可以在Windows上运行
当我在Windows上运行所有这些程序时,Perl单行代码实际上不像在Linux上那样工作,因此,为了处理每个头文件,我不得不将Perl命令分批包装为-循环,这非常慢。为了弥补这一点,我将所有内容合并为一个名为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($1)/g" %1
:: Exchange @ and wrap in parenthesis for any substring starting with @ and ending with ; in each header file.
perl -pi -e "s/[@] ?+([^;]*)/AT($1)/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
先决条件
Perl必须安装在Windows计算机上。我使用StrawberryPerl
编辑:
主要是固定的错别字。
说明了如何处理short long