473,760 Members | 10,633 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

simple command line parser

Well since getopt() doesn't seem to be compatible with Windows, and
the free implementation of it for Windows that I found still had some
annoying restrictions, I thought I'd whip up a simple parser myself.
Just wanted to see if anyone could provide me with some constructive
criticism :) any feedback would be greatly appreciated
-----------------------------------------------------------------------------

#include "stdio.h"
#include "string.h"
#include "stdlib.h"

#define MAX_OPTION_ARGS 10

enum optionName {
Start,
Stop,
Remove,
Install,
Debug,
Num_Opts
};

typedef struct optionStruct {
char *name;
int expNumVal;
char *val[MAX_OPTION_ARGS];
int valid;
} optStruct;

optStruct optData[Num_Opts] = {
{ "-start", 1 },
{ "-stop", 2 },
{ "-remove", 2 },
{ "-install", 1 },
{ "-debug", 3 }
};

int usage(void)
{
printf("Usage is as follows...");
return 0;
}

int StartService(ch ar * service_name)
{
return 0;
}

int main (int argc, char * argv[])
{
int a, b, c;
const char *optstring;
const struct option *longopts;
int *longindex;

for (a = 1; a < argc; a++)
{
for (b = 0; b < Num_Opts; b++)
{
if (strcmp(argv[a], optData[b].name) == 0)
{
if (a + optData[b].expNumVal< argc)
{
for (c = 0; c < optData[b].expNumVal; c++)
{
optData[b].val[c] = argv[a + c + 1];
}
optData[b].valid = 1;
a += optData[b].expNumVal;
}
else
{
fprintf(stderr, "ERROR: insufficient number of arguments for
option %s\n", optData[b].name);
usage();
return 1;
}

break;
}
}

if (b == Num_Opts)
fprintf(stderr, "Warning: unknown option %s (ignored)\n", argv[a]);
}
/*
Sample usage...

if (optData[Start].valid == 1)
{
StartService(op tData[Start].val[0]);

}
*/
return 0;
}
Nov 13 '05 #1
4 11448
ru******@hotmai l.com (Greg B) wrote in
<f5************ **************@ posting.google. com>:
Well since getopt() doesn't seem to be compatible with Windows, and
the free implementation of it for Windows that I found still had some
annoying restrictions, I thought I'd whip up a simple parser myself.
Just wanted to see if anyone could provide me with some constructive
criticism :) any feedback would be greatly appreciated
-----------------------------------------------------------------------------

#include "stdio.h"
#include "string.h"
#include "stdlib.h"

#define MAX_OPTION_ARGS 10

enum optionName {
Start,
Stop,
Remove,
Install,
Debug,
Num_Opts
};

typedef struct optionStruct {
char *name;
int expNumVal;
char *val[MAX_OPTION_ARGS];
That's what I'd call an annoying restriction. :)
Why not char *val and dynamic memory allocation?
int valid;
} optStruct;

optStruct optData[Num_Opts] = {
{ "-start", 1 },
{ "-stop", 2 },
{ "-remove", 2 },
{ "-install", 1 },
{ "-debug", 3 }
}; Nice, you include the dash with every option name. :)

int usage(void)
{
printf("Usage is as follows...");
return 0;
}

int StartService(ch ar * service_name)
{
return 0;
}
Please, don't use TABs for formatting code you post in usenet -
this wastes space and garbles the lines.
<code gently reformatted>int main (int argc, char * argv[])
{
int a, b, c;
const char *optstring;
const struct option *longopts;
int *longindex;

for (a = 1; a < argc; a++)
{
for (b = 0; b < Num_Opts; b++)
{
if (strcmp(argv[a], optData[b].name) == 0)
{
if (a + optData[b].expNumVal< argc)
{
for (c = 0; c < optData[b].expNumVal; c++)
{
optData[b].val[c] = argv[a + c + 1];
}
optData[b].valid = 1;
a += optData[b].expNumVal;
}
else
{
fprintf(stderr, "ERROR: insufficient number of arguments "
"for option %s\n", optData[b].name);
usage();
return 1;
}
break; This break has absolutely no chance of beeing executed!
}
}
if (b == Num_Opts)
fprintf(stderr, "Warning: unknown option %s (ignored)\n", argv[a]);
}
/*
Sample usage...

if (optData[Start].valid == 1)
{
StartService(op tData[Start].val[0]);
}
*/
return 0;
}

Sorry, if my critique is somewhat destructive, but this is one of
the most complex option parsers I've been looking at. Anyway, if it
meets your needs, use it, but it might be a good idea to capsule it
in a separate module in order to keep your main function tidy and
clean. And you should consider not to make excessive use of global
variables, as this may lead to unwanted interferences eventually.

Btw: did you compile it? This is what I got when I did:

gcc.exe "D:\Temp\ngetop t.c" -o "D:\Temp\ngetop t.exe" -W -Wall
-Wunreachable-code -ansi -O3 -g3 -I"C:\Programme\ DevCpp5b8\inclu de"
-L"C:\Programme\ DevCpp5b8\lib"

ngetopt.c:25: warning: missing initializer
ngetopt.c:25: warning: (near initialization for `optData[0].val')
ngetopt.c:26: warning: missing initializer
ngetopt.c:26: warning: (near initialization for `optData[1].val')
ngetopt.c:27: warning: missing initializer
ngetopt.c:27: warning: (near initialization for `optData[2].val')
ngetopt.c:28: warning: missing initializer
ngetopt.c:28: warning: (near initialization for `optData[3].val')
ngetopt.c:29: warning: missing initializer
ngetopt.c:29: warning: (near initialization for `optData[4].val')
ngetopt.c:46: warning: unused variable `optstring'
ngetopt.c:47: warning: unused variable `longopts'
ngetopt.c:48: warning: unused variable `longindex'
ngetopt.c:72: warning: will never be executed
ngetopt.c:38: warning: unused parameter `service_name'

If one takes warnings as errors (at least, I do), this is a /bit/
more than I'd expect from 86 lines of my code (though there are
no severe warnings, and you can get rid of them very easily).

I hope my reply wasn't to harsh... :)

Regards,
Irrwahn

--
When things look dark,
hold your head high so it can rain up your nose.
Nov 13 '05 #2
Irrwahn Grausewitz wrote:

ru******@hotmai l.com (Greg B) wrote:
for (b = 0; b < Num_Opts; b++)
{
if (strcmp(argv[a], optData[b].name) == 0)
{
if (a + optData[b].expNumVal< argc)
{
for (c = 0; c < optData[b].expNumVal; c++)
{
optData[b].val[c] = argv[a + c + 1];
}
optData[b].valid = 1;
a += optData[b].expNumVal;
}
else
{
fprintf(stderr, "ERROR: insufficient number of arguments "
"for option %s\n", optData[b].name);
usage();
return 1;
}
break;

This break has absolutely no chance of beeing executed!


Why not?

--
Er*********@sun .com
Nov 13 '05 #3
Eric Sosman <Er*********@su n.com> wrote in <3F************ ***@sun.com>:
Irrwahn Grausewitz wrote:
ru******@hotmai l.com (Greg B) wrote:
> break;

This break has absolutely no chance of beeing executed!


Why not?


Urgh, sorry, my fault. I'll go looking for my glasses... :)

--
Air is water with holes in it.
Nov 13 '05 #4
Greg B <ru******@hotma il.com> wrote:
Well since getopt() doesn't seem to be compatible with Windows, and
the free implementation of it for Windows that I found still had some
annoying restrictions, I thought I'd whip up a simple parser myself.
Just wanted to see if anyone could provide me with some constructive
criticism :) any feedback would be greatly appreciated
----------------------------------------------------------------------------- #include "stdio.h"
#include "string.h"
#include "stdlib.h"
Why are these in double-quotes? It would be more reasonable to
expect the compiler to look for these headers in their proper
locations to start with, not in the current directory.
#define MAX_OPTION_ARGS 10 enum optionName {
Start,
Stop,
Remove,
Install,
Debug,
Num_Opts
};
This has nothing to do with the rest of your code.
typedef struct optionStruct {
char *name;
int expNumVal;
char *val[MAX_OPTION_ARGS];
int valid;
} optStruct;
If you are going to be spelling out 'Struct' anyway, then why not
just lose the typedef? You will be saving yourself a shift-key hit.
If you insist on using the typedef, you do not need the structure
identifier, since you are not using it.
optStruct optData[Num_Opts] = {
{ "-start", 1 },
{ "-stop", 2 },
{ "-remove", 2 },
{ "-install", 1 },
{ "-debug", 3 }
};
Why not make the option prefix configurable via a define or somesuch?
Additionally, you should be initializing 'valid'.
int usage(void)
{
printf("Usage is as follows...");
return 0;
}
This is not terribly useful.
int StartService(ch ar * service_name)
{
return 0;
}
Neither is this.

Here is your reindented code. Still unfitting line length for Usenet,
I'm afraid.
int
main (int argc, char *argv[])
{
int a, b, c;
const char *optstring;
You don't use this.
const struct option *longopts;
What is 'struct option'? You haven't defined it.
int *longindex;
You don't use this.
for (a = 1; a < argc; a++)
{
for (b = 0; b < Num_Opts; b++)
{
if (strcmp (argv[a], optData[b].name) == 0)
{
if (a + optData[b].expNumVal < argc)
{
This is where it gets really silly. You take the index of the
argv element you are parsing and add an offset to produce the
index of an expected supplementary value?
for (c = 0; c < optData[b].expNumVal; c++)
{
optData[b].val[c] = argv[a + c + 1];
}
optData[b].valid = 1;
a += optData[b].expNumVal;


Hmmm...

< snip the rest >

This is the most complicated and constrained way of getting
command-line arguments that I have ever seen.

You need to rethink your design by properly defining the problem
domain.

- What kind of options are you going to be parsing?

- Will there be only boolean options or will you have to handle
various supplementary types such as strings, integers, floats
and so on?

- What will happen if an option has incorrect syntax or a
a mandatory option is missing?

- Do you want to copy and paste code for each new program you
write or do you want to make a universally usable library
function, which will be configurable by the user?

To get you started, here is what I think your options structure
should look like.

enum opt_t { BOOL, INT, STR /*, etc */ }

struct option
{
char *opt; /* option name */
opt_t type; /* option type */
char mandatory; /* is option mandatory ? */
char *usage; /* usage for this specific option */
void *value; /* parsed value or null */
}

....only the last element is an output of the parser.

In your client code, you will populate an array of 'struct
option' and pass it to your parser along with argc and argv.

At any time if the parser fails, it will print out a program
usage based on the 'usage' fields in the array.

You should also leave it up the client code to define the prefix

Hope this helps.

Alex
Nov 13 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
2452
by: Leif K-Brooks | last post by:
I'm writing a site with mod_python which will have, among other things, forums. I want to allow users to use some HTML (<em>, <strong>, <p>, etc.) on the forums, but I don't want to allow bad elements and attributes (onclick, <script>, etc.). I would also like to do basic validation (no overlapping elements like <strong><em>foo</em></strong>, no missing end tags). I'm not asking anyone to write a script for me, but does anyone have general...
4
7572
by: Boogie El Aceitoso | last post by:
Hi, I need a command line parser that understands filename swith spaces. Since I'm absolutelly sure I'm not the first developer to need a command line parser, I was wondering is there's a decent open source one available. I really don't want to reinvent the wheel.... O:-) TIA
1
1604
by: Larry | last post by:
I am a C++/Java programmer trying to get going with some simpe xml transformations at work here. I bought the O'Reilly book Learning xlst for kicks. Someone at work sent me this xml shown below, they wanted me to try to output some simple text which summarizes the basic data in the xml and do it without perl. After that I guess they will want me to convert other xml files into some kind of text file I am assuming. I downloaded xalan, but...
17
1998
by: News | last post by:
Hi everyone, My goal is to pull command switches/options from a file and then assign the values to select variables which would eventually be included in a class object. The data file looks something like this but the switches could be in any order and not all may be used. -m quemanager -s server -p port -k key -o object -c 20 -t test@email.com
8
3514
by: Andrew Robert | last post by:
Hi Everyone. I tried the following to get input into optionparser from either a file or command line. The code below detects the passed file argument and prints the file contents but the individual swithces do not get passed to option parser.
6
4169
by: 31337one | last post by:
Hello all, I was wondering if there is a C/C++ command line parser that works for linux AND windows. . Anyways, the ideal parser im looking for should be able to support multiple arguments per option. Example: $myProg --option1 arg arg arg --option2 arg --option3 arg
16
2719
by: John Salerno | last post by:
Here's my new project: I want to write a little script that I can type at the terminal like this: $ scriptname package1 where scriptname is my module name and any subsequent arguments are the names of Linux packages to install. Running the script as above will create this line: sudo aptitude install package1 package2 ...
0
1089
by: vincent90152900 | last post by:
I'm trying to get PowerShell script to run a program. Here is the command line I need to run: "\"C:\\Program Files\\PDF2allTest\\pdf2all\" -c pdf2jpg -s \"c:\\test\\test\\01.pdf\" -or 600" I get the following error message. How to solve this? System.Management.Automation.ParseException was unhandled Message="You must provide a value expression on the right-hand side of the '-' operator." Source="System.Management.Automation" ...
4
5500
by: cjt22 | last post by:
Hi there. I just wondered whether anyone could recommend the correct way I should be passing command line parameters into my program. I am currently using the following code: def main(argv = None): file1= "directory1" file2 = "directory2"
0
9521
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9333
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
1
9900
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9765
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8768
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
5214
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
3863
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
3442
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2733
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.