Delayed "printf"

There is nothing dumb about it at all. It can be a bit tricky, though. But it's really just a variation on logging in general, so there may be a logger laying around somewhere that fits your specs so you don't have to spend a lot of time building one.

--
Les Cargill
Reply to
Les Cargill
Loading thread data ...

So look over a few varargs examples. If the first argument is a count of other arguments, and it's "format string" driven, then you should be able to just copy the args to .... something and pick 'em up later.

Just be careful of the lifetime of objects to be printed.

--
Les Cargill
Reply to
Les Cargill

Yeah, naah, that doesn't work when a translation needs to display the arguments in a different order from the parameter order.

For this purpose you need to be able to number the parameters in the format string, e.g.:

message("File %2$.*1$s was not available for operation %3$s", max_length, filename, operation_name);

That's almost exactly what we did, but using C++ and my ArgList construct meant we had guaranteed type safety at runtime, even when using a format string fetched from a catalog. A bad catalog cannot crash the formatting program.

I used an XML format for the message catalog source file, and generated from that #include files which defined integer message identifiers (as well as optionally including the default English language format strings).

The integers were designed to mesh on Windows with HRESULT values, so they were made up of a 12-bit "facility number" and a 16 bit message number within that facility. Each subsystem had a manually allocated facility number, and maintained its own messages (and allocated its own message numbers). The message numbers were often displayed using an sNNNmMMM format - so-called S/M numbers. This left four bits at the top for normal Windows HRESULT code severity markers.

Each message had an extended explanatory note which was used in producing the "Error message manual" - which ran to almost 500 pages in a PDF files, cataloged by SM number. The support department loved me for it :). But when you're talking about a system that even in 2007 was upwards of 3 million lines of code (excluding whitespace and comments) you really need this level of discipline.

The message catalog compiler performed various gyrations, including splitting or combining multiple XML files by language or facility, as well as producing a standard binary indexed compiled file for runtime. The compiler would check that each message had a translation into each target language, and could emit a file of those messages for which no translation was yet available, to be sent to the translators.

The other thing we did was to encourage message authors to break each message into three fragments: Problem, Reason and Solution. It's alarming how much software does not tell you the things you need to know. ENOENT -> "No such file or directory". Well, great. Was it a file or a directory that was missing? Perhaps you could even tell me which one?

We used to jeer at Microsoft for this kind of behaviour, with their "Unknown error 0x80000000", but they copied "errno" from Unix, and it has always cause the same kind of problems there too.

Hopefully I've given you a few more things to include in your design considerations.

Clifford Heath.

Reply to
Clifford Heath

Your main problem may be to know when the printf() is done, so that the source data is free to be used again. You may need to copy the printf argument values to a buffer, or maybe do a sprintf() and queue the string to the output device. In any case, delaying the output means needing to have buffer space.

The problem is similar to one in many networking hacks, where the protocol stack forces delaying sending the data.

--

-TV
Reply to
Tauno Voipio

Thanks, that's interesting. In this instance the use case is a bit different - running unmodified third-party C code. You really don't want to go around manually restructuring every printf if you can avoid it, hence the need for it to use source transformations. Locales are just a pre-existing mechanism for that; the messages never need to get translated into another language.

Theo

Reply to
Theo Markettos

It's so dumb that I do it often. Usually as a ring buffer of {format string ptr, arg...} with a fixed limit on the number of args. Sometime I actually do the print offline, from coredumps or shared memory.

Reply to
mac

I do something similar. In the latest incarnation, there's a dedicated sourceid/instance index, two 32-bit "parameters", and the printf "format" string is limited to somehting like 16 bytes.

There's a C macro that puts that stuff into a circular buffer in shared memory. Then there is a seperate utility to print the buffer contents.

--
Grant Edwards               grant.b.edwards        Yow! Wow!  Look!!  A stray 
                                  at               meatball!!  Let's interview 
                              gmail.com            it!
Reply to
Grant Edwards

If you want to save even more time/space, you can require that the format string have a static lifetime, and just copy a pointer into the circular buffer.

--
Grant Edwards               grant.b.edwards        Yow! You mean you don't 
                                  at               want to watch WRESTLING 
                              gmail.com            from ATLANTA?
Reply to
Grant Edwards

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.