/* the common types are handled in _begin.def and _end.def, individual .def files are free to create special types as well, but should * provide macros for all the ifdef's supported here for any additions. */ /* for declaring the want-specific sample data structure (used by vmon.h) */ #ifdef VMON_DECLARE_MEMBERS #define vmon_datum_str(_name, _sym, _label, _desc) char *_name; #define vmon_datum_str_array(_name, _sym, _label, _desc) char **_name; #define vmon_datum_char(_name, _sym, _label, _desc) char _name; #define vmon_datum_char_array(_name, _sym, _label, _desc) vmon_char_array_t _name; #define vmon_datum_int(_name, _sym, _label, _desc) int _name; #define vmon_datum_uint(_name, _sym, _label, _desc) unsigned int _name; #define vmon_datum_ulong(_name, _sym, _label, _desc) unsigned long _name; #define vmon_datum_ulonglong(_name, _sym, _label, _desc) unsigned long long _name; #define vmon_datum_long(_name, _sym, _label, _desc) long _name; #define vmon_datum_longlong(_name, _sym, _label, _desc) long long _name; /* leave omissions undefined, they'll get defined as noops at the end of this file */ #endif /* for creating the symbolic constants enumeration (used by vmon.h) */ #ifdef VMON_ENUM_SYMBOLS #define vmon_datum_str(_name, _sym, _label, _desc) VMON_ ## _sym, #define vmon_datum_str_array(_name, _sym, _label, _desc) VMON_ ## _sym, #define vmon_datum_char(_name, _sym, _label, _desc) VMON_ ## _sym, #define vmon_datum_char_array(_name, _sym, _label, _desc) VMON_ ## _sym, #define vmon_datum_int(_name, _sym, _label, _desc) VMON_ ## _sym, #define vmon_datum_uint(_name, _sym, _label, _desc) VMON_ ## _sym, #define vmon_datum_ulong(_name, _sym, _label, _desc) VMON_ ## _sym, #define vmon_datum_ulonglong(_name, _sym, _label, _desc) VMON_ ## _sym, #define vmon_datum_long(_name, _sym, _label, _desc) VMON_ ## _sym, #define vmon_datum_longlong(_name, _sym, _label, _desc) VMON_ ## _sym, /* leave omissions undefined, they'll get defined as noops at the end of this file */ #endif /* for creating an offset table relating symbols to struct member offsets */ #ifdef VMON_INITIALIZE_OFFSET_TABLE /* TODO: error out using #error if VMON_OFFSET_TABLE_STRUCT is not defined */ /* I use the gcc builtin here because it's convenient, otherwise we either do the double macro expansion dance or put the offsetof definition here */ #define vmon_datum_str(_name, _sym, _label, _desc) __builtin_offsetof(VMON_OFFSET_TABLE_STRUCT, _name), #define vmon_datum_str_array(_name, _sym, _label, _desc) __builtin_offsetof(VMON_OFFSET_TABLE_STRUCT, _name), #define vmon_datum_char(_name, _sym, _label, _desc) __builtin_offsetof(VMON_OFFSET_TABLE_STRUCT, _name), #define vmon_datum_char_array(_name, _sym, _label, _desc) __builtin_offsetof(VMON_OFFSET_TABLE_STRUCT, _name), #define vmon_datum_int(_name, _sym, _label, _desc) __builtin_offsetof(VMON_OFFSET_TABLE_STRUCT, _name), #define vmon_datum_uint(_name, _sym, _label, _desc) __builtin_offsetof(VMON_OFFSET_TABLE_STRUCT, _name), #define vmon_datum_ulong(_name, _sym, _label, _desc) __builtin_offsetof(VMON_OFFSET_TABLE_STRUCT, _name), #define vmon_datum_ulonglong(_name, _sym, _label, _desc) __builtin_offsetof(VMON_OFFSET_TABLE_STRUCT, _name), #define vmon_datum_long(_name, _sym, _label, _desc) __builtin_offsetof(VMON_OFFSET_TABLE_STRUCT, _name), #define vmon_datum_longlong(_name, _sym, _label, _desc) __builtin_offsetof(VMON_OFFSET_TABLE_STRUCT, _name), /* no offsets can exist for omitted members, so they're declared as nops */ /* leave omissions undefined, they'll get defined as noops at the end of this file */ #endif /* for creating a lookup table for the member names as strings, indexed by the enumerated symbols */ #ifdef VMON_INITIALIZE_NAME_TABLE #define vmon_datum_str(_name, _sym, _label, _desc) #_name , #define vmon_datum_str_array(_name, _sym, _label, _desc) #_name , #define vmon_datum_char(_name, _sym, _label, _desc) #_name , #define vmon_datum_char_array(_name, _sym, _label, _desc) #_name , #define vmon_datum_int(_name, _sym, _label, _desc) #_name , #define vmon_datum_uint(_name, _sym, _label, _desc) #_name , #define vmon_datum_ulong(_name, _sym, _label, _desc) #_name , #define vmon_datum_ulonglong(_name, _sym, _label, _desc) #_name , #define vmon_datum_long(_name, _sym, _label, _desc) #_name , #define vmon_datum_longlong(_name, _sym, _label, _desc) #_name , /* leave omissions undefined, they'll get defined as noops at the end of this file */ #endif /* for creating a lookup table for the human-readable descriptions, indexed by the enumerated symbols */ #ifdef VMON_INITIALIZE_DESC_TABLE #define vmon_datum_str(_name, _sym, _label, _desc) _desc , #define vmon_datum_str_array(_name, _sym, _label, _desc) _desc , #define vmon_datum_char(_name, _sym, _label, _desc) _desc , #define vmon_datum_char_array(_name, _sym, _label, _desc) _desc , #define vmon_datum_int(_name, _sym, _label, _desc) _desc , #define vmon_datum_uint(_name, _sym, _label, _desc) _desc , #define vmon_datum_ulong(_name, _sym, _label, _desc) _desc , #define vmon_datum_ulonglong(_name, _sym, _label, _desc) _desc , #define vmon_datum_long(_name, _sym, _label, _desc) _desc , #define vmon_datum_longlong(_name, _sym, _label, _desc) _desc , /* leave omissions undefined, they'll get defined as noops at the end of this file */ #endif /* these are different from the symbols, because they ignore the omissions, the definition includes all fields so we can parse the file, * but the symbols only relate to fields we actually store in memory. */ #ifdef VMON_ENUM_PARSER_STATES #define vmon_datum_str(_name, _sym, _label, _desc) VMON_PARSER_STATE_ ## _sym, #define vmon_datum_str_array(_name, _sym, _label, _desc) VMON_PARSER_STATE_ ## _sym, #define vmon_datum_char(_name, _sym, _label, _desc) VMON_PARSER_STATE_ ## _sym, #define vmon_datum_char_array(_name, _sym, _label, _desc) VMON_PARSER_STATE_ ## _sym, #define vmon_datum_int(_name, _sym, _label, _desc) VMON_PARSER_STATE_ ## _sym, #define vmon_datum_uint(_name, _sym, _label, _desc) VMON_PARSER_STATE_ ## _sym, #define vmon_datum_ulong(_name, _sym, _label, _desc) VMON_PARSER_STATE_ ## _sym, #define vmon_datum_ulonglong(_name, _sym, _label, _desc) VMON_PARSER_STATE_ ## _sym, #define vmon_datum_long(_name, _sym, _label, _desc) VMON_PARSER_STATE_ ## _sym, #define vmon_datum_longlong(_name, _sym, _label, _desc) VMON_PARSER_STATE_ ## _sym, #define vmon_omit_n(_n, _sym, _desc) VMON_PARSER_STATE_ ## _sym, #define vmon_omit_literal(_lit, _sym) VMON_PARSER_STATE_ ## _sym, #define vmon_omit_run(_char, _sym) VMON_PARSER_STATE_ ## _sym, #define vmon_omit_str(_name, _sym, _label, _desc) VMON_PARSER_STATE_ ## _sym, #define vmon_omit_str_array(_name, _sym, _label, _desc) VMON_PARSER_STATE_ ## _sym, #define vmon_omit_char(_name, _sym, _label, _desc) VMON_PARSER_STATE_ ## _sym, #define vmon_omit_char_array(_name, _sym, _label, _desc) VMON_PARSER_STATE_ ## _sym, #define vmon_omit_int(_name, _sym, _label, _desc) VMON_PARSER_STATE_ ## _sym, #define vmon_omit_uint(_name, _sym, _label, _desc) VMON_PARSER_STATE_ ## _sym, #define vmon_omit_ulong(_name, _sym, _label, _desc) VMON_PARSER_STATE_ ## _sym, #define vmon_omit_ulonglong(_name, _sym, _label, _desc) VMON_PARSER_STATE_ ## _sym, #define vmon_omit_long(_name, _sym, _label, _desc) VMON_PARSER_STATE_ ## _sym, #define vmon_omit_longlong(_name, _sym, _label, _desc) VMON_PARSER_STATE_ ## _sym, #endif /* most the stuff we need in scope for the parser generated via VMON_IMPLEMENT_PARSER before including the appropriate .def */ #ifdef VMON_PREPARE_PARSER struct _parser { char input; int var_isneg; int var_int; unsigned int var_uint; long var_long; long long var_longlong; unsigned long var_ulong; unsigned long long var_ulonglong; char *var_array; int var_array_alloc_len; int var_array_len; } _p = {}; #define vmon_datum_str(_name, _sym, _label, _desc) #define vmon_datum_str_array(_name, _sym, _label, _desc) #define vmon_datum_char(_name, _sym, _label, _desc) #define vmon_datum_char_array(_name, _sym, _label, _desc) #define vmon_datum_int(_name, _sym, _label, _desc) #define vmon_datum_uint(_name, _sym, _label, _desc) #define vmon_datum_ulong(_name, _sym, _label, _desc) #define vmon_datum_ulonglong(_name, _sym, _label, _desc) #define vmon_datum_long(_name, _sym, _label, _desc) #define vmon_datum_longlong(_name, _sym, _label, _desc) #define vmon_omit_n(_n, _sym, _desc) #define vmon_omit_literal(_lit, _sym) #define vmon_omit_run(_char, _sym) #define vmon_omit_str(_name, _sym, _label, _desc) #define vmon_omit_str_array(_name, _sym, _label, _desc) #define vmon_omit_char(_name, _sym, _label, _desc) #define vmon_omit_char_array(_name, _sym, _label, _desc) #define vmon_omit_int(_name, _sym, _label, _desc) #define vmon_omit_uint(_name, _sym, _label, _desc) #define vmon_omit_ulong(_name, _sym, _label, _desc) #define vmon_omit_ulonglong(_name, _sym, _label, _desc) #define vmon_omit_long(_name, _sym, _label, _desc) #define vmon_omit_longlong(_name, _sym, _label, _desc) #endif /* implements the cases for a simple switch()-based bytestream parser */ #ifdef VMON_IMPLEMENT_PARSER /* TODO: error out if the following aren't defined, these are utilized by the parser FSM: * VMON_PARSER_DELIM <-- what value to treat as a delimiter for string/char arrays (sort of like IFS in bash) * TODO: there are a bunch of variables we assume are available and named a certain way here, * it would be preferable to be able to define those externally and inform the x-macro of their * names etc. */ #define vmon_datum_str(_name, _sym, _label, _desc) case VMON_PARSER_STATE_ ## _sym:\ switch (_p.input) {\ case VMON_PARSER_DELIM:\ /* store accumulated string, reset tmp, and advance */\ if ((*store)->_name) {\ if ( strncmp((*store)->name, _p.var_array, _p.var_array_len) ||\ (*store)->name[_p.var_array_len] != '\0') {\ BITSET((*store)->changed, VMON_ ## _sym);\ changes++;\ }\ free((*store)->name);\ } else {\ BITSET((*store)->changed, VMON_ ## _sym);\ changes++;\ }\ (*store)->_name = strndup(_p.var_array, _p.var_array_len);\ _p.var_array_len = 0;\ state++;\ break;\ default:\ /* accumulate string */\ _p.var_array[_p.var_array_len++] = _p.input;\ break;\ }\ break; #define vmon_datum_str_array(_name, _sym, _label, _desc) case VMON_PARSER_STATE_ ## _sym:\ /* TODO ? */ \ break; #define vmon_datum_char(_name, _sym, _label, _desc) case VMON_PARSER_STATE_ ## _sym:\ if ((*store)->_name != _p.input) {\ BITSET((*store)->changed, VMON_ ## _sym);\ changes++;\ (*store)->_name = _p.input;\ }\ state++;\ break; #define vmon_datum_char_array(_name, _sym, _label, _desc) case VMON_PARSER_STATE_ ## _sym:\ /* TODO */\ /* TODO */\ break; #define vmon_datum_int(_name, _sym, _label, _desc) case VMON_PARSER_STATE_ ## _sym:\ switch (_p.input) {\ case '-':\ /* TODO: we don't verify the '-' is leading... */\ _p.var_isneg = 1;\ break;\ case '0' ... '9':\ _p.var_int *= 10;\ _p.var_int += _p.input - '0';\ break;\ default:\ if (_p.var_isneg) {\ _p.var_int = -_p.var_int;\ _p.var_isneg = 0;\ }\ if ((*store)->_name != _p.var_int) {\ BITSET((*store)->changed, VMON_ ## _sym);\ changes++;\ (*store)->_name = _p.var_int;\ }\ _p.var_int = 0;\ state++;\ break;\ }\ if (state == VMON_PARSER_STATE_ ## _sym)\ /* we want to fall-through when the state advances */\ break; #define vmon_datum_uint(_name, _sym, _label, _desc) case VMON_PARSER_STATE_ ## _sym:\ switch (_p.input) {\ case '0' ... '9':\ _p.var_uint *= 10;\ _p.var_uint += _p.input - '0';\ break;\ default:\ if ((*store)->_name != _p.var_uint) {\ BITSET((*store)->changed, VMON_ ## _sym);\ changes++;\ (*store)->_name = _p.var_uint;\ }\ _p.var_uint = 0;\ state++;\ break;\ }\ if (state == VMON_PARSER_STATE_ ## _sym)\ /* we want to fall-through when the state advances */\ break; #define vmon_datum_ulong(_name, _sym, _label, _desc) case VMON_PARSER_STATE_ ## _sym:\ switch (_p.input) {\ case '0' ... '9':\ _p.var_ulong *= 10;\ _p.var_ulong += _p.input - '0';\ break;\ default:\ if ((*store)->_name != _p.var_ulong) {\ BITSET((*store)->changed, VMON_ ## _sym);\ changes++;\ (*store)->_name = _p.var_ulong;\ }\ _p.var_ulong = 0;\ state++;\ break;\ }\ if (state == VMON_PARSER_STATE_ ## _sym)\ /* we want to fall-through when the state advances */\ break; #define vmon_datum_ulonglong(_name, _sym, _label, _desc) case VMON_PARSER_STATE_ ## _sym:\ switch (_p.input) {\ case '0' ... '9':\ _p.var_ulonglong *= 10;\ _p.var_ulonglong += _p.input - '0';\ break;\ default:\ if ((*store)->_name != _p.var_ulonglong) {\ BITSET((*store)->changed, VMON_ ## _sym);\ changes++;\ (*store)->_name = _p.var_ulonglong;\ }\ _p.var_ulonglong = 0;\ state++;\ break;\ }\ if (state == VMON_PARSER_STATE_ ## _sym)\ /* we want to fall-through when the state advances */\ break; #define vmon_datum_long(_name, _sym, _label, _desc) case VMON_PARSER_STATE_ ## _sym:\ switch (_p.input) {\ case '-':\ /* TODO: we dont verify the '-' is leading... */\ _p.var_isneg = 1;\ break;\ case '0' ... '9':\ _p.var_long *= 10;\ _p.var_long += _p.input - '0';\ break;\ default:\ if (_p.var_isneg) {\ _p.var_long = -_p.var_long;\ _p.var_isneg = 0;\ }\ if ((*store)->_name != _p.var_long) {\ BITSET((*store)->changed, VMON_ ## _sym);\ changes++;\ (*store)->_name = _p.var_long;\ }\ _p.var_long = 0;\ state++;\ break;\ }\ if (state == VMON_PARSER_STATE_ ## _sym)\ /* we want to fall-through when the state advances */\ break; #define vmon_datum_longlong(_name, _sym, _label, _desc) case VMON_PARSER_STATE_ ## _sym:\ switch (_p.input) {\ case '-':\ /* TODO: we dont verify the '-' is leading... */\ _p.var_isneg = 1;\ break;\ case '0' ... '9':\ _p.var_longlong *= 10;\ _p.var_longlong += _p.input - '0';\ break;\ default:\ if (_p.var_isneg) {\ _p.var_longlong = -_p.var_longlong;\ _p.var_isneg = 0;\ }\ if ((*store)->_name != _p.var_longlong) {\ BITSET((*store)->changed, VMON_ ## _sym);\ changes++;\ (*store)->_name = _p.var_longlong;\ }\ _p.var_longlong = 0;\ state++;\ break;\ }\ if (state == VMON_PARSER_STATE_ ## _sym)\ /* we want to fall-through when the state advances */\ break; /* parse but simply skip omitted fields, advance on the delimiter */ #define vmon_omit_n(_n, _sym, _desc) case VMON_PARSER_STATE_ ## _sym:\ _p.var_int++;\ if (_p.var_int >= _n) {\ _p.var_int = 0;\ state++;\ }\ break; #define vmon_omit_literal(_lit, _sym) case VMON_PARSER_STATE_ ## _sym:\ /* TODO make this actually match the literal, for now we skip the length. */ \ _p.var_int++;\ if (_p.var_int >= (sizeof(_lit) - 1)) {\ _p.var_int = 0;\ state++;\ }\ break; #define vmon_omit_run(_char, _sym) case VMON_PARSER_STATE_ ## _sym:\ if (_p.input != _char) {\ state++;\ /* XXX: we fall-through to the next case because this byte belongs to the next state */\ } else {\ break;\ } #define vmon_omit_str(_name, _sym, _label, _desc) case VMON_PARSER_STATE_ ## _sym:\ if (_p.input == VMON_PARSER_DELIM) {\ state++;\ } else {\ break;\ } #define vmon_omit_str_array(_name, _sym, _label, _desc) case VMON_PARSER_STATE_ ## _sym:\ if (_p.input == VMON_PARSER_DELIM) {\ state++;\ } else {\ break;\ } #define vmon_omit_char(_name, _sym, _label, _desc) case VMON_PARSER_STATE_ ## _sym:\ state++;\ break; #define vmon_omit_char_array(_name, _sym, _label, _desc) case VMON_PARSER_STATE_ ## _sym:\ if (_p.input == VMON_PARSER_DELIM) {\ state++;\ } else {\ break;\ } #define vmon_omit_int(_name, _sym, _label, _desc) case VMON_PARSER_STATE_ ## _sym:\ switch (_p.input) {\ case '0' ... '9':\ case '-':\ break;\ default:\ state++;\ break;\ }\ if (state == VMON_PARSER_STATE_ ## _sym)\ /* we want to fall-through when the state advances */\ break;\ #define vmon_omit_uint(_name, _sym, _label, _desc) case VMON_PARSER_STATE_ ## _sym:\ switch (_p.input) {\ case '0' ... '9':\ break;\ default:\ state++;\ break;\ }\ if (state == VMON_PARSER_STATE_ ## _sym)\ /* we want to fall-through when the state advances */\ break; #define vmon_omit_ulong(_name, _sym, _label, _desc) case VMON_PARSER_STATE_ ## _sym:\ switch (_p.input) {\ case '0' ... '9':\ break;\ default:\ state++;\ break;\ }\ if (state == VMON_PARSER_STATE_ ## _sym)\ /* we want to fall-through when the state advances */\ break; #define vmon_omit_ulonglong(_name, _sym, _label, _desc) case VMON_PARSER_STATE_ ## _sym:\ switch (_p.input) {\ case '0' ... '9':\ break;\ default:\ state++;\ break;\ }\ if (state == VMON_PARSER_STATE_ ## _sym)\ /* we want to fall-through when the state advances */\ break; #define vmon_omit_long(_name, _sym, _label, _desc) case VMON_PARSER_STATE_ ## _sym:\ switch (_p.input) {\ case '0' ... '9':\ case '-':\ break;\ default:\ state++;\ break;\ }\ if (state == VMON_PARSER_STATE_ ## _sym)\ /* we want to fall-through when the state advances */\ break; #define vmon_omit_longlong(_name, _sym, _label, _desc) case VMON_PARSER_STATE_ ## _sym:\ switch (_p.input) {\ case '0' ... '9':\ case '-':\ break;\ default:\ state++;\ break;\ }\ if (state == VMON_PARSER_STATE_ ## _sym)\ /* we want to fall-through when the state advances */\ break; #endif /* for convenience, if the omit macros are undefind define them as noops, since that's the most common pattern */ /* XXX TODO: we may need to add some mechanism for informing the VMON_SUPPRESS_UNDEFS clause in _end.def when these * have been automatically defined vs. explicitly defined. When automatically defined, we should undefine them regarldess * of undef suppression. But when they are explicitly defined prior to entering here, we should honor the undef suppression. * I'm going to leave it as-is for now until it bites me in the ass. */ #ifndef vmon_omit_n # define vmon_omit_n(_n, _sym, _desc) #endif #ifndef vmon_omit_literal # define vmon_omit_literal(_lit, _sym) #endif #ifndef vmon_omit_run # define vmon_omit_run(_char, _sym) #endif #ifndef vmon_omit_str # define vmon_omit_str(_name, _sym, _label, _desc) #endif #ifndef vmon_omit_str_array # define vmon_omit_str_array(_name, _sym, _label, _desc) #endif #ifndef vmon_omit_char # define vmon_omit_char(_name, _sym, _label, _desc) #endif #ifndef vmon_omit_char_array # define vmon_omit_char_array(_name, _sym, _label, _desc) #endif #ifndef vmon_omit_int # define vmon_omit_int(_name, _sym, _label, _desc) #endif #ifndef vmon_omit_uint # define vmon_omit_uint(_name, _sym, _label, _desc) #endif #ifndef vmon_omit_ulong # define vmon_omit_ulong(_name, _sym, _label, _desc) #endif #ifndef vmon_omit_ulonglong # define vmon_omit_ulonglong(_name, _sym, _label, _desc) #endif #ifndef vmon_omit_long # define vmon_omit_long(_name, _sym, _label, _desc) #endif #ifndef vmon_omit_longlong # define vmon_omit_longlong(_name, _sym, _label, _desc) #endif