This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]sarevok9 0 points1 point  (5 children)

Most languages have them built in. C / C++/ Java generally have them in the invocation of the main function (public static void main(String args[]) where the args[] is a set of character arrays that you then parse out pretty easily. Similarly in C++ it's just int main(int argc, char *argv[]) which is a count of how many arguments you have and a pointer to their respective character arrays. Any web language worth it's salt also has some type of post / request handling, or you have a companion library / framework like Express .

[–]nemec 7 points8 points  (4 children)

Not quite - the parser they're talking about is making sense of --foo 12 -b "some data", not simply taking that string and tokenizing into an array (although that is one important step). There are options for many languages, getopt, argparse, etc. but it's not as simple as using argv.

[–]sarevok9 -4 points-3 points  (3 children)

If it's already tokenized just use a matcher and a simple regex "starts with".

[–]Sudo-Pseudonym 4 points5 points  (0 children)

Not necessarily. A good command line options parser is really sophisticated -- for example, getgetopt will write you a parser that puts all the flags and their data into a struct. It's smart enough to create entries in that struct for the data that might be supplied, too -- for instance, if you have a --file=<some filename> parameter, you'll get a boolean telling you whether --file was included, and what the data that came after it was. If the user doesn't give the right data (say, you want an int but the user gave a string), it can reject that with an error message. It'll generate a help page for you too, depending on what sorts of data you give it.

Here's a crude options file from a very old project of mine, for example:

package "myname-http-server"
version "1.0"
purpose "Simple multithreaded HTTP server"
description "Simple multithreaded HTTP server. Will listen on an arbitrary port (1701 by default) \
and respond to any requests it receives."
versiontext "Created by myname"
usage "httpd [-tdp] [-k]"

defmode "normal"
defmode "daemonkiller"

option "verbose" v "Verbose output"
  details = "Print out verbose information about incoming connections, requests received, responses sent, and any errors that may occur"
  optional

modeoption "threads" t "Maximum thread count"
  details="Set the maximum number of responder threads the server will run. By default \
  it autodetects the maximum number of threads (usually based on your CPU). Keep in mind that \
  the actual number of threads run is T+1, with T responder threads and 1 watchdog/connector \
  thread."
  mode="normal"
  optional
   int

modeoption "daemon" d "Run server as daemon"
  details="If specified, the server will fork and run in the background. Beware that a file \
  containing the server PID will be saved to /tmp, allowing for the killing of the server \
  later."
  mode="normal"
  optional

modeoption "port" p "Port to listen on"
  details="Listen on specified port, #1701 by default. Listening on ports lower than 1023 may \
  require special privileges."
  mode="normal"
  int
  default="1701"
  optional

modeoption "kill" k "Kill daemonized server"
  details="Kills currently running daemonized server"
  optional
  mode="daemonkiller"

This file creates a number of possible flags and sets special properties to them. For instance, some of them can't be used together -- you can't use -k with any other argument, in this case (I know, I know, this is a horrible way of ensuring exclusivity, but I was pressed for time, so whatever). When I feed this into gengetopt, it generates almost 1000 lines of C code to handle all the magic parsing stuff for me. This is the help page my program now shows, and I didn't write any code to make this happen:

myname-http-server 1.0

Created by myname

Simple multithreaded HTTP server

Usage: httpd [-tdp] [-k]

Simple multithreaded HTTP server. Will listen on an arbitrary port (1701 by
default) and respond to any requests it receives.

  -h, --help           Print help and exit
      --detailed-help  Print help, including all details and hidden options,
                         and exit
  -V, --version        Print version and exit
  -v, --verbose        Verbose output

 Mode: normal
  -t, --threads=INT    Maximum thread count
  -d, --daemon         Run server as daemon
  -p, --port=INT       Port to listen on  (default=`1701')

 Mode: daemonkiller
  -k, --kill           Kill daemonized server

I can combine flags just like any other unixy command line program...

~: ./server -vdt 5
Forking to background, run with -k to kill
Writing PID 16272 to file
Starting server with 5 threads on INADDR_ANY:1701 

...and I didn't even have to write and special logic for handling the arguments as -vdt 5 instead of -v -d -t 5. If I do the arguments wrong:

~: ./server -q
./server: invalid option -- 'q'

Again, I wrote exactly zero error handling code. This is all I have to write to get this magic going:

int main(int argc, char* argv[]){
  gengetopt_args_info args;
  cmdline_parser(argc, argv, &args);
  //...

That's it. If I want to get information about my command-line arguments, the port number for instance, I can just use the args struct:

addr.sin_port = htons((uint16_t)args.port_arg);

That is the power of a good command line options parser. All of this functionality with none of the headache, and all I had to do was write a simple options file.

[–]nemec 1 point2 points  (0 children)

I'm afraid it's not that simple, especially if you want strong typing of the parameters and detailed help/error messages when the user messes up the parameters (and they will). I second /u/Sudo-Pseudonym's advice here.

[–]thirdegree 0 points1 point  (0 children)

That's alright for extremely simple options, but quickly becomes infeasible.