/* +JMJ * inifile.c - INI file reader/parser module * 2014 David Meyer <papa@sdf.org> * * Primitive objects: * i: scanned INI file property data * p: property (section/key name combination) * s: section * k: key name * v: value */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "krcompat.h" #include "adamstyl.h" #include "inifile.h" void parse_property PARAMS((char* linein, char* wcurrs)); void parse_section PARAMS((char* linein, char* wcurrs)); int nump = 0; char vsop[MAXP][LENW]; char vkop[MAXP][LENW]; char kvop[MAXP][LENL]; int nums = 0; char vsection[MAXS][LENW]; int icurrp, icurrs; char wsearchs[LENW]; /* iproprty - Return index of property or -1 for undefined */ int iproprty (wsection, wkey) char* wsection; char* wkey; { int ip = 0; while (ip < nump && (strcmp (vsop[ip], wsection) != 0 || strcmp (vkop[ip], wkey) != 0)) ip++; if (ip < nump) return ip; else return -1; } /* ireadi - Read and parse groups/keys/values from specified INI file * Returns number of keys processed */ int ireadi (winifn) char* winifn; { FILE* xinif; char lin[LENL]; char wcurrs[LENW] = ""; int nump0; nump0 = nump; xinif = fopen (winifn, "r"); while (fgets (lin, LENL, xinif) != NULL) { switch (lin[0]) { case '#': case ';': case ' ': case '\t': case '\n': case '\r': case '\0': break; case '[': parse_section (lin, wcurrs); break; default: parse_property (lin, wcurrs); } } return nump-nump0; } /* ireseti - forget all group/key/value data */ int ireseti () { int ip, is; for (ip = 0; ip < nump+1; ip++) { vsop[ip][0] = '\0'; vkop[ip][0] = '\0'; kvop[ip][0] = '\0'; } nump = 0; for (is = 0; is < nums+1; is++) { vsection[is][0] = '\0'; } nums = 0; return 0; } /* isection - Return index for section or -1 if section not defined */ int isection (wsection) char* wsection; { int is = 0; while (is < nums && strcmp (vsection[is], wsection) != 0) is++; if (is == nums) return -1; else return is; } /* lvop - Value string of specified group/key * Returns null string for group/key not defined or group/key * defined without value (use iproprty() to differentiate) */ char* lvop (wsection, wkey) char* wsection; char* wkey; { int ip = 0; while (ip < nump && (strcmp (vsop[ip], wsection) != 0 || strcmp (vkop[ip], wkey) != 0)) ip++; if (ip == nump) return NULL; else return kvop[ip]; } /* parse_property - parse property name and value from input * line and record with section name. */ void parse_property (lin, wcurrs) char* lin; char* wcurrs; { char wkey[LENW]; char lvalue[LENL]; int i, ilenl, ilenk, ioldp; ilenl = strlen (lin); for (i = 0; i < ilenl && lin[i] != '='; i++) wkey[i] = lin[i]; wkey[i] = '\0'; ilenk = i; if (lin[i] == '=') i++; while (i < ilenl) { lvalue[i-ilenk-1] = lin[i]; i++; } lvalue[i-ilenk-1] = '\0'; if (lvalue[i-ilenk-2] == '\n' || lvalue[i-ilenk-2] == '\r') lvalue[i-ilenk-2] = '\0'; if (lvalue[i-ilenk-3] == '\n' || lvalue[i-ilenk-3] == '\r') lvalue[i-ilenk-3] = '\0'; ioldp = iproprty (wcurrs, wkey); if (ioldp > -1) strcpy (kvop[ioldp], lvalue); else { if (nump == MAXP) { fprintf (stderr, "Error: more than %d INI file properties\n", MAXP); exit (1); } strcpy (vsop[nump], wcurrs); strcpy (vkop[nump], wkey); strcpy (kvop[nump], lvalue); nump++; if (strcmp (wcurrs, "") != 0 && isection (wcurrs) == -1) { if (nums == MAXS) { fprintf (stderr, "Error: more than %d INI file sections\n", MAXS); exit (1); } strcpy (vsection[nums], wcurrs); nums++; } } } /* parse_section - parse section name from input line. */ void parse_section (lin, wcurrs) char* lin; char* wcurrs; { int i, n; n = strlen (lin); for (i = 1; lin[i] != ']' && i < n; i++) wcurrs[i-1] = lin[i]; wcurrs[n-2] = '\0'; } /* wfkos - First key name in specified section */ char* wfkos (wsection) char* wsection; { icurrp = 0; while (icurrp < nump && strcmp (vsop[icurrp], wsection) != 0) icurrp++; if (icurrp < nump) { strcpy (wsearchs, wsection); return vkop[icurrp]; } else { icurrp = 0; wsearchs[0] = '\0'; return NULL; } } /* wfsoi - First section name */ char* wfsoi () { if (nums > 0) { icurrs = 0; return vsection[0]; } else return NULL; } /* wnkos - Next key in previously previously specified section */ char* wnkos () { icurrp++; if (icurrp < nump && strcmp (vsop[icurrp], wsearchs) == 0) return vkop[icurrp]; else { icurrp = 0; wsearchs[0] = '\0'; return NULL; } } /* wnsoi - Next section name */ char* wnsoi () { icurrs++; if (nums > icurrs) { return vsection[icurrs]; } else return NULL; }