#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <ssdef.h>
#include <stdlib.h>
#include "base_includes.h"
#include "load.h"

int load_depth = 0;

char *sindex(char *str, char *let)
{
  char *l;
  for (;*str;str++)
    for (l=let;*l;l++)
       if (*str == *l) return str;
  return NULL;
}

static int get_a_line(FILE *file, char *str, int maxlen)
{
  char temp[MAXLEN], *walk, *first_non_space = NULL;

  if (!fgets(temp, sizeof(temp), file)) return FALSE;
  temp[strlen(temp)-1] = 0;
  walk = temp;
  while (*walk) {
    if (isspace(*walk)) *walk = 32;
    else {
      if (!first_non_space) first_non_space = walk;
    }
    walk++;
  }
  if (!first_non_space || (*first_non_space=='#'))
    return get_a_line(file, str, maxlen);
  strncpy(str, first_non_space, maxlen);
  str[maxlen] = 0;
  return TRUE;
}

static void raw_load_file(FILE *file)
{
  char buffer[MAXLEN*100], str[MAXLEN], *last, *walk, *ptr, *start;
  int first = TRUE, oldc, add = FALSE, my_level, len;

  buffer[0] = 0;
  my_level = 0;
  for (;;)
  {
    if (get_a_line(file, str, sizeof(str)-1))
    {
      start = str;
      while (start && *start)
      {
        if (strlen(buffer)>=sizeof(buffer)) yell("Oh shit, length problem2");
        walk = start;

/* Basically what the next line does is find the first unescaped {,} or ; */
        while ((ptr = sindex(walk, "{};")) && (ptr!=start) && (ptr[-1]=='\\'))
          walk = ptr + 1;
        if (!add) add = TRUE;
        else if ((!ptr || (ptr!=start)) && *buffer) {
          if (!my_level) {
            parse_line(buffer, NULL, FALSE, FALSE);
            buffer[0] = 0;
          } else strcat(buffer, ";");
        }
        if (ptr)
        {
          char old = *ptr;
          *ptr = 0;
          strcat(buffer, start);
          *ptr = old;
          switch (old)
          {
          case '{':
            my_level++;
            if (ptr == start) strcat(buffer, " {");
            else strcat(buffer, "{");
            add = FALSE;
            break;
          case '}':
            if (!my_level) yell("Extra } encoutered in [%s]", start);
            else {
              my_level--;
              strcat(buffer, "}");
              if (ptr[1]) add = FALSE;
              else add = TRUE;
            }
            break;
          case ';':
            strcat(buffer, ";");
            add = FALSE;
            break;
          }
          start = ptr + 1;
        } else {
          strcat(buffer, start);
          start = NULL;
        }
      } /* while (start && *start) */
    } else break;
  } /* for (;;) */
  if (*buffer) {
    if (my_level) yell("Unexpected EOF");
    else parse_line(buffer, NULL, FALSE, FALSE);
  }
}

/* ---------------------------------------------------------------------- */
void load_file(char *filename, int varpar, char *subparams)
{
  FILE *file = NULL;
  char path[MAXLEN], *walk, one_path[MAXLEN], buffer[MAXLEN];
  int disp, old;

  if (!get_variable("LOAD_PATH", NULL, path))
    yell("Could not get load path");
  walk = path;
  while (!file) {
    if (!grab_word(&walk, ' ', one_path)) break;
    (void)sprintf(buffer, "%s%s", one_path, filename);
    file = fopen(buffer, "r");
  }
  if (!file) file = fopen(filename, "r");
  if (!file) {
/* can you say hack? I knew you could. */
    if (strcmp(filename, "sys$login:.ircrc") != 0)
      say("*** Could not load [%s]", filename);
    return;
  }

  if (++load_depth>10) {
    load_depth--;
    yell("*** Too many nested loads - %d!", load_depth);
    return;
  }
  disp = getivar(VAR_DISPLAY);
  old = sys$setast(0);
  setivar(VAR_DISPLAY, -1);
  raw_load_file(file);
  if (fclose(file)==-1) yell("error closing file in load");
  if (getivar(VAR_DISPLAY)==-1)
    setivar(VAR_DISPLAY, disp);
  if (old==SS$_WASSET) sys$setast(1);
  load_depth--;
}
