일의 특성상 IDE Tool 이 아닌 오직 shell & vi 환경에서만 작업을 하다보니 여러가지 문명의 이기에서 멀어져가고 있습니다.
그다지 범용적인 개발 환경이 아닌지라 공개되어있는 개발 방법도 적어서 정보도 얻기가 힘들군요.
그런저런 이유로 이번에는 function prototype 의 자동생성에 대해서 알아봤습니다.

현재 제가 다니는 회사에서 사용되는 function prototype 생성 툴은 충분히 잘 돌아갑니다만 범용적으로 사용되기에는 조금 제약사항이 따르는 것이 사실입니다.
일단 가장 범용적으로 사용되는 util 을 찾아봤습니다.

cproto -- generate C function prototypes from C source code
Cproto is a program that generates function prototypes and variable declarations from C source code. It can also convert function definitions between the old style and the ANSI C style.


이 util 을 선택한 이유는 보통의 linux 환경에서는 compiler 를 설치할때 기본적으로 선택되는 util 이라는 점도 있었지만 무엇보다 범용적으로 사용되고 있다는 것입니다.
가장 큰 장점 중 하나는 -D option 을 사용해 option compile 시와 마찬가지로 prototype 을 생성할 수 있다는 것입니다.

다양한 option 을 지원하지만 여기에서 모든 것을 다 설명할 필요는 없으므로 man page 등을 참고하시기 바랍니다.
cproto 의 homepage 는 아래와 같습니다.
http://cproto.sourceforge.net/


현재 제가 다니는 회사의 source code 에 적합한 예를 몇개 들어보겠습니다.

1. 전역 변수 처리
cproto -I ../h -O /dev/null -v -f0 -e *.c

위의 명령으로 함수에 정의 되어있는 전역변수의 prototype을 뽑아내서 앞에 extern을 붙여 출력하게 됩니다.

옵션 설명
> -I : header 의 path 를 나타내는 것입니다.
> -O : stderr로 나오는 warning 이나 error 의 출력을 지정해주는 것입니다. –q 옵션도 있지만 일부 warning 에 대해 처리가 안되는 것을 확인했습니다.
> -v : 함수 뿐 아니라 전역 변수로 선언된 것의 prototype 을 출력하라는 것입니다.
> -f0 : 이 option 은 0~3까지 있습니다. 0은 함수의 prototype을 출력 안하는 것이고 1,2,3은 각각의 format 으로 출력하는 것입니다. 기본은 –f3이고 –f3이 현재 대부분의 사람들이 사용하는 one line 의 가장 보편적인 prototype 형식입니다.
> -e : 해당 prototype 앞에 extern을 붙이라는 옵션입니다.

아래는 출력 예입니다.
/* sctp_ipif.c */
extern int ISSECURE;
/* sctp_main.c */
extern sctpInstance_t sctpInst[(13 + 1) ];
extern SCTP_ulpCallbacks sctpUlp;
extern SCTP_InstanceParameters instancePara;
extern SCTP_LibraryParameters libPara;
/* sctp_misc.c */


2. 함수 prototype 처리
cproto -I ../h -O /dev/null *.c

위 명령은 *.c 파일 내부의 함수의 prototype을 출력하게 합니다.
option 설명은 이미 위에서 하였으니 부연설명은 안하겠습니다. –f3옵션은 default이기 때문에 하지 않은 것이고 –e 옵션은 extern을 붙일 필요가 없기 때문에 하지 않은 것입니다.

아래는 출력 예입니다.
/* sctp_ipif.c */
void *ip_interface(void);
/* sctp_main.c */
sint main(void);
void to_exit(uint exit_code);
sint initSctp(void);
sint initialize(void);
/* sctp_proc.c */
void timer_expired(unsigned int tID, void *para1, void *para2);
void proc_lower(ipcMsg_t *pMsg);
void proc_upper(ipcMsg_t *pMsg);
sint setServiceIp(void);
sint getLeal(void);
/* sctp_recv.c */
sint searchSntId(uint key);


3. 자동화 처리
단순한 shell script를 사용하여 처리하였습니다.
extern 선언 부분과 function 선언부분에 특정한 주석을 삽입하여 그 사이에 결과를 넣도록 처리한 것입니다.
좀더 세련된 방법이나 좋은 방법이 있으신 분은 알려주시기 바랍니다.

#! /bin/sh
IFS=''
replace_flag=0

while read -r line; do
if [ "$replace_flag" != "1" ]; then
echo "$line"
fi

if [ "$line" = "/* extern declare */" ]; then
replace_flag=1
cproto -I ../h -O /dev/null -v -f0 -e *.c
fi

if [ "$line" = "/* extern declare end */" ]; then
replace_flag=0
echo "$line"
fi

if [ "$line" = "/* function prototype declare */" ]; then
replace_flag=1
cproto -I ../h -O /dev/null *.c
fi

if [ "$line" = "/* function prototype declare end */" ]; then
replace_flag=0
echo "$line"
fi

done < $1



IFS의 값을 없애지 않으면 애써 이쁘게 만들어 놓은 선언이 엉망이 됩니다.
이와 같은 script 를 Makefile 내에 proto 로 선언한 곳에서 사용하도록 하면 make tag와 같이 유용하게 사용될 수 있을 것이라 생각합니다.



4. 단점
> 약간은 깨끗하지 못하게 파일에 대한 주석이 나온다. (아무것도 출력되는게 없을 경우에 파일 이름의 주석을 없애는 옵션은 발견하지 못했습니다. 아마도 이런 옵션은 후에도 나오지 않을 것으로 생각됩니다.)
> 속도가 느리다. (생각보다 속도가 많이 느립니다. 거의 컴파일러 수준이라고 생각하시면 됩니다. 그대신 –D 옵션이 먹는 것만으로도 충분히 가치가 있다고 생각합니다.)