Ben said:
I see three problems: first you need to find a way that does not add
characters to the format. I need to be able to write "%sc" and have a
'c' come after the string. Secondly, you'd want to borrow as much power
as you can from the existing formats. I should be able to use field
widths, and precision, and alternate forms, and padding characters for
my multiple hex bytes (or, indeed, my multiple ints or whatever). The
third is that one would often want to include literal characters as well
(printing multiple bytes in hex is problematic to read unless there is a
separator).
printf isn't really right for this. The problem isn't hard, but the
syntax gets messy in a hurry, and printf is getting messier and messier
as more things are added to it.
Almost certainly this has been worked out more elegantly in some other
language, but, in general terms a print function needs:
1. input identifiers (defaults to order of arguments, if
that has an unambiguous meaning)
2. number of elements to print (defaults to 1)
3. format for each element (width, precision, hex, integer. etc.
There is no default for this part.)
4. data type (c=char, w=wide char, s=short, i=int, etc., defaults
to whatever the format would use in printf).
Printf went off course back in the K&R days by mixing 3 and 4, and
I don't think it is possible at this point to separate them again.
Anyway, a more generic format specifier might look like
%repeat#(%<modifiers>format(datatype(input)))
If the datatype matches the default for format, then leave off
(datatype). If only one instance is needed leave off %number#().
If the current index for an input is needed precede it with i.
The repeat construct could be nested.
For simple things the function still looks like printf:
general_print(stdout,"%s\n",string);
but soon it doesn't. Print a line of 400 hex characters, 4 hex
charactersfor each of 100 wide chars:
general_print(stdout,"%100#(%4.4x(w))\n",wbuffer);
or if length is a variable, one of these
general_print(stdout,"%*#(%2.2x(w))\n",len,wbuffer);
general_print(stdout,"%#(1)(%2.2x(w))\n",len,wbuffer);
Allow nested repeats and access to the (implicit) input indices and it
becomes more powerful, but the syntax gets complicated. Here's hoping I
counted parens correctly:
general_print(stdout,
"%#(1)(%3d(i2) %5#(%3x(i(2)):%2d(l(3)), )%3x((2)):%2d(l(3))\n)",
len,buffer1,buffer2);
which if len was 4 would print:
0 xxx:yy, xxx:yy, xxx:yy, xxx:yy, xxx:yy, xxx:yy
5 xxx:yy, xxx:yy, xxx:yy, xxx:yy, xxx:yy, xxx:yy
10 xxx:yy, xxx:yy, xxx:yy, xxx:yy, xxx:yy, xxx:yy
15 xxx:yy, xxx:yy, xxx:yy, xxx:yy, xxx:yy, xxx:yy
where the xxx values are hex taken as ints from buffer 1 and yy are
decimal values as longs from buffer2.
If the input indices are not hidden it will look a lot like fortran
formatting.
By this point it looks like named format blocks would help, since the
same pattern was used twice in the example above. Something like
this if standard defines are to be understood within the print format
line:
#define ABLOCK %3d(i(2)):%2d(l(3))
general_print(stdout,
"%#(1)(%3d(i2) %5#({ABLOCK}, ){ABLOCK}\n)",
len,buffer1,buffer2);
And that's enough speculation for one day.
Regards,
David Mathog