/* This file is part of the Project Athena Zephyr Notification System.
 * It contains support functions for the windowgram description compiler.
 *
 *	Created by:	Mark W Eichin
 *
 *	$Source: /mit/zephyr/src/zwgc/RCS/support.c,v $
 *	$Author: eichin $
 *
 *	Copyright (c) 1987 by the Massachusetts Institute of Technology.
 *	For copying and distribution information, see the file
 *	"mit-copyright.h". 
 */

#include <zephyr/mit-copyright.h>

#ifndef lint
static char rcsid_scanner_c[] = "$Header: support.c,v 2.3 88/07/10 22:11:22 eichin Exp $";
#endif lint

#include <stdio.h>
#include "ropes.h"
#include "support.h"
#define CMDCODES		/* to bring in the actual names... */
#include "cmds.h"

int max_vars;
int max_raws;

char **variables;
char **raw_table;

void token_init()
{
  max_vars = MAXTAB;
  variables = (char **)malloc(max_vars*sizeof(char *));
  bzero(variables, max_vars*sizeof(char *));
  
  max_raws = MAXRAWTAB;
  raw_table = (char **)malloc(max_raws*sizeof(char *));
  bzero(raw_table, max_raws*sizeof(char *));
}

Parse_Error(text)
     char *text;
{
  printf("zwgc:support Error message was %s, ignorning...\n", text);
}

Error(text)
     char *text;
{
  printf("zwgc:support Error message was %s, ABORTING!\n", text);
  fflush(stdout);
  abort();
}

#define TOKEN_ERR -1
rope tokenize__(string, len, table_in, table_out, tp1, tp2, mx)
     char *string;
     int len;
     char *table_in[], *table_out[];
     rope_type tp1, tp2;
     int *mx;
{
  rope ro;

  ro.typ = tp1;
  ro.ind.ex = token_casefind(string, len, table_in);
  if (ro.ind.ex == TOKEN_ERR)
    {
      ro.typ = tp2;
      ro.ind.ex = token_add(string, len, table_out, mx);
    }
  return(ro);
}

rope tokenizecase__(string, len, table_in, table_out, tp1, tp2, mx)
     char *string;
     int len;
     char *table_in[], *table_out[];
     rope_type tp1, tp2;
     int *mx;
{
  rope ro;

  ro.typ = tp1;
  ro.ind.ex = token_find(string, len, table_in);
  if (ro.ind.ex == TOKEN_ERR)
    {
      ro.typ = tp2;
      ro.ind.ex = token_add(string, len, table_out, mx);
    }
  return(ro);
}

rope tokenize_variable(string, len)
     char *string;
     int len;
{
  rope ro;
  int tmpr;
  
  if(*string == '$')		/* is this needed? hmm... */
    {
      string++;
      len--;
    }
  if((tmpr=atoi(string))>0)
    {
      ro.typ = FIELD;
      ro.ind.ex = tmpr-1;
      return(ro);
    }
  ro.typ = HEAD;
  ro.ind.ex = token_casefind(string, len, table_heads);
  if(ro.ind.ex == TOKEN_ERR)
    {
      return(tokenize__(string, len, variables, variables,
			VAR, VAR, &max_vars));
    }
  else
    return(ro);
}	

rope tokenize_command(string, len)
     char *string;
     int len;
{
  return(tokenize__(string, len, table_commands, raw_table,
		    COMMAND, RAW, &max_raws));
}

rope tokenize_show(string, len)
     char *string;
     int len;
{
  return(tokenize__(string, len, table_shows, raw_table,
		    SHOW, RAW, &max_raws));
}

rope tokenize_raw(string, len)
     char *string;
     int len;
{
  return(tokenizecase__(string, len, raw_table, raw_table,
		    RAW, RAW, &max_raws));
}

rope tokenize_separator(c)	/* ??? */
     char c;
{
  rope ro;
  ro.typ = RAW;
  ro.ind.ex = token_find(&c, 1, raw_table);
  if (ro.ind.ex == TOKEN_ERR)
    {
      ro.ind.ex = token_add(&c, 1, raw_table, &max_raws);
    }
  return(ro);
}

int token_casefind(string, len, table)
     char *string;
     int len;
     char *table[];
{
  int i = 0;

  while(table[i])
    {
      if((strlen(table[i]) == len)
	 && !strncasecmp(table[i],string,len))
	break;
      i++;
    }
  if(table[i])
    {
      return(i);
    }
  else
    return(TOKEN_ERR);
}

int token_find(string, len, table)
     char *string;
     int len;
     char *table[];
{
  int i = 0;

  while(table[i])
    {
      if((strlen(table[i]) == len)
	 && !strncmp(table[i],string,len))
	break;
      i++;
    }
  if(table[i])
    {
      return(i);
    }
  else
    return(TOKEN_ERR);
}


int token_add(string, len, table, mx)
     char *string;
     int len;
     char *table[];
     int *mx;
{
  int i = -1;
  char *realloc();

  while(table[++i]);

  if(i+1 >= *mx)		/* always allow a null pad */
    {
      *mx <<= 1;
      table = (char **)realloc(table, (*mx)*sizeof(char *));
      bzero(&table[i],i * sizeof(char *));
    }
  
  table[i] = strndup(string, len);
  table[i][len] = '\0';
  
  return(i);
}


