/***************************************************************************/
/*                                                                         */
/*　　　　６８０９＆６３０９アセンブラ　ＡＳＭ０９  Version1.0             */
/*                                      １９９１年８月２３日（水）         */
/*                                     Ｂｙ　Ｊｕｎ．Ｄｉｍｅ              */
/*                                                                         */
/*        このアセンブラはＦＭ−Ｔｏｗｎｓを対象にかかれたものであり、     */
/*　　　Ｈｉｇｈ−Ｃ以外及びＤＯＳ｜Ｅｘｔｅｎｄｅｒ以外での動作は確認     */
/*　　　していません。                                                     */
/***************************************************************************/
pragma Ipath("a:/inc/");

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

#define BEGIN      {              /****************************************/
#define END        }              /*                                      */
#define IF         if(            /*    この表記法は純正Ｃプログラマには  */
#define THEN       ){             /*  許し難いものでしょうが、Ｃの表記に  */
#define ELSE       }else{         /*  にいつまでも馴れない者の悪掻きだと  */
#define ELSEIF     }else{if(      /*  思ってやってください。ＰＡＳＣＡＬ  */
#define ENDIF      }              /*  風に最初するつもりだったのですが、  */
#define WHILE      while(         /*  長年親しんだＭＷ−Ｂａｓｉｃ風にな  */
#define DO         ){             /*  ってしまいました。                  */
#define FOR        for(           /*                                      */
#define TO         ;              /*                                      */
#define BY         ;              /*                                      */
#define LOOP       for(;;){       /*                                      */
#define ENDWHILE   }              /*                                      */
#define REPEAT     do{            /*                                      */
#define UNTIL(s)   }while(s);     /*                                      */
#define SWITCH(s)  switch(s){     /*                                      */
#define CASE(s)    case(s):       /*                                      */
#define DEFAULT    default:       /*                                      */
#define BREAK      break;         /*                                      */
#define ENDSWITCH  }              /*                                      */
#define RETURN(s)  return(s);     /*                                      */
#define FUNCTION   int            /*                                      */
#define MODULE     void           /*                                      */
#define OR         ||             /*                                      */
#define AND        &&             /*                                      */
#define NOT        !              /*                                      */
#define EQU        ==             /*                                      */
#define NEQ        !=             /*                                      */
#define MODULE     void           /*                                      */
#define ON         0xFF           /*                                      */
#define OFF        0x00           /*                                      */
#define TAB        0x09           /*                                      */
#define LF         0x0A           /*                                      */
#define CR         0x0D           /*                                      */
#define BLANK      0x20           /*                                      */
#define COMMA      0x2C           /*                                      */
#define ZERO       0x00           /****************************************/

typedef struct OP  {char op[5],Code ;} OPCODE;
typedef struct SYM {char *SP,*SA    ;} SYMBOL;
typedef struct CA  {char      *Label
                       ,*Instruction
                           ,*Argment;
                    int     ArgmentC;} COMLINE;
typedef struct CI  {char       *Code
                           ,*Argment;
                    int   Code_Count
                          ,Arg_Count;} CODEINF;

struct Registar { char         R[3];
                  int               Numb;
                } RNum[16] = {{ "D",0x06},{ "X",0x10},{ "Y",0x20},{ "U",0x40}
                             ,{ "S",0x40},{"PC",0x80},{ "W",0x00},{ "V",0x00}
                             ,{ "A",0x04},{ "B",0x02},{"CC",0x01},{"DP",0x08}
                             ,{ "N",0x00},{ "M",0x00},{ "E",0x00},{ "F",0x00}};
char Post_Register[4][2] = {"X","Y","U","S"};
char Code_Info[2][3] = {{0x70,0x00,0x60},{0x30,0x00,0x20}};
char PArea[65536]     ,Symbol_Table[65536]
    ,EQUL_Table[65536],EQU_Table[65536]
    ,SETL_Table[65536],SET_Table[65536];
int Pass_flag = 0,Symbol_Count;
SYMBOL Symbol[255],Equ[255],Set[255];


int           Byte_Count  ;

/******************** 6309 asm Main routin **********************************/
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*　　　                                                                    */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
MODULE main(argc,argv)
int         argc;
char            *argv[];
BEGIN
  FILE *fp,*temp_fp,*Ofp;
  char Label[255],Instruction[10],Argment[255],One_Line[255]/*,*TP*/;
/*  SYMBOL Symbol[255],Equ[255],Set[255];*/
  COMLINE ComLine;
/*  CODEINF CodeInf;*/
  int i,bc,ArgmentC,c,Line_Count,EQU_Count,SET_Count;
  Byte_Count = bc = c = Line_Count = Symbol_Count = EQU_Count = SET_Count = 0;
  ComLine.Label       = Label;
  ComLine.Instruction = Instruction;
  ComLine.Argment     = Argment;

  IF argc < 2 THEN
    exit(0);
  ENDIF

  i = 0;
  WHILE strcmp((char *)argv[i],"-c") NEQ ZERO AND i < argc DO
    i++;
  ENDWHILE
  fp = fopen(argv[i + 1],"r");
  i = 0;
  WHILE strcmp((char *)argv[i],"-o") NEQ ZERO AND i < argc DO
    i++;
  ENDWHILE
  Ofp = fopen(argv[i + 1],"w");
  temp_fp = fopen("temp.$$$","w");

  Symbol[Symbol_Count].SP = Symbol_Table;
  Equ[EQU_Count].SP = EQUL_Table;
  Set[SET_Count].SP = SETL_Table;
  Equ[EQU_Count].SA = EQU_Table;
  Set[SET_Count].SA = SET_Table;  
  WHILE fgets(One_Line,255,fp) NEQ ZERO DO
 /*   printf("%05d ",Line_Count++);*/
    IF One_Line[0] EQU '*' THEN
      strcpy(Label,One_Line);
      Label[strlen(Label) - 1] = ZERO;
/*      printf("     %s\n",Label);*/
    ELSE
      Command_Analysis(One_Line,Label,Instruction,Argment);
      fputs(Label,temp_fp);fputs(" ",temp_fp);
      fputs(Instruction,temp_fp);fputs(" ",temp_fp);
/*      fputs(Argment,temp_fp);fputs(" \n",temp_fp);*/
      IF   strcmp(Instruction,"SET") EQU ZERO
        OR strcmp(Instruction,"EQU") EQU ZERO THEN
        IF strcmp(Instruction,"EQU") EQU ZERO THEN
          Symbol_Entry(ComLine,Equ,&EQU_Count);
        ENDIF
        IF strcmp(Instruction,"SET") EQU ZERO THEN
         Symbol_Entry(ComLine,Set,&SET_Count);
        ENDIF        
      ELSE
        IF Symbol_Entry(ComLine,Symbol,&Symbol_Count) > ZERO THEN
          Symbol[Symbol_Count - 1].SA = (char *)bc;
        ENDIF
      ENDIF
      IF Instruction[0] NEQ ZERO THEN
        fputs(Argment,temp_fp);fputs(" \n",temp_fp);
        ComLine.ArgmentC = ArgmentC = Argment_Count(Argment);
/*        fputs(Argment,temp_fp);fputs(" \n",temp_fp);*/
/*        Number_Analysis(Argment,ArgmentC,temp_fp);*/
        IF ArgmentC EQU 1 THEN
          
        ENDIF
        IF (c = One_Byte_Code(Instruction,&PArea[bc])) EQU 0 THEN
          IF (c = Two_Byte_Code(Instruction,&PArea[bc])) EQU 0 THEN
            IF (c = Search_Branch(Instruction
                                       ,Argment,&PArea[bc],bc)) EQU 0 THEN
               IF (c = Inherent_Code(Instruction,Argment
                                       ,ArgmentC,&PArea[bc])) EQU 0 THEN
                 IF (c = ExImmediate_Code(Instruction,Argment
                                       ,ArgmentC,&PArea[bc])) EQU 0 THEN
                   IF (c = InInstruction(Instruction,Argment
                                       ,ArgmentC,&PArea[bc])) EQU 0 THEN

                   ENDIF
                 ENDIF 
              ENDIF 
            ENDIF
          ENDIF
        ENDIF
      ENDIF

/*      Command_Line_Print(ComLine,bc,c);*/
      bc = bc + c;
    ENDIF
  ENDWHILE
  fclose(fp);
  fclose(temp_fp);

  Pass_flag = 1;
  Line_Count = bc = 0;
  fp = fopen("temp.$$$","r");
  
  WHILE fgets(One_Line,255,fp) NEQ ZERO DO
    printf("%05d ",Line_Count++);
    IF One_Line[0] EQU '*' THEN
      printf("     %s\n",Label);
    ELSE
      Command_Analysis(One_Line,Label,Instruction,Argment);
      IF Instruction[0] NEQ ZERO THEN
        ComLine.ArgmentC = ArgmentC = Argment_Count(Argment);
        IF (c = One_Byte_Code(Instruction,&PArea[bc])) EQU 0 THEN
          IF (c = Two_Byte_Code(Instruction,&PArea[bc])) EQU 0 THEN
            IF (c = Search_Branch(Instruction
                                       ,Argment,&PArea[bc],bc)) EQU 0 THEN
               IF (c = Inherent_Code(Instruction,Argment
                                       ,ArgmentC,&PArea[bc])) EQU 0 THEN
                 IF (c = ExImmediate_Code(Instruction,Argment
                                       ,ArgmentC,&PArea[bc])) EQU 0 THEN
                   IF (c = InInstruction(Instruction,Argment
                                       ,ArgmentC,&PArea[bc])) EQU 0 THEN
                   ENDIF
                 ENDIF 
               ENDIF 
             ENDIF
           ENDIF
         ENDIF
       ENDIF

      Command_Line_Print(ComLine,bc,c);
      bc = bc + c;
    ENDIF
  ENDWHILE
  fclose(fp);

  fwrite(PArea,bc,1,Ofp);
  fclose(Ofp);

  Dump_Code(PArea,bc);

  printf("\n*************************   Label list  ***********************");
  Symbol_Print(Symbol,Symbol_Count,0);
/* printf("\n*************************    EQU list   ***********************");
  Symbol_Print(Equ,EQU_Count,1);
  printf("\n*************************    SET list   ***********************");
  Symbol_Print(Set,SET_Count,1);*/
  

END
/******************** 6309 asm Main routin **********************************/

/************************  Command Analysis *********************************/
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*　　　テキストファイルから１行を読み込みラベル・命令・パラメータに振り    */
/*    分ける。                                                              */
/*                                                                          */
/****************************************************************************/
FUNCTION Command_Analysis(One_Line,Label,Instruction,Argment)
char                     *One_Line
                               ,*Label
                                     ,*Instruction
                                                 ,*Argment;
BEGIN
  int i,j,Return_Variable;

  Return_Variable = Label[0] = Instruction[0] = Argment[0] = i = j = 0;
  WHILE  One_Line[i] > BLANK    AND i < 255 DO
    Label[j] = toupper(One_Line[i]);
    j = j + 1;
    i = i + 1;
  ENDWHILE
  Label[i] = OFF;
  WHILE (One_Line[i] EQU BLANK
      OR One_Line[i] EQU TAB  ) AND i < 255 DO
    i = i + 1;
  ENDWHILE
  j = 0;
  WHILE  One_Line[i] > BLANK    AND i < 255 DO
    Instruction[j] = toupper(One_Line[i]);
    j = j + 1;
    i = i + 1;
  ENDWHILE
  Instruction[j] = OFF;
  WHILE  (One_Line[i] EQU BLANK
      OR  One_Line[i] EQU TAB ) AND i < 255 DO
    i = i + 1;
  ENDWHILE
  j = 0;
  WHILE   One_Line[i] > BLANK   AND i < 255 DO
    Argment[j] = toupper(One_Line[i]);
    j = j + 1;
    i = i + 1;
  ENDWHILE
  Argment[j] = OFF;
  RETURN(Return_Variable);
END
/************************  Command Analysis *********************************/

/**************************  Argment Count  *********************************/
/*                                                                          */
/*　　”，”を一つの区切りとし、スペースを終了コードとしてパラメータの数    */
/*　をカウントする。この時、”，”はヌルコードに置き換える。                */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
FUNCTION  Argment_Count(Argment)
char                    Argment[];
BEGIN
  int i,k;
  i = k = 0;
  IF strlen(Argment) NEQ ZERO THEN
    k = 1;
    WHILE Argment[i] NEQ ZERO DO
      IF Argment[i] EQU COMMA THEN
        Argment[i] = OFF;
        k++;
      ENDIF
      i++;
    ENDWHILE
  ENDIF
  RETURN(k);
END
/**************************  Argment Count  *********************************/

/************************ One Byte Code Analysis ****************************/
/*                                                                          */
/* 　本ルーチンでは１バイト命令インハレントコードのみを処理する。           */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
FUNCTION One_Byte_Code(Instruction,Code)
char                  *Instruction
                                 ,*Code;
BEGIN
  static struct 
    OP Oop[34] = {{ "ABX",0x3A},{"SYNC",0x13},{ "NOP",0x12},{ "MUL",0x3D}
                 ,{ "SWI",0x3F},{ "DAA",0x19}
                 ,{"ASLA",0x48},{"LSLA",0x48},{"ASLB",0x58},{"LSLB",0x58}
                 ,{"ASRA",0x47},{"ASRB",0x57},{"CLRA",0x4F},{"CLRB",0x5F}
                 ,{"COMA",0x43},{"COMB",0x53},{"DECA",0x4A},{"DECB",0x5A}
                 ,{"ROLA",0x49},{"ROLB",0x59},{"RORA",0x46},{"RORB",0x56}
                 ,{ "RTI",0x3B},{ "RTS",0x39},{ "SEX",0x1D},{"SEXW",0x14}
                 ,{"TSTA",0x4D},{"TSTB",0x5D},{"INCA",0x4C},{"INCB",0x5C}
                 ,{"LSRA",0x44},{"LSRB",0x54},{"NEGA",0x40},{"NEGB",0x50}};
  int i = 0;

  WHILE strcmp(Instruction,Oop[i].op) NEQ ZERO AND i < 34 DO
    i++;
  ENDWHILE
  IF i < 34 THEN
    Code[0] = Oop[i].Code;
    i = 1;
  ELSE
    i = 0;
  ENDIF
  RETURN(i);

END
/************************ One Byte Code Analysis ****************************/

/************************ Two Byte Code Analysis ****************************/
/*                                                                          */
/*  本ルーチンでは２バイト命令インハレントコードのみを処理する。            */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
FUNCTION Two_Byte_Code(Instruction,Code)
char                  *Instruction
                                 ,*Code;
BEGIN
  static struct 
  OP T10op[26] = {{ "ASLD",0x48},{ "NEGD",0x40},{ "SWI2",0x3F}
                 ,{ "ASLD",0x48},{ "LSLD",0x48},{ "ASRD",0x47}
                 ,{ "CLRD",0x4F},{ "CLRW",0x5F},{ "COMD",0x43},{ "COMW",0x53}
                 ,{ "DECD",0x4A},{ "DECW",0x5A},{ "ROLD",0x49},{ "ROLW",0x59}
                 ,{ "RORD",0x46},{ "RORW",0x56},{ "TSTD",0x4D},{ "TSTW",0x5D}
                 ,{ "INCD",0x4C},{ "INCW",0x5C},{ "LSRD",0x44},{ "LSRW",0x54}
                 ,{"PSHSW",0x38},{"PSHUW",0x3A},{"PULSW",0x37},{"PULUW",0x3B}
                   };
  static struct
  OP T11op[11] = {{ "SWI3",0x3F}
                 ,{ "CLRE",0x4F},{ "CLRF",0x5F},{ "COME",0x43},{ "COMF",0x53}
                 ,{ "DECE",0x4A},{ "DECF",0x5A},{ "TSTE",0x4D},{ "TSTF",0x5D}
                 ,{ "INCE",0x4C},{ "INCF",0x5C}};

  int i = 0;

  WHILE strcmp(Instruction,T10op[i].op) NEQ ZERO AND i < 26 DO
    i++;
  ENDWHILE
  IF i < 26 THEN
    Code[0] = 0x10;
    Code[1] = T10op[i].Code;
    i = 2;
  ELSE
    i = 0;
    WHILE strcmp(Instruction,T11op[i].op) NEQ ZERO AND i < 11 DO
    i++;
    ENDWHILE
    IF i < 11 THEN
      Code[0] = 0x11;
      Code[1] = T11op[i].Code;
      i = 2;
    ENDIF
    i = 0;    
  ENDIF
  RETURN(i);
END
/************************ One Byte Code Analysis ****************************/

/************************ Inherent Code Analysis ****************************/
/*                                                                          */
/*  インハレントコードの中でもポストバイトの処理を要するものを処理。        */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
FUNCTION Inherent_Code(Instruction,Argment,ArgmentC,Code)
char                  *Instruction
                                 ,*Argment;
int                                        ArgmentC;
unsigned char                                      *Code;
BEGIN
  static struct
    OP IOop[6]  = {{ "TFR",0x1F},{ "EXG",0x1E}
                  ,{"PSHS",0x34},{"PSHU",0x36},{"PULS",0x35},{"PULU",0x37}};
  static struct 
    OP I10op[8] = {{"ADCR",0x31},{"ADDR",0x30},{"ANDR",0x34},{"CMPR",0x37}
                  ,{"SBCR",0x33},{"SUBR",0x32},{"EORR",0x36},{ "ORR",0x35}};
  int i,j,k,re;
  char *TP,TEMP[2][10];
  i = j = k = re = 0;
  Code[0] = Code[1] = Code[2] = ZERO;
  TP = Argment;

  WHILE strcmp(Instruction,IOop[i].op) NEQ ZERO AND i < 6 DO
    i++;
  ENDWHILE
  IF i < 6 THEN
    Code[0] = IOop[i].Code;
    IF i EQU 0 OR i EQU 1 THEN
      WHILE strcmp(TP,RNum[Code[1] / 0x10].R) NEQ ZERO DO
        Code[1] = Code[1] + 0x10;
      ENDWHILE
      TP = TP + strlen(TP) + 1;
      WHILE strcmp(TP,RNum[Code[1] & 0x0f].R) NEQ ZERO DO
        Code[1]++;
      ENDWHILE
    ELSE
      WHILE j++ < ArgmentC DO
        k = 0 ;
        WHILE strcmp(TP,RNum[k].R) NEQ ZERO DO
          k++;
        ENDWHILE
        TP = TP + strlen(TP) + 1;
        Code[1] = Code[1] | RNum[k].Numb;
      ENDWHILE
    ENDIF
    re = 2;
  ENDIF 
  i = 0;
  WHILE strcmp(Instruction,I10op[i].op) NEQ ZERO AND i < 8 DO
    i++;
  ENDWHILE
  IF i < 8 THEN
    Code[0] = 0x10;
    Code[1] = I10op[i].Code;
    WHILE strcmp(TP,RNum[Code[2] / 0x10].R) NEQ ZERO DO
      Code[2] = Code[2] + 0x10;
    ENDWHILE
    TP = TP + strlen(TP) + 1;
    WHILE strcmp(TP,RNum[Code[2] & 0x0f].R) NEQ ZERO DO
      Code[2]++;
    ENDWHILE
    re = 3;
  ENDIF
  
  IF strcmp(Instruction,"TFM") EQU ZERO THEN
    strcpy(TEMP[0],TP);
    TP = TP + strlen(TP) + 1;
    strcpy(TEMP[1],TP);
    Code[0] = 0x11;
    IF   TEMP[0][strlen(TEMP[0]) - 1] EQU '-'
     AND TEMP[1][strlen(TEMP[1]) - 1] EQU '-' THEN
      Code[1] = 0x39;
      TEMP[0][strlen(TEMP[0]) - 1] = ZERO;
      TEMP[1][strlen(TEMP[1]) - 1] = ZERO;
    ELSE
      IF TEMP[0][strlen(TEMP[0]) - 1] EQU '+' THEN
         TEMP[0][strlen(TEMP[0]) - 1] = ZERO;
        IF TEMP[1][strlen(TEMP[1]) - 1] EQU '+' THEN
           TEMP[1][strlen(TEMP[1]) - 1] = ZERO;
          Code[1] = 0x38;
        ELSE
          Code[1] = 0x3A;
        ENDIF
      ELSE
        IF TEMP[1][strlen(TEMP[1]) - 1] EQU '+' THEN
           TEMP[1][strlen(TEMP[1]) - 1] = ZERO;
          Code[1] = 0x3B;
        ENDIF
      ENDIF
      re = 3;
    ENDIF

    WHILE strcmp(TEMP[0],RNum[Code[2]/0x10].R) NEQ ZERO AND Code[2] < 0xFF DO
      Code[2] = Code[2] + 0x10;
    ENDWHILE
    WHILE strcmp(TEMP[1],RNum[Code[2]&0x0F].R) NEQ ZERO AND Code[2] < 0xFF DO
      Code[2]++;
    ENDWHILE
  ENDIF

  RETURN(re);
END
/************************ Inherent Code Analysis ****************************/

/************************* Branch Code Analysis *****************************/
/*                                                                          */
/*   ブランチ命令の処理。                                                   */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
FUNCTION Search_Branch(Instruction,Argment,Code,bc)
char                  *Instruction
                                 ,*Argment
                                         ,*Code;
int                                             bc;
BEGIN
  int Address,i,Count;
  static struct
    OP Bop[21] = {{"LBSR",0x17},{"LBRA",0x16}
                 ,{"BSR",0x8D},{"BRA",0x20},{"BRN",0x21}
                 ,{"BHI",0x22},{"BLS",0x23},{"BCC",0x24},{"BCS",0x25}
                 ,{"BHS",0x24},{"BLO",0x25},{"BNE",0x26},{"BEQ",0x27}
                 ,{"BVC",0x28},{"BVS",0x29},{"BPL",0x2A},{"BMI",0x2B}
                 ,{"BGE",0x2C},{"BLT",0x2D},{"BGT",0x2E},{"BLE",0x2F}};

  IF Argment[0] >= '0' AND Argment[0] <= '9' THEN
    Address = atoi((char *)Argment);
  ELSE
    IF Argment[0] EQU '%' OR Argment[0] EQU '$' THEN
      Address = BHconv(Argment[1]);
    ELSE
      IF Pass_flag NEQ ZERO THEN
        i = 0;
        WHILE strcmp(Argment,Symbol[i].SP) NEQ ZERO AND i < Symbol_Count DO
         i++;
        ENDWHILE
        Address = (int)Symbol[i].SA;
      ELSE
        Address = 0x7FFF;
      ENDIF
    ENDIF
  ENDIF

 Count = i = 0;
 IF strcmp(Instruction,Bop[i++].op) EQU ZERO THEN
    Count = 3;
    Code[0] = Bop[0].Code;
    Code[1] = (Address - bc - Count) / 0x100 & 0xFF;
    Code[2] = (Address - bc - Count)         & 0xFF;
  ELSEIF strcmp((char *)Instruction,Bop[i++].op) EQU ZERO THEN
      Count = 3;
      Code[0] = Bop[1].Code;
      Code[1] = (Address - bc - Count) / 0x100 & 0xFF;
      Code[2] = (Address - bc - Count)         & 0xFF;
    ELSE
      WHILE NOT(strcmp( Instruction   ,Bop[i].op) EQU ZERO
            OR  strcmp(&Instruction[1],Bop[i].op) EQU ZERO
            AND Instruction[0] EQU 'L')   AND    i < 21    DO
        i++;
      ENDWHILE
      IF i < 20 THEN
        IF Instruction[0] EQU 'L' THEN
          Count = 4;
          Code[0] = 0x10;
          Code[1] = Bop[i].Code;
          Code[2] = (Address - bc - Count) / 0x100 & 0xFF;
          Code[3] = (Address - bc - Count)         & 0xFF;
        ELSE
          Count = 2;
          Code[0] = Bop[i].Code;
          Code[1] = (Address - bc - Count)         & 0xFF;
        ENDIF
      ENDIF
    ENDIF
  ENDIF
  RETURN(Count);
END
/************************* Branch Code Analysis *****************************/

/*********************** ExImmediate Code Analysis **************************/
/*   イミディエートコードのない命令全般を処理。                             */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
FUNCTION ExImmediate_Code(Instruction,Argment,ArgmentC,Code)
char                     *Instruction
                                    ,*Argment;
int                                           ArgmentC;
char                                                  *Code;
BEGIN
  static struct 
    OP EI1op[17] = {{ "NEG",0x00},{ "OIM",0x01},{ "AIM",0x02},{ "COM",0x03}
                   ,{ "LSR",0x04},{ "EIM",0x05},{ "ROR",0x06},{ "ASR",0x07}
                   ,{ "ASL",0x08},{ "ROL",0x09},{ "DEC",0x0A},{ "TIM",0x0B}
                   ,{ "INC",0x0C},{ "TST",0x0D},{ "JMP",0x0E},{ "CLR",0x0F}
                   ,{ "LSL",0x08}};
  static struct
    OP EI2op[31] = {{"SUBA",0x90},{"SUBB",0xD0},{"CMPA",0x91},{"CMPB",0xD1}
                   ,{"SBCA",0x92},{"SBCB",0xD2},{"SUBD",0x93},{"ADDD",0xD3}
                   ,{"ANDA",0x94},{"ANDB",0xD4},{"BITA",0x95},{"BITB",0xD5}
                   ,{ "LDA",0x96},{ "LDB",0xD6},{ "STA",0x97},{ "STB",0xD7}
                   ,{"EORA",0x98},{"EORB",0xD8},{"ADCA",0x99},{"ADCB",0xD9}
                   ,{ "ORA",0x9A},{ "ORB",0xDA},{"ADDA",0x9B},{"ADDB",0xDB}
                   ,{"CMPX",0x9C},{ "LDD",0xDC}              ,{ "STD",0xDD}
                   ,{ "LDX",0x9E},{ "LDU",0xDE},{ "STX",0x9F},{ "STU",0xDF}};
  static struct
    OP E10op[18] = {{"SUBW",0x90},{"CMPW",0x91},{"SBCD",0x92},{"CMPD",0x93}
                                 ,{"BITD",0x95},{ "LDW",0x96},{ "STW",0x97}
                   ,{"EORD",0x98},{"ADCD",0x99},{ "ORD",0x9A},{"ADDW",0x9B}
                   ,{"CMPY",0x9C}              ,{ "LDY",0x9E},{ "STY",0x9F}
                   ,{ "LDQ",0xDC},{ "STQ",0xDD},{ "LDS",0xDE},{ "STS",0xDF}};
  static struct
    OP E11op[15] = {{"SUBE",0x90},{"CMPE",0x91}              ,{"CMPU",0x93}
                                               ,{ "LDE",0x96},{ "STE",0x97}
                                                             ,{"ADDE",0x9B}
                   ,{"CMPS",0x9C},{"DIVD",0x9D},{"DIVQ",0x9E},{"MULD",0x9F}
                   ,{"SUBF",0xD0},{"CMPF",0xD1}
                                               ,{ "LDF",0xD6},{ "STF",0xD7}
                                                             ,{"ADDF",0xDB}};
  int re;
  IF (re = NIC_Analysis(Instruction,Argment,ArgmentC
                        , Code   ,Code_Info[0],EI1op,17)) EQU ZERO THEN
    IF (re = NIC_Analysis(Instruction,Argment,ArgmentC
                        , Code   ,Code_Info[1],EI2op,31)) EQU ZERO THEN
      IF (re = NIC_Analysis(Instruction,Argment,ArgmentC
                        ,&Code[1],Code_Info[1],E10op,18)) EQU ZERO THEN
        IF (re = NIC_Analysis(Instruction,Argment,ArgmentC
                        ,&Code[1],Code_Info[1],E11op,15)) EQU ZERO THEN
        ELSE
          re++;
          Code[0] = 0x11;
        ENDIF
      ELSE
        re++;
        Code[0] = 0x10;
      ENDIF
    ENDIF
  ENDIF

  RETURN(re);
END
/*********************** ExImmediate Code Analysis **************************/

/*********************** InImmediate Code Analysis **************************/
/*                                                                          */
/*   イミディエートコードを含む命令全般を処理。                             */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
FUNCTION NIC_Analysis(Instruction,Argment,ArgmentC,Code,Code_Info,CP,CPc)
char                  *Instruction
                                 ,*Argment;
int                                       ArgmentC;
char                                              *Code
                                                      ,*Code_Info;
struct OP                                                        *CP;
int                                                                  CPc;
BEGIN
  int i,j,re,Offset;
  i = j = re = 0;
  WHILE strcmp(Instruction,CP[i].op) NEQ ZERO AND i < CPc DO
    i++;
  ENDWHILE
  IF i < CPc THEN
    Code[0] = CP[i].Code;
    IF ArgmentC EQU 1 THEN
      switch(Argment[0])
      BEGIN
        case'<':
          IF Argment[1] EQU '%' OR Argment[1] EQU '$' THEN
            Offset = BHconv(&Argment[1]);
          ELSE
            Offset = atoi(&Argment[1]);
          ENDIF
          Code[1] = Offset;
          re = 2;
          break;
        case'#':
          IF Argment[1] EQU '%' OR Argment[1] EQU '$' THEN
            Offset = BHconv(&Argment[1]);
          ELSE
            Offset = atoi(&Argment[1]);
          ENDIF
          IF Instruction[0] NEQ 'S' OR Instruction[1] NEQ 'T' THEN
            Code[0] = (Code[0] & 0xCF) | Code_Info[1];
            IF Instruction[strlen(Instruction) - 1] EQU 'D' THEN
              Code[1] = Offset / 0x100 & 0xFF;
              Code[2] = Offset         & 0xFF;
              re = 3;
            ELSE
              Code[1] = Offset         & 0xFF;
              re = 2;
            ENDIF
          ENDIF 
          break;
        case'>':
          IF Argment[1] EQU '%' OR Argment[1] EQU '$' THEN
            Offset = BHconv(&Argment[1]);
          ELSE
            Offset = atoi(&Argment[1]);
          ENDIF
          Code[0] = (Code[0] & 0xCF) | Code_Info[0];
          Code[1] = Offset / 0x100 & 0xFF;
          Code[2] = Offset         & 0xFF;
          re = 3;
          break;
        case'[':
          Code[0] = (Code[0] & 0xCF) | Code_Info[2];
          Code[1] = 0xAF;
          Code[2] = Offset / 0x100 & 0xFF;
          Code[3] = Offset         & 0xFF;
          re = 4;
          break;
        default:break;
      END
    ELSE
      IF ArgmentC EQU 2 THEN
        Code[0] = (Code[0] & 0xCF) | Code_Info[2];
        IF (re = Direct_or_InDirect(Argment,&Code[1])) > ZERO THEN
          j = 0;
          re++;
        ENDIF
      ENDIF
    ENDIF
  ENDIF
  RETURN(re)
END

/*********************** ExImmediate Code Analysis **************************/

/************************** Direct or InDirect  *****************************/
/*                                                                          */
/*  ダイレクト及びインダイレクトの判定。                                    */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
FUNCTION Direct_or_InDirect(Argment,Code)
char                       *Argment
                                  ,*Code;
BEGIN
  char *TEMP[2],buffer[20];
  int  Return_Variable = 0;
  TEMP[0] = buffer;
  strcpy(TEMP[0],Argment);
  TEMP[1] = TEMP[0] + strlen(TEMP[0]) + 1;
  strcpy(TEMP[1],&Argment[strlen(Argment) + 1]);
  IF TEMP[0][0]  EQU '[' THEN
    IF TEMP[1][strlen(TEMP[1]) - 1] EQU ']' THEN
      strcpy(TEMP[0],&Argment[1]);
      TEMP[1][strlen(TEMP[1]) - 1] = ZERO;
      IF (Return_Variable = PostByte_Analysis(TEMP,Code)) > ZERO THEN
        Code[0] = Code[0] | 0x10;
        IF (Code[0] & 0x8F) EQU 0x8F THEN
          Code[0] = Code[0] & 0xF0;
        ENDIF
      ENDIF
    ENDIF
  ELSE
    Return_Variable = PostByte_Analysis(TEMP,Code);
  ENDIF
  RETURN(Return_Variable);
END
/************************** Direct or InDirect  *****************************/

/*************************** PostByte Analysis ******************************/
/*                                                                          */
/*  ポストバイトの解析。                                                    */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
FUNCTION PostByte_Analysis(Argment,Code)
char                     **Argment
                                 ,*Code;
BEGIN
  int Byte_Length;
  IF (Byte_Length = PCW_Judgment(Argment,Code)) EQU ZERO THEN
    IF (Byte_Length = AutoInc_Judgment(Argment,Code)) EQU ZERO THEN
      IF (Byte_Length = Acc_Judgment(Argment,Code)) EQU ZERO THEN
      ENDIF
    ENDIF
  ENDIF
  RETURN(Byte_Length);
END
/*************************** PostByte Analysis ******************************/

/************************** Bit Length Judgment *****************************/
/*                                                                          */
/*　相対アドレスのビット長の計算。                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
FUNCTION BitLen(Offset)
int             Offset;
BEGIN
  int Bit_Length = 0;
  IF Offset NEQ ZERO THEN
    IF Offset >= -16 AND Offset < 16 THEN
      Bit_Length = 5;
    ELSE
      IF Offset >= -128 AND Offset < 128 THEN
        Bit_Length = 8;
      ELSE
        IF Offset >= -32768 AND Offset < 32768 THEN
          Bit_Length = 16;
        ENDIF
      ENDIF
    ENDIF
  ENDIF
  RETURN(Bit_Length);
END
/************************** Bit Length Judgment *****************************/

/***************** PC Register And W Register Judgment **********************/
/*                                                                          */
/*  ＰＣレジスタとＷレジスタの判定。                                        */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
FUNCTION PCW_Judgment(Argment,Code)
char                **Argment
                            ,*Code;
BEGIN
  int Bit_Length,Byte_Length,Offset,i;
  IF Argment[0][0] EQU '%' OR Argment[0][0] EQU '$' THEN
    Offset = BHconv(Argment[0]);
  ELSE
    Offset = atoi(Argment[0]);
  ENDIF
  IF Offset > ZERO OR strlen(Argment[0]) EQU ZERO THEN
    Bit_Length = BitLen(Offset);
    Byte_Length = 0;
    IF strcmp(Argment[1],"PCR") EQU ZERO THEN
      Code[0] = 0x8C;
      IF Bit_Length > 8 THEN
        Code[0] = Code[0] | 0x01;
        Code[1] = Offset / 0x100 & 0xFF;
        Code[2] = Offset         & 0xFF;
        Byte_Length = 3;
      ELSE
        Code[1] = Offset         & 0xFF;
        Byte_Length = 2;
      ENDIF
    ENDIF
    IF strcmp(Argment[1],  "W") EQU ZERO THEN
      Code[0] = 0x8F;
      Byte_Length = 1;
      IF Bit_Length NEQ ZERO THEN
        Code[0] = Code[0] | 0x20;
        Code[1] = Offset / 0x100 & 0xFF;
        Code[2] = Offset         & 0xFF;
        Byte_Length = 3;
      ENDIF
    ENDIF
    i = 0;
    WHILE strcmp(Argment[1],Post_Register[i]) NEQ ZERO AND i < 4 THEN
      i++;
    ENDWHILE
    IF i < 4 THEN
      Code[0] = (char)(i * 0x20);
      Byte_Length = 1;
      SWITCH(Bit_Length)
        CASE( 0)
          Code[0] = Code[0] | 0x84       ;BREAK
        CASE( 5)
          Code[0] = Code[0] | Offset     ;BREAK
        CASE( 8)
          Code[0] = Code[0] | 0x88       ;
          Code[1] = Offset         & 0xFF;
          Byte_Length++                  ;BREAK
        CASE(16)
          Code[0] = Code[0] | 0x89       ;
          Code[1] = Offset / 0x100 & 0xFF;
          Code[2] = Offset         & 0xFF;
          Byte_Length = 3                ;BREAK
        DEFAULT BREAK
      ENDSWITCH
    ENDIF
  ELSE
    Byte_Length = 0;
  ENDIF
  RETURN(Byte_Length);
END
/***************** PC Counter And W Register Judgment ***********************/

/*********************** Auto Incriment Judgment ****************************/
/*                                                                          */
/*  オートインクリメントの処理。                                            */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
FUNCTION AutoInc_Judgment(Argment,Code)
char                    **Argment
                                ,*Code;
BEGIN
  int i = 0,j = 0,Byte_Length = 0;

  IF Argment[1][strlen(Argment[1]) - 1] EQU '+' THEN
    Code[0] = 0x80;
    Argment[1][strlen(Argment[1]) - 1] = ZERO;
    IF Argment[1][strlen(Argment[1]) - 1] EQU '+' THEN
      Code[0] = Code[0] | 0x01;
      Argment[1][strlen(Argment[1]) - 1] = ZERO;
      IF strcmp(Argment[1],"W") EQU ZERO THEN
        Byte_Length = 1;
        Code[0] = 0xCF;
      ENDIF
    ENDIF
    WHILE strcmp(Argment[1],Post_Register[i]) NEQ ZERO AND i < 4 DO
      i++;
    ENDWHILE
    IF i < 4 THEN
      Byte_Length = 1;
      Code[0] = Code[0] | (char)(i * 0x20);
    ENDIF
  ENDIF

  IF Argment[1][0] EQU '-' THEN    
    Code[0] = 0x82;
    j = 1;
    IF Argment[1][1] EQU '-' THEN
      Code[0] = Code[0] | 0x01;
      j++;
      IF strcmp(&Argment[1][2],"W") EQU ZERO THEN
        Byte_Length = 1;
        Code[0] = 0xEF;
      ENDIF      
    ENDIF
    WHILE strcmp(&Argment[1][j],Post_Register[i]) NEQ ZERO AND i < 4 DO
      i++;
    ENDWHILE
    IF i < 4 THEN
      Byte_Length = 1;
      Code[0] = Code[0] | (char)(i * 0x20);
    ENDIF
  ENDIF

  RETURN(Byte_Length);
END
/*********************** Auto Incriment Judgment ****************************/

/************************ Accumulators Jugment ******************************/
/*                                                                          */
/*  アキュムレータレジスタとインデックスレジスタの演算を含んだ処理。        */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
FUNCTION Acc_Judgment(Argment,Code)
char                **Argment
                            ,*Code;
BEGIN
  int i = 0;

  WHILE strcmp(Argment[1],Post_Register[i]) NEQ ZERO AND i < 4 DO
    i++;
  ENDWHILE
  IF i < 4 THEN
    Code[0] = (char)(i * 0x20);
    i = 1;
    IF strcmp(Argment[0],"A") EQU ZERO THEN
      Code[0] = Code[0] | 0x86;
    ELSE
      IF strcmp(Argment[0],"B") EQU ZERO THEN
        Code[0] = Code[0] | 0x85;
      ELSE
        IF strcmp(Argment[0],"D") EQU ZERO THEN
          Code[0] = Code[0] | 0x8B;
        ELSE
          IF strcmp(Argment[0],"E") EQU ZERO THEN
            Code[0] = Code[0] | 0x87;
          ELSE
            IF strcmp(Argment[0],"F") EQU ZERO THEN
              Code[0] = Code[0] | 0x8A;
            ELSE
              IF strcmp(Argment[0],"W") EQU ZERO THEN
                Code[0] = Code[0] | 0x8E;
              ELSE
                i = 0;
              ENDIF
            ENDIF
          ENDIF
        ENDIF
      ENDIF
    ENDIF
  ENDIF

  RETURN(i) 
END
/************************* Accumulators Judgment ****************************/

/************************** InInstruction ***********************************/
/*                                                                          */
/*  データ部表記用疑似命令処理。                                            */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
FUNCTION InInstruction(Instruction,Argment,ArgmentC,Code)
char                  *Instruction
                                 ,*Argment;
int                                        ArgmentC;
char                                               *Code;
BEGIN
  int i = 0,Byte_Count = 0;
  char *TP,Delimiter;
  TP = Argment;
  IF strcmp(Instruction,"FCB") EQU ZERO THEN
    WHILE Byte_Count < ArgmentC DO
      Code[Byte_Count++] = atoi(TP);
      TP = TP + strlen(TP) + 1;
    ENDWHILE
  ELSE
    IF strcmp(Instruction,"FDB") EQU ZERO THEN
      WHILE (Byte_Count / 2) < ArgmentC DO
        Code[Byte_Count++] = atoi(TP) / 0x100 & 0xFF;
        Code[Byte_Count++] = atoi(TP)         & 0xFF;
        TP = TP + strlen(TP) + 1;
      ENDWHILE
    ELSE
      IF   strcmp(Instruction,"FCC") EQU ZERO 
        OR strcmp(Instruction,"FCS") EQU ZERO THEN
        IF Argment[0] > 0x20 AND Argment[0] <= 0x2F THEN
          Delimiter = Argment[0];
          i = 1;
          WHILE Argment[i] NEQ Delimiter DO
            Code[Byte_Count++] = Argment[i++];
          ENDWHILE
        ENDIF
        IF strcmp(Instruction,"FCS") EQU ZERO THEN
          Code[Byte_Count - 1] = Code[Byte_Count - 1] | 0x80;
        ENDIF
      ENDIF
    ENDIF
  ENDIF
  RETURN(Byte_Count);
END
/************************** InInstruction ***********************************/

/************************** Symbol Print ************************************/
/*                                                                          */
/*　シンボルネームの一覧。                                                  */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
FUNCTION Symbol_Print(Symbol,Symbol_Count,flag)
struct SYM           *Symbol;
int                          Symbol_Count,flag;
BEGIN
  int i,j;
  i = j = 0;
  printf("\n");
  WHILE j < Symbol_Count DO
    printf("%04d %s ",j,Symbol[j].SP);
    IF flag EQU ZERO THEN
    WHILE (i + strlen(Symbol[j].SP)) < 66 DO
      printf("-");i++;
    ENDWHILE
      printf(" %04X\n",Symbol[j++].SA);
    ELSE
      WHILE (i + strlen(Symbol[j].SP) + strlen(Symbol[j - 1].SA)) < 70 DO
        printf("-");i++;
      ENDWHILE
      printf(" %s\n",Symbol[j].SA);
    ENDIF
  i = 0;
  ENDWHILE
  RETURN(0);
END
/************************** Symbol Print ************************************/

/*************************** Dump Code **************************************/
/*　アセンブルされたコードをダンプ形式で表示。                              */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
FUNCTION Dump_Code(Code,Count)
unsigned char     *Code;
int                     Count;
BEGIN
  int i,j;
  i = j = 0;
  printf("\n");
  WHILE i < Count DO
    printf("%04X ",i);
    j = 0;
    WHILE j++ < 16 DO
      printf("%02X ",Code[i++]);
    ENDWHILE
    printf("   ");
    j = 0;
    i = i - 16;
    WHILE j++ < 16 DO
      IF Code[i] > 0x20 THEN
        printf("%1c",Code[i]);
      ELSE
        printf(".");
      ENDIF
      i++;
    ENDWHILE
    printf("\n");
  ENDWHILE
  RETURN(0);
END
/*************************** Dump Code **************************************/

/*********************** Command Line Print *********************************/
/*                                                                          */
/*　コマンドラインの表示。                                                  */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
FUNCTION Command_Line_Print(ComLine,bc,c)
COMLINE            ComLine;
int                        bc,c;
BEGIN
  int    j;
  char *TP;

  IF c NEQ ZERO THEN
    printf("%04X ",bc);
  ELSE
    printf("     ");
  ENDIF

  j = 0;
  WHILE j < 8 DO
    IF j++ < c THEN
      printf("%02X ",(unsigned char)PArea[bc++]);
    ELSE
      printf("   ");
    ENDIF
  ENDWHILE

  WHILE j++ < c DO bc++; ENDWHILE

  printf("%-10s",ComLine.Label);
  printf("%-6s" ,ComLine.Instruction);
  j = 0;
  TP = ComLine.Argment;
  printf("%s",TP);
  WHILE j++ < ComLine.ArgmentC - 1 DO
    TP = TP + strlen(TP) + 1;
    printf(",%s",TP);
  ENDWHILE 
  printf("\n");
  RETURN(0);
END
/*********************** Command Line Print *********************************/

/************************ Symbol Entry **************************************/
/*                                                                          */
/*  シンボル，ＥＱＵ，ＳＥＴ命令のラベルを登録。                            */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
FUNCTION Symbol_Entry(ComLine,Symbol,Count)
COMLINE               ComLine;
SYMBOL                       *Symbol;
int                                 Count[];
BEGIN
  int i = 0;
  IF strlen(ComLine.Label) > 0 THEN
    WHILE strcmp(ComLine.Label,Symbol[i].SP) NEQ ZERO AND i++ < Count[0] DO
    ENDWHILE
    IF i < Count[0]  THEN
      IF strcmp(ComLine.Instruction,"SET") NEQ ZERO THEN
      printf("Error !!\n");
      i = -1;
      ELSE
      ENDIF
    ELSE
      strcpy(Symbol[Count[0]++].SP,ComLine.Label);
      Symbol[Count[0]].SP = Symbol[Count[0]-1].SP + strlen(ComLine.Label ) + 1;
      IF   strcmp(ComLine.Instruction,"SET") EQU ZERO
        OR strcmp(ComLine.Instruction,"EQU") EQU ZERO THEN
        strcpy(Symbol[Count[0] - 1].SA,ComLine.Argment);
        Symbol[Count[0]].SA= Symbol[Count[0]-1].SA+strlen(ComLine.Argment) + 1;
      ENDIF
    ENDIF
  ELSE
    i = -1;
  ENDIF
  RETURN(i);
END
/************************ Symbol Entry **************************************/

/*************************** BHconv *****************************************/
/*　アセンブルされたコードを                                                */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
FUNCTION BHconv(BH)
unsigned char   BH[];
BEGIN
  int I = 0,i = 1;
  IF BH[0] EQU '%' THEN
    WHILE BH[i] EQU 0x30 OR BH[i] EQU 0x31 DO
      I = I * 2;
      I = I + BH[i++] - '0';
    ENDWHILE
  ENDIF
  IF BH[0] EQU '$' THEN
    WHILE BH[i] >= '0' AND BH[i] <= '9' 
       OR BH[i] >= 'A' AND BH[i] <= 'F' DO
      I = I * 0x10;
      IF BH[i] > '9' THEN
        I = I + BH[i] - 'A' + 10;
      ELSE
        I = I + BH[i] - '0';
      ENDIF
      i++;
    ENDWHILE
  ENDIF
  RETURN(I);
END
/*************************** BHconv *****************************************/
