Step to UEFI (192)UEFI Shell 下实现 INI 文件的解析

INI 文件是一种有简单格式的文本文件(ASCII),可以用来提供一些配置信息。比如下面这个文件:

; exp ini file
[port]
Portname=COM4
Port=4
[settings]
Baud=115200 ;Speed

第一行是注释。然后  port 和 settings 都被称作 section。其中的 Portname Port 和 Baud 都是 Key,相应的,每一个 Key 都有 value 。

虽然这样的结构并不复杂,但是如果完全自己来写还是很麻烦的。经过搜索,找到了 iniparser 【参考1】这个开源项目。对应的库需要有一点修改才能编译成功, iniparser.c 中需要如下改动:  

return last - s;    ---->    return (unsigned int) (last - s);

根据例子编写的测试代码:

#include  <Uefi.h>
#include  <Library/BaseLib.h>
#include  <Library/UefiLib.h>
#include  <Library/ShellCEntryLib.h>

#include "iniparser.h"

extern  EFI_SYSTEM_TABLE    *gST;
extern  EFI_BOOT_SERVICES   *gBS;


void create_example_ini_file(void)
{
    FILE    *   ini ;
    if ((ini=fopen("example.ini", "w"))==NULL) {
        fprintf(stderr, "iniparser: cannot create example.ini\n");
        return ;
    }

    fprintf(ini,
    "#\n"
    "# This is an example of ini file\n"
    "#\n"
    "\n"
    "[Pizza]\n"
    "\n"
    "Ham       = yes ;\n"
    "Mushrooms = TRUE ;\n"
    "Capres    = 0 ;\n"
    "Cheese    = Non ;\n"
    "\n"
    "\n"
    "[Wine]\n"
    "\n"
    "Grape     = Cabernet Sauvignon ;\n"
    "Year      = 1989 ;\n"
    "Country   = Spain ;\n"
    "Alcohol   = 12.5  ;\n"
    "\n");
    fclose(ini);
}


int parse_ini_file(char * ini_name)
{
    dictionary  *   ini ;

    /* Some temporary variables to hold query results */
    int             b ;
    int             i ;
    double          d ;
    const char  *   s ;

    ini = iniparser_load(ini_name);
    if (ini==NULL) {
        fprintf(stderr, "cannot parse file: %s\n", ini_name);
        return -1 ;
    }
    iniparser_dump(ini, stderr);

    /* Get pizza attributes */
    printf("Pizza:\n");

    b = iniparser_getboolean(ini, "pizza:ham", -1);
    printf("Ham:       [%d]\n", b);
    b = iniparser_getboolean(ini, "pizza:mushrooms", -1);
    printf("Mushrooms: [%d]\n", b);
    b = iniparser_getboolean(ini, "pizza:capres", -1);
    printf("Capres:    [%d]\n", b);
    b = iniparser_getboolean(ini, "pizza:cheese", -1);
    printf("Cheese:    [%d]\n", b);

    /* Get wine attributes */
    printf("Wine:\n");
    s = iniparser_getstring(ini, "wine:grape", NULL);
    printf("Grape:     [%s]\n", s ? s : "UNDEF");

    i = iniparser_getint(ini, "wine:year", -1);
    printf("Year:      [%d]\n", i);

    s = iniparser_getstring(ini, "wine:country", NULL);
    printf("Country:   [%s]\n", s ? s : "UNDEF");

    d = iniparser_getdouble(ini, "wine:alcohol", -1.0);
    printf("Alcohol:   [%g]\n", d);

    iniparser_freedict(ini);
    return 0 ;
}

/***
  Print a welcoming message.

  Establishes the main structure of the application.

  @retval  0         The application exited normally.
  @retval  Other     An error occurred.
***/
INTN
EFIAPI
main (
  IN UINTN Argc,
  IN CHAR8 **Argv
  )
{
    int     status ;

    if (Argc<2) {
        create_example_ini_file();
        status = parse_ini_file("example.ini");
    } else {
        status = parse_ini_file(Argv[1]);
    }
    return status ;
}

因为用到的fopen ,所以需要特别加入  DevShell 在LibraryClasses 中

[Defines]
  INF_VERSION                    = 0x00010006
  BASE_NAME                      = init
  FILE_GUID                      = a912f198-7f0e-4805-b90A-b757b806ec85
  MODULE_TYPE                    = UEFI_APPLICATION
  VERSION_STRING                 = 0.1
  ENTRY_POINT                    = ShellCEntryLib

#
#  VALID_ARCHITECTURES           = IA32 X64
#

[Sources]
  INITest.c
  iniparser.c
  iniparser.h
  dictionary.h
  dictionary.c

[Packages]
  MdePkg/MdePkg.dec
  ShellPkg/ShellPkg.dec
  StdLib/StdLib.dec
  
[LibraryClasses]
  UefiLib
  ShellCEntryLib
  IoLib
  LibC
  LibStdio
  DevShell

运行结果:

不加参数会读取example.ini

加入参数可以读取指定文件:

完整的代码下载:

参考:

1.https://github.com/ndevilla/iniparser

发表回复

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