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