diff options
-rw-r--r-- | ChangeLog | 25 | ||||
-rw-r--r-- | match.c | 29 | ||||
-rw-r--r-- | match.h | 3 | ||||
-rw-r--r-- | parser.h | 1 | ||||
-rw-r--r-- | parser.l | 14 | ||||
-rw-r--r-- | parser.y | 10 | ||||
-rw-r--r-- | txr.c | 1 |
7 files changed, 79 insertions, 4 deletions
@@ -1,3 +1,28 @@ +2012-02-24 Kaz Kylheku <kaz@kylheku.com> + + First cut at @(load) directive. Incomplete: debug location info + needs to record file name, not only line number; absolute paths + not handled, etc. + + * match.c (load_s): New symbol variable. + (v_load): New static function. + (syms_init): load_s initialized. + (dir_tables_init): Load directive registered. + + * match.h (load_s): Declared. + + * parser.h (parse_reset): New function declared. + + * parser.l (spec_file_str): Global variable moved from txr.c. + (parse_reset): New function. + + * parser.y (clause): Special handling for @(load ...) directive. + parent file path inserted into the syntax at parse time, + so when the load directive executes, it can load the file from + the same directory as the parent file. + + * txr.c (spec_file_str): Global variable moved to parser.l. + 2012-02-22 Kaz Kylheku <kaz@kylheku.com> * tests/010/seq.txr: New file. @@ -54,7 +54,7 @@ int opt_arraydims = 1; val decline_k, next_spec_k, repeat_spec_k; val mingap_k, maxgap_k, gap_k, mintimes_k, maxtimes_k, times_k; val lines_k, chars_k; -val text_s, choose_s, gather_s, do_s, mod_s, modlast_s, fuzz_s; +val text_s, choose_s, gather_s, do_s, mod_s, modlast_s, fuzz_s, load_s; val longest_k, shortest_k, greedy_k; val vars_k, resolve_k; val append_k, into_k, var_k, list_k, string_k, env_k, counter_k; @@ -3373,6 +3373,31 @@ static val v_do(match_files_ctx *c) return next_spec_k; } +static val v_load(match_files_ctx *c) +{ + spec_bind (specline, first_spec, c->spec); + val args = rest(first_spec); + val parent = first(args); + val target = txeval(specline, second(args), c->bindings); + + if (rest(specline)) + sem_error(specline, lit("unexpected material after load"), nao); + + { + val path = cat_str(nappend2(sub_list(split_str(parent, lit("/")), + zero, negone), + cons(target, nil)), lit("/")); + int gc = gc_state(0); + parse_reset(path); + yyparse(); + gc_state(gc); + { + val spec = get_spec(); + return match_files(mf_spec(*c, spec)); + } + } +} + static val h_do(match_line_ctx *c) { val elem = first(c->specline); @@ -3588,6 +3613,7 @@ static void syms_init(void) choose_s = intern(lit("choose"), user_package); gather_s = intern(lit("gather"), user_package); do_s = intern(lit("do"), user_package); + load_s = intern(lit("load"), user_package); longest_k = intern(lit("longest"), keyword_package); shortest_k = intern(lit("shortest"), keyword_package); greedy_k = intern(lit("greedy"), keyword_package); @@ -3648,6 +3674,7 @@ static void dir_tables_init(void) sethash(v_directive_table, filter_s, cptr((mem_t *) v_filter)); sethash(v_directive_table, eof_s, cptr((mem_t *) v_eof)); sethash(v_directive_table, do_s, cptr((mem_t *) v_do)); + sethash(v_directive_table, load_s, cptr((mem_t *) v_load)); sethash(h_directive_table, text_s, cptr((mem_t *) h_text)); sethash(h_directive_table, var_s, cptr((mem_t *) h_var)); @@ -24,7 +24,8 @@ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -extern val text_s, choose_s, gather_s, do_s, mod_s, modlast_s, counter_k; +extern val text_s, choose_s, gather_s, do_s; +extern val load_s, mod_s, modlast_s, counter_k; val format_field(val string_or_list, val modifier, val filter, val eval_fun); val match_filter(val name, val arg, val other_args); val match_fun(val name, val args, val input, val files); @@ -39,6 +39,7 @@ void end_of_regex(void); void end_of_char(void); int yylex(void); void parse_init(void); +void parse_reset(val spec_file); val source_loc(val form); val rl(val form, val lineno); INLINE val rlcp(val to, val from) @@ -66,6 +66,7 @@ cnum lineno = 1; int opt_loglevel = 1; /* 0 - quiet; 1 - normal; 2 - verbose */ int errors; +val spec_file_str; val form_to_ln_hash; @@ -693,3 +694,16 @@ void parse_init(void) form_to_ln_hash = make_hash(t, nil, nil); } + +void parse_reset(val spec_file) +{ + errors = 0; + lineno = 1; + spec_file_str = spec_file; + { + FILE *in = w_fopen(c_str(spec_file_str), L"r"); + if (in == 0) + uw_throwf(file_error_s, lit("unable to open ~a"), spec_file_str, nao); + yyin_stream = make_stdio_stream(in, spec_file_str, t, nil); + } +} @@ -141,7 +141,15 @@ clause : all_clause { $$ = list($1, nao); rlcp($$, $1); } rlcp($$, $1); } | try_clause { $$ = list($1, nao); rlcp($$, $1); } | output_clause { $$ = list($1, nao); rlcp($$, $1); } - | line { $$ = $1; } + | line { val elem = car($1); + + if (consp(elem) && car(elem) == load_s) + { elem = rlcp(cons(load_s, + cons(spec_file_str, + cdr(elem))), elem); + $$ = rlcp(cons(elem, cdr($1)), $1); } + else + { $$ = $1; } } | repeat_clause { $$ = nil; yyerror("repeat outside of output"); } ; @@ -46,7 +46,6 @@ const wchli_t *version = wli("57"); const wchar_t *progname = L"txr"; const wchar_t *spec_file = L"stdin"; -val spec_file_str; /* * Can implement an emergency allocator here from a fixed storage |