/* Set pixel (X,Y) to color C. */
void
bogl_pcfb_pixel (int x, int y, int c)
{
  bogl_drawing = 1;

  assert (x >= 0 && x < bogl_xres);
  assert (y >= 0 && y < bogl_yres);

  put_var (bogl_frame + y * bogl_line_len, x, cmap_lookup(c), bpp);

  bogl_drawing = 0;
}
/* Paints a vertical line from (X,Y1) to (X,Y2) in color C.  The final
   point is not painted. */
void
bogl_pcfb_vline (int x, int y1, int y2, int c)
{
  assert (x >= 0 && x < bogl_xres);
  assert (y1 >= 0 && y1 < bogl_yres);
  assert (y2 >= 0 && y2 <= bogl_yres);
  assert (y2 >= y1);

  bogl_drawing = 1;
  for (; y1 < y2; y1++)
    put_var (bogl_frame + (y1 * bogl_line_len), x, cmap_lookup(c), bpp);
  bogl_drawing = 0;
}
void
bogl_pcfb_move (int sx, int sy, int dx, int dy, int w, int h)
{
  int i, j;

  bogl_drawing = 1;

  /* FIXME: Some clever memmove magic would undoubtedly be more efficient. */
  for (i = 0; i < h; i++)
    {
      for (j = 0; j < w; j++)
	{
	  unsigned int c;
	  c = get_var (bogl_frame + (sy+i) * bogl_line_len, sx+j, bpp);
	  put_var (bogl_frame + (dy+i) * bogl_line_len, dx+j, c, bpp);
	}
    }

  bogl_drawing = 0;
}
Exemplo n.º 4
0
void proc_exp_assign(double *result)
    {
    char temp_token[MAXLEN];
    enum tok_type temp_type;
    int i;
    if (token_type == Variable)
        {
        strcpy(temp_token, cur_token);
        temp_type = token_type;
        i = cur_token[0];
        get_token();
        if (strcmp(cur_token, "=") == 0)   /* if assignment */
            {
            get_token();
            proc_exp_assign(result);
            put_var(i, *result);
            return;
            }
        put_back();
        strcpy(cur_token, temp_token);
        token_type = temp_type;
        }
    proc_exp_relop(result);
    }
/* Draw mouse pointer POINTER with its hotspot at (X,Y), if VISIBLE !=
   0.  Restores the previously saved background at that point, if
   VISIBLE == 0.  COLORS[] gives the color indices to paint the
   cursor.

   This routine performs full clipping on all sides of the screen. */
void 
bogl_pcfb_pointer (int visible, int x1, int y1,
		    const struct bogl_pointer *pointer,
		    int colors[2])
{
  int y_count;		/* Number of scanlines. */
  int y_ofs;		/* Number of scanlines to skip drawing. */
  int x_ofs;		/* Number of pixels to skip drawing on each line. */

  assert (pointer != NULL);

  x1 -= pointer->hx;
  y1 -= pointer->hy;
  
  if (y1 + 16 > bogl_yres)
    {
      y_count = bogl_yres - y1;
    }
  else
    y_count = 16;

  if (x1 < 0)
    {
      x_ofs = -x1;
      x1 = 0;
    }
  else
    x_ofs = 0;

  if (y1 < 0)
    {
      y_ofs = -y1;
      y1 = 0;
      y_count -= y_ofs;
    }
  else
    y_ofs = 0;

  bogl_drawing = 1;

  /* Save or restore the framebuffer contents. */
  {
    int sx_ofs = x1;
    int rowbytes = 16 * bpp / 8;

    if (sx_ofs + 16 > bogl_xres)
      {
	sx_ofs = bogl_xres - 16;
      }
    /* Avoid mouse droppings on <8-bit displays */
    else if (bpp < 8 && sx_ofs % (8 / bpp))
      rowbytes++;

    if (visible)
      {
	char *dst = save;
	char *src = (char *) bogl_frame
	  + (sx_ofs * bpp / 8)
	  + (y1 * bogl_line_len);
	int y;
	
	for (y = 0; y < y_count; y++)
	  {
	    memcpy (dst, src, rowbytes);
	    dst += rowbytes;
	    src += bogl_line_len;
	  }
      }
    else
      {
	char *dst = (char *) bogl_frame
	  + (sx_ofs * bpp / 8)
	  + (y1 * bogl_line_len);
	char *src = save;
	int y;
	
	for (y = 0; y < y_count; y++)
	  {
	    memcpy (dst, src, rowbytes);
	    dst += bogl_line_len;
	    src += rowbytes;
	  }
      }
  }

  /* Now draw it */
  if (visible)
    {
      const unsigned short *mask_p, *color_p;
      int y;
      int x_count = 16;
      
      if (x1 + 16 > bogl_xres)
	x_count = bogl_xres - x1;

      mask_p = pointer->mask + y_ofs;
      color_p = pointer->color + y_ofs;
      for (y = 0; y < y_count; y++, mask_p++, color_p++)
	{
	  unsigned char *dst;
	  unsigned short bg_bits, fg_bits;
	  int x;
	  
	  dst = (char *) bogl_frame
	    + ((y1 + y) * bogl_line_len);
	  bg_bits = *mask_p ^ *color_p;
	  fg_bits = *mask_p & *color_p;

	  for (x = 0; x < x_count; x++)
	    {
	      if (bg_bits & 0x8000)
		put_var (dst, x + x1, cmap_lookup(colors[0]), bpp);
	      else if (fg_bits & 0x8000)
		put_var (dst, x + x1, cmap_lookup(colors[1]), bpp);
	      else ; /* transparent (we hope) */
	      bg_bits <<= 1;
	      fg_bits <<= 1;
	    }
	}
    }

  bogl_drawing = 0;
}
void
bogl_pcfb_text (int xx, int yy, const char *s, int n, int fg, int bg, int ul,
		const struct bogl_font *font)
{
  int h, k;
  wchar_t wc;

  assert (xx >= 0 && xx < bogl_xres);
  assert (yy >= 0 && yy < bogl_yres);

  bogl_drawing = 1;

  h = bogl_font_height (font);
  if (yy + h > bogl_yres)
    h = bogl_yres - yy;

  mbtowc (0, 0, 0);
  for (; (k = mbtowc (&wc, s, n)) > 0; s += k, n -= k)
    {
      char *dst = (char *) bogl_frame + (yy * bogl_line_len);

      u_int32_t *character = NULL;
      int w = bogl_font_glyph (font, wc, &character);

      int x, y, h1 = ul ? h - 1 : h;

      if (character == NULL)
	continue;
 
      if (xx + w > bogl_xres)
	w = bogl_xres - xx;
      
      for (y = 0; y < h1; y++)
	{
	  u_int32_t c = *character++;
	  
	  for (x = 0; x < w; x++)
	    {
	      if (c & 0x80000000)
		put_var (dst, xx+x, cmap_lookup(fg), bpp);
	      else if (bg != -1)
		put_var (dst, xx+x, cmap_lookup(bg), bpp);

	      c <<= 1;
	    }

	  dst += bogl_line_len;
	}

      if (ul)
        for (x = 0; x < w; x++)
          put_var (dst, xx+x, cmap_lookup(fg), bpp);
        

      xx += w;
      if (xx >= bogl_xres)
	break;
    }

  bogl_drawing = 0;
}
Exemplo n.º 7
0
 virtual void     notify_distrib(STDdstream &ds,CGELptr&g) {
                          TAGformat d(&ds,class_name(),1); put_var(d,g);}
Exemplo n.º 8
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;
}