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