#ifndef CCMD_H_
#define CCMD_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
*/

/* ccmd.h
 *
 * Include this file if your program will make use of the CCMD
 * command parsing routines.  Included here are function and
 * flag definitions, error codes, and parsing structure declarations.
 * As much as possible, symbols are patterned after corresponding
 * TOPS-20 symbols, with non-alphameric characters (. and %) replaced
 * by underscores.
 */

#include "args.h"
#ifndef stdin
# include <stdio.h>
# if !HAVE_STDC
extern int close ARGS((int));
#  if defined(sun)
extern int open ARGS((const char *, int, ...));
#  else
#   if defined(sgi) || defined(_IBMR2)
    /* open() already declared with ellipses prototype in pre-ANSI compiler
    <fcntl.h>, which conflicts with empty argument list (ANSI 3.5.4.3). */
#   else
extern int open ARGS((const char *, int));
#   endif /* defined(sgi) || defined(_IBMR2) */
#  endif /* defined(sun) */
extern int read ARGS((int , void *, unsigned));
extern int write ARGS((int , void *, unsigned));
# endif
#endif /* stdin */

#ifndef _JBLEN
#include <setjmp.h>
#endif

typedef unsigned int flag_t;	/* unsigned to eliminate lint warnings */

#include "cmfnc.h"		/* get function-specific symbols */
#include "ccmdmd.h"		/* get machine dependent symbols */

#ifndef fileno
extern int fileno ARGS((FILE *));
#endif

/* The function are not declared in many UNIX __STDC__ environments */
extern int pclose ARGS((FILE *stream_));
extern FILE *fdopen ARGS((int, const char *));
extern FILE *popen ARGS((const char *, const char *));

#if defined(__sgi)
#define HANDLER_ARGS	fdb *, int, int
#else
#define HANDLER_ARGS	fdb *fdblist_, int brk_, int deferred_
#endif

/* These used to be in ccmdlib.h, but they can be defined in either
unistd.h included there, or by stdio.h, included here. */
#if defined(L_SET) && !defined(SEEK_SET)
#define SEEK_SET	L_SET
#define SEEK_CUR	L_INCR
#define SEEK_END	L_XTND
#endif

/*
 * BRKTAB is a pair of 128-bit arrays specifying the break characteristics
 * of the ASCII characters.  The _br1st array specifies characters which
 * will break field input when they are typed as the first character of
 * a field.  The _brrest array specifies characters that break in other
 * than the first position.  Each array contains one bit per ASCII
 * code, ordered according to the ASCII sequence.  The leftmost (most
 * significant) bit of the first byte corresponds to ASCII code 0, and
 * the rightmost bit of that same byte corresponds to ASCII code 7.
 * Leftmost bit of the second bit is for ASCII code 8, and so on.
 * When a bit is on, the corresponding character will act as a break
 * character, otherwise it will not.
 *
 * Routines in module cmutil can be used to construct and maintain
 * break tables.
 */

typedef struct BRKTAB {
	unsigned char _br1st[16];  /* Bit array for initial character breaks */
	unsigned char _brrest[16]; /* Bit array for subsequent breaks */
} brktab;

/*
 * FDB structures hold information required to parse specific fields of
 * a command line.
 */

typedef struct FDB {
	int	_cmfnc;		/* Function code for this field */
	flag_t	_cmffl;		/* Function specific parse flags */
	struct FDB * _cmlst;	/* Link to alternate FDB */
	pdat	_cmdat;		/* Function specific parsing data */
	const char * _cmhlp;	/* pointer to help string */
	const char * _cmdef;	/* pointer to default string */
	brktab * _cmbrk;	/* pointer to special break table */
	const char * _cmest;	/* specialized error string */
} fdb;

/* Common flag defined for all parse functions */
#define	CM_SDH	0x8000		/* Suppress default help message */
#define CM_SDE	0x4000		/* Supress default error msg */
#define CM_NLH  0x2000		/* Extra newline help for multi fdbs */
#define CM_NEOF 0x1000		/* parser handles eof itself. */

typedef struct histbuf {
    int *buf;
    int len;
} cmhistbuf;



typedef struct hist {
    cmhistbuf *bufs;		/* array of history buffers */
    int  len;			/* how many buffers there are */
    int  next;			/* index of next buffer to write into */
    int  current;		/* index of current point in history */
    int  enabled;		/* tell if we should remember */
} cmhist;
/*
 * CSB structure holds information on the state of parsing a command
 * line, as well as pointers to required buffers.
 */

typedef struct CSB {
	flag_t _cmflg;		/* flags describing parse state */
	flag_t _cmflg2;		/* more flags */
	FILE *  _cmij;		/* file for command input */
	FILE *	_cmoj;		/* file for command output */
	FILE *  _cmej;		/* file for error output */
	const char * _cmrty;	/* pointer to prompt string */
	int *	_cmbfp;		/* pointer to beginning of user input */
	int *	_cmptr;		/* pointer to beg of next field to parse */
	int 	_cmcnt;		/* # of chars in buffer past _cmptr */
	int	_cminc;		/* number of unparsed chars after _cmptr */
	int *	_cmhst;		/* history parse point */
	char *	_cmabp;		/* pointer to beginning of atom buffer */
	int	_cmabc;		/* size of atom buffer */
	char *	_cmwbp;		/* pointer to beginning of work buffer */
	int	_cmwbc;		/* size of work buffer */
	int (** _cmact) ARGS((HANDLER_ARGS));
				/* table of character action routines */
	int 	_cmbkc;	    	/* break character that caused deferred */
				/*  action or confirmation */
	int	_cmcmx;		/* maximum column position on terminal */
	int	_cmcol;		/* current column position on terminal */
	int	_cmerr;		/* most recent parse error */
	fdb *	_cmifd;		/* ptr to FDB giving an incomplete parse */
	int     (* _cmrph)(VOID); /* function to call when reparse is needed */
	int     (* _cmerh) ARGS((int, ...)); /* function to call on parse error */
	const char * _cmntb;	/* comment to eol string */
	const char * _cmnts;	/* delimited comment beginning */
	const char * _cmnte;	/* delimited comment end */
	int 	_cmmax;		/* maximum number of help tokens to display */
	int     (* _cmblh) ARGS((int));	/* function to call nonblocking and no data */
	int 	_cmwrp;		/* column to wrap at */
	cmhist *_cmhist;	/* command history structure */
	int 	_cmrmx;		/* max number of rows */
	int *	_cmcur;		/* current position in cmd buffer */
	int (** _cmpract) ARGS((fdb *,int,int));
				/* table of actions after prefix character */
} csb;

typedef struct cmacttab {	/* table of action chars */
    char actionchar;		/* action character */
    int (* actionfunc) ARGS((HANDLER_ARGS)); /* action routine */
} cmacttab;

/*
 * major command line editing modes up to 16
 */
#define CMaNOSET 0		/* used to not set a field */

#define CMaEMACS 0x0001		/* emacs like actions */
#define CMaGMACS 0x0002		/* gnuemacs like actions */
#define CMaVI    0x0003		/* vi like actions (not implemented) */

/*
 * modifiers to cmd line editor
 */
#define CMaFCASE 0x0010		/* forward casing */
#define CMaBCASE 0x0020		/* backward casing */
#define CMaEOF   0x0040		/* handle eof */
#define CMaIEOF  0x0080		/* ignore eof */

/* Flags that can be set in individual character entries (each an int) in
** the _cmbfp buffer of the CSB.  The CC_QUO flag is the high order bit in
** the right half, all the rest are in the left half.  CC_QUO is left in
** the right half so that parse routines can see it, since the parse routines
** get their data as character strings, without the left half flags.
**/

#define	CC_CHR	0x007f		/* character data field */
#define CC_QUO	0x0080		/* character was quoted */
#define	CC_QCH	0x00ff		/* character data with quote flag */
#define	CC_NEC	0x0100		/* character was not echoed */
#define CC_HID	0x0200		/* character is hidden from user */
#define CC_SKP	0x0400		/* character is to be skipped (not */
				/*  considered input for parsing) */
#define	CC_CSK	0x0800		/* char is conditionally skipped, */
				/*  meaning that it is skipped as */
				/*  long as it is followed by a (possibly */
				/*  empty) string of characters with the */
				/*  CC_CSK flag, and eventually a character */
				/*  with the CC_SKP flag. */
#define CC_ACT	0x1000		/* char should be treated as an action char */
				/*  on reparse. */

/* Flag values for _cmflg field of CSB */

/*   Settable by user... */
#define	CM_RAI	0x0001		/* Convert to uppercase before parsing */
#define	CM_WKF	0x0002		/* Wake up as each field is terminated */
#define	CM_NEC	0x0004		/* Do not echo tty input as it is typed */

/*   Maintained by ccmd routines */
#define CM_ESC	0x0008		/* This field got completion to successful */
				/*  parse */
#define	CM_NOP	0x0010		/* Field could not be parsed */
#define	CM_RPT	0x0020		/* Reparse needed -- previously parsed */
				/*  input has been edited */
#define	CM_SWT	0x0040		/* Switch was terminated with a colon */
#define	CM_PFE	0x0080		/* Previous field got completion (for */
				/*  noise word handling) */
#define	CM_DRT	0x0100		/* New input has been typed (and possibly */
				/*  erased) since the last cmini call on */
				/*  this CSB. */
#define CM_CFM	0x0200		/* This field was terminated by a newline */
#define	CM_ACT	0x0400	    	/* Deferred action is set, waiting for a */
				/*  field to run out of input */
#define	CM_PRS	0x0800		/* Data has been parsed in this cmd line */
				/*  (used to ignore confirms following only */
				/*  white space) */
#define CM_ITTY 0x1000		/* input is a terminal */
#define CM_OTTY 0x2000		/* output is a terminal */
#define	CM_TTY	0x3000		/* Command source is a terminal */

#define	CM_NAC	0x4000		/* Do not copy parsed text to atom buffer */
#define CM_CMT	0x8000		/* Currently inside a comment */

/*
 * flags bits for the second flag word.
 */

/*
 * user settable bits.
 */
#define CM_NIN	0x0001		/* don't do indirections */
#define CM_NHM  0x0002		/* don't use "more" code during help */
				/* a specialized help string */
/*
 * CCMD maintained bits
 */
#define CM_IND	0x0004		/* currently in an indirect parse */
#define CM_EOF  0x0008		/* flag EOF condition */
#define	CM_CRT	0x0010		/* Command source is a video terminal */

extern csb cmcsb;		/* CSB for all parses (ccmd) */

/* Miscellaneous definitions */

#ifndef TRUE
#define	TRUE	-1
#define	FALSE	0
#endif

#ifndef NULL
#define NULL 0
#endif

extern char *_findenv ARGS((const char *name_, int *offset_));
extern char *cm_version ARGS((void));
extern char *cmini ARGS((void));
extern char *cmpasswd ARGS((const char *prmpt_));

#if !defined(cmrealloc)
extern char *cmrealloc ARGS((char *ptr_, int size_));
#endif

extern char *getenv ARGS((const char *name_));
extern char *tilde_expand ARGS((const char *dirname_));
extern fdb *fdbchn ARGS((fdb *, ...));
			/* NB: cannot represent variable number of
			arguments with old-style varargs.h interface */
extern int *disp_forward_char ARGS((int n_));
extern int *go_backward_char ARGS((int n_));
extern int *go_forward_char ARGS((int n_));
extern int *go_from ARGS((int *p1_, int *p2_));
extern int *goto_beginning_of_line ARGS((void));
extern int *goto_end_of_line ARGS((void));
extern int backchar ARGS((HANDLER_ARGS));
extern int backword ARGS((HANDLER_ARGS));
extern int bcap_word ARGS((HANDLER_ARGS));
extern int bcase_word ARGS((HANDLER_ARGS, int action_));
extern int bdowncase_word ARGS((HANDLER_ARGS));
extern int begact ARGS((HANDLER_ARGS));
extern int begline ARGS((HANDLER_ARGS));
extern int bsact ARGS((HANDLER_ARGS));
extern int bupcase_word ARGS((HANDLER_ARGS));
extern int cap_word ARGS((HANDLER_ARGS));
extern int cfmact ARGS((HANDLER_ARGS));
extern int cm_env_var ARGS((char *var_));
extern int cm_major ARGS((void));
extern int cm_minor ARGS((void));
extern int cmact ARGS((int (**acttab_ ) ARGS((HANDLER_ARGS))));
extern int cmargs ARGS((int argc_, char **argv_));
extern int cmbljmp ARGS((int ret_));
extern int cmbufs ARGS((int *cmdbuf_, int cmdlen_, char *atombuf_, int atomlen_,
	 char *workbuf_, int worklen_));
extern int cmceol ARGS((void));
extern int cmcls ARGS((void));
extern int cmcplt ARGS((int full_));
extern int cmcpos ARGS((void));
extern int cmdflt ARGS((fdb *fdblist_));
extern int cmdownl ARGS((void));
extern int cmerjmp ARGS((int ret_, const char *str_, flag_t flags_));
extern int cmerjnp ARGS((int ret_));
extern int cmgetc ARGS((int *c_, FILE *fd_));
extern int cmhelp ARGS((fdb *fdblist_, int helpchar_));
extern int cmhelp_more ARGS((const char *str_));
extern int cmleft ARGS((void));
extern int cmp_pre ARGS((HANDLER_ARGS));
extern int cmpact ARGS((HANDLER_ARGS));
extern int cmpact2 ARGS((HANDLER_ARGS));
extern int cmpdflt ARGS((fdb *fdblist_));
extern int cmprefix ARGS((HANDLER_ARGS));
extern int cmprep ARGS((char *tobuf_, int tosize_, int *tolen_));
extern int cmraise ARGS((int flag_));
extern int cmright ARGS((void));
extern int cmrpjmp ARGS((void));
extern int cmseti ARGS((FILE *input_, FILE *output_, FILE *error_));
extern int cmsti ARGS((const char *s_, flag_t flags_));
extern int cmsti1 ARGS((int c_, flag_t flags_));
extern int cmstin ARGS((const char *s_, int n_, flag_t flags_));
extern int cmsystem ARGS((const char *cmd_));
extern int cmupl ARGS((void));
extern int cmwake ARGS((int flag_));
extern int cmxeprintf ARGS((const char *, ...));
			/* NB: cannot represent variable number of
			arguments with old-style varargs.h interface */
extern int cmxera ARGS((int n_, int doprompt_));
extern int cmxprintf ARGS((const char *, ...));
			/* NB: cannot represent variable number of
			arguments with old-style varargs.h interface */
extern int delact ARGS((HANDLER_ARGS));
extern int delchar ARGS((HANDLER_ARGS));
extern int delcurrent ARGS((int eralen_));
extern int downcase_word ARGS((HANDLER_ARGS));
extern int dtdow ARGS((int mon_, int day_, int yr_));
extern int dtdst ARGS((datime *dtblk_));
extern int dtparse ARGS((flag_t flags_, char *text_, int textlen_,
	datime *dtblk_, int *parselen_, const char **completion_,
	int *incomplete_));
extern int endline ARGS((HANDLER_ARGS));
extern int fcap_word ARGS((HANDLER_ARGS));
extern int fcase_word ARGS((HANDLER_ARGS, int action_));
extern int fdowncase_word ARGS((HANDLER_ARGS));
extern int fixact ARGS((HANDLER_ARGS));
extern int fmatch ARGS((const char *string_, const char *pattern_,
	int partial_));
extern int force_reparse ARGS((void));
extern int forchar ARGS((HANDLER_ARGS));
extern int forword ARGS((HANDLER_ARGS));
extern int fupcase_word ARGS((HANDLER_ARGS));
extern int hlpact ARGS((HANDLER_ARGS));
extern int hstact ARGS((HANDLER_ARGS));
extern int indiract ARGS((HANDLER_ARGS, flag_t flags_));
extern int iswild ARGS((const char *str_));
extern int iswordchar ARGS((int c_));
extern int killeol ARGS((HANDLER_ARGS));
extern int killword ARGS((HANDLER_ARGS));
extern int main ARGS((int Argc_, char **Argv_));
extern int main ARGS((int argc_, char **argv_));
extern int match ARGS((const char *string_, int len_, fdb *fdblist_,
	pval *value_, fdb **usedfdb_, int *parselen_));
extern int maybe_reparse ARGS((void));
extern int nextact ARGS((HANDLER_ARGS));
extern int parse ARGS((fdb *fdblist_, pval *value_, fdb **usedfdb_));
extern int pbeep ARGS((HANDLER_ARGS));
extern int pcmact ARGS((HANDLER_ARGS));
extern int prevact ARGS((HANDLER_ARGS));
extern int prompt ARGS((const char *p_));
extern int quoact ARGS((HANDLER_ARGS));
extern int setenv ARGS((const char *name_, const char *value_, int rewrite_));
extern int twiddle ARGS((HANDLER_ARGS));
extern int upcase_word ARGS((HANDLER_ARGS));
extern int ustrcmp ARGS((const char *s1_, const char *s2_));
extern int wrdact ARGS((HANDLER_ARGS));
extern long datime_to_time ARGS((datime *dt_));
extern tzinf *dttzinf ARGS((int key_));
extern void abscharpos ARGS((int *ptr_, int *lpos_, int *cpos_));

#if defined(__osf__) || defined(__hpux) || defined(HAVE_BCOPY)
  /* avoid conflict with <strings.h> version, which has const char *src_ */
#else
extern void bcopy ARGS((char *src_, char *dest_, int len_));
#endif

extern void cm_env_actions ARGS((char *env_));
extern void cm_para_abort ARGS((void));
extern void cm_para_eof ARGS((void));
extern void cm_set_ind ARGS((int flag_));
extern void cmbuiltin_act ARGS((int actiontype_));
extern void cmcr ARGS((FILE *fd_));
extern void cmdone ARGS((void));
extern void cmecho ARGS((int flag_));
extern void cmechx ARGS((int c_));
extern void cmfileini ARGS((void));
extern void cmflsh ARGS((FILE *fd_));
extern void cmflush ARGS((FILE *fd_));
extern void cmgetenv ARGS((void));
extern void cmhst ARGS((int n_));
extern void cmhst_disable ARGS((void));
extern void cmhst_enable ARGS((void));
extern void cmindend ARGS((void));
extern void cminderr ARGS((int code_));
extern void cmnl ARGS((FILE *fd_));
extern void cmpemsg ARGS((const char *estr_, flag_t flags_));
extern void cmperr ARGS((int ecode_, flag_t flags_));
extern void cmputc ARGS((int c_, FILE *fd_));
extern void cmputs ARGS((const char *s_, FILE *fd_));
extern void cmsetact ARGS((cmacttab *acttab_,
	int (*(actvec_[])) (HANDLER_ARGS)));
extern void cmtake ARGS((int (*proutine_)(void)));
extern void cmtend ARGS((void));
extern void cmtset ARGS((void));
extern void cmwrap ARGS((FILE *fd_));
extern void cmxbol ARGS((void));
extern void cmxcll ARGS((void));
extern void cmxcls ARGS((void));
extern void cmxerr ARGS((const char *s_));
extern void cmxflsh ARGS((void));
extern void cmxnl ARGS((void));
extern void cmxputc ARGS((int c_));
extern void cmxputs ARGS((const char *s_));
extern void confirm ARGS((void));
extern void dtnow ARGS((datime *dtblk_));
extern void go_backward ARGS((int n_));
extern void go_down_line ARGS((int n_));
extern void go_forward ARGS((int n_));
extern void go_up_line ARGS((int n_));
extern void goto_current_pos ARGS((void));
extern void ind_oldfds ARGS((void));
extern void noise ARGS((const char *nw_));
extern void refresh_eol ARGS((void));
extern void relcharpos ARGS((int *lpos_, int *cpos_, int *start_, int *end_));
extern void remember ARGS((void));

#if !defined(HAVE_UNSETENV)
extern void unsetenv ARGS((const char *name_));
#endif

#if defined(NEED_SIGBLOCK_SIGSETMASK)
extern int sigblock ARGS((int));
extern int sigsetmask ARGS((int));
#endif

#endif /* CCMD_H_ */
