1
- from __future__ import print_function
2
- import os
3
- import sys
4
- from .compiler import Compiler
5
- from .compiler .util import encodeBinRawSav , setErrorMode
6
-
7
- if len (sys .argv ) < 2 :
8
- print ("PDPy11 Compiler" )
9
- print ("(c) 2018 Ivanq" )
10
- print ()
11
- print ("Usage:" )
12
- print ("""pdpy11 file.mac Compile file.mac to file.bin """ )
13
- print ("""pdpy11 file.mac --bin Compile file.mac to file.bin, replaces """ )
14
- print (""" make_raw / make_bk0010_rom / make_bin / make_sav""" )
15
- print ("""pdpy11 file.mac --sav Compile file.mac to file.sav, replaces """ )
16
- print (""" make_raw / make_bk0010_rom / make_bin / make_sav""" )
17
- print ("""pdpy11 file.mac --raw Compile file.mac to file, without bin header """ )
18
- print ("""pdpy11 a b c Compile & link files a, b and c to a.bin """ )
19
- print ("""pdpy11 a b c -o proj --raw Compile & link files a, b and c to proj (w/o bin""" )
20
- print (""" header) """ )
21
- print ("""pdpy11 a b c -o proj Compile & link files a, b and c to proj.bin (w/ """ )
22
- print (""" bin header) """ )
23
- print ("""pdpy11 --project dir Compile & link file dir/main.mac (see Project """ )
24
- print (""" mode) """ )
25
- print ()
26
- print ("""pdpy11 file.mac --lst Generate listing file "file.lst" """ )
27
- print ()
28
- print ("""--link n Link file/project from 0oN (default -- 0o1000) """ )
29
- print ()
30
- print ("""--syntax pdp11asm Use pdp11asm bugs/features: @M is same as @M(PC)""" )
31
- print (""" (M is not resolved to M-.), .INCLUDE is same as """ )
32
- print (""" .INCLUDE .END """ )
33
- print ("""--syntax pdpy11 (default) Use PDPy11 features, fix pdp11asm """ )
34
- print (""" bugs. This is the recommended mode for all new """ )
35
- print (""" projects. """ )
36
- print ("""-Dname=value Set global label <name> to integer <value> """ )
37
- print (""" (parsed using assembler rules) """ )
38
- print ("""-Dname="value" or Set global label <name> to string <value> """ )
39
- print ("""-Dname='value' or """ )
40
- print ("""-Dname=/value/ """ )
41
- print ()
42
- print ("""--sublime Output errors in Sublime-compatible format. This""" )
43
- print (""" allows Sublime to show errors inline. """ )
44
- print ()
45
- print ("Directives:" )
46
- print ("""ORG n / .LINK n / .LA n Link file from N (replaces --link). However, if """ )
47
- print (""" an included file contains .LINK, the included """ )
48
- print (""" file will be linked from N, but written to ".". """ )
49
- print (""".INCLUDE "filename" / Compile file "filename", then return to current """ )
50
- print (""".RAW_INCLUDE filename file. Embed "filename" to current binary file, """ )
51
- print (""" and link it from ".". """ )
52
- print (""" In "pdp11asm" mode, .INCLUDE is same as .INCLUDE""" )
53
- print (""" .END, and .RAW_INCLUDE is same as .INCLUDE. """ )
54
- print (""" In "pdpy11" mode, they work the same way, only """ )
55
- print (""" syntax differs. """ )
56
- print (""" Technically, this is the same as directly """ )
57
- print (""" inserting the included file's source code to """ )
58
- print (""" current file, with only .EXTERNal labels being """ )
59
- print (""" visible to other files. This also means that """ )
60
- print (""" including a file that has ".EXTERN" twice is """ )
61
- print (""" not a good idea -- an error will be raised, as """ )
62
- print (""" labels are redefined. Use ".ONCE" to fix this. """ )
63
- print (""".PDP11 Ignored """ )
64
- print (""".i8080 Emits syntax error """ )
65
- print (""".SYNTAX {pdp11asm/pdpy11} Change syntax locally, for 1 file """ )
66
- print (""".DB n / .BYTE n / DB n Emits byte N """ )
67
- print (""".DW n / .WORD n / DW n Emits word N """ )
68
- print (""".END / END Same as EOF; inside .REPEAT block works like """ )
69
- print (""" 'continue' operator """ )
70
- print (""".DS n / .BLKB n / DS n Emits N zero bytes """ )
71
- print (""".BLKW n Emits N zero words (N * 2 bytes) """ )
72
- print (""".EVEN If . points to an odd address, emit 1 zero byte """ )
73
- print ("""ALIGN n Align . by n, ceiling if n is not a divisor of """ )
74
- print (""" ".". """ )
75
- print (""".ASCII "..." Emits string """ )
76
- print (""".ASCIZ "..." Emits string, plus zero byte """ )
77
- print ("""make_raw ["..."] Same as --raw. If string is passed, this is the """ )
78
- print (""" resulting filename. """ )
79
- print ("""make_bk0010_rom ["..."] / Same as --bin. If string is passed, this is the """ )
80
- print ("""make_bin ["..."] resulting filename. """ )
81
- print ("""make_sav ["..."] Same as --sav. If string is passed, this is the """ )
82
- print (""" resulting filename. """ )
83
- print ("""convert1251toKOI8R {ON|OFF} Ignored """ )
84
- print ("""decimalnumbers {ON|OFF} If ON, N is the same as N., and you must use """ )
85
- print (""" 0oN or 0N or No for octal. This does not affect """ )
86
- print (""" --link and other CLI arguments. """ )
87
- print ("""insert_file "filename" Insert raw file "filename" to . """ )
88
- print (""".REPEAT count { code } Repeat code inside .REPEAT block <count> times """ )
89
- print (""".EXTERN NONE / Sets which labels are visible in other files. """ )
90
- print (""".EXTERN ALL / "NONE" means all global labels are visible in """ )
91
- print (""".EXTERN label1[, label2[, ...]] current file, but not others. "ALL" is the same """ )
92
- print (""" as mentioning all the labels defined in current """ )
93
- print (""" file. See also: Project mode. """ )
94
- print (""".ONCE Makes current file includable only once -- if it""" )
95
- print (""" was included before, it works like ".END". """ )
96
- print ()
97
- print ("Project mode" )
98
- print ("""PDPy11 can compile projects. Use `--project directory` CLI argument for this. """ )
99
- print ("""PDPy11 will compile all files (except the ones mentioned in `.pdpy11ignore` -- """ )
100
- print ("""see below) containing `make_raw`, `make_bk0010_rom`, `make_bin` or `make_sav` """ )
101
- print ("""directive. Such files are called "include roots". """ )
102
- print ()
103
- print ("""In project mode, `.INCLUDE` and `.RAW_INCLUDE` can include directories, which """ )
104
- print ("""means to include all `.mac` files inside the directory (except files mentioned """ )
105
- print ("""in `.pdpy11ignore`). """ )
106
- print ()
107
- print (".pdpy11ignore" )
108
- print ("""This file has syntax similar to `.gitignore`. It sets what files to ignore when """ )
109
- print ("""including directories. """ )
110
- print ("""Example: """ )
111
- print ("""filename.mac ; Ignore all files called filename.mac """ )
112
- print ("""a/* ; Ignore files in "a" directory and "whatever/a" directory """ )
113
- print ("""/a ; Ignore files in "a" directory only """ )
114
- print ("""test.mac/ ; Ignore everything inside "test.mac" directory and """ )
115
- print (""" ; whatever/test.mac" directory, but not "test.mac" file or """ )
116
- print (""" ; "whatever/test.mac" file """ )
117
-
118
- raise SystemExit (0 )
119
-
120
-
121
- # Parse CLI arguments
122
- output_format = None
123
- files = []
124
- output = None
125
- syntax = "pdpy11"
126
- link = "1000"
127
- project = None
128
- defines = []
129
- do_lst = False
130
-
131
- args = sys .argv [1 :]
132
- while len (args ):
133
- arg = args .pop (0 )
134
-
135
- if arg == "--bin" :
136
- output_format = "bin"
137
- elif arg == "--sav" :
138
- output_format = "sav"
139
- elif arg == "--raw" :
140
- output_format = "raw"
141
- elif arg == "--lst" :
142
- do_lst = True
143
- elif arg == "--project" :
144
- if project is not None :
145
- print ("Only 1 project may be linked" )
146
- raise SystemExit (1 )
147
-
148
- project = args .pop (0 )
149
- elif arg == "-o" :
150
- output = args .pop (0 )
151
- elif arg == "--link" :
152
- link = args .pop (0 )
153
- elif arg == "--syntax" :
154
- syntax = args .pop (0 )
155
- elif arg .startswith ("--syntax=" ):
156
- syntax = arg .replace ("--syntax=" , "" )
157
- elif arg == "--sublime" :
158
- setErrorMode (sublime = True )
159
- elif arg [:2 ] == "-D" :
160
- name , value = arg [2 :].split ("=" , 1 )
161
- str_punct = ("\" " , "'" , "/" )
162
- if value == "" :
163
- pass
164
- elif value [0 ] == value [- 1 ] and value [0 ] in str_punct :
165
- # String
166
- defines .append ((name , value [1 :- 1 ]))
167
- else :
168
- # Integer
169
- if value [:2 ] in ("0x" , "0X" ):
170
- value = int (value [2 :], 16 )
171
- elif value [- 1 ] == "." :
172
- value = int (value [:- 1 ], 10 )
173
- else :
174
- value = int (value , 8 )
175
- defines .append ((name , value ))
176
- else :
177
- files .append (arg )
178
-
179
- if len (files ) == 0 and project is None :
180
- print ("No files passed" )
181
- raise SystemExit (1 )
182
- elif len (files ) != 0 and project is not None :
183
- print ("Either a project or file list may be passed, not both" )
184
- raise SystemExit (1 )
185
- elif syntax not in ("pdp11asm" , "pdpy11" ):
186
- print ("Invalid syntax (expected 'pdp11asm' or 'pdpy11', got '{}')" .format (syntax ))
187
- raise SystemExit (1 )
188
-
189
- if link [:2 ] in ("0x" , "0X" ):
190
- link = int (link [2 :], 16 )
191
- elif link [- 1 ] == "." :
192
- link = int (link [:- 1 ], 10 )
193
- else :
194
- link = int (link , 8 )
195
-
196
- output_noext = output
197
- if output is None :
198
- if project is not None :
199
- output = project
200
- output_noext = output
201
-
202
- # Add extension
203
- if output_format is None or output_format == "bin" :
204
- output += ".bin"
205
- elif output_format == "sav" :
206
- output += ".sav"
207
- else :
208
- output += ".raw"
209
- else :
210
- output = files [0 ]
211
- if output .endswith (".mac" ):
212
- output = output [:- 4 ]
213
- output_noext = output
214
-
215
- # Add extension
216
- if output_format is None or output_format == "bin" :
217
- output += ".bin"
218
- elif output_format == "sav" :
219
- output += ".sav"
220
-
221
- file_list = []
222
-
223
- if project is not None :
224
- # Get pdpy11ignore
225
- pdpy11ignore = []
226
- try :
227
- with open (os .path .join (project , ".pdpy11ignore" )) as f :
228
- for line in f .read ().split ("\n " ):
229
- # Replace directory separators
230
- line = line .replace ("/" , os .sep )
231
- line = line .replace ("\\ " , os .sep )
232
-
233
- isRoot = line .startswith (os .sep )
234
- isDir = line .endswith (os .sep )
235
-
236
- # Split
237
- line = line .split (os .sep )
238
-
239
- # Remove empty parts
240
- line = [part for part in line if part != "" ]
241
-
242
- # Join back
243
- line = os .sep .join (line )
244
-
245
- # Save
246
- pdpy11ignore .append ((line , isRoot , isDir ))
247
- except IOError :
248
- pass
249
-
250
- # Get file list
251
- for dirName , _ , fileNames in os .walk (project ):
252
- for fileName in fileNames :
253
- file = os .path .join (dirName , fileName )
254
-
255
- for line , isRoot , isDir in pdpy11ignore :
256
- if file == line :
257
- # Full match
258
- if not isDir :
259
- break
260
- elif file .startswith (line + os .sep ):
261
- # Prefix match
262
- break
263
- elif file .endswith (os .sep + line ):
264
- # Suffix match
265
- if not isRoot :
266
- break
267
- elif os .sep + line + os .sep in file :
268
- # Substring match
269
- if not isRoot :
270
- break
271
- else :
272
- # No match -- not in pdpy11ignore
273
- if file .endswith (".mac" ):
274
- file = os .path .join (os .getcwd (), file )
275
- file_list .append (file )
276
-
277
-
278
- compiler = Compiler (syntax = syntax , link = link , file_list = file_list , project = project )
279
- for name , value in defines :
280
- compiler .define (name , value )
281
-
282
- if project is not None :
283
- # Project mode
284
- lstname = project
285
- for ext , file , output , link_address in compiler .buildProject ():
286
- with open (file , "wb" ) as f :
287
- f .write (encodeBinRawSav (ext , output , link_address ))
288
- else :
289
- # Single file mode
290
- lstname = files [0 ]
291
- if lstname .endswith (".mac" ):
292
- lstname = lstname [:- 4 ]
293
- for file in files :
294
- compiler .include_root = file
295
- compiler .addFile (file )
296
-
297
- out_files = compiler .link ()
298
-
299
- for ext , file in out_files :
300
- with open (file , "wb" ) as f :
301
- f .write (encodeBinRawSav (ext , compiler .output , compiler .link_address ))
302
-
303
- if len (out_files ) == 0 or output_format is None :
304
- # No output file
305
- with open (output , "wb" ) as f :
306
- f .write (encodeBinRawSav (output_format or "bin" , compiler .output , compiler .link_address ))
307
-
308
- if do_lst :
309
- with open (lstname + ".lst" , "w" ) as f :
310
- for line in compiler .generateLst ():
311
- f .write (line + "\n " )
1
+ from .pdpy11 import __main__
0 commit comments