Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15317097
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类: 嵌入式

2009-07-08 16:33:01

浅析minigui-1.6.10启动脚本MiniGUI.cfg加载和section解析

《浅析MiniGuI v1.62配置文件MiniGUI.cfg所在目录获取的先后优先级》

//=======================================================
//看看对hMgEtc实际使用
static inline int GetMgEtcValue(const char* pSection,
                const char *pKey, char *pValue, int iLen)
{
#ifndef _INCORE_RES
    if (!hMgEtc)
        return GetValueFromEtcFile (ETCFILEPATH, pSection, pKey, pValue, iLen);
#endif

    return GetValueFromEtc (hMgEtc, pSection, pKey, pValue, iLen);
}

industrialsample/libminigui-1.6.10/src/kernel/event.c
static void GetDblclickTime(void)
{
    char szValue[11];
    int ms;

    dblclicktime = DEF_MSEC_DBLCLICK / 10;
// Mouse event parameters.
// #define MOUSEPARA                           "mouse"
// #define MOUSEPARA_DBLCLICKTIME              "dblclicktime"
// 在MiniGUI.cfg中有如下节
// [mouse]
// dblclicktime=300
// 读取section名为mouse下key为dblclicktime的键值
    if( GetMgEtcValue (MOUSEPARA, MOUSEPARA_DBLCLICKTIME, szValue, 10) < 0 )
        return;

    ms = atoi(szValue);

    if (ms > 0 && ms < 1000) {
        dblclicktime = ms / 10;
    }
}
再来看看cursor指针的例子
BOOL realInitCursor(void)
{

    ......
    // #define CURSORSECTION    "cursorinfo"
    // 查找节名为cursorinfo,key为cursornumber的键值
    // 在MiniGUI.cfg中有如下节
    // [cursorinfo]
    // cursorpath=/usr/local/lib/minigui/res/cursor/
    // cursornumber=23
    // cursor0=d_arrow.cur
    // cursor1=d_beam.cur
    // cursor2=d_pencil.cur
    // cursor3=d_cross.cur
    // cursor4=d_move.cur
    // cursor5=d_sizenwse.cur
    // cursor6=d_sizenesw.cur
    // cursor7=d_sizewe.cur
    // cursor8=d_sizens.cur
    // cursor9=d_uparrow.cur
    // cursor10=d_none.cur
    // cursor11=d_help.cur
    // cursor12=d_busy.cur
    // cursor13=d_wait.cur
    // cursor14=g_rarrow.cur
    // cursor15=g_col.cur
    // cursor16=g_row.cur
    // cursor17=g_drag.cur
    // cursor18=g_nodrop.cur
    // cursor19=h_point.cur
    // cursor20=h_select.cur
    // cursor21=ho_split.cur
    // cursor22=ve_split.cur

    if( GetMgEtcValue (CURSORSECTION, "cursornumber", szValue, 10) < 0 )
        goto error;
    
    number = atoi(szValue); // cursornumber=23

    if(number <= 0)
        return TRUE;

    number = number < (MAX_SYSCURSORINDEX + 1) ?
             number : (MAX_SYSCURSORINDEX + 1);

    for(i = 0; i < number; i++) {
        if ( !(SysCursor[i] = LoadSystemCursor(i)) ) // 加载23个cursor资源
             goto error;
    }
   

    return TRUE;
error:
    TerminateCursor();
    return FALSE;
}

PCURSOR LoadSystemCursor (int i)
{
    PCURSOR tempcsr;

    char szValue[MAX_NAME + 1];
    char szPathName[MAX_PATH + 1];
    char szKey[10];
    // #define CURSORSECTION    "cursorinfo"
    // 查找节名为cursorinfo,key为cursorpath的键值
    // 在MiniGUI.cfg中有如下节
    // [cursorinfo]
    // cursorpath=/usr/local/lib/minigui/res/cursor/
    // cursornumber=23
    // cursor0=d_arrow.cur
    // cursor1=d_beam.cur
    // cursor2=d_pencil.cur
    // cursor3=d_cross.cur
    // ......
    if (GetMgEtcValue (CURSORSECTION, "cursorpath", szPathName, MAX_PATH) < 0)
                 goto error;

    sprintf (szKey, "cursor%d", i); // 获得key为cursor0 cursor1...等键值
    if (GetMgEtcValue (CURSORSECTION, szKey, szValue, MAX_NAME) < 0)
                goto error;

    strcat (szPathName, szValue); // 读取/usr/local/lib/minigui/res/cursor/d_cross.cur

    if (!(tempcsr = (PCURSOR)LoadCursorFromFile (szPathName))) // 加载到内存
                     goto error;

    return tempcsr;

error:
    return 0;
}
//=======================================================
//看看系统初始化
InitGUI==>InitMisc==>InitMgEtc

#ifndef _INCORE_RES
BOOL InitMgEtc (void)
{
    if (hMgEtc)
        return TRUE;

    if ( !(hMgEtc = LoadEtcFile (ETCFILEPATH)) ) // 获取MiniGUI.cfg中脚本数据,源码见后
// 数据以key和value,这种字典形式保存[luther.gliethttp]
// hMgEtc是指向ETC_S存储空间的指针,只是这里hMgEtc以int形式存在[luther.gliethttp]
        return FALSE;
    return TRUE;
}

/* Terminate MiniGUI etc file object */
void TerminateMgEtc (void)
{
    UnloadEtcFile (hMgEtc); // 释放内存
    hMgEtc = 0;
}

#else
// 使用built-in方式的配置
extern GHANDLE __mg_get_mgetc (void);

BOOL InitMgEtc (void)
{
#ifndef DYNAMIC_LOAD
    hMgEtc = __mg_get_mgetc (); // 获取MGETC全局量中定义的minigui资源配置信息,适合uc/os-ii或者FreeRTOS系统[lutehr.gliethttp]
#else
    hMgEtc = set_mgetc ();
#endif
    return TRUE;
}

void TerminateMgEtc (void) { }

#endif

#if defined (WIN32) || (defined (__THREADX__) && defined (__TARGET_VFANVIL__))
// 这里我们只关心MiniGUI.cfg脚本的加载和解析[luther.gliethttp]
GHANDLE GUIAPI LoadEtcFile (const char * pEtcFile)
{
    FILE* fp = NULL;
    ETC_S *petc;
    char *filebuf;
    char *pnextread;
    int  nReadByte, nFileSize, i;
#ifdef WIN32   
    struct stat filestat;
#endif
// 这里pEtcFile等于"/usr/local/etc/MiniGUI.cfg"

    if (pEtcFile && !(fp = fopen (pEtcFile, "r")))
         return 0;
   
    petc = (ETC_S*) malloc (sizeof(ETC_S));
   
    /* we allocate 15 sections first */
    // misc.h
    // #define NR_SECTS_INIT_ALLOC     16
    petc->sections = // 先大概其的申请16个section空间
            (PETCSECTION) malloc (sizeof(ETCSECTION)* NR_SECTS_INIT_ALLOC);

    petc->section_nr = 0; // 当前1个都没有登记,16个空间全部是空的[luther.gliethttp]
    petc->sect_nr_alloc = NR_SECTS_INIT_ALLOC; // 申请了16个

    if (pEtcFile == NULL) { /* return an empty etc object */
    // 此句判断没有意义,因为如果能执行到这里pEtcFile就一定非NULL
        return (GHANDLE) petc;
    }

#if defined (__THREADX__) && defined (__TARGET_VFANVIL__)
    nFileSize = tp_flength(fp);
#else
    fstat (fileno(fp), &filestat); // linux系统,获取MiniGUI.cfg文件大小[luther.gliethttp]
    nFileSize = filestat.st_size;
#endif

    if (nFileSize <= 0) {
        goto endflag;
    }

    filebuf = (char *)calloc (1, nFileSize + 1); // 申请清0内存
    if (filebuf == NULL)
        goto endflag;

    nReadByte = fread (filebuf, 1, nFileSize, fp); // 将MiniGUI.cfg内容一次性读入该内存
/*
    if (nReadByte != nFileSize) { // 既然不做判断,变量就应该删掉,看来minigui对无用代码的清理工作做得不甚好.
        goto endflag;
    }
*/
    filebuf [nFileSize] = '\0';
    for (i = 0; i< nFileSize; i++) {
        //if (filebuf [i] == '\n' || filebuf [i] == '\r')
        if (filebuf [i] == 0x0D || filebuf [i] == 0x0A)
            filebuf [i] = '\0'; // 每一行的'\r\n'均变为0,这样filebuf缓冲区就包含了
            // 众多字符串[每一行对应一个字符串][luther.gliethttp].
    }
   
    pnextread = filebuf; // 使用临时指针,
    while (etc_ReadSection (filebuf, nFileSize + 1, &pnextread,
                            petc->sections + petc->section_nr) == ETC_OK) {
        petc->section_nr ++;
        if (petc->section_nr == petc->sect_nr_alloc) {
            /* add 5 sections each time we realloc */
            petc->sect_nr_alloc += NR_SECTS_INC_ALLOC;
            petc->sections = realloc (petc->sections,
                            sizeof (ETCSECTION)*petc->sect_nr_alloc);
        }
    }

endflag:
    fclose (fp);
    free (filebuf); // 释放内存
    return (GHANDLE)petc;
}
#else
// 这才是ubuntu下实际使用到的函数呢,汗:(
GHANDLE GUIAPI LoadEtcFile (const char * pEtcFile)
{
    FILE* fp = NULL;
    ETC_S *petc;
// 这里pEtcFile等于"/usr/local/etc/MiniGUI.cfg"
    if (pEtcFile && !(fp = fopen (pEtcFile, "r")))
         return 0;

    petc = (ETC_S*) malloc (sizeof(ETC_S));
    petc->section_nr = 0; // 当前1个都没有登记,16个空间全部是空的[luther.gliethttp]
// misc.h
// #define NR_SECTS_INIT_ALLOC     16
    petc->sect_nr_alloc = NR_SECTS_INIT_ALLOC; // 先大概其的申请16个section空间

    /* we allocate 15 sections first */
    petc->sections =
            (PETCSECTION) malloc (sizeof(ETCSECTION)*NR_SECTS_INIT_ALLOC);

    if (pEtcFile == NULL) { /* return an empty etc object */
    // 此句判断没有意义,因为如果能执行到这里pEtcFile就一定非NULL
        return (GHANDLE) petc;
    }

    while (etc_ReadSection (fp, petc->sections + petc->section_nr) == ETC_OK) {
        // 向petc->section_nr[petc->section_nr]空间填入一个section信息.
        petc->section_nr ++; // 下一个内存区
        if (petc->section_nr == petc->sect_nr_alloc) {
            /* add 5 sections each time we realloc */
            // misc.h
            // #define NR_SECTS_INC_ALLOC      8
            petc->sect_nr_alloc += NR_SECTS_INC_ALLOC; // 那么重新申请16+8+...个
            petc->sections = realloc (petc->sections,
                            sizeof(ETCSECTION)*petc->sect_nr_alloc);
        }
    }

    fclose (fp);
    return (GHANDLE)petc; // ok, 我们已经解析完毕MiniGUI.cfg所有脚本信息,将petc地址转为int类型返回给hMgEtc.
}

static int etc_ReadSection (FILE* fp, PETCSECTION psect)
{
    char szBuff[ETC_MAXLINE + 1 + 1];
    char* sect_name;

    psect->name = NULL;
    psect->key_nr = 0;
    psect->keys = NULL;
    psect->values = NULL;

    while (TRUE) {
        int bufflen;

        if (!fgets(szBuff, ETC_MAXLINE, fp)) { // 读取一行数据
            if (feof (fp)) { // 判断是否文件结尾了
                if (psect->name)
                    break;
                else
                    return ETC_SECTIONNOTFOUND;
            }
            else
                return ETC_FILEIOFAILED;
        }

        bufflen = strlen (szBuff);
        if (szBuff [bufflen - 1] == '\n')
            szBuff [bufflen - 1] = '\0';

        if (!psect->name) { /* read section name */
            // 该psect内存空间还没有节名
            sect_name = get_section_name (szBuff); // 尝试从szBuff中获取节名,源码见后
            if (!sect_name) // 如果不是section name,那么continue,直到读取到一个合法的sect_name.
                continue;

            psect->name = FixStrDup (sect_name); // 调用FixStrAlloc()快速获取一块内存,之后拷贝sect_name到新内存空间
            psect->key_nr = 0; // 初始化section name下包含的key内存
            // misc.h
            // #define NR_KEYS_INIT_ALLOC      8
            // #define NR_KEYS_INC_ALLOC       4
            psect->key_nr_alloc = NR_KEYS_INIT_ALLOC; // 申请8个key所需空间
            // 之后按4个key大小增长该空间.
            psect->keys = malloc (sizeof (char*) * NR_KEYS_INIT_ALLOC);
            psect->values = malloc (sizeof (char*) * NR_KEYS_INIT_ALLOC);
        }
        else { /* read key and value */
            int ret;
            char *key, *value;
            // 该section 已经有了名字,那么填充该section管理的属性值[luther.gliethttp]

            ret = get_key_value (szBuff, &key, &value); // 源码见后
            if (ret < 0) // 小于0表示此行无效,continue继续读取下一行
                continue;
            else if (ret > 0) {  /* another section begins */
                // 大于0表示下一个section开始符号'['被发现,此section所管理的内容到此结束
                // 退回读取到的改行数据,fp指针调整[lutehr.gliethttp]
                fseek (fp, -bufflen, SEEK_CUR);
                break;
            }

            etc_NewKeyValue (psect, key, value); // 将该字典数据存入该psect所在内存空间,源码见后[luther.gliethttp]
        }
    }

    return ETC_OK;
}
#endif

static char* get_section_name (char *section_line)
{
    char* current;
    char* name;

    if (!section_line)
        return NULL;

    current = section_line; // 一串字符串

    while (*current == ' ' ||  *current == '\t') current++; // 忽略空格和tab

    if (*current == ';' || *current == '#') // 是否为注释
        return NULL;

    if (*current++ == '[') // 是否以[开头(这是有效section name的开始)
        while (*current == ' ' ||  *current == '\t') current ++; // 过滤空格和tab
    else
        return NULL; // 不是以[开头,那么此行字符串不是section name,直接返回.

    name = current; // ok, 现在current处在有效名字的第一个字符.
    while (*current != ']' && *current != '\n' &&
          *current != ';' && *current != '#' && *current != '\0')
          current++; // 寻找section名字的结尾[luther.gliethttp]
    *current = '\0'; // 截断字符串,这样name有了有效的字符串结尾0.
    while (*current == ' ' || *current == '\t') {
        *current = '\0'; // shorten name.
        current--;
    }

    return name;
}

static int get_key_value (char *key_line, char **mykey, char **myvalue)
{
    char* current;
    char* tail;
    char* value;

    if (!key_line)
        return -1;

    current = key_line; // 一行字符串

    while (*current == ' ' ||  *current == '\t') current++;

    if (*current == ';' || *current == '#')
        return -1; // 为注释行

    if (*current == '[') // 为新的section
        return 1;

    if (*current == '\n' || *current == '\0')
        return -1; // 一个只有回车的空行

    tail = current;
    // 寻找等号'='
    while (*tail != '=' && *tail != '\n' &&
          *tail != ';' && *tail != '#' && *tail != '\0')
          tail++;

    value = tail + 1; // 数据位于等号后面
    if (*tail != '=')
        *value = '\0';

    *tail-- = '\0';
    while (*tail == ' ' || *tail == '\t') {
        *tail = '\0';
        tail--;
    }
       
    tail = value;
    while (*tail != '\n' && *tail != '\0') tail++;
    *tail = '\0';

    if (mykey)
        *mykey = current; // key值,已经在'='所在位置填入字符串结尾符'\0'
    if (myvalue)
        *myvalue = value;

    return 0;
}

static void etc_NewKeyValue (PETCSECTION psect,
                const char* key, const char* value)
{
    if (psect->key_nr == psect->key_nr_alloc) {
        // 如果申请的key[]内存空间已经全部填充,那么realloc重新多申请8个key空间
        psect->key_nr_alloc += NR_KEYS_INC_ALLOC;
        psect->keys = realloc (psect->keys,
                            sizeof (char*) * psect->key_nr_alloc);
        psect->values = realloc (psect->values,
                            sizeof (char*) * psect->key_nr_alloc);
    }

    psect->keys [psect->key_nr] = FixStrDup (key); // 调用FixStrAlloc()快速获取一块内存,之后拷贝sect_name到新内存空间
    psect->values [psect->key_nr] = FixStrDup (value); // 调用FixStrAlloc()快速获取一块内存,之后拷贝sect_name到新内存空间

    psect->key_nr++;
}

int GUIAPI UnloadEtcFile (GHANDLE hEtc)
{
    int i;
    ETC_S *petc = (ETC_S*) hEtc;

    if (!petc)
        return -1;
    // 一共section_nr个section
    for (i=0; isection_nr; i++) {
        PETCSECTION psect = petc->sections + i;
        int j;

        if (!psect->name) // 该section没有
            continue;
       
        // 该section共有key_nr个key
        for (j=0; jkey_nr; j++) {
            // 释放key和value
            FreeFixStr (psect->keys [j]);
            FreeFixStr (psect->values [j]);
        }
        free (psect->keys); // 释放malloc到的内存
        free (psect->values);
        FreeFixStr (psect->name); // 释放name
    }

    free (petc->sections); // 释放malloc到的内存
    free (petc);

    return 0;
}
阅读(3196) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~