Line Control
#line
#line Linenum Filename
#line Linenum
#line
지시자를 이용하면 __FILE__
과 __LINE__
매크로 값을 임의로 변경할 수 있습니다.
$ gcpp
#line 100 "foo.c" // 다음 라인부터 __FILE__ 값은 "foo.c" 가 되고
__FILE__ : __LINE__ // __LINE__ 값은 100 이 된다.
__FILE__ : __LINE__
#warning message 111
#line 200 "bar.c" // 다음 라인부터 __FILE__ 값은 "bar.c" 가 되고
__FILE__ : __LINE__ // __LINE__ 값은 200 이 된다.
__FILE__ : __LINE__
#warning message 222
#line 300 // 라인 번호만 설정
__FILE__ : __LINE__
__FILE__ : __LINE__
#warning message 333
@
foo.c:102:2: warning: #warning message 111 [-Wcpp]
bar.c:202:2: warning: #warning message 222 [-Wcpp]
bar.c:302:2: warning: #warning message 333 [-Wcpp]
"foo.c" : 100
"foo.c" : 101
"bar.c" : 200
"bar.c" : 201
"bar.c" : 300
"bar.c" : 301
-----------------------------------------------------
$ gcc -xc - <<\@
int main() {
#line 1000 "foo.c" // 다음 라인부터 __FILE__ 값은 "foo.c" 가 되고
foo("hello"); // __LINE__ 값은 1000 이 된다.
#line 2000 "bar.c" // 다음 라인부터 __FILE__ 값은 "bar.c" 가 되고
bar("world"); // __LINE__ 값은 2000 이 된다.
}
@
foo.c: In function ‘main’:
foo.c:1000:5: warning: implicit declaration of function ‘foo’ ...
bar.c:2000:5: warning: implicit declaration of function ‘bar’ ...
. . .
yacc
파서 생성기에 입력으로 plural.y
파일을 사용하면 결과로 plural.c
파일이
생성되는데 이때 plural.y
파일 내용이 plural.c
에서 사용됩니다.
다음을 보면 plural.y
파일 내용이 사용된 곳에서
#line
지시자를 이용해 해당 위치를 지정하는 것을 볼 수 있습니다.
/usr/share/gettext/intl/plural.c 참조
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
union YYSTYPE
{
#line 49 "plural.y" // 다음 라인부터 __FILE__ 값은 "plural.y" 가 되고
// __LINE__ 값은 49 가 된다.
unsigned long int num;
enum expression_operator op;
struct expression *exp;
#line 176 "plural.c" // 다음 라인부터 __FILE__ 값은 "plural.c" 가 되고
}; // __LINE__ 값은 176 이 된다.
typedef union YYSTYPE YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1
#endif
. . .
. . .
YY_REDUCE_PRINT (yyn);
switch (yyn)
{
case 2:
#line 153 "plural.y" /* yacc.c:1646 */
{
if ((yyvsp[0].exp) == NULL)
YYABORT;
arg->res = (yyvsp[0].exp);
}
#line 1365 "plural.c" /* yacc.c:1646 */
break;
case 3:
#line 161 "plural.y" /* yacc.c:1646 */
{
(yyval.exp) = new_exp_3 (qmop, (yyvsp[-4].exp), (yyvsp[-2].exp), ...
}
#line 1373 "plural.c" /* yacc.c:1646 */
break;
case 4:
#line 165 "plural.y" /* yacc.c:1646 */
{
(yyval.exp) = new_exp_2 (lor, (yyvsp[-2].exp), (yyvsp[0].exp));
}
#line 1381 "plural.c" /* yacc.c:1646 */
break;
. . .
. . .
Quiz
오류코드 중에 하나인 EWOULDBLOCK
과 EAGAIN
은 어떤 차이가 있을까요?
EWOULDBLOCK
의 의미는 "operation would block" 을 나타내고
EAGAIN
는 "temporary resource shortage made an operation impossible" 을 나타냈는데
현재는 두 매크로 값을 구분 없이 같은 값을 사용하고 있습니다.
$ header-macro errno.h -e EWOULDBLOCK // Resource temporarily unavailable
11
$ header-macro errno.h -e EAGAIN // Resource temporarily unavailable
11
$ header-macro errno.h -s EWOULDBLOCK
#define EWOULDBLOCK EAGAIN
하지만 2002 년 이전의 AIX 4.3,5.1 HP-UX 11.22 OSF1 같은 운영체제에서는 다른 값을 사용했다고 합니다. 이때도 매크로 값은 다르지만 같은 의미로 사용됐으므로 이와 같은 구 버전의 OS 도 지원하려면 다음 세 번째와 같이 작성하면 되고 그렇지 않을 경우는 첫 번째와 두 번째는 차이가 없습니다.
if ( errno == EAGAIN ) { ...
if ( errno == EWOULDBLOCK ) { ...
if ( errno == EWOULDBLOCK || errno == EAGAIN ) { ...
2 .
socket
함수의 원형은 아래와 같은데요.
여기서 세 번째 인수인 protocol 값으로 0
을 사용하는 경우가 많습니다.
여기서 0
은 어떤 값일까요 ?
int socket( int domain, int type, int protocol );
int sockfd = socket( AF_INET, SOCK_STREAM, 0 );
int sockfd = socket( AF_INET, SOCK_DGRAM, 0 );
int sockfd = socket( AF_UNIX, SOCK_STREAM, 0 );
AF_INET
의 protocol 값으로 사용되는 0
은 IPPROTO_IP
를 나타냅니다.
여기서 IPPROTO_IP
는 매크로가 아니고 enum 입니다.
그러니까 0
대신에 IPPROTO_IP
를 입력한 것과 동일한 것이 됩니다.
protocol 값이 IPPROTO_IP
이면 socket 함수가 자동으로 domain 과 type 을 보고 판단하여
SOCK_STREAM
일 경우는 protocol 값으로 IPPROTO_TCP
를 사용하고
SOCK_DGRAM
일 경우는 IPPROTO_UDP
를 사용합니다.
AF_UNIX
( unix domain socket ) 같은 경우는 local 접속에 사용되는 것으로
따로 protocol 이 사용되지 않으므로 0
을 사용합니다.
그 외에는 아래 세 번째와 같이 직접 protocol 값을 적어주어야 합니다.
$ header-enum netinet/in.h -s IPPROTO_IP # 매크로가 아니고 enum 값이다.
enum {
IPPROTO_IP = 0,
IPPROTO_ICMP = 1,
. . .
$ header-macro netinet/in.h -s IPPROTO_IP
#define IPPROTO_IP IPPROTO_IP
#define IPPROTO_IPIP IPPROTO_IPIP
#define IPPROTO_IPV6 IPPROTO_IPV6
# 직접 protocol 값을 적어주어야 한다.
int sockfd = socket( AF_INET, SOCK_STREAM, IPPROTO_SCTP)