Skip to content

Commit cf8f3dd

Browse files
committed
add shebang support to compiler driver
1 parent 5d8b15b commit cf8f3dd

4 files changed

Lines changed: 45 additions & 5 deletions

File tree

FE/lexer.cc

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,20 @@ typedef std::array<uint8_t, 129> TrieNode;
6464

6565
LexerStats LexerRaw::stats;
6666

67+
LexerRaw::LexerRaw(std::string_view input, Name file_id)
68+
: input_(input), end_(input.size()) {
69+
srcloc_.file = file_id;
70+
if (input.starts_with("#!")) {
71+
// shebang line, skip it
72+
for (pos_ = 2; pos_ < input_.size(); ++pos_) {
73+
if (input_[pos_] == '\n') {
74+
++line_no_;
75+
break;
76+
}
77+
}
78+
}
79+
}
80+
6781
// Below is bunch of adhoc lexer helpers
6882
// These are quite horrible and the only excuse for them
6983
// is that they let us do without a depenency on a lexer library,
@@ -156,7 +170,7 @@ uint32_t LexerRaw::HandleSimpleStr() {
156170
return i + 1 - pos_;
157171
break;
158172
}
159-
if(c == '\n') CompilerError(srcloc_) << "Newline in string literal";
173+
if (c == '\n') CompilerError(srcloc_) << "Newline in string literal";
160174
}
161175
}
162176
}

FE/lexer.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,7 @@ class LexerRaw {
4545
static LexerStats stats;
4646

4747
// input is assumed to have a trailing zero byte
48-
LexerRaw(std::string_view input, Name file_id)
49-
: input_(input), end_(input.size()) {
50-
srcloc_.file = file_id;
51-
}
48+
LexerRaw(std::string_view input, Name file_id);
5249

5350
~LexerRaw() {
5451
stats.num_files++;

FE/lexer_tab.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,10 @@ def __init__(self: Any, filename: str, fp: io.TextIOWrapper):
406406
self._col_no = 0
407407
self._current_line = ""
408408
self._trie: TRIE = MakeTrie(False)
409+
self._current_line = self._fill_line()
410+
if self._current_line.startswith("#!"):
411+
# ignore shebang mode
412+
self._current_line = self._fill_line()
409413

410414
def _GetSrcLoc(self) -> cwast.SrcLoc:
411415
return cwast.SrcLoc(self._fileamame, self._line_no)

cwerg.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import os
88
import platform
99
import sys
10+
import subprocess
1011
from typing import Any
1112

1213

@@ -130,6 +131,27 @@ def Diagnostics():
130131
print()
131132

132133

134+
def ShebangMode(script_path: str, extra_args: list[str]) -> int:
135+
import uuid
136+
import tempfile
137+
arch = DEFAULT_ARCH
138+
prefix = tempfile.gettempdir() + f"/cwerg_shebang_{uuid.uuid4().hex}"
139+
ir_file = f"{prefix}.ir"
140+
fe_cmd = GetFeCommand("c++", arch, script_path, ir_file)
141+
if 0 != os.system(fe_cmd):
142+
return 1
143+
exe_file = f"{prefix}.exe"
144+
be_cmd = GetBeCommand("c++", arch, ir_file, exe_file)
145+
if 0 != os.system(be_cmd):
146+
return 1
147+
rm_cmd = f"chmod a+x {exe_file} ; rm -f {ir_file}"
148+
if 0 != os.system(rm_cmd):
149+
return 1
150+
res = subprocess.run([exe_file] + extra_args).returncode
151+
os.remove(exe_file)
152+
return res
153+
154+
133155
def main():
134156
if sys.version_info[0] != 3 or sys.version_info[1] < 12:
135157
print("Cwerg requires Python 3.12 or higher")
@@ -138,6 +160,9 @@ def main():
138160
print("Cwerg currently requires Linux")
139161
return 1
140162

163+
if sys.argv[1] == "@script@":
164+
exit(ShebangMode(sys.argv[2], sys.argv[3:]))
165+
141166
parser = argparse.ArgumentParser(add_help=False)
142167
parser.add_argument('-diag', help='show diagnostics and exit',
143168
action='store_true')

0 commit comments

Comments
 (0)