/* * Copyright (c) 2002 Gus Baldauf (gus@picturel.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU * General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* * iverilog-vpi.c * * this program provides the functionality of iverilog-vpi.sh under Win32 */ #include #include #include #include #include #include static void setup_ivl_environment(); static void assign(char **ptr, char *str); /* The compile options: compiler, flags, etc. are in here */ #include "config.h" /* pointers to global strings */ static struct global_strings { char *pCCSRC; /* list of C source files (*.c) */ char *pCXSRC; /* list of C++ source files (*.cc, *.cpp) */ char *pOBJ; /* list of object files */ char *pLIB; /* list of library files */ char *pINCS; /* list of include directories */ char *pDEFS; /* list of definitions */ char *pOUT; /* output file name (.vpi extension), if 0 length then no source files specified */ char *pMINGW; /* path to MinGW directory */ char *pIVL; /* path to IVL directory */ char *pCFLAGS; /* CFLAGS option */ char *pLDLIBS; /* LDLIBS option */ char *pNewPath; /* new PATH environment variable setting */ char *pLD; /* what to use for a linker */ } gstr; static void deInitDynString(char *str) { free(str); } /* when finished, free allocated memory and return error code */ static void myExit(int exitVal) { deInitDynString(gstr.pCCSRC); deInitDynString(gstr.pCXSRC); deInitDynString(gstr.pOBJ); deInitDynString(gstr.pLIB); deInitDynString(gstr.pINCS); deInitDynString(gstr.pDEFS); deInitDynString(gstr.pOUT); deInitDynString(gstr.pMINGW); deInitDynString(gstr.pIVL); deInitDynString(gstr.pCFLAGS); deInitDynString(gstr.pLDLIBS); deInitDynString(gstr.pNewPath); free(gstr.pLD); exit(exitVal); } /* display usage summary and exit */ static void usage() { fprintf(stderr,"usage: iverilog-vpi" IVERILOG_SUFFIX " [src and obj files]...\n"); fprintf(stderr," or iverilog-vpi" IVERILOG_SUFFIX " -mingw=dir\n"); fprintf(stderr," or iverilog-vpi" IVERILOG_SUFFIX " -ivl=dir\n"); myExit(1); } static void initDynString(char **str) { *str = (char *) malloc(1); if (!*str) { fprintf(stderr,"error: out of memory\n"); myExit(4); } *str[0] = 0; } /* initialize dynamic memory buffers */ static void init() { initDynString(&gstr.pCCSRC); initDynString(&gstr.pCXSRC); initDynString(&gstr.pOBJ); initDynString(&gstr.pLIB); initDynString(&gstr.pINCS); initDynString(&gstr.pDEFS); initDynString(&gstr.pOUT); initDynString(&gstr.pMINGW); initDynString(&gstr.pIVL); initDynString(&gstr.pCFLAGS); initDynString(&gstr.pLDLIBS); initDynString(&gstr.pNewPath); /* By default use the C compiler to link the programs. */ assign(&gstr.pLD, IVERILOG_VPI_CC); } /* return true if "str" is terminated with with "end", case insensitive */ static int endsIn (char *end, char *str) { char *ext; if (strlen(end) >= strlen(str)) return 0; ext = str + (strlen(str) - strlen(end)); return stricmp(end,ext) ? 0 : 1; } /* return true if "str" begins with "prefix", case insensitive */ static int startsWith (char *prefix, char *str) { if (strlen(prefix) >= strlen(str)) return 0; return strnicmp(prefix,str,strlen(prefix)) ? 0 : 1; } /* append "app" to "ptr", allocating memory as needed */ /* if count is zero, then copy all characters of "app" */ static void appendn (char **ptr, char *app, int count) { *ptr = (char *) realloc(*ptr,strlen(*ptr)+(count?count:strlen(app))+1); if (*ptr == NULL) { fprintf(stderr,"error: out of memory\n"); myExit(4); } if (count) strncat(*ptr,app,count); else strcat(*ptr,app); } /* append "app" to "ptr", allocating memory as needed */ static void append (char **ptr, char *app) { appendn(ptr,app,0); } /* if the string does not end with a backslash, add one */ static void appendBackSlash(char **str) { if ((*str)[strlen(*str)-1] != '\\') append(str,"\\"); } /* copy count characters of "str" to "ptr", allocating memory as needed */ /* if count is zero, then copy all characters of "str" */ static void assignn (char **ptr, char *str, int count) { *ptr = (char *) realloc(*ptr,(count?count:strlen(str))+1); if (*ptr == NULL) { fprintf(stderr,"error: out of memory\n"); myExit(4); } if (count) { strncpy(*ptr,str,count); (*ptr)[count] = 0; } else strcpy(*ptr,str); } /* copy count characters of "str" to "ptr", allocating memory as needed */ static void assign (char **ptr, char *str) { assignn(ptr,str,0); } /* get a copy of a Icarus Verilog registry string key */ static int GetRegistryKey(char *key, char **value) { long lrv; HKEY hkKey; char *regKeyBuffer; DWORD regKeyType, regKeySize; lrv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\Icarus Verilog",0,KEY_QUERY_VALUE,&hkKey); if (lrv != ERROR_SUCCESS) return 0; lrv = RegQueryValueEx(hkKey,key,NULL,®KeyType,NULL,®KeySize); if ((lrv != ERROR_SUCCESS) || (regKeyType != REG_SZ) || (!regKeySize)) { lrv = RegCloseKey(hkKey); return 0; } regKeyBuffer = (char *) malloc(regKeySize+1); if (!regKeyBuffer) { lrv = RegCloseKey(hkKey); fprintf(stderr,"error: out of memory\n"); myExit(4); } regKeyBuffer[regKeySize] = 0; /* makes sure there is a trailing NULL */ /* This needs an unsigned char *, but for MinGW the char is signed. */ lrv = RegQueryValueEx(hkKey, key, NULL, ®KeyType, (unsigned char *) regKeyBuffer, ®KeySize); if ((lrv != ERROR_SUCCESS) || (regKeyType != REG_SZ) || (!regKeySize)) { lrv = RegCloseKey(hkKey); free(regKeyBuffer); return 0; } RegCloseKey(hkKey); assign(value,regKeyBuffer); free(regKeyBuffer); return 1; } /* store a copy of a Icarus Verilog registry string key */ static void SetRegistryKey(char *key, char *value) { HKEY hkKey; DWORD res; if (RegCreateKeyEx( HKEY_LOCAL_MACHINE, "Software\\Icarus Verilog", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,NULL, &hkKey, &res) != ERROR_SUCCESS) return; /* This needs an unsigned char *, but for MinGW the char is signed. */ RegSetValueEx(hkKey, key, 0, REG_SZ, (unsigned char *) value, strlen(value)+1); RegCloseKey(hkKey); printf("info: storing %s in Windows' registry entry\n",value); printf(" HKEY_LOCAL_MACHINE\\Software\\Icarus Verilog\\%s\n",key); } /* parse the command line, assign results to global variable strings */ static int parse(int argc, char *argv[]) { int idx, srcFileCnt=0; char dot_c_ext[] = ".c"; char dot_cc_ext[] = ".cc"; char dot_cpp_ext[] = ".cpp"; char dot_o_ext[] = ".o"; char name_option[] = "--name="; char lib_option[] = "-l"; char inc_option[] = "-I"; char mingw_option[] = "-mingw="; char ivl_option[] = "-ivl="; char def_option[] = "-D"; if (argc == 1) return 0; for (idx=1; idx