Provided by: dist_3.5-30-3.3_all bug

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 ram@acri.fr (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  developped  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 sytem structure lacks one otherwise  standard  field,  or
       simply  wheter  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 wether 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 explicitely 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/adm/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 accomodate 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 <lwall@netlabs.com> for version 2.0.
       Harlan Stenn <harlan@mumps.pfcs.com> for important unit extensions.
       Raphael Manfredi <ram@hptnos02.grenoble.hp.com>.
       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)