/*
 * $Id: opsv.c,v 1.1.1.1 2005/09/18 22:04:10 dhmunro Exp $
 *
 * Load up virtual functions for the various DataBlock and Symbol types.
 */
/* Copyright (c) 2005, The Regents of the University of California.
 * All rights reserved.
 * This file is part of yorick (http://yorick.sourceforge.net).
 * Read the accompanying LICENSE file for details.
 */

#include "ydata.h"
#include "pstdlib.h"

/* Include file automatically generated by the FMCALC program.  */
#ifndef PRMTYP_FILE
#define PRMTYP_FILE "prmtyp.h"
#endif
#include PRMTYP_FILE

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

extern StackOp NoOp;
extern UnaryOp No_Op;

extern Operand *FormOperandIS(Symbol *owner, Operand *op);
extern Operand *FormOperandLS(Symbol *owner, Operand *op);
extern Operand *FormOperandDS(Symbol *owner, Operand *op);
extern Operand *FormOperandDB(Symbol *owner, Operand *op);
extern Operand *FormOperandRF(Symbol *owner, Operand *op);

extern StackOp ToCharIS, ToCharLS, ToCharDS, ToCharDB;
extern StackOp ToShortIS, ToShortLS, ToShortDS, ToShortDB;
extern StackOp          ToIntLS, ToIntDS, ToIntDB;
extern StackOp ToLongIS,            ToLongDS, ToLongDB;
extern StackOp ToFloatIS, ToFloatLS, ToFloatDS, ToFloatDB;
extern StackOp ToDoubleIS, ToDoubleLS,             ToDoubleDB;
extern StackOp ToComplexIS, ToComplexLS, ToComplexDS, ToComplexDB;

extern UnaryOp          ToShortC, ToIntC, ToLongC,
               ToFloatC, ToDoubleC, ToComplexC;
extern UnaryOp ToCharS,           ToIntS, ToLongS,
               ToFloatS, ToDoubleS, ToComplexS;
extern UnaryOp ToCharI, ToShortI,         ToLongI,
               ToFloatI, ToDoubleI, ToComplexI;
extern UnaryOp ToCharL, ToShortL, ToIntL,
               ToFloatL, ToDoubleL, ToComplexL;
extern UnaryOp ToCharF, ToShortF, ToIntF, ToLongF,
                         ToDoubleF, ToComplexF;
extern UnaryOp ToCharD, ToShortD, ToIntD, ToLongD,
               ToFloatD,            ToComplexD;
extern UnaryOp ToCharZ, ToShortZ, ToIntZ, ToLongZ,
               ToFloatZ, ToDoubleZ;

extern PromoteOp PromNOP;
extern PromoteOp         PromCS, PromCI, PromCL, PromCF, PromCD, PromCZ;
extern PromoteOp PromSC,         PromSI, PromSL, PromSF, PromSD, PromSZ;
extern PromoteOp PromIC, PromIS,         PromIL, PromIF, PromID, PromIZ;
extern PromoteOp PromLC, PromLS, PromLI,         PromLF, PromLD, PromLZ;
extern PromoteOp PromFC, PromFS, PromFI, PromFL,         PromFD, PromFZ;
extern PromoteOp PromDC, PromDS, PromDI, PromDL, PromDF,         PromDZ;
extern PromoteOp PromZC, PromZS, PromZI, PromZL, PromZF, PromZD;

extern StackOp OrII, OrIL, OrIB,
               OrLI, OrLL, OrLB,
               OrBI, OrBL, OrBB, OrXX;
extern BinaryOp OrC, OrS, OrI, OrL;

extern StackOp AndII, AndIL, AndIB,
               AndLI, AndLL, AndLB,
               AndBI, AndBL, AndBB, AndXX;
extern BinaryOp AndC, AndS, AndI, AndL;

extern StackOp XorII, XorIL, XorIB,
               XorLI, XorLL, XorLB,
               XorBI, XorBL, XorBB, XorXX;
extern BinaryOp XorC, XorS, XorI, XorL;

extern StackOp ShiftLII, ShiftLIL, ShiftLIB,
               ShiftLLI, ShiftLLL, ShiftLLB,
               ShiftLBI, ShiftLBL, ShiftLBB, ShiftLXX;
extern BinaryOp ShiftLC, ShiftLS, ShiftLI, ShiftLL;

extern StackOp ShiftRII, ShiftRIL, ShiftRIB,
               ShiftRLI, ShiftRLL, ShiftRLB,
               ShiftRBI, ShiftRBL, ShiftRBB, ShiftRXX;
extern BinaryOp ShiftRC, ShiftRS, ShiftRI, ShiftRL;

extern StackOp ComplementIS, ComplementLS,
               ComplementDB, ComplementXX;
extern UnaryOp ComplementC, ComplementS, ComplementI, ComplementL;

extern StackOp NegateIS, NegateLS, NegateDS, NegateDB;
extern UnaryOp NegateC, NegateS, NegateI, NegateL,
               NegateF, NegateD, NegateZ;

extern StackOp NotIS, NotLS, NotDS, NotDB;
extern UnaryOp NotC, NotS, NotI, NotL, NotF, NotD, NotZ,
               NotQ, NotP, NotSI, NotVD;

extern StackOp TrueIS, TrueLS, TrueDS, TrueDB;
extern UnaryOp TrueC, TrueS, TrueI, TrueL, TrueF, TrueD, TrueZ,
               TrueQ, TrueP, TrueSI, TrueVD;

extern StackOp AddII, AddIL, AddID, AddIB,
               AddLI, AddLL, AddLD, AddLB,
               AddDI, AddDL, AddDD, AddDB,
               AddBI, AddBL, AddBD, AddBB;
extern BinaryOp AddC, AddS, AddI, AddL,
                AddF, AddD, AddZ, AddQ;

extern StackOp SubtractII, SubtractIL, SubtractID, SubtractIB,
               SubtractLI, SubtractLL, SubtractLD, SubtractLB,
               SubtractDI, SubtractDL, SubtractDD, SubtractDB,
               SubtractBI, SubtractBL, SubtractBD, SubtractBB;
extern BinaryOp SubtractC, SubtractS, SubtractI, SubtractL,
                SubtractF, SubtractD, SubtractZ;

extern StackOp MultiplyII, MultiplyIL, MultiplyID, MultiplyIB,
               MultiplyLI, MultiplyLL, MultiplyLD, MultiplyLB,
               MultiplyDI, MultiplyDL, MultiplyDD, MultiplyDB,
               MultiplyBI, MultiplyBL, MultiplyBD, MultiplyBB;
extern BinaryOp MultiplyC, MultiplyS, MultiplyI, MultiplyL,
                MultiplyF, MultiplyD, MultiplyZ;

extern StackOp DivideII, DivideIL, DivideID, DivideIB,
               DivideLI, DivideLL, DivideLD, DivideLB,
               DivideDI, DivideDL, DivideDD, DivideDB,
               DivideBI, DivideBL, DivideBD, DivideBB;
extern BinaryOp DivideC, DivideS, DivideI, DivideL,
                DivideF, DivideD, DivideZ;

extern StackOp ModuloII, ModuloIL, ModuloID, ModuloIB,
               ModuloLI, ModuloLL, ModuloLD, ModuloLB,
               ModuloDI, ModuloDL, ModuloDD, ModuloDB,
               ModuloBI, ModuloBL, ModuloBD, ModuloBB;
extern BinaryOp ModuloC, ModuloS, ModuloI, ModuloL,
                ModuloF, ModuloD, ModuloZ;

extern StackOp PowerII, PowerIL, PowerID, PowerIB,
               PowerLI, PowerLL, PowerLD, PowerLB,
               PowerDI, PowerDL, PowerDD, PowerDB,
               PowerBI, PowerBL, PowerBD, PowerBB;
extern BinaryOp PowerC, PowerS, PowerI, PowerL,
                PowerF, PowerD, PowerZ;

extern BinaryOp PowerXF, PowerXD, PowerXZ;

extern StackOp GreaterII, GreaterIL, GreaterID, GreaterIB,
               GreaterLI, GreaterLL, GreaterLD, GreaterLB,
               GreaterDI, GreaterDL, GreaterDD, GreaterDB,
               GreaterBI, GreaterBL, GreaterBD, GreaterBB;
extern BinaryOp GreaterC, GreaterS, GreaterI, GreaterL,
                GreaterF, GreaterD, GreaterZ, GreaterQ;

extern StackOp LessII, LessIL, LessID, LessIB,
               LessLI, LessLL, LessLD, LessLB,
               LessDI, LessDL, LessDD, LessDB,
               LessBI, LessBL, LessBD, LessBB;

extern StackOp GreaterEQII, GreaterEQIL, GreaterEQID, GreaterEQIB,
               GreaterEQLI, GreaterEQLL, GreaterEQLD, GreaterEQLB,
               GreaterEQDI, GreaterEQDL, GreaterEQDD, GreaterEQDB,
               GreaterEQBI, GreaterEQBL, GreaterEQBD, GreaterEQBB;
extern BinaryOp GreaterEQC, GreaterEQS, GreaterEQI, GreaterEQL,
                GreaterEQF, GreaterEQD, GreaterEQZ, GreaterEQQ;

extern StackOp LessEQII, LessEQIL, LessEQID, LessEQIB,
               LessEQLI, LessEQLL, LessEQLD, LessEQLB,
               LessEQDI, LessEQDL, LessEQDD, LessEQDB,
               LessEQBI, LessEQBL, LessEQBD, LessEQBB;

extern StackOp EqualII, EqualIL, EqualID, EqualIB,
               EqualLI, EqualLL, EqualLD, EqualLB,
               EqualDI, EqualDL, EqualDD, EqualDB,
               EqualBI, EqualBL, EqualBD, EqualBB;
extern BinaryOp EqualC, EqualS, EqualI, EqualL,
                EqualF, EqualD, EqualZ, EqualQ, EqualP,
                EqualSI, EqualR;

extern StackOp NotEqualII, NotEqualIL, NotEqualID, NotEqualIB,
               NotEqualLI, NotEqualLL, NotEqualLD, NotEqualLB,
               NotEqualDI, NotEqualDL, NotEqualDD, NotEqualDB,
               NotEqualBI, NotEqualBL, NotEqualBD, NotEqualBB;
extern BinaryOp NotEqualC, NotEqualS, NotEqualI, NotEqualL,
                NotEqualF, NotEqualD, NotEqualZ, NotEqualQ, NotEqualP,
                NotEqualSI, NotEqualR;

extern StackOp Assign;
extern BinaryOp AssignC, AssignS, AssignI, AssignL,
                AssignF, AssignD, AssignZ, AssignQ, AssignP,
                AssignSI;

extern MemberOp GetMemberAY, GetMemberLV, GetMemberIO;

extern BinaryOp MatMultC, MatMultS, MatMultI, MatMultL,
                MatMultF, MatMultD, MatMultZ;

extern UnaryOp EvalAY, EvalLV;
extern UnaryOp EvalFN, EvalBI;
extern UnaryOp EvalSD, EvalIO;

extern UnaryOp SetupC, SetupS, SetupI, SetupL, SetupR, SetupVD;

extern UnaryOp PrintC, PrintS, PrintI, PrintL, PrintF, PrintD, PrintZ,
  PrintQ, PrintP, PrintSI, PrintR, PrintVD, PrintSD, PrintIO,
  PrintFN, PrintBI;

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

extern void InitStructDefs(void);   /* defined below */

static void BadRef(void);
static Operand *FormOperandXX(Symbol *owner, Operand *op);
static void ToAnyQ(Operand *op);
static void ToAnyP(Operand *op);
static void ToAnySI(Operand *op);
static void ToAnyR(Operand *op);
/*extern void ToAnyX(Operand *op);*/   /* for use by foreign types */
static void UnaryLV(Operand *op);
static void BinaryLV(Operand *l, Operand *r);
static void FreeVoid(void *v);

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

OpTable intScalar= {
  0, &FormOperandIS,
  &ToCharIS, &ToShortIS, &NoOp, &ToLongIS, &ToFloatIS, &ToDoubleIS,
    &ToComplexIS,
  &NegateIS, &ComplementIS, &NotIS, &TrueIS,
  {&AddII, &AddIL, &AddID, &AddIB},
  {&SubtractII, &SubtractIL, &SubtractID, &SubtractIB},
  {&MultiplyII, &MultiplyIL, &MultiplyID, &MultiplyIB},
  {&DivideII, &DivideIL, &DivideID, &DivideIB},
  {&ModuloII, &ModuloIL, &ModuloID, &ModuloIB},
  {&PowerII, &PowerIL, &PowerID, &PowerIB},
  {&EqualII, &EqualIL, &EqualID, &EqualIB},
  {&NotEqualII, &NotEqualIL, &NotEqualID, &NotEqualIB},
  {&GreaterII, &GreaterIL, &GreaterID, &GreaterIB},
  {&LessII, &LessIL, &LessID, &LessIB},
  {&GreaterEQII, &GreaterEQIL, &GreaterEQID, &GreaterEQIB},
  {&LessEQII, &LessEQIL, &LessEQID, &LessEQIB},
  {&ShiftLII, &ShiftLIL, &ShiftLXX, &ShiftLIB},
  {&ShiftRII, &ShiftRIL, &ShiftRXX, &ShiftRIB},
  {&OrII, &OrIL, &OrXX, &OrIB},
  {&AndII, &AndIL, &AndXX, &AndIB},
  {&XorII, &XorIL, &XorXX, &XorIB}
};

OpTable longScalar= {
  1, &FormOperandLS,
  &ToCharLS, &ToShortLS, &ToIntLS, &NoOp, &ToFloatLS, &ToDoubleLS,
    &ToComplexLS,
  &NegateLS, &ComplementLS, &NotLS, &TrueLS,
  {&AddLI, &AddLL, &AddLD, &AddLB},
  {&SubtractLI, &SubtractLL, &SubtractLD, &SubtractLB},
  {&MultiplyLI, &MultiplyLL, &MultiplyLD, &MultiplyLB},
  {&DivideLI, &DivideLL, &DivideLD, &DivideLB},
  {&ModuloLI, &ModuloLL, &ModuloLD, &ModuloLB},
  {&PowerLI, &PowerLL, &PowerLD, &PowerLB},
  {&EqualLI, &EqualLL, &EqualLD, &EqualLB},
  {&NotEqualLI, &NotEqualLL, &NotEqualLD, &NotEqualLB},
  {&GreaterLI, &GreaterLL, &GreaterLD, &GreaterLB},
  {&LessLI, &LessLL, &LessLD, &LessLB},
  {&GreaterEQLI, &GreaterEQLL, &GreaterEQLD, &GreaterEQLB},
  {&LessEQLI, &LessEQLL, &LessEQLD, &LessEQLB},
  {&ShiftLLI, &ShiftLLL, &ShiftLXX, &ShiftLLB},
  {&ShiftRLI, &ShiftRLL, &ShiftRXX, &ShiftRLB},
  {&OrLI, &OrLL, &OrXX, &OrLB},
  {&AndLI, &AndLL, &AndXX, &AndLB},
  {&XorLI, &XorLL, &XorXX, &XorLB}
};

OpTable doubleScalar= {
  2, &FormOperandDS,
  &ToCharDS, &ToShortDS, &ToIntDS, &ToLongDS, &ToFloatDS, &NoOp,
    &ToComplexDS,
  &NegateDS, &ComplementXX, &NotDS, &TrueDS,
  {&AddDI, &AddDL, &AddDD, &AddDB},
  {&SubtractDI, &SubtractDL, &SubtractDD, &SubtractDB},
  {&MultiplyDI, &MultiplyDL, &MultiplyDD, &MultiplyDB},
  {&DivideDI, &DivideDL, &DivideDD, &DivideDB},
  {&ModuloDI, &ModuloDL, &ModuloDD, &ModuloDB},
  {&PowerDI, &PowerDL, &PowerDD, &PowerDB},
  {&EqualDI, &EqualDL, &EqualDD, &EqualDB},
  {&NotEqualDI, &NotEqualDL, &NotEqualDD, &NotEqualDB},
  {&GreaterDI, &GreaterDL, &GreaterDD, &GreaterDB},
  {&LessDI, &LessDL, &LessDD, &LessDB},
  {&GreaterEQDI, &GreaterEQDL, &GreaterEQDD, &GreaterEQDB},
  {&LessEQDI, &LessEQDL, &LessEQDD, &LessEQDB},
  {&ShiftLXX, &ShiftLXX, &ShiftLXX, &ShiftLXX},
  {&ShiftRXX, &ShiftRXX, &ShiftRXX, &ShiftRXX},
  {&OrXX, &OrXX, &OrXX, &OrXX},
  {&AndXX, &AndXX, &AndXX, &AndXX},
  {&XorXX, &XorXX, &XorXX, &XorXX}
};

OpTable dataBlockSym= {
  3, &FormOperandDB,
  &ToCharDB, &ToShortDB, &ToIntDB, &ToLongDB, &ToFloatDB, &ToDoubleDB,
    &ToComplexDB,
  &NegateDB, &ComplementDB, &NotDB, &TrueDB,
  {&AddBI, &AddBL, &AddBD, &AddBB},
  {&SubtractBI, &SubtractBL, &SubtractBD, &SubtractBB},
  {&MultiplyBI, &MultiplyBL, &MultiplyBD, &MultiplyBB},
  {&DivideBI, &DivideBL, &DivideBD, &DivideBB},
  {&ModuloBI, &ModuloBL, &ModuloBD, &ModuloBB},
  {&PowerBI, &PowerBL, &PowerBD, &PowerBB},
  {&EqualBI, &EqualBL, &EqualBD, &EqualBB},
  {&NotEqualBI, &NotEqualBL, &NotEqualBD, &NotEqualBB},
  {&GreaterBI, &GreaterBL, &GreaterBD, &GreaterBB},
  {&LessBI, &LessBL, &LessBD, &LessBB},
  {&GreaterEQBI, &GreaterEQBL, &GreaterEQBD, &GreaterEQBB},
  {&LessEQBI, &LessEQBL, &LessEQBD, &LessEQBB},
  {&ShiftLBI, &ShiftLBL, &ShiftLXX, &ShiftLBB},
  {&ShiftRBI, &ShiftRBL, &ShiftRXX, &ShiftRBB},
  {&OrBI, &OrBL, &OrXX, &OrBB},
  {&AndBI, &AndBL, &AndXX, &AndBB},
  {&XorBI, &XorBL, &XorXX, &XorBB}
};

OpTable referenceSym= {
  0, &FormOperandRF,
  &BadRef, &BadRef, &BadRef, &BadRef, &BadRef, &BadRef,
    &BadRef,
  &BadRef, &BadRef, &BadRef, &BadRef,
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef}
};

OpTable returnSym= {
  0, &FormOperandXX,
  &BadRef, &BadRef, &BadRef, &BadRef, &BadRef, &BadRef,
    &BadRef,
  &BadRef, &BadRef, &BadRef, &BadRef,
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef},
  {&BadRef, &BadRef, &BadRef, &BadRef}
};

static void BadRef(void)
{ YError("(BUG) unexpected referenceSym or returnSym"); }

/* ARGSUSED */
static Operand *FormOperandXX(Symbol *owner, Operand *op)
{ YError("(BUG) unexpected returnSym"); return 0; }

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

static void ToAnyQ(Operand *op)
{ YError("string cannot be converted to numeric data type"); }

static void ToAnyP(Operand *op)
{ YError("pointer cannot be converted to numeric data type"); }

static void ToAnySI(Operand *op)
{ YError("structure instance cannot be converted to numeric data type"); }

static void ToAnyR(Operand *op)
{ YError("index range cannot be converted to numeric data type"); }

void ToAnyX(Operand *op)
{ YError("impossible data type conversion"); }

static void UnaryLV(Operand *op)
{ YError("(BUG) impossible appearance of LValue"); }

static void BinaryLV(Operand *l, Operand *r) { UnaryLV(l); }

void EvalX(Operand *op)
{ YError("attempt to call non-function or index non-array"); }

void EvalIO(Operand *op)
{ EvalX(op); }

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

Operations charOps = {
  &FreeArray, T_CHAR, 1, T_CHAR, "char",
  {&PromNOP, &PromCS, &PromCI, &PromCL, &PromCF, &PromCD, &PromCZ, &PromXX},
  &No_Op, &ToShortC, &ToIntC, &ToLongC, &ToFloatC, &ToDoubleC, &ToComplexC,
  &NegateC, &ComplementC, &NotC, &TrueC,
  &AddC, &SubtractC, &MultiplyC, &DivideC, &ModuloC, &PowerC,
  &EqualC, &NotEqualC, &GreaterC, &GreaterEQC,
  &ShiftLC, &ShiftRC, &OrC, &AndC, &XorC,
  &AssignC, &EvalAY, &SetupC, &GetMemberAY, &MatMultC, &PrintC
};

Operations shortOps = {
  &FreeArray, T_SHORT, 1, T_SHORT, "short",
  {&PromSC, &PromNOP, &PromSI, &PromSL, &PromSF, &PromSD, &PromSZ, &PromXX},
  &ToCharS, &No_Op, &ToIntS, &ToLongS, &ToFloatS, &ToDoubleS, &ToComplexS,
  &NegateS, &ComplementS, &NotS, &TrueS,
  &AddS, &SubtractS, &MultiplyS, &DivideS, &ModuloS, &PowerS,
  &EqualS, &NotEqualS, &GreaterS, &GreaterEQS,
  &ShiftLS, &ShiftRS, &OrS, &AndS, &XorS,
  &AssignS, &EvalAY, &SetupS, &GetMemberAY, &MatMultS, &PrintS
};

Operations intOps = {
  &FreeArray, T_INT, 1, T_INT, "int",
  {&PromIC, &PromIS, &PromNOP, &PromIL, &PromIF, &PromID, &PromIZ, &PromXX},
  &ToCharI, &ToShortI, &No_Op, &ToLongI, &ToFloatI, &ToDoubleI, &ToComplexI,
  &NegateI, &ComplementI, &NotI, &TrueI,
  &AddI, &SubtractI, &MultiplyI, &DivideI, &ModuloI, &PowerI,
  &EqualI, &NotEqualI, &GreaterI, &GreaterEQI,
  &ShiftLI, &ShiftRI, &OrI, &AndI, &XorI,
  &AssignI, &EvalAY, &SetupI, &GetMemberAY, &MatMultI, &PrintI
};

Operations longOps = {
  &FreeArray, T_LONG, 1, T_LONG, "long",
  {&PromLC, &PromLS, &PromLI, &PromNOP, &PromLF, &PromLD, &PromLZ, &PromXX},
  &ToCharL, &ToShortL, &ToIntL, &No_Op, &ToFloatL, &ToDoubleL, &ToComplexL,
  &NegateL, &ComplementL, &NotL, &TrueL,
  &AddL, &SubtractL, &MultiplyL, &DivideL, &ModuloL, &PowerL,
  &EqualL, &NotEqualL, &GreaterL, &GreaterEQL,
  &ShiftLL, &ShiftRL, &OrL, &AndL, &XorL,
  &AssignL, &EvalAY, &SetupL, &GetMemberAY, &MatMultL, &PrintL
};

Operations floatOps = {
  &FreeArray, T_FLOAT, 1, T_FLOAT, "float",
  {&PromFC, &PromFS, &PromFI, &PromFL, &PromNOP, &PromFD, &PromFZ, &PromXX},
  &ToCharF, &ToShortF, &ToIntF, &ToLongF, &No_Op, &ToDoubleF, &ToComplexF,
  &NegateF, &ComplementX, &NotF, &TrueF,
  &AddF, &SubtractF, &MultiplyF, &DivideF, &ModuloF, &PowerF,
  &EqualF, &NotEqualF, &GreaterF, &GreaterEQF,
  &ShiftLX, &ShiftRX, &OrX, &AndX, &XorX,
  &AssignF, &EvalAY, &SetupX, &GetMemberAY, &MatMultF, &PrintF
};

Operations doubleOps = {
  &FreeArray, T_DOUBLE, 1, T_DOUBLE, "double",
  {&PromDC, &PromDS, &PromDI, &PromDL, &PromDF, &PromNOP, &PromDZ, &PromXX},
  &ToCharD, &ToShortD, &ToIntD, &ToLongD, &ToFloatD, &No_Op, &ToComplexD,
  &NegateD, &ComplementX, &NotD, &TrueD,
  &AddD, &SubtractD, &MultiplyD, &DivideD, &ModuloD, &PowerD,
  &EqualD, &NotEqualD, &GreaterD, &GreaterEQD,
  &ShiftLX, &ShiftRX, &OrX, &AndX, &XorX,
  &AssignD, &EvalAY, &SetupX, &GetMemberAY, &MatMultD, &PrintD
};

Operations complexOps = {
  &FreeArray, T_COMPLEX, 1, T_COMPLEX, "complex",
  {&PromZC, &PromZS, &PromZI, &PromZL, &PromZF, &PromZD, &PromNOP, &PromXX},
  &ToCharZ, &ToShortZ, &ToIntZ, &ToLongZ, &ToFloatZ, &ToDoubleZ, &No_Op,
  &NegateZ, &ComplementX, &NotZ, &TrueZ,
  &AddZ, &SubtractZ, &MultiplyZ, &DivideZ, &ModuloZ, &PowerZ,
  &EqualZ, &NotEqualZ, &GreaterZ, &GreaterEQZ,
  &ShiftLX, &ShiftRX, &OrX, &AndX, &XorX,
  &AssignZ, &EvalAY, &SetupX, &GetMemberAY, &MatMultZ, &PrintZ
};

Operations stringOps = {
  &FreeArray, T_STRING, 1, T_STRING, "string",
  {&PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX},
  &ToAnyQ, &ToAnyQ, &ToAnyQ, &ToAnyQ, &ToAnyQ, &ToAnyQ, &ToAnyQ,
  &NegateX, &ComplementX, &NotQ, &TrueQ,
  &AddQ, &SubtractX, &MultiplyX, &DivideX, &ModuloX, &PowerX,
  &EqualQ, &NotEqualQ, &GreaterQ, &GreaterEQQ,
  &ShiftLX, &ShiftRX, &OrX, &AndX, &XorX,
  &AssignQ, &EvalAY, &SetupX, &GetMemberAY, &MatMultX, &PrintQ
};

Operations pointerOps = {
  &FreeArray, T_POINTER, 1, T_STRING, "pointer",
  {&PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX},
  &ToAnyP, &ToAnyP, &ToAnyP, &ToAnyP, &ToAnyP, &ToAnyP, &ToAnyP,
  &NegateX, &ComplementX, &NotP, &TrueP,
  &AddX, &SubtractX, &MultiplyX, &DivideX, &ModuloX, &PowerX,
  &EqualP, &NotEqualP, &GreaterX, &GreaterEQX,
  &ShiftLX, &ShiftRX, &OrX, &AndX, &XorX,
  &AssignP, &EvalAY, &SetupX, &GetMemberAY, &MatMultX, &PrintP
};

Operations structOps = {
  &FreeArray, T_STRUCT, 1, T_STRING, "struct_instance",
  {&PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX},
  &ToAnySI, &ToAnySI, &ToAnySI, &ToAnySI, &ToAnySI, &ToAnySI, &ToAnySI,
  &NegateX, &ComplementX, &NotSI, &TrueSI,
  &AddX, &SubtractX, &MultiplyX, &DivideX, &ModuloX, &PowerX,
  &EqualSI, &NotEqualSI, &GreaterX, &GreaterEQX,
  &ShiftLX, &ShiftRX, &OrX, &AndX, &XorX,
  &AssignSI, &EvalAY, &SetupX, &GetMemberAY, &MatMultX, &PrintSI
};

Operations *yOpsStruct= &structOps;
Operations *yOpsStream= &streamOps;
Operations *yOpsStructDef= &structDefOps;

Operations rangeOps = {
  &FreeRange, T_RANGE, 0, T_STRING, "range",
  {&PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX},
  &ToAnyR, &ToAnyR, &ToAnyR, &ToAnyR, &ToAnyR, &ToAnyR, &ToAnyR,
  &NegateX, &ComplementX, &NotX, &TrueX,
  &AddX, &SubtractX, &MultiplyX, &DivideX, &ModuloX, &PowerX,
  &EqualR, &NotEqualR, &GreaterX, &GreaterEQX,
  &ShiftLX, &ShiftRX, &OrX, &AndX, &XorX,
  &AssignX, &EvalX, &SetupR, &GetMemberX, &MatMultX, &PrintR
};

Operations lvalueOps = {
  &FreeLValue, T_LVALUE, 0, T_STRING, "lvalue",
  {&PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX},
  &UnaryLV, &UnaryLV, &UnaryLV, &UnaryLV, &UnaryLV, &UnaryLV, &UnaryLV,
  &UnaryLV, &UnaryLV, &UnaryLV, &UnaryLV,
  &BinaryLV, &BinaryLV, &BinaryLV, &BinaryLV, &BinaryLV, &BinaryLV,
  &BinaryLV, &BinaryLV, &BinaryLV, &BinaryLV,
  &BinaryLV, &BinaryLV, &BinaryLV, &BinaryLV, &BinaryLV,
  &BinaryLV, &EvalLV, &UnaryLV, &GetMemberLV, &BinaryLV, &UnaryLV
};

/* Nil, or [], the one instance of a void.  */
DataBlock nilDB= { 0, &voidOps };

static void FreeVoid(void *v)
{ if (nilDB.references<0) nilDB.references= 0;
  YError("(BUG) attempt to free nilDB DataBlock"); }

Operations voidOps = {
  &FreeVoid, T_VOID, 0, T_STRING, "void",
  {&PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX},
  &ToAnyX, &ToAnyX, &ToAnyX, &ToAnyX, &ToAnyX, &ToAnyX, &ToAnyX,
  &NegateX, &ComplementX, &NotVD, &TrueVD,
  &AddX, &SubtractX, &MultiplyX, &DivideX, &ModuloX, &PowerX,
  &EqualX, &NotEqualX, &GreaterX, &GreaterEQX,
  &ShiftLX, &ShiftRX, &OrX, &AndX, &XorX,
  &AssignX, &EvalX, &SetupVD, &GetMemberX, &MatMultX, &PrintVD
};

Operations functionOps = {
  &FreeFunction, T_FUNCTION, 0, T_STRING, "function",
  {&PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX},
  &ToAnyX, &ToAnyX, &ToAnyX, &ToAnyX, &ToAnyX, &ToAnyX, &ToAnyX,
  &NegateX, &ComplementX, &NotVD, &TrueVD,
  &AddX, &SubtractX, &MultiplyX, &DivideX, &ModuloX, &PowerX,
  &EqualX, &NotEqualX, &GreaterX, &GreaterEQX,
  &ShiftLX, &ShiftRX, &OrX, &AndX, &XorX,
  &AssignX, &EvalFN, &SetupX, &GetMemberX, &MatMultX, &PrintFN
};

Operations builtinOps = {
  &FreeBIFunction, T_BUILTIN, 0, T_STRING, "builtin",
  {&PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX},
  &ToAnyX, &ToAnyX, &ToAnyX, &ToAnyX, &ToAnyX, &ToAnyX, &ToAnyX,
  &NegateX, &ComplementX, &NotVD, &TrueVD,
  &AddX, &SubtractX, &MultiplyX, &DivideX, &ModuloX, &PowerX,
  &EqualX, &NotEqualX, &GreaterX, &GreaterEQX,
  &ShiftLX, &ShiftRX, &OrX, &AndX, &XorX,
  &AssignX, &EvalBI, &SetupX, &GetMemberX, &MatMultX, &PrintBI
};

Operations structDefOps = {
  &FreeStructDef, T_STRUCTDEF, 0, T_STRING, "struct_definition",
  {&PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX},
  &ToAnyX, &ToAnyX, &ToAnyX, &ToAnyX, &ToAnyX, &ToAnyX, &ToAnyX,
  &NegateX, &ComplementX, &NotX, &TrueX,
  &AddX, &SubtractX, &MultiplyX, &DivideX, &ModuloX, &PowerX,
  &EqualX, &NotEqualX, &GreaterX, &GreaterEQX,
  &ShiftLX, &ShiftRX, &OrX, &AndX, &XorX,
  &AssignX, &EvalSD, &SetupX, &GetMemberX, &MatMultX, &PrintSD
};

/* These IOStream operations are only defaults...  Other classes of IOStream
   may exist with alternative virtual functions.  */
Operations streamOps = {
  &FreeIOStream, T_STREAM, 0, T_STRING, "stream",
  {&PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX, &PromXX},
  &ToAnyX, &ToAnyX, &ToAnyX, &ToAnyX, &ToAnyX, &ToAnyX, &ToAnyX,
  &NegateX, &ComplementX, &NotX, &TrueX,
  &AddX, &SubtractX, &MultiplyX, &DivideX, &ModuloX, &PowerX,
  &EqualX, &NotEqualX, &GreaterX, &GreaterEQX,
  &ShiftLX, &ShiftRX, &OrX, &AndX, &XorX,
  &AssignX, &EvalIO, &SetupX, &GetMemberIO, &MatMultX, &PrintIO
};

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

/* Floating point layouts for floats and doubles on this machine */
static FPLayout fltSLayout= {1, P_FLOAT_LAYOUT};
static FPLayout dblSLayout= {1, P_DOUBLE_LAYOUT};
FPLayout *fltLayout= &fltSLayout;
FPLayout *dblLayout= &dblSLayout;

StructDef charStruct = {
  0, &structDefOps, &charOps, sizeof(char),
  P_CHAR_ALIGN, {0, 0, 0, 0, 0}, 0, 0,
  &CopyX, 0, 0, 0, 0, 0, 0, 0 };

StructDef shortStruct = {
  0, &structDefOps, &shortOps, sizeof(short),
  P_SHORT_ALIGN, {0, 0, 0, 0, 0}, 0, 0,
  &CopyX, 0, 1, 0, 0, 0, P_SHORT_ORDER, 0 };

StructDef intStruct = {
  0, &structDefOps, &intOps, sizeof(int),
  P_INT_ALIGN, {0, 0, 0, 0, 0}, 0, 0,
  &CopyX, 0, 2, 0, 0, 0, P_INT_ORDER, 0 };

StructDef longStruct = {
  0, &structDefOps, &longOps, sizeof(long),
  P_LONG_ALIGN, {0, 0, 0, 0, 0}, 0, 0,
  &CopyX, 0, 3, 0, 0, 0, P_LONG_ORDER, 0 };

StructDef floatStruct = {
  0, &structDefOps, &floatOps, sizeof(float),
  P_FLOAT_ALIGN, {0, 0, 0, 0, 0}, 0, 0,
  &CopyX, 0, 4, 0, 0, 0, P_FLOAT_ORDER, &fltSLayout };

StructDef doubleStruct = {
  0, &structDefOps, &doubleOps, sizeof(double),
  P_DOUBLE_ALIGN, {0, 0, 0, 0, 0}, 0, 0,
  &CopyX, 0, 5, 0, 0, 0, P_DOUBLE_ORDER, &dblSLayout };

StructDef stringStruct = {
  0, &structDefOps, &stringOps, sizeof(char *),
  P_POINTER_ALIGN, {0, 0, 0, 0, 0}, 0, 0,
  &CopyQ, 0, 6, 0, 0, 0, 0, 0 };

StructDef pointerStruct = {
  0, &structDefOps, &pointerOps, sizeof(void *),
  P_POINTER_ALIGN, {0, 0, 0, 0, 0}, 0, 0,
  &CopyP, 0, 7, 0, 0, 0, P_LONG_ORDER, 0 };

StructDef complexStruct = {
  0, &structDefOps, 0 /* &complexOps */, 0 /* 2*sizeof(double) */,
  0 /* P_DOUBLE_ALIGN */, {0, 0, 0, 0, 0}, 0, 0,
  &CopyX, 0, 8, 0, 0, 0, 0, 0 };

int yStructAlign= P_STRUCT_ALIGN;

HashTable yStructTable;
StructDef **yStructList= 0;

static void PrimInstall(char *name, StructDef *base);
static void GlobInstall(const char *name, StructDef *base);

static void GlobInstall(const char *name, StructDef *base)
{
  long index= Globalize(name, 0L);
  if (globTab[index].ops==&dataBlockSym &&
      globTab[index].value.db==&nilDB) {
    globTab[index].value.db= (DataBlock *)Ref(base);
    Unref(&nilDB);
  }
}

void (*DefInstallHook)(const char *name, StructDef *base)= &GlobInstall;

static void PrimInstall(char *name, StructDef *base)
{
  HashAdd(&yStructTable, name, 0L);
  HASH_MANAGE(yStructTable, StructDef *, yStructList);
  yStructList[hashIndex]= base;
  if (DefInstallHook) DefInstallHook(name, base);
}

void InitStructDefs(void)
{
  /* install the basic StructDefs into the global symbol table --
     this order is critical */
  PrimInstall("char", &charStruct);
  PrimInstall("short", &shortStruct);
  PrimInstall("int", &intStruct);
  PrimInstall("long", &longStruct);
  PrimInstall("float", &floatStruct);
  PrimInstall("double", &doubleStruct);
  PrimInstall("string", &stringStruct);
  PrimInstall("pointer", &pointerStruct);

  /* define the re and im parts of complex */
  HashAdd(&yStructTable, "complex", 0L);
  HASH_MANAGE(yStructTable, StructDef *, yStructList);
  yStructList[hashIndex]= &complexStruct;
  AddMember(&complexStruct, -1L, "re", &doubleStruct, (Dimension *)0);
  AddMember(&complexStruct, -1L, "im", &doubleStruct, (Dimension *)0);
  InstallStruct(&complexStruct, (StructDef *)0);
  complexStruct.dataOps= &complexOps;
}

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