Blame dc/misc.c

Packit 70b277
/* 
Packit 70b277
 * misc. functions for the "dc" Desk Calculator language.
Packit 70b277
 *
Packit 70b277
 * Copyright (C) 1994, 1997, 1998, 2000, 2006, 2008, 2013
Packit 70b277
 * Free Software Foundation, Inc.
Packit 70b277
 *
Packit 70b277
 * This program is free software; you can redistribute it and/or modify
Packit 70b277
 * it under the terms of the GNU General Public License as published by
Packit 70b277
 * the Free Software Foundation; either version 3, or (at your option)
Packit 70b277
 * any later version.
Packit 70b277
 *
Packit 70b277
 * This program is distributed in the hope that it will be useful,
Packit 70b277
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 70b277
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 70b277
 * GNU General Public License for more details.
Packit 70b277
 *
Packit 70b277
 * You should have received a copy of the GNU General Public License
Packit 70b277
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit 70b277
 *
Packit 70b277
 */
Packit 70b277
Packit 70b277
/* This module contains miscellaneous functions that have no
Packit 70b277
 * special knowledge of any private data structures.
Packit 70b277
 * They could each be moved to their own separate modules,
Packit 70b277
 * but are aggregated here as a matter of convenience.
Packit 70b277
 */
Packit 70b277
Packit 70b277
#include "config.h"
Packit 70b277
Packit 70b277
#include <stdio.h>
Packit 70b277
#ifdef HAVE_STDLIB_H
Packit 70b277
# include <stdlib.h>
Packit 70b277
#endif
Packit 70b277
#ifdef HAVE_STRING_H
Packit 70b277
# include <string.h>
Packit 70b277
#else
Packit 70b277
# ifdef HAVE_STRINGS_H
Packit 70b277
#  include <strings.h>
Packit 70b277
# endif
Packit 70b277
#endif
Packit 70b277
#include <ctype.h>
Packit 70b277
#ifndef isgraph
Packit 70b277
# ifndef HAVE_ISGRAPH
Packit 70b277
#  define isgraph isprint
Packit 70b277
# endif
Packit 70b277
#endif
Packit 70b277
#include <getopt.h>
Packit 70b277
#include "dc.h"
Packit 70b277
#include "dc-proto.h"
Packit 70b277
Packit 70b277
#ifndef EXIT_FAILURE	/* C89 <stdlib.h> */
Packit 70b277
# define EXIT_FAILURE	1
Packit 70b277
#endif
Packit 70b277
Packit 70b277

Packit 70b277
/* print an "out of memory" diagnostic and exit program */
Packit 70b277
void
Packit 70b277
dc_memfail DC_DECLVOID()
Packit 70b277
{
Packit 70b277
	fprintf(stderr, "%s: out of memory\n", progname);
Packit 70b277
	exit(EXIT_FAILURE);
Packit 70b277
}
Packit 70b277
Packit 70b277
/* malloc or die */
Packit 70b277
void *
Packit 70b277
dc_malloc DC_DECLARG((len))
Packit 70b277
	size_t len DC_DECLEND
Packit 70b277
{
Packit 70b277
	void *result = malloc(len);
Packit 70b277
Packit 70b277
	if (result == NULL)
Packit 70b277
		dc_memfail();
Packit 70b277
	return result;
Packit 70b277
}
Packit 70b277
Packit 70b277

Packit 70b277
/* print the id in a human-understandable form
Packit 70b277
 *  fp is the output stream to place the output on
Packit 70b277
 *  id is the name of the register (or command) to be printed
Packit 70b277
 *  suffix is a modifier (such as "stack") to be printed
Packit 70b277
 */
Packit 70b277
void
Packit 70b277
dc_show_id DC_DECLARG((fp, id, suffix))
Packit 70b277
	FILE *fp DC_DECLSEP
Packit 70b277
	int id DC_DECLSEP
Packit 70b277
	const char *suffix DC_DECLEND
Packit 70b277
{
Packit 70b277
	if (isgraph(id))
Packit 70b277
		fprintf(fp, "'%c' (%#o)%s", (unsigned int) id, id, suffix);
Packit 70b277
	else
Packit 70b277
		fprintf(fp, "%#o%s", (unsigned int) id, suffix);
Packit 70b277
}
Packit 70b277
Packit 70b277

Packit 70b277
/* report that corrupt data has been detected;
Packit 70b277
 * use the msg and regid (if nonnegative) to give information
Packit 70b277
 * about where the garbage was found,
Packit 70b277
 *
Packit 70b277
 * will abort() so that a debugger might be used to help find
Packit 70b277
 * the bug
Packit 70b277
 */
Packit 70b277
/* If this routine is called, then there is a bug in the code;
Packit 70b277
 * i.e. it is _not_ a data or user error
Packit 70b277
 */
Packit 70b277
void
Packit 70b277
dc_garbage DC_DECLARG((msg, regid))
Packit 70b277
	const char *msg DC_DECLSEP
Packit 70b277
	int regid DC_DECLEND
Packit 70b277
{
Packit 70b277
	if (regid < 0) {
Packit 70b277
		fprintf(stderr, "%s: garbage %s\n", progname, msg);
Packit 70b277
	} else {
Packit 70b277
		fprintf(stderr, "%s:%s register ", progname, msg);
Packit 70b277
		dc_show_id(stderr, regid, " is garbage\n");
Packit 70b277
	}
Packit 70b277
	abort();
Packit 70b277
}
Packit 70b277
Packit 70b277

Packit 70b277
/* call system() with the passed string;
Packit 70b277
 * if the string contains a newline, terminate the string
Packit 70b277
 * there before calling system.
Packit 70b277
 * Return a pointer to the first unused character in the string
Packit 70b277
 * (i.e. past the '\n' if there was one, to the '\0' otherwise).
Packit 70b277
 */
Packit 70b277
const char *
Packit 70b277
dc_system DC_DECLARG((s))
Packit 70b277
	const char *s DC_DECLEND
Packit 70b277
{
Packit 70b277
	const char *p;
Packit 70b277
	char *tmpstr;
Packit 70b277
	size_t len;
Packit 70b277
Packit 70b277
	p = strchr(s, '\n');
Packit 70b277
	if (p != NULL) {
Packit 70b277
		len = (size_t) (p - s);
Packit 70b277
		tmpstr = dc_malloc(len + 1);
Packit 70b277
		strncpy(tmpstr, s, len);
Packit 70b277
		tmpstr[len] = '\0';
Packit 70b277
		system(tmpstr);
Packit 70b277
		free(tmpstr);
Packit 70b277
		return p + 1;
Packit 70b277
	}
Packit 70b277
	system(s);
Packit 70b277
	return s + strlen(s);
Packit 70b277
}
Packit 70b277
Packit 70b277

Packit 70b277
/* print out the indicated value */
Packit 70b277
void
Packit 70b277
dc_print DC_DECLARG((value, obase, newline_p, discard_p))
Packit 70b277
	dc_data value DC_DECLSEP
Packit 70b277
	int obase DC_DECLSEP
Packit 70b277
	dc_newline newline_p DC_DECLSEP
Packit 70b277
	dc_discard discard_p DC_DECLEND
Packit 70b277
{
Packit 70b277
	if (value.dc_type == DC_NUMBER) {
Packit 70b277
		dc_out_num(value.v.number, obase, discard_p);
Packit 70b277
	} else if (value.dc_type == DC_STRING) {
Packit 70b277
		dc_out_str(value.v.string, discard_p);
Packit 70b277
	} else {
Packit 70b277
		dc_garbage("in data being printed", -1);
Packit 70b277
	}
Packit 70b277
	if (newline_p == DC_WITHNL)
Packit 70b277
		putchar ('\n');
Packit 70b277
	fflush(stdout);
Packit 70b277
}
Packit 70b277
Packit 70b277
/* return a duplicate of the passed value, regardless of type */
Packit 70b277
dc_data
Packit 70b277
dc_dup DC_DECLARG((value))
Packit 70b277
	dc_data value DC_DECLEND
Packit 70b277
{
Packit 70b277
	if (value.dc_type!=DC_NUMBER && value.dc_type!=DC_STRING)
Packit 70b277
		dc_garbage("in value being duplicated", -1);
Packit 70b277
	if (value.dc_type == DC_NUMBER)
Packit 70b277
		return dc_dup_num(value.v.number);
Packit 70b277
	/*else*/
Packit 70b277
	return dc_dup_str(value.v.string);
Packit 70b277
}
Packit 70b277
Packit 70b277

Packit 70b277
/*
Packit 70b277
 * Local Variables:
Packit 70b277
 * mode: C
Packit 70b277
 * tab-width: 4
Packit 70b277
 * End:
Packit 70b277
 * vi: set ts=4 :
Packit 70b277
 */