Пример #1
0
JSValueRef function_raw_read_stdin(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject,
                                   size_t argc, const JSValueRef args[], JSValueRef *exception) {
    char buf[1024 + 1];

    size_t n = fread(buf, 1, config.is_tty ? 1 : 1024, stdin);
    if (n > 0) {
        buf[n] = '\0';
        return c_string_to_value(ctx, buf);
    }

    return JSValueMakeNull(ctx);
}
Пример #2
0
JSValueRef function_list_files(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject,
                               size_t argc, const JSValueRef args[], JSValueRef *exception) {
    if (argc == 1
        && JSValueGetType(ctx, args[0]) == kJSTypeString) {

        char *path = value_to_c_string(ctx, args[0]);

        size_t capacity = 32;
        size_t count = 0;
        JSValueRef *paths = malloc(capacity * sizeof(paths));

        DIR *d;
        struct dirent *dir;
        d = opendir(path);

        size_t path_len = strlen(path);
        if (path_len && path[path_len - 1] == '/') {
            path[--path_len] = 0;
        }

        if (d) {
            while ((dir = readdir(d)) != NULL) {
                if (strcmp(dir->d_name, ".") && strcmp(dir->d_name, "..")) {

                    char *buf = malloc((path_len + strlen(dir->d_name) + 2));
                    sprintf(buf, "%s/%s", path, dir->d_name);
                    paths[count++] = c_string_to_value(ctx, buf);
                    free(buf);

                    if (count == capacity) {
                        capacity *= 2;
                        paths = realloc(paths, capacity * sizeof(paths));
                    }
                }
            }

            closedir(d);
        }

        free(path);

        JSValueRef rv = JSObjectMakeArray(ctx, count, paths, NULL);
        free(paths);

        return rv;
    }
    return JSValueMakeNull(ctx);
}
Пример #3
0
JSValueRef function_file_input_stream_open(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject,
                                           size_t argc, const JSValueRef args[], JSValueRef *exception) {
    if (argc == 1
        && JSValueGetType(ctx, args[0]) == kJSTypeString) {

        char *path = value_to_c_string(ctx, args[0]);

        uint64_t descriptor = file_open_read(path);

        free(path);

        char *descriptor_str = descriptor_int_to_str(descriptor);
        JSValueRef rv = c_string_to_value(ctx, descriptor_str);
        free(descriptor_str);

        return rv;
    }

    return JSValueMakeNull(ctx);
}
Пример #4
0
JSValueRef function_read_password(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject,
                                  size_t argc, const JSValueRef args[], JSValueRef *exception) {
    if (argc == 1
        && JSValueGetType(ctx, args[0]) == kJSTypeString) {

        char *prompt = value_to_c_string(ctx, args[0]);

        char *pass = getpass(prompt);

        JSValueRef rv;

        if (pass) {
            rv = c_string_to_value(ctx, pass);
            memset(pass, 0, strlen(pass));
        } else {
            rv = JSValueMakeNull(ctx);
        }

        free(prompt);
        return rv;
    }
    return JSValueMakeNull(ctx);
}
Пример #5
0
JSValueRef function_file_writer_open(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject,
                                     size_t argc, const JSValueRef args[], JSValueRef *exception) {
    if (argc == 3
        && JSValueGetType(ctx, args[0]) == kJSTypeString
        && JSValueGetType(ctx, args[1]) == kJSTypeBoolean) {

        char *path = value_to_c_string(ctx, args[0]);
        bool append = JSValueToBoolean(ctx, args[1]);
        char *encoding = value_to_c_string(ctx, args[2]);

        uint64_t descriptor = ufile_open_write(path, append, encoding);

        free(path);
        free(encoding);

        char *descriptor_str = descriptor_int_to_str(descriptor);
        JSValueRef rv = c_string_to_value(ctx, descriptor_str);
        free(descriptor_str);

        return rv;
    }

    return JSValueMakeNull(ctx);
}
Пример #6
0
JSValueRef timeout_data_to_js_value(JSContextRef ctx, struct timeout_data_t *timeout_data) {
    char *id_str = timeout_id_to_str(timeout_data->id);
    JSValueRef rv = c_string_to_value(ctx, id_str);
    free(id_str);
    return rv;
}
Пример #7
0
JSValueRef function_fstat(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject,
                          size_t argc, const JSValueRef args[], JSValueRef *exception) {
    if (argc == 1
        && JSValueGetType(ctx, args[0]) == kJSTypeString) {

        char *path = value_to_c_string(ctx, args[0]);

        struct stat file_stat;

        int retval = lstat(path, &file_stat);

        if (retval == 0) {
            JSObjectRef result = JSObjectMake(ctx, NULL, NULL);

            char *type = "unknown";
            if (S_ISDIR(file_stat.st_mode)) {
                type = "directory";
            } else if (S_ISREG(file_stat.st_mode)) {
                type = "file";
            } else if (S_ISLNK(file_stat.st_mode)) {
                type = "symbolic-link";
            } else if (S_ISSOCK(file_stat.st_mode)) {
                type = "socket";
            } else if (S_ISFIFO(file_stat.st_mode)) {
                type = "fifo";
            } else if (S_ISCHR(file_stat.st_mode)) {
                type = "character-special";
            } else if (S_ISBLK(file_stat.st_mode)) {
                type = "block-special";
            }

            JSObjectSetProperty(ctx, result, JSStringCreateWithUTF8CString("type"),
                                c_string_to_value(ctx, type),
                                kJSPropertyAttributeReadOnly, NULL);


            double device_id = (double) file_stat.st_rdev;
            if (device_id) {
                JSObjectSetProperty(ctx, result, JSStringCreateWithUTF8CString("device-id"),
                                    JSValueMakeNumber(ctx, device_id),
                                    kJSPropertyAttributeReadOnly, NULL);
            }

            double file_number = (double) file_stat.st_ino;
            if (file_number) {
                JSObjectSetProperty(ctx, result, JSStringCreateWithUTF8CString("file-number"),
                                    JSValueMakeNumber(ctx, file_number),
                                    kJSPropertyAttributeReadOnly, NULL);
            }

            JSObjectSetProperty(ctx, result, JSStringCreateWithUTF8CString("permissions"),
                                JSValueMakeNumber(ctx, (double) (ACCESSPERMS & file_stat.st_mode)),
                                kJSPropertyAttributeReadOnly, NULL);

            JSObjectSetProperty(ctx, result, JSStringCreateWithUTF8CString("reference-count"),
                                JSValueMakeNumber(ctx, (double) file_stat.st_nlink),
                                kJSPropertyAttributeReadOnly, NULL);

            JSObjectSetProperty(ctx, result, JSStringCreateWithUTF8CString("uid"),
                                JSValueMakeNumber(ctx, (double) file_stat.st_uid),
                                kJSPropertyAttributeReadOnly, NULL);

            struct passwd *uid_passwd = getpwuid(file_stat.st_uid);

            if (uid_passwd) {
                JSObjectSetProperty(ctx, result, JSStringCreateWithUTF8CString("uname"),
                                    c_string_to_value(ctx, uid_passwd->pw_name),
                                    kJSPropertyAttributeReadOnly, NULL);
            }

            JSObjectSetProperty(ctx, result, JSStringCreateWithUTF8CString("gid"),
                                JSValueMakeNumber(ctx, (double) file_stat.st_gid),
                                kJSPropertyAttributeReadOnly, NULL);

            struct group *gid_group = getgrgid(file_stat.st_gid);

            if (gid_group) {
                JSObjectSetProperty(ctx, result, JSStringCreateWithUTF8CString("gname"),
                                    c_string_to_value(ctx, gid_group->gr_name),
                                    kJSPropertyAttributeReadOnly, NULL);
            }

            JSObjectSetProperty(ctx, result, JSStringCreateWithUTF8CString("file-size"),
                                JSValueMakeNumber(ctx, (double) file_stat.st_size),
                                kJSPropertyAttributeReadOnly, NULL);

#ifdef __APPLE__
#define birthtime(x) x.st_birthtime
#else
#define birthtime(x) x.st_ctime
#endif

            JSObjectSetProperty(ctx, result, JSStringCreateWithUTF8CString("created"),
                                JSValueMakeNumber(ctx, 1000 * birthtime(file_stat)),
                                kJSPropertyAttributeReadOnly, NULL);

            JSObjectSetProperty(ctx, result, JSStringCreateWithUTF8CString("modified"),
                                JSValueMakeNumber(ctx, 1000 * file_stat.st_mtime),
                                kJSPropertyAttributeReadOnly, NULL);

            return result;
        }

        free(path);
    }
    return JSValueMakeNull(ctx);
}
Пример #8
0
int main(int argc, char **argv) {
	struct option long_options[] = {
		{"help", no_argument, NULL, 'h'},
		{"legal", no_argument, NULL, 'l'},
		{"verbose", no_argument, NULL, 'v'},
		{"quiet", no_argument, NULL, 'q'},
		{"repl", no_argument, NULL, 'r'},
		{"static-fns", no_argument, NULL, 's'},
		{"elide-asserts", no_argument, NULL, 'a'},
		{"cache", required_argument, NULL, 'k'},
		{"eval", required_argument, NULL, 'e'},
		{"theme", required_argument, NULL, 't'},
		{"classpath", required_argument, NULL, 'c'},
		{"auto-cache", no_argument, NULL, 'K'},
		{"init", required_argument, NULL, 'i'},
		{"main", required_argument, NULL, 'm'},

		// development options
		{"javascript", no_argument, NULL, 'j'},
		{"out", required_argument, NULL, 'o'},

		{0, 0, 0, 0}
	};
	int opt, option_index;
	while ((opt = getopt_long(argc, argv, "h?lvrsak:je:t:c:o:Ki:qm:", long_options, &option_index)) != -1) {
		switch (opt) {
		case 'h':
			usage(argv[0]);
			exit(0);
		case 'l':
			legal();
			return 0;
		case 'v':
			verbose = true;
			break;
		case 'q':
			quiet = true;
			break;
		case 'r':
			repl = true;
			break;
		case 's':
			static_fns = true;
			break;
		case 'a':
			elide_asserts = true;
			break;
		case 'k':
			cache_path = argv[optind - 1];
			break;
		case 'K':
			cache_path = ".planck_cache";
			{
				char *path_copy = strdup(cache_path);
				char *dir = dirname(path_copy);
				if (mkdir_p(dir) < 0) {
					fprintf(stderr, "Could not create %s: %s\n", cache_path, strerror(errno));
				}
				free(path_copy);
			}
			break;
		case 'j':
			javascript = true;
			break;
		case 'e':
			num_scripts += 1;
			scripts = realloc(scripts, num_scripts * sizeof(struct script));
			scripts[num_scripts - 1].type = "text";
			scripts[num_scripts - 1].expression = true;
			scripts[num_scripts - 1].source = argv[optind - 1];
			break;
		case 'i':
			num_scripts += 1;
			scripts = realloc(scripts, num_scripts * sizeof(struct script));
			scripts[num_scripts - 1].type = "path";
			scripts[num_scripts - 1].expression = false;
			scripts[num_scripts - 1].source = argv[optind - 1];
			break;
		case 'm':
			main_ns_name = argv[optind - 1];
		case 't':
			theme = argv[optind - 1];
			break;
		case 'c':
			{
				char *classpath = argv[optind - 1];
				char *source = strtok(classpath, ":");
				while (source != NULL) {
					char *type = "src";
					if (str_has_suffix(source, ".jar") == 0) {
						type = "jar";
					}

					num_src_paths += 1;
					src_paths = realloc(src_paths, num_src_paths * sizeof(struct src_path));
					src_paths[num_src_paths - 1].type = type;
					src_paths[num_src_paths - 1].path = strdup(source);

					source = strtok(NULL, ":");
				}

				break;
			}
		case 'o':
			out_path = argv[optind - 1];
			break;
		case '?':
			usage(argv[0]);
			exit(1);
		default:
			printf("unhandled argument: %c\n", opt);
		}
	}

	int num_rest_args = 0;
	char **rest_args = NULL;
	if (optind < argc) {
		num_rest_args = argc - optind;
		rest_args = malloc((argc - optind) * sizeof(char*));
		int i = 0;
		while (optind < argc) {
			rest_args[i++] = argv[optind++];
		}
	}

	if (num_scripts == 0 && main_ns_name == NULL && num_rest_args == 0) {
		repl = true;
	}

	if (main_ns_name != NULL && repl) {
		printf("Only one main-opt can be specified.");
	}

	JSGlobalContextRef ctx = JSGlobalContextCreate(NULL);

	JSStringRef nameRef = JSStringCreateWithUTF8CString("planck");
	JSGlobalContextSetName(ctx, nameRef);

	evaluate_script(ctx, "var global = this;", "<init>");

	register_global_function(ctx, "AMBLY_IMPORT_SCRIPT", function_import_script);
	bootstrap(ctx, out_path);

	register_global_function(ctx, "PLANCK_CONSOLE_LOG", function_console_log);
	register_global_function(ctx, "PLANCK_CONSOLE_ERROR", function_console_error);

	evaluate_script(ctx, "var console = {};"\
			"console.log = PLANCK_CONSOLE_LOG;"\
			"console.error = PLANCK_CONSOLE_ERROR;", "<init>");

	evaluate_script(ctx, "var PLANCK_VERSION = \"" PLANCK_VERSION "\";", "<init>");

	// require app namespaces
	evaluate_script(ctx, "goog.require('planck.repl');", "<init>");

	// without this things won't work
	evaluate_script(ctx, "var window = global;", "<init>");

	register_global_function(ctx, "PLANCK_READ_FILE", function_read_file);
	register_global_function(ctx, "PLANCK_LOAD", function_load);
	register_global_function(ctx, "PLANCK_LOAD_DEPS_CLJS_FILES", function_load_deps_cljs_files);
	register_global_function(ctx, "PLANCK_CACHE", function_cache);

	register_global_function(ctx, "PLANCK_EVAL", function_eval);

	register_global_function(ctx, "PLANCK_GET_TERM_SIZE", function_get_term_size);
	register_global_function(ctx, "PLANCK_PRINT_FN", function_print_fn);
	register_global_function(ctx, "PLANCK_PRINT_ERR_FN", function_print_err_fn);

	register_global_function(ctx, "PLANCK_SET_EXIT_VALUE", function_set_exit_value);

	is_tty = isatty(STDIN_FILENO) == 1;
	register_global_function(ctx, "PLANCK_RAW_READ_STDIN", function_raw_read_stdin);
	register_global_function(ctx, "PLANCK_RAW_WRITE_STDOUT", function_raw_write_stdout);
	register_global_function(ctx, "PLANCK_RAW_FLUSH_STDOUT", function_raw_flush_stdout);
	register_global_function(ctx, "PLANCK_RAW_WRITE_STDERR", function_raw_write_stderr);
	register_global_function(ctx, "PLANCK_RAW_FLUSH_STDERR", function_raw_flush_stderr);

	{
		JSValueRef arguments[num_rest_args];
		for (int i = 0; i < num_rest_args; i++) {
			arguments[i] = c_string_to_value(ctx, rest_args[i]);
		}
		JSValueRef args_ref = JSObjectMakeArray(ctx, num_rest_args, arguments, NULL);

		JSValueRef global_obj = JSContextGetGlobalObject(ctx);
		JSStringRef prop = JSStringCreateWithUTF8CString("PLANCK_INITIAL_COMMAND_LINE_ARGS");
		JSObjectSetProperty(ctx, JSValueToObject(ctx, global_obj, NULL), prop, args_ref, kJSPropertyAttributeNone, NULL);
		JSStringRelease(prop);
	}

	evaluate_script(ctx, "cljs.core.set_print_fn_BANG_.call(null,PLANCK_PRINT_FN);", "<init>");
	evaluate_script(ctx, "cljs.core.set_print_err_fn_BANG_.call(null,PLANCK_PRINT_ERR_FN);", "<init>");

	char *elide_script = str_concat("cljs.core._STAR_assert_STAR_ = ", elide_asserts ? "false" : "true");
	evaluate_script(ctx, elide_script, "<init>");
	free(elide_script);

	{
		JSValueRef arguments[4];
		arguments[0] = JSValueMakeBoolean(ctx, repl);
		arguments[1] = JSValueMakeBoolean(ctx, verbose);
		JSValueRef cache_path_ref = NULL;
		if (cache_path != NULL) {
			JSStringRef cache_path_str = JSStringCreateWithUTF8CString(cache_path);
			cache_path_ref = JSValueMakeString(ctx, cache_path_str);
		}
		arguments[2] = cache_path_ref;
		arguments[3] = JSValueMakeBoolean(ctx, static_fns);
		JSValueRef ex = NULL;
		JSObjectCallAsFunction(ctx, get_function(ctx, "planck.repl", "init"), JSContextGetGlobalObject(ctx), 4, arguments, &ex);
		debug_print_value("planck.repl/init", ctx, ex);
	}

	if (repl) {
		evaluate_source(ctx, "text", "(require '[planck.repl :refer-macros [apropos dir find-doc doc source pst]])", true, false, "cljs.user", "dumb");
	}

	evaluate_script(ctx, "goog.provide('cljs.user');", "<init>");
	evaluate_script(ctx, "goog.require('cljs.core');", "<init>");

	evaluate_script(ctx, "cljs.core._STAR_assert_STAR_ = true;", "<init>");

	// Process init arguments

	for (int i = 0; i < num_scripts; i++) {
		// TODO: exit if not successfull
		evaluate_source(ctx, scripts[i].type, scripts[i].source, scripts[i].expression, false, NULL, theme);
	}

	// Process main arguments

	if (main_ns_name != NULL) {
		run_main_in_ns(ctx, main_ns_name, num_rest_args, rest_args);
	} else if (!repl && num_rest_args > 0) {
		char *path = rest_args[0];

		struct script script;
		if (strcmp(path, "-") == 0) {
			char *source = read_all(stdin);
			script.type = "text";
			script.source = source;
			script.expression = false;
		} else {
			script.type = "path";
			script.source = path;
			script.expression = false;
		}

		evaluate_source(ctx, script.type, script.source, script.expression, false, NULL, theme);
	} else if (repl) {
		if (!quiet) {
			banner();
		}

		char *home = getenv("HOME");
		char *history_path = NULL;
		if (home != NULL) {
			char history_name[] = ".planck_history";
			int len = strlen(home) + strlen(history_name) + 2;
			history_path = malloc(len * sizeof(char));
			snprintf(history_path, len, "%s/%s", home, history_name);

			linenoiseHistoryLoad(history_path);
		}

		char *prompt = javascript ? " > " : " => ";

		char *line;
		while ((line = linenoise(prompt)) != NULL) {
			if (javascript) {
				JSValueRef res = evaluate_script(ctx, line, "<stdin>");
				print_value("", ctx, res);
			} else {
				evaluate_source(ctx, "text", line, true, true, "cljs.user", theme);
			}
			linenoiseHistoryAdd(line);
			if (history_path != NULL) {
				linenoiseHistorySave(history_path);
			}
			free(line);
		}
	}

	return exit_value;
}