metaconfig(1)

NAME

   metaconfig - a Configure script generator

SYNOPSIS

   metaconfig [ -dhkmostvwGMV ] [ -L dir ]

DESCRIPTION

   Metaconfig  is a program that generates Configure scripts. If you don't
   know what a Configure script is, please skip to the TUTORIAL section of
   this manual page. If you want a full (formal) description of the way to
   use metaconfig and its units, please look at the REFERENCE section. The
   following  is  a  quick  introduction  and  reference for knowledgeable
   users.

   Metaconfig operates from set of  units  which  define  everything  that
   metaconfig  knows  about portability.  Each unit is self-contained, and
   does not have to be registered anywhere  other  than  by  inclusion  in
   either the public U directory or your private U directory.  If the dist
   package (of which metaconfig is a part) is installed in LIB,  then  the
   public  U  directory  is  LIB/dist/mcon/U.  On  this  machine,  the LIB
   directory is /usr/share/dist.  Your private U directory,  if  you  have
   one, is in the top level directory of your package.  Before you can run
   metaconfig you must do a several things:

   *    Create a .package file in the package's  top  level  directory  by
        running  packinit.   This  program will ask you about your package
        and remember what you tell it so that all the dist programs can be
        smart.

   *    Consult  the  Glossary  (in  LIB/dist/mcon)  and  write your shell
        scripts and C programs in terms of  the  symbols  that  metaconfig
        knows  how  to  define.   You  don't need to tell metaconfig which
        symbols you used, since metaconfig will figure that out for you.

   *    Generate any .SH  scripts  needed  to  write  Makefiles  or  shell
        scripts that will depend on values defined by Configure.  There is
        a program called makeSH that will help you convert a plain  script
        into  a  script.SH  template;  some  editing will still need to be
        performed  on  the  resulting  .SH  file  to  move  the   variable
        configuration  part  in  the  top  part  of the script (see inline
        comments generated by makeSH within your .SH file).

   *    Create a MANIFEST.new file in your top level directory that  lists
        all  the  files in your package. This file will remain private and
        will not be part of the final distribution. (As a convenience, the
        MANIFEST   file  will  be  used  by  metaconfig  if  there  is  no
        MANIFEST.new file yet.)  The filename should be the first field on
        each  line.   After  some  whitespace  you can add a short comment
        describing your file.  Only  source  files  should  be  listed  in
        there.  The  special  file  patchlevel.h  (which  is  handled  and
        maintained by the patching tools -- see pat(1)) should be part  of
        the  MANIFEST.new file, but may be silently ignored by some tools.
        As a rule of thumb, only files maintained by RCS should be  listed
        in there, the patchlevel.h file being one important exception.

   *    Optionally,  you may wish to create a MANIFEST file, which will be
        an exported version of your MANIFEST.new. That file must  be  made
        part  of  the  release,  i.e. listed in both your MANIFEST.new and
        MANIFEST itself.  One of the metaconfig  units  knows  about  this
        file and will force Configure to perform a release check, ensuring
        all the files listed there  are  part  of  the  distribution.  The
        MANIFEST and MANIFEST.new files should be distinct, not links.

   *    Copy  any  .U  files  that  you  want  to modify to your private U
        directory.  Any .U files in your private U directory will be  used
        in  preference to the one in the public U directory.  For example,
        one way to force inclusion of any unit is to copy the  End.U  file
        to  your  .U  directory and add the name of the unit you want as a
        dependency on the end of the ?MAKE: line.  Certain units can  ONLY
        be  forced  in  this  way,  namely  those of the form Warn_*.U and
        Chk_*.U.   You  can  also  customize  certain  default   Configure
        variables   by  copying  Myinit.U  to  your  package's  private  U
        directory and setting the variables in that unit.

   Now you are ready to run metaconfig. That will create a Configure file,
   and  optionally  a  config_h.SH file (if your sources make any use of C
   symbols).  The generated files will  automatically  be  added  to  your
   MANIFEST.new  if  necessary. Do not forget to update your MANIFEST file
   though.

   In order to create new units, do the following:

   *    Copy a similar unit to a new .U file.  The name you choose  should
        be  the name of a variable generated by the unit, although this is
        only a convenience for you, not a requirement.  It should be 12 or
        less characters to prevent filename chopping.  Actually, it should
        probably be 10 or less so that those who want to use RCS can  have
        a  .U,v  on the end without chopping.  Metaconfig uses the case of
        the first letter to determine if any variable is actually produced
        by this unit, so don't Capitalize your unit name if it is supposed
        to produce a shell variable.

   *    Edit the new .U file to do what you want.  The first  ?MAKE:  line
        indicates  the  dependencies;  before the final list colon all the
        variables this unit defines, and after the  final  colon  all  the
        variables (or other units) on which this unit depends.  It is very
        important that  these  lists  be  accurate.  If  a  dependency  is
        optional  and  a  default value can be used, you should prefix the
        dependency with a '+' sign. The corresponding  unit  will  not  be
        loaded  to  compute  the symbol, unless really required by another
        unit.

   *    To the extent possible, parameterize  your  unit  based  on  shell
        variable  defined  on  ?INIT:  lines.  This will move the variable
        definitions up to the Init.U unit, where they can be overridden by
        definitions in Myinit.U, which is included after Init.U.

   *    Add  the definition of any C symbols desired as ?H: lines.  A line
        beginning with ?H:?%<: in  the  .U  file  will  be  added  to  the
        eventual config.h file if and only if metaconfig decides that this
        unit is needed.  The %< stands for the unit's name, which  happens
        to  be  the  name of the file too (without .U) if you followed the
        convention.  Always put a comment on each ?H: line in case one  of
        the  variable  substitutions  earlier on the line starts a comment
        without finishing it.  Any shell variable starting with d_ may  do
        this,  so beware.  If you ommit the ?%<:, then metaconfig will try
        to  intuit  the  symbol  whose  definition  is  needed  prior  any
        inclusion in config.h.

   *    Add  glossary definitions as ?S: lines for shell variables and ?C:
        lines for C  preprocessor  variables.   See  a  current  unit  for
        examples.   It  is  VERY important to start each entry with a left
        justified symbol name, and end each entry  with  a  ?C:.  or  ?S:.
        line.  The algorithm that translates C preprocessor symbol entries
        for the Glossary into comments for config.h depends on this.

   *    Make sure the order of all your ? lines  is  right.   The  correct
        order is:

             ?RCS: and ?X:  basically just comments
             ?MAKE:         metaconfig dependencies
             ?Y:            unit layout directive
             ?S:            glossary shell definitions
             ?C:            glossary C definitions
             ?H:            config.h definitions
             ?M:            confmagic.h definitions
             ?W:            wanted symbols
             ?V:            visible symbols
             ?F:            files created by this unit
             ?T:            temporary shell symbols used
             ?D:            optional dependencies default value
             ?O:            used to mark obsolete units
             ?LINT:         metalint hints
             ?INIT:         shell symbols initializations

   Here  is  an  example to show the ordering of the lines and the various
   formats allowed:

        ?RCS: $RCS-Id$
        ?RCS: Copyright information
        ?RCS: $RCS-Log$
        ?X:
        ?X: A contrived example
        ?X:
        ?MAKE:d_one two: three +four Five
        ?MAKE:    -pick add $@ %<
        ?Y:DEFAULT
        ?S:d_one:
        ?S:  First shell symbol, conditionally defines ONE.
        ?S:.
        ?S:two:
        ?S:  Second shell symbol, value for TWO.
        ?S:.
        ?C:ONE:
        ?C:  First C symbol.
        ?C:.
        ?C:TWO:
        ?C:  Second C symbol.
        ?C:.
        ?H:#$d_one ONE /**/
        ?H:#define TWO "$two"
        ?H:#$d_one ONE_TWO "$two"
        ?H:.
        ?M:flip: HAS_FLIP
        ?M:#ifndef HAS_FLIP
        ?M:#define flip(x) flop(x)
        ?M:#endif
        ?M:.
        ?W:%<:one_two
        ?V:p_one p_two:p_three
        ?F:file ./ftest !tmp
        ?T:tmp var
        ?D:two='undef'
        ?LINT:change three
        ?INIT:two_init='2'
        : shell code implementing the unit follows
        p_one='one'
        p_two='two'
        p_three=""

   Let me state it one more time: the above unit definition is a fake  one
   to  only  show  the  different  possibilities.  Such a unit would serve
   little purpose anyway... Some more advanced features are not  described
   here.   Please  refer  to  the  REFERENCE  section  for  more  complete
   information.

   *      Put  the  unit  into  the  public  or  private  U  directory  as
          appropriate.

   *      Rerun metaconfig.

   *      Send  your  unit to [email protected] (Raphael Manfredi) for inclusion
          in the master copy, if you think it's of general interest.

   In order to add a new program to be located:

   *      Edit Loc.U, and add the name of the program both to  the  ?MAKE:
          line  (between  the two colons) and to either loclist or trylist
          (depending on whether the program is mandatory or not).

   *      Rerun metaconfig.

   *      Send your unit to me for inclusion in the master  copy,  if  you
          think it's of general interest.

   Notes for writing .U files:

   *    Always  use  "rm  -f"  because  there  are  systems  where  rm  is
        interactive by default.

   *    Do not use "set -- ..." because '--'  does  not  work  with  every
        shell. Use "set x ...; shift".

   *    Do  not  use  "unset  ENV" since unset is not fully portable.  Say
        "ENV=''" instead.

   *    Always use echo " " (with a space) because of Eunice systems.

   *    Only use test with -r, -w, -f or  -d  since  those  are  the  only
        portable switches. In particular, avoid "test -x".

   *    Use only programs that came with V7, so that you know everyone has
        them.

   *    Use $contains when you want to grep conditionally, since  not  all
        greps  return a reasonable status.  Be sure to redirect the output
        to /dev/null, by using '>/dev/null 2>&1'.

   *    Use "if test" rather than "if [...]" since not every sh knows  the
        latter construct.

   *    Use the myread script for inputs so that they can do shell escapes
        and default evaluation.  The general form is

             case "$grimble" in
             '') dflt=452;;
             *) dflt="$grimble";;
             esac
             rp='How many grimbles do you have?'
             . ./myread
             grimble="$ans"

   *    Use the getfile script when asking for a file pathname in order to
        have optional ~name expansion and sanity checks. See the Getfile.U
        unit for a full decription.

   *    Always put a

                  $startsh

        at the top of every generated script that is going to be  launched
        or sourced by Configure.

   *    Never  assume  common  UNIX-isms like the fact that an object file
        ends with a .o and that a library name ends with .a.  Use the  $_o
        and $_a variables instead (see Unix.U).

   *    When doing a compile-link-execute test, always write it like this:

             $cc $ccflags $ldflags try.c -o try $libs

        because  some  systems  require  that  linking  flags be specified
        before the compiled target (with the exception of trailing linking
        libraries).

   *    Issue  important messages on file descriptor #4, by using '>&4' to
        redirect output. Only those  messages  will  appear  when  the  -s
        switch is given to Configure on the command line (silent mode).

   *    Always  try  to determine whether a feature is present in the most
        specific way--don't say "if bsd" when you can  grep  libc.   There
        are  many  hybrid systems out there, and each feature should stand
        or fall by itself.

   *    Always try to determine whether a feature is present in  the  most
        general way, so that other packages can use your unit.

   *    When in doubt, set a default and ask.  Don't assume anything.

   *    If  you think the user is wrong, allow for the fact that he may be
        right.  For instance, he could be running Configure on a different
        system than he is going to use the final product on.

   Metaconfig  reserves  the following names in your directory, and if you
   use such a name it may get clobbered or have other unforeseen effects:

         .MT/*
        Configure
        Wanted
        Obsolete
        configure
        config_h.SH
        confmagic.h
        U/*
        MANIFEST.new

   Additionally, Configure may clobber these names in the directory it  is
   run in:

        UU/*
        config.sh
        config.h

OPTIONS

   The following options are recognized by metaconfig:

   -d             Turn  on  debug  mode.  Not really useful unless you are
                  debugging metaconfig itself.

   -h             Print help message and exit.

   -k             Keep temporary directory, so that you  may  examine  the
                  working files used by metaconfig to build your Configure
                  script. Useful only when debugging the units.

   -m             Assume lots of memory and swap space. This will speed up
                  symbol lookup in source files by a significant amount of
                  time, at the expense of memory consumption...

   -o             Map obsolete symbols on new ones. Use this switch if you
                  still have some obsolete symbols in your source code and
                  do not  want  (or  cannot)  remove  them  for  now.  The
                  obsolete  symbols  are  otherwise ignored, although that
                  will give you a warning from metaconfig.

   -s             Turn silent mode on.

   -t             Trace symbols as they are found.

   -v             Turn verbose mode on.

   -w             Assume Wanted file is up-to-date.  This  will  skip  the
                  time and memory consuming phase of source code scanning,
                  looking for known symbols.  Use it only  when  you  know
                  your  source  file  have not changed with respect to the
                  pool of metaconfig symbols used.

   -G             Also provide a  GNU  configure-like  front  end  to  the
                  generated  Configure  script,  to  be  included  in  the
                  distribution as well. This is only a wrapper around  the
                  Configure  script naturally, but it lets people familiar
                  with the GNU tool to not  be  lost  when  facing  a  new
                  distribution.

   -L dir         Override  default library location. Normally only useful
                  for metaconfig maintainers  to  locally  use  the  units
                  being  developed instead of the publicly available ones.
                  The dir specified is the  one  containing  the  units  U
                  directory.

   -M             Allow  production of a confmagic.h file to automagically
                  remap some well-known symbols to some other alternative,
                  like  bcopy()  being  remapped transparently to memcpy()
                  when  not  available.   This   option   is   turned   on
                  automatically when a confmagic.h file exists in the top-
                  level directory. Simply remove that file if you wish  to
                  disable this option permanently.

   -V             Print version number and exit.

TUTORIAL

   This  (long) section is an introduction to metaconfig, in which we will
   learn all the basics. If you already know how to  use  metaconfig,  you
   may safely skip to the next section.

   Overview
   Usually  when you want to get some source package to compile on a given
   platform you have to edit the main Makefile (assuming there  is  one!),
   choose  a C compiler, make sure you have the proper libraries, and then
   fire the make command. If the package is reasonably  well  written,  it
   will  compile  (without  a  warning being an option :-). In itself, the
   last sentence is a real performance, since given the  variety  of  UNIX
   platforms available today and the diversity of flavours, that means the
   author of the package has gone into deep  trouble  to  figure  out  the
   right  choices  given  some standard trial, guessing and messing around
   with system includes and types.

   However, despite all his talent, the author cannot possibly  know  that
   some  system  has  a  broken system call, or that some system structure
   lacks one otherwise standard field, or simply whether a  given  include
   file  exists  or not. And I'm not considering the implicit assumptions,
   like the type returned by the malloc() function or the presence of  the
   rename()  system call to name a few. But that knowledge is necessary to
   achieve real portability.

   Now let's not abuse ourselves. Using that information requires  greater
   skills,  yet  it  can  lead  to more portable programs since it is then
   written in a system-independant fashion and relies  only  on  the  fact
   that  some  assumption  is  true  or false on a particular system, each
   assumption being unrelated with each other. That is to say, we  do  not
   say:  We're on a BSD system or we are on a USG system. That's too fuzzy
   anyway nowadays.  No, we want to say to the source  code:  this  system
   does  not have the rename() system call and malloc() returns a (void *)
   value.

   Metaconfig is a  tool  that  will  let  you  do  just  that,  with  the
   additional  benefit of not having to hand-edit the Makefile if all goes
   well. By running metaconfig, you create a shell script named Configure.
   Lots  of efforts have been devoted to the Configure script internals to
   ensure it will run on 99% of the existing shells available as  of  this
   writing.  Configure will probe the target system, asking questions when
   in doubt and gather all the answers in one single shell file, which  in
   turn  can  be used to automatically generate configured Makefiles and C
   include files.

   There is only a limited (but quite large) set of symbols available  for
   your  shell  scripts  and  C  programs.  They are all documented in the
   Glossary file.  All you need to do is learn about them and start  using
   them  to  address  portability  and  configuration  problems.  Then, by
   running metaconfig, a suitable Configure script will be  generated  for
   your package.

   The  Configure  script is built out several units (more than 300), each
   unit being responsible for defining a small number of  shell  and/or  C
   symbols.  Units are assembled together at the final stage, honoring the
   dependency graph (one unit may need the result of several  other  units
   which are then placed before in the script).

   Symbols
   Symbols  are the most important thing in the metaconfig world. They are
   the smallest recognized entity, usually a word, and can  be  granted  a
   value  at  the end of the Configure execution. For instance, the C pre-
   processor symbol HAS_RENAME is a metaconfig symbol that is guranteed to
   be  defined  if,  and  only  if,  the  rename() system call is present.
   Likewise, the $ranlib shell variable will  be  set  to  either  ':'  or
   'ranlib'  depending on whether the call to the ranlib program is needed
   to order a library file. How this works is not important for now,  what
   is important is to understand that those symbols are given a life (i.e.
   a value) upon Configure execution.

   Using symbols is relatively straightforward. In a C  source  file,  you
   simply use the symbol value, as a pre-processor directive (for instance
   an: #ifdef HAS_RENAME) or, if the symbol value is a string, directly as
   you  would use a macro in C. And in a shell file or a Makefile, you may
   reference a shell symbol directly.

   Actually, I'm lying, because that's not  completely  as  magic  as  the
   previous  paragraph  could  sound. In a C file, you need to include the
   Configure-produced config.h file, and you must wrap your  shell  script
   or  Makefile  in a .SH file and you may reference the shell symbol only
   in the variable substitution part of that .SH file. More on this later.

   Source Files
   Symbols may only appear in a  limited  set  of  source  files,  because
   metaconfig  will only scan those when looking for known symbols, trying
   to figure out which units it will need. You may  use  C  symbols  in  C
   source  files,  i.e. files with a .c, .h, .y or .l extension, and shell
   symbols are looked for only in .SH files.

   In order to get the value of a symbol, a C file needs  to  include  the
   special  config.h  file,  which is produced by Configure when C symbols
   are present. And .SH files are run through a  shell,  producing  a  new
   file.   However,  in  the  top  section  of  the  .SH file, the special
   config.sh file (also produced by running  Configure)  is  sourced,  and
   variable substitutions apply. Actually, config.h is produced by running
   the  metaconfig-produced  config_h.SH  file,   again   using   variable
   substitution.  So  we're  going  to  look at that a little more closely
   since this is the heart of the whole configuration scheme...

   Variable Substitution
   There is shell construct called here document which enables  a  command
   to  take  an  input  specified  within the script itself. That input is
   interpreted by the shell as a double-quoted string or a  single  quoted
   string depending on the form of the here document specification.

   To  specify  a  here  document,  the  '<<' token is used, followed by a
   single identifier. From then on, the remaining script  lines  form  the
   input  for  the  command, until the here document is found on a line by
   itself.  Shell substitution (including shell variable substitutions) is
   done  unless  the  identifier  is  surrounded  by  single  quotes.  For
   instance:

        var='first'
        tar='second'
        echo "--> first here document:"
        cat <<EOM
        var='$var'
        tar='$tar'
        EOM
        echo "--> second here document:"
        cat <<'EOM'
        echo $var
        echo $tar
        EOM
        echo "--> end."

   will produce, when run through a shell:

        --> first here document:
        var='first'
        tar='second'
        --> second here document:
        echo $var
        echo $tar
        --> end.

   The first here document has its content interpreted whilst  the  second
   one  is  output as-is. Both are useful in a .SH script, as we are about
   to see.

   Using .SH Scripts
   A .SH script is usually produced by running the MakeSH script other  an
   existing  file,  transforming  file into a file.SH. Let's take a single
   example. Here is a little script (let's call it intsize) which prints a
   single  message,  the size of the int datatype in C.  Unfortunately, it
   has the value hardwired in it, thusly:

        #!/bin/sh
        intsize='4'
        echo "On this machine, the int type is $intsize bytes"

   Let's run makeSH on it by typing 'makeSH  intsize'.  We  get  a  single
   intsize.SH file that looks like this:

        case $CONFIG in
        '')
             if test -f config.sh; then TOP=.;
             elif test -f ../config.sh; then TOP=..;
             elif test -f ../../config.sh; then TOP=../..;
             elif test -f ../../../config.sh; then TOP=../../..;
             elif test -f ../../../../config.sh; then TOP=../../../..;
             else
                  echo "Can't find config.sh."; exit 1
             fi
             . $TOP/config.sh
             ;;
        esac
        : This forces SH files to create target in same directory as SH file.
        : This is so that make depend always knows where to find SH derivatives.
        case "$0" in
        */*) cd `expr X$0 : 'X\(.*\)/'` ;;
        esac
        echo "Extracting intsize (with variable substitutions)"
        : This section of the file will have variable substitutions done on it.
        : Move anything that needs config subs from !NO!SUBS! section to !GROK!THIS!.
        : Protect any dollar signs and backticks that you do not want interpreted
        : by putting a backslash in front.  You may delete these comments.
        $spitshell >intsize <<!GROK!THIS!
        $startsh
        !GROK!THIS!

        : In the following dollars and backticks do not need the extra backslash.
        $spitshell >>intsize <<'!NO!SUBS!'
        intsize='4'
        echo "On this machine, the int type is $intsize bytes"
        !NO!SUBS!
        chmod 755 intsize
        $eunicefix intsize

   The  first  part  of  this  script (in the case statement) is trying to
   locate the config.sh file, in order to source it. The $CONFIG  variable
   is  false  by  default, by true when config.sh has been sourced already
   (which would be  the  case  if  this  file  was  executed  from  within
   Configure itself, but let's not confuse the issue here).

   Once the config.sh file has been sources, all the shell symbols defined
   by Configure are set. We know reach a second case  statement,  used  to
   change  the  current  directory  should  a  path  be used to reach this
   program (for instance if we said 'sh ../scripts/intsize.SH',  we  would
   first  run 'cd ../scripts' before continuing). If you do not understand
   this, don't worry about it.

   Here comes the  intersting  stuff.  This  script  uses  the  $spitshell
   variable,  and  it's  not  something  we  know about...yet. If you look
   through the Glossary file, you will see that this is a  variable  known
   by  metaconfig.  If  you  make  this file part of your distribution (by
   including it in the MANIFEST.new file, we'll come back  to  that  later
   on)  and  run  metaconfig,  then  the Configure script will determine a
   suitable value for this variable and it will be set in config.sh.  Same
   goes  for  $startsh  and  the  mysterious  $eunicefix  at the end. On a
   reasonable system, the relevant part of config.sh would look like this:

        spitshell='cat'
        startsh='#!/bin/sh'
        eunicefix=':'

   Ah! We're getting there. Now it looks familiar. We're facing  a  single
   cat  command  whose  input  comes  from  a  variable-interpolated  here
   document and whose output is redirected to intsize. The value  will  be
   that of $startsh, i.e. '#!/bin/sh'. Fine so far.

   Then  we reach the second here document expansion, to get the remaining
   of the script. This time, the here document  symbol  is  surrounded  by
   single  quotes so the contents will be appended verbatim to the intsize
   file.  So, by running 'sh intsize.SH', we get the following output:

        Extracting intsize (with variable substitutions)

   and by looking at the produced intsize file, we see:

        #!/bin/sh
        intsize='4'
        echo "On this machine, the int type is $intsize bytes"

   which is exactly what we had at the  beginning.  So  far,  it's  a  no-
   operation   procedure...  But,  how  marvelous!  It  so  happens  (pure
   coincidence, trust me!), that metaconfig knows about the $intsize shell
   symbol.  By  moving  the  initialization  of  intsize  to the variable-
   interpolated area of the  .SH  script  and  initializing  it  with  the
   Configure-computed  value,  and removing the now useless comments added
   by makeSH, we get:

        case $CONFIG in
        '')
             if test -f config.sh; then TOP=.;
             elif test -f ../config.sh; then TOP=..;
             elif test -f ../../config.sh; then TOP=../..;
             elif test -f ../../../config.sh; then TOP=../../..;
             elif test -f ../../../../config.sh; then TOP=../../../..;
             else
                  echo "Can't find config.sh."; exit 1
             fi
             . $TOP/config.sh
             ;;
        esac
        case "$0" in
        */*) cd `expr X$0 : 'X\(.*\)/'` ;;
        esac
        echo "Extracting intsize (with variable substitutions)"
        $spitshell >intsize <<!GROK!THIS!
        $startsh
        intsize='$intsize'
        !GROK!THIS!

        $spitshell >>intsize <<'!NO!SUBS!'
        echo "On this machine, the int type is $intsize bytes"
        !NO!SUBS!
        chmod 755 intsize
        $eunicefix intsize

   Of course, running this script through a shell will  again  output  the
   same  script.  But  if  we  run  Configure on a machine where an int is
   stored as a 64 bits quantity, config.sh will set intsize to 8  and  the
   intsize script will bear the right value and print:

        On this machine, the int type is 8 bytes

   which  is  correct.  Congratulations!  We  have just configured a shell
   script!!

   Producing config.h
   We can now have  a  look  at  the  way  config.h  is  produced  out  of
   config_h.SH. We know that running Configure produces a config.sh script
   (how exactly this is done is not strictly relevant here,  but  for  the
   curious,  it's  another  here  document  substitution  within Configure
   itself). The config_h.SH itself is built by metaconfig at the same time
   Configure  is,  provided  you  make use of at least one C symbol within
   your sources.

   Let's have a look at some random config_h.SH file to  see  what  really
   happens:

        case $CONFIG in
        '')
             if test -f config.sh; then TOP=.;
             elif test -f ../config.sh; then TOP=..;
             elif test -f ../../config.sh; then TOP=../..;
             elif test -f ../../../config.sh; then TOP=../../..;
             elif test -f ../../../../config.sh; then TOP=../../../..;
             else
                  echo "Can't find config.sh."; exit 1
             fi
             . $TOP/config.sh
             ;;
        esac
        case "$0" in
        */*) cd `expr X$0 : 'X\(.*\)/'` ;;
        esac
        echo "Extracting config.h (with variable substitutions)"
        sed <<!GROK!THIS! >config.h -e 's!^#undef!/define!' -e 's!^#un-def!#undef!'
        /*
         * This file was produced by running the config_h.SH script, which
         * gets its values from config.sh, which is generally produced by
         * running Configure.
         *
         * Feel free to modify any of this as the need arises.  Note, however,
         * that running config.h.SH again will wipe out any changes you've made.
         * For a more permanent change edit config.sh and rerun config.h.SH.
         */

        /* Configuration time: $cf_time
         * Configured by: $cf_by
         * Target system: $myuname
         */

        #ifndef _config_h_
        #define _config_h_

        /* bcopy:
         *   This symbol is maped to memcpy if the bcopy() routine is not
         *   available to copy strings.
         */
        /* HAS_BCOPY:
         *   This symbol is defined if the bcopy() routine is available to
         *   copy blocks of memory. You should not use this symbol under
         *   normal circumstances and use bcopy() directly instead, which
         *   will get mapped to memcpy() if bcopy is not available.
         */
        #$d_bcopy HAS_BCOPY /**/
        #ifndef HAS_BCOPY
        #ifdef bcopy
        #un-def bcopy
        #endif
        #define bcopy(s,d,l) memcpy((d),(s),(l))          /* mapped to memcpy */
        #endif

        /* HAS_DUP2:
         *   This symbol, if defined, indicates that the dup2 routine is
         *   available to duplicate file descriptors.
         */
        #$d_dup2 HAS_DUP2   /**/

        /* I_STRING:
         *   This symbol, if defined, indicates to the C program that it should
         *   include <string.h> (USG systems) instead of <strings.h> (BSD systems).
         */
        #$i_string I_STRING      /**/

        #endif
        !GROK!THIS!

   At the top of the file, we recognize the standard .SH construct that we
   have already studied in detail. Next comes the extraction of  the  file
   itself,  via a here document with variable substitutions. However, here
   we do not use a plain cat but a sed instead, since we need to  do  some
   further  editing  on-the-fly.  We'll  see why later on, so let's forget
   about it right now.

   We now reach the leading comment, and  the  file  is  tagged  with  the
   configuration  time,  the target system, etc... (those variables coming
   from the sourced config.sh file have been set up by  Configure).   That
   comment  header  is followed by a '#ifndef' protection to guard against
   multiple inclusions of this file. Then comes the heart of the file...

   It helps to know that  $d_*  and  $i_*  variables  are  set  to  either
   'define' or 'undef' by Configure, depending on whether a function or an
   include file is present on the system or not.  That means the:

        #$d_bcopy HAS_BCOPY /**/

   line will be expanded to either:

        #define HAS_BCOPY /**/

   if the $d_bcopy variable is set to 'define' or:

        #undef HAS_BCOPY /**/

   if $d_bcopy was set to 'undef', because  the  feature  was  not  there.
   However,  that's  not what gets written in the config.h file because of
   the sed filter we have already seen, which will  transform  the  second
   form into:

        /*#define HAS_BCOPY /**/

   That's a handy form for later editing of config.h because you only need
   to remove the leading '/*' if you want to override Configure's  choice.
   Likewise,  you  may  add  a single '/*' at the beginning of a '#define'
   line to avoid the definition of a particular symbol. This is  why  each
   symbol  definition  is  protected  by  a  trailing '/**/', to close the
   leading comment opened by '/*' (comments are not nested in C).

   Now transforming '#undef' into '/*#define' is nice, but if we  want  to
   actually  write  a '#undef', we're stuck... unless we write it as '#un-
   def' and let sed fix that to '#undef' while producing  config.h,  which
   is what is actually done here.

   The same kind of reasoning applies to those two lines:

        #$d_dup2 HAS_DUP2   /**/
        #$i_string I_STRING      /**/

   and assuming config.sh defines:

        d_dup2='define'
        i_string='undef'

   we'll get in the produced config.h:

        #define HAS_DUP2   /**/
        /*#define I_STRING      /**/

   Clear as running water? Good!

   Now  it  should  be  obvious  that  by including config.h in all your C
   source files, you get to  know  what  Configure  has  guessed  on  your
   system. In effect, by using those symbols, you are writing configured C
   code, since metaconfig will know that you need those symbols  and  will
   generate  a suitable config_h.SH file as well as all the necessary code
   in Configure to compute a proper value for them (by assigning values to
   associated shell variables).

   Running Metaconfig
   Let's  focus on the metaconfig program for a while to understand how it
   uses its  units  and  your  source  code  to  produce  all  the  needed
   configuration  files. If you intend to write new units, you should have
   a good understanding of the whole scheme.

   If there is no MANIFEST.new  file,  metaconfig  will  try  to  use  the
   MANIFEST   file   instead,  for  convenience.   Everywhere  we  mention
   MANIFEST.new, it can be understood as MANIFEST  provided  there  is  no
   MANIFEST.new file found at the root of your package.

   Assuming  your  MANIFEST.new  file  is  properly  set and lists all the
   source files you wish to configure, and that you have  run  packint  in
   your  root  source  directory  to  create  a .package file, you may run
   metaconfig and you'll get the following:

        $ metaconfig
        Locating units...
        Extracting dependency lists from 312 units...
        Extracting filenames (*.[chyl] and *.SH) from MANIFEST.new...
        Building a Wanted file...
          Scanning .[chyl] files for symbols...
          Scanning .SH files for symbols...
        Computing optimal dependency graph...
          Building private make file...
          Determining loadable units...
          Updating make file...
        Determining the correct order for the units...
        Creating Configure...
        Done.

   The first phase looks for all the units files (ending with .U)  in  the
   public  directory first, then in your private one. If you copy a public
   file in your private U directory (i.e. a directory named U at  the  top
   level  of  your  package), it will override the public version. Once it
   has a list of all the available units, it parses them and extracts  all
   the  ?MAKE:  lines  to  know about the dependencies and the known shell
   symbols. It also focuses on the ?H: lines to learn about the C  symbols
   and  which shell symbols needs to be computed to get a proper value for
   that C symbol (so we have another level of dependencies here).

   Next, the proper filenames are extracted from  the  MANIFEST.new  files
   and  a  Wanted file is built: that file lists all the C symbols and the
   shell symbols needed for that package. We first scan the  C-type  files
   for  C  symbols,  then  propagate  the dependencies to their associated
   shell symbols (gathered from ?H: lines). Next .SH files are scanned and
   finally all the shell symbols are known.

   A  temporary  Makefile  is  built  and metaconfig tries to make all the
   shell symbols to see what commands (listed on the second ?MAKE:  lines)
   are  executed,  and  thus which units are really needed. Optional units
   not otherwise required are removed and a second Makefile is  generated.
   This  time,  we  know  about all the units and their respective orders,
   optional units having been removed  and  default  values  computed  for
   their  shell symbols. The Configure script can then be generated, along
   with config_h.SH. We're done.

   Conventions
   Proper conventions needs to be  followed  to  make  the  whole  process
   sound.   There  is  a  case  convention for units and a variable naming
   convention.

   All units should have their first letter lower-cased, unless  they  are
   special  units. By special, we mean they do not really define new shell
   variables that can be used by the user in his  .SH  files,  but  rather
   units  producing  scripts  or  shell  variables  that  are  to  be used
   internally by the Configure script. Typical  examples  are  the  Init.U
   file  which  is  the  main  variable  initialization, or Myread.U which
   produces the myread script used almost everywhere in Configure  when  a
   question is to be asked to the user.

   Non-special units then subdivise in two distinct groups: units defining
   variables associated to a C symbol and units defining  shell  variables
   of  their  own. The first group is further divided in variables related
   to include files (their name begin with i_) and  variables  related  to
   other  definitions (name starting with d_). The second group have names
   standing for itself, for instance cc.U defines the $cc  shell  variable
   whose value is the C compiler to be used.

   Special  units  sometimes  reserve themselves some pre-defined variable
   and return "results" in other well-known variables. For  instance,  the
   myread  script  produced  by  Myread.U  expects  the prompt in $rp, the
   default answer in $dflt and places the user answer in $ans. This is not
   documented  in  this  manual  page: you have to go and look at the unit
   itself to understand which variables are used and how the unit is to be
   used.

   Using The Glossary
   The  Glossary  file  is automatically produced by the makegloss script,
   which extracts the information from  ?S:,  ?C:  and  ?MAKE:  lines  and
   reformats them into an alphabetically sorted glossary.  It is important
   to read the Glossary to know about the symbols you are allowed to  use.
   However,  the  Glossary  will  not  tell you how to use them.  Usually,
   that's up to you.

   One day, you will probably write your  own  units  and  you  will  know
   enough  about  metaconfig  to  do  so quickly and efficiently. However,
   never forget to properly document your work in the ?S: and  ?C:  lines,
   or  other  people will not be able to reuse it. Remember about the time
   where you had only the Glossary and this manual page to get started.

   Conclusion
   Now  that  you  know  the  metaconfig  basics,  you  should  read   the
   DESCRIPTION  section, then skip to the REFERENCE section to learn about
   all the gory details such as the allowed syntax for unit control  lines
   (lines  starting  with  a  '?')  or  the distinct MAKE commands you are
   allowed to use.

REFERENCE

   This section documents the internals of metaconfig, basically the  unit
   syntax, the special units you should know about and the hint files.

   General Unit Syntax
   A  metaconfig  unit  is  divided  into  two  distinct parts. The header
   section (lines starting with '?') and  a  shell  section  (code  to  be
   included in the Configure script). It is possible to add '?X:' comments
   anywhere within the unit, but the other '?' lines (also called  control
   lines) have a strict ordering policy.

   If  a control line is too long, it is possible to use a continuation by
   escaping the final new-line with a backslash and continuing on the next
   line (which should then be indented by spaces or tabs).

   The  following  is  a  formal description of each of the control lines.
   Unless stated otherwise, the order of this presentation is the order to
   be used within the unit.

   ?RCS: free text
        To be used for RCS comments, at the top of the unit.

   ?X: any text
        General purpose comments. May appear anywhere in the unit but must
        be left justfied. For RCS comments, please use the  ?RCS:  comment
        form.

   ?MAKE:symbol list: dependency list [+optional]
        This  is  the  first dependency line. The first symbol list should
        list all the symbols built by  this  unit  (i.e.  whose  value  is
        computed  by  the  shell  section  of the unit). Symbols should be
        space separated. If a defined symbol is for internal use only  and
        should  not appear in the generated config.sh file, then it should
        be  preceded  by  a  '+'  (not  to  be  confused   with   optional
        dependencies  defined  hereafter).   The  second  part of the list
        (after the middle ':') is the unit dependency.  It should list all
        the  needed  special units, as well as all the symbols used by the
        shell implementation. If a symbol is nedded but its  configuration
        value  is not critical, it can be preceded by a '+', in which case
        it is called a conditional dependency: its corresponding unit will
        be loaded if, and only if, that symbol is otherwise really wanted;
        otherwise the default value will be used.

   ?MAKE:tab command
        There can be one or  more  command  lines  following  the  initial
        dependency  lines.   Those commands will be executed when the unit
        is wanted to load them into Configure.  See  the  paragraph  about
        make  commands  for  more  information.  Note that the leading tab
        character is required before the command.

   ?Y:layout
        Declare a layout directive for this unit. That  directive  may  be
        one  of  the strings top, default or bottom (case does not matter,
        recommended style is to spell them out  uppercased).  If  omitted,
        default is assumed.

        This directive is only required if you wish to force a unit at the
        top or the bottom of  the  generated  Configure  script,  as  unit
        dependencies  permit it. Important questions may thus be forced at
        the beginning. Within the same  layout  class,  units  are  sorted
        alphabetically  with  two  special  cases  for  d_* and i_* units,
        forced respectively at the top and bottom of  their  classes  (but
        these should belong to the default class).

        It  you force at the top a unit whose dependencies require all the
        other  unit  to  precede  it,  you  achieve  nothing  interesting.
        Therefore,  that  directive  should really be used to increase the
        priority of some interactive units that  do  not  depend  on  many
        other user-visible symbols, like path-related questions.

   ?S:symbol_name [(obsolete symbol list)]:
        Introduces  a  shell  symbol.  This  first  line names the symbol,
        optionally followed by a list  enclosed  between  parenthesis  and
        giving  the  obsolete  equivalent.  Those obsolete symbols will be
        remapped to the new symbol_name if  the  -o  option  is  given  to
        metaconfig.

   ?S:any text, for Glossary
        Basically  a  comment  describing  the shell symbol, which will be
        extracted by makegloss into the Glossary file.

   ?S:. Closes the shell symbol comment.

   ?C:symbol_name [~ alias] [(obsolete symbol list)]:
        Introduces a new C symbol. The alias name is the name under  which
        the  C  symbol  will  be  controlled,  i.e. if the alias symbol is
        wanted, then that C symbol will  be  written  in  the  config_h.SH
        file. Usually, the alias is just '%<' (stands for the unit's name)
        and there is also a ?W: line mapping a C symbol to the alias. Also
        the  relevant parts of the ?H: lines are explicitly protected by a
        '?%<' condition.  See  the  symbol  aliasing  paragraph  for  more
        details.   The  remaining  of  the  line  is the optional obsolete
        symbol list, which lists old equivalents for the new symbol_name.

   ?C:any text, for Glossary and config_h.SH
        Basically a  comment  describing  the  C  symbol,  which  will  be
        extracted  by  makegloss  into the Glossary file and by metaconfig
        into the config_h.SH file if the symbol is wanted (or if its alias
        is wanted when symbol aliasing is used).

   ?C:. Closes the C symbol comment.

   ?H:?symbol:config_h.SH stuff
        This  is  the general inclusion request into config_h.SH. The line
        is only written when the guarding symbol is  really  wanted.  This
        general form is needed when C symbol aliasing was used. Otherwise,
        if you use one of the other  "standard"  forms,  the  guarding  is
        automatically done by metaconfig itself.

   ?H:#$d_var VAR "$var"
        Conditionally  defines  the  VAR C symbol into $var when is set to
        'define'. Implies a '?VAR:'  guarding  condition,  and  metaconfig
        automatically  links  VAR  to  its two shell variable dependencies
        (i.e. both $d_var and $var will be flagged as  wanted  if  VAR  is
        used in C sources).

   ?H:#define VAR [optional text]
        Always  defines  the VAR C symbol to some value. Implies a '?VAR:'
        guarding condition. An automatic shell dependency is made  to  the
        unit itself.

   ?H:#define VAR(x,y,z) $var
        Always defines the macro VAR to be the value of the $var variable.
        It is up to the unit to ensure $var holds a   sensible  value.  An
        automatic  dependency  between  the  C  macro  VAR  and  the shell
        variable is established, and the  whole  line  is  guarded  by  an
        implicit '?VAR:'.

   ?H:#$d_var VAR
        Conditionally defines VAR if $d_var is set to 'define'.  Implies a
        '?VAR:' guarding  condition.  An  automatic  shell  dependency  is
        generated towards $d_war.

   ?H:#define VAR "$var"
        Assigns  a configured value to the VAR C symbol. Implies a '?VAR:'
        gurading condition. An automatic shell dependency is generated  to
        link VAR and $var.

   ?H:. Closes the config_h.SH inclusion requests.

   ?M:C symbol: C dependencies
        Introduces   magic   definition   concerning  the  C  symbol,  for
        confmagic.h, and defines the guarding symbol for the remaining ?M:
        definitions. This line silently implies '?W:%<:C symbol', i.e. the
        unit will be loaded into Configure if the C symbol appears  within
        the  C  sources,  whether magic is used or not. The C dependencies
        are activated  when  magic  is  used,  in  order  to  force  their
        definition in config_h.SH. However, if magic is not used but the C
        symbol appears in the source without the  needed  C  dependencies,
        you  will  be warned every time the Wanted file is built, since it
        may  be  a  portability  issue  (and  also  because  the  unit  is
        unconditionally  loaded  into  Configure  whenever the C symbol is
        used, regardless of the other ?C: lines from the unit).

   ?M:cpp defs
        Defines the magic cpp mapping  to  be  introduced  in  confmagic.h
        whenever the concerned symbol is used. There is an implicit '?sym'
        guarding where sym is the symbol name defined by the  leading  ?M:
        line.

   ?M:. Closes the confmagic.h inclusion request.

   ?W:shell symbol list:C symbol list
        Ties  up  the  destiny  of  the  shell  symbols with that of the C
        symbols: if any of the C symbols listed is wanted,  then  all  the
        shell symbols are marked as wanted. Useful to force inclusion of a
        unit (shell symbol list set to '%<') when the presence of  some  C
        symbol  is  detected.  The shell symbol list may be left empty, to
        benefit from the side effect  of  C  symbol  location  within  the
        builtin pre-processor (symbol being defined for that pre-processor
        if located in the source). To look for patterns with  a  space  in
        them,  you need to quote the C symbols within simple quotes, as in
        'struct timezone'.

   ?V:read-only symbols:read-write symbols
        This is a metalint hint and should be used only in  special  units
        exporting  some  shell  variables. The variables before the middle
        ':' are exported read-only (changing them will issue  a  warning),
        while other symbols may be freely read and changed.

   ?F:files created
        This  line  serves two purposes: it is a metalint hint, and also a
        placeholder for future jmake use.  It  must  list  three  kind  of
        files: the temporary one which are created for a test, the private
        UU ones created in the UU directory for  later  perusal,  and  the
        public  ones  left in the root directory of the package. Temporary
        files must be listed with a preceding '!' character (meaning  "no!
        they're  not re-used later!"), private UU files should be preceded
        by a './' (meaning: to use them, say ./file, not just  file),  and
        public ones should be named as-is.

   ?T:shell temporaries
        Another  metalint  hint.  This  line lists all the shell variables
        used as temporaries within the shell section of this unit.

   ?D:symbol='value'
        Initialization value for symbols used as conditional dependencies.
        If  no  ?D:  line is found, then a null value is used instead. The
        metalint program will warn you if a symbol is used at  least  once
        as  a  conditional  dependency  and  does  not  have  a proper ?D:
        initialization. It's a good practice to add those lines even for a
        null  initialization  since it emphasizes on the possibly optional
        nature of a symbol.

   ?O:any message you want
        This directive indicates that this unit is obsolete  as  a  whole.
        Whenever  usage  of  any of its symbols is made (or indirect usage
        via dependencies),  the  message  is  output  on  the  screen  (on
        stderr).  You  can put one ore more lines, in which case each line
        will be printed, in order.

   ?LINT:metalint hints
        See the metalint manual page for an explaination of  the  distinct
        hints that can be used.

   ?INIT:initialization code
        The  initialization  code specified by this line will be loaded at
        the top of the Configure script provided the unit is needed.

   C Symbol Aliasing
   Sometimes it is not  possible  to  rely  on  metaconfig's  own  default
   selection  for  config_h.SH  comments  and  C symbol definition. That's
   where aliasing comes into play. Since it's rather  tricky  to  explain,
   we'll study an example to understand the underlying mechanism.

   The  d_const.U  unit  tries to determine whether or not your C compiler
   known about the const keyword. If it doesn't  we  want  to  remap  that
   keyword  to  a  null  string,  in  order  to  let  the program compile.
   Moreover, we want to automatically trigger the test when the const word
   is used.

   Here are the relevant parts of the d_const.U unit:

        ?MAKE:d_const: cat cc ccflags Setvar
        ?MAKE:    -pick add $@ %<
        ?S:d_const:
        ?S:  This variable conditionally defines the HASCONST symbol, which
        ?S:  indicates to the C program that this C compiler knows about the
        ?S:  const type.
        ?S:.
        ?C:HASCONST ~ %<:
        ?C:  This symbol, if defined, indicates that this C compiler knows about
        ?C:  the const type. There is no need to actually test for that symbol
        ?C:  within your programs. The mere use of the "const" keyword will
        ?C:  trigger the necessary tests.
        ?C:.
        ?H:?%<:#$d_const HASCONST     /**/
        ?H:?%<:#ifndef HASCONST
        ?H:?%<:#define const
        ?H:?%<:#endif
        ?H:.
        ?W:%<:const
        ?LINT:set d_const
        ?LINT:known const
        : check for const keyword
        echo " "
        echo 'Checking to see if your C compiler knows about "const"...' >&4
        /bin/cat >const.c <<'EOCP'
        main()
        {
             const char *foo;
        }
        EOCP
        if $cc -c $ccflags const.c >/dev/null 2>&1 ; then
             val="$define"
             echo "Yup, it does."
        else
             val="$undef"
             echo "Nope, it doesn't."
        fi
        set d_const
        eval $setvar

   First we notice the use of a ?W: line, which basically says: "This unit
   is wanted when the const keyword is used in a C  file.".  In  order  to
   conditionally  remap  const  to  a  null string in config.h, I chose to
   conditionally define HASCONST via $d_const.

   However, this raises a problem, because  the  HASCONST  symbol  is  not
   going  to  be used in the sources, only the const token is. And the ?H:
   line  defining  HASCONST  is  implicitely   guarded   by   '?HASCONST'.
   Therefore, we must add the explicit '?%<' constraint to tell metaconfig
   that those lines should be included in config_h.SH  whenever  the  '%<'
   symbol gets wanted (%< refers to the unit's name, here d_const).

   That's  almost perfect, because the ?W: line will want d_const whenever
   const is used, then the ?H: lines will get included in the  config_h.SH
   file.  However, the leading comment (?C: lines) attached to HASCONST is
   itself also guarded via HASCONST, i.e. it has an  implicit  '?HASCONST'
   constraint. Hence the need for aliasing the HASCONST symbol to '%<'.

   The   remaining   part   of   the  unit  (the  shell  part)  is  really
   straightforward.  It simply tries to compile a sample C  program  using
   the  const  keyword.   If  it can, then it will define $d_const via the
   $setvar fonction (defined by the  Setvar.U  unit).  See  the  paragraph
   about special units for more details.

   Make Commands
   On  the  ?MAKE:  command  line,  you  may  write  a shell command to be
   executed  as-is  or  a  special  -pick  command  which  is  trapped  by
   metaconfig  and  parsed  to see what should be done. The leading '-' is
   only there to prevent make from failing when the command returns a non-
   zero status -- it's not really needed since we use 'make -n' to resolve
   the dependencies, but I advise you  to  keep  it  in  case  it  becomes
   mandatory in future versions.  The syntax of the pick command is:

        -pick cmd $@ target_file

   where  $@  is  the  standard  macro  within  Makefiles standing for the
   current target (the name of the unit being built,  with  the  final  .U
   extension  stripped).  The cmd part is the actual metaconfig command to
   be  run,  and  the  target_file  is  yet   another   parameter,   whose
   interpretation  depends  on  the  cmd  itself. It also has its final .U
   extension stripped and normally refers to a unit file, unless it  start
   with  './'  in  which  case it references one of the metaconfig control
   files in the '.MT directory.

   The available commands are:

   add       Adds the target_file to Configure.

   add.Config_sh
             Fills in that part of Configure producing the config.sh file.
             Only   used  variables  are  added,  conditional  ones  (from
             conditional dependencies) are skipped.

   add.Null  Adds the section initializing all the shell variables used to
             an empty string.

   c_h_weed  Produces  the  config_h.SH file. Only the necessary lines are
             printed.

   cm_h_weed Produces the confmagic.h file. Only the necessary  lines  are
             printed.   This command is only enabled when the -M switch is
             given, or when a confmagic.h file already exists.

   close.Config_sh
             Adds the final 'EOT' symbol on a line by itself  to  end  the
             here document construct producing the config.sh file.

   prepend   Prepends the content of the target to the target_file if that
             file is not empty.

   weed      Adds the unit to Configure like the  add  command,  but  make
             some  additional  tests to remove the '?symbol' and '%symbol'
             lines from the target_file if the symbol  is  not  wanted  or
             conditionally wanted. The '%' form is only used internally by
             metaconfig while producing its own  .U  files  in  the  '.MT'
             directory.

   wipe      Same   as  add  really,  but  performs  an  additional  macro
             substitution.  The available  macros  are  described  in  the
             Hardwired Macros paragraph.

   As a side note, metaconfig generates a -cond command internally to deal
   with conditional dependencies. You should not use it by  yourself,  but
   you  will  see  it  if  scanning  the  generated  Makefile  in  the .MT
   directory.

   Hardwired Macros
   The following macros are recognized by the wipe command and  subsituted
   before inclusion in Configure:

   <BASEREV> The  base  revision  number  of  the  package,  derived  from
             .package.

   <DATE>    The current date.

   <MAINTLOC>
             The e-mail address of the maintainer of this package, derived
             from your .package.

   <PACKAGENAME>
             The name of the package, as derived from your .package file.

   <PATCHLEVEL>
             The  patch  level  of  the  metaconfig program (deprecated in
             favor of <REVISION>).

   <REVISION>
             The SVN revision level of the metaconfig program.

   <VERSION> The version number of the metaconfig program.

   Those macros are mainly used to identify the  metaconfig  version  that
   generated  a  particular  Configure script and for which package it was
   done. The e-mail address of the maintainer is hardwired in the  leading
   instructions that Configure prints when starting.

   Recent metaconfig versions understand a much more general syntax of the
   form:

             <$variable>

   which is replaced at Configure-generation time by the value of variable
   taken  from  your  .package  file.  Eventually, the old hardwired macro
   format will disappear, and <$baserev> will replace <BASEREV> in all the
   supplied units.

   Special Units
   The  following  special  units  are  used to factorize code and provide
   higher level functionalities. They either produce a shell  script  that
   can  be  sourced  or  a  shell  variable that can be eval'ed. Parameter
   passing is done via well-know variables, either named or anonymous like
   $1,  $2,  etc...  (which can be easily set via the shell set operator).
   When Configure executes, it creates and goes into a  UU  directory,  so
   every  produced  script  lies  in there and does not interfere with the
   files from your package.

   Here are the sepcial units that you should know about, and the  way  to
   use them.

   Cppsym.U
        This unit produces a shell script called Cppsym, which can be used
        to determine whether any symbol in a list  is  defined  by  the  C
        preprocessor  or  C compiler you have specified.  It can determine
        the status of any symbol, though the symbols in  (attribute  list)
        are more easily determined.

   Csym.U
        This  sets  the $csym shell variable, used internally by Configure
        to check whether a given C symbol is defined or not. A typical use
        is:

             set symbol result [-fva] [previous]
             eval $csym

        That  will set the result variable to 'true' if the function [-f],
        variable [-v] or array [-a] is defined, 'false'  otherwise.  If  a
        previous  value  is  given  and  the  -r  switch  was  provided to
        Configure (see the Configure Options paragraph), then  that  value
        is re-used without questioning.

        The  way  this  computation is done depends on the answer the user
        gives to the question Configure will ask about whether  it  should
        perform an nm extraction or not. If the exctraction was performed,
        the unit simply  looks  through  the  symbol  list,  otherwise  it
        performs  a  compile-link  test,  unless -r was given to reuse the
        previously computed value, naturally...

   End.U
        By copying this unit into your private U directory  and  appending
        dependencies  on the ?MAKE: line, you can force a given unit to be
        loaded into Configure even if it is  not  otherwise  wanted.  Some
        units may only be forced into Configure that way.

   Filexp.U
        This  unit  produces  a  shell  script  filexp  which  will expand
        filenames beginning with tildes. A typical use is:

             exp_name=`./filexp $name`

        to assign the expanded file name in exp_name.

   Findhdr.U
        This unit produces a findhdr script which is used  to  locate  the
        header  files  in  $usrinc  or  other  stranger  places  using cpp
        capabilities.  The script is given an include file base name  like
        'stdio.h'  or  'sys/file.h'  and  it  returns the full path of the
        inlcude file and a zero status if found, or an empty string and  a
        non-zero status if the file could not be located.

   Getfile.U
        This  unit  produces  a  bit of shell code that must be sourced in
        order to get a file name and make some sanity checks.  Optionally,
        a ~name expansion is performed.

        To  use  this  unit,  $rp and $dflt must hold the question and the
        default answer, which will be passed as-is to  the  myread  script
        (see   forthcoming   Myread.U).  The  $fn  variable  controls  the
        operation and the result is returned into $ans.

        To locate a file or directory, put 'f' or 'd' in  f~/.  If  a  '~'
        appears,  then  ~name  substitution  is allowed. If a '/' appears,
        only absolute pathnames are accepted and  ~name  subsitutions  are
        always  expanded before returning.  If '+' is specified, existence
        checks are skipped. If 'n' appears within $fn, then  the  user  is
        allowed to answer 'none'.

        Usually,  unless  you  asked  for  portability, ~name substitution
        occurs when requested. However, there are some times you  wish  to
        bypass portability and force the substitution. You may use the 'e'
        letter (expand) to do that.

        If the special 'l' (locate) type is used, then  the  $fn  variable
        must end with a ':', followed by a file basename. If the answer is
        a directory, the file basename will be appended before testing for
        file  existence.  This  is  useful  in locate-style questions like
        this:

             dflt='~news/lib'
             : no need to specify 'd' or 'f' when 'l' is used
             fn='l~:active'
             rp='Where is the active file?'
             . ./getfile
             active="$ans"

        Additionally, the 'p' (path) letter may  be  used  in  conjunction
        with 'l' to tell getfile that an answer without a '/' in it should
        be accepted, assuming that it will be in everyone's  PATH  at  the
        time this value will be needed.

        Also  useful  is the possibility to specify a list of answers that
        should be accepted verbatim, bypassing all the checks.  This  list
        must be within parenthesis and items must be comma separated, with
        no interleaving spaces.   Don't  forget  to  quote  the  resulting
        string   since  parenthesis  are  meaningful  to  the  shell.  For
        instance:

             dflt='/bin/install'
             fn='/fe~(install,./install)'
             rp='Use which install program?'
             . ./getfile
             install="$ans"

        would let the user only specify fully qualified paths referring to
        existing   files,  but  still  allow  the  special  "install"  and
        "./install" answers as-is (assuming of course something will  deal
        with  them  specially  later  on  in  the  chain since they do not
        conform with the general expected frame).

        If the answer to the question is 'none', then the existence checks
        are  skipped  and  the  empty  string is returned. Note that since
        getfile calls myread internally, all the features  available  with
        myread apply here to.

        If  a  completely  expanded  value  is  needed  (for instance in a
        Makefile), you may use the $ansexp variable which is always set up
        properly by getfile as the expanded version of $ans. Of course, it
        will not expand ~name if you did not allow that in the first place
        in the $fn variable.

   Inhdr.U
        This  unit  produces the $inhdr shell variable, used internally by
        Configure to check whether a  set  of  headers  exist  or  not.  A
        typical use is:

             set header i_header [ header2 i_header2 ... ]
             eval $inhdr

        That  will print a message, saying whether the header was found or
        not and set the i_header variable accordingly. If  more  than  one
        header  is specified and the first header is not found, we try the
        next one, until the list is empty or one is found.

   Inlibc.U
        This unit produces the $inlibc shell variable, used internally  by
        Configure  to  check whether a given C function is defined or not.
        A typical use is:

             set function d_func
             eval $inlibc

        That will print a message, saying whether the function  was  found
        or  not and set $d_func accordingly. Internally, it used the $csym
        routine.

   Loc.U
        This important unit produces a shell script loc which can be  used
        to  find out where in a list of directories a given file lies. The
        first argument specifies  the  file  to  be  located,  the  second
        argument  is  what  will  be returned if the search fails, and the
        reamining arguments are a list of directories where the file is to
        be searched. For instance:

             dflt=`./loc sendmail.cf X /usr/lib /var/lib/sendmail /lib`

        would  set  $dflt  to X if no sendmail.cf file was found under the
        listed directories, or something like /usr/lib/sendmail.cf on some
        systems. See also Getfile.U.

   MailAuthor.U
        This  unit  needs  to  be  included on the ?MAKE: line of your own
        private End.U to make it into Configure. It  offers  the  user  to
        register himself to the author, optionally being notified when new
        patches arrive or receiving them automatically  when  issued.  You
        need to install mailagent to do this (at least version 3.0).

   MailList.U
        This  unit  needs  to  be  included on the ?MAKE: line of your own
        private End.U to make it into Configure. It  offers  the  user  to
        subscribe  or  unsubscribe  to  a  mailing  list  where discussion
        related to the package are taking place. You need to run  packinit
        and answer the mailing list related questions to set up the proper
        variables  in  your  .package  before   this   unit   may   become
        operational.

   Myinit.U
        Copy  this  unit  into  your  private  U directory to add your own
        default values to some internal variables.  This  unit  is  loaded
        into  Configure  after  all  the default initializations have been
        done.

   Myread.U
        This unit produces the myread shell script that must be sourced in
        order  to  do  a read. It allows shell escapes, default assignment
        and parameter evaluation, as documented in the Instruct.U unit. It
        also  allows  dynamic setting of the -d option, which will be used
        for the remaining of the script execution.

        To use this unit, $rp must hold  the  question  and  $dflt  should
        contain  the  default  answer. The question will be printed by the
        script itself, and the result is returned in the $ans variable.

        Here is a typical usage:

             dflt='y'
             rp='Question?'
             . ./myread
             value="$ans"

        See the unit itself for more information.

   Oldconfig.U
        This unit must be part of your dependency ?MAKE: line when some of
        your  units  tries  to  reuse  an  old  symbol value. This unit is
        responsible  for  getting  the  old  answers  from  config.sh   or
        providing  useful  hints  when running on a given platform for the
        first time. See the Configure Hints paragraph for more information
        about hints.

   Prefixit.U
        The  purpose of this unit is to detect changes in the installation
        prefix directory to recompute automatically suitable defaults from
        previous  answers.   It  relies  on  the  value  of the $oldprefix
        variable  which  holds  the  previous  prefix  directory  when  it
        changed,  and  is empty otherwise. For instance, if the prefix was
        changed  from  /opt  to  /usr/local,  then  the  previous   binary
        installation   directory   will   be   changed  from  /opt/bin  to
        /usr/local/bin, or will remain unchanged if it was, say, /bin.

        You need to call set before issuing an eval on $prefixit, such as:

             set dflt var [dir]
             eval $prefixit

        which would set $dflt to $var or $prefix/dir depending on  whether
        the  prefix remained the same or not. If dir is the string none, a
        single space value in $dflt is kept as-is, even  when  the  prefix
        changes.  If  dir is omitted, then $dflt is set to an empty string
        if the prefix changed, to $var otherwise.

   Prefixup.U
        The intent of thit unit is similar to that of Prefixit.U, i.e.  it
        helps  fixing  the  default  string to accommodate prefix changes.
        However, the shell variable $prefixup, when evaluated,  will  only
        restore  ~name  expansions,  should  prefix  use  such  an  escape
        mechanism. Use it as:

             set dflt
             eval $prefixup

        before prompting via getfile for instance. If the prefix does  not
        make  use  of  ~name expanstion, then the above will be a no-op on
        the y variable, naturally.

   Typedef.U
        This unit produces the $typedef shell variable, used internally by
        Configure  to check whether a typedef exists or not. A typical use
        is:

             set typedef val_t default [ includes ]
             eval $typedef

        This will set the variable val_t to the value of  default  if  the
        typedef  was  not  found  among  the  listed  include files, or to
        typedef if found. If no include  files  are  specified,  the  unit
        looks  in  <sys/types.h> only. If you specifiy some includes, only
        those are looked at.

   Unix.U
        The purpose of this unit is to define  some  of  the  most  common
        UNIX-isms via variables which can be altered from the command line
        or via proper hint files. In particular, $_exe, $_o  and  $_a  are
        set. All the units should refer to $_o and not to .o directly. The
        '.' is part of these variables.

   Setvar.U
        This unit produces the  variable,  which  is  used  internally  by
        Configure  to set a define/undef value to a given symbol, emitting
        a warning when it suddenly changes  from  a  previous  value.  For
        instance:

             val="$define"
             set d_variable
             eval $setvar

        If  the  previous  $d_variable  value  was  non-null  and  $val is
        different, a "whoa" warning is issued.

   Whoa.U
        This unit produces the whoa script, which emits a warning when the
        value  in  variable  whose name is $var is not the same as its old
        previous value held in $was. Upon return, $td  and  $tu  hold  the
        proper  value  to  define  or undef the variable.  See examples in
        Inlibc.U.

   Builtin Pre-processor
   Each unit to be included in Configure is ran through  a  built-in  pre-
   processor. Pre-processor statements are introduced by the '@' character
   ('#' is the shell comment character). It functions merely as the C pre-
   processor  does  but  allows  for  shell and perl escapes. Here are the
   available functions:

   @if expression
             If expression is true,  continue  loading  code  until  @end,
             @elsif or @else.

   @elsif expression
             Alternative  choice.  If expression is true, continue loading
             code until @end, another @elsif or @else.

   @else     Default code to be loaded if the @if expression was false and
             none of the optional @elsif matched. Load until @end.

   @end      Close the conditional loading statement opened by @if.

   @define symbol
             Tells the pre-processor that symbol is defined from now on.

   The  conditional  expression can include symbol names (value is true if
   symbol is wanted or defined via @define or  shell/perl  escapes.  Those
   atoms  can  be combined using the traditional boolean operators '!' for
   negation, '&&' for logical and, and '||' for logical or.

   Text enclosed within single  brackets  is  a  shell  test,  while  text
   between double brakets is a perl test. Namely the expressions:

        { shell text }
        {{ perl text }}

   are translated into:

        if shell text >/dev/null 2>&1; then exit 0; else exit 1; fi
        if (perl text) {exit 0;} else {exit 1;}

   and the exit status is used in the standard way to get a boolean value,
   i.e. 0 is true and everything else is  false.  Note  that  only  simple
   conditions  can  be  expressed  in perl, until some complex code can be
   loaded within metaconfig and executed.

   The built-in pre-processor can be used to finely tune some  units  (see
   d_gethname.U  for  a complex example) depending on the symbols actually
   used by the program or the files  present  in  the  distribution.   For
   instance, the Oldconfig.U uses a test like:

        @if {test -d ../hints}

   and Configure will contain hint-dependent code only if there is a hints
   directory in the package's top level directory. Note that tests are ran
   from within the '.MT' directory, hence the needed '../' in the test.

   The pre-processor can also be used to avoid putting useless code when a
   symbol is not defined. Units defining  more  than  one  symbol  can  be
   protected  that  way (since the unit is loaded as a whole) by gathering
   symbol-dependent code within an @if/@end pair. For instance:

        @if I_TIME || I_SYS_TIME || I_SYS_TIME_KERNEL
        need_time_h='true'
        @else
        need_time_h='false'
        @end

   will test whether the source code makes any use of  one  of  the  three
   symbols  that control the time.h or sys/time.h inclusion and define the
   shell symbol accordingly. That gives Configure a feedback on  what  the
   sources need and avoid the drawback of having fixed frozen units.

   Via the '?W:' lines, you can get intersting combinations. For instance,
   the i_time.U unit needs to know whether the C sources make any  use  of
   the struct timezone type. Therefore, the line:

        ?W::timezone

   is  used  for  its  side-effect of defining the symbol timezone for the
   pre-processor. The unit code can then say:

        @if timezone
        for s_timezone in '-DS_TIMEZONE' ''; do
        @else
        s_timezone=''
        @end

        ... code using s_timezone ...

        @if timezone
        done
        @end

   and have an extra loop trying two successive values for the  s_timezone
   variable, but only if needed.

   Obsolete Symbols
   Obsolete  symbols  are  preserved  to  ease  the  transition with older
   metaconfig units. Unless the -o switch is  passed  to  metaconfig  they
   will  be  ignored. However, an Obsolete file will be generated, telling
   you which files are making use of those obsolete symbols and  what  are
   the new symbols to be used.

   The  lifetime for obsolete symbols is one full revision, i.e. they will
   be removed when the next base revision is issued (patch upgrades do not
   count  of  course). Therefore, it is wise to translate your sources and
   start using the new symbols as soon as possible.

   Configure Hints
   It may happen that the internal configuration  logic  makes  the  wrong
   choices.   For  instance,  on some platform, the vfork() system call is
   present but broken, so it should not be used. It  is  not  possible  to
   include that knowledge in the units themselves, because that might be a
   temporary problem which the vendor will eventually  fix,  or  something
   that was introduced by a new OS upgrade.

   Anyway,  for  all  those  tiny  little  problems  that  are too system-
   specific, metaconfig provides hint files support. To use it,  you  need
   to  create  a hints directory in the package's top level directory, and
   have it when you run metaconfig. That will load the  hint-related  part
   from Oldconfig.U.

   From  then  on,  you  may pre-set some of the shell variables Configure
   uses in an OS-specific .sh file. There  is  code  in  Oldconfig.U  that
   tries to guess which hint files are needed by computing a standard name
   based on the system OS name,  the  kernel  name,  the  release  number,
   etc...  Since  this  information  is  likely to change rapidly, I'm not
   documenting it here.  You  have  to  reverse  engineer  the  code  from
   Oldconfig.U.

   When  you  first release your package, your hints file directory should
   be empty.  If the users of your package complain that they have problem
   with Configure defaults on a particular system, you have to see whether
   this is a platform-specific problem or a general  one.  In  the  former
   case,  it's time to introduce a new hint file, while in the latter, the
   corresponding unit should be revised.

   For instance, SGI systems are known to have  a  broken  vfork()  system
   call,  as  of  this  writing.  And  the corresponding hint file name is
   sgi.sh.  So all you need to do is create a hints/sgi.sh file  in  which
   you write:

        d_vfork="$define"

   which  will always remap vfork on fork (see d_vfork.U). When running on
   SGI systems for the first time, Configure will detect that there is  an
   hints/sgi.sh  file, and that we are on an IRIX machine (the kernel name
   is often /irix), therefore it will propose sgi as a possible hint.   If
   the  user  accepts it, and since the $d_vfork value is modified via the
   $setvar call, a whoa! will be emitted to warn  that  we  are  about  to
   override the value computed by Configure.

   Note that you don't have to provide all the hints known by Oldconfig.U.
   If a hint file is missing, it  will  not  be  proposed  as  a  possible
   choice. The heuristic tests ran to compute the possible hint candidates
   are flaky. If you have new values or different tests, please send  them
   to me...

   Overriding Choices
   If  you create a config.over file in the top level directory, Configure
   will ask you if you wish to load it to  override  the  default  values.
   This  is  done  prior creation of the config.sh file, so it gives you a
   chance to patch the values stored in there.

   This is distinct from the hints approach in that it is  a  local  file,
   which  the  user  is  free  to create for his own usage. You should not
   provide such a  file  yourself,  but  let  the  user  know  about  this
   possibility.

   Configure Options
   The  Configure  script may be called with some options specified on the
   command line, to slightly modify its behaviour. Here  are  the  allowed
   options:

   -d        Use defaults for all answers.

   -e        Go on without questioning past the production of config.sh.

   -f file   Use  the  specified  file as a default configuration. If this
             switch  is  not  used,  the  configuration  is   taken   from
             config.sh, when present.

   -h        Print help message and exit.

   -r        Reuse  C symbols value if possible. This will skip the costly
             nm symbol  extraction.  If  used  the  first  time  (with  no
             previous  configuration  file), Configure will try to compile
             and link a small program in order to know about the  presence
             of a symbol, or absence thereof.

   -s        Silent  mode. Only strings printed on file descriptor #4 will
             be seen on the screen (that's the important  messages).  It's
             not  possible  to completely turn off any output, but you may
             use 'Configure -ders >/dev/null 2>&1' to have  a  full  batch
             run with no output and no user interaction required.

   -D symbol=value
             Pre-defines  symbol  to  bear the specified value. It is also
             possible to use '-D symbol' which will use a default value of
             'define'.

   -E        Stop  at the end of the configuration questions, after having
             produced a config.sh. This will not perform any 'make depend'
             or .SH files extraction.

   -K        Knowledgeable  user.  When you use this option, you know what
             you are doing and therefore the config.sh file will always be
             handled  as  if it was intended to be re-used, even though it
             might have  been  generated  on  an  alien  system.  It  also
             prevents  aborting  when  Configure  detects  an  unusable  C
             compiler or a wrong set of C flags.  Further shortcuts  might
             be  turned  on  by  this  option as well in the future.  This
             option is documented  in  the  Configure  usage  message,  to
             remind  us  about its existence, but the given description is
             hoped to be cryptic enough. :-)

   -O        Allow values specified via a -D or -U  to  override  settings
             from  any  loaded configuration file. This is not the default
             behaviour since the overriding  will  not  be  propagated  to
             variables  derived  from  those  you  are presently altering.
             Naturally, without -O, the  setting  is  only  done  when  no
             configuration  file is loaded, which is safe since derivative
             variables have not been computed yet...

   -S        Perform variable substitution on all the .SH files.  You  can
             combine  it with the -f switch to propagate any configuration
             you like.

   -U symbol=
             Pre-sets symbol to bear an empty value. It is  also  possible
             to use '-U symbol' which will set symbol to 'undef'.

   -V        Print  the  version  number  of the metaconfig that generated
             this Configure script and exit.

   Running Environment
   Upon starting, Configure creates a local UU  directory  and  runs  from
   there. The directory is removed when Configure ends, but this means you
   must run the script from a place where you can write, i.e. not  from  a
   read-only file system.

   You can run Configure remotely though, as in:

             ../package/Configure

   to  configure  sources  that are not present locally. All the generated
   files will be put in the directory  where  you're  running  the  script
   from. This magic is done thanks to the src.U unit, which is setting the
   $src and $rsrc variables to point to the package sources. That path  is
   full or relative, depending on whether Configure was invoked via a full
   or relative path.

   From within the UU subdirectory, you can use $rsrc to access the source
   files (units referring to source files link hints shall always use this
   mechanism and not assume the file is present in the parent  directory).
   All  the  Makefiles  should  use  the $src variable as a pointer to the
   sources from the top of the build directory (where Configure  is  run),
   either directly or via a VPATH setting.

   When  running  Configure  remotely,  the .SH files are extracted in the
   build directory, not in the source tree. However, it requires some kind
   of  a  make  support  to be able to compile things in a build directory
   whilst the sources lie elsewhere.

   Using Magic Redefinitions
   By making use of the -M switch, some magic remappings  may  take  place
   within  a  confmagic.h  file.  That  file  needs  to  be included after
   config.h, of course, but also after all the other needed include files.
   Namely:

        #include "config.h"
        ...
        ... other inclusions ...
        ...
        #include "confmagic.h"

   Typically,  confmagic.h will attempt to remap bcopy() on memcpy() if no
   bcopy() is  available  locally,  or  transform  vfork  into  fork  when
   necessary,  hence  making  it  useless  to  bother  about the HAS_VFORK
   symbol.

   This configuration magic is documented in the Glossary file.

   Unit Templates
   There is a set of unit templates in the  metaconfig  source  directory,
   which are intended to be used by a (not yet written) program to quickly
   produce new units for various kind of situations. No documentation  for
   this unfinished project, but I thought I would mention it in the manual
   page in case you wish to do it yourself and then contribute it...

AUTHORS

   Larry Wall <[email protected]> for version 2.0.
   Harlan Stenn <[email protected]> for important unit extensions.
   Raphael Manfredi <[email protected]>.
   Many other contributors for the metaconfig units. See the  credit  file
   for a list.

FILES

   LIB/dist/mcon/U/*.U
             Public unit files
   U/*.U     Private unit files
   LIB/dist/mcon/Glossary
             Glossary file, describing all the metaconfig symbols.
   Obsolete  Lists all the obsolete symbols used by the sources.
   Wanted    Lists all the wanted symbols.

                  where LIB is /usr/share/dist.

BUGS

   Units  are  sometimes  included  unnecessarily if one of its symbols is
   accidentally mentioned, e.g. in a comment.  Better too many units  than
   too few, however.

SEE ALSO

   pat(1), makeSH(1), makedist(1), metalint(1)

                            Version 3.5 PL0                  METACONFIG(1)



Opportunity


Personal Opportunity - Free software gives you access to billions of dollars of software at no cost. Use this software for your business, personal use or to develop a profitable skill. Access to source code provides access to a level of capabilities/information that companies protect though copyrights. Open source is a core component of the Internet and it is available to you. Leverage the billions of dollars in resources and capabilities to build a career, establish a business or change the world. The potential is endless for those who understand the opportunity.

Business Opportunity - Goldman Sachs, IBM and countless large corporations are leveraging open source to reduce costs, develop products and increase their bottom lines. Learn what these companies know about open source and how open source can give you the advantage.


Free Software


Free Software provides computer programs and capabilities at no cost but more importantly, it provides the freedom to run, edit, contribute to, and share the software. The importance of free software is a matter of access, not price. Software at no cost is a benefit but ownership rights to the software and source code is far more significant.

Free Office Software - The Libre Office suite provides top desktop productivity tools for free. This includes, a word processor, spreadsheet, presentation engine, drawing and flowcharting, database and math applications. Libre Office is available for Linux or Windows.


Free Books


The Free Books Library is a collection of thousands of the most popular public domain books in an online readable format. The collection includes great classical literature and more recent works where the U.S. copyright has expired. These books are yours to read and use without restrictions.

Source Code - Want to change a program or know how it works? Open Source provides the source code for its programs so that anyone can use, modify or learn how to write those programs themselves. Visit the GNU source code repositories to download the source.


Education


Study at Harvard, Stanford or MIT - Open edX provides free online courses from Harvard, MIT, Columbia, UC Berkeley and other top Universities. Hundreds of courses for almost all major subjects and course levels. Open edx also offers some paid courses and selected certifications.

Linux Manual Pages - A man or manual page is a form of software documentation found on Linux/Unix operating systems. Topics covered include computer programs (including library and system calls), formal standards and conventions, and even abstract concepts.