/** * mpsl_error - Generates an error. * @err: the error message * * Generates an error. The @err error message is stored in the ERROR * mpsl variable and the mpsl_abort global flag is set, so no further * mpsl code can be executed until reset. */ mpdm_t mpsl_error(mpdm_t err) { /* abort further execution */ mpsl_abort = 1; /* set the error */ return mpdm_hset_s(mpdm_root(), L"ERROR", err); }
O_TYPE O_global(O_ARGS) { mpdm_t v = RF(M1); if (MPDM_IS_ARRAY(v)) { int n; for (n = 0; n < mpdm_size(v); n++) mpdm_hset(mpdm_root(), mpdm_aget(v, n), NULL); } else mpdm_hset(mpdm_root(), v, NULL); UF(v); return NULL; }
/** * mpsl_set_symbol - Sets value to a symbol. * @s: symbol name * @v: value * @l: local symbol table * * Assigns the value @v to the @s symbol. If the value exists as * a local symbol, it's assigned to it; otherwise, it's set as a global * symbol (and created if it does not exist). */ mpdm_t mpsl_set_symbol(mpdm_t s, mpdm_t v, mpdm_t l) { int n; mpdm_t r, p, w; mpdm_ref(l); mpdm_ref(s); mpdm_ref(v); /* get the local or global symbol table */ if ((r = find_local_symtbl(s, l)) == NULL) r = mpdm_root(); /* splits the path, if needed */ if (MPDM_IS_ARRAY(s)) p = mpdm_ref(s); else p = mpdm_ref(mpdm_split_s(s, L".")); w = r; for (n = 0; w != NULL && n < mpdm_size(p); n++) { /* is executable? run it and take its output */ while (MPDM_IS_EXEC(w)) w = mpdm_exec(w, NULL, NULL); /* last component? */ if (n == mpdm_size(p) - 1) { /* yes; do the setting */ if (MPDM_IS_HASH(w)) w = mpdm_hset(w, mpdm_aget(p, n), v); else if (MPDM_IS_ARRAY(w)) w = mpdm_aset(w, v, mpdm_ival(mpdm_aget(p, n))); } else { if (MPDM_IS_HASH(w)) w = mpdm_hget(w, mpdm_aget(p, n)); else if (MPDM_IS_ARRAY(w)) w = mpdm_aget(w, mpdm_ival(mpdm_aget(p, n))); else { mpdm_void(w); w = NULL; } } } mpdm_unref(p); mpdm_unref(v); mpdm_unref(s); mpdm_unref(l); return w; }
/** * mpsl_argv - Fills the ARGV global array. * @argc: number of arguments * @argv: array of string values * * Fills the ARGV global MPSL array with an array of arguments. These * are usually the ones sent to main(). */ void mpsl_argv(int argc, char *argv[]) { int n; mpdm_t ARGV; /* create the ARGV array */ ARGV = mpdm_hset_s(mpdm_root(), L"ARGV", MPDM_A(0)); for (n = 0; n < argc; n++) mpdm_push(ARGV, MPDM_MBS(argv[n])); }
void test_abort_and_eval(void) { mpdm_t v; mpdm_t e; mpsl_abort = 0; v = mpdm_ref(mpsl_compile(MPDM_S(L"1000;"), NULL)); do_test("Abort 1", mpdm_ival(mpdm_exec(v, NULL, NULL)) == 1000); /* set global abort function */ mpsl_abort = 1; do_test("Abort 2", mpdm_exec(v, NULL, NULL) == NULL); mpsl_abort = 0; do_test("Abort 3", mpdm_ival(mpdm_exec(v, NULL, NULL)) == 1000); mpdm_unref(v); mpsl_error(NULL); v = mpsl_eval(MPDM_S(L"invalid_code()"), NULL, NULL); e = mpdm_get_wcs(mpdm_root(), L"ERROR"); printf("The following error is OK:\n"); mpdm_dump(e); do_test("eval 1", v == NULL && e != NULL); v = mpsl_eval(MPDM_S(L"undef_func();"), NULL, NULL); e = mpdm_get_wcs(mpdm_root(), L"ERROR"); printf("The following error is also OK:\n"); mpdm_dump(e); do_test("eval 2", v == NULL && e != NULL); v = mpsl_eval(MPDM_S(L"load('unexistent_file.mpsl');"), NULL, NULL); e = mpdm_get_wcs(mpdm_root(), L"ERROR"); printf("The following error is also OK:\n"); mpdm_dump(e); do_test("eval 3", v == NULL && e != NULL); v = mpsl_eval(MPDM_S(L"2000;"), NULL, NULL); e = mpdm_get_wcs(mpdm_root(), L"ERROR"); do_test("eval 4", mpdm_ival(v) == 2000 && e == NULL); }
extern "C" int kde4_drv_detect(int *argc, char ***argv) { mpdm_t drv; KCmdLineOptions opts; Display *x11_display; int n; for (n = 0; n < *argc; n++) { if (strcmp(argv[0][n], "-txt") == 0 || strcmp(argv[0][n], "-h") == 0) return 0; } /* try connecting directly to the Xserver */ if ((x11_display = XOpenDisplay((char *) NULL)) == NULL) return 0; KAboutData aboutData("mp", 0, ki18n("Minimum Profit"), VERSION, ki18n("A programmer's text editor"), KAboutData::License_GPL, ki18n("Copyright (c) 1991-2009 Angel Ortega"), ki18n(""), "http://triptico.com", "*****@*****.**"); KCmdLineArgs::init(*argc, *argv, &aboutData); /* command line options should be inserted here (I don't like this) */ opts.add("t {tag}", ki18n("Edits the file where tag is defined")); opts.add("e {mpsl_code}", ki18n("Executes MPSL code")); opts.add("f {mpsl_script}", ki18n("Executes MPSL script file")); opts.add("d {directory}", ki18n("Sets working directory")); opts.add("x {file}", ki18n("Open file in the hexadecimal viewer")); opts.add(" +NNN", ki18n("Moves to line number NNN of last file")); opts.add("txt", ki18n("Use text mode instead of GUI")); opts.add("+[file(s)]", ki18n("Documents to open")); KCmdLineArgs::addCmdLineOptions(opts); /* this is where it crashes if no X server */ app = new KApplication(x11_display); drv = mpdm_hset_s(mpdm_root(), L"mp_drv", MPDM_H(0)); mpdm_hset_s(drv, L"id", MPDM_LS(L"kde4")); mpdm_hset_s(drv, L"startup", MPDM_X(kde4_drv_startup)); return 1; }
static void register_functions(void) { mpdm_t drv; drv = mpdm_hget_s(mpdm_root(), L"mp_drv"); mpdm_hset_s(drv, L"main_loop", MPDM_X(kde4_drv_main_loop)); mpdm_hset_s(drv, L"shutdown", MPDM_X(kde4_drv_shutdown)); mpdm_hset_s(drv, L"clip_to_sys", MPDM_X(kde4_drv_clip_to_sys)); mpdm_hset_s(drv, L"sys_to_clip", MPDM_X(kde4_drv_sys_to_clip)); mpdm_hset_s(drv, L"update_ui", MPDM_X(kde4_drv_update_ui)); mpdm_hset_s(drv, L"timer", MPDM_X(kde4_drv_timer)); mpdm_hset_s(drv, L"busy", MPDM_X(kde4_drv_busy)); mpdm_hset_s(drv, L"alert", MPDM_X(kde4_drv_alert)); mpdm_hset_s(drv, L"confirm", MPDM_X(kde4_drv_confirm)); mpdm_hset_s(drv, L"openfile", MPDM_X(kde4_drv_openfile)); mpdm_hset_s(drv, L"savefile", MPDM_X(kde4_drv_savefile)); mpdm_hset_s(drv, L"form", MPDM_X(kde4_drv_form)); }
mpdm_t mpsl_build_funcs(void) /* build all functions */ { mpdm_t c; int n; /* creates all the symbols in the CORE library */ c = MPDM_O(); for (n = 0; mpsl_funcs[n].name != NULL; n++) { mpdm_t f = MPDM_S(mpsl_funcs[n].name); mpdm_t x = MPDM_X(mpsl_funcs[n].func); mpdm_set(mpdm_root(), x, f); mpdm_set(c, x, f); } return c; }
/** * mpsl_startup - Initializes MPSL. * * Initializes the Minimum Profit Scripting Language. Returns 0 if * everything went OK. */ int mpsl_startup(void) { mpdm_t r; mpdm_t m; /* startup MPDM */ mpdm_startup(); r = mpdm_root(); /* creates INC, unless already defined */ if (mpdm_hget_s(r, L"INC") == NULL) mpdm_hset_s(r, L"INC", MPDM_A(0)); /* the TRUE value */ mpdm_hset_s(r, L"TRUE", MPDM_I(1)); /* standard file descriptors */ mpdm_hset_s(r, L"STDIN", MPDM_F(stdin)); mpdm_hset_s(r, L"STDOUT", MPDM_F(stdout)); mpdm_hset_s(r, L"STDERR", MPDM_F(stderr)); /* home and application directories */ mpdm_hset_s(r, L"HOMEDIR", mpdm_home_dir()); mpdm_hset_s(r, L"APPDIR", mpdm_app_dir()); /* fill now the MPSL hash */ m = MPDM_H(0); mpdm_hset_s(r, L"MPSL", m); /* store things there */ mpdm_hset_s(m, L"VERSION", MPDM_MBS(VERSION)); mpdm_hset_s(m, L"OPCODE", mpsl_build_opcodes()); mpdm_hset_s(m, L"LC", MPDM_H(0)); mpdm_hset_s(m, L"CORE", mpsl_build_funcs()); mpdm_dump_1 = mpsl_dump_1; return 0; }
/** * mpsl_boolean - Returns 'true' or 'false' MPSL stock values. * @b: boolean selector * * Returns MPSL's 'false' or 'true' values depending on the value in @b. */ mpdm_t mpsl_boolean(int b) { return b ? mpdm_hget_s(mpdm_root(), L"TRUE") : NULL; }
void test_compiler_diffs(void) { mpdm_t r, cc, ac; int n; struct { wchar_t *code; int line; } compiler_tests[] = { // CT(L"local a = 1, b = 2, c, d = 3;"), // CT(L"local a = 1;"), // CT(L"local v; 1;"), // CT(L"local x, y, z; 2;"), CT(L"a |= 6;"), CT(L"a %= 6;"), CT(L"a /= 6;"), CT(L"a *= 6;"), CT(L"a -= 6;"), CT(L"a += 6;"), CT(L"for (n = 0; n < 100; n = n + 1) { print('kill'); } 1234;"), CT(L"for (;;) { print('kill'); } 1234;"), CT(L"foreach (v, i, [1, 2, 3]) { print(e); } 666;"), CT(L"eol = driver == 'win32' && 'crlf' || 'lf';"), CT(L"255 $ '%x';"), CT(L"foreach (e, [1, 2, 3]) { print(e); } 666;"), // CT(L"global v; 1;"), // CT(L"global x, y, z; 2;"), CT(L"sub pi { 3.1416; } 100;"), CT(L"sub pi () { 3.1416; } 200;"), CT(L"sub by2(v) { v * 2; } 250;"), CT(L"sub mul(v1, v2) { v1 * v2; } 300;"), CT(L"mul = sub (v1, v2) { v1 * v2; }; 123;"), CT(L"by2 = sub (e) { e * 2; }; 100;"), CT(L"pi = sub { 3.14; }; 6;"), CT(L"f->write('hi', string(1 + 3), eol); 1;"), CT(L"f->read(); 1;"), CT(L"while (1) 2;"), CT(L"while (1) { 2; 3; }"), CT(L"while (a < 10) { a = a + 1; }"), CT(L"if (a == 1) { b = 2 + 4; c = 3 * 2; } else { d = 3; e = d / 2; }"), CT(L"if (1) 2; else 3;"), CT(L"if (1) { 2; 3; }"), CT(L"if (1) { 2; }"), CT(L"if (1) 2;"), CT(L"if (2 + 3) 4 + 5;"), CT(L"if (a == 1) b = 2;"), CT(L"list[0];"), CT(L"list[1] = 1;"), CT(L"MPSL['OPCODE'];"), CT(L"q = 1 + 2 * 3;"), CT(L"q.q = 1 * 2 + 3; q2 = [];"), CT(L"q = 100;"), CT(L"MPSL.CORE.random;"), CT(L"1 + 2; [1, 2] ; {};"), CT(L"a + 1;"), CT(L"1 * (2 + 3);"), CT(L"{};"), CT(L"{a: 1};"), CT(L"{c: 2, d: 3};"), CT(L"{'e' => 4, 'f' => 5};"), CT(L"{g: 6, 'h' => 7};"), CT(L"{a: 2 * 3, b: 5 + 8};"), CT(L"[];"), CT(L"[1, 2, 3];"), CT(L"[1, 2 + 3, 4];"), CT(L"MPSL.CORE.random();"), CT(L"bool(1, 2) + 666;"), CT(L"1 ; 2 ; 3;"), CT(L"random();"), CT(L"5 != '5';"), CT(L"10 == '10';"), CT(L"10 > 1 + 2;"), CT(L"1 + 2 * 3;"), CT(L"1 * 2 + 3;"), CT(L"1.2 + 3.4;"), CT(L"/* test test */"), CT(L"1;"), CT(L"!1;"), CT(L"'abcde';"), CT(L"3.14;"), CT(NULL) }; printf("\nComparing the output of the two compilers:\n"); r = mpdm_get_wcs(mpdm_root(), L"MPSL"); cc = mpdm_get_wcs(r, L"c_compiler"); ac = mpdm_get_wcs(r, L"a_compiler"); for (n = 0; compiler_tests[n].code; n++) { mpdm_t c, x1, x2, d1, d2; c = MPDM_S(compiler_tests[n].code); mpdm_ref(c); mpdm_set_wcs(r, cc, L"compiler"); x1 = mpsl_compile(c, NULL); d1 = mpsl_decompile(x1); mpdm_set_wcs(r, ac, L"compiler"); x2 = mpsl_compile(c, NULL); d2 = mpsl_decompile(x2); /* printf("%ls\n", mpdm_string(d1)); printf("%ls\n", mpdm_string(d2));*/ _do_test("compiler output equal", mpdm_cmp(d1, d2) == 0, compiler_tests[n].line); mpdm_unref(c); } mpdm_set_wcs(r, cc, L"compiler"); }
static mpdm_t F_getenv(F_ARGS) { mpdm_t e = mpdm_get_wcs(mpdm_root(), L"ENV"); return mpdm_get(e, mpdm_get_i(a, 0)); }