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
do_verbose_emit(fcode_env_t * env)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
do_emit(fcode_env_t * env,uchar_t c)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
system_message(fcode_env_t * env,char * msg)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
emit(fcode_env_t * env)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
keyquestion(fcode_env_t * env)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
key(fcode_env_t * env)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
type(fcode_env_t * env)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
paren_cr(fcode_env_t * env)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
fc_crlf(fcode_env_t * env)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
fc_num_out(fcode_env_t * env)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
fc_num_line(fcode_env_t * env)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
expect(fcode_env_t * env)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
span(fcode_env_t * env)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
do_ms(fcode_env_t * env)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
do_get_msecs(fcode_env_t * env)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
validfmt(char * fmt,cmn_fmt_t * cfstr)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
fmt_args(fcode_env_t * env,int cw,int fw,char format,long * arg,long long * llarg)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
fmt_str(fcode_env_t * env,char * fmt,char * fmtbuf,int bsize)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
fc_cmn_append(fcode_env_t * env)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
fc_cmn_end(fcode_env_t * env)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
fc_cmn_start(fcode_env_t * env,char * head,int path)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
fc_cmn_type(fcode_env_t * env)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
fc_cmn_msg(fcode_env_t * env)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
fc_cmn_note(fcode_env_t * env)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
fc_cmn_warn(fcode_env_t * env)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
fc_cmn_error(fcode_env_t * env)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
fc_cmn_fatal(fcode_env_t * env)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
_init(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