blob: 328735737d1811acb69f2782934d046c2329bc06 [file] [log] [blame]
Gavin Howard5715b042018-02-12 16:11:42 -07001/*
Gavin Howardb5904bf2018-02-20 13:28:18 -07002 * *****************************************************************************
Gavin Howard5715b042018-02-12 16:11:42 -07003 *
Gavin Howardb5904bf2018-02-20 13:28:18 -07004 * Copyright 2018 Gavin D. Howard
Gavin Howard5715b042018-02-12 16:11:42 -07005 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
14 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
16 *
Gavin Howardb5904bf2018-02-20 13:28:18 -070017 * *****************************************************************************
Gavin Howard5715b042018-02-12 16:11:42 -070018 *
19 * The entry point for bc.
20 *
21 */
22
Gavin Howardc5e491b2018-02-20 13:51:20 -070023#include <stdbool.h>
Gavin Howard3e7cf052018-01-27 00:50:45 -070024#include <stdio.h>
Gavin Howarddce6dc92018-01-26 12:08:43 -070025#include <string.h>
26
Gavin Howardbc9fa772018-01-24 11:49:33 -070027#include <locale.h>
28
Gavin Howarddce6dc92018-01-26 12:08:43 -070029#include <getopt.h>
30
Gavin Howard13ccc4a2018-02-15 14:09:41 -070031#include <bc.h>
Gavin Howarddec399f2018-01-23 12:09:11 -070032
Gavin Howard07add2e2018-03-10 19:23:41 -070033static const struct option bc_opts[] = {
Gavin Howarddce6dc92018-01-26 12:08:43 -070034
Gavin Howard914030d2018-02-08 20:05:19 -070035 { "code", no_argument, NULL, 'c' },
Gavin Howarddce6dc92018-01-26 12:08:43 -070036 { "help", no_argument, NULL, 'h' },
37 { "interactive", no_argument, NULL, 'i' },
38 { "mathlib", no_argument, NULL, 'l' },
39 { "quiet", no_argument, NULL, 'q' },
40 { "standard", no_argument, NULL, 's' },
41 { "version", no_argument, NULL, 'v' },
42 { "warn", no_argument, NULL, 'w' },
43 { 0, 0, 0, 0 },
44
45};
46
Gavin Howard07add2e2018-03-10 19:23:41 -070047static const char *bc_short_opts = "chilqsvw";
Gavin Howard3e7cf052018-01-27 00:50:45 -070048
Gavin Howard07add2e2018-03-10 19:23:41 -070049static const char *bc_help =
Gavin Howardf03f34c2018-02-20 13:46:46 -070050 "usage: bc [-hilqsvw] [long-options] [file...]\n"
Gavin Howard3e7cf052018-01-27 00:50:45 -070051 "\n"
52 "bc is a command-line calculator with a Turing-complete language.\n"
53 "\n"
Gavin Howard91072cf2018-02-08 21:07:51 -070054 " -c --code print bytecode instead of executing it\n"
Gavin Howard3e7cf052018-01-27 00:50:45 -070055 " -h --help print this usage message and exit\n"
56 " -i --interactive force interactive mode\n"
57 " -l --mathlib use predefined math routines:\n\n"
58 " s(expr) = sine of expr in radians\n"
59 " c(expr) = cosine of expr in radians\n"
60 " a(expr) = arctangent of expr, returning radians\n"
61 " l(expr) = natural log of expr\n"
62 " e(expr) = raises e to the power of expr\n"
63 " j(n, x) = Bessel function of integer order n of x\n"
64 "\n"
65 " -q --quiet don't print version and copyright\n"
66 " -s --standard error if any non-POSIX extensions are used\n"
67 " -w --warn warn if any non-POSIX extensions are used\n"
68 " -v --version print version information and copyright and exit\n\n";
69
Gavin Howard12ca4702018-03-09 19:27:11 -070070BcGlobals bcg;
Gavin Howarddce6dc92018-01-26 12:08:43 -070071
Gavin Howard8d1f1db2018-02-23 11:29:41 -070072int main(int argc, char *argv[]) {
Gavin Howarddce6dc92018-01-26 12:08:43 -070073
Gavin Howardc5e491b2018-02-20 13:51:20 -070074 BcStatus status;
Gavin Howarddce6dc92018-01-26 12:08:43 -070075 unsigned int flags;
76 unsigned int filec;
Gavin Howardb5f1cb12018-03-13 12:39:52 -060077 char** filev;
Gavin Howardc5e491b2018-02-20 13:51:20 -070078 bool do_exit;
Gavin Howarddce6dc92018-01-26 12:08:43 -070079
Gavin Howard4bc73ee2018-01-26 11:39:20 -070080 setlocale(LC_ALL, "");
Gavin Howarddce6dc92018-01-26 12:08:43 -070081
Gavin Howard12ca4702018-03-09 19:27:11 -070082 memset(&bcg, 0, sizeof(BcGlobals));
Gavin Howard729f7642018-03-09 02:58:44 -070083
Gavin Howardc5e491b2018-02-20 13:51:20 -070084 do_exit = false;
Gavin Howarddce6dc92018-01-26 12:08:43 -070085 flags = 0;
Gavin Howardc5e491b2018-02-20 13:51:20 -070086 status = BC_STATUS_SUCCESS;
Gavin Howarddce6dc92018-01-26 12:08:43 -070087
88 // Getopt needs this.
89 int opt_idx = 0;
90
91 int c = getopt_long(argc, argv, bc_short_opts, bc_opts, &opt_idx);
92
93 while (c != -1) {
94
95 switch (c) {
96
97 case 0:
98 {
99 // This is the case when a long option is
100 // found, so we don't need to do anything.
101 break;
102 }
103
Gavin Howard914030d2018-02-08 20:05:19 -0700104 case 'c':
105 {
Gavin Howardee110332018-02-08 20:52:41 -0700106 flags |= BC_FLAG_CODE;
107 break;
Gavin Howard914030d2018-02-08 20:05:19 -0700108 }
109
Gavin Howarddce6dc92018-01-26 12:08:43 -0700110 case 'h':
111 {
Gavin Howardd8a2b502018-02-24 13:26:48 -0700112 if (printf("%s", bc_help) < 0) return BC_STATUS_IO_ERR;
Gavin Howardc5e491b2018-02-20 13:51:20 -0700113 do_exit = true;
Gavin Howarddce6dc92018-01-26 12:08:43 -0700114 break;
115 }
116
117 case 'i':
118 {
119 flags |= BC_FLAG_INTERACTIVE;
120 break;
121 }
122
123 case 'l':
124 {
125 flags |= BC_FLAG_MATHLIB;
126 break;
127 }
128
129 case 'q':
130 {
131 flags |= BC_FLAG_QUIET;
132 break;
133 }
134
135 case 's':
136 {
137 flags |= BC_FLAG_STANDARD;
138 break;
139 }
140
141 case 'v':
142 {
Gavin Howarda280bde2018-03-13 13:49:12 -0600143 if (printf("%s", bc_header) < 0) return BC_STATUS_IO_ERR;
Gavin Howardc5e491b2018-02-20 13:51:20 -0700144 do_exit = true;
Gavin Howarddce6dc92018-01-26 12:08:43 -0700145 break;
146 }
147
148 case 'w':
149 {
150 flags |= BC_FLAG_WARN;
151 break;
152 }
153
154 // Getopt printed an error message, but we should exit.
155 case '?':
156 default:
157 {
158 return BC_STATUS_INVALID_OPTION;
159 break;
160 }
161 }
162
163 c = getopt_long(argc, argv, bc_short_opts, bc_opts, &opt_idx);
164 }
165
Gavin Howardc5e491b2018-02-20 13:51:20 -0700166 if (do_exit) return status;
Gavin Howard3e7cf052018-01-27 00:50:45 -0700167
Gavin Howardc5e491b2018-02-20 13:51:20 -0700168 if (argv[optind] && strcmp(argv[optind], "--") == 0) ++optind;
Gavin Howarddce6dc92018-01-26 12:08:43 -0700169
170 filec = argc - optind;
Gavin Howardb5f1cb12018-03-13 12:39:52 -0600171 filev = argv + optind;
Gavin Howarddce6dc92018-01-26 12:08:43 -0700172
Gavin Howardf1ab44f2018-03-13 16:15:38 -0600173 return bc_main(flags, filec, filev);
Gavin Howarddec399f2018-01-23 12:09:11 -0700174}