fsplit.c revision 1.14 1 1.1 cgd /*
2 1.4 perry * Copyright (c) 1983, 1993
3 1.4 perry * The Regents of the University of California. All rights reserved.
4 1.1 cgd *
5 1.1 cgd * This code is derived from software contributed to Berkeley by
6 1.1 cgd * Asa Romberger and Jerry Berkman.
7 1.1 cgd *
8 1.1 cgd * Redistribution and use in source and binary forms, with or without
9 1.1 cgd * modification, are permitted provided that the following conditions
10 1.1 cgd * are met:
11 1.1 cgd * 1. Redistributions of source code must retain the above copyright
12 1.1 cgd * notice, this list of conditions and the following disclaimer.
13 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
14 1.1 cgd * notice, this list of conditions and the following disclaimer in the
15 1.1 cgd * documentation and/or other materials provided with the distribution.
16 1.10 agc * 3. Neither the name of the University nor the names of its contributors
17 1.1 cgd * may be used to endorse or promote products derived from this software
18 1.1 cgd * without specific prior written permission.
19 1.1 cgd *
20 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 1.1 cgd * SUCH DAMAGE.
31 1.1 cgd */
32 1.1 cgd
33 1.5 lukem #include <sys/cdefs.h>
34 1.1 cgd #ifndef lint
35 1.13 lukem __COPYRIGHT("@(#) Copyright (c) 1983, 1993\
36 1.13 lukem The Regents of the University of California. All rights reserved.");
37 1.1 cgd #endif /* not lint */
38 1.1 cgd
39 1.1 cgd #ifndef lint
40 1.5 lukem #if 0
41 1.5 lukem static char sccsid[] = "from: @(#)fsplit.c 8.1 (Berkeley) 6/6/93";
42 1.6 wsanchez #else
43 1.14 dholland __RCSID("$NetBSD: fsplit.c,v 1.14 2008/11/16 03:13:39 dholland Exp $");
44 1.5 lukem #endif
45 1.1 cgd #endif /* not lint */
46 1.1 cgd
47 1.5 lukem #include <sys/types.h>
48 1.5 lukem #include <sys/stat.h>
49 1.5 lukem
50 1.1 cgd #include <ctype.h>
51 1.1 cgd #include <stdio.h>
52 1.8 matt #include <stdlib.h>
53 1.3 cgd #include <string.h>
54 1.5 lukem #include <unistd.h>
55 1.12 dholland #include <err.h>
56 1.1 cgd
57 1.1 cgd /*
58 1.1 cgd * usage: fsplit [-e efile] ... [file]
59 1.1 cgd *
60 1.1 cgd * split single file containing source for several fortran programs
61 1.1 cgd * and/or subprograms into files each containing one
62 1.1 cgd * subprogram unit.
63 1.1 cgd * each separate file will be named using the corresponding subroutine,
64 1.1 cgd * function, block data or program name if one is found; otherwise
65 1.1 cgd * the name will be of the form mainNNN.f or blkdtaNNN.f .
66 1.1 cgd * If a file of that name exists, it is saved in a name of the
67 1.1 cgd * form zzz000.f .
68 1.1 cgd * If -e option is used, then only those subprograms named in the -e
69 1.1 cgd * option are split off; e.g.:
70 1.1 cgd * fsplit -esub1 -e sub2 prog.f
71 1.1 cgd * isolates sub1 and sub2 in sub1.f and sub2.f. The space
72 1.1 cgd * after -e is optional.
73 1.1 cgd *
74 1.1 cgd * Modified Feb., 1983 by Jerry Berkman, Computing Services, U.C. Berkeley.
75 1.1 cgd * - added comments
76 1.1 cgd * - more function types: double complex, character*(*), etc.
77 1.1 cgd * - fixed minor bugs
78 1.1 cgd * - instead of all unnamed going into zNNN.f, put mains in
79 1.1 cgd * mainNNN.f, block datas in blkdtaNNN.f, dups in zzzNNN.f .
80 1.1 cgd */
81 1.1 cgd
82 1.1 cgd #define BSZ 512
83 1.1 cgd char buf[BSZ];
84 1.1 cgd FILE *ifp;
85 1.1 cgd char x[]="zzz000.f",
86 1.1 cgd mainp[]="main000.f",
87 1.1 cgd blkp[]="blkdta000.f";
88 1.5 lukem
89 1.14 dholland void badparms(void);
90 1.14 dholland char *functs(char *);
91 1.14 dholland int getline(void);
92 1.14 dholland void get_name(char *, int);
93 1.14 dholland int main(int, char **);
94 1.14 dholland int lend(void);
95 1.14 dholland int lname(char *, size_t);
96 1.14 dholland char *look(char *, char *);
97 1.14 dholland int saveit(char *);
98 1.14 dholland int scan_name(char *, char *);
99 1.14 dholland char *skiplab(char *);
100 1.1 cgd
101 1.1 cgd #define TRUE 1
102 1.1 cgd #define FALSE 0
103 1.1 cgd int extr = FALSE,
104 1.1 cgd extrknt = -1,
105 1.1 cgd extrfnd[100];
106 1.1 cgd char extrbuf[1000],
107 1.1 cgd *extrnames[100];
108 1.1 cgd struct stat sbuf;
109 1.1 cgd
110 1.1 cgd #define trim(p) while (*p == ' ' || *p == '\t') p++
111 1.1 cgd
112 1.5 lukem int
113 1.14 dholland main(int argc, char **argv)
114 1.1 cgd {
115 1.5 lukem FILE *ofp; /* output file */
116 1.5 lukem int rv; /* 1 if got card in output file, 0 otherwise */
117 1.5 lukem char *ptr;
118 1.5 lukem int nflag; /* 1 if got name of subprog., 0 otherwise */
119 1.5 lukem int retval, i;
120 1.5 lukem char name[20], *extrptr = extrbuf;
121 1.1 cgd
122 1.1 cgd /* scan -e options */
123 1.1 cgd while ( argc > 1 && argv[1][0] == '-' && argv[1][1] == 'e') {
124 1.1 cgd extr = TRUE;
125 1.1 cgd ptr = argv[1] + 2;
126 1.1 cgd if(!*ptr) {
127 1.1 cgd argc--;
128 1.1 cgd argv++;
129 1.1 cgd if(argc <= 1) badparms();
130 1.1 cgd ptr = argv[1];
131 1.1 cgd }
132 1.1 cgd extrknt = extrknt + 1;
133 1.1 cgd extrnames[extrknt] = extrptr;
134 1.1 cgd extrfnd[extrknt] = FALSE;
135 1.1 cgd while(*ptr) *extrptr++ = *ptr++;
136 1.1 cgd *extrptr++ = 0;
137 1.1 cgd argc--;
138 1.1 cgd argv++;
139 1.1 cgd }
140 1.1 cgd
141 1.1 cgd if (argc > 2)
142 1.1 cgd badparms();
143 1.1 cgd else if (argc == 2) {
144 1.1 cgd if ((ifp = fopen(argv[1], "r")) == NULL) {
145 1.1 cgd fprintf(stderr, "fsplit: cannot open %s\n", argv[1]);
146 1.1 cgd exit(1);
147 1.1 cgd }
148 1.1 cgd }
149 1.1 cgd else
150 1.1 cgd ifp = stdin;
151 1.1 cgd for(;;) {
152 1.1 cgd /* look for a temp file that doesn't correspond to an existing file */
153 1.1 cgd get_name(x, 3);
154 1.1 cgd ofp = fopen(x, "w");
155 1.12 dholland if (ofp == NULL) {
156 1.12 dholland err(1, "%s", x);
157 1.12 dholland }
158 1.1 cgd nflag = 0;
159 1.1 cgd rv = 0;
160 1.1 cgd while (getline() > 0) {
161 1.1 cgd rv = 1;
162 1.1 cgd fprintf(ofp, "%s", buf);
163 1.1 cgd if (lend()) /* look for an 'end' statement */
164 1.1 cgd break;
165 1.1 cgd if (nflag == 0) /* if no name yet, try and find one */
166 1.9 itojun nflag = lname(name, sizeof(name));
167 1.1 cgd }
168 1.1 cgd fclose(ofp);
169 1.1 cgd if (rv == 0) { /* no lines in file, forget the file */
170 1.1 cgd unlink(x);
171 1.1 cgd retval = 0;
172 1.1 cgd for ( i = 0; i <= extrknt; i++ )
173 1.1 cgd if(!extrfnd[i]) {
174 1.1 cgd retval = 1;
175 1.1 cgd fprintf( stderr, "fsplit: %s not found\n",
176 1.1 cgd extrnames[i]);
177 1.1 cgd }
178 1.1 cgd exit( retval );
179 1.1 cgd }
180 1.1 cgd if (nflag) { /* rename the file */
181 1.1 cgd if(saveit(name)) {
182 1.1 cgd if (stat(name, &sbuf) < 0 ) {
183 1.1 cgd link(x, name);
184 1.1 cgd unlink(x);
185 1.1 cgd printf("%s\n", name);
186 1.1 cgd continue;
187 1.1 cgd } else if (strcmp(name, x) == 0) {
188 1.1 cgd printf("%s\n", x);
189 1.1 cgd continue;
190 1.1 cgd }
191 1.1 cgd printf("%s already exists, put in %s\n", name, x);
192 1.1 cgd continue;
193 1.1 cgd } else
194 1.1 cgd unlink(x);
195 1.1 cgd continue;
196 1.1 cgd }
197 1.1 cgd if(!extr)
198 1.1 cgd printf("%s\n", x);
199 1.1 cgd else
200 1.1 cgd unlink(x);
201 1.1 cgd }
202 1.1 cgd }
203 1.1 cgd
204 1.5 lukem void
205 1.14 dholland badparms(void)
206 1.1 cgd {
207 1.1 cgd fprintf(stderr, "fsplit: usage: fsplit [-e efile] ... [file] \n");
208 1.1 cgd exit(1);
209 1.1 cgd }
210 1.1 cgd
211 1.5 lukem int
212 1.14 dholland saveit(char *name)
213 1.1 cgd {
214 1.1 cgd int i;
215 1.1 cgd char fname[50],
216 1.1 cgd *fptr = fname;
217 1.1 cgd
218 1.1 cgd if(!extr) return(1);
219 1.1 cgd while(*name) *fptr++ = *name++;
220 1.1 cgd *--fptr = 0;
221 1.1 cgd *--fptr = 0;
222 1.1 cgd for ( i=0 ; i<=extrknt; i++ )
223 1.1 cgd if( strcmp(fname, extrnames[i]) == 0 ) {
224 1.1 cgd extrfnd[i] = TRUE;
225 1.1 cgd return(1);
226 1.1 cgd }
227 1.1 cgd return(0);
228 1.1 cgd }
229 1.1 cgd
230 1.5 lukem void
231 1.14 dholland get_name(char *name, int letters)
232 1.1 cgd {
233 1.5 lukem char *ptr;
234 1.1 cgd
235 1.1 cgd while (stat(name, &sbuf) >= 0) {
236 1.1 cgd for (ptr = name + letters + 2; ptr >= name + letters; ptr--) {
237 1.1 cgd (*ptr)++;
238 1.1 cgd if (*ptr <= '9')
239 1.1 cgd break;
240 1.1 cgd *ptr = '0';
241 1.1 cgd }
242 1.1 cgd if(ptr < name + letters) {
243 1.1 cgd fprintf( stderr, "fsplit: ran out of file names\n");
244 1.1 cgd exit(1);
245 1.1 cgd }
246 1.1 cgd }
247 1.1 cgd }
248 1.1 cgd
249 1.5 lukem int
250 1.14 dholland getline(void)
251 1.1 cgd {
252 1.5 lukem char *ptr;
253 1.1 cgd
254 1.1 cgd for (ptr = buf; ptr < &buf[BSZ]; ) {
255 1.1 cgd *ptr = getc(ifp);
256 1.1 cgd if (feof(ifp))
257 1.1 cgd return (-1);
258 1.1 cgd if (*ptr++ == '\n') {
259 1.1 cgd *ptr = 0;
260 1.1 cgd return (1);
261 1.1 cgd }
262 1.1 cgd }
263 1.1 cgd while (getc(ifp) != '\n' && feof(ifp) == 0) ;
264 1.1 cgd fprintf(stderr, "line truncated to %d characters\n", BSZ);
265 1.1 cgd return (1);
266 1.1 cgd }
267 1.1 cgd
268 1.1 cgd /* return 1 for 'end' alone on card (up to col. 72), 0 otherwise */
269 1.5 lukem int
270 1.14 dholland lend(void)
271 1.1 cgd {
272 1.5 lukem char *p;
273 1.1 cgd
274 1.1 cgd if ((p = skiplab(buf)) == 0)
275 1.1 cgd return (0);
276 1.1 cgd trim(p);
277 1.1 cgd if (*p != 'e' && *p != 'E') return(0);
278 1.1 cgd p++;
279 1.1 cgd trim(p);
280 1.1 cgd if (*p != 'n' && *p != 'N') return(0);
281 1.1 cgd p++;
282 1.1 cgd trim(p);
283 1.1 cgd if (*p != 'd' && *p != 'D') return(0);
284 1.1 cgd p++;
285 1.1 cgd trim(p);
286 1.1 cgd if (p - buf >= 72 || *p == '\n')
287 1.1 cgd return (1);
288 1.1 cgd return (0);
289 1.1 cgd }
290 1.1 cgd
291 1.1 cgd /* check for keywords for subprograms
292 1.1 cgd return 0 if comment card, 1 if found
293 1.1 cgd name and put in arg string. invent name for unnamed
294 1.1 cgd block datas and main programs. */
295 1.5 lukem
296 1.5 lukem int
297 1.14 dholland lname(char *s, size_t l)
298 1.1 cgd {
299 1.1 cgd # define LINESIZE 80
300 1.5 lukem char *ptr, *p;
301 1.1 cgd char line[LINESIZE], *iptr = line;
302 1.1 cgd
303 1.1 cgd /* first check for comment cards */
304 1.1 cgd if(buf[0] == 'c' || buf[0] == 'C' || buf[0] == '*') return(0);
305 1.1 cgd ptr = buf;
306 1.1 cgd while (*ptr == ' ' || *ptr == '\t') ptr++;
307 1.1 cgd if(*ptr == '\n') return(0);
308 1.1 cgd
309 1.1 cgd
310 1.1 cgd ptr = skiplab(buf);
311 1.1 cgd if (ptr == 0)
312 1.1 cgd return (0);
313 1.1 cgd
314 1.1 cgd
315 1.1 cgd /* copy to buffer and converting to lower case */
316 1.1 cgd p = ptr;
317 1.1 cgd while (*p && p <= &buf[71] ) {
318 1.11 dsl *iptr = tolower((unsigned char)*p);
319 1.1 cgd iptr++;
320 1.1 cgd p++;
321 1.1 cgd }
322 1.1 cgd *iptr = '\n';
323 1.1 cgd
324 1.1 cgd if ((ptr = look(line, "subroutine")) != 0 ||
325 1.1 cgd (ptr = look(line, "function")) != 0 ||
326 1.1 cgd (ptr = functs(line)) != 0) {
327 1.1 cgd if(scan_name(s, ptr)) return(1);
328 1.9 itojun strlcpy(s, x, l);
329 1.1 cgd } else if((ptr = look(line, "program")) != 0) {
330 1.1 cgd if(scan_name(s, ptr)) return(1);
331 1.9 itojun get_name(mainp, 4);
332 1.9 itojun strlcpy(s, mainp, l);
333 1.1 cgd } else if((ptr = look(line, "blockdata")) != 0) {
334 1.1 cgd if(scan_name(s, ptr)) return(1);
335 1.1 cgd get_name( blkp, 6);
336 1.9 itojun strlcpy(s, blkp, l);
337 1.1 cgd } else if((ptr = functs(line)) != 0) {
338 1.1 cgd if(scan_name(s, ptr)) return(1);
339 1.9 itojun strlcpy(s, x, l);
340 1.1 cgd } else {
341 1.9 itojun get_name(mainp, 4);
342 1.9 itojun strlcpy(s, mainp, l);
343 1.1 cgd }
344 1.1 cgd return(1);
345 1.1 cgd }
346 1.1 cgd
347 1.5 lukem int
348 1.14 dholland scan_name(char *s, char *ptr)
349 1.1 cgd {
350 1.1 cgd char *sptr;
351 1.1 cgd
352 1.1 cgd /* scan off the name */
353 1.1 cgd trim(ptr);
354 1.1 cgd sptr = s;
355 1.1 cgd while (*ptr != '(' && *ptr != '\n') {
356 1.1 cgd if (*ptr != ' ' && *ptr != '\t')
357 1.1 cgd *sptr++ = *ptr;
358 1.1 cgd ptr++;
359 1.1 cgd }
360 1.1 cgd
361 1.1 cgd if (sptr == s) return(0);
362 1.1 cgd
363 1.1 cgd *sptr++ = '.';
364 1.1 cgd *sptr++ = 'f';
365 1.1 cgd *sptr++ = 0;
366 1.1 cgd return(1);
367 1.1 cgd }
368 1.1 cgd
369 1.5 lukem char *
370 1.14 dholland functs(char *p)
371 1.1 cgd {
372 1.5 lukem char *ptr;
373 1.1 cgd
374 1.1 cgd /* look for typed functions such as: real*8 function,
375 1.1 cgd character*16 function, character*(*) function */
376 1.1 cgd
377 1.1 cgd if((ptr = look(p,"character")) != 0 ||
378 1.1 cgd (ptr = look(p,"logical")) != 0 ||
379 1.1 cgd (ptr = look(p,"real")) != 0 ||
380 1.1 cgd (ptr = look(p,"integer")) != 0 ||
381 1.1 cgd (ptr = look(p,"doubleprecision")) != 0 ||
382 1.1 cgd (ptr = look(p,"complex")) != 0 ||
383 1.1 cgd (ptr = look(p,"doublecomplex")) != 0 ) {
384 1.1 cgd while ( *ptr == ' ' || *ptr == '\t' || *ptr == '*'
385 1.1 cgd || (*ptr >= '0' && *ptr <= '9')
386 1.1 cgd || *ptr == '(' || *ptr == ')') ptr++;
387 1.1 cgd ptr = look(ptr,"function");
388 1.1 cgd return(ptr);
389 1.1 cgd }
390 1.1 cgd else
391 1.1 cgd return(0);
392 1.1 cgd }
393 1.1 cgd
394 1.1 cgd /* if first 6 col. blank, return ptr to col. 7,
395 1.1 cgd if blanks and then tab, return ptr after tab,
396 1.1 cgd else return 0 (labelled statement, comment or continuation */
397 1.5 lukem
398 1.5 lukem char *
399 1.14 dholland skiplab(char *p)
400 1.1 cgd {
401 1.5 lukem char *ptr;
402 1.1 cgd
403 1.1 cgd for (ptr = p; ptr < &p[6]; ptr++) {
404 1.1 cgd if (*ptr == ' ')
405 1.1 cgd continue;
406 1.1 cgd if (*ptr == '\t') {
407 1.1 cgd ptr++;
408 1.1 cgd break;
409 1.1 cgd }
410 1.1 cgd return (0);
411 1.1 cgd }
412 1.1 cgd return (ptr);
413 1.1 cgd }
414 1.1 cgd
415 1.1 cgd /* return 0 if m doesn't match initial part of s;
416 1.1 cgd otherwise return ptr to next char after m in s */
417 1.5 lukem
418 1.5 lukem char *
419 1.14 dholland look(char *s, char *m)
420 1.1 cgd {
421 1.5 lukem char *sp, *mp;
422 1.1 cgd
423 1.1 cgd sp = s; mp = m;
424 1.1 cgd while (*mp) {
425 1.1 cgd trim(sp);
426 1.1 cgd if (*sp++ != *mp++)
427 1.1 cgd return (0);
428 1.1 cgd }
429 1.1 cgd return (sp);
430 1.1 cgd }
431