/* @(#)Copyright (c), 1987, 1996 StatSci, Inc.  All rights reserved. */

#ifndef _S_S_H_ /*(*/
#define _S_S_H_
/* NOTE: This file (S.h) is a "private-to-S" file.  It will include
         further .h files that are "public" header files (e.g. S+API or
         its users could include them).  In order to distinguish between
         the environments and workaround possible namespace collisions,
         the #define '_S_private_symbols' was invented.  It should be
         defined to get the old private names for various things. */
#define _S_private_symbols
   
#include <ansi_things.h>
#include <sccs.h>
SCCS_ID_C(0005,@(#)S.h 3.104 last edit 6/13/96 StatSci)
#define SPLUS_VERSION 3400
#include "cdefs.h"
/* library declarations for ANSI C */
#ifdef S_UsePrototypes	/* ( */
extern char *mktemp(char *template);
extern char *ecvt(double value, int ndigit, int *decpt, int *sign);
#if !defined(WIN386)
extern void _exit(int status);
#endif
extern long lseek(int fildes, long offset, int whence);

/* library declarations for "old" C */
#else	/* ! S_UsePrototypes )( */
extern char *mktemp(), *ecvt(), *getenv();
extern void exit(), _exit();
extern long lseek();
#endif	/* ! S_UsePrototypes ) */

/* SAB 11/22/91 Removed sbrk extern from above, since all references to it
 *              should explicitly cast it to the desired type. It is declared
 *              as (void *) on some systems (hpux 8.0 at least), and needs to
 *              be cast to something to perform pointer arithmetic with it
 *              (which seems to be what happens most).
 */

/* library declarations for all versions of C */
#include <stdio.h>
#ifdef S_UsePrototypes
extern FILE * popen(const char *, const char *);
extern int pclose(FILE *);
#endif
#if defined(DOS386)
#include <io.h>
#endif
#if defined(APOLLO)  /* Problems on the APOLLO with string.h vs. strings.h */
		     /* strlen is defined as unsigned in string.h but as int 
			strings.h - if both are ever loaded -compilation fails*/
#define SYSV_STRINGS /* Attempt to force X11 programs used with S.h to load 
			string.h instead of strings.h */
#ifdef strlen
#undef strlen
#endif
#endif
#include <string.h>
#include <errno.h>
#include <setjmp.h>
#include <math.h>
#include <ctype.h>
#include <signal.h>

#include "machine.h"	/* machine arithmetic constants */
#include "system.h"	/* operating system, compiler stuff */
#include "signed.h"

/*
 * All calls to calloc, realloc and free should go through the following
 * three macros.  There should be no explicit calls to malloc in the code.
 */ 
#define Calloc(n,t)	(t *)S_ok_calloc((unsigned)(n),sizeof(t))
#define Realloc(p,n,t)	(t *)S_ok_realloc((char *)(p),(unsigned)(n)*sizeof(t))
#define Free(p)		S_ok_free((char *)(p)), (p) = NULL

/*
 * Automatic casting of sizes to int or unsigned int,
 * for the C libraries.  These should be redefined
 * or even written as functions if an int is smaller
 * than a long, and if vector lengths might be longer
 * than what can be held in an int; for example, if
 * ints are 16 bits and longs are 32 bits.
 */
#define Memcpy(p,q,n)	memcpy((char *)(p),(char *)(q),(int)((n)*sizeof(*(p))))
#define Qsort(p,n,c)	qsort((char *)(p),(int)(n),sizeof(*(p)),c)
#define Fread(p,n,f)	((f) ? fread((char *)(p),sizeof(*(p)),(int)(n),f) : \
	(Recover("System error: null file for reading",NULL_ENTRY),0))
#define Fwrite(p,n,f)	((f) ? fwrite((char *)(p),sizeof(*(p)),(int)(n),f) : \
	(Recover("System error: null file for writing",NULL_ENTRY),0))

#if !defined(_DEBUG_MALLOC_INC) /*(*/
#if (defined(S_ANSI_LibC) || defined(HPUX) || defined(SUNOS4) || \
     defined(DECSTATION)) && \
    !defined(SUNOS5) && !defined(_AIX) /*(*/
#define memcpy memmove
extern S_malloc_t memmove();
#else /*)(*/
#if defined(Berkeley) /*(*/
#define memcpy(a,b,n) bcopy(b,a,n)
#if !defined(NEXTM) && !defined(OSF1_DECALPHA) /*(*/
extern S_malloc_t bcopy();
#endif /*)*/

#if defined(_AIX) /*(*/
#if defined(memcpy) /*(*/
#undef memcpy
#define memcpy memmove
extern S_malloc_t memmove();
#else /*)(*/
#define memcpy(a,b,n) bcopy(b,a,n)
extern S_malloc_t bcopy();
#endif /*)*/
#endif /*)*/

#endif /*)*/
#if defined(ATT_UNIX) && !defined(_AIX) /*(*/
#define memcpy(a,b,n) sbcopy(b,a,n)
extern S_malloc_t sbcopy();
#endif /*)*/
#ifdef DOS386 /*(*/
#define memcpy memmove
extern S_malloc_t memmove();
#endif /*)*/
#endif /*)*/
#else /*)(*/
/* dbmalloc does a #define index to something...this confuses vars named index. */
#undef index
#undef memcpy
#define memcpy memmove
#endif /*)*/

#ifdef lint
#ifndef memcpy
char *memcpy(); /* is this needed? */
#endif
#endif

/* Split special value handle off to separate .h file */
#include "S_specials.h"

#include "S_sig.h"

/*
 * Decide on how various systems are to handle fork()/vfork(). Since there may
 * be cases where vfork can't be used (even on systems that support it), setup
 * defines S_VFORK and S_FORK that can be used where their counterparts can.
 * If a system doesn't support vfork(), set S_VFORK to fork.
 */
#define S_fork fork

#if defined(Berkeley) || defined(HPUX) /*(*/
/* SAB 08/29/91 NOTE: This is NOT complete - Berkeley & HPUX are the ones I */
/*                    know of that support vfork.                           */
#define S_vfork vfork
#if defined(SUNOS4) && defined(SPARC) /* ( */
/*
   From 'man vfork' on a Sun 4 running SunOS 4.1:
     On Sun-4 machines, the parent inherits the values  of  local
     and  incoming argument registers from the child.  Since this
     violates the usual data flow properties of procedure  calls,
     the  file  <vfork.h>  must  be included in programs that are
     compiled using global optimization.
 */
#include <vfork.h>
#endif /*  ) sun && sparc */

#else /*)(*/
#define S_vfork S_fork
#endif /*)*/

/* Includes some object types & s_vector/s_pointer definitions */
#include "S_tokens.h"
#include "S_structs.h"
typedef struct s_vector vector;
typedef union s_pointer pointer;

/* error code for S_debug, long jumps */
#define SIGSERROR 1000

/* extended alpha list */
#define ISALPHA(p) (isalpha(p) || (p)=='.')

#define MAX_DB		50

/* pointers to C routines */
typedef int (*fun_ptr) ();

/* structure for parameters involved in printing floating-point numbers -
 * originally only in $QPE/pratom.c 
 */
struct numsize {
	int sign, nsignif;
	int nleft, nright, nexp;
	char pmode, width;
};
typedef struct numsize NUMSIZE;

typedef struct s_vector *(*vfun_ptr)();

#define Nchildren(p) ((p)->length)
#define Child1(p) \
	(Nchildren(p)>0 ? \
		*((p)->value.tree) : \
		(Recover("Nonexistent subtree", NULL_ENTRY), (vector *)NULL))
#define Child2(p) \
	(Nchildren(p)>1 ? \
		*((p)->value.tree+1) : \
		(Recover("Nonexistent subtree", NULL_ENTRY), (vector *)NULL))
#define Child3(p) \
	(Nchildren(p)>2 ? \
		*((p)->value.tree+2) : \
		(Recover("Nonexistent subtree", NULL_ENTRY), (vector *)NULL))

/* status flags for ent->x.status */
#define PRECIOUS(p)		(p->x.frame != NULL_ENTRY)
#define CHECK_IT		63

/* defines for function calls */
#define Args(ent)		(((ent)->value.tree)+1)
#define Nargs(ent)		((ent)->length-1)

#define Arg1(p) \
	(Nargs(ent)>0 ? \
		*((p)->value.tree+1) :\
		(Recover("Not enough arguments", NULL_ENTRY), (vector *)NULL))
#define Arg2(p) \
	(Nargs(ent)>1 ? \
		*((p)->value.tree+2) :\
		(Recover("Not enough arguments", NULL_ENTRY), (vector *)NULL))

#define data_mode(p)		((atomic_type(p->mode))?p->mode : Data_mode(p))
#define data_length(p)		((atomic_type(p->mode))?p->length : Data_length(p))

#define SHORT_LIST_LENGTH	10

/* cases for rec_check */
#define REC_INIT		0
#define REC_ADD			1
#define REC_DELETE		2
#define REC_CHECK		3

#define EXTRA_FRAMES    	2L
#define PERM_FRAME		-2L
#define OLD_S_FRAME		-1L
#define FRAME0			0L
#define DICT_FRAME(p)	(-(p)-EXTRA_FRAMES)

/* some codes used by which_frame and its callers */
#define NO_FRAME		-MAX_DB-4L
#define UNKNOWN_FRAME		-MAX_DB-5L
#define COMP_FRAME		-MAX_DB-6L

/* for lint: force c to be used/meaningful */
#ifdef	lint
#define	UNUSED(c)	NONEXISTENT((char *)c)
#define MEANINGFUL(c)	c = 0; UNUSED(c)
#else
#define	UNUSED(c)
#define MEANINGFUL(c)
#endif

#define MESSAGE		sprintf(error_buf,
#define PROBLEM		sprintf(error_buf,
#define WARNING(x)	), Warning(error_buf, x)
#define RECOVER(x)	), Recover(error_buf, x)
#define TERMINATE	), S_terminate(error_buf)
#define PRINT_IT	), print_message(error_buf,0L,stderr),fputs("\n",stderr)
#define AUDIT		), audit_print_buf()
#define END_MESSAGE	)
#define ERROR_BUF_LENGTH 4096

/* Include file of externs split out of here, primarily for S+API */
#include "S_externs.h"

extern vector *do_op(), *do_math(), *do_summary(), *attribute();
extern vector *S_dictionary(), *S_extract(), *S_replace();
extern vector *S_class(), *Sfun(), *S_unprotect(), *S_switch();
extern vector *As_vector(), *Is_vector(), *S_dtype(), *S_list(), *S_unlist();
extern vector *New_vector(), *alcvec(), *alc_name(), *alc_tss(), *alcf();
extern vector *alcvec_u() ;
extern vector *alc1(), *alc2(), *alc3(), *alclist(), *alcuny(), *alcchar();
extern vector *cmpx_op(), *add_comment(), *mk_comment(), *comment_out();
extern vector *coe_vec(), *coe_ves(), *coestr(), *coedata();
extern vector *class_fun(), *class_op();
extern vector *do_lexlist(), *do_assign(), *do_return(), *do_fcall();
extern vector *do_op_list(), *do_lbrace(), *internal_symbol();
extern vector *eval(), *deparse(), *enc_data(), *parent_data(), *fnd_data();
extern vector *get_data(), *db_set_data(), *set_data();
extern vector *append_data(), *copy_data(), *move_data();
extern vector *find_comp(), *find_data(), *append_el();
extern vector *do_na_out(), *combine(), *pop_frame();
extern vector *get_S_entry(), *S_to_QPE(), *S_na_funs(), *S_deparse();
extern vector *S_sh_dp(), *S_method(), *dcty_names(), *cur_call();
extern vector *assign_obj(), *fun_args(), *compact_keep();
extern vector *deparse(), *rec_check(), *S_rcbind(), *S_split_atomic();
extern vector *get_hash(), *get_local(), *set_names();
extern vector *get_names(), *xact_comp(), *get_dim(), *get_dimnames();
extern vector *blt_in_NA, *blt_in_TRUE, *blt_in_FALSE;
#if defined(IEEE)
extern vector *blt_in_NaN,*blt_in_Infi;
#endif
extern vector *blt_in_NULL, *blt_in_Inf, *blt_in_empty;
extern vector *Frames, *Local_data, *S_data, *S_ptree;
extern vector *cons_frame, *alias_frame;
extern vector *Warn_list, *C_on_stop, *Program, **C_specials, *C_wrapup;
extern vector *S_void, *frame0, *deflt_class;

#if !defined(_DEBUG_MALLOC_INC) && !defined(S_ANSI_LibC)
/* These are defined in <stdlib.h> for ANSI/ISO C. */
extern S_malloc_t malloc(), calloc(), realloc();
#endif
extern char *encs1(), *encs2(), *enci1(), *enci2(), *encr1(), *encd1();
extern char *short_dp(), *true_file_name(), *whoami(), *ch_collapse();
extern char *string_value(), *sanity(), *c_symbol(), *ftn_symbol(), *S_strdup();
extern char *do_unlex(), *sanity(), *s_get_s(), *c_s_cpy();
extern char *S_alloc(), *S_realloc(), *S_ok_calloc(), *S_ok_realloc();
extern char *S_malloc(), *S_ok_malloc();
extern char *fun_name(), *cur_fun_name(), *find_method();
#if defined(WIN386) /*(*/
extern char *collapse_char(vector *char_vector, int crlf_sep);
#endif /*)*/
extern char *shome, *user_home, *prog_name, *quick_name;
extern char *sbrk0, load_time[], error_buf[], save_error_buf[], *s_strerror();

extern long Data_length(), long_value(), unlex_len(), print_message();
extern long x_which_comp(), which_frame(), which_comp();
extern long min_length(), menu(), file_mtime(), set_alloc(), next_db_frame();
extern long cur_frame, Nframe, quick_frame;

extern int coerce_to(), alloc_ptr(), check_assign();
extern int logical_value(), is_directory(); 
extern int check_obj(); 
extern int do_hash(); 
extern int bad_guy(), bad_header(), check_this_arena(); 
extern int S_yyparse(), S_lex(); 
extern int set_repl_alloc(); 
extern int cmpx_cmp(), expr_cmp(), clean_list(), do_parse(), op_action();
extern int Data_mode(), del_comp(), hash(), get_cdcty(), db_hash();
extern int push_source(), pop_source(), has_names(), move_block();
#if defined(WIN386) /*(*/
extern int S_copy_text_to_clip(char *file, char *text);
extern int S_copy_text_from_clip(char *file, char **text);
extern int coe_exact_to_int(long *ret, int from_mode);
#endif /*)*/
extern int numstat();
extern int mode_size();
extern S_sig catchall();
extern int running_S, sys_index, eval_open, cur_interact, db_level;
extern int last_signal, doing_list, runit_pid, mainpid, S_lex_debug;
extern int Initialized, Restart, sinkpipe, in_old_S;
extern int S_allocation, interrupt_code, saw_interrupt;
extern int in_deparse;
extern int test_na(), test_inf(), audit_print_buf();
extern int S_set_eval_state();

extern fun_ptr get_entry();

extern unsigned long charmash();

extern double double_value(), lgamma(), unif_rand(), norm_rand();
extern double proc_time();
extern double *data_header;

#ifdef lint
extern free();
#else
#if !defined(_DEBUG_MALLOC_INC)
#if !defined(SUNOS4) && !defined(SPARC)
extern void free();
#endif
#endif
#endif

extern void S_ok_free();
extern void init_load(), clear_alloc(), mem_size(), set_frame();
extern void window_size();
extern void un_hash(), hash_enter(), n_prime(), names_unlex();
extern void Warning(), new_frame(), db_enter(), comp_init();
extern void echo_on(), echo_off(), flush_input(), S_terminate(), Recover();
extern void add_error(), add_exit(), del_error(), do_C_stop(), clock_init();
extern void S_init(), command_prompt(), Slexinit(), put_data(), set_for_method();
extern void flush_data(), frame0_assign(), interactive();
extern void prmatrix(), prts(), prnum(), zero_numsize();
extern void pratom(), do_S(), frames_init(), warn_message(), do_C_wrap();
extern void do_stop(), set_stdout(), set_precious();
extern void try_to_free(), check_frame(), check_frame0();
extern void call_S(), replace_dots(), data_wrap(), set_dollar(), put_to_file();
extern void make_cdcty(), cdump();
extern void seed_in(), seed_out(), setseed();
extern void set_na(), set_inf();
extern void open_for_rescale(), read_and_rescale();
extern void S_set_complex_warn();
extern void set_length2();
extern void device_init(), gr_signalled(), gr_wrap();
extern void malloc_resetp(), free_header(), free_block(), pop_brk();
extern void db_compact(), S_check_backup_chains(), data_clear();
extern void S_yyerror();
extern void do_x();
extern void no_nas_allowed();
#if defined(WIN386) /*(*/
extern void realloc_char(char **return_string, char *new_value, long new_length);
#endif /*)*/

#if 0 /*(*/
  /* this was for bug 2715, Splus for IRIX 4, and appears no longer necessary
   * in Splus for IRIX 5.2;  -peter
   */
#if defined(IRIS4D) /*(*/
#define brk S_brk_iris
#define sbrk S_sbrk_iris
char *S_sbrk_iris(/* int incr; */);	
#endif /*)*/
#endif /*)*/

#if defined(F77_MAP_LOGICALS) /*(*/
extern void logical_C_to_f77(), logical_f77_to_C() ;
#endif /*)*/

#if defined(APOLLO) /*(*/
extern long sys_fp_traps,S_fp_traps,cur_fp_traps; /*For fp trap enables*/
extern long fp_traps();
extern long fp_init();
#else /*)(*/
#if defined(DOS386) /*(*/
extern unsigned int S_fp_traps, cur_fp_traps;
#endif /*)*/
#endif /*)*/

extern FILE *MemCheckFile;
extern char *MemSbrk;

/* macros for warning and error messages */
#ifdef lint
#define Recover(a,b)	if(Warning(a,b),1) 0
#undef RECOVER
#undef Fread
#undef Fwrite
#define RECOVER(a)	), Warning(error_buf, a)
#define Fread(p,n,f)	fread((char *)p,sizeof(*(p)),(int)(n),f)
#define Fwrite(p,n,f)	fwrite((char *)p,sizeof(*(p)),(int)(n),f)
#endif

/* macros for accessing, setting attributes from C */
#define GET_ATTR(x,what) (x->mode == STRUCTURE ? xact_comp(x, what) : 0)
#define GET_DIM(x) (x->mode == STRUCTURE ? xact_comp(x, ".Dim") : 0)
#define GET_DIMNAMES(x) (x->mode == STRUCTURE ? xact_comp(x, ".Dimnames") : 0)
#define GET_COLNAMES(x) get_dimnames_el(x,1)
#define GET_ROWNAMES(x) get_dimnames_el(x,0)
#define GET_LEVELS(x) (x->mode == STRUCTURE ? xact_comp(x, ".Label") : 0)
#define GET_TSP(x) (x->mode == STRUCTURE ? xact_comp(x, ".Tsp") : 0)
#define GET_CLASS(x) (x->mode == STRUCTURE ? xact_comp(x, "class") : 0)
#define GET_EL(x,i,mode) (x->value.mode)[i]
#define AS_VECTOR(x) coevec(x, ANY, TRUE, CHECK_IT)
#define AS_LIST(x) coevec(x, LIST, TRUE, CHECK_IT)
#define AS_CHARACTER(x) coevec(x, CHAR, TRUE, CHECK_IT)
#define AS_NUMERIC(x) coevec(x, DOUBLE, TRUE, CHECK_IT)
#define AS_INTEGER(x) coevec(x, INT, TRUE, CHECK_IT)

#define IS_NUMERIC(x) (d__mode = data_mode(x), d__mode>=LGL && d__mode <= DOUBLE)
#define IS_ATOMIC(x) (d__mode = data_mode(x), atomic_type(d__mode))
#define IS_RECURSIVE(x) (d__mode = data_mode(x), !NOT_RECURSIVE(d__mode))
extern vector *NO_NAME(), *CALL_3(), *CALL_2(), *CALL_1(), *CALL_0();
extern vector *CALL_2_F(), *CALL_1_F(), *CALL_0_F(),
	*STRING_VECTOR(), *NUMERIC_VECTOR(), *GET_NAMES();
extern vector *NO_NAME(), *get_dimnames_el();
extern void ATTR_GETS(), ELEMENT_GETS();
extern int d__mode;

/* Time codes. See c_support.c:S_convert_date. */
#define EPOCH_INT_T	1
	/* seconds since midnight 1/1/70 GMT */
/* add other integer codes here, up to 9 */

#define ASC_STR_T	10
	/* asctime() format without the \n, "Sun Sep 16 01:03:52 1973" */
#define ABBREV_STR_T	11
	/* "73.09.16   1:03" */
	/* "73.09.16  11:03" */
/* add other string codes here, then change MAX_TIME_CODE */

#define MIN_TIME_CODE	EPOCH_INT_T
#define MAX_TIME_CODE	ABBREV_STR_T

/* evaluator states; see S_set_eval_state() and Default_pgm() */
#define EV_IN_PARSE	0
#define EV_PARSE_DONE	1
#define EV_MIN_STATE	EV_IN_PARSE
#define EV_MAX_STATE	EV_PARSE_DONE
#define EV_GET_STATE	(EV_MIN_STATE - 1)

#endif /* !_S_S_H_ )*/
