Step to UEFI (156)UEFI 的表达式计算库

在软件工程领域,有一句著名的话,叫做“Don't Reinvent the Wheel”-----不要重复发明轮子。究其原因一方面是重复发明效率低下,另一方面是重新发明的轮子未必好用,也许发明之后发现轴承有问题,或者是有着各种瑕疵…….对于编程来说,“复用代码”有着更明确的好处。因此,如果有可能,我们希望更多秉承鲁迅先生提出的“拿来主义”在代码设计上。最近研究了一些C语言的库,得益于UEFI 的设计和 CLIB 的支持,大部分库都可以直接使用。今天介绍的是一个可以用于表达式计算的库:TinyExpr【参考1】。

首先是要将 TinyExpr Porting 到UEFI上,直接编译会出现一些 Error 和 Warning。经过研究,需要在 INF中加入下面的内容:
1.引入LibMath,否则一些 cos 之类的函数无法识别

[LibraryClasses]
  ShellCEntryLib
  UefiLib
  LibC
  LibStdio
  LibMath

 

2.关闭一些 Warning

[BuildOptions]
   MSFT:*_*_IA32_CC_FLAGS         = /Ze /wd4201 /wd4152 /wd4090 /wd4204 /wd4055 /wd4244
   MSFT:*_*_X64_CC_FLAGS          = /Ze /wd4201 /wd4152 /wd4090 /wd4204 /wd4055 /wd4244

 

其中 C4201 Warning【参考2】,是 VS 编译器的扩展特性,比如下面这样的定义,在正经的 C 中是不允许的,但是 VC 中做了扩展是可以的:

struct S  
{  
   float y;  
   struct  
   {  
      int a, b, c;  // C4201  
   };  
} z;

 

这样扩展之后,可以直接使用 z.a 和 z.b。

此外,tinyexpr.c 中有关于 NAN 的定义和StdLib中的 Math.h中的存在冲突。我的解决方法是先用 #undef NAN 取消之前的定义,再根据 VS 编译器中 Math.h 的定义重写一次,结果如下:

//#ifndef NAN
//#define NAN (0.0/0.0)
#undef NAN
#define NAN        ((float)(INFINITY * 0.0F))
//#endif    

最终测试代码如下:
#include <Library/BaseLib.h>
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/PrintLib.h>
#include <Library/ShellCEntryLib.h>
#include <Protocol/EfiShell.h>
#include <Library/ShellLib.h>
#include <stdio.h>
#include <math.h>
#include "tinyexpr.h"

/**
  Set the socket options

  @param [in] Argc  The number of arguments
  @param [in] Argv  The argument value array

  @retval  0        The application exited normally.
  @retval  Other    An error occurred.
**/
int
main (
  IN int Argc,
  IN char **Argv
  )
{
    const char *c = "sqrt(5^2+7^2+11^2+(8-2)^2)";
    double r = te_interp(c, 0);
    printf("The expression:\n\t%s\nevaluates to:\n\t%f\n", c, r);

    return 0;
}

 

上述代码计算表达式

结果如下:

完整的代码下载:
expr

参考:
1.https://github.com/codeplea/tinyexpr
2.https://msdn.microsoft.com/en-us/library/c89bw853.aspx

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注