1 /* 2 * misc. functions for 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 /* This module contains miscelaneous functions that have no 23 * special knowledge of any private data structures. 24 * They could all be moved to their own separate modules, but 25 * are agglomerated here for convenience. 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 <ctype.h> 42 #ifndef isgraph 43 # ifndef HAVE_ISGRAPH 44 # define isgraph isprint 45 # endif 46 #endif 47 #include <getopt.h> 48 #include "dc.h" 49 #include "dc-proto.h" 50 51 #include "version.h" 52 53 #ifndef EXIT_FAILURE /* C89 <stdlib.h> */ 54 # define EXIT_FAILURE 1 55 #endif 56 57 58 /* print an "out of memory" diagnostic and exit program */ 59 void 60 dc_memfail DC_DECLVOID() 61 { 62 fprintf(stderr, "%s: out of memory\n", progname); 63 exit(EXIT_FAILURE); 64 } 65 66 /* malloc or die */ 67 void * 68 dc_malloc DC_DECLARG((len)) 69 size_t len DC_DECLEND 70 { 71 void *result = malloc(len); 72 73 if (!result) 74 dc_memfail(); 75 return result; 76 } 77 78 79 /* print the id in a human-understandable form 80 * fp is the output stream to place the output on 81 * id is the name of the register (or command) to be printed 82 * suffix is a modifier (such as "stack") to be printed 83 */ 84 void 85 dc_show_id DC_DECLARG((fp, id, suffix)) 86 FILE *fp DC_DECLSEP 87 int id DC_DECLSEP 88 const char *suffix DC_DECLEND 89 { 90 if (isgraph(id)) 91 fprintf(fp, "'%c' (%#o)%s", id, id, suffix); 92 else 93 fprintf(fp, "%#o%s", id, suffix); 94 } 95 96 97 /* report that corrupt data has been detected; 98 * use the msg and regid (if nonnegative) to give information 99 * about where the garbage was found, 100 * 101 * will abort() so that a debugger might be used to help find 102 * the bug 103 */ 104 /* If this routine is called, then there is a bug in the code; 105 * i.e. it is _not_ a data or user error 106 */ 107 void 108 dc_garbage DC_DECLARG((msg, regid)) 109 const char *msg DC_DECLSEP 110 int regid DC_DECLEND 111 { 112 if (regid < 0) { 113 fprintf(stderr, "%s: garbage %s\n", progname, msg); 114 } else { 115 fprintf(stderr, "%s:%s register ", progname, msg); 116 dc_show_id(stderr, regid, " is garbage\n"); 117 } 118 abort(); 119 } 120 121 122 /* call system() with the passed string; 123 * if the string contains a newline, terminate the string 124 * there before calling system. 125 * Return a pointer to the first unused character in the string 126 * (i.e. past the '\n' if there was one, to the '\0' otherwise). 127 */ 128 const char * 129 dc_system DC_DECLARG((s)) 130 const char *s DC_DECLEND 131 { 132 const char *p; 133 char *tmpstr; 134 size_t len; 135 136 p = strchr(s, '\n'); 137 if (p) { 138 len = p - s; 139 tmpstr = dc_malloc(len + 1); 140 strncpy(tmpstr, s, len); 141 tmpstr[len] = '\0'; 142 system(tmpstr); 143 free(tmpstr); 144 return p + 1; 145 } 146 system(s); 147 return s + strlen(s); 148 } 149 150 151 /* print out the indicated value */ 152 void 153 dc_print DC_DECLARG((value, obase, newline_p, discard_p)) 154 dc_data value DC_DECLSEP 155 int obase DC_DECLSEP 156 dc_newline newline_p DC_DECLSEP 157 dc_discard discard_p DC_DECLEND 158 { 159 if (value.dc_type == DC_NUMBER) { 160 dc_out_num(value.v.number, obase, newline_p, discard_p); 161 } else if (value.dc_type == DC_STRING) { 162 dc_out_str(value.v.string, newline_p, discard_p); 163 } else { 164 dc_garbage("in data being printed", -1); 165 } 166 } 167 168 /* return a duplicate of the passed value, regardless of type */ 169 dc_data 170 dc_dup DC_DECLARG((value)) 171 dc_data value DC_DECLEND 172 { 173 if (value.dc_type!=DC_NUMBER && value.dc_type!=DC_STRING) 174 dc_garbage("in value being duplicated", -1); 175 if (value.dc_type == DC_NUMBER) 176 return dc_dup_num(value.v.number); 177 /*else*/ 178 return dc_dup_str(value.v.string); 179 } |