--- camlp4/meta/pa_macro.ml 29 Oct 2003 22:04:22 -0000 +++ camlp4/meta/pa_macro.ml 29 Oct 2003 22:42:01 -0000 @@ -16,8 +16,8 @@ In expressions: - IFDEF THEN ELSE ENDIF - IFNDEF THEN ELSE ENDIF + IFDEF THEN [ ELSE ] ENDIF + IFNDEF THEN [ ELSE ] ENDIF __FILE__ __LOCATION__ @@ -30,12 +30,18 @@ -D -U + -I After having used a DEFINE followed by "= ", you can use it in expressions *and* in patterns. If the expression defining the macro cannot be used as a pattern, there is an error message if it is used in a pattern. + INCLUDE can be used to include a file with a number of macro definitions; + however it can not have any non-macro toplevel items. The INCLUDE files + are looked up in directories passed in via the -I option, falling back to + current directory. + The expression __FILE__ returns the current compiled file name. The expression __LOCATION__ returns the current location of itself. @@ -50,7 +56,8 @@ [ SdStr of 'a | SdDef of string and option (list string * MLast.expr) | SdUnd of string - | SdITE of string and list (item_or_def 'a) and list (item_or_def 'a) ] + | SdITE of string and list (item_or_def 'a) and list (item_or_def 'a) + | SdInc of string ] ; value rec list_remove x = @@ -185,12 +192,45 @@ [ Not_found -> () ] ; +(* This is a list of directories to search for INCLUDE statements. *) +value include_dirs = ref [] +; + +(* Add something to the above, make sure it ends with a slash. *) +value add_include_dir str = + if str <> "" then + let str = + if String.get str ((String.length str)-1) = '/' + then str else str ^ "/" + in include_dirs.val := include_dirs.val @ [str] + else () +; + +value smlist = Grammar.Entry.create Pcaml.gram "smlist" +; + +value parse_include_file = + let dir_ok file dir = Sys.file_exists (dir ^ file) in + fun file -> + let file = + try (List.find (dir_ok file) (include_dirs.val @ ["./"])) ^ file + with [ Not_found -> file ] + in + let st = Stream.of_channel (open_in file) in + let old_input = Pcaml.input_file.val in + do { + Pcaml.input_file.val := file; + let items = Grammar.Entry.parse smlist st in + do { Pcaml.input_file.val := old_input; items } } +; + value rec execute_macro = fun [ SdStr i -> [i] | SdDef x eo -> do { define eo x; [] } | SdUnd x -> do { undef x; [] } | SdITE i l1 l2 -> - execute_macro_list (if is_defined i then l1 else l2) ] + execute_macro_list (if is_defined i then l1 else l2) +| SdInc f -> execute_macro_list (parse_include_file f) ] and execute_macro_list = fun [ [] -> [] @@ -201,7 +241,7 @@ ; EXTEND - GLOBAL: expr patt str_item sig_item; + GLOBAL: expr patt str_item sig_item smlist; str_item: FIRST [ [ x = macro_def -> match execute_macro x with @@ -220,7 +260,8 @@ SdITE i [] dl | "IFNDEF"; i = uident; "THEN"; dl1 = smlist; "ELSE"; dl2 = smlist; "ENDIF" -> - SdITE i dl2 dl1 ] ] + SdITE i dl2 dl1 + | "INCLUDE"; file = STRING -> SdInc file ] ] ; smlist: [ [ sml = LIST1 str_item_or_macro -> sml ] ] @@ -267,4 +308,7 @@ ; Pcaml.add_option "-U" (Arg.String undef) " Undefine for IFDEF instruction." +; +Pcaml.add_option "-I" (Arg.String add_include_dir) + " Add a directory to INCLUDE search path." ;