dc.c revision 247441
1250136Simp/* $OpenBSD: dc.c,v 1.11 2009/10/27 23:59:37 deraadt Exp $ */ 2250136Simp 3250134Simp/* 4250134Simp * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net> 5250136Simp * Copyright (c) 2009, Gabor Kovesdan <gabor@FreeBSD.org> 6178172Simp * 7250134Simp * Permission to use, copy, modify, and distribute this software for any 8250134Simp * purpose with or without fee is hereby granted, provided that the above 9250134Simp * copyright notice and this permission notice appear in all copies. 10178172Simp * 11250134Simp * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12250134Simp * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13250134Simp * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14250134Simp * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15250134Simp * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16250134Simp * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17250134Simp * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18250134Simp */ 19250136Simp 20250134Simp#include <sys/cdefs.h> 21250134Simp__FBSDID("$FreeBSD: head/usr.bin/dc/dc.c 247441 2013-02-28 01:22:14Z gjb $"); 22250134Simp 23250134Simp#include <sys/stat.h> 24250134Simp 25250134Simp#include <ctype.h> 26250134Simp#include <err.h> 27250134Simp#include <errno.h> 28250134Simp#include <getopt.h> 29250134Simp#include <stdio.h> 30250134Simp#include <stdlib.h> 31250134Simp#include <string.h> 32250134Simp#include <unistd.h> 33250134Simp 34250136Simp#include "extern.h" 35250136Simp 36178172Simp#define DC_VER "1.3-FreeBSD" 37178172Simp 38178172Simpstatic void usage(void); 39250136Simp 40250136Simpextern char *__progname; 41250135Simp 42250136Simpstatic struct source src; 43250135Simp 44250136Simpstatic const struct option long_options[] = 45250136Simp{ 46250136Simp {"expression", required_argument, NULL, 'e'}, 47250136Simp {"file", required_argument, NULL, 'f'}, 48250136Simp {"help", no_argument, NULL, 'h'}, 49250136Simp {"version", no_argument, NULL, 'V'} 50250136Simp}; 51250136Simp 52250136Simpstatic void 53250136Simpusage(void) 54250136Simp{ 55250136Simp fprintf(stderr, "usage: %s [-hVx] [-e expression] [file]\n", 56250136Simp __progname); 57250136Simp exit(1); 58250136Simp} 59250136Simp 60250136Simpstatic void 61250136Simpprocfile(char *fname) { 62250136Simp struct stat st; 63250136Simp FILE *file; 64250136Simp 65250136Simp file = fopen(fname, "r"); 66250136Simp if (file == NULL) 67250136Simp err(1, "cannot open file %s", fname); 68250136Simp if (fstat(fileno(file), &st) == -1) 69250136Simp err(1, "%s", fname); 70250136Simp if (S_ISDIR(st.st_mode)) { 71250136Simp errno = EISDIR; 72250136Simp err(1, "%s", fname); 73250136Simp } 74250136Simp src_setstream(&src, file); 75250136Simp reset_bmachine(&src); 76250136Simp eval(); 77250136Simp fclose(file); 78250136Simp} 79250136Simp 80250136Simpint 81250136Simpmain(int argc, char *argv[]) 82250136Simp{ 83250136Simp int ch; 84250136Simp bool extended_regs = false, preproc_done = false; 85250136Simp 86250136Simp /* accept and ignore a single dash to be 4.4BSD dc(1) compatible */ 87250136Simp while ((ch = getopt_long(argc, argv, "e:f:hVx", long_options, NULL)) != -1) { 88250136Simp switch (ch) { 89250136Simp case 'e': 90250136Simp if (!preproc_done) 91250136Simp init_bmachine(extended_regs); 92250136Simp src_setstring(&src, optarg); 93250136Simp reset_bmachine(&src); 94250136Simp eval(); 95250136Simp preproc_done = true; 96250136Simp break; 97250136Simp case 'f': 98250136Simp if (!preproc_done) 99250136Simp init_bmachine(extended_regs); 100250136Simp procfile(optarg); 101250136Simp preproc_done = true; 102250136Simp break; 103250136Simp case 'x': 104250136Simp extended_regs = true; 105250136Simp break; 106250136Simp case 'V': 107250136Simp fprintf(stderr, "%s (BSD bc) %s\n", __progname, DC_VER); 108250136Simp exit(0); 109 break; 110 case '-': 111 break; 112 case 'h': 113 /* FALLTHROUGH */ 114 default: 115 usage(); 116 } 117 } 118 argc -= optind; 119 argv += optind; 120 121 if (!preproc_done) 122 init_bmachine(extended_regs); 123 setlinebuf(stdout); 124 setlinebuf(stderr); 125 126 if (argc > 1) 127 usage(); 128 if (argc == 1) { 129 procfile(argv[0]); 130 preproc_done = true; 131 } 132 if (preproc_done) 133 return (0); 134 135 src_setstream(&src, stdin); 136 reset_bmachine(&src); 137 eval(); 138 139 return (0); 140} 141