the default path is /var/mail, not /var/spool/mail...
[unix-history] / usr / src / usr.bin / fsplit / fsplit.c
CommitLineData
d4f06e9c 1/*
64f62623
KB
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
d4f06e9c
KB
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Asa Romberger and Jerry Berkman.
7 *
6ecf3d85 8 * %sccs.include.redist.c%
d4f06e9c
KB
9 */
10
11#ifndef lint
64f62623
KB
12static char copyright[] =
13"@(#) Copyright (c) 1983, 1993\n\
14 The Regents of the University of California. All rights reserved.\n";
d4f06e9c
KB
15#endif /* not lint */
16
17#ifndef lint
64f62623 18static char sccsid[] = "@(#)fsplit.c 8.1 (Berkeley) %G%";
d4f06e9c
KB
19#endif /* not lint */
20
b327e077
KB
21#include <ctype.h>
22#include <stdio.h>
23#include <sys/types.h>
24#include <sys/stat.h>
25
26/*
27 * usage: fsplit [-e efile] ... [file]
28 *
29 * split single file containing source for several fortran programs
30 * and/or subprograms into files each containing one
31 * subprogram unit.
32 * each separate file will be named using the corresponding subroutine,
33 * function, block data or program name if one is found; otherwise
34 * the name will be of the form mainNNN.f or blkdtaNNN.f .
35 * If a file of that name exists, it is saved in a name of the
36 * form zzz000.f .
37 * If -e option is used, then only those subprograms named in the -e
38 * option are split off; e.g.:
39 * fsplit -esub1 -e sub2 prog.f
40 * isolates sub1 and sub2 in sub1.f and sub2.f. The space
41 * after -e is optional.
42 *
43 * Modified Feb., 1983 by Jerry Berkman, Computing Services, U.C. Berkeley.
44 * - added comments
45 * - more function types: double complex, character*(*), etc.
46 * - fixed minor bugs
47 * - instead of all unnamed going into zNNN.f, put mains in
48 * mainNNN.f, block datas in blkdtaNNN.f, dups in zzzNNN.f .
49 */
50
51#define BSZ 512
52char buf[BSZ];
53FILE *ifp;
54char x[]="zzz000.f",
55 mainp[]="main000.f",
56 blkp[]="blkdta000.f";
57char *look(), *skiplab(), *functs();
58
59#define TRUE 1
60#define FALSE 0
61int extr = FALSE,
62 extrknt = -1,
63 extrfnd[100];
64char extrbuf[1000],
65 *extrnames[100];
66struct stat sbuf;
67
68#define trim(p) while (*p == ' ' || *p == '\t') p++
69
70main(argc, argv)
71char **argv;
72{
73 register FILE *ofp; /* output file */
74 register rv; /* 1 if got card in output file, 0 otherwise */
75 register char *ptr;
76 int nflag, /* 1 if got name of subprog., 0 otherwise */
77 retval,
78 i;
79 char name[20],
80 *extrptr = extrbuf;
81
82 /* scan -e options */
83 while ( argc > 1 && argv[1][0] == '-' && argv[1][1] == 'e') {
84 extr = TRUE;
85 ptr = argv[1] + 2;
86 if(!*ptr) {
87 argc--;
88 argv++;
89 if(argc <= 1) badparms();
90 ptr = argv[1];
91 }
92 extrknt = extrknt + 1;
93 extrnames[extrknt] = extrptr;
94 extrfnd[extrknt] = FALSE;
95 while(*ptr) *extrptr++ = *ptr++;
96 *extrptr++ = 0;
97 argc--;
98 argv++;
99 }
100
101 if (argc > 2)
102 badparms();
103 else if (argc == 2) {
104 if ((ifp = fopen(argv[1], "r")) == NULL) {
105 fprintf(stderr, "fsplit: cannot open %s\n", argv[1]);
106 exit(1);
107 }
108 }
109 else
110 ifp = stdin;
111 for(;;) {
112 /* look for a temp file that doesn't correspond to an existing file */
113 get_name(x, 3);
114 ofp = fopen(x, "w");
115 nflag = 0;
116 rv = 0;
117 while (getline() > 0) {
118 rv = 1;
119 fprintf(ofp, "%s", buf);
120 if (lend()) /* look for an 'end' statement */
121 break;
122 if (nflag == 0) /* if no name yet, try and find one */
123 nflag = lname(name);
124 }
125 fclose(ofp);
126 if (rv == 0) { /* no lines in file, forget the file */
127 unlink(x);
128 retval = 0;
129 for ( i = 0; i <= extrknt; i++ )
130 if(!extrfnd[i]) {
131 retval = 1;
132 fprintf( stderr, "fsplit: %s not found\n",
133 extrnames[i]);
134 }
135 exit( retval );
136 }
137 if (nflag) { /* rename the file */
138 if(saveit(name)) {
139 if (stat(name, &sbuf) < 0 ) {
140 link(x, name);
141 unlink(x);
142 printf("%s\n", name);
143 continue;
144 } else if (strcmp(name, x) == 0) {
145 printf("%s\n", x);
146 continue;
147 }
148 printf("%s already exists, put in %s\n", name, x);
149 continue;
150 } else
151 unlink(x);
152 continue;
153 }
154 if(!extr)
155 printf("%s\n", x);
156 else
157 unlink(x);
158 }
159}
160
161badparms()
162{
163 fprintf(stderr, "fsplit: usage: fsplit [-e efile] ... [file] \n");
164 exit(1);
165}
166
167saveit(name)
168char *name;
169{
170 int i;
171 char fname[50],
172 *fptr = fname;
173
174 if(!extr) return(1);
175 while(*name) *fptr++ = *name++;
176 *--fptr = 0;
177 *--fptr = 0;
178 for ( i=0 ; i<=extrknt; i++ )
179 if( strcmp(fname, extrnames[i]) == 0 ) {
180 extrfnd[i] = TRUE;
181 return(1);
182 }
183 return(0);
184}
185
186get_name(name, letters)
187char *name;
188int letters;
189{
190 register char *ptr;
191
192 while (stat(name, &sbuf) >= 0) {
193 for (ptr = name + letters + 2; ptr >= name + letters; ptr--) {
194 (*ptr)++;
195 if (*ptr <= '9')
196 break;
197 *ptr = '0';
198 }
199 if(ptr < name + letters) {
200 fprintf( stderr, "fsplit: ran out of file names\n");
201 exit(1);
202 }
203 }
204}
205
206getline()
207{
208 register char *ptr;
209
210 for (ptr = buf; ptr < &buf[BSZ]; ) {
211 *ptr = getc(ifp);
212 if (feof(ifp))
213 return (-1);
214 if (*ptr++ == '\n') {
215 *ptr = 0;
216 return (1);
217 }
218 }
219 while (getc(ifp) != '\n' && feof(ifp) == 0) ;
220 fprintf(stderr, "line truncated to %d characters\n", BSZ);
221 return (1);
222}
223
224/* return 1 for 'end' alone on card (up to col. 72), 0 otherwise */
225lend()
226{
227 register char *p;
228
229 if ((p = skiplab(buf)) == 0)
230 return (0);
231 trim(p);
232 if (*p != 'e' && *p != 'E') return(0);
233 p++;
234 trim(p);
235 if (*p != 'n' && *p != 'N') return(0);
236 p++;
237 trim(p);
238 if (*p != 'd' && *p != 'D') return(0);
239 p++;
240 trim(p);
241 if (p - buf >= 72 || *p == '\n')
242 return (1);
243 return (0);
244}
245
246/* check for keywords for subprograms
247 return 0 if comment card, 1 if found
248 name and put in arg string. invent name for unnamed
249 block datas and main programs. */
250lname(s)
251char *s;
252{
253# define LINESIZE 80
254 register char *ptr, *p, *sptr;
255 char line[LINESIZE], *iptr = line;
256
257 /* first check for comment cards */
258 if(buf[0] == 'c' || buf[0] == 'C' || buf[0] == '*') return(0);
259 ptr = buf;
260 while (*ptr == ' ' || *ptr == '\t') ptr++;
261 if(*ptr == '\n') return(0);
262
263
264 ptr = skiplab(buf);
4fb21885
KB
265 if (ptr == 0)
266 return (0);
267
b327e077
KB
268
269 /* copy to buffer and converting to lower case */
270 p = ptr;
271 while (*p && p <= &buf[71] ) {
272 *iptr = isupper(*p) ? tolower(*p) : *p;
273 iptr++;
274 p++;
275 }
276 *iptr = '\n';
277
278 if ((ptr = look(line, "subroutine")) != 0 ||
279 (ptr = look(line, "function")) != 0 ||
280 (ptr = functs(line)) != 0) {
281 if(scan_name(s, ptr)) return(1);
282 strcpy( s, x);
283 } else if((ptr = look(line, "program")) != 0) {
284 if(scan_name(s, ptr)) return(1);
285 get_name( mainp, 4);
286 strcpy( s, mainp);
287 } else if((ptr = look(line, "blockdata")) != 0) {
288 if(scan_name(s, ptr)) return(1);
289 get_name( blkp, 6);
290 strcpy( s, blkp);
291 } else if((ptr = functs(line)) != 0) {
292 if(scan_name(s, ptr)) return(1);
293 strcpy( s, x);
294 } else {
295 get_name( mainp, 4);
296 strcpy( s, mainp);
297 }
298 return(1);
299}
300
b327e077
KB
301scan_name(s, ptr)
302char *s, *ptr;
303{
304 char *sptr;
305
306 /* scan off the name */
307 trim(ptr);
308 sptr = s;
309 while (*ptr != '(' && *ptr != '\n') {
310 if (*ptr != ' ' && *ptr != '\t')
311 *sptr++ = *ptr;
312 ptr++;
313 }
314
315 if (sptr == s) return(0);
316
317 *sptr++ = '.';
318 *sptr++ = 'f';
319 *sptr++ = 0;
42c6d7a7 320 return(1);
b327e077
KB
321}
322
323char *functs(p)
324char *p;
325{
326 register char *ptr;
327
328/* look for typed functions such as: real*8 function,
329 character*16 function, character*(*) function */
330
331 if((ptr = look(p,"character")) != 0 ||
332 (ptr = look(p,"logical")) != 0 ||
333 (ptr = look(p,"real")) != 0 ||
334 (ptr = look(p,"integer")) != 0 ||
335 (ptr = look(p,"doubleprecision")) != 0 ||
336 (ptr = look(p,"complex")) != 0 ||
337 (ptr = look(p,"doublecomplex")) != 0 ) {
338 while ( *ptr == ' ' || *ptr == '\t' || *ptr == '*'
339 || (*ptr >= '0' && *ptr <= '9')
340 || *ptr == '(' || *ptr == ')') ptr++;
341 ptr = look(ptr,"function");
342 return(ptr);
343 }
344 else
345 return(0);
346}
347
348/* if first 6 col. blank, return ptr to col. 7,
349 if blanks and then tab, return ptr after tab,
350 else return 0 (labelled statement, comment or continuation */
351char *skiplab(p)
352char *p;
353{
354 register char *ptr;
355
356 for (ptr = p; ptr < &p[6]; ptr++) {
357 if (*ptr == ' ')
358 continue;
359 if (*ptr == '\t') {
360 ptr++;
361 break;
362 }
363 return (0);
364 }
365 return (ptr);
366}
367
368/* return 0 if m doesn't match initial part of s;
369 otherwise return ptr to next char after m in s */
370char *look(s, m)
371char *s, *m;
372{
373 register char *sp, *mp;
374
375 sp = s; mp = m;
376 while (*mp) {
377 trim(sp);
378 if (*sp++ != *mp++)
379 return (0);
380 }
381 return (sp);
382}