[루아1.1] inout.c inout.h 읽기

3 분 소요

Inout.h

Inout.h 파일은 짧습니다. 함수 선언을 제외하면 extern으로 전역 변수를 외부에서 접근할 수 있게 해주는게 전부입니다.

extern int lua_linenumber;
extern int lua_debug;
extern int lua_debugline;

int  lua_openfile     (char *fn);
void lua_closefile    (void);
int  lua_openstring   (char *s);
void lua_closestring  (void);
int  lua_pushfunction (int file, int function);
void lua_popfunction  (void);
void lua_reportbug    (char *s);

딱히 설명할 것이 더 없네요. 그냥 가볍게 쭉 읽고 지나가죠.

Inout.c

/* Exported variables */
int lua_linenumber;
int lua_debug;
int lua_debugline;

/* Internal variables */
#ifndef MAXFUNCSTACK
#define MAXFUNCSTACK 32
#endif
static struct { int file; int function; } funcstack[MAXFUNCSTACK];
static int nfuncstack=0;

static FILE *fp;
static char *st;
static void (*usererror) (char *s);

Inout.c 파일은 디버거 관련 기능을 구현한 것 같습니다. 그런데 정적 전역 변수들 선언을 보니, 아마도 함수 콜 스택 추적 정도 기능만 구현한 듯 보입니다. 진짜 그런지 코드를 읽어 보죠.

/*
** Function to set user function to handle errors.
*/
void lua_errorfunction (void (*fn) (char *s))
{
 usererror = fn;
}

/*
** Function to get the next character from the input file
*/
static int fileinput (void)
{
 int c = fgetc (fp);
 return (c == EOF ? 0 : c);
}

/*
** Function to get the next character from the input string
*/
static int stringinput (void)
{
 st++;
 return (*(st-1));
}

lua_errorfunction() 함수는 Lua.h 파일에 선언이 있습니다. 외부에 노출되는 라이브러리 함수 구현입니다. 아마 호스트 프로그램에서 에러 함수를 재정의 할 수 있게 해주는 인터페이스인듯 합니다. fileinput() 함수와 stringinput() 함수는 lexer 읽을 때 역할을 봤던 함수입니다.

/*
** Function to open a file to be input unit. 
** Return 0 on success or 1 on error.
*/
int lua_openfile (char *fn)
{
 lua_linenumber = 1;
 lua_setinput (fileinput);
 fp = fopen (fn, "r");
 if (fp == NULL) return 1;
 if (lua_addfile (fn)) return 1;
 return 0;
}

/*
** Function to close an opened file
*/
void lua_closefile (void)
{
 if (fp != NULL)
 {
  lua_delfile();
  fclose (fp);
  fp = NULL;
 }
}

/*
** Function to open a string to be input unit
*/
int lua_openstring (char *s)
{
 lua_linenumber = 1;
 lua_setinput (stringinput);
 st = s;
 {
  char sn[64];
  sprintf (sn, "String: %10.10s...", s);
  if (lua_addfile (sn)) return 1;
 }
 return 0;
}

/*
** Function to close an opened string
*/
void lua_closestring (void)
{
 lua_delfile();
}

루아 소스 코드를 파일로 입력 받거나 문자열로 입력 받을 때, 열고 닫기 위해 각각 호출하는 open, close 함수 짝입니다.

/*
** Call user function to handle error messages, if registred. Or report error
** using standard function (fprintf).
*/
void lua_error (char *s)
{
 if (usererror != NULL) usererror (s);
 else			    fprintf (stderr, "lua: %s\n", s);
}

lua_error() 함수는 에러 출력하는 기본 함수 입니다. 만약 lua_errorfunction() 함수를 호출해서 에러 출력 함수를 재정의하면 해당 재정의한 함수가 호출됩니다.

/*
** Called to execute  SETFUNCTION opcode, this function pushs a function into
** function stack. Return 0 on success or 1 on error.
*/
int lua_pushfunction (int file, int function)
{
 if (nfuncstack >= MAXFUNCSTACK-1)
 {
  lua_error ("function stack overflow");
  return 1;
 }
 funcstack[nfuncstack].file = file;
 funcstack[nfuncstack].function = function;
 nfuncstack++;
 return 0;
}

/*
** Called to execute  RESET opcode, this function pops a function from 
** function stack.
*/
void lua_popfunction (void)
{
 nfuncstack--;
}

lua_pushfunction() 함수는 주석에 기능이 잘 적혀 있네요. 구현 자체는 별것 없습니다. funcstack 배열에 파일 이름과 함수 포인터를 저장합니다. 이 함수는 SETFUNCTION 명령어를 처리할 때 VM이 호출합니다. Lua.stx에 보면 function 문법에서 SETFUNCTION 명령어를 바이트 코드 스택에 넣는데, lua_debug 플래그가 true일 때만 해당 동작을 수행합니다. 디버그 전용 명령어인가봅니다.

/*
** Report bug building a message and sending it to lua_error function.
*/
void lua_reportbug (char *s)
{
 char msg[1024];
 strcpy (msg, s);
 if (lua_debugline != 0)
 {
  int i;
  if (nfuncstack > 0)
  {
   sprintf (strchr(msg,0), 
         "\n\tin statement begining at line %d in function \"%s\" of file \"%s\"",
         lua_debugline, s_name(funcstack[nfuncstack-1].function),
  	 lua_file[funcstack[nfuncstack-1].file]);
   sprintf (strchr(msg,0), "\n\tactive stack\n");
   for (i=nfuncstack-1; i>=0; i--)
    sprintf (strchr(msg,0), "\t-> function \"%s\" of file \"%s\"\n", 
                            s_name(funcstack[i].function),
			    lua_file[funcstack[i].file]);
  }
  else
  {
   sprintf (strchr(msg,0),
         "\n\tin statement begining at line %d of file \"%s\"", 
         lua_debugline, lua_filename());
  }
 }
 lua_error (msg);
}

루아 1.1 소스 코드 전반에 걸쳐 에러 출력할 상황일 때 lua_reportbug() 함수를 호출합니다. lua_debug 플래그가 켜져 있으면 함수 정의 할 때마다 lua_pushfunction() 함수를 호출하므로 그 때 nfuncstack 숫자가 올라갑니다. 그래서 디버그 플래그가 켜져 있으면 더 자세한 정보가 에러 상황에서 출력됩니다.

Inout.c 파일을 다 읽고 나니, 소스 코드에서 의미하는 debug는 제가 생각했던 그런 수준의 디버그는 아니었습니다. 저는 gdb로 디버그하는 수준의 디버깅 정보를 기록하나?했는데 그런것은 아니고 오류 상황일 때 콜 스택을 에러 메시지에 출력해주는 수준의 디버그 기능으로 이해했습니다.

댓글남기기