/* * intcnv.c - convert integer into various forms */ /*- * Copyright (c) 2008-2019 * Jeffrey Allen Neitzel . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY JEFFREY ALLEN NEITZEL ``AS IS'', AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL JEFFREY ALLEN NEITZEL BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @(#)$Id: intcnv.c,v 1.1.1.1 2019/04/30 01:12:17 jneitzel Exp $ */ #include #include #include #include #include #include #include #ifndef lint #ifndef INTCNV_ATTR # if __GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 4 # define INTCNV_ATTR __attribute__((__used__)) # elif defined(__GNUC__) # define INTCNV_ATTR __attribute__((__unused__)) # else # define INTCNV_ATTR /* nothing */ # endif #endif /* !INTCNV_ATTR */ /*@unused@*/ static const char *const vcid[] INTCNV_ATTR = { "\100(#)\044Id: intcnv-current \044", "\100(#)\044Id: Copyright (c) 2008-2019 Jeffrey Allen Neitzel. \044" }; #endif /* !lint */ #define MYNAME "unknown" #define BITMAX (sizeof(int) * CHAR_BIT) #define BUFMAX (BITMAX + 1) /*@observer@*/ static const char *myname = NULL; static void setmyname(/*@null@*/ const char *); static bool xstrtonum(int *, const char *, int); static char *numtobin(/*@out@*/ /*@returned@*/ char *, int, size_t); static int getbitval(unsigned, unsigned); static void writeout(const char *, int); /* * NAME * intcnv - convert integer into various forms * * SYNOPSIS * intcnv [-b] integer * * DESCRIPTION * See the intcnv(1) manual page for full details. */ int main(int argc, char **argv) { int num = 0; char buf[BUFMAX]; bool bflag = false; setmyname(argv[0]); if (argc > 1 && strcmp(argv[1], "-b") == 0) { bflag = true; argc--; argv++; } if (argc != 2) { (void)fprintf(stderr, "usage: %s [-b] integer\n", myname); return 1; } if (!xstrtonum(&num, argv[1], bflag ? 2 : 0)) return 1; writeout(numtobin(buf, num, sizeof(buf)), num); return 0; } /* * Set the global myname to the basename of the string pointed to by s. */ static void setmyname(const char *s) { const char *p; if (s != NULL && *s != '\0') { if ((p = strrchr(s, '/')) != NULL) p++; else p = s; } else /* should never (but can) be true */ p = MYNAME; myname = p; } /* * According to base b (2 for base-2 or 0 for base-(8|10|16)), convert * the string pointed to by s into a number pointed to by integer n. * Return true on success. Return false on error. */ static bool xstrtonum(int *n, const char *s, int b) { long num; char *nbad; errno = 0; num = strtol(s, &nbad, b); if (*s == '\0' || *nbad != '\0') { (void)fprintf(stderr, "%s: %s: Invalid integer\n", myname, s); *n = 0; return false; } /* From: EXAMPLES section of NetBSD strtol(3) (see LICENSE) */ if ((errno == ERANGE && (num == LONG_MAX || num == LONG_MIN)) || (num > INT_MAX || num < INT_MIN)) { (void)fprintf(stderr, "%s: %s: Out of range\n", myname, s); *n = 0; return false; } *n = (int)num; return true; } /* * Convert the number num into its binary form, copy it to buf, * and return a pointer it. */ static char * numtobin(char *buf, int num, size_t siz) { int bps; char *b; *buf = '\0'; for (b=buf, bps=(int)BITMAX-1; b < &buf[siz] && bps >= 0; b++, bps--) *b = getbitval((unsigned)num, (unsigned)bps); *b = '\0'; return buf; } /* * Get the bit value in integer n at bit position b. * Return the '0' or '1' character on success. * Return -1 on error. */ static int getbitval(unsigned n, unsigned b) { if (b >= (unsigned)BITMAX) /* should never be true */ return -1; return ((n & (1U << b)) == 0) ? '0' : '1'; } /* * Write the conversion results to the standard output stream. */ static void writeout(const char *b, int n) { (void)printf(" Binary: %s\n" , b); (void)printf(" Octal: 0%o\n" , /*(unsigned)*/n); (void)printf(" Decimal: % d\n" , n); (void)printf("Hexadecimal: 0x%X\n", /*(unsigned)*/n); }