== QSEAWK ==

QSEAWK는 임베딩가능한 AWK인터프리터이며, [wiki:FrontPage QSE] 라이브러리의 일부입니다. 이 인터프리터는 [http://cm.bell-labs.com/cm/cs/awkbook/ The AWK Programming Language]에 기술되어 있는 언어를 구현하며, 일련의 확장도 포함하고 있습니다. 플랫폼 의존성을 최소화 하면서, 유연하고 견고한 임베딩API를 작성하는데 중점을 두고 있습니다. 임베딩하는 응용프로그램은 다음의 작업들을 수행할 수 있습니다.

 * 새로운 전역변수와 함수 추가
 * 전역변수의 값을 변경하거나 가져오기
 * 함수를 호출하고 리턴값을 가져오기
 * 파일, 파이프, 콘솔 입출력 처리방법을 원하는대로 변경하기
 * 독립적인 한개 이상의 인터프리터 생성하기
 * 한개의 스크립트를 서로 다른 입출력 방법을 이용하여 독립적으로 실행하기
 * 선택사항을 변경하여 언어의 형태를 변경하기
 * 기타 다른 것들

인터프리터를 임베딩하려면 일반적으로 다음의 과정을 따라야 합니다.

 * 새로운 인터프리터 열기
 * 소스 스크립트 분석하기
 * 실행 문맥 열기
 * BEGIN,패턴-액션,END블록들을 실행 하거나 함수를 호출하기
 * 실행 문맥 닫기
 * 인터프리터 닫기

아래의 C 코드는 이 과정을 보여줍니다. 한줄 짜리 스크립트 '''BEGIN { print "hello, world" }'''을 실행합니다.

{{{
/* cc -o hello hello.c -lqsecmn -lqseawk */
#include <qse/awk/std.h>
#include <qse/cmn/stdio.h>

#define FAIL(msg) do { qse_printf(QSE_T("ERR: %s\n"),msg); goto oops; } while(0)

int main ()
{
    qse_awk_t* awk = QSE_NULL;
    qse_awk_rtx_t* rtx = QSE_NULL;
    qse_awk_val_t* retv;
    qse_awk_parsestd_in_t psin;
    int ret = -1;

    awk = qse_awk_openstd (0); /* 인터프리터 열기 */
    if (!awk) FAIL ("cannot open awk");

    /* 문자열에 저장된 스크립트 분석하기 */
    psin.type = QSE_AWK_PARSESTD_CP;
    psin.u.cp = QSE_T("BEGIN { print \"hello, world\" }");
    if (qse_awk_parsestd (awk, &psin, QSE_NULL) <= -1) 
        FAIL (qse_awk_geterrmsg(awk));

    rtx = qse_awk_rtx_openstd ( /* 실행문맥 열기 */
        awk, 0,             /* 확장영역 없음 */
        QSE_T("hello"),     /* ARGV[0] */
        QSE_NULL,           /* stdin */
        QSE_NULL            /* stdout */               
    );
    if (!rtx) FAIL (qse_awk_geterrmsg(awk));
    
    retv = qse_awk_rtx_loop (rtx); /* BEGIN,패턴-액션,END블록 실행하기 */
    if (!retv) FAIL (qse_awk_rtx_geterrmsg(rtx));

    qse_awk_rtx_refdownval (rtx, retv); /* 리턴값 제거 */
    ret = 0;

oops:
    if (rtx) qse_awk_rtx_close (rtx); /* 실행문맥 닫기 */
    if (awk) qse_awk_close (awk); /* 인터프리터 닫기 */
    return ret;
}
}}}

C++용 API를 사용하면 보다 간단한 처리가 가능합니다. 단, C++용 API는 인터프리터당 하나의 실행 문맥만 지원합니다.

{{{
/* c++ -o hello hello.cpp -lqsecmn -lqseawk -lqseawkxx */
#include <qse/awk/StdAwk.hpp>
#include <iostream>

#ifdef QSE_CHAR_IS_MCHAR
#       define xcout std::cout
#else
#       define xcout std::wcout
#endif

struct MyAwk: public QSE::StdAwk { ~MyAwk () { QSE::StdAwk::close (); } };

#define FAIL(awk) do { \
    xcout << QSE_T("ERR: ") << awk.getErrorMessage() << std::endl; \
    return -1; \
} while (0)

int main (int argc, char* argv[])
{
    MyAwk awk;

    // 새로운 인터프리터 열기
    if (awk.open () <= -1) FAIL (awk);

    // ARGV[0] 설정하기
    if (awk.addArgument (QSE_T("hello")) <= -1) FAIL (awk);

    // 문자열에 저장된 스크립트 분석
    MyAwk::SourceString in(QSE_T("BEGIN { print \"hello, world\" }"));
    if (awk.parse (in, MyAwk::Source::NONE) == QSE_NULL) FAIL (awk);

    // BEGIN,패턴-액션,END블록 실행하기
    MyAwk::Value r;
    if (awk.loop (&r) <= -1) FAIL (awk);

    return 0;
}
}}}
