#include <perms.h>
_imp_string Date(void);
_imp_string Time(void);
extern void Exit(int Rc);
int Cputime(void);
void Getblock(int Len, unsigned char *Base);
int Getlong(void);
int Getword(void);
void Get(int *N);
void Put(int N);
void Putword(int N);
void Putlong(int N);
void Putblock(int Len, unsigned char *B);
void Selectinputtank(int N);
void Selectoutputtank(int N);
void Printrecord(int Len, unsigned char *Buff);
int Look(void);
int Tag(void);
_imp_string Itos(int N, int P);
static const int Report = 0;
static const int Objectfile = 1;
static const int Listing = 2;
static const int Diagstream = Listing;
static const int Maxident = 31;
static const int Fatal = 0x1000002C;
extern _imp_string Version;
extern int Command;
extern int Control;
static const int Diagbit = 000004;
static const int Linebit = 000010;
static const int Logbit = 000020;
static const int Timebit = 001000;
static const int Entrybit = 002000;
static const int Initbit = 004000;
static const int Picbit = 010000;
static const int Asscheck = 1;
static const int Strcheck = 2;
static const int Forcheck = 4;
static const int Arrcheck = 8;
static const int Ovfcheck = 16;
static const int Recround = 128;
static const int Profiling = 256;
static const int Objextern = 1;
static const int Objcode = 2;
static const int Objgla = 3;
static const int Objpdef = 4;
static const int Objpspec = 5;
static const int Objddef = 6;
static const int Objdspec = 7;
static const int Objreloc = 8;
static const int Objset = 9;
static const int Objheader = 10;
static const int Objcall = 11;
static const int Objjump = 12;
static const int Objprimspec = 13;
static const int Objend = 14;
static const int Objline = 15;
static const int Objterm = 16;
static const int Objdiagp = 17;
static const int Objdiagv = 18;
static const int Objweak = 19;
static const int Objblab = 20;
static const int Objwlab = 21;
static const int Objglam = 22;
static const int Objmodd = 23;
static const int Objprimref = 24;
static const int Objextref = 25;
static const int Lastobjcode = 25;
static const int Dirused = 1;
static const int Dirldef = 2;
static const int Dirpref = 3;
static const int Dircref = 4;
static const int Diruref = 5;
static const int Dirend = 6;
static const int Dirsizes = 7;
static const int Dirxend = 8;
static const int Dirheader = 9;
static const int Direntry = 10;
static const int Lastdircode = 10;
static const int Maxtag = 4000;
static const int Maxref = 6000;
static const int Maxprocs = 600;
static const int Maxexternals = 400;
static const int Maxrec = 512;
void Pass3(_imp_string Module, int Object, int Directives) {
  int Checkass = Control & Asscheck;
  int Diags = Command & Diagbit;
  int Ldump = Command & Linebit;
  int Pic = Command & Picbit;
  int Init = Command & Initbit;
  int Timing = Command & Timebit;
  int Clog = Command & Logbit;
  static const int Procenterprim = 13;
  static const int Nonzero = 1;
  static const int Brb = 0x11;
  static const int Brw = 0x31;
  static const int Jmp = 0x17;
  static const int Bneq = 0x12;
  static const int Bnequ = 0x12;
  static const int Beql = 0x13;
  static const int Beqlu = 0x13;
  static const int Bgtr = 0x14;
  static const int Bleq = 0x15;
  static const int Bgeq = 0x18;
  static const int Blss = 0x19;
  static const int Bgtru = 0x1A;
  static const int Blequ = 0x1B;
  static const int Bgequ = 0x1E;
  static const int Blssu = 0x1F;
  static const int Jsb = 0x16;
  static const int Calls = 0xFB;
  static const int Movl = 0xD0;
  static const int Moval = 0xDE;
  static const int Movab = 0x9E;
  static const int Subl2 = 0xC2;
  static const int Movc5 = 0x2C;
  static const unsigned char Branch[16 /*0:15*/] = {0x11, 0x13, 0x19, 0x15, 0x14, 0x18, 0x12, 0,
                                                    0x11, 0x13, 0x1F, 0x1B, 0x1A, 0x1E, 0x12, 0};
  static const int Margin = 800;
  static const int Safelow = 0xFFFF8001 + Margin;
  static const int Safehigh = 0x00008000 - Margin;
  static const int Middling = 0x1000;
  static const int Objhdr = 0;
  static const int Hdrmhd = 0;
  static const int Hdrlng = 1;
  static const int Objgsd = 1;
  static const int Gsdpsc = 0;
  static const int Gsdsym = 1;
  static const int Gsdepm = 2;
  static const int Objtir = 2;
  static const int Tirstag = 0;
  static const int Tirstasb = 1;
  static const int Tirstasw = 2;
  static const int Tirstal = 3;
  static const int Tirstpbb = 4;
  static const int Tirstpbw = 5;
  static const int Tirstpbl = 6;
  static const int Tirstaub = 7;
  static const int Tirstob = 20;
  static const int Tirstow = 21;
  static const int Tirstol = 22;
  static const int Tirstold = 25;
  static const int Tirstopidr = 27;
  static const int Tirstopicr = 28;
  static const int Tirstorl = 31;
  static const int Tirstoub = 33;
  static const int Tirstogb = 37;
  static const int Tirstorb = 39;
  static const int Tirstorw = 40;
  static const int Tiradd = 51;
  static const int Tirsetrb = 80;
  static const int Tiraugrb = 81;
  static const int Objeom = 3;
  static const int Objdbg = 4;
  static const int Quad = 3;
  static const int Pspic = 1 << 0;
  static const int Psrel = 1 << 3;
  static const int Psshr = 1 << 5;
  static const int Psexe = 1 << 6;
  static const int Psrd = 1 << 7;
  static const int Pswrt = 1 << 8;
  static int *Ca;
  static int *Ga;
  static int Base = 0;
  static short Refhead = 0;
  static short *Refchain;
  Refchain = &Refhead;
  static short Deflist = 0;
  static int Thisline = 0;
  static int Entrytag = -1;
  static const int Codeflags = Pspic | Psrel | Psrd | Psexe | Psshr;
  static int Glapflags = Psrd | Pswrt | Psrel | Pspic;
  static const int Diagflags = Pspic | Psrel | Psrd | Psshr;
  static const int Lineflags = Pspic | Psrel | Psrd | Psshr;
  static const _imp_string Codename = _imp_str_literal("$_CODEAREA");
  static _imp_string Glapname = _imp_str_literal("$_GLAPAREA");
  static const _imp_string Diagname = _imp_str_literal("$_DIAGAREA");
  static const _imp_string Linename = _imp_str_literal("$_CODELINE");
  static const _imp_string Initproc = _imp_str_literal("IMP$_INIT");
  int Refs;
  int Lasttag;
  int Codesize;
  int Glapsize;
  int Diagsize;
  int Linesize;
  int Procs;
  int Events;
  int Eventbase;
  int Evp;
  int Specs;
  static _imp_string Text;
  typedef struct Psectfm {
    int Bp;
    int Pa;
    int Dump;
    int Bs;
    int Lr;
    int Lrp;
    int Index;
    int Lbs;
    int Bb;
    int Be;
    int Max;
  } Psectfm;
  static Psectfm Codep;
  static Psectfm Glapp;
  static Psectfm Workp;
  static Psectfm Diagp;
  static Psectfm Linep;
  static Psectfm *Buff;
  typedef struct Reffm {
    int Ca;
    int Tag;
    short Flag;
    short Link;
  } Reffm;
  typedef struct Deffm {
    int Ca;
    short Uses;
    short Link;
  } Deffm;
  Deffm Def[4001 /*0:4000*/];
  Reffm Ref[6000 /*1:6000*/];
  typedef struct Procfm {
    int Frame;
    short Type;
    short Mask;
    short Diag;
    short Diagep;
    short Lineep;
  } Procfm;
  Procfm Proctab[600 /*1:600*/];
  unsigned char Extused[400 /*1:400*/];
  _imp_string Exttext[400 /*1:400*/];
  void Error(_imp_string Text, int Extra) {
    Selectoutput(Report);
    Newline();
    Printstring(_imp_str_literal("***Pass3 fails \""));
    Printstring(Text);
    Printstring(_imp_str_literal("\" ("));
    Write(Extra, 0);
    Printsymbol(')');
    Newline();
    _imp_monitor();
    Exit(0x1000002C);
  }
  void Getstring(_imp_string * T) {
    int Len;
    int Filelen;
    Get(Len);
    Filelen = Len;
    if (0 >= Len || Len > Maxident) Error(_imp_str_literal("external size?"), Len);
    if (Len == Maxident) Len--;
    *Length(*T) = Len;
    Getblock(Filelen, *Charno(*T, 1));
  }
  auto void Stpb(Psectfm * P, int D);
  auto void Add(int B);
  void Flushbuff(void) {
    int *Bp;
    Bp = &Buff->* Bp;
    if (*Bp > Maxrec) Error(_imp_str_literal("buffer error - seek help!!"), *Bp - Maxrec);
    if (Buff->Dump) {
      if (Buff->Bs > 0) Error(_imp_str_literal("buffer error"), 1);
      if (*Bp > 1) Printrecord(*Bp, Buff->B);
    }
    Buff->Bs = 0;
    Buff->Be = 0;
    Buff->Lbs = 0;
    Buff->Lr = 0;
    *Bp = 1;
    if (Buff->Type == Objtir && Buff->Dump != 0) {
      Stpb(*Buff, Buff->Pa);
      Add(Tirsetrb);
      Buff->Lr = Buff->* Bp;
      Buff->Lrp = 1;
    }
  }
  void Need(int B) {
    if (Buff->Bp + B > Maxrec) Flushbuff();
  }
  void Setwork(int Type) {
    Buff = &Workp;
    Flushbuff();
    Workp = 0;
    Workp.Dump = 1;
    Workp.Type = Type;
    Workp.Bp = 1;
  }
  void Add(int B) {
    if (!Buff->Dump) return;
    Buff->Bp = Buff->Bp + 1;
    Buff->B = B & 255;
  }
  void Addw(int N) {
    if (!Buff->Dump) return;
    Shortinteger = N;
    Buff->Bp = Buff->Bp + 2;
  }
  void Addl(int N) {
    if (!Buff->Dump) return;
    *Integer(Addr(Buff->B)) = N;
    Buff->Bp = Buff->Bp + 4;
  }
  void Addstring(int From, _imp_string S) {
    int B;
    int L;
    if (!Buff->Dump) return;
    L = *Length(S);
    if (!From) {
      *String(Addr(Buff->B(Buff->Bp + 1))) = S;
      Buff->Bp = Buff->Bp + 1;
    } else {
      B = Buff->B(Buff->Bp);
      *String(Addr(Buff->B(Buff->Bp))) = S;
      Buff->B(Buff->Bp) = B;
    }
    Buff->Bp = Buff->Bp + L;
  }
  void Addtext(int Data) {
    _imp_string T = Text;
    if (!Buff->Dump) return;
    if (Data) T = _imp_join(T, _imp_str_literal("_"));
    Addstring(0, T);
  }
  int Range(int Disp, int Extra) {
    if (-128 <= Disp && Disp <= 127) return (1);
    if (0xFFFF8000 <= Disp - Extra && Disp - Extra <= 0x7FFF) return (2);
    return (4);
  }
  void Stag(_imp_string S) {
    Need(1 + 1 + *Length(S));
    Add(Tirstag);
    Addstring(0, S);
  }
  void Tircommand(int *Value, int Param, unsigned char Clist) {
    int Size;
    Size = Range(*Value, 0);
    Need(2 + Size);
    Add(Clist);
    if (Param >= 0) Add(Param);
    if (Size == 1)
      Add(*Value);
    else if (Size == 2)
      Addw(*Value);
    else
      Addl(*Value);
    *Value = Size;
  }
  void Stpb(Psectfm * P, int Offset) {
    static unsigned char Stpbc[4 /*1:4*/] = {4, 5, 0, 6};
    Tircommand(Offset, P.Index, Stpbc);
  }
  void Stak(int Value) {
    static unsigned char Stac[4 /*1:4*/] = {1, 2, 0, 3};
    Tircommand(Value, -1, Stac);
  }
  void Select(int Disp) {
    if (!Buff->Dump) return;
    Need(7);
    if (Disp > Buff->Max) Error(_imp_str_literal("psect overflow"), Disp);
    if (Buff->Lr == Buff->Bp) {
      Buff->Bp = Buff->Lrp;
      Buff->Pa = -20;
    }
    if (Buff->Pa != Disp) {
      Buff->Lrp = Buff->Bp;
      Stpb(*Buff, Disp);
      Add(Tirsetrb);
      Buff->Lr = Buff->Bp;
      Buff->Pa = Disp;
    }
  }
  void Startimmed(int Max) {
    if (!Buff->Dump) return;
    if (Buff->Bs) Error(_imp_str_literal("buffer in use"), 0);
    if (Max > 128) Error(_imp_str_literal("immediate size error"), Max);
    Need(Max + 1);
    if (Buff->Be == Buff->Bp && Max + (Buff->Bp - Buff->Lbs) <= 128)
      Buff->Bs = Buff->Lbs;
    else {
      Add(0);
      Buff->Bs = Buff->Bp;
    }
    Buff->Bb = Buff->Bp;
  }
  void Endimmed(void) {
    int Size;
    if (!Buff->Dump) return;
    if (!Buff->Bs) Error(_imp_str_literal("buffer not in use"), 0);
    Size = Buff->Bp - Buff->Bs;
    if (Size) {
      if (Size > 128) Error(_imp_str_literal("buffer overflow"), Size);
      Buff->B = -Size;
      Buff->Lbs = Buff->Bs;
      Buff->Be = Buff->Bp;
    } else
      Buff->Bp = Buff->Bp - 1;
    Buff->Pa = Buff->Pa + Buff->Bp - Buff->Bb;
    if (Buff->Pa > Buff->Max) Error(_imp_str_literal("Psect immediate overflow"), 0);
    Buff->Bs = 0;
  }
  void Spec(int Flags, int Data, int Value, int Mask) {
    int Def;
    int Len;
    int Psect;
    Psect = abs(Data);
    if (Data < 0) Data = 0;
    Def = Flags & 2;
    Len = (1 + 1) + (Data + *Length(Text));
    if (Def) Len += 7;
    Setwork(Objgsd);
    if (!Def)
      Add(Gsdsym);
    else
      Add(Gsdepm);
    Add(0);
    Addw(Flags);
    if (Def) {
      Add(Psect);
      Addl(Value);
      Addw(Mask);
    }
    Addtext(Data);
  }
  void Inputdirectives(void) {
    static int D_sw;
    static void *D[10 /*1:10*/] = {
        &&D_1, &&D_2, &&D_3, &&D_4, &&D_5, &&D_6, &&D_7, &&D_8, &&D_9, &&D_10,
    };
    short First = 0;
    short List = 0;
    short *Reflist = &First;
    short *End;
    Procfm *Proc;
    Reffm *R;
    Deffm *T;
    int *Q;
    int Prochead;
    int N;
    int Frame;
    int Ldiag;
    int Ecode;
    int Unasscode;
    int Size;
    int Rp;
    int Tag;
    int Blocktag;
    int Dcode;
    static int Dap = 0;
    static int Lap = 2;
    Procs++;
    Proc = &Proctab[Procs];
    Proc->Diagep = 0;
    Proc->Lineep = 0;
    for (;;) {
      Get(Dcode);
      if (1 <= Dcode && Dcode <= Lastdircode) goto *D[D_sw = (Dcode)-1];
      Error(_imp_str_literal("spurious directive"), Dcode);
    D_1:;
      Extused[Getword()] = Nonzero;
      continue;
    D_2:;
      Tag = Getword();
      if (0 >= Tag || Tag > Maxtag) Error(_imp_str_literal("too many labels"), Tag);
      T = &Def[Tag];
      T->*Ca = Getlong();
      if (!List) End = &T->Link;
      T->Link = List;
      List = Tag;
      continue;
    D_3:;
    D_4:;
    D_5:;
      Tag = Getword();
      if (0 >= Tag || Tag > Maxtag) Error(_imp_str_literal("too many labels"), N);
      if (Refs == Maxref) Error(_imp_str_literal("too many references"), Refs);
      Refs++;
      R = &Ref[Refs];
      R->Tag = Tag;
      R->*Ca = Getlong();
      R->Flag = Dcode - 3;
      *Reflist = Refs;
      Reflist = &R->Link;
      continue;
    D_10:;
      Entrytag = Getword();
      continue;
    D_9:;
      Inputdirectives();
    }
  D_6:;
    Proc->Type = Getlong();
    Proc->Mask = Getword() & 0xCFFC;
    Frame = -Getlong();
    Proc->Frame = Frame;
    Ldiag = Getword();
    Proc->Diag = Ldiag;
    if (Ldiag == 0 && Diags != 0) Error(_imp_str_literal("corrupt diags"), Diags);
    Proc->Diagep = Dap;
    Dap += Ldiag;
    Proc->Lineep = Lap;
    Lap += Getword();
    Blocktag = Getword();
    Ecode = 2;
    if (Blocktag == Entrytag && Init != 0) {
      Ecode += 7;
    }
    if (Proc->Type) {
      Ecode += 7;
    }
    Ecode += 3;
    if (Frame) {
      Unasscode = 8;
      if (Frame <= 63) {
        Ecode += 3;
        Unasscode = 6;
      } else if (Frame <= 0x7FFF) {
        Ecode += 5;
      } else {
        Ecode += 7;
      }
      if (Checkass) {
        Ecode += Unasscode;
        Proc->Mask = Proc->Mask | 0x003C;
      }
    }
    T = &Def[Blocktag];
    T->*Ca = T->* Ca - Ecode;
    Base += Ecode;
  D_8:;
    Tag = List;
    while (Tag) {
      T = &Def[Tag];
      T->*Ca = T->* Ca + Base;
      Tag = T->Link;
    }
    if (List) {
      *End = Deflist;
      Deflist = List;
    }
    *Reflist = 0;
    Rp = First;
    while (Rp) {
      R = &Ref[Rp];
      R->*Ca = R->* Ca + Base;
      Rp = R->Link;
    }
    Size = Getlong();
    Base += Size;
    if (First) {
      *Refchain = First;
      Refchain = Reflist;
      *Refchain = 0;
    }
    return;
  D_7:;
    Glapsize = Getlong();
    Lasttag = Getword();
    Specs = Getword();
    Diagsize = Getword();
    Events = Getword();
    Proctab[1].Diagep = Dap;
    Linesize = Lap;
  }
  void Stretchjumps(void) {
    int Extra;
    int Here;
    int There;
    int Disp;
    int Mod;
    int Tag;
    int *Pt;
    short *Last;
    short *Next;
    Reffm *R;
    Deffm *T;
    do {
      Extra = 0;
      Last = &Refhead;
      while (*Last) {
        R = &Ref[*Last];
        Next = &R->Link;
        R->*Ca = R->* Ca + Extra;
        Here = R->* Ca + 2;
        There = Def[R->Tag].* Ca;
        Disp = There - Here;
        Mod = 0;
        if ((R->Flag & Middling) == 0 && -128 > Disp || Disp > 127) {
          R->Flag = R->Flag | Middling;
          Mod = 1;
          if (R->Flag & 1) Mod = 3;
        } else if (0xFFFF8001 > Disp || Disp > 0x8000) {
          *Last = *Next;
          Next = Last;
          Mod = 2;
          if (R->Flag & 3) Mod = 3;
        }
        if (Mod) {
          Tag = Deflist;
          while (Tag) {
            T = &Def[Tag];
            Pt = &T->* Ca;
            if (*Pt < Here) break;
            *Pt = *Pt + Mod;
            Tag = T->Link;
          }
          Extra += Mod;
        }
        Last = Next;
      }
      Base += Extra;
    } while (Extra);
    Eventbase = (Base + 7) & (~7);
    Evp = Eventbase;
    Codesize = Eventbase + Events * 16 + 4;
  }
  void Dumpcode(int Base, int Btag, int Limit) {
    static int C_sw;
    static void *C[25 /*1:25*/] = {
        &&C_default, &&C_2,  &&C_3,  &&C_4,  &&C_5,  &&C_6,  &&C_7,  &&C_8,  &&C_9,  &&C_10, &&C_11, &&C_12, &&C_13,
        &&C_14,      &&C_15, &&C_16, &&C_17, &&C_18, &&C_19, &&C_20, &&C_21, &&C_22, &&C_23, &&C_24, &&C_25,
    };
    static unsigned char Basemod[11 /*5:15*/];
    static const unsigned char Codetype[25 /*1:25*/] = {0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
                                                        0, 3, 0, 2, 2, 0, 0, 0, 1, 0, 0, 0};
    static Psectfm Bufffor[4 /*0:3*/];
    static int Called = 0;
    int Disp;
    int Cond;
    int Ldiag;
    int Value;
    int Ocode;
    int Type;
    int Gb;
    int Gx;
    int Cx;
    int Xno;
    int Pno;
    int Oldca;
    int Oldla;
    int Oldda;
    int Count;
    int Size;
    int N;
    int Save;
    int Reg;
    int Specifier;
    int Mode;
    int Evlow;
    int Evep;
    int Evword;
    int Tag;
    int Lim;
    int Nbase;
    Procfm *Proc;
    void Dumpline(void) {
      Buff = &Linep;
      Startimmed(6);
      Addl(*Ca);
      Addw(Thisline);
      Endimmed();
    }
    void Loadblock(void) {
      int N;
      Get(N);
      Startimmed(N);
      Getblock(N, Buff->B);
      Buff->Bp = Buff->Bp + N;
      Endimmed();
    }
    void Setprimtext(int Pno) {
      Text = _imp_str_literal("$_");
      while (Pno > 26) {
        Text = _imp_join(Text, _imp_str_literal("_"));
        Pno -= 26;
      }
      Text = _imp_join(Text, Tostring('A' - 1 + Pno));
    }
    void Plugglap(Psectfm * With, int Withdisp, int Where, int Inst) {
      int Oldga = *Ga;
      if (0 >= Where || Where >= Glapsize) Error(_imp_str_literal("faulty glap relocation"), Where);
      Buff = &Glapp;
      Select(Where);
      Need(7);
      Stpb(*With, Withdisp);
      Add(Inst);
      Select(Oldga);
    }
    void Bsel(int *Old, Psectfm *P, int New) {
      Buff = P;
      *Old = P.Pa;
      Select(New);
    }
    void Initialisebuffers(void) {
      Bufffor[0] = &Codep;
      Bufffor[1] = &Glapp;
      Bufffor[2] = &Diagp;
      Bufffor[3] = &Linep;
      Called = Nonzero;
    }
    void Handleblockentry(void) {
      int Mask;
      int Unsaved;
      int Reg;
      int Frame;
      if (Base == 12) Base = 13;
      if (Ldump) Dumpline();
      Buff = &Codep;
      Mask = Proc->Mask;
      Unsaved = 0;
      for (Reg = 2; Reg <= 11; Reg++)
        if (!(Mask & (1 << Reg))) Unsaved++;
      Basemod[Base] = Unsaved * 4;
      Frame = Proc->Frame;
      Startimmed(50);
      Addw(Mask);
      if (Proc->Type) {
        Getstring(Text);
        if (Entrytag == Btag && Init != 0) {
          Add(Calls);
          Add(0);
          Endimmed();
          Stag(Initproc);
          Add(Tirstopicr);
          *Ca = *Ca + 5;
          Startimmed(1);
        }
        Add(Moval);
        Endimmed();
        Need(1 + 1 + *Length(Text) + 1 + 1);
        Stag(_imp_join(Text, _imp_str_literal("_")));
        Add(Tirstopicr);
        *Ca = *Ca + 5;
        Startimmed(50);
        Add(0x5B);
      }
      Add(Movl);
      Add(0x5D);
      Add(0x50 + Base);
      if (Frame) {
        if (Frame <= 63) {
          Add(Subl2);
          Add(Frame);
        } else if (Frame <= 0x7FFF) {
          Add(Movab);
          Add(0xCE);
          Addw(-Frame);
        } else {
          Add(Subl2);
          Add(0x8F);
          Addl(Frame);
        }
        Add(0x5E);
        if (Checkass) {
          Add(Movc5);
          Add(0);
          Add(0x6D);
          Add(0x6B);
          if (Frame <= 63)
            Add(Frame);
          else {
            Add(0x8F);
            Addw(Frame & 0x7FFF);
          }
          Add(0x6E);
        }
      }
      Endimmed();
    }
    if (!Called) Initialisebuffers();
    Procs++;
    Proc = &Proctab[Procs];
    Bsel(Oldda, Diagp, Proc->Diagep);
    Bsel(Oldla, Linep, Proc->Lineep);
    Bsel(Oldca, Codep, Def[Btag].* Ca);
    if (Base) Handleblockentry();
    for (;;) {
      Get(Ocode);
      Buff = &Bufffor[Codetype[Ocode]];
      if (0 < Ocode && Ocode <= 25) goto *C[C_sw = (Ocode)-1];
    C_default:
      Error(_imp_str_literal("spurious object"), Ocode);
    C_17:;
      N = Getword();
      Getstring(Text);
      Ldiag = Proc->Diag;
      if (!Ldiag) Error(_imp_str_literal("corrupt diags"), 0);
      Startimmed(50);
      Addw(Ldiag);
      Addw(N);
      Addl(Limit);
      Addtext(0);
      Endimmed();
      continue;
    C_18:;
      Startimmed(50);
      Addw(Getword());
      Addl(Getlong());
      Getstring(Text);
      Addtext(0);
      Endimmed();
      continue;
    C_2:;
      Loadblock();
      continue;
    C_23:;
      Get(Ocode);
      if (Ocode != 2) Error(_imp_str_literal("faulty mod"), Ocode);
      Get(N);
      Startimmed(N);
      Get(Specifier);
      N--;
      Reg = Specifier & 15;
      Add(Specifier);
      if (N == 1)
        Get(Disp);
      else if (N == 2)
        Disp = Getword();
      else if (N == 4)
        Disp = Getlong();
      else
        Error(_imp_str_literal("faulty disp in mod"), N);
      Disp -= Basemod[Reg];
      Add(Disp);
      if (N > 1) Add((unsigned)Disp >> 8);
      if (N == 4) Addw((unsigned)Disp >> 16);
      Endimmed();
      continue;
    C_3:;
      Gb = Getlong();
      if (Gb != *Ga) Error(_imp_str_literal("gla pos error"), Gb - *Ga);
      Loadblock();
      continue;
    C_22:;
      Gb = Getlong();
      if (Gb != *Ga) Error(_imp_str_literal("glam pos error"), Gb - *Ga);
      Value = Getlong();
      Count = Getlong();
      Size = Getlong();
      if (Count * Size > 15) {
        Stak(Value);
        Stak(Count);
        Need(1);
        if (Size == 1)
          Add(Tirstorb);
        else if (Size == 2)
          Add(Tirstorw);
        else if (Size == 4)
          Add(Tirstorl);
        else
          Error(_imp_str_literal("Faulty glam size"), Size);
        *Ga = *Ga + Count * Size;
      } else {
        Startimmed(Count * Size);
        for (N = 1; N <= Count; N++)
          if (Size == 1)
            Add(Value);
          else if (Size == 2)
            Addw(Value);
          else if (Size == 4)
            Addl(Value);
          else
            Error(_imp_str_literal("Faulty glam size"), Size);
        Endimmed();
      }
      continue;
    C_4:;
      Tag = Getlong();
      Getstring(Text);
      Spec(0b1010, 0, Def[Tag].* Ca, Proc->Mask);
      Spec(0b1010, 1, 0, 0);
      continue;
    C_5:;
      Xno = Getword();
      Getstring(Text);
      if (Extused[Xno]) {
        Spec(0b1000, 0, 0, 0);
        Exttext[Xno] = Text;
      }
      continue;
    C_6:;
      Gx = Getlong();
      Getstring(Text);
      Spec(0b1010, -1, Gx, 0);
      continue;
    C_19:;
    C_7:;
      Xno = Getword();
      Getstring(Text);
      Exttext[Xno] = Text;
      Mode = 0b1000;
      if (Ocode == Objweak) Mode = 0b1001;
      Spec(Mode, 0, 0, 0);
      continue;
    C_25:;
      Xno = Getword();
      Disp = Getlong();
      Get(Reg);
      Stag(Exttext[Xno]);
      if (Disp) {
        Stak(Disp);
        Need(1);
        Add(Tiradd);
      }
      Need(1);
      Add(Tirstopicr);
      *Ca = *Ca + 5;
      if (Reg & 16) {
        Need(16);
        Add(Tiraugrb);
        Addl(-5);
        Add(Tirstaub);
        Add(0xFF);
        Add(Tirstoub);
        Add(Tiraugrb);
        Addl(4);
      }
      continue;
    C_8:;
      Gb = Getlong();
      Gx = Getlong();
      Plugglap(Glapp, Gx, Gb, Tirstopidr);
      continue;
    C_9:;
      Cx = Def[Getlong()].* Ca;
      Gb = Getlong();
      Plugglap(Codep, Cx + 4, Gb, Tirstold);
      continue;
    C_10:;
      Get(Nbase);
      Tag = Getword();
      Lim = Getword();
      Thisline = Getword();
      Dumpcode(Nbase, Tag, Def[Lim].* Ca);
      continue;
    C_11:;
      Tag = Getlong();
      Disp = Def[Tag].* Ca - *Ca - 2;
      Startimmed(5);
      N = Range(Disp, 1);
      if (N == 1) {
        Add(0xAF);
        Add(Disp);
      } else if (N == 2) {
        Add(0xCF);
        Addw(Disp - 1);
      } else {
        Add(0xEF);
        Addl(Disp - 3);
      }
      Endimmed();
      continue;
    C_12:;
      Get(Cond);
      Tag = Getword();
      Cond = Cond & 15;
      Disp = Def[Tag].* Ca - *Ca - 2;
      Size = Range(Disp, 1);
      Startimmed(8);
      if (!Cond)
        if (Size == 1) {
          Add(Brb);
          Add(Disp);
        } else if (Size == 2) {
          Add(Brw);
          Addw(Disp - 1);
        } else {
          Add(Jmp);
          Add(0xEF);
          Addl(Disp - 4);
        }
      else if (Size == 1) {
        Add(Branch[Cond]);
        Add(Disp);
      } else if (Size == 2) {
        Add(Branch[Cond ^ 7]);
        Add(3);
        Add(Brw);
        Addw(Disp - 3);
      } else {
        Add(Branch[Cond ^ 7]);
        Add(6);
        Add(Jmp);
        Add(0xEF);
        Addl(Disp - 6);
      }
      Endimmed();
      continue;
    C_20:;
    C_21:;
      Disp = Def[Getword()].* Ca - *Ca - 1;
      Startimmed(2);
      if (Ocode == Objwlab)
        Addw(Disp - 1);
      else {
        if (-128 > Disp || Disp > 127) Error(_imp_str_literal("branch overflow"), Disp);
        Add(Disp);
      }
      Endimmed();
      continue;
    C_13:;
      Get(Pno);
      Setprimtext(Pno);
      Spec(0b1000, 0, 0, 0);
      continue;
    C_24:;
      Get(Pno);
      Setprimtext(Pno);
      if (Pno != Procenterprim) {
        Startimmed(1);
        Add(Jsb);
        Endimmed();
      }
      Stag(Text);
      Need(1);
      Add(Tirstopicr);
      *Ca = *Ca + 5;
      continue;
    C_15:;
      Thisline = Getword();
      if (Ldump) Dumpline();
    }
  C_16:;
    if (Diagp.Pa) {
      Buff = &Diagp;
      Startimmed(1);
      Add(0);
      Endimmed();
    }
    Evword = Getword();
    if (Evword) {
      Evlow = Getword();
      Evep = Getword();
      Buff = &Codep;
      Save = *Ca;
      Select(Evp);
      Startimmed(16);
      Addl(Evword);
      Addl(Def[Evlow].* Ca);
      Addl(Save);
      Addl(Def[Evep].* Ca);
      Endimmed();
      Evp += 16;
    }
  C_14:;
    Bsel(N, Diagp, Oldda);
    Bsel(N, Linep, Oldla);
    Bsel(N, Codep, Oldca);
  }
  void Dumpallcode(void) {
    Selectinputtank(Object);
    Procs = 0;
    Dumpcode(0, 0, 0);
  }
  void Definepsect(Psectfm * Ps, int Align, int Flags, int Size, _imp_string Name) {
    static int Psectno = 0;
    Setwork(Objgsd);
    Add(Gsdpsc);
    Add(Align);
    Addw(Flags);
    Addl(Size);
    Addstring(0, Name);
    *Ps = 0;
    Ps.Dump = 1;
    Ps.Type = Objtir;
    Ps.Bp = 1;
    Ps.Max = Size;
    Ps.Index = Psectno;
    Psectno++;
    Flushbuff();
    Buff = Ps;
    Ps.Pa = -999;
    Select(0);
  }
  void Dumpmoduleheader(void) {
    _imp_string Temp;
    Selectoutput(Objectfile);
    Setwork(Objhdr);
    Add(Hdrmhd);
    Add(0);
    Addw(Maxrec);
    Addstring(0, Module);
    Addstring(0, _imp_str_literal("V01.00"));
    Temp = _imp_join(Date(), _imp_join(_imp_str_literal(" "), Time()));
    *Length(Temp) = *Length(Temp) - 3;
    Addstring(1, Temp);
    Addstring(1, _imp_str_literal("IMP is wonderful!"));
    Setwork(Objhdr);
    Add(Hdrlng);
    Addstring(1, _imp_join(_imp_str_literal("VAX-11 Imp77 "), Version));
  }
  void Definepsects(void) {
    Definepsect(Codep, Quad, Codeflags, Codesize, Codename);
    Definepsect(Glapp, Quad, Glapflags, Glapsize, Glapname);
    if (Diags) {
      Definepsect(Diagp, Quad, Diagflags, Diagsize + 2, Diagname);
    } else
      Diagp.Dump = 0;
    if (Ldump) {
      Definepsect(Linep, Quad, Lineflags, Linesize, Linename);
      Buff = &Linep;
      Select(0);
      Startimmed(2);
      Addw(Linesize);
      Endimmed();
    } else
      Linep.Dump = 0;
  }
  void Initialise(void) {
    int J;
    for (J = 1; J <= Maxexternals; J++) Extused[J] = 0;
    Selectinputtank(Directives);
    Refs = 0;
    Procs = 0;
    Def[0] = 0;
    Ca = &Codep.Pa;
    Ga = &Glapp.Pa;
  }
  void Specinitproc(void) {
    if (Entrytag < 0 || Init == 0) return;
    Setwork(Objgsd);
    Add(Gsdsym);
    Add(0);
    Addw(0b1000);
    Addstring(0, Initproc);
    Flushbuff();
  }
  void Plugpsects(void) {
    Buff = &Glapp;
    Select(12);
    Need(50);
    Stpb(Codep, 4);
    Add(Tirstold);
    *Ga = *Ga + 4;
    if (Diags)
      Stpb(Diagp, 4);
    else
      Stak(4);
    Add(Tirstold);
    *Ga = *Ga + 4;
    if (Ldump)
      Stpb(Linep, 4);
    else
      Stak(4);
    Add(Tirstold);
    *Ga = *Ga + 4;
    Startimmed(10);
    Addw(0);
    Addl(Proctab[1].Diagep);
    Addl(Eventbase);
    Endimmed();
    Buff = &Codep;
    Select(Evp);
    Stak(0);
    Add(Tirstol);
    if (Diags) {
      Buff = &Diagp;
      Select(Diagsize);
      Startimmed(2);
      Addw(0);
      Endimmed();
    }
  }
  void Dumpeom(void) {
    Setwork(Objeom);
    Add(0);
    if (Entrytag >= 0) {
      Add(0);
      Addl(Def[Entrytag].* Ca);
    }
    Flushbuff();
  }
  void Flushbuffers(void) {
    Buff = &Codep;
    Flushbuff();
    Buff = &Glapp;
    Flushbuff();
    Buff = &Diagp;
    Flushbuff();
    Buff = &Linep;
    Flushbuff();
    Buff = &Workp;
    Flushbuff();
  }
  void Reportinfo(void) {
    int Stream;
    for (Stream = Report; Stream <= Listing; Stream += Listing - Report) {
      if (Clog == 0 && Stream == Report) continue;
      Selectoutput(Stream);
      Printstring(_imp_str_literal("Code"));
      Write(Codep.Max - 4, 1);
      Printstring(_imp_str_literal(" bytes  Glap"));
      Write(Glapp.Max, 1);
      Printstring(_imp_str_literal(" bytes  Diags"));
      Write(Diagp.Max + Linep.Max, 1);
      Printstring(_imp_str_literal(" bytes   Total size"));
      Write(Codep.Max - 4 + Glapp.Max + Diagp.Max + Linep.Max, 1);
      Printstring(_imp_str_literal(" bytes"));
      Newline();
    }
  }
  void Time(void R(void), _imp_string Name) {
    int Pagefaults(void);
    int T;
    int P;
    static int Called = 0;
    P = Pagefaults();
    T = Cputime();
    R;
    T -= Cputime();
    P -= Pagefaults();
    if (!Timing) return;
    Selectoutput(Report);
    if (!Called) {
      Printstring(_imp_str_literal("Pass 3 breakdown:"));
      Newline();
    }
    Called = 1;
    Spaces(3);
    Printstring(Name);
    Printsymbol(':');
    Spaces(15 - *Length(Name));
    Space();
    if (T >= 20) {
      Write(T, -5);
      Printstring(_imp_str_literal("ms,    "));
    } else
      Printstring(_imp_str_literal("negligible, "));
    Write(P, -3);
    Printstring(_imp_str_literal(" page fault"));
    if (P != 1) Printsymbol('s');
    Newline();
    Selectoutput(Objectfile);
  }
  Initialise();
  Time(Inputdirectives(), _imp_str_literal("Directive input"));
  Time(Stretchjumps(), _imp_str_literal("Jump stretching"));
  Dumpmoduleheader();
  Definepsects();
  Specinitproc();
  Time(Dumpallcode(), _imp_str_literal("Code dumping"));
  Plugpsects();
  Flushbuffers();
  Dumpeom();
  Reportinfo();
}
int _imp_mainep(int _imp_argc, char **_imp_argv) {
  exit(0);
  return (1);
}
