mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-03-03 19:43:09 +08:00
Merge remote-tracking branch 'upstream/master' into legic_cliparser
This commit is contained in:
commit
6221bb061f
6 changed files with 261 additions and 63 deletions
|
@ -230,59 +230,61 @@ static int usage_lf_find(void) {
|
|||
PrintAndLogEx(NORMAL, _YELLOW_(" lf search 1 u") " - use data from GraphBuffer & search for known and unknown tags");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_lf_tune(void) {
|
||||
PrintAndLogEx(NORMAL, "Continuously measure LF antenna tuning.");
|
||||
PrintAndLogEx(NORMAL, "Press button or Enter to interrupt.");
|
||||
PrintAndLogEx(NORMAL, "Usage: lf tune [h] [n <iter>] [q <divisor> | f <freq>]");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h - This help");
|
||||
PrintAndLogEx(NORMAL, " n <iter> - number of iterations (default: 0=infinite)");
|
||||
PrintAndLogEx(NORMAL, " q <divisor> - Frequency divisor. %d -> 134 kHz, %d -> 125 kHz", LF_DIVISOR_134, LF_DIVISOR_125);
|
||||
PrintAndLogEx(NORMAL, " f <freq> - Frequency in kHz");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdLFTune(const char *Cmd) {
|
||||
int iter = 0;
|
||||
uint8_t divisor = LF_DIVISOR_125;//Frequency divisor
|
||||
bool errors = false;
|
||||
uint8_t cmdp = 0;
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (param_getchar(Cmd, cmdp)) {
|
||||
case 'h':
|
||||
return usage_lf_tune();
|
||||
case 'q':
|
||||
errors |= param_getdec(Cmd, cmdp + 1, &divisor);
|
||||
cmdp += 2;
|
||||
if (divisor < 19) {
|
||||
PrintAndLogEx(ERR, "divisor must be between 19 and 255");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
break;
|
||||
case 'f': {
|
||||
float freq = param_getfloat(Cmd, cmdp + 1, 125);
|
||||
if ((freq < 47) || (freq > 600)) {
|
||||
PrintAndLogEx(ERR, "freq must be between 47 and 600");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
divisor = LF_FREQ2DIV(freq);
|
||||
cmdp += 2;
|
||||
break;
|
||||
}
|
||||
case 'n':
|
||||
iter = param_get32ex(Cmd, cmdp + 1, 0, 10);
|
||||
cmdp += 2;
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "lf tune",
|
||||
"Continuously measure LF antenna tuning.\n"
|
||||
"Press button or <Enter> to interrupt.",
|
||||
"lf tune"
|
||||
);
|
||||
|
||||
char q_str[60];
|
||||
snprintf(q_str, sizeof(q_str), "Frequency divisor. %d -> 134 kHz, %d -> 125 kHz", LF_DIVISOR_134, LF_DIVISOR_125);
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_u64_0("n", "iteration", "<dec>", "number of iterations (default: 0=infinite)"),
|
||||
arg_u64_0("q", "divisor", "<dec>", q_str),
|
||||
arg_dbl0("f", "freq", "<float>", "Frequency in kHz"),
|
||||
arg_lit0(NULL, "bar", "bar style"),
|
||||
arg_lit0(NULL, "mix", "mixed style"),
|
||||
arg_lit0(NULL, "value", "values style"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
uint32_t iter = arg_get_u32_def(ctx, 1, 0);
|
||||
uint8_t divisor = arg_get_u32_def(ctx, 2, LF_DIVISOR_125);
|
||||
double freq = arg_get_dbl_def(ctx, 3, 125);
|
||||
|
||||
bool is_bar = arg_get_lit(ctx, 4);
|
||||
bool is_mix = arg_get_lit(ctx, 5);
|
||||
bool is_value = arg_get_lit(ctx, 6);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (divisor < 19) {
|
||||
PrintAndLogEx(ERR, "divisor must be between 19 and 255");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
//Validations
|
||||
if (errors) return usage_lf_tune();
|
||||
if ((freq < 47) || (freq > 600)) {
|
||||
PrintAndLogEx(ERR, "freq must be between 47 and 600");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
divisor = LF_FREQ2DIV(freq);
|
||||
|
||||
if ((is_bar + is_mix + is_value) > 1) {
|
||||
PrintAndLogEx(ERR, "Select only one output style");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
barMode_t style = session.bar_mode;
|
||||
if (is_bar)
|
||||
style = STYLE_BAR;
|
||||
if (is_mix)
|
||||
style = STYLE_MIXED;
|
||||
if (is_value)
|
||||
style = STYLE_VALUE;
|
||||
|
||||
PrintAndLogEx(INFO, "Measuring LF antenna at " _YELLOW_("%.2f") " kHz, click " _GREEN_("pm3 button") " or press " _GREEN_("Enter") " to exit", LF_DIV2FREQ(divisor));
|
||||
|
||||
|
@ -298,6 +300,13 @@ static int CmdLFTune(const char *Cmd) {
|
|||
}
|
||||
|
||||
params[0] = 2;
|
||||
|
||||
#define MAX_ADC_LF_VOLTAGE 140800
|
||||
uint32_t max = 71000;
|
||||
bool first = true;
|
||||
|
||||
print_progress(0, max, style);
|
||||
|
||||
// loop forever (till button pressed) if iter = 0 (default)
|
||||
for (uint8_t i = 0; iter == 0 || i < iter; i++) {
|
||||
if (kbd_enter_pressed()) {
|
||||
|
@ -308,15 +317,23 @@ static int CmdLFTune(const char *Cmd) {
|
|||
if (!WaitForResponseTimeout(CMD_MEASURE_ANTENNA_TUNING_LF, &resp, 1000)) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(WARNING, "Timeout while waiting for Proxmark LF measure, aborting");
|
||||
return PM3_ETIMEOUT;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((resp.status == PM3_EOPABORTED) || (resp.length != sizeof(uint32_t))) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t volt = resp.data.asDwords[0];
|
||||
PrintAndLogEx(INPLACE, " %u mV / %3u V", volt, (uint32_t)(volt / 1000));
|
||||
if (first) {
|
||||
max = (volt * 1.03);
|
||||
first = false;
|
||||
}
|
||||
if ( volt > max) {
|
||||
max = (volt * 1.03);
|
||||
}
|
||||
print_progress(volt, max, style);
|
||||
}
|
||||
|
||||
params[0] = 3;
|
||||
|
@ -325,7 +342,7 @@ static int CmdLFTune(const char *Cmd) {
|
|||
PrintAndLogEx(WARNING, "Timeout while waiting for Proxmark LF shutdown, aborting");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "\x1b%c[2K\r", 30);
|
||||
PrintAndLogEx(INFO, "Done.");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -21,9 +21,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#ifndef DropField
|
||||
#define DropField() { \
|
||||
clearCommandBuffer(); SendCommandNG(CMD_HF_DROPFIELD, NULL, 0); \
|
||||
}
|
||||
#define DropField() { clearCommandBuffer(); SendCommandNG(CMD_HF_DROPFIELD, NULL, 0); }
|
||||
#endif
|
||||
|
||||
#ifndef DropFieldEx
|
||||
|
@ -48,7 +46,6 @@ typedef enum {
|
|||
FPGA_MEM,
|
||||
} DeviceMemType_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
bool run; // If TRUE, continue running the uart_communication thread
|
||||
bool block_after_ACK; // if true, block after receiving an ACK package
|
||||
|
|
|
@ -55,6 +55,7 @@ int preferences_load(void) {
|
|||
session.overlay_sliders = true;
|
||||
session.show_hints = true;
|
||||
|
||||
session.bar_mode = STYLE_VALUE;
|
||||
// setDefaultPath (spDefault, "");
|
||||
// setDefaultPath (spDump, "");
|
||||
// setDefaultPath (spTrace, "");
|
||||
|
@ -210,6 +211,20 @@ void preferences_save_callback(json_t *root) {
|
|||
default:
|
||||
JsonSaveStr(root, "logging.level", "NORMAL");
|
||||
}
|
||||
|
||||
switch (session.bar_mode) {
|
||||
case STYLE_BAR:
|
||||
JsonSaveStr(root, "show.bar.mode", "bar");
|
||||
break;
|
||||
case STYLE_MIXED:
|
||||
JsonSaveStr(root, "show.bar.mode", "mixed");
|
||||
break;
|
||||
case STYLE_VALUE:
|
||||
JsonSaveStr(root, "show.bar.mode", "value");
|
||||
break;
|
||||
default:
|
||||
JsonSaveStr(root, "show.bar.mode", "value");
|
||||
}
|
||||
/*
|
||||
switch (session.device_debug_level) {
|
||||
case ddbOFF:
|
||||
|
@ -298,6 +313,16 @@ void preferences_load_callback(json_t *root) {
|
|||
|
||||
if (json_unpack_ex(root, &up_error, 0, "{s:b}", "os.supports.colors", &b1) == 0)
|
||||
session.supports_colors = (bool)b1;
|
||||
|
||||
// bar mode
|
||||
if (json_unpack_ex(root, &up_error, 0, "{s:s}", "show.bar.mode", &s1) == 0) {
|
||||
strncpy(tempStr, s1, sizeof(tempStr) - 1);
|
||||
str_lower(tempStr);
|
||||
if (strncmp(tempStr, "bar", 5) == 0) session.bar_mode = STYLE_BAR;
|
||||
if (strncmp(tempStr, "mixed", 5) == 0) session.bar_mode = STYLE_MIXED;
|
||||
if (strncmp(tempStr, "value", 7) == 0) session.bar_mode = STYLE_VALUE;
|
||||
}
|
||||
|
||||
/*
|
||||
// Logging Level
|
||||
if (json_unpack_ex(root, &up_error, 0, "{s:s}", "device.debug.level", &s1) == 0) {
|
||||
|
@ -343,6 +368,17 @@ static int usage_set_debug(void) {
|
|||
PrintAndLogEx(NORMAL, " "_GREEN_("full")" - full debug messages");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int usage_set_bar_mode(void) {
|
||||
PrintAndLogEx(NORMAL, "Usage: pref set barmode <bar | mixed | value>");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " "_GREEN_("help")" - This help");
|
||||
PrintAndLogEx(NORMAL, " "_GREEN_("bar")" - measured values as bar only");
|
||||
PrintAndLogEx(NORMAL, " "_GREEN_("mixed")" - measured values as numbers and bar");
|
||||
PrintAndLogEx(NORMAL, " "_GREEN_("value")" - measured values");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
static int usage_set_devicedebug(void) {
|
||||
PrintAndLogEx(NORMAL, "Usage: pref set devicedebug <off | error | info | debug | extended>");
|
||||
|
@ -521,6 +557,23 @@ static void showPlotSliderState(prefShowOpt_t opt) {
|
|||
PrintAndLogEx(INFO, " %s show plot sliders...... "_WHITE_("off"), prefShowMsg(opt));
|
||||
}
|
||||
|
||||
static void showBarModeState(prefShowOpt_t opt) {
|
||||
|
||||
switch (session.bar_mode) {
|
||||
case STYLE_BAR:
|
||||
PrintAndLogEx(INFO, " %s mode................... "_GREEN_("bar"), prefShowMsg(opt));
|
||||
break;
|
||||
case STYLE_MIXED:
|
||||
PrintAndLogEx(INFO, " %s mode................... "_GREEN_("mixed"), prefShowMsg(opt));
|
||||
break;
|
||||
case STYLE_VALUE:
|
||||
PrintAndLogEx(INFO, " %s mode................... "_GREEN_("value"), prefShowMsg(opt));
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(INFO, " %s mode.................. "_RED_("unknown"), prefShowMsg(opt));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int setCmdEmoji(const char *Cmd) {
|
||||
uint8_t cmdp = 0;
|
||||
|
@ -921,6 +974,57 @@ static int getCmdHelp(const char *Cmd) {
|
|||
}
|
||||
*/
|
||||
|
||||
static int setCmdBarMode(const char *Cmd) {
|
||||
uint8_t cmdp = 0;
|
||||
bool errors = false;
|
||||
bool validValue = false;
|
||||
char strOpt[50];
|
||||
barMode_t newValue = session.bar_mode;
|
||||
|
||||
if (param_getchar(Cmd, cmdp) == 0x00)
|
||||
return usage_set_bar_mode();
|
||||
|
||||
while ((param_getchar(Cmd, cmdp) != 0x00) && !errors) {
|
||||
|
||||
if (param_getstr(Cmd, cmdp++, strOpt, sizeof(strOpt)) != 0) {
|
||||
str_lower(strOpt); // convert to lowercase
|
||||
|
||||
if (strncmp(strOpt, "help", 4) == 0)
|
||||
return usage_set_bar_mode();
|
||||
|
||||
if (strncmp(strOpt, "bar", 3) == 0) {
|
||||
validValue = true;
|
||||
newValue = STYLE_BAR;
|
||||
}
|
||||
if (strncmp(strOpt, "mixed", 5) == 0) {
|
||||
validValue = true;
|
||||
newValue = STYLE_MIXED;
|
||||
}
|
||||
if (strncmp(strOpt, "value", 5) == 0) {
|
||||
validValue = true;
|
||||
newValue = STYLE_VALUE;
|
||||
}
|
||||
|
||||
if (validValue) {
|
||||
if (session.bar_mode != newValue) {// changed
|
||||
showBarModeState(prefShowOLD);
|
||||
session.bar_mode = newValue;
|
||||
showBarModeState(prefShowNEW);
|
||||
preferences_save();
|
||||
} else {
|
||||
PrintAndLogEx(INFO, "nothing changed");
|
||||
showBarModeState(prefShowNone);
|
||||
}
|
||||
} else {
|
||||
PrintAndLogEx(ERR, "invalid option");
|
||||
return usage_set_bar_mode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int getCmdEmoji(const char *Cmd) {
|
||||
showEmojiState(prefShowNone);
|
||||
return PM3_SUCCESS;
|
||||
|
@ -946,27 +1050,35 @@ static int getCmdPlotSlider(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int getCmdBarMode(const char *Cmd) {
|
||||
showBarModeState(prefShowNone);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static command_t getCommandTable[] = {
|
||||
// {"help", getCmdHelp, AlwaysAvailable, "This help"},
|
||||
{"emoji", getCmdEmoji, AlwaysAvailable, "Get emoji display preference"},
|
||||
{"hints", getCmdHint, AlwaysAvailable, "Get hint display preference"},
|
||||
{"barmode", getCmdBarMode, AlwaysAvailable, "Get bar mode preference"},
|
||||
{"clientdebug", getCmdDebug, AlwaysAvailable, "Get client debug level preference"},
|
||||
{"color", getCmdColor, AlwaysAvailable, "Get color support preference"},
|
||||
// {"defaultsavepaths", getCmdSavePaths, AlwaysAvailable, "... to be adjusted next ... "},
|
||||
{"clientdebug", getCmdDebug, AlwaysAvailable, "Get client debug level preference"},
|
||||
{"plotsliders", getCmdPlotSlider, AlwaysAvailable, "Get plot slider display preference"},
|
||||
// {"devicedebug", getCmdDeviceDebug, AlwaysAvailable, "Get device debug level"},
|
||||
{"emoji", getCmdEmoji, AlwaysAvailable, "Get emoji display preference"},
|
||||
{"hints", getCmdHint, AlwaysAvailable, "Get hint display preference"},
|
||||
{"plotsliders", getCmdPlotSlider, AlwaysAvailable, "Get plot slider display preference"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
static command_t setCommandTable[] = {
|
||||
{"help", setCmdHelp, AlwaysAvailable, "This help"},
|
||||
{"barmode", setCmdBarMode, AlwaysAvailable, "Set bar mode"},
|
||||
{"clientdebug", setCmdDebug, AlwaysAvailable, "Set client debug level"},
|
||||
{"color", setCmdColor, AlwaysAvailable, "Set color support"},
|
||||
{"emoji", setCmdEmoji, AlwaysAvailable, "Set emoji display"},
|
||||
{"hints", setCmdHint, AlwaysAvailable, "Set hint display"},
|
||||
{"color", setCmdColor, AlwaysAvailable, "Set color support"},
|
||||
// {"defaultsavepaths", setCmdSavePaths, AlwaysAvailable, "... to be adjusted next ... "},
|
||||
{"clientdebug", setCmdDebug, AlwaysAvailable, "Set client debug level"},
|
||||
{"plotsliders", setCmdPlotSliders, AlwaysAvailable, "Set plot slider display"},
|
||||
// {"devicedebug", setCmdDeviceDebug, AlwaysAvailable, "Set device debug level"},
|
||||
{"plotsliders", setCmdPlotSliders, AlwaysAvailable, "Set plot slider display"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
@ -1009,6 +1121,8 @@ static int CmdPrefShow(const char *Cmd) {
|
|||
showClientDebugState(prefShowNone);
|
||||
showPlotSliderState(prefShowNone);
|
||||
// showDeviceDebugState(prefShowNone);
|
||||
|
||||
showBarModeState(prefShowNone);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -624,4 +624,69 @@ void iceSimple_Filter(int *data, const size_t len, uint8_t k) {
|
|||
}
|
||||
}
|
||||
|
||||
void print_progress(size_t count, uint64_t max, barMode_t style) {
|
||||
|
||||
#define PERCENTAGE(V, T) (100 - (((T - V) * 100) / T))
|
||||
|
||||
/*
|
||||
typedef struct smooth_s {
|
||||
const char *bar;
|
||||
} smooth_t;
|
||||
|
||||
static smooth_t smoothtable[] = {
|
||||
{"\xe2\x96\x8F"},
|
||||
{"\xe2\x96\x8E"},
|
||||
{"\xe2\x96\x8D"},
|
||||
{"\xe2\x96\x8C"},
|
||||
{"\xe2\x96\x8B"},
|
||||
{"\xe2\x96\x8A"},
|
||||
{"\xe2\x96\x89"},
|
||||
{"\xe2\x96\x88"},
|
||||
};
|
||||
*/
|
||||
|
||||
// +1 for \0
|
||||
char *bar = calloc(100 + 1, sizeof(uint8_t));
|
||||
|
||||
uint8_t value = PERCENTAGE(count, max);
|
||||
|
||||
// prefix is added already.
|
||||
memset(bar + strlen(bar), 0x23, value);
|
||||
|
||||
// add spaces
|
||||
memset(bar + strlen(bar), 0x2E, 100 - value);
|
||||
|
||||
// color buffer
|
||||
uint8_t collen = 100 + 1 + 40;
|
||||
char *cbar = calloc(collen, sizeof(uint8_t));
|
||||
|
||||
// Add colors
|
||||
snprintf(cbar, collen, _GREEN_("%.*s"), 60, bar);
|
||||
snprintf(cbar + strlen(cbar), collen - strlen(cbar), _CYAN_("%.*s"), 20, bar + 60);
|
||||
snprintf(cbar + strlen(cbar), collen - strlen(cbar), _YELLOW_("%.*s"), 20, bar + 80);
|
||||
|
||||
uint8_t len = collen + 1 + 1 + 30;
|
||||
char *buffer = calloc(len, sizeof(uint8_t));
|
||||
|
||||
switch(style) {
|
||||
case STYLE_BAR: {
|
||||
sprintf(buffer, "%s", cbar);
|
||||
printf("\b%c[2K\r[" _YELLOW_("=")"] %s", 27, buffer);
|
||||
break;
|
||||
}
|
||||
case STYLE_MIXED: {
|
||||
sprintf(buffer, "%s [ %zu mV / %3u V ]", cbar, count, (uint32_t)(count / 1000));
|
||||
printf("\b%c[2K\r[" _YELLOW_("=")"] %s ", 27, buffer);
|
||||
break;
|
||||
}
|
||||
case STYLE_VALUE: {
|
||||
printf("[" _YELLOW_("=")"] %zu mV / %3u V \r", count, (uint32_t)(count / 1000));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
free(buffer);
|
||||
free(bar);
|
||||
free(cbar);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ extern "C" {
|
|||
|
||||
#define _USE_MATH_DEFINES
|
||||
|
||||
typedef enum {STYLE_BAR, STYLE_MIXED, STYLE_VALUE} barMode_t;
|
||||
typedef enum logLevel {NORMAL, SUCCESS, INFO, FAILED, WARNING, ERR, DEBUG, INPLACE, HINT} logLevel_t;
|
||||
typedef enum emojiMode {ALIAS, EMOJI, ALTTEXT, ERASE} emojiMode_t;
|
||||
typedef enum clientdebugLevel {cdbOFF, cdbSIMPLE, cdbFULL} clientdebugLevel_t;
|
||||
|
@ -45,6 +46,7 @@ typedef struct {
|
|||
bool incognito;
|
||||
// char *defaultPaths[spItemCount]; // Array should allow loop searching for files
|
||||
clientdebugLevel_t client_debug_level;
|
||||
barMode_t bar_mode;
|
||||
// uint8_t device_debug_level;
|
||||
char *history_path;
|
||||
pm3_device *current_device;
|
||||
|
@ -69,6 +71,8 @@ int searchHomeFilePath(char **foundpath, const char *subdir, const char *filenam
|
|||
|
||||
extern pthread_mutex_t print_lock;
|
||||
|
||||
void print_progress(size_t count, uint64_t max, barMode_t style);
|
||||
|
||||
void iceIIR_Butterworth(int *data, const size_t len);
|
||||
void iceSimple_Filter(int *data, const size_t len, uint8_t k);
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -108,4 +108,5 @@ uint32_t bitcount32(uint32_t a);
|
|||
uint64_t bitcount64(uint64_t a);
|
||||
uint32_t leadingzeros32(uint32_t a);
|
||||
uint64_t leadingzeros64(uint64_t a);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue