removal due to another working script
[trueprint.git] / src / index.c
blob7d563969dd6b10b31d1c7fe3105cae0aaf45d589
1 /*
2 * Source file:
3 * index.c
4 */
6 #include "config.h"
8 #if TM_IN_SYS_TIME
9 # include <sys/time.h>
10 #else
11 # include <time.h>
12 #endif
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <unistd.h>
21 #include "trueprint.h"
22 #include "main.h"
23 #include "headers.h"
24 #include "postscript.h"
25 #include "debug.h"
26 #include "utils.h"
28 #include "index.h"
31 * Public part
35 * Private part
37 #define LINE 0
38 #define INPUT_END 1
39 #define BLOCK_SIZE 1000
41 typedef struct {
42 char name[SYMBOL_LEN];
43 long name_start_char;
44 long name_end_char;
45 long page_number;
46 long end_page;
47 boolean changed;
48 char *filename;
49 } function_entry;
51 typedef struct {
52 long starting_page;
53 long ending_page;
54 char *name;
55 time_t modified;
56 } file_entry;
58 typedef struct {
59 boolean changed;
60 } page_entry;
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 /*****************************************************************************
83 * Function:
84 * setup_index
86 void
87 setup_index(void)
89 max_function_name_length = 0;
90 max_file_name_length = 0;
92 no_of_functions=0;
93 function_list_size = 0;
94 file_list_size = 0;
95 page_list_size = 0;
96 functions = NULL;
97 sorted_functions = NULL;
98 files = NULL;
99 pages = NULL;
101 current_function_changed = FALSE;
104 /*****************************************************************************
105 * Function:
106 * grow_array
108 static void
109 grow_array(void *list_ptr_ptr, unsigned int *list_size_ptr, size_t list_entry_size)
112 size_t size_needed;
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);
122 else
123 *(void **)list_ptr_ptr = xrealloc(*(void **)list_ptr_ptr, size_needed);
126 /*****************************************************************************
127 * Function:
128 * page_has_changed
130 * Flag this page and function as containing a change
132 void
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 /*****************************************************************************
146 * Function:
147 * add_file
149 * Remembers the starting page and other info for the named file.
151 void
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");
167 exit(1);
170 files[this_file_number].modified = stat_buffer.st_mtime;
171 } else {
172 files[this_file_number].modified = 0;
175 if (length > max_file_name_length)
176 max_file_name_length = length;
179 /*****************************************************************************
180 * Function:
181 * end_file
183 * Remembers the ending page for the named file.
185 void
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 /*****************************************************************************
196 * Function:
197 * get_file_last_page
199 * Return the last page number for a file
201 long
202 get_file_last_page(unsigned int this_file_number)
205 return files[this_file_number].ending_page;
208 /*****************************************************************************
209 * Function:
210 * get_file_first_page
212 * Return the first page number for a file
214 long
215 get_file_first_page(unsigned int this_file_number)
218 return files[this_file_number].starting_page;
221 /*****************************************************************************
222 * Function:
223 * get_file_modified_time
225 * Return the struct time_t containing the last modified time of the file
227 struct tm *
228 get_file_modified_time(unsigned int this_file_number)
231 if (files[this_file_number].modified == 0)
232 return NULL;
234 return localtime(&files[this_file_number].modified);
237 /*****************************************************************************
238 * Function:
239 * add_function.
241 * Remembers the start and end characters, the page number and the filename
242 * for the named function.
244 void
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",
252 name,page,filename);
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 /*****************************************************************************
268 * Function:
269 * end_function
271 * Remembers the end page for the current function, and gets ready for
272 * information on the next function.
274 void
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 /*****************************************************************************
287 * Function:
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.
293 char_status
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);
310 return(CHAR_BOLD);
313 return(current_status);
316 /*****************************************************************************
317 * Function:
318 * get_function_name
320 * Get the current function name for the specified page.
322 char *
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);
333 for (;;)
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 /*****************************************************************************
349 * Function:
350 * get_file_name
352 * Get the appropriate file name
355 char *
356 file_name(int file_number)
359 return files[file_number].name;
362 /*****************************************************************************
363 * Function:
364 * function_changed
366 * Has the current function changed?
368 boolean
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);
376 for (;;)
378 if (page < functions[current_function].page_number)
379 return(FALSE);
380 if (page <= functions[current_function].end_page)
381 return(functions[current_function].changed);
382 if (current_function >= no_of_functions-1)
383 return(FALSE);
384 current_function += 1;
388 /*****************************************************************************
389 * Function:
390 * page_changed
392 * Has the current page changed?
394 boolean
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 /*****************************************************************************
405 * Function:
406 * dot_fill
408 * Take a string and fill in the middle set of spaces with dots.
410 void
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 /*****************************************************************************
426 * Function:
427 * compare
429 * Compares two function entries, used by qsort().
430 * Looks at name first, then start char.
433 compare(const void *p1, const void *p2)
436 int r;
437 r = strcmp(((function_entry *)p1)->name,((function_entry *)p2)->name);
438 if (r == 0)
440 if (((function_entry *)p1)->name_start_char > ((function_entry *)p2)->name_start_char)
441 r = 1;
442 else
443 if (((function_entry *)p1)->name_start_char < ((function_entry *)p2)->name_start_char)
444 r = -1;
445 else
446 r = 0;
448 return r;
451 /*****************************************************************************
452 * Function:
453 * sort_function_names
455 * Sort the array of function records into alphabetical order into the
456 * array sorted_functions[].
458 void
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 /*****************************************************************************
476 * Function:
477 * print_index
479 * Print out the contents of sorted_functions in order on a page or pages.
481 void
482 print_index(void)
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;
496 * For every page...
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);
530 else
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;
539 function_idx += 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 /*****************************************************************************
562 * Function:
563 * print_index_line
565 * Prints out a line of the file index, which is either a filename or
566 * a function name within the current file.
568 short
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().
582 if (first_call)
584 printf("Lpt( %-24s %5ld) BF setfont show CF setfont Nl\n",
585 files[current_file].name,
586 files[current_file].starting_page);
587 first_call = FALSE;
588 return(LINE);
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 */
601 function_idx += 1;
602 continue;
604 else
605 break;
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);
622 function_idx = 0;
623 return(LINE);
627 * If "print_bold" then fill in with dots while printing out
628 * function details.
630 if (print_bold)
632 char string[INPUT_LINE_LEN];
634 sprintf(string," %-24s %4ld",
635 sorted_functions[function_idx].name,
636 sorted_functions[function_idx].page_number);
637 dot_fill(string);
639 printf("Lpt(%s) show Nl\n",string);
641 else
643 printf("Lpt( %-24s %4ld) show Nl\n",
644 sorted_functions[function_idx].name,
645 sorted_functions[function_idx].page_number);
647 function_idx += 1;
648 return(LINE);
651 /*****************************************************************************
652 * Function:
653 * print_out_file_index
655 * Print out the contents of sorted_functions in order per file.
657 void
658 print_out_file_index(void)
661 long index_page_number=0;
662 short output_line_number;
663 short retval = LINE;
664 boolean reached_end_of_sheet;
667 * For every page...
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)
685 PUTS(" ");
686 if ((retval = print_index_line(output_line_number &1))
687 == INPUT_END) break;
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);