[
  {
    "path": ".gitignore",
    "content": ".idea\n*.tmp\ndocs\n*.exe\nsrc/*_fixed.s\n"
  },
  {
    "path": "Makefile",
    "content": "CC = gcc\nCFLAGS =-Wno-implicit-int -Wno-int-conversion -m32\n\nc0_src = $(wildcard src/c0*.c)\nc1_src = $(wildcard src/c1*.c)\n\nc1_tabs = $(wildcard src/*tab.s)\nc1_tabs_fixed = $(c1_tabs:%tab.s=%tab_fixed.s)\n\nall: c0 c1\n\nc0: $(c0_src) src/c0.h\n\t$(CC) $(CFLAGS) -o c0 $(c0_src)\n\nc1: $(c1_src) $(c1_tabs_fixed) src/c1.h\n\t$(CC) $(CFLAGS) -o c1 $(c1_src) $(c1_tabs_fixed)\n\ncvopt: src/cvopt.c\n\t$(CC) $(CFLAGS) -o cvopt src/cvopt.c\n\n%tab_fixed.s: %tab.s cvopt\n\t./fix_tab.sh $< > $@\n\n"
  },
  {
    "path": "README.md",
    "content": "# first-cc-gcc\nA port of the [earliest C compiler](https://www.bell-labs.com/usr/dmr/www/primevalC.html) to modern GCC. The compiler outputs PDP-11 assembly code that can be compiled and run on a PDP-11 emulator (check out [c72](https://github.com/vegesm/c72) if you want x86 code that runs on current Linux). The compiler runs only in 32 bit mode as the original code assumes that the pointer size and word size are the same.\n\n## Usage\nTo compile the compiler and run it simply do:\n```shell\nmake\n./cc examples/fizzbuzz.c > fizzbuzz.s\n```\nNote: if you get errors on missing \"bits/libc-header-start.h\" headers make sure you have the 32bit libc installed.\n\n### Emulator\nThe hard part is to set up an emulator, transfer the file to it(!) and run the assembler. A very [early UNIX implementation](https://github.com/qrush/unix) based on SIMH is available. For Windows, there is also a [pre-built binary](http://sourceforge.net/project/downloading.php?group_id=204974&filename=Research-unixv1-0.3.exe&a=25520957)\n\nI could not get the tape emulators working so ended up with a hacky solution to transfer files. The simulator lets you to log in via telnet, so the files are copied by starting up a text editor on the simulator and streaming the characters into it and then saving and closing the file.\n\nAlso, if you close the connection the session is lost, so it is important to keep the connection to the \nsimulator alive with a hack using ncat.\n```shell\n# Start emulator\npdp11 simh.cfg\n# Open a pipe to the simulator\n# If you use the prebuilt Windows simulator, use port 12323\nncat -lk -p 5556 | ncat localhost 5555\n\n# send login username to emulator\necho root | emulator/emucat\n# copy file over by typing it into ed\nemulator/cpfile fizzbuzz.s /fizzbz.s \n# call assembler and linker\nemulator/emucc /fizzbz.s \n# execute the compiled program\necho a.out | emulator/emucat\n```\n\nNote that the file is called `fizzbz.s` on the emulator. This is because the UNIX used here handles 8 character long filenames only!\n\n## Old C features \n\nThis version of C is from around 1972. While the general syntax is pretty much the same as today,\nthere are tons of missing features:\n- no preprocessor, no for loops\n- even though there is a keyword for `float` and `double`, floating point calculations are not implemented, you can not even write a floating point literal\n- the type system is very weak: pointers, chars, ints can be freely converted into one another\n- types of the function parameters are not checked, anything can be passed to any function\n- compound assignment operators are reversed, they are `=+`, `=*`\n- only integer global variables can be defined, and the syntax is strange (see helloworld example)\n- variable names can be of any length but only the first 8 characters are used; i.e. deadbeef1 and deadbeef2 are effectively the same variables\n  \n\nInterestingly, some features that were already existing in this early version:\n- function pointers\n- the ABI is nearly the same as today's 32 bit ABI\n- `a[b]` is implemented as `*(a+b)`\n\n"
  },
  {
    "path": "cc",
    "content": "#!/bin/sh\n\nBUILD_FOLDER=.\n$BUILD_FOLDER/c0 $1 $1.tmp\n$BUILD_FOLDER/c1 $1.tmp |  tr -d '\\r'"
  },
  {
    "path": "emulator/cpfile",
    "content": "#!/bin/bash\n\necho rm $2 | emulator/emucat\necho ed $2 | emulator/emucat\necho a | emulator/emucat\n# slow down transfer to prevent dropping characters\ncat $1 | (lines=0; while read line; do echo $line; if [ $((++lines % 5)) -eq 0 ]; then sleep 1; fi; done) | emulator/emucat\necho | emulator/emucat\necho . | emulator/emucat\necho w | emulator/emucat\necho q | emulator/emucat"
  },
  {
    "path": "emulator/emucat",
    "content": "#!/bin/bash\nncat localhost 5556"
  },
  {
    "path": "emulator/emucc",
    "content": "#!/bin/bash\n\necho as -u $1 | emulator/emucat\nNAME=`basename $1 .s`\necho mv a.out $NAME.o | emulator/emucat\necho ld /usr/lib/crt0.o $NAME.o -lc -l | emulator/emucat"
  },
  {
    "path": "examples/fizzbuzz.c",
    "content": "main() {\n    auto n,i;\n    n = 20;\n\n    i = 1;  /* no for loops */\n    while (i <= n) {\n        if (i % 15 == 0) {\n            printf(\"fizzbuzz\\n\");\n        } else if (i % 3 == 0) {\n            printf(\"fizz\\n\");\n        } else if (i % 5 == 0) {\n            printf(\"buzz\\n\");\n        } else {\n            printf(\"%d\\n\", i);\n        }\n        i++;\n    }\n\n}"
  },
  {
    "path": "examples/helloworld.c",
    "content": "main() {\n    extern printf;\n    printf(\"Hello world!\\n\");\n    printf(\"%d\\n\", 4);\n}\n\nglobint 4;\nglobarr[] 1, 2, 3;"
  },
  {
    "path": "fix_tab.sh",
    "content": "#!/bin/sh\n\nUNDERSCORE=_\nif [ \"$(expr substr $(uname -s) 1 5)\" = \"Linux\" ]; then\n\tUNDERSCORE=\nfi\n\n# convert original asm listing and remove comments\ncat $1  | ./cvopt  | sed 's|/.*||g'  | \\\n\t# convert the lookup table at the start to use .int directives\n\tsed -r 's/([0-9]+)\\.;[[:blank:]]+([A-Za-z0-9]+)/.int \\1, \\2/g' | \\\n\t# replace .even directive with .balign, replace first row of the lookup table\n\tsed 's/\\.even/.balign 4/g' | sed -r 's/_(eff|reg|sp|cc)tab=\\.;[[:blank:]]*\\.\\+2/_\\1tab:.int .,.+4/g'  | \\\n\t# replace single `0` characters with .int directive\n\tsed -r 's/^([[:blank:]]+)0$/\\1.int 0/g' | \\\n\t# remove leading underscore on linux\n\tsed -r 's/_(eff|reg|sp|cc)tab/'$UNDERSCORE'\\1tab/'\n"
  },
  {
    "path": "src/c0.h",
    "content": "#include <stdio.h>\n#include \"config.h\"\n//#define DEBUG\n\n/* c00.c */\nsetup();\ninit(char[], int);\nint *lookup();\nsymbol();\nsubseq(int,int,int);\ngetstr();\ngetcc();\nmapch(int);\ntree();\nvoid declare(int);\n\n/* c01.c */\nvoid build(int);\nint *convert(int[], int, int, int);\nchkw(int[]);\nlintyp(int);\nerror(char[]);\nerror1(char[],int);\nerror2(char[],int,int);\nint *block(int, ...);\nchklval(int[]);\nnotcompat(int, int);\nmax(int, int);\n\n/* c02.c */\nfunction(char[]);\nvoid extdef();\nvoid statement();\npexpr();\npswitch();\nblkhed();\nblkend();\nerrflush(int);\ndeclist();\neasystmt();\nbranch(int);\n\n/* c03.c */\njumpc(int[], int, int);\nrcexpr(int[], int);\njump(int);\nlabel(int);\nretseq();\nslabel();\nvoid setstk(int);\ndefvec();\ndefstat(int[]);\n\nlength(int);\nrlength(int);\nputwrd(int);\nprintn(int,int);\nvoid cc_printf(char[], ...);\ncc_putchar(int);\n\n/* globals */\nextern ossiz;\nextern ospace[];\nextern regtab;\nextern efftab;\nextern cctab;\nextern sptab;\nextern symbuf[];\nextern pssiz;\nextern namsiz;\nextern nwps;\nextern hshused;\nextern hshsiz;\nextern hshlen;\nextern hshtab[];\nextern *space;\nextern *cp;\nextern cmsiz;\nextern cmst[];\nextern ctyp;\nextern isn;\nextern swsiz;\nextern swtab[];\nextern *swp;\nextern contlab;\nextern brklab;\nextern deflab;\nextern nreg;\nextern maprel[];\nextern nauto;\nextern stack;\nextern peeksym;\nextern peekc;\nextern eof;\nextern line;\nextern int *csym;\nextern cval;\nextern ncpw;\nextern nerror;\nextern FILE *fout;\nextern int *paraml;\nextern int *parame;\nextern tmpfil;\n\n/* code tables */\nextern char ctab[];\nextern int opdope[];\nextern int cvtab[];\n#define printf cc_printf\n#define putchar cc_putchar\n"
  },
  {
    "path": "src/c00.c",
    "content": "/* C compiler\n\nCopyright 1972 Bell Telephone Laboratories, Inc.\n\n*/\n\n#include \"c0.h\"\n#include <stdlib.h>\n\nossiz = 250;\nint ospace[250];\t/* fake */\n\n/*\n * Adds the string s with id t to the hash table.\n */\ninit(s, t)\nchar s[]; {\n\tchar *sp;\n\tint *np, i;\n\n\t/* copy s to symbuf */\n\ti = namsiz;\n\tsp = symbuf;\n\twhile(i--)\n\t\tif ((*sp++ = *s++)=='\\0') --s;\n\tnp = lookup();\n\t*np++ = 1;\n\t*np = t;\n}\n\n/*\n * First pass of the C compiler. It parses the input and generates an intermediate(?) output,\n * containing parsed expression trees with some additional assembly code.\n *\n * Short overview: the compiler parses global elements, which can be either functions or\n * global variable declarations. In functions, each expression is parsed into a tree, which is stored\n * in ospace. Interestingly, the next pass of the compiler is expected to be loaded at the same location as this pass.\n * So, the child node pointers in the tree are simply saved directly in the output and are expected to be loaded\n * back at the same memory location.\n *\n * The tree parser also does a rough estimation of how many registers are needed for calculating a tree\n * using the Sethi-Ullman algorithm. Additionally, sides of a binary operation can be flipped such that\n * the more difficult subtree comes first. See the C compiler tour in the UNIX manual.\n */\nmain(argc, argv)\nchar *argv[]; {\n\tif(argc<3) {\n\t\terror(\"Arg count\");\n\t\texit(1);\n\t}\n\tif(freopen(argv[1], \"r\", stdin)==NULL) {\n\t\terror1(\"Can't find %s\", argv[1]);\n\t\texit(1);\n\t}\n\tif((fout=fopen(argv[2], \"wb\"))==NULL) {\n\t\terror1(\"Can't create %s\", argv[2]);\n\t\texit(1);\n\t}\n\n\tinit(\"int\", 0);\n\tinit(\"char\", 1);\n\tinit(\"float\", 2);\n\tinit(\"double\", 3);\n/*\tinit(\"long\", 4);  */\n\tinit(\"auto\", 5);\n\tinit(\"extern\", 6);\n\tinit(\"static\", 7);\n\tinit(\"goto\", 10);\n\tinit(\"return\", 11);\n\tinit(\"if\", 12);\n\tinit(\"while\", 13);\n\tinit(\"else\", 14);\n\tinit(\"switch\", 15);\n\tinit(\"case\", 16);\n\tinit(\"break\", 17);\n\tinit(\"continue\", 18);\n\tinit(\"do\", 19);\n\tinit(\"default\", 20);\n\twhile(!eof) {\n\t\textdef();\n\t\tblkend();\n\t}\n\tfflush(stdout);\n\n\texit(nerror!=0);\n}\n\n/*\n * Looks up an element in the hash table. The key is in symbuf.\n * Returns a pointer to the 4 word long data section.\n * Following these 4 words, another 4 words contain the key.\n */\nint *lookup() {\n\tauto i, j, *np, *sp, *rp;\n\n\ti = 0;\n\tsp = symbuf;\n\tj = nwps;\n\twhile(j--)\n\t\ti += *sp++;\n\tif (i<0) i = -i;\n\ti %= hshsiz;  /* the hash of symbuf */\n\n\ti *= pssiz;\n\twhile(*(np = &hshtab[i+4])) {\n\t\tsp = symbuf;\n\t\tj = nwps;\n\t\twhile(j--)\n\t\t\tif (*np++ != *sp++) goto no;  /* key does not match, go to next one */\n\t\treturn(&hshtab[i]);\nno:\t\tif ((i += pssiz) >= hshlen) i = 0;\n\t}\n\n\t/* not found, add new element */\n\tif(hshused++ > hshsiz) {\n\t\terror(\"Symbol table overflow\");\n\t\texit(1);\n\t}\n\trp = np = &hshtab[i];\n\tsp = symbuf;\n\tj = 4;\n\twhile(j--)  /* clear out data */\n\t\t*np++ = 0;\n\tj = nwps;\n\twhile(j--) /* copy key into &hshtab[i+4] */\n\t\t*np++ = *sp++;\n\treturn(rp);\n}\n\n/*\n * The lexer, returns the opcode of the next symbol. If the caller does not want to use the symbol,\n * it can \"push it back\" using the peeksym global variable.\n *\n * The return value is the opcode of the current symbol. See c0t.c for the mapping between\n * the symbols and numbers.\n * If the current symbol is a number/character literal, the cval variable is set to the numeric value.\n * If the current symbol is a string, cval contains its label.\n * If the current symbol is a keyword, cval contains its id.\n * If the current symbol is a name, csym will point to the corresponding entry in the hashtable.\n * See csym comments at the bottom for its contents.\n */\nsymbol() {\n\tauto b, c;\n\tchar *sp;\n\n\tif (peeksym>=0) {  /* if we have a peeked symbol, return that */\n\t\tc = peeksym;\n\t\tpeeksym = -1;\n\t\treturn(c);\n\t}\n\tif (peekc) {  /* use peeked character, if has one */\n\t\tc = peekc;\n\t\tpeekc = 0;\n\t} else\n\t\tif (eof)\n\t\t\treturn(0); else\n\t\t\tc = getchar();\nloop:\n\tswitch(ctab[c]) {\n\n\tcase 125:\t/* newline */\n\t\tline++;\n\n\tcase 126:\t/* white space */\n\t\tc = getchar();\n\t\tgoto loop;\n\n\tcase 0:\t\t/* EOF */\n\t\teof++;\n\t\treturn(0);\n\n\tcase 40:\t/* + */\n\t\treturn(subseq(c,40,30));\n\n\tcase 41:\t/* - */\n\t\treturn(subseq(c,41,31));\n\n\tcase 80:\t/* = */\n\t\tif (subseq(' ',0,1)) return(80);\n\t\tc = symbol();\n\t\tif (c>=40 & c<=49)  /* c is binary operator */\n\t\t\treturn(c+30);\n\t\tif (c==80)   /* = */\n\t\t\treturn(60);\n\t\tpeeksym = c;\n\t\treturn(80);\n\n\tcase 63:\t/* < */\n\t\tif (subseq(c,0,1)) return(46);\n\t\treturn(subseq('=',63,62));\n\n\tcase 65:\t/* > */\n\t\tif (subseq(c,0,1)) return(45);\n\t\treturn(subseq('=',65,64));\n\n\tcase 34:\t/* ! */\n\t\treturn(subseq('=',34,61));\n\n\tcase 43:\t/* / */\n\t\tif (subseq('*',1,0))\n\t\t\treturn(43);\ncom:\n        /* inside a comment */\n\t\tc = getchar();\ncom1:\n\t\tif (c=='\\0') {\n\t\t\teof++;\n\t\t\terror(\"Nonterminated comment\");\n\t\t\treturn(0);\n\t\t}\n\t\tif (c=='\\n')\n\t\t\tline++;\n\t\tif (c!='*')\n\t\t\tgoto com;\n\t\tc = getchar();\n\t\tif (c!='/')\n\t\t\tgoto com1;\n\t\tc = getchar();\n\t\tgoto loop;\n\n\tcase 124:\t/* number */\n\t\tcval = 0;\n\t\tif (c=='0')\n\t\t\tb = 8; else\n\t\t\tb = 10;\n\t\twhile(ctab[c]==124) {\n\t\t\tcval = cval*b + c -'0';\n\t\t\tc = getchar();\n\t\t}\n\t\tpeekc = c;\n\t\treturn(21);\n\n\tcase 122:\t/* \" */\n\t\treturn(getstr());\n\n\tcase 121:\t/* ' */\n\t\treturn(getcc());\n\n\tcase 123:\t/* letter */\n\t\tsp = symbuf;\n\t\twhile(ctab[c]==123 | ctab[c]==124) {  /* while c is alphanumeric */\n\t\t\tif (sp<((char *)symbuf)+namsiz) *sp++ = c;\n\t\t\tc = getchar();\n\t\t}\n\t\twhile(sp<((char *)symbuf)+namsiz)\n\t\t\t*sp++ = '\\0';\n\t\tpeekc = c;\n\t\tcsym = lookup();  /* find in hashtable */\n\t\tif (csym[0]==1) {\t/* keyword */\n\t\t\tcval = csym[1];\n\t\t\treturn(19);\n\t\t}\n\t\treturn(20);\n\n\tcase 127:\t/* unknown */\n\t\terror(\"Unknown character\");\n\t\tc = getchar();\n\t\tgoto loop;\n\n\t}\n\treturn(ctab[c]);\n}\n\n/*\n * Peeks at the next char and if it is c then eats it and returns b, otherwise returns a.\n * Useful for two character symbols, e.g. distinguish between ! and =\n * call subseq('=', note_equal_code, logical_not_code).\n */\nsubseq(c,a,b) {\n\tif (!peekc)\n\t\tpeekc = getchar();\n\tif (peekc != c)\n\t\treturn(a);\n\tpeekc = 0;\n\treturn(b);\n}\n\n/*\n * Gets a string. It assumes the opening quotation mark has been already processed.\n */\ngetstr() {\n\tauto c;\n\n\tprintf(\".data;l%d:.byte \", cval=isn++);\n\twhile((c=mapch('\"')) >= 0)\n\t\tprintf(\"%o,\", c);\n\tprintf(\"0;.even;.text\\n\");\n\treturn(22);\n}\n\n/*\n * Reads a character literal. Assumes opening ' has been read already.\n */\ngetcc()\n{\n\tauto c, cc;\n\tchar *cp;\n\n\tcval = 0;\n\tcp = &cval;\n\tcc = 0;\n\twhile((c=mapch('\\'')) >= 0)\n\t\tif(cc++ < ncpw)\n\t\t\t*cp++ = c;\n\tif(cc>ncpw)\n\t\terror(\"Long character constant\");\n\treturn(21);\n}\n\n\n/*\n * Processes a character from a string/character literal. c contains the delimiter char.\n * This function handles mapping of escape sequences.\n */\nmapch(c)\n{\n\tauto a;\n\n\tif((a=getchar())==c)\n\t\treturn(-1);\n\tswitch(a) {\n\n\tcase '\\n':\n\tcase 0:\n\t\terror(\"Nonterminated string\");\n\t\tpeekc = a;\n\t\treturn(-1);\n\n\tcase '\\\\':\n\t\tswitch (a=getchar()) {\n\n\t\tcase 't':\n\t\t\treturn('\\t');\n\n\t\tcase 'n':\n\t\t\treturn('\\n');\n\n\t\tcase '0':\n\t\t\treturn('\\0');\n\n\t\tcase 'r':\n\t\t\treturn('\\r');\n\n\t\tcase '\\n':\n\t\t\tline++;\n\t\t\treturn('\\n');\n\t\t}\n\n\t}\n\treturn(a);\n}\n\n/*\n * Builds an expression tree. The outline of the algorithm:\n * There are three stacks:\n * cmst - tree node stack, contains the partially built parts of the expression tree.\n * opst - operator stack, contains the ids of the operators. The bottom element is the EOF operator\n * prst - precedence stack, contains the precedences of operators. Note that the precedence stack only contains\n * element, if the precedence has increased, so it is not in one-to-one correspondence with opst.\n *\n * The algorithm goes over the operator produced by the symbol function. Leaf nodes (numbers,\n * string/char literals, names) are placed on the node stack. If an operator is encountered,\n * it is placed on the operator stack if its precedence is higher than the current precedence.\n * Otherwise, the operator and tree node stack is unwinded by building partial subtrees,\n * until the top of the prst is smaller than current operator's precedence.\n */\ntree() {\n\tauto *op, opst[20], *pp, prst[20], andflg, o,\n\t\tp, ps, os;\n\n\tspace = ospace;\n\top = opst;  /* top of operator stack */\n\tpp = prst;  /* top of precedence stack */\n\tcp = cmst;  /* top of tree node stack */\n\t*op = 200;\t\t/* stack EOF */\n\t*pp = 06;\n\tandflg = 0;\n\nadvanc:\n\tswitch (o=symbol()) {\n\n\t/* name */\n\tcase 20:\n\t\tif (*csym==0)  /* storage not yet decided */\n\t\t\tif((peeksym=symbol())==6)  /* (, mark function calls as extern */\n\t\t\t\t*csym = 6;\t/* extern */\n\t\t\telse {\n\t\t\t\tif(csym[2]==0)\t/* unseen so far */\n\t\t\t\t\tcsym[2] = isn++;\n\t\t\t}\n        if(*csym==6)\t/* extern */\n            *cp++ = block(5,20,csym[1],0,*csym,\n                csym[4],csym[5],csym[6],csym[7]);\n        else\n            *cp++ = block(2,20,csym[1],0,*csym,csym[2]);\n\t\tgoto tand;\n\n\t/* short constant */\n\tcase 21:\n\tcase21:\n\t\t*cp++ = block(1,21,ctyp,0,cval);  /* ctyp is always 0 */\n\t\tgoto tand;\n\n\t/* string constant */\n\tcase 22:\n\t\t*cp++ = block(1,22,17,0,cval);  /* 17 is char[] */\n\ntand:\n\t\tif(cp>=cmst+cmsiz) {\n\t\t\terror(\"Expression overflow\");\n\t\t\texit(1);\n\t\t}\n\t\tif (andflg)\n\t\t\tgoto syntax;\n\t\tandflg = 1;\n\t\tgoto advanc;\n\n\t/* ++, -- */\n\tcase 30:\n\tcase 31:\n\t\tif (andflg)  /* convert to postfix */\n\t\t\to += 2;\n\t\tgoto oponst;\n\n\t/* ! */\n\tcase 34:\n\t\tif (andflg)\n\t\t\tgoto syntax;\n\t\tgoto oponst;\n\n\t/* - */\n\tcase 41:\n\t\tif (!andflg) {\n\t\t\tpeeksym = symbol();\n\t\t\tif (peeksym==21) {  /* negative literal */\n\t\t\t\tpeeksym = -1;\n\t\t\t\tcval = -cval;\n\t\t\t\tgoto case21;\n\t\t\t}\n\t\t\to = 37;\n\t\t}\n\t\tandflg = 0;\n\t\tgoto oponst;\n\n\t/* & */\n\t/* * */\n\tcase 47:\n\tcase 42:\n\t\tif (andflg)\n\t\t\tandflg = 0; else\n\t\t\tif(o==47)\n\t\t\t\to = 35;\n\t\t\telse\n\t\t\t\to = 36;\n\t\tgoto oponst;\n\n\t/* ( */\n\tcase 6:\n\t\tif (andflg) {\n\t\t    /* this is a function call */\n\t\t\to = symbol();\n\t\t\tif (o==7)  /* ) */\n\t\t\t\to = 101; else {  /* 101 - call without args */\n\t\t\t\tpeeksym = o;\n\t\t\t\to = 100;\n\t\t\t\tandflg = 0;\n\t\t\t}\n\t\t}\n\tgoto oponst;\n\n\t/* ) */\n\t/* ] */\n\tcase 5:\n\tcase 7:\n\t\tif (!andflg)\n\t\t\tgoto syntax;\n\t\tgoto oponst;\n\t}\n\n\t/* binary operators */\n\tif (!andflg)\n\t\tgoto syntax;\n\tandflg = 0;\n\noponst:  /* place operator on stack */\n\tp = (opdope[o]>>9) & 077;  /* extract operator precedence */\nopon1:\n\tps = *pp;  /* currently highest precedence */\n\tif (p>ps | p==ps & (opdope[o]&0200)!=0) { /* right-assoc */\nputin:\n\t\tswitch (o) {\n\n\t\tcase 6: /* ( */\n\t\tcase 4: /* [ */\n\t\tcase 100: /* call */\n\t\t\tp = 04;\n\t\t}\n\t\tif(op>=opst+20) {\t\t/* 20 is the size of opstack */\n\t\t\terror(\"expression overflow\");\n\t\t\texit(1);\n\t\t}\n\t\t*++op = o;\n\t\t*++pp = p;\n\t\tgoto advanc;\n\t}\n\t--pp;  /* pop precedence stack */\n\tswitch (os = *op--) {\n\n\t/* EOF */\n\tcase 200:\n\t\tpeeksym = o;\n\t\treturn(*--cp);\n\n\t/* call */\n\tcase 100:\n\t\tif (o!=7)  /* unmatching parenthesis */\n\t\t\tgoto syntax;\n\t\tbuild(os);\n\t\tgoto advanc;\n\n\t/* mcall */\n\tcase 101:\n\t\t*cp++ = 0;\t\t/* 0 arg call */\n\t\tos = 100;\n\t\tgoto fbuild;\n\n\t/* ( */\n\tcase 6:\n\t\tif (o!=7)  /* unmatching parenthesis */\n\t\t\tgoto syntax;\n\t\tgoto advanc;\n\n\t/* [ */\n\tcase 4:\n\t\tif (o!=5)\n\t\t\tgoto syntax;\n\t\tbuild(4);\n\t\tgoto advanc;\n\t}\nfbuild:\n\tbuild(os);\n\tgoto opon1;  /* unwinds precedence stack till at the same level as o */\n\nsyntax:\n\terror(\"Expression syntax\");\n\terrflush(o);\n\treturn(0);\n}\n\n/*\n * Processes a variable declaration, the preceding type/storage keyword has been processed already.\n * kw - the id of the preceding type/storage keyword, 8 for function parameter list.\n */\nvoid declare(kw) {\n\tint o;\n\n\twhile((o=symbol())==20) {\t\t/* name */\n\t\tif(kw>=5) {\t\t\t/* type or storage location keyword? */\n\t\t\tif(*csym>0)\n\t\t\t\terror1(\"%p redeclared\", &csym[4]);  /* storage area redeclared */\n\t\t\t*csym = kw;\n\t\t} else {\n\t\t\tif ((csym[1]&017)!=0)  /* type already defined, adding pointer behavior is allowed */\n\t\t\t\terror1(\"%p redeclared\", &csym[4]);\n\t\t\tcsym[1] |= csym[1]&0760 | kw;  // set kw to lower 4 bits\n\t\t\tif (*csym==0)\n\t\t\t\t*csym = -2;\n\t\t}\n\t\t/* add pointer indirection */\n\t\twhile((o=symbol())==4) {\t/* [ */\n\t\t\tif((o=symbol())==21) {\t/* const */\n\t\t\t\tif(csym[1]>=020)\n\t\t\t\t\terror(\"Bad vector\");\n\t\t\t\tcsym[3] = cval;\n\t\t\t\to = symbol();\n\t\t\t}\n\t\t\tif (o!=5)\t\t/* ] */\n\t\t\t\tgoto syntax;\n\t\t\tcsym[1] += 020;\n\t\t}\n\t\tif(kw==8)  {\t\t/* parameter */\n\t\t\t*csym = -1;\n\t\t\tif (paraml==0) /* paraml points to the first element in the parameter list */\n\t\t\t\tparaml = csym;\n\t\t\telse\n\t\t\t\t*parame = csym;  /* set previous parameter's first word to point to the current parameter */\n\t\t\tparame = csym;\n\t\t}\n\t\tif (o!=9)\t/* , */\n\t\t\tbreak;\n\t}\n\tif(o==1 & kw!=8 | o==7 & kw==8)  /* not parameter list and ; or parameter list and ) */\n\t\treturn;\nsyntax:\n\terror(\"Declaration syntax\");\n\terrflush(o);\n}\n\n/* constants for code generator tables */\nregtab = 0;\nefftab = 1;\ncctab = 2;\nsptab = 3;\n\n/* hash table */\nsymbuf[2];  /* buffer for the key to look up in has table. 8 byte long, should be 8/sizeof(int); original value was 4 */\npssiz = 8;  /* size of an entry in the hashtable,  should be 4 + nwps */\nnamsiz = 8;  /* maximum length of the key in bytes */\nnwps = 2;  /* number of words per symbuf - originally 4 */\nhshused = 0;  /* number of elements in the hash table */\nhshsiz= 100;  /* maximum number of elements in the table */\nhshlen =800;\t/* size of the table in word, equals to pssiz*hshsiz */\nhshtab[800];  /* The hash table for symbols. For eahc entry, the first 4 bytes are the data, the next 4 bytes are the key. */\n\nint *space= 0;\nint *cp= 0;  /* top of the cmst stack */\ncmsiz= 40;  /* size of the cmst stack */\ncmst[40];  /* the tree node stack, contains pointers to the nodes*/\nctyp = 0; /* id of the int type, constant */\nisn = 1;  /* current label number */\nswsiz = 120;\nswtab[120];\nint *swp = 0;\ncontlab = 0;  /* label for a continue statement in the current loop */\nbrklab = 0;   /* label for a break statement in the current loop */\ndeflab = 0;   /* label for a deafult statement in the current switch */\nnreg = 4;  /* number of general registers available */\nmaprel[]={ 60,61,64,65,62,63,68,69,66,67};  /* maps binary relations to the their flipped pairs */\nnauto = 0;\nstack = 0;\npeeksym = -1;  /* peeked symbol */\npeekc= 0;  /* peeked character */\neof = 0;  /* true if reached end of file */\nline = 1;  /* current line */\nint *csym = 0;  /* current symbol see meaning below */\ncval = 0;  // contains the currently read character literal\nncpw = 2;  /* number of characters per word */\nnerror = 0;  /* number of errors during parsing */\nFILE *fout;  /* putchar prints characters to this file */\nint *paraml;  /* head of the parameter list */\nint *parame;  /* last element in the parameter list */\n\n\n/*\n * csym - current symbol description, points to the corresponding element in the hash table.\n * Meaning of the 4 words\n * 0 - if 1 then keyword, otherwise storage scope (keyword ID), 8 for function parameters\n *        -1 (temporary) for function parameters csym[0] forms a linked list, -1 marks the end\n *        -2 default storage scope (auto)\n *        1 - keyword\n *        2 - label\n *        5 - auto\n *        6 - extern\n *        7 - static\n *       10 - function parameter (set by blkhed)\n * 1 - type description\n *        lower 4 bits contain raw type (char/double/int)\n *        then 020 is added for every indirection\n *        e.g. 020 refers to int[]\n * 2 - location/label\n *     in case of parameters/auto the offset from the stack frame\n *     in case of statics, the label of the variable\n * 3 - the length in case of arrays, 0 otherwise\n * 4 - the name of the symbol\n *\n * cval - value in the current symbol\n * if number literal - the number\n * if char literal - character ascii code\n * if keyword - the keyword ID\n * if string - the label in the assembly output\n */\n"
  },
  {
    "path": "src/c01.c",
    "content": "#include \"c0.h\"\n#include <stdlib.h>\n#include <stdarg.h>\n\n/*\n * Builds a new node of the operator tree and pushes it onto the cmst stack.\n * The necessary parameters are popped from cmst.\n */\nvoid build(op) {\n\tauto *p1, t1, d1, *p2, t2, d2, t;\n\tauto d, dope, lr, cvn;\n\n    /* replace a[b] with *(a+b) */\n\tif (op==4)  {\t\t/* [] */\n\t\tbuild(40);  /* + */\n\t\top = 36;\n\t}\n\tdope = opdope[op];\n\tif ((dope&01)!=0) {  /* binary */\n\t\tp2 = *--cp; /* second subtree */\n\t\tif(p2 != 0) {  /* if op was mcall originally, there is a fake 0 null pointer here, ignore it */\n            t2 = p2[1];\n            d2 = p2[2];\n        }\n\t}\n\tp1 = *--cp;  /* first subtree */\n\tt1 = p1[1];\n\td1 = p1[2];\n\tswitch (op) {\n\n\t/* , */\n\tcase 9:\n\t\t*cp++ = block(2, 9, 0, 0, p1, p2);\n\t\treturn;\n\n\t/* ? */\n\tcase 90:\n\t\tif (*p2!=8)\n\t\t\terror(\"Illegal conditional\");\n\t\tgoto goon;\n\n\t/* call */\n\tcase 100:\n\t\t*cp++ = block(2,100,t1,24,p1,p2);\n\t\treturn;\n\n\t/* * */\n\tcase 36:\n\t\tif ((t1 -= 16)<0)  {\n\t\t\terror(\"Illegal indirection\");\n\t\t\tt1 += 16;\n\t\t}\n\t\tif (*p1!=20 & d1==0)\n\t\t\td1 = 1;\n\t\t*cp++ = block(1,36,t1,d1,p1);\n\t\treturn;\n\n\t/* & unary */\n\tcase 35:\n\t\tif (*p1 == 36) {\t/* * - shorten &*p to p */\n\t\t\t*cp++ = p1[3];\n\t\t\treturn;\n\t\t}\n\t\tif (*p1 == 20) {  /* name */\n\t\t\t*cp++ = block(1,p1[3]==5?29:35,t1+16,1,p1); /* is it auto? */\n\t\t\treturn;\n\t\t}\n\t\terror(\"Illegal lvalue\");\n\t}\ngoon:\n\tif ((dope&02)!=0)\t\t/* lvalue needed on left? */\n\t\tchklval(p1);\n\tif ((dope&020)!=0)\t\t/* word operand on left? */\n\t\tchkw(p1);\n\tif ((dope&040)!=0)\t\t/* word operand on right? */\n\t\tchkw(p2);\n\tif ((dope&01)!=0) {\t\t/* binary op? */\n\t\tcvn = cvtab[9*lintyp(t1)+lintyp(t2)];  /* conversion from t1 to t2 ?? */\n \t\tif ((dope&010)!=0)  {\t/* assignment? */\n\t\t\tt = t1;\n\t\t\tlr = 1;\n\t\t\tcvn &= 07;\n\t\t} else {\n\t\t\tt = (cvn&0100)!=0? t2:t1;  /* who gets the result */\n\t\t\tlr = cvn&0200;\n\t\t\tcvn = (cvn>>3)&07;\n\t\t}\n\t\tif (cvn) {\n\t\t\tif (cvn==07) {\n\t\t\t\terror(\"Illegal conversion\");\n\t\t\t\tgoto nocv;\n\t\t\t}\n\t\t\tcvn += (dope&010)!=0? 83:93;\n\t\t\tif (lr) {  /* left argument determines the target type */\n\t\t\t\tt2 = t;\n\t\t\t\t d2 = (p2=convert(p2, t, d2, cvn))[2];\n\t\t\t} else {\n\t\t\t\tt1 = t;\n\t\t\t\td1 = (p1=convert(p1, t, d1, cvn))[2];\n\t\t\t}\nnocv:;\t\t}\n\t\tif (d2>d1 & (dope&0100)!=0) {\t/* flip operation, if second tree is more difficult */\n\t\t\tif ((dope&04)!=0)\t/* relational? */\n\t\t\t\top = maprel[op-60];\n\t\t\td = d1;\n\t\t\td1 = d2;\n\t\t\td2 = d;\n\t\t\td = p1;\n\t\t\tp1 = p2;\n\t\t\tp2 = d;\n\t\t\td = t1;\n\t\t\tt1 = t2;\n\t\t\tt2 = d;\n\t\t}\n\t\tif (d1==d2)  /* calculating registers needed for this node using Sethi-Ullman */\n\t\t\td = d1+1; else\n\t\t\td = max(d1,d2);\n\t\tif ((dope&04)!=0)\n\t\t\tt = 0;\t\t/* relational ops have integer type */\n\t\t*cp++ = block(2,op,t,d,p1,p2);\n\t\treturn;\n\t}\n\t*cp++ = block(1,op,t1,d1==0?1:d1,p1);  /* unary operator */\n}\n\n/* Creates a node for type conversion */\nint *convert(p, t, d, cvn)\nint p[];\n{\n\tauto c;\n\tif (*p==21) {\t\t/* constant */\n\t\tc = p[3];\n\t\tswitch(cvn) {\n\n\t\tcase 99:\t\t/* c18 */\n\t\t\tc <<= 1;\n\n\t\tcase 98:\t\t/* c14 */\n\t\t\tc <<= 1;\n\n\t\tcase 97:\t\t/* c12 */\n\t\t\tc <<= 1;\n\n\t\t\tp[3] = c;\n\t\treturn(p);\n\t\t}\n\t}\n\treturn(block(1, cvn, t, max(1,d), p));\n}\n\n/* check if p is a word type */\nchkw(p)\nint p[]; {\n\tauto t;\n\n\tif ((t=p[1])>1 & t<16)\n\t\terror(\"Integer operand required\");\n}\n\n/* Compresses type id to one used in cvtable */\nlintyp(t) {\n\treturn(t<16? t:(t<32? t-12: 8));\n}\n\n\nerror(s)\nchar s[];{\n    error2(s, 0, 0);\n}\n\nerror1(s, p1)\nchar s[];{\n    error2(s, p1, 0);\n}\n\nerror2(s, p1, p2)\nchar s[];{\n\tFILE *f;\n\n\tnerror++;\n\tfflush(fout);\n\tf = fout;\n\tfout = stderr;\n\tprintf(\"%d: \", line);\n\tprintf(s, p1, p2);\n\tputchar('\\n');\n\tfflush(stderr);\n\tfout = f;\n}\n\n/*\n * Creates a new node and appends it to the end of *ospace. The parameters of the node\n * are passed after the argument n, which contains the number of optional parameters.\n * Each node has 3 mandatory parameters and any number of optional ones. The mandatory parameters:\n * op - operator id\n * t - type\n * d - difficulty, number of registers to calculate the node, or statement difficulty level in c1\n * These are followed by the (op dependent) optional parameters, which usually are the subtrees.\n */\nint *block(int n, ...)\n{\n\tauto *p;\n\tva_list arguments;\n\n#ifdef DEBUG\n\tva_list dbg_args;\n\tva_start(dbg_args, n);\n\tint op = va_arg(dbg_args, int);\n\tint type = va_arg(dbg_args, int);\n\tint regcnt = va_arg(dbg_args, int);\n\tprintf(\"loc %d: %d t=%d d=%d nump=%d \", space-ospace, op, type, regcnt, n);\n    for (int i = 0; i < n; ++i) {\n        int d = va_arg(dbg_args, int);\n        printf(\"%d (%d) \", d, (int*)d-ospace);\n    }\n    printf(\"\\n\");\n    va_end(dbg_args);\n#endif\n\n\tp = space;\n\tva_start(arguments, n);\n\tn += 3;\n\tif(space+n >= ospace+ossiz) {\n\t\terror(\"Expression overflow\");\n\t\texit(1);\n\t}\n\twhile(n--)\n\t\t*space++ = va_arg(arguments, int);\n\n\tva_end(arguments);\n\treturn(p);\n}\n\n/* check if p is an lvalue (name or pointer) */\nchklval(p)\nint p[]; {\n\tif (*p!=20)\n\t\tif (*p!=36)\n\t\t\terror(\"Lvalue required\");\n}\n\nmax(a, b)\n{\n\tif (a>b)\n\t\treturn(a);\n\treturn(b);\n}\n\n"
  },
  {
    "path": "src/c02.c",
    "content": "#include \"c0.h\"\n\n/* P\n * arses a function, the function name and the opening parenthesis of the\n * argument list has already been read. name contains the name of the function.\n */\nfunction(name)\nchar name[]; {\n#ifdef UNIXV5_ABI\n\tprintf( \".text; %p:\\n\", name);\n#else\n    printf( \".data; %p:1f\\n.text; 1:\", name);\n#endif\n\tprintf(\"mov r5,-(sp); mov sp,r5\\n\");  /* set up stack frame */\n\tdeclare(8);  /* read parameter list */\n\tdeclist(); /* type declarations of parameters */\n\n\tstatement(1);\n\tretseq();\n}\n\n/* Parses the next function/global variable definition. */\nvoid extdef() {\n\tauto o, c, *cs;\n\tchar *s;\n\n\tif(((o=symbol())==0) || o==1)\t/* EOF */\n\t\treturn;\n\tif(o!=20)  /* not a name -> syntax error */\n\t\tgoto syntax;\n\tcsym[0] = 6;\n\tcs = &csym[4];  // name of the symbol\n\tprintf(\".globl\t%p\\n\", cs);\n\ts = \".data; %p:1f\\n\";\n\tswitch(o=symbol()) {\n\n\tcase 6:\t\t\t\t/* ( - function definition*/\n\t\tfunction(cs);\n\t\treturn;\n\n\tcase 21:\t\t\t/* const - variable has default value*/\n\t\tprintf(\".data; %p: %o\\n\", cs, cval);\n\t\tif((o=symbol())!=1)\t/* ; */\n\t\t\tgoto syntax;\n\t\treturn;\n\n\tcase 1:\t\t\t\t/* ; */\n\t\tprintf(\".bss; %p: .=.+2\\n\", cs);  /* unitialized variable */\n\t\treturn;\n\n\tcase 4:\t\t\t\t/* [ */\n\t\tc = 0;\n\t\tif((o=symbol())==21) {\t/* const */\n\t\t\tc = cval<<1;  /* multiply by two (number of bytes per word), should be changed for 32bit systems */\n\t\t\to = symbol();\n\t\t}\n\t\tif(o!=5)\t\t/* ] */\n\t\t\tgoto syntax;\n\t\tprintf(s, cs);\n\t\tif((o=symbol())==1) {\t/* ; */\n\t\t\tprintf(\".bss; 1:.=.+%o\\n\", c);\n\t\t\treturn;\n\t\t}\n\t\t/* symbol list, e.g.:\n\t\tarrname[] 23, 43 ,5; */\n\t\tprintf(\"1:\");\n\t\twhile(o==21) {\t\t/* const */\n\t\t\tprintf(\"%o\\n\", cval);\n\t\t\tc -= 2;\n\t\t\tif((o=symbol())==1)\t/* ; */\n\t\t\t\tgoto done;\n\t\t\tif(o!=9)\t\t/* , */\n\t\t\t\tgoto syntax;\n\t\t\telse\n\t\t\t\to = symbol();\n\t\t}\n\t\tgoto syntax;\n\tdone:\n\t\tif(c>0)\n\t\t\tprintf(\".=.+%o\\n\", c);\n\t\treturn;\n\n\tcase 0:\t\t\t\t/* EOF */\n\t\treturn;\n\t}\n\nsyntax:\n\terror(\"External definition syntax\");\n\terrflush(o);\n\tstatement(0);\n}\n\n/*\n * Parses (a block of) statements.\n * d - true if this is a start of a function block\n */\nvoid statement(d) {\n\tint o, o1, o2, o3, *np;\n\nstmt:\n\tswitch(o=symbol()) {\n\n\t/* EOF */\n\tcase 0:\n\t\terror(\"Unexpected EOF\");\n\t/* ; */\n\tcase 1:\n\t/* } */\n\tcase 3:\n\t\treturn;\n\n\t/* { */\n\tcase 2: {\n\t\tif(d)\n\t\t\tblkhed();  /* process definitions at the start of the funciton */\n\t\t/* recursively process this block of code */\n\t\twhile (!eof) {\n\t\t\tif ((o=symbol())==3)\t/* } */\n\t\t\t\tgoto bend;\n\t\t\tpeeksym = o;\n\t\t\tstatement(0);\n\t\t}\n\t\terror(\"Missing '}'\");\n\tbend:\n\t\treturn;\n\t}\n\n\t/* keyword */\n\tcase 19:\n\t\tswitch(cval) {\n\n\t\t/* goto */\n\t\tcase 10:\n\t\t\to1 = block(1,102,0,0,tree());\n\t\t\trcexpr(o1, regtab);\n\t\t\tgoto semi;\n\n\t\t/* return */\n\t\tcase 11:\n\t\t\tif((peeksym=symbol())==6)\t/* ( */\n\t\t\t\trcexpr(pexpr(), regtab);\n\t\t\tretseq();\n\t\t\tgoto semi;\n\n\t\t/* if */\n\t\tcase 12:\n\t\t\tjumpc(pexpr(), o1=isn++, 0);\n\t\t\tstatement(0);\n\t\t\tif ((o=symbol())==19 & cval==14) {  /* else */\n\t\t\t\to2 = isn++;\n\t\t\t\t(easystmt()?branch:jump)(o2);  /* branch can only jump to a close location */\n\t\t\t\tlabel(o1);\n\t\t\t\tstatement(0);\n\t\t\t\tlabel(o2);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tpeeksym = o;\n\t\t\tlabel(o1);\n\t\t\treturn;\n\n\t\t/* while */\n\t\tcase 13:\n\t\t\to1 = contlab;\n\t\t\to2 = brklab;\n\t\t\tlabel(contlab = isn++);\n\t\t\tjumpc(pexpr(), brklab=isn++, 0);\n\t\t\to3 = easystmt();\n\t\t\tstatement(0);\n\t\t\t(o3?branch:jump)(contlab);\n\t\t\tlabel(brklab);\n\t\t\tcontlab = o1;\n\t\t\tbrklab = o2;\n\t\t\treturn;\n\n\t\t/* break */\n\t\tcase 17:\n\t\t\tif(brklab==0)\n\t\t\t\terror(\"Nothing to break from\");\n\t\t\tjump(brklab);\n\t\t\tgoto semi;\n\n\t\t/* continue */\n\t\tcase 18:\n\t\t\tif(contlab==0)\n\t\t\t\terror(\"Nothing to continue\");\n\t\t\tjump(contlab);\n\t\t\tgoto semi;\n\n\t\t/* do */\n\t\tcase 19:\n\t\t\to1 = contlab;\n\t\t\to2 = brklab;\n\t\t\tcontlab = isn++;\n\t\t\tbrklab = isn++;\n\t\t\tlabel(o3 = isn++);\n\t\t\tstatement(0);\n\t\t\tlabel(contlab);\n\t\t\tcontlab = o1;\n\t\t\tif ((o=symbol())==19 & cval==13) { /* while */\n\t\t\t\tjumpc(tree(), o3, 1);\n\t\t\t\tlabel(brklab);\n\t\t\t\tbrklab = o2;\n\t\t\t\tgoto semi;\n\t\t\t}\n\t\t\tgoto syntax;\n\n\t\t/* case */\n\t\tcase 16:\n\t\t\tif ((o=symbol())!=21)\t/* constant */\n\t\t\t\tgoto syntax;\n\t\t\tif ((o=symbol())!=8)\t/* : */\n\t\t\t\tgoto syntax;\n\t\t\tif (swp==0) {\n\t\t\t\terror(\"Case not in switch\");\n\t\t\t\tgoto stmt;\n\t\t\t}\n\t\t\tif(swp>=swtab+swsiz) {\n\t\t\t\terror(\"Switch table overflow\");\n\t\t\t} else {\n\t\t\t\t*swp++ = isn;  /* add value and label to switch table */\n\t\t\t\t*swp++ = cval;\n\t\t\t\tlabel(isn++);\n\t\t\t}\n\t\t\tgoto stmt;\n\n\t\t/* switch */\n\t\tcase 15:\n\t\t\to1 = brklab;\n\t\t\tbrklab = isn++;\n\t\t\tnp = pexpr();\n\t\t\tif (np[1]>1 & np[1]<16)\n\t\t\t\terror(\"Integer required\");\n\t\t\trcexpr(np, regtab);\n\t\t\tpswitch();\n\t\t\tbrklab = o1;\n\t\t\treturn;\n\n\t\t/* default */\n\t\tcase 20:\n\t\t\tif (swp==0)\n\t\t\t\terror(\"Default not in switch\");\n\t\t\tif ((o=symbol())!=8)\t/* : */\n\t\t\t\tgoto syntax;\n\t\t\tdeflab = isn++;\n\t\t\tlabel(deflab);\n\t\t\tgoto stmt;\n\t\t}\n\n\t\terror(\"Unknown keyword\");\n\t\tgoto syntax;\n\n\t/* name */\n\tcase 20:\n\t\tif (peekc==':') {  /* label */\n\t\t\tpeekc = 0;\n\t\t\tif (csym[0]>0) {\n\t\t\t\terror(\"Redefinition\");\n\t\t\t\tgoto stmt;\n\t\t\t}\n\t\t\tcsym[0] = 2;\n\t\t\tcsym[1] = 020;\t/* int[] */\n\t\t\tif (csym[2]==0)\n\t\t\t\tcsym[2] = isn++;\n\t\t\tslabel();\n\t\t\tgoto stmt;\n\t\t}\n\t}\n\n\tpeeksym = o;\n\trcexpr(tree(), efftab);\n\tgoto semi;\n\nsemi:\n\tif ((o=symbol())!=1)\t\t/* ; */\n\t\tgoto syntax;\n\treturn;\n\nsyntax:\n\terror(\"Statement syntax\");\n\terrflush(o);\n\tgoto stmt;\n}\n\n/*\n * Parses an expression enclosed in parenthesis.\n * Returns the address to the parsed tree.\n */\npexpr()\n{\n\tauto o, t;\n\n\tif ((o=symbol())!=6)\t/* ( */\n\t\tgoto syntax;\n\tt = tree();\n\tif ((o=symbol())!=7)\t/* ) */\n\t\tgoto syntax;\n\treturn(t);\nsyntax:\n\terror(\"Statement syntax\");\n\terrflush(o);\n\treturn(0);\n}\n\n/* Parses the contents of a switch block. */\npswitch() {\n\tint *sswp, dl, cv, swlab;  /* ?, default label, current ?, switch label */\n\n\tsswp = swp;  /* save swp */\n\tif (swp==0)\n\t\tswp = swtab;\n\tswlab = isn++;\n\tprintf(\"jsr\tpc,bswitch; l%d\\n\", swlab);\n\tdl = deflab;  /* save deflab */\n\tdeflab = 0;\n\tstatement(0);\n\tif (!deflab) {\n\t\tdeflab = isn++;\n\t\tlabel(deflab);\n\t}\n\t/* generate switch table */\n\tprintf(\"L%d:.data;L%d:\", brklab, swlab);\n\twhile(swp>sswp & swp>swtab) {\n\t\tcv = *--swp;\n\t\tprintf(\"%o; l%d\\n\", cv, *--swp);\n\t}\n\tprintf(\"L%d; 0\\n.text\\n\", deflab);\n\tdeflab = dl;\n\tswp = sswp;\n}\n\n/*\n * Function block head: processes variable definitions.\n */\nblkhed()\n{\n\tint o, al, pl, *cs, hl;\n\n\tdeclist();\n\tstack = al = -2;\n\tpl = 4;\n\twhile(paraml) {\n\t\t*parame = 0;  /* set the end of linked list to 0 (originally -1), will break the loop */\n\t\tparaml = *(cs = paraml);  /* next element in list */\n\t\tcs[2] = pl;  /* location relative to stack frame */\n\t\t*cs = 10;\n\t\tpl += rlength(cs[1]);\n\t}\n\tcs = hshtab;\n\thl = hshsiz;\n\twhile(hl--) {  /* go through symbol table, i.e. all defined names */\n\t    if (cs[4])\n\t\tswitch(cs[0]) {  /* if defined */\n\n\t\t/* sort unmentioned */\n\t\tcase -2:\n\t\t\tcs[0] = 5;\t\t/* auto */\n\n\t\t/* auto */\n\t\tcase 5:\n\t\t\tif (cs[3]) {\t/* array */\n\t\t\t\tal -= (cs[3]*length(cs[1]-020)+1) & 077776;  /* push array on stack */\n\t\t\t\tsetstk(al);\n\t\t\t\tdefvec(al);\n\t\t\t}\n\t\t\tcs[2] = al;\n\t\t\tal -= rlength(cs[1]);\n\t\t\tgoto loop;\n\n\t\t/* parameter */\n\t\tcase 10:\n\t\t\tcs[0] = 5;\n\t\t\tgoto loop;\n\n\t\t/* static */\n\t\tcase 7:\n\t\t\tcs[2] = isn++;\n\t\t\tdefstat(cs);\n\t\t\tgoto loop;\n\n\t\tloop:;\n\t\t}\n\t\tcs = cs+pssiz;\n\t}\n\tsetstk(al);\n}\n\n/*\n * Clears all elements from the symbol table,\n * except keywords.\n */\nblkend() {\n\tauto i, hl;\n\n\ti = 0;\n\thl = hshsiz;\n\twhile(hl--) {\n\t\tif(hshtab[i+4])\n\t\t\tif (hshtab[i]==0)\n\t\t\t\terror1(\"%p undefined\", &hshtab[i+4]);\n\t\t\tif(hshtab[i]!=1) {\t/* not keyword */\n\t\t\t\thshused--;\n\t\t\t\thshtab[i+4] = 0;\n\t\t\t}\n\t\ti += pssiz;\n\t}\n}\n\n/* Throw away symbols until end of statement. */\nerrflush(o) {\n\twhile(o>3)\t/* ; { } */\n\t\to = symbol();\n\tpeeksym  = o;\n}\n\n/*\n * Variable declarations. Either function parameter type declaration\n * or function local variable declarations.\n */\ndeclist()\n{\n\tauto o;\n\n\twhile((o=symbol())==19 & cval<10)  /* cval<10 means it is a type/storage area definition (int/char/extern/static) */\n\t\tdeclare(cval);\n\tpeeksym = o;\n}\n\n/*\n * Detects whether the next statement is expected to be small - i.e. not a compound statement\n* This usually means it is a single statement or conditional.\n* e.g. goto, break, or not a label or block */\neasystmt()\n{\n\tif((peeksym=symbol())==20)\t/* name */\n\t\treturn(peekc!=':');\t /* not label */\n\tif (peeksym==19) {\t\t/* keyword */\n\t\tswitch(cval)\n\n\t\tcase 10:\t/* goto */\n\t\tcase 11:\t/* return */\n\t\tcase 17:\t/* break */\n\t\tcase 18:\t/* continue */\n\t\t\treturn(1);\n\t\treturn(0);\n\t}\n\treturn(peeksym!=2);\t\t/* { */\n}\n\n/* Emits a branch instruction */\nbranch(lab)\n{\n\tprintf(\"br\tL%d\\n\", lab);\n}\n\n"
  },
  {
    "path": "src/c03.c",
    "content": "#include \"c0.h\"\n#include <stdarg.h>\n/*\n * Records a conditional jump. If the jump is short (easystmt is true),\n * it generates a branch isntruction, otherwise a jump instruction.\n *\n * tree - tree containing a conditional expression\n * lbl - where to jump\n * cond - decides whether to jump when condition is true or false\n */\njumpc(tree, lbl, cond)\nint tree[];\n{\n\trcexpr(block(1,easystmt()+103,tree,lbl,cond),cctab);\n}\n\n/*\n * Prints the binary representation of the tree.\n * table - the expression translation table used in the next pass.\n */\nrcexpr(tree, table)\nint tree[], table;  // table: the code generation table\n{\n\tint c, *sp;\n\n\tputchar('#');\n\tc = space-ospace;\n\tsp = ospace;\n\n\tputwrd(ospace);  /* save start of array location (original code expects it to be loaded at the same place */\n\tputwrd(c);\n\tputwrd(tree);\n\tputwrd(table);\n\tputwrd(line);\n\twhile(c--)\n\t\tputwrd(*sp++);\n#ifdef DEBUG\n\tprintf(\"\\n\");\n#endif\n}\n\njump(lab) {\n\tprintf(\"jmp\\tl%d\\n\", lab);\n}\n\nlabel(l) {\n\tprintf(\"l%d:\", l);\n}\n\n/* Generates code for a return statement. */\nretseq() {\n#ifdef UNIXV5_ABI\n    printf(\"mov\\tr5,sp\\nmov\\t(sp)+,r5\\nrts\\tpc\\n\");\n#else\n\tprintf(\"jmp\\tretrn\\n\");\n#endif\n}\n\n/* Label for a static variable */\nslabel() {\n\tprintf(\".data; l%d: 1f; .text; 1:\\n\", csym[2]);\n}\n\n/*\n * Reserves space on the stack.\n * a - amount of bytes to add to the stack\n */\nvoid setstk(a) {\n\tauto ts;\n\n\tts = a-stack;  /* relative distance */\n\tstack = a;\n\tswitch(ts) {\n\n\tcase 0:\n\t\treturn;\n\n\tcase -2:\t/* -2 */\n\t\tprintf(\"tst\t-(sp)\\n\");\n\t\treturn;\n\n\tcase -4:\t/* -4 */\n\t\tprintf(\"cmp\t-(sp),-(sp)\\n\");\n\t\treturn;\n\t}\n\tprintf(\"add\t$%o,sp\\n\", ts);\n}\n\n/* define array on stack, simply saves the pointer to the top of the stack */\nint defvec() {\n\tprintf(\"mov\\tsp,r0\\nmov\\tr0,-(sp)\\n\");\n\tstack -= 2;\n}\n\n/*\n * Define static variable.\n * s - pointer to symbol table entry\n */\ndefstat(s)\nint s[]; {\n\tint len;\n\n\tlen = length(s[1]);\n\tif (s[3])  /* array */\n\t\tprintf(\".data; l%d:1f; .bss; 1:.=.+%o; .even; .text\\n\", s[2],\n\t\t\ts[3]*len);\n\telse  /* scalar */\n\t\tprintf(\".bss; l%d:.=.+%o; .even; .text\\n\", s[2], len);\n}\n\n/*\n * Length of the datatype, t is the type descriptor.\n * The id of the type is the id of the keyword + 020 for every indirection\n */\nlength(t) {\n\n\tif (t<0)\n\t\tt += 020;\n\tif (t>=020)  /* array/pointer */\n\t\treturn(2);\n\tswitch(t) {\n\n\tcase 0:\n\t\treturn(2);\n\n\tcase 1:\n\t\treturn(1);\n\n\tcase 2:\n\t\treturn(4);\n\n\tcase 3:\n\t\treturn(8);\n\n\tcase 4:\n\t\treturn(4);\n\n\t}\n\treturn(1024);\n}\n\n/* rounded length */\nrlength(c) {\n\tauto l;\n\n\treturn((l=length(c))==1? 2: l);\n}\n\n\n/* prints the number n in base b */\nprintn(n,b) {\n\tauto a;\n\n\tif(a=n/b) /* assignment, not test for equality */\n\t\tprintn(a, b); /* recursive */\n\tputchar(n%b + '0');\n}\n\nputwrd(a) {\n    printf(\"%d;\", a);\n}\n\ncc_putchar(int c)\n{\n    putc(c, fout);\n}\n\nvoid cc_printf(char *fmt, ...)\n{\n\tstatic char *s;\n\tauto *adx, x, c, *i;\n\tva_list arguments;\n\n    va_start ( arguments, fmt);\nloop:\n\twhile((c = *fmt++) != '%') {\n\t\tif(c == '\\0') {\n\t\t    va_end(arguments);\n            return;\n        }\n\t\tputchar(c);\n\t}\n\tswitch (c = *fmt++) {\n\n\tcase 'd': /* decimal */\n\tcase 'o': /* octal */\n\t    x = va_arg(arguments, int);\n\t\tif(x < 0) {\n\t\t\tx = -x;\n\t\t\tif(x<0)  {\t/* - infinity */\n\t\t\t\tif(c=='o')\n\t\t\t\t\tprintf(\"100000\");\n\t\t\t\telse\n\t\t\t\t\tprintf(\"-32767\");\n\t\t\t\tgoto loop;\n\t\t\t}\n\t\t\tputchar('-');\n\t\t}\n\t\tprintn(x, c=='o'?8:10);\n\t\tgoto loop;\n\n\tcase 's': /* string */\n\t    x = va_arg(arguments, int);\n\t    s=x;\n\t\twhile(c = *s++) {\n            putchar(c);\n        }\n\t\tgoto loop;\n\n\tcase 'p':\n\t\ts =va_arg(arguments, int*);\n\t\tputchar('_');\n\t\tc = namsiz;\n\t\twhile(c--)\n\t\t\tif(*s)\n\t\t\t\tputchar(*s++);\n\t\tgoto loop;\n\t}\n\tputchar('%');\n\tfmt--;\n\tgoto loop;\n}\n\n"
  },
  {
    "path": "src/c0t.c",
    "content": "#include \"c0.h\"\n\n// Converts ascii characters to symbols\n// 127 means unknown character, 123 are letters, 124 digits\nchar ctab[]={  0, 127, 127, 127, 127, 127, 127, 127,   /*  0 -  7 */\n             127, 126, 125, 127, 127, 127, 127, 127,   /*  8 - 15 */\n             127, 127, 127, 127, 127, 127, 127, 127,   /* 16 - 23 */\n             127, 127, 127, 127, 127, 127, 127, 127,   /* 24 - 31 */\n             126,  34, 122, 127, 127,  44,  47, 121,   /* 32 - 39 */\n               6,   7,  42,  40,   9,  41, 127,  43,   /* 40 - 47 */\n             124, 124, 124, 124, 124, 124, 124, 124,   /* 48 - 55 */\n             124, 124,   8,   1,  63,  80,  65,  90,   /* 56 - 63 */\n             127, 123, 123, 123, 123, 123, 123, 123,   /* 64 - 72 */\n             123, 123, 123, 123, 123, 123, 123, 123,\n             123, 123, 123, 123, 123, 123, 123, 123,\n             123, 123, 123,   4, 127,   5,  49, 127,\n             127, 123, 123, 123, 123, 123, 123, 123,\n             123, 123, 123, 123, 123, 123, 123, 123,\n             123, 123, 123, 123, 123, 123, 123, 123,\n             123, 123, 123,   2,  48,   3, 127, 127};\n\n\nint opdope[] ={\n    000000,  // EOF\n    000000,  // ;\n    000000,  // {\n    000000,  // }\n    036000,  // [\n    002000,  // ]\n    036000,  // (\n    002000,  // )\n    014201,  // :\n    007001,  // ,\n    000000,  // 10\n    000000,  // 11\n    000000,  // 12\n    000000,  // 13\n    000000,  // 14\n    000000,  // 15\n    000000,  // 16\n    000000,  // 17\n    000000,  // 18\n    000000,  // 19\n    000000,  // name\n    000000,  // short constant\n    000000,  // string\n    000000,  // float\n    000000,  // double\n    000000,  // 25\n    000000,  // 26\n    000000,  // 27\n    000000,  // 28\n    000000,  // 29\n    034202,  // ++pre\n    034202,  // --pre\n    034202,  // ++post\n    034202,  // --post\n    034220,  // !un\n    034202,  // &un\n    034220,  // *un\n    034200,  // -un\n    034220,  // ~un\n    000000,  // 39\n    030101,  // +\n    030001,  // -\n    032101,  // *\n    032001,  // //\n    032001,  // %\n    026061,  // >>\n    026061,  // <<\n    020161,  // &\n    016161,  // |\n    016161,  // ^\n    000000,  // 50\n    000000,  // 51\n    000000,  // 52\n    000000,  // 53\n    000000,  // 54\n    000000,  // 55\n    000000,  // 56\n    000000,  // 57\n    000000,  // 58\n    000000,  // 59\n    022105,  // ==\n    022105,  // !=\n    024105,  // <=\n    024105,  // <\n    024105,  // >=\n    024105,  // >\n    024105,  // <p\n    024105,  // <=p\n    024105,  // >p\n    024105,  // >=p\n    012213,  // =+\n    012213,  // =-\n    012213,  // =*\n    012213,  // =//\n    012213,  // =%\n    012253,  // =>>\n    012253,  // =<<\n    012253,  // =&\n    012253,  // =|\n    012253,  // =^\n    012213,  // =\n    000000,  // 81\n    000000,  // 82\n    000000,  // 83\n    000000,  // int -> float\n    000000,  // int -> double\n    000000,  // float -> int\n    000000,  // float -> double\n    000000,  // double -> int\n    000000,  // double -> float\n    014201,  // ?\n    000000,  // 91\n    000000,  // 92\n    000000,  // 93\n    000000,  // int -> float\n    000000,  // int -> double\n    000000,  // float -> double\n    000000,  // int -> int[]\n    000000,  // int -> float[]\n    000000,  // int -> double[]\n    036001,  // call\n    036001,  // mcall\n};\n\nint cvtab[] ={\n    0000,  // i:i\n\t0000,  // i:c\n\t0113,  // i:f\n\t0125,  // i:d\n\t0140,  // i:i[]\n\t0100,  // i:c[]\n\t0150,  // i:f[]\n\t0160,  // i:d[]\n\t0140,  // i:[][]\n\n\t0100,  // c:i\n\t0100,  // c:c\n\t0113,  // c:f\n\t0125,  // c:d\n\t0140,  // c:i[]\n\t0100,  // c:c[]\n\t0150,  // c:f[]\n\t0160,  // c:d[]\n\t0140,  // c[][]\n\n\t0211,  // f:i\n\t0211,  // f:c\n\t0000,  // f:f\n\t0136,  // f:d\n\t0211,  // f:i[]\n\t0211,  // f:c[]\n\t0211,  // f:f[]\n\t0211,  // f:d[]\n\t0211,  // f:[][]\n\n\t0222,  // d:i\n\t0222,  // d:c\n\t0234,  // d:f\n\t0000,  // d:d\n\t0222,  // d:i[]\n\t0222,  // d:c[]\n\t0222,  // d:f[]\n\t0222,  // d:d[]\n\t0222,  // d:[][]\n\n\t0240,  // i[]:i\n\t0240,  // i[]:c\n\t0113,  // i[]:f\n\t0125,  // i[]:d\n\t0000,  // i[]:i[]\n\t0000,  // i[]:c[]\n\t0100,  // i[]:f[]\n\t0100,  // i[]:d[]\n\t0100,  // i[]:[][]\n\n\t0000,  // c[]:i\n\t0000,  // c[]:c\n\t0113,  // c[]:f\n\t0125,  // c[]:d\n\t0200,  // c[]:i[]\n\t0000,  // c[]:c[]\n\t0200,  // c[]:f[]\n\t0200,  // c[]:d[]\n\t0200,  // c[]:[][]\n\n\t0250,  // f[]:i\n\t0250,  // f[]:c\n\t0113,  // f[]:f\n\t0125,  // f[]:d\n\t0000,  // f[]:i[]\n\t0000,  // f[]:c[]\n\t0000,  // f[]:f[]\n\t0100,  // f[]:d[]\n\t0000,  // f[]:[][]\n\n\t0260,  // d[]:i\n\t0260,  // d[]:c\n\t0113,  // d[]:f\n\t0125,  // d[]:d\n\t0000,  // d[]:i[]\n\t0000,  // d[]:c[]\n\t0000,  // d[]:f[]\n\t0000,  // d[]:d[]\n\t0000,  // d[]:[][]\n\n\t0240,  // [][]:i\n\t0240,  // [][]:c\n\t0113,  // [][]:f\n\t0125,  // [][]:d\n\t0000,  // [][]:i[]\n\t0000,  // [][]:c[]\n\t0100,  // [][]:f[]\n\t0100,  // [][]:d[]\n\t0000,  // [][]:[][]\n};"
  },
  {
    "path": "src/c0t.s",
    "content": "/ word I/O\n\n.globl\t_putwrd\n\n.globl\t_tmpfil\n.globl\tputw\n.globl\tfcreat\n.globl\tflush\n\n.data\n_putwrd: 1f\n.text\n1:\n\ttst\tbuf  / if tmp file not open\n\tbne\t1f\n\tmov\t_tmpfil,r0\n\tjsr\tr5,fcreat; buf  / open tmpfile\n\tbec\t1f\n\tmov\t$1,r0  / if couldn't open file, print error message\n\tsys\twrite; botch; ebotch-botch\n\tsys\texit\n1:\n\tmov\t2(sp),r0\n\tjsr\tr5,putw; buf\n\trts\tpc\n.globl\t_flshw\n.data\n_flshw:\t1f\n.text\n1:\n\tjsr\tr5,flush; buf\n\trts\tpc\n\nbotch:\t<Temp file?\\n\\0>; ebotch:\n.even\n\n.bss\nbuf:\t.=.+518.\n.text\n\n/ C operator and conversion tables\n\n.globl\t_opdope\n.globl\t_cvtab\n\n_opdope:.+2\n\t00000\t/ EOF\n\t00000\t/ ;\n\t00000\t/ {\n\t00000\t/ }\n\t36000\t/ [\n\t02000\t/ ]\n\t36000\t/ (\n\t02000\t/ )\n\t14201\t/ :\n\t07001\t/ ,\n\t00000\t/ 10\n\t00000\t/ 11\n\t00000\t/ 12\n\t00000\t/ 13\n\t00000\t/ 14\n\t00000\t/ 15\n\t00000\t/ 16\n\t00000\t/ 17\n\t00000\t/ 18\n\t00000\t/ 19\n\t00000\t/ name\n\t00000\t/ short constant\n\t00000\t/ string\n\t00000\t/ float\n\t00000\t/ double\n\t00000\t/ 25\n\t00000\t/ 26\n\t00000\t/ 27\n\t00000\t/ 28\n\t00000\t/ 29\n\t34202\t/ ++pre\n\t34202\t/ --pre\n\t34202\t/ ++post\n\t34202\t/ --post\n\t34220\t/ !un\n\t34202\t/ &un\n\t34220\t/ *un\n\t34200\t/ -un\n\t34220\t/ ~un\n\t00000\t/ 39\n\t30101\t/ +\n\t30001\t/ -\n\t32101\t/ *\n\t32001\t/ /\n\t32001\t/ %\n\t26061\t/ >>\n\t26061\t/ <<\n\t20161\t/ &\n\t16161\t/ |\n\t16161\t/ ^\n\t00000\t/ 50\n\t00000\t/ 51\n\t00000\t/ 52\n\t00000\t/ 53\n\t00000\t/ 54\n\t00000\t/ 55\n\t00000\t/ 56\n\t00000\t/ 57\n\t00000\t/ 58\n\t00000\t/ 59\n\t22105\t/ ==\n\t22105\t/ !=\n\t24105\t/ <=\n\t24105\t/ <\n\t24105\t/ >=\n\t24105\t/ >\n\t24105\t/ <p\n\t24105\t/ <=p\n\t24105\t/ >p\n\t24105\t/ >=p\n\t12213\t/ =+\n\t12213\t/ =-\n\t12213\t/ =*\n\t12213\t/ =/\n\t12213\t/ =%\n\t12253\t/ =>>\n\t12253\t/ =<<\n\t12253\t/ =&\n\t12253\t/ =|\n\t12253\t/ =^\n\t12213\t/ =\n\t00000\t/ 81\n\t00000\t/ 82\n\t00000\t/ 83\n\t00000\t/ int -> float\n\t00000\t/ int -> double\n\t00000\t/ float -> int\n\t00000\t/ float -> double\n\t00000\t/ double -> int\n\t00000\t/ double -> float\n\t14201\t/ ?\n\t00000\t/ 91\n\t00000\t/ 92\n\t00000\t/ 93\n\t00000\t/ int -> float\n\t00000\t/ int -> double\n\t00000\t/ float -> double\n\t00000\t/ int -> int[]\n\t00000\t/ int -> float[]\n\t00000\t/ int -> double[]\n\t36001\t/ call\n\t36001\t/ mcall\n\n_cvtab:\t.+2\n\t.byte\t000\t/ i:i\n\t.byte\t000\t/ i:c\n\t.byte\t113\t/ i:f\n\t.byte\t125\t/ i:d\n\t.byte\t140\t/ i:i[]\n\t.byte\t100\t/ i:c[]\n\t.byte\t150\t/ i:f[]\n\t.byte\t160\t/ i:d[]\n\t.byte\t140\t/ i:[][]\n\n\t.byte\t100\t/ c:i\n\t.byte\t100\t/ c:c\n\t.byte\t113\t/ c:f\n\t.byte\t125\t/ c:d\n\t.byte\t140\t/ c:i[]\n\t.byte\t100\t/ c:c[]\n\t.byte\t150\t/ c:f[]\n\t.byte\t160\t/ c:d[]\n\t.byte\t140\t/ c[][]\n\n\t.byte\t211\t/ f:i\n\t.byte\t211\t/ f:c\n\t.byte\t000\t/ f:f\n\t.byte\t136\t/ f:d\n\t.byte\t211\t/ f:i[]\n\t.byte\t211\t/ f:c[]\n\t.byte\t211\t/ f:f[]\n\t.byte\t211\t/ f:d[]\n\t.byte\t211\t/ f:[][]\n\n\t.byte\t222\t/ d:i\n\t.byte\t222\t/ d:c\n\t.byte\t234\t/ d:f\n\t.byte\t000\t/ d:d\n\t.byte\t222\t/ d:i[]\n\t.byte\t222\t/ d:c[]\n\t.byte\t222\t/ d:f[]\n\t.byte\t222\t/ d:d[]\n\t.byte\t222\t/ d:[][]\n\n\t.byte\t240\t/ i[]:i\n\t.byte\t240\t/ i[]:c\n\t.byte\t113\t/ i[]:f\n\t.byte\t125\t/ i[]:d\n\t.byte\t000\t/ i[]:i[]\n\t.byte\t000\t/ i[]:c[]\n\t.byte\t100\t/ i[]:f[]\n\t.byte\t100\t/ i[]:d[]\n\t.byte\t100\t/ i[]:[][]\n\n\t.byte\t000\t/ c[]:i\n\t.byte\t000\t/ c[]:c\n\t.byte\t113\t/ c[]:f\n\t.byte\t125\t/ c[]:d\n\t.byte\t200\t/ c[]:i[]\n\t.byte\t000\t/ c[]:c[]\n\t.byte\t200\t/ c[]:f[]\n\t.byte\t200\t/ c[]:d[]\n\t.byte\t200\t/ c[]:[][]\n\n\t.byte\t250\t/ f[]:i\n\t.byte\t250\t/ f[]:c\n\t.byte\t113\t/ f[]:f\n\t.byte\t125\t/ f[]:d\n\t.byte\t000\t/ f[]:i[]\n\t.byte\t000\t/ f[]:c[]\n\t.byte\t000\t/ f[]:f[]\n\t.byte\t100\t/ f[]:d[]\n\t.byte\t000\t/ f[]:[][]\n\n\t.byte\t260\t/ d[]:i\n\t.byte\t260\t/ d[]:c\n\t.byte\t113\t/ d[]:f\n\t.byte\t125\t/ d[]:d\n\t.byte\t000\t/ d[]:i[]\n\t.byte\t000\t/ d[]:c[]\n\t.byte\t000\t/ d[]:f[]\n\t.byte\t000\t/ d[]:d[]\n\t.byte\t000\t/ d[]:[][]\n\n\t.byte\t240\t/ [][]:i\n\t.byte\t240\t/ [][]:c\n\t.byte\t113\t/ [][]:f\n\t.byte\t125\t/ [][]:d\n\t.byte\t000\t/ [][]:i[]\n\t.byte\t000\t/ [][]:c[]\n\t.byte\t100\t/ [][]:f[]\n\t.byte\t100\t/ [][]:d[]\n\t.byte\t000\t/ [][]:[][]\n\n.even\n\n/ character type table\n\n.globl\t_ctab\n\n_ctab: .+2\n\t.byte 000.,127.,127.,127.,127.,127.,127.,127.\n\t.byte 127.,126.,125.,127.,127.,127.,127.,127.\n\t.byte 127.,127.,127.,127.,127.,127.,127.,127.\n\t.byte 127.,127.,127.,127.,127.,127.,127.,127.\n\t.byte 126.,034.,122.,127.,127.,044.,047.,121.\n\t.byte 006.,007.,042.,040.,009.,041.,127.,043.\n\t.byte 124.,124.,124.,124.,124.,124.,124.,124.\n\t.byte 124.,124.,008.,001.,063.,080.,065.,090.\n\t.byte 127.,123.,123.,123.,123.,123.,123.,123.\n\t.byte 123.,123.,123.,123.,123.,123.,123.,123.\n\t.byte 123.,123.,123.,123.,123.,123.,123.,123.\n\t.byte 123.,123.,123.,004.,127.,005.,049.,127.\n\t.byte 127.,123.,123.,123.,123.,123.,123.,123.\n\t.byte 123.,123.,123.,123.,123.,123.,123.,123.\n\t.byte 123.,123.,123.,123.,123.,123.,123.,123.\n\t.byte 123.,123.,123.,002.,048.,003.,127.,127.\n\n"
  },
  {
    "path": "src/c1.h",
    "content": "//\n// Created by veges on 2021. 03. 17..\n//\n\n#ifndef LEGACY_CC_C1_H\n#define LEGACY_CC_C1_H\n\n#include <stdio.h>\n#include <stdarg.h>\n#include \"config.h\"\n\n/* c10.c */\ngenerate();\nchar *match(int*, int*, int);\nvoid rcexpr(int*, int*, int);\ncexpr(int*, int*, int);\nvoid pname(int *);\ndcalc(int *, int);\nnotcompat(int,int );\nvoid prins(int, int);\ncollcon(int*);\nisfloat(int *, char *s[]);\n\n/* c11.c */\nvoid jumpc(int[],int,int);\nvoid cbranch(int[], int, int, int);\nbranch(int,int,int);\njump(int);\nlabel(int);\nvoid popstk(int);\nlength(int);\nrlength(int);\ngetwrd();\nprintn(int,int);\nvoid cc_printf(char*,...);\nvoid cc_putchar(int);\nerror(char[]);\nerror1(char[],int);\nerror2(char[],int,int);\n\nint *fixp(int*);\n\n/* Globals */\nextern int regtab[];\nextern int efftab[];\nextern int cctab[];\nextern int sptab[];\n\nextern int opdope[];\nextern int ospace[];\nextern int *baseptr;\nextern nreg;\nextern isn;\nextern namsiz;\nextern FILE* fout;\nextern line;\nextern tmpfil;\nextern nerror;\nextern fltmod;\n\nextern int instabcode[];\nextern char *instabstr[];\n\n#define printf cc_printf\n#define putchar cc_putchar\n\n#endif //LEGACY_CC_C1_H\n"
  },
  {
    "path": "src/c10.c",
    "content": "/*\n\n\t    \tC compiler, part 2\n\n\tCopyright 1972 Bell Telephone Laboratories, Inc.\n\n*/\n#include \"c1.h\"\n#include <stdlib.h>\n\nospace[1000];\t/* fake */\n\n/*\n * Second pass of the compiler. The code was expected to be loaded at the same location as the first pass,\n * such that ospace is at the same location as in the first pass. Because of this, pointers in the\n * expression trees were saved using  the absolute address. The fixp function converts the incorrect addresses\n * to ones pointing into this pass' ospace. Throughout this code, unfixed pointer means the fixp function\n * hasn't been called for the pointer yet.\n *\n * For details of the algorithm, see the \"A Tour through the UNIX C Compiler\" in the UNIX v7 manual.\n * Though it is for a newer version of C, almost everything is applicable to this compiler.\n * The difficulty levels used in this compiler:\n * z -  4 - zero\n * c -  8 - number\n * i - 12 - name/string/float/double, pointer address(&)\n * a - 16 - addressible by PDP11 address instructions\n * e - 20 - easy statement, value can be calculated using the available registers only\n * n - 63 - anything\n */\nmain(argc, argv)\nchar *argv[];\n{\n\tint *sp, c, *table, *tabtab[4], tree;\n\n\tif (argc<2) {\n\t\terror(\"Arg count\");\n\t\texit(1);\n\t}\n\tif(freopen(argv[1], \"r\", stdin)==NULL) {\n\t\terror1(\"Can't find %s\", argv[1]);\n\t\texit(1);\n\t}\n\tfout = stdout;\n\n\ttabtab[0] = regtab;\n\ttabtab[1] = efftab;\n\ttabtab[2] = cctab;\n\ttabtab[3] = sptab;\n\twhile((c=getchar())>0) {\n\t\tif(c=='#') {  /* expression */\n\t\t\tsp = ospace;\n\t\t\tbaseptr=getwrd();\n\t\t\tc = getwrd();\n\t\t\ttree = getwrd();\n\t\t\ttable = tabtab[getwrd()];\n\t\t\tline = getwrd();\n\t\t\twhile(c--)\n\t\t\t\t*sp++ = getwrd();\n\t\t\trcexpr(tree, table, 0);\n\t\t} else\n\t\t\tputchar(c);\n\t}\n\n\texit(nerror!=0);\n}\n\n/*\n * Finds a code generation template in the generation table.\n * Returns a pointer to the template string.\n *\n * tree is an unfixed pointer\n * nreg - number of available registers\n */\nchar *match(tree, table, nreg)\nint tree[], table[]; {\n\tint op, d1, d2, t1, t2, *p1, *p2;\n\tchar *mp;\n\n\t/* t1/t2 - type of the result of subtree, d1/d2 - difficulty of the subtree */\n\n\tif (tree==0)\n\t\treturn(0);\n\n\ttree = fixp(tree);\n\top = *tree;\n\tif (op>=29)\t\t\t/* if not leaf */\n\t\tp1 = fixp(tree[3]);\n\telse\n\t\tp1 = tree;\n\tt1 = p1[1];\n\td1 = dcalc(p1, nreg);\n\tif ((opdope[op]&01)!=0) {\t/* binary? */\n\t\tif(tree[4]!=0) { /* in function calls second argument is empty at this point */\n    \t\tp2 = fixp(tree[4]);\n            t2 = p2[1];\n            d2 = dcalc(p2, nreg);\n        } else {\n\t\t    p2 = 0;\n\t\t}\n\t}\n\n\t/* Look up the entries for this operator */\n\twhile(*table) {\n\t\tif (*table++ == op) goto foundop;\n\t\ttable++;\n\t}\n\treturn(0);\nfoundop:\n\ttable = *table;\nnxtry:\n    /* Iterate over the list of templates for this op */\n\tmp = table;\n\tif (*mp == 0)\n\t\treturn(0);\n\tif (d1 > (*mp&077) | (*mp>=0100)&(*p1!=36)) /* tree1 has a difficulty level <= than this condition, or this is a pointer */\n\t\tgoto notyet;\n\tif (notcompat(t1, mp[1]))\n\t\tgoto notyet;\n\tif ((opdope[op]&01)!=0 & p2!=0) {  /* binary op, check second argument */\n\t\tif (d2 > (mp[2]&077) | (mp[2]>=0100)&(*p2!=36))\n\t\t\tgoto notyet;\n\t\tif (notcompat(t2,mp[3]))\n\t\t\tgoto notyet;\n\t}\nnow:\n\treturn(table[1]);  /* parameters are 4bytes = 1 word */\nnotyet:\n\ttable = table+2;  /* jump to next entry in table (on entry is 4 bytes + 1 sizeof(int *) ) */\n\tgoto nxtry;\n}\n\n/*\n * Generates code for this expression. If the instruction does not have a matching entry\n * in one of the specialized code tables, it falls back to regtab and moves the result\n * to the appropriate place.\n *\n * tree is an unfixed pointer\n * reg - result should go into this register if table==regtab;\n *       Additionally, the code generator should leave lower numbered registers alone,\n *       and only use reg or higher numbered registers.\n */\nvoid rcexpr(tree, table, reg)\nint tree[], table[]; {\n    int *origtree;\n\n\tif(tree==0)\n\t\treturn;\n\n\torigtree = tree;\n\ttree = fixp(tree);\n\n\tif(*tree >= 103) {  /* conditional jump */\n\t    if(*tree==103)\n\t        jumpc(tree[1],tree[2],tree[3]);\n\t    else\n\t        cbranch(tree[1],tree[2],tree[3],0);\n\n\t\treturn;\n\t}\n\tif (cexpr(origtree, table, reg))\n\t\treturn;\n\tif (table!=regtab)\n\t\tif(cexpr(origtree, regtab, reg)) {\n\t\t\tif (table==sptab)\n\t\t\t\tprintf(\"mov\tr%d,-(sp)\\n\", reg);\n\t\t\tif (table==cctab)\n\t\t\t\tprintf(\"tst\tr%d\\n\", reg);\n\t\t\treturn;\n\t\t}\n\terror1(\"No match for op %d\", *tree);\n}\n\n/*\n * Generate code using the given table. If a template was found\n * and the code successfully generated then returns 1, otherwise 0.\n *\n * tree is an unfixed pointer\n * reg - result should go into this register if table==regtab;\n *       Additionally, the code generator should leave lower numbered registers alone,\n *       and only use reg or higher numbered registers.\n */\ncexpr(tree, table, reg)\nint tree[], table[]; {\n\tint *p1, *fp1, *p2, *fp2, c, r, *p, *otable, *ctable, *origtree;\n\tchar *string;\n\n\torigtree = tree;\n\ttree = fixp(tree);\n\n\tif ((c = *tree)==100) {\t\t/* function call, push params on stack */\n\t\tp1 = tree[3];\n\t\tp2 = tree[4];\n\t\tfp2 = fixp(p2);\n\t\tr = 0;\n\t\tif(p2) {\n\t\t\twhile (*fp2==9) { /* comma */\n\t\t\t\trcexpr(fp2[4], sptab, 0);\n\t\t\t\tr += rlength(fixp(p=fp2[4])[1]);\n\t\t\t\tp2 = fp2[3];\n\t\t\t\tfp2 = fixp(p2);\n\t\t\t}\n\t\t\trcexpr(p2, sptab, 0);\n\t\t\tr += rlength(fp2[1]);\n\t\t}\n\t\t*tree = 101;\n\t\ttree[2] = r;\t\t/* save arg length */\n\t}\n\tif(c==90) {\t\t/* ? */\n\t\tcbranch(tree[3], c=isn++, 0, reg);\n\t\trcexpr(fixp(tree[4])[3], table, reg);\n\t\tbranch(r=isn++, 0, 0);\n\t\tlabel(c);\n\t\trcexpr(fixp(tree[4])[4], table, reg);\n\t\tlabel(r);\n\t\treturn(1);\n\t}\n\tif ((string=match(origtree, table, nreg-reg))==0)  /* find code template */\n\t\treturn(0);\n\tp1 = tree[3];\n\tp2 = tree[4];\n\tfp1 = fixp(p1);\n\tfp2 = fixp(p2);\nloop:\n\tswitch(c = *string++) {\n\n\tcase '\\0':\n\t\tp = tree;\n\t\tif (*p==101 & p[2]>0) {  /* if this was a function call, pop parameters from stack. */\n\t\t\tpopstk(p[2]);\n\t\t}\n\t\treturn(1);\n\n\t/* A1 */\n\tcase 'A':\n\t\tp = fixp(tree[3]);\n\t\tgoto adr;\n\n\t/* A2 */\n\tcase 'B':\n\t\tp = fixp(tree[4]);\n\t\tgoto adr;\n\n\t/* A */\n\tcase 'O':\n\t\tp = tree;\n\tadr:\n\t\tpname(p);\n\t\tgoto loop;\n\n\t/* I */\n\tcase 'M':\n\t\tif ((c = *string)=='\\'')\n\t\t\tstring++; else\n\t\t\tc = 0;\n\t\tprins(*tree, c);\n\t\tgoto loop;\n\n\t/* B1 */\n\tcase 'C':\n\t\tp = fixp(tree[3]);\n\t\tgoto pbyte;\n\n\t/* BF */\n\tcase 'P':\n\t\tp = tree;\n\t\tgoto pb1;\n\n\t/* B2 */\n\tcase 'D':\n\t\tp = fixp(tree[4]);\n\tpbyte:\n\t\tif (p[1]==1)\t/* char type? */\n\t\t\tputchar('b');\npb1:\n\t\tif (isfloat(p, 0))\n\t\t\tputchar('f');\n\t\tgoto loop;\n\n\t/* BE */\n\tcase 'L':\n\t\tif (fixp(tree[3])[1]==1 | fixp(tree[4])[1]==1)\n\t\t\tputchar('b');\n\t\tgoto loop;\n\n\t/* C1 */\n\tcase 'E':\n\t\tp = fp1[3];\n\t\tgoto constl;\n\n\t/* C2 */\n\tcase 'F':\n\t\tp = fp2[3];\n\tconstl:\n\t\tprintf(\"%o\", p);\n\t\tgoto loop;\n\n\t/* F */\n\tcase 'G':\n\t\tp = p1;\n\t\tgoto subtre;\n\n\t/* S */\n\tcase 'K':\n\t\tp = p2;\n\t\tgoto subtre;\n\n\t/* H */\n\tcase 'H':\n\t\tp = origtree;\n\n\tsubtre:\n\t\tctable = regtab;\n\t\tr = reg;\n\t\tc = *string++ - 'A';\n\t\tif ((c&02)!=0)  /* should it go to stack? */\n\t\t\tctable = sptab;\n\t\tif ((c&04)!=0)  /* is it a conditional expression? */\n\t\t\tctable = cctab;\n\t\tif((c&010)!=0)  /* F1, S1, H1 - using the next register */\n\t\t\tr = reg+1;\n\t\tif((c&01)!=0)\n\t\t\tif(*fixp(p)==36) { /* if this has the shape *(x+c), print tree for x only */\n\t\t\t\tp = fixp(p)[3];\n\t\t\t\tif(collcon(fixp(p)) & (ctable!=sptab))\n\t\t\t\t\tp = fixp(p)[3];\n\t\t\t}\n\t\trcexpr(p, ctable, r);\n\t\tgoto loop;\n\n\t/* R */\n\tcase 'I':\n\t\tr = reg;\n\t\tgoto preg;\n\n\t/* R1 */\n\tcase 'J':\n\t\tr = reg+1;\n\tpreg:\n\t\tprintf(\"r%d\", r);\n\t\tgoto loop;\n\n\tcase '#':\n\t\tp = fp1[3];\n\t\tgoto nmbr;\n\n\tcase '\"':\n\t\tp = fp2[3];\n\t\tgoto nmbr;\n\tcase '~':\n\t\tp = tree[3];\n\n\tnmbr:\n\t    p = fixp(p);\n\t\tif(collcon(p)) {  /* If this has the form *(x+const), print const */\n\t\t\tc = *p;\n\t\t\tif(r = fixp(p=p[4])[3])\n\t\t\t\tprintf(\"%o\", c==40?r:-r);\n\t\t}\n\t\tgoto loop;\n\n\t/* M */\n\tcase 'N':\n\t\tif ((c=isfloat(tree, &string))==fltmod)\n\t\t\tgoto loop;\n\t\tprintf((fltmod=c)==2?\"setf\\n\":\"setd\\n\");\n\t\tgoto loop;\n\n\t/* Z */\n\tcase 'Z':\n\t\tprintf(\"$%o\", fp1[4]);\n\t\tgoto loop;\n\n\t}\n\tputchar(c);\n\tfflush(stdout);\n\tgoto loop;\n}\n\n/* Prints the value/label/location of a tree node. p is a fixed pointer */\nvoid pname(p)\nint *p; {\n\tchar *np;\n\tint i;\n\nloop:\n\tswitch(*p) {\n\n\tcase 21:\t\t/* const */\n\t\tprintf(\"$%o\", p[3]);\n\t\treturn;\n\n\tcase 22:\t\t/* string */\n\t\tprintf(\"$l%d\", p[3]);\n\t\treturn;\n\n\tcase 20:\t\t/* name */\n\t\tswitch(p[3]) {\n\n\t\tcase 5:\t\t/* auto, param */\n\t\t\tprintf(\"%o(r5)\", p[4]);\n\t\t\treturn;\n\n\t\t/* extern */\n\t\tcase 6:\n\t\t\tprintf(\"%p\", &p[4]);\n\t\t\treturn;\n\n\t\t}\n\t\tprintf(\"l%d\", p[4]);  /* static */\n\t\treturn;\n\n\tcase 35:\t\t/* & */\n\t\tputchar('$');\n\t\tp = fixp(p[3]);\n\t\tgoto loop;\n\n\tcase 36:\t\t/* * */\n\t\tputchar('*');\n\t\tp = fixp(p[3]);\n\t\tgoto loop;\n\t}\n\terror(\"pname called illegally\");\n}\n\n/*\n * Difficulty level calculation.\n * p points to a fixed optable entry.\n * nreg - number of free registers.\n */\ndcalc(p, nreg)\nint p[]; {\n\tint op, t;\n\n\tif (p==0)\n\t\treturn(0);\n\top = *p;\n\tswitch (op) {\n\n\tcase 20:\t\t/* name */\n\tcase 22:\t\t/* string */\n\tcase 23:\t\t/* float */\n\tcase 24:\t\t/* double */\n\t\treturn(12);\n\n\tcase 21:\t\t/* short constant */\n\t\treturn(p[3]==0? 4:8);\n\n\tcase 35:\t\t/* & */\n\t\treturn(12);\n\n\tcase 36:\t\t/* * */\n\t\tif ((op=dcalc(fixp(p[3]), nreg))<16)  /* if argument of pointer is constant/simple name, this is PDP-11 addressible */\n\t\t\treturn(16);\n\t}\n\ndef:\n\treturn(p[2]<=nreg? 20: 24);  /* can this tree be calculated using nreg registers? */\n}\n\n/*\n * Checks if the two type: at and st are not compatible\n * at - type in the tree\n * st - type in the code template table\n * */\nnotcompat(at, st) {\n\n\tif (st==0)\t\t/* word, byte */\n\t\treturn(at>1 & at<16);  /* can store char or int only */\n\tif (st==1)\t\t/* word */\n\t\treturn(at>0 & at<16);  /* can store int only */\n\tst -= 2;\n\tif (st==2 & at==3)\n\t\tat = 2;\n\treturn(st != at);\n}\n\n/*\n * Prints the instruction belonging to this opcode. c decides whether\n * the first or the second subinstruction should be printed.\n */\nvoid prins(op, c) {\n\tint *insp;\n\tchar **insstrp;\n\tchar *s;\n\n\tinsp = instabcode;\n\tinsstrp = instabstr;\n\twhile(*insp) {\n\t\tif (*insp == op) {\n\t\t\tif ((s = insstrp[c!=0])==NULL)\n\t\t\t\tgoto err;\n\t\t\tprintf(\"%s\", s);\n\t\t\treturn;\n\t\t} else {\n            insp = insp + 1;\n            insstrp +=2;\n        }\n\t}\nerr:\n\terror1(\"No match for op %d\", op);\n}\n\n/* True if p is in 'x+const' form */\ncollcon(p)\nint p[]; {\n\tint *p1;\n\n\tif(*p==40 | *p==41)\n\t\tif(*(p1=fixp(p[4]))==21)\n\t\t\treturn(1);\n\treturn(0);\n}\n\n/* tree - correct pointer into ospace */\nisfloat(t, s)\nint t[];\nchar *s[];\n{\n\tint rt;\n\n\tif(s!= 0) {\n        rt = **s - '0';\n        if (rt==2 | rt==4) {\n            (*s)++;\n            return(rt>2?3:2);\n        }\n    }\n\tif ((opdope[t[0]]&010)!=0)\t/* relational */\n\t\tt = fixp(t[3]);\n\tif ((rt=t[1])>=2 && rt<=3)  /* type is float or double */\n\t\treturn(rt);\n\treturn(0);\n}\n\nint *baseptr=0;\nnreg = 4;  /* number of available registers */\nisn = 10000;\nnamsiz = 8;  /* max length of a name */\nFILE* fout;\nline;\ntmpfil;\nnerror;\nfltmod;\n\n"
  },
  {
    "path": "src/c11.c",
    "content": "#include \"c1.h\"\n\n/*\n * Tree is a n unfixed pointer to the conditional expression.\n * lbl - label to jump to\n * cond - 0: jump if condition is false, 1: jump if condition is true\n */\nvoid jumpc(tree, lbl, cond)\nint tree[]; {\n\tint l1, l2, *origtree;\n\n\tif (tree==0)\n\t\treturn;\n\n    origtree=tree;\n\ttree=fixp(tree);\n\n\tswitch(*tree) {\n\n\t/* & */\n\tcase 47:\n\t\tif (cond) {\n\t\t\tcbranch(tree[3], l1=isn++, 0, 0);\n\t\t\tcbranch(tree[4], l1, 0, 0);\n\t\t\tjump(lbl);\n\t\t\tlabel(l1);\n\t\t} else {\n\t\t\tcbranch(tree[3], l1=isn++, 0, 0);\n\t\t\tcbranch(tree[4], l2=isn++, 1, 0);\n\t\t\tlabel(l1);\n\t\t\tjump(lbl);\n\t\t\tlabel(l2);\n\t\t}\n\t\treturn;\n\n\t/* | */\n\tcase 48:\n\t\tif (cond) {\n\t\t\tcbranch(tree[3], l1=isn++, 1, 0);\n\t\t\tcbranch(tree[4], l2=isn++, 0, 0);\n\t\t\tlabel(l1);\n\t\t\tjump(lbl);\n\t\t\tlabel(l2);\n\t\t} else {\n\t\t\tcbranch(tree[3], l1=isn++, 1, 0);\n\t\t\tcbranch(tree[4], l1, 1, 0);\n\t\t\tjump(lbl);\n\t\t\tlabel(l1);\n\t\t}\n\t\treturn;\n\n\t/* ! */\n\tcase 34:\n\t\tjumpc(tree[3], lbl, !cond);\n\t\treturn;\n\t}\n\trcexpr(origtree, cctab, 0);\n\tbranch(l1=isn++, *tree, cond);\n\tjump(lbl);\n\tlabel(l1);\n\treturn;\n}\n\n/*\n * Tree is an unfixed pointer to the conditional expression.\n * lbl - label to jump to\n * cond - 0: jump if condition is false, 1: jump if condition is true\n */\nvoid cbranch(tree, lbl, cond, reg)\nint tree[]; {\n\tint l1, *origtree;\n\n\tif (tree==0)\n\t\treturn;\n\n\torigtree=tree;\n\ttree=fixp(tree);\n\tswitch(*tree) {\n\n\t/* & */\n\tcase 47:\n\t\tif (cond) {\n\t\t\tcbranch(tree[3], l1=isn++, 0, reg);\n\t\t\tcbranch(tree[4], lbl, 1, reg);\n\t\t\tlabel(l1);\n\t\t} else {\n\t\t\tcbranch(tree[3], lbl, 0, reg);\n\t\t\tcbranch(tree[4], lbl, 0, reg);\n\t\t}\n\t\treturn;\n\n\t/* | */\n\tcase 48:\n\t\tif (cond) {\n\t\t\tcbranch(tree[3], lbl, 1, reg);\n\t\t\tcbranch(tree[4], lbl, 1, reg);\n\t\t} else {\n\t\t\tcbranch(tree[3], l1=isn++, 1, reg);\n\t\t\tcbranch(tree[4], lbl, 0, reg);\n\t\t\tlabel(l1);\n\t\t}\n\t\treturn;\n\n\t/* ! */\n\tcase 34:\n\t\tcbranch(tree[3], lbl, !cond, reg);\n\t\treturn;\n\t}\n\trcexpr(origtree, cctab, reg);\n\tbranch(lbl, *tree, !cond);\n\treturn;\n}\n\n\nbranch(lbl, op, c) {\n\tif(op) {\n\t\tif((opdope[op]&04)==0)  /* conditional jump? */\n\t\t\top = 61;\n\t\tprins(op,c);\n\t} else\n\t\tprintf(\"br\");\n\tprintf(\"\\tl%d\\n\", lbl);\n}\n\njump(lab) {\n\tprintf(\"jmp\\tl%d\\n\", lab);\n}\n\nlabel(l) {\n\tprintf(\"l%d:\", l);\n}\n\n/* Decreases the stack size, moving sp the required amounts. */\nvoid popstk(a) {\n\n\tswitch(a) {\n\n\tcase 0:\n\t\treturn;\n\n\tcase 2:\n\t\tprintf(\"tst\t(sp)+\\n\");\n\t\treturn;\n\n\tcase 4:\n\t\tprintf(\"cmp\t(sp)+,(sp)+\\n\");\n\t\treturn;\n\t}\n\tprintf(\"add\t$%o,sp\\n\", a);\n}\n\nint *fixp(p)\nint *p; {\n    return (void*)p-(void*)baseptr+(void*)ospace;\n}\n\nlength(t) {\n\n\tif (t<0)\n\t\tt += 020;\n\tif (t>=020)\n\t\treturn(2);\n\tswitch(t) {\n\n\tcase 0:\n\t\treturn(2);\n\n\tcase 1:\n\t\treturn(1);\n\n\tcase 2:\n\t\treturn(4);\n\n\tcase 3:\n\t\treturn(8);\n\n\tcase 4:\n\t\treturn(4);\n\n\t}\n\treturn(1024);\n}\n\n/* rounded length */\nrlength(c) {\n\tauto l;\n\n\treturn((l=length(c))==1? 2: l);\n}\n\n/* Get a number from the input file */\nint getwrd() {\n    int i;\n    char c;\n\n    scanf(\"%d\", &i);\n    c = getchar();\n    if(c!=';') {\n        error1(\"Unknown char id: %d\", (int) c);\n    }\n\n    return i;\n}\n\nprintn(n,b) {\n\tauto a;\n\n\tif(a=n/b) /* assignment, not test for equality */\n\t\tprintn(a, b); /* recursive */\n\tputchar(n%b + '0');\n}\n\ncc_putchar(int c)\n{\n    putc(c, fout);\n}\n\nvoid cc_printf(char *fmt, ...)\n{\n\tstatic char *s;\n\tauto *adx, x, c, *i;\n\tva_list arguments;\n\n    va_start ( arguments, fmt);\nloop:\n\twhile((c = *fmt++) != '%') {\n\t\tif(c == '\\0') {\n\t\t    va_end(arguments);\n\t\t    fflush(stdout);\n            return;\n        }\n\t\tputchar(c);\n\t}\n\tswitch (c = *fmt++) {\n\n\tcase 'd': /* decimal */\n\tcase 'o': /* octal */\n\t    x = va_arg(arguments, int);\n\t\tif(x < 0) {\n\t\t\tx = -x;\n\t\t\tif(x<0)  {\t/* - infinity */\n\t\t\t\tif(c=='o')\n\t\t\t\t\tprintf(\"100000\");\n\t\t\t\telse\n\t\t\t\t\tprintf(\"-32767\");\n\t\t\t\tgoto loop;\n\t\t\t}\n\t\t\tputchar('-');\n\t\t}\n\t\tprintn(x, c=='o'?8:10);\n\t\tgoto loop;\n\n\tcase 's': /* string */\n\t    x = va_arg(arguments, int);\n\t    s=x;\n\t\twhile(c = *s++) {\n            putchar(c);\n        }\n\t\tgoto loop;\n\n\tcase 'p':\n\t\ts =va_arg(arguments, int*);\n\t\tputchar('_');\n\t\tc = namsiz;\n\t\twhile(c--)\n\t\t\tif(*s)\n\t\t\t\tputchar(*s++);\n\t\tgoto loop;\n\t}\n\tputchar('%');\n\tfmt--;\n\tgoto loop;\n}\n\nerror(s)\nchar s[];{\n    error2(s, 0, 0);\n}\n\nerror1(s, p1)\nchar s[];{\n    error2(s, p1, 0);\n}\n\n\nerror2(s, p1, p2)\nchar s[];{\n\tFILE *f;\n\n\tnerror++;\n\tfflush(stdout);\n\tf = fout;\n\tfout = stdout;\n\tprintf(\"%d: \", line);\n\tprintf(s, p1, p2);\n\tputchar('\\n');\n\tfout = f;\n}\n\n"
  },
  {
    "path": "src/c1t.c",
    "content": "//\n// Created by veges on 2021. 03. 19..\n//\n#include \"c1.h\"\n\nint instabcode[]={\n    40,\n\t70,\n\t41,\n\t71,\n\t30,\n\t31,\n\t32,\n\t33,\n\n\t45,\n\t46,\n\t75,\n\t76,\n\t43,\n\t44,\n\t73,\n\t74,\n\n\t60,\n\t61,\n\t62,\n\t63,\n\t64,\n\t65,\n\t66,\n\t67,\n\t68,\n\t69,\n\t0,\n};\n\nchar *instabstr[]= {\n\t\"add\", \"add\",  // 1\n\t\"add\", \"add\",\n\t\"sub\", \"sub\",  // 2 sub\n\t\"sub\", \"sub\",\n\t\"inc\", \"add\",  // 3:inc\n\t\"dec\", \"sub\",  //4dec\n\t\"inc\", \"add\",\n\t\"dec\", \"sub\",\n\n\t\"sub\", \"ac\", // 5:ac\n\t\"mov\", \"r4\", //\"6:mov, 7:r4\n\t\"sub\", \"ac\",\n\t\"mov\", \"r4\",\n\t\"r4\", \"divf\", // 1:div7\n\t\"ac\", NULL,\n\t\"r4\", \"add\",\n\t\"ac\", NULL,\n\n    \"beq\", \"bne\", // 0:beq, 1:bne\n\t\"bne\", \"beq\",\n\t\"ble\", \"bgt\", // 2:ble, 5: bgt\n\t\"blt\", \"bge\", // 3:blt, 4:bge\n\t\"bge\", \"blt\",\n\t\"bgt\", \"ble\",\n\t\"blos\", \"bhi\", //6:blos, 9:bhi\n\t\"blo\", \"bhis\", // 7:blo 8:bhis\n\t\"bhis\", \"blo\",\n\t\"bhi\", \"blos\"\n};\n\nint opdope[] = {\n        000000,  // EOF\n        000000,  // ;\n        000000,  // {\n        000000,  // }\n        036000,  // [\n        002000,  // ]\n        036000,  // (\n        002000,  // )\n        002000,  // :\n        007001,  // ,\n        000000,  // 10\n        000000,  // 11\n        000000,  // 12\n        000000,  // 13\n        000000,  // 14\n        000000,  // 15\n        000000,  // 16\n        000000,  // 17\n        000000,  // 18\n        000000,  // 19\n        000000,  // name\n        000000,  // short constant\n        000000,  // string\n        000000,  // float\n        000000,  // double\n        000000,  // 25\n        000000,  // 26\n        000000,  // 27\n        000000,  // 28\n        000000,  // 29\n        034002,  // ++pre\n        034002,  // --pre\n        034002,  // ++post\n        034002,  // --post\n        034020,  // !un\n        034002,  // &un\n        034020,  // *un\n        034000,  // -un\n        034020,  // ~un\n        000000,  // 39\n        030101,  // +\n        030001,  // -\n        032101,  // *\n        032001,  // //\n        032001,  // %\n        026061,  // >>\n        026061,  // <<\n        020161,  // &\n        016161,  // |\n        016161,  // ^\n        000000,  // 50\n        000000,  // 51\n        000000,  // 52\n        000000,  // 53\n        000000,  // 54\n        000000,  // 55\n        000000,  // 56\n        000000,  // 57\n        000000,  // 58\n        000000,  // 59\n        022105,  // ==\n        022105,  // !=\n        024105,  // <=\n        024105,  // <\n        024105,  // >=\n        024105,  // >\n        024105,  // <p\n        024105,  // <=p\n        024105,  // >p\n        024105,  // >=p\n        012013,  // =+\n        012013,  // =-\n        012013,  // =*\n        012013,  // =//\n        012013,  // =%\n        012053,  // =>>\n        012053,  // =<<\n        012053,  // =&\n        012053,  // =|\n        012053,  // =^\n        012013,  // =\n        000000,  // 81\n        000000,  // 82\n        000000,  // 83\n        000000,  // int -> float\n        000000,  // int -> double\n        000000,  // float -> int\n        000000,  // float -> double\n        000000,  // double -> int\n        000000,  // double -> float\n        014001,  // ?\n        000000,  // 91\n        000000,  // 92\n        000000,  // 93\n        000000,  // int -> float\n        000000,  // int -> double\n        000000,  // float -> double\n        000000,  // int -> int[]\n        000000,  // int -> float[]\n        000000,  // int -> double[]\n        036001,  // call\n        036001  // mcall\n};"
  },
  {
    "path": "src/c1t.s",
    "content": "/ C operator tables\n\n.globl\t_getwrd\n\n.globl\tgetw\n.globl\tfopen\n.globl\t_tmpfil\n\n.data\n_getwrd: 1f\n.text\n1:\n\ttst\tbuf\n\tbne\t1f\n\tmov\t_tmpfil,r0\n\tjsr\tr5,fopen; buf\n\tbes\tbotchp\n1:\n\tjsr\tr5,getw; buf\n\tbes\tbotchp\n\trts\tpc\nbotchp:\n\tmov\t$1,r0\n\tsys\twrite; botch; ebotch-botch\n\tsys\texit\nbotch:\n\t<Temp file botch.\\n>; ebotch:\n.even\n.bss\nbuf:\t.=.+518.\n.text\n.globl\t_opdope\n.globl\t_instab\n\n_instab:.+2\n\t40.; 1f; 1f; .data; 1:<add\\0>; .text\n\t70.; 1b; 1b\n\t41.; 2f; 2f; .data; 2:<sub\\0>; .text\n\t71.; 2b; 2b\n\t30.; 3f; 1b; .data; 3:<inc\\0>; .text\n\t31.; 4f; 2b; .data; 4:<dec\\0>; .text\n\t32.; 3b; 1b\n\t33.; 4b; 2b\n\n\t45.; 2b; 5f; .data; 5:<ac\\0>; .text\n\t46.; 6f; 7f; .data; 6:<mov\\0>; 7:<(r4)\\0>; .text\n\t75.; 2b; 5b\n\t76.; 6b; 7b\n\t43.; 7b; 1f; .data; 1:<divf\\0>; .text\n\t44.; 5b; 0\n\t73.; 7b; 1b\n\t74.; 5b; 0\n\n\t60.; 0f; 1f; .data; 0:<beq\\0>; 1:<bne\\0>; .text\n\t61.; 1b; 0b\n\t62.; 2f; 5f; .data; 2:<ble\\0>; 5:<bgt\\0>; .text\n\t63.; 3f; 4f; .data; 3:<blt\\0>; 4:<bge\\0>; .text\n\t64.; 4b; 3b\n\t65.; 5b; 2b\n\t66.; 6f; 9f; .data; 6:<blos\\0>; 9:<bhi\\0>; .text\n\t67.; 7f; 8f; .data; 7:<blo\\0>; 8:<bhis\\0>; .text\n\t68.; 8b; 7b\n\t69.; 9b; 6b\n\t0\n\t.data\n\t.even\n\t.text\n\n_opdope:.+2\n\t00000\t/ EOF\n\t00000\t/ ;\n\t00000\t/ {\n\t00000\t/ }\n\t36000\t/ [\n\t02000\t/ ]\n\t36000\t/ (\n\t02000\t/ )\n\t02000\t/ :\n\t07001\t/ ,\n\t00000\t/ 10\n\t00000\t/ 11\n\t00000\t/ 12\n\t00000\t/ 13\n\t00000\t/ 14\n\t00000\t/ 15\n\t00000\t/ 16\n\t00000\t/ 17\n\t00000\t/ 18\n\t00000\t/ 19\n\t00000\t/ name\n\t00000\t/ short constant\n\t00000\t/ string\n\t00000\t/ float\n\t00000\t/ double\n\t00000\t/ 25\n\t00000\t/ 26\n\t00000\t/ 27\n\t00000\t/ 28\n\t00000\t/ 29\n\t34002\t/ ++pre\n\t34002\t/ --pre\n\t34002\t/ ++post\n\t34002\t/ --post\n\t34020\t/ !un\n\t34002\t/ &un\n\t34020\t/ *un\n\t34000\t/ -un\n\t34020\t/ ~un\n\t00000\t/ 39\n\t30101\t/ +\n\t30001\t/ -\n\t32101\t/ *\n\t32001\t/ /\n\t32001\t/ %\n\t26061\t/ >>\n\t26061\t/ <<\n\t20161\t/ &\n\t16161\t/ |\n\t16161\t/ ^\n\t00000\t/ 50\n\t00000\t/ 51\n\t00000\t/ 52\n\t00000\t/ 53\n\t00000\t/ 54\n\t00000\t/ 55\n\t00000\t/ 56\n\t00000\t/ 57\n\t00000\t/ 58\n\t00000\t/ 59\n\t22105\t/ ==\n\t22105\t/ !=\n\t24105\t/ <=\n\t24105\t/ <\n\t24105\t/ >=\n\t24105\t/ >\n\t24105\t/ <p\n\t24105\t/ <=p\n\t24105\t/ >p\n\t24105\t/ >=p\n\t12013\t/ =+\n\t12013\t/ =-\n\t12013\t/ =*\n\t12013\t/ =/\n\t12013\t/ =%\n\t12053\t/ =>>\n\t12053\t/ =<<\n\t12053\t/ =&\n\t12053\t/ =|\n\t12053\t/ =^\n\t12013\t/ =\n\t00000\t/ 81\n\t00000\t/ 82\n\t00000\t/ 83\n\t00000\t/ int -> float\n\t00000\t/ int -> double\n\t00000\t/ float -> int\n\t00000\t/ float -> double\n\t00000\t/ double -> int\n\t00000\t/ double -> float\n\t14001\t/ ?\n\t00000\t/ 91\n\t00000\t/ 92\n\t00000\t/ 93\n\t00000\t/ int -> float\n\t00000\t/ int -> double\n\t00000\t/ float -> double\n\t00000\t/ int -> int[]\n\t00000\t/ int -> float[]\n\t00000\t/ int -> double[]\n\t36001\t/ call\n\t36001\t/ mcall\n"
  },
  {
    "path": "src/cctab.s",
    "content": "/ c code tables-- set condition codes\n\n.globl\t_cctab\n\n_cctab=.;.+2\n\t20.;\trest\n\t21.;\trest\n\t22.;\trest\n\t30.;\trest\n\t31.;\trest\n\t34.;\trest\n\t35.;\trest\n\t36.;\trest\n\t37.;\trest\n\t40.;\trest\n\t41.;\trest\n\t42.;\trest\n\t43.;\trest\n\t44.;\trest\n\t45.;\trest\n\t46.;\trest\n\t47.;\trest\n\t48.;\trest\n\t60.;\tcc60\n\t61.;\tcc60\n\t62.;\tcc60\n\t63.;\tcc60\n\t64.;\tcc60\n\t65.;\tcc60\n\t66.;\tcc60\n\t67.;\tcc60\n\t68.;\tcc60\n\t69.;\tcc60\n\t70.;\trest\n\t71.;\trest\n\t72.;\trest\n\t73.;\trest\n\t74.;\trest\n\t75.;\trest\n\t76.;\trest\n\t77.;\trest\n\t78.;\trest\n\t79.;\trest\n\t80.;\trest\n\n/ relationals\ncc60:\n%a,z\n\ttstB1\tA1\n\n%n*,z\n\tF*\n\ttstB1\t#1(R)\n\n%n,z\n\tF\n\ttst\tR\n\n%a,a\n\tcmpBE\tA1,A2\n\n%n*,a\n\tF*\n\tcmpBE\t#1(R),A2\n\n%n,a\n\tF\n\tcmpB2\tR,A2\n\n%n*,e*\n\tF*\n\tS1*\n\tcmpBE\t#1(R),#2(R1)\n\n%n*,e\n\tF*\n\tS1\n\tcmpB1\t#1(R),R1\n\n%n,e*\n\tF\n\tS1*\n\tcmpB2\tR,#2(R1)\n\n%n,e\n\tF\n\tS1\n\tcmp\tR,R1\n\n%n*,n*\n\tFS*\n\tS*\n\tcmpBE\t(sp)+,#2(R)\n\n%n*,n\n\tFS*\n\tS\n\tcmpB1\t*(sp)+,R\n\n%n,n*\n\tFS\n\tS*\n\tcmpB2\t(sp)+,#2(R)\n\n%n,n\n\tFS\n\tS\n\tcmp\t(sp)+,R\n\n/ set codes right\nrest:\n%n,n\n\tH\n\n.data\n.even\n.text\n\n"
  },
  {
    "path": "src/config.h",
    "content": "// Use V5 style ABI, instead of the original V2 one\n// the difference is how labels are pointing to functions\n//#define UNIXV5_ABI"
  },
  {
    "path": "src/cvopt.c",
    "content": "#include <stdio.h>\n\n#define getc cc_getc\ngetc();\nflag();\n\npeekc = 0;\nnofloat = 0;\nvoid main() {\n/*\n  converts code generation template .s files by replacing % part using the rules below:\n\tA1 -> A\n\tA2    B\n\tA     O\n\tB1    C\n\tB2    D\n\tBE    L\n\tBF    P\n\tC1    E\n\tC2    F\n\tF     G\n\tH     H\n\tR     I\n\tR1    J\n\tS     K\n\tI     M\n\tM     N\n\n\t\t*\t+1\n\t\tS\t+2\n\t\tC\t+4\n\t\t1\t+8\n\n\tz  -> 4\n\tc     10\n\ta     14\n\te     20\n\tn     63\n\t*\t+0100\n*/\n\n\tauto c,snlflg,nlflg,t,smode,m,ssmode;\n\n\t/*\n\t * ssmode: next non % should output a data segment header\n\t */\n\n\tsmode = nlflg = snlflg = ssmode = 0;\nloop:\n\tc = getc();\n\tif (c!='\\n' & c!='\\t') nlflg = 0;\n\tif (ssmode!=0 & c!='%') {\n\t\tssmode = 0;\n\t\tprintf(\".data\\n1: .ascii \\\"\");\n\t}\n\tswitch(c) {\n\n\tcase '\\0':\n\t\tprintf(\".text; .int 0\\n\");\n\t\tfflush(stdout);\n\t\treturn;\n\n\tcase ':':\n\t\tif (!smode)  /* convert into pointer */\n\t\t\tprintf(\"=.+4; .int 0\"); else  /* should be sizeof(int*) */\n\t\t\tputchar(':');\n\t\tgoto loop;\n\n\tcase 'A':\n\t\tif ((c=getc())=='1' | c=='2') {\n\t\t\tputchar(c+'A'-'1');\n\t\t\tgoto loop;\n\t\t}\n\t\tputchar('O');\n\t\tpeekc = c;\n\t\tgoto loop;\n\n\tcase 'B':\n\t\tswitch (getc()) {\n\n\t\tcase '1':\n\t\t\tputchar('C');\n\t\t\tgoto loop;\n\n\t\tcase '2':\n\t\t\tputchar('D');\n\t\t\tgoto loop;\n\n\t\tcase 'E':\n\t\t\tputchar('L');\n\t\t\tgoto loop;\n\n\t\tcase 'F':\n\t\t\tputchar('P');\n\t\t\tgoto loop;\n\t\t}\n\t\tputchar('?');\n\t\tgoto loop;\n\n\tcase 'C':\n\t\tputchar(getc()+'E'-'1');\n\t\tgoto loop;\n\n\tcase 'F':\n\t\tputchar('G');\n\t\tgoto subtre;\n\n\tcase 'R':\n\t\tif ((c=getc()) == '1')\n\t\tputchar('J'); else {\n\t\t\tputchar('I');\n\t\t\tpeekc = c;\n\t\t}\n\t\tgoto loop;\n\n\tcase 'H':\n\t\tputchar('H');\n\t\tgoto subtre;\n\n\tcase 'I':\n\t\tputchar('M');\n\t\tgoto loop;\n\n\tcase 'M':\n\t\tputchar('N');\n\t\tsnlflg++;\n\t\tgoto loop;\n\n\tcase 'S':\n\t\tputchar('K');\nsubtre:\n\t\tsnlflg = 1;\n\t\tt = 'A';\nl1:\n\t\tswitch (c=getc()) {\n\n\t\tcase '*':\n\t\t\tt++;\n\t\t\tgoto l1;\n\n\t\tcase 'S':\n\t\t\tt += 2;\n\t\t\tgoto l1;\n\n\t\tcase 'C':\n\t\t\tt += 4;\n\t\t\tgoto l1;\n\n\t\tcase '1':\n\t\t\tt += 8;\n\t\t\tgoto l1;\n\t\t}\n\t\tpeekc = c;\n\t\tputchar(t);\n\t\tgoto loop;\n\n\tcase '#':\n\t\tif(getc()=='1')\n\t\t\tputchar('#'); else\n\t\t\tprintf(\"\\\\\\\"\");\n\t\tgoto loop;\n\n\tcase '%':\n\t\tif (smode)\n\t\t\tprintf(\".text;\");\nloop1:\n\t\tswitch (c=getc()) {\n\n\t\tcase 'a':\n\t\t\tm = 16;\n\t\t\tt = flag();\n\t\t\tgoto pf;\n\n\t\tcase ',':\n\t\t\tputchar(';');\n\t\t\tgoto loop1;\n\n\t\tcase 'i':\n\t\t\tm = 12;\n\t\t\tt = flag();\n\t\t\tgoto pf;\n\t\tcase 'z':\n\t\t\tm = 4;\n\t\t\tt = 0;\n\t\t\tgoto pf;\n\n\t\tcase 'c':\n\t\t\tt = 0;\n\t\t\tm = 8;\n\t\t\tgoto pf;\n\n\t\tcase 'e':\n\t\t\tt = flag();\n\t\t\tm = 20;\n\t\t\tgoto pf;\n\n\t\tcase 'n':\n\t\t\tt = flag();\n\t\t\tm = 63;\npf:\n\t\t\tif ((c=getc())=='*')\n\t\t\t\tm += 0100; else\n\t\t\t\tpeekc = c;\n\t\t\tprintf(\".byte 0%o,0%o\", m, t);\n\t\t\tgoto loop1;\n\n\t\tcase '\\n':\n\t\t\tprintf(\";.int 1f\\n\");\n\t\t\tssmode = 1;\n\t\t\tnlflg = 1;\n\t\t\tsmode = 1;\n\t\t\tgoto loop;\n\t\t}\n\t\tputchar(c);\n\t\tgoto loop1;\n\n\tcase '\\t':\n\t\tif (nlflg) {\n\t\t\tnlflg = 0;\n\t\t\tgoto loop;\n\t\t}\n\t\tputchar('\\t');\n\t\tgoto loop;\n\n\tcase '\\n':\n\t\tif (!smode)  {  /* outside optree definition just emit new line */\n\t\t\tputchar('\\n');\n\t\t\tgoto loop;\n\t\t}\n\t\tif (nlflg) {  /* empty line, close off optree section */\n\t\t\tnlflg = 0;\n\t\t\tprintf(\"\\\\0\\\"\\n.text\\n\");\n\t\t\tsmode = 0;\n\t\t\tgoto loop;\n\t\t}\n\t\tif (!snlflg)\n\t\t\tprintf(\"\\\\n\");\n\t\tsnlflg = 0;\n\t\tprintf(\"\\\"\\n.ascii \\\"\");\n\t\tnlflg = 1;\n\t\tgoto loop;\n\t}\n\tputchar(c);\n\tgoto loop;\n}\n\n/* Gets the next character, ignores blocks of codes inside { } */\ngetc() {\n\tauto t, ifcnt;\n\n\tifcnt = 0;\ngc:\n\tif (peekc) {\n\t\tt = peekc;\n\t\tpeekc = 0;\n\t} else\n\t\tt = getchar();\n\tif (t==0 | t==EOF)\n\t\treturn(0);\n\tif (t=='{') {\n\t\tifcnt++;\n\t\tt = getchar();\n\t}\n\tif (t=='}') {\n\t\tt = getc();\n\t\tif (--ifcnt==0)\n\t\t\tif (t=='\\n')\n\t\t\t\tt = getc();\n\t}\n\tif (ifcnt & nofloat)\n\t\tgoto gc;\n\treturn(t);\n}\n\nflag() {\n\tauto c, f;\n\n\tf = 0;\nl1:\n\tswitch(c=getc()) {\n\n\tcase 'w':  /* word */\n\t\tf = 1;\n\t\tgoto l1;\n\n\tcase 'i':\n\t\tf = 2;\n\t\tgoto l1;\n\n\tcase 'b':  /* byte */\n\t\tf = 3;\n\t\tgoto l1;\n\n\tcase 'f':  /* float */\n\t\tf = 4;\n\t\tgoto l1;\n\n\tcase 'd':  /* double */\n\t\tf = 5;\n\t\tgoto l1;\n\n\tcase 'p':  /* pointer? */\n\t\tf += 16;\n\t\tgoto l1;\n\t}\n\tpeekc = c;\n\treturn(f);\n}\n\n"
  },
  {
    "path": "src/efftab.s",
    "content": "/ c code tables\n\n.globl\t_efftab\n\n_efftab=.;.+2\n\t30.;\tci30\n\t31.;\tci30\n\t32.;\tci30\t/ same as 30\n\t33.;\tci30\t/ same as 31\n\t80.;\tci80\n\t70.;\tci70\n\t71.;\tci70\t/ - like +\n\t77.;\tci77\n\t78.;\tci78\n\t0\n\n/ ++ prefix\nci30:\n%ai,n\n%abp,n\n%ab,n\n\tIB1\tA1\n\n%aip,n\n\tI'\t$2,A1\n\n%nbp*,n\n%ni*,n\n%nb*,n\n\tF\n\tIB1\t#1(R)\n\n%nip*,n\n\tF*\n\tI'\t$2,#1(R)\n\n/ =\nci80:\n%a,z\n\tclrB1\tA1\n\n%n*,z\n\tF*\n\tclrB1\t#1(R)\n\n%a,aw\n\tmovB1\tA2,A1\n\n%a,nw*\n\tS*\n\tmovB1\t#2(R),A1\n\n%a,n\n\tS\n\tmovB1\tR,A1\n\n%n*,aw\n\tF*\n\tmovB1\tA2,#1(R)\n\n%n*,ew*\n\tF*\n\tS1*\n\tmovB1\t#2(R1),#1(R)\n\n%n*,e\n\tF*\n\tS1\n\tmovB1\tR1,#1(R)\n\n%e*,nw*\n\tS*\n\tF1*\n\tmovB1\t#2(R),#1(R1)\n\n%e*,n\n\tS\n\tF1*\n\tmovB1\tR,#1(R1)\n\n%n*,nw*\n\tFS*\n\tS*\n\tmovB1\t#2(R),*(sp)+\n\n%n*,n\n\tFS*\n\tS\n\tmovB1\tR,*(sp)+\n\n/ =| i\nci78:\n%a,a\n\tbisBE\tA2,A1\n\n%a,n\n\tS\n\tbisB1\tR,A1\n\n%n*,a\n\tF*\n\tbisBE\tA2,#1(R)\n\n%e*,n*\n\tS*\n\tF1*\n\tbisBE\t#2(R),#1(R1)\n\n%e*,n\n\tS\n\tF1*\n\tbisBE\tR,#1(R1)\n\n%n*,e*\n\tF*\n\tS1*\n\tbisBE\t#2(R1),#1(R)\n\n%n*,e\n\tF*\n\tS1\n\tbisBE\tR1,#1(R)\n\n%n*,n*\n\tFS*\n\tS*\n\tbisBE\t#2(R),*(sp)+\n\n%n*,n\n\tFS*\n\tS\n\tbisBE\tR,*(sp)+\n\n/ =& i\nci77:\n%a,c\n\tbicB1\t$!C2,A1\n\n%a,n\n\tS\n\tcom\tR\n\tbicB1\tR,A1\n\n%e*,n\n\tS\n\tF1*\n\tcom\tR\n\tbicB1\tR,#1(R1)\n\n%n*,c\n\tF*\n\tbicB1\t$!C2,#1(R)\n\n%n*,e\n\tF*\n\tS1\n\tcom\tR1\n\tbicB1\tR1,#1(R)\n\n%n*,n\n\tFS*\n\tS\n\tcom\tR\n\tbicB1\tR,*(sp)+\n\n/ =+\nci70:\n%aw,aw\n\tI\tA2,A1\n\n%aw,nw*\n\tS*\n\tI\t#2(R),A1\n\n%aw,n\n\tS\n\tI\tR,A1\n\n%ew*,nw*\n\tS*\n\tF1*\n\tI\t#2(R),#1(R1)\n\n%a,nw*\n\tS*\n\tmovB1\tA1,R1\n\tI\t#2(R),R1\n\tmovB1\tR1,#2(R)\n\n%a,n\n\tS\n\tmovB1\tA1,R1\n\tI\tR1,R\n\tmovB1\tR,A1\n\n%ew*,n\n\tS\n\tF1*\n\tI\tR,#1(R1)\n\n%nw*,n\n\tSS\n\tF*\n\tI\t(sp)+,#1(R)\n\n%n*,n\n\tSS\n\tF*\n\tmovB1\t#1(R),R1\n\tI\t(sp)+,R1\n\tmovB1\tR1,#1(R)\n\n.data\n.even\n\n"
  },
  {
    "path": "src/regtab.s",
    "content": "/ c code tables-- compile to register\n\nfp = 1\t\t/ enable floating-point\nunixv5 = 0\t\t/ unix v5 style abi, extra instructions\n\n.globl\t_regtab\n\n_regtab=.; .+2\n\t20.;\tcr20\n\t21.;\tcr20\n\t22.;\tcr20\n\t30.;\tcr30\n\t31.;\tcr30\n\t32.;\tcr32\n\t33.;\tcr32\n\t34.;\tcr34\n\t35.;\tcr35\n\t29.;\tcr29\n\t36.;\tcr36\n\t37.;\tcr37\n\t38.;\tcr38\n\t101.;\tcr100\n\t80.;\tcr80\n\t40.;\tcr40\n\t41.;\tcr40\t/ - like +\n\t42.;\tcr42\n\t43.;\tcr43\n\t44.;\tcr43\n\t45.;\tcr45\n\t46.;\tcr45\n\t47.;\tcr47\n\t48.;\tcr48\n\t60.;\tcr60\n\t61.;\tcr60\n\t62.;\tcr60\n\t63.;\tcr60\n\t64.;\tcr60\n\t65.;\tcr60\n\t66.;\tcr60\n\t67.;\tcr60\n\t68.;\tcr60\n\t69.;\tcr60\n\t70.;\tcr70\n\t71.;\tcr70\n\t72.;\tcr72\n\t73.;\tcr73\n\t74.;\tcr73\n\t75.;\tcr75\n\t76.;\tcr75\n\t77.;\tcr77\n\t78.;\tcr78\n\t102.;\tcr102\n\t97.;\tcr97\n\t0\n\n/ goto\ncr102:\n%i,n\n\tjmp\t*A1\n\n%n*,n\n\tF*\n\tjmp\t*#1(R)\n\n%n,n\n\tF\n\tjmp\t(R)\n\n/ call\n.if unixv5\ncr100:\n%n*,n\n\tF*\n\tjsr\tpc,#1(R)\n\n%a,n\n\tjsr\tpc,A1\n\n%n,n\n\tF\n\tjsr\tpc,R\n\n.else\ncr100:\n%n*,n\n\tF*\n\tjsr\tpc,*#1(R)\n\n%a,n\n\tjsr\tpc,*A1\n\n%n,n\n\tF\n\tjsr\tpc,(R)\n\n.endif\n\n/ name, constant\ncr20:\n%z,n\n\tclr\tR\n\n%aw,n\n\tmov\tA,R\n\n%ab,n\n\tmovb\tA,R\n\n.if fp\n%af,n\n\tM\n\tmovf\tA,R\n\n.endif\n\n/++,-- prefix\ncr30:\n%ai,n\n%abp,n\n%ab,n\n\tIB1\tA1\n\tmovB1\tA1,R\n\n%a,n\n\tI'\t$2,A1\n\tmov\tA1,R\n\n%nbp*,n\n%ni*,n\n%nb*,n\n\tF*\n\tIB1\t#1(R)\n\tmovB1\t#1(R),R\n\n%n*,n\n\tF*\n\tI'\t$2,#1(R)\n\tmov\t#1(R),R\n\n/ ++,-- postfix\ncr32:\n%ai,n\n%abp,n\n%ab,n\n\tmovB1\tA1,R\n\tIB1\tA1\n\n%a,n\n\tmov\tA1,R\n\tI'\t$2,A1\n\n%nbp*,n\n%nb*,n\n%ni*,n\n\tF*\n\tmovB1\t#1(R),-(sp)\n\tIB1\t#1(R)\n\tmovB1\t(sp)+,R\n\n%n*,n\n\tF*\n\tmov\t#1(R),-(sp)\n\tI'\t$2,#1(R)\n\tmov\t(sp)+,R\n\n/ !\ncr34:\n%n,n\n\tFC\n\tbeq\t1f\n\tclr\tR\n\tbr\t2f\n1:\tmov\t$1,R\n2:\n\n/ &unary\ncr35:\n%a,n\n\tmov\t$A1,R\n\n/ & unary of auto\ncr29:\n%e,n\n\tmov\tr5,R\n\tadd\tZ,R\n\n/ *unary\ncr36:\n%abp*,n\n\tF\n\tmovb\t(R),R\n\n%a*,n\n\tF\n\tmov\t(R),R\n\n%abp,n\n\tmovb\t*A1,R\n\n%a,n\n\tmov\t*A1,R\n\n%nbp*,n\n\tF*\n\tmovb\t*#1(R),R\n\n%n*,n\n\tF*\n\tmov\t*#1(R),R\n\n%nbp,n\n\tH*\n\tmovb\t~(R),R\n\n%n,n\n\tH*\n\tmov\t~(R),R\n\n/ - unary\ncr37:\n%n,n\n\tF\n\tneg\tR\n\n/ ~\ncr38:\n%n,n\n\tF\n\tcom\tR\n\n/ =\ncr80:\n%a,n\n\tS\n\tmovB1\tR,A1\n\n%n*,a\n\tF*\n\tmovB1\tA2,#1(R)\n\tmovB1\t#1(R),R\n\n%n*,e\n\tF*\n\tS1\n\tmovB1\tR1,#1(R)\n\tmov\tR1,R\n\n%n*,n\n\tFS*\n\tS\n\tmovB1\tR,*(sp)+\n\n/ |\ncr48:\n%n,a\n\tF\n\tbisB2\tA2,R\n\n%n,e*\n\tF\n\tS1*\n\tbisB2\t#2(R1),R\n\n%n,e\n\tF\n\tS1\n\tbis\tR1,R\n\n%n,n\n\tFS\n\tS\n\tbis\t(sp)+,R\n\n/ &\ncr47:\n%n,c\n\tF\n\tbic\t$!C2,R\n\n%n,e\n\tF\n\tS1\n\tcom\tR1\n\tbic\tR1,R\n\n%n,n\n\tFS\n\tS\n\tcom\t(sp)\n\tbic\t(sp)+,R\n\n/ relationals\ncr60:\n%n,n\n\tHC\n\tI\t2f\n\tclr\tR\n\tbr\t1f\n2:\tmov\t$1,R\n1:\n\n/ >>, <<\ncr45:\n%a,aw\n\tmovB1\tA1,I'\n\tI\tA2,lsh\n\tmovB1\tI',R\n\n%n*,aw\n\tF*\n\tmovB1\t#1(R),I'\n\tI\tA2,lsh\n\tmovB1\tI',R\n\n%n,aw\n\tF\n\tmov\tR,I'\n\tI\tA2,lsh\n\tmov\tI',R\n\n%a,nw*\n\tS*\n\tmovB1\tA1,(r4)\n\tI\t#2(R),lsh\n\tmov\t(r4),R\n\n%a,n\n\tS\n\tmovB1\tA1,I'\n\tI\tR,lsh\n\tmov\tI',R\n\n%n,n\n\tFS\n\tS\n\tmov\t(sp)+,I'\n\tI\tR,lsh\n\tmov\tI',R\n\n/ +, -\ncr40:\n%n,aw\n\tF\n\tI\tA2,R\n\n%n,ew*\n\tF\n\tS1*\n\tI\t#2(R1),R\n\n%n,e\n\tF\n\tS1\n\tI\tR1,R\n\n%n,nw*\n\tSS*\n\tF\n\tI\t*(sp)+,R\n\n%n,n\n\tSS\n\tF\n\tI\t(sp)+,R\n\n/ *\ncr42:\n%aw,a\n\tmov\tA1,(r4)+\n\tmovB2\tA2,(r4)\n\tmov\t-(r4),R\n\n%n,a\n\tF\n\tmov\tR,(r4)+\n\tmovB2\tA2,(r4)\n\tmov\t-(r4),R\n\n%n,e\n\tF\n\tS1\n\tmov\tR,(r4)+\n\tmov\tR1,(r4)\n\tmov\t-(r4),R\n\n%n,n\n\tFS\n\tS\n\tmov\t(sp)+,(r4)+\n\tmov\tR,(r4)\n\tmov\t-(r4),R\n\n/ /; mod\ncr43:\n.if unixv5\n%a,a\n\tmov r5, -(sp)\n\tmovB1\tA1,r5\n\tmov $0, r4\n\tdiv\tA2,r4\n\tmov r5, R\n\tmov (sp)+,r5\n\n%n,n\n\tFS\n\tS\n\tmov r5, -(sp)\n\tmov $0, r4\n\tmov 2(sp), r5\n\tdiv\tR, r4\n\tmov r5, R\n\tmov (sp)+,r5\n\ttst (sp)+\n\n.else\n%a,a\n\tmovB1\tA1,(r4)\n\tmovB2\tA2,div\n\tmov\tI,R\n\n%a,n\n\tS\n\tmovB1\tA1,(r4)\n\tmov\tR,div\n\tmov\tI,R\n\n%n,a\n\tF\n\tmov\tR,(r4)\n\tmovB2\tA2,div\n\tmov\tI,R\n\n%n,e\n\tF\n\tS1\n\tmov\tR,(r4)\n\tmov\tR1,div\n\tmov\tI,R\n\n%e,n\n\tS\n\tF1\n\tmov\tR1,(r4)\n\tmov\tR,div\n\tmov\tI,R\n\n%n,n\n\tFS\n\tS\n\tmov\t(sp)+,(r4)\n\tmov\tR,div\n\tmov\tI,R\n\n.endif\n\n/ =*\ncr72:\n%a,a\n\tmovB1\tA1,(r4)\n\tmovB2\tA2,mul\n\tmovB1\t(r4),A1\n\tmov\t(r4),R\n\n%a,n\n\tS\n\tmov\tR,(r4)+\n\tmovB1\tA1,(r4)\n\tmov\t-(r4),R\n\tmovB1\tR,A1\n\n%n*,a\n\tF*\n\tmovB1\t#1(R),(r4)\n\tmovB2\tA2,mul\n\tmovB1\t(r4),#1(R)\n\tmov\t(r4),R\n\n%n*,e\n\tF*\n\tS1\n\tmovB1\t#1(R),(r4)\n\tmov\tR1,mul\n\tmovB1\t(r4),#1(R)\n\tmov\t(r4),R\n\n%e*,n\n\tS\n\tF1*\n\tmovB1\t#1(R1),(r4)\n\tmov\tR,mul\n\tmovB1\t(r4),#1(R1)\n\tmov\t(r4),R\n\n%n*,n\n\tFS*\n\tS\n\tmovB1\t*(sp),(r4)\n\tmov\tR,mul\n\tmovB1\t(r4),*(sp)+\n\tmov\t(r4),R\n\n/ =mod, =/\ncr73:\n%a,a\n\tmovB1\tA1,(r4)\n\tmovB2\tA2,div\n\tmovB1\tI,A1\n\tmov\tI,R\n\n%a,n\n\tS\n\tmovB1\tA1,(r4)\n\tmov\tR,div\n\tmov\tI,R\n\tmovB1\tR,A1\n\n%n*,a\n\tF*\n\tmovB1\t#1(R),(r4)\n\tmovB2\tA2,div\n\tmovB1\tI,#1(R)\n\tmov\tI,R\n\n%n*,e\n\tF*\n\tS1\n\tmovB1\t#1(R),(r4)\n\tmov\tR1,div\n\tmovB1\tI,#1(R)\n\tmov\tI,R\n\n%e*,n\n\tS\n\tF1*\n\tmovB1\t#1(R1),(r4)\n\tmov\tR,div\n\tmovB1\tI,#1(R1)\n\tmov\tI,R\n\n%n*,n\n\tFS*\n\tS\n\tmovB1\t*(sp),(r4)\n\tmov\tR,div\n\tmovB1\tI,*(sp)+\n\tmov\tI,R\n\n/ =|\ncr78:\n%a,a\n\tbisBE\tA2,A1\n\tmovB1\tA1,R\n\n%a,n\n\tS\n\tbisB1\tR,A1\n\tmovB1\tA1,R\n\n%n*,a\n\tF*\n\tbisBE\tA2,#1(R)\n\tmovB1\t#1(R),R\n\n%e*,n*\n\tS*\n\tF1*\n\tbisBE\t#1(R1),#2(R)\n\tmovB1\t#2(R),R\n\n%e*,n\n\tS\n\tF1*\n\tbisBE\tR,#1(R1)\n\tmovB1\t#1(R1),R\n\n%n*,e*\n\tF*\n\tS1*\n\tbisBE\t#2(R1),#1(R)\n\tmovB1\t#1(R),R\n\n%n*,e\n\tF*\n\tS1\n\tbisBE\tR1,#1(R)\n\tmovB2\t#1(R),R\n\n%n*,n*\n\tFS*\n\tS*\n\tbisBE\t#2(R),*(sp)\n\tmovB2\t*(sp)+,R\n\n%n*,n\n\tFS*\n\tS\n\tbisBE\tR,*(sp)\n\tmov\t*(sp)+,R\n\n/ =&\ncr77:\n%a,c\n\tbicB1\t$!C2,A1\n\tmovB2\tA1,R\n\n%a,n\n\tS\n\tcom\tR\n\tbicB1\tR,A1\n\tmovB1\tA1,R\n\n%e*,n\n\tS\n\tF1*\n\tcom\tR\n\tbicB1\tR,#1(R1)\n\tmovB1\t#1(R1),R\n\n%n*,e\n\tF*\n\tS1\n\tcom\tR1\n\tbicB1\tR1,#1(R)\n\tmovB1\t#1(R),R\n\n%n*,n\n\tFS*\n\tS\n\tcom\tR\n\tbicB1\tR,*(sp)\n\tmovB1\t*(sp)+,R\n\n/ =>>, =<<\ncr75:\n%a,aw\n\tmovB1\tA1,I'\n\tI\tA2,lsh\n\tmovB1\tI',A1\n\tmovB1\tI',R\n\n%a,n\n\tS\n\tmovB1\tA1,I'\n\tI\tR,lsh\n\tmovB1\tI',A1\n\tmovB1\tI',R\n\n%n*,e\n\tF*\n\tS1\n\tmovB1\t#1(R),I'\n\tI\tR1,lsh\n\tmovB1\tI',#1(R)\n\tmovB1\tI',R\n\n%e*,n\n\tS\n\tF1*\n\tmovB1\t#1(R1),I'\n\tI\tR,lsh\n\tmovB\tI',#1(R1)\n\tmovB1\tI',R\n\n%n*,n\n\tFS*\n\tS\n\tmovB1\t*(sp),I'\n\tI\tR,lsh\n\tmovB1\tI',*(sp)+\n\tmovB1\tI',R\n\n/ =+\ncr70:\n%aw,aw\n\tI\tA2,A1\n\tmov\tA1,R\n\n%aw,nw*\n\tS*\n\tI\t#2(R),A1\n\tmov\tA1,R\n\n%aw,n\n\tS\n\tI\tR,A1\n\tmov\tA1,R\n\n%ew*,nw*\n\tS*\n\tF1*\n\tI\t#2(R),#1(R1)\n\tmov\t#1(R1),R\n\n%a,nw*\n\tS*\n\tmovB1\tA1,R1\n\tI\t#2(R),R1\n\tmovB1\tR1,#2(R)\n\tmov\tR1,R\n\n%a,n\n\tS\n\tmovB1\tA1,R1\n\tI\tR1,R\n\tmovB1\tR,A1\n\n%ew*,n\n\tS\n\tF1*\n\tI\tR,#1(R1)\n\tmov\t#1(R1),R\n\n%nw*,n\n\tSS\n\tF*\n\tI\t(sp)+,#1(R)\n\tmov\t#1(R),R\n\n%n*,n\n\tSS\n\tF*\n\tmovB1\t#1(R),R1\n\tI\t(sp)+,R1\n\tmovB1\tR1,#1(R)\n\tmov\tR1,R\n\n/ int -> int[]\ncr97:\n%n,n\n\tF\n\tasl\tR\n\n.data\n.even\n.text\n\n"
  },
  {
    "path": "src/sptab.s",
    "content": "/ c code tables-- expression to -(sp)\n\n.globl\t_sptab\n\n_sptab=.;.+2\n\t20.;\tcs20\n\t21.;\tcs21\n\t22.;\tcs21\n\t30.;\tcs30\n\t31.;\tcs30\n\t32.;\tcs32\n\t33.;\tcs32\n\t35.;\tcs35\n\t36.;\tcs36\n\t40.;\tcs40\n\t41.;\tcs40\n\t42.;\tcs42\n\t47.;\tcs47\n\t48.;\tcs48\n\t0\n\n\n/ name\ncs20:\n%aw,n\n\tmov\tA,-(sp)\n\n/ constant\ncs21:\n%z,n\n\tclr\t-(sp)\n\n%a,n\n\tmov\tA,-(sp)\n\n/ ++,-- prefix\ncs30:\n%ai,n\n%abp,n\n\tI\tA1\n\tmov\tA1,-(sp)\n\n%aw,n\n\tI'\t$2,A1\n\tmov\tA1,-(sp)\n\n%nbp*,n\n%ni*,n\n\tF*\n\tI\t#1(R)\n\tmov\t#1(R),-(sp)\n\n%nip*,n\n\tF*\n\tmov\t#1(R),-(sp)\n\tI'\t$2,#1(R)\n\n/ ++,-- postfix\ncs32:\n%ai,n\n%abp,n\n\tmov\tA1,-(sp)\n\tI\tA1\n\n%aip,n\n\tmov\tA1,-(sp)\n\tI'\t$2,A1\n\n%nbp*,n\n%ni*,n\n\tF*\n\tmov\t#1(R),-(sp)\n\tI\t#1(R)\n\n%nip*,n\n\tF*\n\tmov\t#1(R),-(sp)\n\tI'\t$2,#1(R)\n\n/ & unary\ncs35:\n%i,n\n\tmov\t$A1,-(sp)\n\n/ * unary\ncs36:\n%aw,n\n\tmov\t*A1,-(sp)\n\n%nw*,n\n\tF*\n\tmov\t#1(R),-(sp)\n\n/ +\ncs40:\n%n,aw\n\tFS\n\tI\tA2,(sp)\n\n%n,nw*\n\tFS\n\tS*\n\tI\t#2(R),(sp)\n\n%n,n\n\tFS\n\tS\n\tI\tR,(sp)\n\n/ *\ncs42:\n%aw,a\n\tmov\tA1,(r4)+\n\tmovB2\tA2,(r4)\n\tmov\t-(r4),-(sp)\n\n%n,a\n\tF\n\tmov\tR,(r4)+\n\tmovB2\tA2,(r4)\n\tmov\t-(r4),-(sp)\n\n%n,nw*\n\tFS\n\tS*\n\tmov\t(sp)+,(r4)+\n\tmov\t#2(R),(r4)\n\tmov\t-(r4),-(sp)\n\n%n,n\n\tFS\n\tS\n\tmov\t(sp)+,(r4)+\n\tmov\tR,(r4)\n\tmov\t-(r4),-(sp)\n\n/ &\ncs47:\n%n,c\n\tFS\n\tbic\t$!C2,(sp)\n\n%n,n\n\tFS\n\tS\n\tcom\tR\n\tbic\tR,(sp)\n\n/ |\ncs48:\n%n,a\n\tFS\n\tbisB2\tA2,(sp)\n\n%n,n*\n\tFS\n\tS*\n\tbisB2\t#2(R),(sp)\n\n%n,n\n\tFS\n\tS\n\tbis\tR,(sp)\n\n.data\n.even\n.text\n"
  }
]