home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / bc-1.03-base.tgz / bc-1.03-base.tar / fsf / bc / dc-misc.c < prev    next >
C/C++ Source or Header  |  1994-08-08  |  6KB  |  238 lines

  1. /* 
  2.  * implement the "dc" Desk Calculator language.
  3.  *
  4.  * Copyright (C) 1994 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 miscelaneous functions that have no
  26.  * special knowledge of any private data structures.
  27.  * They could all be moved to their own separate modules, but
  28.  * are agglomerated here for convenience.
  29.  */
  30.  
  31. #include "config.h"
  32.  
  33. #include <stdio.h>
  34. #ifdef HAVE_STDLIB_H
  35. # include <stdlib.h>
  36. #endif
  37. #ifdef HAVE_STRING_H
  38. # include <string.h>
  39. #else
  40. # ifdef HAVE_STRINGS_H
  41. #  include <strings.h>
  42. # endif
  43. #endif
  44. #include <ctype.h>
  45. #ifndef isgraph
  46. # ifndef HAVE_ISGRAPH
  47. #  define isgraph isprint
  48. # endif
  49. #endif
  50. #include "dc.h"
  51. #include "dc-proto.h"
  52.  
  53. #include "dc-version.h"
  54.  
  55. #ifndef EXIT_SUCCESS    /* C89 <stdlib.h> */
  56. # define EXIT_SUCCESS    0
  57. #endif
  58. #ifndef EXIT_FAILURE    /* C89 <stdlib.h> */
  59. # define EXIT_FAILURE    1
  60. #endif
  61.  
  62. const char *progname;    /* basename of program invocation */
  63.  
  64. /* your generic usage function */
  65. static void
  66. usage DC_DECLARG((f))
  67.     FILE *f DC_DECLEND
  68. {
  69.     fprintf(f, "Usage: %s [OPTION]\n", progname);
  70.     fprintf(f, "  --help      display this help and exit\n");
  71.     fprintf(f, "  --version   output version information and exit\n");
  72. }
  73.  
  74. /* returns a pointer to one past the last occurance of c in s,
  75.  * or s if c does not occur in s.
  76.  */
  77. static char *
  78. r1bindex DC_DECLARG((s, c))
  79.     char *s DC_DECLSEP
  80.     int  c DC_DECLEND
  81. {
  82.     char *p = strrchr(s, c);
  83.  
  84.     if (!p)
  85.         return s;
  86.     return p + 1;
  87. }
  88.  
  89.  
  90. int
  91. main DC_DECLARG((argc, argv))
  92.     int  argc DC_DECLSEP
  93.     char **argv DC_DECLEND
  94. {
  95.     progname = r1bindex(*argv, '/');
  96.     if (argc>1 && strcmp(argv[1], "--version")==0){
  97.         printf("%s\n", Version);
  98.         return EXIT_SUCCESS;
  99.     }else if (argc>1 && strcmp(argv[1], "--help")==0){
  100.         usage(stdout);
  101.         return EXIT_SUCCESS;
  102.     }else if (argc==2 && strcmp(argv[1], "--")==0){
  103.         /*just ignore it*/
  104.     }else if (argc != 1){
  105.         usage(stderr);
  106.         return EXIT_FAILURE;
  107.     }
  108.  
  109.     dc_math_init();
  110.     dc_string_init();
  111.     dc_register_init();
  112.     dc_array_init();
  113.     dc_evalfile(stdin);
  114.     return EXIT_SUCCESS;
  115. }
  116.  
  117.  
  118. /* print an "out of memory" diagnostic and exit program */
  119. void
  120. dc_memfail DC_DECLVOID()
  121. {
  122.     fprintf(stderr, "%s: out of memory\n", progname);
  123.     exit(EXIT_FAILURE);
  124. }
  125.  
  126. /* malloc or die */
  127. void *
  128. dc_malloc DC_DECLARG((len))
  129.     size_t len DC_DECLEND
  130. {
  131.     void *result = malloc(len);
  132.  
  133.     if (!result)
  134.         dc_memfail();
  135.     return result;
  136. }
  137.  
  138.  
  139. /* print the id in a human-understandable form
  140.  *  fp is the output stream to place the output on
  141.  *  id is the name of the register (or command) to be printed
  142.  *  suffix is a modifier (such as "stack") to be printed
  143.  */
  144. void
  145. dc_show_id DC_DECLARG((fp, id, suffix))
  146.     FILE *fp DC_DECLSEP
  147.     int id DC_DECLSEP
  148.     const char *suffix DC_DECLEND
  149. {
  150.     if (isgraph(id))
  151.         fprintf(fp, "'%c' (%#o)%s", id, id, suffix);
  152.     else
  153.         fprintf(fp, "%#o%s", id, suffix);
  154. }
  155.  
  156.  
  157. /* report that corrupt data has been detected;
  158.  * use the msg and regid (if nonnegative) to give information
  159.  * about where the garbage was found,
  160.  *
  161.  * will abort() so that a debugger might be used to help find
  162.  * the bug
  163.  */
  164. /* If this routine is called, then there is a bug in the code;
  165.  * i.e. it is _not_ a data or user error
  166.  */
  167. void
  168. dc_garbage DC_DECLARG((msg, regid))
  169.     const char *msg DC_DECLSEP
  170.     int regid DC_DECLEND
  171. {
  172.     if (regid < 0){
  173.         fprintf(stderr, "%s: garbage %s\n", progname, msg);
  174.     }else{
  175.         fprintf(stderr, "%s:%s register ", progname, msg);
  176.         dc_show_id(stderr, regid, " is garbage\n");
  177.     }
  178.     abort();
  179. }
  180.  
  181.  
  182. /* call system() with the passed string;
  183.  * if the string contains a newline, terminate the string
  184.  * there before calling system.
  185.  * Return a pointer to the first unused character in the string
  186.  * (i.e. past the '\n' if there was one, to the '\0' otherwise).
  187.  */
  188. const char *
  189. dc_system DC_DECLARG((s))
  190.     const char *s DC_DECLEND
  191. {
  192.     const char *p;
  193.     char *tmpstr;
  194.     size_t len;
  195.  
  196.     p = strchr(s, '\n');
  197.     if (p){
  198.         len = p - s;
  199.         tmpstr = dc_malloc(len + 1);
  200.         strncpy(tmpstr, s, len);
  201.         tmpstr[len] = '\0';
  202.         system(tmpstr);
  203.         free(tmpstr);
  204.         return p + 1;
  205.     }
  206.     system(s);
  207.     return s + strlen(s);
  208. }
  209.  
  210.  
  211. /* print out the indicated value */
  212. void
  213. dc_print DC_DECLARG((value, obase))
  214.     dc_data value DC_DECLSEP
  215.     int obase DC_DECLEND
  216. {
  217.     if (value.dc_type == DC_NUMBER){
  218.         dc_out_num(value.v.number, obase, DC_TRUE, DC_FALSE);
  219.     }else if (value.dc_type == DC_STRING){
  220.         dc_out_str(value.v.string, DC_TRUE, DC_FALSE);
  221.     }else{
  222.         dc_garbage("in data being printed", -1);
  223.     }
  224. }
  225.  
  226. /* return a duplicate of the passed value, regardless of type */
  227. dc_data
  228. dc_dup DC_DECLARG((value))
  229.     dc_data value DC_DECLEND
  230. {
  231.     if (value.dc_type!=DC_NUMBER && value.dc_type!=DC_STRING)
  232.         dc_garbage("in value being duplicated", -1);
  233.     if (value.dc_type == DC_NUMBER)
  234.         return dc_dup_num(value.v.number);
  235.     /*else*/
  236.     return dc_dup_str(value.v.string);
  237. }
  238.