int main( int argc, char ** argv )

{
    EarlySetConfigOptions(argc, argv);

/* -------------------------------------------------------------------- */
/*      Register standard GDAL drivers, and process generic GDAL        */
/*      command options.                                                */
/* -------------------------------------------------------------------- */
    GDALAllRegister();
    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
    if( argc < 1 )
        exit( -argc );

    for( int i = 0; argv != NULL && argv[i] != NULL; i++ )
    {
        if( EQUAL(argv[i], "--utility_version") )
        {
            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
            CSLDestroy( argv );
            return 0;
        }
        else if( EQUAL(argv[i],"--help") )
        {
            Usage(NULL);
        }
    }

    GDALBuildVRTOptionsForBinary* psOptionsForBinary = GDALBuildVRTOptionsForBinaryNew();
    /* coverity[tainted_data] */
    GDALBuildVRTOptions *psOptions = GDALBuildVRTOptionsNew(argv + 1, psOptionsForBinary);
    CSLDestroy( argv );

    if( psOptions == NULL )
    {
        Usage(NULL);
    }

    if( psOptionsForBinary->pszDstFilename == NULL )
    {
        Usage("No target filename specified.");
    }

    if( !(psOptionsForBinary->bQuiet) )
    {
        GDALBuildVRTOptionsSetProgress(psOptions, GDALTermProgress, NULL);
    }

    /* Avoid overwriting a non VRT dataset if the user did not put the */
    /* filenames in the right order */
    VSIStatBuf sBuf;
    if (!psOptionsForBinary->bOverwrite)
    {
        int bExists = (VSIStat(psOptionsForBinary->pszDstFilename, &sBuf) == 0);
        if (bExists)
        {
            GDALDriverH hDriver = GDALIdentifyDriver( psOptionsForBinary->pszDstFilename, NULL );
            if (hDriver && !(EQUAL(GDALGetDriverShortName(hDriver), "VRT") ||
                   (EQUAL(GDALGetDriverShortName(hDriver), "API_PROXY") &&
                    EQUAL(CPLGetExtension(psOptionsForBinary->pszDstFilename), "VRT"))) )
            {
                fprintf(stderr,
                        "'%s' is an existing GDAL dataset managed by %s driver.\n"
                        "There is an high chance you did not put filenames in the right order.\n"
                        "If you want to overwrite %s, add -overwrite option to the command line.\n\n",
                        psOptionsForBinary->pszDstFilename, GDALGetDriverShortName(hDriver), psOptionsForBinary->pszDstFilename);
                Usage();
            }
        }
    }

    int bUsageError = FALSE;
    GDALDatasetH hOutDS = GDALBuildVRT(psOptionsForBinary->pszDstFilename,
                                       psOptionsForBinary->nSrcFiles,
                                       NULL,
                                       (const char* const*)psOptionsForBinary->papszSrcFiles,
                                       psOptions, &bUsageError);
    if( bUsageError )
        Usage();
    int nRetCode = (hOutDS) ? 0 : 1;

    GDALBuildVRTOptionsFree(psOptions);
    GDALBuildVRTOptionsForBinaryFree(psOptionsForBinary);

    CPLErrorReset();
    // The flush to disk is only done at that stage, so check if any error has
    // happened
    GDALClose( hOutDS );
    if( CPLGetLastErrorType() != CE_None )
        nRetCode = 1;

    GDALDumpOpenDatasets( stderr );

    GDALDestroyDriverManager();

    OGRCleanupAll();

    return nRetCode;
}
/** Load proj.4 geoidgrids as GDAL dataset
 *
 * @param pszProj4Geoidgrids Value of proj.4 geoidgrids parameter.
 * @param pbError If not NULL, the pointed value will be set to TRUE if an
 *                error occurred.
 *
 * @return a dataset. If not NULL, it must be closed with GDALClose().
 *
 * @since GDAL 2.2
 */
GDALDatasetH GDALOpenVerticalShiftGrid( const char* pszProj4Geoidgrids,
                                        int* pbError )
{
    char** papszGrids = CSLTokenizeString2( pszProj4Geoidgrids, ",", 0);
    const int nGridCount = CSLCount(papszGrids);
    if( nGridCount == 1 )
    {
        CSLDestroy(papszGrids);

        bool bMissingOk = false;
        if( *pszProj4Geoidgrids == '@' )
        {
            pszProj4Geoidgrids ++;
            bMissingOk = true;
        }
        const CPLString osFilename(GetProj4Filename(pszProj4Geoidgrids));
        const char* const papszOpenOptions[] =
            { "@SHIFT_ORIGIN_IN_MINUS_180_PLUS_180=YES", nullptr };
        GDALDatasetH hDS = GDALOpenEx(osFilename, 0, nullptr, papszOpenOptions, nullptr);
        if( hDS == nullptr )
        {
            CPLDebug("GDAL", "Cannot find file corresponding to %s",
                     pszProj4Geoidgrids);
        }
        if( pbError )
            *pbError = (!bMissingOk && hDS == nullptr);
        return hDS;
    }

    CPLStringList aosFilenames;
    for( int i = nGridCount - 1; i >= 0; i-- )
    {
        const char* pszName = papszGrids[i];
        bool bMissingOk = false;
        if( *pszName == '@' )
        {
            pszName ++;
            bMissingOk = true;
        }
        const CPLString osFilename(GetProj4Filename(pszName));
        VSIStatBufL sStat;
        if( osFilename.empty() || VSIStatL(osFilename, &sStat) != 0 )
        {
            CPLDebug("GDAL", "Cannot find file corresponding to %s",
                     pszName);
            if( !bMissingOk )
            {
                if( pbError )
                    *pbError = true;
                CSLDestroy(papszGrids);
                return nullptr;
            }
        }
        else
        {
            aosFilenames.AddString(osFilename);
        }
    }

    CSLDestroy(papszGrids);

    if( aosFilenames.empty() )
    {
        if( pbError )
            *pbError = false;
        return nullptr;
    }

    char** papszArgv = nullptr;
    papszArgv = CSLAddString(papszArgv, "-resolution");
    papszArgv = CSLAddString(papszArgv, "highest");
    papszArgv = CSLAddString(papszArgv, "-vrtnodata");
    papszArgv = CSLAddString(papszArgv, "-inf");
    papszArgv = CSLAddString(papszArgv, "-oo");
    papszArgv = CSLAddString(papszArgv, "@SHIFT_ORIGIN_IN_MINUS_180_PLUS_180=YES");
    GDALBuildVRTOptions* psOptions = GDALBuildVRTOptionsNew(papszArgv, nullptr);
    CSLDestroy(papszArgv);
    GDALDatasetH hDS =
        GDALBuildVRT( "", aosFilenames.size(), nullptr, aosFilenames.List(),
                     psOptions, nullptr );
    GDALBuildVRTOptionsFree( psOptions );
    if( pbError )
        *pbError = hDS != nullptr;
    return hDS;
}