在旧的嵌入式c / c ++代码上启用现代代码分析工具的使用

问题描述

如何在较旧的嵌入式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这样的人,他们回答了我的相关问题herehere,并提供了更完整的答案。

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

有两种选择