⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sflini.c

📁 短小精悍的C语言标准函数库。提供450个以上的可移植的算法和工具代码。
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  ----------------------------------------------------------------<Prolog>-
    Name:       sflini.c
    Title:      Initialisation file access functions
    Package:    Standard Function Library (SFL)

    Written:    1994/01/18  iMatix SFL project team <sfl@imatix.com>
    Revised:    2000/01/19

    Copyright:  Copyright (c) 1996-2000 iMatix Corporation
    License:    This is free software; you can redistribute it and/or modify
                it under the terms of the SFL License Agreement as provided
                in the file LICENSE.TXT.  This software is distributed in
                the hope that it will be useful, but without any warranty.
 ------------------------------------------------------------------</Prolog>-*/

#include "prelude.h"                    /*  Universal header file            */
#include "sflstr.h"                     /*  String functions                 */
#include "sfllist.h"                    /*  List access functions            */
#include "sflmem.h"                     /*  Memory access functions          */
#include "sflfile.h"                    /*  File access functions            */
#include "sflsymb.h"                    /*  Symbol table functions           */
#include "sflenv.h"                     /*  Environment access functions     */
#include "sfltok.h"                     /*  Token-handling functions         */
#include "sfldate.h"                    /*  Date and time functions          */
#include "sfltron.h"                    /*  Trace functions                  */
#include "sflprint.h"                   /*  snprintf functions               */
#include "sflini.h"                     /*  Prototypes for functions         */


/*  Static variables used globally in this source file only                  */

static char
    iniline     [LINE_MAX + 1],         /*  Line from ini file               */
    ini_section [LINE_MAX + 1],         /*  Match [section name]             */
    ini_keyword [LINE_MAX + 1],         /*  Match keyword =                  */
    ini_value   [LINE_MAX + 1];         /*  Match = value                    */


/*  ---------------------------------------------------------------------[<]-
    Function: ini_find_section

    Synopsis:
    Finds a specific section in the ini file.  An ini file contains lines
    as shown below.  The section name can be any mix of upper or lowercase.
    You should open the ini file using file_open before you call this
    function.  If the 'top' argument is TRUE, repositions to the start
    of the file before reading, else reads from the current file offset.
    Returns TRUE if the section was found, and positions on the line that
    follows the section.  Returns FALSE if the section was not found, and
    positions at the end of the file.

    Examples:
    ;   comments like this, or
    #   comments like this if you prefer
    !   Text is echoed to console using trace()
    [Section]
        keyword = key_value; comments
        keyword = "key_value"; comments
        keyword = 'key_value'; comments
        ...
    [Section]
        keyword = key_value; comments
        ...
    ---------------------------------------------------------------------[>]-*/

Bool
ini_find_section (
    FILE *inifile,
    char *section,
    Bool top)
{
    char
        *first;
        
    ASSERT (inifile != NULL);
    ASSERT (section != NULL);

    if (top)                            /*  Reposition at top if wanted      */
        fseek (inifile, 0, SEEK_SET);

    /*  Read through file until we find what we are looking for              */
    while (file_read (inifile, iniline))
      {
        first = strskp (iniline);       /*  Skip leading spaces              */
           
        if (*first == ';' || *first == '#' || *first == 0)
            continue;                   /*  Comment line                     */
        else
        if (*first == '!')
          {
            first = strskp (first + 1);
            trace (first);
          }
        else
        if (sscanf (first, "[%[^]]", ini_section) == 1
        &&  lexcmp (ini_section, section) == 0)
            return (TRUE);
      }
    return (FALSE);
}


/*  ---------------------------------------------------------------------[<]-
    Function: ini_scan_section

    Synopsis:
    Scans the current section of the ini file, and returns a keyword and
    value if such was found.  Returns the address of these values in the
    supplied arguments.  The addresses point to static values that are
    overwritten with each call.  Returns TRUE when a keyword/value pair
    is found.  Returns FALSE if a new section name or end of file is found.
    In the first case, sets the keyword to the section name; in the second
    case sets the keyword to NULL.  Ignores blank and comment lines, and
    lines that look like junk.  Keyword and section names are returned as
    lower-case; values are returned exactly as specified in the ini file.
    ---------------------------------------------------------------------[>]-*/

Bool
ini_scan_section (
    FILE *inifile,
    char **keyword,
    char **value)
{
    int
        remaining;                      /*  Space remaining in line buffer   */
    char
        *first,
        *valueptr,
        *lineptr;

    /*  Read through file until we find what we are looking for              */
    while (file_read (inifile, iniline))
      {
        strcrop (iniline);
        if (strnull (iniline))
            continue;                   /*  Skip empty lines                 */

        /*  Calculate space remaining in buffer after this line; we need to
         *  know this later if we start reading continuation lines.
         */
        remaining = LINE_MAX - strlen (iniline);
            
        first = strskp (iniline);       /*  Skip leading spaces              */
        if (*first == ';' || *first == '#' || *first == 0)
            continue;                   /*  Comment line                     */
        else
        if (*first == '!')
          {
            first = strskp (first + 1);
            trace (first);
          }
        else                            /*  Have name = value                */
        if ((valueptr = strchr (first, '=')) != NULL)
          {
            *valueptr++ = '\0';
            strcpy (ini_keyword, strcrop (strlwc (first)));
            while (*valueptr == ' ')
                valueptr++;             /*    and leading spaces             */
            
            if (*valueptr == '"')        
              {                         /*  Have value in quotes             */
                /*  Get continuation lines as necessary and possible         */
                first = &strlast (valueptr);
                while (*first == '-' && remaining > 0)
                  {
                    if (!file_readn (inifile, first, remaining))
                        break;                  /*  Abrubt end of file       */
                    strcrop (first);
                    remaining -= strlen (first) - 1;
                    first     += strlen (first) - 1;
                  } 
                /*  Now find closing quote and terminate value there         */
                for (lineptr = valueptr + 1; *lineptr; lineptr++)
                  {
                    if (*lineptr == '\\')
                        lineptr++;      /*  Ignore next char                 */
                    else
                    if (*lineptr == '"')
                      {                 
                        lineptr [1] = '\0';
                        break;          /*  Closing quote, end of value      */
                      }
                  }
              }
            else
              {                         /*  Have unquoted value              */
                strconvch (valueptr, ';', '\0');
                strconvch (valueptr, '#', '\0');
              }
            strcrop (valueptr);
            strcpy (ini_value, valueptr);
            *keyword = ini_keyword;
            *value   = ini_value;
            return (TRUE);              /*  Found keyword = value            */
          }
        else
        if (sscanf (first, "[%[^]]", ini_section) == 1)
          {
            *keyword = strlwc (ini_section);
            *value   = NULL;
            return (FALSE);             /*  New section name                 */
          }
        else
        if (streq (first, "[]"))        /*  Allow empty section names        */
          {
            strcpy (ini_section, "");
            *keyword = ini_section;
            *value   = NULL;
            return (FALSE);             /*  New section name                 */
          }
      }
    *keyword = NULL;
    return (FALSE);                     /*  End of file                      */
}


/*  ---------------------------------------------------------------------[<]-
    Function: ini_dyn_load

    Synopsis: Loads the contents of an .ini file into a symbol table.  If
    no symbol table is specified, creates a new symbol table.  The ini file
    data is loaded as a set of symbols and values, where the symbol name is
    built from the section name and keyword like this: "section:keyword".
    The symbol name is always stored in lowercase, with no trailing spaces.
    If the same keyword occurs several times in a section, earlier symbols
    are overwritten.  Ignores all comments and blank lines.  Returns NULL
    if there is not enough memory.  Stores these control variables in the
    symbol table if the table was freshly created or the file was loaded:
    <TABLE>
    filename        Name of input file
    filetime        Time of input file, as 8-digit string "HHMMSSCC"
    filedate        Date of input file, as 8-digit string "YYYYMMDD"
    </TABLE>
    Also creates a symbol for each section, with name equal to the section
    name, and value equal to an empty string.  Looks for the .ini file on
    the current PATH.  The table is sorted after loading.
    ---------------------------------------------------------------------[>]-*/

SYMTAB *
ini_dyn_load (
    SYMTAB *load_symtab,
    const char *filename)
{
    FILE
        *inifile;
    SYMTAB
        *symtab,                        /*  Symbol table to populate         */
        *envtab;                        /*  Environment, as symbol table     */
    char
        *section = NULL,                /*  Filled as we scan through        */
        *keyword = NULL,                /*    the ini file                   */
        *value   = NULL,
        *fromptr,
        *toptr,
        *section_end;                   /*  Null byte at end of section      */

    ASSERT (filename);
    inifile = file_locate ("PATH", filename, NULL);

    if (load_symtab)                    /*  Use specified symbol table       */
        symtab = load_symtab;           /*    or create a new one            */
    else
      {
        symtab = sym_create_table ();
        if (symtab == NULL)
            return (NULL);              /*  Quit if insufficient memory      */
      }
    /*  Store control variables in symbol table                              */
    if (inifile || load_symtab == NULL)
      {
        sym_assume_symbol (symtab, "filename", filename);
        snprintf (iniline, sizeof (iniline), "%ld", 
	 	           timer_to_date (get_file_time (filename)));
        sym_assume_symbol (symtab, "filedate", iniline);
        snprintf (iniline, sizeof (iniline), "%ld", 
		           timer_to_time (get_file_time (filename)));
        sym_assume_symbol (symtab, "filetime", iniline);
      }
    if (!inifile)
        return (symtab);                /*  File not found; empty table      */

    /*  Now load the ini file, starting from the beginning                   */
    envtab = env2symb ();
    fseek (inifile, 0, SEEK_SET);
    FOREVER
      {
        if (ini_scan_section (inifile, &keyword, &value))
          {
            if (section)
              {
                section_end = strchr (section, '\0');
                ASSERT (section_end);
                xstrcat (section, ":", keyword, NULL);
                value = tok_subst (value, envtab);

                /*  Handle value in quotes                                   */
                if (*value == '"')
                  {
                    /*  Unescape value if necessary                          */
                    if (strchr (value, '\\'))
                      {
                        toptr = value;
                        for (fromptr = value; *fromptr; fromptr++)
                          {
                            if (*fromptr == '\\')
                              {
                                fromptr++;
                                if (*fromptr == 'n')
                                    *toptr++ = '\n';
                                else
                                    *toptr++ = *fromptr;
                              }
                            else
                                *toptr++ = *fromptr;
                          }
                        *toptr = '\0';
                      }
                    strlast (value) = '\0'; 
                    sym_assume_symbol (symtab, section, value + 1);
                  }
                else
                    sym_assume_symbol (symtab, section, value);

                mem_strfree (&value);
                *section_end = '\0';
              }
          }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -