1/* 2 * misc. functions for the "dc" Desk Calculator language. 3 * 4 * Copyright (C) 1994, 1997, 1998, 2000 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 * 59 Temple Place, Suite 330 21 * Boston, MA 02111 USA 22 */ 23 24/* This module contains miscelaneous functions that have no 25 * special knowledge of any private data structures. 26 * They could all be moved to their own separate modules, but 27 * are agglomerated here for convenience. 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#include <ctype.h> 44#ifndef isgraph 45# ifndef HAVE_ISGRAPH 46# define isgraph isprint 47# endif 48#endif 49#include <getopt.h> 50#include "dc.h" 51#include "dc-proto.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 */ 59void 60dc_memfail DC_DECLVOID() 61{ 62 fprintf(stderr, "%s: out of memory\n", progname); 63 exit(EXIT_FAILURE); 64} 65 66/* malloc or die */ 67void * 68dc_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 */ 84void 85dc_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 */ 107void 108dc_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 */ 128const char * 129dc_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 */ 152void 153dc_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 */ 169dc_data 170dc_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} 180