3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
10 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12 * Copyright (c) 2001-2004, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * If you want to redistribute modifications, please consider that
21 * scientific software is very special. Version control is crucial -
22 * bugs must be traceable. We will be happy to consider code for
23 * inclusion in the official distribution, but derived work must not
24 * be called official GROMACS. Details are found in the README & COPYING
25 * files - if they are missing, get the official version at www.gromacs.org.
27 * To help us fund GROMACS development, we humbly ask that you cite
28 * the papers on the package - you can find them in the top README file.
30 * For more info, check our website at http://www.gromacs.org
33 * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
39 #include <sys/types.h>
50 #include "gromacs/fileio/futil.h"
52 #include "gmx_fatal.h"
61 static t_define *defs = NULL;
63 static char **incl = 0;
65 /* enum used for handling ifdefs */
67 eifTRUE, eifFALSE, eifIGNORE, eifNR
70 typedef struct gmx_cpp {
79 struct gmx_cpp *child, *parent;
82 static gmx_bool is_word_end(char c)
84 return !(isalnum(c) || c == '_');
87 static const char *strstrw(const char *buf, const char *word)
91 while ((ptr = strstr(buf, word)) != NULL)
93 /* Check if we did not find part of a longer word */
95 is_word_end(ptr[strlen(word)]) &&
96 (((ptr > buf) && is_word_end(ptr[-1])) || (ptr == buf)))
101 buf = ptr + strlen(word);
106 static gmx_bool find_directive(char *buf, char **name, char **val)
108 /* Skip initial whitespace */
109 while (isspace(*buf))
113 /* Check if this is a directive */
118 /* Skip the hash and any space after it */
120 while (isspace(*buf))
124 /* Set the name pointer and find the next space */
126 while (*buf != 0 && !isspace(*buf))
130 /* Set the end of the name here, and skip any space */
135 while (isspace(*buf))
140 /* Check if anything is remaining */
141 *val = (*buf != 0) ? buf : NULL;
145 static gmx_bool is_ifdeffed_out(gmx_cpp_t handle)
147 return ((handle->nifdef > 0) && (handle->ifdefs[handle->nifdef-1] != eifTRUE));
150 static void add_include(const char *include)
159 for (i = 0; (i < nincl); i++)
161 if (strcmp(incl[i], include) == 0)
170 incl[nincl-1] = strdup(include);
174 static void add_define(const char *name, const char *value)
178 for (i = 0; (i < ndef); i++)
180 if (strcmp(defs[i].name, name) == 0)
190 defs[i].name = strdup(name);
192 else if (defs[i].def)
196 fprintf(debug, "Overriding define %s\n", name);
200 if (value && strlen(value) > 0)
202 defs[i].def = strdup(value);
210 /* Open the file to be processed. The handle variable holds internal
211 info for the cpp emulator. Return integer status */
212 int cpp_open_file(const char *filenm, gmx_cpp_t *handle, char **cppopts)
220 /* First process options, they might be necessary for opening files
221 (especially include statements). */
227 if (strstr(cppopts[i], "-I") == cppopts[i])
229 add_include(cppopts[i]+2);
231 if (strstr(cppopts[i], "-D") == cppopts[i])
233 /* If the option contains a =, split it into name and value. */
234 ptr = strchr(cppopts[i], '=');
237 buf = gmx_strndup(cppopts[i] + 2, ptr - cppopts[i] - 2);
238 add_define(buf, ptr + 1);
243 add_define(cppopts[i] + 2, NULL);
251 fprintf(debug, "GMXCPP: added %d command line arguments\n", i);
257 /* Find the file. First check whether it is in the current directory. */
258 if (gmx_fexist(filenm))
260 cpp->fn = strdup(filenm);
264 /* If not, check all the paths given with -I. */
265 for (i = 0; i < nincl; ++i)
267 snew(buf, strlen(incl[i]) + strlen(filenm) + 2);
268 sprintf(buf, "%s/%s", incl[i], filenm);
276 /* If still not found, check the Gromacs library search path. */
279 cpp->fn = low_gmxlibfn(filenm, FALSE, FALSE);
284 gmx_fatal(FARGS, "Topology include file \"%s\" not found", filenm);
288 fprintf(debug, "GMXCPP: cpp file open %s\n", cpp->fn);
290 /* If the file name has a path component, we need to change to that
291 * directory. Note that we - just as C - always use UNIX path separators
292 * internally in include file names.
294 ptr = strrchr(cpp->fn, '/');
295 ptr2 = strrchr(cpp->fn, DIR_SEPARATOR);
297 if (ptr == NULL || (ptr2 != NULL && ptr2 > ptr))
310 cpp->fn = strdup(ptr+1);
311 snew(cpp->cwd, STRLEN);
313 gmx_getcwd(cpp->cwd, STRLEN);
316 fprintf(debug, "GMXCPP: cwd %s\n", cpp->cwd);
318 gmx_chdir(cpp->path);
322 fprintf(debug, "GMXCPP: chdir to %s\n", cpp->path);
336 fprintf(debug, "GMXCPP: opening file %s\n", cpp->fn);
338 cpp->fp = fopen(cpp->fn, "r");
353 process_directive(gmx_cpp_t *handlep, const char *dname, const char *dval)
355 gmx_cpp_t handle = (gmx_cpp_t)*handlep;
356 int i, i0, len, status;
362 /* #ifdef or ifndef statement */
363 bIfdef = (strcmp(dname, "ifdef") == 0);
364 bIfndef = (strcmp(dname, "ifndef") == 0);
365 if (bIfdef || bIfndef)
367 if ((handle->nifdef > 0) && (handle->ifdefs[handle->nifdef-1] != eifTRUE))
370 srenew(handle->ifdefs, handle->nifdef);
371 handle->ifdefs[handle->nifdef-1] = eifIGNORE;
375 snew(name, strlen(dval)+1);
376 sscanf(dval, "%s", name);
377 for (i = 0; (i < ndef); i++)
379 if (strcmp(defs[i].name, name) == 0)
385 srenew(handle->ifdefs, handle->nifdef);
386 if ((bIfdef && (i < ndef)) || (bIfndef && (i == ndef)))
388 handle->ifdefs[handle->nifdef-1] = eifTRUE;
392 handle->ifdefs[handle->nifdef-1] = eifFALSE;
399 /* #else statement */
400 if (strcmp(dname, "else") == 0)
402 if (handle->nifdef <= 0)
406 if (handle->ifdefs[handle->nifdef-1] == eifTRUE)
408 handle->ifdefs[handle->nifdef-1] = eifFALSE;
410 else if (handle->ifdefs[handle->nifdef-1] == eifFALSE)
412 handle->ifdefs[handle->nifdef-1] = eifTRUE;
417 /* #endif statement */
418 if (strcmp(dname, "endif") == 0)
420 if (handle->nifdef <= 0)
428 /* Check whether we're not ifdeffed out. The order of this statement
429 is important. It has to come after #ifdef, #else and #endif, but
430 anything else should be ignored. */
431 if (is_ifdeffed_out(handle))
436 /* Check for include statements */
437 if (strcmp(dname, "include") == 0)
441 for (i1 = 0; (i1 < strlen(dval)); i1++)
443 if ((dval[i1] == '"') || (dval[i1] == '<') || (dval[i1] == '>'))
465 strncpy(inc_fn, dval+i0, len);
470 fprintf(debug, "Going to open include file '%s' i0 = %d, strlen = %d\n",
473 /* Open include file and store it as a child in the handle structure */
474 status = cpp_open_file(inc_fn, &(handle->child), NULL);
476 if (status != eCPP_OK)
478 handle->child = NULL;
481 /* Make a linked list of open files and move on to the include file */
482 handle->child->parent = handle;
483 *handlep = handle->child;
488 /* #define statement */
489 if (strcmp(dname, "define") == 0)
491 /* Split it into name and value. */
493 while ((*ptr != '\0') && !isspace(*ptr))
497 name = gmx_strndup(dval, ptr - dval);
499 while ((*ptr != '\0') && isspace(*ptr))
504 add_define(name, ptr);
509 /* #undef statement */
510 if (strcmp(dname, "undef") == 0)
512 snew(name, strlen(dval)+1);
513 sscanf(dval, "%s", name);
514 for (i = 0; (i < ndef); i++)
516 if (strcmp(defs[i].name, name) == 0)
524 for (; (i < ndef-1); i++)
526 defs[i].name = defs[i+1].name;
527 defs[i].def = defs[i+1].def;
534 /* If we haven't matched anything, this is an unknown directive */
538 /* Return one whole line from the file into buf which holds at most n
539 characters, for subsequent processing. Returns integer status. This
540 routine also does all the "intelligent" work like processing cpp
541 directives and so on. Note that often the routine is called
542 recursively and no cpp directives are printed. */
543 int cpp_read_line(gmx_cpp_t *handlep, int n, char buf[])
545 gmx_cpp_t handle = (gmx_cpp_t)*handlep;
546 int i, nn, len, status;
547 const char *ptr, *ptr2;
554 return eCPP_INVALID_HANDLE;
558 return eCPP_FILE_NOT_OPEN;
561 bEOF = feof(handle->fp);
564 /* Read the actual line now. */
565 if (fgets2(buf, n-1, handle->fp) == NULL)
567 /* Recheck EOF, since we could have been at the end before
568 * the fgets2 call, but we need to read past the end to know.
570 bEOF = feof(handle->fp);
573 /* Something strange happened, fgets returned NULL,
574 * but we are not at EOF.
583 if (handle->parent == NULL)
587 cpp_close_file(handlep);
588 *handlep = handle->parent;
589 handle->child = NULL;
590 return cpp_read_line(handlep, n, buf);
594 if (n > handle->line_len)
596 handle->line_len = n;
597 srenew(handle->line, n);
599 strcpy(handle->line, buf);
602 /* Now we've read a line! */
605 fprintf(debug, "%s : %4d : %s\n", handle->fn, handle->line_nr, buf);
608 /* Process directives if this line contains one */
609 if (find_directive(buf, &dname, &dval))
611 status = process_directive(handlep, dname, dval);
612 if (status != eCPP_OK)
616 /* Don't print lines with directives, go on to the next */
617 return cpp_read_line(handlep, n, buf);
620 /* Check whether we're not ifdeffed out. The order of this statement
621 is important. It has to come after #ifdef, #else and #endif, but
622 anything else should be ignored. */
623 if (is_ifdeffed_out(handle))
625 return cpp_read_line(handlep, n, buf);
628 /* Check whether we have any defines that need to be replaced. Note
629 that we have to use a best fit algorithm, rather than first come
630 first go. We do this by sorting the defines on length first, and
631 then on alphabetical order. */
632 for (i = 0; (i < ndef); i++)
638 while ((ptr = strstrw(ptr, defs[i].name)) != NULL)
641 ptr += strlen(defs[i].name);
645 len = strlen(buf) + nn*max(4, 4+strlen(defs[i].def)-strlen(defs[i].name));
648 while ((ptr2 = strstrw(ptr, defs[i].name)) != NULL)
650 strncat(name, ptr, (int)(ptr2-ptr));
651 strcat(name, defs[i].def);
652 ptr = ptr2 + strlen(defs[i].name);
664 char *cpp_cur_file(const gmx_cpp_t *handlep)
666 return (*handlep)->fn;
669 int cpp_cur_linenr(const gmx_cpp_t *handlep)
671 return (*handlep)->line_nr;
674 /* Close the file! Return integer status. */
675 int cpp_close_file(gmx_cpp_t *handlep)
678 gmx_cpp_t handle = (gmx_cpp_t)*handlep;
682 return eCPP_INVALID_HANDLE;
686 return eCPP_FILE_NOT_OPEN;
690 fprintf(debug, "GMXCPP: closing file %s\n", handle->fn);
693 if (NULL != handle->cwd)
697 fprintf(debug, "GMXCPP: chdir to %s\n", handle->cwd);
699 gmx_chdir(handle->cwd);
709 return eCPP_FILE_NOT_FOUND;
711 return eCPP_FILE_NOT_OPEN;
713 return eCPP_INTERRUPT;
717 fprintf(debug, "Strange stuff closing file, errno = %d", errno);
724 if (NULL != handle->fn)
729 if (NULL != handle->line)
734 if (NULL != handle->ifdefs)
736 sfree(handle->ifdefs);
739 if (NULL != handle->path)
743 if (NULL != handle->cwd)
751 /* Return a string containing the error message coresponding to status
753 char *cpp_error(gmx_cpp_t *handlep, int status)
756 const char *ecpp[] = {
757 "OK", "File not found", "End of file", "Syntax error", "Interrupted",
758 "Invalid file handle",
759 "File not open", "Unknown error", "Error status out of range"
761 gmx_cpp_t handle = (gmx_cpp_t)*handlep;
765 return (char *)ecpp[eCPP_INVALID_HANDLE];
768 if ((status < 0) || (status >= eCPP_NR))
773 sprintf(buf, "%s - File %s, line %d\nLast line read:\n'%s'",
775 (handle && handle->fn) ? handle->fn : "unknown",
776 (handle) ? handle->line_nr : -1,
777 handle->line ? handle->line : "");