-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathcommand_line_args.jou
127 lines (115 loc) · 6.03 KB
/
command_line_args.jou
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
import "stdlib/io.jou"
import "stdlib/str.jou"
import "stdlib/mem.jou"
import "stdlib/process.jou"
import "./update.jou"
class CommandLineArgs:
argv0: byte* # Program name
verbosity: int # How much debug/progress info to print, how many times -v/--verbose passed
valgrind: bool # true --> Use valgrind when runnning user's jou program
tokenize_only: bool # If true, tokenize the file passed on command line and don't actually compile anything
parse_only: bool # If true, parse the file passed on command line and don't actually compile anything
uvg_only: bool # If true, generate and print UVG's and don't actually compile anything
optlevel: int # Optimization level (0 don't optimize, 3 optimize a lot)
infile: byte* # The "main" Jou file (can import other files)
outfile: byte* # If not NULL, where to output executable
linker_flags: byte* # String that is appended to linking command
# Command-line arguments are a global variable because I like it.
# This variable is also accessed from other files because I like it.
@public
global command_line_args: CommandLineArgs
def print_help(argv0: byte*) -> None:
printf("Usage:\n")
printf(" %s [-o OUTFILE] [-O0|-O1|-O2|-O3] [--verbose] [--linker-flags \"...\"] FILENAME\n", argv0)
printf(" %s --help # This message\n", argv0)
printf(" %s --update # Download and install the latest Jou\n", argv0)
printf("\n")
printf("Options:\n")
printf(" -o OUTFILE output an executable file, don't run the code\n")
printf(" -O0/-O1/-O2/-O3 set optimization level (0 = no optimization, 1 = default, 3 = runs fastest)\n")
printf(" -v / --verbose display some progress information\n")
printf(" -vv display a lot of information about all compilation steps\n")
printf(" --valgrind use valgrind when running the code\n")
printf(" --linker-flags appended to the linker command, so you can use external libraries\n")
printf(" --tokenize-only display the output of the tokenizer, do not compile further\n")
printf(" --parse-only display the AST (parse tree), do not compile further\n")
printf(" --uvg-only display Undefined Value Graphs, do not compile further\n")
@public
def parse_command_line_args(argc: int, argv: byte**) -> None:
memset(&command_line_args, 0, sizeof command_line_args)
command_line_args.argv0 = argv[0]
# Set default optimize to O1, user sets optimize will overwrite the default flag
command_line_args.optlevel = 1
if argc == 2:
match argv[1] with strcmp:
case "--help":
print_help(argv[0])
exit(0)
case "--update":
update_jou_compiler()
exit(0)
i = 1
while i < argc:
match argv[i] with strcmp:
case "--help" | "--update":
fprintf(stderr, "%s: \"%s\" cannot be used with other arguments (try \"%s --help\")\n", argv[0], argv[i], argv[0])
exit(2)
case "--verbose":
command_line_args.verbosity++
i++
case "--valgrind":
command_line_args.valgrind = True
i++
case "--tokenize-only":
if argc > 3:
fprintf(stderr, "%s: --tokenize-only cannot be used together with other flags (try \"%s --help\")\n", argv[0], argv[0])
exit(2)
command_line_args.tokenize_only = True
i++
case "--parse-only":
if argc > 3:
fprintf(stderr, "%s: --parse-only cannot be used together with other flags (try \"%s --help\")", argv[0], argv[0])
exit(2)
command_line_args.parse_only = True
i++
case "--uvg-only":
if argc > 3:
fprintf(stderr, "%s: --uvg-only cannot be used together with other flags (try \"%s --help\")", argv[0], argv[0])
exit(2)
command_line_args.uvg_only = True
i++
case "--linker-flags":
if command_line_args.linker_flags != NULL:
fprintf(stderr, "%s: --linker-flags cannot be given multiple times (try \"%s --help\")\n", argv[0], argv[0])
exit(2)
if argc-i < 2:
fprintf(stderr, "%s: there must be a string of flags after --linker-flags (try \"%s --help\")\n", argv[0], argv[0])
exit(2)
command_line_args.linker_flags = argv[i+1]
i += 2
case "-O0" | "-O1" | "-O2" | "-O3":
command_line_args.optlevel = argv[i][2] - '0'
i++
case "-o":
if argc-i < 2:
fprintf(stderr, "%s: there must be a file name after -o (try \"%s --help\")\n", argv[0], argv[0])
exit(2)
command_line_args.outfile = argv[i+1]
if strlen(command_line_args.outfile) > 4 and ends_with(command_line_args.outfile, ".jou"):
fprintf(stderr, "%s: the filename after -o should be an executable, not a Jou file (try \"%s --help\")\n", argv[0], argv[0])
exit(2)
i += 2
case _:
if starts_with(argv[i], "-v") and strspn(&argv[i][1], "v") == strlen(argv[i])-1:
command_line_args.verbosity += (strlen(argv[i++]) as int) - 1
elif argv[i][0] == '-':
fprintf(stderr, "%s: unknown argument \"%s\" (try \"%s --help\")\n", argv[0], argv[i], argv[0])
exit(2)
elif command_line_args.infile != NULL:
fprintf(stderr, "%s: you can only pass one Jou file (try \"%s --help\")\n", argv[0], argv[0])
exit(2)
else:
command_line_args.infile = argv[i++]
if command_line_args.infile == NULL:
fprintf(stderr, "%s: missing Jou file name (try \"%s --help\")\n", argv[0], argv[0])
exit(2)