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