#include "perms.h" #include <ctype.h> #include <errno.h> // This is Hamish Dewar's syntax checker for the subset of Imp80 and Imp77 agreed upon // by the ERCC and the Department of Computer Science. // Note the small differences between chimps.imp77 and chimps.imp80 - the latter allows // the X'nnnn' style of constants, whereas this and chimps.imp77 do not. // Unfortunately the current Imp to C converter loses comments. That will be fixed // eventually, the underlying parser does preserve them. I've added them manually // for now, but not the many comments which comprised of commented-out Imp code... // This translation is now almost all automatic. The small manual tweaks needed were // for arrays with non-0 lower bounds, and treating %name parameters to procedures // properly. See the chimps77.c.PENDING-DIFF file for all changes. // Obviously a main() harness had to be added as we are not calling this from Vecce or EMAS. // I'm not entirely sure I know what the params should be. This is just a guess. // -GT // IMP syntax checker - based on M68000 IMP compiler // (qv for fuller annotation) // Hamish Dewar Computer Science Edinburgh University 1983 // const int Maxname = 127; typedef struct Edfile { int Start1; int Lim1; int Start2; int Lim2; int Lim; int Lbeg; int Fp; int Change; int Flag; int Line; int Diff; int Shift; unsigned char Top; unsigned char Win; unsigned char Bot; unsigned char Min; unsigned char Row; unsigned char Col; _imp_string Name; } Edfile; #ifdef EDITOR_SUPPORT void Edi(Edfile *Main, Edfile *Sec, _imp_string Message); // <---- TO DO! #endif void Connectedfile(Edfile *F); // <---- void Disconnectedfile(Edfile *F); /* (unused) */ const _imp_string Permfile = _imp_str_literal("ECCE_PERM"); const int Logbit = 0x00040000; // print log const int Warnbit = 0x00020000; // print warnings const int Nonsbit = 0x00010000; // print nonstandard reports const int Dictlist = 0x00001000; // list dict entries const int Explist = 0x00000800; // list EXP entries static int Control;// = Warnbit + Nonsbit; // Had to move initialisation of statics to entry point. C doesn't consider a "const int" to be a constant. ///////////////////////////////////////////////// void Ecceci(Edfile *Main) { ///////////////////////////////////////////////// static _imp_string Extraname; static Edfile Extra = {0}; static Edfile Null = {0}; int Curstart; int Curlim; int Nonstop; static int Change = 0; // Fault numbers const int Formerr = 0; const int Atomerr = 1; const int Namerr = 2; const int Caterr = 3; const int Sizerr = 4; const int Asserr = 5; const int Typerr = 6; const int Duperr = 7; const int Nostart = 8; const int Nocycle = 9; const int Ordererr = 10; const int Matcherr = 11; const int Rangerr = 12; const int Nonliteral = 13; const int Boundserr = 14; const int Accesserr = 15; const int Notinloop = 16; const int Notinrout = 17; const int Notinfun = 18; const int Notinpred = 19; const int Plexerr = 20; const int Noif = 21; const int Nonstand = 22; const int Notin = 23; const int Indexerr = 24; const int Moperr = 27; const int Noterm = 28; const int Nonstarter = 29; const int Nonvar = 30; const int Nonref = 31; const int Toomany = 32; const int Toofew = 33; const int Unwanted = 34; const int Noparm = 35; const int Unending = 37; const int Selfref = 38; const int Noend = 40; const int Nobegin = 41; const int Idmissing = 42; const int Nofinish = 43; const int Norepeat = 44; const int Counterr = 45; const int Noresult = 46; const int Errmax = 46; const int Point = 64; const int Warn = 128; static int Faultnum = 0; static int Faults = 0; //fault count const int Maxint = 0x7FFFFFFF; const int Minint = ~Maxint; const int Max10 = Maxint / 10; const int Maxdig = Maxint - Max10 * 10; const int False = 0; const int True = 1; int I; static int Statements = 0; // // Program statistics //!!!!!!!!!!!!!!!! Operand Representation !!!!!!!!!!!!!!!!!!! const int Smallmin = -1000; const int Smallmax = 1000; const int Litmin = Smallmax + 1; const int Litmax = Smallmax + 1000; const int D0 = Litmax + 1; const int D1 = D0 + 1; const int D2 = D0 + 2; const int D6 = D0 + 6; const int D7 = D0 + 7; const int A0 = D0 + 8; const int A1 = A0 + 1; const int A6 = A0 + 6; const int A7 = A0 + 7; const int Inda0 = A0 + 8; const int Posta0 = Inda0 + 8; const int Posta7 = Posta0 + 7; const int Prea0 = Posta0 + 8; const int Prea7 = Prea0 + 7; const int Dictmin = Prea0 + 8; const int Dictmax = Prea0 + 1200; const int Labmin = Dictmax + 1; const int Lab1 = Labmin + 1; const int Labmax = Labmin + 20; const int Expmin = Labmax + 1; const int Expmax = Labmax + 300; const int Undef = Expmax + 1; const int Ad = 0x4000; const int Maxdreg = D0 + 4; const int Maxareg = A0 + 3; const int D0b = 1; const int D1b = 2; const int D2b = 4; const int A0b = 0x100; const int A1b = 0x200; const int A2b = 0x400; const int Allregs = 0b0000111100011111; //a3:a0 & d4:d0 static int Free;// = Allregs; const int Nulltype = Dictmin; const int Recy = Nulltype + 1; const int Arry = Recy + 1; const int Stringy = Arry + 1; const int Realy = Stringy + 1; const int Inty = Realy + 1; const int Chartype = Inty + 1; const int Booltype = Chartype + 1; const int Falseconst = Booltype + 1; const int Trueconst = Booltype + 2; const int Inttype = Trueconst + 1; const int Shorttype = Inttype + 1; const int Halftype = Shorttype + 1; const int Bytetype = Halftype + 1; const int Mitetype = Bytetype + 1; const int Bittype = Mitetype + 1; const int Longinttype = Bittype + 1; const int Realtype = Longinttype + 1; const int Longrealtype = Realtype + 1; const int Puretype = 8191; const int Direct = 8192; const int Indirect = 16384; const int Anyint = Inty + Direct; const int Anyintvar = Inty + Indirect; const int Anystring = Stringy + Direct; const int Anystringvar = Stringy + Indirect; const int Anyname = Nulltype + Indirect; static int Dictshown;// = Dictmin; //!!!!!!!!!!!!!!!!!!!!!!! Big Literals !!!!!!!!!!!!!!!!!!!!!!! static int Litpos;// = Litmin; static int Slitpos;// = Litmax; int Litstore[1001+ 1000 /*1001:2000*/]; // //!!!!!!!!!!!!!!!!!!!!!!!!!! MODE VALUES !!!!!!!!!!!!!!!!!!!!!!!!! //Size codes: const int Bytesize = 1; const int Wordsize = 2; const int Longsize = 3; const int Sizemask = 0xC0; const int Sizeshift = 6; //Address modes: const int Dmode = 0; const int Amode = 0b001000; const int Indmode = 0b010000; const int Postmode = 0b011000; const int Premode = 0b100000; const int Dispmode = 0b101000; const int Indexmode = 0b110000; const int Absmode = 0b111000; const int Pcmode = 0b111010; const int Litmode = 0b111100; const int Ownmode = Dispmode + 6; // I may not have got these variants correct, however I don't // think they are ever used to convert data from one form to // another - rather they're used to save space, which we don't // care about for now. /* %recordformat OBJINFO %C (%integer flags,type, (%integer extra, %byteinteger spare,mode %or %integer low), %integer val) */ // //!!!!!!!!!!!!!!!!!!!!!!!! Identifiers !!!!!!!!!!!!!!!!!!!!!!!! // typedef struct Objinfo { int Flags; int Type; union { int Extra; int Low; }; unsigned char Spare, Mode; int Val; } Objinfo; /* %recordformat IDENTINFO %C ((%integer flags,type, (%integer extra, %byteinteger spare,mode %or %integer low), %integer val %or %record(objinfo) details), %integer text,link) */ typedef struct Identinfo { union { struct { int Flags; int Type; union { int Extra; int Low; }; unsigned char Spare, Mode; int Val; }; Objinfo Details; }; int Text; int Link; } Identinfo; // // Significance of FLAGS: const int Var = 0x0001; const int Lab = 0x0002; const int Proc = 0x0004; const int Static = 0x0008; const int Spec = 0x0010; const int Ext = 0x0020; const int Parm = 0x0040; const int More = 0x0080; const int Typeid = 0x0100; const int Okflag = 0x0200; const int Alt = 0x0800; const int Rflag = 0x1000; const int Wflag = 0x2000; // // Significance of VAL: // for literal : the actual value // for variable : machine address (displacement) // for undefined label : reference chain // for undefined procedure : " // for base type : (index to) range // for record type : size of record in bytes // // Identifier dictionary: Identinfo Dict[2001+ 1254 /*2001:3254*/]; // indexing DICT: static int Dlim;// = Trueconst + 1; //dict limit (up) static int Dlim0; static int Permlim;// = Dictmin; static int Dmin;// = Dictmax - 1; //dict upper limit (down) // Text of identifiers (indexed by _TEXT): const int Charbound = 6000; unsigned char Char[6001 /*0:6000*/]; int Charbase; int Charlim; int Charmin; //pointers int Newlen; // Hash index to DICT: int Hashindex[256 /*0:255*/]; int *Head; //head of ident search list // //!!!!!!!!!!!!!!!!!!!! Complex operands !!!!!!!!!!!!!!!!!!!!!!! static int Explo;// = Expmax + 1; static int Oldexplo;// = Expmax + 1; const int Np0;// = Expmin; static int Np; static int Condnp; static int Instnp; //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //!!!!!!!!!!!!!!!!!! Keywords and operators !!!!!!!!!!!!!!!!!!!! //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //!*!!!!!!! Keyword codes -- used by KEYGEN to produce tables !! const int End = 1; //end const int Repeat = 2; //repeat const int Finish = 3; //finish const int Else = 4; //else const int Begin = 5; //begin const int Exit = 6; //exit_1,continue_0 const int Return = 7; //return const int Tf = 8; //true_1,false_0 const int Result = 9; //result const int Stop = 10; //stop const int Goto = 11; //goto const int Signal = 12; //signal const int Monitor = 13; //monitor const int On = 15; //on const int Iu = 16; //if_0,unless_1 const int While = 17; //while const int Until = 18; //until_1 const int For = 19; //for const int Then = 20; //then const int Start = 21; //start const int Cycle = 22; //cycle const int Keylabel = 23; //label const int Prefix = 24; //const_9,constant_9,own_8,external_40,system_40,dynamic_40 const int Krange = 25; //short_1,half_2,byte_3,mite_4,bit_5 const int Keylong = 26; //long const int Keyinteger = 27; //integer const int Keyreal = 28; //real const int Keystring = 29; //string const int Keyrecord = 30; //record const int Keyformat = 31; //format const int Fnmap = 32; //fn_0,function_0,map_1 const int Rpred = 33; //routine_0,predicate_1 const int Keyspec = 34; //spec const int Keyarray = 35; //array const int Keyname = 36; //name const int Keyswitch = 37; //switch const int Of = 38; //of const int Keyfile = 39; //file const int Program = 40; //program const int Keylist = 41; //list const int Keycontrol = 42; //control const int Comment = 43; //comment const int Keyevent = 44; //event const int Include = 45; //include const int Alias = 46; //alias const int Keynot = 47; //not const int Keyand = 64; //and const int Keyor = 65; //or const int Syminit[97+ 26 /*97:122*/] = { [0 ... 96 ] = 0, 2, 15, 27, 57, 64, 87, 118, 122, 126, 1, 1, 141, 154, 168, 175, 184, 1, 199, 230, 270, 278, 1, 288, 1, 1, 1}; const unsigned char Symbol[1+ 292 /*1:292*/] = { 0, 128, 114, 114, 97, 121, 163, 108, 105, 97, 115, 174, 110, 100, 192, 101, 103, 105, 110, 133, 121, 116, 101, 153, 105, 116, 153, 111, 110, 116, 105, 110, 117, 101, 134, 121, 99, 108, 101, 150, 109, 109, 101, 110, 116, 171, 115, 116, 97, 110, 116, 152, 152, 114, 111, 108, 170, 121, 110, 97, 109, 105, 99, 152, 110, 100, 129, 108, 115, 101, 132, 120, 105, 116, 134, 118, 101, 110, 116, 172, 116, 101, 114, 110, 97, 108, 152, 105, 110, 105, 115, 104, 131, 97, 108, 115, 101, 136, 111, 114, 109, 97, 116, 159, 110, 160, 117, 110, 99, 116, 105, 111, 110, 160, 147, 108, 101, 167, 111, 116, 111, 139, 97, 108, 102, 153, 102, 144, 110, 116, 101, 103, 101, 114, 155, 99, 108, 117, 100, 101, 173, 97, 98, 101, 108, 151, 111, 110, 103, 154, 105, 115, 116, 169, 111, 110, 105, 116, 111, 114, 141, 105, 116, 101, 153, 97, 112, 160, 97, 109, 101, 164, 111, 116, 175, 110, 143, 119, 110, 152, 102, 166, 114, 193, 114, 101, 100, 105, 99, 97, 116, 101, 161, 111, 103, 114, 97, 109, 168, 101, 112, 101, 97, 116, 130, 111, 117, 116, 105, 110, 101, 161, 116, 117, 114, 110, 135, 115, 117, 108, 116, 137, 97, 108, 156, 99, 111, 114, 100, 158, 116, 111, 112, 138, 105, 103, 110, 97, 108, 140, 121, 115, 116, 101, 109, 152, 104, 111, 114, 116, 153, 112, 101, 99, 162, 119, 105, 116, 99, 104, 165, 97, 114, 116, 149, 114, 105, 110, 103, 157, 114, 117, 101, 136, 104, 101, 110, 148, 110, 108, 101, 115, 115, 144, 116, 105, 108, 146, 104, 105, 108, 101, 145}; const unsigned char Altdisp[1+ 292 /*1:292*/] = { 0, 0, 5, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 4, 0, 0, 3, 0, 0, 5, 8, 12, 17, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 3, 0, 0, 4, 0, 0, 0, 4, 8, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 6, 27, 0, 0, 0, 0, 5, 0, 0, 0, 0, 6, 0, 14, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 4, 0, 0, 4, 0, 0, 1, 4, 0, 0, 0, 0, 0, 0, 2, 0, 3, 0, 8, 2, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 6, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 5, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 30, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 40, 5, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 1, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0}; //*!!!!!! end of generated tables !!!!!!!!!!!!!!!!!!!!!!!!!!! // const int Terminator = 52; const int Const = 53; const int Ident = 54; const int Aref = 55; const int Recref = 56; const int Modsign = 57; const int Colon = 58; const int Comma = 59; const int Right = 60; const int Rightbracket = 61; const int Dud = 63; //Operators (in banks of 8 acc to rank) const int Booland = 64; const int Boolor = 65; const int Boolnot = 66; const int Float = 67; const int Imod = 68; const int Fmod = 69; const int Equals = 70; const int Noteq = 71; const int Lesseq = 72; const int Less = 73; const int Greateq = 74; const int Greater = 75; const int Eqeq = 76; const int Noteqeq = 77; const int Resolve = 79; const int Plus = 80; const int Minus = 81; const int Logor = 82; const int Logxor = 83; const int Concat = 84; const int Mult = 88; const int Fdiv = 89; const int Idiv = 90; const int Logand = 91; const int Fpower = 96; const int Ipower = 97; const int Lshift = 100; const int Rshift = 101; const int Lognot = 102; const int Fcall = 106; const int Mcall = 107; const int Atommax = 107; // Instruction actions: const int Swgoto = 35; const int Rcall = Mcall + 2; const int Assign = 41; const int Jamassign = 42; const int Plusass = 43; const int Compare = 44; const int Jump = 45; const int Label = 46; const int Adecl = 47; const int Actmax = 49; // //Branch cases ( = machine condition-code) const int Eq = 0b0111; const int Ne = 0b0110; const int Gt = 0b1110; const int Le = 0b1111; const int Lt = 0b1101; const int Ge = 0b1100; const int Cc = 0b0100; const int Cs = 0b0101; const int Double = 16; //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // Perm procedure identifiers which are recognised explicitly and // either implemented in-line or mapped to system entry-point const int Dshort = Dictmin + 6; const int Dlength = Dshort + 1; const int Dcharno = Dlength + 1; const int Daddr = Dcharno + 1; const int Dtostr = Daddr + 1; const int Drem = Dtostr + 1; const int Dnextsym = Drem + 1; const int Dreadsym = Dnextsym + 1; const int Dprintstr = Dreadsym + 3; const int Dread = Dictmin + 27; const int Dnewline = Dictmin + 41; //System entry-points used explicitly const int Sigentry = 0x1114; const int Scompentry = 0x1128; const int Boundentry = 0x1134; const int Agetentry = 0x1138; const int Indexentry = 0x113C; const int Ireadentry = 0x1118; //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! static int Starts = 0; static int Cycles = 0; static int Looplab = 0; static int Curlab;// = Lab1; // typedef struct Blockinf { int Sp; int Delta; int Fortemps; int Flags; int Type; int Localdpos; int Parlim; int Localtext; int Localpc; int Localspc; int Pidpos; int Access; int Forward; int Events; int Eventpc; int Faults; int Return; int Shorts; } Blockinf; //Flag bits (VAR=1 from D_FLAGS) const int Wrongcc = 2; const int Nonlocalref = 4; const int Dynarray = 8; const int Hadon = 0x10; const int Hadinst = 0x20; const int Outerlevel = 0; const int Maxlevel = 16; static int Level;// = Outerlevel; //current block level Blockinf C; //info for current block Blockinf Hold[16 /*0:15*/]; //info for global blocks // Final core image const int Purebound = 0; const int Ownbase = Purebound + 1; const int Finalbound = Ownbase + 8191; unsigned char Final[8193 /*0:8192*/]; //for switch info only static int Finalad = 2; static int Ownad;// = Ownbase; static int Pc = 0; static int Spc;// = Finalbound; //Recognition:- const int Casemask = 95; const int Casebit = 32; //Memo variables for current statement:- static int Item = 0; //current operand Objinfo T; //full typeinfo for ITEM Identinfo *Ditem; static int Elements; //range details static int Hash; static int Speccing = 0; static int Mcoding = 0; static int Declmode; static int Dsize; static Identinfo D; //declaration details //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // Source file input and listing static int Atom = 0; //current lexical atom static int Matched = 1; //indic that atom has been matched static int Sym = '\n'; //current input symbol static int Line = 0; //current line number static int Mainline = 0; static int Diagline = -9999; static int Proline = 0; static int Modesym = '&'; //space or '+' or '&' or '"' // Pointers to source file: static int Linestart = 0; static int Fp = 0; //(file pointer) current position static int Chars = 0; static int Atomp = 0; //start of current atom static int Faultp = 0; //fault position static int Mainfp; static int Stringp; static int Expp; static int Listout = 0; // // Listing, diagnostic and report routines // static _imp_string Rep = _imp_str_literal(""); // #undef Newline // current prims suffer from a small degree of namespace pollution :-( void Newline(void) { Printstring(Rep); Printsymbol('\n'); #ifdef NEVER Rep = _imp_str_literal(""); #else *Length(Rep) = 0; *Charno(Rep,1) = '\0'; #endif } void Putsym(int K) { // We can do this a lot more efficiently... if (*Length(Rep) < 132) #ifdef NEVER Rep = _imp_join(Rep, Tostring(K)); #else { *Charno(Rep, *Length(Rep)+1) = K&255; *Length(Rep) += 1; *Charno(Rep, *Length(Rep)+1) = '\0'; } #endif } #undef Printstring void Printstring(_imp_string S) { if (*Length(Rep) < 132) Rep = _imp_join(Rep, S); } #undef Spaces void Spaces(int N) { while (N > 0) { // These are all really inefficient :-/ Rep = _imp_join(Rep, _imp_str_literal(" ")); N--; } } #undef Write void Write(int Val, int P) { void Pd(int V) { P--; if (V <= -10) { Pd(V / 10); V -= V / 10 * 10; } if (P > 0) { Spaces(P); P = 0; } Putsym('0' - V); } if (Val < 0) { Putsym('-'); Pd(Val); } else Pd(-Val); } void Report(int N, int Joker) { int Mark; int Start; int Errline; int K; int Editfp; void Printident(int X) { Putsym('"'); Printstring(*String(Dict[X].Text + Charbase)); Putsym('"'); } void Printtext(int X, int Stream) { const int Esc = 27; int K; int P; static int S_sw; static void *S[47 /*0:46*/] = { &&S_0, &&S_1, &&S_2, &&S_3, &&S_4, &&S_5, &&S_6, &&S_7, &&S_8, &&S_9, &&S_10, &&S_11, &&S_12, &&S_13, &&S_14, &&S_15, &&S_16, &&S_17, &&S_18, &&S_19, &&S_20, &&S_21, &&S_22, &&S_23, &&S_24, &&S_default, &&S_default, &&S_27, &&S_28, &&S_29, &&S_30, &&S_31, &&S_32, &&S_33, &&S_34, &&S_35, &&S_default, &&S_37, &&S_38, &&S_default, &&S_40, &&S_41, &&S_42, &&S_43, &&S_44, &&S_45, &&S_46, }; Putsym(Mark); Write(Line, 4); Putsym(Modesym); Putsym(' '); goto *S[S_sw = N & 63]; S_0: /*formerr*/ Printstring(_imp_str_literal("Faulty form")); goto Print; S_1: /*atomerr*/ Printstring(_imp_str_literal("Unknown atom")); goto Print; S_2: /*namerr*/ Printstring(_imp_str_literal("Unknown name")); goto Print; S_3: /*caterr*/ Printstring(_imp_str_literal("Unsuitable")); goto Print; S_4: /*sizerr*/ Printstring(_imp_str_literal("Size")); goto Print; S_6: /*typerr*/ Printstring(_imp_str_literal("Wrong type")); goto Print; S_14: /*boundserr*/ Printstring(_imp_str_literal("Inside out")); goto Print; S_37: /*unending*/ Printstring(_imp_str_literal("Endless loop")); goto Print; S_24: /*indexerr*/ Printstring(_imp_str_literal("Index")); goto Print; S_15: /*accesserr*/ Printstring(_imp_str_literal("Not accessible")); goto Print; S_16: /*notinloop*/ Printstring(_imp_str_literal("Not in loop")); goto Print; S_17: /*notinrout*/ Printstring(_imp_str_literal("Not in routine")); goto Print; S_18: /*notinfun*/ Printstring(_imp_str_literal("Not in fn/map")); goto Print; S_19: /*notinpred*/ Printstring(_imp_str_literal("Not in pred")); goto Print; S_20: /*plexerr*/ Printstring(_imp_str_literal("Too complex!")); goto Print; S_7: /*duperr*/ Printstring(_imp_str_literal("Duplicate")); goto Print; S_10: /*ordererr*/ Printstring(_imp_str_literal("Out of order")); goto Print; S_11: /*matcherr*/ Printstring(_imp_str_literal("Mismatch")); goto Print; S_12: /*rangerr*/ Printstring(_imp_str_literal("Out of range")); goto Print; S_13: /*nonliteral*/ Printstring(_imp_str_literal("Not literal")); goto Print; S_22: /*nonstand*/ Printstring(_imp_str_literal("Nonstandard")); goto Print; S_23: /*notin*/ Printstring(_imp_str_literal("Not in yet")); goto Print; S_27: /*moperr*/ Printstring(_imp_str_literal("Faulty operand")); goto Print; S_9: /*nocycle*/ Printstring(_imp_str_literal("Missing %CYCLE")); goto Print; S_8: /*nostart*/ Printstring(_imp_str_literal("Missing %START")); goto Print; S_21: /*noif*/ Printstring(_imp_str_literal("Missing %IF")); goto Print; S_28: /*noterm*/ Printstring(_imp_str_literal("';' missing")); goto Print; S_29: /*nonstarter*/ Printstring(_imp_str_literal("Non-starter")); goto Print; S_30: /*nonvar*/ Printstring(_imp_str_literal("Not variable")); goto Print; S_31: /*nonref*/ Printstring(_imp_str_literal("Not reference")); goto Print; S_35: /*noparm*/ Printstring(_imp_str_literal("No parameters")); goto Print; S_33: /*toofew*/ Printstring(_imp_str_literal("Too few")); goto Print; S_34: /*unwanted*/ Printstring(_imp_str_literal("Unwanted")); goto Print; S_32: /*toomany*/ Printstring(_imp_str_literal("Too many")); goto Print; S_38: /*selfref*/ Printstring(_imp_str_literal("Self-reference")); goto Print; S_41: /*nobegin*/ Printstring(_imp_str_literal("Extra %END")); goto Print; Print:; Spaces(21 - *Length(Rep)); P = Start; if (P < Faultp - 50) { P = Faultp - 47; Printstring(_imp_str_literal("...")); } else Putsym(' '); for (;;) { K = *Byteinteger(P); P++; if (P == Faultp) { // Highlighting: //if (!Stream) { // Putsym(Esc); // Putsym('F'); //} Putsym('~'); //if (!Stream) { // Putsym(Esc); // Putsym('G'); //} } if (K == '\n') break; if (' ' <= K && K <= '~') Putsym(K); else { // Non-printable characters: Putsym('['); Write(K, -1); Putsym(']'); } } return; S_40: /*noend*/ Printstring(_imp_str_literal("%END")); goto Mend; S_46: /*noresult*/ Printstring(_imp_str_literal("Result")); goto Mend; S_43: /*nofinish*/ Printstring(_imp_str_literal("%FINISH")); goto Mend0; S_44: /*norepeat*/ Printstring(_imp_str_literal("%REPEAT")); Mend0: if (Curlab > Lab1 + 2) Printstring(_imp_str_literal(" etc")); goto Mend; S_42:; /*idmissing*/ do { Putsym(' '); Printident(X); if (!(Dict[X].Flags & Spec)) Printstring(_imp_str_literal("(?)")); X = Dict[X].Val; } while (X); Mend:; Printstring(_imp_str_literal(" missing")); if (C.Type) { Printstring(_imp_str_literal(" at END of ")); Printident(C.Pidpos); } else N = 0; return; S_45:; /*counterr*/ if (Elements < 0) { Write(-Elements, 0); Printstring(_imp_str_literal(" extra")); } else { Write(Elements, 0); Printstring(_imp_str_literal(" missing")); } Printstring(_imp_str_literal(" value(s) for ")); Printident(X); return; S_5:; /*asserr*/ Printident(X); Printstring(_imp_str_literal(" void")); goto S_skip; S_default: fprintf(stderr, "Switch label 'S(%d):' not set in %s", S_sw, __PRETTY_FUNCTION__); exit(1) /* or %signal ... */; S_skip:; } //fprintf(stderr, "Report %d\n", __LINE__); //Warning or error Mark = '?'; if (!(N & Warn)) { Mark = '*'; C.Faults = C.Faults + 1; Faults++; } Faultnum = 0; C.Access = -1; //Ignore uncorrected earlier error if (Main->Start1 <= Fp && Fp < Change) return; //fprintf(stderr, "Report %d\n", __LINE__); //Track back if before current line Start = Linestart; Errline = Line; if (!(N & Point)) Faultp = 0; else { if (Joker > 0) Faultp = Joker; while (Faultp <= Start) { Start--; if (*Byteinteger(Start) == '\n') Errline--; } while (Start != Curstart && *Byteinteger(Start - 1) != '\n') Start--; } //fprintf(stderr, "Report %d\n", __LINE__); Editfp = Start; if (Faultp > Start) Editfp = Faultp - 1; if (Curlim == Extra.Lim2) Editfp = Mainfp; while (*Byteinteger(Start) == ' ') Start++; Printtext(Joker, 0); //fprintf(stderr, "Report %d\n", __LINE__); if ((N & Warn) != 0 || Nonstop != 0) { Newline(); return; } Newline(); return; //#ifdef EDITOR_SUPPORT Main->Fp = Editfp; Main->Line = Line; if (Change) Main->Change = 0x7FFFFFFE; //Edi(Main, &Null, Rep); Rep = _imp_str_literal(""); if (Main->Flag == 'I') Nonstop = 1; //fprintf(stderr, "Report %d\n", __LINE__); if (Main->Flag < 0) exit(0); //fprintf(stderr, "Report %d\n", __LINE__); if (Main->Change < 0x7FFFFFFE) { // change made //fprintf(stderr, "skip %%SIGNAL 12 at line %d\n", __LINE__); // this is causing ECCE_PERM to be read again! Screw-up in %on %event I think. _imp_signal(12, 0, 0, _imp_str_literal("")); } //#endif //fprintf(stderr, "Report %d\n", __LINE__); } // report void Croak(_imp_string S) { Printstring(_imp_join( _imp_str_literal("** "), _imp_join(S, _imp_str_literal(". Checking abandoned at line ")))); Write(Line, 0); Newline(); Nonstop = -999; fprintf(stderr, "%%SIGNAL 12 at line %d\n", __LINE__); _imp_signal(12, 0, 0, _imp_str_literal("")); } void Fault(int N) { //Note fault number and position of (earliest) fault // for subsequent reporting (warnings and weak errors) if (!Faultnum) { Faultnum = N; Faultp = Atomp; } } void Expfault(int N) { if (Faultnum == 0 || Expp < Faultp) { Faultnum = N | Point; Faultp = Expp; } } const int Pred = 1; const int Uparr = 1 << 1; const int Nocomma = 1 << 2; const int Overload = 1 << 3; const int Ranges = 1 << 4; const int Nolength = 1 << 5; const int Initass = 1 << 6; const int Kgoto = 1 << 7; const int Hyphen = 1 << 8; const int Naming = 1 << 9; const int Klabel = 1 << 10; const int Ibmhex = 1 << 11; const int Oldcycle = 1 << 12; const int Loop2 = 1 << 13; void Nonstandard(int Case) { static int Hadit = 0; if ((Control & Nonsbit) != 0 && (Case & Hadit) == 0) { Hadit += Case; Fault(Nonstand + Point + Warn); } } void Error(int Case) { Report(Case, Atomp); fprintf(stderr, "%%SIGNAL 14 at line %d\n", __LINE__); _imp_signal(14, 0, __LINE__, _imp_str_literal("")); } void Nameerror(void) { //check if the culprit has occurred before //and, if not, add it to the pool of unknowns stored at the //far end of the dictionary. while (Item < 0 && _imp_strcmp(*String(Dict[-Item].Text + Charbase), *String(Charlim)) != 0) Item = Dict[-Item].Link; if (Item >= 0) { //first time Report(Namerr + Point, Atomp); if (Charmin - Newlen - 80 >= Charlim) { Dmin--; Charmin = Charmin - Newlen - 1; *String(Charmin) = *String(Charlim); Dict[Dmin].Text = Charmin - Charbase; while (*Head > 0) Head = &Dict[*Head].Link; //find last link Dict[Dmin].Link = *Head; *Head = -Dmin; } } //fprintf(stderr, "%%SIGNAL 14 at line %d\n", __LINE__); _imp_signal(14, 0, __LINE__, _imp_str_literal("")); } void Syntaxerror(void) { int E; E = Formerr + Point; if (Atom == Dud) E = Atomerr + Point; Report(E, Atomp); //fprintf(stderr, "%%SIGNAL 14 at line %d\n", __LINE__); _imp_signal(14, 0, __LINE__, _imp_str_literal("")); } //!!!!!!!!!!!!!!!!!!! CELL CONSTRUCTORS !!!!!!!!!!!!!!!!!!! int Floated(int Item) { if (!Item) return (0); return (Explo); } //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //!!!!!!!!!!!!!!!! CODE GENERATION !!!!!!!!!!!!!!!!!!!!!!!! void Forget(void) {} void Forgetall(void) { int I; int J; Litpos = Litmin; Explo = Expmax + 1; Oldexplo = Explo; } // void Setlabel(int B) { } //set label void Setuserlabel(int Dpos) { } void Compile(int From, int To) { Np = Np0; } void Compileentry(void) { } void Compileend(void) { } //compile end //!!!!!!!!!!!!!! end of Code Generation !!!!!!!!!!!!!!!!!!!!!!! //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! void Put3(int Act, int X, int Y) { } // void Put2(int Act, int X) { } // int Tempvar(void) { return (Dlim); } void Openblock(int Pidpos) { Forget(); //a bit extreme if (Level == Maxlevel) Croak(_imp_str_literal("Too many levels")); Hold[Level] = C; Level++; C = (Blockinf){0}; Starts = 0; Cycles = 0; Curlab = Lab1; Looplab = 0; Forgetall(); C.Flags = 0; C.Type = D.Type; C.Pidpos = Pidpos; C.Localdpos = Dlim; C.Parlim = Dlim; C.Localtext = Charlim; C.Localpc = Pc; C.Localspc = Spc; C.Access = 1; } //OPEN BLOCK void Closeblock(void) { int I; int Miss; int Dpos; int *P; Identinfo *Dp; Miss = 0; P = &Miss; Dpos = C.Localdpos; while (Dpos != Dlim) { Dp = &Dict[Dpos]; if ((Dp->Flags & (Proc + Lab)) != 0 && (Dp->Flags & (Ext + Spec)) == Spec) { *P = Dpos; P = &Dp->Val; *P = 0; } Dpos++; } if (Miss) Report(Idmissing, Miss); Compileend(); Pc = C.Localpc; Spc = C.Localspc; Dlim = C.Parlim; Charlim = C.Localtext; for (I = 0; I <= 255; I++) while (Hashindex[I] >= C.Localdpos) Hashindex[I] = Dict[Hashindex[I]].Link; Level--; C = Hold[Level]; Starts = 0; Cycles = 0; } //CLOSE BLOCK //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //!!!!!!!!!!!!!!!!!!! Source input !!!!!!!!!!!!!!!!!!!!!!!!!!!! //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // void Switchinput(void) { if (Fp == Main->Lim2) { fprintf(stderr, "%%SIGNAL 12 at line %d\n", __LINE__); _imp_signal(12, 0, 0, _imp_str_literal("")); } if (Nonstop < 0) { //perming Nonstop += 3; Permlim = Dlim; C.Localdpos = Dlim; C.Parlim = Dlim; Statements = 0; } if (Fp != Main->Lim1) { Nonstop--; Fp = Mainfp; Line = Mainline; Curstart = Main->Start1; Curlim = Main->Lim1; } else Fp = Main->Start2; if (Main->Start2 <= Fp && Fp <= Main->Lim2) { Curstart = Main->Start2; Curlim = Main->Lim2; } Modesym = ' '; Sym = '\n'; } void Readline(void) { if (Faultnum) Report(Faultnum, Faultp); while (Sym != '\n') { Sym = *Byteinteger(Fp); Fp++; } while (Fp == Curlim) Switchinput(); Line++; Linestart = Fp; Sym = 0; } //READ LINE // //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //!!!!!!!!!!!!!!!!!!! Lexical processing !!!!!!!!!!!!!!!!!!!!!! //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! static int Percent = 0; static int Subatom = 0; // //Aliases: const int Arrow = Resolve; const int Exclam = Logor; const int Exclam2 = Logxor; const int Dot = Concat; const int Star = Mult; const int Slash = Fdiv; const int Slash2 = Idiv; const int Ampersand = Logand; const int Backslash = Fpower; const int Backslash2 = Ipower; const int Uparrow = Fpower; const int Uparrow2 = Ipower; const int Tilde = Lognot; const int Left = Aref; const int Underline = Recref; const int Leftbracket = 106; const int Simple = 104; const int Major = Plus; const int Scond = Equals; const int Cond = Keyand; // // Type compatibility vectors: const int Recok = 1 << 0; const int Arrok = 1 << 1; const int Stringok = 1 << 2; const int Realok = 1 << 3; const int Intok = 1 << 4; const int Charok = 1 << 5; const int Boolok = 1 << 6; const int Enumok = 1 << 7; const int Setok = 1 << 8; const int Znop = 1 << 9; const int Refonly = 1 << 10; const int Varonly = 1 << 11; const int Arithok = Intok + Realok; const int Ordok = Intok + Charok + Boolok + Enumok; const int Any = Realok + Ordok + Stringok + Arrok + Recok; // const int Opbits[64+ 44 /*64:107*/] = { [ 0 ... 63 ] = 0, /*BOOLAND*/ 64, /*BOOLOR*/ 64, /**/ 0, 0, 0, 0, /*EQUALS*/ 255, /*NOTEQ*/ 255, /*LESSEQ*/ 508, /*LESS*/ 252, /*GREATEQ*/ 508, /*GREATER*/ 252, /**/ 255, /**/ 255, /**/ 0, /*RESOLVE*/ 4, /*PLUS*/ 792, /*MINUS*/ 792, /*LOGOR*/ 528, /*LOGXOR*/ 528, /*CONCAT*/ 4, /**/ 0, 0, 0, /*MULT*/ 24, /*FDIV*/ 24, /*IDIV*/ 16, /*LOGAND*/ 16, /**/ 0, 0, 0, 0, /*FPOWER*/ 24, /*IPOWER*/ 16, /**/ 0, 0, /*LSHIFT*/ 528, /*RSHIFT*/ 528, /*LOGNOT*/ 16, /**/ 0, /*AREF*/ 2, /*RECREF*/ 1, /**/ 0, 0}; // int Nextatom(void) { //Encode next atom from source fileEncode next atom from source file //[Time-critical] static int S_sw; static void *S[256 /*0:255*/] = { &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_9, &&S_10, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_33, &&S_34, &&S_35, &&S_default, &&S_37, &&S_38, &&S_39, &&S_40, &&S_41, &&S_42, &&S_43, &&S_44, &&S_45, &&S_46, &&S_47, &&S_48, &&S_49, &&S_50, &&S_51, &&S_52, &&S_53, &&S_54, &&S_55, &&S_56, &&S_57, &&S_58, &&S_59, &&S_60, &&S_61, &&S_62, &&S_default, &&S_default, &&S_65, &&S_66, &&S_67, &&S_68, &&S_69, &&S_70, &&S_71, &&S_72, &&S_73, &&S_74, &&S_75, &&S_76, &&S_77, &&S_78, &&S_79, &&S_80, &&S_81, &&S_82, &&S_83, &&S_84, &&S_85, &&S_86, &&S_87, &&S_88, &&S_89, &&S_90, &&S_default, &&S_92, &&S_default, &&S_94, &&S_95, &&S_default, &&S_97, &&S_98, &&S_99, &&S_100, &&S_101, &&S_102, &&S_103, &&S_104, &&S_105, &&S_106, &&S_107, &&S_108, &&S_109, &&S_110, &&S_111, &&S_112, &&S_113, &&S_114, &&S_115, &&S_116, &&S_117, &&S_118, &&S_119, &&S_120, &&S_121, &&S_122, &&S_123, &&S_124, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, &&S_default, }; const int Tab = 9; int I; int J; int P; int Radix; int Digits; float Rval; const unsigned char Map[128 /*0:127*/] = {[0 ... 47] = 0, '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0, 0, 0, 0, 0, 0, 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, 0, 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, 0}; void Assemblereal(void) { J = 0; for (;;) { do { Sym = *Byteinteger(Fp); Fp++; } while (Sym == ' '); I = Sym - '0'; if (0 > I || I >= Radix) return; Rval = Rval * Radix + I; J++; } } if (0) { char *s = (char *)(Fp); fprintf(stderr, "FP=%d: ", Fp); while (isalnum(*s)) { fprintf(stderr, "%c", *s++); } fprintf(stderr, "\n"); } Matched = 0; Again: S_9:; /*tab*/ if (Sym == '\n') Readline(); do { Sym = *Byteinteger(Fp); Fp++; } while (Sym == ' '); Atomp = Fp; //(actually one after) goto *S[S_sw = Sym]; Linebreak: S_10:; /*nl*/ if (Atom != Comma) return (Terminator); goto Again; S_123:; /*{*/ do { Sym = *Byteinteger(Fp); Fp++; if (Sym == '\n') goto Linebreak; } while (Sym != '}'); goto Again; S_43: /*+*/ return (Plus); S_45: /*-*/ if (*Byteinteger(Fp) == '>') { Fp++; return (Arrow); } if (*Byteinteger(Fp) == '\n') goto Again; return (Minus); S_42: /* * */ return (Star); S_47: /* / */ if (*Byteinteger(Fp) == '/') { Fp++; return (Slash2); } return (Slash); S_92: /* \ */ if (*Byteinteger(Fp) == '\\') { Fp++; return (Backslash2); } return (Backslash); S_94: /*^*/ Nonstandard(Uparr); if (*Byteinteger(Fp) == '^') { Fp++; return (Uparrow2); } return (Uparrow); S_33: /*!*/ if (*Byteinteger(Fp) == '!') { Fp++; return (Exclam2); } return (Exclam); S_38: /*&*/ return (Ampersand); S_46: /*.*/ return (Dot); S_61: /*=*/ if (*Byteinteger(Fp) == '=') { Fp++; return (Eqeq); } return (Equals); S_35: /*#*/ if (*Byteinteger(Fp) == '#') { Fp++; return (Noteqeq); } return (Noteq); S_60: /*<*/ if (*Byteinteger(Fp) == '=') { Fp++; return (Lesseq); } if (*Byteinteger(Fp) == '>') { Fp++; return (Noteq); } if (*Byteinteger(Fp) == '<') { Fp++; return (Lshift); } return (Less); S_62: /*>*/ if (*Byteinteger(Fp) == '=') { Fp++; return (Greateq); } if (*Byteinteger(Fp) == '>') { Fp++; return (Rshift); } return (Greater); S_95: /*_*/ return (Underline); S_58: /*:*/ return (Colon); S_44: /*,*/ return (Comma); S_59: /*;*/ return (Terminator); S_40: /*(*/ return (Left); S_41: /*)*/ return (Right); S_124: /*|*/ return (Modsign); S_69: /*E*/ S_101:; /*e*/ if (*Byteinteger(Fp) == '"') { Fp++; goto Stringconst; } S_77: /*M*/ S_109: /*m*/ S_67: /*C*/ S_99:; /*c*/ if (*Byteinteger(Fp) == '\'') { Fp++; goto Charconst; } S_65: /*A*/ S_66: /*B*/ S_68: /*D*/ S_70: /*F*/ S_71: /*G*/ S_72:; /*H*/ S_73: /*I*/ S_74: /*J*/ S_75: /*K*/ S_76: /*K*/ S_78: /*N*/ S_79: /*O*/ S_80:; /*P*/ S_81: /*Q*/ S_82: /*R*/ S_83: /*S*/ S_84: /*T*/ S_85: /*U*/ S_86: /*V*/ S_87: /*W*/ S_88:; /*X*/ S_89: /*Y*/ S_90: /*Z*/ S_97: /*a*/ S_98: /*b*/ S_100: /*d*/ S_102:; /*f*/ S_103: /*g*/ S_104: /*h*/ S_105: /*i*/ S_106: /*j*/ S_107: /*k*/ S_108: /*l*/ S_110:; /*n*/ S_111: /*o*/ S_112: /*p*/ S_113: /*q*/ S_114: /*r*/ S_115: /*s*/ S_116: /*t*/ S_117: /*u*/ S_118:; /*v*/ S_119: /*w*/ S_120: /*x*/ S_121: /*y*/ S_122:; /*z*/ if (Percent) goto Keyword; Newlen = Charlim + 1; Hash = Sym | Casebit; //lower-case (if letter) *Byteinteger(Newlen) = Hash; do { Sym = *Byteinteger(Fp); Fp++; } while (Sym == ' '); Sym = Map[Sym]; if (Sym) do { Newlen++; *Byteinteger(Newlen) = Sym; Hash = Hash << 1 ^ Sym; do { Sym = *Byteinteger(Fp); Fp++; } while (Sym == ' '); Sym = Map[Sym]; } while (Sym); Fp--; Newlen -= Charlim; *Byteinteger(Charlim) = Newlen; Head = &Hashindex[Hash & 255]; Item = *Head; if (Item > 0) do { //fprintf(stderr, "do;\n"); if (Item <= 0) { //fprintf(stderr, "return;\n"); return (Ident); } Ditem = &Dict[Item]; #ifdef NEVER fprintf(stderr, "strcmp(\""); PRINTSTRING(*String(Ditem->Text + Charbase)); fprintf(stderr, "\", \""); PRINTSTRING(*String(Charlim)); fprintf(stderr, "\")\n"); #endif if (_imp_strcmp(*String(Ditem->Text + Charbase), *String(Charlim)) == 0) { //fprintf(stderr, "cmp-break;\n"); break; } Item = Ditem->Link; } while (Item > 0); //fprintf(stderr, "break;\n"); return (Ident); S_37:; /*%*/ Sym = *Byteinteger(Fp); if ('a' > (Sym | Casebit) || (Sym | Casebit) > 'z') goto Again; Fp++; Keyword:; Percent = 0; P = Syminit[Sym | Casebit]; for (;;) { while (Symbol[P] == (*Byteinteger(Fp) | Casebit)) { P++; Fp++; } if (Symbol[P] >= 128) break; Atom = Altdisp[P]; if (!Atom) { if ((Sym | Casebit) != 'c' || *Byteinteger(Fp) != '\n') return (Dud); Readline(); goto Again; } P += Atom; } if ('a' <= (*Byteinteger(Fp) | Casebit) && (*Byteinteger(Fp) | Casebit) <= 'z') Percent = 1; Subatom = Altdisp[P]; Atom = Symbol[P] - 128; if (!Atom) return (Dud); return (Atom); S_48: /*0*/ S_49: /*1*/ S_50: /*2*/ S_51: /*3*/ S_52: /*4*/ S_53: /*5*/ S_54: /*6*/ S_55: /*7*/ S_56: /*8*/ S_57:; /*9*/ Item = 0; T.Type = Inty; Radix = 10; T.Val = Sym - '0'; Ibm1:; for (;;) { for (;;) { do { Sym = *Byteinteger(Fp); Fp++; } while (Sym == ' '); I = Sym - '0'; if (Radix == 10) { if (I < 0 || I >= 10) break; if (T.Val > Max10 || (T.Val == Max10 && I > Maxdig)) { T.Type = Realy; Rval = T.Val; Assemblereal(); break; } T.Val = T.Val * 10 + I; } else { if (I >= 10) I = (Sym | Casebit) - 'a' + 10; if (I < 0 || I >= Radix) break; J = Radix; do { if (J & 1) I += T.Val; T.Val = T.Val << 1; J = J >> 1; } while (J); T.Val = I; } } if (Sym != '_') break; Radix = T.Val; if (!Radix) return (Dud); T.Val = 0; } if (Sym == '.') { if (T.Type == Inty) { T.Type = Realy; Rval = T.Val; } Assemblereal(); if (!J) return (Dud); Rval = Rval / REXP(Radix, J); } Fp--; Sym = 0; return (Const); S_39:; /*'*/ Charconst:; Item = 0; T.Type = Inty; T.Val = 0; for (;;) { Sym = *Byteinteger(Fp); Fp++; if (Sym == '\n') return (Dud); if (Sym == '\'') { if (*Byteinteger(Fp) != '\'') break; Fp++; } T.Val = (T.Val << 8) + Sym; } if (T.Val) return (Const); return (Dud); S_34:; /*"*/ Stringconst:; Item = 0; T.Type = Stringy; Stringp = Atomp; T.Val = 0; I = Line; J = Linestart; for (;;) { Sym = *Byteinteger(Fp); Fp++; if (Sym == '"') { if (*Byteinteger(Fp) != '"') break; Fp++; } T.Val = T.Val + 1; if (T.Val > 255) { Sym = 0; Fp = Atomp; Linestart = J; return (Dud); } if (Sym == '\n') Readline(); } return (Const); S_default:; return (Dud); } //NEXT ATOM void Lookupfieldident(int List) { Item = List; if (!Item) return; for (;;) { Ditem = &Dict[Item]; if (!(Ditem->Flags & Typeid)) { fprintf(stderr, "Compare %s vs %s\n", (char *)(Ditem->Text + Charbase + 1), (char *)(Charlim + 1)); if (_imp_strcmp(*String(Ditem->Text + Charbase), *String(Charlim)) == 0) return; if (!(Ditem->Flags & More)) break; } Item++; } Item = 0; } int /* boolean */ A(int K) { //Basic atom-testing predicate if (Matched) Atom = Nextatom(); if (K != Atom) return (0); Matched = 1; return (1); } void Get(int K) { if (Matched) Atom = Nextatom(); Matched = 1; if (Atom == K) return; if (Atom == Dud) Syntaxerror(); Faultp = Atomp; Report(Formerr + Point, -K); fprintf(stderr, "%%SIGNAL 14 at line %d\n", __LINE__); _imp_signal(14, 0, __LINE__, _imp_str_literal("")); } void Allow(int K) { if (A(K)) ; } void Declare(void) { if (!Speccing) { //not within spec params if (Item >= C.Localdpos) { //there already if ((D.Flags & Spec) == 0 && D.Flags + Spec == Ditem->Flags && Ditem->Type == D.Type) { Ditem->Flags = Ditem->Flags - Spec; return; } Fault(Duperr + Point); } D.Link = *Head; *Head = Dlim; if (Item > 0) D.Text = Ditem->Text; else { D.Text = Charlim - Charbase; Charlim = Charlim + Newlen + 1; if (Charlim + 80 >= Charmin) Croak(_imp_str_literal("Identifier space exhausted")); } } else D.Text = 0; Item = Dlim; Ditem = &Dict[Item]; *Ditem = D; Dlim++; if (Dlim >= Dmin) Croak(_imp_str_literal("Too many identifiers")); } //DECLARE void Declareanon(void) { D.Text = 0; D.Link = 0; Dict[Dlim] = D; Dlim++; if (Dlim >= Dmin) Croak(_imp_str_literal("Too many identifiers")); } static int Jammy; int /* boolean */ Aassop(void) { if (Matched) Atom = Nextatom(); if (Atom != Equals && Atom != Eqeq) { if (Atom != Less || *Byteinteger(Fp) != '-') return (0); Jammy = 2; Fp++; } else Jammy = 0; Matched = 1; return (1); } //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //!!!!!!!!!!!!!!!!!!! Expressions !!!!!!!!!!!!!!!!!!!!!!!!!!!!! //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! static int Literal = 0; auto void Getexpression(int Rank, int Control); int Compat(int Control) { if (T.Type == Inty) { if ((Control & Intok) == 0 && (Control & Realok) != 0) { Item = Floated(Item); T.Type = Realy; } return (Control & (Intok + Realok)); } if (T.Type <= Booltype) return (Control & (Boolok >> (Booltype - T.Type))); if (T.Type < Direct) return (Control & Enumok); return (Control & Arrok); } // int Listmatch(int Alist, int Blist) { Identinfo *Ap; Identinfo *Bp; if (Alist == Blist) return (1); if (Alist < Dictmin || Blist < Dictmin) return (0); do { Ap = &Dict[Alist]; Bp = &Dict[Blist]; if (Ap->Type != Bp->Type) return (0); Alist++; Blist++; } while (Ap->Flags & Bp->Flags & More); if ((Ap->Flags & More) != 0 || (Bp->Flags & More) != 0) return (0); return (1); } // void Getreference(int Reftype) { int Type; int Temp; Getexpression(Simple, Refonly + Any); Type = Ditem->Type & Puretype; Reftype = Reftype & Puretype; if (Reftype == Type) return; if (Type < Reftype) { Temp = Type; Type = Reftype; Reftype = Temp; } if (Reftype == Nulltype) return; Type = Dict[Type].Type; if (Type <= Inty && Type == Reftype) return; if (Type >= Direct && Type == Dict[Reftype].Type) return; Expfault(Typerr + Point); } // void Getvalue(int Valtype) { Identinfo *Dp; Identinfo *P; Getexpression(Major, Any); Valtype = Valtype & Puretype; Dp = &Dict[Valtype]; if (T.Type != Dp->Type) { //base types differ if (Item == 0 && 0 == T.Val) //zero return; if (Dp->Type == Realy && T.Type == Inty) { //float T.Type = Realy; return; } } else if (T.Type >= Inty) { //scalar if (!Item) { if (Dp->Low <= T.Val && T.Val <= Dp->Val) return; if (Jammy >= 0) Jammy = Jammy | 1; } else { // Damn! Another dangling else situation. if (T.Low >= Dp->Low) { if (T.Val <= Dp->Val) return; if (Jammy >= 0) Jammy = Jammy | 1; if (T.Low <= Dp->Val) return; } else { if (Jammy >= 0) Jammy = Jammy | 1; if (T.Val >= Dp->Low) return; } } if (Jammy < 2) Expfault(Rangerr + Point); return; } else if (T.Type == Stringy) { //VALUE = LENGTH* if (T.Val > Dp->Val) { if (Jammy >= 0) Jammy = Jammy | 1; if (Item == 0 && Jammy < 2) Expfault(Rangerr + Point); } return; } else if (T.Type == Recy) { if (T.Extra == Dp->Extra) return; if (Jammy >= 2) { Jammy = Jammy | 1; return; } } else if (T.Type == Realy) return; Expfault(Typerr + Point); } //GET VALUE // void Getliteral(int Littype) { Literal++; Getvalue(Littype); Literal--; } // void Getlitint(void) { Literal++; Getexpression(Major, Intok); Literal--; } // void Getlitstring(void) { int Holditem; Holditem = Item; //preserve Get(Const); if (T.Type != Stringy) Error(Typerr + Point); Item = Holditem; //restore } // void Getparmlist(void) { Identinfo *Hp; Identinfo *Dp; int I; int J; int Headitem; int Headact; int Dpos; int Case; int Procnp; int First; Headitem = Item; Hp = Ditem; Headact = Rcall; //stack procedure ident I = 0; First = 1; Dpos = Headitem; Dp = Hp; do { //Set up expression state from formal param details if (!(Dp->Flags & More)) Error(Toomany + Point); do { Dpos++; Dp = &Dict[Dpos]; } while (!(Dp->Flags & Parm)); if (Dp->Flags & Proc) { Get(Ident); if (Item <= 0) Nameerror(); if (!(Ditem->Flags & Proc)) Fault(Typerr + Point); //for now if (Item > Headitem) Fault(Caterr + Point); } else if (Dp->Type < Indirect) { Case = I & 7; I++; Getvalue(Dp->Type); } else { //name or proc Case = (I >> 3) + 8; I += 8; Getreference(Dp->Type); } } while (A(Comma)); Item = Explo; } //get PARMLIST // void Getresolution(void) { if (!A(Left)) { Getreference(Anystringvar); Get(Dot); Get(Left); } Getvalue(Anystring); Get(Right); if (A(Dot)) Getreference(Anystringvar); } // //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // void Getexpression(int Rank, int Control) { //Main expression recognition routine //To bring together the treatment of all binary operators // and ensure fast recognition of simple expressions, // expressions of different levels are handled by // precedence techniques rather than syntactically //CONTROL defines acceptability int Type; int F; int Opok; int C1; int Op; int Atomp1; int Item1; Objinfo T1; Identinfo *Dp; int Litval(void) { static int Lit_sw; static void *Lit[44 /*64:107*/] = { &&Lit_64, &&Lit_65, &&Lit_66, &&Lit_default, &&Lit_default, &&Lit_default, &&Lit_70, &&Lit_71, &&Lit_72, &&Lit_73, &&Lit_74, &&Lit_75, &&Lit_default, &&Lit_default, &&Lit_default, &&Lit_default, &&Lit_80, &&Lit_81, &&Lit_82, &&Lit_83, &&Lit_84, &&Lit_default, &&Lit_default, &&Lit_default, &&Lit_88, &&Lit_default, &&Lit_90, &&Lit_91, &&Lit_default, &&Lit_default, &&Lit_default, &&Lit_default, &&Lit_default, &&Lit_default, &&Lit_default, &&Lit_default, &&Lit_100, &&Lit_101, &&Lit_102, &&Lit_default, &&Lit_default, &&Lit_default, &&Lit_default, &&Lit_default, }; goto *Lit[Lit_sw = (Op)-64]; Lit_80: /*plus*/ return (T1.Val + T.Val); Lit_81: /*minus*/ return (T1.Val - T.Val); Lit_88: /*mult*/ return (T1.Val * T.Val); Lit_90: /*idiv*/ if (T.Val) return (T1.Val / T.Val); Fault(Rangerr); return (0); Lit_91:; /*logand*/ Lit_64: /*booland*/ return (T1.Val & T.Val); Lit_82:; /*logor*/ Lit_65: /*boolor*/ return (T1.Val | T.Val); Lit_83: /*logxor*/ return (T1.Val ^ T.Val); Lit_100: /*lshift*/ return (T1.Val << T.Val); Lit_101: /*rshift*/ return (T1.Val >> T.Val); Lit_66: /*boolnot*/ return (T.Val ^ True); Lit_102: /*lognot*/ return (~T.Val); Lit_70: /*equals*/ if (T1.Val == T.Val) return (True); return (False); Lit_71: /*noteq*/ if (T1.Val != T.Val) return (True); return (False); Lit_72: /*lesseq*/ if (T1.Val <= T.Val) return (True); return (False); Lit_73: /*less*/ if (T1.Val < T.Val) return (True); return (False); Lit_74: /*greateq*/ if (T1.Val >= T.Val) return (True); return (False); Lit_75: /*greater*/ if (T1.Val > T.Val) return (True); return (False); Lit_84: /*concat*/ return (T1.Val + T.Val); Lit_default:; return (1); } //Get leading operand if (Matched) Atom = Nextatom(); Atomp1 = Atomp; //note position for reports if (Atom == Ident) { Matched = 1; if (Item <= 0) Nameerror(); if (Item >= Dlim0) Fault(Selfref + Point); Type = Ditem->Type; if (Control & (Refonly + Varonly)) { if ((Control & Varonly) != 0 && (F & Var) == 0) Error(Nonvar + Point); if (Type < Direct) Error(Nonref + Point); } F = Ditem->Flags; if (Inty <= Type && Type <= Booltype && (F & Proc) == 0) { //literal Item = 0; T = Ditem->Details; } else { if (Literal > 0) Fault(Nonliteral + Point); if (F & Proc) { if (F & Parm) { Ditem = &Dict[Type]; Type = Ditem->Type; } if (Type == Nulltype) Error(Caterr + Point); //routine if (A(Left)) { Dp = Ditem; Getparmlist(); Get(Right); Ditem = Dp; } else { if (Ditem->Flags & More) Error(Toofew + Point); Item = Explo; } } for (;;) { Dp = &Dict[Type & Puretype]; T = Dp->Details; if (Matched) Atom = Nextatom(); if (Atom != Underline && Atom != Left) break; Matched = 1; Item1 = Item; if (Atom == Left) { for (;;) { if (T.Type < Direct) Syntaxerror(); //element type Type = T.Type; Getvalue(T.Val); //index Item = Explo; Ditem = Dp; if (!A(Comma)) break; Dp = &Dict[Type & Puretype]; T = Dp->Details; Item1 = Item; } Get(Right); } else { //rec subfield if (T.Type != Recy) Syntaxerror(); Get(Ident); Lookupfieldident(T.Extra); if (Item <= 0) Error(Namerr + Point); Type = Ditem->Type; Item = Explo; } } if (Control & (Varonly + Refonly)) goto Final; } } else { if (Control & Varonly) Error(Nonvar + Point); if (Control & Refonly) Error(Nonref + Point); if (A(Const)) ; else if (Atom == Minus) { //leave unmatched Item = 0; T = (Objinfo){0}; T.Type = Inty; } else if (A(Left)) { if (Rank < Major) //condition Getexpression(Cond, Any); else { Jammy -= 4; C1 = Control; if (C1 & Realok) C1 = C1 | Intok; Getexpression(Major, C1); Jammy += 4; } Get(Right); } else if (A(Keynot)) { if (Rank >= Major) Syntaxerror(); Getexpression(Scond, Any); if (!Item) T.Val = T.Val ^ True; else Item = Explo;//expref(boolnot,item,0) } else if (Atom == Backslash) { Item = 0; T = (Objinfo){0}; T.Type = Inty; Atom = Tilde; } else if (A(Modsign)) { if (!(Control & Arithok)) Fault(Typerr + Point); Getexpression(Major, Arithok); Get(Modsign); if (!Item) { // another dangling else if (T.Val < 0) { if (T.Val != Minint) T.Val = -T.Val; else Expfault(Rangerr); } } else if (T.Type == Inty) { // check for dangling else against Imp source Item = Explo; } else if (T.Type == Realy) { Item = Explo; } else Error(Typerr); } else Syntaxerror(); } if (Matched) Atom = Nextatom(); while (Atom >= Rank) { Op = Atom; Matched = 1; Opok = Opbits[Op]; C1 = Compat(Opok); //[may change ITEM,T_TYPE] if (!C1) Fault(Typerr + Point); Item1 = Item; T1 = T; if (Op >= Major) { //non-conditional if (Op == Dot) Getexpression(Dot, Stringok); /*right-associate*/ else Getexpression((Op & (~7)) + 8, C1); if (T.Type == Realy && T1.Type == Inty) { Item1 = Floated(Item1); T1.Type = Realy; } } else { if (Op == Resolve) Getresolution(); else if (Op >= Eqeq) Getexpression(Simple, Any + Refonly); else if (Op >= Equals) { Getexpression(Major, C1); if (Equals <= Atom && Atom < Eqeq) { Op = Atom; Matched = 1; Getexpression(Major, C1); } if (T.Type == Realy && T1.Type == Inty) { Item1 = Floated(Item1); T1.Type = Realy; } } else { Getexpression(Scond, Any); if (Atom >= Cond) if (Atom != Op) Syntaxerror(); } T.Type = Booltype; if (Item) { T.Low = 0; T.Val = 1; } } if (!Item1) //first operand literal if (!Item) { //both literal T.Val = Litval(); if (!Item) continue; } if (!Item) { //second operand literal if (Op == Minus && T.Type == Inty) { //standardise if (T.Val != Minint) T.Val = -T.Val; Op = Plus; } if (T.Val == 0 && (Opok & Znop) != 0) { Item = Item1; continue; } } Item = Explo;//expref(op,item1,item,t_val) T.Low = Minint; T.Val = Maxint; } Final:; Expp = Atomp1; if (!Compat(Control)) Expfault(Typerr); } //get EXPRESSION //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //!!!!!!!!!!!!!!!!!!! Conditions and loops !!!!!!!!!!!!!!!!!!!! //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // void Getcondition(void) { int Polarity; Polarity = Subatom; Condnp = Np; Getexpression(Cond, Any); } //get CONDITION void Getstatements(int Stopper) { int Holdnp; int Holdlooplab; static int Initial_sw; static void *Initial[108 /*0:107*/] = { &&Initial_default, &&Initial_1, &&Initial_2, &&Initial_3, &&Initial_4, &&Initial_5, &&Initial_6, &&Initial_7, &&Initial_8, &&Initial_9, &&Initial_10, &&Initial_11, &&Initial_12, &&Initial_13, &&Initial_default, &&Initial_15, &&Initial_16, &&Initial_17, &&Initial_default, &&Initial_19, &&Initial_default, &&Initial_default, &&Initial_22, &&Initial_23, &&Initial_24, &&Initial_25, &&Initial_26, &&Initial_27, &&Initial_28, &&Initial_29, &&Initial_30, &&Initial_default, &&Initial_default, &&Initial_33, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_37, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_41, &&Initial_42, &&Initial_default, &&Initial_default, &&Initial_45, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_52, &&Initial_default, &&Initial_54, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_63, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_79, &&Initial_default, &&Initial_default, &&Initial_82, &&Initial_83, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_88, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, &&Initial_default, }; void Getinstruction(void) { int Item1; int Hold; int Act; Identinfo *Ditem1; void Putact(void) { } // if (C.Flags < Hadinst) { //first in block C.Flags = C.Flags + Hadinst; if (Level <= Outerlevel) Fault(Ordererr); } Instnp = Np; do if (A(Ident)) { if (Item <= 0) Nameerror(); if (Ditem->Flags & Var) { Matched = 0; Getexpression(Simple, Any); Item1 = Item; Ditem1 = Ditem; if (A(Equals)) { Getvalue(Ditem1->Type); } else if (A(Eqeq)) { if (Ditem1->Type < Indirect) Syntaxerror(); Getreference(Ditem1->Type); if (Item) Item += Ad; } else if (Atom == Less && *Byteinteger(Fp) == '-') { Fp++; Matched = 1; Jammy = 2; Getvalue(Ditem1->Type); } else { if (!A(Arrow)) Syntaxerror(); Getresolution(); } } else { if (!(Ditem->Flags & Proc)) Error(Caterr + Point); if (Ditem->Flags & Parm) Ditem = &Dict[Ditem->Type]; if (Ditem->Type != Nulltype) Error(Caterr + Point); if (A(Left)) { Getparmlist(); Get(Right); } else { //parameterless routine if (Ditem->Flags & More) Error(Toofew + Point); } } } else { Act = Atom; Hold = Subatom; T.Val = 0; C.Access = 0; if (A(Monitor)) { C.Access = 1; } else if (A(Exit)) { if (!Looplab) Fault(Notinloop + Point); else { T.Val = Looplab; Putact(); } break; } else if (A(Return)) { if (C.Type != Nulltype) Fault(Notinrout + Point); else Putact(); break; } else if (A(Result)) { if (C.Type <= Nulltype) Error(Notinfun + Point); if (!Aassop()) Syntaxerror(); if (C.Type < Direct) { //function if (Atom == Eqeq) Fault(Caterr + Point); Getvalue(C.Type); } else { //map if (Atom != Eqeq) Fault(Caterr + Point); Getreference(C.Type + (Indirect - Direct)); } break; } else if (A(Tf)) { //%true, %false if (C.Type != Booltype) Fault(Notinpred + Point); else Putact(); break; } else if (A(Arrow) || A(Goto)) { if (Atom == Goto) Nonstandard(Kgoto); Get(Ident); if (*Byteinteger(Fp) != '(') { if (Item < C.Localdpos || (Ditem->Flags & Lab) == 0 || Ditem->Type != Nulltype) { D.Flags = Spec + Lab; D.Type = Nulltype; Declare(); } } else { if (Item < C.Localdpos) Nameerror(); if ((Ditem->Flags & Lab) == 0 || Ditem->Type == Nulltype) Syntaxerror(); Get(Left); Getvalue(Ditem->Type); Get(Right); } break; } else if (A(Stop)) { Putact(); break; } else if (A(Signal)) { C.Access = 1; Allow(Keyevent); Getlitint(); if (0 > T.Val || T.Val > 15) Expfault(Rangerr + Point); Hold = T.Val; T.Val = 0; if (A(Comma)) Getlitint(); Hold += T.Val << 4; Item = 0; T.Val = 0; if (A(Comma)) Getvalue(Anyint); break; } else Syntaxerror(); } while (A(Keyand)); } //GET INSTRUCTION void Getforclause(void) { int Loopvar; int K; int S; int Start; int Sval; int I; int Inc; int Ival; int E; int N; int Temp; int Eval; Identinfo *Dp; Holdnp = Np; Temp = 0; Dict[Curlab].Val = 1; Condnp = Np; Get(Ident); if (Item <= 0) Nameerror(); if (Dict[Ditem->Type & Puretype].Type != Inty) Fault(Typerr + Point); if (Ditem->Type != Direct + Inttype) Fault(Caterr + Point + Warn); Loopvar = Item; Dp = Ditem; Get(Equals); Getvalue(Ditem->Type); Start = Item; Sval = T.Val; Get(Comma); Getvalue(Anyint); Inc = Item; Ival = T.Val; if (Inc == 0 && 0 == Ival) { Expfault(Rangerr + Point); Ival = 1; } Get(Comma); Getvalue(Ditem->Type); //Deal with INC and replace START by START-INC if (!Inc) { //literal increment I = 1; //litref(ival) if (!Start) { //START and INC both literal Sval -= Ival; S = 1; //litref(sval) } else { S = Explo;//expref(plus,start,litref(-ival)) } } else { //allocate temp var S = Explo;//expref(minus,s,i) } if (!(Start | Inc | Item)) { //all literal K = T.Val - Sval; N = K / Ival; if (N < 0) Fault(Boundserr); if (N * Ival != K) Fault(Unending); } } //get FORCLAUSE void Getswitchindex(void) { int Item1; Identinfo *Dp; Item1 = Item; Dp = Ditem; Get(Left); Item = 1; if (A(Star)) { if (Dp->Spare) Fault(Duperr + Point); Dp->Spare = 1; } else { Getliteral(Dp->Type); if (Dp->Type > Inttype && Faultnum == 0) { T.Val = T.Val - Dict[Dp->Type].Low + Dp->Val; if (Final[T.Val]) Expfault(Duperr + Point); Final[T.Val] = 1; } } Get(Right); C.Access = 1; } //[unsure of efficiency implications of trapping overflow lower down] if (_imp_on_event(1, 14)) { _reset: // if (_imp_on_event(1, 14)) goto _reset; /* previously, trapping an event once removed the event handler! */ //fprintf(stderr, "%%ON %%EVENT 1, 14 at line %d\n", __LINE__); if (EVENT.EVENT == 1) Report(Rangerr, 0); goto Skip; } //!!!!!!!!!!!!!!!!!! Start of new statement !!!!!!!!!!!!!!!!!!! Next:; Statements++; Next1:; if (Faultnum) Report(Faultnum, Faultp); D = (Identinfo){0}; Declmode = 0; Dsize = 0; Dlim0 = Dlim; Elements = 0; Speccing = 0; Mcoding = 0; Literal = 0; Jammy = 0; Dict[Curlab].Val = 0; Dict[Curlab + 1].Val = 0; Np = Np0; Instnp = Np0; Condnp = Np0; if (Explo < Expmin + 50 || Litpos > Litmax - 50) Forgetall(); T.Val = 0; // Initial_52:; /*terminator*/ Atom = Nextatom(); Matched = 1; goto *Initial[Initial_sw = Atom]; Initial_88: /*star*/ Initial_82: /*exclam*/ Initial_83:; /*exclam2*/ Readline(); goto Next1; Term:; Get(Terminator); goto Next; Skip:; C.Access = -1; if (Atom != Terminator) { do { Subatom = Atom; Atom = Nextatom(); } while (Atom != Terminator); if (Subatom == Start) Starts++; if (Subatom == Cycle) Cycles++; } goto Next; Initial_63:; /*dud*/ Syntaxerror(); //ie atom error Initial_default:; Error(Nonstarter + Point); Initial_54:; /*ident*/ if (*Byteinteger(Fp) == ':') { //simple label Fp++; D.Flags = Lab; D.Type = Nulltype; Declare(); Setuserlabel(Item); goto Next; } if (Item <= 0) Nameerror(); if (Ditem->Flags & Lab) { Getswitchindex(); Get(Colon); goto Next; } Initial_7: /*return*/ Initial_9: /*result*/ Initial_8:; /*tf*/ Initial_10: /*stop*/ Initial_12: /*signal*/ Initial_13:; /*monitor*/ Initial_6: /*exit*/ Initial_11: /*goto*/ Initial_79:; /*arrowarrow*/ Matched = 0; Getinstruction(); if (A(Terminator)) goto Next; C.Access = 1; if (A(Iu)) { Holdnp = Np; Getcondition(); } else if (A(While)) { Holdnp = Np; Getcondition(); } else if (A(For)) { Getforclause(); } else { if (!A(Until)) Syntaxerror(); Getcondition(); } goto Term; Initial_16:; /*iu*/ //%if, %unless for (;;) { Holdnp = Np; Getcondition(); if (A(Then)) { if (A(Start)) goto Fudge; Getinstruction(); } else { Get(Start); Fudge:; for (;;) { Get(Terminator); Curlab += 2; Getstatements(Else); Curlab -= 2; if (Atom != Else) break; if (A(Iu)) Getcondition(); } if (Atom != Finish) return; } if (!A(Else)) break; if (A(Start)) goto Fudge; if (!A(Iu)) { Getinstruction(); break; } } goto Term; Initial_22:; /*cycle*/ if (A(Terminator)) { Holdlooplab = Looplab; Looplab = Curlab; Curlab += 2; Getstatements(Repeat); Curlab -= 2; Looplab = Holdlooplab; if (Atom != Repeat) return; if (A(Until)) Getcondition(); goto Term; } Nonstandard(Oldcycle); Getforclause(); goto For1; Initial_17:; /*while*/ Holdnp = Np; Getcondition(); Get(Cycle); Get(Terminator); Holdlooplab = Looplab; Looplab = Curlab; Curlab += 2; Getstatements(Repeat); Curlab -= 2; Looplab = Holdlooplab; if (Atom != Repeat) return; if (A(Until)) { Nonstandard(Loop2); Getcondition(); } goto Term; Initial_19:; /*for*/ Getforclause(); Get(Cycle); For1:; Get(Terminator); Holdlooplab = Looplab; Looplab = Curlab; Curlab += 2; Getstatements(Repeat); Curlab -= 2; Looplab = Holdlooplab; if (Atom != Repeat) return; goto Term; Initial_15:; /*on*/ if (C.Flags >= Hadon || Level <= Outerlevel) Fault(Ordererr + Point); C.Flags = C.Flags | Hadon; Matched = 1; Allow(Keyevent); do { Getlitint(); if (0 > T.Val || T.Val > 15) Expfault(Rangerr + Point); C.Events = C.Events | 1 << T.Val; } while (A(Comma)); Get(Start); Curlab += 2; Getstatements(Finish); Curlab -= 2; if (Atom != Finish) return; goto Term; // Initial_4:; /*else*/ if (Starts) goto Skip; if (Stopper == Else) return; if (Stopper == Finish) Error(Noif); Initial_3:; /*finish*/ if (Starts) { Starts--; goto Skip; } if (Stopper == Finish || Stopper == Else) return; Error(Nostart); Initial_2:; /*repeat*/ if (Cycles) { Cycles--; goto Skip; } if (Stopper == Repeat) return; Error(Nocycle); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //!!!!!!!!!!!!!!!!!!! Declarations !!!!!!!!!!!!!!!!!!!!!!!!!!!! //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // int Newatype(int Eltype, int Xtype) { int Dpos; Identinfo *Dp; static Identinfo D = {0}; Dpos = Dictmin; do { Dp = &Dict[Dpos]; if ((Dp->Flags & Typeid) != 0 && Dp->Type == Eltype && Dp->Val == Xtype) return (Dpos + Direct); Dpos++; } while (Dpos != Dlim); D.Flags = Typeid; D.Type = Eltype; D.Val = Xtype; Dict[Dpos] = D; Dlim++; if (Dlim >= Dmin) Croak(_imp_str_literal("Too many identifers")); return (Dpos + Direct); } // int Newstype(int Max) { int Dpos; Identinfo *Dp; static Identinfo D = {0}; Dpos = Dictmin; do { Dp = &Dict[Dpos]; if (Dp->Type == Stringy && Dp->Val == Max) return (Dpos); Dpos++; } while (Dpos != Dlim); D.Flags = Typeid; D.Type = Stringy; D.Val = Max; Dict[Dpos] = D; Dlim++; if (Dlim >= Dmin) Croak(_imp_str_literal("Too many identifers")); return (Dpos); } // int Newrange(int Type, int Lower, int Upper) { int Dpos; Identinfo *Dp; static Identinfo D = {0}; if (Lower > Upper) { Fault(Boundserr); Upper = Lower; } Elements = Maxint; if ((Upper ^ Lower) >= 0 || Minint + Upper - Lower < 0) Elements = Upper - Lower; if (Elements != Maxint) Elements++; Dpos = Dictmin; do { Dp = &Dict[Dpos]; if (Dp->Flags == Typeid && Dp->Type == Type && Dp->Low == Lower && Dp->Val == Upper) return (Dpos); Dpos++; } while (Dpos == Dlim); D.Flags = Typeid; D.Type = Type; D.Low = Lower; D.Val = Upper; Dict[Dpos] = D; Dlim++; if (Dlim >= Dmin) Croak(_imp_str_literal("Too many identifers")); return (Dpos); } void Getlitbounds(void) { int Lower; Get(Left); Getlitint(); Lower = T.Val; Get(Colon); Getlitint(); Get(Right); T.Low = Lower; //always integer at present Item = Newrange(Inty, T.Low, T.Val); } void Getident(void) { Dlim0 = Dlim; Get(Ident); Declare(); if ((D.Flags & Ext) != 0 && A(Alias)) Getlitstring(); } void Getidentlist(void) { Dlim0 = Dlim; do { Get(Ident); Declare(); if ((D.Flags & Ext) != 0 && A(Alias)) Getlitstring(); } while (A(Comma)); } void Gettype(int Flags) { static int Fbase; static Identinfo *Formp; static Identinfo *Fieldp; // void Getformatdef(void) { int Disp; int Max; int Base; void Getfieldident(void) { Get(Ident); if (Item > 0) D.Text = Ditem->Text; else { D.Text = Charlim - Charbase; Charlim = Charlim + Newlen + 1; if (Charlim + 80 >= Charmin) Croak(_imp_str_literal("Identifier space exhausted")); } Ditem = &Dict[Dlim]; Fieldp = Ditem; *Ditem = D; if (!Formp->Extra) Formp->Extra = Dlim; Dlim++; if (Dlim >= Dmin) Croak(_imp_str_literal("Too many identifiers")); } void Getunit(void) { for (;;) if (A(Left)) { Getformatdef(); Get(Right); if (!A(Comma)) return; } else { Gettype(Static + More); if (!(D.Flags & Parm)) do { if ((Disp & 1) != 0 && Dsize != 1) Disp++; D.Val = Disp; Disp += Dsize; Getfieldident(); if (!A(Comma)) return; Atom = Nextatom(); } while (Atom == Ident); else { // check for dangling else here too. D.Flags = D.Flags - Parm; if (Disp & 1) Disp++; D.Val = Disp; Getfieldident(); Getlitbounds(); Fieldp->Type = Newatype(D.Type, Item); Disp += Dsize * Elements; if (!A(Comma)) return; } } } Max = 0; Base = 0; do { Disp = Base; Getunit(); if (Max < Disp) Max = Disp; } while (A(Keyor)); Base = Max; } //get FORMATDEF Dsize = 0; D.Mode = 0; D.Val = 0; D.Type = Nulltype; if (A(Rpred)) { //%routine,(%integerfn) if (Flags & Ext) Flags = Flags & (~Static); if (Flags & Static) Syntaxerror(); if (Subatom) { Nonstandard(Pred); D.Type = Booltype; } D.Flags = Flags + Proc; Declmode += Pcmode; return; } if (A(Krange)) { //%byte,%short,%half,%mite D.Type = Inttype + Subatom; Dsize = 1; if (D.Type == Shorttype || D.Type == Halftype) Dsize = 2; if (D.Type >= Mitetype) Nonstandard(Ranges); Allow(Keyinteger); } else if (A(Keyinteger)) { //%integer D.Type = Inttype; Dsize = 4; Atom = Nextatom(); if (Atom == Left) { Getlitbounds(); D.Type = Item; if (Elements <= 65536 && T.Low >= -32768) Dsize = 2; if (Elements <= 256 && T.Low >= -128) Dsize = 1; } } else if (A(Keylong)) { //%long D.Type = Longinttype; Dsize = 8; if (!A(Keyinteger)) { D.Type = Longrealtype; Get(Keyreal); } } else if (A(Keyreal)) { //%real D.Type = Realtype; Dsize = 4; } else if (A(Keystring)) { //%string D.Type = Stringy; T.Val = 255; Dsize = 256; if (A(Left)) { T.Val = 0; if (!A(Star)) { Getlitint(); if (0 >= T.Val || T.Val > 255) { Expfault(Rangerr + Point); T.Val = 255; } } Get(Right); } else Nonstandard(Nolength); if (T.Val) { D.Type = Newstype(T.Val); Dsize = (T.Val + 2) & (~1); } } else if (A(Keyrecord)) { //%record D.Type = Recy; if (A(Keyformat)) { if (Flags & (Static + Ext)) Syntaxerror(); if (A(Keyspec)) { D.Flags = Typeid + Spec; Getident(); } else { D.Flags = Typeid; Getident(); Formp = Ditem; Get(Left); Fbase = 0; Getformatdef(); Fieldp->Flags = Fieldp->Flags - More; Get(Right); } D.Flags = Typeid; return; } Get(Left); if (!A(Star)) { if (!A(Ident)) { Getformatdef(); Fieldp->Flags = Fieldp->Flags - More; Get(Right); D.Flags = Typeid; Declareanon(); } if (Item <= 0) Nameerror(); if (Ditem->Type != Recy) Syntaxerror(); D.Type = Item; Dsize = Ditem->Val; } Get(Right); } else { if (Atom != Keyname) Syntaxerror(); //untyped %name } //End of basic type info: set item size in DECLMODE if (Dsize <= 4) if (Dsize <= 2) Declmode = Dsize << Sizeshift; else Declmode = Longsize << Sizeshift; //Appendages if (A(Fnmap)) { //%fn, %map if (Flags & Ext) Flags = Flags & (~Static); if (Flags & Static) Syntaxerror(); if (Subatom) { Flags++; /*flags = flags+var*/ D.Type = D.Type + Direct; //map } D.Flags = Flags + Proc; Declmode += Pcmode; return; } D.Type = D.Type + Direct; while (A(Keyarray) || A(Keyname)) { if (Atom == Keyarray) { //%array if (D.Type >= Indirect) Nonstandard(Naming); if (!A(Keyname)) { if (Flags & Parm) Syntaxerror(); Flags += Parm; //as indic break; } D.Type = Newatype(D.Type, Inty); } if (D.Type >= Indirect) Syntaxerror(); D.Type = D.Type + (Indirect - Direct); Dsize = 4; } D.Flags = Flags ^ Var; } //GET TYPE // void Getownarraydeclaration(void) { int Holdval; int Dpos; Identinfo *Dp; Getident(); Dpos = Item; Dp = Ditem; Getlitbounds(); Dp->Type = Newatype(D.Type, Item); if (Aassop()) { Allow(Terminator); do { Getliteral(D.Type); if (Faultnum == Rangerr + Point) Faultnum = Rangerr + Point + Warn; Holdval = T.Val; T.Val = 1; if (A(Left)) { T.Val = Elements; if (!A(Star)) Getlitint(); Get(Right); } Elements -= T.Val; } while (A(Comma)); if (Elements != 0 && Faultnum == 0) Report(Counterr, Dpos); } } //get OWN ADECL void Getarraydeclaration(void) { //ie get IDENTLISTS and BOUNDS int I; int Dlim1; int Hold; int Holdval; int Type; void Getbounds(void) { int Range; Getvalue(Anyint); Hold = Item; if (Hold) T.Val = Minint; Holdval = T.Val; Get(Colon); Getvalue(Anyint); if (Item) T.Val = Maxint; Range = Newrange(Inty, Holdval, T.Val); if (A(Comma)) Getbounds(); Type = Newatype(Type, Range); } do { Type = D.Type; Getidentlist(); Dlim1 = Dlim; Get(Left); Getbounds(); Get(Right); while (Dlim0 != Dlim1) { Dict[Dlim0].Type = Type; Dlim0++; } } while (A(Comma)); } //get BOUNDS void Getparmdef(void) { int Headitem; int Dpos; int Dlim1; Identinfo *Headditem; Identinfo *Dp; int Parmmatch(int Apos) { int Bpos; Identinfo *Ap; Identinfo *Bp; Bpos = Dlim1; Ap = &Dict[Apos]; while (Bpos != Dlim) { if (!(Ap->Flags & More)) return (0); do { Apos++; Ap = &Dict[Apos]; } while (!(Ap->Flags & Parm)); Bp = &Dict[Bpos]; if (Ap->Type != Bp->Type) return (0); Bpos++; } if (!(Ap->Flags & More)) return (1); return (0); } // Headitem = Item; Headditem = Ditem; Dlim1 = Dlim; if (A(Left)) { for (;;) { if (Atom != Ident) Gettype(Parm | More); if (!(D.Flags & Proc)) { Getident(); if (!A(Comma) && Atom == Right) break; if (Atom != Comma) Nonstandard(Nocomma); else Atom = Nextatom(); } else { Getident(); Speccing += 2; Getparmdef(); Speccing -= 2; if (!A(Comma)) break; } } Dict[Dlim - 1].Flags = Dict[Dlim - 1].Flags - More; Get(Right); } if (Speccing >= 2) { Dpos = Dictmin; do { Dp = &Dict[Dpos]; if ((Dp->Flags & Proc) != 0 && Dp->Type == Headditem->Type) if (Parmmatch(Dpos)) { Headditem->Type = Dpos; Dlim = Dlim1; return; } Dpos++; } while (Dpos < Headitem); Fault(Caterr); Dlim = Dlim1; return; } if (Speccing == 0 && (Headditem->Flags & Spec) != 0) { Headditem->Flags = Headditem->Flags - Spec; if (!Parmmatch(Headitem)) Fault(Matcherr); } else if (Dlim != Dlim1) Headditem->Flags = Headditem->Flags | More; } //get PARMDEF Initial_23: /*keylabel*/ Nonstandard(Klabel); D.Flags = Lab + Spec; D.Type = Nulltype; Getidentlist(); goto Term; Initial_24:; /*prefix*/ D.Flags = Subatom; Atom = Nextatom(); Initial_25: /*krange*/ Initial_26:; /*keylong*/ Initial_27: /*keyinteger*/ Initial_28:; /*keyreal*/ Initial_29: /*keystring*/ Initial_30:; /*keyrecord*/ Initial_33:; /*rpred*/ Matched = 0; Gettype(D.Flags); if (A(Keyspec)) { if (A(Left)) { Getlitint(); Get(Right); Declmode = (Declmode & Sizemask) + Absmode; D.Val = T.Val; Getident(); if (D.Flags & Proc) { Speccing = 1; Getparmdef(); } goto Term; } D.Flags = D.Flags + Spec; if (!(D.Flags & Proc)) { Getidentlist(); goto Term; } } if (D.Flags & Proc) { Get(Ident); if (Item >= C.Localdpos && Ditem->Type == D.Type && (Ditem->Flags & Proc) != 0) { if ((Ditem->Flags & Spec) == 0 || (D.Flags & Spec) != 0) { Item = 0; D.Flags = D.Flags + Alt; Declare(); } } else Declare(); if ((D.Flags & Ext) != 0 && A(Alias)) Getlitstring(); if (D.Flags & Spec) { Speccing = 1; Getparmdef(); } else { Openblock(Item); Getparmdef(); C.Parlim = Dlim; Compileentry(); Get(Terminator); Getstatements(End); Closeblock(); } } else if (D.Flags == Typeid) ; else if (D.Flags & Parm) { D.Flags = D.Flags - Parm; if (D.Flags & Static) Getownarraydeclaration(); else { if ((D.Flags & Static) == 0 && C.Flags >= Hadon) { Fault(Ordererr); C.Flags = C.Flags & (~(Hadon + Hadinst)); } Getarraydeclaration(); } } else if (D.Flags == Static) { D.Type = Dict[D.Type & Puretype].Type; if (D.Type == Recy || D.Type == Stringy) D.Type = D.Type + Direct; do { Getident(); if (!Aassop()) Syntaxerror(); Getliteral(D.Type); if (Faultnum == Rangerr + Point) Faultnum = Rangerr + Point + Warn; Dict[Dlim - 1].Val = T.Val; } while (A(Comma)); } else if (D.Flags & Static) { Declmode += Ownmode; do { Getident(); T.Val = 0; if (Aassop()) { Getliteral(D.Type); if (Faultnum == Rangerr + Point) Faultnum = Rangerr + Point + Warn; } Elements = 1; } while (A(Comma)); } else { //dynamic variable if ((D.Flags & Static) == 0 && C.Flags >= Hadon) { Fault(Ordererr); C.Flags = C.Flags & (~(Hadon + Hadinst)); } do { C.Delta = C.Delta - Dsize; if (C.Delta & 1) C.Delta = C.Delta - 1; T.Val = C.Sp + C.Delta; Getident(); if (Aassop()) { Nonstandard(Initass); if (D.Type >= Indirect) { if (Atom != Eqeq) Fault(Caterr + Point); Getreference(D.Type); if (Item) Item += Ad; } else { if (Atom == Eqeq) Fault(Caterr + Point); Getvalue(D.Type); } } } while (A(Comma)); } goto Term; void Getswitchdeclaration(void) { int I; int J; int Dlim1; Matched = 1; do { D.Flags = Lab; D.Type = Nulltype; Declmode = Pcmode + (Wordsize << Sizeshift); Getidentlist(); Dlim1 = Dlim; Getlitbounds(); do { //For each ident in group if (Spc - Elements <= 0) break; //ignore if too many for (I = 1; I <= Elements; I++) { Spc--; Final[Spc] = 0; } Dict[Dlim0].Val = Spc; Dict[Dlim0].Type = Item; Dlim0++; } while (Dlim0 != Dlim1); } while (A(Comma)); } Initial_37:; /*keyswitch*/ Getswitchdeclaration(); goto Term; //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //!!!!!!!!!!!!!! Control statements !!!!!!!!!!!!!!!!!!!!!!!!!!! //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // Initial_42:; /*keycontrol*/ Getlitint(); if (!T.Val) Control = 0; Control = Control ^ T.Val; goto Term; Initial_45:; /*include*/ Getlitstring(); Extra.Name = _imp_str_literal(""); while (T.Val > 0) { Extra.Name = _imp_join(Extra.Name, Tostring(*Byteinteger(Atomp))); Atomp++; T.Val = T.Val - 1; } Curlim = Extra.Lim2; Get(Terminator); if (!Faultnum) { Connectedfile(&Extra); // <--- load %include file? if (Extra.Flag) { Nonstop = -999; fprintf(stderr, "%%SIGNAL 12 at line %d\n", __LINE__); _imp_signal(12, 0, 0, _imp_str_literal("")); } Mainfp = Fp; Mainline = Line; Line = 0; Sym = '\n'; Fp = Extra.Start2; Curstart = Fp; Curlim = Extra.Lim2; Modesym = '&'; Nonstop++; } goto Next; Initial_41:; /*keylist*/ goto Term; Initial_5:; /*begin*/ C.Sp = -8; Get(Terminator); Openblock(0); Getstatements(0); Closeblock(); if (Stopper >= 0) goto Term; return; Initial_1:; /*end*/ if (!A(Of)) { if (Stopper == Else || Stopper == Finish) Fault(Nofinish); if (Stopper == Repeat) Fault(Norepeat); if (Stopper >= 0) return; Fault(Nobegin); goto Term; } if (A(Keylist)) goto Term; if (A(Keyfile)) { /* dangling-else ambiguity fixed here manually */ if (Curlim == Extra.Lim2) { Switchinput(); goto Next; } } else Get(Program); } //GET STATEMENTS void Init(int T, int L, int H) { D.Flags = Typeid; D.Type = T; D.Low = L; D.Val = H; Dict[Dlim] = D; Dlim++; } // Ex-bedded static initializers: Control = Warnbit + Nonsbit; Free = Allregs; Dictshown = Dictmin; Litpos = Litmin; Slitpos = Litmax; Dlim = Trueconst + 1; Permlim = Dictmin; Dmin = Dictmax - 1; Explo = Expmax + 1; Oldexplo = Expmax + 1; Curlab = Lab1; Level = Outerlevel; Ownad = Ownbase; Spc = Finalbound; if (_imp_on_event(12)) { _reset: if (_imp_on_event(12)) goto _reset; /* reset for next time, although this would cause a problem if %signal 12 raised in this block! */ //fprintf(stderr, "%%ON %%EVENT 12 at line %d\n", __LINE__); if (Fp == Main->Lim2) goto Printout; if (Main->Flag < 0 || Nonstop == -999) goto Ended; //abandon or CROAK Change = Main->Change; } Printstring(_imp_str_literal(" IMP Checker ")); Newline(); for (I = 0; I <= 255; I++) Hashindex[I] = 0; //hash table empty Charbase = Addr(Char[0]); *Byteinteger(Charbase) = 0; //for anon ident Charlim = Charbase + 1; Charmin = Charlim + Charbound; //(1 over top) for (I = D0; I <= Labmax; I++) Dict[I].Val = 0; D.Flags = Typeid; D.Low = Minint; D.Val = Maxint; Dmin = Dictmax - 1; Dlim = Dictmin; do { D.Type = Dlim; Dict[Dlim] = D; Dlim++; } while (Dlim <= Booltype); D.Flags = 0; Init(Booltype, 0, 0); Init(Booltype, 0, 1); D.Flags = Typeid; Init(Inty, Minint, Maxint); Init(Inty, -32768, 32767); Init(Inty, 0, 65535); Init(Inty, 0, 255); Init(Inty, -128, 127); Init(Inty, 0, 1); Init(Inty, Minint, Maxint); Init(Realy, Minint, Maxint); Init(Realy, Minint, Maxint); C = (Blockinf){0}; C.Localdpos = Dlim; C.Parlim = Dlim; Level = Outerlevel; Spc = Finalbound; Faults = 0; Line = 0; Mainline = 0; // Mainfp = Main->Start1; Extra.Name = Permfile; Connectedfile(&Extra); // <--- load ECCE_PERM if (Extra.Flag) { Nonstop = -999; fprintf(stderr, "%%SIGNAL 12 at line %d\n", __LINE__); _imp_signal(12, 0, 0, _imp_str_literal("")); } Fp = Extra.Start2; Curstart = Fp; Curlim = Extra.Lim2; Nonstop = -2; if (Main->Flag == 'I') Nonstop = -1; Sym = '\n'; Getstatements(-1); Printout:; if (!Faults) { Write(Statements, 1); Printstring(_imp_str_literal(" statements checked ")); } else { Write(Faults, 1); Printstring(_imp_str_literal(" fault")); if (Faults > 1) Putsym('s'); Printstring(_imp_str_literal(" reported ")); } Newline(); Ended:; Newline(); //*for now to ensure message not erased* } //of ECCECI #ifdef EDITOR_SUPPORT void Edi(Edfile *Main, Edfile *Sec, _imp_string Message) { /* This is the procedure used to call the editor itself. MAIN identifies the file being edited and SEC any secondary input file supplied at the outset (a dummy edfile record set to zero will suffice if not relevant). Message provides text to be printed at the bottom of the screen at the outset. Apart from the fields set up by CONNECT EDFILE (and subsequently modified by the editor or, compatibly, by other programs), the following fields are relevant: FP : the current position in the file, which must always satisfy either START1 <= FP < LIM1 or START2 <= FP <= LIM2 LINE : the line number of the current line (if known) If zero, the editor will establish the line number afresh On return from the editor, any of the pointer values may have changed and the field CHANGE will identify the earliest position in the file modified during the last edit. LIM1 is guaranteed to co-incide with a line break. (Programs which cannot cope with a file split in two, even at a guaranteed line break, are free to consolidate the file by copying part 1 DOWN to be adjacent to part2 and adjusting all pointers accordingly). FLAG will be negative if the user has abandoned the edit. */ } #endif void Connectedfile(Edfile *F) { // CONNECT EDFILE - Load included file F->Name here? /* This routine is used to connect (ie read into store) a file to be edited. Before the call, the field NAME should be set to the name of the file, and the field FLAG should be set to the number of extra bytes to be allowed for expansion (32k is a typical figure). On successful return, the file specified will have been read into store at a system-selected position, the field LIM1 will be equal to START1, and the fields START2 and LIM2 will delimit the whole of the file. The fields LINE, CHANGE and FLAG will be zero. If FLAG is non-zero, this indicates a failure to connect; a report will already have been made. */ char buff[1000000]; // space on stack large enough for file. FILE *src = fopen(F->Name.cstr.s, "r"); int i, size = 0; if (src == NULL) { F->Flag = errno; fprintf(stderr, "chimps: %s - %s\n", F->Name.cstr.s, strerror(errno)); return; } for (;;) { int c = fgetc(src); if (c == EOF) break; buff[size++] = c&255; } // Now we know the size, transfer from stack to heap. F->Start1 = (int)malloc(size+2)+1; *(char *)(F->Start1-1) = '\n'; // add an extra NL before and after buffer (for Ecce to bounce off) for (i = 0; i < size; i++) *(char *)(F->Start1+i) = buff[i]; *(char *)(F->Start1+size) = '\n'; F->Lbeg = F->Start1; F->Lim1 = F->Start1+size; F->Lim = F->Lim1; F->Fp = F->Start1; F->Start2 = F->Lim1; F->Lim2 = F->Lim1; //fprintf(stderr, "Checking %s - %d bytes from %d to %d\n", F->Name.cstr.s, size, F->Start1, F->Lim1); /* F->Change; F->Flag; F->Line; F->Diff; F->Shift; F->Top; F->Win; F->Bot; F->Min; F->Row; F->Col; */ } void Disconnectedfile(Edfile *F) { // DISCONNECT EDFILE - Unstack? /* This routine is used to close off an edited file. It is particularly important to ensure that this procedure is called in all cases, even if the associated program is being abandoned, since otherwise changes made to the file are all lost. On return, NAME will indicate the name under which the file was actually written (maybe different from that originally specified). */ free((char *)(F->Start1-1)); } int _imp_mainep(int _imp_argc, char **_imp_argv) { Edfile Source = { 0 }; if (_imp_argc != 2) { fprintf(stderr, "syntax: chimps file.imp\n"); exit(1); } Source.Name = _imp_c2istr(_imp_argv[1]); Connectedfile(&Source); if (Source.Flag) { exit(Source.Flag); } Ecceci(&Source); Disconnectedfile(&Source); exit(0); }