Beispiel #1
0
int
main (int argc, char **argv)
{
  // Set exit routines
  atexit (GC_gcollect);
  atexit (close_libs);
  atexit (thread_cleanup);

  // Start the garbage collector
  GC_INIT ();

  // Set up GMP library
  mp_set_memory_functions (&FACT_malloc,
			   &gmp_realloc_wrapper,
			   &gmp_free_wrapper);

  // Start the main thread
  root_thread = FACT_malloc (sizeof (FACT_thread_t));
  root_thread->tid = pthread_self ();
  root_thread->exited  = false;
  root_thread->destroy = false;
  root_thread->next = NULL;
  root_thread->prev = NULL;
  root_thread->root = NULL;
  root_thread->nid  = 0;
  pthread_mutex_init (&root_thread->queue_lock, NULL);

  // Process the arguments and start the interpreter.
  process_args (argc, argv);

  // Exit.
  exit (0);
}
Beispiel #2
0
void FACT_send_message (FACT_num_t msg, size_t dest) /* Add a message to a thread's queue. */
{
  FACT_thread_t curr;
  struct FACT_thread_queue *last;

  /* Find the thread number "dest". If it doesn't exist or is dead,
   * throw an error.
   */
  for (curr = threads; curr != NULL; curr = curr->next) {
    if (curr->thread_num == dest)
      goto found_thread;
  }
  /* The thread does not exist, throw an error. */
  FACT_throw_error (CURR_THIS, "no thread number %zu exists", dest);

 found_thread: /* We've found the thread. */
  if (curr->run_flag == T_DEAD) /* The thread has terminated, throw an error. */
    FACT_throw_error (CURR_THIS, "thread number %zu is dead", dest);

  /* Gain control of the message queue and add the message. */
  pthread_mutex_lock (&curr->queue_lock);

  if (curr->root_message == NULL) {
    /* Add the root message. */
    curr->root_message = FACT_malloc (sizeof (struct FACT_thread_queue));
    curr->root_message->sender_id = curr_thread->thread_num;
    curr->root_message->msg = FACT_alloc_num ();
    curr->root_message->next = NULL;
    FACT_set_num (curr->root_message->msg, msg);
    pthread_cond_broadcast(&curr->msg_block);
  } else {
    /* Find the next open spot in the linked list. */
    for (last = curr->root_message; last->next != NULL; last = last->next)
      ;
    last->next = FACT_malloc (sizeof (struct FACT_thread_queue));
    last = last->next;
    last->sender_id = curr_thread->thread_num;
    last->msg = FACT_alloc_num ();
    FACT_set_num (last->msg, msg);
  }

  curr->num_messages++;  
  pthread_mutex_unlock (&curr->queue_lock);
}
Beispiel #3
0
FACT_t
sprout (func_t * scope, syn_tree_t expression)
{
  /**
   * sprout - Create a new thread and manage the threads structure. 
   * returns the id of the thread created.
   */
  syn_tree_t    *arg;
  FACT_thread_t *curr;
  FACT_thread_t *temp;

  static pthread_mutex_t list_lock = PTHREAD_MUTEX_INITIALIZER;
    
  expression.syntax += get_ip ();
  arg = better_malloc (sizeof (syn_tree_t));
  *arg = expression;

  // Wait until we have control of the list
  while (pthread_mutex_trylock (&list_lock) == EBUSY); // Do nothing
  
  for (curr = root_thread; curr->next != NULL; curr = curr->next)
    {
      if (curr->exited && curr->destroy)
        break;
    }

  if (curr->exited && curr->destroy)
    {
      // Use a pre-existing thread.
      curr->ip = 0;
      curr->exited = false;
      curr->destroy = false;
      curr->root = NULL;
    }
  else
    {
      // Allocate memory for a new thread.
      temp = FACT_malloc (sizeof (FACT_thread_t));
      pthread_mutex_init (&temp->queue_lock, NULL);
      temp->ip = 0;
      temp->nid = curr->nid + 1;
      temp->exited = false;
      temp->destroy = false;
      temp->root = NULL;
      temp->next = NULL;
      temp->prev = curr;
      curr->next = temp;
      curr = curr->next;
    }

  pthread_create (&(curr->tid), NULL, thread_wrapper, (void *) arg);
  pthread_mutex_unlock (&list_lock);
  return FACT_get_ui (curr->nid);
}
Beispiel #4
0
bool
check (char **input, const char *f_name, int start_line, int *lines)
{
  /**
   * check - check for errors potentially harmful to the parser, and
   * print them out. Among other things, this function checks for
   * incompletions.
   */
  
  int i, j;
  int prec;
  int state;
  int s_size;
  int p_hold;
  int p_count, b_count, c_count;

  char *custom_fmt;
  char *next_token;
  char *prev_token;
  bool *com_stack, *def_stack, *semi_stack;

#define STACK_REALLOC() com_stack = FACT_realloc (com_stack, sizeof (bool) * (s_size + 1)); \
  def_stack = FACT_realloc (def_stack, sizeof (bool) * (s_size + 1));   \
  semi_stack = FACT_realloc (semi_stack, sizeof (bool) * (s_size + 1))

  // Possible values of state
#define START 0
#define OP    1
#define VAR   2

  com_stack = FACT_malloc (sizeof (bool));
  def_stack = FACT_malloc (sizeof (bool));
  semi_stack = FACT_malloc (sizeof (bool));

  prev_token = NULL;
  state = START;

  s_size = 1;
  semi_stack[s_size - 1] = true;
  com_stack[s_size - 1] = def_stack[s_size - 1] = false;
  p_count = b_count = c_count = 0;

  for (i = 0; input[i] != NULL; i++)
    {
      next_token = input[i + 1];

      if (def_stack[s_size - 1])
        {
          if (op_get_prec (input[i]) == -1)
            {
              if (isnum (input[i]))
                {
                  custom_fmt = "cannot define, %s is a number";
                  goto custom_error;
                }
              s_size--;
              STACK_REALLOC ();
              com_stack[s_size] = def_stack[s_size] = semi_stack[s_size] = false;
              state = VAR;
              continue;
            }
          if (strcmp (input[i], "["))
            goto error;
        }
          
      if (!strcmp (input[i], "("))
        {
          if (prev_token != NULL && (!strcmp (prev_token, "$")
                                     || !strcmp (prev_token, "&")))
            {
              state = OP;
              STACK_REALLOC ();
              com_stack[s_size] = true;
              def_stack[s_size] = semi_stack[s_size] = false;
              s_size++;
            }
          else
            {
              if (state == VAR && (prev_token != NULL && strcmp (prev_token, "}")))
                goto error;
              state = OP;
              STACK_REALLOC ();
              com_stack[s_size] = def_stack[s_size] = semi_stack[s_size] = false;
              s_size++;
            }
          p_count++;
        }
      else if (input[i][0] == ')')
        {
          s_size--;
          STACK_REALLOC ();
          com_stack[s_size] = def_stack[s_size] = semi_stack[s_size] = false;

          if ((input[i][1] != ')' && state == OP)
              || (state != VAR && (prev_token == NULL || strcmp (prev_token, "("))))
            goto error;
          if (input[i][1] != '\0')
            {
              state = START;
              if (input[i][1] == ')')
                input[i] = ")";
            }
          if (--p_count < 0)
            {
              custom_fmt = "mismatched %s";
              goto custom_error;
            }
        }
      else if (!strcmp (input[i], "["))
        {
          if (state != VAR)
            {
              STACK_REALLOC ();
              com_stack[s_size] = true;
              def_stack[s_size] = semi_stack[s_size] = false;
              s_size++;
              input[i] = "![";
            }
          else
            {
              STACK_REALLOC ();
              com_stack[s_size] = def_stack[s_size] = semi_stack[s_size] = false;
              s_size++;
            }
          b_count++;
          state = OP;
        }
      else if (!strcmp (input[i], "]"))
        {
          if (state != VAR)
            goto error;
          if (--b_count < 0)
            {
              custom_fmt = "mismatched %s";
              goto custom_error;
            }
          s_size--;
          STACK_REALLOC ();
          com_stack[s_size] = def_stack[s_size] = semi_stack[s_size] = false;
        }
      else if (!strcmp (input[i], "{"))
        {
          if (state == VAR && (prev_token != NULL && strcmp (prev_token, "}")))
            goto error;
          state = START;
          STACK_REALLOC ();
          semi_stack[s_size] = true;
          com_stack[s_size] = def_stack[s_size] = false;
          s_size++;
          c_count++;
        }
      else if (!strcmp (input[i], "}"))
        {
          if (--c_count < 0)
            {
              custom_fmt = "mismatched %s";
              goto custom_error;
            }
          if (prev_token == NULL || (strcmp (prev_token, ";") && strcmp (prev_token, "}")))
            {
              custom_fmt = "expected ';' before %s";
              goto custom_error;
            }
          s_size--;
          STACK_REALLOC ();
          com_stack[s_size] = def_stack[s_size] = semi_stack[s_size] = false;
          state = VAR;
        }
      else if (!strcmp (input[i], "$") || !strcmp (input[i], "&"))
        {
          if (state == VAR && (prev_token != NULL && strcmp (prev_token, "}")))
            {
              if (!strcmp (input[i], "&"))
                {
                  input[i] = "&!";
                  state = OP;
                }
              else
                goto error;
            }
          else if (strcmp (next_token, "("))
            {
              custom_fmt = "expected '(' after %s";
              goto custom_error;
            }
        }
      else if (!strcmp (input[i], ","))
        {
          if (!com_stack[s_size - 1] || state != VAR)
            goto error;
          state = OP;
        }
      else if (!strcmp (input[i], ";"))
        {
          if (!semi_stack[s_size - 1] || state != VAR)
            goto error;
          state = START;
        }
      else if (!strcmp (input[i], "@"))
        {
          if (state != VAR || next_token == NULL || strcmp (next_token, "("))
            goto error;
          p_hold = p_count + 1;
          p_count = 1;
          for (j = i + 2; p_count > 0; j++)
            {
              if (input[j] == NULL)
                {
                  custom_fmt = "expected '( exp )' after %s";
                  goto custom_error;
                }
              if (!strcmp (input[j], "("))
                p_count++;
              else if (!strcmp (input[j], ")"))
                p_count--;
            }
          p_count = p_hold;
          if (input[j] == NULL || strcmp (input[j], "{"))
            {
              custom_fmt = "expected '{' after %s";
              goto custom_error;
            }
          input[j - 1] = "))";
          i++;
          state = OP;
          STACK_REALLOC ();
          com_stack[s_size] = true;
          def_stack[s_size] = semi_stack[s_size] = false;
          s_size++;
        }
      else if (!strcmp (input[i], "if") || !strcmp (input[i], "while")
               || !strcmp (input[i], "error"))
        {
          // Todo: check for correct/incorrect break placements in while.
          if (state != START && (prev_token != NULL && strcmp (prev_token, "}")))
            goto error;
          if (next_token == NULL || strcmp (next_token, "("))
            {
              custom_fmt = "expected '(' after %s";
              goto custom_error;
            }
          p_hold = p_count + 1;
          p_count = 1;
          for (j = i + 2; p_count > 0; j++)
            {
              if (input[j] == NULL)
                {
                  custom_fmt = "expected '( exp )' after %s";
                  goto custom_error;
                }
              if (!strcmp (input[j], "("))
                p_count++;
              else if (!strcmp (input[j], ")"))
                p_count--;
            }
          input[j - 1] = ")!";
          state = OP;
        }
      else if (!strcmp (input[i], "for"))
        {
          if (state != START && (prev_token != NULL && strcmp (prev_token, "}")))
            goto error;
          STACK_REALLOC ();
          com_stack[s_size] = true;
          def_stack[s_size] = semi_stack[s_size] = false;
          s_size++;
          state = OP;
        }
      else if (!strcmp (input[i], "then"))
        {
          if (state != VAR)
            goto error;
          s_size--;
          STACK_REALLOC ();
          com_stack[s_size] = def_stack[s_size] = semi_stack[s_size] = false;
          state = START;
        }
      else if (!strcmp (input[i], "def") || !strcmp (input[i], "defunc"))
        {
          if (state == VAR && (prev_token != NULL && strcmp (prev_token, "}")))
            goto error;
          state = VAR;
          STACK_REALLOC ();
          def_stack[s_size] = true;
          com_stack[s_size] = semi_stack[s_size] = false;
          s_size++;
        }
      else if (!strcmp (input[i], "sprout"))
        {
          if (state == VAR && (prev_token != NULL && strcmp (prev_token, "}")))
            goto error;
          state = START;
        }
      else if (!strcmp (input[i], "return") || !strcmp (input[i], "give"))
        {
          if (state != START && (prev_token != NULL && strcmp (prev_token, "}")))
            goto error;
          if (next_token == NULL || !strcmp (next_token, ";"))
            {
              custom_fmt = "%s cannot be alone in an expression.";
              goto custom_error;
            }
          state = OP;
        }
      else if (!strcmp (input[i], "else"))
        {
          if (state != START && (prev_token != NULL && strcmp (prev_token, "}")))
            goto error;
          state = START;
        }
      else if ((prec = op_get_prec (input[i])) <= 14 && prec >= 1 && prec != 3)
        {
          // If we've hit an operator
          if (state != VAR)
            {
              if (!strcmp (input[i], "-")
                  && (prev_token == NULL || strcmp (prev_token, "--")))
                input[i] = "--";
              else if (!strcmp (input[i], "~")
                       && (prev_token == NULL || strcmp (prev_token, "~!")))
                input[i] = "~!";
              else
                goto error;
            }
          state = OP;
        }
      else if (!strcmp (input[i], "\""))
        {
          // Skip quotes.
          if (state == VAR && (prev_token != NULL && strcmp (prev_token, "}")))
            goto error;
          state = VAR;
          i += 2;
        }
      else
        {
          // We've hit a variable.
          if (state == VAR && (prev_token != NULL && strcmp (prev_token, "}")))
            goto error;
          state = VAR;
        }          
      prev_token = input[i];
    }

  if (p_count)
    {
      custom_fmt = "unmatched '('";
      goto custom_error;
    }
  else if (b_count)
    {
      custom_fmt = "unmatched '['";
      goto custom_error;
    }
  else if (c_count)
    {
      custom_fmt = "unmatched '{'";
      goto custom_error;
    }

  FACT_free (com_stack);
  FACT_free (def_stack);
  FACT_free (semi_stack);
  return false;

 error:
  custom_fmt = "unexpected %s";
 custom_error:
  // Get the line number of the error.
  for (j = i; j >= 0; j--)
    start_line += lines[j];

  // Print the error.
  fprintf (stderr, "E> Parsing error in (%s) on line %d: ",  f_name, start_line);
  fprintf (stderr, custom_fmt, input[i]);
  fprintf (stderr, "\n");

  // Free the stacks.
  FACT_free (com_stack);
  FACT_free (def_stack);
  FACT_free (semi_stack);
  return true;
}