How to Develop a Command Line Parser in C++?

CommandLineParser

Command Line Parser
Goal
Strengthening students’ skills in gaining new knowledge in C coding particularly, with string
processing and pointers
Description
Homeworks 3 and 4 will involve developing a basic shell (command line interpreter) for Linux.
In this assignment, HW3, you will build the portion of the shell that parses a user-entered command
sequence so that it can later be executed. In this portion of the assignment you are only building a
parser for the commands, you don’t actually execute them yet. Instead you print out the details of
the parsed commands.
You are given a skeleton code and required to build on it to achieve this task. The user entry is a
number of commands with their arguments, if any, separated by pipes, if any.
Here are some valid, sample inputs:
ls –la
ls –la | wc –l
ls | grep “something” | sort | wc –l
Functionality
A basic shell is just an infinite loop that prints a print, receives a line of user input, and executes the appropriate programs. In this assignment, you will only write the parser. Consider the following pseudo-code for this assignment:
Ø Infinite loop
ü The program displays a prompt,
ü The user enters a commands on a line,
ü The program reads the line,
§ if the user entry is spaces or empty line, then perform next iteration of the loop i.e., continue
§ if the user entry is a special command, exit, then exit the loop i.e., break
ü Parse the commands, i.e., recognize the commands and store them in an array of a given formatted structure,
ü Call a provided function, print_commands, to display the information about  these commands
ü Display the prompt again, waiting for the user to enter another command.
Ø end

Solution:

get_commands.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include “command.h”
#define TOKEN_BUFSIZE 64
#define TOKEN_DELIM ” \t\r\n\a”
int get_commands(char* line, struct command mycommands[])
{
 
    /*
    TODO: Fill in code here to do the following:
    -Parse the line and fill in the mycommands array
    -Return the number of commands read
    */
   int bufsize =TOKEN_BUFSIZE, position = 0;
  char **tokens = malloc(bufsize * sizeof(char*));
  char *token, **tokens_backup;
  int command_count=0;
  int no_of_args = 1;
  int order = 0;
  if (!tokens) {
    exit(EXIT_FAILURE);
  }

  token = strtok(line, TOKEN_DELIM);
  while (token != NULL) {
    tokens[position] = token;
   if(strcmp(token,”|”) == 0)
            {
        command_count ++;
        order ++;
                position = 0;
                no_of_args = 1;
    token = strtok(NULL, TOKEN_DELIM);
        }
   if(position == 0)
{
    mycommands[command_count].comm = token;
    mycommands[command_count].order= order;
}
   else
   {
    mycommands[command_count].args[no_of_args]  =  (char *)malloc(TOKEN_BUFSIZE);
    memcpy(mycommands[command_count].args[no_of_args],token,TOKEN_BUFSIZE);
    mycommands[command_count].no_args= no_of_args;
     no_of_args ++;
   }
   position++;
   
    if (position >= bufsize) {
      bufsize += TOKEN_BUFSIZE;
      tokens_backup = tokens;
      tokens = realloc(tokens, bufsize * sizeof(char*));
      if (!tokens) {
        free(tokens_backup);
        fprintf(stderr, “lsh: allocation error\n”);
        exit(EXIT_FAILURE);
      }
    }

    token = strtok(NULL, TOKEN_DELIM);
  }
  tokens[position] = NULL;
    return command_count+1;
}

 

parser.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include “command.h”
#include “print_commands.h”
#include “get_commands.h”
int status = 1;
char *readline(void);

int main()
{
char *prompt = “cmps405> “;
char **args;
int no_of_commands;
char line[MAX_CHAR_LINE];
struct command mycommands[MAX_COMMANDS];
while(1)
{
/*
TODO: Fill in code here to do the following:
-Display the prompt
-Read a line from the user
-Call the function get_commands to parse the line and place
its contents into mycommands
-Call the function print_commands to print the commands in mycommands

Note:
-If the user enters “exit” then this program should quit.
*/

printf(“%s”,prompt);
memset(line,’\0′,MAX_CHAR_LINE);
memcpy(line,readline(),MAX_CHAR_LINE);
if(strcmp(line,”exit”) == 0)
break;
else if(strcmp(line,”\r\n”) == 0)
{}
else
{
no_of_commands = get_commands(line,mycommands);
print_commands(mycommands,no_of_commands);
}

}
return 0;
}

char *readline(void)
{
int bufsize = MAX_CHAR_LINE;
int position = 0;
char *buffer = malloc(sizeof(char) * bufsize);
int c;

if (!buffer) {
exit(EXIT_FAILURE);
}

while (1) {
// Read a character
c = getchar();
if (c == EOF || c == ‘\n’) {
buffer[position] = ‘\0’;
return buffer;
} else {
buffer[position] = c;
}
position++;
if (position >= bufsize) {
bufsize += MAX_CHAR_LINE;
buffer = realloc(buffer, bufsize);
if (!buffer) {
fprintf(stderr, “allocation error\n”);
exit(EXIT_FAILURE);
}
}
}
}

print_commands.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include “command.h”

void print_commands(struct command mycommands[], int no_commands)
{
    int i;
    for(i=0; i<no_commands; i++)
    {
        int j;
        fputs(“command order: “, stdout);
        fprintf(stdout,”%d”,mycommands[i].order);
        fputs(“\n”,stdout);
        fputs(“command: “, stdout);
        fputs(mycommands[i].comm, stdout);
        fputs(“\n”,stdout);
        fputs(“no of args: “, stdout);
        fprintf(stdout,”%d”,mycommands[i].no_args);
        fputs(“\n”,stdout);
        fputs(“args: “, stdout);
        for(j=1; j<=mycommands[i].no_args; j++)
        {
            fputs(mycommands[i].args[j], stdout);
            fputs(” “,stdout);
        }
        fputs(“\n”,stdout);
    }
}

Output Screenshot:

Command Line Parser

Command Line Parser

Command Line Parser

compile,Command Line Parser

LEAVE A REPLY

Please enter your comment!
Please enter your name here