From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-0.8 required=5.0 tests=BAYES_00,INVALID_DATE autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,130283ad9c6c2e69 X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 1994-10-14 15:41:39 PST Newsgroups: comp.lang.ada Path: bga.com!news.sprintlink.net!howland.reston.ans.net!noc.near.net!inmet!spock!stt From: stt@spock.camb.inmet.com (Tucker Taft) Subject: Re: Interfacing Ada to Unix/execl var. arg. list function? Message-ID: Sender: news@inmet.camb.inmet.com Organization: Intermetrics, Inc. References: <37ioh5$h9v@goanna.cs.rmit.oz.au> Date: Thu, 13 Oct 1994 19:28:35 GMT Date: 1994-10-13T19:28:35+00:00 List-Id: In article <37ioh5$h9v@goanna.cs.rmit.oz.au>, Dale Stanbrough wrote: >I am currently trying to develop a simple Ada/Unix binding (not Posix!) >that will allow students to use the packages with a minimum of fuss. >(i.e. reading the Unix man page/Unix programming text would give them >a fair idea of how to use the Ada version). > >I've got stuck on how to implement Ada calls to the corresponding >variable parameter list C functions, specifically execl. > >Also the solutions I have written currently look clunky. I was wondering if >there was a better way to implement these features. > > > >Problem #1. >----------- >Passing in a list of variable length strings... > >The possible options for passing in strings would be... > >type string_ptr is access all string; >type string_array is array(natural range <>) of string_ptr; If you change "string_ptr" to be: type string_ptr is access constant string; Then allocators for string_ptr can be done statically. >then... > >#1 ...execv(pathname, strings'("a","bb","cccc")); >#2 ...execv(pathname, strings_array'("a"'access, "bb"'access, "ccc"'access)); >#3 ...execv(pathname, strings_array'(a'access,b'access,c'access)); >#4 ...execv(pathname, ?); > >#1 won't work because arrays elements have to be the same size >#2 won't work because I don't know why ?:-/ (I wish Gnat gave me LRM ref's!). A string literal is not a name, and attributes are only allowed on names. >#3 seems awfully clunky, esp. as you have to alias all the strings before hand. >#4 is there a better one? Yes, I would recommend: execv(pathname, (new String'("a"), new String("bb"), new String("cccc"))); For convenience you could define an inline function: function "+"(S : String) return String_Ptr; pragma Inline("+"); function "+"(S : String) return String_Ptr is pragma Inline("+"); begin return new String'(S); end "+"; which would reduce this to: execv(pathname, (+"a", +"bb", +"cccc")); Alternatively, you could also define some operators which produce String_Arrays directly, eliminating the need for the explicit aggregate (this kind of operator overloading is not necessarily considered "good form" by all, perhaps because it can hinder readability if overdone): function "+"(Left : String_Array; Right : String) return String_Array; function "+"(Right : String) return String_Array; pragma Inline("+"); function "+"(Left : String_Array; Right : String) return String_Array is begin return Left & new String'(Right); end "+"; function "+"(Right : String) return String_Array is begin return (1 => new String'(Right)); end "+"; With the above, the call on execv would reduce to: execv(pathname, "a" + "bb" + "cccc"); >Problem #2. >----------- >Defining a constant null array seems to require the declaration of a >superfluous variable just to make the compiler happy... > >------------------------------------------------------------ >package unix is > type string_ptr is access all string; > type string_array is array(natural range <>) of string_ptr; > > null_arg_list :constant string_array; > > function execl( path :string; > arg_list:string_array := null_arg_list) > return integer; > >private > > dummy :aliased constant string := ""; --?? superfluous? > null_arg_list :constant string_array := (1..0 => dummy'access); No, you can use null instead: null_arg_list : constant String_Array := (1 .. 0 => null); >end unix.process; >------------------------------------------------------------ >Problem #3. >----------- >How to specify and pass in a variable list of pointers to a C program. >(Yes, I know we've been down this path before, but generally w.r.t. >printf, which has varying types of parameters, as well as number). > >----------------------------------------------------------- >-- Calling profile for execl in C. >-- >-- int execl(path, arg0 [ , arg1,... , argn ] (char *)0) >-- char *path, *arg0, *arg1, ..., *argn; >-- > >function execl( path :string; > arg_list :string_array) return integer is > > --------------------------------------------- > function C_execl( path :system.address; > C_arg_list: --?? What type here? > return interfaces.c.int; > pragma import(C, C_execl, "execl"); It will probably work to have a bunch of separate functions all with the same external_name, with different numbers of parameters. E.g.: function C_execl(Path : System.Address; C_arg1 : System.Address); function C_execl(Path : System.Address; C_arg1, C_arg2 : System.Address); function C_execl(Path : System.Address; C_arg1, C_arg2, C_arg3 : System.Address); ... etc. pragma Import(C, C_execl, "execl"); >begin > -- how to do this? Actually, execl is normally implemented in terms of execv, so I am a little surprised you would try to hook up to execl here. But if you really wanted to, you would have to have a case statement: case arg_list'Length is when 1 => return Integer(c_execl(path'address, c_arg_list(1)'address)); when 2 => return Integer(c_execl(path'address, c_arg_list(1)'address, c_arg_list(2)'address)); ... when others => -- complain end case; However, as mentioned above, the right solution for this particular case seems to be to build up an array of addresses, and then pass that to C's execv, instead of calling C's execl. In fact, given the way of handling variable-length lists in Ada, there seems no reason to distinguish between execv and execl. >end; >----------------------------------------------------------- >Thanks for any help you can give... > >Dale >------------------------------------------------------------- >Dale Stanbrough, RMIT, Melbourne, Australia, dale@rmit.edu.au -Tucker Taft stt@inmet.com Intermetrics, Inc. Cambridge, MA 02138