/*====================================================================* * * Copyright (c) 2013 Qualcomm Atheros, Inc. * * All rights reserved. * *====================================================================*/ /*====================================================================* * * config.c - configuration file reader; * * configuration files contain named parts where each part may * contain one of more named items that have text definitions; * * the named file can be searched for the first occurance of a * named part then the first occurance of a named item; * * [part1] * item1=string * item2=string * * [part2] * item1=string * item2=string * *--------------------------------------------------------------------*/ #ifndef CONFIG_SOURCE #define CONFIG_SOURCE /*====================================================================* * system header files; *--------------------------------------------------------------------*/ #include #include #include #include /*====================================================================* * custom header files; *--------------------------------------------------------------------*/ #include "../tools/config.h" #include "../tools/types.h" #include "../tools/chars.h" /*====================================================================* * program variables; *--------------------------------------------------------------------*/ static signed c; /*====================================================================* * * bool _compare (FILE * fp, char const *sp); * * compare file and text characters until they differ or until end * of text, line or file occurs; a match is declared when the text * ends before the line or file; * * spaces and tabs within the argument string or file string are * ignored such that "item1", " item1 " and "item 1" all match; * *--------------------------------------------------------------------*/ static bool _compare (FILE * fp, char const * sp) { while (isblank ((unsigned char)* sp)) { sp++; } while ((* sp) && nobreak (c)) { if (toupper (c) != toupper ((unsigned char)* sp)) { return (0); } do { sp++; } while (isblank ((unsigned char)* sp)); do { c = getc (fp); } while (isblank (c)); } return (! * sp); } /*====================================================================* * * void _collect (FILE * fp, char buffer [], size_t length); * * collect text to end of line; remove leading and trailing space * but preserve embedded space; replace selected escape sequences; * *--------------------------------------------------------------------*/ static void _collect (FILE * fp, char buffer [], size_t length) { char * string = buffer; while ((c != ';') && nobreak (c)) { if (c == '\\') { c = getc (fp); if (c == 'n') { c = '\n'; } if (c == 'r') { c = '\r'; } if (c == 't') { c = '\t'; } } if (length > 1) { * buffer++ = c; length--; } if (! isblank (c)) { string = buffer; } c = getc (fp); } * string = '\0'; return; } /*====================================================================* * * void _discard (FILE * fp); * * read and discard characters until end-of-line or end-of-file * is detected; read the first character of next line if end of * file has not been detected; * *--------------------------------------------------------------------*/ static void _discard (FILE * fp) { while (nobreak (c)) { c = getc (fp); } if (c != EOF) { c = getc (fp); } return; } /*====================================================================* * * const char * configstring (char const * file, char const * part, char const * item, char const * string) * * open the named file, locate the named part and return the named * item as a text string, if present; return an alternative string * if the file, part or item is missing; the calling function must * preserve the returned strings because they are overwritten with * each call; * *--------------------------------------------------------------------*/ char const * configstring (char const * file, char const * part, char const * item, char const * string) { FILE * fp; static char buffer [1024]; if ((! file) || (! part) || (! item)) { return (string); } if ((fp = fopen (file, "rb"))) { for (c = getc (fp); c != EOF; _discard (fp)) { while (isblank (c)) { c = getc (fp); } if (c != '[') { continue; } do { c = getc (fp); } while (isblank (c)); if (! _compare (fp, part)) { continue; } if (c != ']') { continue; } for (_discard (fp); (c != '[') && (c != EOF); _discard (fp)) { while (isblank (c)) { c = getc (fp); } if (c == ';') { continue; } if (! _compare (fp, item)) { continue; } if (c != '=') { continue; } do { c = getc (fp); } while (isblank (c)); _collect (fp, buffer, sizeof (buffer)); string = buffer; break; } break; } fclose (fp); } #if 0 fprintf (stderr, "[%s][%s][%s]='%s'\n", file, part, item, string); #endif return (string); } /*====================================================================* * * unsigned confignumber (char const * file, char const * part, char const * item, unsigned number) * * open the named file, locate the named part and return the named * item as an unsigned integer, if present; return a default number * if the file, part or item is missing; * *--------------------------------------------------------------------*/ unsigned confignumber (char const * file, char const * part, char const * item, unsigned number) { unsigned value = 0; char const * string = configstring (file, part, item, ""); if ((string) && (* string)) { while (isdigit ((unsigned char)* string)) { value *= 10; value += * string++ - '0'; } if (! (* string)) { number = value; } } return (number); } /*====================================================================* * * int main (int argc, char const * argv []); * * demo/test program; arguments are file, part, item and text in * that order; you can construct your own configuration file and * observe behaviour; * *--------------------------------------------------------------------*/ #if 0 #include int main (int argc, char const * argv []) { char const * string = configstring (argv [1], argv [2], argv [3], argv [4]); printf ("file=[%s] part=[%s] item=[%s] text=[%s]\n", argv [1], argv [2], argv [3], string); return (0); } #endif /*====================================================================* * *--------------------------------------------------------------------*/ #endif