37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow/*
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * This file and its contents are supplied under the terms of the
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * Common Development and Distribution License ("CDDL"), version 1.0.
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * You may only use this file in accordance with the terms of version
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * 1.0 of the CDDL.
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow *
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * A full copy of the text of the CDDL should have accompanied this
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * source. A copy of the CDDL is also available via the Internet at
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * http://www.illumos.org/license/CDDL.
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow */
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow/*
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * Copyright 2014 Joyent, Inc.
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow */
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow/*
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * This program implements a small domain-specific language (DSL) for the
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * generation of nvlists, and subsequent printing in JSON-formatted output.
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * The test suite uses this tool to drive the JSON formatting routines in
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * libnvpair(3LIB) for testing.
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow */
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow#include <stdlib.h>
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow#include <stdio.h>
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow#include <errno.h>
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow#include <string.h>
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow#include <ctype.h>
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow#include <limits.h>
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow#include <locale.h>
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow#include <libnvpair.h>
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow#define MAX_ARGS 100
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow#define CMD_NAME_LEN 50
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow/*
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * As we are parsing a language that allows the creation of arbitrarily nested
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * state, i.e. both nested nvlists and arrays of nested nvlists, we store that
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * state in a stack. The top frame in the stack represents the nested nvlist
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * (or nvlists, for an array) that we are currently building.
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow *
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * When creating an array, the "next" directive advances lw_pos and allocates a
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * new nvlist. The "end" directive commits either the nvlist, or array of
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * nvlists, into the parent nvlist. It then pops and frees the stack frame
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * before returning control to the parser.
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow */
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowtypedef struct list_wrap {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow nvlist_t *lw_nvl[MAX_ARGS];
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow char *lw_name;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow int lw_pos;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow boolean_t lw_array;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow struct list_wrap *lw_next;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow} list_wrap_t;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowint
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowlist_wrap_depth(list_wrap_t *lw)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow{
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow int d = 0;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow while (lw != NULL) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow d++;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow lw = lw->lw_next;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (d);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow}
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowlist_wrap_t *
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowlist_wrap_alloc(list_wrap_t *next)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow{
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow list_wrap_t *out = calloc(1, sizeof (list_wrap_t));
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (out == NULL)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow abort();
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow out->lw_next = next;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (out);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow}
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowlist_wrap_t *
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowlist_wrap_pop_and_free(list_wrap_t *lw)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow{
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow list_wrap_t *next = lw->lw_next;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow free(lw->lw_name);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow free(lw);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (next);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow}
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow/*
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * Generic integer and floating point parsing routines:
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow */
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowint
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowparse_int(char *in, int64_t *val, int64_t min, int64_t max)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow{
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow int64_t t;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow char *end = NULL;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow errno = 0;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow t = strtoll(in, &end, 10);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (errno != 0 || end == in || *end != '\0') {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (errno == ERANGE) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "ERROR: integer %s not in "
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow "range [%lld,%lld]\n", in, min, max);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "ERROR: could not parse \"%s\" as "
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow "signed integer (%s)\n", in, strerror(errno));
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (t < min || t > max) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "ERROR: integer %lld not in range "
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow "[%lld,%lld]\n", t, min, max);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow *val = t;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (0);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow}
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowint
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowparse_uint(char *in, uint64_t *val, uint64_t min, uint64_t max)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow{
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow uint64_t t;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow char *end = NULL;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow errno = 0;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow t = strtoull(in, &end, 10);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (errno != 0 || end == in || *end != '\0') {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (errno == ERANGE) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "ERROR: integer %s not in "
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow "range [%llu,%llu]\n", in, min, max);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "ERROR: could not parse \"%s\" as "
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow "unsigned integer (%s)\n", in, strerror(errno));
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (t < min || t > max) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "ERROR: integer %llu not in range "
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow "[%llu,%llu]\n", t, min, max);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow *val = t;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (0);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow}
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowint
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowparse_double(char *in, double *val)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow{
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow double t;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow char *end = NULL;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow errno = 0;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow t = strtod(in, &end);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (errno != 0 || end == in || *end != '\0') {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "ERROR: could not parse \"%s\" as "
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow "double\n", in);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow *val = t;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (0);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow}
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow/*
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * Command-specific handlers for directives specified in the DSL input:
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow */
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowtypedef int (*command_handler_t)(list_wrap_t **, boolean_t, int,
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow char **);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowstatic int
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowch_add_string(list_wrap_t **lw, boolean_t array, int argc, char **argv)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow{
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow nvlist_t *nvl = (*lw)->lw_nvl[(*lw)->lw_pos];
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (array) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (nvlist_add_string_array(nvl, argv[0], &argv[1],
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow argc - 1) != 0) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "fail at "
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow "nvlist_add_string_array\n");
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (nvlist_add_string(nvl, argv[0], argv[1]) != 0) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "fail at nvlist_add_string\n");
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (0);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow}
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowstatic int
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowch_add_boolean(list_wrap_t **lw, boolean_t array, int argc, char **argv)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow{
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow nvlist_t *nvl = (*lw)->lw_nvl[(*lw)->lw_pos];
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (array)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow abort();
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (nvlist_add_boolean(nvl, argv[0]) != 0) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "fail at nvlist_add_boolean\n");
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (0);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow}
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowstatic int
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowch_add_boolean_value(list_wrap_t **lw, boolean_t array, int argc, char **argv)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow{
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow int i;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow nvlist_t *nvl = (*lw)->lw_nvl[(*lw)->lw_pos];
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow boolean_t arrval[MAX_ARGS];
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow for (i = 1; i < argc; i++) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (strcmp(argv[i], "true") == 0) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow arrval[i - 1] = B_TRUE;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else if (strcmp(argv[i], "false") == 0) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow arrval[i - 1] = B_FALSE;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "invalid boolean value: %s\n",
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow argv[i]);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (array) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (nvlist_add_boolean_array(nvl, argv[0], arrval,
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow argc - 1) != 0) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "fail at "
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow "nvlist_add_boolean_array\n");
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (nvlist_add_boolean_value(nvl, argv[0], arrval[0]) != 0) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "fail at "
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow "nvlist_add_boolean_value\n");
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (0);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow}
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow/*
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * The confluence of a strongly typed C API for libnvpair(3LIB) and the
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * combinatorial explosion of both sizes and signedness is unfortunate. Rather
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * than reproduce the same code over and over, this macro parses an integer,
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * checks applicable bounds based on size and signedness, and stores the value
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * (or array of values).
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow */
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow#define DO_CMD_NUMBER(typ, nam, min, max, ptyp, func) \
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow ptyp val; \
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow typ ## _t arrval[MAX_ARGS]; \
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow int i; \
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow for (i = 1; i < argc; i++) { \
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (func(argv[i], &val, min, max) != 0) { \
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1); \
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } \
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow arrval[i - 1] = (typ ## _t) val; \
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } \
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (array) { \
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (nvlist_add_ ## nam ## _array(nvl, argv[0], \
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow arrval, argc - 1) != 0) { \
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "fail at " \
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow "nvlist_add_" #nam "_array\n"); \
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1); \
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } \
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else { \
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (nvlist_add_ ## nam(nvl, argv[0], \
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow arrval[0]) == -1) { \
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "fail at " \
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow "nvlist_add_" #nam "\n"); \
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1); \
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } \
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } \
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (0);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowstatic int
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowch_add_byte(list_wrap_t **lw, boolean_t array, int argc, char **argv)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow{
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow nvlist_t *nvl = (*lw)->lw_nvl[(*lw)->lw_pos];
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow DO_CMD_NUMBER(uchar, byte, 0, UCHAR_MAX, uint64_t, parse_uint)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow}
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowstatic int
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowch_add_int8(list_wrap_t **lw, boolean_t array, int argc, char **argv)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow{
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow nvlist_t *nvl = (*lw)->lw_nvl[(*lw)->lw_pos];
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow DO_CMD_NUMBER(int8, int8, INT8_MIN, INT8_MAX, int64_t, parse_int)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow}
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowstatic int
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowch_add_uint8(list_wrap_t **lw, boolean_t array, int argc, char **argv)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow{
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow nvlist_t *nvl = (*lw)->lw_nvl[(*lw)->lw_pos];
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow DO_CMD_NUMBER(uint8, uint8, 0, UINT8_MAX, uint64_t, parse_uint)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow}
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowstatic int
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowch_add_int16(list_wrap_t **lw, boolean_t array, int argc, char **argv)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow{
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow nvlist_t *nvl = (*lw)->lw_nvl[(*lw)->lw_pos];
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow DO_CMD_NUMBER(int16, int16, INT16_MIN, INT16_MAX, int64_t, parse_int)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow}
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowstatic int
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowch_add_uint16(list_wrap_t **lw, boolean_t array, int argc, char **argv)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow{
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow nvlist_t *nvl = (*lw)->lw_nvl[(*lw)->lw_pos];
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow DO_CMD_NUMBER(uint16, uint16, 0, UINT16_MAX, uint64_t, parse_uint)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow}
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowstatic int
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowch_add_int32(list_wrap_t **lw, boolean_t array, int argc, char **argv)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow{
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow nvlist_t *nvl = (*lw)->lw_nvl[(*lw)->lw_pos];
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow DO_CMD_NUMBER(int32, int32, INT32_MIN, INT32_MAX, int64_t, parse_int)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow}
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowstatic int
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowch_add_uint32(list_wrap_t **lw, boolean_t array, int argc, char **argv)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow{
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow nvlist_t *nvl = (*lw)->lw_nvl[(*lw)->lw_pos];
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow DO_CMD_NUMBER(uint32, uint32, 0, UINT32_MAX, uint64_t, parse_uint)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow}
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowstatic int
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowch_add_int64(list_wrap_t **lw, boolean_t array, int argc, char **argv)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow{
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow nvlist_t *nvl = (*lw)->lw_nvl[(*lw)->lw_pos];
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow DO_CMD_NUMBER(int64, int64, INT64_MIN, INT64_MAX, int64_t, parse_int)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow}
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowstatic int
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowch_add_uint64(list_wrap_t **lw, boolean_t array, int argc, char **argv)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow{
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow nvlist_t *nvl = (*lw)->lw_nvl[(*lw)->lw_pos];
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow DO_CMD_NUMBER(uint64, uint64, 0, UINT64_MAX, uint64_t, parse_uint)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow}
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowstatic int
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowch_add_double(list_wrap_t **lw, boolean_t array, int argc, char **argv)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow{
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow nvlist_t *nvl = (*lw)->lw_nvl[(*lw)->lw_pos];
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow double val;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (array)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow abort();
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (parse_double(argv[1], &val) != 0) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (nvlist_add_double(nvl, argv[0], val) != 0) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "fail at nvlist_add_double_value\n");
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (0);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow}
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowstatic int
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowch_end(list_wrap_t **lw, boolean_t array, int argc, char **argv)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow{
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow nvlist_t *parent;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow char *name;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (list_wrap_depth(*lw) < 2) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "ERROR: not nested, cannot end.\n");
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow parent = (*lw)->lw_next->lw_nvl[(*lw)->lw_next->lw_pos];
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow name = (*lw)->lw_name;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if ((*lw)->lw_array) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow /*
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * This was an array of objects.
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow */
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow nvlist_t **children = (*lw)->lw_nvl;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow int nelems = (*lw)->lw_pos + 1;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (nvlist_add_nvlist_array(parent, name, children,
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow nelems) != 0) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "fail at "
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow "nvlist_add_nvlist_array\n");
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow /*
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * This was a single object.
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow */
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow nvlist_t *child = (*lw)->lw_nvl[0];
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if ((*lw)->lw_pos != 0)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow abort();
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (nvlist_add_nvlist(parent, name, child) != 0) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "fail at nvlist_add_nvlist\n");
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow *lw = list_wrap_pop_and_free(*lw);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (0);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow}
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowstatic int
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowch_next(list_wrap_t **lw, boolean_t array, int argc, char **argv)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow{
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (!(*lw)->lw_array) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "ERROR: cannot use 'next' outside an "
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow "object array.\n");
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if ((*lw)->lw_pos++ >= MAX_ARGS) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "ERROR: object array too long\n");
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (nvlist_alloc(&(*lw)->lw_nvl[(*lw)->lw_pos], NV_UNIQUE_NAME,
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow 0) != 0) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "ERROR: failed at nvlist_alloc\n");
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (0);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow}
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowstatic int
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowch_add_object(list_wrap_t **lw, boolean_t array, int argc, char **argv)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow{
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow *lw = list_wrap_alloc(*lw);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (*lw)->lw_name = strdup(argv[0]);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (*lw)->lw_array = array;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (nvlist_alloc(&(*lw)->lw_nvl[0], NV_UNIQUE_NAME, 0) != 0) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "fail at nvlist_alloc\n");
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (0);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow}
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowtypedef struct command {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow char cmd_name[CMD_NAME_LEN];
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow command_handler_t cmd_func;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow int cmd_min_args;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow int cmd_max_args;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow boolean_t cmd_array_mode;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow} command_t;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow/*
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * These are the commands we support in the testing DSL, and their
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * handling functions:
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow */
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowcommand_t command_handlers[] = {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "add_boolean", ch_add_boolean, 1, 1, B_FALSE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "add_boolean_value", ch_add_boolean_value, 2, 2, B_FALSE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "add_byte", ch_add_byte, 2, 2, B_FALSE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "add_int8", ch_add_int8, 2, 2, B_FALSE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "add_uint8", ch_add_uint8, 2, 2, B_FALSE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "add_int16", ch_add_int16, 2, 2, B_FALSE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "add_uint16", ch_add_uint16, 2, 2, B_FALSE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "add_int32", ch_add_int32, 2, 2, B_FALSE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "add_uint32", ch_add_uint32, 2, 2, B_FALSE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "add_int64", ch_add_int64, 2, 2, B_FALSE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "add_uint64", ch_add_uint64, 2, 2, B_FALSE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "add_double", ch_add_double, 2, 2, B_FALSE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "add_string", ch_add_string, 2, 2, B_FALSE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "add_object", ch_add_object, 1, 1, B_FALSE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "add_boolean_array", ch_add_boolean_value, 1, MAX_ARGS, B_TRUE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "add_byte_array", ch_add_byte, 1, MAX_ARGS, B_TRUE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "add_int8_array", ch_add_int8, 1, MAX_ARGS, B_TRUE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "add_uint8_array", ch_add_uint8, 1, MAX_ARGS, B_TRUE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "add_int16_array", ch_add_int16, 1, MAX_ARGS, B_TRUE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "add_uint16_array", ch_add_uint16, 1, MAX_ARGS, B_TRUE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "add_int32_array", ch_add_int32, 1, MAX_ARGS, B_TRUE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "add_uint32_array", ch_add_uint32, 1, MAX_ARGS, B_TRUE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "add_int64_array", ch_add_int64, 1, MAX_ARGS, B_TRUE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "add_uint64_array", ch_add_uint64, 1, MAX_ARGS, B_TRUE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "add_string_array", ch_add_string, 1, MAX_ARGS, B_TRUE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "add_object_array", ch_add_object, 1, 1, B_TRUE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "end", ch_end, 0, 0, B_FALSE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { "next", ch_next, 0, 0, B_FALSE },
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow { 0 }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow};
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow/*
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * This function determines which command we are executing, checks argument
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * counts, and dispatches to the appropriate handler:
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow */
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowstatic int
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowcommand_call(list_wrap_t **lw, char *command, int argc, char **argv)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow{
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow int ch;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow for (ch = 0; command_handlers[ch].cmd_name[0] != '\0'; ch++) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (strcmp(command, command_handlers[ch].cmd_name) != 0)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow continue;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (argc > command_handlers[ch].cmd_max_args ||
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow argc < command_handlers[ch].cmd_min_args) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "ERROR: command \"%s\""
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow " expects between %d and %d arguments,"
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow " but %d were provided.\n", command,
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow command_handlers[ch].cmd_min_args,
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow command_handlers[ch].cmd_max_args,
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow argc);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (command_handlers[ch].cmd_func(lw,
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow command_handlers[ch].cmd_array_mode, argc, argv));
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "ERROR: invalid command: \"%s\"\n", command);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow}
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow/*
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * The primary state machine for parsing the input DSL is implemented in
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * this function:
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow */
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowtypedef enum state {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow STATE_REST = 1,
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow STATE_COMMAND,
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow STATE_ARG_FIND,
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow STATE_ARG,
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow STATE_ARG_ESCAPE,
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow STATE_ARG_ESCAPE_HEX,
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow STATE_C_COMMENT_0,
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow STATE_C_COMMENT_1,
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow STATE_C_COMMENT_2
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow} state_t;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowint
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowparse(FILE *in, list_wrap_t **lw)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow{
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow char b[8192];
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow int bp;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow state_t st = STATE_REST;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow int argc = 0;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow char *argv[MAX_ARGS];
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow int line = 1;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow char hex[3];
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow int nhex = 0;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow b[0] = '\0';
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow bp = 0;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow for (;;) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow int c = fgetc(in);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow /*
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * Signal an error if the file ends part way through a
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * construct:
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow */
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (st != STATE_REST && c == EOF) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "ERROR: unexpected end of "
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow "file\n");
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else if (c == EOF) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (0);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (c == '\n')
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow line++;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow switch (st) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow case STATE_REST:
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (isalpha(c) || c == '_') {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow argc = 0;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow bp = 0;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow b[bp++] = c;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow b[bp] = '\0';
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow st = STATE_COMMAND;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow continue;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else if (c == ' ' || c == '\t' || c == '\n') {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow /*
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * Ignore whitespace.
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow */
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow continue;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else if (c == '/') {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow st = STATE_C_COMMENT_0;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow continue;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow goto unexpected;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow case STATE_C_COMMENT_0:
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (c != '*') {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow goto unexpected;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow st = STATE_C_COMMENT_1;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow continue;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow case STATE_C_COMMENT_1:
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (c == '*') {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow st = STATE_C_COMMENT_2;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow continue;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow case STATE_C_COMMENT_2:
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (c == '/') {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow st = STATE_REST;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else if (c != '*') {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow st = STATE_C_COMMENT_1;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow continue;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow case STATE_COMMAND:
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (isalnum(c) || c == '_') {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow b[bp++] = c;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow b[bp] = '\0';
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow st = STATE_COMMAND;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow continue;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else if (isspace(c)) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow /*
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * Start collecting arguments into 'b'
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * after the command.
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow */
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow st = STATE_ARG_FIND;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow bp++;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow continue;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else if (c == ';') {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow /*
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * This line was _just_ a command,
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * so break out and process now:
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow */
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow goto execute;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow goto unexpected;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow case STATE_ARG_FIND:
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (isspace(c)) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow /*
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * Whitespace, ignore.
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow */
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow continue;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else if (c == ';') {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow /*
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * Break out to process command.
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow */
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow goto execute;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else if (c == '"') {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow st = STATE_ARG;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow argv[argc] = &b[++bp];
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow b[bp] = '\0';
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow continue;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow goto unexpected;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow case STATE_ARG:
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (c == '"') {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (argc++ >= MAX_ARGS) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "ERROR: too "
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow "many args\n");
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow st = STATE_ARG_FIND;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow continue;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else if (c == '\n') {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "ERROR: line not "
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow "finished\n");
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else if (c == '\\') {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow st = STATE_ARG_ESCAPE;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow continue;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow b[bp++] = c;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow b[bp] = '\0';
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow continue;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow case STATE_ARG_ESCAPE:
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (c == 'a') {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow c = '\a';
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else if (c == 'b') {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow c = '\b';
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else if (c == 'f') {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow c = '\f';
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else if (c == 'n') {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow c = '\n';
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else if (c == 'r') {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow c = '\r';
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else if (c == 't') {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow c = '\t';
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else if (c == 'v') {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow c = '\v';
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else if (c == 'x') {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow st = STATE_ARG_ESCAPE_HEX;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow hex[0] = hex[1] = hex[2] = '\0';
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow nhex = 0;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow continue;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow } else if (c != '\\' && c != '"') {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow goto unexpected;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow b[bp++] = c;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow b[bp] = '\0';
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow st = STATE_ARG;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow continue;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow case STATE_ARG_ESCAPE_HEX:
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (!isxdigit(c)) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow goto unexpected;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow hex[nhex] = c;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (nhex++ >= 1) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow /*
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * The hex escape pair is complete, parse
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * the integer and insert it as a character:
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow */
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow int x;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow errno = 0;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if ((x = strtol(hex, NULL, 16)) == 0 ||
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow errno != 0) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow goto unexpected;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow b[bp++] = (char)x;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow b[bp] = '\0';
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow st = STATE_ARG;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow continue;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow /*
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * We do not ever expect to break out of the switch block
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * above. If we do, it's a programmer error.
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow */
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow abort();
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowexecute:
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (command_call(lw, b, argc, argv) == -1)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow st = STATE_REST;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow continue;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowunexpected:
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "ERROR: (line %d) unexpected "
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow "character: %c\n", line, c);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (-1);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow}
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow/*
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * Entry point:
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow */
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowint
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowmain(int argc, char **argv)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow{
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow int rc = EXIT_FAILURE;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow list_wrap_t *lw;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow /*
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * Be locale-aware. The JSON output functions will process multibyte
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * characters in the current locale, and emit a correct JSON encoding
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * for unprintable characters.
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow */
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (setlocale(LC_ALL, "") == NULL) {
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) fprintf(stderr, "Could not set locale: %s\n",
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow strerror(errno));
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow goto out;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow }
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow lw = list_wrap_alloc(NULL);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (nvlist_alloc(&lw->lw_nvl[0], NV_UNIQUE_NAME, 0) != 0)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow goto out;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow /*
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * Generate the list from the commands passed to us on stdin:
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow */
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (parse(stdin, &lw) != 0)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow goto out;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow /*
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow * Print the resultant list, and a terminating newline:
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow */
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow if (nvlist_print_json(stdout, lw->lw_nvl[0]) != 0 ||
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow fprintf(stdout, "\n") < 0)
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow goto out;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow rc = EXIT_SUCCESS;
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulowout:
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow (void) list_wrap_pop_and_free(lw);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow return (rc);
37c79205ad46187f54b2edbf6a468160935f14d9Joshua M. Clulow}