A little light code review requested

Discussion in 'C Programming' started by luserXtrog, Aug 18, 2010.

  1. luserXtrog

    luserXtrog Guest

    Me again. Back in black. This is a little experiment in
    using stdarg to simulate functions that both receive and
    return variable numbers of variables (determined by the
    opcode). It seems to be working but strikes me as sufficiently
    bizarre that I'd greatly appreciate even one other set of
    eyes to glance over it.
    It is halfway sensible and confusing due to the nature of the
    problem? Or is it totally wacko-jacko?

    575(1)09:40 PM:xpost 0> echo '//@@@@snip here@@@@'|cat oper.c -
    object.h
    #include <stdarg.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include "object.h"

    Object *Iadd(Object oa[]) {
    oa[0].u.i += oa[1].u.i;
    return oa;
    }

    Object *moveto(Object oa[]) {
    printf("%d %d moveto\n", oa[0].u.i, oa[1].u.i);
    return oa;
    }

    Object *stroke(Object oa[]) {
    printf("stroke\n");
    return oa;
    }

    #define OPERATORS \
    X(Iadd, 2,1) \
    X(moveto,2,0) \
    X(stroke,0,0) \

    #define X(op,in,out) OP_ ## op,
    enum e_opnames { OPERATORS };
    #undef X

    struct s_operator {
    Object * (*fp)(Object []);
    int in, out;
    } oplist[] =
    #define X(op,in,out) { op, in, out },
    { OPERATORS };
    #undef X
    typedef struct s_operator Oper;

    void opcall (int opcode, ...) {
    Oper oper;
    int n;

    oper = oplist[opcode];
    n = oper.out>oper.in? oper.out: oper.in;
    {
    va_list ap;
    Object oa[n];
    Object *op;
    int i;

    va_start(ap, opcode);
    for (i=0; i<oper.in; i++)
    oa = * va_arg(ap, Object *);
    va_end(ap);

    oper.fp(oa);

    va_start(ap,opcode);
    for (i=0; i<oper.out; i++) {
    op = va_arg(ap, Object *);
    *op = oa;
    }
    va_end(ap);
    }
    return ;
    }

    int main() {
    Object x = { .type = integertype, .u.i = 72 };
    Object y = { .type = integertype, .u.i = 72 };
    opcall(OP_Iadd, &x, &y);
    opcall(OP_moveto, &x, &y);
    opcall(OP_stroke);
    return 0;
    }

    //eof
    //@@@@snip here@@@@

    #define LIT 1<<7

    //composite attributes
    #define READ 1
    #define WRITE 2
    #define EXEC 4

    #define Types \
    X( mark, int m) \
    X( null, int u) \
    X( integer, int i) \
    X( real, double r) \
    X( boolean, unsigned char b) \
    X( array, size_t a) \
    X(packedarray, size_t pa) \
    X( string, size_t s) \
    X( name, size_t n) \
    X( dict, size_t d) \
    X( operator, int o) \
    X( file, int * f) \
    X( save, Save * v) \
    X( font, int * t)

    #define X(a,b) a ## type,
    enum e_types{ Types };
    #undef X

    typedef struct s_array Array;
    struct s_array {
    unsigned char attr;
    size_t a;
    size_t n;
    };

    typedef struct s_string String;
    struct s_string {
    unsigned char attr;
    size_t s;
    size_t n;
    };

    typedef struct s_dict Dict;
    struct s_dict {
    unsigned char attr;
    size_t d;
    size_t n;
    };

    typedef struct s_save Save;
    struct s_save {
    unsigned char *vm;
    unsigned int level;
    size_t sz;
    size_t pointer;
    };

    #define X(a,b) b;
    typedef struct s_object Object;
    struct s_object {
    unsigned char type;
    union { Types } u;
    };
    #undef X

    Object integer (int i);
    Object real (double r);
    Object boolean (unsigned char b);
    Object name (Object s);
    extern Object mark;
    extern Object null;
    576(1)09:54 PM:xpost 0> !gc
    gcc -g -o oper oper.c
    577(1)09:55 PM:xpost 0> gcc -Wall -o oper oper.c
    578(1)09:55 PM:xpost 0> oper
    144 72 moveto
    stroke
    579(1)09:55 PM:xpost 0>

    tia
    Semolina Sensemilla
     
    luserXtrog, Aug 18, 2010
    #1
    1. Advertising

  2. luserXtrog

    Eric Sosman Guest

    On 8/17/2010 10:57 PM, luserXtrog wrote:
    > Me again. Back in black. This is a little experiment in
    > using stdarg to simulate functions that both receive and
    > return variable numbers of variables (determined by the
    > opcode). [...]


    The crux seems to be (and I've only skimmed the rest):

    > void opcall (int opcode, ...) {
    > Oper oper;
    > int n;
    >
    > oper = oplist[opcode];
    > n = oper.out>oper.in? oper.out: oper.in;
    > {
    > va_list ap;
    > Object oa[n];
    > Object *op;
    > int i;
    >
    > va_start(ap, opcode);
    > for (i=0; i<oper.in; i++)
    > oa = * va_arg(ap, Object *);
    > va_end(ap);
    >
    > oper.fp(oa);
    >
    > va_start(ap,opcode);
    > for (i=0; i<oper.out; i++) {
    > op = va_arg(ap, Object *);
    > *op = oa;
    > }
    > va_end(ap);
    > }
    > return ;
    > }


    As far as I can see this will work, provided a copy of an Object
    is as good as the original (see `FILE' for a counter-example). An
    Object struct with a flexible array member would be troublesome, and
    a call like `opcall(OP_Iadd, &obj, &obj)' would yield results that
    might not be what you desire.

    However, it strikes me as not terribly useful. Consider: To make
    use of this wrapper, the caller already needs to know how many operands
    the `oper' requires and how many results it returns (and in what order).
    That is, the caller knows so much about `oper' that it's hard to see
    why it would bother going through all this hocus-pocus rather than just
    calling the target function directly. Human-written code, anyhow, would
    seem to have little use for this. Machine-generated code, perhaps, but
    if you're "compiling" a language or framework into C source, wouldn't
    it make more sense to adopt a less convoluted infrastructure?

    --
    Eric Sosman
    lid
     
    Eric Sosman, Aug 18, 2010
    #2
    1. Advertising

  3. luserXtrog

    luserXtrog Guest

    On Aug 17, 10:28 pm, Eric Sosman <> wrote:
    > On 8/17/2010 10:57 PM, luserXtrog wrote:
    >
    > > Me again. Back in black. This is a little experiment in
    > > using stdarg to simulate functions that both receive and
    > > return variable numbers of variables (determined by the
    > > opcode). [...]

    >
    >      The crux seems to be (and I've only skimmed the rest):
    >
    >
    >
    > > void opcall (int opcode, ...) {
    > >      Oper oper;
    > >      int n;

    >
    > >      oper = oplist[opcode];
    > >      n = oper.out>oper.in? oper.out: oper.in;
    > >      {
    > >          va_list ap;
    > >          Object oa[n];
    > >          Object *op;
    > >          int i;

    >
    > >          va_start(ap, opcode);
    > >          for (i=0; i<oper.in; i++)
    > >              oa = * va_arg(ap, Object *);
    > >          va_end(ap);

    >
    > >          oper.fp(oa);

    >
    > >          va_start(ap,opcode);
    > >          for (i=0; i<oper.out; i++) {
    > >              op = va_arg(ap, Object *);
    > >              *op = oa;
    > >          }
    > >          va_end(ap);
    > >      }
    > >      return ;
    > > }

    >
    >      As far as I can see this will work, provided a copy of an Object
    > is as good as the original (see `FILE' for a counter-example).  An
    > Object struct with a flexible array member would be troublesome, and
    > a call like `opcall(OP_Iadd, &obj, &obj)' would yield results that
    > might not be what you desire.
    >
    >      However, it strikes me as not terribly useful.  Consider: To make
    > use of this wrapper, the caller already needs to know how many operands
    > the `oper' requires and how many results it returns (and in what order).
    > That is, the caller knows so much about `oper' that it's hard to see
    > why it would bother going through all this hocus-pocus rather than just
    > calling the target function directly.  Human-written code, anyhow, would
    > seem to have little use for this.  Machine-generated code, perhaps, but
    > if you're "compiling" a language or framework into C source, wouldn't
    > it make more sense to adopt a less convoluted infrastructure?
    >


    Yes. It's mostly just a testing function but I may have need of it
    later. This is a postscript interpreter, by the way.

    My idea here is that the payload of an operator object is just an
    integer index into the function array (this allows functions to
    operate on functions). I plan on a slightly different handler for
    normal execution which will pass a pointer from the global operand
    stack and then readjust the stack pointer to account for the
    difference. But this opcall function will (I hope) allow more
    flexibility for operator functions to make use of each other
    independently of the operand stack.

    I was a little concerned about using stdarg and VLAs in the same
    function; but it certainly seems to work. It actually compiled
    clean the very first time. So I dared to run it and received the
    to-be-expected segmentation violation. It was hilarious.

    looza lychee
     
    luserXtrog, Aug 18, 2010
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ian Pilcher

    Code review requested

    Ian Pilcher, Dec 15, 2003, in forum: Java
    Replies:
    0
    Views:
    350
    Ian Pilcher
    Dec 15, 2003
  2. Ed

    Code review requested

    Ed, Jul 19, 2004, in forum: Java
    Replies:
    1
    Views:
    381
    Filip Larsen
    Jul 19, 2004
  3. Mike Wahler
    Replies:
    1
    Views:
    411
    E. Robert Tisdale
    Oct 18, 2004
  4. Vyacheslav Kononenko

    Re: Code review requested, Accelerated C++

    Vyacheslav Kononenko, Oct 18, 2004, in forum: C++
    Replies:
    0
    Views:
    507
    Vyacheslav Kononenko
    Oct 18, 2004
  5. www
    Replies:
    51
    Views:
    1,517
Loading...

Share This Page