전에 C 코드를 분석해서 그 안에 있는 내용을 추출해내려 한다는 이야기와 함께 몇가지 시도를 했다는 것을 올린 적이 있습니다. Perl을 이용해서 함수 호출 및 상수 추출 등을 구현해 보았는데요, 어찌보면 정식 방법은 아니죠. 보다 정확하게 하려면 C의 문법을 이용해서 처리를 해야 하는데, 생각보다 쉽지는 않네요. 물론 제대로된 노력을 해보지 않은 탓도 있겠지만요.
한동안은 C 코드 분석과 관련된 내용을 생각치 않고 있다가, 어제부터 다시 시작하게 되었습니다. 이번에는 좀더 개선된 내용으로 만들어 볼까 하는데, 이번에도 잘 될지는 의문입니다.
이번에 시작하면서 가장 먼저 하는 것은 코드 상에 존재하는 주석을 제거하는 일입니다. 여타의 컴파일러가 하듯이 말이죠. Perl의 Parse::RecDescent 모듈을 보면 주석을 제거 하는 부분이 들어가 있음을 알 수 있습니다. C 언어의 문법을 활용하는 방법입니다.
하지만 여기서는 좀더 단순히 주석만을 제거한 새로운 C 코드를 얻는 것을 일차적인 목표로 합니다. 주석이 제거 되고 나면 그 다음에 문법을 활용해서 파싱을 하든, 예전처럼 꽁수를 부려 원하는 정보를 얻어 내든 할 수 있을 테니까요.
주석을 제거하기 위해 처음에는 라인 단위로 읽어서 처리하려고 했습니다. 그러다보니 예외 케이스가 많이 있더군요. 그래서 적용한 방법은 한문자씩 읽어서 주석의 시작과 끝을 판단, 주석이라고 판단되면 출력하지 않는 것입니다. C 코드를 작성할 때 단순히 ASCII 코드만 있으면 좀더 처리가 편리하겠지만, 요즘은 UniCode를 지원해야겠죠? 그래서 아래와 같은 코드를 삽입하게 됩니다.
private String getStringChar(int unicode)
{
char[] codeUnits = new char[2];
int count = Character.toChars(unicode, codeUnits, 0);
return new String(codeUnits, 0, count);
}
{
char[] codeUnits = new char[2];
int count = Character.toChars(unicode, codeUnits, 0);
return new String(codeUnits, 0, count);
}
위의 코드는 Supplementary Characters in the Java Platform에서 참고하였습니다. 코드 내용은 unicode 코드의 값을 String으로 변환해주는 것입니다.
주석을 판단하여 제거하는 부분은 다음과 같습니다.
public void removeComments(File srcFile, File tgtFile) throws Exception
{
BufferedReader br = new BufferedReader(new FileReader(srcFile));
BufferedWriter bw = new BufferedWriter(new FileWriter(tgtFile));
StringBuffer buffer = new StringBuffer();
int unicodeChar;
int prevChar = -1;
boolean comments = false;
while( (unicodeChar = br.read()) >= 0 )
{
String str = getStringChar(unicodeChar);
if( !comments && unicodeChar == '/')
{
int nextChar = br.read();
if( nextChar == '*' )
{
comments = true;
bw.write(buffer.toString());
buffer = new StringBuffer();
} else
str += getStringChar(nextChar);
}
if( !comments )
buffer.append(str);
if( comments && unicodeChar == '/' && prevChar == '*')
comments = false;
prevChar = unicodeChar;
}
if( buffer.length() > 0 ) bw.write(buffer.toString());
bw.close();
br.close();
}
{
BufferedReader br = new BufferedReader(new FileReader(srcFile));
BufferedWriter bw = new BufferedWriter(new FileWriter(tgtFile));
StringBuffer buffer = new StringBuffer();
int unicodeChar;
int prevChar = -1;
boolean comments = false;
while( (unicodeChar = br.read()) >= 0 )
{
String str = getStringChar(unicodeChar);
if( !comments && unicodeChar == '/')
{
int nextChar = br.read();
if( nextChar == '*' )
{
comments = true;
bw.write(buffer.toString());
buffer = new StringBuffer();
} else
str += getStringChar(nextChar);
}
if( !comments )
buffer.append(str);
if( comments && unicodeChar == '/' && prevChar == '*')
comments = false;
prevChar = unicodeChar;
}
if( buffer.length() > 0 ) bw.write(buffer.toString());
bw.close();
br.close();
}
원본 파일과 주석이 제거된 내용을 저장할 파일을 받아서 처리를 하게 됩니다. C 에서는 /* ~ */ 형태의 주석만을 사용하기 때문에 이러한 패턴만을 찾아서 제거합니다.
아직 개선의 여지가 있을 수 있는 코드이기는 하지만, 처음에 생각했던 것 보다는 코드가 꽤나 단순해 보이네요.
이제 이 결과물을 이용해서 원하는 정보를 뽑아내는 과정을 고심해봐야겠습니다.
TRACKBACK :: http://naratalk.com/trackback/277
-
Subject: 주석 제거 프로그램(CommentRemover) 배포
Tracked from Adobe AIR Devpia. 삭제Adobe AIR Application Installer Page Download Application now. This application requires Adobe® AIR™ to be installed for Mac OS or Windows. ↑Install Now 버튼(배지)을 클릭하세요. 프로그래밍 작업을 완료한 후 주석을 제거해 본 적 있으신가요? 타 업체에 소스 코드를 넘길 때..또는 CSS, 자바스크립트를 웹에 올..
2009/08/29 02:36
이올린에 북마크하기
이올린에 추천하기
댓글을 달아 주세요