Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals  

_inifile.c

Go to the documentation of this file.
00001 
00002 /*
00003    _inifile.c
00004 
00005    C INI file reader
00006 
00007    Modification history:
00008 
00009    11-Oct-2000 WPS added code to eliminate white space after the variable.
00010    23-Sep-1999 WPS removed isspace which is not supported under CE.
00011    16-Jun-1999  FMP fixed bug in which, for example, "I" matched "INPUT"
00012    if "I" were not present but "INPUT" were
00013    18-Dec-1997  FMP set up as C/C++ split for emcnml directory
00014    7-Nov-1997  FMP fixed bug in afterequal so that it terminates at a 0
00015    24-Apr-1997  FMP split into C and C++ sections; changed ini_find to
00016    iniFind; put iniSection into C part
00017    25-Jul-1996  FMP added find_section() and ::section()
00018    11-Jul-1996  Fred Proctor made sure ini_find() returned NULL if a
00019    section were provided and no match was detected when the section
00020    was left; fixed bug which required the last line to have a newline
00021    */
00022 #include "rcs_defs.hh"
00023 
00024 #include "inifile.h"
00025 
00026 
00027 #if !defined(INIFILE_USE_INET_FILES) && !defined(NO_STDIO)
00028 #include <stdio.h>              /* FILE *, fopen(), fclose(), NULL */
00029 #endif
00030 
00031 #include <string.h>             /* strlen(), etc. */
00032 #include <ctype.h>              /* isspace() */
00033 
00034 /* if the next non-whitespace character in string is '=', returns
00035    ptr to next non-whitespace after that, or NULL. */
00036 static const char *
00037 afterequal (const char *string)
00038 {
00039   const char *spot = string;    /* non-reentrant */
00040 
00041   for (;;)
00042     {
00043       if (*spot == '=')
00044         {
00045           /* = is there-- return next non-white, or NULL if not there */
00046           for (;;)
00047             {
00048               spot++;
00049               if (0 == *spot)
00050                 {
00051                   /* ran out */
00052                   return NULL;
00053                 }
00054               else if (*spot != ' ' && *spot != '\t' && *spot != '\r'
00055                        && *spot != '\n')
00056                 {
00057                   /* matched! */
00058                   return spot;
00059                 }
00060               else
00061                 {
00062                   /* keep going for the text */
00063                   continue;
00064                 }
00065             }
00066         }
00067       else if (*spot == 0)
00068         {
00069           /* end of string */
00070           return NULL;
00071         }
00072       else
00073         {
00074           /* haven't seen '=' yet-- keep going */
00075           spot++;
00076           continue;
00077         }
00078     }
00079 }
00080 
00081 /* returns ptr to first non-white in string, or NULL if it's all white */
00082 static char *
00083 skipwhite (char *string)
00084 {
00085   for (;;)
00086     {
00087       if (*string == 0)
00088         {
00089           return NULL;
00090         }
00091 
00092       if (*string == COMMENT_CHAR)
00093         {
00094           return NULL;
00095         }
00096 
00097       if (*string != ' ' && *string != '\t' && *string != '\r'
00098           && *string != '\n')
00099         {
00100           return string;
00101         }
00102 
00103       string++;
00104     }
00105 }
00106 
00107 /*
00108    Positions file at line after section tag. Returns 0 if section found;
00109    -1 if not.
00110    */
00111 static int
00112 findSection (void *fp, const char *section)
00113 {
00114   static char line[INIFILE_MAX_LINELEN + 2];    /* 1 for newline, 1 for NULL */
00115   static char bracketsection[INIFILE_MAX_LINELEN + 2];
00116   char *nonwhite;
00117 
00118   /* check valid file */
00119   if (NULL == fp)
00120     {
00121       return -1;
00122     }
00123 
00124   /* start from beginning */
00125 #ifndef INIFILE_USE_INET_FILES
00126   rewind ((FILE *) fp);
00127 #else
00128   inet_file_rewind ((INET_FILE *) fp);
00129 #endif
00130 
00131   /* if section is NULL, we're already positioned */
00132   if (NULL == section)
00133     {
00134       return 0;
00135     }
00136 
00137   /* wrap section in brackets, so it matches */
00138 #ifndef NO_STDIO
00139   sprintf (bracketsection, "[%s]", section);
00140 #else
00141   strcpy (bracketsection, "[");
00142   strcat (bracketsection, section);
00143   strcat (bracketsection, "]");
00144 #endif
00145 
00146   /* find [section], and position fp just after it */
00147 #ifndef INIFILE_USE_INET_FILES
00148   while (!feof ((FILE *) fp))
00149 #else
00150   while (!inet_file_eof ((INET_FILE *) fp))
00151 #endif
00152     {
00153 
00154 #ifndef INIFILE_USE_INET_FILES
00155       if (NULL == fgets (line, INIFILE_MAX_LINELEN + 1, (FILE *) fp))
00156         {
00157           /* got to end of file without finding it */
00158           return -1;
00159         }
00160 #else
00161       if (NULL ==
00162           inet_file_gets (line, INIFILE_MAX_LINELEN + 1, (INET_FILE *) fp))
00163         {
00164           /* got to end of file without finding it */
00165           return -1;
00166         }
00167 #endif
00168 
00169       /* got a line-- check it for real data, not comment or blank line */
00170       if (NULL == (nonwhite = skipwhite (line)))
00171         {
00172           /* blank line-- skip it */
00173           continue;
00174         }
00175 
00176       /* not a blank line-- compare with section tag */
00177       if (0 != strncmp (bracketsection, nonwhite, strlen (bracketsection)))
00178         {
00179           /* not on this line */
00180           continue;
00181         }
00182 
00183       /* else it matches-- fp is now set up for search on tag */
00184       return 0;
00185     }
00186 
00187   /* didn't find it */
00188   return -1;
00189 }
00190 
00191 /* Returns string in file associated with tag, e.g., in a file that
00192    contains
00193 
00194    PRINTER=fred
00195 
00196    iniFind("PRINTER");
00197 
00198    would return "fred", and
00199 
00200    iniFind("printer");
00201 
00202    would return NULL.
00203 
00204    The FILE * needs to have been opened; its position after the call
00205    to iniFind is undefined.
00206  */
00207 
00208 const char *
00209 iniFind (void *fp, const char *tag, const char *section)
00210 {
00211   static char line[INIFILE_MAX_LINELEN + 2];    /* 1 for newline, 1 for NULL */
00212   static char bracketsection[INIFILE_MAX_LINELEN + 2];
00213   char *nonwhite;
00214   int newlinepos;               /* position of newline to strip */
00215   int len;
00216   char tagend;
00217   char *value_string;
00218   char *end_value_string;
00219   /* check valid file */
00220   if (NULL == fp)
00221     return NULL;
00222 
00223   /* start from beginning */
00224 #ifndef INIFILE_USE_INET_FILES
00225   rewind ((FILE *) fp);
00226 #else
00227   inet_file_rewind ((INET_FILE *) fp);
00228 #endif
00229 
00230   /* check for section first-- if it's non-NULL, then position file at line
00231      after [section] */
00232   if (NULL != section)
00233     {
00234 #ifndef NO_STDIO
00235       sprintf (bracketsection, "[%s]", section);
00236 #else
00237       strcpy (bracketsection, "[");
00238       strcat (bracketsection, section);
00239       strcat (bracketsection, "]");
00240 #endif
00241 
00242       /* find [section], and position fp just after it */
00243 
00244 #ifndef INIFILE_USE_INET_FILES
00245       while (!feof ((FILE *) fp))
00246 #else
00247       while (!inet_file_eof ((INET_FILE *) fp))
00248 #endif
00249         {
00250 
00251 
00252 #ifndef INIFILE_USE_INET_FILES
00253           if (NULL == fgets (line, INIFILE_MAX_LINELEN + 1, (FILE *) fp))
00254             {
00255               /* got to end of file without finding it */
00256               return NULL;
00257             }
00258 #else
00259           if (NULL ==
00260               inet_file_gets (line, INIFILE_MAX_LINELEN + 1,
00261                               (INET_FILE *) fp))
00262             {
00263               /* got to end of file without finding it */
00264               return NULL;
00265             }
00266 #endif
00267           /* got a line */
00268 
00269           /* strip off newline */
00270           newlinepos = strlen (line) - 1;       /* newline is on back from 0 */
00271           if (newlinepos < 0)
00272             {
00273               newlinepos = 0;
00274             }
00275           if (line[newlinepos] == '\n')
00276             {
00277               line[newlinepos] = 0;     /* make the newline 0 */
00278             }
00279 
00280           if (NULL == (nonwhite = skipwhite (line)))
00281             {
00282               /* blank line-- skip */
00283               continue;
00284             }
00285 
00286           /* not a blank line, and nonwhite is first char */
00287           if (0 !=
00288               strncmp (bracketsection, nonwhite, strlen (bracketsection)))
00289             {
00290               /* not on this line */
00291               continue;
00292             }
00293 
00294           /* it matches-- fp is now set up for search on tag */
00295           break;
00296         }
00297     }
00298 
00299 #ifndef INIFILE_USE_INET_FILES
00300   while (!feof ((FILE *) fp))
00301 #else
00302   while (!inet_file_eof ((INET_FILE *) fp))
00303 #endif
00304     {
00305       /* check for end of file */
00306 #ifndef INIFILE_USE_INET_FILES
00307       if (NULL == fgets (line, INIFILE_MAX_LINELEN + 1, (FILE *) fp))
00308         {
00309           /* got to end of file without finding it */
00310           return NULL;
00311         }
00312 #else
00313       if (NULL ==
00314           inet_file_gets (line, INIFILE_MAX_LINELEN + 1, (INET_FILE *) fp))
00315         {
00316           /* got to end of file without finding it */
00317           return NULL;
00318         }
00319 #endif
00320 
00321       /* got a line */
00322 
00323       /* strip off newline */
00324       newlinepos = strlen (line) - 1;   /* newline is on back from 0 */
00325       if (newlinepos < 0)
00326         {
00327           newlinepos = 0;
00328         }
00329       if (line[newlinepos] == '\n')
00330         {
00331           line[newlinepos] = 0; /* make the newline 0 */
00332         }
00333 
00334       /* skip leading whitespace */
00335       if (NULL == (nonwhite = skipwhite (line)))
00336         {
00337           /* blank line-- skip */
00338           continue;
00339         }
00340 
00341       /* check for '[' char-- if so, it's a section tag, and we're out of
00342          our section */
00343       if (NULL != section && nonwhite[0] == '[')
00344         {
00345           return NULL;
00346         }
00347 
00348       len = strlen (tag);
00349 
00350       if (0 != strncmp (tag, nonwhite, len))
00351         {
00352           /* not on this line */
00353           continue;
00354         }
00355 
00356       /* it matches the first part of the string-- if whitespace or =
00357          is next char then call it a match */
00358       tagend = nonwhite[len];
00359       if (tagend == ' ' || tagend == '\r' || tagend == '\t' || tagend == '\n'
00360           || tagend == '=')
00361         {
00362           /* it matches-- return string after =, or NULL */
00363           nonwhite += len;
00364           value_string = (char *) afterequal (nonwhite);        /* Cast is needed because we are discarding the const. */
00365           /* Eliminate white space at the end of a line also. */
00366           if (NULL == value_string)
00367             {
00368               return NULL;
00369             }
00370           end_value_string = value_string + strlen (value_string) - 1;
00371           while (*end_value_string == ' ' || *end_value_string == '\t'
00372                  || *end_value_string == '\r')
00373             {
00374               *end_value_string = 0;
00375               end_value_string--;
00376             }
00377           return value_string;
00378         }
00379       /* else continue */
00380     }
00381 
00382   return NULL;
00383 }
00384 
00385 /*
00386    given 'section' and array of strings, fills strings with what was
00387    found in the section, one line per string. Comments and blank lines
00388    are omitted. 'array' is assumed to be allocated, of 'max' entries
00389    of size INIFILE_MAX_LINELEN.
00390 
00391    Returns number of entries found; 0 if section is there but no entries
00392    in it, or -1 if section is not there.
00393 */
00394 
00395 int
00396 iniSection (void *fp, const char *section, INIFILE_ENTRY array[], int max)
00397 {
00398   static char line[INIFILE_MAX_LINELEN + 2];    /* 1 for newline, 1 for NULL */
00399   int count = 0;
00400   char *nonwhite;
00401   int newlinepos;
00402   const char *entry;
00403 #ifdef UNDER_CE
00404   int i = 0;
00405 #endif
00406 
00407   if (NULL == fp)
00408     {
00409       return -1;
00410     }
00411 
00412   /*  position at section */
00413   if (-1 == findSection (fp, section))
00414     {
00415       /* didn't find it */
00416       return -1;
00417     }
00418 
00419   /* found section-- start loading lines */
00420 
00421 #ifndef INIFILE_USE_INET_FILES
00422   while (!feof ((FILE *) fp) &&
00423 #else
00424   while (!inet_file_eof ((INET_FILE *) fp) &&
00425 #endif
00426          count < max)
00427     {
00428 #ifndef INIFILE_USE_INET_FILES
00429       if (NULL == fgets (line, INIFILE_MAX_LINELEN + 1, (FILE *) fp))
00430         {
00431           /* got to end of file without finding it */
00432           return count;
00433         }
00434 #else
00435       if (NULL ==
00436           inet_file_gets (line, INIFILE_MAX_LINELEN + 1, (INET_FILE *) fp))
00437         {
00438           /* got to end of file without finding it */
00439           return count;
00440         }
00441 #endif
00442 
00443       /* got a line-- check for blank */
00444       if (NULL == (nonwhite = skipwhite (line)))
00445         {
00446           continue;
00447         }
00448 
00449       /* check for new section-- if so, we're done */
00450       if ('[' == *nonwhite)
00451         {
00452           return count;
00453         }
00454 
00455       /* strip off newline  */
00456       newlinepos = strlen (line) - 1;   /* newline is one back from 0 */
00457       if (newlinepos < 0)
00458         {
00459           newlinepos = 0;
00460         }
00461       if (line[newlinepos] == '\n')
00462         {
00463           line[newlinepos] = 0; /* make the newline 0 */
00464         }
00465 
00466       /* it's a valid line-- copy into entry struct */
00467 
00468       /* read first tag */
00469 #ifndef UNDER_CE
00470       sscanf (line, "%s", array[count].tag);
00471 #else
00472       i = 0;
00473       while (line[i] != 0 && line[i] != ' ' && line[i] != '\t'
00474              && line[i] != '\r')
00475         {
00476           array[count].tag[i] = line[i];
00477           i++;
00478         }
00479       array[count].tag[i] = 0;
00480 #endif
00481 
00482       /* copy everything after equal to the rest */
00483 
00484       entry = afterequal (line);
00485       if (NULL != entry)
00486         {
00487           strcpy (array[count].rest, afterequal (line));
00488         }
00489       else
00490         {
00491           array[count].rest[0] = 0;     /* make it the empty string */
00492         }
00493       count++;
00494     }
00495 
00496   /* got to end of file */
00497   return count;
00498 }

Generated on Sun Dec 2 15:56:47 2001 for rcslib by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001