arge
arge

Reputation: 635

serial line command parsing

I'm quite new to C and programming in general, I tried to implement a simple command parser function, which should do the following:

Read characters from the serial line and parse for the string "boot\n". If I receive this command I would like to output the name of the application over the serial line. For the command "boot AppName\n", I would start the application with the name given in AppName. How can I achieve this with a quite simple parser, by simple I mean in code complexity?

static void parse_input(void)
{
    uint16_t i;
    char input_buf[30];
    char c;

    read_character(&c);
    if (c == '\n') /* sync character */
        for (i=0; i < 20; i++)
        {
            read_character(&c);
            input_buf[i] = c;
        }
    /* check for string "boot" in input buffer */
    /* maybe string compare? */
}

Thx

Upvotes: 0

Views: 3227

Answers (3)

Jayesh Bhoi
Jayesh Bhoi

Reputation: 25865

The another way for getting serial data and parse as follows i have modified your code

static void parse_input(void)
{
    uint16_t i;
    char input_buf[30];
    char c;
    char cmdBuf[ 1024 ];    /* character input buffer */

    int bufPos = 0;

    memset(cmdBuf,0, 1024);
    for(;;) 
    {
        read_character(&c);
        if( ( c == '\r') || ( c == '\n' ) ) 
        {
          if( ( 1 + bufPos ) < 1024 ) {
                cmdBuf[bufPos++] = '\0';
            }

            if(cmdBuf[0] != 0)
            {
                //serial data available in cmdBuf
                //here your code what to do
               //whether you application or other stuff

            }

            break;
        }
        else 
        {
            if( c == '\b' ) 
            {
                if( bufPos > 0 ) {
                    bufPos--;
                }
            }
            else 
            {
                if( ( 1 + bufPos ) < 1024 ) {
                    cmdBuf[bufPos++] = c;
                }
            }
        }
    }

}

Upvotes: 1

Elias Van Ootegem
Elias Van Ootegem

Reputation: 76395

Given that you're working with a fixed size input buffer, I'd simply settle for something like:

fflush(stdout);
if ((fgets(input_buf, 30, stdin)) == NULL)
{
    puts("No input...");
    return;
}
if ((strncmp(buffer, "boot", 4)) != 0)
{//boot was NOT found
    printf("Command: %s is unknown\n", buffer);
    return;
}
//boot was found, so something like:
char *token = strtok(buffer, " \n");
while(token != NULL)
{
    token = strtok(NULL, " \n");
    if (token) printf("To boot -> %s\n", token);
}

The latter is just simply "chunking" the string using spaces as a delimiter. so token will point to boot after the first call, and then it'll point to whatever words (if any) that follow.

Of course, an easier way would be to do

char *boot_what = buffer+5;
buffer[4] = '\0';

But this implies that the first 5 chars of the buffer are indeed 'b''o''o''t'' ', the easiest way to obtain this is by doing:

char *boot_ptr = strstr(buffer, "boot ");

because strstr returns a pointer to where the string-to-find is found in the given string... ah well, play around with the functions in <string.h> and find what works best for your purpouse.

Upvotes: 3

0xF1
0xF1

Reputation: 6116

I think the best way is using a state machine as follows:

  • Take a integer variable state initially equal to 0 denoting no character found.

  • This variable will be the condition for a switch statement

  • For case 0: keep scanning characters until you find 'b', where you will update state to 1

  • For case 1, likewise, you will be searching for 'o', if you encounter any other character then reset the state to 0.

  • Similarly for 'o' and 't'

  • Whatever follows after "boot" will be your AppName.

Upvotes: 1

Related Questions