MPW Tools (split from MPW)
This commit is contained in:
commit
e6f0a12ef0
|
@ -0,0 +1,346 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <Files.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
Duplicate # duplicate files and directories
|
||||||
|
Duplicate [-y | -n | -c] [-p] [-d | -r] name... target > progress
|
||||||
|
-y # overwrite target files (avoids dialog)
|
||||||
|
-n # don't overwrite target files (avoids dialog)
|
||||||
|
-c # cancel if conflict occurs (avoids dialog)
|
||||||
|
-p # write progress information to diagnostics
|
||||||
|
-d # duplicate data fork only
|
||||||
|
-r # duplicate resource fork only
|
||||||
|
-rs # resolve leaf aliases in the source path(s)
|
||||||
|
-rt # resolve leaf aliases in the target path
|
||||||
|
-f # preserve Finder icon locations
|
||||||
|
|
||||||
|
*/
|
||||||
|
// todo -- support src1 src2 ... dest/
|
||||||
|
|
||||||
|
|
||||||
|
char *c2p(const char *cp)
|
||||||
|
{
|
||||||
|
int length;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if (!cp) return NULL;
|
||||||
|
length = strlen(cp);
|
||||||
|
if (length > 255)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error: Pathname is too long.\n");
|
||||||
|
exit(1);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = malloc(length + 2); // + 2 for \0 and length.
|
||||||
|
if (!p)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error: unable to allocate memory.\n");
|
||||||
|
exit(1);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
p[0] = length;
|
||||||
|
memcpy(p + 1, cp, length + 1);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void help(void)
|
||||||
|
{
|
||||||
|
fprintf(stdout, "Usage: Duplicate [-y | -n | -c] [-p] [-d |-r] source destination\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int getopt(int *opts, int argc, char **argv)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (i = 1; i < argc; ++i)
|
||||||
|
{
|
||||||
|
char *str = argv[i];
|
||||||
|
char c = str[0];
|
||||||
|
|
||||||
|
if (c != '-') return i;
|
||||||
|
++str;
|
||||||
|
|
||||||
|
// -- to terminate
|
||||||
|
if (str[0] == '-' && str[1] == 0)
|
||||||
|
return i + 1;
|
||||||
|
|
||||||
|
// skip -rt, -rs
|
||||||
|
if (str[0] == 'r' && str[1] == 's' && str[2] == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (str[0] == 'r' && str[1] == 't' && str[2] == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (; *str; ++str)
|
||||||
|
{
|
||||||
|
c = *str;
|
||||||
|
switch(c)
|
||||||
|
{
|
||||||
|
case 'r':
|
||||||
|
case 'd':
|
||||||
|
opts['r' - 'a'] = 0;
|
||||||
|
opts['d' - 'a'] = 0;
|
||||||
|
opts[c - 'a'] = 1;
|
||||||
|
break;
|
||||||
|
case 'y':
|
||||||
|
case 'n':
|
||||||
|
case 'c':
|
||||||
|
opts['y' - 'a'] = 0;
|
||||||
|
opts['n' - 'a'] = 0;
|
||||||
|
opts['c' - 'a'] = 0;
|
||||||
|
opts[c - 'a'] = 1;
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
opts[c - 'a'] = 1;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
help();
|
||||||
|
exit(0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Duplicate - Invalid flag: \"%c\"\n", c);
|
||||||
|
exit(1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int copyFork(const char *src, const char *dest, unsigned fork)
|
||||||
|
{
|
||||||
|
static char buffer[4096];
|
||||||
|
|
||||||
|
int rfd, wfd;
|
||||||
|
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
fork = fork ? O_RSRC : 0;
|
||||||
|
|
||||||
|
rfd = open(src, O_RDONLY | O_BINARY | fork);
|
||||||
|
if (rfd < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error opening %s: %s\n", src, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// no 3rd parameter to open.
|
||||||
|
wfd = open(dest, O_WRONLY | O_BINARY | O_CREAT |O_TRUNC| fork);
|
||||||
|
if (wfd < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error opening %s: %s\n", dest, strerror(errno));
|
||||||
|
close(rfd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = -1;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
ssize_t rsize;
|
||||||
|
ssize_t wsize;
|
||||||
|
|
||||||
|
rsize = read(rfd, buffer, sizeof(buffer));
|
||||||
|
if (rsize == 0)
|
||||||
|
{
|
||||||
|
rv = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (rsize < 0)
|
||||||
|
{
|
||||||
|
if (errno == EINTR) continue;
|
||||||
|
fprintf(stderr, "Error reading %s: %s\n", src, strerror(errno));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
wsize = write(wfd, buffer, rsize);
|
||||||
|
if (wsize != rsize)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error writing %s: %s\n", dest, strerror(errno));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(rfd);
|
||||||
|
close(wfd);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
int copyFinderInfo(const char *src, const char *dest)
|
||||||
|
{
|
||||||
|
FInfo finderInfo;
|
||||||
|
OSErr status;
|
||||||
|
|
||||||
|
char *psrc;
|
||||||
|
char *pdest;
|
||||||
|
|
||||||
|
psrc = c2p(src);
|
||||||
|
pdest = c2p(dest);
|
||||||
|
if (!psrc || !pdest) return -1;
|
||||||
|
|
||||||
|
// getfinfo/setfinfo seem to have bugs.
|
||||||
|
|
||||||
|
memset(&finderInfo, 0, sizeof(finderInfo));
|
||||||
|
|
||||||
|
status = GetFInfo((unsigned char *)psrc, 0, &finderInfo);
|
||||||
|
if (status == 0)
|
||||||
|
{
|
||||||
|
status = SetFInfo((unsigned char *)pdest, 0, &finderInfo);
|
||||||
|
}
|
||||||
|
free(psrc);
|
||||||
|
free(pdest);
|
||||||
|
|
||||||
|
if (status) return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int createFile(const char *src, const char *dest)
|
||||||
|
{
|
||||||
|
FInfo finderInfo;
|
||||||
|
OSErr status;
|
||||||
|
|
||||||
|
char *psrc;
|
||||||
|
char *pdest;
|
||||||
|
|
||||||
|
psrc = c2p(src);
|
||||||
|
pdest = c2p(dest);
|
||||||
|
if (!psrc || !pdest) return -1;
|
||||||
|
|
||||||
|
memset(&finderInfo, 0, sizeof(finderInfo));
|
||||||
|
|
||||||
|
status = GetFInfo((unsigned char *)psrc, 0, &finderInfo);
|
||||||
|
|
||||||
|
status = Create((unsigned char *)pdest, 0, finderInfo.fdCreator, finderInfo.fdType);
|
||||||
|
free(psrc);
|
||||||
|
free(pdest);
|
||||||
|
|
||||||
|
if (status) return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -1 - error.
|
||||||
|
// 0 - no file
|
||||||
|
// 1 - regular file
|
||||||
|
// 2 - directory.
|
||||||
|
int mode(const char *path)
|
||||||
|
{
|
||||||
|
char *pname;
|
||||||
|
CInfoPBRec rec;
|
||||||
|
OSErr status;
|
||||||
|
|
||||||
|
memset(&rec, 0, sizeof(rec));
|
||||||
|
|
||||||
|
pname = c2p(path);
|
||||||
|
if (!pname) return -1;
|
||||||
|
|
||||||
|
rec.hFileInfo.ioNamePtr = (unsigned char *)pname;
|
||||||
|
status = PBGetCatInfo(&rec, false);
|
||||||
|
free(pname);
|
||||||
|
|
||||||
|
if (status) return 0;
|
||||||
|
if (rec.hFileInfo.ioFlAttrib & kioFlAttribDirMask)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int opts[26];
|
||||||
|
int optind;
|
||||||
|
int ok;
|
||||||
|
char *src;
|
||||||
|
char *dest;
|
||||||
|
int m;
|
||||||
|
|
||||||
|
memset(opts, 0, sizeof(opts));
|
||||||
|
|
||||||
|
opts['n' - 'a'] = 1;
|
||||||
|
optind = getopt(opts, argc, argv);
|
||||||
|
argc -= optind;
|
||||||
|
argv += optind;
|
||||||
|
|
||||||
|
if (argc != 2)
|
||||||
|
{
|
||||||
|
help();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
src = argv[0];
|
||||||
|
dest = argv[1];
|
||||||
|
|
||||||
|
// 1. check if src exists
|
||||||
|
// 2. check if dest exists
|
||||||
|
|
||||||
|
// 3. copy data fork unless -r
|
||||||
|
// 4. copy resource fork unless -d
|
||||||
|
// 5. copy finder info.
|
||||||
|
|
||||||
|
ok = 0;
|
||||||
|
// -n - do not overwrite
|
||||||
|
// -c - cancel if conflict
|
||||||
|
|
||||||
|
m = mode(dest);
|
||||||
|
if (m == 2)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error: directory destination is not yet supported.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (m == 0 && opts['r' - 'a'])
|
||||||
|
{
|
||||||
|
// workaround to create the file if
|
||||||
|
// only copying the resource fork.
|
||||||
|
|
||||||
|
// TODO -- call Create(name, 0, creator, filetype)
|
||||||
|
|
||||||
|
if (opts['p' - 'a'])
|
||||||
|
printf("Creating file %s\n", dest);
|
||||||
|
ok = createFile(src, dest);
|
||||||
|
if (ok < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error creating %s\n", dest);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m == 1)
|
||||||
|
{
|
||||||
|
// todo -- should this check at the file level or at the fork level?
|
||||||
|
// seems to check at the file level.
|
||||||
|
|
||||||
|
// file exists.
|
||||||
|
if (opts['c' - 'a'] || opts['n' - 'a'])
|
||||||
|
{
|
||||||
|
if (opts['p' - 'a'])
|
||||||
|
{
|
||||||
|
printf("File exists - nothing done.\n");
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (opts['r' - 'a'] == 0)
|
||||||
|
{
|
||||||
|
if (opts['p' - 'a'])
|
||||||
|
printf("Copying Data Fork.\n");
|
||||||
|
ok = copyFork(src, dest, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts['d' - 'a'] == 0)
|
||||||
|
{
|
||||||
|
if (opts['p' - 'a'])
|
||||||
|
printf("Copying Resource Fork.\n");
|
||||||
|
ok = copyFork(src, dest, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* GetEnv variable
|
||||||
|
* read an mpw variable.
|
||||||
|
* eg: CLibraries=`mpw GetEnv CLibraries`
|
||||||
|
* (makefile) CLibraries = $(shell mpw GetEnv CLibraries)
|
||||||
|
* flags to do name = value?
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *value;
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
if (argc != 2)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
name = argv[1];
|
||||||
|
value = getenv(name);
|
||||||
|
// value == null if not defined.
|
||||||
|
if (value) puts(value);
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
/*
* MPW Help utility.
*
* help topic
* does a cat of $ShellDirectory:Help:topic
*/
/*
* MPW 3.2
*
* C Help.c -o Help.c.o -r {SymOptions}
*
* Link {SymOptions} -w -c 'MPS ' -t MPST Help.c.o ∂
* -sn STDIO=Main ∂
* -sn INTENV=Main ∂
* -sn %A5Init=Main ∂
* "{Libraries}"Stubs.o ∂
* "{CLibraries}"StdCLib.o ∂
* "{Libraries}"Interface.o ∂
* "{Libraries}"Runtime.o ∂
* "{Libraries}"ToolLibs.o ∂
* -o Help
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *base(char *str)
{
char *rv = str;
char *tmp = str;
if (!str) return str;
for (tmp = str; *tmp; ++tmp)
{
char c = *tmp;
if (c == ':' || c == '/') rv = tmp + 1;
}
return rv;
}
void help(char *root, char *topic)
{
int l;
char *path;
FILE *fp;
// todo -- check if they're being stupid or malicious and
// handle / or : chars.
topic = base(topic);
if (!topic || !*topic)
{
return;
}
l = strlen(root) + strlen("Help:") + strlen(topic) + 1;
path = malloc(1);
if (!path)
{
fprintf(stderr, "### Help - Memory allocation failure.\n");
return;
}
sprintf(path, "%sHelp:%s", root, topic);
fp = fopen(path, "r");
free(path);
if (!fp)
{
fprintf(stderr, "### Help - \"%s\" was not found.\n", topic);
return;
}
for(;;)
{
char buffer[512];
int count;
count = fread(buffer, 1, sizeof(buffer), fp);
if (count == 0) break;
fwrite(buffer, 1, count, stdout);
}
fwrite("\r", 1, 1, stdout);
fclose(fp);
}
int main(int argc, char **argv)
{
char *root;
root = getenv("ShellDirectory");
if (!root || !*root)
{
fprintf(stderr, "### Help - $ShellDirectory is not defined.\n");
return 1;
}
if (argc == 1)
{
help(root, "MPW");
}
else
{
int i;
for (i = 1; i < argc; ++i)
{
help(root, argv[i]);
}
}
return 0;
}
|
|
@ -0,0 +1,151 @@
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include <Finder.h>
|
||||||
|
#include <Files.h>
|
||||||
|
|
||||||
|
#include "SetFile-flags.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int tox(char c)
|
||||||
|
{
|
||||||
|
c |= 0x20;
|
||||||
|
if (c >='0' && c <= '9') return c - '0';
|
||||||
|
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hex(const char *in, char *out, int length)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < length; ++i)
|
||||||
|
{
|
||||||
|
int tmp = 0;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
c = *in++;
|
||||||
|
if (!isxdigit(c)) return -1;
|
||||||
|
tmp |= tox(c) << 4;
|
||||||
|
|
||||||
|
c = *in++;
|
||||||
|
if (!isxdigit(c)) return -1;
|
||||||
|
tmp |= tox(c);
|
||||||
|
|
||||||
|
*out++ = tmp;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert the file/creators...
|
||||||
|
// format:
|
||||||
|
// 0x \xdigit{8}
|
||||||
|
// $ \xdigit{8}
|
||||||
|
// 4-cc code
|
||||||
|
int checkcode(const char *in, char *out)
|
||||||
|
{
|
||||||
|
int length;
|
||||||
|
|
||||||
|
length = strlen(in);
|
||||||
|
|
||||||
|
if (length == 4)
|
||||||
|
{
|
||||||
|
// 4 cc code.
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 4; ++i)
|
||||||
|
out[i] = in[i];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length == 9 && in[0] == '$')
|
||||||
|
return hex(in + 1, out, 4);
|
||||||
|
|
||||||
|
if (length ==10 && in[0] == '0' && in[1] == 'x')
|
||||||
|
return hex(in + 2, out, 4);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
|
||||||
|
FInfo newFI;
|
||||||
|
int optind;
|
||||||
|
int ok;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
|
||||||
|
optind = FlagsParse(argc, argv);
|
||||||
|
|
||||||
|
argc -= optind;
|
||||||
|
argv += optind;
|
||||||
|
|
||||||
|
if (argc == 0)
|
||||||
|
{
|
||||||
|
FlagsHelp();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
memset(&newFI, 0, sizeof(newFI));
|
||||||
|
|
||||||
|
if (!flags._t && !flags._c) return 0;
|
||||||
|
|
||||||
|
if (flags._t)
|
||||||
|
{
|
||||||
|
ok = checkcode(flags._t, (char *)&newFI.fdType);
|
||||||
|
if (ok < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "SetFile: invalid file type: `%s`\n", flags._t);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags._c)
|
||||||
|
{
|
||||||
|
ok = checkcode(flags._c, (char *)&newFI.fdCreator);
|
||||||
|
if (ok < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "SetFile: invalid creator type: `%s`\n", flags._c);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < argc; ++i)
|
||||||
|
{
|
||||||
|
FInfo fi;
|
||||||
|
char buffer[256];
|
||||||
|
char *cp;
|
||||||
|
int l;
|
||||||
|
|
||||||
|
cp = argv[i];
|
||||||
|
l = strlen(cp);
|
||||||
|
if (l > 255)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "SetFile: %s: file name too long.\n", cp);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer[0] = l;
|
||||||
|
memcpy(buffer + 1, cp, l);
|
||||||
|
|
||||||
|
memset(&fi, 0, sizeof(fi));
|
||||||
|
|
||||||
|
ok = GetFInfo((unsigned char *)buffer, 0, &fi);
|
||||||
|
|
||||||
|
if (flags._t) fi.fdType = newFI.fdType;
|
||||||
|
if (flags._c) fi.fdCreator = newFI.fdCreator;
|
||||||
|
|
||||||
|
ok = SetFInfo((unsigned char *)buffer, 0, &fi);
|
||||||
|
if (ok != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "SetFile: %s: unable to set finder info: %d\n", cp, ok);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,314 @@
|
||||||
|
#!/usr/bin/env ruby -w
|
||||||
|
|
||||||
|
# process the flags.yaml file
|
||||||
|
# and generate a flags.h and flags.c file.
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# todo -- support for long-options (--longoption, --longoption=value, etc)
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
require 'erb'
|
||||||
|
require 'yaml'
|
||||||
|
|
||||||
|
header_preamble = <<EOF
|
||||||
|
|
||||||
|
#ifndef __flags_h__
|
||||||
|
#define __flags_h__
|
||||||
|
|
||||||
|
typedef struct Flags {
|
||||||
|
EOF
|
||||||
|
|
||||||
|
header_postamble = <<EOF
|
||||||
|
} Flags;
|
||||||
|
|
||||||
|
|
||||||
|
extern struct Flags flags;
|
||||||
|
|
||||||
|
int FlagsParse(int argc, char **argv);
|
||||||
|
|
||||||
|
void FlagsHelp(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
|
||||||
|
class Option
|
||||||
|
@@map = {
|
||||||
|
# some of these are a bad idea but whatever...
|
||||||
|
'>' => 'gt',
|
||||||
|
'<' => 'lt',
|
||||||
|
',' => 'comma',
|
||||||
|
'.' => 'period',
|
||||||
|
'/' => 'forward_slash',
|
||||||
|
'\\' => 'back_slash',
|
||||||
|
'?' => 'question',
|
||||||
|
'|' => 'pipe',
|
||||||
|
'~' => 'tilde',
|
||||||
|
'`' => 'grave',
|
||||||
|
'!' => 'bang',
|
||||||
|
'@' => 'at',
|
||||||
|
'#' => 'hash',
|
||||||
|
'$' => 'dollar',
|
||||||
|
'%' => 'percent',
|
||||||
|
'^' => 'caret',
|
||||||
|
'&' => 'ampersand',
|
||||||
|
'*' => 'star',
|
||||||
|
'(' => 'left_paren',
|
||||||
|
')' => 'right_paren',
|
||||||
|
'-' => 'minus',
|
||||||
|
'+' => 'plus',
|
||||||
|
'=' => 'equal',
|
||||||
|
'[' => 'left_bracket',
|
||||||
|
']' => 'right_bracket',
|
||||||
|
'{' => 'left_brace',
|
||||||
|
'}' => 'right_brace',
|
||||||
|
':' => 'colon',
|
||||||
|
';' => 'semi_colon',
|
||||||
|
'\'' => 'apostrophe',
|
||||||
|
'"' => 'quote'
|
||||||
|
}
|
||||||
|
|
||||||
|
def initialize(hash)
|
||||||
|
|
||||||
|
@char = hash['char'].to_s
|
||||||
|
@argument = hash['argument'] || false
|
||||||
|
|
||||||
|
@flag_name = hash['flag_name']
|
||||||
|
@flag_name = @flag_name.to_s if @flag_name
|
||||||
|
|
||||||
|
@xor = hash['xor'] || []
|
||||||
|
@xor = case @xor
|
||||||
|
when Array
|
||||||
|
@xor
|
||||||
|
when Integer, String
|
||||||
|
[ @xor ]
|
||||||
|
else
|
||||||
|
raise "Invalid xor type: #{@xor}"
|
||||||
|
end
|
||||||
|
|
||||||
|
@xor.map! { |x| x.to_s }
|
||||||
|
end
|
||||||
|
|
||||||
|
attr_reader :char, :xor, :argument
|
||||||
|
|
||||||
|
def flag_name
|
||||||
|
return @flag_name if @flag_name
|
||||||
|
return self.class.flag_name(@char)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.flag_name(char)
|
||||||
|
return '_' + @@map[char] if @@map[char]
|
||||||
|
return '_' + char
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
# better ARGF.
|
||||||
|
def argf_each
|
||||||
|
|
||||||
|
if ARGV.count > 0
|
||||||
|
|
||||||
|
ARGV.each {|file|
|
||||||
|
|
||||||
|
File.open(file, "r") {|io|
|
||||||
|
yield file, io
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
yield nil, $stdin
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def escape_cstr(x)
|
||||||
|
|
||||||
|
# escape a c string
|
||||||
|
|
||||||
|
x.gsub(/([\\"])/, "\\\\1")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
code = ERB.new(DATA.read(), 0, "%<>")
|
||||||
|
|
||||||
|
argf_each {|filename, file|
|
||||||
|
|
||||||
|
|
||||||
|
data = YAML.load(file)
|
||||||
|
|
||||||
|
help = data['help']
|
||||||
|
options = data['options']
|
||||||
|
|
||||||
|
# options is an array of items which may be hashes, strings, or numbers.
|
||||||
|
# normalize them.
|
||||||
|
|
||||||
|
options = options.map {|opt|
|
||||||
|
|
||||||
|
opt = case opt
|
||||||
|
when String, Integer
|
||||||
|
{ 'char' => opt }
|
||||||
|
when Hash
|
||||||
|
# {'o' => { ... }}
|
||||||
|
# or
|
||||||
|
# {'char' => , ... }
|
||||||
|
if opt['char']
|
||||||
|
opt
|
||||||
|
else
|
||||||
|
opt = opt.first
|
||||||
|
opt[1].merge({ 'char' => opt[0] })
|
||||||
|
end
|
||||||
|
else
|
||||||
|
raise "Unexpected data type: #{opt}"
|
||||||
|
end
|
||||||
|
|
||||||
|
Option.new(opt)
|
||||||
|
}
|
||||||
|
|
||||||
|
#data[options] = options
|
||||||
|
# check for help?
|
||||||
|
|
||||||
|
basename = filename
|
||||||
|
basename = $1 if filename && filename =~ /^(.*)\./
|
||||||
|
|
||||||
|
b = binding # bind help, options for ERB.
|
||||||
|
|
||||||
|
io = basename ? File.open(basename + ".c", "w") : $stdout
|
||||||
|
io.write(code.result(b))
|
||||||
|
|
||||||
|
io.close unless io == $stdout
|
||||||
|
|
||||||
|
|
||||||
|
io = basename ? File.open(basename + ".h", "w") : $stdout
|
||||||
|
io.write(header_preamble)
|
||||||
|
# two passes - one with arguments, one without.
|
||||||
|
options.each {|opt|
|
||||||
|
if opt.argument
|
||||||
|
io.printf(" char *%s;\n", opt.flag_name)
|
||||||
|
end
|
||||||
|
}
|
||||||
|
io.puts()
|
||||||
|
options.each {|opt|
|
||||||
|
if !opt.argument
|
||||||
|
io.printf(" unsigned %s:1;\n", opt.flag_name)
|
||||||
|
end
|
||||||
|
}
|
||||||
|
io.puts
|
||||||
|
|
||||||
|
io.write(header_postamble)
|
||||||
|
io.close unless io == $stdout
|
||||||
|
|
||||||
|
|
||||||
|
# #puts options.to_yaml
|
||||||
|
# puts code.result(binding())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__END__
|
||||||
|
|
||||||
|
#ifdef __ORCAC__
|
||||||
|
#pragma optimize 79
|
||||||
|
#pragma noroot
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "<%= basename + '.h' %>"
|
||||||
|
|
||||||
|
void FlagsHelp(void)
|
||||||
|
{
|
||||||
|
% help.each do |h|
|
||||||
|
fputs("<%= escape_cstr(h) %>\n", stdout);
|
||||||
|
% end
|
||||||
|
fputs("\n", stdout);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Flags flags;
|
||||||
|
int FlagsParse(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *cp;
|
||||||
|
char c;
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
memset(&flags, 0, sizeof(flags));
|
||||||
|
|
||||||
|
for (i = 1; i < argc; ++i)
|
||||||
|
{
|
||||||
|
cp = argv[i];
|
||||||
|
c = cp[0];
|
||||||
|
|
||||||
|
if (c != '-')
|
||||||
|
return i;
|
||||||
|
|
||||||
|
// -- = end of options.
|
||||||
|
if (cp[1] == '-' && cp[2] == 0)
|
||||||
|
return i + 1;
|
||||||
|
|
||||||
|
// now scan all the flags in the string...
|
||||||
|
for (j = 1; ; ++j)
|
||||||
|
{
|
||||||
|
int skip = 0;
|
||||||
|
|
||||||
|
c = cp[j];
|
||||||
|
if (c == 0) break;
|
||||||
|
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
% if help && !options.find_index {|x| x.char == 'h' }
|
||||||
|
case 'h':
|
||||||
|
FlagsHelp();
|
||||||
|
break;
|
||||||
|
% end
|
||||||
|
% #
|
||||||
|
% options.each do |opt|
|
||||||
|
case '<%= escape_cstr(opt.char) %>':
|
||||||
|
% # check for an argument.
|
||||||
|
% flag_name = 'flags.' + opt.flag_name
|
||||||
|
% #
|
||||||
|
% if opt.argument
|
||||||
|
// -xarg or -x arg
|
||||||
|
skip = 1;
|
||||||
|
if (cp[j + 1])
|
||||||
|
{
|
||||||
|
<%= flag_name %> = cp + j + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (++i >= argc)
|
||||||
|
{
|
||||||
|
fputs("option requires an argument -- <%= opt.char %>\n", stderr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
<%= flag_name %> = argv[i];
|
||||||
|
}
|
||||||
|
% else # no argument.
|
||||||
|
<%= flag_name %> = 1;
|
||||||
|
% end # if no argument.
|
||||||
|
% #
|
||||||
|
% # unset any exclusive or values
|
||||||
|
% opt.xor.each do |xor_opt|
|
||||||
|
flags.<%= Option.flag_name(xor_opt) %> = 0;
|
||||||
|
%end
|
||||||
|
break;
|
||||||
|
% end # options.each
|
||||||
|
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "illegal option -- %c\n", c);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skip) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
# makefile
|
||||||
|
|
||||||
|
Libraries=~/mpw/Libraries/Libraries
|
||||||
|
CLibraries=~/mpw/Libraries/CLibraries
|
||||||
|
|
||||||
|
# MPW 3.2
|
||||||
|
LIBS = \
|
||||||
|
$(Libraries)/Stubs.o \
|
||||||
|
$(CLibraries)/StdCLib.o \
|
||||||
|
$(Libraries)/Interface.o \
|
||||||
|
$(Libraries)/Runtime.o \
|
||||||
|
$(Libraries)/ToolLibs.o
|
||||||
|
|
||||||
|
LDFLAGS = -w -c 'MPS ' -t MPST \
|
||||||
|
-sn STDIO=Main -sn INTENV=Main -sn %A5Init=Main
|
||||||
|
|
||||||
|
# MPW 3.5
|
||||||
|
|
||||||
|
# LIBS = \
|
||||||
|
# $(CLibraries)/StdCLib.o \
|
||||||
|
# $(Libraries)/Stubs.o \
|
||||||
|
# $(Libraries)/IntEnv.o \
|
||||||
|
# $(Libraries)/MacRuntime.o \
|
||||||
|
# $(Libraries)/Interface.o \
|
||||||
|
# $(Libraries)/ToolLibs.o
|
||||||
|
|
||||||
|
# LDFLAGS = -d -c 'MPS ' -t MPST
|
||||||
|
|
||||||
|
all: Help GetEnv Duplicate SetFile
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.c.o
|
||||||
|
rm -f Help GetEnv Duplicate SetFile
|
||||||
|
|
||||||
|
GetEnv: GetEnv.c.o
|
||||||
|
mpw Link $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||||
|
|
||||||
|
Help: Help.c.o
|
||||||
|
mpw Link $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||||
|
|
||||||
|
|
||||||
|
Duplicate: Duplicate.c.o
|
||||||
|
mpw Link $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||||
|
|
||||||
|
|
||||||
|
SetFile: SetFile.c.o SetFile-flags.c.o
|
||||||
|
mpw Link $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||||
|
|
||||||
|
|
||||||
|
#SetFile.c : SetFile.rl
|
||||||
|
# ragel -G2 -p -m -o $@ $<
|
||||||
|
|
||||||
|
|
||||||
|
%.c.o : %.c
|
||||||
|
mpw SC -p $< -o $@
|
||||||
|
|
||||||
|
# GetEnv.c.o : GetEnv.c
|
||||||
|
# mpw SC -p GetEnv.c -o $@
|
||||||
|
|
||||||
|
# Help.c.o : Help.c
|
||||||
|
# mpw SC -p Help.c -o $@
|
|
@ -0,0 +1,44 @@
|
||||||
|
#!/usr/bin/env ruby -w
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# format
|
||||||
|
# -
|
||||||
|
# name # comment
|
||||||
|
#
|
||||||
|
|
||||||
|
file = nil
|
||||||
|
state = nil
|
||||||
|
#ARGF.binmode
|
||||||
|
#ARGF.set_encoding("BINARY")
|
||||||
|
ARGF.each { |line|
|
||||||
|
|
||||||
|
line.chomp!
|
||||||
|
|
||||||
|
case state
|
||||||
|
when nil
|
||||||
|
if line == '-'
|
||||||
|
state = :name
|
||||||
|
end
|
||||||
|
|
||||||
|
when :name
|
||||||
|
if line.match(/^([A-Za-z0-F]+)\s?#?/)
|
||||||
|
state = :data
|
||||||
|
filename = $1
|
||||||
|
file = File::new("Help.Files/#{filename}", "w")
|
||||||
|
#file.set_encoding("BINARY")
|
||||||
|
end
|
||||||
|
|
||||||
|
when :data
|
||||||
|
if line == '-'
|
||||||
|
state = :name
|
||||||
|
file = nil
|
||||||
|
else
|
||||||
|
file.puts(line)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue