#For those familiar with K&C variants of C & older compiler versions where stdarg.h wasn't available

65 messages · Page 1 of 1 (latest)

delicate copper
#

Was thinking about how to make a better variant of printf (under a different name of course) and was thinking about how to do it without stdarg.h so it could compile under earlier compiler versions.

The idea is relatively simple:

#define BAR(T,V,N) &(struct{char const *type=#T,void *data = &(V),size_t size = sizeof(V),void* next = N})
...
foo
(BAR(char const*,"Meaning of life according to HGTTG is ",BAR(int,42,BAR(char,'\n',NULL))));

Is something like that possible with those early versions or would I have to add a function call into that macro to get the simplified input? Also would be nice to get some links for online resources about this sort of stuff. Failed to figure out the right search keywords to find them with.

feral acornBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.

spice osprey
delicate copper
#

Did you even look at the example I just gave of what I wanted to do?

spice osprey
delicate copper
#

Linked list, look closer at the definition of BAR

#

In other words a single argument is used to provide the whole list

spice osprey
#

so you're passing the arguments as a linked list?

delicate copper
#

yes

#

I could live with something like what I'm going to type out but it requires a call and I was hoping to implement the list without the call

spice osprey
#

first issue is that your definition of BAR doesn't even make sense

#

also, const didn't exist in K&R

#

you should remove all const if you want to be following K&R

delicate copper
#
void *bar( char const *type, void *data, size_t size, void *next );
#define BAR(T,V,N) bar(#T,&(V),sizeof(V),N)
spice osprey
#

void is also a new type in C89

#

didn't exist in K&R

delicate copper
#

ah ok, so I'll just shove a define in to switch between normal C and K&R. Also just realised I was mis-remembering the name of K&R

#

Any ideas on how to detect running under K&R with just the preprocessor?

delicate copper
#

Isn't that exclusive to -std=c...?

spice osprey
#

no

delicate copper
#

Oh nice :D

spice osprey
#

though you should be aware, before standardization compilers diverged quite a bit on important details

#

(that's why standardization happened)

delicate copper
#

I'm aware of that, it was just a rando thought and figured if I can do it in my projects I might as well

spice osprey
#

instead there were some tricks used before that (ab)used the way old preprocessors were implemented

#

though strictly following K&R it was impossible

delicate copper
#

ah, that's disappointing. Do you have any links for resources that listed those tricks?

spice osprey
delicate copper
#

oh nice

spice osprey
#

many pre-standard preprocessors were literally text based, not token based; despite K&R saying otherwise

delicate copper
#

guess I'll make a define to switch between the two

spice osprey
#

you can mimic some of the pre-standard preprocessor stuff on gcc

#

with -traditional-cpp

delicate copper
#

Wasn't planning on mimicking it but good to know. Just wanted to simplify life if I ever decide to try porting something I'm developing to K&R

spice osprey
delicate copper
#

they had typedef at least right?

spice osprey
#

no it was just int

delicate copper
#

more defines then 🤷

spice osprey
#

but to be able to traverse it at all, there needs to be a consistent type for all of the links

delicate copper
#

That's the main thing I was asking about, was that possible?

spice osprey
#

have you considered just creating a big array to contain all of the values, then passing that in and extracting the values via memcpy

delicate copper
#

I wanted the simplicity of temporary stack assignment like get with say printf("%i",1+2);

spice osprey
#
unsigned char h[sizeof(int)*3];
int x=1,y=2,z=3;
memcpy(h,&x,sizeof(int));
memcpy(h+sizeof(int),&y,sizeof(int));
memcpy(h+sizeof(int)*2,&z,sizeof(int));
print("%i %i %i\n",h);```something like that
spice osprey
#

that requires creating variables, which in K&R and C89 have to be at the top of the function

delicate copper
#

Hmm, maybe something like this?:```C
struct BAR_T { char *type, char data, int size, struct BAR_T next }
struct BAR_T
bar( struct BAR_T
this, char *type, char *data, int size, struct BAR_T next );
#define BAR(T,V,S,N) bar(&((BAR_T){NULL}),T,&(V),sizeof(T),N)
...
foo( BAR(char
,"Hello World!\n",NULL) )

spice osprey
#

compound literals aren't in K&R or C89

delicate copper
#

Hmm, I have an idea, not fully formulated yet but it involves adding an error member to each node and not returning anything from foo (void foo( struct BAR_T *next );) and defining a do {} while (0) FOO of some kind. Got something to do for now so I'll come back to this later today. Just a rando idea to begin with so not end of the world if I can't push it's support as far back as K&R but will do if I can

delicate copper
#

If alloca's available then I could instead replaced the line ```C
#define BAR(T,V,S,N) bar(&((BAR_T){NULL}),T,&(V),sizeof(T),N)

with```C
#define BAR(T,V,S,N) bar(alloca(sizeof(struct BAR_T)),T,&(V),sizeof(T),N)
spice osprey
delicate copper
#

darn

spice osprey
#

specifying how it works is pretty weird anyway

delicate copper
#

Well for now I'll settle with C89 and come back to the K&R bit later if I get a new idea

feral acornBOT
#

This question is being automatically marked as stale.
If your question has been answered, type !solved.
If your question is not answered feel free to bump the post or re-ask.
Take a look at !howto ask for tips on improving your question.

delicate copper
#

How about the following?```C
#define BAR(T,V) {T,&(V),sizeof(T),1}
#define BARVEC(T,V,S) {T,V,sizeof(T),sizeof(V)/sizeof(V[0])}
#define ERRBAR(PTR) {int,
#define FOO(LIST)
do
{
BAR_T _foo_bar_list[] = { LIST, {"",NULL,0} };
foo( _foo_bar_list, sizeof(_foo_bar_list) / sizeof(BAR_T) );
} while (0)
FOO( BARVEC(char,"Hello "), BAR(int,1), BARVEC(char," World!") );

spice osprey
#

btw, C89 and perhaps some K&R compilers restrict expressions in initializer lists to be constant expressions

rancid tulipBOT
#
Compilation Errors
<source>:10:64: error: macro 'FOO' passed 3 arguments, but takes just 1
   10 | FOO( BARVEC(char,"Hello "), BAR(int,1), BARVEC(char," World!") );
      |                                                                ^
<source>:4:9: note: macro 'FOO' defined here
    4 | #define FOO(LIST) \
      |         ^~~
spice osprey
#

sleepy compiler bot