10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 230Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 280Sstevel@tonic-gate 290Sstevel@tonic-gate #include <ctype.h> 300Sstevel@tonic-gate #include <stdio.h> 310Sstevel@tonic-gate #include <unistd.h> 320Sstevel@tonic-gate #include <stdlib.h> 330Sstevel@tonic-gate #include <string.h> 340Sstevel@tonic-gate #include <sys/time.h> 350Sstevel@tonic-gate 360Sstevel@tonic-gate #include <fcode/private.h> 370Sstevel@tonic-gate #include <fcode/log.h> 380Sstevel@tonic-gate 390Sstevel@tonic-gate 400Sstevel@tonic-gate static variable_t verbose_emit; 410Sstevel@tonic-gate 420Sstevel@tonic-gate void 430Sstevel@tonic-gate do_verbose_emit(fcode_env_t *env) 440Sstevel@tonic-gate { 450Sstevel@tonic-gate verbose_emit ^= 1; 460Sstevel@tonic-gate } 470Sstevel@tonic-gate 480Sstevel@tonic-gate /* 490Sstevel@tonic-gate * Internal "emit". 500Sstevel@tonic-gate * Note log_emit gathers up characters and issues a syslog or write to 510Sstevel@tonic-gate * error log file if enabled. 520Sstevel@tonic-gate */ 530Sstevel@tonic-gate void 540Sstevel@tonic-gate do_emit(fcode_env_t *env, uchar_t c) 550Sstevel@tonic-gate { 560Sstevel@tonic-gate if (verbose_emit) 570Sstevel@tonic-gate log_message(MSG_ERROR, "emit(%x)\n", c); 580Sstevel@tonic-gate 590Sstevel@tonic-gate if (c == '\n') { 600Sstevel@tonic-gate env->output_column = 0; 610Sstevel@tonic-gate env->output_line++; 620Sstevel@tonic-gate } else if (c == '\r') 630Sstevel@tonic-gate env->output_column = 0; 640Sstevel@tonic-gate else 650Sstevel@tonic-gate env->output_column++; 660Sstevel@tonic-gate if (isatty(fileno(stdout))) { 670Sstevel@tonic-gate if ((c >= 0x20 && c <= 0x7f) || c == '\n' || c == '\r' || 680Sstevel@tonic-gate c == '\b') 690Sstevel@tonic-gate putchar(c); 70*796Smathue else if (c < 0x20) 710Sstevel@tonic-gate printf("@%c", c + '@'); 720Sstevel@tonic-gate else 730Sstevel@tonic-gate printf("\\%x", c); 740Sstevel@tonic-gate fflush(stdout); 750Sstevel@tonic-gate } 760Sstevel@tonic-gate log_emit(c); 770Sstevel@tonic-gate } 780Sstevel@tonic-gate 790Sstevel@tonic-gate void 800Sstevel@tonic-gate system_message(fcode_env_t *env, char *msg) 810Sstevel@tonic-gate { 820Sstevel@tonic-gate throw_from_fclib(env, 1, msg); 830Sstevel@tonic-gate } 840Sstevel@tonic-gate 850Sstevel@tonic-gate void 860Sstevel@tonic-gate emit(fcode_env_t *env) 870Sstevel@tonic-gate { 880Sstevel@tonic-gate fstack_t d; 890Sstevel@tonic-gate 900Sstevel@tonic-gate CHECK_DEPTH(env, 1, "emit"); 910Sstevel@tonic-gate d = POP(DS); 920Sstevel@tonic-gate do_emit(env, d); 930Sstevel@tonic-gate } 940Sstevel@tonic-gate 950Sstevel@tonic-gate #include <sys/time.h> 960Sstevel@tonic-gate 970Sstevel@tonic-gate /* 980Sstevel@tonic-gate * 'key?' - abort if stdin is not a tty. 990Sstevel@tonic-gate */ 1000Sstevel@tonic-gate void 1010Sstevel@tonic-gate keyquestion(fcode_env_t *env) 1020Sstevel@tonic-gate { 1030Sstevel@tonic-gate struct timeval timeval; 1040Sstevel@tonic-gate fd_set readfds; 1050Sstevel@tonic-gate int ret; 1060Sstevel@tonic-gate 1070Sstevel@tonic-gate if (isatty(fileno(stdin))) { 1080Sstevel@tonic-gate FD_ZERO(&readfds); 1090Sstevel@tonic-gate FD_SET(fileno(stdin), &readfds); 1100Sstevel@tonic-gate timeval.tv_sec = 0; 1110Sstevel@tonic-gate timeval.tv_usec = 1000; 1120Sstevel@tonic-gate ret = select(fileno(stdin) + 1, &readfds, NULL, NULL, &timeval); 1130Sstevel@tonic-gate if (FD_ISSET(fileno(stdin), &readfds)) 1140Sstevel@tonic-gate PUSH(DS, TRUE); 1150Sstevel@tonic-gate else 1160Sstevel@tonic-gate PUSH(DS, FALSE); 1170Sstevel@tonic-gate } else 1180Sstevel@tonic-gate forth_abort(env, "'key?' called in non-interactive mode"); 1190Sstevel@tonic-gate } 1200Sstevel@tonic-gate 1210Sstevel@tonic-gate /* 1220Sstevel@tonic-gate * 'key' - abort if stdin is not a tty, will block on read if char not avail. 1230Sstevel@tonic-gate */ 1240Sstevel@tonic-gate void 1250Sstevel@tonic-gate key(fcode_env_t *env) 1260Sstevel@tonic-gate { 1270Sstevel@tonic-gate uchar_t c; 1280Sstevel@tonic-gate 1290Sstevel@tonic-gate if (isatty(fileno(stdin))) { 1300Sstevel@tonic-gate read(fileno(stdin), &c, 1); 1310Sstevel@tonic-gate PUSH(DS, c); 1320Sstevel@tonic-gate } else 1330Sstevel@tonic-gate forth_abort(env, "'key' called in non-interactive mode"); 1340Sstevel@tonic-gate } 1350Sstevel@tonic-gate 1360Sstevel@tonic-gate void 1370Sstevel@tonic-gate type(fcode_env_t *env) 1380Sstevel@tonic-gate { 1390Sstevel@tonic-gate int len; 1400Sstevel@tonic-gate char *ptr; 1410Sstevel@tonic-gate 1420Sstevel@tonic-gate CHECK_DEPTH(env, 2, "type"); 1430Sstevel@tonic-gate ptr = pop_a_string(env, &len); 1440Sstevel@tonic-gate while (len--) 1450Sstevel@tonic-gate do_emit(env, *ptr++); 1460Sstevel@tonic-gate } 1470Sstevel@tonic-gate 1480Sstevel@tonic-gate void 1490Sstevel@tonic-gate paren_cr(fcode_env_t *env) 1500Sstevel@tonic-gate { 1510Sstevel@tonic-gate do_emit(env, '\r'); 1520Sstevel@tonic-gate } 1530Sstevel@tonic-gate 1540Sstevel@tonic-gate void 1550Sstevel@tonic-gate fc_crlf(fcode_env_t *env) 1560Sstevel@tonic-gate { 1570Sstevel@tonic-gate do_emit(env, '\n'); 1580Sstevel@tonic-gate } 1590Sstevel@tonic-gate 1600Sstevel@tonic-gate void 1610Sstevel@tonic-gate fc_num_out(fcode_env_t *env) 1620Sstevel@tonic-gate { 1630Sstevel@tonic-gate PUSH(DS, (fstack_t)(&env->output_column)); 1640Sstevel@tonic-gate } 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate void 1670Sstevel@tonic-gate fc_num_line(fcode_env_t *env) 1680Sstevel@tonic-gate { 1690Sstevel@tonic-gate PUSH(DS, (fstack_t)(&env->output_line)); 1700Sstevel@tonic-gate } 1710Sstevel@tonic-gate 1720Sstevel@tonic-gate void 1730Sstevel@tonic-gate expect(fcode_env_t *env) 1740Sstevel@tonic-gate { 1750Sstevel@tonic-gate char *buf, *rbuf; 1760Sstevel@tonic-gate int len; 1770Sstevel@tonic-gate 1780Sstevel@tonic-gate CHECK_DEPTH(env, 2, "expect"); 1790Sstevel@tonic-gate buf = pop_a_string(env, &len); 1800Sstevel@tonic-gate read_line(env); 1810Sstevel@tonic-gate rbuf = pop_a_string(env, NULL); 1820Sstevel@tonic-gate if (rbuf) { 1830Sstevel@tonic-gate strcpy(buf, rbuf); 1840Sstevel@tonic-gate env->span = strlen(buf); 1850Sstevel@tonic-gate } else 1860Sstevel@tonic-gate env->span = 0; 1870Sstevel@tonic-gate } 1880Sstevel@tonic-gate 1890Sstevel@tonic-gate void 1900Sstevel@tonic-gate span(fcode_env_t *env) 1910Sstevel@tonic-gate { 1920Sstevel@tonic-gate PUSH(DS, (fstack_t)&env->span); 1930Sstevel@tonic-gate } 1940Sstevel@tonic-gate 1950Sstevel@tonic-gate void 1960Sstevel@tonic-gate do_ms(fcode_env_t *env) 1970Sstevel@tonic-gate { 1980Sstevel@tonic-gate fstack_t d; 1990Sstevel@tonic-gate timespec_t rqtp; 2000Sstevel@tonic-gate 2010Sstevel@tonic-gate CHECK_DEPTH(env, 1, "ms"); 2020Sstevel@tonic-gate d = POP(DS); 2030Sstevel@tonic-gate if (d) { 2040Sstevel@tonic-gate rqtp.tv_sec = 0; 2050Sstevel@tonic-gate rqtp.tv_nsec = d*1000*1000; 2060Sstevel@tonic-gate nanosleep(&rqtp, 0); 2070Sstevel@tonic-gate } 2080Sstevel@tonic-gate } 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate void 2110Sstevel@tonic-gate do_get_msecs(fcode_env_t *env) 2120Sstevel@tonic-gate { 2130Sstevel@tonic-gate struct timeval tp; 2140Sstevel@tonic-gate long ms; 2150Sstevel@tonic-gate timespec_t rqtp; 2160Sstevel@tonic-gate 2170Sstevel@tonic-gate gettimeofday(&tp, NULL); 2180Sstevel@tonic-gate ms = (tp.tv_usec/1000) + (tp.tv_sec * 1000); 2190Sstevel@tonic-gate PUSH(DS, (fstack_t)ms); 2200Sstevel@tonic-gate rqtp.tv_sec = 0; 2210Sstevel@tonic-gate rqtp.tv_nsec = 1000*1000; 2220Sstevel@tonic-gate nanosleep(&rqtp, 0); 2230Sstevel@tonic-gate } 2240Sstevel@tonic-gate 2250Sstevel@tonic-gate #define CMN_MSG_SIZE 256 2260Sstevel@tonic-gate #define CMN_MAX_DIGITS 3 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate typedef struct CMN_MSG_T cmn_msg_t; 2290Sstevel@tonic-gate 2300Sstevel@tonic-gate struct CMN_MSG_T { 2310Sstevel@tonic-gate char buf[CMN_MSG_SIZE]; 2320Sstevel@tonic-gate int level; 2330Sstevel@tonic-gate int len; 2340Sstevel@tonic-gate cmn_msg_t *prev; 2350Sstevel@tonic-gate cmn_msg_t *next; 2360Sstevel@tonic-gate }; 2370Sstevel@tonic-gate 2380Sstevel@tonic-gate typedef struct CMN_FMT_T cmn_fmt_t; 2390Sstevel@tonic-gate 2400Sstevel@tonic-gate struct CMN_FMT_T { 2410Sstevel@tonic-gate int fwidth; /* format field width */ 2420Sstevel@tonic-gate int cwidth; /* column width specified in format */ 2430Sstevel@tonic-gate char format; /* format type */ 2440Sstevel@tonic-gate }; 2450Sstevel@tonic-gate 2460Sstevel@tonic-gate static cmn_msg_t *root = NULL; 2470Sstevel@tonic-gate static int cmn_msg_level = 0; 2480Sstevel@tonic-gate 2490Sstevel@tonic-gate /* 2500Sstevel@tonic-gate * validfmt() 2510Sstevel@tonic-gate * 2520Sstevel@tonic-gate * Called by fmt_str() function to validate and extract formatting 2530Sstevel@tonic-gate * information from the supplied input buffer. 2540Sstevel@tonic-gate * 2550Sstevel@tonic-gate * Supported formats are: 2560Sstevel@tonic-gate * %c - character 2570Sstevel@tonic-gate * %d - signed decimal 2580Sstevel@tonic-gate * %x - unsigned hex 2590Sstevel@tonic-gate * %s - string 2600Sstevel@tonic-gate * %ld - signed 64 bit data 2610Sstevel@tonic-gate * %lx - unsigned 64 bit data 2620Sstevel@tonic-gate * %p - unsigned 64 bit data(pointer) 2630Sstevel@tonic-gate * %% - print as single "%" character 2640Sstevel@tonic-gate * 2650Sstevel@tonic-gate * Return values are: 2660Sstevel@tonic-gate * 0 - valid formatting 2670Sstevel@tonic-gate * 1 - invalid formatting found in the input buffer 2680Sstevel@tonic-gate * -1 - NULL pointer passed in for caller's receptacle 2690Sstevel@tonic-gate * 2700Sstevel@tonic-gate * 2710Sstevel@tonic-gate * For valid formatting, caller's supplied cmn_fmt_t elements are 2720Sstevel@tonic-gate * filled in: 2730Sstevel@tonic-gate * fwidth: 2740Sstevel@tonic-gate * > 0 - returned value is the field width 2750Sstevel@tonic-gate * < 0 - returned value is negation of field width for 2760Sstevel@tonic-gate * 64 bit data formats 2770Sstevel@tonic-gate * cwidth: 2780Sstevel@tonic-gate * formatted column width(if specified), otherwise 0 2790Sstevel@tonic-gate * 2800Sstevel@tonic-gate * format: 2810Sstevel@tonic-gate * contains the formatting(single) character 2820Sstevel@tonic-gate */ 2830Sstevel@tonic-gate static int 2840Sstevel@tonic-gate validfmt(char *fmt, cmn_fmt_t *cfstr) 2850Sstevel@tonic-gate { 2860Sstevel@tonic-gate int isll = 0; 2870Sstevel@tonic-gate int *fwidth, *cwidth; 2880Sstevel@tonic-gate char *format; 2890Sstevel@tonic-gate char *dig1, *dig2; 2900Sstevel@tonic-gate char cdigs[CMN_MAX_DIGITS+1]; 2910Sstevel@tonic-gate 2920Sstevel@tonic-gate if (cfstr == NULL) 2930Sstevel@tonic-gate return (-1); 2940Sstevel@tonic-gate 2950Sstevel@tonic-gate fwidth = &cfstr->fwidth; 2960Sstevel@tonic-gate cwidth = &cfstr->cwidth; 2970Sstevel@tonic-gate format = &cfstr->format; 2980Sstevel@tonic-gate *fwidth = *cwidth = 0; 2990Sstevel@tonic-gate *format = NULL; 3000Sstevel@tonic-gate dig1 = dig2 = NULL; 3010Sstevel@tonic-gate 3020Sstevel@tonic-gate /* check for left justification character */ 3030Sstevel@tonic-gate if (*fmt == '-') { 3040Sstevel@tonic-gate fmt++; 3050Sstevel@tonic-gate (*fwidth)++; 3060Sstevel@tonic-gate 3070Sstevel@tonic-gate /* check for column width specification */ 3080Sstevel@tonic-gate if (isdigit(*fmt)) 3090Sstevel@tonic-gate dig1 = fmt; /* save ptr to first digit */ 3100Sstevel@tonic-gate while (isdigit(*fmt)) { 3110Sstevel@tonic-gate fmt++; 3120Sstevel@tonic-gate (*fwidth)++; 3130Sstevel@tonic-gate } 3140Sstevel@tonic-gate /* if ljust specified w/o size, return format error */ 3150Sstevel@tonic-gate if (*fwidth == 1) { 3160Sstevel@tonic-gate return (1); 3170Sstevel@tonic-gate } 3180Sstevel@tonic-gate dig2 = fmt; /* save ptr to last digit + 1 */ 3190Sstevel@tonic-gate } else { 3200Sstevel@tonic-gate /* check for column width specification */ 3210Sstevel@tonic-gate if (isdigit(*fmt)) { 3220Sstevel@tonic-gate dig1 = fmt; /* save ptr to first digit */ 3230Sstevel@tonic-gate while (isdigit(*fmt)) { 3240Sstevel@tonic-gate fmt++; 3250Sstevel@tonic-gate (*fwidth)++; 3260Sstevel@tonic-gate } 3270Sstevel@tonic-gate dig2 = fmt; /* save ptr to last digit + 1 */ 3280Sstevel@tonic-gate } 3290Sstevel@tonic-gate } 3300Sstevel@tonic-gate 3310Sstevel@tonic-gate /* if a column width was specified, save it in caller's struct */ 3320Sstevel@tonic-gate if (dig1) { 3330Sstevel@tonic-gate int nbytes; 3340Sstevel@tonic-gate 3350Sstevel@tonic-gate nbytes = dig2 - dig1; 3360Sstevel@tonic-gate /* if too many digits in the width return error */ 3370Sstevel@tonic-gate if (nbytes > CMN_MAX_DIGITS) 3380Sstevel@tonic-gate return (1); 3390Sstevel@tonic-gate strncpy(cdigs, dig1, nbytes); 3400Sstevel@tonic-gate cdigs[nbytes] = 0; 3410Sstevel@tonic-gate *cwidth = atoi(cdigs); 3420Sstevel@tonic-gate } 3430Sstevel@tonic-gate 3440Sstevel@tonic-gate /* check for long format specifier */ 3450Sstevel@tonic-gate if (*fmt == 'l') { 3460Sstevel@tonic-gate fmt++; 3470Sstevel@tonic-gate (*fwidth)++; 3480Sstevel@tonic-gate isll = 1; 3490Sstevel@tonic-gate } 3500Sstevel@tonic-gate 3510Sstevel@tonic-gate /* process by specific format type */ 3520Sstevel@tonic-gate switch (*fmt) { 3530Sstevel@tonic-gate case 'c': 3540Sstevel@tonic-gate case 's': 3550Sstevel@tonic-gate case '%': 3560Sstevel@tonic-gate if (isll) 3570Sstevel@tonic-gate return (1); 3580Sstevel@tonic-gate case 'd': 3590Sstevel@tonic-gate case 'x': 3600Sstevel@tonic-gate *format = *fmt; 3610Sstevel@tonic-gate (*fwidth)++; 3620Sstevel@tonic-gate break; 3630Sstevel@tonic-gate case 'p': 3640Sstevel@tonic-gate isll = 1; /* uses 64 bit format */ 3650Sstevel@tonic-gate *format = *fmt; 3660Sstevel@tonic-gate (*fwidth)++; 3670Sstevel@tonic-gate break; 3680Sstevel@tonic-gate default: 3690Sstevel@tonic-gate return (1); /* unknown format type */ 3700Sstevel@tonic-gate } 3710Sstevel@tonic-gate if (isll) { 3720Sstevel@tonic-gate *fwidth *= -1; 3730Sstevel@tonic-gate } 3740Sstevel@tonic-gate return (0); 3750Sstevel@tonic-gate } 3760Sstevel@tonic-gate 3770Sstevel@tonic-gate /* 3780Sstevel@tonic-gate * fmt_args() 3790Sstevel@tonic-gate * 3800Sstevel@tonic-gate * Called by fmt_str() to setup arguments for subsequent snprintf() 3810Sstevel@tonic-gate * calls. For cases not involving column width limitations, processing 3820Sstevel@tonic-gate * simply POPs the data stack as required to setup caller's arg(or 3830Sstevel@tonic-gate * llarg, as appropriate). When a column width is specified for output, 3840Sstevel@tonic-gate * a temporary buffer is constructed to contain snprintf() generated 3850Sstevel@tonic-gate * output for the argument. Testing is then performed to determine if 3860Sstevel@tonic-gate * the specified column width will require truncation of the output. 3870Sstevel@tonic-gate * If so, truncation of least significant digits is performed as 3880Sstevel@tonic-gate * necessary, and caller's arg(or llarg) is adjusted to obtain the 3890Sstevel@tonic-gate * specified column width. 3900Sstevel@tonic-gate * 3910Sstevel@tonic-gate */ 3920Sstevel@tonic-gate 3930Sstevel@tonic-gate static void 3940Sstevel@tonic-gate fmt_args(fcode_env_t *env, int cw, int fw, char format, long *arg, 3950Sstevel@tonic-gate long long *llarg) 3960Sstevel@tonic-gate { 3970Sstevel@tonic-gate char *cbuf; 3980Sstevel@tonic-gate char snf[3]; 3990Sstevel@tonic-gate int cbsize; 4000Sstevel@tonic-gate int cnv = 10, ndigits = 0; 4010Sstevel@tonic-gate 4020Sstevel@tonic-gate if (fw > 0) { /* check for normal (not long) formats */ 4030Sstevel@tonic-gate 4040Sstevel@tonic-gate /* initialize format string for snprintf call */ 4050Sstevel@tonic-gate snf[0] = '%'; 4060Sstevel@tonic-gate snf[1] = format; 4070Sstevel@tonic-gate snf[2] = 0; 4080Sstevel@tonic-gate 4090Sstevel@tonic-gate /* process by format type */ 4100Sstevel@tonic-gate switch (format) { 4110Sstevel@tonic-gate case 'x': 4120Sstevel@tonic-gate cnv = 16; 4130Sstevel@tonic-gate case 'd': 4140Sstevel@tonic-gate case 'c': 4150Sstevel@tonic-gate case 'p': 4160Sstevel@tonic-gate *arg = POP(DS); 4170Sstevel@tonic-gate break; 4180Sstevel@tonic-gate case 's': 4190Sstevel@tonic-gate POP(DS); 4200Sstevel@tonic-gate *arg = POP(DS); 4210Sstevel@tonic-gate break; 4220Sstevel@tonic-gate case '%': 4230Sstevel@tonic-gate return; 4240Sstevel@tonic-gate default: 4250Sstevel@tonic-gate log_message(MSG_ERROR, 4260Sstevel@tonic-gate "fmt_args:invalid format type! (%s)\n", 4270Sstevel@tonic-gate &format); 4280Sstevel@tonic-gate return; 4290Sstevel@tonic-gate } 4300Sstevel@tonic-gate 4310Sstevel@tonic-gate /* check if a column width was specified */ 4320Sstevel@tonic-gate if (cw) { 4330Sstevel@tonic-gate /* allocate a scratch buffer */ 4340Sstevel@tonic-gate cbsize = 2*(sizeof (long long)) + 1; 4350Sstevel@tonic-gate cbuf = MALLOC(cbsize); 4360Sstevel@tonic-gate 4370Sstevel@tonic-gate if (snprintf(cbuf, cbsize, snf, *arg) < 0) 4380Sstevel@tonic-gate log_message(MSG_ERROR, 4390Sstevel@tonic-gate "fmt_args: snprintf output error\n"); 4400Sstevel@tonic-gate while ((cbuf[ndigits] != NULL) && 4410Sstevel@tonic-gate (ndigits < cbsize)) 4420Sstevel@tonic-gate ndigits++; 4430Sstevel@tonic-gate 4440Sstevel@tonic-gate /* if truncation is necessary, do it */ 4450Sstevel@tonic-gate if (ndigits > cw) { 4460Sstevel@tonic-gate cbuf[cw] = 0; 4470Sstevel@tonic-gate if (format == 's') { 4480Sstevel@tonic-gate char *str; 4490Sstevel@tonic-gate str = (char *)*arg; 4500Sstevel@tonic-gate str[cw] = 0; 4510Sstevel@tonic-gate } else 4520Sstevel@tonic-gate *arg = strtol(cbuf, 4530Sstevel@tonic-gate (char **)NULL, cnv); 4540Sstevel@tonic-gate } 4550Sstevel@tonic-gate free(cbuf); 4560Sstevel@tonic-gate } 4570Sstevel@tonic-gate 4580Sstevel@tonic-gate } else { /* process long formats */ 4590Sstevel@tonic-gate 4600Sstevel@tonic-gate *llarg = POP(DS); 4610Sstevel@tonic-gate 4620Sstevel@tonic-gate /* check if a column width was specified */ 4630Sstevel@tonic-gate if (cw) { 4640Sstevel@tonic-gate /* allocate a scratch buffer */ 4650Sstevel@tonic-gate cbsize = 2*(sizeof (long long)) + 1; 4660Sstevel@tonic-gate cbuf = MALLOC(cbsize); 4670Sstevel@tonic-gate 4680Sstevel@tonic-gate switch (format) { 4690Sstevel@tonic-gate case 'p': 4700Sstevel@tonic-gate cnv = 16; 4710Sstevel@tonic-gate if (snprintf(cbuf, cbsize, "%p", *llarg) < 0) 4720Sstevel@tonic-gate log_message(MSG_ERROR, 4730Sstevel@tonic-gate "fmt_args: snprintf error\n"); 4740Sstevel@tonic-gate break; 4750Sstevel@tonic-gate case 'x': 4760Sstevel@tonic-gate cnv = 16; 4770Sstevel@tonic-gate if (snprintf(cbuf, cbsize, "%lx", *llarg) < 0) 4780Sstevel@tonic-gate log_message(MSG_ERROR, 4790Sstevel@tonic-gate "fmt_args: snprintf error\n"); 4800Sstevel@tonic-gate break; 4810Sstevel@tonic-gate case 'd': 4820Sstevel@tonic-gate if (snprintf(cbuf, cbsize, "%ld", *llarg) < 0) 4830Sstevel@tonic-gate log_message(MSG_ERROR, 4840Sstevel@tonic-gate "fmt_args: snprintf error\n"); 4850Sstevel@tonic-gate break; 4860Sstevel@tonic-gate default: 4870Sstevel@tonic-gate log_message(MSG_ERROR, 4880Sstevel@tonic-gate "invalid long format type! (l%s)\n", 4890Sstevel@tonic-gate &format); 4900Sstevel@tonic-gate free(cbuf); 4910Sstevel@tonic-gate return; 4920Sstevel@tonic-gate } 4930Sstevel@tonic-gate while ((cbuf[ndigits] != NULL) && 4940Sstevel@tonic-gate (ndigits < cbsize)) { 4950Sstevel@tonic-gate ndigits++; 4960Sstevel@tonic-gate } 4970Sstevel@tonic-gate /* if truncation is necessary, do it */ 4980Sstevel@tonic-gate if (ndigits > cw) { 4990Sstevel@tonic-gate cbuf[cw] = 0; 5000Sstevel@tonic-gate *llarg = strtoll(cbuf, (char **)NULL, cnv); 5010Sstevel@tonic-gate } 5020Sstevel@tonic-gate free(cbuf); 5030Sstevel@tonic-gate } 5040Sstevel@tonic-gate } 5050Sstevel@tonic-gate } 5060Sstevel@tonic-gate 5070Sstevel@tonic-gate /* 5080Sstevel@tonic-gate * fmt_str() 5090Sstevel@tonic-gate * 5100Sstevel@tonic-gate * Extracts text from caller's input buffer, processes explicit 5110Sstevel@tonic-gate * formatting as necessary, and outputs formatted text to caller's 5120Sstevel@tonic-gate * receptacle. 5130Sstevel@tonic-gate * 5140Sstevel@tonic-gate * env - pointer to caller's fcode environment 5150Sstevel@tonic-gate * fmt - pointer to caller's input buffr 5160Sstevel@tonic-gate * fmtbuf - ponter to caller's receptacle buffer 5170Sstevel@tonic-gate * bsize - size of caller's fmtbuf buffer 5180Sstevel@tonic-gate * 5190Sstevel@tonic-gate * This function performs an initial test to determine if caller's 5200Sstevel@tonic-gate * input buffer contains formatting(specified by presence of "%") 5210Sstevel@tonic-gate * in the buffer. If so, validfmt() function is called to verify 5220Sstevel@tonic-gate * the formatting, after which the buffer is processed according 5230Sstevel@tonic-gate * to the field width specified by validfmt() output. Special 5240Sstevel@tonic-gate * processing is required when caller's buffer contains a double 5250Sstevel@tonic-gate * "%" ("%%"), in which case the second "%" is accepted as normal 5260Sstevel@tonic-gate * text. 5270Sstevel@tonic-gate */ 5280Sstevel@tonic-gate 5290Sstevel@tonic-gate static void 5300Sstevel@tonic-gate fmt_str(fcode_env_t *env, char *fmt, char *fmtbuf, int bsize) 5310Sstevel@tonic-gate { 5320Sstevel@tonic-gate char tbuf[CMN_MSG_SIZE]; 5330Sstevel@tonic-gate char *fmptr, *pct; 5340Sstevel@tonic-gate int l, cw, fw, bytes; 5350Sstevel@tonic-gate long arg; 5360Sstevel@tonic-gate long long llarg; 5370Sstevel@tonic-gate 5380Sstevel@tonic-gate *fmtbuf = 0; 5390Sstevel@tonic-gate if ((pct = strchr(fmt, '%')) != 0) { 5400Sstevel@tonic-gate cmn_fmt_t cfstr; 5410Sstevel@tonic-gate int vferr; 5420Sstevel@tonic-gate 5430Sstevel@tonic-gate l = strlen(pct++); 5440Sstevel@tonic-gate vferr = validfmt(pct, &cfstr); 5450Sstevel@tonic-gate if (!vferr) { 5460Sstevel@tonic-gate fw = cfstr.fwidth; 5470Sstevel@tonic-gate cw = cfstr.cwidth; 5480Sstevel@tonic-gate fmptr = &cfstr.format; 5490Sstevel@tonic-gate } else { 5500Sstevel@tonic-gate if (vferr < 0) { 5510Sstevel@tonic-gate log_message(MSG_ERROR, 5520Sstevel@tonic-gate "fmt_str: NULL ptr supplied to validfmt()\n"); 5530Sstevel@tonic-gate return; 5540Sstevel@tonic-gate } 5550Sstevel@tonic-gate 5560Sstevel@tonic-gate bytes = pct - fmt; 5570Sstevel@tonic-gate strncpy(tbuf, fmt, bytes); 5580Sstevel@tonic-gate strncpy(tbuf+bytes, "%", 1); 5590Sstevel@tonic-gate strncpy(tbuf+bytes+1, fmt+bytes, 1); 5600Sstevel@tonic-gate bytes += 2; 5610Sstevel@tonic-gate tbuf[bytes] = 0; 5620Sstevel@tonic-gate 5630Sstevel@tonic-gate log_message(MSG_ERROR, 5640Sstevel@tonic-gate "fmt_str: invalid format type! (%s)\n", 5650Sstevel@tonic-gate tbuf+bytes-3); 5660Sstevel@tonic-gate 5670Sstevel@tonic-gate strncpy(fmtbuf, tbuf, bsize); 5680Sstevel@tonic-gate return; 5690Sstevel@tonic-gate } 5700Sstevel@tonic-gate 5710Sstevel@tonic-gate if (fw > 0) { /* process normal (not long) formats */ 5720Sstevel@tonic-gate bytes = pct - fmt + fw; 5730Sstevel@tonic-gate strncpy(tbuf, fmt, bytes); 5740Sstevel@tonic-gate tbuf[bytes] = 0; 5750Sstevel@tonic-gate } else { 5760Sstevel@tonic-gate /* if here, fw must be a long format */ 5770Sstevel@tonic-gate if (*fmptr == 'p') { 5780Sstevel@tonic-gate bytes = pct - fmt - fw; 5790Sstevel@tonic-gate strncpy(tbuf, fmt, bytes); 5800Sstevel@tonic-gate tbuf[bytes] = 0; 5810Sstevel@tonic-gate } else { 5820Sstevel@tonic-gate bytes = pct - fmt - fw - 2; 5830Sstevel@tonic-gate strncpy(tbuf, fmt, bytes); 5840Sstevel@tonic-gate tbuf[bytes] = 'l'; 5850Sstevel@tonic-gate strncpy(tbuf+bytes+1, fmt+bytes, 2); 5860Sstevel@tonic-gate tbuf[bytes+1+2] = 0; 5870Sstevel@tonic-gate } 5880Sstevel@tonic-gate } 5890Sstevel@tonic-gate 5900Sstevel@tonic-gate /* if more input buffer to process, recurse */ 5910Sstevel@tonic-gate if ((l - abs(fw)) != 0) { 5920Sstevel@tonic-gate fmt_str(env, pct+abs(fw), (tbuf + strlen(tbuf)), 5930Sstevel@tonic-gate CMN_MSG_SIZE - strlen(tbuf)); 5940Sstevel@tonic-gate } 5950Sstevel@tonic-gate 5960Sstevel@tonic-gate /* call to extract args for snprintf() calls below */ 5970Sstevel@tonic-gate fmt_args(env, cw, fw, *fmptr, &arg, &llarg); 5980Sstevel@tonic-gate 5990Sstevel@tonic-gate if (fw > 0) { /* process normal (not long) formats */ 6000Sstevel@tonic-gate switch (*fmptr) { 6010Sstevel@tonic-gate case 'd': 6020Sstevel@tonic-gate case 'x': 6030Sstevel@tonic-gate case 'c': 6040Sstevel@tonic-gate case 's': 6050Sstevel@tonic-gate case 'p': 6060Sstevel@tonic-gate (void) snprintf(fmtbuf, bsize, tbuf, arg); 6070Sstevel@tonic-gate break; 6080Sstevel@tonic-gate case '%': 6090Sstevel@tonic-gate (void) snprintf(fmtbuf, bsize, tbuf); 6100Sstevel@tonic-gate break; 6110Sstevel@tonic-gate default: 6120Sstevel@tonic-gate log_message(MSG_ERROR, 6130Sstevel@tonic-gate "fmt_str: invalid format (%s)\n", 6140Sstevel@tonic-gate fmptr); 6150Sstevel@tonic-gate return; 6160Sstevel@tonic-gate } 6170Sstevel@tonic-gate 6180Sstevel@tonic-gate } else /* process long formats */ 6190Sstevel@tonic-gate (void) snprintf(fmtbuf, bsize, tbuf, llarg); 6200Sstevel@tonic-gate 6210Sstevel@tonic-gate } else 6220Sstevel@tonic-gate strncpy(fmtbuf, fmt, bsize); 6230Sstevel@tonic-gate } 6240Sstevel@tonic-gate 6250Sstevel@tonic-gate /* 6260Sstevel@tonic-gate * fc_cmn_append() 6270Sstevel@tonic-gate * 6280Sstevel@tonic-gate * Pops data stack to obtain message text, and calls fmt_str() 6290Sstevel@tonic-gate * function to perform any message formatting necessary. 6300Sstevel@tonic-gate * 6310Sstevel@tonic-gate * This function is called from fc_cmn_end() or directly in 6320Sstevel@tonic-gate * processing a cmn-append token. Since a pre-existing message 6330Sstevel@tonic-gate * context is assumed, initial checking is performed to verify 6340Sstevel@tonic-gate * its existence. 6350Sstevel@tonic-gate */ 6360Sstevel@tonic-gate 6370Sstevel@tonic-gate void 6380Sstevel@tonic-gate fc_cmn_append(fcode_env_t *env) 6390Sstevel@tonic-gate { 6400Sstevel@tonic-gate int len; 6410Sstevel@tonic-gate char *str; 6420Sstevel@tonic-gate 6430Sstevel@tonic-gate if (root == NULL) { 6440Sstevel@tonic-gate log_message(MSG_ERROR, 6450Sstevel@tonic-gate "fc_cmn_append: no message context for append\n"); 6460Sstevel@tonic-gate return; 6470Sstevel@tonic-gate } 6480Sstevel@tonic-gate 6490Sstevel@tonic-gate len = POP(DS); 6500Sstevel@tonic-gate str = (char *)POP(DS); 6510Sstevel@tonic-gate 6520Sstevel@tonic-gate if ((root->len + len) < CMN_MSG_SIZE) { 6530Sstevel@tonic-gate fmt_str(env, str, root->buf+root->len, CMN_MSG_SIZE - 6540Sstevel@tonic-gate root->len); 6550Sstevel@tonic-gate root->len += len; 6560Sstevel@tonic-gate } else 6570Sstevel@tonic-gate log_message(MSG_ERROR, 6580Sstevel@tonic-gate "fc_cmn_append: append exceeds max msg size\n"); 6590Sstevel@tonic-gate } 6600Sstevel@tonic-gate 6610Sstevel@tonic-gate /* 6620Sstevel@tonic-gate * fc_cmn_end() 6630Sstevel@tonic-gate * 6640Sstevel@tonic-gate * Process ]cmn-end token to log the message initiated by a preceeding 6650Sstevel@tonic-gate * fc_cmn_start() call. 6660Sstevel@tonic-gate * 6670Sstevel@tonic-gate * Since nested cmn-xxx[ calls are supported, a test is made to determine 6680Sstevel@tonic-gate * if this is the final cmn-end of a nested sequence. If so, or if 6690Sstevel@tonic-gate * there was no nesting, log_message() is called with the appropriate 6700Sstevel@tonic-gate * text buffer. Otherwise, the root variable is adjusted to point to 6710Sstevel@tonic-gate * the preceeding message in the sequence and links in the list are 6720Sstevel@tonic-gate * updated. No logging is performed until the final ]cmn-end of the 6730Sstevel@tonic-gate * sequence is processed; then, messages are logged in FIFO order. 6740Sstevel@tonic-gate */ 6750Sstevel@tonic-gate void 6760Sstevel@tonic-gate fc_cmn_end(fcode_env_t *env) 6770Sstevel@tonic-gate { 6780Sstevel@tonic-gate cmn_msg_t *old; 6790Sstevel@tonic-gate 6800Sstevel@tonic-gate if (root == 0) { 6810Sstevel@tonic-gate log_message(MSG_ERROR, "]cmn-end call w/o buffer\n"); 6820Sstevel@tonic-gate return; 6830Sstevel@tonic-gate } 6840Sstevel@tonic-gate 6850Sstevel@tonic-gate fc_cmn_append(env); 6860Sstevel@tonic-gate 6870Sstevel@tonic-gate if (root->prev == 0) { 6880Sstevel@tonic-gate cmn_msg_t *next; 6890Sstevel@tonic-gate do { 6900Sstevel@tonic-gate log_message(root->level, "%s\n", root->buf); 6910Sstevel@tonic-gate next = root->next; 6920Sstevel@tonic-gate free(root); 6930Sstevel@tonic-gate root = next; 6940Sstevel@tonic-gate } while (root); 6950Sstevel@tonic-gate } else { 6960Sstevel@tonic-gate old = root->prev; 6970Sstevel@tonic-gate old->next = root; 6980Sstevel@tonic-gate root = old; 6990Sstevel@tonic-gate } 7000Sstevel@tonic-gate } 7010Sstevel@tonic-gate 7020Sstevel@tonic-gate /* 7030Sstevel@tonic-gate * fc_cmn_start() 7040Sstevel@tonic-gate * 7050Sstevel@tonic-gate * Generic function to begin a common message. 7060Sstevel@tonic-gate * 7070Sstevel@tonic-gate * Allocates a new cmn_msg_t to associate with the message, and sets 7080Sstevel@tonic-gate * up initial text as specified by callers' inputs: 7090Sstevel@tonic-gate * 7100Sstevel@tonic-gate * env - pointer to caller's fcode environment 7110Sstevel@tonic-gate * head - pointer to initial text portion of the message 7120Sstevel@tonic-gate * path - flag to indicate if a device path is to be generated 7130Sstevel@tonic-gate */ 7140Sstevel@tonic-gate static void 7150Sstevel@tonic-gate fc_cmn_start(fcode_env_t *env, char *head, int path) 7160Sstevel@tonic-gate { 7170Sstevel@tonic-gate cmn_msg_t *new; 7180Sstevel@tonic-gate char *dpath; 7190Sstevel@tonic-gate 7200Sstevel@tonic-gate new = MALLOC(sizeof (cmn_msg_t)); 7210Sstevel@tonic-gate new->prev = root; 7220Sstevel@tonic-gate if (root != 0) 7230Sstevel@tonic-gate root->next = new; 7240Sstevel@tonic-gate strcpy(new->buf, head); 7250Sstevel@tonic-gate new->len = strlen(head); 7260Sstevel@tonic-gate if (path && env->current_device) { 7270Sstevel@tonic-gate dpath = get_path(env, env->current_device); 7280Sstevel@tonic-gate strcpy(new->buf+new->len, dpath); 7290Sstevel@tonic-gate new->len += strlen(dpath); 7300Sstevel@tonic-gate strncpy(new->buf+new->len++, ": ", 2); 7310Sstevel@tonic-gate ++new->len; 7320Sstevel@tonic-gate free(dpath); 7330Sstevel@tonic-gate } 7340Sstevel@tonic-gate new->level = cmn_msg_level; 7350Sstevel@tonic-gate new->next = NULL; 7360Sstevel@tonic-gate root = new; 7370Sstevel@tonic-gate } 7380Sstevel@tonic-gate 7390Sstevel@tonic-gate /* 7400Sstevel@tonic-gate * fc_cmn_type() 7410Sstevel@tonic-gate * 7420Sstevel@tonic-gate * Process cmn-type[ token. 7430Sstevel@tonic-gate * 7440Sstevel@tonic-gate * Invokes fc_cmn_start() to create a message containing blank 7450Sstevel@tonic-gate * header and no device path information. 7460Sstevel@tonic-gate */ 7470Sstevel@tonic-gate void 7480Sstevel@tonic-gate fc_cmn_type(fcode_env_t *env) 7490Sstevel@tonic-gate { 7500Sstevel@tonic-gate cmn_msg_level = MSG_INFO; 7510Sstevel@tonic-gate fc_cmn_start(env, "", 0); 7520Sstevel@tonic-gate } 7530Sstevel@tonic-gate 7540Sstevel@tonic-gate /* 7550Sstevel@tonic-gate * fc_cmn_msg() 7560Sstevel@tonic-gate * 7570Sstevel@tonic-gate * Process cmn-msg[ token. 7580Sstevel@tonic-gate * 7590Sstevel@tonic-gate * Invokes fc_cmn_start() to create a message containing blank 7600Sstevel@tonic-gate * header but specifying device path information. 7610Sstevel@tonic-gate */ 7620Sstevel@tonic-gate void 7630Sstevel@tonic-gate fc_cmn_msg(fcode_env_t *env) 7640Sstevel@tonic-gate { 7650Sstevel@tonic-gate 7660Sstevel@tonic-gate cmn_msg_level = MSG_INFO; 7670Sstevel@tonic-gate fc_cmn_start(env, "", 1); 7680Sstevel@tonic-gate } 7690Sstevel@tonic-gate 7700Sstevel@tonic-gate /* 7710Sstevel@tonic-gate * fc_cmn_note() 7720Sstevel@tonic-gate * 7730Sstevel@tonic-gate * Process cmn-note[ token. 7740Sstevel@tonic-gate * 7750Sstevel@tonic-gate * Invokes fc_cmn_start() to create a message with NOTICE stamping in 7760Sstevel@tonic-gate * the header and specification of device path information. 7770Sstevel@tonic-gate */ 7780Sstevel@tonic-gate void 7790Sstevel@tonic-gate fc_cmn_note(fcode_env_t *env) 7800Sstevel@tonic-gate { 7810Sstevel@tonic-gate cmn_msg_level = MSG_NOTE; 7820Sstevel@tonic-gate fc_cmn_start(env, "NOTICE: ", 1); 7830Sstevel@tonic-gate } 7840Sstevel@tonic-gate 7850Sstevel@tonic-gate /* 7860Sstevel@tonic-gate * fc_cmn_warn() 7870Sstevel@tonic-gate * 7880Sstevel@tonic-gate * Process cmn-warn[ token. 7890Sstevel@tonic-gate * 7900Sstevel@tonic-gate * Invokes fc_cmn_start() to create a message with WARNING stamping in 7910Sstevel@tonic-gate * the header and specification of device path information. 7920Sstevel@tonic-gate */ 7930Sstevel@tonic-gate void 7940Sstevel@tonic-gate fc_cmn_warn(fcode_env_t *env) 7950Sstevel@tonic-gate { 7960Sstevel@tonic-gate cmn_msg_level = MSG_WARN; 7970Sstevel@tonic-gate fc_cmn_start(env, "WARNING: ", 1); 7980Sstevel@tonic-gate } 7990Sstevel@tonic-gate 8000Sstevel@tonic-gate /* 8010Sstevel@tonic-gate * fc_cmn_error() 8020Sstevel@tonic-gate * 8030Sstevel@tonic-gate * Process cmn-error[ token. 8040Sstevel@tonic-gate * 8050Sstevel@tonic-gate * Invokes fc_cmn_start() to create a message with ERROR stamping in 8060Sstevel@tonic-gate * the header and specification of device path information. 8070Sstevel@tonic-gate */ 8080Sstevel@tonic-gate void 8090Sstevel@tonic-gate fc_cmn_error(fcode_env_t *env) 8100Sstevel@tonic-gate { 8110Sstevel@tonic-gate cmn_msg_level = MSG_ERROR; 8120Sstevel@tonic-gate fc_cmn_start(env, "ERROR: ", 1); 8130Sstevel@tonic-gate } 8140Sstevel@tonic-gate 8150Sstevel@tonic-gate /* 8160Sstevel@tonic-gate * fc_cmn_fatal() 8170Sstevel@tonic-gate * 8180Sstevel@tonic-gate * Process cmn-fatal[ token. 8190Sstevel@tonic-gate * 8200Sstevel@tonic-gate * Invokes fc_cmn_start() to create a message with FATAL stamping in 8210Sstevel@tonic-gate * the header and specification of device path information. 8220Sstevel@tonic-gate */ 8230Sstevel@tonic-gate void 8240Sstevel@tonic-gate fc_cmn_fatal(fcode_env_t *env) 8250Sstevel@tonic-gate { 8260Sstevel@tonic-gate cmn_msg_level = MSG_FATAL; 8270Sstevel@tonic-gate fc_cmn_start(env, "FATAL: ", 1); 8280Sstevel@tonic-gate } 8290Sstevel@tonic-gate 8300Sstevel@tonic-gate #pragma init(_init) 8310Sstevel@tonic-gate 8320Sstevel@tonic-gate static void 8330Sstevel@tonic-gate _init(void) 8340Sstevel@tonic-gate { 8350Sstevel@tonic-gate fcode_env_t *env = initial_env; 8360Sstevel@tonic-gate ASSERT(env); 8370Sstevel@tonic-gate NOTICE; 8380Sstevel@tonic-gate 8390Sstevel@tonic-gate ANSI(0x088, 0, "span", span); 8400Sstevel@tonic-gate ANSI(0x08a, 0, "expect", expect); 8410Sstevel@tonic-gate 8420Sstevel@tonic-gate ANSI(0x08d, 0, "key?", keyquestion); 8430Sstevel@tonic-gate ANSI(0x08e, 0, "key", key); 8440Sstevel@tonic-gate ANSI(0x08f, 0, "emit", emit); 8450Sstevel@tonic-gate ANSI(0x090, 0, "type", type); 8460Sstevel@tonic-gate ANSI(0x091, 0, "(cr", paren_cr); 8470Sstevel@tonic-gate ANSI(0x092, 0, "cr", fc_crlf); 8480Sstevel@tonic-gate ANSI(0x093, 0, "#out", fc_num_out); 8490Sstevel@tonic-gate ANSI(0x094, 0, "#line", fc_num_line); 8500Sstevel@tonic-gate 8510Sstevel@tonic-gate FCODE(0x125, 0, "get-msecs", do_get_msecs); 8520Sstevel@tonic-gate FCODE(0x126, 0, "ms", do_ms); 8530Sstevel@tonic-gate 8540Sstevel@tonic-gate FORTH(0, "verbose-emit", do_verbose_emit); 8550Sstevel@tonic-gate FCODE(0x7e9, 0, "cmn-fatal[", fc_cmn_fatal); 8560Sstevel@tonic-gate FCODE(0x7ea, 0, "cmn-error[", fc_cmn_error); 8570Sstevel@tonic-gate FCODE(0x7eb, 0, "cmn-warn[", fc_cmn_warn); 8580Sstevel@tonic-gate FCODE(0x7ec, 0, "cmn-note[", fc_cmn_note); 8590Sstevel@tonic-gate FCODE(0x7ed, 0, "cmn-type[", fc_cmn_type); 8600Sstevel@tonic-gate FCODE(0x7ee, 0, "cmn-append", fc_cmn_append); 8610Sstevel@tonic-gate FCODE(0x7ef, 0, "]cmn-end", fc_cmn_end); 8620Sstevel@tonic-gate FCODE(0x7f0, 0, "cmn-msg[", fc_cmn_msg); 8630Sstevel@tonic-gate } 864