Conversation
Expand expecets a function that takes a string and returns an array of string which then are parsed inplace of the string argument.
Comment string for the argumnet is added as well as a test for the new spec.
|
It's actually a bit more general than @xavierleroy suggestion in #748, since with this PR the user is responsible for expanding the argument (which could amount to reading a response file, or something else e.g. some environment variable). |
|
However it does not enforce the user to choose some predefined response file style. |
|
I personally like this way to separate the two aspects of the discussed feature and thing this one could be merged as soon as we want to -- but of course I won't consider MPR#7050 solved before we have at least one easy-to-use parsing function. |
|
I think |
|
You are right, there are some complications concerning the documentation and also the implementation. |
|
Given the heavy skew of the current API towards heavily imperative left-to-right processing, I think that the following specification could be the simplest one:
This immediately suggests an implementation that actually concatenates the argument arrays, and makes no validity check on Regarding recursion, it seems natural to me that nested expansions should be permitted and I think that it matters in practice: the idea should be that if a given command-line is too long, it is always possible to stuff it in a file and use (I'll temporarily remove the "approved tag" during the design discussion to avoid confusion.) |
Makes sense. I will update the PR accordingly.
I would let the user decide on the recursion for himself. |
Instead of introducing a new counter the recursive call takes the original counter. Furthermore the documentation is updated to reflect the actually semantics of Expand.
Well there is a realistic risk that someone would put |
|
How about an adding an additional bool to expand that states if recursion is allowed? |
|
I just recognized that when the current variable is used for the recursive call the whole function needs to be changed, since the current variable is used to get the arguments. |
Reusing the current pointer only works if the arrays are concatenated.
|
The arrays now are concatenated and the recursion is removed. |
No, I feel that this is not a meaningful choice to give to the users (because why would they not allow it?). But not having any termination-checking behavior is probably fine for a first PR. Thanks for the new implementation that is about what I would expect. Note that it should be possible to implement it without actual array concatenation (which has a quadratic behavior) by keeping a stack (a list) of (currently processed array, offset of the first element to substract when indexing in it) pairs, but I think implementing that is probably premature optimization and a simpler, easier-to-understand concatenating implementation is fine. I would replace the |
|
My first implementation try did use a list, however the possibility to have arguments of the form -foo=bar made this far more complicated. I will replace l with the length. |
This avoids forgetting to update the lenght of after the Array is updated.
|
No, I was thinking of a list of let rec elem idx = function
| [] -> assert false
| (argv, offset) :: rest ->
if idx < offset then elem idx rest
else argv.(idx - offset)
in
elem !current !argv_stackbut, again, I think this is premature optimization (also I'm not completely sure how reliably that works if/when user code modifies the |
|
Okay. However I think the concatenation is not that bad since ideally it should not happen to often. |
|
BTW, at some point we might want to allow the user to get access to the expanded array. There are programs such as the toplevel or ocamldebug that are using the |
|
Adding such a function should not be that complicated and makes sense. Any suggestions for a name? |
The new function takes a reference to the argv array and modifies it if an Expand spec is encountered. Also added tests for this.
|
I added a function |
|
Thanks, I reviewed the changes and they look good to me. @gasche are you happy as well with the current patch? One thing I was wondering is whether |
|
I would like most users to be able to take advantage of One suggestion I considered is to have a global I think I dislike the current, very stateful API of |
|
One could use a slightly different approach to handle |
|
That doesn't really work if the expansion depends on state modified by the processing of previous options (for example one could think of |
|
Then one probably wants to forbid the usage of |
|
About a better API for
(1) doesn't seem worth supporting. (2) is what is more commonly used, by the toplevel or ocamldebug for instance. For (2), we can have an API without out-variables: val parse_blah
: int * string array
-> (key * spec * doc) list ref
-> anon_fun
-> usage_msg
-> int * string arrayone issue is how to tell To use the toplevel method with an API without out-variables, we would need to pass We could use the ocamldebug method and have a special exception to stop parsing. It's not super nice but we already have a few special exceptions ( That said, the whole API of |
|
My suggestions:
|
|
Sorry for the delay, yes these suggestions look right to me. For |
Since Expand modifies the array and if the array is not passed as reference the usage of Expand would break lead to problems when current is used.
|
I just noticed a bug in the current implementation of Fails with: which is due to the fact that follow ref is never unset. |
stdlib/arg.ml
Outdated
|
|
||
| let parse_argv_dynamic ?(current=current) argv speclist anonfun errmsg = | ||
| let l = Array.length argv in | ||
| let parse_and_expand_argv_dynamic_aux expand current argv speclist anonfun errmsg = |
There was a problem hiding this comment.
I find expand not very descriptive, maybe expand_allowed?
There was a problem hiding this comment.
It is now named expand_allowed.
stdlib/arg.ml
Outdated
| done; | ||
| | Expand f -> | ||
| if not expand then | ||
| raise (Stop (Message ("Expand is not allowed"))); |
There was a problem hiding this comment.
This is in fact a misuse of the API so it should raise Invalid_argument. I would put some informative message to help the programmer debug the problem: "Arg.Expand is only allowed with Arg.parse_and_expand_argv_dynamic"
stdlib/arg.mli
Outdated
| See {!Arg.parse_dynamic}. | ||
| *) | ||
|
|
||
| val parse_and_expand_argv_dynamic : ?current:int ref -> string array ref -> |
There was a problem hiding this comment.
Having ?current default to Arg.current doesn't seem right. We might as well make current a mandatory argument for this function
There was a problem hiding this comment.
Current is now mandatory.
For the parse_and_expand_argv_dynamic function a current reference is now mandatory. As well as Invalid_arg is raised if Expand is used in any other function then parse_and_expand_argv_dynamic.
|
The current state looks good to me. I'm planning to merge this PR unless someone disagrees (/cc @gasche ) |
|
I haven't followed the last iterations but I trust @diml's opinion. |
|
Alright, it's now merged. @bschommer thanks for your contribution |
|
(Also, thanks everyone for the work!) |
Add the `Arg.Expand` constructor to `Arg.spec`. This new specification allows the user to expand the `argv` array being parsed, for instance to implement responsefile support. A new function `Arg.parse_and_expand_argv_dynamic` is added. It takes both `current` and `argv` as references and as mandatory arguments. This function allows the user to access the `argv` array after expansion. To avoid confusion regarding the `?current` argument of the various parsing functions as well as with `Arg.current`, `Arg.Expand` is only allowed with the new function. Tests for this PR are added to the testsuite.
Comment on caml_domain_spawn also calling in install_backup_thread
25188da flambda-backend: Missed comment from PR802 (ocaml#887) 9469765 flambda-backend: Improve the semantics of asynchronous exceptions (new simpler version) (ocaml#802) d9e4dd0 flambda-backend: Fix `make runtest` on NixOS (ocaml#874) 4bbde7a flambda-backend: Simpler symbols (ocaml#753) ef37262 flambda-backend: Add opaqueness to Obj.magic under Flambda 2 (ocaml#862) a9616e9 flambda-backend: Add build system hooks for ocaml-jst (ocaml#869) 045ef67 flambda-backend: Allow the compiler to build with stock Dune (ocaml#868) 3cac5be flambda-backend: Simplify Makefile logic for natdynlinkops (ocaml#866) c5b12bf flambda-backend: Remove unnecessary install lines (ocaml#860) ff12bbe flambda-backend: Fix unused variable warning in st_stubs.c (ocaml#861) c84976c flambda-backend: Static check for noalloc: attributes (ocaml#825) ca56052 flambda-backend: Build system refactoring for ocaml-jst (ocaml#857) 39eb7f9 flambda-backend: Remove integer comparison involving nonconstant polymorphic variants (ocaml#854) c102688 flambda-backend: Fix soundness bug by using currying information from typing (ocaml#850) 6a96b61 flambda-backend: Add a primitive to enable/disable the tick thread (ocaml#852) f64370b flambda-backend: Make Obj.dup use a new primitive, %obj_dup (ocaml#843) 9b78eb2 flambda-backend: Add test for ocaml#820 (include functor soundness bug) (ocaml#841) 8f24346 flambda-backend: Add `-dtimings-precision` flag (ocaml#833) 65c2f22 flambda-backend: Add test for ocaml#829 (ocaml#831) 7b27a49 flambda-backend: Follow-up PR#829 (comballoc fixes for locals) (ocaml#830) ad7ec10 flambda-backend: Use a custom condition variable implementation (ocaml#787) 3ee650c flambda-backend: Fix soundness bug in include functor (ocaml#820) 2f57378 flambda-backend: Static check noalloc (ocaml#778) aaad625 flambda-backend: Emit begin/end region only when stack allocation is enabled (ocaml#812) 17c7173 flambda-backend: Fix .cmt for included signatures (ocaml#803) e119669 flambda-backend: Increase delays in tests/lib-threads/beat.ml (ocaml#800) ccc356d flambda-backend: Prevent dynamic loading of the same .cmxs twice in private mode, etc. (ocaml#784) 14eb572 flambda-backend: Make local extension point equivalent to local_ expression (ocaml#790) 487d11b flambda-backend: Fix tast_iterator and tast_mapper for include functor. (ocaml#795) a50a818 flambda-backend: Reduce closure allocation in List (ocaml#792) 96c9c60 flambda-backend: Merge ocaml-jst a775b88 flambda-backend: Fix ocaml/otherlibs/unix 32-bit build (ocaml#767) f7c2679 flambda-backend: Create object files internally to avoid invoking GAS (ocaml#757) c7a46bb flambda-backend: Bugfix for Cmmgen.expr_size with locals (ocaml#756) b337cb6 flambda-backend: Fix build_upstream for PR749 (ocaml#750) 8e7e81c flambda-backend: Differentiate is_int primitive between generic and variant-only versions (ocaml#749) git-subtree-dir: ocaml git-subtree-split: 25188da
This PR adds a new spec for the
Argparser:Expand of (string -> string array)which takes a function as arguments and parses the returnedstring arrayrecursively with the same set of specs.This implements the approach mentioned by @xavierleroy in #748.