








              How to Use the Plan 9 C Compiler


                          Rob Pike
                  rob@plan9.bell-labs.com






_IIII_nnnn_tttt_rrrr_oooo_dddd_uuuu_cccc_tttt_iiii_oooo_nnnn

     The C compiler on Plan 9 is a wholly  new  program;  in
fact  it  was  the  first piece of software written for what
would eventually become Plan 9 from Bell Labs.   Programmers
familiar  with  existing  C  compilers will find a number of
differences in both the language the Plan 9 compiler accepts
and in how the compiler is used.

     The compiler is really a set of compilers, one for each
architecture  - MIPS, SPARC, Motorola 68020, Intel 386, etc.
- that accept a dialect of ANSI C  and  efficiently  produce
fairly good code for the target machine.  There is a packag-
ing of the compiler that accepts strict ANSI C for  a  POSIX
environment,  but this document focuses on the native Plan 9
environment, that in which all the system source and  almost
all the utilities are written.

_SSSS_oooo_uuuu_rrrr_cccc_eeee

     The language accepted by the compilers is the core ANSI
C language with some modest extensions, a greatly simplified
preprocessor, a smaller library that includes  system  calls
and related facilities, and a completely different structure
for include files.

     Official ANSI C accepts the old (K&R) style of declara-
tions  for  functions; the Plan 9 compilers are more demand-
ing.  Without an explicit run-time flag ( -_BBBB) whose  use  is
discouraged, the compilers insist on new-style function dec-
larations, that is, prototypes for function arguments.   The
function  declarations  in  the libraries' include files are
all in the new style so the interfaces are checked  at  com-
pile  time.   For C programmers who have not yet switched to
function prototypes the clumsy syntax may seem repellent but
the  payoff  in  stronger  typing is substantial.  Those who
wish to import existing software to Plan 9 are urged to  use
the opportunity to update their code.

     The compilers include an integrated  preprocessor  that


                       April 5, 2011






                           - 2 -


accepts  the  familiar    #_iiii_nnnn_cccc_llll_uuuu_dddd_eeee,  #_dddd_eeee_ffff_iiii_nnnn_eeee for macros both
with and without arguments,   #_uuuu_nnnn_dddd_eeee_ffff,    #_llll_iiii_nnnn_eeee,    #_iiii_ffff_dddd_eeee_ffff,
#_iiii_ffff_nnnn_dddd_eeee_ffff,  and    #_eeee_nnnn_dddd_iiii_ffff.   It supports neither  #_iiii_ffff nor  ##,
although it does honor a few  #_pppp_rrrr_aaaa_gggg_mmmm_aaaa_ssss.  The  #_iiii_ffff  directive
was omitted because it greatly complicates the preprocessor,
is never necessary, and is usually abused.  Conditional com-
pilation  in general makes code hard to understand; the Plan
9 source uses it sparingly.   Also,  because  the  compilers
remove  dead code, regular  _iiii_ffff statements with constant con-
ditions are more readable equivalents to  many    #_iiii_ffff_ssss.   To
compile  imported code ineluctably fouled by  #_iiii_ffff there is a
separate command,  /_bbbb_iiii_nnnn/_cccc_pppp_pppp, that  implements  the  complete
ANSI C preprocessor specification.

     Include files fall into two  groups:  machine-dependent
and   machine-independent.   The  machine-independent  files
occupy the directory  /_ssss_yyyy_ssss/_iiii_nnnn_cccc_llll_uuuu_dddd_eeee; the others are placed in
a   directory   appropriate   to   the  machine,  such  as
/_mmmm_iiii_pppp_ssss/_iiii_nnnn_cccc_llll_uuuu_dddd_eeee.  The  compiler  searches  for  include  files
first  in  the  machine-dependent  directory and then in the
machine-independent directory.  At the time of writing there
are  thirty-one  machine-independent  include  files and two
(per machine) machine-dependent ones:  <_uuuu_rrrr_eeee_gggg._hhhh> and   <_uuuu._hhhh>.
The  first  describes  the layout of registers on the system
stack, for use by the debugger.   The  second  defines  some
architecture-dependent  types  such  as  _jjjj_mmmm_pppp__bbbb_uuuu_ffff for  _ssss_eeee_tttt_jjjj_mmmm_pppp
and the  _vvvv_aaaa__aaaa_rrrr_gggg and  _vvvv_aaaa__llll_iiii_ssss_tttt macros for  handling  arguments
to variadic functions, as well as a set of  _tttt_yyyy_pppp_eeee_dddd_eeee_ffff abbrevi-
ations for  _uuuu_nnnn_ssss_iiii_gggg_nnnn_eeee_dddd  _ssss_hhhh_oooo_rrrr_tttt and so on.

     Here is an excerpt from  /_6666_8888_0000_2222_0000/_iiii_nnnn_cccc_llll_uuuu_dddd_eeee/_uuuu._hhhh:

  #define nil             ((void*)0)
  typedef unsigned short  ushort;
  typedef unsigned char   uchar;
  typedef unsigned long   ulong;
  typedef unsigned int    uint;
  typedef   signed char   schar;
  typedef long long       vlong;

  typedef long    jmp_buf[2];
  #define JMPBUFSP        0
  #define JMPBUFPC        1
  #define JMPBUFDPC       0

Plan 9 programs use  _nnnn_iiii_llll for the  name  of  the  zero-valued
pointer.  The type  _vvvv_llll_oooo_nnnn_gggg is the largest integer type avail-
able; on most architectures it is a 64-bit value.  A  couple
of other types in  <_uuuu._hhhh> are  _uuuu_3333_2222_iiii_nnnn_tttt, which is guaranteed to
have exactly 32 bits (a possibility  on  all  the  supported
architectures)  and    _mmmm_pppp_dddd_iiii_gggg_iiii_tttt,  which is used by the multi-
precision math package  <_mmmm_pppp._hhhh>.  The  #_dddd_eeee_ffff_iiii_nnnn_eeee constants per-
mit  an  architecture-independent  (but  compiler-dependent)
implementation  of  stack-switching  using    _ssss_eeee_tttt_jjjj_mmmm_pppp  and


                       April 5, 2011






                           - 3 -


_llll_oooo_nnnn_gggg_jjjj_mmmm_pppp.

     Every Plan 9 C program begins

  #include <u.h>

because all the  other  installed  header  files  use  the
_tttt_yyyy_pppp_eeee_dddd_eeee_ffff_ssss declared in  <_uuuu._hhhh>.

     In strict ANSI C, include files are grouped to  collect
related  functions  in  a  single file: one for string func-
tions, one for memory functions, one for I/O, and  none  for
system  calls.  Each include file is protected by an  #_iiii_ffff_dddd_eeee_ffff
to guarantee its contents are  seen  by  the  compiler  only
once.   Plan 9 takes a different approach.  Other than a few
include files that define external formats such as archives,
the  files  in   /_ssss_yyyy_ssss/_iiii_nnnn_cccc_llll_uuuu_dddd_eeee correspond to  _llll_iiii_bbbb_rrrr_aaaa_rrrr_iiii_eeee_ssss. If a
program is using a library, it  includes  the  corresponding
header.   The  default C library comprises string functions,
memory functions, and so on, largely as in ANSI C, some for-
matted  I/O  routines, plus all the system calls and related
functions.  To use these functions, one must   #_iiii_nnnn_cccc_llll_uuuu_dddd_eeee  the
file   <_llll_iiii_bbbb_cccc._hhhh>, which in turn must follow  <_uuuu._hhhh>, to define
their prototypes for the compiler.   Here  is  the  complete
source to the traditional first C program:

  #include <u.h>
  #include <libc.h>

  void
  main(void)
  {
          print("hello world\n");
          exits(0);
  }

The  _pppp_rrrr_iiii_nnnn_tttt routine and its relatives   _ffff_pppp_rrrr_iiii_nnnn_tttt  and    _ssss_pppp_rrrr_iiii_nnnn_tttt
resemble  the  similarly-named functions in Standard I/O but
are not attached to a specific I/O library.  In Plan 9  _mmmm_aaaa_iiii_nnnn
is  not integer-valued; it should call  _eeee_xxxx_iiii_tttt_ssss, which takes a
string argument (or null; here ANSI C promotes the 0 to  a
_cccc_hhhh_aaaa_rrrr*).   All  these functions are, of course, documented in
the Programmer's Manual.

     To use  _pppp_rrrr_iiii_nnnn_tttt_ffff,  <_ssss_tttt_dddd_iiii_oooo._hhhh> must be included  to  define
the function prototype for  _pppp_rrrr_iiii_nnnn_tttt_ffff:










                       April 5, 2011






                           - 4 -


  #include <u.h>
  #include <libc.h>
  #include <stdio.h>

  void
  main(int argc, char *argv[])
  {
          printf("%s: hello world; argc = %d\n", argv[0], argc);
          exits(0);
  }

In practice, Standard I/O is not used much in Plan  9.   I/O
libraries are discussed in a later section of this document.

     There are libraries for handling  regular  expressions,
raster graphics, windows, and so on, and each has an associ-
ated include file.  The manual for each library states which
include  files  are  needed.   The  files  are not protected
against multiple inclusion and themselves contain no nested
#_iiii_nnnn_cccc_llll_uuuu_dddd_eeee_ssss.   Instead  the programmer is expected to sort out
the requirements and to  #_iiii_nnnn_cccc_llll_uuuu_dddd_eeee the necessary  files  once
at  the  top of each source file.  In practice this is triv-
ial: this way of handling include files is  so  straightfor-
ward  that it is rare for a source file to contain more than
half a dozen  #_iiii_nnnn_cccc_llll_uuuu_dddd_eeee_ssss.

     The compilers do their own register allocation so the
_rrrr_eeee_gggg_iiii_ssss_tttt_eeee_rrrr  keyword  is  ignored.   For  different  reasons,
_vvvv_oooo_llll_aaaa_tttt_iiii_llll_eeee and  _cccc_oooo_nnnn_ssss_tttt are also ignored.

     To make it easier to share  code  with  other  systems,
Plan  9  has  a version of the compiler,  _pppp_cccc_cccc, that provides
the standard ANSI C  preprocessor,  headers,  and  libraries
with  POSIX extensions.   _PPPP_cccc_cccc is recommended only when broad
external portability is mandated.  It compiles slower,  pro-
duces  slower code (it takes extra work to simulate POSIX on
Plan 9), eliminates those parts of the Plan 9 interface  not
related to POSIX, and illustrates the clumsiness of an envi-
ronment designed by committee.   _PPPP_cccc_cccc is  described  in  more
detail  in      _AAAA_PPPP_EEEE-_TTTT_hhhh_eeee  _AAAA_NNNN_SSSS_IIII/_PPPP_OOOO_SSSS_IIII_XXXX  _EEEE_nnnn_vvvv_iiii_rrrr_oooo_nnnn_mmmm_eeee_nnnn_tttt,  by Howard
Trickey.

_PPPP_rrrr_oooo_cccc_eeee_ssss_ssss

     Each CPU architecture supported by Plan 9 is identified
by  a  single,  arbitrary,  alphanumeric  character:   _kkkk for
SPARC,  _qqqq for Motorola Power PC 630 and 640,  _vvvv for MIPS,  _1111
for  Motorola 68000,  _2222 for Motorola 68020 and 68040,  _5555 for
Acorn ARM 7500,  _6666 for Intel 960,  _7777 for DEC Alpha,   _8888  for
Intel  386,  and  _9999 for AMD 29000.  The character labels the
support  tools  and  files  for  that   architecture.    For
instance,  for  the 68020 the compiler is  _2222_cccc, the assembler
is  _2222_aaaa, the link editor/loader is  _2222_llll, the object files  are
suffixed  ._2222, and the default name for an executable file is


                       April 5, 2011






                           - 5 -


 _2222._oooo_uuuu_tttt.  Before we can use the compiler we therefore need to
know  which  machine we are compiling for.  The next section
explains how this decision is made; for the moment assume we
are building 68020 binaries and make the mental substitution
for  _2222 appropriate to the machine you are actually using.

     To convert source to an executable binary is a two-step
process.   First  run the compiler,  _2222_cccc, on the source, say
_ffff_iiii_llll_eeee._cccc, to generate an object file  _ffff_iiii_llll_eeee._2222.   Then  run  the
loader,    _2222_llll,  to generate an executable  _2222._oooo_uuuu_tttt that may be
run (on a 680X0 machine):

  2c file.c
  2l file.2
  2.out

The loader automatically links with whatever  libraries  the
program  needs,  usually including the standard C library as
defined by  <_llll_iiii_bbbb_cccc._hhhh>.  Of course  the  compiler  and  loader
have  lots of options, both familiar and new; see the manual
for details.  The compiler does not generate  an  executable
automatically;  the  output of the compiler must be given to
the loader.  Since most compilation is done under  the  con-
trol of  _mmmm_kkkk (see below), this is rarely an inconvenience.

     The distribution  of  work  between  the  compiler  and
loader  is  unusual.  The compiler integrates preprocessing,
parsing,  register  allocation,  code  generation  and  some
assembly.  Combining these tasks in a single program is part
of the reason for the  compiler's  efficiency.   The  loader
does  instruction  selection,  branch  folding,  instruction
scheduling, and writes the final executable.   There  is  no
separate  C preprocessor and no assembler in the usual pipe-
line.  Instead the intermediate object  file  (here  a    ._2222
file)  is  a type of binary assembly language.  The instruc-
tions in the intermediate format are not  exactly  those  in
the  machine.  For example, on the 68020 the object file may
specify a MOVE instruction but the loader will  decide  just
which variant of the MOVE instruction - MOVE immediate, MOVE
quick, MOVE address, etc. - is most efficient.

     The assembler,  _2222_aaaa, is just a  translator  between  the
textual  and  binary representations of the object file for-
mat.  It is not an assembler in the traditional  sense.   It
has  limited  macro capabilities (the same as the integral C
preprocessor in the compiler), clumsy  syntax,  and  minimal
error  checking.  For instance, the assembler will accept an
instruction (such as memory-to-memory MOVE on the MIPS) that
the  machine does not actually support; only when the output
of the assembler is passed to the loader will the  error  be
discovered.   The  assembler  is  intended  only for writing
things that need access to instructions  invisible  from  C,
such  as  the machine-dependent part of an operating system;
very little code in Plan 9 is in assembly language.


                       April 5, 2011






                           - 6 -


     The compilers take an option  -_SSSS that  causes  them  to
print  on their standard output the generated code in a for-
mat acceptable as input  to  the  assemblers.   This  is  of
course  merely  a formatting of the data in the object file;
therefore the assembler is just an ASCII-to-binary converter
for  this format.  Other than the specific instructions, the
input to the assemblers is largely architecture-independent;
see  ``A Manual for the Plan 9 Assembler'', by Rob Pike, for
more information.

     The loader is an integral part of the compilation  pro-
cess.   Each  library  header  file contains a  #_pppp_rrrr_aaaa_gggg_mmmm_aaaa that
tells the loader the name of the associated archive;  it  is
not  necessary  to tell the loader which libraries a program
uses.  The C run-time startup is found, by default, in the C
library.   The  loader  starts  with  an  undefined symbol,
__mmmm_aaaa_iiii_nnnn, that is resolved by pulling in the  run-time  startup
code  from  the library.  (The loader undefines  __mmmm_aaaa_iiii_nnnn_pppp when
profiling is enabled, to  force  loading  of  the  profiling
start-up instead.)

     Unlike its counterpart on other  systems,  the  Plan  9
loader  rearranges  data to optimize access.  This means the
order of variables in the loaded program is unrelated to its
order  in  the  source.   Most programs don't care, but some
assume that, for example, the variables declared by

  int a;
  int b;

will appear at adjacent addresses in  memory.   On  Plan  9,
they won't.

_HHHH_eeee_tttt_eeee_rrrr_oooo_gggg_eeee_nnnn_eeee_iiii_tttt_yyyy

     When the system starts or a user logs in  the  environ-
ment is configured so the appropriate binaries are available
in  /_bbbb_iiii_nnnn.  The configuration process  is  controlled  by  an
environment  variable,  $_cccc_pppp_uuuu_tttt_yyyy_pppp_eeee, with value such as  _mmmm_iiii_pppp_ssss,
_6666_8888_0000_2222_0000,  _3333_8888_6666, or  _ssss_pppp_aaaa_rrrr_cccc.  For each architecture  there  is  a
directory in the root, with the appropriate name, that holds
the binary and library files for that architecture.   Thus
/_mmmm_iiii_pppp_ssss/_llll_iiii_bbbb  contains  the object code libraries for MIPS pro-
grams,  /_mmmm_iiii_pppp_ssss/_iiii_nnnn_cccc_llll_uuuu_dddd_eeee holds MIPS-specific include files, and
  /_mmmm_iiii_pppp_ssss/_bbbb_iiii_nnnn  has  the  MIPS  binaries.   These  binaries are
attached to  /_bbbb_iiii_nnnn at boot time by binding  /$_cccc_pppp_uuuu_tttt_yyyy_pppp_eeee/_bbbb_iiii_nnnn to
/_bbbb_iiii_nnnn, so  /_bbbb_iiii_nnnn always contains the correct files.

     The MIPS compiler,  _vvvv_cccc, by definition  produces  object
files for the MIPS architecture, regardless of the architec-
ture of the machine on which the compiler is running.  There
is  a  version  of    _vvvv_cccc  compiled  for  each architecture:
/_mmmm_iiii_pppp_ssss/_bbbb_iiii_nnnn/_vvvv_cccc,  /_6666_8888_0000_2222_0000/_bbbb_iiii_nnnn/_vvvv_cccc,   /_ssss_pppp_aaaa_rrrr_cccc/_bbbb_iiii_nnnn/_vvvv_cccc,  and  so  on,
each  capable  of  producing MIPS object files regardless of


                       April 5, 2011






                           - 7 -


the native instruction set.  If one is running on a SPARC,
/_ssss_pppp_aaaa_rrrr_cccc/_bbbb_iiii_nnnn/_vvvv_cccc  will compile programs for the MIPS; if one is
running on machine  $_cccc_pppp_uuuu_tttt_yyyy_pppp_eeee,  /$_cccc_pppp_uuuu_tttt_yyyy_pppp_eeee/_bbbb_iiii_nnnn/_vvvv_cccc will compile
programs for the MIPS.

     Because of the bindings that assemble  /_bbbb_iiii_nnnn, the  shell
always looks for a command, say  _dddd_aaaa_tttt_eeee, in  /_bbbb_iiii_nnnn and automat-
ically finds the file   /$_cccc_pppp_uuuu_tttt_yyyy_pppp_eeee/_bbbb_iiii_nnnn/_dddd_aaaa_tttt_eeee.   Therefore  the
MIPS  compiler  is known as just  _vvvv_cccc; the shell will invoke
/_bbbb_iiii_nnnn/_vvvv_cccc and that is guaranteed to be the version of the MIPS
compiler  appropriate  for  the machine running the command.
Regardless of the architecture of the  compiling  machine,
/_bbbb_iiii_nnnn/_vvvv_cccc is  _aaaa_llll_wwww_aaaa_yyyy_ssss the MIPS compiler.

     Also, the output of  _vvvv_cccc and  _vvvv_llll is completely  indepen-
dent  of  the  machine  type on which they are executed:  ._vvvv
files compiled (with  _vvvv_cccc) on a SPARC may be  linked  (with
_vvvv_llll)  on  a  386.  (The resulting  _vvvv._oooo_uuuu_tttt will run, of course,
only  on  a  MIPS.)   Similarly,  the  MIPS  libraries  in
/_mmmm_iiii_pppp_ssss/_llll_iiii_bbbb  are suitable for loading with  _vvvv_llll on any machine;
there is only one set of MIPS libraries,  not  one  set  for
each architecture that supports the MIPS compiler.

_HHHH_eeee_tttt_eeee_rrrr_oooo_gggg_eeee_nnnn_eeee_iiii_tttt_yyyy _aaaa_nnnn_dddd _mmmm_kkkk

     Most software on Plan 9 is compiled under  the  control
of    _mmmm_kkkk,  a  descendant  of  _mmmm_aaaa_kkkk_eeee that is documented in the
Programmer's Manual.  A  convention  used  throughout  the
_mmmm_kkkk_ffff_iiii_llll_eeee_ssss  makes  it  easy  to  compile the source into binary
suitable for any architecture.

     The variable  $_cccc_pppp_uuuu_tttt_yyyy_pppp_eeee  is  advisory:  it  reports  the
architecture  of  the current environment, and should not be
modified.  A second variable,   $_oooo_bbbb_jjjj_tttt_yyyy_pppp_eeee,  is  used  to  set
which  architecture  is  being  _cccc_oooo_mmmm_pppp_iiii_llll_eeee_dddd for.  The value of
$_oooo_bbbb_jjjj_tttt_yyyy_pppp_eeee can be used by a  _mmmm_kkkk_ffff_iiii_llll_eeee to configure the  compila-
tion environment.

     In each machine's root directory  there  is  a  short
_mmmm_kkkk_ffff_iiii_llll_eeee  that  defines  a  set  of  macros  for the compiler,
loader, etc.  Here is  /_mmmm_iiii_pppp_ssss/_mmmm_kkkk_ffff_iiii_llll_eeee:

  </sys/src/mkfile.proto

  CC=vc
  LD=vl
  O=v
  AS=va

The line

  </sys/src/mkfile.proto

causes  _mmmm_kkkk to include the file  /_ssss_yyyy_ssss/_ssss_rrrr_cccc/_mmmm_kkkk_ffff_iiii_llll_eeee._pppp_rrrr_oooo_tttt_oooo, which


                       April 5, 2011






                           - 8 -


contains general definitions:

  #
  # common mkfile parameters shared by all architectures
  #

  OS=v486xq7
  CPUS=mips 386 power alpha
  CFLAGS=-FVw
  LEX=lex
  YACC=yacc
  MK=/bin/mk

 _CCCC_CCCC is obviously the compiler,  _AAAA_SSSS the assembler,  and    _LLLL_DDDD
the loader.   _OOOO is the suffix for the object files and  _CCCC_PPPP_UUUU_SSSS
and  _OOOO_SSSS are used in special rules described below.

     Here is a  _mmmm_kkkk_ffff_iiii_llll_eeee to build the installed  source  for
_ssss_aaaa_mmmm:

  </$objtype/mkfile
  OBJ=sam.$O address.$O buffer.$O cmd.$O disc.$O error.$O \
          file.$O io.$O list.$O mesg.$O moveto.$O multi.$O \
          plan9.$O rasp.$O regexp.$O string.$O sys.$O xec.$O

  $O.out: $OBJ
          $LD $OBJ

  install:        $O.out
          cp $O.out /$objtype/bin/sam

  installall:
          for(objtype in $CPUS) mk install

  %.$O:   %.c
          $CC $CFLAGS $stem.c

  $OBJ:   sam.h errors.h mesg.h
  address.$O cmd.$O parse.$O xec.$O unix.$O:      parse.h

  clean:V:
          rm -f [$OS].out *.[$OS] y.tab.?

(The actual  _mmmm_kkkk_ffff_iiii_llll_eeee imports most of  its  rules  from  other
secondary  files, but this example works and is not mislead-
ing.)  The first line causes  _mmmm_kkkk to include the contents of
/$_oooo_bbbb_jjjj_tttt_yyyy_pppp_eeee/_mmmm_kkkk_ffff_iiii_llll_eeee  in  the current  _mmmm_kkkk_ffff_iiii_llll_eeee.  If  $_oooo_bbbb_jjjj_tttt_yyyy_pppp_eeee is
_mmmm_iiii_pppp_ssss, this inserts the MIPS  macro  definitions  into  the
_mmmm_kkkk_ffff_iiii_llll_eeee.   In  this  case  the rule for  $_OOOO._oooo_uuuu_tttt uses the MIPS
tools to build  _vvvv._oooo_uuuu_tttt.  The  %.$_OOOO rule in  the  file  uses
_mmmm_kkkk's pattern matching facilities to convert the source files
to the object files through the compiler.  (The text of  the
rules  is passed directly to the shell,  _rrrr_cccc, without further
translation.   See  the    _mmmm_kkkk  manual  if  any  of  this  is


                       April 5, 2011






                           - 9 -


unfamiliar.)  Because the default rule builds  $_OOOO._oooo_uuuu_tttt rather
than  _ssss_aaaa_mmmm, it is possible to maintain binaries for  multiple
machines  in  the  same  source  directory without conflict.
This is also, of course, why the output files from the vari-
ous compilers and loaders have distinct names.

     The rest of the   _mmmm_kkkk_ffff_iiii_llll_eeee  should  be  easy  to  follow;
notice  how  the  rules for  _cccc_llll_eeee_aaaa_nnnn and  _iiii_nnnn_ssss_tttt_aaaa_llll_llll_aaaa_llll_llll (that is,
install versions for all  architectures)  use  other  macros
defined  in  /$_oooo_bbbb_jjjj_tttt_yyyy_pppp_eeee/_mmmm_kkkk_ffff_iiii_llll_eeee.  In Plan 9,  _mmmm_kkkk_ffff_iiii_llll_eeee_ssss for com-
mands conventionally contain rules to  _iiii_nnnn_ssss_tttt_aaaa_llll_llll (compile  and
install the version for  $_oooo_bbbb_jjjj_tttt_yyyy_pppp_eeee),  _iiii_nnnn_ssss_tttt_aaaa_llll_llll_aaaa_llll_llll (compile and
install for all  $_oooo_bbbb_jjjj_tttt_yyyy_pppp_eeee_ssss), and  _cccc_llll_eeee_aaaa_nnnn (remove  all  object
files, binaries, etc.).

     The  _mmmm_kkkk_ffff_iiii_llll_eeee is easy to use.  To build a MIPS  binary,
_vvvv._oooo_uuuu_tttt:

  % objtype=mips
  % mk

To build and install a MIPS binary:

  % objtype=mips
  % mk install

To build and install all versions:

  % mk installall

These conventions make cross-compilation as easy  to  manage
as  traditional native compilation.  Plan 9 programs compile
and run without change on machines from  large  multiproces-
sors  to  laptops.  For more information about this process,
see ``Plan 9 Mkfiles'', by Bob Flandrena.

_PPPP_oooo_rrrr_tttt_aaaa_bbbb_iiii_llll_iiii_tttt_yyyy

     Within Plan 9, it is painless to  write  portable  pro-
grams,  programs  whose source is independent of the machine
on which they execute.  The operating system  is  fixed  and
the  compiler, headers and libraries are constant so most of
the stumbling blocks to portability are removed.   Attention
to a few details can avoid those that remain.

     Plan 9 is a heterogeneous environment, so programs must
  _eeee_xxxx_pppp_eeee_cccc_tttt  that external files will be written by programs on
machines of different  architectures.   The  compilers,  for
instance, must handle without confusion object files written
by other machines.  The traditional approach to this problem
is  to pepper the source with  #_iiii_ffff_dddd_eeee_ffff_ssss to turn byte-swapping
on and off.  Plan 9 takes a different approach: of the hand-
ful  of machine-dependent  #_iiii_ffff_dddd_eeee_ffff_ssss in all the source, almost
all are deep in the libraries.  Instead  programs  read  and


                       April 5, 2011






                           - 10 -


write  files  in  a  defined  format, either (for low volume
applications) as formatted text, or (for high volume  appli-
cations)  as  binary in a known byte order.  If the external
data were written with the most significant byte first,  the
following  code  reads a 4-byte integer correctly regardless
of the architecture of the executing  machine  (assuming  an
unsigned long holds 4 bytes):

  ulong
  getlong(void)
  {
          ulong l;

          l = (getchar()&0xFF)<<24;
          l |= (getchar()&0xFF)<<16;
          l |= (getchar()&0xFF)<<8;
          l |= (getchar()&0xFF)<<0;
          return l;
  }

Note that this code does not `swap' the  bytes;  instead  it
just  reads  them  in the correct order.  Variations of this
code will handle any binary format and also  avoid  problems
involving  how structures are padded, how words are aligned,
and other impediments to  portability.   Be  aware,  though,
that extra care is needed to handle floating point data.

     Efficiency hounds will argue that this method is unnec-
essarily  slow and clumsy when the executing machine has the
same byte order (and padding and  alignment)  as  the  data.
The  CPU cost of I/O processing is rarely the bottleneck for
an application, however, and the gain in simplicity of port-
ing  and  maintaining  the  code greatly outweighs the minor
speed loss from handling data in  this  general  way.   This
method  is  how the Plan 9 compilers, the window system, and
even the file servers transmit data between programs.

     To port programs beyond Plan 9, where the system inter-
face  is more variable, it is probably necessary to use  _pppp_cccc_cccc
and hope that the target machine supports ANSI C and POSIX.

_IIII/_OOOO

     The default C library, defined by  the  include  file
<_llll_iiii_bbbb_cccc._hhhh>,  contains  no  buffered I/O package.  It does have
several entry points for printing  formatted  text:    _pppp_rrrr_iiii_nnnn_tttt
outputs text to the standard output,  _ffff_pppp_rrrr_iiii_nnnn_tttt outputs text to
a specified integer file descriptor, and  _ssss_pppp_rrrr_iiii_nnnn_tttt places text
in  a  character array.  To access library routines for buf-
fered I/O, a program must explicitly include the header file
associated with an appropriate library.

     The recommended I/O library, used by most Plan 9 utili-
ties,  is    _bbbb_iiii_oooo (buffered I/O), defined by  <_bbbb_iiii_oooo._hhhh>.  There


                       April 5, 2011






                           - 11 -


also exists an implementation of ANSI Standard I/O,  _ssss_tttt_dddd_iiii_oooo.

      _BBBB_iiii_oooo is small and efficient, particularly  for  buffer-
at-a-time  or  line-at-a-time I/O.  Even for character-at-a-
time I/O, however, it is significantly faster than the Stan-
dard I/O library,  _ssss_tttt_dddd_iiii_oooo.  Its interface is compact and reg-
ular, although  it  lacks  a  few  conveniences.   The  most
noticeable  is  that  one must explicitly define buffers for
standard input and output;  _bbbb_iiii_oooo  does  not  predefine  them.
Here  is  a program to copy input to output a byte at a time
using  _bbbb_iiii_oooo:

  #include <u.h>
  #include <libc.h>
  #include <bio.h>

  Biobuf  bin;
  Biobuf  bout;

  main(void)
  {
          int c;

          Binit(&bin, 0, OREAD);
          Binit(&bout, 1, OWRITE);

          while((c=Bgetc(&bin)) != Beof)
                  Bputc(&bout, c);
          exits(0);
  }

For peak performance, we could replace  _BBBB_gggg_eeee_tttt_cccc and  _BBBB_pppp_uuuu_tttt_cccc  by
their  equivalent  in-line  macros  _BBBB_GGGG_EEEE_TTTT_CCCC and  _BBBB_PPPP_UUUU_TTTT_CCCC but the
performance gain would be modest.  For more information on
_bbbb_iiii_oooo, see the Programmer's Manual.

     Perhaps the most dramatic difference in the I/O  inter-
face  of  Plan  9  from  other  systems' is that text is not
ASCII.  The format for text  in  Plan  9  is  a  byte-stream
encoding  of  16-bit characters.  The character set is based
on the Unicode Standard  and  is  backward  compatible  with
ASCII:  characters  with value 0 through 127 are the same in
both sets.  The 16-bit characters, called  _rrrr_uuuu_nnnn_eeee_ssss in Plan  9,
are  encoded  using a representation called UTF, an encoding
that is becoming accepted as  a  standard.   (ISO  calls  it
UTF-8; throughout Plan 9 it's just called UTF.)  UTF defines
multibyte sequences to represent character values from 0  to
65535.   In UTF, character values up to 127 decimal, 7F hex-
adecimal, represent themselves, so straight ASCII files  are
also valid UTF.  Also, UTF guarantees that bytes with values
0 to 127 (NUL to DEL, inclusive) will appear only when  they
represent  themselves,  so  programs that read bytes looking
for plain ASCII characters will continue to work.  Any  pro-
gram  that expects a one-to-one correspondence between bytes


                       April 5, 2011






                           - 12 -


and characters will, however, need to be modified.  An exam-
ple  is  parsing file names.  File names, like all text, are
in UTF, so it is incorrect to search for a  character  in  a
string  by  _ssss_tttt_rrrr_cccc_hhhh_rrrr(_ffff_iiii_llll_eeee_nnnn_aaaa_mmmm_eeee,  _cccc) because the character might
have a multi-byte encoding.  The correct method is to call
_uuuu_tttt_ffff_rrrr_uuuu_nnnn_eeee(_ffff_iiii_llll_eeee_nnnn_aaaa_mmmm_eeee,  _cccc), defined in  _rrrr_uuuu_nnnn_eeee(2), which interprets
the file name as a sequence  of  encoded  characters  rather
than  bytes.  In fact, even when you know the character is a
single byte that can represent only itself, it is  safer  to
use   _uuuu_tttt_ffff_rrrr_uuuu_nnnn_eeee because that assumes nothing about the charac-
ter set and its representation.

     The library defines several  symbols  relevant  to  the
representation  of characters.  Any byte with unsigned value
less than  _RRRR_uuuu_nnnn_eeee_ssss_yyyy_nnnn_cccc will not appear in any multi-byte encod-
ing  of  a character.   _UUUU_tttt_ffff_rrrr_uuuu_nnnn_eeee compares the character being
searched against  _RRRR_uuuu_nnnn_eeee_ssss_yyyy_nnnn_cccc to see if  it  is  sufficient  to
call  _ssss_tttt_rrrr_cccc_hhhh_rrrr or if the byte stream must be interpreted.  Any
byte with unsigned value less than  _RRRR_uuuu_nnnn_eeee_ssss_eeee_llll_ffff is  represented
by  a single byte with the same value.  Finally, when errors
are encountered converting to runes from a byte stream,  the
library  returns  the  rune  value  _RRRR_uuuu_nnnn_eeee_eeee_rrrr_rrrr_oooo_rrrr and advances a
single byte.  This permits programs to find  runes  embedded
in binary data.

      _BBBB_iiii_oooo includes routines    _BBBB_gggg_eeee_tttt_rrrr_uuuu_nnnn_eeee  and    _BBBB_pppp_uuuu_tttt_rrrr_uuuu_nnnn_eeee  to
transform  the  external  byte stream UTF format to and from
internal 16-bit runes.  Also, the    %_ssss  format  to    _pppp_rrrr_iiii_nnnn_tttt
accepts  UTF;  %_cccc prints a character after narrowing it to 8
bits.  The  %_SSSS format prints a null-terminated  sequence  of
runes;  %_CCCC prints a character after narrowing it to 16 bits.
For more information, see the Programmer's Manual,  in  par-
ticular   _uuuu_tttt_ffff(6) and  _rrrr_uuuu_nnnn_eeee(2), and the paper, ``Hello world,
or Καλημέρα κόσμε, or  こんにちは  世界'',  by  Rob  Pike  and  Ken
Thompson; there is not room for the full story here.

     These issues  affect  the  compiler  in  several  ways.
First,  the  C  source is in UTF.  ANSI says C variables are
formed from ASCII alphanumerics, but  comments  and  literal
strings  may  contain  any  characters encoded in the native
encoding, here UTF.  The declaration

  char *cp = "abcÿ";

initializes the variable  _cccc_pppp to point to an array  of  bytes
holding  the UTF representation of the characters  _aaaa_bbbb_cccc____________ÿ. The
type  _RRRR_uuuu_nnnn_eeee is defined in  <_uuuu._hhhh> to be  _uuuu_ssss_hhhh_oooo_rrrr_tttt, which is also
the   `wide  character' type in the compiler.  Therefore the
declaration

  Rune *rp = L"abcÿ";

initializes the variable    _rrrr_pppp  to  point  to  an  array  of
unsigned  short  integers  holding  the 16-bit values of the


                       April 5, 2011






                           - 13 -


characters  _aaaa_bbbb_cccc________ÿ.  Note that in both these declarations  the
characters  in the source that represent  _aaaa_bbbb_ccccÿ are the same;
what changes is how those characters are represented in mem-
ory in the program.  The following two lines:

  print("%s\n", "abcÿ");
  print("%S\n", L"abcÿ");

produce the same UTF string on their output,  the  first  by
copying  the  bytes,  the second by converting from runes to
bytes.

     In C, character constants  are  integers  but  narrowed
through  the  _cccc_hhhh_aaaa_rrrr type.  The Unicode character  ÿ has value
255, so if the  _cccc_hhhh_aaaa_rrrr type is signed, the constant   'ÿ'  has
value  -1 (which is equal to EOF).  On the other hand,  _LLLL'ÿ'
narrows through the wide character type,  _uuuu_ssss_hhhh_oooo_rrrr_tttt, and there-
fore has value 255.

     Finally, although it's not ANSI C, the Plan 9 C compil-
ers  assume  any  character with value above  _RRRR_uuuu_nnnn_eeee_ssss_eeee_llll_ffff is an
alphanumeric, so α is a  legal,  if  non-portable,  variable
name.

_AAAA_rrrr_gggg_uuuu_mmmm_eeee_nnnn_tttt_ssss

     Some macros are defined in  <_llll_iiii_bbbb_cccc._hhhh>  for  parsing  the
arguments to  _mmmm_aaaa_iiii_nnnn().  They are described in  _AAAA_RRRR_GGGG(2) but are
fairly self-explanatory.  There are four macros:    _AAAA_RRRR_GGGG_BBBB_EEEE_GGGG_IIII_NNNN
and    _AAAA_RRRR_GGGG_EEEE_NNNN_DDDD are used to bracket a hidden  _ssss_wwww_iiii_tttt_cccc_hhhh statement
within which  _AAAA_RRRR_GGGG_CCCC  returns  the  current  option  character
(rune) being processed and  _AAAA_RRRR_GGGG_FFFF returns the argument to the
option, as in the loader option  -_oooo  _ffff_iiii_llll_eeee.  Here, for  exam-
ple,  is  the  code  at the beginning of  _mmmm_aaaa_iiii_nnnn() in  _rrrr_aaaa_mmmm_ffff_ssss._cccc
(see  _rrrr_aaaa_mmmm_ffff_ssss(1)) that cracks its arguments:





















                       April 5, 2011






                           - 14 -


  void
  main(int argc, char *argv[])
  {
          char *defmnt;
          int p[2];
          int mfd[2];
          int stdio = 0;

          defmnt = "/tmp";
          ARGBEGIN{
          case 'i':
                  defmnt = 0;
                  stdio = 1;
                  mfd[0] = 0;
                  mfd[1] = 1;
                  break;
          case 's':
                  defmnt = 0;
                  break;
          case 'm':
                  defmnt = ARGF();
                  break;
          default:
                  usage();
          }ARGEND


_EEEE_xxxx_tttt_eeee_nnnn_ssss_iiii_oooo_nnnn_ssss

     The compiler has several extensions to ANSI C,  all  of
which  are  used  extensively in the system source.  First,
_ssss_tttt_rrrr_uuuu_cccc_tttt_uuuu_rrrr_eeee  _dddd_iiii_ssss_pppp_llll_aaaa_yyyy_ssss permit  _ssss_tttt_rrrr_uuuu_cccc_tttt expressions to be  formed
dynamically.  Given these declarations:

  typedef struct Point Point;
  typedef struct Rectangle Rectangle;

  struct Point
  {
          int x, y;
  };

  struct Rectangle
  {
          Point min, max;
  };

  Point   p, q, add(Point, Point);
  Rectangle r;
  int     x, y;

this assignment may appear anywhere an assignment is legal:

  r = (Rectangle){add(p, q), (Point){x, y+3}};


                       April 5, 2011






                           - 15 -


The syntax is the same as for initializing a  structure  but
with a leading cast.

     If an  _aaaa_nnnn_oooo_nnnn_yyyy_mmmm_oooo_uuuu_ssss   _ssss_tttt_rrrr_uuuu_cccc_tttt_uuuu_rrrr_eeee  or    _uuuu_nnnn_iiii_oooo_nnnn  is  declared
within another structure or union, the members of the inter-
nal structure or union are addressable without prefix in the
outer  structure.  This feature eliminates the clumsy naming
of nested structures and, particularly, unions.   For  exam-
ple, after these declarations,

  struct Lock
  {
          int     locked;
  };

  struct Node
  {
          int     type;
          union{
                  double  dval;
                  double  fval;
                  long    lval;
          };              /* anonymous union */
          struct Lock;    /* anonymous structure */
  } *node;

  void    lock(struct Lock*);

one may refer to  _nnnn_oooo_dddd_eeee->_tttt_yyyy_pppp_eeee,   _nnnn_oooo_dddd_eeee->_dddd_vvvv_aaaa_llll,    _nnnn_oooo_dddd_eeee->_ffff_vvvv_aaaa_llll,
_nnnn_oooo_dddd_eeee->_llll_vvvv_aaaa_llll,  and  _nnnn_oooo_dddd_eeee->_llll_oooo_cccc_kkkk_eeee_dddd.  Moreover, the address of a
_ssss_tttt_rrrr_uuuu_cccc_tttt  _NNNN_oooo_dddd_eeee may be used without a cast  anywhere  that  the
address  of  a    _ssss_tttt_rrrr_uuuu_cccc_tttt   _LLLL_oooo_cccc_kkkk is used, such as in argument
lists.  The compiler automatically  promotes  the  type  and
adjusts the address.  Thus one may invoke  _llll_oooo_cccc_kkkk(_nnnn_oooo_dddd_eeee).

     Anonymous structures and unions may be accessed by type
name  if  (and  only  if) they are declared using a  _tttt_yyyy_pppp_eeee_dddd_eeee_ffff
name.  For example, using the above declaration for   _PPPP_oooo_iiii_nnnn_tttt,
one may declare

  struct
  {
          int     type;
          Point;
  } p;

and refer to  _pppp._PPPP_oooo_iiii_nnnn_tttt.

     In the initialization of arrays,  a  number  in  square
brackets  before  an element sets the index for the initial-
ization.  For example, to  initialize  some  elements  in  a
table of function pointers indexed by ASCII character,




                       April 5, 2011






                           - 16 -


  void    percent(void), slash(void);

  void    (*func[128])(void) =
  {
          ['%']   percent,
          ['/']   slash,
  };


A similar syntax allows one  to  initialize  structure  ele-
ments:

  Point p =
  {
          .y 100,
          .x 200
  };

These initialization syntaxes were later added  to  ANSI  C,
with the addition of an equals sign between the index or tag
and the value.  The Plan 9 compiler accepts either form.

     Finally, the declaration

  extern register reg;

( _tttt_hhhh_iiii_ssss appearance of the register keyword  is  not  ignored)
allocates  a  global  register  to  hold  the variable  _rrrr_eeee_gggg.
External registers must be used carefully: they need  to  be
declared  in   _aaaa_llll_llll source files and libraries in the program
to guarantee the register is not allocated  temporarily  for
other  purposes.  Especially on machines with few registers,
such as the i386, it is easy to link accidentally with  code
that  has  already usurped the global registers and there is
no diagnostic  when  this  happens.   Used  wisely,  though,
external  registers are powerful.  The Plan 9 operating sys-
tem uses them to access  per-process  and  per-machine  data
structures on a multiprocessor.  The storage class they pro-
vide is hard to create in other ways.

_TTTT_hhhh_eeee _cccc_oooo_mmmm_pppp_iiii_llll_eeee-_tttt_iiii_mmmm_eeee _eeee_nnnn_vvvv_iiii_rrrr_oooo_nnnn_mmmm_eeee_nnnn_tttt

     The code generated by the compilers is  `optimized'  by
default:  variables  are  placed  in  registers and peephole
optimizations are performed.  The compiler flag  -_NNNN disables
these optimizations.  Registerization is done locally rather
than throughout a function: whether a  variable  occupies  a
register  or  the  memory  location identified in the symbol
table depends on the activity of the variable and may change
throughout the life of the variable.  The  -_NNNN flag is rarely
needed; its main use is to simplify debugging.  There is  no
information in the symbol table to identify the registeriza-
tion of a variable, so  -_NNNN guarantees the variable is always
where the symbol table says it is.


                       April 5, 2011






                           - 17 -


     Another flag,  -_wwww, turns  _oooo_nnnn warnings about portability
and problems detected in flow analysis.  Most code in Plan 9
is compiled with warnings enabled; these warnings  plus  the
type checking offered by function prototypes provide most of
the support of the Unix tool  _llll_iiii_nnnn_tttt more accurately and  with
less  chatter.   Two of the warnings, `used and not set' and
`set and not used', are almost always accurate  but  may  be
triggered  spuriously  by  code with invisible control flow,
such as in routines that call  _llll_oooo_nnnn_gggg_jjjj_mmmm_pppp.  The compiler state-
ments

  SET(v1);
  USED(v2);

decorate the flow graph to  silence  the  compiler.   Either
statement  accepts a comma-separated list of variables.  Use
them carefully: they may silence real errors.  For the  com-
mon  case  of  unused  parameters to a function, leaving the
name off the declaration silences the  warnings.   That  is,
listing  the type of a parameter but giving it no associated
variable name does the trick.

_DDDD_eeee_bbbb_uuuu_gggg_gggg_iiii_nnnn_gggg

     There are two  debuggers  available  on  Plan  9.   The
first,  and  older,  is    _dddd_bbbb, a revision of Unix  _aaaa_dddd_bbbb.  The
other,  _aaaa_cccc_iiii_dddd, is a source-level debugger whose commands  are
statements  in  a  true  programming language.   _AAAA_cccc_iiii_dddd is the
preferred debugger, but since it borrows some elements  of
_dddd_bbbb,  notably  the formats for displaying values, it is worth
knowing a little bit about  _dddd_bbbb.

     Both debuggers support multiple architectures in a sin-
gle  program;  that  is, the programs are  _dddd_bbbb and  _aaaa_cccc_iiii_dddd, not
for example  _vvvv_dddd_bbbb and    _vvvv_aaaa_cccc_iiii_dddd.   They  also  support  cross-
architecture  debugging  comfortably:  one may debug a 68020
binary on a MIPS.

     Imagine a program has crashed mysteriously:

  % X11/X
  Fatal server bug!
  failed to create default stipple
  X 106: suicide: sys: trap: fault read addr=0x0 pc=0x00105fb8
  %

When a process dies on Plan 9 it hangs in the `broken' state
for  debugging.   Attach a debugger to the process by naming
its process id:







                       April 5, 2011






                           - 18 -


  % acid 106
  /proc/106/text:mips plan 9 executable

  /sys/lib/acid/port
  /sys/lib/acid/mips
  acid:

The  _aaaa_cccc_iiii_dddd function  _ssss_tttt_kkkk() reports the stack traceback:

  acid: stk()
  At pc:0x105fb8:abort+0x24 /sys/src/ape/lib/ap/stdio/abort.c:6
  abort() /sys/src/ape/lib/ap/stdio/abort.c:4
          called from FatalError+#4e
                  /sys/src/X/mit/server/dix/misc.c:421
  FatalError(s9=#e02, s8=#4901d200, s7=#2, s6=#72701, s5=#1,
      s4=#7270d, s3=#6, s2=#12, s1=#ff37f1c, s0=#6, f=#7270f)
      /sys/src/X/mit/server/dix/misc.c:416
          called from gnotscreeninit+#4ce
                  /sys/src/X/mit/server/ddx/gnot/gnot.c:792
  gnotscreeninit(snum=#0, sc=#80db0)
      /sys/src/X/mit/server/ddx/gnot/gnot.c:766
          called from AddScreen+#16e
                  /n/bootes/sys/src/X/mit/server/dix/main.c:610
  AddScreen(pfnInit=0x0000129c,argc=0x00000001,argv=0x7fffffe4)
      /sys/src/X/mit/server/dix/main.c:530
          called from InitOutput+0x80
                  /sys/src/X/mit/server/ddx/brazil/brddx.c:522
  InitOutput(argc=0x00000001,argv=0x7fffffe4)
      /sys/src/X/mit/server/ddx/brazil/brddx.c:511
          called from main+0x294
                  /sys/src/X/mit/server/dix/main.c:225
  main(argc=0x00000001,argv=0x7fffffe4)
      /sys/src/X/mit/server/dix/main.c:136
          called from _main+0x24
                  /sys/src/ape/lib/ap/mips/main9.s:8

The function  _llll_ssss_tttt_kkkk() is similar but also reports the  values
of  local  variables.  Note that the traceback includes full
file names; this is a boon to debugging, although  it  makes
the output much noisier.

     To use  _aaaa_cccc_iiii_dddd well you will need to learn its input lan-
guage;  see  the  ``Acid Manual'', by Phil Winterbottom, for
details.  For simple debugging, however, the information  in
the  manual page is sufficient.  In particular, it describes
the most useful functions for examining a process.

     The compiler does not place information describing  the
types  of  variables  in  the executable, but a compile-time
flag provides crude support for symbolic debugging.  The  -_aaaa
flag  to the compiler suppresses code generation and instead
emits source text in the  _aaaa_cccc_iiii_dddd language to format  and  dis-
play data structure types defined in the program.  The easi-
est way to use this feature is to put a rule in the  _mmmm_kkkk_ffff_iiii_llll_eeee:


                       April 5, 2011






                           - 19 -


  syms:   main.$O
          $CC -a main.c > syms

Then from within  _aaaa_cccc_iiii_dddd,

  acid: include("sourcedirectory/syms")

to  read  in  the  relevant  definitions.   (For  multi-file
source,  you need to be a little fancier; see  _2222_cccc(1)).  This
text includes, for each defined compound  type,  a  function
with  that  name  that  may  be called with the address of a
structure of that type to display its contents.   For  exam-
ple,  if   _rrrr_eeee_cccc_tttt is a global variable of type  _RRRR_eeee_cccc_tttt_aaaa_nnnn_gggg_llll_eeee, one
may execute

  Rectangle(*rect)

to display it.  The  * (indirection) operator  is  necessary
because  of  the  way  _aaaa_cccc_iiii_dddd works: each global symbol in the
program is defined as a variable by  _aaaa_cccc_iiii_dddd, with value  equal
to the  _aaaa_dddd_dddd_rrrr_eeee_ssss_ssss of the symbol.

     Another common technique is to write by hand  special
_aaaa_cccc_iiii_dddd  code  to define functions to aid debugging, initialize
the debugger, and so on.  Conventionally, this is placed  in
a file called  _aaaa_cccc_iiii_dddd in the source directory; it has a line

  include("sourcedirectory/syms");

to load the compiler-produced symbols.   One  may  edit  the
compiler  output  directly but it is wiser to keep the hand-
generated  _aaaa_cccc_iiii_dddd separate from the machine-generated.

     To make things simple, the default rules in the system
_mmmm_kkkk_ffff_iiii_llll_eeee_ssss  include  entries  to make  _ffff_oooo_oooo._aaaa_cccc_iiii_dddd from  _ffff_oooo_oooo._cccc, so
one may use  _mmmm_kkkk to automate the production of  _aaaa_cccc_iiii_dddd  defini-
tions for a given C source file.

     There is much more to say here.  See  _aaaa_cccc_iiii_dddd manual page,
the  reference manual, or the paper ``Acid: A Debugger Built
From A Language'', also by Phil Winterbottom.















                       April 5, 2011



