void repl() { char str[FG_MAX_INPUT]; struct context *context = context_new(NULL, true, true); for (;;) { fflush(stdin); str[0] = 0; printf("f> "); if (!fgets(str, FG_MAX_INPUT, stdin)) { if (feof(stdin)) return; if (ferror(stdin)) { printf("unknown error reading stdin\n"); return; } } struct byte_array *input = byte_array_from_string(str); struct byte_array *program = build_string(input, NULL); if (!setjmp(trying)) { run(context, program, NULL, true); } byte_array_del(input); byte_array_del(program); } }
bool custom_method(struct context *context, const char *method, struct variable *indexable, struct variable *index, struct variable *value) { struct variable *custom; struct byte_array *key = byte_array_from_string(method); if (indexable->map && (custom = (struct variable*)map_get(indexable->map, key))) { DEBUGPRINT("\n"); vm_call(context, custom, indexable, index, value, NULL); return true; } return false; }
struct variable *sys_send(struct context *context) { struct variable *arguments = (struct variable*)stack_pop(context->operand_stack); struct variable *sender = (struct variable*)array_get(arguments->list, 1); const char *message = param_str(arguments, 2); assert_message(sender->type == VAR_INT, "non int fd"); int32_t fd = sender->integer; struct thread_argument *ta = (struct thread_argument*)map_get(socket_listeners, (void*)(VOID_INT)fd); printf("send on ssl=%p\n", ta->ssl); if (CyaSSL_write(ta->ssl, message, strlen(message)) != strlen(message)) context->vm_exception = variable_new_str(context, byte_array_from_string("CyaSSL_write error")); return NULL; }
void vm_call_src(struct context *context, struct variable *func) { struct map *env = NULL; if (func->map) { struct variable *v = (struct variable*)variable_map_get(context, func, byte_array_from_string(RESERVED_ENV)); if (v) env = v->map; } struct program_state *state = (struct program_state*)stack_peek(context->program_stack, 0); struct variable *s = (struct variable*)stack_peek(context->operand_stack, 0); state->args = array_copy(s->list); INDENT // call the function switch (func->type) { case VAR_FNC: run(context, func->str, env, false); break; case VAR_C: { struct variable *v = func->cfnc(context); if (!v) v = variable_new_src(context, 0); else if (v->type != VAR_SRC) { // convert to VAR_SRC variable stack_push(context->operand_stack, v); v = variable_new_src(context, 1); } stack_push(context->operand_stack, v); // push the result } break; case VAR_NIL: vm_exit_message(context, "can't find function"); break; default: vm_exit_message(context, "not a function"); break; } state->args = NULL; UNDENT }
int main (int argc, char** argv) { struct sigaction act, oact; // for handling ctrl-c act.sa_handler = sig_handler; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGINT, &act, &oact); if (1 == argc) { repl(); } else { struct byte_array *args = arg2ba(argc, argv); struct byte_array *path = byte_array_from_string(argv[1]); interpret_file(path, args); if (NULL != args) { byte_array_del(args); } byte_array_del(path); } }
static struct variable *list_get_int(struct context *context, const struct variable *indexable, uint32_t index) { null_check(indexable); enum VarType it = (enum VarType)indexable->type; switch (it) { case VAR_INT: return variable_new_int(context, index); case VAR_LST: if (index < indexable->list->length) return (struct variable*)array_get(indexable->list, index); return variable_new_nil(context); case VAR_STR: { vm_assert(context, index < indexable->str->length, "index out of bounds"); char *str = (char*)malloc(2); sprintf(str, "%c", indexable->str->data[index]); return variable_new_str(context, byte_array_from_string(str)); } default: vm_exit_message(context, "indexing non-indexable"); return NULL; } }
struct byte_array *arg2ba(int argc, char **argv) { if (argc < 3) { return NULL; } return byte_array_from_string(argv[2]); }
struct variable *sys_connect(struct context *context) { struct variable *arguments = (struct variable*)stack_pop(context->operand_stack); const char *serveraddr = param_str(arguments, 1); const int32_t serverport = param_int(arguments, 2); struct variable *listener = ((struct variable*)array_get(arguments->list, 2)); int sockfd; struct sockaddr_in servaddr; CYASSL_CTX* ctx; CYASSL* ssl; node_init(); // Create and initialize CYASSL_CTX structure if ( (ctx = CyaSSL_CTX_new(CyaTLSv1_client_method())) == NULL) { context->vm_exception = variable_new_str(context, byte_array_from_string("SSL_CTX_new error")); CyaSSL_Cleanup(); return NULL; } // Load CA certificates into CYASSL_CTX if (CyaSSL_CTX_load_verify_locations(ctx, "./conf/ca-cert.pem", 0) != SSL_SUCCESS) { context->vm_exception = variable_new_str(context, byte_array_from_string("Error loading ca-cert.pem, please check the file.\n")); CyaSSL_CTX_free(ctx); CyaSSL_Cleanup(); return NULL; } // Create Socket file descriptor sockfd = socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(serverport); inet_pton(AF_INET, serveraddr, &servaddr.sin_addr); // Blocking Connect to socket file descriptor connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)); // Create CYASSL object if ((ssl = CyaSSL_new(ctx)) == NULL) { context->vm_exception = variable_new_str(context, byte_array_from_string("CyaSSL_new error")); CyaSSL_CTX_free(ctx); CyaSSL_Cleanup(); return NULL; } CyaSSL_set_fd(ssl, sockfd); fprintf(stderr, "Connected on %d -- %p\n", sockfd, ssl); struct thread_argument *ta = (struct thread_argument *)malloc(sizeof(struct thread_argument)); ta->find = context->find; ta->listener = listener; ta->ssl = ssl; ta->fd = sockfd; ta->cya = ctx; if (socket_listeners == NULL) socket_listeners = map_new_ex(NULL, &int_compare, &int_hash, &int_copy, &int_del); map_insert(socket_listeners, (void*)(VOID_INT)sockfd, (void*)(VOID_INT)ta); return variable_new_int(context, sockfd); }