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

Cache object: 44eed46fc018b9a6c533439178f7460a


[ 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.