Author: tkreuzer Date: Thu Nov 4 00:54:04 2010 New Revision: 49462
URL: http://svn.reactos.org/svn/reactos?rev=49462&view=rev Log: [SPEC2PDEF] This tool will make me rich. Dedicated to Amine and Richard.
Added: branches/cmake-bringup/tools/spec2pdef/ (with props) branches/cmake-bringup/tools/spec2pdef/spec2pdef.c (with props)
Propchange: branches/cmake-bringup/tools/spec2pdef/ ------------------------------------------------------------------------------ --- bugtraq:logregex (added) +++ bugtraq:logregex Thu Nov 4 00:54:04 2010 @@ -1,0 +1,2 @@ +([Ii]ssue|[Bb]ug)s? #?(\d+)(,? ?#?(\d+))*(,? ?(and |or )?#?(\d+))? +(\d+)
Propchange: branches/cmake-bringup/tools/spec2pdef/ ------------------------------------------------------------------------------ bugtraq:message = See issue #%BUGID% for more details.
Propchange: branches/cmake-bringup/tools/spec2pdef/ ------------------------------------------------------------------------------ bugtraq:url = http://www.reactos.org/bugzilla/show_bug.cgi?id=%BUGID%
Propchange: branches/cmake-bringup/tools/spec2pdef/ ------------------------------------------------------------------------------ tsvn:logminsize = 10
Added: branches/cmake-bringup/tools/spec2pdef/spec2pdef.c URL: http://svn.reactos.org/svn/reactos/branches/cmake-bringup/tools/spec2pdef/sp... ============================================================================== --- branches/cmake-bringup/tools/spec2pdef/spec2pdef.c (added) +++ branches/cmake-bringup/tools/spec2pdef/spec2pdef.c [iso-8859-1] Thu Nov 4 00:54:04 2010 @@ -1,0 +1,348 @@ +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> + +enum +{ + CC_STDCALL, + CC_CDECL, + CC_FASTCALL, + CC_EXTERN, +}; + +char* astrCallingConventions[] = +{ + "STDCALL", + "CDECL", + "FASTCALL", + "EXTERN" +}; + +int +_strcmpx(const char *string1, const char *string2) +{ + while (*string2) + { + if (*string1 != *string2) return (*string1 - *string2); + string1++; + string2++; + } + return 0; +} + +char * +NextLine(char *pc) +{ + /* Skip until the next line or EOF */ + while (*pc != '\n' && *pc != '\r' && *pc != 0) pc++; + if (*pc++ == '\r') pc++; + return pc; +} + +char * +NextToken(char *pc) +{ + /* Skip string */ + while (isprint(*pc) && !isspace(*pc)) pc++; + + /* Skip white spaces */ + while (*pc == ' ' || *pc == '\t') pc++; + + return pc; +} + +typedef struct +{ + char *pcName; + int nNameLength; + char *pcRedirection; + int nRedirectionLength; + int nCallingConvention; + int nOrdinal; + int nStackBytes; +} EXPORT; + +int +ParseLine(char* pcLine, int nLine, EXPORT *pexp) +{ + char *pcCurrent; + + //fprintf(stderr, "info: line %d, pcLine:'%.30s'\n", nLine, pcLine); + + pcCurrent = pcLine; + + /* skip white spaces */ + while (*pcCurrent == ' ') pcCurrent++; + + /* Check for line break */ + if (*pcCurrent == '\n' || *pcCurrent == '\r' || *pcCurrent == 0) return 0; + + /* Check for comment */ + if (*pcCurrent == '#' || *pcCurrent == ';') return 0; + + /* Now we should get either an ordinal or @ */ + if (*pcCurrent == '@') pexp->nOrdinal = -1; + else pexp->nOrdinal = atol(pcCurrent); + + /* Go to next token */ + pcCurrent = NextToken(pcCurrent); + + //fprintf(stderr, "info: Token:'%.10s'\n", pcCurrent); + + /* Now we should get the calling convention */ + if (_strcmpx(pcCurrent, "stdcall ") == 0) + { + pexp->nCallingConvention = CC_STDCALL; + } + else if (_strcmpx(pcCurrent, "cdecl ") == 0) + { + pexp->nCallingConvention = CC_CDECL; + } + else if (_strcmpx(pcCurrent, "fastcall ") == 0 || + _strcmpx(pcCurrent, "FASTCALL ") == 0) + { + pexp->nCallingConvention = CC_FASTCALL; + } + else if (_strcmpx(pcCurrent, "extern ") == 0) + { + pexp->nCallingConvention = CC_EXTERN; + } + else + { + fprintf(stderr, "error: line %d, expected cc, got (%p) %d\n", nLine, pcCurrent, *pcCurrent); + return -1; + } + + //fprintf(stderr, "info: nCallingConvention: %d\n", pexp->nCallingConvention); + + /* Go to next token */ + pcCurrent = NextToken(pcCurrent); + + /* Handle option */ + while (*pcCurrent == '-') + { + fprintf(stderr, "info: got option: '%.10s'\n", pcCurrent); + // FIXME: handle options + + /* Go to next token */ + pcCurrent = NextToken(pcCurrent); + } + + //fprintf(stderr, "info: Name:'%.10s'\n", pcCurrent); + + /* Get name */ + pexp->pcName = pcCurrent; + while (isprint(*pcCurrent) && *pcCurrent != '(') pcCurrent++; + pexp->nNameLength = pcCurrent - pexp->pcName; + + /* Handle parameters */ + pexp->nStackBytes = 0; + if (pexp->nCallingConvention != CC_EXTERN) + { + //fprintf(stderr, "info: options:'%.10s'\n", pcCurrent); + + /* Syntax check */ + if (*pcCurrent++ != '(') + { + fprintf(stderr, "error: line %d, expected '('\n", nLine); + return -1; + } + + pexp->nStackBytes = 0; + while (isalpha(*pcCurrent)) + { + if (_strcmpx(pcCurrent, "long") == 0) + pexp->nStackBytes += 4; + else if (_strcmpx(pcCurrent, "double") == 0) + pexp->nStackBytes += 8; + else if (_strcmpx(pcCurrent, "ptr") == 0 || + _strcmpx(pcCurrent, "str") == 0 || + _strcmpx(pcCurrent, "wstr") == 0) + pexp->nStackBytes += sizeof(void*); + else + fprintf(stderr, "error: line %d, expected type, got: %.10s\n", nLine, pcCurrent); + + /* Go to next parameter */ + while (isalpha(*pcCurrent)) pcCurrent++; + while (isspace(*pcCurrent)) pcCurrent++; + } + + /* Check syntax */ + if (*pcCurrent++ != ')') + { + fprintf(stderr, "error: line %d, expected ')'\n", nLine); + return -1; + } + + /* Skip white spaces */ + while (*pcCurrent == ' ' || *pcCurrent == '\t') pcCurrent++; + } + + /* Get optional redirection */ + if (isprint(*pcCurrent)) + { + pexp->pcRedirection = pcCurrent; + while (isprint(*pcCurrent) && !isspace(*pcCurrent)) pcCurrent++; + pexp->nRedirectionLength = pcCurrent - pexp->pcRedirection; + } + else + { + pexp->pcRedirection = 0; + pexp->nRedirectionLength = 0; + } + + return 1; +} + +int +OutputLine_def(FILE *fileDest, EXPORT *exp) +{ + fprintf(fileDest, " "); + if (exp->nCallingConvention == CC_FASTCALL) fprintf(fileDest, "@"); + fprintf(fileDest, "%.*s", exp->nNameLength, exp->pcName); + + if (exp->nCallingConvention == CC_STDCALL || + exp->nCallingConvention == CC_FASTCALL) + { + fprintf(fileDest, "@%d", exp->nStackBytes); + } + + if (exp->pcRedirection) + { + if (exp->nCallingConvention == CC_FASTCALL) fprintf(fileDest, "@"); + fprintf(fileDest, "=%.*s", exp->nRedirectionLength, exp->pcRedirection); + if (exp->nCallingConvention == CC_STDCALL || + exp->nCallingConvention == CC_FASTCALL) + { + fprintf(fileDest, "@%d", exp->nStackBytes); + } + } + + if (exp->nOrdinal != -1) + { + fprintf(fileDest, " @%d", exp->nOrdinal); + } + + if (exp->nCallingConvention == CC_EXTERN) + { + fprintf(fileDest, " DATA"); + } + + fprintf(fileDest, "\n"); + + return 1; +} + +int +OutputLine(FILE *fileDest, EXPORT *exp) +{ + fprintf(fileDest, "_NAME(%.*s,%s,%d)", + exp->nNameLength, exp->pcName, + astrCallingConventions[exp->nCallingConvention], + exp->nStackBytes); + + if (exp->pcRedirection) + { + fprintf(fileDest, "= _NAME(%.*s,%s,%d)", + exp->nRedirectionLength, exp->pcRedirection, + astrCallingConventions[exp->nCallingConvention], + exp->nStackBytes); + } + + if (exp->nOrdinal != -1) + { + fprintf(fileDest, " @%d", exp->nOrdinal); + } + + if (exp->nCallingConvention == CC_EXTERN) + { + fprintf(fileDest, " DATA"); + } + + fprintf(fileDest, "\n"); + + return 1; +} + +void +OutputHeader(FILE *file) +{ + fprintf(file, + "; File generated automatically, do not edit!\n\n" + "LIBRARY ntoskrnl.exe\n\n" + "EXPORTS\n" + "#define FOOL(x) x\n" + "#ifdef _MSC_VER\n" + "#define _NAME_STDCALL(name, stackbytes) name\n" + "#define _NAME_FASTCALL(name, stackbytes) name\n" + "#define _NAME_CDECL(name, stackbytes) name\n" + "#else\n" + "#define _NAME_STDCALL(name, stackbytes) FOOL(name)@stackbytes\n" + "#define _NAME_FASTCALL(name, stackbytes) FOOL(@)FOOL(name)@stackbytes\n" + "#define _NAME_CDECL(name, stackbytes) FOOL(name)\n" + "#endif\n" + "#define _NAME_EXTERN(name, stackbytes) name\n" + "#define _NAME(name, cc, stackbytes) _NAME_##cc(name, stackbytes)\n"); +} + + +int main(int argc, char *argv[]) +{ + size_t nFileSize; + char *pszSource, *pcLine; + int nLine, result; + FILE *fileSource, *fileDest; + EXPORT exp; + + /* Open input file argv[1] */ + fileSource = fopen(argv[1], "r"); + if (!fileSource) + { + fprintf(stderr, "error: could not open file %s ", argv[1]); + return -1; + } + + /* Get file size */ + fseek(fileSource, 0, SEEK_END); + nFileSize = ftell(fileSource); + rewind(fileSource); + + /* Allocate memory buffer */ + pszSource = malloc(nFileSize + 1); + if (!pszSource) return -1; + + /* Load input file into memory */ + nFileSize = fread(pszSource, 1, nFileSize, fileSource); + + /* Zero terminate the source */ + pszSource[nFileSize] = '\0'; + + // open output file argv[2] + fileDest = fopen(argv[2], "w"); + if (!fileDest) + { + fprintf(stderr, "error: could not open output file %s ", argv[2]); + return -1; + } + + OutputHeader(fileDest); + + pcLine = pszSource; + for (nLine = 1; *pcLine != 0; pcLine = NextLine(pcLine), nLine++) + { + /* Parse the spec file line */ + result = ParseLine(pcLine, nLine, &exp); + + if (result == 1) + { + OutputLine(fileDest, &exp); + } + else if (result == -1) break; + + + } + + fclose(fileDest); + fclose(fileSource); + return 0; +}
Propchange: branches/cmake-bringup/tools/spec2pdef/spec2pdef.c ------------------------------------------------------------------------------ svn:eol-style = native