Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #94244 > unrolled thread
| Started by | James Harris <james.harris.1@gmail.com> |
|---|---|
| First post | 2016-09-29 16:20 +0100 |
| Last post | 2016-10-02 21:27 +0200 |
| Articles | 20 on this page of 44 — 9 participants |
Back to article view | Back to comp.lang.c
When parameters to printf are in memory James Harris <james.harris.1@gmail.com> - 2016-09-29 16:20 +0100
Re: When parameters to printf are in memory James Harris <james.harris.1@gmail.com> - 2016-09-29 16:43 +0100
Re: When parameters to printf are in memory Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-29 20:30 +0100
Re: When parameters to printf are in memory James Harris <james.harris.1@gmail.com> - 2016-09-29 21:23 +0100
Re: When parameters to printf are in memory BartC <bc@freeuk.com> - 2016-09-29 22:03 +0100
Re: When parameters to printf are in memory James Harris <james.harris.1@gmail.com> - 2016-09-29 22:35 +0100
Re: When parameters to printf are in memory BartC <bc@freeuk.com> - 2016-09-29 23:11 +0100
Re: When parameters to printf are in memory James Harris <james.harris.1@gmail.com> - 2016-09-30 19:53 +0100
Re: When parameters to printf are in memory Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-30 20:53 +0100
Re: When parameters to printf are in memory James Harris <james.harris.1@gmail.com> - 2016-10-01 09:08 +0100
Re: When parameters to printf are in memory BartC <bc@freeuk.com> - 2016-10-01 11:15 +0100
Re: When parameters to printf are in memory James Harris <james.harris.1@gmail.com> - 2016-10-04 08:32 +0100
Re: When parameters to printf are in memory Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-10-01 11:15 +0100
Re: When parameters to printf are in memory James Harris <james.harris.1@gmail.com> - 2016-10-04 08:28 +0100
Re: When parameters to printf are in memory Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-10-04 09:49 +0100
Re: When parameters to printf are in memory BartC <bc@freeuk.com> - 2016-10-04 11:43 +0100
Re: When parameters to printf are in memory Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-10-04 13:42 +0100
Re: When parameters to printf are in memory BartC <bc@freeuk.com> - 2016-10-04 14:03 +0100
Re: When parameters to printf are in memory Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-10-04 14:16 +0100
Re: When parameters to printf are in memory James Harris <james.harris.1@gmail.com> - 2016-10-04 20:01 +0100
Re: When parameters to printf are in memory Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-10-04 20:24 +0100
Re: When parameters to printf are in memory James Harris <james.harris.1@gmail.com> - 2016-10-04 20:40 +0100
Re: When parameters to printf are in memory Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-10-04 22:51 +0100
Re: When parameters to printf are in memory "James R. Kuyper" <jameskuyper@verizon.net> - 2016-10-04 14:25 -0400
Re: When parameters to printf are in memory James Harris <james.harris.1@gmail.com> - 2016-10-04 20:31 +0100
Re: When parameters to printf are in memory BartC <bc@freeuk.com> - 2016-09-29 17:03 +0100
Re: When parameters to printf are in memory gazelle@shell.xmission.com (Kenny McCormack) - 2016-09-30 12:20 +0000
Re: When parameters to printf are in memory Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-30 05:55 -0700
Re: When parameters to printf are in memory James Harris <james.harris.1@gmail.com> - 2016-09-30 20:06 +0100
Re: When parameters to printf are in memory gazelle@shell.xmission.com (Kenny McCormack) - 2016-09-30 22:01 +0000
Re: When parameters to printf are in memory James Harris <james.harris.1@gmail.com> - 2016-10-01 09:15 +0100
Re: When parameters to printf are in memory Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-30 23:18 -0700
Re: When parameters to printf are in memory James Harris <james.harris.1@gmail.com> - 2016-10-01 09:32 +0100
Re: When parameters to printf are in memory jacobnavia <jacob@jacob.remcomp.fr> - 2016-09-29 18:35 +0200
Re: When parameters to printf are in memory James Harris <james.harris.1@gmail.com> - 2016-09-29 19:55 +0100
Re: When parameters to printf are in memory jacobnavia <jacob@jacob.remcomp.fr> - 2016-09-29 21:22 +0200
Re: When parameters to printf are in memory Barry Schwarz <schwarzb@dqel.com> - 2016-09-29 11:20 -0700
Re: When parameters to printf are in memory James Harris <james.harris.1@gmail.com> - 2016-09-29 20:08 +0100
Re: When parameters to printf are in memory Lőrinczy Zsigmond <nospam@for.me> - 2016-10-02 20:15 +0200
Re: When parameters to printf are in memory Lőrinczy Zsigmond <nospam@for.me> - 2016-10-02 20:19 +0200
Re: When parameters to printf are in memory gazelle@shell.xmission.com (Kenny McCormack) - 2016-10-02 18:29 +0000
Re: When parameters to printf are in memory Lőrinczy Zsigmond <nospam@for.me> - 2016-10-03 07:04 +0200
Re: When parameters to printf are in memory James Harris <james.harris.1@gmail.com> - 2016-10-04 08:36 +0100
Re: When parameters to printf are in memory jacobnavia <jacob@jacob.remcomp.fr> - 2016-10-02 21:27 +0200
Page 2 of 3 — ← Prev page 1 [2] 3 Next page →
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2016-10-04 20:24 +0100 |
| Message-ID | <87eg3v2a03.fsf@bsb.me.uk> |
| In reply to | #94450 |
James Harris <james.harris.1@gmail.com> writes:
> On 04/10/2016 09:49, Ben Bacarisse wrote:
<snip>
>> But there are very many other possible problems that come [down] to one
>> basic problem. If the format has "%d" the corresponding argument must
>> be an int and not a union that might contain an int.
>
> So if I had
>
> union any {
> int16_t i16;
> int i;
> double d;
> } u;
>
> I guess you are saying that the code to work with "%d" would have to
> refer to u.i instead of u?
Yes, to follow the letter of the standard.
The most significant practical issues will come from calling conventions
that pass different types in different ways (doubles seem to be a
problem in practice, for example) and systems where the promoted type
won't match the layout of the same data when its in a union.
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | James Harris <james.harris.1@gmail.com> |
|---|---|
| Date | 2016-10-04 20:40 +0100 |
| Message-ID | <nt10ia$sk9$1@dont-email.me> |
| In reply to | #94452 |
On 04/10/2016 20:24, Ben Bacarisse wrote:
> James Harris <james.harris.1@gmail.com> writes:
>
>> On 04/10/2016 09:49, Ben Bacarisse wrote:
> <snip>
>>> But there are very many other possible problems that come [down] to one
>>> basic problem. If the format has "%d" the corresponding argument must
>>> be an int and not a union that might contain an int.
>>
>> So if I had
>>
>> union any {
>> int16_t i16;
>> int i;
>> double d;
>> } u;
>>
>> I guess you are saying that the code to work with "%d" would have to
>> refer to u.i instead of u?
>
> Yes, to follow the letter of the standard.
That's not a major departure from what I had in mind because I expected
it to follow the model of va_arg wherein the type has to be supplied.
But if I use printf's format codes it could be awkward to pull the
correctly adjusted size of type from the format string, e.g. the
difference between d and ld.
> The most significant practical issues will come from calling conventions
> that pass different types in different ways (doubles seem to be a
> problem in practice, for example) and systems where the promoted type
> won't match the layout of the same data when its in a union.
Not a problem. There was never a question of wanting to kludge it.
This was to be part of exception handling which was to be part of an
app. As I've just said to James (Kuyper) I decided to write the app in
Python for now. It has exception handling built in and automatic
rendering to text.
At some point I'll come back to the C version, though. The Python code
will do at this stage but compiled code is where this will need to go
eventually.
--
James Harris
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2016-10-04 22:51 +0100 |
| Message-ID | <878tu3236k.fsf@bsb.me.uk> |
| In reply to | #94454 |
James Harris <james.harris.1@gmail.com> writes:
> On 04/10/2016 20:24, Ben Bacarisse wrote:
>> James Harris <james.harris.1@gmail.com> writes:
>>
>>> On 04/10/2016 09:49, Ben Bacarisse wrote:
>> <snip>
>>>> But there are very many other possible problems that come [down] to one
>>>> basic problem. If the format has "%d" the corresponding argument must
>>>> be an int and not a union that might contain an int.
>>>
>>> So if I had
>>>
>>> union any {
>>> int16_t i16;
>>> int i;
>>> double d;
>>> } u;
>>>
>>> I guess you are saying that the code to work with "%d" would have to
>>> refer to u.i instead of u?
>>
>> Yes, to follow the letter of the standard.
>
> That's not a major departure from what I had in mind because I
> expected it to follow the model of va_arg wherein the type has to be
> supplied. But if I use printf's format codes it could be awkward to
> pull the correctly adjusted size of type from the format string,
> e.g. the difference between d and ld.
Yes, that going to get fussy, but that's all. If you supply a type that
either is the right one, or promotes to the right one, it must work.
<snip>
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | "James R. Kuyper" <jameskuyper@verizon.net> |
|---|---|
| Date | 2016-10-04 14:25 -0400 |
| Message-ID | <449b9df4-6dda-8898-f9a3-2aa389d36eb3@verizon.net> |
| In reply to | #94320 |
On 09/30/2016 02:53 PM, James Harris wrote:
> On 29/09/2016 23:11, BartC wrote:
...
>> If the format string is:
>>
>> "(%2d-%2d-%4d)"
>>
>> and you start at the first "(", should it stop on (but not including)
>> the first "-", or at the second "%"? And how to make it do that.
>
> Why not:
>
> - copy the literal "(" into the output
> - copy "%2d" into a 'format buffer' and terminate it
> - call snprintf using that buffer
>
> and then repeat the process for the rest of the string?
>
>> There might be some hairy methods of doing this: copying the format
>> string, detecting the start of a format (first "%"), skipping to the
>> start of the next "%", temporarily putting a null there, calling
>> snprintf on the first bit, then restoring the second "%" and repeating
>> with the next bit. With special handling for "%%" and for the last format.
>
> If I omit the size checking for now, how about something like this:
>
> for (;;) { /* Each pair of non-format, format */
>
> /* Copy normal characters straight to the output buffer */
> while (*src != '%' && *src != '\0') {
> *dest++ = *src++;
> }
> if (*src == '\0') {
> break;
> }
>
> /* Copy the format string (starting with %) to a format buffer */
> format = format_buffer;
> *format++ = *src++;
> if (*src == '%') { /* If the source has %% */
> *dest++ = '%';
> }
> else { /* A single percent sign, i.e. starting a format spec */
> for (;;) { /* Until a terminating character */
> ch = *src++;
> if (ch == '\0') ....error....;
> *format++ = ch;
> if (ch ....is one of the terminating characters....) break;
> }
> *format = '\0';
>
> /* Format an argument */
> bytes = sprintf(dest, format, ....current arg ++....);
"current arg ++" is a syntax error unless either "current" or "arg" is a
macro of some kind. I'm not sure what, precisely, it's supposed to mean.
I wouldn't think you want to increment the argument itself. I can
imagine that you might want to increment a pointer to the current
argument, but it's the value of that argument that you need to pass to
sprintf().
I'm not sure I understand all of the "...." in your call to sprintf() -
ordinarily, I'd interpret that as shorthand indicating that your
sprintf() call has other arguments that you're not bothering to specify,
in addition to the ones you've shown explicitly. However, if I
understand your code properly, the format string contains only a single
format specifier extracted from the src string. Unless that format
specifier contains a field width or precision specification of "*"
(which your code does not seem designed to handle), then, as I
understand it, your sprintf() call should have exactly three arguments.
In the context of your original message, my best guess is that you meant
something like the following:
union any {
int i;
long l;
long long ll;
double d;
long double ld;
// etc.
};
struct {
char *text;
union any parms[];
} *p = malloc(sizeof *p + 5*sizeof *p->parms);
// Error handling if p is null
p->text = "array[%d][%ld][%lld] = %f - %lf\n";
p->parms[0].i = 1;
p->parms[1].l = 2L;
p->parms[2].ll = 3LL;
p->parms[3].d = 4.0;
p->parms[4].ld = 5.0L;
union any *current_arg = p->parms;
...
bytes = sprintf(dest, format, *current_arg++);
But 7.21.6.1p9 says that "If any argument is not the correct type for
the corresponding conversion specification, the behavior is undefined.".
There is no specifier for which a "union any" object is the correct
type. The first sizeof(type) bytes of that object should contain an
object of the right type, which might, on some systems, be enough to
make this work properly. If you've actually used an approach on such a
system, you might think it's guaranteed to work. However, in general it
isn't.
For example, consider what happens on a system where the first 4
arguments of integer types with a size less than or equal to sizeof(int)
get passed in specified registers, while the first 4 arguments of
pointer type get passed in a different set of registers, with all other
arguments being loaded onto the stack. I gather that some real-world
systems have ABIs that are at least that complicated, and that the
specification of va_arg() was carefully designed to allow it to do the
complicated handling required by such an ABI. va_list would have to
contain fields that keep track of how many arguments that can be stored
in registers have already been processed, and va_arg() would have to use
those fields to determine how to extract the next argument, and it would
have to update them as appropriate. There's no way, with such an ABI,
that *current_arg will be passed in the correct way if the format
specifies an integer or a pointer type.
What your code needs to do is parse out not only the conversion
specifier (which, if I understand your code above correctly, should be
stored in "ch"), but also the optional length modifier (7.21.6.1p7)
which precedes it, and then use them together to determine the
appropriate member of *current_arg++ to extract in order to pass it on
to sprintf(). For instance, if the length modifier is "l" and the
conversion specifier is 'd' or 'i', then you need to extract the long
integer member of the union:
bytes = sprintf(dest, format, current_arg++->l);
[toc] | [prev] | [next] | [standalone]
| From | James Harris <james.harris.1@gmail.com> |
|---|---|
| Date | 2016-10-04 20:31 +0100 |
| Message-ID | <nt101m$qn2$1@dont-email.me> |
| In reply to | #94448 |
On 04/10/2016 19:25, James R. Kuyper wrote:
> On 09/30/2016 02:53 PM, James Harris wrote:
>> On 29/09/2016 23:11, BartC wrote:
> ...
>>> If the format string is:
>>>
>>> "(%2d-%2d-%4d)"
>>>
>>> and you start at the first "(", should it stop on (but not including)
>>> the first "-", or at the second "%"? And how to make it do that.
>>
>> Why not:
>>
>> - copy the literal "(" into the output
>> - copy "%2d" into a 'format buffer' and terminate it
>> - call snprintf using that buffer
>>
>> and then repeat the process for the rest of the string?
>>
>>> There might be some hairy methods of doing this: copying the format
>>> string, detecting the start of a format (first "%"), skipping to the
>>> start of the next "%", temporarily putting a null there, calling
>>> snprintf on the first bit, then restoring the second "%" and repeating
>>> with the next bit. With special handling for "%%" and for the last
>>> format.
>>
>> If I omit the size checking for now, how about something like this:
>>
>> for (;;) { /* Each pair of non-format, format */
>>
>> /* Copy normal characters straight to the output buffer */
>> while (*src != '%' && *src != '\0') {
>> *dest++ = *src++;
>> }
>> if (*src == '\0') {
>> break;
>> }
>>
>> /* Copy the format string (starting with %) to a format buffer */
>> format = format_buffer;
>> *format++ = *src++;
>> if (*src == '%') { /* If the source has %% */
>> *dest++ = '%';
>> }
>> else { /* A single percent sign, i.e. starting a format spec */
>> for (;;) { /* Until a terminating character */
>> ch = *src++;
>> if (ch == '\0') ....error....;
>> *format++ = ch;
>> if (ch ....is one of the terminating characters....) break;
>> }
>> *format = '\0';
>>
>> /* Format an argument */
>> bytes = sprintf(dest, format, ....current arg ++....);
>
> "current arg ++" is a syntax error unless either "current" or "arg" is a
> macro of some kind. I'm not sure what, precisely, it's supposed to mean.
> I wouldn't think you want to increment the argument itself. I can
> imagine that you might want to increment a pointer to the current
> argument, but it's the value of that argument that you need to pass to
> sprintf().
> I'm not sure I understand all of the "...." in your call to sprintf() -
> ordinarily, I'd interpret that as shorthand indicating that your
> sprintf() call has other arguments that you're not bothering to specify,
> in addition to the ones you've shown explicitly.
Yes, that was the idea. The code was meant only to outline the suggested
approach. I recognise that the code would need to use the right member
of the union.
> However, if I
> understand your code properly, the format string contains only a single
> format specifier extracted from the src string. Unless that format
> specifier contains a field width or precision specification of "*"
> (which your code does not seem designed to handle), then, as I
> understand it, your sprintf() call should have exactly three arguments.
>
> In the context of your original message, my best guess is that you meant
> something like the following:
>
> union any {
> int i;
> long l;
> long long ll;
> double d;
> long double ld;
> // etc.
> };
> struct {
> char *text;
> union any parms[];
> } *p = malloc(sizeof *p + 5*sizeof *p->parms);
> // Error handling if p is null
>
> p->text = "array[%d][%ld][%lld] = %f - %lf\n";
> p->parms[0].i = 1;
> p->parms[1].l = 2L;
> p->parms[2].ll = 3LL;
> p->parms[3].d = 4.0;
> p->parms[4].ld = 5.0L;
>
> union any *current_arg = p->parms;
Exactly.
>
> ...
>
> bytes = sprintf(dest, format, *current_arg++);
I hadn't bottomed out the third argument part. I was thinking it would
be similar to the va_arg mechanism of having to supply the type. But
that's all.
As you went on to say (snipped) I can see I would have to supply the
type by referring to the correct member of the union, and that would
require recognition of the type code used in the format string. Easy for
single character type codes but awkward when size modifiers are involved.
I will maybe come back to this in C. For the time being I have written
the app that this mechanism was to support in <heresy>Python</heresy>!
It has each object know how to render an instance of itself as text. And
that conversion gets invoked automatically if the format string has %s.
It will do for now.
--
James Harris
[toc] | [prev] | [next] | [standalone]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2016-09-29 17:03 +0100 |
| Message-ID | <nsje01$1ma$1@dont-email.me> |
| In reply to | #94244 |
On 29/09/2016 16:20, James Harris wrote:
> Imagine an array holding an arbitrary number of values which need to be
> supplied to one of the printf family of functions. Normally, the values
> passed to such a function would be arguments but in this case they are
> in memory.
>
> Can the elements be passed as arguments?
>
> To make an example, imagine the following struct (untested):
>
> struct {
> char *text;
> union any parms[];
> };
>
> Naturally, text is a pointer to the string and parms is the array. I am
> not sure that a union (definition not shown, for brevity) can be used
> the way that I have used it but you can probably guess that the idea is
> to specify that each element of the array can be any data type specified
> in the union.
The problem with such a union is that each element is the same width
(the maximum needed to accommodate each kind of member). With a normal
set of arguments, there will a mix of 32- and 64-bit values. (It might
not be a problem with a 64-bit system.)
> Putting the union issue aside, the idea is that text and parms would be
> fed to a printf family function such as
>
> snprintf(dest, size, text, P);
I don't think this would work because the arguments need to be on the
stack. This will just push one value (P).
Maybe, the vsnprintf that was mentioned might work, if the mysterious
'va_args' type can be just replaced with a pointer to your argument
list. (If the latter is in the stack format expected.)
> The parms which are in memory and are of arbitrary length need to go in
> position P.
>
> Can that be done in C (without writing the code needed to scan the
> string explicitly)?
This has similarities to my problem of wanting to call an arbitrary
pointer to a DLL function, with an arbitrary number of parameters (which
can also all be different types). The consensus was that where was no
solution in plain C, although some complicated libraries were suggested
('FF' something or other, but I thought that was overkill).
So perhaps vsnprintf is worth pursuing.
--
Bartc
[toc] | [prev] | [next] | [standalone]
| From | gazelle@shell.xmission.com (Kenny McCormack) |
|---|---|
| Date | 2016-09-30 12:20 +0000 |
| Message-ID | <nsll9t$f0q$1@news.xmission.com> |
| In reply to | #94249 |
In article <nsje01$1ma$1@dont-email.me>, BartC <bc@freeuk.com> wrote:
...
>This has similarities to my problem of wanting to call an arbitrary
>pointer to a DLL function, with an arbitrary number of parameters (which
>can also all be different types). The consensus was that where was no
>solution in plain C, although some complicated libraries were suggested
>('FF' something or other, but I thought that was overkill).
OP's problem sounds like a typical academic CLC-type problem - that is, not
a real world question. If both of the following are, in fact, true, then
the advice given in this thread is probably as good as it gets:
1) Solution must be entirely in on-topic standard C.
2) The problem really is limited to printf (and friends). That is,
we're not trying to solve the general problem of calling arbitrary
functions with arbitrary signatures at runtime.
However, if one or both of the above assumptions can be overridden, then
you (and by "you", I mean both the OP and BartC) really should look into
the "libffi" package.
P.S. Usenet posters frequently mis-use, as you did here, the word
"overkill".
>So perhaps vsnprintf is worth pursuing.
No. I actually think that the standardized varargs (aka, stdarg)
functionality is pretty much useless. About its only reason for being is
that it allow you to, under certain circumstances, write wrappers for the
existing *printf() functions.
--
"You can safely assume that you have created God in your own image when
it turns out that God hates all the same people you do." -- Anne Lamott
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2016-09-30 05:55 -0700 |
| Message-ID | <acf27df9-7c42-425e-be08-62f8f49c12fb@googlegroups.com> |
| In reply to | #94281 |
On Friday, September 30, 2016 at 1:20:22 PM UTC+1, Kenny McCormack wrote:
> In article <nsje01$1ma$1@dont-email.me>, BartC <bc@freeuk.com> wrote:
> ...
> >This has similarities to my problem of wanting to call an arbitrary
> >pointer to a DLL function, with an arbitrary number of parameters (which
> >can also all be different types). The consensus was that where was no
> >solution in plain C, although some complicated libraries were suggested
> >('FF' something or other, but I thought that was overkill).
>
> OP's problem sounds like a typical academic CLC-type problem - that is, not
> a real world question. If both of the following are, in fact, true, then
> the advice given in this thread is probably as good as it gets:
>
> 1) Solution must be entirely in on-topic standard C.
> 2) The problem really is limited to printf (and friends). That is,
> we're not trying to solve the general problem of calling arbitrary
> functions with arbitrary signatures at runtime.
>
> However, if one or both of the above assumptions can be overridden, then
> you (and by "you", I mean both the OP and BartC) really should look into
> the "libffi" package.
>
> P.S. Usenet posters frequently mis-use, as you did here, the word
> "overkill".
>
It;s one of the few thigns that C won't let you do. Build an arbitrary va_list at
runtime.
>
> >So perhaps vsnprintf is worth pursuing.
>
> No. I actually think that the standardized varargs (aka, stdarg)
> functionality is pretty much useless. About its only reason for being is
> that it allow you to, under certain circumstances, write wrappers for the
> existing *printf() functions.
>
I'd agree. You can pass name / value pairs using the same interface, but I've
never actually seen it done in real production code. Generally if you need
to pass a variable number of parameters, you wrap them up in some sort
of structure and pass that. Then you can build the list at runtime should
that be necessary.
[toc] | [prev] | [next] | [standalone]
| From | James Harris <james.harris.1@gmail.com> |
|---|---|
| Date | 2016-09-30 20:06 +0100 |
| Message-ID | <nsmd2o$52a$1@dont-email.me> |
| In reply to | #94281 |
On 30/09/2016 13:20, Kenny McCormack wrote:
> In article <nsje01$1ma$1@dont-email.me>, BartC <bc@freeuk.com> wrote:
>> This has similarities to my problem of wanting to call an arbitrary
>> pointer to a DLL function, with an arbitrary number of parameters (which
>> can also all be different types). The consensus was that where was no
>> solution in plain C, although some complicated libraries were suggested
>> ('FF' something or other, but I thought that was overkill).
>
> OP's problem sounds like a typical academic CLC-type problem - that is, not
> a real world question. If both of the following are, in fact, true, then
> the advice given in this thread is probably as good as it gets:
>
> 1) Solution must be entirely in on-topic standard C.
> 2) The problem really is limited to printf (and friends). That is,
> we're not trying to solve the general problem of calling arbitrary
> functions with arbitrary signatures at runtime.
>
> However, if one or both of the above assumptions can be overridden, then
> you (and by "you", I mean both the OP and BartC) really should look into
> the "libffi" package.
The problem in this case is to store data about exceptions. It seems
practical to have an exception made up of
an identifier for the exception's type
parameters
The exception would have an associated string which would be printed if
a stack trace is generated. The parameters are any values which are
relevant to the exception and could be referred to from within the string.
So it's not an academic query. The issue is to render the string with
values filled in.
--
James Harris
[toc] | [prev] | [next] | [standalone]
| From | gazelle@shell.xmission.com (Kenny McCormack) |
|---|---|
| Date | 2016-09-30 22:01 +0000 |
| Message-ID | <nsmnbg$v53$1@news.xmission.com> |
| In reply to | #94321 |
In article <nsmd2o$52a$1@dont-email.me>,
James Harris <james.harris.1@gmail.com> wrote:
...
>The exception would have an associated string which would be printed if
>a stack trace is generated. The parameters are any values which are
>relevant to the exception and could be referred to from within the string.
>
>So it's not an academic query. The issue is to render the string with
>values filled in.
Well, can you answer for my benefit the two questions that I (implicitly)
asked above, namely:
1) Are you limited to standard (on-topic) C?
2) Are you interested in the general solution or do you really only
care about re-implementing printf()?
If the answer to both of these questions is "no", then you really, really,
really need to look into "libffi". "libffi" will make your life better.
However, if the answer to either question is "yes", then I guess you are
stuck with trying to re-implement printf().
--
The randomly chosen signature file that would have appeared here is more than 4
lines long. As such, it violates one or more Usenet RFCs. In order to remain in
compliance with said RFCs, the actual sig can be found at the following web address:
http://www.xmission.com/~gazelle/Sigs/FreeCollege
[toc] | [prev] | [next] | [standalone]
| From | James Harris <james.harris.1@gmail.com> |
|---|---|
| Date | 2016-10-01 09:15 +0100 |
| Message-ID | <nsnrb0$n6o$1@dont-email.me> |
| In reply to | #94341 |
On 30/09/2016 23:01, Kenny McCormack wrote: > In article <nsmd2o$52a$1@dont-email.me>, > James Harris <james.harris.1@gmail.com> wrote: > ... >> The exception would have an associated string which would be printed if >> a stack trace is generated. The parameters are any values which are >> relevant to the exception and could be referred to from within the string. >> >> So it's not an academic query. The issue is to render the string with >> values filled in. > > Well, can you answer for my benefit the two questions that I (implicitly) > asked above, namely: > > 1) Are you limited to standard (on-topic) C? > > 2) Are you interested in the general solution or do you really only > care about re-implementing printf()? Sorry, didn't mean to avoid them. For the first one, Yes, it would be limited to standard C and is to work portably even on different architectures with different word sizes. For the second question, this was primarily about printf-family routines but I would rather find general solutions where possible. > If the answer to both of these questions is "no", then you really, really, > really need to look into "libffi". "libffi" will make your life better. > > However, if the answer to either question is "yes", then I guess you are > stuck with trying to re-implement printf(). I did look at libffi. For my purposes it was too heavy handed. But I made a mental note that it existed. It is a great idea and something I may need one day. -- James Harris
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2016-09-30 23:18 -0700 |
| Message-ID | <4c9d5fe4-9f6f-46ec-92ff-1da78b41e836@googlegroups.com> |
| In reply to | #94321 |
On Friday, September 30, 2016 at 8:06:20 PM UTC+1, James Harris wrote: > > The problem in this case is to store data about exceptions. It seems > practical to have an exception made up of > > an identifier for the exception's type > parameters > > The exception would have an associated string which would be printed if > a stack trace is generated. The parameters are any values which are > relevant to the exception and could be referred to from within the string. > > So it's not an academic query. The issue is to render the string with > values filled in. > So fundamentally you need a structure like this formatstring (eg "%s%p%d") parameters eg asciiz string, undereferenceable memory address, 32 bit integer thinking of it like that, the problem is a straightforwards one of rearranging data. Thinking of it in terms of higher-level language constructs, it becomes intractable. And you can't unfortunately use printf, because it has been specified in terms of higher level constructs rather than to operate on bits. But it's easy enough to implement, especially if you don't need field width and precision.
[toc] | [prev] | [next] | [standalone]
| From | James Harris <james.harris.1@gmail.com> |
|---|---|
| Date | 2016-10-01 09:32 +0100 |
| Message-ID | <nsnsab$ps7$1@dont-email.me> |
| In reply to | #94346 |
On 01/10/2016 07:18, Malcolm McLean wrote: > On Friday, September 30, 2016 at 8:06:20 PM UTC+1, James Harris wrote: >> >> The problem in this case is to store data about exceptions. It seems >> practical to have an exception made up of >> >> an identifier for the exception's type >> parameters >> >> The exception would have an associated string which would be printed if >> a stack trace is generated. The parameters are any values which are >> relevant to the exception and could be referred to from within the string. >> >> So it's not an academic query. The issue is to render the string with >> values filled in. >> > So fundamentally you need a structure like this > > formatstring (eg "%s%p%d") > parameters eg asciiz string, undereferenceable memory address, 32 bit integer Yes, but also with some text among the placeholders. Such a string would be a human-language description and the parameters would provide specifics. In the future the message string could come from a table which was keyed on message id and human language so that the exception report could be rendered in French, Swahili etc. But for now I'll settle for English. > thinking of it like that, the problem is a straightforwards one > of rearranging data. Thinking of it in terms of higher-level > language constructs, it becomes intractable. > > And you can't unfortunately use printf, because it has been specified > in terms of higher level constructs rather than to operate on > bits. But it's easy enough to implement, especially if you don't > need field width and precision. I was trying to take an easy course but that turns out not to be feasible. I will need to do it properly! What I should really do is provide /named/ parameters. Then they can appear in the message text under their names rather than being positional. E.g. "Division failure trying to divide $(numerator) by $(denominator)" Using names would make the message text more recognisable. It would allow parameters to be printed in a different order in different human languages. And it would allow a given parameter to be printed more than once, perhaps in both decimal and hex. This is a lot of work though. And this was only to support the real program I was writing. Aargh! ;-) -- James Harris
[toc] | [prev] | [next] | [standalone]
| From | jacobnavia <jacob@jacob.remcomp.fr> |
|---|---|
| Date | 2016-09-29 18:35 +0200 |
| Message-ID | <nsjfsa$8p0$1@dont-email.me> |
| In reply to | #94244 |
Le 29/09/2016 à 17:20, James Harris a écrit : > Can that be done in C? No. Under modern (64 bits) windows/linux this is not possible since the first four members of the array should be in fixed registers, the rest in memory. Under linux there are more parameters in registers and there the situation is even worst. Besides, you haven't an array. An array has elements of an homogeneous type, printf arguments can be of any type. Worst: If one of the first arguments is too big to pass into a register it will be stored in the stack. BUT under linux, that makes for a free register that will be used for further arguments. The only way to do this is in assembly language
[toc] | [prev] | [next] | [standalone]
| From | James Harris <james.harris.1@gmail.com> |
|---|---|
| Date | 2016-09-29 19:55 +0100 |
| Message-ID | <nsjo3d$816$1@dont-email.me> |
| In reply to | #94252 |
On 29/09/2016 17:35, jacobnavia wrote: > Le 29/09/2016 à 17:20, James Harris a écrit : >> Can that be done in C? > > No. > > Under modern (64 bits) windows/linux this is not possible since the > first four members of the array should be in fixed registers, the rest > in memory. Under linux there are more parameters in registers and there > the situation is even worst. Are args for variable length parameter lists also passed in registers? They would be hard for the va_arg macros to process if they were. > Besides, you haven't an array. An array has elements of an homogeneous > type, printf arguments can be of any type. I have to say I disagree with that. AISI I would have an array of unions. Each element would have the same type, i.e. the declared union. -- James Harris
[toc] | [prev] | [next] | [standalone]
| From | jacobnavia <jacob@jacob.remcomp.fr> |
|---|---|
| Date | 2016-09-29 21:22 +0200 |
| Message-ID | <nsjpkg$e2t$1@dont-email.me> |
| In reply to | #94257 |
Le 29/09/2016 à 20:55, James Harris a écrit : > On 29/09/2016 17:35, jacobnavia wrote: >> Le 29/09/2016 à 17:20, James Harris a écrit : >>> Can that be done in C? >> >> No. >> >> Under modern (64 bits) windows/linux this is not possible since the >> first four members of the array should be in fixed registers, the rest >> in memory. Under linux there are more parameters in registers and there >> the situation is even worst. > > Are args for variable length parameter lists also passed in registers? Yes. > They would be hard for the va_arg macros to process if they were. > Noghtmarish. There is no other word. Not only that they are *HARD*, it is even HARDER to generate code that will implement those macros. I generate a structure with a pointer and a count. If the counter is less than 4, I search the parameters in the saved registers UNLESS the parameter can't fit in a register. If they do not fit (and the structure passed by value is within the first four), I use the pointer to the stack area, and increment it with the size of the structure. After the fourth argument I use the pointer to the stack area only. I do not see how you could do that in C.
[toc] | [prev] | [next] | [standalone]
| From | Barry Schwarz <schwarzb@dqel.com> |
|---|---|
| Date | 2016-09-29 11:20 -0700 |
| Message-ID | <fllqubh7o6fcg84v16442ht345s9rj8qfd@4ax.com> |
| In reply to | #94244 |
On Thu, 29 Sep 2016 16:20:56 +0100, James Harris
<james.harris.1@gmail.com> wrote:
>Imagine an array holding an arbitrary number of values which need to be
>supplied to one of the printf family of functions. Normally, the values
>passed to such a function would be arguments but in this case they are
>in memory.
>
>Can the elements be passed as arguments?
>
>To make an example, imagine the following struct (untested):
>
> struct {
> char *text;
> union any parms[];
> };
>
>Naturally, text is a pointer to the string and parms is the array. I am
>not sure that a union (definition not shown, for brevity) can be used
>the way that I have used it but you can probably guess that the idea is
>to specify that each element of the array can be any data type specified
>in the union.
>
>Putting the union issue aside, the idea is that text and parms would be
>fed to a printf family function such as
>
> snprintf(dest, size, text, P);
>
>The parms which are in memory and are of arbitrary length need to go in
>position P.
>
>Can that be done in C (without writing the code needed to scan the
>string explicitly)?
If you want to deal with an arbitrary number of array elements, you
are going to have to scan the string to compute the size argument.
Consider the following:
dest is a pointer to the final output.
temp is a pointer to working storage large enough for any one
argument's output.
format is a pointer to working storage large enough for any one
format specification (e.g., %d).
text = strtok(text,"%");
sprintf(dest, text); /* handle text prior to first format */
while (text = strtok(NULL,"%")) /* point to char after % */
{
strcat(strcpy(format,"%"),text); /* build format spec with % */
sprintf(temp, format, P++); /* print element, incr to next */
strcat(dest,temp); /* append to final */
}
--
Remove del for email
[toc] | [prev] | [next] | [standalone]
| From | James Harris <james.harris.1@gmail.com> |
|---|---|
| Date | 2016-09-29 20:08 +0100 |
| Message-ID | <nsjoqv$auu$1@dont-email.me> |
| In reply to | #94256 |
On 29/09/2016 19:20, Barry Schwarz wrote:
> On Thu, 29 Sep 2016 16:20:56 +0100, James Harris
> <james.harris.1@gmail.com> wrote:
>
>> Imagine an array holding an arbitrary number of values which need to be
>> supplied to one of the printf family of functions. Normally, the values
>> passed to such a function would be arguments but in this case they are
>> in memory.
>>
>> Can the elements be passed as arguments?
>>
>> To make an example, imagine the following struct (untested):
>>
>> struct {
>> char *text;
>> union any parms[];
>> };
>>
>> Naturally, text is a pointer to the string and parms is the array. I am
>> not sure that a union (definition not shown, for brevity) can be used
>> the way that I have used it but you can probably guess that the idea is
>> to specify that each element of the array can be any data type specified
>> in the union.
>>
>> Putting the union issue aside, the idea is that text and parms would be
>> fed to a printf family function such as
>>
>> snprintf(dest, size, text, P);
>>
>> The parms which are in memory and are of arbitrary length need to go in
>> position P.
>>
>> Can that be done in C (without writing the code needed to scan the
>> string explicitly)?
>
> If you want to deal with an arbitrary number of array elements, you
> are going to have to scan the string to compute the size argument.
What I was thinking of doing is using the return value to find out how
large a buffer was needed. The simplest option is that the first call
would set the size to zero to find out the length needed. Then there
would be a second call to write the buffer.
The sequence, then, would have been basically
size = snprintf(NULL, 0, text, ...) + 1;
buf = if(malloc(size) ....;
snprintf(buf, size, text, ...);
> Consider the following:
> dest is a pointer to the final output.
> temp is a pointer to working storage large enough for any one
> argument's output.
> format is a pointer to working storage large enough for any one
> format specification (e.g., %d).
>
> text = strtok(text,"%");
> sprintf(dest, text); /* handle text prior to first format */
> while (text = strtok(NULL,"%")) /* point to char after % */
> {
> strcat(strcpy(format,"%"),text); /* build format spec with % */
> sprintf(temp, format, P++); /* print element, incr to next */
> strcat(dest,temp); /* append to final */
> }
It seems I'm going to have to do something like that to split the string
at the % signs.
--
James Harris
[toc] | [prev] | [next] | [standalone]
| From | Lőrinczy Zsigmond <nospam@for.me> |
|---|---|
| Date | 2016-10-02 20:15 +0200 |
| Message-ID | <nsrish$1cca$1@gioia.aioe.org> |
| In reply to | #94244 |
Q: In C-code, is it possible to create an argument-list
that can be used as 'va_list'?
A: No. There are va_* macros to _read_ from such argument-list,
but there is no standardized way to _create_ such lists.
You would think an array of intptr_t elements would do the trick,
but it won't work on some platforms:
on those that pass function-parameters in registers (eg amd64)
On such platforms type va_list is not simply a pointer,
it is something like this:
typedef struct {
unsigned int gp_offset;
unsigned int fp_offset;
void *overflow_arg_area;
void *reg_save_area;
} va_list[1];
[toc] | [prev] | [next] | [standalone]
| From | Lőrinczy Zsigmond <nospam@for.me> |
|---|---|
| Date | 2016-10-02 20:19 +0200 |
| Message-ID | <nsrj3r$1cml$1@gioia.aioe.org> |
| In reply to | #94399 |
Nonetheless, it is possible to create a function that takes arguments from such a list: int myprintf (const char *fmt, intptr_t params[])
[toc] | [prev] | [next] | [standalone]
Page 2 of 3 — ← Prev page 1 [2] 3 Next page →
Back to top | Article view | comp.lang.c
csiph-web