依存関係を整理
[YACASL2.git] / src / casl2.c
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 #define _GNU_SOURCE
5 #include <getopt.h>
6
7 #include "assemble.h"
8 #include "exec.h"
9 #include "cerr.h"
10 #include "cmem.h"
11
12 /**
13  * casl2コマンドのオプション
14  */
15 static struct option longopts[] = {
16     { "source", no_argument, NULL, 's' },
17     { "label", no_argument, NULL, 'l' },
18     { "labelonly", no_argument, NULL, 'L' },
19     { "assembledetail", no_argument, NULL, 'a' },
20     { "assembledetailonly", no_argument, NULL, 'A' },
21     { "assembleout", optional_argument, NULL, 'o' },
22     { "assembleoutonly", optional_argument, NULL, 'O' },
23     { "trace", no_argument, NULL, 't' },
24     { "tracearithmetic", no_argument, NULL, 't' },
25     { "tracelogical", no_argument, NULL, 'T' },
26     { "dump", no_argument, NULL, 'd' },
27     { "memorysize", required_argument, NULL, 'M' },
28     { "clocks", required_argument, NULL, 'C' },
29     { "help", no_argument, NULL, 'h' },
30     { 0, 0, 0, 0 },
31 };
32
33 /**
34  * casl2のエラー定義
35  */
36 static CERR cerr_casl2[] = {
37     { 126, "no source file" },
38 };
39
40 /**
41  * アセンブル結果を書き込むファイルの名前
42  */
43 static const char *objfile_name(const char *str)
44 {
45     const char *default_name = "a.o";
46     return (str == NULL) ? default_name : str;
47 }
48
49 /**
50  *  casl2コマンドのメイン
51  */
52 int main(int argc, char *argv[])
53 {
54     int memsize = DEFAULT_MEMSIZE, clocks = DEFAULT_CLOCKS;
55     int status = 0, opt, i;
56     PASS pass;
57     bool res = false;
58     WORD beginptr[argc];
59     char *objfile = NULL;
60     const char *usage =
61         "Usage: %s [-slLaAtTdh] [-oO[<OBJECTFILE>]] [-M <MEMORYSIZE>] [-C <CLOCKS>] FILE1[ FILE2  ...]\n";
62
63     cerr_init();
64     addcerrlist(sizeof(cerr_casl2), cerr_casl2);
65     /* オプションの処理 */
66     while((opt = getopt_long(argc, argv, "tTdslLao::O::AM:C:h", longopts, NULL)) != -1) {
67         switch(opt) {
68         case 's':
69             asmode.src = true;
70             break;
71         case 'l':
72             asmode.label = true;
73             break;
74         case 'L':
75             asmode.label = true;
76             asmode.onlylabel = true;
77             break;
78         case 'a':
79             asmode.asdetail = true;
80             break;
81         case 'A':
82             asmode.asdetail = true;
83             asmode.onlyassemble = true;
84             break;
85         case 'o':
86             objfile = strdup_chk(objfile_name(optarg), "objfile");
87             break;
88         case 'O':
89             asmode.onlyassemble = true;
90             objfile = strdup_chk(objfile_name(optarg), "objfile");
91             break;
92         case 't':
93             execmode.trace = true;
94             break;
95         case 'T':
96             execmode.trace = true;
97             execmode.logical = true;
98             break;
99         case 'd':
100             execmode.dump = true;
101             break;
102         case 'M':
103             memsize = atoi(optarg);
104             break;
105         case 'C':
106             clocks = atoi(optarg);
107             break;
108         case 'h':
109             fprintf(stdout, usage, argv[0]);
110             return 0;
111         case '?':
112             fprintf(stderr, usage, argv[0]);
113             exit(-1);
114         }
115     }
116     /* ソースファイルが指定されていない場合は終了 */
117     if(argv[optind] == NULL) {
118         setcerr(126, NULL);    /* no source file */
119         fprintf(stderr, "CASL2 error - %d: %s\n", cerr->num, cerr->msg);
120         exit(-1);
121     }
122     /* COMET II仮想マシンのリセット */
123     reset(memsize, clocks);
124     /* アセンブル。ラベル表作成のため、2回行う */
125     for(pass = FIRST; pass <= SECOND; pass++) {
126         if(pass == FIRST) {
127             create_cmdtype_code();        /* 命令の名前とタイプがキーのハッシュ表を作成 */
128             asprop = malloc_chk(sizeof(ASPROP), "asprop"); /* アセンブル時のプロパティ用の領域確保 */
129         }
130         for(i = optind; i < argc; i++) {
131             /* データの格納開始位置 */
132             if(pass == FIRST) {
133                 beginptr[i] = asprop->ptr;
134             } else if(pass == SECOND) {
135                 asprop->ptr = beginptr[i];
136             }
137             asprop->prog = NULL;
138             if(execmode.trace == true || execmode.dump == true || asmode.src == true ||
139                asmode.label == true || asmode.asdetail == true)
140             {
141                 fprintf(stdout, "\nAssemble %s (%d)\n", argv[i], pass);
142             }
143             if((res = assemble(argv[i], pass)) == false) {
144                 exit(-1);
145             }
146         }
147         if(pass == FIRST && asmode.label == true) {
148             fprintf(stdout, "\nLabel::::\n");
149             printlabel();
150             if(asmode.onlylabel == true) {
151                 return 0;
152             }
153         }
154         if(pass == SECOND) {
155             freelabel();            /* ラベルハッシュ表を解放 */
156             free_chk(asprop->prog, "asprop.prog"); /* プログラム名を解放 */
157             free_chk(asprop, "asprop");       /* アセンブル時のプロパティを解放 */
158             free_cmdtype_code();    /* 命令の名前とタイプがキーのハッシュ表を解放 */
159         }
160     }
161     if(res == true) {
162         if(objfile != NULL) {
163             outassemble(objfile);
164         }
165         if(asmode.onlyassemble == false) {
166             create_code_type();    /* 命令のコードとタイプがキーのハッシュ表を作成 */
167             res = exec();          /* プログラム実行 */
168             free_code_type();      /* 命令のコードとタイプがキーのハッシュ表を解放 */
169         }
170     }
171     /* COMET II仮想マシンのシャットダウン */
172     shutdown();
173     if(cerr->num > 0) {
174         status = -1;
175     }
176     free_chk(objfile, "objfile");
177     /* エラーの解放 */
178     freecerr();
179     return status;
180 }