1202719Sgabor/*	$OpenBSD: dc.c,v 1.11 2009/10/27 23:59:37 deraadt Exp $	*/
2202719Sgabor
3202719Sgabor/*
4202719Sgabor * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
5202719Sgabor * Copyright (c) 2009, Gabor Kovesdan <gabor@FreeBSD.org>
6202719Sgabor *
7202719Sgabor * Permission to use, copy, modify, and distribute this software for any
8202719Sgabor * purpose with or without fee is hereby granted, provided that the above
9202719Sgabor * copyright notice and this permission notice appear in all copies.
10202719Sgabor *
11202719Sgabor * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12202719Sgabor * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13202719Sgabor * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14202719Sgabor * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15202719Sgabor * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16202719Sgabor * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17202719Sgabor * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18202719Sgabor */
19202719Sgabor
20202719Sgabor#include <sys/cdefs.h>
21202719Sgabor__FBSDID("$FreeBSD: stable/10/usr.bin/dc/dc.c 315135 2017-03-12 05:36:31Z pfg $");
22202719Sgabor
23202719Sgabor#include <sys/stat.h>
24202719Sgabor
25202719Sgabor#include <ctype.h>
26202719Sgabor#include <err.h>
27202719Sgabor#include <errno.h>
28202719Sgabor#include <getopt.h>
29202719Sgabor#include <stdio.h>
30202719Sgabor#include <stdlib.h>
31202719Sgabor#include <string.h>
32202719Sgabor#include <unistd.h>
33202719Sgabor
34202719Sgabor#include "extern.h"
35202719Sgabor
36202719Sgabor#define	DC_VER		"1.3-FreeBSD"
37202719Sgabor
38202719Sgaborstatic void		 usage(void);
39202719Sgabor
40202719Sgaborextern char		*__progname;
41202719Sgabor
42227163Sedstatic struct source	 src;
43202719Sgabor
44227163Sedstatic const struct option long_options[] =
45202719Sgabor{
46202719Sgabor	{"expression",		required_argument,	NULL,	'e'},
47202719Sgabor	{"file",		required_argument,	NULL,	'f'},
48202719Sgabor	{"help",		no_argument,		NULL,	'h'},
49202719Sgabor	{"version",		no_argument,		NULL,	'V'}
50202719Sgabor};
51202719Sgabor
52202719Sgaborstatic void
53202719Sgaborusage(void)
54202719Sgabor{
55202719Sgabor	fprintf(stderr, "usage: %s [-hVx] [-e expression] [file]\n",
56202719Sgabor	    __progname);
57202719Sgabor	exit(1);
58202719Sgabor}
59202719Sgabor
60202719Sgaborstatic void
61202719Sgaborprocfile(char *fname) {
62203443Sgabor	struct stat st;
63203443Sgabor	FILE *file;
64202719Sgabor
65202719Sgabor	file = fopen(fname, "r");
66202719Sgabor	if (file == NULL)
67202719Sgabor		err(1, "cannot open file %s", fname);
68202719Sgabor	if (fstat(fileno(file), &st) == -1)
69202719Sgabor		err(1, "%s", fname);
70202719Sgabor	if (S_ISDIR(st.st_mode)) {
71202719Sgabor		errno = EISDIR;
72202719Sgabor		err(1, "%s", fname);
73202719Sgabor	}
74202719Sgabor	src_setstream(&src, file);
75202719Sgabor	reset_bmachine(&src);
76202719Sgabor	eval();
77202719Sgabor	fclose(file);
78202719Sgabor}
79202719Sgabor
80202719Sgaborint
81202719Sgabormain(int argc, char *argv[])
82202719Sgabor{
83203443Sgabor	int ch;
84203443Sgabor	bool extended_regs = false, preproc_done = false;
85202719Sgabor
86202719Sgabor	/* accept and ignore a single dash to be 4.4BSD dc(1) compatible */
87247441Sgjb	while ((ch = getopt_long(argc, argv, "e:f:hVx", long_options, NULL)) != -1) {
88202719Sgabor		switch (ch) {
89202719Sgabor		case 'e':
90208974Sgabor			if (!preproc_done)
91208867Sgabor				init_bmachine(extended_regs);
92202719Sgabor			src_setstring(&src, optarg);
93202719Sgabor			reset_bmachine(&src);
94202719Sgabor			eval();
95202719Sgabor			preproc_done = true;
96202719Sgabor			break;
97202719Sgabor		case 'f':
98208974Sgabor			if (!preproc_done)
99208867Sgabor				init_bmachine(extended_regs);
100202719Sgabor			procfile(optarg);
101202719Sgabor			preproc_done = true;
102202719Sgabor			break;
103202719Sgabor		case 'x':
104202719Sgabor			extended_regs = true;
105202719Sgabor			break;
106202719Sgabor		case 'V':
107202719Sgabor			fprintf(stderr, "%s (BSD bc) %s\n", __progname, DC_VER);
108202719Sgabor			exit(0);
109202719Sgabor			break;
110202719Sgabor		case '-':
111202719Sgabor			break;
112202719Sgabor		case 'h':
113202719Sgabor			/* FALLTHROUGH */
114202719Sgabor		default:
115202719Sgabor			usage();
116202719Sgabor		}
117202719Sgabor	}
118202719Sgabor	argc -= optind;
119202719Sgabor	argv += optind;
120202719Sgabor
121208867Sgabor	if (!preproc_done)
122208867Sgabor		init_bmachine(extended_regs);
123315135Spfg	(void)setvbuf(stdout, NULL, _IOLBF, 0);
124315135Spfg	(void)setvbuf(stderr, NULL, _IOLBF, 0);
125203438Sgabor
126202719Sgabor	if (argc > 1)
127202719Sgabor		usage();
128202719Sgabor	if (argc == 1) {
129202719Sgabor		procfile(argv[0]);
130202719Sgabor		preproc_done = true;
131202719Sgabor	}
132202719Sgabor	if (preproc_done)
133202719Sgabor		return (0);
134202719Sgabor
135202719Sgabor	src_setstream(&src, stdin);
136202719Sgabor	reset_bmachine(&src);
137202719Sgabor	eval();
138202719Sgabor
139202719Sgabor	return (0);
140202719Sgabor}
141