zoukankan      html  css  js  c++  java
  • yacc解析conf

    my.conf

    globals {
    name XXX;
    home XXX;

    ok on;

    health {
    good;
    }

    }

    other {
    iqn iqn.2015-10-10.com.name;
    }

    Makefile

    FLEX = flex
    YACC = bison
    YFLAGS = -d
    CC = gcc

    BUILT_SOURCES = confl.c confy.c confy.h
    CONFIGURE_SOURCE = configure.c configure.h
    TEST_SOURCE = test.c

    TARGET = test

    $(TARGET):lex
    $(CC) -o $@ $(TEST_SOURCE) $(BUILT_SOURCES) $(CONFIGURE_SOURCE)

    lex:yacc
    $(FLEX) -o confl.c confl.l
    yacc:
    $(YACC) -o confy.c -d confy.y

    .PHONY:clean
    clean:
    -rm -f confl.c confy.c confy.h $(TARGET)

    test.c

    #include <stdio.h>
    #include "configure.h"


    int main(int argc, char *argv[])
    {
    conf_init();
    printf("name: %s ", glo_conf.name);
    conf_destroy();
    return 0;
    }

    configure.c

    #include <stdio.h>
    #include <unistd.h>
    #include <errno.h>
    #include <stdlib.h>
    #include <string.h>

    #include "configure.h"
    #include "confy.h"

    extern FILE *yyin;

    int line = 1;

    healthconf_t health_conf;
    struct otherconf_t other_conf;
    struct gloconf_t glo_conf;

    static char config_path[MAXSIZE];


    int get_health(const char *health)
    {
    if (health != NULL) {
    strncpy(health_conf.health, health, MAXSIZE);
    health_conf.count++;
    }
    return 0;
    }

    void yyerror(const char *str)
    {
    fprintf(stderr, "config: parse %s error at line %d, %s ",
    config_path, line, str);

    exit(1);
    }

    int yywrap() {
    return 1;
    }

    extern int yyparse();

    int conf_init()
    {
    int ret;
    char cwd[MAXSIZE];
    getcwd(cwd, MAXSIZE);

    snprintf(config_path, MAXSIZE, "%s/my.conf", cwd);


    /* default */
    memset(glo_conf.name, 0x0, MAXSIZE);
    strcpy(glo_conf.name, "none");
    strcpy(other_conf.iqn, "none");
    glo_conf.ok = 1;

    memset(health_conf.health, 0x0, MAXSIZE);
    strcpy(health_conf.health, "none");
    health_conf.count = 0;

    yyin = fopen(config_path, "r");
    if (yyin == NULL) {
    ret = errno;
    fprintf(stderr, "open %s fail, ret %u ", config_path, ret);
    goto err_ret;
    }


    yyparse();

    return 0;
    err_ret:
    return ret;
    }


    int conf_destroy(void)
    {
    fclose(yyin);

    return 0;
    }

    LLU str2val(const char *str)
    {
    LLU val;
    val = atoll(str);
    return val;
    }


    int keyis(const char *src, const char *dst)
    {
    int dstlen;

    dstlen = strlen(dst);

    if (strncmp(src, dst, dstlen) == 0)
    return 1;
    else
    return 0;
    }

    int set_value(const char* key, const char* value, int type)
    {
    int vallen;
    LLU _value;

    vallen = strlen(value);

    if (type == V_NUMBER)
    _value = str2val(value);
    else if (type == V_STATE) {
    if (strncasecmp("on", value, vallen) == 0)
    _value = 1;
    else
    _value = 0;
    }

    /**
    * other configure
    */
    else if (keyis("iqn", key))
    strncpy(other_conf.iqn, value, MAXSIZE);
    else if (keyis("health", key)) {
    strncpy(health_conf.health, value, MAXSIZE);
    health_conf.count++;
    }

    /**
    * global configure
    */
    else if (keyis("name", key))
    strncpy(glo_conf.name, value, MAXSIZE);
    else if (keyis("home", key))
    strncpy(glo_conf.home, value, MAXSIZE);
    else if (keyis("ok", key))
    glo_conf.ok = _value;

    /**
    * error.
    */
    else {
    fprintf(stderr, "%s:%s no such key_value ", key, value);
    }

    return 0;
    }

    configure.h

    #ifndef __CONFIGURE_H__
    #define __CONFIGURE_H__

    #include <stdint.h>
    #define MAXSIZE 256
    typedef unsigned long long LLU;

    enum value_type {
    V_STATE,
    V_NUMBER,
    V_STRING,
    };


    typedef struct {
    int count;
    char health[MAXSIZE];
    }healthconf_t;

    /* other configure */
    struct otherconf_t
    {
    char iqn[MAXSIZE];
    };

    /* global configure */
    struct gloconf_t
    {
    char name[MAXSIZE];
    char home[MAXSIZE];
    int ok;
    };

    extern int conf_init(void);
    extern int conf_destroy(void);

    extern healthconf_t health_conf;
    extern struct otherconf_t other_conf;
    extern struct gloconf_t glo_conf;

    #endif

    confl.l

    %{
    #include <stdio.h>
    #include "configure.h"
    #include "confy.h"

    extern int line;
    %}

    %%
    "globals" { return GLOBALS; }
    "other" { return OTHER; }

    "health" {
    yylval.string = strdup(yytext);
    return HEALTH;
    }

    "on" {
    yylval.string = strdup(yytext);
    return STATE;
    }

    "of" {
    yylval.string = strdup(yytext);
    return STATE;
    }

    [0-9]+ {
    yylval.string = strdup(yytext);
    return NUMBER;
    }

    [a-zA-Z0-9_]{0,512} {
    yylval.string = strdup(yytext);
    return WORD;
    }

    iqn.[0-9]{4}-[0-9]{2}(-[0-9]{1,4})?.com.[a-zA-Z0-9_]+ {
    yylval.string = strdup(yytext);
    return IQN;
    }

    [()] { return *yytext; }
    { { return OBRACE; }
    } { return EBRACE; }
    { line++; }
    ; { return SEMICOLON; }
    [ ]+ /** ignore whitespace */
    #[^ ]* /** ignore comment */
    . {
    fprintf(stderr, "unkonw char %c ", *yytext);
    return 0;
    }

    %%

    confy.y

    %{
    #include <stdio.h>
    #include "configure.h"

    extern int yylex(void);
    extern void yyerror(char *s);
    extern int get_health(const char *health);
    extern int set_value(const char* key, const char* value, int type);
    %}

    %defines

    %union {
    double value;
    char *string;
    }

    %token OTHER GLOBALS SEMICOLON OBRACE EBRACE
    %token <string> HEALTH
    %token <string> WORD
    %token <string> STATE
    %token <string> NUMBER
    %token <string> IQN

    %start conf

    %%

    conf: subapps
    ;
    subapps: subapp
    | subapps subapp
    ;

    subapp: app app_subsets
    ;

    app: OTHER
    | GLOBALS
    ;

    app_subsets: OBRACE local_values sub_values EBRACE
    ;

    local_values:
    | local_values local_value
    ;

    local_value: key_value SEMICOLON
    ;

    sub_values:
    | sub_value sub_values
    ;

    // sub
    sub_value: healths_value
    ;

    healths_value: HEALTH OBRACE healths_lines EBRACE
    ;

    healths_lines: healths_line
    | healths_lines healths_line
    ;

    healths_line: WORD SEMICOLON {
    get_health($1);
    free($1);
    }
    ;

    key_value: WORD NUMBER {
    set_value($1, $2, V_NUMBER);
    free($1);
    free($2);
    }
    ;

    key_value: WORD WORD {
    set_value($1, $2, V_STRING);
    free($1);
    free($2);
    }
    ;

    key_value: WORD STATE {
    set_value($1, $2, V_STATE);
    free($1);
    free($2);
    }
    ;
    key_value: WORD IQN {
    set_value($1, $2, V_STRING);
    free($1);
    free($2);
    }
    ;
    %%

  • 相关阅读:
    actionbar
    记:使用Xenocode加壳混淆后,无法“自杀覆盖”的自动更新
    用c# 实现设计器 DesignSurface
    将C#程序嵌入资源中(C# 调用嵌入资源的EXE文件方法)
    【转】给自己的软件制作注册码
    免费的Web Service网址
    MS SQL 2005/8 无法远程连接的解决方案【留】
    IIS 部署 ASP.NET 的一个注意点
    成语验证
    C#利用msscript.ocx控件执行JS脚本
  • 原文地址:https://www.cnblogs.com/banwhui/p/4867775.html
Copyright © 2011-2022 走看看