Beispiel #1
0
ISR(TWI_vect, ISR_BLOCK) {
    
    status_set(true);
    //uart_send("TWI ISR");
    //DUMP_ERROR();
    if (TW_STATUS == TW_SR_SLA_ACK) {
        
        //uart_send("Got my SLA+W");
        command = 0xFF;
        
    } else if (TW_STATUS == TW_ST_SLA_ACK) {
        
        if (command == 0x0) {
            //uart_send("Got into a ST with a PUT --- wwwwat");
        } else {
        
            //uart_send("Got a GET");
            if (get_callback) {
                TWDR = get_callback();
            } else {
                //uart_send("No callback, sending 0xFF");
                TWDR = 0xFF;
            }
            
            // For the last data byte we need to set ack to 0
            SEND(0, 0);
            return;
        }
        
    } else if (TW_STATUS == TW_SR_DATA_ACK) {
        
        if (command == 0xFF) {
            command = TWDR;
            
            //sprintf(str, "Got command = %x", command);
            //uart_send(str);
            
        } else if (command == 0x0) {
            
            //uart_send("Got a PUT");
            if (put_callback) {
                put_callback(TWDR);
            }
            
        } else {
            //uart_send("WAAAAAAT -- Got a DATA ACK on a GET");
        }
        
    } else if (TW_STATUS == TW_ST_DATA_ACK) {
        
        //uart_send("WTF - Got DATA ACK on ST");
        
    }
    
    SEND(1, 0);
}
Beispiel #2
0
/*-------------------------------------------------------------------------*/
svalue_t *
x_filter_string (svalue_t *sp, int num_arg)

/* EFUN: filter() for strings.
 *
 *   string filter(string arr, string fun, string|object obj, mixed extra, ...)
 *   string filter(string arr, closure cl, mixed extra, ...)
 *   string filter(string arr, mapping map)
 *
 * Filter the elements of <arr> through a filter defined by the other
 * arguments, and return an array of those elements, for which the
 * filter yields non-zero.
 *
 * The filter can be a function call:
 *
 *    <obj>-><fun>(elem, <extra>...)
 *
 * or a mapping query:
 *
 *    <map>[elem]
 *
 * <obj> can both be an object reference or a filename. If omitted,
 * this_object() is used (this also works if the third argument is
 * neither a string nor an object).
 */

{
    string_t *rc;     /* Result string */
    string_t *str;    /* Argument string  */
    svalue_t *arg;    /* First argument the vm stack */
    mp_int    slen;   /* Argument string length */
    char     *src, *dest; /* String text work pointers */

    char     *flags;  /* Flag array, one flag for each element of <str>
                       * (in reverse order). */
    mp_int    res;    /* Number of surviving elements */

    res = 0;

    /* Locate the args on the stack, extract the string to filter
     * and allocate the flags vector.
     */
    arg = sp - num_arg + 1;

    str = arg->u.str;
    slen = (mp_int)mstrsize(str);

    /* Every element in flags is associated by index number with an
     * element in the vector to filter. The filter function is evaluated
     * for every string character, and the associated flag is set to 0
     * or 1 according to the result.
     * At the end, all 1-flagged elements are gathered and copied
     * into the result string.
     */

    if (arg[1].type == T_MAPPING)
    {
        mp_int cnt;

        /* --- Filter by mapping query --- */
        mapping_t *m;

        if (num_arg > 2) {
            errorf("Too many arguments to filter(array)\n");
        }
        /* Allocate memory for the flag array. Simultaneously an error
         * handler is pushed onto the stack (after the arguments) for freeing
         * the buffer in case of runtime errors. */
        flags = xalloc_with_error_handler((size_t)slen + 1);
        if (!flags)
        {
          errorf("Out of memory (%zu bytes) for temporary buffer in filter().\n",
                 (size_t)slen + 1);
        }
        sp = inter_sp;

        m = arg[1].u.map;
        
        for (src = get_txt(str), cnt = slen; --cnt >= 0; src++)
        {
            svalue_t key;

            put_number(&key,  *src);
            if (get_map_value(m, &key) == &const0)
            {
                flags[cnt] = 0;
                continue;
            }
            flags[cnt] = 1;
            res++;
        }

    } else {

        /* --- Filter by function call --- */

        int         error_index;
        callback_t  cb;
        mp_int cnt;

        assign_eval_cost();

        /* setup_efun_callback() will adopt and therefore remove the 
         * arguments from arg+1 on to arg+num_arg from the stack and update 
         * inter_sp. New top-of-stack will be arg. */
        error_index = setup_efun_callback(&cb, arg+1, num_arg-1);
        if (error_index >= 0)
        {
            vefun_bad_arg(error_index+2, arg);
            /* NOTREACHED */
            return arg;
        }
        /* push the callback structure onto the stack. */
        sp = arg + 1;
        put_callback(sp, &cb);

        /* Allocate memory for the flag array. Simultaneously an error
         * handler is pushed onto the stack (after the arguments) for freeing
         * the buffer in case of runtime errors. */
        inter_sp = sp;
        flags = xalloc_with_error_handler((size_t)slen + 1);
        if (!flags)
        {
            errorf("Out of memory (%"PRIdMPINT" bytes) for temporary buffer "
                "in filter().\n", slen + 1);
        }
        sp = inter_sp;
        
        /* Loop over all elements in p and call the filter.
         * w is the current element filtered.
         */
        for (src = get_txt(str), cnt = slen; --cnt >= 0; src++)
        {
            svalue_t *v;

            flags[cnt] = 0;

            if (current_object->flags & O_DESTRUCTED)
                continue;
                /* Don't call the filter anymore, but fill the
                 * flags array with 0es.
                 */

            if (!callback_object(&cb))
            {
                inter_sp = sp;
                errorf("object used by filter(array) destructed");
            }

            push_number(inter_sp, *src);

            v = apply_callback(&cb, 1);
            if (!v || (v->type == T_NUMBER && !v->u.number) )
                continue;

            flags[cnt] = 1;
            res++;
        }
    }

    /* flags[] holds the filter results, res is the number of
     * elements to keep. Now create the result vector.
     */
    rc = alloc_mstring(res);
    if (!rc)
    {
        errorf("Out of memory (%"PRIdMPINT" bytes) for result in filter().\n",
            slen+1);
    }
  
    for (src = get_txt(str), dest = get_txt(rc), flags = &flags[slen]
       ; res > 0 ; src++)
    {
        if (*--flags)
        {
            *dest++ = *src;
            res--;
        }
    }
  
    /* Cleanup. Arguments for the closure have already been removed. On the
     * stack are now the string, the mapping or callback structure and the
     * error handler. (Not using pop_n_elems() for 2 elements for saving loop 
     * and function call overhead.) */
    free_svalue(sp--);  /* errorhandler, buffer and flags are freed by this. */
    free_svalue(sp--);  /* mapping or callback structure. */
    free_mstring(str);  /* string, at arg == sp */
    sp->u.str = rc;     /* put result here */

    return sp;
} /* x_filter_string() */
Beispiel #3
0
/*-------------------------------------------------------------------------*/
svalue_t *
x_map_struct (svalue_t *sp, int num_arg)

/* EFUN map() on structs
 *
 *   mixed * map(struct arg, string func, string|object ob, mixed extra...)
 *   mixed * map(struct arg, closure cl, mixed extra...)
 *   mixed * map(struct arr, mapping map [, int col])
 *
 * Map the elements of <arr> through a filter defined by the other
 * arguments, and return an array of the elements returned by the filter.
 *
 * The filter can be a function call:
 *
 *    <obj>-><fun>(elem, <extra>...)
 *
 * or a mapping query:
 *
 *    <map>[elem[,idx]]
 *
 * In the mapping case, if <map>[elem[,idx]] does not exist, the original
 * value is returned in the result.
 * [Note: argument type and range checking for idx is done in v_map()]
 *
 * <obj> can both be an object reference or a filename. If <ob> is
 * omitted, or neither an object nor a string, then this_object() is used.
 *
 * As a bonus, all references to destructed objects in <arr> are replaced
 * by proper 0es.
 */

{
    struct_t   *st;
    struct_t   *res;
    svalue_t   *arg;
    svalue_t   *v, *w, *x;
    mp_int      cnt;

    inter_sp = sp;
    arg = sp - num_arg + 1;

    st = arg->u.strct;
    cnt = (mp_int)struct_size(st);

    if (arg[1].type == T_MAPPING)
    {
        /* --- Map through mapping --- */

        mapping_t *m;
        p_int column = 0; /* mapping column to use */

        m = arg[1].u.map;

        if (num_arg > 2)
            column = arg[2].u.number;

        res = struct_new(st->type);
        if (!res)
            errorf("(map_struct) Out of memory: struct[%"PRIdMPINT"] for result\n", cnt);
        push_struct(inter_sp, res); /* In case of errors */

        for (w = st->member, x = res->member; --cnt >= 0; w++, x++)
        {
            if (destructed_object_ref(w))
                assign_svalue(w, &const0);

            v = get_map_value(m, w);
            if (v == &const0)
                assign_svalue_no_free(x, w);
            else
                assign_svalue_no_free(x, v + column);
        }

        if (num_arg > 2)
            free_svalue(arg+2);
        free_svalue(arg+1); /* the mapping */
        sp = arg;
    }
    else
    {
        /* --- Map through function call --- */

        callback_t  cb;
        int         error_index;

        error_index = setup_efun_callback(&cb, arg+1, num_arg-1);
        if (error_index >= 0)
        {
            vefun_bad_arg(error_index+2, arg);
            /* NOTREACHED */
            return arg;
        }
        inter_sp = sp = arg+1;
        put_callback(sp, &cb);
        num_arg = 2;

        res = struct_new(st->type);
        if (!res)
            errorf("(map_struct) Out of memory: struct[%"PRIdMPINT"] for result\n", cnt);
        push_struct(inter_sp, res); /* In case of errors */

        /* Loop through arr and res, mapping the values from arr */
        for (w = st->member, x = res->member; --cnt >= 0; w++, x++)
        {
            if (current_object->flags & O_DESTRUCTED)
                continue;

            if (destructed_object_ref(w))
                assign_svalue(w, &const0);

            if (!callback_object(&cb))
                errorf("object used by map_array destructed");

            push_svalue(w);

            v = apply_callback(&cb, 1);
            if (v)
            {
                transfer_svalue_no_free(x, v);
                v->type = T_INVALID;
            }
        }

        free_callback(&cb);
    }
    
    /* The arguments have been removed already, now just replace
     * the struct on the stack with the result.
     */
    free_struct(st);
    arg->u.strct = res; /* Keep svalue type T_STRUCT */

    return arg;
} /* x_map_struct () */