poptの使い方

オプション解析ライブラリ.
getoptとおんなじだけど,ちょっと違う.

使い方って,流れを見た方が早いことって多いよね.

ということで,流れを紹介. というか,manそのまんまなんだけどね.

たぶん,スイッチのオプションを解析したあとに, フラッグなしの数字を処理した方がよいと思われる. つまり,poptGetNextOpt(optCon)が先で,poptGetArgが後.

実際に使ってみた例はこっち. ちょっと汚いけど,こんな感じで使うもんなのかな,といったもの.


#include <popt.h>
#include <stdio.h>

/* これつけた方がカッコイイ */
void usage(poptContext optCon, int exitcode, char *error, char *addl) {
    poptPrintUsage(optCon, stderr, 0);
    if (error) fprintf(stderr, "%s: %s0, error, addl);
    exit(exitcode);
}

int main(int argc, char *argv[]) {
   char    c;            /* used for argument parsing */
   int     i = 0;        /* used for tracking options */
   char    *portname;
   int     speed = 0;    /* used in argument parsing to set speed */
   int     raw = 0;      /* raw mode? */
   int     j;
   char    buf[BUFSIZ+1];
   poptContext optCon;   /* context for parsing command-line options */

   /* ここでオプションを設定 */
   struct poptOption optionsTable[] = {
   /*{ "longname", "shortname", argInfo,      *arg,   int val, description, argment description} */
     { "bps",      'b',         POPT_ARG_INT, &speed, 0,       "signaling rate in bits-per-second", "BPS" },
     { "crnl",     'c',         0,            0,      'c',     "expand cr characters to cr/lf sequences" },
     { "hwflow",   'h',         0,            0,      'h',     "use hardware (RTS/CTS) flow control" },
     { "noflow",   'n',         0,            0,      'n',     "use no flow control" },
     { "raw",      'r',         0,            &raw,   0,       "don't perform any character conversions" },
     { "swflow",   's',         0,            0,      's',     "use software (XON/XOF) flow control" } ,
       POPT_AUTOHELP             { NULL, 0, 0, NULL, 0 }
   };
   /* この場合,へルプはこんな風に表示される.
   $ a.out --help

   Usage: a.out [OPTIONS]* 
     -b, --bps=BPS   signaling rate in bits-per-second
     -c, --crnl      expand cr characters to cr/lf sequences
     -h, --hwflow    use hardware (RTS/CTS) flow control
     -n, --noflow    use no flow control
     -r, --raw       don't perform any character conversions
     -s, --swflow    use software (XON/XOF) flow control

   Help options
     -?, --help      Show this help message
     --usage         Display brief usage message
   */

   optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);   /* オプションを読み込む */
   poptSetOtherOptionHelp(optCon, "[OPTIONS]* <port>");          /* これをつけると,へルプのところに[OPTIONS]* がつく*/

   if (argc < 2) {
               poptPrintUsage(optCon, stderr, 0);
               exit(1);
   }

   /* Now do options processing, get portname */
   while ((c = poptGetNextOpt(optCon)) >= 0) {
      switch (c) {
         case 'c':
            buf[i++] = 'c';
            break;
         case 'h':
            buf[i++] = 'h';
            break;
         case 's':
            buf[i++] = 's';
            break;
         case 'n':
            buf[i++] = 'n';
            break;
      }
   }
   /* ここでは,数字は1つしかないので,単純に読み込む.
      二つ以上ある場合は,
      poptPeekArg(optCon)を利用したりして分岐する必要があるかも知れない */
   portname = poptGetArg(optCon);

   if((portname == NULL) || !(poptPeekArg(optCon) == NULL))
      usage(optCon, 1, "Specify a single port", ".e.g., /dev/cua0");

   if (c < -1) {
      /* an error occurred during option processing */
      fprintf(stderr, "%s: %s\n",
              poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
              poptStrerror(c));
      return 1;
   }

   /* 結果出力 */
   printf("Options  chosen: ");
   for(j = 0; j < i ; j++)
      printf("-%c ", buf[j]);
   if(raw) printf("-r ");
   if(speed) printf("-b %d ", speed);
   printf("\nPortname chosen: %s\n", portname);

   /* これを忘れないこと.メモリリークが起きる(たぶん). */
   poptFreeContext(optCon);

   exit(0);
}