1 /*
2 ** $PROJECT:
3 **
4 ** $VER: autodoc.c 2.2 (25.01.95)
5 **
6 ** by
7 **
8 ** Stefan Ruppert , Windthorststra_e 5 , 65439 Flvrsheim , GERMANY
9 **
10 ** (C) Copyright 1995
11 ** All Rights Reserved !
12 **
13 ** $HISTORY:
14 **
15 ** 25.01.95 : 002.002 : changed to patchlevel 33
16 ** 22.01.95 : 000.001 : initial
17 */
18 
19 #include "c2man.h"
20 #include "manpage.h"
21 #include "output.h"
22 #include <ctype.h>
23 
24 #ifdef DEBUG
25 #define D(x)  x
26 #else
27 #define D(x)
28 #endif
29 
30 #define MAX_TAG      10
31 
32 static const int linelength   = 79;
33 static const int tablength    =  4;
34 static const int indentlength =  4;
35 
36 static int indent      = 4;
37 static int list_indent = 0;
38 static int column      = 0;
39 static int newline     = FALSE;
40 static int breakline   = FALSE;
41 static int see_also    = FALSE;
42 static int fileend     = FALSE;
43 static int acttable    = -1;
44 static int tablemaxtag[MAX_TAG];
45 
autodoc_format(text)46 void autodoc_format(text)
47 const char *text;
48 {
49     if(see_also)
50     {
51        if(column + ((text) ? strlen(text) + 2 : 1) > linelength)
52        {
53            putchar('\n');
54            newline = TRUE;
55        }
56     }
57 
58     if(newline)
59     {
60        int i;
61        column = i = indent + list_indent;
62        for(; i ; i--)
63           putchar(' ');
64        newline = FALSE;
65     }
66 }
67 
autodoc_text(text)68 void autodoc_text(text)
69 const char *text;
70 {
71     int br = 1;
72     autodoc_format(text);
73 
74     if(!see_also || (br = strcmp(text,",\n")))
75     {
76         if(see_also < 2)
77         {
78            put_string(text);
79            column += strlen(text);
80         }
81     } else if(!br)
82     {
83         column += 2;
84         put_string(", ");
85     }
86 }
87 
autodoc_char(c)88 void autodoc_char(c)
89 const int c;
90 {
91     if(c != '\f')
92     {
93        autodoc_format(NULL);
94 
95        if(c == '\t')
96        {
97           int i = tablength - (column % tablength);
98           column += i;
99           for(; i ; i--)
100              putchar(' ');
101        } else
102        {
103           if(see_also)
104           {
105              if(c == '(')
106                  see_also++;
107              else if(c == ')')
108                  see_also--;
109           }
110 
111           putchar(c);
112           column++;
113        }
114 
115        if((newline = (c == '\n')))
116            column = 0;
117    }
118 }
119 
autodoc_comment()120 void autodoc_comment() { }
121 
autodoc_header(firstpage,input_files,grouped,name,terse,section)122 void autodoc_header(firstpage, input_files, grouped, name, terse, section)
123 ManualPage *firstpage;
124 int input_files;
125 boolean grouped;
126 const char *name;
127 const char *terse;
128 const char *section;
129 {
130     const char *basename = strrchr(firstpage->sourcefile, '/');
131     int len;
132     int spc;
133 
134     fileend = FALSE;
135 
136     if(basename && *basename == '/')
137         basename++;
138 
139     len =  ((basename) ? strlen(basename) + 1 : 0) + strlen(name);
140     spc  = linelength - 2 * len;
141 
142     see_also = FALSE;
143 
144     if(basename)
145     {
146        autodoc_text(basename);
147        autodoc_char('/');
148     }
149     autodoc_text(name);
150 
151     if(spc > 0)
152     {
153       while(spc)
154       {
155          autodoc_char(' ');
156          spc--;
157       }
158        if(basename)
159        {
160           autodoc_text(basename);
161           autodoc_char('/');
162        }
163        autodoc_text(name);
164     } else
165     {
166        const char *ptr = name;
167        len = linelength - 1 - len;
168 
169        while(len)
170        {
171           if(basename && *basename)
172           {
173              autodoc_char(*basename);
174              basename++;
175           } else
176           {
177              if(ptr == name && basename)
178                 autodoc_char('/');
179              else
180              {
181                 autodoc_char(*ptr);
182                 ptr++;
183              }
184           }
185           len--;
186        }
187     }
188 
189     put_string("\n");
190 }
191 
autodoc_dash()192 void autodoc_dash()       { put_string("-"); }
193 
autodoc_section(name)194 void autodoc_section(name)
195 const char *name;
196 {
197     D((fprintf(stderr,"section : %s\n",name)));
198     newline = FALSE;
199     see_also = FALSE;
200     put_string("\n");
201     if(!strcmp(name,"DESCRIPTION"))
202        name = "FUNCTION";
203     else if(!strcmp(name,"PARAMETERS"))
204        name = "INPUTS";
205     else if(!strcmp(name,"RETURNS"))
206        name = "RESULT";
207     else if(!strcmp(name,"SEE ALSO"))
208        see_also = TRUE;
209 
210     put_string("    ");
211     autodoc_text(name);
212     indent = 8;
213     list_indent = 0;
214     autodoc_char('\n');
215 }
216 
autodoc_sub_section(name)217 void autodoc_sub_section(name)
218 const char *name;
219 {
220     autodoc_text(name);
221     indent = 12;
222 }
223 
autodoc_break_line()224 void autodoc_break_line()
225 {
226    breakline = TRUE;
227 }
228 
autodoc_blank_line()229 void autodoc_blank_line()
230 {
231     autodoc_char('\n');
232 }
233 
autodoc_code_start()234 void autodoc_code_start() {  }
autodoc_code_end()235 void autodoc_code_end()   {  }
236 
autodoc_code(text)237 void autodoc_code(text)
238 const char *text;
239 {
240     autodoc_text(text);
241 }
242 
autodoc_tag_entry_start()243 void autodoc_tag_entry_start()
244 {
245     if(list_indent > 0)
246     {
247         autodoc_char('\n');
248         list_indent -= indentlength;
249     }
250 }
autodoc_tag_entry_start_extra()251 void autodoc_tag_entry_start_extra()
252 {
253     if(list_indent > 0)
254     {
255         autodoc_char('\n');
256         list_indent -= indentlength;
257     }
258 }
autodoc_tag_entry_end()259 void autodoc_tag_entry_end()
260 {
261    list_indent += indentlength;
262    autodoc_char('\n');
263 }
autodoc_tag_entry_end_extra(text)264 void autodoc_tag_entry_end_extra(text)
265 const char *text;
266 {
267     put_string("\" \"\t(");
268     autodoc_text(text);
269     put_string(")\"\n");
270     list_indent += indentlength;
271 }
272 
autodoc_table_start(longestag)273 void autodoc_table_start(longestag)
274 const char *longestag;
275 {
276    if(acttable < MAX_TAG - 1)
277    {
278       acttable++;
279       tablemaxtag[acttable] = strlen(longestag);
280    }
281 
282    indent += indentlength;
283    newline = TRUE;
284 }
285 
autodoc_table_entry(name,description)286 void autodoc_table_entry(name, description)
287 const char *name;
288 const char *description;
289 {
290     int i = tablemaxtag[acttable] - strlen(name) + 1;
291 
292     autodoc_code(name);
293     while(i > 0)
294     {
295        putchar(' ');
296        i--;
297     }
298     putchar('-');
299     putchar(' ');
300 
301     if (description)
302         output_comment(description);
303     else
304         autodoc_char('\n');
305 }
306 
autodoc_table_end()307 void autodoc_table_end()
308 {
309     if(acttable > -1)
310       acttable--;
311 
312     autodoc_char('\n');
313     indent -= indentlength;
314     if(list_indent > 0)
315        list_indent -= indentlength;
316 }
317 
autodoc_indent()318 void autodoc_indent()
319 {
320     int i;
321     for(i = indent + list_indent; i ; i--)
322        autodoc_char(' ');
323 }
324 
autodoc_list_start()325 void autodoc_list_start()
326 {
327    indent += indentlength;
328    newline = TRUE;
329 }
330 
autodoc_list_entry(name)331 void autodoc_list_entry(name)
332 const char *name;
333 {
334     autodoc_code(name);
335 }
336 
autodoc_list_separator()337 void autodoc_list_separator() { put_string(" ,"); }
autodoc_list_end()338 void autodoc_list_end()   { autodoc_char('\n'); autodoc_table_end(); }
339 
autodoc_include(filename)340 void autodoc_include(filename)
341 const char *filename;
342 {
343 
344 }
345 
autodoc_terse_sep()346 void autodoc_terse_sep()
347 {
348     autodoc_char(' ');
349     autodoc_dash();
350     autodoc_char(' ');
351 }
352 
autodoc_name(name)353 void autodoc_name(name)
354 const char *name;
355 {
356    if(name)
357       autodoc_text(name);
358    else
359       autodoc_section("NAME");
360 }
361 
autodoc_file_end()362 void autodoc_file_end()
363 {
364    if(!fileend)
365       putchar('\f');
366    fileend = TRUE;
367    newline = FALSE;
368 }
369 
370 /* ideally, this should be made aware of embedded autodoc commands */
autodoc_description(text)371 void autodoc_description(text)
372 const char *text;
373 {
374     enum { TEXT, PERIOD, CAPITALISE } state = CAPITALISE;
375     boolean new_line = TRUE;
376 
377     /* correct punctuation a bit as it goes out */
378     for (;*text;text++)
379     {
380 	int c = *text;
381 
382 	if (new_line && (c == '-' || c == '*'))
383 	{
384 	    output->break_line();
385 	    state = CAPITALISE;
386 	}
387 	else if (c == '.')
388 	    state = PERIOD;
389 	else if (isspace(c) && state == PERIOD)
390 	    state = CAPITALISE;
391 	else if (isalnum(c) || ispunct(c))
392 	{
393 	    if (islower(c) && state == CAPITALISE)	c = toupper(c);
394 	    state = TEXT;
395 	}
396 
397 	output->character(c);
398 	new_line = c == '\n';
399     }
400 
401     /* do a full stop if there wasn't one */
402     if (state == TEXT)	output->character('.');
403 }
404 
405 /* ideally, this should be made aware of embedded autodoc commands */
406 void
autodoc_returns(comment)407 autodoc_returns(comment)
408 const char *comment;
409 {
410     enum { TEXT, PERIOD, CAPITALISE } state = CAPITALISE;
411     char lastchar = '\n';
412     boolean tag_list_started = FALSE;
413 
414     /* for each line... */
415     while (*comment)
416     {
417 	boolean tagged = FALSE;
418 
419 	{
420 	    const char *c = comment;
421 
422 	    /* search along until the end of a word */
423 	    while (*c && *c != ':' && !isspace(*c))
424 		c++;
425 
426 	    /* skip all spaces or tabs after the first word */
427 	    while (*c && *c != '\n')
428 	    {
429 		if (*c == '\t' || *c == ':')
430 		{
431 		    tagged = TRUE;
432 		    break;
433 		}
434 		else if (!isspace(*c))
435 		    break;
436 
437 		c++;
438 	    }
439 	}
440 
441 	/* is it tagged?; explicitly reject dot commands */
442 	if (tagged)
443 	{
444 	    /* output lingering newline if necessary */
445 	    if (lastchar != '\n')
446 	    {
447 		if (state == TEXT && !ispunct(lastchar))	output->character('.');
448 		output->character(lastchar = '\n');
449 	    }
450 
451 	    if (!tag_list_started)
452 	    {
453 		output->tag_list_start();
454 		tag_list_started = TRUE;
455 	    }
456 
457 	    /* output the taggy bit */
458 	    output->tag_entry_start();
459 	    while (*comment && *comment != ':' && !isspace(*comment))
460 		output->character(*comment++);
461 	    output->tag_entry_end();
462 
463 	    /* skip any extra tabs or spaces */
464 	    while (*comment == ':' || (isspace(*comment) && *comment != '\n'))
465 		comment++;
466 
467 	    state = CAPITALISE;
468 	}
469 
470 	/* terminate the previous line if necessary */
471 	if (lastchar != '\n')	output->character(lastchar = '\n');
472 
473 	/* correct punctuation a bit as the line goes out */
474 	for (;*comment && *comment != '\n'; comment++)
475 	{
476 	    char c = *comment;
477 
478 	    if (c == '.')
479 		state = PERIOD;
480 	    else if (isspace(c) && state == PERIOD)
481 		state = CAPITALISE;
482 	    else if (isalnum(c))
483 	    {
484 		if (islower(c) && state == CAPITALISE && fixup_comments)
485 		    c = toupper(c);
486 		state = TEXT;
487 	    }
488 
489 	    output->character(lastchar = c);
490 	}
491 
492 	/* if it ended in punctuation, just output the nl straight away. */
493 	if (ispunct(lastchar))
494 	{
495 	    if (lastchar == '.')	state = CAPITALISE;
496 	    output->character(lastchar = '\n');
497 	}
498 
499 	if (*comment)	comment++;
500     }
501 
502     /* output lingering newline if necessary */
503     if (lastchar != '\n')
504     {
505 	if (state == TEXT && !ispunct(lastchar) && fixup_comments)
506 	    output->character('.');
507 	output->character('\n');
508     }
509 
510     if (tag_list_started)
511 	output->tag_list_end();
512 }
513 
514 
515 struct Output autodoc_output =
516 {
517     autodoc_comment,
518     autodoc_header,
519     autodoc_dash,
520     autodoc_section,
521     autodoc_sub_section,
522     autodoc_break_line,
523     autodoc_blank_line,
524     autodoc_code_start,
525     autodoc_code_end,
526     autodoc_code,
527     dummy,              /* autodoc_tag_list_start */
528     dummy,              /* autodoc_tag_list_end */
529     autodoc_tag_entry_start,
530     autodoc_tag_entry_start_extra,
531     autodoc_tag_entry_end,
532     autodoc_tag_entry_end_extra,
533     autodoc_table_start,
534     autodoc_table_entry,
535     autodoc_table_end,
536     autodoc_indent,
537     autodoc_list_start,
538     autodoc_code,         /* autodoc_list_entry */
539     autodoc_list_separator,
540     autodoc_list_end,
541     autodoc_include,
542     autodoc_file_end,      /* autodoc_file_end */
543     autodoc_text,
544     autodoc_char,
545     NULL,                  /* autodoc_parse_option */
546     dummy,                 /* autodoc_print_options */
547     autodoc_name,
548     autodoc_terse_sep,
549     autodoc_text,          /* autodoc_reference */
550     autodoc_text,          /* autodoc_emphasized */
551     autodoc_description,
552     autodoc_returns
553 };
554 
555