Beispiel #1
0
static void command_switch(void)
{
	input_port_entry *switch_name;
	input_port_entry *switch_setting;

	find_switch(current_command->u.switch_args.name, current_command->u.switch_args.value,
		IPT_DIPSWITCH_NAME, IPT_DIPSWITCH_SETTING, &switch_name, &switch_setting);

	if (!switch_name || !switch_setting)
	{
		find_switch(current_command->u.switch_args.name, current_command->u.switch_args.value,
			IPT_CONFIG_NAME, IPT_CONFIG_SETTING, &switch_name, &switch_setting);
	}

	if (!switch_name)
	{
		state = STATE_ABORTED;
		report_message(MSG_FAILURE, "Cannot find switch named '%s'", current_command->u.switch_args.name);
		return;
	}

	if (!switch_setting)
	{
		state = STATE_ABORTED;
		report_message(MSG_FAILURE, "Cannot find setting '%s' on switch '%s'",
			current_command->u.switch_args.value, current_command->u.switch_args.name);
		return;
	}

	switch_name->default_value = switch_setting->default_value;
}
static void command_switch(running_machine &machine)
{
	int found_field;
	const input_setting_config *setting;

	/* special hack until we support video targets natively */
	if (!strcmp(current_command->u.switch_args.name, "Video type"))
	{
		render_target *target = machine.render().target_by_index(0);
		int view_index = 0;
		const char *view_name;

		while((view_name = target->view_name(view_index)) != NULL)
		{
			if (!strcmp(view_name, current_command->u.switch_args.value))
				break;
			view_index++;
		}

		if (view_name)
		{
			target->set_view(view_index);
			return;
		}
	}

	/* first try dip switches */
	setting = find_switch(machine, current_command->u.switch_args.name,
		current_command->u.switch_args.value, IPT_DIPSWITCH, &found_field);

	if (setting == NULL)
	{
		/* failing that, try configs */
		setting = find_switch(machine, current_command->u.switch_args.name,
			current_command->u.switch_args.value, IPT_CONFIG, &found_field);
	}

	if (setting == NULL)
	{
		/* now failing that, really fail - lets report a good message */
		if (found_field)
		{
			report_message(MSG_FAILURE, "Cannot find setting '%s' on switch '%s'",
				current_command->u.switch_args.value, current_command->u.switch_args.name);
		}
		else
		{
			report_message(MSG_FAILURE, "Cannot find switch named '%s'", current_command->u.switch_args.name);
		}
		state = STATE_ABORTED;
		return;
	}

	/* success! */
	/* FIXME */
	/* switch_name->default_value = setting->value; */
}
Beispiel #3
0
static void command_switch(void)
{
	input_port_entry *switch_name;
	input_port_entry *switch_setting;

	/* special hack until we support video targets natively */
	if (!strcmp(current_command->u.switch_args.name, "Video type"))
	{
		render_target *target = render_target_get_indexed(0);
		int view_index = 0;
		const char *view_name;

		while((view_name = render_target_get_view_name(target, view_index)) != NULL)
		{
			if (!strcmp(view_name, current_command->u.switch_args.value))
				break;
			view_index++;
		}
		
		if (view_name)
		{
			render_target_set_view(target, view_index);
			return;
		}
	}

	find_switch(current_command->u.switch_args.name, current_command->u.switch_args.value,
		IPT_DIPSWITCH_NAME, IPT_DIPSWITCH_SETTING, &switch_name, &switch_setting);

	if (!switch_name || !switch_setting)
	{
		find_switch(current_command->u.switch_args.name, current_command->u.switch_args.value,
			IPT_CONFIG_NAME, IPT_CONFIG_SETTING, &switch_name, &switch_setting);
	}

	if (!switch_name)
	{
		state = STATE_ABORTED;
		report_message(MSG_FAILURE, "Cannot find switch named '%s'", current_command->u.switch_args.name);
		return;
	}

	if (!switch_setting)
	{
		state = STATE_ABORTED;
		report_message(MSG_FAILURE, "Cannot find setting '%s' on switch '%s'",
			current_command->u.switch_args.value, current_command->u.switch_args.name);
		return;
	}

	switch_name->default_value = switch_setting->default_value;
}
Beispiel #4
0
bool CmdLineOptions::get_switch(std::string const &switch_name) const {
  SwitchOptList::const_iterator found = find_switch(switch_name);
  if (found != switchOptionList_.end()) {
    return found->get();
  }
  return false;
}
Beispiel #5
0
void CmdLineOptions::parse(int argc, char **argv, StringList &left_overs) {
  std::unique_lock<std::mutex> l(mutex_);
  left_overs.clear();

  auto get_nice_program_name = [argv]() -> std::string {
    std::string result = std::string(argv[0]);
    // Remove everything but the command's name.
    size_t const pos = result.find_last_of("/");
    if (pos != result.npos) {
      if (pos + 1 < result.size()) {
        result = result.substr(pos);
      }
    }
    return result;
  };
  programName_ = get_nice_program_name();

  StringList listOfOptionsWithNoValue;

  for (int i(1); i < argc; ++i) {
    int const next = (i + 1) < argc ? i + 1 : -1;

    std::string arg(argv[i]);
    {
      SwitchOptList::iterator it = find_switch(arg);
      if (it != switchOptionList_.end()) {
        it->set(!it->get_default());
        continue;
      }
    }
    {
      ArgOptList::iterator it = find_arg(arg);
      if (it != argOptionList_.end()) {
        if (next != -1) {
          it->set(argv[next]);
          ++i;
          continue;
        } else {
          listOfOptionsWithNoValue.push_back(arg);
          continue;
        }
      }
    }

    // not an option :/
    left_overs.push_back(arg);
  }

  // check for the help switch.
  if (get_switch(HELP_SWITCH_NAME)) {
    print_usage(stdStream_);
    exit(EXIT_SUCCESS);
  }

  StringList listOfMissingRequiredOptions;
  StringList listOfInvalidOptions;
  for (StringOption const &option : argOptionList_) {
    if (!option.is_set() && option.is_required()) {
      listOfMissingRequiredOptions.push_back(option.name());
    } else {
      // Validate the argument
      ValidatorFunctionMap::const_iterator it = validatorFunctionMap_.find(
          option.name());
      if (it != validatorFunctionMap_.end()) {
        ValidatorFunctionList const &list(it->second);
        for (ValidatorFunction const &validator : list) {
          if (!validator(option.name(), option.get())) {
            listOfInvalidOptions.push_back(option.name());
          }
        }
      }
    }
  }

  parserResultHandler_(left_overs, listOfMissingRequiredOptions,
                       listOfOptionsWithNoValue, listOfInvalidOptions);
}
Beispiel #6
0
bool CmdLineOptions::is_switch(std::string const &name) const {
  SwitchOptList::const_iterator it = find_switch(name);
  return it != switchOptionList_.end();
}
Beispiel #7
0
const unsigned char*
do_action( const unsigned char* action, CIStream* args, COStream out) {
    const unsigned char* as;
    unsigned char ac;
    int argn = 0;

    as = action;
    if ( as != NULL )
        for ( ; ; ) {
            ac = *as++;
            switch (ac) {
            case PT_END:
                return as-1;
            case PT_SEPARATOR:
                return as;
            case PT_PUT_ARG: {
                CIStream arg = args[ (*as++) - 1 ];
                cis_rewind(arg);
                cos_copy_input_stream(out,arg);
                break;
            }
            case PT_ONE_OPT:
                cos_putch(out,arg_char);
                break;

            case PT_DOMAIN: {
                CIStream inbuf;
                Pattern save_rule = current_rule;
#if MAX_DOMAINS < 256
                int domain = *as++ - 1;
#else
                /* Get domain index as 14 bit little endian number */
                int domain = ((unsigned char)*as++)&0x7f;
                domain = ((((unsigned char)*as++)&0x7f)<<7) | domain;
#endif
                if ( as[0] == PT_VAR1 ||
                        ( as[0] == PT_OP &&
                          ( as[1] == OP_VAR || as[1] == OP_VAR_DFLT ) ) ) {
                    /* for safety, copy the variable's value in case it is
                       changed during translation.  */
                    COStream outbuf;
                    outbuf = make_buffer_output_stream();
                    as = do_action( as, args, outbuf );
                    inbuf = convert_output_to_input( outbuf );
                }
                else /* optimized operand access */
                    inbuf = function_operand( &as, args );
#ifdef TRACE
                if ( trace_switch ) {
                    int n;
                    fprintf( stderr, "%12ld,%2d ",
                             cis_line(input_stream), cis_column(input_stream));
                    for ( n = trace_indent ; n > 0 ; n-- )
                        fputc(' ',stderr);
                    if ( cis_is_file(inbuf) ) {
                        const char* inpath = cis_pathname(inbuf);
                        if ( inpath == NULL )
                            inpath = "-";
                        fprintf( stderr, "@%s{@read{%s}}\n",
                                 domains[domain]->name, inpath);
                    }
                    else
                        fprintf( stderr, "@%s{%.60s}\n",
                                 domains[domain]->name, cis_whole_string(inbuf));
                    ++trace_indent;
                }
#endif
                if ( !translate( inbuf, domains[domain], out, NULL ) &&
                        cis_is_file(inbuf) && exit_status < EXS_FAIL )
                    exit_status = EXS_FAIL;
#ifdef TRACE
                if ( trace_switch ) {
                    --trace_indent;
                }
#endif
                current_rule = save_rule;
                cis_close(inbuf);
                break;
            }

            case PT_VAR1: {
                char vname[2];
                vname[0] = *as++;
                vname[1] = '\0';
                put_var(out, vname, FALSE);
                break;
            }

            case PT_LINE:
                cos_freshline(out);
                break;

            case PT_MATCHED_TEXT:
                do_action( current_rule->pattern, args, out );
                break;

            case PT_SPECIAL_ARG:
#if MAX_DOMAINS >= 256 /* advance one more since  2 bytes for domain index */
            case PT_RECUR:
#endif
                as++;
            case PT_REGEXP:
#if MAX_DOMAINS < 256
            case PT_RECUR:
#endif
                as++;
            case PT_MATCH_ANY:
            case PT_MATCH_ONE: {
                /* these will be encountered only when replaying the template as $0 */
                CIStream arg = args[ argn++ ];
                cis_rewind(arg);
                cos_copy_input_stream(out,arg);
                break;
            }

            case PT_AUX:
                as++;
                break;

            case PT_OP: {
                CIStream inbuf = NULL;
                enum Operators ac;
                ac = (enum Operators)*as++;
                switch(ac) {
                case OP_UNDEFINE:
                case OP_DEFINE: {
                    inbuf = function_operand( &as, args );
                    read_patterns(inbuf, "", ac==OP_UNDEFINE);
                    break;
                }

                case OP_SUBST: {
                    int d;
                    CIStream arg;
                    Pattern save_rule = current_rule;
                    arg = function_operand( &as, args );
                    d = read_patterns(arg," temp ",FALSE);
                    inbuf = function_operand( &as, args );
                    translate ( inbuf, domains[d], out, NULL );
                    current_rule = save_rule;
                    delete_domain(d);
                    cis_close(arg);
                    break;
                }

                case OP_VAR: {
                    inbuf = function_operand( &as, args );
                    put_var(out, cis_whole_string(inbuf), FALSE );
                    break;
                }
                case OP_VAR_DFLT: {
                    inbuf = function_operand( &as, args ); /* variable name */
                    if ( put_var(out, cis_whole_string(inbuf), TRUE ) )
                        as = skip_action(as); /* skip default value */
                    else as = do_action( as, args, out ); /* output default */
                    break;
                }

                case OP_SET: {
                    CIStream name;
                    name = function_operand( &as, args );
                    inbuf = function_operand( &as, args );
                    set_var( cis_whole_string(name),
                             cis_whole_string(inbuf), cis_length(inbuf) );
                    cis_close(name);
                    break;
                }

                case OP_BIND: {
                    CIStream name;
                    name = function_operand( &as, args );
                    inbuf = function_operand( &as, args );
                    bind_var( cis_whole_string(name),
                              cis_whole_string(inbuf), cis_length(inbuf) );
                    cis_close(name);
                    break;
                }
                case OP_UNBIND: {
                    CIStream name;
                    name = function_operand( &as, args );
                    unbind_var( cis_whole_string(name) );
                    cis_close(name);
                    break;
                }

                case OP_APPEND: {
                    CIStream name;
                    name = function_operand( &as, args );
                    inbuf = function_operand( &as, args );
                    append_var( cis_whole_string(name),
                                cis_whole_string(inbuf), cis_length(inbuf) );
                    cis_close(name);
                    break;
                }

                case OP_INCR:
                case OP_DECR: {
                    CIStream name;
                    name = function_operand( &as, args );
                    incr_var( cis_whole_string(name), ac==OP_DECR? -1 : 1 );
                    cis_close(name);
                    break;
                }

                case OP_GETENV:
                case OP_GETENV_DEFAULT: {
                    CIStream dbuf = NULL;
                    char* value;
                    inbuf = function_operand( &as, args );
                    if ( ac == OP_GETENV_DEFAULT )
                        dbuf = function_operand( &as, args );
                    value = getenv(cis_whole_string(inbuf));
                    if ( value == NULL )
                        cos_copy_input_stream(out, dbuf);
                    else cos_puts(out, value);
                    cis_close(dbuf);
                    break;
                }

                case OP_ERR: {
                    static COStream err_stream = NULL;
                    if ( err_stream == NULL )
                        err_stream = make_file_output_stream(stderr,"stderr");
                    as = do_action( as, args, err_stream );
                    break;
                }

                case OP_OUT: {
                    as = do_action( as, args, output_stream );
                    break;
                }

                case OP_PATH:
                case OP_FILE: {
                    const char* path = cis_pathname(input_stream);
                    if ( path != NULL ) {
                        if ( ac == OP_FILE )
                            path = pathname_name_and_type(path);
                        cos_puts(out, path);
                    }
                    break;
                }
                case OP_OUTFILE: {
                    const char* opath;
                    opath = cos_pathname(out);
                    if ( opath == NULL )
                        opath = cos_pathname(output_stream);
                    cos_puts(out, opath);
                    break;
                }

                case OP_LINE: {
                    put_number(out, cis_line(input_stream));
                    break;
                }
                case OP_COL: {
                    put_number(out, cis_column(input_stream));
                    break;
                }
                case OP_OUTCOL: {
                    put_number(out, cos_column(output_stream));
                    break;
                }
                case OP_HELP:
                    usage();
                    break;
                case OP_VERSION:
                    cos_puts(out, Version);
                    break;

                case OP_DATE:
                case OP_TIME: {
                    time_t now;
                    struct tm* ts;
                    char tbuf [12];
                    now = time(NULL);
                    ts = localtime(&now);
                    if ( ac == OP_TIME )
                        sprintf(tbuf, "%02d:%02d:%02d",
                                ts->tm_hour, ts->tm_min, ts->tm_sec);
                    else sprintf(tbuf, "%02d/%02d/%d",
                                     ts->tm_mon + 1, ts->tm_mday, 1900 + ts->tm_year);
                    cos_puts(out, tbuf);
                    break;
                }
                case OP_DATIME: {
                    time_t now;
                    now = time(NULL);
                    put_datime( out, &now );
                    break;
                }
                case OP_MODTIME: {
                    time_t mtime;
                    mtime = cis_mod_time(input_stream);
                    if ( mtime != 0 )
                        put_datime( out, &mtime );
                    break;
                }
                case OP_PROBE: {
                    inbuf = function_operand( &as, args );
                    cos_putch(out, probe_pathname(cis_whole_string(inbuf)));
                    break;
                }

                case OP_READ: {
                    const char* pathname;
                    CIStream in;
                    inbuf = function_operand( &as, args );
                    pathname = cis_whole_string(inbuf);
                    close_output(pathname);
                    in = open_input_file(pathname,binary);
                    cos_copy_input_stream(out, in);
                    cis_close(in);
                    break;
                }

                case OP_WRITE: {
                    COStream oldout;
                    const char* pathname;
                    oldout = output_stream;
                    inbuf = function_operand( &as, args );
                    pathname = cis_whole_string(inbuf);
                    output_stream = find_output_file(pathname,TRUE);
                    as = do_action( as, args, output_stream );
                    output_stream = oldout;
                    break;
                }

                case OP_CLOSE: {
                    inbuf = function_operand( &as, args );
                    close_output(cis_whole_string(inbuf));
                    break;
                }

                case OP_COMBINEPATH:
                case OP_MERGEPATH: {
                    CIStream dir;
                    CIStream name;
                    CIStream typ;
                    dir = function_operand( &as, args );
                    name = function_operand( &as, args );
                    typ = function_operand( &as, args );
                    merge_pathnames( out, ac==OP_COMBINEPATH, cis_whole_string(dir),
                                     cis_whole_string(name),
                                     cis_whole_string(typ) );
                    cis_close(dir);
                    cis_close(name);
                    cis_close(typ);
                    break;
                }
                case OP_RELPATH: {
                    CIStream dir;
                    dir = function_operand( &as, args );
                    inbuf = function_operand( &as, args );
                    cos_puts( out, relative_pathname(cis_whole_string(dir),
                                                     cis_whole_string(inbuf)) );
                    cis_close(dir);
                    break;
                }
                case OP_EXP_WILD: {
                    inbuf = function_operand( &as, args );
                    expand_wildcard ( cis_whole_string(inbuf), out );
                    break;
                }

                case OP_ADD:
                case OP_SUB:
                case OP_MUL:
                case OP_DIV:
                case OP_MOD:
                case OP_AND:
                case OP_OR: {
                    long x,y,z;
                    x = numeric_operand( &as, args );
                    y = numeric_operand( &as, args );
                    switch(ac) {
                    case OP_ADD:
                        z = x + y;
                        break;
                    case OP_SUB:
                        z = x - y;
                        break;
                    case OP_MUL:
                        z = x * y;
                        break;
                    case OP_DIV:
                        z = x / y;
                        break;
                    case OP_MOD:
                        z = x % y;
                        break;
                    case OP_AND:
                        z = x & y;
                        break;
                    case OP_OR:
                        z = x | y;
                        break;
                    default: /* can't happen; just to avoid compiler warning */
                        assert(FALSE);
                        z = 0;
                        break;
                    }
                    put_number(out,z);
                    break;
                }
                case OP_NOT:
                    put_number(out, ~ numeric_operand( &as, args ) );
                    break;

                case OP_RADIX: {
                    int from, to;
                    unsigned long value;
                    char* string;
                    char* end;
                    const char* fmt;
                    char buf[24]; /* enough for 64 bits in octal */
                    from = (int)numeric_operand( &as, args );
                    to = (int)numeric_operand( &as, args );
                    inbuf = function_operand( &as, args );
                    string = cis_whole_string(inbuf);
                    value = strtoul( string, &end, from );
                    if ( *end != '\0' )
                        input_error ( input_stream, EXS_NUM,
                                      "Invalid argument for radix %d conversion: \"%.99s\"\n",
                                      from, string);
                    if ( to == 8 )
                        fmt = "%lo";
                    else if ( to == 16 )
                        fmt = "%lX";
                    else {
                        if ( to != 10 )
                            input_error ( input_stream, EXS_NUM,
                                          "Unsupported radix: %d\n", to);
                        while ( isspace(string[0]) )
                            string++;
                        fmt = (string[0]=='-') ? "%ld" : "%lu";
                    }
                    sprintf(buf, fmt, value);
                    cos_puts(out, buf);
                    break;
                }

                case OP_STR_CMP:
                case OP_STRI_CMP: {	/* string comparison */
                    CIStream x = function_operand( &as, args );
                    CIStream y = function_operand( &as, args );
                    const char* xs = cis_whole_string(x);
                    const char* ys = cis_whole_string(y);
                    int cmp;
                    cmp = ac == OP_STRI_CMP ? stricmp(xs, ys) : strcmp(xs, ys);
                    cis_close(x);
                    cis_close(y);
                    as = do_cmp( cmp, as, args, out);
                    break;
                }
                case OP_NUM_CMP: {	/* numeric comparison */
                    long x = numeric_operand( &as, args );
                    long y = numeric_operand( &as, args );
                    int cmp;
                    if ( x < y )
                        cmp = -1;
                    else if ( x == y )
                        cmp = 0;
                    else cmp = 1;
                    as = do_cmp( cmp, as, args, out);
                    break;
                }

                case OP_LENGTH: {
                    inbuf = function_operand( &as, args );
                    put_number(out, cis_length(inbuf));
                    break;
                }

                case OP_TAB: {
                    int col;
                    col = (int)numeric_operand( &as, args );
                    cos_spaces(out, col - (int)cos_column(out));
                    break;
                }

                case OP_WRAP: {
                    unsigned length;
                    unsigned col;
                    inbuf = function_operand( &as, args );
                    length = cis_length(inbuf);
                    col = cos_column(out);
                    if ( ( ((int)(col + length)) > wrap_column &&
                            col > wrap_indent_length ) ||
                            ( col <= 1 && length > 0 ) ) {
                        cos_freshline(out);
                        cos_puts(out, wrap_indent);
                        skip_whitespace(inbuf);
                    }
                    cos_copy_input_stream(out, inbuf);
                    break;
                }

                case OP_SET_WRAP: {
                    wrap_column = (int)numeric_operand( &as, args );
                    inbuf = function_operand( &as, args );
                    if ( wrap_indent != NULL )
                        free(wrap_indent);
                    wrap_indent_length = cis_length(inbuf);
                    wrap_indent = str_dup_len( cis_whole_string(inbuf),
                                               wrap_indent_length );
                    break;
                }

                case OP_RIGHT:
                case OP_LEFT:
                case OP_CENTER: { /* justify value in fixed-length field */
                    int field_length, string_length, left_pad, right_pad;
                    field_length = (int)numeric_operand( &as, args );
                    inbuf = function_operand( &as, args );
                    string_length = cis_length(inbuf);
                    left_pad = field_length - string_length;
                    right_pad = 0;
                    if ( left_pad < 0 )
                        left_pad = 0;
                    if ( ac == OP_LEFT ) {
                        right_pad = left_pad;
                        left_pad = 0;
                    }
                    else if ( ac == OP_CENTER ) {
                        left_pad = left_pad / 2;
                        right_pad = field_length - string_length - left_pad;
                    }
                    cos_spaces(out, left_pad);
                    cos_copy_input_stream(out, inbuf);
                    cos_spaces(out, right_pad);
                    break;
                }

                case OP_FILL_RIGHT:
                case OP_FILL_LEFT:
                case OP_FILL_CENTER: { /* justify value in fixed-length field */
                    int field_length, string_length, left_pad, right_pad;
                    CIStream background;
                    int i;
                    background = function_operand( &as, args );
                    field_length = cis_length(background);
                    inbuf = function_operand( &as, args );
                    string_length = cis_length(inbuf);
                    left_pad = field_length - string_length;
                    right_pad = 0;
                    if ( left_pad < 0 )
                        left_pad = 0;
                    if ( ac == OP_FILL_LEFT ) {
                        right_pad = left_pad;
                        left_pad = 0;
                    }
                    else if ( ac == OP_FILL_CENTER ) {
                        left_pad = left_pad / 2;
                        right_pad = field_length - string_length - left_pad;
                    } else assert( ac == OP_FILL_RIGHT );
                    for ( i = left_pad ; i > 0 ; i-- )
                        cos_putch(out, cis_getch(background));
                    cos_copy_input_stream(out, inbuf);
                    if ( right_pad > 0 ) {
                        for ( i = string_length ; i > 0 ; i-- )
                            (void)cis_getch(background);
                        cos_copy_input_stream(out, background);
                    }
                    cis_close(background);
                    break;
                }

                case OP_SUBSTRING: {
                    int skip_length, result_length, string_length;
                    skip_length = (int)numeric_operand( &as, args );
                    result_length = (int)numeric_operand( &as, args );
                    inbuf = function_operand( &as, args );
                    string_length = cis_length(inbuf);
                    if ( skip_length <= string_length ) {
                        if ( skip_length < 0 )
                            skip_length = 0;
                        if ( (skip_length + result_length) > string_length )
                            result_length = string_length - skip_length;
                        cos_put_len(out, cis_whole_string(inbuf) + skip_length,
                                    result_length);
                    }
                    break;
                }

                case OP_DOWNCASE:
                case OP_UPCASE: {
                    int cc;
                    inbuf = function_operand( &as, args );
                    while ( (cc = cis_getch(inbuf)) != EOF )
                        cos_putch(out, ac==OP_DOWNCASE ? tolower(cc) : toupper(cc) );
                    break;
                }

                case OP_CHARINT:
                    inbuf = function_operand( &as, args );
                    put_number(out, cis_getch(inbuf));
                    break;
                case OP_INTCHAR:
                    cos_putch(out, (char)numeric_operand( &as, args ));
                    break;

                case OP_REVERSE: {
                    int len;
                    const char* start;
                    const char* ip;
                    inbuf = function_operand( &as, args );
                    len = cis_length(inbuf);
                    start = cis_whole_string(inbuf);
                    for ( ip = start+len-1 ; ip >= start ; ip-- )
                        cos_putch(out, *ip);
                    break;
                }

                case OP_SHELL: {
                    const char* command;
                    inbuf = function_operand( &as, args );
                    command = cis_whole_string(inbuf);
                    fflush(stdout);
                    if ( system( command ) < 0 ) {
                        input_error ( input_stream, EXS_SHELL,
                                      "Failed shell command \"%.20s...\":\n", command );
                        perror("system");
                    }
                    break;
                }

                case OP_EXIT:
                    translation_status = Translate_Exited;
                    break;

                case OP_FAIL:
                    translation_status = Translate_Failed;
                    break;

                case OP_END_OR_FAIL:
                    /* ideally this should be testing whether the input stream
                       has been advanced, but that is not so easy. */
                    translation_status =
                        ( cis_out_length(out) == 0 )? Translate_Failed : Translate_Exited;
                    break;

                case OP_EXIT_STATUS:
                    exit_status = (Exit_States)(int)numeric_operand( &as, args );
                    break;

                case OP_ABORT:
                    exit((int)(exit_status > EXS_FAIL ? exit_status : EXS_FAIL ));
                    break;

                case OP_GET_SWITCH:
                case OP_SET_SWITCH: {
                    const char* name;
                    int* valpt;
                    inbuf = function_operand( &as, args );
                    name = cis_whole_string(inbuf);
                    valpt = find_switch(name);
                    if ( valpt == NULL ) {
                        input_error(input_stream, EXS_UNDEF,
                                    "Undefined switch name \"%.99s\"\n", name );
                        if ( ac == OP_SET_SWITCH )
                            (void)numeric_operand( &as, args );
                    }
                    else {
                        if ( ac == OP_SET_SWITCH )
                            *valpt = (int)numeric_operand( &as, args );
                        else
                            put_number( out, *valpt );
                    }
                    break;
                }

                case OP_SET_PARM: {
                    const char* name;
                    CIStream val;
                    inbuf = function_operand( &as, args );
                    name = cis_whole_string(inbuf);
                    val = function_operand( &as, args );
                    if ( !set_parm( name, cis_whole_string(val) ) )
                        input_error(input_stream, EXS_UNDEF,
                                    "Undefined parameter name \"%.99s\"\n", name );
                    cis_close(val);
                    break;
                }

                case OP_SYNTAX: {
                    const char* type;
                    const char* charset;
                    CIStream val;
                    inbuf = function_operand( &as, args );
                    val = function_operand( &as, args );
                    charset = cis_whole_string(val);
                    for ( type = cis_whole_string(inbuf) ; *type != '\0' ; type++ ) {
                        const char* chars;
                        char c[2];
                        if ( type[1] == '\0' )
                            chars = charset;
                        else {
                            c[0] = *charset++;
                            c[1] = '\0';
                            chars = c;
                        }
                        if ( !set_syntax(type[0], chars) )
                            input_error(input_stream, EXS_UNDEF,
                                        "Undefined syntax type \"%.99s\"\n", type );
                    }
                    cis_close(val);
                    break;
                }

                case OP_DEFAULT_SYNTAX:
                    initialize_syntax();
                    break;

#ifndef MSDOS
                case OP_LOCALE: {
                    const char* lname;
                    inbuf = function_operand( &as, args );
                    lname = cis_whole_string(inbuf);
                    if ( setlocale(LC_ALL, lname) == NULL )
                        input_error(input_stream, EXS_UNDEF,
                                    "Undefined locale \"%.99s\"\n", lname );
                    break;
                }
#endif

                case OP_REPEAT: {
                    long n = numeric_operand( &as, args );
                    if ( n <= 0 )
                        as = skip_action(as);
                    else {
                        const unsigned char* start = as;
                        for ( ; n > 0 ; n-- )
                            as = do_action( start, args, out );
                    }
                    break;
                }

                case OP_QUOTE: {
                    inbuf = function_operand( &as, args );
                    quoted_copy( inbuf, out );
                    break;
                }
                default:
                    fprintf(stderr, "Undefined op in action: %d\n", (int)ac);
                    break;

                } /* end switch on ops */
                cis_close(inbuf);
                break;
                } /* end PT_OP */

            case PT_WORD_DELIM:
            case PT_ID_DELIM:
                /* Ignore if in expansion of "$0" */
                if ( current_rule == NULL || action != current_rule->pattern ) {
                    /* output a space if needed as a delimiter */
                    int prevch = cos_prevch(out);
                    if ( prevch != EOF )
                        if ( ac == PT_ID_DELIM ? isident(prevch) : isalnum(prevch) )
                            cos_putch(out,' ');
                }
                break;
#if 0   /* not needed now */
            case PT_ARG_DELIM:
                if ( cos_prevch(out) != Arg_Delim )
                    cos_putch(out,Arg_Delim);
                break;
#endif

            case PT_SPACE: {
                /* output a space if the last character is not white space */
                int prevch = cos_prevch(out);
                if ( !isspace(prevch) )
                    cos_putch(out,' ');
                break;
            }

            case PT_SKIP_WHITE_SPACE:
                break;

            case PT_QUOTE:		/* use next character literally */
                ac = *as++;
            /* and fall-through */
            default:
                cos_putch(out, ac);
            } /* end switch ac */
        } /* end for */
    /* can't ever get here, but return to avoid Gnu compiler warning. */
    return as;
}