


       



       .














                                   Cook

                         A File Construction Tool




                                User Guide







                               Peter Miller

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

































       .












       This document describes Cook version 2.25
       and was prepared 29 October 2011.






       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
       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  2  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, write to the Free
       Software Foundation,  Inc.,  59  Temple  Place,  Suite  330,
       Boston, MA 02111, USA.



















       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.




       Peter Miller                                          Page 1





       Cook                                              User Guide



          +o Cook can distribute builds across your LAN.

          +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


       Peter Miller                                          Page 2





       Cook                                              User Guide



       [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
       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 wieghting 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 synchronised 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 accomplised 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 rond 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
       heterogenous  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 heterogenous 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  [4mHeterogenous[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  crontrol  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 fubarcomplier 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 deafult 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
       [40mbacause 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 becaise 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/usr/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 individial 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
                 [40mindividial recipes or commands.[0m

       [40mingredients-fingerprint This  flag  may  be  used  to  cause[0m
                 [40mrecipes to re-trigger when their ingredients  list[0m
                 [40mchages in any way.  This is especially useful, for[0m
                 [40mexample, in causing libraries to be rebuilt when a[0m
                 [40mcontent 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

       [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 supresses 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

       
       Peter Miller                                         Page 54





       Cook                                              User Guide



       [40m          adjust  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
       [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





       ____________________

       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



       [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
       [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


       
       Peter Miller                                         Page 56





       Cook                                              User Guide



       [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
            [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

       
       Peter Miller                                         Page 57





       Cook                                              User Guide



       [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

       [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



       ____________________

       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



       [40m[4m7.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
       [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

       
       Peter Miller                                         Page 59





       Cook                                              User Guide



       [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
       [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

       ____________________

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

       Peter Miller                                         Page 60





       Cook                                              User Guide



       [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

       [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




       
       Peter Miller                                         Page 61





       Cook                                              User Guide



       [40m[4m7.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
       [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


       
       Peter Miller                                         Page 62





       Cook                                              User Guide



       [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
       [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



       
       Peter Miller                                         Page 63





       Cook                                              User Guide



       [40m[4m7.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 invokation 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
       [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

       
       Peter Miller                                         Page 64





       Cook                                              User Guide



       [40m[4m7.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

       
       Peter Miller                                         Page 72





       Cook                                              User Guide



       [40m     if [not [test -d fubar]] then[0m
            [40m{[0m
                    [40mrm -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


















       ____________________

       9. See [4msh[24m (1) and [4mcsh[24m(1) for more information.

       Peter Miller                                         Page 87





       Cook                                              User Guide



       [40m[4m8.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

       [4m[40m8.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


       
       Peter Miller                                         Page 88





       Cook                                              User Guide



       [40m[4m8.53.3[24m  [4mAlso[24m [4mKnown[24m [4mAs[0m
       [40mreldir[0m

       [4m[40m8.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




       
       Peter Miller                                         Page 90





       Cook                                              User Guide



       [40m[4m8.58.2[24m  [4mSee[24m [4mAlso[0m
       [40munsplit, join, catenate, strip[0m

       [4m[40m8.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


















       
       Peter Miller                                         Page 92





       Cook                                              User Guide



       [40m[4m8.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 litteral 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

       [4m[40m8.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








       
       Peter Miller                                         Page 93





       Cook                                              User Guide



       [40m[4m8.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

       [4m[40m8.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







       
       Peter Miller                                         Page 94





       Cook                                              User Guide



       [40m[4m8.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

       [4m[40m8.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




       
       Peter Miller                                         Page 95





       Cook                                              User Guide



       [40m[4m8.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

       [4m[40m8.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


       
       Peter Miller                                         Page 96





       Cook                                              User Guide



       [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

       [4m[40m8.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  [4myounger[0m

       [40mThe  subset of the ingredients of the recipe currently being[0m
       [40mcooked which are younger than the target.[0m

       [4m[40m9.22[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
       [40mautomaticly 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 frequenty  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/usr/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


















       
       Peter Miller                                        Page 118





       Cook                                              User Guide



       [40m[4m14.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

       [4m[40m14.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

       
       Peter Miller                                        Page 119





       Cook                                              User Guide



       [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

       [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




       
       Peter Miller                                        Page 121





       Cook                                              User Guide



       [40m[4m14.10.2[24m  [4mrecipes[0m


       [40mall       Construct the targets named in [all].[0m

       [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

















       
       Peter Miller                                        Page 122





       Cook                                              User Guide



       [40m[4m14.12[24m  [4mrecursive[0m

       [40mThis  cookbook  may  be  used  to  construct  recursive cook[0m
       [40mdirewctory structures, where  the  top-level  cookbook  only[0m
       [40minvokes cookbooks in deeper directories.[0m

       [40mAll  largets  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

       [4m[40m14.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



       
       Peter Miller                                        Page 123





       Cook                                              User Guide



       [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

       [4m[40m14.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














       
       Peter Miller                                        Page 124





       Cook                                              User Guide



       [40m[4m14.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

       [4m[40m14.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    Heterogenous 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 .................................. 90[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 ....................................... 95[0m
            [40m8.64   suffix ...................................... 95[0m
            [40m8.65   tail ........................................ 96[0m
            [40m8.66   un-dos-path ................................. 96[0m
            [40m8.67   unsplit ..................................... 96[0m
            [40m8.68   upcase ...................................... 97[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   younger .................................... 102[0m
            [40m9.22   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 ........................................ 121[0m
            [40m14.5   gcc ........................................ 121[0m


       
                                    iv









       [40m     14.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 .................................. 125[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 .................................. 127[0m
            [40m14.18  yacc ....................................... 127[0m

       [40m15.  Glossary .......................................... 128[0m








































       
                                     v

































































                                    vi


