The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/tools/makesyscalls.lua

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 --
    2 -- SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3 --
    4 -- Copyright (c) 2019 Kyle Evans <kevans@FreeBSD.org>
    5 --
    6 -- Redistribution and use in source and binary forms, with or without
    7 -- modification, are permitted provided that the following conditions
    8 -- are met:
    9 -- 1. Redistributions of source code must retain the above copyright
   10 --    notice, this list of conditions and the following disclaimer.
   11 -- 2. Redistributions in binary form must reproduce the above copyright
   12 --    notice, this list of conditions and the following disclaimer in the
   13 --    documentation and/or other materials provided with the distribution.
   14 --
   15 -- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16 -- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17 -- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18 -- ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19 -- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20 -- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21 -- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22 -- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23 -- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24 -- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25 -- SUCH DAMAGE.
   26 --
   27 -- $FreeBSD$
   28 --
   29 
   30 
   31 -- We generally assume that this script will be run by flua, however we've
   32 -- carefully crafted modules for it that mimic interfaces provided by modules
   33 -- available in ports.  Currently, this script is compatible with lua from ports
   34 -- along with the compatible luafilesystem and lua-posix modules.
   35 local lfs = require("lfs")
   36 local unistd = require("posix.unistd")
   37 
   38 local savesyscall = -1
   39 local maxsyscall = -1
   40 local generated_tag = "@" .. "generated"
   41 
   42 -- Default configuration; any of these may get replaced by a configuration file
   43 -- optionally specified.
   44 local config = {
   45         os_id_keyword = "FreeBSD",
   46         abi_func_prefix = "",
   47         sysnames = "syscalls.c",
   48         sysproto = "../sys/sysproto.h",
   49         sysproto_h = "_SYS_SYSPROTO_H_",
   50         syshdr = "../sys/syscall.h",
   51         sysmk = "../sys/syscall.mk",
   52         syssw = "init_sysent.c",
   53         syscallprefix = "SYS_",
   54         switchname = "sysent",
   55         namesname = "syscallnames",
   56         systrace = "systrace_args.c",
   57         capabilities_conf = "capabilities.conf",
   58         capenabled = {},
   59         mincompat = 0,
   60         abi_type_suffix = "",
   61         abi_flags = "",
   62         abi_flags_mask = 0,
   63         ptr_intptr_t_cast = "intptr_t",
   64 }
   65 
   66 local config_modified = {}
   67 local cleantmp = true
   68 local tmpspace = "/tmp/sysent." .. unistd.getpid() .. "/"
   69 
   70 local output_files = {
   71         "sysnames",
   72         "syshdr",
   73         "sysmk",
   74         "syssw",
   75         "systrace",
   76         "sysproto",
   77 }
   78 
   79 -- These ones we'll create temporary files for; generation purposes.
   80 local temp_files = {
   81         "sysaue",
   82         "sysdcl",
   83         "syscompat",
   84         "syscompatdcl",
   85         "sysent",
   86         "sysinc",
   87         "sysarg",
   88         "sysprotoend",
   89         "systracetmp",
   90         "systraceret",
   91 }
   92 
   93 -- Opened files
   94 local files = {}
   95 
   96 local function cleanup()
   97         for _, v in pairs(files) do
   98                 assert(v:close())
   99         end
  100         if cleantmp then
  101                 if lfs.dir(tmpspace) then
  102                         for fname in lfs.dir(tmpspace) do
  103                                 if fname ~= "." and fname ~= ".." then
  104                                         assert(os.remove(tmpspace .. "/" ..
  105                                             fname))
  106                                 end
  107                         end
  108                 end
  109 
  110                 if lfs.attributes(tmpspace) and not lfs.rmdir(tmpspace) then
  111                         assert(io.stderr:write("Failed to clean up tmpdir: " ..
  112                             tmpspace .. "\n"))
  113                 end
  114         else
  115                 assert(io.stderr:write("Temp files left in " .. tmpspace ..
  116                     "\n"))
  117         end
  118 end
  119 
  120 local function abort(status, msg)
  121         assert(io.stderr:write(msg .. "\n"))
  122         cleanup()
  123         os.exit(status)
  124 end
  125 
  126 -- Each entry should have a value so we can represent abi flags as a bitmask
  127 -- for convenience.  One may also optionally provide an expr; this gets applied
  128 -- to each argument type to indicate whether this argument is subject to ABI
  129 -- change given the configured flags.
  130 local known_abi_flags = {
  131         long_size = {
  132                 value   = 0x00000001,
  133                 expr    = "_Contains[a-z_]*_long_",
  134         },
  135         time_t_size = {
  136                 value   = 0x00000002,
  137                 expr    = "_Contains[a-z_]*_timet_/",
  138         },
  139         pointer_args = {
  140                 value   = 0x00000004,
  141         },
  142         pointer_size = {
  143                 value   = 0x00000008,
  144                 expr    = "_Contains[a-z_]*_ptr_",
  145         },
  146 }
  147 
  148 local known_flags = {
  149         STD             = 0x00000001,
  150         OBSOL           = 0x00000002,
  151         RESERVED        = 0x00000004,
  152         UNIMPL          = 0x00000008,
  153         NODEF           = 0x00000010,
  154         NOARGS          = 0x00000020,
  155         NOPROTO         = 0x00000040,
  156         NOSTD           = 0x00000080,
  157         NOTSTATIC       = 0x00000100,
  158         CAPENABLED      = 0x00000200,
  159 
  160         -- Compat flags start from here.  We have plenty of space.
  161 }
  162 
  163 -- All compat_options entries should have five entries:
  164 --      definition: The preprocessor macro that will be set for this
  165 --      compatlevel: The level this compatibility should be included at.  This
  166 --          generally represents the version of FreeBSD that it is compatible
  167 --          with, but ultimately it's just the level of mincompat in which it's
  168 --          included.
  169 --      flag: The name of the flag in syscalls.master.
  170 --      prefix: The prefix to use for _args and syscall prototype.  This will be
  171 --          used as-is, without "_" or any other character appended.
  172 --      descr: The description of this compat option in init_sysent.c comments.
  173 -- The special "stdcompat" entry will cause the other five to be autogenerated.
  174 local compat_options = {
  175         {
  176                 definition = "COMPAT_43",
  177                 compatlevel = 3,
  178                 flag = "COMPAT",
  179                 prefix = "o",
  180                 descr = "old",
  181         },
  182         { stdcompat = "FREEBSD4" },
  183         { stdcompat = "FREEBSD6" },
  184         { stdcompat = "FREEBSD7" },
  185         { stdcompat = "FREEBSD10" },
  186         { stdcompat = "FREEBSD11" },
  187         { stdcompat = "FREEBSD12" },
  188 }
  189 
  190 local function trim(s, char)
  191         if s == nil then
  192                 return nil
  193         end
  194         if char == nil then
  195                 char = "%s"
  196         end
  197         return s:gsub("^" .. char .. "+", ""):gsub(char .. "+$", "")
  198 end
  199 
  200 -- We have to io.popen it, making sure it's properly escaped, and grab the
  201 -- output from the handle returned.
  202 local function exec(cmd)
  203         cmd = cmd:gsub('"', '\\"')
  204 
  205         local shcmd = "/bin/sh -c \"" .. cmd .. "\""
  206         local fh = io.popen(shcmd)
  207         local output = fh:read("a")
  208 
  209         fh:close()
  210         return output
  211 end
  212 
  213 -- config looks like a shell script; in fact, the previous makesyscalls.sh
  214 -- script actually sourced it in.  It had a pretty common format, so we should
  215 -- be fine to make various assumptions
  216 local function process_config(file)
  217         local cfg = {}
  218         local comment_line_expr = "^%s*#.*"
  219         -- We capture any whitespace padding here so we can easily advance to
  220         -- the end of the line as needed to check for any trailing bogus bits.
  221         -- Alternatively, we could drop the whitespace and instead try to
  222         -- use a pattern to strip out the meaty part of the line, but then we
  223         -- would need to sanitize the line for potentially special characters.
  224         local line_expr = "^([%w%p]+%s*)=(%s*[`\"]?[^\"`]+[`\"]?)"
  225 
  226         if not file then
  227                 return nil, "No file given"
  228         end
  229 
  230         local fh = assert(io.open(file))
  231 
  232         for nextline in fh:lines() do
  233                 -- Strip any whole-line comments
  234                 nextline = nextline:gsub(comment_line_expr, "")
  235                 -- Parse it into key, value pairs
  236                 local key, value = nextline:match(line_expr)
  237                 if key ~= nil and value ~= nil then
  238                         local kvp = key .. "=" .. value
  239                         key = trim(key)
  240                         value = trim(value)
  241                         local delim = value:sub(1,1)
  242                         if delim == '`' or delim == '"' then
  243                                 local trailing_context
  244                                 -- Strip off the key/value part
  245                                 trailing_context = nextline:sub(kvp:len() + 1)
  246                                 -- Strip off any trailing comment
  247                                 trailing_context = trailing_context:gsub("#.*$",
  248                                     "")
  249                                 -- Strip off leading/trailing whitespace
  250                                 trailing_context = trim(trailing_context)
  251                                 if trailing_context ~= "" then
  252                                         print(trailing_context)
  253                                         abort(1, "Malformed line: " .. nextline)
  254                                 end
  255                         end
  256                         if delim == '`' then
  257                                 -- Command substition may use $1 and $2 to mean
  258                                 -- the syscall definition file and itself
  259                                 -- respectively.  We'll go ahead and replace
  260                                 -- $[0-9] with respective arg in case we want to
  261                                 -- expand this in the future easily...
  262                                 value = trim(value, delim)
  263                                 for capture in value:gmatch("$([0-9]+)") do
  264                                         capture = tonumber(capture)
  265                                         if capture > #arg then
  266                                                 abort(1, "Not enough args: " ..
  267                                                     value)
  268                                         end
  269                                         value = value:gsub("$" .. capture,
  270                                             arg[capture])
  271                                 end
  272 
  273                                 value = exec(value)
  274                         elseif delim == '"' then
  275                                 value = trim(value, delim)
  276                         else
  277                                 -- Strip off potential comments
  278                                 value = value:gsub("#.*$", "")
  279                                 -- Strip off any padding whitespace
  280                                 value = trim(value)
  281                                 if value:match("%s") then
  282                                         abort(1, "Malformed config line: " ..
  283                                             nextline)
  284                                 end
  285                         end
  286                         cfg[key] = value
  287                 elseif not nextline:match("^%s*$") then
  288                         -- Make sure format violations don't get overlooked
  289                         -- here, but ignore blank lines.  Comments are already
  290                         -- stripped above.
  291                         abort(1, "Malformed config line: " .. nextline)
  292                 end
  293         end
  294 
  295         assert(io.close(fh))
  296         return cfg
  297 end
  298 
  299 local function grab_capenabled(file, open_fail_ok)
  300         local capentries = {}
  301         local commentExpr = "#.*"
  302 
  303         if file == nil then
  304                 print "No file"
  305                 return {}
  306         end
  307 
  308         local fh = io.open(file)
  309         if fh == nil then
  310                 if not open_fail_ok then
  311                         abort(1, "Failed to open " .. file)
  312                 end
  313                 return {}
  314         end
  315 
  316         for nextline in fh:lines() do
  317                 -- Strip any comments
  318                 nextline = nextline:gsub(commentExpr, "")
  319                 if nextline ~= "" then
  320                         capentries[nextline] = true
  321                 end
  322         end
  323 
  324         assert(io.close(fh))
  325         return capentries
  326 end
  327 
  328 local function process_compat()
  329         local nval = 0
  330         for _, v in pairs(known_flags) do
  331                 if v > nval then
  332                         nval = v
  333                 end
  334         end
  335 
  336         nval = nval << 1
  337         for _, v in pairs(compat_options) do
  338                 if v["stdcompat"] ~= nil then
  339                         local stdcompat = v["stdcompat"]
  340                         v["definition"] = "COMPAT_" .. stdcompat:upper()
  341                         v["compatlevel"] = tonumber(stdcompat:match("([0-9]+)$"))
  342                         v["flag"] = stdcompat:gsub("FREEBSD", "COMPAT")
  343                         v["prefix"] = stdcompat:lower() .. "_"
  344                         v["descr"] = stdcompat:lower()
  345                 end
  346 
  347                 local tmpname = "sys" .. v["flag"]:lower()
  348                 local dcltmpname = tmpname .. "dcl"
  349                 files[tmpname] = io.tmpfile()
  350                 files[dcltmpname] = io.tmpfile()
  351                 v["tmp"] = tmpname
  352                 v["dcltmp"] = dcltmpname
  353 
  354                 known_flags[v["flag"]] = nval
  355                 v["mask"] = nval
  356                 nval = nval << 1
  357 
  358                 v["count"] = 0
  359         end
  360 end
  361 
  362 local function process_abi_flags()
  363         local flags, mask = config["abi_flags"], 0
  364         for txtflag in flags:gmatch("([^|]+)") do
  365                 if known_abi_flags[txtflag] == nil then
  366                         abort(1, "Unknown abi_flag: " .. txtflag)
  367                 end
  368 
  369                 mask = mask | known_abi_flags[txtflag]["value"]
  370         end
  371 
  372         config["abi_flags_mask"] = mask
  373 end
  374 
  375 local function abi_changes(name)
  376         if known_abi_flags[name] == nil then
  377                 abort(1, "abi_changes: unknown flag: " .. name)
  378         end
  379 
  380         return config["abi_flags_mask"] & known_abi_flags[name]["value"] ~= 0
  381 end
  382 
  383 local function strip_abi_prefix(funcname)
  384         local abiprefix = config["abi_func_prefix"]
  385         local stripped_name
  386         if abiprefix ~= "" and funcname:find("^" .. abiprefix) then
  387                 stripped_name = funcname:gsub("^" .. abiprefix, "")
  388         else
  389                 stripped_name = funcname
  390         end
  391 
  392         return stripped_name
  393 end
  394 
  395 local function read_file(tmpfile)
  396         if files[tmpfile] == nil then
  397                 print("Not found: " .. tmpfile)
  398                 return
  399         end
  400 
  401         local fh = files[tmpfile]
  402         assert(fh:seek("set"))
  403         return assert(fh:read("a"))
  404 end
  405 
  406 local function write_line(tmpfile, line)
  407         if files[tmpfile] == nil then
  408                 print("Not found: " .. tmpfile)
  409                 return
  410         end
  411         assert(files[tmpfile]:write(line))
  412 end
  413 
  414 local function write_line_pfile(tmppat, line)
  415         for k in pairs(files) do
  416                 if k:match(tmppat) ~= nil then
  417                         assert(files[k]:write(line))
  418                 end
  419         end
  420 end
  421 
  422 local function isptrtype(type)
  423         return type:find("*") or type:find("caddr_t")
  424             -- XXX NOTYET: or type:find("intptr_t")
  425 end
  426 
  427 local process_syscall_def
  428 
  429 -- These patterns are processed in order on any line that isn't empty.
  430 local pattern_table = {
  431         {
  432                 pattern = "%s*$" .. config['os_id_keyword'],
  433                 process = function(_, _)
  434                         -- Ignore... ID tag
  435                 end,
  436         },
  437         {
  438                 dump_prevline = true,
  439                 pattern = "^#%s*include",
  440                 process = function(line)
  441                         line = line .. "\n"
  442                         write_line('sysinc', line)
  443                 end,
  444         },
  445         {
  446                 dump_prevline = true,
  447                 pattern = "^#",
  448                 process = function(line)
  449                         if line:find("^#%s*if") then
  450                                 savesyscall = maxsyscall
  451                         elseif line:find("^#%s*else") then
  452                                 maxsyscall = savesyscall
  453                         end
  454                         line = line .. "\n"
  455                         write_line('sysent', line)
  456                         write_line('sysdcl', line)
  457                         write_line('sysarg', line)
  458                         write_line_pfile('syscompat[0-9]*$', line)
  459                         write_line('sysnames', line)
  460                         write_line_pfile('systrace.*', line)
  461                 end,
  462         },
  463         {
  464                 -- Buffer anything else
  465                 pattern = ".+",
  466                 process = function(line, prevline)
  467                         local incomplete = line:find("\\$") ~= nil
  468                         -- Lines that end in \ get the \ stripped
  469                         -- Lines that start with a syscall number, prepend \n
  470                         line = trim(line):gsub("\\$", "")
  471                         if line:find("^[0-9]") and prevline then
  472                                 process_syscall_def(prevline)
  473                                 prevline = nil
  474                         end
  475 
  476                         prevline = (prevline or '') .. line
  477                         incomplete = incomplete or prevline:find(",$") ~= nil
  478                         incomplete = incomplete or prevline:find("{") ~= nil and
  479                             prevline:find("}") == nil
  480                         if prevline:find("^[0-9]") and not incomplete then
  481                                 process_syscall_def(prevline)
  482                                 prevline = nil
  483                         end
  484 
  485                         return prevline
  486                 end,
  487         },
  488 }
  489 
  490 local function process_sysfile(file)
  491         local capentries = {}
  492         local commentExpr = "^%s*;.*"
  493 
  494         if file == nil then
  495                 print "No file"
  496                 return {}
  497         end
  498 
  499         local fh = io.open(file)
  500         if fh == nil then
  501                 print("Failed to open " .. file)
  502                 return {}
  503         end
  504 
  505         local function do_match(nextline, prevline)
  506                 local pattern, handler, dump
  507                 for _, v in pairs(pattern_table) do
  508                         pattern = v['pattern']
  509                         handler = v['process']
  510                         dump = v['dump_prevline']
  511                         if nextline:match(pattern) then
  512                                 if dump and prevline then
  513                                         process_syscall_def(prevline)
  514                                         prevline = nil
  515                                 end
  516 
  517                                 return handler(nextline, prevline)
  518                         end
  519                 end
  520 
  521                 abort(1, "Failed to handle: " .. nextline)
  522         end
  523 
  524         local prevline
  525         for nextline in fh:lines() do
  526                 -- Strip any comments
  527                 nextline = nextline:gsub(commentExpr, "")
  528                 if nextline ~= "" then
  529                         prevline = do_match(nextline, prevline)
  530                 end
  531         end
  532 
  533         -- Dump any remainder
  534         if prevline ~= nil and prevline:find("^[0-9]") then
  535                 process_syscall_def(prevline)
  536         end
  537 
  538         assert(io.close(fh))
  539         return capentries
  540 end
  541 
  542 local function get_mask(flags)
  543         local mask = 0
  544         for _, v in ipairs(flags) do
  545                 if known_flags[v] == nil then
  546                         abort(1, "Checking for unknown flag " .. v)
  547                 end
  548 
  549                 mask = mask | known_flags[v]
  550         end
  551 
  552         return mask
  553 end
  554 
  555 local function get_mask_pat(pflags)
  556         local mask = 0
  557         for k, v in pairs(known_flags) do
  558                 if k:find(pflags) then
  559                         mask = mask | v
  560                 end
  561         end
  562 
  563         return mask
  564 end
  565 
  566 local function align_sysent_comment(col)
  567         write_line("sysent", "\t")
  568         col = col + 8 - col % 8
  569         while col < 56 do
  570                 write_line("sysent", "\t")
  571                 col = col + 8
  572         end
  573 end
  574 
  575 local function strip_arg_annotations(arg)
  576         arg = arg:gsub("_In[^ ]*[_)] ?", "")
  577         arg = arg:gsub("_Out[^ ]*[_)] ?", "")
  578         return trim(arg)
  579 end
  580 
  581 local function check_abi_changes(arg)
  582         for k, v in pairs(known_abi_flags) do
  583                 local expr = v["expr"]
  584                 if abi_changes(k) and expr ~= nil and arg:find(expr) then
  585                         return true
  586                 end
  587         end
  588 
  589         return false
  590 end
  591 
  592 local function process_args(args)
  593         local funcargs = {}
  594 
  595         for arg in args:gmatch("([^,]+)") do
  596                 local abi_change = not isptrtype(arg) or check_abi_changes(arg)
  597 
  598                 arg = strip_arg_annotations(arg)
  599 
  600                 local argname = arg:match("([^* ]+)$")
  601 
  602                 -- argtype is... everything else.
  603                 local argtype = trim(arg:gsub(argname .. "$", ""), nil)
  604 
  605                 if argtype == "" and argname == "void" then
  606                         goto out
  607                 end
  608 
  609                 -- XX TODO: Forward declarations? See: sysstubfwd in CheriBSD
  610                 if abi_change then
  611                         local abi_type_suffix = config["abi_type_suffix"]
  612                         argtype = argtype:gsub("_native ", "")
  613                         argtype = argtype:gsub("(struct [^ ]*)", "%1" ..
  614                             abi_type_suffix)
  615                         argtype = argtype:gsub("(union [^ ]*)", "%1" ..
  616                             abi_type_suffix)
  617                 end
  618 
  619                 funcargs[#funcargs + 1] = {
  620                         type = argtype,
  621                         name = argname,
  622                 }
  623         end
  624 
  625         ::out::
  626         return funcargs
  627 end
  628 
  629 local function handle_noncompat(sysnum, thr_flag, flags, sysflags, rettype,
  630     auditev, syscallret, funcname, funcalias, funcargs, argalias)
  631         local argssize
  632 
  633         if #funcargs > 0 or flags & known_flags["NODEF"] ~= 0 then
  634                 argssize = "AS(" .. argalias .. ")"
  635         else
  636                 argssize = "0"
  637         end
  638 
  639         write_line("systrace", string.format([[
  640         /* %s */
  641         case %d: {
  642 ]], funcname, sysnum))
  643         write_line("systracetmp", string.format([[
  644         /* %s */
  645         case %d:
  646 ]], funcname, sysnum))
  647         write_line("systraceret", string.format([[
  648         /* %s */
  649         case %d:
  650 ]], funcname, sysnum))
  651 
  652         if #funcargs > 0 then
  653                 write_line("systracetmp", "\t\tswitch (ndx) {\n")
  654                 write_line("systrace", string.format(
  655                     "\t\tstruct %s *p = params;\n", argalias))
  656 
  657                 local argtype, argname
  658                 for idx, arg in ipairs(funcargs) do
  659                         argtype = arg["type"]
  660                         argname = arg["name"]
  661 
  662                         argtype = trim(argtype:gsub("__restrict$", ""), nil)
  663                         -- Pointer arg?
  664                         if argtype:find("*") then
  665                                 write_line("systracetmp", string.format(
  666                                     "\t\tcase %d:\n\t\t\tp = \"userland %s\";\n\t\t\tbreak;\n",
  667                                     idx - 1, argtype))
  668                         else
  669                                 write_line("systracetmp", string.format(
  670                                     "\t\tcase %d:\n\t\t\tp = \"%s\";\n\t\t\tbreak;\n",
  671                                     idx - 1, argtype))
  672                         end
  673 
  674                         if isptrtype(argtype) then
  675                                 write_line("systrace", string.format(
  676                                     "\t\tuarg[%d] = (%s)p->%s; /* %s */\n",
  677                                     idx - 1, config["ptr_intptr_t_cast"],
  678                                     argname, argtype))
  679                         elseif argtype == "union l_semun" then
  680                                 write_line("systrace", string.format(
  681                                     "\t\tuarg[%d] = p->%s.buf; /* %s */\n",
  682                                     idx - 1, argname, argtype))
  683                         elseif argtype:sub(1,1) == "u" or argtype == "size_t" then
  684                                 write_line("systrace", string.format(
  685                                     "\t\tuarg[%d] = p->%s; /* %s */\n",
  686                                     idx - 1, argname, argtype))
  687                         else
  688                                 write_line("systrace", string.format(
  689                                     "\t\tiarg[%d] = p->%s; /* %s */\n",
  690                                     idx - 1, argname, argtype))
  691                         end
  692                 end
  693 
  694                 write_line("systracetmp",
  695                     "\t\tdefault:\n\t\t\tbreak;\n\t\t};\n")
  696 
  697                 write_line("systraceret", string.format([[
  698                 if (ndx == 0 || ndx == 1)
  699                         p = "%s";
  700                 break;
  701 ]], syscallret))
  702         end
  703         write_line("systrace", string.format(
  704             "\t\t*n_args = %d;\n\t\tbreak;\n\t}\n", #funcargs))
  705         write_line("systracetmp", "\t\tbreak;\n")
  706 
  707         local nargflags = get_mask({"NOARGS", "NOPROTO", "NODEF"})
  708         if flags & nargflags == 0 then
  709                 if #funcargs > 0 then
  710                         write_line("sysarg", string.format("struct %s {\n",
  711                             argalias))
  712                         for _, v in ipairs(funcargs) do
  713                                 local argname, argtype = v["name"], v["type"]
  714                                 write_line("sysarg", string.format(
  715                                     "\tchar %s_l_[PADL_(%s)]; %s %s; char %s_r_[PADR_(%s)];\n",
  716                                     argname, argtype,
  717                                     argtype, argname,
  718                                     argname, argtype))
  719                         end
  720                         write_line("sysarg", "};\n")
  721                 else
  722                         write_line("sysarg", string.format(
  723                             "struct %s {\n\tregister_t dummy;\n};\n", argalias))
  724                 end
  725         end
  726 
  727         local protoflags = get_mask({"NOPROTO", "NODEF"})
  728         if flags & protoflags == 0 then
  729                 if funcname == "nosys" or funcname == "lkmnosys" or
  730                     funcname == "sysarch" or funcname:find("^freebsd") or
  731                     funcname:find("^linux") or
  732                     funcname:find("^cloudabi") then
  733                         write_line("sysdcl", string.format(
  734                             "%s\t%s(struct thread *, struct %s *)",
  735                             rettype, funcname, argalias))
  736                 else
  737                         write_line("sysdcl", string.format(
  738                             "%s\tsys_%s(struct thread *, struct %s *)",
  739                             rettype, funcname, argalias))
  740                 end
  741                 write_line("sysdcl", ";\n")
  742                 write_line("sysaue", string.format("#define\t%sAUE_%s\t%s\n",
  743                     config['syscallprefix'], funcalias, auditev))
  744         end
  745 
  746         write_line("sysent",
  747             string.format("\t{ .sy_narg = %s, .sy_call = (sy_call_t *)", argssize))
  748         local column = 8 + 2 + #argssize + 15
  749 
  750         if flags & known_flags["NOSTD"] ~= 0 then
  751                 write_line("sysent", string.format(
  752                     "lkmressys, .sy_auevent = AUE_NULL, " ..
  753                     ".sy_flags = %s, .sy_thrcnt = SY_THR_ABSENT },",
  754                     sysflags))
  755                 column = column + #"lkmressys" + #"AUE_NULL" + 3
  756         else
  757                 if funcname == "nosys" or funcname == "lkmnosys" or
  758                     funcname == "sysarch" or funcname:find("^freebsd") or
  759                     funcname:find("^linux") or
  760                     funcname:find("^cloudabi") then
  761                         write_line("sysent", string.format(
  762                             "%s, .sy_auevent = %s, .sy_flags = %s, .sy_thrcnt = %s },",
  763                             funcname, auditev, sysflags, thr_flag))
  764                         column = column + #funcname + #auditev + #sysflags + 3
  765                 else
  766                         write_line("sysent", string.format(
  767                             "sys_%s, .sy_auevent = %s, .sy_flags = %s, .sy_thrcnt = %s },",
  768                             funcname, auditev, sysflags, thr_flag))
  769                         column = column + #funcname + #auditev + #sysflags + 7
  770                 end
  771         end
  772 
  773         align_sysent_comment(column)
  774         write_line("sysent", string.format("/* %d = %s */\n",
  775             sysnum, funcalias))
  776         write_line("sysnames", string.format("\t\"%s\",\t\t\t/* %d = %s */\n",
  777             funcalias, sysnum, funcalias))
  778 
  779         if flags & known_flags["NODEF"] == 0 then
  780                 write_line("syshdr", string.format("#define\t%s%s\t%d\n",
  781                     config['syscallprefix'], funcalias, sysnum))
  782                 write_line("sysmk", string.format(" \\\n\t%s.o",
  783                     funcalias))
  784         end
  785 end
  786 
  787 local function handle_obsol(sysnum, funcname, comment)
  788         write_line("sysent",
  789             "\t{ .sy_narg = 0, .sy_call = (sy_call_t *)nosys, " ..
  790             ".sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_ABSENT },")
  791         align_sysent_comment(34)
  792 
  793         write_line("sysent", string.format("/* %d = obsolete %s */\n",
  794             sysnum, comment))
  795         write_line("sysnames", string.format(
  796             "\t\"obs_%s\",\t\t\t/* %d = obsolete %s */\n",
  797             funcname, sysnum, comment))
  798         write_line("syshdr", string.format("\t\t\t\t/* %d is obsolete %s */\n",
  799             sysnum, comment))
  800 end
  801 
  802 local function handle_compat(sysnum, thr_flag, flags, sysflags, rettype,
  803     auditev, funcname, funcalias, funcargs, argalias)
  804         local argssize, out, outdcl, wrap, prefix, descr
  805 
  806         if #funcargs > 0 or flags & known_flags["NODEF"] ~= 0 then
  807                 argssize = "AS(" .. argalias .. ")"
  808         else
  809                 argssize = "0"
  810         end
  811 
  812         for _, v in pairs(compat_options) do
  813                 if flags & v["mask"] ~= 0 then
  814                         if config["mincompat"] > v["compatlevel"] then
  815                                 funcname = strip_abi_prefix(funcname)
  816                                 funcname = v["prefix"] .. funcname
  817                                 return handle_obsol(sysnum, funcname, funcname)
  818                         end
  819                         v["count"] = v["count"] + 1
  820                         out = v["tmp"]
  821                         outdcl = v["dcltmp"]
  822                         wrap = v["flag"]:lower()
  823                         prefix = v["prefix"]
  824                         descr = v["descr"]
  825                         goto compatdone
  826                 end
  827         end
  828 
  829         ::compatdone::
  830         local dprotoflags = get_mask({"NOPROTO", "NODEF"})
  831         local nargflags = dprotoflags | known_flags["NOARGS"]
  832         if #funcargs > 0 and flags & nargflags == 0 then
  833                 write_line(out, string.format("struct %s {\n", argalias))
  834                 for _, v in ipairs(funcargs) do
  835                         local argname, argtype = v["name"], v["type"]
  836                         write_line(out, string.format(
  837                             "\tchar %s_l_[PADL_(%s)]; %s %s; char %s_r_[PADR_(%s)];\n",
  838                             argname, argtype,
  839                             argtype, argname,
  840                             argname, argtype))
  841                 end
  842                 write_line(out, "};\n")
  843         elseif flags & nargflags == 0 then
  844                 write_line("sysarg", string.format(
  845                     "struct %s {\n\tregister_t dummy;\n};\n", argalias))
  846         end
  847         if flags & dprotoflags == 0 then
  848                 write_line(outdcl, string.format(
  849                     "%s\t%s%s(struct thread *, struct %s *);\n",
  850                     rettype, prefix, funcname, argalias))
  851                 write_line("sysaue", string.format(
  852                     "#define\t%sAUE_%s%s\t%s\n", config['syscallprefix'],
  853                     prefix, funcname, auditev))
  854         end
  855 
  856         if flags & known_flags['NOSTD'] ~= 0 then
  857                 write_line("sysent", string.format(
  858                     "\t{ .sy_narg = %s, .sy_call = (sy_call_t *)%s, " ..
  859                     ".sy_auevent = %s, .sy_flags = 0, " ..
  860                     ".sy_thrcnt = SY_THR_ABSENT },",
  861                     "0", "lkmressys", "AUE_NULL"))
  862                 align_sysent_comment(8 + 2 + #"0" + 15 + #"lkmressys" +
  863                     #"AUE_NULL" + 3)
  864         else
  865                 write_line("sysent", string.format(
  866                     "\t{ %s(%s,%s), .sy_auevent = %s, .sy_flags = %s, .sy_thrcnt = %s },",
  867                     wrap, argssize, funcname, auditev, sysflags, thr_flag))
  868                 align_sysent_comment(8 + 9 + #argssize + 1 + #funcname +
  869                     #auditev + #sysflags + 4)
  870         end
  871 
  872         write_line("sysent", string.format("/* %d = %s %s */\n",
  873             sysnum, descr, funcalias))
  874         write_line("sysnames", string.format(
  875             "\t\"%s.%s\",\t\t/* %d = %s %s */\n",
  876             wrap, funcalias, sysnum, descr, funcalias))
  877         -- Do not provide freebsdN_* symbols in libc for < FreeBSD 7
  878         local nosymflags = get_mask({"COMPAT", "COMPAT4", "COMPAT6"})
  879         if flags & nosymflags ~= 0 then
  880                 write_line("syshdr", string.format(
  881                     "\t\t\t\t/* %d is %s %s */\n",
  882                     sysnum, descr, funcalias))
  883         elseif flags & known_flags["NODEF"] == 0 then
  884                 write_line("syshdr", string.format("#define\t%s%s%s\t%d\n",
  885                     config['syscallprefix'], prefix, funcalias, sysnum))
  886                 write_line("sysmk", string.format(" \\\n\t%s%s.o",
  887                     prefix, funcalias))
  888         end
  889 end
  890 
  891 local function handle_unimpl(sysnum, sysstart, sysend, comment)
  892         if sysstart == nil and sysend == nil then
  893                 sysstart = tonumber(sysnum)
  894                 sysend = tonumber(sysnum)
  895         end
  896 
  897         sysnum = sysstart
  898         while sysnum <= sysend do
  899                 write_line("sysent", string.format(
  900                     "\t{ .sy_narg = 0, .sy_call = (sy_call_t *)nosys, " ..
  901                     ".sy_auevent = AUE_NULL, .sy_flags = 0, " ..
  902                     ".sy_thrcnt = SY_THR_ABSENT },\t\t\t/* %d = %s */\n",
  903                     sysnum, comment))
  904                 write_line("sysnames", string.format(
  905                     "\t\"#%d\",\t\t\t/* %d = %s */\n",
  906                     sysnum, sysnum, comment))
  907                 sysnum = sysnum + 1
  908         end
  909 end
  910 
  911 local function handle_reserved(sysnum, sysstart, sysend, comment)
  912         handle_unimpl(sysnum, sysstart, sysend, "reserved for local use")
  913 end
  914 
  915 process_syscall_def = function(line)
  916         local sysstart, sysend, flags, funcname, sysflags
  917         local thr_flag, syscallret
  918         local orig = line
  919         flags = 0
  920         thr_flag = "SY_THR_STATIC"
  921 
  922         -- Parse out the interesting information first
  923         local initialExpr = "^([^%s]+)%s+([^%s]+)%s+([^%s]+)%s*"
  924         local sysnum, auditev, allflags = line:match(initialExpr)
  925 
  926         if sysnum == nil or auditev == nil or allflags == nil then
  927                 -- XXX TODO: Better?
  928                 abort(1, "Completely malformed: " .. line)
  929         end
  930 
  931         if sysnum:find("-") then
  932                 sysstart, sysend = sysnum:match("^([%d]+)-([%d]+)$")
  933                 if sysstart == nil or sysend == nil then
  934                         abort(1, "Malformed range: " .. sysnum)
  935                 end
  936                 sysnum = nil
  937                 sysstart = tonumber(sysstart)
  938                 sysend = tonumber(sysend)
  939                 if sysstart ~= maxsyscall + 1 then
  940                         abort(1, "syscall number out of sync, missing " ..
  941                             maxsyscall + 1)
  942                 end
  943         else
  944                 sysnum = tonumber(sysnum)
  945                 if sysnum ~= maxsyscall + 1 then
  946                         abort(1, "syscall number out of sync, missing " ..
  947                             maxsyscall + 1)
  948                 end
  949         end
  950 
  951         -- Split flags
  952         for flag in allflags:gmatch("([^|]+)") do
  953                 if known_flags[flag] == nil then
  954                         abort(1, "Unknown flag " .. flag .. " for " ..  sysnum)
  955                 end
  956                 flags = flags | known_flags[flag]
  957         end
  958 
  959         if (flags & get_mask({"RESERVED", "UNIMPL"})) == 0 and sysnum == nil then
  960                 abort(1, "Range only allowed with RESERVED and UNIMPL: " .. line)
  961         end
  962 
  963         if (flags & known_flags["NOTSTATIC"]) ~= 0 then
  964                 thr_flag = "SY_THR_ABSENT"
  965         end
  966 
  967         -- Strip earlier bits out, leave declaration + alt
  968         line = line:gsub("^.+" .. allflags .. "%s*", "")
  969 
  970         local decl_fnd = line:find("^{") ~= nil
  971         if decl_fnd and line:find("}") == nil then
  972                 abort(1, "Malformed, no closing brace: " .. line)
  973         end
  974 
  975         local decl, alt
  976         if decl_fnd then
  977                 line = line:gsub("^{", "")
  978                 decl, alt = line:match("([^}]*)}[%s]*(.*)$")
  979         else
  980                 alt = line
  981         end
  982 
  983         if decl == nil and alt == nil then
  984                 abort(1, "Malformed bits: " .. line)
  985         end
  986 
  987         local funcalias, funcomment, argalias, rettype, args
  988         if not decl_fnd and alt ~= nil and alt ~= "" then
  989                 -- Peel off one entry for name
  990                 funcname = trim(alt:match("^([^%s]+)"), nil)
  991                 alt = alt:gsub("^([^%s]+)[%s]*", "")
  992         end
  993         -- Do we even need it?
  994         if flags & get_mask({"OBSOL", "UNIMPL"}) ~= 0 then
  995                 local NF = 0
  996                 for _ in orig:gmatch("[^%s]+") do
  997                         NF = NF + 1
  998                 end
  999 
 1000                 funcomment = funcname or ''
 1001                 if NF < 6 then
 1002                         funcomment = funcomment .. " " .. alt
 1003                 end
 1004 
 1005                 funcomment = trim(funcomment)
 1006 
 1007 --              if funcname ~= nil then
 1008 --              else
 1009 --                      funcomment = trim(alt)
 1010 --              end
 1011                 goto skipalt
 1012         end
 1013 
 1014         if alt ~= nil and alt ~= "" then
 1015                 local altExpr = "^([^%s]+)%s+([^%s]+)%s+([^%s]+)"
 1016                 funcalias, argalias, rettype = alt:match(altExpr)
 1017                 funcalias = trim(funcalias)
 1018                 if funcalias == nil or argalias == nil or rettype == nil then
 1019                         abort(1, "Malformed alt: " .. line)
 1020                 end
 1021         end
 1022         if decl_fnd then
 1023                 -- Don't clobber rettype set in the alt information
 1024                 if rettype == nil then
 1025                         rettype = "int"
 1026                 end
 1027                 -- Peel off the return type
 1028                 syscallret = line:match("([^%s]+)%s")
 1029                 line = line:match("[^%s]+%s(.+)")
 1030                 -- Pointer incoming
 1031                 if line:sub(1,1) == "*" then
 1032                         syscallret = syscallret .. " "
 1033                 end
 1034                 while line:sub(1,1) == "*" do
 1035                         line = line:sub(2)
 1036                         syscallret = syscallret .. "*"
 1037                 end
 1038                 funcname = line:match("^([^(]+)%(")
 1039                 if funcname == nil then
 1040                         abort(1, "Not a signature? " .. line)
 1041                 end
 1042                 args = line:match("^[^(]+%((.+)%)[^)]*$")
 1043                 args = trim(args, '[,%s]')
 1044         end
 1045 
 1046         ::skipalt::
 1047 
 1048         if funcname == nil then
 1049                 funcname = funcalias
 1050         end
 1051 
 1052         funcname = trim(funcname)
 1053 
 1054         sysflags = "0"
 1055 
 1056         -- NODEF events do not get audited
 1057         if flags & known_flags['NODEF'] ~= 0 then
 1058                 auditev = 'AUE_NULL'
 1059         end
 1060 
 1061         -- If applicable; strip the ABI prefix from the name
 1062         local stripped_name = strip_abi_prefix(funcname)
 1063 
 1064         if flags & known_flags['CAPENABLED'] ~= 0 or
 1065             config["capenabled"][funcname] ~= nil or
 1066             config["capenabled"][stripped_name] ~= nil then
 1067                 sysflags = "SYF_CAPENABLED"
 1068         end
 1069 
 1070         local funcargs = {}
 1071         if args ~= nil then
 1072                 funcargs = process_args(args)
 1073         end
 1074 
 1075         local argprefix = ''
 1076         if abi_changes("pointer_args") then
 1077                 for _, v in ipairs(funcargs) do
 1078                         if isptrtype(v["type"]) then
 1079                                 -- argalias should be:
 1080                                 --   COMPAT_PREFIX + ABI Prefix + funcname
 1081                                 argprefix = config['abi_func_prefix']
 1082                                 funcalias = config['abi_func_prefix'] ..
 1083                                     funcname
 1084                                 goto ptrfound
 1085                         end
 1086                 end
 1087                 ::ptrfound::
 1088         end
 1089         if funcalias == nil or funcalias == "" then
 1090                 funcalias = funcname
 1091         end
 1092 
 1093         if argalias == nil and funcname ~= nil then
 1094                 argalias = argprefix .. funcname .. "_args"
 1095                 for _, v in pairs(compat_options) do
 1096                         local mask = v["mask"]
 1097                         if (flags & mask) ~= 0 then
 1098                                 -- Multiple aliases doesn't seem to make
 1099                                 -- sense.
 1100                                 argalias = v["prefix"] .. argalias
 1101                                 goto out
 1102                         end
 1103                 end
 1104                 ::out::
 1105         elseif argalias ~= nil then
 1106                 argalias = argprefix .. argalias
 1107         end
 1108 
 1109         local ncompatflags = get_mask({"STD", "NODEF", "NOARGS", "NOPROTO",
 1110             "NOSTD"})
 1111         local compatflags = get_mask_pat("COMPAT.*")
 1112         -- Now try compat...
 1113         if flags & compatflags ~= 0 then
 1114                 if flags & known_flags['STD'] ~= 0 then
 1115                         abort(1, "Incompatible COMPAT/STD: " .. line)
 1116                 end
 1117                 handle_compat(sysnum, thr_flag, flags, sysflags, rettype,
 1118                     auditev, funcname, funcalias, funcargs, argalias)
 1119         elseif flags & ncompatflags ~= 0 then
 1120                 handle_noncompat(sysnum, thr_flag, flags, sysflags, rettype,
 1121                     auditev, syscallret, funcname, funcalias, funcargs,
 1122                     argalias)
 1123         elseif flags & known_flags["OBSOL"] ~= 0 then
 1124                 handle_obsol(sysnum, funcname, funcomment)
 1125         elseif flags & known_flags["RESERVED"] ~= 0 then
 1126                 handle_reserved(sysnum, sysstart, sysend)
 1127         elseif flags & known_flags["UNIMPL"] ~= 0 then
 1128                 handle_unimpl(sysnum, sysstart, sysend, funcomment)
 1129         else
 1130                 abort(1, "Bad flags? " .. line)
 1131         end
 1132 
 1133         if sysend ~= nil then
 1134                 maxsyscall = sysend
 1135         elseif sysnum ~= nil then
 1136                 maxsyscall = sysnum
 1137         end
 1138 end
 1139 
 1140 -- Entry point
 1141 
 1142 if #arg < 1 or #arg > 2 then
 1143         error("usage: " .. arg[0] .. " input-file <config-file>")
 1144 end
 1145 
 1146 local sysfile, configfile = arg[1], arg[2]
 1147 
 1148 -- process_config either returns nil and a message, or a
 1149 -- table that we should merge into the global config
 1150 if configfile ~= nil then
 1151         local res = assert(process_config(configfile))
 1152 
 1153         for k, v in pairs(res) do
 1154                 if v ~= config[k] then
 1155                         config[k] = v
 1156                         config_modified[k] = true
 1157                 end
 1158         end
 1159 end
 1160 
 1161 -- We ignore errors here if we're relying on the default configuration.
 1162 if not config_modified["capenabled"] then
 1163         config["capenabled"] = grab_capenabled(config['capabilities_conf'],
 1164             config_modified["capabilities_conf"] == nil)
 1165 elseif config["capenabled"] ~= "" then
 1166         -- Due to limitations in the config format mostly, we'll have a comma
 1167         -- separated list.  Parse it into lines
 1168         local capenabled = {}
 1169         -- print("here: " .. config["capenabled"])
 1170         for sysc in config["capenabled"]:gmatch("([^,]+)") do
 1171                 capenabled[sysc] = true
 1172         end
 1173         config["capenabled"] = capenabled
 1174 end
 1175 process_compat()
 1176 process_abi_flags()
 1177 
 1178 if not lfs.mkdir(tmpspace) then
 1179         error("Failed to create tempdir " .. tmpspace)
 1180 end
 1181 
 1182 -- XXX Revisit the error handling here, we should probably move the rest of this
 1183 -- into a function that we pcall() so we can catch the errors and clean up
 1184 -- gracefully.
 1185 for _, v in ipairs(temp_files) do
 1186         local tmpname = tmpspace .. v
 1187         files[v] = io.open(tmpname, "w+")
 1188         -- XXX Revisit these with a pcall() + error handler
 1189         if not files[v] then
 1190                 abort(1, "Failed to open temp file: " .. tmpname)
 1191         end
 1192 end
 1193 
 1194 for _, v in ipairs(output_files) do
 1195         local tmpname = tmpspace .. v
 1196         files[v] = io.open(tmpname, "w+")
 1197         -- XXX Revisit these with a pcall() + error handler
 1198         if not files[v] then
 1199                 abort(1, "Failed to open temp output file: " .. tmpname)
 1200         end
 1201 end
 1202 
 1203 -- Write out all of the preamble bits
 1204 write_line("sysent", string.format([[
 1205 
 1206 /* The casts are bogus but will do for now. */
 1207 struct sysent %s[] = {
 1208 ]], config['switchname']))
 1209 
 1210 write_line("syssw", string.format([[/*
 1211  * System call switch table.
 1212  *
 1213  * DO NOT EDIT-- this file is automatically %s.
 1214  * $%s$
 1215  */
 1216 
 1217 ]], generated_tag, config['os_id_keyword']))
 1218 
 1219 write_line("sysarg", string.format([[/*
 1220  * System call prototypes.
 1221  *
 1222  * DO NOT EDIT-- this file is automatically %s.
 1223  * $%s$
 1224  */
 1225 
 1226 #ifndef %s
 1227 #define %s
 1228 
 1229 #include <sys/signal.h>
 1230 #include <sys/acl.h>
 1231 #include <sys/cpuset.h>
 1232 #include <sys/domainset.h>
 1233 #include <sys/_ffcounter.h>
 1234 #include <sys/_semaphore.h>
 1235 #include <sys/ucontext.h>
 1236 #include <sys/wait.h>
 1237 
 1238 #include <bsm/audit_kevents.h>
 1239 
 1240 struct proc;
 1241 
 1242 struct thread;
 1243 
 1244 #define PAD_(t) (sizeof(register_t) <= sizeof(t) ? \
 1245                 0 : sizeof(register_t) - sizeof(t))
 1246 
 1247 #if BYTE_ORDER == LITTLE_ENDIAN
 1248 #define PADL_(t)        0
 1249 #define PADR_(t)        PAD_(t)
 1250 #else
 1251 #define PADL_(t)        PAD_(t)
 1252 #define PADR_(t)        0
 1253 #endif
 1254 
 1255 ]], generated_tag, config['os_id_keyword'], config['sysproto_h'],
 1256     config['sysproto_h']))
 1257 for _, v in pairs(compat_options) do
 1258         write_line(v["tmp"], string.format("\n#ifdef %s\n\n", v["definition"]))
 1259 end
 1260 
 1261 write_line("sysnames", string.format([[/*
 1262  * System call names.
 1263  *
 1264  * DO NOT EDIT-- this file is automatically %s.
 1265  * $%s$
 1266  */
 1267 
 1268 const char *%s[] = {
 1269 ]], generated_tag, config['os_id_keyword'], config['namesname']))
 1270 
 1271 write_line("syshdr", string.format([[/*
 1272  * System call numbers.
 1273  *
 1274  * DO NOT EDIT-- this file is automatically %s.
 1275  * $%s$
 1276  */
 1277 
 1278 ]], generated_tag, config['os_id_keyword']))
 1279 
 1280 write_line("sysmk", string.format([[# FreeBSD system call object files.
 1281 # DO NOT EDIT-- this file is automatically %s.
 1282 # $%s$
 1283 MIASM = ]], generated_tag, config['os_id_keyword']))
 1284 
 1285 write_line("systrace", string.format([[/*
 1286  * System call argument to DTrace register array converstion.
 1287  *
 1288  * DO NOT EDIT-- this file is automatically %s.
 1289  * $%s$
 1290  * This file is part of the DTrace syscall provider.
 1291  */
 1292 
 1293 static void
 1294 systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
 1295 {
 1296         int64_t *iarg = (int64_t *)uarg;
 1297         switch (sysnum) {
 1298 ]], generated_tag, config['os_id_keyword']))
 1299 
 1300 write_line("systracetmp", [[static void
 1301 systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
 1302 {
 1303         const char *p = NULL;
 1304         switch (sysnum) {
 1305 ]])
 1306 
 1307 write_line("systraceret", [[static void
 1308 systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
 1309 {
 1310         const char *p = NULL;
 1311         switch (sysnum) {
 1312 ]])
 1313 
 1314 -- Processing the sysfile will parse out the preprocessor bits and put them into
 1315 -- the appropriate place.  Any syscall-looking lines get thrown into the sysfile
 1316 -- buffer, one per line, for later processing once they're all glued together.
 1317 process_sysfile(sysfile)
 1318 
 1319 write_line("sysinc",
 1320     "\n#define AS(name) (sizeof(struct name) / sizeof(register_t))\n")
 1321 
 1322 for _, v in pairs(compat_options) do
 1323         if v["count"] > 0 then
 1324                 write_line("sysinc", string.format([[
 1325 
 1326 #ifdef %s
 1327 #define %s(n, name) .sy_narg = n, .sy_call = (sy_call_t *)__CONCAT(%s, name)
 1328 #else
 1329 #define %s(n, name) .sy_narg = 0, .sy_call = (sy_call_t *)nosys
 1330 #endif
 1331 ]], v["definition"], v["flag"]:lower(), v["prefix"], v["flag"]:lower()))
 1332         end
 1333 
 1334         write_line(v["dcltmp"], string.format("\n#endif /* %s */\n\n",
 1335             v["definition"]))
 1336 end
 1337 
 1338 write_line("sysprotoend", string.format([[
 1339 
 1340 #undef PAD_
 1341 #undef PADL_
 1342 #undef PADR_
 1343 
 1344 #endif /* !%s */
 1345 ]], config["sysproto_h"]))
 1346 
 1347 write_line("sysmk", "\n")
 1348 write_line("sysent", "};\n")
 1349 write_line("sysnames", "};\n")
 1350 -- maxsyscall is the highest seen; MAXSYSCALL should be one higher
 1351 write_line("syshdr", string.format("#define\t%sMAXSYSCALL\t%d\n",
 1352     config["syscallprefix"], maxsyscall + 1))
 1353 write_line("systrace", [[
 1354         default:
 1355                 *n_args = 0;
 1356                 break;
 1357         };
 1358 }
 1359 ]])
 1360 
 1361 write_line("systracetmp", [[
 1362         default:
 1363                 break;
 1364         };
 1365         if (p != NULL)
 1366                 strlcpy(desc, p, descsz);
 1367 }
 1368 ]])
 1369 
 1370 write_line("systraceret", [[
 1371         default:
 1372                 break;
 1373         };
 1374         if (p != NULL)
 1375                 strlcpy(desc, p, descsz);
 1376 }
 1377 ]])
 1378 
 1379 -- Finish up; output
 1380 write_line("syssw", read_file("sysinc"))
 1381 write_line("syssw", read_file("sysent"))
 1382 
 1383 write_line("sysproto", read_file("sysarg"))
 1384 write_line("sysproto", read_file("sysdcl"))
 1385 for _, v in pairs(compat_options) do
 1386         write_line("sysproto", read_file(v["tmp"]))
 1387         write_line("sysproto", read_file(v["dcltmp"]))
 1388 end
 1389 write_line("sysproto", read_file("sysaue"))
 1390 write_line("sysproto", read_file("sysprotoend"))
 1391 
 1392 write_line("systrace", read_file("systracetmp"))
 1393 write_line("systrace", read_file("systraceret"))
 1394 
 1395 for _, v in ipairs(output_files) do
 1396         local target = config[v]
 1397         if target ~= "/dev/null" then
 1398                 local fh = assert(io.open(target, "w+"))
 1399                 if fh == nil then
 1400                         abort(1, "Failed to open '" .. target .. "'")
 1401                 end
 1402                 assert(fh:write(read_file(v)))
 1403                 assert(fh:close())
 1404         end
 1405 end
 1406 
 1407 cleanup()

Cache object: 70a299ed0f89e524ca9eb49493191719


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.