매크로 프로세서 작성중 오류..(도저히 못 찾겠네요...)

San의 이미지


#include <stdio.h>
#include <string.h>
#include <fcntl.h>

#define TT

void GoPass1(char buf[40]);
void GoPass2(char buf[40]);



int main(int argc, char *argv[]) {
FILE *infp, *outfp;
char buf[40];


infp = fopen(argv[1], "r");
outfp = fopen(argv[2], "w");

  if(argc < 3) {
  printf("파일명    원본파일명    목적파일명\n");
  printf("위의 형식을 따라 주세요\n");
  exit(1);
  }

  while(fgets(buf, 40, infp) != NULL) {
  GoPass1(buf);
  }

/*  while(fgets(buf, 40, outfp) != NULL) {
  GoPass2();
  }*/
fclose(infp);
fclose(outfp);

}


void GoPass1(char buf[40]) {
FILE *tmpfp, *insoo1fp, *define; // 패스1과 2사이의 임시파일, 형식인수테이블파일, 매크로정의 테이블파일
char *word[5]; // 인덱스 테이블생성시 사용.

char  cmpbufword[10],*cmpindexword,indexbuf[40]; // 형식인수테이블과 원본테이블에서 읽은 문자비교시.
                                                 // 버퍼에서 읽은 토큰, 형식인수테이블에서 읽은 토큰, 인덱스테이블에서 읽은 한 라인.
                                                 // 원본파일에서 읽은 한 라인은 함수에 buf인수로 넘어온다.
char tmpbuf[10], *cmpindex; // 형식인수 인덱스로 치환하기 위해 그 뒤의 라인을 임시로 저장. 인수명을 인덱스로 치환하기 위한 인덱스 저장.

int i = 0,j;  // 각 기능에서 임시로 사용하는 카운터변수
int index = 0;
static int isMacroBody = 0;   // 매크로 정의 본체를 읽는 중인지 아닌지 체크.1혹은 0.

int chP = 0;
int p = 0;

  if(strstr(buf, "MACRO")!=NULL) { // 읽은 라인에 MACRO 라는 단어가 있으면 인수표 생성시작.
  insoo1fp = fopen("insoo","a");
  define = fopen("define","a");

  fprintf(define,"%s\n",buf);
  isMacroBody = 1;
    while((word[i] = strtok(buf,",\t \n"))!=NULL) {
    i++;
    buf = (char *)0;
    }
    
    for(j = 2; j < i; j++) { 
    fprintf(insoo1fp,"#%d  %s\n", index =(j-1), word[j]);
    }
  fclose(insoo1fp);
  fclose(define);
  return;
  }//여기까지가 매크로 제목줄의 인수로 인수표를 생성하는 부분.메인으로 복귀.



  if(isMacroBody == 0) { // 매크로와 관계 없는 부분은 그냥 tmp에 복사한다.
  tmpfp = fopen("tmp","a");
  fputs(buf, tmpfp);
  fclose(tmpfp);
  return;
  }// 비 매크로 부분 복사후 메인으로 복귀

  else if(isMacroBody == 1) {                                  // 매크로 바디부분처리
  insoo1fp = fopen("insoo","r");
  define = fopen("define","a");

  if(strstr(buf,"ENDM")!=NULL) {
   isMacroBody = 0;
   fputs(&buf[0],define);
   return; // GoPass1 함수를 빠져나가 main으로.
   }


      while(buf[chP]!='\n') {
printf("1111111111\n");fflush(stdout);
        while(buf[chP]==' '||buf[chP]=='\t'||buf[chP]==',') chP++; // 공백을 뛰어넘고 (공백부분일때의 chP의 증가)
        while(buf[chP]!=' '&&buf[chP]!='\t'&&buf[chP]!=','&&buf[chP]!='\n') { 
         // 문자부분은 한문자씩 공백이 아닌지 비교해가면서 공백이면 루프빠져나감.
        cmpbufword[p]=buf[chP];   // 배열의 현재 행에 복사
        p++;                   // 단어가 읽히기 시작한 순간부터 p값 증가.
        chP++;                 // 해당 버퍼 전체에 대한 포인터 (chP값의 문자부분을 읽을때의 증가부분.)        
        }                      // 하나의 단어를 다 저장하면 빠져나간다.                  
      cmpbufword[p] = '\0';   // 문자열 맨 끝에 NULL추가.


      while(fgets(indexbuf,40,insoo1fp)!=NULL) {
        cmpindex = strtok(indexbuf," ,\t\n"); // 첫번째 토큰은 치환할 경우를 대비하여 변수에 저장해둠.     
        cmpindexword = strtok(NULL," ,\t\n"); // 두번째 토큰(아규먼트이름)의 주소를 변수에 저장.
          if(!strcmp(cmpindexword,cmpbufword)) {  printf("ok\n");//원본파일에서 잘라낸 토큰과 인덱스테이블에서 읽은 토큰이 같으면 화면에 ok출력및 if문 진입.
          strcpy(tmpbuf,&buf[chP]);            // 치환의 바로 뒷부분을 치환후 붙이기 위해 저장.
          strcpy(&buf[chP-p],cmpindex);        // 치환할 부분의 시작주소에 인덱스를 치환해 넣는다.
          chP = chP-p+strlen(cmpindex); // 치환한 바로 뒷 부분을 chP가 가리키게 한다.
          strcpy(&buf[chP], tmpbuf);              // chP가 가리키는 부분에 저장해 두었던 치환한 바로 뒷부분에 이어지는 문자열을 복사해 넣는다.
          fputs(&buf[0], define); 
          break;
          } // if(!strmcp) - END
        p = 0;
        }//while(fgets(indexbuf,~~~~) { ) - END
        p = 0;
        rewind(insoo1fp);
      }//while(buf[chP-1]!='\0') - END
   fclose(define);
   fclose(insoo1fp);
   }// else if(isMacroBody == 1) { - END
}// GoPass1(car buf[40]) { - END

코드는 상기와 같습니다...

증상이 하도 이상하여 원인을 알 수가 없네요...

인덱스 테이블과 정의 테이블을 모두 화일로 구현하였는데요

아규먼트가 꼭 'X' 혹은 'XXX'처럼 X

자가 들어가는 것만 제대로 치환이 되고,

나머지는 원래 문자 뒤에 치환이 되어 정의 테이블로 들어가는군요.

예를 들면

MOVES MACRO  X, Y, Z

      MOV AX, X
      MOV BX, Y
      MOV CX, Z

      ENDM

MAIN SEGMENT
     MOVES 1,2,3
     MOV AH, 4CH
     INT  21H
MAIN ENDS
END

가 원본일 경우 정의 테이블에는

OVES MACRO  X, Y, Z

      MOV AX, #1
      MOV BX, Y#2
      MOV CX, Z#3
      ENDM

로 들어가고 있습니다.

인수표를 만드는 순서도 바꾸어보고 , 밑의 명령어순서도 바꾸어 보았는데

꼭 X자가 들어간 것만 골라서 (순서에 상관없이) 제대로 치환되고

나머지는 글자수에 상관없이 원래 이름바로뒤에 '#숫자' 가오니..

한번 X자 를 아규먼트 에서 아예 제외하고 실행하였더니 모든

아규먼트가 하나씩 밀려 나오고 제대로 된 것이 없었습니다.

이런 경우는 무엇이 문제인지..

제가 무엇을 놓치고 있는지 모르겠네요...

시간이 없어 속이 타는 상황이고

가능한한 내일 새벽까지도 깨어 있을 작정이니

보시고 꼭좀 도와주시면 감사하겠습니다.

물론 제가 버그를 발견 하였을 시는 발견 즉시 여기로 와 답글을

달도록 하지요.

San의 이미지

break;
          } // if(!strmcp) - END
        p = 0;
        }//while(fgets(indexbuf,~~~~) { ) - END
        p = 0; 

무심코 넣은 p = 0; 하나.(위의 것)

이 문제였군요.

깊이 생각하지 않고 '여기도 들어 가겠지' 식으로 넣어놓고 잊어버렸

었습니다. 인덱스갯수만큼 비교하기 전에 p를 초기화 시켜 버리면

앞에 바꾼 글자수를 기억못하는 것은 당연하겠지요.

아마도 X만 괜찮았던 것은 X가 첫번째 인덱스여서 루핑으로 다시

돌아가지 않아서일텐데, 제가먼저 테스트 해 본 인덱스 순서 바꾸기도

무슨 정신에선지 잘못 한 듯 합니다.

라면하나 먹고 다시 와서 붙잡으니 힘이 나네요 ^^

gdb print로 해당 구역 내 모든 버퍼를 다

트레이스 해서 찾았습니다 ^^

그럼 이만~

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.