~ubuntu-branches/ubuntu/karmic/gnustep-base/karmic

« back to all changes in this revision

Viewing changes to Tools/autogsdoc.m

  • Committer: Bazaar Package Importer
  • Author(s): Eric Heintzmann
  • Date: 2005-04-17 00:14:38 UTC
  • mfrom: (1.2.1 upstream) (2.1.2 hoary)
  • Revision ID: james.westby@ubuntu.com-20050417001438-enf0y07c9tku85z1
Tags: 1.10.3-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/** This tool produces gsdoc files from source files.
 
1
/** This tool produces GSDoc files from source files.
2
2
 
3
3
   <title>Autogsdoc ... a tool to make documentation from source code</title>
4
4
   Copyright (C) 2001 Free Software Foundation, Inc.
20
20
 
21
21
<chapter>
22
22
  <heading>The autogsdoc tool</heading>
23
 
  <p>
24
 
    The autogsdoc tool is a command-line utility for parsing ObjectiveC
25
 
    source code (header files and optionally source files) in order to
26
 
    generate documentation covering the public interface of the various
27
 
    classes, categories, and protocols in the source.
28
 
  </p>
29
 
  <p>
30
 
    The simple way to use this is to run the command with one or more
31
 
    header file names as arguments ... the tool will automatically
32
 
    parse corresponding source files in the same directory (or the
33
 
    directory specified using the DocumentationDirectory default),
34
 
    and produce gsdoc files as output.<br />
35
 
  </p>
36
 
  <p>
37
 
    Even without any human assistance, this tool will produce skeleton
38
 
    documents listing the methods in the classes found in the source
39
 
    files, but more importantly it can take specially formatted comments
40
 
    from the source files and insert those comments into the gsdoc output.
41
 
  </p>
42
 
  <p>
43
 
    Any comment beginning with slash and <em>two</em> asterisks rather than
44
 
    the common slash and single asterisk, is taken to be gsdoc markup, to
45
 
    be use as the description of the class or method following it.  This
46
 
    comment text is reformatted and then inserted into the output.
47
 
  </p>
48
 
  <p>
49
 
    There are some cases where special extra processing is performed,
50
 
    predominantly in the first comment found in the source file,
51
 
    from which various chunks of gsdoc markup may be extracted and
52
 
    placed into appropriate locations in the output document -
53
 
  </p>
54
 
  <list>
55
 
    <item><strong>AutogsdocSource</strong>
56
 
      In any line where <code>AutogsdocSource</code>: is found, the remainder
57
 
      of the line is taken as a source file name to be used instead of
58
 
      making the assumption that each .h file processed uses a .m file
59
 
      of the same name.  You may supply multiple <code>AutogsdocSource</code>:
60
 
      lines where a header file declares items which are defined in
61
 
      multiple source files.
62
 
    </item>
63
 
    <item><strong>&lt;abstract&gt;</strong>
64
 
      An abstract of the content of the document ... placed in the head
65
 
      of the gsdoc output.
66
 
    </item>
67
 
    <item><strong>&lt;author&gt;</strong>
68
 
      A description of the author of the code - may be repeated to handle
69
 
      the case where a document has multiple authors.  Placed in the
70
 
      head of the gsdoc output.<br />
71
 
      As an aid to readability of the source, some special additional
72
 
      processing is performed related to the document author -<br />
73
 
      Any line of the form '<code>Author</code>: name &lt;email-address&gt;',
74
 
      or '<code>By</code>: name &lt;email-address&gt;',
75
 
      or '<code>Author</code>: name' or '<code>By</code>: name'
76
 
      will be recognised and converted to an <em>author</em> element,
77
 
      possibly containing an <em>email</em> element.
78
 
    </item>
79
 
    <item><strong>&lt;back&gt;</strong>
80
 
      Placed in the gsdoc output just before the end of the body of the
81
 
      document - intended to be used for appendices, index etc.
82
 
    </item>
83
 
    <item><strong>&lt;chapter&gt;</strong>
84
 
      Placed immediately before any generated class documentation ...
85
 
      intended to be used to provide overall description of how the
86
 
      code being documented works.<br />
87
 
    </item>
88
 
    <item><strong>&lt;copy&gt;</strong>
89
 
      Copyright of the content of the document ... placed in the head
90
 
      of the gsdoc output.<br />
91
 
      As an aid to readability of the source, some special additional
92
 
      processing is performed -<br />
93
 
      Any line of the form 'Copyright (C) text' will be recognised and
94
 
      converted to a <em>copy</em> element.
95
 
    </item>
96
 
    <item><strong>&lt;date&gt;</strong>
97
 
      Date of the revision of the document ... placed in the head
98
 
      of the gsdoc output.  If this is omitted the tool will try to
99
 
      construct a value from the RCS Date tag (if available).
100
 
    </item>
101
 
    <item><strong>&lt;front&gt;</strong>
102
 
      Inserted into the document at the start of the body ... intended
103
 
      to provide for introduction or contents pages etc.
104
 
    </item>
105
 
    <item><strong>&lt;title&gt;</strong>
106
 
      Title of the document ... placed in the head of the gsdoc output.
107
 
      If this is omitted the tool will generate a (probably poor)
108
 
      title of its own.
109
 
    </item>
110
 
    <item>
111
 
      <strong>NB</strong>This markup may be used within
112
 
      class, category, or protocol documentation ... if so, it is
113
 
      extracted and wrapped round the rest of the documentation for
114
 
      the class as the classes chapter.
115
 
      The rest of the class documentation is normally
116
 
      inserted at the end of the chapter, but may instead be sbstituted
117
 
      in in place of the &lt;unit /&gt; pseudo-element within the
118
 
      &lt;chapter&gt; element.
119
 
    </item>
120
 
    <item><strong>&lt;version&gt;</strong>
121
 
      Version identifier of the document ... placed in the head
122
 
      of the gsdoc output.  If this is omitted the tool will try to
123
 
      construct a value from the RCS Revision tag (if available).
124
 
    </item>
125
 
  </list>
126
 
  <p>
127
 
    In comments being used to provide text for a method description, the
128
 
    following markup is removed from the text and handled specially -
129
 
  </p>
130
 
  <list>
131
 
    <item><strong>&lt;init /&gt;</strong>
132
 
      The method is marked as being the designated initialiser for the class.
133
 
    </item>
134
 
    <item><strong>&lt;override-subclass /&gt;</strong>
135
 
      The method is marked as being one which subclasses must override
136
 
      (eg an abstract method).
137
 
    </item>
138
 
    <item><strong>&lt;override-never /&gt;</strong>
139
 
      The method is marked as being one which subclasses should <em>NOT</em>
140
 
      override.
141
 
    </item>
142
 
    <item><strong>&lt;standards&gt; ... &lt;/standards&gt;</strong>
143
 
      The markup is removed from the description and placed <em>after</em>
144
 
      it in the gsdoc output - so that the method is described as
145
 
      conforming (or not conforming) to the specified standards.
146
 
    </item>
147
 
  </list>
148
 
  <p>
149
 
    Generally, the text in comments is reformatted to standardise and
150
 
    indent it nicely ... the reformatting is <em>not</em> performed on
151
 
    any text inside an &lt;example&gt; element.<br />
152
 
    When the text is reformatted, it is broken into whitespace separated
153
 
    'words' which are then subjected to some extra processing ...
154
 
  </p>
155
 
  <list>
156
 
    <item>Certain well known constants such as YES, NO, and nil are
157
 
      enclosed in &lt;code&gt; ... &lt;/code&gt; markup.
158
 
    </item>
159
 
    <item>The names of method arguments within method descriptions are
160
 
      enclosed in &lt;var&gt; ... &lt;/var&gt; markup.
161
 
    </item>
162
 
    <item>Method names (beginning with a plus or minus) are enclosed
163
 
      in &lt;ref...&gt; ... &lt;/ref&gt; markup.<br />
164
 
      eg. "-init" (without the quotes) would be wrapped in a gsdoc
165
 
      reference element to point to the init method of the current
166
 
      class or, if only one known class had an init method, it
167
 
      would refer to the method of that class.
168
 
      <br />Note the fact that the method name must be surrounded by
169
 
      whitespace (though a comma, fullstop, or semicolon at the end
170
 
      of the specifier will also act as a whitespace terminator).
171
 
    </item>
172
 
    <item>Method specifiers including class names (beginning and ending with
173
 
      square brackets) are enclosed in &lt;ref...&gt; ... &lt;/ref&gt; markup.
174
 
      <br />eg. [ NSObject-init],
175
 
      will create a reference to the init method of NSObject, while
176
 
      <br />[ (NSCopying)-copyWithZone:], creates a
177
 
      reference to a method in the NSCopyIng protocol.
178
 
      <br />Note that no spaces must appear between the square brackets
179
 
      in these specifiers.
180
 
      <br />Protocol namnes are enclosed in round brackets rather than
181
 
      the customary angle brackets, because gsdoc is an XML language, and
182
 
      XML treats angle brackets specially.
183
 
    </item>
184
 
  </list>
185
 
  <p>
186
 
    The tools accepts certain user defaults (which can of course be
187
 
    supplied as command-line arguments as usual) -
188
 
  </p>
189
 
  <list>
190
 
    <item><strong>Declared</strong>
191
 
      Specify where headers are to be documented as being found.<br />
192
 
      The actual name produced in the documentation is formed by appending
193
 
      the last component of the header file name to the value of this
194
 
      default.<br />
195
 
      If this default is not specified, the full name of the header file
196
 
      (as supplied on the command line), with the HeaderDirectory
197
 
      default prepended, is used.<br />
198
 
      A typical usage of this might be <code>-Declared Foundation</code>
199
 
      when generating documentation for the GNUstep base library.  This
200
 
      would result in the documentation saying that NSString is declared
201
 
      in <code>Foundation/NSString.h</code>
202
 
    </item>
203
 
    <item><strong>DocumentAllInstanceVariables</strong>
204
 
      This flag permits you to generate documentation for all instance
205
 
      variables.  Normally, only those explicitly declared 'public' or
206
 
      'protected' will be documented.
207
 
    </item>
208
 
    <item><strong>DocumentationDirectory</strong>
209
 
      May be used to specify the directory in which generated
210
 
      documentation is to be placed.  If this is not set, output
211
 
      is placed in the current directory.
212
 
    </item>
213
 
    <item><strong>GenerateHtml</strong>
214
 
      May be used to specify if HTML output is to be generated.
215
 
      Defaults to YES.
216
 
    </item>
217
 
    <item><strong>HeaderDirectory</strong>
218
 
      May be used to specify the directory to be searched for header files.
219
 
      If this is not specified, headers are looked for relative to the
220
 
      current directory or using absolute path names if given.
221
 
    </item>
222
 
    <item><strong>IgnoreDependencies</strong>
223
 
      A boolean value which may be used to specify that the program should
224
 
      ignore file modification times and regenerate files anyway.  Provided
225
 
      for use in conjunction with the <code>make</code> system, which is
226
 
      expected to manage dependency checking itsself.
227
 
    </item>
228
 
    <item><strong>LocalProjects</strong>
229
 
      This value is used to control the automatic inclusion of local
230
 
      external projects into the indexing system for generation of
231
 
      cross-references in final document output.<br />
232
 
      If set to 'None', then no local project references are done,
233
 
      otherwise, the 'Local' GNUstep documentation directory is recursively
234
 
      searched for files with a <code>.igsdoc</code> extension, and the
235
 
      indexing information from those files is used.<br />
236
 
      The value of this string is also used to generate the filenames in
237
 
      the cross reference ... if it is an empty string, the path to use
238
 
      is assumed to be a file in the same directory where the igsdoc
239
 
      file was found, otherwise it is used as a prefix to the name in
240
 
      the index.
241
 
    </item>
242
 
    <item><strong>Project</strong>
243
 
      May be used to specify the name of this project ... determines the
244
 
      name of the index reference file produced as part of the documentation
245
 
      to provide information enabling other projects to cross-reference to
246
 
      items in this project.
247
 
    </item>
248
 
    <item><strong>Projects</strong>
249
 
      This value may be supplied as a dictionary containing the paths to
250
 
      the igsdoc index/reference files used by external projects, along
251
 
      with values to be used to map the filenames found in the indexes.<br />
252
 
      For example, if a project index (igsdoc) file says that the class
253
 
      <code>Foo</code> is found in the file <code>Foo</code>, and the
254
 
      path associated with that project index is <code>/usr/doc/proj</code>,
255
 
      Then generated html output may reference the class as being in
256
 
      <code>/usr/doc/prj/Foo.html</code>
257
 
    </item>
258
 
    <item><strong>ShowDependencies</strong>
259
 
      A boolean value which may be used to specify that the program should
260
 
      log which files are being regenerated because of their dependencies
261
 
      on other files.
262
 
    </item>
263
 
    <item><strong>Standards</strong>
264
 
      A boolean value used to specify whether the program should insert
265
 
      information about standards complience into ythe documentation.
266
 
      This should only be used when documenting the GNUstep libraries
267
 
      and tools themselves as it assumes that the code being documented
268
 
      is part of GNUstep and possibly complies with the OpenStep standard
269
 
      or implements MacOS-X compatible methods.
270
 
    </item>
271
 
    <item><strong>SystemProjects</strong>
272
 
      This value is used to control the automatic inclusion of system
273
 
      external projects into the indexing system for generation of
274
 
      cross-references in final document output.<br />
275
 
      If set to 'None', then no system project references are done,
276
 
      otherwise, the 'System' GNUstep documentation directory is recursively
277
 
      searched for files with a <code>.igsdoc</code> extension, and the
278
 
      indexing information from those files is used.<br />
279
 
      The value of this string is also used to generate the filenames in
280
 
      the cross reference ... if it is an empty string, the path to use
281
 
      is assumed to be a file in the same directory where the igsdoc
282
 
      file was found, otherwise it is used as a prefix to the name in
283
 
      the index.
284
 
    </item>
285
 
    <item><strong>Up</strong>
286
 
      A string used to supply the name to be used in the 'up' link from
287
 
      generated gsdoc documents.  This should normally be the name of a
288
 
      file which contains an index of the contents of a project.<br />
289
 
      If this is missing or set to an empty string, then no 'up' link
290
 
      will be provided in the documents.
291
 
    </item>
292
 
    <item><strong>WordMap</strong>
293
 
      This value is a dictionary used to map identifiers/keywords found
294
 
      in the source files  to other words.  Generally you will not have
295
 
      to use this, but it is sometimes helpful to avoid the parser being
296
 
      confused by the use of C preprocessor macros.  You can effectively
297
 
      redefine the macro to something less confusing.
298
 
    </item>
299
 
  </list>
 
23
  <section>
 
24
    <heading>Overview</heading>
 
25
    <p>
 
26
      The autogsdoc tool is a command-line utility that helps developers
 
27
      produce reference documentation for GNUstep APIs.  It also enables
 
28
      developers to write and maintain other documentation in XML and have it
 
29
      converted to HTML.  In detail, autogsdoc will:
 
30
    </p>
 
31
    <list>
 
32
      <item>
 
33
        Extract special comments describing the public interfaces of classes,
 
34
        categories, protocols, functions, and macros from Objective C source
 
35
        code (header files and optionally source files) into GSDoc XML files.
 
36
        (Note that since C is a subset of Objective C, this tool can operate
 
37
        to document functions and other C structures in plain C source.)
 
38
      </item>
 
39
      <item>
 
40
        Convert GSDoc XML files, whether generated from source code or written
 
41
        manually by developers, into HTML.
 
42
      </item>
 
43
      <item>
 
44
        Construct indices based on GSDoc XML file sets, and convert those
 
45
        to HTML as well.
 
46
      </item>
 
47
    </list>
 
48
    <p>
 
49
      synopsis: <code>autogsdoc (options) (files)</code><br/>
 
50
        &#160;&#160;&#160;&#160;(options) described below<br/>
 
51
        &#160;&#160;&#160;&#160;(files) <code>.h</code>, <code>.m</code>, <code>.gsdoc</code>, and/or <code>.html</code> files, in any order.
 
52
    </p>
 
53
    <p>
 
54
      The most common usage this is to run the command with one or more
 
55
      header file names as arguments ... the tool will automatically
 
56
      parse corresponding source files in the same directory as the
 
57
      headers (or the current directory, or the directory specified
 
58
      using the DocumentationDirectory default), and produce GSDoc
 
59
      and HTML files as output.  For best results this mode should be
 
60
      run from the directory containing the source files.
 
61
    </p>
 
62
    <p>
 
63
      GSDoc files may also be given directly in addition or by themselves, and
 
64
      will be converted to HTML.  See the
 
65
      <uref url="gsdoc.html">GSDoc reference</uref> for information
 
66
      on the GSDoc format.
 
67
    </p>
 
68
    <p>
 
69
      Finally, HTML files may be given on the command line.  Cross-references
 
70
      to other parts of code documentation found within them will be rewritten
 
71
      based on what is found in the project currently.
 
72
    </p>
 
73
  </section>
 
74
  <section>
 
75
    <heading>Source Code Markup</heading>
 
76
    <p>
 
77
      The source code parser will automatically produce GSDoc documents
 
78
      listing the methods in the classes found in the source files, and it
 
79
      will include text from specially formatted comments from the source
 
80
      files.
 
81
    </p>
 
82
    <p>
 
83
      Any comment beginning with slash and <em>two</em> asterisks rather than
 
84
      the common slash and single asterisk, is taken to be GSDoc markup, to
 
85
      be use as the description of the class or method following it.  This
 
86
      comment text is reformatted and then inserted into the output.<br />
 
87
      Where multiple comments are associated with the same item, they are
 
88
      joined together with a line break (&lt;br /&gt;) between each if
 
89
      necessary.
 
90
    </p>
 
91
    <p>
 
92
      The tool can easily be used to document programs as well as libraries,
 
93
      simply by giving it the name of the source file containing the main()
 
94
      function of the program - it takes the special comments from that
 
95
      function and handles them specially, inserting them as a section at
 
96
      the end of the first chapter of the document (it creates the first
 
97
      chapter if necessary).
 
98
    </p>
 
99
    <p>
 
100
      <strong>Options</strong> are described in the section
 
101
      <em>Arguments and Defaults</em> below.
 
102
    </p>
 
103
  </section>
 
104
  <section>
 
105
    <heading>Extra markup</heading>
 
106
    <p>
 
107
      There are some cases where special extra processing is performed,
 
108
      predominantly in the first comment found in the source file,
 
109
      from which various chunks of GSDoc markup may be extracted and
 
110
      placed into appropriate locations in the output document -
 
111
    </p>
 
112
    <list>
 
113
      <item><strong>AutogsdocSource</strong>:&#160;
 
114
        In any line where <code>AutogsdocSource</code>:&#160; is found, the
 
115
        remainder of the line is taken as a source file name to be used
 
116
        instead of making the assumption that each&#160;.h file processed uses
 
117
        a &#160;.m file of the same name.  You may supply multiple
 
118
        <code>AutogsdocSource</code>:&#160; lines where a header file declares
 
119
        items which are defined in multiple source files.<br /> If a file name
 
120
        is absolute, it is used just as supplied.<br /> If on the other hand,
 
121
        it is a relative path, the software looks for the source file first
 
122
        relative to the location of the header file, and if not found there,
 
123
        relative to the current directory in which autogsdoc is running, and
 
124
        finally relative to the directory specified by the
 
125
        <code>DocumentationDirectory</code> default.
 
126
      </item>
 
127
      <item><strong>&lt;abstract&gt;</strong>
 
128
        An abstract of the content of the document ... placed in the head
 
129
        of the GSDoc output.
 
130
      </item>
 
131
      <item><strong>&lt;author&gt;</strong>
 
132
        A description of the author of the code - may be repeated to handle
 
133
        the case where a document has multiple authors.  Placed in the
 
134
        head of the GSDoc output.<br />
 
135
        As an aid to readability of the source, some special additional
 
136
        processing is performed related to the document author -<br />
 
137
        Any line of the form '<code>Author</code>: name &lt;email-address&gt;',
 
138
        or '<code>By</code>: name &lt;email-address&gt;',
 
139
        or '<code>Author</code>: name' or '<code>By</code>: name'
 
140
        will be recognised and converted to an <em>author</em> element,
 
141
        possibly containing an <em>email</em> element.
 
142
      </item>
 
143
      <item><strong>&lt;back&gt;</strong>
 
144
        Placed in the GSDoc output just before the end of the body of the
 
145
        document - intended to be used for appendices, index etc..
 
146
      </item>
 
147
      <item><strong>&lt;chapter&gt;</strong>
 
148
        Placed immediately before any generated class documentation ...
 
149
        intended to be used to provide overall description of how the
 
150
        code being documented works.<br />Any documentation for the main()
 
151
        function of a program is inserted as a section at the end of this
 
152
        chapter.
 
153
      </item>
 
154
      <item><strong>&lt;copy&gt;</strong>
 
155
        Copyright of the content of the document ... placed in the head
 
156
        of the GSDoc output.<br />
 
157
        As an aid to readability of the source, some special additional
 
158
        processing is performed -<br />
 
159
        Any line of the form 'Copyright (C) text' will be recognised and
 
160
        converted to a <em>copy</em> element.
 
161
      </item>
 
162
      <item><strong>&lt;date&gt;</strong>
 
163
        Date of the revision of the document ... placed in the head
 
164
        of the GSDoc output.  If this is omitted the tool will try to
 
165
        construct a value from the RCS Date tag (if available).
 
166
      </item>
 
167
      <item><strong>&lt;front&gt;</strong>
 
168
        Inserted into the document at the start of the body ... intended
 
169
        to provide for introduction or contents pages etc.
 
170
      </item>
 
171
      <item><strong>&lt;title&gt;</strong>
 
172
        Title of the document ... placed in the head of the GSDoc output.
 
173
        If this is omitted the tool will generate a (probably poor)
 
174
        title of its own - so you should include this markup manually.
 
175
      </item>
 
176
      <item><strong>&lt;version&gt;</strong>
 
177
        Version identifier of the document ... placed in the head
 
178
        of the GSDoc output.  If this is omitted the tool will try to
 
179
        construct a value from the RCS Revision tag (if available).
 
180
      </item>
 
181
    </list>
 
182
    <p>
 
183
      <strong>NB</strong>The markup just described may be used within class,
 
184
        category, or protocol documentation ... if so, it is extracted and
 
185
        wrapped round the rest of the documentation for the class as the
 
186
        class's chapter.  The rest of the class documentation is normally
 
187
        inserted at the end of the chapter, but may instead be substituted in
 
188
        in place of the &lt;unit /&gt; pseudo-element within the
 
189
        &lt;chapter&gt; element.
 
190
    </p>
 
191
  </section>
 
192
  <section>
 
193
    <heading>Method markup</heading>
 
194
    <p>
 
195
      In comments being used to provide text for a method description, the
 
196
      following markup is removed from the text and handled specially -
 
197
    </p>
 
198
    <list>
 
199
      <item><strong>&lt;init /&gt;</strong>
 
200
        The method is marked as being the designated initialiser for the class.
 
201
      </item>
 
202
      <item><strong>&lt;override-subclass /&gt;</strong>
 
203
        The method is marked as being one which subclasses must override
 
204
        (e.g. an abstract method).
 
205
      </item>
 
206
      <item><strong>&lt;override-never /&gt;</strong>
 
207
        The method is marked as being one which subclasses should <em>NOT</em>
 
208
        override.
 
209
      </item>
 
210
      <item><strong>&lt;standards&gt; ... &lt;/standards&gt;</strong>
 
211
        The markup is removed from the description and placed <em>after</em>
 
212
        it in the GSDoc output - so that the method is described as
 
213
        conforming (or not conforming) to the specified standards.
 
214
      </item>
 
215
    </list>
 
216
  </section>
 
217
  <section>
 
218
    <heading>Automated markup</heading>
 
219
    <p>
 
220
      Generally, the text in comments is reformatted to standardise and
 
221
      indent it nicely ... the reformatting is <em>not</em> performed on
 
222
      any text inside an &lt;example&gt; element.<br />
 
223
      When the text is reformatted, it is broken into whitespace separated
 
224
      'words' which are then subjected to some extra processing ...
 
225
    </p>
 
226
    <list>
 
227
      <item>Certain well known constants such as YES, NO, and nil are
 
228
        enclosed in &lt;code&gt; ... &lt;/code&gt; markup.
 
229
      </item>
 
230
      <item>The names of method arguments within method descriptions are
 
231
        enclosed in &lt;var&gt; ... &lt;/var&gt; markup.
 
232
      </item>
 
233
      <item>Method names (beginning with a plus or minus) are enclosed
 
234
        in &lt;ref...&gt; ... &lt;/ref&gt; markup.<br />
 
235
        e.g. "-init" (without the quotes) would be wrapped in a GSDoc
 
236
        reference element to point to the init method of the current
 
237
        class or, if only one known class had an init method, it
 
238
        would refer to the method of that class.
 
239
        <br />Note the fact that the method name must be surrounded by
 
240
        whitespace to be recognized (though a comma, fullstop, or semicolon
 
241
        at the end of the specifier will act like whitespace).
 
242
      </item>
 
243
      <item>Method specifiers including class names (beginning and ending with
 
244
        square brackets) are enclosed in &lt;ref...&gt; ... &lt;/ref&gt; markup.
 
245
        <br />e.g. <code>[</code>NSObject-init<code>]</code>,
 
246
        will create a reference to the init method of NSObject (either the
 
247
        class proper, or any of its categories), while
 
248
        <br /><code>[</code>(NSCopying)-copyWithZone:<code>]</code>, creates a
 
249
        reference to a method in the NSCopying protocol.
 
250
        <br />Note that no spaces must appear between the square brackets
 
251
        in these specifiers.
 
252
        <br />Protocol names are enclosed in round brackets rather than
 
253
        the customary angle brackets, because GSDoc is an XML language, and
 
254
        XML treats angle brackets specially.
 
255
      </item>
 
256
      <item>Class names (and also protocol and category names) enclosed
 
257
        in square brackets are also cross referenced.
 
258
        <br />Protocol names are enclosed in round brackets rather than
 
259
        the customary angle brackets, because GSDoc is an XML language, and
 
260
        XML treats angle brackets specially.
 
261
      </item>
 
262
      <item>Function names (ending with '()') other than 'main()' are enclosed
 
263
        in &lt;ref...&gt; ... &lt;/ref&gt; markup.<br />
 
264
        e.g. "NSLogv()" (without the quotes) would be wrapped in a GSDoc
 
265
        reference element to point to the documentation of the NSLog function.
 
266
        <br />Note the fact that the function name must be surrounded by
 
267
        whitespace (though a comma, fullstop, or semicolon at the end
 
268
        of the specifier will also act as a whitespace terminator).
 
269
        <br />
 
270
      </item>
 
271
    </list>
 
272
  </section>
 
273
  <section>
 
274
    <heading>Arguments and Defaults</heading>
 
275
    <p>
 
276
      The tool accepts certain user defaults (which can of course be
 
277
      supplied as command-line arguments by prepending '-' before the default
 
278
      name and giving the value afterwards, as in -<code>Clean YES</code>):
 
279
    </p>
 
280
    <list>
 
281
      <item><strong>Clean</strong>
 
282
        If this boolean value is set to YES, then rather than generating
 
283
        documentation, the tool removes all GSDoc files generated in the
 
284
        project, and all html files generated from them (as well as any
 
285
        which would be generated from GSDoc files listed explicitly),
 
286
        and finally removes the project index file.<br />
 
287
        The only exception to this is that template GSDoc files (i.e. those
 
288
        specified using "-ConstantsTemplate ...", "-FunctionsTemplate ..."
 
289
        arguments etc) are not deleted unless the CleanTemplates flag is set.
 
290
      </item>
 
291
      <item><strong>CleanTemplates</strong>
 
292
        This flag specifies whether template GSDoc files are to be removed
 
293
        along with other files when the Clean option is specified.
 
294
        The default is for them not to be removed ... since these templates
 
295
        may have been produced manually and just had data inserted into them.
 
296
      </item>
 
297
      <item><strong>ConstantsTemplate</strong>
 
298
        Specify the name of a template document into which documentation
 
299
        about constants should be inserted from all files in the project.<br />
 
300
        This is useful if constants in the source code are scattered around many
 
301
        files, and you need to group them into one place.<br />
 
302
        You are responsible for ensuring that the basic template document
 
303
        (into which individual constant documentation is inserted) contains
 
304
        all the other information you want, but as a convenience autogsdoc
 
305
        will generate a simple template (which you may then edit) for you
 
306
        if the file does not exist.
 
307
        <br />Insertion takes place immediately before the <em>back</em>
 
308
        element (or if that does not exist, immediately before the end
 
309
        of the <em>body</em> element) in the template.
 
310
      </item>
 
311
      <item><strong>Declared</strong>
 
312
        Specify where headers are to be documented as being found.<br />
 
313
        The actual name produced in the documentation is formed by appending
 
314
        the last component of the header file name to the value of this
 
315
        default.<br />
 
316
        If this default is not specified, the full name of the header file
 
317
        (as supplied on the command line), with the HeaderDirectory
 
318
        default prepended, is used.<br />
 
319
        A typical usage of this might be <code>"-Declared Foundation"</code>
 
320
        when generating documentation for the GNUstep base library.  This
 
321
        would result in the documentation saying that NSString is declared
 
322
        in <code>Foundation/NSString.h</code>
 
323
      </item>
 
324
      <item><strong>DocumentAllInstanceVariables</strong>
 
325
        This flag permits you to generate documentation for all instance
 
326
        variables.  Normally, only those explicitly declared 'public' or
 
327
        'protected' will be documented.
 
328
      </item>
 
329
      <item><strong>DocumentInstanceVariables</strong>
 
330
        This flag permits you to turn off documentation for instance
 
331
        variables completely.  Normally, explicitly declared 'public' or
 
332
        'protected' instance variables will be documented.
 
333
      </item>
 
334
      <item><strong>InstanceVariablesAtEnd</strong>
 
335
        This flag, if set, directs the HTML generator to place instance
 
336
        variable documentation at the end of the class, instead of the
 
337
        beginning.  This is useful if you use a lot of protected instance
 
338
        variables which are only going to be of secondary interest to general
 
339
        users of the class.
 
340
      </item>
 
341
      <item><strong>DocumentationDirectory</strong>
 
342
        May be used to specify the directory in which generated documentation
 
343
        is to be placed.  If this is not set, output is placed in the current
 
344
        directory.  This directory is also used as a last resort to locate
 
345
        source files (not headers), and more importantly, it is used as the
 
346
        <em>first and only</em> resort to locate any <code>.gsdoc</code> files
 
347
        that are passed in on the command line.  Any path information given
 
348
        for these files is <em><strong>removed</strong></em> and they are
 
349
        searched for in <code>DocumentationDirectory</code> (even though they
 
350
        may not have been autogenerated).
 
351
      </item>
 
352
      <item><strong>Files</strong>
 
353
        Specifies the name of a file containing a list of file names as
 
354
        a property list array <em>(name1,name2,...)</em> format.  If this
 
355
        is present, filenames in the program argument list are ignored and
 
356
        the names in this file are used as the list of names to process.
 
357
      </item>
 
358
      <item><strong>FunctionsTemplate</strong>
 
359
        Specify the name of a template document into which documentation
 
360
        about functions should be inserted from all files in the project.<br />
 
361
        This is useful if function source code is scattered around many
 
362
        files, and you need to group it into one place.<br />
 
363
        You are responsible for ensuring that the basic template document
 
364
        (into which individual function documentation is inserted) contains
 
365
        all the other information you want, but as a convenience autogsdoc
 
366
        will generate a simple template (which you may then edit) for you
 
367
        if the file does not exist.
 
368
        <br />Insertion takes place immediately before the <em>back</em>
 
369
        element (or if that does not exist, immediately before the end
 
370
        of the <em>body</em> element) in the template.
 
371
      </item>
 
372
      <item><strong>GenerateHtml</strong>
 
373
        May be used to specify if HTML output is to be generated.
 
374
        Defaults to YES.
 
375
      </item>
 
376
      <item><strong>HeaderDirectory</strong>
 
377
        May be used to specify the directory to be searched for header files.
 
378
        When supplied, this value is prepended to relative header names,
 
379
        otherwise the relative header names are interpreted relative to
 
380
        the current directory.<br />
 
381
        Header files specified as absolute paths are not influenced by this
 
382
        default.
 
383
      </item>
 
384
      <item><strong>IgnoreDependencies</strong>
 
385
        A boolean value which may be used to specify that the program should
 
386
        ignore file modification times and regenerate files anyway.  Provided
 
387
        for use in conjunction with the <code>make</code> system, which is
 
388
        expected to manage dependency checking itself.
 
389
      </item>
 
390
      <item><strong>LocalProjects</strong>
 
391
        This value is used to control the automatic inclusion of local
 
392
        external projects into the indexing system for generation of
 
393
        cross-references in final document output.<br />
 
394
        If set to 'None', then no local project references are done,
 
395
        otherwise, the 'Local' GNUstep documentation directory is recursively
 
396
        searched for files with a <code>.igsdoc</code> extension, and the
 
397
        indexing information from those files is used.<br />
 
398
        The value of this string is also used to generate the filenames in
 
399
        the cross reference ... if it is an empty string, the path to use
 
400
        is assumed to be a file in the same directory where the igsdoc
 
401
        file was found, otherwise it is used as a prefix to the name in
 
402
        the index.<br />
 
403
        NB. Local projects with the same name as the project currently
 
404
        being documented will <em>not</em> be included by this mechanism.
 
405
        If you wish to include such projects, you must do so explicitly
 
406
        using <em>"-Projects ..."</em>
 
407
      </item>
 
408
      <item><strong>MacrosTemplate</strong>
 
409
        Specify the name of a template document into which documentation
 
410
        about macros should be inserted from all files in the project.<br />
 
411
        This is useful if macro code is scattered around many
 
412
        files, and you need to group it into one place.<br />
 
413
        You are responsible for ensuring that the basic template document
 
414
        (into which individual macro documentation is inserted) contains
 
415
        all the other information you want, but as a convenience autogsdoc
 
416
        will generate a simple template (which you may then edit) for you
 
417
        if the file does not exist.
 
418
        <br />Insertion takes place immediately before the <em>back</em>
 
419
        element (or if that does not exist, immediately before the end
 
420
        of the <em>body</em> element) in the template.
 
421
      </item>
 
422
      <item><strong>MakeDependencies</strong>
 
423
        A filename to be used to output dependency information for make.  This
 
424
        will take the form of listing all header and source files known for
 
425
        the project as dependencies of the project name (see
 
426
        <code>Project</code>).
 
427
      </item>
 
428
      <item><strong>Project</strong>
 
429
        Specifies the name of this project ... determines the
 
430
        name of the index reference file produced as part of the documentation
 
431
        to provide information enabling other projects to cross-reference to
 
432
        items in this project.  If not set, 'Untitled' is used.
 
433
      </item>
 
434
      <item><strong>Projects</strong>
 
435
        This value may be supplied as a dictionary containing the paths to
 
436
        the igsdoc index/reference files used by external projects, along
 
437
        with values to be used to map the filenames found in the indexes.<br />
 
438
        For example, if a project index (igsdoc) file says that the class
 
439
        <code>Foo</code> is found in the file <code>Foo</code>, and the
 
440
        path associated with that project index is <code>/usr/doc/proj</code>,
 
441
        Then generated html output may reference the class as being in
 
442
        <code>/usr/doc/prj/Foo.html</code> .  Note that a dictionary may be
 
443
        given on the command line by using the standard PropertyList format
 
444
        (not the XML format of OS X), using semicolons as line-separators, and
 
445
        enclosing it in single quotes.
 
446
      </item>
 
447
      <item><strong>ShowDependencies</strong>
 
448
        A boolean value which may be used to specify that the program should
 
449
        log which files are being regenerated because of their dependencies
 
450
        on other files.
 
451
      </item>
 
452
      <item><strong>Standards</strong>
 
453
        A boolean value used to specify whether the program should insert
 
454
        information about standards complience into the documentation.
 
455
        This should only be used when documenting the GNUstep libraries
 
456
        and tools themselves as it assumes that the code being documented
 
457
        is part of GNUstep and possibly complies with the OpenStep standard
 
458
        or implements MacOS-X compatible methods.
 
459
      </item>
 
460
      <item><strong>SystemProjects</strong>
 
461
        This value is used to control the automatic inclusion of system
 
462
        external projects into the indexing system for generation of
 
463
        cross-references in final document output.<br />
 
464
        If set to 'None', then no system project references are done,
 
465
        otherwise, the 'System' GNUstep documentation directory is recursively
 
466
        searched for files with a <code>.igsdoc</code> extension, and the
 
467
        indexing information from those files is used.<br />
 
468
        The value of this string is also used to generate the filenames in
 
469
        the cross reference ... if it is an empty string, the path to use
 
470
        is assumed to be a file in the same directory where the igsdoc
 
471
        file was found, otherwise it is used as a prefix to the name in
 
472
        the index.<br />
 
473
        NB. System projects with the same name as the project currently
 
474
        being documented will <em>not</em> be included by this mechanism.
 
475
        If you wish to include such projects, you must do so explicitly
 
476
        using <em>"-Projects ..."</em>
 
477
      </item>
 
478
      <item><strong>TypedefsTemplate</strong>
 
479
        Specify the name of a template document into which documentation
 
480
        about typedefs should be inserted from all files in the project.<br />
 
481
        This is useful if typedef source code is scattered around many
 
482
        files, and you need to group it into one place.<br />
 
483
        You are responsible for ensuring that the basic template document
 
484
        (into which individual typedef documentation is inserted) contains
 
485
        all the other information you want, but as a convenience autogsdoc
 
486
        will generate a simple template (which you may then edit) for you
 
487
        if the file does not exist.
 
488
        <br />Insertion takes place immediately before the <em>back</em>
 
489
        element (or if that does not exist, immediately before the end
 
490
        of the <em>body</em> element) in the template.
 
491
      </item>
 
492
      <item><strong>Up</strong>
 
493
        A string used to supply the name to be used in the 'up' link from
 
494
        generated GSDoc documents.  This should normally be the name of a
 
495
        file which contains an index of the contents of a project.<br />
 
496
        If this is missing or set to an empty string, then no 'up' link
 
497
        will be provided in the documents.
 
498
      </item>
 
499
      <item><strong>VariablesTemplate</strong>
 
500
        Specify the name of a template document into which documentation
 
501
        about variables should be inserted from all files in the project.<br />
 
502
        This is useful if variable source code is scattered around many
 
503
        files, and you need to group it into one place.<br />
 
504
        You are responsible for ensuring that the basic template document
 
505
        (into which individual variable documentation is inserted) contains
 
506
        all the other information you want, but as a convenience autogsdoc
 
507
        will generate a simple template (which you may then edit) for you
 
508
        if the file does not exist.
 
509
        <br />Insertion takes place immediately before the <em>back</em>
 
510
        element (or if that does not exist, immediately before the end
 
511
        of the <em>body</em> element) in the template.
 
512
      </item>
 
513
      <item><strong>Verbose</strong>
 
514
        A boolean used to specify whether you want verbose debug/warning
 
515
        output to be produced.
 
516
      </item>
 
517
      <item><strong>Warn</strong>
 
518
        A boolean used to specify whether you want standard warning
 
519
        output (e.g. report of undocumented methods) produced.
 
520
      </item>
 
521
      <item><strong>WordMap</strong>
 
522
        This value is a dictionary used to map identifiers/keywords found
 
523
        in the source files  to other words.  Generally you will not have
 
524
        to use this, but it is sometimes helpful to avoid the parser being
 
525
        confused by the use of C preprocessor macros.  You can effectively
 
526
        redefine the macro to something less confusing.<br />
 
527
        The value you map the identifier to must be one of -<br />
 
528
        Another identifier,<br />
 
529
        An empty string - the value is ignored,<br />
 
530
        Two slashes ('//') - the rest of the line is ignored.<br />
 
531
        Note that a dictionary may be given on the command line by using the
 
532
        standard PropertyList format (not the XML format of OS X), using
 
533
        semicolons as line-separators, and enclosing it in single quotes.
 
534
      </item>
 
535
    </list>
 
536
  </section>
300
537
  <section>
301
538
    <heading>Inter-document linkage</heading>
302
539
    <p>
304
541
      should be used as the 'up' link for any other documents used.<br />
305
542
      This name must not include a path or extension.<br />
306
543
      Generally, the document referred to by this default should be a
307
 
      hand-edited gsdoc document which should have a <em>back</em>
308
 
      section containing a project index. eg.
 
544
      hand-edited GSDoc document which should have a <em>back</em>
 
545
      section containing a project index. e.g.
309
546
    </p>
310
547
<example>
311
548
  &lt;?xml version="1.0"?&gt;
312
 
  &lt;!DOCTYPE gsdoc PUBLIC "-//GNUstep//DTD gsdoc 0.6.7//EN" 
313
 
  "http://www.gnustep.org/gsdoc-0_6_7.xml"&gt;
 
549
  &lt;!DOCTYPE gsdoc PUBLIC "-//GNUstep//DTD gsdoc 1.0.1//EN"
 
550
  "http://www.gnustep.org/gsdoc-1_0_1.xml"&gt;
314
551
  &lt;gsdoc base="index"&gt;
315
552
    &lt;head&gt;
316
553
      &lt;title&gt;My project reference&lt;/title&gt;
327
564
  &lt;/gsdoc&gt;
328
565
</example>
329
566
  </section>
 
567
 
 
568
  <section>
 
569
    <heading>Implementation Notes</heading>
 
570
    <p>
 
571
      The autogsdoc tool internally makes use of the following four classes-
 
572
    </p>
 
573
    <deflist>
 
574
      <term><ref type="class" id="AGSParser"/></term>
 
575
      <desc>Parses source code comments to an internal representation.
 
576
      </desc>
 
577
      <term><ref type="class" id="AGSOutput"/></term>
 
578
      <desc>Converts internal representation of source comments to a gsdoc
 
579
            document.</desc>
 
580
      <term><ref type="class" id="AGSIndex"/></term>
 
581
      <desc>Internal representation of an igsdoc file, representing indices
 
582
            of a project's files.</desc>
 
583
      <term><ref type="class" id="AGSHtml"/></term>
 
584
      <desc>Converts gsdoc XML to HTML, using AGSIndex instances.</desc>
 
585
    </deflist>
 
586
  </section>
 
587
 
330
588
</chapter>
331
589
<back>
332
590
  <index type="title" scope="project" />
333
 
  <index type="class" scope="project" />
334
591
</back>
 
592
 
335
593
   */
336
594
 
337
595
#include        <config.h>
340
598
#include "AGSOutput.h"
341
599
#include "AGSIndex.h"
342
600
#include "AGSHtml.h"
343
 
 
344
 
 
 
601
#include "GNUstepBase/GNUstep.h"
 
602
#ifdef NeXT_Foundation_LIBRARY
 
603
#include "GNUstepBase/GSCategories.h"
 
604
#endif
 
605
 
 
606
/** Invokes the autogsdoc tool. */
345
607
int
346
608
main(int argc, char **argv, char **env)
347
609
{
348
610
  NSProcessInfo         *proc;
349
611
  unsigned              i;
 
612
  NSDictionary          *argsRecognized;
350
613
  NSUserDefaults        *defs;
351
614
  NSFileManager         *mgr;
352
615
  NSString              *documentationDirectory;
353
616
  NSString              *declared;
354
617
  NSString              *headerDirectory;
355
618
  NSString              *project;
 
619
  NSString              *refsName;
356
620
  NSDictionary          *originalIndex;
357
621
  AGSIndex              *projectRefs;
358
622
  AGSIndex              *globalRefs;
360
624
  NSString              *refsFile;
361
625
  id                    obj;
362
626
  unsigned              count;
 
627
  unsigned              firstFile = 1;
363
628
  BOOL                  generateHtml = YES;
364
629
  BOOL                  ignoreDependencies = NO;
365
630
  BOOL                  showDependencies = NO;
366
631
  BOOL                  verbose = NO;
367
 
  NSArray               *files;
 
632
  BOOL                  warn = NO;
 
633
  BOOL                  instanceVarsAtEnd = YES;
 
634
  NSArray               *files = nil;
368
635
  NSMutableArray        *sFiles = nil;  // Source
369
636
  NSMutableArray        *gFiles = nil;  // GSDOC
370
637
  NSMutableArray        *hFiles = nil;  // HTML
371
 
  CREATE_AUTORELEASE_POOL(outer);
372
 
  CREATE_AUTORELEASE_POOL(pool);
373
 
 
374
 
  RELEASE(pool);
 
638
#if GS_WITH_GC == 0
 
639
  NSAutoreleasePool     *outer = nil;
 
640
  NSAutoreleasePool     *pool = nil;
 
641
#endif
 
642
  NSString      *arg;
 
643
  NSString      *opt;
 
644
  NSSet         *argSet;
 
645
  NSArray       *argsGiven;
 
646
  NSArray       *informalProtocols = nil;
 
647
 
 
648
  /*
 
649
   Overall process in this file is as follows:
 
650
 
 
651
   1) Get/test defaults and arguments.
 
652
 
 
653
   2) Init filename list, and move .h/.m into "source files", .gsdoc into
 
654
      "gsdoc files", and .html into "html files".
 
655
 
 
656
   3) Load existing .igsdoc file (PropertyList/Dictionary format) if found,
 
657
      initializing an AGSIndex from it.
 
658
 
 
659
   4) Clean if desired:
 
660
 
 
661
      4a) Build list of all template files, and remove generated content
 
662
          from them if not cleaning templates.
 
663
      4b) Figure out generated files from index file (if none assumes none
 
664
          generated) and remove them (but not template files unless
 
665
          supposed to).
 
666
      4c) Remove index file.
 
667
      4d) Remove HTML files corresponding to .gsdoc files in current list.
 
668
 
 
669
   5) Start with "source files".. for each one (hereafter called a "header
 
670
      file"):
 
671
 
 
672
      5a) Parse declarations (in .h or .m) using an AGSParser object.
 
673
      5b) Determine (possibly multiple) dependent .m files corresponding to
 
674
          a .h and parse them.
 
675
      5c) Feed parser results to an AGSOutput instance.
 
676
 
 
677
   6) Move to "gsdoc files" (including both command-line given ones and
 
678
      just-generated ones).. and generate the index; for each one:
 
679
 
 
680
      6a) Remove any path specification and search in
 
681
          documentationDirectory then CWD for it.
 
682
      6b) Parse the file, call [localRefs makeRefs: root],
 
683
          [projectRefs mergeRefs: localRefs] to make indices.
 
684
 
 
685
   7) Write the .igsdoc file.
 
686
 
 
687
   8) Build index references to external projects.
 
688
 
 
689
   9) Create HTML frames auxiliary files.
 
690
 
 
691
   10) If needed, re-pass through the "gsdoc files" to generate HTML.
 
692
      10a) Find files as before.
 
693
      10b) Parse as before.
 
694
      10c) Feed the DOM tree to an AGSHtml instance, and dump the result to
 
695
           a file.
 
696
 
 
697
   11) For HTML files that were given on the command line, adjust all cross
 
698
       reference HREFs to paths given in arguments.
 
699
 
 
700
   12) If MakeDependencies was requested, list all header and source files
 
701
       as colon-dependencies of the project name.
 
702
 
 
703
   */
375
704
 
376
705
#ifdef GS_PASS_ARGUMENTS
377
706
  [NSProcessInfo initializeWithArguments: argv count: argc environment: env];
378
707
#endif
379
708
 
380
 
#if HAVE_LIBXML == 0
 
709
#if GS_WITH_GC == 0
 
710
  outer = [NSAutoreleasePool new];
 
711
#endif
 
712
 
 
713
#ifndef HAVE_LIBXML
381
714
  NSLog(@"ERROR: The GNUstep Base Library was built\n"
382
715
@"        without an available libxml library. Autogsdoc needs the libxml\n"
383
716
@"        library to function. Aborting");
384
 
  exit(1);
 
717
  exit(EXIT_FAILURE);
385
718
#endif
386
719
 
 
720
  /*
 
721
   * 1) Get/test defaults and arguments.
 
722
   */
387
723
  defs = [NSUserDefaults standardUserDefaults];
388
724
  [defs registerDefaults: [NSDictionary dictionaryWithObjectsAndKeys:
389
725
    @"Untitled", @"Project",
390
726
    nil]];
391
727
 
 
728
  // BEGIN test for any unrecognized arguments, or "--help"
 
729
  argsRecognized = [NSDictionary dictionaryWithObjectsAndKeys:
 
730
    @"\t\t\tBOOL\t(NO)\n\tproduce verbose output",
 
731
    @"Verbose",
 
732
    @"\t\t\tBOOL\t(NO)\n\tproduce warnings",
 
733
    @"Warn",
 
734
    @"\tBOOL\t(NO)\n\tignore file mod times (always generate)",
 
735
    @"IgnoreDependencies",
 
736
    @"\t\tBOOL\t(NO)\n\tlog files being regenerated due to dependencies",
 
737
    @"ShowDependencies",
 
738
    @"\t\tBOOL\t(YES)\n\tgenerate HTML output "
 
739
      @"(as opposed to just gsdoc from source)",
 
740
    @"GenerateHtml",
 
741
    @"\t\t\tSTR\t(\"\")\n\tspecify where headers "
 
742
      @"are to be documented as being found",
 
743
    @"Declared",
 
744
    @"\t\t\tSTR\t(\"Untitled\")\n\thead title name of this documentation",
 
745
    @"Project",
 
746
    @"\t\tSTR\t(.)\n\tdirectory to search for .h files",
 
747
    @"HeaderDirectory",
 
748
    @"\tSTR\t(.)\n\tdirectory to place generated files and "
 
749
      @"search for gsdoc files",
 
750
    @"DocumentationDirectory",
 
751
    @"\t\t\tSTR\t(\"\")\n\tname of file containing filenames to document",
 
752
    @"Files",
 
753
    @"\t\t\tBOOL\t(NO)\n\tremove all generated files",
 
754
    @"Clean",
 
755
    @"\t\tBOOL\t(NO)\n\tremove template files when cleaning",
 
756
    @"CleanTemplates",
 
757
    @"\t\t\tSTR\t(\"\")\n\tfilename to link to from generated HTML",
 
758
    @"Up",
 
759
    @"\t\t\tspecial\t(nil)\n\tdictionary used to preprocess (see docs)",
 
760
    @"WordMap",
 
761
    @"\t\t\tBOOL\t(NO)\n\twhether to insert information on "
 
762
      @"standards compliance",
 
763
    @"Standards",
 
764
    @"BOOL\t(NO)\n\tdocument private instance variables",
 
765
    @"DocumentAllInstanceVariables",
 
766
    @"\tBOOL\t(YES)\n\tdocument instance variables at all",
 
767
    @"DocumentInstanceVariables",
 
768
    @"\tBOOL\t(YES)\n\tput instance variable docs at end of class",
 
769
    @"InstanceVariablesAtEnd",
 
770
    @"\t\tSTR\t(\"None\")\n\twhether to include other projects in index",
 
771
    @"LocalProjects",
 
772
    @"\t\tSTR\t(\"None\")\n\twhether to include system projects in index",
 
773
    @"SystemProjects",
 
774
    @"\t\t\tSTR\t(\"None\")\n\texplicit list of other projects to index",
 
775
    @"Projects",
 
776
    @"\t\tSTR\t(\"\")\n\tfile to output dependency info for 'make' into",
 
777
    @"MakeDependencies",
 
778
    @"\t\tSTR\t(\"\")\n\tfile into which docs for constants "
 
779
      @"should be consolidated",
 
780
    @"ConstantsTemplate",
 
781
    @"\t\tSTR\t(\"\")\n\tfile into which docs for functions "
 
782
      @"should be consolidated",
 
783
    @"FunctionsTemplate",
 
784
    @"\t\tSTR\t(\"\")\n\tfile into which docs for macros "
 
785
      @"should be consolidated",
 
786
    @"MacrosTemplate",
 
787
    @"\t\tSTR\t(\"\")\n\tfile into which docs for typedefs "
 
788
      @"should be consolidated",
 
789
    @"TypedefsTemplate",
 
790
    @"\t\tSTR\t(\"\")\n\tfile into which docs for variables "
 
791
      @"should be consolidated",
 
792
    @"VariablesTemplate",
 
793
    @"\t\tBOOL\t(NO)\n\tif YES, create documentation pages "
 
794
      @"for display in HTML frames",
 
795
    @"MakeFrames",
 
796
    nil];
 
797
  argSet = [NSSet setWithArray: [argsRecognized allKeys]];
 
798
  argsGiven = [[NSProcessInfo processInfo] arguments];
 
799
 
 
800
  for (i = 0; i < [argsGiven count]; i++)
 
801
    {
 
802
      arg = [argsGiven objectAtIndex: i];
 
803
      if ([arg characterAtIndex: 0] == '-')
 
804
        {
 
805
          opt = ([arg characterAtIndex: 1] == '-') ?
 
806
              [arg substringFromIndex: 2] : [arg substringFromIndex: 1];
 
807
        }
 
808
      else
 
809
        {
 
810
          continue;
 
811
        }
 
812
      if (![argSet containsObject: opt] || [@"help" isEqual: opt])
 
813
        {
 
814
          NSArray       *args = [argsRecognized allKeys];
 
815
 
 
816
          GSPrintf(stderr, @"Usage:\n");
 
817
          GSPrintf(stderr, [NSString stringWithFormat:
 
818
            @"    %@ [options] [files]\n", [argsGiven objectAtIndex: 0]]);
 
819
          GSPrintf(stderr, @"\n Options:\n");
 
820
          for (i = 0; i < [args count]; i++)
 
821
            {
 
822
              arg = [args objectAtIndex: i];
 
823
              GSPrintf(stderr,
 
824
                [NSString stringWithFormat: @"     -%@\t%@\n\n",
 
825
                   arg, [argsRecognized objectForKey: arg]]);
 
826
            }
 
827
 
 
828
          GSPrintf(stderr, @"\n Files:\n");
 
829
          GSPrintf(stderr, @"  [.h files]\t\tMust be in 'HeaderDirectory'\n");
 
830
          GSPrintf(stderr,
 
831
            @"  [.m files]\t\tAbsolute or relative path (from here)\n");
 
832
          GSPrintf(stderr,
 
833
            @"  [.gsdoc files]\tMust be in 'DocumentationDirectory'\n\n");
 
834
          exit(1);
 
835
        }
 
836
    }
 
837
 
 
838
  mgr = [NSFileManager defaultManager];
 
839
 
 
840
 
392
841
  verbose = [defs boolForKey: @"Verbose"];
 
842
  warn = [defs boolForKey: @"Warn"];
393
843
  ignoreDependencies = [defs boolForKey: @"IgnoreDependencies"];
394
844
  showDependencies = [defs boolForKey: @"ShowDependencies"];
395
845
  if (ignoreDependencies == YES)
407
857
      generateHtml = [defs boolForKey: @"GenerateHtml"];
408
858
    }
409
859
 
 
860
  obj = [defs objectForKey: @"InstanceVariablesAtEnd"];
 
861
  if (obj != nil)
 
862
    {
 
863
      instanceVarsAtEnd = [defs boolForKey: @"InstanceVariablesAtEnd"];
 
864
    }
 
865
 
410
866
  declared = [defs stringForKey: @"Declared"];
411
867
  project = [defs stringForKey: @"Project"];
 
868
  refsName = [[project stringByAppendingPathExtension: @"igsdoc"] copy];
412
869
 
413
870
  headerDirectory = [defs stringForKey: @"HeaderDirectory"];
414
871
  if (headerDirectory == nil)
421
878
    {
422
879
      documentationDirectory = @"";
423
880
    }
 
881
  if ([documentationDirectory length] > 0
 
882
    && [mgr fileExistsAtPath: documentationDirectory] == NO)
 
883
    {
 
884
      [mgr createDirectoryAtPath: documentationDirectory attributes: nil];
 
885
    }
424
886
 
425
887
  proc = [NSProcessInfo processInfo];
426
888
  if (proc == nil)
427
889
    {
428
890
      NSLog(@"unable to get process information!");
429
 
      exit(1);
 
891
      exit(EXIT_FAILURE);
430
892
    }
431
893
 
432
894
  /*
433
 
   * Build an array of files to be processed.
 
895
   * 2) Build an array of files to be processed.
434
896
   */
435
 
  files = [proc arguments];
 
897
  obj = [defs stringForKey: @"Files"];
 
898
  if (obj != nil)
 
899
    {
 
900
      files = [NSArray arrayWithContentsOfFile: obj];
 
901
      if (files == nil)
 
902
        {
 
903
          NSLog(@"Failed to load files from '%@'", obj);
 
904
          exit(EXIT_FAILURE);
 
905
        }
 
906
      firstFile = 0;    // Not an argument list ... read from index 0
 
907
    }
 
908
  else
 
909
    {
 
910
      files = [proc arguments];
 
911
      firstFile = 1;    // An argument list ... ignore the program name.
 
912
    }
436
913
  sFiles = [NSMutableArray array];
437
914
  gFiles = [NSMutableArray array];
438
915
  hFiles = [NSMutableArray array];
442
919
      NSLog(@"Proc ... %@", proc);
443
920
      NSLog(@"Name ... %@", [proc processName]);
444
921
      NSLog(@"Files ... %@", files);
 
922
      NSLog(@"HeaderDirectory ... %@", headerDirectory);
 
923
      NSLog(@"DocumentationDirectory ... %@", documentationDirectory);
445
924
    }
446
 
  for (i = 1; i < count; i++)
 
925
  for (i = firstFile; i < count; i++)
447
926
    {
448
927
      NSString *arg = [files objectAtIndex: i];
449
928
 
455
934
        {
456
935
          [sFiles addObject: arg];
457
936
        }
458
 
      else if ([arg hasSuffix: @".m"] == YES)
 
937
      else if (([arg hasSuffix: @".m"] == YES)
 
938
               || ([arg hasSuffix: @".c"] == YES))
459
939
        {
460
940
          [sFiles addObject: arg];
461
941
        }
474
954
        }
475
955
    }
476
956
 
477
 
  if ([sFiles count] == 0 && [gFiles count] == 0 && [hFiles count] == 0)
478
 
    {
479
 
      NSLog(@"No filename arguments found ... giving up");
480
 
      return 1;
481
 
    }
482
 
 
483
 
  mgr = [NSFileManager defaultManager];
484
 
 
485
957
  /*
486
 
   * Load any old project indexing information and determine when the
487
 
   * indexing information was last updated (never ==> distant past)
 
958
   * 3) Load old project indexing information from the .igsdoc file if
 
959
   *    present and determine when the indexing information was last
 
960
   *    updated (never ==> distant past).
488
961
   */
489
962
  refsFile = [documentationDirectory
490
963
    stringByAppendingPathComponent: project];
506
979
 
507
980
          [projectRefs mergeRefs: originalIndex override: NO];
508
981
          dict = [mgr fileAttributesAtPath: refsFile traverseLink: YES];
509
 
          rDate = [dict objectForKey: NSFileModificationDate];
510
 
        }
511
 
    }
512
 
 
 
982
          rDate = [dict fileModificationDate];
 
983
        }
 
984
    }
 
985
 
 
986
  /*
 
987
   * 4) Clean if desired:
 
988
   */
 
989
  if ([defs boolForKey: @"Clean"] == YES)
 
990
    {
 
991
      NSDictionary      *output;
 
992
      NSEnumerator      *enumerator;
 
993
      NSArray           *outputNames;
 
994
      NSMutableSet      *allPaths;
 
995
      NSMutableSet      *templates = nil;
 
996
      NSSet             *preserve = nil;
 
997
      NSString          *path;
 
998
      NSArray   *keys = [NSArray arrayWithObjects:
 
999
        @"Constants",
 
1000
        @"Functions",
 
1001
        @"Macros",
 
1002
        @"Typedefs",
 
1003
        @"Variables",
 
1004
        nil];
 
1005
 
 
1006
      /*
 
1007
       * 4a) Build a set of all template files.
 
1008
       */
 
1009
      templates = AUTORELEASE([NSMutableSet new]);
 
1010
      enumerator = [keys objectEnumerator];
 
1011
      while ((path = [enumerator nextObject]) != nil)
 
1012
        {
 
1013
          path = [path stringByAppendingString: @"Template"];
 
1014
          path = [defs stringForKey: path];
 
1015
          if (path != nil)
 
1016
            {
 
1017
              path = [path stringByAppendingPathExtension: @"gsdoc"];
 
1018
              if ([path isAbsolutePath] == NO)
 
1019
                {
 
1020
                  path = [documentationDirectory
 
1021
                    stringByAppendingPathComponent: path];
 
1022
                }
 
1023
              [templates addObject: path];
 
1024
            }
 
1025
        }
 
1026
 
 
1027
      /*
 
1028
       * 4b) Unless we are supposed to clean templates, we preserve any
 
1029
       *     template gsdoc files, but remove any generated content.
 
1030
       */
 
1031
      if ([defs boolForKey: @"CleanTemplates"] == NO)
 
1032
        {
 
1033
          preserve = templates;
 
1034
          enumerator = [templates objectEnumerator];
 
1035
          while ((path = [enumerator nextObject]) != nil)
 
1036
            {
 
1037
              if ([mgr isReadableFileAtPath: path] == YES)
 
1038
                {
 
1039
                  NSMutableString       *ms;
 
1040
                  NSEnumerator          *e = [keys objectEnumerator];
 
1041
                  NSString              *k;
 
1042
                  unsigned              length;
 
1043
 
 
1044
                  ms = [[NSMutableString alloc] initWithContentsOfFile: path];
 
1045
                  if (ms == nil)
 
1046
                    {
 
1047
                      NSLog(@"Cleaning ... failed to read '%@'", path);
 
1048
                      continue;
 
1049
                    }
 
1050
                  length = [ms length];
 
1051
                  while ((k = [e nextObject]) != nil)
 
1052
                    {
 
1053
                      NSString  *ss;
 
1054
                      NSString  *es;
 
1055
                      NSRange   sr;
 
1056
                      NSRange   er;
 
1057
 
 
1058
                      ss = [NSString stringWithFormat: @"<!--Start%@-->", k];
 
1059
                      sr = [ms rangeOfString: ss];
 
1060
                      es = [NSString stringWithFormat: @"<!--End%@-->", k];
 
1061
                      er = [ms rangeOfString: es];
 
1062
                      if (sr.length > 0 && er.length > 0
 
1063
                        && er.location > sr.location)
 
1064
                        {
 
1065
                          NSRange       r;
 
1066
 
 
1067
                          r.location = sr.location;
 
1068
                          r.length = NSMaxRange(er) - r.location;
 
1069
                          [ms replaceCharactersInRange: r withString: @""];
 
1070
                        }
 
1071
                    }
 
1072
                  if ([ms length] != length)
 
1073
                    {
 
1074
                      if ([ms writeToFile: path atomically: YES] == NO)
 
1075
                        {
 
1076
                          NSLog(@"Cleaning ... failed to write '%@'", path);
 
1077
                        }
 
1078
                    }
 
1079
                }
 
1080
            }
 
1081
        }
 
1082
 
 
1083
      /*
 
1084
       * 4b) Build a list of all generated gsdoc files, then remove them
 
1085
       *     and their corresponding html documents.
 
1086
       */
 
1087
      output = [[projectRefs refs] objectForKey: @"output"];
 
1088
      enumerator = [output objectEnumerator];
 
1089
      allPaths = [[NSMutableSet alloc] initWithSet: templates];
 
1090
      while ((outputNames = [enumerator nextObject]) != nil)
 
1091
        {
 
1092
          [allPaths addObjectsFromArray: outputNames];
 
1093
        }
 
1094
      enumerator = [allPaths objectEnumerator];
 
1095
      while ((path = [enumerator nextObject]) != nil)
 
1096
        {
 
1097
          /*
 
1098
           * Delete any gsdoc files which are not in the preserve set.
 
1099
           */
 
1100
          if ([preserve member: path] == nil)
 
1101
            {
 
1102
              if ([mgr fileExistsAtPath: path] == YES)
 
1103
                {
 
1104
                  if ([mgr removeFileAtPath: path handler: nil] == NO)
 
1105
                    {
 
1106
                      NSLog(@"Cleaning ... failed to remove %@", path);
 
1107
                    }
 
1108
                }
 
1109
            }
 
1110
          path = [path stringByDeletingPathExtension];
 
1111
          path = [path stringByAppendingPathExtension: @"html"];
 
1112
          if ([mgr fileExistsAtPath: path] == YES)
 
1113
            {
 
1114
              if ([mgr removeFileAtPath: path handler: nil] == NO)
 
1115
                {
 
1116
                  NSLog(@"Cleaning ... failed to remove %@", path);
 
1117
                }
 
1118
            }
 
1119
        }
 
1120
      RELEASE(allPaths);
 
1121
 
 
1122
      /*
 
1123
       * 4c) Remove the project index file.
 
1124
       */
 
1125
      if ([mgr fileExistsAtPath: refsFile] == YES)
 
1126
        {
 
1127
          if ([mgr removeFileAtPath: refsFile handler: nil] == NO)
 
1128
            {
 
1129
              NSLog(@"Cleaning ... failed to remove %@", refsFile);
 
1130
            }
 
1131
        }
 
1132
 
 
1133
      /*
 
1134
       * 4d) Remove any HTML documents resulting from gsdoc files which
 
1135
       *     were specified on the command line rather than generated.
 
1136
       */
 
1137
      enumerator = [gFiles objectEnumerator];
 
1138
      while ((path = [enumerator nextObject]) != nil)
 
1139
        {
 
1140
          path = [path lastPathComponent];
 
1141
          path = [path stringByDeletingPathExtension];
 
1142
          path = [path stringByAppendingPathExtension: @"html"];
 
1143
          path = [documentationDirectory
 
1144
            stringByAppendingPathComponent: path];
 
1145
          if ([mgr fileExistsAtPath: path] == YES)
 
1146
            {
 
1147
              if ([mgr removeFileAtPath: path handler: nil] == NO)
 
1148
                {
 
1149
                  NSLog(@"Cleaning ... failed to remove %@", path);
 
1150
                }
 
1151
            }
 
1152
        }
 
1153
      return 0;
 
1154
    }
 
1155
 
 
1156
  if ([sFiles count] == 0 && [gFiles count] == 0 && [hFiles count] == 0)
 
1157
    {
 
1158
      NSLog(@"No .h, .m, .c, .gsdoc, or .html filename arguments found ... giving up");
 
1159
      return 1;
 
1160
    }
 
1161
 
 
1162
  /*
 
1163
   * 5) Start with "source files".. for each one (hereafter called a
 
1164
   *    "header file"):
 
1165
   *    a) Parse declarations (in .h or .m/.c) using an AGSParser object.
 
1166
   *    b) Determine (possibly multiple) dependent .m/.c files corresponding to
 
1167
   *       a .h and parse them.
 
1168
   *    c) Feed parser results to an AGSOutput instance.
 
1169
   */
513
1170
  count = [sFiles count];
514
1171
  if (count > 0)
515
1172
    {
519
1176
 
520
1177
      up = [defs stringForKey: @"Up"];
521
1178
 
 
1179
#if GS_WITH_GC == 0
522
1180
      pool = [NSAutoreleasePool new];
 
1181
#endif
523
1182
 
524
1183
      parser = [AGSParser new];
525
1184
      [parser setWordMap: [defs dictionaryForKey: @"WordMap"]];
526
 
      [parser setVerbose: verbose];
527
1185
      output = [AGSOutput new];
528
1186
      if ([defs boolForKey: @"Standards"] == YES)
529
1187
        {
533
1191
        {
534
1192
          [parser setDocumentAllInstanceVariables: YES];
535
1193
        }
 
1194
      if ([defs objectForKey: @"DocumentInstanceVariables"] != nil
 
1195
          && [defs boolForKey: @"DocumentInstanceVariables"] == NO)
 
1196
        {
 
1197
          [parser setDocumentInstanceVariables: NO];
 
1198
        }
536
1199
 
537
1200
      for (i = 0; i < count; i++)
538
1201
        {
539
 
          NSString      *hfile = [sFiles objectAtIndex: i];
540
 
          NSString      *gsdocfile;
541
 
          NSString      *file;
542
 
          NSArray       *a;
543
 
          NSDictionary  *attrs;
544
 
          NSDate        *sDate = nil;
545
 
          NSDate        *gDate = nil;
546
 
          unsigned      i;
 
1202
          NSString              *hfile = [sFiles objectAtIndex: i];
 
1203
          NSString              *gsdocfile;
 
1204
          NSString              *file;
 
1205
          NSMutableArray        *a;
 
1206
          NSDictionary          *attrs;
 
1207
          NSDate                *sDate = nil;
 
1208
          NSDate                *gDate = nil;
 
1209
          unsigned              j;
547
1210
 
 
1211
#if GS_WITH_GC == 0
548
1212
          if (pool != nil)
549
1213
            {
550
1214
              RELEASE(pool);
551
1215
              pool = [NSAutoreleasePool new];
552
1216
            }
 
1217
#endif
553
1218
 
554
1219
          /*
555
1220
           * Note the name of the header file without path or extension.
556
 
           * This will be used to generate the outut file.
 
1221
           * This will be used to generate the output file.
557
1222
           */
558
1223
          file = [hfile stringByDeletingPathExtension];
559
1224
          file = [file lastPathComponent];
560
1225
 
561
1226
          /*
562
1227
           * Ensure that header file name is set up using the
563
 
           * header directory specified unless is is absolute.
 
1228
           * header directory specified unless it is absolute.
564
1229
           */
565
1230
          if ([hfile isAbsolutePath] == NO)
566
1231
            {
567
 
              if ([[hfile pathExtension] isEqual: @"h"] == YES)
 
1232
              if ([headerDirectory length] > 0
 
1233
                && [[hfile pathExtension] isEqual: @"h"] == YES)
568
1234
                {
569
 
                  if ([headerDirectory length] > 0)
570
 
                    {
571
 
                      hfile = [headerDirectory stringByAppendingPathComponent:
572
 
                        [hfile lastPathComponent]];
573
 
                    }
 
1235
                  hfile = [headerDirectory stringByAppendingPathComponent:
 
1236
                    hfile];
574
1237
                }
575
1238
            }
576
1239
 
582
1245
            {
583
1246
              NSDate    *d;
584
1247
 
585
 
              attrs = [mgr fileAttributesAtPath: hfile
586
 
                                   traverseLink: YES];
587
 
              d = [attrs objectForKey: NSFileModificationDate];
588
 
              if (sDate == nil || [d earlierDate: sDate] == sDate)
589
 
                {
590
 
                  sDate = d;
591
 
                  AUTORELEASE(RETAIN(sDate));
592
 
                }
593
1248
              /*
594
1249
               * Ask existing project info (.gsdoc file) for dependency
595
 
               * information.  Then check the dates on the source files.
 
1250
               * information.  Then check the dates on the source files
 
1251
               * and the header file.
596
1252
               */
597
1253
              a = [projectRefs sourcesForHeader: hfile];
598
 
              for (i = 0; i < [a count]; i++)
 
1254
              [a insertObject: hfile atIndex: 0];
 
1255
              for (j = 0; j < [a count]; j++)
599
1256
                {
600
 
                  NSString      *sfile = [a objectAtIndex: i];
 
1257
                  NSString      *sfile = [a objectAtIndex: j];
601
1258
 
602
1259
                  attrs = [mgr fileAttributesAtPath: sfile
603
1260
                                       traverseLink: YES];
604
 
                  d = [attrs objectForKey: NSFileModificationDate];
 
1261
                  d = [attrs fileModificationDate];
605
1262
                  if (sDate == nil || [d earlierDate: sDate] == sDate)
606
1263
                    {
607
1264
                      sDate = d;
608
1265
                      AUTORELEASE(RETAIN(sDate));
609
1266
                    }
610
1267
                }
611
 
 
612
 
              attrs = [mgr fileAttributesAtPath: gsdocfile traverseLink: YES];
613
 
              gDate = [attrs objectForKey: NSFileModificationDate];
614
 
              AUTORELEASE(RETAIN(gDate));
 
1268
              if (verbose == YES)
 
1269
                {
 
1270
                  NSLog(@"Saved sources for %@ are %@ ... %@", hfile, a, sDate);
 
1271
                }
 
1272
 
 
1273
              /*
 
1274
               * Ask existing project info (.gsdoc file) for dependency
 
1275
               * information.  Then check the dates on the output files.
 
1276
               * If none are set, assume the defualt.
 
1277
               */
 
1278
              a = [projectRefs outputsForHeader: hfile];
 
1279
              if ([a count] == 0)
 
1280
                {
 
1281
                  [a insertObject: gsdocfile atIndex: 0];
 
1282
                }
 
1283
              for (j = 0; j < [a count]; j++)
 
1284
                {
 
1285
                  NSString      *ofile = [a objectAtIndex: j];
 
1286
 
 
1287
                  attrs = [mgr fileAttributesAtPath: ofile traverseLink: YES];
 
1288
                  d = [attrs fileModificationDate];
 
1289
                  if (gDate == nil || [d laterDate: gDate] == gDate)
 
1290
                    {
 
1291
                      gDate = d;
 
1292
                      AUTORELEASE(RETAIN(gDate));
 
1293
                    }
 
1294
                }
 
1295
              if (verbose == YES)
 
1296
                {
 
1297
                  NSLog(@"Saved outputs for %@ are %@ ... %@", hfile, a, gDate);
 
1298
                }
615
1299
            }
616
1300
 
617
1301
          if (gDate == nil || [sDate earlierDate: gDate] == gDate)
627
1311
 
628
1312
              /*
629
1313
               * Try to parse header to see what needs documenting.
630
 
               * If the header given was actually a .m file, this will
 
1314
               * If the header given was actually a .m/.c file, this will
631
1315
               * parse that file for declarations rather than definitions.
632
1316
               */
633
1317
              if ([mgr isReadableFileAtPath: hfile] == NO)
643
1327
                }
644
1328
              [parser parseFile: hfile isSource: NO];
645
1329
 
646
 
              a = [parser source];
647
1330
              /*
648
1331
               * Record dependency information.
649
1332
               */
 
1333
              a = [parser outputs];
 
1334
              if ([a count] > 0)
 
1335
                {
 
1336
                  /*
 
1337
                   * Adjust the location of the output files to be in the
 
1338
                   * documentation directory.
 
1339
                   */
 
1340
                  for (j = 0; j < [a count]; j++)
 
1341
                    {
 
1342
                      NSString  *s = [a objectAtIndex: j];
 
1343
 
 
1344
                      if ([s isAbsolutePath] == NO)
 
1345
                        {
 
1346
                          s = [documentationDirectory
 
1347
                            stringByAppendingPathComponent: s];
 
1348
                          [a replaceObjectAtIndex: j withObject: s];
 
1349
                        }
 
1350
                    }
 
1351
                  if (verbose == YES)
 
1352
                    {
 
1353
                      NSLog(@"Computed outputs for %@ are %@", hfile, a);
 
1354
                    }
 
1355
                  [projectRefs setOutputs: a forHeader: hfile];
 
1356
                }
 
1357
              a = [parser sources];
650
1358
              if ([a count] > 0)
651
1359
                {
652
1360
                  [projectRefs setSources: a forHeader: hfile];
653
1361
                }
 
1362
              if (verbose == YES)
 
1363
                {
 
1364
                  NSLog(@"Computed sources for %@ are %@", hfile, a);
 
1365
                }
654
1366
 
655
 
              for (i = 0; i < [a count]; i++)
 
1367
              for (j = 0; j < [a count]; j++)
656
1368
                {
657
 
                  NSString      *sfile = [a objectAtIndex: i];
 
1369
                  NSString      *sfile = [a objectAtIndex: j];
658
1370
 
659
1371
                  /*
660
1372
                   * If we can read a source file, parse it for any
679
1391
 
680
1392
              /*
681
1393
               * Only produce linkage if the up link is not empty.
682
 
               * Don't add an up link if this *is* the up link document.
 
1394
               * Do not add an up link if this *is* the up link document.
683
1395
               */
684
1396
              if ([up length] > 0 && [up isEqual: file] == NO)
685
1397
                {
710
1422
          else
711
1423
            {
712
1424
              /*
713
 
               * Add the gsdoc file corresponding to the .h file to the list of
714
 
               * those to process.
 
1425
               * Add the .h file to the list of those to process.
715
1426
               */
716
 
              [gFiles addObject: [gsdocfile lastPathComponent]];
 
1427
              [gFiles addObject: [hfile lastPathComponent]];
717
1428
            }
718
1429
        }
 
1430
      informalProtocols = RETAIN([output informalProtocols]);
 
1431
#if GS_WITH_GC == 0
719
1432
      DESTROY(pool);
 
1433
#endif
720
1434
      DESTROY(parser);
721
1435
      DESTROY(output);
722
1436
    }
723
1437
 
 
1438
  /*
 
1439
   * 6) Now move to "gsdoc files" (including both command-line given ones and
 
1440
   *    just-generated ones).. and generate the index.
 
1441
   *
 
1442
   */
724
1443
  count = [gFiles count];
725
1444
  if (count > 0)
726
1445
    {
735
1454
          NSDictionary  *attrs;
736
1455
          NSDate        *gDate = nil;
737
1456
 
 
1457
#if GS_WITH_GC == 0
738
1458
          if (arp != nil)
739
1459
            {
740
1460
              RELEASE(arp);
741
1461
              arp = [NSAutoreleasePool new];
742
1462
            }
 
1463
#endif
 
1464
          /*
 
1465
           * 6a) Chop off any path specification that might be there (for files
 
1466
           *     given on the command line) and search for the file only in
 
1467
           *     'DocumentationDirectory' or the CWD (which is assumed to be
 
1468
           *     the directory with the source files, though this will not be
 
1469
           *     true if path information was given for them on the command
 
1470
           *     line).
 
1471
           */
743
1472
          file = [[arg lastPathComponent] stringByDeletingPathExtension];
744
1473
 
745
1474
          gsdocfile = [documentationDirectory
747
1476
          gsdocfile = [gsdocfile stringByAppendingPathExtension: @"gsdoc"];
748
1477
 
749
1478
          /*
750
 
           * Our source file is a gsdoc file ... so it may be located
 
1479
           * If our source file is a gsdoc file ... it may be located
751
1480
           * in the current (input) directory rather than the documentation
752
1481
           * (output) directory.
753
1482
           */
758
1487
          if (ignoreDependencies == NO)
759
1488
            {
760
1489
              attrs = [mgr fileAttributesAtPath: gsdocfile traverseLink: YES];
761
 
              gDate = [attrs objectForKey: NSFileModificationDate];
 
1490
              gDate = [attrs fileModificationDate];
762
1491
              AUTORELEASE(RETAIN(gDate));
763
1492
            }
764
1493
 
765
1494
          /*
766
 
           * Now we try to process the gsdoc data to make index info
767
 
           * unless the project index is already more up to date than
768
 
           * this file.
 
1495
           * 6b) Now we try to process the gsdoc data to make index info
 
1496
           *     unless the project index is already more up to date than
 
1497
           *     this file (or the gsdoc file does not exist of course).
769
1498
           */
770
 
          if (gDate == nil || [gDate earlierDate: rDate] == rDate)
 
1499
          if (gDate != nil && [gDate earlierDate: rDate] == rDate)
771
1500
            {
772
1501
              if (showDependencies == YES)
773
1502
                {
776
1505
                }
777
1506
              if ([mgr isReadableFileAtPath: gsdocfile] == YES)
778
1507
                {
 
1508
                  GSXMLNode     *root;
779
1509
                  GSXMLParser   *parser;
780
1510
                  AGSIndex      *localRefs;
781
1511
 
 
1512
                  // This parses the file for index info
782
1513
                  parser = [GSXMLParser parserWithContentsOfFile: gsdocfile];
783
 
                  [parser substituteEntities: NO];
784
1514
                  [parser doValidityChecking: YES];
785
1515
                  [parser keepBlanks: NO];
 
1516
                  [parser substituteEntities: NO];
786
1517
                  if ([parser parse] == NO)
787
1518
                    {
788
1519
                      NSLog(@"WARNING %@ is not a valid document", gsdocfile);
789
1520
                    }
790
 
                  if (![[[[parser doc] root] name] isEqualToString: @"gsdoc"])
 
1521
                  root = [[parser document] root];
 
1522
                  if (![[root name] isEqualToString: @"gsdoc"])
791
1523
                    {
792
1524
                      NSLog(@"not a gsdoc document - because name node is %@",
793
 
                        [[[parser doc] root] name]);
 
1525
                        [root name]);
794
1526
                      return 1;
795
1527
                    }
796
1528
 
797
1529
                  localRefs = AUTORELEASE([AGSIndex new]);
798
 
                  [localRefs makeRefs: [[parser doc] root]];
 
1530
                  // This is the main call that computes index information
 
1531
                  [localRefs makeRefs: root];
799
1532
 
800
1533
                  /*
801
1534
                   * accumulate index info in project references
804
1537
                }
805
1538
              else
806
1539
                {
807
 
                  NSLog(@"No readable documentation at '%@' ... skipping",
 
1540
                  NSLog(@"File '%@' not found in $DocumentationDirectory or '.' ... skipping indexing",
808
1541
                    gsdocfile);
809
1542
                }
810
1543
            }
811
1544
        }
 
1545
      if (informalProtocols != nil) {
 
1546
          [projectRefs addInformalProtocols: informalProtocols];
 
1547
          DESTROY(informalProtocols);
 
1548
      }
 
1549
#if GS_WITH_GC == 0
812
1550
      DESTROY(arp);
 
1551
#endif
813
1552
 
814
1553
      /*
815
 
       * Save project references if they have been modified.
 
1554
       * 7) Save project references if they have been modified
 
1555
       *    (into an .igsdoc file named for the project).
816
1556
       */
817
1557
      projectIndex = [projectRefs refs];
818
1558
      if (projectIndex != nil && [originalIndex isEqual: projectIndex] == NO)
826
1566
    }
827
1567
 
828
1568
  globalRefs = [AGSIndex new];
829
 
  
 
1569
 
830
1570
  /*
831
 
   * If we are either generating html output, or relocating existing
832
 
   * html documents, we must build up the indexing information needed
833
 
   * for any cross-referencing etc.
 
1571
   * 8) If we are either generating html output, or relocating existing
 
1572
   *    html documents, we must build up the indexing information needed
 
1573
   *    for any cross-referencing etc..  This comes from the "xxxProjects"
 
1574
   *    defaults.  Each of these is used to find a project directory, in
 
1575
   *    which an .igsdoc index cache file is searched for.  If found, its
 
1576
   *    contents are read in and merged with the current project (but NOT
 
1577
   *    merged into its index file).
834
1578
   */
835
1579
  if (generateHtml == YES || [hFiles count] > 0)
836
1580
    {
837
1581
      NSMutableDictionary       *projects;
838
1582
      NSString                  *systemProjects;
839
1583
      NSString                  *localProjects;
840
 
 
841
 
      pool = [NSAutoreleasePool new];
 
1584
      CREATE_AUTORELEASE_POOL (pool);
842
1585
 
843
1586
      localProjects = [defs stringForKey: @"LocalProjects"];
844
1587
      if (localProjects == nil)
854
1597
      AUTORELEASE(projects);
855
1598
 
856
1599
      /*
857
 
       * Merge any external project references into the
858
 
       * main cross reference index.
 
1600
       * Merge any system project references.
859
1601
       */
860
1602
      if ([systemProjects caseInsensitiveCompare: @"None"] != NSOrderedSame)
861
1603
        {
876
1618
                {
877
1619
                  NSString      *ext = [file pathExtension];
878
1620
 
879
 
                  if ([ext isEqualToString: @"igsdoc"] == YES)
 
1621
                  if ([ext isEqualToString: @"igsdoc"] == YES
 
1622
                    && [[file lastPathComponent] isEqual: refsName] == NO)
880
1623
                    {
881
1624
                      NSString  *key;
882
1625
                      NSString  *val;
895
1638
            }
896
1639
        }
897
1640
 
 
1641
      /*
 
1642
       * Merge any local project references.
 
1643
       */
898
1644
      if ([localProjects caseInsensitiveCompare: @"None"] != NSOrderedSame)
899
1645
        {
900
1646
          NSString      *base = [NSSearchPathForDirectoriesInDomains(
914
1660
              while ((file = [enumerator nextObject]) != nil)
915
1661
                {
916
1662
                  NSString      *ext = [file pathExtension];
 
1663
                
917
1664
 
918
 
                  if ([ext isEqualToString: @"igsdoc"] == YES)
 
1665
                  if ([ext isEqualToString: @"igsdoc"] == YES
 
1666
                    && [[file lastPathComponent] isEqual: refsName] == NO)
919
1667
                    {
920
1668
                      NSString  *key;
921
1669
                      NSString  *val;
933
1681
            }
934
1682
        }
935
1683
 
 
1684
      /*
 
1685
       * Merge any "plain project" references.
 
1686
       */
936
1687
      if (projects != nil)
937
1688
        {
938
1689
          NSEnumerator  *e = [projects keyEnumerator];
983
1734
       */
984
1735
      [globalRefs mergeRefs: [projectRefs refs] override: YES];
985
1736
 
 
1737
#if GS_WITH_GC == 0
986
1738
      RELEASE(pool);
987
 
    }
988
 
 
989
 
  /*
990
 
   * Next pass ... generate html output from gsdoc files if required.
 
1739
#endif
 
1740
    }
 
1741
 
 
1742
  /*
 
1743
   * 9) If we are generating HTML frames, create the gsdoc files specifying
 
1744
   *      indices that we will use.
 
1745
   */
 
1746
  if ([defs boolForKey: @"MakeFrames"] == YES)
 
1747
    {
 
1748
      int i;
 
1749
      int cap = 1360;
 
1750
      NSArray           *idxTypes = [NSArray arrayWithObjects:
 
1751
                                               @"class",
 
1752
                                             @"protocol",
 
1753
                                             @"constant",
 
1754
                                             @"function",
 
1755
                                             @"macro",
 
1756
                                             @"type",
 
1757
                                             @"variable",
 
1758
                                             @"tool",
 
1759
                                             nil];
 
1760
      NSString          *idxIndexFile;
 
1761
      NSMutableString   *idxIndex= [NSMutableString stringWithCapacity: 5*cap];
 
1762
      NSString          *framesetFile;
 
1763
      NSMutableString   *frameset = [NSMutableString stringWithCapacity: cap];
 
1764
      NSMutableString   *tocSkel = [NSMutableString stringWithCapacity: cap];
 
1765
      NSString          *prjFile =
 
1766
        [NSString stringWithFormat: @"%@.gsdoc",project];
 
1767
 
 
1768
      // skeleton for table of contents files
 
1769
      [tocSkel setString: @"<?xml version=\"1.0\"?>\n"
 
1770
@"<!DOCTYPE gsdoc PUBLIC \"-//GNUstep//DTD gsdoc 1.0.1//EN\" \"http://www.gnustep.org/gsdoc-1_0_1.xml\">\n"
 
1771
@"<gsdoc base=\"[typeU]\" stylesheeturl=\"gsdoc_contents\">\n"
 
1772
@"  <head>\n"
 
1773
@"    <title>[typeU]</title>\n"
 
1774
@"  </head>\n"
 
1775
@"  <body>\n"
 
1776
@"    <chapter>\n"
 
1777
@"      <index type=\"[typeL]\" scope=\"project\" target=\"mainFrame\"\n"
 
1778
@"             style=\"bare\" />\n"
 
1779
@"    </chapter>\n"
 
1780
@"  </body>\n"
 
1781
@"</gsdoc>\n"];
 
1782
      [tocSkel replaceString: @"[prjName]" withString: project];
 
1783
 
 
1784
      // file for top-left frame (header only; rest appended below)
 
1785
      idxIndexFile = [@"MainIndex" stringByAppendingPathExtension: @"html"];
 
1786
      [idxIndex setString: @"<HTML>\n  <BODY>\n"
 
1787
@"    <FONT FACE=\"sans\" SIZE=\"+1\"><B>Index</B></FONT><BR/><BR/>\n"
 
1788
@"    <FONT FACE=\"sans\" SIZE=\"-1\">"];
 
1789
 
 
1790
      // this becomes index.html
 
1791
      framesetFile = [@"index" stringByAppendingPathExtension: @"html"];
 
1792
      [frameset setString: @"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n"
 
1793
@"<HTML>\n"
 
1794
@"  <HEAD>\n"
 
1795
@"  <TITLE>\n"
 
1796
@"    Autogsdoc-generated Documentation for [prjName]\n"
 
1797
@"  </TITLE>\n"
 
1798
@"  </HEAD>\n"
 
1799
@"  <FRAMESET cols=\"20%,80%\">\n"
 
1800
@"    <FRAMESET rows=\"30%,70%\">\n"
 
1801
@"      <FRAME src=\"MainIndex.html\" name=\"packageListFrame\">\n"
 
1802
@"      <FRAME src=\"ClassesTOC.html\" name=\"packageFrame\">\n"
 
1803
@"    </FRAMESET>\n"
 
1804
@"    <FRAME src=\"[prjName].html\" name=\"mainFrame\">\n"
 
1805
@"  </FRAMESET>\n"
 
1806
@"</HTML>\n"];
 
1807
      [frameset replaceString: @"[prjName]" withString: project];
 
1808
 
 
1809
      // generate the table of contents gsdoc files
 
1810
      for (i = 0; i < [idxTypes count]; i++)
 
1811
        {
 
1812
          NSString              *gsdocFile;
 
1813
          NSString              *htmlFile;
 
1814
          NSMutableString       *contents;
 
1815
          NSString              *typeL = [idxTypes objectAtIndex: i];
 
1816
          NSString              *typeU = [typeL capitalizedString];
 
1817
 
 
1818
          contents = [NSMutableString stringWithCapacity: cap];
 
1819
          [contents setString: tocSkel];
 
1820
          typeU = [@"Class" isEqualToString: typeU] ?
 
1821
            [typeU stringByAppendingString: @"es"] :
 
1822
            [typeU stringByAppendingString: @"s"];
 
1823
          [contents replaceString: @"[typeL]" withString: typeL];
 
1824
          [contents replaceString: @"[typeU]" withString: typeU];
 
1825
          gsdocFile = [[typeU stringByAppendingString: @"TOC"]
 
1826
                       stringByAppendingPathExtension: @"gsdoc"];
 
1827
          htmlFile = [[typeU stringByAppendingString: @"TOC"]
 
1828
                       stringByAppendingPathExtension: @"html"];
 
1829
 
 
1830
          if ([[projectRefs refs] objectForKey: typeL] != nil)
 
1831
            {
 
1832
              [contents writeToFile:
 
1833
                  [documentationDirectory stringByAppendingPathComponent:
 
1834
                                            gsdocFile]
 
1835
                         atomically: YES];
 
1836
              [gFiles addObject: gsdocFile];
 
1837
              [idxIndex appendFormat:
 
1838
                  @"    <A HREF=\"%@\" TARGET=\"packageFrame\">%@</A><BR/>\n",
 
1839
                        htmlFile, typeU];
 
1840
            }
 
1841
        }
 
1842
 
 
1843
      [idxIndex appendString: @"    <BR/>\n"];
 
1844
      [idxIndex appendFormat:
 
1845
        @"    (<A HREF=\"%@.html\" TARGET=\"mainFrame\">intro</A>)&nbsp;",
 
1846
        project];
 
1847
      [idxIndex appendFormat:
 
1848
        @"&nbsp;(<A HREF=\"%@.html\" TARGET=\"_top\">unframe</A>)\n",
 
1849
        project];
 
1850
      [idxIndex appendString: @"    </FONT>\n  </BODY>\n</HTML>\n"];
 
1851
      [idxIndex writeToFile:
 
1852
        [documentationDirectory stringByAppendingPathComponent: idxIndexFile]
 
1853
                 atomically: YES];
 
1854
 
 
1855
      [frameset writeToFile:
 
1856
        [documentationDirectory stringByAppendingPathComponent: framesetFile]
 
1857
                 atomically: YES];
 
1858
 
 
1859
      // it is possible that <project>.gsdoc does not exist; if that is the
 
1860
      // case, generate one now as a placeholder
 
1861
      for (i = 0; i < [gFiles count]; i++)
 
1862
        {
 
1863
          NSString      *fname = [gFiles objectAtIndex: i];
 
1864
          if ([fname rangeOfString: prjFile].length > 0)
 
1865
              break;
 
1866
        }
 
1867
      if (i == [gFiles count])
 
1868
        {
 
1869
          NSMutableString       *prjFileContents =
 
1870
            [NSMutableString stringWithCapacity: cap];
 
1871
          NSLog(@"\n\nNOTE: Generating a simple introductory page for your"
 
1872
@" project.\nTo replace this with a custom version, edit the gsdoc file \n"
 
1873
@"named %@ in the documentation output directory.\n"
 
1874
@"Then include this file in the arguments to autogsdoc.\n\n", prjFile);
 
1875
          [prjFileContents setString: @"<?xml version=\"1.0\"?>\n"
 
1876
@"<!DOCTYPE gsdoc PUBLIC \"-//GNUstep//DTD gsdoc 1.0.1//EN\" \"http://www.gnustep.org/gsdoc-1_0_1.xml\">\n"
 
1877
@"<gsdoc base=\"[prjName]\">\n"
 
1878
@"  <head>\n"
 
1879
@"    <title>The [prjName] Project</title>\n"
 
1880
@"  </head>\n"
 
1881
@"  <body>\n"
 
1882
@"    <chapter>\n"
 
1883
@"      <p>The index below lists the major components of the [prjName] \n"
 
1884
@"         documentation.<br/></p>\n"
 
1885
@"      <index type=\"title\" scope=\"project\" target=\"mainFrame\" />\n"
 
1886
@"    </chapter>\n"
 
1887
@"  </body>\n"
 
1888
@"</gsdoc>\n"];
 
1889
          [prjFileContents replaceString: @"[prjName]" withString: project];
 
1890
          [prjFileContents writeToFile:
 
1891
            [documentationDirectory stringByAppendingPathComponent: prjFile]
 
1892
                            atomically: YES];
 
1893
          [gFiles addObject: prjFile];
 
1894
        }
 
1895
    }
 
1896
 
 
1897
 
 
1898
  /*
 
1899
   * 10) Next pass ... generate html output from gsdoc files if required.
991
1900
   */
992
1901
  count = [gFiles count];
993
1902
  if (generateHtml == YES && count > 0)
994
1903
    {
 
1904
#if GS_WITH_GC == 0
995
1905
      pool = [NSAutoreleasePool new];
 
1906
#endif
996
1907
 
997
1908
      for (i = 0; i < count; i++)
998
1909
        {
1005
1916
          NSDate        *gDate = nil;
1006
1917
          NSDate        *hDate = nil;
1007
1918
 
 
1919
#if GS_WITH_GC == 0
1008
1920
          if (pool != nil)
1009
1921
            {
1010
1922
              RELEASE(pool);
1011
1923
              pool = [NSAutoreleasePool new];
1012
1924
            }
 
1925
#endif
 
1926
          /*
 
1927
           * 10a) As before in connection with (6a), drop path information
 
1928
           *      and look for gsdoc files in 'documentationDirectory' or
 
1929
           *      CWD.
 
1930
           */
1013
1931
          file = [[arg lastPathComponent] stringByDeletingPathExtension];
1014
1932
 
1015
1933
          gsdocfile = [documentationDirectory
1036
1954
               * When were the files last modified?
1037
1955
               */
1038
1956
              attrs = [mgr fileAttributesAtPath: gsdocfile traverseLink: YES];
1039
 
              gDate = [attrs objectForKey: NSFileModificationDate];
 
1957
              gDate = [attrs fileModificationDate];
1040
1958
              AUTORELEASE(RETAIN(gDate));
1041
1959
              attrs = [mgr fileAttributesAtPath: htmlfile traverseLink: YES];
1042
 
              hDate = [attrs objectForKey: NSFileModificationDate];
 
1960
              hDate = [attrs fileModificationDate];
1043
1961
              AUTORELEASE(RETAIN(hDate));
1044
1962
            }
1045
1963
 
1047
1965
            {
1048
1966
              if (hDate == nil || [gDate earlierDate: hDate] == hDate)
1049
1967
                {
 
1968
                  NSData        *d;
 
1969
                  GSXMLNode     *root;
1050
1970
                  GSXMLParser   *parser;
1051
1971
                  AGSIndex      *localRefs;
1052
1972
                  AGSHtml       *html;
1056
1976
                      NSLog(@"%@: gsdoc %@, html %@ ==> regenerate",
1057
1977
                        file, gDate, hDate);
1058
1978
                    }
 
1979
                  // 10b) parse the .gsdoc file
1059
1980
                  parser = [GSXMLParser parserWithContentsOfFile: gsdocfile];
1060
 
                  [parser substituteEntities: NO];
1061
1981
                  [parser doValidityChecking: YES];
1062
1982
                  [parser keepBlanks: NO];
 
1983
                  [parser substituteEntities: NO];
1063
1984
                  if ([parser parse] == NO)
1064
1985
                    {
1065
1986
                      NSLog(@"WARNING %@ is not a valid document", gsdocfile);
1066
1987
                    }
1067
 
                  if (![[[[parser doc] root] name] isEqualToString: @"gsdoc"])
 
1988
                  root = [[parser document] root];
 
1989
                  if (![[root name] isEqualToString: @"gsdoc"])
1068
1990
                    {
1069
1991
                      NSLog(@"not a gsdoc document - because name node is %@",
1070
 
                        [[[parser doc] root] name]);
 
1992
                        [root name]);
1071
1993
                      return 1;
1072
1994
                    }
1073
1995
 
1074
1996
                  localRefs = AUTORELEASE([AGSIndex new]);
1075
 
                  [localRefs makeRefs: [[parser doc] root]];
 
1997
                  [localRefs makeRefs: root];
1076
1998
 
1077
1999
                  /*
1078
 
                   * We perform final output
 
2000
                   * 10c) Feed the XML tree to an AGSHtml instance, and dump
 
2001
                   *      the result to a file.
1079
2002
                   */
1080
2003
                  html = AUTORELEASE([AGSHtml new]);
1081
2004
                  [html setGlobalRefs: globalRefs];
1082
2005
                  [html setProjectRefs: projectRefs];
1083
2006
                  [html setLocalRefs: localRefs];
1084
 
                  generated = [html outputDocument: [[parser doc] root]];
1085
 
                  if ([generated writeToFile: htmlfile atomically: YES] == NO)
 
2007
                  [html setInstanceVariablesAtEnd: instanceVarsAtEnd];
 
2008
                  generated = [html outputDocument: root];
 
2009
                  d = [generated dataUsingEncoding: NSUTF8StringEncoding];
 
2010
                  if ([d writeToFile: htmlfile atomically: YES] == NO)
1086
2011
                    {
1087
2012
                      NSLog(@"Sorry unable to write %@", htmlfile);
1088
2013
                    }
1089
2014
                }
1090
2015
            }
1091
 
          else
 
2016
          else if ([arg hasSuffix: @".gsdoc"] == YES)
1092
2017
            {
1093
 
              NSLog(@"No readable documentation at '%@' ... skipping",
 
2018
              NSLog(@"File '%@' not found in $DocumentationDirectory or '.' ... skipping",
1094
2019
                gsdocfile);
1095
2020
            }
1096
2021
        }
 
2022
#if GS_WITH_GC == 0
1097
2023
      RELEASE(pool);
 
2024
#endif
1098
2025
    }
1099
2026
 
1100
2027
  /*
1101
 
   * Relocate existing html documents if required ... adjust all cross
1102
 
   * referencing within those documents.
 
2028
   * 11) Relocate existing html documents if required ... adjust all cross
 
2029
   *     referencing within those documents.  This entails searching for
 
2030
   *     <a rel="..." href="..."> links, parsing the key, and replacing the
 
2031
   *     contents as per our current index info (which may have changed).
1103
2032
   */
1104
2033
  count = [hFiles count];
1105
2034
  if (count > 0)
1106
2035
    {
 
2036
#if GS_WITH_GC == 0
1107
2037
      pool = [NSAutoreleasePool new];
 
2038
#endif
1108
2039
 
1109
2040
      for (i = 0; i < count; i++)
1110
2041
        {
1112
2043
          NSString      *src;
1113
2044
          NSString      *dst;
1114
2045
 
 
2046
#if GS_WITH_GC == 0
1115
2047
          if (pool != nil)
1116
2048
            {
1117
2049
              RELEASE(pool);
1118
2050
              pool = [NSAutoreleasePool new];
1119
2051
            }
 
2052
#endif
 
2053
 
1120
2054
          file = [file lastPathComponent];
1121
2055
 
1122
2056
          src = file;
1145
2079
              [html setGlobalRefs: globalRefs];
1146
2080
              [html setProjectRefs: projectRefs];
1147
2081
              [html setLocalRefs: nil];
 
2082
              [html setInstanceVariablesAtEnd: instanceVarsAtEnd];
1148
2083
 
1149
2084
              s = [NSMutableString stringWithContentsOfFile: src];
1150
2085
              l = [s length];
1280
2215
              d = [s dataUsingEncoding: NSUTF8StringEncoding];
1281
2216
              [d writeToFile: dst atomically: YES];
1282
2217
            }
1283
 
          else
 
2218
          else if ([file hasSuffix: @".gsdoc"] == YES)
1284
2219
            {
1285
2220
              NSLog(@"No readable documentation at '%@' ... skipping", src);
1286
2221
            }
 
2222
          else
 
2223
            {
 
2224
              NSLog(@"Type of file '%@' unrecognized ... skipping", src);
 
2225
            }
1287
2226
        }
 
2227
#if GS_WITH_GCC == 0
1288
2228
      RELEASE(pool);
 
2229
#endif
 
2230
    }
 
2231
 
 
2232
  /*
 
2233
   * 12) If MakeDependencies was requested, list all header and source files
 
2234
   *     as colon-dependencies of the project name.
 
2235
   */
 
2236
  if ([defs stringForKey: @"MakeDependencies"] != nil)
 
2237
    {
 
2238
      NSString          *stamp = [defs stringForKey: @"MakeDependencies"];
 
2239
      NSMutableSet      *mset = [NSMutableSet setWithCapacity: 128];
 
2240
      NSDictionary      *files = [[projectRefs  refs] objectForKey: @"source"];
 
2241
      NSEnumerator      *enumerator = [files keyEnumerator];
 
2242
      NSString          *file;
 
2243
      NSMutableString   *depend;
 
2244
 
 
2245
      /*
 
2246
       * Build set of all header and source files used in project.
 
2247
       */
 
2248
      while ((file = [enumerator nextObject]) != nil)
 
2249
        {
 
2250
          [mset addObject: file];
 
2251
          [mset addObjectsFromArray: [files objectForKey: file]];
 
2252
        }
 
2253
 
 
2254
      enumerator = [mset objectEnumerator];
 
2255
      depend = [NSMutableString stringWithFormat: @"%@:", stamp];
 
2256
      while ((file = [enumerator nextObject]) != nil)
 
2257
        {
 
2258
          [depend appendFormat: @" \\\n\t%@", file];
 
2259
        }
 
2260
 
 
2261
      file = [stamp stringByDeletingLastPathComponent];
 
2262
      if ([file length]> 0 && [mgr fileExistsAtPath: file] == NO)
 
2263
        {
 
2264
          [mgr createDirectoryAtPath: file attributes: nil];
 
2265
        }
 
2266
      [depend writeToFile: stamp atomically: YES];
1289
2267
    }
1290
2268
 
1291
2269
  RELEASE(outer);
1292
2270
  return 0;
1293
2271
}
1294