StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
f77290.c
1 /*
2  f77290.c
3  a f77 (fixed format) -> f90 (free format) converter;
4  if QPRECISION is defined, also converts double prec
5  to quad prec (using the conventions of qcomplex.f90)
6  Sept 97, last modified 18 Aug 04 th
7 */
8 
9 #define QPRECISION
10 #define MAXLINELENGTH 82
11 
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <ctype.h>
16 #include <math.h>
17 
18 #define upper(a) &a[sizeof(a)/sizeof(char *)]
19 
20 const char *ops[] = {
21  ".eq.", "==", ".ne.", "/=",
22  ".le.", "<=", ".ge.", ">=",
23  ".lt.", "<", ".gt.", ">" };
24 
25 const char *types[] = {
26 #ifdef QPRECISION
27  "type(complex32)",
28 #else
29  "double complex",
30 #endif
31  "double precision",
32  "integer", "real", "character", "complex", "logical" };
33 
34 const char *units[] = {
35  "function", "subroutine", "block data", "program" };
36 
37 typedef struct sourceline {
38  struct sourceline *next;
39  int label, indent;
40  char s[132];
41 } SOURCELINE;
42 
43 void f90name(char *oldname)
44 {
45  char *p = strchr(oldname, '.');
46  if( p && (*(p + 1) | 0x20) == 'f' ) strcpy(p, ".f90");
47  else strcat(oldname, "90");
48 }
49 
50 int isnumber(char c1, char c2, char c3, char c4)
51 {
52  int i2 = isdigit(c2), i3 = isdigit(c3);
53 
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);
60 }
61 
62 #ifdef QPRECISION
63 void typereplace(char *s, char *d, char *from, char *to)
64 {
65  int i;
66  char *p, s2[200];
67 
68  if( (p = strstr(s, from)) ) {
69  i = strlen(from);
70  strcpy(s2, p + i);
71  strcpy(p, to);
72  strcat(p, s2);
73  p = d + (int)(p - s);
74  strcpy(s2, p + i);
75  strcpy(p, to);
76  strcat(p, s2);
77  }
78 }
79 #endif
80 
81 int main(int argc, char **argv)
82 {
83  FILE *f;
84  char s[512], s2[512], *p, *d, *d2;
85  char fnstack[500], *funcname[10], **fnp = funcname;
86  char functype[50], ch;
87  const char **pp;
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;
91  SOURCELINE *xref[300], **xrp = xref, **xxp;
92  int gotos[150], *gp = gotos, donum[150], *dgp = donum, *ip;
93  char *dos[150], **dp = dos, **cp;
94 #ifdef QPRECISION
95  int usemodule = 0;
96 #endif
97 
98  if( argc < 2 ) {
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",
103  argv[0]);
104  exit(1);
105  }
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]);
109  exit(2);
110  }
111  if( (p = getenv("MAXLINELENGTH")) ) maxllen = atoi(p);
112 
113  *funcname = fnstack;
114  while( !feof(f) ) {
115  *s = 0;
116  ++lnr;
117  fgets(s, sizeof(s), f);
118  *(s + strlen(s) - 1) = 0;
119  if( *s == 0 ) continue;
120  p = s;
121  cont = 0;
122  if( strncmp(s, " ", 5) == 0 && s[5] > ' ' ) {
123  if( throwout ) continue;
124  p += 6;
125  if( last ) {
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++ = '&';
133  *d = 0;
134  }
135  }
136  else if( strncasecmp(p + strspn(p, " \t"), "intrinsic", 9) == 0 ) {
137  throwout = 1;
138  continue;
139  }
140  throwout = 0;
141  if( cont < 2 ) {
142  new = malloc(sizeof(SOURCELINE));
143  if( !start ) start = current = new;
144  else {
145  current->next = new;
146  current = new;
147  }
148  current->indent = indent;
149  d = current->s;
150  if( *s == '\t' || cont == 1 ) current->label = 0;
151  else {
152  current->label = strtol(s, &d2, 10);
153  if( d2 != s ) p = d2, *xrp++ = current;
154  }
155  if( cont == 1 ) {
156  current->indent += 2;
157  if( !space ) *d++ = '&';
158  }
159  }
160  p = (char *)memccpy(d, p + strspn(p, " \t"), 0, 256) - 2;
161  while( p > s && (*p == ' ' || *p == '\t') ) --p;
162  *++p = 0;
163  if( *s == '*' || (*s | 0x20) == 'c' ) {
164  *d = '!';
165  /* this is a dirty hack to cure some problems
166  the DEC f90 compiler has with FF */
167  if( strstr(s, "#] declarations") ) strcpy(p, "\ncontinue");
168  continue;
169  }
170  for( p = s, d2 = d; *d2; ) *p++ = tolower(*d2++);
171  *p = 0;
172  if( strncmp(s, "include", 7) == 0 || strncmp(s, "#include", 8) == 0 ) {
173  if( (p = strpbrk(d + 7, "'\"<")) && (d2 = strpbrk(++p, "'\">")) ) {
174  ch = *d2;
175  *d2 = 0;
176  f90name(p);
177  *(p += strlen(p)) = ch;
178  *(p + 1) = 0;
179  }
180  }
181 #ifdef QPRECISION
182  if( usemodule && !cont ) {
183  new = malloc(sizeof(SOURCELINE));
184  memcpy(new, current, sizeof(SOURCELINE));
185  current->next = new;
186  current->label = 0;
187  strcpy(current->s, "use qcomplex");
188  current = new;
189  d = current->s;
190  usemodule = 0;
191  }
192 #endif
193  if( defertype && !cont && strncmp(s, "implicit", 8) ) {
194  new = malloc(sizeof(SOURCELINE));
195  memcpy(new, current, sizeof(SOURCELINE));
196  current->next = new;
197  current->label = 0;
198  strcpy(current->s, functype);
199  strcat(current->s, *(fnp - 1) + 9);
200  current = new;
201  d = current->s;
202  param = justif = defertype = 0;
203  }
204 #ifdef QPRECISION
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");
210 #endif
211  if( *s == '#' ) continue;
212  if( !cont ) param = justif = 0;
213  last = current;
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);
219  }
220  for(pp = units; pp < upper(units); ++pp)
221  if( strncmp(s, *pp, strlen(*pp)) == 0 ) {
222 copyfname:
223 #ifdef QPRECISION
224  if( fnp == funcname ) usemodule = 1;
225 #endif
226  for( d2 = *fnp, p = d; *p && *p != '('; ) *d2++ = *p++;
227  *d2++ = 0;
228  *++fnp = d2;
229  gp = gotos;
230  dp = dos;
231  dgp = donum;
232  xrp = xref;
233  goto lineok;
234  }
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, ":: ");
241  strcpy(d, p);
242  defertype = 1;
243  goto copyfname;
244  }
245  strcpy(s2, p);
246  strcpy(p, ":: ");
247  strcpy(p + 3, s2);
248  break;
249  }
250  if( strcmp(s, "end") == 0 || strncmp(s, "end function", 12) == 0 ||
251  strncmp(s, "end subroutine", 14) == 0 ) {
252  if( fnp == funcname ) {
253  *d = 0;
254  fprintf(stderr,
255  "warning: superfluous END statement in line %d\n", lnr);
256  }
257  else {
258  for( xxp = xref; xxp < xrp; ++xxp ) {
259  i = (*xxp)->label;
260  for( ip = gotos; ip < gp; ++ip )
261  if(*ip == i) goto keep;
262  for( cp = dos, ip = donum; cp < dp; ++cp, ++ip )
263  if( *ip == i ) {
264  strcpy(*cp, *cp + strspn(*cp, "0123456789 \t"));
265  new = malloc(sizeof(SOURCELINE));
266  new->next = (*xxp)->next;
267  new->indent = (*xxp)->indent;
268  (*xxp)->label = new->label = 0;
269  strcpy(new->s, "enddo");
270  (*xxp)->next = new;
271  }
272 keep: ;
273  }
274  *(d + 3) = ' ';
275  strcpy(d + 4, *--fnp);
276  strcat(d + 4, "\n");
277  }
278  current->indent = indent = 0;
279  gp = gotos;
280  dgp = donum;
281  dp = dos;
282  xrp = xref;
283  }
284  else if( justif || (strncmp(s, "if", 2) == 0 && !isalnum(s[2])) ) {
285  if( strstr(s, "then") ) justif = 0, indent += 2;
286  else justif = 1;
287  }
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;
295  }
296  if( (p = strstr(s, "goto")) || (p = strstr(s, "go to")) )
297  if( (i = strtol(p + 5, &d2, 10)) ) *gp++ = i;
298 #ifdef QPRECISION
299  if( strncmp(s, "parameter", 9) == 0 ) param = 1;
300  if( param ) {
301  p = d;
302  while( (p = strchr(p, '=')) )
303  if( *(p += 1 + strspn(p + 1, " \t")) == '(' ) {
304  strcpy(s2, p);
305  strcpy(p, "complex32");
306  strcpy(p += 9, s2);
307  }
308  p = s;
309  i = 0;
310  while( (p = strstr(p, "dcmplx")) ) {
311  strcpy(s2, d2 = d + (int)((p += 6) - s + i));
312  strcpy(d2 - 6, "complex32");
313  strcpy(d2 + 3, s2);
314  i += 3;
315  }
316  }
317  /* statement functions _are_ a problem if they
318  contain type(complex32) functions :-(,
319  therefore: */
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(")) ) {
324  strcpy(p, p + 3);
325  p = d + (int)(p - s);
326  memcpy(p, p + 5, i = strcspn(p + 5, ")"));
327  strcpy(p += i, "%re");
328  strcpy(p + 3,p + 6);
329  }
330  while( (p = strstr(s + 5, "dimag(")) ) {
331  strcpy(p, p + 4);
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);
336  }
337  }
338 #endif
339 lineok: ;
340  }
341  fclose(f);
342  current->next = NULL;
343 
344  if( argc > 2 ) {
345  if(strcmp(p = argv[2], "-") == 0) f = stdout;
346  }
347  else {
348  if( f == stdin ) f = stdout;
349  else {
350  strcpy(s, argv[1]);
351  f90name(p = s);
352  }
353  }
354  if( f != stdout && (f = fopen(p,"w")) == NULL ) {
355  fprintf(stderr, "cannot create %s\n", p);
356  exit(2);
357  }
358 
359  indent = 0;
360  for( new = start; new; new = new->next ) {
361  if( *new->s == '#' || *new->s == '!' ) {
362  fprintf(f, "%s\n", new->s);
363  continue;
364  }
365  if( strcasecmp(new->s, "enddo") == 0 ||
366  strcasecmp(new->s, "end do") == 0 ) indent -= 2;
367  new->indent += indent;
368  if( new->label ) {
369  for( i = new->label; i; i /= 10 ) --new->indent;
370  if( --new->indent <= 0 ) *s = 0;
371  else {
372  memset(s, ' ', new->indent);
373  *(s + new->indent) = 0;
374  }
375  fprintf(f, "%d %s%s\n", new->label, s, new->s);
376  }
377  else if( strcasecmp(new->s, "continue") ) {
378  if(new->indent <= 0) *s = 0;
379  else {
380  memset(s, ' ', new->indent);
381  *(s + new->indent) = 0;
382  }
383  fprintf(f, "%s%s\n", s, new->s);
384  }
385  if( strncasecmp(new->s, "do ", 3) == 0 && !isdigit(new->s[3]) )
386  indent += 2;
387  }
388  fclose(f);
389  return 0;
390 }
391