ACD.1
上传用户:jnzhq888
上传日期:2007-01-18
资源大小:51694k
文件大小:22k
- .TH ACD 1
- .SH NAME
- acd - a compiler driver
- .SH SYNOPSIS
- .B acd
- fB-vfR[fInfR]
- fB-vnfR[fInfR]
- .BI -name " name"
- .BI -descr " descr"
- .BI -T " dir"
- .RI [ arg " ...]"
- .SH DESCRIPTION
- .de SP
- .if t .sp 0.4
- .if n .sp
- ..
- .B Acd
- is a compiler driver, a program that calls the several passes that are needed
- to compile a source file. It keeps track of all the temporary files used
- between the passes. It also defines the interface of the compiler, the
- options the user gets to see.
- .PP
- This text only describes
- .B acd
- itself, it says nothing about the different options the C-compiler accepts.
- (It has nothing to do with any language, other than being a tool to give
- a compiler a user interface.)
- .SH OPTIONS
- .B Acd
- itself takes five options:
- .TP
- fB-vfR[fInfR]
- Sets the diagnostic level to
- .I n
- (by default
- .BR 2 ).
- The higher
- .I n
- is, the more output
- .B acd
- generates:
- .B -v0
- does not produce any output.
- .B -v1
- prints the basenames of the programs called.
- .B -v2
- prints names and arguments of the programs called.
- .B -v3
- shows the commands executed from the description file too.
- .B -v4
- shows the program read from the description file too. Levels 3 and 4 use
- backspace overstrikes that look good when viewing the output with a smart
- pager.
- .TP
- fB-vnfR[fInfR]
- Like
- .B -v
- except that no command is executed. The driver is just play-acting.
- .TP
- .BI -name " name"
- .B Acd
- is normally linked to the name the compiler is to be called with by the
- user. The basename of this, say
- .BR cc ,
- is the call name of the driver. It plays a role in selecting the proper
- description file. With the
- .B -name
- option one can change this.
- .B Acd -name cc
- has the same effect as calling the program as
- .BR cc .
- .TP
- .BI -descr " descr"
- Allows one to choose the pass description file of the driver. By default
- .I descr
- is the same as
- .IR name ,
- the call name of the program. If
- .I descr
- doesn't start with
- .BR / ,
- .BR ./ ,
- or
- .BR ../
- then the file
- .BI /usr/lib/ descr /descr
- will be used for the description, otherwise
- .I descr
- itself. Thus
- .B cc -descr newcc
- calls the C-compiler with a different description file without changing the
- call name. Finally, if
- .I descr
- is fB"-"fP, standard input is read. (The default lib directory
- .BR /usr/lib ,
- may be changed to
- .I dir
- at compile time by fB-DLIB=e"fPfIdirfPfBe"fP. The default
- .I descr
- may be set with fB-DDESCR=e"fPfIdescrfPfBe"fP for simple
- installations on a system without symlinks.)
- .TP
- .BI -T " dir"
- Temporary files are made in
- .B /tmp
- by default, which may be overridden by the environment variable
- .BR TMPDIR ,
- which may be overridden by the
- .B -T
- option.
- .SH "THE DESCRIPTION FILE"
- The description file is a program interpreted by the driver. It has variables,
- lists of files, argument parsing commands, and rules for transforming input
- files.
- .SS Syntax
- There are four simple objects:
- .PP
- .RS
- Words, Substitutions, Letters, and Operators.
- .RE
- .PP
- And there are two ways to group objects:
- .PP
- .RS
- Lists, forming sequences of anything but letters,
- .SP
- Strings, forming sequences of anything but Words and Operators.
- .RE
- .PP
- Each object has the following syntax:
- .IP Words
- They are sequences of characters, like
- .BR cc ,
- .BR -I/usr/include ,
- .BR /lib/cpp .
- No whitespace and no special characters. The backslash character
- .RB ( e )
- may be used to make special characters common, except whitespace. A backslash
- followed by whitespace is completely removed from the input. The sequence
- .B en
- is changed to a newline.
- .IP Substitutions
- A substitution (henceforth called 'subst') is formed with a
- .BR $ ,
- e.g.
- .BR $opt ,
- .BR $PATH ,
- .BR ${lib} ,
- .BR $(** .
- The variable name after the
- .B $
- is made of letters, digits and underscores, or any sequence of characters
- between parentheses or braces, or a single other character. A subst indicates
- that the value of the named variable must be substituted in the list or string
- when fully evaluated.
- .IP Letters
- Letters are the single characters that would make up a word.
- .IP Operators
- The characters
- .BR = ,
- .BR + ,
- .BR - ,
- .BR (** ,
- .BR < ,
- and
- .B >
- are the operators. The first four must be surrounded by whitespace if they
- are to be seen as special (they are often used in arguments). The last two
- are always special.
- .IP Lists
- One line of objects in the description file forms a list. Put parentheses
- around it and you have a sublist. The values of variables are lists.
- .IP Strings
- Anything that is not yet a word is a string. All it needs is that the substs
- in it are evaluated, e.g.
- .BR $LIBPATH/lib$key.a .
- A single subst doesn't make a string, it expands to a list. You need at
- least one letter or other subst next to it. Strings (and words) may also
- be formed by enclosing them in double quotes. Only
- .B e
- and
- .B $
- keep their special meaning within quotes.
- .SS Evaluation
- One thing has to be carefully understood: Substitutions are delayed until
- the last possible moment, and description files make heavy use of this.
- Only if a subst is tainted, either because its variable is declared local, or
- because a subst in its variable's value is tainted, is it immediately
- substituted. So if a list is assigned to a variable then this list is only
- checked for tainted substs. Those substs are replaced by the value
- of their variable. This is called partial evaluation.
- .PP
- Full evaluation expands all substs, the list is flattened, i.e. all
- parentheses are removed from sublists.
- .PP
- Implosive evaluation is the last that has to be done to a list before it
- can be used as a command to execute. The substs within a string have been
- evaluated to lists after full expansion, but a string must be turned into
- a single word, not a list. To make this happen, a string is first exploded
- to all possible combinations of words choosing one member of the lists within
- the string. These words are tried one by one to see if they exist as a
- file. The first one that exists is taken, if none exists than the first
- choice is used. As an example, assume
- .B LIBPATH
- equals
- .BR "(/lib /usr/lib)" ,
- .B key
- is
- .B (c)
- and
- .B key
- happens to be local. Then we have:
- .PP
- .RS
- fB"$LIBPATH/lib$key.a"fP
- .RE
- .PP
- before evaluation,
- .PP
- .RS
- fB"$LIBPATH/lib(c).a"fP
- .RE
- .PP
- after partial evaluation,
- .PP
- .RS
- fB"(/lib/libc.a /usr/lib/libc.a)"fP
- .RE
- .PP
- after full evaluation, and finally
- .PP
- .RS
- .B /usr/lib/libc.a
- .RE
- .PP
- after implosion, if the file exists.
- .SS Operators
- The operators modify the way evaluation is done and perform a special
- function on a list:
- .TP
- .B (**
- Forces full evaluation on all the list elements following it. Use it to
- force substitution of the current value of a variable. This is the only
- operator that forces immediate evaluation.
- .TP
- .B +
- When a
- .B +
- exists in a list that is fully evaluated, then all the elements before the
- .B +
- are imploded and all elements after the
- .B +
- are imploded and added to the list if they are not already in the list. So
- this operator can be used either for set addition, or to force implosive
- expansion within a sublist.
- .TP
- .B -
- Like
- .BR + ,
- except that elements after the
- .B -
- are removed from the list.
- .PP
- The set operators can be used to gather options that exclude each other
- or for their side effect of implosive expansion. You may want to write:
- .PP
- .RS
- fBcpp -I$LIBPATH/includefP
- .RE
- .PP
- to call cpp with an extra include directory, but
- .B $LIBPATH
- is expanded using a filename starting with
- .B -I
- so this won't work. Given that any problem in Computer Science can be solved
- with an extra level of indirection, use this instead:
- .PP
- .RS
- .ft B
- cpp -I$INCLUDE
- .br
- INCLUDE = $LIBPATH/include +
- .ft P
- .RE
- .SS "Special Variables"
- There are three special variables used in a description file:
- .BR $(** ,
- .BR $< ,
- and
- .BR $> .
- These variables are always local and mostly read-only. They will be
- explained later.
- .SS "A Program"
- The lists in a description file form a program that is executed from the
- first to the last list. The first word in a list may be recognized as a
- builtin command (only if the first list element is indeed simply a word.)
- If it is not a builtin command then the list is imploded and used as a
- s-2UNIXs+2 command with arguments.
- .PP
- Indentation (by tabs or spaces) is not just makeup for a program, but are
- used to group lines together. Some builtin commands need a body. These
- bodies are simply lines at a deeper indentation.
- .PP
- Empty lines are not ignored either, they have the same indentation level as
- the line before it. Comments (starting with a
- .B #
- and ending at end of line) have an indentation of their own and can be used
- as null commands.
- .PP
- .B Acd
- will complain about unexpected indentation shifts and empty bodies. Commands
- can share the same body by placing them at the same indentation level before
- the indented body. They are then "guards" to the same body, and are tried
- one by one until one succeeds, after which the body is executed.
- .PP
- Semicolons may be used to separate commands instead of newlines. The commands
- are then all at the indentation level of the first.
- .SS "Execution phases"
- The driver runs in three phases: Initialization, Argument scanning, and
- Compilation. Not all commands work in all phases. This is further explained
- below.
- .SS "The Commands"
- The commands accept arguments that are usually generic expressions that
- implode to a word or a list of words. When
- .I var
- is specified, then a single word or subst needs to be given, so
- an assignment can be either
- .I name
- .B =
- .IR value ,
- or
- .BI $ name
- .B =
- .IR value .
- .TP
- .IB "var " = " expr ..."
- The partially evaluated list of expressions is assigned to
- .IR var .
- During the evaluation is
- .I var
- marked as local, and after the assignment set from undefined to defined.
- .TP
- .BI unset " var"
- .I Var
- is set to null and is marked as undefined.
- .TP
- .BI import " var"
- If
- .I var
- is defined in the environment of
- .B acd
- then it is assigned to
- .IR var .
- The environment variable is split into words at whitespace and colons. Empty
- space between two colons
- .RB ( :: )
- is changed to a dot.
- .TP
- .BI mktemp " var " [ suffix ]
- Assigns to
- .I var
- the name of a new temporary file, usually something like /tmp/acd12345x. If
- .I suffix
- is present then it will be added to the temporary file's name. (Use it
- because some programs require it, or just because it looks good.)
- .B Acd
- remembers this file, and will delete it as soon as you stop referencing it.
- .TP
- .BI temporary " word"
- Mark the file named by
- .I word
- as a temporary file. You have to make sure that the name is stored in some
- list in imploded form, and not just temporarily created when
- .I word
- is evaluated, because then it will be immediately removed and forgotten.
- .TP
- .BI stop " suffix"
- Sets the target suffix for the compilation phase. Something like
- .B stop .o
- means that the source files must be compiled to object files. At least one
- .B stop
- command must be executed before the compilation phase begins. It may not be
- changed during the compilation phase. (Note: There is no restriction on
- .IR suffix ,
- it need not start with a dot.)
- .TP
- .BI treat " file suffix"
- Marks the file as having the given suffix for the compile phase. Useful
- for sending a
- .B -l
- option directly to the loader by treating it as having the
- .B .a
- suffix.
- .TP
- .BI numeric " arg"
- Checks if
- .I arg
- is a number. If not then
- .B acd
- will exit with a nice error message.
- .TP
- .BI error " expr ..."
- Makes the driver print the error message
- .I "expr ..."
- and exit.
- .TP
- .BI if " expr " = " expr"
- .B If
- tests if the two expressions are equal using set comparison, i.e. each
- expression should contain all the words in the other expression. If the
- test succeeds then the if-body is executed.
- .TP
- .BI ifdef " var"
- Executes the ifdef-body if
- .I var
- is defined.
- .TP
- .BI ifndef " var"
- Executes the ifndef-body if
- .I var
- is undefined.
- .TP
- .BI iftemp " arg"
- Executes the iftemp-body if
- .I arg
- is a temporary file. Use it when a command has the same file as input and
- output and you don't want to clobber the source file:
- .SP
- .RS
- .nf
- .ft B
- transform .o .o
- iftemp $(**
- $> = $(**
- else
- cp $(** $>
- optimize $>
- .ft P
- .fi
- .RE
- .TP
- .BI ifhash " arg"
- Executes the ifhash-body if
- .I arg
- is an existing file with a 'fB#fP' as the very first character. This
- usually indicates that the file must be pre-processed:
- .SP
- .RS
- .nf
- .ft B
- transform .s .o
- ifhash $(**
- mktemp ASM .s
- $CPP $(** > $ASM
- else
- ASM = $(**
- $AS -o $> $ASM
- unset ASM
- .ft P
- .fi
- .RE
- .TP
- .B else
- Executes the else-body if the last executed
- .BR if ,
- .BR ifdef ,
- .BR ifndef ,
- .BR iftemp ,
- or
- .B ifhash
- was unsuccessful. Note that
- .B else
- need not immediately follow an if, but you are advised not to make use of
- this. It is a "feature" that may not last.
- .TP
- .BI apply " suffix1 suffix2"
- Executed inside a transform rule body to transform the input file according
- to another transform rule that has the given input and output suffixes. The
- file under
- .B $(**
- will be replaced by the new file. So if there is a
- .B .c .i
- preprocessor rule then the example of
- .B ifhash
- can be replaced by:
- .SP
- .RS
- .nf
- .ft B
- transform .s .o
- ifhash $(**
- apply .c .i
- $AS -o $> $*
- .ft P
- .fi
- .RE
- .TP
- .BI include " descr"
- Reads another description file and replaces the
- .B include
- with it. Execution continues with the first list in the new program. The
- search for
- .I descr
- is the same as used for the
- .B -descr
- option. Use
- .B include
- to switch in different front ends or back ends, or to call a shared
- description file with a different initialization. Note that
- .I descr
- is only evaluated the first time the
- .B include
- is called. After that the
- .B include
- has been replaced with the included program, so changing its argument won't
- get you a different file.
- .TP
- .BI arg " string ..."
- .B Arg
- may be executed in the initialization and scanning phase to post an argument
- scanning rule, that's all the command itself does. Like an
- .B if
- that fails it allows more guards to share the same body.
- .TP
- .BI transform " suffix1 suffix2"
- .BR Transform ,
- like
- .BR arg ,
- only posts a rule to transform a file with the suffix
- .I suffix1
- into a file with the suffix
- .IR suffix2 .
- .TP
- .BI prefer " suffix1 suffix2"
- Tells that the transformation rule from
- .I suffix1
- to
- .I suffix2
- is to be preferred when looking for a transformation path to the stop suffix.
- Normally the shortest route to the stop suffix is used.
- .B Prefer
- is ignored on a
- .BR combine ,
- because the special nature of combines does not allow ambiguity.
- .SP
- The two suffixes on a
- .B transform
- or
- .B prefer
- may be the same, giving a rule that is only executed when preferred.
- .TP
- .BI combine " suffix-list suffix"
- .B Combine
- is like
- .B transform
- except that it allows a list of input suffixes to match several types of
- input files that must be combined into one.
- .TP
- .B scan
- The scanning phase may be run early from the initialization phase with the
- .B scan
- command. Use it if you need to make choices based on the arguments before
- posting the transformation rules. After running this,
- .B scan
- and
- .B arg
- become no-ops.
- .TP
- .B compile
- Move on to the compilation phase early, so that you have a chance to run
- a few extra commands before exiting. This command implies a
- .BR scan .
- .PP
- Any other command is seen as a s-2UNIXs+2 command. This is where the
- .B <
- and
- .B >
- operators come into play. They redirect standard input and standard output
- to the file mentioned after them, just like the shell.
- .B Acd
- will stop with an error if the command is not successful.
- .SS The Initialization Phase
- The driver starts by executing the program once from top to bottom to
- initialize variables and post argument scanning and transformation rules.
- .SS The Scanning Phase
- In this phase the driver makes a pass over the command line arguments to
- process options. Each
- .B arg
- rule is tried one by one in the order they were posted against the front of
- the argument list. If a match is made then the matched arguments are removed
- from the argument list and the arg-body is executed. If no match can be made
- then the first argument is moved to the list of files waiting to be
- transformed and the scan is restarted.
- .PP
- The match is done as follows: Each of the strings after
- .B arg
- must match one argument at the front of the argument list. A character
- in a string must match a character in an argument word, a subst in a string
- may match 1 to all remaining characters in the argument, preferring the
- shortest possible match. The hyphen in a argument starting with a hyphen
- cannot be matched by a subst. Therefore:
- .PP
- .RS
- .B arg -i
- .RE
- .PP
- matches only the argument
- .BR -i .
- .PP
- .RS
- .B arg -O$n
- .RE
- .PP
- matches any argument that starts with
- .B -O
- and is at least three characters long. Lastly,
- .PP
- .RS
- .B arg -o $out
- .RE
- .PP
- matches
- .B -o
- and the argument following it, unless that argument starts with a hyphen.
- .PP
- The variable
- .B $(**
- is set to all the matched arguments before the arg-body is executed. All
- the substs in the arg strings are set to the characters they match. The
- variable
- .B $>
- is set to null. All the values of the variables are saved and the variables
- marked local. All variables except
- .B $>
- are marked read-only. After the arg-body is executed is the value of
- .B $>
- concatenated to the file list. This allows one to stuff new files into the
- transformation phase. These added names are not evaluated until the start
- of the next phase.
- .SS The Compilation Phase
- The files gathered in the file list in the scanning phase are now transformed
- one by one using the transformation rules. The shortest, or preferred route
- is computed for each file all the way to the stop suffix. Each file is
- transformed until it lands at the stop suffix, or at a combine rule. After
- a while all files are either fully transformed or at a combine rule.
- .PP
- The driver chooses a combine rule that is not on a path from another combine
- rule and executes it. The file that results is then transformed until it
- again lands at a combine rule or the stop suffix. This continues until all
- files are at the stop suffix and the program exits.
- .PP
- The paths through transform rules may be ambiguous and have cycles, they will
- be resolved. But paths through combines must be unambiguous, because of
- the many paths from the different files that meet there. A description file
- will usually have only one combine rule for the loader. However if you do
- have a combine conflict then put a no-op transform rule in front of one to
- resolve the problem.
- .PP
- If a file matches a long and a short suffix then the long suffix is preferred.
- By putting a null input suffix (fB""fP) in a rule one can match any file
- that no other rule matches. You can send unknown files to the loader this
- way.
- .PP
- The variable
- .B $(**
- is set to the file to be transformed or the files to be combined before the
- transform or combine-body is executed.
- .B $>
- is set to the output file name, it may again be modified.
- .B $<
- is set to the original name of the first file of
- .B $(**
- with the leading directories and the suffix removed.
- .B $(**
- will be made up of temporary files after the first rule.
- .B $>
- will be another temporary file or the name of the target file
- .RB ( $<
- plus the stop suffix), if the stop suffix is reached.
- .PP
- .B $>
- is passed to the next rule; it is imploded and checked to be a single word.
- This driver does not store intermediate object files in the current directory
- like most other compilers, but keeps them in
- .B /tmp
- too. (Who knows if the current directory can have files created in?) As an
- example, here is how you can express the "normal" method:
- .PP
- .RS
- .nf
- .ft B
- transform .s .o
- if $> = $<.o
- # Stop suffix is .o
- else
- $> = $<.o
- temporary $>
- $AS -o $> $(**
- .ft P
- .fi
- .RE
- .PP
- Note that
- .B temporary
- is not called if the target is already the object file, or you would lose
- the intended result!
- .B $>
- is known to be a word, because
- .B $<
- is local. (Any string whose substs are all expanded changes to a word.)
- .SS "Predefined Variables"
- The driver has three variables predefined:
- .BR PROGRAM ,
- set to the call name of the driver,
- .BR VERSION ,
- the driver's version number, and
- .BR ARCH ,
- set to the name of the default output architecture. The latter is optional,
- and only defined if
- .B acd
- was compiled with fB-DARCH=e"fPfIarch-namefPfBe"fP.
- .SH EXAMPLE
- As an example a description file for a C compiler is given. It has a
- front end (ccom), an intermediate code optimizer (opt), a code generator (cg),
- an assembler (as), and a loader (ld). The compiler can pre-process, but
- there is also a separate cpp. If the
- .B -D
- and options like it are changed to look like
- .B -o
- then this example is even as required by s-2POSIXs+2.
- .RS
- .nf
- # The compiler support search path.
- C = /lib /usr/lib /usr/local/lib
- # Compiler passes.
- CPP = $C/cpp $CPP_F
- CCOM = $C/ccom $CPP_F
- OPT = $C/opt
- CG = $C/cg
- AS = $C/as
- LD = $C/ld
- # Predefined symbols.
- CPP_F = -D__EXAMPLE_CC__
- # Library path.
- LIBPATH = $USERLIBPATH $C
- # Default transformation target.
- stop .out
- # Preprocessor directives.
- arg -D$name
- arg -U$name
- arg -I$dir
- CPP_F = $CPP_F $(**
- # Stop suffix.
- arg -c
- stop .o
- arg -E
- stop .E
- # Optimization.
- arg -O
- prefer .m .m
- OPT = $OPT -O1
- arg -O$n
- numeric $n
- prefer .m .m
- OPT = $OPT $(**
- # Add debug info to the executable.
- arg -g
- CCOM = $CCOM -g
- # Add directories to the library path.
- arg -L$dir
- USERLIBPATH = $USERLIBPATH $dir
- # -llib must be searched in $LIBPATH later.
- arg -l$lib
- $> = $LIBPATH/lib$lib.a
- # Change output file.
- arg -o$out
- arg -o $out
- OUT = $out
- # Complain about a missing argument.
- arg -o
- error "argument expected after '$(**'"
- # Any other option (like -s) are for the loader.
- arg -$any
- LD = $LD $(**
- # Preprocess C-source.
- transform .c .i
- $CPP $(** > $>
- # Preprocess C-source and send it to standard output or $OUT.
- transform .c .E
- ifndef OUT
- $CPP $(**
- else
- $CPP $(** > $OUT
- # Compile C-source to intermediate code.
- transform .c .m
- transform .i .m
- $CCOM $(** $>
- # Intermediate code optimizer.
- transform .m .m
- $OPT $(** > $>
- # Intermediate to assembly.
- transform .m .s
- $CG $(** > $>
- # Assembler to object code.
- transform .s .o
- if $> = $<.o
- ifdef OUT
- $> = $OUT
- $AS -o $> $(**
- # Combine object files and libraries to an executable.
- combine (.o .a) .out
- ifndef OUT
- OUT = a.out
- $LD -o $OUT $C/crtso.o $(** $C/libc.a
- .fi
- .RE
- .SH FILES
- .TP 25n
- .RI /usr/lib/ descr /descr
- - compiler driver description file.
- .SH "SEE ALSO"
- .BR cc (1).
- .SH ACKNOWLEDGEMENTS
- Even though the end result doesn't look much like it, many ideas were
- nevertheless derived from the ACK compiler driver by Ed Keizer.
- .SH BUGS
- s-2POSIXs+2 requires that if compiling one source file to an object file
- fails then the compiler should continue with the next source file. There is
- no way
- .B acd
- can do this, it always stops after error. It doesn't even know what an
- object file is! (The requirement is stupid anyhow.)
- .PP
- If you don't think that tabs are 8 spaces wide, then don't mix them with
- spaces for indentation.
- .SH AUTHOR
- Kees J. Bot (kjb@cs.vu.nl)