2009. 3. 28. 13:15

NAME


  getopt, getopt_long, getopt_long_only - 명령라인 옵션을 분석(parse)한다.   
 

SYNOPSIS


 #include <unistd.h>

 int getopt(int argc, char * const argv[], const char *
optstring
);

 extern char *
optarg
;
 extern int optind, opterr, optopt
;

 #define _GNU_SOURCE

 #include <getopt.h>

 int getopt_long(int
argc, char * const argv[], const char optstring,
  const struct option *longopts
, int *
longindex
);
 int getopt_long_only(int argc
, char * const
argv[]
,
  const char *
optstring, const struct option *longopts, int *longindex);

DESCRIPTION

getopt() 는 입력라인의 인자(arguments)를 분석한다.
프로그램 실행에 의해 main()함수에서 넘겨진 argc와 argv는 인자의 수와 배열을 나타낸다.
'-' 또는 '--'를 정확히 구분을 하지않지만
'-'으로 시작되는 argv의 요소가 옵션 요소(option element)가 된다.
'-'으로 시작하여 뒤에 있는 문자는 옵션문자(option characters)가 된다.
getopt() 를 반복적으로 호출하게 되면 각각의 옵션인자(option element)에서
각각의 옵션 문자(option characters)들이 성공적으로 반환된다.

만일
getopt()가 또 다른 옵션 문자가 있음을 발견하게 된다면, 이 문자를 반환하고,
외부 변수
optind와 정적 변수 nextchar를 업데이트함으로서,
getopt() 함수가 다시 호출되었을때 현재 검색된 다음 인자(argv)또는
다음 옵션부터 검색할수 있도록 있도록 한다.

일 더이상의 옵션 문자가 없다면, getopt()는 -1 을 반환하며,
optindargv들중에 첫번째 argv-요소를 가르킴으로서 더이상 옵션이 존재하지 않음을 알린다.
(주:argv의 첫번째는 프로그램 자신이며, 옵션이 아니죠.)

optstring
은 규칙에 맞는 옵션 문자들이 포함되어 있는 문자열을 나타낸다.
만일 이러한 문자뒤에 콜론(:)이 있다면, 해당 옵션이 인자를 요구한다는 것을 의미한다.
따라서,
getopt는 현재 argv-요소(element)에 뒤따르는 텍스트 부분으로 포인터를 이동시키거나,
optarg내의 다음
argv요소에 있는 텍스트 부분으로 포인터를 이동시킨다.
두개의 콜론(::)은 옵션이 추가적인 인자를 요구함을 나타낸다.
만일 현재
argv-요소에 텍스트가 존재한다면, optarg으로 반환되며,
그렇지 않다면
optarg는 '0'의 값을 지니게 된다. 이것은 GNU 확장이다.
optstring이 ';'(semicolon)을 수반하는 W를 포함한다면,
-W foo는 long option --foo로써 다루어진다.
(kim: foo가 하나의 arg로 다루어진다는 건지 테스트 필요)
(-W option은 구현 확장들에 대해 POSIX.2에 의해 예약되어있다.)
이 동작은 GNU extension이며, glibc 2 이전의 library에서 이용가능하지 않다.

기본적으로, getopt()는 argv를 읽음으로써 argv의 내용을 재배치하여 결과적으로
모든 non-option들을 뒤에 놓는다. 두개의 다른 mode들이 또한 구현되어있다.
optstring의 첫번째 character가 '+' 이거나 환경변수 POSIXLY_CORRECT가 설정되어있다면,
option processing은 non-option argument와 마주치면서 곧바로 멈춘다.
optionstring의 첫번째 character가 '-'이라면, 각 non-option argv-element는
마치 그것이 chracter code 1인 option의 argument로써 다루어진다.
(이것은 options들과 다른 argv-element들이 어떤 순서 혹은 두가지 처리에 대해
유념하는 것이 있을 거라는 것을 예상하고 쓰여진 프로그램에 의해 사용된다.
special argument "--"는 scanning mode에 관계없이 option-scanning의 마지막을 강요한다.

getopt()가 option character를 알아차리지 못한다면, stderr로 error message를 출력하고,
optopt안에 character를 저장하며 '?'를 return한다.
호출하는 program은 opterr를 0으로 설정함으로서 error message를 방지한다.

getopt()가 optstring에 포함되지 않은 argv안에 option character를 찾거나
missing option argument를 감지한다면, '?'를 return하고 external variable optopt를 실제
option character로 설정한다. optstring의 (위에 서술된 어떤 추가적인 '+' 또는 '-'를 수반하는)
첫번째 character가 ':'(colon)이라면 getopt는 missing option argument를 가리키는 '?'
대신에 ':'를 리턴한다. error가 감지되었다면, optstring의 첫번째 character는 colon(':')이
아니고 external variable opterr는 0이 아니며,(기본적으로) error message를 출력한다. 

  getopt_long()과 getopt_long_only()

getopt_long()함수는 2개의 dash(--)로 시작되는 long options을 허용하는것을 제외하고는
getopt()와 같이 동작한다. (프로그램이 long option만이 허용된다면, optstring은
empty string ("")로써 명시되어질 수 있다, NULL이 아님) Long option name은
어떤 정의된 option에 대해 정확히 대응되거나 유일한 단축이라면 생략될 수 있다.
long option은 --arg=param 또는 --arg param 형태의 parameter를 취할 수 있다.

longopts는 다음의 <getopt.h>에 선언되어진
struct option의 배열의 첫번째 요소에 대한 pointer이다. 

  struct option { 
      const char *name; 
      int         has_arg; 
      int        *flag; 
      int         val; 
 }; 
 


각 field들의 의미는: 
     name :
        long option의 이름 

     has_arg :
        option이 argument를 취하지 않는다면 no_argument(또는 0);
        option이 하나의 argument를 취한다면 required_argument(또는 1);
        option이 추가적인 argument를 취한다면 optional_argument(또는 2). 

     flag :
        어떻게 결과가 long option에 대해 return되는지 명시한다.
        flag가 NULL이면, getopt_long()는 val을 return한다.

        (예를 들어, 호출하는 program은 동등한 short option character로 val설정 할 것이다.)
        다른 경우라면, getopt_long()는 0을 return하고 flag는 option이 발견되면 val로 설정한
        variable을 가리킨다. 
그러나 option이 발견되지 않으면 바뀌지 않게 내비둔다. 

     val :
        return되는 값이거나 flag에 의해 가리키는 variable로 로드한다. 

array의 마지막 element는 0으로 채워져야 한다. 

longindex가 NULL이 아니라면 longopts에 상대적인 long option의 index로 설정된 variable을 가리킨다. 

getopt_long_only() 은 getopt_long()이랑 같지 않다,
하지만 '-' 뿐만아니라 "--"는 long option을 가리킬수 있다.
option이 long option과 대응되지 않는 '-'("--"이 아님)으로 시작한다면,
하지만 short option은 대응된다, 그러면 대신에 short option으로 분석(parse)되어진다. 

 

RETURN VALUE

option이 성공적으로 찾아지면, getopt()는 option character를 return한다. 
모든 command-line option들이 분석(parse)되어진다면, getopt()은 -1을 return한다.
getopt()이 optstring안에 없는 option character와 마주치면, '?'이 return된다.
getopt()이 missing argument을 갖는 option에 마주치면, 
return value는 optstring내의 첫번째 character에 의존한다.
: ':'이라면, ':'이 return된다; 다른 경우 '?'이 return된다. 

getopt_long()과 getopt_long_only() 또한 short option을 알아볼때
option character가 return된다.
long option에 대해, flag가 NULL이라면 val을 retun하고, 다른경우는 0이다.
Error와 -1 return 은 getopt()에 관해서 같다, 모호하게 대응하거나 관계없는 
parameter에 대해 '?'가 더해진다.

 

ENVIRONMENT

 POSIXLY_CORRECT 
      설정되어 있다면, option processing은 
      non-option argument와 마주치게 되어 곧바로 멈춘다. 

 _<PID>_GNU_nonoption_argv_flags_ 

      이 variable은 argument들이 wildcard 확장의 결과 또는 option들로써
     고려되어지지 않을 수 있는 gblic와 통신하기 위해 bash 2.0에 의해 사용되어진다.

 

CONFORMING TO


  getopt(): 
      POSIX.2 와 POSIX.1-2001는 환경 변수 POSIXLY_CORRECT가 설정되어 제공되어진다. 
      다른경우, argv의 element들은 const가 아니다, 왜냐하면 순서를 바꾸기때문이다.
      우리는 다른 시스템들과 호환되기 위한 prototype내에 const이기를 의도한다. 

      어떤 오래된 구현상에서, getopt()는 <
stdio.h>안에 선언되어있다. 
      SUSv1은 <
unistd.h> 또는 <stdio.h> 둘다 선언을 허용한다.  
      POSIX.1-2001는 LEGACY인 목적에 대해 <
stdio.h> 사용을 언급하였다.
      POSIX.1-2001은 <
stdio.h>내의 선언을 허용하지 않는다. 
 

BUGS

getopt()의 POSIX.2 명세는 POSIX.2 interpretation 150안에 기술된 기술적 error를 가진다.
GNU implementation(그리고 아마도 모든 다른 implementation들)는
명시된 것 보다 올바른 행동을 이행한다.

 

EXAMPLE

다음의 예제 program은 두개의 program options을 다루는 getopt()을 사용한다.
 :value와 관련 없는 -n; 그리고 관련된 value를 예상하는 -t val

       #include <unistd.h>
       #include <stdlib.h>
       #include <stdio.h>

       int
       main(int argc, char *argv[])
       {
           int flags, opt;
           int nsecs, tfnd;

           nsecs = 0;
           tfnd = 0;
           flags = 0;
           while ((opt = getopt(argc, argv, "nt:")) != -1) {
               switch (opt) {
               case 'n':
                   flags = 1;
                   break;
               case 't':
                   nsecs = atoi(optarg);
                   tfnd = 1;
                   break;
               default: /* '?' */
                   fprintf(stderr, "Usage: %s [-t nsecs] [-n] name\n",
                           argv[0]);
                   exit(EXIT_FAILURE);
               }
           }

           printf("flags=%d; tfnd=%d; optind=%d\n", flags, tfnd, optind);

           if (optind >= argc) {
               fprintf(stderr, "Expected argument after options\n");
               exit(EXIT_FAILURE);
           }

           printf("name argument = %s\n", argv[optind]);

           /* Other code omitted */

           exit(EXIT_SUCCESS);
       }



다음의 예제 program은 대부분의 특징을 갖는 getopt_long()의 사용을 예시한다. 

       #include <stdio.h>     /* for printf */
       #include <stdlib.h>    /* for exit */
       #include <getopt.h>

       int
       main(int argc, char **argv)
       {
           int c;
           int digit_optind = 0;

           while (1) {
               int this_option_optind = optind ? optind : 1;
               int option_index = 0;
               static struct option long_options[] = {
                   {"add", 1, 0, 0},
                   {"append", 0, 0, 0},
                   {"delete", 1, 0, 0},
                   {"verbose", 0, 0, 0},
                   {"create", 1, 0, 'c'},
                   {"file", 1, 0, 0},
                   {0, 0, 0, 0}
               };

               c = getopt_long(argc, argv, "abc:d:012",
                        long_options, &option_index);
               if (c == -1)
                   break;

               switch (c) {
               case 0:
                   printf("option %s", long_options[option_index].name);
                   if (optarg)
                       printf(" with arg %s", optarg);
                   printf("\n");
                   break;

               case '0':
               case '1':
               case '2':
                   if (digit_optind != 0 && digit_optind != this_option_optind)
                     printf("digits occur in two different argv-elements.\n");
                   digit_optind = this_option_optind;
                   printf("option %c\n", c);
                   break;

               case 'a':
                   printf("option a\n");
                   break;

               case 'b':
                   printf("option b\n");
                   break;

               case 'c':
                   printf("option c with value '%s'\n", optarg);
                   break;

               case 'd':
                   printf("option d with value '%s'\n", optarg);
                   break;

               case '?':
                   break;

               default:
                   printf("?? getopt returned character code 0%o ??\n", c);
               }
           }

           if (optind < argc) {
               printf("non-option ARGV-elements: ");
               while (optind < argc)
                   printf("%s ", argv[optind++]);
               printf("\n");
           }

           exit(EXIT_SUCCESS);
       }


 

SEE ALSO


    getsubopt(3), feature_test_macros(7) 


'API 및 라이브러리 > C 라이브러리 함수' 카테고리의 다른 글

malloc(3)  (0) 2009.03.31
strcpy(3)  (0) 2009.03.31
getenv(3)  (1) 2009.03.30
fclose(3)  (0) 2009.03.29
exit(3)  (0) 2009.03.29
Posted by devanix