fixed WIndows build error; minor MIB compiler refactoring
[public/netxms.git] / src / snmp / nxmibc / nxmibc.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** NetXMS MIB compiler
4 ** Copyright (C) 2005-2012 Victor Kirhenshtein
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation; either version 2 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 ** File: nxmibc.cpp
21 **
22 **/
23
24 #include "nxmibc.h"
25
26 #ifdef _WIN32
27 #include <conio.h>
28 #endif
29
30 /**
31 * Severity codes
32 */
33 #define MIBC_INFO 0
34 #define MIBC_WARNING 1
35 #define MIBC_ERROR 2
36
37 /**
38 * Externals
39 */
40 int ParseMIBFiles(StringList *fileList, SNMP_MIBObject **ppRoot);
41
42 /**
43 * Static data
44 */
45 static char m_szOutFile[MAX_PATH] = "netxms.mib";
46 static StringList s_fileList;
47 static bool s_pauseBeforeExit = false;
48
49 /**
50 * Errors
51 */
52 static struct
53 {
54 int nSeverity;
55 const TCHAR *pszText;
56 } m_errorList[] =
57 {
58 { MIBC_INFO, _T("Operation completed successfully") },
59 { MIBC_ERROR, _T("Import symbol \"%hs\" unresolved") },
60 { MIBC_ERROR, _T("Import module \"%hs\" unresolved") },
61 { MIBC_ERROR, _T("Parser error - %hs in line %d") },
62 { MIBC_ERROR, _T("Cannot open input file (%hs)") },
63 { MIBC_ERROR, _T("Cannot resolve symbol %hs") },
64 { MIBC_WARNING, _T("Cannot resolve data type \"%hs\" for object \"%hs\"") }
65 };
66
67 /**
68 * Pause if needed
69 */
70 static void Pause()
71 {
72 if (s_pauseBeforeExit)
73 {
74 #ifdef _WIN32
75 _tprintf(_T("Press any key to continue...\n"));
76 _getch();
77 #else
78 _tprintf(_T("Press ENTER to continue...\n"));
79 char temp[256];
80 fgets(temp, 255, stdin);
81 #endif
82 }
83 }
84
85 /**
86 * Display error text and abort compilation
87 */
88 extern "C" void Error(int nError, char *pszModule, ...)
89 {
90 va_list args;
91 static const TCHAR *severityText[] = { _T("INFO"), _T("WARNING"), _T("ERROR") };
92
93 _tprintf(_T("%hs: %s %03d: "), pszModule, severityText[m_errorList[nError].nSeverity], nError);
94 va_start(args, pszModule);
95 _vtprintf(m_errorList[nError].pszText, args);
96 va_end(args);
97 _tprintf(_T("\n"));
98 if (m_errorList[nError].nSeverity == MIBC_ERROR)
99 {
100 Pause();
101 exit(1);
102 }
103 }
104
105 /**
106 * Display help and exit
107 */
108 static void Help()
109 {
110 _tprintf(_T("Usage:\n\n")
111 _T("nxmibc [options] source1 ... sourceN\n\n")
112 _T("Valid options:\n")
113 _T(" -d <dir> : Include all MIB files from given directory to compilation\n")
114 _T(" -r : Scan sub-directories \n")
115 _T(" -e <ext> : Specify file extensions (default extension: \"txt\") \n")
116 _T(" -o <file> : Set output file name (default is netxms.mib)\n")
117 _T(" -P : Pause before exit\n")
118 _T(" -s : Strip descriptions from MIB objects\n")
119 _T(" -z : Compress output file\n")
120 _T("\n"));
121 exit(0);
122 }
123
124 /**
125 * Scan directory for MIB files
126 */
127 static void ScanDirectory(const TCHAR *path, const StringSet *extensions, bool recursive)
128 {
129 _TDIR *pDir = _topendir(path);
130 if (pDir != NULL)
131 {
132 while(true)
133 {
134 struct _tdirent *pFile = _treaddir(pDir);
135 if (pFile == NULL)
136 break;
137 if (_tcscmp(pFile->d_name, _T(".")) && _tcscmp(pFile->d_name, _T("..")))
138 {
139 TCHAR szBuffer[MAX_PATH];
140 _sntprintf(szBuffer, MAX_PATH, _T("%s") FS_PATH_SEPARATOR _T("%s"), path, pFile->d_name);
141 if (recursive && (pFile->d_type == DT_DIR))
142 {
143 ScanDirectory(szBuffer, extensions, recursive);
144 }
145 else
146 {
147 TCHAR *extension = _tcsrchr(pFile->d_name, _T('.'));
148 if ((extension != NULL) && extensions->contains(extension + 1))
149 s_fileList.add(szBuffer);
150 }
151 }
152 }
153 _tclosedir(pDir);
154 }
155 }
156
157 /**
158 * Entry point
159 */
160 int main(int argc, char *argv[])
161 {
162 bool recursive = false;
163 bool scanDir = false;
164 SNMP_MIBObject *pRoot;
165 DWORD dwFlags = 0, dwRet;
166 int i, ch, rc = 0;
167
168 InitNetXMSProcess(true);
169
170 _tprintf(_T("NetXMS MIB Compiler Version ") NETXMS_VERSION_STRING _T(" (") NETXMS_BUILD_TAG _T(")\n")
171 _T("Copyright (c) 2005-2017 Raden Solutions\n\n"));
172
173 StringList paths;
174 StringSet extensions;
175 extensions.add(_T("txt"));
176
177 // Parse command line
178 opterr = 1;
179 while((ch = getopt(argc, argv, "rd:ho:e:Psz")) != -1)
180 {
181 switch(ch)
182 {
183 case 'e':
184 #ifdef UNICODE
185 extensions.addPreallocated(WideStringFromMBStringSysLocale(optarg));
186 #else
187 extensions.add(optarg);
188 #endif
189 break;
190 case 'h': // Display help and exit
191 Help();
192 break;
193 case 'd':
194 #ifdef UNICODE
195 paths.addPreallocated(_wcslwr(WideStringFromMBStringSysLocale(optarg)));
196 #else
197 paths.add(strlwr(optarg));
198 #endif
199 scanDir = true;
200 break;
201 case 'o':
202 strncpy(m_szOutFile, optarg, MAX_PATH);
203 m_szOutFile[MAX_PATH - 1] = 0;
204 break;
205 case 'P':
206 s_pauseBeforeExit = true;
207 break;
208 case 'r':
209 recursive = true;
210 break;
211 case 's':
212 dwFlags |= SMT_SKIP_DESCRIPTIONS;
213 break;
214 case 'z':
215 dwFlags |= SMT_COMPRESS_DATA;
216 break;
217 case '?':
218 return 255;
219 default:
220 break;
221 }
222 }
223
224 if (scanDir)
225 {
226 for(int i = 0; i < paths.size(); i++)
227 {
228 ScanDirectory(paths.get(i), &extensions, recursive);
229 }
230 }
231
232 for(i = optind; i < argc; i++)
233 {
234 #ifdef UNICODE
235 s_fileList.addPreallocated(WideStringFromMBStringSysLocale(argv[i]));
236 #else
237 s_fileList.add(argv[i]);
238 #endif
239 }
240
241 if (s_fileList.size() > 0)
242 {
243 ParseMIBFiles(&s_fileList, &pRoot);
244
245 if (pRoot != NULL)
246 {
247 #ifdef UNICODE
248 WCHAR *wname = WideStringFromMBString(m_szOutFile);
249 dwRet = SNMPSaveMIBTree(wname, pRoot, dwFlags);
250 free(wname);
251 #else
252 dwRet = SNMPSaveMIBTree(m_szOutFile, pRoot, dwFlags);
253 #endif
254 delete pRoot;
255 if (dwRet != SNMP_ERR_SUCCESS)
256 {
257 _tprintf(_T("ERROR: Cannot save output file %hs (%s)\n"), m_szOutFile, SNMPGetErrorText(dwRet));
258 rc = 1;
259 }
260 }
261 }
262 else
263 {
264 _tprintf(_T("ERROR: No source files given\n"));
265 rc = 1;
266 }
267
268 Pause();
269 return rc;
270 }