mirror of https://github.com/GOSTSec/sgminer
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
151 lines
4.3 KiB
151 lines
4.3 KiB
#include <stdio.h> |
|
#include <string.h> |
|
#include "config.h" |
|
|
|
/** |
|
* typesafe_cb - macros for safe callbacks. |
|
* |
|
* The basis of the typesafe_cb header is typesafe_cb_cast(): a |
|
* conditional cast macro. If an expression exactly matches a given |
|
* type, it is cast to the target type, otherwise it is left alone. |
|
* |
|
* This allows us to create functions which take a small number of |
|
* specific types, rather than being forced to use a void *. In |
|
* particular, it is useful for creating typesafe callbacks as the |
|
* helpers typesafe_cb(), typesafe_cb_preargs() and |
|
* typesafe_cb_postargs() demonstrate. |
|
* |
|
* The standard way of passing arguments to callback functions in C is |
|
* to use a void pointer, which the callback then casts back to the |
|
* expected type. This unfortunately subverts the type checking the |
|
* compiler would perform if it were a direct call. Here's an example: |
|
* |
|
* static void my_callback(void *_obj) |
|
* { |
|
* struct obj *obj = _obj; |
|
* ... |
|
* } |
|
* ... |
|
* register_callback(my_callback, &my_obj); |
|
* |
|
* If we wanted to use the natural type for my_callback (ie. "void |
|
* my_callback(struct obj *obj)"), we could make register_callback() |
|
* take a void * as its first argument, but this would subvert all |
|
* type checking. We really want register_callback() to accept only |
|
* the exactly correct function type to match the argument, or a |
|
* function which takes a void *. |
|
* |
|
* This is where typesafe_cb() comes in: it uses typesafe_cb_cast() to |
|
* cast the callback function if it matches the argument type: |
|
* |
|
* void _register_callback(void (*cb)(void *arg), void *arg); |
|
* #define register_callback(cb, arg) \ |
|
* _register_callback(typesafe_cb(void, void *, (cb), (arg)), \ |
|
* (arg)) |
|
* |
|
* On compilers which don't support the extensions required |
|
* typesafe_cb_cast() and friend become an unconditional cast, so your |
|
* code will compile but you won't get type checking. |
|
* |
|
* Example: |
|
* #include <ccan/typesafe_cb/typesafe_cb.h> |
|
* #include <stdlib.h> |
|
* #include <stdio.h> |
|
* |
|
* // Generic callback infrastructure. |
|
* struct callback { |
|
* struct callback *next; |
|
* int value; |
|
* int (*callback)(int value, void *arg); |
|
* void *arg; |
|
* }; |
|
* static struct callback *callbacks; |
|
* |
|
* static void _register_callback(int value, int (*cb)(int, void *), |
|
* void *arg) |
|
* { |
|
* struct callback *new = malloc(sizeof(*new)); |
|
* new->next = callbacks; |
|
* new->value = value; |
|
* new->callback = cb; |
|
* new->arg = arg; |
|
* callbacks = new; |
|
* } |
|
* #define register_callback(value, cb, arg) \ |
|
* _register_callback(value, \ |
|
* typesafe_cb_preargs(int, void *, \ |
|
* (cb), (arg), int),\ |
|
* (arg)) |
|
* |
|
* static struct callback *find_callback(int value) |
|
* { |
|
* struct callback *i; |
|
* |
|
* for (i = callbacks; i; i = i->next) |
|
* if (i->value == value) |
|
* return i; |
|
* return NULL; |
|
* } |
|
* |
|
* // Define several silly callbacks. Note they don't use void *! |
|
* #define DEF_CALLBACK(name, op) \ |
|
* static int name(int val, int *arg) \ |
|
* { \ |
|
* printf("%s", #op); \ |
|
* return val op *arg; \ |
|
* } |
|
* DEF_CALLBACK(multiply, *); |
|
* DEF_CALLBACK(add, +); |
|
* DEF_CALLBACK(divide, /); |
|
* DEF_CALLBACK(sub, -); |
|
* DEF_CALLBACK(or, |); |
|
* DEF_CALLBACK(and, &); |
|
* DEF_CALLBACK(xor, ^); |
|
* DEF_CALLBACK(assign, =); |
|
* |
|
* // Silly game to find the longest chain of values. |
|
* int main(int argc, char *argv[]) |
|
* { |
|
* int i, run = 1, num = argv[1] ? atoi(argv[1]) : 0; |
|
* |
|
* for (i = 1; i < 1024;) { |
|
* // Since run is an int, compiler checks "add" does too. |
|
* register_callback(i++, add, &run); |
|
* register_callback(i++, divide, &run); |
|
* register_callback(i++, sub, &run); |
|
* register_callback(i++, multiply, &run); |
|
* register_callback(i++, or, &run); |
|
* register_callback(i++, and, &run); |
|
* register_callback(i++, xor, &run); |
|
* register_callback(i++, assign, &run); |
|
* } |
|
* |
|
* printf("%i ", num); |
|
* while (run < 56) { |
|
* struct callback *cb = find_callback(num % i); |
|
* if (!cb) { |
|
* printf("-> STOP\n"); |
|
* return 1; |
|
* } |
|
* num = cb->callback(num, cb->arg); |
|
* printf("->%i ", num); |
|
* run++; |
|
* } |
|
* printf("-> Winner!\n"); |
|
* return 0; |
|
* } |
|
* |
|
* License: LGPL (2 or any later version) |
|
* Author: Rusty Russell <rusty@rustcorp.com.au> |
|
*/ |
|
int main(int argc, char *argv[]) |
|
{ |
|
if (argc != 2) |
|
return 1; |
|
|
|
if (strcmp(argv[1], "depends") == 0) { |
|
return 0; |
|
} |
|
|
|
return 1; |
|
}
|
|
|