v04i038: generalized base converter
der Mouse
mouse%mcgill-vision.UUCP at Larry.McRCIM.McGill.EDU
Sat Aug 27 21:07:19 AEST 1988
Posting-number: Volume 4, Issue 38
Submitted-by: "der Mouse " <mouse%mcgill-vision.UUCP at Larry.McRCIM.McGill.EDU>
Archive-name: cvtbase
A generalized base-conversion program. No compilation options needed;
"cc -o cvtbase cvtbase.c" should work fine.
Known to work on BSD and at least one SV-based system. Read the
leading comment for more info.
As always, bug reports are welcome. Bug fixes are even more welcome.
Flames are merely accepted :-). All of the above should be mailed to
me at one of the addresses below.
der Mouse
old: mcgill-vision!mouse
new: mouse at larry.mcrcim.mcgill.edu
#! /bin/sh
#
# Shar: Shell Archiver
#
# This archive created Sat Aug 27 07:01:24 1988
# Run this through sh to create:
# cvtbase.c
echo x - cvtbase.c \(4639 characters\)
sed 's/^X//' > cvtbase.c << \EOF
X/*
X * cvtbase -- convert from one base to another. Usage:
X *
X * cvtbase input-base-spec output-base-spec < input > output
X *
X * where a base spec is one of:
X *
X * d
X * D Specifies "decimal" -- digits 0 through 9
X *
X * x
X * h Specifies "hexadecimal" -- digits 0-9 and a-f
X *
X * X
X * H Specifies "Hexadecimal" -- digits 0-9 and A-F
X *
X * o
X * O Specifies "octal" -- digits 0 through 7
X *
X * b
X * B Specifies "binary" -- digits 0 and 1
X *
X * or a string of two or more characters, which are the digits (eg. 012 would
X * use ternary notation). Any of these may be preceded by a - sign to
X * indicate that the base in question is negative. A leading + sign is
X * stripped; to enter a string of digits beginning with a + or - sign, you
X * must precede the string with a + or - sign (depending on whether you want
X * a positive or negative base).
X *
X * Any base specifier may be preceded by an m (or an M) and one other
X * character to change the minus sign (the default is of course -).
X *
X * For a minus sign to be recognized in the input, it must be immediately
X * followed by the number. If anything (such as a space) intervenes, the
X * minus sign will be echoed and ignored (as if it were an ordinary
X * character).
X *
X * Bases -1, 0, and 1 are disallowed.
X *
X * Input is taken from the standard input; the converted output appears
X * on the standard output.
X *
X * Copyright 1988 by Mike Parker. All rights reserved. Non-profit
X * redistribution permitted.
X */
X#include <stdio.h>
X
X/* extern */ char **argvec;
X
Xstatic int errs;
X
Xstatic int indig;
Xstatic char *idigits;
Xstatic char isign;
Xstatic int ondig;
Xstatic char *odigits;
Xstatic char osign;
X
Xchar *index();
X
Xlong int get_number(ndig,digits,sign)
Xint ndig;
Xchar *digits;
Xchar sign;
X{
X long int retval;
X int minus;
X char c;
X char *cp;
X
X retval = 0;
X minus = 1;
X while (1)
X { c = getchar();
X if (feof(stdin))
X { if (minus < 0)
X { putchar(sign);
X minus = 1;
X }
X exit(0);
X }
X if ((cp=index(digits,c)) != 0)
X { break;
X }
X if ((c == sign) && (ndig > 0))
X { minus = - minus;
X }
X else
X { if (minus < 0)
X { putchar(sign);
X minus = 1;
X }
X putchar(c);
X }
X }
X while (1)
X { retval *= ndig;
X retval += (cp-digits);
X c = getchar();
X if (feof(stdin))
X { break;
X }
X if ((cp=index(digits,c)) == 0)
X { break;
X }
X }
X ungetc(c,stdin);
X return(minus*retval);
X}
X
Xput_number(ndig,digits,sign,value)
Xint ndig;
Xchar *digits;
Xchar sign;
Xlong int value;
X{
X if ((value < 0) && (ndig > 0))
X { putchar(sign);
X value = - value;
X }
X _put_number(ndig,digits,value);
X}
X
X_put_number(ndig,digits,value)
Xint ndig;
Xchar *digits;
Xlong int value;
X{
X long int i;
X int j;
X
X i = value / ndig;
X j = value % ndig;
X if (j < 0)
X { j -= ndig;
X i ++;
X }
X if (i != 0)
X { _put_number(ndig,digits,i);
X }
X putchar(digits[j]);
X}
X
Xget_base(arg,Ndig,Digits,Sign)
Xchar *arg;
Xint *Ndig;
X#define ndig (*Ndig)
Xchar **Digits;
X#define digits (*Digits)
Xchar *Sign;
X#define sign (*Sign)
X{
X int isneg;
X char *origarg = arg;
X
X sign = '-';
X isneg = 0;
X if ((*arg == 'm') || (*arg == 'M'))
X { sign = *++arg;
X if (sign == '\0')
X { fprintf(stderr,"%s: %c must be followed by a sign character\n",
X argvec[0],arg[-1]);
X errs = 1;
X return;
X }
X arg ++;
X }
X if ((*arg == '+') || (*arg == '-'))
X { isneg = (*arg++ == '-');
X }
X switch (*arg++)
X { case 'b': case 'B':
X digits = "01";
X break;
X case 'o': case 'O':
X digits = "01234567";
X break;
X case 'd': case 'D':
X digits = "0123456789";
X break;
X case 'h': case 'x':
X digits = "0123456789abcdef";
X break;
X case 'H': case 'X':
X digits = "0123456789ABCDEF";
X break;
X case '\0':
X fprintf(stderr,"%s: null base specifier `%s'\n",argvec[0],origarg);
X errs = 1;
X return;
X break;
X default:
X if (*arg == '\0')
X { fprintf(stderr,"%s: unknown base key `%c' (or base 1)\n",
X argvec[0],arg[-1]);
X errs = 1;
X return;
X }
X digits = arg-1;
X arg = "";
X break;
X }
X if (*arg)
X { fprintf(stderr,"%s: junk `%s' at end of base spec `%s'\n",
X argvec[0],arg,origarg);
X errs = 1;
X return;
X }
X ndig = strlen(digits) * (isneg ? -1 : 1);
X}
X
Xmain(ac,av)
Xint ac;
Xchar **av;
X{
X long int value;
X
Xargvec=av;/*grrr...*/
X if (ac < 3)
X { fprintf(stderr,"Usage: %s <input-base> <output-base>\n",
X argvec[0]);
X exit(1);
X }
X errs = 0;
X get_base(av[1],&indig,&idigits,&isign);
X get_base(av[2],&ondig,&odigits,&osign);
X if (errs)
X { exit(1);
X }
X while (1)
X { value = get_number(indig,idigits,isign);
X put_number(ondig,odigits,osign,value);
X }
X}
EOF
if test 4639 -ne "`wc -c cvtbase.c`"
then
echo shar: error transmitting cvtbase.c \(should have been 4639 characters\)
fi
exit 0
# end of shell archive
More information about the Comp.sources.misc
mailing list