henry@utzoo.UUCP (Henry Spencer) (07/26/84)
The following is the source and manual page for bytes(1), the latest minor local innovation. It's a general program for doing byte selection and swapping in binary data. It will swap bytes, swap words, etc., and will let you pick out specific bytes of words. (Why would you want to do the latter? Well, EPROMs are only a byte wide, so a 16-bit machine needs an EPROM of high bytes and an EPROM of low bytes...). It is public domain. Bytes uses four functions not in the standard C library: getopt, strtok, error, and efopen. Getopt and strtok are from System V, but public-domain implementations exist and have been posted to the net within the last six months. Error and efopen are trivial routines from Kernighan&Pike; if you haven't already done so, type them in and put them in your library -- they are useful! [What, you don't have a copy of Kernighan&Pike? Stop reading this minute, run right down to your neighborhood Unix bookstore, buy one, and read it. Then start typing things in.] [Oh yes, you System V types will need to '#define index strchr', but then you're probably used to that already.] ----- /* * bytes - select and permute bytes */ #include <stdio.h> int exact = 0; /* Insist on exact number of records? */ int recsize = 0; /* Record size. */ int bytenos[BUFSIZ]; /* Bytes to output; 0 terminates. */ char *progname; /* * main - parse arguments and handle options */ main(argc, argv) int argc; char *argv[]; { register char *p; /* For scanning byte list. */ register int nb; /* Number of byte numbers seen. */ int c; int errflg = 0; FILE *in; extern int optind; extern char *optarg; extern FILE *efopen(); extern char *index(); extern char *strtok(); progname = argv[0]; while ((c = getopt(argc, argv, "e")) != EOF) switch (c) { case 'e': exact++; break; case '?': default: errflg++; break; } if (errflg || optind >= argc) { fprintf(stderr, "Usage: %s [-e] b,b,...[/size] [file] ...\n", progname); exit(2); } p = index(argv[optind], '/'); if (p != NULL) { *p = '\0'; p++; recsize = atoi(p); if (recsize < 1 || recsize >= BUFSIZ) error("invalid record size \"%s\"", p); } nb = 0; for (p = strtok(argv[optind], " \t,"); p != NULL; p = strtok((char *)NULL, " \t,")) { bytenos[nb] = atoi(p); if (bytenos[nb] < 1 || bytenos[nb] >= BUFSIZ) error("invalid byte number \"%s\"", p); if (bytenos[nb] > recsize) recsize = bytenos[nb]; nb++; } bytenos[nb] = 0; optind++; if (optind == argc) process(stdin, "stdin"); else for (; optind < argc; optind++) { in = efopen(argv[optind], "r"); process(in, argv[optind]); fclose(in); } exit(0); } /* * process - process input file */ /* ARGSUSED */ process(in, inname) FILE *in; char *inname; { char buf[BUFSIZ]; register int n; register int i; while ((n = fread(buf, 1, recsize, in)) > 0) { if (n < recsize) { if (exact) error("partial record", ""); for (; n < recsize; n++) buf[n] = '\0'; } for (i = 0; bytenos[i] != 0; i++) putchar(buf[bytenos[i]-1]); } } ----- .TH BYTES 1 local .DA 14 July 1984 .SH NAME bytes \- select and permute bytes .SH SYNOPSIS .B bytes [ .B \-e ] b\fB,\fRb\fB,\fR...[\fB/\fRsize] [ file ... ] .SH DESCRIPTION .I Bytes selects bytes from its input .IR file s (default standard input) and puts them out in a specified order. Conceptually, it repeatedly reads \fIn\fR bytes, numbers them from 1 to \fIn\fR, and then outputs the bytes whose numbers appear in the list that is the first argument, in the order they appear in the list. Bytes not mentioned in the list are discarded. .PP The value of \fIn\fR can be set by appending a slash and a .I size value to the list. The default is equal to the largest byte number in the list. .PP If an incomplete record is read (e.g. at end-of-file), .I bytes normally pads it on the end with zeros. The .B \-e option suppresses this padding, in which case .I bytes complains if the input is not an exact number of records. .PP Note that byte numbers start at 1, not 0. .SH EXAMPLES .nf .ta \w'\fBbytes 3,4,1,2\fR'u+2n \fBbytes 1,2\fR output identical to input \fBbytes 2,1\fR adjacent bytes swapped \fBbytes 3,4,1,2\fR adjacent two-byte words swapped \fBbytes 1/2\fR low-order bytes of pdp11 words \fBbytes 1,2/4\fR low-order halfwords of VAX words \fBbytes 2,1/4\fR same, with bytes swapped .fi .SH SEE ALSO dd(1) .SH HISTORY Local product. ----- -- Henry Spencer @ U of Toronto Zoology {allegra,ihnp4,linus,decvax}!utzoo!henry