Shinnara's Blog
Talking with Shinnara :: NaraTalk.com


 전에 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);
    }

 위의 코드는 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();       
    }

 원본 파일과 주석이 제거된 내용을 저장할 파일을 받아서 처리를 하게 됩니다. C 에서는 /* ~ */ 형태의 주석만을 사용하기 때문에 이러한 패턴만을 찾아서 제거합니다.

아직 개선의 여지가 있을 수 있는 코드이기는 하지만, 처음에 생각했던 것 보다는 코드가 꽤나 단순해 보이네요.

이제 이 결과물을 이용해서 원하는 정보를 뽑아내는 과정을 고심해봐야겠습니다.








신고
1 Trackback, 0 Comment

댓글을 달아 주세요

1 ··· 46 47 48 49 50 51 52 53 54 ··· 264 
다...... (264)
Computer/Programming (106)
Links (14)
책 읽는 즐거움 (7)
끄적임 (66)
즐거운 과학 나라 (7)
일본 (5)
Study (4)

티스토리 툴바