PDA

View Full Version : command line parser in C


mile1982
09-06-2004, 08:27 PM
hey peeps

got a little problem. heres what i need to do. write a function that takes a line of input text and parses it into some sort of command structure containing info about the program name, arguments, and optios fro I/O redirection, pipes and background jobs.
it needs to look smth like this:

if "/bin/sleep 10 & ls -lt xyz > junk" was entered:

command[0]:
com_pathname=/bin/sleep
argc=2
argv[0]=/bin/sleep
argv[1]=10
#######
redirect_in=NULL
redirect_out=NULL
com_suffix=&

command[1]:
com_pathname=ls
argc=3
argv[0]=ls
argv[1]=-lt
argv[2]=xyz
#######
redirect_in=NULL
redirect_out=junk
com_suffix=

---
what i have achieved so far is that i have separeted the command line input into tokens. now how can separate those tokens into commands, eg: know where the first command ends and the next beging??

thanks
mile1982

i3839
09-06-2004, 10:02 PM
The commandline is already parsed into seperate tokens for you, you can find them in argv[], so not sure what you mean there. Oh wait, you mean you're writing a shell like thing which is parsing input data?

When one command begins and the other ends depend on what you're parsing of course. If it's a shell script then you need to know about all the special characters like ' " ` & ; | $ > etc. and look for them. If you don't encounter something special then pass them as arguments for the program which is the first token. If you do, then handle it according to the meaning of such token.

Nope
09-07-2004, 06:38 AM
As far as I can see all the things you need seperated have a ' ' (space) in
between. So you have a lot different possibilities to get them seperated.


You can look with "pointer=strchr(inputstring,' ');" for the first space in the
string, that would result in something like that:


char *p;
char *lauf=inputstring;
char *result[50];
int i=0;

do
{
result[i++]=lauf; /* save last startpoint */

p=strchr(lauf,' ');

if(p!=0) /* a space was found */
{
*p=0; /* replace space with '\0'
lauf=p+1; /* next start after last found space */
}

} while((p!=0)&&(i<49));

result[i]=0; /* this kind of list is normally finished with a NULL pointer */


Now you'll have the string seperated and the start of each is saved in the
result char pointer array. The filled in '\0' will mark the end of each for
further processing. The number of strings is in 'i'. So you can use a normal
for(;;) to check the strings for their content. Nice thing is also that this is
the zero-copy version of the whole thing...

There are several other possibilities to do this. You could also walk
through the whole inputstring with a while and check every char against ' '
and '\0'. Or you could use the strtok commands to split it. Or you could
use strpbrk() instead of strchr() and so check for multiple possible
seperation chars like "\n\r " to also find the line end prior to the ending \0,
and so on.

How the single commands are seperated is a thing you must know. Basically you have to check every single string part for a length of 1 and then check it against the "command" chars like &> and so on. You can do that with a switch() or a series of if() commands.


i=0;
while(result[i]!=0)
{
if(strlen(result[i])==1) /* look for length of 1 */
switch(*result[i]) /* switch on the first char */
{
case '&': /* end of command, program stays resident */
break;
case '>': /* output is redirected, result[i+1] contains target */
break;
case '<': /* output is redirected, result[i+1] contains target */
break;
default: /* no known command, ignore */
}
i++;
}



As said, what you do with that is up to you.

mile1982
09-07-2004, 05:18 PM
thanks a lot for your help mate!! always appreciate when a good example is included!!

cheers
mile