[Pointless-Fight] Shell Arguments/Parameters
[Pointless-Fight] Shell Arguments/Parameters
It has been a long time (like 30 days) since my last interaction with Basic OS. Now, I am struggling with the console arguments. I want to be able to do stuff like "echo hello", etc. Now I was thinking about getting it to work with some string split methods, but my string split is screwed up. Should I port a random string split or there is another way?
Last edited by Octacone on Sun Oct 30, 2016 6:01 am, edited 1 time in total.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
Re: Shell Arguments/Parameters
http://forum.osdev.org/viewtopic.php?f=13&t=28654
Here is a discussion that I started 2 years ago (wow...) about my idea for parsing console commands. It may give you some ideas about where to start if you want a fairly simple yet powerful command line parser that supports nested commands, like
This approach has worked well for my needs, so just let me know if the link makes sense to you, or if you have any questions.
Good luck.
Here is a discussion that I started 2 years ago (wow...) about my idea for parsing console commands. It may give you some ideas about where to start if you want a fairly simple yet powerful command line parser that supports nested commands, like
Code: Select all
openFile("myFile.txt").writeText("Add this text to the bottom of the file.").getFileLength()
Good luck.
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
Re: [Pointless-Fight] Shell Arguments/Parameters
Well, to give you a simple answer atleast (please dont just copy and paste the code) here is the one I coded for SIMPLE parsing.
I coded it a way so all the data can fit into one page and only one malloc is needed.
This has been done because I do this in kernel rather then usermode.
I coded it a way so all the data can fit into one page and only one malloc is needed.
This has been done because I do this in kernel rather then usermode.
Code: Select all
char **cmd_to_argv(char *commandline, int *_argc)
{
if(!commandline || !_argc)
return 0;
int argc = 1;
bool b_escaped = true;
char **argv = malloc_p(4096, PTE_WRITE);
argv[0] = commandline;
while(*commandline && argc < 1024)
{
if(*commandline == '"' || *commandline == 39)
{
b_escaped = !b_escaped;
*commandline = '\0';
if(!b_escaped)
{
if(*(commandline + 1) != '"' && *(commandline + 1) != 39 && *(commandline + 1) != '\0')
{
argv[argc] = commandline + 1;
argc++;
}
}
}
else if(*commandline == ' ' && b_escaped)
{
*commandline = '\0';
if(*(commandline + 1) != '"' && *(commandline + 1) != 39 && *(commandline + 1) != ' ' && *(commandline + 1) != '\0')
{
argv[argc] = commandline + 1;
argc++;
}
}
commandline++;
}
*_argc = argc;
return argv;
}
- crunch
- Member
- Posts: 81
- Joined: Wed Aug 31, 2016 9:53 pm
- Libera.chat IRC: crunch
- Location: San Diego, CA
Re: [Pointless-Fight] Shell Arguments/Parameters
Inspired by Ch4ozz's post (and my own need for a halfway decent non-strtok parser), I cooked something up and figured I would share it. It should fit most general use cases, as you can specify the delimiter and escaped character strings. It relies heavily on the use of strspn() but that should be trivial to implement.
Escaped characters are replaced with '\0' if there is a match (i.e. for quotations), otherwise they are ignored.
Multiple delimiters are likewise ignored (i.e. multiple spaces, tabs, etc). Hopefully someone can find this useful.
example usage as follows:
Escaped characters are replaced with '\0' if there is a match (i.e. for quotations), otherwise they are ignored.
Multiple delimiters are likewise ignored (i.e. multiple spaces, tabs, etc). Hopefully someone can find this useful.
example usage as follows:
Code: Select all
char** argv = tokenize("echo \"hello world\"", " ", "\"", &argc);
Code: Select all
/* Released to public domain */
/* Simple argument parsing - returns an array of char* pointers
@str is the string to be parsed
@delim is a string containing characters to split by
@escape is a string containing characters to escape ("\"\'\n", etc) - optional
@_argc is a pointer to integer containing the size of returned pointer array */
char** tokenize(const char* str, const char* delim, const char* escape, int* _argc) {
if (!str || !_argc || !delim)
return NULL;
int i, argc = 0;
char* split = strdup(str);
/* first pass, approximate how many arguments there are for allocation */
while(*str) {
if (strspn(str, delim)) {
argc++;
str += strspn(str, delim);
}
str++;
}
/* allocate a pointer array of the proper size */
char** ret = malloc(sizeof(char*) * argc);
argc = 0;
ret[argc++] = split;
/* second pass, split strings by the delimiter */
while(*split) {
if (escape && strspn(split, escape)) {
i = strspn(split, escape);
/* save the escaped character for matching */
char c = *split;
split += i;
/* if we can't find a matching character to escape, ignore it */
if (!strchr(split, c)) {
ret[argc++] = split - i;
split++;
continue;
}
*(split - i) = '\0';
ret[argc++] = split;
/* pointer to first matching character */
split = strchr(split, c);
*split = '\0';
split++;
/* Make sure we don't return the last character as an argument */
if (!strspn(split, delim) && (strlen(split) > 1))
ret[argc++] = split;
}
if (strspn(split, delim)) {
i = strspn(split, delim);
*split = '\0';
split += i;
/* if there's an escaped character, try to escape it */
if (escape && strspn(split, escape))
continue;
ret[argc++] = split;
}
else
split++;
}
*_argc = argc;
return ret;
}
Some of my open-source projects:
Ext2/ELF32 bootloader
Lightweight x86 assembler, designed to be portable for osdev
Scheme in under 1000 lines of C
Ext2/ELF32 bootloader
Lightweight x86 assembler, designed to be portable for osdev
Scheme in under 1000 lines of C