Merge branch 'master'
[YACASL2.git] / src / casl2.c
1 #include "package.h"
2 #include "assemble.h"
3 #include "exec.h"
4
5 /**
6  * @brief CASL IIのエラーをエラーリストに追加
7  *
8  * @return なし
9  */
10 void addcerrlist_casl2();
11
12 /**
13  * @brief アセンブル結果を書き込むファイルの名前
14  *
15  * @return ファイル名
16  *
17  * @param *str ファイル名
18  */
19 char *objfile_name(const char *str);
20
21 /**
22  * @brief casl2コマンドのオプション
23  */
24 static struct option longopts[] = {
25     { "source", no_argument, NULL, 's' },
26     { "label", no_argument, NULL, 'l' },
27     { "labelonly", no_argument, NULL, 'L' },
28     { "assembledetail", no_argument, NULL, 'a' },
29     { "assembledetailonly", no_argument, NULL, 'A' },
30     { "assembleout", optional_argument, NULL, 'o' },
31     { "assembleoutonly", optional_argument, NULL, 'O' },
32     { "trace", no_argument, NULL, 't' },
33     { "tracearithmetic", no_argument, NULL, 't' },
34     { "tracelogical", no_argument, NULL, 'T' },
35     { "dump", no_argument, NULL, 'd' },
36     { "monitor", no_argument, NULL, 'm' },
37     { "memorysize", required_argument, NULL, 'M' },
38     { "clocks", required_argument, NULL, 'C' },
39     { "version", no_argument, NULL, 'v' },
40     { "help", no_argument, NULL, 'h' },
41     { 0, 0, 0, 0 },
42 };
43
44 /**
45  * @brief casl2のエラー定義
46  */
47 CERR cerr_casl2[] = {
48     { 126, "no source file" },
49     { 127, "invalid option" },
50 };
51
52 void addcerrlist_casl2()
53 {
54     addcerrlist(ARRAYSIZE(cerr_casl2), cerr_casl2);
55 }
56
57 char *objfile_name(const char *name)
58 {
59     const char *default_name = "a.o";
60     return strdup_chk(
61         (name == NULL || !name[0]) ? default_name : name,
62         "objfile_name"
63         );
64 }
65
66 /**
67  * @brief casl2コマンドのメイン
68  *
69  * @return 正常終了時は0、エラー発生時は1
70  *
71  * @param argc コマンドライン引数の数
72  * @param *argv[] コマンドライン引数の配列
73  */
74 int main(int argc, char *argv[])
75 {
76     int memsize = DEFAULT_MEMSIZE;
77     int clocks = DEFAULT_CLOCKS;
78     int opt = 0;
79     int stat = 0;
80     int asfilecnt = 0;
81     char **asfile = NULL;
82     char *objfile = NULL;
83     const char *version = PACKAGE_VERSION;
84     const char *cmdversion = "casl2 of YACASL2 version %s\n";
85     const char *usage =
86         "Usage: %s [-slLaAtTdmvh] [-oO[<OBJECTFILE>]] [-M <MEMORYSIZE>] [-C <CLOCKS>] FILE1[ FILE2  ...]\n";
87
88     /* エラーの定義 */
89     cerr_init();
90     addcerrlist_casl2();
91     addcerrlist_assemble();
92     addcerrlist_exec();
93
94     /* オプションの処理 */
95     while((opt = getopt_long(argc, argv, "tTdslLmao::O::AM:C:vh", longopts, NULL)) != -1) {
96         switch(opt) {
97         case 's':
98             asmode.src = true;
99             break;
100         case 'l':
101             asmode.label = true;
102             break;
103         case 'L':
104             asmode.label = true;
105             asmode.onlylabel = true;
106             break;
107         case 'a':
108             asmode.asdetail = true;
109             break;
110         case 'A':
111             asmode.asdetail = true;
112             asmode.onlyassemble = true;
113             break;
114         case 'o':
115             objfile = objfile_name(optarg);
116             break;
117         case 'O':
118             asmode.onlyassemble = true;
119             objfile = objfile_name(optarg);
120             break;
121         case 't':
122             execmode.trace = true;
123             break;
124         case 'T':
125             execmode.trace = true;
126             execmode.logical = true;
127             break;
128         case 'd':
129             execmode.dump = true;
130             break;
131         case 'm':
132             execmode.step = true;
133             break;
134         case 'M':
135             memsize = atoi(optarg);
136             break;
137         case 'C':
138             clocks = atoi(optarg);
139             break;
140         case 'v':
141             fprintf(stdout, cmdversion, version);
142             goto casl2fin;
143         case 'h':
144             fprintf(stdout, usage, argv[0]);
145             goto casl2fin;
146         case '?':
147             fprintf(stderr, usage, argv[0]);
148             setcerr(212, "");    /* invalid option */
149             goto casl2fin;
150         }
151     }
152
153     /* ソースファイルが指定されていない場合は終了 */
154     if(argv[optind] == NULL) {
155         setcerr(126, "");    /* no source file */
156         fprintf(stderr, "casl2 error - %d: %s\n", cerr->num, cerr->msg);
157         goto casl2fin;
158     }
159     create_cmdtable(HASH_CMDTYPE);                 /* 命令の名前とタイプがキーのハッシュ表を作成 */
160     reset(memsize, clocks);                        /* 仮想マシンCOMET IIのリセット */
161     asfilecnt = argc - optind;
162     asfile = calloc_chk(asfilecnt, sizeof(char *), "asfile");
163     for(int i = 0; i < asfilecnt; i++) {           /* 引数からファイル名配列を取得 */
164         asfile[i] = argv[optind + i];
165     }
166     /* アセンブル */
167     if(assemble(asfilecnt, asfile, 0) == false || asmode.onlylabel == true) {
168         goto shutdown;
169     }
170     /* オブジェクトファイル名が指定されている場合は、アセンブル結果をオブジェクトファイルに出力 */
171     if(objfile != NULL) {
172         outassemble(objfile);
173     }
174     /* onlyassembleモード以外の場合、仮想マシンCOMET IIを実行 */
175     if(asmode.onlyassemble == false) {
176         exec();                                    /* 仮想マシンCOMET IIの実行 */
177     }
178 shutdown:
179     shutdown();                                   /* 仮想マシンCOMET IIのシャットダウン */
180 casl2fin:
181     FREE(objfile);
182     FREE(asfile);
183     free_cmdtable(HASH_CMDTYPE);
184     if(cerr->num > 0) {
185         stat = 1;
186     }
187     freecerr();                                    /* エラーの解放 */
188     return stat;
189 }