Skip to content

Commit

Permalink
mamake: tighten the strict mode some more (re: 45feaa5, fbf8f42)
Browse files Browse the repository at this point in the history
The following changes apply to the strict mode only.

src/cmd/INIT/mamake.c:
- Use a state flag (state.strict) instead of a function for the
  strict mode. Amend the `setv` command to set this flag if the
  varname is `MAMAKE_STRICT`. This is simpler and more elegant.
- Produce a deprecation warning on assigning the 'generated',
  'archive', and 'joint' attributes. Ignore direct assignment of
  'generated' in strict mode. (It is implicitly assigned by 'exec'.
  The other two have always been simply ignored.)
- Make 'info' and 'meta' unknown commands. (These have always
  been ignored and I'd already removed all use of them before
  introducing the strict mode, so no backward compat problem).

src/{cmd/INIT,lib/libast}/Mamfile:
- Do not run mktest to regenerate .tst regression test scripts from
  .rt originals. It is not correct to do this at build time, as the
  originals do not contain the expected output -- it is obtained
  from the programs tested, assumed to be correct, and stored in
  the .tst output. So this must always be done manually and verified
  carefully before committing the changes.
  • Loading branch information
McDutchie committed Feb 4, 2024
1 parent f5c901b commit 9d714fc
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 53 deletions.
2 changes: 1 addition & 1 deletion src/Mamfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ note * Mamfiles are processed by mamake (src/cmd/INIT/mamake.c); we added
note * indentation to improve readability. The language is documented in
note * src/cmd/INIT/README-mamake.md.
note *
setv MAMAKE_SSTRICT
setv MAMAKE_STRICT
make test virtual
make test_announce virtual
exec - : testing KornShell $KSH_VERSION :
Expand Down
9 changes: 2 additions & 7 deletions src/cmd/INIT/Mamfile
Original file line number Diff line number Diff line change
Expand Up @@ -388,13 +388,8 @@ make test dontcare virtual
exec - regress iffe.tst iffe
done
make test.mamake virtual
make mamake.tst
prev mamake.rt
exec - if test mamake.rt -nt mamake.tst
exec - then "$SHELL" "$INSTALLROOT/bin/mktest" --style=regress mamake.rt > mamake.tst
exec - fi
done
exec - : testing mamake as built by package.sh :
prev mamake.tst
exec - : testing non-libast mamake at $PWD/mamake :
exec - regress mamake.tst mamake
done
done test
46 changes: 29 additions & 17 deletions src/cmd/INIT/README-mamake.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,17 @@ whereas `mamake` is simple and portable, and offers all the same flexibility.

Compared to the 2012-08-01 AT&T distribution,
ksh 93u+m made a number of changes to `mamake` that make it easier to maintain Mamfiles by hand:
* If the `MAMAKE_STRICT` variable is set before any other mamake command is executed,
some backward incompatible changes are activated to facilitate maintainability.
* Introduced a strict mode that activates some backward incompatible changes and deprecation warnings.
* All Mamfiles have been indented for legibility. (See `bin/Mamfile_indent` in the distribution.)
* Indentation and word separators may use any whitespace (e.g. tabs), not only spaces.
* Unrecognized commands and rule attributes throw an error instead of being silently ignored.
* Fixed some crashing bugs and memory leaks.
* The `silent` and `ignore` command prefixes for shell actions are processed internally
for backward compatibility, unless the `MAMAKE_STRICT` variable is set.
for backward compatibility, except in the strict mode.
* The `prev` command may now be used without a prior `make`...`done` to declare a simple
prerequisite, provided the `MAMAKE_STRICT` variable is set.
prerequisite, provided the strict mode is activated.
* The `notrace` attribute was added to disable xtrace for a rule's shell action.
* If `MAMAKE_STRICT` is set, appending attributes to the `done` command
* In the strict mode, appending attributes to the `done` command
produces a deprecation warning; please append them to `make` instead.
* Repeating the rule name in the `done` commnand is now optional so that
a simple `done` also works to terminate the current rule.
Expand All @@ -47,7 +46,7 @@ In addition, the following two simple shell scripts are now provided to aid
in maintaining and modernising Mamfiles:

* `src/cmd/INIT/utils/Mamfile_indent`: Automatically indent or re-indent a Mamfile.
* `src/cmd/INIT/utils/Mamfile_rm_unused_vars`: Remove unused `setv` variable
* `src/cmd/INIT/utils/Mamfile_rm_unused_vars`: Remove unreferenced `setv` variable
definitions from a Mamfile (except `MAMAKE_STRICT`).

## Commands ##
Expand All @@ -61,10 +60,17 @@ Unrecognized commands or attributes are an error.
The *argument* is a single word.
The *operand string* is any arbitrary text until the end of the line.

### Strict and legacy modes ###

If the `MAMAKE_STRICT` variable is set (`setv MAMAKE_STRICT`),
some backward incompatible changes and deprecation warnings
are activated to facilitate human maintenance of the Mamfiles.
We call this the "strict mode" and its absence the "legacy mode".

### Comments ###

`note` is the comment command and is ignored.
For historical reasons, `info` and `meta` are also ignored.
In the legacy mode, `info` and `meta` are also ignored.

### Rules ###

Expand Down Expand Up @@ -97,31 +103,37 @@ comes with the distribution or a file generated by a previously run Mamfile.

One or more *attribute*s may be specified by appending them to the `make` command.
(They may also be appended to the `done` command; the effect is the same either way.
This is deprecated and produces a warning if the `MAMAKE_STRICT` variable is defined.)
This is deprecated and produces a warning in the strict mode.)
**Attributes apply to the current rule only and do not propagate down to nested rules.**
The following *attribute*s are available:
* `archive`: Ignored.
Historically used to mark the generation of an `ar`(1) archive.
* `dontcare`: Marks files that do not need to exist.
If the file exists then its last-modified timestamp is checked and propagated,
otherwise it is silently ignored.
* `generated`: Marks rules that produce output files generated by a shell action.
The `exec` command implicitly assigns this attribute.
* `ignore`: The timestamp associated with *rule* is ignored in dependency resolution.
* `implicit`: Marks the current rule as an implicit prerequisite of the enclosing parent rule.
An implicit prerequisite can make the parent rule out of date without triggering the parent action.
Implicit prerequisites usually correspond to `#include` prerequisites.
For example, if `foo.o` is generated from `foo.c` and `foo.c` includes `foo.h`,
then `foo.h` should be marked as an implicit prerequisite of `foo.c`
so that touching `foo.h` does not make `foo.c` out of date while making `foo.o` out of date.
* `joint`: Ignored.
Historically used to mark one of a group of rules that are built by a single shell action.
* `notrace`: Disables echoing (xtrace) of shell action commands.
* `virtual`: Marks a rule that is not associated with any file.
The commands within are executed every time the Mamfile is processed.
By convention, a virtual rule named `all` makes everything,
and a virtual rule named `install` performs installation.

Specifying the following *attribute*s is deprecated
and will produce a warning in the strict mode:
* `archive`: Ignored.
Historically used to mark the generation of an `ar`(1) archive.
* `generated`: Marks rules that produce output files generated by a shell action.
The explicit assignment of this attribute is ignored in the strict mode.
The `exec` command implicitly assigns this attribute.
If a rule has this attribute, other rules dependent on this rule
will avoid applying viewpathing based on this rule.
* `joint`: Ignored.
Historically used to mark one of a group of rules that are built by a single shell action.

### Referencing prerequisites or previously defined rules ###

`prev` *rule* [ *attribute* ... ]
Expand All @@ -131,12 +143,12 @@ The `prev` command is used in two ways:
1. If *rule* is a previously defined rule, `prev` adds a dependency on that rule to the current rule.
This can be used to make a rule a prerequisite of multiple `make`...`done` blocks without repeating the rule.
No attributes should be given for this use of `prev`, because the attributes of the referenced rule are used.
Superfluous attributes are an error if the `MAMAKE_STRICT` variable has been set, otherwise they are ignored.
Superfluous attributes are an error in the strict mode and ignored in the legacy mode.

2. If *rule* is not a previously defined rule, the following applies.
If the `MAMAKE_STRICT` variable is not set, `prev` creates an empty dummy
In the legacy mode, `prev` creates an empty dummy
*rule* and ignores the *attribute*s; this is for backward compatibility.
If the `MAMAKE_STRICT` variable is set,
In the strict mode,
`prev` creates a rule that declares a dependency on a prerequisite file named by *rule*
in a manner equivalent to an empty `make`...`done` block,
with any *attribute*s given applied to the new rule, and
Expand Down
42 changes: 20 additions & 22 deletions src/cmd/INIT/mamake.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
* coded for portability
*/

#define RELEASE_DATE "2024-02-03"
#define RELEASE_DATE "2024-02-04"
static char id[] = "\n@(#)$Id: mamake (ksh 93u+m) " RELEASE_DATE " $\0\n";

#if _PACKAGE_ast
Expand Down Expand Up @@ -257,6 +257,8 @@ typedef struct View_s /* viewpath level */

static struct /* program state */
{
int strict; /* strict mode activated if set */

Buf_t* buf; /* work buffer */
Buf_t* old; /* dropped buffers */
Buf_t* opt; /* option buffer */
Expand Down Expand Up @@ -610,19 +612,6 @@ search(Dict_t* dict, char* name, void* value)
return NULL;
}

/*
* return true if in strict mode
*/

static int
strict(void)
{
static int found = -1;
if (found < 0)
found = search(state.vars, "MAMAKE_STRICT", NULL) != NULL;
return found;
}

/*
* low level for walk()
*/
Expand Down Expand Up @@ -1277,7 +1266,7 @@ run(Rule_t* r, char* s)
if (x)
{
/* stubs for backward compat */
if (!strict())
if (!state.strict)
append(buf,
"alias silent=\n"
"ignore() { env \"$@\" || :; }\n"
Expand Down Expand Up @@ -1504,8 +1493,9 @@ attributes(Rule_t* r, char* s)
flag = RULE_dontcare;
break;
case 'g':
/* 'exec' assigns this attribute; ignore explicit assignment in strict mode */
if (n == 9 && !strncmp(t, "generated", n))
flag = RULE_generated;
flag = state.strict ? -1 : RULE_generated;
break;
case 'i':
if (n == 6 && !strncmp(t, "ignore", n))
Expand Down Expand Up @@ -1537,6 +1527,9 @@ attributes(Rule_t* r, char* s)
t[n] = '\0';
report(3, "unknown attribute", t, 0);
}
/* deprecate ignored attributes */
else if (state.strict)
report(1, "deprecated", t, 0);
}
}

Expand Down Expand Up @@ -1751,12 +1744,12 @@ make(Rule_t* r)
if (*t)
{ /* target is optional; use it for sanity check if present */
q = rule(expand(buf, t));
if (q != r && (t[0] != '$' || strict()))
if (q != r && (t[0] != '$' || state.strict))
report(3, "mismatched done statement", t, 0);
if (*v)
{
if (strict())
report(1, v, "done: attributes are deprecated here, please move them to 'make'", 0);
if (state.strict)
report(1, v, "done: attributes deprecated; move to 'make'", 0);
attributes(r, v);
}
}
Expand Down Expand Up @@ -1810,7 +1803,7 @@ make(Rule_t* r)
case KEY('p','r','e','v'):
{
char *name = expand(buf, t);
if (!strict())
if (!state.strict)
q = rule(name); /* for backward compat */
else if (!(q = (Rule_t*)search(state.rules, name, NULL)))
{ /*
Expand Down Expand Up @@ -1840,6 +1833,8 @@ make(Rule_t* r)
continue;
}
case KEY('s','e','t','v'):
if (strcmp(t, "MAMAKE_STRICT") == 0)
state.strict = 1;
if (!search(state.vars, t, NULL))
{
if (*v == '"')
Expand All @@ -1859,11 +1854,14 @@ make(Rule_t* r)
probe();
}
continue;
case KEY('i','n','f','o'):
case KEY('n','o','t','e'):
case KEY('m','e','t','a'):
/* comment command */
continue;
case KEY('i','n','f','o'):
case KEY('m','e','t','a'):
if (!state.strict)
continue;
/* FALLTHROUGH */
default:
report(3, "unknown command", u, 0);
}
Expand Down
12 changes: 12 additions & 0 deletions src/cmd/INIT/mamake.rt
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
NOTE regression tests for the mamake command

# To regenerate mamake.tst from this file:
#
# bin/package use
# cd $INSTALLROOT # needed to stop mamake complaining about not being under VPATH
# mktest $PACKAGEROOT/src/cmd/INIT/mamake.rt > $PACKAGEROOT/src/cmd/INIT/mamake.tst
#
# WARNING: the regeneration assumes mamake's output is correct, so VERIFY THE RESULTS!
# Always do 'git diff mamake.tst' to check that no unexpected changes have been made.

# ======
# the one original AT&T test -- uses legacy mode

UNIT mamake

TEST macros
Expand Down
9 changes: 3 additions & 6 deletions src/lib/libast/Mamfile
Original file line number Diff line number Diff line change
Expand Up @@ -4999,11 +4999,8 @@ make install virtual
done install
make test dontcare virtual
make test.mamake virtual
make mamake.tst
prev ${PACKAGEROOT}/src/cmd/INIT/mamake.rt
exec - mktest --style=regress ${PACKAGEROOT}/src/cmd/INIT/mamake.rt > mamake.tst
done
exec - : testing the libast rebuild of mamake :
exec - regress mamake.tst mamake
prev ${PACKAGEROOT}/src/cmd/INIT/mamake.tst
exec - : testing the libast rebuild of mamake at $PWD/mamake :
exec - regress ${PACKAGEROOT}/src/cmd/INIT/mamake.tst mamake
done
done test

0 comments on commit 9d714fc

Please sign in to comment.