/* -----------------------------------------------------------------------------

 TeX parser ©1996 BURGHARD Eric
    ScanLib ©1996 Dietmar Eiler

 GoldED syntax parser library (uses a syntax cache).
 Highlight TeX instructions, comments, arguments, options, spell errors

 Private code
 -------------------------------------------------------------------------------
*/

/// "Includes"

#include "defs.h"
#define CATCOMP_NUMBERS
#include "locale.h"
#include "funcs.h"
#include "private.h"
#include "debug.h"

///
/// "Definitions"

//Declared in funcs.c
extern struct Library *SysBase, *DOSBase, *LibBase, *RexxSysBase;
extern BPTR SegList;
extern struct LocaleInfo li;

char dimkeys[]="bpcccmemexinmmpcptsp";
int (* const parser[])(struct ParseInfo *)={fINT,fCHK,fINS,fINSD,fINSH,fARG,fARGD,fNBH,
                                     fNBHD,fNBO,fNBOD,fASC,fSIG,fNBR,fDEC,fDECD,
                                     fASCD};
void (* const endparser[])(struct ParseInfo *)={feVOID,feCHK,feVOID,feINSD,feINSH,feVOID,
                                         feARGD,feVOID,feNBHD,feVOID,feNBOD,feVOID,
                                         feVOID,feNBR,feVOID,feDECD,feVOID,feVOID};
extern int (* const parseint[256])(struct ParseInfo *);
extern int (* const parsesig[256])(struct ParseInfo *);

///
/// "Private functions"

/* -------------------------------- ParseString --------------------------------

 Parse a string, build a syntax description.
 Return EMPTY_STACK in case there is nothing to highlight.

*/

struct SyntaxChunk *
ParseString(UBYTE *text, UWORD len, ULONG scanID)
{   int etat=INT;
    struct ParseInfo pinfo;

    #ifdef DEBUG
      DbgPrintf("\nParseString(\"%s\", %d, $%08lx)\n", text, len, scanID);
    #endif

    if (len)
    {   pinfo.syntaxStack = ((struct BufferHandle *)scanID)->bh_SyntaxStack;
        pinfo.sstkind=0;
        pinfo.scanID=scanID;
        pinfo.text=text;
        // trailing spaces have to be ignored
        while (len && (pinfo.text[len - 1] == ' '))
            --len;
        // leading spaces have to be ignored
        for (pinfo.start = 0; len && (text[pinfo.start] == ' '); ++pinfo.start, --len);
        pinfo.end=pinfo.start;
        pinfo.endstr=pinfo.start+len;

        #ifdef DEBUG
          DbgPrintf("start=%d\tlen=%d\tendstr=%d\n", pinfo.start, len, pinfo.endstr);
        #endif

        while ((pinfo.end < pinfo.endstr) && (etat != END))
          etat=parser[etat](&pinfo);

        endparser[etat](&pinfo);

        if (pinfo.sstkind != 0)
        { pinfo.syntaxStack[pinfo.sstkind].sc_Level = FALSE;
          pinfo.syntaxStack[pinfo.sstkind].sc_Start = FALSE;
          pinfo.syntaxStack[pinfo.sstkind].sc_End   = FALSE;
          return(pinfo.syntaxStack);
        }
        else
          return(EMPTY_STACK);
    }
    else
      return(EMPTY_STACK);
}

/*
/* Parser functions called at end of parsing
/**/

// Hidden Instruction
void feINSH(struct ParseInfo *pinfo)
{
  pinfo->syntaxStack[pinfo->sstkind].sc_Level = INTH;
  pinfo->syntaxStack[pinfo->sstkind].sc_Start = pinfo->start;
  pinfo->syntaxStack[pinfo->sstkind].sc_End   = (isalpha(pinfo->text[pinfo->end])) ? pinfo->end : pinfo->end-1;

  #ifdef DEBUG
    DbgPrintf("Instruction: start=%d end=%d\n", pinfo->start, (isalpha(pinfo->text[pinfo->end])) ? pinfo->end : pinfo->end-1);
  #endif

  pinfo->sstkind++;
}

// Instruction
void feINSD(struct ParseInfo *pinfo)
{
  pinfo->syntaxStack[pinfo->sstkind].sc_Level = INTL;
  pinfo->syntaxStack[pinfo->sstkind].sc_Start = pinfo->start;
  pinfo->syntaxStack[pinfo->sstkind].sc_End   = (isalpha(pinfo->text[pinfo->end])) ? pinfo->end : pinfo->end-1;

  #ifdef DEBUG
    DbgPrintf("Instruction: start=%d end=%d\n", pinfo->start, (isalpha(pinfo->text[pinfo->end])) ? pinfo->end : pinfo->end-1);
  #endif

  pinfo->sstkind++;
}

// Macro Argument
void feARGD(struct ParseInfo *pinfo)
{
  pinfo->syntaxStack[pinfo->sstkind].sc_Level = MACA;
  pinfo->syntaxStack[pinfo->sstkind].sc_Start = pinfo->start;
  pinfo->syntaxStack[pinfo->sstkind].sc_End   = (isdigit(pinfo->text[pinfo->end])) ? pinfo->end : pinfo->end-1;

  #ifdef DEBUG
    DbgPrintf("Argument Macro: start=%d end=%d\n", pinfo->start, (isdigit(pinfo->text[pinfo->end])) ? pinfo->end : pinfo->end-1);
  #endif

  pinfo->sstkind++;
}

// Number
void feNBR(struct ParseInfo *pinfo)
{
  pinfo->syntaxStack[pinfo->sstkind].sc_Level = NBRE;
  pinfo->syntaxStack[pinfo->sstkind].sc_Start = pinfo->start;
  pinfo->syntaxStack[pinfo->sstkind].sc_End   = (isdigit(pinfo->text[pinfo->end])) ? pinfo->end : pinfo->end-1;

  #ifdef DEBUG
    DbgPrintf("Nombre: start=%d end=%d\n", pinfo->start, (isdigit(pinfo->text[pinfo->end])) ? pinfo->end : pinfo->end-1);
  #endif

  pinfo->sstkind++;
}

// Octal Number
void feNBOD(struct ParseInfo *pinfo)
{
  pinfo->syntaxStack[pinfo->sstkind].sc_Level = NBRE;
  pinfo->syntaxStack[pinfo->sstkind].sc_Start = pinfo->start;
  pinfo->syntaxStack[pinfo->sstkind].sc_End   = (isxdigit(pinfo->text[pinfo->end])) ? pinfo->end : pinfo->end-1;

  #ifdef DEBUG
    DbgPrintf("Nombre Octal: start=%d end=%d\n", pinfo->start, (isxdigit(pinfo->text[pinfo->end])) ? pinfo->end : pinfo->end-1);
  #endif

  pinfo->sstkind++;
}

// Hexadecimal Number
void feNBHD(struct ParseInfo *pinfo)
{
  pinfo->syntaxStack[pinfo->sstkind].sc_Level = NBRE;
  pinfo->syntaxStack[pinfo->sstkind].sc_Start = pinfo->start;
  pinfo->syntaxStack[pinfo->sstkind].sc_End   = (isodigit(pinfo->text[pinfo->end])) ? pinfo->end : pinfo->end-1;

  #ifdef DEBUG
    DbgPrintf("Nombre Hexadécimal: start=%d end=%d\n", pinfo->start, (isodigit(pinfo->text[pinfo->end])) ? pinfo->end : pinfo->end-1);
  #endif

  pinfo->sstkind++;
}

// Do nothing
void feVOID(struct ParseInfo *pinfo)
{
}

// Word to check
void feCHK(struct ParseInfo *pinfo)
{
#ifdef ISPELL
  #ifdef DEBUG
    DbgPrintf("Mot: start=%d end=%d\n", pinfo->start, pinfo->end-1);
  #endif

  if (((struct BufferHandle *)pinfo->scanID)->bh_ISpellCheck)
  { if (CheckThisWord(pinfo->scanID, pinfo->text+pinfo->start, pinfo->end-pinfo->start))
    { pinfo->syntaxStack[pinfo->sstkind].sc_Level = ISPE;
      pinfo->syntaxStack[pinfo->sstkind].sc_Start = pinfo->start;
      pinfo->syntaxStack[pinfo->sstkind].sc_End   = (isword(pinfo->text[pinfo->end])) ? pinfo->end : pinfo->end-1;
      pinfo->sstkind++;
    }
  }
  else if (FindPort("IRexxSpell"))
    ((struct BufferHandle *)pinfo->scanID)->bh_ISpellCheck=TRUE;
#endif
}

// Real Number
void feDECD(struct ParseInfo *pinfo)
{
  pinfo->syntaxStack[pinfo->sstkind].sc_Level = NBRE;
  pinfo->syntaxStack[pinfo->sstkind].sc_Start = pinfo->start;
  pinfo->syntaxStack[pinfo->sstkind].sc_End   = (isdigit(pinfo->text[pinfo->end])) ? pinfo->end : pinfo->end-1;

  #ifdef DEBUG
    DbgPrintf("Nombre réel: start=%d end=%d\n", pinfo->start, (isdigit(pinfo->text[pinfo->end])) ? pinfo->end : pinfo->end-1);
  #endif

  pinfo->sstkind++;
}

/*
/* Functions called through parseint tab
/**/

// '\'
int fasl(struct ParseInfo *pinfo)
{
  pinfo->start=pinfo->end++;
  return(INS);
}

// '#'
int fdis(struct ParseInfo *pinfo)
{
  pinfo->start=pinfo->end++;
  return(ARG);
}

// '"'
int fgui(struct ParseInfo *pinfo)
{
  pinfo->start=pinfo->end++;
  return(NBH);
}

// '''
int fapo(struct ParseInfo *pinfo)
{
  pinfo->start=pinfo->end++;
  return(NBO);
}

// '`'
int fquo(struct ParseInfo *pinfo)
{
  pinfo->start=pinfo->end++;
  return(ASC);
}

// '+','-'
int fpmi(struct ParseInfo *pinfo)
{
  pinfo->start=pinfo->end++;
  return(SIG);
}

// ',' & '.'
int fvir(struct ParseInfo *pinfo)
{
  pinfo->start=pinfo->end++;
  return(DEC);
}

// '0'...'9'
int fnum(struct ParseInfo *pinfo)
{
  pinfo->start=pinfo->end++;
  return(NBR);
}

// '}' & '{'
int faco(struct ParseInfo *pinfo)
{
  #ifdef DEBUG
    DbgPrintf("Groupe: start=%d end=%d\n", pinfo->end, pinfo->end);
  #endif

  pinfo->syntaxStack[pinfo->sstkind].sc_Level = GRPE;
  pinfo->syntaxStack[pinfo->sstkind].sc_Start = pinfo->end;
  pinfo->syntaxStack[pinfo->sstkind].sc_End   = pinfo->end;
  pinfo->sstkind++;
  pinfo->start=++pinfo->end;
  return(INT);
}

// '[' & ']'
int fcro(struct ParseInfo *pinfo)
{
  #ifdef DEBUG
    DbgPrintf("Options: start=%d end=%d\n", pinfo->end, pinfo->end);
  #endif

  pinfo->syntaxStack[pinfo->sstkind].sc_Level = OPTI;
  pinfo->syntaxStack[pinfo->sstkind].sc_Start = pinfo->end;
  pinfo->syntaxStack[pinfo->sstkind].sc_End   = pinfo->end;
  pinfo->sstkind++;
  pinfo->start=++pinfo->end;
  return(INT);
}

// '$'
int fdol(struct ParseInfo *pinfo)
{
  #ifdef DEBUG
    DbgPrintf("Mode Mathématique: start=%d end=%d\n", pinfo->end, pinfo->end);
  #endif

  pinfo->syntaxStack[pinfo->sstkind].sc_Level = MATH;
  pinfo->syntaxStack[pinfo->sstkind].sc_Start = pinfo->end;
  pinfo->syntaxStack[pinfo->sstkind].sc_End   = pinfo->end;
  pinfo->sstkind++;
  pinfo->start=++pinfo->end;
  return(INT);
}

// '~'
int ftil(struct ParseInfo *pinfo)
{
  #ifdef DEBUG
    DbgPrintf("Caractère insécable: start=%d end=%d\n", pinfo->end, pinfo->end);
  #endif

  pinfo->syntaxStack[pinfo->sstkind].sc_Level = INSC;
  pinfo->syntaxStack[pinfo->sstkind].sc_Start = pinfo->end;
  pinfo->syntaxStack[pinfo->sstkind].sc_End   = pinfo->end;
  pinfo->sstkind++;
  pinfo->start=++pinfo->end;
  return(INT);
}

// '^' & '_'
int fiex(struct ParseInfo *pinfo)
{
  #ifdef DEBUG
    DbgPrintf("Indice-Exposant: start=%d end=%d\n", pinfo->end, pinfo->end);
  #endif

  pinfo->syntaxStack[pinfo->sstkind].sc_Level = MTHS;
  pinfo->syntaxStack[pinfo->sstkind].sc_Start = pinfo->end;
  pinfo->syntaxStack[pinfo->sstkind].sc_End   = pinfo->end;
  pinfo->sstkind++;
  pinfo->start=++pinfo->end;
  return(INT);
}

// '%'
int fpou(struct ParseInfo *pinfo)
{
  pinfo->start=pinfo->end;

  #ifdef DEBUG
    DbgPrintf("Commentaire: start=%d end=%d\n", pinfo->start, pinfo->endstr-1);
  #endif

  pinfo->syntaxStack[pinfo->sstkind].sc_Level = COMM;
  pinfo->syntaxStack[pinfo->sstkind].sc_Start = pinfo->start;
  pinfo->syntaxStack[pinfo->sstkind].sc_End   = pinfo->endstr-1;
  pinfo->sstkind++;
  return(END);
}

// default
int fdef(struct ParseInfo *pinfo)
{
  #ifdef ISPELL
  if (isword(pinfo->text[pinfo->end]))
  { pinfo->start=pinfo->end++;
    return(CHK);
  }
  else
  #endif
  pinfo->end++;
  return(INT);
}

/*
/* Functions called through parsesig tab (+ or - has been encountered)
/**/

// '"'
int gquo(struct ParseInfo *pinfo)
{
  pinfo->end++;
  return(NBH);
}

// '''
int gasl(struct ParseInfo *pinfo)
{
  pinfo->end++;
  return(NBO);
}

// ',' & '.'
int gvir(struct ParseInfo *pinfo)
{
  pinfo->end++;
  return(DEC);
}

// '0'...'9'
int gnum(struct ParseInfo *pinfo)
{
  pinfo->end++;
  return(NBR);
}

// default
int gdef(struct ParseInfo *pinfo)
{
  pinfo->start=pinfo->end;
  return(INT);
}

// Hexadecimal number
int fNBH(struct ParseInfo *pinfo)
{
  if (!isxdigit(pinfo->text[pinfo->end]))
  { pinfo->start=pinfo->end;
    return(INT);
  }
  else
  { pinfo->end++;
    return(NBHD);
  }
}

/*
/* Functions called through the parser tab
/**/

// Initial State
int fINT(struct ParseInfo *pinfo)
{
   return(parseint[pinfo->text[pinfo->end]](pinfo));
}

// Word to check
int fCHK(struct ParseInfo *pinfo)
{
#ifdef ISPELL
  if (!isword(pinfo->text[pinfo->end]))
  {
    #ifdef DEBUG
      DbgPrintf("Mot: start=%d end=%d\n", pinfo->start, pinfo->end-1);
    #endif

    if (CheckThisWord(pinfo->scanID, pinfo->text+pinfo->start, pinfo->end-pinfo->start))
    { pinfo->syntaxStack[pinfo->sstkind].sc_Level = ISPE;
      pinfo->syntaxStack[pinfo->sstkind].sc_Start = pinfo->start;
      pinfo->syntaxStack[pinfo->sstkind].sc_End   = pinfo->end-1;
      pinfo->sstkind++;
    }
    pinfo->start=pinfo->end;
    return(INT);
  }
  else
    pinfo->end++;
#endif
  return(CHK);
}

// Instruction (common part)
int fINS(struct ParseInfo *pinfo)
{
  if (!isalpha(pinfo->text[pinfo->end]))
  { if (pinfo->text[pinfo->end] == ')' || pinfo->text[pinfo->end] =='(') {
      pinfo->syntaxStack[pinfo->sstkind].sc_Level = MATH;
      pinfo->syntaxStack[pinfo->sstkind].sc_Start = pinfo->start;
      pinfo->syntaxStack[pinfo->sstkind].sc_End   = pinfo->end;
    }
    else
    { pinfo->syntaxStack[pinfo->sstkind].sc_Level = INTS;
      pinfo->syntaxStack[pinfo->sstkind].sc_Start = pinfo->start;
      pinfo->syntaxStack[pinfo->sstkind].sc_End   = pinfo->end;
    }
    pinfo->sstkind++;
    pinfo->start=++pinfo->end;
    return(INT);
  }
  else
  { pinfo->end++;
    return(INSD);
  }
}

// Hidden Instruction
int fINSH(struct ParseInfo *pinfo)
{
  if (!isalpha(pinfo->text[pinfo->end]))
  { if (pinfo->text[pinfo->end] == '@')
    { pinfo->end++;
      return(INSH);
    }
    else
    { pinfo->syntaxStack[pinfo->sstkind].sc_Level = INTH;
      pinfo->syntaxStack[pinfo->sstkind].sc_Start = pinfo->start;
      pinfo->syntaxStack[pinfo->sstkind].sc_End   = pinfo->end-1;

      #ifdef DEBUG
        DbgPrintf("Instruction: start=%d end=%d\n", pinfo->start, pinfo->end-1);
      #endif

      pinfo->sstkind++;
      pinfo->start=pinfo->end;
      return(INT);
    }
  }
  else
    pinfo->end++;
  return(INSH);
}

// Long Instruction
int fINSD(struct ParseInfo *pinfo)
{
  if (!isalpha(pinfo->text[pinfo->end]))
  { if (pinfo->text[pinfo->end] == '@')
    { pinfo->end++;
      return(INSH);
    }
    else
    { pinfo->syntaxStack[pinfo->sstkind].sc_Level = INTL;
      pinfo->syntaxStack[pinfo->sstkind].sc_Start = pinfo->start;
      pinfo->syntaxStack[pinfo->sstkind].sc_End   = pinfo->end-1;

      #ifdef DEBUG
        DbgPrintf("Instruction: start=%d end=%d\n", pinfo->start, pinfo->end-1);
      #endif

      pinfo->sstkind++;
      pinfo->start=pinfo->end;
      return(INT);
    }
  }
  else
    pinfo->end++;
  return(INSD);
}

// Macro Argument
int fARG(struct ParseInfo *pinfo)
{
  if (!isdigit(pinfo->text[pinfo->end]))
  { pinfo->start=pinfo->end;
    return(INT);
  }
  else
  { pinfo->end++;
    return(ARGD);
  }
}

// Macro Argument
int fARGD(struct ParseInfo *pinfo)
{
  if (!isdigit(pinfo->text[pinfo->end]))
  { pinfo->syntaxStack[pinfo->sstkind].sc_Level = MACA;
    pinfo->syntaxStack[pinfo->sstkind].sc_Start = pinfo->start;
    pinfo->syntaxStack[pinfo->sstkind].sc_End   = pinfo->end-1;

    #ifdef DEBUG
      DbgPrintf("Arguments Macro: start=%d end=%d\n", pinfo->start, pinfo->end-1);
    #endif

    pinfo->sstkind++;
    pinfo->start=pinfo->end;
    return(INT);
  }
  else
    pinfo->end++;
  return(ARGD);
}

// Sign + or -
int fSIG(struct ParseInfo *pinfo)
{
  return(parsesig[pinfo->text[pinfo->end]](pinfo));
}

// Hexadecimal number
int fNBHD(struct ParseInfo *pinfo)
{
  if (!isxdigit(pinfo->text[pinfo->end]))
  { pinfo->syntaxStack[pinfo->sstkind].sc_Level = NBRE;
    pinfo->syntaxStack[pinfo->sstkind].sc_Start = pinfo->start;
    pinfo->syntaxStack[pinfo->sstkind].sc_End   = pinfo->end-1;

    #ifdef DEBUG
      DbgPrintf("Nombre Hexadecimal: start=%d end=%d\n", pinfo->start, pinfo->end-1);
    #endif

    pinfo->sstkind++;
    pinfo->start=pinfo->end;
    return(INT);
  }
  else
    pinfo->end++;
  return(NBHD);
}

// Octal number
int fNBO(struct ParseInfo *pinfo)
{
  if (!isodigit(pinfo->text[pinfo->end]))
  { pinfo->start=pinfo->end;
    return(INT);
  }
  else
  { pinfo->end++;
    return(NBOD);
  }
}

// Octal Number
int fNBOD(struct ParseInfo *pinfo)
{
  if (!isodigit(pinfo->text[pinfo->end]))
  { pinfo->syntaxStack[pinfo->sstkind].sc_Level = NBRE;
    pinfo->syntaxStack[pinfo->sstkind].sc_Start = pinfo->start;
    pinfo->syntaxStack[pinfo->sstkind].sc_End   = pinfo->end-1;

    #ifdef DEBUG
      DbgPrintf("Nombre Octal: start=%d end=%d\n", pinfo->start, pinfo->end-1);
    #endif

    pinfo->sstkind++;
    pinfo->start=pinfo->end;
    return(INT);
  }
  else
    pinfo->end++;
  return(NBOD);
}

// Number
int fNBR(struct ParseInfo *pinfo)
{ int etat=NBR;

  if (pinfo->text[pinfo->end] == '.' || pinfo->text[pinfo->end] == ',')
  { pinfo->end++;
    etat=DECD;
  }
  else if (!isdigit(pinfo->text[pinfo->end]))
  { char *k;
    int t;

    for (t=pinfo->end; pinfo->text[t] == ' '; t++);
    for (k=dimkeys; *k != '\0'; k+=2)
    { if (k[0] == pinfo->text[t] && k[1] == pinfo->text[t+1])
      { pinfo->syntaxStack[pinfo->sstkind].sc_Level = DIME;
        pinfo->syntaxStack[pinfo->sstkind].sc_Start = pinfo->start;
        pinfo->syntaxStack[pinfo->sstkind].sc_End   = t+1;
        #ifdef DEBUG
          DbgPrintf("Dimension: start=%d end=%d\n", pinfo->start, t);
        #endif
        pinfo->sstkind++;
        pinfo->start=t+2;
        etat=INT;
        break;
      }
    }
    if (*k == '\0')
    { pinfo->syntaxStack[pinfo->sstkind].sc_Level = NBRE;
      pinfo->syntaxStack[pinfo->sstkind].sc_Start = pinfo->start;
      pinfo->syntaxStack[pinfo->sstkind].sc_End   = pinfo->end-1;
      #ifdef DEBUG
        DbgPrintf("Nombre: start=%d end=%d\n", pinfo->start, pinfo->end-1);
      #endif
      pinfo->sstkind++;
      pinfo->start=pinfo->end;
      etat=INT;
    }
  }
  else
    pinfo->end++;
  return(etat);
}

// Decimal Number
int fDEC(struct ParseInfo *pinfo) 
{
  if (!isdigit(pinfo->text[pinfo->end]))
  { pinfo->start=pinfo->end;
    return(INT);
  }
  else
  { pinfo->end++;
    return(DECD);
  }
}

// Decimal Number
int fDECD(struct ParseInfo *pinfo) 
{ int etat=DECD;
  if (!isdigit(pinfo->text[pinfo->end]))
  { char *k;
    int t;

    for (t=pinfo->end; pinfo->text[t] == ' '; t++);
    for (k=dimkeys; *k != '\0'; k+=2)
    { if (k[0] == pinfo->text[t] && k[1] == pinfo->text[t+1])
      { pinfo->syntaxStack[pinfo->sstkind].sc_Level = DIME;
        pinfo->syntaxStack[pinfo->sstkind].sc_Start = pinfo->start;
        pinfo->syntaxStack[pinfo->sstkind].sc_End   = t+1;
        #ifdef DEBUG
          DbgPrintf("Dimension: start=%d end=%d\n", pinfo->start, t);
        #endif
        pinfo->sstkind++;
        pinfo->start=t+2;
        etat=INT;
        break;
      }
    }
    if (*k == '\0')
    { pinfo->syntaxStack[pinfo->sstkind].sc_Level = NBRE;
      pinfo->syntaxStack[pinfo->sstkind].sc_Start = pinfo->start;
      pinfo->syntaxStack[pinfo->sstkind].sc_End   = pinfo->end-1;
      #ifdef DEBUG
        DbgPrintf("Nombre réel: start=%d end=%d\n", pinfo->start, pinfo->end-1);
      #endif
      pinfo->sstkind++;
      pinfo->start=pinfo->end;
      etat=INT;
    }
  }
  else
    pinfo->end++;
  return(etat);
}

int fASC(struct ParseInfo *pinfo)
{
  if (pinfo->text[pinfo->end] == '\\')
  { pinfo->end++;
    return(ASCD);
  }
  else
  { pinfo->start=pinfo->end;
    return(INT);
  }
}

int fASCD(struct ParseInfo *pinfo)
{
  pinfo->syntaxStack[pinfo->sstkind].sc_Level = NBRE;
  pinfo->syntaxStack[pinfo->sstkind].sc_Start = pinfo->start;
  pinfo->syntaxStack[pinfo->sstkind].sc_End   = pinfo->end;
  #ifdef DEBUG
    DbgPrintf("Nombre: start=%d end=%d\n", pinfo->start, pinfo->end);
  #endif
  pinfo->sstkind++;
  pinfo->start=++pinfo->end;
  return(INT);
}


/* --------------------------------- DupStack ----------------------------------

 Duplicate syntax stack (to be FreeVec'ed). Return NULL in case of failure.

*/

struct SyntaxChunk *
DupStack(syntaxStack)

struct SyntaxChunk *syntaxStack;
{
    #ifdef DEBUG
      DbgPrintf("DupStack(syntaxStack=%08x)\n", syntaxStack);
    #endif

    if (syntaxStack && (syntaxStack != EMPTY_STACK)) {

        struct SyntaxChunk *chunk;
        UWORD               elements;

        // determine stack size

        for (elements = 0, chunk = syntaxStack; chunk->sc_Level; ++chunk)
            ++elements;

        // create copy of syntax stack (to be attached to a text line by the caller)

        if (elements) {

            ULONG size = (++elements) * sizeof(struct SyntaxChunk);

            chunk = syntaxStack;

            if (syntaxStack = AllocVec(size, MEMF_PUBLIC))
                movmem(chunk, syntaxStack, size);
        }
        else
            syntaxStack = EMPTY_STACK;
    }

    return(syntaxStack);
}


///
/// "Spell functions"
#ifdef ISPELL
/* ------------------------------- CheckThisWord -------------------------------

 Check word <check> of length <len>. Return TRUE if word is not known. Ignore
 single letters.

*/

BOOL
CheckThisWord(scanID, check, len)

UBYTE  *check;
UWORD   len;
ULONG   scanID;
{

    BOOL error = FALSE;
    UBYTE *command;
    struct BufferHandle *handle;

    #ifdef DEBUG
      DbgPrintf("CheckThisWord(scanID=%08x, check=\"%s\", len=%d)\n", scanID, check, len);
    #endif

    if (len > 1) {

        handle = (struct BufferHandle *)scanID;

        command = handle->bh_Command;

        movmem(check, command, len);

        command[len] = 0;

        strins(command, "QUICKCHECK ");

        // make ISpell check command quickly

        if (SendRexxCommand("IRexxSpell", command, handle->bh_ReplyPort, handle->bh_Results)) {

            // unknown word (not 'ok') ?

            if (stricmp(handle->bh_Results, "ok")) {

                    error = TRUE;

            }
        }
    }

    return(error);
}
#endif
///
