diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /dviware/beebe/src/bintnxvm.c |
Initial commit
Diffstat (limited to 'dviware/beebe/src/bintnxvm.c')
-rw-r--r-- | dviware/beebe/src/bintnxvm.c | 390 |
1 files changed, 390 insertions, 0 deletions
diff --git a/dviware/beebe/src/bintnxvm.c b/dviware/beebe/src/bintnxvm.c new file mode 100644 index 0000000000..ff71700f68 --- /dev/null +++ b/dviware/beebe/src/bintnxvm.c @@ -0,0 +1,390 @@ +/*********************************************************************** +Convert a TOPS-20 file transferred in FTP "binary" mode to "tenex" mode. +In "binary" mode, we have 2 36-bit words in 9 8-bit bytes. In "tenex" +mode, we want the top 32 bits of each 36-bit group, giving 8 8-bit +bytes. + +Who knows what FTP did if the file had an odd number of 36-bit words. + +[08-Oct-87] + +This version is intended for VAX VMS only. Modified by Jerry Leichter +(LEICHTER@VENUS.YCC.YALE.ARPA). + +Usage: + bintnxvms [-f[xx]] [filespec] + +Filespec may be wild-carded; if it is missing, *.* is assumed. Each +matching file is read, and a new version the same specification is +created. (Note that you can only specify one filespec, however.) If +-fxx is specified, the last block of the file is filled with bytes of +the given value (xx), which must be a hex number. If -f is given with +no value, 0 is assumed. Appropriate values seem to be: + + * DVI DF + * GF DF + PK F6 (File spec defines no filler, F6 may be an artifact) + PXL ?? (Unknown, probably not significant) + TFM 00 (File spec defines no filler) + +"Fill" is definitely significant, at least in some applications, for the +file types marked, with a "*"; it probably doesn't matter for others. +Note, how- ever, that there is no certainty that files filled this way +will actually be readable to all programs, since the transfer process +may insert other random junk at the end of the file. + +The filler is used by programs that wish to read the files from end to +beginning - for example, by DVI file translators that need to reverse +page order. The author has observed that "fixed up" files often follow +the pattern: + + <data> <fill-bytes> <FFFFFFFF> <fill-bytes> end-of-block + +The first set of fill bytes were probably inserted by the program that +wrote the file to being with. (There should be from 1 to 4 of them, +bringing the file to an even number of 4-byte longwords.) The +<FFFFFFFF> filler is four bytes of hex FF characters, and probably +were inserted by VMS FTP to mark the end of the file on the TOPS-20 +system. The rest of the <fill-bytes> were inserted by fixfile. If +you run into a program that is unable to read a file produced by +fixfile, DUMP the last block of the file and see if this pattern +occurs. If so, it should be straightforward to over-write the FF's +with more <fill-byte>'s. +***********************************************************************/ + +#include <ctype.h> +#include <stdio.h> +#include <rms.h> + +FILE *fwild(); +FILE *fnext(); + +main(argc, argv) +int argc; +char *argv[]; +{ + FILE *infile; + FILE *outfile; + int fill = FALSE; + int fillchar = 0; + char *fspec; + char thefile[NAM$C_MAXRSS + 1]; + char *c; + int d; + + if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'f') + { + fill = TRUE; + c = &argv[1][2]; + while (isxdigit(*c)) + { + if (isdigit(*c)) + d = *c - '0'; + else + d = 10 + toupper(*c) - 'A'; + fillchar = (fillchar << 4) | d; + c++; + } + argc--; + argv++; + } + if (argc > 1) + fspec = argv[1]; + else + fspec = "*.*"; + + if ((infile = fwild(fspec, "r")) == NULL) + { + perror("Bad file spec"); + exit(0); + } + + while (fnext(infile) != NULL) + { + fgetname(infile, thefile); + /* Remove version number */ + d = strlen(thefile) - 1; + while (thefile[d] != ';') + d--; + thefile[d] = '\0'; + (void)printf("[%s", thefile); + if ((outfile = fopen(thefile, "wb", "rfm=fix", "mrs=512")) + == NULL) + { + perror("] Can't open output file"); + continue; + } + dofile(infile, outfile, fill, fillchar); + fclose(outfile); + (void)printf("]\n"); + } + +} + +dofile(infile, outfile, fill, fillchar) +FILE *infile; +FILE *outfile; +int fill; +int fillchar; +{ + int c; + int d; + unsigned int bytecount = 0; + +#define GET() fgetc(infile) +#define PUT(c) (fputc((c),outfile),bytecount++) +#define ECHO() PUT(GET()) + + for (;;) + { + c = GET(); + if (c == EOF) + break; + + PUT(c); /* 0..7 */ + ECHO(); /* 8..15 */ + ECHO(); /* 16..23 */ + ECHO(); /* 24..31 */ + + d = GET(); + c = (d << 4); + d = GET(); + c |= 0xFF & (d >> 4); + PUT(c); /* 4..11 */ + + c = (d << 4); + d = GET(); + c |= 0xFF & (d >> 4); + PUT(c); /* 12..19 */ + + c = (d << 4); + d = GET(); + c |= 0xFF & (d >> 4); + PUT(c); /* 20..27 */ + + c = (d << 4); + d = GET(); + c |= 0xFF & (d >> 4); + PUT(c); /* 28..36 */ + } + + if (fill) + { + while (bytecount & 511) + PUT(fillchar); + } +} + +/* + * Fwild and fnext for vms. Written by Martin Minow; taken from the + * DECUS C VMS compatibility collection. + */ + +/* #include <stdio.h> */ +/* #include <rms.h> */ +#include <ssdef.h> +#include <descrip.h> +#include <ctype.h> + +#define TRUE 1 +#define FALSE 0 +#define EOS 0 + +typedef struct rmsstuff +{ + int flag; /* Flag for nonwildcard calls */ + char *wildmode; + struct FAB fab; + struct NAM nam; + char starname[NAM$C_MAXRSS + 1]; + char filename[NAM$C_MAXRSS + 1]; +} RMSSTUFF; + +static RMSSTUFF *wilddata[_NFILE]; /* RMS struct for each file */ + +/* + * rms->flag can take on the following values: + * ISWILD A file with wild-card bytes. + * UNWILD A file without wild-cards, unopened. + * UNWILD_OPENED A file without wild-cards, opened. + */ +#define ISWILD 0 +#define UNWILD 1 +#define UNWILD_OPENED 2 + +extern FILE *cleanup(); +FILE * +fwild(filename, mode) +char *filename; +char *mode; +/* + * Do wildcard setup + */ +{ + register FILE *fd; + register RMSSTUFF *r; + register int index; + + /* First get a file to work with. In the process, make sure the + mode we got passed is valid. Note that every file we will open + from here on already exists, so an open for write will fail + (since the open will include the fully-expanded file name, + including the version number). Unfortunately, opening a file on + the null device always succeeds. So, to simplify matters, we + just reject a "w" mode request right here. (We could as well let + it go and then find "no matching files" when all later open + requests fail. But this makes more sense.) */ + if (*mode == 'w' || (fd = fopen("_nl:", mode)) == NULL) + { + return (NULL); + } + /* Warning: the package depends on fileno(fd) remaining + unchanged after calls to freopen(). */ + index = fileno(fd); + /* If we've been here before, make sure buffers are released. */ + cleanup(index); + if ((r = malloc(sizeof(RMSSTUFF))) == NULL + || (r->wildmode = malloc(strlen(mode) + 1)) == NULL) + return (cleanup(index)); + strcpy(r->wildmode, mode); + wilddata[index] = r; + /* Setup the fab and nam blocks. */ + r->fab = cc$rms_fab; /* Initialize fab */ + r->nam = cc$rms_nam; /* and nam blocks */ + r->fab.fab$l_nam = &r->nam; /* fab -> nam */ + r->fab.fab$l_fna = filename; /* Argument filename */ + r->fab.fab$b_fns = strlen(filename); /* filename size */ + r->nam.nam$l_esa = r->starname; /* Expanded file name */ + r->nam.nam$b_ess = NAM$C_MAXRSS; /* ... size */ + r->nam.nam$l_rsa = r->filename; /* Result filename */ + r->nam.nam$b_rss = NAM$C_MAXRSS; /* ... size */ + /* Parse the file name */ + if (sys$parse(&r->fab) != RMS$_NORMAL) + return (cleanup(index)); + /* Success. Null-terminate expanded file name and set flag to + distinguish between "wild" and "non-wild" filenames. */ + ((char *) r->nam.nam$l_esa)[r->nam.nam$b_esl] = EOS; + r->flag = ((r->nam.nam$l_fnb & NAM$M_WILDCARD) == 0) ? + UNWILD : ISWILD; + return (fd); +} + + +FILE * +fnext(fd) +FILE *fd; +/* + * Open the next valid file. return fd if successful, NULL if finished. + */ +{ + register int index; + register RMSSTUFF *r; + register int errorcode; + FILE *test; + + index = fileno(fd); + if ((r = wilddata[index]) == NULL || r->flag == UNWILD_OPENED) + { + /* It wasn't ours, or wasn't a wildcard and has already been + processed. */ + fclose(fd); + fd = NULL; + } + else + if (r->flag == UNWILD) + { + /* Not a wildcard file, first time through */ + fd = freopen(r->starname, r->wildmode, fd); + r->flag = UNWILD_OPENED; + } + else + { + /* Look for the next match -- who says you can't write obscure + structured code? */ + for (;;) + { + /* Look 'em up but skip any with protection violation + errors. */ + r->fab.fab$w_ifi = 0; /* Internal file index */ + if ((errorcode = sys$search(&r->fab)) == RMS$_NORMAL) + { + /* We have a file. Open it if we have access rights. + Determining this isn't as simple as it might be + because the access() function checks the wrong thing: + It ignores ACL's and any special privileges. So we + just open the file twice. (We have to check first + since if we fail, freopen will free up our file + pointer and we can't be sure of getting it back.) + Opening the file twice has one unfortunate side + effect - it bumps the file revision by 2. That's + life. */ + ((char *) r->nam.nam$l_rsa)[r->nam.nam$b_rsl] = EOS; + if ((test = fopen(r->filename, r->wildmode)) == NULL) + { + /* Couldn't open it; try for another. */ + continue; + } + else + { + /* Close up the test channel first (to avoid + problems with sharing; then open the file. We + should normally be able to open the file. It + this fails, something is wrong inside the C + library. (More likely, a timing problem occured + - between our test and our actual open, someone + deleted the file, or between our close and + re-open, someone else opened it in an + incompatible mode.) In any case, we've lost our + file descriptor, and there is no good way to + recover; so we just return NULL and let the + caller think that's all there is. */ + fclose(test); + fd = freopen(r->filename, r->wildmode, fd); + break; + } + } + else + if (errorcode == RMS$_PRV) + { + /* sys$search() found something, but we don't have + privileges to open it. Look for another. */ + continue; + } + else + { + /* Can't find a file. This should be RMS$_NMF. */ + fclose(fd); + fd = NULL; + break; + } + } + } + /* Cleanup if any errors */ + if (fd == NULL) + { + cleanup(index); + } + return (fd); +} + +static FILE * +cleanup(index) +register int index; +/* + * Empty out any stored information + */ +{ + register RMSSTUFF *r; + + r = wilddata[index]; + if (r != NULL) + { + if (r->wildmode != NULL) + { + free(r->wildmode); + } + free(r); + wilddata[index] = NULL; + } + return (NULL); +} |