"Fossies" - the Fresh Open Source Software Archive

Member "bc-1.06.95/dc/dc.c" (11 Jun 2006, 7293 Bytes) of package /linux/misc/old/bc-1.06.95.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "dc.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.06.95_vs_1.07.

    1 /*
    2  * implement the "dc" Desk Calculator language.
    3  *
    4  * Copyright (C) 1994, 1997, 1998, 2000, 2003, 2006 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:
   19  *   The Free Software Foundation, Inc.
   20  *   51 Franklin Street, Fifth Floor
   21  *   Boston, MA 02110-1301  USA
   22  */
   23 
   24 /* Written with strong hiding of implementation details
   25  * in their own specialized modules.
   26  */
   27 /* This module contains the argument processing/main functions.
   28  */
   29 
   30 #include "config.h"
   31 
   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 #ifdef HAVE_FSTAT
   44 # include <sys/types.h>
   45 # include <sys/stat.h>
   46 #endif
   47 #include <getopt.h>
   48 #include "dc.h"
   49 #include "dc-proto.h"
   50 
   51 #ifndef EXIT_SUCCESS    /* C89 <stdlib.h> */
   52 # define EXIT_SUCCESS   0
   53 #endif
   54 #ifndef EXIT_FAILURE    /* C89 <stdlib.h> */
   55 # define EXIT_FAILURE   1
   56 #endif
   57 
   58 const char *progname;   /* basename of program invocation */
   59 
   60 static void
   61 bug_report_info DC_DECLVOID()
   62 {
   63     printf("Email bug reports to:  bug-dc@gnu.org .\n");
   64 }
   65 
   66 static void
   67 show_version DC_DECLVOID()
   68 {
   69     printf("dc (GNU %s %s) %s\n", PACKAGE, VERSION, DC_VERSION);
   70     printf("\n%s\n\
   71 This is free software; see the source for copying conditions.  There is NO\n\
   72 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n\
   73 to the extent permitted by law.\n", DC_COPYRIGHT);
   74 }
   75 
   76 /* your generic usage function */
   77 static void
   78 usage DC_DECLARG((f))
   79     FILE *f DC_DECLEND
   80 {
   81     fprintf(f, "\
   82 Usage: %s [OPTION] [file ...]\n\
   83   -e, --expression=EXPR    evaluate expression\n\
   84   -f, --file=FILE          evaluate contents of file\n\
   85   -h, --help               display this help and exit\n\
   86   -V, --version            output version information and exit\n\
   87 \n\
   88 ", progname);
   89     bug_report_info();
   90 }
   91 
   92 /* returns a pointer to one past the last occurance of c in s,
   93  * or s if c does not occur in s.
   94  */
   95 static char *
   96 r1bindex DC_DECLARG((s, c))
   97     char *s DC_DECLSEP
   98     int  c DC_DECLEND
   99 {
  100     char *p = strrchr(s, c);
  101 
  102     if (p == NULL)
  103         return s;
  104     return p + 1;
  105 }
  106 
  107 static void
  108 try_file(const char *filename)
  109 {
  110     FILE *input;
  111 
  112     if (strcmp(filename, "-") == 0) {
  113         input = stdin;
  114     } else if ( (input=fopen(filename, "r")) == NULL ) {
  115         fprintf(stderr, "%s: Could not open file %s\n", progname, filename);
  116         return;
  117     }
  118     {
  119         /* Several complaints have been filed about dc's silence
  120          * when a "cd" typo is made.  I really wanted to avoid
  121          * this mess, but I guess it really should be added...
  122          */
  123 #ifndef HAVE_FSTAT
  124         /* non-POSIXish system; this code _might_ notice a directory */
  125         int c = getc(input);
  126         if (c == EOF && ferror(input)) {
  127             perror(filename);
  128             goto close;
  129         }
  130         ungetc(c, input);
  131 
  132 #else /* HAVE_FSTAT */
  133   /* If HAVE_FSTAT and no S_IS*() macros, it must be a pre-POSIX
  134    * Unix-ish system?
  135    */
  136 # ifndef S_ISREG
  137 #  ifdef S_IFREG
  138 #    define S_ISREG(m)  (((m)&S_IFMT)==S_IFREG)
  139 #   else
  140 #    define S_ISREG(m)  0
  141 #  endif
  142 # endif
  143 # ifndef S_ISCHR
  144 #  ifdef S_IFCHR
  145 #   define S_ISCHR(m)   (((m)&S_IFMT)==S_IFCHR)
  146 #  endif
  147 # endif
  148 # ifndef S_ISFIFO
  149 #  ifdef S_IFIFO
  150 #   define S_ISFIFO(m)  (((m)&S_IFMT)==S_IFIFO)
  151 #  endif
  152 # endif
  153 # ifndef S_ISSOCK
  154 #  ifdef S_IFSOCK
  155 #   define S_ISSOCK(m)  (((m)&S_IFMT)==S_IFSOCK)
  156 #  endif
  157 # endif
  158 # ifndef S_ISDIR
  159 #  ifdef S_IFDIR
  160 #   define S_ISDIR(m)   (((m)&S_IFMT)==S_IFDIR)
  161 #  endif
  162 # endif
  163 # ifndef S_ISBLK
  164 #  ifdef S_IFBLK
  165 #   define S_ISBLK(m)   (((m)&S_IFMT)==S_IFBLK)
  166 #  endif
  167 # endif
  168         struct stat s;
  169         if (fstat(fileno(input), &s) == -1) {
  170             /* "can't happen" */
  171             fprintf(stderr, "%s: Could not fstat file ", progname);
  172             perror(filename);
  173             goto close;
  174         }
  175 
  176 #ifdef S_ISDIR
  177         if (S_ISDIR(s.st_mode)) {
  178             fprintf(stderr,
  179                 "%s: Will not attempt to process directory %s\n",
  180                 progname, filename);
  181             goto close;
  182         } else
  183 #endif
  184 #ifdef S_ISBLK
  185         if (S_ISBLK(s.st_mode)) {
  186             fprintf(stderr,
  187                 "%s: Will not attempt to process block-special file %s\n",
  188                 progname, filename);
  189             goto close;
  190         } else
  191 #endif
  192         if (!S_ISREG(s.st_mode)
  193 # ifdef S_ISCHR
  194             /* typically will be /dev/null or some sort of tty */
  195             && !S_ISCHR(s.st_mode)
  196 # endif
  197 # ifdef S_ISFIFO
  198             && !S_ISFIFO(s.st_mode)
  199 # endif
  200 # ifdef S_ISSOCK
  201             && !S_ISSOCK(s.st_mode)
  202 # endif
  203                 ) {
  204             fprintf(stderr,
  205                 "%s: Will not attempt to process file of unusual type: %s\n",
  206                 progname, filename);
  207             goto close;
  208         }
  209 #endif /* HAVE_FSTAT */
  210     }
  211     if (dc_evalfile(input) != DC_SUCCESS)
  212         exit(EXIT_FAILURE);
  213 close:
  214     if (input != stdin)
  215         fclose(input);
  216 }
  217 
  218 
  219 
  220 /* Check to see if there were any output errors; if so, then give
  221  * an error message (if stderr is not known to be unhappy), and
  222  * ensure that the program exits with an error indication.
  223  */
  224 static int
  225 flush_okay DC_DECLVOID()
  226 {
  227     const char *errmsg = NULL;
  228     int r = EXIT_SUCCESS;
  229 
  230     if (ferror(stdout))
  231         errmsg = "error writing to stdout";
  232     else if (fflush(stdout))
  233         errmsg = "error flushing stdout";
  234     else if (fclose(stdout))
  235         errmsg = "error closing stdout";
  236 
  237     if (errmsg) {
  238         fprintf(stderr, "%s: ", progname);
  239         perror(errmsg);
  240         r = EXIT_FAILURE;
  241     }
  242 
  243     if (ferror(stderr) || fclose(stderr))
  244         r = EXIT_FAILURE;
  245     return r;
  246 }
  247 
  248 
  249 int
  250 main DC_DECLARG((argc, argv))
  251     int  argc DC_DECLSEP
  252     char **argv DC_DECLEND
  253 {
  254     static struct option const long_opts[] = {
  255         {"expression", required_argument, NULL, 'e'},
  256         {"file", required_argument, NULL, 'f'},
  257         {"help", no_argument, NULL, 'h'},
  258         {"version", no_argument, NULL, 'V'},
  259         {NULL, 0, NULL, 0}
  260     };
  261     int did_eval = 0;
  262     int c;
  263 
  264     progname = r1bindex(*argv, '/');
  265 #ifdef HAVE_SETVBUF
  266     /* attempt to simplify interaction with applications such as emacs */
  267     (void) setvbuf(stdout, NULL, _IOLBF, 0);
  268 #endif
  269     dc_math_init();
  270     dc_string_init();
  271     dc_register_init();
  272     dc_array_init();
  273 
  274     while ((c = getopt_long(argc, argv, "hVe:f:", long_opts, (int *)0)) != EOF) {
  275         switch (c) {
  276         case 'e':
  277             {   dc_data string = dc_makestring(optarg, strlen(optarg));
  278                 if (dc_evalstr(&string) != DC_SUCCESS)
  279                     return flush_okay();
  280                 dc_free_str(&string.v.string);
  281                 did_eval = 1;
  282             }
  283             break;
  284         case 'f':
  285             try_file(optarg);
  286             did_eval = 1;
  287             break;
  288         case 'h':
  289             usage(stdout);
  290             return flush_okay();
  291         case 'V':
  292             show_version();
  293             return flush_okay();
  294         default:
  295             usage(stderr);
  296             return EXIT_FAILURE;
  297         }
  298     }
  299 
  300     for (; optind < argc; ++optind) {
  301         try_file(argv[optind]);
  302         did_eval = 1;
  303     }
  304     if (did_eval == 0) {
  305         /* if no -e commands and no command files, then eval stdin */
  306         if (dc_evalfile(stdin) != DC_SUCCESS)
  307             return EXIT_FAILURE;
  308     }
  309     return flush_okay();
  310 }
  311 
  312 
  313 /*
  314  * Local Variables:
  315  * mode: C
  316  * tab-width: 4
  317  * End:
  318  * vi: set ts=4 :
  319  */