14b88c807SRodney W. Grimes /*- 24b88c807SRodney W. Grimes * Copyright (c) 1991, 1993, 1994 34b88c807SRodney W. Grimes * The Regents of the University of California. All rights reserved. 44b88c807SRodney W. Grimes * 54b88c807SRodney W. Grimes * This code is derived from software contributed to Berkeley by 64b88c807SRodney W. Grimes * Keith Muller of the University of California, San Diego and Lance 74b88c807SRodney W. Grimes * Visser of Convex Computer Corporation. 84b88c807SRodney W. Grimes * 94b88c807SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 104b88c807SRodney W. Grimes * modification, are permitted provided that the following conditions 114b88c807SRodney W. Grimes * are met: 124b88c807SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 134b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 144b88c807SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 154b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 164b88c807SRodney W. Grimes * documentation and/or other materials provided with the distribution. 174b88c807SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 184b88c807SRodney W. Grimes * must display the following acknowledgement: 194b88c807SRodney W. Grimes * This product includes software developed by the University of 204b88c807SRodney W. Grimes * California, Berkeley and its contributors. 214b88c807SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 224b88c807SRodney W. Grimes * may be used to endorse or promote products derived from this software 234b88c807SRodney W. Grimes * without specific prior written permission. 244b88c807SRodney W. Grimes * 254b88c807SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 264b88c807SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 274b88c807SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 284b88c807SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 294b88c807SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 304b88c807SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 314b88c807SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 324b88c807SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 334b88c807SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 344b88c807SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 354b88c807SRodney W. Grimes * SUCH DAMAGE. 364b88c807SRodney W. Grimes */ 374b88c807SRodney W. Grimes 384b88c807SRodney W. Grimes #ifndef lint 39cbf6f7d3SPhilippe Charnier #if 0 401ba0e048SPhilippe Charnier static char sccsid[] = "@(#)args.c 8.3 (Berkeley) 4/2/94"; 41cbf6f7d3SPhilippe Charnier #endif 42cbf6f7d3SPhilippe Charnier static const char rcsid[] = 432a456239SPeter Wemm "$FreeBSD$"; 444b88c807SRodney W. Grimes #endif /* not lint */ 454b88c807SRodney W. Grimes 464b88c807SRodney W. Grimes #include <sys/types.h> 474b88c807SRodney W. Grimes 484b88c807SRodney W. Grimes #include <err.h> 494b88c807SRodney W. Grimes #include <errno.h> 504b88c807SRodney W. Grimes #include <limits.h> 514b88c807SRodney W. Grimes #include <stdlib.h> 524b88c807SRodney W. Grimes #include <string.h> 534b88c807SRodney W. Grimes 544b88c807SRodney W. Grimes #include "dd.h" 554b88c807SRodney W. Grimes #include "extern.h" 564b88c807SRodney W. Grimes 574b88c807SRodney W. Grimes static int c_arg __P((const void *, const void *)); 584b88c807SRodney W. Grimes static int c_conv __P((const void *, const void *)); 594b88c807SRodney W. Grimes static void f_bs __P((char *)); 604b88c807SRodney W. Grimes static void f_cbs __P((char *)); 614b88c807SRodney W. Grimes static void f_conv __P((char *)); 624b88c807SRodney W. Grimes static void f_count __P((char *)); 634b88c807SRodney W. Grimes static void f_files __P((char *)); 644b88c807SRodney W. Grimes static void f_ibs __P((char *)); 654b88c807SRodney W. Grimes static void f_if __P((char *)); 664b88c807SRodney W. Grimes static void f_obs __P((char *)); 674b88c807SRodney W. Grimes static void f_of __P((char *)); 684b88c807SRodney W. Grimes static void f_seek __P((char *)); 694b88c807SRodney W. Grimes static void f_skip __P((char *)); 70e14f7e78SBrian Feldman static quad_t get_num __P((char *)); 714b88c807SRodney W. Grimes 724b88c807SRodney W. Grimes static struct arg { 734b88c807SRodney W. Grimes char *name; 744b88c807SRodney W. Grimes void (*f) __P((char *)); 754b88c807SRodney W. Grimes u_int set, noset; 764b88c807SRodney W. Grimes } args[] = { 774b88c807SRodney W. Grimes { "bs", f_bs, C_BS, C_BS|C_IBS|C_OBS|C_OSYNC }, 784b88c807SRodney W. Grimes { "cbs", f_cbs, C_CBS, C_CBS }, 794b88c807SRodney W. Grimes { "conv", f_conv, 0, 0 }, 804b88c807SRodney W. Grimes { "count", f_count, C_COUNT, C_COUNT }, 814b88c807SRodney W. Grimes { "files", f_files, C_FILES, C_FILES }, 824b88c807SRodney W. Grimes { "ibs", f_ibs, C_IBS, C_BS|C_IBS }, 834b88c807SRodney W. Grimes { "if", f_if, C_IF, C_IF }, 844b88c807SRodney W. Grimes { "obs", f_obs, C_OBS, C_BS|C_OBS }, 854b88c807SRodney W. Grimes { "of", f_of, C_OF, C_OF }, 864b88c807SRodney W. Grimes { "seek", f_seek, C_SEEK, C_SEEK }, 874b88c807SRodney W. Grimes { "skip", f_skip, C_SKIP, C_SKIP }, 884b88c807SRodney W. Grimes }; 894b88c807SRodney W. Grimes 904b88c807SRodney W. Grimes static char *oper; 914b88c807SRodney W. Grimes 924b88c807SRodney W. Grimes /* 934b88c807SRodney W. Grimes * args -- parse JCL syntax of dd. 944b88c807SRodney W. Grimes */ 954b88c807SRodney W. Grimes void 964b88c807SRodney W. Grimes jcl(argv) 974b88c807SRodney W. Grimes char **argv; 984b88c807SRodney W. Grimes { 994b88c807SRodney W. Grimes struct arg *ap, tmp; 1004b88c807SRodney W. Grimes char *arg; 1014b88c807SRodney W. Grimes 1024b88c807SRodney W. Grimes in.dbsz = out.dbsz = 512; 1034b88c807SRodney W. Grimes 104ad66f7eeSPoul-Henning Kamp while ((oper = *++argv) != NULL) { 1054c339742SEivind Eklund if ((oper = strdup(oper)) == NULL) 10654946e00SBrian Feldman errx(1, "unable to allocate space for the argument \"%s\"", *argv); 1074b88c807SRodney W. Grimes if ((arg = strchr(oper, '=')) == NULL) 1084b88c807SRodney W. Grimes errx(1, "unknown operand %s", oper); 1094b88c807SRodney W. Grimes *arg++ = '\0'; 1104b88c807SRodney W. Grimes if (!*arg) 1114b88c807SRodney W. Grimes errx(1, "no value specified for %s", oper); 1124b88c807SRodney W. Grimes tmp.name = oper; 11354946e00SBrian Feldman if (!(ap = (struct arg *)bsearch(&tmp, args, 11454946e00SBrian Feldman sizeof(args)/sizeof(struct arg), sizeof(struct arg), 11554946e00SBrian Feldman c_arg))) 1164b88c807SRodney W. Grimes errx(1, "unknown operand %s", tmp.name); 1174b88c807SRodney W. Grimes if (ddflags & ap->noset) 11854946e00SBrian Feldman errx(1, "%s: illegal argument combination or already set", 11954946e00SBrian Feldman tmp.name); 1204b88c807SRodney W. Grimes ddflags |= ap->set; 1214b88c807SRodney W. Grimes ap->f(arg); 1224b88c807SRodney W. Grimes } 1234b88c807SRodney W. Grimes 1244b88c807SRodney W. Grimes /* Final sanity checks. */ 1254b88c807SRodney W. Grimes 1264b88c807SRodney W. Grimes if (ddflags & C_BS) { 1274b88c807SRodney W. Grimes /* 1284b88c807SRodney W. Grimes * Bs is turned off by any conversion -- we assume the user 1294b88c807SRodney W. Grimes * just wanted to set both the input and output block sizes 1304b88c807SRodney W. Grimes * and didn't want the bs semantics, so we don't warn. 1314b88c807SRodney W. Grimes */ 1324b88c807SRodney W. Grimes if (ddflags & (C_BLOCK|C_LCASE|C_SWAB|C_UCASE|C_UNBLOCK)) 1334b88c807SRodney W. Grimes ddflags &= ~C_BS; 1344b88c807SRodney W. Grimes 1354b88c807SRodney W. Grimes /* Bs supersedes ibs and obs. */ 1364b88c807SRodney W. Grimes if (ddflags & C_BS && ddflags & (C_IBS|C_OBS)) 1374b88c807SRodney W. Grimes warnx("bs supersedes ibs and obs"); 1384b88c807SRodney W. Grimes } 1394b88c807SRodney W. Grimes 1404b88c807SRodney W. Grimes /* 1414b88c807SRodney W. Grimes * Ascii/ebcdic and cbs implies block/unblock. 1424b88c807SRodney W. Grimes * Block/unblock requires cbs and vice-versa. 1434b88c807SRodney W. Grimes */ 1444b88c807SRodney W. Grimes if (ddflags & (C_BLOCK|C_UNBLOCK)) { 1454b88c807SRodney W. Grimes if (!(ddflags & C_CBS)) 1464b88c807SRodney W. Grimes errx(1, "record operations require cbs"); 1474b88c807SRodney W. Grimes if (cbsz == 0) 1484b88c807SRodney W. Grimes errx(1, "cbs cannot be zero"); 1494b88c807SRodney W. Grimes cfunc = ddflags & C_BLOCK ? block : unblock; 1504b88c807SRodney W. Grimes } else if (ddflags & C_CBS) { 1514b88c807SRodney W. Grimes if (ddflags & (C_ASCII|C_EBCDIC)) { 1524b88c807SRodney W. Grimes if (ddflags & C_ASCII) { 1534b88c807SRodney W. Grimes ddflags |= C_UNBLOCK; 1544b88c807SRodney W. Grimes cfunc = unblock; 1554b88c807SRodney W. Grimes } else { 1564b88c807SRodney W. Grimes ddflags |= C_BLOCK; 1574b88c807SRodney W. Grimes cfunc = block; 1584b88c807SRodney W. Grimes } 1594b88c807SRodney W. Grimes } else 1604b88c807SRodney W. Grimes errx(1, "cbs meaningless if not doing record operations"); 1614b88c807SRodney W. Grimes } else 1624b88c807SRodney W. Grimes cfunc = def; 1634b88c807SRodney W. Grimes } 1644b88c807SRodney W. Grimes 1654b88c807SRodney W. Grimes static int 1664b88c807SRodney W. Grimes c_arg(a, b) 1674b88c807SRodney W. Grimes const void *a, *b; 1684b88c807SRodney W. Grimes { 1694b88c807SRodney W. Grimes 1704b88c807SRodney W. Grimes return (strcmp(((struct arg *)a)->name, ((struct arg *)b)->name)); 1714b88c807SRodney W. Grimes } 1724b88c807SRodney W. Grimes 1734b88c807SRodney W. Grimes static void 1744b88c807SRodney W. Grimes f_bs(arg) 1754b88c807SRodney W. Grimes char *arg; 1764b88c807SRodney W. Grimes { 177e14f7e78SBrian Feldman quad_t res = get_num(arg); 1784b88c807SRodney W. Grimes 17954946e00SBrian Feldman if (res < 1 || res > INT_MAX) 18054946e00SBrian Feldman errx(1, "bs must be between 1 and %d", INT_MAX); 18154946e00SBrian Feldman in.dbsz = out.dbsz = (int)res; 1824b88c807SRodney W. Grimes } 1834b88c807SRodney W. Grimes 1844b88c807SRodney W. Grimes static void 1854b88c807SRodney W. Grimes f_cbs(arg) 1864b88c807SRodney W. Grimes char *arg; 1874b88c807SRodney W. Grimes { 188e14f7e78SBrian Feldman quad_t res = get_num(arg); 1894b88c807SRodney W. Grimes 19054946e00SBrian Feldman if (res < 1 || res > INT_MAX) 19154946e00SBrian Feldman errx(1, "cbs must be between 1 and %d", INT_MAX); 19254946e00SBrian Feldman cbsz = (int)res; 1934b88c807SRodney W. Grimes } 1944b88c807SRodney W. Grimes 1954b88c807SRodney W. Grimes static void 1964b88c807SRodney W. Grimes f_count(arg) 1974b88c807SRodney W. Grimes char *arg; 1984b88c807SRodney W. Grimes { 1994b88c807SRodney W. Grimes 200e14f7e78SBrian Feldman cpy_cnt = get_num(arg); 201e14f7e78SBrian Feldman 2024b88c807SRodney W. Grimes if (!cpy_cnt) 2034b88c807SRodney W. Grimes terminate(0); 20454946e00SBrian Feldman if (cpy_cnt < 0) 20554946e00SBrian Feldman errx(1, "count cannot be negative"); 2064b88c807SRodney W. Grimes } 2074b88c807SRodney W. Grimes 2084b88c807SRodney W. Grimes static void 2094b88c807SRodney W. Grimes f_files(arg) 2104b88c807SRodney W. Grimes char *arg; 2114b88c807SRodney W. Grimes { 2124b88c807SRodney W. Grimes 213e14f7e78SBrian Feldman files_cnt = get_num(arg); 214e14f7e78SBrian Feldman if (files_cnt < 0) 215e14f7e78SBrian Feldman errx(1, "files cannot be negative"); 2164b88c807SRodney W. Grimes } 2174b88c807SRodney W. Grimes 2184b88c807SRodney W. Grimes static void 2194b88c807SRodney W. Grimes f_ibs(arg) 2204b88c807SRodney W. Grimes char *arg; 2214b88c807SRodney W. Grimes { 2224b88c807SRodney W. Grimes 22354946e00SBrian Feldman if (!(ddflags & C_BS)) { 224e14f7e78SBrian Feldman quad_t res = get_num(arg); 22554946e00SBrian Feldman 22654946e00SBrian Feldman if (res < 1 || res > INT_MAX) 22754946e00SBrian Feldman errx(1, "ibs must be between 1 and %d", INT_MAX); 22854946e00SBrian Feldman in.dbsz = (int)res; 22954946e00SBrian Feldman } 2304b88c807SRodney W. Grimes } 2314b88c807SRodney W. Grimes 2324b88c807SRodney W. Grimes static void 2334b88c807SRodney W. Grimes f_if(arg) 2344b88c807SRodney W. Grimes char *arg; 2354b88c807SRodney W. Grimes { 2364b88c807SRodney W. Grimes 2374b88c807SRodney W. Grimes in.name = arg; 2384b88c807SRodney W. Grimes } 2394b88c807SRodney W. Grimes 2404b88c807SRodney W. Grimes static void 2414b88c807SRodney W. Grimes f_obs(arg) 2424b88c807SRodney W. Grimes char *arg; 2434b88c807SRodney W. Grimes { 2444b88c807SRodney W. Grimes 24554946e00SBrian Feldman if (!(ddflags & C_BS)) { 246e14f7e78SBrian Feldman quad_t res = get_num(arg); 24754946e00SBrian Feldman 24854946e00SBrian Feldman if (res < 1 || res > INT_MAX) 24954946e00SBrian Feldman errx(1, "ibs must be between 1 and %d", INT_MAX); 25054946e00SBrian Feldman out.dbsz = (int)res; 25154946e00SBrian Feldman } 2524b88c807SRodney W. Grimes } 2534b88c807SRodney W. Grimes 2544b88c807SRodney W. Grimes static void 2554b88c807SRodney W. Grimes f_of(arg) 2564b88c807SRodney W. Grimes char *arg; 2574b88c807SRodney W. Grimes { 2584b88c807SRodney W. Grimes 2594b88c807SRodney W. Grimes out.name = arg; 2604b88c807SRodney W. Grimes } 2614b88c807SRodney W. Grimes 2624b88c807SRodney W. Grimes static void 2634b88c807SRodney W. Grimes f_seek(arg) 2644b88c807SRodney W. Grimes char *arg; 2654b88c807SRodney W. Grimes { 2664b88c807SRodney W. Grimes 267e14f7e78SBrian Feldman out.offset = get_num(arg); 2684b88c807SRodney W. Grimes } 2694b88c807SRodney W. Grimes 2704b88c807SRodney W. Grimes static void 2714b88c807SRodney W. Grimes f_skip(arg) 2724b88c807SRodney W. Grimes char *arg; 2734b88c807SRodney W. Grimes { 2744b88c807SRodney W. Grimes 275e14f7e78SBrian Feldman in.offset = get_num(arg); 2764b88c807SRodney W. Grimes } 2774b88c807SRodney W. Grimes 2784b88c807SRodney W. Grimes static struct conv { 2794b88c807SRodney W. Grimes char *name; 2804b88c807SRodney W. Grimes u_int set, noset; 2814b88c807SRodney W. Grimes u_char *ctab; 2824b88c807SRodney W. Grimes } clist[] = { 2834b88c807SRodney W. Grimes { "ascii", C_ASCII, C_EBCDIC, e2a_POSIX }, 2844b88c807SRodney W. Grimes { "block", C_BLOCK, C_UNBLOCK, NULL }, 2854b88c807SRodney W. Grimes { "ebcdic", C_EBCDIC, C_ASCII, a2e_POSIX }, 2864b88c807SRodney W. Grimes { "ibm", C_EBCDIC, C_ASCII, a2ibm_POSIX }, 2874b88c807SRodney W. Grimes { "lcase", C_LCASE, C_UCASE, NULL }, 2884b88c807SRodney W. Grimes { "noerror", C_NOERROR, 0, NULL }, 2894b88c807SRodney W. Grimes { "notrunc", C_NOTRUNC, 0, NULL }, 2904b88c807SRodney W. Grimes { "oldascii", C_ASCII, C_EBCDIC, e2a_32V }, 2914b88c807SRodney W. Grimes { "oldebcdic", C_EBCDIC, C_ASCII, a2e_32V }, 2924b88c807SRodney W. Grimes { "oldibm", C_EBCDIC, C_ASCII, a2ibm_32V }, 2934b88c807SRodney W. Grimes { "osync", C_OSYNC, C_BS, NULL }, 2941898febeSJoerg Wunsch { "sparse", C_SPARSE, 0, NULL }, 2954b88c807SRodney W. Grimes { "swab", C_SWAB, 0, NULL }, 2964b88c807SRodney W. Grimes { "sync", C_SYNC, 0, NULL }, 2974b88c807SRodney W. Grimes { "ucase", C_UCASE, C_LCASE, NULL }, 2984b88c807SRodney W. Grimes { "unblock", C_UNBLOCK, C_BLOCK, NULL }, 2994b88c807SRodney W. Grimes }; 3004b88c807SRodney W. Grimes 3014b88c807SRodney W. Grimes static void 3024b88c807SRodney W. Grimes f_conv(arg) 3034b88c807SRodney W. Grimes char *arg; 3044b88c807SRodney W. Grimes { 3054b88c807SRodney W. Grimes struct conv *cp, tmp; 3064b88c807SRodney W. Grimes 3074b88c807SRodney W. Grimes while (arg != NULL) { 3084b88c807SRodney W. Grimes tmp.name = strsep(&arg, ","); 30954946e00SBrian Feldman if (!(cp = (struct conv *)bsearch(&tmp, clist, 31054946e00SBrian Feldman sizeof(clist)/sizeof(struct conv), sizeof(struct conv), 3114b88c807SRodney W. Grimes c_conv))) 3124b88c807SRodney W. Grimes errx(1, "unknown conversion %s", tmp.name); 3134b88c807SRodney W. Grimes if (ddflags & cp->noset) 3144b88c807SRodney W. Grimes errx(1, "%s: illegal conversion combination", tmp.name); 3154b88c807SRodney W. Grimes ddflags |= cp->set; 3164b88c807SRodney W. Grimes if (cp->ctab) 3174b88c807SRodney W. Grimes ctab = cp->ctab; 3184b88c807SRodney W. Grimes } 3194b88c807SRodney W. Grimes } 3204b88c807SRodney W. Grimes 3214b88c807SRodney W. Grimes static int 3224b88c807SRodney W. Grimes c_conv(a, b) 3234b88c807SRodney W. Grimes const void *a, *b; 3244b88c807SRodney W. Grimes { 3254b88c807SRodney W. Grimes 3264b88c807SRodney W. Grimes return (strcmp(((struct conv *)a)->name, ((struct conv *)b)->name)); 3274b88c807SRodney W. Grimes } 3284b88c807SRodney W. Grimes 3294b88c807SRodney W. Grimes /* 33054946e00SBrian Feldman * Convert an expression of the following forms to a quad_t. 3314b88c807SRodney W. Grimes * 1) A positive decimal number. 33254946e00SBrian Feldman * 2) A positive decimal number followed by a b (mult by 512.) 33354946e00SBrian Feldman * 3) A positive decimal number followed by a k (mult by 1 << 10.) 33454946e00SBrian Feldman * 4) A positive decimal number followed by a m (mult by 1 << 20.) 33554946e00SBrian Feldman * 5) A positive decimal number followed by a g (mult by 1 << 30.) 33654946e00SBrian Feldman * 5) A positive decimal number followed by a w (mult by sizeof int.) 33754946e00SBrian Feldman * 6) Two or more positive decimal numbers (with/without [bkmgw]) 33846be34b9SKris Kennaway * separated by x (also * for backwards compatibility), specifying 3394b88c807SRodney W. Grimes * the product of the indicated values. 3404b88c807SRodney W. Grimes */ 34154946e00SBrian Feldman static quad_t 342e14f7e78SBrian Feldman get_num(val) 3434b88c807SRodney W. Grimes char *val; 3444b88c807SRodney W. Grimes { 34554946e00SBrian Feldman quad_t num, t; 3464b88c807SRodney W. Grimes char *expr; 3474b88c807SRodney W. Grimes 34854946e00SBrian Feldman errno = 0; 349767bc8adSBrian Feldman num = strtoq(val, &expr, 0); 350e14f7e78SBrian Feldman if (errno) /* Overflow or underflow. */ 35154946e00SBrian Feldman err(1, "%s", oper); 35254946e00SBrian Feldman 353e14f7e78SBrian Feldman if (expr == val) /* Not a valid number */ 3544b88c807SRodney W. Grimes errx(1, "%s: illegal numeric value", oper); 3554b88c807SRodney W. Grimes 3564b88c807SRodney W. Grimes switch (*expr) { 3574b88c807SRodney W. Grimes case 'b': 3584b88c807SRodney W. Grimes t = num; 3594b88c807SRodney W. Grimes num *= 512; 3604b88c807SRodney W. Grimes if (t > num) 3614b88c807SRodney W. Grimes goto erange; 3624b88c807SRodney W. Grimes ++expr; 3634b88c807SRodney W. Grimes break; 3644b88c807SRodney W. Grimes case 'k': 3654b88c807SRodney W. Grimes t = num; 36654946e00SBrian Feldman num *= 1 << 10; 3674b88c807SRodney W. Grimes if (t > num) 3684b88c807SRodney W. Grimes goto erange; 3694b88c807SRodney W. Grimes ++expr; 3704b88c807SRodney W. Grimes break; 3714b88c807SRodney W. Grimes case 'm': 3724b88c807SRodney W. Grimes t = num; 37354946e00SBrian Feldman num *= 1 << 20; 37454946e00SBrian Feldman if (t > num) 37554946e00SBrian Feldman goto erange; 37654946e00SBrian Feldman ++expr; 37754946e00SBrian Feldman break; 37854946e00SBrian Feldman case 'g': 37954946e00SBrian Feldman t = num; 38054946e00SBrian Feldman num *= 1 << 30; 3814b88c807SRodney W. Grimes if (t > num) 3824b88c807SRodney W. Grimes goto erange; 3834b88c807SRodney W. Grimes ++expr; 3844b88c807SRodney W. Grimes break; 3854b88c807SRodney W. Grimes case 'w': 3864b88c807SRodney W. Grimes t = num; 3874b88c807SRodney W. Grimes num *= sizeof(int); 3884b88c807SRodney W. Grimes if (t > num) 3894b88c807SRodney W. Grimes goto erange; 3904b88c807SRodney W. Grimes ++expr; 3914b88c807SRodney W. Grimes break; 3924b88c807SRodney W. Grimes } 3934b88c807SRodney W. Grimes 3944b88c807SRodney W. Grimes switch (*expr) { 3954b88c807SRodney W. Grimes case '\0': 3964b88c807SRodney W. Grimes break; 3974b88c807SRodney W. Grimes case '*': /* Backward compatible. */ 3984b88c807SRodney W. Grimes case 'x': 3994b88c807SRodney W. Grimes t = num; 400e14f7e78SBrian Feldman num *= get_num(expr + 1); 401e14f7e78SBrian Feldman if (t <= num) 4024b88c807SRodney W. Grimes break; 403e14f7e78SBrian Feldman erange: 404e14f7e78SBrian Feldman errx(1, "%s: %s", oper, strerror(ERANGE)); 4054b88c807SRodney W. Grimes default: 4064b88c807SRodney W. Grimes errx(1, "%s: illegal numeric value", oper); 4074b88c807SRodney W. Grimes } 4084b88c807SRodney W. Grimes return (num); 4094b88c807SRodney W. Grimes } 410