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