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); }
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); }
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); }
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; }