home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   comp.lang.c      Meh, in C you gotta define EVERYTHING      243,242 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 243,183 of 243,242   
   Waldek Hebisch to Bart   
   Re: printf and time_t   
   07 Feb 26 22:48:32   
   
   From: antispam@fricas.org   
      
   Bart  wrote:   
   > On 07/02/2026 18:07, Kaz Kylheku wrote:   
   >> On 2026-02-06, Michael S  wrote:   
   >>> On Fri, 6 Feb 2026 12:39:55 +0000   
   >>> Bart  wrote:   
   >>>   
   >>>> On 06/02/2026 05:10, Keith Thompson wrote:   
   >>>>> Bart  writes:   
   >>>>> [...]   
   >>>>>> /Some/ compilers with /some/ options will /sometimes/ tell you when   
   >>>>>> you've got it wrong.   
   >>>>>>   
   >>>>>> But you first have to make an educated guess, or put in some dummy   
   >>>>>> format code.   
   >>>>>>   
   >>>>>> Eventually, it will compile. Until someone else builds your   
   >>>>>> program, using a slightly different set of headers where certain   
   >>>>>> types are defined, and then it might either give compiler messages   
   >>>>>> that they have to fix, or it show wrong results.   
   >>>>>   
   >>>>> That's not how I do it, and I don't think it's how most programmers   
   >>>>> do it.   
   >>>>>   
   >>>>> I know the rules well enough that I can usually write a correct   
   >>>>> format string in the first place.  If I make a mistake, gcc's   
   >>>>> warnings are a nice check.   
   >>>>   
   >>>> I guess you've never used printf-family functions via the FFI of   
   >>>> another language!   
   >>>>   
   >>>>   
   >>>   
   >>> Vararg via FFI? Is it really a good idea?   
   >>   
   >> I support it in TXR Lisp. However, it's limited in that the FFI   
   >> definition is nailed to a particular choice of arguments.   
   >>   
   >> For instance we could make a function foo which takes two arguments:   
   >> a str and an int, and calls the variadic printf.   
   >>   
   >> Then we can call (foo "%d" 42). It will call printf("%d", 42).   
   >>   
   >> We cannot pass fewer or more than two arguments to foo, and they have to   
   >> be compatible with str and int.   
   >>   
   >> Demo:   
   >>   
   >> $ txr   
   >> This is the TXR Lisp interactive listener of TXR 302.   
   >> Quit with :quit or Ctrl-D on an empty line. Ctrl-X ? for cheatsheet.   
   >> 1> (with-dyn-lib nil   
   >>       (deffi printf-int "printf" int (str : int)))   
   >> printf-int   
   >> 2> (printf-int "%d\n" 42)   
   >> 42   
   >> 3   
   >>   
   >> 42 is output; 3 is the result value (3 characters output).   
   >>   
   >> The : syntax in the deffi macro call indicates the variadic list.   
   >> It's not the case that we can make a variadic Lisp function pass its   
   arguments   
   >> as an arbitrarily long variadic list with arbitrary types to the wrapped FFI   
   >> function. Fixed parameters must be declared after the colon.   
   >   
   > There's another issue with calling variadic functions, unrelated to the   
   > number of args. I can't tell from the above whether it's convered.   
   >   
   > Normally an arg that is passed in a register, will be passed in GPR for   
   > integer, or a floating point register if not.   
   >   
   > But a variadic float argument has to be passed in both, so for Win64   
   > ABI/x64 it might be in both rcx and xmm1. I think it is similar on SYS V   
   > for both x64 and arm64 (maybe on the latter both are passed in the GPR;   
   > I'd have to go and look it up).   
      
   In SYS V convention argument is passed in exactly one place.  It may   
   be GPR, may be XMM register, may be on the stack.  If you put right   
   thing in RAX, then your arguments are valid regardless if the function   
   is a vararg function or not.   
      
   >> A dynamic treatment could be arranged via a heavy weight wrapper mechanism   
   which   
   >> dynamically analyzes the actual arguments, builds a libffi function   
   descriptor   
   >> on the fly, then uses it to make the call; it could be wortwhile for   
   someone,   
   >> but I didn't implement such a thing.  Metaprogramming tricks revolving   
   around   
   >> dynamically evaluating deffi are also possible.   
   >   
   > My LIBFFI approach just uses assembly; it's the simplest way to do it.   
   > (The LIBFFI 'C' library also uses assembly to do the tricky bits.)   
   >   
   > There, for Win64 ABI, I found it easiest to just load all the register   
   > args to both integer and float registers, whether the called function   
   > was variadic or not. That's far more efficient than figuring out the   
   > right register argument by argument.   
   >   
   > I haven't implemented that for SYS V; that's more of a nightmare ABI   
   > where up to 6-12 args (8-16 on aarch64) can be passed between int and   
   > float registers depending on the mix of types.   
   >   
   > On Win64 ABI, it is 4 args, always.   
      
   My code works fine for SYS V on amd64 and arm32.  I do not think FFI   
   for aarch64 will be any harder, but ATM I do not have code generator   
   for aarch64, no need for FFI there.   
      
   I did not bother with Windows, since I do not use it it would be   
   untested and hence buggy code anyway.   
      
   --   
                                 Waldek Hebisch   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca