| 2563 | | \chapter*{Appendix: \Algol 60 Compiler} |
|---|
| 2564 | | |
|---|
| 2565 | | Installation, supported GCCs, usual stuff. |
|---|
| 2566 | | |
|---|
| | 2557 | \chapter*{Appendix: The \Algol 60 Compiler} |
|---|
| | 2558 | |
|---|
| | 2559 | \section*{Requirements} |
|---|
| | 2560 | |
|---|
| | 2561 | The \Algol 60 GCC front end has following build requirements: |
|---|
| | 2562 | |
|---|
| | 2563 | \begin{itemize} |
|---|
| | 2564 | \item GCC 4.2.x with resolved dependencies. GCC 4.1.x or earlier will |
|---|
| | 2565 | NOT work. You will need either complete GCC package |
|---|
| | 2566 | (e.g. \file{gcc-4.2.0.tar.bz2}), or core package and testsuite |
|---|
| | 2567 | (e.g. \file{gcc-core-4.2.0.tar.bz2} and |
|---|
| | 2568 | \file{gcc-testsuite-4.2.0.tar.bz2}). |
|---|
| | 2569 | \item Flex 2.5.31 or newer |
|---|
| | 2570 | \item Bison 2.3 or newer |
|---|
| | 2571 | \item \literal{libga60} wraps around target-native \literal{libc} and |
|---|
| | 2572 | \literal{libm}, which have to be available on target site. |
|---|
| | 2573 | \end{itemize} |
|---|
| | 2574 | |
|---|
| | 2575 | \section*{Supported Arches} |
|---|
| | 2576 | |
|---|
| | 2577 | \file{gcc-algol} was successfully compiled and testsuite passed on |
|---|
| | 2578 | systems with following triplets: |
|---|
| | 2579 | |
|---|
| | 2580 | \begin{itemize} |
|---|
| | 2581 | \item i686-pc-linux-gnu |
|---|
| | 2582 | \item ia64-unknwon-linux-gnu |
|---|
| | 2583 | \item mips-sgi-irix6.5 |
|---|
| | 2584 | \end{itemize} |
|---|
| | 2585 | |
|---|
| | 2586 | \section*{Build Process} |
|---|
| | 2587 | |
|---|
| | 2588 | Only a straight build (i.e. no Canadian Crosses) is supported at the |
|---|
| | 2589 | moment. (Or at least tested. Chances are the compiler will work also |
|---|
| | 2590 | for non-native setups.) First, prepare a source tree: |
|---|
| | 2591 | |
|---|
| | 2592 | \program{\ind\=\+ |
|---|
| | 2593 | \$ ls\\ |
|---|
| | 2594 | {\em gcc-4.2.0.tar.bz2 gcc-algol60-0.2.tar.bz2}\\ |
|---|
| | 2595 | \$ tar xjf gcc-4.2.0.tar.bz2\\ |
|---|
| | 2596 | \$ pushd gcc-4.2.0\\ |
|---|
| | 2597 | \$ tar xjf ../gcc-algol60-0.3.tar.bz2\\ |
|---|
| | 2598 | \$ patch -p1 $<$ gcc-4.2.0-toplevel.patch\\ |
|---|
| | 2599 | {\em patching file configure}\\ |
|---|
| | 2600 | {\em patching file Makefile.in}\\ |
|---|
| | 2601 | {\em patching file Makefile.def}\\ |
|---|
| | 2602 | \$ popd} |
|---|
| | 2603 | |
|---|
| | 2604 | Then prepare for the build: |
|---|
| | 2605 | |
|---|
| | 2606 | \program{\ind\=\+ |
|---|
| | 2607 | \$ mkdir build-4.2.0\\ |
|---|
| | 2608 | \$ cd build-4.2.0\\ |
|---|
| | 2609 | \$ ../gcc-4.2.0/configure \=-{}-prefix=`pwd`/../inst-4.2.0/ $\backslash$\\ |
|---|
| | 2610 | \>-{}-enable-version-specific-runtime-libs $\backslash$\\ |
|---|
| | 2611 | \>-{}-enable-languages=c,algol60 $\backslash$\\ |
|---|
| | 2612 | \>-{}-disable-werror} |
|---|
| | 2613 | |
|---|
| | 2614 | The \option{-{}-disable-werror} part is unfortunate, but necessary: |
|---|
| | 2615 | the parser and lexer \file{.c} files, generated from yacc and flex |
|---|
| | 2616 | respectively, currently generate a lot of warnings. |
|---|
| | 2617 | |
|---|
| | 2618 | Finally, do a build itself: |
|---|
| | 2619 | |
|---|
| | 2620 | \program{\ind\=\+ |
|---|
| | 2621 | \$ gmake -j 4\\ |
|---|
| | 2622 | {\em ...lots of output...}\\ |
|---|
| | 2623 | {\em gmake[1]: Leaving directory `/tmp/build-4.2.0'}} |
|---|
| | 2624 | |
|---|
| | 2625 | (The \option{-j} constant determines how many parallel processes make |
|---|
| | 2626 | should launch. You will want to adjust this value depending on number |
|---|
| | 2627 | of CPUs or cores of your computer.) |
|---|
| | 2628 | |
|---|
| | 2629 | You can test GCC as a whole with \literal{gmake check}, or just \Algol |
|---|
| | 2630 | 60 front end with \literal{gmake -C gcc check-algol60}. If you so |
|---|
| | 2631 | wish, you can install the front end with \literal{gmake install}, it |
|---|
| | 2632 | will end up in configured \option{-{}-prefix} directory. |
|---|
| | 2633 | |
|---|
| | 2634 | \section*{Using \file{gcc-algol}} |
|---|
| | 2635 | |
|---|
| | 2636 | From now on, you can use it as an ordinary GCC |
|---|
| | 2637 | command\footnote{Actually, in the case as illustrated, the compiler |
|---|
| | 2638 | would likely end up in a directory outside \literal{PATH} and |
|---|
| | 2639 | \literal{LD\_LIBRARY\_PATH}. You may need to adjust these |
|---|
| | 2640 | variables.}: |
|---|
| | 2641 | |
|---|
| | 2642 | \program{\ind\=\+ |
|---|
| | 2643 | \$ which ga60-4.2.0\\ |
|---|
| | 2644 | {\em /tmp/inst-4.2.0/bin/ga60-4.2.0}\\ |
|---|
| | 2645 | \$ ga60-4.2.0 --version $|$ head -n 1\\ |
|---|
| | 2646 | {\em ga60-4.2.0 (GCC) 4.2.0}\\ |
|---|
| | 2647 | \$ cat x.a60\\ |
|---|
| | 2648 | {\em 'begin' puts(`Yay, it works!'); 'end';}\\ |
|---|
| | 2649 | \$ ga60-4.2.0 x.a60 -o x\\ |
|---|
| | 2650 | \$ ./x\\ |
|---|
| | 2651 | {\em Yay, it works!}} |
|---|
| | 2652 | |
|---|
| | 2653 | Let's have a look at the compiled binary: |
|---|
| | 2654 | |
|---|
| | 2655 | \program{\ind\=\+ |
|---|
| | 2656 | \$ readelf -a x $|$ grep NEEDED\\ |
|---|
| | 2657 | {\em 0x0000000000000001} \={\em{}(NEEDED)} \={\em{}Shared library: [libga60.so.1]}\\ |
|---|
| | 2658 | {\em 0x0000000000000001} \>{\em{}(NEEDED)} \>{\em{}Shared library: [libm.so.6.1]}\\ |
|---|
| | 2659 | {\em 0x0000000000000001} \>{\em{}(NEEDED)} \>{\em{}Shared library: [libc.so.6.1]}} |
|---|
| | 2660 | |
|---|
| | 2661 | The binary itself depends on \file{libm} and \file{libc}. These |
|---|
| | 2662 | dependencies are injected into the binary by the linking hook |
|---|
| | 2663 | \function{lang\_specific\_driver}. If we link the binary with gcc |
|---|
| | 2664 | driver, our hook will not be called, and only \file{libc} will be |
|---|
| | 2665 | linked in: |
|---|
| | 2666 | |
|---|
| | 2667 | \program{\ind\=\+ |
|---|
| | 2668 | \$ gcc-4.2.0 x.a60 -o x -lga60\\ |
|---|
| | 2669 | \$ readelf -a x $|$ grep NEEDED\\ |
|---|
| | 2670 | {\em{}0x0000000000000001} \={\em{}(NEEDED)} \={\em{}Shared library: [libga60.so.1]}\\ |
|---|
| | 2671 | {\em{}0x0000000000000001} \>{\em{}(NEEDED)} \>{\em{}Shared library: [libc.so.6.1]}} |
|---|
| | 2672 | |
|---|
| | 2673 | Under current setup, where all \Algol 60 services are provided by {\em |
|---|
| | 2674 | shared} \file{libga60}, explicit dependence on \file{libm} is |
|---|
| | 2675 | unnecessary, and even wrong---\file{libga60} itself should have these |
|---|
| | 2676 | dependencies (and has!). However, \file{libga60} doesn't have to be |
|---|
| | 2677 | shared, and in that case \file{libm} has to be brought in explicitly. |
|---|
| | 2678 | |
|---|
| | 2679 | \file{gcc-algol} uses a preprocessor, and understands traditional |
|---|
| | 2680 | preprocessing directives. The preprocessor is not run by default, |
|---|
| | 2681 | only when the file extension is \file{.A60} or \file{.ALG} (i.e. upper |
|---|
| | 2682 | case. This notion is used also for assembly and fortran source |
|---|
| | 2683 | files). For example, let's have the two files as shown on figures |
|---|
| | 2684 | \ref{Figure++PreprocessX} and \ref{Figure++PreprocessY}. |
|---|
| | 2685 | |
|---|
| | 2686 | \begin{figure} |
|---|
| | 2687 | \begin{verbatim} |
|---|
| | 2688 | #if !defined(_ALGOL60_) || !defined(USK) |
|---|
| | 2689 | # error That does not compute. |
|---|
| | 2690 | #else |
|---|
| | 2691 | 'begin' |
|---|
| | 2692 | /* funky C-like comment */ |
|---|
| | 2693 | # include "y.ALG" |
|---|
| | 2694 | 'end'; |
|---|
| | 2695 | #endif |
|---|
| | 2696 | \end{verbatim} |
|---|
| | 2697 | \caption{Preprocessing: Example file x.ALG} |
|---|
| | 2698 | \label{Figure++PreprocessX} |
|---|
| | 2699 | \end{figure} |
|---|
| | 2700 | |
|---|
| | 2701 | \begin{figure} |
|---|
| | 2702 | \begin{verbatim} |
|---|
| | 2703 | |
|---|
| | 2704 | |
|---|
| | 2705 | 'string' a; |
|---|
| | 2706 | \end{verbatim} |
|---|
| | 2707 | \caption{Preprocessing: Example file y.ALG} |
|---|
| | 2708 | \label{Figure++PreprocessY} |
|---|
| | 2709 | \end{figure} |
|---|
| | 2710 | |
|---|
| | 2711 | \program{\ind\=\+ |
|---|
| | 2712 | \$ ga60-4.2.0 ./x.ALG\\ |
|---|
| | 2713 | {\em{}./x.ALG:2: error: \#error That does not compute.}\\ |
|---|
| | 2714 | \$ ga60-4.2.0 -DUSK ./x.ALG\\ |
|---|
| | 2715 | {\em{}./y.ALG:1: error: type 'string' is invalid in this context.}\\ |
|---|
| | 2716 | \$ ga60-4.2.0 -DUSK -M ./x.ALG\\ |
|---|
| | 2717 | {\em{}x.o: x.ALG y.ALG}\\ |
|---|
| | 2718 | \$ ga60-4.2.0 -DUSK -E ./x.ALG\\ |
|---|
| | 2719 | {\em{}\# 1 "./x.ALG"}\\ |
|---|
| | 2720 | {\em{}\# 1 "$<$built-in$>$"}\\ |
|---|
| | 2721 | {\em ... more preprocessed output ... }} |
|---|
| | 2722 | |
|---|
| | 2723 | The errors at the first and second commands are intentional. |
|---|
| | 2724 | The first is here to display that it's possible to pass in your own |
|---|
| | 2725 | defines. The second shows that \file{gcc-algol} correctly tracks |
|---|
| | 2726 | files and line numbers: even though the erroneous line appears as |
|---|
| | 2727 | twelfth line of preprocessed output, error message is located |
|---|
| | 2728 | properly. |
|---|
| | 2729 | |
|---|
| | 2730 | Most of this work is done by GCC itself: GCC launches preprocessor, |
|---|
| | 2731 | decides that the processing should be stopped after that when |
|---|
| | 2732 | \option{-E} is passed in, and GCC generated the make dependency rule. |
|---|