#include "config.h"
/*
 * Copyright (c) 1986, 2014 by The Trustees of Columbia University in
 * the City of New York.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  + Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 *  + Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 *  + Neither the name of Columbia University nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.

 Author: Andrew Lowry
*/
/* cmtok
**
** This module contains handlers for parsing arbitrary token strings.
** A parse succeeds if the current input exactly matches the given
** token, with case insignificant in letters.  No terminating character
** is needed for a successful parse.  Completion succeeds if any
** prefix of the token has been typed.  Full completion adds a space
** after the token as well.  Partial completion will stop after the
** first punctuation char completed. Help text echoes the expected string.
** The standard break table breaks on every single character,
** so CM_WKF parsing will work correctly (since no terminating
** character is required).
**/

#define	TOKERR			/* token error table allocated here */

#include "ccmdlib.h"			/* get standard symbols */
#include "cmfncs.h"		/* and internal symbols */

/* Forward declaration of handler routines */

PASSEDSTATIC int tokcplt ARGS((char *text, int textlen, fdb *fdbp,
	 int full, const char **cplt, int *cpltlen));
PASSEDSTATIC int tokhlp ARGS((char *text, int textlen, fdb *fdbp,
	 int cust, int lines));
PASSEDSTATIC int tokprs ARGS((char *text, int textlen, fdb *fdbp,
	 int *parselen, pval *value));

#define	tokbrk	cmallbk		/* std break table breaks on everything */

ftspec ft_tok = { tokprs, tokhlp, tokcplt, 0, &tokbrk };

/* tokprs
**
** Purpose:
**   Attempt to parse the given token string.  If the string is
**   not completely present in the input, signal an incomplete
**   parse.  If there are any mismatched characters, signal an
**   error.
**/

PASSEDSTATIC int
#if HAVE_STDC
tokprs(char *text, int textlen, fdb *fdbp, int *parselen, pval *value)
#else /* K&R style */
tokprs(text,textlen,fdbp,parselen,value)
char *text;
int textlen;
fdb *fdbp;
int *parselen;
pval *value;
#endif /* HAVE_STDC */
{
  char *tok = (char *) fdbp->_cmdat;	/* point to token string */
  char c1,c2;				/* chars in token and text */
  int toklen;				/* length of token string */

  toklen = 0;				/* haven't parsed any chars yet */
  while ((c1 = *tok++) != NULCHAR) {	/* loop to end of token string */
    if (++toklen > textlen)		/* ran out of input? */
      return(CMxINC);			/* ok, good match up to here */
    c2 = (*text++) & CC_CHR;		/* get next input char */
    if (islower(c1))			/* convert both chars to upper case */
      c1 = toupper(c1);
    if (islower(c2))
      c2 = toupper(c2);
    if (c1 != c2)
      return(TOKxNP);			/* mismatch */
  }
  *parselen = toklen;			/* good match - set parse length */
  value->_pvstr = cmcsb._cmabp;		/* return value in atom buffer */
  if (toklen == textlen)
      if (!(fdbp->_cmffl & TOK_WAK))
	  return(CMxINC);
  return(CMxOK);
}



/* tokhlp - Identify the string we're looking for */

PASSEDSTATIC int
#if HAVE_STDC
tokhlp(char *text, int textlen, fdb *fdbp, int cust, int lines)
#else /* K&R style */
tokhlp(text,textlen,fdbp,cust, lines)
char *text;
int textlen,cust;
fdb *fdbp;
int lines;
#endif /* HAVE_STDC */
{
  if (!cust)
    cmxputs("matching token: ");	/* start the message if they didnt */
  cmxputs((char *) fdbp->_cmdat);	/* then print the token string */
  return(lines-1);
}




/* tokcplt - Finish off the token string for them.  Add a space if
** this is full completion.
**/

PASSEDSTATIC int
#if HAVE_STDC
tokcplt(char *text, int textlen, fdb *fdbp, int full, const char **cplt, int *cpltlen)
#else /* K&R style */
tokcplt(text,textlen,fdbp,full,cplt,cpltlen)
char *text;
const char **cplt;
int textlen,full,*cpltlen;
fdb *fdbp;
#endif /* HAVE_STDC */
{
  char *tok = (char *) fdbp->_cmdat;	/* point to token string */

  if (textlen == 0) {
    *cplt = NULL;			/* beep on no text */
    return(CMP_BEL);
  }
  *cplt = tok + textlen;		/* set rest of token for completion */
  *cpltlen = -1;			/* complete to end of string */
  if (full)
    return(CMP_SPC | CMP_GO);		/* add space and wakeup for full */
  else
    return(CMP_PNC);			/* only up to punct for partial */
}
