#include <stddef.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>

#include "sysdep.h"
#include "memory.h"
#include "useful.h"
#include "opvalscan.h"
#include "RMFBuffer.h"

enum scan_state_en {
  SCAN_START,
  SCAN_OP,
  SCAN_VAL,
  SCAN_QUOTED_VAL,
  SCAN_END
  };

NORET
Alopvalscan(input,operator,value)
     const char *input;
     char *operator;
     char *value;
{
  enum scan_state_en cur_state = SCAN_START;
  char ch;
  Bool BS;

  while (cur_state != SCAN_END) {
    BS=Bool_FALSE;
    ch = *input++;
    if (!ch) break;
    if (ch=='\\') {
      ch = *input++;
      BS=Bool_TRUE;
    }
    switch (cur_state) {
    case SCAN_START:
      if (isspace(ch))
	;			/* just keep scanning */
      else if (ch == '"')
	cur_state = SCAN_QUOTED_VAL;
      else if (ispunct(ch)) {
	*operator++ = ch;
	cur_state = SCAN_OP;
      } else {
	*value++ = ch;
	cur_state = SCAN_VAL;
      }
      break;
    case SCAN_OP:
      if (ch == '"') {
	cur_state = SCAN_QUOTED_VAL;
      } else if (ch == ' ')
	cur_state = SCAN_VAL;
      else 
	*operator++ = ch;
      break;
    case SCAN_VAL:
      *value++ = ch;
      break;
    case SCAN_QUOTED_VAL:
      if (ch == '"') {
	if (BS==Bool_TRUE)
	  *value++ = ch;
	else
	  cur_state = SCAN_END;
      }
      else
	*value++ = ch;
      break;
    default:
      assert(0);
    }
  }
  *value = *operator = '\0';
  return;
}

/*--------------------------------------------------*/
Bool Alopvalmake (buffer,buf_len,op,value)
char *buffer;
int buf_len;
const char *op, *value;
{
  char *buff, c;
  int i, size, opl, vl;

  if (op!=NULL)
    opl=strlen(op);
  else
    opl=0;
  vl=strlen(value);
  size=opl+vl+4;		/* 4 = 1 Space, 2 ", and 1 NUL */
  if (size>buf_len)
    return(Bool_FALSE);
  if (op!=NULL) {
    strcpy(buffer,op);
    buffer[opl]=' ';
    strcpy(buffer+opl+1,value);
    buffer[opl+vl+1]='\0';
  }
  else { /* op==NULL */
    if (ispunct(value[0])) {
      buff[0]='"';
      strcpy(buff+1,value);
      buffer[vl+1]='"';
      buffer[vl+2]='\0';
    }
    else {
      strcpy(buffer,value);
      buffer[vl+1]='\0';
    }
  }
  return(Bool_TRUE);
}

/*--------------------------------------------------*/
/* this needs major speed improvements !!! */
/* this should be expanded to do nonprintables too !!!*/
/*----------------------------------------*/
char* Alopval_expand_quotes(s)
char* s;
{
  RMFBuffer B;
  char t[2], *r;
  int i,l;

  printf("EQin:.%s.\n",s);
  t[1]='\0';
  B=RMFBuffer_create("",20);
  l=strlen(s);
  for (i=0;i<l;i++) {
    if (s[i]==(char)'"') {
      RMFBuffer_append(B,"\\034");  /* store them as base 10 , no octal crap */
    }
    else {
      t[0]=s[i];  /* this should be made into a function */
      RMFBuffer_append(B,t);
    }
  }
  r=RMFBuffer_copy_of_buff(B);  /* use a get_real_buff here for speed */
  RMFBuffer_destroy(B);
  printf("EQ:.%s.\n",r);
  return(r);
}

/*--------------------------------------------------*/
char* Alopval_compress_backslashes(s)
char* s;
{
  RMFBuffer B;
  int i,l;
  char t[4];
  char t2[2], *r;

  printf("CBin:.%s.\n",s);
  t2[1]='\0';
  t[3]='\0';
  B=RMFBuffer_create("",10);
  l=strlen(s);
  for (i=0;i<l;i++) {
    if (s[i]=='\\') {
      t[0]=s[++i];  t[1]=s[++i];  t[2]=s[++i];
      t2[0]=(char)atoi(t);
      RMFBuffer_append(B,t2);
    }
    else {
      t2[0]=s[i];
      RMFBuffer_append(B,t2);
    }
  }
  r=RMFBuffer_copy_of_buff(B);  /* use a get_real_buff here for speed */
  RMFBuffer_destroy(B);
  printf("CB:.%s.\n",r);
  return(r);
}

/*--------------------------------------------------*/
NORET Alopval_free(s)
char *s;
{
  Memory_free(s);
}
