17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate #include <ctype.h>
307c478bd9Sstevel@tonic-gate #include <stdio.h>
317c478bd9Sstevel@tonic-gate #include <unistd.h>
327c478bd9Sstevel@tonic-gate #include <stdlib.h>
337c478bd9Sstevel@tonic-gate #include <string.h>
347c478bd9Sstevel@tonic-gate #include <sys/time.h>
357c478bd9Sstevel@tonic-gate
367c478bd9Sstevel@tonic-gate #include <fcode/private.h>
377c478bd9Sstevel@tonic-gate #include <fcode/log.h>
387c478bd9Sstevel@tonic-gate
397c478bd9Sstevel@tonic-gate
407c478bd9Sstevel@tonic-gate static variable_t verbose_emit;
417c478bd9Sstevel@tonic-gate
427c478bd9Sstevel@tonic-gate void
do_verbose_emit(fcode_env_t * env)437c478bd9Sstevel@tonic-gate do_verbose_emit(fcode_env_t *env)
447c478bd9Sstevel@tonic-gate {
457c478bd9Sstevel@tonic-gate verbose_emit ^= 1;
467c478bd9Sstevel@tonic-gate }
477c478bd9Sstevel@tonic-gate
487c478bd9Sstevel@tonic-gate /*
497c478bd9Sstevel@tonic-gate * Internal "emit".
507c478bd9Sstevel@tonic-gate * Note log_emit gathers up characters and issues a syslog or write to
517c478bd9Sstevel@tonic-gate * error log file if enabled.
527c478bd9Sstevel@tonic-gate */
537c478bd9Sstevel@tonic-gate void
do_emit(fcode_env_t * env,uchar_t c)547c478bd9Sstevel@tonic-gate do_emit(fcode_env_t *env, uchar_t c)
557c478bd9Sstevel@tonic-gate {
567c478bd9Sstevel@tonic-gate if (verbose_emit)
577c478bd9Sstevel@tonic-gate log_message(MSG_ERROR, "emit(%x)\n", c);
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate if (c == '\n') {
607c478bd9Sstevel@tonic-gate env->output_column = 0;
617c478bd9Sstevel@tonic-gate env->output_line++;
627c478bd9Sstevel@tonic-gate } else if (c == '\r')
637c478bd9Sstevel@tonic-gate env->output_column = 0;
647c478bd9Sstevel@tonic-gate else
657c478bd9Sstevel@tonic-gate env->output_column++;
667c478bd9Sstevel@tonic-gate if (isatty(fileno(stdout))) {
677c478bd9Sstevel@tonic-gate if ((c >= 0x20 && c <= 0x7f) || c == '\n' || c == '\r' ||
687c478bd9Sstevel@tonic-gate c == '\b')
697c478bd9Sstevel@tonic-gate putchar(c);
70*360e6f5eSmathue else if (c < 0x20)
717c478bd9Sstevel@tonic-gate printf("@%c", c + '@');
727c478bd9Sstevel@tonic-gate else
737c478bd9Sstevel@tonic-gate printf("\\%x", c);
747c478bd9Sstevel@tonic-gate fflush(stdout);
757c478bd9Sstevel@tonic-gate }
767c478bd9Sstevel@tonic-gate log_emit(c);
777c478bd9Sstevel@tonic-gate }
787c478bd9Sstevel@tonic-gate
797c478bd9Sstevel@tonic-gate void
system_message(fcode_env_t * env,char * msg)807c478bd9Sstevel@tonic-gate system_message(fcode_env_t *env, char *msg)
817c478bd9Sstevel@tonic-gate {
827c478bd9Sstevel@tonic-gate throw_from_fclib(env, 1, msg);
837c478bd9Sstevel@tonic-gate }
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate void
emit(fcode_env_t * env)867c478bd9Sstevel@tonic-gate emit(fcode_env_t *env)
877c478bd9Sstevel@tonic-gate {
887c478bd9Sstevel@tonic-gate fstack_t d;
897c478bd9Sstevel@tonic-gate
907c478bd9Sstevel@tonic-gate CHECK_DEPTH(env, 1, "emit");
917c478bd9Sstevel@tonic-gate d = POP(DS);
927c478bd9Sstevel@tonic-gate do_emit(env, d);
937c478bd9Sstevel@tonic-gate }
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate #include <sys/time.h>
967c478bd9Sstevel@tonic-gate
977c478bd9Sstevel@tonic-gate /*
987c478bd9Sstevel@tonic-gate * 'key?' - abort if stdin is not a tty.
997c478bd9Sstevel@tonic-gate */
1007c478bd9Sstevel@tonic-gate void
keyquestion(fcode_env_t * env)1017c478bd9Sstevel@tonic-gate keyquestion(fcode_env_t *env)
1027c478bd9Sstevel@tonic-gate {
1037c478bd9Sstevel@tonic-gate struct timeval timeval;
1047c478bd9Sstevel@tonic-gate fd_set readfds;
1057c478bd9Sstevel@tonic-gate int ret;
1067c478bd9Sstevel@tonic-gate
1077c478bd9Sstevel@tonic-gate if (isatty(fileno(stdin))) {
1087c478bd9Sstevel@tonic-gate FD_ZERO(&readfds);
1097c478bd9Sstevel@tonic-gate FD_SET(fileno(stdin), &readfds);
1107c478bd9Sstevel@tonic-gate timeval.tv_sec = 0;
1117c478bd9Sstevel@tonic-gate timeval.tv_usec = 1000;
1127c478bd9Sstevel@tonic-gate ret = select(fileno(stdin) + 1, &readfds, NULL, NULL, &timeval);
1137c478bd9Sstevel@tonic-gate if (FD_ISSET(fileno(stdin), &readfds))
1147c478bd9Sstevel@tonic-gate PUSH(DS, TRUE);
1157c478bd9Sstevel@tonic-gate else
1167c478bd9Sstevel@tonic-gate PUSH(DS, FALSE);
1177c478bd9Sstevel@tonic-gate } else
1187c478bd9Sstevel@tonic-gate forth_abort(env, "'key?' called in non-interactive mode");
1197c478bd9Sstevel@tonic-gate }
1207c478bd9Sstevel@tonic-gate
1217c478bd9Sstevel@tonic-gate /*
1227c478bd9Sstevel@tonic-gate * 'key' - abort if stdin is not a tty, will block on read if char not avail.
1237c478bd9Sstevel@tonic-gate */
1247c478bd9Sstevel@tonic-gate void
key(fcode_env_t * env)1257c478bd9Sstevel@tonic-gate key(fcode_env_t *env)
1267c478bd9Sstevel@tonic-gate {
1277c478bd9Sstevel@tonic-gate uchar_t c;
1287c478bd9Sstevel@tonic-gate
1297c478bd9Sstevel@tonic-gate if (isatty(fileno(stdin))) {
1307c478bd9Sstevel@tonic-gate read(fileno(stdin), &c, 1);
1317c478bd9Sstevel@tonic-gate PUSH(DS, c);
1327c478bd9Sstevel@tonic-gate } else
1337c478bd9Sstevel@tonic-gate forth_abort(env, "'key' called in non-interactive mode");
1347c478bd9Sstevel@tonic-gate }
1357c478bd9Sstevel@tonic-gate
1367c478bd9Sstevel@tonic-gate void
type(fcode_env_t * env)1377c478bd9Sstevel@tonic-gate type(fcode_env_t *env)
1387c478bd9Sstevel@tonic-gate {
1397c478bd9Sstevel@tonic-gate int len;
1407c478bd9Sstevel@tonic-gate char *ptr;
1417c478bd9Sstevel@tonic-gate
1427c478bd9Sstevel@tonic-gate CHECK_DEPTH(env, 2, "type");
1437c478bd9Sstevel@tonic-gate ptr = pop_a_string(env, &len);
1447c478bd9Sstevel@tonic-gate while (len--)
1457c478bd9Sstevel@tonic-gate do_emit(env, *ptr++);
1467c478bd9Sstevel@tonic-gate }
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gate void
paren_cr(fcode_env_t * env)1497c478bd9Sstevel@tonic-gate paren_cr(fcode_env_t *env)
1507c478bd9Sstevel@tonic-gate {
1517c478bd9Sstevel@tonic-gate do_emit(env, '\r');
1527c478bd9Sstevel@tonic-gate }
1537c478bd9Sstevel@tonic-gate
1547c478bd9Sstevel@tonic-gate void
fc_crlf(fcode_env_t * env)1557c478bd9Sstevel@tonic-gate fc_crlf(fcode_env_t *env)
1567c478bd9Sstevel@tonic-gate {
1577c478bd9Sstevel@tonic-gate do_emit(env, '\n');
1587c478bd9Sstevel@tonic-gate }
1597c478bd9Sstevel@tonic-gate
1607c478bd9Sstevel@tonic-gate void
fc_num_out(fcode_env_t * env)1617c478bd9Sstevel@tonic-gate fc_num_out(fcode_env_t *env)
1627c478bd9Sstevel@tonic-gate {
1637c478bd9Sstevel@tonic-gate PUSH(DS, (fstack_t)(&env->output_column));
1647c478bd9Sstevel@tonic-gate }
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate void
fc_num_line(fcode_env_t * env)1677c478bd9Sstevel@tonic-gate fc_num_line(fcode_env_t *env)
1687c478bd9Sstevel@tonic-gate {
1697c478bd9Sstevel@tonic-gate PUSH(DS, (fstack_t)(&env->output_line));
1707c478bd9Sstevel@tonic-gate }
1717c478bd9Sstevel@tonic-gate
1727c478bd9Sstevel@tonic-gate void
expect(fcode_env_t * env)1737c478bd9Sstevel@tonic-gate expect(fcode_env_t *env)
1747c478bd9Sstevel@tonic-gate {
1757c478bd9Sstevel@tonic-gate char *buf, *rbuf;
1767c478bd9Sstevel@tonic-gate int len;
1777c478bd9Sstevel@tonic-gate
1787c478bd9Sstevel@tonic-gate CHECK_DEPTH(env, 2, "expect");
1797c478bd9Sstevel@tonic-gate buf = pop_a_string(env, &len);
1807c478bd9Sstevel@tonic-gate read_line(env);
1817c478bd9Sstevel@tonic-gate rbuf = pop_a_string(env, NULL);
1827c478bd9Sstevel@tonic-gate if (rbuf) {
1837c478bd9Sstevel@tonic-gate strcpy(buf, rbuf);
1847c478bd9Sstevel@tonic-gate env->span = strlen(buf);
1857c478bd9Sstevel@tonic-gate } else
1867c478bd9Sstevel@tonic-gate env->span = 0;
1877c478bd9Sstevel@tonic-gate }
1887c478bd9Sstevel@tonic-gate
1897c478bd9Sstevel@tonic-gate void
span(fcode_env_t * env)1907c478bd9Sstevel@tonic-gate span(fcode_env_t *env)
1917c478bd9Sstevel@tonic-gate {
1927c478bd9Sstevel@tonic-gate PUSH(DS, (fstack_t)&env->span);
1937c478bd9Sstevel@tonic-gate }
1947c478bd9Sstevel@tonic-gate
1957c478bd9Sstevel@tonic-gate void
do_ms(fcode_env_t * env)1967c478bd9Sstevel@tonic-gate do_ms(fcode_env_t *env)
1977c478bd9Sstevel@tonic-gate {
1987c478bd9Sstevel@tonic-gate fstack_t d;
1997c478bd9Sstevel@tonic-gate timespec_t rqtp;
2007c478bd9Sstevel@tonic-gate
2017c478bd9Sstevel@tonic-gate CHECK_DEPTH(env, 1, "ms");
2027c478bd9Sstevel@tonic-gate d = POP(DS);
2037c478bd9Sstevel@tonic-gate if (d) {
2047c478bd9Sstevel@tonic-gate rqtp.tv_sec = 0;
2057c478bd9Sstevel@tonic-gate rqtp.tv_nsec = d*1000*1000;
2067c478bd9Sstevel@tonic-gate nanosleep(&rqtp, 0);
2077c478bd9Sstevel@tonic-gate }
2087c478bd9Sstevel@tonic-gate }
2097c478bd9Sstevel@tonic-gate
2107c478bd9Sstevel@tonic-gate void
do_get_msecs(fcode_env_t * env)2117c478bd9Sstevel@tonic-gate do_get_msecs(fcode_env_t *env)
2127c478bd9Sstevel@tonic-gate {
2137c478bd9Sstevel@tonic-gate struct timeval tp;
2147c478bd9Sstevel@tonic-gate long ms;
2157c478bd9Sstevel@tonic-gate timespec_t rqtp;
2167c478bd9Sstevel@tonic-gate
2177c478bd9Sstevel@tonic-gate gettimeofday(&tp, NULL);
2187c478bd9Sstevel@tonic-gate ms = (tp.tv_usec/1000) + (tp.tv_sec * 1000);
2197c478bd9Sstevel@tonic-gate PUSH(DS, (fstack_t)ms);
2207c478bd9Sstevel@tonic-gate rqtp.tv_sec = 0;
2217c478bd9Sstevel@tonic-gate rqtp.tv_nsec = 1000*1000;
2227c478bd9Sstevel@tonic-gate nanosleep(&rqtp, 0);
2237c478bd9Sstevel@tonic-gate }
2247c478bd9Sstevel@tonic-gate
2257c478bd9Sstevel@tonic-gate #define CMN_MSG_SIZE 256
2267c478bd9Sstevel@tonic-gate #define CMN_MAX_DIGITS 3
2277c478bd9Sstevel@tonic-gate
2287c478bd9Sstevel@tonic-gate typedef struct CMN_MSG_T cmn_msg_t;
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate struct CMN_MSG_T {
2317c478bd9Sstevel@tonic-gate char buf[CMN_MSG_SIZE];
2327c478bd9Sstevel@tonic-gate int level;
2337c478bd9Sstevel@tonic-gate int len;
2347c478bd9Sstevel@tonic-gate cmn_msg_t *prev;
2357c478bd9Sstevel@tonic-gate cmn_msg_t *next;
2367c478bd9Sstevel@tonic-gate };
2377c478bd9Sstevel@tonic-gate
2387c478bd9Sstevel@tonic-gate typedef struct CMN_FMT_T cmn_fmt_t;
2397c478bd9Sstevel@tonic-gate
2407c478bd9Sstevel@tonic-gate struct CMN_FMT_T {
2417c478bd9Sstevel@tonic-gate int fwidth; /* format field width */
2427c478bd9Sstevel@tonic-gate int cwidth; /* column width specified in format */
2437c478bd9Sstevel@tonic-gate char format; /* format type */
2447c478bd9Sstevel@tonic-gate };
2457c478bd9Sstevel@tonic-gate
2467c478bd9Sstevel@tonic-gate static cmn_msg_t *root = NULL;
2477c478bd9Sstevel@tonic-gate static int cmn_msg_level = 0;
2487c478bd9Sstevel@tonic-gate
2497c478bd9Sstevel@tonic-gate /*
2507c478bd9Sstevel@tonic-gate * validfmt()
2517c478bd9Sstevel@tonic-gate *
2527c478bd9Sstevel@tonic-gate * Called by fmt_str() function to validate and extract formatting
2537c478bd9Sstevel@tonic-gate * information from the supplied input buffer.
2547c478bd9Sstevel@tonic-gate *
2557c478bd9Sstevel@tonic-gate * Supported formats are:
2567c478bd9Sstevel@tonic-gate * %c - character
2577c478bd9Sstevel@tonic-gate * %d - signed decimal
2587c478bd9Sstevel@tonic-gate * %x - unsigned hex
2597c478bd9Sstevel@tonic-gate * %s - string
2607c478bd9Sstevel@tonic-gate * %ld - signed 64 bit data
2617c478bd9Sstevel@tonic-gate * %lx - unsigned 64 bit data
2627c478bd9Sstevel@tonic-gate * %p - unsigned 64 bit data(pointer)
2637c478bd9Sstevel@tonic-gate * %% - print as single "%" character
2647c478bd9Sstevel@tonic-gate *
2657c478bd9Sstevel@tonic-gate * Return values are:
2667c478bd9Sstevel@tonic-gate * 0 - valid formatting
2677c478bd9Sstevel@tonic-gate * 1 - invalid formatting found in the input buffer
2687c478bd9Sstevel@tonic-gate * -1 - NULL pointer passed in for caller's receptacle
2697c478bd9Sstevel@tonic-gate *
2707c478bd9Sstevel@tonic-gate *
2717c478bd9Sstevel@tonic-gate * For valid formatting, caller's supplied cmn_fmt_t elements are
2727c478bd9Sstevel@tonic-gate * filled in:
2737c478bd9Sstevel@tonic-gate * fwidth:
2747c478bd9Sstevel@tonic-gate * > 0 - returned value is the field width
2757c478bd9Sstevel@tonic-gate * < 0 - returned value is negation of field width for
2767c478bd9Sstevel@tonic-gate * 64 bit data formats
2777c478bd9Sstevel@tonic-gate * cwidth:
2787c478bd9Sstevel@tonic-gate * formatted column width(if specified), otherwise 0
2797c478bd9Sstevel@tonic-gate *
2807c478bd9Sstevel@tonic-gate * format:
2817c478bd9Sstevel@tonic-gate * contains the formatting(single) character
2827c478bd9Sstevel@tonic-gate */
2837c478bd9Sstevel@tonic-gate static int
validfmt(char * fmt,cmn_fmt_t * cfstr)2847c478bd9Sstevel@tonic-gate validfmt(char *fmt, cmn_fmt_t *cfstr)
2857c478bd9Sstevel@tonic-gate {
2867c478bd9Sstevel@tonic-gate int isll = 0;
2877c478bd9Sstevel@tonic-gate int *fwidth, *cwidth;
2887c478bd9Sstevel@tonic-gate char *format;
2897c478bd9Sstevel@tonic-gate char *dig1, *dig2;
2907c478bd9Sstevel@tonic-gate char cdigs[CMN_MAX_DIGITS+1];
2917c478bd9Sstevel@tonic-gate
2927c478bd9Sstevel@tonic-gate if (cfstr == NULL)
2937c478bd9Sstevel@tonic-gate return (-1);
2947c478bd9Sstevel@tonic-gate
2957c478bd9Sstevel@tonic-gate fwidth = &cfstr->fwidth;
2967c478bd9Sstevel@tonic-gate cwidth = &cfstr->cwidth;
2977c478bd9Sstevel@tonic-gate format = &cfstr->format;
2987c478bd9Sstevel@tonic-gate *fwidth = *cwidth = 0;
2997c478bd9Sstevel@tonic-gate *format = NULL;
3007c478bd9Sstevel@tonic-gate dig1 = dig2 = NULL;
3017c478bd9Sstevel@tonic-gate
3027c478bd9Sstevel@tonic-gate /* check for left justification character */
3037c478bd9Sstevel@tonic-gate if (*fmt == '-') {
3047c478bd9Sstevel@tonic-gate fmt++;
3057c478bd9Sstevel@tonic-gate (*fwidth)++;
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate /* check for column width specification */
3087c478bd9Sstevel@tonic-gate if (isdigit(*fmt))
3097c478bd9Sstevel@tonic-gate dig1 = fmt; /* save ptr to first digit */
3107c478bd9Sstevel@tonic-gate while (isdigit(*fmt)) {
3117c478bd9Sstevel@tonic-gate fmt++;
3127c478bd9Sstevel@tonic-gate (*fwidth)++;
3137c478bd9Sstevel@tonic-gate }
3147c478bd9Sstevel@tonic-gate /* if ljust specified w/o size, return format error */
3157c478bd9Sstevel@tonic-gate if (*fwidth == 1) {
3167c478bd9Sstevel@tonic-gate return (1);
3177c478bd9Sstevel@tonic-gate }
3187c478bd9Sstevel@tonic-gate dig2 = fmt; /* save ptr to last digit + 1 */
3197c478bd9Sstevel@tonic-gate } else {
3207c478bd9Sstevel@tonic-gate /* check for column width specification */
3217c478bd9Sstevel@tonic-gate if (isdigit(*fmt)) {
3227c478bd9Sstevel@tonic-gate dig1 = fmt; /* save ptr to first digit */
3237c478bd9Sstevel@tonic-gate while (isdigit(*fmt)) {
3247c478bd9Sstevel@tonic-gate fmt++;
3257c478bd9Sstevel@tonic-gate (*fwidth)++;
3267c478bd9Sstevel@tonic-gate }
3277c478bd9Sstevel@tonic-gate dig2 = fmt; /* save ptr to last digit + 1 */
3287c478bd9Sstevel@tonic-gate }
3297c478bd9Sstevel@tonic-gate }
3307c478bd9Sstevel@tonic-gate
3317c478bd9Sstevel@tonic-gate /* if a column width was specified, save it in caller's struct */
3327c478bd9Sstevel@tonic-gate if (dig1) {
3337c478bd9Sstevel@tonic-gate int nbytes;
3347c478bd9Sstevel@tonic-gate
3357c478bd9Sstevel@tonic-gate nbytes = dig2 - dig1;
3367c478bd9Sstevel@tonic-gate /* if too many digits in the width return error */
3377c478bd9Sstevel@tonic-gate if (nbytes > CMN_MAX_DIGITS)
3387c478bd9Sstevel@tonic-gate return (1);
3397c478bd9Sstevel@tonic-gate strncpy(cdigs, dig1, nbytes);
3407c478bd9Sstevel@tonic-gate cdigs[nbytes] = 0;
3417c478bd9Sstevel@tonic-gate *cwidth = atoi(cdigs);
3427c478bd9Sstevel@tonic-gate }
3437c478bd9Sstevel@tonic-gate
3447c478bd9Sstevel@tonic-gate /* check for long format specifier */
3457c478bd9Sstevel@tonic-gate if (*fmt == 'l') {
3467c478bd9Sstevel@tonic-gate fmt++;
3477c478bd9Sstevel@tonic-gate (*fwidth)++;
3487c478bd9Sstevel@tonic-gate isll = 1;
3497c478bd9Sstevel@tonic-gate }
3507c478bd9Sstevel@tonic-gate
3517c478bd9Sstevel@tonic-gate /* process by specific format type */
3527c478bd9Sstevel@tonic-gate switch (*fmt) {
3537c478bd9Sstevel@tonic-gate case 'c':
3547c478bd9Sstevel@tonic-gate case 's':
3557c478bd9Sstevel@tonic-gate case '%':
3567c478bd9Sstevel@tonic-gate if (isll)
3577c478bd9Sstevel@tonic-gate return (1);
3587c478bd9Sstevel@tonic-gate case 'd':
3597c478bd9Sstevel@tonic-gate case 'x':
3607c478bd9Sstevel@tonic-gate *format = *fmt;
3617c478bd9Sstevel@tonic-gate (*fwidth)++;
3627c478bd9Sstevel@tonic-gate break;
3637c478bd9Sstevel@tonic-gate case 'p':
3647c478bd9Sstevel@tonic-gate isll = 1; /* uses 64 bit format */
3657c478bd9Sstevel@tonic-gate *format = *fmt;
3667c478bd9Sstevel@tonic-gate (*fwidth)++;
3677c478bd9Sstevel@tonic-gate break;
3687c478bd9Sstevel@tonic-gate default:
3697c478bd9Sstevel@tonic-gate return (1); /* unknown format type */
3707c478bd9Sstevel@tonic-gate }
3717c478bd9Sstevel@tonic-gate if (isll) {
3727c478bd9Sstevel@tonic-gate *fwidth *= -1;
3737c478bd9Sstevel@tonic-gate }
3747c478bd9Sstevel@tonic-gate return (0);
3757c478bd9Sstevel@tonic-gate }
3767c478bd9Sstevel@tonic-gate
3777c478bd9Sstevel@tonic-gate /*
3787c478bd9Sstevel@tonic-gate * fmt_args()
3797c478bd9Sstevel@tonic-gate *
3807c478bd9Sstevel@tonic-gate * Called by fmt_str() to setup arguments for subsequent snprintf()
3817c478bd9Sstevel@tonic-gate * calls. For cases not involving column width limitations, processing
3827c478bd9Sstevel@tonic-gate * simply POPs the data stack as required to setup caller's arg(or
3837c478bd9Sstevel@tonic-gate * llarg, as appropriate). When a column width is specified for output,
3847c478bd9Sstevel@tonic-gate * a temporary buffer is constructed to contain snprintf() generated
3857c478bd9Sstevel@tonic-gate * output for the argument. Testing is then performed to determine if
3867c478bd9Sstevel@tonic-gate * the specified column width will require truncation of the output.
3877c478bd9Sstevel@tonic-gate * If so, truncation of least significant digits is performed as
3887c478bd9Sstevel@tonic-gate * necessary, and caller's arg(or llarg) is adjusted to obtain the
3897c478bd9Sstevel@tonic-gate * specified column width.
3907c478bd9Sstevel@tonic-gate *
3917c478bd9Sstevel@tonic-gate */
3927c478bd9Sstevel@tonic-gate
3937c478bd9Sstevel@tonic-gate static void
fmt_args(fcode_env_t * env,int cw,int fw,char format,long * arg,long long * llarg)3947c478bd9Sstevel@tonic-gate fmt_args(fcode_env_t *env, int cw, int fw, char format, long *arg,
3957c478bd9Sstevel@tonic-gate long long *llarg)
3967c478bd9Sstevel@tonic-gate {
3977c478bd9Sstevel@tonic-gate char *cbuf;
3987c478bd9Sstevel@tonic-gate char snf[3];
3997c478bd9Sstevel@tonic-gate int cbsize;
4007c478bd9Sstevel@tonic-gate int cnv = 10, ndigits = 0;
4017c478bd9Sstevel@tonic-gate
4027c478bd9Sstevel@tonic-gate if (fw > 0) { /* check for normal (not long) formats */
4037c478bd9Sstevel@tonic-gate
4047c478bd9Sstevel@tonic-gate /* initialize format string for snprintf call */
4057c478bd9Sstevel@tonic-gate snf[0] = '%';
4067c478bd9Sstevel@tonic-gate snf[1] = format;
4077c478bd9Sstevel@tonic-gate snf[2] = 0;
4087c478bd9Sstevel@tonic-gate
4097c478bd9Sstevel@tonic-gate /* process by format type */
4107c478bd9Sstevel@tonic-gate switch (format) {
4117c478bd9Sstevel@tonic-gate case 'x':
4127c478bd9Sstevel@tonic-gate cnv = 16;
4137c478bd9Sstevel@tonic-gate case 'd':
4147c478bd9Sstevel@tonic-gate case 'c':
4157c478bd9Sstevel@tonic-gate case 'p':
4167c478bd9Sstevel@tonic-gate *arg = POP(DS);
4177c478bd9Sstevel@tonic-gate break;
4187c478bd9Sstevel@tonic-gate case 's':
4197c478bd9Sstevel@tonic-gate POP(DS);
4207c478bd9Sstevel@tonic-gate *arg = POP(DS);
4217c478bd9Sstevel@tonic-gate break;
4227c478bd9Sstevel@tonic-gate case '%':
4237c478bd9Sstevel@tonic-gate return;
4247c478bd9Sstevel@tonic-gate default:
4257c478bd9Sstevel@tonic-gate log_message(MSG_ERROR,
4267c478bd9Sstevel@tonic-gate "fmt_args:invalid format type! (%s)\n",
4277c478bd9Sstevel@tonic-gate &format);
4287c478bd9Sstevel@tonic-gate return;
4297c478bd9Sstevel@tonic-gate }
4307c478bd9Sstevel@tonic-gate
4317c478bd9Sstevel@tonic-gate /* check if a column width was specified */
4327c478bd9Sstevel@tonic-gate if (cw) {
4337c478bd9Sstevel@tonic-gate /* allocate a scratch buffer */
4347c478bd9Sstevel@tonic-gate cbsize = 2*(sizeof (long long)) + 1;
4357c478bd9Sstevel@tonic-gate cbuf = MALLOC(cbsize);
4367c478bd9Sstevel@tonic-gate
4377c478bd9Sstevel@tonic-gate if (snprintf(cbuf, cbsize, snf, *arg) < 0)
4387c478bd9Sstevel@tonic-gate log_message(MSG_ERROR,
4397c478bd9Sstevel@tonic-gate "fmt_args: snprintf output error\n");
4407c478bd9Sstevel@tonic-gate while ((cbuf[ndigits] != NULL) &&
4417c478bd9Sstevel@tonic-gate (ndigits < cbsize))
4427c478bd9Sstevel@tonic-gate ndigits++;
4437c478bd9Sstevel@tonic-gate
4447c478bd9Sstevel@tonic-gate /* if truncation is necessary, do it */
4457c478bd9Sstevel@tonic-gate if (ndigits > cw) {
4467c478bd9Sstevel@tonic-gate cbuf[cw] = 0;
4477c478bd9Sstevel@tonic-gate if (format == 's') {
4487c478bd9Sstevel@tonic-gate char *str;
4497c478bd9Sstevel@tonic-gate str = (char *)*arg;
4507c478bd9Sstevel@tonic-gate str[cw] = 0;
4517c478bd9Sstevel@tonic-gate } else
4527c478bd9Sstevel@tonic-gate *arg = strtol(cbuf,
4537c478bd9Sstevel@tonic-gate (char **)NULL, cnv);
4547c478bd9Sstevel@tonic-gate }
4557c478bd9Sstevel@tonic-gate free(cbuf);
4567c478bd9Sstevel@tonic-gate }
4577c478bd9Sstevel@tonic-gate
4587c478bd9Sstevel@tonic-gate } else { /* process long formats */
4597c478bd9Sstevel@tonic-gate
4607c478bd9Sstevel@tonic-gate *llarg = POP(DS);
4617c478bd9Sstevel@tonic-gate
4627c478bd9Sstevel@tonic-gate /* check if a column width was specified */
4637c478bd9Sstevel@tonic-gate if (cw) {
4647c478bd9Sstevel@tonic-gate /* allocate a scratch buffer */
4657c478bd9Sstevel@tonic-gate cbsize = 2*(sizeof (long long)) + 1;
4667c478bd9Sstevel@tonic-gate cbuf = MALLOC(cbsize);
4677c478bd9Sstevel@tonic-gate
4687c478bd9Sstevel@tonic-gate switch (format) {
4697c478bd9Sstevel@tonic-gate case 'p':
4707c478bd9Sstevel@tonic-gate cnv = 16;
4717c478bd9Sstevel@tonic-gate if (snprintf(cbuf, cbsize, "%p", *llarg) < 0)
4727c478bd9Sstevel@tonic-gate log_message(MSG_ERROR,
4737c478bd9Sstevel@tonic-gate "fmt_args: snprintf error\n");
4747c478bd9Sstevel@tonic-gate break;
4757c478bd9Sstevel@tonic-gate case 'x':
4767c478bd9Sstevel@tonic-gate cnv = 16;
4777c478bd9Sstevel@tonic-gate if (snprintf(cbuf, cbsize, "%lx", *llarg) < 0)
4787c478bd9Sstevel@tonic-gate log_message(MSG_ERROR,
4797c478bd9Sstevel@tonic-gate "fmt_args: snprintf error\n");
4807c478bd9Sstevel@tonic-gate break;
4817c478bd9Sstevel@tonic-gate case 'd':
4827c478bd9Sstevel@tonic-gate if (snprintf(cbuf, cbsize, "%ld", *llarg) < 0)
4837c478bd9Sstevel@tonic-gate log_message(MSG_ERROR,
4847c478bd9Sstevel@tonic-gate "fmt_args: snprintf error\n");
4857c478bd9Sstevel@tonic-gate break;
4867c478bd9Sstevel@tonic-gate default:
4877c478bd9Sstevel@tonic-gate log_message(MSG_ERROR,
4887c478bd9Sstevel@tonic-gate "invalid long format type! (l%s)\n",
4897c478bd9Sstevel@tonic-gate &format);
4907c478bd9Sstevel@tonic-gate free(cbuf);
4917c478bd9Sstevel@tonic-gate return;
4927c478bd9Sstevel@tonic-gate }
4937c478bd9Sstevel@tonic-gate while ((cbuf[ndigits] != NULL) &&
4947c478bd9Sstevel@tonic-gate (ndigits < cbsize)) {
4957c478bd9Sstevel@tonic-gate ndigits++;
4967c478bd9Sstevel@tonic-gate }
4977c478bd9Sstevel@tonic-gate /* if truncation is necessary, do it */
4987c478bd9Sstevel@tonic-gate if (ndigits > cw) {
4997c478bd9Sstevel@tonic-gate cbuf[cw] = 0;
5007c478bd9Sstevel@tonic-gate *llarg = strtoll(cbuf, (char **)NULL, cnv);
5017c478bd9Sstevel@tonic-gate }
5027c478bd9Sstevel@tonic-gate free(cbuf);
5037c478bd9Sstevel@tonic-gate }
5047c478bd9Sstevel@tonic-gate }
5057c478bd9Sstevel@tonic-gate }
5067c478bd9Sstevel@tonic-gate
5077c478bd9Sstevel@tonic-gate /*
5087c478bd9Sstevel@tonic-gate * fmt_str()
5097c478bd9Sstevel@tonic-gate *
5107c478bd9Sstevel@tonic-gate * Extracts text from caller's input buffer, processes explicit
5117c478bd9Sstevel@tonic-gate * formatting as necessary, and outputs formatted text to caller's
5127c478bd9Sstevel@tonic-gate * receptacle.
5137c478bd9Sstevel@tonic-gate *
5147c478bd9Sstevel@tonic-gate * env - pointer to caller's fcode environment
5157c478bd9Sstevel@tonic-gate * fmt - pointer to caller's input buffr
5167c478bd9Sstevel@tonic-gate * fmtbuf - ponter to caller's receptacle buffer
5177c478bd9Sstevel@tonic-gate * bsize - size of caller's fmtbuf buffer
5187c478bd9Sstevel@tonic-gate *
5197c478bd9Sstevel@tonic-gate * This function performs an initial test to determine if caller's
5207c478bd9Sstevel@tonic-gate * input buffer contains formatting(specified by presence of "%")
5217c478bd9Sstevel@tonic-gate * in the buffer. If so, validfmt() function is called to verify
5227c478bd9Sstevel@tonic-gate * the formatting, after which the buffer is processed according
5237c478bd9Sstevel@tonic-gate * to the field width specified by validfmt() output. Special
5247c478bd9Sstevel@tonic-gate * processing is required when caller's buffer contains a double
5257c478bd9Sstevel@tonic-gate * "%" ("%%"), in which case the second "%" is accepted as normal
5267c478bd9Sstevel@tonic-gate * text.
5277c478bd9Sstevel@tonic-gate */
5287c478bd9Sstevel@tonic-gate
5297c478bd9Sstevel@tonic-gate static void
fmt_str(fcode_env_t * env,char * fmt,char * fmtbuf,int bsize)5307c478bd9Sstevel@tonic-gate fmt_str(fcode_env_t *env, char *fmt, char *fmtbuf, int bsize)
5317c478bd9Sstevel@tonic-gate {
5327c478bd9Sstevel@tonic-gate char tbuf[CMN_MSG_SIZE];
5337c478bd9Sstevel@tonic-gate char *fmptr, *pct;
5347c478bd9Sstevel@tonic-gate int l, cw, fw, bytes;
5357c478bd9Sstevel@tonic-gate long arg;
5367c478bd9Sstevel@tonic-gate long long llarg;
5377c478bd9Sstevel@tonic-gate
5387c478bd9Sstevel@tonic-gate *fmtbuf = 0;
5397c478bd9Sstevel@tonic-gate if ((pct = strchr(fmt, '%')) != 0) {
5407c478bd9Sstevel@tonic-gate cmn_fmt_t cfstr;
5417c478bd9Sstevel@tonic-gate int vferr;
5427c478bd9Sstevel@tonic-gate
5437c478bd9Sstevel@tonic-gate l = strlen(pct++);
5447c478bd9Sstevel@tonic-gate vferr = validfmt(pct, &cfstr);
5457c478bd9Sstevel@tonic-gate if (!vferr) {
5467c478bd9Sstevel@tonic-gate fw = cfstr.fwidth;
5477c478bd9Sstevel@tonic-gate cw = cfstr.cwidth;
5487c478bd9Sstevel@tonic-gate fmptr = &cfstr.format;
5497c478bd9Sstevel@tonic-gate } else {
5507c478bd9Sstevel@tonic-gate if (vferr < 0) {
5517c478bd9Sstevel@tonic-gate log_message(MSG_ERROR,
5527c478bd9Sstevel@tonic-gate "fmt_str: NULL ptr supplied to validfmt()\n");
5537c478bd9Sstevel@tonic-gate return;
5547c478bd9Sstevel@tonic-gate }
5557c478bd9Sstevel@tonic-gate
5567c478bd9Sstevel@tonic-gate bytes = pct - fmt;
5577c478bd9Sstevel@tonic-gate strncpy(tbuf, fmt, bytes);
5587c478bd9Sstevel@tonic-gate strncpy(tbuf+bytes, "%", 1);
5597c478bd9Sstevel@tonic-gate strncpy(tbuf+bytes+1, fmt+bytes, 1);
5607c478bd9Sstevel@tonic-gate bytes += 2;
5617c478bd9Sstevel@tonic-gate tbuf[bytes] = 0;
5627c478bd9Sstevel@tonic-gate
5637c478bd9Sstevel@tonic-gate log_message(MSG_ERROR,
5647c478bd9Sstevel@tonic-gate "fmt_str: invalid format type! (%s)\n",
5657c478bd9Sstevel@tonic-gate tbuf+bytes-3);
5667c478bd9Sstevel@tonic-gate
5677c478bd9Sstevel@tonic-gate strncpy(fmtbuf, tbuf, bsize);
5687c478bd9Sstevel@tonic-gate return;
5697c478bd9Sstevel@tonic-gate }
5707c478bd9Sstevel@tonic-gate
5717c478bd9Sstevel@tonic-gate if (fw > 0) { /* process normal (not long) formats */
5727c478bd9Sstevel@tonic-gate bytes = pct - fmt + fw;
5737c478bd9Sstevel@tonic-gate strncpy(tbuf, fmt, bytes);
5747c478bd9Sstevel@tonic-gate tbuf[bytes] = 0;
5757c478bd9Sstevel@tonic-gate } else {
5767c478bd9Sstevel@tonic-gate /* if here, fw must be a long format */
5777c478bd9Sstevel@tonic-gate if (*fmptr == 'p') {
5787c478bd9Sstevel@tonic-gate bytes = pct - fmt - fw;
5797c478bd9Sstevel@tonic-gate strncpy(tbuf, fmt, bytes);
5807c478bd9Sstevel@tonic-gate tbuf[bytes] = 0;
5817c478bd9Sstevel@tonic-gate } else {
5827c478bd9Sstevel@tonic-gate bytes = pct - fmt - fw - 2;
5837c478bd9Sstevel@tonic-gate strncpy(tbuf, fmt, bytes);
5847c478bd9Sstevel@tonic-gate tbuf[bytes] = 'l';
5857c478bd9Sstevel@tonic-gate strncpy(tbuf+bytes+1, fmt+bytes, 2);
5867c478bd9Sstevel@tonic-gate tbuf[bytes+1+2] = 0;
5877c478bd9Sstevel@tonic-gate }
5887c478bd9Sstevel@tonic-gate }
5897c478bd9Sstevel@tonic-gate
5907c478bd9Sstevel@tonic-gate /* if more input buffer to process, recurse */
5917c478bd9Sstevel@tonic-gate if ((l - abs(fw)) != 0) {
5927c478bd9Sstevel@tonic-gate fmt_str(env, pct+abs(fw), (tbuf + strlen(tbuf)),
5937c478bd9Sstevel@tonic-gate CMN_MSG_SIZE - strlen(tbuf));
5947c478bd9Sstevel@tonic-gate }
5957c478bd9Sstevel@tonic-gate
5967c478bd9Sstevel@tonic-gate /* call to extract args for snprintf() calls below */
5977c478bd9Sstevel@tonic-gate fmt_args(env, cw, fw, *fmptr, &arg, &llarg);
5987c478bd9Sstevel@tonic-gate
5997c478bd9Sstevel@tonic-gate if (fw > 0) { /* process normal (not long) formats */
6007c478bd9Sstevel@tonic-gate switch (*fmptr) {
6017c478bd9Sstevel@tonic-gate case 'd':
6027c478bd9Sstevel@tonic-gate case 'x':
6037c478bd9Sstevel@tonic-gate case 'c':
6047c478bd9Sstevel@tonic-gate case 's':
6057c478bd9Sstevel@tonic-gate case 'p':
6067c478bd9Sstevel@tonic-gate (void) snprintf(fmtbuf, bsize, tbuf, arg);
6077c478bd9Sstevel@tonic-gate break;
6087c478bd9Sstevel@tonic-gate case '%':
6097c478bd9Sstevel@tonic-gate (void) snprintf(fmtbuf, bsize, tbuf);
6107c478bd9Sstevel@tonic-gate break;
6117c478bd9Sstevel@tonic-gate default:
6127c478bd9Sstevel@tonic-gate log_message(MSG_ERROR,
6137c478bd9Sstevel@tonic-gate "fmt_str: invalid format (%s)\n",
6147c478bd9Sstevel@tonic-gate fmptr);
6157c478bd9Sstevel@tonic-gate return;
6167c478bd9Sstevel@tonic-gate }
6177c478bd9Sstevel@tonic-gate
6187c478bd9Sstevel@tonic-gate } else /* process long formats */
6197c478bd9Sstevel@tonic-gate (void) snprintf(fmtbuf, bsize, tbuf, llarg);
6207c478bd9Sstevel@tonic-gate
6217c478bd9Sstevel@tonic-gate } else
6227c478bd9Sstevel@tonic-gate strncpy(fmtbuf, fmt, bsize);
6237c478bd9Sstevel@tonic-gate }
6247c478bd9Sstevel@tonic-gate
6257c478bd9Sstevel@tonic-gate /*
6267c478bd9Sstevel@tonic-gate * fc_cmn_append()
6277c478bd9Sstevel@tonic-gate *
6287c478bd9Sstevel@tonic-gate * Pops data stack to obtain message text, and calls fmt_str()
6297c478bd9Sstevel@tonic-gate * function to perform any message formatting necessary.
6307c478bd9Sstevel@tonic-gate *
6317c478bd9Sstevel@tonic-gate * This function is called from fc_cmn_end() or directly in
6327c478bd9Sstevel@tonic-gate * processing a cmn-append token. Since a pre-existing message
6337c478bd9Sstevel@tonic-gate * context is assumed, initial checking is performed to verify
6347c478bd9Sstevel@tonic-gate * its existence.
6357c478bd9Sstevel@tonic-gate */
6367c478bd9Sstevel@tonic-gate
6377c478bd9Sstevel@tonic-gate void
fc_cmn_append(fcode_env_t * env)6387c478bd9Sstevel@tonic-gate fc_cmn_append(fcode_env_t *env)
6397c478bd9Sstevel@tonic-gate {
6407c478bd9Sstevel@tonic-gate int len;
6417c478bd9Sstevel@tonic-gate char *str;
6427c478bd9Sstevel@tonic-gate
6437c478bd9Sstevel@tonic-gate if (root == NULL) {
6447c478bd9Sstevel@tonic-gate log_message(MSG_ERROR,
6457c478bd9Sstevel@tonic-gate "fc_cmn_append: no message context for append\n");
6467c478bd9Sstevel@tonic-gate return;
6477c478bd9Sstevel@tonic-gate }
6487c478bd9Sstevel@tonic-gate
6497c478bd9Sstevel@tonic-gate len = POP(DS);
6507c478bd9Sstevel@tonic-gate str = (char *)POP(DS);
6517c478bd9Sstevel@tonic-gate
6527c478bd9Sstevel@tonic-gate if ((root->len + len) < CMN_MSG_SIZE) {
6537c478bd9Sstevel@tonic-gate fmt_str(env, str, root->buf+root->len, CMN_MSG_SIZE -
6547c478bd9Sstevel@tonic-gate root->len);
6557c478bd9Sstevel@tonic-gate root->len += len;
6567c478bd9Sstevel@tonic-gate } else
6577c478bd9Sstevel@tonic-gate log_message(MSG_ERROR,
6587c478bd9Sstevel@tonic-gate "fc_cmn_append: append exceeds max msg size\n");
6597c478bd9Sstevel@tonic-gate }
6607c478bd9Sstevel@tonic-gate
6617c478bd9Sstevel@tonic-gate /*
6627c478bd9Sstevel@tonic-gate * fc_cmn_end()
6637c478bd9Sstevel@tonic-gate *
6647c478bd9Sstevel@tonic-gate * Process ]cmn-end token to log the message initiated by a preceeding
6657c478bd9Sstevel@tonic-gate * fc_cmn_start() call.
6667c478bd9Sstevel@tonic-gate *
6677c478bd9Sstevel@tonic-gate * Since nested cmn-xxx[ calls are supported, a test is made to determine
6687c478bd9Sstevel@tonic-gate * if this is the final cmn-end of a nested sequence. If so, or if
6697c478bd9Sstevel@tonic-gate * there was no nesting, log_message() is called with the appropriate
6707c478bd9Sstevel@tonic-gate * text buffer. Otherwise, the root variable is adjusted to point to
6717c478bd9Sstevel@tonic-gate * the preceeding message in the sequence and links in the list are
6727c478bd9Sstevel@tonic-gate * updated. No logging is performed until the final ]cmn-end of the
6737c478bd9Sstevel@tonic-gate * sequence is processed; then, messages are logged in FIFO order.
6747c478bd9Sstevel@tonic-gate */
6757c478bd9Sstevel@tonic-gate void
fc_cmn_end(fcode_env_t * env)6767c478bd9Sstevel@tonic-gate fc_cmn_end(fcode_env_t *env)
6777c478bd9Sstevel@tonic-gate {
6787c478bd9Sstevel@tonic-gate cmn_msg_t *old;
6797c478bd9Sstevel@tonic-gate
6807c478bd9Sstevel@tonic-gate if (root == 0) {
6817c478bd9Sstevel@tonic-gate log_message(MSG_ERROR, "]cmn-end call w/o buffer\n");
6827c478bd9Sstevel@tonic-gate return;
6837c478bd9Sstevel@tonic-gate }
6847c478bd9Sstevel@tonic-gate
6857c478bd9Sstevel@tonic-gate fc_cmn_append(env);
6867c478bd9Sstevel@tonic-gate
6877c478bd9Sstevel@tonic-gate if (root->prev == 0) {
6887c478bd9Sstevel@tonic-gate cmn_msg_t *next;
6897c478bd9Sstevel@tonic-gate do {
6907c478bd9Sstevel@tonic-gate log_message(root->level, "%s\n", root->buf);
6917c478bd9Sstevel@tonic-gate next = root->next;
6927c478bd9Sstevel@tonic-gate free(root);
6937c478bd9Sstevel@tonic-gate root = next;
6947c478bd9Sstevel@tonic-gate } while (root);
6957c478bd9Sstevel@tonic-gate } else {
6967c478bd9Sstevel@tonic-gate old = root->prev;
6977c478bd9Sstevel@tonic-gate old->next = root;
6987c478bd9Sstevel@tonic-gate root = old;
6997c478bd9Sstevel@tonic-gate }
7007c478bd9Sstevel@tonic-gate }
7017c478bd9Sstevel@tonic-gate
7027c478bd9Sstevel@tonic-gate /*
7037c478bd9Sstevel@tonic-gate * fc_cmn_start()
7047c478bd9Sstevel@tonic-gate *
7057c478bd9Sstevel@tonic-gate * Generic function to begin a common message.
7067c478bd9Sstevel@tonic-gate *
7077c478bd9Sstevel@tonic-gate * Allocates a new cmn_msg_t to associate with the message, and sets
7087c478bd9Sstevel@tonic-gate * up initial text as specified by callers' inputs:
7097c478bd9Sstevel@tonic-gate *
7107c478bd9Sstevel@tonic-gate * env - pointer to caller's fcode environment
7117c478bd9Sstevel@tonic-gate * head - pointer to initial text portion of the message
7127c478bd9Sstevel@tonic-gate * path - flag to indicate if a device path is to be generated
7137c478bd9Sstevel@tonic-gate */
7147c478bd9Sstevel@tonic-gate static void
fc_cmn_start(fcode_env_t * env,char * head,int path)7157c478bd9Sstevel@tonic-gate fc_cmn_start(fcode_env_t *env, char *head, int path)
7167c478bd9Sstevel@tonic-gate {
7177c478bd9Sstevel@tonic-gate cmn_msg_t *new;
7187c478bd9Sstevel@tonic-gate char *dpath;
7197c478bd9Sstevel@tonic-gate
7207c478bd9Sstevel@tonic-gate new = MALLOC(sizeof (cmn_msg_t));
7217c478bd9Sstevel@tonic-gate new->prev = root;
7227c478bd9Sstevel@tonic-gate if (root != 0)
7237c478bd9Sstevel@tonic-gate root->next = new;
7247c478bd9Sstevel@tonic-gate strcpy(new->buf, head);
7257c478bd9Sstevel@tonic-gate new->len = strlen(head);
7267c478bd9Sstevel@tonic-gate if (path && env->current_device) {
7277c478bd9Sstevel@tonic-gate dpath = get_path(env, env->current_device);
7287c478bd9Sstevel@tonic-gate strcpy(new->buf+new->len, dpath);
7297c478bd9Sstevel@tonic-gate new->len += strlen(dpath);
7307c478bd9Sstevel@tonic-gate strncpy(new->buf+new->len++, ": ", 2);
7317c478bd9Sstevel@tonic-gate ++new->len;
7327c478bd9Sstevel@tonic-gate free(dpath);
7337c478bd9Sstevel@tonic-gate }
7347c478bd9Sstevel@tonic-gate new->level = cmn_msg_level;
7357c478bd9Sstevel@tonic-gate new->next = NULL;
7367c478bd9Sstevel@tonic-gate root = new;
7377c478bd9Sstevel@tonic-gate }
7387c478bd9Sstevel@tonic-gate
7397c478bd9Sstevel@tonic-gate /*
7407c478bd9Sstevel@tonic-gate * fc_cmn_type()
7417c478bd9Sstevel@tonic-gate *
7427c478bd9Sstevel@tonic-gate * Process cmn-type[ token.
7437c478bd9Sstevel@tonic-gate *
7447c478bd9Sstevel@tonic-gate * Invokes fc_cmn_start() to create a message containing blank
7457c478bd9Sstevel@tonic-gate * header and no device path information.
7467c478bd9Sstevel@tonic-gate */
7477c478bd9Sstevel@tonic-gate void
fc_cmn_type(fcode_env_t * env)7487c478bd9Sstevel@tonic-gate fc_cmn_type(fcode_env_t *env)
7497c478bd9Sstevel@tonic-gate {
7507c478bd9Sstevel@tonic-gate cmn_msg_level = MSG_INFO;
7517c478bd9Sstevel@tonic-gate fc_cmn_start(env, "", 0);
7527c478bd9Sstevel@tonic-gate }
7537c478bd9Sstevel@tonic-gate
7547c478bd9Sstevel@tonic-gate /*
7557c478bd9Sstevel@tonic-gate * fc_cmn_msg()
7567c478bd9Sstevel@tonic-gate *
7577c478bd9Sstevel@tonic-gate * Process cmn-msg[ token.
7587c478bd9Sstevel@tonic-gate *
7597c478bd9Sstevel@tonic-gate * Invokes fc_cmn_start() to create a message containing blank
7607c478bd9Sstevel@tonic-gate * header but specifying device path information.
7617c478bd9Sstevel@tonic-gate */
7627c478bd9Sstevel@tonic-gate void
fc_cmn_msg(fcode_env_t * env)7637c478bd9Sstevel@tonic-gate fc_cmn_msg(fcode_env_t *env)
7647c478bd9Sstevel@tonic-gate {
7657c478bd9Sstevel@tonic-gate
7667c478bd9Sstevel@tonic-gate cmn_msg_level = MSG_INFO;
7677c478bd9Sstevel@tonic-gate fc_cmn_start(env, "", 1);
7687c478bd9Sstevel@tonic-gate }
7697c478bd9Sstevel@tonic-gate
7707c478bd9Sstevel@tonic-gate /*
7717c478bd9Sstevel@tonic-gate * fc_cmn_note()
7727c478bd9Sstevel@tonic-gate *
7737c478bd9Sstevel@tonic-gate * Process cmn-note[ token.
7747c478bd9Sstevel@tonic-gate *
7757c478bd9Sstevel@tonic-gate * Invokes fc_cmn_start() to create a message with NOTICE stamping in
7767c478bd9Sstevel@tonic-gate * the header and specification of device path information.
7777c478bd9Sstevel@tonic-gate */
7787c478bd9Sstevel@tonic-gate void
fc_cmn_note(fcode_env_t * env)7797c478bd9Sstevel@tonic-gate fc_cmn_note(fcode_env_t *env)
7807c478bd9Sstevel@tonic-gate {
7817c478bd9Sstevel@tonic-gate cmn_msg_level = MSG_NOTE;
7827c478bd9Sstevel@tonic-gate fc_cmn_start(env, "NOTICE: ", 1);
7837c478bd9Sstevel@tonic-gate }
7847c478bd9Sstevel@tonic-gate
7857c478bd9Sstevel@tonic-gate /*
7867c478bd9Sstevel@tonic-gate * fc_cmn_warn()
7877c478bd9Sstevel@tonic-gate *
7887c478bd9Sstevel@tonic-gate * Process cmn-warn[ token.
7897c478bd9Sstevel@tonic-gate *
7907c478bd9Sstevel@tonic-gate * Invokes fc_cmn_start() to create a message with WARNING stamping in
7917c478bd9Sstevel@tonic-gate * the header and specification of device path information.
7927c478bd9Sstevel@tonic-gate */
7937c478bd9Sstevel@tonic-gate void
fc_cmn_warn(fcode_env_t * env)7947c478bd9Sstevel@tonic-gate fc_cmn_warn(fcode_env_t *env)
7957c478bd9Sstevel@tonic-gate {
7967c478bd9Sstevel@tonic-gate cmn_msg_level = MSG_WARN;
7977c478bd9Sstevel@tonic-gate fc_cmn_start(env, "WARNING: ", 1);
7987c478bd9Sstevel@tonic-gate }
7997c478bd9Sstevel@tonic-gate
8007c478bd9Sstevel@tonic-gate /*
8017c478bd9Sstevel@tonic-gate * fc_cmn_error()
8027c478bd9Sstevel@tonic-gate *
8037c478bd9Sstevel@tonic-gate * Process cmn-error[ token.
8047c478bd9Sstevel@tonic-gate *
8057c478bd9Sstevel@tonic-gate * Invokes fc_cmn_start() to create a message with ERROR stamping in
8067c478bd9Sstevel@tonic-gate * the header and specification of device path information.
8077c478bd9Sstevel@tonic-gate */
8087c478bd9Sstevel@tonic-gate void
fc_cmn_error(fcode_env_t * env)8097c478bd9Sstevel@tonic-gate fc_cmn_error(fcode_env_t *env)
8107c478bd9Sstevel@tonic-gate {
8117c478bd9Sstevel@tonic-gate cmn_msg_level = MSG_ERROR;
8127c478bd9Sstevel@tonic-gate fc_cmn_start(env, "ERROR: ", 1);
8137c478bd9Sstevel@tonic-gate }
8147c478bd9Sstevel@tonic-gate
8157c478bd9Sstevel@tonic-gate /*
8167c478bd9Sstevel@tonic-gate * fc_cmn_fatal()
8177c478bd9Sstevel@tonic-gate *
8187c478bd9Sstevel@tonic-gate * Process cmn-fatal[ token.
8197c478bd9Sstevel@tonic-gate *
8207c478bd9Sstevel@tonic-gate * Invokes fc_cmn_start() to create a message with FATAL stamping in
8217c478bd9Sstevel@tonic-gate * the header and specification of device path information.
8227c478bd9Sstevel@tonic-gate */
8237c478bd9Sstevel@tonic-gate void
fc_cmn_fatal(fcode_env_t * env)8247c478bd9Sstevel@tonic-gate fc_cmn_fatal(fcode_env_t *env)
8257c478bd9Sstevel@tonic-gate {
8267c478bd9Sstevel@tonic-gate cmn_msg_level = MSG_FATAL;
8277c478bd9Sstevel@tonic-gate fc_cmn_start(env, "FATAL: ", 1);
8287c478bd9Sstevel@tonic-gate }
8297c478bd9Sstevel@tonic-gate
8307c478bd9Sstevel@tonic-gate #pragma init(_init)
8317c478bd9Sstevel@tonic-gate
8327c478bd9Sstevel@tonic-gate static void
_init(void)8337c478bd9Sstevel@tonic-gate _init(void)
8347c478bd9Sstevel@tonic-gate {
8357c478bd9Sstevel@tonic-gate fcode_env_t *env = initial_env;
8367c478bd9Sstevel@tonic-gate ASSERT(env);
8377c478bd9Sstevel@tonic-gate NOTICE;
8387c478bd9Sstevel@tonic-gate
8397c478bd9Sstevel@tonic-gate ANSI(0x088, 0, "span", span);
8407c478bd9Sstevel@tonic-gate ANSI(0x08a, 0, "expect", expect);
8417c478bd9Sstevel@tonic-gate
8427c478bd9Sstevel@tonic-gate ANSI(0x08d, 0, "key?", keyquestion);
8437c478bd9Sstevel@tonic-gate ANSI(0x08e, 0, "key", key);
8447c478bd9Sstevel@tonic-gate ANSI(0x08f, 0, "emit", emit);
8457c478bd9Sstevel@tonic-gate ANSI(0x090, 0, "type", type);
8467c478bd9Sstevel@tonic-gate ANSI(0x091, 0, "(cr", paren_cr);
8477c478bd9Sstevel@tonic-gate ANSI(0x092, 0, "cr", fc_crlf);
8487c478bd9Sstevel@tonic-gate ANSI(0x093, 0, "#out", fc_num_out);
8497c478bd9Sstevel@tonic-gate ANSI(0x094, 0, "#line", fc_num_line);
8507c478bd9Sstevel@tonic-gate
8517c478bd9Sstevel@tonic-gate FCODE(0x125, 0, "get-msecs", do_get_msecs);
8527c478bd9Sstevel@tonic-gate FCODE(0x126, 0, "ms", do_ms);
8537c478bd9Sstevel@tonic-gate
8547c478bd9Sstevel@tonic-gate FORTH(0, "verbose-emit", do_verbose_emit);
8557c478bd9Sstevel@tonic-gate FCODE(0x7e9, 0, "cmn-fatal[", fc_cmn_fatal);
8567c478bd9Sstevel@tonic-gate FCODE(0x7ea, 0, "cmn-error[", fc_cmn_error);
8577c478bd9Sstevel@tonic-gate FCODE(0x7eb, 0, "cmn-warn[", fc_cmn_warn);
8587c478bd9Sstevel@tonic-gate FCODE(0x7ec, 0, "cmn-note[", fc_cmn_note);
8597c478bd9Sstevel@tonic-gate FCODE(0x7ed, 0, "cmn-type[", fc_cmn_type);
8607c478bd9Sstevel@tonic-gate FCODE(0x7ee, 0, "cmn-append", fc_cmn_append);
8617c478bd9Sstevel@tonic-gate FCODE(0x7ef, 0, "]cmn-end", fc_cmn_end);
8627c478bd9Sstevel@tonic-gate FCODE(0x7f0, 0, "cmn-msg[", fc_cmn_msg);
8637c478bd9Sstevel@tonic-gate }
864