Thread: using getopt_long_only and subopts together.

  1. #1
    Banned
    Join Date
    Aug 2017
    Posts
    861

    using getopt_long_only and subopts together.

    I maybe in denial, But is their a way to use two subopts switches within the main getopt_long_only switch ?

    I a trying to but i am running out of ideas on how to get this to work, if it is even possible.

    I really have no idea how much of my code I should, or need to add so here is just a little of it and some pseudo code to go along with it.

    I have tried numerous combinations so it is a little bit of a blur in my head right now.
    Code:
    
    enum
    {
      T, TH , TV ,THV, RT ,RTH ,RTV ,RTHV  ,FLIP_IMAGES  , BUTT
    };
    
    
    enum
    {
        FD , FH , FV , RFD , RFH  , RFV  , BUTT2
    };
    
    
    char *tile_opts[] =
    {
      [T] = "n",
      [TH] = "h",
      [TV] = "v",
      [THV] = "hv",
      [RT] = "rt",
      [RTH] = "rh",
      [RTV] = "rv",
      [RTHV] ="rhv",
      [FLIP_IMAGES] = "fi",
    
    
      [BUTT] = NULL
    };
    
    char *flip_opts [] =
    {
    
            [FD] = "fd",
            [FH] = "fh",
            [FV] = "fv",
            [RFD] = "rd",
            [RFH] = "rh",
            [RFV] = "rv",
            [BUTT2] = NULL
    };
    
    static char string_options [] = "FfCc:t:s:d:a:"; //htT::g:a:s:D:n:i:d:";
    
     static struct option long_options[] = {
    blah, blah 
       {"tile",1, 0, 't'},
        {"fi",1,0,202}, // flip Image fi
    ....
    }
    
    while (( oc = getopt_long_only(argc, argv, string_options, long_options,&option_index) ) != -1)
    {
       switch (oc)
            {
           case 1:
              do something
               break;
    case 't':
                   subopts = optarg;
                    printf("%s subopts\n", subopts);
                    while (*subopts != '\0')
                        switch (getsubopt (&subopts, tile_opts, &value))
                        {
                            case T:
                                img.mode = TILE;
                                img.which_image_type = 2;
                                printf("Tile subopts mode # %d\n",(int)img.mode);
                                break;
                             ..................
                    }  // end subopt switch
           case 202:
                             // second subopts fi
                           printf("Case FI %s\n",optarg);
                             subopts = optarg;
                        while (*subopts != '\0')
                           switch (getsubopt (&subopts, flip_opts, &value))
                           {
                            case FD:
                                img.mode = FLIPD;
                                img.which_image_type = 3;
                                printf("flipD %d\n", (int)img.mode);
                                break;
                     ................
    } // end second subopts switch
    
    default:
     break
    } // end main switch
    if the answer is no, please just confirm it, so I can move on to a different logic on how to get this options menu to get all of the different combinations I have into it.

    Thanks,

    (ps I hope I get an e-mail form this forum so I know if this has been answered)

    PSS this is in Linux btw if that matters.
    Last edited by userxbw; 08-28-2017 at 06:42 PM. Reason: cleaned it up I think and added hopefully needed stuff

  2. #2
    Registered User
    Join Date
    Jun 2015
    Posts
    1,643
    Quote Originally Posted by userxbw View Post
    is their a way to use two subopts switches within the main getopt_long_only switch ?
    Of course you can. What's the problem?

    Your "pseudocode" is useless, however. E.g., it's missing needed break statements.

    If you need help, we need to see some real code.
    If the program is long, make a shorter version that compiles and runs.
    Explode the sunlight here, gentlemen, and you explode the entire universe. - Plan 9 from Outer Space

  3. #3
    Banned
    Join Date
    Aug 2017
    Posts
    861
    Quote Originally Posted by algorism View Post
    Of course you can. What's the problem?

    Your "pseudocode" is useless, however. E.g., it's missing needed break statements.

    If you need help, we need to see some real code.
    If the program is long, make a shorter version that compiles and runs.
    O thanks I wasn't sure what to put. I'll update that original post with real code. two: I've tried it a few different ways, obviously not the correct one.
    Just let me cook something up that will run off the menu options.
    Last edited by userxbw; 08-29-2017 at 08:19 AM.

  4. #4
    Banned
    Join Date
    Aug 2017
    Posts
    861
    I didn't see an edit selection on my original post anymore so I'll re-post it here, in replay to you.


    I'm going to leave the default: break: alone because I obviously am not getting this right in the first place so it wouldn't much matter where I put them.

    it is taking the first sub option -t n
    then still going into the second subopt in this writing. I can't get it to use one or the other and not both, one after the other. Because some of the options have same letter or the directive of what it is for.

    just gcc main.c get a.out
    or how ever you do on your side.

    Code:
    /*
    Aug 27, 2017
    */
    
    #include <X11/Xlib.h>
    #include <X11/Xutil.h>
    #include <getopt.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    
    
    enum
    {
      T, TH , TV ,THV, RT ,RTH ,RTV ,RTHV  ,FLIP_IMAGES  , BUTT
    };
    
    
    enum
    {
        FD , FH , FV , RFD , RFH  , RFV , BUTT2
    };
    
    // leading r is for resize
    
    char *tile_opts[] =
    {
      [T] = "n",
      [TH] = "h",
      [TV] = "v",
      [THV] = "hv",
      [RT] = "rt",
      [RTH] = "rh",
      [RTV] = "rv",
      [RTHV] ="rhv",
      //[FLIP_IMAGES] = "fi",
      [BUTT] = NULL
    };
    
    char *flip_opts [] =
    {
    
            [FD] = "d",
            [FH] = "h",
            [FV] = "v",
            [RFD] = "rd",
            [RFH] = "rh",
            [RFV] = "rv",
            [BUTT2] = NULL
    };
    
    
    void mh_parse_options_array(int argc, char **argv)
    {
        int oc = 0;
        int option_index = 0;
        char *subopts;
    
        char *value, *color;
        extern char *optarg;
        extern int optind;
    
    
        static char string_options [] = "FfCc:t:s:d:a:";
            //  no_argument  0
            // required_argument 1   (‘:’) to indicate that it takes a required argument
            // optional_argument 2  (‘::’), its argument is optional
        static struct option long_options[] = {
     // a b c d e f g h i j k l m n o p q r s t u v w x y z
            {"fullscreen", 0,  0,  'f'},
            {"fill",  0 ,  0, 'F'},
            {"center", 0 ,0,'C'},
             {"resize-center", 1, 0, 'c'},
             {"solid", 1,0,'s'},
             {"distance",1,0,'d'},
             {"angle",1,0,'a'},
                 {"tile",1, 0, 't'},
            {"add",1,0,200},
             {"rf",0,0,201}, // random files
             {"fi",1,0,202}, // flip Image fi
             {0,0,0,0}
    
        }; // end options
    
        while (( oc = getopt_long_only(argc, argv, string_options, long_options,&option_index) ) != -1)
    
            switch (oc)
            {
                case 'f':
                    printf("Full screen\n");
                    break;
                case 'F':
                    printf("Fill screen\n");
                    break;
                case 'C':
                        printf("Center Screen\n");
                    break;
                case 'c':
                    printf("resize center screen: Size %s\n", optarg);
                    break;
                       case 'd':
                            printf("distance %s\n", optarg);
                    break;
                case 'a':
                    printf("angle %s\n", optarg);
    
                    break;
                case 's':
                    printf("solid: color %s \n", optarg);
    
                    break;
                case 200:
                   printf("add (2) colors C = %s\n", optarg);
    
                    break;
                case 201:
                    printf("Random files\n");
                    break;
            case '?':
                    printf("What did you forget?  Think about it.\n");
                    exit(1);
                    break;
    
                case 't': // sub opts one
                    printf("in tile\n");
                    subopts = optarg;
    
                    while (*subopts != '\0')
                        switch (getsubopt (&subopts, tile_opts, &value))
                        {
                            case T:
    
                                printf("Tile subopts mode\n");
                                break;
                            case TH:
    
                                printf("tile hor subopts mode\n");
                                break;
                            case TV:
    
                                printf("tile vert subopts mode \n");
                                break;
                            case THV:
    
                                printf("Tile Hor vert subopt mode\n");
                                break;
                            case RT:
                                    printf("RTILE: image_size %s\n",value);
                                    break;
                                case RTH:
                                        printf("Resize tile Hor: image_size %s\n", value);
    
                                  break;
                            case RTV:
                                    printf(" Resize TIle Vert\n");
    
                                break;
                            case RTHV:
                                    printf("resize tile hor %s value\n", value);
                                     break;
                          //  default:
                          //      break;
                        } // end first sub opts.
                  case 202: // taken from main switch long opts
                             // second subopts fi
                           printf("Case FI %s\n",optarg);
                             subopts = optarg;
                        while (*subopts != '\0')
                           switch (getsubopt (&subopts, flip_opts, &value))
                           {
                            case FD:
                                    printf("flipD\n");
                                break;
                             case FH:
                                printf("flipH\n");
                                break;
                            case FV:
                                printf("flipV \n");
                                break;
                            case RFD:
                                if (value == NULL)
                                {
                                    printf("bad value %s\n", value);
                                    exit(1);
                                }
                                else
                                {
                                    printf("resize flipsd %s\n", value);
                                }
                                break;
                            case RFH:
                                if(value == NULL)
                                {
                                    printf("bad value %s\n", value);
                                    exit(1);
                                }
                                else
                                {
                                    printf("resize flipH %s\n");
                                }
                                break;
                            case RFV:
                                if(value == NULL)
                                {
                                    printf("bad value %s\n", value);
                                    exit(1);
                                }
                                else
                                {
                                    printf("resizeflipd V %s\n");
                                }
                                break;
    
                            default:
                                    //Second suboption.
                                printf ("Unknown suboption `%s'\n", value);
                            break;
    
                          } // end second switch subopts
    
    
                default:
                    printf("Default main switch\n");
                    break;
    
            } // end main switch
    
    
    //printf("optind %d, argc %d\n", optind, argc);
    
        if(optind == argc)
        {
            printf("if(optind == argc)%s \n", argv[optind]);
        }
    
        if (optind < argc)
        {
            printf( " loading image path if ( optind < argc) %s argv[argc]\n", argv[optind]);
    
            for(; optind < argc ; optind++)
            {
                printf("getting files\n");
            }
    
        optind = 0;
        }
    
    } //end function
    
    void check_options(void)
    {
    
      printf("check_options\n");
    
    
    }
    
    
    int main (int argc, char **argv )
    {
    
    mh_parse_options_array(argc,  argv);
    
    
    return 0;
    }
    Last edited by userxbw; 08-29-2017 at 09:09 AM.

  5. #5
    Registered User
    Join Date
    Jun 2015
    Posts
    1,643
    Obviously the X11 headers aren't needed in this example.
    gcc warns me that:
    * The printf's on lines 196 and 207 are missing their char* arguments.
    * color is unused.

    Nothing to do with your problem, though.

    You're still missing the breaks that I mentioned with your pseudocode. The main switch needs breaks after the second-level switches. The "break" in the inner switches will not break out of the outer switches. So, in the listing above, breaks are needed between lines 164 and 165 and on line 221.

    BTW, your spacing is a little off. That's not a good sign!

    Anyway, the following fixes the above-mentioned errors. Please run your test cases on it. Show your command lines, the output, and, if the output is "wrong", what you expect the output to be.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <getopt.h>
    
    enum { T, TH, TV, THV, RT, RTH, RTV, RTHV, FLIP_IMAGES, BUTT }; 
    enum { FD, FH, FV, RFD, RFH, RFV, BUTT2 };
     
    char *tile_opts[] = {
        [T]    = "n",
        [TH]   = "h",
        [TV]   = "v",
        [THV]  = "hv",
        [RT]   = "rt",
        [RTH]  = "rh",
        [RTV]  = "rv",
        [RTHV] = "rhv",
        //[FLIP_IMAGES] = "fi",
        [BUTT] = NULL
    };
     
    char *flip_opts [] = {
        [FD]    = "d",
        [FH]    = "h",
        [FV]    = "v",
        [RFD]   = "rd",
        [RFH]   = "rh",
        [RFV]   = "rv",
        [BUTT2] = NULL
    };
    
    void mh_parse_options_array(int argc, char **argv) {
        int oc = 0;
        int option_index = 0;
        char *subopts;
        char *value;
        extern char *optarg;
        extern int optind;
        static char *string_options = "FfCc:t:s:d:a:";
        static struct option long_options[] = {
            {"fullscreen",    0, 0, 'f'},
            {"fill",          0, 0, 'F'},
            {"center",        0, 0, 'C'},
            {"resize-center", 1, 0, 'c'},
            {"solid",         1, 0, 's'},
            {"distance",      1, 0, 'd'},
            {"angle",         1, 0, 'a'},
            {"tile",          1, 0, 't'},
            {"add",           1, 0, 200},
            {"rf",            0, 0, 201}, // random files
            {"fi",            1, 0, 202}, // flip Image fi
            {0,               0, 0, 0  }
        };
     
        while ((oc = getopt_long_only(argc, argv, string_options,
                         long_options, &option_index) ) != -1)
    
            switch (oc) {
    
            case 'f':
                printf("Full screen\n");
                break;
            case 'F':
                printf("Fill screen\n");
                break;
            case 'C':
                printf("Center Screen\n");
                break;
            case 'c':
                printf("resize center screen: Size %s\n", optarg);
                break;
            case 'd':
                printf("distance %s\n", optarg);
                break;
            case 'a':
                printf("angle %s\n", optarg);
                break;
            case 's':
                printf("solid: color %s\n", optarg);
                break;
            case 200:
                printf("add (2) colors C = %s\n", optarg);
                break;
            case 201:
                printf("Random files\n");
                break;
     
            case 't':
                printf("Case tile: optarg %s\n", optarg);
                subopts = optarg;
                while (*subopts != '\0')
                    switch (getsubopt (&subopts, tile_opts, &value)) {
                    case T:
                        printf("Tile subopts mode\n");
                        break;
                    case TH:
                        printf("tile hor subopts mode\n");
                        break;
                    case TV:
                        printf("tile vert subopts mode \n");
                        break;
                    case THV:
                        printf("Tile Hor vert subopt mode\n");
                        break;
                    case RT:
                        printf("RTILE: image_size %s\n",value);
                        break;
                    case RTH:
                        printf("Resize tile Hor: image_size %s\n", value);
                        break;
                    case RTV:
                        printf(" Resize TIle Vert\n");
                        break;
                    case RTHV:
                        printf("resize tile hor %s value\n", value);
                        break;
                    default:
                        printf ("Unknown tile suboption `%s'\n", value);
                        exit(1);
                        break;
                    }
                    
                    break;
    
            case 202:
                printf("Case fi: optarg %s\n", optarg);
                subopts = optarg;
                while (*subopts != '\0')
                    switch (getsubopt (&subopts, flip_opts, &value)) {
                    case FD:
                        printf("flipD\n");
                        break;
                    case FH:
                        printf("flipH\n");
                        break;
                    case FV:
                        printf("flipV \n");
                        break;
                    case RFD:
                        if (value == NULL) {
                            printf("value == NULL\n");
                            exit(1);
                        }
                        else
                            printf("resize flipsd %s\n", value);
                        break;
                    case RFH:
                        if (value == NULL) {
                            printf("value == NULL\n");
                            exit(1);
                        }
                        else
                            printf("resize flipH %s\n", value);
                        break;
                    case RFV:
                        if (value == NULL) {
                            printf("value == NULL\n");
                            exit(1);
                        }
                        else
                            printf("resizeflipd V %s\n", value);
                        break;
                    default:
                        printf ("Unknown fi suboption `%s'\n", value);
                        exit(1);
                        break;
                    }
    
                    break;
    
            case '?':
                printf("What did you forget?  Think about it.\n");
                exit(1);
                break;
            default:
                printf("Default main switch\n");
                exit(1);
                break;
            }
     
        if (optind == argc)
            printf("optind == argc\n");
        else
            for ( ; optind < argc ; optind++)
                printf("getting file: %s\n", argv[optind]);
    }
    
    int main (int argc, char **argv) {
        mh_parse_options_array(argc,  argv);
        return 0;
    }
    Explode the sunlight here, gentlemen, and you explode the entire universe. - Plan 9 from Outer Space

  6. #6
    Banned
    Join Date
    Aug 2017
    Posts
    861

    Thumbs up

    Code:
    /*
    Aug 27, 2017
    */
    
    #include <X11/Xlib.h>
    #include <X11/Xutil.h>
    #include <getopt.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    
    
    enum
    {
      T, TH , TV ,THV, RT ,RTH ,RTV ,RTHV  ,FLIP_IMAGES  , BUTT
    };
    
    
    enum
    {
        FD , FH , FV , RFD , RFH  , RFV , BUTT2
    };
    
    // leading r is for resize
    
    char *tile_opts[] =
    {
      [T] = "n",
      [TH] = "h",
      [TV] = "v",
      [THV] = "hv",
      [RT] = "rt",
      [RTH] = "rh",
      [RTV] = "rv",
      [RTHV] ="rhv",
      //[FLIP_IMAGES] = "fi",
      [BUTT] = NULL
    };
    
    char *flip_opts [] =
    {
    
            [FD] = "d",
            [FH] = "h",
            [FV] = "v",
            [RFD] = "rd",
            [RFH] = "rh",
            [RFV] = "rv",
            [BUTT2] = NULL
    };
    
    
    void mh_parse_options_array(int argc, char **argv)
    {
        int oc = 0;
        int option_index = 0;
        char *subopts;
    
        char *value;
        extern char *optarg;
        extern int optind;
    
    
        static char string_options [] = "FfCc:t:s:d:a:";
            //  no_argument  0
            // required_argument 1   (:) to indicate that it takes a required argument
            // optional_argument 2  (::), its argument is optional
        static struct option long_options[] = {
     // a b c d e f g h i j k l m n o p q r s t u v w x y z
            {"fullscreen", 0,  0,  'f'},
            {"fill",  0 ,  0, 'F'},
            {"center", 0 ,0,'C'},
             {"resize-center", 1, 0, 'c'},
             {"solid", 1,0,'s'},
             {"distance",1,0,'d'},
             {"angle",1,0,'a'},
                 {"tile",1, 0, 't'},
            {"add",1,0,200},
             {"rf",0,0,201}, // random files
             {"fi",1,0,202}, // flip Image fi
             {0,0,0,0}
    
        }; // end options
    
        while (( oc = getopt_long_only(argc, argv, string_options, long_options,&option_index) ) != -1)
    
            switch (oc)
            {
                case 'f':
                    printf("Full screen\n");
                    break;
                case 'F':
                    printf("Fill screen\n");
                    break;
                case 'C':
                        printf("Center Screen\n");
                    break;
                case 'c':
                    printf("resize center screen: Size %s\n", optarg);
                    break;
                       case 'd':
                            printf("distance %s\n", optarg);
                    break;
                case 'a':
                    printf("angle %s\n", optarg);
    
                    break;
                case 's':
                    printf("solid: color %s \n", optarg);
    
                    break;
                case 200:
                   printf("add (2) colors C = %s\n", optarg);
    
                    break;
                case 201:
                    printf("Random files\n");
                    break;
            case '?':
                    printf("What did you forget?  Think about it.\n");
                    exit(1);
                    break;
    
                case 't': // sub opts one
                    printf("in tile\n");
                    subopts = optarg;
    
                    while (*subopts != '\0')
                        switch (getsubopt (&subopts, tile_opts, &value))
                        {
                            case T:
    
                                printf("Tile subopts mode\n");
                                break;
                            case TH:
    
                                printf("tile hor subopts mode\n");
                                break;
                            case TV:
    
                                printf("tile vert subopts mode \n");
                                break;
                            case THV:
    
                                printf("Tile Hor vert subopt mode\n");
                                break;
                            case RT:
                                    printf("RTILE: image_size %s\n",value);
                                    break;
                                case RTH:
                                        printf("Resize tile Hor: image_size %s\n", value);
    
                                  break;
                            case RTV:
                                    printf(" Resize TIle Vert\n");
    
                                break;
                            case RTHV:
                                    printf("resize tile hor %s value\n", value);
                                     break;
                          default: // UNCOMMENTED THIS DEFAULT BREAK
                            printf("default setopts one\n");
                                break;
                        } // end first sub opts.
                        break; // ADDED BREAK HERE
                  case 202: // taken from main switch long opts
                             // second subopts fi
                           printf("Case FI %s\n",optarg);
                             subopts = optarg;
                        while (*subopts != '\0')
                           switch (getsubopt (&subopts, flip_opts, &value))
                           {
                            case FD:
                                    printf("flipD\n");
                                break;
                             case FH:
                                printf("flipH\n");
                                break;
                            case FV:
                                printf("flipV \n");
                                break;
                            case RFD:
                                if (value == NULL)
                                {
                                    printf("bad value %s\n", value);
                                    exit(1);
                                }
                                else
                                {
                                    printf("resize flipsd %s\n", value);
                                }
                                break;
                            case RFH:
                                if(value == NULL)
                                {
                                    printf("bad value %s\n", value);
                                    exit(1);
                                }
                                else
                                {
                                    printf("resize flipH %s\n",value);
                                }
                                break;
                            case RFV:
                                if(value == NULL)
                                {
                                    printf("bad value %s\n", value);
                                    exit(1);
                                }
                                else
                                {
                                    printf("resizeflipd V %s\n",value);
                                }
                                break;
    
                            default:
                                    //Second suboption.
                                printf ("Unknown suboption `%s'\n", value);
                            break;
    
                          } // end second switch subopts
                        break; // ADDED BREAK HERE
    
                default:
                    printf("Default main switch\n");
                    break;
    
            } // end main switch
    
    
    //printf("optind %d, argc %d\n", optind, argc);
    
        if(optind == argc)
        {
            printf("if(optind == argc)%s \n", argv[optind]);
        }
    
        if (optind < argc)
        {
            printf( " loading image path if ( optind < argc) %s argv[argc]\n", argv[optind]);
    
            for(; optind < argc ; optind++)
            {
                printf("getting files\n");
            }
    
        optind = 0;
        }
    
    } //end function
    
    void check_options(void)
    {
    
      printf("check_options\n");
    
    
    }
    
    
    int main (int argc, char **argv )
    {
    
    mh_parse_options_array(argc,  argv);
    
    
    return 0;
    }
    It's jumping out of the loop now and giving me the proper responses.

    Thanks a load.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. getopt_long_only tutorial?
    By dayalsoap in forum C Programming
    Replies: 7
    Last Post: 09-24-2010, 12:11 PM

Tags for this Thread