OSDev.org

The Place to Start for Operating System Developers
It is currently Fri Oct 23, 2020 7:20 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 4 posts ] 
Author Message
 Post subject: [Pointless-Fight] Shell Arguments/Parameters
PostPosted: Thu Oct 20, 2016 9:59 am 
Offline
Member
Member
User avatar

Joined: Fri Aug 07, 2015 6:13 am
Posts: 1099
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?

_________________
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader


Last edited by Octacone on Sun Oct 30, 2016 6:01 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Shell Arguments/Parameters
PostPosted: Fri Oct 21, 2016 3:52 pm 
Offline
Member
Member
User avatar

Joined: Sun Sep 19, 2010 10:05 pm
Posts: 1074
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

Code:
openFile("myFile.txt").writeText("Add this text to the bottom of the file.").getFileLength()


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.

_________________
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


Top
 Profile  
 
 Post subject: Re: [Pointless-Fight] Shell Arguments/Parameters
PostPosted: Mon Oct 31, 2016 4:26 am 
Offline
Member
Member
User avatar

Joined: Mon Jul 18, 2016 2:46 pm
Posts: 170
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.

Code:
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;
}


Top
 Profile  
 
 Post subject: Re: [Pointless-Fight] Shell Arguments/Parameters
PostPosted: Thu Nov 03, 2016 1:03 am 
Offline
Member
Member
User avatar

Joined: Wed Aug 31, 2016 9:53 pm
Posts: 81
Location: San Diego, CA
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:
Code:
char** argv = tokenize("echo \"hello world\"", " ", "\"", &argc);


Code:
/* 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


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 13 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group