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

« back to all changes in this revision

Viewing changes to Tools/AGSOutput.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:
21
21
   */
22
22
 
23
23
#include "AGSOutput.h"
 
24
#include "GNUstepBase/GNUstep.h"
 
25
#include "GNUstepBase/GSCategories.h"
24
26
 
25
27
@interface AGSOutput (Private)
26
28
- (NSString*) mergeMarkup: (NSString*)markup
69
71
 *  far too special purpose.</p>
70
72
 *  <unit />
71
73
 *  <p>Here is the afterword for the class.</p>
 
74
 *  <p> And here is some automated cross referencing ...
 
75
 *  A method in a protocol: [(NSCopying)-copyWithZone:], a class:
 
76
 *  [NSString], a protocol: [(NSCopying)], and a
 
77
 *  category: [NSRunLoop(GNUstepExtensions)].
 
78
 *  </p>
72
79
 * </unit>
73
80
 * And finally, here is the actual class description ... outside the chapter.
 
81
 * This is the class description for <code>AGSOutput</code>, including some
 
82
 * sample uses of GSDoc, such as cross-references (see [NSString]).
 
83
 * Functions, like escapeType(), are automatically referenced (if they are
 
84
 * found).
74
85
 */
75
86
@implementation AGSOutput
76
87
 
77
 
+ (void) initialize
 
88
- (NSString*) checkComment: (NSString*)comment
 
89
                      unit: (NSString*)unit
 
90
                      info: (NSDictionary*)d
78
91
{
79
 
  NSUserDefaults        *ud = [NSUserDefaults standardUserDefaults];
 
92
  if ([comment length] == 0)
 
93
    {
 
94
      comment = @"<em>Description forthcoming.</em>";
 
95
      if (warn == YES)
 
96
        {
 
97
          NSString      *name = [d objectForKey: @"Name"];
 
98
          NSString      *type = [d objectForKey: @"Type"];
80
99
 
81
 
  [ud registerDefaults: [NSDictionary dictionaryWithObjectsAndKeys:
82
 
    @"TypesAndConstants", @"ConstantsTemplate",
83
 
    @"Functions", @"FunctionsTemplate",
84
 
    @"TypesAndConstants", @"TypedefsTemplate",
85
 
    @"TypesAndConstants", @"VariablesTemplate",
86
 
    nil]];
 
100
          if (unit == nil)
 
101
            {
 
102
              if (type == nil)
 
103
                {
 
104
                  NSLog(@"Warning - No comments for %@", name);
 
105
                }
 
106
              else
 
107
                {
 
108
                  NSLog(@"Warning - No comments for %@ %@", type, name);
 
109
                }
 
110
            }
 
111
          else
 
112
            {
 
113
              if ([d objectForKey: @"ReturnType"] != nil)
 
114
                {
 
115
                  NSLog(@"Warning - No comments for [%@ %@]", unit, name);
 
116
                }
 
117
              else
 
118
                {
 
119
                  NSLog(@"Warning - No comments for instance variable %@ in %@",
 
120
                    name, unit);
 
121
                }
 
122
            }
 
123
        }
 
124
    }
 
125
  return comment;
87
126
}
88
127
 
89
128
- (void) dealloc
92
131
  DESTROY(identStart);
93
132
  DESTROY(spaces);
94
133
  DESTROY(spacenl);
 
134
  DESTROY(informalProtocols);
95
135
  [super dealloc];
96
136
}
97
137
 
192
232
    @"_0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"]);
193
233
  identStart = RETAIN([NSCharacterSet characterSetWithCharactersInString:
194
234
    @"_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"]);
 
235
  informalProtocols = [NSMutableArray new];
 
236
  verbose = [[NSUserDefaults standardUserDefaults] boolForKey: @"Verbose"];
 
237
  warn = [[NSUserDefaults standardUserDefaults] boolForKey: @"Warn"];
195
238
 
196
239
  return self;
197
240
}
210
253
  NSDictionary          *types;
211
254
  NSDictionary          *variables;
212
255
  NSDictionary          *constants;
 
256
  NSDictionary          *macros;
213
257
  NSMutableArray        *files;
214
258
  NSArray               *authors;
215
259
  NSString              *base;
240
284
  types = [info objectForKey: @"Types"];
241
285
  variables = [info objectForKey: @"Variables"];
242
286
  constants = [info objectForKey: @"Constants"];
 
287
  macros = [info objectForKey: @"Macros"];
243
288
 
244
289
  [str appendString: @"<?xml version=\"1.0\"?>\n"];
245
290
  [str appendString: @"<!DOCTYPE gsdoc PUBLIC "];
246
 
  [str appendString: @"\"-//GNUstep//DTD gsdoc 0.6.7//EN\" "];
247
 
  [str appendString: @"\"http://www.gnustep.org/gsdoc-0_6_7.xml\">\n"];
 
291
  [str appendString: @"\"-//GNUstep//DTD gsdoc 1.0.1//EN\" "];
 
292
  [str appendString: @"\"http://www.gnustep.org/gsdoc-1_0_1.xml\">\n"];
248
293
  [str appendFormat: @"<gsdoc"];
249
294
 
250
295
  if (base != nil)
284
329
        }
285
330
      else
286
331
        {
287
 
          [str appendFormat: @"%@ autogsdoc generated documentation",
 
332
          [str appendFormat: @"%@ documentation",
288
333
            [info objectForKey: @"base"]];
289
334
        }
290
335
      [str appendString: @"</title>\n"];
312
357
          [self reformat: author withIndent: 4 to: str];
313
358
        }
314
359
    }
315
 
  
 
360
 
316
361
  /*
317
362
   * The version element is optional ... fill in if available.
318
363
   */
321
366
    {
322
367
      [self reformat: tmp withIndent: 4 to: str];
323
368
    }
324
 
  
 
369
 
325
370
  /*
326
371
   * The date element is optional ... fill in if available.
327
372
   */
330
375
    {
331
376
      [self reformat: tmp withIndent: 4 to: str];
332
377
    }
333
 
  
 
378
 
334
379
  /*
335
380
   * The abstract element is optional ... fill in if available.
336
381
   */
339
384
    {
340
385
      [self reformat: tmp withIndent: 4 to: str];
341
386
    }
342
 
  
 
387
 
343
388
  /*
344
389
   * The copy element is optional ... fill in if available.
345
390
   */
348
393
    {
349
394
      [self reformat: tmp withIndent: 4 to: str];
350
395
    }
351
 
  
 
396
 
352
397
  [str appendString: @"  </head>\n"];
353
398
  [str appendString: @"  <body>\n"];
354
399
 
447
492
        }
448
493
 
449
494
      [m appendString: @"    </chapter>\n"];
450
 
      
 
495
 
451
496
      tmp = [self mergeMarkup: m ofKind: @"Typedefs"];
452
497
      if (tmp == nil)
453
498
        {
497
542
      RELEASE(m);
498
543
    }
499
544
 
 
545
  if ([macros count] > 0)
 
546
    {
 
547
      NSMutableString   *m = [NSMutableString new];
 
548
      NSArray           *names;
 
549
      unsigned          i;
 
550
      unsigned          c = [macros count];
 
551
 
 
552
      [m appendString: @"    <chapter>\n"];
 
553
      [m appendFormat: @"      <heading>%@ macros</heading>\n", base];
 
554
      [m appendString: @"      <p></p>\n"];
 
555
 
 
556
      names = [macros allKeys];
 
557
      names = [names sortedArrayUsingSelector: @selector(compare:)];
 
558
      for (i = 0; i < c; i++)
 
559
        {
 
560
          NSString      *name = [names objectAtIndex: i];
 
561
          NSDictionary  *d = [macros objectForKey: name];
 
562
 
 
563
          [self outputMacro: d to: m];
 
564
        }
 
565
 
 
566
      [m appendString: @"    </chapter>\n"];
 
567
 
 
568
      tmp = [self mergeMarkup: m ofKind: @"Macros"];
 
569
      if (tmp == nil)
 
570
        {
 
571
          [str appendString: m];
 
572
          chapters++;
 
573
        }
 
574
      else
 
575
        {
 
576
          [files addObject: tmp];
 
577
        }
 
578
      RELEASE(m);
 
579
    }
 
580
 
500
581
  if ([variables count] > 0)
501
582
    {
502
583
      NSMutableString   *m = [NSMutableString new];
608
689
  NSString      *declared = [d objectForKey: @"Declared"];
609
690
  NSString      *standards = nil;
610
691
 
611
 
  if ([[d objectForKey: @"Implemented"] isEqual: @"YES"] == NO)
 
692
  if (warn == YES && [[d objectForKey: @"Implemented"] isEqual: @"YES"] == NO)
612
693
    {
613
694
      NSLog(@"Warning ... %@ %@ is not implemented where expected", kind, name);
614
695
    }
635
716
    }
636
717
 
637
718
  [str appendString: @"        <desc>\n"];
638
 
  if ([comment length] == 0)
639
 
    {
640
 
      comment = @"<em>Description forthcoming.</em>";
641
 
    }
 
719
  comment = [self checkComment: comment unit: nil info: d];
642
720
  [self reformat: comment withIndent: 10 to: str];
643
721
  [str appendString: @"        </desc>\n"];
644
722
  if (standards != nil)
662
740
  NSString      *standards = nil;
663
741
  unsigned      i = [aa count];
664
742
 
665
 
  if ([[d objectForKey: @"Implemented"] isEqual: @"YES"] == NO)
 
743
  if (warn == YES && [[d objectForKey: @"Implemented"] isEqual: @"YES"] == NO)
666
744
    {
667
745
      NSLog(@"Warning ... function %@ is not implemented where expected", name);
668
746
    }
695
773
   * Check special markup which should be removed from the text
696
774
   * actually placed in the gsdoc method documentation ... the
697
775
   * special markup is included in the gsdoc markup differently.
698
 
   */ 
 
776
   */
699
777
  if (comment != nil)
700
778
    {
701
779
      NSMutableString   *m = nil;
769
847
    }
770
848
  if ([[d objectForKey: @"VarArgs"] boolValue] == YES)
771
849
    {
772
 
      [str appendString: @"<vararg />\n"];
 
850
      [str appendString: @"        <vararg />\n"];
773
851
    }
774
852
 
775
853
  if (declared != nil)
780
858
    }
781
859
 
782
860
  [str appendString: @"        <desc>\n"];
783
 
  if ([comment length] == 0)
784
 
    {
785
 
      comment = @"<em>Description forthcoming.</em>";
786
 
    }
 
861
  comment = [self checkComment: comment unit: nil info: d];
787
862
  [self reformat: comment withIndent: 10 to: str];
788
863
  [str appendString: @"        </desc>\n"];
789
864
  if (standards != nil)
797
872
/**
798
873
 * Output the gsdoc code for an instance variable.
799
874
 */
800
 
- (void) outputInstanceVariable: (NSDictionary*)d to: (NSMutableString*)str
 
875
- (void) outputInstanceVariable: (NSDictionary*)d
 
876
                             to: (NSMutableString*)str
 
877
                            for: (NSString*)unit
801
878
{
802
 
  NSString      *type = [d objectForKey: @"Type"];
 
879
  NSString      *pref = [d objectForKey: @"Prefix"];
 
880
  NSString      *type = [d objectForKey: @"BaseType"];
803
881
  NSString      *validity = [d objectForKey: @"Validity"];
804
882
  NSString      *name = [d objectForKey: @"Name"];
805
883
  NSString      *comment = [d objectForKey: @"Comment"];
807
885
 
808
886
  [str appendString: @"        <ivariable type=\""];
809
887
  [str appendString: escapeType(type)];
 
888
  if ([pref length] > 0)
 
889
    {
 
890
      [str appendString: pref];
 
891
    }
810
892
  [str appendString: @"\" name=\""];
811
893
  [str appendString: name];
812
894
  if (validity != nil)
817
899
  [str appendString: @"\">\n"];
818
900
 
819
901
  [str appendString: @"          <desc>\n"];
820
 
  if ([comment length] == 0)
821
 
    {
822
 
      comment = @"<em>Description forthcoming.</em>";
823
 
    }
 
902
  comment = [self checkComment: comment unit: unit info: d];
824
903
  [self reformat: comment withIndent: 12 to: str];
825
904
  [str appendString: @"          </desc>\n"];
826
905
  if (standards != nil)
832
911
 
833
912
/**
834
913
 * Uses -split: and -reformat:withIndent:to:.
 
914
 */
 
915
- (void) outputMacro: (NSDictionary*)d
 
916
                  to: (NSMutableString*)str
 
917
{
 
918
  NSString      *name = [d objectForKey: @"Name"];
 
919
  NSString      *comment = [d objectForKey: @"Comment"];
 
920
  NSString      *declared = [d objectForKey: @"Declared"];
 
921
  NSString      *standards = nil;
 
922
  unsigned      i;
 
923
 
 
924
  if (standards == nil)
 
925
    {
 
926
      standards = [d objectForKey: @"Standards"];
 
927
    }
 
928
 
 
929
  [str appendString: @"      <macro name=\""];
 
930
  [str appendString: name];
 
931
  [str appendString: @"\">\n"];
 
932
 
 
933
  /*
 
934
   * Storing the argument names array in the 'args' ivar ensures that
 
935
   * when we output comments, the argument names are highlighted.
 
936
   */
 
937
  args = [d objectForKey: @"Args"];
 
938
  for (i = 0; i < [args count]; i++)
 
939
    {
 
940
      NSString          *s = [args objectAtIndex: i];
 
941
 
 
942
      [str appendString: @"        <arg>"];
 
943
      [str appendString: s];
 
944
      [str appendString: @"</arg>\n"];
 
945
    }
 
946
  if ([[d objectForKey: @"VarArgs"] boolValue] == YES)
 
947
    {
 
948
      [str appendString: @"        <vararg />\n"];
 
949
    }
 
950
 
 
951
  if (declared != nil)
 
952
    {
 
953
      [str appendString: @"        <declared>"];
 
954
      [str appendString: declared];
 
955
      [str appendString: @"</declared>\n"];
 
956
    }
 
957
 
 
958
  [str appendString: @"        <desc>\n"];
 
959
  comment = [self checkComment: comment unit: nil info: d];
 
960
  [self reformat: comment withIndent: 10 to: str];
 
961
  [str appendString: @"        </desc>\n"];
 
962
  if (standards != nil)
 
963
    {
 
964
      [self reformat: standards withIndent: 8 to: str];
 
965
    }
 
966
  [str appendString: @"      </macro>\n"];
 
967
  args = nil;
 
968
}
 
969
 
 
970
/**
 
971
 * Uses -split: and -reformat:withIndent:to:.
835
972
 * Also has fun with YES, NO, and nil.
836
973
 */
837
974
- (void) outputMethod: (NSDictionary*)d
847
984
  NSString      *override = nil;
848
985
  NSString      *standards = nil;
849
986
 
850
 
  if (unit != nil && [[d objectForKey: @"Implemented"] isEqual: @"YES"] == NO)
 
987
  if (warn == YES && unit != nil
 
988
    && [[d objectForKey: @"Implemented"] isEqual: @"YES"] == NO)
851
989
    {
852
990
      NSLog(@"Warning ... method %@ %@ is not implemented where expected",
853
991
        unit, name);
861
999
   * Check special markup which should be removed from the text
862
1000
   * actually placed in the gsdoc method documentation ... the
863
1001
   * special markup is included in the gsdoc markup differently.
864
 
   */ 
 
1002
   */
865
1003
  if (comment != nil)
866
1004
    {
867
1005
      NSMutableString   *m = nil;
989
1127
    }
990
1128
  if ([[d objectForKey: @"VarArgs"] boolValue] == YES)
991
1129
    {
992
 
      [str appendString: @"<vararg />\n"];
 
1130
      [str appendString: @"          <vararg />\n"];
993
1131
    }
994
1132
 
995
1133
  [str appendString: @"          <desc>\n"];
996
 
  if ([comment length] == 0)
997
 
    {
998
 
      comment = @"<em>Description forthcoming.</em>";
999
 
    }
 
1134
  comment = [self checkComment: comment unit: unit info: d];
1000
1135
  [self reformat: comment withIndent: 12 to: str];
1001
1136
  [str appendString: @"          </desc>\n"];
1002
1137
  if (standards != nil)
1011
1146
{
1012
1147
  NSString      *name = [d objectForKey: @"Name"];
1013
1148
  NSString      *type = [d objectForKey: @"Type"];
1014
 
  NSDictionary  *methods = [d objectForKey: @"Methods"];
1015
 
  NSDictionary  *ivars = [d objectForKey: @"InstanceVariables"];
 
1149
  NSString      *kind = type;
 
1150
  NSMutableDictionary   *methods = [d objectForKey: @"Methods"];
 
1151
  NSMutableDictionary   *ivars = [d objectForKey: @"InstanceVariables"];
1016
1152
  NSString      *comment = [d objectForKey: @"Comment"];
1017
1153
  NSString      *unitName = nil;
1018
1154
  NSArray       *names;
1019
1155
  NSArray       *protocols;
1020
1156
  NSString      *standards = nil;
1021
1157
  NSString      *tmp;
1022
 
  NSString      *unit;
 
1158
  NSString      *unit = nil;
1023
1159
  NSRange       r;
1024
1160
  unsigned      ind;
1025
1161
  unsigned      i;
1027
1163
 
1028
1164
  if ([[d objectForKey: @"Implemented"] isEqual: @"YES"] == NO)
1029
1165
    {
1030
 
      NSLog(@"Warning ... unit %@ is not implemented where expected", name);
 
1166
      if ([name hasPrefix:  @"NSObject("] == YES)
 
1167
        {
 
1168
          NSEnumerator          *e = [methods objectEnumerator];
 
1169
          NSMutableDictionary   *m;
 
1170
 
 
1171
          /*
 
1172
           * Assume an unimplemented category of NSObject is an
 
1173
           * informal protocol, and stop warnings being issued
 
1174
           * about unimplemented methods.
 
1175
           */
 
1176
          unitName = name;
 
1177
          kind = @"informal protocol";
 
1178
          while ((m = [e nextObject]) != nil)
 
1179
            {
 
1180
              [m setObject: @"YES" forKey: @"Implemented"];
 
1181
            }
 
1182
 
 
1183
          [informalProtocols addObject: name];
 
1184
        }
 
1185
      else if (warn == YES)
 
1186
        {
 
1187
          NSLog(@"Warning ... unit %@ is not implemented where expected", name);
 
1188
        }
1031
1189
    }
1032
1190
  else
1033
1191
    {
1034
1192
      unitName = name;
1035
1193
    }
1036
1194
 
1037
 
  r = [comment rangeOfString: @"<standards>"];
1038
 
  if (comment != nil && r.length > 0)
 
1195
  if (comment != nil)
1039
1196
    {
1040
 
      unsigned  i = r.location;
1041
 
 
1042
 
      r = NSMakeRange(i, [comment length] - i);
1043
 
      r = [comment rangeOfString: @"</standards>"
1044
 
                     options: NSLiteralSearch
1045
 
                       range: r];
 
1197
      r = [comment rangeOfString: @"<standards>"];
1046
1198
      if (r.length > 0)
1047
1199
        {
1048
 
          NSMutableString       *m;
1049
 
 
1050
 
          r = NSMakeRange(i, NSMaxRange(r) - i);
1051
 
          standards = [comment substringWithRange: r];
1052
 
          m = [comment mutableCopy];
1053
 
          [m deleteCharactersInRange: r];
1054
 
          comment = m;
1055
 
          AUTORELEASE(m);
1056
 
        }
1057
 
      else
1058
 
        {
1059
 
          NSLog(@"unterminated <standards> in comment for %@", name);
 
1200
          unsigned  i = r.location;
 
1201
 
 
1202
          r = NSMakeRange(i, [comment length] - i);
 
1203
          r = [comment rangeOfString: @"</standards>"
 
1204
                         options: NSLiteralSearch
 
1205
                           range: r];
 
1206
          if (r.length > 0)
 
1207
            {
 
1208
              NSMutableString   *m;
 
1209
 
 
1210
              r = NSMakeRange(i, NSMaxRange(r) - i);
 
1211
              standards = [comment substringWithRange: r];
 
1212
              m = [comment mutableCopy];
 
1213
              [m deleteCharactersInRange: r];
 
1214
              comment = m;
 
1215
              AUTORELEASE(m);
 
1216
            }
 
1217
          else
 
1218
            {
 
1219
              NSLog(@"unterminated <standards> in comment for %@", name);
 
1220
            }
1060
1221
        }
1061
1222
    }
1062
1223
  if (standards == nil)
1068
1229
   * Make sure we have a 'unit' part and a class 'desc' part (comment)
1069
1230
   * to be output.
1070
1231
   */
1071
 
  r = [comment rangeOfString: @"<unit>"];
1072
 
  if (comment != nil && r.length > 0)
 
1232
  if (comment != nil)
1073
1233
    {
1074
 
      unsigned  pos = r.location;
1075
 
 
1076
 
      r = [comment rangeOfString: @"</unit>"];
1077
 
      if (r.length == 0 || r.location < pos)
1078
 
        {
1079
 
          NSLog(@"Unterminated <unit> in comment for %@", name);
1080
 
          return;
1081
 
        }
1082
 
      
1083
 
      if (pos == 0)
1084
 
        {
1085
 
          if (NSMaxRange(r) == [comment length])
1086
 
            {
1087
 
              unit = comment;
1088
 
              comment = nil;
1089
 
            }
1090
 
          else
1091
 
            {
1092
 
              unit = [comment substringToIndex: NSMaxRange(r)];
1093
 
              comment = [comment substringFromIndex: NSMaxRange(r)];
1094
 
            }
1095
 
        }
1096
 
      else
1097
 
        {
1098
 
          if (NSMaxRange(r) == [comment length])
1099
 
            {
1100
 
              unit = [comment substringFromIndex: pos];
1101
 
              comment = [comment substringToIndex: pos];
1102
 
            }
1103
 
          else
1104
 
            {
1105
 
              unsigned  end = NSMaxRange(r);
1106
 
 
1107
 
              r = NSMakeRange(pos, end-pos);
1108
 
              unit = [comment substringWithRange: r];
1109
 
              comment = [[comment substringToIndex: pos]
1110
 
                stringByAppendingString: [comment substringFromIndex: end]];
1111
 
            }
1112
 
        }
1113
 
      unit = [unit stringByReplacingString: @"unit>" withString: @"chapter>"];
 
1234
      r = [comment rangeOfString: @"<unit>"];
 
1235
      if (r.length > 0)
 
1236
        {
 
1237
          unsigned      pos = r.location;
 
1238
 
 
1239
          r = [comment rangeOfString: @"</unit>"];
 
1240
          if (r.length == 0 || r.location < pos)
 
1241
            {
 
1242
              NSLog(@"Unterminated <unit> in comment for %@", name);
 
1243
              return;
 
1244
            }
 
1245
        
 
1246
          if (pos == 0)
 
1247
            {
 
1248
              if (NSMaxRange(r) == [comment length])
 
1249
                {
 
1250
                  unit = comment;
 
1251
                  comment = nil;
 
1252
                }
 
1253
              else
 
1254
                {
 
1255
                  unit = [comment substringToIndex: NSMaxRange(r)];
 
1256
                  comment = [comment substringFromIndex: NSMaxRange(r)];
 
1257
                }
 
1258
            }
 
1259
          else
 
1260
            {
 
1261
              if (NSMaxRange(r) == [comment length])
 
1262
                {
 
1263
                  unit = [comment substringFromIndex: pos];
 
1264
                  comment = [comment substringToIndex: pos];
 
1265
                }
 
1266
              else
 
1267
                {
 
1268
                  unsigned      end = NSMaxRange(r);
 
1269
 
 
1270
                  r = NSMakeRange(pos, end-pos);
 
1271
                  unit = [comment substringWithRange: r];
 
1272
                  comment = [[comment substringToIndex: pos]
 
1273
                    stringByAppendingString: [comment substringFromIndex: end]];
 
1274
                }
 
1275
            }
 
1276
          unit = [unit stringByReplacingString: @"unit>"
 
1277
                                    withString: @"chapter>"];
 
1278
        }
1114
1279
    }
1115
 
  else
 
1280
  if (unit == nil)
1116
1281
    {
1117
1282
      unit = [NSString stringWithFormat:
1118
1283
        @"    <chapter>\n      <heading>Software documentation "
1119
 
        @"for the %@ %@</heading>\n    </chapter>\n", name, type];
 
1284
        @"for the %@ %@</heading>\n    </chapter>\n", name, kind];
1120
1285
    }
1121
1286
 
1122
1287
  /*
1189
1354
 
1190
1355
  for (j = 0; j < ind; j++) [str appendString: @" "];
1191
1356
  [str appendString: @"<desc>\n"];
1192
 
  if ([comment length] == 0)
1193
 
    {
1194
 
      comment = @"<em>Description forthcoming.</em>";
1195
 
    }
 
1357
  comment = [self checkComment: comment unit: nil info: d];
1196
1358
  [self reformat: comment withIndent: ind + 2 to: str];
1197
1359
  for (j = 0; j < ind; j++) [str appendString: @" "];
1198
1360
  [str appendString: @"</desc>\n"];
1199
 
  
 
1361
 
1200
1362
  names = [[ivars allKeys] sortedArrayUsingSelector: @selector(compare:)];
1201
1363
  for (i = 0; i < [names count]; i++)
1202
1364
    {
1203
1365
      NSString  *vName = [names objectAtIndex: i];
1204
1366
 
1205
 
      [self outputInstanceVariable: [ivars objectForKey: vName] to: str];
 
1367
      [self outputInstanceVariable: [ivars objectForKey: vName]
 
1368
                                to: str
 
1369
                               for: unitName];
1206
1370
    }
1207
1371
 
1208
1372
  names = [[methods allKeys] sortedArrayUsingSelector: @selector(compare:)];
1237
1401
           withIndent: (unsigned)ind
1238
1402
                   to: (NSMutableString*)buf
1239
1403
{
 
1404
#if GS_WITH_GC == 0
1240
1405
  CREATE_AUTORELEASE_POOL(arp);
 
1406
#endif
1241
1407
  unsigned      l = [str length];
1242
1408
  NSRange       r = NSMakeRange(0, l);
1243
1409
  unsigned      i = 0;
1263
1429
          i = r.location;
1264
1430
        }
1265
1431
      /*
1266
 
       * Now find the end of the exmple, and output the whole example
 
1432
       * Now find the end of the example, and output the whole example
1267
1433
       * literally as it appeared in the comment.
1268
1434
       */
1269
1435
      r = [str rangeOfString: @"</example>"
1302
1468
  a = [self split: str];
1303
1469
  for (i = 0; i < [a count]; i++)
1304
1470
    {
1305
 
      int       j;
 
1471
      unsigned int      j;
1306
1472
 
1307
1473
      str = [a objectAtIndex: i];
1308
1474
 
1360
1526
  return ind;
1361
1527
}
1362
1528
 
 
1529
/**
 
1530
 * Split comment text into an array of words (to be reformatted) and
 
1531
 * insert markup for cross referencing and highlighting.
 
1532
 */
1363
1533
- (NSArray*) split: (NSString*)str
1364
1534
{
1365
1535
  NSMutableArray        *a = [NSMutableArray arrayWithCapacity: 128];
1479
1649
               */
1480
1650
              if (optr[-2] == '/' && optr[-3] != ' ')
1481
1651
                {
1482
 
                  unsigned      len = ptr - buf;
 
1652
                  unsigned      len = optr - buf;
1483
1653
                  unichar       c[len + 1];
1484
1654
 
1485
1655
                  memcpy(c, buf, (len+1)*sizeof(unichar));
1490
1660
                }
1491
1661
              else
1492
1662
                {
1493
 
                  tmp = [NSString stringWithCharacters: buf length: ptr - buf];
 
1663
                  tmp = [NSString stringWithCharacters: buf length: optr - buf];
1494
1664
                }
1495
1665
              [a addObject: tmp];
1496
1666
            }
1511
1681
 
1512
1682
  /*
1513
1683
   * Phase 2 ... the array of words is checked to see if a word contains
1514
 
   * a well known constant, or a method name specification.
 
1684
   * a well known constant, or a method or function name specification.
1515
1685
   * Where these special cases apply, the array of words is modified to
1516
1686
   * insert extra gsdoc markup to highlight the constants and to create
1517
 
   * references to where the named methods are documented.
 
1687
   * references to where the named methods or functions are documented.
1518
1688
   */
1519
1689
  for (l = 0; l < [a count]; l++)
1520
1690
    {
1523
1693
      NSString          *tmp = [a objectAtIndex: l];
1524
1694
      unsigned          pos;
1525
1695
      NSRange           r;
1526
 
      BOOL              hadMethod = NO;
1527
1696
 
1528
1697
      if (constants == nil)
1529
1698
        {
1666
1835
      /*
1667
1836
       * Ensure that methods are rendered as references.
1668
1837
       * First look for format with class name in square brackets.
 
1838
       * If that's all there is, we make a class reference.
1669
1839
       */
1670
1840
      r = [tmp rangeOfString: @"["];
1671
1841
      if (r.length > 0)
1680
1850
              unsigned  ePos = r.location;
1681
1851
              NSString  *cName = nil;
1682
1852
              NSString  *mName = nil;
1683
 
              unichar   c;
 
1853
              unichar   c = 0;
 
1854
              BOOL      isProtocol = NO;
1684
1855
 
1685
1856
              if (pos < ePos
1686
1857
                && [identStart characterIsMember:
1737
1908
                      cName = [tmp substringWithRange: r];
1738
1909
                    }
1739
1910
                }
1740
 
              else if (pos < ePos
1741
 
                && (c = [tmp characterAtIndex: pos]) == '(')
 
1911
              else if (pos < ePos && (c = [tmp characterAtIndex: pos]) == '(')
1742
1912
                {
1743
1913
                  /*
1744
1914
                   * Look for protocol name.
1760
1930
                        }
1761
1931
                      pos++;
1762
1932
                    }
 
1933
                  isProtocol = YES;
1763
1934
                }
1764
1935
 
1765
1936
              if (pos < ePos && (c == '+' || c == '-'))
1766
 
                { 
 
1937
                {
1767
1938
                  unsigned      mStart = pos;
1768
1939
 
1769
1940
                  pos++;
1811
1982
                  if (sPos > 0)
1812
1983
                    {
1813
1984
                      start = [tmp substringToIndex: sPos];
 
1985
                      if ([start isEqualToString: @"["] == YES)
 
1986
                        {
 
1987
                          start = nil;
 
1988
                        }
 
1989
                      else if ([start hasSuffix: @"["] == YES)
 
1990
                        {
 
1991
                          start = [start substringToIndex: [start length] - 1];
 
1992
                        }
1814
1993
                    }
1815
1994
                  else
1816
1995
                    {
1819
1998
                  if (ePos < [tmp length])
1820
1999
                    {
1821
2000
                      end = [tmp substringFromIndex: ePos];
 
2001
                      if ([end isEqualToString: @"]"] == YES)
 
2002
                        {
 
2003
                          end = nil;
 
2004
                        }
 
2005
                      else if ([end hasPrefix: @"]"] == YES)
 
2006
                        {
 
2007
                          end = [end substringFromIndex: 1];
 
2008
                        }
1822
2009
                    }
1823
2010
                  else
1824
2011
                    {
1843
2030
                      ref = [NSString stringWithFormat:
1844
2031
                        @"<ref type=\"method\" id=\"%@\">", mName];
1845
2032
                    }
 
2033
                  else if (isProtocol == YES)
 
2034
                    {
 
2035
                      ref = [NSString stringWithFormat:
 
2036
                        @"<ref type=\"method\" id=\"%@\" class=\"%@\">",
 
2037
                        mName, cName];
 
2038
                      if (isProtocol == YES)
 
2039
                        {
 
2040
                          if (sub == nil)
 
2041
                            {
 
2042
                              sub = tmp;
 
2043
                            }
 
2044
                          sub = [sub stringByReplacingString: @"("
 
2045
                                                  withString: @"&lt;"];
 
2046
                          sub = [sub stringByReplacingString: @")"
 
2047
                                                  withString: @"&gt;"];
 
2048
                        }
 
2049
                    }
1846
2050
                  else
1847
2051
                    {
1848
2052
                      ref = [NSString stringWithFormat:
1849
2053
                        @"<ref type=\"method\" id=\"%@\" class=\"%@\">",
1850
2054
                        mName, cName];
 
2055
                      sub = [NSString stringWithFormat: @"[%@&nbsp;%@]",
 
2056
                        cName, mName];
1851
2057
                    }
1852
2058
                  [a insertObject: ref atIndex: l++];
1853
2059
                  if (sub != nil)
1861
2067
                    {
1862
2068
                      [a insertObject: end atIndex: ++l];
1863
2069
                    }
1864
 
                  hadMethod = YES;
 
2070
                }
 
2071
              else if (pos == ePos && cName != nil)
 
2072
                {
 
2073
                  NSString      *ref;
 
2074
 
 
2075
                  if (isProtocol == YES)
 
2076
                    {
 
2077
                      NSRange   r;
 
2078
 
 
2079
                      r = NSMakeRange(1, [cName length] - 2);
 
2080
                      cName = [cName substringWithRange: r];
 
2081
                      ref = [NSString stringWithFormat:
 
2082
                        @"<ref type=\"protocol\" id=\"(%@)\">&lt;%@&gt;</ref>",
 
2083
                        cName, cName];
 
2084
                    }
 
2085
                  else if ([cName hasSuffix: @")"] == YES)
 
2086
                    {
 
2087
                      ref = [NSString stringWithFormat:
 
2088
                        @"<ref type=\"category\" id=\"%@\">%@</ref>",
 
2089
                        cName, cName];
 
2090
                    }
 
2091
                  else
 
2092
                    {
 
2093
                      ref = [NSString stringWithFormat:
 
2094
                        @"<ref type=\"class\" id=\"%@\">%@</ref>",
 
2095
                        cName, cName];
 
2096
                    }
 
2097
                  [a replaceObjectAtIndex: l withObject: ref];
 
2098
                  if (ePos < [tmp length])
 
2099
                    {
 
2100
                      NSString  *end = [tmp substringFromIndex: ePos];
 
2101
 
 
2102
                      if ([end isEqualToString: @"]"] == YES)
 
2103
                        {
 
2104
                          end = nil;
 
2105
                        }
 
2106
                      if ([end hasPrefix: @"]"] == YES)
 
2107
                        {
 
2108
                          end = [end substringFromIndex: 1];
 
2109
                        }
 
2110
                      if ([end length] > 0)
 
2111
                        {
 
2112
                          [a insertObject: end atIndex: ++l];
 
2113
                        }
 
2114
                    }
1865
2115
                }
1866
2116
            }
 
2117
          continue;
1867
2118
        }
1868
 
      
 
2119
 
1869
2120
      /*
1870
2121
       * Now handle bare method names for current class ... outside brackets.
1871
2122
       */
1872
 
      if (hadMethod == NO && ([tmp hasPrefix: @"-"] || [tmp hasPrefix: @"+"]))
 
2123
      if ([tmp hasPrefix: @"-"] || [tmp hasPrefix: @"+"])
1873
2124
        {
1874
2125
          unsigned      ePos = [tmp length];
1875
2126
          NSString      *mName = nil;
1898
2149
                  isEqual: @",..."])
1899
2150
                {
1900
2151
                  pos += 4;
1901
 
                  c = [tmp characterAtIndex: pos];
 
2152
                  if (pos < ePos)
 
2153
                    {
 
2154
                      c = [tmp characterAtIndex: pos];
 
2155
                    }
1902
2156
                }
1903
2157
              if (pos > 1 && (pos == ePos || c == ',' || c == '.' || c == ';'))
1904
2158
                {
1932
2186
                    {
1933
2187
                      [a insertObject: end atIndex: ++l];
1934
2188
                    }
1935
 
                  hadMethod = YES;
1936
 
                }
 
2189
                }
 
2190
            }
 
2191
          continue;
 
2192
        }
 
2193
      /*
 
2194
       * Now handle function names.  Anything ending in '()' is assumed to
 
2195
       * be a referencable function name except 'main()' ... which is special.
 
2196
       * NB. A comma, fullstop, or semicolon following '()' is counted as if
 
2197
       * the text ended in '()'
 
2198
       */
 
2199
      r = [tmp rangeOfString: @"()"];
 
2200
      if (r.length > 0)
 
2201
        {
 
2202
          unsigned      c = [tmp characterAtIndex: 0];
 
2203
          unsigned      len = [tmp length];
 
2204
          NSString      *str = [tmp substringToIndex: r.location];
 
2205
          BOOL          ok = NO;
 
2206
 
 
2207
          if ([identStart characterIsMember: c] == YES
 
2208
            && [str isEqual: @"main"] == NO)
 
2209
            {
 
2210
              ok = YES;
 
2211
              if (len > NSMaxRange(r))
 
2212
                {
 
2213
                  NSString      *end;
 
2214
 
 
2215
                  end = [tmp substringFromIndex: NSMaxRange(r)];
 
2216
                  c = [end characterAtIndex: 0];
 
2217
                  if (c == ',' || c == '.' || c == ';')
 
2218
                    {
 
2219
                      [a insertObject: end atIndex: l + 1];
 
2220
                      tmp = [tmp substringToIndex: NSMaxRange(r)];
 
2221
                      [a replaceObjectAtIndex: l withObject: tmp];
 
2222
                    }
 
2223
                  else
 
2224
                    {
 
2225
                      ok = NO;
 
2226
                    }
 
2227
                }
 
2228
            }
 
2229
          if (ok == YES)
 
2230
            {
 
2231
              str = [NSString stringWithFormat:
 
2232
                @"<ref type=\"function\" id=\"%@\">", str];
 
2233
              [a insertObject: str atIndex: l++];
 
2234
              l++;      // Point past the function name in the array.
 
2235
              [a insertObject: @"</ref>" atIndex: l++];
 
2236
              continue;
1937
2237
            }
1938
2238
        }
1939
2239
    }
1941
2241
  return a;
1942
2242
}
1943
2243
 
 
2244
- (NSArray*) informalProtocols
 
2245
{
 
2246
  return informalProtocols;
 
2247
}
 
2248
 
1944
2249
@end
1945
2250
 
1946
2251
 
1993
2298
        }
1994
2299
      else
1995
2300
        {
 
2301
          NSString      *up = [ud stringForKey: @"Up"];
 
2302
 
1996
2303
          /*
1997
2304
           * No pre-existing file, and no blank template available ...
1998
2305
           * Generate a standard template.
2001
2308
 
2002
2309
          [str appendString: @"<?xml version=\"1.0\"?>\n"];
2003
2310
          [str appendString: @"<!DOCTYPE gsdoc PUBLIC "];
2004
 
          [str appendString: @"\"-//GNUstep//DTD gsdoc 0.6.7//EN\" "];
2005
 
          [str appendString: @"\"http://www.gnustep.org/gsdoc-0_6_7.xml\">\n"];
 
2311
          [str appendString: @"\"-//GNUstep//DTD gsdoc 1.0.1//EN\" "];
 
2312
          [str appendString: @"\"http://www.gnustep.org/gsdoc-1_0_1.xml\">\n"];
2006
2313
          [str appendString: @"<gsdoc base=\""];
2007
2314
          [str appendString: [name lastPathComponent]];
 
2315
          /*
 
2316
           * If a -Up default has been set, create an up link in this
 
2317
           * template file... as long as the specified up link is not
 
2318
           * the template file itself.
 
2319
           */
 
2320
          if (up != nil && [up isEqual: [name lastPathComponent]] == NO)
 
2321
            {
 
2322
              [str appendString: @"\" up=\""];
 
2323
              [str appendString: up];
 
2324
            }
2008
2325
          [str appendString: @"\">\n"];
2009
2326
          [str appendString: @"  <head>\n"];
2010
2327
          [str appendString: @"    <title>"];
2016
2333
          [str appendString: @"\"></author>\n"];
2017
2334
          [str appendString: @"  </head>\n"];
2018
2335
          [str appendString: @"  <body>\n"];
 
2336
          [str appendString: @"    <front><contents /></front>\n"];
2019
2337
          [str appendString: @"  </body>\n"];
2020
2338
          [str appendString: @"</gsdoc>\n"];
2021
2339
        }
2028
2346
  start = [str rangeOfString: tmp];
2029
2347
  if (start.length == 0)
2030
2348
    {
2031
 
      start = [str rangeOfString: @"</body>"];
2032
 
      if (start.length == 0)
2033
 
        {
2034
 
          NSLog(@"No </body> markup in %@ document", kind);
 
2349
      start = [str rangeOfString: @"<back>"];
 
2350
      if (start.length == 0)
 
2351
        {
 
2352
          start = [str rangeOfString: @"</body>"];
 
2353
        }
 
2354
      if (start.length == 0)
 
2355
        {
 
2356
          NSLog(@"No <back> or </body> markup in %@ document", kind);
2035
2357
          return NO;
2036
2358
        }
2037
2359
      [str insertString: tmp atIndex: start.location];