#include <ctype.h>
#include <endian.h>
#include <err.h>
#include <stdint.h>
#include <stdio.h>
static int32_t getint(const char **);
static int copybyte(const char);
int
main(int argc, char *argv[])
{
const char *cmd;
int32_t pos;
int32_t dest;
int32_t val;
int32_t i;
if (argc != 2)
errx(1, "usage: binedit command_string");
cmd = argv[1];
dest = pos = val = 0;
while (*cmd != '\0') {
switch (*cmd++) {
case 'a':
while (pos < dest) {
pos++;
if (copybyte('a') == EOF)
errx(1, "a: EOF");
}
break;
case 'c':
i = getint(&cmd);
pos += i;
while (i--)
if (copybyte('c') == EOF)
errx(1, "c: EOF");
break;
case 'd':
dest = val;
break;
case 'f':
if (*cmd != '\0')
errx(1, "%s: not the last command", cmd - 1);
while (copybyte('f') != EOF)
continue;
break;
case 'i':
i = getint(&cmd);
if (i == 0)
i = 1;
val += i;
break;
case 'r':
pos += sizeof(i);
if (fread(&i, sizeof(i), 1, stdin) != 1) {
if (ferror(stdin))
err(1, "r: fread");
else
errx(1, "r: EOF");
}
val = be32toh(i);
break;
case 's':
i = getint(&cmd);
pos += i;
while (i--) {
if (getchar() == EOF) {
if (ferror(stdin))
err(1, "s: getchar");
else
errx(1, "s: EOF");
}
}
break;
case 'w':
if (*cmd == '-' || *cmd == '+' ||
isdigit((unsigned char)*cmd))
val = getint(&cmd);
i = htobe32(val);
if (fwrite(&i, sizeof(i), 1, stdout) != 1)
err(1, "w: fwrite");
break;
default:
errx(1, "%c: invalid command", cmd[-1]);
}
}
return 0;
}
static int32_t
getint(const char **cmd)
{
int32_t res;
int minus;
res = 0;
minus = 0;
if (**cmd == '-') {
minus = 1;
(*cmd)++;
} else if (**cmd == '+')
(*cmd)++;
while(isdigit((unsigned char)**cmd))
res = res * 10 + *(*cmd)++ - '0';
return minus ? -res : res;
}
static int
copybyte(const char cmd)
{
int ch;
if ((ch = getchar()) == EOF) {
if (ferror(stdin))
err(1, "%c: getchar", cmd);
} else if (putchar(ch) == EOF)
err(1, "%c: putchar", cmd);
return ch;
}