27static void usage(
const char *prog) {
28 fprintf(stderr,
"Usage: %s [--fix] [--quiet] <file1.fun> [file2.fun ...]\n", prog);
41static int read_all(
const char *
path,
char **out_buf,
size_t *out_len) {
44 FILE *
f = fopen(
path,
"rb");
46 if (fseek(
f, 0, SEEK_END) != 0) {
55 if (fseek(
f, 0, SEEK_SET) != 0) {
59 char *
buf = (
char *)malloc((
size_t)
sz + 1);
64 size_t rd = fread(
buf, 1, (
size_t)
sz,
f);
80static int write_all(
const char *
path,
const char *
buf,
size_t len) {
81 FILE *
f = fopen(
path,
"wb");
83 size_t wr = fwrite(
buf, 1,
len,
f);
94static int is_word(
int c) {
95 return (
c ==
'_' || isalnum(
c));
116static char *apply_fixes(
const char *src,
size_t len,
size_t *out_len) {
120 char *
out = (
char *)malloc(
cap);
121 if (!
out)
return NULL;
129 char *
n = (
char *)realloc(
out,
cap);
138 size_t line_start_out = o;
145 if (
c ==
'\r' ||
c ==
'\n')
break;
146 if (at_bol && (
c ==
' ' ||
c ==
'\t')) {
149 }
else if (
c ==
'\t') {
159 int normalized = (spaces % 2 == 0) ? spaces : spaces + 1;
160 for (
int k = 0;
k < normalized;
k++) {
176 size_t line_content_start = i;
177 size_t line_end_i = i;
179 while (line_end_i <
len) {
180 char c = src[line_end_i];
185 if (
c ==
'\n')
break;
189 size_t trim_end = line_end_i;
190 while (trim_end > i && src[trim_end - 1] ==
' ')
195 while (
p < trim_end) {
197 const char *keys[] = {
"sint8",
"sint16",
"sint32",
"sint64"};
198 const char *
vals[] = {
"int8",
"int16",
"int32",
"int64"};
201 const char *
k = keys[
idx];
202 size_t klen = strlen(
k);
203 if (
p + klen <= trim_end && strncmp(&src[
p],
k, klen) == 0) {
204 int left_ok = (
p == i) || !is_word((
unsigned char)src[
p - 1]);
205 int right_ok = (
p + klen == trim_end) || !is_word((
unsigned char)src[
p + klen]);
206 if (left_ok && right_ok) {
208 size_t vlen = strlen(
v);
209 if (o + vlen + 16 >=
cap) {
218 memcpy(&
out[o],
v, vlen);
226 if (replaced)
continue;
227 if (o + 1 + 16 >=
cap) {
240 if (line_end_i <
len) {
242 if (src[line_end_i] ==
'\r') {
244 if (line_end_i <
len && src[line_end_i] ==
'\n') line_end_i++;
245 }
else if (src[line_end_i] ==
'\n') {
261 (void)line_start_out;
262 (void)line_content_start;
267 if (o == 0 ||
out[o - 1] !=
'\n') {
270 char *
n = (
char *)realloc(
out,
cap);
282 char *shr = (
char *)realloc(
out, o + 1);
299int main(
int argc,
char **argv) {
302 int first_file_arg = 1;
305 for (
int i = 1; i < argc; i++) {
306 if (strcmp(argv[i],
"--fix") == 0) {
311 if (strcmp(argv[i],
"--quiet") == 0) {
317 if (argv[i][0] !=
'-')
break;
319 if (strncmp(argv[i],
"--", 2) == 0) {
326 if (first_file_arg >= argc) {
333 for (
int i = first_file_arg; i < argc; i++) {
334 const char *
path = argv[i];
340 if (!read_all(
path, &orig, &orig_len)) {
345 size_t fixed_len = 0;
346 char *fixed = apply_fixes(orig, orig_len, &fixed_len);
348 fprintf(stderr,
"%s: out of memory while fixing\n",
path);
358 int line = 0, col = 0;
360 fprintf(stderr,
"%s:%d:%d: syntax error after --fix attempt: %s\n",
path, line, col, msg);
362 fprintf(stderr,
"%s: syntax error (unknown) after --fix attempt\n",
path);
373 if (orig_len != fixed_len || memcmp(orig, fixed, (orig_len < fixed_len ? orig_len : fixed_len)) != 0) changed = 1;
375 if (!write_all(
path, fixed, fixed_len)) {
376 fprintf(stderr,
"%s: failed to write fixed file\n",
path);
391 int line = 0, col = 0;
393 fprintf(stderr,
"%s:%d:%d: syntax error: %s\n",
path, line, col, msg);
395 fprintf(stderr,
"%s: syntax error (unknown)\n",
path);
405 return hadError ? 1 : 0;
void bytecode_free(Bytecode *bc)
Free a Bytecode and all memory it owns.
Definitions for the Fun VM bytecode: opcodes, instruction format, and bytecode container API.
int main(void)
Build and execute a demo bytecode program and print results.
Bytecode * parse_string_to_bytecode(const char *source)
Parse a source string and return compiled bytecode.
int parser_last_error(char *msgBuf, unsigned long msgCap, int *outLine, int *outCol)
Retrieve the last parser/compiler error information, if any.
Bytecode * parse_file_to_bytecode(const char *path)
Parse a .fun source file and return compiled bytecode.
Public API for parsing Fun source into bytecode.