Merge from vendor branch OPENSSH:
[dragonfly.git] / contrib / bc / dc / misc.c
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 \f
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 \f
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 \f
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 \f
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 \f
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 }