- Timestamp:
- Mar 20, 2012 6:07:34 PM (13 years ago)
- Location:
- trunk/src/bldprogs
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/bldprogs/Makefile.kmk
r40549 r40554 5 5 6 6 # 7 # Copyright (C) 2006-201 0Oracle Corporation7 # Copyright (C) 2006-2012 Oracle Corporation 8 8 # 9 9 # This file is part of VirtualBox Open Source Edition (OSE), as … … 41 41 scmrw.cpp \ 42 42 scmstream.cpp \ 43 scmsubversion.cpp 43 scmsubversion.cpp 44 44 45 45 46 #BLDPROGS += VBoxTpG46 BLDPROGS += VBoxTpG 47 47 VBoxTpG_TEMPLATE = VBoxAdvBldProg 48 48 VBoxTpG_SOURCES = \ -
trunk/src/bldprogs/VBoxTpG.cpp
r40549 r40554 5 5 6 6 /* 7 * Copyright (C) 201 0-2012 Oracle Corporation7 * Copyright (C) 2012 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 20 20 * Header Files * 21 21 *******************************************************************************/ 22 #include <iprt/alloca.h> 22 23 #include <iprt/assert.h> 23 24 #include <iprt/ctype.h> 24 25 #include <iprt/env.h> 25 26 #include <iprt/err.h> 27 #include <iprt/file.h> 26 28 #include <iprt/getopt.h> 27 29 #include <iprt/initterm.h> 30 #include <iprt/list.h> 28 31 #include <iprt/mem.h> 29 32 #include <iprt/message.h> 33 #include <iprt/process.h> 30 34 #include <iprt/stream.h> 31 35 #include <iprt/string.h> 36 #include <iprt/strcache.h> 32 37 33 38 #include "scmstream.h" 34 39 35 enum 36 { 37 kVBoxTpGOpt_32Bit = 1000, 38 kVBoxTpGOpt_64Bit, 39 kVBoxTpGOpt_Assembler, 40 kVBoxTpGOpt_AssemblerOption, 41 kVBoxTpGOpt_AssemblerFmtOpt, 42 kVBoxTpGOpt_AssemblerFmtVal, 43 kVBoxTpGOpt_AssemblerOutputOpt, 44 }; 45 46 47 int main(int argc, char **argv) 48 { 49 int rc = RTR3InitExe(argc, &argv, 0); 40 41 /******************************************************************************* 42 * Structures and Typedefs * 43 *******************************************************************************/ 44 typedef struct VTGARG 45 { 46 const char *pszName; 47 const char *pszType; 48 } VTGARG; 49 typedef VTGARG *PVTGARG; 50 51 typedef struct VTGPROBE 52 { 53 RTLISTNODE ListEntry; 54 const char *pszName; 55 uint32_t cArgs; 56 PVTGARG paArgs; 57 } VTGPROBE; 58 typedef VTGPROBE *PVTGPROBE; 59 60 typedef struct VTGPROVIDER 61 { 62 RTLISTNODE ListEntry; 63 const char *pszName; 64 RTLISTANCHOR ProbeHead; 65 } VTGPROVIDER; 66 typedef VTGPROVIDER *PVTGPROVIDER; 67 68 69 /******************************************************************************* 70 * Global Variables * 71 *******************************************************************************/ 72 /** String cache used for storing strings when parsing. */ 73 static RTSTRCACHE g_hStrCache = NIL_RTSTRCACHE; 74 /** List of providers created by the parser. */ 75 static RTLISTANCHOR g_ProviderHead; 76 77 /** @name Options 78 * @{ */ 79 static enum 80 { 81 kVBoxTpGAction_Nothing, 82 kVBoxTpGAction_GenerateHeader, 83 kVBoxTpGAction_GenerateObject 84 } g_enmAction = kVBoxTpGAction_Nothing; 85 static uint32_t g_cBits = ARCH_BITS; 86 static bool g_fApplyCpp = false; 87 static uint32_t g_cVerbosity = 0; 88 static const char *g_pszOutput = NULL; 89 static const char *g_pszScript = NULL; 90 static const char *g_pszTempAsm = NULL; 91 #ifdef RT_OS_DARWIN 92 static const char *g_pszAssembler = "yasm"; 93 static const char *g_pszAssemblerFmtOpt = "--oformat"; 94 static const char g_szAssemblerFmtVal32[] = "macho32"; 95 static const char g_szAssemblerFmtVal64[] = "macho64"; 96 #elif defined(RT_OS_OS2) 97 static const char *pszAssembler = "nasm.exe"; 98 static const char *pszAssemblerFmtOpt = "-f"; 99 static const char g_szAssemblerFmtVal32[] = "obj"; 100 static const char g_szAssemblerFmtVal64[] = "elf64"; 101 #elif defined(RT_OS_WINDOWS) 102 static const char *g_pszAssembler = "yasm.exe"; 103 static const char *g_pszAssemblerFmtOpt = "--oformat"; 104 static const char g_szAssemblerFmtVal32[] = "win32"; 105 static const char g_szAssemblerFmtVal64[] = "win64"; 106 #else 107 static const char *g_pszAssembler = "yasm"; 108 static const char *g_pszAssemblerFmtOpt = "--oformat"; 109 static const char g_szAssemblerFmtVal32[] = "elf32"; 110 static const char g_szAssemblerFmtVal64[] = "elf64"; 111 #endif 112 static const char *g_pszAssemblerFmtVal = RT_CONCAT(g_szAssemblerFmtVal, ARCH_BITS); 113 static const char *g_pszAssemblerOutputOpt = "-o"; 114 static unsigned g_cAssemblerOptions = 0; 115 static const char *g_apszAssemblerOptions[32]; 116 /** @} */ 117 118 119 static RTEXITCODE generateInvokeAssembler(const char *pszOutput, const char *pszTempAsm) 120 { 121 RTPrintf("Todo invoke the assembler\n"); 122 return RTEXITCODE_SKIPPED; 123 } 124 125 126 static RTEXITCODE generateFile(const char *pszOutput, const char *pszWhat, 127 RTEXITCODE (*pfnGenerator)(PSCMSTREAM)) 128 { 129 SCMSTREAM Strm; 130 int rc = ScmStreamInitForWriting(&Strm, NULL); 50 131 if (RT_FAILURE(rc)) 51 return 1; 52 132 return RTMsgErrorExit(RTEXITCODE_FAILURE, "ScmStreamInitForWriting returned %Rrc when generating the %s file", 133 rc, pszWhat); 134 135 RTEXITCODE rcExit = pfnGenerator(&Strm); 136 if (RT_FAILURE(ScmStreamGetStatus(&Strm))) 137 rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Stream error %Rrc generating the %s file", 138 ScmStreamGetStatus(&Strm), pszWhat); 139 if (rcExit == RTEXITCODE_SUCCESS) 140 { 141 rc = ScmStreamWriteToFile(&Strm, "%s", pszOutput); 142 if (RT_FAILURE(rc)) 143 rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "ScmStreamWriteToFile returned %Rrc when writing '%s' (%s)", 144 rc, pszOutput, pszWhat); 145 if (rcExit == RTEXITCODE_SUCCESS) 146 { 147 if (g_cVerbosity > 0) 148 RTMsgInfo("Successfully generated '%s'.", pszOutput); 149 if (g_cVerbosity > 1) 150 { 151 RTMsgInfo("================ %s - start ================", pszWhat); 152 ScmStreamRewindForReading(&Strm); 153 const char *pszLine; 154 size_t cchLine; 155 SCMEOL enmEol; 156 while ((pszLine = ScmStreamGetLine(&Strm, &cchLine, &enmEol)) != NULL) 157 RTPrintf("%.*s\n", cchLine, pszLine); 158 RTMsgInfo("================ %s - end ================", pszWhat); 159 } 160 } 161 } 162 ScmStreamDelete(&Strm); 163 return rcExit; 164 } 165 166 167 static RTEXITCODE generateAssembly(PSCMSTREAM pStrm) 168 { 169 if (g_cVerbosity > 0) 170 RTMsgInfo("Generating assembly code..."); 171 172 RTPrintf("Todo generate the assembly code\n"); 173 return RTEXITCODE_SUCCESS; 174 } 175 176 177 static RTEXITCODE generateObject(const char *pszOutput, const char *pszTempAsm) 178 { 179 if (!pszTempAsm) 180 { 181 size_t cch = strlen(pszTempAsm); 182 char *psz = (char *)alloca(cch + sizeof(".asm")); 183 memcpy(psz, pszOutput, cch); 184 memcpy(psz + cch, ".asm", sizeof(".asm")); 185 pszTempAsm = psz; 186 } 187 188 RTEXITCODE rcExit = generateFile(pszTempAsm, "assembly", generateAssembly); 189 if (rcExit == RTEXITCODE_SUCCESS) 190 rcExit = generateInvokeAssembler(pszOutput, pszTempAsm); 191 RTFileDelete(pszTempAsm); 192 return rcExit; 193 } 194 195 196 static RTEXITCODE generateHeaderInner(PSCMSTREAM pStrm) 197 { 198 RTPrintf("Todo generate the header\n"); 199 return RTEXITCODE_SUCCESS; 200 } 201 202 203 static RTEXITCODE generateHeader(const char *pszHeader) 204 { 205 return generateFile(pszHeader, "header", generateHeaderInner); 206 } 207 208 /** 209 * If the given C word is at off - 1, return @c true and skip beyond it, 210 * otherwise return @c false. 211 * 212 * @retval true if the given C-word is at the current position minus one char. 213 * The stream position changes. 214 * @retval false if not. The stream position is unchanged. 215 * 216 * @param pStream The stream. 217 * @param cchWord The length of the word. 218 * @param pszWord The word. 219 */ 220 bool ScmStreamCMatchingWordM1(PSCMSTREAM pStream, size_t cchWord, const char *pszWord) 221 { 222 /* Check stream state. */ 223 AssertReturn(!pStream->fWriteOrRead, false); 224 AssertReturn(RT_SUCCESS(pStream->rc), false); 225 AssertReturn(pStream->fFullyLineated, false); 226 227 /* Sufficient chars left on the line? */ 228 size_t const iLine = pStream->iLine; 229 AssertReturn(pStream->off > pStream->paLines[iLine].off, false); 230 size_t const cchLeft = pStream->paLines[iLine].cch + pStream->paLines[iLine].off - (pStream->off - 1); 231 if (cchWord > cchLeft) 232 return false; 233 234 /* Do they match? */ 235 const char *psz = &pStream->pch[pStream->off - 1]; 236 if (memcmp(psz, pszWord, cchWord)) 237 return false; 238 239 /* Is it the end of a C word? */ 240 if (cchWord < cchLeft) 241 { 242 psz += cchWord; 243 if (RT_C_IS_ALNUM(*psz) || *psz == '_') 244 return false; 245 } 246 247 /* Skip ahead. */ 248 pStream->off += cchWord - 1; 249 return true; 250 } 251 252 /** 253 * Get's the C word starting at the current position. 254 * 255 * @returns Pointer to the word on success and the stream position advanced to 256 * the end of it. 257 * NULL on failure, stream position normally unchanged. 258 * @param pStream The stream to get the C word from. 259 * @param pcchWord Where to return the word length. 260 */ 261 const char *ScmStreamCGetWord(PSCMSTREAM pStream, size_t *pcchWord) 262 { 263 /* Check stream state. */ 264 AssertReturn(!pStream->fWriteOrRead, false); 265 AssertReturn(RT_SUCCESS(pStream->rc), false); 266 AssertReturn(pStream->fFullyLineated, false); 267 268 /* Get the number of chars left on the line and locate the current char. */ 269 size_t const iLine = pStream->iLine; 270 size_t const cchLeft = pStream->paLines[iLine].cch + pStream->paLines[iLine].off - pStream->off; 271 const char *psz = &pStream->pch[pStream->off]; 272 273 /* Is it a leading C character. */ 274 if (!RT_C_IS_ALPHA(*psz) && !*psz == '_') 275 return NULL; 276 277 /* Find the end of the word. */ 278 char ch; 279 size_t off = 1; 280 while ( off < cchLeft 281 && ( (ch = psz[off]) == '_' 282 || RT_C_IS_ALNUM(ch))) 283 off++; 284 285 pStream->off += off; 286 *pcchWord = off; 287 return psz; 288 } 289 290 291 /** 292 * Parser error with line and position. 293 * 294 * @returns RTEXITCODE_FAILURE. 295 * @param pStrm The stream. 296 * @param cb The offset from the current position to the 297 * point of failure. 298 * @param pszMsg The message to display. 299 */ 300 static RTEXITCODE parseError(PSCMSTREAM pStrm, size_t cb, const char *pszMsg) 301 { 302 ScmStreamSeekRelative(pStrm, -cb); 303 size_t const off = ScmStreamTell(pStrm); 304 size_t const iLine = ScmStreamTellLine(pStrm); 305 ScmStreamSeekByLine(pStrm, iLine); 306 size_t const offLine = ScmStreamTell(pStrm); 307 308 RTPrintf("%s:%d:%zd: error: %s\n", g_pszScript, iLine + 1, off - offLine, pszMsg); 309 310 size_t cchLine; 311 SCMEOL enmEof; 312 const char *pszLine = ScmStreamGetLineByNo(pStrm, iLine, &cchLine, &enmEof); 313 if (pszLine) 314 RTPrintf(" %.*s\n" 315 " %*s^\n", 316 cchLine, pszLine, off - offLine, ""); 317 return RTEXITCODE_FAILURE; 318 } 319 320 /** 321 * Handles a C++ one line comment. 322 * 323 * @returns Exit code. 324 * @param pStrm The stream. 325 */ 326 static RTEXITCODE parseOneLineComment(PSCMSTREAM pStrm) 327 { 328 ScmStreamSeekByLine(pStrm, ScmStreamTellLine(pStrm) + 1); 329 return RTEXITCODE_SUCCESS; 330 } 331 332 /** 333 * Handles a multi-line C/C++ comment. 334 * 335 * @returns Exit code. 336 * @param pStrm The stream. 337 */ 338 static RTEXITCODE parseMultiLineComment(PSCMSTREAM pStrm) 339 { 340 unsigned ch; 341 while ((ch = ScmStreamGetCh(pStrm)) != ~(unsigned)0) 342 { 343 if (ch == '*') 344 { 345 do 346 ch = ScmStreamGetCh(pStrm); 347 while (ch == '*'); 348 if (ch == '/') 349 return RTEXITCODE_SUCCESS; 350 } 351 } 352 353 parseError(pStrm, 1, "Expected end of comment, got end of file"); 354 return RTEXITCODE_FAILURE; 355 } 356 357 358 /** 359 * Skips spaces and comments. 360 * 361 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE. 362 * @param pStrm The stream.. 363 */ 364 static RTEXITCODE parseSkipSpacesAndComments(PSCMSTREAM pStrm) 365 { 366 unsigned ch; 367 while ((ch = ScmStreamPeekCh(pStrm)) != ~(unsigned)0) 368 { 369 if (!RT_C_IS_SPACE(ch) && ch != '/') 370 return RTEXITCODE_SUCCESS; 371 ch = ScmStreamGetCh(pStrm); 372 AssertBreak(ch != ~(unsigned)0); 373 if (ch == '/') 374 { 375 ch = ScmStreamGetCh(pStrm); 376 RTEXITCODE rcExit; 377 if (ch == '*') 378 rcExit = parseMultiLineComment(pStrm); 379 else if (ch == '/') 380 rcExit = parseOneLineComment(pStrm); 381 else 382 rcExit = parseError(pStrm, 2, "Unexpected character"); 383 if (rcExit != RTEXITCODE_SUCCESS) 384 return rcExit; 385 } 386 } 387 388 return parseError(pStrm, 0, "Unexpected end of file"); 389 } 390 391 392 393 static RTEXITCODE parseProvider(PSCMSTREAM pStrm) 394 { 53 395 /* 54 * Parse arguments and process input in order (because this is the only 55 * thing that works at the moment). 396 * Next up is a name followed by a curly bracket. Ignore comment.s 56 397 */ 398 RTEXITCODE rcExit = parseSkipSpacesAndComments(pStrm); 399 if (rcExit != RTEXITCODE_SUCCESS) 400 return parseError(pStrm, 1, "Expected a provider name starting with an alphabetical character"); 401 size_t cchName; 402 const char *pszName = ScmStreamCGetWord(pStrm, &cchName); 403 if (!pszName) 404 return parseError(pStrm, 0, "Bad provider name"); 405 if (RT_C_IS_DIGIT(pszName[cchName - 1])) 406 return parseError(pStrm, 1, "A provider name cannot end with digit"); 407 408 rcExit = parseSkipSpacesAndComments(pStrm); 409 if (rcExit != RTEXITCODE_SUCCESS) 410 return parseError(pStrm, 1, "Expected a provider name starting with an alphabetical character"); 411 unsigned ch = ScmStreamGetCh(pStrm); 412 if (ch != '{') 413 return parseError(pStrm, 1, "Expected '{' after the provider name"); 414 415 /* 416 * Create a provider instance. 417 */ 418 PVTGPROVIDER pProv = (PVTGPROVIDER)RTMemAllocZ(sizeof(*pProv)); 419 if (!pProv) 420 return parseError(pStrm, 0, "Out of memory"); 421 RTListAppend(&g_ProviderHead, &pProv->ListEntry); 422 pProv->pszName = RTStrCacheEnterN(g_hStrCache, pszName, cchName); 423 if (pProv->pszName) 424 return parseError(pStrm, 0, "Out of memory"); 425 426 /* 427 * Next up is a brace 428 */ 429 430 431 return parseError(pStrm, 0, "'provider' not implemented"); 432 } 433 434 435 static RTEXITCODE parseScript(const char *pszScript) 436 { 437 SCMSTREAM Strm; 438 int rc = ScmStreamInitForReading(&Strm, pszScript); 439 if (RT_FAILURE(rc)) 440 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to open & read '%s' into memory: %Rrc", pszScript, rc); 441 if (g_cVerbosity > 0) 442 RTMsgInfo("Parsing '%s'...", pszScript); 443 444 RTEXITCODE rcExit = RTEXITCODE_SUCCESS; 445 unsigned ch; 446 while ((ch = ScmStreamGetCh(&Strm)) != ~(unsigned)0) 447 { 448 if (RT_C_IS_SPACE(ch)) 449 continue; 450 switch (ch) 451 { 452 case '/': 453 ch = ScmStreamGetCh(&Strm); 454 if (ch == '*') 455 rcExit = parseMultiLineComment(&Strm); 456 else if (ch == '/') 457 rcExit = parseOneLineComment(&Strm); 458 else 459 rcExit = parseError(&Strm, 2, "Unexpected character"); 460 break; 461 462 case 'p': 463 if (ScmStreamCMatchingWordM1(&Strm, RT_STR_TUPLE("provider"))) 464 rcExit = parseProvider(&Strm); 465 else 466 rcExit = parseError(&Strm, 1, "Unexpected character"); 467 break; 468 469 case '#': 470 rcExit = parseError(&Strm, 1, "Not implemented"); 471 break; 472 473 default: 474 rcExit = parseError(&Strm, 1, "Unexpected character"); 475 break; 476 } 477 if (rcExit != RTEXITCODE_SUCCESS) 478 return rcExit; 479 } 480 481 ScmStreamDelete(&Strm); 482 if (g_cVerbosity > 0 && rcExit == RTEXITCODE_SUCCESS) 483 RTMsgInfo("Successfully parsed '%s'.", pszScript); 484 return rcExit; 485 } 486 487 488 /** 489 * Parses the arguments. 490 */ 491 static RTEXITCODE parseArguments(int argc, char **argv) 492 { 493 enum 494 { 495 kVBoxTpGOpt_32Bit = 1000, 496 kVBoxTpGOpt_64Bit, 497 kVBoxTpGOpt_Assembler, 498 kVBoxTpGOpt_AssemblerFmtOpt, 499 kVBoxTpGOpt_AssemblerFmtVal, 500 kVBoxTpGOpt_AssemblerOutputOpt, 501 kVBoxTpGOpt_AssemblerOption, 502 kVBoxTpGOpt_End 503 }; 504 57 505 static RTGETOPTDEF const s_aOpts[] = 58 506 { 59 { "-32", kVBoxTpGOpt_32BIT, RTGETOPT_REQ_NOTHING }, 60 { "-64", kVBoxTpGOpt_64BIT, RTGETOPT_REQ_NOTHING }, 507 /* dtrace w/ long options */ 508 { "-32", kVBoxTpGOpt_32Bit, RTGETOPT_REQ_NOTHING }, 509 { "-64", kVBoxTpGOpt_64Bit, RTGETOPT_REQ_NOTHING }, 61 510 { "--apply-cpp", 'C', RTGETOPT_REQ_NOTHING }, 62 511 { "--generate-obj", 'G', RTGETOPT_REQ_NOTHING }, … … 64 513 { "--output", 'o', RTGETOPT_REQ_STRING }, 65 514 { "--script", 's', RTGETOPT_REQ_STRING }, 515 { "--verbose", 'v', RTGETOPT_REQ_NOTHING }, 516 /* out stuff */ 66 517 { "--assembler", kVBoxTpGOpt_Assembler, RTGETOPT_REQ_STRING }, 67 518 { "--assembler-fmt-opt", kVBoxTpGOpt_AssemblerFmtOpt, RTGETOPT_REQ_STRING }, … … 71 522 }; 72 523 73 enum74 {75 kVBoxTpGAction_Nothing,76 kVBoxTpGAction_GenerateHeader,77 kVBoxTpGAction_GenerateObject,78 } enmAction = kVBoxTpGAction_Nothing;79 80 const char *pszAssembler = "yasm";81 const char *pszAssemblerFmtOpt = "--oformat";82 #ifdef RT_OS_DARWIN83 const char *pszAssemblerFmtVal = "macho" RT_XSTR(ARCH_BITS);84 #elif defined(RT_OS_WINDOWS)85 const char *pszAssemblerFmtVal = "win" RT_XSTR(ARCH_BITS);86 #else87 const char *pszAssemblerFmtVal = "elf" RT_XSTR(ARCH_BITS);88 #endif89 const char *pszAssemblerOutputOpt = "-o"90 const char *apszAssemblerOptions[32] = { NULL, NULL, };91 92 93 524 RTGETOPTUNION ValueUnion; 94 525 RTGETOPTSTATE GetOptState; 95 rc = RTGetOptInit(&GetOptState, argc, argv, &s_aOpts[0], RT_ELEMENTS(s_aOpts), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST); 96 AssertReleaseRCReturn(rc, 1); 97 size_t cProcessed = 0; 526 int rc = RTGetOptInit(&GetOptState, argc, argv, &s_aOpts[0], RT_ELEMENTS(s_aOpts), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST); 527 AssertReleaseRCReturn(rc, RTEXITCODE_FAILURE); 98 528 99 529 while ((rc = RTGetOpt(&GetOptState, &ValueUnion)) != 0) … … 101 531 switch (rc) 102 532 { 533 /* 534 * DTrace compatible options. 535 */ 536 case kVBoxTpGOpt_32Bit: 537 g_cBits = 32; 538 g_pszAssemblerFmtOpt = g_szAssemblerFmtVal32; 539 break; 540 541 case kVBoxTpGOpt_64Bit: 542 g_cBits = 64; 543 g_pszAssemblerFmtOpt = g_szAssemblerFmtVal64; 544 break; 545 546 case 'C': 547 g_fApplyCpp = true; 548 RTMsgWarning("Ignoring the -C option - no preprocessing of the D script will be performed"); 549 break; 550 551 case 'G': 552 if ( g_enmAction != kVBoxTpGAction_Nothing 553 && g_enmAction != kVBoxTpGAction_GenerateObject) 554 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "-G and -h does not mix"); 555 g_enmAction = kVBoxTpGAction_GenerateObject; 556 break; 557 103 558 case 'h': 104 RTPrintf("VirtualBox Tracepoint Generator\n" 105 "\n" 106 "Usage: %s [options]\n" 107 "\n" 108 "Options:\n", g_szProgName); 109 for (size_t i = 0; i < RT_ELEMENTS(s_aOpts); i++) 110 if ((unsigned)s_aOpts[i].iShort < 128) 111 RTPrint(" -%c,%s\n", s_aOpts[i].iShort, s_aOpts[i].pszLong); 112 else 113 RTPrint(" %s\n", s_aOpts[i].pszLong); 114 return 1; 559 if (!strcmp(GetOptState.pDef->pszLong, "--generate-header")) 560 { 561 if ( g_enmAction != kVBoxTpGAction_Nothing 562 && g_enmAction != kVBoxTpGAction_GenerateHeader) 563 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "-h and -G does not mix"); 564 g_enmAction = kVBoxTpGAction_GenerateHeader; 565 } 566 else 567 { 568 /* --help or similar */ 569 RTPrintf("VirtualBox Tracepoint Generator\n" 570 "\n" 571 "Usage: %s [options]\n" 572 "\n" 573 "Options:\n", RTProcShortName()); 574 for (size_t i = 0; i < RT_ELEMENTS(s_aOpts); i++) 575 if ((unsigned)s_aOpts[i].iShort < 128) 576 RTPrintf(" -%c,%s\n", s_aOpts[i].iShort, s_aOpts[i].pszLong); 577 else 578 RTPrintf(" %s\n", s_aOpts[i].pszLong); 579 return RTEXITCODE_SUCCESS; 580 } 581 break; 582 583 case 'o': 584 if (g_pszOutput) 585 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Output file is already set to '%s'", g_pszOutput); 586 g_pszOutput = ValueUnion.psz; 587 break; 588 589 case 's': 590 if (g_pszScript) 591 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Script file is already set to '%s'", g_pszScript); 592 g_pszScript = ValueUnion.psz; 593 break; 594 595 case 'v': 596 g_cVerbosity++; 597 break; 115 598 116 599 case 'V': … … 120 603 const char *psz = RTStrStripL(strchr(s_szRev, ' ')); 121 604 RTPrintf("r%.*s\n", strchr(psz, ' ') - psz, psz); 122 return 0;605 return RTEXITCODE_SUCCESS; 123 606 } 124 607 125 126 608 case VINF_GETOPT_NOT_OPTION: 127 if ( enmAction == kVBoxTpGAction_GenerateObject)609 if (g_enmAction == kVBoxTpGAction_GenerateObject) 128 610 break; /* object files, ignore them. */ 129 /* fall thru */ 130 611 return RTGetOptPrintError(rc, &ValueUnion); 612 613 614 /* 615 * Out options. 616 */ 617 case kVBoxTpGOpt_Assembler: 618 g_pszAssembler = ValueUnion.psz; 619 break; 620 621 case kVBoxTpGOpt_AssemblerFmtOpt: 622 g_pszAssemblerFmtOpt = ValueUnion.psz; 623 break; 624 625 case kVBoxTpGOpt_AssemblerFmtVal: 626 g_pszAssemblerFmtVal = ValueUnion.psz; 627 break; 628 629 case kVBoxTpGOpt_AssemblerOutputOpt: 630 g_pszAssemblerOutputOpt = ValueUnion.psz; 631 break; 632 633 case kVBoxTpGOpt_AssemblerOption: 634 if (g_cAssemblerOptions >= RT_ELEMENTS(g_apszAssemblerOptions)) 635 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Too many assembly options (max %u)", RT_ELEMENTS(g_apszAssemblerOptions)); 636 g_apszAssemblerOptions[g_cAssemblerOptions] = ValueUnion.psz; 637 g_cAssemblerOptions++; 638 break; 639 640 /* 641 * Errors and bugs. 642 */ 131 643 default: 644 return RTGetOptPrintError(rc, &ValueUnion); 645 } 646 } 647 648 /* 649 * Check that we've got all we need. 650 */ 651 if (g_enmAction == kVBoxTpGAction_Nothing) 652 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "No action specified (-h or -G)"); 653 if (!g_pszScript) 654 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "No script file specified (-s)"); 655 if (!g_pszOutput) 656 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "No output file specified (-o)"); 657 658 return RTEXITCODE_SUCCESS; 659 } 660 661 662 int main(int argc, char **argv) 663 { 664 int rc = RTR3InitExe(argc, &argv, 0); 665 if (RT_FAILURE(rc)) 666 return 1; 667 668 RTEXITCODE rcExit = parseArguments(argc, argv); 669 if (rcExit == RTEXITCODE_SUCCESS) 670 { 671 /* 672 * Parse the script. 673 */ 674 rc = RTStrCacheCreate(&g_hStrCache, "VBoxTpG"); 675 if (RT_SUCCESS(rc)) 676 { 677 RTListInit(&g_ProviderHead); 678 rcExit = parseScript(g_pszScript); 679 if (rcExit == RTEXITCODE_SUCCESS) 132 680 { 133 int rc2 = scmSettingsBaseHandleOpt(&pSettings->Base, rc, &ValueUnion); 134 if (RT_SUCCESS(rc2)) 135 break; 136 if (rc2 != VERR_GETOPT_UNKNOWN_OPTION) 137 return 2; 138 return RTGetOptPrintError(rc, &ValueUnion); 681 /* 682 * Take action. 683 */ 684 if (g_enmAction == kVBoxTpGAction_GenerateHeader) 685 rcExit = generateHeader(g_pszOutput); 686 else 687 rcExit = generateObject(g_pszOutput, g_pszTempAsm); 139 688 } 689 RTStrCacheDestroy(g_hStrCache); 140 690 } 141 691 } 142 692 143 144 return 0; 145 } 693 return rcExit; 694 } 695 -
trunk/src/bldprogs/scmstream.cpp
r40530 r40554 643 643 { 644 644 /** @todo this doesn't work when pStream->off != 645 * pStream->paLines[pStream->iLine-1]. pff. */645 * pStream->paLines[pStream->iLine-1].off. */ 646 646 if (!pStream->fFullyLineated) 647 647 return scmStreamGetLineInternal(pStream, pcchLine, penmEol); … … 649 649 } 650 650 651 652 /** 653 * Gets a character from the stream. 654 * 655 * @returns The next unsigned character in the stream. 656 * ~(unsigned)0 on failure. 657 * @param pStream The stream. Must be in read mode. 658 */ 659 unsigned ScmStreamGetCh(PSCMSTREAM pStream) 660 { 661 /* Check stream state. */ 662 AssertReturn(!pStream->fWriteOrRead, ~(unsigned)0); 663 if (RT_FAILURE(pStream->rc)) 664 return ~(unsigned)0; 665 if (RT_UNLIKELY(!pStream->fFullyLineated)) 666 { 667 int rc = scmStreamLineate(pStream); 668 if (RT_FAILURE(rc)) 669 return ~(unsigned)0; 670 } 671 672 /* If there isn't enough stream left, fail already. */ 673 if (RT_UNLIKELY(pStream->off >= pStream->cb)) 674 return ~(unsigned)0; 675 676 /* Read a character. */ 677 char ch = pStream->pch[pStream->off++]; 678 679 /* Advance the line indicator. */ 680 size_t iLine = pStream->iLine; 681 if (pStream->off >= pStream->paLines[iLine].off + pStream->paLines[iLine].cch + pStream->paLines[iLine].enmEol) 682 pStream->iLine++; 683 684 return (unsigned)ch; 685 } 686 687 688 /** 689 * Peeks at the next character from the stream. 690 * 691 * @returns The next unsigned character in the stream. 692 * ~(unsigned)0 on failure. 693 * @param pStream The stream. Must be in read mode. 694 */ 695 unsigned ScmStreamPeekCh(PSCMSTREAM pStream) 696 { 697 /* Check stream state. */ 698 AssertReturn(!pStream->fWriteOrRead, ~(unsigned)0); 699 if (RT_FAILURE(pStream->rc)) 700 return ~(unsigned)0; 701 if (RT_UNLIKELY(!pStream->fFullyLineated)) 702 { 703 int rc = scmStreamLineate(pStream); 704 if (RT_FAILURE(rc)) 705 return ~(unsigned)0; 706 } 707 708 /* If there isn't enough stream left, fail already. */ 709 if (RT_UNLIKELY(pStream->off >= pStream->cb)) 710 return ~(unsigned)0; 711 712 /* Peek at the next character. */ 713 char ch = pStream->pch[pStream->off++]; 714 return (unsigned)ch; 715 } 716 717 651 718 /** 652 719 * Reads @a cbToRead bytes into @a pvBuf. … … 670 737 671 738 /* If there isn't enough stream left, fail already. */ 672 if (RT_UNLIKELY(pStream->cb - pStream-> cb< cbToRead))739 if (RT_UNLIKELY(pStream->cb - pStream->off < cbToRead)) 673 740 return VERR_EOF; 674 741 … … 677 744 return ScmStreamSeekAbsolute(pStream, pStream->off + cbToRead); 678 745 } 746 679 747 680 748 /** -
trunk/src/bldprogs/scmstream.h
r40528 r40554 107 107 const char *ScmStreamGetLineByNo(PSCMSTREAM pStream, size_t iLine, size_t *pcchLine, PSCMEOL penmEol); 108 108 const char *ScmStreamGetLine(PSCMSTREAM pStream, size_t *pcchLine, PSCMEOL penmEol); 109 unsigned ScmStreamGetCh(PSCMSTREAM pStream); 110 unsigned ScmStreamPeekCh(PSCMSTREAM pStream); 109 111 int ScmStreamRead(PSCMSTREAM pStream, void *pvBuf, size_t cbToRead); 110 112 bool ScmStreamIsWhiteLine(PSCMSTREAM pStream, size_t iLine);
Note:
See TracChangeset
for help on using the changeset viewer.