metalint - a metaconfig unit consistency checker
metalint [ -hklsV ] [ -L dir ]
Metalint parses the units and performs some extensive
consistency checks, to make sure the whole set is sound. Due to the
relatively huge amount of units available, it is becoming very difficult to
maintain the units manually, and an automated process can be of real help,
although not perfect.
Metalint operates from within your top level package
directory and is used to make sure your own private units are correctly
relying on the publicly available units. If you intensively develop new
units, you should run metalint on them before making them publicly
available.
Metalint recognizes the following set of options:
- -h
- Print a short usage description and exit.
- -k
- Keep temporary .MT directory.
- -l
- (not implemented yet) By default, metalint only reports problems
related to your own private units. This switch directs metalint to
also report problems in publicly available units.
- -s
- Silent mode.
- -L dir
- Override default library location. Normally only useful for metaconfig
maintainers to locally check the units being developed instead of the
publicly available ones. The dir specified is the one containing
the units U directory.
- -V
- Print version number and exit.
The following diagnostics may be emitted by metalint:
- "(?MAKE) command line must start with a leading TAB
character."
- Self explanatory.
- "(?MAKE) fourth pick argument is missing."
- Self explanatory.
- "(?MAKE) fourth pick argument should probably be the %<
macro."
- When the fourth argument is not a relative path, it is expected to be the
current unit name, which is best described using the "%<"
string, a macro handled by metaconfig and which is substituted with
the current unit name.
- "(?MAKE) ignoring duplicate dependency listing line."
- More than one ?MAKE: line bearing dependencies was found in the unit.
There may be only one such line, although multiple ?MAKE action lines may
occur.
- "(?MAKE) special unit 'Xxx' should not be listed as made."
- A special unit symbol (first letter capitalized) may only be listed as
made in the special unit itself. To suppress this warning in legitimate
cases, add a '+' in front of the offending symbol (note that for
non-special units, the '+' in this position indicates an internal symbol
which should not appear in the config.sh file).
- "(?MAKE) '+xxx' is listed x times."
- A conditional dependency is listed more than once. This is harmless
though.
- "(?MAKE) 'xxx' is listed x times."
- A normal depdendency is listed more than once. Again, an harmless
error.
- "(?MAKE) 'xxx' listed as both conditional and full
dependency."
- Symbol is listed as a normal dependency and as a conditional one.
Metaconfig will consider this as being a full dependency, but that
may not be what you initially wanted...
- "(?MAKE) pick needs a command argument."
- There is no command name after the special "pick" directive,
which is invalid.
- "(?MAKE) third pick argument must be $@.
- The third argument to the special "pick" directive must be $@,
litterally.
- "(?MAKE) unknown pick command 'xxx'.
- The command argument listed for the special "pick" directive is
unknown.
- "(?MAKE) weird fourth argument 'xxx' to pick.
- The fourth argument for pick, the target file, should be a unit name, a
file path introduced by "./" or the special "%<"
token.
- "(?Y) unknown layout directive 'xxx'."
- Layout directives may only be one of top, default or
bottom, but case does not matter. An unknown directive is just
ignored and handled as if default had been specified.
- "(?S) duplicate description for variable '$xxx'."
- Shell symbol is described more than once, and that will produce two
entries in the Glossary.
- "(?S) variable '$xxx' is not listed on ?MAKE: line."
- The unit describes a shell symbol entry which cannot be used externally
since not listed as a dependency.
- "(?S) syntax error in ?S: construct."
- Self explanatory.
- "(?C) duplicate description for symbol 'XXX'."
- C symbol is described more than once, and that will produce two entries
for it in the Glossary.
- "(?C) syntax error in ?C: construct."
- Self explanatory.
- "(?H) symbol 'XXX' was already defined."
- Apparently, two ?H: lines are defining the same C symbol.
- "(?H) variable '$xxx' not even listed on ?MAKE: line."
- A variable is used, but not listed on the dependency line.
- "(?H) section was already terminated by '?H:.'."
- There can be no more ?H: lines after the first '?H:.' marking the end of
that section.
- "(?H) uncommon cpp line should be protected with
'?%<:'."
- All ?H: lines that are recognized by metaconfig and thus
metalint have their inclusion in config.h automatically protected
by a suitable symbol if none is provided. However, unrecognized lines must
be protected with the '?%<:' sequence to avoid their inclusion should
the unit not be loaded in Configure.
- "(?H) line should not be listed here but in '?C:'."
- Only cpp lines should appear in the ?H: section. If you have a comment to
put regarding the symbol, use ?C:. If you want to comment a particular
generation sequence, put them into ?X: comment so that they don't make it
into config.h.
- "(?H) constraint 'xxx' is an unknown symbol."
- All the leading ?sym: constraints on the ?H: lines should be a valid shell
or C symbol, defined in the unit.
- "(?M) syntax error in ?M: construct."
- Self explanatory.
- "(?M) symbol 'xxx' already listed on a ?M: line in 'yyy'."
- A magic definition for symbol xxx is attempted, but another one was
already provided in unit yyy.
- "(?V) visible declaration in non-special unit ignored."
- Visible declarations (?V: lines) may only appear in special units.
Otherwise, they are meaningless.
- "(?V) wanted variable '$xxx' made visible."
- A wanted variable (described as a dependency on the ?MAKE: line) cannot be
made visible since that does not make any sense: the unit cannot depend on
it and then advertise it as being locally defined.
- "(?V) defined variable '$xxx' made visible."
- A defined variable (listed as made on the ?MAKE: line) cannot be made
visible, since it could as well be directly wanted in another unit.
- "(?V) variable '$xxx' already made visible by unit yyy."
- Inconsistent declaration: two units are making one single symbol
visible...
- "(?V) variable '$xxx' already read-write visible in yyy."
- The variable was already made visible as read-write by another unit.
- "(?V) variable '$xxx' already read-only visible in yyy."
- The variable was already made visible as read-only by another unit.
- "(?W) variable '$xxx' already wanted."
- Variable is already wanted, there is no need to explicitly ask for it
here.
- "(?W) variable '$xxx' also locally defined."
- A wanted variable would conflict with a locally defined variable and could
result in getting a garbage value.
- "(?W) variable '$xxx' already listed on a ?W: line in
'yyy'."
- The variable in the shell symbol section of a ?W: line can only appear in
one unit.
- "(?F) produced file 'xxx' mutiply declared."
- The file is listed more than once on the ?F: line, under the same name.
This does not appear when declaring both a private UU file and a public
file with the same name, for instance.
- "(?F) UU file 'xxx' in non-special unit ignored."
- Private UU files (i.e. files like the myread script created for
later perusal by Configure) may only be created in special units.
Exceptions allowed if the ?F: line is preceded by a proper ?LINT:
hint.
- "(?F) file 'xxx' already exported by yyy.U."
- The listed file 'xxx' is already reported exported (listed likewise) in
the other unit yyy.U and is conflicting. An exported file is a generated
file above the UU directory.
- "(?F) UU file 'xxx' already created by yyy.U."
- The listed file 'xxx' is already created in the UU directory by the other
unit yyy.U. A created file is listed as ./xxx on the ?F: line.
- "(?T) temporary symbol '$xxx' multiply declared."
- Self explanatory.
- "directive should come after ?MAKE declarations."
- The directive listed between () at the beginning of this message should
really come after the ?MAKE: lines. You must reorder the unit or
metalint will not be able to properly diagnose problems.
- "control sequence '?XXX:' ignored within body."
- Attempt to use a control line other than ?X: or ?LINT: in the unit body,
which should be only shell code
- "variable '$xxx' is changed."
- A variable listed as wanted in the dependency line is changed. Such a
variable should be read-only for the unit. Use the change lint hint
to suppress this message in pathological cases.
- "no ?MAKE: line describing dependencies."
- Every unit should have a dependency line, or it will be silently ignored
by metaconfig. This message is suppressed by a ?LINT: empty
hint.
- "first body line should be a general ': description'."
- The very first shell line of the unit that will be added to the generated
Configure script should hold a description of the unit's purpose, on a ':'
line. There must be a space after the ':', since it is interpreted by the
shell, and the description should avoid meta-characters like '(' or '>'
unless the whole string is quoted. This message is suppressed by a ?LINT:
nocomment hint.
- "missing space after ':' to make it a comment."
- A line starting by ':' is interpreted by the shell but will be ignored.
There must be a space after the ':' though, or the shell will try to
execute an unknown command...
- "found unquoted meta-character > on comment line."
- A line starting by ':' is interpreted by the shell but will be ignored.
This means that meaningful meta-characters such as '(' or '>' must be
quoted or escaped with a leading backslash.
- "found dangling quote on ':' comment line."
- An unclosed single or double quote was spotted on a ':' comment line.
Since those lines are interpreted by the shell, albeit ignored, all quotes
must match perfectly.
- "not ending with a blank line."
- Since all units are gathered together to form one big script, it is
recommended (hence enforced by metalint) that every unit file end
with an empty line.
- "last line not ending with a new-line character."
- This is merely intended to users whose editor does not always append a
new-line at the end of text files. Should not happen when you use
vi.
- "symbol '$xxx' was not described."
- The shell symbol defined by this unit was not documented. Use the
describe lint hint to suppress this message.
- "C symbol 'XXX' was not described."
- The C symbol defined by this unit was not documented. Use the known
lint hint to suppress this message.
- "C symbol 'XXX' was not defined by any ?H: line."
- A C symbol was advertised by never defined, hence it cannot appear in the
config.h file and is therefore useless...
- "variable '$xxx' should have been set."
- A variable listed on the make line as made by the unit was not set by the
shell code body. Use the set lint hint to suppress this message in
pathological cases.
- "unused dependency variable '$xxx'."
- Apparently no usage is made from a shell variable. Use the change
or use lint hints (depending on the situation) to suppress this
message.
- "unused conditional variable '$xxx'.
- Apparently no usage is made from this conditional dependency. The
change or use lint hints can be used to suppress this
message.
- "unused temporary variable '$xxx'."
- A variable declared as temporary in a ?T: line is not used. The use
lint hint will fool metalint into thinking it's indeed used.
- "unknown control sequence '?XXX:'."
- Attempt to use an unknown control sequence.
- "unknown LINT request 'false' ignored."
- An unknown ?LINT: tag was used. All such tags must be spelled out in
lowercase.
- "symbol '$xxx' has no default value."
- A symbol used as a conditional dependency in some unit has no default
value set by a ?D: line.
- "stale ?MAKE: dependency 'xxx'."
- Unit lists a symbol as a dependency, but that symbol is otherwise unknown,
i.e. never appears as made by any other unit.
- "symbol '$xxx' missing from ?MAKE."
- A symbol used or defined was not listed as a dependency in the ?MAKE:
line.
- "missing xxx from ?MAKE for visible '$yyy'."
- A symbol defined as visible by a special unit is used, but that special
unit is not part of the dependency line.
- "stale ?M: dependency 'xxx'."
- Magic line lists a C symbol as a dependency but that symbol is not known
by any unit.
- "unknown symbol '$xxx'."
- I have no idea about what this symbol is. If the variable is externally
define, this warning can be suppresed via a proper ?LINT: extern.
- "read-only symbol '$xxx' is set."
- A symbol that should be read-only is set by the unit's shell code
body.
- "obsolete symbol 'xxx' is used."
- An obsolete symbol is used in the unit's shell code.
- "undeclared symbol '$xxx' is set."
- The unit tries to set a shell variable which has not been otherwise
declared as made or as a temporary variable, or whatever.
- "unclosed ?H: section."
- The ?H: section was not terminated by a single '?H:.' line before the body
of the unit or the start of another ?C: section.
- "C symbol 'xxx' is defined in the following units:"
- The C symbol is defined in more that one unit. Offending units are
listed.
- "Shell symbol 'xxx' is defined in the following units:"
- A shell symbol is defined in more than one unit. Offending units
folllow.
- "Shell symbol 'xxx' is altogether:"
- A shell symbol is defined by some units, obsoleted by others and used as a
temporary.
- "Shell symbol 'xxx' is both defined and obsoleted:"
- Self explanatory.
- "Shell symbol 'xxx' is both defined and used as temporary:"
- Self explanatory.
- "Shell symbol 'xxx' obsoleted also used as temporary:"
- Self explanatory.
- "definition of '$xxx' not closed by '?S:.'."
- Self explanatory.
- "definition of 'XXX' not closed by '?C:.'."
- Self explanatory.
- "magic definition of 'xxx' not closed by '?M:.'."
- Self explanatory.
- "variable '$xxx' is defined externally."
- A variable defined externally (i.e. in another unit) is used, without
proper dependency information. Use the extern lint hint to suppress
this message.
- "file 'xxx' was not created."
- A file listed as a private UU file is not created by the special unit.
Creation is detected by seing an explicit shell redirection to the file,
not by an implicit creation (such as a C compilation would for instance).
All special units should create only shell scripts explicitly anyway so
this message cannot be suppressed via a lint hint.
- "local file 'xxx' may override the one set by 'unit.U'."
- You are attempting to create a local file, but the special unit creates
one bearing the exact same name and should it be loaded before within
Configure, you would override that file. Change the name of your
local file.
- "unused temporary file 'xxx'.
- The file was declared on the ?F: line but does not appear to be used
anywhere.
- "mis-used temporary file 'xxx'.
- A local temporary file has been declared on the ?F: line and is used in a
way that may not be the proper one. Indeed, all such local files should be
called with an explicit relative path, to avoid PATH lookups which could
get you another file.
- "you might not always get file 'xxx' from 'unit.U'."
- You seem to be calling the specified file, but not by using an explicit
relative pathname. Relying on the PATH to find this file is not safe. To
fix this problem, call your file using somthing like ./xxx.
- "missing Unit from ?MAKE for private file 'xxx'."
- You are using a private UU file without listing the special unit that
produces it in your dependency line. Add the unit to your dependency
list.
- "unknown private file 'xxx'."
- The file does not appear on any ?F: line; however it should.
- "File 'xxx' is defined in the following units:"
- The listed units cannot seem to agree on who is defining the file.
- "empty here-document name discouraged."
- You should refrain from using empty names for here documents, as
metalint will not monitor those.
- "unclosed here-document xxx started line x."
- The opened here-document at line x was never closed in this unit. This
generally mean that when the unit is used, the generated script will not
work!
- "spurious 'LINT xxx' directive."
- You have inserted a ?LINT: directive that is not used to shut-up
warnings.
- "Cycle found for:"
- There is a dependency cycle found for the symbols listed. Only the symbols
involved in the cycle are listed.
- "Cycle involves:"
- An exerpt of the dependencies where the cycle was found is listed. This
may involve far more symbols than the previous message, because
metalint actually rescans the rules to emphasize the cycle and
stops whenever it has found one, i.e. it does not try to minimize it (the
cycle is found using another algorithm, which unfortunately cannot spit it
out but only say for sure there is one).
Metalint uses the following control lines, which are
otherwise ignored by metaconfig:
- ?V:read-only symbols:read-write symbols
- This line should be used only in special units. It lists all the shell
variable defined by the unit which should not be used directly as
dependencies by other units: they must include this special unit in their
dependency list if they make use of any of the symbols described here.
Those can be viewed as exported symbols which you inherit from when
depending from the unit. Symbols may be exported read-only or
read-write.
- ?F:files created
- This line serves two purposes: it is a metalint hint, and also a
placeholder for future jmake use. It must list three kind of files:
the temporary one which are created for a test, the private UU ones
created in the UU directory for later perusal, and the public ones left in
the root directory of the package. Temporary files must be listed with a
preceding '!' character (meaning "no! they're not re-used
later!"), private UU files should be preceded by a './' (meaning: to
use them, say ./file, not just file), and public ones should
be named as-is.
- ?T:shell temporaries
- This line should list all the shell variables used as temporaries within
the unit's body. This line should be kept accurate, and prevents you from
writing a unit defining a symbol which would be used as a scratch variable
in another unit...
- ?LINT:keyword symbol_list
- Specifies a lint hint. The following keywords are available:
- change
- shell variable ok to be changed
- create
- persistent file ok to be created by non-special unit
- define
- shell variables listed are defined in this unit
- describe
- listed shell variables are described by ?S:
- extern
- variable known to be externally defined
- empty
- unit file is empty and kept only as a placeholder.
- known
- listed C variables are described
- unit file is special and may miss a leading ': description' line.
- nothere
- listed names are not here documents (e.g. "1 << foo" in a
C program)
- set
- listed variables are set
- use
- variables listed are used by this unit
- unclosed
- listed names of here-documents are not closed in this unit
- usefile
- listed file is used (do not prepend name with '!' for temporary ones)
Harlan Stenn <harlan@mumps.pfcs.com> wrote the first
version, based on Larry Wall's metaconfig from dist 2.0.
Raphael Manfredi <Raphael.Manfredi@pobox.com> rewrote it from scratch
for 3.0 with a few enhancements.
- LIB/dist/mcon/U/*.U
- Public unit files
- U/*.U
- Private unit files
where LIB is /usr/share/dist.