Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/tools/build/v2/util/doc.jam @ 12

Last change on this file since 12 was 12, checked in by landauf, 17 years ago

added boost

File size: 28.2 KB
Line 
1# (C) Copyright Rene Rivera, 2002-2003.
2#
3# See accompanying license for terms and conditions of use.
4#
5
6# Documentation system, handles --help requests.
7# It defines rules that attach documentation to modules, rules, and variables.
8# Collects and generates documentation for the various parts of the build system.
9# The documentation is collected from comments integrated into the code.
10
11import modules ;
12import print ;
13import set ;
14import container ;
15import "class" ;
16import sequence ;
17
18# The type of output to generate.
19# "console" is formated text echoed to the console (the default);
20# "text" is formated text appended to the output file;
21# "html" is HTML output to the file.
22#
23help-output = console ;
24
25# The file to output documentation to when generating "text" or "html"
26# help. This is without extension as the extension is determined by the
27# type of output.
28#
29help-output-file = help ;
30
31# Whether to include local rules in help output.
32#
33.option.show-locals ?= ;
34
35# When showing documentation for a module, whether to also generate
36# automatically the detailed docs for each item in the module.
37#
38.option.detailed ?= ;
39
40# Generate debug output as the help is generated and modules
41# are parsed.
42#
43.option.debug ?= ;
44
45# Enable or disable a documentation option.
46#
47local rule set-option (
48    option # The option name.
49    : value ? # Enabled (non-empty), or disabled (empty)
50    )
51{
52    .option.$(option) = $(value) ;
53}
54
55# Set the type of output.
56#
57local rule set-output (
58    type
59    )
60{
61    help-output = $(type) ;
62}
63
64# Set the output to a file.
65#
66local rule set-output-file (
67    file
68    )
69{
70    help-output-file = $(file) ;
71}
72
73# Extracts the brief comment from a complete comment. The brief
74# comment is the first sentence.
75#
76local rule brief-comment (
77    docs * # The comment documentation.
78    )
79{
80    local d = $(docs:J=" ") ;
81    local p = [ MATCH ".*([.])$" : $(d) ] ;
82    if ! $(p) { d = $(d)"." ; }
83    d = $(d)" " ;
84    local m = [ MATCH "^([^.]+[.])(.*)" : $(d) ] ;
85    local brief = $(m[1]) ;
86    while $(m[2]) && [ MATCH "^([^ ])" : $(m[2]) ]
87    {
88        m = [ MATCH "^([^.]+[.])(.*)" : $(m[2]) ] ;
89        brief += $(m[1]) ;
90    }
91    return $(brief:J="") ;
92}
93
94# Specifies the documentation for the current module.
95#
96local rule set-module-doc (
97    module-name ? # The name of the module to document.
98    : docs * # The documentation for the module.
99    )
100{
101    module-name ?= * ;
102
103    $(module-name).brief = [ brief-comment $(docs) ] ;
104    $(module-name).docs = $(docs) ;
105
106    if ! $(module-name) in $(documented-modules)
107    {
108        documented-modules += $(module-name) ;
109    }
110}
111
112# Specifies the documentation for the current module.
113#
114local rule set-module-copyright (
115    module-name ? # The name of the module to document.
116    : copyright * # The copyright for the module.
117    )
118{
119    module-name ?= * ;
120
121    $(module-name).copy-brief = [ brief-comment $(copyright) ] ;
122    $(module-name).copy-docs = $(docs) ;
123
124    if ! $(module-name) in $(documented-modules)
125    {
126        documented-modules += $(module-name) ;
127    }
128}
129
130# Specifies the documentation for a rule in the current module.
131# If called in the global module, this documents a global rule.
132#
133local rule set-rule-doc (
134    name # The name of the rule.
135    module-name ? # The name of the module to document.
136    is-local ? # Whether the rule is local to the module.
137    : docs * # The documentation for the rule.
138    )
139{
140    module-name ?= * ;
141
142    $(module-name).$(name).brief = [ brief-comment $(docs) ] ;
143    $(module-name).$(name).docs = $(docs) ;
144    $(module-name).$(name).is-local = $(is-local) ;
145
146    if ! $(name) in $($(module-name).rules)
147    {
148        $(module-name).rules += $(name) ;
149    }
150}
151
152# Specify a class, will turn a rule into a class.
153#
154local rule set-class-doc (
155    name # The name of the class.
156    module-name ? # The name of the module to document.
157    : super-name ? # The super class name.
158    )
159{
160    module-name ?= * ;
161
162    $(module-name).$(name).is-class = true ;
163    $(module-name).$(name).super-name = $(super-name) ;
164    $(module-name).$(name).class-rules =
165        [ MATCH "^($(name)[.].*)" : $($(module-name).rules) ] ;
166    $(module-name).$($(module-name).$(name).class-rules).is-class-rule = true ;
167
168    $(module-name).classes += $(name) ;
169    $(module-name).class-rules += $($(module-name).$(name).class-rules) ;
170    $(module-name).rules =
171        [ set.difference $($(module-name).rules) :
172            $(name) $($(module-name).$(name).class-rules) ] ;
173}
174
175# Set the argument call signature of a rule.
176#
177local rule set-rule-arguments-signature (
178    name # The name of the rule.
179    module-name ? # The name of the module to document.
180    : signature * # The arguments signature.
181    )
182{
183    module-name ?= * ;
184
185    $(module-name).$(name).signature = $(signature) ;
186}
187
188# Specifies the documentation for an argument of a rule.
189#
190local rule set-argument-doc (
191    name # The name of the argument.
192    qualifier # Argument syntax qualifier, "*", "+", etc.
193    rule-name # The name of the rule.
194    module-name ? # THe optional name of the module.
195    : docs * # The documentation.
196    )
197{
198    module-name ?= * ;
199
200    $(module-name).$(rule-name).args.$(name).qualifier = $(qualifier) ;
201    $(module-name).$(rule-name).args.$(name).docs = $(docs) ;
202
203    if ! $(name) in $($(module-name).$(rule-name).args)
204    {
205        $(module-name).$(rule-name).args += $(name) ;
206    }
207}
208
209# Specifies the documentation for a variable in the current module.
210# If called in the global module, the global variable is documented.
211#
212local rule set-variable-doc (
213    name # The name of the variable.
214    default # The default value.
215    initial # The initial value.
216    module-name ? # The name of the module to document.
217    : docs * # The documentation for the variable.
218    )
219{
220    module-name ?= * ;
221
222    $(module-name).$(name).brief = [ brief-comment $(docs) ] ;
223    $(module-name).$(name).default = $(default) ;
224    $(module-name).$(name).initial = $(initial) ;
225    $(module-name).$(name).docs = $(docs) ;
226
227    if ! $(name) in $($(module-name).variables)
228    {
229        $(module-name).variables += $(name) ;
230    }
231}
232
233# Generates a general description of the documentation and help system.
234#
235local rule print-help-top ( )
236{
237    print.section "Available Help"
238        These are the available options for obtaining documentation.
239        Some options have additional instructions on how to get more
240        detailed information. Multiple options are allowed and
241        sometimes required. For example, the options that configure
242        the help system still require a regular help request option
243        for any output to be generated.
244        ;
245    print.list-start ;
246    print.list-item --help; This help message. ;
247    print.list-item --help-usage; How to invoke '"bjam".' ;
248    print.list-item --help-all; Brief information on available modules. ;
249    print.list-item --help <module-name>; Get information about a module. ;
250    print.list-item --help-options; Options for controlling the help display. ;
251    print.list-item --help-output <type>; The type of output to genetare.
252        '"console" is formated text echoed to the console (the default);'
253        '"text" is formated text appended to the output file;'
254        '"html" is HTML output to the file.' ;
255    print.list-item --help-output-file <file>; The file to output the documentation. ;
256    print.list-end ;
257}
258
259# Generate Jam/Boost.Jam command usage information.
260#
261local rule print-help-usage ( )
262{
263    print.section "Boost.Jam Usage"
264        "bjam [ options... ] targets..."
265        ;
266    print.list-start ;
267    print.list-item -a;
268        Build all targets, even if they are current. ;
269    print.list-item -fx;
270        Read '"x"' as the Jamfile for building instead of searching
271        for the Boost.Build system. ;
272    print.list-item -jx;
273        Run up to '"x"' commands concurrently. ;
274    print.list-item -n;
275        Do not execute build commands. Instead print out the commands
276        as they would be executed if building. ;
277    print.list-item -ox;
278        Write the build commands to the file '"x"'. ;
279    print.list-item -q;
280        Quit as soon as the build of a target fails. Specifying this prevents the
281        attempt of building as many targets as possible regardless of failures. ;
282    print.list-item -sx=y;
283        Sets a Jam variable '"x"' to the value '"y"', overriding any value that
284        variable would have from the environment. ;
285    print.list-item -tx;
286        Rebuild the target '"x"', even if it is up-to-date. ;
287    print.list-item -v;
288        Display the version of bjam. ;
289    print.list-item --x;
290        Option '"x"' is ignored but considered and option. The option is then
291        available from the '"ARGV"' variable. ;
292    print.list-item -dn;
293        Enables output of diagnostic messages. The debug level '"n"' and all
294        below it are enabled by this option. ;
295    print.list-item -d+n;
296        Enables output of diagnostic messages. Only the output for debug level '"n"'
297        is enabled. ;
298    print.list-end ;
299    print.section "Debug Levels"
300        Each debug level shows a different set of information. Usually with the higher
301        levels producing more verbose information. The following levels are supported:
302        ;
303    print.list-start ;
304    print.list-item 0;
305        Turn off all diagnostic output. Only errors are reported. ;
306    print.list-item 1;
307        Show the actions taken for building targets, as they are executed. ;
308    print.list-item 2;
309        Show "quiet" actions and display all action text, as they are executed. ;
310    print.list-item 3;
311        Show dependency analysis, and target/source timestamps/paths. ;
312    print.list-item 4;
313        Show arguments of shell invocations. ;
314    print.list-item 5;
315        Show rule invocations and variable expansions. ;
316    print.list-item 6;
317        Show directory/header file/archive scans, and attempts at binding to targets. ;
318    print.list-item 7;
319        Show variable settings. ;
320    print.list-item 8;
321        Show variable fetches, variable expansions, and evaluation of '"if"' expressions. ;
322    print.list-item 9;
323        Show variable manipulation, scanner tokens, and memory usage. ;
324    print.list-item 10;
325        Show execution times for rules. ;
326    print.list-item 11;
327        Show parsing progress of Jamfiles. ;
328    print.list-item 12;
329        Show graph for target dependencies. ;
330    print.list-item 13;
331        Show changes in target status (fate). ;
332    print.list-end ;
333}
334
335# Generates description of options controlling the help system.
336# This automatically reads the options as all variables in the doc
337# module of the form ".option.*".
338#
339local rule print-help-options (
340    module-name # The doc module.
341    )
342{
343    print.section "Help Options"
344        These are all the options available for enabling or disabling
345        to control the help system in various ways. Options can be enabled
346        or disabled with '"--help-enable-<option>"', and "'--help-disable-<option>'"
347        respectively.
348        ;
349    local options-to-list = [ MATCH ^[.]option[.](.*) : $($(module-name).variables) ] ;
350    if $(options-to-list)
351    {
352        print.list-start ;
353        for local option in [ sequence.insertion-sort $(options-to-list) ]
354        {
355            local def = disabled ;
356            if $($(module-name)..option.$(option).default) != "(empty)"
357            {
358                def = enabled ;
359            }
360            print.list-item $(option): $($(module-name)..option.$(option).docs)
361                Default is $(def). ;
362        }
363        print.list-end ;
364    }
365}
366
367# Generate brief documentation for all the known items in the section
368# for a module. Possible sections are: "rules", and "variables".
369#
370local rule print-help-module-section (
371    module # The module name.
372    section # rules or variables.
373    : section-head # The title of the section.
374    section-description * # The detailed description of the section.
375    )
376{
377    if $($(module).$(section))
378    {
379        print.section $(section-head) $(section-description) ;
380        print.list-start ;
381        for local item in [ sequence.insertion-sort $($(module).$(section)) ]
382        {
383            local show = ;
384            if ! $($(module).$(item).is-local)
385            {
386                show = yes ;
387            }
388            if $(.option.show-locals)
389            {
390                show = yes ;
391            }
392            if $(show)
393            {
394                print.list-item $(item): $($(module).$(item).brief) ;
395            }
396        }
397        print.list-end ;
398    }
399}
400
401# Generate documentation for possible modules. We attempt to list all known
402# modules, and a brief description of each.
403#
404local rule print-help-all (
405    ignored # Usually the module name, but is ignored here.
406    )
407{
408    print.section "Modules"
409        "These are all the known modules. Use --help <module> to get more"
410        "detailed information."
411        ;
412    if $(documented-modules)
413    {
414        print.list-start ;
415        for local module-name in [ sequence.insertion-sort $(documented-modules) ]
416        {
417            # The brief docs for each module.
418            print.list-item $(module-name): $($(module-name).brief) ;
419        }
420        print.list-end ;
421    }
422    # The documentation for each module when details are requested.
423    if $(documented-modules) && $(.option.detailed)
424    {
425        for local module-name in [ sequence.insertion-sort $(documented-modules) ]
426        {
427            # The brief docs for each module.
428            print-help-module $(module-name) ;
429        }
430    }
431}
432
433# Generate documentation for a module. Basic information about
434# the module is generated.
435#
436local rule print-help-module (
437    module-name # The module to generate docs for.
438    )
439{
440    # Print the docs.
441    print.section "Module '$(module-name)'" $($(module-name).docs) ;
442   
443    # Print out the documented classes.
444    print-help-module-section $(module-name) classes : "Module '$(module-name)' classes"
445        Use --help $(module-name).<class-name> to get more information. ;
446   
447    # Print out the documented rules.
448    print-help-module-section $(module-name) rules : "Module '$(module-name)' rules"
449        Use --help $(module-name).<rule-name> to get more information. ;
450   
451    # Print out the documented variables.
452    print-help-module-section $(module-name) variables : "Module '$(module-name)' variables"
453        Use --help $(module-name).<variable-name> to get more information. ;
454   
455    # Print out all the same information but indetailed form.
456    if $(.option.detailed)
457    {
458        print-help-classes $(module-name) ;
459        print-help-rules $(module-name) ;
460        print-help-variables $(module-name) ;
461    }
462}
463
464# Generate documentation for a set of rules in a module.
465#
466local rule print-help-rules (
467    module-name # Module of the rules.
468    : name * # Optional list of rules to describe.
469    )
470{
471    name ?= $($(module-name).rules) ;
472    if [ set.intersection $(name) : $($(module-name).rules) $($(module-name).class-rules) ]
473    {
474        # Print out the given rules.
475        for local rule-name in [ sequence.insertion-sort $(name) ]
476        {
477            if $(.option.show-locals) || ! $($(module-name).$(rule-name).is-local)
478            {
479                local signature = $($(module-name).$(rule-name).signature:J=" ") ;
480                signature ?= "" ;
481                print.section "Rule '$(module-name).$(rule-name) ( $(signature) )'"
482                    $($(module-name).$(rule-name).docs) ;
483                if $($(module-name).$(rule-name).args)
484                {
485                    print.list-start ;
486                    for local arg-name in $($(module-name).$(rule-name).args)
487                    {
488                        print.list-item $(arg-name): $($(module-name).$(rule-name).args.$(arg-name).docs) ;
489                    }
490                    print.list-end ;
491                }
492            }
493        }
494    }
495}
496
497# Generate documentation for a set of classes in a module.
498#
499local rule print-help-classes (
500    module-name # Module of the classes.
501    : name * # Optional list of classes to describe.
502    )
503{
504    name ?= $($(module-name).classes) ;
505    if [ set.intersection $(name) : $($(module-name).classes) ]
506    {
507        # Print out the given classes.
508        for local class-name in [ sequence.insertion-sort $(name) ]
509        {
510            if $(.option.show-locals) || ! $($(module-name).$(class-name).is-local)
511            {
512                local signature = $($(module-name).$(class-name).signature:J=" ") ;
513                signature ?= "" ;
514                print.section "Class '$(module-name).$(class-name) ( $(signature) )'"
515                    $($(module-name).$(class-name).docs)
516                   "Inherits from '"$($(module-name).$(class-name).super-name)"'." ;
517                if $($(module-name).$(class-name).args)
518                {
519                    print.list-start ;
520                    for local arg-name in $($(module-name).$(class-name).args)
521                    {
522                        print.list-item $(arg-name): $($(module-name).$(class-name).args.$(arg-name).docs) ;
523                    }
524                    print.list-end ;
525                }
526            }
527           
528            # Print out the documented rules of the class.
529            print-help-module-section $(module-name) $(class-name).class-rules : "Class '$(module-name).$(class-name)' rules"
530                Use --help $(module-name).<rule-name> to get more information. ;
531           
532            # Print out all the rules if details are requested.
533            if $(.option.detailed)
534            {
535                print-help-rules $(module-name) : $($(module-name).$(class-name).class-rules) ;
536            }
537        }
538    }
539}
540
541# Generate documentation for a set of variables in a module.
542#
543local rule print-help-variables (
544    module-name ? # Module of the variables.
545    : name * # Optional list of variables to describe.
546    )
547{
548    name ?= $($(module-name).variables) ;
549    if [ set.intersection $(name) : $($(module-name).variables) ]
550    {
551        # Print out the given variables.
552        for local variable-name in [ sequence.insertion-sort $(name) ]
553        {
554            print.section "Variable '$(module-name).$(variable-name)'" $($(module-name).$(variable-name).docs) ;
555            if $($(module-name).$(variable-name).default) ||
556                $($(module-name).$(variable-name).initial)
557            {
558                print.list-start ;
559                if $($(module-name).$(variable-name).default)
560                {
561                    print.list-item "default value:" '$($(module-name).$(variable-name).default:J=" ")' ;
562                }
563                if $($(module-name).$(variable-name).initial)
564                {
565                    print.list-item "initial value:" '$($(module-name).$(variable-name).initial:J=" ")' ;
566                }
567                print.list-end ;
568            }
569        }
570    }
571}
572
573local rule __test__
574{
575}
576
577ws = "   " ;
578
579# Extract the text from a block of comments.
580#
581local rule extract-comment (
582    var # The name of the variable to extract from.
583    )
584{
585    local comment = ;
586    local line = $($(var)[1]) ;
587    local l = [ MATCH "^[$(ws)]*(#)(.*)$" : $(line) ] ;
588    while $(l[1]) && $($(var))
589    {
590        if $(l[2]) { comment += [ MATCH "^[$(ws)](.*)$" : $(l[2]) ] ; }
591        else { comment += "" ; }
592        $(var) = $($(var)[2-]) ;
593        line = $($(var)[1]) ;
594        l = [ MATCH "^[$(ws)]*(#)(.*)$" : $(line) ] ;
595    }
596    return $(comment) ;
597}
598
599# Extract s single line of Jam syntax, ignoring any comments.
600#
601local rule extract-syntax (
602    var # The name of the variable to extract from.
603    )
604{
605    local syntax = ;
606    local line = $($(var)[1]) ;
607    while ! $(syntax) && ! [ MATCH "^[$(ws)]*(#)" : $(line) ] && $($(var))
608    {
609        local m = [ MATCH "^[$(ws)]*(.*)$" : $(line) ] ;
610        if $(m) && ! $(m) = ""
611        {
612            syntax = $(m) ;
613        }
614        $(var) = $($(var)[2-]) ;
615        line = $($(var)[1]) ;
616    }
617    return $(syntax) ;
618}
619
620# Extract the next token, this is either a single Jam construct
621# or a comment as a single token.
622#
623local rule extract-token (
624    var # The name of the variable to extract from.
625    )
626{
627    local parts = ;
628    while ! $(parts)
629    {
630        parts = [ MATCH "^[$(ws)]*([^$(ws)]+)[$(ws)]*(.*)" : $($(var)[1]) ] ;
631        if ! $(parts)
632        {
633            $(var) = $($(var)[2-]) ;
634        }
635    }
636    local token = ;
637    if [ MATCH "^(#)" : $(parts[1]) ]
638    {
639        token = $(parts:J=" ") ;
640        $(var) = $($(var)[2-]) ;
641    }
642    else
643    {
644        token = $(parts[1]) ;
645        $(var) = $(parts[2-]:J=" ") $($(var)[2-]) ;
646    }
647    return $(token) ;
648}
649
650# Scan for a rule declaration as the next item in the variable.
651#
652local rule scan-rule (
653    syntax ? # The first part of the text which contains the rule declaration.
654    : var # The name of the variable to extract from.
655    )
656{
657    local rule-parts =
658        [ MATCH "^[$(ws)]*(rule|local[$(ws)]*rule)[$(ws)]+([^$(ws)]+)[$(ws)]*(.*)" : $(syntax:J=" ") ] ;
659    if $(rule-parts[1])
660    {
661        # mark as doc for rule.
662        local rule-name = $(rule-parts[2]) ;
663        if $(scope-name)
664        {
665            rule-name = $(scope-name).$(rule-name) ;
666        }
667        local is-local = [ MATCH "^(local).*" : $(rule-parts[1]) ] ;
668        if $(comment-block)
669        {
670            set-rule-doc $(rule-name) $(module-name) $(is-local) : $(comment-block) ;
671        }
672        # parse args of rule.
673        $(var) = $(rule-parts[3-]) $($(var)) ;
674        set-rule-arguments-signature $(rule-name) $(module-name) : [ scan-rule-arguments $(var) ] ;
675        # scan within this rules scope.
676        local scope-level = [ extract-token $(var) ] ;
677        local scope-name = $(rule-name) ;
678        while $(scope-level)
679        {
680            local comment-block = [ extract-comment $(var) ] ;
681            local syntax-block = [ extract-syntax $(var) ] ;
682            if [ scan-rule $(syntax-block) : $(var) ]
683            {
684            }
685            else if [ MATCH "^(\\{)" : $(syntax-block) ]
686            {
687                scope-level += "{" ;
688            }
689            else if [ MATCH "^[^\\}]*([\\}])[$(ws)]*$"  : $(syntax-block) ]
690            {
691                scope-level = $(scope-level[2-]) ;
692            }
693        }
694       
695        return true ;
696    }
697}
698
699# Scan the arguments of a rule.
700#
701local rule scan-rule-arguments (
702    var # The name of the variable to extract from.
703    )
704{
705    local arg-syntax = ;
706    local token = [ extract-token $(var) ] ;
707    while $(token) != "(" && $(token) != "{"
708    {
709        token = [ extract-token $(var) ] ;
710    }
711    if $(token) != "{"
712    {
713        token = [ extract-token $(var) ] ;
714    }
715    local arg-signature = ;
716    while $(token) != ")" && $(token) != "{"
717    {
718        local arg-name = ;
719        local arg-qualifier = " " ;
720        local arg-doc = ;
721        if $(token) = ":"
722        {
723            arg-signature += $(token) ;
724            token = [ extract-token $(var) ] ;
725        }
726        arg-name = $(token) ;
727        arg-signature += $(token) ;
728        token = [ extract-token $(var) ] ;
729        if [ MATCH "^([\\*\\+\\?])" : $(token) ]
730        {
731            arg-qualifier = $(token) ;
732            arg-signature += $(token) ;
733            token = [ extract-token $(var) ] ;
734        }
735        if $(token) = ":"
736        {
737            arg-signature += $(token) ;
738            token = [ extract-token $(var) ] ;
739        }
740        if [ MATCH "^(#)" : $(token) ]
741        {
742            $(var) = $(token) $($(var)) ;
743            arg-doc = [ extract-comment $(var) ] ;
744            token = [ extract-token $(var) ] ;
745        }
746        set-argument-doc $(arg-name) $(arg-qualifier) $(rule-name) $(module-name) : $(arg-doc) ;
747    }
748    while $(token) != "{"
749    {
750        token = [ extract-token $(var) ] ;
751    }
752    $(var) = "{" $($(var)) ;
753    arg-signature ?= "" ;
754    return $(arg-signature) ;
755}
756
757# Scan for a variable declaration.
758local rule scan-variable (
759    syntax ? # The first part of the text which contains the variable declaration.
760    : var # The name of the variable to extract from.
761    )
762{
763    # [1] = name, [2] = value(s)
764    local var-parts =
765        [ MATCH "^[$(ws)]*([^$(ws)]+)[$(ws)]+([\\?\\=]*)[$(ws)]+([^\\;]*)\\;" : $(syntax) ] ;
766    if $(var-parts)
767    {
768        local value = [ MATCH "^(.*)[ ]$" : $(var-parts[3-]:J=" ") ] ;
769        local default-value = "" ;
770        local initial-valie = "" ;
771        if $(var-parts[2]) = "?="
772        {
773            default-value = $(value) ;
774            default-value ?= "(empty)" ;
775        }
776        else
777        {
778            initial-value = $(value) ;
779            initial-value ?= "(empty)" ;
780        }
781        if $(comment-block)
782        {
783            set-variable-doc $(var-parts[1]) $(default-value) $(initial-value) $(module-name) : $(comment-block) ;
784        }
785        return true ;
786    }
787}
788
789# Scan a class declaration.
790local rule scan-class (
791    syntax ? # The syntax text for the class declaration.
792    )
793{
794    # [1] = class?, [2] = name, [3] = superclass
795    local class-parts =
796        [ MATCH "^[$(ws)]*([^$(ws)]+)[$(ws)]+([^$(ws)]+)[$(ws)]+:*[$(ws)]*([^$(ws);]*)" : $(syntax) ] ;
797    if $(class-parts[1]) = "class" || $(class-parts[1]) = "class.class"
798    {
799        set-class-doc $(class-parts[2]) $(module-name) : $(class-parts[3]) ;
800    }
801}
802
803# Scan a module file for documentation comments. This also
804# invokes any actions assigned to the module. The actions
805# are the rules that do the actual output of the documentation.
806# This rue is invoked as the header scan rule for the module file.
807#
808rule scan-module (
809    target # The module file.
810    : text * # The text in the file, one item per line.
811    : binding
812    )
813{   
814    if $(.option.debug) { ECHO "HELP:" scanning module target '$(target)' ; }
815    local module-name = $(.module<$(target)>.name) ;
816    local module-documented = ;
817    local comment-block = ;
818    local syntax-block = ;
819    # This is a hack because we can't get the line of a file if it
820    # happens to not have a new-line termination.
821    text += "}" ;
822    while $(text)
823    {
824        comment-block = [ extract-comment text ] ;
825        syntax-block = [ extract-syntax text ] ;
826        if $(.option.debug)
827        {
828            ECHO "HELP:" comment block; '$(comment-block)' ;
829            ECHO "HELP:" syntax block; '$(syntax-block)' ;
830        }
831        if [ scan-rule $(syntax-block) : text ] { }
832        else if [ scan-variable $(syntax-block) : text ] { }
833        else if [ scan-class $(syntax-block) ] { }
834        else if [ MATCH .*([cC]opyright).* : $(comment-block:J=" ") ]
835        {
836            # mark as the copy for the module.
837            set-module-copyright $(module-name) : $(comment-block) ;
838        }
839        else if ! $(module-documented)
840        {
841            # document the module.
842            set-module-doc $(module-name) : $(comment-block) ;
843            module-documented = true ;
844        }
845    }
846    for local action in $(.module<$(target)>.actions)
847    {
848        local action-rule = [ $(action).front ] ; $(action).pop-front ;
849        local action-args = [ $(action).get ] ;
850        local ignored = [ $(action-rule) $(module-name) : $(action-args) ] ;
851    }
852}
853
854# Import scan-module to global scope, so that it's available during
855# header scanning phase.
856IMPORT $(__name__) : scan-module : : doc.scan-module ;
857
858
859# Add a scan action to perform to generate the help documentation.
860# The action rule is passed the name of the module as the first argument.
861# The second argument(s) are optional and passed directly as specified
862# here.
863#
864local rule do-scan (
865    modules + # The modules to scan and perform the action on.
866    : action * # The action rule, plus the secondary arguments to pass to the action rule.
867    )
868{
869    local targets = ;
870    for local module-file in $(modules)
871    {
872        local module-name = $(module-file:B) ;
873        .module<$(module-file)>.name = $(module-name) ;
874        if $(action)
875        {
876            .module<$(module-file)>.actions += [ class.new vector $(action) ] ;
877        }
878        HDRSCAN on $(module-file) = "^(.*).$" ;
879        HDRRULE on $(module-file) = doc.scan-module ;
880        NOTFILE $(module-name).scan ;
881        ALWAYS $(module-name).scan ;
882        INCLUDES $(module-name).scan : $(module-file) ;
883        targets += $(module-name).scan ;
884    }
885    if $(help-output) = console
886    {
887        DEPENDS all : $(targets) ;
888    }
889    if $(help-output) = text
890    {
891        print.output $(help-output-file).txt plain ;
892        ALWAYS $(help-output-file).txt ;
893        DEPENDS $(help-output-file).txt : $(targets) ;
894        DEPENDS all : $(help-output-file).txt ;
895    }
896    if $(help-output) = html
897    {
898        print.output $(help-output-file).html html ;
899        ALWAYS $(help-output-file).html ;
900        DEPENDS $(help-output-file).html : $(targets) ;
901        DEPENDS all : $(help-output-file).html ;
902    }
903}
Note: See TracBrowser for help on using the repository browser.