-
Notifications
You must be signed in to change notification settings - Fork 138
/
cotorra.c
297 lines (220 loc) · 6.53 KB
/
cotorra.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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
/*
Copyright (C) 2009-2010, Parrot Foundation.
=head1 NAME
cotorra - A parrot embedding test
=head1 SYNOPSIS
cotorra file.pbc
=head1 DESCRIPTION
A test of parrot embedding in a C program.
Is a simplified form of the parrot main executable, with just a few
options and able to run only pbc files.
=cut
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "parrot/parrot.h"
#include "parrot/extend.h"
/**********************************************************************/
void fail(const char *msg);
unsigned int getuintval(const char *s);
Parrot_Run_core_t getruncore(const char *name);
Parrot_String create_string(Parrot_Interp interp, const char *name);
int cotorra_main(Parrot_Interp interp, int argc, const char **argv);
/**********************************************************************/
/*
=head2 Functions
=over 4
=cut
*/
/* Auxiliary generic functions */
/*
=item C<void fail(const char *msg)>
Fatal error, print the msg to stderr and exit.
=cut
*/
void fail(const char *msg)
{
fprintf(stderr, "cotorra failed: %s\n", msg);
exit(EXIT_FAILURE);
}
/*
=item C<unsigned int getuintval(const char *s)>
Get an unsigned int value from a C string.
Fails on invalid argument.
=cut
*/
unsigned int getuintval(const char *s)
{
char *aux;
unsigned long int n = strtoul(s, &aux, 0);
if (*aux != '\0')
fail("Invalid number");
return n;
}
struct runcoreinfo {
Parrot_Run_core_t id;
const char *name;
};
/*
=item C<Parrot_Run_core_t getruncore(const char *name)>
Get a runcore id from his name.
Fails on invalid argument.
=cut
*/
Parrot_Run_core_t getruncore(const char *name)
{
static const struct runcoreinfo cores [] = {
{ PARROT_SLOW_CORE, "slow" },
{ PARROT_GC_DEBUG_CORE, "gcdebug" },
};
static const unsigned int n = sizeof (cores)/sizeof (struct runcoreinfo);
unsigned int i;
for (i= 0; i < n; ++i) {
if (strcmp(name, cores[i].name) == 0)
break;
}
if (i >= n)
fail("Invalid runcore");
return cores[i].id;
}
/**********************************************************************/
/* Auxiliary parrot functions */
/*
=item C<Parrot_String create_string(Parrot_Interp interp, const char *name)>
Auxiliary function to shorten Parrot String creation,
=cut
*/
Parrot_String create_string(Parrot_Interp interp, const char *name)
{
return Parrot_str_new_init(interp, name, strlen(name), (const char *) NULL, 0);
}
/**********************************************************************/
/*
=item C<int cotorra_main(Parrot_Interp interp, int argc, const char **argv)>
Auxiliary function to minimize the size of main.
=cut
*/
int cotorra_main(Parrot_Interp interp, int argc, const char **argv)
{
const char *source;
Parrot_PackFile pf;
const char *stname = NULL;
const char *exec = NULL;
const char *module = NULL;
int i;
/* Incompatible options are not checked yet */
for (i = 1; i < argc; ++i) {
if (strcmp(argv[i], "--trace") == 0) {
++i;
if (i >= argc)
fail("Option needs argument");
Parrot_set_trace(interp, getuintval(argv[i]));
}
else if (strcmp(argv[i], "--warnings") == 0) {
++i;
if (i >= argc)
fail("Option needs argument");
Parrot_setwarnings(interp, getuintval(argv[i]));
}
else if (strcmp(argv[i], "-e") == 0) {
++i;
if (i >= argc)
fail("Option needs argument");
exec = argv[i];
}
else if (strcmp(argv[i], "--start") == 0) {
++i;
if (i >= argc)
fail("Option needs argument");
stname = argv[i];
}
else if (strcmp(argv[i], "--load") == 0) {
++i;
if (i >= argc)
fail("Option needs argument");
module = argv[i];
}
else if (strcmp(argv[i], "--runcore") == 0) {
++i;
if (i >= argc)
fail("Option needs argument");
Parrot_set_run_core(interp, getruncore(argv[i]));
}
else
break;
}
if (module)
Parrot_load_bytecode(interp, create_string(interp, module));
if (exec) {
Parrot_String compiler = create_string(interp, "PIR");
Parrot_String errstr;
Parrot_PMC code = Parrot_compile_string(interp, compiler, exec, &errstr);
Parrot_ext_call(interp, code, "->");
return 0;
}
if (i >= argc && ! (module && stname))
fail("No file to load");
source = argv[i];
if (source && ! stname) {
pf = Parrot_pbc_read(interp, source, 0);
if (! pf)
fail("Cannot load file");
Parrot_pbc_load(interp, pf);
Parrot_pbc_fixup_loaded(interp);
}
if (stname) {
Parrot_PMC rootns = Parrot_ns_get_root_namespace(interp);
Parrot_String parrotname = create_string(interp, "parrot");
Parrot_PMC parrotns = Parrot_PMC_get_pmc_keyed_str(interp, rootns, parrotname);
Parrot_String name = create_string(interp, stname);
Parrot_PMC start = Parrot_PMC_get_pmc_keyed_str(interp, parrotns, name);
if (Parrot_pmc_is_null(interp, start))
fail("start sub not found");
if (i < argc) {
int pos;
Parrot_PMC arg = Parrot_pmc_new(interp,
Parrot_pmc_get_type_str(interp,
Parrot_str_new(interp, "FixedStringArray", 0)));
Parrot_PMC_set_integer_native(interp, arg, argc - i);
for (pos = 0; i < argc; ++i, ++pos) {
Parrot_PMC_set_string_keyed_int(interp, arg, pos, create_string(interp, argv[i]));
}
Parrot_ext_call(interp, start, "P->", arg);
}
else
Parrot_ext_call(interp, start, "->");
}
else {
Parrot_runcode(interp, argc - i, argv + i);
}
return 0;
}
/*
=item C<int main(int argc, const char **argv)>
Main function. Create the parrot interpreter and call cotorra_main.
=cut
*/
int main(int argc, const char **argv)
{
Parrot_Interp interp;
int r;
Parrot_set_config_hash();
interp = Parrot_new(NULL);
if (! interp)
fail("Cannot create parrot interpreter");
Parrot_set_executable_name(interp, create_string(interp, argv[0]));
r = cotorra_main(interp, argc, argv);
Parrot_destroy(interp);
return r;
}
/*
=back
=cut
*/
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
*/