[mercury-users] Problem with mmake
Richard A. O'Keefe
ok at atlas.otago.ac.nz
Thu May 31 13:29:01 AEST 2001
Fergus Henderson <fjh at cs.mu.OZ.AU> wrote:
If you don't use --use-subdirs, then Mmake does assume that anything named
*.d in the current directory is a dependency file. I don't think it is
worth changing that assumption, since it would complicate the software,
and it is easy to avoid, either by using --use-subdirs, or by naming your
directories something different.
It's a bug. It should be easy enough to fix.
I *don't* want to use --use-subdirs, and I don't see why I should have to
change a naming convention that has worked perfectly well for the last 20
years just because one program is a bit lazy about checking.
At Quintus we had a customer complain about [foo] trying to load a directory,
and I personally fixed the responsible code. C'mon, it *can't* be hard
to fix this bug. [Wait an hour.... I've fixed it.]
Mmake should certainly issue a proper error message rather than just
dumping the directory in binary. However, Mmake just uses the system
utility `cat'. If `cat' is dumping the binary contents of directories,
rather than reporting an error message to stderr, I'd consider that a bug
in `cat'.
It is documented behaviour in UNIX ever since Version 6.
I suggest you contact your OS vendor, and in the mean time
install GNU cat (it's part of the GNU textutils package).
I can confidently predict that the OS vendor will refuse to "correct" a
program that works precisely as documented.
On Solaris 2.7 (SunOS 5.7), /bin/cat seems to do the right thing for
directories (i.e. it reports an error "cat: input error on foo.d:
Invalid argument"). Which version of Solaris are you using?
Ever since NFS came out, SunOS and then Solaris have been consistently
inconsistent here. *Local* directories are readable, *NFS* directories
are not. I discovered this the hard way 15 years ago, when a certain
directory was readable on the server but not a client. It has nothing
to do with 'cat'; _any_ program trying to open a directory on a local hard
disc for input will succeed, _any_ program trying to open an NFS-mounted
directory for input will fail.
Here is the simple fix.
Change code like
dvs="`echo *.dv`"
if [ "$dvs" = "*.dv" ]; then
dvs=""
fi
in mmake to
dvs="`mmfind .dv`"
with similar changes for deps and ds, and also change code like
dvs="`echo Mercury/deps/*.dv`"
if [ "$dvs" = "Mercury/deps/*.dv" ]; then
dvs=""
fi
in mmake to
dvs="`mmfind Mercury/deps .dv`"
with similar changes for deps and ds,
where mmfind is obtained by compiling the following file with -DMAIN:
/* File : mmfind.c
Author : Richard A. O'Keefe
Updated: 2001.05.31
Purpose: Find readable plain-text files with a given suffix.
Usage : mmfind(suffix, handler); passes name and stat record to handler.
Command: mmfind [dir] {suffix} writes file names one per line.
Errors : function returns 0 for success, -1 for failure.
Note : file names beginning with '.' are not reported.
Compile: with -DMAIN to get the command, otherwise you just get the fn.
mmfind suffix
reports all the file names in the current directory that
- don't begin with "."
- are strictly longer than suffix
- end with suffix
- can be opened for input
- and are not directories.
mmfind directory suffix
does the same thing in directory; each output line has the form
directory/filename
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
int mmfind(
char const *suffix,
void (*handler)(char const *, struct stat const *)
) {
size_t suflen, namlen;
DIR *d;
struct dirent *f;
struct stat b;
int fd;
if (suffix == (char const *)0
|| handler == (void (*)(char const *, struct stat const *))0
) return errno = EINVAL, -1;
d = opendir(".");
if (d == 0) return -1; /* errno set by opendir() */
suflen = strlen(suffix);
while ((f = readdir(d)) != (struct dirent *)0) {
if (f->d_name[0] != '.'
&& (namlen = strlen(f->d_name)) > suflen
&& 0 == strcmp(f->d_name + (namlen - suflen), suffix)
&& (fd = open(f->d_name, O_RDONLY, 0)) >= 0
&& fstat(fd, &b) >= 0
&& S_ISREG(b.st_mode)
) {
handler(f->d_name, &b);
}
}
(void)closedir(d);
return 0;
}
#ifdef MAIN
#include <stdio.h>
#include <stdlib.h>
static char *directory = (char *)0;
static void handler(char const *name, struct stat const *buf) {
if ((directory == (char *)0 ? puts(name)
: printf("%s/%s\n", directory, name)
) < 0
) {
perror("/dev/stdout");
exit(EXIT_FAILURE);
}
}
int main(int argc, char **argv) {
if (argc == 3) {
directory = argv[1];
if (chdir(directory) < 0) {
perror(directory);
return EXIT_FAILURE;
}
argv++, argc--;
} else {
if (argc != 2) {
fprintf(stderr, "Usage: %s SUFFIX\n", argv[0]);
return EXIT_FAILURE;
}
}
if (mmfind(argv[1], handler) < 0) {
perror(argv[0]);
return EXIT_FAILURE;
}
if (fflush(stdout) != 0) {
perror("/dev/stdout");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
#endif
--------------------------------------------------------------------------
mercury-users mailing list
post: mercury-users at cs.mu.oz.au
administrative address: owner-mercury-users at cs.mu.oz.au
unsubscribe: Address: mercury-users-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-users-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the users
mailing list