17 #include <sys/types.h>
21 #include "trueprint.h"
24 #include "postscript.h"
39 #define BLOCK_SIZE 1000
42 char name
[SYMBOL_LEN
];
62 static void dot_fill(char string
[]);
63 static int compare(const void *, const void *);
64 static short print_index_line(int print_bold
);
66 static size_t max_function_name_length
= 0;
67 static size_t max_file_name_length
= 0;
69 static unsigned short no_of_functions
=0;
70 static unsigned int function_list_size
= 0;
71 static unsigned int file_list_size
= 0;
72 static unsigned int page_list_size
= 0;
73 static function_entry
*functions
= NULL
;
74 static function_entry
*sorted_functions
= NULL
;
75 static file_entry
*files
= NULL
;
76 static page_entry
*pages
= NULL
;
78 static boolean current_function_changed
= FALSE
;
80 static void grow_array(void *list_ptr_ptr
, unsigned int *, size_t);
82 /*****************************************************************************
89 max_function_name_length
= 0;
90 max_file_name_length
= 0;
93 function_list_size
= 0;
97 sorted_functions
= NULL
;
101 current_function_changed
= FALSE
;
104 /*****************************************************************************
109 grow_array(void *list_ptr_ptr
, unsigned int *list_size_ptr
, size_t list_entry_size
)
114 *list_size_ptr
+= BLOCK_SIZE
;
116 size_needed
= *list_size_ptr
* list_entry_size
;
118 dm('i',3,"index.c:grow_array() Growing array by %d bytes\n", size_needed
);
120 if (*(void **)list_ptr_ptr
== NULL
)
121 *(void **)list_ptr_ptr
= xmalloc(size_needed
);
123 *(void **)list_ptr_ptr
= xrealloc(*(void **)list_ptr_ptr
, size_needed
);
126 /*****************************************************************************
130 * Flag this page and function as containing a change
133 page_has_changed(long this_page_number
)
136 if (pass
== 1) return;
138 while (this_page_number
>= page_list_size
)
139 grow_array(&pages
, &page_list_size
, sizeof(page_entry
));
141 current_function_changed
= TRUE
;
142 pages
[this_page_number
].changed
= TRUE
;
145 /*****************************************************************************
149 * Remembers the starting page and other info for the named file.
152 add_file(char *filename
, unsigned int this_file_number
, long this_file_page_number
)
155 size_t length
= strlen(filename
);
156 struct stat stat_buffer
;
158 if (this_file_number
>= file_list_size
)
159 grow_array(&files
, &file_list_size
, sizeof(file_entry
));
161 files
[this_file_number
].starting_page
= this_file_page_number
;
162 files
[this_file_number
].name
= strdup(filename
);
164 if (strcmp(filename
,"-") != 0) {
165 if (stat(filename
,&stat_buffer
) == -1) {
166 perror(CMD_NAME
": cannot stat file");
170 files
[this_file_number
].modified
= stat_buffer
.st_mtime
;
172 files
[this_file_number
].modified
= 0;
175 if (length
> max_file_name_length
)
176 max_file_name_length
= length
;
179 /*****************************************************************************
183 * Remembers the ending page for the named file.
186 end_file(unsigned int this_file_number
, long this_file_page_number
)
189 if (this_file_number
>= file_list_size
)
190 grow_array(&files
, &file_list_size
, sizeof(file_entry
));
192 files
[this_file_number
].ending_page
= this_file_page_number
;
195 /*****************************************************************************
199 * Return the last page number for a file
202 get_file_last_page(unsigned int this_file_number
)
205 return files
[this_file_number
].ending_page
;
208 /*****************************************************************************
210 * get_file_first_page
212 * Return the first page number for a file
215 get_file_first_page(unsigned int this_file_number
)
218 return files
[this_file_number
].starting_page
;
221 /*****************************************************************************
223 * get_file_modified_time
225 * Return the struct time_t containing the last modified time of the file
228 get_file_modified_time(unsigned int this_file_number
)
231 if (files
[this_file_number
].modified
== 0)
234 return localtime(&files
[this_file_number
].modified
);
237 /*****************************************************************************
241 * Remembers the start and end characters, the page number and the filename
242 * for the named function.
245 add_function(char *name
, long start
, long end
, long page
, char *filename
)
248 size_t length
= strlen(name
);
249 if (pass
== 1) return;
251 dm('i',2,"index.c:add_function() Adding %s, page %ld filename %s\n",
254 if (no_of_functions
== function_list_size
)
255 grow_array(&functions
, &function_list_size
, sizeof(function_entry
));
257 strcpy(functions
[no_of_functions
].name
, name
);
258 functions
[no_of_functions
].name_start_char
= start
;
259 functions
[no_of_functions
].name_end_char
= end
;
260 functions
[no_of_functions
].page_number
= page
;
261 functions
[no_of_functions
].filename
= filename
;
262 if (length
> max_function_name_length
)
263 max_function_name_length
= length
;
264 current_function_changed
= FALSE
;
267 /*****************************************************************************
271 * Remembers the end page for the current function, and gets ready for
272 * information on the next function.
275 end_function(long page
)
278 if (pass
== 1) return;
280 dm('i',2,"index.c:end_function() Ending function on page %ld\n",page
);
282 functions
[no_of_functions
].changed
= current_function_changed
;
283 functions
[no_of_functions
++].end_page
= page
;
286 /*****************************************************************************
288 * get_function_name_posn
290 * Looks at current_char and returns whether this character starts a
291 * function name, ends a function name, or does neither.
294 get_function_name_posn(long current_char
, char_status current_status
)
297 static unsigned short current_function
=0;
299 if (pass
==0) return(current_status
);
301 /* If there were no functions simply return CHAR */
302 if (no_of_functions
== 0) return (current_status
);
304 if ((current_char
>= functions
[current_function
].name_start_char
)
305 && (current_char
<= functions
[current_function
].name_end_char
))
307 if (current_char
== functions
[current_function
].name_end_char
)
308 current_function
+= 1;
309 dm('i',5,"index.c:get_function_name_posn() Returning TRUE for char posn %ld\n", current_char
);
313 return(current_status
);
316 /*****************************************************************************
320 * Get the current function name for the specified page.
323 get_function_name(long page
)
326 unsigned short current_function
=0;
327 static char dummy_return
[] = "";
329 dm('i',4,"Index: Searching for function name for page %ld\n",page
);
331 if ((pass
==0) || (no_of_functions
== 0)) return(dummy_return
);
335 if (page
< functions
[current_function
].page_number
)
336 return(dummy_return
);
337 if (page
<= functions
[current_function
].end_page
)
339 dm('i',4,"Index: Function name for page %ld = %s\n",page
,functions
[current_function
].name
);
340 return(functions
[current_function
].name
);
342 if (current_function
>= no_of_functions
-1)
343 return(dummy_return
);
344 current_function
+= 1;
348 /*****************************************************************************
352 * Get the appropriate file name
356 file_name(int file_number
)
359 return files
[file_number
].name
;
362 /*****************************************************************************
366 * Has the current function changed?
369 function_changed(long page
)
372 static unsigned short current_function
=0;
374 if (pass
==0) return(FALSE
);
375 if (no_of_functions
== 0) return(FALSE
);
378 if (page
< functions
[current_function
].page_number
)
380 if (page
<= functions
[current_function
].end_page
)
381 return(functions
[current_function
].changed
);
382 if (current_function
>= no_of_functions
-1)
384 current_function
+= 1;
388 /*****************************************************************************
392 * Has the current page changed?
395 page_changed(long page
)
398 if (pass
== 0) return FALSE
;
399 if (page
> page_list_size
) return FALSE
;
401 return pages
[page
].changed
;
404 /*****************************************************************************
408 * Take a string and fill in the middle set of spaces with dots.
411 dot_fill(char string
[])
414 short string_index
= 0;
416 /* Find the end of the first set of spaces */
417 while (string
[string_index
] == ' ') string_index
+= 1;
418 /* Find the start of the second set of spaces */
419 while (string
[string_index
] != ' ') string_index
+= 1;
420 /* Change spaces to dots */
421 while (string
[string_index
] == ' ')
422 string
[string_index
++] = '.';
425 /*****************************************************************************
429 * Compares two function entries, used by qsort().
430 * Looks at name first, then start char.
433 compare(const void *p1
, const void *p2
)
437 r
= strcmp(((function_entry
*)p1
)->name
,((function_entry
*)p2
)->name
);
440 if (((function_entry
*)p1
)->name_start_char
> ((function_entry
*)p2
)->name_start_char
)
443 if (((function_entry
*)p1
)->name_start_char
< ((function_entry
*)p2
)->name_start_char
)
451 /*****************************************************************************
453 * sort_function_names
455 * Sort the array of function records into alphabetical order into the
456 * array sorted_functions[].
459 sort_function_names(void)
462 unsigned short every_function
;
464 size_t size_needed
= function_list_size
* sizeof(function_entry
);
466 if (function_list_size
== 0) return;
468 sorted_functions
= xmalloc(size_needed
);
470 for (every_function
=0;every_function
<no_of_functions
;every_function
++)
471 sorted_functions
[every_function
] = functions
[every_function
];
472 qsort((char *)sorted_functions
,(int)no_of_functions
,sizeof(function_entry
),compare
);
475 /*****************************************************************************
479 * Print out the contents of sorted_functions in order on a page or pages.
485 unsigned short function_idx
=0;
486 long index_page_number
=0;
487 short output_line_number
;
488 boolean reached_end_of_sheet
;
491 * If there is nothing to print, then print nothing...
493 if (no_of_functions
== 0) return;
500 index_page_number
+= 1;
503 * ...print the header...
505 print_index_header(index_page_number
);
507 output_line_number
= 0;
510 * ...print the index a line at a time...
512 while ((output_line_number
< page_length
)
513 && (function_idx
< no_of_functions
))
516 char output_line
[INPUT_LINE_LEN
];
519 * Every second line has dots in it...
521 if ((function_idx
& 1) == 1)
523 sprintf(output_line
," %-24s %4ld (%s)",
524 sorted_functions
[function_idx
].name
,
525 sorted_functions
[function_idx
].page_number
,
526 sorted_functions
[function_idx
].filename
);
527 dot_fill(output_line
);
528 printf("Lpt(%s) show Nl\n",output_line
);
532 sprintf(output_line
," %-24s %4ld (%s)\n",
533 sorted_functions
[function_idx
].name
,
534 sorted_functions
[function_idx
].page_number
,
535 sorted_functions
[function_idx
].filename
);
536 printf("Lpt(%s) show Nl\n",output_line
);
538 output_line_number
+= 1;
543 * ...and print the footer
545 reached_end_of_sheet
= PS_endpage(TRUE
);
547 } while (function_idx
< no_of_functions
);
550 * Print blank pages until the last page printed was the last page
551 * on a physical sheet.
553 while (!reached_end_of_sheet
)
555 index_page_number
+= 1;
556 print_index_header(index_page_number
);
557 reached_end_of_sheet
= PS_endpage(TRUE
);
561 /*****************************************************************************
565 * Prints out a line of the file index, which is either a filename or
566 * a function name within the current file.
569 print_index_line(int print_bold
)
572 static unsigned int current_file
= 0;
573 static unsigned short function_idx
= 0;
574 static boolean first_call
= TRUE
;
577 * If we haven't started printing out functions for a file
578 * then we have to print out the filename first and we
579 * print it in bold. This will only happen on the first
580 * call to print_index_line().
584 printf("Lpt( %-24s %5ld) BF setfont show CF setfont Nl\n",
585 files
[current_file
].name
,
586 files
[current_file
].starting_page
);
592 * OK, so we need to print out a function name. Find the next
593 * function name belonging to the current file in the sorted
594 * array of functions.
596 while (function_idx
!= no_of_functions
)
598 if (strcmp(files
[current_file
].name
, sorted_functions
[function_idx
].filename
) != 0)
600 /* if no match and not reached end continue with the next function name */
609 * If this comparison is true then we didn't find any more functions for this file.
611 if (function_idx
== no_of_functions
)
613 /* If reached end of last file return */
614 if (++current_file
>= no_of_files
) return(INPUT_END
);
616 * else reached end of this file - print the filename of the next file in
617 * bold and set up for starting printing function names for this title
619 printf("Lpt( %-24s %5ld) BF setfont show CF setfont Nl\n",
620 files
[current_file
].name
,
621 files
[current_file
].starting_page
);
627 * If "print_bold" then fill in with dots while printing out
632 char string
[INPUT_LINE_LEN
];
634 sprintf(string
," %-24s %4ld",
635 sorted_functions
[function_idx
].name
,
636 sorted_functions
[function_idx
].page_number
);
639 printf("Lpt(%s) show Nl\n",string
);
643 printf("Lpt( %-24s %4ld) show Nl\n",
644 sorted_functions
[function_idx
].name
,
645 sorted_functions
[function_idx
].page_number
);
651 /*****************************************************************************
653 * print_out_file_index
655 * Print out the contents of sorted_functions in order per file.
658 print_out_file_index(void)
661 long index_page_number
=0;
662 short output_line_number
;
664 boolean reached_end_of_sheet
;
671 index_page_number
+= 1;
674 * ...print the header...
676 print_file_header(index_page_number
);
678 output_line_number
= 0;
681 * ...print all the lines, every second one with dots...
683 while (output_line_number
< page_length
)
686 if ((retval
= print_index_line(output_line_number
&1))
688 output_line_number
+= 1;
692 * ...and print the footer...
694 reached_end_of_sheet
= PS_endpage(TRUE
);
696 } while (retval
== LINE
);
699 * Print blank pages until the last page printed was the last page
700 * on a physical sheet.
702 while (!reached_end_of_sheet
)
704 index_page_number
+= 1;
705 print_file_header(index_page_number
);
706 reached_end_of_sheet
= PS_endpage(TRUE
);