beta-0.89.2
[luatex.git] / source / libs / luajit / LuaJIT-src / dynasm / dynasm.lua
blobfffda7513c8831c5b49a109e42c0c5f16e67e8ac
1 ------------------------------------------------------------------------------
2 -- DynASM. A dynamic assembler for code generation engines.
3 -- Originally designed and implemented for LuaJIT.
4 --
5 -- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
6 -- See below for full copyright notice.
7 ------------------------------------------------------------------------------
9 -- Application information.
10 local _info = {
11 name = "DynASM",
12 description = "A dynamic assembler for code generation engines",
13 version = "1.3.0",
14 vernum = 10300,
15 release = "2011-05-05",
16 author = "Mike Pall",
17 url = "http://luajit.org/dynasm.html",
18 license = "MIT",
19 copyright = [[
20 Copyright (C) 2005-2015 Mike Pall. All rights reserved.
22 Permission is hereby granted, free of charge, to any person obtaining
23 a copy of this software and associated documentation files (the
24 "Software"), to deal in the Software without restriction, including
25 without limitation the rights to use, copy, modify, merge, publish,
26 distribute, sublicense, and/or sell copies of the Software, and to
27 permit persons to whom the Software is furnished to do so, subject to
28 the following conditions:
30 The above copyright notice and this permission notice shall be
31 included in all copies or substantial portions of the Software.
33 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
34 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
35 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
36 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
37 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
38 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
39 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
41 [ MIT license: http://www.opensource.org/licenses/mit-license.php ]
42 ]],
45 -- Cache library functions.
46 local type, pairs, ipairs = type, pairs, ipairs
47 local pcall, error, assert = pcall, error, assert
48 local _s = string
49 local sub, match, gmatch, gsub = _s.sub, _s.match, _s.gmatch, _s.gsub
50 local format, rep, upper = _s.format, _s.rep, _s.upper
51 local _t = table
52 local insert, remove, concat, sort = _t.insert, _t.remove, _t.concat, _t.sort
53 local exit = os.exit
54 local io = io
55 local stdin, stdout, stderr = io.stdin, io.stdout, io.stderr
57 ------------------------------------------------------------------------------
59 -- Program options.
60 local g_opt = {}
62 -- Global state for current file.
63 local g_fname, g_curline, g_indent, g_lineno, g_synclineno, g_arch
64 local g_errcount = 0
66 -- Write buffer for output file.
67 local g_wbuffer, g_capbuffer
69 ------------------------------------------------------------------------------
71 -- Write an output line (or callback function) to the buffer.
72 local function wline(line, needindent)
73 local buf = g_capbuffer or g_wbuffer
74 buf[#buf+1] = needindent and g_indent..line or line
75 g_synclineno = g_synclineno + 1
76 end
78 -- Write assembler line as a comment, if requestd.
79 local function wcomment(aline)
80 if g_opt.comment then
81 wline(g_opt.comment..aline..g_opt.endcomment, true)
82 end
83 end
85 -- Resync CPP line numbers.
86 local function wsync()
87 if g_synclineno ~= g_lineno and g_opt.cpp then
88 wline("#line "..g_lineno..' "'..g_fname..'"')
89 g_synclineno = g_lineno
90 end
91 end
93 -- Dummy action flush function. Replaced with arch-specific function later.
94 local function wflush(term)
95 end
97 -- Dump all buffered output lines.
98 local function wdumplines(out, buf)
99 for _,line in ipairs(buf) do
100 if type(line) == "string" then
101 assert(out:write(line, "\n"))
102 else
103 -- Special callback to dynamically insert lines after end of processing.
104 line(out)
109 ------------------------------------------------------------------------------
111 -- Emit an error. Processing continues with next statement.
112 local function werror(msg)
113 error(format("%s:%s: error: %s:\n%s", g_fname, g_lineno, msg, g_curline), 0)
116 -- Emit a fatal error. Processing stops.
117 local function wfatal(msg)
118 g_errcount = "fatal"
119 werror(msg)
122 -- Print a warning. Processing continues.
123 local function wwarn(msg)
124 stderr:write(format("%s:%s: warning: %s:\n%s\n",
125 g_fname, g_lineno, msg, g_curline))
128 -- Print caught error message. But suppress excessive errors.
129 local function wprinterr(...)
130 if type(g_errcount) == "number" then
131 -- Regular error.
132 g_errcount = g_errcount + 1
133 if g_errcount < 21 then -- Seems to be a reasonable limit.
134 stderr:write(...)
135 elseif g_errcount == 21 then
136 stderr:write(g_fname,
137 ":*: warning: too many errors (suppressed further messages).\n")
139 else
140 -- Fatal error.
141 stderr:write(...)
142 return true -- Stop processing.
146 ------------------------------------------------------------------------------
148 -- Map holding all option handlers.
149 local opt_map = {}
150 local opt_current
152 -- Print error and exit with error status.
153 local function opterror(...)
154 stderr:write("dynasm.lua: ERROR: ", ...)
155 stderr:write("\n")
156 exit(1)
159 -- Get option parameter.
160 local function optparam(args)
161 local argn = args.argn
162 local p = args[argn]
163 if not p then
164 opterror("missing parameter for option `", opt_current, "'.")
166 args.argn = argn + 1
167 return p
170 ------------------------------------------------------------------------------
172 -- Core pseudo-opcodes.
173 local map_coreop = {}
174 -- Dummy opcode map. Replaced by arch-specific map.
175 local map_op = {}
177 -- Forward declarations.
178 local dostmt
179 local readfile
181 ------------------------------------------------------------------------------
183 -- Map for defines (initially empty, chains to arch-specific map).
184 local map_def = {}
186 -- Pseudo-opcode to define a substitution.
187 map_coreop[".define_2"] = function(params, nparams)
188 if not params then return nparams == 1 and "name" or "name, subst" end
189 local name, def = params[1], params[2] or "1"
190 if not match(name, "^[%a_][%w_]*$") then werror("bad or duplicate define") end
191 map_def[name] = def
193 map_coreop[".define_1"] = map_coreop[".define_2"]
195 -- Define a substitution on the command line.
196 function opt_map.D(args)
197 local namesubst = optparam(args)
198 local name, subst = match(namesubst, "^([%a_][%w_]*)=(.*)$")
199 if name then
200 map_def[name] = subst
201 elseif match(namesubst, "^[%a_][%w_]*$") then
202 map_def[namesubst] = "1"
203 else
204 opterror("bad define")
208 -- Undefine a substitution on the command line.
209 function opt_map.U(args)
210 local name = optparam(args)
211 if match(name, "^[%a_][%w_]*$") then
212 map_def[name] = nil
213 else
214 opterror("bad define")
218 -- Helper for definesubst.
219 local gotsubst
221 local function definesubst_one(word)
222 local subst = map_def[word]
223 if subst then gotsubst = word; return subst else return word end
226 -- Iteratively substitute defines.
227 local function definesubst(stmt)
228 -- Limit number of iterations.
229 for i=1,100 do
230 gotsubst = false
231 stmt = gsub(stmt, "#?[%w_]+", definesubst_one)
232 if not gotsubst then break end
234 if gotsubst then wfatal("recursive define involving `"..gotsubst.."'") end
235 return stmt
238 -- Dump all defines.
239 local function dumpdefines(out, lvl)
240 local t = {}
241 for name in pairs(map_def) do
242 t[#t+1] = name
244 sort(t)
245 out:write("Defines:\n")
246 for _,name in ipairs(t) do
247 local subst = map_def[name]
248 if g_arch then subst = g_arch.revdef(subst) end
249 out:write(format(" %-20s %s\n", name, subst))
251 out:write("\n")
254 ------------------------------------------------------------------------------
256 -- Support variables for conditional assembly.
257 local condlevel = 0
258 local condstack = {}
260 -- Evaluate condition with a Lua expression. Substitutions already performed.
261 local function cond_eval(cond)
262 local func, err
263 if setfenv then
264 func, err = loadstring("return "..cond, "=expr")
265 else
266 -- No globals. All unknown identifiers evaluate to nil.
267 func, err = load("return "..cond, "=expr", "t", {})
269 if func then
270 if setfenv then
271 setfenv(func, {}) -- No globals. All unknown identifiers evaluate to nil.
273 local ok, res = pcall(func)
274 if ok then
275 if res == 0 then return false end -- Oh well.
276 return not not res
278 err = res
280 wfatal("bad condition: "..err)
283 -- Skip statements until next conditional pseudo-opcode at the same level.
284 local function stmtskip()
285 local dostmt_save = dostmt
286 local lvl = 0
287 dostmt = function(stmt)
288 local op = match(stmt, "^%s*(%S+)")
289 if op == ".if" then
290 lvl = lvl + 1
291 elseif lvl ~= 0 then
292 if op == ".endif" then lvl = lvl - 1 end
293 elseif op == ".elif" or op == ".else" or op == ".endif" then
294 dostmt = dostmt_save
295 dostmt(stmt)
300 -- Pseudo-opcodes for conditional assembly.
301 map_coreop[".if_1"] = function(params)
302 if not params then return "condition" end
303 local lvl = condlevel + 1
304 local res = cond_eval(params[1])
305 condlevel = lvl
306 condstack[lvl] = res
307 if not res then stmtskip() end
310 map_coreop[".elif_1"] = function(params)
311 if not params then return "condition" end
312 if condlevel == 0 then wfatal(".elif without .if") end
313 local lvl = condlevel
314 local res = condstack[lvl]
315 if res then
316 if res == "else" then wfatal(".elif after .else") end
317 else
318 res = cond_eval(params[1])
319 if res then
320 condstack[lvl] = res
321 return
324 stmtskip()
327 map_coreop[".else_0"] = function(params)
328 if condlevel == 0 then wfatal(".else without .if") end
329 local lvl = condlevel
330 local res = condstack[lvl]
331 condstack[lvl] = "else"
332 if res then
333 if res == "else" then wfatal(".else after .else") end
334 stmtskip()
338 map_coreop[".endif_0"] = function(params)
339 local lvl = condlevel
340 if lvl == 0 then wfatal(".endif without .if") end
341 condlevel = lvl - 1
344 -- Check for unfinished conditionals.
345 local function checkconds()
346 if g_errcount ~= "fatal" and condlevel ~= 0 then
347 wprinterr(g_fname, ":*: error: unbalanced conditional\n")
351 ------------------------------------------------------------------------------
353 -- Search for a file in the given path and open it for reading.
354 local function pathopen(path, name)
355 local dirsep = package and match(package.path, "\\") and "\\" or "/"
356 for _,p in ipairs(path) do
357 local fullname = p == "" and name or p..dirsep..name
358 local fin = io.open(fullname, "r")
359 if fin then
360 g_fname = fullname
361 return fin
366 -- Include a file.
367 map_coreop[".include_1"] = function(params)
368 if not params then return "filename" end
369 local name = params[1]
370 -- Save state. Ugly, I know. but upvalues are fast.
371 local gf, gl, gcl, gi = g_fname, g_lineno, g_curline, g_indent
372 -- Read the included file.
373 local fatal = readfile(pathopen(g_opt.include, name) or
374 wfatal("include file `"..name.."' not found"))
375 -- Restore state.
376 g_synclineno = -1
377 g_fname, g_lineno, g_curline, g_indent = gf, gl, gcl, gi
378 if fatal then wfatal("in include file") end
381 -- Make .include and conditionals initially available, too.
382 map_op[".include_1"] = map_coreop[".include_1"]
383 map_op[".if_1"] = map_coreop[".if_1"]
384 map_op[".elif_1"] = map_coreop[".elif_1"]
385 map_op[".else_0"] = map_coreop[".else_0"]
386 map_op[".endif_0"] = map_coreop[".endif_0"]
388 ------------------------------------------------------------------------------
390 -- Support variables for macros.
391 local mac_capture, mac_lineno, mac_name
392 local mac_active = {}
393 local mac_list = {}
395 -- Pseudo-opcode to define a macro.
396 map_coreop[".macro_*"] = function(mparams)
397 if not mparams then return "name [, params...]" end
398 -- Split off and validate macro name.
399 local name = remove(mparams, 1)
400 if not name then werror("missing macro name") end
401 if not (match(name, "^[%a_][%w_%.]*$") or match(name, "^%.[%w_%.]*$")) then
402 wfatal("bad macro name `"..name.."'")
404 -- Validate macro parameter names.
405 local mdup = {}
406 for _,mp in ipairs(mparams) do
407 if not match(mp, "^[%a_][%w_]*$") then
408 wfatal("bad macro parameter name `"..mp.."'")
410 if mdup[mp] then wfatal("duplicate macro parameter name `"..mp.."'") end
411 mdup[mp] = true
413 -- Check for duplicate or recursive macro definitions.
414 local opname = name.."_"..#mparams
415 if map_op[opname] or map_op[name.."_*"] then
416 wfatal("duplicate macro `"..name.."' ("..#mparams.." parameters)")
418 if mac_capture then wfatal("recursive macro definition") end
420 -- Enable statement capture.
421 local lines = {}
422 mac_lineno = g_lineno
423 mac_name = name
424 mac_capture = function(stmt) -- Statement capture function.
425 -- Stop macro definition with .endmacro pseudo-opcode.
426 if not match(stmt, "^%s*.endmacro%s*$") then
427 lines[#lines+1] = stmt
428 return
430 mac_capture = nil
431 mac_lineno = nil
432 mac_name = nil
433 mac_list[#mac_list+1] = opname
434 -- Add macro-op definition.
435 map_op[opname] = function(params)
436 if not params then return mparams, lines end
437 -- Protect against recursive macro invocation.
438 if mac_active[opname] then wfatal("recursive macro invocation") end
439 mac_active[opname] = true
440 -- Setup substitution map.
441 local subst = {}
442 for i,mp in ipairs(mparams) do subst[mp] = params[i] end
443 local mcom
444 if g_opt.maccomment and g_opt.comment then
445 mcom = " MACRO "..name.." ("..#mparams..")"
446 wcomment("{"..mcom)
448 -- Loop through all captured statements
449 for _,stmt in ipairs(lines) do
450 -- Substitute macro parameters.
451 local st = gsub(stmt, "[%w_]+", subst)
452 st = definesubst(st)
453 st = gsub(st, "%s*%.%.%s*", "") -- Token paste a..b.
454 if mcom and sub(st, 1, 1) ~= "|" then wcomment(st) end
455 -- Emit statement. Use a protected call for better diagnostics.
456 local ok, err = pcall(dostmt, st)
457 if not ok then
458 -- Add the captured statement to the error.
459 wprinterr(err, "\n", g_indent, "| ", stmt,
460 "\t[MACRO ", name, " (", #mparams, ")]\n")
463 if mcom then wcomment("}"..mcom) end
464 mac_active[opname] = nil
469 -- An .endmacro pseudo-opcode outside of a macro definition is an error.
470 map_coreop[".endmacro_0"] = function(params)
471 wfatal(".endmacro without .macro")
474 -- Dump all macros and their contents (with -PP only).
475 local function dumpmacros(out, lvl)
476 sort(mac_list)
477 out:write("Macros:\n")
478 for _,opname in ipairs(mac_list) do
479 local name = sub(opname, 1, -3)
480 local params, lines = map_op[opname]()
481 out:write(format(" %-20s %s\n", name, concat(params, ", ")))
482 if lvl > 1 then
483 for _,line in ipairs(lines) do
484 out:write(" |", line, "\n")
486 out:write("\n")
489 out:write("\n")
492 -- Check for unfinished macro definitions.
493 local function checkmacros()
494 if mac_capture then
495 wprinterr(g_fname, ":", mac_lineno,
496 ": error: unfinished .macro `", mac_name ,"'\n")
500 ------------------------------------------------------------------------------
502 -- Support variables for captures.
503 local cap_lineno, cap_name
504 local cap_buffers = {}
505 local cap_used = {}
507 -- Start a capture.
508 map_coreop[".capture_1"] = function(params)
509 if not params then return "name" end
510 wflush()
511 local name = params[1]
512 if not match(name, "^[%a_][%w_]*$") then
513 wfatal("bad capture name `"..name.."'")
515 if cap_name then
516 wfatal("already capturing to `"..cap_name.."' since line "..cap_lineno)
518 cap_name = name
519 cap_lineno = g_lineno
520 -- Create or continue a capture buffer and start the output line capture.
521 local buf = cap_buffers[name]
522 if not buf then buf = {}; cap_buffers[name] = buf end
523 g_capbuffer = buf
524 g_synclineno = 0
527 -- Stop a capture.
528 map_coreop[".endcapture_0"] = function(params)
529 wflush()
530 if not cap_name then wfatal(".endcapture without a valid .capture") end
531 cap_name = nil
532 cap_lineno = nil
533 g_capbuffer = nil
534 g_synclineno = 0
537 -- Dump a capture buffer.
538 map_coreop[".dumpcapture_1"] = function(params)
539 if not params then return "name" end
540 wflush()
541 local name = params[1]
542 if not match(name, "^[%a_][%w_]*$") then
543 wfatal("bad capture name `"..name.."'")
545 cap_used[name] = true
546 wline(function(out)
547 local buf = cap_buffers[name]
548 if buf then wdumplines(out, buf) end
549 end)
550 g_synclineno = 0
553 -- Dump all captures and their buffers (with -PP only).
554 local function dumpcaptures(out, lvl)
555 out:write("Captures:\n")
556 for name,buf in pairs(cap_buffers) do
557 out:write(format(" %-20s %4s)\n", name, "("..#buf))
558 if lvl > 1 then
559 local bar = rep("=", 76)
560 out:write(" ", bar, "\n")
561 for _,line in ipairs(buf) do
562 out:write(" ", line, "\n")
564 out:write(" ", bar, "\n\n")
567 out:write("\n")
570 -- Check for unfinished or unused captures.
571 local function checkcaptures()
572 if cap_name then
573 wprinterr(g_fname, ":", cap_lineno,
574 ": error: unfinished .capture `", cap_name,"'\n")
575 return
577 for name in pairs(cap_buffers) do
578 if not cap_used[name] then
579 wprinterr(g_fname, ":*: error: missing .dumpcapture ", name ,"\n")
584 ------------------------------------------------------------------------------
586 -- Sections names.
587 local map_sections = {}
589 -- Pseudo-opcode to define code sections.
590 -- TODO: Data sections, BSS sections. Needs extra C code and API.
591 map_coreop[".section_*"] = function(params)
592 if not params then return "name..." end
593 if #map_sections > 0 then werror("duplicate section definition") end
594 wflush()
595 for sn,name in ipairs(params) do
596 local opname = "."..name.."_0"
597 if not match(name, "^[%a][%w_]*$") or
598 map_op[opname] or map_op["."..name.."_*"] then
599 werror("bad section name `"..name.."'")
601 map_sections[#map_sections+1] = name
602 wline(format("#define DASM_SECTION_%s\t%d", upper(name), sn-1))
603 map_op[opname] = function(params) g_arch.section(sn-1) end
605 wline(format("#define DASM_MAXSECTION\t\t%d", #map_sections))
608 -- Dump all sections.
609 local function dumpsections(out, lvl)
610 out:write("Sections:\n")
611 for _,name in ipairs(map_sections) do
612 out:write(format(" %s\n", name))
614 out:write("\n")
617 ------------------------------------------------------------------------------
619 -- Replacement for customized Lua, which lacks the package library.
620 local prefix = ""
621 if not require then
622 function require(name)
623 local fp = assert(io.open(prefix..name..".lua"))
624 local s = fp:read("*a")
625 assert(fp:close())
626 return assert(loadstring(s, "@"..name..".lua"))()
630 -- Load architecture-specific module.
631 local function loadarch(arch)
632 if not match(arch, "^[%w_]+$") then return "bad arch name" end
633 local ok, m_arch = pcall(require, "dasm_"..arch)
634 if not ok then return "cannot load module: "..m_arch end
635 g_arch = m_arch
636 wflush = m_arch.passcb(wline, werror, wfatal, wwarn)
637 m_arch.setup(arch, g_opt)
638 map_op, map_def = m_arch.mergemaps(map_coreop, map_def)
641 -- Dump architecture description.
642 function opt_map.dumparch(args)
643 local name = optparam(args)
644 if not g_arch then
645 local err = loadarch(name)
646 if err then opterror(err) end
649 local t = {}
650 for name in pairs(map_coreop) do t[#t+1] = name end
651 for name in pairs(map_op) do t[#t+1] = name end
652 sort(t)
654 local out = stdout
655 local _arch = g_arch._info
656 out:write(format("%s version %s, released %s, %s\n",
657 _info.name, _info.version, _info.release, _info.url))
658 g_arch.dumparch(out)
660 local pseudo = true
661 out:write("Pseudo-Opcodes:\n")
662 for _,sname in ipairs(t) do
663 local name, nparam = match(sname, "^(.+)_([0-9%*])$")
664 if name then
665 if pseudo and sub(name, 1, 1) ~= "." then
666 out:write("\nOpcodes:\n")
667 pseudo = false
669 local f = map_op[sname]
670 local s
671 if nparam ~= "*" then nparam = nparam + 0 end
672 if nparam == 0 then
673 s = ""
674 elseif type(f) == "string" then
675 s = map_op[".template__"](nil, f, nparam)
676 else
677 s = f(nil, nparam)
679 if type(s) == "table" then
680 for _,s2 in ipairs(s) do
681 out:write(format(" %-12s %s\n", name, s2))
683 else
684 out:write(format(" %-12s %s\n", name, s))
688 out:write("\n")
689 exit(0)
692 -- Pseudo-opcode to set the architecture.
693 -- Only initially available (map_op is replaced when called).
694 map_op[".arch_1"] = function(params)
695 if not params then return "name" end
696 local err = loadarch(params[1])
697 if err then wfatal(err) end
698 wline(format("#if DASM_VERSION != %d", _info.vernum))
699 wline('#error "Version mismatch between DynASM and included encoding engine"')
700 wline("#endif")
703 -- Dummy .arch pseudo-opcode to improve the error report.
704 map_coreop[".arch_1"] = function(params)
705 if not params then return "name" end
706 wfatal("duplicate .arch statement")
709 ------------------------------------------------------------------------------
711 -- Dummy pseudo-opcode. Don't confuse '.nop' with 'nop'.
712 map_coreop[".nop_*"] = function(params)
713 if not params then return "[ignored...]" end
716 -- Pseudo-opcodes to raise errors.
717 map_coreop[".error_1"] = function(params)
718 if not params then return "message" end
719 werror(params[1])
722 map_coreop[".fatal_1"] = function(params)
723 if not params then return "message" end
724 wfatal(params[1])
727 -- Dump all user defined elements.
728 local function dumpdef(out)
729 local lvl = g_opt.dumpdef
730 if lvl == 0 then return end
731 dumpsections(out, lvl)
732 dumpdefines(out, lvl)
733 if g_arch then g_arch.dumpdef(out, lvl) end
734 dumpmacros(out, lvl)
735 dumpcaptures(out, lvl)
738 ------------------------------------------------------------------------------
740 -- Helper for splitstmt.
741 local splitlvl
743 local function splitstmt_one(c)
744 if c == "(" then
745 splitlvl = ")"..splitlvl
746 elseif c == "[" then
747 splitlvl = "]"..splitlvl
748 elseif c == "{" then
749 splitlvl = "}"..splitlvl
750 elseif c == ")" or c == "]" or c == "}" then
751 if sub(splitlvl, 1, 1) ~= c then werror("unbalanced (), [] or {}") end
752 splitlvl = sub(splitlvl, 2)
753 elseif splitlvl == "" then
754 return " \0 "
756 return c
759 -- Split statement into (pseudo-)opcode and params.
760 local function splitstmt(stmt)
761 -- Convert label with trailing-colon into .label statement.
762 local label = match(stmt, "^%s*(.+):%s*$")
763 if label then return ".label", {label} end
765 -- Split at commas and equal signs, but obey parentheses and brackets.
766 splitlvl = ""
767 stmt = gsub(stmt, "[,%(%)%[%]{}]", splitstmt_one)
768 if splitlvl ~= "" then werror("unbalanced () or []") end
770 -- Split off opcode.
771 local op, other = match(stmt, "^%s*([^%s%z]+)%s*(.*)$")
772 if not op then werror("bad statement syntax") end
774 -- Split parameters.
775 local params = {}
776 for p in gmatch(other, "%s*(%Z+)%z?") do
777 params[#params+1] = gsub(p, "%s+$", "")
779 if #params > 16 then werror("too many parameters") end
781 params.op = op
782 return op, params
785 -- Process a single statement.
786 dostmt = function(stmt)
787 -- Ignore empty statements.
788 if match(stmt, "^%s*$") then return end
790 -- Capture macro defs before substitution.
791 if mac_capture then return mac_capture(stmt) end
792 stmt = definesubst(stmt)
794 -- Emit C code without parsing the line.
795 if sub(stmt, 1, 1) == "|" then
796 local tail = sub(stmt, 2)
797 wflush()
798 if sub(tail, 1, 2) == "//" then wcomment(tail) else wline(tail, true) end
799 return
802 -- Split into (pseudo-)opcode and params.
803 local op, params = splitstmt(stmt)
805 -- Get opcode handler (matching # of parameters or generic handler).
806 local f = map_op[op.."_"..#params] or map_op[op.."_*"]
807 if not f then
808 if not g_arch then wfatal("first statement must be .arch") end
809 -- Improve error report.
810 for i=0,9 do
811 if map_op[op.."_"..i] then
812 werror("wrong number of parameters for `"..op.."'")
815 werror("unknown statement `"..op.."'")
818 -- Call opcode handler or special handler for template strings.
819 if type(f) == "string" then
820 map_op[".template__"](params, f)
821 else
822 f(params)
826 -- Process a single line.
827 local function doline(line)
828 if g_opt.flushline then wflush() end
830 -- Assembler line?
831 local indent, aline = match(line, "^(%s*)%|(.*)$")
832 if not aline then
833 -- No, plain C code line, need to flush first.
834 wflush()
835 wsync()
836 wline(line, false)
837 return
840 g_indent = indent -- Remember current line indentation.
842 -- Emit C code (even from macros). Avoids echo and line parsing.
843 if sub(aline, 1, 1) == "|" then
844 if not mac_capture then
845 wsync()
846 elseif g_opt.comment then
847 wsync()
848 wcomment(aline)
850 dostmt(aline)
851 return
854 -- Echo assembler line as a comment.
855 if g_opt.comment then
856 wsync()
857 wcomment(aline)
860 -- Strip assembler comments.
861 aline = gsub(aline, "//.*$", "")
863 -- Split line into statements at semicolons.
864 if match(aline, ";") then
865 for stmt in gmatch(aline, "[^;]+") do dostmt(stmt) end
866 else
867 dostmt(aline)
871 ------------------------------------------------------------------------------
873 -- Write DynASM header.
874 local function dasmhead(out)
875 out:write(format([[
877 ** This file has been pre-processed with DynASM.
878 ** %s
879 ** DynASM version %s, DynASM %s version %s
880 ** DO NOT EDIT! The original file is in "%s".
883 ]], _info.url,
884 _info.version, g_arch._info.arch, g_arch._info.version,
885 g_fname))
888 -- Read input file.
889 readfile = function(fin)
890 g_indent = ""
891 g_lineno = 0
892 g_synclineno = -1
894 -- Process all lines.
895 for line in fin:lines() do
896 g_lineno = g_lineno + 1
897 g_curline = line
898 local ok, err = pcall(doline, line)
899 if not ok and wprinterr(err, "\n") then return true end
901 wflush()
903 -- Close input file.
904 assert(fin == stdin or fin:close())
907 -- Write output file.
908 local function writefile(outfile)
909 local fout
911 -- Open output file.
912 if outfile == nil or outfile == "-" then
913 fout = stdout
914 else
915 fout = assert(io.open(outfile, "w"))
918 -- Write all buffered lines
919 wdumplines(fout, g_wbuffer)
921 -- Close output file.
922 assert(fout == stdout or fout:close())
924 -- Optionally dump definitions.
925 dumpdef(fout == stdout and stderr or stdout)
928 -- Translate an input file to an output file.
929 local function translate(infile, outfile)
930 g_wbuffer = {}
931 g_indent = ""
932 g_lineno = 0
933 g_synclineno = -1
935 -- Put header.
936 wline(dasmhead)
938 -- Read input file.
939 local fin
940 if infile == "-" then
941 g_fname = "(stdin)"
942 fin = stdin
943 else
944 g_fname = infile
945 fin = assert(io.open(infile, "r"))
947 readfile(fin)
949 -- Check for errors.
950 if not g_arch then
951 wprinterr(g_fname, ":*: error: missing .arch directive\n")
953 checkconds()
954 checkmacros()
955 checkcaptures()
957 if g_errcount ~= 0 then
958 stderr:write(g_fname, ":*: info: ", g_errcount, " error",
959 (type(g_errcount) == "number" and g_errcount > 1) and "s" or "",
960 " in input file -- no output file generated.\n")
961 dumpdef(stderr)
962 exit(1)
965 -- Write output file.
966 writefile(outfile)
969 ------------------------------------------------------------------------------
971 -- Print help text.
972 function opt_map.help()
973 stdout:write("DynASM -- ", _info.description, ".\n")
974 stdout:write("DynASM ", _info.version, " ", _info.release, " ", _info.url, "\n")
975 stdout:write[[
977 Usage: dynasm [OPTION]... INFILE.dasc|-
979 -h, --help Display this help text.
980 -V, --version Display version and copyright information.
982 -o, --outfile FILE Output file name (default is stdout).
983 -I, --include DIR Add directory to the include search path.
985 -c, --ccomment Use /* */ comments for assembler lines.
986 -C, --cppcomment Use // comments for assembler lines (default).
987 -N, --nocomment Suppress assembler lines in output.
988 -M, --maccomment Show macro expansions as comments (default off).
990 -L, --nolineno Suppress CPP line number information in output.
991 -F, --flushline Flush action list for every line.
993 -D NAME[=SUBST] Define a substitution.
994 -U NAME Undefine a substitution.
996 -P, --dumpdef Dump defines, macros, etc. Repeat for more output.
997 -A, --dumparch ARCH Load architecture ARCH and dump description.
999 exit(0)
1002 -- Print version information.
1003 function opt_map.version()
1004 stdout:write(format("%s version %s, released %s\n%s\n\n%s",
1005 _info.name, _info.version, _info.release, _info.url, _info.copyright))
1006 exit(0)
1009 -- Misc. options.
1010 function opt_map.outfile(args) g_opt.outfile = optparam(args) end
1011 function opt_map.include(args) insert(g_opt.include, 1, optparam(args)) end
1012 function opt_map.ccomment() g_opt.comment = "/*|"; g_opt.endcomment = " */" end
1013 function opt_map.cppcomment() g_opt.comment = "//|"; g_opt.endcomment = "" end
1014 function opt_map.nocomment() g_opt.comment = false end
1015 function opt_map.maccomment() g_opt.maccomment = true end
1016 function opt_map.nolineno() g_opt.cpp = false end
1017 function opt_map.flushline() g_opt.flushline = true end
1018 function opt_map.dumpdef() g_opt.dumpdef = g_opt.dumpdef + 1 end
1020 ------------------------------------------------------------------------------
1022 -- Short aliases for long options.
1023 local opt_alias = {
1024 h = "help", ["?"] = "help", V = "version",
1025 o = "outfile", I = "include",
1026 c = "ccomment", C = "cppcomment", N = "nocomment", M = "maccomment",
1027 L = "nolineno", F = "flushline",
1028 P = "dumpdef", A = "dumparch",
1031 -- Parse single option.
1032 local function parseopt(opt, args)
1033 opt_current = #opt == 1 and "-"..opt or "--"..opt
1034 local f = opt_map[opt] or opt_map[opt_alias[opt]]
1035 if not f then
1036 opterror("unrecognized option `", opt_current, "'. Try `--help'.\n")
1038 f(args)
1041 -- Parse arguments.
1042 local function parseargs(args)
1043 -- Default options.
1044 g_opt.comment = "//|"
1045 g_opt.endcomment = ""
1046 g_opt.cpp = true
1047 g_opt.dumpdef = 0
1048 g_opt.include = { "" }
1050 -- Process all option arguments.
1051 args.argn = 1
1052 repeat
1053 local a = args[args.argn]
1054 if not a then break end
1055 local lopt, opt = match(a, "^%-(%-?)(.+)")
1056 if not opt then break end
1057 args.argn = args.argn + 1
1058 if lopt == "" then
1059 -- Loop through short options.
1060 for o in gmatch(opt, ".") do parseopt(o, args) end
1061 else
1062 -- Long option.
1063 parseopt(opt, args)
1065 until false
1067 -- Check for proper number of arguments.
1068 local nargs = #args - args.argn + 1
1069 if nargs ~= 1 then
1070 if nargs == 0 then
1071 if g_opt.dumpdef > 0 then return dumpdef(stdout) end
1073 opt_map.help()
1076 -- Translate a single input file to a single output file
1077 -- TODO: Handle multiple files?
1078 translate(args[args.argn], g_opt.outfile)
1081 ------------------------------------------------------------------------------
1083 -- Add the directory dynasm.lua resides in to the Lua module search path.
1084 local arg = arg
1085 if arg and arg[0] then
1086 prefix = match(arg[0], "^(.*[/\\])")
1087 if package and prefix then package.path = prefix.."?.lua;"..package.path end
1090 -- Start DynASM.
1091 parseargs{...}
1093 ------------------------------------------------------------------------------