dc.c revision 208974
1139749Simp/*	$OpenBSD: dc.c,v 1.11 2009/10/27 23:59:37 deraadt Exp $	*/
2119917Swpaul
3119917Swpaul/*
4139749Simp * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
5119917Swpaul * Copyright (c) 2009, Gabor Kovesdan <gabor@FreeBSD.org>
6119917Swpaul *
7119917Swpaul * Permission to use, copy, modify, and distribute this software for any
8119917Swpaul * purpose with or without fee is hereby granted, provided that the above
9119917Swpaul * copyright notice and this permission notice appear in all copies.
10119917Swpaul *
11119917Swpaul * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12119917Swpaul * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13119917Swpaul * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14119917Swpaul * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15119917Swpaul * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16119917Swpaul * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17119917Swpaul * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18119917Swpaul */
19119917Swpaul
20119917Swpaul#include <sys/cdefs.h>
21119917Swpaul__FBSDID("$FreeBSD: head/usr.bin/dc/dc.c 208974 2010-06-10 10:17:00Z gabor $");
22119917Swpaul
23119917Swpaul#include <sys/stat.h>
24119917Swpaul
25119917Swpaul#include <ctype.h>
26119917Swpaul#include <err.h>
27119917Swpaul#include <errno.h>
28119917Swpaul#include <getopt.h>
29119917Swpaul#include <stdio.h>
30119917Swpaul#include <stdlib.h>
31119917Swpaul#include <string.h>
32119917Swpaul#include <unistd.h>
33181953Syongari
34181953Syongari#include "extern.h"
35181953Syongari
36181953Syongari#define	DC_VER		"1.3-FreeBSD"
37119917Swpaul
38129879Sphkstatic void		 usage(void);
39181953Syongari
40119917Swpaulextern char		*__progname;
41181953Syongari
42181994Syongaristruct source		 src;
43119917Swpaul
44181953Syongaristruct option long_options[] =
45119917Swpaul{
46119917Swpaul	{"expression",		required_argument,	NULL,	'e'},
47119917Swpaul	{"file",		required_argument,	NULL,	'f'},
48119917Swpaul	{"help",		no_argument,		NULL,	'h'},
49119917Swpaul	{"version",		no_argument,		NULL,	'V'}
50119917Swpaul};
51119917Swpaul
52119917Swpaulstatic void
53119917Swpaulusage(void)
54119917Swpaul{
55119917Swpaul	fprintf(stderr, "usage: %s [-hVx] [-e expression] [file]\n",
56119917Swpaul	    __progname);
57119917Swpaul	exit(1);
58181953Syongari}
59181953Syongari
60119917Swpaulstatic void
61119917Swpaulprocfile(char *fname) {
62119917Swpaul	struct stat st;
63119917Swpaul	FILE *file;
64119917Swpaul
65119917Swpaul	file = fopen(fname, "r");
66151545Simp	if (file == NULL)
67119917Swpaul		err(1, "cannot open file %s", fname);
68119917Swpaul	if (fstat(fileno(file), &st) == -1)
69119917Swpaul		err(1, "%s", fname);
70119917Swpaul	if (S_ISDIR(st.st_mode)) {
71119917Swpaul		errno = EISDIR;
72119917Swpaul		err(1, "%s", fname);
73119917Swpaul	}
74134590Sdes	src_setstream(&src, file);
75134590Sdes	reset_bmachine(&src);
76119917Swpaul	eval();
77119917Swpaul	fclose(file);
78119917Swpaul}
79119917Swpaul
80119917Swpaulint
81119917Swpaulmain(int argc, char *argv[])
82164456Sjhb{
83164456Sjhb	int ch;
84119917Swpaul	bool extended_regs = false, preproc_done = false;
85119917Swpaul
86181953Syongari	/* accept and ignore a single dash to be 4.4BSD dc(1) compatible */
87119917Swpaul	while ((ch = getopt_long(argc, argv, "e:f:Vx", long_options, NULL)) != -1) {
88136804Smtm		switch (ch) {
89119917Swpaul		case 'e':
90119917Swpaul			if (!preproc_done)
91136804Smtm				init_bmachine(extended_regs);
92119917Swpaul			src_setstring(&src, optarg);
93175787Syongari			reset_bmachine(&src);
94173839Syongari			eval();
95119917Swpaul			preproc_done = true;
96119917Swpaul			break;
97119917Swpaul		case 'f':
98119917Swpaul			if (!preproc_done)
99119917Swpaul				init_bmachine(extended_regs);
100181953Syongari			procfile(optarg);
101181953Syongari			preproc_done = true;
102181953Syongari			break;
103119917Swpaul		case 'x':
104119917Swpaul			extended_regs = true;
105119917Swpaul			break;
106119917Swpaul		case 'V':
107119917Swpaul			fprintf(stderr, "%s (BSD bc) %s\n", __progname, DC_VER);
108119917Swpaul			exit(0);
109119917Swpaul			break;
110119917Swpaul		case '-':
111133282Sdes			break;
112119917Swpaul		case 'h':
113119917Swpaul			/* FALLTHROUGH */
114119917Swpaul		default:
115119917Swpaul			usage();
116119917Swpaul		}
117119917Swpaul	}
118119917Swpaul	argc -= optind;
119119917Swpaul	argv += optind;
120119917Swpaul
121119917Swpaul	if (!preproc_done)
122119917Swpaul		init_bmachine(extended_regs);
123119917Swpaul	setlinebuf(stdout);
124119917Swpaul	setlinebuf(stderr);
125181953Syongari
126181953Syongari	if (argc > 1)
127119917Swpaul		usage();
128119917Swpaul	if (argc == 1) {
129181994Syongari		procfile(argv[0]);
130119917Swpaul		preproc_done = true;
131119917Swpaul	}
132119917Swpaul	if (preproc_done)
133119917Swpaul		return (0);
134119917Swpaul
135119917Swpaul	src_setstream(&src, stdin);
136119917Swpaul	reset_bmachine(&src);
137164456Sjhb	eval();
138164456Sjhb
139119917Swpaul	return (0);
140119917Swpaul}
141119917Swpaul