VirtualBox

Changeset 40554 in vbox for trunk


Ignore:
Timestamp:
Mar 20, 2012 6:07:34 PM (13 years ago)
Author:
vboxsync
Message:

-> home

Location:
trunk/src/bldprogs
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/bldprogs/Makefile.kmk

    r40549 r40554  
    55
    66#
    7 # Copyright (C) 2006-2010 Oracle Corporation
     7# Copyright (C) 2006-2012 Oracle Corporation
    88#
    99# This file is part of VirtualBox Open Source Edition (OSE), as
     
    4141        scmrw.cpp \
    4242        scmstream.cpp \
    43         scmsubversion.cpp 
     43        scmsubversion.cpp
    4444
    4545
    46  #BLDPROGS += VBoxTpG
     46 BLDPROGS += VBoxTpG
    4747 VBoxTpG_TEMPLATE = VBoxAdvBldProg
    4848 VBoxTpG_SOURCES = \
  • trunk/src/bldprogs/VBoxTpG.cpp

    r40549 r40554  
    55
    66/*
    7  * Copyright (C) 2010-2012 Oracle Corporation
     7 * Copyright (C) 2012 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2020*   Header Files                                                               *
    2121*******************************************************************************/
     22#include <iprt/alloca.h>
    2223#include <iprt/assert.h>
    2324#include <iprt/ctype.h>
    2425#include <iprt/env.h>
    2526#include <iprt/err.h>
     27#include <iprt/file.h>
    2628#include <iprt/getopt.h>
    2729#include <iprt/initterm.h>
     30#include <iprt/list.h>
    2831#include <iprt/mem.h>
    2932#include <iprt/message.h>
     33#include <iprt/process.h>
    3034#include <iprt/stream.h>
    3135#include <iprt/string.h>
     36#include <iprt/strcache.h>
    3237
    3338#include "scmstream.h"
    3439
    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*******************************************************************************/
     44typedef struct VTGARG
     45{
     46    const char     *pszName;
     47    const char     *pszType;
     48} VTGARG;
     49typedef VTGARG *PVTGARG;
     50
     51typedef struct VTGPROBE
     52{
     53    RTLISTNODE      ListEntry;
     54    const char     *pszName;
     55    uint32_t        cArgs;
     56    PVTGARG         paArgs;
     57} VTGPROBE;
     58typedef VTGPROBE *PVTGPROBE;
     59
     60typedef struct VTGPROVIDER
     61{
     62    RTLISTNODE      ListEntry;
     63    const char     *pszName;
     64    RTLISTANCHOR    ProbeHead;
     65} VTGPROVIDER;
     66typedef VTGPROVIDER *PVTGPROVIDER;
     67
     68
     69/*******************************************************************************
     70*   Global Variables                                                           *
     71*******************************************************************************/
     72/** String cache used for storing strings when parsing. */
     73static RTSTRCACHE       g_hStrCache = NIL_RTSTRCACHE;
     74/** List of providers created by the parser. */
     75static RTLISTANCHOR     g_ProviderHead;
     76
     77/** @name Options
     78 * @{ */
     79static enum
     80{
     81    kVBoxTpGAction_Nothing,
     82    kVBoxTpGAction_GenerateHeader,
     83    kVBoxTpGAction_GenerateObject
     84}                           g_enmAction                 = kVBoxTpGAction_Nothing;
     85static uint32_t             g_cBits                     = ARCH_BITS;
     86static bool                 g_fApplyCpp                 = false;
     87static uint32_t             g_cVerbosity                = 0;
     88static const char          *g_pszOutput                 = NULL;
     89static const char          *g_pszScript                 = NULL;
     90static const char          *g_pszTempAsm                = NULL;
     91#ifdef RT_OS_DARWIN
     92static const char          *g_pszAssembler              = "yasm";
     93static const char          *g_pszAssemblerFmtOpt        = "--oformat";
     94static const char           g_szAssemblerFmtVal32[]     = "macho32";
     95static const char           g_szAssemblerFmtVal64[]     = "macho64";
     96#elif defined(RT_OS_OS2)
     97static const char          *pszAssembler                = "nasm.exe";
     98static const char          *pszAssemblerFmtOpt          = "-f";
     99static const char           g_szAssemblerFmtVal32[]     = "obj";
     100static const char           g_szAssemblerFmtVal64[]     = "elf64";
     101#elif defined(RT_OS_WINDOWS)
     102static const char          *g_pszAssembler              = "yasm.exe";
     103static const char          *g_pszAssemblerFmtOpt        = "--oformat";
     104static const char           g_szAssemblerFmtVal32[]     = "win32";
     105static const char           g_szAssemblerFmtVal64[]     = "win64";
     106#else
     107static const char          *g_pszAssembler              = "yasm";
     108static const char          *g_pszAssemblerFmtOpt        = "--oformat";
     109static const char           g_szAssemblerFmtVal32[]     = "elf32";
     110static const char           g_szAssemblerFmtVal64[]     = "elf64";
     111#endif
     112static const char          *g_pszAssemblerFmtVal        = RT_CONCAT(g_szAssemblerFmtVal, ARCH_BITS);
     113static const char          *g_pszAssemblerOutputOpt     = "-o";
     114static unsigned             g_cAssemblerOptions         = 0;
     115static const char          *g_apszAssemblerOptions[32];
     116/** @} */
     117
     118
     119static RTEXITCODE generateInvokeAssembler(const char *pszOutput, const char *pszTempAsm)
     120{
     121    RTPrintf("Todo invoke the assembler\n");
     122    return RTEXITCODE_SKIPPED;
     123}
     124
     125
     126static RTEXITCODE generateFile(const char *pszOutput, const char *pszWhat,
     127                               RTEXITCODE (*pfnGenerator)(PSCMSTREAM))
     128{
     129    SCMSTREAM Strm;
     130    int rc = ScmStreamInitForWriting(&Strm, NULL);
    50131    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
     167static 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
     177static 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
     196static RTEXITCODE generateHeaderInner(PSCMSTREAM pStrm)
     197{
     198    RTPrintf("Todo generate the header\n");
     199    return RTEXITCODE_SUCCESS;
     200}
     201
     202
     203static 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 */
     220bool 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 */
     261const 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 */
     300static 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 */
     326static 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 */
     338static 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 */
     364static 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
     393static RTEXITCODE parseProvider(PSCMSTREAM pStrm)
     394{
    53395    /*
    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
    56397     */
     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
     435static 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 */
     491static 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
    57505    static RTGETOPTDEF const s_aOpts[] =
    58506    {
    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 },
    61510        { "--apply-cpp",                        'C',                                    RTGETOPT_REQ_NOTHING },
    62511        { "--generate-obj",                     'G',                                    RTGETOPT_REQ_NOTHING },
     
    64513        { "--output",                           'o',                                    RTGETOPT_REQ_STRING  },
    65514        { "--script",                           's',                                    RTGETOPT_REQ_STRING  },
     515        { "--verbose",                          'v',                                    RTGETOPT_REQ_NOTHING },
     516        /* out stuff */
    66517        { "--assembler",                        kVBoxTpGOpt_Assembler,                  RTGETOPT_REQ_STRING  },
    67518        { "--assembler-fmt-opt",                kVBoxTpGOpt_AssemblerFmtOpt,            RTGETOPT_REQ_STRING  },
     
    71522    };
    72523
    73     enum
    74     {
    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_DARWIN
    83     const char     *pszAssemblerFmtVal           = "macho" RT_XSTR(ARCH_BITS);
    84 #elif defined(RT_OS_WINDOWS)
    85     const char     *pszAssemblerFmtVal           = "win" RT_XSTR(ARCH_BITS);
    86 #else
    87     const char     *pszAssemblerFmtVal           = "elf" RT_XSTR(ARCH_BITS);
    88 #endif
    89     const char     *pszAssemblerOutputOpt        = "-o"
    90     const char     *apszAssemblerOptions[32]     = { NULL, NULL,  };
    91 
    92 
    93524    RTGETOPTUNION   ValueUnion;
    94525    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);
    98528
    99529    while ((rc = RTGetOpt(&GetOptState, &ValueUnion)) != 0)
     
    101531        switch (rc)
    102532        {
     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
    103558            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;
    115598
    116599            case 'V':
     
    120603                const char *psz = RTStrStripL(strchr(s_szRev, ' '));
    121604                RTPrintf("r%.*s\n", strchr(psz, ' ') - psz, psz);
    122                 return 0;
     605                return RTEXITCODE_SUCCESS;
    123606            }
    124607
    125 
    126608            case VINF_GETOPT_NOT_OPTION:
    127                 if (enmAction == kVBoxTpGAction_GenerateObject)
     609                if (g_enmAction == kVBoxTpGAction_GenerateObject)
    128610                    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             */
    131643            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
     662int 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)
    132680            {
    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);
    139688            }
     689            RTStrCacheDestroy(g_hStrCache);
    140690        }
    141691    }
    142692
    143 
    144     return 0;
    145 }
     693    return rcExit;
     694}
     695
  • trunk/src/bldprogs/scmstream.cpp

    r40530 r40554  
    643643{
    644644    /** @todo this doesn't work when pStream->off !=
    645      *        pStream->paLines[pStream->iLine-1].pff. */
     645     *        pStream->paLines[pStream->iLine-1].off. */
    646646    if (!pStream->fFullyLineated)
    647647        return scmStreamGetLineInternal(pStream, pcchLine, penmEol);
     
    649649}
    650650
     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 */
     659unsigned 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 */
     695unsigned 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
    651718/**
    652719 * Reads @a cbToRead bytes into @a pvBuf.
     
    670737
    671738    /* 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))
    673740        return VERR_EOF;
    674741
     
    677744    return ScmStreamSeekAbsolute(pStream, pStream->off + cbToRead);
    678745}
     746
    679747
    680748/**
  • trunk/src/bldprogs/scmstream.h

    r40528 r40554  
    107107const char *ScmStreamGetLineByNo(PSCMSTREAM pStream, size_t iLine, size_t *pcchLine, PSCMEOL penmEol);
    108108const char *ScmStreamGetLine(PSCMSTREAM pStream, size_t *pcchLine, PSCMEOL penmEol);
     109unsigned    ScmStreamGetCh(PSCMSTREAM pStream);
     110unsigned    ScmStreamPeekCh(PSCMSTREAM pStream);
    109111int         ScmStreamRead(PSCMSTREAM pStream, void *pvBuf, size_t cbToRead);
    110112bool        ScmStreamIsWhiteLine(PSCMSTREAM pStream, size_t iLine);
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette