Sync usage with man page.
[netbsd-mini2440.git] / gnu / dist / bc / dc / dc.c
blobfb798a2201914397de2eab2c1c8d733122715e88
1 /*
2 * implement the "dc" Desk Calculator language.
4 * Copyright (C) 1994, 1997, 1998, 2000 Free Software Foundation, Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you can either send email to this
18 * program's author (see below) or write to:
19 * The Free Software Foundation, Inc.
20 * 59 Temple Place, Suite 330
21 * Boston, MA 02111 USA
24 /* Written with strong hiding of implementation details
25 * in their own specialized modules.
27 /* This module contains the argument processing/main functions.
30 #include "config.h"
32 #include <stdio.h>
33 #ifdef HAVE_STDLIB_H
34 # include <stdlib.h>
35 #endif
36 #ifdef HAVE_STRING_H
37 # include <string.h>
38 #else
39 # ifdef HAVE_STRINGS_H
40 # include <strings.h>
41 # endif
42 #endif
43 #include <getopt.h>
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #include <errno.h>
47 #include "dc.h"
48 #include "dc-proto.h"
50 #ifndef EXIT_SUCCESS /* C89 <stdlib.h> */
51 # define EXIT_SUCCESS 0
52 #endif
53 #ifndef EXIT_FAILURE /* C89 <stdlib.h> */
54 # define EXIT_FAILURE 1
55 #endif
57 const char *progname; /* basename of program invocation */
59 static void
60 bug_report_info DC_DECLVOID()
62 printf("Email bug reports to: bug-dc@gnu.org .\n");
65 static void
66 show_version DC_DECLVOID()
68 printf("dc (GNU %s %s) %s\n", PACKAGE, VERSION, DC_VERSION);
69 printf("\n%s\n\
70 This is free software; see the source for copying conditions. There is NO\n\
71 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n\
72 to the extent permitted by law.\n", DC_COPYRIGHT);
75 /* your generic usage function */
76 static void
77 usage DC_DECLARG((f))
78 FILE *f DC_DECLEND
80 fprintf(f, "\
81 Usage: %s [OPTION] [file ...]\n\
82 -e, --expression=EXPR evaluate expression\n\
83 -f, --file=FILE evaluate contents of file\n\
84 -h, --help display this help and exit\n\
85 -V, --version output version information and exit\n\
86 \n\
87 ", progname);
88 bug_report_info();
91 /* returns a pointer to one past the last occurance of c in s,
92 * or s if c does not occur in s.
94 static char *
95 r1bindex DC_DECLARG((s, c))
96 char *s DC_DECLSEP
97 int c DC_DECLEND
99 char *p = strrchr(s, c);
101 if (!p)
102 return s;
103 return p + 1;
106 static void
107 try_file(const char *filename)
109 FILE *input;
111 if (strcmp(filename, "-") == 0) {
112 input = stdin;
113 } else {
114 struct stat sb;
115 if (stat(filename, &sb) < 0) {
116 fprintf(stderr, "Cannot stat %s: %s\n",
117 filename, strerror(errno));
118 exit(EXIT_FAILURE);
120 if (S_ISDIR(sb.st_mode)) {
121 fprintf(stderr, "Cannot use directory as input!\n");
122 exit(EXIT_FAILURE);
124 if ( !(input=fopen(filename, "r")) ) {
125 fprintf(stderr, "Could not open file ");
126 perror(filename);
127 exit(EXIT_FAILURE);
130 if (dc_evalfile(input))
131 exit(EXIT_FAILURE);
132 if (input != stdin)
133 fclose(input);
138 main DC_DECLARG((argc, argv))
139 int argc DC_DECLSEP
140 char **argv DC_DECLEND
142 static struct option const long_opts[] = {
143 {"expression", required_argument, NULL, 'e'},
144 {"file", required_argument, NULL, 'f'},
145 {"help", no_argument, NULL, 'h'},
146 {"version", no_argument, NULL, 'V'},
147 {NULL, 0, NULL, 0}
149 int did_eval = 0;
150 int c;
152 progname = r1bindex(*argv, '/');
153 #ifdef HAVE_SETVBUF
154 /* attempt to simplify interaction with applications such as emacs */
155 (void) setvbuf(stdout, NULL, _IOLBF, 0);
156 #endif
157 dc_math_init();
158 dc_string_init();
159 dc_register_init();
160 dc_array_init();
162 while ((c = getopt_long(argc, argv, "hVe:f:", long_opts, (int *)0)) != EOF) {
163 switch (c) {
164 case 'e':
165 { dc_data string = dc_makestring(optarg, strlen(optarg));
166 if (dc_evalstr(string))
167 return EXIT_SUCCESS;
168 dc_free_str(&string.v.string);
169 did_eval = 1;
171 break;
172 case 'f':
173 try_file(optarg);
174 did_eval = 1;
175 break;
176 case 'h':
177 usage(stdout);
178 return EXIT_SUCCESS;
179 case 'V':
180 show_version();
181 return EXIT_SUCCESS;
182 default:
183 usage(stderr);
184 return EXIT_FAILURE;
188 for (; optind < argc; ++optind) {
189 try_file(argv[optind]);
190 did_eval = 1;
192 if (!did_eval) {
193 /* if no -e commands and no command files, then eval stdin */
194 if (dc_evalfile(stdin))
195 return EXIT_FAILURE;
197 return EXIT_SUCCESS;