4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
11 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
12 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
13 * Copyright (c) 2001-2004, The GROMACS development team,
14 * check out http://www.gromacs.org for more information.
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * If you want to redistribute modifications, please consider that
22 * scientific software is very special. Version control is crucial -
23 * bugs must be traceable. We will be happy to consider code for
24 * inclusion in the official distribution, but derived work must not
25 * be called official GROMACS. Details are found in the README & COPYING
26 * files - if they are missing, get the official version at www.gromacs.org.
28 * To help us fund GROMACS development, we humbly ask that you cite
29 * the papers on the package - you can find them in the top README file.
31 * For more info, check our website at http://www.gromacs.org
34 * GROningen Mixture of Alchemy and Childrens' Stories
42 /* This file is NOT threadsafe, but it is only used to create
43 * the innerloops during the build process, so it will never be
44 * executed by multiple threads.
47 #define MAXCODESIZE 1000000
58 #define REAL_FORMAT "%.16f"
62 char header
[10000]; /* Should be enough for a few comment lines
63 * and the function name
66 char *codebuffer
=NULL
;
70 int nargs
=0; /* the first nargs entries in the declaration list
71 * are function arguments
78 static bool first
=TRUE
;
81 IND
= bC
? CIND
: F77IND
;
83 /* sanity check if the buffers are initialized more than once.
84 * They are also emptied upon flushing.
87 decl_list
=(decl_t
*)malloc(sizeof(decl_t
)*MAXDECL
);
88 codebuffer
=(char *)malloc(MAXCODESIZE
);
98 void add_to_buffer(char *buffer
,char *term
)
106 static bool findname(char *buffer
,char *name
)
108 /* This routine returns true if name is found in
109 * buffer, and the surrounding characters are non
110 * alphanumeric. (i.e. it is not a substring of
111 * a longer word). It might catch things in comments
112 * if you choose to keep them with -DKEEP_COMMENTS, though,
113 * in which case you'll get warnings about unused variables.
117 /* the first character will be a space,
118 * so it is safe to start at buffer+1.
123 if((ch
=strstr(ch
+1,name
))!=NULL
) {
124 /* Found something. But is it a full variable
125 * or a substring in a larger name?
126 * Check if the prev/next chars are alphanumeric!
128 if(!isalnum(*(ch
+strlen(name
))) && !isalnum(*(ch
-1)))
129 return TRUE
; /* found it! */
133 return FALSE
; /* no hit */
137 void flush_buffers(void)
142 /* scan the code output buffer for arguments and
143 * variables. Remove all that are unreferenced!
146 decl_list
[i
].breferenced
=findname(codebuffer
,decl_list
[i
].name
);
148 /* write the function name (and start argument list) */
149 fprintf(output
,header
);
152 /* write out all referenced FUNCTION ARGUMENTS */
153 for(i
=0;i
<nargs
;i
++) {
154 if(!decl_list
[i
].breferenced
)
156 if(nwritten
) /* separate from earlier arg with comma */
160 fprintf(output
,"\n\t%15s %s%s",decl_list
[i
].typename
,decl_list
[i
].name
,
161 decl_list
[i
].bvector
? "[]" : "");
163 fprintf(output
,"\n" FCON
" %s",decl_list
[i
].name
);
166 /* finish argument list, start function */
167 fprintf(output
,")\n");
169 fprintf(output
,"{\n");
173 /* declare arguments in fortran */
175 fprintf(output
,"%simplicit none\n",indent());
176 for(i
=0;i
<nargs
;i
++) {
177 if(!decl_list
[i
].breferenced
)
179 fprintf(output
,"%s%-10s %s%s\n",indent(),
180 decl_list
[i
].typename
,decl_list
[i
].name
,
181 decl_list
[i
].bvector
? "(*)" : "");
185 /* declare all non-removed VARIABLES following the arguments */
186 for(i
=nargs
;i
<ndecl
;i
++) {
187 if(!decl_list
[i
].breferenced
)
190 fprintf(output
,"%s%-10s %s%s",indent(),
191 decl_list
[i
].typename
,decl_list
[i
].name
,
192 decl_list
[i
].bvector
? "[]" : "");
193 if(decl_list
[i
].bconst
)
194 fprintf(output
," = %s;\n",decl_list
[i
].constval
);
196 fprintf(output
,";\n");
198 fprintf(output
,"%s%-10s %s%s\n",indent(),
199 decl_list
[i
].typename
,decl_list
[i
].name
,
200 decl_list
[i
].bvector
? "(*)" : "");
204 /* assign fortran parameters */
206 for(i
=nargs
;i
<ndecl
;i
++)
207 if(decl_list
[i
].breferenced
&& decl_list
[i
].bconst
)
208 fprintf(output
,"%sparameter (%s = %s)\n",
209 indent(),decl_list
[i
].name
,decl_list
[i
].constval
);
211 /* write one huge piece of function code */
212 fprintf(output
,codebuffer
);
214 /* empty the buffers to prepare for next routine... */
222 /* Return the correct indentation as a string */
225 static char indbuf
[1024];
236 void fortran_splitline(char *line
)
238 char tmpbuf
[1024],linebuf
[1000];
244 while(i
+72-IND
<maxlen
) {
253 (line
[j
]=='*' && line
[j
-1]!='*') || /* dont split pows */
259 printf("Error: Couldn't break this line:\n%s\n",line
);
262 strncpy(tmpbuf
,line
+i
,j
-i
+1);
265 strcat(codebuffer
,tmpbuf
);
268 strcat(codebuffer
,FCON
" ");
270 strcat(codebuffer
,line
+i
);
274 /* Print a line of code to the output file */
275 void code(char *fmt
, ...)
284 sprintf(outbuf
,"%s",indent());
293 sprintf(tmpbuf
,"%d",d
);
294 strcat(outbuf
,tmpbuf
);
297 f
= va_arg(ap
, double);
298 sprintf(tmpbuf
,REAL_FORMAT
,f
);
299 strcat(outbuf
,tmpbuf
);
302 s
= va_arg(ap
, char *);
304 strcat(outbuf
,tmpbuf
);
307 fprintf(stderr
,"Error, unsupported format supplied to code()\n");
312 sprintf(tmpbuf
,"%c",*fmt
);
313 strcat(outbuf
,tmpbuf
);
319 strcat(codebuffer
,outbuf
);
321 fortran_splitline(outbuf
);
330 strcat(codebuffer
,"\n");
333 /* Add a comment - might just come in handy for debugging,
334 but we don't need it in production level code */
335 void comment(char *s
)
340 sprintf(buf
,"\n%s/* %s */\n",indent(),s
);
343 sprintf(buf
,"\nC%s%s\n",indent(),s
);
346 strcat(codebuffer
,buf
);
351 /* Define a new floating-point variable */
352 void declare_real(char *name
)
356 strcpy(decl_list
[ndecl
].typename
,"real");
358 sprintf(decl_list
[ndecl
].typename
,"real*%d",prec
);
360 strcpy(decl_list
[ndecl
].name
,name
);
362 decl_list
[ndecl
].breferenced
=TRUE
;
363 decl_list
[ndecl
].bvector
=FALSE
;
364 decl_list
[ndecl
].bconst
=FALSE
;
368 void declare_real4(char *name
)
372 strcpy(decl_list
[ndecl
].typename
,"float");
374 sprintf(decl_list
[ndecl
].typename
,"real*4");
376 strcpy(decl_list
[ndecl
].name
,name
);
378 decl_list
[ndecl
].breferenced
=TRUE
;
379 decl_list
[ndecl
].bvector
=FALSE
;
380 decl_list
[ndecl
].bconst
=FALSE
;
384 void declare_real_vector(char *name
)
388 strcpy(decl_list
[ndecl
].typename
,"real");
390 sprintf(decl_list
[ndecl
].typename
,"real*%d",prec
);
392 strcpy(decl_list
[ndecl
].name
,name
);
394 decl_list
[ndecl
].breferenced
=TRUE
;
395 decl_list
[ndecl
].bvector
=TRUE
;
396 decl_list
[ndecl
].bconst
=FALSE
;
401 void declare_intreal(char *name
)
411 void declare_const_real(char *name
,double val
)
414 strcpy(decl_list
[ndecl
].typename
,"const real");
416 sprintf(decl_list
[ndecl
].typename
,"real*%d",prec
);
418 strcpy(decl_list
[ndecl
].name
,name
);
420 decl_list
[ndecl
].breferenced
=TRUE
;
421 decl_list
[ndecl
].bvector
=FALSE
; /* cant have const vectors */
422 decl_list
[ndecl
].bconst
=TRUE
;
423 sprintf(decl_list
[ndecl
].constval
,REAL_FORMAT
,val
);
427 void declare_const_int(char *name
,int val
)
430 strcpy(decl_list
[ndecl
].typename
,"const int");
432 sprintf(decl_list
[ndecl
].typename
,"integer*4");
434 strcpy(decl_list
[ndecl
].name
,name
);
436 decl_list
[ndecl
].breferenced
=TRUE
;
437 decl_list
[ndecl
].bvector
=FALSE
; /* cant have const vectors */
438 decl_list
[ndecl
].bconst
=TRUE
;
439 sprintf(decl_list
[ndecl
].constval
,"%d",val
);
444 void declare_int(char *name
)
447 strcpy(decl_list
[ndecl
].typename
,"int");
449 sprintf(decl_list
[ndecl
].typename
,"integer*%d",(int)sizeof(int));
451 strcpy(decl_list
[ndecl
].name
,name
);
453 decl_list
[ndecl
].breferenced
=TRUE
;
454 decl_list
[ndecl
].bvector
=FALSE
;
455 decl_list
[ndecl
].bconst
=FALSE
;
459 void declare_int_vector(char *name
)
462 strcpy(decl_list
[ndecl
].typename
,"int");
464 sprintf(decl_list
[ndecl
].typename
,"integer*%d",(int)sizeof(int));
466 strcpy(decl_list
[ndecl
].name
,name
);
468 decl_list
[ndecl
].breferenced
=TRUE
;
469 decl_list
[ndecl
].bvector
=TRUE
;
470 decl_list
[ndecl
].bconst
=FALSE
;
475 void declare_int4(char *name
)
478 strcpy(decl_list
[ndecl
].typename
,"int");
480 strcpy(decl_list
[ndecl
].typename
,"integer*4");
482 strcpy(decl_list
[ndecl
].name
,name
);
484 decl_list
[ndecl
].breferenced
=TRUE
;
485 decl_list
[ndecl
].bvector
=FALSE
;
486 decl_list
[ndecl
].bconst
=FALSE
;
491 void declare_int8(char *name
)
494 strcpy(decl_list
[ndecl
].typename
,"long long");
496 strcpy(decl_list
[ndecl
].typename
,"integer*8");
498 strcpy(decl_list
[ndecl
].name
,name
);
500 decl_list
[ndecl
].breferenced
=TRUE
;
501 decl_list
[ndecl
].bvector
=FALSE
;
502 decl_list
[ndecl
].bconst
=FALSE
;
506 void declare_other(char *typename
,char *name
)
509 strcpy(decl_list
[ndecl
].typename
,typename
);
511 strcpy(decl_list
[ndecl
].typename
,typename
);
513 strcpy(decl_list
[ndecl
].name
,name
);
515 decl_list
[ndecl
].breferenced
=TRUE
;
516 decl_list
[ndecl
].bvector
=FALSE
;
517 decl_list
[ndecl
].bconst
=FALSE
;
522 /* Cray vector pragma */
523 void vector_pragma(void)
527 strcat(codebuffer
,"#pragma ivdep\n");
529 strcat(codebuffer
,"cdir$ivdep\n");
533 char *_array(char *a
, char *idx
, ...)
535 char arrtmp
[1000],idxtmp
[1000],tmp
[1000];
540 arrtmp
[0]=idxtmp
[0]=0;
552 s
= va_arg(ap
, char *);
560 fprintf(stderr
,"Error, unsupported format supplied to _array()\n");
565 sprintf(tmp
,"%c",*a
);
578 s
= va_arg(ap
, char *);
586 fprintf(stderr
,"Error, unsupported format supplied to _array()\n");
591 sprintf(tmp
,"%c",*idx
);
598 sprintf(tmp
,"%s%c%s%c",arrtmp
, bC
? '[' : '(',idxtmp
, bC
? ']' : ')');
599 /* ok, now we got the array reference in tmp. But there might be
600 * some stupid things which need to be removed. First, if we add
601 * a negative offset of e.g. -1 somewhere, we will get a "+-1" which
602 * is bad... remove the minus sign:
604 if((s
=strstr(tmp
,"+-"))!=NULL
) {
605 strcpy(arrtmp
,s
+1); /* copy to tmparray */
606 strcpy(s
,arrtmp
); /* copy back */
609 /* It is also stupid to add a zero offset. Kill that cat! */
610 if((s
=strstr(tmp
,"+0"))!=NULL
) {
611 strcpy(arrtmp
,s
+2); /* copy to tmparray */
612 strcpy(s
,arrtmp
); /* copy back */
619 void file_error(char *fn
)
621 fprintf(stderr
,"Error creating file %s\n",fn
);
626 void _p_state(char *left
,char *right
,char *symb
)
631 if (IND
+16+3+strlen(right
) > 78) {
632 sprintf(buf
,"%s%-16s %2s \n",indent(),left
,symb
);
633 strcat(codebuffer
,buf
);
635 sprintf(buf
,"%s%s;\n",indent(),right
);
636 strcat(codebuffer
,buf
);
640 sprintf(buf
,"%s%-16s %2s %s;\n",indent(),left
,symb
,right
);
641 strcat(codebuffer
,buf
);
645 if (IND
+16+3+strlen(right
) > 72) {
646 sprintf(buf
,"%s%-16s = \n%s",indent(),left
,FCON
);
647 strcat(codebuffer
,buf
);
653 sprintf(buf
,"%s%-16s = %s\n",indent(),left
,right
);
654 strcat(codebuffer
,buf
);
660 void assign(char *left
,char *right
, ...)
662 char ltmp
[1000],rtmp
[1000],tmp
[1000];
680 f
= va_arg(ap
, double);
681 sprintf(tmp
,REAL_FORMAT
,f
);
684 s
= va_arg(ap
, char *);
692 fprintf(stderr
,"Error, unsupported format supplied to code()\n");
697 sprintf(tmp
,"%c",*left
);
710 f
= va_arg(ap
, double);
711 sprintf(tmp
,REAL_FORMAT
,f
);
714 s
= va_arg(ap
, char *);
722 fprintf(stderr
,"Error, unsupported format supplied to code()\n");
727 sprintf(tmp
,"%c",*right
);
733 _p_state(ltmp
,rtmp
,"=");
737 void increment(char *left
,char *right
, ...)
739 char ltmp
[1000],rtmp
[1000],tmp
[1000];
757 f
= va_arg(ap
, double);
758 sprintf(tmp
,REAL_FORMAT
,f
);
761 s
= va_arg(ap
, char *);
769 fprintf(stderr
,"Error, unsupported format supplied to code()\n");
774 sprintf(tmp
,"%c",*left
);
790 f
= va_arg(ap
, double);
791 sprintf(tmp
,REAL_FORMAT
,f
);
794 s
= va_arg(ap
, char *);
802 fprintf(stderr
,"Error, unsupported format supplied to code()\n");
807 sprintf(tmp
,"%c",*right
);
813 _p_state(ltmp
,rtmp
,"=");
818 void decrement(char *left
,char *right
, ...)
820 char ltmp
[1000],rtmp
[1000],tmp
[1000];
838 f
= va_arg(ap
, double);
839 sprintf(tmp
,REAL_FORMAT
,f
);
842 s
= va_arg(ap
, char *);
850 fprintf(stderr
,"Error, unsupported format supplied to code()\n");
855 sprintf(tmp
,"%c",*left
);
871 f
= va_arg(ap
, double);
872 sprintf(tmp
,REAL_FORMAT
,f
);
875 s
= va_arg(ap
, char *);
883 fprintf(stderr
,"Error, unsupported format supplied to code()\n");
888 sprintf(tmp
,"%c",*right
);
894 _p_state(ltmp
,rtmp
,"=");
899 void add(char *left
,char *r1
,char *r2
, ...)
901 char ltmp
[1000],rtmp
[1000],tmp
[1000];
919 f
= va_arg(ap
, double);
920 sprintf(tmp
,REAL_FORMAT
,f
);
923 s
= va_arg(ap
, char *);
931 fprintf(stderr
,"Error, unsupported format supplied to code()\n");
936 sprintf(tmp
,"%c",*left
);
949 f
= va_arg(ap
, double);
950 sprintf(tmp
,REAL_FORMAT
,f
);
953 s
= va_arg(ap
, char *);
961 fprintf(stderr
,"Error, unsupported format supplied to code()\n");
966 sprintf(tmp
,"%c",*r1
);
980 f
= va_arg(ap
, double);
981 sprintf(tmp
,REAL_FORMAT
,f
);
984 s
= va_arg(ap
, char *);
992 fprintf(stderr
,"Error, unsupported format supplied to code()\n");
997 sprintf(tmp
,"%c",*r2
);
1003 _p_state(ltmp
,rtmp
,"=");
1007 void subtract(char *left
,char *r1
,char *r2
, ...)
1009 char ltmp
[1000],rtmp
[1000],tmp
[1000];
1023 d
= va_arg(ap
, int);
1024 sprintf(tmp
,"%d",d
);
1027 f
= va_arg(ap
, double);
1028 sprintf(tmp
,REAL_FORMAT
,f
);
1031 s
= va_arg(ap
, char *);
1035 c
= va_arg(ap
, int);
1036 sprintf(tmp
,"%c",c
);
1039 fprintf(stderr
,"Error, unsupported format supplied to code()\n");
1044 sprintf(tmp
,"%c",*left
);
1053 d
= va_arg(ap
, int);
1054 sprintf(tmp
,"%d",d
);
1057 f
= va_arg(ap
, double);
1058 sprintf(tmp
,REAL_FORMAT
,f
);
1061 s
= va_arg(ap
, char *);
1065 c
= va_arg(ap
, int);
1066 sprintf(tmp
,"%c",c
);
1069 fprintf(stderr
,"Error, unsupported format supplied to code()\n");
1074 sprintf(tmp
,"%c",*r1
);
1084 d
= va_arg(ap
, int);
1085 sprintf(tmp
,"%d",d
);
1088 f
= va_arg(ap
, double);
1089 sprintf(tmp
,REAL_FORMAT
,f
);
1092 s
= va_arg(ap
, char *);
1096 c
= va_arg(ap
, int);
1097 sprintf(tmp
,"%c",c
);
1100 fprintf(stderr
,"Error, unsupported format supplied to code()\n");
1105 sprintf(tmp
,"%c",*r2
);
1111 _p_state(ltmp
,rtmp
,"=");
1116 void multiply(char *left
,char *r1
,char *r2
, ...)
1118 char ltmp
[1000],rtmp
[1000],tmp
[1000];
1132 d
= va_arg(ap
, int);
1133 sprintf(tmp
,"%d",d
);
1136 f
= va_arg(ap
, double);
1137 sprintf(tmp
,REAL_FORMAT
,f
);
1140 s
= va_arg(ap
, char *);
1144 c
= va_arg(ap
, int);
1145 sprintf(tmp
,"%c",c
);
1148 fprintf(stderr
,"Error, unsupported format supplied to code()\n");
1153 sprintf(tmp
,"%c",*left
);
1162 d
= va_arg(ap
, int);
1163 sprintf(tmp
,"%d",d
);
1166 f
= va_arg(ap
, double);
1167 sprintf(tmp
,REAL_FORMAT
,f
);
1170 s
= va_arg(ap
, char *);
1174 c
= va_arg(ap
, int);
1175 sprintf(tmp
,"%c",c
);
1178 fprintf(stderr
,"Error, unsupported format supplied to code()\n");
1183 sprintf(tmp
,"%c",*r1
);
1193 d
= va_arg(ap
, int);
1194 sprintf(tmp
,"%d",d
);
1197 f
= va_arg(ap
, double);
1198 sprintf(tmp
,REAL_FORMAT
,f
);
1201 s
= va_arg(ap
, char *);
1205 c
= va_arg(ap
, int);
1206 sprintf(tmp
,"%c",c
);
1209 fprintf(stderr
,"Error, unsupported format supplied to code()\n");
1214 sprintf(tmp
,"%c",*r2
);
1220 _p_state(ltmp
,rtmp
,"=");
1226 void edit_warning(char *fn
)
1230 " /**********************************************************\n"
1231 " * This code is generated automatically by %s\n"
1232 " * DO NOT EDIT THIS FILE\n"
1233 " * Erik Lindahl, David van der Spoel 1999-2000\n"
1234 " **********************************************************/"
1238 "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n"
1239 "C This code is generated automatically by %s\n"
1240 "C DO NOT EDIT THIS FILE\n"
1241 "C Erik Lindahl, David van der Spoel 1999-2000\n"
1242 "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n",
1249 strcat(codebuffer
,"}\n\n");
1256 void usage(int argc
,char *argv
[])
1258 fprintf(stderr
,"Usage: %s language\n",argv
[0]);
1259 fprintf(stderr
,"\tAvailable languages: c fortran\n");
1263 int count_lines(char *fn
)
1269 if ((fp
= fopen(fn
,"r")) == NULL
) {
1274 while (fgets(buf
,255,fp
) != NULL
)
1282 void start_loop(char *lvar
,char *from
,char *to
)
1285 code("for(%s=%s; (%s<%s); %s++) {", lvar
,from
,lvar
,to
,lvar
);
1287 code("do %s=%s,%s",lvar
,from
,to
);
1293 void start_stride_loop(char *lvar
,char *from
,char *to
, char *stride
)
1296 code("for(%s=%s; (%s<%s); %s+=%s) {", lvar
,from
,lvar
,to
,lvar
,stride
);
1298 code("do %s=%s,%s,%s",lvar
,from
,to
,stride
);
1315 void start_if(char *cond
)
1318 code("if(%s) {", cond
);
1320 code("if (%s) then",cond
);
1353 strcat(codebuffer
,"}\n\n");