Subversion Repositories shark

Rev

Blame | Last modification | View Log | RSS feed

#include <ctype.h>
#include "hlpdemo.h"

extern taskconf_list_t *taskconf;
extern mutex_list_t *mutexes;

typedef enum { TT_TASK = 0,
               TT_EVERY = 1,
               TT_RUNS = 2,
               TT_LOCKS = 3,
               TT_UNLOCKS = 4,
               TT_ID,
               TT_INT,
               TT_INVALID = -1 } keyword_t;

/* multitype value management */
typedef struct value_struct {
  int type; /* -1 invalid, 0 int, 1 string, 2 token, 3 eof */
  int intval;
  char *strval;
  keyword_t keyword;
} value_t;

value_t *invalid_value (int type)
{
  value_t *new;
  new = (value_t *) kern_alloc(sizeof(value_t));
  new->type = type;
  new->intval = -1;
  new->strval = NULL;
  new->keyword = TT_INVALID;
  return new;
}

char *strdup(char *str)
{
  char *ret;
 
  ret = (char *)kern_alloc((strlen(str) + 1) * sizeof(char));
  strncpy(ret, str, strlen(str));
  ret[strlen(str)] = '\0';
 
  return ret;
}

value_t *keyword_value (char *token)
{
  int i;
  value_t *new = NULL;
  char *type_assoc[] = { "task",
                         "every",
                         "runs",
                         "locks",
                         "unlocks",
                        NULL};
  for (i=0; type_assoc[i] != NULL ; i++)
    {
      if (strcmp(token, type_assoc[i]) == 0)
        {
          new = (value_t *)kern_alloc(sizeof(value_t));
          new->type = 2;
          new->intval = -1;
          new->strval = strdup(token);
          new->keyword = (keyword_t)i;
        }
    }
  return new;
}  

value_t *int_value (int n)
{
  value_t *new;
  new = (value_t *) kern_alloc(sizeof(value_t));
  new->type = 0;
  new->intval = n;
  new->strval = NULL;
  new->keyword = TT_INT;
  return new;
}

value_t *str_value (char *str)
{
  value_t *new;
  new = (value_t *) kern_alloc(sizeof(value_t));
  new->type = 1;
  new->intval = -1;
  new->strval = strdup(str);
  new->keyword = TT_ID;
  return new;
}

void dprint(char *str)
{
#ifdef DEBUG
  if (str)
    cprintf("%s\n", str);
#endif
}

void dprint_value(value_t *val)
{
#ifdef DEBUG
  switch (val->type) {
  case 0:
    cprintf("Value is an integer: %d\n", val->intval);
    break;
  case 1:
    cprintf("Value is a string: '%s'\n", val->strval);
    break;
  case 2:
    cprintf("Value is a keyword: %d\n", (int)val->keyword);
    break;
  case 3:
    cprintf("Value is an eof terminator\n");
    break;
  }
#endif
}

int intlen(int val)
{
  int ret = 1;
 
  while ( (val = val / 10) >= 1) ret++;
 
  return ret;
}

/*
   @desc Tokenizza uno stream, riconoscendo interi, identificatori e
   token del linguaggio. Ad ogni chiamata restituisce il prossimo
   token.
   @return il prossimo token come multitype value (esistono i value di errore)
*/

value_t *get_token_from_str (char *stream, unsigned int size)
{
  int c, intval;
  static int pos = 0;

  /* Ignore white space, get first nonwhite character.  */
  while ((c = stream[pos++]) == ' ' || c == '\t' || c == '\n');
 
  if (c == EOF || c == '\0' || pos == size - 1)
    return invalid_value(3);
 
  /* Char starts a number => parse the number.         */
  if (c == '.' || isdigit (c))
    {
      pos--;
      sscanf (&stream[pos], "%d", &intval);
      pos += intlen(intval);
      return int_value(intval);
    }
     
  /* Char starts an identifier => read the name.       */
  if (isalpha (c))
    {
      value_t *keyword_val;
      static char *symbuf = 0;
      static int length = 0;
      int i;
     
      /* Initially make the buffer long enough
         for a 40-character symbol name.  */

      if (length == 0)
        length = 40, symbuf = (char *)kern_alloc (length + 1);
     
      i = 0;
      do
        {
          /* If buffer is full, make it bigger.        */
          if (i == length)
            {
              length *= 2;
              symbuf = (char *) realloc (symbuf, length + 1);
            }
          /* Add this character to the buffer.         */
          symbuf[i++] = c;
          /* Get another character.                    */
          c = stream[pos++];
        }
      while (isalnum (c));
     
      pos--;
      symbuf[i] = '\0';
     
      keyword_val = keyword_value(symbuf);

      if (keyword_val->type == 2)
        {
          dprint("found a keyword");
          return keyword_val;
        }
      else
        {
          dprint("found an identifier");
          return str_value(symbuf);
        }
    }
     
  /* Any other character is a token by itself.        */
#ifdef DEBUG
  cprintf("Invalid Token: '%c'\n", c);
#endif
  return invalid_value(-1);
}


/*
   @desc Ricerca un mutex di un dato nome in una mutex_list_t
   @return il mutex trovato o NULL in caso di mutex non trovato
*/

mutex_list_t *in_mutex_list(char *needle, mutex_list_t *list)
{
  while (list)
    {
      if (!strcmp(needle, list->name))
        break;
      list = list->next;
    }

  return list;
}

/* @return Calcola il wcet sommando tutte le azioni di load */
DWORD calc_wcet(taskconf_list_t *task)
{
  action_list_t *scan = task->actionlist;
  DWORD wcet = 0;

  while(scan)
    {
      wcet += (scan->type == LOAD ? scan->time : 0);
      scan = scan->next;
    }

  return wcet;
}

/*
   @desc Legge la configurazione dal buffer esterno myfilebuf
         Riempie la struttura dati esterna taskconf
   @return 0  ok
           -1 errore nel parsing
*/

int read_conf(char *stream, unsigned int size)
{
  value_t *tmpval, *curval = get_token_from_str(stream, size);
  taskconf_list_t *tcnew, *tccur = taskconf;
  action_list_t *acnew, *accur = NULL;
  mutex_list_t *mutnew, *mutcur = NULL;
  TIME seme;

  dprint(stream);

  while (curval->type != 3) /* until eof */
    {
      switch (curval->keyword)
        {
        case TT_TASK: /* create new task */
          tmpval = get_token_from_str(stream, size);  /* get the name */

          if (tmpval->type != 1) {
            dprint("No name after task");
            return -1;
          }

          /* alloc mem and set default data */
          tcnew = (taskconf_list_t *)kern_alloc((sizeof(taskconf_list_t)));
          tcnew->name = strdup(tmpval->strval);
          tcnew->period = -1;
          tcnew->wcet = 0;
          tcnew->next = NULL;
          tcnew->mutexlist = NULL;
          tcnew->actionlist = NULL;
         
          /* reset current mutex and current action */
          mutcur = NULL;
          accur = NULL;
         
          /* fill the first taskconf */
          if (taskconf == NULL)
            taskconf = tcnew;

          if (tccur != NULL)
            tccur->next = tcnew;

          tccur = tcnew;

          break;

        case TT_EVERY:
          tmpval = get_token_from_str(stream, size);
          if (tmpval->type != 0) {
            dprint("No period after every");
            return -1;
          }
          tccur->period = tmpval->intval;
          break;

        case TT_RUNS:
          /* making new action */
          tmpval = get_token_from_str(stream, size);
          if (tmpval->type != 0) {
            dprint("No period after runs");
            return -1;
          }
         
          acnew = (action_list_t *)kern_alloc((sizeof(action_list_t)));
          acnew->type = LOAD;
          acnew->time = tmpval->intval;
          acnew->next = NULL;
          acnew->mutex = NULL;

          if (tccur->actionlist == NULL)
            tccur->actionlist = acnew;
          else
            accur->next = acnew;

          accur = acnew;

          /* calculate wcet for the former task */
          if (tccur != NULL)
          {
            /* calc the wcet */
            tccur->wcet = calc_wcet(tccur);
          }

          break;

        case TT_LOCKS:

          tmpval = get_token_from_str(stream, size);

          if (tmpval->type != 1)
            return -1;

          acnew = (action_list_t *)kern_alloc(sizeof(action_list_t));
          acnew->type = LOCK;
          acnew->time = -1;
          acnew->next = NULL;

          /* create new mutex if does not exist*/
          if ( !(mutnew = in_mutex_list(tmpval->strval, mutexes)))
            {
              mutnew = (mutex_list_t *)kern_alloc(sizeof(mutex_list_t));
              mutnew->name = strdup(tmpval->strval);
             
              seme = sys_gettime(NULL);
              srand(seme);
              mutnew->color = rgb16(rand() % 255,
                                    rand() % 255,
                                    rand() % 255);
              mutnew->next = NULL;
             
              /* adding to mutexes */
              if (mutexes == NULL)
                mutexes = mutnew;
              else
                mutexes->next = mutnew;
            }
          acnew->mutex = mutnew;
         
          /* add mutex to the list of tasks using it */
          if (tccur->mutexlist == NULL)
            {
              tccur->mutexlist = mutnew;
            }
          else
            {
              if (in_mutex_list(tmpval->strval, tccur->mutexlist))
                mutcur->next = mutnew;
            }

          mutcur = mutnew;

          /* updating action list */
          if (tccur->actionlist == NULL)
            tccur->actionlist = acnew;
          else
            accur->next = acnew;

          accur = acnew;
          break;

        case TT_UNLOCKS:

          tmpval = get_token_from_str(stream, size);
          if (tmpval->type != 1)
            return -1;

          acnew = (action_list_t *)kern_alloc((sizeof(action_list_t)));
          acnew->type = UNLOCK;
          acnew->time = -1;
          acnew->next = NULL;

          if ( (mutnew = in_mutex_list(tmpval->strval, tccur->mutexlist)) == NULL)
            {
#ifdef DEBUG
              cprintf("Mutex %s unlocked but never locked\n", tmpval->strval);
#endif       
            return -1;
            }

          acnew->mutex = mutnew;

          if (tccur->actionlist == NULL)
            tccur->actionlist = acnew;
          else
            accur->next = acnew;

          accur = acnew;
          break;

        case TT_ID:
          dprint_value(curval);
          break;
         
        case TT_INT:
          dprint_value(curval);
          break;

        case TT_INVALID:
          break;
        }
      curval = get_token_from_str(stream, size);
    }
  return 0;
}

void print_taskconf(taskconf_list_t *tc)
{
  action_list_t *action;
  mutex_list_t *mutex;

  if (tc == NULL)
    return;

  cprintf("Task: %s, period %ld, wcet %ld\n", tc->name, tc->period, tc->wcet);
  cprintf("Actions:\n");

  action = tc->actionlist;

  while (action)
    {
      cprintf("---Type %d, time %d, mutex %s\n", action->type, action->time, (action->mutex == NULL ? "" : action->mutex->name));
      action = action->next;
    }
 
  cprintf("Mutex used:\n");
  mutex = tc->mutexlist;

  while (mutex)
    {
      cprintf("---Name %s, Color %d\n", mutex->name, mutex->color);
      mutex = mutex->next;
    }

  print_taskconf(tc->next);
}