Pristine Ack-5.5
[Ack-5.5.git] / util / ack / scan.c
1 /*
2  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3  * See the copyright notice in the ACK home directory, in the file "Copyright".
4  *
5  */
6
7 #include "ack.h"
8 #include "list.h"
9 #include "trans.h"
10 #include "data.h"
11
12 #ifndef NORCSID
13 static char rcs_id[] = "$Id: scan.c,v 2.9 1994/06/24 10:13:09 ceriel Exp $" ;
14 #endif
15
16 enum f_path getpath(first) register trf **first ; {
17         /* Try to find a transformation path */
18
19         start_scan();
20         /*
21                 The end result is the chaining of
22                 the consequtive phases with the t_next field.
23                 The list is scanned for possible transformations
24                 stopping at stopsuffix or the last transformation in the list.
25                 The scan flags are set by this process.
26                 When a transformation is found, it is compared with
27                 the last transformation found.
28         */
29         try(l_first(tr_list),p_suffix);
30         return scan_end(first);
31 }
32
33 /******************** data used only while scanning *******************/
34
35 static  int     last_pcount;    /* The added priority of
36                                    the best path so far */
37
38 static  int     last_ncount;    /* The # of non-optimizing transformations
39                                    in the best path sofar */
40
41 static  int     last_ocount;    /* The # of optimizing transformations in the
42                                    best path sofar */
43
44 static  int     suf_found;      /* Was the suffix at least recognized ? */
45
46 /********************       The hard work          ********************/
47
48 start_scan() {
49         register list_elem *scan ;
50
51         scanlist(l_first(tr_list),scan) {
52                 t_cont(*scan)->t_scan=NO ;
53         }
54         suf_found= 0 ;
55 #ifdef DEBUG
56         if ( debug>=3 ) vprint("Scan_start\n");
57 #endif
58         last_ncount= -1 ;
59         last_ocount= 0 ;
60 }
61
62 try(f_scan,suffix) list_elem *f_scan; char *suffix; {
63         register list_elem *scan ;
64         register trf  *trafo ;
65         /* Try to find a transformation path starting at f_scan for a
66            file with the indicated suffix.
67            If the suffix is already reached or a combiner is found
68            call scan_found() to OK the scan.
69            If a transformation is found it calls itself recursively
70            with as starting point the next transformation in the list.
71         */
72         if ( stopsuffix && *stopsuffix && strcmp(stopsuffix,suffix)==0 ) {
73                 scan_found();
74                 return ;
75         }
76         if (! f_scan) return;
77         scanlist(f_scan, scan) {
78                 trafo= t_cont(*scan) ;
79                 if ( satisfy(trafo,suffix) ) {
80                         /* Found a transformation */
81                         suf_found= 1;
82 #ifdef DEBUG
83                         if ( debug>=4 ) {
84                                 vprint("Found %s for %s: result %s\n",
85                                        trafo->t_name,suffix,trafo->t_out);
86                         }
87 #endif
88                         trafo->t_scan=YES ;
89                         if ( trafo->t_prep ) {
90                                 if ( !cpp_trafo ) {
91                                         find_cpp() ;
92                                 }
93                                 if ( stopsuffix &&
94                                      strcmp(stopsuffix,
95                                         cpp_trafo->t_out)==0 )
96                                 {
97                                         scan_found() ;
98                                         return ;
99                                 }
100                         }
101                         if ( trafo->t_next ) {
102                                 /* We know what happens from this phase on,
103                                    so take a shortcut.
104                                 */
105                                 register trf *sneak ;
106                                 sneak= trafo ;
107                                 while( sneak=sneak->t_next ) {
108                                         sneak->t_scan=YES ;
109                                 }
110                                 scan_found() ;
111                                 sneak= trafo ;
112                                 while( sneak=sneak->t_next ) {
113                                         sneak->t_scan=NO ;
114                                 }
115                                 return ;
116                         }
117                         if ( trafo->t_linker && stopsuffix && !*stopsuffix ) {
118                                 trafo->t_scan=NO ;
119                                 scan_found() ;
120                                 return ;
121                         }
122                         if (! l_next(*scan) && !stopsuffix) {
123                                 scan_found() ;
124                         } else {
125                                 try(l_next(*scan),trafo->t_out);
126                         }
127                         trafo->t_scan= NO ;
128                 }
129         }
130 }
131
132 scan_found() {
133         register list_elem *scan;
134         int ncount, ocount, pcount ;
135
136         suf_found= 1;
137 #ifdef DEBUG
138         if ( debug>=3 ) vprint("Scan found\n") ;
139 #endif
140         /* Gather data used in comparison */
141         ncount=0; ocount=0; pcount=0;
142         scanlist(l_first(tr_list),scan) {
143                 if (t_cont(*scan)->t_scan) {
144 #ifdef DEBUG
145                         if ( debug>=4 ) vprint("%s-",t_cont(*scan)->t_name) ;
146 #endif
147                         if( t_cont(*scan)->t_optim ) ocount++ ;else ncount++ ;
148                         if( t_cont(*scan)->t_optim>Optlevel ) pcount-- ;
149                         pcount += t_cont(*scan)->t_priority ;
150                 }
151         }
152 #ifdef DEBUG
153         if ( debug>=4 ) vprint("\n");
154 #endif
155         /* Is this transformation better then any found yet ? */
156 #ifdef DEBUG
157         if ( debug>=3 ) {
158                 vprint("old n:%d, o:%d, p:%d - new n:%d, o:%d, p:%d\n",
159                         last_ncount,last_ocount,last_pcount,
160                         ncount,ocount,pcount) ;
161         }
162 #endif
163         if ( last_ncount== -1 ||                /* None found yet */
164              last_pcount<pcount ||              /* Better priority */
165              ( last_pcount==pcount &&           /* Same prio, and */
166                 ( last_ncount>ncount ||              /* Shorter nec. path */
167                   (last_ncount==ncount &&            /* Same nec. path, optimize?*/
168                     (Optlevel? last_ocount<ocount : last_ocount>ocount ))))) {
169                 /* Yes it is */
170 #ifdef DEBUG
171                 if ( debug>=3 ) vprint("Better\n");
172 #endif
173                 scanlist(l_first(tr_list),scan) {
174                         t_cont(*scan)->t_bscan=t_cont(*scan)->t_scan;
175                 }
176                 last_ncount=ncount; last_ocount=ocount; last_pcount=pcount;
177         }
178 }
179
180 int satisfy(trafo,suffix) register trf *trafo; char *suffix ; {
181         register char *f_char, *l_char ;
182         /* Check whether this transformation is present for
183            the current machine and the parameter suffix is among
184            the input suffices. If so, return 1. 0 otherwise
185         */
186         if ( trafo->t_isprep ) return 0 ;
187         l_char=trafo->t_in ;
188         while ( l_char ) {
189                 f_char= l_char ;
190                 if ( *f_char!=SUFCHAR || ! *(f_char+1) ) {
191                         fuerror("Illegal input suffix entry for %s",
192                                 trafo->t_name) ;
193                 }
194                 l_char=strindex(f_char+1,SUFCHAR);
195                 if ( l_char ) *l_char = 0;
196                 if ( strcmp(f_char,suffix)==0 ) {
197                         if ( l_char ) *l_char = SUFCHAR;
198                         return 1;
199                 }
200                 if ( l_char ) *l_char = SUFCHAR;
201         }
202         return 0 ;
203 }
204
205 enum f_path scan_end(first) trf **first ; {    /* Finalization */
206         /* Return value indicating whether a transformation was found */
207         /* Set the flags for the transformation up to, but not including,
208            the combiner
209         */
210         register trf *prev, *curr ;
211         register list_elem *scan;
212
213 #ifdef DEBUG
214         if ( debug>=3 ) vprint("End_scan\n");
215 #endif
216         if ( last_ncount== -1 ) return suf_found ? F_NOPATH : F_NOMATCH ;
217 #ifdef DEBUG
218         if ( debug>=2 ) vprint("Transformation found\n");
219 #endif
220         prev= (trf *)0 ; *first= prev ;
221         scanlist(l_first(tr_list),scan) {
222                 curr= t_cont(*scan) ;
223                 if ( curr->t_bscan ) {
224                         if ( prev ) {
225                                 prev->t_next= curr ;
226                                 if ( curr->t_linker ) prev->t_keep=YES ;
227                         } else {
228                                 *first= curr ;
229                         }
230                         if ( curr->t_next ) {
231                                 return F_OK ;
232                         }
233                         prev=curr ;
234                 }
235         }
236         if ( cpp_trafo && stopsuffix &&
237              strcmp(stopsuffix,cpp_trafo->t_out)==0 ) {
238                 cpp_trafo->t_keep=YES ;
239         }
240         if ( prev ) {
241                 prev->t_keep=YES ;
242         }
243         return F_OK ;
244 }
245
246 find_cpp() {
247         register list_elem *elem ;
248         scanlist( l_first(tr_list), elem ) {
249                 if ( t_cont(*elem)->t_isprep ) {
250                         if ( cpp_trafo ) fuerror("Multiple cpp's present") ;
251                         cpp_trafo= t_cont(*elem) ;
252                 }
253         }
254         if ( !cpp_trafo ) fuerror("No cpp present") ;
255 }