Changeset 41186 in vbox
- Timestamp:
- May 7, 2012 1:42:20 PM (13 years ago)
- Location:
- trunk/src/bldprogs
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/bldprogs/Makefile.kmk
r41179 r41186 50 50 scmstream.cpp 51 51 52 BLDPROGS += VBoxCPP52 #BLDPROGS += VBoxCPP 53 53 VBoxCPP_TEMPLATE = VBoxAdvBldProg 54 54 VBoxCPP_SOURCES = \ -
trunk/src/bldprogs/VBoxCPP.cpp
r41179 r41186 1 1 /* $Id$ */ 2 2 /** @file 3 * VBox Build Tool - A mini C Preprocessor. 4 * 5 * This is not attempting to be standard compliant, just get the job done! 3 * VBox Build Tool - A mini C Preprocessor. 4 * 5 * Purpuses to which this preprocessor will be put: 6 * - Preprocessig vm.h into dtrace/lib/vm.d so we can access the VM 7 * structure (as well as substructures) from DTrace without having 8 * to handcraft it all. 9 * - Removing \#ifdefs relating to a new feature that has become 10 * stable and no longer needs \#ifdef'ing. 11 * - Pretty printing preprocessor directives. This will be used by 12 * SCM. 6 13 */ 7 14 … … 75 82 76 83 77 /** 84 /** 78 85 * A define. 79 86 */ … … 120 127 typedef VBCPPCTX *PVBCPPCTX; 121 128 129 /** 130 * Evaluation result. 131 */ 132 typedef enum VBCPPEVAL 133 { 134 kVBCppEval_Invalid = 0, 135 kVBCppEval_True, 136 kVBCppEval_False, 137 kVBCppEval_Undecided, 138 kVBCppEval_End 139 } VBCPPEVAL; 140 141 142 /** 143 * The condition kind. 144 */ 145 typedef enum VBCPPCONDKIND 146 { 147 kVBCppCondKind_Invalid = 0, 148 /** \#if expr */ 149 kVBCppCondKind_If, 150 /** \#ifdef define */ 151 kVBCppCondKind_IfDef, 152 /** \#ifndef define */ 153 kVBCppCondKind_IfNDef, 154 /** \#elif expr */ 155 kVBCppCondKind_ElIf, 156 /** The end of valid values. */ 157 kVBCppCondKind_End 158 } VBCPPCONDKIND; 159 160 161 /** 162 * Conditional stack entry. 163 */ 164 typedef struct VBCPPCOND 165 { 166 /** The next conditional on the stack. */ 167 struct VBCPPCOND *pUp; 168 /** The kind of conditional. This changes on encountering \#elif. */ 169 VBCPPCONDKIND enmKind; 170 /** Evaluation result. */ 171 VBCPPEVAL enmResult; 172 /** The evaluation result of the whole stack. */ 173 VBCPPEVAL enmStackResult; 174 175 /** Whether we've seen the last else. */ 176 bool fSeenElse; 177 /** The nesting level of this condition. */ 178 uint16_t iLevel; 179 /** The nesting level of this condition wrt the ones we keep. */ 180 uint16_t iKeepLevel; 181 182 /** The condition string. (Points within the stream buffer.) */ 183 const char *pchCond; 184 /** The condition length. */ 185 size_t cchCond; 186 } VBCPPCOND; 187 /** Pointer to a conditional stack entry. */ 188 typedef VBCPPCOND *PVBCPPCOND; 189 190 191 /** 192 * Input buffer stack entry. 193 */ 194 typedef struct VBCPPINPUT 195 { 196 /** Pointer to the next input on the stack. */ 197 struct VBCPPINPUT *pUp; 198 /** The input stream. */ 199 SCMSTREAM StrmInput; 200 /** Pointer into szName to the part which was specified. */ 201 const char *pszSpecified; 202 /** The input file name with include path. */ 203 char szName[1]; 204 } VBCPPINPUT; 205 /** Pointer to a input buffer stack entry */ 206 typedef VBCPPINPUT *PVBCPPINPUT; 207 122 208 123 209 /** … … 127 213 { 128 214 /** @name Options 129 * @{ */ 215 * @{ */ 130 216 /** The preprocessing mode. */ 131 217 VBCPPMODE enmMode; … … 143 229 const char *pszOutput; 144 230 /** @} */ 145 231 146 232 /** The define string space. */ 147 233 RTSTRSPACE StrSpace; 234 /** The string space holding explicitly undefined macros for selective 235 * preprocessing runs. */ 236 RTSTRSPACE UndefStrSpace; 148 237 /** Indicates whether a C-word might need expansion. 149 * The bitmap is indexed by C-word lead character. Bits that are set 150 * indicates that the lead character is used in a \#define that we know and 151 * should expand. */ 238 * The bitmap is indexed by C-word lead character. Bits that are set 239 * indicates that the lead character is used in a \#define that we know and 240 * should expand. */ 152 241 VBCPP_BITMAP_TYPE bmDefined[VBCPP_BITMAP_SIZE]; 153 242 /** Indicates whether a C-word might need argument expansion. 154 * The bitmap is indexed by C-word lead character. Bits that are set 155 * indicates that the lead character is used in an argument of an currently 243 * The bitmap is indexed by C-word lead character. Bits that are set 244 * indicates that the lead character is used in an argument of an currently 156 245 * expanding \#define. */ 157 246 VBCPP_BITMAP_TYPE bmArgs[VBCPP_BITMAP_SIZE]; 158 247 159 248 /** Expansion context stack. */ 160 PVBCPPCTX pStack; 161 /** The current stack depth. */ 162 uint32_t cStackDepth; 249 PVBCPPCTX pExpStack; 250 /** The current expansion stack depth. */ 251 uint32_t cExpStackDepth; 252 253 /** The current depth of the conditional stack. */ 254 uint32_t cCondStackDepth; 255 /** Conditional stack. */ 256 PVBCPPCOND pCondStack; 257 /** The current condition evaluates to kVBCppEval_False, don't output. */ 258 bool fIf0Mode; 259 163 260 /** Whether the current line could be a preprocessor line. 164 * This is set when EOL is encountered and cleared again when a 165 * non-comment-or-space character is encountered. See vbcppPreprocess. */ 261 * This is set when EOL is encountered and cleared again when a 262 * non-comment-or-space character is encountered. See vbcppPreprocess. */ 166 263 bool fMaybePreprocessorLine; 167 264 168 /** The current input stream. */ 169 PSCMSTREAM pCurStrmInput; 170 /** The input stream. */ 171 SCMSTREAM StrmInput; 265 /** The input stack depth */ 266 uint32_t cInputStackDepth; 267 /** The input buffer stack. */ 268 PVBCPPINPUT pInputStack; 269 172 270 /** The output stream. */ 173 271 SCMSTREAM StrmOutput; … … 198 296 pThis->pszOutput = NULL; 199 297 pThis->StrSpace = NULL; 200 pThis->pStack = NULL; 201 pThis->cStackDepth = 0; 298 pThis->UndefStrSpace = NULL; 299 pThis->pExpStack = NULL; 300 pThis->cExpStackDepth = 0; 301 pThis->cCondStackDepth = 0; 302 pThis->pCondStack = NULL; 303 pThis->fIf0Mode = false; 304 pThis->fMaybePreprocessorLine = true; 202 305 VBCPP_BITMAP_EMPTY(pThis->bmDefined); 203 306 VBCPP_BITMAP_EMPTY(pThis->bmArgs); 204 RT_ZERO(pThis->StrmInput); 307 pThis->cCondStackDepth = 0; 308 pThis->pInputStack = NULL; 205 309 RT_ZERO(pThis->StrmOutput); 206 310 pThis->rcExit = RTEXITCODE_SUCCESS; … … 210 314 211 315 /** 212 * Displays an error message. 213 * 316 * Displays an error message. 317 * 214 318 * @returns RTEXITCODE_FAILURE 215 319 * @param pThis The C preprocessor instance. … … 220 324 { 221 325 NOREF(pThis); 222 va_list va; 223 va_start(va, pszMsg); 224 RTMsgErrorV(pszMsg, va); 225 va_end(va); 326 if (pThis->pInputStack) 327 { 328 PSCMSTREAM pStrm = &pThis->pInputStack->StrmInput; 329 330 size_t const off = ScmStreamTell(pStrm); 331 size_t const iLine = ScmStreamTellLine(pStrm); 332 ScmStreamSeekByLine(pStrm, iLine); 333 size_t const offLine = ScmStreamTell(pStrm); 334 335 va_list va; 336 va_start(va, pszMsg); 337 RTPrintf("%s:%d:%zd: error: %N.\n", pThis->pInputStack->szName, iLine + 1, off - offLine + 1, pszMsg, va); 338 va_end(va); 339 340 size_t cchLine; 341 SCMEOL enmEof; 342 const char *pszLine = ScmStreamGetLineByNo(pStrm, iLine, &cchLine, &enmEof); 343 if (pszLine) 344 RTPrintf(" %.*s\n" 345 " %*s^\n", 346 cchLine, pszLine, off - offLine, ""); 347 348 ScmStreamSeekAbsolute(pStrm, off); 349 } 350 else 351 { 352 va_list va; 353 va_start(va, pszMsg); 354 RTMsgErrorV(pszMsg, va); 355 va_end(va); 356 } 226 357 return pThis->rcExit = RTEXITCODE_FAILURE; 227 358 } … … 229 360 230 361 /** 231 * Displays an error message. 232 * 362 * Displays an error message. 363 * 233 364 * @returns RTEXITCODE_FAILURE 234 * @param pThis The C preprocessor instance. 365 * @param pThis The C preprocessor instance. 235 366 * @param pszPos Pointer to the offending character. 236 367 * @param pszMsg The message. … … 249 380 250 381 /** 251 * Checks if the given character is a valid C identifier lead character. 252 * 382 * Checks if the given character is a valid C identifier lead character. 383 * 253 384 * @returns true / false. 254 385 * @param ch The character to inspect. … … 262 393 263 394 /** 264 * Checks if the given character is a valid C identifier character. 265 * 395 * Checks if the given character is a valid C identifier character. 396 * 266 397 * @returns true / false. 267 398 * @param ch The character to inspect. … … 276 407 277 408 /** 278 * 279 * @returns @c true if valid, @c false if not. Error message already displayed 409 * 410 * @returns @c true if valid, @c false if not. Error message already displayed 280 411 * on failure. 281 412 * @param pThis The C preprocessor instance. 282 413 * @param pchIdentifier The start of the identifier to validate. 283 * @param cchIdentifier The length of the identifier. RTSTR_MAX if not 414 * @param cchIdentifier The length of the identifier. RTSTR_MAX if not 284 415 * known. 285 416 */ … … 315 446 316 447 /** 317 * Frees a define. 318 * 448 * Frees a define. 449 * 319 450 * @returns VINF_SUCCESS (used when called by RTStrSpaceDestroy) 320 451 * @param pStr Pointer to the VBCPPDEF::Core member. … … 331 462 /** 332 463 * Removes a define. 333 * 464 * 334 465 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE + msg. 335 466 * @param pThis The C preprocessor instance. 336 * @param pszDefine The define name, no argument list or anything. 467 * @param pszDefine The define name, no argument list or anything. 337 468 * @param cchDefine The length of the name. RTSTR_MAX is ok. 338 */ 339 static RTEXITCODE vbcppRemoveDefine(PVBCPP pThis, const char *pszDefine, size_t cchDefine) 469 * @param fExplicitUndef Explicit undefinition, that is, in a selective 470 * preprocessing run it will evaluate to undefined. 471 */ 472 static RTEXITCODE vbcppDefineUndef(PVBCPP pThis, const char *pszDefine, size_t cchDefine, bool fExplicitUndef) 340 473 { 341 474 PRTSTRSPACECORE pHit = RTStrSpaceGetN(&pThis->StrSpace, pszDefine, cchDefine); … … 345 478 vbcppFreeDefine(pHit, NULL); 346 479 } 480 481 if (fExplicitUndef) 482 { 483 if (cchDefine == RTSTR_MAX) 484 cchDefine = strlen(pszDefine); 485 486 PRTSTRSPACECORE pStr = (PRTSTRSPACECORE)RTMemAlloc(sizeof(*pStr) + cchDefine + 1); 487 if (!pStr) 488 return vbcppError(pThis, "out of memory"); 489 char *pszDst = (char *)(pStr + 1); 490 pStr->pszString = pszDst; 491 memcpy(pszDst, pszDefine, cchDefine); 492 pszDst[cchDefine] = '\0'; 493 if (!RTStrSpaceInsert(&pThis->UndefStrSpace, pStr)) 494 RTMemFree(pStr); 495 } 496 347 497 return RTEXITCODE_SUCCESS; 348 498 } 349 499 350 /** 351 * Inserts a define. 352 * 500 501 /** 502 * Inserts a define. 503 * 353 504 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE + msg. 354 505 * @param pThis The C preprocessor instance. 355 506 * @param pDef The define to insert. 356 507 */ 357 static RTEXITCODE vbcpp InsertDefine(PVBCPP pThis, PVBCPPDEF pDef)508 static RTEXITCODE vbcppDefineInsert(PVBCPP pThis, PVBCPPDEF pDef) 358 509 { 359 510 if (RTStrSpaceInsert(&pThis->StrSpace, &pDef->Core)) … … 362 513 { 363 514 RTMsgWarning("Redefining '%s'\n", pDef->Core.pszString); 364 PVBCPPDEF pOld = (PVBCPPDEF)vbcpp RemoveDefine(pThis, pDef->Core.pszString, pDef->Core.cchString);515 PVBCPPDEF pOld = (PVBCPPDEF)vbcppDefineUndef(pThis, pDef->Core.pszString, pDef->Core.cchString, false); 365 516 bool fRc = RTStrSpaceInsert(&pThis->StrSpace, &pDef->Core); 366 517 Assert(fRc); Assert(pOld); … … 373 524 374 525 /** 375 * Adds a define. 376 * 526 * Adds a define. 527 * 377 528 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE + msg. 378 529 * @param pThis The C preprocessor instance. 379 530 * @param pszDefine The define name, no parameter list. 380 531 * @param cchDefine The length of the name. 381 * @param pszParams The parameter list. 382 * @param cchParams The length of the parameter list. 383 * @param pszValue The value. 532 * @param pszParams The parameter list. 533 * @param cchParams The length of the parameter list. 534 * @param pszValue The value. 384 535 * @param cchDefine The length of the value. 385 536 */ 386 static RTEXITCODE vbcpp AddDefineFn(PVBCPP pThis, const char *pszDefine, size_t cchDefine,537 static RTEXITCODE vbcppDefineAddFn(PVBCPP pThis, const char *pszDefine, size_t cchDefine, 387 538 const char *pszParams, size_t cchParams, 388 539 const char *pszValue, size_t cchValue) … … 393 544 Assert(RTStrNLen(pszValue, cchValue) == cchValue); 394 545 395 /* 546 /* 396 547 * Determin the number of arguments and how much space their names 397 548 * requires. Performing syntax validation while parsing. 398 */ 549 */ 399 550 uint32_t cchArgNames = 0; 400 551 uint32_t cArgs = 0; … … 486 637 Assert((uintptr_t)pszDst <= (uintptr_t)pDef->papszArgs); 487 638 488 return vbcpp InsertDefine(pThis, pDef);489 } 490 491 492 /** 493 * Adds a define. 494 * 639 return vbcppDefineInsert(pThis, pDef); 640 } 641 642 643 /** 644 * Adds a define. 645 * 495 646 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE + msg. 496 647 * @param pThis The C preprocessor instance. 497 * @param pszDefine The define name and optionally the argument 648 * @param pszDefine The define name and optionally the argument 498 649 * list. 499 650 * @param cchDefine The length of the name. RTSTR_MAX is ok. 500 * @param pszValue The value. 651 * @param pszValue The value. 501 652 * @param cchDefine The length of the value. RTSTR_MAX is ok. 502 653 */ 503 static RTEXITCODE vbcpp AddDefine(PVBCPP pThis, const char *pszDefine, size_t cchDefine,654 static RTEXITCODE vbcppDefineAdd(PVBCPP pThis, const char *pszDefine, size_t cchDefine, 504 655 const char *pszValue, size_t cchValue) 505 656 { … … 537 688 pszParams++; 538 689 cchParams -= 2; 539 return vbcpp AddDefineFn(pThis, pszDefine, cchDefine, pszParams, cchParams, pszValue, cchValue);690 return vbcppDefineAddFn(pThis, pszDefine, cchDefine, pszParams, cchParams, pszValue, cchValue); 540 691 } 541 692 … … 561 712 pDef->szValue[cchValue] = '\0'; 562 713 563 return vbcppInsertDefine(pThis, pDef); 714 return vbcppDefineInsert(pThis, pDef); 715 } 716 717 718 /** 719 * Checks if a define exists. 720 * 721 * @returns true or false. 722 * @param pThis The C preprocessor instance. 723 * @param pszDefine The define name and optionally the argument 724 * list. 725 * @param cchDefine The length of the name. RTSTR_MAX is ok. 726 */ 727 static bool vbcppDefineExists(PVBCPP pThis, const char *pszDefine, size_t cchDefine) 728 { 729 return cchDefine > 0 730 && VBCPP_BITMAP_IS_SET(pThis->bmDefined, *pszDefine) 731 && RTStrSpaceGetN(&pThis->StrSpace, pszDefine, cchDefine) != NULL; 564 732 } 565 733 … … 567 735 /** 568 736 * Adds an include directory. 569 * 737 * 570 738 * @returns Program exit code, with error message on failure. 571 739 * @param pThis The C preprocessor instance. … … 593 761 594 762 /** 595 * Parses the command line options. 596 * 763 * Parses the command line options. 764 * 597 765 * @returns Program exit code. Exit on non-success or if *pfExit is set. 598 766 * @param pThis The C preprocessor instance. … … 649 817 const char *pszEqual = strchr(ValueUnion.psz, '='); 650 818 if (pszEqual) 651 rcExit = vbcpp AddDefine(pThis, ValueUnion.psz, pszEqual - ValueUnion.psz, pszEqual + 1, RTSTR_MAX);819 rcExit = vbcppDefineAdd(pThis, ValueUnion.psz, pszEqual - ValueUnion.psz, pszEqual + 1, RTSTR_MAX); 652 820 else 653 rcExit = vbcpp AddDefine(pThis, ValueUnion.psz, RTSTR_MAX, "1", 1);821 rcExit = vbcppDefineAdd(pThis, ValueUnion.psz, RTSTR_MAX, "1", 1); 654 822 if (rcExit != RTEXITCODE_SUCCESS) 655 823 return rcExit; … … 664 832 665 833 case 'U': 666 rcExit = vbcpp RemoveDefine(pThis, ValueUnion.psz, RTSTR_MAX);834 rcExit = vbcppDefineUndef(pThis, ValueUnion.psz, RTSTR_MAX, true); 667 835 break; 668 836 … … 687 855 else if (!pThis->pszOutput) 688 856 pThis->pszOutput = ValueUnion.psz; 689 else 857 else 690 858 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "too many file arguments"); 691 859 break; … … 706 874 /** 707 875 * Opens the input and output streams. 708 * 876 * 709 877 * @returns Exit code. 710 878 * @param pThis The C preprocessor instance. … … 715 883 return vbcppError(pThis, "Preprocessing the standard input stream is currently not supported"); 716 884 717 int rc = ScmStreamInitForReading(&pThis->StrmInput, pThis->pszInput); 885 size_t cchName = strlen(pThis->pszInput); 886 PVBCPPINPUT pInput = (PVBCPPINPUT)RTMemAlloc(RT_OFFSETOF(VBCPPINPUT, szName[cchName + 1])); 887 if (!pInput) 888 return vbcppError(pThis, "out of memory"); 889 pInput->pUp = pThis->pInputStack; 890 pInput->pszSpecified = pInput->szName; 891 memcpy(pInput->szName, pThis->pszInput, cchName + 1); 892 pThis->pInputStack = pInput; 893 int rc = ScmStreamInitForReading(&pInput->StrmInput, pThis->pszInput); 718 894 if (RT_FAILURE(rc)) 719 895 return vbcppError(pThis, "ScmStreamInitForReading returned %Rrc when opening input file (%s)", 720 896 rc, pThis->pszInput); 721 897 722 rc = ScmStreamInitForWriting(&pThis->StrmOutput, &p This->StrmInput);898 rc = ScmStreamInitForWriting(&pThis->StrmOutput, &pInput->StrmInput); 723 899 if (RT_FAILURE(rc)) 724 900 return vbcppError(pThis, "ScmStreamInitForWriting returned %Rrc", rc); … … 730 906 731 907 /** 732 * Outputs a character. 733 * 908 * Outputs a character. 909 * 734 910 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. 735 911 * @param pThis The C preprocessor instance. … … 747 923 /** 748 924 * Outputs a string. 749 * 925 * 750 926 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. 751 927 * @param pThis The C preprocessor instance. 752 * @param pch The string. 753 * @param cch The number of characters to write. 928 * @param pch The string. 929 * @param cch The number of characters to write. 754 930 */ 755 931 static RTEXITCODE vbcppOutputWrite(PVBCPP pThis, const char *pch, size_t cch) … … 764 940 /** 765 941 * Processes a multi-line comment. 766 * 767 * Must either string the comment or keep it. If the latter, we must refrain 768 * from replacing C-words in it. 769 * 942 * 943 * Must either string the comment or keep it. If the latter, we must refrain 944 * from replacing C-words in it. 945 * 770 946 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. 771 947 * @param pThis The C preprocessor instance. … … 814 990 815 991 /** 816 * Processes a single line comment. 817 * 818 * Must either string the comment or keep it. If the latter, we must refrain 819 * from replacing C-words in it. 820 * 992 * Processes a single line comment. 993 * 994 * Must either string the comment or keep it. If the latter, we must refrain 995 * from replacing C-words in it. 996 * 821 997 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. 822 998 * @param pThis The C preprocessor instance. … … 852 1028 853 1029 /** 854 * Processes a double quoted string. 855 * 856 * Must not replace any C-words in strings. 857 * 1030 * Processes a double quoted string. 1031 * 1032 * Must not replace any C-words in strings. 1033 * 858 1034 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. 859 1035 * @param pThis The C preprocessor instance. … … 882 1058 break; 883 1059 fEscaped = !fEscaped && ch == '\\'; 884 } 1060 } 885 1061 } 886 1062 return rcExit; … … 890 1066 /** 891 1067 * Processes a single quoted litteral. 892 * 893 * Must not replace any C-words in strings. 894 * 1068 * 1069 * Must not replace any C-words in strings. 1070 * 895 1071 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. 896 1072 * @param pThis The C preprocessor instance. … … 919 1095 break; 920 1096 fEscaped = !fEscaped && ch == '\\'; 921 } 1097 } 922 1098 } 923 1099 return rcExit; … … 926 1102 927 1103 /** 928 * Processes a preprocessor directive. 929 * 1104 * Skips white spaces, including escaped new-lines. 1105 * 1106 * @param pStrmInput The input stream. 1107 */ 1108 static void vbcppProcessSkipWhiteAndEscapedEol(PSCMSTREAM pStrmInput) 1109 { 1110 unsigned chPrev = ~(unsigned)0; 1111 unsigned ch; 1112 while ((ch = ScmStreamPeekCh(pStrmInput)) != ~(unsigned)0) 1113 { 1114 if (ch == '\r' || ch == '\n') 1115 { 1116 if (chPrev != '\\') 1117 break; 1118 chPrev = ch; 1119 ScmStreamSeekByLine(pStrmInput, ScmStreamTellLine(pStrmInput) + 1); 1120 } 1121 else if (RT_C_IS_SPACE(ch)) 1122 { 1123 ch = chPrev; 1124 ch = ScmStreamGetCh(pStrmInput); 1125 Assert(ch == chPrev); 1126 } 1127 else 1128 break; 1129 } 1130 } 1131 1132 1133 /** 1134 * Skips white spaces, escaped new-lines and multi line comments. 1135 * 1136 * @param pThis The C preprocessor instance. 1137 * @param pStrmInput The input stream. 1138 */ 1139 static RTEXITCODE vbcppProcessSkipWhiteEscapedEolAndComments(PVBCPP pThis, PSCMSTREAM pStrmInput) 1140 { 1141 unsigned chPrev = ~(unsigned)0; 1142 unsigned ch; 1143 while ((ch = ScmStreamPeekCh(pStrmInput)) != ~(unsigned)0) 1144 { 1145 if (!RT_C_IS_SPACE(ch)) 1146 { 1147 /* Multi-line Comment? */ 1148 if (ch != '/') 1149 break; /* most definitely, not. */ 1150 1151 size_t offSaved = ScmStreamTell(pStrmInput); 1152 ScmStreamGetCh(pStrmInput); 1153 if (ScmStreamPeekCh(pStrmInput) != '*') 1154 { 1155 ScmStreamSeekAbsolute(pStrmInput, offSaved); 1156 break; /* no */ 1157 } 1158 1159 /* Skip to the end of the comment. */ 1160 while ((ch = ScmStreamGetCh(pStrmInput)) != ~(unsigned)0) 1161 { 1162 if (ch == '*') 1163 { 1164 ch = ScmStreamGetCh(pStrmInput); 1165 if (ch == '/') 1166 break; 1167 if (ch == ~(unsigned)0) 1168 break; 1169 } 1170 } 1171 if (ch == ~(unsigned)0) 1172 return vbcppError(pThis, "unterminated multi-line comment"); 1173 chPrev = '/'; 1174 } 1175 /* New line (also matched by RT_C_IS_SPACE). */ 1176 else if (ch == '\r' || ch == '\n') 1177 { 1178 /* Stop if not escaped. */ 1179 if (chPrev != '\\') 1180 break; 1181 chPrev = ch; 1182 ScmStreamSeekByLine(pStrmInput, ScmStreamTellLine(pStrmInput) + 1); 1183 } 1184 /* Real space char. */ 1185 else 1186 { 1187 chPrev = ch; 1188 ch = ScmStreamGetCh(pStrmInput); 1189 Assert(ch == chPrev); 1190 } 1191 } 1192 return RTEXITCODE_SUCCESS; 1193 } 1194 1195 1196 /** 1197 * Skips white spaces, escaped new-lines, and multi line comments, then checking 1198 * that we're at the end of a line. 1199 * 1200 * @param pThis The C preprocessor instance. 1201 * @param pStrmInput The input stream. 1202 */ 1203 static RTEXITCODE vbcppProcessSkipWhiteEscapedEolAndCommentsCheckEol(PVBCPP pThis, PSCMSTREAM pStrmInput) 1204 { 1205 RTEXITCODE rcExit = vbcppProcessSkipWhiteEscapedEolAndComments(pThis, pStrmInput); 1206 if (rcExit == RTEXITCODE_SUCCESS) 1207 { 1208 unsigned ch = ScmStreamPeekCh(pStrmInput); 1209 if ( ch != ~(unsigned)0 1210 && ch != '\r' 1211 && ch != '\n') 1212 rcExit = vbcppError(pThis, "Did not expected anything more on this line"); 1213 } 1214 return rcExit; 1215 } 1216 1217 1218 /** 1219 * Skips white spaces. 1220 * 1221 * @param pStrmInput The input stream. 1222 */ 1223 static void vbcppProcessSkipWhite(PSCMSTREAM pStrmInput) 1224 { 1225 unsigned ch; 1226 while ((ch = ScmStreamPeekCh(pStrmInput)) != ~(unsigned)0) 1227 { 1228 if (!RT_C_IS_SPACE(ch) || ch == '\r' || ch == '\n') 1229 break; 1230 unsigned chCheck = ScmStreamGetCh(pStrmInput); 1231 AssertBreak(chCheck == ch); 1232 } 1233 } 1234 1235 1236 1237 /** 1238 * Processes a abbreviated line number directive. 1239 * 930 1240 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. 931 1241 * @param pThis The C preprocessor instance. 932 1242 * @param pStrmInput The input stream. 1243 * @param offStart The stream position where the directive 1244 * started (for pass thru). 1245 */ 1246 static RTEXITCODE vbcppProcessInclude(PVBCPP pThis, PSCMSTREAM pStrmInput, size_t offStart) 1247 { 1248 /* 1249 * Parse it. 1250 */ 1251 RTEXITCODE rcExit = vbcppProcessSkipWhiteEscapedEolAndComments(pThis, pStrmInput); 1252 if (rcExit == RTEXITCODE_SUCCESS) 1253 { 1254 size_t cchFilename; 1255 const char *pchFilename; 1256 1257 unsigned ch = ScmStreamPeekCh(pStrmInput); 1258 unsigned chType = ch; 1259 if (ch == '"' || ch == '<') 1260 { 1261 ScmStreamGetCh(pStrmInput); 1262 pchFilename = ScmStreamGetCur(pStrmInput); 1263 unsigned chPrev = ch; 1264 while ( (ch = ScmStreamGetCh(pStrmInput)) != ~(unsigned)0 1265 && ch != chType) 1266 { 1267 if (ch == '\r' || ch == '\n') 1268 { 1269 rcExit = vbcppError(pThis, "Multi-line include file specfications are not supported"); 1270 break; 1271 } 1272 } 1273 1274 if (rcExit != RTEXITCODE_SUCCESS) 1275 { 1276 if (ch != ~(unsigned)0) 1277 cchFilename = ScmStreamGetCur(pStrmInput) - pchFilename; 1278 else 1279 rcExit = vbcppError(pThis, "Expected '%c'", chType); 1280 } 1281 } 1282 else if (vbcppIsCIdentifierLeadChar(ch)) 1283 { 1284 //size_t cchDefine; 1285 //const char *pchDefine = ScmStreamCGetWord(pStrmInput, &cchDefine); 1286 rcExit = vbcppError(pThis, "Including via a define is not implemented yet") 1287 } 1288 else 1289 rcExit = vbcppError(pThis, "Malformed include directive") 1290 1291 /* 1292 * Take down the location of the next non-white space, if we need to 1293 * pass thru the directive further down. Then skip to the end of the 1294 * line. 1295 */ 1296 if (rcExit != RTEXITCODE_SUCCESS) 1297 vbcppProcessSkipWhite(pStrmInput); 1298 size_t const offIncEnd = ScmStreamTell(pStrmInput); 1299 if (rcExit != RTEXITCODE_SUCCESS) 1300 rcExit = vbcppProcessSkipWhiteEscapedEolAndCommentsCheckEol(pThis, pStrmInput); 1301 1302 if (rcExit != RTEXITCODE_SUCCESS) 1303 { 1304 /* 1305 * Execute it. 1306 */ 1307 if (pThis->enmMode < kVBCppMode_Selective) 1308 { 1309 /** @todo Search for the include file and push it onto the input stack. 1310 * Not difficult, just unnecessary rigth now. */ 1311 rcExit = vbcppError(pThis, "Includes are fully implemented"); 1312 } 1313 else if (pThis->enmMode != kVBCppMode_SelectiveD) 1314 { 1315 /** @todo put this in a function or smth. */ 1316 ssize_t cch = ScmStreamPrintf(&pThis->StrmOutput, "#%*sinclude %.*s", 1317 pCond->iKeepLevel - 1, "", pchCondition); 1318 if (cch < 0) 1319 return vbcppError(pThis, "Output error %Rrc", (int)cch); 1320 if (offIncEnd < ScmStreamTell(pStrmInput)) 1321 { 1322 /** @todo */ 1323 ScmStreamPrintf(&pThis->StrmOutput, "/* missing comment - fixme */"); 1324 } 1325 1326 } 1327 /* else: strip it */ 1328 } 1329 } 1330 return rcExit; 1331 } 1332 1333 1334 /** 1335 * Processes a abbreviated line number directive. 1336 * 1337 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. 1338 * @param pThis The C preprocessor instance. 1339 * @param pStrmInput The input stream. 1340 * @param offStart The stream position where the directive 1341 * started (for pass thru). 1342 */ 1343 static RTEXITCODE vbcppProcessDefine(PVBCPP pThis, PSCMSTREAM pStrmInput, size_t offStart) 1344 { 1345 return vbcppError(pThis, "Not implemented %s", __FUNCTION__); 1346 } 1347 1348 1349 /** 1350 * Processes a abbreviated line number directive. 1351 * 1352 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. 1353 * @param pThis The C preprocessor instance. 1354 * @param pStrmInput The input stream. 1355 * @param offStart The stream position where the directive 1356 * started (for pass thru). 1357 */ 1358 static RTEXITCODE vbcppProcessUndef(PVBCPP pThis, PSCMSTREAM pStrmInput, size_t offStart) 1359 { 1360 return vbcppError(pThis, "Not implemented %s", __FUNCTION__); 1361 } 1362 1363 1364 static VBCPPEVAL vbcppCondCombine(VBCPPEVAL enmEvalPush, VBCPPEVAL enmEvalTop) 1365 { 1366 if (enmEvalTop == kVBCppEval_False) 1367 return kVBCppEval_False; 1368 return enmEvalPush; 1369 } 1370 1371 1372 static RTEXITCODE vbcppCondPush(PVBCPP pThis, PSCMSTREAM pStrmInput, size_t offStart, 1373 VBCPPCONDKIND enmKind, VBCPPEVAL enmResult, 1374 const char *pchCondition, size_t cchCondition) 1375 { 1376 if (pThis->cCondStackDepth >= _64K) 1377 return vbcppError(pThis, "Too many nested #if/#ifdef/#ifndef statements"); 1378 1379 /* 1380 * Allocate a new entry and push it. 1381 */ 1382 PVBCPPCOND pCond = (PVBCPPCOND)RTMemAlloc(sizeof(*pCond)); 1383 if (!pCond) 1384 return vbcppError(pThis, "out of memory"); 1385 1386 PVBCPPCOND pUp = pThis->pCondStack; 1387 pCond->enmKind = enmKind; 1388 pCond->enmResult = enmResult; 1389 pCond->enmStackResult = pUp ? vbcppCondCombine(enmResult, pUp->enmStackResult) : enmResult; 1390 pCond->fSeenElse = false; 1391 pCond->iLevel = pThis->cCondStackDepth; 1392 pCond->iKeepLevel = (pUp ? pUp->iKeepLevel : 0) + enmResult == kVBCppEval_Undecided; 1393 pCond->pchCond = pchCondition; 1394 pCond->cchCond = cchCondition; 1395 1396 pCond->pUp = pThis->pCondStack; 1397 pThis->pCondStack = pCond; 1398 pThis->fIf0Mode = pCond->enmStackResult == kVBCppEval_False; 1399 1400 /* 1401 * Do pass thru. 1402 */ 1403 if ( !pThis->fIf0Mode 1404 && enmResult == kVBCppEval_Undecided) 1405 { 1406 /** @todo this is stripping comments of \#ifdef and \#ifndef atm. */ 1407 const char *pszDirective; 1408 switch (enmKind) 1409 { 1410 case kVBCppCondKind_If: pszDirective = "if"; break; 1411 case kVBCppCondKind_IfDef: pszDirective = "ifdef"; break; 1412 case kVBCppCondKind_IfNDef: pszDirective = "ifndef"; break; 1413 case kVBCppCondKind_ElIf: pszDirective = "elif"; break; 1414 default: AssertFailedReturn(RTEXITCODE_FAILURE); 1415 } 1416 ssize_t cch = ScmStreamPrintf(&pThis->StrmOutput, "#%*s%s %.*s", 1417 pCond->iKeepLevel - 1, "", pszDirective, cchCondition, pchCondition); 1418 if (cch < 0) 1419 return vbcppError(pThis, "Output error %Rrc", (int)cch); 1420 } 1421 1422 return RTEXITCODE_SUCCESS; 1423 } 1424 1425 1426 /** 1427 * Processes a abbreviated line number directive. 1428 * 1429 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. 1430 * @param pThis The C preprocessor instance. 1431 * @param pStrmInput The input stream. 1432 * @param offStart The stream position where the directive 1433 * started (for pass thru). 1434 */ 1435 static RTEXITCODE vbcppProcessIf(PVBCPP pThis, PSCMSTREAM pStrmInput, size_t offStart) 1436 { 1437 return vbcppError(pThis, "Not implemented %s", __FUNCTION__); 1438 } 1439 1440 1441 /** 1442 * Processes a abbreviated line number directive. 1443 * 1444 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. 1445 * @param pThis The C preprocessor instance. 1446 * @param pStrmInput The input stream. 1447 * @param offStart The stream position where the directive 1448 * started (for pass thru). 1449 */ 1450 static RTEXITCODE vbcppProcessIfDef(PVBCPP pThis, PSCMSTREAM pStrmInput, size_t offStart) 1451 { 1452 /* 1453 * Parse it. 1454 */ 1455 RTEXITCODE rcExit = vbcppProcessSkipWhiteEscapedEolAndComments(pThis, pStrmInput); 1456 if (rcExit == RTEXITCODE_SUCCESS) 1457 { 1458 size_t cchDefine; 1459 const char *pchDefine = ScmStreamCGetWord(pStrmInput, &cchDefine); 1460 if (pchDefine) 1461 { 1462 rcExit = vbcppProcessSkipWhiteEscapedEolAndCommentsCheckEol(pThis, pStrmInput); 1463 if (rcExit == RTEXITCODE_SUCCESS) 1464 { 1465 /* 1466 * Evaluate it. 1467 */ 1468 VBCPPEVAL enmEval; 1469 if (vbcppDefineExists(pThis, pchDefine, cchDefine)) 1470 enmEval = kVBCppEval_True; 1471 else if ( pThis->enmMode < kVBCppMode_Selective 1472 || RTStrSpaceGetN(&pThis->UndefStrSpace, pchDefine, cchDefine) != NULL) 1473 enmEval = kVBCppEval_False; 1474 else 1475 enmEval = kVBCppEval_Undecided; 1476 rcExit = vbcppCondPush(pThis, pStrmInput, offStart, kVBCppCondKind_IfDef, enmEval, 1477 pchDefine, cchDefine); 1478 } 1479 } 1480 else 1481 rcExit = vbcppError(pThis, "Malformed #ifdef"); 1482 } 1483 return rcExit; 1484 } 1485 1486 1487 /** 1488 * Processes a abbreviated line number directive. 1489 * 1490 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. 1491 * @param pThis The C preprocessor instance. 1492 * @param pStrmInput The input stream. 1493 * @param offStart The stream position where the directive 1494 * started (for pass thru). 1495 */ 1496 static RTEXITCODE vbcppProcessIfNDef(PVBCPP pThis, PSCMSTREAM pStrmInput, size_t offStart) 1497 { 1498 /* 1499 * Parse it. 1500 */ 1501 RTEXITCODE rcExit = vbcppProcessSkipWhiteEscapedEolAndComments(pThis, pStrmInput); 1502 if (rcExit == RTEXITCODE_SUCCESS) 1503 { 1504 size_t cchDefine; 1505 const char *pchDefine = ScmStreamCGetWord(pStrmInput, &cchDefine); 1506 if (pchDefine) 1507 { 1508 rcExit = vbcppProcessSkipWhiteEscapedEolAndCommentsCheckEol(pThis, pStrmInput); 1509 if (rcExit == RTEXITCODE_SUCCESS) 1510 { 1511 /* 1512 * Evaluate it. 1513 */ 1514 VBCPPEVAL enmEval; 1515 if (vbcppDefineExists(pThis, pchDefine, cchDefine)) 1516 enmEval = kVBCppEval_False; 1517 else if ( pThis->enmMode < kVBCppMode_Selective 1518 || RTStrSpaceGetN(&pThis->UndefStrSpace, pchDefine, cchDefine) != NULL) 1519 enmEval = kVBCppEval_True; 1520 else 1521 enmEval = kVBCppEval_Undecided; 1522 rcExit = vbcppCondPush(pThis, pStrmInput, offStart, kVBCppCondKind_IfNDef, enmEval, 1523 pchDefine, cchDefine); 1524 } 1525 } 1526 else 1527 rcExit = vbcppError(pThis, "Malformed #ifdef"); 1528 } 1529 return rcExit; 1530 } 1531 1532 1533 /** 1534 * Processes a abbreviated line number directive. 1535 * 1536 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. 1537 * @param pThis The C preprocessor instance. 1538 * @param pStrmInput The input stream. 1539 * @param offStart The stream position where the directive 1540 * started (for pass thru). 1541 */ 1542 static RTEXITCODE vbcppProcessElse(PVBCPP pThis, PSCMSTREAM pStrmInput, size_t offStart) 1543 { 1544 return vbcppError(pThis, "Not implemented %s", __FUNCTION__); 1545 } 1546 1547 1548 /** 1549 * Processes a abbreviated line number directive. 1550 * 1551 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. 1552 * @param pThis The C preprocessor instance. 1553 * @param pStrmInput The input stream. 1554 * @param offStart The stream position where the directive 1555 * started (for pass thru). 1556 */ 1557 static RTEXITCODE vbcppProcessEndif(PVBCPP pThis, PSCMSTREAM pStrmInput, size_t offStart) 1558 { 1559 return vbcppError(pThis, "Not implemented %s", __FUNCTION__); 1560 } 1561 1562 1563 /** 1564 * Processes a abbreviated line number directive. 1565 * 1566 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. 1567 * @param pThis The C preprocessor instance. 1568 * @param pStrmInput The input stream. 1569 * @param offStart The stream position where the directive 1570 * started (for pass thru). 1571 */ 1572 static RTEXITCODE vbcppProcessPragma(PVBCPP pThis, PSCMSTREAM pStrmInput, size_t offStart) 1573 { 1574 return vbcppError(pThis, "Not implemented %s", __FUNCTION__); 1575 } 1576 1577 1578 /** 1579 * Processes a abbreviated line number directive. 1580 * 1581 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. 1582 * @param pThis The C preprocessor instance. 1583 * @param pStrmInput The input stream. 1584 * @param offStart The stream position where the directive 1585 * started (for pass thru). 1586 */ 1587 static RTEXITCODE vbcppProcessLineNo(PVBCPP pThis, PSCMSTREAM pStrmInput, size_t offStart) 1588 { 1589 return vbcppError(pThis, "Not implemented %s", __FUNCTION__); 1590 } 1591 1592 1593 /** 1594 * Processes a abbreviated line number directive. 1595 * 1596 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. 1597 * @param pThis The C preprocessor instance. 1598 * @param pStrmInput The input stream. 1599 * @param offStart The stream position where the directive 1600 * started (for pass thru). 1601 */ 1602 static RTEXITCODE vbcppProcessLineNoShort(PVBCPP pThis, PSCMSTREAM pStrmInput, size_t offStart) 1603 { 1604 return vbcppError(pThis, "Not implemented %s", __FUNCTION__); 1605 } 1606 1607 1608 /** 1609 * Handles a preprocessor directive. 1610 * 1611 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. 1612 * @param pThis The C preprocessor instance. 1613 * @param pStrmInput The input stream. 933 1614 */ 934 1615 static RTEXITCODE vbcppProcessDirective(PVBCPP pThis, PSCMSTREAM pStrmInput) 935 1616 { 936 #if 0 937 size_t const offStart = ScmStreamTell(pStrmInput); 938 939 /* 940 * Skip spaces. 1617 /* 1618 * Get the directive and do a string switch on it. 941 1619 */ 942 unsigned chPrev = ~(unsigned)0; 943 unsigned ch; 944 while ((ch = ScmStreamGetCh(pStrmInput)) != ~(unsigned)0) 945 { 946 if (!RT_C_IS_SPACE(ch)) 947 { 948 if () 949 { 950 } 951 } 952 ch = chPrev; 953 } 954 #endif 955 return vbcppError(pThis, "Not implemented"); 1620 RTEXITCODE rcExit = vbcppProcessSkipWhiteEscapedEolAndComments(pThis, pStrmInput); 1621 if (rcExit != RTEXITCODE_SUCCESS) 1622 return rcExit; 1623 size_t cchDirective; 1624 const char *pchDirective = ScmStreamCGetWord(pStrmInput, &cchDirective); 1625 if (pchDirective) 1626 { 1627 size_t const offStart = ScmStreamTell(pStrmInput); 1628 #define IS_DIRECTIVE(a_sz) ( sizeof(a_sz) - 1 == cchDirective && strncmp(pchDirective, a_sz, sizeof(a_sz) - 1) == 0) 1629 if (IS_DIRECTIVE("if")) 1630 rcExit = vbcppProcessIf(pThis, pStrmInput, offStart); 1631 else if (IS_DIRECTIVE("ifdef")) 1632 rcExit = vbcppProcessIfDef(pThis, pStrmInput, offStart); 1633 else if (IS_DIRECTIVE("ifndef")) 1634 rcExit = vbcppProcessIfNDef(pThis, pStrmInput, offStart); 1635 else if (IS_DIRECTIVE("else")) 1636 rcExit = vbcppProcessElse(pThis, pStrmInput, offStart); 1637 else if (IS_DIRECTIVE("endif")) 1638 rcExit = vbcppProcessEndif(pThis, pStrmInput, offStart); 1639 else if (!pThis->fIf0Mode) 1640 { 1641 if (IS_DIRECTIVE("include")) 1642 rcExit = vbcppProcessInclude(pThis, pStrmInput, offStart); 1643 else if (IS_DIRECTIVE("define")) 1644 rcExit = vbcppProcessDefine(pThis, pStrmInput, offStart); 1645 else if (IS_DIRECTIVE("undef")) 1646 rcExit = vbcppProcessUndef(pThis, pStrmInput, offStart); 1647 else if (IS_DIRECTIVE("pragma")) 1648 rcExit = vbcppProcessPragma(pThis, pStrmInput, offStart); 1649 else if (IS_DIRECTIVE("line")) 1650 rcExit = vbcppProcessLineNo(pThis, pStrmInput, offStart); 1651 else 1652 rcExit = vbcppError(pThis, "Unknown preprocessor directive '#%.*s'", cchDirective, pchDirective); 1653 } 1654 #undef IS_DIRECTIVE 1655 } 1656 else if (!pThis->fIf0Mode) 1657 { 1658 /* Could it be a # <num> "file" directive? */ 1659 unsigned ch = ScmStreamPeekCh(pStrmInput); 1660 if (RT_C_IS_DIGIT(ch)) 1661 rcExit = vbcppProcessLineNoShort(pThis, pStrmInput); 1662 else 1663 rcExit = vbcppError(pThis, "Malformed preprocessor directive"); 1664 } 1665 return rcExit; 956 1666 } 957 1667 … … 959 1669 /** 960 1670 * Processes a C word, possibly replacing it with a definition. 961 * 1671 * 962 1672 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. 963 1673 * @param pThis The C preprocessor instance. … … 974 1684 /** 975 1685 * Does the actually preprocessing of the input file. 976 * 1686 * 977 1687 * @returns Exit code. 978 * @param pThis The C preprocessor instance. 979 * @param pStrmInput The input stream. 980 */ 981 static RTEXITCODE vbcppPreprocess(PVBCPP pThis, PSCMSTREAM pStrmInput) 982 { 983 /* 984 * Push. 1688 * @param pThis The C preprocessor instance. 1689 */ 1690 static RTEXITCODE vbcppPreprocess(PVBCPP pThis) 1691 { 1692 RTEXITCODE rcExit = RTEXITCODE_SUCCESS; 1693 1694 /* 1695 * Parse. 985 1696 */ 986 PSCMSTREAM pStrmInputOld = pThis->pCurStrmInput; 987 pThis->pCurStrmInput = pStrmInput; 988 pThis->fMaybePreprocessorLine = true; 989 990 /* 991 * Parse. 992 */ 993 RTEXITCODE rcExit = RTEXITCODE_SUCCESS; 994 unsigned ch; 995 while ((ch = ScmStreamGetCh(pStrmInput)) != ~(unsigned)0) 996 { 997 if (ch == '/') 998 { 999 ch = ScmStreamPeekCh(pStrmInput); 1000 if (ch == '*') 1001 rcExit = vbcppProcessMultiLineComment(pThis, pStrmInput); 1002 else if (ch == '/') 1003 rcExit = vbcppProcessOneLineComment(pThis, pStrmInput); 1697 while (pThis->pInputStack) 1698 { 1699 pThis->fMaybePreprocessorLine = true; 1700 1701 PSCMSTREAM pStrmInput = &pThis->pInputStack->StrmInput; 1702 unsigned ch; 1703 while ((ch = ScmStreamGetCh(pStrmInput)) != ~(unsigned)0) 1704 { 1705 if (ch == '/') 1706 { 1707 ch = ScmStreamPeekCh(pStrmInput); 1708 if (ch == '*') 1709 rcExit = vbcppProcessMultiLineComment(pThis, pStrmInput); 1710 else if (ch == '/') 1711 rcExit = vbcppProcessOneLineComment(pThis, pStrmInput); 1712 else 1713 { 1714 pThis->fMaybePreprocessorLine = false; 1715 if (!pThis->fIf0Mode) 1716 rcExit = vbcppOutputCh(pThis, '/'); 1717 } 1718 } 1719 else if (ch == '#' && pThis->fMaybePreprocessorLine) 1720 { 1721 rcExit = vbcppProcessDirective(pThis, pStrmInput); 1722 pStrmInput = &pThis->pInputStack->StrmInput; 1723 } 1724 else if (ch == '\r' || ch == '\n') 1725 { 1726 pThis->fMaybePreprocessorLine = true; 1727 rcExit = vbcppOutputCh(pThis, ch); 1728 } 1729 else if (RT_C_IS_SPACE(ch)) 1730 { 1731 if (!pThis->fIf0Mode) 1732 rcExit = vbcppOutputCh(pThis, ch); 1733 } 1004 1734 else 1005 1735 { 1006 1736 pThis->fMaybePreprocessorLine = false; 1007 rcExit = vbcppOutputCh(pThis, '/'); 1008 } 1009 } 1010 else if (ch == '#' && pThis->fMaybePreprocessorLine) 1011 rcExit = vbcppProcessDirective(pThis, pStrmInput); 1012 else if (ch == '\r' || ch == '\n') 1013 { 1014 pThis->fMaybePreprocessorLine = true; 1015 rcExit = vbcppOutputCh(pThis, ch); 1016 } 1017 else if (RT_C_IS_SPACE(ch)) 1018 rcExit = vbcppOutputCh(pThis, ch); 1019 else 1020 { 1021 pThis->fMaybePreprocessorLine = false; 1022 if (ch == '"') 1023 rcExit = vbcppProcessDoubleQuotedString(pThis, pStrmInput); 1024 else if (ch == '\'') 1025 rcExit = vbcppProcessSingledQuotedString(pThis, pStrmInput); 1026 else if (vbcppIsCIdentifierLeadChar(ch)) 1027 rcExit = vbcppProcessCWord(pThis, pStrmInput, ch); 1028 else 1029 rcExit = vbcppOutputCh(pThis, ch); 1030 } 1737 if (!pThis->fIf0Mode) 1738 { 1739 if (ch == '"') 1740 rcExit = vbcppProcessDoubleQuotedString(pThis, pStrmInput); 1741 else if (ch == '\'') 1742 rcExit = vbcppProcessSingledQuotedString(pThis, pStrmInput); 1743 else if (vbcppIsCIdentifierLeadChar(ch)) 1744 rcExit = vbcppProcessCWord(pThis, pStrmInput, ch); 1745 else 1746 rcExit = vbcppOutputCh(pThis, ch); 1747 } 1748 } 1749 if (rcExit != RTEXITCODE_SUCCESS) 1750 break; 1751 } 1752 1753 /* 1754 * Check for errors. 1755 */ 1031 1756 if (rcExit != RTEXITCODE_SUCCESS) 1032 1757 break; 1033 } 1034 1035 /* 1036 * Pop. 1037 */ 1038 pThis->pCurStrmInput = pStrmInputOld; 1039 pThis->fMaybePreprocessorLine = true; 1758 1759 /* 1760 * Pop the input stack. 1761 */ 1762 PVBCPPINPUT pPopped = pThis->pInputStack; 1763 pThis->pInputStack = pPopped->pUp; 1764 RTMemFree(pPopped); 1765 } 1766 1040 1767 return rcExit; 1041 1768 } … … 1043 1770 1044 1771 /** 1045 * Terminates the preprocessor. 1046 * 1047 * This may return failure if an error was delayed. 1048 * 1772 * Terminates the preprocessor. 1773 * 1774 * This may return failure if an error was delayed. 1775 * 1049 1776 * @returns Exit code. 1050 1777 * @param pThis The C preprocessor instance. … … 1074 1801 * Cleanup. 1075 1802 */ 1076 ScmStreamDelete(&pThis->StrmInput); 1803 while (pThis->pInputStack) 1804 { 1805 ScmStreamDelete(&pThis->pInputStack->StrmInput); 1806 void *pvFree = pThis->pInputStack; 1807 pThis->pInputStack = pThis->pInputStack->pUp; 1808 RTMemFree(pvFree); 1809 } 1810 1077 1811 ScmStreamDelete(&pThis->StrmOutput); 1078 1812 … … 1108 1842 rcExit = vbcppOpenStreams(&This); 1109 1843 if (rcExit == RTEXITCODE_SUCCESS) 1110 rcExit = vbcppPreprocess(&This , &This.StrmInput);1844 rcExit = vbcppPreprocess(&This); 1111 1845 } 1112 1846 -
trunk/src/bldprogs/VBoxTpG.cpp
r41176 r41186 369 369 ScmStreamDelete(&Strm); 370 370 return rcExit; 371 }372 373 374 /**375 * Formats a string and writes it to the SCM stream.376 *377 * @returns The number of bytes written (>= 0). Negative value are IPRT error378 * status codes.379 * @param pStream The stream to write to.380 * @param pszFormat The format string.381 * @param va The arguments to format.382 */383 static ssize_t ScmStreamPrintfV(PSCMSTREAM pStream, const char *pszFormat, va_list va)384 {385 char *psz;386 ssize_t cch = RTStrAPrintfV(&psz, pszFormat, va);387 if (cch)388 {389 int rc = ScmStreamWrite(pStream, psz, cch);390 RTStrFree(psz);391 if (RT_FAILURE(rc))392 cch = rc;393 }394 return cch;395 }396 397 398 /**399 * Formats a string and writes it to the SCM stream.400 *401 * @returns The number of bytes written (>= 0). Negative value are IPRT error402 * status codes.403 * @param pStream The stream to write to.404 * @param pszFormat The format string.405 * @param ... The arguments to format.406 */407 static ssize_t ScmStreamPrintf(PSCMSTREAM pStream, const char *pszFormat, ...)408 {409 va_list va;410 va_start(va, pszFormat);411 ssize_t cch = ScmStreamPrintfV(pStream, pszFormat, va);412 va_end(va);413 return cch;414 371 } 415 372 … … 1077 1034 } 1078 1035 1079 /**1080 * If the given C word is at off - 1, return @c true and skip beyond it,1081 * otherwise return @c false.1082 *1083 * @retval true if the given C-word is at the current position minus one char.1084 * The stream position changes.1085 * @retval false if not. The stream position is unchanged.1086 *1087 * @param pStream The stream.1088 * @param cchWord The length of the word.1089 * @param pszWord The word.1090 */1091 bool ScmStreamCMatchingWordM1(PSCMSTREAM pStream, const char *pszWord, size_t cchWord)1092 {1093 /* Check stream state. */1094 AssertReturn(!pStream->fWriteOrRead, false);1095 AssertReturn(RT_SUCCESS(pStream->rc), false);1096 AssertReturn(pStream->fFullyLineated, false);1097 1098 /* Sufficient chars left on the line? */1099 size_t const iLine = pStream->iLine;1100 AssertReturn(pStream->off > pStream->paLines[iLine].off, false);1101 size_t const cchLeft = pStream->paLines[iLine].cch + pStream->paLines[iLine].off - (pStream->off - 1);1102 if (cchWord > cchLeft)1103 return false;1104 1105 /* Do they match? */1106 const char *psz = &pStream->pch[pStream->off - 1];1107 if (memcmp(psz, pszWord, cchWord))1108 return false;1109 1110 /* Is it the end of a C word? */1111 if (cchWord < cchLeft)1112 {1113 psz += cchWord;1114 if (RT_C_IS_ALNUM(*psz) || *psz == '_')1115 return false;1116 }1117 1118 /* Skip ahead. */1119 pStream->off += cchWord - 1;1120 return true;1121 }1122 1123 /**1124 * Get's the C word starting at the current position.1125 *1126 * @returns Pointer to the word on success and the stream position advanced to1127 * the end of it.1128 * NULL on failure, stream position normally unchanged.1129 * @param pStream The stream to get the C word from.1130 * @param pcchWord Where to return the word length.1131 */1132 const char *ScmStreamCGetWord(PSCMSTREAM pStream, size_t *pcchWord)1133 {1134 /* Check stream state. */1135 AssertReturn(!pStream->fWriteOrRead, NULL);1136 AssertReturn(RT_SUCCESS(pStream->rc), NULL);1137 AssertReturn(pStream->fFullyLineated, NULL);1138 1139 /* Get the number of chars left on the line and locate the current char. */1140 size_t const iLine = pStream->iLine;1141 size_t const cchLeft = pStream->paLines[iLine].cch + pStream->paLines[iLine].off - pStream->off;1142 const char *psz = &pStream->pch[pStream->off];1143 1144 /* Is it a leading C character. */1145 if (!RT_C_IS_ALPHA(*psz) && *psz == '_')1146 return NULL;1147 1148 /* Find the end of the word. */1149 char ch;1150 size_t off = 1;1151 while ( off < cchLeft1152 && ( (ch = psz[off]) == '_'1153 || RT_C_IS_ALNUM(ch)))1154 off++;1155 1156 pStream->off += off;1157 *pcchWord = off;1158 return psz;1159 }1160 1161 1162 /**1163 * Get's the C word starting at the current position minus one.1164 *1165 * @returns Pointer to the word on success and the stream position advanced to1166 * the end of it.1167 * NULL on failure, stream position normally unchanged.1168 * @param pStream The stream to get the C word from.1169 * @param pcchWord Where to return the word length.1170 */1171 const char *ScmStreamCGetWordM1(PSCMSTREAM pStream, size_t *pcchWord)1172 {1173 /* Check stream state. */1174 AssertReturn(!pStream->fWriteOrRead, NULL);1175 AssertReturn(RT_SUCCESS(pStream->rc), NULL);1176 AssertReturn(pStream->fFullyLineated, NULL);1177 1178 /* Get the number of chars left on the line and locate the current char. */1179 size_t const iLine = pStream->iLine;1180 size_t const cchLeft = pStream->paLines[iLine].cch + pStream->paLines[iLine].off - (pStream->off - 1);1181 const char *psz = &pStream->pch[pStream->off - 1];1182 1183 /* Is it a leading C character. */1184 if (!RT_C_IS_ALPHA(*psz) && *psz == '_')1185 return NULL;1186 1187 /* Find the end of the word. */1188 char ch;1189 size_t off = 1;1190 while ( off < cchLeft1191 && ( (ch = psz[off]) == '_'1192 || RT_C_IS_ALNUM(ch)))1193 off++;1194 1195 pStream->off += off - 1;1196 *pcchWord = off;1197 return psz;1198 }1199 1200 1036 1201 1037 /** -
trunk/src/bldprogs/scmstream.cpp
r41180 r41186 706 706 } 707 707 708 /** 709 * Get the current buffer pointer. 710 * 711 * @returns Buffer pointer on success, NULL on failure (asserted). 712 * @param pStream The stream. Must be in read mode. 713 */ 714 const char *ScmStreamGetCur(PSCMSTREAM pStream) 715 { 716 AssertReturn(!pStream->fWriteOrRead, NULL); 717 return pStream->pch + pStream->off; 718 } 708 719 709 720 /** … … 1109 1120 1110 1121 /** 1122 * Formats a string and writes it to the SCM stream. 1123 * 1124 * @returns The number of bytes written (>= 0). Negative value are IPRT error 1125 * status codes. 1126 * @param pStream The stream to write to. 1127 * @param pszFormat The format string. 1128 * @param va The arguments to format. 1129 */ 1130 ssize_t ScmStreamPrintfV(PSCMSTREAM pStream, const char *pszFormat, va_list va) 1131 { 1132 char *psz; 1133 ssize_t cch = RTStrAPrintfV(&psz, pszFormat, va); 1134 if (cch) 1135 { 1136 int rc = ScmStreamWrite(pStream, psz, cch); 1137 RTStrFree(psz); 1138 if (RT_FAILURE(rc)) 1139 cch = rc; 1140 } 1141 return cch; 1142 } 1143 1144 /** 1145 * Formats a string and writes it to the SCM stream. 1146 * 1147 * @returns The number of bytes written (>= 0). Negative value are IPRT error 1148 * status codes. 1149 * @param pStream The stream to write to. 1150 * @param pszFormat The format string. 1151 * @param ... The arguments to format. 1152 */ 1153 ssize_t ScmStreamPrintf(PSCMSTREAM pStream, const char *pszFormat, ...) 1154 { 1155 va_list va; 1156 va_start(va, pszFormat); 1157 ssize_t cch = ScmStreamPrintfV(pStream, pszFormat, va); 1158 va_end(va); 1159 return cch; 1160 } 1161 1162 /** 1111 1163 * Copies @a cLines from the @a pSrc stream onto the @a pDst stream. 1112 1164 * … … 1144 1196 } 1145 1197 1198 1199 /** 1200 * If the given C word is at off - 1, return @c true and skip beyond it, 1201 * otherwise return @c false. 1202 * 1203 * @retval true if the given C-word is at the current position minus one char. 1204 * The stream position changes. 1205 * @retval false if not. The stream position is unchanged. 1206 * 1207 * @param pStream The stream. 1208 * @param cchWord The length of the word. 1209 * @param pszWord The word. 1210 */ 1211 bool ScmStreamCMatchingWordM1(PSCMSTREAM pStream, const char *pszWord, size_t cchWord) 1212 { 1213 /* Check stream state. */ 1214 AssertReturn(!pStream->fWriteOrRead, false); 1215 AssertReturn(RT_SUCCESS(pStream->rc), false); 1216 AssertReturn(pStream->fFullyLineated, false); 1217 1218 /* Sufficient chars left on the line? */ 1219 size_t const iLine = pStream->iLine; 1220 AssertReturn(pStream->off > pStream->paLines[iLine].off, false); 1221 size_t const cchLeft = pStream->paLines[iLine].cch + pStream->paLines[iLine].off - (pStream->off - 1); 1222 if (cchWord > cchLeft) 1223 return false; 1224 1225 /* Do they match? */ 1226 const char *psz = &pStream->pch[pStream->off - 1]; 1227 if (memcmp(psz, pszWord, cchWord)) 1228 return false; 1229 1230 /* Is it the end of a C word? */ 1231 if (cchWord < cchLeft) 1232 { 1233 psz += cchWord; 1234 if (RT_C_IS_ALNUM(*psz) || *psz == '_') 1235 return false; 1236 } 1237 1238 /* Skip ahead. */ 1239 pStream->off += cchWord - 1; 1240 return true; 1241 } 1242 1243 /** 1244 * Get's the C word starting at the current position. 1245 * 1246 * @returns Pointer to the word on success and the stream position advanced to 1247 * the end of it. 1248 * NULL on failure, stream position normally unchanged. 1249 * @param pStream The stream to get the C word from. 1250 * @param pcchWord Where to return the word length. 1251 */ 1252 const char *ScmStreamCGetWord(PSCMSTREAM pStream, size_t *pcchWord) 1253 { 1254 /* Check stream state. */ 1255 AssertReturn(!pStream->fWriteOrRead, NULL); 1256 AssertReturn(RT_SUCCESS(pStream->rc), NULL); 1257 AssertReturn(pStream->fFullyLineated, NULL); 1258 1259 /* Get the number of chars left on the line and locate the current char. */ 1260 size_t const iLine = pStream->iLine; 1261 size_t const cchLeft = pStream->paLines[iLine].cch + pStream->paLines[iLine].off - pStream->off; 1262 const char *psz = &pStream->pch[pStream->off]; 1263 1264 /* Is it a leading C character. */ 1265 if (!RT_C_IS_ALPHA(*psz) && *psz == '_') 1266 return NULL; 1267 1268 /* Find the end of the word. */ 1269 char ch; 1270 size_t off = 1; 1271 while ( off < cchLeft 1272 && ( (ch = psz[off]) == '_' 1273 || RT_C_IS_ALNUM(ch))) 1274 off++; 1275 1276 pStream->off += off; 1277 *pcchWord = off; 1278 return psz; 1279 } 1280 1281 1282 /** 1283 * Get's the C word starting at the current position minus one. 1284 * 1285 * @returns Pointer to the word on success and the stream position advanced to 1286 * the end of it. 1287 * NULL on failure, stream position normally unchanged. 1288 * @param pStream The stream to get the C word from. 1289 * @param pcchWord Where to return the word length. 1290 */ 1291 const char *ScmStreamCGetWordM1(PSCMSTREAM pStream, size_t *pcchWord) 1292 { 1293 /* Check stream state. */ 1294 AssertReturn(!pStream->fWriteOrRead, NULL); 1295 AssertReturn(RT_SUCCESS(pStream->rc), NULL); 1296 AssertReturn(pStream->fFullyLineated, NULL); 1297 1298 /* Get the number of chars left on the line and locate the current char. */ 1299 size_t const iLine = pStream->iLine; 1300 size_t const cchLeft = pStream->paLines[iLine].cch + pStream->paLines[iLine].off - (pStream->off - 1); 1301 const char *psz = &pStream->pch[pStream->off - 1]; 1302 1303 /* Is it a leading C character. */ 1304 if (!RT_C_IS_ALPHA(*psz) && *psz == '_') 1305 return NULL; 1306 1307 /* Find the end of the word. */ 1308 char ch; 1309 size_t off = 1; 1310 while ( off < cchLeft 1311 && ( (ch = psz[off]) == '_' 1312 || RT_C_IS_ALNUM(ch))) 1313 off++; 1314 1315 pStream->off += off - 1; 1316 *pcchWord = off; 1317 return psz; 1318 } 1319 1320 1321 -
trunk/src/bldprogs/scmstream.h
r41179 r41186 99 99 int ScmStreamWriteToFile(PSCMSTREAM pStream, const char *pszFilenameFmt, ...); 100 100 int ScmStreamWriteToStdOut(PSCMSTREAM pStream); 101 101 102 size_t ScmStreamTell(PSCMSTREAM pStream); 102 103 size_t ScmStreamTellLine(PSCMSTREAM pStream); … … 106 107 int ScmStreamSeekRelative(PSCMSTREAM pStream, ssize_t offRelative); 107 108 int ScmStreamSeekByLine(PSCMSTREAM pStream, size_t iLine); 109 108 110 const char *ScmStreamGetLineByNo(PSCMSTREAM pStream, size_t iLine, size_t *pcchLine, PSCMEOL penmEol); 109 111 const char *ScmStreamGetLine(PSCMSTREAM pStream, size_t *pcchLine, PSCMEOL penmEol); 110 112 unsigned ScmStreamGetCh(PSCMSTREAM pStream); 113 const char *ScmStreamGetCur(PSCMSTREAM pStream); 111 114 unsigned ScmStreamPeekCh(PSCMSTREAM pStream); 112 115 int ScmStreamRead(PSCMSTREAM pStream, void *pvBuf, size_t cbToRead); … … 114 117 SCMEOL ScmStreamGetEol(PSCMSTREAM pStream); 115 118 SCMEOL ScmStreamGetEolByLine(PSCMSTREAM pStream, size_t iLine); 119 116 120 int ScmStreamPutLine(PSCMSTREAM pStream, const char *pchLine, size_t cchLine, SCMEOL enmEol); 117 121 int ScmStreamWrite(PSCMSTREAM pStream, const char *pchBuf, size_t cchBuf); 118 122 int ScmStreamPutCh(PSCMSTREAM pStream, char ch); 123 ssize_t ScmStreamPrintf(PSCMSTREAM pStream, const char *pszFormat, ...); 124 ssize_t ScmStreamPrintfV(PSCMSTREAM pStream, const char *pszFormat, va_list va); 119 125 int ScmStreamCopyLines(PSCMSTREAM pDst, PSCMSTREAM pSrc, size_t cLines); 126 127 bool ScmStreamCMatchingWordM1(PSCMSTREAM pStream, const char *pszWord, size_t cchWord); 128 const char *ScmStreamCGetWord(PSCMSTREAM pStream, size_t *pcchWord); 129 const char *ScmStreamCGetWordM1(PSCMSTREAM pStream, size_t *pcchWord); 120 130 121 131 RT_C_DECLS_END
Note:
See TracChangeset
for help on using the changeset viewer.