func for matching level strings

master
Ondřej Hruška 9 years ago
parent 3bef041547
commit 588bb22270
  1. 6
      Makefile
  2. 20
      main.c
  3. BIN
      main.elf
  4. 86
      scpi_parser.c
  5. 4
      scpi_parser.h

@ -0,0 +1,6 @@
all: main.c scpi_parser.c scpi_parser.h
gcc main.c scpi_parser.c -o main.elf
run: all
./main.elf

@ -7,8 +7,8 @@ void cmd_APPL_SIN_cb(const SCPI_argval_t *args);
void cmd_APPL_TRI_cb(const SCPI_argval_t *args); void cmd_APPL_TRI_cb(const SCPI_argval_t *args);
void cmd_FREQ_cb(const SCPI_argval_t *args); void cmd_FREQ_cb(const SCPI_argval_t *args);
const uint16_t scpi_cmd_lang_len = 4;
const SCPI_command_t scpi_cmd_lang[] = { const SCPI_command_t scpi_cmd_lang[4] = {
{ {
.level_cnt = 1, .levels = {"*IDN?"}, .level_cnt = 1, .levels = {"*IDN?"},
.param_cnt = 0, .params = {}, .param_cnt = 0, .params = {},
@ -60,5 +60,19 @@ void cmd_FREQ_cb(const SCPI_argval_t *args)
int main(int argc, const char**argv) int main(int argc, const char**argv)
{ {
const char *inp = argv[1]; const char *inp = argv[1];
printf("cmd lang len = %d\n", (int) sizeof(scpi_cmd_lang)/sizeof(SCPI_command_t));
// printf("%d\n", char_equals_ci('a','A'));
// printf("%d\n", char_equals_ci('z','z'));
// printf("%d\n", char_equals_ci('z','Z'));
// printf("%d\n", char_equals_ci('M','M'));
// printf("%d\n", char_equals_ci('M','q'));
// printf("%d\n", char_equals_ci('*','*'));
// printf("%d\n", char_equals_ci('a',' '));
// printf("%d\n", level_str_matches("A","A"));
// printf("%d\n", level_str_matches("AbCdE","ABCDE"));
// printf("%d\n", level_str_matches("*IDN?","*IDN?"));
// printf("%d\n", level_str_matches("*IDN?","*IDN"));
// printf("%d\n", level_str_matches("MEAS","MEASure"));
//printf("%d\n", level_str_matches("*FBAZ?","*FxyzBAZ?"));
} }

Binary file not shown.

@ -6,7 +6,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
typedef enum { typedef enum {
PARS_COMMAND, PARS_COMMAND,
PARS_ARG, // collect generic arg, terminated with comma or newline. Leading and trailing whitespace ignored. PARS_ARG, // collect generic arg, terminated with comma or newline. Leading and trailing whitespace ignored.
@ -60,9 +59,14 @@ static void pars_match_level(void); // match charbuf content to a level, advance
// char matching // char matching
#define INRANGE(c, a, b) ((c) >= (a) && (c) <= (b)) #define INRANGE(c, a, b) ((c) >= (a) && (c) <= (b))
#define IS_WHITESPACE(c) (INRANGE((c), 0, 9) || INRANGE((c), 11, 32)) #define IS_WHITESPACE(c) (INRANGE((c), 0, 9) || INRANGE((c), 11, 32))
#define IS_IDENT_CHAR(c) (INRANGE((c), 'a', 'z') || INRANGE((c), 'A', 'Z') || INRANGE((c), '0', '9') || (c) == '_')
#define IS_INT_CHAR(c) INRANGE((c), '0', '9') #define IS_LCASE_CHAR(c) INRANGE((c), 'a', 'z')
#define IS_FLOAT_CHAR(c) (IS_INT_CHAR((c)) || (c) == '.' || (c) == 'e' || (c) == 'E' || (e) == '+' || (e) == '-') #define IS_UCASE_CHAR(c) INRANGE((c), 'A', 'Z')
#define IS_NUMBER_CHAR(c) INRANGE((c), '0', '9')
#define IS_IDENT_CHAR(c) (IS_LCASE_CHAR((c)) || IS_UCASE_CHAR((c)) || IS_NUMBER_CHAR((c)) || (c) == '_')
#define IS_INT_CHAR(c) IS_NUMBER_CHAR((c))
#define IS_FLOAT_CHAR(c) (IS_NUMBER_CHAR((c)) || (c) == '.' || (c) == 'e' || (c) == 'E' || (e) == '+' || (e) == '-')
static void pars_reset_cmd(void) static void pars_reset_cmd(void)
@ -123,7 +127,7 @@ void scpi_receive_byte(const uint8_t b)
// invalid or delimiter // invalid or delimiter
if (IS_WHITESPACE(c)) { if (IS_WHITESPACE(c)) {
pars_cmd_space(); // whitespace in command - end of command? // pars_cmd_space(); // whitespace in command - end of command?
break; break;
} }
@ -133,11 +137,11 @@ void scpi_receive_byte(const uint8_t b)
break; break;
case '\n': // line terminator case '\n': // line terminator
pars_cmd_newline(); // pars_cmd_newline();
break; break;
case ';': // ends a command, does not reset cmd path. case ';': // ends a command, does not reset cmd path.
pars_cmd_semicolon(); // pars_cmd_semicolon();
break; break;
default: default:
@ -159,9 +163,6 @@ void scpi_receive_byte(const uint8_t b)
} }
// whitespace (INRANGE(c, 0, 9) || INRANGE(c, 11, 32))
static void pars_cmd_colon(void) static void pars_cmd_colon(void)
{ {
if (pstate.charbuf_ptr == 0) { if (pstate.charbuf_ptr == 0) {
@ -182,6 +183,71 @@ static void pars_cmd_colon(void)
} }
} }
#define CHAR_TO_LOWER(ucase) ((ucase) + 32)
#define CHAR_TO_UPPER(lcase) ((lcase) - 32)
/** Check if chars equal, ignore case */
static bool char_equals_ci(char a, char b)
{
if (IS_LCASE_CHAR(a)) {
if (IS_LCASE_CHAR(b)) {
return a == b;
} else if (IS_UCASE_CHAR(b)) {
return a == CHAR_TO_LOWER(b);
} else {
return false;
}
} else if (IS_UCASE_CHAR(a)) {
if (IS_UCASE_CHAR(b)) {
return a == b;
} else if (IS_LCASE_CHAR(b)) {
return a == CHAR_TO_UPPER(b);
} else {
return false;
}
} else {
return a == b; // exact match, not letters
}
}
/** Check if command matches a pattern */
static bool level_str_matches(const char *test, const char *pattern)
{
const uint8_t testlen = strlen(test);
uint8_t pi, ti;
for (pi = 0, ti = 0; pi < strlen(pattern); pi++) {
if (ti > testlen) return false; // not match
const char pc = pattern[pi];
const char tc = test[ti]; // may be at the \0 terminator
if (IS_LCASE_CHAR(pc)) {
// optional char
if (char_equals_ci(pc, tc)) {
ti++; // advance test string
}
continue; // next pi - tc stays in place
} else {
// require exact match (case insensitive)
if (char_equals_ci(pc, tc)) {
ti++;
} else {
return false;
}
}
}
return (ti >= testlen);
}
static void pars_match_level(void) static void pars_match_level(void)
{ {

@ -45,4 +45,8 @@ typedef struct {
} SCPI_command_t; } SCPI_command_t;
extern const uint16_t scpi_cmd_lang_len; // number of commands
extern const SCPI_command_t scpi_cmd_lang[]; extern const SCPI_command_t scpi_cmd_lang[];
// --------------- functions --------------------

Loading…
Cancel
Save