Exemple #1
0
V7_PRIVATE enum v7_err do_exec(struct v7 *v7, const char *file_name,
  const char *source_code, int sp) {
  int has_ret = 0;
  struct v7_pstate old_pstate = v7->pstate;
  enum v7_err err = V7_OK;

  v7->pstate.source_code = v7->pstate.pc = source_code;
  v7->pstate.file_name = file_name;
  v7->pstate.line_no = 1;

  // Prior calls to v7_exec() may have left current_scope modified, reset now
  // TODO(lsm): free scope chain
  v7->this_obj = &v7->root_scope;

  next_tok(v7);
  while ((err == V7_OK) && (v7->cur_tok != TOK_END_OF_INPUT)) {
    // Reset stack on each statement
    if ((err = inc_stack(v7, sp - v7->sp)) == V7_OK) {
      err = parse_statement(v7, &has_ret);
    }
  }

  //printf("%s: [%s] %d %d\n", __func__, file_name, v7->pstate.line_no, err);
  assert(v7->root_scope.proto == &s_global);
  v7->pstate = old_pstate;

  return err;
}
Exemple #2
0
void eat_it(tokenizer_t t, token_kind_t kind) {
    if(cur_tok(t).kind == kind) {
        next_tok(t);
    }
    else {
        //printf("exit\n");
        exit(1);
    }
}
Exemple #3
0
void eat_it(tokenizer_t t, token_kind_t tok_kind){
    struct token tok = cur_tok(t);
    if (tok_kind != TOK_ANY && tok.kind != tok_kind){
        printf("expected ");
        output_token_kind(tok_kind);
        printf("unexpected ");
        output_token_kind(tok.kind);
        syntax_error(t, "eat_it error");
    }
    output_token(t);
    next_tok(t);
}
Exemple #4
0
int main(int argc, char ** argv){
  tokenizer_t t = mk_tokenizer(argv[1]);
  while(cur_tok(t).kind != tok_eof){
    if(cur_tok(t).kind == tok_nl){
      t->num = 0;
      next_tok(t);
    }
    else{
      int x = eat_int(t);
      while(cur_tok(t).kind != tok_nl){
        eat_plus(t);
        int y = eat_int(t);
        x = x + y;
      }
      t->num = 0;
      next_tok(t);
      printf("sum = %d\n", x);
    }
  }
  return 0;
}
Exemple #5
0
tokenizer_t mk_tokenizer(char * filename){
  tokenizer_t t = (tokenizer_t)malloc(sizeof(struct tokenizer));
  FILE * fp = safe_fopen(filename, "r");
  t->tok.filename = (char *)malloc((strlen(filename)+1)*sizeof(char));
  int c;
  t->tok.a = (char *)malloc(sizeof(char) * 100);
  t->tok.num = (char *)malloc(sizeof(char) * 100);
  c = fgetc(fp);
  t->c = c;
  t->fp = fp;
  t->tok.filename = filename;
  t->tok.line_num = 1;
  next_tok(t);
  return t;
}
Exemple #6
0
int
eval_expression(struct eval *eval, const tchar *expr, const tchar *elim, unsigned long *result)
{
	struct tok *tok, *op;
	trans_fn fn;
	int n;

	if (eval == NULL || expr == NULL || expr > elim || result == NULL) {
		PMNO(errno = EINVAL);
		return -1;
	}
	if (expr == elim) {
		*result = 0;
		return 0;
	}
	do {
		if ((n = next_tok(eval, expr, elim, &tok)) == -1) {
			AMSG("");
			return -1;
		}

		do {
			op = stack_peek(eval->opstk);
			fn = trans_matrix[tok->type - 1][op->type - 1];
			if (fn && fn(eval, tok) == -1) {
				AMSG("");
				return -1;
			}
		} while (fn == pop);

		expr += n;
	} while (n);

	if ((tok = stack_pop(eval->stk))) {
		*result = tok->val;
	} else {
		*result = 0;
	}

	return 0;
}
void
hpcrun_sample_sources_from_eventlist(char* evl)
{
  if (evl == NULL) {
    hpcrun_ssfail_none();
  }

  TMSG(EVENTS,"evl (before processing) = |%s|",evl);

  for(char *event = start_tok(evl); more_tok(); event = next_tok()){
    sample_source_t *s;
    if (strcasecmp(event, "LIST") == 0) {
      hpcrun_display_avail_events();
    }
    else if ( (s = hpcrun_source_can_process(event)) ){
      add_source(s);
      METHOD_CALL(s, add_event, event);
    }
    else {
      hpcrun_ssfail_unknown(event);
    }
  }
}
Exemple #8
0
token get_tok(char *s, unsigned *k) {
  token tok;
  while ((tok = next_tok(s, k)).type == WHITE);
  return tok;
}
Exemple #9
0
/* 
 * Parses string containing encoded plot limits and writes then to 'limits' 
 * returns 1 on success, 0 if parse error.
 */
static int parse_limits(Limits * limits, char *lim_string)
{
    token *tok;
    char *tmp;
    int i, lim_pos = 0, sign = 1;

    if (!limits)
        return 0;

    /* parse all 4 limits */
    for (i = 0; i < 4; i++) {
        if (i > 0) {
            tok = next_tok(lim_string, lim_pos);
            if (tok->type != T_COLON) {
                (void) parse_error(tok, "Delimiter expected");
                free(tok);
                return 0;
            }
            lim_pos += tok->len;
            free(tok);
        }

        sign = 1;
        tok = next_tok(lim_string, lim_pos);
        /* minus does not bind to a number, it behaves like an unary operator */
        if (tok->type == T_OP && lim_string[tok->pos] == '-') {
            sign = -1;
            lim_pos += tok->len;
            free(tok);
            tok = next_tok(lim_string, lim_pos);
        }

        tmp = (char *) malloc(sizeof(char) * (tok->len + 1));
        assert(tmp);

        strncpy(tmp, lim_string + tok->pos, tok->len);
        tmp[tok->len] = '\0';

        /* parse number according to its type */
        switch (tok->type) {
        case T_HEX:
        case T_DEC:
        case T_OCT:
            *((double *) limits + i) =
                sign * (double) strtoul(tmp, NULL, 0);
            break;
        case T_FLOAT:
            *((double *) limits + i) = sign * (double) strtod(tmp, NULL);
            break;
            /* handle errors by the same function that is used by main parser */
        default:
            (void) parse_error(tok, "Number expected");
            free(tmp);
            free(tok);
            return 0;
        }
        lim_pos += tok->len;
        free(tmp);
        free(tok);
    }

    /* check if last token is eof */
    tok = next_tok(lim_string, lim_pos);
    if (tok->type != T_EOF) {
        (void) parse_error(tok, "Redundant");
        free(tok);
        return 0;
    }
    free(tok);


    /* Perform check on limits, do not allow reversed x-axis */
    if (limits->x_low >= limits->x_high || limits->y_low >= limits->y_high) {
        fprintf(stderr, "Low limit must be less than high limit\n");
        return 0;
    }

    return 1;
}
Exemple #10
0
// take a tokenized expression (expr) with precalculated internal values (llp and ldp) and evaluate it
// HIHI maybe put the return value in an arg, and pass back an error flag? -- otherwise need *inf, so I can show_errors?
// -- move this back into cpp?? It's not generic enough.
int32_t calculate_expr(uint8_t *expr, uint64_t *llp, int32_t llcnt, double *ldp, int32_t ldblcnt)
{
	uint8_t *s, *e, *p, *c, restart, tok, type[200];
	int i;
	restart = 0;

	i = 200;
	while (--i >= 0) type[i] = 0;			// init the unused part of the array to 0
	i = llcnt;
	while (--i >= 0) type[i] = 1;			// init all the ints to uint64_t
	i = ldblcnt;
	while (--i >= 0) type[199 - i] = 42;	// init all the floats to long double
// HIHI! enforce that llcnt + ldblcnt < 256 - TOK_SIZEOF

	s = expr;
	// scan to the first ')' token, scan backwards to the first '(' token -- then evaluate that subexpression
	// -- each pair of parens get deleted after their whole subexpression is done parsing
	while (*s != TOK_C_PAREN && *s != TOK_ILLEGAL) ++s;
	while (*s != TOK_ILLEGAL)
	{
		e = s;
		while (*--s != TOK_O_PAREN);
		// find the highest precedence operator in the expression
		// no "primary" operators are allowed in the preprocessor -- scan right to left for the first active unary operator
		p = e;
		// + - ! ~ sizeof(cast) (casts)=masking
		while (*--p != TOK_O_PAREN && restart == 0)
		{
			if (*p == TOK_B_NOT || *p == TOK_NOT)		// in this compiler, bitwise not and boolean not are the same operator
			{
				tok = next_tok(p);			// the next token *must* be an rvalue for the operator
//				if (tok <= TOK_SIZEOF, or if the variable is a float?) show_error;
				// modify the rvalue at the right end of the expression
				llp[tok - TOK_SIZEOF - 1] = ~llp[tok - TOK_SIZEOF - 1];
				*p = TOK_NO_OP;							// now that the operator has been processed, delete it
				p = e;
			}
			// a minus sign is a NEG unary operator if there is another operator (and not a "variable") to the left
	// HIHI!! gotta handle the float case, too!
			else if (*p == TOK_SUB && prev_tok(p) <= TOK_SIZEOF)
			{
				tok = next_tok(p);			// the next token *must* be an rvalue for the operator
//				if (tok <= TOK_SIZEOF) show_error;
				// modify the rvalue at the right end of the expression
	// check "type" to see if this tok is a float
				llp[tok - TOK_SIZEOF - 1] = - (int64_t) llp[tok - TOK_SIZEOF - 1];
				*p = TOK_NO_OP;							// now that the operator has been processed, delete it
				p = e;
			}
			// a plus sign is a unary operator (and a no-op) if there is another operator (and not a "variable") to the left
			else if (*p == TOK_ADD && prev_tok(p) <= TOK_SIZEOF)
			{
				*p = TOK_NO_OP;							// delete the + operator and restart the scan
				p = e;
			}
			else if (*p >= TOK_BOOL_T && *p <= TOK_UNSGN_T)
			{
				// either this is an input into sizeof (as a cast), or it's a cast of the following value
				// -- so (multiple) type keywords should be the only thing inside the parens
				// -- because the preprocessor doesn't know about function or variable declarations
				c = p - 1;
				while (*c == TOK_NO_OP || (*c >= TOK_BOOL_T && *c <= TOK_UNSGN_T)) --c;
				// verify the open and close parens around this (cast)
				// obviously, s also points at the '(' and e points at the ')'
	// HIHI!!! woops! the next tok may be a *, and not a paren! Need to scan that direction, too!
				if (next_tok(p) != TOK_C_PAREN || c != s)
				{
					i = 0;
//					show_error(0,"typecast(?) not in parens",NULL,1);
				}
				p = s;
				while (*--p == TOK_NO_OP);
				if (*p == TOK_SIZEOF)		// immediately convert a sizeof(cast) into a variable (with the correct value)
				{
					// get the next open int variable number
					type[llcnt] = 0;
					i = -1;
					while (type[++i] != 0);
					if (i == llcnt) ++llcnt;				// HIHI!! need to put a 199 limit on llcnt!
					// replace the sizeof() token with the actual size, and no-op the cast
					*p = i + TOK_SIZEOF + 1;
					llp[i] = size_of(s + 1);
					type[i] = 1;
					while (*++p != TOK_C_PAREN) *p = TOK_NO_OP;
					*p = TOK_NO_OP;
					restart = 1;
				}
				else
				{
					// do an immediate mask and type modification of the rvalue variable
					tok = next_tok(p);				// get the variable index
					i = size_of(s + 1) - 1;			// get the byte count - 1
					if (i == 3) i = 2;				// convert to a mask index
					if (i < 3)
						llp[tok - TOK_SIZEOF - 1] &= size_mask[i];
					else i = 3;
					type[tok - TOK_SIZEOF - 1] = 4 - i;		// convert to a type (maybe I should reverse the order of the types?? HIHI)
				}
			}
		}
		// then the multiplicative operators -- p already points to the start
		while (restart == 0 && *++p != TOK_C_PAREN)
		{
			if (*p == TOK_MULT || *p == TOK_DIV || *p == TOK_MOD)
			{
				restart = 1;
				binary_op(p, llp, type);
			}
		}

		// then additiive
		p = s;
		while (restart == 0 && *++p != TOK_C_PAREN)
		{
			if (*p == TOK_ADD || *p == TOK_SUB)
			{
				restart = 1;
				binary_op(p, llp, type);
			}
		}

		// then shifts
		p = s;
		while (restart == 0 && *++p != TOK_C_PAREN)
		{
			if (*p == TOK_SHR || *p == TOK_SHL)
			{
				restart = 1;
				binary_op(p, llp, type);
			}
		}

		// then relational conditionals
		p = s;
		while (restart == 0 && *++p != TOK_C_PAREN)
		{
			if (*p == TOK_B_LT || *p == TOK_B_GT || *p == TOK_B_LE || *p == TOK_B_GE)
			{
				restart = 1;
				binary_op(p, llp, type);
			}
		}

		// then equality conditionals
		p = s;
		while (restart == 0 && *++p != TOK_C_PAREN)
		{
			if (*p == TOK_B_EQ || *p == TOK_B_NE)
			{
				restart = 1;
				binary_op(p, llp, type);
			}
		}

		// then bitwise operators -- AND &
		p = s;
		while (restart == 0 && *++p != TOK_C_PAREN)
		{
			if (*p == TOK_AND)
			{
				restart = 1;
				binary_op(p, llp, type);
			}
		}

		// XOR ^
		p = s;
		while (restart == 0 && *++p != TOK_C_PAREN)
		{
			if (*p == TOK_XOR)
			{
				restart = 1;
				binary_op(p, llp, type);
			}
		}

		// OR |
		p = s;
		while (restart == 0 && *++p != TOK_C_PAREN)
		{
			if (*p == TOK_OR)
			{
				restart = 1;
				binary_op(p, llp, type);
			}
		}

		// then booleans &&
		p = s;
		while (restart == 0 && *++p != TOK_C_PAREN)
		{
			if (*p == TOK_B_AND)
			{
				restart = 1;
				binary_op(p, llp, type);
			}
		}

		// ||
		p = s;
		while (restart == 0 && *++p != TOK_C_PAREN)
		{
			if (*p == TOK_B_OR)
			{
				restart = 1;
				binary_op(p, llp, type);
			}
		}

		// and last, the stupid "ternary condtional" ?	evaluate right to left, p is already set properly
		while (restart == 0 && *--p != TOK_O_PAREN)
		{
			if (*p == TOK_QMARK)
				i = 8;			// HIHI!!! gotta parse it and eliminate it from the expr
		}

		// are there any operators left between s and e? If not, destroy the parens of this fully evaluated subexpression.
		p = s + 1;
		while (*p > TOK_SIZEOF || *p == TOK_NO_OP) ++p;
		if (*p == TOK_C_PAREN)
		{
			*s = TOK_NO_OP;
			*p = TOK_NO_OP;
		}
		restart = 0;
		s = expr;
		while (*s != TOK_C_PAREN && *s != TOK_ILLEGAL) ++s;
	}
	// there must be one variable left in the expression now -- that's the return value
	p = expr + 1;
	while (*p < TOK_SIZEOF) ++p;

	if (llp[*p - TOK_SIZEOF - 1] == 0) return 0;
	return -1;
}
Exemple #11
0
// HIHI!! almost certainly need to change the return value -- return error codes, return float values, or int values
void binary_op(uint8_t *p, uint64_t *llp, uint8_t *type)
{
	uint64_t result;
	uint8_t rval_idx, op, i, j;
	op = *p;										// preserve the operator token
	rval_idx = next_tok(p);
	if (rval_idx <= TOK_SIZEOF) rval_idx = TOK_SIZEOF + 1;		// a blank "variable" means a value of 0
	
	while (*--p == TOK_NO_OP);							// find the lval
	if (*p <= TOK_SIZEOF)  *++p = TOK_SIZEOF + 1;

	i = rval_idx - TOK_SIZEOF - 1;
	j = *p - TOK_SIZEOF - 1;
	result = 0;

	switch (op)
	{
	case TOK_B_EQ:
		if (llp[j] == llp[i]) result = BOOL_TRUE;
		break;
	case TOK_B_NE:
		if (llp[j] != llp[i]) result = BOOL_TRUE;
		break;
	case TOK_B_LT:
		if (llp[j] < llp[i]) result = BOOL_TRUE;
		break;
	case TOK_B_GT:
		if (llp[j] > llp[i]) result = BOOL_TRUE;
		break;
	case TOK_B_LE:
		if (llp[j] <= llp[i]) result = BOOL_TRUE;
		break;
	case TOK_B_GE:
		if (llp[j] >= llp[i]) result = BOOL_TRUE;
		break;
	case TOK_MULT:
		result = llp[j] * llp[i];
		break;
	case TOK_DIV:
		result = llp[j] / llp[i];
		break;
	case TOK_MOD:
		result = llp[j] % llp[i];
		break;
	case TOK_ADD:
		result = llp[j] + llp[i];
		break;
	case TOK_SUB:
		result = llp[j] - llp[i];
		break;
	case TOK_SHL:
		result = llp[j] << (char) llp[i];
		break;
	case TOK_SHR:
		result = llp[j] >> (char) llp[i];
		break;
	case TOK_B_AND:
	case TOK_AND:
		result = llp[j] & llp[i];
		break;
	case TOK_XOR:
		result = llp[j] ^ llp[i];
		break;
	case TOK_B_OR:
	case TOK_OR:
		result = llp[j] | llp[i];
	}
	// delete the variable with the shorter type -- set its type to 0 (longer types have lower "type" values)
	// -- unless the varaible was undefined (and has a value of 0)
	if (type[i] < type[j]) i = j, j = rval_idx - TOK_SIZEOF - 1;
	if (i != 0) type[i] = 0;

	// if *BOTH* variables were undefined, then allocate an actual variable for the result
	if (j == 0)
	{
		while (type[++j] != 0);		// the caller is required to have one slot open in the array
		type[j] = 1;
	}

	// if the result was from a boolean operation, set the type of the remaining variable to bool, and mask to 1 byte
	if (op == TOK_B_EQ || op == TOK_B_NE || op == TOK_B_LT || op == TOK_B_GT || op == TOK_B_LE || op == TOK_B_GE ||
		op == TOK_B_AND || op == TOK_B_OR)
	{
		type[j] = 4;
		result &= 0xff;
	}

	// store result in the remaining variable
	llp[j] = result;

	// overwrite *p with the variable token
	*p = j + TOK_SIZEOF + 1;

	// scan forward to the operator, overwrite with a no-op
	while (*++p == TOK_NO_OP);
	*p = TOK_NO_OP;
	// scan forward to the rval, overwrite it with a no-op -- if it existed!
	if (rval_idx != TOK_SIZEOF + 1)
	{
		while (*++p == TOK_NO_OP);
		*p = TOK_NO_OP;
	}
}
Exemple #12
0
static void
METHOD_FN(process_event_list, int lush_metrics)
{

  // fetch the event string for the sample source
  char* _p = METHOD_CALL(self, get_event_str);
  
  //
  // EVENT: Only 1 wallclock event
  //
  char* event = start_tok(_p);

  char name[1024]; // local buffer needed for extract_ev_threshold

  TMSG(_TST_CTL,"checking event spec = %s",event);

  // extract event threshold
  hpcrun_extract_ev_thresh(event, sizeof(name), name, &period, DEFAULT_THRESHOLD);

  // store event threshold
  METHOD_CALL(self, store_event, _TST_EVENT, period);
  TMSG(OPTIONS,"_TST period set to %ld",period);

  // set up file local variables for sample source control
  int seconds = period / 1000000;
  int microseconds = period % 1000000;

  TMSG(OPTIONS,"init timer w sample_period = %ld, seconds = %ld, usec = %ld",
       period, seconds, microseconds);

  // signal once after the given delay
  itimer.it_value.tv_sec = seconds;
  itimer.it_value.tv_usec = microseconds;

  // macros define whether automatic restart or not
  itimer.it_interval.tv_sec  =  AUTOMATIC_ITIMER_RESET_SECONDS(seconds);
  itimer.it_interval.tv_usec =  AUTOMATIC_ITIMER_RESET_MICROSECONDS(microseconds);

  // handle metric allocation
  hpcrun_pre_allocate_metrics(1 + lush_metrics);
  
  int metric_id = hpcrun_new_metric();
  METHOD_CALL(self, store_metric_id, _TST_EVENT, metric_id);

  // set metric information in metric table

#ifdef USE_ELAPSED_TIME_FOR_WALLCLOCK
# define sample_period 1
#else
# define sample_period period
#endif

  TMSG(_TST_CTL, "setting metric _TST, period = %ld", sample_period);
  hpcrun_set_metric_info_and_period(metric_id, "_TST",
				    MetricFlags_ValFmt_Int,
				    sample_period, metric_property_none);
  if (lush_metrics == 1) {
    int mid_idleness = hpcrun_new_metric();
    lush_agents->metric_time = metric_id;
    lush_agents->metric_idleness = mid_idleness;

    hpcrun_set_metric_info_and_period(mid_idleness, "idleness (ms)",
				      MetricFlags_ValFmt_Real,
				      sample_period, metric_property_none);
  }

  event = next_tok();
  if (more_tok()) {
    EMSG("MULTIPLE _TST events detected! Using first event spec: %s");
  }
}
Exemple #13
0
void eat_plus(tokenizer_t t){
  token tok = cur_tok(t);
  if (tok.kind != tok_plus) syntax_error(t);
  next_tok(t);
}
Exemple #14
0
int eat_int(tokenizer_t t){
  token tok = cur_tok(t);
  if(tok.kind != tok_int) syntax_error(t);
  next_tok(t);
  return tok.ival;
}
Exemple #15
0
static void
METHOD_FN(process_event_list, int lush_metrics)
{
  char name[1024]; // local buffer needed for extract_ev_threshold

  TMSG(ITIMER_CTL, "process event list, lush_metrics = %d", lush_metrics);

  // fetch the event string for the sample source
  char* evlist = METHOD_CALL(self, get_event_str);
  char* event = start_tok(evlist);

  TMSG(ITIMER_CTL,"checking event spec = %s",event);

  if (hpcrun_ev_is(event, WALLCLOCK_EVENT_NAME)) {
#ifdef HOST_SYSTEM_IBM_BLUEGENE
    use_itimer = true;
    the_event_name = WALLCLOCK_EVENT_NAME;
    the_metric_name = WALLCLOCK_METRIC_NAME;
    the_signal_num = ITIMER_SIGNAL;
#else
#ifdef ENABLE_CLOCK_CPUTIME
    use_cputime = true;
    the_event_name = CPUTIME_EVENT_NAME;
    the_metric_name = CPUTIME_METRIC_NAME;
    the_signal_num = REALTIME_SIGNAL;
#else
    EEMSG("Event %s (%s) is not available on this system.",
	  WALLCLOCK_EVENT_NAME, CPUTIME_EVENT_NAME);
    hpcrun_ssfail_unknown(event);
#endif
#endif
  }

  if (hpcrun_ev_is(event, REALTIME_EVENT_NAME)) {
#ifdef ENABLE_CLOCK_REALTIME
    use_realtime = true;
    the_event_name = REALTIME_EVENT_NAME;
    the_metric_name = REALTIME_METRIC_NAME;
    the_signal_num = REALTIME_SIGNAL;
#else
    EEMSG("Event %s is not available on this system.", REALTIME_EVENT_NAME);
    hpcrun_ssfail_unknown(event);
#endif
  }

  if (hpcrun_ev_is(event, CPUTIME_EVENT_NAME)) {
#ifdef ENABLE_CLOCK_CPUTIME
    use_cputime = true;
    the_event_name = CPUTIME_EVENT_NAME;
    the_metric_name = CPUTIME_METRIC_NAME;
    the_signal_num = REALTIME_SIGNAL;
#else
    EEMSG("Event %s is not available on this system.", CPUTIME_EVENT_NAME);
    hpcrun_ssfail_unknown(event);
#endif
  }

  if (hpcrun_ev_is(event, ITIMER_EVENT_NAME)) {
    use_itimer = true;
    the_event_name = ITIMER_EVENT_NAME;
    the_metric_name = ITIMER_METRIC_NAME;
    the_signal_num = ITIMER_SIGNAL;
  }

  if (!use_itimer && !use_realtime && !use_cputime) {
    // should never get here if supports_event is true
    hpcrun_ssfail_unknown(event);
  }

  // extract event threshold
  hpcrun_extract_ev_thresh(event, sizeof(name), name, &period, DEFAULT_PERIOD);

  // store event threshold
  METHOD_CALL(self, store_event, ITIMER_EVENT, period);
  TMSG(OPTIONS,"wallclock period set to %ld",period);

  // set up file local variables for sample source control
  int seconds = period / 1000000;
  int microseconds = period % 1000000;

  TMSG(ITIMER_CTL, "init %s sample_period = %ld, seconds = %d, usec = %d",
       the_event_name, period, seconds, microseconds);

  itval_start.it_value.tv_sec = seconds;
  itval_start.it_value.tv_usec = microseconds;
  itval_start.it_interval.tv_sec = 0;
  itval_start.it_interval.tv_usec = 0;

  itspec_start.it_value.tv_sec = seconds;
  itspec_start.it_value.tv_nsec = 1000 * microseconds;
  itspec_start.it_interval.tv_sec = 0;
  itspec_start.it_interval.tv_nsec = 0;

  // older versions of BG/P incorrectly delivered SIGALRM when
  // interval is zero. I (krentel) believe this is no longer
  // necessary, but it can't really hurt.
#ifdef HOST_SYSTEM_IBM_BLUEGENE
  itval_start.it_interval.tv_sec = 3600;
  itspec_start.it_interval.tv_sec = 3600;
#endif

  memset(&itval_stop, 0, sizeof(itval_stop));
  memset(&itspec_stop, 0, sizeof(itspec_stop));

  sigemptyset(&timer_mask);
  sigaddset(&timer_mask, the_signal_num);

  // handle metric allocation
  hpcrun_pre_allocate_metrics(1 + lush_metrics);
  
  int metric_id = hpcrun_new_metric();
  METHOD_CALL(self, store_metric_id, ITIMER_EVENT, metric_id);

  // set metric information in metric table
  TMSG(ITIMER_CTL, "setting metric timer period = %ld", sample_period);
  hpcrun_set_metric_info_and_period(metric_id, the_metric_name,
				    MetricFlags_ValFmt_Int,
				    sample_period, metric_property_time);
  if (lush_metrics == 1) {
    int mid_idleness = hpcrun_new_metric();
    lush_agents->metric_time = metric_id;
    lush_agents->metric_idleness = mid_idleness;

    hpcrun_set_metric_info_and_period(mid_idleness, IDLE_METRIC_NAME,
				      MetricFlags_ValFmt_Real,
				      sample_period, metric_property_time);
  }

  event = next_tok();
  if (more_tok()) {
    EEMSG("Can't use multiple timer events in the same run.");
    hpcrun_ssfail_conflict("timer", event);
  }
}
static NSS_STATUS fill_grent(struct group *result, struct winbindd_gr *gr,
		      char *gr_mem, char **buffer, size_t *buflen)
{
	fstring name;
	int i;
	char *tst;

	/* Group name */

	if ((result->gr_name =
	     get_static(buffer, buflen, strlen(gr->gr_name) + 1)) == NULL) {

		/* Out of memory */

		return NSS_STATUS_TRYAGAIN;
	}

	strlcpy(result->gr_name, gr->gr_name, strlen(gr->gr_name) + 1);

	/* Password */

	if ((result->gr_passwd =
	     get_static(buffer, buflen, strlen(gr->gr_passwd) + 1)) == NULL) {

		/* Out of memory */
		
		return NSS_STATUS_TRYAGAIN;
	}

	strlcpy(result->gr_passwd, gr->gr_passwd, strlen(gr->gr_passwd) + 1);

	/* gid */

	result->gr_gid = gr->gr_gid;

	/* Group membership */

	if ((gr->num_gr_mem < 0) || !gr_mem) {
		gr->num_gr_mem = 0;
	}

	/* this next value is a pointer to a pointer so let's align it */

	/* Calculate number of extra bytes needed to align on pointer size boundry */
	if ((i = (unsigned long)(*buffer) % sizeof(char*)) != 0)
		i = sizeof(char*) - i;
	
	if ((tst = get_static(buffer, buflen, ((gr->num_gr_mem + 1) * 
				 sizeof(char *)+i))) == NULL) {

		/* Out of memory */

		return NSS_STATUS_TRYAGAIN;
	}
	result->gr_mem = (char **)(tst + i);

	if (gr->num_gr_mem == 0) {

		/* Group is empty */

		*(result->gr_mem) = NULL;
		return NSS_STATUS_SUCCESS;
	}

	/* Start looking at extra data */

	i = 0;

	while(next_tok((char **)&gr_mem, name, ",", sizeof(fstring))) {
        
		/* Allocate space for member */
        
		if (((result->gr_mem)[i] = 
		     get_static(buffer, buflen, strlen(name) + 1)) == NULL) {
            
			/* Out of memory */
            
			return NSS_STATUS_TRYAGAIN;
		}        
        
		strlcpy((result->gr_mem)[i], name, strlen(name) + 1);
		i++;
	}

	/* Terminate list */

	(result->gr_mem)[i] = NULL;

	return NSS_STATUS_SUCCESS;
}