10 #define MAXLINELENGTH 82
18 #define upper(a) &a[sizeof(a)/sizeof(char *)]
21 ".eq.",
"==",
".ne.",
"/=",
22 ".le.",
"<=",
".ge.",
">=",
23 ".lt.",
"<",
".gt.",
">" };
25 const char *types[] = {
32 "integer",
"real",
"character",
"complex",
"logical" };
34 const char *units[] = {
35 "function",
"subroutine",
"block data",
"program" };
43 void f90name(
char *oldname)
45 char *p = strchr(oldname,
'.');
46 if( p && (*(p + 1) | 0x20) ==
'f' ) strcpy(p,
".f90");
47 else strcat(oldname,
"90");
50 int isnumber(
char c1,
char c2,
char c3,
char c4)
52 int i2 = isdigit(c2), i3 = isdigit(c3);
54 if( i3 )
return i2 || ((c2 | 0x21) ==
'e' && isdigit(c1)) ||
55 ((c2 ==
'+' || c2 ==
'-') && (c1 | 0x21) ==
'e');
56 if( i2 )
return (c3 | 0x21) ==
'e' &&
57 (c4 ==
'+' || c4 ==
'-' || isdigit(c4));
58 return (c2 | 0x21) ==
'e' && isdigit(c1) &&
59 (c3 ==
'+' || c3 ==
'-') && isdigit(c4);
63 void typereplace(
char *s,
char *d,
char *from,
char *to)
68 if( (p = strstr(s, from)) ) {
81 int main(
int argc,
char **argv)
84 char s[512], s2[512], *p, *d, *d2;
85 char fnstack[500], *funcname[10], **fnp = funcname;
86 char functype[50], ch;
88 int lnr = 0, maxllen = MAXLINELENGTH, cont, space, i, throwout = 0;
89 int indent = 0, defertype = 0, justif = 0, param = 0;
90 SOURCELINE *start = NULL, *current = NULL, *
new, *last = NULL;
92 int gotos[150], *gp = gotos, donum[150], *dgp = donum, *ip;
93 char *dos[150], **dp = dos, **cp;
99 fprintf(stderr,
"usage: %s file.f [file.f90]\n"
100 " translates fixed-style f77 source code file.f to "
101 "free-style f90 source code.\n"
102 " if the file is -, stdin/stdout is used.\n",
106 if( strcmp(argv[1],
"-") == 0 ) f = stdin;
107 else if( (f = fopen(argv[1],
"r")) == NULL ) {
108 fprintf(stderr,
"%s not found\n", argv[1]);
111 if( (p = getenv(
"MAXLINELENGTH")) ) maxllen = atoi(p);
117 fgets(s,
sizeof(s), f);
118 *(s + strlen(s) - 1) = 0;
119 if( *s == 0 )
continue;
122 if( strncmp(s,
" ", 5) == 0 && s[5] >
' ' ) {
123 if( throwout )
continue;
126 d = last->s + (i = strlen(last->s));
127 d2 = p + strspn(p,
" \t");
128 space = strchr(
",()=/", *(d - 1)) || strchr(
",()=/", *d2) ||
129 (*(d - 1) >=
'A' && *(d - 1) <=
'z' && *d2 >=
'A' && *d2 <=
'z');
130 if( space ) *d++ =
' ';
131 cont = 1 + (i + strlen(p) < maxllen && last == current);
132 if( cont == 1 ) *d++ =
'&';
136 else if( strncasecmp(p + strspn(p,
" \t"),
"intrinsic", 9) == 0 ) {
143 if( !start ) start = current =
new;
148 current->indent = indent;
150 if( *s ==
'\t' || cont == 1 ) current->label = 0;
152 current->label = strtol(s, &d2, 10);
153 if( d2 != s ) p = d2, *xrp++ = current;
156 current->indent += 2;
157 if( !space ) *d++ =
'&';
160 p = (
char *)memccpy(d, p + strspn(p,
" \t"), 0, 256) - 2;
161 while( p > s && (*p ==
' ' || *p ==
'\t') ) --p;
163 if( *s ==
'*' || (*s | 0x20) ==
'c' ) {
167 if( strstr(s,
"#] declarations") ) strcpy(p,
"\ncontinue");
170 for( p = s, d2 = d; *d2; ) *p++ = tolower(*d2++);
172 if( strncmp(s,
"include", 7) == 0 || strncmp(s,
"#include", 8) == 0 ) {
173 if( (p = strpbrk(d + 7,
"'\"<")) && (d2 = strpbrk(++p,
"'\">")) ) {
177 *(p += strlen(p)) = ch;
182 if( usemodule && !cont ) {
187 strcpy(current->s,
"use qcomplex");
193 if( defertype && !cont && strncmp(s,
"implicit", 8) ) {
198 strcpy(current->s, functype);
199 strcat(current->s, *(fnp - 1) + 9);
202 param = justif = defertype = 0;
205 typereplace(s, d,
"double complex",
"type(complex32)");
206 typereplace(s, d,
"complex*16",
"type(complex32)");
207 typereplace(s, d,
"double precision",
"real*16");
208 typereplace(s, d,
"real*8",
"real*16");
209 typereplace(s, d,
"real*4",
"real*16");
211 if( *s ==
'#' )
continue;
212 if( !cont ) param = justif = 0;
214 for( pp = ops; pp < upper(ops); pp += 2 )
215 while( (p = strstr(s, *pp)) ) {
216 strcpy((
char *)memccpy(d + (
int)(p - s), *(pp + 1), 0, 10) - 1,
217 d + (
int)(p - s + 4));
218 strcpy((
char *)memccpy(p, *(pp + 1), 0, 10) - 1, p + 4);
220 for(pp = units; pp < upper(units); ++pp)
221 if( strncmp(s, *pp, strlen(*pp)) == 0 ) {
224 if( fnp == funcname ) usemodule = 1;
226 for( d2 = *fnp, p = d; *p && *p !=
'('; ) *d2++ = *p++;
235 for( pp = types; pp < upper(types); ++pp )
236 if( strncmp(s, *pp, i = strlen(*pp)) == 0 ) {
237 p = d + (i += strspn(d + i,
"*0123456789() \t"));
238 if( strncmp(s + i,
"function", 8) == 0 ) {
239 memcpy(functype, d, i);
240 strcpy(functype + i,
":: ");
250 if( strcmp(s,
"end") == 0 || strncmp(s,
"end function", 12) == 0 ||
251 strncmp(s,
"end subroutine", 14) == 0 ) {
252 if( fnp == funcname ) {
255 "warning: superfluous END statement in line %d\n", lnr);
258 for( xxp = xref; xxp < xrp; ++xxp ) {
260 for( ip = gotos; ip < gp; ++ip )
261 if(*ip == i)
goto keep;
262 for( cp = dos, ip = donum; cp < dp; ++cp, ++ip )
264 strcpy(*cp, *cp + strspn(*cp,
"0123456789 \t"));
266 new->next = (*xxp)->next;
267 new->indent = (*xxp)->indent;
268 (*xxp)->label =
new->label = 0;
269 strcpy(new->s,
"enddo");
275 strcpy(d + 4, *--fnp);
278 current->indent = indent = 0;
284 else if( justif || (strncmp(s,
"if", 2) == 0 && !isalnum(s[2])) ) {
285 if( strstr(s,
"then") ) justif = 0, indent += 2;
288 else if( strncmp(s,
"else", 4) == 0 )
289 current->indent -= 2;
290 else if( strcmp(s,
"endif") == 0 || strcmp(s,
"end if") == 0 )
291 indent -= 2, current->indent -= 2;
292 else if( strncmp(s,
"do ", 3) == 0 ) {
293 i = strtol(d + 3, &p, 10);
294 if( i ) *dgp++ = i, *dp++ = d + 3;
296 if( (p = strstr(s,
"goto")) || (p = strstr(s,
"go to")) )
297 if( (i = strtol(p + 5, &d2, 10)) ) *gp++ = i;
299 if( strncmp(s,
"parameter", 9) == 0 ) param = 1;
302 while( (p = strchr(p,
'=')) )
303 if( *(p += 1 + strspn(p + 1,
" \t")) ==
'(' ) {
305 strcpy(p,
"complex32");
310 while( (p = strstr(p,
"dcmplx")) ) {
311 strcpy(s2, d2 = d + (
int)((p += 6) - s + i));
312 strcpy(d2 - 6,
"complex32");
320 else if( !cont && (strncmp(s,
"absc(", 5) == 0 ||
321 strncmp(s,
"absr(", 5) == 0 ||
322 strncmp(s,
"norm(", 5) == 0) ) {
323 while( (p = strstr(s + 5,
"dble(")) ) {
325 p = d + (int)(p - s);
326 memcpy(p, p + 5, i = strcspn(p + 5,
")"));
327 strcpy(p += i,
"%re");
330 while( (p = strstr(s + 5,
"dimag(")) ) {
332 p = d + (int)(p - s);
333 memcpy(p, p + 6, i = strcspn(p + 6,
")"));
334 strcpy(p += i,
"%im");
335 strcpy(p + 3, p + 7);
342 current->next = NULL;
345 if(strcmp(p = argv[2],
"-") == 0) f = stdout;
348 if( f == stdin ) f = stdout;
354 if( f != stdout && (f = fopen(p,
"w")) == NULL ) {
355 fprintf(stderr,
"cannot create %s\n", p);
360 for(
new = start;
new;
new =
new->next ) {
361 if( *new->s ==
'#' || *new->s ==
'!' ) {
362 fprintf(f,
"%s\n", new->s);
365 if( strcasecmp(new->s,
"enddo") == 0 ||
366 strcasecmp(new->s,
"end do") == 0 ) indent -= 2;
367 new->indent += indent;
369 for( i = new->label; i; i /= 10 ) --
new->indent;
370 if( --new->indent <= 0 ) *s = 0;
372 memset(s,
' ', new->indent);
373 *(s +
new->indent) = 0;
375 fprintf(f,
"%d %s%s\n", new->label, s, new->s);
377 else if( strcasecmp(new->s,
"continue") ) {
378 if(new->indent <= 0) *s = 0;
380 memset(s,
' ', new->indent);
381 *(s +
new->indent) = 0;
383 fprintf(f,
"%s%s\n", s, new->s);
385 if( strncasecmp(new->s,
"do ", 3) == 0 && !isdigit(new->s[3]) )