Search code examples
cglibc

In C, how would I tell argp what to do if no option is passed?


Mods, please do not shoot this down, as I have been searching in every nook and cranny of Google for a solution in my free time over the past week or so and have still come up with nothing.

I've been working on learning C. You can find the entire project pertaining to this question here, although many other programs may want to be able to have an answaer as well:

https://github.com/Christoffen-Corporation/logo-generator

but this question primarily concerns the file main.c. Here's the source:

#include <stdio.h>
#include <argp.h>
#include <cairo.h>
#include "include.h"
const char *argp_program_version = "The Christoffen Corporation Logo Generator v2.0.1";
const char *argp_program_bug_address = "M. Gage Morgan <gage@christoffen.com>";
static char doc[] = "Generates all of the logo, or just some.";

static int parse_opt (int key, char *arg, struct argp_state *state) {
 switch (key) {
 case 'C': 
 colored_nologo(); 
 break;
 case 'c':
 colored_all();
 break;
 case 'O':
 outlined_nologo();
 break;
 case 'o':
 outlined_all();
 break;
 case 'F':
 frankenlogos();
 break;
 case 'a': 
 all_imgs();
 }
 return 0;
}

int main (int argc, char **argv) {
struct argp_option options[] =
 {
 { "colored-no-logo", 'C', 0, 0, "Generate all colored triangles, except for the logo\n"},
 { "colored-all", 'c', 0, 0, "Generate all colored triangles, and the logo\n"},
 { "outlined-no-logo", 'O', 0, 0, "Generate all outlined triangles, except for the logo\n"},
 { "outlined-all", 'o', 0, 0, "Generate all outlined triangles, and the logo\n"}, 
 { "frankenlogos", 'F', 0, 0, "Generate the Frankenlogos (don't ask; just do)\n"}, 
 { "all-images", 'a', 0, 0, "Generate all images: Outlines, Colors, and Logos.\n"},
 { 0 }
 };
 struct argp argp = { options, parse_opt, 0, 0 };
 return argp_parse (&argp, argc, argv, 0, 0, 0); 
}

I have looked EVERYWHERE, and either I'm missing something right in front of me, or there is no way to get argp to have a "fallback" if no option is specified.

Any program that has command line options should be able to have a fallback if none is specified. In this case, for example, I wanted it to be able to either generate just seven triangles and a logo ("./logo-generator -c" or "./logo-generator -o"), or everything possible if nothing specified as an option ("./logo-generator")

I have a function titled all_imgs() that I'd like the program to fallback on when no options are specified. I know it sounds simple and at first I felt stupid for not knowing, but about 1.5 pages into 14 different Google queries, I realized that I wasn't going crazy and that there was no "if nothing specified do this" example.

By having the source available and the scenario, I really hope this is specific enough for one of you here at SO to figure out. If there is any other information I left out, please ask and I will be glad to give it to you. Also, if you absolutely need to know about functions I'm using in main.c, they can be found in options.c, which can be found in the GitHub repo above (<10 reputation disables me from putting it here, I mean no harm, swear).

I'm not asking you to re-write main.c and/or any other files. Specifically, this is a problem in main.c and no other files are affecting it. It compiles just fine, but I'm looking for a minimal change, not an entire re-write, of main.c. I'm asking for the SIMPLEST solution to this problem.

I appreciate your time.

--MGage

EDIT: I've added the source in as requested. I've checked the link added for "User Options," but I don't want to use arguments, and I don't understand what is so hard about that. Just options. I need the user to be able to specify an option if they want to generate only a portion of the images, and if not, then generate everything. Again, I don't want to re-write main.

FINAL EDIT: I don't know why I didn't realize this sooner, but the answer I marked correct WAS helpful. I apologize for making this difficult. The result was to add the conditional IF before the function started, give the desired function to argc, and then use ELSE to stick the desired part of argp I wanted into the program. To demonstrate, here's the final result (and it works!):

#include <stdio.h>
#include <argp.h>
#include <cairo.h>
#include "include.h"
const char *argp_program_version = "The Christoffen Corporation Logo Generator v2.0.1";
const char *argp_program_bug_address = "M. Gage Morgan <gage@christoffen.com>";
static char doc[] = "Generates all of the logo, or just some.";

static int parse_opt (int key, char *arg, struct argp_state *state) {
 switch (key) {
 case 'C': 
 colored_nologo(); 
 break;
 case 'c':
 colored_all();
 break;
 case 'O':
 outlined_nologo();
 break;
 case 'o':
 outlined_all();
 break;
 case 'F':
 frankenlogos();
 break;
 }
 return 0;
}

int main (int argc, char **argv) {
if (argc == 1) {
all_imgs();
} else {
 struct argp_option options[] =
 {
 { "colored-no-logo", 'C', 0, 0, "Generate all colored triangles, except for the logo\n"},
 { "colored-all", 'c', 0, 0, "Generate all colored triangles, and the logo\n"},
 { "outlined-no-logo", 'O', 0, 0, "Generate all outlined triangles, except for the logo\n"},
 { "outlined-all", 'o', 0, 0, "Generate all outlined triangles, and the logo\n"}, 
 { "frankenlogos", 'F', 0, 0, "Generate the Frankenlogos (don't ask; just do)\n"}, 
 { 0 }
 };
 struct argp argp = { options, parse_opt, 0, 0 };
 return argp_parse (&argp, argc, argv, 0, 0, 0); 
  }
}

Thanks, everyone. I know a lot of you reading this probably got frustrated with my boneheadedness.


Solution

  • You know that argc is the number of arguments passed, right? You don't need a library to count them. The first argument is always the name of the program, so you are looking for the case argc == 1.

    int main(int argc, char **argv)
    {
      if (argc == 1) {
        /* there are no extra arguments, handle this case */
      } else {
        /* there are arguments, proceed to parse and handle them */
      }
    }