Exemple #1
0
fsmReturnStatus led_toggle(Fsm * fsm, const Event* e) {

//!!!!!!make all tasks global.
//!!!mistake: set td.next=NULL will disrupt scheduler!!!!
//	static taskDescriptor td;
//	td.task = &wrapper_red_led;
//	//td.param = &;  //void pointer point to void, param is of type void
//	td.expire = 0;
//	td.period = 250;   //0.25s = 4Hz
//	td.execute = 0;
//	td.next = NULL;
//
//	static taskDescriptor td2;
//	td2.task = &wrapper_turnoff_led;
//	td2.param = fsm;  //void pointer point to void, param is of type void
//	td2.expire = 5000;  //count 5s
//	td2.period = 0;
//	td2.execute = 0;
//	td2.next = NULL;
//
//	static taskDescriptor td3;
//	td3.task = &time_increment;
//	td3.param = fsm;
//	td3.expire = 0;
//	td3.period = 1000; // every second update the time of the clock
//	td3.execute = 0;
//	td3.next = NULL;

	switch (e->signal) {
	case ENTRY:
		td_toggle_led.expire = 0;
		td_turnoff_led.expire = 5000;
		td_time_increment.expire = 0;
		scheduler_add(&td_toggle_led);
		scheduler_add(&td_turnoff_led);
		scheduler_add(&td_time_increment);
		return RET_HANDLED;
	case JOYSTICK_PRESSED:
		return TRANSITION(normal_operating);
	case ROTARY_PRESSED:
		return TRANSITION(normal_operating);
	case EXIT:
		led_redOff();
		scheduler_remove(&td_toggle_led);
		scheduler_remove(&td_turnoff_led);
		scheduler_remove(&td_time_increment);
		return RET_HANDLED;
	default:
		return RET_IGNORED;
	}
}
Exemple #2
0
int main(void) {
	button_init(true);
	led_greenInit();
	led_yellowInit();
	led_redInit();//testing
	lcd_init();
	scheduler_init();

//5.2.1:toggle green led every 2s
	taskDescriptor td1; //= (taskDescriptor*) malloc(sizeof(taskDescriptor));
	td1.task = &wrapper_greenToggle;
	//td.param = &;  //void pointer point to void, param is of type void
	td1.expire = 2000;
	td1.period = 2000;
	td1.execute = 0;
	td1.next = NULL;
	scheduler_add(&td1);

//5.2.2: schedule button_checkState
	taskDescriptor td2; //= (taskDescriptor*) malloc(sizeof(taskDescriptor));
	td2.task = &wrapper_button_checkState;
	//td.param = &;  //void pointer point to void, param is of type void
	td2.expire = 0;
	td2.period = 5;
	td2.execute = 0;
	td2.next = NULL;
	scheduler_add(&td2);

//5.2.3: scheduler or button click determines the situation
	button_setJoystickButtonCallback(control_yellow);

//5.2.4 :schedule stopwatch
	fprintf(lcdout, "Please press the rotary button to start the stopwatch");
	button_setRotaryButtonCallback(stopWatch);

	taskDescriptor td5; //= (taskDescriptor*) malloc(sizeof(taskDescriptor));
	td5.task = &calc_time;
	//td5.param = ;  //void pointer point to void, param is of type void
	td5.expire = 0; //immediately run
	td5.period = 100; //0.1s
	td5.execute = 0;
	td5.next = NULL;
	scheduler_add(&td5);

	sei();
	scheduler_run();
	return 1;
}
Exemple #3
0
fsmReturnStatus normal_operating(Fsm * fsm, const Event* e) {
	static bool enable = false;

	switch (e->signal) {
	case ENTRY:
		td_time_increment.expire = 0;
		scheduler_add(&td_time_increment);
		return RET_HANDLED;
	case JOYSTICK_PRESSED:
		return TRANSITION(set_alarm_hour);
	case ROTARY_PRESSED:
		enable = !enable;
		fsm->isAlarmEnabled = enable;
		if (enable)
			led_yellowOn();
		else
			led_yellowOff();
		return RET_HANDLED;
	case MATCHING:
		if (fsm->isAlarmEnabled) {
			return TRANSITION(led_toggle);
		} else
			return RET_HANDLED;
	case EXIT:
		scheduler_remove(&td_time_increment);
		return RET_HANDLED;
	default:
		return RET_IGNORED;
	}
}
Exemple #4
0
int main() {

//task 6.1
	pButtonCallback joystickButton = wrapper_pwm;
	button_init(true); //debouncing, timer1 is initialized in this function
	button_setJoystickButtonCallback(joystickButton);

	pwm_init();
	pwm_setDutyCycle(0); //initially motor idle

//task 6.2,6.3
	lcd_init();
	led_yellowInit();
	led_greenInit();
	scheduler_init(); // timer2_start() is called there.
	motorFrequency_init(); //timer 5 and external interrupt settings

	taskDescriptor td1; //= (taskDescriptor*) malloc(sizeof(taskDescriptor));
	td1.task = &display;
//td.param = &;  //void pointer point to void, param is of type void
	td1.expire = 0;
	td1.period = 500; //timer2 INT every 1ms
	td1.execute = 0;
	td1.next = NULL;
	scheduler_add(&td1);

//task6.4
	uart_init(57600); //debugging

	pidData_t pidData;
	pid_Init(P * SCALING_FACTOR, I* SCALING_FACTOR, D *SCALING_FACTOR, &pidData); //set p=0; i=1.5, d=0;
	taskDescriptor td2; //= (taskDescriptor*) malloc(sizeof(taskDescriptor));
	td2.task = &wrapper_pid;
	td2.param = &pidData;  //void pointer point to void, param is of type void
	td2.expire = 0;
	td2.period = 200; //timer2 INT every 1ms
	td2.execute = 0;
	td2.next = NULL;
	scheduler_add(&td2);

	sei();
	scheduler_run();
	return 0;
}
Exemple #5
0
void scheduler_clear(void)
{
//    deb = get_iopin(9);
//    set_dir(deb, 1);

    for (uint16_t i=0; i<MAX_TRIGGERED; i++) {
        triggered_tasks[i] = 0;
    }
    num_scheduled = 0;
    scheduler_add(10, led_task);
}
Exemple #6
0
fsmReturnStatus alarm_init(Fsm * fsm, const Event* e) {

	td_toggle_led.task = &wrapper_red_led;
	//td.param = ;
	td_toggle_led.expire = 0;
	td_toggle_led.period = 250;   //0.25s = 4Hz
	td_toggle_led.execute = 0;
	td_toggle_led.next = NULL;

	td_turnoff_led.task = &wrapper_turnoff_led;
	td_turnoff_led.param = fsm;
	td_turnoff_led.expire = 5000;  //count 5s
	td_turnoff_led.period = 0;
	td_turnoff_led.execute = 0;
	td_turnoff_led.next = NULL;

	td_time_increment.task = &time_increment;
//	td3.param ;
	td_time_increment.expire = 0;
	td_time_increment.period = 1000; // every second update the time of the clock
	td_time_increment.execute = 0;
	td_time_increment.next = NULL;

	td_check_matching.task = &check_matching;
//	td4.param
	td_check_matching.expire = 0;
	td_check_matching.period = 1000; // every second check if matching
	td_check_matching.execute = 0;
	td_check_matching.next = NULL;


	td_check_rotary_encoder.task = &wrapper_check_rotary;
	td_check_rotary_encoder.expire = 0;  //immediately execute the task
	td_check_rotary_encoder.period = 1; //
	td_check_rotary_encoder.execute = 0;
	td_check_rotary_encoder.next = NULL;
	scheduler_add(&td_check_rotary_encoder);


	switch (e->signal) {
	case ENTRY:
		fsm->isAlarmEnabled = false;
		fprintf(lcdout, "%02d:%02d\n", 0, 0);
		fprintf(lcdout, "set clock hour");
		(fsm->timeSet).hour = 0;
		(fsm->timeSet).minute = 0;
		(fsm->timeSet).second = 0;
		return TRANSITION(sethour);
	default:
		return RET_IGNORED;
	}
}
Exemple #7
0
/*-------------------------------------------------------------------------*/
message_t *fsm_handle_preload(fsm_t *fsm, message_t *msg) {
  ophcrack_t *crack = fsm->crack;
  scheduler_t *sched = crack->sched;

  // If the preloading of the tables is finished, then we start
  // searching into the tables.

  if (msg->kind == msg_done) {
    msg_done_t *done = (msg_done_t*)msg->data;
    int nthreads = sched->nthreads;
    int n;    

    if (done->kind == preload_all) {
      assert(fsm->psize_curr <= fsm->psize_total);

      // Check that the tables have been correctly preloaded.

//      if (fsm->psize_curr < fsm->psize_total)
//	ophcrack_preload_check(crack);

      // This is necessary to prevent the status bar from indicating
      // that a preload task is 'waiting' if no preloading occured.

      fsm->psize_curr  = 1;
      fsm->psize_total = 1;

      // Start the work tasks.

      for (n=0; n < MY_MAX(1, nthreads-1); ++n)
	if (ophcrack_next(crack) == 0) break;

      // If no tasks have been scheduled, then we schedule a fake task
      // which will possibly trigger the 'done(all)' message if it is
      // the last one to be executed. This trick is required since the
      // brute force might still be running, therefore we should not
      // stop here, but wait until the 'done(all)' message is
      // received.

      if (n == 0) {
	ophtask_t *task = ophtask_alloc(find);
	scheduler_add(sched, task, low);
      }

      fsm->state = st_work1;
    }
  }

  return msg;
}
Exemple #8
0
/*-------------------------------------------------------------------------*/
void fsm_launch_preload(fsm_t *fsm) {
  ophcrack_t *crack = fsm->crack;
  scheduler_t *sched = crack->sched;

  ophtask_t *task = ophtask_alloc(preload_all);
  ophload_t *load = (ophload_t*)task->data;

  list_t *enabled = crack->enabled;
  list_nd_t *tnd  = 0;

  for (tnd = enabled->head; tnd != 0; tnd = tnd->next)
    list_add_tail(load->tables, tnd->data);
  
  scheduler_add(sched, task, disk);
  fsm->preload = 0;
}
Exemple #9
0
fsmReturnStatus set_alarm_min(Fsm * fsm, const Event* e) {

	Time_t *temp = &(fsm->timeSet);

	switch (e->signal) {
	case ENTRY:
		lcd_clear();
		lcd_setCursor(0, 0);
		fprintf(lcdout, "%02d:%02d\n", temp->hour, temp->minute);
		fprintf(lcdout, "set alarm min");
		return RET_HANDLED;
	case ROTARY_PRESSED:
		if (++(temp->minute) > 59)
			temp->minute = 0;
		lcd_clear();
		lcd_setCursor(0, 0);
		fprintf(lcdout, "%02d:%02d\n", temp->hour, temp->minute);
		fprintf(lcdout, "set alarm min");
		return RET_HANDLED;
	case ROTARY_INC:
		if (++(temp->minute) > 59)
			temp->minute = 0;
		lcd_clear();
		lcd_setCursor(0, 0);
		fprintf(lcdout, "%02d:%02d\n", temp->hour, temp->minute);
		fprintf(lcdout, "set alarm min");
		return RET_HANDLED;
	case ROTARY_DEC:
		if ((temp->minute) == 0)
			temp->minute = 60;
		lcd_clear();
		lcd_setCursor(0, 0);
		fprintf(lcdout, "%02d:%02d\n", temp->hour, --(temp->minute));
		fprintf(lcdout, "set alarm min");
		return RET_HANDLED;
	case JOYSTICK_PRESSED:
		return TRANSITION(normal_operating);
	case EXIT:
		td_check_matching.param = fsm;//in order to get the timeSet in the check matching
		td_check_matching.expire = 0;
		scheduler_add(&td_check_matching);
		return RET_HANDLED;
	default:
		return RET_IGNORED;
	}
}
Exemple #10
0
void control_yellow() {
	static taskDescriptor td3;
	//td3 should remain same as before.
	//without static, the parameter in wrapper_yellowOff(&td3); would be null.
	state_on = !state_on;

	if (state_on) {
		led_yellowOn();
		td3.task = &wrapper_yellowOff;
		td3.param = &td3;
		td3.expire = 5000; //count 5s
		td3.period = 0;//run once
		td3.execute = 0;
		td3.next = NULL;
		scheduler_add(&td3);
	} else {
		led_redOff();
		wrapper_yellowOff(&td3);
		scheduler_remove(&td3);
	}
}
Exemple #11
0
/*-------------------------------------------------------------------------*/
void fsm_launch_bforce(fsm_t *fsm) {
  ophcrack_t *crack = fsm->crack;
  scheduler_t *sched = crack->sched;

  ophtask_t *task = ophtask_alloc(bforce_all);
  ophbforce_t *force = (ophbforce_t*)task->data;

  list_t *hashes = crack->hashes;
  list_nd_t *nd;

  int nhashes = hashes->size;
  int n;

  force->nhashes = nhashes;
  force->hashes  = (hash_t**)malloc(nhashes*sizeof(hash_t*));
  
  for (nd=hashes->head, n=0; nd!=0; nd=nd->next, ++n)
    force->hashes[n] = (hash_t*)nd->data;

  scheduler_add(sched, task, low);
  fsm->bforce = 0;
}
Exemple #12
0
/*-------------------------------------------------------------------------*/
message_t *fsm_handle_work2(fsm_t *fsm, message_t *msg) {
  ophcrack_t *crack = fsm->crack;
  scheduler_t *sched = crack->sched;
  arg_t *arg = fsm->arg;

  if (msg->kind != msg_done) return msg;

  msg_done_t *done = (msg_done_t*)msg->data;

  if (done->kind == all) {
    // If there are still some hashes to crack and some tables remain,
    // then we continue.

    int npwds_total = crack->npwds_total;
    int npwds_found = crack->npwds_found;

    if (crack->remaining->size > 0 && npwds_found < npwds_total) {
      ophtask_t *task = ophtask_alloc(preload_all);
      scheduler_add(sched, task, disk);

      fsm->state = st_preload;
    }

    // Otherwise, we stop.

    else {
      if (arg->bforce) {
	fsm->bforce_curr  = 1;
	fsm->bforce_total = 1;
      }

      fsm->state = st_wait;
    }
  } 
  
  return msg;
}
int main( int argc, char* argv[] ) {
	// setup COM2/terminal
	bwsetfifo( COM2, OFF );
	
	// setup peripherals and handlers
	kernel_init();

	// Create idle task	
	struct task* idle_task = task_create(&idle_task_entry, PRIORITY_IDLE, -1);
	scheduler_add(idle_task);

	// bootstrap first user task
	struct task* first_task = task_create(&first_task_entry, PRIORITY_HIGHEST, -1);
	scheduler_add(first_task);

	long idleTicks = 0;
	long userTicks = 0;	

	struct task *current_task;
	int request;
	long elapsed;
	
	while (1) {
		current_task = scheduler_get_next();
		if (current_task == 0) {
			break;
		}
		
ACTIVATE:

		// Time the execution of the task
		elapsed = rtc_get_ticks();

		// run the user task
		request = task_activate(current_task);

		elapsed = rtc_get_ticks() - elapsed;

		if (current_task == idle_task) {
			idleTicks += elapsed;
		}
		userTicks += elapsed;
		
		switch (__interrupt_type) {
			case INT_TYPE_HWI:
				// handle the interrupt request and determine if we should preempt the running task
				if (interrupts_handle_irq(current_task) == HWI_CONTINUE && current_task != idle_task) {
					goto ACTIVATE;
				} else {
					scheduler_add(current_task);
				}
				break;
			
			case INT_TYPE_SWI:
				// handle the system call request and determine if we should shutdown
				if (sys_handle_request(current_task, request) == -1) {
					goto shutdown;
				}
				break;
				
			default:
				KASSERT(0, "We got a weird interrupt type... %d", __interrupt_type);
				break;
		}
	}
	
shutdown:
	kernel_shutdown();
	
	// reset the scrolling window, in case it exists!
	bwprintf(COM2, CURSOR_SCROLL, 0, 999);
	bwprintf(COM2, CURSOR_CLEAR_SCREEN);

//	int i;
//	for (i = 0; i < MAX_NUM_TASKS; i++) {
//		task_print(COM2, i);
//	}

	printSensorTicks();

	bwprintf(COM2, "Idle time: %d%%\r\n", ((idleTicks * 100) / userTicks));
	bwprintf(COM2, "Kernel exiting.\r\n");
	return 0;
}
Exemple #14
0
void qlevel_load(STRING *filename)
{
	STRING *file = "#256";
	make_path(file, filename);
	if(!file_exists(file))
	{
		error("FIXIT! qlevel_load: File does not exist!");
		return;
	}
		
	level_load(NULL);
	
	int countEntity = ini_read_int(file, "Level Information", "EntityCount", 0);
	int countLight = ini_read_int(file, "Level Information", "LightCount", 0);
	int countFog = ini_read_int(file, "Level Information", "FogCount", 0);
	
	STRING *section = "#64";
	
	int i;
	char buffer[256];
	STRING *strTemp = "#128";
	for(i = 0; i < countEntity; i++)
	{
		diag("\nLoad :");
		str_cpy(section, "Entity ");
		str_cat(section, str_for_int(NULL, i));
		diag(section);
		
		ini_read_buffer(file, section, "Model", "error.mdl", buffer, 256);
		ENTITY *ent = ent_create(buffer, nullvector, qlevel_entity_init);
		ent->group = GROUP_LEVEL;
		ent->x = ini_read_float(file, section, "X", 0);
		ent->y = ini_read_float(file, section, "Y", 0);
		ent->z = ini_read_float(file, section, "Z", 0);
		
		ent->pan = ini_read_float(file, section, "Pan", 0);
		ent->tilt = ini_read_float(file, section, "Tilt", 0);
		ent->roll = ini_read_float(file, section, "Roll", 0);
		
		ent->scale_x = ini_read_float(file, section, "ScaleX", 0);
		ent->scale_y = ini_read_float(file, section, "ScaleY", 0);
		ent->scale_z = ini_read_float(file, section, "ScaleZ", 0);
		
		ent->lightrange = ini_read_float(file, section, "Lightrange", 0);
		
		int iActionCount = ini_read_int(file, section, "ActionCount", 0);
		int iA = 0;
		STRING *actionName = "#64";
		for(iA = 0; iA < iActionCount; iA++)
		{
			str_cpy(actionName, "Action");
			str_cat(actionName, str_for_int(NULL, iA));
			ini_read_buffer(file, section, actionName, "", buffer, 256);
			str_cpy(strTemp, buffer);
			diag("\nTry adding action '");
			diag(strTemp);
			diag("'...");
			if(actinfo_add(ent->string1, strTemp))
			{
				diag(" SUCCESS!\n\tTry getting function pointer...");
				void *fn = action_getptr(strTemp);
				if(fn != NULL)
				{
					diag(" SUCCESS!");
					scheduler_add(fn, ent);
				}
				else
				{
					diag(" FAILED!");				
				}
			}
			else
			{
				diag(" FAILED!");
			}
		}
		diag("\nEntity loaded!");
	}
}
Exemple #15
0
static void get_note_list(note_list *l, doc *d)
{
  struct {
    int delta;
    alteration_type alter[128];
    alteration_type armature_alter[128];
  } *sl;
  struct {
    int n;
    unsigned long start_time;
    unsigned long end_time;
  } midi[16];
  /* we may have as many silence channels as ncessary */
  struct {
    int on;
    unsigned long start_time;
    unsigned long end_time;
  } *silence = NULL;
  int silence_size = 0;
  int silence_used_size = 0;
  schedule_list s;
  int i, n;
  int line;
  int max;
  unsigned long curtime;
  unsigned long min_advance;
  double duration;

  memset(&s, 0, sizeof(s));
  for (i = 0; i < 16; i++) midi[i].n = -1;

  /* get biggest line size and allocate sl appropriately */
  max = 0;
  for (i = 0; i < d->size; i++) {
    if (d->l[i].n > max) max = d->l[i].n;
  }
  sl = malloc(max * sizeof(*sl)); if (sl == NULL) abort();

  curtime = 0;

  /* feed the scheduler */
  for (line = 0; line < d->size; line++) {
    int it;
    for (i = 0; i < d->l[line].n; i++) {
      /* by default central line is si */
      sl[i].delta = 0;
      memset(&sl[i].alter, 0, sizeof(sl[i].alter));
      memset(&sl[i].armature_alter, 0, sizeof(sl[i].armature_alter));
    }
    for (it = 0; it < d->l[line].size; it++) {
      item *cur = &d->l[line].i[it];
      int k;
      min_advance = ULONG_MAX;
      for (k = 0; k < cur->size; k++) {
        vertical_item *v = &cur->i[k];
        switch (v->t) {
        case CLEF:
          switch (v->clef.t) {
          case CLEF_SOL: sl[v->clef.s].delta = -v->clef.p - 2; break;
          case CLEF_FA: sl[v->clef.s].delta = -v->clef.p - 10; break;
          case CLEF_DO: sl[v->clef.s].delta = -v->clef.p - 6; break;
          }
          break;
        case ARMATURE:
          switch (v->armature.t) {
          default: /* normally you can't come here */ break;
          case DIESE:
          case BEMOL:
          case BECARRE:
            i = pos_to_midi(v->armature.p+sl[v->armature.s].delta) % 12;
            while (i < 128) {
              sl[v->armature.s].alter[i] =
              sl[v->armature.s].armature_alter[i] = v->armature.t;
              i += 12;
            }
            break;
          }
          break;
        case NOTE: {
          int cc;
          double dd;
          int mm, deltamm;
          duration = 4. / (1UL << v->note.duration);
          duration = 60000. / d->tempo * duration;
          /* not fully sure of how to deal with multiple dots */
          for (cc = 0, dd = duration / 2; cc < v->note.dots; cc++, dd /= 2)
            duration += dd;
          mm = pos_to_midi(v->note.p+sl[v->note.s].delta);
          /* deal with alterations */
          /* not sure about DDIESE/BBEMOL, do they imply continuous DIESE/BEMOL
           * or continuous DDIESE/BBEMOL or something else?
           * let's go continuous DIESE/BEMOL
           */
          switch (v->note.alteration) {
          case DDIESE: deltamm = 1; sl[v->note.s].alter[mm] = DIESE; break;
          case DIESE: deltamm = 0; sl[v->note.s].alter[mm] = DIESE; break;
          case BBEMOL: deltamm = -1; sl[v->note.s].alter[mm] = BEMOL; break;
          case BEMOL: deltamm = 0; sl[v->note.s].alter[mm] = BEMOL; break;
          case BECARRE:
            deltamm = 0; sl[v->note.s].alter[mm] = NO_ALTERATION; break;
          case NO_ALTERATION: deltamm = 0; break;
          }
          switch (sl[v->note.s].alter[mm]) {
          case DIESE: mm++; break;
          case BEMOL: mm--; break;
          case NO_ALTERATION: /* nothing */ break;
          default: abort();
          }
          mm += deltamm;
          if (mm < 0) mm = 0; if (mm > 127) mm = 127;
          scheduler_add(&s, mm, curtime, curtime + duration, line, it);
          if (duration < min_advance) min_advance = duration;
          break;
        }
        case SILENCE: {
          /* add a note -1 */
          int cc;
          double dd;
          duration = 4. / (1UL << v->silence.duration);
          duration = 60000. / d->tempo * duration;
          /* not fully sure of how to deal with multiple dots */
          for (cc = 0, dd = duration / 2; cc < v->silence.dots; cc++, dd /= 2)
            duration += dd;
          scheduler_add(&s, -1, curtime, curtime + duration, line, it);
          if (duration < min_advance) min_advance = duration;
          break;
        }
        case BAR:
          for (i = 0; i < d->l[line].n; i++)
            memcpy(&sl[i].alter, &sl[i].armature_alter, sizeof(sl[i].alter));
          break;
        }
      }
      if (min_advance != ULONG_MAX) curtime += min_advance;
    }
  }

  /* sort the scheduler */
  qsort(s.s, s.size, sizeof(s.s[0]), sched_sort);

  /* schedule the 16 midi channels with our notes */
  /* If all 16 channels are full when scheduling a note
   * stop the note that would stop first and take its place.
   * I don't think a more complex scheme is required practically speaking,
   * even if this one is not very good (the shortest note might be a new one
   * that has not even been played yet at all).
   */
  /* 2015-07-19: I think I get it wrong. I think midi can throw more
   * than one note per channel.
   * Anyway, I'll keep the thing as it is, no big deal.
   */
  n = 0;
  curtime = 0;
  while (1) {
    unsigned long nexttime = ULONG_MAX;

    /* schedule note off */
    for (i = 0; i < 16; i++)
      if (midi[i].n != -1 && midi[i].end_time == curtime) {
        add_note_elem(l, (note_elem){ t:NOTE_OFF, port:i, note:midi[i].n });
        midi[i].n = -1;
      }
Exemple #16
0
Item *every(List *expression)
{
    scheduler_add(eval_as_uint16(second(expression)),store_expression(rest(rest(expression))));
    return 0;
}