/* $Id: expr.h,v 1.2 2006/05/24 15:02:32 ellson Exp $ $Revision: 1.2 $ */
/* vim:set shiftwidth=4 ts=8: */

/**********************************************************
*      This software is part of the graphviz package      *
*                http://www.graphviz.org/                 *
*                                                         *
*            Copyright (c) 1994-2004 AT&T Corp.           *
*                and is licensed under the                *
*            Common Public License, Version 1.0           *
*                      by AT&T Corp.                      *
*                                                         *
*        Information and Software Systems Research        *
*              AT&T Research, Florham Park NJ             *
**********************************************************/

#ifdef __cplusplus
extern "C" {
#endif

/*
 * Glenn Fowler
 * AT&T Research
 *
 * expression library definitions
 */

#ifndef _EXPR_H
#define _EXPR_H

#include <ast.h>

#undef	RS			/* hp.pa <signal.h> grabs this!! */

#ifndef __CYGWIN__
#if _BLD_expr && defined(__EXPORT__)
#define extern		__EXPORT__
#endif
#if !_BLD_expr && defined(__IMPORT__)
#define extern		extern __IMPORT__
#endif
#endif

#include <exparse.h>

#undef	extern

#include <cdt.h>
#include <vmalloc.h>

#define EX_VERSION	20000101L

/*
 * flags
 */

#define EX_CHARSTRING	(1<<0)	/* '...' same as "..."          */
#define EX_CONSTANT	(1<<1)	/* compile to constant expr     */
#define EX_FATAL	(1<<2)	/* errors are fatal             */
#define EX_INTERACTIVE	(1<<3)	/* interactive input            */
#define EX_PURE		(1<<4)	/* no default symbols/keywords  */
#define EX_QUALIFY	(1<<5)	/* '.' refs qualified in id tab */
#define EX_RETAIN	(1<<6)	/* retain expressions on redef  */
#define EX_SIZED	(1<<7)	/* strings are sized buffers    */
#define EX_STRICT	(1<<8)	/* don't override null label    */
#define EX_UNDECLARED	(1<<9)	/* allow undeclared identifiers */

#define EX_ARRAY	(-3)	/* getval() array elt   */
#define EX_CALL		(-2)	/* getval() function call elt   */
#define EX_SCALAR	(-1)	/* getval() scalar elt          */

#define EX_NAMELEN	32	/* default Exid_t.name length   */

#define EX_INTARRAY  1		/* integer-index array */

/* previously known as EXID, but EXID is also defined by bison in y.tab.h */
#define EX_ID(n,l,i,t,f)	{{0},(l),(i),(t),0,(f),0,{0},n}

#define DELETE		BREAK	/* exexpr() delete `type'       */

#define INTEGRAL(t)	((t)>=INT&&(t)<=CHAR)
#define BUILTIN(t)  ((t) > MINTOKEN)

/* function type mechanism
 * types are encoded in TBITS
 * Thus, maximum # of parameters, including return type,
 * is sizeof(Exid_t.type)/TBITS. Also see T in exgram.h
 */

/*
 * arg 0 is the return value type
 */

#define F		01	/* FLOATING                     */
#define I		02	/* INTEGER                      */
#define S		03	/* STRING                       */

#define TBITS       4
#define TMASK       ((1<<TBITS)-1)
#define A(n,t)		((t)<<((n)*TBITS))	/* function arg n is type t     */
#define N(t)		((t)>>=TBITS)	/* shift for next arg           */

#define exalloc(p,n)		exnewof(p,0,char,n,0)
#define exnewof(p,o,t,n,x)	vmnewof((p)->vm,o,t,n,x)
#define exfree(p,x)		vmfree((p)->vm,x)
#define exstrdup(p,s)		vmstrdup((p)->vm,s)

#if LONG_MAX > INT_MAX
    typedef int Exshort_t;
#else
    typedef short Exshort_t;
#endif

    typedef EXSTYPE Extype_t;

    union Exdata_u;
    typedef union Exdata_u Exdata_t;
    struct Exdisc_s;
    typedef struct Exdisc_s Exdisc_t;
    struct Exnode_s;
    typedef struct Exnode_s Exnode_t;
    struct Expr_s;
    typedef struct Expr_s Expr_t;
    struct Exref_s;
    typedef struct Exref_s Exref_t;

    typedef int (*Exerror_f) (Expr_t *, Exdisc_t *, int, const char *,
			      ...);

    typedef struct {		/* user defined member type       */
	Sflong_t number;
	char *pointer;
    } Exlocal_t;

    typedef struct Exid_s {	/* id symbol table info           */
	Dtlink_t link;		/* symbol table link            */
	long lex;		/* lex class                    */
	long index;		/* user defined index           */
	long type;		/* symbol and arg types         */
	long index_type;	/* index type for arrays        */
	long flags;		/* user defined flags           */
	Exnode_t *value;	/* value                        */
	Exlocal_t local;	/* user defined local stuff     */
	char name[EX_NAMELEN];	/* symbol name                 */
    } Exid_t;

    struct Exref_s {		/* . reference list               */
	Exref_t *next;		/* next in list                 */
	Exid_t *symbol;		/* reference id symbol          */
	Exnode_t *index;	/* optional reference index     */
    };

    typedef struct {		/* sized buffer                   */
	unsigned long size;	/* buffer size                  */
	char *data;		/* buffer data                  */
    } Exbuf_t;

    union Exdata_u {

	struct {
	    Extype_t value;	/* constant value               */
	    Exid_t *reference;	/* conversion reference symbol  */
	} constant;		/* variable reference           */

	struct {
	    Exnode_t *left;	/* left operand                 */
	    Exnode_t *right;	/* right operand                */
	} operand;		/* operands                     */

	struct {
	    Exnode_t *statement;	/* case label statement(s)      */
	    Exnode_t *next;	/* next case item               */
	    Extype_t **constant;	/* case label constant array    */
	} select;		/* case item                    */

	struct {
	    Exid_t *symbol;	/* id symbol table entry        */
	    Exref_t *reference;	/* . reference list             */
	    Exnode_t *index;	/* array index expression       */
	    Exnode_t *dyna;	/* dynamic expression   */
	} variable;		/* variable reference           */

#ifdef _EX_DATA_PRIVATE_
	 _EX_DATA_PRIVATE_
#endif
    };

    struct Exnode_s {		/* expression tree node           */
	Exshort_t type;		/* value type                   */
	Exshort_t op;		/* operator                     */
	Exshort_t binary;	/* data.operand.{left,right} ok */
	Exshort_t pad_1;	/* padding to help cc           */
	Exlocal_t local;	/* user defined local stuff     */
	union {
	    double (*floating) (char **);	/* FLOATING return value        */
	     Sflong_t(*integer) (char **);	/* INTEGER|UNSIGNED return value */
	    char *(*string) (char **);	/* STRING return value          */
	} compiled;		/* compiled function pointer    */
	Exdata_t data;		/* node data                    */

#ifdef _EX_NODE_PRIVATE_
	 _EX_NODE_PRIVATE_
#endif
    };

    struct Exdisc_s {		/* discipline                     */
	unsigned long version;	/* EX_VERSION                   */
	unsigned long flags;	/* EX_* flags                   */
	Exid_t *symbols;	/* static symbols               */
	char **data;		/* compiled function arg data   */
	char *lib;		/* pathfind() lib               */
	char *type;		/* pathfind() type              */
	int (*castf) (Expr_t *, Exnode_t *, const char *, int, Exid_t *,
		      int, Exdisc_t *);
	/* unknown cast function        */
	int (*convertf) (Expr_t *, Exnode_t *, int, Exid_t *, int,
			 Exdisc_t *);
	/* type conversion function     */
	int (*binaryf) (Expr_t *, Exnode_t *, Exnode_t *, Exnode_t *, int,
			Exdisc_t *);
	/* binary operator function     */
	char *(*typename) (Expr_t *, int);
	/* application type names       */
	int (*stringof) (Expr_t *, Exnode_t *, int);
	/* value to string conversion   */
	 Extype_t(*keyf) (Expr_t *, Extype_t, int, Exdisc_t *);
	/* dictionary key for external type objects     */
	Exerror_f errorf;	/* error function               */
	 Extype_t(*getf) (Expr_t *, Exnode_t *, Exid_t *, Exref_t *,
			  void *, int, Exdisc_t *);
	/* get value function           */
	 Extype_t(*reff) (Expr_t *, Exnode_t *, Exid_t *, Exref_t *,
			  char *, int, Exdisc_t *);
	/* reference value function     */
	int (*setf) (Expr_t *, Exnode_t *, Exid_t *, Exref_t *, void *,
		     int, Extype_t, Exdisc_t *);
	/* set value function           */
	int (*matchf) (Expr_t *, Exnode_t *, const char *, Exnode_t *,
		       const char *, void *, Exdisc_t *);
	int *types;
	void *user;
    };

    struct Expr_s {		/* ex program state               */
	const char *id;		/* library id                   */
	Dt_t *symbols;		/* symbol table                 */
	const char *more;	/* more after %% (sp or != 0)   */
	Sfio_t *file[10];	/* io streams                   */
	Vmalloc_t *vm;		/* program store                */

#ifdef _EX_PROG_PRIVATE_
	 _EX_PROG_PRIVATE_
#endif
    };

    struct Excc_s;
    typedef struct Excc_s Excc_t;
    struct Exccdisc_s;
    typedef struct Exccdisc_s Exccdisc_t;

    struct Exccdisc_s {		/* excc() discipline              */
	Sfio_t *text;		/* text output stream           */
	char *id;		/* symbol prefix                */
	unsigned long flags;	/* EXCC_* flags                 */
	int (*ccf) (Excc_t *, Exnode_t *, Exid_t *, Exref_t *, Exnode_t *,
		    Exccdisc_t *);
	/* program generator function   */
    };

    struct Excc_s {		/* excc() state                   */
	Expr_t *expr;		/* exopen() state               */
	Exdisc_t *disc;		/* exopen() discipline          */

#ifdef _EX_CC_PRIVATE_
	 _EX_CC_PRIVATE_
#endif
    };

#ifndef __CYGWIN__
#if _BLD_expr && defined(__EXPORT__)
#define extern		__EXPORT__
#endif
#endif

    extern Exnode_t *excast(Expr_t *, Exnode_t *, int, Exnode_t *, int);
    extern Exnode_t *exnoncast(Exnode_t *);
    extern int excc(Excc_t *, const char *, Exid_t *, int);
    extern int exccclose(Excc_t *);
    extern Excc_t *exccopen(Expr_t *, Exccdisc_t *);
    extern void exclose(Expr_t *, int);
    extern int excomp(Expr_t *, const char *, int, const char *, Sfio_t *);
    extern char *excontext(Expr_t *, char *, int);
    extern int exdump(Expr_t *, Exnode_t *, Sfio_t *);
    extern void exerror(const char *, ...);
    extern void exwarn(const char *, ...);
    extern Extype_t exeval(Expr_t *, Exnode_t *, void *);
    extern Exnode_t *exexpr(Expr_t *, const char *, Exid_t *, int);
    extern void exfreenode(Expr_t *, Exnode_t *);
    extern Exnode_t *exnewnode(Expr_t *, int, int, int, Exnode_t *,
			       Exnode_t *);
    extern Expr_t *exopen(Exdisc_t *);
    extern int expop(Expr_t *);
    extern int expush(Expr_t *, const char *, int, const char *, Sfio_t *);
    extern int exrewind(Expr_t *);
    extern void exstatement(Expr_t *);
    extern int extoken_fn(Expr_t *);
    extern char *exstring(Expr_t *, char *);
    extern void *exstralloc(Expr_t *, void *, size_t);
    extern int exstrfree(Expr_t *, void *);
    extern char *extype(int);
    extern Extype_t exzero(int);
    extern char *exopname(int);
    extern char *extypename(Expr_t * p, int);
    extern int exisAssign(Exnode_t *);

#undef	extern

#endif

#ifdef __cplusplus
}
#endif
