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/makeobjops.awk

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 #!/usr/bin/awk -f
    2 
    3 #-
    4 # Copyright (c) 1992, 1993
    5 #        The Regents of the University of California.  All rights reserved.
    6 #
    7 # Redistribution and use in source and binary forms, with or without
    8 # modification, are permitted provided that the following conditions
    9 # are met:
   10 # 1. Redistributions of source code must retain the above copyright
   11 #    notice, this list of conditions and the following disclaimer.
   12 # 2. Redistributions in binary form must reproduce the above copyright
   13 #    notice, this list of conditions and the following disclaimer in the
   14 #    documentation and/or other materials provided with the distribution.
   15 # 4. Neither the name of the University nor the names of its contributors
   16 #    may be used to endorse or promote products derived from this software
   17 #    without specific prior written permission.
   18 #
   19 # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   20 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22 # ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   23 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29 # SUCH DAMAGE.
   30 #
   31 # From @(#)vnode_if.sh        8.1 (Berkeley) 6/10/93
   32 # From @(#)makedevops.sh 1.1 1998/06/14 13:53:12 dfr Exp $
   33 # From @(#)makedevops.sh ?.? 1998/10/05
   34 # From src/sys/kern/makedevops.pl,v 1.12 1999/11/22 14:40:04 n_hibma Exp
   35 # From src/sys/kern/makeobjops.pl,v 1.8 2001/11/16 02:02:42 joe Exp
   36 #
   37 # $FreeBSD$
   38 
   39 #
   40 #   Script to produce kobj front-end sugar.
   41 #
   42 
   43 function usage ()
   44 {
   45         print "usage: makeobjops.awk <srcfile.m> [-d] [-p] [-l <nr>] [-c|-h]";
   46         print "where -c   produce only .c files";
   47         print "      -h   produce only .h files";
   48         print "      -p   use the path component in the source file for destination dir";
   49         print "      -l   set line width for output files [80]";
   50         print "      -d   switch on debugging";
   51         exit 1;
   52 }
   53 
   54 function warn (msg)
   55 {
   56         print "makeobjops.awk:", msg > "/dev/stderr";
   57 }
   58 
   59 function warnsrc (msg)
   60 {
   61         warn(src ":" lineno ": " msg);
   62 }
   63 
   64 function debug (msg)
   65 {
   66         if (opt_d)
   67                 warn(msg);
   68 }
   69 
   70 function die (msg)
   71 {
   72         warn(msg);
   73         exit 1;
   74 }
   75 
   76 #   These are just for convenience ...
   77 function printc(s) {if (opt_c) print s > ctmpfilename;}
   78 function printh(s) {if (opt_h) print s > htmpfilename;}
   79 
   80 #
   81 #   If a line exceeds maxlength, split it into multiple
   82 #   lines at commas.  Subsequent lines are indented by
   83 #   the specified number of spaces.
   84 #
   85 #   In other words:  Lines are split by replacing ", "
   86 #   by ",\n" plus indent spaces.
   87 #
   88 
   89 function format_line (line, maxlength, indent)
   90 {
   91         rline = "";
   92 
   93         while (length(line) > maxlength) {
   94                 #
   95                 #   Find the rightmost ", " so that the part
   96                 #   to the left of it is just within maxlength.
   97                 #   If there is none, give up and leave it as-is.
   98                 #
   99                 if (!match(substr(line, 1, maxlength + 1), /^.*, /))
  100                         break;
  101                 rline = rline substr(line, 1, RLENGTH - 1) "\n";
  102                 line = sprintf("%*s", indent, "") substr(line, RLENGTH + 1);
  103         }
  104         return rline line;
  105 }
  106 
  107 #
  108 #   Join an array into a string.
  109 #
  110 
  111 function join (separator, array, num)
  112 {
  113         _result = ""
  114         if (num) {
  115                 while (num > 1)
  116                         _result = separator array[num--] _result;
  117                 _result = array[1] _result;
  118         }
  119         return _result;
  120 }
  121 
  122 #
  123 #   Execute a system command and report if it failed.
  124 #
  125 
  126 function system_check (cmd)
  127 {
  128         if ((rc = system(cmd)))
  129                 warn(cmd " failed (" rc ")");
  130 }
  131 
  132 #
  133 #   Handle "INTERFACE" line.
  134 #
  135 
  136 function handle_interface ()
  137 {
  138         intname = $2;
  139         sub(/;$/, "", intname);
  140         if (intname !~ /^[a-z_][a-z0-9_]*$/) {
  141                 debug($0);
  142                 warnsrc("Invalid interface name '" intname "', use [a-z_][a-z0-9_]*");
  143                 error = 1;
  144                 return;
  145         }
  146         if (!/;[        ]*$/)
  147                 warnsrc("Semicolon missing at end of line, no problem");
  148 
  149         debug("Interface " intname);
  150 
  151         printh("#ifndef _" intname "_if_h_");
  152         printh("#define _" intname "_if_h_\n");
  153         printc("#include \"" intname "_if.h\"\n");
  154 }
  155 
  156 #
  157 # Pass doc comments through to the C file
  158 #
  159 function handle_doc ()
  160 {
  161         doc = ""
  162         while (!/\*\//) {
  163                 doc = doc $0 "\n";
  164                 getline < src;
  165                 lineno++;
  166         }
  167         doc = doc $0 "\n";
  168         return doc;
  169 }
  170 
  171 #
  172 #   Handle "CODE" and "HEADER" sections.
  173 #   Returns the code as-is.
  174 #
  175 
  176 function handle_code ()
  177 {
  178         code = "\n";
  179         getline < src;
  180         indent = $0;
  181         sub(/[^  ].*$/, "", indent);    # find the indent used
  182         while (!/^}/) {
  183                 sub("^" indent, "");    # remove the indent
  184                 code = code $0 "\n";
  185                 getline < src;
  186                 lineno++;;
  187         }
  188         return code;
  189 }
  190 
  191 #
  192 #   Handle "METHOD" and "STATICMETHOD" sections.
  193 #
  194 
  195 function handle_method (static, doc)
  196 {
  197         #
  198         #   Get the return type and function name and delete that from
  199         #   the line. What is left is the possibly first function argument
  200         #   if it is on the same line.
  201         #
  202         if (!intname) {
  203                 warnsrc("No interface name defined");
  204                 error = 1;
  205                 return;
  206         }
  207         sub(/^[^        ]+[     ]+/, "");
  208         ret = $0;
  209         sub(/[  ]*\{.*$/, "", ret);
  210         name = ret;
  211         sub(/^.*[       ]/, "", name);  # last element is name of method
  212         sub(/[  ]+[^    ]+$/, "", ret); # return type
  213         debug("Method: name=" name " return type=" ret);
  214 
  215         sub(/^[^\{]*\{[  ]*/, "");
  216 
  217         if (!name || !ret) {
  218                 debug($0);
  219                 warnsrc("Invalid method specification");
  220                 error = 1;
  221                 return;
  222         }
  223 
  224         if (name !~ /^[a-z_][a-z_0-9]*$/) {
  225                 warnsrc("Invalid method name '" name "', use [a-z_][a-z0-9_]*");
  226                 error = 1;
  227                 return;
  228         }
  229 
  230         if (methods[name]) {
  231                 warnsrc("Duplicate method name");
  232                 error = 1;
  233                 return;
  234         }
  235         methods[name] = name;
  236 
  237         line = $0;
  238         while (line !~ /\}/ && (getline < src) > 0) {
  239                 line = line " " $0;
  240                 lineno++
  241         }
  242 
  243         default = "";
  244         if (!match(line, /\};?/)) {
  245                 warnsrc("Premature end of file");
  246                 error = 1;
  247                 return;
  248         }
  249         extra = substr(line, RSTART + RLENGTH);
  250         if (extra ~ /[   ]*DEFAULT[     ]*[a-zA-Z_][a-zA-Z_0-9]*[       ]*;/) {
  251                 default = extra;
  252                 sub(/.*DEFAULT[  ]*/, "", default);
  253                 sub(/[;         ]+.*$/, "", default);
  254         }
  255         else if (extra && opt_d) {
  256                 #   Warn about garbage at end of line.
  257                 warnsrc("Ignored '" extra "'");
  258         }
  259         sub(/\};?.*$/, "", line);
  260 
  261         #
  262         #   Create a list of variables without the types prepended.
  263         #
  264         sub(/^[  ]+/, "", line);        # remove leading ...
  265         sub(/[  ]+$/, "", line);        # ... and trailing whitespace
  266         gsub(/[  ]+/, " ", line);       # remove double spaces
  267 
  268         num_arguments = split(line, arguments, / *; */) - 1;
  269         delete varnames;                # list of varnames
  270         num_varnames = 0;
  271         for (i = 1; i <= num_arguments; i++) {
  272                 if (!arguments[i])
  273                         continue;       # skip argument if argument is empty
  274                 num_ar = split(arguments[i], ar, /[*    ]+/);
  275                 if (num_ar < 2) {       # only 1 word in argument?
  276                         warnsrc("no type for '" arguments[i] "'");
  277                         error = 1;
  278                         return;
  279                 }
  280                 #   Last element is name of variable.
  281                 varnames[++num_varnames] = ar[num_ar];
  282         }
  283 
  284         argument_list = join(", ", arguments, num_arguments);
  285         varname_list = join(", ", varnames, num_varnames);
  286 
  287         if (opt_d) {
  288                 warn("Arguments: " argument_list);
  289                 warn("Varnames: " varname_list);
  290         }
  291 
  292         mname = intname "_" name;       # method name
  293         umname = toupper(mname);        # uppercase method name
  294 
  295         firstvar = varnames[1];
  296 
  297         if (default == "")
  298                 default = "kobj_error_method";
  299 
  300         # the method description 
  301         printh("/** @brief Unique descriptor for the " umname "() method */");
  302         printh("extern struct kobjop_desc " mname "_desc;");
  303         # the method typedef
  304         printh("/** @brief A function implementing the " umname "() method */");
  305         prototype = "typedef " ret " " mname "_t(";
  306         printh(format_line(prototype argument_list ");",
  307             line_width, length(prototype)));
  308 
  309         # Print out the method desc
  310         printc("struct kobj_method " mname "_method_default = {");
  311         printc("\t&" mname "_desc, (kobjop_t) " default);
  312         printc("};\n");
  313 
  314         printc("struct kobjop_desc " mname "_desc = {");
  315         printc("\t0, &" mname "_method_default");
  316         printc("};\n");
  317 
  318         # Print out the method itself
  319         printh(doc);
  320         if (0) {                # haven't chosen the format yet
  321                 printh("static __inline " ret " " umname "(" varname_list ")");
  322                 printh("\t" join(";\n\t", arguments, num_arguments) ";");
  323         }
  324         else {
  325                 prototype = "static __inline " ret " " umname "(";
  326                 printh(format_line(prototype argument_list ")",
  327                     line_width, length(prototype)));
  328         }
  329         printh("{");
  330         printh("\tkobjop_t _m;");
  331         if (!static)
  332                 firstvar = "((kobj_t)" firstvar ")";
  333         printh("\tKOBJOPLOOKUP(" firstvar "->ops," mname ");");
  334         retrn =  (ret != "void") ? "return " : "";
  335         printh("\t" retrn "((" mname "_t *) _m)(" varname_list ");");
  336         printh("}\n");
  337 }
  338 
  339 #
  340 #   Begin of the main program.
  341 #
  342 
  343 BEGIN {
  344 
  345 line_width = 80;
  346 gerror = 0;
  347 
  348 #
  349 #   Process the command line.
  350 #
  351 
  352 num_files = 0;
  353 
  354 for (i = 1; i < ARGC; i++) {
  355         if (ARGV[i] ~ /^-/) {
  356                 #
  357                 #   awk doesn't have getopt(), so we have to do it ourselves.
  358                 #   This is a bit clumsy, but it works.
  359                 #
  360                 for (j = 2; j <= length(ARGV[i]); j++) {
  361                         o = substr(ARGV[i], j, 1);
  362                         if      (o == "c")      opt_c = 1;
  363                         else if (o == "h")      opt_h = 1;
  364                         else if (o == "p")      opt_p = 1;
  365                         else if (o == "d")      opt_d = 1;
  366                         else if (o == "l") {
  367                                 if (length(ARGV[i]) > j) {
  368                                         opt_l = substr(ARGV[i], j + 1);
  369                                         break;
  370                                 }
  371                                 else {
  372                                         if (++i < ARGC)
  373                                                 opt_l = ARGV[i];
  374                                         else
  375                                                 usage();
  376                                 }
  377                         }
  378                         else
  379                                 usage();
  380                 }
  381         }
  382         else if (ARGV[i] ~ /\.m$/)
  383                 filenames[num_files++] = ARGV[i];
  384         else
  385                 usage();
  386 }
  387 
  388 if (!num_files || !(opt_c || opt_h))
  389         usage();
  390 
  391 if (opt_p)
  392         debug("Will produce files in original not in current directory");
  393 
  394 if (opt_l) {
  395         if (opt_l !~ /^[0-9]+$/ || opt_l < 1)
  396                 die("Invalid line width '" opt_l "'");
  397         line_width = opt_l;
  398         debug("Line width set to " line_width);
  399 }
  400 
  401 for (i = 0; i < num_files; i++)
  402         debug("Filename: " filenames[i]);
  403 
  404 for (file_i = 0; file_i < num_files; file_i++) {
  405         src = filenames[file_i];
  406         cfilename = hfilename = src;
  407         sub(/\.m$/, ".c", cfilename);
  408         sub(/\.m$/, ".h", hfilename);
  409         if (!opt_p) {
  410                 sub(/^.*\//, "", cfilename);
  411                 sub(/^.*\//, "", hfilename);
  412         }
  413 
  414         debug("Processing from " src " to " cfilename " / " hfilename);
  415 
  416         ctmpfilename = cfilename ".tmp";
  417         htmpfilename = hfilename ".tmp";
  418 
  419         common_head = \
  420             "/*\n" \
  421             " * This file is produced automatically.\n" \
  422             " * Do not modify anything in here by hand.\n" \
  423             " *\n" \
  424             " * Created from source file\n" \
  425             " *   " src "\n" \
  426             " * with\n" \
  427             " *   makeobjops.awk\n" \
  428             " *\n" \
  429             " * See the source file for legal information\n" \
  430             " */\n";
  431 
  432         printc(common_head "\n" \
  433             "#include <sys/param.h>\n" \
  434             "#include <sys/queue.h>\n" \
  435             "#include <sys/kernel.h>\n" \
  436             "#include <sys/kobj.h>");
  437 
  438         printh(common_head);
  439 
  440         delete methods;         # clear list of methods
  441         intname = "";
  442         lineno = 0;
  443         error = 0;              # to signal clean up and gerror setting
  444         lastdoc = "";
  445 
  446         while (!error && (getline < src) > 0) {
  447                 lineno++;
  448 
  449                 #
  450                 #   Take special notice of include directives.
  451                 #
  452                 if (/^#[        ]*include[      ]+["<][^">]+[">]/) {
  453                         incld = $0;
  454                         sub(/^#[        ]*include[      ]+/, "", incld);
  455                         debug("Included file: " incld);
  456                         printc("#include " incld);
  457                 }
  458 
  459                 sub(/#.*/, "");         # remove comments
  460                 sub(/^[  ]+/, "");      # remove leading ...
  461                 sub(/[  ]+$/, "");      # ... and trailing whitespace
  462 
  463                 if (/^$/) {             # skip empty lines
  464                 }
  465                 else if (/^\/\*\*/)
  466                         lastdoc = handle_doc();
  467                 else if (/^INTERFACE[   ]+[^    ;]*[    ]*;?[   ]*$/) {
  468                         printh(lastdoc);
  469                         lastdoc = "";
  470                         handle_interface();
  471                 } else if (/^CODE[      ]*{$/)
  472                         printc(handle_code());
  473                 else if (/^HEADER[       ]*{$/)
  474                         printh(handle_code());
  475                 else if (/^METHOD/) {
  476                         handle_method(0, lastdoc);
  477                         lastdoc = "";
  478                 } else if (/^STATICMETHOD/) {
  479                         handle_method(1, lastdoc);
  480                         lastdoc = "";
  481                 } else {
  482                         debug($0);
  483                         warnsrc("Invalid line encountered");
  484                         error = 1;
  485                 }
  486         }
  487 
  488         #
  489         #   Print the final '#endif' in the header file.
  490         #
  491         printh("#endif /* _" intname "_if_h_ */");
  492 
  493         close (ctmpfilename);
  494         close (htmpfilename);
  495 
  496         if (error) {
  497                 warn("Output skipped");
  498                 system_check("rm -f " ctmpfilename " " htmpfilename);
  499                 gerror = 1;
  500         }
  501         else {
  502                 if (opt_c)
  503                         system_check("mv -f " ctmpfilename " " cfilename);
  504                 if (opt_h)
  505                         system_check("mv -f " htmpfilename " " hfilename);
  506         }
  507 }
  508 
  509 exit gerror;
  510 
  511 }

Cache object: 2960c34c5c0fc7a4e112a7712797765e


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