<commit_before>// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.

#include <boost/algorithm/string.hpp>
#include <boost/interprocess/ipc/message_queue.hpp>
#include <boost/tokenizer.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/version.hpp>

#if defined(WIN32) && (!defined(BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME) || !defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) || BOOST_VERSION < 104900)
#warning Compiling without BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME and BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME uncommented in boost/interprocess/detail/tmp_dir_helpers.hpp or using a boost version before 1.49 may have unintended results see svn.boost.org/trac/boost/ticket/5392
#endif

#include "ui_interface.h"
#include "qtipcserver.h"

using namespace boost::interprocess;
using namespace boost::posix_time;
using namespace boost;
using namespace std;

#ifdef MAC_OSX
// URI handling not implemented on OSX yet

void ipcInit() { }
void ipcShutdown() { }

#else

void ipcShutdown()
{
    message_queue::remove(BITCOINURI_QUEUE_NAME);
}

void ipcThread(void* parg)
{
    message_queue* mq = (message_queue*)parg;
    char strBuf[257];
    size_t nSize;
    unsigned int nPriority;
    loop
    {
        ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(100);
        if(mq->timed_receive(&strBuf, sizeof(strBuf), nSize, nPriority, d))
        {
            uiInterface.ThreadSafeHandleURI(std::string(strBuf, nSize));
            Sleep(1000);
        }
        if (fShutdown)
        {
            ipcShutdown();
            break;
        }
    }
    ipcShutdown();
}

void ipcInit()
{
    message_queue* mq;
    char strBuf[257];
    size_t nSize;
    unsigned int nPriority;
    try {
        mq = new message_queue(open_or_create, BITCOINURI_QUEUE_NAME, 2, 256);

        // Make sure we don't lose any bitcoin: URIs
        for (int i = 0; i < 2; i++)
        {
            ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(1);
            if(mq->timed_receive(&strBuf, sizeof(strBuf), nSize, nPriority, d))
            {
                uiInterface.ThreadSafeHandleURI(std::string(strBuf, nSize));
            }
            else
                break;
        }

        // Make sure only one bitcoin instance is listening
        message_queue::remove(BITCOINURI_QUEUE_NAME);
        mq = new message_queue(open_or_create, BITCOINURI_QUEUE_NAME, 2, 256);
    }
    catch (interprocess_exception &ex) {
        return;
    }
    if (!CreateThread(ipcThread, mq))
    {
        delete mq;
    }
}

#endif
<commit_msg>Give the GUI-IPC thread a name as well<commit_after>// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.

#include <boost/algorithm/string.hpp>
#include <boost/interprocess/ipc/message_queue.hpp>
#include <boost/tokenizer.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/version.hpp>

#if defined(WIN32) && (!defined(BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME) || !defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) || BOOST_VERSION < 104900)
#warning Compiling without BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME and BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME uncommented in boost/interprocess/detail/tmp_dir_helpers.hpp or using a boost version before 1.49 may have unintended results see svn.boost.org/trac/boost/ticket/5392
#endif

#include "ui_interface.h"
#include "qtipcserver.h"
#include "util.h"

using namespace boost::interprocess;
using namespace boost::posix_time;
using namespace boost;
using namespace std;

#ifdef MAC_OSX
// URI handling not implemented on OSX yet

void ipcInit() { }
void ipcShutdown() { }

#else

void ipcShutdown()
{
    message_queue::remove(BITCOINURI_QUEUE_NAME);
}

void ipcThread(void* parg)
{
    // Make this thread recognisable as the GUI-IPC thread
    RenameThread("bitcoin-gui-ipc");

    message_queue* mq = (message_queue*)parg;
    char strBuf[257];
    size_t nSize;
    unsigned int nPriority;
    loop
    {
        ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(100);
        if(mq->timed_receive(&strBuf, sizeof(strBuf), nSize, nPriority, d))
        {
            uiInterface.ThreadSafeHandleURI(std::string(strBuf, nSize));
            Sleep(1000);
        }
        if (fShutdown)
        {
            ipcShutdown();
            break;
        }
    }
    ipcShutdown();
}

void ipcInit()
{
    message_queue* mq;
    char strBuf[257];
    size_t nSize;
    unsigned int nPriority;
    try {
        mq = new message_queue(open_or_create, BITCOINURI_QUEUE_NAME, 2, 256);

        // Make sure we don't lose any bitcoin: URIs
        for (int i = 0; i < 2; i++)
        {
            ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(1);
            if(mq->timed_receive(&strBuf, sizeof(strBuf), nSize, nPriority, d))
            {
                uiInterface.ThreadSafeHandleURI(std::string(strBuf, nSize));
            }
            else
                break;
        }

        // Make sure only one bitcoin instance is listening
        message_queue::remove(BITCOINURI_QUEUE_NAME);
        mq = new message_queue(open_or_create, BITCOINURI_QUEUE_NAME, 2, 256);
    }
    catch (interprocess_exception &ex) {
        return;
    }
    if (!CreateThread(ipcThread, mq))
    {
        delete mq;
    }
}

#endif
<|endoftext|>


<commit_before>/*
 * =====================================================================================
 *
 *       Filename:  requesthandler.cpp
 *
 *    Description:  Handle requests
 *
 *        Version:  1.0
 *        Created:  28/01/13 21:47:34
 *       Revision:  none
 *       Compiler:  g++
 *
 *         Author:  Daniel Bugl <Daniel.Bugl@touchlay.com>
 *   Organization:  TouchLay
 *
 * =====================================================================================
 */

// Headers
#include "requesthandler.h"

/* RequestHandler: Constructor */
RequestHandler::RequestHandler(int connection, char *cip) {
 // TODO: Create a blacklist for IPs
 clientip = cip;

 // Initialise request
 InitRequest(&request);

 // Handle request and check request type
 if (handle(connection) == true) {
  #ifdef DEBUG
  std::cout << "[DEBUG] [request     ] handle() returned true, continuing!" << std::endl;
  #endif
  if (request.type == HTTP) {
   #ifdef DEBUG
   std::cout << "[DEBUG] [request_http] This is an HTTP request." << std::endl;
   #endif
   if (request.status == 200) {
    #ifdef DEBUG
    std::cout << "[DEBUG] [request_http] Status 200, returning result." << std::endl;
    #endif
    if (parseJSON()) {
     API api = API(jRoot);
     #ifdef DEBUG
     std::cout << "[DEBUG] [request_api ] Got API result(" << strlen(api.result.c_str()) << "): " << api.result << std::endl;
     #endif
     outputHTTP(connection, &request, api.result.c_str());
    } else outputHTTP(connection, &request, "{\"type\": \"error\", \"msg\": \"Invalid JSON.\"}");
    #ifdef DEBUG
    std::cout << "[DEBUG] [request_http] Answered to request with HTTP." << std::endl;
    #endif
   } else {
    std::stringstream sbuffer;
    sbuffer << "{\"type\": \"error\", \"msg\": \"HTTP Error " << request.status << "\"}";
    outputHTTP(connection, &request, sbuffer.str());
   }
   usleep(REQUEST_TIMEOUT_SEND*1000000);
  } else if (request.type == TN) {
   #ifdef DEBUG
   std::cout << "[DEBUG] [request_tn  ] This is a TN request." << std::endl;
   #endif
   if (parseJSON()) {
    API api = API(jRoot);
    #ifdef DEBUG
    std::cout << "[DEBUG] [request_api ] Got API result(" << strlen(api.result.c_str()) << "): " << api.result << std::endl;
    #endif
    s_writeline(connection, api.result.c_str(), strlen(api.result.c_str()));
   } else s_writeline(connection, "{\"type\": \"error\", \"msg\": \"Invalid JSON.\"}", 41);
   #ifdef DEBUG
   std::cout << "[DEBUG] [request_tn  ] Answered to request with TN." << std::endl;
   usleep(REQUEST_TIMEOUT_SEND*1000000);
   #endif
  } else std::cout << "[WARN ] [request     ] Unknown request type, killing request." << std::endl;
 } else std::cout << "[WARN ] [request     ] Couldn't handle request, killing it." << std::endl;
}

/* parseJSON: JSON parser */
bool RequestHandler::parseJSON() {
 if (request.type == HTTP) memmove(request.resource, request.resource+1, strlen(request.resource)); // Remove / prefix from the GET request
 std::string data = decodeURI(request.resource);
 #ifdef DEBUG
 std::cout << "[DEBUG] [request_json] Got data: " << data << "\n";
 #endif
 if (!jReader.parse(data, jRoot, false)) {
  #ifdef DEBUG
  std::cout << "[DEBUG] [request_json] Invalid JSON (" << data << ")." << std::endl;
  #endif
  return false;
 }
 else return true;
}

/* ~RequestHandler: Destructor */
RequestHandler::~RequestHandler() {
 #ifdef DEBUG
 std::cout << "[DEBUG] [request     ] Destructed RequestHandler." << std::endl;
 #endif
}

/* InitRequest: Initialises the request data */
void RequestHandler::InitRequest(Request *request) {
 request->status = 200;
 request->method = UNSUPPORTED;
 request->resource = NULL;
 #ifdef DEBUG
 std::cout << "[DEBUG] [request     ] Initialised request." << std::endl;
 #endif
}

/* FreeRequest: Clear the request data */
void RequestHandler::FreeRequest(Request *request) {
 if (request->resource) delete request->resource;
 #ifdef DEBUG
 std::cout << "[DEBUG] [request     ] Free'd request." << std::endl;
 #endif
}

/* handle: Handle a request */
bool RequestHandler::handle(int connection) {
 char buffer[MAX_REQ_LINE] = {0};
 int rval;
 fd_set fds;
 struct timeval tv;

 // Timeout
 tv.tv_sec = REQUEST_TIMEOUT_RECV;
 tv.tv_usec = 0;

 do {
  // Reset FD
  FD_ZERO(&fds);
  FD_SET(connection, &fds);

  rval = select(connection+1, &fds, NULL, NULL, &tv); // Select from request

  if (rval < 0) std::cout << "[WARN ] [request     ] Couldn't select from request." << std::endl;
  else if (rval == 0) return false; // Timeout, kill request
  else {
   s_readline(connection, buffer, MAX_REQ_LINE - 1);

   #ifdef DEBUG
   std::cout << "[DEBUG] [request     ] Received buffer: " << buffer << std::endl;
   #endif

   if (buffer[0] == '{') {
    request.type = TN;
    request.resource = buffer;
    request.level = SIMPLE;
    return true;
   } else {
    request.type = HTTP;
    strim(buffer);
    char *buf = buffer;
    char *endptr = NULL;
    int len;
    if (!strncmp(buffer, "GET ", 4)) {
     request.method = GET;
     buf += 4;
    } else if (!strncmp(buffer, "HEAD ", 5)) {
     request.method = HEAD;
     buf += 5;
    } else {
     request.method = UNSUPPORTED;
     request.status = 501;
     return true;
    }

    while (*buf && isspace(*buf)) buf++; // Skip the start

    endptr = strchr(buf, ' ');
    if (endptr == NULL) len = strlen(buf);
    else len = endptr - buf;

    if (len == 0) {
     request.status = 400;
     return true;
    }

    request.resource = (char *)calloc(len + 1, sizeof(char));
    strncpy(request.resource, buf, len);

    request.level = SIMPLE;

    return true;
   }
  }
 } while (request.level != SIMPLE);
 return true; // Successfully processed
}

bool RequestHandler::outputHTTP(int connection, Request *request, std::string content) {
 std::stringstream sbuffer;

 sbuffer << "HTTP/1.1 " << request->status << " OK\r\n";
 s_writeline(connection, sbuffer.str().c_str(), strlen(sbuffer.str().c_str()));
 sbuffer << "Server: " << NAME << "/" << VERSION << "\r\n";
 s_writeline(connection, sbuffer.str().c_str(), strlen(sbuffer.str().c_str()));
 s_writeline(connection, "Content-Type: application/json\r\n", 32);
 sbuffer << "Content-Length: " << strlen(content.c_str()) << "\r\n";
 s_writeline(connection, sbuffer.str().c_str(), strlen(sbuffer.str().c_str()));
 s_writeline(connection, "\r\n", 2);
 s_writeline(connection, content.c_str(), strlen(content.c_str()));

 return true;
}
<commit_msg>Improved the HTTP output a lot.<commit_after>/*
 * =====================================================================================
 *
 *       Filename:  requesthandler.cpp
 *
 *    Description:  Handle requests
 *
 *        Version:  1.0
 *        Created:  28/01/13 21:47:34
 *       Revision:  none
 *       Compiler:  g++
 *
 *         Author:  Daniel Bugl <Daniel.Bugl@touchlay.com>
 *   Organization:  TouchLay
 *
 * =====================================================================================
 */

// Headers
#include "requesthandler.h"

/* RequestHandler: Constructor */
RequestHandler::RequestHandler(int connection, char *cip) {
 // TODO: Create a blacklist for IPs
 clientip = cip;

 // Initialise request
 InitRequest(&request);

 // Handle request and check request type
 if (handle(connection) == true) {
  #ifdef DEBUG
  std::cout << "[DEBUG] [request     ] handle() returned true, continuing!" << std::endl;
  #endif
  if (request.type == HTTP) {
   #ifdef DEBUG
   std::cout << "[DEBUG] [request_http] This is an HTTP request." << std::endl;
   #endif
   if (request.status == 200) {
    #ifdef DEBUG
    std::cout << "[DEBUG] [request_http] Status 200, returning result." << std::endl;
    #endif
    if (parseJSON()) {
     API api = API(jRoot);
     #ifdef DEBUG
     std::cout << "[DEBUG] [request_api ] Got API result(" << strlen(api.result.c_str()) << "): " << api.result << std::endl;
     #endif
     outputHTTP(connection, &request, api.result.c_str());
    } else outputHTTP(connection, &request, "{\"type\": \"error\", \"msg\": \"Invalid JSON.\"}");
    #ifdef DEBUG
    std::cout << "[DEBUG] [request_http] Answered to request with HTTP." << std::endl;
    #endif
   } else {
    std::stringstream sbuffer;
    sbuffer << "{\"type\": \"error\", \"msg\": \"HTTP Error " << request.status << "\"}";
    outputHTTP(connection, &request, sbuffer.str());
   }
   usleep(REQUEST_TIMEOUT_SEND*1000000);
  } else if (request.type == TN) {
   #ifdef DEBUG
   std::cout << "[DEBUG] [request_tn  ] This is a TN request." << std::endl;
   #endif
   if (parseJSON()) {
    API api = API(jRoot);
    #ifdef DEBUG
    std::cout << "[DEBUG] [request_api ] Got API result(" << strlen(api.result.c_str()) << "): " << api.result << std::endl;
    #endif
    s_writeline(connection, api.result.c_str(), strlen(api.result.c_str()));
   } else s_writeline(connection, "{\"type\": \"error\", \"msg\": \"Invalid JSON.\"}", 41);
   #ifdef DEBUG
   std::cout << "[DEBUG] [request_tn  ] Answered to request with TN." << std::endl;
   usleep(REQUEST_TIMEOUT_SEND*1000000);
   #endif
  } else std::cout << "[WARN ] [request     ] Unknown request type, killing request." << std::endl;
 } else std::cout << "[WARN ] [request     ] Couldn't handle request, killing it." << std::endl;
}

/* parseJSON: JSON parser */
bool RequestHandler::parseJSON() {
 if (request.type == HTTP) memmove(request.resource, request.resource+1, strlen(request.resource)); // Remove / prefix from the GET request
 std::string data = decodeURI(request.resource);
 #ifdef DEBUG
 std::cout << "[DEBUG] [request_json] Got data: " << data << "\n";
 #endif
 if (!jReader.parse(data, jRoot, false)) {
  #ifdef DEBUG
  std::cout << "[DEBUG] [request_json] Invalid JSON (" << data << ")." << std::endl;
  #endif
  return false;
 }
 else return true;
}

/* ~RequestHandler: Destructor */
RequestHandler::~RequestHandler() {
 #ifdef DEBUG
 std::cout << "[DEBUG] [request     ] Destructed RequestHandler." << std::endl;
 #endif
}

/* InitRequest: Initialises the request data */
void RequestHandler::InitRequest(Request *request) {
 request->status = 200;
 request->method = UNSUPPORTED;
 request->resource = NULL;
 #ifdef DEBUG
 std::cout << "[DEBUG] [request     ] Initialised request." << std::endl;
 #endif
}

/* FreeRequest: Clear the request data */
void RequestHandler::FreeRequest(Request *request) {
 if (request->resource) delete request->resource;
 #ifdef DEBUG
 std::cout << "[DEBUG] [request     ] Free'd request." << std::endl;
 #endif
}

/* handle: Handle a request */
bool RequestHandler::handle(int connection) {
 char buffer[MAX_REQ_LINE] = {0};
 int rval;
 fd_set fds;
 struct timeval tv;

 // Timeout
 tv.tv_sec = REQUEST_TIMEOUT_RECV;
 tv.tv_usec = 0;

 do {
  // Reset FD
  FD_ZERO(&fds);
  FD_SET(connection, &fds);

  rval = select(connection+1, &fds, NULL, NULL, &tv); // Select from request

  if (rval < 0) std::cout << "[WARN ] [request     ] Couldn't select from request." << std::endl;
  else if (rval == 0) return false; // Timeout, kill request
  else {
   s_readline(connection, buffer, MAX_REQ_LINE - 1);

   #ifdef DEBUG
   std::cout << "[DEBUG] [request     ] Received buffer: " << buffer << std::endl;
   #endif

   if (buffer[0] == '{') {
    request.type = TN;
    request.resource = buffer;
    request.level = SIMPLE;
    return true;
   } else {
    request.type = HTTP;
    strim(buffer);
    char *buf = buffer;
    char *endptr = NULL;
    int len;
    if (!strncmp(buffer, "GET ", 4)) {
     request.method = GET;
     buf += 4;
    } else if (!strncmp(buffer, "HEAD ", 5)) {
     request.method = HEAD;
     buf += 5;
    } else {
     request.method = UNSUPPORTED;
     request.status = 501;
     return true;
    }

    while (*buf && isspace(*buf)) buf++; // Skip the start

    endptr = strchr(buf, ' ');
    if (endptr == NULL) len = strlen(buf);
    else len = endptr - buf;

    if (len == 0) {
     request.status = 400;
     return true;
    }

    request.resource = (char *)calloc(len + 1, sizeof(char));
    strncpy(request.resource, buf, len);

    request.level = SIMPLE;

    return true;
   }
  }
 } while (request.level != SIMPLE);
 return true; // Successfully processed
}

bool RequestHandler::outputHTTP(int connection, Request *request, std::string content) {
 std::stringstream sbuffer;

 if (request->status == 200) sbuffer << "HTTP/1.1 " << request->status << " OK\r\n";
 else if (request->status == 400) sbuffer << "HTTP/1.1 " << request->status << " Bad Request\r\n";
 else sbuffer << "HTTP/1.1 501 Not Implemented\r\n";
 s_writeline(connection, sbuffer.str().c_str(), strlen(sbuffer.str().c_str()));
 sbuffer.str(std::string());
 sbuffer << "Server: " << NAME << "/" << VERSION << "\r\n";
 s_writeline(connection, sbuffer.str().c_str(), strlen(sbuffer.str().c_str()));
 sbuffer.str(std::string());
 s_writeline(connection, "Content-Type: application/json\r\n", 32);
 sbuffer << "Content-Length: " << strlen(content.c_str()) << "\r\n";
 s_writeline(connection, sbuffer.str().c_str(), strlen(sbuffer.str().c_str()));
 sbuffer.str(std::string());
 s_writeline(connection, "\r\n", 2);
 s_writeline(connection, content.c_str(), strlen(content.c_str()));

 return true;
}
<|endoftext|>


<commit_before>76b48c6e-4b02-11e5-9a54-28cfe9171a43<commit_msg>Did ANOTHER thing<commit_after>76c22ae1-4b02-11e5-9f46-28cfe9171a43<|endoftext|>


<commit_before>8f15ba57-4b02-11e5-8237-28cfe9171a43<commit_msg>Stuff changed<commit_after>8f23f10c-4b02-11e5-a661-28cfe9171a43<|endoftext|>


<commit_before>/*****************************************************************************
 * main.cpp: ActiveX control for VLC
 *****************************************************************************
 * Copyright (C) 2005 the VideoLAN team
 *
 * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#include "plugin.h"
#include "utils.h"

#include <stdio.h>

#include <comcat.h>
#include <windows.h>
#include <shlwapi.h>

using namespace std;

#define COMPANY_STR "VideoLAN"
#define PROGRAM_STR "VLCPlugin"
#define DESCRIPTION "VideoLAN VLC ActiveX Plugin"

#define THREADING_MODEL "Apartment"
#define MISC_STATUS     "131473"

#define PROGID_STR COMPANY_STR"."PROGRAM_STR

#define GUID_STRLEN 39

/*
** MingW headers do not declare those
*/
extern const CATID CATID_SafeForInitializing;
extern const CATID CATID_SafeForScripting;

static LONG i_class_ref= 0;
static HINSTANCE h_instance= 0;

HMODULE DllGetModule()
{
    return h_instance;
};

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
{
    HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;

    *ppv = NULL;

    if( (CLSID_VLCPlugin == rclsid )
     || ( CLSID_VLCPlugin2 == rclsid) )
    {
        VLCPluginClass *plugin = new VLCPluginClass(&i_class_ref, h_instance, rclsid);
        hr = plugin->QueryInterface(riid, ppv);
        plugin->Release();
    }
    return hr;
};

STDAPI DllCanUnloadNow(VOID)
{
    return (0 == i_class_ref) ? S_OK: S_FALSE;
};

static inline HKEY keyCreate(HKEY parentKey, LPCSTR keyName)
{
    HKEY childKey;
    if( ERROR_SUCCESS == RegCreateKeyExA(parentKey, keyName, 0, NULL,
                REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &childKey, NULL) )
    {
        return childKey;
    }
    return NULL;
};

static inline HKEY keySet(HKEY hKey, LPCSTR valueName, const void *s, size_t len)
{
    if( NULL != hKey )
    {
        RegSetValueExA(hKey, valueName, 0, REG_SZ,
            (const BYTE*)s, len);
    }
    return hKey;
};

static inline HKEY keySetDef(HKEY hKey, const void *s, size_t len)
{
    return keySet(hKey, NULL, s, len);
};

static inline HKEY keySetDef(HKEY hKey, LPCSTR s)
{
    return keySetDef(hKey, s, strlen(s)+1);
};

static inline HKEY keyClose(HKEY hKey)
{
    if( NULL != hKey )
    {
        RegCloseKey(hKey);
    }
    return NULL;
};

static HRESULT UnregisterProgID(REFCLSID rclsid, unsigned int version)
{
    LPCSTR psz_CLSID = CStrFromGUID(rclsid);

    if( NULL == psz_CLSID )
        return E_OUTOFMEMORY;

    char progId[sizeof(PROGID_STR)+16];
    sprintf(progId, "%s.%u", PROGID_STR, version);

    SHDeleteKeyA(HKEY_CLASSES_ROOT, progId);

    HKEY hClsIDKey;
    if( ERROR_SUCCESS == RegOpenKeyExA(HKEY_CLASSES_ROOT, "CLSID", 0, KEY_WRITE, &hClsIDKey) )
    {
        SHDeleteKey(hClsIDKey, psz_CLSID);
        RegCloseKey(hClsIDKey);
    }
    CoTaskMemFree((void *)psz_CLSID);
};

STDAPI DllUnregisterServer(VOID)
{
    // unregister type lib from the registry
    UnRegisterTypeLib(LIBID_AXVLC, 1, 0, LOCALE_NEUTRAL, SYS_WIN32);

    // remove component categories we supports
    ICatRegister *pcr;
    if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr,
            NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {
        CATID implCategories[] = {
            CATID_Control,
            CATID_PersistsToPropertyBag,
            CATID_SafeForInitializing,
            CATID_SafeForScripting,
        };

        pcr->UnRegisterClassImplCategories(CLSID_VLCPlugin,
                sizeof(implCategories)/sizeof(CATID), implCategories);
        pcr->UnRegisterClassImplCategories(CLSID_VLCPlugin2,
                sizeof(implCategories)/sizeof(CATID), implCategories);
        pcr->Release();
    }

    SHDeleteKey(HKEY_CLASSES_ROOT, TEXT(PROGID_STR));

    UnregisterProgID(CLSID_VLCPlugin, 2);
    UnregisterProgID(CLSID_VLCPlugin2, 1);

    return S_OK;
};

static HRESULT RegisterClassID(HKEY hParent, REFCLSID rclsid, unsigned int version, BOOL isDefault, const char *path, size_t pathLen)
{
    char progId[sizeof(PROGID_STR)+16];
    sprintf(progId, "%s.%u", PROGID_STR, version);

    char description[sizeof(DESCRIPTION)+16];
    sprintf(description, "%s v%u", DESCRIPTION, version);

    HKEY hClassKey;
    {
        LPCSTR psz_CLSID = CStrFromGUID(rclsid);

        if( NULL == psz_CLSID )
            return E_OUTOFMEMORY;

        HKEY hProgKey = keyCreate(HKEY_CLASSES_ROOT, progId);
        if( NULL != hProgKey )
        {
            // default key value
            keySetDef(hProgKey, description);

            keyClose(keySetDef(keyCreate(hProgKey, "CLSID"),
                psz_CLSID,
                GUID_STRLEN));

            //hSubKey = keyClose(keyCreate(hBaseKey, "Insertable"));

            RegCloseKey(hProgKey);
        }
        if( isDefault )
        {
            hProgKey = keyCreate(HKEY_CLASSES_ROOT, PROGID_STR);
            if( NULL != hProgKey )
            {
                // default key value
                keySetDef(hProgKey, description);

                keyClose(keySetDef(keyCreate(hProgKey, "CLSID"),
                    psz_CLSID,
                    GUID_STRLEN));

                keyClose(keySetDef(keyCreate(hProgKey, "CurVer"),
                    progId));
            }
        }
        hClassKey = keyCreate(hParent, psz_CLSID);
        CoTaskMemFree((void *)psz_CLSID);
    }
    if( NULL != hClassKey )
    {
        // default key value
        keySetDef(hClassKey, description);

        // Control key value
        keyClose(keyCreate(hClassKey, "Control"));

        // Insertable key value
        //keyClose(keyCreate(hClassKey, "Insertable"));

        // ToolboxBitmap32 key value
        {
            char iconPath[pathLen+3];
            memcpy(iconPath, path, pathLen);
            strcpy(iconPath+pathLen, ",1");
            keyClose(keySetDef(keyCreate(hClassKey,
                "ToolboxBitmap32"),
                iconPath, sizeof(iconPath)));
        }

#ifdef BUILD_LOCALSERVER
        // LocalServer32 key value
        keyClose(keySetDef(keyCreate(hClassKey,
            "LocalServer32", path, pathLen+1)));
#else
        // InprocServer32 key value
        {
            HKEY hSubKey = keySetDef(keyCreate(hClassKey,
                "InprocServer32"),
                path, pathLen+1);
            keySet(hSubKey,
                "ThreadingModel",
                THREADING_MODEL, sizeof(THREADING_MODEL));
            keyClose(hSubKey);
        }
#endif

        // MiscStatus key value
        keyClose(keySetDef(keyCreate(hClassKey,
            "MiscStatus\\1"),
            MISC_STATUS, sizeof(MISC_STATUS)));

        // Programmable key value
        keyClose(keyCreate(hClassKey, "Programmable"));

        // ProgID key value
        keyClose(keySetDef(keyCreate(hClassKey,
            TEXT("ProgID")),
            progId));

        // VersionIndependentProgID key value
        keyClose(keySetDef(keyCreate(hClassKey,
            "VersionIndependentProgID"),
            PROGID_STR, sizeof(PROGID_STR)));

        // Version key value
        keyClose(keySetDef(keyCreate(hClassKey,
            "Version"),
            "1.0"));

        // TypeLib key value
        LPCSTR psz_LIBID = CStrFromGUID(LIBID_AXVLC);
        if( NULL != psz_LIBID )
        {
            keyClose(keySetDef(keyCreate(hClassKey,
                    "TypeLib"),
                    psz_LIBID, GUID_STRLEN));
            CoTaskMemFree((void *)psz_LIBID);
        }
        RegCloseKey(hClassKey);
    }
    return S_OK;
}

STDAPI DllRegisterServer(VOID)
{
    DllUnregisterServer();

    char DllPath[MAX_PATH];
    DWORD DllPathLen=GetModuleFileNameA(h_instance, DllPath, sizeof(DllPath)) ;
	if( 0 == DllPathLen )
        return E_UNEXPECTED;

    HKEY hBaseKey;

    if( ERROR_SUCCESS != RegOpenKeyExA(HKEY_CLASSES_ROOT, "CLSID", 0, KEY_CREATE_SUB_KEY, &hBaseKey) )
        return SELFREG_E_CLASS;

    RegisterClassID(hBaseKey, CLSID_VLCPlugin, 1, FALSE, DllPath, DllPathLen);
    RegisterClassID(hBaseKey, CLSID_VLCPlugin2, 2, TRUE, DllPath, DllPathLen);

    RegCloseKey(hBaseKey);

    // indicate which component categories we support
    ICatRegister *pcr;
    if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr,
            NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {
        CATID implCategories[] = {
            CATID_Control,
            CATID_PersistsToPropertyBag,
            CATID_SafeForInitializing,
            CATID_SafeForScripting,
        };

        pcr->RegisterClassImplCategories(CLSID_VLCPlugin,
                sizeof(implCategories)/sizeof(CATID), implCategories);
        pcr->RegisterClassImplCategories(CLSID_VLCPlugin2,
                sizeof(implCategories)/sizeof(CATID), implCategories);
        pcr->Release();
    }

    // register type lib into the registry
    ITypeLib *typeLib;

#ifdef BUILD_LOCALSERVER
    // replace .exe by .tlb
    strcpy(DllPath+DllPathLen-4, ".tlb");
#endif

#ifndef OLE2ANSI
    size_t typeLibPathLen = MultiByteToWideChar(CP_ACP, 0, DllPath, -1, NULL, 0);
    if( typeLibPathLen > 0 )
    {
        LPOLESTR typeLibPath = (LPOLESTR)CoTaskMemAlloc(typeLibPathLen*sizeof(wchar_t));
        MultiByteToWideChar(CP_ACP, 0, DllPath, DllPathLen, typeLibPath, typeLibPathLen);
        if( FAILED(LoadTypeLibEx(typeLibPath, REGKIND_REGISTER, &typeLib)) )
#ifndef BUILD_LOCALSERVER
            return SELFREG_E_TYPELIB;
        typeLib->Release();
#endif
        CoTaskMemFree((void *)typeLibPath);
    }
#else
    if( FAILED(LoadTypeLibEx((LPOLESTR)DllPath, REGKIND_REGISTER, &typeLib)) )
        return SELFREG_E_TYPELIB;
    typeLib->Release();
#endif

    return S_OK;
};

#ifdef BUILD_LOCALSERVER

/*
** easier to debug an application than a DLL on cygwin GDB :)
*/
#include <iostream>

STDAPI_(int) WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
{
    MSG msg;

    if( FAILED(OleInitialize(NULL)) )
    {
        cerr << "cannot initialize OLE" << endl;
        return 1;
    }

    h_instance = hInst;

    if( FAILED(DllRegisterServer()) )
    {
        cerr << "cannot register Local Server" << endl;
        return 1;
    }

    IUnknown *classProc = NULL;

    if( FAILED(DllGetClassObject(CLSID_VLCPlugin, IID_IUnknown, (LPVOID *)&classProc)) )
        return 0;

    DWORD dwRegisterClassObject;
    DWORD dwRegisterClassObject2;

    if( FAILED(CoRegisterClassObject(CLSID_VLCPlugin, classProc,
        CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwRegisterClassObject)) )
        return 0;

    DWORD dwRegisterActiveObject;

    if( FAILED(RegisterActiveObject(classProc, CLSID_VLCPlugin,
                    ACTIVEOBJECT_WEAK, &dwRegisterActiveObject)) )
        return 0;

    if( FAILED(RegisterActiveObject(classProc, CLSID_VLCPlugin2,
                    ACTIVEOBJECT_WEAK, &dwRegisterActiveObject2)) )
        return 0;

    classProc->Release();

    /*
    * Polling messages from event queue
    */
    while( S_FALSE == DllCanUnloadNow() )
    {
        while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
        {
            if( msg.message == WM_QUIT )
                break;  // break out PeekMessage loop

            /*if(TranslateAccelerator(ghwndApp, ghAccel, &msg))
                continue;*/

            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        if(msg.message == WM_QUIT)
            break;  // break out main loop

        WaitMessage();
    }

    if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject, NULL)) )
        CoRevokeClassObject(dwRegisterClassObject);

    if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject2, NULL)) )
        CoRevokeClassObject(dwRegisterClassObject2);

    // Reached on WM_QUIT message
    OleUninitialize();
    return ((int) msg.wParam);
};

#else

STDAPI_(BOOL) DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpReserved )
{
    switch( fdwReason )
    {
        case DLL_PROCESS_ATTACH:
            h_instance = (HINSTANCE)hModule;
            break;

        default:
            break;
    }
    return TRUE;
};

#endif

<commit_msg>Remove excess whitespace<commit_after>/*****************************************************************************
 * main.cpp: ActiveX control for VLC
 *****************************************************************************
 * Copyright (C) 2005 the VideoLAN team
 *
 * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#include "plugin.h"
#include "utils.h"

#include <stdio.h>

#include <comcat.h>
#include <windows.h>
#include <shlwapi.h>

using namespace std;

#define COMPANY_STR "VideoLAN"
#define PROGRAM_STR "VLCPlugin"
#define DESCRIPTION "VideoLAN VLC ActiveX Plugin"

#define THREADING_MODEL "Apartment"
#define MISC_STATUS     "131473"

#define PROGID_STR COMPANY_STR"."PROGRAM_STR

#define GUID_STRLEN 39

/*
** MingW headers do not declare those
*/
extern const CATID CATID_SafeForInitializing;
extern const CATID CATID_SafeForScripting;

static LONG i_class_ref= 0;
static HINSTANCE h_instance= 0;

HMODULE DllGetModule()
{
    return h_instance;
};

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
{
    HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;

    *ppv = NULL;

    if( (CLSID_VLCPlugin == rclsid )
     || ( CLSID_VLCPlugin2 == rclsid) )
    {
        VLCPluginClass *plugin = new VLCPluginClass(&i_class_ref, h_instance, rclsid);
        hr = plugin->QueryInterface(riid, ppv);
        plugin->Release();
    }
    return hr;
};

STDAPI DllCanUnloadNow(VOID)
{
    return (0 == i_class_ref) ? S_OK: S_FALSE;
};

static inline HKEY keyCreate(HKEY parentKey, LPCSTR keyName)
{
    HKEY childKey;
    if( ERROR_SUCCESS == RegCreateKeyExA(parentKey, keyName, 0, NULL,
                REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &childKey, NULL) )
    {
        return childKey;
    }
    return NULL;
};

static inline HKEY keySet(HKEY hKey, LPCSTR valueName, const void *s, size_t len)
{
    if( NULL != hKey )
    {
        RegSetValueExA(hKey, valueName, 0, REG_SZ,
            (const BYTE*)s, len);
    }
    return hKey;
};

static inline HKEY keySetDef(HKEY hKey, const void *s, size_t len)
{
    return keySet(hKey, NULL, s, len);
};

static inline HKEY keySetDef(HKEY hKey, LPCSTR s)
{
    return keySetDef(hKey, s, strlen(s)+1);
};

static inline HKEY keyClose(HKEY hKey)
{
    if( NULL != hKey )
    {
        RegCloseKey(hKey);
    }
    return NULL;
};

static HRESULT UnregisterProgID(REFCLSID rclsid, unsigned int version)
{
    LPCSTR psz_CLSID = CStrFromGUID(rclsid);

    if( NULL == psz_CLSID )
        return E_OUTOFMEMORY;

    char progId[sizeof(PROGID_STR)+16];
    sprintf(progId, "%s.%u", PROGID_STR, version);

    SHDeleteKeyA(HKEY_CLASSES_ROOT, progId);

    HKEY hClsIDKey;
    if( ERROR_SUCCESS == RegOpenKeyExA(HKEY_CLASSES_ROOT, "CLSID", 0, KEY_WRITE, &hClsIDKey) )
    {
        SHDeleteKey(hClsIDKey, psz_CLSID);
        RegCloseKey(hClsIDKey);
    }
    CoTaskMemFree((void *)psz_CLSID);
};

STDAPI DllUnregisterServer(VOID)
{
    // unregister type lib from the registry
    UnRegisterTypeLib(LIBID_AXVLC, 1, 0, LOCALE_NEUTRAL, SYS_WIN32);

    // remove component categories we supports
    ICatRegister *pcr;
    if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr,
            NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {
        CATID implCategories[] = {
            CATID_Control,
            CATID_PersistsToPropertyBag,
            CATID_SafeForInitializing,
            CATID_SafeForScripting,
        };

        pcr->UnRegisterClassImplCategories(CLSID_VLCPlugin,
                sizeof(implCategories)/sizeof(CATID), implCategories);
        pcr->UnRegisterClassImplCategories(CLSID_VLCPlugin2,
                sizeof(implCategories)/sizeof(CATID), implCategories);
        pcr->Release();
    }

    SHDeleteKey(HKEY_CLASSES_ROOT, TEXT(PROGID_STR));

    UnregisterProgID(CLSID_VLCPlugin, 2);
    UnregisterProgID(CLSID_VLCPlugin2, 1);

    return S_OK;
};

static HRESULT RegisterClassID(HKEY hParent, REFCLSID rclsid, unsigned int version, BOOL isDefault, const char *path, size_t pathLen)
{
    char progId[sizeof(PROGID_STR)+16];
    sprintf(progId, "%s.%u", PROGID_STR, version);

    char description[sizeof(DESCRIPTION)+16];
    sprintf(description, "%s v%u", DESCRIPTION, version);

    HKEY hClassKey;
    {
        LPCSTR psz_CLSID = CStrFromGUID(rclsid);

        if( NULL == psz_CLSID )
            return E_OUTOFMEMORY;

        HKEY hProgKey = keyCreate(HKEY_CLASSES_ROOT, progId);
        if( NULL != hProgKey )
        {
            // default key value
            keySetDef(hProgKey, description);

            keyClose(keySetDef(keyCreate(hProgKey, "CLSID"),
                psz_CLSID,
                GUID_STRLEN));

            //hSubKey = keyClose(keyCreate(hBaseKey, "Insertable"));

            RegCloseKey(hProgKey);
        }
        if( isDefault )
        {
            hProgKey = keyCreate(HKEY_CLASSES_ROOT, PROGID_STR);
            if( NULL != hProgKey )
            {
                // default key value
                keySetDef(hProgKey, description);

                keyClose(keySetDef(keyCreate(hProgKey, "CLSID"),
                    psz_CLSID,
                    GUID_STRLEN));

                keyClose(keySetDef(keyCreate(hProgKey, "CurVer"),
                    progId));
            }
        }
        hClassKey = keyCreate(hParent, psz_CLSID);
        CoTaskMemFree((void *)psz_CLSID);
    }
    if( NULL != hClassKey )
    {
        // default key value
        keySetDef(hClassKey, description);

        // Control key value
        keyClose(keyCreate(hClassKey, "Control"));

        // Insertable key value
        //keyClose(keyCreate(hClassKey, "Insertable"));

        // ToolboxBitmap32 key value
        {
            char iconPath[pathLen+3];
            memcpy(iconPath, path, pathLen);
            strcpy(iconPath+pathLen, ",1");
            keyClose(keySetDef(keyCreate(hClassKey,
                "ToolboxBitmap32"),
                iconPath, sizeof(iconPath)));
        }

#ifdef BUILD_LOCALSERVER
        // LocalServer32 key value
        keyClose(keySetDef(keyCreate(hClassKey,
            "LocalServer32", path, pathLen+1)));
#else
        // InprocServer32 key value
        {
            HKEY hSubKey = keySetDef(keyCreate(hClassKey,
                "InprocServer32"),
                path, pathLen+1);
            keySet(hSubKey,
                "ThreadingModel",
                THREADING_MODEL, sizeof(THREADING_MODEL));
            keyClose(hSubKey);
        }
#endif

        // MiscStatus key value
        keyClose(keySetDef(keyCreate(hClassKey,
            "MiscStatus\\1"),
            MISC_STATUS, sizeof(MISC_STATUS)));

        // Programmable key value
        keyClose(keyCreate(hClassKey, "Programmable"));

        // ProgID key value
        keyClose(keySetDef(keyCreate(hClassKey,
            TEXT("ProgID")),
            progId));

        // VersionIndependentProgID key value
        keyClose(keySetDef(keyCreate(hClassKey,
            "VersionIndependentProgID"),
            PROGID_STR, sizeof(PROGID_STR)));

        // Version key value
        keyClose(keySetDef(keyCreate(hClassKey,
            "Version"),
            "1.0"));

        // TypeLib key value
        LPCSTR psz_LIBID = CStrFromGUID(LIBID_AXVLC);
        if( NULL != psz_LIBID )
        {
            keyClose(keySetDef(keyCreate(hClassKey,
                    "TypeLib"),
                    psz_LIBID, GUID_STRLEN));
            CoTaskMemFree((void *)psz_LIBID);
        }
        RegCloseKey(hClassKey);
    }
    return S_OK;
}

STDAPI DllRegisterServer(VOID)
{
    DllUnregisterServer();

    char DllPath[MAX_PATH];
    DWORD DllPathLen=GetModuleFileNameA(h_instance, DllPath, sizeof(DllPath)) ;
    if( 0 == DllPathLen )
        return E_UNEXPECTED;

    HKEY hBaseKey;

    if( ERROR_SUCCESS != RegOpenKeyExA(HKEY_CLASSES_ROOT, "CLSID", 0, KEY_CREATE_SUB_KEY, &hBaseKey) )
        return SELFREG_E_CLASS;

    RegisterClassID(hBaseKey, CLSID_VLCPlugin, 1, FALSE, DllPath, DllPathLen);
    RegisterClassID(hBaseKey, CLSID_VLCPlugin2, 2, TRUE, DllPath, DllPathLen);

    RegCloseKey(hBaseKey);

    // indicate which component categories we support
    ICatRegister *pcr;
    if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr,
            NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {
        CATID implCategories[] = {
            CATID_Control,
            CATID_PersistsToPropertyBag,
            CATID_SafeForInitializing,
            CATID_SafeForScripting,
        };

        pcr->RegisterClassImplCategories(CLSID_VLCPlugin,
                sizeof(implCategories)/sizeof(CATID), implCategories);
        pcr->RegisterClassImplCategories(CLSID_VLCPlugin2,
                sizeof(implCategories)/sizeof(CATID), implCategories);
        pcr->Release();
    }

    // register type lib into the registry
    ITypeLib *typeLib;

#ifdef BUILD_LOCALSERVER
    // replace .exe by .tlb
    strcpy(DllPath+DllPathLen-4, ".tlb");
#endif

#ifndef OLE2ANSI
    size_t typeLibPathLen = MultiByteToWideChar(CP_ACP, 0, DllPath, -1, NULL, 0);
    if( typeLibPathLen > 0 )
    {
        LPOLESTR typeLibPath = (LPOLESTR)CoTaskMemAlloc(typeLibPathLen*sizeof(wchar_t));
        MultiByteToWideChar(CP_ACP, 0, DllPath, DllPathLen, typeLibPath, typeLibPathLen);
        if( FAILED(LoadTypeLibEx(typeLibPath, REGKIND_REGISTER, &typeLib)) )
#ifndef BUILD_LOCALSERVER
            return SELFREG_E_TYPELIB;
        typeLib->Release();
#endif
        CoTaskMemFree((void *)typeLibPath);
    }
#else
    if( FAILED(LoadTypeLibEx((LPOLESTR)DllPath, REGKIND_REGISTER, &typeLib)) )
        return SELFREG_E_TYPELIB;
    typeLib->Release();
#endif

    return S_OK;
};

#ifdef BUILD_LOCALSERVER

/*
** easier to debug an application than a DLL on cygwin GDB :)
*/
#include <iostream>

STDAPI_(int) WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
{
    MSG msg;

    if( FAILED(OleInitialize(NULL)) )
    {
        cerr << "cannot initialize OLE" << endl;
        return 1;
    }

    h_instance = hInst;

    if( FAILED(DllRegisterServer()) )
    {
        cerr << "cannot register Local Server" << endl;
        return 1;
    }

    IUnknown *classProc = NULL;

    if( FAILED(DllGetClassObject(CLSID_VLCPlugin, IID_IUnknown, (LPVOID *)&classProc)) )
        return 0;

    DWORD dwRegisterClassObject;
    DWORD dwRegisterClassObject2;

    if( FAILED(CoRegisterClassObject(CLSID_VLCPlugin, classProc,
        CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwRegisterClassObject)) )
        return 0;

    DWORD dwRegisterActiveObject;

    if( FAILED(RegisterActiveObject(classProc, CLSID_VLCPlugin,
                    ACTIVEOBJECT_WEAK, &dwRegisterActiveObject)) )
        return 0;

    if( FAILED(RegisterActiveObject(classProc, CLSID_VLCPlugin2,
                    ACTIVEOBJECT_WEAK, &dwRegisterActiveObject2)) )
        return 0;

    classProc->Release();

    /*
    * Polling messages from event queue
    */
    while( S_FALSE == DllCanUnloadNow() )
    {
        while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
        {
            if( msg.message == WM_QUIT )
                break;  // break out PeekMessage loop

            /*if(TranslateAccelerator(ghwndApp, ghAccel, &msg))
                continue;*/

            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        if(msg.message == WM_QUIT)
            break;  // break out main loop

        WaitMessage();
    }

    if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject, NULL)) )
        CoRevokeClassObject(dwRegisterClassObject);

    if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject2, NULL)) )
        CoRevokeClassObject(dwRegisterClassObject2);

    // Reached on WM_QUIT message
    OleUninitialize();
    return ((int) msg.wParam);
};

#else

STDAPI_(BOOL) DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpReserved )
{
    switch( fdwReason )
    {
        case DLL_PROCESS_ATTACH:
            h_instance = (HINSTANCE)hModule;
            break;

        default:
            break;
    }
    return TRUE;
};

#endif

<|endoftext|>


<commit_before>8c8d5097-4b02-11e5-a809-28cfe9171a43<commit_msg>Made changes so it will hopefully compile by the next commit<commit_after>8c9b6759-4b02-11e5-b647-28cfe9171a43<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////
// main.cpp -- Test Main
// Date: Wed Nov 27 23:07:19 2013
///////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <assert.h>

#include <sys/stat.h>

#include "glue.hpp"
#include "utils.hpp"
#include "ansi-c-yacc.hpp"
#include "comp.hpp"
#include "config.hpp"

#include <iostream>
#include <istream>
#include <sstream>

extern char *optarg;
extern int optind;
extern int optopt;
extern int opterr;
extern int optreset;

static void
usage(const char *cmd) {
	std::cout
		<< "Usage: " << cmd << "[-d] [-g opt] [-Ddefine] [-I path] [-p] [-h]\n"
		<< "where:\n"
		<< "  -d            Enables lexical/yacc debug output\n"
		<< "  -y            Enable dump of yacc nodes\n"
		<< "  -g opt        Pass 'opt' to gcc\n"
		<< "  -D define     gcc macro declare option\n"
		<< "  -I path       gcc include path\n"
		<< "  -p            Just show platform details and exit\n"
		<< "  -h            This help info and exit.\n";
}

int
main(int argc,char **argv) {
	std::stringstream opt_gcc;
	std::string platform, version, machine;
	bool opt_show_platform = false;
	char optch;
	extern int yydebug;

	config.debug = false;

	while ( (optch = getopt(argc,argv,"dyI:D:g:ph")) != -1) {
		switch ( optch ) {
		case 'd' :
			yydebug = 1;
			config.debug = true;
			break;
		case 'y' :
			yacc_dump = 1;
			break;
		case 'g' :
			opt_gcc << optarg << " ";
			break;
		case 'D' :
			opt_gcc << "-D" << optarg << " ";
			break;
		case 'I' :
			opt_gcc << "-I" << optarg << " ";
			break;
		case 'p' :
			opt_show_platform = true;
			break;
		case 'h' :
		default:
			usage(argv[0]);
			exit(optch == 'h' ? 0 : 1);
		}
        }

        config.gcc_options = opt_gcc.str();

	platform = uts_platform();
	version = uts_version();
	machine = uts_machine();

	std::cout
		<< "Platform:    " << platform << "\n"
		<< "Machine:     " << machine << "\n"
		<< "Version:     " << version << "\n"
		<< "gcc options: " << config.gcc_options << "\n";

	if ( opt_show_platform )
		exit(0);

	loadconfig();

	system("rm -fr ./staging");
	mkdir("./staging",0777);

	//////////////////////////////////////////////////////////////
	// Copy out canned portions of code to staging directory
	//////////////////////////////////////////////////////////////
	{
		for ( auto it=config.copies.begin(); it != config.copies.end(); ++it ) {
			const std::string filename = *it;
			std::stringstream ss;

			ss << "cp " << filename << " ./staging/.";
			const std::string cmd = ss.str();
			system(cmd.c_str());
		}
	}

	comp_macros();
	comp_types();
	comp_systypes();

	emit_basic_types();
	emit_sys_types();
	emit_macros();
	emit_structs();
	emit_section2();

	system("cat ./staging/????.ads >posix.ads");
	system("cat ./staging/????.adb >posix.adb");

	{
		std::fstream mktests;
		int count = 0;

		mktests.open("Makefile.tests",std::fstream::out);

		mktests << "# Makefile.tests - generated file\n\n"
			<< "test:\ttests\n"
			<< "tests:\t";

		for ( auto it=config.tests.begin(); it != config.tests.end(); ++it ) {
			int testno = *it;

			mktests << "t";
			mktests.width(4);
			mktests.fill('0');
			mktests << testno << " ";
			if ( ++count % 10 == 0 )
				mktests << "\\\n";
		}

		mktests << "\n";
	}
}

// End main.cpp
<commit_msg>Modified to invoke the tests<commit_after>//////////////////////////////////////////////////////////////////////
// main.cpp -- Test Main
// Date: Wed Nov 27 23:07:19 2013
///////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <assert.h>

#include <sys/stat.h>

#include "glue.hpp"
#include "utils.hpp"
#include "ansi-c-yacc.hpp"
#include "comp.hpp"
#include "config.hpp"

#include <iostream>
#include <istream>
#include <sstream>

extern char *optarg;
extern int optind;
extern int optopt;
extern int opterr;
extern int optreset;

static void
usage(const char *cmd) {
	std::cout
		<< "Usage: " << cmd << "[-d] [-g opt] [-Ddefine] [-I path] [-p] [-h]\n"
		<< "where:\n"
		<< "  -d            Enables lexical/yacc debug output\n"
		<< "  -y            Enable dump of yacc nodes\n"
		<< "  -g opt        Pass 'opt' to gcc\n"
		<< "  -D define     gcc macro declare option\n"
		<< "  -I path       gcc include path\n"
		<< "  -p            Just show platform details and exit\n"
		<< "  -h            This help info and exit.\n";
}

int
main(int argc,char **argv) {
	std::stringstream opt_gcc;
	std::string platform, version, machine;
	bool opt_show_platform = false;
	char optch;
	extern int yydebug;

	config.debug = false;

	while ( (optch = getopt(argc,argv,"dyI:D:g:ph")) != -1) {
		switch ( optch ) {
		case 'd' :
			yydebug = 1;
			config.debug = true;
			break;
		case 'y' :
			yacc_dump = 1;
			break;
		case 'g' :
			opt_gcc << optarg << " ";
			break;
		case 'D' :
			opt_gcc << "-D" << optarg << " ";
			break;
		case 'I' :
			opt_gcc << "-I" << optarg << " ";
			break;
		case 'p' :
			opt_show_platform = true;
			break;
		case 'h' :
		default:
			usage(argv[0]);
			exit(optch == 'h' ? 0 : 1);
		}
        }

        config.gcc_options = opt_gcc.str();

	platform = uts_platform();
	version = uts_version();
	machine = uts_machine();

	std::cout
		<< "Platform:    " << platform << "\n"
		<< "Machine:     " << machine << "\n"
		<< "Version:     " << version << "\n"
		<< "gcc options: " << config.gcc_options << "\n";

	if ( opt_show_platform )
		exit(0);

	loadconfig();

	system("rm -fr ./staging");
	mkdir("./staging",0777);

	//////////////////////////////////////////////////////////////
	// Copy out canned portions of code to staging directory
	//////////////////////////////////////////////////////////////
	{
		for ( auto it=config.copies.begin(); it != config.copies.end(); ++it ) {
			const std::string filename = *it;
			std::stringstream ss;

			ss << "cp " << filename << " ./staging/.";
			const std::string cmd = ss.str();
			system(cmd.c_str());
		}
	}

	comp_macros();
	comp_types();
	comp_systypes();

	emit_basic_types();
	emit_sys_types();
	emit_macros();
	emit_structs();
	emit_section2();

	system("cat ./staging/????.ads >posix.ads");
	system("cat ./staging/????.adb >posix.adb");

	{
		std::fstream mktests;
		int count = 0;

		mktests.open("Makefile.tests",std::fstream::out);

		mktests << "# Makefile.tests - generated file\n\n"
			<< "test:\ttests\n"
			<< "tests:\t";

		for ( auto it=config.tests.begin(); it != config.tests.end(); ++it ) {
			int testno = *it;

			mktests << "t";
			mktests.width(4);
			mktests.fill('0');
			mktests << testno << " ";
			if ( ++count % 10 == 0 )
				mktests << "\\\n";
		}

		mktests << "\n";

		for ( auto it=config.tests.begin(); it != config.tests.end(); ++it ) {
			int testno = *it;

			mktests << "\t./t";
			mktests.width(4);
			mktests.fill('0');
			mktests << testno << "\n";
		}
	}
}

// End main.cpp
<|endoftext|>


<commit_before>#include <bits/stdc++.h>
using namespace std;

#define MAXN    100005
#define clip(X) min(X,10000)

// IMPLEMENTACAO/TESTES
// antes, procurar formulas menores nas maiores, mais ou menos R² * d(phi)
// dp para otimizar o renaming restringindo o nro maximo de literais
// procurar um benchmark
// adaptar entrada para o benchmark
// adaptar saida para algum provador, colocando em CNF

// MONOGRAFIA
// colocar exemplo 3.2

// formula
enum {CONJ=0,DISJ,IMPL,EQUI,NEGA,ATOM};
struct Vertex {
  char type;
  int literal;
  int up;
  vector<int> down;
  int p;
  Vertex() : p(1) {}
} G[MAXN];
int V = 0;

// create tree parsing formula from string
// first: tree
// second: number of literals
pair<vector<Vertex>,int> parse(string phi) {
  // check
  auto isvarsym = [](char c) {
    return
      ('0' <= c && c <= '9') ||
      ('a' <= c && c <= 'z') ||
      ('A' <= c && c <= 'Z')
    ;
  };

  vector<Vertex> ret(1);
  ret.back().type = CONJ;
  ret.back().up = 0;
  stack<int> S;
  S.push(0);
  map<string,int> id;
  int nextlit = 1;
  for (int i = 0; i < phi.size(); i++) {
    char c = phi[i];
    if (c == ' ' || c == '\t') continue;
    else if (c == '&') ret[S.top()].type = CONJ;
    else if (c == '|') ret[S.top()].type = DISJ;
    else if (c == '=') { ret[S.top()].type = IMPL; i++; }
    else if (c == '<') { ret[S.top()].type = EQUI; i += 2; }
    else if (c == '(' || c == '~') {
      S.push(ret.size());
      ret.emplace_back();
      ret.back().type = (c == '(' ? CONJ : NEGA);
    }
    else if (c == ')') {
      int u = S.top();
      S.pop();
      ret[u].up = S.top();
      ret[S.top()].down.push_back(u);
    }
    else { // literal
      string tmp = {phi[i]};
      while (i+1 < phi.size() && isvarsym(phi[i+1])) tmp += phi[++i];
      int& lit = id[tmp];
      if (!lit) lit = nextlit++;
      ret[S.top()].down.push_back(ret.size());
      ret.emplace_back();
      ret.back().type = ATOM;
      ret.back().literal = lit;
      ret.back().up = S.top();
      if (ret[S.top()].type == NEGA) { phi[i] = ')'; i--; }
    }
  }
  return make_pair(ret,id.size());
}

void nnf(vector<Vertex>& T) {
  // copy tree rooted at u
  function<int(int)> copy = [&](int u) {
    int nu = T.size(); T.emplace_back();
    T[nu].type = T[u].type;
    T[nu].literal = T[u].literal;
    for (int v : T[u].down) {
      int tmp = copy(v);
      T[tmp].up = nu;
      T[nu].down.push_back(tmp);
    }
    return nu;
  };

  // remove implications and equivalences
  function<void(int)> dfs1 = [&](int u) {
    if (T[u].type == IMPL) {
      T[u].type = DISJ;
      int v = T[u].down.front();
      int negi = T.size(); T.emplace_back();
      T[negi].type = NEGA;
      T[u].down.front() = negi;
      T[negi].up = u;
      T[negi].down.push_back(v);
      T[v].up = negi;
    }
    else if (T[u].type == EQUI) {
      auto f = [&](int a, int b) {
        int impi = T.size(); T.emplace_back();
        T[impi].type = IMPL;
        T[u].down.push_back(impi);
        T[impi].up = u;
        T[impi].down.push_back(a), T[impi].down.push_back(b);
        T[a].up = impi, T[b].up = impi;
      };
      T[u].type = CONJ;
      int a = T[u].down.front(),  b = T[u].down.back();
      int c = copy(b),            d = copy(a);
      T[u].down.clear();
      f(a,b);
      f(c,d);
    }
    for (int v : T[u].down) dfs1(v);
  };
  dfs1(0);

  // remove negations
  function<void(int,bool)> dfs2 = [&](int u, bool neg) {
    if (!neg) {
      if (T[u].type == NEGA) {
        auto& phi1 = T[T[u].down.front()];
        if (phi1.type == NEGA) {
          auto& phi2 = T[phi1.down.front()];
          T[u].type = phi2.type;
          T[u].literal = phi2.literal;
          T[u].down = phi2.down;
          for (int v : T[u].down) T[v].up = u;
          phi1.type = CONJ, phi2.type = CONJ; // removing phi1 and phi2
        }
        else if (phi1.type != ATOM) { // CONJ or DISJ
          T[u].type = (phi1.type == CONJ ? DISJ : CONJ);
          T[u].down = phi1.down;
          for (int v : T[u].down) T[v].up = u;
          phi1.type = CONJ; // removing phi1
          neg = true;
        }
      }
    }
    else {
      if (T[u].type == NEGA) {
        auto& phi1 = T[T[u].down.front()];
        T[u].type = phi1.type;
        T[u].literal = phi1.literal;
        T[u].down = phi1.down;
        for (int v : T[u].down) T[v].up = u;
        phi1.type = CONJ; // removing phi1
        neg = false;
      }
      else if (T[u].type != ATOM) { // CONJ or DISJ
        T[u].type = (T[u].type == CONJ ? DISJ : CONJ);
      }
      else { // ATOM
        int atmi = copy(u);
        T[u].type = NEGA;
        T[u].down.push_back(atmi);
        T[atmi].up = u;
        neg = false;
      }
    }
    for (int v : T[u].down) dfs2(v,neg);
  };
  dfs2(0,false);
}

// build DAG from tree T
void build(const vector<Vertex>& T) {
  map<int,int> lit_newu;
  map<int,multiset<int>> oldp_newc;
  V = 1;

  // create vertices for literals
  for (int i = 0; i < T.size(); i++) if (T[i].type == ATOM) {
    auto& phi = T[i];
    int& u = lit_newu[phi.literal];
    if (!u) {
      u = ++V;
      G[u].type = ATOM;
      G[u].literal = phi.literal;
    }
    oldp_newc[phi.up].insert(u);
  }

  // search tree bottom-up to create vertices for subformulas
  for (map<multiset<int>,int> newc_newp; !oldp_newc.empty();) {
    list<pair<int,int>> tmp;
    for (auto kv = oldp_newc.begin(); kv != oldp_newc.end();) {
      auto& phi = T[kv->first];
      if (kv->second.size() < phi.down.size()) { kv++; continue; }
      int& u = newc_newp[kv->second];
      if (!u) {
        u = (phi.up != kv->first) ? ++V : 1;
        G[u].type = phi.type;
        for (int v : kv->second) G[u].down.push_back(v);
      }
      if (phi.up != kv->first) tmp.emplace_back(phi.up,u);
      oldp_newc.erase(kv++);
    }
    for (auto& kv : tmp) oldp_newc[kv.first].insert(kv.second);
  }
}

// position of u in a reverse toposort
int pos(int u) {
  static int next = 1, dp[MAXN] = {};
  int& ans = dp[u];
  if (ans) return ans;
  for (int v : G[u].down) pos(v);
  return ans = next++;
}

// p(phi(u))
int p(int u) {
  static int dp[MAXN] = {};
  int& ans = dp[u];
  if (ans) return ans;
  switch (G[u].type) {
    case CONJ: ans = 0; for (int v : G[u].down) ans = clip(ans+p(v)); break;
    case DISJ: ans = 1; for (int v : G[u].down) ans = clip(ans*p(v)); break;
    default:   ans = 1; break;
  }
  return ans;
}

// Boy de la Tour's top-down renaming
vector<int> R;
int nextR;
void R_rec(int u, int a) {
  auto& phi = G[u];
  if (phi.p == 1) return;

  // check renaming condition
  bool renamed = false;
  if (a > 1) {
    a = 1;
    renamed = true;
  }

  // search children
  if (phi.type == CONJ) {
    for (int v : phi.down) R_rec(v,a);
    phi.p = 0; for (int v : phi.down) phi.p = clip(phi.p+G[v].p);
  }
  else { // phi.type == DISJ
    int n = phi.down.size();

    vector<int> dp(n,1); // dp[i] = prod(phi_j.p), i < j < n
    for (int i = n-2; 0 <= i; i--) dp[i] = clip(G[phi.down[i+1]].p*dp[i+1]);

    int ai = a; // ai = a*prod(phi_j.p), 0 <= j < i
    for (int i = 0; i < n; i++) {
      R_rec(phi.down[i],clip(ai*dp[i]));
      ai = clip(ai*G[phi.down[i]].p);
    }
    phi.p = 1; for (int v : phi.down) phi.p = clip(phi.p*G[v].p);
  }

  if (renamed) {
    R.push_back(u);
    phi.type |= (1<<7);
    phi.literal = nextR++;
    phi.p = 1;
  }
}

// pretty print formula root at u
void print(int u, bool enclose = true) {
  auto& phi = G[u];

  // literal
  if (phi.type == ATOM || phi.type&(1<<7)) {
    cout << 'p' << phi.literal;
    return;
  }

  // negation
  if (phi.type == NEGA) {
    cout << '~';
    print(phi.down.front());
    return;
  }

  // subformulas
  if (enclose) cout << '(';
  char op = phi.type == CONJ ? '&' : '|';
  bool printed = false;
  for (int v : phi.down) {
    if (printed) cout << " " << op << " ";
    printed = true;
    print(v);
  }
  if (enclose) cout << ')';
}

int main() {

  // input
  string phi;
  getline(cin,phi);

  // preprocess
  auto tree = parse(phi);
  nnf(tree.first);
  build(tree.first);
  auto toposort = [](int u, int v){ return pos(u) < pos(v); };
  for (int u = 1; u <= V; u++) {
    auto& phi = G[u];
    sort(phi.down.begin(),phi.down.end(),toposort);
    phi.p = p(u);
  }
  print(1,false);
  cout << endl;

  // renaming
  nextR = tree.second+1;
  R_rec(1,1);

  // output
  print(1);
  for (int u : R) {
    auto& phi = G[u];
    printf(" & (~p%d | ",phi.literal);
    phi.type &= ~(1<<7);
    print(u);
    phi.type |=  (1<<7);
    printf(")");
  }
  cout << endl;

  return 0;
}
<commit_msg>Improving parser<commit_after>#include <bits/stdc++.h>
using namespace std;

#define MAXN    100005
#define clip(X) min(X,10000)

// IMPLEMENTACAO/TESTES
// antes, procurar formulas menores nas maiores, mais ou menos R² * d(phi)
// dp para otimizar o renaming restringindo o nro maximo de literais
// procurar um benchmark
// adaptar entrada para o benchmark
// adaptar saida para algum provador, colocando em CNF

// MONOGRAFIA
// colocar exemplo 3.2

// formula
enum {CONJ=0,DISJ,IMPL,EQUI,NEGA,ATOM};
struct Vertex {
  char type;
  int literal;
  int up;
  vector<int> down;
  int p;
  Vertex() : p(1) {}
} G[MAXN];
int V = 0;

// create tree parsing formula from string
// first: tree
// second: number of literals
pair<vector<Vertex>,int> parse(string phi) {
  // check
  auto isvarsym = [](char c) {
    return
      ('0' <= c && c <= '9') ||
      ('a' <= c && c <= 'z') ||
      ('A' <= c && c <= 'Z')
    ;
  };

  vector<Vertex> ret(1);
  ret.back().type = CONJ;
  ret.back().up = 0;
  stack<int> S;
  S.push(0);
  map<string,int> id;
  int nextlit = 1;
  for (int i = 0; i < phi.size(); i++) {
    char c = phi[i];
    if (c == ' ' || c == '\t') continue;
    else if (c == '&') ret[S.top()].type = CONJ;
    else if (c == '|') ret[S.top()].type = DISJ;
    else if (c == '=') { ret[S.top()].type = IMPL; i++; }
    else if (c == '<') { ret[S.top()].type = EQUI; i += 2; }
    else if (c == '(' || c == '~') {
      S.push(ret.size());
      ret.emplace_back();
      ret.back().type = (c == '(' ? CONJ : NEGA);
    }
    else if (c == ')') {
      int u = S.top();
      S.pop();
      ret[u].up = S.top();
      ret[S.top()].down.push_back(u);
      if (ret[u].type != NEGA && ret[u].down.size() == 1) {
        int u1 = ret[u].down.front();
        ret[u].type = ret[u1].type;
        ret[u].down = ret[u1].down;
        for (int v : ret[u].down) ret[v].up = u;
      }
    }
    else { // literal
      string tmp = {phi[i]};
      while (i+1 < phi.size() && isvarsym(phi[i+1])) tmp += phi[++i];
      int& lit = id[tmp];
      if (!lit) lit = nextlit++;
      ret[S.top()].down.push_back(ret.size());
      ret.emplace_back();
      ret.back().type = ATOM;
      ret.back().literal = lit;
      ret.back().up = S.top();
      if (ret[S.top()].type == NEGA) { phi[i] = ')'; i--; }
    }
  }
  if (ret[0].down.size() == 1) {
    int u = ret[0].down.front();
    ret[0].type = ret[u].type;
    ret[0].down = ret[u].down;
    for (int v : ret[0].down) ret[v].up = 0;
  }
  return make_pair(ret,id.size());
}

void nnf(vector<Vertex>& T) {
  // copy tree rooted at u
  function<int(int)> copy = [&](int u) {
    int nu = T.size(); T.emplace_back();
    T[nu].type = T[u].type;
    T[nu].literal = T[u].literal;
    for (int v : T[u].down) {
      int tmp = copy(v);
      T[tmp].up = nu;
      T[nu].down.push_back(tmp);
    }
    return nu;
  };

  // remove implications and equivalences
  function<void(int)> dfs1 = [&](int u) {
    if (T[u].type == IMPL) {
      T[u].type = DISJ;
      int v = T[u].down.front();
      int negi = T.size(); T.emplace_back();
      T[negi].type = NEGA;
      T[u].down.front() = negi;
      T[negi].up = u;
      T[negi].down.push_back(v);
      T[v].up = negi;
    }
    else if (T[u].type == EQUI) {
      auto f = [&](int a, int b) {
        int impi = T.size(); T.emplace_back();
        T[impi].type = IMPL;
        T[u].down.push_back(impi);
        T[impi].up = u;
        T[impi].down.push_back(a), T[impi].down.push_back(b);
        T[a].up = impi, T[b].up = impi;
      };
      T[u].type = CONJ;
      int a = T[u].down.front(),  b = T[u].down.back();
      int c = copy(b),            d = copy(a);
      T[u].down.clear();
      f(a,b);
      f(c,d);
    }
    for (int v : T[u].down) dfs1(v);
  };
  dfs1(0);

  // remove negations
  function<void(int,bool)> dfs2 = [&](int u, bool neg) {
    if (!neg) {
      if (T[u].type == NEGA) {
        auto& phi1 = T[T[u].down.front()];
        if (phi1.type == NEGA) {
          auto& phi2 = T[phi1.down.front()];
          T[u].type = phi2.type;
          T[u].literal = phi2.literal;
          T[u].down = phi2.down;
          for (int v : T[u].down) T[v].up = u;
          phi1.type = CONJ, phi2.type = CONJ; // removing phi1 and phi2
        }
        else if (phi1.type != ATOM) { // CONJ or DISJ
          T[u].type = (phi1.type == CONJ ? DISJ : CONJ);
          T[u].down = phi1.down;
          for (int v : T[u].down) T[v].up = u;
          phi1.type = CONJ; // removing phi1
          neg = true;
        }
      }
    }
    else {
      if (T[u].type == NEGA) {
        auto& phi1 = T[T[u].down.front()];
        T[u].type = phi1.type;
        T[u].literal = phi1.literal;
        T[u].down = phi1.down;
        for (int v : T[u].down) T[v].up = u;
        phi1.type = CONJ; // removing phi1
        neg = false;
      }
      else if (T[u].type != ATOM) { // CONJ or DISJ
        T[u].type = (T[u].type == CONJ ? DISJ : CONJ);
      }
      else { // ATOM
        int atmi = copy(u);
        T[u].type = NEGA;
        T[u].down.push_back(atmi);
        T[atmi].up = u;
        neg = false;
      }
    }
    for (int v : T[u].down) dfs2(v,neg);
  };
  dfs2(0,false);
}

// build DAG from tree T
void build(const vector<Vertex>& T) {
  map<int,int> lit_newu;
  map<int,multiset<int>> oldp_newc;
  V = 1;

  // create vertices for literals
  for (int i = 0; i < T.size(); i++) if (T[i].type == ATOM) {
    auto& phi = T[i];
    int& u = lit_newu[phi.literal];
    if (!u) {
      u = ++V;
      G[u].type = ATOM;
      G[u].literal = phi.literal;
    }
    oldp_newc[phi.up].insert(u);
  }

  // search tree bottom-up to create vertices for subformulas
  for (map<multiset<int>,int> newc_newp; !oldp_newc.empty();) {
    list<pair<int,int>> tmp;
    for (auto kv = oldp_newc.begin(); kv != oldp_newc.end();) {
      auto& phi = T[kv->first];
      if (kv->second.size() < phi.down.size()) { kv++; continue; }
      int& u = newc_newp[kv->second];
      if (!u) {
        u = (phi.up != kv->first) ? ++V : 1;
        G[u].type = phi.type;
        for (int v : kv->second) G[u].down.push_back(v);
      }
      if (phi.up != kv->first) tmp.emplace_back(phi.up,u);
      oldp_newc.erase(kv++);
    }
    for (auto& kv : tmp) oldp_newc[kv.first].insert(kv.second);
  }
}

// position of u in a reverse toposort
int pos(int u) {
  static int next = 1, dp[MAXN] = {};
  int& ans = dp[u];
  if (ans) return ans;
  for (int v : G[u].down) pos(v);
  return ans = next++;
}

// p(phi(u))
int p(int u) {
  static int dp[MAXN] = {};
  int& ans = dp[u];
  if (ans) return ans;
  switch (G[u].type) {
    case CONJ: ans = 0; for (int v : G[u].down) ans = clip(ans+p(v)); break;
    case DISJ: ans = 1; for (int v : G[u].down) ans = clip(ans*p(v)); break;
    default:   ans = 1; break;
  }
  return ans;
}

// Boy de la Tour's top-down renaming
vector<int> R;
int nextR;
void R_rec(int u, int a) {
  auto& phi = G[u];
  if (phi.p == 1) return;

  // check renaming condition
  bool renamed = false;
  if (a > 1) {
    a = 1;
    renamed = true;
  }

  // search children
  if (phi.type == CONJ) {
    for (int v : phi.down) R_rec(v,a);
    phi.p = 0; for (int v : phi.down) phi.p = clip(phi.p+G[v].p);
  }
  else { // phi.type == DISJ
    int n = phi.down.size();

    vector<int> dp(n,1); // dp[i] = prod(phi_j.p), i < j < n
    for (int i = n-2; 0 <= i; i--) dp[i] = clip(G[phi.down[i+1]].p*dp[i+1]);

    int ai = a; // ai = a*prod(phi_j.p), 0 <= j < i
    for (int i = 0; i < n; i++) {
      R_rec(phi.down[i],clip(ai*dp[i]));
      ai = clip(ai*G[phi.down[i]].p);
    }
    phi.p = 1; for (int v : phi.down) phi.p = clip(phi.p*G[v].p);
  }

  if (renamed) {
    R.push_back(u);
    phi.type |= (1<<7);
    phi.literal = nextR++;
    phi.p = 1;
  }
}

// pretty print formula root at u
void print(int u, bool enclose = true) {
  auto& phi = G[u];

  // literal
  if (phi.type == ATOM || phi.type&(1<<7)) {
    cout << 'p' << phi.literal;
    return;
  }

  // negation
  if (phi.type == NEGA) {
    cout << '~';
    print(phi.down.front());
    return;
  }

  // subformulas
  if (enclose) cout << '(';
  char op = phi.type == CONJ ? '&' : '|';
  bool printed = false;
  for (int v : phi.down) {
    if (printed) cout << " " << op << " ";
    printed = true;
    print(v);
  }
  if (enclose) cout << ')';
}

int main() {

  // input
  string phi;
  getline(cin,phi);

  // preprocess
  auto tree = parse(phi);
  nnf(tree.first);
  build(tree.first);
  auto toposort = [](int u, int v){ return pos(u) < pos(v); };
  for (int u = 1; u <= V; u++) {
    auto& phi = G[u];
    sort(phi.down.begin(),phi.down.end(),toposort);
    phi.p = p(u);
  }
  print(1,false);
  cout << endl;

  // renaming
  nextR = tree.second+1;
  R_rec(1,1);

  // output
  print(1);
  for (int u : R) {
    auto& phi = G[u];
    printf(" & (~p%d | ",phi.literal);
    phi.type &= ~(1<<7);
    print(u);
    phi.type |=  (1<<7);
    printf(")");
  }
  cout << endl;

  return 0;
}
<|endoftext|>


<commit_before>#include "mpdas.h"

void
onclose()
{
	iprintf("%s", "Closing mpdas.");

	if(MPD) delete MPD;
	if(AudioScrobbler) delete AudioScrobbler;
	if(Cache) delete Cache;
	if(Config) delete Config;
}

void
setid(char* username)
{
	passwd* userinfo = 0;

	if(getuid != 0) {
		eprintf("%s", "You are not root.");
		exit(EXIT_FAILURE);
	}

	userinfo = getpwnam(username);
	if(!userinfo) {
		eprintf("%s", "The user you specified does not exist.");
		exit(EXIT_FAILURE);
	}

	if(setuid(userinfo->pw_uid == -1 || setgid(userinfo->pw_gid))) {
			eprintf("%s %s", "Could not switch to user", username);
			exit(EXIT_FAILURE);
	}

	setenv("HOME", userinfo->pw_dir, 0);
}

int
main(int argc, char* argv[])
{
	atexit(onclose);

	if(argc >= 2)
		setid(argv[2]);

	Config = new CConfig();

	MPD = new CMPD();
	if(!MPD->isConnected())
		return EXIT_FAILURE;

	AudioScrobbler = new CAudioScrobbler();
	AudioScrobbler->Handshake();
	Cache = new CCache();
	Cache->LoadCache();

scan:
	MPD->Update();
	Cache->WorkCache();
	usleep(500000);
	goto scan;

	return EXIT_SUCCESS;
}
<commit_msg>fix user switching<commit_after>#include "mpdas.h"

void
onclose()
{
	iprintf("%s", "Closing mpdas.");

	if(MPD) delete MPD;
	if(AudioScrobbler) delete AudioScrobbler;
	if(Cache) delete Cache;
	if(Config) delete Config;
}

void
setid(char* username)
{
	passwd* userinfo = 0;

	if(getuid() != 0) {
		eprintf("%s", "You are not root.");
		exit(EXIT_FAILURE);
	}

	userinfo = getpwnam(username);
	if(!userinfo) {
		eprintf("%s", "The user you specified does not exist.");
		exit(EXIT_FAILURE);
	}

	if(setuid(userinfo->pw_uid == -1 || setgid(userinfo->pw_gid))) {
			eprintf("%s %s", "Could not switch to user", username);
			exit(EXIT_FAILURE);
	}

	setenv("HOME", userinfo->pw_dir, 1);
}

int
main(int argc, char* argv[])
{
	atexit(onclose);

	if(argc >= 2)
		setid(argv[1]);

	Config = new CConfig();

	MPD = new CMPD();
	if(!MPD->isConnected())
		return EXIT_FAILURE;

	AudioScrobbler = new CAudioScrobbler();
	AudioScrobbler->Handshake();
	Cache = new CCache();
	Cache->LoadCache();

scan:
	MPD->Update();
	Cache->WorkCache();
	usleep(500000);
	goto scan;

	return EXIT_SUCCESS;
}
<|endoftext|>