├── NEWS ├── COPYING ├── test ├── regression │ ├── a.obj │ ├── fig16.14.obj │ ├── stdio.h │ ├── fig15.2.c │ ├── fig15.1.c │ ├── fig15.4.c │ ├── fig18.1.c │ ├── fig14.1.c │ ├── fig17.13.c │ ├── fig16.12.c │ ├── fig16.1.c │ ├── fig16.4.c │ ├── fig14.11.c │ ├── spill.c │ ├── 8q.c │ ├── fig17.18.c │ ├── fig15.3.c │ ├── fig16.10.c │ ├── fig16.8.c │ ├── array.c │ ├── incr.c │ ├── fig14.10.c │ ├── fig14.2.c │ ├── fig16.13.c │ ├── fig16.6.c │ ├── fig16.9.c │ ├── sort.c │ ├── fig16.14.c │ ├── struct.c │ ├── a.sym │ ├── fig16.14.sym │ └── switch.c └── limitations │ ├── stdio.h │ ├── getchar.asm │ ├── putchar.asm │ ├── fig14.3.c │ ├── init.c │ ├── wf1.c │ ├── printf.asm │ └── scanf.asm ├── lc3lib ├── stdio.h ├── getchar.asm ├── putchar.asm ├── printf.asm └── scanf.asm ├── AUTHORS ├── src ├── inits.c ├── event.c ├── bind.c ├── list.c ├── alloc.c ├── null.c ├── ops.h ├── config.h ├── error.c ├── Makefile.def ├── input.c ├── output.c ├── stab.h ├── string.c ├── dagcheck.md ├── trace.c ├── tree.c ├── bytecode.c ├── main.c └── prof.c ├── include ├── assert.h ├── limits.h ├── math.h ├── stdarg.h └── float.h ├── lib ├── yynull.c ├── assert.c ├── Makefile.def └── bbexit.c ├── TODO ├── .gitignore ├── cpp ├── getopt.c ├── Makefile.def ├── hideset.c ├── nlist.c ├── unix.c ├── include.c ├── cpp.h └── cpp.c ├── NO_WARRANTY ├── etc ├── lc3.c └── Makefile.def ├── INSTALL.txt ├── ChangeLog ├── doc └── man1 │ ├── bprint.1 │ └── lburg.1 ├── lburg ├── lburg.h └── Makefile.def ├── lc3pp └── Makefile.def ├── README ├── CPYRIGHT ├── Makefile.def ├── README.md └── configure /NEWS: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Please see the CPYRIGHT file for the copyright regarding LCC. 2 | 3 | -------------------------------------------------------------------------------- /test/regression/a.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haplesshero13/lcc-lc3/HEAD/test/regression/a.obj -------------------------------------------------------------------------------- /test/regression/fig16.14.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haplesshero13/lcc-lc3/HEAD/test/regression/fig16.14.obj -------------------------------------------------------------------------------- /lc3lib/stdio.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | extern void printf(const char *format, ...); 5 | extern void scanf(const char *format, ...); 6 | -------------------------------------------------------------------------------- /test/limitations/stdio.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | extern void printf(const char *format, ...); 5 | extern void scanf(const char *format, ...); 6 | -------------------------------------------------------------------------------- /test/regression/stdio.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | extern void printf(const char *format, ...); 5 | extern void scanf(const char *format, ...); 6 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | 2 | The authors of LCC are Christopher W. Fraser and David R. Hanson. 3 | 4 | Ajay Ladsaria wrote lc3.md and modified lex.c and c.h to make LC-3 a new target 5 | for LCC. 6 | 7 | -------------------------------------------------------------------------------- /test/regression/fig15.2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | int i; 6 | int j; 7 | 8 | for (i = 0; i <= 10; i++) 9 | j = i * 7; 10 | printf("%d x 7 = %d\n", i, j); 11 | } 12 | -------------------------------------------------------------------------------- /test/regression/fig15.1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | int i 6 | int j; 7 | 8 | for (i = 0; i <= 10; i++) { 9 | j = i * 7; 10 | printf("%d x 7 = %d\n", i, j); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/inits.c: -------------------------------------------------------------------------------- 1 | void init(int argc, char *argv[]) { 2 | {extern void input_init(int, char *[]); input_init(argc, argv);} 3 | {extern void main_init(int, char *[]); main_init(argc, argv);} 4 | {extern void type_init(int, char *[]); type_init(argc, argv);} 5 | } 6 | -------------------------------------------------------------------------------- /lc3lib/getchar.asm: -------------------------------------------------------------------------------- 1 | 2 | ; char getchar(void) 3 | LC3_GFLAG getchar LC3_GFLAG .FILL lc3_getchar 4 | 5 | lc3_getchar 6 | 7 | STR R7, R6, #-3 8 | STR R0, R6, #-2 9 | GETC 10 | OUT 11 | STR R0, R6, #-1 12 | LDR R0, R6, #-2 13 | LDR R7, R6, #-3 14 | ADD R6, R6, #-1 15 | RET 16 | -------------------------------------------------------------------------------- /lc3lib/putchar.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; void putchar(char) 4 | LC3_GFLAG putchar LC3_GFLAG .FILL lc3_putchar 5 | 6 | lc3_putchar 7 | 8 | STR R7, R6, #-3 9 | STR R0, R6, #-2 10 | 11 | LDR R0, R6, #0 12 | OUT 13 | 14 | LDR R0, R6, #-2 15 | LDR R7, R6, #-3 16 | ADD R6, R6, #-1 17 | RET 18 | -------------------------------------------------------------------------------- /test/limitations/getchar.asm: -------------------------------------------------------------------------------- 1 | 2 | ; char getchar(void) 3 | LC3_GFLAG getchar LC3_GFLAG .FILL lc3_getchar 4 | 5 | lc3_getchar 6 | 7 | STR R7, R6, #-3 8 | STR R0, R6, #-2 9 | GETC 10 | OUT 11 | STR R0, R6, #-1 12 | LDR R0, R6, #-2 13 | LDR R7, R6, #-3 14 | ADD R6, R6, #-1 15 | RET 16 | -------------------------------------------------------------------------------- /test/limitations/putchar.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; void putchar(char) 4 | LC3_GFLAG putchar LC3_GFLAG .FILL lc3_putchar 5 | 6 | lc3_putchar 7 | 8 | STR R7, R6, #-3 9 | STR R0, R6, #-2 10 | 11 | LDR R0, R6, #0 12 | OUT 13 | 14 | LDR R0, R6, #-2 15 | LDR R7, R6, #-3 16 | ADD R6, R6, #-1 17 | RET 18 | -------------------------------------------------------------------------------- /test/regression/fig15.4.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | int year; 6 | 7 | printf("Input a year (i.e., 1996): "); 8 | scanf("%d", &year); 9 | 10 | if (year % 4 == 0) 11 | printf("This year is a leap year"\n); 12 | else 13 | printf("This year is not a leap year"\n); 14 | } 15 | -------------------------------------------------------------------------------- /include/assert.h: -------------------------------------------------------------------------------- 1 | #ifndef __ASSERT 2 | #define __ASSERT 3 | 4 | void assert(int); 5 | 6 | #endif /* __ASSERT */ 7 | 8 | #undef assert 9 | #ifdef NDEBUG 10 | #define assert(ignore) ((void)0) 11 | #else 12 | extern int _assert(char *, char *, unsigned); 13 | #define assert(e) ((void)((e)||_assert(#e, __FILE__, __LINE__))) 14 | #endif /* NDEBUG */ 15 | -------------------------------------------------------------------------------- /test/regression/fig18.1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | char inChar1; 6 | char inChar2; 7 | 8 | printf("Input character 1:\n"); 9 | inChar1 = getchar(); 10 | 11 | printf("Input character 2:\n"); 12 | inChar2 = getchar(); 13 | 14 | printf("Character 1 is %c\n", inChar1); 15 | printf("Character 2 is %c\n", inChar2); 16 | } 17 | -------------------------------------------------------------------------------- /test/regression/fig14.1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void PrintBanner(); /* Function declaration */ 4 | 5 | int main() 6 | { 7 | PrintBanner(); /* Function call */ 8 | printf("A simple C program.\n"); 9 | PrintBanner(); 10 | } 11 | 12 | void PrintBanner() /* Function definition */ 13 | { 14 | printf("============================\n"); 15 | } 16 | 17 | -------------------------------------------------------------------------------- /lib/yynull.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #ifndef EXPORT 4 | #define EXPORT 5 | #endif 6 | 7 | static char rcsid[] = "$Id: yynull.c,v 1.1.1.1 2004/03/24 04:37:35 sjp Exp $"; 8 | 9 | EXPORT void _YYnull(char *file, int line) { 10 | fprintf(stderr, "null pointer dereferenced:"); 11 | if (file) 12 | fprintf(stderr, " file %s,", file); 13 | fprintf(stderr, " line %d\n", line); 14 | fflush(stderr); 15 | abort(); 16 | } 17 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | 2 | Things that need to be done: 3 | 4 | gnu autoconf,automake's use needs to be improved. 5 | --many of auto*'s true portability features are not used, when they perhaps 6 | should be. 7 | --auto*'s check feature where it performs some tests to see if the 8 | installation was sucessful is not used 9 | --the generate makefile doesn't build all the programs or perform all the 10 | tests that the original makefile distributed with the lcc dist does 11 | 12 | 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Temp and backup files 2 | *~ 3 | *.swp 4 | 5 | # Mac OS X Stuff 6 | .DS_Store 7 | .Trashes 8 | .Spotlight-V100 9 | ._* 10 | *.dSYM 11 | 12 | # Other source repository archive directories (protects when importing) 13 | *.hg* 14 | .svn 15 | CVS 16 | 17 | # Object files 18 | *.o 19 | 20 | # Libraries 21 | *.lib 22 | 23 | # Shared objects (inc. Windows DLLs) 24 | *.dll 25 | *.so 26 | 27 | # Executables 28 | *.exe 29 | *.out 30 | 31 | # Makefile 32 | Makefile 33 | 34 | -------------------------------------------------------------------------------- /lib/assert.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #ifndef EXPORT 4 | #define EXPORT 5 | #endif 6 | 7 | static char rcsid[] = "$Id: assert.c,v 1.1.1.1 2004/03/24 04:37:35 sjp Exp $"; 8 | 9 | EXPORT int _assert(char *e, char *file, int line) { 10 | fprintf(stderr, "assertion failed:"); 11 | if (e) 12 | fprintf(stderr, " %s", e); 13 | if (file) 14 | fprintf(stderr, " file %s", file); 15 | fprintf(stderr, " line %d\n", line); 16 | fflush(stderr); 17 | abort(); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /test/regression/fig17.13.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int Fibonacci(int n); 4 | 5 | int main() 6 | { 7 | int in; 8 | int number; 9 | 10 | printf("Which Fibonacci number? "); 11 | scanf("%d", &in); 12 | 13 | number = Fibonacci(in); 14 | printf("That Fibonacci number is %d\n", number); 15 | } 16 | 17 | int Fibonacci(int n) 18 | { 19 | int sum; 20 | 21 | if (n == 0 || n == 1) 22 | return 1; 23 | else { 24 | sum = (Fibonacci(n-1) + Fibonacci(n-2)); 25 | return sum; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /test/regression/fig16.12.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAX_STRING 20 3 | 4 | int StringLength(char string[]); 5 | 6 | int main() 7 | { 8 | char input[MAX_STRING]; /* Input string */ 9 | int length = 0; 10 | 11 | printf("Input a word (less than 20 characters): "); 12 | scanf("%s", input); 13 | 14 | length = StringLength(input); 15 | printf("The word contains %d characters\n", length); 16 | } 17 | 18 | int StringLength(char string[]) 19 | { 20 | int index = 0; 21 | 22 | while (string[index] != '\0') 23 | index = index + 1; 24 | 25 | return index; 26 | } 27 | -------------------------------------------------------------------------------- /test/regression/fig16.1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void Swap(int firstVal, int secondVal); 4 | 5 | int main() 6 | { 7 | int valueA = 3; 8 | int valueB = 4; 9 | 10 | printf("Before Swap "); 11 | printf("valueA = %d and valueB = %d\n", valueA, valueB); 12 | 13 | Swap(valueA, valueB); 14 | 15 | printf("After Swap "); 16 | printf("valueA = %d and valueB = %d\n", valueA, valueB); 17 | } 18 | 19 | void Swap(int firstVal, int secondVal) 20 | { 21 | int tempVal; /* Holds firstVal when swapping */ 22 | 23 | tempVal = firstVal; 24 | firstVal = secondVal; 25 | secondVal = tempVal; 26 | } 27 | -------------------------------------------------------------------------------- /src/event.c: -------------------------------------------------------------------------------- 1 | #include "c.h" 2 | 3 | static char rcsid[] = "$Id: event.c,v 1.1.1.1 2004/03/24 04:37:33 sjp Exp $"; 4 | 5 | struct entry { 6 | Apply func; 7 | void *cl; 8 | }; 9 | 10 | Events events; 11 | void attach(Apply func, void *cl, List *list) { 12 | struct entry *p; 13 | 14 | NEW(p, PERM); 15 | p->func = func; 16 | p->cl = cl; 17 | *list = append(p, *list); 18 | } 19 | void apply(List event, void *arg1, void *arg2) { 20 | if (event) { 21 | List lp = event; 22 | do { 23 | struct entry *p = lp->x; 24 | (*p->func)(p->cl, arg1, arg2); 25 | lp = lp->link; 26 | } while (lp != event); 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /test/regression/fig16.4.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void NewSwap(int *firstVal, int *secondVal); 4 | 5 | int main() 6 | { 7 | int valueA = 3; 8 | int valueB = 4; 9 | 10 | printf("Before Swap "); 11 | printf("valueA = %d and valueB = %d\n", valueA, valueB); 12 | 13 | NewSwap(&valueA, &valueB); 14 | 15 | printf("After Swap "); 16 | printf("valueA = %d and valueB = %d\n", valueA, valueB); 17 | } 18 | 19 | void NewSwap(int *firstVal, int *secondVal) 20 | { 21 | int tempVal; /* Holds firstVal when swapping */ 22 | 23 | tempVal = *firstVal; 24 | *firstVal = *secondVal; 25 | *secondVal = tempVal; 26 | } 27 | -------------------------------------------------------------------------------- /src/bind.c: -------------------------------------------------------------------------------- 1 | #include "c.h" 2 | #undef yy 3 | #define yy \ 4 | xx(lc3, lc3IR) \ 5 | xx(alpha/osf, alphaIR) \ 6 | xx(mips/irix, mipsebIR) \ 7 | xx(sparc/sun, sparcIR) \ 8 | xx(sparc/solaris,solarisIR) \ 9 | xx(x86/win32, x86IR) \ 10 | xx(x86/linux, x86linuxIR) \ 11 | xx(symbolic/osf, symbolic64IR) \ 12 | xx(symbolic/irix,symbolicIR) \ 13 | xx(symbolic, symbolicIR) \ 14 | xx(bytecode, bytecodeIR) \ 15 | xx(null, nullIR) 16 | 17 | #undef xx 18 | #define xx(a,b) extern Interface b; 19 | yy 20 | 21 | Binding bindings[] = { 22 | #undef xx 23 | #define xx(a,b) #a, &b, 24 | yy 25 | NULL, NULL 26 | }; 27 | #undef yy 28 | #undef xx 29 | -------------------------------------------------------------------------------- /test/regression/fig14.11.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int Squared(int x); 4 | 5 | int main() 6 | { 7 | int sideA; 8 | int sideB; 9 | int sideC; 10 | int maxC; 11 | 12 | printf("Enter the maximum length of hypotenuse: "); 13 | scanf("%d", &maxC); 14 | 15 | for (sideC = 1; sideC <= maxC; sideC++) { 16 | for (sideB = 1; sideB <= maxC; sideB++) { 17 | for (sideA = 1; sideA <= maxC; sideA++) { 18 | if (Squared(sideC) == Squared(sideA) + Squared(sideB)) 19 | printf("%d %d %d\n", sideA, sideB, sideC); 20 | } 21 | } 22 | } 23 | } 24 | 25 | /* Calculate the square of a number */ 26 | int Squared(int x) 27 | { 28 | return x * x; 29 | } 30 | -------------------------------------------------------------------------------- /include/limits.h: -------------------------------------------------------------------------------- 1 | #ifndef __LIMITS 2 | #define __LIMITS 3 | 4 | #define CHAR_BIT 8 5 | #define MB_LEN_MAX 1 6 | 7 | #define UCHAR_MAX 0xff 8 | #define USHRT_MAX 0xffff 9 | #define UINT_MAX (~0U) 10 | #define ULONG_MAX (~0UL) 11 | 12 | #define SCHAR_MAX 0x7f 13 | #define SHRT_MAX 0x7fff 14 | #define INT_MAX 0x7fffffff 15 | #define LONG_MAX 0x7fffffffL 16 | 17 | #define SCHAR_MIN (-SCHAR_MAX-1) 18 | #define SHRT_MIN (-SHRT_MAX-1) 19 | #define INT_MIN (-INT_MAX-1) 20 | #define LONG_MIN (-LONG_MAX-1) 21 | 22 | #ifdef __CHAR_UNSIGNED__ 23 | #define CHAR_MAX UCHAR_MAX 24 | #define CHAR_MIN 0 25 | #else 26 | #define CHAR_MAX SCHAR_MAX 27 | #define CHAR_MIN SCHAR_MIN 28 | #endif 29 | 30 | #endif /* __LIMITS */ 31 | -------------------------------------------------------------------------------- /test/regression/spill.c: -------------------------------------------------------------------------------- 1 | main(){ 2 | f5(); 3 | } 4 | 5 | f(i){i=f()+f();} 6 | 7 | f2(i){i=f()+(i?f():1);} 8 | 9 | f3(int i,int *p){register r1=0,r2=0,r3=0,r4=0,r5=0,r6=0,r7=0,r8=0,r9=0,r10=0;*p++=i?f():0;} 10 | 11 | int aa[10],ab[10]; 12 | int i; 13 | f4(){register r6=0,r7=0,r8=0,r9=0,r10=0,r11=0;i=aa[i]+ab[i] && i && aa[i]-ab[i];} 14 | /* f4 causes parent to spill child on vax when odd double regs are enabled */ 15 | 16 | int j=1, k=2, m=3, n=3; 17 | //int *A, *B, x; 18 | int A[10] = {1,1,2,3,4,5,6,7,8,9}; 19 | int B[10] = {1,1,2,3,4,5,6,7,8,9}; 20 | int x=0; 21 | 22 | f5(){ 23 | x=A[k*m]*A[j*m]+B[k*n]*B[j*n]; 24 | printf("%d\n",x); 25 | x=A[k*m]*B[j*n]-B[k*n]*A[j*m]; 26 | printf("%d\n",x); 27 | } 28 | -------------------------------------------------------------------------------- /test/regression/8q.c: -------------------------------------------------------------------------------- 1 | int up[15], down[15], rows[8], x[8]; 2 | int queens(), print(); 3 | 4 | main() 5 | { 6 | int i; 7 | 8 | for (i = 0; i < 15; i++) 9 | up[i] = down[i] = 1; 10 | for (i = 0; i < 8; i++) 11 | rows[i] = 1; 12 | queens(0); 13 | return 0; 14 | } 15 | 16 | queens(c) 17 | { 18 | int r; 19 | 20 | for (r = 0; r < 8; r++) 21 | if (rows[r] && up[r-c+7] && down[r+c]) { 22 | rows[r] = up[r-c+7] = down[r+c] = 0; 23 | x[c] = r; 24 | if (c == 7) 25 | print(); 26 | else 27 | queens(c + 1); 28 | rows[r] = up[r-c+7] = down[r+c] = 1; 29 | } 30 | } 31 | 32 | print() 33 | { 34 | int k; 35 | 36 | for (k = 0; k < 8; k++) 37 | printf("%c ", x[k]+'1'); 38 | printf("\n"); 39 | } 40 | -------------------------------------------------------------------------------- /test/regression/fig17.18.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void IntToAscii(int i); 4 | 5 | int main() 6 | { 7 | int in; 8 | 9 | printf("Input number: "); 10 | scanf("%d", &in); 11 | 12 | IntToAscii(in); 13 | printf("\n"); 14 | } 15 | 16 | void IntToAscii(int num) 17 | { 18 | int prefix; 19 | int currDigit; 20 | 21 | if (num < 10) /* The terminal case */ 22 | printf("%c", num + '0'); 23 | else { 24 | prefix = num / 10; /* Convert the number */ 25 | IntToAscii(prefix); /* without last digit */ 26 | 27 | currDigit = num % 10; /* Then print last digit */ 28 | printf("%c", currDigit + '0'); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/regression/fig15.3.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int AllSum(int n); 4 | 5 | int main() 6 | { 7 | int in; /* Input value */ 8 | int sum; /* Value of 1+2+3+..+n */ 9 | 10 | printf("Input a number: "); 11 | scanf("%d", &in); 12 | 13 | sum = AllSum(in); 14 | printf("The AllSum of %d is %d\n", in, sum); 15 | } 16 | 17 | 18 | int AllSum(int n) 19 | { 20 | int result; /* Result to be returned */ 21 | int i; /* Iteration count */ 22 | 23 | for (i = 1; i <= n; i++) /* This calculates sum */ 24 | result = result + i; 25 | 26 | return result; /* Return to caller */ 27 | } 28 | -------------------------------------------------------------------------------- /test/limitations/fig14.3.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Function declarations */ 4 | double AreaOfCircle(double radius); 5 | 6 | int main() 7 | { 8 | double outer; /* Outer radius */ 9 | double inner; /* Inner radius */ 10 | double areaOfRing; /* Area of ring */ 11 | 12 | printf("Enter outer radius: "); 13 | scanf("%lf", &outer); 14 | 15 | printf("Enter inner radius: "); 16 | scanf("%lf", &inner); 17 | 18 | areaOfRing = AreaOfCircle(outer) - AreaOfCircle(inner); 19 | printf("The area of the ring is %f\n", areaOfRing); 20 | } 21 | 22 | /* Calculate area of circle given a radius */ 23 | double AreaOfCircle(double radius) 24 | { 25 | double pi = 3.14159265; 26 | 27 | return pi * radius * radius; 28 | } 29 | -------------------------------------------------------------------------------- /include/math.h: -------------------------------------------------------------------------------- 1 | #ifndef __MATH 2 | #define __MATH 3 | 4 | #define HUGE_VAL 1.79769313486231570000e+308 5 | 6 | extern double acos(double); 7 | extern double asin(double); 8 | extern double atan(double); 9 | extern double atan2(double, double); 10 | extern double cos(double); 11 | extern double sin(double); 12 | extern double tan(double); 13 | extern double cosh(double); 14 | extern double sinh(double); 15 | extern double tanh(double); 16 | extern double exp(double); 17 | extern double frexp(double, int *); 18 | extern double ldexp(double, int); 19 | extern double log(double); 20 | extern double log10(double); 21 | extern double modf(double, double *); 22 | extern double pow(double, double); 23 | extern double sqrt(double); 24 | extern double ceil(double); 25 | extern double fabs(double); 26 | extern double floor(double); 27 | extern double fmod(double, double); 28 | 29 | #endif /* __MATH */ 30 | -------------------------------------------------------------------------------- /test/regression/fig16.10.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAX_NUMS 10 3 | 4 | int Average(int input_values[]); 5 | 6 | int main() 7 | { 8 | int index; /* Loop iteration variable */ 9 | int mean; /* average of numbers */ 10 | int numbers[MAX_NUMS]; /* Original input numbers */ 11 | 12 | 13 | /* Get input */ 14 | printf("Enter %d numbers.\n", MAX_NUMS); 15 | for (index = 0; index < MAX_NUMS; index++) { 16 | printf("Input number %d : ", index); 17 | scanf("%d", &numbers[index]); 18 | } 19 | 20 | mean = Average(numbers); 21 | 22 | printf("The average of these numbers is %d\n", mean); 23 | } 24 | 25 | int Average(int inputValues[]) 26 | { 27 | int index; 28 | int sum = 0; 29 | 30 | for (index = 0; index < MAX_NUMS; index++) { 31 | sum = sum + inputValues[index]; 32 | } 33 | 34 | return (sum / MAX_NUMS); 35 | } 36 | -------------------------------------------------------------------------------- /test/regression/fig16.8.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define NUM_STUDENTS 10 3 | 4 | int main() 5 | { 6 | int i; 7 | int Exam1[NUM_STUDENTS]; 8 | int Exam2[NUM_STUDENTS]; 9 | int Total[NUM_STUDENTS]; 10 | 11 | /* Input Exam 1 scores */ 12 | for (i = 0; i < NUM_STUDENTS; i++) { 13 | printf("Input Exam 1 score for student %d : ", i); 14 | scanf("%d", &Exam1[i]); 15 | } 16 | printf("\n"); 17 | 18 | /* Input Exam 2 scores */ 19 | for (i = 0; i < NUM_STUDENTS; i++) { 20 | printf("Input Exam 2 score for student %d : ", i); 21 | scanf("%d", &Exam2[i]); 22 | } 23 | printf("\n"); 24 | 25 | /* Calculate Total Points */ 26 | for (i = 0; i < NUM_STUDENTS; i++) { 27 | Total[i] = Exam1[i] + Exam2[i]; 28 | } 29 | 30 | /* Output the Total Points */ 31 | for (i = 0; i < NUM_STUDENTS; i++) { 32 | printf("Total for Student %d = %d\n", i, Total[i]); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /test/regression/array.c: -------------------------------------------------------------------------------- 1 | int x[3][4], *y[3]; 2 | 3 | main() { 4 | int z[3][4]; 5 | int i, j, *p; 6 | 7 | for (i = 0; i < 3; i++) { 8 | for (j = 0; j < 4; j++) 9 | x[i][j] = 1000*i + j; 10 | y[i] = x[i]; 11 | } 12 | f(); 13 | for (i = 0; i < 3; i++) { 14 | y[i] = p = &z[i][0]; 15 | for (j = 0; j < 4; j++) 16 | p[j] = x[i][j]; 17 | } 18 | g(z, y); 19 | return 0; 20 | } 21 | 22 | f() { 23 | int i, j; 24 | 25 | for (i = 0; i < 3; i++) 26 | for (j = 0; j < 4; j++) 27 | printf(" %d", x[i][j]); 28 | printf("\n"); 29 | for (i = 0; i < 3; i++) 30 | for (j = 0; j < 4; j++) 31 | printf(" %d", y[i][j]); 32 | printf("\n"); 33 | } 34 | 35 | g(x, y) 36 | int x[][4], *y[]; 37 | { 38 | int i, j; 39 | 40 | for (i = 0; i < 3; i++) 41 | for (j = 0; j < 4; j++) 42 | printf(" %d", x[i][j]); 43 | printf("\n"); 44 | for (i = 0; i < 3; i++) 45 | for (j = 0; j < 4; j++) 46 | printf(" %d", y[i][j]); 47 | printf("\n"); 48 | } 49 | -------------------------------------------------------------------------------- /test/regression/incr.c: -------------------------------------------------------------------------------- 1 | char gx = 'd'; 2 | char gy = 'd'; 3 | int a = 60; 4 | int b = 10; 5 | 6 | main() { 7 | memchar(); 8 | memint(); 9 | regchar(); 10 | regint(); 11 | } 12 | 13 | memchar() { 14 | char x, *p; 15 | 16 | &x, &p; 17 | x = gx; 18 | p = &gy; 19 | x = *p++; 20 | x = *++p; 21 | x = *p--; 22 | x = *--p; 23 | printf("%c %c\n",x,*p); 24 | } 25 | 26 | memint() { 27 | int x, *p; 28 | 29 | &x, &p; 30 | 31 | x = a; 32 | p = &b; 33 | x = *p++; 34 | x = *++p; 35 | x = *p--; 36 | x = *--p; 37 | printf("%d %x %o %b %d\n",x, x, x, x,*p); 38 | printf("%d %d\n", x,*p); 39 | } 40 | 41 | regchar() { 42 | register char x, *p; 43 | x = gx; 44 | p = &gy; 45 | 46 | x = *p++; 47 | x = *++p; 48 | x = *p--; 49 | x = *--p; 50 | printf("%c %c\n",x,*p); 51 | } 52 | 53 | regint() { 54 | register int x, *p; 55 | 56 | x = a; 57 | p = &b; 58 | x = *p++; 59 | x = *++p; 60 | x = *p--; 61 | x = *--p; 62 | printf("%x %d\n",x,*p); 63 | } 64 | -------------------------------------------------------------------------------- /test/regression/fig14.10.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Function declaration */ 4 | char ToUpper(char inchar); 5 | 6 | /* Function main: */ 7 | /* Prompt for a line of text, Read one character, */ 8 | /* convert to uppercase, print it out, then get another */ 9 | int main() 10 | { 11 | char echo = 'A'; /* Initialize input character */ 12 | char upcase; /* Converted character */ 13 | 14 | while (echo != '\n') { 15 | scanf("%c", &echo); 16 | upcase = ToUpper(echo); 17 | printf("%c", upcase); 18 | } 19 | } 20 | 21 | /* Function ToUpper: */ 22 | /* If the parameter is lower case return */ 23 | /* its uppercase ASCII value */ 24 | char ToUpper(char inchar) 25 | { 26 | char outchar; 27 | 28 | if ('a' <= inchar && inchar <= 'z') 29 | outchar = inchar - ('a' - 'A'); 30 | else 31 | outchar = inchar; 32 | 33 | return outchar; 34 | } 35 | -------------------------------------------------------------------------------- /test/regression/fig14.2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int Factorial(int n); /*! Function Declaration !*/ 4 | 5 | int main() /* Definition for main */ 6 | { 7 | int number; /* Number from user */ 8 | int answer; /* Answer of factorial */ 9 | 10 | printf("Input a number: "); /* Call to printf */ 11 | 12 | scanf("%d", &number); /* Call to scanf */ 13 | 14 | answer = Factorial(number); /*! Call to factorial !*/ 15 | 16 | printf("The factorial of %d is %d\n", number, answer); 17 | } 18 | 19 | int Factorial(int n) /*! Function Definition !*/ 20 | { 21 | int i; /* Iteration count */ 22 | int result = 1; /* Initialized result */ 23 | 24 | for (i = 1; i <= n; i++) /* Calculate factorial */ 25 | result = result * i; 26 | 27 | return result; /*! Return to caller !*/ 28 | } 29 | -------------------------------------------------------------------------------- /include/stdarg.h: -------------------------------------------------------------------------------- 1 | #ifndef __STDARG 2 | #define __STDARG 3 | 4 | #if !defined(_VA_LIST) && !defined(__VA_LIST_DEFINED) 5 | #define _VA_LIST 6 | #define _VA_LIST_DEFINED 7 | typedef char *__va_list; 8 | #endif 9 | static float __va_arg_tmp; 10 | typedef __va_list va_list; 11 | 12 | #define va_start(list, start) ((void)((list) = (sizeof(start)<4 ? \ 13 | (char *)((int *)&(start)+1) : (char *)(&(start)+1)))) 14 | #define __va_arg(list, mode, n) (\ 15 | __typecode(mode)==1 && sizeof(mode)==4 ? \ 16 | (__va_arg_tmp = *(double *)(&(list += ((sizeof(double)+n)&~n))[-(int)((sizeof(double)+n)&~n)]), \ 17 | *(mode *)&__va_arg_tmp) : \ 18 | *(mode *)(&(list += ((sizeof(mode)+n)&~n))[-(int)((sizeof(mode)+n)&~n)])) 19 | #define _bigendian_va_arg(list, mode, n) (\ 20 | sizeof(mode)==1 ? *(mode *)(&(list += 4)[-1]) : \ 21 | sizeof(mode)==2 ? *(mode *)(&(list += 4)[-2]) : __va_arg(list, mode, n)) 22 | #define _littleendian_va_arg(list, mode, n) __va_arg(list, mode, n) 23 | #define va_end(list) ((void)0) 24 | #define va_arg(list, mode) _littleendian_va_arg(list, mode, 3U) 25 | typedef void *__gnuc_va_list; 26 | #endif 27 | -------------------------------------------------------------------------------- /test/regression/fig16.13.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAX_STRING 20 3 | 4 | int StringLength(char string[]); 5 | void CharSwap(char *firstVal, char *secondVal); 6 | void Reverse(char string[]); 7 | 8 | int main() 9 | { 10 | char input[MAX_STRING]; /* Input string */ 11 | 12 | printf("Input a word (less than 20 characters): "); 13 | scanf("%s", input); 14 | 15 | Reverse(input); 16 | printf("The word reversed is %s.\n", input); 17 | } 18 | 19 | int StringLength(char string[]) 20 | { 21 | int index = 0; 22 | 23 | while (string[index] != '\0') 24 | index = index + 1; 25 | 26 | return index; 27 | } 28 | 29 | void CharSwap(char *firstVal, char *secondVal) 30 | { 31 | char tempVal; /* Temporary location for swapping */ 32 | 33 | tempVal = *firstVal; 34 | *firstVal = *secondVal; 35 | *secondVal = tempVal; 36 | } 37 | 38 | void Reverse(char string[]) 39 | { 40 | int index; 41 | int length; 42 | 43 | length = StringLength(string); 44 | 45 | for (index = 0; index < (length / 2); index++) 46 | CharSwap(&string[index], &string[length - (index + 1)]); 47 | } 48 | -------------------------------------------------------------------------------- /include/float.h: -------------------------------------------------------------------------------- 1 | #ifndef __FLOAT 2 | #define __FLOAT 3 | 4 | #define FLT_ROUNDS (__flt_rounds()) 5 | #define FLT_RADIX 2 6 | 7 | #define FLT_DIG 6 8 | #define FLT_EPSILON 1.19209289550781250000e-07 9 | #define FLT_MANT_DIG 24 10 | #define FLT_MAX 3.40282346638528860000e+38 11 | #define FLT_MAX_10_EXP 38 12 | #define FLT_MAX_EXP 128 13 | #define FLT_MIN 1.17549435082228750000e-38 14 | #define FLT_MIN_10_EXP -37 15 | #define FLT_MIN_EXP -125 16 | 17 | #define DBL_DIG 15 18 | #define DBL_EPSILON 2.22044604925031310000e-16 19 | #define DBL_MANT_DIG 53 20 | #define DBL_MAX 1.79769313486231570000e+308 21 | #define DBL_MAX_10_EXP 308 22 | #define DBL_MAX_EXP 1024 23 | #define DBL_MIN 2.22507385850720140000e-308 24 | #define DBL_MIN_10_EXP -307 25 | #define DBL_MIN_EXP -1021 26 | 27 | #define LDBL_MANT_DIG DBL_MANT_DIG 28 | #define LDBL_EPSILON DBL_EPSILON 29 | #define LDBL_DIG DBL_DIG 30 | #define LDBL_MIN_EXP DBL_MIN_EXP 31 | #define LDBL_MIN DBL_MIN 32 | #define LDBL_MIN_10_EXP DBL_MIN_10_EXP 33 | #define LDBL_MAX_EXP DBL_MAX_EXP 34 | #define LDBL_MAX DBL_MAX 35 | #define LDBL_MAX_10_EXP DBL_MAX_10_EXP 36 | 37 | #endif /* __FLOAT */ 38 | -------------------------------------------------------------------------------- /test/regression/fig16.6.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int IntDivide(int x, int y, int *quoPtr, int *remPtr); 4 | 5 | int main() 6 | { 7 | int dividend; /* The number to be divided */ 8 | int divisor; /* The number to divide by */ 9 | int quotient; /* Integer result of division */ 10 | int remainder; /* Integer remainder of division */ 11 | int error; /* Did something go wrong? */ 12 | 13 | printf("Input dividend: "); 14 | scanf("%d", ÷nd); 15 | printf("Input divisor: "); 16 | scanf("%d", &divisor); 17 | 18 | error = IntDivide(dividend,divisor,"ient,&remainder); 19 | 20 | if (!error) /* !error indicates no error */ 21 | printf("Answer: %d remainder %d\n", quotient, remainder); 22 | else 23 | printf("IntDivide failed.\n"); 24 | } 25 | 26 | int IntDivide(int x, int y, int *quoPtr, int *remPtr) 27 | { 28 | if (y != 0) { 29 | *quoPtr = x / y; /* Modify *quoPtr */ 30 | *remPtr = x % y; /* Modify *remPtr */ 31 | return 0; 32 | } 33 | else 34 | return -1; 35 | } 36 | -------------------------------------------------------------------------------- /test/regression/fig16.9.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAX_NUMS 10 3 | 4 | int main() 5 | { 6 | int index; /* Loop iteration variable */ 7 | int repIndex; /* Loop variable for rep loop */ 8 | int numbers[MAX_NUMS]; /* Original input numbers */ 9 | int repeats[MAX_NUMS]; /* Number of repeats */ 10 | 11 | /* Get input */ 12 | printf("Enter %d numbers.\n", MAX_NUMS); 13 | for (index = 0; index < MAX_NUMS; index++) { 14 | printf("Input number %d : ", index); 15 | scanf("%d", &numbers[index]); 16 | } 17 | 18 | /* Scan through entire array, counting number of */ 19 | /* repeats per element within the original array */ 20 | for (index = 0; index < MAX_NUMS; index++) { 21 | repeats[index] = 0; 22 | for (repIndex = 0; repIndex < MAX_NUMS; repIndex++) { 23 | if (numbers[repIndex] == numbers[index]) 24 | repeats[index]++; 25 | } 26 | } 27 | 28 | /* Print the results */ 29 | for (index = 0; index < MAX_NUMS; index++) 30 | printf("Original number %d. Number of repeats %d\n", 31 | numbers[index], repeats[index]); 32 | } 33 | -------------------------------------------------------------------------------- /test/limitations/init.c: -------------------------------------------------------------------------------- 1 | 2 | typedef struct { int codes[3]; char name[6]; } Word; 3 | 4 | Word words[] = { 5 | // 1, 2, 3, "if", 6 | { { 4, 5 }, { 'f', 'o', 'r' } }, 7 | // 6, 7, 8, {"else"}, 8 | // { { 9, 10, 11,}, 'w', 'h', 'i', 'l', 'e', }, 9 | // { 0 }, 10 | }, *wordlist = words; 11 | 12 | int x[][5] = { 1, 2, 3, 4, 0, { 5, 6 }, { 7 } }; 13 | int *y[] = { x[0], x[1], x[2], 0 }; 14 | 15 | 16 | main() 17 | { 18 | int i, j; 19 | 20 | for (i = 0; y[i]; i++) { 21 | for (j = 0; y[i][j]; j++) 22 | printf(" %d", y[i][j]); 23 | printf("\n"); 24 | } 25 | f(); 26 | g(wordlist); 27 | return 0; 28 | } 29 | 30 | f() { 31 | static char *keywords[] = {"if", "for", "else", "while", 0, }; 32 | char **p; 33 | 34 | for (p = keywords; *p; p++) 35 | printf("%s\n", *p); 36 | } 37 | 38 | g(p) 39 | Word *p; 40 | { 41 | int i; 42 | 43 | for ( ; p->codes[0]; p++) { 44 | for (i = 0; i < sizeof p->codes/sizeof(p->codes[0]); i++) 45 | printf("%d ", p->codes[i]); 46 | printf("%s\n", p->name); 47 | } 48 | h(); 49 | } 50 | 51 | h() 52 | { 53 | int i; 54 | 55 | for (i = 0; i < sizeof(words)/sizeof(Word); i++) 56 | printf("%d %d %d %s\n", words[i].codes[0], 57 | words[i].codes[1], words[i].codes[2], 58 | &words[i].name[0]); 59 | } 60 | -------------------------------------------------------------------------------- /cpp/getopt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define EPR fprintf(stderr, 4 | #define ERR(str, chr) if(opterr){EPR "%s%c\n", str, chr);} 5 | int opterr = 1; 6 | int optind = 1; 7 | int optopt; 8 | char *optarg; 9 | 10 | int 11 | getopt (int argc, char *const argv[], const char *opts) 12 | { 13 | static int sp = 1; 14 | int c; 15 | char *cp; 16 | 17 | if (sp == 1) 18 | if (optind >= argc || 19 | argv[optind][0] != '-' || argv[optind][1] == '\0') 20 | return -1; 21 | else if (strcmp(argv[optind], "--") == 0) { 22 | optind++; 23 | return -1; 24 | } 25 | optopt = c = argv[optind][sp]; 26 | if (c == ':' || (cp=strchr(opts, c)) == 0) { 27 | ERR (": illegal option -- ", c); 28 | if (argv[optind][++sp] == '\0') { 29 | optind++; 30 | sp = 1; 31 | } 32 | return '?'; 33 | } 34 | if (*++cp == ':') { 35 | if (argv[optind][sp+1] != '\0') 36 | optarg = &argv[optind++][sp+1]; 37 | else if (++optind >= argc) { 38 | ERR (": option requires an argument -- ", c); 39 | sp = 1; 40 | return '?'; 41 | } else 42 | optarg = argv[optind++]; 43 | sp = 1; 44 | } else { 45 | if (argv[optind][++sp] == '\0') { 46 | sp = 1; 47 | optind++; 48 | } 49 | optarg = 0; 50 | } 51 | return c; 52 | } 53 | -------------------------------------------------------------------------------- /src/list.c: -------------------------------------------------------------------------------- 1 | #include "c.h" 2 | 3 | static char rcsid[] = "$Id: list.c,v 1.1.1.1 2004/03/24 04:37:33 sjp Exp $"; 4 | 5 | static List freenodes; /* free list nodes */ 6 | 7 | /* append - append x to list, return new list */ 8 | List append(void *x, List list) { 9 | List new; 10 | 11 | if ((new = freenodes) != NULL) 12 | freenodes = freenodes->link; 13 | else 14 | NEW(new, PERM); 15 | if (list) { 16 | new->link = list->link; 17 | list->link = new; 18 | } else 19 | new->link = new; 20 | new->x = x; 21 | return new; 22 | } 23 | 24 | /* length - # elements in list */ 25 | int length(List list) { 26 | int n = 0; 27 | 28 | if (list) { 29 | List lp = list; 30 | do 31 | n++; 32 | while ((lp = lp->link) != list); 33 | } 34 | return n; 35 | } 36 | 37 | /* ltov - convert list to an NULL-terminated vector allocated in arena */ 38 | void *ltov(List *list, unsigned arena) { 39 | int i = 0; 40 | void **array = newarray(length(*list) + 1, sizeof array[0], arena); 41 | 42 | if (*list) { 43 | List lp = *list; 44 | do { 45 | lp = lp->link; 46 | array[i++] = lp->x; 47 | } while (lp != *list); 48 | #ifndef PURIFY 49 | lp = (*list)->link; 50 | (*list)->link = freenodes; 51 | freenodes = lp; 52 | #endif 53 | } 54 | *list = NULL; 55 | array[i] = NULL; 56 | return array; 57 | } 58 | -------------------------------------------------------------------------------- /NO_WARRANTY: -------------------------------------------------------------------------------- 1 | NO WARRANTY 2 | 3 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 4 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 5 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 6 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 7 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 8 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 9 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 10 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 11 | REPAIR OR CORRECTION. 12 | 13 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 14 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 15 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 16 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 17 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 18 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 19 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 20 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 21 | POSSIBILITY OF SUCH DAMAGES. 22 | -------------------------------------------------------------------------------- /etc/lc3.c: -------------------------------------------------------------------------------- 1 | /* x86s running Linux */ 2 | 3 | #include 4 | 5 | static char rcsid[] = "$Id: lc3.c,v 1.1.1.1 2004/03/24 04:37:35 sjp Exp $"; 6 | 7 | #ifndef LCCDIR 8 | #define LCCDIR "./" 9 | #endif 10 | 11 | #ifndef BASEDIR 12 | #define BASEDIR "./" 13 | #endif 14 | 15 | /* char *suffixes[] = { ".c", ".i", ".s", ".o", ".out", 0 }; */ 16 | char *suffixes[] = { ".c", ".i", ".lcc", ".asm", ".obj", ".out", 0 }; 17 | char inputs[256] = ""; 18 | char *cpp[] = { LCCDIR "cpp", 19 | "-U__GNUC__", "-D__STDC__=1", "-D__STRICT_ANSI__", "-D__signed__=signed", 20 | "$1", "$2", "$3", 0 }; 21 | char *include[] = {"-I" LCCDIR "include", "-I" BASEDIR "lc3lib", 0 }; 22 | char *com[] = { LCCDIR "rcc", "-target=lc3", "$1", "$2", "$3", 0 }; 23 | char *as[] = { LCCDIR "lc3as", "$1", "$2", 0 }; 24 | char *ld[] = { LCCDIR "lc3pp", BASEDIR "lc3lib", "$1", "$2", "$3", 0 }; 25 | 26 | extern char *concat(char *, char *); 27 | 28 | int option(char *arg) { 29 | if (strncmp(arg, "-lccdir=", 8) == 0) { 30 | include[0] = concat("-I", concat(&arg[8], "/include")); 31 | cpp[0] = concat(&arg[8], "/install/cpp"); 32 | com[0] = concat(&arg[8], "/install/rcc"); 33 | ld[0] = concat(&arg[8], "/install/lc3lib"); 34 | ld[1] = concat(&arg[8], "/lc3lib"); 35 | } else if (strncmp(arg, "-ld=", 4) == 0) 36 | ld[0] = &arg[4]; 37 | else return 0; 38 | return 1; 39 | } 40 | -------------------------------------------------------------------------------- /test/regression/sort.c: -------------------------------------------------------------------------------- 1 | int nn[] = {10, 32, -1, 567, 3, 18, 1, -51, 789, 0}; 2 | 3 | main() { 4 | int i; 5 | 6 | sort(nn, (sizeof nn)/(sizeof nn[0])); 7 | for (i = 0; i < (sizeof nn)/(sizeof nn[0]); i++) { 8 | putd(nn[i]); 9 | putchar('\n'); 10 | } 11 | return 0; 12 | } 13 | 14 | /* putd - output decimal number */ 15 | putd(n) { 16 | if (n < 0) { 17 | putchar('-'); 18 | n = -n; 19 | } 20 | if (n/10) 21 | putd(n/10); 22 | putchar(n%10 + '0'); 23 | } 24 | 25 | int *xx; 26 | 27 | /* sort - sort a[0..n-1] into increasing order */ 28 | sort(a, n) int a[]; { 29 | quick(xx = a, 0, --n); 30 | } 31 | 32 | /* quick - quicksort a[lb..ub] */ 33 | quick(a, lb, ub) int a[]; { 34 | int k, partition(); 35 | 36 | if (lb >= ub) 37 | return; 38 | k = partition(a, lb, ub); 39 | quick(a, lb, k - 1); 40 | quick(a, k + 1, ub); 41 | } 42 | 43 | /* partition - partition a[i..j] */ 44 | int partition(a, i, j) int a[]; { 45 | int v, k; 46 | 47 | j++; 48 | k = i; 49 | v = a[k]; 50 | while (i < j) { 51 | i++; while (a[i] < v) i++; 52 | j--; while (a[j] > v) j--; 53 | if (i < j) exchange(&a[i], &a[j]); 54 | } 55 | exchange(&a[k], &a[j]); 56 | return j; 57 | } 58 | 59 | /* exchange - exchange *x and *y */ 60 | exchange(x, y) int *x, *y; { 61 | int t; 62 | 63 | printf("exchange(%d,%d)\n", x - xx, y - xx); 64 | t = *x; *x = *y; *y = t; 65 | } 66 | -------------------------------------------------------------------------------- /INSTALL.txt: -------------------------------------------------------------------------------- 1 | Basic Installation 2 | ================== 3 | 4 | These are generic installation instructions. 5 | 6 | The `configure' shell script attempts to guess correct values for 7 | various system-dependent variables used during compilation. It uses 8 | those values to create a `Makefile' in each directory of the package. 9 | 10 | If you need to do unusual things to compile the package, please try 11 | to figure out how `configure' could check whether to do them, and mail 12 | diffs or instructions to the address given in the `README' so they can 13 | be considered for the next release. 14 | 15 | The simplest way to compile this package is: 16 | 17 | 1. `cd' to the directory containing the package's source code and type 18 | `./configure' to configure the package for your system. If you're 19 | using `csh' on an old version of System V, you might need to type 20 | `sh ./configure' instead to prevent `csh' from trying to execute 21 | `configure' itself. 22 | 23 | 2. Type `make' to compile the package. 24 | 25 | 4. Type `make install' to install the programs and any data files and 26 | documentation. 27 | 28 | 5. You can remove the program binaries and object files from the 29 | source code directory by typing `make clean'. To also remove the 30 | files that `configure' created (so you can compile the package for 31 | a different kind of computer), type `make distclean'. 32 | -------------------------------------------------------------------------------- /test/regression/fig16.14.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #define MAX_NUMS 10 4 | 5 | void InsertionSort(int list[]); 6 | 7 | int main() 8 | { 9 | int index; /* iteration variable */ 10 | int numbers[MAX_NUMS]; /* list of number to be sorted */ 11 | 12 | /* Get input */ 13 | printf("Enter %d numbers.\n", MAX_NUMS); 14 | for (index = 0; index < MAX_NUMS; index++) { 15 | printf("Input number %d : ", index); 16 | scanf("%d", &numbers[index]); 17 | } 18 | 19 | InsertionSort(numbers); /* Call sorting routine */ 20 | 21 | /* Print sorted list */ 22 | printf("\nThe input set, in ascending order:\n"); 23 | for (index = 0; index < MAX_NUMS; index++) 24 | printf("%d\n", numbers[index]); 25 | } 26 | 27 | void InsertionSort(int list[]) 28 | { 29 | int unsorted; /* index for unsorted list items */ 30 | int sorted; /* index for sorted items */ 31 | int unsortedItem; /* Current item to be sorted */ 32 | 33 | /* This loop iterates from 1 thru MAX_NUMS */ 34 | for (unsorted = 1; unsorted < MAX_NUMS; unsorted++) { 35 | unsortedItem = list[unsorted]; 36 | 37 | /* This loop iterates from unsorted thru 0, unless 38 | we hit an element smaller than current item */ 39 | for (sorted = unsorted - 1; 40 | (sorted >= 0) && (list[sorted] > unsortedItem); 41 | sorted--) 42 | list[sorted + 1] = list[sorted]; 43 | 44 | list[sorted + 1] = unsortedItem; /* Insert item */ 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /test/regression/struct.c: -------------------------------------------------------------------------------- 1 | typedef struct point { int x,y; } point; 2 | typedef struct rect { point pt1, pt2; } rect; 3 | 4 | point addpoint(point p1, point p2) { /* add two points */ 5 | p1.x += p2.x; 6 | p1.y += p2.y; 7 | return p1; 8 | } 9 | 10 | #define min(a, b) ((a) < (b) ? (a) : (b)) 11 | #define max(a, b) ((a) > (b) ? (a) : (b)) 12 | 13 | rect canonrect(rect r) { /* canonicalize rectangle coordinates */ 14 | rect temp; 15 | 16 | temp.pt1.x = min(r.pt1.x, r.pt2.x); 17 | temp.pt1.y = min(r.pt1.y, r.pt2.y); 18 | temp.pt2.x = max(r.pt1.x, r.pt2.x); 19 | temp.pt2.y = max(r.pt1.y, r.pt2.y); 20 | return temp; 21 | } 22 | 23 | point makepoint(int x, int y) { /* make a point from x and y components */ 24 | point p; 25 | 26 | p.x = x; 27 | p.y = y; 28 | return p; 29 | } 30 | 31 | rect makerect(point p1, point p2) { /* make a rectangle from two points */ 32 | rect r; 33 | 34 | r.pt1 = p1; 35 | r.pt2 = p2; 36 | return canonrect(r); 37 | } 38 | 39 | int ptinrect(point p, rect r) { /* is p in r? */ 40 | return p.x >= r.pt1.x && p.x < r.pt2.x 41 | && p.y >= r.pt1.y && p.y < r.pt2.y; 42 | } 43 | 44 | struct odd {char a[3]; } y = {'a', 'b', 0}; 45 | 46 | odd(struct odd y) { 47 | struct odd x = y; 48 | printf("%s\n", x.a); 49 | } 50 | 51 | main() { 52 | int i; 53 | point x, origin = { 0, 0 }, maxpt = { 320, 320 }; 54 | point pts[] = { -1, -1, 1, 1, 20, 300, 500, 400 }; 55 | rect screen = makerect(addpoint(maxpt, makepoint(-10, -10)), 56 | addpoint(origin, makepoint(10, 10))); 57 | 58 | for (i = 0; i < sizeof pts/sizeof pts[0]; i++) { 59 | printf("(%d,%d) is ", pts[i].x, 60 | (x = makepoint(pts[i].x, pts[i].y)).y); 61 | if (ptinrect(x, screen) == 0) 62 | printf("not "); 63 | printf("within [%d,%d; %d,%d]\n", screen.pt1.x, screen.pt1.y, 64 | screen.pt2.x, screen.pt2.y); 65 | } 66 | odd(y); 67 | return 0; 68 | } 69 | 70 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 4 May 2012 Sean Smith, Stephen Cannon, Avery Yen 2 | Modified configure to compile on Mac OS X, especially Lion. 3 | Modified Makefile.def and configure to automatically install to ~/.lc3. 4 | Also, `make install` now only installs executables. 5 | 6 | 23 March 2004 Sanjay J. Patel 7 | Modified lcc.c and lc3.c to customize the compile process around the LC-3 tools. 8 | 9 | 8 March 2004 Sanjay J. Patel 10 | Cleaned up the configuration process and the install 11 | 12 | 7 January 2004 Ajay Ladsaria 13 | stab.h: This file was not included in the distribution initially! 14 | README: Updated to provide proper installation instructions. 15 | Makefile.am: The man pages in doc/ correctly install 16 | Example makefile in test/regressions/ has been updated and commented 17 | 18 | 7 January 2004 Ajay Ladsaria 19 | makefile.am: Fixed the installation of the 3 manual pages 20 | 21 | 5 January 2004 Ajay Ladsaria 22 | lc3pp.c: Now does not hard code max lengths for source line and global var 23 | length 24 | lc3pp.c: Allocates tmp files with unique names and deletes them 25 | lc3pp.c: A third arg now specifies where to look for lib files 26 | 27 | 17 December 2003 Ajay Ladsaria 28 | lc3.md: Terminal names now reflect the one byte size of LC-3's basic types 29 | lc3.md: Stripped useless comments and added some new ones 30 | 31 | 15 December 2003 Ajay Ladsaria 32 | printf now supports format strings %x,%o,%b to print a num as hex,oct,bin 33 | lc3.md: defstring updated to handle all basic C string escape sequences 34 | 35 | 15 December 2003 Ajay Ladsaria 36 | printf now supports format strings %x,%o,%b to print a num as hex,oct,bin 37 | 38 | 31 November 2003 Ajay Ladsaria 39 | made all the makefiles recursive 40 | used BUILT_SOURCES in makefile.am for *.md files 41 | 42 | -------------------------------------------------------------------------------- /doc/man1/bprint.1: -------------------------------------------------------------------------------- 1 | .\" $Id: bprint.1,v 1.1.1.1 2004/03/24 04:37:34 sjp Exp $ 2 | .TH BPRINT 1 "local \- $Date: 2004/03/24 04:37:34 $" 3 | .SH NAME 4 | bprint \- expression profiler 5 | .SH SYNOPSIS 6 | .B bprint 7 | [ 8 | .I option ... 9 | ] 10 | [ 11 | .I file ... 12 | ] 13 | .SH DESCRIPTION 14 | .I bprint 15 | produces on the standard output a listing of the programs compiled by 16 | .I lcc 17 | with the 18 | .B \-b 19 | option. 20 | Executing an 21 | .B a.out 22 | so compiled appends profiling data to 23 | .BR prof.out . 24 | The first token of each expression in the listing is preceded 25 | by the number of times it was executed 26 | enclosed in angle brackets as determined from the data in 27 | .BR prof.out . 28 | .I bprint 29 | interprets the following options. 30 | .TP 31 | .B \-c 32 | Compress the 33 | .B prof.out 34 | file, which otherwise grows with every execution of 35 | .BR a.out . 36 | .TP 37 | .B \-b 38 | Print an annotated listing as described above. 39 | .TP 40 | .B \-n 41 | Include line numbers in the listing. 42 | .TP 43 | .B \-f 44 | Print only the number of invocations of each function. 45 | A second 46 | .B \-f 47 | summarizes call sites instead of callers. 48 | .TP 49 | .BI \-I \*Sdir 50 | specifies additional directories in which to seek 51 | files given in 52 | .B prof.out 53 | that do not begin with `/'. 54 | .PP 55 | If any file names are given, only the requested data for those files are printed 56 | in the order presented. 57 | If no options are given, 58 | .B \-b 59 | is assumed. 60 | .SH FILES 61 | .PP 62 | .ta \w'$LCCDIR/liblcc.{a,lib}XX'u 63 | .nf 64 | prof.out profiling data 65 | $LCCDIR/liblcc.{a,lib} \fIlcc\fP-specific library 66 | .SH "SEE ALSO" 67 | .IR lcc (1), 68 | .IR prof (1) 69 | .SH BUGS 70 | Macros and comments can confuse 71 | .I bprint 72 | because it uses post-expansion source coordinates 73 | to annotate pre-expansion source files. 74 | If 75 | .I bprint 76 | sees that it's about to print a statement count 77 | .I inside 78 | a number or identifier, it moves the count to just 79 | .I before 80 | the token. 81 | .PP 82 | Can't cope with an ill-formed 83 | .BR prof.out . 84 | -------------------------------------------------------------------------------- /src/alloc.c: -------------------------------------------------------------------------------- 1 | #include "c.h" 2 | struct block { 3 | struct block *next; 4 | char *limit; 5 | char *avail; 6 | }; 7 | union align { 8 | long l; 9 | char *p; 10 | double d; 11 | int (*f)(void); 12 | }; 13 | union header { 14 | struct block b; 15 | union align a; 16 | }; 17 | #ifdef PURIFY 18 | union header *arena[3]; 19 | 20 | void *allocate(unsigned long n, unsigned a) { 21 | union header *new = malloc(sizeof *new + n); 22 | 23 | assert(a < NELEMS(arena)); 24 | if (new == NULL) { 25 | error("insufficient memory\n"); 26 | exit(1); 27 | } 28 | new->b.next = (void *)arena[a]; 29 | arena[a] = new; 30 | return new + 1; 31 | } 32 | 33 | void deallocate(unsigned a) { 34 | union header *p, *q; 35 | 36 | assert(a < NELEMS(arena)); 37 | for (p = arena[a]; p; p = q) { 38 | q = (void *)p->b.next; 39 | free(p); 40 | } 41 | arena[a] = NULL; 42 | } 43 | 44 | void *newarray(unsigned long m, unsigned long n, unsigned a) { 45 | return allocate(m*n, a); 46 | } 47 | #else 48 | static struct block 49 | first[] = { { NULL }, { NULL }, { NULL } }, 50 | *arena[] = { &first[0], &first[1], &first[2] }; 51 | static struct block *freeblocks; 52 | 53 | void *allocate(unsigned long n, unsigned a) { 54 | struct block *ap; 55 | 56 | assert(a < NELEMS(arena)); 57 | assert(n > 0); 58 | ap = arena[a]; 59 | n = roundup(n, sizeof (union align)); 60 | while (n > ap->limit - ap->avail) { 61 | if ((ap->next = freeblocks) != NULL) { 62 | freeblocks = freeblocks->next; 63 | ap = ap->next; 64 | } else 65 | { 66 | unsigned m = sizeof (union header) + n + roundup(10*1024, sizeof (union align)); 67 | ap->next = malloc(m); 68 | ap = ap->next; 69 | if (ap == NULL) { 70 | error("insufficient memory\n"); 71 | exit(1); 72 | } 73 | ap->limit = (char *)ap + m; 74 | } 75 | ap->avail = (char *)((union header *)ap + 1); 76 | ap->next = NULL; 77 | arena[a] = ap; 78 | 79 | } 80 | ap->avail += n; 81 | return ap->avail - n; 82 | } 83 | 84 | void *newarray(unsigned long m, unsigned long n, unsigned a) { 85 | return allocate(m*n, a); 86 | } 87 | void deallocate(unsigned a) { 88 | assert(a < NELEMS(arena)); 89 | arena[a]->next = freeblocks; 90 | freeblocks = first[a].next; 91 | first[a].next = NULL; 92 | arena[a] = &first[a]; 93 | } 94 | #endif 95 | -------------------------------------------------------------------------------- /src/null.c: -------------------------------------------------------------------------------- 1 | #include "c.h" 2 | #define I(f) null_##f 3 | 4 | static Node I(gen)(Node p) { return p; } 5 | static void I(address)(Symbol q, Symbol p, long n) {} 6 | static void I(blockbeg)(Env *e) {} 7 | static void I(blockend)(Env *e) {} 8 | static void I(defaddress)(Symbol p) {} 9 | static void I(defconst)(int suffix, int size, Value v) {} 10 | static void I(defstring)(int len, char *s) {} 11 | static void I(defsymbol)(Symbol p) {} 12 | static void I(emit)(Node p) {} 13 | static void I(export)(Symbol p) {} 14 | static void I(function)(Symbol f, Symbol caller[], Symbol callee[], int ncalls) {} 15 | static void I(global)(Symbol p) {} 16 | static void I(import)(Symbol p) {} 17 | static void I(local)(Symbol p) {} 18 | static void I(progbeg)(int argc, char *argv[]) {} 19 | static void I(progend)(void) {} 20 | static void I(segment)(int s) {} 21 | static void I(space)(int n) {} 22 | static void I(stabblock)(int brace, int lev, Symbol *p) {} 23 | static void I(stabend)(Coordinate *cp, Symbol p, Coordinate **cpp, Symbol *sp, Symbol *stab) {} 24 | static void I(stabfend)(Symbol p, int lineno) {} 25 | static void I(stabinit)(char *file, int argc, char *argv[]) {} 26 | static void I(stabline)(Coordinate *cp) {} 27 | static void I(stabsym)(Symbol p) {} 28 | static void I(stabtype)(Symbol p) {} 29 | 30 | static char rcsid[] = "$Id: null.c,v 1.1.1.1 2004/03/24 04:37:33 sjp Exp $"; 31 | 32 | Interface nullIR = { 33 | 1, 1, 0, /* char */ 34 | 2, 2, 0, /* short */ 35 | 4, 4, 0, /* int */ 36 | 8, 8, 1, /* long */ 37 | 8 ,8, 1, /* long long */ 38 | 4, 4, 1, /* float */ 39 | 8, 8, 1, /* double */ 40 | 16,16,1, /* long double */ 41 | 4, 4, 0, /* T* */ 42 | 0, 4, 0, /* struct */ 43 | 1, /* little_endian */ 44 | 0, /* mulops_calls */ 45 | 0, /* wants_callb */ 46 | 0, /* wants_argb */ 47 | 1, /* left_to_right */ 48 | 0, /* wants_dag */ 49 | 0, /* unsigned_char */ 50 | I(address), 51 | I(blockbeg), 52 | I(blockend), 53 | I(defaddress), 54 | I(defconst), 55 | I(defstring), 56 | I(defsymbol), 57 | I(emit), 58 | I(export), 59 | I(function), 60 | I(gen), 61 | I(global), 62 | I(import), 63 | I(local), 64 | I(progbeg), 65 | I(progend), 66 | I(segment), 67 | I(space), 68 | I(stabblock), 69 | I(stabend), 70 | I(stabfend), 71 | I(stabinit), 72 | I(stabline), 73 | I(stabsym), 74 | I(stabtype) 75 | }; 76 | -------------------------------------------------------------------------------- /lburg/lburg.h: -------------------------------------------------------------------------------- 1 | #ifndef BURG_INCLUDED 2 | #define BURG_INCLUDED 3 | 4 | /* $Id: lburg.h,v 1.1.1.1 2004/03/24 04:37:35 sjp Exp $ */ 5 | /* iburg.c: */ 6 | extern void *alloc(int nbytes); 7 | 8 | typedef enum { TERM=1, NONTERM } Kind; 9 | typedef struct rule *Rule; 10 | typedef struct term *Term; 11 | struct term { /* terminals: */ 12 | char *name; /* terminal name */ 13 | Kind kind; /* TERM */ 14 | int esn; /* external symbol number */ 15 | int arity; /* operator arity */ 16 | Term link; /* next terminal in esn order */ 17 | Rule rules; /* rules whose pattern starts with term */ 18 | }; 19 | 20 | typedef struct nonterm *Nonterm; 21 | struct nonterm { /* nonterminals: */ 22 | char *name; /* nonterminal name */ 23 | Kind kind; /* NONTERM */ 24 | int number; /* identifying number */ 25 | int lhscount; /* # times nt appears in a rule lhs */ 26 | int reached; /* 1 iff reached from start nonterminal */ 27 | Rule rules; /* rules w/nonterminal on lhs */ 28 | Rule chain; /* chain rules w/nonterminal on rhs */ 29 | Nonterm link; /* next terminal in number order */ 30 | }; 31 | extern Nonterm nonterm(char *id); 32 | extern Term term(char *id, int esn); 33 | 34 | typedef struct tree *Tree; 35 | struct tree { /* tree patterns: */ 36 | void *op; /* a terminal or nonterminal */ 37 | Tree left, right; /* operands */ 38 | int nterms; /* number of terminal nodes in this tree */ 39 | }; 40 | extern Tree tree(char *op, Tree left, Tree right); 41 | 42 | struct rule { /* rules: */ 43 | Nonterm lhs; /* lefthand side nonterminal */ 44 | Tree pattern; /* rule pattern */ 45 | int ern; /* external rule number */ 46 | int packed; /* packed external rule number */ 47 | int cost; /* cost, if a constant */ 48 | char *code; /* cost, if an expression */ 49 | char *template; /* assembler template */ 50 | Rule link; /* next rule in ern order */ 51 | Rule next; /* next rule with same pattern root */ 52 | Rule chain; /* next chain rule with same rhs */ 53 | Rule decode; /* next rule with same lhs */ 54 | Rule kids; /* next rule with same _kids pattern */ 55 | }; 56 | extern Rule rule(char *id, Tree pattern, char *template, char *code); 57 | 58 | /* gram.y: */ 59 | void yyerror(char *fmt, ...); 60 | int yyparse(void); 61 | void yywarn(char *fmt, ...); 62 | extern int errcnt; 63 | extern FILE *infp; 64 | extern FILE *outfp; 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /lc3pp/Makefile.def: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Makefile (and Makefile.def) -- Makefile for the LC-3 tools 3 | # 4 | # "Copyright (c) 2003 by Steven S. Lumetta." 5 | # 6 | # Permission to use, copy, modify, and distribute this software and its 7 | # documentation for any purpose, without fee, and without written 8 | # agreement is hereby granted, provided that the above copyright notice 9 | # and the following two paragraphs appear in all copies of this software, 10 | # that the files COPYING and NO_WARRANTY are included verbatim with 11 | # any distribution, and that the contents of the file README are included 12 | # verbatim as part of a file named README with any distribution. 13 | # 14 | # IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, 15 | # INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT 16 | # OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE AUTHOR 17 | # HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 18 | # 19 | # THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 20 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | # A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" 22 | # BASIS, AND THE AUTHOR NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 23 | # UPDATES, ENHANCEMENTS, OR MODIFICATIONS." 24 | # 25 | # Author: Steve Lumetta 26 | # Version: 1 27 | # Creation Date: 18 October 2003 28 | # Filename: Makefile[.def] 29 | # History: 30 | # SSL 2 31 October 2003 31 | # Added lc3convert tool into distribution. 32 | # SSL 1 18 October 2003 33 | # Copyright notices and Gnu Public License marker added. 34 | # 35 | ############################################################################### 36 | 37 | # These path names are automatically set by configure. 38 | GCC = __GCC__ 39 | FLEX = __FLEX__ 40 | EXE = __EXE__ 41 | RM = __RM__ 42 | CP = __CP__ 43 | MKDIR = __MKDIR__ 44 | CHMOD = __CHMOD__ 45 | SED = __SED__ 46 | MAKE = __MAKE__ 47 | AR = __AR__ 48 | RANLIB = __RANLIB__ 49 | INSTALL_DIR = __INSTALL_DIR__ 50 | TOP_DIR = __TOP_DIR__ 51 | # End of configuration block. 52 | 53 | CFLAGS = -g -m32 54 | LDFLAGS = -g -m32 55 | LC3AS = ./lc3as 56 | 57 | %.o: %.c 58 | ${GCC} -c ${CFLAGS} -o $@ $< 59 | 60 | dist: lc3pp 61 | 62 | distclean:: 63 | ${RM} -f *.o *~ 64 | 65 | distclear: distclean 66 | ${RM} -f lc3pp${EXE} 67 | 68 | lc3pp: lc3pp.c 69 | ${GCC} ${CFLAGS} -o $@ $< 70 | -------------------------------------------------------------------------------- /lburg/Makefile.def: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Makefile (and Makefile.def) -- Makefile for the LC-3 tools 3 | # 4 | # "Copyright (c) 2003 by Steven S. Lumetta." 5 | # 6 | # Permission to use, copy, modify, and distribute this software and its 7 | # documentation for any purpose, without fee, and without written 8 | # agreement is hereby granted, provided that the above copyright notice 9 | # and the following two paragraphs appear in all copies of this software, 10 | # that the files COPYING and NO_WARRANTY are included verbatim with 11 | # any distribution, and that the contents of the file README are included 12 | # verbatim as part of a file named README with any distribution. 13 | # 14 | # IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, 15 | # INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT 16 | # OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE AUTHOR 17 | # HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 18 | # 19 | # THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 20 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | # A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" 22 | # BASIS, AND THE AUTHOR NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 23 | # UPDATES, ENHANCEMENTS, OR MODIFICATIONS." 24 | # 25 | # Author: Steve Lumetta 26 | # Version: 1 27 | # Creation Date: 18 October 2003 28 | # Filename: Makefile[.def] 29 | # History: 30 | # SSL 2 31 October 2003 31 | # Added lc3convert tool into distribution. 32 | # SSL 1 18 October 2003 33 | # Copyright notices and Gnu Public License marker added. 34 | # 35 | ############################################################################### 36 | 37 | # These path names are automatically set by configure. 38 | GCC = __GCC__ 39 | FLEX = __FLEX__ 40 | EXE = __EXE__ 41 | RM = __RM__ 42 | CP = __CP__ 43 | MKDIR = __MKDIR__ 44 | CHMOD = __CHMOD__ 45 | SED = __SED__ 46 | MAKE = __MAKE__ 47 | AR = __AR__ 48 | RANLIB = __RANLIB__ 49 | INSTALL_DIR = __INSTALL_DIR__ 50 | TOP_DIR = __TOP_DIR__ 51 | # End of configuration block. 52 | 53 | CFLAGS = -g -m32 -I. 54 | LDFLAGS = -g -m32 55 | LC3AS = ./lc3as 56 | 57 | %.o: %.c 58 | ${GCC} -c ${CFLAGS} -o $@ $< 59 | 60 | dist: lburg 61 | 62 | distclean: 63 | ${RM} -f *.o *~ 64 | 65 | distclear: distclean 66 | ${RM} -f lburg${EXE} 67 | 68 | lburg: gram.o lburg.o 69 | ${GCC} ${CFLAGS} -o $@ $^ 70 | -------------------------------------------------------------------------------- /lib/Makefile.def: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Makefile (and Makefile.def) -- Makefile for the LC-3 tools 3 | # 4 | # "Copyright (c) 2003 by Steven S. Lumetta." 5 | # 6 | # Permission to use, copy, modify, and distribute this software and its 7 | # documentation for any purpose, without fee, and without written 8 | # agreement is hereby granted, provided that the above copyright notice 9 | # and the following two paragraphs appear in all copies of this software, 10 | # that the files COPYING and NO_WARRANTY are included verbatim with 11 | # any distribution, and that the contents of the file README are included 12 | # verbatim as part of a file named README with any distribution. 13 | # 14 | # IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, 15 | # INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT 16 | # OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE AUTHOR 17 | # HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 18 | # 19 | # THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 20 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | # A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" 22 | # BASIS, AND THE AUTHOR NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 23 | # UPDATES, ENHANCEMENTS, OR MODIFICATIONS." 24 | # 25 | # Author: Steve Lumetta 26 | # Version: 1 27 | # Creation Date: 18 October 2003 28 | # Filename: Makefile[.def] 29 | # History: 30 | # SSL 2 31 October 2003 31 | # Added lc3convert tool into distribution. 32 | # SSL 1 18 October 2003 33 | # Copyright notices and Gnu Public License marker added. 34 | # 35 | ############################################################################### 36 | 37 | # These path names are automatically set by configure. 38 | GCC = __GCC__ 39 | FLEX = __FLEX__ 40 | EXE = __EXE__ 41 | RM = __RM__ 42 | CP = __CP__ 43 | MKDIR = __MKDIR__ 44 | CHMOD = __CHMOD__ 45 | SED = __SED__ 46 | MAKE = __MAKE__ 47 | AR = __AR__ 48 | RANLIB = __RANLIB__ 49 | INSTALL_DIR = __INSTALL_DIR__ 50 | # End of configuration block. 51 | 52 | CFLAGS = -g -Wall -m32 53 | LDFLAGS = -g -m32 54 | LC3AS = ./lc3as 55 | 56 | %.o: %.c 57 | ${GCC} -c ${CFLAGS} -o $@ $< 58 | 59 | dist: liblcc.a 60 | 61 | distclean:: 62 | ${RM} -f *.o *~ 63 | 64 | distclear: distclean 65 | ${RM} -f liblcc.a 66 | 67 | liblcc.a: assert.o bbexit.o yynull.o 68 | -rm -f liblcc.a 69 | ${AR} cru $@ $< 70 | ${RANLIB} $@ 71 | 72 | -------------------------------------------------------------------------------- /etc/Makefile.def: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Makefile (and Makefile.def) -- Makefile for the LC-3 tools 3 | # 4 | # "Copyright (c) 2003 by Steven S. Lumetta." 5 | # 6 | # Permission to use, copy, modify, and distribute this software and its 7 | # documentation for any purpose, without fee, and without written 8 | # agreement is hereby granted, provided that the above copyright notice 9 | # and the following two paragraphs appear in all copies of this software, 10 | # that the files COPYING and NO_WARRANTY are included verbatim with 11 | # any distribution, and that the contents of the file README are included 12 | # verbatim as part of a file named README with any distribution. 13 | # 14 | # IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, 15 | # INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT 16 | # OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE AUTHOR 17 | # HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 18 | # 19 | # THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 20 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | # A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" 22 | # BASIS, AND THE AUTHOR NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 23 | # UPDATES, ENHANCEMENTS, OR MODIFICATIONS." 24 | # 25 | # Author: Steve Lumetta 26 | # Version: 1 27 | # Creation Date: 18 October 2003 28 | # Filename: Makefile[.def] 29 | # History: 30 | # SSL 2 31 October 2003 31 | # Added lc3convert tool into distribution. 32 | # SSL 1 18 October 2003 33 | # Copyright notices and Gnu Public License marker added. 34 | # 35 | ############################################################################### 36 | 37 | # These path names are automatically set by configure. 38 | GCC = __GCC__ 39 | FLEX = __FLEX__ 40 | EXE = __EXE__ 41 | RM = __RM__ 42 | CP = __CP__ 43 | MKDIR = __MKDIR__ 44 | CHMOD = __CHMOD__ 45 | SED = __SED__ 46 | MAKE = __MAKE__ 47 | AR = __AR__ 48 | RANLIB = __RANLIB__ 49 | LCCDIR = __INSTALL_DIR__ 50 | BASEDIR = __TOP_DIR__ 51 | # End of configuration block. 52 | 53 | CFLAGS = -g -m32 -DLCCDIR='"${LCCDIR}/"' -DBASEDIR='"${BASEDIR}/"' 54 | LDFLAGS = -g -m32 55 | LC3AS = ./lc3as 56 | 57 | %.o: %.c 58 | ${GCC} -c ${CFLAGS} -o $@ $< 59 | 60 | dist: lcc 61 | 62 | distclean:: 63 | ${RM} -f *.o *~ 64 | 65 | distclear: distclean 66 | ${RM} -f lcc${EXE} 67 | 68 | lcc: lcc.o lc3.o 69 | ${GCC} ${CFLAGS} -o $@ $^ 70 | -------------------------------------------------------------------------------- /test/limitations/wf1.c: -------------------------------------------------------------------------------- 1 | /* wf1 - print word frequencies; uses structures */ 2 | 3 | struct node { 4 | int count; /* frequency count */ 5 | struct node *left; /* left subtree */ 6 | struct node *right; /* right subtree */ 7 | char *word; /* word itself */ 8 | } words[2000]; 9 | int next; /* index of next free entry in words */ 10 | 11 | struct node *lookup(); 12 | 13 | main() { 14 | struct node *root; 15 | char word[20]; 16 | 17 | root = 0; 18 | next = 0; 19 | while (getword(word)) 20 | lookup(word, &root)->count++; 21 | tprint(root); 22 | return 0; 23 | } 24 | 25 | /* err - print error message s and die */ 26 | err(s) char *s; { 27 | printf("? %s\n", s); 28 | exit(1); 29 | } 30 | 31 | /* getword - get next input word into buf, return 0 on EOF */ 32 | int getword(buf) char *buf; { 33 | char *s; 34 | int c; 35 | 36 | while ((c = getchar()) != -1 && isletter(c) == 0) 37 | ; 38 | for (s = buf; c = isletter(c); c = getchar()) 39 | *s++ = c; 40 | *s = 0; 41 | if (s > buf) 42 | return (1); 43 | return (0); 44 | } 45 | 46 | /* isletter - return folded version of c if it is a letter, 0 otherwise */ 47 | int isletter(c) { 48 | if (c >= 'A' && c <= 'Z') 49 | c += 'a' - 'A'; 50 | if (c >= 'a' && c <= 'z') 51 | return (c); 52 | return (0); 53 | } 54 | 55 | /* lookup - lookup word in tree; install if necessary */ 56 | struct node *lookup(word, p) char *word; struct node **p; { 57 | int cond; 58 | char *malloc(); 59 | 60 | if (*p) { 61 | cond = strcmp(word, (*p)->word); 62 | if (cond < 0) 63 | return lookup(word, &(*p)->left); 64 | else if (cond > 0) 65 | return lookup(word, &(*p)->right); 66 | else 67 | return *p; 68 | } 69 | if (next >= 2000) 70 | err("out of node storage"); 71 | words[next].count = 0; 72 | words[next].left = words[next].right = 0; 73 | words[next].word = malloc(strlen(word) + 1); 74 | if (words[next].word == 0) 75 | err("out of word storage"); 76 | strcpy(words[next].word, word); 77 | return *p = &words[next++]; 78 | } 79 | 80 | /* tprint - print tree */ 81 | tprint(tree) struct node *tree; { 82 | if (tree) { 83 | tprint(tree->left); 84 | printf("%d\t%s\n", tree->count, tree->word); 85 | tprint(tree->right); 86 | } 87 | } 88 | 89 | /* strcmp - compare s1 and s2, return <0, 0, or >0 */ 90 | int strcmp(s1, s2) char *s1, *s2; { 91 | while (*s1 == *s2) { 92 | if (*s1++ == 0) 93 | return 0; 94 | ++s2; 95 | } 96 | if (*s1 == 0) 97 | return -1; 98 | else if (*s2 == 0) 99 | return 1; 100 | return *s1 - *s2; 101 | } 102 | -------------------------------------------------------------------------------- /cpp/Makefile.def: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Makefile (and Makefile.def) -- Makefile for the LC-3 tools 3 | # 4 | # "Copyright (c) 2003 by Steven S. Lumetta." 5 | # 6 | # Permission to use, copy, modify, and distribute this software and its 7 | # documentation for any purpose, without fee, and without written 8 | # agreement is hereby granted, provided that the above copyright notice 9 | # and the following two paragraphs appear in all copies of this software, 10 | # that the files COPYING and NO_WARRANTY are included verbatim with 11 | # any distribution, and that the contents of the file README are included 12 | # verbatim as part of a file named README with any distribution. 13 | # 14 | # IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, 15 | # INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT 16 | # OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE AUTHOR 17 | # HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 18 | # 19 | # THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 20 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | # A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" 22 | # BASIS, AND THE AUTHOR NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 23 | # UPDATES, ENHANCEMENTS, OR MODIFICATIONS." 24 | # 25 | # Author: Steve Lumetta 26 | # Version: 1 27 | # Creation Date: 18 October 2003 28 | # Filename: Makefile[.def] 29 | # History: 30 | # SSL 2 31 October 2003 31 | # Added lc3convert tool into distribution. 32 | # SSL 1 18 October 2003 33 | # Copyright notices and Gnu Public License marker added. 34 | # 35 | ############################################################################### 36 | 37 | # These path names are automatically set by configure. 38 | GCC = __GCC__ 39 | FLEX = __FLEX__ 40 | EXE = __EXE__ 41 | RM = __RM__ 42 | CP = __CP__ 43 | MKDIR = __MKDIR__ 44 | CHMOD = __CHMOD__ 45 | SED = __SED__ 46 | MAKE = __MAKE__ 47 | AR = __AR__ 48 | RANLIB = __RANLIB__ 49 | INSTALL_DIR = __INSTALL_DIR__ 50 | TOP_DIR = __TOP_DIR__ 51 | # End of configuration block. 52 | 53 | CFLAGS = -g -m32 54 | LDFLAGS = -g -m32 55 | LC3AS = ./lc3as 56 | 57 | %.o: %.c 58 | ${GCC} -c ${CFLAGS} -o $@ $< 59 | 60 | dist: cpp 61 | 62 | distclean:: 63 | ${RM} -f *.o *~ 64 | 65 | distclear: distclean 66 | ${RM} -f cpp${EXE} 67 | 68 | cpp_OBJECTS = cpp.o eval.o getopt.o \ 69 | hideset.o include.o lex.o \ 70 | macro.o nlist.o tokens.o unix.o 71 | 72 | cpp: ${cpp_OBJECTS} 73 | ${GCC} ${CFLAGS} -o $@ $^ 74 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | ------------------------------- 2 | DESCRIPTION OF CONTENTS 3 | ------------------------------- 4 | 5 | This is the preliminary distribution of LCC that supports the LC-3. This 6 | is my first time the auto configuration process, so if it doesn't work for 7 | you, please email me and I will try to see what I can do. The copyright 8 | information is in the file CPYRIGHT. There is absolutely no warranty for 9 | this software. The installation information is in INSTALL. TODO contains 10 | a to-do list. 11 | 12 | ------------------------------- 13 | INSTALLATION INSTRUCTIONS 14 | ------------------------------- 15 | Untar the package with a command like 'tar -xzf lcc-1.1.tar.gz.' 16 | 17 | From the top-level directory type 'configure' 18 | 19 | Now install the lcc/lc3 binaries by typing 'make install' 20 | 21 | If everything goes well, the make process will create a directory off the 22 | top level called "install". It should contain the various binaries needed 23 | by the compiler, along with some informational files, such as this README 24 | file, a sample C file to compile, and a makefile for compiling that file. 25 | 26 | ------------------------------- 27 | HOW TO USE 28 | ------------------------------- 29 | 30 | In the package there is a regressions and limitations test directiory in 31 | topdir/test/limitations and topdir/test/regression. The regression 32 | directory has a small set of files that have been tested to compile 33 | properly and have been assembled and simulated using Steve Lumetta's LC-3 34 | simulator. Many of these examples are taken from the book by Patt and Patel. 35 | 36 | Compiling programs using the compiler is similar to using a standard C 37 | compiler. Behind the scenes, the compiler will (1) compile the .c files 38 | into a set of pseudo-assembly .lcc files, (2) use the lc3pp (lc3 post 39 | processor) to link and massage the .lcc files and library files into a 40 | single .asm file, and (3) use Steve Lumetta's LC-3 assembler to assemble 41 | the .asm into a .obj file. This object file can then be loaded The file 42 | topdir/test/regressions/Makefile provides an example of how the 43 | compilation process works. 44 | 45 | Note: not all C programs will compile to the LC-3. Programs with floating 46 | point types, for example will not currently compile. Also, certain 47 | complex integer expressions will not generate properly because of the 48 | limited LC-3 register set. See topdir/test/limitations for some examples 49 | that do not compile properly. I hope to reduce this set of exceptional 50 | cases over time. 51 | 52 | Ajay Ladsaria 53 | Sanjay J. Patel (sjp@crhc.uiuc.edu) -------------------------------------------------------------------------------- /cpp/hideset.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "cpp.h" 5 | 6 | /* 7 | * A hideset is a null-terminated array of Nlist pointers. 8 | * They are referred to by indices in the hidesets array. 9 | * Hideset 0 is empty. 10 | */ 11 | 12 | #define HSSIZ 32 13 | typedef Nlist **Hideset; 14 | Hideset *hidesets; 15 | int nhidesets = 0; 16 | int maxhidesets = 3; 17 | int inserths(Hideset, Hideset, Nlist *); 18 | 19 | /* 20 | * Test for membership in a hideset 21 | */ 22 | int 23 | checkhideset(int hs, Nlist *np) 24 | { 25 | Hideset hsp; 26 | 27 | if (hs>=nhidesets) 28 | abort(); 29 | for (hsp = hidesets[hs]; *hsp; hsp++) { 30 | if (*hsp == np) 31 | return 1; 32 | } 33 | return 0; 34 | } 35 | 36 | /* 37 | * Return the (possibly new) hideset obtained by adding np to hs. 38 | */ 39 | int 40 | newhideset(int hs, Nlist *np) 41 | { 42 | int i, len; 43 | Nlist *nhs[HSSIZ+3]; 44 | Hideset hs1, hs2; 45 | 46 | len = inserths(nhs, hidesets[hs], np); 47 | for (i=0; i=HSSIZ) 53 | return hs; 54 | if (nhidesets >= maxhidesets) { 55 | maxhidesets = 3*maxhidesets/2+1; 56 | hidesets = (Hideset *)realloc(hidesets, (sizeof (Hideset *))*maxhidesets); 57 | if (hidesets == NULL) 58 | error(FATAL, "Out of memory from realloc"); 59 | } 60 | hs1 = (Hideset)domalloc(len*sizeof *hs1); 61 | memmove(hs1, nhs, len*sizeof *hs1); 62 | hidesets[nhidesets] = hs1; 63 | return nhidesets++; 64 | } 65 | 66 | int 67 | inserths(Hideset dhs, Hideset shs, Nlist *np) 68 | { 69 | Hideset odhs = dhs; 70 | 71 | while (*shs && *shs < np) 72 | *dhs++ = *shs++; 73 | if (*shs != np) 74 | *dhs++ = np; 75 | do { 76 | *dhs++ = *shs; 77 | } while (*shs++); 78 | return dhs - odhs; 79 | } 80 | 81 | /* 82 | * Hideset union 83 | */ 84 | int 85 | unionhideset(int hs1, int hs2) 86 | { 87 | Hideset hp; 88 | 89 | for (hp = hidesets[hs2]; *hp; hp++) 90 | hs1 = newhideset(hs1, *hp); 91 | return hs1; 92 | } 93 | 94 | void 95 | iniths(void) 96 | { 97 | hidesets = (Hideset *)domalloc(maxhidesets*sizeof(Hideset *)); 98 | hidesets[0] = (Hideset)domalloc(sizeof *hidesets[0]); 99 | *hidesets[0] = NULL; 100 | nhidesets++; 101 | } 102 | 103 | void 104 | prhideset(int hs) 105 | { 106 | Hideset np; 107 | 108 | for (np = hidesets[hs]; *np; np++) { 109 | fprintf(stderr, (char*)(*np)->name, (*np)->len); 110 | fprintf(stderr, " "); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /cpp/nlist.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "cpp.h" 5 | 6 | extern int getopt(int, char *const *, const char *); 7 | extern char *optarg; 8 | extern int optind; 9 | extern int verbose; 10 | extern int Cplusplus; 11 | Nlist *kwdefined; 12 | 13 | #define NLSIZE 128 14 | 15 | static Nlist *nlist[NLSIZE]; 16 | 17 | struct kwtab { 18 | char *kw; 19 | int val; 20 | int flag; 21 | } kwtab[] = { 22 | "if", KIF, ISKW, 23 | "ifdef", KIFDEF, ISKW, 24 | "ifndef", KIFNDEF, ISKW, 25 | "elif", KELIF, ISKW, 26 | "else", KELSE, ISKW, 27 | "endif", KENDIF, ISKW, 28 | "include", KINCLUDE, ISKW, 29 | "define", KDEFINE, ISKW, 30 | "undef", KUNDEF, ISKW, 31 | "line", KLINE, ISKW, 32 | "error", KERROR, ISKW, 33 | "pragma", KPRAGMA, ISKW, 34 | "eval", KEVAL, ISKW, 35 | "defined", KDEFINED, ISDEFINED+ISUNCHANGE, 36 | "ident", KPRAGMA, ISKW, /* treat like pragma (ignored) */ 37 | "__LINE__", KLINENO, ISMAC+ISUNCHANGE, 38 | "__FILE__", KFILE, ISMAC+ISUNCHANGE, 39 | "__DATE__", KDATE, ISMAC+ISUNCHANGE, 40 | "__TIME__", KTIME, ISMAC+ISUNCHANGE, 41 | "__STDC__", KSTDC, ISUNCHANGE, 42 | NULL 43 | }; 44 | 45 | unsigned long namebit[077+1]; 46 | Nlist *np; 47 | 48 | void 49 | setup_kwtab(void) 50 | { 51 | struct kwtab *kp; 52 | Nlist *np; 53 | Token t; 54 | static Token deftoken[1] = {{ NAME, 0, 0, 0, 7, (uchar*)"defined" }}; 55 | static Tokenrow deftr = { deftoken, deftoken, deftoken+1, 1 }; 56 | 57 | for (kp=kwtab; kp->kw; kp++) { 58 | t.t = (uchar*)kp->kw; 59 | t.len = strlen(kp->kw); 60 | np = lookup(&t, 1); 61 | np->flag = kp->flag; 62 | np->val = kp->val; 63 | if (np->val == KDEFINED) { 64 | kwdefined = np; 65 | np->val = NAME; 66 | np->vp = &deftr; 67 | np->ap = 0; 68 | } 69 | } 70 | } 71 | 72 | Nlist * 73 | lookup(Token *tp, int install) 74 | { 75 | unsigned int h; 76 | Nlist *np; 77 | uchar *cp, *cpe; 78 | 79 | h = 0; 80 | for (cp=tp->t, cpe=cp+tp->len; cpt==*np->name && tp->len==np->len 86 | && strncmp((char*)tp->t, (char*)np->name, tp->len)==0) 87 | return np; 88 | np = np->next; 89 | } 90 | if (install) { 91 | np = new(Nlist); 92 | np->vp = NULL; 93 | np->ap = NULL; 94 | np->flag = 0; 95 | np->val = 0; 96 | np->len = tp->len; 97 | np->name = newstring(tp->t, tp->len, 0); 98 | np->next = nlist[h]; 99 | nlist[h] = np; 100 | quickset(tp->t[0], tp->len>1? tp->t[1]:0); 101 | return np; 102 | } 103 | return NULL; 104 | } 105 | -------------------------------------------------------------------------------- /src/ops.h: -------------------------------------------------------------------------------- 1 | /* $Id: ops.h,v 1.1.1.1 2004/03/24 04:37:33 sjp Exp $ */ 2 | 3 | gop(CNST,1) 4 | op(CNST,F,fdx) 5 | op(CNST,I,csilh) 6 | op(CNST,P,p) 7 | op(CNST,U,csilh) 8 | gop(ARG,2) 9 | op(ARG,B,-) 10 | op(ARG,F,fdx) 11 | op(ARG,I,ilh) 12 | op(ARG,P,p) 13 | op(ARG,U,ilh) 14 | gop(ASGN,3) 15 | op(ASGN,B,-) 16 | op(ASGN,F,fdx) 17 | op(ASGN,I,csilh) 18 | op(ASGN,P,p) 19 | op(ASGN,U,csilh) 20 | gop(INDIR,4) 21 | op(INDIR,B,-) 22 | op(INDIR,F,fdx) 23 | op(INDIR,I,csilh) 24 | op(INDIR,P,p) 25 | op(INDIR,U,csilh) 26 | gop(CVF,7) 27 | op(CVF,F,fdx) 28 | op(CVF,I,ilh) 29 | gop(CVI,8) 30 | op(CVI,F,fdx) 31 | op(CVI,I,csilh) 32 | op(CVI,U,csilhp) 33 | gop(CVP,9) 34 | op(CVP,U,p) 35 | gop(CVU,11) 36 | op(CVU,I,csilh) 37 | op(CVU,P,p) 38 | op(CVU,U,csilh) 39 | gop(NEG,12) 40 | op(NEG,F,fdx) 41 | op(NEG,I,ilh) 42 | gop(CALL,13) 43 | op(CALL,B,-) 44 | op(CALL,F,fdx) 45 | op(CALL,I,ilh) 46 | op(CALL,P,p) 47 | op(CALL,U,ilh) 48 | op(CALL,V,-) 49 | gop(RET,15) 50 | op(RET,F,fdx) 51 | op(RET,I,ilh) 52 | op(RET,P,p) 53 | op(RET,U,ilh) 54 | op(RET,V,-) 55 | gop(ADDRG,16) 56 | op(ADDRG,P,p) 57 | gop(ADDRF,17) 58 | op(ADDRF,P,p) 59 | gop(ADDRL,18) 60 | op(ADDRL,P,p) 61 | gop(ADD,19) 62 | op(ADD,F,fdx) 63 | op(ADD,I,ilh) 64 | op(ADD,P,p) 65 | op(ADD,U,ilhp) 66 | gop(SUB,20) 67 | op(SUB,F,fdx) 68 | op(SUB,I,ilh) 69 | op(SUB,P,p) 70 | op(SUB,U,ilhp) 71 | gop(LSH,21) 72 | op(LSH,I,ilh) 73 | op(LSH,U,ilh) 74 | gop(MOD,22) 75 | op(MOD,I,ilh) 76 | op(MOD,U,ilh) 77 | gop(RSH,23) 78 | op(RSH,I,ilh) 79 | op(RSH,U,ilh) 80 | gop(BAND,24) 81 | op(BAND,I,ilh) 82 | op(BAND,U,ilh) 83 | gop(BCOM,25) 84 | op(BCOM,I,ilh) 85 | op(BCOM,U,ilh) 86 | gop(BOR,26) 87 | op(BOR,I,ilh) 88 | op(BOR,U,ilh) 89 | gop(BXOR,27) 90 | op(BXOR,I,ilh) 91 | op(BXOR,U,ilh) 92 | gop(DIV,28) 93 | op(DIV,F,fdx) 94 | op(DIV,I,ilh) 95 | op(DIV,U,ilh) 96 | gop(MUL,29) 97 | op(MUL,F,fdx) 98 | op(MUL,I,ilh) 99 | op(MUL,U,ilh) 100 | gop(EQ,30) 101 | op(EQ,F,fdx) 102 | op(EQ,I,ilh) 103 | op(EQ,U,ilhp) 104 | gop(GE,31) 105 | op(GE,F,fdx) 106 | op(GE,I,ilh) 107 | op(GE,U,ilhp) 108 | gop(GT,32) 109 | op(GT,F,fdx) 110 | op(GT,I,ilh) 111 | op(GT,U,ilhp) 112 | gop(LE,33) 113 | op(LE,F,fdx) 114 | op(LE,I,ilh) 115 | op(LE,U,ilhp) 116 | gop(LT,34) 117 | op(LT,F,fdx) 118 | op(LT,I,ilh) 119 | op(LT,U,ilhp) 120 | gop(NE,35) 121 | op(NE,F,fdx) 122 | op(NE,I,ilh) 123 | op(NE,U,ilhp) 124 | gop(JUMP,36) 125 | op(JUMP,V,-) 126 | gop(LABEL,37) 127 | op(LABEL,V,-) 128 | gop(LOAD,14) 129 | op(LOAD,B,-) 130 | op(LOAD,F,fdx) 131 | op(LOAD,I,csilh) 132 | op(LOAD,P,p) 133 | op(LOAD,U,csilhp) 134 | -------------------------------------------------------------------------------- /cpp/unix.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "cpp.h" 6 | 7 | /* fix for newer Mac environments. sws, dartmouth, april 2011 */ 8 | #ifdef memmove 9 | #undef memmove 10 | #endif 11 | 12 | 13 | extern int getopt(int, char *const *, const char *); 14 | extern char *optarg, rcsid[]; 15 | extern int optind; 16 | int verbose; 17 | int Mflag; /* only print active include files */ 18 | char *objname; /* "src.$O: " */ 19 | int Cplusplus = 1; 20 | 21 | void 22 | setup(int argc, char **argv) 23 | { 24 | int c, i; 25 | FILE *fd; 26 | char *fp, *dp; 27 | Tokenrow tr; 28 | extern void setup_kwtab(void); 29 | 30 | setup_kwtab(); 31 | while ((c = getopt(argc, argv, "MNOVv+I:D:U:F:lg")) != -1) 32 | switch (c) { 33 | case 'N': 34 | for (i=0; i=0; i--) { 40 | if (includelist[i].file==NULL) { 41 | includelist[i].always = 1; 42 | includelist[i].file = optarg; 43 | break; 44 | } 45 | } 46 | if (i<0) 47 | error(FATAL, "Too many -I directives"); 48 | break; 49 | case 'D': 50 | case 'U': 51 | setsource("", NULL, optarg); 52 | maketokenrow(3, &tr); 53 | gettokens(&tr, 1); 54 | doadefine(&tr, c); 55 | unsetsource(); 56 | break; 57 | case 'M': 58 | Mflag++; 59 | break; 60 | case 'v': 61 | fprintf(stderr, "%s %s\n", argv[0], rcsid); 62 | break; 63 | case 'V': 64 | verbose++; 65 | break; 66 | case '+': 67 | Cplusplus++; 68 | break; 69 | default: 70 | break; 71 | } 72 | dp = "."; 73 | fp = ""; 74 | fd = stdin; 75 | if (optind 2 | #include 3 | #include 4 | #include "cpp.h" 5 | 6 | Includelist includelist[NINCLUDE]; 7 | 8 | extern char *objname; 9 | 10 | void 11 | doinclude(Tokenrow *trp) 12 | { 13 | char fname[256], iname[256]; 14 | Includelist *ip; 15 | int angled, len, i; 16 | FILE *fd; 17 | 18 | trp->tp += 1; 19 | if (trp->tp>=trp->lp) 20 | goto syntax; 21 | if (trp->tp->type!=STRING && trp->tp->type!=LT) { 22 | len = trp->tp - trp->bp; 23 | expandrow(trp, ""); 24 | trp->tp = trp->bp+len; 25 | } 26 | if (trp->tp->type==STRING) { 27 | len = trp->tp->len-2; 28 | if (len > sizeof(fname) - 1) 29 | len = sizeof(fname) - 1; 30 | strncpy(fname, (char*)trp->tp->t+1, len); 31 | angled = 0; 32 | } else if (trp->tp->type==LT) { 33 | len = 0; 34 | trp->tp++; 35 | while (trp->tp->type!=GT) { 36 | if (trp->tp>trp->lp || len+trp->tp->len+2 >= sizeof(fname)) 37 | goto syntax; 38 | strncpy(fname+len, (char*)trp->tp->t, trp->tp->len); 39 | len += trp->tp->len; 40 | trp->tp++; 41 | } 42 | angled = 1; 43 | } else 44 | goto syntax; 45 | trp->tp += 2; 46 | if (trp->tp < trp->lp || len==0) 47 | goto syntax; 48 | fname[len] = '\0'; 49 | if (fname[0]=='/') { 50 | fd = fopen(fname, "r"); 51 | strcpy(iname, fname); 52 | } else for (fd = NULL,i=NINCLUDE-1; i>=0; i--) { 53 | ip = &includelist[i]; 54 | if (ip->file==NULL || ip->deleted || (angled && ip->always==0)) 55 | continue; 56 | if (strlen(fname)+strlen(ip->file)+2 > sizeof(iname)) 57 | continue; 58 | strcpy(iname, ip->file); 59 | strcat(iname, "/"); 60 | strcat(iname, fname); 61 | if ((fd = fopen(iname, "r")) != NULL) 62 | break; 63 | } 64 | if ( Mflag>1 || !angled&&Mflag==1 ) { 65 | fwrite(objname,1,strlen(objname),stdout); 66 | fwrite(iname,1,strlen(iname),stdout); 67 | fwrite("\n",1,1,stdout); 68 | } 69 | if (fd != NULL) { 70 | if (++incdepth > 10) 71 | error(FATAL, "#include too deeply nested"); 72 | setsource((char*)newstring((uchar*)iname, strlen(iname), 0), fd, NULL); 73 | genline(); 74 | } else { 75 | trp->tp = trp->bp+2; 76 | error(ERROR, "Could not find include file %r", trp); 77 | } 78 | return; 79 | syntax: 80 | error(ERROR, "Syntax error in #include"); 81 | return; 82 | } 83 | 84 | /* 85 | * Generate a line directive for cursource 86 | */ 87 | void 88 | genline(void) 89 | { 90 | static Token ta = { UNCLASS }; 91 | static Tokenrow tr = { &ta, &ta, &ta+1, 1 }; 92 | uchar *p; 93 | 94 | ta.t = p = (uchar*)outp; 95 | strcpy((char*)p, "#line "); 96 | p += sizeof("#line ")-1; 97 | p = (uchar*)outnum((char*)p, cursource->line); 98 | *p++ = ' '; *p++ = '"'; 99 | strcpy((char*)p, cursource->filename); 100 | p += strlen((char*)p); 101 | *p++ = '"'; *p++ = '\n'; 102 | ta.len = (char*)p-outp; 103 | outp = (char*)p; 104 | tr.tp = tr.bp; 105 | puttokens(&tr); 106 | } 107 | 108 | void 109 | setobjname(char *f) 110 | { 111 | int n = strlen(f); 112 | objname = (char*)domalloc(n+5); 113 | strcpy(objname,f); 114 | if(objname[n-2]=='.'){ 115 | strcpy(objname+n-1,"$O: "); 116 | }else{ 117 | strcpy(objname+n,"$O: "); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /test/limitations/printf.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 4 | ; void printf(const char *format, ...) 5 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 6 | LC3_GFLAG printf LC3_GFLAG .FILL lc3_printf 7 | 8 | PRINTF_PERCENT .FILL -37 9 | PRINTF_C .FILL -99 10 | PRINTF_D .FILL -100 11 | PRINTF_S .FILL -115 12 | PRINTF_0 .FILL 48 ;postive ascii value of '0' 13 | PRINTF_MINUS .FILL 45 14 | PRINTF_BUF .BLKW 7 15 | 16 | 17 | lc3_printf 18 | ADD R6, R6, #-2 19 | STR R7, R6, #0 ;return address 20 | ADD R6, R6, #-1 21 | STR R5, R6, #0 22 | ADD R5, R6, #-1 23 | 24 | ADD R6, R6, #-1 25 | STR R4, R6, #0 26 | 27 | ADD R5, R5, #4 ;cheating with the bp (no longer bp) 28 | LDR R4, R5, #0 ;got addr of format string 29 | 30 | 31 | PRINTF_LOOP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 32 | 33 | LDR R0, R4, #0 34 | 35 | ADD R0, R0, #0 ;End of string? (0x0000) 36 | BRz PRINTF_DONE 37 | 38 | ADD R2, R0, #0 39 | LD R1, PRINTF_PERCENT 40 | ADD R2, R2, R1 41 | BRnp PRINTF_CHAR 42 | 43 | ADD R4, R4, #1 44 | LDR R0, R4, #0 45 | ;is it %c? 46 | ADD R2, R0, #0 47 | LD R3, PRINTF_C 48 | ADD R2, R2, R3 49 | BRnp PRINTF_CHECKSTR 50 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%c 51 | ADD R5, R5, #1 52 | LDR R0, R5, #0 53 | 54 | PRINTF_CHAR 55 | OUT 56 | 57 | ADD R4, R4, #1 58 | BRnzp PRINTF_LOOP 59 | 60 | PRINTF_CHECKSTR 61 | ;is it %s? 62 | ADD R2, R0, #0 63 | LD R7, PRINTF_S 64 | ADD R2, R2, R7 65 | BRnp PRINTF_CHECKDEC 66 | 67 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%s 68 | 69 | ADD R5, R5, #1 70 | LDR R0, R5, #0 71 | PUTS 72 | 73 | ADD R4, R4, #1 74 | BRnzp PRINTF_LOOP 75 | 76 | PRINTF_CHECKDEC 77 | ;is it %s? 78 | ADD R2, R0, #0 79 | LD R7, PRINTF_D 80 | ADD R2, R2, R7 81 | BRnp PRINTF_ERROR 82 | 83 | 84 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%d 85 | 86 | LEA R7, PRINTF_BUF 87 | ADD R7, R7, #5 88 | 89 | AND R2, R2, #0 90 | ADD R2, R2, #-10 ;going to divide by 10 by using sub loop 91 | 92 | ADD R5, R5, #1 ;acquire the binary number 93 | LDR R0, R5, #0 94 | 95 | ADD R0, R0, #0 96 | BRzp PRINTF_DECPOS 97 | 98 | NOT R0, R0 ;make num positive for sub loop 99 | ADD R0, R0, #1 100 | 101 | PRINTF_DECPOS 102 | 103 | AND R3, R3, #0 104 | ADD R3, R3, #-1 105 | 106 | PRINTF_DIVLOOP 107 | ADD R3, R3, #1 ;num/10 108 | ADD R0, R0, R2 ;R0 = num % 10 - 10 109 | BRzp PRINTF_DIVLOOP 110 | 111 | ADD R3, R3, #0 112 | BRz PRINTF_LASTDIGIT 113 | 114 | LD R1, PRINTF_0 115 | ADD R1, R1, R0 116 | ADD R1, R1, #10 117 | STR R1, R7, #0 118 | ADD R7, R7, #-1 ;stored ascii value of one digit 119 | 120 | ADD R0, R3, #0 ;num/10 121 | 122 | BRnzp PRINTF_DECPOS 123 | 124 | PRINTF_LASTDIGIT 125 | 126 | LD R1, PRINTF_0 127 | ADD R1, R1, R0 128 | ADD R1, R1, #10 129 | STR R1, R7, #0 ;stored ascii value of highest order digit 130 | 131 | LDR R0, R5, #0 132 | ADD R0, R0, #0 133 | BRzp PRINTF_DECSTRING 134 | 135 | LD R0, PRINTF_MINUS ;num was negative 136 | ADD R7, R7, #-1 137 | STR R0, R7, #0 ;stored ascii value negative sign 138 | 139 | PRINTF_DECSTRING ;print the calculated string 140 | ADD R0, R7, #0 141 | PUTS 142 | 143 | ADD R4, R4, #1 144 | BRnzp PRINTF_LOOP 145 | 146 | PRINTF_ERROR 147 | PRINTF_DONE 148 | 149 | LDR R4, R6, #0 ;restore R4 150 | ADD R6, R6, #1 151 | 152 | LDR R5, R6, #0 ;restore bp 153 | ADD R6, R6, #1 154 | 155 | LDR R7, R6, #0 ;restore ret addr 156 | ADD R6, R6, #1 157 | 158 | RET 159 | -------------------------------------------------------------------------------- /test/regression/switch.c: -------------------------------------------------------------------------------- 1 | main() 2 | { 3 | int i; char *s; 4 | 5 | for (s = "bfnrtvx"; *s; s++) 6 | printf("%c = 0x%x\n", *s, backslash(*s)); 7 | f(); 8 | g(); 9 | h(); 10 | for (i = 0x1000; i&0x7000; i += 0x1000) 11 | big(i); 12 | limit(); 13 | return 0; 14 | } 15 | 16 | backslash(c) 17 | { 18 | switch (c) { 19 | case 'b': 20 | return '\b'; 21 | case 'f': 22 | return '\f'; 23 | case 'n': 24 | return '\n'; 25 | case 'r': 26 | return '\r'; 27 | case 't': 28 | return '\t'; 29 | case 'v': 30 | return '\v'; 31 | } 32 | return c; 33 | } 34 | 35 | f() { 36 | int i, x = 0, y; 37 | 38 | printf("f:\n"); 39 | for (i = 0; i <= 20; i++) { 40 | y = i; 41 | switch (i) { 42 | case 1: x = i; break; 43 | case 2: x = i; break; 44 | case 7: x = i; break; 45 | case 8: x = i; break; 46 | case 9: x = i; break; 47 | case 16: x = i; break; 48 | case 17: x = i; break; 49 | case 18: x = i; break; 50 | case 19: x = i; break; 51 | case 20: x = i; break; 52 | } 53 | printf("x = %d\n", x); 54 | } 55 | } 56 | 57 | g() { 58 | int i; 59 | 60 | printf("g:\n"); 61 | for (i = 1; i <= 10; i++) 62 | switch (i) { 63 | case 1: case 2: printf("1 %d\n", i); break; 64 | case 3: case 4: case 5: printf("2 %d\n", i); break; 65 | case 6: case 7: case 8: printf("3 %d\n", i); 66 | default: 67 | printf("d %d\n", i); break; 68 | case 1001: case 1002: case 1003: case 1004: 69 | printf("5 %d\n", i); break; 70 | case 3001: case 3002: case 3003: case 3004: 71 | printf("6 %d\n", i); break; 72 | } 73 | } 74 | 75 | h() 76 | { 77 | int i, n=0; 78 | 79 | printf("h:\n"); 80 | for (i = 1; i <= 500; i++) 81 | switch (i) { 82 | default: n++; continue; 83 | case 128: printf("i = %d\n", i); break; 84 | case 16: printf("i = %d\n", i); break; 85 | case 8: printf("i = %d\n", i); break; 86 | case 120: printf("i = %d\n", i); break; 87 | case 280: printf("i = %d\n", i); break; 88 | case 264: printf("i = %d\n", i); break; 89 | case 248: printf("i = %d\n", i); break; 90 | case 272: printf("i = %d\n", i); break; 91 | case 304: printf("i = %d\n", i); break; 92 | case 296: printf("i = %d\n", i); break; 93 | case 288: printf("i = %d\n", i); break; 94 | case 312: printf("i = %d\n", i); break; 95 | } 96 | printf("%d defaults\n", n); 97 | } 98 | 99 | big(x) int x; { 100 | switch(x&0x6000){ 101 | case -1: 102 | case -2: 103 | case 0x0000: 104 | printf("x = 0x%d\n", x); break; 105 | case 0x2000: 106 | printf("x = 0x%d\n", x); break; 107 | case 0x4000: 108 | printf("x = 0x%d\n", x); break; 109 | default: 110 | printf("x = 0x%d (default)\n", x); break; 111 | } 112 | } 113 | 114 | #define INT_MIN -32000 115 | #define INT_MAX 32000 116 | 117 | limit() { 118 | int i; 119 | 120 | for (i = INT_MIN; i <= INT_MIN+5; i++) 121 | switch (i) { 122 | case INT_MIN: printf("0\n"); break; 123 | case INT_MIN+1: printf("1\n"); break; 124 | case INT_MIN+2: printf("2\n"); break; 125 | case INT_MIN+3: printf("3\n"); break; 126 | case INT_MIN+4: printf("4\n"); break; 127 | default: printf("5\n"); break; 128 | } 129 | for (i = INT_MAX; i >= INT_MAX-5; i--) 130 | switch (i) { 131 | case INT_MAX: printf("0\n"); break; 132 | case INT_MAX-1: printf("1\n"); break; 133 | case INT_MAX-2: printf("2\n"); break; 134 | case INT_MAX-3: printf("3\n"); break; 135 | case INT_MAX-4: printf("4\n"); break; 136 | default: printf("5\n"); break; 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/error.c: -------------------------------------------------------------------------------- 1 | #include "c.h" 2 | 3 | static char rcsid[] = "$Id: error.c,v 1.1.1.1 2004/03/24 04:37:33 sjp Exp $"; 4 | 5 | static void printtoken(void); 6 | int errcnt = 0; 7 | int errlimit = 20; 8 | char kind[] = { 9 | #define xx(a,b,c,d,e,f,g) f, 10 | #define yy(a,b,c,d,e,f,g) f, 11 | #include "token.h" 12 | }; 13 | int wflag; /* != 0 to suppress warning messages */ 14 | 15 | void test(int tok, char set[]) { 16 | if (t == tok) 17 | t = gettok(); 18 | else { 19 | expect(tok); 20 | skipto(tok, set); 21 | if (t == tok) 22 | t = gettok(); 23 | } 24 | } 25 | void expect(int tok) { 26 | if (t == tok) 27 | t = gettok(); 28 | else { 29 | error("syntax error; found"); 30 | printtoken(); 31 | fprint(stderr, " expecting `%k'\n", tok); 32 | } 33 | } 34 | void error(const char *fmt, ...) { 35 | va_list ap; 36 | 37 | if (errcnt++ >= errlimit) { 38 | errcnt = -1; 39 | error("too many errors\n"); 40 | exit(1); 41 | } 42 | va_start(ap, fmt); 43 | if (firstfile != file && firstfile && *firstfile) 44 | fprint(stderr, "%s: ", firstfile); 45 | fprint(stderr, "%w: ", &src); 46 | vfprint(stderr, NULL, fmt, ap); 47 | va_end(ap); 48 | } 49 | 50 | void skipto(int tok, char set[]) { 51 | int n; 52 | char *s; 53 | 54 | assert(set); 55 | for (n = 0; t != EOI && t != tok; t = gettok()) { 56 | for (s = set; *s && kind[t] != *s; s++) 57 | ; 58 | if (kind[t] == *s) 59 | break; 60 | if (n++ == 0) 61 | error("skipping"); 62 | if (n <= 8) 63 | printtoken(); 64 | else if (n == 9) 65 | fprint(stderr, " ..."); 66 | } 67 | if (n > 8) { 68 | fprint(stderr, " up to"); 69 | printtoken(); 70 | } 71 | if (n > 0) 72 | fprint(stderr, "\n"); 73 | } 74 | /* fatal - issue fatal error message and exit */ 75 | int fatal(const char *name, const char *fmt, int n) { 76 | print("\n"); 77 | errcnt = -1; 78 | error("compiler error in %s--", name); 79 | fprint(stderr, fmt, n); 80 | exit(EXIT_FAILURE); 81 | return 0; 82 | } 83 | 84 | /* printtoken - print current token preceeded by a space */ 85 | static void printtoken(void) { 86 | switch (t) { 87 | case ID: fprint(stderr, " `%s'", token); break; 88 | case ICON: 89 | fprint(stderr, " `%s'", vtoa(tsym->type, tsym->u.c.v)); 90 | break; 91 | case SCON: { 92 | int i, n; 93 | if (ischar(tsym->type->type)) { 94 | char *s = tsym->u.c.v.p; 95 | n = tsym->type->size; 96 | fprint(stderr, " \""); 97 | for (i = 0; i < 20 && i < n && *s; s++, i++) 98 | if (*s < ' ' || *s >= 0177) 99 | fprint(stderr, "\\%o", *s); 100 | else 101 | fprint(stderr, "%c", *s); 102 | } else { /* wchar_t string */ 103 | unsigned int *s = tsym->u.c.v.p; 104 | assert(tsym->type->type->size == widechar->size); 105 | n = tsym->type->size/widechar->size; 106 | fprint(stderr, " L\""); 107 | for (i = 0; i < 20 && i < n && *s; s++, i++) 108 | if (*s < ' ' || *s >= 0177) 109 | fprint(stderr, "\\x%x", *s); 110 | else 111 | fprint(stderr, "%c", *s); 112 | } 113 | if (i < n) 114 | fprint(stderr, " ..."); 115 | else 116 | fprint(stderr, "\""); 117 | break; 118 | } 119 | case FCON: 120 | fprint(stderr, " `%S'", token, (char*)cp - token); 121 | break; 122 | case '`': case '\'': fprint(stderr, " \"%k\"", t); break; 123 | default: fprint(stderr, " `%k'", t); 124 | } 125 | } 126 | 127 | /* warning - issue warning error message */ 128 | void warning(const char *fmt, ...) { 129 | va_list ap; 130 | 131 | va_start(ap, fmt); 132 | if (wflag == 0) { 133 | errcnt--; 134 | error("warning: "); 135 | vfprint(stderr, NULL, fmt, ap); 136 | } 137 | va_end(ap); 138 | } 139 | -------------------------------------------------------------------------------- /src/Makefile.def: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Makefile (and Makefile.def) -- Makefile for the LC-3 tools 3 | # 4 | # "Copyright (c) 2003 by Steven S. Lumetta." 5 | # 6 | # Permission to use, copy, modify, and distribute this software and its 7 | # documentation for any purpose, without fee, and without written 8 | # agreement is hereby granted, provided that the above copyright notice 9 | # and the following two paragraphs appear in all copies of this software, 10 | # that the files COPYING and NO_WARRANTY are included verbatim with 11 | # any distribution, and that the contents of the file README are included 12 | # verbatim as part of a file named README with any distribution. 13 | # 14 | # IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, 15 | # INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT 16 | # OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE AUTHOR 17 | # HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 18 | # 19 | # THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 20 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | # A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" 22 | # BASIS, AND THE AUTHOR NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 23 | # UPDATES, ENHANCEMENTS, OR MODIFICATIONS." 24 | # 25 | # Author: Steve Lumetta 26 | # Version: 1 27 | # Creation Date: 18 October 2003 28 | # Filename: Makefile[.def] 29 | # History: 30 | # SSL 2 31 October 2003 31 | # Added lc3convert tool into distribution. 32 | # SSL 1 18 October 2003 33 | # Copyright notices and Gnu Public License marker added. 34 | # 35 | ############################################################################### 36 | 37 | # These path names are automatically set by configure. 38 | GCC = __GCC__ 39 | FLEX = __FLEX__ 40 | EXE = __EXE__ 41 | RM = __RM__ 42 | CP = __CP__ 43 | MKDIR = __MKDIR__ 44 | CHMOD = __CHMOD__ 45 | SED = __SED__ 46 | MAKE = __MAKE__ 47 | AR = __AR__ 48 | RANLIB = __RANLIB__ 49 | INSTALL_DIR = __INSTALL_DIR__ 50 | TOP_DIR = __TOP_DIR__ 51 | # End of configuration block. 52 | 53 | CFLAGS = -g -m32 -mno-sse 54 | LDFLAGS = -g -m32 -mno-sse 55 | LC3AS = ./lc3as 56 | 57 | librcc_OBJECTS = alloc.o bind.o dag.o dagcheck.o decl.o \ 58 | enode.o error.o expr.o event.o \ 59 | init.o inits.o input.o lex.o list.o \ 60 | main.o output.o prof.o profio.o simp.o stmt.o \ 61 | string.o sym.o \ 62 | trace.o tree.o types.o null.o symbolic.o gen.o \ 63 | bytecode.o alpha.o mips.o lc3.o sparc.o stab.o \ 64 | x86.o x86linux.o 65 | 66 | %.o: %.c 67 | ${GCC} -c ${CFLAGS} -o $@ $< 68 | 69 | dist: lburg rcc 70 | 71 | distclean:: 72 | ${RM} -f *.o *~ 73 | cd ${TOP_DIR}/lburg && ${MAKE} distclear 74 | 75 | distclear: distclean 76 | ${RM} -f rcc${EXE} librcc.a 77 | cd ${TOP_DIR}/lburg && ${MAKE} distclean 78 | 79 | lburg: 80 | cd ${TOP_DIR}/lburg && ${MAKE} dist 81 | 82 | rcc: main.o librcc.a 83 | ${GCC} ${CFLAGS} -o $@ $^ 84 | 85 | librcc.a: ${librcc_OBJECTS} 86 | -rm -f librcc.a 87 | ${AR} cru librcc.a ${librcc_OBJECTS} 88 | ${RANLIB} librcc.a 89 | 90 | dagcheck.c: dagcheck.md 91 | ${TOP_DIR}/lburg/lburg dagcheck.md dagcheck.c 92 | 93 | alpha.c: alpha.md 94 | ${TOP_DIR}/lburg/lburg alpha.md alpha.c 95 | 96 | sparc.c: sparc.md 97 | ${TOP_DIR}/lburg/lburg sparc.md sparc.c 98 | 99 | mips.c: mips.md 100 | ${TOP_DIR}/lburg/lburg mips.md mips.c 101 | 102 | x86.c: x86.md 103 | ${TOP_DIR}/lburg/lburg x86.md x86.c 104 | 105 | x86linux.c: x86linux.md 106 | ${TOP_DIR}/lburg/lburg x86linux.md x86linux.c 107 | 108 | lc3.c: lc3.md 109 | ${TOP_DIR}/lburg/lburg lc3.md lc3.c 110 | -------------------------------------------------------------------------------- /lib/bbexit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #ifndef EXPORT 4 | #define EXPORT 5 | #endif 6 | 7 | static char rcsid[] = "$Id: bbexit.c,v 1.1.1.1 2004/03/24 04:37:35 sjp Exp $"; 8 | 9 | EXPORT struct callsite { 10 | char *file, *name; 11 | union coordinate { 12 | struct { unsigned int index:6,x:10,y:16; } be; 13 | struct { unsigned int y:16,x:10,index:6; } le; 14 | unsigned int coord; 15 | } u; 16 | } *_caller, **_callerp = &_caller; 17 | 18 | EXPORT void _setcallerp(struct callsite **p) { 19 | _callerp = p; 20 | } 21 | 22 | static struct _bbdata { 23 | struct _bbdata *link; 24 | int npoints, *counts; 25 | union coordinate *coords; 26 | char **files; 27 | struct func { 28 | struct func *link; 29 | struct caller { 30 | struct caller *link; 31 | struct callsite *caller; 32 | int count; 33 | } *callers; 34 | char *name; 35 | union coordinate src; 36 | } *funcs; 37 | } tail, *_bblist = &tail; 38 | 39 | static void unpack(unsigned int coord, int *index, int *x, int *y) { 40 | static union { int x; char endian; } little = { 1 }; 41 | union coordinate u; 42 | 43 | u.coord = coord; 44 | if (little.endian) { 45 | *index = u.le.index; 46 | *x = u.le.x; 47 | *y = u.le.y; 48 | } else { 49 | *index = u.be.index; 50 | *x = u.be.x; 51 | *y = u.be.y; 52 | } 53 | } 54 | 55 | static void profout(struct _bbdata *p, FILE *fp) { 56 | int i, index, x, y; 57 | struct func *f; 58 | struct caller *q; 59 | 60 | for (i = 0; p->files[i]; i++) 61 | ; 62 | fprintf(fp, "%d\n", i); 63 | for (i = 0; p->files[i]; i++) 64 | fprintf(fp, "%s\n", p->files[i]); 65 | for (i = 0, f = p->funcs; f; i++, f = f->link) 66 | if (q = f->callers) 67 | for (i--; q; q = q->link) 68 | i++; 69 | fprintf(fp, "%d\n", i); 70 | for (f = p->funcs; f; f = f->link) { 71 | int n = 0; 72 | for (q = f->callers; q; n += q->count, q = q->link) { 73 | unpack(f->src.coord, &index, &x, &y); 74 | fprintf(fp, "%s %d %d %d %d", f->name, index, x, y, q->count); 75 | if (q->caller) { 76 | unpack(q->caller->u.coord, &index, &x, &y); 77 | fprintf(fp, " %s %s %d %d\n", q->caller->name, q->caller->file, x, y); 78 | } else 79 | fprintf(fp, " ? ? 0 0\n"); 80 | } 81 | if (n == 0) { 82 | unpack(f->src.coord, &index, &x, &y); 83 | fprintf(fp, "%s %d %d %d 0 ? ? 0 0\n", f->name, index, x, y); 84 | } 85 | } 86 | fprintf(fp, "%d\n", p->npoints); 87 | for (i = 0; i < p->npoints; i++) { 88 | unpack(p->coords[i].coord, &index, &x, &y); 89 | fprintf(fp, "%d %d %d %d\n", index, x, y, p->counts[i]); 90 | } 91 | } 92 | 93 | static void bbexit(void) { 94 | FILE *fp; 95 | 96 | if (_bblist != &tail && (fp = fopen("prof.out", "a"))) { 97 | for ( ; _bblist != &tail; _bblist = _bblist->link) 98 | profout(_bblist, fp); 99 | fclose(fp); 100 | } 101 | } 102 | 103 | EXPORT void _epilogue(struct func *callee) { 104 | *_callerp = 0; 105 | } 106 | 107 | EXPORT void _prologue(struct func *callee, struct _bbdata *yylink) { 108 | static struct caller callers[4096]; 109 | static int next; 110 | struct caller *p; 111 | 112 | if (!yylink->link) { 113 | yylink->link = _bblist; 114 | _bblist = yylink; 115 | if (next == 0) 116 | atexit(bbexit); 117 | } 118 | for (p = callee->callers; p; p = p->link) 119 | if (p->caller == *_callerp) { 120 | p->count++; 121 | break; 122 | } 123 | if (!p && next < sizeof callers/sizeof callers[0]) { 124 | p = &callers[next++]; 125 | p->caller = *_callerp; 126 | p->count = 1; 127 | p->link = callee->callers; 128 | callee->callers = p; 129 | } 130 | *_callerp = 0; 131 | } 132 | -------------------------------------------------------------------------------- /src/input.c: -------------------------------------------------------------------------------- 1 | #include "c.h" 2 | 3 | static char rcsid[] = "$Id: input.c,v 1.1.1.1 2004/03/24 04:37:33 sjp Exp $"; 4 | 5 | static void pragma(void); 6 | static void resynch(void); 7 | 8 | static int bsize; 9 | static unsigned char buffer[MAXLINE+1 + BUFSIZE+1]; 10 | unsigned char *cp; /* current input character */ 11 | char *file; /* current input file name */ 12 | char *firstfile; /* first input file */ 13 | unsigned char *limit; /* points to last character + 1 */ 14 | char *line; /* current line */ 15 | int lineno; /* line number of current line */ 16 | 17 | void nextline(void) { 18 | do { 19 | if (cp >= limit) { 20 | fillbuf(); 21 | if (cp >= limit) 22 | cp = limit; 23 | if (cp == limit) 24 | return; 25 | } else { 26 | lineno++; 27 | for (line = (char *)cp; *cp==' ' || *cp=='\t'; cp++) 28 | ; 29 | if (*cp == '#') { 30 | resynch(); 31 | nextline(); 32 | } 33 | } 34 | } while (*cp == '\n' && cp == limit); 35 | } 36 | void fillbuf(void) { 37 | if (bsize == 0) 38 | return; 39 | if (cp >= limit) 40 | cp = &buffer[MAXLINE+1]; 41 | else 42 | { 43 | int n = limit - cp; 44 | unsigned char *s = &buffer[MAXLINE+1] - n; 45 | assert(s >= buffer); 46 | line = (char *)s - ((char *)cp - line); 47 | while (cp < limit) 48 | *s++ = *cp++; 49 | cp = &buffer[MAXLINE+1] - n; 50 | } 51 | if (feof(stdin)) 52 | bsize = 0; 53 | else 54 | bsize = fread(&buffer[MAXLINE+1], 1, BUFSIZE, stdin); 55 | if (bsize < 0) { 56 | error("read error\n"); 57 | exit(EXIT_FAILURE); 58 | } 59 | limit = &buffer[MAXLINE+1+bsize]; 60 | *limit = '\n'; 61 | } 62 | void input_init(int argc, char *argv[]) { 63 | static int inited; 64 | 65 | if (inited) 66 | return; 67 | inited = 1; 68 | main_init(argc, argv); 69 | limit = cp = &buffer[MAXLINE+1]; 70 | bsize = -1; 71 | lineno = 0; 72 | file = NULL; 73 | fillbuf(); 74 | if (cp >= limit) 75 | cp = limit; 76 | nextline(); 77 | } 78 | 79 | /* ident - handle #ident "string" */ 80 | static void ident(void) { 81 | while (*cp != '\n' && *cp != '\0') 82 | cp++; 83 | } 84 | 85 | /* pragma - handle #pragma ref id... */ 86 | static void pragma(void) { 87 | if ((t = gettok()) == ID && strcmp(token, "ref") == 0) 88 | for (;;) { 89 | while (*cp == ' ' || *cp == '\t') 90 | cp++; 91 | if (*cp == '\n' || *cp == 0) 92 | break; 93 | if ((t = gettok()) == ID && tsym) { 94 | tsym->ref++; 95 | use(tsym, src); 96 | } 97 | } 98 | } 99 | 100 | /* resynch - set line number/file name in # n [ "file" ], #pragma, etc. */ 101 | static void resynch(void) { 102 | for (cp++; *cp == ' ' || *cp == '\t'; ) 103 | cp++; 104 | if (limit - cp < MAXLINE) 105 | fillbuf(); 106 | if (strncmp((char *)cp, "pragma", 6) == 0) { 107 | cp += 6; 108 | pragma(); 109 | } else if (strncmp((char *)cp, "ident", 5) == 0) { 110 | cp += 5; 111 | ident(); 112 | } else if (*cp >= '0' && *cp <= '9') { 113 | line: for (lineno = 0; *cp >= '0' && *cp <= '9'; ) 114 | lineno = 10*lineno + *cp++ - '0'; 115 | lineno--; 116 | while (*cp == ' ' || *cp == '\t') 117 | cp++; 118 | if (*cp == '"') { 119 | file = (char *)++cp; 120 | while (*cp && *cp != '"' && *cp != '\n') 121 | cp++; 122 | file = stringn(file, (char *)cp - file); 123 | if (*cp == '\n') 124 | warning("missing \" in preprocessor line\n"); 125 | if (firstfile == 0) 126 | firstfile = file; 127 | } 128 | } else if (strncmp((char *)cp, "line", 4) == 0) { 129 | for (cp += 4; *cp == ' ' || *cp == '\t'; ) 130 | cp++; 131 | if (*cp >= '0' && *cp <= '9') 132 | goto line; 133 | if (Aflag >= 2) 134 | warning("unrecognized control line\n"); 135 | } else if (Aflag >= 2 && *cp != '\n') 136 | warning("unrecognized control line\n"); 137 | while (*cp) 138 | if (*cp++ == '\n') 139 | if (cp == limit + 1) { 140 | nextline(); 141 | if (cp == limit) 142 | break; 143 | } else 144 | break; 145 | } 146 | 147 | -------------------------------------------------------------------------------- /Makefile.def: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Makefile (and Makefile.def) -- Makefile for the LC-3 tools 3 | # 4 | # "Copyright (c) 2003 by Steven S. Lumetta." 5 | # 6 | # Permission to use, copy, modify, and distribute this software and its 7 | # documentation for any purpose, without fee, and without written 8 | # agreement is hereby granted, provided that the above copyright notice 9 | # and the following two paragraphs appear in all copies of this software, 10 | # that the files COPYING and NO_WARRANTY are included verbatim with 11 | # any distribution, and that the contents of the file README are included 12 | # verbatim as part of a file named README with any distribution. 13 | # 14 | # IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, 15 | # INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT 16 | # OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE AUTHOR 17 | # HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 18 | # 19 | # THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 20 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | # A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" 22 | # BASIS, AND THE AUTHOR NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 23 | # UPDATES, ENHANCEMENTS, OR MODIFICATIONS." 24 | # 25 | # Author: Steve Lumetta 26 | # Version: 1 27 | # Creation Date: 18 October 2003 28 | # Filename: Makefile[.def] 29 | # History: 30 | # SSL 2 31 October 2003 31 | # Added lc3convert tool into distribution. 32 | # SSL 1 18 October 2003 33 | # Copyright notices and Gnu Public License marker added. 34 | # 35 | ############################################################################### 36 | 37 | # These path names are automatically set by configure. 38 | GCC = __GCC__ 39 | FLEX = __FLEX__ 40 | EXE = __EXE__ 41 | RM = __RM__ 42 | CP = __CP__ 43 | MKDIR = __MKDIR__ 44 | CHMOD = __CHMOD__ 45 | SED = __SED__ 46 | MAKE = __MAKE__ 47 | AR = __AR__ 48 | RANLIB = __RANLIB__ 49 | INSTALL_DIR = __INSTALL_DIR__ 50 | # End of configuration block. 51 | 52 | CFLAGS = -g -Wall -m32 53 | LDFLAGS = -g -m32 54 | LC3AS = ./lc3as 55 | 56 | ALL: dist_lcc dist_cpp dist_lc3pp dist_rcc 57 | 58 | clean: dist_lcc_clean dist_cpp_clean dist_lc3pp_clean dist_rcc_clean 59 | 60 | clear: dist_lcc_clear dist_cpp_clear dist_lc3pp_clear dist_rcc_clear 61 | 62 | distclean: clean clear 63 | ${RM} -f Makefile *~ 64 | -${RM} -rf ${INSTALL_DIR} 65 | 66 | install: ALL 67 | ${MKDIR} -p ${INSTALL_DIR} 68 | -${CP} -f src/rcc${EXE} etc/lcc${EXE} cpp/cpp${EXE} lc3pp/lc3pp${EXE} ${INSTALL_DIR} 69 | # COPYING NO_WARRANTY README test/regression/Makefile test/regression/fig16.14.c ${INSTALL_DIR} 70 | ${CHMOD} 555 ${INSTALL_DIR}/rcc${EXE} \ 71 | ${INSTALL_DIR}/lcc${EXE} ${INSTALL_DIR}/cpp${EXE} \ 72 | ${INSTALL_DIR}/lc3pp 73 | # ${CHMOD} 444 ${INSTALL_DIR}/COPYING ${INSTALL_DIR}/NO_WARRANTY \ 74 | # ${INSTALL_DIR}/README 75 | 76 | 77 | # 78 | # Makefile fragment for lcc 79 | # 80 | dist_lcc: 81 | cd etc && ${MAKE} dist 82 | 83 | dist_lcc_clean: 84 | cd etc && ${MAKE} distclean 85 | 86 | dist_lcc_clear: 87 | cd etc && ${MAKE} distclear 88 | 89 | # 90 | # Makefile fragment for lc3pp 91 | # 92 | dist_lc3pp: 93 | cd lc3pp && ${MAKE} dist 94 | 95 | dist_lc3pp_clean: 96 | cd lc3pp && ${MAKE} distclean 97 | 98 | dist_lc3pp_clear: 99 | cd lc3pp && ${MAKE} distclear 100 | 101 | # 102 | # Makefile fragment for cpp 103 | # 104 | dist_cpp: 105 | cd cpp && ${MAKE} dist 106 | 107 | dist_cpp_clean: 108 | cd cpp && ${MAKE} distclean 109 | 110 | dist_cpp_clear: 111 | cd cpp && ${MAKE} distclear 112 | 113 | # 114 | # Makefile fragment for rcc 115 | # 116 | dist_rcc: 117 | cd src && ${MAKE} dist 118 | 119 | dist_rcc_clean: 120 | cd src && ${MAKE} distclean 121 | 122 | dist_rcc_clear: 123 | cd src && ${MAKE} distclear 124 | 125 | 126 | -------------------------------------------------------------------------------- /src/output.c: -------------------------------------------------------------------------------- 1 | #include "c.h" 2 | 3 | static char rcsid[] = "$Id: output.c,v 1.1.1.1 2004/03/24 04:37:33 sjp Exp $"; 4 | 5 | static char *outs(const char *str, FILE *f, char *bp) { 6 | if (f) 7 | fputs(str, f); 8 | else 9 | while (*bp = *str++) 10 | bp++; 11 | return bp; 12 | } 13 | 14 | static char *outd(long n, FILE *f, char *bp) { 15 | unsigned long m; 16 | char buf[25], *s = buf + sizeof buf; 17 | 18 | *--s = '\0'; 19 | if (n < 0) 20 | m = -n; 21 | else 22 | m = n; 23 | do 24 | *--s = m%10 + '0'; 25 | while ((m /= 10) != 0); 26 | if (n < 0) 27 | *--s = '-'; 28 | return outs(s, f, bp); 29 | } 30 | 31 | static char *outu(unsigned long n, int base, FILE *f, char *bp) { 32 | char buf[25], *s = buf + sizeof buf; 33 | 34 | *--s = '\0'; 35 | do 36 | *--s = "0123456789abcdef"[n%base]; 37 | while ((n /= base) != 0); 38 | return outs(s, f, bp); 39 | } 40 | void print(const char *fmt, ...) { 41 | va_list ap; 42 | 43 | va_start(ap, fmt); 44 | vfprint(stdout, NULL, fmt, ap); 45 | va_end(ap); 46 | } 47 | /* fprint - formatted output to f */ 48 | void fprint(FILE *f, const char *fmt, ...) { 49 | va_list ap; 50 | 51 | va_start(ap, fmt); 52 | vfprint(f, NULL, fmt, ap); 53 | va_end(ap); 54 | } 55 | 56 | /* stringf - formatted output to a saved string */ 57 | char *stringf(const char *fmt, ...) { 58 | char buf[1024]; 59 | va_list ap; 60 | 61 | va_start(ap, fmt); 62 | vfprint(NULL, buf, fmt, ap); 63 | va_end(ap); 64 | return string(buf); 65 | } 66 | 67 | /* vfprint - formatted output to f or string bp */ 68 | void vfprint(FILE *f, char *bp, const char *fmt, va_list ap) { 69 | for (; *fmt; fmt++) 70 | if (*fmt == '%') 71 | switch (*++fmt) { 72 | case 'd': bp = outd(va_arg(ap, int), f, bp); break; 73 | case 'D': bp = outd(va_arg(ap, long), f, bp); break; 74 | case 'U': bp = outu(va_arg(ap, unsigned long), 10, f, bp); break; 75 | case 'u': bp = outu(va_arg(ap, unsigned), 10, f, bp); break; 76 | case 'o': bp = outu(va_arg(ap, unsigned), 8, f, bp); break; 77 | case 'X': bp = outu(va_arg(ap, unsigned long), 16, f, bp); break; 78 | case 'x': bp = outu(va_arg(ap, unsigned), 16, f, bp); break; 79 | case 'f': case 'e': 80 | case 'g': { 81 | static char format[] = "%f"; 82 | char buf[128]; 83 | format[1] = *fmt; 84 | sprintf(buf, format, va_arg(ap, double)); 85 | bp = outs(buf, f, bp); 86 | } 87 | ; break; 88 | case 's': bp = outs(va_arg(ap, char *), f, bp); break; 89 | case 'p': { 90 | void *p = va_arg(ap, void *); 91 | if (p) 92 | bp = outs("0x", f, bp); 93 | bp = outu((unsigned long)p, 16, f, bp); 94 | break; 95 | } 96 | case 'c': if (f) fputc(va_arg(ap, int), f); else *bp++ = va_arg(ap, int); break; 97 | case 'S': { char *s = va_arg(ap, char *); 98 | int n = va_arg(ap, int); 99 | if (s) 100 | for ( ; n-- > 0; s++) 101 | if (f) (void)putc(*s, f); else *bp++ = *s; 102 | } break; 103 | case 'k': { int t = va_arg(ap, int); 104 | static char *tokens[] = { 105 | #define xx(a,b,c,d,e,f,g) g, 106 | #define yy(a,b,c,d,e,f,g) g, 107 | #include "token.h" 108 | }; 109 | assert(tokens[t&0177]); 110 | bp = outs(tokens[t&0177], f, bp); 111 | } break; 112 | case 't': { Type ty = va_arg(ap, Type); 113 | assert(f); 114 | outtype(ty ? ty : voidtype, f); 115 | } break; 116 | case 'w': { Coordinate *p = va_arg(ap, Coordinate *); 117 | if (p->file && *p->file) { 118 | bp = outs(p->file, f, bp); 119 | bp = outs(":", f, bp); 120 | } 121 | bp = outd(p->y, f, bp); 122 | } break; 123 | case 'I': { int n = va_arg(ap, int); 124 | while (--n >= 0) 125 | if (f) (void)putc(' ', f); else *bp++ = ' '; 126 | } break; 127 | default: if (f) (void)putc(*fmt, f); else *bp++ = *fmt; break; 128 | } 129 | else if (f) 130 | (void)putc(*fmt, f); 131 | else 132 | *bp++ = *fmt; 133 | if (!f) 134 | *bp = '\0'; 135 | } 136 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | LCC-LC3 C Compiler 2 | =================== 3 | 4 | ##Recent Changes 5 | ####May 2012 6 | 7 | *Avery Yen* 8 | 9 | Modified Makefile.def and configure to automatically install to `~/.lc3`. Also, `make install` now only installs executables. This is because having documents like a Makefile and a README in your executable path is a Bad Idea. The Makefile, README, and other documents previously installed by `make install` already live in the source directory. There doesn't seem to be any reason to make them live in two places. 10 | 11 | *Sean Smith (Dartmouth College), Stephen Canon* 12 | 13 | Modified configure to compile on Mac OS X, especially Lion, but should be compatible with Leopard/Snow Leopard. 14 | 15 | On Mac OS X Lion using Xcode 4.3, compiling with `/usr/bin/gcc` produces a binary lcc that crashes every time it is called. The fix is to use the `-mno-sse` flag when compiling `rcc`. Sean Smith reports that the issue appears to be with the MOVAPS instruction that gets compiled by `/usr/bin/gcc`, using the latest llvm-gcc compiler that comes with Xcode 4.3 on OS X Lion, which expects to copy aligned memory, but for some reason doesn't. 16 | 17 | From Stephen Canon: 18 | 19 | > `/usr/bin/gcc` is a bit of a frankencompiler on Lion; it's actually an alias for `llvm-gcc-4.2`, which uses the front end of GCC-4.2 and the LLVM back end. I suspect that the GCC frontend is making an alignment assumption in its internal representation that would later get unwound by the GCC backend, but that never has a chance to happen... 20 | 21 | 22 | ##Description Of Contents 23 | 24 | This is the preliminary distribution of LCC that supports the LC-3. This 25 | is the slightly modified version of Ladsaria and Patel's LCC for use at Dartmouth College. The copyright information is in the file CPYRIGHT. There is absolutely no warranty for this software. Complete installation information is in INSTALL. TODO contains a to-do list. 26 | 27 | ##Installation Instructions 28 | 29 | First, you must install the [LC3 Tools](https://github.com/haplesshero13/lc3tools) to have `lc3as`. 30 | 31 | Download and unpack this source, either with `git clone git://github.com/haplesshero13/lc3tools.git` or by clicking on the ZIP download button at the top of this github page. 32 | 33 | Change to the lcc directory with `cd lcc-1.3` 34 | 35 | From the top-level directory type `configure` 36 | 37 | Now install the lcc/lc3 binaries by typing `make install` 38 | 39 | If everything goes well, the make process will create a directory off the 40 | top level called "install". It should contain the various binaries needed 41 | by the compiler, along with some informational files, such as this README 42 | file, a sample C file to compile, and a makefile for compiling that file. 43 | 44 | 45 | ##How To Use 46 | 47 | In the package there is a regressions and limitations test directiory in 48 | topdir/test/limitations and topdir/test/regression. The regression 49 | directory has a small set of files that have been tested to compile 50 | properly and have been assembled and simulated using Steve Lumetta's LC-3 51 | simulator. Many of these examples are taken from the book by Patt and Patel. 52 | 53 | Compiling programs using the compiler is similar to using a standard C 54 | compiler. Behind the scenes, the compiler will (1) compile the .c files 55 | into a set of pseudo-assembly .lcc files, (2) use the lc3pp (lc3 post 56 | processor) to link and massage the .lcc files and library files into a 57 | single .asm file, and (3) use Steve Lumetta's LC-3 assembler to assemble 58 | the .asm into a .obj file. This object file can then be loaded The file 59 | topdir/test/regressions/Makefile provides an example of how the 60 | compilation process works. 61 | 62 | Note: not all C programs will compile to the LC-3. Programs with floating 63 | point types, for example will not currently compile. Also, certain 64 | complex integer expressions will not generate properly because of the 65 | limited LC-3 register set. See topdir/test/limitations for some examples 66 | that do not compile properly. I hope to reduce this set of exceptional 67 | cases over time. 68 | 69 | ##Maintainers and Contributors 70 | * Sean Smith 71 | * Stephen Canon 72 | * Avery Yen 73 | 74 | ##Original Authors 75 | 76 | * Ajay Ladsaria 77 | * Sanjay J. Patel (sjp@crhc.uiuc.edu) 78 | -------------------------------------------------------------------------------- /configure: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Parse the arguments... 5 | 6 | INSTALL_DIR="$HOME/.lc3" 7 | TOP_DIR="`pwd`" 8 | case $1 in 9 | --installdir) 10 | INSTALL_DIR=$2 ; 11 | ;; 12 | --help) 13 | echo "--installdir " 14 | echo "--help" 15 | exit 16 | ;; 17 | esac 18 | 19 | 20 | # Some binaries that we'll need, and the places that we might find them. 21 | 22 | binlist="uname gcc rm cp mkdir chmod sed make ranlib ar" 23 | pathlist="/bin /usr/bin /usr/local/bin /usr/ccs/bin" 24 | libpathlist="/lib /usr/lib /usr/local/lib" 25 | incpathlist="/include /usr/include /usr/local/include" 26 | 27 | 28 | # Find the binaries (or die trying). 29 | 30 | for binary in $binlist ; do 31 | for path in $pathlist ; do 32 | if [ -r $path/$binary ] ; then 33 | eval "$binary=${path}/${binary}" ; 34 | break ; 35 | fi ; 36 | done ; 37 | eval "if [ -z \"\$$binary\" ] ; then echo \"Cannot locate $binary binary.\" ; exit ; fi" 38 | done 39 | 40 | 41 | # These default values are overridden below for some operating systems. 42 | 43 | EXE="" 44 | DYN="so" 45 | 46 | # Tailor the variables based on OS. 47 | 48 | case `$uname -s` in 49 | CYGWIN*) 50 | EXE=".exe" 51 | DYN="dll" 52 | echo "Configuring for Cygwin..." 53 | ;; 54 | Linux*) echo "Configuring for Linux..." 55 | OS_SIM_LIBS="-lcurses" 56 | ;; 57 | SunOS*) echo "Configuring for Solaris..." 58 | OS_SIM_LIBS="-lcurses -lsocket -lnsl" 59 | ;; 60 | # Darwin*) echo "Configuring for Darwin..." 61 | # eval "gcc=/usr/bin/gcc-4.2"; 62 | esac 63 | echo "Installation directory is $INSTALL_DIR" 64 | 65 | 66 | # Splice it all in to the various Makefile.defs to create the Makefiles. 67 | 68 | # ./src 69 | rm -f Makefile 70 | sed -e "s __GCC__ $gcc g" -e "s __EXE__ $EXE g" \ 71 | -e "s __RM__ $rm g" -e "s __RANLIB__ $ranlib g" -e "s __AR__ $ar g" \ 72 | -e "s __CP__ $cp g" -e "s __MKDIR__ $mkdir g" -e "s __CHMOD__ $chmod g" \ 73 | -e "s*__INSTALL_DIR__*$INSTALL_DIR*g" -e "s*__TOP_DIR__*$TOP_DIR*g" \ 74 | -e "s __MAKE__ $make g" -e "s __SED__ $sed g" Makefile.def > Makefile 75 | 76 | # ./src 77 | cd src 78 | rm -f Makefile 79 | sed -e "s __GCC__ $gcc g" -e "s __EXE__ $EXE g" \ 80 | -e "s __RM__ $rm g" -e "s __RANLIB__ $ranlib g" -e "s __AR__ $ar g" \ 81 | -e "s __CP__ $cp g" -e "s __MKDIR__ $mkdir g" -e "s __CHMOD__ $chmod g" \ 82 | -e "s*__INSTALL_DIR__*$INSTALL_DIR*g" -e "s*__TOP_DIR__*$TOP_DIR*g" \ 83 | -e "s __MAKE__ $make g" -e "s __SED__ $sed g" Makefile.def > Makefile 84 | cd ../cpp 85 | rm -f Makefile 86 | sed -e "s __GCC__ $gcc g" -e "s __EXE__ $EXE g" \ 87 | -e "s __RM__ $rm g" -e "s __RANLIB__ $ranlib g" -e "s __AR__ $ar g" \ 88 | -e "s __CP__ $cp g" -e "s __MKDIR__ $mkdir g" -e "s __CHMOD__ $chmod g" \ 89 | -e "s*__INSTALL_DIR__*$INSTALL_DIR*g" -e "s*__TOP_DIR__*$TOP_DIR*g" \ 90 | -e "s __MAKE__ $make g" -e "s __SED__ $sed g" Makefile.def > Makefile 91 | cd ../lib 92 | rm -f Makefile 93 | sed -e "s __GCC__ $gcc g" -e "s __EXE__ $EXE g" \ 94 | -e "s __RM__ $rm g" -e "s __RANLIB__ $ranlib g" -e "s __AR__ $ar g" \ 95 | -e "s __CP__ $cp g" -e "s __MKDIR__ $mkdir g" -e "s __CHMOD__ $chmod g" \ 96 | -e "s*__INSTALL_DIR__*$INSTALL_DIR*g" -e "s*__TOP_DIR__*$TOP_DIR*g" \ 97 | -e "s __MAKE__ $make g" -e "s __SED__ $sed g" Makefile.def > Makefile 98 | cd ../lburg 99 | rm -f Makefile 100 | sed -e "s __GCC__ $gcc g" -e "s __EXE__ $EXE g" \ 101 | -e "s __RM__ $rm g" -e "s __RANLIB__ $ranlib g" -e "s __AR__ $ar g" \ 102 | -e "s __CP__ $cp g" -e "s __MKDIR__ $mkdir g" -e "s __CHMOD__ $chmod g" \ 103 | -e "s*__INSTALL_DIR__*$INSTALL_DIR*g" -e "s*__TOP_DIR__*$TOP_DIR*g" \ 104 | -e "s __MAKE__ $make g" -e "s __SED__ $sed g" Makefile.def > Makefile 105 | cd ../etc 106 | rm -f Makefile 107 | sed -e "s __GCC__ $gcc g" -e "s __EXE__ $EXE g" \ 108 | -e "s __RM__ $rm g" -e "s __RANLIB__ $ranlib g" -e "s __AR__ $ar g" \ 109 | -e "s __CP__ $cp g" -e "s __MKDIR__ $mkdir g" -e "s __CHMOD__ $chmod g" \ 110 | -e "s*__INSTALL_DIR__*$INSTALL_DIR*g" -e "s*__TOP_DIR__*$TOP_DIR*g" \ 111 | -e "s __MAKE__ $make g" -e "s __SED__ $sed g" Makefile.def > Makefile 112 | cd ../lc3pp 113 | rm -f Makefile 114 | sed -e "s __GCC__ $gcc g" -e "s __EXE__ $EXE g" \ 115 | -e "s __RM__ $rm g" -e "s __RANLIB__ $ranlib g" -e "s __AR__ $ar g" \ 116 | -e "s __CP__ $cp g" -e "s __MKDIR__ $mkdir g" -e "s __CHMOD__ $chmod g" \ 117 | -e "s*__INSTALL_DIR__*$INSTALL_DIR*g" -e "s*__TOP_DIR__*$TOP_DIR*g" \ 118 | -e "s __MAKE__ $make g" -e "s __SED__ $sed g" Makefile.def > Makefile 119 | -------------------------------------------------------------------------------- /src/stab.h: -------------------------------------------------------------------------------- 1 | /* @(#)stab.h 1.11 92/05/11 SMI */ 2 | /* $Id: stab.h,v 1.1.1.1 2004/03/24 04:37:33 sjp Exp $ */ 3 | /* 4 | * Copyright (c) 1990 by Sun Microsystems, Inc. 5 | */ 6 | 7 | /* 8 | * This file gives definitions supplementing 9 | * for permanent symbol table entries. 10 | * These must have one of the N_STAB bits on, 11 | * and are subject to relocation according to the masks in . 12 | */ 13 | 14 | #ifndef _STAB_H 15 | #define _STAB_H 16 | 17 | 18 | #if !defined(_a_out_h) && !defined(_A_OUT_H) 19 | /* this file contains fragments of a.out.h and stab.h relevant to 20 | * support of stabX processing within ELF files - see the 21 | * Format of a symbol table entry 22 | */ 23 | struct nlist { 24 | union { 25 | char *n_name; /* for use when in-core */ 26 | long n_strx; /* index into file string table */ 27 | } n_un; 28 | unsigned char n_type; /* type flag (N_TEXT,..) */ 29 | char n_other; /* unused */ 30 | short n_desc; /* see */ 31 | unsigned long n_value; /* value of symbol (or sdb offset) */ 32 | }; 33 | 34 | /* 35 | * Simple values for n_type. 36 | */ 37 | #define N_UNDF 0x0 /* undefined */ 38 | #define N_ABS 0x2 /* absolute */ 39 | #define N_TEXT 0x4 /* text */ 40 | #define N_DATA 0x6 /* data */ 41 | #define N_BSS 0x8 /* bss */ 42 | #define N_COMM 0x12 /* common (internal to ld) */ 43 | #define N_FN 0x1f /* file name symbol */ 44 | 45 | #define N_EXT 01 /* external bit, or'ed in */ 46 | #define N_TYPE 0x1e /* mask for all the type bits */ 47 | 48 | #endif 49 | 50 | /* 51 | * for symbolic debugger, sdb(1): 52 | */ 53 | #define N_GSYM 0x20 /* global symbol: name,,0,type,0 */ 54 | #define N_FNAME 0x22 /* procedure name (f77 kludge): name,,0 */ 55 | #define N_FUN 0x24 /* procedure: name,,0,linenumber,address */ 56 | #define N_STSYM 0x26 /* static symbol: name,,0,type,address */ 57 | #define N_LCSYM 0x28 /* .lcomm symbol: name,,0,type,address */ 58 | #define N_MAIN 0x2a /* name of main routine : name,,0,0,0 */ 59 | #define N_ROSYM 0x2c /* ro_data objects */ 60 | #define N_OBJ 0x38 /* object file path or name */ 61 | #define N_OPT 0x3c /* compiler options */ 62 | #define N_RSYM 0x40 /* register sym: name,,0,type,register */ 63 | #define N_SLINE 0x44 /* src line: 0,,0,linenumber,address */ 64 | #define N_FLINE 0x4c /* function start.end */ 65 | #define N_SSYM 0x60 /* structure elt: name,,0,type,struct_offset */ 66 | #define N_ENDM 0x62 /* last stab emitted for module */ 67 | #define N_SO 0x64 /* source file name: name,,0,0,address */ 68 | #define N_LSYM 0x80 /* local sym: name,,0,type,offset */ 69 | #define N_BINCL 0x82 /* header file: name,,0,0,0 */ 70 | #define N_SOL 0x84 /* #included file name: name,,0,0,address */ 71 | #define N_PSYM 0xa0 /* parameter: name,,0,type,offset */ 72 | #define N_EINCL 0xa2 /* end of include file */ 73 | #define N_ENTRY 0xa4 /* alternate entry: name,linenumber,address */ 74 | #define N_LBRAC 0xc0 /* left bracket: 0,,0,nesting level,address */ 75 | #define N_EXCL 0xc2 /* excluded include file */ 76 | #define N_RBRAC 0xe0 /* right bracket: 0,,0,nesting level,address */ 77 | #define N_BCOMM 0xe2 /* begin common: name,, */ 78 | #define N_ECOMM 0xe4 /* end common: name,, */ 79 | #define N_ECOML 0xe8 /* end common (local name): ,,address */ 80 | #define N_LENG 0xfe /* second stab entry with length information */ 81 | 82 | /* 83 | * for the berkeley pascal compiler, pc(1): 84 | */ 85 | #define N_PC 0x30 /* global pascal symbol: name,,0,subtype,line */ 86 | #define N_WITH 0xea /* pascal with statement: type,,0,0,offset */ 87 | 88 | /* 89 | * for code browser only 90 | */ 91 | #define N_BROWS 0x48 /* path to associated .cb file */ 92 | 93 | /* 94 | * Optional langauge designations for N_SO 95 | */ 96 | #define N_SO_AS 1 /* Assembler */ 97 | #define N_SO_C 2 /* C */ 98 | #define N_SO_ANSI_C 3 /* ANSI C */ 99 | #define N_SO_CC 4 /* C++ */ 100 | #define N_SO_FORTRAN 5 /* Fortran 77 */ 101 | #define N_SO_PASCAL 6 /* Pascal */ 102 | 103 | /* 104 | * Floating point type values 105 | */ 106 | #define NF_NONE 0 /* Undefined type */ 107 | #define NF_SINGLE 1 /* IEEE 32 bit float */ 108 | #define NF_DOUBLE 2 /* IEEE 64 bit float */ 109 | #define NF_COMPLEX 3 /* Fortran complex */ 110 | #define NF_COMPLEX16 4 /* Fortran double complex */ 111 | #define NF_COMPLEX32 5 /* Fortran complex*16 */ 112 | #define NF_LDOUBLE 6 /* Long double */ 113 | 114 | #endif 115 | -------------------------------------------------------------------------------- /src/string.c: -------------------------------------------------------------------------------- 1 | #include "c.h" 2 | 3 | static char rcsid[] = "$Id: string.c,v 1.1.1.1 2004/03/24 04:37:33 sjp Exp $"; 4 | 5 | static struct string { 6 | char *str; 7 | int len; 8 | struct string *link; 9 | } *buckets[1024]; 10 | static int scatter[] = { /* map characters to random values */ 11 | 2078917053, 143302914, 1027100827, 1953210302, 755253631, 12 | 2002600785, 1405390230, 45248011, 1099951567, 433832350, 13 | 2018585307, 438263339, 813528929, 1703199216, 618906479, 14 | 573714703, 766270699, 275680090, 1510320440, 1583583926, 15 | 1723401032, 1965443329, 1098183682, 1636505764, 980071615, 16 | 1011597961, 643279273, 1315461275, 157584038, 1069844923, 17 | 471560540, 89017443, 1213147837, 1498661368, 2042227746, 18 | 1968401469, 1353778505, 1300134328, 2013649480, 306246424, 19 | 1733966678, 1884751139, 744509763, 400011959, 1440466707, 20 | 1363416242, 973726663, 59253759, 1639096332, 336563455, 21 | 1642837685, 1215013716, 154523136, 593537720, 704035832, 22 | 1134594751, 1605135681, 1347315106, 302572379, 1762719719, 23 | 269676381, 774132919, 1851737163, 1482824219, 125310639, 24 | 1746481261, 1303742040, 1479089144, 899131941, 1169907872, 25 | 1785335569, 485614972, 907175364, 382361684, 885626931, 26 | 200158423, 1745777927, 1859353594, 259412182, 1237390611, 27 | 48433401, 1902249868, 304920680, 202956538, 348303940, 28 | 1008956512, 1337551289, 1953439621, 208787970, 1640123668, 29 | 1568675693, 478464352, 266772940, 1272929208, 1961288571, 30 | 392083579, 871926821, 1117546963, 1871172724, 1771058762, 31 | 139971187, 1509024645, 109190086, 1047146551, 1891386329, 32 | 994817018, 1247304975, 1489680608, 706686964, 1506717157, 33 | 579587572, 755120366, 1261483377, 884508252, 958076904, 34 | 1609787317, 1893464764, 148144545, 1415743291, 2102252735, 35 | 1788268214, 836935336, 433233439, 2055041154, 2109864544, 36 | 247038362, 299641085, 834307717, 1364585325, 23330161, 37 | 457882831, 1504556512, 1532354806, 567072918, 404219416, 38 | 1276257488, 1561889936, 1651524391, 618454448, 121093252, 39 | 1010757900, 1198042020, 876213618, 124757630, 2082550272, 40 | 1834290522, 1734544947, 1828531389, 1982435068, 1002804590, 41 | 1783300476, 1623219634, 1839739926, 69050267, 1530777140, 42 | 1802120822, 316088629, 1830418225, 488944891, 1680673954, 43 | 1853748387, 946827723, 1037746818, 1238619545, 1513900641, 44 | 1441966234, 367393385, 928306929, 946006977, 985847834, 45 | 1049400181, 1956764878, 36406206, 1925613800, 2081522508, 46 | 2118956479, 1612420674, 1668583807, 1800004220, 1447372094, 47 | 523904750, 1435821048, 923108080, 216161028, 1504871315, 48 | 306401572, 2018281851, 1820959944, 2136819798, 359743094, 49 | 1354150250, 1843084537, 1306570817, 244413420, 934220434, 50 | 672987810, 1686379655, 1301613820, 1601294739, 484902984, 51 | 139978006, 503211273, 294184214, 176384212, 281341425, 52 | 228223074, 147857043, 1893762099, 1896806882, 1947861263, 53 | 1193650546, 273227984, 1236198663, 2116758626, 489389012, 54 | 593586330, 275676551, 360187215, 267062626, 265012701, 55 | 719930310, 1621212876, 2108097238, 2026501127, 1865626297, 56 | 894834024, 552005290, 1404522304, 48964196, 5816381, 57 | 1889425288, 188942202, 509027654, 36125855, 365326415, 58 | 790369079, 264348929, 513183458, 536647531, 13672163, 59 | 313561074, 1730298077, 286900147, 1549759737, 1699573055, 60 | 776289160, 2143346068, 1975249606, 1136476375, 262925046, 61 | 92778659, 1856406685, 1884137923, 53392249, 1735424165, 62 | 1602280572 63 | }; 64 | char *string(const char *str) { 65 | const char *s; 66 | 67 | for (s = str; *s; s++) 68 | ; 69 | return stringn(str, s - str); 70 | } 71 | char *stringd(long n) { 72 | char str[25], *s = str + sizeof (str); 73 | unsigned long m; 74 | 75 | if (n == LONG_MIN) 76 | m = (unsigned long)LONG_MAX + 1; 77 | else if (n < 0) 78 | m = -n; 79 | else 80 | m = n; 81 | do 82 | *--s = m%10 + '0'; 83 | while ((m /= 10) != 0); 84 | if (n < 0) 85 | *--s = '-'; 86 | return stringn(s, str + sizeof (str) - s); 87 | } 88 | char *stringn(const char *str, int len) { 89 | int i; 90 | unsigned int h; 91 | const char *end; 92 | struct string *p; 93 | 94 | assert(str); 95 | for (h = 0, i = len, end = str; i > 0; i--) 96 | h = (h<<1) + scatter[*(unsigned char *)end++]; 97 | h &= NELEMS(buckets)-1; 98 | for (p = buckets[h]; p; p = p->link) 99 | if (len == p->len) { 100 | const char *s1 = str; 101 | char *s2 = p->str; 102 | do { 103 | if (s1 == end) 104 | return p->str; 105 | } while (*s1++ == *s2++); 106 | } 107 | { 108 | static char *next, *strlimit; 109 | if (len + 1 >= strlimit - next) { 110 | int n = len + 4*1024; 111 | next = allocate(n, PERM); 112 | strlimit = next + n; 113 | } 114 | NEW(p, PERM); 115 | p->len = len; 116 | for (p->str = next; str < end; ) 117 | *next++ = *str++; 118 | *next++ = 0; 119 | p->link = buckets[h]; 120 | buckets[h] = p; 121 | return p->str; 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/dagcheck.md: -------------------------------------------------------------------------------- 1 | %{ 2 | #include "c.h" 3 | typedef Node NODEPTR_TYPE; 4 | #define OP_LABEL(p) (specific((p)->op)) 5 | #define LEFT_CHILD(p) ((p)->kids[0]) 6 | #define RIGHT_CHILD(p) ((p)->kids[1]) 7 | #define STATE_LABEL(p) ((p)->x.state) 8 | #define PANIC error 9 | %} 10 | %term CNSTF=17 CNSTI=21 CNSTP=23 CNSTU=22 11 | %term ARGB=41 ARGF=33 ARGI=37 ARGP=39 ARGU=38 12 | %term ASGNB=57 ASGNF=49 ASGNI=53 ASGNP=55 ASGNU=54 13 | %term INDIRB=73 INDIRF=65 INDIRI=69 INDIRP=71 INDIRU=70 14 | %term CVFF=113 CVFI=117 15 | %term CVIF=129 CVII=133 CVIU=134 16 | %term CVPP=151 CVPU=150 17 | %term CVUI=181 CVUP=183 CVUU=182 18 | %term NEGF=193 NEGI=197 19 | %term CALLB=217 CALLF=209 CALLI=213 CALLP=215 CALLU=214 CALLV=216 20 | %term RETF=241 RETI=245 RETP=247 RETU=246 RETV=248 21 | %term ADDRGP=263 22 | %term ADDRFP=279 23 | %term ADDRLP=295 24 | %term ADDF=305 ADDI=309 ADDP=311 ADDU=310 25 | %term SUBF=321 SUBI=325 SUBP=327 SUBU=326 26 | %term LSHI=341 LSHU=342 27 | %term MODI=357 MODU=358 28 | %term RSHI=373 RSHU=374 29 | %term BANDI=389 BANDU=390 30 | %term BCOMI=405 BCOMU=406 31 | %term BORI=421 BORU=422 32 | %term BXORI=437 BXORU=438 33 | %term DIVF=449 DIVI=453 DIVU=454 34 | %term MULF=465 MULI=469 MULU=470 35 | %term EQF=481 EQI=485 EQU=486 36 | %term GEF=497 GEI=501 GEU=502 37 | %term GTF=513 GTI=517 GTU=518 38 | %term LEF=529 LEI=533 LEU=534 39 | %term LTF=545 LTI=549 LTU=550 40 | %term NEF=561 NEI=565 NEU=566 41 | %term JUMPV=584 42 | %term LABELV=600 43 | %% 44 | stmt: INDIRB(P) "" 45 | stmt: INDIRF(P) "" 46 | stmt: INDIRI(P) "" 47 | stmt: INDIRU(P) "" 48 | stmt: INDIRP(P) "" 49 | stmt: CALLF(P) "" 50 | stmt: CALLI(P) "" 51 | stmt: CALLU(P) "" 52 | stmt: CALLP(P) "" 53 | stmt: V "" 54 | bogus: I "" 1 55 | bogus: U "" 1 56 | bogus: P "" 1 57 | bogus: F "" 1 58 | bogus: B "" 1 59 | bogus: V "" 1 60 | I: bogus "" 1 61 | U: bogus "" 1 62 | P: bogus "" 1 63 | F: bogus "" 1 64 | B: bogus "" 1 65 | V: bogus "" 1 66 | F: CNSTF "" 67 | I: CNSTI "" 68 | P: CNSTP "" 69 | U: CNSTU "" 70 | V: ARGB(B) "" 71 | V: ARGF(F) "" 72 | V: ARGI(I) "" 73 | V: ARGU(U) "" 74 | V: ARGP(P) "" 75 | V: ASGNB(P,B) "" 76 | V: ASGNF(P,F) "" 77 | V: ASGNI(P,I) "" 78 | V: ASGNU(P,U) "" 79 | V: ASGNP(P,P) "" 80 | B: INDIRB(P) "" 81 | F: INDIRF(P) "" 82 | I: INDIRI(P) "" 83 | U: INDIRU(P) "" 84 | P: INDIRP(P) "" 85 | I: CVII(I) "" 86 | I: CVUI(U) "" 87 | I: CVFI(F) "" 88 | U: CVIU(I) "" 89 | U: CVUU(U) "" 90 | U: CVPU(P) "" 91 | F: CVIF(I) "" 92 | F: CVFF(F) "" 93 | P: CVUP(U) "" 94 | P: CVPP(P) "" 95 | F: NEGF(F) "" 96 | I: NEGI(I) "" 97 | V: CALLB(P,P) "" 98 | F: CALLF(P) "" 99 | I: CALLI(P) "" 100 | U: CALLU(P) "" 101 | P: CALLP(P) "" 102 | V: CALLV(P) "" 103 | V: RETF(F) "" 104 | V: RETI(I) "" 105 | V: RETU(U) "" 106 | V: RETP(P) "" 107 | V: RETV "" 108 | P: ADDRGP "" 109 | P: ADDRFP "" 110 | P: ADDRLP "" 111 | F: ADDF(F,F) "" 112 | I: ADDI(I,I) "" 113 | P: ADDP(P,I) "" 114 | P: ADDP(I,P) "" 115 | P: ADDP(U,P) "" 116 | P: ADDP(P,U) "" 117 | U: ADDU(U,U) "" 118 | F: SUBF(F,F) "" 119 | I: SUBI(I,I) "" 120 | P: SUBP(P,I) "" 121 | P: SUBP(P,U) "" 122 | U: SUBU(U,U) "" 123 | I: LSHI(I,I) "" 124 | U: LSHU(U,I) "" 125 | I: MODI(I,I) "" 126 | U: MODU(U,U) "" 127 | I: RSHI(I,I) "" 128 | U: RSHU(U,I) "" 129 | U: BANDU(U,U) "" 130 | I: BANDI(I,I) "" 131 | U: BCOMU(U) "" 132 | I: BCOMI(I) "" 133 | I: BORI(I,I) "" 134 | U: BORU(U,U) "" 135 | U: BXORU(U,U) "" 136 | I: BXORI(I,I) "" 137 | F: DIVF(F,F) "" 138 | I: DIVI(I,I) "" 139 | U: DIVU(U,U) "" 140 | F: MULF(F,F) "" 141 | I: MULI(I,I) "" 142 | U: MULU(U,U) "" 143 | V: EQF(F,F) "" 144 | V: EQI(I,I) "" 145 | V: EQU(U,U) "" 146 | V: GEF(F,F) "" 147 | V: GEI(I,I) "" 148 | V: GEU(U,U) "" 149 | V: GTF(F,F) "" 150 | V: GTI(I,I) "" 151 | V: GTU(U,U) "" 152 | V: LEF(F,F) "" 153 | V: LEI(I,I) "" 154 | V: LEU(U,U) "" 155 | V: LTF(F,F) "" 156 | V: LTI(I,I) "" 157 | V: LTU(U,U) "" 158 | V: NEF(F,F) "" 159 | V: NEI(I,I) "" 160 | V: NEU(U,U) "" 161 | V: JUMPV(P) "" 162 | V: LABELV "" 163 | %% 164 | 165 | static void reduce(NODEPTR_TYPE p, int goalnt) { 166 | int i, sz = opsize(p->op), rulenumber = _rule(p->x.state, goalnt); 167 | short *nts = _nts[rulenumber]; 168 | NODEPTR_TYPE kids[10]; 169 | 170 | assert(rulenumber); 171 | _kids(p, rulenumber, kids); 172 | for (i = 0; nts[i]; i++) 173 | reduce(kids[i], nts[i]); 174 | switch (optype(p->op)) { 175 | #define xx(ty) if (sz == ty->size) return 176 | case I: 177 | case U: 178 | xx(chartype); 179 | xx(shorttype); 180 | xx(inttype); 181 | xx(longtype); 182 | xx(longlong); 183 | xx(signedptr); 184 | xx(unsignedptr); 185 | break; 186 | case F: 187 | xx(floattype); 188 | xx(doubletype); 189 | xx(longdouble); 190 | break; 191 | case P: 192 | xx(voidptype); 193 | xx(funcptype); 194 | break; 195 | case V: 196 | case B: if (sz == 0) return; 197 | #undef xx 198 | } 199 | printdag(p, 2); 200 | assert(0); 201 | } 202 | 203 | void check(Node p) { 204 | struct _state { short cost[1]; }; 205 | 206 | _label(p); 207 | if (((struct _state *)p->x.state)->cost[1] > 0) { 208 | printdag(p, 2); 209 | assert(0); 210 | } 211 | reduce(p, 1); 212 | } 213 | -------------------------------------------------------------------------------- /lc3lib/printf.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 4 | ; void printf(const char *format, ...) 5 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 6 | LC3_GFLAG printf LC3_GFLAG .FILL lc3_printf 7 | 8 | PRINTF_PERCENT .FILL -37 9 | PRINTF_C .FILL -99 10 | PRINTF_D .FILL -100 11 | PRINTF_S .FILL -115 12 | PRINTF_B .FILL -98 13 | PRINTF_O .FILL -111 14 | PRINTF_X .FILL -120 15 | PRINTF_ASCII .FILL 48 ;postive ascii value of '0' 16 | .FILL 49 17 | .FILL 50 18 | .FILL 51 19 | .FILL 52 20 | .FILL 53 21 | .FILL 54 22 | .FILL 55 23 | .FILL 56 24 | .FILL 57 25 | .FILL 65 ;A 26 | .FILL 66 27 | .FILL 67 28 | .FILL 68 29 | .FILL 69 30 | .FILL 70 31 | PRINTF_MINUS .FILL 45 32 | PRINTF_BUF .BLKW 18 33 | 34 | 35 | lc3_printf 36 | ADD R6, R6, #-2 37 | STR R7, R6, #0 ;return address 38 | ADD R6, R6, #-1 39 | STR R5, R6, #0 40 | ADD R5, R6, #-1 41 | 42 | ADD R6, R6, #-1 43 | STR R4, R6, #0 44 | 45 | ADD R5, R5, #4 ;cheating with the bp (no longer bp) 46 | LDR R4, R5, #0 ;got addr of format string 47 | 48 | 49 | PRINTF_LOOP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 50 | 51 | LDR R0, R4, #0 52 | 53 | ADD R0, R0, #0 ;End of string? (0x0000) 54 | BRz PRINTF_DONE 55 | 56 | ADD R2, R0, #0 57 | LD R1, PRINTF_PERCENT 58 | ADD R2, R2, R1 59 | BRnp PRINTF_CHAR 60 | 61 | ADD R4, R4, #1 62 | LDR R0, R4, #0 63 | ;is it %c? 64 | ADD R2, R0, #0 65 | LD R3, PRINTF_C 66 | ADD R2, R2, R3 67 | BRnp PRINTF_CHECKSTR 68 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%c 69 | ADD R5, R5, #1 70 | LDR R0, R5, #0 71 | 72 | PRINTF_CHAR 73 | OUT 74 | 75 | ADD R4, R4, #1 76 | BRnzp PRINTF_LOOP 77 | 78 | PRINTF_CHECKSTR 79 | ;is it %s? 80 | ADD R2, R0, #0 81 | LD R7, PRINTF_S 82 | ADD R2, R2, R7 83 | BRnp PRINTF_CHECKDEC 84 | 85 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%s 86 | 87 | ADD R5, R5, #1 88 | LDR R0, R5, #0 89 | PUTS 90 | 91 | ADD R4, R4, #1 92 | BRnzp PRINTF_LOOP 93 | 94 | PRINTF_CHECKDEC 95 | ;is it %d? 96 | ADD R2, R0, #0 97 | LD R7, PRINTF_D 98 | ADD R2, R2, R7 99 | ;BRnp PRINTF_ERROR 100 | BRnp PRINTF_CHECKHEX 101 | 102 | AND R2, R2, #0 103 | ADD R2, R2, #-10 ;going to divide by 10 by using sub loop 104 | BRnzp PRINTF_NUM 105 | 106 | PRINTF_CHECKHEX 107 | 108 | ADD R2, R0, #0 109 | LD R7, PRINTF_X 110 | ADD R2, R2, R7 111 | BRnp PRINTF_CHECKOCT 112 | 113 | AND R2, R2, #0 114 | ADD R2, R2, #-16 ;going to divide by 10 by using sub loop 115 | BRnzp PRINTF_NUM 116 | 117 | PRINTF_CHECKOCT 118 | 119 | ADD R2, R0, #0 120 | LD R7, PRINTF_O 121 | ADD R2, R2, R7 122 | BRnp PRINTF_CHECKBIN 123 | 124 | AND R2, R2, #0 125 | ADD R2, R2, #-8 ;going to divide by 10 by using sub loop 126 | BRnzp PRINTF_NUM 127 | 128 | PRINTF_CHECKBIN 129 | 130 | ADD R2, R0, #0 131 | LD R7, PRINTF_B 132 | ADD R2, R2, R7 133 | BRnp PRINTF_ERROR 134 | 135 | AND R2, R2, #0 136 | ADD R2, R2, #-2 ;going to divide by 10 by using sub loop 137 | ;BRnzp PRINTF_NUM 138 | 139 | 140 | 141 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%d 142 | PRINTF_NUM 143 | 144 | LEA R7, PRINTF_BUF 145 | ADD R7, R7, #15 146 | ADD R7, R7, #1 147 | 148 | ;AND R2, R2, #0 149 | ;ADD R2, R2, #-10 ;going to divide by 10 by using sub loop 150 | 151 | ADD R5, R5, #1 ;acquire the binary number 152 | LDR R0, R5, #0 153 | 154 | ADD R0, R0, #0 155 | BRzp PRINTF_DECPOS 156 | 157 | NOT R0, R0 ;make num positive for sub loop 158 | ADD R0, R0, #1 159 | 160 | PRINTF_DECPOS 161 | 162 | AND R3, R3, #0 163 | ADD R3, R3, #-1 164 | 165 | PRINTF_DIVLOOP 166 | ADD R3, R3, #1 ;num/10 167 | ADD R0, R0, R2 ;R0 = num % 10 - 10 168 | BRzp PRINTF_DIVLOOP 169 | 170 | ADD R3, R3, #0 171 | BRz PRINTF_LASTDIGIT 172 | 173 | ;LD R1, PRINTF_ASCII 174 | ;ADD R1, R1, R0 175 | ;NOT R2, R2 176 | ;ADD R1, R1, R2 177 | ;ADD R1, R1, #1 178 | ;NOT R2, R2 179 | ;;;;;ADD R1, R1, #10 180 | ;STR R1, R7, #0 181 | ;ADD R7, R7, #-1 ;stored ascii value of one digit 182 | 183 | LEA R1, PRINTF_ASCII 184 | ADD R1, R1, R0 185 | NOT R2, R2 186 | ADD R1, R1, R2 187 | ADD R1, R1, #1 188 | NOT R2, R2 189 | LDR R1, R1, #0 190 | STR R1, R7, #0 191 | ADD R7, R7, #-1 ;stored ascii value of one digit 192 | 193 | ADD R0, R3, #0 ;num/10 194 | 195 | BRnzp PRINTF_DECPOS 196 | 197 | PRINTF_LASTDIGIT 198 | 199 | ;LD R1, PRINTF_ASCII 200 | ;ADD R1, R1, R0 201 | ;ADD R1, R1, #10 202 | ;STR R1, R7, #0 203 | 204 | LEA R1, PRINTF_ASCII 205 | ADD R1, R1, R0 206 | NOT R2, R2 207 | ADD R1, R1, R2 208 | ADD R1, R1, #1 209 | NOT R2, R2 210 | LDR R1, R1, #0 211 | STR R1, R7, #0 ;stored ascii value of highest order digit 212 | 213 | LDR R0, R5, #0 214 | ADD R0, R0, #0 215 | BRzp PRINTF_DECSTRING 216 | 217 | LD R0, PRINTF_MINUS ;num was negative 218 | ADD R7, R7, #-1 219 | STR R0, R7, #0 ;stored ascii value negative sign 220 | 221 | PRINTF_DECSTRING ;print the calculated string 222 | ADD R0, R7, #0 223 | PUTS 224 | 225 | ADD R4, R4, #1 226 | BRnzp PRINTF_LOOP 227 | 228 | PRINTF_ERROR 229 | PRINTF_DONE 230 | 231 | LDR R4, R6, #0 ;restore R4 232 | ADD R6, R6, #1 233 | 234 | LDR R5, R6, #0 ;restore bp 235 | ADD R6, R6, #1 236 | 237 | LDR R7, R6, #0 ;restore ret addr 238 | ADD R6, R6, #1 239 | 240 | RET 241 | -------------------------------------------------------------------------------- /src/trace.c: -------------------------------------------------------------------------------- 1 | #include "c.h" 2 | 3 | static char rcsid[] = "$Id: trace.c,v 1.1.1.1 2004/03/24 04:37:33 sjp Exp $"; 4 | 5 | static char *fmt, *fp, *fmtend; /* format string, current & limit pointer */ 6 | static Tree args; /* printf arguments */ 7 | static Symbol frameno; /* local holding frame number */ 8 | 9 | /* appendstr - append str to the evolving format string, expanding it if necessary */ 10 | static void appendstr(char *str) { 11 | do 12 | if (fp == fmtend) 13 | if (fp) { 14 | char *s = allocate(2*(fmtend - fmt), FUNC); 15 | strncpy(s, fmt, fmtend - fmt); 16 | fp = s + (fmtend - fmt); 17 | fmtend = s + 2*(fmtend - fmt); 18 | fmt = s; 19 | } else { 20 | fp = fmt = allocate(80, FUNC); 21 | fmtend = fmt + 80; 22 | } 23 | while ((*fp++ = *str++) != 0); 24 | fp--; 25 | } 26 | 27 | /* tracevalue - append format and argument to print the value of e */ 28 | static void tracevalue(Tree e, int lev) { 29 | Type ty = unqual(e->type); 30 | 31 | switch (ty->op) { 32 | case INT: 33 | if (ty == chartype || ty == signedchar) 34 | appendstr("'\\x%02x'"); 35 | else if (ty == longtype) 36 | appendstr("0x%ld"); 37 | else 38 | appendstr("0x%d"); 39 | break; 40 | case UNSIGNED: 41 | if (ty == chartype || ty == unsignedchar) 42 | appendstr("'\\x%02x'"); 43 | else if (ty == unsignedlong) 44 | appendstr("0x%lx"); 45 | else 46 | appendstr("0x%x"); 47 | break; 48 | case FLOAT: 49 | if (ty == longdouble) 50 | appendstr("%Lg"); 51 | else 52 | appendstr("%g"); 53 | break; 54 | case POINTER: 55 | if (unqual(ty->type) == chartype 56 | || unqual(ty->type) == signedchar 57 | || unqual(ty->type) == unsignedchar) { 58 | static Symbol null; 59 | if (null == NULL) 60 | null = mkstr("(null)"); 61 | tracevalue(cast(e, unsignedtype), lev + 1); 62 | appendstr(" \"%.30s\""); 63 | e = condtree(e, e, pointer(idtree(null->u.c.loc))); 64 | } else { 65 | appendstr("("); appendstr(typestring(ty, "")); appendstr(")0x%x"); 66 | } 67 | break; 68 | case STRUCT: { 69 | Field q; 70 | appendstr("("); appendstr(typestring(ty, "")); appendstr("){"); 71 | for (q = ty->u.sym->u.s.flist; q; q = q->link) { 72 | appendstr(q->name); appendstr("="); 73 | tracevalue(field(addrof(e), q->name), lev + 1); 74 | if (q->link) 75 | appendstr(","); 76 | } 77 | appendstr("}"); 78 | return; 79 | } 80 | case UNION: 81 | appendstr("("); appendstr(typestring(ty, "")); appendstr("){...}"); 82 | return; 83 | case ARRAY: 84 | if (lev && ty->type->size > 0) { 85 | int i; 86 | e = pointer(e); 87 | appendstr("{"); 88 | for (i = 0; i < ty->size/ty->type->size; i++) { 89 | Tree p = (*optree['+'])(ADD, e, consttree(i, inttype)); 90 | if (isptr(p->type) && isarray(p->type->type)) 91 | p = retype(p, p->type->type); 92 | else 93 | p = rvalue(p); 94 | if (i) 95 | appendstr(","); 96 | tracevalue(p, lev + 1); 97 | } 98 | appendstr("}"); 99 | } else 100 | appendstr(typestring(ty, "")); 101 | return; 102 | default: 103 | assert(0); 104 | } 105 | e = cast(e, promote(ty)); 106 | args = tree(mkop(ARG,e->type), e->type, e, args); 107 | } 108 | 109 | /* tracefinis - complete & generate the trace call to print */ 110 | static void tracefinis(Symbol printer) { 111 | Tree *ap; 112 | Symbol p; 113 | 114 | *fp = 0; 115 | p = mkstr(string(fmt)); 116 | for (ap = &args; *ap; ap = &(*ap)->kids[1]) 117 | ; 118 | *ap = tree(ARG+P, charptype, pointer(idtree(p->u.c.loc)), 0); 119 | walk(calltree(pointer(idtree(printer)), freturn(printer->type), args, NULL), 0, 0); 120 | args = 0; 121 | fp = fmtend = 0; 122 | } 123 | 124 | /* tracecall - generate code to trace entry to f */ 125 | static void tracecall(Symbol printer, Symbol f, void *ignore) { 126 | int i; 127 | Symbol counter = genident(STATIC, inttype, GLOBAL); 128 | 129 | defglobal(counter, BSS); 130 | (*IR->space)(counter->type->size); 131 | frameno = genident(AUTO, inttype, level); 132 | addlocal(frameno); 133 | appendstr(f->name); appendstr("#"); 134 | tracevalue(asgn(frameno, incr(INCR, idtree(counter), consttree(1, inttype))), 0); 135 | appendstr("("); 136 | for (i = 0; f->u.f.callee[i]; i++) { 137 | if (i) 138 | appendstr(","); 139 | appendstr(f->u.f.callee[i]->name); appendstr("="); 140 | tracevalue(idtree(f->u.f.callee[i]), 0); 141 | } 142 | if (variadic(f->type)) 143 | appendstr(",..."); 144 | appendstr(") called\n"); 145 | tracefinis(printer); 146 | } 147 | 148 | /* tracereturn - generate code to trace return e */ 149 | static void tracereturn(Symbol printer, Symbol f, Tree e) { 150 | appendstr(f->name); appendstr("#"); 151 | tracevalue(idtree(frameno), 0); 152 | appendstr(" returned"); 153 | if (freturn(f->type) != voidtype && e) { 154 | appendstr(" "); 155 | tracevalue(e, 0); 156 | } 157 | appendstr("\n"); 158 | tracefinis(printer); 159 | } 160 | 161 | /* traceInit - initialize for tracing */ 162 | void traceInit(char *arg) { 163 | if (strncmp(arg, "-t", 2) == 0 && strchr(arg, '=') == NULL) { 164 | Symbol printer = mksymbol(EXTERN, arg[2] ? &arg[2] : "printf", 165 | ftype(inttype, ptr(qual(CONST, chartype)), voidtype, NULL)); 166 | printer->defined = 0; 167 | attach((Apply)tracecall, printer, &events.entry); 168 | attach((Apply)tracereturn, printer, &events.returns); 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /cpp/cpp.h: -------------------------------------------------------------------------------- 1 | /* $Id: cpp.h,v 1.1.1.1 2004/03/24 04:37:35 sjp Exp $ */ 2 | #include 3 | #define INS 32768 /* input buffer */ 4 | #define OBS 4096 /* outbut buffer */ 5 | #define NARG 32 /* Max number arguments to a macro */ 6 | #define NINCLUDE 32 /* Max number of include directories (-I) */ 7 | #define NIF 32 /* depth of nesting of #if */ 8 | #ifndef EOF 9 | #define EOF (-1) 10 | #endif 11 | #ifndef NULL 12 | #define NULL 0 13 | #endif 14 | 15 | #ifndef __alpha 16 | typedef unsigned char uchar; 17 | #endif 18 | 19 | enum toktype { END, UNCLASS, NAME, NUMBER, STRING, CCON, NL, WS, DSHARP, 20 | EQ, NEQ, LEQ, GEQ, LSH, RSH, LAND, LOR, PPLUS, MMINUS, 21 | ARROW, SBRA, SKET, LP, RP, DOT, AND, STAR, PLUS, MINUS, 22 | TILDE, NOT, SLASH, PCT, LT, GT, CIRC, OR, QUEST, 23 | COLON, ASGN, COMMA, SHARP, SEMIC, CBRA, CKET, 24 | ASPLUS, ASMINUS, ASSTAR, ASSLASH, ASPCT, ASCIRC, ASLSH, 25 | ASRSH, ASOR, ASAND, ELLIPS, 26 | DSHARP1, NAME1, DEFINED, UMINUS }; 27 | 28 | enum kwtype { KIF, KIFDEF, KIFNDEF, KELIF, KELSE, KENDIF, KINCLUDE, KDEFINE, 29 | KUNDEF, KLINE, KERROR, KPRAGMA, KDEFINED, 30 | KLINENO, KFILE, KDATE, KTIME, KSTDC, KEVAL }; 31 | 32 | #define ISDEFINED 01 /* has #defined value */ 33 | #define ISKW 02 /* is PP keyword */ 34 | #define ISUNCHANGE 04 /* can't be #defined in PP */ 35 | #define ISMAC 010 /* builtin macro, e.g. __LINE__ */ 36 | 37 | #define EOB 0xFE /* sentinel for end of input buffer */ 38 | #define EOFC 0xFD /* sentinel for end of input file */ 39 | #define XPWS 1 /* token flag: white space to assure token sep. */ 40 | 41 | typedef struct token { 42 | unsigned char type; 43 | unsigned char flag; 44 | unsigned short hideset; 45 | unsigned int wslen; 46 | unsigned int len; 47 | uchar *t; 48 | } Token; 49 | 50 | typedef struct tokenrow { 51 | Token *tp; /* current one to scan */ 52 | Token *bp; /* base (allocated value) */ 53 | Token *lp; /* last+1 token used */ 54 | int max; /* number allocated */ 55 | } Tokenrow; 56 | 57 | typedef struct source { 58 | char *filename; /* name of file of the source */ 59 | int line; /* current line number */ 60 | int lineinc; /* adjustment for \\n lines */ 61 | uchar *inb; /* input buffer */ 62 | uchar *inp; /* input pointer */ 63 | uchar *inl; /* end of input */ 64 | FILE* fd; /* input source */ 65 | int ifdepth; /* conditional nesting in include */ 66 | struct source *next; /* stack for #include */ 67 | } Source; 68 | 69 | typedef struct nlist { 70 | struct nlist *next; 71 | uchar *name; 72 | int len; 73 | Tokenrow *vp; /* value as macro */ 74 | Tokenrow *ap; /* list of argument names, if any */ 75 | char val; /* value as preprocessor name */ 76 | char flag; /* is defined, is pp name */ 77 | } Nlist; 78 | 79 | typedef struct includelist { 80 | char deleted; 81 | char always; 82 | char *file; 83 | } Includelist; 84 | 85 | #define new(t) (t *)domalloc(sizeof(t)) 86 | #define quicklook(a,b) (namebit[(a)&077] & (1<<((b)&037))) 87 | #define quickset(a,b) namebit[(a)&077] |= (1<<((b)&037)) 88 | extern unsigned long namebit[077+1]; 89 | 90 | enum errtype { WARNING, ERROR, FATAL }; 91 | 92 | void expandlex(void); 93 | void fixlex(void); 94 | void setup(int, char **); 95 | int gettokens(Tokenrow *, int); 96 | int comparetokens(Tokenrow *, Tokenrow *); 97 | Source *setsource(char *, FILE *, char *); 98 | void unsetsource(void); 99 | void puttokens(Tokenrow *); 100 | void process(Tokenrow *); 101 | void *domalloc(int); 102 | void dofree(void *); 103 | void error(enum errtype, char *, ...); 104 | void flushout(void); 105 | int fillbuf(Source *); 106 | int trigraph(Source *); 107 | int foldline(Source *); 108 | Nlist *lookup(Token *, int); 109 | void control(Tokenrow *); 110 | void dodefine(Tokenrow *); 111 | void doadefine(Tokenrow *, int); 112 | void doinclude(Tokenrow *); 113 | void doif(Tokenrow *, enum kwtype); 114 | void expand(Tokenrow *, Nlist *); 115 | void builtin(Tokenrow *, int); 116 | int gatherargs(Tokenrow *, Tokenrow **, int *); 117 | void substargs(Nlist *, Tokenrow *, Tokenrow **); 118 | void expandrow(Tokenrow *, char *); 119 | void maketokenrow(int, Tokenrow *); 120 | Tokenrow *copytokenrow(Tokenrow *, Tokenrow *); 121 | Token *growtokenrow(Tokenrow *); 122 | Tokenrow *normtokenrow(Tokenrow *); 123 | void adjustrow(Tokenrow *, int); 124 | void movetokenrow(Tokenrow *, Tokenrow *); 125 | void insertrow(Tokenrow *, int, Tokenrow *); 126 | void peektokens(Tokenrow *, char *); 127 | void doconcat(Tokenrow *); 128 | Tokenrow *stringify(Tokenrow *); 129 | int lookuparg(Nlist *, Token *); 130 | long eval(Tokenrow *, int); 131 | void genline(void); 132 | void setempty(Tokenrow *); 133 | void makespace(Tokenrow *); 134 | char *outnum(char *, int); 135 | int digit(int); 136 | uchar *newstring(uchar *, int, int); 137 | int checkhideset(int, Nlist *); 138 | void prhideset(int); 139 | int newhideset(int, Nlist *); 140 | int unionhideset(int, int); 141 | void iniths(void); 142 | void setobjname(char *); 143 | #define rowlen(tokrow) ((tokrow)->lp - (tokrow)->bp) 144 | 145 | extern char *outp; 146 | extern Token nltoken; 147 | extern Source *cursource; 148 | extern char *curtime; 149 | extern int incdepth; 150 | extern int ifdepth; 151 | extern int ifsatisfied[NIF]; 152 | extern int Mflag; 153 | extern int skipping; 154 | extern int verbose; 155 | extern int Cplusplus; 156 | extern Nlist *kwdefined; 157 | extern Includelist includelist[NINCLUDE]; 158 | extern char wd[]; 159 | -------------------------------------------------------------------------------- /doc/man1/lburg.1: -------------------------------------------------------------------------------- 1 | .TH LBURG 1 "local \- 11/30/94" 2 | .\" $Id: lburg.1,v 1.1.1.1 2004/03/24 04:37:34 sjp Exp $ 3 | .SH NAME 4 | lburg \- lcc's code-generator generator 5 | .SH SYNOPSIS 6 | .B lburg 7 | [ 8 | .I option 9 | ]... 10 | [ [ 11 | .I input 12 | ] 13 | .I output 14 | ] 15 | .br 16 | .SH DESCRIPTION 17 | .PP 18 | .I lburg 19 | reads an lcc-style BURG specification from 20 | .I input 21 | and writes a pattern-matching code generator to 22 | .IR output . 23 | If 24 | .I input 25 | is `\-' or is omitted, 26 | .I lburg 27 | reads the standard input; 28 | If 29 | .I output 30 | is `\-' or is omitted, 31 | .I lburg 32 | writes to the standard output. 33 | .PP 34 | .I lburg 35 | accepts specifications that conform to the following EBNF grammar. 36 | Terminals are enclosed in single quotes or are 37 | given in uppercase, all other symbols are nonterminals or English phrases, 38 | {X} denotes zero or more instances of X, and [X] denotes an optional X. 39 | .PP 40 | .nf 41 | .RS 42 | .ft CW 43 | spec: `%{' configuration `%}' { dcl } `%%' { rule } 44 | [ `%%' C code ] 45 | 46 | dcl: `%start' nonterm 47 | `%term' { ID `=' INT } 48 | 49 | rule: nonterm `:' tree template [ C expression ] 50 | 51 | tree: term `(' tree `,' tree `)' 52 | term `(' tree `)' 53 | term 54 | nonterm 55 | 56 | nonterm: ID 57 | 58 | template: `"' { any character except double quote } `"' 59 | .RE 60 | .fi 61 | .PP 62 | Specifications are structurally similar to 63 | .IR yacc 's. 64 | Text between 65 | `\f(CW%{\fP' 66 | and 67 | `\f(CW%}\fP' 68 | is called the configuration section; there may be several such segments. 69 | All are concatenated and copied verbatim into the head of the output. 70 | Text after the second 71 | `\f(CW%%\fP', 72 | if any, is also copied verbatim into the output, at the end. 73 | .PP 74 | Specifications consist of declarations, a 75 | `\f(CW%%\fP' 76 | separator, and rules. 77 | Input is line-oriented; each declaration and rule must appear on a separate line, 78 | and declarations must begin in column 1. 79 | Declarations declare terminals \(em the operators in subject 80 | trees \(em and associate a unique, positive external symbol 81 | number with each one. 82 | Nonterminals are declared by their presence 83 | on the left side of rules. The 84 | \f(CW%start\fP 85 | declaration optionally declares a nonterminal as the start symbol. 86 | In the grammar above, 87 | \f(CWterm\fP 88 | and 89 | \f(CWnonterm\fP 90 | denote identifiers that are terminals and nonterminals. 91 | .PP 92 | Rules define tree patterns in a fully parenthesized prefix 93 | form. Every nonterminal denotes a tree. 94 | Each operator has a fixed 95 | arity, which is inferred from the rules in which it is used. 96 | A chain rule is a rule whose pattern is another nonterminal. 97 | If no start symbol is declared, the nonterminal defined by the first rule is used. 98 | .PP 99 | Each rule ends with an expression that computes the cost of matching 100 | that rule; omitted costs 101 | default to zero. Costs of chain rules must be constants. 102 | .PP 103 | The configuration section configures the output 104 | for the trees being parsed and the client's environment. 105 | As shown, this section must define 106 | \f(CWNODEPTR_TYPE\fP 107 | to be a visible typedef symbol for a pointer to a 108 | node in the subject tree. 109 | The labeller invokes 110 | \f(CWOP_LABEL(p)\fP, 111 | \f(CWLEFT\_CHILD(p)\fP, and 112 | \f(CWRIGHT\_CHILD(p)\fP 113 | to read the operator and children from the node pointed to by \f(CWp\fP. 114 | If the configuration section defines these operations as macros, they are implemented in-line; 115 | otherwise, they must be implemented as functions. 116 | .PP 117 | The matcher 118 | computes and stores a single integral state in each node of the subject tree. 119 | The configuration section must define a macro 120 | \f(CWSTATE_LABEL(p)\fP 121 | to access the state field of the node pointed to 122 | by \f(CWp\fP. It must be large enough to hold a pointer, and 123 | a macro is required because it is used as an lvalue. 124 | .PP 125 | .SH OPTIONS 126 | .TP 127 | .BI \-p \ prefix 128 | .br 129 | .ns 130 | .TP 131 | .BI \-p prefix 132 | Use 133 | .I prefix 134 | as the disambiquating prefix for visible names and fields. 135 | The default is `\f(CW_\fP'. 136 | .TP 137 | .B \-T 138 | Arrange for 139 | .sp 140 | .nf 141 | .ft CW 142 | void _trace(NODEPTR_TYPE p, int eruleno, 143 | int cost, int bestcost); 144 | .sp 145 | .fi 146 | .ft R 147 | to be called at each successful match. 148 | \f(CWp\fP 149 | identifies the node and 150 | \f(CWeruleno\fP 151 | identifies the matching rule; the rules are numbered 152 | beginning at 1 in the order they appear in the input. 153 | \f(CWcost\fP 154 | is the cost of the match and 155 | \f(CWbestcost\fP 156 | is the cost of the best previous match. The current match 157 | wins only if 158 | \f(CWcost\fP 159 | is less than \f(CWbestcost\fP. 160 | 32767 represents the infinite cost of no previous match. 161 | \f(CW_trace\fP must be declared in the configuration section. 162 | .SH "SEE ALSO" 163 | .IR lcc (1) 164 | .PP 165 | C. W. Fraser and D. R. Hanson, 166 | .IR A Retargetable C Compiler: Design and Implementation , 167 | Benjamin/Cummings, Redwood City, CA, 1995, 168 | ISBN 0-8053-1670-1. Chapter 14. 169 | .PP 170 | C. W. Fraser, D. R. Hanson and T. A. Proebsting, 171 | `Engineering a simple, efficient code generator generator,' 172 | .I 173 | ACM Letters on Programming Languages and Systems 174 | .BR 1 , 175 | 3 (Sep. 1992), 213-226. 176 | .br 177 | .SH BUGS 178 | Mail bug reports along with the shortest input 179 | that exposes them to drh@cs.princeton.edu. 180 | -------------------------------------------------------------------------------- /lc3lib/scanf.asm: -------------------------------------------------------------------------------- 1 | 2 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 3 | ; void scanf(const char *format, ...) 4 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 5 | LC3_GFLAG scanf LC3_GFLAG .FILL lc3_scanf 6 | 7 | SCANF_PERCENT .FILL -37 8 | SCANF_C .FILL -99 9 | SCANF_D .FILL -100 10 | SCANF_S .FILL -115 11 | SCANF_0 .FILL -48 12 | SCANF_9 .FILL -57 13 | SCANF_MINUS .FILL -45 14 | SCANF_BUF .BLKW 6 15 | 16 | lc3_scanf 17 | ADD R6, R6, #-2 18 | STR R7, R6, #0 19 | 20 | ADD R6, R6, #-1 ;save R5 = bp 21 | STR R5, R6, #0 22 | ADD R5, R6, #-1 23 | 24 | ADD R6, R6, #-1 ;save R4 = gp 25 | STR R4, R6, #0 26 | 27 | ADD R5, R5, #4 ;cheating with the bp (no longer bp) 28 | LDR R4, R5, #0 ;got addr of format string 29 | 30 | 31 | 32 | 33 | SCANF_LOOP ;outer loop, R0=tmp register for use with GETC 34 | ;R2 holds either cur letter of format string or 35 | ;current addr to store a char, dec, or string 36 | 37 | 38 | 39 | LDR R2, R4, #0 40 | 41 | ADD R2, R2, #0 ;End of format string? (0x0000) 42 | BRz SCANF_DONE 43 | 44 | LD R1, SCANF_PERCENT 45 | ADD R0, R2, #0 46 | ADD R0, R0, R1 47 | BRnp SCANF_MATCHCHAR ;% not found 48 | 49 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;% found! 50 | ADD R4, R4, #1 ;R4 points to next char of format string 51 | LDR R2, R4, #0 52 | 53 | LD R1, SCANF_C 54 | ADD R0, R2, #0 ;next char = c? 55 | ADD R0, R0, R1 56 | BRnp SCANF_CHECKD 57 | 58 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%c found 59 | ADD R5, R5, #1 60 | LDR R2, R5, #0 ;R2 has addr for char to be read into 61 | 62 | GETC 63 | OUT 64 | STR R0, R2, #0 65 | 66 | ADD R4, R4, #1 67 | BRnzp SCANF_LOOP 68 | 69 | SCANF_CHECKD 70 | ;is it %d? 71 | LD R1, SCANF_D 72 | ADD R0, R2, #0 73 | ADD R0, R0, R1 74 | BRnp SCANF_STR 75 | 76 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%d found 77 | ;consider using vars to store reg 78 | ;registers 0,1,2,3,7 available as tmp regs 79 | 80 | 81 | ADD R6, R6, #-1 ;saving current ptr into format string 82 | STR R4, R6, #0 83 | 84 | ;ADD R6, R6, #-7 ;making 7byte buffer for ascbin 85 | ;ADD R4, R6, #0 ;ptr into that buffer 86 | LEA R4, SCANF_BUF 87 | LD R2, SCANF_0 88 | LD R1, SCANF_9 89 | 90 | SCANF_SCANNUM 91 | 92 | GETC 93 | OUT 94 | STR R0, R4, #0 ;Reading and storing typed char 95 | 96 | ADD R0, R2, R0 97 | BRZP SCANF_CHECKEDLOWER 98 | 99 | LDR R0, R4, #0 100 | LD R7, SCANF_MINUS 101 | ADD R0, R0, R7 102 | BRz SCANF_CHECKEDLOWER 103 | 104 | LEA R0, SCANF_BUF 105 | NOT R0, R0 106 | ADD R0, R0, #1 107 | ADD R0, R4, R0 108 | BRz SCANF_SCANNUM ;buffer is empty and wrong char, go to error? 109 | 110 | ADD R4, R4, #-1 ;fixme: need to save this char 111 | BRnzp SCANF_NUMDONE 112 | 113 | 114 | SCANF_CHECKEDLOWER 115 | 116 | LDR R0, R4, #0 117 | ADD R0, R1, R0 118 | BRNZ SCANF_CHECKEDUPPER 119 | 120 | LEA R0, SCANF_BUF 121 | NOT R0, R0 122 | ADD R0, R0, #1 123 | ADD R0, R4, R0 124 | BRz SCANF_SCANNUM ;buffer is empty and wrong char, go to error? 125 | 126 | ADD R4, R4, #-1 ;fixme: need to save this char 127 | BRnzp SCANF_NUMDONE 128 | 129 | SCANF_CHECKEDUPPER 130 | 131 | LEA R0, SCANF_BUF 132 | ADD R0, R0, #5 133 | 134 | NOT R0, R0 135 | ADD R0, R0, #1 136 | ADD R0, R4, R0 137 | BRz SCANF_NUMDONE ;buffer is full 138 | 139 | ADD R4, R4, #1 140 | BRnzp SCANF_SCANNUM 141 | 142 | SCANF_NUMDONE 143 | ;R4 points to last char entered in (ones digit) 144 | 145 | ;ADD R7, R6, #0 ;R7 points to the highest order digit 146 | LEA R7, SCANF_BUF 147 | LD R0, SCANF_MINUS 148 | LD R1, SCANF_BUF 149 | ADD R0, R0, R1 150 | BRnp SCANF_NOTMINUS 151 | ADD R7, R7, #1 ;fixme check for - - 152 | 153 | SCANF_NOTMINUS 154 | 155 | ;STR R2, R6, #-1 ;psuedo stored -'0' on stack 156 | AND R2, R2, #0 ;R2 acts as the acumulator 157 | 158 | SCANF_CALC 159 | 160 | LDR R0, R7, #0 161 | ;LDR R1, R6, #-1 162 | LD R1, SCANF_0 163 | ADD R0, R0, R1 164 | ADD R2, R2, R0 165 | 166 | NOT R1, R7 167 | ADD R1, R1, #1 168 | ADD R1, R4, R1 169 | BRz SCANF_CALCDONE 170 | ;R2 = 10*R2 171 | ADD R0, R2, #0 172 | AND R1, R1, #0 173 | ADD R1, R1, #9 ;R1 = counter 174 | 175 | SCANF_MULLOOP 176 | ADD R2, R2, R0 177 | ADD R1, R1, #-1 178 | BRnp SCANF_MULLOOP 179 | 180 | ADD R7, R7, #1 181 | BRnzp SCANF_CALC 182 | 183 | SCANF_CALCDONE 184 | 185 | LD R0, SCANF_MINUS 186 | LD R1, SCANF_BUF 187 | ADD R0, R0, R1 188 | BRnp SCANF_NOTNEG 189 | NOT R2, R2 190 | ADD R2, R2, #1 191 | 192 | SCANF_NOTNEG 193 | 194 | 195 | ADD R5, R5, #1 196 | LDR R0, R5, #0 197 | 198 | STR R2, R0, #0 ;store decimal number into address 199 | 200 | ;ADD R6, R6, #7 201 | 202 | LDR R4, R6, #0 203 | ADD R6, R6, #1 ;restoring current ptr into format string 204 | 205 | 206 | ADD R4, R4, #1 ;point to next element of format string 207 | BRnzp SCANF_LOOP 208 | 209 | 210 | SCANF_STR 211 | LD R1, SCANF_S 212 | ADD R0, R2, #0 213 | ADD R0, R0, R1 214 | BRnp SCANF_ERROR 215 | 216 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%s found 217 | ADD R6, R6, #-1 ;saving current ptr into format string 218 | STR R4, R6, #0 219 | 220 | ADD R5, R5, #1 ;getting starting addr of space for string to be read in 221 | LDR R4, R5, #0 222 | 223 | SCANSTRLOOP 224 | GETC 225 | OUT 226 | STR R0, R4, #0 ;Reading and storing typed char 227 | ADD R4, R4, #1 228 | 229 | ADD R0, R0, #-10 ;End of string? Looking for CR (0x000A) 230 | BRnp SCANSTRLOOP 231 | 232 | SCANSTRDONE 233 | AND R0, R0, #0 ;null terminate string 234 | STR R0, R4, #-1 235 | 236 | LDR R4, R6, #0 ;restore r4 237 | ADD R6, R6, #1 238 | 239 | ADD R4, R4, #1 240 | BRnzp SCANF_LOOP 241 | 242 | 243 | SCANF_MATCHCHAR 244 | ADD R4, R4, #1 245 | GETC 246 | OUT 247 | NOT R0, R0 248 | ADD R0, R0, #1 249 | ADD R0, R0, R2 250 | BRz SCANF_LOOP 251 | 252 | SCANF_ERROR 253 | SCANF_DONE 254 | 255 | LDR R4, R6, #0 ;restore R4 256 | ADD R6, R6, #1 257 | 258 | LDR R5, R6, #0 ;restore bp 259 | ADD R6, R6, #1 260 | 261 | LDR R7, R6, #0 ;restore ret addr 262 | ADD R6, R6, #1 263 | 264 | RET 265 | 266 | -------------------------------------------------------------------------------- /test/limitations/scanf.asm: -------------------------------------------------------------------------------- 1 | 2 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 3 | ; void scanf(const char *format, ...) 4 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 5 | LC3_GFLAG scanf LC3_GFLAG .FILL lc3_scanf 6 | 7 | SCANF_PERCENT .FILL -37 8 | SCANF_C .FILL -99 9 | SCANF_D .FILL -100 10 | SCANF_S .FILL -115 11 | SCANF_0 .FILL -48 12 | SCANF_9 .FILL -57 13 | SCANF_MINUS .FILL -45 14 | SCANF_BUF .BLKW 6 15 | 16 | lc3_scanf 17 | ADD R6, R6, #-2 18 | STR R7, R6, #0 19 | 20 | ADD R6, R6, #-1 ;save R5 = bp 21 | STR R5, R6, #0 22 | ADD R5, R6, #-1 23 | 24 | ADD R6, R6, #-1 ;save R4 = gp 25 | STR R4, R6, #0 26 | 27 | ADD R5, R5, #4 ;cheating with the bp (no longer bp) 28 | LDR R4, R5, #0 ;got addr of format string 29 | 30 | 31 | 32 | 33 | SCANF_LOOP ;outer loop, R0=tmp register for use with GETC 34 | ;R2 holds either cur letter of format string or 35 | ;current addr to store a char, dec, or string 36 | 37 | 38 | 39 | LDR R2, R4, #0 40 | 41 | ADD R2, R2, #0 ;End of format string? (0x0000) 42 | BRz SCANF_DONE 43 | 44 | LD R1, SCANF_PERCENT 45 | ADD R0, R2, #0 46 | ADD R0, R0, R1 47 | BRnp SCANF_MATCHCHAR ;% not found 48 | 49 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;% found! 50 | ADD R4, R4, #1 ;R4 points to next char of format string 51 | LDR R2, R4, #0 52 | 53 | LD R1, SCANF_C 54 | ADD R0, R2, #0 ;next char = c? 55 | ADD R0, R0, R1 56 | BRnp SCANF_CHECKD 57 | 58 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%c found 59 | ADD R5, R5, #1 60 | LDR R2, R5, #0 ;R2 has addr for char to be read into 61 | 62 | GETC 63 | OUT 64 | STR R0, R2, #0 65 | 66 | ADD R4, R4, #1 67 | BRnzp SCANF_LOOP 68 | 69 | SCANF_CHECKD 70 | ;is it %d? 71 | LD R1, SCANF_D 72 | ADD R0, R2, #0 73 | ADD R0, R0, R1 74 | BRnp SCANF_STR 75 | 76 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%d found 77 | ;consider using vars to store reg 78 | ;registers 0,1,2,3,7 available as tmp regs 79 | 80 | 81 | ADD R6, R6, #-1 ;saving current ptr into format string 82 | STR R4, R6, #0 83 | 84 | ;ADD R6, R6, #-7 ;making 7byte buffer for ascbin 85 | ;ADD R4, R6, #0 ;ptr into that buffer 86 | LEA R4, SCANF_BUF 87 | LD R2, SCANF_0 88 | LD R1, SCANF_9 89 | 90 | SCANF_SCANNUM 91 | 92 | GETC 93 | OUT 94 | STR R0, R4, #0 ;Reading and storing typed char 95 | 96 | ADD R0, R2, R0 97 | BRZP SCANF_CHECKEDLOWER 98 | 99 | LDR R0, R4, #0 100 | LD R7, SCANF_MINUS 101 | ADD R0, R0, R7 102 | BRz SCANF_CHECKEDLOWER 103 | 104 | LEA R0, SCANF_BUF 105 | NOT R0, R0 106 | ADD R0, R0, #1 107 | ADD R0, R4, R0 108 | BRz SCANF_SCANNUM ;buffer is empty and wrong char, go to error? 109 | 110 | ADD R4, R4, #-1 ;fixme: need to save this char 111 | BRnzp SCANF_NUMDONE 112 | 113 | 114 | SCANF_CHECKEDLOWER 115 | 116 | LDR R0, R4, #0 117 | ADD R0, R1, R0 118 | BRNZ SCANF_CHECKEDUPPER 119 | 120 | LEA R0, SCANF_BUF 121 | NOT R0, R0 122 | ADD R0, R0, #1 123 | ADD R0, R4, R0 124 | BRz SCANF_SCANNUM ;buffer is empty and wrong char, go to error? 125 | 126 | ADD R4, R4, #-1 ;fixme: need to save this char 127 | BRnzp SCANF_NUMDONE 128 | 129 | SCANF_CHECKEDUPPER 130 | 131 | LEA R0, SCANF_BUF 132 | ADD R0, R0, #5 133 | 134 | NOT R0, R0 135 | ADD R0, R0, #1 136 | ADD R0, R4, R0 137 | BRz SCANF_NUMDONE ;buffer is full 138 | 139 | ADD R4, R4, #1 140 | BRnzp SCANF_SCANNUM 141 | 142 | SCANF_NUMDONE 143 | ;R4 points to last char entered in (ones digit) 144 | 145 | ;ADD R7, R6, #0 ;R7 points to the highest order digit 146 | LEA R7, SCANF_BUF 147 | LD R0, SCANF_MINUS 148 | LD R1, SCANF_BUF 149 | ADD R0, R0, R1 150 | BRnp SCANF_NOTMINUS 151 | ADD R7, R7, #1 ;fixme check for - - 152 | 153 | SCANF_NOTMINUS 154 | 155 | ;STR R2, R6, #-1 ;psuedo stored -'0' on stack 156 | AND R2, R2, #0 ;R2 acts as the acumulator 157 | 158 | SCANF_CALC 159 | 160 | LDR R0, R7, #0 161 | ;LDR R1, R6, #-1 162 | LD R1, SCANF_0 163 | ADD R0, R0, R1 164 | ADD R2, R2, R0 165 | 166 | NOT R1, R7 167 | ADD R1, R1, #1 168 | ADD R1, R4, R1 169 | BRz SCANF_CALCDONE 170 | ;R2 = 10*R2 171 | ADD R0, R2, #0 172 | AND R1, R1, #0 173 | ADD R1, R1, #9 ;R1 = counter 174 | 175 | SCANF_MULLOOP 176 | ADD R2, R2, R0 177 | ADD R1, R1, #-1 178 | BRnp SCANF_MULLOOP 179 | 180 | ADD R7, R7, #1 181 | BRnzp SCANF_CALC 182 | 183 | SCANF_CALCDONE 184 | 185 | LD R0, SCANF_MINUS 186 | LD R1, SCANF_BUF 187 | ADD R0, R0, R1 188 | BRnp SCANF_NOTNEG 189 | NOT R2, R2 190 | ADD R2, R2, #1 191 | 192 | SCANF_NOTNEG 193 | 194 | 195 | ADD R5, R5, #1 196 | LDR R0, R5, #0 197 | 198 | STR R2, R0, #0 ;store decimal number into address 199 | 200 | ;ADD R6, R6, #7 201 | 202 | LDR R4, R6, #0 203 | ADD R6, R6, #1 ;restoring current ptr into format string 204 | 205 | 206 | ADD R4, R4, #1 ;point to next element of format string 207 | BRnzp SCANF_LOOP 208 | 209 | 210 | SCANF_STR 211 | LD R1, SCANF_S 212 | ADD R0, R2, #0 213 | ADD R0, R0, R1 214 | BRnp SCANF_ERROR 215 | 216 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%s found 217 | ADD R6, R6, #-1 ;saving current ptr into format string 218 | STR R4, R6, #0 219 | 220 | ADD R5, R5, #1 ;getting starting addr of space for string to be read in 221 | LDR R4, R5, #0 222 | 223 | SCANSTRLOOP 224 | GETC 225 | OUT 226 | STR R0, R4, #0 ;Reading and storing typed char 227 | ADD R4, R4, #1 228 | 229 | ADD R0, R0, #-10 ;End of string? Looking for CR (0x000A) 230 | BRnp SCANSTRLOOP 231 | 232 | SCANSTRDONE 233 | AND R0, R0, #0 ;null terminate string 234 | STR R0, R4, #-1 235 | 236 | LDR R4, R6, #0 ;restore r4 237 | ADD R6, R6, #1 238 | 239 | ADD R4, R4, #1 240 | BRnzp SCANF_LOOP 241 | 242 | 243 | SCANF_MATCHCHAR 244 | ADD R4, R4, #1 245 | GETC 246 | OUT 247 | NOT R0, R0 248 | ADD R0, R0, #1 249 | ADD R0, R0, R2 250 | BRz SCANF_LOOP 251 | 252 | SCANF_ERROR 253 | SCANF_DONE 254 | 255 | LDR R4, R6, #0 ;restore R4 256 | ADD R6, R6, #1 257 | 258 | LDR R5, R6, #0 ;restore bp 259 | ADD R6, R6, #1 260 | 261 | LDR R7, R6, #0 ;restore ret addr 262 | ADD R6, R6, #1 263 | 264 | RET 265 | 266 | -------------------------------------------------------------------------------- /src/tree.c: -------------------------------------------------------------------------------- 1 | #include "c.h" 2 | 3 | static char rcsid[] = "$Id: tree.c,v 1.1.1.1 2004/03/24 04:37:33 sjp Exp $"; 4 | 5 | int where = STMT; 6 | static int warn; 7 | static int nid = 1; /* identifies trees & nodes in debugging output */ 8 | static struct nodeid { 9 | int printed; 10 | Tree node; 11 | } ids[500]; /* if ids[i].node == p, then p's id is i */ 12 | 13 | static void printtree1(Tree, int, int); 14 | 15 | Tree tree(int op, Type type, Tree left, Tree right) { 16 | Tree p; 17 | 18 | NEW0(p, where); 19 | p->op = op; 20 | p->type = type; 21 | p->kids[0] = left; 22 | p->kids[1] = right; 23 | return p; 24 | } 25 | 26 | Tree texpr(Tree (*f)(int), int tok, int a) { 27 | int save = where; 28 | Tree p; 29 | 30 | where = a; 31 | p = (*f)(tok); 32 | where = save; 33 | return p; 34 | } 35 | static Tree root1(Tree p) { 36 | if (p == NULL) 37 | return p; 38 | if (p->type == voidtype) 39 | warn++; 40 | switch (generic(p->op)) { 41 | case COND: { 42 | Tree q = p->kids[1]; 43 | assert(q && q->op == RIGHT); 44 | if (p->u.sym && q->kids[0] && generic(q->kids[0]->op) == ASGN) 45 | q->kids[0] = root1(q->kids[0]->kids[1]); 46 | else 47 | q->kids[0] = root1(q->kids[0]); 48 | if (p->u.sym && q->kids[1] && generic(q->kids[1]->op) == ASGN) 49 | q->kids[1] = root1(q->kids[1]->kids[1]); 50 | else 51 | q->kids[1] = root1(q->kids[1]); 52 | p->u.sym = 0; 53 | if (q->kids[0] == 0 && q->kids[1] == 0) 54 | p = root1(p->kids[0]); 55 | } 56 | break; 57 | case AND: case OR: 58 | if ((p->kids[1] = root1(p->kids[1])) == 0) 59 | p = root1(p->kids[0]); 60 | break; 61 | case NOT: 62 | if (warn++ == 0) 63 | warning("expression with no effect elided\n"); 64 | return root1(p->kids[0]); 65 | case RIGHT: 66 | if (p->kids[1] == 0) 67 | return root1(p->kids[0]); 68 | if (p->kids[0] && p->kids[0]->op == CALL+B 69 | && p->kids[1] && p->kids[1]->op == INDIR+B) 70 | /* avoid premature release of the CALL+B temporary */ 71 | return p->kids[0]; 72 | if (p->kids[0] && p->kids[0]->op == RIGHT 73 | && p->kids[1] == p->kids[0]->kids[0]) 74 | /* de-construct e++ construction */ 75 | return p->kids[0]->kids[1]; 76 | p = tree(RIGHT, p->type, root1(p->kids[0]), root1(p->kids[1])); 77 | return p->kids[0] || p->kids[1] ? p : (Tree)0; 78 | case EQ: case NE: case GT: case GE: case LE: case LT: 79 | case ADD: case SUB: case MUL: case DIV: case MOD: 80 | case LSH: case RSH: case BAND: case BOR: case BXOR: 81 | if (warn++ == 0) 82 | warning("expression with no effect elided\n"); 83 | p = tree(RIGHT, p->type, root1(p->kids[0]), root1(p->kids[1])); 84 | return p->kids[0] || p->kids[1] ? p : (Tree)0; 85 | case INDIR: 86 | if (p->type->size == 0 && unqual(p->type) != voidtype) 87 | warning("reference to `%t' elided\n", p->type); 88 | if (isptr(p->kids[0]->type) && isvolatile(p->kids[0]->type->type)) 89 | warning("reference to `volatile %t' elided\n", p->type); 90 | /* fall thru */ 91 | case NEG: case BCOM: case FIELD: 92 | if (warn++ == 0) 93 | warning("expression with no effect elided\n"); 94 | return root1(p->kids[0]); 95 | case ADDRL: case ADDRG: case ADDRF: case CNST: 96 | if (needconst) 97 | return p; 98 | if (warn++ == 0) 99 | warning("expression with no effect elided\n"); 100 | return NULL; 101 | case CVF: 102 | if (optype(p->op) == I 103 | || p->type->size < p->kids[0]->type->size) 104 | if (warn++ == 0) 105 | warning("expression with no effect elided\n"); 106 | return root1(p->kids[0]); 107 | case CVI: 108 | if ((optype(p->op) == U || optype(p->op) == I) 109 | && p->type->size < p->kids[0]->type->size 110 | && specific(p->kids[0]->op) != CALL+I) 111 | if (warn++ == 0) 112 | warning("expression with no effect elided\n"); 113 | return root1(p->kids[0]); 114 | case CVU: case CVP: 115 | if (optype(p->op) == U && p->type->size < p->kids[0]->type->size 116 | || optype(p->op) == I && p->type->size <= p->kids[0]->type->size) 117 | if (warn++ == 0) 118 | warning("expression with no effect elided\n"); 119 | return root1(p->kids[0]); 120 | case ARG: case ASGN: case CALL: case JUMP: case LABEL: 121 | break; 122 | default: assert(0); 123 | } 124 | return p; 125 | } 126 | 127 | Tree root(Tree p) { 128 | warn = 0; 129 | return root1(p); 130 | } 131 | 132 | char *opname(int op) { 133 | static char *opnames[] = { 134 | "", 135 | "CNST", 136 | "ARG", 137 | "ASGN", 138 | "INDIR", 139 | "CVC", 140 | "CVD", 141 | "CVF", 142 | "CVI", 143 | "CVP", 144 | "CVS", 145 | "CVU", 146 | "NEG", 147 | "CALL", 148 | "*LOAD*", 149 | "RET", 150 | "ADDRG", 151 | "ADDRF", 152 | "ADDRL", 153 | "ADD", 154 | "SUB", 155 | "LSH", 156 | "MOD", 157 | "RSH", 158 | "BAND", 159 | "BCOM", 160 | "BOR", 161 | "BXOR", 162 | "DIV", 163 | "MUL", 164 | "EQ", 165 | "GE", 166 | "GT", 167 | "LE", 168 | "LT", 169 | "NE", 170 | "JUMP", 171 | "LABEL", 172 | "AND", 173 | "NOT", 174 | "OR", 175 | "COND", 176 | "RIGHT", 177 | "FIELD" 178 | }, *suffixes[] = { 179 | "0", "F", "D", "C", "S", "I", "U", "P", "V", "B", 180 | "10","11","12","13","14","15" 181 | }; 182 | 183 | if (generic(op) >= AND && generic(op) <= FIELD && opsize(op) == 0) 184 | return opnames[opindex(op)]; 185 | return stringf("%s%s%s", 186 | opindex(op) > 0 && opindex(op) < NELEMS(opnames) ? 187 | opnames[opindex(op)] : stringd(opindex(op)), 188 | suffixes[optype(op)], opsize(op) > 0 ? stringd(opsize(op)) : ""); 189 | } 190 | 191 | int nodeid(Tree p) { 192 | int i = 1; 193 | 194 | ids[nid].node = p; 195 | while (ids[i].node != p) 196 | i++; 197 | if (i == nid) 198 | ids[nid++].printed = 0; 199 | return i; 200 | } 201 | 202 | /* printed - return pointer to ids[id].printed */ 203 | int *printed(int id) { 204 | if (id) 205 | return &ids[id].printed; 206 | nid = 1; 207 | return 0; 208 | } 209 | 210 | /* printtree - print tree p on fd */ 211 | void printtree(Tree p, int fd) { 212 | (void)printed(0); 213 | printtree1(p, fd, 1); 214 | } 215 | 216 | /* printtree1 - recursively print tree p */ 217 | static void printtree1(Tree p, int fd, int lev) { 218 | FILE *f = fd == 1 ? stdout : stderr; 219 | int i; 220 | static char blanks[] = " "; 221 | 222 | if (p == 0 || *printed(i = nodeid(p))) 223 | return; 224 | fprint(f, "#%d%S%S", i, blanks, i < 10 ? 2 : i < 100 ? 1 : 0, blanks, lev); 225 | fprint(f, "%s %t", opname(p->op), p->type); 226 | *printed(i) = 1; 227 | for (i = 0; i < NELEMS(p->kids); i++) 228 | if (p->kids[i]) 229 | fprint(f, " #%d", nodeid(p->kids[i])); 230 | if (p->op == FIELD && p->u.field) 231 | fprint(f, " %s %d..%d", p->u.field->name, 232 | fieldsize(p->u.field) + fieldright(p->u.field), fieldright(p->u.field)); 233 | else if (generic(p->op) == CNST) 234 | fprint(f, " %s", vtoa(p->type, p->u.v)); 235 | else if (p->u.sym) 236 | fprint(f, " %s", p->u.sym->name); 237 | if (p->node) 238 | fprint(f, " node=%p", p->node); 239 | fprint(f, "\n"); 240 | for (i = 0; i < NELEMS(p->kids); i++) 241 | printtree1(p->kids[i], fd, lev + 1); 242 | } 243 | -------------------------------------------------------------------------------- /cpp/cpp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "cpp.h" 7 | 8 | #define OUTS 16384 9 | char outbuf[OUTS]; 10 | char *outp = outbuf; 11 | Source *cursource; 12 | int nerrs; 13 | struct token nltoken = { NL, 0, 0, 0, 1, (uchar*)"\n" }; 14 | char *curtime; 15 | int incdepth; 16 | int ifdepth; 17 | int ifsatisfied[NIF]; 18 | int skipping; 19 | 20 | char rcsid[] = "$Revision: 1.1.1.1 $ $Date: 2004/03/24 04:37:35 $"; 21 | 22 | int 23 | main(int argc, char **argv) 24 | { 25 | Tokenrow tr; 26 | time_t t; 27 | char ebuf[BUFSIZ]; 28 | 29 | setbuf(stderr, ebuf); 30 | t = time(NULL); 31 | curtime = ctime(&t); 32 | maketokenrow(3, &tr); 33 | expandlex(); 34 | setup(argc, argv); 35 | fixlex(); 36 | iniths(); 37 | genline(); 38 | process(&tr); 39 | flushout(); 40 | fflush(stderr); 41 | exit(nerrs > 0); 42 | return 0; 43 | } 44 | 45 | void 46 | process(Tokenrow *trp) 47 | { 48 | int anymacros = 0; 49 | 50 | for (;;) { 51 | if (trp->tp >= trp->lp) { 52 | trp->tp = trp->lp = trp->bp; 53 | outp = outbuf; 54 | anymacros |= gettokens(trp, 1); 55 | trp->tp = trp->bp; 56 | } 57 | if (trp->tp->type == END) { 58 | if (--incdepth>=0) { 59 | if (cursource->ifdepth) 60 | error(ERROR, 61 | "Unterminated conditional in #include"); 62 | unsetsource(); 63 | cursource->line += cursource->lineinc; 64 | trp->tp = trp->lp; 65 | genline(); 66 | continue; 67 | } 68 | if (ifdepth) 69 | error(ERROR, "Unterminated #if/#ifdef/#ifndef"); 70 | break; 71 | } 72 | if (trp->tp->type==SHARP) { 73 | trp->tp += 1; 74 | control(trp); 75 | } else if (!skipping && anymacros) 76 | expandrow(trp, NULL); 77 | if (skipping) 78 | setempty(trp); 79 | puttokens(trp); 80 | anymacros = 0; 81 | cursource->line += cursource->lineinc; 82 | if (cursource->lineinc>1) { 83 | genline(); 84 | } 85 | } 86 | } 87 | 88 | void 89 | control(Tokenrow *trp) 90 | { 91 | Nlist *np; 92 | Token *tp; 93 | 94 | tp = trp->tp; 95 | if (tp->type!=NAME) { 96 | if (tp->type==NUMBER) 97 | goto kline; 98 | if (tp->type != NL) 99 | error(ERROR, "Unidentifiable control line"); 100 | return; /* else empty line */ 101 | } 102 | if ((np = lookup(tp, 0))==NULL || (np->flag&ISKW)==0 && !skipping) { 103 | error(WARNING, "Unknown preprocessor control %t", tp); 104 | return; 105 | } 106 | if (skipping) { 107 | if ((np->flag&ISKW)==0) 108 | return; 109 | switch (np->val) { 110 | case KENDIF: 111 | if (--ifdepthifdepth; 114 | setempty(trp); 115 | return; 116 | 117 | case KIFDEF: 118 | case KIFNDEF: 119 | case KIF: 120 | if (++ifdepth >= NIF) 121 | error(FATAL, "#if too deeply nested"); 122 | ++cursource->ifdepth; 123 | return; 124 | 125 | case KELIF: 126 | case KELSE: 127 | if (ifdepth<=skipping) 128 | break; 129 | return; 130 | 131 | default: 132 | return; 133 | } 134 | } 135 | switch (np->val) { 136 | case KDEFINE: 137 | dodefine(trp); 138 | break; 139 | 140 | case KUNDEF: 141 | tp += 1; 142 | if (tp->type!=NAME || trp->lp - trp->bp != 4) { 143 | error(ERROR, "Syntax error in #undef"); 144 | break; 145 | } 146 | if ((np = lookup(tp, 0)) != NULL) 147 | np->flag &= ~ISDEFINED; 148 | break; 149 | 150 | case KPRAGMA: 151 | return; 152 | 153 | case KIFDEF: 154 | case KIFNDEF: 155 | case KIF: 156 | if (++ifdepth >= NIF) 157 | error(FATAL, "#if too deeply nested"); 158 | ++cursource->ifdepth; 159 | ifsatisfied[ifdepth] = 0; 160 | if (eval(trp, np->val)) 161 | ifsatisfied[ifdepth] = 1; 162 | else 163 | skipping = ifdepth; 164 | break; 165 | 166 | case KELIF: 167 | if (ifdepth==0) { 168 | error(ERROR, "#elif with no #if"); 169 | return; 170 | } 171 | if (ifsatisfied[ifdepth]==2) 172 | error(ERROR, "#elif after #else"); 173 | if (eval(trp, np->val)) { 174 | if (ifsatisfied[ifdepth]) 175 | skipping = ifdepth; 176 | else { 177 | skipping = 0; 178 | ifsatisfied[ifdepth] = 1; 179 | } 180 | } else 181 | skipping = ifdepth; 182 | break; 183 | 184 | case KELSE: 185 | if (ifdepth==0 || cursource->ifdepth==0) { 186 | error(ERROR, "#else with no #if"); 187 | return; 188 | } 189 | if (ifsatisfied[ifdepth]==2) 190 | error(ERROR, "#else after #else"); 191 | if (trp->lp - trp->bp != 3) 192 | error(ERROR, "Syntax error in #else"); 193 | skipping = ifsatisfied[ifdepth]? ifdepth: 0; 194 | ifsatisfied[ifdepth] = 2; 195 | break; 196 | 197 | case KENDIF: 198 | if (ifdepth==0 || cursource->ifdepth==0) { 199 | error(ERROR, "#endif with no #if"); 200 | return; 201 | } 202 | --ifdepth; 203 | --cursource->ifdepth; 204 | if (trp->lp - trp->bp != 3) 205 | error(WARNING, "Syntax error in #endif"); 206 | break; 207 | 208 | case KERROR: 209 | trp->tp = tp+1; 210 | error(WARNING, "#error directive: %r", trp); 211 | break; 212 | 213 | case KLINE: 214 | trp->tp = tp+1; 215 | expandrow(trp, ""); 216 | tp = trp->bp+2; 217 | kline: 218 | if (tp+1>=trp->lp || tp->type!=NUMBER || tp+3lp 219 | || (tp+3==trp->lp && ((tp+1)->type!=STRING)||*(tp+1)->t=='L')){ 220 | error(ERROR, "Syntax error in #line"); 221 | return; 222 | } 223 | cursource->line = atol((char*)tp->t)-1; 224 | if (cursource->line<0 || cursource->line>=32768) 225 | error(WARNING, "#line specifies number out of range"); 226 | tp = tp+1; 227 | if (tp+1lp) 228 | cursource->filename=(char*)newstring(tp->t+1,tp->len-2,0); 229 | return; 230 | 231 | case KDEFINED: 232 | error(ERROR, "Bad syntax for control line"); 233 | break; 234 | 235 | case KINCLUDE: 236 | doinclude(trp); 237 | trp->lp = trp->bp; 238 | return; 239 | 240 | case KEVAL: 241 | eval(trp, np->val); 242 | break; 243 | 244 | default: 245 | error(ERROR, "Preprocessor control `%t' not yet implemented", tp); 246 | break; 247 | } 248 | setempty(trp); 249 | return; 250 | } 251 | 252 | void * 253 | domalloc(int size) 254 | { 255 | void *p = malloc(size); 256 | 257 | if (p==NULL) 258 | error(FATAL, "Out of memory from malloc"); 259 | return p; 260 | } 261 | 262 | void 263 | dofree(void *p) 264 | { 265 | free(p); 266 | } 267 | 268 | void 269 | error(enum errtype type, char *string, ...) 270 | { 271 | va_list ap; 272 | char *cp, *ep; 273 | Token *tp; 274 | Tokenrow *trp; 275 | Source *s; 276 | int i; 277 | 278 | fprintf(stderr, "cpp: "); 279 | for (s=cursource; s; s=s->next) 280 | if (*s->filename) 281 | fprintf(stderr, "%s:%d ", s->filename, s->line); 282 | va_start(ap, string); 283 | for (ep=string; *ep; ep++) { 284 | if (*ep=='%') { 285 | switch (*++ep) { 286 | 287 | case 's': 288 | cp = va_arg(ap, char *); 289 | fprintf(stderr, "%s", cp); 290 | break; 291 | case 'd': 292 | i = va_arg(ap, int); 293 | fprintf(stderr, "%d", i); 294 | break; 295 | case 't': 296 | tp = va_arg(ap, Token *); 297 | fprintf(stderr, "%.*s", tp->len, tp->t); 298 | break; 299 | 300 | case 'r': 301 | trp = va_arg(ap, Tokenrow *); 302 | for (tp=trp->tp; tplp&&tp->type!=NL; tp++) { 303 | if (tp>trp->tp && tp->wslen) 304 | fputc(' ', stderr); 305 | fprintf(stderr, "%.*s", tp->len, tp->t); 306 | } 307 | break; 308 | 309 | default: 310 | fputc(*ep, stderr); 311 | break; 312 | } 313 | } else 314 | fputc(*ep, stderr); 315 | } 316 | va_end(ap); 317 | fputc('\n', stderr); 318 | if (type==FATAL) 319 | exit(1); 320 | if (type!=WARNING) 321 | nerrs = 1; 322 | fflush(stderr); 323 | } 324 | -------------------------------------------------------------------------------- /src/bytecode.c: -------------------------------------------------------------------------------- 1 | #include "c.h" 2 | #define I(f) b_##f 3 | 4 | static char rcsid[] = "$Id: bytecode.c,v 1.1.1.1 2004/03/24 04:37:33 sjp Exp $"; 5 | 6 | static void I(segment)(int n) { 7 | static int cseg; 8 | 9 | if (cseg != n) 10 | switch (cseg = n) { 11 | case CODE: print("code\n"); return; 12 | case DATA: print("data\n"); return; 13 | case BSS: print("bss\n"); return; 14 | case LIT: print("lit\n"); return; 15 | default: assert(0); 16 | } 17 | } 18 | 19 | static void I(address)(Symbol q, Symbol p, long n) { 20 | q->x.name = stringf("%s%s%D", p->x.name, n > 0 ? "+" : "", n); 21 | } 22 | 23 | static void I(defaddress)(Symbol p) { 24 | print("address %s\n", p->x.name); 25 | } 26 | 27 | static void I(defconst)(int suffix, int size, Value v) { 28 | switch (suffix) { 29 | case I: 30 | if (size > sizeof (int)) 31 | print("byte %d %D\n", size, v.i); 32 | else 33 | print("byte %d %d\n", size, v.i); 34 | return; 35 | case U: 36 | if (size > sizeof (unsigned)) 37 | print("byte %d %U\n", size, v.u); 38 | else 39 | print("byte %d %u\n", size, v.u); 40 | return; 41 | case P: print("byte %d %U\n", size, (unsigned long)v.p); return; 42 | case F: 43 | if (size == 4) { 44 | float f = v.d; 45 | print("byte 4 %u\n", *(unsigned *)&f); 46 | } else { 47 | double d = v.d; 48 | unsigned *p = (unsigned *)&d; 49 | print("byte 4 %u\n", p[swap]); 50 | print("byte 4 %u\n", p[1 - swap]); 51 | } 52 | return; 53 | } 54 | assert(0); 55 | } 56 | 57 | static void I(defstring)(int len, char *str) { 58 | char *s; 59 | 60 | for (s = str; s < str + len; s++) 61 | print("byte 1 %d\n", (*s)&0377); 62 | } 63 | 64 | static void I(defsymbol)(Symbol p) { 65 | if (p->scope == CONSTANTS) 66 | switch (optype(ttob(p->type))) { 67 | case I: p->x.name = stringf("%D", p->u.c.v.i); break; 68 | case U: p->x.name = stringf("%U", p->u.c.v.u); break; 69 | case P: p->x.name = stringf("%U", p->u.c.v.p); break; 70 | default: assert(0); 71 | } 72 | else if (p->scope >= LOCAL && p->sclass == STATIC) 73 | p->x.name = stringf("$%d", genlabel(1)); 74 | else if (p->scope == LABELS || p->generated) 75 | p->x.name = stringf("$%s", p->name); 76 | else 77 | p->x.name = p->name; 78 | } 79 | 80 | static void dumptree(Node p) { 81 | switch (specific(p->op)) { 82 | case ASGN+B: 83 | assert(p->kids[0]); 84 | assert(p->kids[1]); 85 | assert(p->syms[0]); 86 | dumptree(p->kids[0]); 87 | dumptree(p->kids[1]); 88 | print("%s %d\n", opname(p->op), p->syms[0]->u.c.v.u); 89 | return; 90 | case RET+V: 91 | assert(!p->kids[0]); 92 | assert(!p->kids[1]); 93 | print("%s\n", opname(p->op)); 94 | return; 95 | } 96 | switch (generic(p->op)) { 97 | case CNST: case ADDRG: case ADDRF: case ADDRL: case LABEL: 98 | assert(!p->kids[0]); 99 | assert(!p->kids[1]); 100 | assert(p->syms[0] && p->syms[0]->x.name); 101 | print("%s %s\n", opname(p->op), p->syms[0]->x.name); 102 | return; 103 | case CVF: case CVI: case CVP: case CVU: 104 | assert(p->kids[0]); 105 | assert(!p->kids[1]); 106 | assert(p->syms[0]); 107 | dumptree(p->kids[0]); 108 | print("%s %d\n", opname(p->op), p->syms[0]->u.c.v.i); 109 | return; 110 | case ARG: case BCOM: case NEG: case INDIR: case JUMP: case RET: 111 | assert(p->kids[0]); 112 | assert(!p->kids[1]); 113 | dumptree(p->kids[0]); 114 | print("%s\n", opname(p->op)); 115 | return; 116 | case CALL: 117 | assert(p->kids[0]); 118 | assert(!p->kids[1]); 119 | assert(optype(p->op) != B); 120 | dumptree(p->kids[0]); 121 | print("%s\n", opname(p->op)); 122 | return; 123 | case ASGN: case BOR: case BAND: case BXOR: case RSH: case LSH: 124 | case ADD: case SUB: case DIV: case MUL: case MOD: 125 | assert(p->kids[0]); 126 | assert(p->kids[1]); 127 | dumptree(p->kids[0]); 128 | dumptree(p->kids[1]); 129 | print("%s\n", opname(p->op)); 130 | return; 131 | case EQ: case NE: case GT: case GE: case LE: case LT: 132 | assert(p->kids[0]); 133 | assert(p->kids[1]); 134 | assert(p->syms[0]); 135 | assert(p->syms[0]->x.name); 136 | dumptree(p->kids[0]); 137 | dumptree(p->kids[1]); 138 | print("%s %s\n", opname(p->op), p->syms[0]->x.name); 139 | return; 140 | } 141 | assert(0); 142 | } 143 | 144 | static void I(emit)(Node p) { 145 | for (; p; p = p->link) 146 | dumptree(p); 147 | } 148 | 149 | static void I(export)(Symbol p) { 150 | print("export %s\n", p->x.name); 151 | } 152 | 153 | static void I(function)(Symbol f, Symbol caller[], Symbol callee[], int ncalls) { 154 | int i; 155 | 156 | (*IR->segment)(CODE); 157 | offset = 0; 158 | for (i = 0; caller[i] && callee[i]; i++) { 159 | offset = roundup(offset, caller[i]->type->align); 160 | caller[i]->x.name = callee[i]->x.name = stringf("%d", offset); 161 | caller[i]->x.offset = callee[i]->x.offset = offset; 162 | offset += caller[i]->type->size; 163 | } 164 | maxargoffset = maxoffset = argoffset = offset = 0; 165 | gencode(caller, callee); 166 | print("proc %s %d %d\n", f->x.name, maxoffset, maxargoffset); 167 | emitcode(); 168 | print("endproc %s %d %d\n", f->x.name, maxoffset, maxargoffset); 169 | 170 | } 171 | 172 | static void gen02(Node p) { 173 | assert(p); 174 | if (generic(p->op) == ARG) { 175 | assert(p->syms[0]); 176 | argoffset += (p->syms[0]->u.c.v.i < 4 ? 4 : p->syms[0]->u.c.v.i); 177 | } else if (generic(p->op) == CALL) { 178 | maxargoffset = (argoffset > maxargoffset ? argoffset : maxargoffset); 179 | argoffset = 0; 180 | } 181 | } 182 | 183 | static void gen01(Node p) { 184 | if (p) { 185 | gen01(p->kids[0]); 186 | gen01(p->kids[1]); 187 | gen02(p); 188 | } 189 | } 190 | 191 | static Node I(gen)(Node p) { 192 | Node q; 193 | 194 | assert(p); 195 | for (q = p; q; q = q->link) 196 | gen01(q); 197 | return p; 198 | } 199 | 200 | static void I(global)(Symbol p) { 201 | print("align %d\n", p->type->align > 4 ? 4 : p->type->align); 202 | print("LABELV %s\n", p->x.name); 203 | } 204 | 205 | static void I(import)(Symbol p) { 206 | print("import %s\n", p->x.name); 207 | } 208 | 209 | static void I(local)(Symbol p) { 210 | offset = roundup(offset, p->type->align); 211 | p->x.name = stringf("%d", offset); 212 | p->x.offset = offset; 213 | offset += p->type->size; 214 | } 215 | 216 | static void I(progbeg)(int argc, char *argv[]) {} 217 | 218 | static void I(progend)(void) {} 219 | 220 | static void I(space)(int n) { 221 | print("skip %d\n", n); 222 | } 223 | 224 | static void I(stabline)(Coordinate *cp) { 225 | static char *prevfile; 226 | static int prevline; 227 | 228 | if (cp->file && (prevfile == NULL || strcmp(prevfile, cp->file) != 0)) { 229 | print("file \"%s\"\n", prevfile = cp->file); 230 | prevline = 0; 231 | } 232 | if (cp->y != prevline) 233 | print("line %d\n", prevline = cp->y); 234 | } 235 | 236 | #define b_blockbeg blockbeg 237 | #define b_blockend blockend 238 | 239 | Interface bytecodeIR = { 240 | 1, 1, 0, /* char */ 241 | 2, 2, 0, /* short */ 242 | 4, 4, 0, /* int */ 243 | 4, 4, 0, /* long */ 244 | 4, 4, 0, /* long long */ 245 | 4, 4, 1, /* float */ 246 | 8, 8, 1, /* double */ 247 | 8, 8, 1, /* long double */ 248 | 4, 4, 0, /* T* */ 249 | 0, 4, 0, /* struct */ 250 | 0, /* little_endian */ 251 | 0, /* mulops_calls */ 252 | 0, /* wants_callb */ 253 | 0, /* wants_argb */ 254 | 1, /* left_to_right */ 255 | 0, /* wants_dag */ 256 | 0, /* unsigned_char */ 257 | I(address), 258 | I(blockbeg), 259 | I(blockend), 260 | I(defaddress), 261 | I(defconst), 262 | I(defstring), 263 | I(defsymbol), 264 | I(emit), 265 | I(export), 266 | I(function), 267 | I(gen), 268 | I(global), 269 | I(import), 270 | I(local), 271 | I(progbeg), 272 | I(progend), 273 | I(segment), 274 | I(space), 275 | 0, /* I(stabblock) */ 276 | 0, /* I(stabend) */ 277 | 0, /* I(stabfend) */ 278 | 0, /* I(stabinit) */ 279 | I(stabline), 280 | 0, /* I(stabsym) */ 281 | 0, /* I(stabtype) */ 282 | }; 283 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | #include "c.h" 2 | 3 | static char rcsid[] = "$Name: $($Id: main.c,v 1.1.1.1 2004/03/24 04:37:33 sjp Exp $)"; 4 | 5 | static void typestab(Symbol, void *); 6 | 7 | static void stabline(Coordinate *); 8 | static void stabend(Coordinate *, Symbol, Coordinate **, Symbol *, Symbol *); 9 | Interface *IR = NULL; 10 | 11 | int Aflag; /* >= 0 if -A specified */ 12 | int Pflag; /* != 0 if -P specified */ 13 | int glevel; /* == [0-9] if -g[0-9] specified */ 14 | int xref; /* != 0 for cross-reference data */ 15 | Symbol YYnull; /* _YYnull symbol if -n or -nvalidate specified */ 16 | Symbol YYcheck; /* _YYcheck symbol if -nvalidate,check specified */ 17 | 18 | static char *comment; 19 | static Interface stabIR; 20 | static char *currentfile; /* current file name */ 21 | static int currentline; /* current line number */ 22 | static FILE *srcfp; /* stream for current file, if non-NULL */ 23 | static int srcpos; /* position of srcfp, if srcfp is non-NULL */ 24 | int main(int argc, char *argv[]) { 25 | int i, j; 26 | for (i = argc - 1; i > 0; i--) 27 | if (strncmp(argv[i], "-target=", 8) == 0) 28 | break; 29 | if (i > 0) { 30 | char *s = strchr(argv[i], '\\'); 31 | if (s != NULL) 32 | *s = '/'; 33 | for (j = 0; bindings[j].name && bindings[j].ir; j++) 34 | if (strcmp(&argv[i][8], bindings[j].name) == 0) { 35 | IR = bindings[j].ir; 36 | break; 37 | } 38 | if (s != NULL) 39 | *s = '\\'; 40 | } 41 | if (!IR) { 42 | fprint(stderr, "%s: unknown target", argv[0]); 43 | if (i > 0) 44 | fprint(stderr, " `%s'", &argv[i][8]); 45 | fprint(stderr, "; must specify one of\n"); 46 | for (i = 0; bindings[i].name; i++) 47 | fprint(stderr, "\t-target=%s\n", bindings[i].name); 48 | exit(EXIT_FAILURE); 49 | } 50 | init(argc, argv); 51 | t = gettok(); 52 | (*IR->progbeg)(argc, argv); 53 | for (i = 1; i < argc; i++) 54 | if (strcmp(argv[i], "-n") == 0) { 55 | if (!YYnull) { 56 | YYnull = install(string("_YYnull"), &globals, GLOBAL, PERM); 57 | YYnull->type = func(voidptype, NULL, 1); 58 | YYnull->sclass = EXTERN; 59 | (*IR->defsymbol)(YYnull); 60 | } 61 | } else if (strncmp(argv[i], "-n", 2) == 0) { /* -nvalid[,check] */ 62 | char *p = strchr(argv[i], ','); 63 | if (p) { 64 | YYcheck = install(string(p+1), &globals, GLOBAL, PERM); 65 | YYcheck->type = func(voidptype, NULL, 1); 66 | YYcheck->sclass = EXTERN; 67 | (*IR->defsymbol)(YYcheck); 68 | p = stringn(argv[i]+2, p - (argv[i]+2)); 69 | } else 70 | p = string(argv[i]+2); 71 | YYnull = install(p, &globals, GLOBAL, PERM); 72 | YYnull->type = func(voidptype, NULL, 1); 73 | YYnull->sclass = EXTERN; 74 | (*IR->defsymbol)(YYnull); 75 | } else { 76 | profInit(argv[i]); 77 | traceInit(argv[i]); 78 | } 79 | if (glevel && IR->stabinit) 80 | (*IR->stabinit)(firstfile, argc, argv); 81 | program(); 82 | if (events.end) 83 | apply(events.end, NULL, NULL); 84 | memset(&events, 0, sizeof events); 85 | if (glevel || xref) { 86 | Symbol symroot = NULL; 87 | Coordinate src; 88 | foreach(types, GLOBAL, typestab, &symroot); 89 | foreach(identifiers, GLOBAL, typestab, &symroot); 90 | src.file = firstfile; 91 | src.x = 0; 92 | src.y = lineno; 93 | if ((glevel > 2 || xref) && IR->stabend) 94 | (*IR->stabend)(&src, symroot, 95 | ltov(&loci, PERM), 96 | ltov(&symbols, PERM), NULL); 97 | else if (IR->stabend) 98 | (*IR->stabend)(&src, NULL, NULL, NULL, NULL); 99 | } 100 | finalize(); 101 | (*IR->progend)(); 102 | deallocate(PERM); 103 | return errcnt > 0; 104 | } 105 | /* main_init - process program arguments */ 106 | void main_init(int argc, char *argv[]) { 107 | char *infile = NULL, *outfile = NULL; 108 | int i; 109 | static int inited; 110 | 111 | if (inited) 112 | return; 113 | inited = 1; 114 | type_init(argc, argv); 115 | for (i = 1; i < argc; i++) 116 | if (strcmp(argv[i], "-g") == 0 || strcmp(argv[i], "-g2") == 0) 117 | glevel = 2; 118 | else if (strncmp(argv[i], "-g", 2) == 0) { /* -gn[,x] */ 119 | char *p = strchr(argv[i], ','); 120 | glevel = atoi(argv[i]+2); 121 | if (p) { 122 | comment = p + 1; 123 | if (glevel == 0) 124 | glevel = 1; 125 | if (stabIR.stabline == NULL) { 126 | stabIR.stabline = IR->stabline; 127 | stabIR.stabend = IR->stabend; 128 | IR->stabline = stabline; 129 | IR->stabend = stabend; 130 | } 131 | } 132 | } else if (strcmp(argv[i], "-x") == 0) 133 | xref++; 134 | else if (strcmp(argv[i], "-A") == 0) { 135 | ++Aflag; 136 | } else if (strcmp(argv[i], "-P") == 0) 137 | Pflag++; 138 | else if (strcmp(argv[i], "-w") == 0) 139 | wflag++; 140 | else if (strcmp(argv[i], "-v") == 0) 141 | fprint(stderr, "%s %s\n", argv[0], rcsid); 142 | else if (strncmp(argv[i], "-s", 2) == 0) 143 | density = strtod(&argv[i][2], NULL); 144 | else if (strncmp(argv[i], "-errout=", 8) == 0) { 145 | FILE *f = fopen(argv[i]+8, "w"); 146 | if (f == NULL) { 147 | fprint(stderr, "%s: can't write errors to `%s'\n", argv[0], argv[i]+8); 148 | exit(EXIT_FAILURE); 149 | } 150 | fclose(f); 151 | f = freopen(argv[i]+8, "w", stderr); 152 | assert(f); 153 | } else if (strncmp(argv[i], "-e", 2) == 0) { 154 | int x; 155 | if ((x = strtol(&argv[i][2], NULL, 0)) > 0) 156 | errlimit = x; 157 | } else if (strncmp(argv[i], "-little_endian=", 15) == 0) 158 | IR->little_endian = argv[i][15] - '0'; 159 | else if (strncmp(argv[i], "-mulops_calls=", 18) == 0) 160 | IR->mulops_calls = argv[i][18] - '0'; 161 | else if (strncmp(argv[i], "-wants_callb=", 13) == 0) 162 | IR->wants_callb = argv[i][13] - '0'; 163 | else if (strncmp(argv[i], "-wants_argb=", 12) == 0) 164 | IR->wants_argb = argv[i][12] - '0'; 165 | else if (strncmp(argv[i], "-left_to_right=", 15) == 0) 166 | IR->left_to_right = argv[i][15] - '0'; 167 | else if (strncmp(argv[i], "-wants_dag=", 11) == 0) 168 | IR->wants_dag = argv[i][11] - '0'; 169 | else if (*argv[i] != '-' || strcmp(argv[i], "-") == 0) { 170 | if (infile == NULL) 171 | infile = argv[i]; 172 | else if (outfile == NULL) 173 | outfile = argv[i]; 174 | } 175 | 176 | if (infile != NULL && strcmp(infile, "-") != 0 177 | && freopen(infile, "r", stdin) == NULL) { 178 | fprint(stderr, "%s: can't read `%s'\n", argv[0], infile); 179 | exit(EXIT_FAILURE); 180 | } 181 | if (outfile != NULL && strcmp(outfile, "-") != 0 182 | && freopen(outfile, "w", stdout) == NULL) { 183 | fprint(stderr, "%s: can't write `%s'\n", argv[0], outfile); 184 | exit(EXIT_FAILURE); 185 | } 186 | } 187 | /* typestab - emit stab entries for p */ 188 | static void typestab(Symbol p, void *cl) { 189 | if (*(Symbol *)cl == 0 && p->sclass && p->sclass != TYPEDEF) 190 | *(Symbol *)cl = p; 191 | if ((p->sclass == TYPEDEF || p->sclass == 0) && IR->stabtype) 192 | (*IR->stabtype)(p); 193 | } 194 | 195 | /* stabline - emit source code for source coordinate *cp */ 196 | static void stabline(Coordinate *cp) { 197 | if (cp->file && cp->file != currentfile) { 198 | if (srcfp) 199 | fclose(srcfp); 200 | currentfile = cp->file; 201 | srcfp = fopen(currentfile, "r"); 202 | srcpos = 0; 203 | currentline = 0; 204 | } 205 | if (currentline != cp->y && srcfp) { 206 | char buf[512]; 207 | if (srcpos > cp->y) { 208 | rewind(srcfp); 209 | srcpos = 0; 210 | } 211 | for ( ; srcpos < cp->y; srcpos++) 212 | if (fgets(buf, sizeof buf, srcfp) == NULL) { 213 | fclose(srcfp); 214 | srcfp = NULL; 215 | break; 216 | } 217 | if (srcfp && srcpos == cp->y) 218 | print("%s%s", comment, buf); 219 | } 220 | currentline = cp->y; 221 | if (stabIR.stabline) 222 | (*stabIR.stabline)(cp); 223 | } 224 | 225 | static void stabend(Coordinate *cp, Symbol p, Coordinate **cpp, Symbol *sp, Symbol *stab) { 226 | if (stabIR.stabend) 227 | (*stabIR.stabend)(cp, p, cpp, sp, stab); 228 | if (srcfp) 229 | fclose(srcfp); 230 | } 231 | -------------------------------------------------------------------------------- /src/prof.c: -------------------------------------------------------------------------------- 1 | #include "c.h" 2 | 3 | static char rcsid[] = "$Id: prof.c,v 1.1.1.1 2004/03/24 04:37:33 sjp Exp $"; 4 | 5 | struct callsite { 6 | char *file, *name; 7 | union coordinate { 8 | unsigned int coord; 9 | struct { unsigned int y:16,x:10,index:6; } le; 10 | struct { unsigned int index:6,x:10,y:16; } be; 11 | } u; 12 | }; 13 | struct func { 14 | struct func *link; 15 | struct caller *callers; 16 | char *name; 17 | union coordinate src; 18 | }; 19 | struct map { /* source code map; 200 coordinates/map */ 20 | int size; 21 | union coordinate u[200]; 22 | }; 23 | 24 | int npoints; /* # of execution points if -b specified */ 25 | int ncalled = -1; /* #times prof.out says current function was called */ 26 | static Symbol YYlink; /* symbol for file's struct _bbdata */ 27 | static Symbol YYcounts; /* symbol for _YYcounts if -b specified */ 28 | static List maplist; /* list of struct map *'s */ 29 | static List filelist; /* list of file names */ 30 | static Symbol funclist; /* list of struct func *'s */ 31 | static Symbol afunc; /* current function's struct func */ 32 | 33 | /* bbpad - emit space, if necessary, to make size%align == 0; return new size */ 34 | static int bbpad(int size, int align) { 35 | if (size%align) { 36 | (*IR->space)(align - size%align); 37 | size = roundup(size, align); 38 | } 39 | return size; 40 | } 41 | 42 | /* bbcall - build tree to set _callsite at call site *cp, emit call site data */ 43 | static void bbcall(Symbol yycounts, Coordinate *cp, Tree *e) { 44 | static Symbol caller; 45 | Value v; 46 | union coordinate u; 47 | Symbol p = genident(STATIC, array(voidptype, 0, 0), GLOBAL); 48 | Tree t; 49 | 50 | defglobal(p, LIT); 51 | defpointer(cp->file ? mkstr(cp->file)->u.c.loc : (Symbol)0); 52 | defpointer(mkstr(cfunc->name)->u.c.loc); 53 | if (IR->little_endian) { 54 | u.le.x = cp->x; 55 | u.le.y = cp->y; 56 | } else { 57 | u.be.x = cp->x; 58 | u.be.y = cp->y; 59 | } 60 | (*IR->defconst)(U, unsignedtype->size, (v.u = u.coord, v)); 61 | bbpad(2*voidptype->size + unsignedtype->size, p->type->align); 62 | if (caller == 0) { 63 | caller = mksymbol(EXTERN, "_caller", ptr(voidptype)); 64 | caller->defined = 0; 65 | } 66 | for (t = *e; generic(t->op) != CALL; t = t->kids[0]) 67 | assert(t->op == RIGHT || !t->kids[1]); 68 | assert(generic(t->op) == CALL); 69 | t = tree(t->op, t->type, 70 | tree(RIGHT, t->kids[0]->type, 71 | t->kids[0], 72 | tree(RIGHT, t->kids[0]->type, asgn(caller, idtree(p)), t->kids[0])), 73 | t->kids[1]); 74 | for ( ; generic((*e)->op) != CALL; e = &(*e)->kids[0]) 75 | ; 76 | *e = t; 77 | } 78 | 79 | /* bbentry - return tree for _prologue(&afunc, &YYlink)' */ 80 | static void bbentry(Symbol yylink, Symbol f, void *ignore) { 81 | static Symbol prologue; 82 | 83 | afunc = genident(STATIC, array(voidptype, 4, 0), GLOBAL); 84 | if (prologue == 0) { 85 | prologue = mksymbol(EXTERN, "_prologue", ftype(inttype, voidptype, voidptype, NULL)); 86 | prologue->defined = 0; 87 | } 88 | walk(vcall(prologue, voidtype, pointer(idtree(afunc)), pointer(idtree(yylink)), NULL), 0, 0); 89 | } 90 | 91 | /* bbexit - return tree for _epilogue(&afunc)' */ 92 | static void bbexit(Symbol yylink, Symbol f, Tree e) { 93 | static Symbol epilogue; 94 | 95 | if (epilogue == 0) { 96 | epilogue = mksymbol(EXTERN, "_epilogue", ftype(inttype, voidptype, NULL)); 97 | epilogue->defined = 0; 98 | } 99 | walk(vcall(epilogue, voidtype, pointer(idtree(afunc)), NULL), 0, 0); 100 | } 101 | 102 | /* bbfile - add file to list of file names, return its index */ 103 | static int bbfile(char *file) { 104 | if (file) { 105 | List lp; 106 | int i = 1; 107 | if ((lp = filelist) != NULL) 108 | do { 109 | lp = lp->link; 110 | if (((Symbol)lp->x)->u.c.v.p == file) 111 | return i; 112 | i++; 113 | } while (lp != filelist); 114 | filelist = append(mkstr(file), filelist); 115 | return i; 116 | } 117 | return 0; 118 | } 119 | 120 | /* bbfunc - emit function name and src coordinates */ 121 | static void bbfunc(Symbol yylink, Symbol f, void *ignore) { 122 | Value v; 123 | union coordinate u; 124 | 125 | defglobal(afunc, DATA); 126 | defpointer(funclist); 127 | defpointer(NULL); 128 | defpointer(mkstr(f->name)->u.c.loc); 129 | if (IR->little_endian) { 130 | u.le.x = f->u.f.pt.x; 131 | u.le.y = f->u.f.pt.y; 132 | u.le.index = bbfile(f->u.f.pt.file); 133 | } else { 134 | u.be.x = f->u.f.pt.x; 135 | u.be.y = f->u.f.pt.y; 136 | u.be.index = bbfile(f->u.f.pt.file); 137 | } 138 | (*IR->defconst)(U, unsignedtype->size, (v.u = u.coord, v)); 139 | bbpad(3*voidptype->size + unsignedtype->size, afunc->type->align); 140 | funclist = afunc; 141 | } 142 | 143 | /* bbincr - build tree to increment execution point at *cp */ 144 | static void bbincr(Symbol yycounts, Coordinate *cp, Tree *e) { 145 | struct map *mp = maplist->x; 146 | Tree t; 147 | 148 | if (needconst) 149 | return; 150 | /* append *cp to source map */ 151 | if (mp->size >= NELEMS(mp->u)) { 152 | NEW(mp, PERM); 153 | mp->size = 0; 154 | maplist = append(mp, maplist); 155 | } 156 | if (IR->little_endian) { 157 | mp->u[mp->size].le.x = cp->x; 158 | mp->u[mp->size].le.y = cp->y; 159 | mp->u[mp->size++].le.index = bbfile(cp->file); 160 | } else { 161 | mp->u[mp->size].be.x = cp->x; 162 | mp->u[mp->size].be.y = cp->y; 163 | mp->u[mp->size++].be.index = bbfile(cp->file); 164 | } 165 | t = incr('+', rvalue((*optree['+'])(ADD, pointer(idtree(yycounts)), 166 | consttree(npoints++, inttype))), consttree(1, inttype)); 167 | if (*e) 168 | *e = tree(RIGHT, (*e)->type, t, *e); 169 | else 170 | *e = t; 171 | } 172 | 173 | /* bbvars - emit definition for basic block counting data */ 174 | static void bbvars(Symbol yylink, void *ignore, void *ignore2) { 175 | int i, j, n = npoints; 176 | Value v; 177 | struct map **mp; 178 | Symbol coords, files, *p; 179 | 180 | if (!YYcounts && !yylink) 181 | return; 182 | if (YYcounts) { 183 | if (n <= 0) 184 | n = 1; 185 | YYcounts->type = array(inttype, n, 0); 186 | defglobal(YYcounts, BSS); 187 | (*IR->space)(YYcounts->type->size); 188 | } 189 | files = genident(STATIC, array(charptype, 1, 0), GLOBAL); 190 | defglobal(files, LIT); 191 | for (p = ltov(&filelist, PERM); *p; p++) 192 | defpointer((*p)->u.c.loc); 193 | defpointer(NULL); 194 | coords = genident(STATIC, array(unsignedtype, n, 0), GLOBAL); 195 | defglobal(coords, LIT); 196 | for (i = n, mp = ltov(&maplist, PERM); *mp; i -= (*mp)->size, mp++) 197 | for (j = 0; j < (*mp)->size; j++) 198 | (*IR->defconst)(U, unsignedtype->size, (v.u = (*mp)->u[j].coord, v)); 199 | if (i > 0) 200 | (*IR->space)(i*coords->type->type->size); 201 | (*IR->defconst)(U, unsignedtype->size, (v.u = 0, v)); 202 | defglobal(yylink, DATA); 203 | defpointer(NULL); 204 | (*IR->defconst)(U, inttype->size, (v.u = n, v)); 205 | bbpad(voidptype->size + inttype->size, yylink->type->align); 206 | defpointer(YYcounts); 207 | defpointer(coords); 208 | defpointer(files); 209 | defpointer(funclist); 210 | } 211 | 212 | /* profInit - initialize basic block profiling options */ 213 | void profInit(char *arg) { 214 | if (strncmp(arg, "-a", 2) == 0) { 215 | if (ncalled == -1 216 | && process(arg[2] ? &arg[2] : "prof.out") > 0) 217 | ncalled = 0; 218 | } else if ((strcmp(arg, "-b") == 0 219 | || strcmp(arg, "-C") == 0) && YYlink == 0) { 220 | YYlink = genident(STATIC, array(voidptype, 0, 0), GLOBAL); 221 | attach((Apply)bbentry, YYlink, &events.entry); 222 | attach((Apply)bbexit, YYlink, &events.returns); 223 | attach((Apply)bbfunc, YYlink, &events.exit); 224 | attach((Apply)bbvars, YYlink, &events.end); 225 | if (strcmp(arg, "-b") == 0) { 226 | YYcounts = genident(STATIC, array(inttype, 0, 0), GLOBAL); 227 | maplist = append(allocate(sizeof (struct map), PERM), maplist); 228 | ((struct map *)maplist->x)->size = 0; 229 | attach((Apply)bbcall, YYcounts, &events.calls); 230 | attach((Apply)bbincr, YYcounts, &events.points); 231 | } 232 | } 233 | } 234 | --------------------------------------------------------------------------------