|
/* |
|
* Dummy port of the Amiga tag based extensible api. See: |
|
* |
|
* http://amigadev.elowar.com/read/ADCD_2.1/Includes_and_Autodocs_3._guide/node03D6.html |
|
* |
|
* |
|
* note that the amiga api relied on the fact that the calling convention was |
|
* very simple so the vararg stub could just take the pointer to the last argument, |
|
* and get an array of TagItem records. |
|
* |
|
* see: |
|
* http://amigadev.elowar.com/read/ADCD_2.1/Includes_and_Autodocs_3._guide/node03D4.html |
|
* |
|
* we cannot do the same with portable C, so this port uses a slightly different approach, |
|
* taking some ideas from https://gist.github.com/mmikulicic/9a02109c8f3b66092038 . |
|
* |
|
*/ |
|
|
|
|
|
#include <stdarg.h> |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
|
|
typedef int (*tag_t)(va_list argp, void* data); |
|
|
|
int TAG_END(va_list argp, void* data) { |
|
return -1; |
|
} |
|
|
|
void process_tags(va_list argp, tag_t tag, void *data) { |
|
while(1) { |
|
if (tag(argp, data) == -1) { |
|
break; |
|
} |
|
tag = va_arg(argp, tag_t); |
|
} |
|
} |
|
|
|
// ----- ns_send |
|
|
|
typedef struct { |
|
int deadline; |
|
int n_headers; |
|
} ns_send_opts_t; |
|
|
|
|
|
int ns_deadline(va_list argp, void* data) { |
|
ns_send_opts_t* opts = (ns_send_opts_t*)data; |
|
opts->deadline = va_arg(argp, int); |
|
|
|
printf("processing ns_deadline: %d\n", opts->deadline); |
|
return 0; |
|
} |
|
|
|
// I'm not saying this should be allowed, but it's technically possible |
|
// to consume multiple arguments instead of bundling them into a struct. |
|
int ns_header(va_list argp, void* data) { |
|
char *key = va_arg(argp, char*); |
|
char *value = va_arg(argp, char*); |
|
printf("processing ns_header: %s:%s\n", key, value); |
|
|
|
ns_send_opts_t* opts = (ns_send_opts_t*)data; |
|
opts->n_headers++; |
|
return 0; |
|
} |
|
|
|
|
|
void ns_send_tags(char* addr, char* body, tag_t tag, ...) { |
|
// some default values |
|
ns_send_opts_t opts = {-1, 0}; |
|
|
|
va_list argp; |
|
va_start(argp, tag); |
|
process_tags(argp, tag, &opts); |
|
va_end(argp); |
|
|
|
printf("sending %s to %s, deadline: %d, num headers: %d\n", body, addr, opts.deadline, opts.n_headers); |
|
} |
|
|
|
void ns_send(char* addr, char* body) { |
|
ns_send_tags(addr, body, TAG_END); |
|
} |
|
|
|
|
|
int main() { |
|
ns_send("foo", "bar"); |
|
ns_send_tags("foo", "bar", ns_header, "test", "blah", ns_deadline, 3600, TAG_END); |
|
|
|
return 0; |
|
} |