/* +JMJ
 * inifile.c - INI file reader/parser module
 * 2014 David Meyer <papa@sdf.org>
 */

/*    Primitive objects:
 *      k: group/key name combination
 *      s: section
 *      n: key name
 *      v: value
 */

#include <stdio.h>
#include <string.h>
#include "krcompat.h"
#include "adamstyl.h"
#include "inifile.h"

int numk = 0;
char vsok[MAXC][LENW];
char vnok[MAXC][LENW];
char kvok[MAXC][LENL];

int nums = 0;
char vsect[MAXG][LENW];

static int icurrk, icurrs;
static char wsrchs[LENW];

/*    ini_reset - forget all group/key/value data
 */
void ini_reset ()
{
  int ik, is;
  for (ik = 0; ik < numk+1; ik++)
  {
    vsok[ik][0] = '\0';
    vnok[ik][0] = '\0';
    kvok[ik][0] = '\0';
  }
  numk = 0;
  for (is = 0; is < nums+1; is++)
  {
    vsect[is][0] = '\0';
  }
  nums = 0;
}

/*    is_defined_section - Have any keys been parsed in the specified section?
 */
int is_defined_section (wsection)
     char* wsection;
{
  int is = 0;
  while (is < nums && strcmp(vsect[is], wsection) != 0) is++;
  if (is == nums) return (FALSE);
  else           return (TRUE);
}

/*    is_defined_key - Has the specified group/key combination been parsed?
 */
int is_defined_key (wsection, wname)
     char* wsection;
     char* wname;
{
  int ik = 0;
  while (ik < numk &&
	 (strcmp(vsok[ik], wsection) != 0 ||
	  strcmp(vnok[ik], wname) != 0))
    ik++;
  if (ik < numk) return (TRUE);
  else           return (FALSE);
}

/*    iniwfs - First section name
 */
char* iniwfs ()
{
  if (nums > 0)
  {
    icurrs = 0;
    return (vsect[0]);
  }
  else
    return ("");
}

/*    iniwns - Next section name
 */
char* iniwns ()
{
  icurrs++;
  if (nums > icurrs)
  {
    return (vsect[icurrs]);
  }
  else
    return ("");
}

/*    iniwfnos - First key name in specified section
 */
char*
iniwfnos (wsection)
  char*   wsection;
{
  icurrk = 0;
  while (icurrk < numk && strcmp(vsok[icurrk], wsection) != 0) icurrk++;
  if (icurrk < numk)
  {
    strcpy(wsection, wsrchs);
    return (vnok[icurrk]);
  }
  else
  {
    icurrk = 0;
    wsrchs[0] = '\0';
    return ("");
  }
}

/*    iniwnnos - Next key in previously previously specified section
 */
char*
iniwnnos ()
{
  icurrk++;
  if (icurrk < numk && strcmp(vsok[icurrk], wsrchs) == 0)
    return (vnok[icurrk]);
  else
  {
    icurrk = 0;
    wsrchs[0] = '\0';
    return ("");
  }
}

/*    ini_read_file - Read and parse groups/keys/values from specified INI file
 *    Returns number of keys processed
 */
int ini_read_file (winifn)
  char* winifn;
{
  FILE* xinif;
  char lin[LENL];
  char wcurrs[LENW] = "";

  xinif = fopen (winifn, "r");
  while (fgets (lin, LENL, xinif) != EOF)
  {
    switch (lin[0])
    {
    case '#': case ';': case ' ': case '\t': case '\n': case '\r':
      break;
    case '[':
      do_parse_section (lin, wcurrs);
      break;
    default:
      do_parse_property (lin, wcurrs);
    }
    return (0);
  }
}
/*    do_parse_property - subroutine
 */
/*    do_parse_section - subroutine
 */
/*    inilvok - Value string of specified group/key
 *    Returns null string for group/key not defined or group/key
 *    defined without value (use is_defined_key() to differentiate)
 */
char* inilvok (wsection, wname)
     char* wsection;
     char* wname;
{
  int ik = 0;
  while (ik < numk &&
	 strcmp(vsok[ik], wsection) != 0 &&
	 strcmp(vnok[ik], wname) != 0)
    ik++;
  if (ik == numk) return ("");
  else            return (kvok[ik]);
}