[comp.sources.bugs] Problems with 'mush' on Pyramid

jimmy@pyrltd.UUCP (Jimmy Aitken) (09/25/87)

There are problems trying to use the recently posted 'mush' on a Pyramid
(or anything that doesn't handle varags like a VAX). Just after startup,
you get a segmentation violation. This happens in print.c to anything that
calls `_doprnt' with the address of the first item on the paramater stack.
Here is a version of print.c that uses the 'varargs' macros as described in the
manual to get round this problem - this should also work on other machines
although I have not had time not the facilities to check this out.

I'm posting the whole file again, as the context differences were about
200 bytes shorter. - Nor a shar file - just extract between the dashes.
Jimmy

----------------------------------------------------------------------
/* @(#)print.c	2.4	(c) copyright 10/15/86 (Dan Heller) */

#include <varargs.h>
#include "mush.h"

/*ARGSUSED*/
/*VARARGS1*/
void
error(fmt, arg1, arg2, arg3, arg4)
register char *fmt;
char *arg1, *arg2, *arg3, *arg4;
{
    print(fmt, arg1, arg2, arg3, arg4);
    print_more(": %s\n", sys_errlist[errno]);
}

#if defined(SUNTOOL) || defined(CURSES)
/*
 * print just like printf -- to a window, to curses, or to stdout.  Use vprintf
 * if available.  msgbuf is the buffer used to print into if necessary.
 * If you're running SUN3.2 or higher, the typecast (unsigned char *)msgbuf
 * (where indicated) otherwise, msgbuf is not typecast at all.
 * Also note same casting in wprint().
 */
/*VARARGS1*/
void
print(fmt, va_alist)
register char *fmt;
va_dcl
{
    static char msgbuf[BUFSIZ];
#ifndef VPRINTF
    FILE foo;
    va_list args;
#endif VPRINTF
#ifdef SUNTOOL
    static int x;
#endif SUNTOOL
    char *p; /* same type as struct file _ptr,_buf in stdio.h */

#ifdef CURSES
    if (iscurses) {
	if (isoff(glob_flags, CONT_PRNT))
	    move(LINES-1, 0), refresh();
	turnoff(glob_flags, CONT_PRNT);
    } else
#endif CURSES
	if (istool < 2) {
#ifdef VPRINTF
	    vprintf(fmt, &args), fflush(stdout);
#else
	    va_start(args);
	    _doprnt(fmt, args, stdout), fflush(stdout);
	    va_end(args);
#endif VPRINTF
	    return;
	}
#ifdef VPRINTF
    if (fmt)
	vsprintf(msgbuf, fmt, &args); /* NULL in fmt reprints last msg */
#else VPRINTF
    foo._cnt = BUFSIZ;
    foo._base = foo._ptr = msgbuf; /* may have to be cast(unsigned char *) */
    foo._flag = _IOWRT+_IOSTRG;
    if (fmt) {   /* passing NULL (not "") reprints last message */
	va_start(args);
	(void) _doprnt(fmt, args, &foo);
	va_end(args);
	*foo._ptr = '\0'; /* plant terminating null character */
    }
#endif VPIRNTF
    p = msgbuf;
    if (iscurses || istool)
	while (p = index(p, '\n'))
	    *p = ' ';
#ifdef CURSES
    if (iscurses) {
	addstr(msgbuf), clrtoeol(), refresh();
	return;
    }
#endif CURSES
#ifdef SUNTOOL
    if (isoff(glob_flags, CONT_PRNT))
	x = 5;
    turnoff(glob_flags, CONT_PRNT);
    pw_text(print_win, x,   l_height(LARGE), PIX_SRC, fonts[LARGE], msgbuf);
    pw_text(print_win, x+1, l_height(LARGE), PIX_SRC|PIX_DST,
		       fonts[LARGE], msgbuf);
    x += strlen(msgbuf) * l_width(LARGE);
    Clrtoeol(print_win, x, l_height(LARGE), LARGE);
#endif SUNTOOL
}
#endif SUNTOOL || CURSES

#ifdef SUNTOOL
/*VARARGS*/
void
wprint(fmt, va_alist)
char *fmt;
va_dcl
{
#ifndef VPRINTF
    FILE foo;
    va_list args;
#endif VPRINTF
    char msgbuf[BUFSIZ]; /* we're not getting huge strings */

    if (istool < 2) {
#ifdef VPRINTF
	vprintf(fmt, &args);
#else VPRINTF
	va_start(args);
	_doprnt(fmt, args, stdout);
	va_end(args);
#endif VPRINTF
	fflush(stdout);
	return;
    }
    if (!fmt)
	return;
#ifdef VPRINTF
    vsprintf(msgbuf, fmt, &args); /* NULL in fmt reprints last msg */
#else VPRINTF
    foo._cnt = BUFSIZ;
    foo._base = foo._ptr = msgbuf; /* may have to typecast (unsigned char *) */
    foo._flag = _IOWRT+_IOSTRG;A
    va_start(args);
    _doprnt(fmt, args, &foo); /* format like printf into msgbuf via foo */
    va_end(args);
    *foo._ptr = '\0'; /* plant terminating null character */
#endif VPRINTF
    Addstr(msgbuf);  /* addstr() will scroll if necessary */
}

/*
 * scroll the msg_win "lines"
 * if `lines' is negative (backwards scroll) msg_pix can't be NULL
 */
void
scroll_win(lines)
register int lines;
{
    register int y = lines * l_height(curfont);
    if (txt.y + y < msg_rect.r_height)
	y = 0;  /* temporary */
    txt.x = 5;

    if (msg_pix) {
	if (txt.y + y >= msg_pix->pr_size.y - 5)
	    y = msg_pix->pr_size.y - txt.y;
	still_more += y; /* let scrolling know where we are */
	txt.y += y;
	pw_rop(msg_win, 0, 5,
	       msg_rect.r_width, crt * l_height(curfont),
	       PIX_SRC, msg_pix, 0, txt.y - msg_rect.r_height + 3);
	tool_more(NULL);
	return;
    }
    /* y must be positive (forward scrolling) so we're scrolling typed
     * text or something like that (~p, ~?, etc...)
     */
    pw_copy(msg_win, 0, 0,
	msg_rect.r_width, msg_rect.r_height - y,
	PIX_SRC, msg_win, 0, y);
    pw_writebackground(msg_win, 0, msg_rect.r_height - y,
	msg_rect.r_width, y, PIX_CLR);
    txt.y -= y;
}
#endif SUNTOOL

#ifdef CURSES
clr_bot_line()
{
    print("");
}
#endif CURSES
----------------------------------------------------------------------
-- 
      -m-------  Jimmy Aitken                Phone : +44 252 373035
    ---mmm-----  Pyramid Technology Ltd      PSS   : Not Yet
  -----mmmmm---  Concept 2000, Farnboro' Rd. Telex : 859056
-------mmmmmmm-  Farnboro', Hants GU14 7NA   ...!mcvax!ukc!pyrltd!jimmy

guy@gorodish.UUCP (09/27/87)

> There are problems trying to use the recently posted 'mush' on a Pyramid
> (or anything that doesn't handle varags like a VAX).

Such as a Sun-4.

>  * if available.  msgbuf is the buffer used to print into if necessary.
>  * If you're running SUN3.2 or higher, the typecast (unsigned char *)msgbuf
>  * (where indicated) otherwise, msgbuf is not typecast at all.
>  * Also note same casting in wprint().

...

> #ifdef VPRINTF
>     if (fmt)
> 	vsprintf(msgbuf, fmt, &args); /* NULL in fmt reprints last msg */
> #else VPRINTF
>     foo._cnt = BUFSIZ;
>     foo._base = foo._ptr = msgbuf; /* may have to be cast(unsigned char *) */
>     foo._flag = _IOWRT+_IOSTRG;
>     if (fmt) {   /* passing NULL (not "") reprints last message */
> 	va_start(args);
> 	(void) _doprnt(fmt, args, &foo);
> 	va_end(args);
> 	*foo._ptr = '\0'; /* plant terminating null character */
>     }
> #endif VPIRNTF

1) On Suns running 3.2 or later, you actually don't *need* the cast - it just
keeps the compiler from issuing a warning.  The same warning will be issued on
other systems, such as most S5R2 or later systems, where the buffer is an array
of "unsigned char".

However, the vanilla S5R[2,3] standard I/O doesn't have _IOSTRG, so this code
won't work there.  Then again,

2) On Suns running 3.2 or later, or machines with the S5R2 or later standard
I/O, none of this is relevant anyway - they have "vprintf", "vfprintf", and
"vsprintf".  Just define VPRINTF when compiling for those systems.
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com