1 /* 2 * implement the "dc" Desk Calculator language. 3 * 4 * Copyright (C) 1994, 1997, 1998 Free Software Foundation, Inc. 5 * 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. 10 * 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. 15 * 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: The Free Software Foundation, 19 * Inc.; 675 Mass Ave. Cambridge, MA 02139, USA. 20 */ 21 22 /* Written with strong hiding of implementation details 23 * in their own specialized modules. 24 */ 25 /* This module contains the argument processing/main functions. 26 */ 27 28 #include "config.h" 29 30 #include <stdio.h> 31 #ifdef HAVE_STDLIB_H 32 # include <stdlib.h> 33 #endif 34 #ifdef HAVE_STRING_H 35 # include <string.h> 36 #else 37 # ifdef HAVE_STRINGS_H 38 # include <strings.h> 39 # endif 40 #endif 41 #include <getopt.h> 42 #include "dc.h" 43 #include "dc-proto.h" 44 45 #include "version.h" 46 47 #ifndef EXIT_SUCCESS /* C89 <stdlib.h> */ 48 # define EXIT_SUCCESS 0 49 #endif 50 #ifndef EXIT_FAILURE /* C89 <stdlib.h> */ 51 # define EXIT_FAILURE 1 52 #endif 53 54 const char *progname; /* basename of program invocation */ 55 56 /* your generic usage function */ 57 static void 58 usage DC_DECLARG((f)) 59 FILE *f DC_DECLEND 60 { 61 fprintf(f, "\ 62 Usage: %s [OPTION] [file ...]\n\ 63 -e, --expression=EXPR evaluate expression\n\ 64 -f, --file=FILE evaluate contents of file\n\ 65 -h, --help display this help and exit\n\ 66 -V, --version output version information and exit\n\ 67 \n\ 68 Report bugs to bug-gnu-utils@prep.ai.mit.edu\n\ 69 Be sure to include the word ``dc'' somewhere in the ``Subject:'' field.\n\ 70 ", progname); 71 } 72 73 static void 74 show_version DC_DECLVOID() 75 { 76 printf("%s\n\n", DC_VERSION); 77 printf("Email bug reports to: bug-gnu-utils@prep.ai.mit.edu .\n"); 78 printf("Be sure to include the word ``dc'' \ 79 somewhere in the ``Subject:'' field.\n"); 80 } 81 82 /* returns a pointer to one past the last occurance of c in s, 83 * or s if c does not occur in s. 84 */ 85 static char * 86 r1bindex DC_DECLARG((s, c)) 87 char *s DC_DECLSEP 88 int c DC_DECLEND 89 { 90 char *p = strrchr(s, c); 91 92 if (!p) 93 return s; 94 return p + 1; 95 } 96 97 static void 98 try_file(const char *filename) 99 { 100 FILE *input; 101 102 if (strcmp(filename, "-") == 0) { 103 input = stdin; 104 } else if ( !(input=fopen(filename, "r")) ) { 105 fprintf(stderr, "Could not open file "); 106 perror(filename); 107 exit(EXIT_FAILURE); 108 } 109 if (dc_evalfile(input)) 110 exit(EXIT_FAILURE); 111 if (input != stdin) 112 fclose(input); 113 } 114 115 116 int 117 main DC_DECLARG((argc, argv)) 118 int argc DC_DECLSEP 119 char **argv DC_DECLEND 120 { 121 static struct option const long_opts[] = { 122 {"expression", required_argument, NULL, 'e'}, 123 {"file", required_argument, NULL, 'f'}, 124 {"help", no_argument, NULL, 'h'}, 125 {"version", no_argument, NULL, 'V'}, 126 {NULL, 0, NULL, 0} 127 }; 128 int did_eval = 0; 129 int c; 130 131 progname = r1bindex(*argv, '/'); 132 #ifdef HAVE_SETVBUF 133 /* attempt to simplify interaction with applications such as emacs */ 134 (void) setvbuf(stdout, NULL, _IOLBF, 0); 135 #endif 136 dc_math_init(); 137 dc_string_init(); 138 dc_register_init(); 139 dc_array_init(); 140 141 while ((c = getopt_long(argc, argv, "hVe:f:", long_opts, (int *)0)) != EOF) { 142 switch (c) { 143 case 'e': 144 { dc_data string = dc_makestring(optarg, strlen(optarg)); 145 if (dc_evalstr(string)) 146 return EXIT_SUCCESS; 147 dc_free_str(&string.v.string); 148 did_eval = 1; 149 } 150 break; 151 case 'f': 152 try_file(optarg); 153 did_eval = 1; 154 break; 155 case 'h': 156 usage(stdout); 157 return EXIT_SUCCESS; 158 case 'V': 159 show_version(); 160 return EXIT_SUCCESS; 161 default: 162 usage(stderr); 163 return EXIT_FAILURE; 164 } 165 } 166 167 for (; optind < argc; ++optind) { 168 try_file(argv[optind]); 169 did_eval = 1; 170 } 171 if (!did_eval) { 172 /* if no -e commands and no command files, then eval stdin */ 173 if (dc_evalfile(stdin)) 174 return EXIT_FAILURE; 175 } 176 return EXIT_SUCCESS; 177 } |