Skip to content

Instantly share code, notes, and snippets.

@mkmik
Created October 15, 2014 14:44
Show Gist options
  • Save mkmik/f84d7236656b3b1c6b58 to your computer and use it in GitHub Desktop.
Save mkmik/f84d7236656b3b1c6b58 to your computer and use it in GitHub Desktop.
/*
* 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;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment