Exemplo n.º 1
0
/* processChar():
 * Used by the main polling loop to deal with incoming characters
 * on the console.
 */
void
processChar(int c)
{
	static char cmd[64];
	static int cmdidx = 0;

	if (c == '\b') {
		if (cmdidx > 0) {
			cmdidx--;
			mon_printf("\b \b");
		}
	}
	else if ((c == '\n') || (c == '\r')) {
		if (cmdidx != 0) {
			cmd[cmdidx] = 0;
			mon_printf("\r\n");
			mon_docommand(cmd,0);
			cmdidx = 0;
		}
		mon_printf("\r\nPROMPT:");
	}
	else {
		if (cmdidx < (sizeof(cmd)-1)) {
			cmd[cmdidx++] = (char)c;
			mon_putchar(c);
		}
		else {
			mon_printf("\ncmd buffer overflow\n");
			cmdidx = 0;
		}
	}
}
Exemplo n.º 2
0
static void parseDL(void)
{
    UWORD tdlist;
    int done = FALSE;
    int screen_ypos;
    UWORD screen_data = 0;

    screen_line_count = 0;
    screen_ypos = 0;
    tdlist = ANTIC_dlist;
    while (!done) {
        UBYTE IR;
        UWORD addr;

        IR = get_dlist_byte(&tdlist);

        switch (IR & 0x0f) {
        case 0x00: // Blank lines
            screen_ypos += ((IR >> 4) & 0x07) + 1;
            break;
        case 0x01: // Jump instructions
            addr = get_dlist_byte(&tdlist);
            addr |= get_dlist_byte(&tdlist) << 8;
            if (IR & 0x40) {
                done = TRUE;
            }
            else {
                tdlist = addr;
            }
            break;
        default:
            if (IR & 0x40) {  // Load data pointer
                addr = get_dlist_byte(&tdlist);
                addr |= get_dlist_byte(&tdlist) << 8;
                screen_data = addr;
            }

#if 0 // Note, horizontal and vertical scrolling is not handled by copy at the moment.				
            if (IR & 0x20)
                mon_printf("VSCROL ");

            if (IR & 0x10)
                mon_printf("HSCROL ");
#endif
            screen_lines[screen_line_count].start_y = screen_ypos;
            screen_lines[screen_line_count].end_y = screen_ypos + mode_scan_lines[IR & 0x0f] - 1;
            screen_lines[screen_line_count].type = IR & 0x0f;
            screen_lines[screen_line_count].data_ptr = screen_data;

            screen_ypos += mode_scan_lines[IR & 0x0f];
            screen_data += mode_memory_bytes[IR & 0x0f];
            screen_line_count++;
            if (screen_line_count == MAX_SCREEN_LINES)
                done = TRUE;
        }
    }
}
Exemplo n.º 3
0
int
cmd_CMD2(int argc, char *argv[])
{
	int i;

	mon_printf("CMD2:\n");
	for(i=0;i<argc;i++)
		mon_printf("arg[%d]: <%s>\n",i,argv[i]);

	return(CMD_SUCCESS);
}
Exemplo n.º 4
0
/* ls():
 *	Just list current set of files in TFS...
 */
void
ls(void)
{
	TFILE	*tfp;

	tfp = (TFILE *)0;
	while((tfp = mon_tfsnext(tfp)))
		mon_printf("%s\n",TFS_NAME(tfp));

	mon_printf("There are currently %d files in TFS\n",
		(int)mon_tfsctrl(TFS_FCOUNT,0,0));
}
Exemplo n.º 5
0
/*
 * Handler for monitor vector cmd -
 * For now we just implement the old "g0" and "g4"
 * commands and a printf hack.
 * [lifted from freed cmu mach3 sun3 port]
 */
static void
v_handler(int addr, char *str)
{

	switch (*str) {
	case '\0':
		/*
		 * No (non-hex) letter was specified on
		 * command line, use only the number given
		 */
		switch (addr) {
		case 0:			/* old g0 */
		case 0xd:		/* 'd'ump short hand */
			_mode_kernel();
			panic("zero");
			/*NOTREACHED*/

		case 4:			/* old g4 */
			goto do_trace;

		default:
			goto err;
		}
		break;

	case 'p':			/* 'p'rint string command */
	case 'P':
		mon_printf("%s\n", (char *)addr);
		break;

	case '%':			/* p'%'int anything a la printf */
		mon_printf(str, addr);
		mon_printf("\n");
		break;

	do_trace:
	case 't':			/* 't'race kernel stack */
	case 'T':
		tracedump(addr);
		break;

	case 'u':			/* d'u'mp hack ('d' look like hex) */
	case 'U':
		goto err;
		break;

	default:
	err:
		mon_printf("Don't understand 0x%x '%s'\n", addr, str);
	}
}
Exemplo n.º 6
0
/*
 * Set the PROM vector handler (for g0, g4, etc.)
 * and set boothowto from the PROM arg strings.
 *
 * Note, args are always:
 * argv[0] = boot_device	(i.e. "sd(0,0,0)")
 * argv[1] = options	(i.e. "-ds" or NULL)
 * argv[2] = NULL
 */
void
sunmon_init(void)
{
	struct sunromvec *rvec;
	struct bootparam *bp;
	char **argp;
	char *p;

	rvec = romVectorPtr;
	bp = *rvec->bootParam;

	/* Save the PROM monitor Vector Base Register (VBR). */
	sunmon_vbr = getvbr();

	/* Arrange for "trap #14" to cause a PROM abort. */
	sunmon_vbr[32+14] = romVectorPtr->abortEntry;

	/* Save and replace the "v command" handler. */
	sunmon_vcmd = *rvec->vector_cmd;
	if (rvec->romvecVersion >= 2)
		*rvec->vector_cmd = v_handler;

	/* Set boothowto flags from PROM args. */
	argp = bp->argPtr;

	/* Skip argp[0] (the device string) */
	argp++;

	/* Have options? */
	if (*argp == NULL)
		return;
	p = *argp;
	if (*p == '-') {
		/* yes, parse options */
#ifdef	DEBUG
		mon_printf("boot option: %s\n", p);
#endif
		for (++p; *p; p++)
			BOOT_FLAG(*p, boothowto);
		argp++;
	}

#ifdef	DEBUG
	/* Have init name? */
	if (*argp == NULL)
		return;
	p = *argp;
	mon_printf("boot initpath: %s\n", p);
#endif
}
Exemplo n.º 7
0
void
usage(char *msg)
{
	char **use;

	if (msg)
		mon_printf("%s\n",msg);
	use = usage_text;

	while(*use) {
		mon_printf("%s\n",*use);
		use++;
	}
	mon_appexit(-1);
}
Exemplo n.º 8
0
/* processARP();
 */
int
processARP(struct ether_header *ehdr,ushort size)
{
    struct	arphdr *arpp;

    arpp = (struct arphdr *)(ehdr+1);
    self_ecs(arpp->hardware);
    self_ecs(arpp->protocol);
    self_ecs(arpp->operation);

    switch(arpp->operation) {
    case ARP_REQUEST:
        if (!memcmp((char *)arpp->targetia, (char *)&thisip.s_addr,4)) {
            ArpStore(arpp->senderia,arpp->senderha);
            SendArpResp(ehdr);
        }
        break;
    case ARP_RESPONSE:
        if (!memcmp((char *)arpp->targetia, (char *)&thisip.s_addr,4)) {
            ArpStore(arpp->senderia,arpp->senderha);
        }
        break;
    default:
        mon_printf("  Invalid ARP operation: 0x%x\n",arpp->operation);
        return(0);
    }
    return(1);
}
Exemplo n.º 9
0
int
func1(void)
{
	mon_printf("func1\n");
	func2(3);
	return(88);
}
Exemplo n.º 10
0
int
func3(int i)
{
	mon_printf("func3 exception now!\n");
	EXCEPTION();
	return(i+5);
}
Exemplo n.º 11
0
int
func2(int i)
{
	mon_printf("func2\n");
	func3(i+3);
	return(99);
}
Exemplo n.º 12
0
void
errtfs(int line, int tfserrno)
{
	mon_printf("TFSERROR_%d (line %d): %s\n",(int)tfserrno,
		line,(char *)mon_tfsctrl(TFS_ERRMSG,tfserrno,0));
	mon_appexit(-1);
}
Exemplo n.º 13
0
int
strace_demo(void)
{
	mon_printf("strace_demo\n");
	mon_setenv("NO_EXCEPTION_RESTART","TRUE");
	func1();
	return(77);
}
Exemplo n.º 14
0
/*VARARGS0*/
static void
tracedump(int x1)
{
	struct funcall_frame *fp = (struct funcall_frame *)(&x1 - 2);
	u_int stackpage = ((u_int)fp) & ~PGOFSET;

	mon_printf("Begin traceback...fp = 0x%x\n", fp);
	do {
		if (fp == fp->fr_savfp) {
			mon_printf("FP loop at 0x%x", fp);
			break;
		}
		mon_printf("Called from 0x%x, fp=0x%x, args=0x%x 0x%x 0x%x 0x%x\n",
				   fp->fr_savpc, fp->fr_savfp,
				   fp->fr_arg[0], fp->fr_arg[1], fp->fr_arg[2], fp->fr_arg[3]);
		fp = fp->fr_savfp;
	} while ( (((u_int)fp) & ~PGOFSET) == stackpage);
	mon_printf("End traceback...\n");
}
Exemplo n.º 15
0
int
main(int argc,char *argv[])
{
    int		i, tfd;
    char	line[80], *fname;

    /* If argument count is greater than one, then dump out the
     * set of CLI arguments...
     */
    if (argc > 1) {
        mon_printf("Argument list...\n");
        for(i=0; i<argc; i++)
            mon_printf("  arg[%d]: %s\n",i,argv[i]);
    }

    /* If the shell variable "USE_THIS_FILE" exists, then use the
     * content of that shell variable as a filename; else use "monrc"...
     */
    fname = mon_getenv("USE_THIS_FILE");
    if (!fname)
        fname = "monrc";

    /* If the file exists, the assume it is ASCII and dump it
     * line by line...
     */
    if (mon_tfsstat(fname)) {
        mon_printf("Dumping content of '%s'...\n",fname);

        tfd = mon_tfsopen(fname,TFS_RDONLY,0);
        if (tfd >= 0) {
            while(mon_tfsgetline(tfd,line,sizeof(line)))
                mon_printf("%s",line);
            mon_tfsclose(tfd,0);
        }
        else {
            mon_printf("TFS error: %s\n",
                       (char *)mon_tfsctrl(TFS_ERRMSG,tfd,0));
        }
    }
    return(0);
}
Exemplo n.º 16
0
void VCMX212_Init(UINT clk)
{
	//TODO: init clock speed based on define CPU_SPEED
	//---------------------------------------------------------------------------------------------------------------------------------------
	//START OF HAB TOOLKIT SECTION 
	//THIS SECTION CAN BE REMOVED IF RUNNING PROGRAMS  USING JTAG OR UMON
	
	//set PLL frequency to 266MHz
	CRM_CSCR=0x1f18060f;
	CRM_MPCTL0=0x007b1c73;
	CRM_CSCR=0x1f38060f;	//MPLL restart
	while((CRM_MPCTL1 & 0x8000)==0);	//wait until PLL locked

	//enable instruction cache
	asm("   MRC p15, 0, r0, c1, c0, 0");
	asm("   ORR r0, r0, #0x1000"); //bit 12 is ICACHE enable
	asm("   MCR p15, 0, r0, c1, c0, 0");
	// Flush instruction cache 
	asm("   MCR p15, 0, r0, c7, c5, 0");
	
	//END OF HAB TOOLKIT SECTION
	//---------------------------------------------------------------------------------------------------------------------------------------	
	
	//init clocks 
	//TODO: verify that all libraries init clocks properly and delete these lines
	CRM_PCDR1=0x0708070f;	//PERCLK clock divider settings (PERCLK4=44.33MHz, PERCLK3=26.6MHz)
	CRM_PCCR0=0x64063841;	//enable I2C, DMA, LCDC, GPIO,UART1

	mon_printf("\nVCMX212_Init: Initialized MX212\n");

	//init the MicroMonitor extended heap, based on how much SDRAM0 is left

	extern char end;													// Assumes end label is setup in ldscript properly!!
	s_pSDRAM0_HeapStart	= (char*)&end;									// from ldscript
	s_iSDRAM0_HeapSize	= (32*1024*1024) - ((UINT)&end - SDRAM0_BASE);	// 32MB - (app + uMon) size

	mon_printf("VCMX212_Init: SDRAM0 start 0x%1x\n", s_pSDRAM0_HeapStart);
	mon_printf("VCMX212_Init: SDRAM0 size  0x%1x\n", s_iSDRAM0_HeapSize);
	mon_heapextend(s_pSDRAM0_HeapStart, s_iSDRAM0_HeapSize);
	
}
Exemplo n.º 17
0
/*
 * Preserve DDB symbols and strings by setting esym.
 */
static void
_save_symtab(void)
{
	int i;
	Elf_Ehdr *ehdr;
	Elf_Shdr *shp;
	vaddr_t minsym, maxsym;

	/*
	 * Check the ELF headers.
	 */

	ehdr = (void *)end;
	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0 ||
	    ehdr->e_ident[EI_CLASS] != ELFCLASS32) {
		mon_printf("_save_symtab: bad ELF magic\n");
		return;
	}

	/*
	 * Find the end of the symbols and strings.
	 */

	maxsym = 0;
	minsym = ~maxsym;
	shp = (Elf_Shdr *)(end + ehdr->e_shoff);
	for (i = 0; i < ehdr->e_shnum; i++) {
		if (shp[i].sh_type != SHT_SYMTAB &&
		    shp[i].sh_type != SHT_STRTAB) {
			continue;
		}
		minsym = min(minsym, (vaddr_t)end + shp[i].sh_offset);
		maxsym = max(maxsym, (vaddr_t)end + shp[i].sh_offset +
			     shp[i].sh_size);
	}
	nsym = 1;
	ssym = (char *)ehdr;
	esym = (char *)maxsym;
}
Exemplo n.º 18
0
/*
 * This function replaces sys/dev/cninit.c
 * Determine which device is the console using
 * the PROM "input source" and "output sink".
 */
void
cninit(void)
{
    struct sunromvec *v;
    struct zschan *zc;
    struct consdev *cn;
    int channel, zs_unit, zstty_unit;
    uint8_t inSource, outSink;
    extern const struct cdevsw zstty_cdevsw;

    /* Get the zs driver ready for console duty. */
    zs_init();

    v = romVectorPtr;
    inSource = *v->inSource;
    outSink  = *v->outSink;
    if (inSource != outSink) {
        mon_printf("cninit: mismatched PROM output selector\n");
    }

    switch (inSource) {
    default:
        mon_printf("cninit: invalid inSource=%d\n", inSource);
        sunmon_abort();
        inSource = 0;
    /* fall through */

    case 0:	/* keyboard/display */
#if NKBD > 0
        zs_unit = 0;
        channel = 0;
        cn = &consdev_kd;
        /* Set cn_dev, cn_pri in kd.c */
        break;
#else	/* NKBD */
        mon_printf("cninit: kdb/display not configured\n");
        sunmon_abort();
        inSource = 1;
        /* fall through */
#endif	/* NKBD */

    case 1:	/* ttya */
    case 2:	/* ttyb */
    case 3:	/* ttyc (rewired keyboard connector) */
    case 4:	/* ttyd (rewired mouse connector)   */
        zstty_unit = inSource - 1;
        zs_unit = zstty_conf[zstty_unit].zs_unit;
        channel = zstty_conf[zstty_unit].channel;
        cn = &consdev_tty;
        cn->cn_dev = makedev(cdevsw_lookup_major(&zstty_cdevsw),
                             zstty_unit);
        cn->cn_pri = CN_REMOTE;
        break;

    }
    /* Now that inSource has been validated, print it. */
    mon_printf("console is %s\n", prom_inSrc_name[inSource]);

    zc = zs_get_chan_addr(zs_unit, channel);
    if (zc == NULL) {
        mon_printf("cninit: zs not mapped.\n");
        return;
    }
    zs_conschan = zc;
    zs_hwflags[zs_unit][channel] = ZS_HWFLAG_CONSOLE;
    cn_tab = cn;
    (*cn->cn_init)(cn);
#ifdef	KGDB
    zs_kgdb_init();
#endif
}
Exemplo n.º 19
0
int
main(int argc, char *argv[])
{
	mon_printf("Hello embedded world!\n");
	return(0);
}
Exemplo n.º 20
0
/* errexit() and errtfs():
 *	Functions used (via macros above) to report error conditions detected
 *	by the tests below.
 */
void
errexit(int line)
{
	mon_printf("ERROR line %d\n",line);
	mon_appexit(-1);
}
Exemplo n.º 21
0
/* main():
 * The equivalent of the MONCMD server built into uMon...
 * Blocks on port 777 waiting for an incoming message, then
 * responds with "thanks".
 */
int
main(int argc, char *argv[])
{
	int rc = 0;

	unetStart();
	cmdInit();
	mon_printf("%s: MONCMD server using uMon's ethernet API...\n",
		argv[0]);

	/* This loop processes incoming UDP and incoming serial port
	 * (console) activity...  Terminate on reception of ctrl-c
	 * (0x03) from console.
	 */
	while(1) {
		if (mon_gotachar()) {
			int c = mon_getchar();

			if (c == 0x03) {
				mon_printf("\n<ctrl-c>\n");
				break;
			}
			else
				processChar(c);
		}

		/* Set up the server to receive packets on any port...
		 * Then after udpRecvFrom returns, use the value of u.dport
		 * to determine which port the packet came in on.
		 */
		udpInfo.dport = ANY_UDP_PORT;
		udpInfo.packet = (char *)unetPacket;
		udpInfo.plen = sizeof(unetPacket);

		/* Check for an incoming packet.  This does not block.  It will
		 * return negative if there is an error, zero of there is no packet
		 * pending; else some positive number representing the incoming
		 * packet size.
		 */
		rc = udpRecvFrom(&udpInfo);

		if (rc > 0) {
			if (udpInfo.dport == 777) {
				udp_umoncmd((char *)udpInfo.udata);
			}
			else {
				mon_printf("\nUDP rcv'd on port %d, from %d.%d.%d.%d:%d ...\n",
					udpInfo.dport,
					IP1(udpInfo.sip.s_addr), IP2(udpInfo.sip.s_addr),
					IP3(udpInfo.sip.s_addr), IP4(udpInfo.sip.s_addr),
					udpInfo.sport);
				mon_printmem((char *)udpInfo.udata,rc,1);
			}
		}
		else if (rc < 0) {
			unetError("recv",rc,UNETACT_ALL);
		}
	}
	unetStop();
	return(0);
}
Exemplo n.º 22
0
int
main(int argc,char *argv[])
{
	int	err, opt, removefiles, list;
	char *file1, *file2;

	verbose = 0;
	list = 0;
	removefiles = 1;
	getoptinit();
	while((opt=getopt(argc,argv,"lrv")) != -1) {
		switch(opt) {
		case 'l':
			list = 1;
			break;
		case 'r':
			removefiles = 0;
			break;
		case 'v':
			verbose++;
			break;
		default:
			usage(0);
		}
	}

	if (argc != optind+2)
		usage("Bad arg count");

	/* Test all aspects of TFS API calls: */
	file1 = argv[optind];
	file2 = argv[optind+1];
	if ((!strcmp(file1,TMPFILE)) || (!strcmp(file2,TMPFILE)))
		usage(TMPFILE);


	if (verbose)
		mon_printf("tfstest %s %s...\n",file1,file2);
	

	/* 
	 *	Start by removing files to be created later...
	 */
	if (mon_tfsstat(TMPFILE)) {
		if (verbose)
			mon_printf("Removing %s...\n",TMPFILE);
		err = mon_tfsunlink(TMPFILE);
		if (err != TFS_OKAY)
			tfsdie(err);
	}
	if (mon_tfsstat(file1)) {
		if (verbose)
			mon_printf("Removing %s...\n",file1);
		err = mon_tfsunlink(file1);
		if (err != TFS_OKAY)
			tfsdie(err);
	}
	if (mon_tfsstat(file2)) {
		if (verbose)
			mon_printf("Removing %s...\n",file2);
		err = mon_tfsunlink(file2);
		if (err != TFS_OKAY)
			tfsdie(err);
	}

	/*
	 *	Create a file...
	 */
	if (verbose)
		mon_printf("Creating %s...\n",file1);
	err = mon_tfsadd(file1,"data1","2",data1,strlen(data1));
	if (err != TFS_OKAY)
		tfsdie(err);

	/*
	 *	Basic getline test...
	 */
	if (verbose)
		mon_printf("Checking 'getline'...\n");
	getlinetest(file1,data1);

	/*
	 *	Now copy the file...
	 */
	if (verbose)
		mon_printf("Copying %s to %s...\n",file1,file2);
	cp(file2,file1);

	/*
	 *	Now compare the two...
	 *	(they should be identical)
	 */
	if (verbose)
		mon_printf("Comparing %s to %s...\n",file1,file2);
	if (cmp(file1,file2) != 0)
		die();

	/*
	 *	Seek test...
	 *  Verify that data at a specified offset is as expected based on the
	 *	file (file1) initially created from the data1 array...
	 */
	if (verbose)
		mon_printf("Running seek test on %s...\n",file1);
	seektest(file1,38,data1[38]);

	/* 
	 *	Truncateion test...
	 *	Truncate a file and verify.
	 */
	if (verbose)
		mon_printf("Running truncation test on %s...\n",file1);
	trunctest(file1,data1);

	/*
	 *	Tfsctrl() function test...
	 */
	if (verbose)
		mon_printf("Running tfsctrl test...\n");
	ctrltest(file1,data1);

	/* 
	 *	Write test...
	 *	Modify a file in a few different ways and verify the modification...
	 *	Note that after this point, file1 and data1 are not the same.
	 *	The content of file1 will be the same as the new_data1 array.
	 */
	if (verbose)
		mon_printf("Running write test on %s...\n",file1);
	writetest(file1,new_data1);
	
	/*
	 *	File in-use test...
	 *	Verify that if a file is in-use, it cannot be removed.
	 */
	if (verbose)
		mon_printf("Running in-use test on %s...\n",file1);
	inusetest(file1);

	/*
	 *	Append test...
	 *	Verify that a file can be properly appended to.
	 */
	if (verbose)
		mon_printf("Running append test on %s...\n",file1);
	appendtest(file1,"this_is_some_data","this_is_the_appended_data");

	/*
	 * If the -r option is not set, then remove the files...
	 */
	if (removefiles) {
		if (mon_tfsstat(file1)) {
			err = mon_tfsunlink(file1);
			if (err != TFS_OKAY)
				tfsdie(err);
		}
		if (mon_tfsstat(file2)) {
			err = mon_tfsunlink(file2);
			if (err != TFS_OKAY)
				tfsdie(err);
		}
		if (mon_tfsstat(TMPFILE)) {
			err = mon_tfsunlink(TMPFILE);
			if (err != TFS_OKAY)
				tfsdie(err);
		}
	}

	if (list)
		ls();

	/* All error cases checked above would have resulted in an exit
	 * of this application, so if we got here, the testing must
	 * have succeeded...
	 */
	mon_printf("TFS test on %s & %s PASSED\n",file1,file2);
	mon_appexit(0);
	return(0);
}
Exemplo n.º 23
0
/* convert_vars():
 * Take base and len as pointers to a file's data in TFS.
 * Parse the file looking for ${xxxx}, if found and if xxxx
 * is an environment variable, replace it with the content of
 * the variable.
 * As of Nov 2009, added support for $[xxxx], to be used as
 * an indicator that 'xxxx' is a command to be run through
 * mon_docommand().
 */
int
convert_vars(char *base, int len)
{
  char varbuf[64];
  char *from = base;
  char *fend = base+len;
  char *to = filebuf;
  char *tend = to+sizeof(filebuf);
  char state = NORMAL;
  char *varname = 0, *env;

  while(from < fend) {
    switch(state) {
      case NORMAL:
    	if (*from == '$')
          state = GOTDOLLAR;
        else
          *to++ = *from;
        break;
      case GOTDOLLAR:
        if (*from == OBRACE)
          state = GOTOBRACE;
        else if (*from == OBRACKET)
          state = GOTOBRACKET;
        else {
          *to++ = '$';
          *to++ = *from;
          state = NORMAL;
        }
        break;
      case GOTOBRACKET:
        if (varname == 0) {
          varname = from;
        }
        else if (*from == CBRACKET) {
          memset(varbuf,0,sizeof(varbuf));
          if ((from-varname) < sizeof(varbuf))
            strncpy(varbuf,varname,from-varname);
          else {
            mon_printf("convert_vars(): overflow protection_1\n");
            return(to-filebuf);
          }
          mon_docommand(varbuf,http_verbose);
          varname = 0;
          state = NORMAL;
        }
        break;
      case GOTOBRACE:
        if (varname == 0) {
          varname = from;
        }
        else if (*from == CBRACE) {
          memset(varbuf,0,sizeof(varbuf));
          if ((from-varname) < sizeof(varbuf))
            strncpy(varbuf,varname,from-varname);
          else {
            mon_printf("convert_vars(): overflow protection_2\n");
            return(to-filebuf);
          }
          env = mon_getenv(varbuf);
          if (to + strlen(env) >= tend) {
            mon_printf("convert_vars(): overflow protection_3\n");
            return(to-filebuf);
          }
          if (env) {
            strcpy(to,env);
            to += strlen(env);
          }
          else {
            strcpy(to,varname);
            to += strlen(varname);
            *to++ = CBRACE;
          }
          varname = 0;
          state = NORMAL;
        }
        break;
    }
    from++;
  }
  return(to-filebuf);
}