Exemple #1
0
/*---------------------------------------------------------------------------
 * Purpose:     Register a documentation string with the switch.
 *
 * Programmer:  Robb Matzke
 *              Wednesday, May 31, 2000
 *
 * Modifications:
 *---------------------------------------------------------------------------
 */
void
switch_doc(switch_t *sw, const char *doc_string)
{
    char        *fulldoc = (char *)malloc(8192);

    /* Set switch info */
    if (!sw) sw = switch_latest;
    if (sw->doc_string) free(sw->doc_string);
    sw->doc_string = safe_strdup(doc_string);

    /* Build browser documentation string */
    switch_synopsis(sw, fulldoc);
    strcat(fulldoc, "\n");
    strcat(fulldoc, doc_string);

    /* Assign browser documentation string to symbols */
    if (sw->short_name) {
        obj_t symbol = obj_new(C_SYM, sw->short_name);
        obj_t docstr = obj_new(C_STR, fulldoc);
        sym_dbind(symbol, docstr);
        obj_dest(symbol);
    }
    if (sw->long_name) {
        obj_t symbol = obj_new(C_SYM, sw->long_name);
        obj_t docstr = obj_new(C_STR, fulldoc);
        sym_dbind(symbol, docstr);
        obj_dest(symbol);
    }
    free(fulldoc);
}
Exemple #2
0
/*-------------------------------------------------------------------------
 * Function:    parse_assignment
 *
 * Purpose:     Parses an assignment statement of the form
 *
 *                      LVALUE = RVALUE
 *
 * Return:      Success:        the resulting parse tree.
 *
 *              Failure:        &ErrorCell
 *
 * Programmer:  Robb Matzke
 *              [email protected]
 *              Feb  7 1997
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
static obj_t
parse_assignment (lex_t *f, int skipnl) {

   obj_t        rt=NIL, retval=NIL;

   retval = parse_selection (f, skipnl);
   if (&ErrorCell==retval) return &ErrorCell;

   if (TOK_EQ==lex_token (f, NULL, skipnl)) {
      lex_consume (f);
      rt = parse_selection (f, skipnl);
      if (&ErrorCell==rt) {
         obj_dest(retval);
         return &ErrorCell;
      }
      retval = obj_new (C_CONS,
                        obj_new (C_SYM, "Assign"),
                        obj_new (C_CONS,
                                 retval,
                                 obj_new (C_CONS,
                                          rt,
                                          NIL)));
   }
   return retval;
}
Exemple #3
0
static void			board_fill(t_env *e)
{
	int		max_bot;
	int		nb_food;
	int		nb_rock;
	int		i;
	int		tmp;

	max_bot = e->opt.limit * e->opt.team_name->len;
	nb_food = max_bot * 10;
	i = 0;
	while (i < nb_food)
	{
		ft_lst_pushend(e->board[sq_rand(e)].obj, obj_new(OBJ_FOOD));
		i++;
	}
	i = 6;
	while (i > 0)
	{
		nb_rock = (i == 6 ? 5 : nb_rock * 2);
		tmp = nb_rock;
		while (tmp--)
			ft_lst_pushend(e->board[sq_rand(e)].obj, obj_new(i));
		i--;
	}
}
Exemple #4
0
/*-------------------------------------------------------------------------
 * Function:    parse_dot
 *
 * Purpose:     Tries to parse an expression followed by the dot operator
 *              followed by another expression.  If the dot is not present
 *              then just the left operand is returned.
 *
 * Return:      Success:        The expression.
 *
 *              Failure:        &ErrorCell
 *
 * Programmer:  Robb Matzke
 *              [email protected]
 *              Dec  5 1996
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
static obj_t
parse_dot (lex_t *f, int skipnl) {

   obj_t        rt=NIL, retval=NIL;

   retval = parse_range (f, skipnl);
   if (&ErrorCell==retval) return &ErrorCell;

   while (TOK_DOT==lex_token(f, NULL, skipnl)) {
      lex_consume (f);
      rt = parse_range (f, skipnl);
      if (&ErrorCell==rt) {
         obj_dest (retval);
         return &ErrorCell;
      }
      retval = obj_new (C_CONS,
                        obj_new (C_SYM, "Dot"),
                        obj_new (C_CONS,
                                 retval,
                                 obj_new (C_CONS,
                                          rt,
                                          NIL)));
   }
   return retval;
}
Exemple #5
0
/*-------------------------------------------------------------------------
 * Function:    bif
 *
 * Purpose:     Installs a builtin function in the symbol table.
 *
 * Return:      void
 *
 * Programmer:  Robb Matzke
 *              [email protected]
 *              Dec  4 1996
 *
 * Modifications:
 *              Robb Matzke, 2000-06-06
 *              Added the DESC and DOC arguments. DESC is an optional
 *              one-line description to be added to the function table of
 *              contents. DOC is a multi-line documentation string.
 *-------------------------------------------------------------------------
 */
static void
bif (const char *func_name, obj_t(*func_ptr)(int x, obj_t y[]), int flags,
     const char *desc, const char *doc) {

    obj_t       name = func_name?obj_new(C_SYM, func_name):NIL;
    obj_t       func = func_ptr?obj_new(C_BIF, func_ptr, flags):NIL;

    /* Bind the function to the symbol */
    if (name) sym_fbind(name, func);
   
    /* Function table of contents */
    if (name && desc) {
        HelpFuncToc[NHelpFuncToc].name = safe_strdup(func_name);
        HelpFuncToc[NHelpFuncToc].desc = safe_strdup(desc);
        NHelpFuncToc++;
    }

    /* Operator table of contents. Operators are added to the operator
     * table of contents if the description contains the string `operator'
    * and the operators are listed in quotes like `this'. */
    if (desc && strstr(desc, "operator")) {
        const char *s=desc, *first, *last;

        while ((first=strchr(s, '`')) && (last=strchr(++first, '\''))) {
            char opname[64];
            strcpy(opname, "op");
            strncpy(opname+2, first, last-first);
            opname[2+last-first] = '\0';
            if (opname[2]) {
                if (doc) {
                    obj_t sym = obj_new(C_SYM, opname);
                    obj_t docval = obj_new(C_STR, doc);
                    sym_dbind(sym, docval);
                    obj_dest(sym);
                }
                strcpy(opname, "\"op");
                strncpy(opname+3, first, last-first);
                strcpy(opname+(3+last-first), "\"");
                HelpOpToc[NHelpOpToc].name = safe_strdup(opname);
                HelpOpToc[NHelpOpToc].desc = safe_strdup(desc);
                NHelpOpToc++;
            }
            s = last+1;
        }
    }

    /* Bind the documentation string to the symbol */
    if (name && doc) {
        obj_t docval = obj_new(C_STR, doc);
        sym_dbind(name, docval);
    }
   
    if (name) obj_dest (name);
    /*dont destroy func or doc*/
}
Exemple #6
0
/*-------------------------------------------------------------------------
 * Function:    sym_eval
 *
 * Purpose:     Returns the variable value of a symbol if it has one.
 *
 * Return:      Success:        Ptr to a copy of the variable value.
 *
 *              Failure:        NIL
 *
 * Programmer:  Robb Matzke
 *              [email protected]
 *              Dec  4 1996
 *
 * Modifications:
 *      Robb Matzke, 4 Feb 1997
 *      Fixed the arguments for the obj_deref() call.
 *
 *      Robb Matzke, 2000-07-03
 *      The symbol `$*' evaluates to a list of all $N files for
 *      consecutive N beginning at 1.
 *-------------------------------------------------------------------------
 */
static obj_t
sym_eval (obj_t _self)
{
    obj_t       name_1=NIL, file_1=NIL, retval=NIL;
    obj_sym_t   *self = MYCLASS(_self);

    /* If the symbol has a variable value then return it. */    
    if (MYCLASS(_self)->sym->var) {
        return obj_copy (MYCLASS(_self)->sym->var, SHALLOW);
    }

    /* The symbol `$*' evaluates to a list of the first consecutive files
     * bound to the $N symbols. */
    if (!strcmp(self->sym->name, "$*")) {
        obj_t   opands[1024], retval;
        int     nopands, i;
        
        for (nopands=0; nopands<NELMTS(opands); nopands++) {
            obj_t symbol;
            char tmp[32];
            sprintf(tmp, "$%d", nopands+1);
            symbol = obj_new(C_SYM, tmp);
            opands[nopands] = sym_vboundp(symbol);
            obj_dest(symbol);
            if (!opands[nopands] || C_FILE!=opands[nopands]->pub.cls) {
                /* We reached the last file or something isn't a file */
                obj_dest(opands[nopands]);
                break;
            }
        }
        retval = V_make_list(nopands, opands);
        for (i=0; i<nopands; i++) {
            obj_dest(opands[i]);
        }
        return retval;
    }

    /* If the symbol exists in the first data file, then return
     * that SDO. */
    name_1 = obj_new (C_SYM, "$1");
    file_1 = MYCLASS(name_1)->sym->var;
    name_1 = obj_dest (name_1);

    if (file_1 && C_FILE==file_1->pub.cls) {
        retval = obj_deref (file_1, 1, &_self);
        return retval;
    }

    /* Symbol has no value. */    
    out_errorn ("eval: variable `%s' has no value", obj_name(_self));
    return NIL;
}
Exemple #7
0
/*---------------------------------------------------------------------------
 * Purpose:     Convenience function for setting the documentation string
 *              of some symbol.
 *
 * Programmer:  Robb Matzke
 *              Tuesday, June  6, 2000
 *
 * Modifications:
 *---------------------------------------------------------------------------
 */
void
sym_doc(const char *symname, const char *docstr)
{
    obj_t       sym = obj_new(C_SYM, symname);

    if (docstr) {
        obj_t doc = obj_new(C_STR, docstr);
        sym_dbind(sym, doc);
    } else {
        sym_dbind(sym, NIL);
    }
    obj_dest(sym);
}
Exemple #8
0
/*-------------------------------------------------------------------------
 * Function:    ptr_bind
 *
 * Purpose:     Binds array dimensions to numeric values.
 *
 * Return:      Success:        SELF
 *
 *              Failure:        NIL
 *
 * Programmer:  Robb Matzke
 *              [email protected]
 *              Jan 13 1997
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
static obj_t
ptr_bind (obj_t _self, void *mem) {

   obj_ptr_t    *self = MYCLASS(_self);
   obj_t        name=NIL, val=NIL, x=NIL;
   int          i;

   if (C_STR==self->sub->pub.cls) {
      name = obj_new (C_SYM, obj_name(self->sub));
      x = sym_vboundp (name);
      name = obj_dest (name);
      val = obj_copy (x, DEEP); /*so we can modify it*/
      x = obj_dest (x);

      /*
       * We're being tricky here.  By assigning a new value to the `sub'
       * field we're modifying all the expressions that share this cell.
       * We must insure that the correct reference count is imparted
       * to the new subtype.
       */
      for (i=1; i<self->pub.ref; i++) {
         x = obj_copy (val, SHALLOW);
         assert (x==val);
      }
      
      if (val) self->sub = val;
   }

   return obj_bind (self->sub, mem ? *((void**)mem) : NULL);
}
Exemple #9
0
struct odes *
obj_clone(struct mempool *pool, struct odes *src)
{
  struct odes *dest = obj_new(pool);
  obj_clone_attr_list(dest, src);
  return dest;
}
Exemple #10
0
struct odes *
obj_add_son(struct odes *o, uns x)
{
  struct odes *son = obj_new(o->pool);
  obj_add_son_ref(o, x, son);
  return son;
}
static void testErrorMessage(CuTest* tc, const char *expected, const char *tlv_file,
		int (*obj_new)(KSI_CTX *ctx, void **),
		void (*obj_free)(void*),
		const KSI_TlvTemplate *tmplete) {
	int res;
	void *obj = NULL;
	char buf[1024];
	size_t len;
	FILE *f = NULL;
	KSI_FTLV ftlv;

	KSI_ERR_clearErrors(ctx);

	f = fopen(getFullResourcePath(tlv_file), "rb");
	CuAssert(tc, "Failed to open file.", f != NULL);

	res = KSI_FTLV_fileRead(f, (unsigned char *)buf, sizeof(buf), &len, &ftlv);
	CuAssert(tc, "Failed read from file.", res == KSI_OK);

	res = obj_new(ctx, &obj);
	CuAssert(tc, "Unable create new obj.", res == KSI_OK);

	res = KSI_TlvTemplate_parse(ctx, (unsigned char *)buf, (unsigned)len, tmplete, obj);
	CuAssert(tc, "Parsing invalid obj must fail.", res != KSI_OK);

	res = KSI_ERR_getBaseErrorMessage(ctx, buf, sizeof(buf), NULL, NULL);
	CuAssert(tc, "Unable to get base error message.", res == KSI_OK);

	CuAssert(tc, "Wrong error message.", strcmp(buf, expected) == 0);

	if (f != NULL) fclose(f);
	obj_free(obj);
}
Exemple #12
0
media_sinker *
media_sinker_alloc(uint32_t size, media_sinker_ops *ops, void *u)
{
	int32_t err;
	media_sinker *sinker;

	if (size < sizeof(*sinker))
		return NULL;

	sinker = (media_sinker*)obj_new(size, on_obj_fin);
	if (sinker)
	{
		init_self(sinker);
		sinker->ops = ops;

		if (ops && ops->init)
		{
			err = (*ops->init)(sinker, u);
			if (err)
			{
				sinker->ops = NULL;
				obj_unref(sinker);
				return NULL;
			}
		}
	}

	return sinker;
}
Exemple #13
0
static Value ripe_fftw_plan2d_new(Value x, Value y, Value v_sign)
{
  Value v_self = obj_new(klass_FftwPlan2D);
  FftwPlan2D* self = obj_c_data(v_self);

  self->x = val_to_int64(x);
  self->y = val_to_int64(y);
  if (self->x < 1 or self->y < 1){
    exc_raise("invalid dimensions of Fftw.Plan2D (%" PRId64"x%" PRId64")",
              self->x, self->y);
  }
  self->in = (fftw_complex*) fftw_malloc(
                               sizeof(fftw_complex) * self->x * self->y
                             );
  self->out = (fftw_complex*) fftw_malloc(
                                sizeof(fftw_complex) * self->x * self->y
                              );
  
  int64 sign = val_to_int64(v_sign);
  if (sign != FFTW_FORWARD and sign != FFTW_BACKWARD){
    exc_raise("invalid flag for FFT (passed %" PRId64")", sign);
  }

  self->plan = fftw_plan_dft_2d(self->x, self->y, self->in, self->out,
                                sign, FFTW_ESTIMATE);
  return v_self;
}
Exemple #14
0
Obj *obj_load(char *filename)
{
    FILE *file;
    Obj *objFile;

    objFile = obj_get_by_filename(filename);
    if (objFile)
    {
        objFile->used++;
        return objFile;
    }

    objFile = obj_new();
    if (!objFile)
    {
        return NULL;
    }

    file = fopen(filename,"r");
    if (file == NULL)
    {
        slog("failed to open file %s",filename);
        return NULL;
    }


    obj_file_get_counts(objFile,file);

    obj_allocate(objFile);
    obj_file_parse(objFile, file);

    fclose(file);

    return objFile;
}
Exemple #15
0
proto_parser *
alloc_proto_parser(uint32_t size, proto_parser_ops *ops, void *u)
{
	proto_parser *parser;
	int32_t err;

	if (size < sizeof(*parser))
		return NULL;

	parser = (proto_parser*)obj_new(size, on_obj_fin);
	parser->ops = NULL;

	if (ops && ops->init)
	{
		err = (*ops->init)(parser, u);
		if (err)
		{
			obj_unref(parser);
			return NULL;
		}
	}

	parser->ops = ops;
	return parser;
}
Exemple #16
0
bool
VectorPath::_SetPointCount(int32 count)
{
	// handle reallocation if we run out of room
	if (count >= fAllocCount) {
		fAllocCount = ((count) / ALLOC_CHUNKS + 1) * ALLOC_CHUNKS;
		if (fPath)
			fPath = obj_renew(fPath, control_point, fAllocCount);
		else
			fPath = obj_new(control_point, fAllocCount);

		if (fPath != NULL) {
			memset(fPath + fPointCount, 0,
				(fAllocCount - fPointCount) * sizeof(control_point));
		}
	}

	// update point count
	if (fPath) {
		fPointCount = count;
	} else {
		// reallocation might have failed
		fPointCount = 0;
		fAllocCount = 0;
		fprintf(stderr, "VectorPath::_SetPointCount(%ld) - allocation failed!\n",
			count);
	}

	fCachedBounds.Set(0.0, 0.0, -1.0, -1.0);

	return fPath != NULL;
}
Exemple #17
0
err_status_t
csbh_context_new(csbh_context_t **ctx)
{
    if (!ctx)
        return CLN_FW_ERR_INVALID_PARAMETER;

    return obj_new("csbh_context_t", ctx);
}
Exemple #18
0
static void object_space_init(void)
{
    global_object_space = malloc(sizeof(*global_object_space));

    // Message names required by the runtime
    acute_forward_msg = msg_new("forward", list_new(), NULL);
    acute_activate_msg = msg_new("activate", list_new(), NULL);

    // Chicken-egg problem commences below.
    obj_t* lobby = obj_new();
	global_object_space->lobby = lobby;
    obj_t* object = obj_new();
    obj_register_slot(lobby, "parent", object);
    obj_register_slot(object, "parent", lobby);
	obj_register_slot(lobby, "test", str_new("Test string", 12));
    object_space_register_proto(global_object_space, "Object", object);
}
Exemple #19
0
Data *Data_new(const char *name, int age, bool mf)
{
    Data *obj = obj_new(Data,Data_dispose);
    obj->name = str_ref((char*)name);
    obj->age = age;
    obj->mf = mf;
    return obj;
}
Exemple #20
0
File *File_new(str_t name) {
    File *res = obj_new(File,File_dispose);
    if (! s_file_type) {
        s_file_type = obj_type_index(res);
    }
    res->name = str_ref(name);
    return res;
}
Exemple #21
0
static Iterator *list_iterable(const void *o) {
    ListIterator* liter = obj_new(ListIterator,NULL);
    liter->li = list_start((List*)o);
    liter->next = iter_list_next;
    liter->nextpair = NULL;
    liter->len = list_size((List*)o);
    return (Iterator*)liter;
}
Exemple #22
0
Value complex_to_val(double real, double imag)
{
    Complex* complex;
    Value v_self = obj_new(klass_Complex, (void**) &complex);
    complex->real = real;
    complex->imag = imag;
    return v_self;
}
Exemple #23
0
static Iterator* iterator_map_init(const void *o) {
    MapIterator *iter = obj_new(MapIterator,MapIterator_dispose);
    iter->mi = map_iter_new((Map*)o,NULL,NULL);
    iter->next = iterator_map_next;
    iter->nextpair = iterator_map_nextpair;
    iter->len = map_size((Map*)o);
    iter->finis = false;
    return (Iterator*)iter;
}
Exemple #24
0
/*-------------------------------------------------------------------------
 * Function:    parse_range
 *
 * Purpose:     Tries to parse a range expression of the form `I1:I2'
 *              where I1 and I2 are integer constants.
 *
 * Return:      Success:        A range object.
 *
 *              Failure:        &ErrorCell
 *
 * Programmer:  Robb Matzke
 *              [email protected]
 *              Jan  3 1997
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
static obj_t
parse_range (lex_t *f, int skipnl) {

   obj_t        lt=NIL, rt=NIL, retval=NIL;
   int          lo, hi;

   lt = parse_term (f, skipnl);
   if (&ErrorCell==lt) return &ErrorCell;

   if (TOK_COLON==lex_token (f, NULL, skipnl)) {
      lex_consume (f);
      rt = parse_term (f, skipnl);
      if (&ErrorCell==rt) {
         obj_dest (rt);
         return &ErrorCell;
      }

      /*
       * Both arguments must be integer constants.
       */
      if (!num_isint(lt)) {
         out_error ("Range: left limit is not an integer constant: ", lt);
         obj_dest (lt);
         obj_dest (rt);
         return &ErrorCell;
      }
      if (!num_isint(rt)) {
         out_error ("Range: right limit is not an integer constant: ", rt);
         obj_dest (lt);
         obj_dest (rt);
         return &ErrorCell;
      }

      /*
       * The constants must be in a reasonable order.
       */
      lo = num_int (lt);
      hi = num_int (rt);
      if (hi<lo) {
         out_errorn ("Range: inverted range %d:%d changed to %d:%d",
                     lo, hi, hi, lo);
         lo = num_int (rt);
         hi = num_int (lt);
      }

      /*
       * Create the range object.
       */
      lt = obj_dest (lt);
      rt = obj_dest (rt);
      retval = obj_new (C_RANGE, lo, hi);
   } else {
      retval = lt;
   }
   return retval;
}
Exemple #25
0
/*-------------------------------------------------------------------------
 * Function:    sym_self_set
 *
 * Purpose:     Gives symbol `self' a new variable value and returns the
 *              previous value.  The new value is not copied.
 *
 * Return:      Success:        Previous value of variable `self'.
 *
 *              Failure:        NIL
 *
 * Programmer:  Robb Matzke
 *              [email protected]
 *              Jan 13 1997
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
obj_t
sym_self_set (obj_t newval) {

   obj_t        oldval=NIL, selfvar=NIL;

   selfvar = obj_new (C_SYM, "self");
   oldval = sym_vboundp (selfvar);
   sym_vbind (selfvar, newval);
   return oldval;
}
Exemple #26
0
obj_t * obj_new_simple()
{
	return obj_new(
		obj_init,
		obj_get,
		obj_set,
		obj_save,
		obj_free,
		obj_dump
	);
}
Exemple #27
0
/*-------------------------------------------------------------------------
 * Function:    sym_truth
 *
 * Purpose:     Returns true if the symbol has a variable value which
 *              is true.
 *
 * Return:      Success:        true
 *
 *              Failure:        false
 *
 * Programmer:  Robb Matzke
 *              [email protected]
 *              Feb  7 1997
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
int
sym_truth (char *name) {

   obj_sym_t    *self=NULL;
   int          retval;

   if (!name || !*name) return false;
   self = (obj_sym_t *)obj_new (C_SYM, name);
   retval = obj_truth (self->sym->var);
   obj_dest ((obj_t)self);
   return retval;
}
Exemple #28
0
Value func_to_val(void* c_func, int num_params)
{
  Func* func;
  Value f = obj_new(klass_func, (void**) &func);
  func->var_params = 0;
  func->num_params = num_params;
  func->func = c_func;
  func->is_block = false;
  func->block_elems = 0;
  func->block_data = NULL;
  return f;
}
Exemple #29
0
/*---------------------------------------------------------------------------
 * Purpose:     Set a builtin symbol to the specified value. If VALUE
 *              looks like a number then it is treated as such, otherwise
 *              the symbol is assigned a string value.
 *
 *              If NAME does not begin with the standard prefix used for
 *              builtin variables then it will be automatically added.
 *
 * Programmer:  Robb Matzke
 *              Thursday, June  1, 2000
 *
 * Modifications:
 *---------------------------------------------------------------------------
 */
void
sym_bi_set(const char *name, const char *value, const char *desc,
           const char *doc)
{
    char        fullname[1024], *rest;
    obj_t       symbol;

    /* Add built-in prefix */
    if (*name!='$') {
        fullname[0] = '$';
        strcpy(fullname+1, name);
        name = fullname;
    }
    symbol = obj_new(C_SYM, name);

    /* Does value look like a number or a string? */
    if (!value || !*value) {
        sym_vbind(symbol, NIL);
    } else {
        strtod(value, &rest);
        if (rest && *rest) {
            sym_vbind(symbol, obj_new(C_STR, value));
        } else {
            sym_vbind(symbol, obj_new(C_NUM, value));
        }
    }

    /* Description for var table of contents */
    if (desc) {
        HelpVarToc[NHelpVarToc].name = safe_strdup(name);
        HelpVarToc[NHelpVarToc].desc = safe_strdup(desc);
        NHelpVarToc++;
    }
    
    /* The documentation string */
    if (doc) sym_dbind(symbol, obj_new(C_STR, doc));
    obj_dest(symbol);
}
Exemple #30
0
/*---------------------------------------------------------------------------
 * Purpose:     Invokes function FUNC on each defined symbol.
 *
 * Programmer:  Robb Matzke
 *              Wednesday, June  7, 2000
 *
 * Modifications:
 *---------------------------------------------------------------------------
 */
int
sym_map(int(*func)(obj_t, void*), void *cdata)
{
    int         i, retval=0;

    for (i=0; i<NSymbols; i++) {
        if (Symbol[i].name) {
            obj_t sym = obj_new(C_SYM, Symbol[i].name);
            retval += (func)(sym, cdata);
            obj_dest(sym);
        }
    }
    return retval;
}