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