Pristine Ack-5.5
[Ack-5.5.git] / util / grind / list.c
1 /* $Id: list.c,v 1.9 1994/06/24 11:00:15 ceriel Exp $ */
2
3 #include <stdio.h>
4 #include <alloc.h>
5
6 #include "position.h"
7 #include "idf.h"
8 #include "file.h"
9 #include "symbol.h"
10 #include "misc.h"
11
12 static  line_positions();
13 extern char     *dirs[];
14 extern FILE     *fopen();
15 extern FILE     *db_out;
16 extern t_lineno currline;
17 extern int      interrupted;
18
19 static void
20 mk_filnm(dir, file, newname)
21   char  *dir;
22   char  *file;
23   char  **newname;
24 {
25   register char *dst = Malloc((unsigned) (strlen(dir) + strlen(file) + 2));
26
27   *newname = dst;
28   if (*dir) {
29         while (*dst++ = *dir++) /* nothing */;
30         *(dst - 1) = '/';
31   }
32   while (*dst++ = *file++) /* nothing */;
33 }
34
35 static FILE *
36 open_file(fn, mode, ffn)
37   char  *fn;
38   char  *mode;
39   char  **ffn;
40 {
41   FILE  *f;
42   char  **p;
43
44   if (fn[0] == '/') {
45         *ffn = fn;
46         return fopen(fn, mode);
47   }
48   p = dirs;
49   while (*p) {  
50         mk_filnm(*p++, fn, ffn);
51         if ((f = fopen(*ffn, mode)) != NULL) {
52                 return f;
53         }
54         free(*ffn);
55   }
56   return NULL;
57 }
58
59 lines(file, l1, l2)
60   register p_file file;
61   int           l1, l2;
62 {
63   static p_file last_file;
64   static FILE *last_f;
65   register FILE *f;
66   register int  n;
67
68   if (last_file != file) {
69         if (last_f) fclose(last_f);
70         last_f = 0;
71         if (!(f = open_file(file->f_sym->sy_idf->id_text, 
72                             "r",
73                             &file->f_fullname))) {
74                 error("could not open %s", file->f_sym->sy_idf->id_text);
75                 return;
76         }
77         last_file = file;
78         last_f = f;
79         if (! file->f_linepos) {
80                 line_positions(file, f);
81         }
82   }
83   else f = last_f;
84
85   if (l1 < 1) l1 = 1;
86   if (l1 > file->f_nlines) l1 = file->f_nlines;
87   if (l1+l2-1 > file->f_nlines) l2 = file->f_nlines - l1 + 1;
88
89   fseek(f, *(file->f_linepos+(l1-1)), 0);
90   for (n = l1; n < l1 + l2; n++) {
91         register int    c;
92
93         if (interrupted) return;
94         fprintf(db_out, "%c%5d\t", currfile && file == currfile->sy_file && n == currline ? '>' : ' ', n);
95         do {
96                 c = getc(f);
97                 if (c != EOF) putc(c, db_out);
98         } while (c != '\n' && c != EOF);
99         if (c == EOF) break;
100   }
101   clearerr(f);
102 }
103
104 static
105 line_positions(file, f)
106   p_file        file;
107   register FILE *f;
108 {
109   int           nl;
110   unsigned int  n_alloc = 256;
111   register long cnt = 0;
112   register int  c;
113
114   file->f_linepos = (long *) Malloc(n_alloc * sizeof(long));
115   file->f_linepos[0] = 0;
116   nl = 1;
117   while ((c = getc(f)) != EOF) {
118         cnt++;
119         if (c == '\n') {
120                 if (nl == n_alloc) {
121                         n_alloc <<= 1;
122                         file->f_linepos =
123                                 (long *) Realloc((char *)(file->f_linepos),
124                                                  n_alloc * sizeof(long));
125                 }
126                 file->f_linepos[nl++] = cnt;
127         }
128   }
129   if (cnt == file->f_linepos[nl-1]) nl--;
130   file->f_linepos = (long *) Realloc((char *)(file->f_linepos),
131                                         (unsigned)nl * sizeof(long));
132   file->f_nlines = nl;
133   clearerr(f);
134 }