dc.c revision 203438
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: head/usr.bin/dc/dc.c 203438 2010-02-03 19:13:41Z gabor $");
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
42202719Sgaborstruct source		 src;
43202719Sgabor
44202719Sgaborstruct 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) {
62202719Sgabor	FILE		*file;
63202719Sgabor	struct stat	 st;
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{
83202719Sgabor	int		 ch;
84202719Sgabor	bool		 extended_regs = false;
85202719Sgabor	bool		 preproc_done = false;
86202719Sgabor
87202719Sgabor	/* accept and ignore a single dash to be 4.4BSD dc(1) compatible */
88202719Sgabor	while ((ch = getopt_long(argc, argv, "e:f:Vx", long_options, NULL)) != -1) {
89202719Sgabor		switch (ch) {
90202719Sgabor		case 'e':
91202719Sgabor			src_setstring(&src, optarg);
92202719Sgabor			reset_bmachine(&src);
93202719Sgabor			eval();
94202719Sgabor			preproc_done = true;
95202719Sgabor			break;
96202719Sgabor		case 'f':
97202719Sgabor			procfile(optarg);
98202719Sgabor			preproc_done = true;
99202719Sgabor			break;
100202719Sgabor		case 'x':
101202719Sgabor			extended_regs = true;
102202719Sgabor			break;
103202719Sgabor		case 'V':
104202719Sgabor			fprintf(stderr, "%s (BSD bc) %s\n", __progname, DC_VER);
105202719Sgabor			exit(0);
106202719Sgabor			break;
107202719Sgabor		case '-':
108202719Sgabor			break;
109202719Sgabor		case 'h':
110202719Sgabor			/* FALLTHROUGH */
111202719Sgabor		default:
112202719Sgabor			usage();
113202719Sgabor		}
114202719Sgabor	}
115202719Sgabor	argc -= optind;
116202719Sgabor	argv += optind;
117202719Sgabor
118203438Sgabor	init_bmachine(extended_regs);
119203438Sgabor	setlinebuf(stdout);
120203438Sgabor	setlinebuf(stderr);
121203438Sgabor
122202719Sgabor	if (argc > 1)
123202719Sgabor		usage();
124202719Sgabor	if (argc == 1) {
125202719Sgabor		procfile(argv[0]);
126202719Sgabor		preproc_done = true;
127202719Sgabor	}
128202719Sgabor	if (preproc_done)
129202719Sgabor		return (0);
130202719Sgabor
131202719Sgabor	src_setstream(&src, stdin);
132202719Sgabor	reset_bmachine(&src);
133202719Sgabor	eval();
134202719Sgabor
135202719Sgabor	return (0);
136202719Sgabor}
137