/* in this module appeaars machinery connected with the recognition
   storage of words */

#include "align.h"     /* align definitions */
/* VAX/VMS version
#include <unixio>
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>


/* externals from errors.c */
extern goof(); /* error-writing routine
  void goof(char *s); */
extern int sinned, error; /* error-flags */

/* externals from slurp.c */
extern char *input_pointer;
extern nextchar(); /* gets next character
  char nextchar(); */
extern peekchar(); /* peeks at next char
  char peekchar() */
extern advance();  /* advances to next printing char
  void advance(); */

/* externals from glosses */
extern char delmark;     /* example delimiter */
extern int wordmax;      /* maximum length of word */

/* word storage */

static char store[charmax];  /* array for storing string */
static char *free_char;      /* pointer to first available position */
static char *top_char;       /* pointer to top of store */

/* initializes store */
init_store()
{
  free_char = store;
  top_char = store+charmax;
}

/* stows characters */
int stow(c)
char c;
{
  if (free_char<top_char) {
    *(free_char++) = c;
    return(TRUE);
  }
  else {
    goof("too many characters in example");
  }
}


static int envpointer; /* keeps track of group nesting */

void readword(here, stop, quit, grab, lookahead)
word *here;      /* location of word record to be filled in */
int *stop;       /* where to record whether stop-delimiter encountered */
int (*quit)();          /* function specifying whether to stop */
char (*grab)();  /* character-reading procedure to be used */
int lookahead;   /* whether to advance to next printing char */
{

  char c;                 /* character holder */

  *stop = FALSE;
  envpointer = 0;

  here->loc=free_char;
  c=grab();
  while (envpointer > 0 || !quit(c)) {  /* there is nothing
      in the stack, or neither of the word-enders encountered */
    stow(c);
    if (error) return;
    else
    if (c == '\\') {
      if (peekchar() == ' ') {
	grab(c);
	stow(c);
      }
    }
    else
    if (c == '{')
      envpointer++;
    if (envpointer > 0 && c == '}')
      envpointer--;
    c=grab();
    if (c == delmark && envpointer > 0) {
      goof("line-break within TeX command");
      envpointer = 0;
    }
  }

  stow('\0'); /* mark end of word i store */
  if (c == delmark) *stop = TRUE;
  if (!*stop) {
    if (lookahead) {
      advance();
      if (peekchar()==delmark) {
	*stop = TRUE;
	nextchar();
      }
    }
  }
}

/* scantil_c
  looks for the first instance in arg2 of some char in arg1; returns 1
  if found; otherwise 0; arg3 points to char if found, arg2
  otherwise */

int scantil_c(forchars,instring,wherefound)
char *forchars;
char *instring;
char **wherefound;
{
  char *whichchar;
  char *locus;

  locus = instring;


  while (*locus != NULL) {
    whichchar = forchars;
    while (*whichchar !=NULL) {
      if (*whichchar  == *locus) {
	*wherefound = locus;
	return(TRUE);
      }
      else whichchar++;
    }
    locus++;
  }
  *wherefound = instring;
  return(FALSE);
}

void stow_stuff(from,to)
char *from;
char *to;
{
  while (from != to) {
    stow(*from);
    from++;
  }
  input_pointer = to;
}

void pull_args(locus)
char **locus;
{
  char *nextloc;

  while (**locus == '{') {
    scantil_c("}{",(*locus)+1,&nextloc);
    if (*nextloc == '}') {
      nextloc++;
      if (*nextloc == '{') {
	*locus = nextloc;
      }
      else break;
    }
    else break;
  }
}



/* command is parsed as anything between \ and a member of the
   1st arg. of scantil_c.  pull_args gets all args but last,
   not allowing embedded commands in these (for labels, etc). */

void get_command()
{
  char *locus;

  scantil_c("{ \\|$_^",input_pointer,&locus);
  pull_args(&locus);
  stow_stuff(input_pointer,locus);

}



/* readword hacked for the peculiar demands of the `columns'
module, essentially being that length calculations are done so
that alignments can be worked out on the screen */

void readword_col(here, bar, quit)
word *here;      /* location of word record to be filled in */
int *bar;       /* where to record whether bar-delimiter encountered */
int (*quit)();          /* function specifying whether to stop */
{

  char c,d;                 /* character holder */
  int size;

  *bar = FALSE;
  envpointer = 0;

  here->loc=free_char;
  size=0;
  c=nextchar();
  while (envpointer > 0 || !quit(c)) {  /* there is nothing
      in the stack, or neither of the word-enders encountered */
    stow(c);
    if (error) return;
    else
    if (c == '\\') {
       get_command();
       if ((d = peekchar()) != '{')
	 size++;
    }
    else
    if (c == '{')
      envpointer++;
    else
    if (envpointer > 0 && c == '}')
      envpointer--;
    else
    if (c == '$') {}
    else
    size++;
    c=nextchar();
    if (c == delmark && envpointer > 0) {
      goof("line-break within TeX command");
      envpointer = 0;
    }
  }
  stow('\0'); /* mark end of word i store */
  here->size = size;
  if (c == '|') *bar = TRUE;

}

/* writes words to a stream */
void writeword(out,it)
FILE *out;
word *it;
{
  fprintf(out,"{%s}",it->loc);
}

/*
char delmark = '\\';
int  wordmax = 60;

main()
{
word sample;
int stop;

get_com_widths("widths.dat");
open_source("text.dat");
init_store();


advance();
readword(&sample,&stop,' ',nextchar,0);
printf("%s, size = %d, bracket= %d\n",sample.loc,sample.size,sample.bracket);
if (stop) printf("stop!\n");

}

*/

/*

char delmark;

main(argc,argv)
int argc;
char **argv;
{
  char **s;
  int whether;

  whether = scantil_c(argv[1],argv[2],s);

  if (whether) {
    puts("yes: ");
  }
  else puts("no: ");
  puts(*s);
}
*/

