/* +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] = "";

  xinif = fopen (winifn, "r");
  while ((int) fgets (lin, LENL, xinif) != EOF)
  {
    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 0;
}

/*    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 "";
  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';
  ioldp = iproprty (wcurrs, wkey);
  if (ioldp > -1)
    strcpy (lvalue, kvop[ioldp]);
  else
  {
    if (nump == MAXP)
    {
      fprintf (stderr, "Error: more than MAXP INI file properties\n");
      exit (1);
    }
    strcpy (wcurrs, vsop[nump]);
    strcpy (wkey,   vkop[nump]);
    strcpy (lvalue, kvop[nump]);
    nump++;
    if (isection (wcurrs) == -1)
    {
      if (nums == MAXS)
      {
	fprintf (stderr, "Error: more than MAXS INI file sections\n");
	exit (1);
      }
      strcpy (wcurrs, vsection[nums]);
      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 (wsection, wsearchs);
    return vkop[icurrp];
  }
  else
  {
    icurrp = 0;
    wsearchs[0] = '\0';
    return "";
  }
}

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

/*    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 "";
  }
}

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