-
Notifications
You must be signed in to change notification settings - Fork 0
/
umlabwrite.c
167 lines (141 loc) · 5.42 KB
/
umlabwrite.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/**************************************************************
*
* umlabwrite.c
*
* Assignment: um
* Authors: Caleb Pekowsky, Labib Afia
* Date: 04//2022
*
* summary:
*
* this is the .c file for our umlabwrite. this helps write test functions.
*
**************************************************************/
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "assert.h"
#include "fmt.h"
#include "seq.h"
extern void Um_write_sequence(FILE *output, Seq_T instructions);
extern void build_halt_test(Seq_T instructions);
extern void build_verbose_halt_test(Seq_T instructions);
extern void build_add(Seq_T instructions);
extern void build_print_six(Seq_T instructions);
extern void build_print_digit(Seq_T instructions);
extern void build_INnOUT(Seq_T stream);
extern void build_Divide(Seq_T stream);
extern void build_Multiply(Seq_T stream);
extern void build_CMOV0(Seq_T stream);
extern void build_CMOV1(Seq_T stream);
extern void build_nand(Seq_T stream);
extern void build_segmented_load(Seq_T stream);
extern void build_segmented_store(Seq_T stream);
extern void build_loadval_test(Seq_T stream);
extern void build_mapbasic(Seq_T stream);
extern void build_unmapbasic(Seq_T stream);
extern void build_mapunmaphard(Seq_T stream);
extern void build_output_test(Seq_T stream);
extern void build_add_verbose(Seq_T stream);
extern void build_input_verbose(Seq_T stream);
extern void build_segmented_store(Seq_T stream);
/* The array `tests` contains all unit tests for the lab. */
static struct test_info {
const char *name;
const char *test_input; /* NULL means no input needed */
const char *expected_output;
/* writes instructions into sequence */
void (*build_test)(Seq_T stream);
} tests[] = {
{ "halt", NULL, "", build_halt_test },
{ "halt-verbose", NULL, "", build_verbose_halt_test },
{ "add" , NULL, "", build_add},
{"print-digit" , NULL, "", build_print_digit},
{ "print-six", NULL, "", build_print_six},
{"in-out" , NULL, "", build_INnOUT},
{"divide" , NULL, "", build_Divide},
{"multiply" , NULL, "", build_Multiply},
{"conditional1", NULL, "", build_CMOV1},
{"conditional0", NULL, "", build_CMOV0},
{"nand", NULL, "", build_nand},
{"sload", NULL, "", build_segmented_load},
{"sstore", NULL, "", build_segmented_store},
{"mapbasic", NULL, "", build_mapbasic},
{"unmapbasic", NULL, "", build_unmapbasic},
{"mapunmaphard", NULL, "", build_mapunmaphard},
{"output", NULL, "", build_output_test},
{"loadval", NULL, "", build_loadval_test},
{"add-verbose", NULL, "", build_add_verbose},
{"input-verbose", NULL, "", build_input_verbose},
{"segstore", NULL, "", build_segmented_store}
};
#define NTESTS (sizeof(tests)/sizeof(tests[0]))
/*
* open file 'path' for writing, then free the pathname;
* if anything fails, checked runtime error
*/
static FILE *open_and_free_pathname(char *path);
/*
* if contents is NULL or empty, remove the given 'path',
* otherwise write 'contents' into 'path'. Either way, free 'path'.
*/
static void write_or_remove_file(char *path, const char *contents);
static void write_test_files(struct test_info *test);
int main (int argc, char *argv[])
{
bool failed = false;
if (argc == 1)
for (unsigned i = 0; i < NTESTS; i++) {
printf("***** Writing test '%s'.\n", tests[i].name);
write_test_files(&tests[i]);
}
else
for (int j = 1; j < argc; j++) {
bool tested = false;
for (unsigned i = 0; i < NTESTS; i++)
if (!strcmp(tests[i].name, argv[j])) {
tested = true;
write_test_files(&tests[i]);
}
if (!tested) {
failed = true;
fprintf(stderr,
"***** No test named %s *****\n",
argv[j]);
}
}
return failed; /* failed nonzero == exit nonzero == failure */
}
static void write_test_files(struct test_info *test)
{
FILE *binary = open_and_free_pathname(Fmt_string("%s.um", test->name));
Seq_T instructions = Seq_new(0);
test->build_test(instructions);
Um_write_sequence(binary, instructions);
Seq_free(&instructions);
fclose(binary);
write_or_remove_file(Fmt_string("%s.0", test->name),
test->test_input);
write_or_remove_file(Fmt_string("%s.1", test->name),
test->expected_output);
}
static void write_or_remove_file(char *path, const char *contents)
{
if (contents == NULL || *contents == '\0') {
remove(path);
} else {
FILE *input = fopen(path, "wb");
assert(input != NULL);
fputs(contents, input);
fclose(input);
}
free(path);
}
static FILE *open_and_free_pathname(char *path)
{
FILE *fp = fopen(path, "wb");
assert(fp != NULL);
free(path);
return fp;
}