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,184 of 243,242   
   Bart to Kaz Kylheku   
   Re: printf and time_t   
   07 Feb 26 20:32:06   
   
   From: bc@freeuk.com   
      
   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).   
      
      
   > 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.   
      
   --- 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