/************************************************
 *                                              *
 *       ***************************            *
 *       *  HAPPy Pascal Compiler  *            *
 *       ***************************            *
 * ( HAPPy = H.Asano Pascal Processing system ) *
 *                                              *
 *     Original program                         *
 *             ---  Pascal P4 ---               *
 *                                              *
 *     Pascal-P4は、public domainらしい｡        *
 *     このHAPPyの著作権は浅野比富美にある｡     *
 *     HAPPyは、Pascal-p4のソースをもとに、     *
 *     アルゴリズムにたちかえって解析し、       *
 *     PascalからC言語に書換え､ISO7185規格に    *
 *     準拠させるため、独自の創作を加えたもの   *
 *     である｡                                  *
 *                                              *
 *        Copyright(c) H.Asano. 1992-1994.      *
 *           All rights resereved.              *
 *                                              *
 ************************************************/

#define EXTERN                          /* pascomp.hで使用            */

#define abnormal  1                     /* usage関数への引数          */
#define normal    0                     /* usage関数への引数          */

#define NormalEnd     0                 /* 正常終了の終了コード       */
#define CompileError  1                 /* コンパイルエラーの終了コード*/
#define EtcError      2                 /* その他のエラーの終了コード */

#include <stdio.h>
#include <string.h>
#include <process.h>
#include <stdlib.h>
#include <ctype.h>
#include "version.h"
#include "pascomp.h"

extern void init(void) ;                /* 初期設定処理               */
extern void insymbol(void);             /* 記号入力処理               */
extern void programme(void);            /* promgramのコンパイル処理   */

FILE *passource ;                       /* pascalソースファイルポインタ */
FILE *pcdfile   ;                       /* P-codeソースファイルポインタ */

static char *asm = "PA.OVL" ;           /* アセンブラのファイル名       */
static char *TempPath       ;           /* 環境変数 TMP の 設定内容     */
static char *PcodeSourceName = "pcode.pcs" ;  /* P-codeソースファイル名 */
static char PcodeSname[30]    ;        /* P-codeソースファイル名        */
static char drive[3] ;
static char dir[31] ;
static char fname[9] ;
static char ext[4] ;

static boolean asmlst = false  ;

/**************************************/
/*    usage() : 使用方法出力処理      */
/**************************************/
static void usage(int type)
{
if(type == abnormal)
 fputs("\nC001: 起動パラメータが誤っている\n",stderr);
else {
 fputs("\n  HAPPy is the H.Asano Pascal Processing system. (^_^)\n",
             stderr);
 fputs(
  "\n  HAPPyはISO7185規格水準0にほぼ準拠したMS-DOS汎用Pascal処理系です。\n",
           stderr) ;
 fputs("  HAPPyの複写・再配付は自由です。\n", stderr) ;
}

fputs("\n  pcｺﾏﾝﾄﾞはPascalｿｰｽからｶﾚﾝﾄﾃﾞｨﾚｸﾄﾘにP-codeｵﾌﾞｼﾞｪｸﾄ(pcode.pco)を\n",
         stderr);
fputs("  作ります。できたｵﾌﾞｼﾞｪｸﾄはpiｺﾏﾝﾄﾞで実行させます。\n\n",stderr);

     fputs("  使い方:  pc [ ｵﾌﾟｼｮﾝ... ] Pascalソースファイル名\n",stderr) ;

     fputs("  ｵﾌﾟｼｮﾝ:\n",stderr);
     fputs("     -c ･･･ 構文チェックのみ行う\n",stderr);
     fputs("     -a ･･･ アセンブルリストを標準出力に出力する\n",stderr);
     fputs("     -d ･･･ 範囲チェック等を行うコードを生成する\n",stderr);

     exit(EtcError);                    /* その他のエラーで終了       */
}

/**************************************/
/* argment() : 起動アーギュメント処理 */
/**************************************/
static void argment(int argc,char *argv[])
{
  int  j  ;
  boolean getfileflag = false ;

    if(argc < 2)  usage(normal);        /* アーギュメントなしの時はusage*/

    _splitpath(argv[0],drive,dir,fname,ext) ; /* コマンド名の分解     */
    TempPath = getenv("TMP") ;          /* 環境変数 TMP を取得        */
    pcode = true  ;                     /* Pコード出力要(ﾃﾞﾌｫﾙﾄ)      */
    pcdinf= false ;                     /* Pコード情報出力不要(ﾃﾞﾌｫﾙﾄ)*/
    debug = false ;                     /* 範囲チェック不要(ﾃﾞﾌｫﾙﾄ)   */
    while(--argc) {
     if(getfileflag) {
       usage(abnormal);                 /* ソースファイル名以降に     */
       break ;                          /* アーギュメントがある場合   */
     }
     if(**++argv == '-') {
      for(j=1;*(*argv+j)!='\0';j++) {
       switch(tolower(*(*argv+j))) {    /* 大文字の時は小文字に変換   */
        case 'c' : pcode  = false ;
                   break          ;
        case 'a' : pcode  = true  ;
                   pcdinf = true  ;
                   asmlst = true  ;
                   break          ;
        case 'd' : debug  = true  ;
                   break          ;
        default  : usage(abnormal);
       }
      }
      if(j==1)  usage(abnormal);        /* - だけの時はusage          */
     }
     else {
      getfileflag = true ;
      passname  = *argv++;
     }
    }

    if(getfileflag) {                   /* ファイル名が指定された時   */
     passource = fopen(passname,"r");
     if(passource == NULL) {
      fprintf(stderr,"C002: Pascalソースファイル(%s)がない\n", passname);
      exit(EtcError);
     }
    }
    else usage(abnormal) ;              /* ファイル名の指定がない時   */

    if(pcode) {
     strcpy(PcodeSname,TempPath) ;
     strcat(PcodeSname,PcodeSourceName) ;
     pcdfile = fopen(PcodeSname,"w");
     if(pcdfile == NULL) {
      fprintf(stderr,"C003: P-codeソースファイル(%s)が作れない\n",PcodeSname) ;
      exit(EtcError);
     }
    }
}

/***************************************/
/*         term() : 終了処理           */
/***************************************/
void term(void)
{
  int resultcode ;
  char instsize[7]  ;

    if(pcode && (errorcount == 0)) {
     fputs(" *** Compile  completed. ***\n",stderr) ;
     fclose(pcdfile) ;
     sprintf(instsize,"%d",ic) ;
     if(asmlst)
      resultcode=execl(strcat(strcat(drive,dir),asm),"",
                       instsize,PcodeSname,version,"l",NULL);
                                                 /* アセンブルリスト付*/
     else
      resultcode=execl(strcat(strcat(drive,dir),asm),"",
                       instsize,PcodeSname,version,NULL) ;
                                                 /* 通常のアセンブル  */
     if(resultcode == -1) {             /* アセンブラが起動できない   */
      fprintf(stderr,"C004: アセンブラ(%s)が起動できない\n",asm) ;
      exit(EtcError) ;
     }
    }
    else if(errorcount != 0) {
     fprintf(stderr," *** %d errors detected. Fail in compile ***\n",
                      errorcount);
    exit(CompileError) ;
    }
    else {                              /* pcode = false              */
     fputs(" *** No Error ***\n",stderr);
     exit(NormalEnd) ;
    }
}

/**************************************/
/*       main() : メイン処理          */
/**************************************/
void main(int argc,char *argv[])
{

    fprintf(stderr,
 "HAPPy Pascal Compiler Version %s  Copyright (c) H.Asano 1992-1994.\n",
                                version) ;

    argment(argc,argv) ;                /* 起動アーギュメント処理     */

    init();                             /* compiler 初期設定処理      */

    insymbol();                         /* 最初のsymbolを読む         */
    programme();                        /* programのコンパイル        */

    term() ;                            /* 終了処理                   */
}
