xref: /csrg-svn/usr.bin/fsplit/fsplit.c (revision 38549)
138281Sbostic #include <ctype.h>
238281Sbostic #include <stdio.h>
338281Sbostic #include <sys/types.h>
438281Sbostic #include <sys/stat.h>
538281Sbostic 
638281Sbostic /*
738281Sbostic  *	usage:		fsplit [-e efile] ... [file]
838281Sbostic  *
938281Sbostic  *	split single file containing source for several fortran programs
1038281Sbostic  *		and/or subprograms into files each containing one
1138281Sbostic  *		subprogram unit.
1238281Sbostic  *	each separate file will be named using the corresponding subroutine,
1338281Sbostic  *		function, block data or program name if one is found; otherwise
1438281Sbostic  *		the name will be of the form mainNNN.f or blkdtaNNN.f .
1538281Sbostic  *		If a file of that name exists, it is saved in a name of the
1638281Sbostic  *		form zzz000.f .
1738281Sbostic  *	If -e option is used, then only those subprograms named in the -e
1838281Sbostic  *		option are split off; e.g.:
1938281Sbostic  *			fsplit -esub1 -e sub2 prog.f
2038281Sbostic  *		isolates sub1 and sub2 in sub1.f and sub2.f.  The space
2138281Sbostic  *		after -e is optional.
2238281Sbostic  *
2338281Sbostic  *	Modified Feb., 1983 by Jerry Berkman, Computing Services, U.C. Berkeley.
2438281Sbostic  *		- added comments
2538281Sbostic  *		- more function types: double complex, character*(*), etc.
2638281Sbostic  *		- fixed minor bugs
2738281Sbostic  *		- instead of all unnamed going into zNNN.f, put mains in
2838281Sbostic  *		  mainNNN.f, block datas in blkdtaNNN.f, dups in zzzNNN.f .
2938281Sbostic  */
3038281Sbostic 
3138281Sbostic #define BSZ 512
3238281Sbostic char buf[BSZ];
3338281Sbostic FILE *ifp;
3438281Sbostic char 	x[]="zzz000.f",
3538281Sbostic 	mainp[]="main000.f",
3638281Sbostic 	blkp[]="blkdta000.f";
3738281Sbostic char *look(), *skiplab(), *functs();
3838281Sbostic 
3938281Sbostic #define TRUE 1
4038281Sbostic #define FALSE 0
4138281Sbostic int	extr = FALSE,
4238281Sbostic 	extrknt = -1,
4338281Sbostic 	extrfnd[100];
4438281Sbostic char	extrbuf[1000],
4538281Sbostic 	*extrnames[100];
4638281Sbostic struct stat sbuf;
4738281Sbostic 
4838281Sbostic #define trim(p)	while (*p == ' ' || *p == '\t') p++
4938281Sbostic 
5038281Sbostic main(argc, argv)
5138281Sbostic char **argv;
5238281Sbostic {
5338281Sbostic 	register FILE *ofp;	/* output file */
5438281Sbostic 	register rv;		/* 1 if got card in output file, 0 otherwise */
5538281Sbostic 	register char *ptr;
5638281Sbostic 	int nflag,		/* 1 if got name of subprog., 0 otherwise */
5738281Sbostic 		retval,
5838281Sbostic 		i;
5938281Sbostic 	char name[20],
6038281Sbostic 		*extrptr = extrbuf;
6138281Sbostic 
6238281Sbostic 	/*  scan -e options */
6338281Sbostic 	while ( argc > 1  && argv[1][0] == '-' && argv[1][1] == 'e') {
6438281Sbostic 		extr = TRUE;
6538281Sbostic 		ptr = argv[1] + 2;
6638281Sbostic 		if(!*ptr) {
6738281Sbostic 			argc--;
6838281Sbostic 			argv++;
6938281Sbostic 			if(argc <= 1) badparms();
7038281Sbostic 			ptr = argv[1];
7138281Sbostic 		}
7238281Sbostic 		extrknt = extrknt + 1;
7338281Sbostic 		extrnames[extrknt] = extrptr;
7438281Sbostic 		extrfnd[extrknt] = FALSE;
7538281Sbostic 		while(*ptr) *extrptr++ = *ptr++;
7638281Sbostic 		*extrptr++ = 0;
7738281Sbostic 		argc--;
7838281Sbostic 		argv++;
7938281Sbostic 	}
8038281Sbostic 
8138281Sbostic 	if (argc > 2)
8238281Sbostic 		badparms();
8338281Sbostic 	else if (argc == 2) {
8438281Sbostic 		if ((ifp = fopen(argv[1], "r")) == NULL) {
8538281Sbostic 			fprintf(stderr, "fsplit: cannot open %s\n", argv[1]);
8638281Sbostic 			exit(1);
8738281Sbostic 		}
8838281Sbostic 	}
8938281Sbostic 	else
9038281Sbostic 		ifp = stdin;
9138281Sbostic     for(;;) {
9238281Sbostic 	/* look for a temp file that doesn't correspond to an existing file */
9338281Sbostic 	get_name(x, 3);
9438281Sbostic 	ofp = fopen(x, "w");
9538281Sbostic 	nflag = 0;
9638281Sbostic 	rv = 0;
9738281Sbostic 	while (getline() > 0) {
9838281Sbostic 		rv = 1;
9938281Sbostic 		fprintf(ofp, "%s", buf);
10038281Sbostic 		if (lend())		/* look for an 'end' statement */
10138281Sbostic 			break;
10238281Sbostic 		if (nflag == 0)		/* if no name yet, try and find one */
10338281Sbostic 			nflag = lname(name);
10438281Sbostic 	}
10538281Sbostic 	fclose(ofp);
10638281Sbostic 	if (rv == 0) {			/* no lines in file, forget the file */
10738281Sbostic 		unlink(x);
10838281Sbostic 		retval = 0;
10938281Sbostic 		for ( i = 0; i <= extrknt; i++ )
11038281Sbostic 			if(!extrfnd[i]) {
11138281Sbostic 				retval = 1;
11238281Sbostic 				fprintf( stderr, "fsplit: %s not found\n",
11338281Sbostic 					extrnames[i]);
11438281Sbostic 			}
11538281Sbostic 		exit( retval );
11638281Sbostic 	}
11738281Sbostic 	if (nflag) {			/* rename the file */
11838281Sbostic 		if(saveit(name)) {
11938281Sbostic 			if (stat(name, &sbuf) < 0 ) {
12038281Sbostic 				link(x, name);
12138281Sbostic 				unlink(x);
12238281Sbostic 				printf("%s\n", name);
12338281Sbostic 				continue;
12438281Sbostic 			} else if (strcmp(name, x) == 0) {
12538281Sbostic 				printf("%s\n", x);
12638281Sbostic 				continue;
12738281Sbostic 			}
12838281Sbostic 			printf("%s already exists, put in %s\n", name, x);
12938281Sbostic 			continue;
13038281Sbostic 		} else
13138281Sbostic 			unlink(x);
13238281Sbostic 			continue;
13338281Sbostic 	}
13438281Sbostic 	if(!extr)
13538281Sbostic 		printf("%s\n", x);
13638281Sbostic 	else
13738281Sbostic 		unlink(x);
13838281Sbostic     }
13938281Sbostic }
14038281Sbostic 
14138281Sbostic badparms()
14238281Sbostic {
14338281Sbostic 	fprintf(stderr, "fsplit: usage:  fsplit [-e efile] ... [file] \n");
14438281Sbostic 	exit(1);
14538281Sbostic }
14638281Sbostic 
14738281Sbostic saveit(name)
14838281Sbostic char *name;
14938281Sbostic {
15038281Sbostic 	int i;
15138281Sbostic 	char	fname[50],
15238281Sbostic 		*fptr = fname;
15338281Sbostic 
15438281Sbostic 	if(!extr) return(1);
15538281Sbostic 	while(*name) *fptr++ = *name++;
15638281Sbostic 	*--fptr = 0;
15738281Sbostic 	*--fptr = 0;
15838281Sbostic 	for ( i=0 ; i<=extrknt; i++ )
15938281Sbostic 		if( strcmp(fname, extrnames[i]) == 0 ) {
16038281Sbostic 			extrfnd[i] = TRUE;
16138281Sbostic 			return(1);
16238281Sbostic 		}
16338281Sbostic 	return(0);
16438281Sbostic }
16538281Sbostic 
16638281Sbostic get_name(name, letters)
16738281Sbostic char *name;
16838281Sbostic int letters;
16938281Sbostic {
17038281Sbostic 	register char *ptr;
17138281Sbostic 
17238281Sbostic 	while (stat(name, &sbuf) >= 0) {
17338281Sbostic 		for (ptr = name + letters + 2; ptr >= name + letters; ptr--) {
17438281Sbostic 			(*ptr)++;
17538281Sbostic 			if (*ptr <= '9')
17638281Sbostic 				break;
17738281Sbostic 			*ptr = '0';
17838281Sbostic 		}
17938281Sbostic 		if(ptr < name + letters) {
18038281Sbostic 			fprintf( stderr, "fsplit: ran out of file names\n");
18138281Sbostic 			exit(1);
18238281Sbostic 		}
18338281Sbostic 	}
18438281Sbostic }
18538281Sbostic 
18638281Sbostic getline()
18738281Sbostic {
18838281Sbostic 	register char *ptr;
18938281Sbostic 
19038281Sbostic 	for (ptr = buf; ptr < &buf[BSZ]; ) {
19138281Sbostic 		*ptr = getc(ifp);
19238281Sbostic 		if (feof(ifp))
19338281Sbostic 			return (-1);
19438281Sbostic 		if (*ptr++ == '\n') {
19538281Sbostic 			*ptr = 0;
19638281Sbostic 			return (1);
19738281Sbostic 		}
19838281Sbostic 	}
19938281Sbostic 	while (getc(ifp) != '\n' && feof(ifp) == 0) ;
20038281Sbostic 	fprintf(stderr, "line truncated to %d characters\n", BSZ);
20138281Sbostic 	return (1);
20238281Sbostic }
20338281Sbostic 
20438281Sbostic /* return 1 for 'end' alone on card (up to col. 72),  0 otherwise */
20538281Sbostic lend()
20638281Sbostic {
20738281Sbostic 	register char *p;
20838281Sbostic 
20938281Sbostic 	if ((p = skiplab(buf)) == 0)
21038281Sbostic 		return (0);
21138281Sbostic 	trim(p);
21238281Sbostic 	if (*p != 'e' && *p != 'E') return(0);
21338281Sbostic 	p++;
21438281Sbostic 	trim(p);
21538281Sbostic 	if (*p != 'n' && *p != 'N') return(0);
21638281Sbostic 	p++;
21738281Sbostic 	trim(p);
21838281Sbostic 	if (*p != 'd' && *p != 'D') return(0);
21938281Sbostic 	p++;
22038281Sbostic 	trim(p);
22138281Sbostic 	if (p - buf >= 72 || *p == '\n')
22238281Sbostic 		return (1);
22338281Sbostic 	return (0);
22438281Sbostic }
22538281Sbostic 
22638281Sbostic /*		check for keywords for subprograms
22738281Sbostic 		return 0 if comment card, 1 if found
22838281Sbostic 		name and put in arg string. invent name for unnamed
22938281Sbostic 		block datas and main programs.		*/
23038281Sbostic lname(s)
23138281Sbostic char *s;
23238281Sbostic {
23338281Sbostic #	define LINESIZE 80
23438281Sbostic 	register char *ptr, *p, *sptr;
23538281Sbostic 	char	line[LINESIZE], *iptr = line;
23638281Sbostic 
23738281Sbostic 	/* first check for comment cards */
23838281Sbostic 	if(buf[0] == 'c' || buf[0] == 'C' || buf[0] == '*') return(0);
23938281Sbostic 	ptr = buf;
24038281Sbostic 	while (*ptr == ' ' || *ptr == '\t') ptr++;
24138281Sbostic 	if(*ptr == '\n') return(0);
24238281Sbostic 
24338281Sbostic 
24438281Sbostic 	ptr = skiplab(buf);
24538281Sbostic 
24638281Sbostic 	/*  copy to buffer and converting to lower case */
24738281Sbostic 	p = ptr;
24838281Sbostic 	while (*p && p <= &buf[71] ) {
24938281Sbostic 	   *iptr = isupper(*p) ? tolower(*p) : *p;
25038281Sbostic 	   iptr++;
25138281Sbostic 	   p++;
25238281Sbostic 	}
25338281Sbostic 	*iptr = '\n';
25438281Sbostic 
25538281Sbostic 	if ((ptr = look(line, "subroutine")) != 0 ||
25638281Sbostic 	    (ptr = look(line, "function")) != 0 ||
25738281Sbostic 	    (ptr = functs(line)) != 0) {
25838281Sbostic 		if(scan_name(s, ptr)) return(1);
25938281Sbostic 		strcpy( s, x);
26038281Sbostic 	} else if((ptr = look(line, "program")) != 0) {
26138281Sbostic 		if(scan_name(s, ptr)) return(1);
26238281Sbostic 		get_name( mainp, 4);
26338281Sbostic 		strcpy( s, mainp);
26438281Sbostic 	} else if((ptr = look(line, "blockdata")) != 0) {
26538281Sbostic 		if(scan_name(s, ptr)) return(1);
26638281Sbostic 		get_name( blkp, 6);
26738281Sbostic 		strcpy( s, blkp);
26838281Sbostic 	} else if((ptr = functs(line)) != 0) {
26938281Sbostic 		if(scan_name(s, ptr)) return(1);
27038281Sbostic 		strcpy( s, x);
27138281Sbostic 	} else {
27238281Sbostic 		get_name( mainp, 4);
27338281Sbostic 		strcpy( s, mainp);
27438281Sbostic 	}
27538281Sbostic 	return(1);
27638281Sbostic }
27738281Sbostic 
27838281Sbostic scan_name(s, ptr)
27938281Sbostic char *s, *ptr;
28038281Sbostic {
28138281Sbostic 	char *sptr;
28238281Sbostic 
28338281Sbostic 	/* scan off the name */
28438281Sbostic 	trim(ptr);
28538281Sbostic 	sptr = s;
28638281Sbostic 	while (*ptr != '(' && *ptr != '\n') {
28738281Sbostic 		if (*ptr != ' ' && *ptr != '\t')
28838281Sbostic 			*sptr++ = *ptr;
28938281Sbostic 		ptr++;
29038281Sbostic 	}
29138281Sbostic 
29238281Sbostic 	if (sptr == s) return(0);
29338281Sbostic 
29438281Sbostic 	*sptr++ = '.';
29538281Sbostic 	*sptr++ = 'f';
29638281Sbostic 	*sptr++ = 0;
297*38549Sbostic 	return(1);
29838281Sbostic }
29938281Sbostic 
30038281Sbostic char *functs(p)
30138281Sbostic char *p;
30238281Sbostic {
30338281Sbostic         register char *ptr;
30438281Sbostic 
30538281Sbostic /*      look for typed functions such as: real*8 function,
30638281Sbostic                 character*16 function, character*(*) function  */
30738281Sbostic 
30838281Sbostic         if((ptr = look(p,"character")) != 0 ||
30938281Sbostic            (ptr = look(p,"logical")) != 0 ||
31038281Sbostic            (ptr = look(p,"real")) != 0 ||
31138281Sbostic            (ptr = look(p,"integer")) != 0 ||
31238281Sbostic            (ptr = look(p,"doubleprecision")) != 0 ||
31338281Sbostic            (ptr = look(p,"complex")) != 0 ||
31438281Sbostic            (ptr = look(p,"doublecomplex")) != 0 ) {
31538281Sbostic                 while ( *ptr == ' ' || *ptr == '\t' || *ptr == '*'
31638281Sbostic 			|| (*ptr >= '0' && *ptr <= '9')
31738281Sbostic 			|| *ptr == '(' || *ptr == ')') ptr++;
31838281Sbostic 		ptr = look(ptr,"function");
31938281Sbostic 		return(ptr);
32038281Sbostic 	}
32138281Sbostic         else
32238281Sbostic                 return(0);
32338281Sbostic }
32438281Sbostic 
32538281Sbostic /* 	if first 6 col. blank, return ptr to col. 7,
32638281Sbostic 	if blanks and then tab, return ptr after tab,
32738281Sbostic 	else return 0 (labelled statement, comment or continuation */
32838281Sbostic char *skiplab(p)
32938281Sbostic char *p;
33038281Sbostic {
33138281Sbostic 	register char *ptr;
33238281Sbostic 
33338281Sbostic 	for (ptr = p; ptr < &p[6]; ptr++) {
33438281Sbostic 		if (*ptr == ' ')
33538281Sbostic 			continue;
33638281Sbostic 		if (*ptr == '\t') {
33738281Sbostic 			ptr++;
33838281Sbostic 			break;
33938281Sbostic 		}
34038281Sbostic 		return (0);
34138281Sbostic 	}
34238281Sbostic 	return (ptr);
34338281Sbostic }
34438281Sbostic 
34538281Sbostic /* 	return 0 if m doesn't match initial part of s;
34638281Sbostic 	otherwise return ptr to next char after m in s */
34738281Sbostic char *look(s, m)
34838281Sbostic char *s, *m;
34938281Sbostic {
35038281Sbostic 	register char *sp, *mp;
35138281Sbostic 
35238281Sbostic 	sp = s; mp = m;
35338281Sbostic 	while (*mp) {
35438281Sbostic 		trim(sp);
35538281Sbostic 		if (*sp++ != *mp++)
35638281Sbostic 			return (0);
35738281Sbostic 	}
35838281Sbostic 	return (sp);
35938281Sbostic }
360