


       



       .














                                   Cook

                         A File Construction Tool




                                User Guide







                               Peter Miller

                         [4mmillerp@canb.auug.org.au[0m

































       .












       This document describes Cook version 2.30
       and was prepared 27 November 2021.






       This  document  describing  the  Cook  program, and the Cook
       program itself, are
       Copyright (C) 1988, 1989,  1990,  1991,  1992,  1993,  1994,
       1995,  1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
       2005, 2006, 2007 Peter Miller; All rights reserved.

       This program is  free  software;  you  can  redistribute  it
       and/or  modify  it under the terms of the GNU General Public
       License as published by the Free Software Foundation; either
       version  3  of  the  License,  or (at your option) any later
       version.

       This program is distributed in the  hope  that  it  will  be
       useful,  but  WITHOUT ANY WARRANTY; without even the implied
       warranty of MERCHANTABILITY  or  FITNESS  FOR  A  PARTICULAR
       PURPOSE.   See  the  GNU  General  Public  License  for more
       details.

       You should have received a copy of the  GNU  General  Public
       License    along    with   this   program.   If   not,   see
       <http://www.gnu.org/licenses/>.




















       Cook                                              User Guide



       [4m1.[24m  [4mIntroduction[0m

       This document describes [1mcook[22m, a maintenance tool designed to
       construct  files.   [1mCook [22mmay be used to maintain consistency
       between executable files and  the  associated  source  files
       that   are  used  to  generate  them.   The  consistency  is
       designated by the relative last-modified times of files  and
       is  thus  automatically adjusted each time a file is edited,
       compiled  or  otherwise  modified.    [1mCook   [22mvalidates   the
       consistency  of  a system of files and executes all commands
       necessary to maintain that consistency.

       [1mCook [22mis a tool for constructing files.  It is given a set of
       files to create, and instructions detailing how to construct
       them.   In   any   non-trivial   program   there   will   be
       prerequisites   to   performing  the  actions  necessary  to
       creating any file, such as extraction from a  source-control
       system.  [1mCook [22mprovides a mechanism to define these.

       When  a  program  is  being  developed  or  maintained,  the
       programmer will typically change one file of  several  which
       comprise the program.  [1mCook [22mexamines the last-modified times
       of the files to see when the prerequisites of  a  file  have
       changed,  implying that the file needs to be recreated as it
       is logically out of date.

       [1mCook [22malso provides a facility for implicit recipes, allowing
       users to specify how to form a file with a given suffix from
       a file with a different  suffix.   For  example,  to  create
       [4mfilename[24m[1m.o [22mfrom [4mfilename[24m[1m.c[0m

       [4m1.1[24m  [4mWhy[24m [4mYou[24m [4mWant[24m [4mTo[24m [4mUse[24m [4mCook[0m

          +o Cook is a replacement for the traditional [4mmake[24m(1) tool.

          +o There   is   a   [4mmake2cook[24m   utility  included  in  the
            distribution to help convert makefiles into cookbooks.

          +o Cook is more powerful than the traditional [4mmake[24m tool.

          +o Cook has true variables, not simple macros.

          +o Cook has a simple but powerful string-based description
            language  with  many  built-in  functions.  This allows
            sophisticated filename specification  and  manipulation
            without loss of readability or performance.

          +o Cook has user defined functions.

          +o Cook can build in parallel.

          +o Cook can distribute builds across your LAN.




       Peter Miller                                          Page 1





       Cook                                              User Guide



          +o Cook  is  able  to  build  your  project  with multiple
            parallel threads, with support for rules which must  be
            single threaded.  It is possible to distribute parallel
            builds over your LAN, allowing you to turn your network
            into a virtual parallel build engine.

          +o Cook  is  able  to  use fingerprints to supplement file
            modification times.   This  allows  build  optimization
            without contorted rules.

          +o Cook can be configured with an explicit list of primary
            source files.  This allow the dependency  graph  to  be
            constructed  faster  by  not  going down dead ends, and
            also allows better error messages when the graph  can't
            be  constructed.  This requires an accurate source file
            manifest.

          +o In addition to walking the dependency graph,  Cook  can
            turn  the  input  rules  into  a shell script, or a web
            page.

          +o Cook  has  special   [4mcascade[24m   dependencies,   allowing
            powerful   include  dependency  specification,  amongst
            other things.

          +o And Cook doesn't interpret tab differently to  8  space
            characters!

       If  you  are putting together a source-code distribution and
       planning to write a makefile, consider  writing  a  cookbook
       instead.   Although  Cook takes a day or two to learn, it is
       much more  powerful  and  a  bit  more  intuitive  than  the
       traditional [4mmake[24m(1) tool.

       [4m1.2[24m  [4mHow[24m [4mto[24m [4mUse[24m [4mthis[24m [4mManual[0m

       This manual is divided into two parts.

       The  first part is tutorial introduction to [1mcook[22m.  This part
       runs from chapter 4 to chapter 5.

       The second part is for reference and details  precisely  how
       [1mcook [22mworks.  This part runs from chapter 6 to chapter 14.

       Users  familiar  with  other  programs  similar  to [1mcook [22mare
       advised to skim the tutorial part  before  diving  into  the
       reference part.

       [4m1.3[24m  [4mAncient[24m [4mHistory[0m

       [1mCook  [22mwas  originally developed because I was marooned on an
       operating system without anything  even  vaguely  resembling
       [4mmake[24m(1).   This was in 1988.  Since I had to write my own, I
       added a few improvements.  When I finally  escaped  back  to


       Peter Miller                                          Page 2





       Cook                                              User Guide



       UNIX,  in  1990,  it  took  only  two  days  to port [1mcook [22mto
       SystemV.  I have since deleted all code  for  that  original
       operating  system,  although clues to its identity are still
       present.

       After I had [1mcook [22mup on UNIX, the progress the world had made
       caught  up  with  me.   It  was  gratifying that many of the
       features other make-oid authors had thought  necessary  were
       either already present, or easily and seamlessly added.

       [1mCook  [22mwas  written  with portability in mind.  This does not
       means it is entirely portable, but it comes close.  [1mCook [22mhas
       been  tested  on  numerous UNIX flavors.  This was made much
       simpler in 1994  when  I  started  using  the  GNU  Autoconf
       utility.   This  means  that when you obtain the sources for
       Cook, all you  have  to  do  is  run  the  [4mconfigure[24m  script
       included in the distribution and Cook will be configured for
       your  system.   See  the  BUILDING  file   in   the   source
       distribution for more information.

       In 1996 Cook had internationalization support added, so that
       users could  have  error  messages  and  other  warning  and
       informational  messages  printed  in  their native language.
       This was made possible by the GNU Gettext utilities.

       In 1997 Cook had a major re-write of significant portions of
       its inference engine.  This enabled the addition of parallel
       processing  support,  and  simplified  adding   user-defined
       functions to the cookbook language.



























       Peter Miller                                          Page 3





       Cook                                              User Guide



       [4m2.[24m  [4mCook[24m [4mfrom[24m [4mthe[24m [4mOutside[0m

       This  chapter is part of the tutorial on how to use the [1mcook[0m
       program.  It focuses on how to use [1mcook[22m, without needing  to
       know how [1mcook [22mworks internally.

       [4m2.1[24m  [4mWhat[24m [4mcan[24m [4mcook[24m [4mdo[24m [4mfor[24m [4mme?[0m

       By far the most common use of cook, by experts and beginners
       alike, is to issue the command
            cook
       and cook will consult its cookbook to see what needs  to  be
       done.

       In  general, [1mcook [22mis used to take a set of files and chew on
       them in some way to produce another set of  files;  such  as
       the  source  files  for a program, and how to turn them into
       the executable program  file.   In  order  for  [1mcook  [22mto  do
       anything  useful, it needs to know what to do.  "What to do"
       is contained  in  a  file  called  [4mHowto.cook[24m  in  the  same
       directory  as the files it is going to work on.  You need to
       execute the  cook command in the same directory  as  all  of
       the files.

       [4m2.2[24m  [4mWhat[24m [4mis[24m [4mcook[24m [4mdoing?[0m

       The [4mHowto.cook[24m file was written by the same person who wrote
       the source files.  It contains a set  of  recipes;  each  of
       which,  among  other  things,  contain  commands  for how to
       manipulate the files.  The [1mcook [22mprogram echos  each  of  the
       commands  it is about to execute, so that you can watch what
       it is doing as it goes.

       If the [4mHowto.cook[24m file contained only commands, you would be
       better  off  using  a  shell  script.   In  addition  to the
       commands is information telling [1mcook [22mwhich files need to  be
       constructed  before  other  files  can  be,  and  from  this
       information [1mcook [22mdetermines the order in  which  to  execute
       the  commands.   Also,  [1mcook  [22mexamines  other information to
       determine  which  commands  it  need  not  do,  because  the
       associated files are already up-to-date.

       [4m2.3[24m  [4mWhat[24m [4mcan[24m [4mcook[24m [4malways[24m [4mdo?[0m

       If  you  are  in a directory with a [4mHowto.cook[24m file, you can
       expect a few common requests to work

       cook clobber   This command can be expected  to  remove  any
                      files  from  the directory which [1mcook [22mis able
                      to reconstruct.

       cook all       This is the default action,  and  so  can  be
                      obtained by a simple cook request.  It causes
                      [1mcook [22mto construct some specific file  or  set


       Peter Miller                                          Page 4





       Cook                                              User Guide



                      of files.

       cook clean     This  is similar to "cook clobber" above, but
                      it only removes intermediate files,  and  not
                      not  the final file or files which "cook all"
                      constructs.

       In addition to the above, many [4mHowto.cook[24m  files  will  also
       define

       cook install   If  a  program  or  library  or  document  is
                      constructed  in  the  directory,   the   this
                      command  will  install  it  into  the correct
                      place in the system.

       cook uninstall The  reverse  of  the   above,   it   removes
                      something from the system.

       [4m2.4[24m  [4mIf[24m [4msomething[24m [4mgoes[24m [4mwrong[0m

       Most  errors  while  [1mcook [22mis constructing file are caused by
       errors in the source files, and not the [4mHowto.cook[24m file.  In
       general,  you  can fix the problems in the source files, and
       execute the [1mcook [22mcommand again, and [1mcook  [22mwill  resume  from
       the command which incurred the error.

       To  help  you  while editing the files with the errors, [1mcook[0m
       keeps a listing file of all the commands  it  executed,  and
       any output of those commands, in a file called [4mHowto.list[24m in
       the current directory.

       You may want [1mcook [22mto find all the errors it can  before  you
       do any editing, do do this, use the [1m-Continue [22moption (it may
       be abbreviated to [1m-c [22mfor convenience).

       [4m2.5[24m  [4mThe[24m [4mReference[24m [4mManual[0m

       For more information about the command  line  arguments  and
       options  of  the  various  commands  mentioned,  you  should
       consult the on-line manual pages.  The Cook Reference Manual
       is  also a good source of this information, and is available
       from the same place as you obtained this manual.














       Peter Miller                                          Page 5





       Cook                                              User Guide



       [4m3.[24m  [4mCook[24m [4mfrom[24m [4ma[24m [4mCookbook[0m

       This  chapter  describes  the  contents  and  meaning  of  a
       cookbook, a file which contains information [1mcook [22mneeds to do
       its job.  It focuses on what  a  cookbook  looks  like,  and
       touches on a few areas of how [1mcook [22mworks does its job.

       [4m3.1[24m  [4mWhat[24m [4mdoes[24m [4mCook[24m [4mdo?[0m

       The  basic  building  block  for  [1mcook  [22mis  the concept of a
       [4mrecipe[24m.  A recipe has three parts:

         1.  one or more files which the recipe  constructs,  known
             as the [4mtargets[24m of the recipe

         2.  zero  or  more  files  which are used by the recipe to
             construct the target, known as the [4mingredients[24m of  the
             recipe

         3.  one  or  more  commands to execute which construct the
             targets from the ingredients, known as the [4mbody[24m of the
             recipe.

       When  a  number  of  recipes  are  given,  some  recipes may
       describe how to cook the ingredients of other recipes.  When
       [1mcook   [22mis   asked   to  construct  a  particular  target  it
       automatically determines the correct order  to  perform  the
       recipe bodies to cook the requested target.

       [1mCook  [22mwould  not  be  especially  useful  if you had to give
       explicit recipes for how to cook every little thing.   As  a
       result,  [1mcook  [22mhas  the  concept  of an [4mimplicit[24m recipe.  An
       implicit recipe is  very  similar  to  an  explicit  recipe,
       except  that  the  targets and ingredients of the recipe are
       [4mpatterns[24m to be matched to file names, rather  than  explicit
       file  names.   This  means it is possible to write a recipe,
       for example which constructs a files with a name  ending  in
       `[1m.o[22m' from a file of the same name, but ending in `[1m.c[22m' rather
       than `[1m.o[22m'.

       In addition to recipes, [1mcook [22mneeds to know [4mwhen[24m to construct
       targets from ingredients.  [1mCook [22mhas been designed to cook as
       little as possible.  "As little as possible"  is  determined
       by  examining  when  each  file  was last modified, and only
       constructing targets when that are  out  of  date  with  the
       ingredients.


       [4m3.1.1[24m  [4mWhen[24m [4mis[24m [4mCook[24m [4museful?[0m
       From  the above description, [1mcook [22mmay be described as a tool
       for maintaining consistency of sets of files.





       Peter Miller                                          Page 6





       Cook                                              User Guide



       [4m3.1.2[24m  [4mWhen[24m [4mis[24m [4mCook[24m [4mnot[24m [4museful?[0m
       Cook is not useful for maintaining consistency  of  sets  of
       things  which  are  [4mwithin[24m  files and thus [1mcook [22mis unable to
       determine when they were modified.  For example, [1mcook [22mis not
       useful for maintaining consistency of sets of records within
       a database.


       [4m3.2[24m  [4mHow[24m [4mdo[24m [4mI[24m [4mtell[24m [4mCook[24m [4mwhat[24m [4mto[24m [4mdo?[0m

       Sets of recipes are gathered together into cookbooks.   When
       [1mcook  [22mis  executed  it  looks  for  a  cookbook  of the name
       [4mHowto.cook[24m in the current directory.  If you did not name  a
       file to be constructed on the command line, the first target
       in the cookbook will be constructed.

       The best way to  understand  how  to  write  recipes  is  an
       example.   In this example, a  program, [4mprog[24m, is composed of
       three files: [4mfoo.c[24m, [4mbar.c[24m and  [4mbaz.c[24m.   To  inform  [1mcook  [22mof
       this, the cookbook
            #include "c"

            prog: foo.o bar.o baz.o
            {
                    cc -o prog foo.o bar.o baz.o;
            }
       is sufficient for [4mprog[24m to be constructed.

       This cookbook has two parts.  The line
            #include "c"
       tells  [1mcook  [22mto  refer  to a system cookbook which tells it,
       among other things, how to construct a [4msomething[24m[1m.o [22mfile from
       a [4msomething[24m[1m.c [22mfile.

       The second part is a recipe.  The first line of this recipe
            prog: foo.o bar.o baz.o
                ...
       names  the  target,  [4mprog[24m, and the ingredients, [4mfoo.o[24m, [4mbar.o[0m
       and [4mbaz.o[24m.

       The next three lines
            ...
            {
                    cc -o prog foo.o bar.o baz.o;
            }
       are the recipe  body,  which  consists  of  a  single  [4mcc[24m(1)
       command  to  be executed.  Recipe bodies are always within [1m{[0m
       curly braces [1m}[22m, and commands always  end  with  a  semicolon
       ([1m;[22m).

       Thus, to update [4mprog[24m after any of the source files have been
       edited, it is only necessary to issue the command
            cook prog
       This could be simplified further, because [1mcook [22mwill cook the


       Peter Miller                                          Page 7





       Cook                                              User Guide



       targets of the first recipe by default; in this case, [4mprog[24m.

       The  power  of cook becomes more apparent when include files
       are considered.  If the files [4mfoo.c[24m and  [4mbaz.c[24m  include  the
       file  [4mdefs.h[24m,  this would automatically be detected by [1mcook[22m.
       If [4mdefs.h[24m were to be  edited,  and  [1mcook  [22mre-executed,  this
       would  cause  [1mcook  [22mto  recompile  both [4mfoo.c[24m and [4mbaz.c[24m, and
       relink [4mprog.[24m  The information about how  to  turn  [1m.c  [22mfiles
       into  [1m.o  [22mfiles  came  from the ``#include "c"'' line, which
       read in the C recipes distributed with Cook.

       [4m3.2.1[24m  [4mThe[24m [4mcommon[24m [4mprogram[24m [4mcase[0m
       The above example may be simplified even  further.   If  the
       four  files  [4mfoo.c[24m, [4mbar.c[24m, [4mbaz.c[24m and [4mdefs.h[24m all resided in a
       directory  with  a  path  of  [4m/some/where/prog[24m,   then   the
       [4mHowto.cook[24m file in that directory need only contain
            #include "c"
            #include "program"
       for  [4mprog[24m  to  be  cooked.   This  is  because the "program"
       cookbook looks for all  of  the  [4msomething[24m[1m.c  [22mfiles  in  the
       current  directory, compiles them all, and links them into a
       program named after the current directory.

       The default target in the "program" cookbook is called  [4mall[24m.
       The ingredient of [4mall[24m is the program named after the current
       directory.  Two other targets are supplied by this cookbook:

       clean removes all of the [4msomething[24m[1m.o [22mfiles from the  current
            directory.

       clobber removes   the   program   named  after  the  current
            directory, and also  removes  all  of  the  [4msomething[24m[1m.o[0m
            files from the current directory.

       [4m3.3[24m  [4mCreating[24m [4ma[24m [4mCookbook[0m

       To  use  [1mcook [22myou will usually need to define a cookbook, by
       creating a file, usually called [4mHowto.cook[24m  in  the  current
       directory, with your favorite text editor.

       This  file  has  a  specific  format.   The  format has been
       designed to be easy to learn,  even  for  the  casual  user.
       Much  of  the  power  of  [1mcook [22mis contained in how it works,
       without complicating the format of the cookbook.












       Peter Miller                                          Page 8





       Cook                                              User Guide



       Example  of  what  a  cookbook  looks  like  are   scattered
       throughout  this  document.   The  following  example is the
       entire cookbook for many programs, some quite large:
            #include "c"
            #include "yacc"
            #include "usr.local"
            #include "program"
       As you can see, even for many complex programs, the cookbook
       is remarkably simple.















































       Peter Miller                                          Page 9





       Cook                                              User Guide



       [4m4.[24m  [4mCooking[24m [4min[24m [4mParallel[0m

       Cook  is  able  to  use  the  dependency  information in the
       cookbook to schedule more than  one  recipe  body  at  once,
       where  they  are  independent.   In  large  projects this is
       almost always possible.

       Parallel  processing  is  of  most  use  on  multi-processor
       systems.  There are cases, however, when running two jobs at
       once on a workstation can take advantage of disk or  network
       latencies.

       Parallel  processing requires more resources than the simple
       case.  Because  more  commands  are  running,  more  CPU  is
       required,  but  also  more virtual memory and more temporary
       file space.  You need to be sure that cooking in parallel is
       a sensible thing to be doing.

       [4m4.1[24m  [4mCommand[24m [4mLine[24m [4mOption[0m

       The  -PARallel option is used to tell Cook to run the recipe
       bodies in parallel.  By default, 4  jobs  run  in  parallel.
       You  may  specify  the number of jobs after the option ([4me.g.[0m
       --par=2) if you wish.

       [4m4.2[24m  [4mCookbook[24m [4mVariable[0m

       It is also possible to set the number of  jobs  from  within
       the  cookbook by using the parallel_jobs variable.  This can
       be used to automate the selection of  the  number  of  jobs,
       based on the current host name:
            if [not [defined parallel_jobs]] then
            {
                    host = [os node];
                    if [in [host] cerberus] then
                            parallel_jobs = 3;
                    else if [in [host] zaphod] then
                            parallel_jobs = 2;
                    else if [in [host] hydra] then
                            parallel_jobs = 8;
            }
       In  this  way,  the number of jobs will be set appropriately
       for each machine,  provided  the  number  of  jobs  was  not
       already set by the command line option.

       [4m4.3[24m  [4mRecipe[24m [4mWriting[0m

       Most  recipes  run  in  parallel without difficulty, however
       some will require special  treatment.   The  problems  arise
       from conflict for resources - usually temporary files.






       Peter Miller                                         Page 10





       Cook                                              User Guide



       The  simplest  example  of  this  is  [4myacc[24m(1).   The  output
       filenames are hard-coded, even when you write a more general
       recipe:
            %.c: %.y
                    single-thread yy.tab.c
            {
                    [yacc] [yacc_flags] %.y;
                    sed "'s/[yY][yY]/%_/g'" yy.tab.c > [target];
                    rm yy.tab.c;
            }
       Replacing  the  YY  is a common method for getting more than
       one yacc grammar into a program.  We run into  trouble  with
       the  yy.tab.c  file  because  every one of the yacc grammars
       will need to use the same temporary file name.

       The single-thread clause tells cook to find  something  else
       to  do  if it discovers that it wants do two of these at the
       same time.

       The temporary file name may not be so evident as in the yacc
       case.   The GNU Autoconf utilities use a number of temporary
       files in the current directory, but none of them  appear  in
       the text of the recipes.
            %: %.in: config.status
                    single-thread conftest.subs
            {
                    CONFIG_FILES\=[target] CONFIG_HEADERS\= config.status;
            }
       It is common, if your project uses GNU Autoconf, to generate
       several files in this way.  Once the config.status script is
       produced,  all  of  these  files will then be candidates for
       cook to generate - but they can only be done one at a time.

       Other resources, such as tape drives, can also be  described
       in the single-thread clause.  You can do this by device name
       ([4me.g.[24m /dev/rmt/0) or by some descriptive string.  The single
       threading  is  performed  by mutually exclusive string sets,
       not by inode.

       [4m4.3.1[24m  [4mConcurrent[24m [4mExecution[24m [4mThreads[0m
       Each recipe, when its  actions  are  executed,  is  executed
       within  an execution thread.  Execution threads share almost
       everything in common; this includes all  of  the  variables,
       the state of the ``set'' statement, the stat cache, [4metc[24m.

       If  you  need  to  create  variable names, or temporary file
       names, which are unique to a  thread,  use  the  [thread-id]
       variable.   This variable has a unique value for the life of
       a thread.  No other concurrent thread  will  have  the  same
       value.

       Note,  however,  that  the  [thread-id]  values of completed
       threads will be re-used; this ensures that when it  is  used
       to  construct variable names, the variables will be re-used.


       Peter Miller                                         Page 11





       Cook                                              User Guide



       This prevents memory bloat when cooking large projects.

       [4m4.4[24m  [4mFile[24m [4mLocking[0m

       The above discussion applies to utilities which  perform  no
       file  locking,  and  thus cannot detect or sequence multiple
       accesses to a resource.  Other programs, such as those which
       access  databases,  may  have  quite  capable  file  locking
       mechanisms and are able to manage multiple parallel  updates
       on  their  own,  obviating  the  need  for the single-thread
       clause.

       [4m4.5[24m  [4mVirtual[24m [4mMachine[0m

       It is possible to simulate a parallel machine if you are  on
       a network.  Cook is able to distribute tasks to computers on
       a network, if it is given sufficient information.

       The first information Cook requires is the list of machines.
       This  is  done using the parallel_hosts variable.  [1mNote: [22mThe
       tasks will be distributed amongst these machines independent
       of  the setting of the parallel_jobs variable.  [4mi.e.[24m even if
       you are not doing parallel processing.
            parallel_hosts = larry curly moe;
       If you want to give one  machine  more  weighting  than  the
       others (say, because it is twice as fast) you simply name it
       more than once.  Cook will use these  names  in  round-robin
       fashion.

       [4m4.5.1[24m  [4mRemote[24m [4mShell[24m [4mCommand[0m
       Cook  uses  the Berkeley [4mrsh[24m(1) command to invoke the remote
       command.  You can set the command, or the command  and  some
       options, using the parallel_rsh variable.  The default value
       is
            parallel_rsh = rsh;
       In  order  to  work  in  a  useful  way,  Cook  makes   some
       assumptions about your environment and your account:

          +o That your system administrators allow [4mrsh[24m(1) to be used
            on your network.

          +o That your account name is  the  same  on  [4mall[24m  machines
            (otherwise  not  even the rsh -l [4mlogin-name[24m option will
            help).

          +o That the /etc/hosts.equiv file, or your ~/.rhosts file,
            is set on [4mall[24m machines so that you don't need to give a
            password.

          +o That all of the necessary  files  and  directories  are
            mounted  in  exactly  the  same  place  on  all  of the
            machines; and that they  are  [4mthe[24m  [4msame[24m  [4mfiles[24m  on  all
            machines,  via  NFS  or similar.  Automounters can make
            this especially messy.


       Peter Miller                                         Page 12





       Cook                                              User Guide



          +o That your account start-up scripts  set  the  necessary
            environment settings, [4me.g.[24m command search PATH, without
            any intervention required.

          +o That all of the machines are of the same  architecture,
            or that the architecture doesn't matter.

          +o That  the  system time is synchronized on all machines,
            using [4mrdate[24m(1) from [4mcron[24m(8), or using NTP, or similar.

       [4m4.5.2[24m  [4mLimitations[0m
       There are some inherent limitations in the [4mrsh[24m(1) protocol.

          +o Your current  environment  variable  settings  are  not
            transferred  across.  Neither are [4mulimit[24m settings, [4metc[24m.
            If any are important, you need to write the cookbook to
            explicitly replicate them.

          +o The  exit  status of the remote command is not reported
            in the exit status of the [4mrsh[24m(1) command1.   There  are
            internal  contortions  used  by Cook to obtain the exit
            status; error about mysteriously  named  files  usually
            indicate  that  one or more of the above assumptions is
            being broken.

       [4m4.5.3[24m  [4mSecure[24m [4mShell[0m
       It is possible to use the  Secure  Shell  (ssh)  instead  of
       Remote  Shell  (rsh).   This  gives you fully authenticated,
       fully encrypted sessions, both over your intranet  and  even
       over   the   Internet.   Once  you  have  it  installed  and
       configured correctly, you simply replace the [4mrsh[24m command  in
       the above examples with the [4mssh[24m command.

       This is accomplished by setting
            parallel_rsh = "ssh";
       Somewhere near the top of your cookbook.

       [4m4.5.4[24m  [4mHost[24m [4mBinding[0m
       In  some  cases, such as licensing conditions, some commands
       will only run on  a  limited  set  of  hosts.   Rather  than
       perform  all commands on those hosts, it is possible to bind
       recipes to  specific  hosts.   This  binding  overrides  the
       parallel_hosts variable.
            %.c: %.esql
                    host-binding shylock
            {
                    esql %.esql > [target];
            }
       This example says that the embedded SQL preprocessor is only

       ____________________

       1. The Berkeley sources certainly don't contain code  to  do
          this.    Do   any   other  vendors  have  a  more  useful
          implementation?

       Peter Miller                                         Page 13





       Cook                                              User Guide



       to  be  run  on  the  database  server  called  ``shylock'',
       probably  due  to usurious licensing fees.  However, you may
       want to perform your other development  activities  on  more
       lightly  loaded  machines;  this clause only applies to this
       one recipe, other recipes behave as normal.

       The host-binding clause may have more than one  host  named,
       and  they  will  be  used in round-robin fashion.  This is a
       recipe-level variant of the parallel_hosts variable.

       The  host-binding  clause  will  apply  independent  of  the
       setting  of  the  settings  parallel_jobs and parallel_hosts
       variables.

       The recipe level host-binding overrides the  cookbook  level
       parallel_hosts when determining which remote hosts should be
       used.

       If the list of hosts given to  the  host-binding  clause  is
       empty,  the local host will be used (normal recipe execution
       will occur).

       If you need to include the local host in  the  round  robin,
       use localhost or [os node], however this will behave exactly
       the same as for a remote host.   You  should  also  consider
       hard  coding the name, that way you get the same behavior no
       mater which of the machines in  the  round  robin  the  Cook
       command is executed on.

       [4m4.5.5[24m  [4mLoad[24m [4mBalancing[0m
       It   is   possible  to  use  [4mhost-binding[24m  to  perform  load
       balancing.  This is accomplished by using [4mrup[24m(1) to discover
       which  hosts are least busy, and then using this information
       to invoke the system's [4mrsh[24m(1).

       This may be accomplished by using
            parallel_rsh = "cook_rsh";
       somewhere near the top of your cookbook (or [4mcook_rsh[24m [4m-s[24m  for
       secure  shell).  You then give classes of hosts to the [4mhost-[0m
       [4mbinding[24m clause of the recipes,  rather  than  specific  host
       names.   See  [4mcook_rsh[24m(1) for more information about setting
       up classes of hosts.

       If you still need  to  give  specific  host  names  to  some
       recipes, [4mcook_rsh[24m(1) will cope with this, too.

       [4m4.6[24m  [4mVirtual[24m [4mMachine,[24m [4mRevisited[0m

       It  is  also possible to have Cook run multiple processes in
       parallel without having to know what machines are available.
       This  method  puts  control  of the network resources in the
       hands of an  external  program,  one  example  of  which  is
       cook_rsh, distributed with Cook.



       Peter Miller                                         Page 14





       Cook                                              User Guide



       Once you have such a virtual network defined it becomes very
       easy  to  build   projects   for   multiple   platforms   or
       architectures  in  the  same  build.   It also allows easily
       adding new machines, or disabling machines for  maintenance.
       The  virtual  network  can  be  changed  at any time without
       disturbing ongoing development.

       The following examples will have the form allowing  multiple
       architecture builds, but of course they will work for single
       architecture as well.

       [4m4.6.1[24m  [4mcook_rsh[0m
       The  cook_rsh  system  is  just  one  way  of  defining  the
       capabilities  of  a  given  network  in  a way that a single
       program can make the best choice of machine for a given job.
       It  does  so in a way that is reliable and does a decent job
       of balancing loads  across  available  machines,  even  with
       multiple developers doing builds at the same time.

       Each  job  that requested via cook_rsh picks the appropriate
       machine from those able to do the job  at  that  instant  in
       time.   In  contrast to parallel_hosts or host-binding hostA
       hostB etc, it does not work from a list which was current at
       the  time  a  cook  process  was  started.   Thus it is less
       vulnerable to machines going off line or becoming overloaded
       as time passes.

       Currently  cook_rsh uses rsh to actually execute the job, so
       requires the same network setup.  The next version  may  use
       multicast instead for even finer control and reliability.

       There  are  minor  differences  in the setup to use cook_rsh
       control.  The first is that Cook no longer requires  a  list
       of  machines.  It is not necessary to set the parallel_hosts
       variable.  The parallel_rsh variable is set as:
            parallel_rsh = cook_rsh -v;
       The -v option produces information as to  what  machine  was
       actually picked for each job.

       [4m4.6.2[24m  [4mHost[24m [4mBinding[0m
       All  recipe bodies which should run in parallel need a host-
       binding setting.  Rather than list the hosts to be  used  we
       form  a  name  which  is  used  by  cook_rsh  to  select  an
       appropriate machine.  This name may include an  architecture
       component and a operation component.
            %1/%.o: %.c
                    host-binding %1_C
            {
                    [%1_cc] -o [target] -c [resolve %.c];
            }

            %1/%2: [addprefix %1/ [%2_objs]]
                    host-binding %1_L
            {


       Peter Miller                                         Page 15





       Cook                                              User Guide



                    [%1_ld] -o [target] [resolve [need]];
            }
       This   example   says   that  the  compiles  for  a  certain
       architecture should take place on any machine designated  as
       a  compile  host  for  that  architecture.  And linking jobs
       should go to machines designated as a  link  host  for  that
       architecture.   Of course the same machine could probably do
       both jobs, but you get to define it  as  you  see  fit,  and
       change  the  designations  from  moment  to moment.  Current
       designations per architecture are:

       _C   Compile   (Compile source code)
       _L   Link      (link binary programs)
       _T   Test      (run automatic tests)
       _B   Build     (including cooking, or generic jobs)
       And others may be added if necessary by simple extension.

       [4m4.6.3[24m  [4mAdministration[24m [4mof[24m [4mcook_rsh[0m
       The definition of the virtual network used  by  cook_rsh  is
       contained in just a two configuration files.  One file lists
       designations,  and  lists   machines   belonging   to   each
       designation.   The  other  is  an  [1mexclude [22mfile, which lists
       machines which should not be used for whatever reason.

       The designations file may be created by hand if desired  but
       a  utility  called  rate_hosts is provided that can generate
       the host_lists.pl file, possibly after being customized  for
       the particular requirements of a given environment.

       The  exclusion  file  lists  machines  that  should never be
       selected.  The exclusion file can be edited at any time  and
       adding  a  machine  will prevent any further jobs from going
       its way.  Removing the name will again  allow  selection  of
       that  machine.   How  soon a job actually goes there depends
       greatly on the network utilization.  The exclude_hosts  file
       contains  machine  names  and optional comments.  An example
       exclude_hosts file might contain:
            # list of hosts to exclude from arch_hosts lists
            # for whatever reason.
            monolith        # not a development machine - the FTP host
            namshub         # developer test station
            tiamat          # unreliable configuration
            locutus         # Being upgraded
       This is handy for maintenance on machines.  If a  particular
       machine  needs to be brought down you simply add its name to
       the exclusion file.  Checking its  process  list  will  tell
       when any currently running remove jobs are done.  After that
       it can safely be brought down without affecting  any  active
       builds.







       Peter Miller                                         Page 16





       Cook                                              User Guide



       [4m5.[24m  [4mInclude[24m [4mFile[24m [4mDependencies[0m

       A significant factor in a cookbook accurately describing the
       dependencies in a program are the include file dependencies.
       There  are  three methods for doing this in Cook.  The first
       is easily understandable but is too slow  to  use  on  large
       projects,  the  second is a little harder to understand, but
       works well for large projects.  The third method  is  rather
       convoluted,  but works well for projects with many thousands
       of source  files  and  multiple  simultaneous  architectures
       built within the same source tree.

       The  recipes  here  are merely examples and starting points;
       you will almost certainly need to enhance them to  suit  the
       needs  of  your  projects.   Areas  you will need to address
       include (a) the existence of cc -I[4mpath[24m options, (b) the  use
       of  search_list variable and the [resolve] function, and (c)
       heterogeneous development.  The  techniques  also  apply  to
       other  languages, such as Fortran, Pascal and Roff, but each
       requires a language-specific include scanning program2.

       [4m5.1[24m  [4mThe[24m [4mManual[24m [4mMethod[0m

       Well,   actually  there  are  four  methods,  if  you  count
       maintaining the dependencies manually.  This has the serious
       defect  that  humans  tend to [4mforget[24m to update the cookbook.
       On a large project not all developers are familiar with  the
       workings  of  Cook,  and  so they shy away from updating the
       cookbook.  By finding ways to  automate  include  dependency
       processing,  we reduce the risk that a developer will forget
       to update the cookbook, and we  reduce  the  risk  that  the
       cookbook's dependency information is out-of-date.

       Automatic  include  dependency  methods described below have
       flaws, and can never replace a  human  for  flexibility  and
       domain  knowledge.   On  the  other hand, humans have better
       things to do with their time than grope  files  for  include
       file dependencies (like write neat software).

       [4m5.2[24m  [4mDebugging[24m [4mCookbooks[0m

       Before  we  proceed  further, it is worth spending some time
       covering some of the methods for  debugging  your  cookbook,
       because small mistakes in implementing the methods below can
       become quite difficult to locate.

       [4m5.2.1[24m  [4mCommand[24m [4mLocations[0m
       Usually Cook will echo all the commands  it  executes,  just
       before executing them.  If you add the line
            set tell-position;

       ____________________

       2. The [4mc_incl[24m program understands Roff, you just need to use
          the -r option.

       Peter Miller                                         Page 17





       Cook                                              User Guide



       near  the  top  of your cookbook, Cook will add the filename
       and line number within  the  cookbook  to  each  command  it
       echoes.   This  can  be  useful in figuring out which recipe
       Cook actually chose to execute.

       [4m5.2.2[24m  [4mPrinting[24m [4mStuff[0m
       Often you will want to have Cook  print  various  pieces  of
       information.   The  wrong  way  to do it is with the shell's
       "echo" command
            echo variable "=" [variable];
       because  this  invokes  another  process  (which  can   make
       debugging  parallel  cookbooks  harder)  and  because of the
       optional [4mdata[24m [4m...[24m [4mdataend[24m which can follow commands (see the
       command  statement  in the language definition, below).  The
       correct method is to call the "print" function, like this
            function print [__FILE__]: [__LINE__]: variable "=" [variable];
       Note the use of the __FILE__ and  __LINE__  builtins,  which
       provide you with cookbook position information.

       [4m5.2.3[24m  [4mTrigger[24m [4mIngredients[0m
       Another useful piece of information is the ingredients which
       caused  Cook  to  invoke  a  particular  recipe  body.   The
       following function
            function say-why =
            {
                    if [count [@1]] then
                            @1 = [@1];
                    if [count [@2]] then
                            @2 = [@2];
                    local tt = [target];
                    if [defined targets] then
                            tt = [targets];
                    local t = ;
                    if [in [count [younger]] 0 1 2 3] then
                    {
                            function print [@1] [@2]
                                    Building [target]
                                    because of [younger];
                    }
                    else
                    {
                            function print [@1] [@2]
                                    Building [target] because of
                                    [wordlist 1 3 [younger]] et al;
                    }
            }
       can be inserted at the beginning of a recipe
            %.o: %.c
            {
                    function say-why [__FILE__] [__LINE__];
                    cc -c %.c;
            }
       to  say  why the recipe was invoked.  This will even include
       dependencies automatically determined by all of the  methods


       Peter Miller                                         Page 18





       Cook                                              User Guide



       which follow, not just those named on the right-hand-side of
       the recipe itself.

       [4m5.3[24m  [4mTools[0m

       All  of  the  automated  include  file  dependency   methods
       described  below  use  the [4mc_incl[24m(1) program included in the
       Cook distribution.  It has a number of options tailored  for
       use  with  Cook.   For  exact  information  about the [4mc_incl[0m
       command, consult the on-line [4mman[24m(1) system (it  should  have
       been installed) or the Cook Reference Manual.

       Other  tools  are  available.   The  commonest is to use the
       gcc-M option, which produces a list of include files on  the
       standard  output.   Because the gcc-M output is aimed at GNU
       Make, you will need an [4mawk[24m(1) or [4msed[24m(1)  script  to  massage
       the output into a format suitable for Cook.

       [4m5.4[24m  [4mThe[24m [4mSmall[24m [4mMethod[0m

       The  easiest  way to determine a file's include dependencies
       is within the recipe's ingredients.
            %.o: %.c: [collect c_incl -api %.c]
            {
                    cc -c %.c;
            }

       Note the second colon - the [4msecond[24m set of  dependencies  are
       only  evaluated after Cook has chosen to activate the recipe
       (based on the first set).  This does not guarantee that  the
       file  exists  yet  (it  may  have  to be generated by [4mlex[24m or
       [4myacc[24m), which is why the  --Absent-Program-Ignore  option  is
       required.

       This  method  has  the  advantage  of simplicity.  It uses a
       single recipe which reads the way recipes usually read,  and
       does not contain any unusual constructs.

       There  are two problems with this method.  The first is that
       it doesn't scale well.  When there are  only  a  few  source
       files,  the processing burden of running [4mc_incl[24m for every [1m.c[0m
       file every time Cook is invoked is hardly  noticeable.   The
       [4mc_incl[24m  program  caches the results of its scans, so that is
       can minimize the length of time taken, and this does help  a
       little.   However  projects  with  hundreds  or thousands of
       files find  even  the  cached  performance  an  unreasonable
       burden;  it is constantly re-calculating something which has
       not changed from one run to the next.

       The second problem is that the [4mc_incl[24m program  is  run  when
       the  dependency  graph  is being built, not when it is being
       walked.  This means that the [1m.c [22mfile (or  a  subordinate  [1m.h[0m
       file) may have been out-of-date at the time.  When the graph
       is walked, it will have been regenerated, and the  two  sets


       Peter Miller                                         Page 19





       Cook                                              User Guide



       of  include  files,  those  determined  by  [4mc_incl[24m  at graph
       building time, and those seen by [4mcc[24m at graph  walking  time,
       may not agree - which may result in compile-time errors.

       [4m5.5[24m  [4mThe[24m [4mLarge[24m [4mMethod[0m

       For  projects  with large numbers of files, hundreds or even
       thousands, it is necessary to re-calculate the include  file
       dependencies  only  when a [1m.c [22mfile changes, or a subordinate
       [1m.h [22mfile.   Ideally,  Cook  should  access  this  information
       directly,  rather  than running a program to determine it or
       to fetch it.

       The first task is  to  move  the  information  which  [4mc_incl[0m
       caches into a format that Cook can access directly; Cook can
       then read in this information as it scans the cookbook.   By
       making  a  separate ``dependency'' file for each [1m.c [22mfile, we
       can use existing Cook mechanisms to  describe  how  to  keep
       this file up-to-date.

       The dependency file is generated and maintained as follows:
            %.c.d: %.c
            {
                    c_incl --no-cache %.c
                            "--prefix='%.o "[target]": %.c'"
                            "--suffix='set nodefault;'"
                            -o [target];
            }

       This  recipe generates a file which contains a mini-cookbook
       describing  the  ingredients  of  the  [4mobject[24m   file.    The
       dependencies  are in terms of the object file because if any
       of the [1m.h [22mfiles change, it is the object file which is  out-
       of-date,  not the [1m.c [22mfile.  The mini-cookbook itself is also
       described, so that if any of the source  files  change,  the
       mini-cookbook can be brought up-to-date again.

       The  recipe  for the object file is less complicated than in
       the previous section, because the mini-cookbooks  supplement
       it:
            %.o: %.c
            {
                    cc -c %.c;
            }

       The  only thing missing is how to get the information in the
       mini-cookbooks into the main cookbook.  This is done with an
       include directive in the cookbook itself, but a special form
       of it.  The names of the mini-cookbooks  can  be  determined
       the  same  way  as  the  names of the object files, and this
       allows the cookbook fragments such as the  following  to  be
       written:
            object_files = [fromto %.c %.o [source_files]];
            dependency_files = [fromto %.c %.c.d [source_files]];


       Peter Miller                                         Page 20





       Cook                                              User Guide



            #include-cooked [dependency_files]

       The  #include-cooked  directive  says  to  include the named
       files (there may be more than one) if the file exist.   Once
       the cookbook (and its includes) have been read in, the files
       included with this directive are checked to see if they  are
       up-to-date.   If  they are not, then they are re-cooked, and
       then Cook starts  over  again;  this  time  with  up-to-date
       include dependencies.

       The  advantage  of  the  method  is that if the source files
       don't   change,   the   dependency   information   is    not
       recalculated, this can result in significant savings.  Also,
       no processes are invoked if nothing has changed, Cook  reads
       the   information   directly.    Because   file   opens  are
       significantly cheaper than process invocations, this results
       in a significant performance improvement.

       The  disadvantage  of  this  method  is that it is harder to
       describe and harder to implement.  To  the  uninitiated  the
       cookbook looks incomplete and overly complex.

       Another  problem is that if you delete an include file, Cook
       will complain that it is unable  to  derive  the  dependency
       file because the include file is not present.  Simply delete
       the dependency file and start again.  To avoid the  problem,
       remove  references  to  include  files, and re-build, before
       deleting the include files.  This problem is seen from  time
       to  time,  but  does  not  present  a huge problem in normal
       practice.

       [4m5.6[24m  [4mThe[24m [4mCascade[24m [4mMethod[0m

       When large numbers of files are involved, it  becomes  clear
       that  the  more  popular  include  files  are  being scanned
       repeatedly.  This can be un-necessarily time-consuming  when
       a  popular  include file is touched, as the dependency files
       of all .c files which reference it, even indirectly, must be
       re-calculated.

       There  is  also a problem when you are attempting to perform
       heterogeneous builds for multiple architectures out  of  the
       same  sources.   This  is  typically  done  by inserting the
       architecture name into the object file path as a  directory.
       This   presents  another  problem:  nominating  all  of  the
       architectures  on  the  left-hand-side  of  the  regenerated
       dependency recipes.  Especially if you add another one after
       the fact - now all the existing  dependency  files  must  be
       recalculated, merely to add the new architecture.

       An  alternative  is  to  scan  each  of the source files and
       include  files  once,  and  request  cook  to  combine  them
       together at build time, rather than at dependence scan time.
       This is done using cascade recipes.  These recipes  nominate


       Peter Miller                                         Page 21





       Cook                                              User Guide



       additional  ingredients (on their right-hand-size) if any of
       the files on their left-hand-size appears in an  ingredients
       list.
            cascade foo.c = bar.h;
       This  recipe  says  that  any  recipe which has [4mfoo.c[24m for an
       ingredient, also has [4mbar.h[24m for an ingredient.

       This takes care of the heterogeneous case, because while the
       recipes remain specified in a simple manner, [4mviz:[0m
            %1/%0%.o: %0%.c
            {
                    %1-gcc -o [target] -c %0%.c;
            }
       Any and all of them which compile [4mfoo.c[24m will depend on [4mbar.h[0m
       from the cascade recipe.  (This example assumes that you are
       using  [4mgcc[24m(1)  in  the usual way, and that your architecture
       names match the GNU target names.)

       The dependency files are generated and  maintained  in  much
       the same way as before, except that you need two: one for .c
       files and one for .h files:
            %0%.c.d: %0%.c
                    set no-cascade
            {
                    c_incl --no-cache --no-recurs %0%.c
                            "--prefix='cascade %0%.c ='"
                            "--suffix=';'"
                            -o [target];
            }
            %0%.h.d: %0%.h
                    set no-cascade
            {
                    c_incl --no-cache --no-recurs %0%.h
                            "--prefix='cascade %0%.h ='"
                            "--suffix=';'"
                            -o [target];
            }
       You will also need to add the .h.d files  to  the  #include-
       cooked  lines,  to  ensure they are generated.  If there are
       any generated .c or .h  files,  you  will  need  to  mention
       these, too.

       [4m5.7[24m  [4mDependencies[24m [4mon[24m [4mDerived[24m [4mFiles[0m

       If   the   relationship  between  a  target  and  a  derived
       ingredient appears only in a derived cookbook, it is  likely
       that  a  clean build (solely from primary source files) will
       fail.  It is recommended that relationships such as this  be
       placed  in  a  primary source cookbook.  Cook looks for such
       dependencies, and will warn you about them.

       An example of this is commonly seen when using the -d option
       with  [4myacc[24m(1).  If you have a separate lexical analyzer (the
       usual reason for using -d)  it  will  need  to  include  the


       Peter Miller                                         Page 22





       Cook                                              User Guide



       generated token definition file.

       When you first add the [4myacc[24m(1) grammar definition, Cook will
       generate both the  .c  and  .h  file  from  the  usual  yacc
       recipes.   It  is  only later, when you have cleaned out all
       derived files (including the dependency files) that you  may
       have  problems.   Where  is  it  recorded that Cook needs to
       regenerate the token definition file before it can determine
       the  include  dependencies  of  the lexical analyzer?  (They
       were in a .d file which was ``cleaned'' away.)

       Cook will  detect  this  situation  at  the  first  possible
       moment,  and warn you.  But placing the dependency in a non-
       derived cookbook ([4me.g.[24m   Howto.cook)  the  warning  will  go
       away, and you will be able to do reliable clean builds.

       If you are convinced that Cook is [4malways[24m wrong in your case,
       it is possible to suppress this warning.  Place the line
            set no-include-cooked-warning;
       in your main cookbook, and the warning will not be issued.

       Suppressing the warning could lead to problems.  It is often
       better to add the ingredients recipe given in the warning to
       the cookbook, even if  you  think  it  is  redundant.   This
       disables  a  single instance of the warning, rather than all
       of them - subsequent [4mvalid[24m instances will still be reported.
       (Implicit  ingredients  recipes,  rather than explicit ones,
       are a useful alternative if you have a consistent pattern.)

       [4m5.8[24m  [4mRenaming[24m [4mInclude[24m [4mFiles[0m

       A consistent problem when you have  automatically  generated
       include  dependencies is that when you move an include file,
       Cook complains that a required ingredient does not exist.

       The easiest way to avoid this is to do a few  things  before
       you build again after moving the include file.

          +o Move the include file to the new name.

          +o Where  the include file was [4mfrom[24m, put a file containing
            the line
                 #error "I'm not here"
            to make Cook happy (the  ingredient  will  exist),  but
            also  have the compiler generate an error if you miss a
            reference to it.

          +o Edit all the references to the old include file name to
            reference the new name.  Don't worry if you miss one or
            two, the previous step will catch it.

          +o Rebuild  the  program.   Cook  will  automatically  re-
            calculate  all  of  the  include  dependences  and then
            recompile.


       Peter Miller                                         Page 23





       Cook                                              User Guide



          +o If you missed one of the include file references,  Cook
            will  not  complain,  but  the  compiler  will.   (This
            assumes  you  are  using   whole-project   builds,   as
            described in the [4mLarge[24m [4mProjects[24m chapter.)

          +o Once  the  program  builds cleanly, remove the fake old
            include file, because you know for certain  that  there
            are no longer any references.
















































       Peter Miller                                         Page 24





       Cook                                              User Guide



       [4m6.[24m  [4mBuilding[24m [4mLarge[24m [4mProjects[0m

       This  chapter covers some of the  issues you may come across
       in building large projects.  It gives a skeleton for how you
       could use Cook to build a medium-to-large projects, and even
       covers some heterogeneous build issues.  It is expected that
       you  will  use  this  chapter  as  a guide; your development
       environment, and the shape of each individual project,  mean
       that you will probably change this to suit your own needs.

       The  material  in  this  chapter uses many, many features of
       Cook.  If you are not familiar with Cook, you  may  want  to
       read  the  rest  of  this  User  Guide to get a good idea of
       Cook's features and capabilities.  Even if you are  familiar
       with  Cook,  you may need to refer to the language guide and
       built-in function descriptions from time to time.

       [4m6.1[24m  [4mWhole[24m [4mProject[24m [4mBuild[0m

       The skeleton given here builds the whole project as a single
       Cook  invocation,  even  when  the  project consists of tens
       thousands of individual source files.  This is distinct from
       a  build  process which has Cook recursively invoking itself
       in deeper directories, or a  shell  script  doing  much  the
       same.   Some of the advantages of doing whole project builds
       will be discussed  in  a  later  section.   For  now  it  is
       sufficient  to say that experience has shown repeatedly that
       this method does scale to significant projects.

       The first thing about a single build pass is that it happens
       relative  to a single fixed place.  The logical place is the
       top  of  the project source tree3.  This works well with the
       [4msearch_list[24m functionality, mentioned below, which simplifies
       the structure of private work areas.

       [4m6.1.1[24m  [4mProject[24m [4mDirectory[24m [4mStructure[0m
       In the examples use in this chapter, the following directory
       structure is assumed:













       ____________________

       3. If  you  ever  want  to  use  Aegis   for   configuration
          management, this is what Aegis expects.

       Peter Miller                                         Page 25





       Cook                                              User Guide



                       ++-
                       -----[4mP[24m-[4mr[24m-[4mo[24m+[4mj[24m+[4me[24m-[4mc[24m-[4mt[24m--
                              +++--Hl-oiwbtroa.rcyook
                              +------++---[4ms[24m-[4mource1[24m.c
                              |      ++---[4ms[24m-[4mource2[24m.c
                              |      ++---[4me[24m-[4mtc...[0m
                              +++--i-nc-l+u-d-e--
                              |  ----++---[4ma[24m-[4mpi1[24m.h
                              |      ++---[4ma[24m-[4mpi2[24m.h
                              |      ++---[4me[24m-[4mtc...[0m
                              +++--[4mp[24m-[4mr[24m-[4mo[24m+[4mg[24m+[4mr[24m-[4ma[24m-[4mm[24m-[4m1[24m-
                              |      ++---[4ms[24m-[4mource3[24m.c
                              |      ++---[4ms[24m-[4mource4[24m.c
                              +++    -+---[4me[24m-[4mtc...[0m
                              +----[4mp[24m-[4mr[24m-[4mo[24m+[4mg[24m+[4mr[24m-[4ma[24m-[4mm[24m-[4m2[24m-
                                     ++---[4ms[24m-[4mource5[24m.c
                                     ++---[4mse[24m-[4motucr.c.e.6[24m.c
                                     -+----

       Below the project directory is a  library  directory,  which
       contains  functions  common  to  all  of  the programs.  All
       source files in this  directory  are  to  be  compiled,  and
       linked  into  a library.  When the programs are linked, they
       will all reference this library.

       Next to the library  directory  is  the  include  directory.
       This  describes  interfaces  and data shared by the project.
       Information which is private to the internals of the library
       or  a  programs  belongs  there,  not  in the shared include
       space.

       The rest of the directories below the project directory  are
       programs  to  be built.  The sources files in each are to be
       compiled and linked, together with the  common  library,  to
       form  the  programs.   The name of the program will be taken
       from the directory.

       This is a common enough picture, repeated for many projects.
       Your  individual  projects  may vary in the details; you may
       have more directory levels below the library  directory,  or
       all   of  your  programs  may  be  below  a  single  command
       directory.  With simple changes to  the  examples  given  in
       this  chapter,  you will be able to cope with just about any
       project structure.

       [4m6.1.2[24m  [4mFile[24m [4mManifest[0m
       There are many ways of discovering the source files you  are
       working  with.   Many  configuration  management systems are
       able to give you a list of them.  For example, if  you  were
       using Aegis, you would say
            change_files =
                    [collect aegis -l cf -terse -p [project] -c [change]];
            project_files =
                    [collect aegis -l pf -terse -p [project] -c [change]];


       Peter Miller                                         Page 26





       Cook                                              User Guide



            manifest =
                    [sort [change_files] [project_files]];

       If  you were using RCS, you could find all of the RCS files,
       and reconstruct the original filenames from them, [4mviz:[0m
            manifest =
                    [fromto ./%0RCS/%,v %0%
                            [collect find .  -path "*/RCS/*,v" -print]
                    ];

       Or you could simply scan the directory tree:
            manifest =
                    [fromto ./%0% %0%
                            [collect find .  ! -type d -print]
                    ];
       This is will find too much, but what  follows  will  not  be
       altered by this.  If you want to get more advanced, however,
       it helps to have an accurate primary source file manifest.

       [4m6.1.3[24m  [4mCompiling[24m [4mC[24m [4mSources[0m
       Recalling that the build will take place from the top of the
       source tree, this means that there it is going to have to be
       directory  components  in  the  filenames  in  the   command
       executed by Cook, and in the recipes Cook is to use.

       This  chapter  uses C examples, but the same techniques work
       just as will with Fortran or Groff, or anything else.   Most
       of  it  maps  directly;  you  may  need  to  adjust for your
       specific compiler behavior.

       This chapter starts with the  lowest  level  of  building  a
       project,  the  individual  source  files,  and works its way
       upwards, building on the examples until the  whole  project,
       including  the  library  and  all  programs  are linked in a
       single pass.

       So, when cooking C sources, you need recipes of the form
            cc = gcc;
            cc_flags = -g -Wall -O;

            %0%.o: %0%.c
            {
                    [cc] [cc_flags] -c %0%.c
                            -o [target];
            }
       The ``%0''  part  of  the  patterns  matches  zero  or  more
       directory  parts.   If  your compiler insists on putting the
       output (.o) file into the current directory (the  top  level
       one) you will need to move it, after:
            %0%.o: %0%.c
            {
                    [cc] [cc_flags] -c %0%.c;
                    mv %.o [target];
            }


       Peter Miller                                         Page 27





       Cook                                              User Guide



       But,  most  existing  sources  will be assuming that most of
       their include files are in the same directory as the  source
       files.   We  need include options to indicate this.  This is
       most easily done by using more pattern elements
            %1/%0%.o: %1/%0%.c
            {
                    [cc] [cc_flags] -I%1 -c %0%.c
                            -o [target];
            }
       Or by using the dirname of the source file
            %0%.o: %0%.c
            {
                    [cc] [cc_flags] -I[dirname %0%.c] -c %0%.c
                            -o [target];
            }
       For structures more  than  2  directories  deep,  these  two
       produce   different  options.   Depending  on  your  project
       structure, if you have deep directories, one  will  probably
       be more suitable than the other.  One elegant use for deeper
       directory structures  is  to  reflect  the  C++  inheritance
       hierarchy directly in the directory hierarchy.

       The  simple  [cc_flags]  variable  is  often not sufficient.
       Instead, you may want to replace it  with  [variable_by_path
       "cc_flags" %0%.c] which will look for several variables (all
       prefixed with "cc_flags") based on the name  of  the  source
       file.   See  the [4mFunctions[24m [4mLibrary[24m chapter for a description
       of this function.

       The common include file  will  also  need  to  be  searched.
       Because  of where the command is issued, it is rather simple
       to add the include directory, [4mviz:[0m
            %0%.o: %0%.c
            {
                    [cc] [cc_flags]
                            -I[dirname %0%.c] -Iinclude
                            -c %0%.c -o [target];
            }
       It is important to note that all of these recipes,  and  the
       commands  they  execute,  are independent of the location of
       the source file.  It is possible to customize  the  cc-flags
       used,  based  on  the  target  file,  or  even the directory
       containing the file, without compromising the generality  of
       the recipe4.

       [4m6.1.4[24m  [4mTracking[24m [4mInclude[24m [4mDependencies[0m
       When it comes to tracking include dependencies using [4mc_incl[24m,
       you need to remember, again, that the Cook  happens  from  a
       single place.  All of the recipes that [4mc_incl[24m writes for you
       must be [4mrelative[24m [4mto[24m [4mthat[24m [4mplace[24m.


       ____________________

       4. Hint: use a function, and pass [target] as the argument.

       Peter Miller                                         Page 28





       Cook                                              User Guide



       Continuing our  example,  and  assuming  we  are  using  the
       cascade include method described in the previous chapter, we
       need include dependency files which look similar to
            cascade [4mprogram1[24m/[4msource3[24m.c =
            include/[4mapi1[24m.h
            ;
       Working backwards, we need to  create  the  dependency  file
       using the following recipe:
            %0%.c.d: %0%.c
                    set nocascade
            {
                    c_incl -nc -ns -nrec
                            -I[dirname %0%.c] -Iinclude
                            %0%.c
                            -prefix "'cascade %0%.c ='"
                            -suffix "';'"
                            -o [target];
            }
       For  other source languages, you will need to use the [4mc_incl[0m
       [4m--language[24m option.

       The dependency files need to be included in the magic way so
       that  Cook  will  build  them again if they are out of date.
       This method needs the source file  manifest  to  know  their
       names.
            dep-files =
                    [addsuffix .d
                            [match_mask %0%.c [manifest] ]
                            [match_mask %0%.h [manifest] ]
                    ];
            #include-cooked [dep-files]
       These  files  will  only be re-calculated if they are out of
       date; they are small  and  often  zero-length,  and  so  are
       usually  very  quick  to  read, adding little to the time it
       takes to read the cookbook.

       Notice that adding a  new  source  file  will  automatically
       cause  it  to  be  scanned for include dependencies, without
       modification to the cookbook.

       [4m6.1.5[24m  [4mLinking[24m [4mLibraries[0m
       To  link  libraries  with  a  generic  recipe,  you  need  a
       generalized  way  of  specifying  their  contents.  A little
       trickery with constructed variable names does the job:
            %/lib%.a: [[target]_obj]
                    set unlink
            {
                    ar cq [target] [[target]_obj];
            }
       The right-hand-side of recipes has late binding, and we  use
       the  name  of the target to tell us the name of the variable
       which  holds  all  of  the  object  files.   Assigning  this
       variable  looks  bizarre,  but  it looks more logical as you
       have more and more of them...


       Peter Miller                                         Page 29





       Cook                                              User Guide



            library/liblibrary.a_obj =
                    [fromto %0%.c %0%.o
                            [match_mask "library/%0%.c" [manifest] ]
                    ];
       The great thing about this construct is that you can build a
       loop,  using  Cook's loop statement, that assigns a variable
       for each of your libraries, if you have more than one.

       Notice  that  adding  a  new  library   source   file   will
       automatically  cause  it  to  be  compiled into the library,
       without modification to the cookbook.

       [4m6.1.6[24m  [4mLinking[24m [4mCommands[0m
       We'll use a similar trick for each of the programs you  want
       to link...  First the link line
            bin/%: [[target]_obj]
                    set mkdir
            {
                    [cc] -o [target] [[target]_obj];
            }
       Then  the  objects  variable.   Note  how  we  add a library
       [4mfilename[24m here, this will still only use the library portions
       actually  referenced,  not  the  whole  library, so it won't
       bloat your programs.
            bin/[4mprogram[24m_obj =
                    [fromto %0%.c %0%.o
                            [match_mask [4mprogram[24m/%0%.c [manifest] ]
                    ]
                    library/liblibrary.a
                    ;

       Notice  that  adding  a  new  program   source   file   will
       automatically  cause  it  to be compiled and linked into the
       program, without modification to the cookbook.

       The loop construct tends to obscure things, which is why the
       essential  assignment  was  given first.  This next fragment
       shows the whole loop.
            programs =
                    [fromto %/main.c %
                            [match_mask %/main.c [manifest] ]
                    ];
            program_list = [programs];
            loop
            {
                    program = [head [program_list]];
                    if [not [count [program]]] then
                            loopstop;
                    program_list = [tail [program_list]];

                    bin/[program]_obj =
                            [fromto %0%.c %0%.o
                                    [match_mask [program]/%0%.c
                                            [manifest]


       Peter Miller                                         Page 30





       Cook                                              User Guide



                                    ]
                            ]
                            library/liblibrary.a
                            ;
            }
       And now tell Cook you actually want it to do something, like
       build all of the programs...
            all: [addprefix bin/ [programs]];

       Notice  they  way the commands variable is constructed: just
       adding  a  new  command   (and   its   main.c   file)   will
       automatically  cause it to be built, without modification to
       the cookbook.


       [4m6.2[24m  [4mPrivate[24m [4mWork[24m [4mAreas[0m

       This chapter is about large  projects,  but  large  projects
       usually  means  large  numbers of developers.  The directory
       structure and cookbook presented so far does not immediately
       lend itself to use by multiple developers.

       [4m6.2.1[24m  [4mDirectory[24m [4mStructure[0m
       The   method   suggested   here   uses   Cook's  [4msearch_list[0m
       functionality, which nominates a search list of  directories
       that  Cook  looks in to find the files named in the recipes.
       This can be used to overlay a private work area on top of  a
       master repository.
       [47m[40m                ++[0m----------[40m+[0m
                      [40m++[0m|[4mReposito[24m[40m+[4m[0m[4mr[24m[40m+[4m[0m[4my[24m|
                     [40m+  [0m|  main.[40m+[0mc[40m+ [0m|      [4m[47mC[24m+[4mo[24m-[4mm[24m-[4mb[24m-[4mi[24m-[4mn[24m-[4me[24m-[4md[24m--[4mV[24m-[4mi[24m-[4me[24m+[4mw[0m
                   [40m++   [0m| part1[40m+[0m.c  |      [40m+[47m+ main.c   |[0m
                   [47m+-[4mW[24m-[4mo[24m-[4mr[24m-[4mk[24m[0m+[47m-[4mA[24m-[4mr[24m-[4me[24m-[4ma[24m-+[0m----[40m+      +[47m+ part1.c  |[0m
                   [47m|  main.c  |   [40m++       [47m| part2.c  |[0m
                   [47m|          | [40m++         [47m+----------+[0m
                   [47m| part2.c  |[40m+[0m
                   [47m+----------+[0m

       [40mWhen  recipes are run, the results are written into the work[0m
       [40marea, which means that  the  repository  can  be  completely[0m
       [40mread-only.[0m

       [40mIt  follows  from  this, that the directory structure of the[0m
       [40mwork area exactly parallels the directory structure  of  the[0m
       [40mrepository.   [4mExcept[24m you only check out files into your work[0m
       [40marea that you actually need to change.[0m

       [4m[40m6.2.2[24m  [4mFinding[24m [4mthe[24m [4mCookbook[0m
       [40mSetting the search list is done with  a  simple  assignment.[0m
       [40mIn   your  work  area,  create  a  simple  Howto.cook  file,[0m
       [40mcontaining only 3 lines:[0m
            [40mset mkdir;[0m
            [40msearch_list = . /project/repository ;[0m
            [40m#include /project/repository/Howto.cook[0m

       
       Peter Miller                                         Page 31





       Cook                                              User Guide



       [40mYou only use this file if  you  don't  need  to  modify  the[0m
       [40mcookbook  itself.   You can make it work always, even if you[0m
       [40mare  modifying  the  cookbook,  by  giving  the  cookbook  a[0m
       [40mdifferent  name  (main.cook),  and  changing  Howto.cook  to[0m
       [40malways read[0m
            [40mset mkdir;[0m
            [40msearch_list = . /project/repository ;[0m
            [40m#include [resolve main.cook][0m
       [40mThe [resolve] function walks the search  list,  looking  for[0m
       [40mthe file5.  This gives you access to Cook's internal  search[0m
       [40mmechanism.   However,  we  also  need  to modify each of the[0m
       [40mrecipes to take the search list into account.[0m

       [40mThe  unexplained  mkdir  flag  is  used  to   request   that[0m
       [40mdirectories  be  automatically  created before recipe bodies[0m
       [40mare run.  This is  common  for  large  projects,  where  the[0m
       [40msource  files  are  structured into several sub-directories,[0m
       [40mrather than all lumped together in the one place.  This  may[0m
       [40mbe  necessary,  for  example, if a .c file in the repository[0m
       [40mneeds to be recompiled because a .h file in  the  work  area[0m
       [40mhas been changed.[0m

       [4m[40m6.2.3[24m  [4mFile[24m [4mManifest[0m
       [40mThe  files  could  be  in either of two places.  You need to[0m
       [40mmerge them.  Most configuration management tools do this for[0m
       [40myou;  in  this example we'll scan the directory trees again.[0m
       [40mFortunately, Cook comes with a tool to do this efficiently.[0m
            [40mall_files_in_. = ;[0m
            [40m#include manifest.cook[0m
            [40mmanifest = [all_files_in_.];[0m

            [40m/* This reduces re-scanning to a minimum. */[0m
            [40mset fingerprint;[0m

            [40m%0manifest.cook: ["if" [in "%0" ""] "then" "." "else" "%0"][0m
                    [40mset mkdir[0m
            [40m{[0m
                    [40mcook_bom /* Bill Of Materials */[0m
                            [40m[addprefix '--dir=' [search_list]][0m
                            [40m[need] [target] ;[0m
            [40m}[0m
       [40mAt the end of this fragment, the manifest variable  contains[0m
       [40ma complete list of all files in the directory tree(s).  This[0m
       [40mvariable  may  then  be  taken  apart  with  the  match_mask[0m
       [40mfunction to build ingredients lists.[0m

       [40mThe if function is different to the [4mif[24m statement.  It allows[0m
       [40myou to select one of two values (the then part or  the  else[0m
       [40mpart)  without  creating a dummy variable.  In this example,[0m
       [40mit would be impossible to create a dummy variable.  Remember[0m

       ____________________

       5. The  search  list  defaults  to  just  dot  (the  current
          directory) if not set.

       Peter Miller                                         Page 32





       Cook                                              User Guide



       [40mto  quote the if, then and else strings, otherwise Cook will[0m
       [40mthink they are [4mif[24m, [4mthen[24m and [4melse[24m keywords, and  give  you  a[0m
       [40msyntax error.[0m

       [40mThe  constructed  [4mmanifest.cook[24m files work for both the top-[0m
       [40mlevel directory and individual sub-directories.[0m

       [4m[40m6.2.4[24m  [4mCompiling[24m [4mC[24m [4mSources[0m
       [40mThe C compilation recipe needs to be changed to read...[0m
            [40m%0%.o: %0%.c[0m
            [40m{[0m
                    [40m[cc] [cc_flags][0m
                            [40m[prepost "-I" /[dirname %0%.c] [search_list]][0m
                            [40m[prepost "-I" "/include" [search_list]][0m
                            [40m-c [resolve %0%.c][0m
                            [40m-o [target];[0m
            [40m}[0m
       [40mThis ensures that the rights places are searched for include[0m
       [40mfiles.[0m

       [40mThe prepost function is used to add a prefix and a suffix to[0m
       [40meach of the remaining strings.  This  is  very  useful  when[0m
       [40mconstructing  filenames,  as are the addprefix and addsuffix[0m
       [40mfunctions.[0m

       [4m[40m6.2.5[24m  [4mTracking[24m [4mInclude[24m [4mDependencies[0m
       [40mA  similar  change  needs  to  be  made   to   the   include[0m
       [40mdependencies recipe...[0m
            [40m%0%.c.d: %0%.c[0m
                    [40mset nocascade[0m
            [40m{[0m
                    [40mc_incl -nc -ns -nrec[0m
                            [40m[prepost "-I" /[dirname %0%.c] [search_list]][0m
                            [40m[prepost "-I" "/include" [search_list]][0m
                            [40m[resolve %0%.c][0m
                            [40m-prefix "'cascade %0%.c ='"[0m
                            [40m-suffix "';'"[0m
                            [40m[addsuffix "-rp=" [search_list]][0m
                            [40m-o [target];[0m
            [40m}[0m
       [40mNote  that  the  form  of the output of this recipe [4mdoes[24m [4mnot[0m
       [40mchange.  This means that the recipes it writes work even  if[0m
       [40myou subsequently copy a file from the repository to the work[0m
       [40marea, or uncopy one.[0m

       [4m[40m6.2.6[24m  [4mLinking[24m [4mLibraries[0m
       [40mThe library recipe needs few modifications.[0m
            [40m%/lib%.a: [[target]_obj][0m
                    [40mset unlink[0m
            [40m{[0m
                    [40mar cq [target] [resolve [[target]_obj]];[0m
            [40m}[0m
       [40mThe   variable   assignment   given   above   requires    no[0m
       [40mmodifications.[0m

       
       Peter Miller                                         Page 33





       Cook                                              User Guide



       [40m[4m6.2.7[24m  [4mLinking[24m [4mCommands[0m
       [40mThe command linking recipe requires few modifications.[0m
            [40mbin/%: [[target]_obj][0m
                    [40mset mkdir[0m
            [40m{[0m
                    [40m[cc] -o [target] [resolve [[target]_obj]];[0m
            [40m}[0m
       [40mThe variable assignment needs no modifications.[0m

       [4m[40m6.3[24m  [4mWhole[24m [4mProject[24m [4mBuild[24m [4mAdvantages[0m

       [40mThe  advantage  of  using  a whole project build is that the[0m
       [40mdependency graph is complete, and the order of traversal may[0m
       [40mbe  freely  determined  by  Cook.   Breaking  the build into[0m
       [40mfractured segments denies Cook access to  the  whole  graph,[0m
       [40mand  dictates  the  order  of traversal to one which, in the[0m
       [40mlight of the entire graph, would be incorrect.[0m

       [40mIt  greatly  simplifies  the  creating  of  work  areas  for[0m
       [40mdevelopers, by using Cook's [4msearch_list[24m functionality.[0m

       [40mA whole project build also permits the [4mcook[24m [4m-continue[24m option[0m
       [40mto work in the presence of a wider range of errors.[0m

       [40mThe whole project build  also  permits  the  [4mcook[24m  [4m-parallel[0m
       [40moption to parallelize more operations.[0m

       [4m[40m6.4[24m  [4mHeterogeneous[24m [4mBuild[0m

       [40mLarge    projects   frequently   involve   numerous   target[0m
       [40marchitectures.  This may be in the form  a  multiple  native[0m
       [40mcompilations,  performed  in  suitable hosts, or it may take[0m
       [40mthe form of cross-compilation.[0m

       [40mIn this example, we assume that the GNU C Compiler (GCC)  is[0m
       [40mbeing  used.  When GCC is installed as a cross compiler, the[0m
       [40mcommand names (cc, as,  ld,  [4metc[24m)  are  installed  with  the[0m
       [40marchitecture  name as a prefix.  For consistency, the native[0m
       [40mcompiler is installed with its own architecture names  as  a[0m
       [40mprefix,  in  addition to the more commonly used gcc command.[0m
       [40mThis example will exploit this normal installation practice.[0m

       [4m[40m6.4.1[24m  [4mCross[24m [4mCompiling[24m [4mC[24m [4mSources[0m
       [40mIn order to  support  cross  compiling,  the  C  compilation[0m
       [40mrecipe needs to be changed to read...[0m
            [40m%1/%0%.o: %0%.c[0m
                    [40mhost-binding [defined-or-null %1-hosts][0m
            [40m{[0m
                    [40m%1-gcc [cc_flags][0m
                            [40m[prepost "-I" /[dirname %0%.c] [search_list]][0m
                            [40m[prepost "-I" "/include" [search_list]][0m
                            [40m-c [resolve %0%.c][0m
                            [40m-o [target];[0m
            [40m}[0m

       
       Peter Miller                                         Page 34





       Cook                                              User Guide



       [40mThis  uses  the  first directory element of the [4mtarget[24m to be[0m
       [40mthe architecture name.  This allows  multiple  architectures[0m
       [40mto be compiled in the same source tree, simultaneously.[0m

       [40mBecause of the practice of installing a duplicate GCC in the[0m
       [40msame form as the cross compilers, this same recipe continues[0m
       [40mto work for native builds.[0m

       [40mThe  [4mhost-binding[24m  line tells Cook to run the command on one[0m
       [40mof  the  hosts  nominated  in  a  variable  named  for   the[0m
       [40marchitecture  (or  as  a  native  cross-compiler  of no such[0m
       [40mvariable  exists).    (The   defined-or-null   function   is[0m
       [40mavailable  in  the  ``functions''  library  distributed with[0m
       [40mCook.)[0m

       [40mRemembering these architectures follow the  GNU  convention,[0m
       [40mthese lines could read[0m
            [40mi386-linux-hosts = fast faster fastest ;[0m
       [40mThis  will  do  two  things  for  you: first, it will always[0m
       [40mexecute linux compiles on linux hosts even when Cook is  not[0m
       [40mexecuted  on  one; second, it will use more than one of them[0m
       [40mwhen you use the --parallel option.[0m

       [40mIt is possible to use implicit ingredients  recipes  to  say[0m
       [40mthat  all  object  of a given architecture depend on a magic[0m
       [40minclude file, [4me.g.[0m
            [40mi386-linux/%0%.o: include/linux-special.h;[0m
       [40mcould be used to say that all Linux object files  depend  on[0m
       [40mthis include file.  (This is a sledge-hammer approach, and a[0m
       [40mmore subtle  method  is  preferable,  but  it  is  sometimes[0m
       [40mrequired.)[0m

       [4m[40m6.4.2[24m  [4mTracking[24m [4mInclude[24m [4mDependencies[0m
       [40mBecause  of the cascade form of include dependency, there is[0m
       [40mno need to do anything different for  include  dependencies,[0m
       [40meven  if  you  add  another  architecture  some  time in the[0m
       [40mfuture.[0m

       [4m[40m6.4.3[24m  [4mLinking[24m [4mLibraries[0m
       [40mThe library recipe needs few modifications.[0m
            [40m%1/%/lib%.a: [%/lib%.a_obj][0m
                    [40mset unlink[0m
            [40m{[0m
                    [40m%1-ar cq [target] [resolve [%/lib%.a_obj]];[0m
            [40m}[0m
       [40mThe   variable   assignment   given   above   requires    no[0m
       [40mmodifications.[0m

       [4m[40m6.4.4[24m  [4mLinking[24m [4mCommands[0m
       [40mThe command linking recipe requires few modifications.[0m
            [40m%1/bin/%: [bin/%_obj][0m
                    [40mset mkdir[0m
            [40m{[0m
                    [40m%1-gcc -o [target] [resolve [bin/%_obj]];[0m

       
       Peter Miller                                         Page 35





       Cook                                              User Guide



       [40m     }[0m
       [40mThe variable assignment needs no modifications.[0m

       [4m[40m6.4.5[24m  [4mWhat[24m [4mto[24m [4mBuild[0m
       [40mThe list of what to build becomes more interesting.  You can[0m
       [40mnominate any and all architectures for which you have  cross[0m
       [40mcompilers, or native compilers and native hosts.[0m
            [40mall:[0m
                    [40m[addprefix i386-linux/bin/ [commands]][0m
                    [40m[addprefix sparc-linux/bin/ [commands]][0m
                    [40m[addprefix sparc-solaris2.0/bin/ [commands]][0m
                    [40m[addprefix m68k-sunos4.1.3/bin/ [commands]][0m
                    [40m;[0m

       [40mAll  of  these  architectures will be built in a single Cook[0m
       [40minvocation, on appropriate machines if necessary.   The  use[0m
       [40mof  --continue  and --parallel work over the entire scope of[0m
       [40mthe build.[0m

       [4m[40m6.5[24m  [4mInstalling[24m [4mThings[0m

       [40mThe biggest hassle is that  the  [4minstall[24m(1)  command,  which[0m
       [40mshould   know   how  to  do  most  installation  tasks,  has[0m
       [40mcompletely incompatible interfaces on the various platforms.[0m
       [40mThis is why the GNU Autoconf system comes with an [4minstall-sh[0m
       [40mscript, which faithfully emulates the BSD options.  Once you[0m
       [40mhave  a  reliable  command  line  interface to an [4minstall[24m(1)[0m
       [40mprogram (be it Perl or shell) you can  then  write  sensible[0m
       [40minstallation cookbooks.[0m

       [40mIf we have a list of commands, we would install as follows:[0m
            [40mprefix = /usr/local;[0m
            [40mbindir = [prefix]/bin;[0m
            [40minstall = install;[0m

            [40minstall: [addprefix [bindir]/ [commands]];[0m
            [40m[bindir]/%0%: bin/%0% bin/%0.mkdir[0m
            [40m{[0m
                    [40m[install] -m 755 bin/%0% [bindir]/%0%;[0m
            [40m}[0m
       [40mThat  magic  bin/%0.mkdir  file  is  used to record that the[0m
       [40mdestination directory exists.  While you  can  often  assume[0m
       [40mthis,  it  is  not  always true when you are building things[0m
       [40mlike RPM packages.[0m
            [40mbin/%0.mkdir:[0m
            [40m{[0m
                    [40m[install] -d [bindir]/%0[0m
                            [40mset errok;[0m
                    [40mtouch [target];[0m
            [40m}[0m
       [40mThe alternative is to use[0m
            [40mset mkdir;[0m
       [40mat the top of your cookbook.  This creates  directories  for[0m
       [40mtargets before rules are run.  The install recipe then reads[0m

       
       Peter Miller                                         Page 36





       Cook                                              User Guide



       [40m     set mkdir;[0m

            [40m[bindir]/%0%: bin/%0%[0m
            [40m{[0m
                    [40m[install] -m 755 bin/%0% [bindir]/%0%;[0m
            [40m}[0m
       [40mbecause  there  is no need for the ``.mkdir'' recipe.  This,[0m
       [40mhowever  gives  you  less  control  over   the   directories[0m
       [40mpermission  modes,  and  it  doesn't  help  when you want to[0m
       [40mcreate empty directories as part of the  install.   Use  the[0m
       [40mappropriate technique for your needs.[0m

       [4m[40m6.6[24m  [4mMiscellaneous[0m

       [40mThis  section  contains  assorted  material  that  covers  a[0m
       [40mvariety of topics.  (As the manual expands, it will probably[0m
       [40mbe moved somewhere else.)[0m

       [4m[40m6.6.1[24m  [4mLots[24m [4mof[24m [4mDependencies[0m
       [40mThere  are  cases  where  you  may  want to nominate a whole[0m
       [40mcategory of files  as  depending  on  something  else.   For[0m
       [40mexample,  you  may  want to say that all your fubar-language[0m
       [40msources  depend  on  your  fubar  compiler  You  could   say[0m
       [40msomething such as[0m
            [40mcascade [match_mask %0%.fubar [manifest]] = fubarcompiler;[0m
       [40mbut  recall  that  [4meverything[24m  which has a .fubar file as an[0m
       [40mingredient will also have fubarcompiler  as  an  ingredient.[0m
       [40mThis may not be what you wanted.[0m

       [40mRecall,   also,   that   compiler   recipes  carry  specific[0m
       [40minformation.   You  could  more  specifically  nominate  the[0m
       [40mcompiler by saying[0m
            [40m%0%.o: %0%.fubar: fubarcompiler[0m
            [40m{[0m
                    [40mfubarcompiler -c %0%.fubar -o [target];[0m
            [40m}[0m
       [40mwhich  would  be  much  more  selective  about which uses of[0m
       [40m.fubar files also depend on fubarcompiler.[0m

       [40mThere are times when writing cross-compilation recipes  when[0m
       [40myou  want  to  nominate an operating-system-specific include[0m
       [40mfile for all of the object files:[0m
            [40m%1/%0%.o: %0%.c[0m
            [40m{[0m
                    [40m/* general cross compiler recipe */[0m
                    [40m%1-gcc -c %0%.c -o [target];[0m
            [40m}[0m
            [40m/* All windows NT objects depend on this include file */[0m
            [40mi386-NT/%0%.o: winnt.h;[0m

       [40mYou can also use [4mgates[24m to make you recipes  more  selective.[0m
       [40mThe  gating  expression  may  be just about anything, but is[0m
       [40moften a pattern match or simple set membership.[0m
            [40m%.o: %.c[0m

       
       Peter Miller                                         Page 37





       Cook                                              User Guide



       [40m             if [in [target] foo.o bar.o][0m
            [40m{[0m
                    [40m/* foo.o and bar.o are magic */[0m
                    [40mcc -DMAGIC [cc_flags] -c %.c;[0m
            [40m}[0m
       [40mThe gate is most easily read as ``if  [4m(this[24m  [4mcondition)[24m  use[0m
       [40mthis recipe''.[0m

       [4m[40m6.6.2[24m  [4mError[24m [4mProcessing[0m
       [40mCook  stops  processing a recipe at the first error.  If the[0m
       [40merror occurs when constructing a command to be executed, the[0m
       [40mcommand  is  [4mnot[24m  executed.   If a recipe body contains more[0m
       [40mthan one command, and one of them gets an error (and doesn't[0m
       [40mhave the [4merrok[24m flag set) the rest of the command will [4mnot[24m be[0m
       [40mexecuted.[0m

       [40mIn addition, if an error occurs  while  executing  a  recipe[0m
       [40mbody,  the  targets  of  the  recipe will be deleted (on the[0m
       [40massumption that they are probably only partially  completed,[0m
       [40mor otherwise defective).  To override this behavior, use the[0m
       [4m[40mprecious[24m flag.[0m

       [4m[40m6.6.3[24m  [4mNFS[0m
       [40mA perennial problem for building projects over  networks  is[0m
       [40mthat  the  clocks  don't  match.  If you use the [4mtime-adjust[0m
       [40mflag, this problem is largely solved.  The  simplest  method[0m
       [40mis to put[0m
            [40mset time-adjust;[0m
       [40mat the top of your cookbook.[0m

       [40mFile  fingerprints,  while not directly relevant to NFS, can[0m
       [40moffer significant  performance  improvements,  as  they  can[0m
       [40meliminate many cases of unnecessary re-compilation.  To turn[0m
       [40mthem on, use[0m
            [40mset fingerprint;[0m
       [40mat the top of your cookbook.  See below for more  discussion[0m
       [40mof fingerprints.[0m

       [4m[40m6.6.4[24m  [4mSymbolic[24m [4mLinks[0m
       [40mSymbolic  links  are  followed  to  the  actual  file,  when[0m
       [40mdetermining file modification times.  The modification  time[0m
       [40mof  the  symbolic  link itself is not used.  This means that[0m
       [40m``symlink farms'' can be used when constructing work  areas,[0m
       [40mparticularly  when  you want functionality more complex than[0m
       [40msearch_list can provide.[0m

       [4m[40m6.7[24m  [4mFile[24m [4mFingerprints[0m

       [40mCook has the ability to supplement the  last-modified  time-[0m
       [40mstamps  the  operating  system supplies for each file with a[0m
       [40m``fingerprint''.   This  is   a   cryptographically   strong[0m
       [40mchecksum,  with  an mind-bogglingly low probability that two[0m
       [40mdifferent files will have the same fingerprint.[0m


       
       Peter Miller                                         Page 38





       Cook                                              User Guide



       [40mWhen Cook needs to know if a file has changed, it  looks  at[0m
       [40mthe  last-modified  time-stamp.  If it has changed since the[0m
       [40mlast time the fingerprint was calculated, the fingerprint is[0m
       [40mre-calculated.   If  the  fingerprints match, Cook knows the[0m
       [40mfile contents are unchanged, and uses  the  old  time-stamp,[0m
       [40mand  also  suppress any recipe actions which would otherwise[0m
       [40mhappen if the file contents  had  actually  changed.   (Cook[0m
       [40mremembers  the  both the new and old time-stamps, so that it[0m
       [40mcan be efficient about re-calculating  checksums  and  still[0m
       [40muse the old time stamp for out-of-date calculations.)[0m

       [40mWhen  recipe  bodies  are run, Cook knows that the target(s)[0m
       [40mhave been modified, so it doesn't  need  to  re-examine  the[0m
       [40moperating  system's idea of the last-modified time-stamp, it[0m
       [40msimply re-fingerprints.[0m

       [40mIt is tempting  to  try  to  achieve  something  similar  by[0m
       [40mwriting recipe bodies which only over-write their targets if[0m
       [40mthey actually changed.  [4mE.g.[0m
            [40m%.o: %.c[0m
            [40m{[0m
                    [40mif [exists [target]] then[0m
                    [40m{[0m
                            [40m[CC] -o %.tmp -c %.c;[0m
                            [40mif cmp %.tmp %.o\;[0m
                            [40mthen mv %.tmp %.o\;[0m
                            [40melse rm %.tmp;[0m
                    [40m}[0m
                    [40melse[0m
                            [40m[CC] -o %.o -c %.c;[0m
            [40m}[0m
       [40mHowever, this  will  not  work  (whether  or  not  you  have[0m
       [40mfingerprints  turned  on).  Largely as a defense against NFS[0m
       [40mtime synchronization problems and stupid systems  with  very[0m
       [40mcoarse  file  time-stamps,  Cook  ``knows'' that because the[0m
       [40mrecipe body was run the target ``changed'', causing all down[0m
       [40mstream dependencies to be considered out-of-date.[0m

       [40mIn addition, this recipe would leave the last-modified time-[0m
       [40mstamp out-of-date if the file was unchanged.  This means the[0m
       [40mrecipe  would  trigger  again  in  the  next Cook execution,[0m
       [40mnegating many of the intended savings.[0m

       [40mFingerprints are intended for this  purpose,  but  have  the[0m
       [40madvantage  of leaving the last-modified time-stamps correct,[0m
       [40mand they need to do half the I/O  that  the  [4mcmp[24m(1)  command[0m
       [40mdoes.  Also, all down stream dependent files are touched, to[0m
       [40mensure their last-modified time-stamps are also  consistent.[0m
       [40mNaturally,  if  they  needed  to  be re-built for some other[0m
       [40mreason, then they would be re-built, not simply touched.[0m

       [40mWhile there is some overhead in  initially  calculating  the[0m
       [40mfingerprints  for  a new work area, they repay that overhead[0m
       [40mmany times over.  This is especially true if your system has[0m

       
       Peter Miller                                         Page 39





       Cook                                              User Guide



       [40mgenerated  code in it, particularly generated include files,[0m
       [40mbut there are also savings for simpler, smaller projects.[0m

       [4m[40m6.7.1[24m  [4mTurning[24m [4mFingerprints[24m [4mOn[0m
       [40mTo turn fingerprints on, you need to add the lines[0m
            [40mset fingerprint;[0m
            [40mset time-adjust;[0m
       [40mto your cookbook.  That second line is no essential, but  it[0m
       [40mcorrects    last-modified    time-stamps   when   NFS   time[0m
       [40msynchronization problems would otherwise cause  inconsistent[0m
       [40mbehavior.[0m

       [40mWhile it is possible to turn fingerprints on for a subset of[0m
       [40mthe files in your project, it is not as  straightforward  as[0m
       [40mit  may  seem.   There  is  no  way  to bind the fingerprint[0m
       [40mrequest to a single file, only to recipes, so  you  need  to[0m
       [40muse  the  ``set  fingerprint''  recipe  flag  on all recipes[0m
       [40mbetween the relevant source file and  the  ultimate  target.[0m
       [40mThis tends to be messy.[0m

       [4m[40m6.7.2[24m  [4mVanishing[24m [4mDependencies[0m
       [40mIt  is  quite common that you need to re-build a file if one[0m
       [40mof the dependencies is removed.  Usually, this is quite hard[0m
       [40mto  detect,  because  Cook has trouble seeing something that[0m
       [40misn't there, compared to the previous execution.  However an[0m
       [40mingenious  method  has  been  described  by  Gilles  Lamiral[0m
       [40m<lamiral@mail.dotcom.fr> which ``remembers'' though a file:[0m
            [40mfunction contents-remember =[0m
            [40m{[0m
                    [40m/* @1 = name of contents file */[0m
                    [40m/* @2..N = the value of [need] */[0m
                    [40m[write [args]];[0m
            [40m}[0m
            [40mfunction contents-changed =[0m
            [40m{[0m
                    [40m/* @1 = name of contents file *[0m
                    [40m/* @2..N = the value of [need] */[0m
                    [40mif [not [exists [resolve [@1]]]] then[0m
                            [40mreturn 0;[0m
                    [40mlocal old-contents = [collect_lines cat [resolve [@1]]];[0m
                    [40m/* return 0 if nothing disappeared, >0 if did disappear */[0m
                    [40mreturn [count [stringset [old-contents] - [tail [arg]]]];[0m
            [40m}[0m
            [40mlibfred.a libfred.contents: [fred_obj][0m
                    [40mset ["if" [contents-changed libfred.contents [fred_obj]][0m
                            [40m"then" forced][0m
                        [40munlink[0m
            [40m{[0m
                    [40mar cq [target] [resolve [fred_obj]];[0m
                    [40m[contents-remember libfred.contents [fred_obj]];[0m
            [40m}[0m

       [40mNote: because the set clause is evaluated when the target is[0m
       [40mevaluated,  the  [need]  variable is not available.  In this[0m

       
       Peter Miller                                         Page 40





       Cook                                              User Guide



       [40mexample,  you  must  have  calculated  the  final  value  of[0m
       [40m[fred_obj]  before  the recipe appears in the cookbook.  The[0m
       [40mevaluation of the set clause also limits the application  of[0m
       [40mthis  technique  to  explicit  recipes; it will not work for[0m
       [40mimplicit (pattern) recipes, because the value of the pattern[0m
       [40melements  is  not  known  at  the  time  the  set  clause is[0m
       [40mevaluated.[0m

       [4m[40m6.8[24m  [4mCoping[24m [4mwith[24m [4mLinks[0m

       [40mYou will notice that the default  operation  of  Cook  copes[0m
       [40mwith  links  (hard  links and symbolic links) rather poorly.[0m
       [40mFor example, the recipe[0m
            [40mtwo: one[0m
            [40m{[0m
                    [40mln one two;[0m
            [40m}[0m
       [40mwill always conclude that file [4mtwo[24m is out-of-date.  This  is[0m
       [40mbecause files [4mone[24m and [4mtwo[24m have exactly the same time stamp.[0m

       [40mIf  you  specify  a  weaker time constraint, Cook will allow[0m
       [40mthis kind of recipe to be  written,  and  [4mnot[24m  conclude  the[0m
       [40mfiles is always out of date:[0m
            [40mtwo: one(weak)[0m
            [40m{[0m
                    [40mln one two;[0m
            [40m}[0m
       [40mThe  ``(weak)'' on the end of the ingredient name tells Cook[0m
       [40mto use the weak edge type, rather than the strict edge type.[0m

       [40mThis technique is useful for symbolic links, too.[0m

       [40mOne other thing which can  be  very  useful  for  both  link[0m
       [40mtypes,  but  particularly  symbolic links to directories, is[0m
       [40mthe ``set unlink'' recipe flag.[0m
            [40mtwo: one(weak)[0m
                    [40mset unlink[0m
            [40m{[0m
                    [40mln -s one two;[0m
            [40m}[0m
       [40mThis removes the target (if  necessary)  before  the  recipe[0m
       [40mbody is run.[0m

       [4m[40m6.9[24m  [4mCoping[24m [4mwith[24m [4mVersion[24m [4mStamps[0m

       [40mIn  some systems, the version stamp is regenerated for every[0m
       [40mbuild, but you don't want to relink zillions of  executables[0m
       [40mjust because the version stamp has changed, but nothing else[0m
       [40mhas.[0m

       [40mBy using the ``(exists)'' edge type, you can tell Cook  that[0m
       [40man  ingredient  is  needed  for  a given target, but that it[0m
       [40mshould never be considered to make the  target  out-of-date.[0m
       [40mFor example:[0m

       
       Peter Miller                                         Page 41





       Cook                                              User Guide



       [40m     #include "c"[0m
            [40mall: prog1 prog2;[0m
            [40mversion.c:[0m
                    [40mset forced[0m
            [40m{[0m
                    [40mdate "'+#define VERSION \"%C\"'" > [target];[0m
            [40m}[0m
            [40mprog1: prog1.o mylib.a version.o(exists)[0m
            [40m{[0m
                    [40mgcc -o [target] [need];[0m
            [40m}[0m
            [40mprog2: prog2.o mylib.a version.o(exists)[0m
            [40m{[0m
                    [40mgcc -o [target] [need];[0m
            [40m}[0m
       [40mThis  cookbook will generate a new [4mversion.c[24m file every time[0m
       [40mthat Cook is run, and thus a new [4mversion.o[24m  file.   However,[0m
       [40mthe  [4mprog1[24m  and  [4mprog2[24m  files  will  not be re-linked unless[0m
       [40msomething else changed as well.[0m




































       
       Peter Miller                                         Page 42





       Cook                                              User Guide



       [40m[4m7.[24m  [4mCookbook[24m [4mLanguage[24m [4mDefinition[0m

       [40mThis chapter  defines  that  language  which  cookbooks  are[0m
       [40mwritten  in.  While some of its properties are similar to C,[0m
       [40mdo not be misled.[0m

       [40mA number of sections appear within this chapter.[0m

         [40m1.  The [4mLexical[24m [4mAnalysis[24m section describes what the  words[0m
             [40mof the cookbook language look like.[0m

         [40m2.  The   [4mPreprocessor[24m   section   describes  the  include[0m
             [40mmechanism and the conditional compilation mechanism.[0m

         [40m3.  The [4mSyntax[24m [4mand[24m [4mSemantics[24m section describes  how  words[0m
             [40min   the  cookbook  may  be  combined  to  form  valid[0m
             [40mconstructs (the [4msyntax[24m),  and  what  these  constructs[0m
             [40mmean (the [4msemantics[24m).[0m

       [40mThe sections are laid out in the recommended reading order.[0m

       [4m[40m7.1[24m  [4mLexical[24m [4mAnalysis[0m

       [40mThe  cookbook  is  made of a number of recipes, which are in[0m
       [40mturn made of words.  This section describes what constitutes[0m
       [40ma word, and what does not.[0m

       [4m[40m7.1.1[24m  [4mWords[24m [4mand[24m [4mKeywords[0m
       [40mWords are made of sequences of almost any character, and are[0m
       [40mseparated by white  space  (including  end-of-line)  or  the[0m
       [40mspecial symbols.  [1mCook [22mis always case sensitive when reading[0m
       [40mcookbooks.[0m

       [40mThe characters [1m:;={}[] [22mare  the  special  symbols,  and  are[0m
       [40mwords in themselves, needing no delimiting.[0m

       [40mIn  addition  to  the  special symbols, some words, known as[0m
       [4m[40mkeywords[24m, have special meaning to [1mcook[22m.  The keywords are:[0m

           [40melse        host-binding      loopstop      single-thread[0m
           [40mfail             if            return           then[0m
         [40mfunction          loop             set          unsetenv[0m
       [40mYou will meet the keywords in later sections.[0m

       [4m[40m7.1.2[24m  [4mEscape[24m [4mSequences[0m
       [40mThe character [1m\ [22mis the [4mescape[24m character.  If a character  is[0m
       [40mpreceded  by  a  [1m\  [22many  specialness, if it had any, will be[0m
       [40mremoved.  If it had no specialness it may have some added.[0m

       [40mThis means that, if you want to use [1mif  [22mas  a  word,  rather[0m
       [40mthan  a  keyword, at least one of its characters needs to be[0m
       [40mescaped, for example [1m\if[22m.[0m

       [40mThe escape sequences which are special are as follows.[0m

       
       Peter Miller                                         Page 43





       Cook                                              User Guide



       [40m           [1m\b    [22mThe backspace character[0m
                  [1m[40m\f    [22mThe form feed character[0m
                  [1m[40m\n    [22mThe newline or linefeed character[0m
                  [1m[40m\r    [22mThe carriage return character[0m
                  [1m[40m\t    [22mThe horizontal tab character[0m
                 [1m[40m\[4m[22mnnn[24m   A character with a value of  [4mnnn[24m,[0m
                        [40mwhere  [4mnnn[24m  is an octal number of[0m
                        [40mat most 3 digits.[0m
       [40mAn escaped end-of-line is totally  ignored.   It  should  be[0m
       [40mnoted  that  a  cookbook may not have any non-printing ASCII[0m
       [40mcharacters in it other than space, tab and end-of-line.[0m

       [4m[40m7.1.3[24m  [4mQuoting[0m
       [40mWords, and sections of words, may be quoted.  If any part of[0m
       [40ma word is quoted it cannot be a keyword.[0m

       [40mThis  means  that,  if  you want to use [1mif [22mas a word, rather[0m
       [40mthan a keyword, at least one of its characters needs  to  be[0m
       [40mquoted, for example [1m'if'[22m.[0m

       [40mBoth  single  ([1m'[22m)  and  double  ([1m"[22m) quotes are understood by[0m
       [1m[40mcook[22m, and one may enclose the other.  If a quote is  escaped[0m
       [40mit does not open or close a quote as it usually would.[0m

       [1m[40mCook  [22mdoes  not  like  newlines  within  quotes.   This is a[0m
       [40mgenerally good heuristic for catching unbalanced quotes.  If[0m
       [40myou  really  want  a  newline  within  a  string, use the \n[0m
       [40mescape.[0m

       [4m[40m7.1.4[24m  [4mComments[0m
       [40mComments are delimited on the left by [1m/*[22m, and on  the  right[0m
       [40mby  [1m*/[22m.   If  the [1m/ [22mcharacter has been escaped or quoted, it[0m
       [40mdoesn't  introduce  a  comment.   Comments  may  be  nested.[0m
       [40mComments  may span multiple lines.  Comments are replaced by[0m
       [40mone logical space.[0m

       [4m[40m7.2[24m  [4mPreprocessor[0m

       [40mThe preprocessor may be thought of as doing  a  little  work[0m
       [40mbefore the [4mSyntax[24m [4mand[24m [4mSemantics[24m section has its turn.[0m

       [40mThe  preprocessor  is  driven by [4mpreprocessor[24m [4mdirectives[24m.  A[0m
       [40mpreprocessor directive is a line which starts  with  a  hash[0m
       [40m([1m#[22m)  character.   Each  of  the  preprocessor  directives is[0m
       [40mdescribed below.[0m

       [4m[40m7.2.1[24m  [4minclude[0m
       [40mThe most common preprocessor directive is[0m
            [40m#include "[4mfilename[24m"[0m

       [40mThis preprocessor directive is processed as if the  contents[0m
       [40mof  the named file had appeared in the cookbook, rather than[0m
       [40mthe preprocessor include directive.[0m


       
       Peter Miller                                         Page 44





       Cook                                              User Guide



       [40mThe most common use of the #include directive is to  include[0m
       [40msystem  cookbooks.   For example, many small programs can be[0m
       [40mdeveloped using the following simple cookbook:[0m
            [40m#include "c"[0m
            [40m#include "program"[0m

       [40mThe standard places to search are first any  path  specified[0m
       [40mwith  the [1m-Include [22mcommand line option, and then [4m$HOME/.cook[0m
       [40mand then [4m${prefix}/share/cook[24m in that order.[0m

       [4m[40m7.2.2[24m  [4minclude-cooked[0m
       [40mThis directive looks similar to the one above, but do not be[0m
       [40mdeceived.[0m
            [40m#include-cooked [4mfilename[24m...[0m
       [40mYou  may name several filenames on the line, and they may be[0m
       [40mexpressions.[0m

       [40mThe search path used for these files is  the  same  as  that[0m
       [40mused  for  other  cooked files, see the [4msearch_list[24m variable[0m
       [40mand the [4mresolve[24m built-in function for more information.  The[0m
       [40morder  in  which  you  set the [4msearch_list[24m and the [4m#include-[0m
       [4m[40mcooked[24m directives is important.  Always set the  [4msearch_list[0m
       [40mvariable first, if you are going to use it.[0m

       [40mFiles included in this way are checked, after they have been[0m
       [40mread, to make sure they are up-to-date.  If  they  are  not,[0m
       [1m[40mcook  [22mbrings  them up-to-date and then re-reads the cookbook[0m
       [40mand starts over.[0m

       [40mYou will only get a warning if  the  files  are  not  found.[0m
       [40mUsually,  [1mcook  [22mwill either succeed in constructing them, in[0m
       [40mwhich case they will be present the second time around, or a[0m
       [40mfatal  error  will result from attempting to construct them.[0m
       [40mNote that it is possible to go into an infinite loop, if the[0m
       [40mfiles are constantly out-of-date.[0m

       [40mThe  commonest  use of this construct is maintaining include[0m
       [40mfile dependency lists for source files.[0m
            [40mobj = [fromto %.c %.o [glob *.c]];[0m

            [40m%.o: %.c[0m
            [40m{[0m
                    [40m[cc] [cc_flags] -c %.c;[0m
            [40m}[0m

            [40m%.c.d: %.c[0m
            [40m{[0m
                    [40mc_incl -prefix "'%.o "[target]": %.c'" -suffix "';'"[0m
                            [40m-no-cache %.c > [target];[0m
            [40m}[0m

            [40m#include-cooked [fromto %.o %.c.d [obj]][0m
       [40mThis cookbook fragment shows how include  file  dependencies[0m
       [40mare  maintained.   Notice  how the [4m.d[24m files have a recipe to[0m

       
       Peter Miller                                         Page 45





       Cook                                              User Guide



       [40mconstruct them, and that they are also included.  [1mCook  [22mwill[0m
       [40mbring  them  up-to-date  if  necessary, and then re-read the[0m
       [40mcookbook, so that it is  always  working  with  the  current[0m
       [40minclude  dependencies.   (The  doubly  nested  quotes are to[0m
       [40minsulate the spaces and special characters  from  both  [1mcook[0m
       [40mand the shell.)[0m

       [40mYou  could  use  [4mgcc[24m  [4m-MM[24m  if you prefer (you will need some[0m
       [40mextra shell script).  The [4mc_incl[24m program understands  absent[0m
       [40mfiles better but doesn't understand conditional compilation,[0m
       [40mand [4mgcc[24m understands conditional compilation but gives  fatal[0m
       [40merrors  for absent include files.  Warning: If you are using[0m
       [4m[40msearch_list[24m you  [1mmust  [22muse  [4mc_incl[24m.   Gcc  returns  complete[0m
       [40mpaths,  which  will result in [1mcook [22mfailing to notice when an[0m
       [40minclude file is copied from later  in  the  search  list  to[0m
       [40mearlier, and then modified.[0m

       [40mThere  are  times  when  you  don't want the #include-cooked[0m
       [40mdirectives to be acted upon.  You can over-ride it using the[0m
       [40m--no-include-cooked  command  line  option,  but it is often[0m
       [40measier to use the  [command-line-goals]  variable,  and  say[0m
       [40msomething like[0m
            [40m#if [not [match %1clean%2 [command-line-goals]]][0m
            [40m#include-cooked [fromto %.o %.c.d [obj]][0m
            [40m#endif[0m
       [40mThis  construct  means  that  whenever an explicit ``clean''[0m
       [40mgoal (or similar) is requested,  the  #include-cooked  lines[0m
       [40mwill  not  be performed.  This is sensible, because cleaning[0m
       [40mactions usually remove dependency files; there is  no  point[0m
       [40mmaking sure they are up-to-date first.[0m

       [4m[40m7.2.3[24m  [4minclude-cooked-nowarn[0m
       [40mThis  directive is almost identical to the one above, but no[0m
       [40mwarning is issued for absent files.[0m
            [40m#include-cooked-nowarn [4mfilename[24m...[0m
       [40mYou may name several filenames on the line, and they may  be[0m
       [40mexpressions.[0m

       [4m[40m7.2.4[24m  [4mif[0m
       [40mThe  #if  directive may be used to conditionally pass tokens[0m
       [40mto the syntax and semantics processing.  Directives take the[0m
       [40mform[0m
            [40m#if [4mexpression1[0m
            [4m[40msomething1[0m
            [40m#elif [4mexpression2[0m
            [4m[40msomething2[0m
            [40m#else[0m
            [4m[40msomething3[0m
            [40m#endif[0m
       [40mThere may be any number of elif clauses, and the else clause[0m
       [40mis optional.  Only one of  the  [4msomethings[24m  will  be  passed[0m
       [40mthrough.[0m



       
       Peter Miller                                         Page 46





       Cook                                              User Guide



       [40m[4m7.2.5[24m  [4mifdef[0m
       [40mThis directive takes a similar form to the if directive, but[0m
       [40mwith a different first line:[0m
            [40m#ifdef [4mvariable[0m
       [40mThis is syntactic sugar for[0m
            [40m#if [defined [4mvariable[24m][0m
       [40mThis is of most use in bracketing #include directives.[0m

       [4m[40m7.2.6[24m  [4mifndef[0m
       [40mThis directive takes a similar form to the if directive, but[0m
       [40mwith a different first line:[0m
            [40m#ifndef [4mvariable[0m
       [40mThis is syntactic sugar for[0m
            [40m#if [not [defined [4mvariable[24m]][0m
       [40mThis is of most use in bracketing #include directives.[0m

       [4m[40m7.2.7[24m  [4mpragma[0m
       [40mThis is for the addition of extensions.[0m

       [4m[40m7.2.7.1[24m  [4monce[0m
       [40mThis  directive  is to ensure that include files in which it[0m
       [40mappears are included exactly once.[0m

       [40mThis directive has the form[0m
            [40m#pragma once[0m

       [4m[40m7.2.7.2[24m  [4munknown[24m [4mextensions[0m
       [40mAny pragma extensions not recognized will be ignored.[0m



























       
       Peter Miller                                         Page 47





       Cook                                              User Guide



       [40m[4m7.3[24m  [4mSyntax[24m [4mand[24m [4mSemantics[0m

       [40mThe syntax is described using ``train track'' diagrams, with[0m
       [40mprose descriptions of the related semantics.[0m

       [4m[40m7.3.1[24m  [4mOverall[24m [4mStructure[0m
       [40mThe general form of the cookbook is defined as[0m
       [40m-c-o-o-k-b-o-o-k------+------------------------------------------+-----[0m
                       [40m-----------------------------     ------[0m
                            [40m------                  ------[0m
                        [40m-------+-----+-----+----------+-----[0m
                                 [40m----+-s-t-m-t+|   ------[0m
                                    [40m+--------[0m
                                  [40m--+f-u-n-c-tion+-----[0m
                                    [40m--------+[0m

       [40mA  cookbook  is  defined  as a sequence of statements.  Each[0m
       [40mstatement statement is executed.  For a definition  of  what[0m
       [40mit  means  when  a statement is executed, see the individual[0m
       [40mstatement definitions.[0m

       [40mThe nonterminal symbol [4mstatement[24m  will  be  defined  in  the[0m
       [40msections below.[0m

       [40mPlease note that a statement is not always evaluated when is[0m
       [40mis read, but at specific, well defined times.[0m

       [4m[40m7.3.2[24m  [4mThe[24m [4mCompound[24m [4mStatement[0m
       [40mA nonterminal symbol which will be referred to below is  the[0m
       [4m[40mcompound_statement[24m symbol, defined as follows:[0m
       [40mcstmt            -------                        -------[0m
       [40m------------------{-------------------------------}--------------[0m
                             [40m------ -----------    ------[0m
                                  [40m---+-----+  ------[0m
                               [40m------+-s-t-m-t++----+-----[0m

       [40mThe  compound statement may be used anywhere a statement may[0m
       [40mbe, and in particular[0m
       [40mstmt                          +-----+[0m
       [40m------------------------------+-c-s-t-m-t+--------------------------[0m


       [4m[40m7.3.3[24m  [4mVariables[24m [4mand[24m [4mExpressions[0m
       [1m[40mCook [22mprovides variables to the user to simplify things.[0m

       [4m[40m7.3.3.1[24m  [4mThe[24m [4mAssignment[24m [4mStatement[0m
       [40mIt is possible to assign to  variables  with  the  following[0m
       [40mstatement.[0m
       [40mstmt                  +----+  ----+-----+  ------[0m
       [40m----------------------+-e-x-p-r+---=---+e-x-p-r-s-+--;--------------------[0m

       [40mWhen this statement is executed, the variable whose name the[0m
       [40mleft hand expression evaluates to will be assigned the value[0m
       [40mthat the right hand expression list evaluates to.[0m

       
       Peter Miller                                         Page 48





       Cook                                              User Guide



       [40mFor example:[0m
            [40mprogram_obj = foo.o bar.o baz.o;[0m

       [1m[40mNote:  [22mIt  is  possible  to  over-ride the value of built-in[0m
       [40mfunctions and variables with this statement.  This will  not[0m
       [40mproduce   an  error  message,  however  it  is  usually  not[0m
       [40mdesirable as it will change the meaning of the rest of  your[0m
       [40mcookbook.[0m

       [4m[40m7.3.3.2[24m  [4mThe[24m [4mAssign-Append[24m [4mStatement[0m
       [40mIt  is possible to append to the value of variables with the[0m
       [40mfollowing statement.[0m
       [40mstmt                  +----+  ----+-----+  ------[0m
       [40m----------------------+-e-x-p-r+---+-=--+e-x-p-r-s-+--;--------------------[0m

       [40mWhen this statement is executed, the variable whose name the[0m
       [40mleft  hand  expression  evaluates  to  will  have  its value[0m
       [40mappended by the value that the right  hand  expression  list[0m
       [40mevaluates   to.   Expression  values  are  lists  of  words,[0m
       [40mappending means to append to the word list; it does [4mnot[24m mean[0m
       [40mappending to the last string of the value.[0m

       [40mFor example:[0m
            [40mprogram_obj += [glob "deeper/*.o" ];[0m

       [1m[40mNote:  [22mIt  is  possible  to  over-ride the value of built-in[0m
       [40mfunctions and variables with this statement.  This will  not[0m
       [40mproduce  an  error  message  (unless evaluating them with no[0m
       [40marguments is an error), however it is usually not  desirable[0m
       [40mas it will change the meaning of the rest of your cookbook.[0m

       [4m[40m7.3.3.3[24m  [4mThe[24m [4mSetenv[24m [4mStatement[0m
       [40mIt  is  possible to assign to environment variables with the[0m
       [40mfollowing statement.[0m
       [40mstmt             -------+----+  ----+-----+  ------[0m
       [40m-----------------s-e-t-e-n-v--+-e-x-p-r+---=---+e-x-p-r-s-+--;----------------[0m

       [40mWhen this statement is executed,  the  environment  variable[0m
       [40mwhose  name  the  left  hand expression evaluates to will be[0m
       [40massigned the value  that  the  right  hand  expression  list[0m
       [40mevaluates  to.   It  is  an  error  if the variable does not[0m
       [40malready exist.[0m

       [40mFor example:[0m
            [40msetenv PATH = [getenv PATH]":"[getenv HOME]/more-bin;[0m

       [4m[40m7.3.3.4[24m  [4mThe[24m [4mSetenv-Append[24m [4mStatement[0m
       [40mIt is possible to append to  the  value  of  an  environment[0m
       [40mvariables with the following statement.[0m
       [40mstmt             -------+----+  ----+-----+  ------[0m
       [40m-----------------s-e-t-e-n-v--+-e-x-p-r+---+-=--+e-x-p-r-s-+--;----------------[0m

       [40mWhen  this  statement  is executed, the environment variable[0m
       [40mwhose name the left hand expression evaluates to  will  have[0m

       
       Peter Miller                                         Page 49





       Cook                                              User Guide



       [40mits  value  appended  by  the  value  that  the  right  hand[0m
       [40mexpression list evaluates to.  Evaluation  is  analogous  to[0m
       [40mthe assign-append statement.[0m

       [40mFor example:[0m
            [40msetenv FRED += nurk;[0m

       [4m[40m7.3.3.5[24m  [4mExpressions[0m
       [40mMany definitions make reference to the [4mexpr,[24m [4melist[24m and [4mexprs[0m
       [40mnonterminal symbols.  These are defined as follows.[0m

       [40mThe [4melist[24m is a list of at least one expression,[0m
                                    [40m-----------[0m
                                  [40m---+------  ------[0m
       [40m-e-l-i-s-t-------------------------+-e-x-p-r-+----+---------------------[0m
                                     [40m-----+|[0m

       [40mwhereas the [4mexprs[24m is a list of zero or more expressions.[0m
       [40m-e-x-p-r-s----------------------------------------------------------[0m
                                  [40m------      ------[0m
                                    [40m--+----+-----[0m
                                      [40m+e-l-i-s-t+[0m


       [40mAn expression is composed  of  words,  variable  references,[0m
       [40mfunction  invocations, or concatenation of expressions.  The[0m
       [40mconcatenation is implied by abutting the two  parts  of  the[0m
       [40mexpression  together, [4me.g.:[24m "[fred]>thing" is an indirection[0m
       [40mon [4mfred[24m concatenated with the literal word ">thing".[0m
       [40mexpr                           ------[0m
       [40m--------------------------------[4mw[24m-[4mo[24m-[4mr[24m-[4md[24m----------------------------[0m
                            [40m----------+----- ------- ------[0m
                             [40m------[---+e-l-i-s-t+--]-------[0m
                                  [40m---------+ ------[0m
                             [40m--+----+-------+----+-----[0m
                               [40m+-e-x-p-r+  -[4mc[24m-[4ma[24m-[4mt[24m  +-e-x-p-r+[0m


       [40mWhen an  [1m[[4m[22melist[24m[1m]  [22mexpression  is  evaluated,  the  [4melist[24m  is[0m
       [40mevaluated  first.   If  the  result is a single word, then a[0m
       [40mvariable of that name is searched for.  If found  the  value[0m
       [40mof an expression of this form is the value of the variable.[0m

       [40mIf  there  is  no  variable  of the given name, or the [4melist[0m
       [40mevaluated to more than one word, the first word is taken  to[0m
       [40mbe  a  built-in  function  name.  If there is no function of[0m
       [40mthis name it is an error.[0m

       [40mThe [4mcat[24m operator works as one would expect, joining the last[0m
       [40mword  of the left expression and the first word of the right[0m
       [40mexpression together, and otherwise leaving the order of  the[0m
       [40mexpressions  alone.   One  usually  uses the trivial case of[0m
       [40msingle word expressions.  For more  complex  concatenations,[0m
       [40msee the [catenate] and [join] built-in functions.[0m

       
       Peter Miller                                         Page 50





       Cook                                              User Guide



       [40m[4m7.3.4[24m  [4mRecipes[0m
       [40mA  number  of  forms of [4mstatement[24m are concerned with telling[0m
       [1m[40mcook [22mhow  to  cook  things.   There  are  three  forms,  the[0m
       [4m[40mexplicit[24m  recipe,  the  [4mimplicit[24m recipe, and the [4mingredients[0m
       [40mrecipe.[0m

       [4m[40m7.3.5[24m  [4mThe[24m [4mExplicit[24m [4mRecipe[24m [4mStatement[0m
       [40mThe explicit recipe has the form[0m
       [40mstmt       +----+  ---+-----++-----+ +----++-----+-+---+[0m
       [40m-----------+e-l-i-s-t+--:---+e-x-p-r-s-++-f-l-a-g-s+-+g-a-t-e-++-c-s-t-m-t+-+u-s-e-++------[0m

       [40mThe target(s) of the recipe are to the left  of  the  colon,[0m
       [40mand  the  ingredients,  if  any,  are  to  the  right.   The[0m
       [40mstatements, usually commands, which are to be  performed  to[0m
       [40m(re)construct  the  target(s)  are contained in the compound[0m
       [40mstatement.  The expressions are only  evaluated  into  words[0m
       [40mwhen  the  recipe is executed.  Recipe bodies may have local[0m
       [40mvariables.[0m

       [40mFor example:[0m
            [40mprogram: [program_obj][0m
            [40m{[0m
                    [40m/* use [need] rather than [program_obj] in case[0m
                       [40mthere are additional ingredients recipes[0m
                       [40m(see below).  */[0m
                    [40mcc -o program [need];[0m
            [40m}[0m

       [40mThe target expressions and recipe flags are  evaluated  when[0m
       [40mthe recipe is instantiated.  The ingredients expressions and[0m
       [40mthe recipe gate are evaluated at graph building  time.   The[0m
       [40mbody and use statements are executed at graph walking time.[0m

       [40mThe recipes also take a ``[4mhost-binding[24m'' attribute.  See the[0m
       [40mchapter on Cooking in Parallel for how this is attribute  is[0m
       [40mwritten  and used.  If the host binding flag is given, it is[0m
       [40malways used, even when not cooking in parallel.   If  it  is[0m
       [40mnot  given  [4mand[24m you are cooking in parallel, it will default[0m
       [40mto the contents of the [parallel_hosts] variable.[0m

       [4m[40m7.3.5.1[24m  [4mRecipe[24m [4mFlags[0m
       [40mThe [4mflags[24m are defined as follows.[0m
       [40m-f-l-a-g-s----------------------------------------------------------[0m
                               [40m------            ------[0m
                                 [40m-------+-----+-----[0m
                                   [40m-s-e-t--+e-x-p-r-s-+[0m

       [40mRecipe flags are  evaluated  when  the  recipe  targets  are[0m
       [40mevaluated.   At  this time, [4mnone[24m of the [target], [targets],[0m
       [40m[need] or [younger] variables are set, and neither  are  any[0m
       [40mof the pattern matches (%, %1, [4metc[24m) available.[0m

       [40mA number of flags may be used[0m


       
       Peter Miller                                         Page 51





       Cook                                              User Guide



       [40mclearstat The  last-modified  time  of  the  files  named in[0m
                 [40mexecuted commands will be removed from  the  last-[0m
                 [40mmodified   time  cache.   This  is  essential  for[0m
                 [40mcommands such as [4mrm[24m(1) and [4mmv[24m(1).[0m

       [40mnoclearstat Do not clear entries from the last-modified time[0m
                 [40mcache.  This is usually the default.[0m

       [40mdefault   If  no  targets are specified on the command line,[0m
                 [40mthe first recipe with the  [4mdefault[24m  flag  will  be[0m
                 [40mused.  Not meaningful for implicit recipes.[0m

       [40mnodefault If  no  targets are specified on the command line,[0m
                 [40mand there are no recipes  with  the  [4mdefault[24m  flag[0m
                 [40mset,  the  first recipe [1mwithout [22mthe [4mnodefault[24m flag[0m
                 [40mwill  be  used.   Not  meaningful   for   implicit[0m
                 [40mrecipes.[0m

       [40merrok     Exit status from commands will be ignored.[0m

       [40mnoerrok   If  the  [4mnoerrok[24m  flag  is specified, the commands[0m
                 [40mwithin the actions bound to the recipe must always[0m
                 [40mbe successful.  This is usually the default.[0m

       [40mfingerprint File  fingerprints  are used to supplement last-[0m
                 [40mmodified time information about  files,  which  is[0m
                 [40mhow  [4mcook[24m  determines if a file is out-of-date and[0m
                 [40mneeds to be cooked.  If a  file  appears  to  have[0m
                 [40mchanged,   from  the  last-modified  time,  it  is[0m
                 [40mfingerprinted, and the fingerprint  compared  with[0m
                 [40mwhat  it was in the past.  The file has changed if[0m
                 [40mand only if the fingerprint has also  changed.   A[0m
                 [40mcryptographically  strong  hash  is  used,  so the[0m
                 [40mchance of  a  file  edit  producing  an  identical[0m
                 [40mfingerprint    is   less   than   1   in   2**200.[0m
                 [40mFingerprinting is disabled by default.[0m

       [40mnofingerprint Do  not  use  file  fingerprinting.   This  is[0m
                 [40musually the default.[0m

       [40mforced    If the [4mforced[24m flag is specified, the actions bound[0m
                 [40mto the recipe will always be evaluated.[0m

       [40mnoforced  If the [4mnoforced[24m flag  is  specified,  the  actions[0m
                 [40mbound  to  the  recipe  will be evaluated when the[0m
                 [40mrecipe is logically out-of-date.  This is  usually[0m
                 [40mthe default.[0m

       [40mgate-after-ingredients This  flags causes the recipe gate to[0m
                 [40mbe  evaluated  after  the  ingredients  have  been[0m
                 [40mevaluated  and determined to be cookable.  This is[0m
                 [40musually the default.[0m



       
       Peter Miller                                         Page 52





       Cook                                              User Guide



       [40mgate-before-ingredients This flag causes the recipe gate  to[0m
                 [40mbe  applied  before  the ingredients are evaluated[0m
                 [40mand determined to be cookable.  This is useful  if[0m
                 [40mthe  ingredients  evaluation  itself  needs  to be[0m
                 [40mconditional.[0m

       [40mimplicit-ingredients[0m
                 [40mThis flag may be used to specify that  a  recipe's[0m
                 [40mingredients  may be satisfied by implicit recipes.[0m
                 [40mThis is usually the default.[0m

       [40mno-implicit-ingredients[0m
                 [40mThis flag may be used to specify that  a  recipe's[0m
                 [40mingredients  may  not  be  satisfied  by  implicit[0m
                 [40mrecipes; this is of most use with  utilities  such[0m
                 [40mas  RCS  where  the  recipe  writer knows that the[0m
                 [40mingredients cannot be constructed.[0m

       [40minclude-cooked-warning This  flag  may  be  used  to  enable[0m
                 [40mwarnings  when  the  relationship between a target[0m
                 [40mand a derived ingredient appears only in a derived[0m
                 [40mcookbook.  This is usually the default.  This flag[0m
                 [40mis only meaningful at the cookbook  level,  it  is[0m
                 [40mnot meaningful for individual recipes or commands.[0m

       [40mno-include-cooked-warning This  flag  may be used to disable[0m
                 [40mwarnings when the relationship  between  a  target[0m
                 [40mand a derived ingredient appears only in a derived[0m
                 [40mcookbook.  This flag is  only  meaningful  at  the[0m
                 [40mcookbook   level,   it   is   not  meaningful  for[0m
                 [40mindividual recipes or commands.[0m

       [40mingredients-fingerprint This  flag  may  be  used  to  cause[0m
                 [40mrecipes  to re-trigger when their ingredients list[0m
                 [40mchanges in any way.  This  is  especially  useful,[0m
                 [40mfor  example,  in  causing libraries to be rebuilt[0m
                 [40mwhen a content source file is removed.[0m

       [40mno-ingredients-fingerprint Cancel  any  active  [4mingredients-[0m
                 [4m[40mfingerprint[24m setting.[0m

       [40mmatch-mode-cook Use native Cook pattern matching.[0m

       [40mmatch-mode-regex Use   POSIX   regular   expression  pattern[0m
                 [40mmatching.[0m

       [40mmeter     If the [4mmeter[24m flag is specified, a summary  of  the[0m
                 [40mCPU  usage by the commands within this recipe will[0m
                 [40mbe printed after each command.  The silent options[0m
                 [40moverride this option.[0m

       [40mnometer   Do  not  meter  commands.   This  is  usually  the[0m
                 [40mdefault.[0m


       
       Peter Miller                                         Page 53





       Cook                                              User Guide



       [40mmkdir     If the [4mmkdir[24m flag is specified, the directories of[0m
                 [40many  targets  will  be  created before the actions[0m
                 [40mbound to the recipe are evaluated.[0m

       [40mnomkdir   If the [4mnomkdir[24m flag is specified, the  directories[0m
                 [40mof  any  targets  will  need  to be created by the[0m
                 [40mactions bound to the recipe.  This is usually  the[0m
                 [40mdefault.[0m

       [40mprecious  If  the [4mprecious[24m flag is specified, if the actions[0m
                 [40mbound to the  recipe  fail,  the  targets  of  the[0m
                 [40mrecipe will not be deleted.[0m

       [40mnoprecious If  the  [4mnoprecious[24m  flag  is  specified,  if the[0m
                 [40mactions bound to the recipe fail, the  targets  of[0m
                 [40mthe  recipe  will be deleted.  This is usually the[0m
                 [40mdefault, so that erroneous  targets  will  be  re-[0m
                 [40mcooked.[0m

       [40mrecurse   If  this  flag  is specified, recipes will recurse[0m
                 [40mupon  themselves  if  one  of  their   ingredients[0m
                 [40mmatches  one  of  their  targets.   This can cause[0m
                 [40mproblems, and so it is not the default.[0m

       [40mnorecurse If this flag is specified,  the  recipe  will  not[0m
                 [40mrecurse  if  one of its ingredients matches one of[0m
                 [40mits targets.  This is the default.[0m

       [40msilent    If the [4msilent[24m  flag  is  specified,  the  commands[0m
                 [40mwithin the actions bound to the recipe will not be[0m
                 [40mechoed.[0m

       [40mnosilent  Commands will be  echoed.   This  is  usually  the[0m
                 [40mdefault.[0m

       [40mstripdot  This  option  causes  [1mcook  [22mto remove leading "./"[0m
                 [40mprefixes from  filenames.   This  is  usually  the[0m
                 [40mdefault.[0m

       [40mnostripdot This  option  causes  [1mcook  [22mto leave leading "./"[0m
                 [40mprefixes on filenames.[0m

       [40msymlink-ingredients When  using  a  search   path,   of   an[0m
                 [40mingredient  exists, but is not in the top level of[0m
                 [40mthe  search  path,  this  option  request  that  a[0m
                 [40msymbolic link to the actual file be created in the[0m
                 [40mtop level directory.   This  option  is  typically[0m
                 [40mused  on  a  per-recipe  basis  for for brain dead[0m
                 [40mtools, like GNU Automake, which don't grok  search[0m
                 [40mpaths.[0m

       [40mno-symlink-ingredients Reverse  of  the above.  Never create[0m
                 [40msymbolic links for ingredients.[0m


       
       Peter Miller                                         Page 54





       Cook                                              User Guide



       [40mtell-position This  option  causes  the  filename  and  line[0m
                 [40mnumber  to  be  printed when echoing commands just[0m
                 [40mbefore they  are  executed,  in  addition  to  the[0m
                 [40mcommand itself.[0m

       [40mno-tell-position This  option suppresses the printing of the[0m
                 [40mfilename and line  number  when  echoing  commands[0m
                 [40mjust  before  they  are executed.  This is usually[0m
                 [40mthe default.[0m

       [40mtime-adjust This option  causes  [1mcook  [22mto  check  the  last-[0m
                 [40mmodified  time  of  the  targets  of  recipes, and[0m
                 [40madjust them if necessary, to make  sure  they  are[0m
                 [40mconsistent  with  (younger than) the last-modified[0m
                 [40mtimes of the ingredients.   This  usually  adjusts[0m
                 [40mthe  file  time into the (near) future.  A warning[0m
                 [40mmessage will be  printed,  telling  you  how  many[0m
                 [40mseconds  the  file  was adjusted.  This results in[0m
                 [40mmore system calls, and can  slow  things  down  on[0m
                 [40msome systems6.[0m

       [40mno-time-adjust Do  not  adjust  the file last-modified times[0m
                 [40mafter performing the body of a  recipe.   This  is[0m
                 [40musually the default.[0m

       [40mtime-adjust-back  This option causes [1mcook [22mto force the last-[0m
                 [40mmodified time of the  targets  of  recipes  to  be[0m
                 [40mexactly one (1) second younger than their youngest[0m
                 [40mingredient.  This usually adjusts  the  file  time[0m
                 [40minto the (recent) past.  A warning message will be[0m
                 [40mprinted, telling you how many seconds the file was[0m
                 [40madjusted.   This results in more system calls, and[0m
                 [40mcan slow things down on  some  systems.   This  is[0m
                 [40mprimarily  useful when some later process is going[0m
                 [40mto compress file modification times; this provides[0m
                 [40msmarter compression.[0m

       [40munlink    If  the  [4munlink[24m  flag is specified, of any targets[0m
                 [40mwill be unlinked before the actions bound  to  the[0m
                 [40mrecipe are performed.[0m

       [40mnounlink  If  the  [4mnounlink[24m  flag  is  specified, the recipe[0m
                 [40mtargets are not removed before the  actions  bound[0m
                 [40mto  the recipe are performed.  This is usually the[0m
                 [40mdefault.[0m

       [40mEach flag may also be specified in the negative, by adding a[0m
       [40m"no"  prefix,  to  override  any  existing  positive default[0m
       [40msetting.  There is  a  strict  precedence  defined  for  the[0m

       ____________________

       6. This  flag  was once named the ``update'' flag.  The name
          was changed to more closely reflect  its  function.   The
          old name continues to work.

       Peter Miller                                         Page 55





       Cook                                              User Guide



       [40mvarious levels of flag setting, see the end of the "How Cook[0m
       [40mWorks" chapter for details.[0m

       [4m[40m7.3.5.2[24m  [4mRecipe[24m [4mGate[0m
       [40mEach recipe  may  have  a  [4mgate[24m.   The  gate  is  a  way  of[0m
       [40mspecifying  a  conditional  recipe;  if the condition is not[0m
       [40mtrue, the recipe is not used.  The condition is in  addition[0m
       [40mto the condition that the ingredients are cookable.[0m
       [40m-g-a-t-e-----------------------------------------------------------[0m
                                [40m------           ------[0m
                                 [40m-------+----+-----[0m
                                    [40m-i-f--+-e-x-p-r+[0m


       [40mFor example:[0m
            [40mprogram: [program_obj][0m
                    [40mif [not [in horrible.o [program_obj]]][0m
            [40m{[0m
                    [40mcc -o program [program_obj];[0m
            [40m}[0m

       [4m[40m7.3.5.3[24m  [4mThen[24m [4mClause[0m
       [40mThere  are  times when it is necessary to know that a recipe[0m
       [40mhas been applied, but because the recipe was up-to-date, the[0m
       [40mrecipe body was not run.[0m
       [40m-u-s-e------------------------------------------------------------[0m
                              [40m------              ------[0m
                                [40m--------+-----+-----[0m
                                  [40mt-h-e-n--+-c-s-t-m-t+[0m

       [40mThe  then-clause  is  run  every time the recipe is applied,[0m
       [40meven if the recipe is up-to-date.  It will be run after  the[0m
       [40mrecipe  body,  if  the recipe body is run.  All of the usual[0m
       [40mpercent  (%)  substitutions  and  automatic  variables  will[0m
       [40mapply.  Recipe then-clauses may have local variables.[0m

       [40mFor example:[0m
            [40mprogram: [program_obj][0m
            [40m{[0m
                    [40mcc -o program [program_obj];[0m
            [40m}[0m
            [40mthen[0m
            [40m{[0m
                    [40minstall-set += program;[0m
            [40m}[0m

       [4m[40m7.3.5.4[24m  [4mDouble[24m [4mColon[0m
       [40mMost  cookbooks  are  constructed  so  that  if [1mcook [22mfinds a[0m
       [40msuitable recipe for the target it is currently constructing,[0m
       [40mit  will  apply  the  recipe  and  then conclude that it has[0m
       [40mfinished constructing the target.  In some  rare  cases  you[0m
       [40mwill  want  [1mcook  [22mto keep going after applying a recipe.  To[0m
       [40mspecify this use a ``double colon'' construction:[0m


       
       Peter Miller                                         Page 56





       Cook                                              User Guide



       [40mstmt       +----+  ---+-----++-----+ +----++-----+-+---+[0m
       [40m-----------+e-l-i-s-t+--:-:--+e-x-p-r-s-++-f-l-a-g-s+-+g-a-t-e-++-c-s-t-m-t+-+u-s-e-++------[0m

       [40mThis operates like a normal explicit recipe, but  [1mcook  [22mwill[0m
       [40mcontinue on looking for recipes after applying this one.  As[0m
       [40msoon as an applicable ``single colon'' recipe is  found  and[0m
       [40mapplied,   [1mcook   [22mwill   conclude   that   it  has  finished[0m
       [40mconstructing the target.[0m

       [40mFor example:[0m
            [40mall:: programs[0m
            [40m{[0m
                    [40m[print "all programs done"];[0m
            [40m}[0m
            [40mall:: libraries[0m
            [40m{[0m
                    [40m[print "all libraries done"];[0m
            [40m}[0m

       [4m[40m7.3.6[24m  [4mThe[24m [4mImplicit[24m [4mRecipe[24m [4mStatement[0m
       [40mImplicit recipes are distinguished from explicit recipes  in[0m
       [40mthat  and  implicit recipe has a target with a '[1m%[22m' character[0m
       [40min it.[0m

       [4m[40m7.3.6.1[24m  [4mSimple[24m [4mForm[0m
       [40mIn general the user will rarely need  to  use  the  implicit[0m
       [40mrecipe  form,  as there are a huge range of implicit recipes[0m
       [40malready defined in the system default recipes.[0m

       [40mAn example of this recipe form is[0m
            [40m%: %.gz[0m
            [40m{[0m
                    [40mgzcat %.gz > %;[0m
            [40m}[0m
       [40mThis recipe tells [1mcook [22mhow to use the [4mgzcat[24m(1) program.[0m

       [4m[40m7.3.6.2[24m  [4mComplex[24m [4mForm[0m
       [40mThe implicit recipe recipe has a second form where there are[0m
       [40mtwo  sets  of  ingredients,  separated by another colon.  In[0m
       [40mthis  form,  the  ingredients   specified   in   the   first[0m
       [40mingredients  list are used to determine the applicability of[0m
       [40mthe recipe; if these are all constructible then  the  recipe[0m
       [40mwill  be  applied,  if  any  are  not constructible then the[0m
       [40mrecipe will not be applied.  If the recipe is  applied,  the[0m
       [40mingredients  specified  in  the  second ingredients list are[0m
       [40mrequired to be constructible.  The  the  second  ingredients[0m
       [40mlist section is known as the [4mforced[24m [4mingredients[24m section.[0m

       [1m[40mNote: [22mif you want the first ingredients list to be empty you[0m
       [4m[40mmust[24m separate the two colons with a  space,  otherwise  [1mcook[0m
       [40mwill think this is a ``double colon'' recipe.[0m

       [40mAn example of this is the C recipe[0m
            [40m%.o: %.c: [collect c_incl -api %.c][0m

       
       Peter Miller                                         Page 57





       Cook                                              User Guide



       [40m     {[0m
                    [40mcc -c %.c;[0m
            [40m}[0m
       [40mThis  recipe  is applied if the [4m%.c[24m file can be constructed,[0m
       [40mand is not applied if it cannot be constructed.  The include[0m
       [40mdependencies are only expressed if the recipe is going to be[0m
       [40mapplied;  but  if  they  are   expressed,   they   [4mmust[24m   be[0m
       [40mconstructible.    This   means  that  absent  include  files[0m
       [40mgenerate an error7.[0m

       [40mThe naive form of this recipe[0m
            [40m%.o: %.c [collect c_incl -api %.c][0m
            [40m{[0m
                    [40mcc -c %.c;[0m
            [40m}[0m
       [40mwill attempt to apply the [4mc_incl[24m command before the [4m%.c[24m file[0m
       [40mis  guaranteed  to  exist.   This  is  because the [4mexprs2[24m is[0m
       [40mperformed after the  [4mexprs1[24m  all  exist  (because  they  are[0m
       [40mconstructible,  they  have been constructed).  In this naive[0m
       [40mform, absent include files result in the  recipe  not  being[0m
       [40mapplied.[0m

       [4m[40m7.3.6.3[24m  [4mDouble[24m [4mColon[0m
       [40mJust as explicit recipes have a ``double colon'' form, so do[0m
       [40mboth  types  of  implicit  recipes.    The   semantics   are[0m
       [40midentical,  with  [1mcook  [22mlooking for more than one applicable[0m
       [40mimplicit recipe, but stopping  if  it  finds  an  applicable[0m
       [40m``single colon'' implicit recipe.[0m

       [40mAs  stated  earlier  in  this  manual,  [1mcook [22mfirst scans for[0m
       [40mexplicit recipes before scanning for implicit  recipes.   If[0m
       [40man explicit recipe has been applied, [1mcook [22mwill not also look[0m
       [40mfor applicable implicit recipes, even if all the  applicable[0m
       [40mexplicit recipes were double colon recipes.[0m

       [4m[40m7.3.7[24m  [4mThe[24m [4mIngredients[24m [4mRecipe[24m [4mStatement[0m
       [40mThe ingredients recipe has the form[0m
       [40mstmt            +----+  ---+-----++-----++----+   ------[0m
       [40m----------------+e-l-i-s-t+--:---+e-x-p-r-s-++f-l-a-g-s-++-g-a-t-e+---;-------------[0m

       [40mThe  target(s)  of  the recipe are to the left of the colon,[0m
       [40mand the prerequisites  are  to  the  right.   There  are  no[0m
       [40mstatements to perform to cook the targets of this recipe, it[0m
       [40mis simply supplementary to  any  other  recipe,  usually  an[0m
       [40mimplicit recipe.[0m

       [40mFor example:[0m
            [40mprogram: batman.o robin.o;[0m


       ____________________

       7. This is not the recommended way of determining C  include
          dependencies,  see  the  ``Include Dependencies'' chapter
          for more information.

       Peter Miller                                         Page 58





       Cook                                              User Guide



       [40mThe  right-hand-side  expressions  are  only  evaluated into[0m
       [40mwords when the recipe is instantiated.[0m

       [40mIngredients recipes are usually explicit,  but  it  is  also[0m
       [40mvalid to use implicit ingredients recipes.[0m

       [40mFor example:[0m
            [40msome-%-program: %.o;[0m

       [4m[40m7.3.8[24m  [4mThe[24m [4mCascade[24m [4mRecipe[24m [4mStatement[0m
       [40mThe cascade recipe statement has the form[0m
        [40mstmt            --------+----+  ----+----+  ------[0m
       [40m-----------------c-a-s-c-a-d+e -+e-l-i-s-t+---=---+e-l-i-s-t+--;----------------[0m

       [40mThis  recipe  specifies  on  its  right-hand-side additional[0m
       [40mingredients for any recipe which has  ingredients  mentioned[0m
       [40mon the left-hand-side of this cascade recipe.[0m

       [40mUnlike  all  other recipe forms, both the left-hand-side [4mand[0m
       [40mthe  right-hand-side  are  evaluated  when  the  recipe   is[0m
       [40minstantiated.[0m

       [40mFor example:[0m
            [40mcascade batman.c = robin.h;[0m
            [40mcascade somelib.a = some-deeper-lib.a;[0m

       [4m[40m7.3.9[24m  [4mCommands[0m
       [40mCommands  may take several forms in [1mcook[22m.  They all have one[0m
       [40mthing in common; they execute a command.[0m

       [4m[40m7.3.10[24m  [4mThe[24m [4mSimple[24m [4mCommand[24m [4mStatement[0m
       [40mThe simplest command form is[0m
       [40mstmt                     +----++-----+  ------[0m
       [40m-------------------------+e-l-i-s-t++-f-l-a-g-s+---;----------------------[0m

       [40mWhen executed, the [4melist[24m is evaluated into a word  list  and[0m
       [40mused  as a command to be passed to the operating system.  On[0m
       [40mUNIX this usually means that a shell is invoked to  run  the[0m
       [40mcommand,   unless   the   string  contains  no  shell  meta-[0m
       [40mcharacters.[0m

       [40mThe [4mflags[24m are those which may be specified in  the  explicit[0m
       [40mrecipe statement.  They have a higher precedence than either[0m
       [40mthe [4mset[24m statement or the recipe flags.[0m

       [40mSome characters in commands are special both  to  the  shell[0m
       [40mand  to  cook.   You  will  need  to  quote  or escape these[0m
       [40mcharacters.  Each command is executed in a separate process,[0m
       [40mso the cd command will not work, you will need to combine it[0m
       [40mwith the relevant commands, not  forgetting  to  escape  the[0m
       [40msemicolon (;) characters.[0m

       [40mWhen  Cook  needs to invoke a shell to execute a command, it[0m
       [40muses the shell named in the SHELL environment variable.   If[0m

       
       Peter Miller                                         Page 59





       Cook                                              User Guide



       [40mthe  cookbook is to be used by a variety of users, each with[0m
       [40ma different shell setting, it may be useful to add a[0m
            [40msetenv SHELL = /bin/sh;[0m
       [40mline at the top of your cookbook.[0m

       [40mIt is also important to note that unless the [4merrok[24m flag  has[0m
       [40mbeen specified, the shell will be given the -e option, which[0m
       [40mwill cause it to exit immediately after  the  first  command[0m
       [40mwhich returns a non-zero exit status.  This can be important[0m
       [40mwhen commands in the [4m.profile[24m or [4m.bashrc[24m (or  similar)  file[0m
       [40mfails.[0m

       [4m[40m7.3.11[24m  [4mThe[24m [4mData[24m [4mCommand[24m [4mStatement[0m
       [40mFor  programs  which require [4mstdin[24m to be supplied by [1mcook [22mto[0m
       [40mperform their functions, the data command statement has been[0m
       [40mprovided.[0m
       [40mstmt         |-----++-----+  ---------+-----+  -----------[0m
       [40m-------------+-e-l-i-s+t++f-l-a-g-s-+--;----d-a-t-a--+-e-x-p-r++-d-a-t-a-e-n+d ----------[0m

       [40mIn this form, the [4mexpr[24m is evaluated and used as input to the[0m
       [40mcommand.   Between  the  [1mdata  [22mand  [1mdataend   [22mkeywords   the[0m
       [40mdefinition  of  the  special  symbols and whitespace change.[0m
       [40mThere are only two  special  symbols,  [1m[  [22mand  [1m][22m,  to  allow[0m
       [40mfunctions   and   variable   references  to  appear  in  the[0m
       [40mexpression.  In addition,  whitespace  ceases  to  have  its[0m
       [40musual specialness; it is handed to the command, instead.[0m

       [40mFor  those  of you familiar with writing shell scripts, this[0m
       [40mis analogous to [4mhere[24m documents.  It allows you to create  an[0m
       [40minput  file without creating an explicit temporary file.  It[0m
       [40malso allows you to create files that you  could  not  create[0m
       [40musing [4mecho[24m redirected into the file8.[0m

       [40mThe [1mdata [22mkeyword must be the  last  on  a  line,  whitespace[0m
       [40mafter the [1mdata [22mkeyword up to and including end-of-line, will[0m
       [4m[40mnot[24m be given to the command.[0m

       [40mThe [1mdataend [22mkeyword must appear alone on a line,  optionally[0m
       [40msurrounded  by  whitespace;  if it is not alone, it is not a[0m
       [1m[40mdataend [22mkeyword and will not terminate the expression.[0m

       [40mAn example of this may be useful.[0m
            [40m/usr/fred/%: %[0m
            [40m{[0m
                    [40mnewgrp fred;[0m
            [40mdata[0m
            [40mcp % /usr/fred/%[0m
            [40mdataend[0m
            [40m}[0m
       [40mThe [4mnewgrp[24m(1) command is used to change the default group of[0m

       ____________________

       8. For  example,  Windows NT has a ludicrously small command
          line length limit.

       Peter Miller                                         Page 60





       Cook                                              User Guide



       [40ma process, and then throw a shell; so the ``cp'' is executed[0m
       [40mby this sub-shell when it reads its standard input.  If  the[0m
       [40mdirectory  [4m/usr/fred[24m  has  read-only permissions for others,[0m
       [40mand group write permissions, and belonged to group [4mfred[24m, and[0m
       [40myou  were  a member of group [4mfred[24m, the above implicit recipe[0m
       [40mcould be used to copy the file.[0m

       [40mHere is an example of how to cope  with  stupidly  short  NT[0m
       [40mcommand lines:[0m
            [40m%.LIB: [%_obj][0m
            [40m{[0m
                    [40mcat > %.contents;[0m
            [40mdata[0m
            [40m[unsplit "\n" [unix-to-dos [need]]][0m
            [40mdataend[0m
                    [40mlink -lib "/out:"[unix-to-dos [target]] @%.contents;[0m
                    [40mrm %.contents;[0m
            [40m}[0m
       [40mThe  ``@[4msomething[24m''  means the linker should read file names[0m
       [40mfrom the [4msomething[24m file.[0m

       [40mThis technique will also work with Unix  if  you  have  more[0m
       [40mthen  5MB  of  command  line  arguments  [4mand[24m  the program is[0m
       [40mwritten to have an option something like this (many  have  a[0m
       [1m[40m-f [22moption).[0m

       [4m[40m7.3.12[24m  [4mThe[24m [4mSet[24m [4mStatement[0m
       [40mIt is possible to override the defaults used by [1mcook [22mor even[0m
       [40mthose specified by the [4mCOOK[24m environment variable,  by  using[0m
       [40mthe [4mset[24m statement.[0m
       [40mstmt                       -----+-----+  ------[0m
       [40m----------------------------s-e-t--+e-x-p-r-s-+--;------------------------[0m

       [40mThe  flag  values are those mentioned in the [4mflags[24m clause of[0m
       [40mthe explicit recipe statement.   Many  command-line  options[0m
       [40mhave  equivalent  flag  settings.   There  is  no  ``unset''[0m
       [40mstatement, to  restore  the  default  settings,  but  it  is[0m
       [40mpossible  to  set flags the other way, by adding or removing[0m
       [40mthe ``no'' prefix.[0m

       [40mTo set flags for individual recipes, use the [4mflags[24m clause of[0m
       [40mthe recipe statements.[0m

       [40mTo  set  flags for individual commands, use the [4mflags[24m clause[0m
       [40mof the command statements.[0m

       [4m[40m7.3.12.1[24m  [4mExamples[0m
       [40mFingerprinting is not used by default, because it can  cause[0m
       [40ma  few  surprises,  and  takes a little more CPU.  To enable[0m
       [40mfingerprinting for you project, place the statement[0m
            [40mset fingerprint;[0m
       [40msomewhere near the  start  of  your  [4mHowto.cook[24m  file.   The[0m
       [1m[40m-No_FingerPrint [22mcommand line option can still override this,[0m
       [40mbut the default behavior will be to use fingerprints.[0m

       
       Peter Miller                                         Page 61





       Cook                                              User Guide



       [40mTo prevent echoing of commands as they are executed, place[0m
            [40mset silent;[0m
       [40msomewhere in your [4mHowto.cook[24m file.   The  [1m-NoSilent  [22mcommand[0m
       [40mline  option  can  still  override  this,  but  the  default[0m
       [40mbehavior will be not to echo commands.[0m

       [4m[40m7.3.13[24m  [4mThe[24m [4mFail[24m [4mStatement[0m
       [1m[40mCook [22mcan be forced to think that a recipe has failed by  the[0m
       [40muses of the [1mfail [22mstatement.[0m
       [40mstmt                      -----+-----+  ------[0m
       [40m--------------------------f-a-i-l--+e-x-p-r-s-+--;-----------------------[0m

       [40mThis  is  hugely useful when programs do not return a useful[0m
       [40mexit status, but [4mdo[24m fail.  If they  have  printed  an  error[0m
       [40mmessage, but not produced the output file, you could use the[0m
       [40mFail statement without arguments:[0m
            [40mfred: other stuff[0m
                    [40mset unlink[0m
            [40m{[0m
                    [40mbrain-dead [need] -o [target];[0m
                    [40mif [not [exists [target]]] then[0m
                            [40mfail;[0m
            [40m}[0m

       [40mIf you give the Fail statement any arguments, they  will  be[0m
       [40mprinted as an error message before the recipe fails:[0m
            [40mfred: other stuff[0m
                    [40mset unlink[0m
            [40m{[0m
                    [40mbrain-dead [need] -o [target];[0m
                    [40mif [not [exists [target]]] then[0m
                            [40mfail Did not produce [target] file.;[0m
            [40m}[0m

       [4m[40m7.3.14[24m  [4mThe[24m [4mIf[24m [4mStatement[0m
       [40mThe if statement has one of two forms.[0m
       [40mstmt    ----+----+  -----+-----+[0m
       [40m-----+--i-f---+e-x-p-r-+--t-h-e-n--+-s-t-m-t++----------------------------[0m
                                         [40m----------+----+  ------[0m
                                          [40m----e-l-s-e--+s-t-m-t-+-----[0m


       [40mIn  nested  if statements, the [1melse [22mwill bind to the closest[0m
       [4m[40melse[24m-less [4mif[24m.  An expression is false if and only if all  of[0m
       [40mits words are null or it has no words.[0m

       [40mNote  that  one or both of the subordinate statements may be[0m
       [40mcompound statements, should you need to say  something  more[0m
       [40mcomplex than a single statement.[0m

       [4m[40m7.3.15[24m  [4mThe[24m [4mLoop[24m [4mand[24m [4mLoopend[24m [4mStatements[0m
       [40mLooping is provided for in [1mcook [22mby the generic infinite loop[0m
       [40mconstruct defined below.[0m


       
       Peter Miller                                         Page 62





       Cook                                              User Guide



       [40mstmt                        ------+----+[0m
       [40m-----------------------------l-o-o-p--+-s-t-m-t+-----------------------[0m

       [40mA facility is provided to break out of a loop at any point.[0m
       [40mstmt                        ----------------[0m
       [40m----------------------------l-o-o-p-s-t-o-p---;-------------------------[0m

       [40mThe statement  following  the  [1mloop  [22mdirective  is  executed[0m
       [40mrepeatedly   forever.    The   [1mloopstop  [22mstatement  is  only[0m
       [40msemantically valid within the scope of a [1mloop [22mstatement.[0m

       [40mHere is an example of how to use the loop statement:[0m
            [40mdirs = a b c d;[0m
            [40msrc = ;[0m

            [40mtmp = [dirs];[0m
            [40mloop[0m
            [40m{[0m
                    [40mtmp_dir = [head [tmp]];[0m
                    [40mif [not [tmp_dir]] then[0m
                            [40mloopstop;[0m
                    [40mtmp = [tail [tmp]];[0m
                    [40msrc = [src] [glob [tmp_dir]"/*.c"];[0m
            [40m}[0m

       [40mThere is also a ``for each'' loop variant, allowing  a  more[0m
       [40mterse expression of exactly the same thing[0m
            [40mdirs = a b c d;[0m
            [40msrc = ;[0m

            [40mloop tmp_dir = [dirs][0m
            [40m{[0m
                    [40msrc = [src] [glob [tmp_dir]"/*.c"];[0m
            [40m}[0m
       [40mYou can use loopstop within such a loop.  Note that the loop[0m
       [40mbody [4mmust[24m be a compound statement.[0m

       [4m[40m7.3.16[24m  [4mFunctions[0m
       [40mIt is possible to define your own functions.[0m

       [4m[40m7.3.16.1[24m  [4mFunction[24m [4mDefinition[0m
       [40mUser-defined functions are specified using something similar[0m
       [40mto an assignment.[0m
       [40mfunction           ----------------   ----+-----+[0m
       [40m-------------------f-u-n-c-t-i-o-n-----[4mw[24m-[4mo[24m-[4mr[24m-[4md[24m-----=---+c-s-t-m-t-+--------------[0m

       [40mFunctions must be defined before they are used.[0m

       [40mYou  need  to  make  sure  you  do not re-define a built-in-[0m
       [40mfunction as this may have dire consequences.[0m

       [4m[40m7.3.16.2[24m  [4mThe[24m [4mReturn[24m [4mStatement[0m
       [40mYou return values  from  a  function  by  using  the  return[0m
       [40mstatement:[0m

       
       Peter Miller                                         Page 63





       Cook                                              User Guide



       [40mstmt                     -------+-----+  ------[0m
       [40m-------------------------r-e-t-u-r-n--+e-x-p-r-s-+--;----------------------[0m

       [40mNote  that  return  statements  are not meaningful outside a[0m
       [40mfunction definition.[0m

       [4m[40m7.3.16.3[24m  [4mFunction[24m [4mArguments[0m
       [40mThe arguments to the function  are  passed  in  the  ``arg''[0m
       [40mvariable.   Each  argument is also separately defined in the[0m
       [40m``@1'' to ``@9'' variables for direct access.  (If there are[0m
       [40mmore  than  9,  you  will need to use ``[word [4mn[24m [arg]]'' for[0m
       [40margument 10 and later).  These variables are unique for each[0m
       [40mfunction invocation, even if they are nested.[0m

       [40mYou  can  use  the  ``@1''  to  ``@9''  variables  as  local[0m
       [40mvariables if you have no need of their values.[0m

       [40mAll of these special names are  thread  safe  and  recursion[0m
       [40msafe.   Every  function  invocation  receives its own set of[0m
       [40mthem.[0m

       [4m[40m7.3.16.4[24m  [4mExample[0m
       [40mAn example of a  function  definition  is  a  ``capitalize''[0m
       [40mfunction:[0m
            [40mfunction capitalize =[0m
            [40m{[0m
                    [40m@1 = ;[0m
                    [40mloop @2 = [downcase [arg]][0m
                    [40m{[0m
                            [40m@1 += [upcase [substr 1 1 [@2]]][substr 2 99 [@2]];[0m
                    [40m}[0m
                    [40mreturn [@1];[0m
            [40m}[0m
       [40mThis  function  capitalizes  the first letter of each of its[0m
       [40marguments.[0m

       [40mUser-defined functions are invoked in the same way a  built-[0m
       [40min functions.[0m
            [40mhost = [os node];[0m
            [40mHost = [capitalize [host]];[0m

       [40mSee the ``Function Library'' section for additional function[0m
       [40mexamples which are distributed with Cook.[0m

       [4m[40m7.3.16.5[24m  [4mFunction[24m [4mCall[24m [4mStatement[0m
       [40mUser defined functions may be invoked in  the  same  way  as[0m
       [40mbuilt-in functions, but they may also be invoked in the same[0m
       [40mway as commands, providing a form of subroutine.[0m
       [40mstmt                 ----------+-----+  ------[0m
       [40m-------------------- -f-u-n-c-t-i-o-n -+e-l-i-s-t-+--;-----------------------[0m


       [40mIf the function return value is not zero, it  is  considered[0m
       [40mto fail, just as a command would fail.  The commonest use of[0m

       
       Peter Miller                                         Page 64





       Cook                                              User Guide



       [40mthis is to invoke the built-in print function for  debugging[0m
       [40mcookbooks.[0m
            [40mfunction print [__FILE__] [__LINE__] hello [getenv USER];[0m

       [40mThese function calls may be used in recipe bodies, or in the[0m
       [40mgeneral cookbook.[0m

       [4m[40m7.3.16.6[24m  [4mLocal[24m [4mVariables[0m
       [40mFunctions can have local variables simply by using the  word[0m
       [40mlocal  on  the left-hand-side of the assignment.  Care needs[0m
       [40mto be taken with the loop statement and the  +=  assignment,[0m
       [40mas  the variable needs to be established as a local variable[0m
       [4m[40mfirst[24m.[0m
            [40mfunction capitalize =[0m
            [40m{[0m
                    [40mlocal result = ;[0m
                    [40mlocal tmp = ;[0m
                    [40mloop tmp = [downcase [arg]][0m
                    [40m{[0m
                            [40mresult += [upcase [substr 1 1 [tmp]]][substr 2 99 [tmp]];[0m
                    [40m}[0m
                    [40mreturn [result];[0m
            [40m}[0m
       [40mFunctions may have as many local variables as they like.[0m

       [40mLocal variables are  reentrant.   You  can  write  recursive[0m
       [40mfunctions,  and  each  invocation  of  the  function  has an[0m
       [40mindependent set of local variables.[0m

       [40mLocal variables are thread-safe.  You can use the same user-[0m
       [40mdefined  function  in  two parallel threads, and their local[0m
       [40mvariables are completely independent.[0m

       [40mThe ``arg'' and ``@1'' to ``@9''  variables  are  implicitly[0m
       [40mlocal.[0m




















       
       Peter Miller                                         Page 65





       Cook                                              User Guide



       [40m[4m8.[24m  [4mBuilt-In[24m [4mFunctions[0m

       [40mThis chapter defines each of the built-in functions of [4mcook[24m.[0m

       [40mA built-in function is invoked by using an expression of the[0m
       [40mform[0m
            [1m[40m[[4m[22mfunc-name[24m [4marg[24m [4marg[24m ...[1m][0m
       [40min most places where a literal word is valid.[0m

       [4m[40m8.1[24m  [4maddprefix[0m

       [40mThe [4maddprefix[24m function is used to add a prefix to a list  or[0m
       [40mwords.   This  function requires at least one argument.  The[0m
       [40mfirst argument is a prefix to be added  to  the  second  and[0m
       [40msubsequent arguments.[0m

       [4m[40m8.1.1[24m  [4mSee[24m [4mAlso[0m
       [40maddsuffix, patsubst, prepost, subst[0m

       [4m[40m8.2[24m  [4maddsuffix[0m

       [40mThe  [4maddsuffix[24m function is used to add a suffix to a list or[0m
       [40mwords.  This function requires at least one  argument.   The[0m
       [40mfirst  argument  is  a  suffix to be added to the second and[0m
       [40msubsequent arguments.[0m

       [4m[40m8.2.1[24m  [4mSee[24m [4mAlso[0m
       [40maddprefix, patsubst, prepost, subst[0m

       [4m[40m8.3[24m  [4mand[0m

       [40mThis function requires at least two arguments, upon which it[0m
       [40mforms  a  logical  conjunction.   The  value returned is "1"[0m
       [40m(true) if none of the arguments are "" (false), otherwise ""[0m
       [40m(false) is returned.[0m

       [4m[40m8.3.1[24m  [4mExample[0m
       [40mThe  following  cookbook fragment shows how to use the [and][0m
       [40mfunction in conditional recipes.[0m
            [40m#if [and [defined change] [defined baseline]][0m
            [4m[40m...do[24m [4msomething...[0m
            [40m#endif[0m
       [40mThis fragment will only [4mdo[24m [4msomething[24m if both the [4mchange[24m  and[0m
       [4m[40mbaseline[24m variables are defined.[0m

       [4m[40m8.3.2[24m  [4mCaveat[0m
       [40mThis  function  is  rather  clumsy, and probably needs to be[0m
       [40mreplaced by a  better  syntax  within  the  cokbook  grammar[0m
       [40mitself.[0m

       [40mThis function does not short-circuit evaluation.[0m




       
       Peter Miller                                         Page 66





       Cook                                              User Guide



       [40m[4m8.3.3[24m  [4mSee[24m [4mAlso[0m
       [40mor, not[0m

       [4m[40m8.4[24m  [4mbasename[0m

       [40mThe [4mbasename[24m treats each argument as filenames, and extracts[0m
       [40mall but the  suffix  of  each  filename.   If  the  filename[0m
       [40mcontains a period, the basename is everything up to (but not[0m
       [40mincluding) the  period.   Otherwise,  the  basename  is  the[0m
       [40mentire filename.[0m

       [40mPlease  note:  this  is  not  the  same behavior as the Unix[0m
       [4m[40mbasename[24m(1) utility.  For this, [basename [notdir [4margs[24m]]  or[0m
       [40m[fromto %0%.c %0% [4margs[24m] may be more appropriate.[0m

       [4m[40m8.4.1[24m  [4mExample[0m

                   [40mExpression               Result[0m
                   [40m-------------------------------------[0m
                   [40m[basename foo.c]         foo[0m
                   [40m[basename foo/bar.c]     foo/bar[0m
                   [40m[basename baz]           baz[0m
                   [40m[basename foo/bar/baz]   foo/bar/baz[0m

       [4m[40m8.4.2[24m  [4mSee[24m [4mAlso[0m
       [40maddsuffix, dirname, entryname, fromto, notdir, suffix[0m

       [4m[40m8.4.3[24m  [4mCaveat[0m
       [40mThis function is almost nothing like the Unix command of the[0m
       [40msame name.  It operates in  this  manner  for  compatibility[0m
       [40mwith other packages.[0m

       [4m[40m8.5[24m  [4mcando[0m

       [40mThis function is used to test whether Cook knows how to cook[0m
       [40mthe given targets.  It returns  all  of  the  arguments  for[0m
       [40mwhich derivations can be found, or nothing if none can.[0m

       [4m[40m8.5.1[24m  [4mCaveat[0m
       [40mThis will use as much of the cookbook as has been read in up[0m
       [40mto the point where this function is  used.   This  can  mean[0m
       [40mthat crucial recipes have yet to be parsed and instantiated.[0m

       [4m[40m8.5.2[24m  [4mSee[24m [4mAlso[0m
       [40mcook, uptodate[0m










       
       Peter Miller                                         Page 67





       Cook                                              User Guide



       [40m[4m8.6[24m  [4mcatenate[0m

       [40mThis  function  requires  zero  or  more  arguments.   If no[0m
       [40marguments are supplied, the result is an  empty  word  list.[0m
       [40mIf  one or more arguments are supplied, the result is a word[0m
       [40mlist of  one  word  being  the  catenation  of  all  of  the[0m
       [40marguments.[0m

       [4m[40m8.6.1[24m  [4mExample[0m

                    [40mExpression      Result[0m
                    [40m----------------------------------[0m
                    [40m[catenate a]    a[0m
                    [40m[catenate a b]  ab[0m
                    [40m[catenate a " " b]      "a b"[0m
       [40mQuotes used in the results for clarity.[0m

       [4m[40m8.6.2[24m  [4mSee[24m [4mAlso[0m
       [40msplit, unsplit, prepost, join[0m

       [4m[40m8.7[24m  [4mcollect_lines[0m

       [40mThe  arguments  are interpreted as a command to be passed to[0m
       [40mthe operating system.  The result is  one  "word"  for  each[0m
       [40mline of the output of the command.[0m

       [4m[40m8.7.1[24m  [4mExample[0m
       [40mTo read each line of a file into a variable:[0m
            [40mfiles = [collect_lines cat file];[0m
       [40mSpaces  and tabs in the input lines will be preserved in the[0m
       [40m"words" of the result.[0m

       [4m[40m8.7.2[24m  [4mSee[24m [4mAlso[0m
       [40mcollect, execute, glob, read, read_lines, write[0m

       [4m[40m8.7.3[24m  [4mCaveat[0m
       [40mYou will probably get better performance using the #include-[0m
       [40mcooked directive, and a recipe to create the included file.[0m

















       
       Peter Miller                                         Page 68





       Cook                                              User Guide



       [40m[4m8.8[24m  [4mcollect[0m

       [40mThe  arguments  are interpreted as a command to be passed to[0m
       [40mthe operating system.  The  result  is  one  word  for  each[0m
       [40mwhite-space separated word of the output of the command.[0m

       [40mThe  command will not be echoed unless the -No_Silent option[0m
       [40mis specified on the command line.[0m

       [4m[40m8.8.1[24m  [4mExample[0m
       [40mRead the date and time and assign it to a variable:[0m
            [40mnow = [collect date];[0m
       [40mDo not  use  the  collect  function  to  expand  a  filename[0m
       [40mwildcard, used the [glob] function instead.[0m

       [4m[40m8.8.2[24m  [4mSee[24m [4mAlso[0m
       [40mcollect_lines, execute, glob, read, read_lines, write[0m

       [4m[40m8.8.3[24m  [4mAlso[24m [4mKnown[24m [4mAs[0m
       [40mshell[0m

       [4m[40m8.9[24m  [4mcook[0m

       [40mThis  function  requires one or more arguments, filenames to[0m
       [40mbe tested to see if they are up-to-date, and be brought  up-[0m
       [40mto-date  if  they are not.  The result are true ("1") if the[0m
       [40mfiles are (now) up-to-date, or false ("") if they could  not[0m
       [40mbe built.[0m

       [4m[40m8.9.1[24m  [4mCaveat[0m
       [40mThis will use as much of the cookbook as has been read in up[0m
       [40mto the point where this function is  used.   This  can  mean[0m
       [40mthat crucial recipes have yet to be parsed and instantiated.[0m

       [40mThis  function works one argument at a time.  This is slower[0m
       [40mthan the  main  cookbook,  which  will  pursue  all  targets[0m
       [40msimultaneously.[0m

       [4m[40m8.9.2[24m  [4mSee[24m [4mAlso[0m
       [40mcando, uptodate[0m















       
       Peter Miller                                         Page 69





       Cook                                              User Guide



       [40m[4m8.10[24m  [4mcount[0m

       [40mThis  function  requires zero or more arguments.  The result[0m
       [40mis a word list of one word containing the  (decimal)  length[0m
       [40mof the argument word list.[0m

       [4m[40m8.10.1[24m  [4mExample[0m
       [40mThis  cookbook fragment echoes the number of files, and then[0m
       [40mthe name of the last file:[0m
            [40mecho There are [count [files]] files.;[0m
            [40mecho The last file is [word [count [files]] [files]].;[0m

       [4m[40m8.10.2[24m  [4mSee[24m [4mAlso[0m
       [40mhead, tail, word[0m

       [4m[40m8.10.3[24m  [4mAlso[24m [4mKnown[24m [4mAs[0m
       [40mwords[0m

       [4m[40m8.11[24m  [4mdefined[0m

       [40mThis function requires a single  argument,  the  name  of  a[0m
       [40mvariable  to be tested for existence.  It returns "1" (true)[0m
       [40mif the named variable is defined and ""  (false)  if  it  is[0m
       [40mnot.[0m

       [4m[40m8.11.1[24m  [4mExample[0m
       [40mThis  function is most often seen in conditional portions of[0m
       [40mcookbooks:[0m
            [40mif [defined baseline] then[0m
                    [40mcc_flags = [cc_flags] -I[baseline];[0m

       [4m[40m8.12[24m  [4mdirname[0m

       [40mThis function requires one or more arguments, the  names  of[0m
       [40mfiles which will have their directory parts extracted.[0m

       [4m[40m8.12.1[24m  [4mExample[0m

                        [40mExpression      Result[0m
                        [40m---------------------------[0m
                        [40m[dirname a]     [4m`pwd`[0m
                        [40m[dirname a/b]   a[0m
                        [40m[dirname a/b/c] a/b[0m
       [40mWhen  the answer would be ``.'' (the current directory), the[0m
       [40mresult  is  instead  the  absolute  path  of   the   current[0m
       [40mdirectory.   This  allows repeated [dirname] applications to[0m
       [40mclimb the directory tree, no matter where  you  start.   See[0m
       [4m[40mrelative_dirname[24m for one which returns ``.'' instead.[0m

       [4m[40m8.12.2[24m  [4mSee[24m [4mAlso[0m
       [40mbasename,  entryname,  notdir,  pathname,  relative_dirname,[0m
       [40msuffix[0m



       
       Peter Miller                                         Page 70





       Cook                                              User Guide



       [40m[4m8.12.3[24m  [4mAlso[24m [4mKnown[24m [4mAs[0m
       [40mdir[0m

       [4m[40m8.13[24m  [4mdir[0m

       [40mThis function requires one or more arguments, the  names  of[0m
       [40mfiles which will have their directory parts extracted.[0m

       [4m[40m8.13.1[24m  [4mExample[0m

                        [40mExpression      Result[0m
                        [40m---------------------------[0m
                        [40m[dir a] .[0m
                        [40m[dir a/b]       a[0m
                        [40m[dir a/b/c]     a/b[0m

       [4m[40m8.13.2[24m  [4mSee[24m [4mAlso[0m
       [40mbasename,  entryname,  notdir,  pathname,  relative_dirname,[0m
       [40msuffix[0m

       [4m[40m8.13.3[24m  [4mAlso[24m [4mKnown[24m [4mAs[0m
       [40mdirname[0m

       [4m[40m8.14[24m  [4mdos-path[0m

       [40mThis function requires one or more arguments, which will  be[0m
       [40mconverted from a UNIX path into a DOS path.  This is of most[0m
       [40muse under Windows-NT, to convert Cook's  internal  pathnames[0m
       [40minto  DOS  pathnames.  (The UNIX porting layer usually hides[0m
       [40mthis from Cook.)[0m

       [4m[40m8.14.1[24m  [4mExample[0m

                [40mExpression                  Result[0m
                [40m-------------------------------------------[0m
                [40m[dos-path a/b/c]            a\b\c[0m
                [40m[dos-path //c/temp]         c:\temp[0m
                [40m[dos-path //server/stuff]   \\server\stuff[0m

       [4m[40m8.14.2[24m  [4mSee[24m [4mAlso[0m
       [40mun-dos-path[0m














       
       Peter Miller                                         Page 71





       Cook                                              User Guide



       [40m[4m8.15[24m  [4mdowncase[0m

       [40mThis function requires one or more arguments,  words  to  be[0m
       [40mforced into lower case.[0m

       [4m[40m8.15.1[24m  [4mExample[0m

                        [40mExpression      Result[0m
                        [40m---------------------------[0m
                        [40m[downcase FOO]  foo[0m
                        [40m[downcase Bar]  bar[0m
                        [40m[downcase baz]  baz[0m

       [4m[40m8.15.2[24m  [4mSee[24m [4mAlso[0m
       [40mupcase[0m

       [4m[40m8.16[24m  [4mentryname[0m

       [40mThis  function  requires one or more arguments, the names of[0m
       [40mfiles which will have their entry name parts extracted.[0m

       [4m[40m8.16.1[24m  [4mExample[0m

                    [40mExpression      Result[0m
                    [40m----------------------------------[0m
                    [40m[entryname foo.c]       foo.c[0m
                    [40m[entryname foo/bar.c]   bar.c[0m
                    [40m[entryname baz] baz[0m

       [4m[40m8.16.2[24m  [4mSee[24m [4mAlso[0m
       [40mbasename, dir, suffix[0m

       [4m[40m8.16.3[24m  [4mAlso[24m [4mKnown[24m [4mAs[0m
       [40mnotdir[0m

       [4m[40m8.17[24m  [4mexecute[0m

       [40mThis function requires at least one argument,  and  executes[0m
       [40mthe command given by the arguments.  If the executed command[0m
       [40mreturns non-zero exit  status  the  resulting  value  is  ""[0m
       [40m(false), otherwise it is "1" (true).[0m

       [40mThe  command will not be echoed unless the -No_Silent option[0m
       [40mis specified on the command line.[0m

       [4m[40m8.17.1[24m  [4mCaveat[0m
       [40mThis function is not often required as its functionality  is[0m
       [40mavailable in a more useful form as recipe bodies.[0m

       [4m[40m8.17.2[24m  [4mExample[0m
       [40mTo  get  access  to  a  wide  range of Unix command, such as[0m
       [4m[40mtest[24m(1), you can use this function in conditionals[0m
            [40mif [not [test -d fubar]] then[0m
            [40m{[0m

       
       Peter Miller                                         Page 72





       Cook                                              User Guide



       [40m             rm -f fubar;[0m
                    [40mmkdir fubar;[0m
            [40m}[0m

       [4m[40m8.17.3[24m  [4mSee[24m [4mAlso[0m
       [40mcollect[0m

       [4m[40m8.18[24m  [4mexists[0m

       [40mThis function requires one argument, being  the  name  of  a[0m
       [40mfile  to  test for existence.  The resulting word list is ""[0m
       [40m(false) if the file does not exist, and "1"  (true)  if  the[0m
       [40mfile does exist.[0m

       [4m[40m8.18.1[24m  [4mExample[0m
       [40mTo remove the target of a recipe before building it again:[0m
            [40m%.a: [%_obj][0m
            [40m{[0m
                    [40mif [exists [target]] then[0m
                            [40mrm [target][0m
                                    [40mset clearstat;[0m
                    [40m[ar] qc [target] [%_obj];[0m
            [40m}[0m
       [40mNote:  you  [4mmust[24m use the clearstat, because otherwise cook's[0m
       [40m"stat cache" will be incorrect.[0m

       [40mThis is only an example.   It  is  better  to  perform  this[0m
       [40mparticular  activity  using  the  ``unlink''  flag.  See the[0m
       [40m[find_command] function, below, for an example.[0m

       [4m[40m8.18.2[24m  [4mSee[24m [4mAlso[0m
       [40mcando, find_command, uptodate[0m

       [4m[40m8.19[24m  [4mexists-symlink[0m

       [40mThis function requires one argument, being  the  name  of  a[0m
       [40mfile  to  test  for  existence.   The  test  will [4mnot[24m follow[0m
       [40msymbolic links, so it may be used to test for the  existence[0m
       [40mof symbolic links themselves.  The resulting word list is ""[0m
       [40m(false) if the file does not exist, and "1"  (true)  if  the[0m
       [40mfile does exist.[0m

       [4m[40m8.19.1[24m  [4mSee[24m [4mAlso[0m
       [40mexists, readlink[0m











       
       Peter Miller                                         Page 73





       Cook                                              User Guide



       [40m[4m8.20[24m  [4mexpr[0m

       [40mThis  function  may  be  used  to  calculate  simple integer[0m
       [40marithmetic expressions.  The numbers and the  operators  are[0m
       [40mexpected  to  each  be a separate argument.  The result is a[0m
       [40mstring containing the value of the evaluated expression.[0m

       [4m[40m8.20.1[24m  [4mOperators[0m
       [40mThe following operators are understood.  They have the  same[0m
       [40mprecedence as the equivalent C operators.[0m

                        [40mOperator    Associativity[0m
                        [40m--------------------------[0m
                        [40m( )              ->[0m
                        [40m! ~ -            <-[0m
                        [40m* / %            ->[0m
                        [40m+ -              ->[0m
                        [40m<< >>            ->[0m
                        [40m< <= > >=        ->[0m
                        [40m== !=            ->[0m
                        [40m&                ->[0m
                        [40m^                ->[0m
                        [40m|                ->[0m
                        [40m&&               ->[0m
                        [40m||               ->[0m
                        [40m?:               <-[0m
       [40mPlease note that there is no short-circuit evaluation of the[0m
       [40m?: or && or || operators.[0m

       [40mYou may need to quote some of  the  operators,  to  insulate[0m
       [40mthem  from their usual Cook interpretation (colon and equals[0m
       [40mcharacters in particular).[0m

       [40mNumbers may be given in decimal, octal (with a 0 prefix), or[0m
       [40mhexadecimal  (with  a  0x  prefix).   The  result  is always[0m
       [40mdecimal.[0m

       [4m[40m8.20.2[24m  [4mSee[24m [4mAlso[0m
       [40mcount[0m
















       
       Peter Miller                                         Page 74





       Cook                                              User Guide



       [40m[4m8.21[24m  [4mfilter_out[0m

       [40mThis function requires one or  more  arguments.   The  first[0m
       [40margument  is  a  pattern, the second and later arguments are[0m
       [40mstrings  to  match  against  this  pattern.   The  resulting[0m
       [40mwordlist  contains  those  arguments which did not match the[0m
       [40mpattern given as the first argument.[0m

       [4m[40m8.21.1[24m  [4mExample[0m

                   [40mExpression                  Result[0m
                   [40m------------------------------------[0m
                   [40m[filter_out %.c a.c a.o]    a.o[0m
                   [40m[filter_out %.cc a.c a.o]   a.c a.o[0m

       [4m[40m8.21.2[24m  [4mMatch[24m [4mMode[0m
       [40mThis function is affected by the selected match  mode.   See[0m
       [40mthe [4mFile[24m [4mName[24m [4mPatterns[24m chapter for details.[0m

       [4m[40m8.21.3[24m  [4mSee[24m [4mAlso[0m
       [40mfilter, stringset[0m

       [4m[40m8.22[24m  [4mfilter[0m

       [40mThis  function  requires  one  or more arguments.  The first[0m
       [40margument is a pattern, the second and  later  arguments  are[0m
       [40mstrings  to  match  against  this  pattern.   The  resulting[0m
       [40mwordlist contains those arguments which matched the  pattern[0m
       [40mgiven as the first argument.[0m

       [4m[40m8.22.1[24m  [4mExample[0m

                      [40mExpression              Result[0m
                      [40m-------------------------------[0m
                      [40m[filter %.c a.c a.o]    a.c[0m
                      [40m[filter %.cc a.c a.o][0m

       [4m[40m8.22.2[24m  [4mMatch[24m [4mMode[0m
       [40mThis  function  is affected by the selected match mode.  See[0m
       [40mthe [4mFile[24m [4mName[24m [4mPatterns[24m chapter for details.[0m

       [4m[40m8.22.3[24m  [4mSee[24m [4mAlso[0m
       [40mfilter_out, stringset[0m

       [4m[40m8.22.4[24m  [4mAlso[24m [4mKnown[24m [4mAs[0m
       [40mmatch_mask[0m









       
       Peter Miller                                         Page 75





       Cook                                              User Guide



       [40m[4m8.23[24m  [4mfind_command[0m

       [40mThis function requires at  least  one  argument,  being  the[0m
       [40mnames  of  commands  to  search for in $PATH.  The resulting[0m
       [40mword list contains either "" (false) or  a  fully  qualified[0m
       [40mpath name for each command given.[0m

       [4m[40m8.23.1[24m  [4mExample[0m
       [40mSome  systems  require  [4mranlib[24m(1) to be run on archives, and[0m
       [40msome do not.  Here is a simple way to test:[0m
            [40mranlib = [find_command ranlib];[0m

            [40m%.a: [%_obj][0m
                    [40mset unlink[0m
            [40m{[0m
                    [40mar qc [target] [%_obj];[0m
                    [40mif [ranlib] then[0m
                            [40m[ranlib] [target];[0m
            [40m}[0m

       [4m[40m8.23.2[24m  [4mSee[24m [4mAlso[0m
       [40mcando, exists, uptodate[0m

       [4m[40m8.24[24m  [4mfindstring[0m

       [40mThe findstring function is used  to  match  a  fixed  string[0m
       [40magainst  a set of strings.  This function takes at least one[0m
       [40margument.  The first  argument  is  the  fixed  string,  the[0m
       [40msecond  and  subsequent  arguments  are  matched against the[0m
       [40mfirst.  The result contains one word for each of the  second[0m
       [40mand  subsequent  arguments,  each  will  either be the empty[0m
       [40mstring (false) or the string to be matched, if a  match  was[0m
       [40mfound.[0m

       [4m[40m8.24.1[24m  [4mExample[0m

                      [40mExpression             Result[0m
                      [40m-------------------------------[0m
                      [40m[findstring a a b c]   a "" ""[0m
                      [40m[findstring a b c]     "" ""[0m
       [40mQuotes  are  for  clarity,  to  emphasize the empty strings.[0m
       [40mBecause the empty string is "false", this can be used in  an[0m
       [4m[40mif[24m statement:[0m
            [40mif [findstring fish [sources]] then[0m
                    [40msources = [sources] hook.c;[0m

       [4m[40m8.24.2[24m  [4mSee[24m [4mAlso[0m
       [40mfilter-out, match, match_mask, patsubst, stringset, subst[0m







       
       Peter Miller                                         Page 76





       Cook                                              User Guide



       [40m[4m8.25[24m  [4mfirstword[0m

       [40mThis function requires zero or more arguments.  The wordlist[0m
       [40mreturned is empty if there were no arguments, or  the  first[0m
       [40margument if there were arguments.[0m

       [4m[40m8.25.1[24m  [4mExample[0m
       [40mYou  can  iterate  along  a  list  using  the [4mloop[24m statement[0m
       [40mcombined with the [4mfirstword[24m and [4mtail[24m functions:[0m
            [40mdirs = a b c d;[0m
            [40msrc = ;[0m

            [40mtmp = [dirs];[0m
            [40mloop[0m
            [40m{[0m
                    [40mtmp_dir = [firstword [tmp]];[0m
                    [40mif [not [tmp_dir]] then[0m
                            [40mloopstop;[0m
                    [40mtmp = [tail [tmp]];[0m
                    [40msrc = [src] [glob [tmp_dir]"/*.c"];[0m
            [40m}[0m
       [40mMore efficient ways exist to do this, this an example only.[0m

       [4m[40m8.25.2[24m  [4mSee[24m [4mAlso[0m
       [40mcount, glob, fromto, prepost, tail, word[0m

       [4m[40m8.25.3[24m  [4mAlso[24m [4mKnown[24m [4mAs[0m
       [40mhead[0m

       [4m[40m8.26[24m  [4mfromto[0m

       [40mThis function requires at least two arguments.  Fromto gives[0m
       [40mthe  user access to the pattern transformations available to[0m
       [1m[40mcook[22m.  The first argument is the  "from"  form,  the  second[0m
       [40margument  is  the "to" form.  All other arguments are mapped[0m
       [40mfrom one to the other.[0m

       [4m[40m8.26.1[24m  [4mExample[0m
       [40mGiven a list of C source files, generate a  list  of  object[0m
       [40mfiles as follows:[0m
            [40mobj = [fromto %.c %.o [src]];[0m

       [4m[40m8.26.2[24m  [4mSee[24m [4mAlso[0m
       [40mfilter, filter_out, subst[0m

       [40mSee  the pattern matching chapter for more information about[0m
       [40mpatterns.[0m

       [4m[40m8.26.3[24m  [4mMatch[24m [4mMode[0m
       [40mThis function is affected by the selected match  mode.   See[0m
       [40mthe [4mFile[24m [4mName[24m [4mPatterns[24m chapter for details.[0m




       
       Peter Miller                                         Page 77





       Cook                                              User Guide



       [40m[4m8.26.4[24m  [4mAlso[24m [4mKnown[24m [4mAs[0m
       [40mpatsubst[0m

       [4m[40m8.27[24m  [4mgetenv[0m

       [40mEach  argument  is  treated  as  the  name of an environment[0m
       [40mvariable.   The  result  is  the  value  of  each   argument[0m
       [40mvariable,  or  ""  if  it  does  not  exist (consistent with[0m
       [40mcommand shell behaviour).[0m

       [4m[40m8.27.1[24m  [4mExample[0m
       [40mTo read the value of the TERM environment variable:[0m
            [40mterm = [getenv TERM];[0m

       [40mValues of variables  are  not  automagically  set  from  the[0m
       [40menvironment, you must set each one explicitly:[0m
            [40mcc = [getenv CC];[0m
            [40mif [not [cc]] then[0m
                    [40mcc = gcc;[0m

       [4m[40m8.27.2[24m  [4mSee[24m [4mAlso[0m
       [40mfind_command, home[0m

       [4m[40m8.28[24m  [4mglob[0m

       [40mEach  argument  is treated as a [4msh[24m(1) file name pattern, and[0m
       [40mexpanded accordingly.  The resulting list  of  filenames  is[0m
       [40msorted lexicographically.[0m

       [40mYou  may  need  to  quote  the  pattern,  to  protect square[0m
       [40mbrackets from the meaning cook attaches to them.[0m

       [1m[40mNote: [22mThe character sequence /* is a comment introducer, and[0m
       [40mis a frequent source of problems when combined with the [4mglob[0m
       [40mfunction.  Remember to quote [4mglob[24m arguments which need  this[0m
       [40mcharacter  sequence.  See the [head] function, below, for an[0m
       [40mexample of this.[0m

       [4m[40m8.28.1[24m  [4mExample[0m
       [40mTo find the sources in the current directory:[0m
            [40msrc = [glob *.c];[0m
            [40mobj = [fromto %.c %.o [src]];[0m

       [4m[40m8.28.2[24m  [4mSee[24m [4mAlso[0m
       [40mfilter, filter_out, shell[0m

       [4m[40m8.28.3[24m  [4mAlso[24m [4mKnown[24m [4mAs[0m
       [40mwildcard[0m







       
       Peter Miller                                         Page 78





       Cook                                              User Guide



       [40m[4m8.29[24m  [4mhead[0m

       [40mThis function requires zero or more arguments.  The wordlist[0m
       [40mreturned  is  empty if there were no arguments, or the first[0m
       [40margument if there were arguments.[0m

       [4m[40m8.29.1[24m  [4mExample[0m
       [40mYou can iterate  along  a  list  using  the  [4mloop[24m  statement[0m
       [40mcombined with the [4mhead[24m and [4mtail[24m functions:[0m
            [40mdirs = a b c d;[0m
            [40msrc = ;[0m

            [40mtmp = [dirs];[0m
            [40mloop[0m
            [40m{[0m
                    [40mtmp_dir = [head [tmp]];[0m
                    [40mif [not [tmp_dir]] then[0m
                            [40mloopstop;[0m
                    [40mtmp = [tail [tmp]];[0m
                    [40msrc = [src] [glob [tmp_dir]"/*.c"];[0m
            [40m}[0m
       [40mMore efficient ways exist to do this, this an example only.[0m

       [4m[40m8.29.2[24m  [4mSee[24m [4mAlso[0m
       [40mcount, glob, fromto, prepost, tail, word[0m

       [4m[40m8.29.3[24m  [4mAlso[24m [4mKnown[24m [4mAs[0m
       [40mfirstword[0m

       [4m[40m8.30[24m  [4mhome[0m

       [40mThe  [4mhome[24m function is used to find the home directory of the[0m
       [40mnamed users.  You may name more than one user.  If no  users[0m
       [40mare  named,  it  returns  the  home directory of the current[0m
       [40muser.[0m

       [4m[40m8.31[24m  [4mif[0m

       [40mThis function requires one or more arguments, the  arguments[0m
       [40mbefore  the  "then"  word  are  used as a condition.  If the[0m
       [40mcondition is true the words between the "then" word and  the[0m
       [40m"else"  word  are  the result, otherwise the words after the[0m
       [40m"else" word are the value.  The "else" clause  is  optional.[0m
       [40mThere is no way to escape the "then" and "else" words.[0m

       [4m[40m8.31.1[24m  [4mExample[0m
       [40mHere is an example of the ``if'' function.  Please note that[0m
       [40m``if'', ``then'' and ``else'' are  reserved  words,  so  you[0m
       [40mneed  to  quote  them  before they will be recognised on the[0m
       [40mfunction context.[0m
            [40m%: %_obj[0m
                    [40mset ["if" [defined all_shallow] "then" shallow][0m
            [40m{[0m
                    [40m[cc] -o [target] [%_obj];[0m

       
       Peter Miller                                         Page 79





       Cook                                              User Guide



       [40m     }[0m

       [4m[40m8.31.2[24m  [4mCaveat[0m
       [40mIt is often clearer  to  use  the  [4mif[24m  [4mstatement[24m  than  this[0m
       [40mfunction.[0m

       [40mThe  recipe  flags  are  evaluated  at  the same time as the[0m
       [40mrecipe targets.  None of the  [target],  [targets],  [need],[0m
       [40m[younger]  variables or pattern matches (%, %1, [4metc[24m) are set[0m
       [40mat this time.[0m

       [4m[40m8.32[24m  [4min[0m

       [40mThis function requires one or more arguments.  The  wordlist[0m
       [40mreturned is a single word: the index of the matching word (1[0m
       [40mbased) if the first argument is equal to any  of  the  later[0m
       [40mones; or "" (false) if not.[0m

       [40mThis  function  can  also be used for equality testing, just[0m
       [40muse a single element in the set.[0m

       [40mBecause it returns the index, the return valus can  be  used[0m
       [40mwith the [4m[word][24m or [4m[words][24m functions.[0m

       [4m[40m8.32.1[24m  [4mExample[0m
       [40mFrequently seen in conditional parts of recipes:[0m
            [40m%: [%_obj][0m
            [40m{[0m
                    [40m[cc] -o [target] [%_obj];[0m
                    [40mif [in [target] [private]] then[0m
                            [40mchmod og-rwx [target];[0m
            [40m}[0m

       [4m[40m8.32.2[24m  [4mSee[24m [4mAlso[0m
       [40mstringset, word, words[0m

       [4m[40m8.33[24m  [4minterior_files[0m

       [40mThis  function  requires  zero arguments.  The result is the[0m
       [40mlist of files which are interior to  the  dependency  graph.[0m
       [40m(Files which are constructed by a recipe.)  This function is[0m
       [40monly meaningful within a recipe body.[0m

       [4m[40m8.33.1[24m  [4mSee[24m [4mAlso[0m
       [40mleaf_files    function,    graph_interior_file     variable,[0m
       [40mgraph_interior_pattern variable[0m









       
       Peter Miller                                         Page 80





       Cook                                              User Guide



       [40m[4m8.34[24m  [4mjoin[0m

       [40mThe  [4mjoin[24m  function  is  used  to  join  two sets of strings[0m
       [40mtogether,  element  by  element.   The  argument  list  must[0m
       [40mcontain  an  even  number  of arguments, with the first half[0m
       [40mjoined pair-wise with the last half.  There is no marker  of[0m
       [40many kind between the lists, so the user needs to ensure they[0m
       [40mare both the same length.[0m

       [4m[40m8.34.1[24m  [4mExample[0m

                         [40mExpression       Result[0m
                         [40m------------------------[0m
                         [40m[join a b c d]   ac bd[0m
                         [40m[join a b]       ab[0m

       [4m[40m8.34.2[24m  [4mSee[24m [4mAlso[0m
       [40mbasename, catenate, suffix[0m

       [4m[40m8.35[24m  [4mleaf_files[0m

       [40mThis function requires zero arguments.  The  result  is  the[0m
       [40mlist  of  files  which  are  leaves of the dependency graph.[0m
       [40m(Files  which  are  not  constructed  by  a  recipe.)   This[0m
       [40mfunction is only meaningful within a recipe body.[0m

       [4m[40m8.35.1[24m  [4mSee[24m [4mAlso[0m
       [40minterior_files     function,    graph_leaf_file    variable,[0m
       [40mgraph_leaf_pattern variable[0m

       [4m[40m8.36[24m  [4mmatches[0m

       [40mThis function requires one or  more  arguments.   The  first[0m
       [40margument  is  a  pattern, the second and later arguments are[0m
       [40mstrings  to  match  against  the  pattern.   The   resulting[0m
       [40mwordlist  contains  ""  (false)  if  did  not  match and the[0m
       [40m1-based list index (true) if it did.[0m

       [40mThe returned list index may be used in combination with  the[0m
       [40m[words] function.[0m

       [4m[40m8.36.1[24m  [4mExample[0m
       [40mThis  function  may be used to test for strings which have a[0m
       [40mparticular form:[0m
            [40mif [matches %1C%2 [version]] then[0m
                    [40mcc_flags = [cc_flags] -DDEBUG[0m
       [40mIf the version contains a Capital-C character, then turn  on[0m
       [40mdebugging.[0m

       [4m[40m8.36.2[24m  [4mMatch[24m [4mMode[0m
       [40mThis  function  is affected by the selected match mode.  See[0m
       [40mthe [4mFile[24m [4mName[24m [4mPatterns[24m chapter for details.[0m



       
       Peter Miller                                         Page 81





       Cook                                              User Guide



       [40m[4m8.36.3[24m  [4mSee[24m [4mAlso[0m
       [40mfilter, filter-out, words[0m

       [4m[40m8.37[24m  [4mmatch_mask[0m

       [40mThis function requires one or  more  arguments.   The  first[0m
       [40margument  is  a  pattern, the second and later arguments are[0m
       [40mstrings  to  match  against  this  pattern.   The  resulting[0m
       [40mwordlist  contains those arguments which matched the pattern[0m
       [40mgiven as the first argument.[0m

       [4m[40m8.37.1[24m  [4mExample[0m

                    [40mExpression                  Result[0m
                    [40m-----------------------------------[0m
                    [40m[match_mask %.c a.c a.o]    a.c[0m
                    [40m[match_mask %.cc a.c a.o][0m

       [4m[40m8.37.2[24m  [4mMatch[24m [4mMode[0m
       [40mThis function is affected by the selected match  mode.   See[0m
       [40mthe [4mFile[24m [4mName[24m [4mPatterns[24m chapter for details.[0m

       [4m[40m8.37.3[24m  [4mSee[24m [4mAlso[0m
       [40mfilter-out, findstring, stringset[0m

       [4m[40m8.37.4[24m  [4mAlso[24m [4mKnown[24m [4mAs[0m
       [40mfilter[0m

       [4m[40m8.38[24m  [4mmtime[0m

       [40mThis  function  requires one argument, the name of a file to[0m
       [40mfetch the last-modified time of.  The resulting wordlist  is[0m
       [40m""  (false)  is  the  file  does  not  exist,  or  a  string[0m
       [40mcontaining a (sortable) representation of the date and  time[0m
       [40mthe files were last modified.[0m

       [4m[40m8.38.1[24m  [4mSee[24m [4mAlso[0m
       [40mexists, mtime-seconds, sort_newest[0m

       [4m[40m8.39[24m  [4mmtime-seconds[0m

       [40mThis  function  requires one argument, the name of a file to[0m
       [40mfetch the last-modified time of.  The resulting wordlist  is[0m
       [40m""  (false)  is  the  file  does  not  exist,  or  a  string[0m
       [40mcontaining number of seconds since the epoch that the  files[0m
       [40mwere  last  modified.   This is more useful than [mtime] for[0m
       [40mdoing arithmetic on.[0m

       [4m[40m8.39.1[24m  [4mSee[24m [4mAlso[0m
       [40mexists, expr, mtime, sort_newest[0m





       
       Peter Miller                                         Page 82





       Cook                                              User Guide



       [40m[4m8.40[24m  [4mnotdir[0m

       [40mThis function requires one or more arguments, the  names  of[0m
       [40mfiles which will have their entry name parts extracted.[0m

       [4m[40m8.40.1[24m  [4mExample[0m

                    [40mExpression      Result[0m
                    [40m----------------------------------[0m
                    [40m[notdir foo.c]  foo.c[0m
                    [40m[notdir foo/bar.c]      bar.c[0m
                    [40m[notdir baz]    baz[0m

       [4m[40m8.40.2[24m  [4mSee[24m [4mAlso[0m
       [40mbasename, dirname, relative_dirname, suffix[0m

       [4m[40m8.40.3[24m  [4mAlso[24m [4mKnown[24m [4mAs[0m
       [40mentryname[0m

       [4m[40m8.41[24m  [4mnot[0m

       [40mThis  function requires zero or more arguments, the value to[0m
       [40mbe logically negated.  It returns "1" (true) if all  of  the[0m
       [40marguments  are  ""  (false),  or there are no arguments; and[0m
       [40mreturns "" (false) otherwise.  This is  symmetric  with  the[0m
       [40mdefinition of true and false for [1mif[22m.[0m

       [4m[40m8.41.1[24m  [4mExample[0m
       [40mThis is often seen in recipes:[0m
            [40m%1/%0%2.o: %1/%0%2.c[0m
                    [40msingle-thread %2.o[0m
            [40m{[0m
                    [40mif [not [exists [dirname [target]]]] then[0m
                            [40mmkdir -p [dirname [target]][0m
                                    [40mset clearstat;[0m
                    [40m[cc] [cc_flags] -I%1 %1/%0%2.c;[0m
                    [40mmv %2.o [target];[0m
            [40m}[0m
       [40mNote that "%0" matches zero or more whole filename portions,[0m
       [40mincluding the trailing slash.  See the  chapter  on  pattern[0m
       [40mmatching for more information.[0m

       [40mThis  is an example only.  The ``mkdir'' recipe flag creates[0m
       [40mthe directory more efficiently.[0m

       [4m[40m8.41.2[24m  [4mSee[24m [4mAlso[0m
       [40mand, or[0m








       
       Peter Miller                                         Page 83





       Cook                                              User Guide



       [40m[4m8.42[24m  [4moperating_system[0m

       [40mThis  function  requires  zero  or  more   arguments.    The[0m
       [40mresulting wordlist contains the values of various attributes[0m
       [40mof the operating system, as named in the arguments.   If  no[0m
       [40mattributes  are named, "system" is assumed.  Below is a list[0m
       [40mof attributes:[0m

       [40mnode      The name of the computer [1mcook [22mis presently running[0m
                 [40mon.[0m

       [40msystem    The name of the operating system [1mcook [22mis presently[0m
                 [40mbeing run under.  For example: if you were running[0m
                 [40mon SunOS 4.1.3, this would return "SunOS".[0m

       [40mrelease   The  specific  release of operating system, within[0m
                 [40mname, [1mcook [22mis  presently  being  run  under.   For[0m
                 [40mexample:  if you were running on SunOS 4.1.3, this[0m
                 [40mwould return "4.1.3".[0m

       [40mversion   Version information.  For SunOS 4.1.3, this  would[0m
                 [40mreturn  the kernel build number, for other systems[0m
                 [40mit is often the kernel patch release number.[0m

       [40mmachine   The name of the hardware [1mcook [22mis presently running[0m
                 [40mon.   For  example:  If  you were running on SunOS[0m
                 [40m4.1.3 this would return "sun4" or similar.[0m

       [40mThis function may be abbreviated to "os".[0m

       [4m[40m8.42.1[24m  [4mExample[0m
       [40mThis function is usually used to determine the  architecture[0m
       [40m(either system or machine):[0m
            [40march=[os system]-[os release]-[os machine];[0m
            [40mif [matches SunOS-4.1%1-sun4%2 [arch]] then[0m
                    [40march = sun4;[0m
            [40melse if [matches SunOS-5.%1-sun4%2 [arch]] then[0m
                    [40march = sun5;[0m
            [40melse if [matches SunOS-5.%1-i86pc [arch]] then[0m
                    [40march = sun5pc;[0m
            [40melse if [matches ConvexOS-%1-%2 [arch]] then[0m
                    [40march = convex;[0m
            [40melse[0m
                    [40march = unknown;[0m

       [4m[40m8.42.2[24m  [4mCaveat[0m
       [40mThis function is implemented using the [4muname[24m(2) system call.[0m
       [40mSome systems do not implement this correctly, and  therefore[0m
       [40mthis  function  is  less useful than it should be, and needs[0m
       [40mthe pattern match appropach used above.[0m

       [4m[40m8.42.3[24m  [4mSee[24m [4mAlso[0m
       [40mcollect[0m


       
       Peter Miller                                         Page 84





       Cook                                              User Guide



       [40m[4m8.42.4[24m  [4mAlso[24m [4mKnown[24m [4mAs[0m
       [40mos[0m

       [4m[40m8.43[24m  [4moptions[0m

       [40mThis  functions  takes  no  arguments.   The  results  is  a[0m
       [40mcomplete  list  of  [4mcook[24m  options,  exactly  describing  the[0m
       [40mcurrent  options  settings.   This  intended  for   use   in[0m
       [40mconstructing recursive [4mcook[24m invocations.[0m

       [40mThe  option  setting  generated  are  a  combination  of the[0m
       [40mcommand line options used to invoke [4mcook,[24m  the  contents  of[0m
       [40mthe  COOK  environment  variable, the results of the ``set''[0m
       [40mcommand and the various ``set'' clauses.[0m

       [4m[40m8.43.1[24m  [4mExample[0m
       [40mThe top level cookbook for a recursive project structure can[0m
       [40mbe as follows:[0m
            [40m%:[0m
            [40m{[0m
                    [40mdirlist = [dirname [glob '*/Howto.cook' ]];[0m
                    [40mloop[0m
                    [40m{[0m
                            [40mdir = [head [dirlist]];[0m
                            [40mif [not [dir]] then[0m
                                    [40mloopstop;[0m
                            [40mdirlist = [tail [dirlist]];[0m

                            [40mcd [dir]\; cook [options] %;[0m
                    [40m}[0m
            [40m}[0m

            [40m/*[0m
             [40m* This recipe sets the default.[0m
             [40m* It doesn't actually do anything.[0m
             [40m*/[0m
            [40mall:;[0m
       [40mPlease  note  the  %  hiding  on  the end of the nested [4mcook[0m
       [40mcommand, this is how  the  target  is  communicated  to  the[0m
       [40mnested [1mcook [22minvocation.[0m

       [4m[40m8.43.2[24m  [4mCaveat[0m
       [40mRecursive  Cook  is not recommended, because it segments the[0m
       [40mdependency graph and  forces  Cook  to  walk  the  graph  in[0m
       [40m(potentially)  the wrong order.  This introduces a number of[0m
       [40msignificant  problems.   A  single  top-level  cookbook   is[0m
       [40mrecommended.[0m

       [4m[40m8.43.3[24m  [4mSee[24m [4mAlso[0m
       [40mThe  supplied  ``recursive'' cookbook does exactly this.  In[0m
       [40morder to use it, you need a [4mHowto.cook[24m file  containing  the[0m
       [40msingle line[0m
            [40m#include "recursive"[0m


       
       Peter Miller                                         Page 85





       Cook                                              User Guide



       [40m[4m8.44[24m  [4mor[0m

       [40mThis function requires at least two arguments, upon which it[0m
       [40mforms a logical disjunction.   The  value  returned  is  "1"[0m
       [40m(true)  if  any  one  of  the  arguments  is not "" (false),[0m
       [40motherwise "" (false) is returned.[0m

       [4m[40m8.44.1[24m  [4mSee[24m [4mAlso[0m
       [40mand, not[0m

       [4m[40m8.45[24m  [4mpathname[0m

       [40mThe function requires one or  more  arguments,  being  files[0m
       [40mnames to be replaced with their full path names.[0m

       [4m[40m8.45.1[24m  [4mExample[0m
       [40mRelative  names are made absolute, and redundant slashes and[0m
       [40mdots are removed:[0m
            [40mpwd = [pathname .];[0m

       [4m[40m8.45.2[24m  [4mSee[24m [4mAlso[0m
       [40mbasename, dirname, entryname[0m

       [4m[40m8.46[24m  [4mpatsubst[0m

       [40mThis function requires at  least  two  arguments.   Patsubst[0m
       [40mgives   the  user  access  to  the  pattern  transformations[0m
       [40mavailable to [1mcook[22m.  The first argument is the  "from"  form,[0m
       [40mthe  second  argument is the "to" form.  All other arguments[0m
       [40mare mapped from one to the other.[0m

       [4m[40m8.46.1[24m  [4mExample[0m
       [40mGiven a list of C source files, generate a  list  of  object[0m
       [40mfiles as follows:[0m
            [40mobj = [patsubst %.c %.o [src]];[0m

       [4m[40m8.46.2[24m  [4mMatch[24m [4mMode[0m
       [40mThis  function  is affected by the selected match mode.  See[0m
       [40mthe [4mFile[24m [4mName[24m [4mPatterns[24m chapter for details.[0m

       [4m[40m8.46.3[24m  [4mSee[24m [4mAlso[0m
       [40mfilter, filter_out, subst[0m

       [4m[40m8.46.4[24m  [4mAlso[24m [4mKnown[24m [4mAs[0m
       [40mfromto[0m










       
       Peter Miller                                         Page 86





       Cook                                              User Guide



       [40m[4m8.47[24m  [4mprepost[0m

       [40mThis function must have at least two arguments.   The  first[0m
       [40margument  is  a  prefix and the second argument is a suffix.[0m
       [40mThe resulting word list is the  third  and  later  arguments[0m
       [40meach given the prefix and suffix as defined by the first and[0m
       [40msecond arguments.[0m

       [4m[40m8.47.1[24m  [4mExample[0m

                [40mExpression               Result[0m
                [40m-------------------------------------------[0m
                [40m[prepost sun4/ .o a b]   sun4/a.o sun4/b.o[0m
                [40m[prepost -I "" . bl]     -I. -Ibl[0m

       [4m[40m8.47.2[24m  [4mSee[24m [4mAlso[0m
       [40maddprefix, addsuffix, patsubst, subst[0m

       [4m[40m8.48[24m  [4mprint[0m

       [40mThe arguments are printed as an  informative  message.   The[0m
       [40musual  output  wrapping  is performed.  The function returns[0m
       [40mthe empty list as a result.[0m

       [40mThis function is frequently use to debug cookbooks.[0m

       [4m[40m8.49[24m  [4mquote[0m

       [40mEach argument  is  quoted  by  double  quotes,  with  shell9[0m
       [40mspecial characters escaped as necessary.[0m

       [4m[40m8.49.1[24m  [4mSee[24m [4mAlso[0m
       [40mcollect, execute[0m

       [4m[40m8.50[24m  [4mread_lines[0m

       [40mThe argument is interpreted as the name of a text file to be[0m
       [40mread.  The result is one word for each line of the file.[0m

       [4m[40m8.50.1[24m  [4mExample[0m
       [40mRead a the [4mexample[24m file and assign it to a variable:[0m
            [40mexample = [read_lines example];[0m

       [4m[40m8.50.2[24m  [4mSee[24m [4mAlso[0m
       [40mcollect, collect_lines, read, write[0m







       ____________________

       9. See [4msh[24m (1) and [4mcsh[24m(1) for more information.

       Peter Miller                                         Page 87





       Cook                                              User Guide



       [40m[4m8.51[24m  [4mreadlink[0m

       [40mThe arguments are assumed to be symbolic  links,  and  their[0m
       [40mvalues are read.  It is a fatal error if the files named are[0m
       [40mnot symbolic links.[0m

       [4m[40m8.51.1[24m  [4mSee[24m [4mAlso[0m
       [40mcollect, exists-symlink[0m

       [4m[40m8.52[24m  [4mread[0m

       [40mThe argument is interpreted as the name of a text file to be[0m
       [40mread.  The result is one word for each white-space separated[0m
       [40mword of the file.[0m

       [4m[40m8.52.1[24m  [4mExample[0m
       [40mRead a the [4mexample[24m file and assign it to a variable:[0m
            [40mexample = [read example];[0m

       [4m[40m8.52.2[24m  [4mSee[24m [4mAlso[0m
       [40mcollect, collect_lines, read_lines, write[0m

       [4m[40m8.53[24m  [4mrelative_dirname[0m

       [40mThis function requires one or more arguments, the  names  of[0m
       [40mfiles which will have their directory parts extracted.[0m

       [4m[40m8.53.1[24m  [4mExample[0m

                 [40mExpression      Result[0m
                 [40m----------------------------------------[0m
                 [40m[relative_dirname a]    .[0m
                 [40m[relative_dirname a/b]  a[0m
                 [40m[relative_dirname a/b/c]        a/b[0m
       [40mSee  [4mdirname[24m  if  you  want to climb the directory tree with[0m
       [40mrepeated applications,  [4mrelative_dirname[24m  will  continue  to[0m
       [40mreturn ``.'' once the current directory is reached.[0m

       [4m[40m8.53.2[24m  [4mSee[24m [4mAlso[0m
       [40mbasename, dirname, entryname, notdir, pathname, suffix[0m

       [4m[40m8.53.3[24m  [4mAlso[24m [4mKnown[24m [4mAs[0m
       [40mreldir[0m












       
       Peter Miller                                         Page 88





       Cook                                              User Guide



       [40m[4m8.54[24m  [4mresolve[0m

       [40mThis  builtin  function  is  used to resolve file names when[0m
       [40musing  the  [4msearch_list[24m  variable  to  locate  files.   This[0m
       [40mbuiltin  function  produces  resolved  file names as output.[0m
       [40mThis is useful when taking partial copies  of  a  source  to[0m
       [40mperform  controlled  updates.   The  targets  of recipes are[0m
       [40malways cooked into the current directory.[0m

       [4m[40m8.54.1[24m  [4mExample[0m
       [40mThis  function  is  used  in  cookbooks   which    use   the[0m
       [4m[40msearch_list[24m functionality:[0m
            [40msearch_list = . baseline;[0m

            [40m%.o: %.c[0m
            [40m{[0m
                    [40m[cc] [cc_flags] [addprefix -I [search_list]] [resolve %.c];[0m
            [40m}[0m

       [40mThe cookbooks distributed with Cook contain full support for[0m
       [40mthe search_list functionality.  They are a  good  source  of[0m
       [40mexamples  of  how  to  write  recipes  which  take this into[0m
       [40maccount.[0m

       [4m[40m8.55[24m  [4mshell[0m

       [40mThe arguments are interpreted as a command to be  passed  to[0m
       [40mthe  operating  system.   The  result  is  one word for each[0m
       [40mwhite-space separated word of the output of the command.[0m

       [40mThe command will not be echoed unless the -No_Silent  option[0m
       [40mis specified on the command line.[0m

       [4m[40m8.55.1[24m  [4mExample[0m
       [40mRead the date and time and assign it to a variable:[0m
            [40mnow = [shell date];[0m
       [40mDo not use the shell function to expand a filename wildcard,[0m
       [40mused the [wildcard] function instead.[0m

       [4m[40m8.55.2[24m  [4mSee[24m [4mAlso[0m
       [40mcollect_lines, execute, wildcard[0m

       [4m[40m8.55.3[24m  [4mAlso[24m [4mKnown[24m [4mAs[0m
       [40mcollect[0m











       
       Peter Miller                                         Page 89





       Cook                                              User Guide



       [40m[4m8.56[24m  [4msort_newest[0m

       [40mThe  arguments  are  sorted  by  file  last-modified   time,[0m
       [40myoungest  to oldest.  File names are resolved first (see the[0m
       [40mresolve function, below).  Absent files will  be  sorted  to[0m
       [40mthe start of the list.[0m

       [4m[40m8.56.1[24m  [4mExample[0m
       [40mThis  function  is  often  used  to  "shorten the wait" when[0m
       [40mbuilding large project, so that the  file  you  edited  most[0m
       [40mrecently is recompiled almost immediately:[0m
            [40msrc = [glob *.c];[0m
            [40mobj = [sort_newest [fromto %.c %.o [src]]];[0m

       [40mThis  trick  does  not always work as expected, and can take[0m
       [40msignificant time for little result.[0m

       [4m[40m8.56.2[24m  [4mSee[24m [4mAlso[0m
       [40mfromto, glob, sort[0m

       [4m[40m8.57[24m  [4msort[0m

       [40mThe arguments are sorted lexicographically.[0m

       [1m[40mNote:  [22mDuplicates  are  [4mnot[24m  removed.   Use  the   [4mstringset[0m
       [40mfunction if you want to do this.[0m

       [4m[40m8.57.1[24m  [4mSee[24m [4mAlso[0m
       [40msort_newest, stringset[0m

       [4m[40m8.58[24m  [4msplit[0m

       [40mThe  [4msplit[24m  function  is used to split strings into multiple[0m
       [40mstrings, given the separator.   This  function  requires  at[0m
       [40mleast  one  argument.   The  first argument is the separator[0m
       [40mcharacter, the second and subsequent  arguments  are  to  be[0m
       [40mseparated.   The  result is the separated strings, each as a[0m
       [40mseparate word.[0m

       [4m[40m8.58.1[24m  [4mExample[0m

                 [40mExpression                  Result[0m
                 [40m----------------------------------------[0m
                 [40m[split ":" "foo:bar:baz"]   foo bar baz[0m
                 [40m[split " " "New York"]      New York[0m
       [40mEach of the words in the result is a separate string.[0m

       [40mThis can be useful in splitting an environment variable into[0m
       [40mseparate words.  For example:[0m
            [40mpath = [split ":" [getenv PATH]];[0m

       [4m[40m8.58.2[24m  [4mSee[24m [4mAlso[0m
       [40munsplit, join, catenate, strip[0m


       
       Peter Miller                                         Page 90





       Cook                                              User Guide



       [40m[4m8.59[24m  [4mstringset[0m

       [40mLogical  operations are performed on sets of strings.  These[0m
       [40minclude conjunction ([1m+[22m) or  implicit,  disjunction  ([1m*[22m)  and[0m
       [40mdifference ([1m-[22m).[0m

       [4m[40m8.59.1[24m  [4mExample[0m

                     [40mExpression                Result[0m
                     [40m---------------------------------[0m
                     [40m[stringset a b a]         a b[0m
                     [40m[stringset a b c * a]     a[0m
                     [40m[stringset a b c - a]     b c[0m
                     [40m[stringset a b - c + d]   a b d[0m

       [40mThe  can  be  very  useful  in  constructing lists of source[0m
       [40mfiles:[0m
            [40msrc = [stringset [glob "*.[cyl]" ] - y.tab.c lex.yy.c];[0m

       [4m[40m8.59.2[24m  [4mSee[24m [4mAlso[0m
       [40mfilter, filter_out, glob, in, patsubst, subst[0m

       [4m[40m8.60[24m  [4mstripdot[0m

       [40mThe [4mstripdot[24m function  is  used  to  remove  leading  ``.\''[0m
       [40mdirectories from each of the path name arguments.[0m

       [4m[40m8.60.1[24m  [4mExample[0m

                       [40mExpression           Result[0m
                       [40m----------------------------[0m
                       [40m[stripdot ./foo.c]    foo.c[0m
                       [40m[stripdot bar.o]     bar.o[0m
                       [40m[stripdot /fubar]    /fubar[0m

       [4m[40m8.60.2[24m  [4mSee[24m [4mAlso[0m
       [40mset stripdot[0m


















       
       Peter Miller                                         Page 91





       Cook                                              User Guide



       [40m[4m8.61[24m  [4mstrip[0m

       [40mThe  [4mstrip[24m  function  is used to remove leading and trailing[0m
       [40mwhite space from words.  Internal sequences of  white  space[0m
       [40mare replaced by a single space.[0m

       [4m[40m8.61.1[24m  [4mExample[0m

                 [40mExpression                  Result[0m
                 [40m-----------------------------------------[0m
                 [40m[strip " " "foo " " bar"]   "" foo bar[0m
                 [40m[strip " really   big  "]   "really big"[0m
       [40mQuotes are used here for clarity, and are not present in the[0m
       [40minternal representation of strings.[0m

       [4m[40m8.61.2[24m  [4mSee[24m [4mAlso[0m
       [40msplit[0m

       [4m[40m8.62[24m  [4msubstr[0m

       [40mThe [4msubstr[24m function is used to perform substring  extracton.[0m
       [40mThe  first  argument is the starting position in the string,[0m
       [40mstarting from one.  The second argument  is  the  number  of[0m
       [40mcharacters to extract.  Thirst and subsequent arguments will[0m
       [40mbe processed to extract sub-strings.[0m

       [4m[40m8.62.1[24m  [4mExample[0m

                      [40mExpression             Result[0m
                      [40m------------------------------[0m
                      [40m[substr 1 1 Peter]     P[0m
                      [40m[substr 3 99 Miller]   ller[0m

       [4m[40m8.62.2[24m  [4mSee[24m [4mAlso[0m
       [40msubst, patsubst[0m

       [4m[40m8.63[24m  [4msubst[0m

       [40mThe [4msubst[24m function is used to perform  string  substitutions[0m
       [40mon  its  arguments.   This  function  requires  at least two[0m
       [40marguments.  The first argument is  the  "from"  string,  the[0m
       [40msecond  argument  is  the  "to" string.  All occurreneces of[0m
       [40m"from" are replaced with "to" in the  third  and  subsequent[0m
       [40marguments.[0m

       [4m[40m8.63.1[24m  [4mExample[0m
       [40mThis is a literal replacement, not a pattern replacement:[0m

            [40mExpression                            Result[0m
            [40m---------------------------------------------------[0m
            [40m[subst buffalo cress water.buffalo]   water.cress[0m
            [40m[subst .c .o test.c]                  test.o[0m
            [40m[subst .c .o stat.cache.c]            stat.oache.o[0m
       [40mNote that last case: it is not selective.[0m

       
       Peter Miller                                         Page 92





       Cook                                              User Guide



       [40m[4m8.63.2[24m  [4mSee[24m [4mAlso[0m
       [40mfilter, filter_out, patsubst[0m

       [4m[40m8.64[24m  [4msuffix[0m

       [40mThe  [4msuffix[24m function treats each argument as a filename, and[0m
       [40mextracts the suffix from each.  If the filename  contains  a[0m
       [40mperiod,  the  suffix  is  everything  starting with the last[0m
       [40mperiod.  Otherwise, the  suffix  is  the  empty  string  (as[0m
       [40mopposed to nothing at all).[0m

       [4m[40m8.64.1[24m  [4mExample[0m

                     [40mExpression              Result[0m
                     [40m---------------------------------[0m
                     [40m[suffix a.c foo b.y]    .c "" .y[0m
                     [40m[suffix stat.cache.c]   .c[0m
                     [40m[suffix .eric]          ""[0m
       [40mQuotes are used here for clarity, and are not present in the[0m
       [40minternal representation of strings.[0m

       [40mThe [4msuffix[24m functions in this way to allow  sensible  results[0m
       [40mwhen   using   the   [4mjoin[24m  function  to  re-unite  filenames[0m
       [40mdismembered by the [4mbasename[24m and [4msuffix[24m functions.[0m

       [4m[40m8.64.2[24m  [4mSee[24m [4mAlso[0m
       [40mbasename, dirname, entryname, join, patsubst[0m

       [4m[40m8.65[24m  [4mtail[0m

       [40mThis function requires zero or  more  arguments.   The  word[0m
       [40mlist  returned  will  be  empty  if  there  is less than two[0m
       [40marguments, otherwise it will consist of the second and later[0m
       [40marguments.[0m

       [4m[40m8.65.1[24m  [4mSee[24m [4mAlso[0m
       [40mcount, head, word[0m


















       
       Peter Miller                                         Page 93





       Cook                                              User Guide



       [40m[4m8.66[24m  [4mun-dos-path[0m

       [40mThis  function requires one or more arguments, which will be[0m
       [40mconverted from a DOS path into a UNIX path.  This is of most[0m
       [40muse  under  Windows-NT, to convert DOS pathnames into Cook's[0m
       [40minternal pathnames.  (The UNIX porting layer  usually  hides[0m
       [40mthis from Cook.)[0m

       [4m[40m8.66.1[24m  [4mExample[0m

              [40mExpression                     Result[0m
              [40m----------------------------------------------[0m
              [40m[un-dos-path a\b\c]            a/b/c[0m
              [40m[un-dos-path c:\temp]          //c/temp[0m
              [40m[un-dos-path \\server\stuff]   //server/stuff[0m

       [4m[40m8.66.2[24m  [4mSee[24m [4mAlso[0m
       [40mdos-path[0m

       [4m[40m8.67[24m  [4munsplit[0m

       [40mThe [4munsplit[24m function is used to glue strings together, using[0m
       [40mthe specified glue.  The first argument is the  text  to  go[0m
       [40mbetween each of the second and subsequent arguments.[0m

       [4m[40m8.67.1[24m  [4mExample[0m

              [40mExpression                    Result[0m
              [40m----------------------------------------------[0m
              [40m[unsplit ":" one two three]   "one:two:three"[0m
              [40m[unsplit " " four five six]   "four five six"[0m
       [40mThe quotes are necessary to isolate characters such as colon[0m
       [40mand space which cook would normally treat differently.[0m

       [4m[40m8.67.2[24m  [4mSee[24m [4mAlso[0m
       [40mcatenate, prepost, split[0m

       [4m[40m8.68[24m  [4mupcase[0m

       [40mThis function requires one or more arguments,  words  to  be[0m
       [40mforced into upper case.[0m

       [4m[40m8.68.1[24m  [4mExample[0m

                          [40mExpression     Result[0m
                          [40m----------------------[0m
                          [40m[upcase FOO]   FOO[0m
                          [40m[upcase Bar]   BAR[0m
                          [40m[upcase baz]   BAZ[0m

       [4m[40m8.68.2[24m  [4mSee[24m [4mAlso[0m
       [40mdowncase[0m



       
       Peter Miller                                         Page 94





       Cook                                              User Guide



       [40m[4m8.69[24m  [4muptodate[0m

       [40mThis  function  may be used to determine if files are up-to-[0m
       [40mdate.  It returns a word list containing the  names  of  the[0m
       [40mup-to-date  files,  or empty if none of them are up-to-date.[0m
       [40mThey are [4mnot[24m brought up to date if  they  are  not  already.[0m
       [40mThis function requires one or more arguments.[0m

       [4m[40m8.69.1[24m  [4mCaveat[0m
       [40mThis will use as much of the cookbook as has been read in up[0m
       [40mto the point where this function is  used.   This  can  mean[0m
       [40mthat crucial recipes have yet to be parsed and instanciated.[0m

       [4m[40m8.69.2[24m  [4mSee[24m [4mAlso[0m
       [40mcando, cook[0m

       [4m[40m8.70[24m  [4mwildcard[0m

       [40mEach  argument  is treated as a [4msh[24m(1) file name pattern, and[0m
       [40mexpanded accordingly.  The resulting list  of  filenames  is[0m
       [40msorted lexicographically.[0m

       [40mYou  may  need  to  quote  the  pattern,  to  protect square[0m
       [40mbrackets from the meaning cook attaches to them.[0m

       [1m[40mNote: [22mThe character sequence /* is a comment introducer, and[0m
       [40mis  a  frequent  source  of  problems when combined with the[0m
       [4m[40mwildcard[24m function.  Remember  to  quote  [4mwildcard[24m  arguments[0m
       [40mwhich need this character sequence.[0m

       [4m[40m8.70.1[24m  [4mExample[0m
       [40mTo find the sources in the current directory:[0m
            [40msrc = [wildcard *.c];[0m
            [40mobj = [patsubst %.c %.o [src]];[0m

       [4m[40m8.70.2[24m  [4mSee[24m [4mAlso[0m
       [40mfilter, filter_out, patsubst[0m

       [4m[40m8.70.3[24m  [4mAlso[24m [4mKnown[24m [4mAs[0m
       [40mglob[0m















       
       Peter Miller                                         Page 95





       Cook                                              User Guide



       [40m[4m8.70.4[24m  [4mWordlist[0m
       [40mThis  function may be used to extract a list of words from a[0m
       [40mlarger list.  The first argument is the  starting  position,[0m
       [40mand  the  second argument is the ending poistion, inclusive.[0m
       [40mThe third and  subsequent  arguments  are  the  list  to  be[0m
       [40mextracted from.  Positions are numbered starting from 1.  If[0m
       [40mthe start is bigger than  the  end,  they  will  be  quietly[0m
       [40mswapped.   If  the start is bigger than the list, the result[0m
       [40mwill be empty.[0m

       [4m[40m8.70.4.1[24m  [4mExample[0m

                   [40mExpression                   Result[0m
                   [40m-------------------------------------[0m
                   [40m[wordlist 2 3 foo bar baz]   bar baz[0m
                   [40m[wordlist 1 1 foo bar baz]   foo[0m
                   [40m[wordlist 7 3 foo bar baz]   baz[0m

       [40mThere are a number of functions which are similar[0m

                  [40mExpression               Similar to[0m
                  [40m---------------------------------------[0m
                  [40m[wordlist 1 1 [4mlist[24m]      [head [4mlist[24m][0m
                  [40m[wordlist 2 9999 [4mlist[24m]   [tail [4mlist[24m][0m
                  [40m[wordlist [4mN[24m [4mN[24m [4mlist[24m]      [word [4mN[24m [4mlist[24m][0m

       [4m[40m8.70.4.2[24m  [4mSee[24m [4mAlso[0m
       [40mfirstword head, tail, word, words[0m

       [4m[40m8.71[24m  [4mword[0m

       [40mThe [4mword[24m function is used to extract a specific word from  a[0m
       [40mlist of words.  The function requires at least one argument.[0m
       [40mThe first argument is the number of the word to extract from[0m
       [40mthe  wordlist.   The  wordlist  is the second and subsequent[0m
       [40marguments.  An empty list will be returned if you ask for an[0m
       [40melement off the end of the list.[0m

       [4m[40m8.71.1[24m  [4mExample[0m

                     [40mExpression               Result[0m
                     [40m--------------------------------[0m
                     [40m[word 1 one two three]   one[0m
                     [40m[word 2 one two three]   two[0m
                     [40m[word 3 one two three]   three[0m
                     [40m[word 5 one two three][0m

       [40mThe last element of a list of words may be extracted as:[0m
            [40mlast = [word [count [list]] [list]];[0m

       [4m[40m8.71.2[24m  [4mSee[24m [4mAlso[0m
       [40mcount, head[0m



       
       Peter Miller                                         Page 96





       Cook                                              User Guide



       [40m[4m8.72[24m  [4mwords[0m

       [40mThis  function  requires zero or more arguments.  The result[0m
       [40mis a word list of one word containing the  (decimal)  length[0m
       [40mof the argument word list.[0m

       [4m[40m8.72.1[24m  [4mExample[0m
       [40mThis  cookbook fragment echoes the number of files, and then[0m
       [40mthe name of the last file:[0m
            [40mecho There are [words [files]] files.;[0m
            [40mecho The last file is [word [words [files]] [files]].;[0m

       [4m[40m8.72.2[24m  [4mSee[24m [4mAlso[0m
       [40mhead, tail, word[0m

       [4m[40m8.72.3[24m  [4mAlso[24m [4mKnown[24m [4mAs[0m
       [40mcount[0m

       [4m[40m8.73[24m  [4mwrite[0m

       [40mThis function requires one or  more  arguments.   The  first[0m
       [40margument  is  the  name  of the file to write, the second an[0m
       [40mlater arguments are lines to be written to the file.   (This[0m
       [40mis  specifically  a text file.)  The result is an empty word[0m
       [40mlist.[0m

       [40mThis function is very useful in writing  command  line  file[0m
       [40mfor  Windows-NT,  due  to  its  absurdly  short command line[0m
       [40minterface.[0m

       [4m[40m8.73.1[24m  [4mSee[24m [4mAlso[0m
       [40mread, read_lines[0m























       
       Peter Miller                                         Page 97





       Cook                                              User Guide



       [40m[4m9.[24m  [4mPredefined[24m [4mVariables[0m

       [40mA number of variables are defined by [1mcook [22mat run-time.[0m

       [4m[40m9.1[24m  [4marg[0m

       [40mThis is  the  arguments  list  for  user-defined  functions.[0m
       [40mIndividual  arguments  are  split out into ``@1'' to ``@9''.[0m
       [40mThese can also be used at automatic variables.  Caution: [4marg[0m
       [40mand   the   automatic  variables  are  [4mshared[24m  for  parallel[0m
       [40mexecution, causing  weird  interactions  if  you  execute  a[0m
       [40mcommand within the function.[0m

       [4m[40m9.2[24m  [4mcommand-line-goals[0m

       [40mThe  value  of  this  variable is the goals specified on the[0m
       [40mcommand line, if any.   If  none  were  specified,  and  the[0m
       [40mdefault goal is in effect, the value will be empty.[0m

       [4m[40m9.3[24m  [4m__FILE__[0m

       [40mThe  value  of this variable is the logical name of the file[0m
       [40mwhich contains it.  In the case  of  #include-cooked  files,[0m
       [40mthe  physical  name  may  be  obtained  using  the [resolve][0m
       [40mfunction.  The logical name  may  be  set  using  the  #line[0m
       [40mdirective.[0m

       [4m[40m9.4[24m  [4m__FUNCTION__[0m

       [40mThe value of this variable is the name of the function which[0m
       [40mexecutes it.  It is not set for the global cookbook scope or[0m
       [40mthe recipe body scope.[0m

       [4m[40m9.5[24m  [4mgraph_leaf_file[0m

       [40mFile  names  which are listed in this variable could be leaf[0m
       [40mfiles of the dependency graph.   (See  also  the  [4mleaf_files[0m
       [40mfunction, for Cook's idea of the leaf files.)[0m

       [4m[40m9.6[24m  [4mgraph_exterior_file[0m

       [40mFile  names  which  are  listed  in  this variable cannot be[0m
       [40mpresent in any way in the dependency graph.[0m

       [4m[40m9.7[24m  [4mgraph_interior_file[0m

       [40mFile names which  are  listed  in  this  variable  could  be[0m
       [40minterior  files  of  the  dependency  graph.   (See also the[0m
       [4m[40minterior_files[24m function, for Cook's  idea  of  the  interior[0m
       [40mfiles.)[0m

       [4m[40m9.8[24m  [4mgraph_leaf_pattern[0m

       [40mFile  names  which match the patterns in this variable could[0m

       
       Peter Miller                                         Page 98





       Cook                                              User Guide



       [40mbe leaf files  of  the  dependency  graph.   (See  also  the[0m
       [4m[40mleaf_files[24m function, for Cook's idea of the leaf files.)[0m

       [4m[40m9.9[24m  [4mgraph_exterior_pattern[0m

       [40mFile  names which match the patterns in this variable cannot[0m
       [40mbe present in any way in the dependency graph.[0m

       [4m[40m9.10[24m  [4mgraph_interior_pattern[0m

       [40mFile names which match the patterns in this  variable  could[0m
       [40mbe  interior  files  of the dependency graph.  (See also the[0m
       [4m[40minterior_files[24m function, for Cook's  idea  of  the  interior[0m
       [40mfiles.)[0m

       [4m[40m9.11[24m  [4m__LINE__[0m

       [40mThe  value of this variable is the line number within of the[0m
       [40mfile which contains it.  The line number may  be  set  using[0m
       [40mthe #line directive.[0m

       [4m[40m9.12[24m  [4mneed[0m

       [40mThe ingredients of the recipe currently being cooked.[0m

       [4m[40m9.13[24m  [4mparallel_hosts[0m

       [40mThis  variable may be set to indicate a list of hosts to use[0m
       [40mto distribute the execution of recipe bodies.[0m

       [4m[40m9.14[24m  [4mparallel_jobs[0m

       [40mThis variable may be set to the number of parallel execution[0m
       [40mthreads  to  perform  simultaneously.   Defaults to 1 if not[0m
       [40mset.[0m

       [4m[40m9.15[24m  [4mparallel_rsh[0m

       [40mThis variable may be set to  the  command  used  to  execute[0m
       [40mcommands  on  remote  machines.  Assumes to take argument in[0m
       [40mthe same form  as  the  BSD  [4mrsh[24m(1)  command.   Defaults  to[0m
       [40m``[4mrsh[24m'' if not set.[0m

       [4m[40m9.16[24m  [4msearch_list[0m

       [40mThis  variable  may  be  set  to a list of directories to be[0m
       [40msearched  for  targets  and  ingredients.   This   list   is[0m
       [40minitially  the  current  directory (.)  and will always have[0m
       [40mthe current directory prepended if it is not present.   This[0m
       [40mis  useful when taking partial copies of a source to perform[0m
       [40mcontrolled updates.  Use the [4mresolve[24m  built-in  function  to[0m
       [40mdetermine  what  file name cook actually found.  The targets[0m
       [40mof recipes are always cooked into the current directory.[0m


       
       Peter Miller                                         Page 99





       Cook                                              User Guide



       [40mThe cookbooks distributed with Cook contain full support for[0m
       [40mthe  search_list  functionality.   They are a good source of[0m
       [40mexamples of how  to  write  recipes  which  take  this  into[0m
       [40maccount.[0m

       [4m[40m9.17[24m  [4mself[0m

       [40mThe  name  [1mcook  [22mwas invoked as, usually "cook".  Be careful[0m
       [40mwhat you call cook, because anything with the string  "cook"[0m
       [40min  it  will be changed, including (but not limited to) file[0m
       [40msuffixes and environment variable names.[0m

       [4m[40m9.18[24m  [4mtarget[0m

       [40mThe target of the recipe  currently  being  cooked,  or  the[0m
       [40mfirst target if there is more than one.[0m

       [4m[40m9.19[24m  [4mtargets[0m

       [40mThe  targets  of  the  recipe  currently being cooked.  This[0m
       [40mincludes all targets of the recipe,  should  there  be  more[0m
       [40mthan one.[0m

       [4m[40m9.20[24m  [4mthread-id[0m

       [40mThis  variable has a unique value for each execution thread,[0m
       [40mfor the lifetime of that thread.  This value may be used  to[0m
       [40mconstruct   thread-unique   variable   names,  thread-unique[0m
       [40mtemporary file names, or anything  else  that  needs  to  be[0m
       [40munique  to  each  execution  thread.  The thread IDs are re-[0m
       [40mused, and so several threads in sequence may have  the  same[0m
       [40mthread  ID; it is only guaranteed that no other simultaneous[0m
       [40mthread will have the same thread  ID.   By  re-using  thread[0m
       [40mIDs,  generated  variable  names  are also re-used, avoiding[0m
       [40mmemory bloat.[0m

       [4m[40m9.21[24m  [4mtimestamp_granularity[0m

       [40mThis  variable  may  be  set  to  the  granularity  of   the[0m
       [40mfilesystem's  modtime  in  seconds.  Defaults to 1 second if[0m
       [40mnot set (a suitable value  for  most  systems).  Recommended[0m
       [40mnon-default values include 2 seconds for Cygwin on FAT32 and[0m
       [40m4 seconds for PrimeOS.[0m

       [4m[40m9.22[24m  [4myounger[0m

       [40mThe subset of the ingredients of the recipe currently  being[0m
       [40mcooked which are younger than the target.[0m

       [4m[40m9.23[24m  [4mversion[0m

       [40mThe version of [1mcook [22mcurrently executing.[0m



       
       Peter Miller                                        Page 100





       Cook                                              User Guide



       [40m[4m10.[24m  [4mFunctions[24m [4mLibrary[0m

       [40mThere is a file of functions available to you by using a[0m
            [40m#include "functions"[0m
       [40mline  in your cookbook.  The file defines a number of useful[0m
       [40mfunctions.[0m

       [40mThe functions in the file also serve as examples of how  you[0m
       [40mcan write your own functions.[0m

       [4m[40m10.1[24m  [4mcapitalize[0m

       [40mThe [4mcapitalize[24m function maps all of its arguments into lower[0m
       [40mcase, and then the first letter of each argument  is  mapped[0m
       [40mto upper case.  Zero, one or more arguments may be given.[0m

       [4m[40m10.2[24m  [4mdefined-or-null[0m

       [40mThe  [4mdefined-or-null[24m  function may be used to determine if a[0m
       [40mvariable has been set (on the command line, for example) and[0m
       [40mreturn its value if so, otherwise return the empty list.[0m

       [40mThis  function  should only be given one argument - the name[0m
       [40mof the variable to look for.  Additional arguments  will  be[0m
       [40mignored.   Too  few arguments will produce a complaint about[0m
       [40mthe "" variable being undefined.[0m

       [4m[40m10.3[24m  [4mdefined-or-default[0m

       [40mThe [4mdefined-or-default[24m function may be used to determine  if[0m
       [40ma  variable  has been set (on the command line, for example)[0m
       [40mand return its value  if  so,  otherwise  return  the  given[0m
       [40mdefault value.[0m

       [40mThe first argument is the name of the variable to look for.[0m

       [40mThe  second and later arguments (if present) are the default[0m
       [40mvalue to be used if  the  named  variable  is  not  defined.[0m
       [40mOptional.[0m

       [4m[40m10.4[24m  [4mrepeat[0m

       [40mThe  [4mrepeat[24m  function  is  used  to  repeatedly call another[0m
       [40mfunction, once for each of the specified arguments.  The can[0m
       [40mbe   useful   when  dealing  with  functions  which  do  not[0m
       [40mautomatically accept argument lists in the form you require.[0m

       [40mThere are many instances where the repeat function  call  be[0m
       [40mused  to  elegantly  avoid used to the ``loop { loopstop }''[0m
       [40mconstruct.[0m

       [40mThe first argument is the name  of  the  function  you  want[0m
       [40mcalled.  This function must accept a single argument.[0m


       
       Peter Miller                                        Page 101





       Cook                                              User Guide



       [40mThe  second  and subsequent arguments are argument values to[0m
       [40mbe passed to the named function, one at a time.[0m

       [40mThe  results  of  the  invocations  of  the   function   are[0m
       [40maccumulated in the order in which they were calculated.  The[0m
       [40maccumulated results are returned.[0m

       [4m[40m10.5[24m  [4mvariable_by_path[0m

       [40mThe [4mvariable_by_path[24m function is used to extract  the  union[0m
       [40mof  option  settings relevant to a particular compilation or[0m
       [40mlink.  By using a variable prefix, this function may be used[0m
       [40mto  obtain  the  setting  of  a  wide variety of options and[0m
       [40mcommands.[0m

       [40mGlobal variables are searched in a no particular  order  for[0m
       [40mthe  necessary information.  All are searched, all found are[0m
       [40mused.[0m

       [40mFor example, the function  call  [variable_by_path  cc_flags[0m
       [40mfoo/bar/baz.c]  will  hunt  for variables with the following[0m
       [40mnames:  cc_flags_foo/bar/baz.c  and   cc_flags_foo/bar   and[0m
       [40mcc_flags_foo  and  cc_flags.   It  is expected that the vast[0m
       [40mmajority of these variables will not be set.  Duplicates are[0m
       [40mremoved.[0m






























       
       Peter Miller                                        Page 102





       Cook                                              User Guide



       [40m[4m11.[24m  [4mActions[24m [4mwhen[24m [4mCooking[0m

       [40mThis  section  describes  what  [1mcook [22mdoes when you ask it to[0m
       [40mcook something.[0m

       [1m[40mCook [22mperforms the following actions in the order stated.[0m

       [4m[40m11.1[24m  [4mScan[24m [4mthe[24m [4mCOOK[24m [4mEnvironment[24m [4mVariable[0m

       [40mThe [1mCOOK [22menvironment variable  is  looked  for.   If  it  is[0m
       [40mfound, it is treated as if it consisted of [1mcook [22mcommand line[0m
       [40marguments.  Only the [1m-Help [22moption is  illegal.   This  could[0m
       [40mresult is very strange behavior if used incorrectly.[0m

       [40mThis  feature  is  supplied  to override [1mcook[22m's default with[0m
       [40myour own preferences.[0m

       [4m[40m11.2[24m  [4mScan[24m [4mthe[24m [4mCommand[24m [4mLine[0m

       [40mThe command line is scanned as defined in chapter 3.[0m

       [4m[40m11.3[24m  [4mLocate[24m [4mthe[24m [4mCookbook[0m

       [40mThe current directory is scanned for  the  cookbook.   Names[0m
       [40mwhich a cookbook may have include[0m

                 [40mhowto.cook    Howto.cook    .howto.cook[0m
                 [40mhow.to.cook   How.to.cook   .how.to.cook[0m
                  [40mcookfile      Cookfile       .cookrc[0m
                  [40mcook.file     Cook.file      .cook.rc[0m
       [40mThe  first so named file found in the current directory will[0m
       [40mbe used.  The order of  search  is  not  defined.   You  are[0m
       [40mstrongly advised to have just [4mone[24m of these name forms in any[0m
       [40mdirectory.  The name [4mHowto.cook[24m is the preferred form.[0m

       [4m[40m11.4[24m  [4mForm[24m [4mthe[24m [4mListing[24m [4mFilename[0m

       [40mThe listing file, if not explicitly named in the environment[0m
       [40mvariable  or  on  the  command line, will be the name of the[0m
       [40mcookbook, with any suffix removed and '.list' appended.[0m

       [4m[40m11.5[24m  [4mCreate[24m [4mthe[24m [4mListing[24m [4mfile[0m

       [40mThe listing file is created.  If [1mcook [22mis  executing  in  the[0m
       [40mbackground,  or the [1m-NoTTy [22moption has been specified, [4mstdout[0m
       [40mand [4mstderr[24m will be redirected into  the  listing  file.   If[0m
       [1m[40mcook  [22mis  executing in the foreground, and the [1m-NoTTy [22moption[0m
       [40mhas not been specified, [4mstdout[24m and [4mstderr[24m will be redirected[0m
       [40minto  a  pipe to a [4mtee[24m(1) command; which will, in turn, copy[0m
       [40mthe output into the named file.[0m

       [40mA heading line with the name of the file and  the  date,  is[0m
       [40mgenerated.[0m


       
       Peter Miller                                        Page 103





       Cook                                              User Guide



       [40m[4m11.6[24m  [4mScan[24m [4mthe[24m [4mCookbook[0m

       [40mWhen  [1mcook  [22mreads  the  cookbook  it  evaluates  all  of the[0m
       [40mstatements  it  finds  in  it.   Usually  these   statements[0m
       [40minstantiate recipes, although other things are possible.[0m

       [40mRecipes   contain   statements   that   are   not  evaluated[0m
       [40mimmediately, but which are remembered  for  later  execution[0m
       [40mwhen cooking a target.  The meaning of a cookbook is defined[0m
       [40min chapter X.[0m

       [4m[40m11.7[24m  [4mDetermine[24m [4mtargets[24m [4mto[24m [4mcook[0m

       [40mIf no target files  are  named  on  the  command  line,  the[0m
       [40mtargets of the first defined explicit or ingredients recipe.[0m
       [40mIt is an error if this is none.[0m

       [4m[40m11.8[24m  [4mCooking[24m [4ma[24m [4mTarget[0m

       [40mA derivation graph is formed using all of the targets given.[0m
       [40mOnce  the  derivation  graph  is  formed, it will be walked,[0m
       [40mlooking for files which are out of date.[0m

       [40mTo build  the  derivation  graph  for  a  target,  each  the[0m
       [40mfollowing steps is performed in the order given:[0m

         [40m1.  [1mCook  [22mexploits  knowledge of the derivation graph that[0m
             [40mthe user may provide to it:[0m

                [40m+o If the [4mgraph_exterior_file[24m variable is  set,  and[0m
                  [40mthe  file name is listed in it, the file is not a[0m
                  [40mleaf, and the derivation will backtrack  and  try[0m
                  [40manother alternative.[0m

                [40m+o If  the  [4mgraph_exterior_pattern[24m  variable is set,[0m
                  [40mand the file name matches  one  of  the  patterns[0m
                  [40mlisted  in  it,  the  file is not a leaf, and the[0m
                  [40mderivation  will  backtrack   and   try   another[0m
                  [40malternative.[0m

                [40m+o If  the  [4mgraph_leaf_file[24m variable is set, and the[0m
                  [40mfile name is listed in it, the  file  is  a  leaf[0m
                  [40mfile  of  the  derivation.   There  is no need to[0m
                  [40mattempt to apply any  recipes.   It  will  be  an[0m
                  [40merror if the file does not exist.[0m

                [40m+o If  the  [4mgraph_leaf_pattern[24m  variable is set, and[0m
                  [40mthe file name matches one of the patterns  listed[0m
                  [40min it, the file is a leaf file of the derivation.[0m
                  [40mThere is no need to attempt to apply any recipes.[0m
                  [40mIt will be an error if the file does not exist.[0m
             [40mThese  optimizations  require  an accurate source file[0m
             [40mmanifest, but can result  is  substantial  performance[0m
             [40mimprovements.[0m

       
       Peter Miller                                        Page 104





       Cook                                              User Guide



       [40m  2.  [1mCook   [22mscans   through  the  instantiated  ingredients[0m
             [40mrecipes  in  the  order  they   were   defined.    All[0m
             [40mingredients  recipes  with  the target in their target[0m
             [40mlist are used.[0m

             [40mIf a recipe is used, then any  ingredients  also  have[0m
             [40mtheir  derivation graph constructed.  When walking the[0m
             [40mgraph, if any of the ingredients are younger than  the[0m
             [40mtarget,  all  other  explicit or implicit recipes with[0m
             [40mthe same target will be deemed to be out of date.10[0m

         [40m3.  [1mCook [22mthen  scans  through  the  instantiated  explicit[0m
             [40mrecipes  in the order they were defined.  All explicit[0m
             [40mrecipes with the target in their target list are used.[0m

             [40mIf a recipe is a used, the ingredients also have their[0m
             [40mderivation graph constructed.  When walking the graph,[0m
             [40mif any ingredients are out of date or the target  does[0m
             [40mnot  yet  exist  (or  the  "forced" flag is set in the[0m
             [40mrecipe's  [4mset[24m  clause)  the  recipe   body   will   be[0m
             [40mperformed.   If  a  recipe has no ingredients, it will[0m
             [40mnot be performed,  unless  the  target  does  not  yet[0m
             [40mexist, or it is forced.[0m

         [40m4.  If  the  target  was  not  in  the  target list of any[0m
             [40mexplicit recipe,  [1mcook  [22mthen  scans  the  instantiated[0m
             [40mimplicit  recipes  in  the order they were defined, in[0m
             [40mtwo passes.   Implicit  recipes  which  not  not  have[0m
             [40mpattern  elements  in  the basename of the targets are[0m
             [40mscanned before implicit recipes which do have patterns[0m
             [40min  the  basename.   Usually  this  has no significant[0m
             [40meffect, however in heavily heterogeneous  builds  this[0m
             [40mmethod  is  often  used in constructing the dependency[0m
             [40mfiles, so that  all  architectures  may  use  the  one[0m
             [40mimplicit  dependency recipe, rather than stating every[0m
             [40marchitecture explicitly.  Within each pass, the  order[0m
             [40mof scan is the order of definition.[0m

             [40mImplicit  recipe targets and ingredients may contain a[0m
             [40mwildcard  character  ([1m%[22m),  which  is  why   they   are[0m
             [40mimplicit.   When  expressions  are evaluated into word[0m
             [40mlists in an implicit recipe, any word  containing  the[0m
             [40mwildcard  character  ([1m%[22m)  will  be expanded out by the[0m
             [40mcurrent wildcard expansion.[0m

             [40mIf the target matches a pattern in the targets  of  an[0m
             [40mimplicit  recipe,  it is a candidate.  Each ingredient[0m
             [40mof a candidate recipe is recursively cooked.   If  any[0m
             [40mingredient  cannot be cooked, then the implicit recipe[0m

       ____________________

       10.A target which does not exist yet  is  considered  to  be
          infinitely  ancient,  and thus everything is younger than
          it.

       Peter Miller                                        Page 105





       Cook                                              User Guide



       [40m      is not used.  If all ingredients can be  cooked,  then[0m
             [40mthe implicit recipe is used.[0m

             [40mIf   an   implicit   recipe  is  a  used,  the  forced[0m
             [40mingredients   also   have   their   derivation   graph[0m
             [40mconstructed.   It  is  an error if a forced ingredient[0m
             [40mcannot be constructed.[0m

             [40mOnly the first implicit recipe to get to this point is[0m
             [40mused.  The scan stops at this point.[0m

         [40m5.  If the target is not the subject of any ingredients or[0m
             [40mexplicit  recipe,  and  no  implicit  recipes  can  be[0m
             [40mapplied,  then  several  derivations are attempted, in[0m
             [40mthe order specified:[0m

                [40m+o If the [4mgraph_interior_file[24m variable is  set,  and[0m
                  [40mthe  file name is listed in it, the file is a not[0m
                  [40mleaf file of the derivation.  Cook will backtrack[0m
                  [40mand try another alternative.[0m

                [40m+o If  the  [4mgraph_interior_pattern[24m  variable is set,[0m
                  [40mand the file name matches  one  of  the  patterns[0m
                  [40mlisted  in it, the file is a not leaf file of the[0m
                  [40mderivation.  Cook will backtrack and try  another[0m
                  [40malternative.[0m

                [40m+o If  the  [4mgraph_leaf_file[24m variable is set, and the[0m
                  [40mfile name is listed in it, the  file  is  a  leaf[0m
                  [40mfile  of  the derivation.  It will be an error if[0m
                  [40mthe file does not exist.[0m

                [40m+o If the [4mgraph_leaf_pattern[24m variable  is  set,  and[0m
                  [40mthe  file name matches one of the patterns listed[0m
                  [40min it, the file is a leaf file of the derivation.[0m
                  [40mIt will be an error if the file does not exist.[0m

                [40m+o If    either    of    the    [4mgraph_leaf_file[24m   or[0m
                  [4m[40mgraph_leaf_pattern[24m variables are  set,  then  the[0m
                  [40mfile  is  not  a  leaf,  and  the derivation will[0m
                  [40mbacktrack and try another alternative.[0m

                [40m+o If the file exists, then it is up  to  date,  and[0m
                  [40mthe file is a leaf file of the derivation.[0m

                [40m+o If the file does not exist then [1mCook [22mdoesn't know[0m
                  [40mhow, and the derivation will  backtrack  and  try[0m
                  [40manother alternative.[0m

       [40mIf  a  command in the body of any recipe fail, [1mcook [22mwill not[0m
       [40mthat body any further, and will not perform the body of  any[0m
       [40mrecipe  for  which  the  target of the failed actions was an[0m
       [40mingredient, directly or indirectly.[0m


       
       Peter Miller                                        Page 106





       Cook                                              User Guide



       [40m[1mCook [22mwill trap recursive looping of targets.[0m

          [40m+o If the file exists, the it is up to date, or[0m

          [40m+o If the file does not exist then [1mcook [22mdoesn't know how.[0m

       [4m[40m11.9[24m  [4mThe[24m [4mDependency[24m [4mGraph[0m

       [40mThe above section describes how Cook derives the  dependency[0m
       [40mgraph.   Once  the  dependency graph has been derived, it is[0m
       [40mthen walked.  The next section describes a little about  how[0m
       [40mCook walks the dependency graph.[0m

       [40mCook  is  a simple kind of expert system.  You give it a set[0m
       [40mof of recipes for how to construct things, and a  target  to[0m
       [40mbe  constructed.   The  recipes can be decomposed into pair-[0m
       [40mwise ordered dependencies between files.[0m

       [40mCook determines how to build the target  by  constructing  a[0m
       [4m[40mdirected[24m  [4macyclic[24m [4mgraph[24m.  The vertexes of this graph are the[0m
       [40mfiles in the system, the edges in this graph are the  inter-[0m
       [40mfile  dependencies.   The  edges  of  the graph are directed[0m
       [40mbecause the pair-wise dependencies are ordered resulting  in[0m
       [40ma  [4macyclic[24m graph - things which look like loops are resolved[0m
       [40mby the direction of the edges.[0m

       [40mFor example, if you have a simple cookbook (with the  recipe[0m
       [40mbodies omitted for simplicity) like this:[0m
            [40mprogram: one.o two.o;[0m
            [40mone.o: one.c one.h;[0m
            [40mtwo.o: two.c two.h one.h;[0m
       [40mhere is the corresponding directed acyclic graph.[0m
       [40m[0m

                                 [40mprogram[0m
                                 [40m+-    -+[0m


                        [40mone.o             +-two.o[0m
                        [40m|    -+             |    -+[0m
                        [40m+                   +[0m


                   [40mone.c     one.h     two.c     two.h[0m



       [40mThere  are  several  things  that can be done with the graph[0m
       [40monce it has been derived:[0m
       [40m* It can be walked to verify and regenerate the  referential[0m
       [40mintegrity of the files (the usual case), or[0m
       [40m*  it  can  walked  to print the pair-wise dependencies (the[0m
       [40m-pairs option), or[0m
       [40m* it can be walked to generate a shell script  (the  -script[0m

       
       Peter Miller                                        Page 107





       Cook                                              User Guide



       [40moption)  which  does  something  very  similar  to the first[0m
       [40moption.[0m

       [4m[40m11.9.1[24m  [4mEdge[24m [4mTypes[0m
       [40mEach of the arrows in the above graph have a specific type.[0m

       [4m[40mstrict[24m edges mean that Cook will decide  that  a  target  is[0m
             [40mout-of-date  if its time stamp is not strictly younger[0m
             [40mthan all of the ingredients.  This  is  almost  always[0m
             [40mwhat you want.[0m

       [4m[40mweak[24m  edges mean that Cook will decide that a target is out-[0m
             [40mof-date if its time stamp is older  than  any  of  the[0m
             [40mingredients.   This means that the times stamps of the[0m
             [40mtarget and ingredients may be equal - this  is  useful[0m
             [40mfor  hard links and symbolic links.  You specify edges[0m
             [40mof this type by appending the ``(weak)'' string to the[0m
             [40mname of the ingredient.[0m

       [4m[40mexists[24m edges  mean that Cook will arrange for the ingredient[0m
             [40mto be cooked before the recipe is run,  but  the  time[0m
             [40mstamp  [4mis[24m  [4mnot[24m  [4mconsulted[24m.  The ingredient cannot ever[0m
             [40mmake the target  out-of-date.   This  is  useful  form[0m
             [40mcoping with version stamps which change often, but you[0m
             [40mdon't want to re-link unless something  else  changes.[0m
             [40mYou  specify  edges  of  this  type  by  appending the[0m
             [40m``(exists)'' string to the name of the ingredient.[0m
       [40mThe default edge type is ``[4mstrict[24m''.  You can use the "time-[0m
       [40madjust" setting (see the "set" command) to make this simpler[0m
       [40mon very fast machines.[0m

       [4m[40m11.10[24m  [4mFile[24m [4mStatus[0m

       [1m[40mCook [22mdetermines the time a file was last modified by  asking[0m
       [40mthe  operating  system.   Because this operation tends to be[0m
       [40mperformed  frequently,  [1mcook  [22mmaintains  a  cache  of   this[0m
       [40minformation,   rather  than  make  redundant  calls  to  the[0m
       [40moperating system.  Because this information is cached, it is[0m
       [40mpossible for [1mcook[22m's memory of a file's last-modified time to[0m
       [40mbecome inconsistent with  the  file's  actual  last-modified[0m
       [40mtime.   In particular, [1mcook [22mdoe [4mnot[24m ask the operating system[0m
       [40mfor the "new" last-modified time of a recipe target  once  a[0m
       [40mrecipe  body is completed.  Careful use of the set clearstat[0m
       [40mclause  will  generally  prevent  this.   For  example,  the[0m
       [40mfollowing  recipe  needs  to create a directory when writing[0m
       [40mits output:[0m
            [40mbin/%: [%_obj][0m
            [40m{[0m
                    [40mif [not [exists bin]] then[0m
                            [40mmkdir bin;[0m
                    [40m[cc] -o [target] [need];[0m
            [40m}[0m
       [40mIf there were several programs being  cooked,  e.g.  [4mbin/foo[0m
       [40mand  [4mbin/bar[24m,  the second time [1mcook [22mperformed the recipe, it[0m

       
       Peter Miller                                        Page 108





       Cook                                              User Guide



       [40mwould erroneously attempt to make the [4mbin[24m directory a second[0m
       [40mtime  -  contrary to the test.  This is because [4m[exists[24m [4mbin][0m
       [40mused the cache, and nothing tells [1mcook [22mthat the cache is now[0m
       [40mwrong.  The recipe should have been written[0m
            [40mbin/%: [%_obj][0m
            [40m{[0m
                    [40mif [not [exists bin]] then[0m
                            [40mmkdir bin[0m
                                    [40mset clearstat;[0m
                    [40m[cc] -o [target] [need];[0m
            [40m}[0m
       [40mwhich  tells  [1mcook  [22mthat it should remove any files named in[0m
       [40mthe [4mmkdir[24m command from the cache.[0m

       [40mAn alternative way of performing the above example is to set[0m
       [40mthe [4mmkdir[24m recipe flag:[0m
            [40mbin/%: [%_obj][0m
                    [40mset mkdir[0m
            [40m{[0m
                    [40m[cc] -o [target] [need];[0m
            [40m}[0m
       [40mThis  flag  instructs  [1mcook  [22mto create the directory for the[0m
       [40mtarget before running the recipe body.  There is  a  similar[0m
       [4m[40munlink[24m  flag, which unlinks the targets of the recipe before[0m
       [40mrunning the recipe body.  These two flags take care of most,[0m
       [40mbut not all, uses of the [4mclearstat[24m flag.[0m

       [40mA  second  mechanism  used  by  [1mcook  [22mto determine the last-[0m
       [40mmodified times of files is a file [4mfingerprint[24m.   This  is  a[0m
       [40mcryptographically  strong  hash  of  the contents of a file.[0m
       [40mThe  chances  of  two  different  files  having   the   same[0m
       [40mfingerprint  is less than 1 in 2**200.  If [1mcook [22mnotices that[0m
       [40ma file has  changed,  because  its  last-modified  time  has[0m
       [40mchanged,  a  fingerprint  is  taken of the file and compared[0m
       [40mwith  the  remembered  fingerprint.   If  the   fingerprints[0m
       [40mdiffer,  the  file  is  considered  to be different.  If the[0m
       [40mfingerprints match, the  file  is  considered  not  to  have[0m
       [40mchanged.[0m

       [40mThis description of fingerprints is somewhat simplified, the[0m
       [40mactual mechanics depends on remembering two different  last-[0m
       [40mmodified times, as well as the fingerprint, in a file called[0m
       [4m[40m.cook.fp[24m in the current directory.[0m

       [40mFingerprinting can cause some surprises.  For example,  when[0m
       [40myou  use  the  [4mtouch[24m(1)  command, [1mcook [22mwill often fail to do[0m
       [40manything, and report instead that everything is  up-to-date.[0m
       [40mThis  is  because  the fingerprint has not changed.  In this[0m
       [40msituation, either remove  the  [4m.cook.fp[24m  file,  or  use  the[0m
       [1m[40m-No_FingerPrint [22mcommand line option.[0m





       
       Peter Miller                                        Page 109





       Cook                                              User Guide



       [40m[4m12.[24m  [4mOption[24m [4mPrecedence[0m

       [40mAt  various  points in the description there are a number of[0m
       [40mflags and options with the same, or similar,  names.   These[0m
       [40mare in fact different levels of the same option.[0m

       [40mThe different levels, from highest precedence to lowest, are[0m
       [40mas follows.[0m

       [40mError     This level is used  to  disable  undesirable  side[0m
                 [40meffects when an error occurs.[0m

       [40mCommand Line Options  specified on the command line override[0m
                 [40malmost everything.  There are some isolated  cases[0m
                 [40mwhere  there is no equivalent command line option.[0m
                 [40mThey are in scope for the entire [1mcook [22msession.[0m

       [40mExecute   When a command attached to a recipe  is  executed,[0m
                 [40mthe  flags  in  the  '[1mset[22m'  clause  are given this[0m
                 [40mprecedence.  They are in scope for the duration of[0m
                 [40mthe execution of the command they are bound to.[0m

       [40mRecipe    When  a recipe is considered for use, the flags in[0m
                 [40mthe '[1mset[22m' clause are given the  precedence.   They[0m
                 [40mare in scope for the evaluation of the ingredients[0m
                 [40mnames and the execution of the recipe  body;  they[0m
                 [40mare not in scope while cooking the ingredients.[0m

       [40mCookbook  When  a  '[1mset[22m'  statement  is  encountered  in the[0m
                 [40mcookbook, the  option  are  given  this  priority.[0m
                 [40mThey  are  in  scope  until  the  end  of the [1mcook[0m
                 [40msession.[0m

       [40mEnvironment Variable[0m
                 [40mWhen the  options in the [1mCOOK [22menvironment variable[0m
                 [40mare set, they are given this precedence.  They are[0m
                 [40min scope for the entire [1mcook [22msession.[0m

       [40mDefault   All options have a default setting.  The  defaults[0m
                 [40mnoted  in  chapter  3  are  given this precedence.[0m
                 [40mThey are in scope for the entire [1mcook [22msession.[0m














       
       Peter Miller                                        Page 110





       Cook                                              User Guide



       [40m[4m13.[24m  [4mFile[24m [4mname[24m [4mpatterns[0m

       [40mThere are two pattern matchers to choose from.[0m

       [40mThe  tough  part  about  designing  a  pattern  matcher  for[0m
       [40msomething  like  Cook  is  that [4mideally[24m the patterns must be[0m
       [40mreversible.  That is, it must be possible to  use  the  same[0m
       [40mstring  both  as  a  pattern  to be matched against and as a[0m
       [40mtemplate for building a string once a pattern  has  matched.[0m
       [40mRather  like the difference between the left and right sides[0m
       [40mof an editor search-and-replace command in an  editor  using[0m
       [40mthe  same  description  for  both the search pattern and the[0m
       [40mreplace template.  This is why classic  regular  expressions[0m
       [40mare not the default.[0m

       [40mThe  choice  of  which pattern matcher to use is dictated by[0m
       [40mflag settings:[0m

       [40mset match-mode-cook[0m
            [40mThis causes patterns to be matched using Cook's  native[0m
            [40mpatterns.  This is the default.[0m

       [40mset match-mode-regex[0m
            [40mThis  causes  patterns  to  be  matched  using  regular[0m
            [40mexpressions.[0m

       [40mThe match mode to use may be set at the cookbook level[0m
            [40mset match-mode-cook;[0m
       [40mor at the recipe level[0m
            [40m%.o: %.c[0m
                    [40mset match-mode-cook[0m
            [40m{[0m
                    [40m[cc] -o %.o -c %.c;[0m
            [40m}[0m
       [40mif you want to change your mind temporarily.[0m

       [40mThe match mode also affects match functions, such as [4mfilter[24m,[0m
       [4m[40mfilter_out[24m,  [4mfromto[24m,  [4mmatch_mask[24m,  [4mmatches[24m and [4mpatsubst[24m.  If[0m
       [40myou use these in your user-defined functions, you need to be[0m
       [40mextra careful about this.[0m

       [40mThe  match  mode  also  affects the graph variables, used to[0m
       [40mspecify explicit graph interior and leaf files.[0m

       [4m[40m13.1[24m  [4mCook[24m [4mPatterns[0m

       [40mThe native Cook pattern matcher has symmetric left-hand-side[0m
       [40mand  right-hand-side  patterns.   This  is best demonstrated[0m
       [40mwith an example recipe:[0m
            [40m%.c %.h: %.y[0m
                    [40mset match-mode-cook[0m
            [40m{[0m
                    [40myacc -d %.y;[0m
                    [40mmv yy.tab.c %.c;[0m

       
       Peter Miller                                        Page 111





       Cook                                              User Guide



       [40m             mv yy.tab.h %.h;[0m
            [40m}[0m
       [40mNotice how the left-hand-side of the  recipe  (the  targets)[0m
       [40muses  the same style of patterns as the right-hand-side (the[0m
       [40mingredients and the recipe body).[0m

       [40mThis matcher has eleven match "fields", referenced as [1m%  [22mand[0m
       [1m[40m%0  [22mto [1m%9[22m.  The [1m% [22mcharacter can be escaped as [1m%%[22m.  The [1m% [22mand[0m
       [1m[40m%1 [22mto [1m%9 [22mforms match any character except slash  ([1m/[22m);  these[0m
       [40mforms  may  not  match  a  leading  empty  string,  to avoid[0m
       [40mproblems with false matches against absolute paths.  The  [1m%0[0m
       [40mform  matches  all  characters, but must be either empty, or[0m
       [40mhave whole path components, including the trailing [1m/ [22mon each[0m
       [40mcomponent.[0m

       [40mA few examples will make this clearer:[0m

                        [40m+-------------------------+[0m
                        [40m|string    does not match |[0m
                        [40m+-------------------------+[0m
                        [40m|%.c       snot/fred.c    |[0m
                        [40m|%1/%2.c   etc/boo/fred.c |[0m
                        [40m+-------------------------+[0m
       [40m+---------------------------------------------------------------+[0m
       [40m|string                 matches                 setting         |[0m
       [40m+---------------------------------------------------------------+[0m
       [40m|%.c                    fred.c                  %="fred"        |[0m
       [40m|%1/%2.c                snot/fred.c             %1="snot"       |[0m
       [40m|                                               %2="fred"       |[0m
       [40m|%0%5.c                 fred.c                  %0=""           |[0m
       [40m|                                               %5="fred"       |[0m
       [40m|%0%6.c                 snot/fred.c             %0="snot/"      |[0m
       [40m|                                               %6="fred"       |[0m
       [40m|%0%7.c                 etc/boo/fred.c          %0="etc/boo/"   |[0m
       [40m|                                               %7="fred"       |[0m
       [40m|/usr/%1/%1%2/%3.%2%4   /usr/man/man1/fred.1x   %1="man"        |[0m
       [40m|                                               %2="1"          |[0m
       [40m|                                               %3="fred"       |[0m
       [40m|                                               %4="x"          |[0m
       [40m+---------------------------------------------------------------+[0m
       [40mThe  [1m%0 [22mbehavior is designed to allow patterns to range over[0m
       [40msubtrees in a controlled manner.  Note that the use of  this[0m
       [40msort  of  pattern in a recipe will result in deeper searches[0m
       [40mthan the naive recipe designer would expect.[0m

       [4m[40m13.1.1[24m  [4mExamples[0m
       [40mThere are two main places where patterns are used: with  the[0m
       [4m[40mmatch_mask[24m and [4mfromto[24m functions, and in recipes.[0m

       [40mYou  can  perform  file  name  filtering  and  rewriting  as[0m
       [40mfollows:[0m
            [40msource_files = [collect cat MANIFEST];[0m
            [40mobject_files =[0m
                    [40m[fromto %0%.c %0%.o [match_mask %0%.c [manifest]]][0m

       
       Peter Miller                                        Page 112





       Cook                                              User Guide



       [40m             [fromto %0%.y %0%.gen.o [match_mask %0%.y [manifest]]][0m
                    [40m;[0m

       [40mThe recipes to go with the above files may be[0m
            [40m%0%.o: %0%.c[0m
                    [40msingle-thread ["if" %0 "then" %.o][0m
            [40m{[0m
                    [40m/* note: no slash before dot */[0m
                    [40mcc -c -I%0. %0%.c;[0m
                    [40mif %0 then[0m
                            [40mmv %.o %0%.o;[0m
            [40m}[0m
       [40mThis recipe can compile files  in  a  large  project,  where[0m
       [40msource  files  appear  in  a number of sub-directories.  The[0m
       [40m``-I%0.'' ensures that there are locally include-able  files[0m
       [40min  the  sub-directories.   If  the ``%0'' had been entirely[0m
       [40momitted from the recipe, it will only compile files  in  the[0m
       [40mcurrent directory.[0m

       [40mA  common [4myacc[24m recipe, used when there is more than one yacc[0m
       [40mgrammar in a project, looks like this:[0m
            [40m%0%.gen.c %0%.gen.h: %0%.y[0m
                    [40msingle-thread yy.tab.c yy.tab.h[0m
            [40m{[0m
                    [40myacc -d %0%.y[0m
                    [40myy = [collect echo %0% | sed "'s/[^A-Za-z0-9]/_/'"];[0m
                    [40msed "'s/[yY][yY]/"[yy]"_/g'" yy.tab.c > %0%.gen.c;[0m
                    [40msed "'s/[yY][yY]/"[yy]"_/g'" yy.tab.h > %0%.gen.h;[0m
                    [40mrm yy.tab.c yy.tab.h;[0m
            [40m}[0m
       [40mTo be more selective about  the  ``%0''  portion,  use  more[0m
       [40mpattern elements before or after it.[0m

       [4m[40m13.2[24m  [4mRegular[24m [4mExpressions[0m

       [40mThe  regular  expression  pattern matcher uses POSIX regular[0m
       [40mexpressions.  It has asymmetric  left-hand-side  and  right-[0m
       [40mhand-side  patterns.   This  is  best  demonstrated  with an[0m
       [40mexample recipe:[0m
            [40m\\(.*\\)\\.c \\(.*\\)\\.h: \\1.y[0m
                    [40mset match-mode-regex[0m
            [40m{[0m
                    [40myacc -d \\1.y;[0m
                    [40mmv yy.tab.c \\1.c;[0m
                    [40mmv yy.tab.h \\1.h;[0m
            [40m}[0m
       [40mNotice how the left-hand-side of the  recipe  (the  targets)[0m
       [40muses  a completely different style of patterns as the right-[0m
       [40mhand-side (the ingredients and the recipe body).[0m

       [40mAll those backslashes are necessary, because Cook  uniformly[0m
       [40mapplies  C  escapes  to  strings  when it reads them, and it[0m
       [40mdoesn't know you mean a regular expression  backslash  until[0m
       [40myou use it in a recipe context.[0m

       
       Peter Miller                                        Page 113





       Cook                                              User Guide



       [40mSee  [4mre_format[24m(7)  for  a definition of POSIX 1003.2 regular[0m
       [40mexpressions; you want the ``basic'' REs.[0m

       [40mPlease note that characters which are special to  Cook  will[0m
       [40mneed  to be escaped with a backslash, or enclosed in quotes.[0m
       [40mThese  include  curly  braces  (``{''  and  ``}''),   square[0m
       [40mbrackets   (``[''  and  ``]''),  colon  (``:'')  and  equals[0m
       [40m(``='').  Backslash always  needs  to  be  escaped,  whether[0m
       [40mencoded  in  a  string  or  not,  because within a string it[0m
       [40mserves to escape the string terminator.[0m

       [40mYou also need to remember  that  dot  (``.'')  is  a  common[0m
       [40mcharacter  in  filenames, and frequently significant in file[0m
       [40mname patters, but it is a regular expression wildcard.   You[0m
       [40mneed to escape it to make it literal.[0m

       [40mYou  need  to make absolutely certain that when recipes have[0m
       [40mmore than one left-hand-size (as in the yacc  example)  that[0m
       [40mthe  patterns  [4mall[24m  assign  identical values to their nested[0m
       [40msub-expressions.[0m

       [40mThe usual right-hand-side  replacements  are  available:  an[0m
       [40mescaped  number  is  replaced  with  the  [4mn[24m-th  nested  sub-[0m
       [40mexpression; and the ampersand (``&'')  is  replaced  by  the[0m
       [40mwhole  left-hand-side  (if you have more than one left-hand-[0m
       [40mside, this is ambiguous).  Backslash may be used  to  escape[0m
       [40mthem.[0m

       [4m[40m13.2.1[24m  [4mExamples[0m
       [40mThere  are two main places where patterns are used: with the[0m
       [4m[40mmatch_mask[24m and [4mfromto[24m functions, and in recipes.[0m

       [40mYou  can  perform  file  name  filtering  and  rewriting  as[0m
       [40mfollows:[0m
            [40mset match-mode-regex;[0m
            [40msource_files = [collect cat MANIFEST];[0m
            [40mobject_files =[0m
                    [40m[fromto \\(.*\\)\\.c \\1.o[0m
                            [40m[match_mask \\(.*\\)\\.c [manifest]]][0m
                    [40m[fromto \\(.*\\)\\.y \\1.gen.o[0m
                            [40m[match_mask \\(.*\\)\\.y [manifest]]][0m
                    [40m;[0m

       [40mThe recipes to go with the above files may be[0m
            [40m\\(.*\\)\\.o: \\1.c[0m
                    [40msingle-thread ["if" [not [in [relative_dirname \\1] .]][0m
                            [40m"then" [notdir \\1.o]][0m
            [40m{[0m
                    [40mcc -c -I[[relative_dirname \\1] \\1.c;[0m
                    [40mif [not [in [relative_dirname \\1] .]] then[0m
                            [40mmv [notdir \\1.o] \\1.o;[0m
            [40m}[0m
       [40mThis  recipe  can  compile  files  in a large project, where[0m
       [40msource files appear in a  number  of  sub-directories.   The[0m

       
       Peter Miller                                        Page 114





       Cook                                              User Guide



       [40m``-I\\1.'' ensures that there are locally include-able files[0m
       [40min the sub-directories.[0m

       [40mA common [4myacc[24m recipe, used when there is more than one  yacc[0m
       [40mgrammar in a project, looks like this:[0m
            [40m\\(.*\\)\\.gen.c \\(.*\\)\\.gen.h: \\1.y[0m
                    [40msingle-thread yy.tab.c yy.tab.h[0m
            [40m{[0m
                    [40myacc -d \\1.y[0m
                    [40myy = [collect echo \\1 | sed "'s/[^A-Za-z0-9]/_/'"];[0m
                    [40msed "'s/[yY][yY]/"[yy]"_/g'" yy.tab.c > \\1.gen.c;[0m
                    [40msed "'s/[yY][yY]/"[yy]"_/g'" yy.tab.h > \\1.gen.h;[0m
                    [40mrm yy.tab.c yy.tab.h;[0m
            [40m}[0m
       [40mTo  be  more  selective  about the ``\\(.*\\)'' portion, use[0m
       [40mmore pattern elements before or after it.[0m







































       
       Peter Miller                                        Page 115





       Cook                                              User Guide



       [40m[4m14.[24m  [4mSupplied[24m [4mCookbooks[0m

       [40mA number of cookbooks are supplied with [1mcook[22m.  To  make  use[0m
       [40mof one, a preprocessor directive of the form[0m
            [40m#include "[4mwhichone[24m"[0m
       [40mmust appear at the start of your cookbook.[0m

       [1m[40mCook  [22mdoes not have any "built-in" recipes.  All recipes are[0m
       [40mstored  in  text  files,  so  they  are  more  easily  read,[0m
       [40munderstood,  copied,  hacked  or  corrected.   The  supplied[0m
       [40mcookbooks live in the [4m${prefix}/share/cook[24m directory.[0m

       [40mYou  may  supply  your  own  "system"  recipes,  by  placing[0m
       [40mcookbooks  into  a directory called [4m$HOME/.cook[24m or using the[0m
       [1m[40m-Include  [22mcommand  line  option,  possibly  in  your   [4m$COOK[0m
       [40menvironment variable.[0m

       [4m[40m14.1[24m  [4mas[0m

       [40mThis cookbook defines how to use the assembler.[0m

       [4m[40m14.1.1[24m  [4mrecipes[0m

       [40m%.o: %.s  Construct   object  files  from  assembler  source[0m
                 [40mfiles.[0m

       [4m[40m14.1.2[24m  [4mvariables[0m

       [40mas        The assembler command.   Not  altered  if  already[0m
                 [40mdefined.[0m

       [40mas_flags  Options   to  pass  the  assembler  command.   Not[0m
                 [40maltered if already defined.  The default is empty.[0m

       [40mas_src    Assembler source files in the current directory.[0m

       [40mdot_src   Source  files   constructable   in   the   current[0m
                 [40mdirectory   (unioned  with  existing  setting,  if[0m
                 [40mnecessary).[0m

       [40mdot_obj   Object  files   constructable   in   the   current[0m
                 [40mdirectory   (unioned  with  existing  setting,  if[0m
                 [40mnecessary).[0m

       [40mdot_clean Files  which  may  be  removed  from  the  current[0m
                 [40mdirectory in a clean target.[0m









       
       Peter Miller                                        Page 116





       Cook                                              User Guide



       [40m[4m14.2[24m  [4mc[0m

       [40mThis  cookbook  describes how to work with C files.  Include[0m
       [40mfile dependencies are automatically determined.[0m

       [4m[40m14.2.1[24m  [4mrecipes[0m

       [40m%.o: %.c  Construct object files form C source  files,  with[0m
                 [40mautomatic include file dependency detection.[0m

       [40m%.ln: %.c Construct  lint  object files from C source files,[0m
                 [40mwith automatic include file dependency detection.[0m

       [4m[40m14.2.2[24m  [4mvariables[0m

       [40mc_incl    The C include  dependency  sniffer  command.   Not[0m
                 [40maltered if already defined.[0m

       [40mcc        The  C  compiler  command.  Not altered if already[0m
                 [40mdefined.[0m

       [40mlint      The lint command.  Not altered if already defined.[0m

       [40mcc_flags  Options to pass to the C  compiler  command.   Not[0m
                 [40maltered if already defined.  The default is "-O".[0m

       [40mcc_include_flags Options passed to the C compiler and c_incl[0m
                 [40mcontrolling include file searching.   Not  altered[0m
                 [40mif already defined.  The default is empty.[0m

       [40mcc_src    C source files in the current directory.[0m

       [40mdot_src   Source   files   constructable   in   the  current[0m
                 [40mdirectory  (unioned  with  existing  setting,   if[0m
                 [40mnecessary).[0m

       [40mdot_obj   Object   files   constructable   in   the  current[0m
                 [40mdirectory  (unioned  with  existing  setting,   if[0m
                 [40mnecessary).[0m

       [40mdot_clean Files  which  may  be  removed  from  the  current[0m
                 [40mdirectory in a clean target.[0m

       [40mdot_lint_obj Lint object files constructable in the  current[0m
                 [40mdirectory   (unioned  with  existing  setting,  if[0m
                 [40mnecessary).[0m

       [4m[40m14.2.3[24m  [4mSee[24m [4mAlso[0m
       [40mThe ``library'' cookbook,  for  linking  C  sources  into  a[0m
       [40mlibrary.[0m
       [40mThe  ``program''  cookbook,  for  linking  C  sources into a[0m
       [40mprogram.[0m



       
       Peter Miller                                        Page 117





       Cook                                              User Guide



       [40m[4m14.3[24m  [4mf77[0m

       [40mThis cookbook describes how to work with Fortran files.[0m

       [4m[40m14.3.1[24m  [4mrecipes[0m

       [40m%.o: %.f77 Construct object files form Fortran source files.[0m

       [4m[40m14.3.2[24m  [4mvariables[0m

       [40mf77       The Fortran  compiler  command.   Not  altered  if[0m
                 [40malready defined.[0m

       [40mf77_flags Options  to  pass to the Fortran compiler command.[0m
                 [40mNot altered if already defined.   The  default  is[0m
                 [40m"-O".[0m

       [40mf77_src   Fortran source files in the current directory.[0m

       [40mdot_src   Source   files   constructable   in   the  current[0m
                 [40mdirectory  (unioned  with  existing  setting,   if[0m
                 [40mnecessary).[0m

       [40mdot_obj   Object   files   constructable   in   the  current[0m
                 [40mdirectory  (unioned  with  existing  setting,   if[0m
                 [40mnecessary).[0m

       [40mdot_clean Files  which  may  be  removed  from  the  current[0m
                 [40mdirectory in a clean target.[0m

       [4m[40m14.3.3[24m  [4mSee[24m [4mAlso[0m
       [40mThe ``library'' cookbook, for linking Fortran sources into a[0m
       [40mlibrary.[0m
       [40mThe ``program'' cookbook, for linking Fortran sources into a[0m
       [40mprogram.[0m

       [4m[40m14.4[24m  [4mg77[0m

       [40mThis cookbook is the same as the ``f77''  cookbook,  but  it[0m
       [40msets the [4mf77[24m variable to the GNU Fortran compiler, g77.[0m















       
       Peter Miller                                        Page 118





       Cook                                              User Guide



       [40m[4m14.5[24m  [4mgcc[0m

       [40mThis cookbook is the same as the ``c'' cookbook, but it sets[0m
       [40mthe [4mcc[24m variable to the GNU C compiler, gcc.[0m

       [4m[40m14.6[24m  [4mhome[0m

       [40mThis cookbook defined where  certain  directories  are,  and[0m
       [40msome common uses of those directories, relative to $HOME.[0m

       [4m[40m14.6.1[24m  [4mvariables[0m

       [40mhome      The current users' home directory.[0m

       [40mbin       The directory to place program binaries into.[0m

       [40minclude   The directory to place include files into.[0m

       [40mlib       The directory to place libraries into.[0m

       [40mcc_include_flags The  [include] directory is appended to the[0m
                 [40msearch options.[0m

       [40mcc_link_flags The [lib] directory is appended to the  search[0m
                 [40moptions.[0m

       [4m[40m14.7[24m  [4mlex[0m

       [40mThis cookbook describes how to work with lex files.[0m

       [4m[40m14.7.1[24m  [4mrecipes[0m

       [40m%.c: %.l  Construct C source files from lex source files.[0m

       [4m[40m14.7.2[24m  [4mvariables[0m

       [40mlex       The lex command.  Not altered if already defined.[0m

       [40mlex_flags Options  to  pass to the lex command.  Not altered[0m
                 [40mif already defined.  The default is empty.[0m

       [40mlex_src   Lex source files in the current directory.[0m

       [40mdot_src   Source  files   constructible   in   the   current[0m
                 [40mdirectory   (unioned  with  existing  setting,  if[0m
                 [40mnecessary).[0m

       [40mdot_obj   Object  files   constructible   in   the   current[0m
                 [40mdirectory   (unioned  with  existing  setting,  if[0m
                 [40mnecessary).[0m

       [40mdot_clean Files  which  may  be  removed  from  the  current[0m
                 [40mdirectory in a clean target.[0m


       
       Peter Miller                                        Page 119





       Cook                                              User Guide



       [40mdot_lint_obj Lint  object files constructible in the current[0m
                 [40mdirectory  (unioned  with  existing  setting,   if[0m
                 [40mnecessary).[0m

       [4m[40m14.8[24m  [4mlibrary[0m

       [40mThis cookbook defines how to construct a library.[0m

       [40mIf  an include file (or files) are defined for this library,[0m
       [40myou will have to append them to [install] in your [4mHowto.cook[0m
       [40mfile.[0m

       [4m[40m14.8.1[24m  [4mvariables[0m

       [40mall       targets of the all recipe[0m

       [40minstall   targets of the install recipe[0m

       [40mme        The   name  of  the  library  to  be  constructed.[0m
                 [40mDefaults to the last component of the pathname  of[0m
                 [40mthe current directory.[0m

       [40mar        The archive command.[0m

       [40minstall   targets  of  the install command.  Only defined if[0m
                 [40mthe [lib] variable is defined.[0m

       [4m[40m14.8.2[24m  [4mrecipes[0m

       [40mall       construct the targets defined in [all].[0m

       [40mclean     remove the files named in [dot_clean].[0m

       [40mclobber   remove the files name in [dot_clean] and [all].[0m

       [40minstall   Construct the  files  named  in  [install].   Only[0m
                 [40mdefined if the [lib] variable is defined.[0m

       [40muninstall Remove the files named in [install].  Only defined[0m
                 [40mif the [lib] variable is defined.[0m















       
       Peter Miller                                        Page 120





       Cook                                              User Guide



       [40m[4m14.9[24m  [4mprint[0m

       [40mThis cookbook is  used  to  print  files.   It  will  almost[0m
       [40mcertainly need to be changed for every site.[0m

       [4m[40m14.9.1[24m  [4mrecipes[0m

       [40m%.lw: %.ps Print a PostScript file.[0m

       [40m%.lp: %   Print a text file.[0m

       [4m[40m14.9.2[24m  [4mvariables[0m

       [40mlp        The   print   command.   Not  altered  if  already[0m
                 [40mdefined.[0m

       [40mlp_flags  Options passed to the print command.  Not  altered[0m
                 [40mif already defined.  Defaults to empty.[0m

       [4m[40m14.10[24m  [4mprogram[0m

       [40mThis cookbook defines how to construct a program.[0m

       [40mIf  your program uses any libraries, you will have to append[0m
       [40mthem to [ld_libraries] in your [4mHowto.cook[24m file.[0m

       [4m[40m14.10.1[24m  [4mvariables[0m

       [40mall       Targets of the all recipe.[0m

       [40minstall   targets of the install recipe[0m

       [40mld        The name of the linker command.   Not  altered  if[0m
                 [40malready  defined.   Set  to the same as the ``cc''[0m
                 [40mvariable if set, otherwise set to the same as  the[0m
                 [40m``f77'' variable if set, otherwise set to ``ld''.[0m

       [40mld_flags  Not  altered  if  already defined.  The default is[0m
                 [40mempty.[0m

       [40mld_libraries Options passed to the C compiler when  linking,[0m
                 [40mthese  are typically library search paths (-L) and[0m
                 [40mlibraries (-l).  Not altered if  already  defined.[0m
                 [40mThe default is empty.[0m

       [40mme        The   name  of  the  program  to  be  constructed.[0m
                 [40mDefaults to the last component of the pathname  of[0m
                 [40mthe current directory.[0m

       [4m[40m14.10.2[24m  [4mrecipes[0m

       [40mall       Construct the targets named in [all].[0m



       
       Peter Miller                                        Page 121





       Cook                                              User Guide



       [40mclean     Remove the files named in [dot_clean].[0m

       [40mclobber   Remove the files named in [dot_clean] and [all].[0m

       [40minstall   Construct  the  files  named  in  [install].  Only[0m
                 [40mdefined if the [lib] variable is defined.[0m

       [40muninstall Remove the files named in [install].  Only defined[0m
                 [40mif the [lib] variable is defined.[0m

       [4m[40m14.10.3[24m  [4mSee[24m [4mAlso[0m
       [40mThe ``c'' cookbook, for C sources.[0m
       [40mThe ``f77'' cookbook, for Fortran sources.[0m
       [40mThe  ``usr''  or  ``usr.local''  or  ``home'' cookbooks, for[0m
       [40mdefining install locations.[0m

       [4m[40m14.11[24m  [4mrcs[0m

       [40mThis cookbook is used to extract files from RCS.[0m

       [4m[40m14.11.1[24m  [4mrecipes[0m

       [40m%: RCS/%,v Extract files from RCS.[0m

       [40m%: %,v    Extract files from RCS.[0m

       [4m[40m14.11.2[24m  [4mvariables[0m

       [40mco        The RCS checkout command.[0m

       [40mco_flags  Flags for the co command, default to empty.[0m

       [4m[40m14.12[24m  [4mrecursive[0m

       [40mThis cookbook  may  be  used  to  construct  recursive  cook[0m
       [40mdirectory  structures,  where  the  top-level  cookbook only[0m
       [40minvokes cookbooks in deeper directories.[0m

       [40mAll targets given  to  this  cookbook  result  in  all  sub-[0m
       [40mdirectories containing a [4mHowto.cook[24m file having [1mcook [22minvoked[0m
       [40mwith the same target.[0m

       [4m[40m14.12.1[24m  [4mRecipes[0m
       [40mThe [4mall[24m recipe is defined, but  it  does  nothing,  it  only[0m
       [40mexists to set the default target name.[0m










       
       Peter Miller                                        Page 122





       Cook                                              User Guide



       [40m[4m14.13[24m  [4msccs[0m

       [40mThis cookbook is used to extract files from SCCS.[0m

       [4m[40m14.13.1[24m  [4mrecipes[0m

       [40m%: SCCS/s.% Extract files from SCCS.[0m

       [40m%: s.%    Extract files from SCCS.[0m

       [4m[40m14.13.2[24m  [4mvariables[0m

       [40mget       The SCCS get command.[0m

       [40mget_flags Flags for the get command, default to empty.[0m

       [4m[40m14.14[24m  [4mtext[0m

       [40mThis cookbook is used to process text documents.[0m

       [40mInclude  file  dependencies are automatically detected.  The[0m
       [40mrequirements for  various  preprocessors  are  automatically[0m
       [40mdetected ([4me.g.[24m eqn, tbl, pic, graf).[0m

       [4m[40m14.14.1[24m  [4mrecipes[0m

       [40m%.ps: %.t PostScript for generic *roff source.[0m

       [40m%: %.t    Straight text from *roff source.[0m

       [4m[40m14.14.2[24m  [4mvariables[0m

       [40mtext_incl The     text_incl     command    (finds    include[0m
                 [40mdependencies).  Not altered if already set.[0m

       [40mtext_roff The   text_roff   command   (finds    preprocessor[0m
                 [40mrequirements).  Not altered if already set.[0m

       [40mroff_flags Arguments  passed to text_roff, and indirectly to[0m
                 [40mthe *roff program.  Not altered  if  already  set.[0m
                 [40mDefaults to empty.[0m














       
       Peter Miller                                        Page 123





       Cook                                              User Guide



       [40m[4m14.15[24m  [4musr.local[0m

       [40mThis  cookbook  defined  where  certain directories are, and[0m
       [40msome  common  uses  of  those   directories,   relative   to[0m
       [40m/usr/local.[0m

       [4m[40m14.15.1[24m  [4mvariables[0m

       [40mbin       The directory to place program binaries into.[0m

       [40minclude   The directory to place include files into.[0m

       [40mlib       The directory to place libraries into.[0m

       [40mcc_include_flags The  [include]  directory  is  added to the[0m
                 [40msearch options.[0m

       [40mcc_link_flags The [lib] directory is  added  to  the  search[0m
                 [40moptions.[0m

       [4m[40m14.16[24m  [4musr[0m

       [40mThis   cookbook   defined  where  certain  directories  are,[0m
       [40mrelative to /usr.[0m

       [4m[40m14.16.1[24m  [4mvariables[0m

       [40mbin       The directory to place program binaries into.[0m

       [40minclude   The directory to place include files into.[0m

       [40mlib       The directory to place libraries into.[0m

       [4m[40m14.17[24m  [4myacc_many[0m

       [40mThis cookbook describes how to  use  yacc.   The  difference[0m
       [40mwith the "yacc" cookbook is that this cookbook allows you to[0m
       [40mhave more  that  one  yacc  generated  parser  in  the  same[0m
       [40mprogram, by using the classic [4msed[24m(1) hack of the output.[0m
















       
       Peter Miller                                        Page 124





       Cook                                              User Guide



       [40m[4m14.18[24m  [4myacc[0m

       [40mThis cookbook describes how to use yacc.[0m

       [40mYou  will  have  to add "-d" to the [yacc_flags] variable if[0m
       [40myou want %.h files generated.[0m

       [40mIf a [4my.output[24m file is  constructed,  it  will  be  moved  to[0m
       [4m[40m%.list[24m.[0m

       [4m[40m14.18.1[24m  [4mrecipes[0m

       [40m%.c %.h: %.y Construct  C  source and header files from yacc[0m
                 [40msource files.  Applied if -d in [yacc_flags].[0m

       [40m%.c: %.y  Construct C source files from yacc  source  files.[0m
                 [40mApplied if -d not in [yacc_flags].[0m

       [4m[40m14.18.2[24m  [4mvariables[0m

       [40myacc_src  Yacc source files in the current directory.[0m

       [40mdot_src   Source   files   constructable   in   the  current[0m
                 [40mdirectory  (unioned  with  existing  setting,   if[0m
                 [40mnecessary).[0m

       [40mdot_obj   Object   files   constructable   in   the  current[0m
                 [40mdirectory  (unioned  with  existing  setting,   if[0m
                 [40mnecessary).[0m

       [40mdot_clean Files  which  may  be  removed  from  the  current[0m
                 [40mdirectory in a clean target.[0m

       [40mdot_lint_obj Lint object files constructable in the  current[0m
                 [40mdirectory   (unioned  with  existing  setting,  if[0m
                 [40mnecessary).[0m



















       
       Peter Miller                                        Page 125





       Cook                                              User Guide



       [40m[4m15.[24m  [4mGlossary[0m

       [40mThis document employs a number of terms specific to [1mcook[22m.[0m

       [4m[40mbody[24m      A set  of  statements,  usually  commands,  to  be[0m
                 [40mperformed  to  [4mcook[24m  the [4mtarget[24ms of a [4mrecipe[24m after[0m
                 [40mthe [4mingredient[24ms exist.[0m

       [4m[40mcommand[24m   A command is a list of words to be passed  to  the[0m
                 [4m[40moperating[24m [4msystem[24m to be executed.[0m

       [4m[40mcook[24m      When  used  as  a verb, refers to the actions [1mcook[0m
                 [40mwould perform to create  a  [4mtarget[24m,  according  to[0m
                 [40msome [4mrecipe[24m.[0m

       [4m[40mcookbook[24m  A file containing input for [1mcook[22m, usually [4mrecipe[24ms.[0m

       [4m[40mexplicit[24m [4mrecipe[24m An  explicit recipe is one where the [4mtarget[24ms[0m
                 [40mcontain  no  patterns.   That  is,  there  are  no[0m
                 [40mpercent ('[1m%[22m') characters in any of the [4mtarget[24ms.[0m

       [4m[40mfingerprint[24m A  cryptographically strong hash of the contents[0m
                 [40mof a file, use to determine if the  file  contents[0m
                 [40mhave changed.[0m

       [4m[40mflag[24m      A  flag  modifies  the behavior of a cook session,[0m
                 [4m[40mrecipe[24m or command.[0m

       [4m[40mforced[24m [4mingredient[24m A files which must exist before  a  [4mtarget[0m
                 [40mfile  of  an  [4mimplicit[24m  [4mrecipe[24m may be cooked.  The[0m
                 [40minability to construct a forced ingredient  is  an[0m
                 [40merror.[0m

       [4m[40mfunction[24m  A function is an action applied to a word list.[0m

       [4m[40mgate[24m      A gate is a condition which allows the conditional[0m
                 [40mapplication of a [4mrecipe[24m.  The gate condition is in[0m
                 [40maddition  to  the requirement that the ingredients[0m
                 [40mare cookable.[0m

       [4m[40mimplicit[24m [4mrecipe[24m An implicit recipe is a recipe with patterns[0m
                 [40min the [4mtarget[24ms.  That is, there is a percent ('[1m%[22m')[0m
                 [40mcharacter in at least one of the [4mtarget[24ms.[0m

       [4m[40mingredient[24m A files which must exist before a [4mtarget[24m file may[0m
                 [40mbe cooked.  In an [4mimplicit[24m [4mrecipe[24m the inability to[0m
                 [40mconstruct of an ingredient means that  the  [4mrecipe[0m
                 [40mwill  not  be  applied.  In an explicit recipe the[0m
                 [40minability to construct an ingredient is an error.[0m

       [4m[40mlast-modified[24m [4mtime[0m
                 [40mUNIX imbues files with several attributes.  One of[0m
                 [40mthese  is  a  time-stamp of when the file was last[0m
                 [40mmodified.  Usually this is when the file was  last[0m

       
       Peter Miller                                        Page 126





       Cook                                              User Guide



       [40m          written to.[0m

       [4m[40mrecipe[24m    A [4mrecipe[24m consists of several parts.[0m

                   [40m1.  A set of [4mtarget[24ms to be cooked,[0m

                   [40m2.  A set of ingredients of those [4mtarget[24ms, and[0m

                   [40m3.  An optional set of forced ingredients.[0m

                   [40m4.  An optional set of flags.[0m

                   [40m5.  An optional gate.[0m

                   [40m6.  An optional body .[0m

       [4m[40mtarget[24m    The object of a [4mrecipe[24m, a thing which is cooked.[0m

       [4m[40mtouch[24m     UNIX imbues files with several attributes.  One of[0m
                 [40mthese is a time-stamp of when the  file  was  last[0m
                 [40mmodified.   Usually this is when the file was last[0m
                 [40mwritten to,  however  it  is  possible  to  simply[0m
                 [40madjust   this   attribute,  rather  than  actually[0m
                 [40mwriting to the file; this is colloquially known as[0m
                 [4m[40mtouch[24ming a file.[0m

       [4m[40mvariable[24m  A  variable  is  a named place holder for a value.[0m
                 [40mThe value may be changed.[0m



























       
       Peter Miller                                        Page 127





       Cook                                              User Guide



























































       Peter Miller                                        Page 128









       [40m                          CONTENTS[0m



       [40m1.   Introduction ........................................ 3[0m
            [40m1.1    Why You Want To Use Cook ..................... 3[0m
            [40m1.2    How to Use this Manual ....................... 4[0m
            [40m1.3    Ancient History .............................. 4[0m

       [40m2.   Cook from the Outside ............................... 6[0m
            [40m2.1    What can cook do for me? ..................... 6[0m
            [40m2.2    What is cook doing? .......................... 6[0m
            [40m2.3    What can cook always do? ..................... 6[0m
            [40m2.4    If something goes wrong ...................... 7[0m
            [40m2.5    The Reference Manual ......................... 7[0m

       [40m3.   Cook from a Cookbook ................................ 8[0m
            [40m3.1    What does Cook do? ........................... 8[0m
            [40m3.2    How do I tell Cook what to do? ............... 9[0m
            [40m3.3    Creating a Cookbook ......................... 10[0m

       [40m4.   Cooking in Parallel ................................ 12[0m
            [40m4.1    Command Line Option ......................... 12[0m
            [40m4.2    Cookbook Variable ........................... 12[0m
            [40m4.3    Recipe Writing .............................. 12[0m
            [40m4.4    File Locking ................................ 14[0m
            [40m4.5    Virtual Machine ............................. 14[0m
            [40m4.6    Virtual Machine, Revisited .................. 16[0m

       [40m5.   Include File Dependencies .......................... 19[0m
            [40m5.1    The Manual Method ........................... 19[0m
            [40m5.2    Debugging Cookbooks ......................... 19[0m
            [40m5.3    Tools ....................................... 21[0m
            [40m5.4    The Small Method ............................ 21[0m
            [40m5.5    The Large Method ............................ 22[0m
            [40m5.6    The Cascade Method .......................... 23[0m
            [40m5.7    Dependencies on Derived Files ............... 24[0m
            [40m5.8    Renaming Include Files ...................... 25[0m

       [40m6.   Building Large Projects ............................ 27[0m
            [40m6.1    Whole Project Build ......................... 27[0m
            [40m6.2    Private Work Areas .......................... 33[0m
            [40m6.3    Whole Project Build Advantages .............. 36[0m
            [40m6.4    Heterogeneous Build ......................... 36[0m
            [40m6.5    Installing Things ........................... 38[0m
            [40m6.6    Miscellaneous ............................... 39[0m
            [40m6.7    File Fingerprints ........................... 40[0m
            [40m6.8    Coping with Links ........................... 43[0m
            [40m6.9    Coping with Version Stamps .................. 43[0m

       [40m7.   Cookbook Language Definition ....................... 45[0m
            [40m7.1    Lexical Analysis ............................ 45[0m
                   [40m7.1.1   Words and Keywords .................. 45[0m


       
                                     i









       [40m            7.1.2   Escape Sequences .................... 45[0m
                   [40m7.1.3   Quoting ............................. 46[0m
                   [40m7.1.4   Comments ............................ 46[0m
            [40m7.2    Preprocessor ................................ 46[0m
                   [40m7.2.1   include ............................. 46[0m
                   [40m7.2.2   include-cooked ...................... 47[0m
                   [40m7.2.3   include-cooked-nowarn ............... 48[0m
                   [40m7.2.4   if .................................. 48[0m
                   [40m7.2.5   ifdef ............................... 49[0m
                   [40m7.2.6   ifndef .............................. 49[0m
                   [40m7.2.7   pragma .............................. 49[0m
            [40m7.3    Syntax and Semantics ........................ 50[0m
                   [40m7.3.1   Overall Structure ................... 50[0m
                   [40m7.3.2   The Compound Statement .............. 50[0m
                   [40m7.3.3   Variables and Expressions ........... 50[0m
                   [40m7.3.4   Recipes ............................. 53[0m
                   [40m7.3.5   The Explicit Recipe Statement ....... 53[0m
                   [40m7.3.6   The Implicit Recipe Statement ....... 59[0m
                   [40m7.3.7   The Ingredients Recipe Statement .... 60[0m
                   [40m7.3.8   The Cascade Recipe Statement ........ 61[0m
                   [40m7.3.9   Commands ............................ 61[0m
                   [40m7.3.10  The Simple Command Statement ........ 61[0m
                   [40m7.3.11  The Data Command Statement .......... 62[0m
                   [40m7.3.12  The Set Statement ................... 63[0m
                   [40m7.3.13  The Fail Statement .................. 64[0m
                   [40m7.3.14  The If Statement .................... 64[0m
                   [40m7.3.15  The Loop and Loopend Statements ..... 64[0m
                   [40m7.3.16  Functions ........................... 65[0m

       [40m8.   Built-In Functions ................................. 68[0m
            [40m8.1    addprefix ................................... 68[0m
            [40m8.2    addsuffix ................................... 68[0m
            [40m8.3    and ......................................... 68[0m
            [40m8.4    basename .................................... 69[0m
            [40m8.5    cando ....................................... 69[0m
            [40m8.6    catenate .................................... 70[0m
            [40m8.7    collect_lines ............................... 70[0m
            [40m8.8    collect ..................................... 71[0m
            [40m8.9    cook ........................................ 71[0m
            [40m8.10   count ....................................... 72[0m
            [40m8.11   defined ..................................... 72[0m
            [40m8.12   dirname ..................................... 72[0m
            [40m8.13   dir ......................................... 73[0m
            [40m8.14   dos-path .................................... 73[0m
            [40m8.15   downcase .................................... 74[0m
            [40m8.16   entryname ................................... 74[0m
            [40m8.17   execute ..................................... 74[0m
            [40m8.18   exists ...................................... 75[0m
            [40m8.19   exists-symlink .............................. 75[0m
            [40m8.20   expr ........................................ 76[0m
            [40m8.21   filter_out .................................. 77[0m
            [40m8.22   filter ...................................... 77[0m
            [40m8.23   find_command ................................ 78[0m


       
                                    ii









       [40m     8.24   findstring .................................. 78[0m
            [40m8.25   firstword ................................... 79[0m
            [40m8.26   fromto ...................................... 79[0m
            [40m8.27   getenv ...................................... 80[0m
            [40m8.28   glob ........................................ 80[0m
            [40m8.29   head ........................................ 81[0m
            [40m8.30   home ........................................ 81[0m
            [40m8.31   if .......................................... 81[0m
            [40m8.32   in .......................................... 82[0m
            [40m8.33   interior_files .............................. 82[0m
            [40m8.34   join ........................................ 83[0m
            [40m8.35   leaf_files .................................. 83[0m
            [40m8.36   matches ..................................... 83[0m
            [40m8.37   match_mask .................................. 84[0m
            [40m8.38   mtime ....................................... 84[0m
            [40m8.39   mtime-seconds ............................... 84[0m
            [40m8.40   notdir ...................................... 85[0m
            [40m8.41   not ......................................... 85[0m
            [40m8.42   operating_system ............................ 86[0m
            [40m8.43   options ..................................... 87[0m
            [40m8.44   or .......................................... 88[0m
            [40m8.45   pathname .................................... 88[0m
            [40m8.46   patsubst .................................... 88[0m
            [40m8.47   prepost ..................................... 89[0m
            [40m8.48   print ....................................... 89[0m
            [40m8.49   quote ....................................... 89[0m
            [40m8.50   read_lines .................................. 89[0m
            [40m8.51   readlink .................................... 90[0m
            [40m8.52   read ........................................ 90[0m
            [40m8.53   relative_dirname ............................ 90[0m
            [40m8.54   resolve ..................................... 91[0m
            [40m8.55   shell ....................................... 91[0m
            [40m8.56   sort_newest ................................. 92[0m
            [40m8.57   sort ........................................ 92[0m
            [40m8.58   split ....................................... 92[0m
            [40m8.59   stringset ................................... 93[0m
            [40m8.60   stripdot .................................... 93[0m
            [40m8.61   strip ....................................... 94[0m
            [40m8.62   substr ...................................... 94[0m
            [40m8.63   subst ....................................... 94[0m
            [40m8.64   suffix ...................................... 95[0m
            [40m8.65   tail ........................................ 95[0m
            [40m8.66   un-dos-path ................................. 96[0m
            [40m8.67   unsplit ..................................... 96[0m
            [40m8.68   upcase ...................................... 96[0m
            [40m8.69   uptodate .................................... 97[0m
            [40m8.70   wildcard .................................... 97[0m
            [40m8.71   word ........................................ 98[0m
            [40m8.72   words ....................................... 99[0m
            [40m8.73   write ....................................... 99[0m

       [40m9.   Predefined Variables .............................. 100[0m
            [40m9.1    arg ........................................ 100[0m


       
                                    iii









       [40m     9.2    command-line-goals ......................... 100[0m
            [40m9.3    __FILE__ ................................... 100[0m
            [40m9.4    __FUNCTION__ ............................... 100[0m
            [40m9.5    graph_leaf_file ............................ 100[0m
            [40m9.6    graph_exterior_file ........................ 100[0m
            [40m9.7    graph_interior_file ........................ 100[0m
            [40m9.8    graph_leaf_pattern ......................... 100[0m
            [40m9.9    graph_exterior_pattern ..................... 101[0m
            [40m9.10   graph_interior_pattern ..................... 101[0m
            [40m9.11   __LINE__ ................................... 101[0m
            [40m9.12   need ....................................... 101[0m
            [40m9.13   parallel_hosts ............................. 101[0m
            [40m9.14   parallel_jobs .............................. 101[0m
            [40m9.15   parallel_rsh ............................... 101[0m
            [40m9.16   search_list ................................ 101[0m
            [40m9.17   self ....................................... 102[0m
            [40m9.18   target ..................................... 102[0m
            [40m9.19   targets .................................... 102[0m
            [40m9.20   thread-id .................................. 102[0m
            [40m9.21   timestamp_granularity ...................... 102[0m
            [40m9.22   younger .................................... 102[0m
            [40m9.23   version .................................... 102[0m

       [40m10.  Functions Library ................................. 103[0m
            [40m10.1   capitalize ................................. 103[0m
            [40m10.2   defined-or-null ............................ 103[0m
            [40m10.3   defined-or-default ......................... 103[0m
            [40m10.4   repeat ..................................... 103[0m
            [40m10.5   variable_by_path ........................... 104[0m

       [40m11.  Actions when Cooking .............................. 105[0m
            [40m11.1   Scan the COOK Environment Variable ......... 105[0m
            [40m11.2   Scan the Command Line ...................... 105[0m
            [40m11.3   Locate the Cookbook ........................ 105[0m
            [40m11.4   Form the Listing Filename .................. 105[0m
            [40m11.5   Create the Listing file .................... 105[0m
            [40m11.6   Scan the Cookbook .......................... 106[0m
            [40m11.7   Determine targets to cook .................. 106[0m
            [40m11.8   Cooking a Target ........................... 106[0m
            [40m11.9   The Dependency Graph ....................... 109[0m
            [40m11.10  File Status ................................ 110[0m

       [40m12.  Option Precedence ................................. 112[0m

       [40m13.  File name patterns ................................ 113[0m
            [40m13.1   Cook Patterns .............................. 113[0m
            [40m13.2   Regular Expressions ........................ 115[0m

       [40m14.  Supplied Cookbooks ................................ 118[0m
            [40m14.1   as ......................................... 118[0m
            [40m14.2   c .......................................... 119[0m
            [40m14.3   f77 ........................................ 120[0m
            [40m14.4   g77 ........................................ 120[0m


       
                                    iv









       [40m     14.5   gcc ........................................ 121[0m
            [40m14.6   home ....................................... 121[0m
            [40m14.7   lex ........................................ 121[0m
            [40m14.8   library .................................... 122[0m
            [40m14.9   print ...................................... 123[0m
            [40m14.10  program .................................... 123[0m
            [40m14.11  rcs ........................................ 124[0m
            [40m14.12  recursive .................................. 124[0m
            [40m14.13  sccs ....................................... 125[0m
            [40m14.14  text ....................................... 125[0m
            [40m14.15  usr.local .................................. 126[0m
            [40m14.16  usr ........................................ 126[0m
            [40m14.17  yacc_many .................................. 126[0m
            [40m14.18  yacc ....................................... 127[0m

       [40m15.  Glossary .......................................... 128[0m







































       
                                     v

































































                                    vi


