Files
openfoam/wmake/src/wmkdep.l
Mark Olesen 10fc0646fb BUG: 'make clean' failed for wmake/src
- caused by the typo '@E' instead of '$E' (commit 997f1713cb)

ENH: minor improvements for wmake/src makefile

- 'make clean' now also tries to remove the parent platforms/
  directory if possible.

- the flex intermediate build target is placed into the platforms/
  directory to avoid touching the src/ directory at all.

- suppress warnings about unused functions (GCC only)
2017-03-09 11:48:52 +01:00

449 lines
11 KiB
C

%{
/*---------------------------------*- C -*-----------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
wmkdep
Description
A fast dependency list generator that emulates the behaviour and the
output of cpp -M. However, the output contains no duplicates and
is approx. 40% faster than cpp.
The algorithm uses flex to scan for includes and searches the files
found. Each file is entered into a hash table so that files are scanned
only once. This is why this program is faster than cpp.
Usage
wmkdep [ -Idir ... -Idir ] [ -iheader .. -iheader ] filename
\*---------------------------------------------------------------------------*/
#define FILE_STACK_SIZE 300
#define HASH_TABLE_SIZE 500
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h> /* POSIX */
#include <dirent.h> /* POSIX */
/* The executable name (for messages), without requiring access to argv[] */
#define EXENAME "wmkdep"
#undef yywrap /* sometimes a macro by default */
#define YY_NO_INPUT /* no input(), yyinput() required */
#pragma GCC diagnostic ignored "-Wunused-function"
void nextFile(const char* fileName);
/*---------------------------------------------------------------------------*/
%}
%x CMNT CFNAME SCFNAME JFNAME FFNAME
%%
"//".*\n ; /* remove c++ style one line comments */
"/*" BEGIN(CMNT); /* start removing c style comment */
<CMNT>.|\n ;
<CMNT>"*/" BEGIN(INITIAL); /* end removing c style comment */
^[ \t]*#[ \t]*include[ \t]+\" BEGIN(CFNAME); /* c-file name */
<CFNAME>[^"\n ]* { BEGIN(INITIAL); nextFile(yytext); } /*"*/
" "include[ \t]+\' BEGIN(FFNAME); /* FORTRAN-file name */
<FFNAME>[^']* { BEGIN(INITIAL); nextFile(yytext); } /*'*/
.|\t|\n ;
%%
/*---------------------------------------------------------------------------*/
/* char* entry in hash table */
struct HashEntry
{
char* name;
struct HashEntry* next;
};
/*
* lookup name in hash table.
* if found - return 1
* if not found - insert in table and return 0
*/
int lookUp(struct HashEntry** hashTable, const char* p)
{
int ii = 0;
struct HashEntry* n;
struct HashEntry* nn;
/* hash */
const char* pp = p;
while (*pp) ii = ii<<1 ^ *pp++;
if (ii < 0) ii = -ii;
ii %= HASH_TABLE_SIZE;
/* search */
for (n=hashTable[ii]; n; n=n->next)
{
if (strcmp(p, n->name) == 0)
{
/* entry found so return true */
return 1;
}
}
/* insert */
nn = (struct HashEntry*)malloc(sizeof(struct HashEntry));
nn->name = strdup(p);
nn->next = hashTable[ii];
hashTable[ii] = nn;
/* entry not found, and therefore added. return false */
return 0;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int nDirectories = 0;
char** directories;
char* sourceFile = NULL;
char* depFile = NULL;
/* Set of files already visited */
struct HashEntry* visitedFiles[HASH_TABLE_SIZE];
/* Buffer pointer stack counter */
int currentBuffer = 0;
/* Buffer pointer stack */
YY_BUFFER_STATE buffers[FILE_STACK_SIZE];
/* Directory paths for the loaded files */
const char* bufferPaths[FILE_STACK_SIZE];
int main(int argc, char* argv[])
{
char *basePos, *dotPos;
int i;
if (argc < 2)
{
fputs(EXENAME ": input file not supplied\n", stderr);
return 1;
}
else if (!strncmp(argv[1], "-h", 2)) /* -h, -help */
{
fputs
(
"\nUsage: " EXENAME
" [-Idir ... -Idir] [-iheader .. -iheader] filename\n\n"
" -Idir Directories to be searched for headers.\n"
" -iheader Headers to be ignored.\n\n"
"Dependency list generator, similar to 'cpp -M'\n\n",
stderr
);
return 0;
}
sourceFile = strdup(argv[argc-1]);
if ((basePos = strrchr(sourceFile, '/')) == NULL)
{
basePos = sourceFile;
}
else
{
++basePos;
}
if
(
(dotPos = strrchr(sourceFile, '.')) == NULL
|| (dotPos < basePos)
)
{
fprintf
(
stderr,
EXENAME ": cannot find extension in source file name '%s'\n",
sourceFile
);
return 1;
}
/* count number of -I directories */
nDirectories = 0;
for (i = 1; i < argc; ++i)
{
if (strncmp(argv[i], "-I", 2) == 0)
{
if (strlen(argv[i]) > 2)
{
++nDirectories;
}
}
}
directories = (char**)malloc(sizeof(char*)*nDirectories);
/* build list of -I directories and add -i ignores */
nDirectories = 0;
for (i = 1; i < argc; ++i)
{
if (strncmp(argv[i], "-I", 2) == 0)
{
if (strlen(argv[i]) > 2)
{
directories[nDirectories++] = strdup(argv[i] + 2);
}
}
else if (strncmp(argv[i], "-i", 2) == 0)
{
if (strlen(argv[i]) > 2)
{
lookUp(visitedFiles, (argv[i] + 2));
}
}
}
/*
* initialise depFile to zero and use strncat rather than strncpy
* because there is a bug in the SGI strncat that if 0 preceeds the '.'
* it inserts a space
*/
depFile = (char*)malloc(strlen(sourceFile) + 20);
depFile[0] = 0;
strcat(depFile, "$(OBJECTS_DIR)/");
strcat(depFile, sourceFile);
strcat(depFile, ".dep");
char *objectFile = strdup(basePos);
objectFile[(dotPos - basePos)/sizeof(char)] = 0;
/* printf("$(OBJECTS_DIR)/%s.o: %s\n", objectFile, depFile); */
printf("%s: \\\n", depFile);
free(objectFile);
/* Initialize buffer path for currentBuffer */
bufferPaths[currentBuffer] = NULL;
nextFile(sourceFile);
yylex();
puts("\n");
for (i = 0; i < nDirectories; ++i)
{
free(directories[i]);
}
free(directories);
free(sourceFile);
free(depFile);
return 0;
}
/*
* Add a directory name to the file name
*/
char* addDirectoryName(const char* dirName, const char* fileName)
{
char* pathName = (char*)malloc(strlen(dirName) + strlen(fileName) + 2);
strcpy(pathName, dirName);
if (dirName[strlen(dirName)-1] != '/')
{
strcat(pathName, "/");
}
strcat(pathName, fileName);
return pathName;
}
/*
* open a file and create buffer and put on stack
*/
void nextFile(const char* fileName)
{
if (lookUp(visitedFiles, fileName))
{
return; /* already existed (did not insert) */
}
if (currentBuffer >= FILE_STACK_SIZE)
{
fprintf
(
stderr,
EXENAME ": depth of file search exceeds stack size %d "
"while opening '%s' for file '%s'\n",
FILE_STACK_SIZE, fileName, sourceFile
);
exit(1);
}
/* Pointer to new file which is set if the file is successfully opened */
FILE* newyyin = NULL;
/* Check if the file has same path as the file in the current buffer */
if (bufferPaths[currentBuffer] != NULL)
{
char* pathName = addDirectoryName(bufferPaths[currentBuffer], fileName);
if ((newyyin = fopen(pathName, "r")))
{
printf("%s \\\n", pathName);
buffers[currentBuffer++] = YY_CURRENT_BUFFER;
bufferPaths[currentBuffer] = bufferPaths[currentBuffer-1];
yy_switch_to_buffer(yy_create_buffer(newyyin, YY_BUF_SIZE));
free(pathName);
return;
}
free(pathName);
}
if (!(newyyin = fopen(fileName, "r")))
{
int d;
for (d=0; d<nDirectories; ++d)
{
char* pathName = addDirectoryName(directories[d], fileName);
if ((newyyin = fopen(pathName, "r")))
{
printf("%s \\\n", pathName);
buffers[currentBuffer++] = YY_CURRENT_BUFFER;
bufferPaths[currentBuffer] = directories[d];
yy_switch_to_buffer(yy_create_buffer(newyyin, YY_BUF_SIZE));
free(pathName);
return;
}
free(pathName);
}
fprintf
(
stderr,
EXENAME ": could not open file '%s' for source file '%s'",
fileName, sourceFile
);
if (nDirectories)
{
fprintf(stderr, ": %s", strerror(errno));
}
fputs("\n", stderr);
fflush(stdout);
fflush(stderr);
/* only report the first occurance */
lookUp(visitedFiles, fileName);
}
else
{
printf("%s \\\n", fileName);
fflush(stdout);
buffers[currentBuffer++] = YY_CURRENT_BUFFER;
bufferPaths[currentBuffer] = NULL;
yy_switch_to_buffer(yy_create_buffer(newyyin, YY_BUF_SIZE));
}
}
/*
* Replace all '.' with '/'
*/
void dotToSlash(char* fileName)
{
const size_t len = strlen(fileName);
size_t i;
for (i=0; i<len; ++i)
{
if (fileName[i] == '.') fileName[i] = '/';
}
}
/*
* The lexer calls yywrap to handle EOF conditions
*/
int yywrap()
{
/* Close the file for the buffer which has just reached EOF */
/* This causes strange problems on some systems
fclose(yyin);
yyin = 0;
*/
/* Delete the buffer */
yy_delete_buffer(YY_CURRENT_BUFFER);
/* Set buffer counter to previous buffer */
currentBuffer--;
if (currentBuffer >= 0) /* if buffer counter refers to a valid file */
{
/* reset input buffer to the previous buffer on the stack */
yy_switch_to_buffer(buffers[currentBuffer]);
/* Return to the normal state for the previous buffer on the stack */
BEGIN(INITIAL);
/* return 0 to inform lex to continue reading */
return 0;
}
else /* else there are no more buffers on the stack */
{
/* return 1 to inform lex finish now that all buffers have been read */
return 1;
}
}
/*****************************************************************************/