<commit_before>#include "aco.hpp"

extern int debug;

ACO::ACO(Graph *graph, ACOStrategy *strategy, ACOParameters *params)
: Metaheuristic()
, graph(graph)
, strategy(strategy)
, params(params) {
  strategy->set_colony(this);
  ants = strategy->create_ants(graph);
  ranking = new Ranking(params, ants);
}

ACO::~ACO() {
  delete strategy;
  if (get_best_solution()) { delete get_best_solution(); }
  delete ranking;
  for (unsigned i = 0, len = ants.size(); i < len; ++i) {
    delete ants[i];
  }
}

void ACO::optimize() {
  strategy->before_optimization();
  while (is_working()) {
    if (debug) {
      cout << "Iteration #" << strategy->get_no_iteration() << ":\tquality:\t";
      Solution *solution = get_best_solution();
      cout << (solution ? solution->get_quality() : 0.0) << endl;
    }
    strategy->perform_iteration();
    finish_iteration();
  }
  strategy->finish_optimization();
}

void ACO::finish_iteration() {
  ranking->update();
  update_pheromones();
  ranking->free_memory();
}

void ACO::update_pheromones() {
  ranking->prepare_pheromones();
  graph->iterate(params->get_ro());
}

<commit_msg>ACO prints<commit_after>#include "aco.hpp"

extern int debug;

ACO::ACO(Graph *graph, ACOStrategy *strategy, ACOParameters *params)
: Metaheuristic()
, graph(graph)
, strategy(strategy)
, params(params) {
  strategy->set_colony(this);
  ants = strategy->create_ants(graph);
  ranking = new Ranking(params, ants);
}

ACO::~ACO() {
  delete strategy;
  if (get_best_solution()) { delete get_best_solution(); }
  delete ranking;
  for (unsigned i = 0, len = ants.size(); i < len; ++i) {
    delete ants[i];
  }
}

void ACO::optimize() {
  strategy->before_optimization();
  while (is_working()) {
    if (debug) {
      cout << "Iteration #" << strategy->get_no_iteration() << ":\tquality:\t";
      Solution *solution = get_best_solution();
      cout << (solution ? solution->print_header() : "0.0") << endl;
    }
    strategy->perform_iteration();
    finish_iteration();
  }
  strategy->finish_optimization();

  cout << "Best found solution:" << endl << *get_best_solution() << endl;
}

void ACO::finish_iteration() {
  ranking->update();
  update_pheromones();
  ranking->free_memory();
}

void ACO::update_pheromones() {
  ranking->prepare_pheromones();
  graph->iterate(params->get_ro());
}

<|endoftext|>


<commit_before>/*
 * Initial version copied from https://github.com/JetBrains/intellij-community/blob/master/native/fsNotifier/mac/fsnotifier.c
 */
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.

/*
 * Apple specific functions.
 */
#if defined(__APPLE__)

#include "native.h"
#include "generic.h"
#include <CoreServices/CoreServices.h>
#include <pthread.h>
#include <strings.h>

JavaVM* jvm = NULL;
bool invalidStateDetected = false;

typedef struct watch_details {
    CFMutableArrayRef rootsToWatch;
    FSEventStreamRef watcherStream;
    pthread_t watcherThread;
    jobject watcherCallback;
    CFRunLoopRef threadLoop;
} watch_details_t;

static jobject getTypeEnum(JNIEnv *env, const char *name) {
    jclass clsType = env->FindClass("net/rubygrapefruit/platform/file/FileWatcherCallback$Type");
    jfieldID fieldId = env->GetStaticFieldID(clsType , name, "Lnet/rubygrapefruit/platform/file/FileWatcherCallback$Type;");
    return env->GetStaticObjectField(clsType, fieldId);
}

static void reportEvent(const char *type, char *path, jobject watcherCallback) {
    // TODO What does this do?
    size_t len = 0;
    if (path != NULL) {
        len = strlen(path);
        for (char *p = path; *p != '\0'; p++) {
            if (*p == '\n') {
                *p = '\0';
            }
        }
    }

    // TODO Extract this logic to some global function
    JNIEnv* env;
    int getEnvStat = jvm->GetEnv((void **)&env, JNI_VERSION_1_6);
    if (getEnvStat == JNI_EDETACHED) {
        if (jvm->AttachCurrentThread((void **) &env, NULL) != JNI_OK) {
            invalidStateDetected = true;
            return;
        }
    } else if (getEnvStat == JNI_EVERSION) {
        invalidStateDetected = true;
        return;
    }

    printf("~~~~ Changed: %s %s\n", path, type);

    jclass callback_class = env->GetObjectClass(watcherCallback);
    jmethodID methodCallback = env->GetMethodID(callback_class, "pathChanged", "(Lnet/rubygrapefruit/platform/file/FileWatcherCallback$Type;Ljava/lang/String;)V");
    env->CallVoidMethod(watcherCallback, methodCallback, getTypeEnum(env, type), env->NewStringUTF(path));
}

static void callback(ConstFSEventStreamRef streamRef,
                     void *clientCallBackInfo,
                     size_t numEvents,
                     void *eventPaths,
                     const FSEventStreamEventFlags eventFlags[],
                     const FSEventStreamEventId eventIds[]) {
    if (invalidStateDetected) return;
    char **paths = (char**) eventPaths;

    jobject watcherCallback = (jobject) clientCallBackInfo;

    for (int i = 0; i < numEvents; i++) {
        FSEventStreamEventFlags flags = eventFlags[i];
        printf("~~~~ Event flags: 0x%x for %s\n", flags, paths[i]);
        const char *type;
        if (IS_SET(flags, kFSEventStreamEventFlagMustScanSubDirs)) {
            type = "INVALIDATE";
        } else if (IS_SET(flags, kFSEventStreamEventFlagItemRenamed)) {
            if (IS_SET(flags, kFSEventStreamEventFlagItemCreated)) {
                type = "REMOVED";
            } else {
                type = "CREATED";
            }
        } else if (IS_SET(flags, kFSEventStreamEventFlagItemModified)) {
            type = "MODIFIED";
        } else if (IS_SET(flags, kFSEventStreamEventFlagItemRemoved)) {
            type = "REMOVED";
        } else if (IS_SET(flags, kFSEventStreamEventFlagItemCreated)) {
            type = "CREATED";
        } else {
            printf("~~~~ Unknwon event %s for %x\n", paths[i], flags);
            type = "UNKNOWN";
            return;
        }
        reportEvent(type, paths[i], watcherCallback);
    }
}

static void *EventProcessingThread(void *data) {
    watch_details_t *details = (watch_details_t*) data;

    printf("~~~~ Starting thread\n");

    CFRunLoopRef threadLoop = CFRunLoopGetCurrent();
    FSEventStreamScheduleWithRunLoop(details->watcherStream, threadLoop, kCFRunLoopDefaultMode);
    FSEventStreamStart(details->watcherStream);
    details->threadLoop = threadLoop;
    // TODO We should wait for this in the caller thread otherwise stopWatching() might crash
    // This triggers run loop for this thread, causing it to run until we explicitly stop it.
    CFRunLoopRun();

    printf("~~~~ Stopping thread\n");

    return NULL;
}

JNIEXPORT jobject JNICALL
Java_net_rubygrapefruit_platform_internal_jni_OsxFileEventFunctions_startWatching(JNIEnv *env, jclass target, jobjectArray paths, CFAbsoluteTime latency, jobject javaCallback, jobject result) {

    printf("\n~~~~ Configuring...\n");

    invalidStateDetected = false;
    CFMutableArrayRef rootsToWatch = CFArrayCreateMutable(NULL, 0, NULL);
    if (rootsToWatch == NULL) {
        mark_failed_with_errno(env, "Could not allocate array to store roots to watch.", result);
        return NULL;
    }
    int count = env->GetArrayLength(paths);
    if (count == 0) {
        mark_failed_with_errno(env, "No paths given to watch.", result);
        return NULL;
    }
    for (int i = 0; i < count; i++) {
        jstring path = (jstring) env->GetObjectArrayElement(paths, i);
        char* watchedPath = java_to_char(env, path, result);
        printf("~~~~ Watching %s\n", watchedPath);
        if (watchedPath == NULL) {
            mark_failed_with_errno(env, "Could not allocate string to store root to watch.", result);
            return NULL;
        }
        CFStringRef stringPath = CFStringCreateWithCString(NULL, watchedPath, kCFStringEncodingUTF8);
        free(watchedPath);
        if (stringPath == NULL) {
            mark_failed_with_errno(env, "Could not create CFStringRef.", result);
            return NULL;
        }
        CFArrayAppendValue(rootsToWatch, stringPath);
    }

    jobject watcherCallback = env->NewGlobalRef(javaCallback);
    if (watcherCallback == NULL) {
        mark_failed_with_errno(env, "Could not create global reference for callback.", result);
        return NULL;
    }

    FSEventStreamContext context = {0, (void*) watcherCallback, NULL, NULL, NULL};
    FSEventStreamRef watcherStream = FSEventStreamCreate (
                NULL,
                &callback,
                &context,
                rootsToWatch,
                kFSEventStreamEventIdSinceNow,
                latency,
                kFSEventStreamCreateFlagNoDefer | kFSEventStreamCreateFlagFileEvents);
    if (watcherStream == NULL) {
         mark_failed_with_errno(env, "Could not create FSEventStreamCreate to track changes.", result);
         return NULL;
    }

    watch_details_t* details = (watch_details_t*)malloc(sizeof(watch_details_t));
    details->rootsToWatch = rootsToWatch;
    details->watcherStream = watcherStream;
    details->watcherCallback = watcherCallback;

    if (pthread_create(&(details->watcherThread), NULL, EventProcessingThread, details) != 0) {
        mark_failed_with_errno(env, "Could not create file watcher thread.", result);
        return NULL;
    }

    // TODO Should this be somewhere global?
    int jvmStatus = env->GetJavaVM(&jvm);
    if (jvmStatus < 0) {
        mark_failed_with_errno(env, "Could not store jvm instance.", result);
        return NULL;
    }

    jclass clsWatcher = env->FindClass("net/rubygrapefruit/platform/internal/jni/OsxFileEventFunctions$WatcherImpl");
    jmethodID constructor = env->GetMethodID(clsWatcher, "<init>", "(Ljava/lang/Object;)V");
    return env->NewObject(clsWatcher, constructor, env->NewDirectByteBuffer(details, sizeof(details)));
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_OsxFileEventFunctions_stopWatching(JNIEnv *env, jclass target, jobject detailsObj, jobject result) {
    watch_details_t *details = (watch_details_t*) env->GetDirectBufferAddress(detailsObj);
    CFMutableArrayRef rootsToWatch = details->rootsToWatch;
    FSEventStreamRef watcherStream = details->watcherStream;
    pthread_t watcherThread = details->watcherThread;
    jobject watcherCallback = details->watcherCallback;
    CFRunLoopRef threadLoop = details->threadLoop;
    free(details);

    // if there were no roots to watch, there are no resources to release
    if (rootsToWatch == NULL) return;
    if (invalidStateDetected) {
        // report and reset flag, but try to clean up state as much as possible
        mark_failed_with_errno(env, "Watcher is in invalid state, reported changes may be incorrect.", result);
    }

    for (int i = 0; i < CFArrayGetCount(rootsToWatch); i++) {
        const void *value = CFArrayGetValueAtIndex(rootsToWatch, i);
        CFRelease(value);
    }
    // TODO Can we release these earlier?
    CFRelease(rootsToWatch);
    rootsToWatch = NULL;

    FSEventStreamStop(watcherStream);
    FSEventStreamInvalidate(watcherStream);
    FSEventStreamRelease(watcherStream);
    // TODO: consider using FSEventStreamFlushSync to flush all pending events.
    watcherStream = NULL;

    // TODO Shouldn't we stop this first and then release the rest?
    CFRunLoopStop(threadLoop);
    threadLoop = NULL;

    env->DeleteGlobalRef(watcherCallback);
    watcherCallback = NULL;

    pthread_join(watcherThread, NULL);
    watcherThread = NULL;
}

#endif
<commit_msg>Free up resources more consistently when there are errors<commit_after>/*
 * Initial version copied from https://github.com/JetBrains/intellij-community/blob/master/native/fsNotifier/mac/fsnotifier.c
 */
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.

/*
 * Apple specific functions.
 */
#if defined(__APPLE__)

#include "native.h"
#include "generic.h"
#include <CoreServices/CoreServices.h>
#include <pthread.h>
#include <strings.h>

JavaVM* jvm = NULL;
bool invalidStateDetected = false;

typedef struct watch_details {
    CFMutableArrayRef rootsToWatch;
    FSEventStreamRef watcherStream;
    pthread_t watcherThread;
    jobject watcherCallback;
    CFRunLoopRef threadLoop;
} watch_details_t;

static jobject getTypeEnum(JNIEnv *env, const char *name) {
    jclass clsType = env->FindClass("net/rubygrapefruit/platform/file/FileWatcherCallback$Type");
    jfieldID fieldId = env->GetStaticFieldID(clsType , name, "Lnet/rubygrapefruit/platform/file/FileWatcherCallback$Type;");
    return env->GetStaticObjectField(clsType, fieldId);
}

static void reportEvent(const char *type, char *path, jobject watcherCallback) {
    // TODO What does this do?
    size_t len = 0;
    if (path != NULL) {
        len = strlen(path);
        for (char *p = path; *p != '\0'; p++) {
            if (*p == '\n') {
                *p = '\0';
            }
        }
    }

    // TODO Extract this logic to some global function
    JNIEnv* env;
    int getEnvStat = jvm->GetEnv((void **)&env, JNI_VERSION_1_6);
    if (getEnvStat == JNI_EDETACHED) {
        if (jvm->AttachCurrentThread((void **) &env, NULL) != JNI_OK) {
            invalidStateDetected = true;
            return;
        }
    } else if (getEnvStat == JNI_EVERSION) {
        invalidStateDetected = true;
        return;
    }

    printf("~~~~ Changed: %s %s\n", path, type);

    jclass callback_class = env->GetObjectClass(watcherCallback);
    jmethodID methodCallback = env->GetMethodID(callback_class, "pathChanged", "(Lnet/rubygrapefruit/platform/file/FileWatcherCallback$Type;Ljava/lang/String;)V");
    env->CallVoidMethod(watcherCallback, methodCallback, getTypeEnum(env, type), env->NewStringUTF(path));
}

static void callback(ConstFSEventStreamRef streamRef,
                     void *clientCallBackInfo,
                     size_t numEvents,
                     void *eventPaths,
                     const FSEventStreamEventFlags eventFlags[],
                     const FSEventStreamEventId eventIds[]) {
    if (invalidStateDetected) return;
    char **paths = (char**) eventPaths;

    jobject watcherCallback = (jobject) clientCallBackInfo;

    for (int i = 0; i < numEvents; i++) {
        FSEventStreamEventFlags flags = eventFlags[i];
        printf("~~~~ Event flags: 0x%x for %s\n", flags, paths[i]);
        const char *type;
        if (IS_SET(flags, kFSEventStreamEventFlagMustScanSubDirs)) {
            type = "INVALIDATE";
        } else if (IS_SET(flags, kFSEventStreamEventFlagItemRenamed)) {
            if (IS_SET(flags, kFSEventStreamEventFlagItemCreated)) {
                type = "REMOVED";
            } else {
                type = "CREATED";
            }
        } else if (IS_SET(flags, kFSEventStreamEventFlagItemModified)) {
            type = "MODIFIED";
        } else if (IS_SET(flags, kFSEventStreamEventFlagItemRemoved)) {
            type = "REMOVED";
        } else if (IS_SET(flags, kFSEventStreamEventFlagItemCreated)) {
            type = "CREATED";
        } else {
            printf("~~~~ Unknwon event %s for %x\n", paths[i], flags);
            type = "UNKNOWN";
            return;
        }
        reportEvent(type, paths[i], watcherCallback);
    }
}

static void *EventProcessingThread(void *data) {
    watch_details_t *details = (watch_details_t*) data;

    printf("~~~~ Starting thread\n");

    CFRunLoopRef threadLoop = CFRunLoopGetCurrent();
    FSEventStreamScheduleWithRunLoop(details->watcherStream, threadLoop, kCFRunLoopDefaultMode);
    FSEventStreamStart(details->watcherStream);
    details->threadLoop = threadLoop;
    // TODO We should wait for this in the caller thread otherwise stopWatching() might crash
    // This triggers run loop for this thread, causing it to run until we explicitly stop it.
    CFRunLoopRun();

    printf("~~~~ Stopping thread\n");

    return NULL;
}

void freeDetails(JNIEnv *env, watch_details_t *details) {
    CFMutableArrayRef rootsToWatch = details->rootsToWatch;
    FSEventStreamRef watcherStream = details->watcherStream;
    pthread_t watcherThread = details->watcherThread;
    jobject watcherCallback = details->watcherCallback;
    CFRunLoopRef threadLoop = details->threadLoop;
    free(details);

    if (threadLoop != NULL) {
        CFRunLoopStop(threadLoop);
    }

    if (watcherThread != NULL) {
        pthread_join(watcherThread, NULL);
    }

    if (rootsToWatch != NULL) {
        for (int i = 0; i < CFArrayGetCount(rootsToWatch); i++) {
            const void *value = CFArrayGetValueAtIndex(rootsToWatch, i);
            CFRelease(value);
        }
        // TODO Can we release these earlier?
        CFRelease(rootsToWatch);
    }

    if (watcherStream != NULL) {
        FSEventStreamStop(watcherStream);
        FSEventStreamInvalidate(watcherStream);
        FSEventStreamRelease(watcherStream);
        // TODO: consider using FSEventStreamFlushSync to flush all pending events.
    }

    if (watcherCallback != NULL) {
        env->DeleteGlobalRef(watcherCallback);
    }
}

JNIEXPORT jobject JNICALL
Java_net_rubygrapefruit_platform_internal_jni_OsxFileEventFunctions_startWatching(JNIEnv *env, jclass target, jobjectArray paths, CFAbsoluteTime latency, jobject javaCallback, jobject result) {

    printf("\n~~~~ Configuring...\n");

    invalidStateDetected = false;
    CFMutableArrayRef rootsToWatch = CFArrayCreateMutable(NULL, 0, NULL);
    if (rootsToWatch == NULL) {
        mark_failed_with_errno(env, "Could not allocate array to store roots to watch.", result);
        return NULL;
    }
    int count = env->GetArrayLength(paths);
    if (count == 0) {
        mark_failed_with_errno(env, "No paths given to watch.", result);
        return NULL;
    }

    watch_details_t* details = (watch_details_t*)malloc(sizeof(watch_details_t));
    details->rootsToWatch = rootsToWatch;
    for (int i = 0; i < count; i++) {
        jstring path = (jstring) env->GetObjectArrayElement(paths, i);
        char* watchedPath = java_to_char(env, path, result);
        printf("~~~~ Watching %s\n", watchedPath);
        if (watchedPath == NULL) {
            mark_failed_with_errno(env, "Could not allocate string to store root to watch.", result);
            freeDetails(env, details);
            return NULL;
        }
        CFStringRef stringPath = CFStringCreateWithCString(NULL, watchedPath, kCFStringEncodingUTF8);
        free(watchedPath);
        if (stringPath == NULL) {
            mark_failed_with_errno(env, "Could not create CFStringRef.", result);
            freeDetails(env, details);
            return NULL;
        }
        CFArrayAppendValue(rootsToWatch, stringPath);
    }

    details->watcherCallback = env->NewGlobalRef(javaCallback);
    if (details->watcherCallback == NULL) {
        mark_failed_with_errno(env, "Could not create global reference for callback.", result);
        freeDetails(env, details);
        return NULL;
    }

    FSEventStreamContext context = {0, (void*) details->watcherCallback, NULL, NULL, NULL};
    details->watcherStream = FSEventStreamCreate (
                NULL,
                &callback,
                &context,
                rootsToWatch,
                kFSEventStreamEventIdSinceNow,
                latency,
                kFSEventStreamCreateFlagNoDefer | kFSEventStreamCreateFlagFileEvents);
    if (details->watcherStream == NULL) {
        mark_failed_with_errno(env, "Could not create FSEventStreamCreate to track changes.", result);
        freeDetails(env, details);
        return NULL;
    }

    if (pthread_create(&(details->watcherThread), NULL, EventProcessingThread, details) != 0) {
        mark_failed_with_errno(env, "Could not create file watcher thread.", result);
        freeDetails(env, details);
        return NULL;
    }

    // TODO Should this be somewhere global?
    int jvmStatus = env->GetJavaVM(&jvm);
    if (jvmStatus < 0) {
        mark_failed_with_errno(env, "Could not store jvm instance.", result);
        freeDetails(env, details);
        return NULL;
    }

    jclass clsWatcher = env->FindClass("net/rubygrapefruit/platform/internal/jni/OsxFileEventFunctions$WatcherImpl");
    jmethodID constructor = env->GetMethodID(clsWatcher, "<init>", "(Ljava/lang/Object;)V");
    return env->NewObject(clsWatcher, constructor, env->NewDirectByteBuffer(details, sizeof(details)));
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_OsxFileEventFunctions_stopWatching(JNIEnv *env, jclass target, jobject detailsObj, jobject result) {
    watch_details_t *details = (watch_details_t*) env->GetDirectBufferAddress(detailsObj);

    if (invalidStateDetected) {
        // report and reset flag, but try to clean up state as much as possible
        mark_failed_with_errno(env, "Watcher is in invalid state, reported changes may be incorrect.", result);
    }

    freeDetails(env, details);
}

#endif
<|endoftext|>


<commit_before>#include "glsl_optimizer.h"
#include "ast.h"
#include "glsl_parser_extras.h"
#include "glsl_parser.h"
#include "ir_optimization.h"
#include "ir_print_glsl_visitor.h"
#include "ir_print_visitor.h"
#include "loop_analysis.h"
#include "program.h"

extern "C" struct gl_shader *
_mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type);

static void
initialize_mesa_context(struct gl_context *ctx, gl_api api)
{
   memset(ctx, 0, sizeof(*ctx));

   ctx->API = api;

   ctx->Extensions.ARB_draw_buffers = GL_TRUE;
   ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE;
   ctx->Extensions.EXT_texture_array = GL_TRUE;
   ctx->Extensions.NV_texture_rectangle = GL_TRUE;
   ctx->Extensions.ARB_shader_texture_lod = GL_TRUE;

   /* 1.10 minimums. */
   ctx->Const.MaxLights = 8;
   ctx->Const.MaxClipPlanes = 8;
   ctx->Const.MaxTextureUnits = 2;

   /* More than the 1.10 minimum to appease parser tests taken from
    * apps that (hopefully) already checked the number of coords.
    */
   ctx->Const.MaxTextureCoordUnits = 4;

   ctx->Const.VertexProgram.MaxAttribs = 16;
   ctx->Const.VertexProgram.MaxUniformComponents = 512;
   ctx->Const.MaxVarying = 8;
   ctx->Const.MaxVertexTextureImageUnits = 0;
   ctx->Const.MaxCombinedTextureImageUnits = 2;
   ctx->Const.MaxTextureImageUnits = 2;
   ctx->Const.FragmentProgram.MaxUniformComponents = 64;

   ctx->Const.MaxDrawBuffers = 2;

   ctx->Driver.NewShader = _mesa_new_shader;
}

struct glslopt_ctx {
	glslopt_ctx (bool openglES) {
		mem_ctx = ralloc_context (NULL);
		initialize_mesa_context (&mesa_ctx, openglES ? API_OPENGLES2 : API_OPENGL);
	}
	~glslopt_ctx() {
		ralloc_free (mem_ctx);
	}
	struct gl_context mesa_ctx;
	void* mem_ctx;
};

glslopt_ctx* glslopt_initialize (bool openglES)
{
	return new glslopt_ctx(openglES);
}

void glslopt_cleanup (glslopt_ctx* ctx)
{
	delete ctx;
	_mesa_glsl_release_types();
	_mesa_glsl_release_functions();
}

struct glslopt_shader {
	static void* operator new(size_t size, void *ctx)
	{
		void *node;
		node = ralloc_size(ctx, size);
		assert(node != NULL);
		return node;
	}
	static void operator delete(void *node)
	{
		ralloc_free(node);
	}

	glslopt_shader ()
		: rawOutput(0)
		, optimizedOutput(0)
		, status(false)
	{
		infoLog = "Shader not compiled yet";
	}

	char*	rawOutput;
	char*	optimizedOutput;
	const char*	infoLog;
	bool	status;
};

static inline void debug_print_ir (const char* name, exec_list* ir, _mesa_glsl_parse_state* state, void* memctx)
{
	#if 0
	printf("**** %s:\n", name);
	//_mesa_print_ir (ir, state);
	char* foobar = _mesa_print_ir_glsl(ir, state, ralloc_strdup(memctx, ""), kPrintGlslFragment);
	printf(foobar);
	validate_ir_tree(ir);
	#endif
}

static void propagate_precision_deref(ir_instruction *ir, void *data)
{
	ir_dereference_variable* der = ir->as_dereference_variable();
	if (der && der->get_precision() == glsl_precision_undefined && der->var->precision != glsl_precision_undefined)
	{
		der->set_precision ((glsl_precision)der->var->precision);
		*(bool*)data = true;
	}
	ir_swizzle* swz = ir->as_swizzle();
	if (swz && swz->get_precision() == glsl_precision_undefined && swz->val->get_precision() != glsl_precision_undefined)
	{
		swz->set_precision (swz->val->get_precision());
		*(bool*)data = true;
	}

}

static void propagate_precision_assign(ir_instruction *ir, void *data)
{
	ir_assignment* ass = ir->as_assignment();
	if (ass && ass->lhs && ass->rhs)
	{
		glsl_precision lp = ass->lhs->get_precision();
		glsl_precision rp = ass->rhs->get_precision();
		if (rp == glsl_precision_undefined)
			return;
		ir_variable* lhs_var = ass->lhs->variable_referenced();
		if (lp == glsl_precision_undefined)
		{
			if (lhs_var)
				lhs_var->precision = rp;
			ass->lhs->set_precision (rp);
			*(bool*)data = true;
		}
	}
}

static void propagate_precision_call(ir_instruction *ir, void *data)
{
	ir_call* call = ir->as_call();
	if (!call)
		return;
	if (call->get_precision() == glsl_precision_undefined /*&& call->get_callee()->precision == glsl_precision_undefined*/)
	{
		glsl_precision prec_params_max = glsl_precision_undefined;
		exec_list_iterator iter_sig  = call->get_callee()->parameters.iterator();
		foreach_iter(exec_list_iterator, iter_param, call->actual_parameters)
		{
			ir_variable* sig_param = (ir_variable*)iter_sig.get();
			ir_rvalue* param = (ir_rvalue*)iter_param.get();

			glsl_precision p = (glsl_precision)sig_param->precision;
			if (p == glsl_precision_undefined)
				p = param->get_precision();

			prec_params_max = higher_precision (prec_params_max, p);

			iter_sig.next();
		}
		if (call->get_precision() != prec_params_max)
		{
			call->set_precision (prec_params_max);
			*(bool*)data = true;
		}
	}
}

static bool propagate_precision(exec_list* list)
{
	bool anyProgress = false;
	bool res;
	do {
		res = false;
		foreach_iter(exec_list_iterator, iter, *list) {
			ir_instruction* ir = (ir_instruction*)iter.get();
			visit_tree (ir, propagate_precision_deref, &res);
			visit_tree (ir, propagate_precision_assign, &res);
			visit_tree (ir, propagate_precision_call, &res);
		}
		anyProgress |= res;
	} while (res);
	return anyProgress;
}

glslopt_shader* glslopt_optimize (glslopt_ctx* ctx, glslopt_shader_type type, const char* shaderSource, unsigned options)
{
	glslopt_shader* shader = new (ctx->mem_ctx) glslopt_shader ();

	GLenum glType = 0;
	PrintGlslMode printMode;
	switch (type) {
	case kGlslOptShaderVertex: glType = GL_VERTEX_SHADER; printMode = kPrintGlslVertex; break;
	case kGlslOptShaderFragment: glType = GL_FRAGMENT_SHADER; printMode = kPrintGlslFragment; break;
	}
	if (!glType)
	{
		shader->infoLog = ralloc_asprintf (ctx->mem_ctx, "Unknown shader type %d", (int)type);
		shader->status = false;
		return shader;
	}

	_mesa_glsl_parse_state* state = new (ctx->mem_ctx) _mesa_glsl_parse_state (&ctx->mesa_ctx, glType, ctx->mem_ctx);
	state->error = 0;

	if (!(options & kGlslOptionSkipPreprocessor))
	{
		state->error = preprocess (state, &shaderSource, &state->info_log, state->extensions, ctx->mesa_ctx.API);
		if (state->error)
		{
			shader->status = !state->error;
			shader->infoLog = state->info_log;
			return shader;
		}
	}

	_mesa_glsl_lexer_ctor (state, shaderSource);
	_mesa_glsl_parse (state);
	_mesa_glsl_lexer_dtor (state);

	exec_list* ir = new (ctx->mem_ctx) exec_list();

	if (!state->error && !state->translation_unit.is_empty())
		_mesa_ast_to_hir (ir, state);

	// Un-optimized output
	if (!state->error) {
		validate_ir_tree(ir);
		shader->rawOutput = _mesa_print_ir_glsl(ir, state, ralloc_strdup(ctx->mem_ctx, ""), printMode);
	}

	// Optimization passes
	const bool linked = !(options & kGlslOptionNotFullShader);
	if (!state->error && !ir->is_empty())
	{
		bool progress;
		do {
			progress = false;
			bool progress2;
			debug_print_ir ("Initial", ir, state, ctx->mem_ctx);
			progress2 = do_function_inlining(ir); progress |= progress2; if (progress2) debug_print_ir ("After inlining", ir, state, ctx->mem_ctx);
			progress2 = do_dead_functions(ir); progress |= progress2; if (progress2) debug_print_ir ("After dead functions", ir, state, ctx->mem_ctx);
			progress2 = do_structure_splitting(ir); progress |= progress2; if (progress2) debug_print_ir ("After struct splitting", ir, state, ctx->mem_ctx);
			progress2 = do_if_simplification(ir); progress |= progress2; if (progress2) debug_print_ir ("After if simpl", ir, state, ctx->mem_ctx);
			progress2 = propagate_precision (ir); progress |= progress2; if (progress2) debug_print_ir ("After prec propagation", ir, state, ctx->mem_ctx);
			progress2 = do_copy_propagation(ir); progress |= progress2; if (progress2) debug_print_ir ("After copy propagation", ir, state, ctx->mem_ctx);
			progress2 = do_copy_propagation_elements(ir); progress |= progress2; if (progress2) debug_print_ir ("After copy propagation elems", ir, state, ctx->mem_ctx);
			if (!linked) {
				progress2 = do_dead_code_unlinked(ir); progress |= progress2; if (progress2) debug_print_ir ("After dead code unlinked", ir, state, ctx->mem_ctx);
			} else {
				progress2 = do_dead_code(ir); progress |= progress2; if (progress2) debug_print_ir ("After dead code", ir, state, ctx->mem_ctx);
			}
			progress2 = do_dead_code_local(ir); progress |= progress2; if (progress2) debug_print_ir ("After dead code local", ir, state, ctx->mem_ctx);
			progress2 = propagate_precision (ir); progress |= progress2; if (progress2) debug_print_ir ("After prec propagation", ir, state, ctx->mem_ctx);
			progress2 = do_tree_grafting(ir); progress |= progress2; if (progress2) debug_print_ir ("After tree grafting", ir, state, ctx->mem_ctx);
			progress2 = do_constant_propagation(ir); progress |= progress2; if (progress2) debug_print_ir ("After const propagation", ir, state, ctx->mem_ctx);
			if (!linked) {
				progress2 = do_constant_variable_unlinked(ir); progress |= progress2; if (progress2) debug_print_ir ("After const variable unlinked", ir, state, ctx->mem_ctx);
			} else {
				progress2 = do_constant_variable(ir); progress |= progress2; if (progress2) debug_print_ir ("After const variable", ir, state, ctx->mem_ctx);
			}
			progress2 = do_constant_folding(ir); progress |= progress2; if (progress2) debug_print_ir ("After const folding", ir, state, ctx->mem_ctx);
			progress2 = do_algebraic(ir); progress |= progress2; if (progress2) debug_print_ir ("After algebraic", ir, state, ctx->mem_ctx);
			progress2 = do_lower_jumps(ir); progress |= progress2; if (progress2) debug_print_ir ("After lower jumps", ir, state, ctx->mem_ctx);
			progress2 = do_vec_index_to_swizzle(ir); progress |= progress2; if (progress2) debug_print_ir ("After vec index to swizzle", ir, state, ctx->mem_ctx);
			//progress2 = do_vec_index_to_cond_assign(ir); progress |= progress2; if (progress2) debug_print_ir ("After vec index to cond assign", ir, state, ctx->mem_ctx);
			progress2 = do_swizzle_swizzle(ir); progress |= progress2; if (progress2) debug_print_ir ("After swizzle swizzle", ir, state, ctx->mem_ctx);
			progress2 = do_noop_swizzle(ir); progress |= progress2; if (progress2) debug_print_ir ("After noop swizzle", ir, state, ctx->mem_ctx);
			progress2 = optimize_redundant_jumps(ir); progress |= progress2; if (progress2) debug_print_ir ("After redundant jumps", ir, state, ctx->mem_ctx);

			loop_state *ls = analyze_loop_variables(ir);
			progress2 = set_loop_controls(ir, ls); progress |= progress2;
			progress2 = unroll_loops(ir, ls, 8); progress |= progress2;
			delete ls;
		} while (progress);

		validate_ir_tree(ir);
	}

	// Final optimized output
	if (!state->error)
	{
		shader->optimizedOutput = _mesa_print_ir_glsl(ir, state, ralloc_strdup(ctx->mem_ctx, ""), printMode);
	}

	shader->status = !state->error;
	shader->infoLog = state->info_log;

	ralloc_free (ir);
	ralloc_free (state);

	return shader;
}

void glslopt_shader_delete (glslopt_shader* shader)
{
	delete shader;
}

bool glslopt_get_status (glslopt_shader* shader)
{
	return shader->status;
}

const char* glslopt_get_output (glslopt_shader* shader)
{
	return shader->optimizedOutput;
}

const char* glslopt_get_raw_output (glslopt_shader* shader)
{
	return shader->rawOutput;
}

const char* glslopt_get_log (glslopt_shader* shader)
{
	return shader->infoLog;
}
<commit_msg>Up the supported version.<commit_after>#include "glsl_optimizer.h"
#include "ast.h"
#include "glsl_parser_extras.h"
#include "glsl_parser.h"
#include "ir_optimization.h"
#include "ir_print_glsl_visitor.h"
#include "ir_print_visitor.h"
#include "loop_analysis.h"
#include "program.h"

extern "C" struct gl_shader *
_mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type);

static void
initialize_mesa_context(struct gl_context *ctx, gl_api api)
{
   memset(ctx, 0, sizeof(*ctx));

   ctx->API = api;

   ctx->Extensions.ARB_draw_buffers = GL_TRUE;
   ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE;
   ctx->Extensions.EXT_texture_array = GL_TRUE;
   ctx->Extensions.NV_texture_rectangle = GL_TRUE;
   ctx->Extensions.ARB_shader_texture_lod = GL_TRUE;

   ctx->Const.GLSLVersion = 120;

   /* 1.20 minimums. */
   ctx->Const.MaxLights = 8;
   ctx->Const.MaxClipPlanes = 8;
   ctx->Const.MaxTextureUnits = 2;

   /* More than the 1.10 minimum to appease parser tests taken from
    * apps that (hopefully) already checked the number of coords.
    */
   ctx->Const.MaxTextureCoordUnits = 4;

   ctx->Const.VertexProgram.MaxAttribs = 16;
   ctx->Const.VertexProgram.MaxUniformComponents = 512;
   ctx->Const.MaxVarying = 8;
   ctx->Const.MaxVertexTextureImageUnits = 0;
   ctx->Const.MaxCombinedTextureImageUnits = 2;
   ctx->Const.MaxTextureImageUnits = 2;
   ctx->Const.FragmentProgram.MaxUniformComponents = 64;

   ctx->Const.MaxDrawBuffers = 2;

   ctx->Driver.NewShader = _mesa_new_shader;
}

struct glslopt_ctx {
	glslopt_ctx (bool openglES) {
		mem_ctx = ralloc_context (NULL);
		initialize_mesa_context (&mesa_ctx, openglES ? API_OPENGLES2 : API_OPENGL);
	}
	~glslopt_ctx() {
		ralloc_free (mem_ctx);
	}
	struct gl_context mesa_ctx;
	void* mem_ctx;
};

glslopt_ctx* glslopt_initialize (bool openglES)
{
	return new glslopt_ctx(openglES);
}

void glslopt_cleanup (glslopt_ctx* ctx)
{
	delete ctx;
	_mesa_glsl_release_types();
	_mesa_glsl_release_functions();
}

struct glslopt_shader {
	static void* operator new(size_t size, void *ctx)
	{
		void *node;
		node = ralloc_size(ctx, size);
		assert(node != NULL);
		return node;
	}
	static void operator delete(void *node)
	{
		ralloc_free(node);
	}

	glslopt_shader ()
		: rawOutput(0)
		, optimizedOutput(0)
		, status(false)
	{
		infoLog = "Shader not compiled yet";
	}

	char*	rawOutput;
	char*	optimizedOutput;
	const char*	infoLog;
	bool	status;
};

static inline void debug_print_ir (const char* name, exec_list* ir, _mesa_glsl_parse_state* state, void* memctx)
{
	#if 0
	printf("**** %s:\n", name);
	//_mesa_print_ir (ir, state);
	char* foobar = _mesa_print_ir_glsl(ir, state, ralloc_strdup(memctx, ""), kPrintGlslFragment);
	printf(foobar);
	validate_ir_tree(ir);
	#endif
}

static void propagate_precision_deref(ir_instruction *ir, void *data)
{
	ir_dereference_variable* der = ir->as_dereference_variable();
	if (der && der->get_precision() == glsl_precision_undefined && der->var->precision != glsl_precision_undefined)
	{
		der->set_precision ((glsl_precision)der->var->precision);
		*(bool*)data = true;
	}
	ir_swizzle* swz = ir->as_swizzle();
	if (swz && swz->get_precision() == glsl_precision_undefined && swz->val->get_precision() != glsl_precision_undefined)
	{
		swz->set_precision (swz->val->get_precision());
		*(bool*)data = true;
	}

}

static void propagate_precision_assign(ir_instruction *ir, void *data)
{
	ir_assignment* ass = ir->as_assignment();
	if (ass && ass->lhs && ass->rhs)
	{
		glsl_precision lp = ass->lhs->get_precision();
		glsl_precision rp = ass->rhs->get_precision();
		if (rp == glsl_precision_undefined)
			return;
		ir_variable* lhs_var = ass->lhs->variable_referenced();
		if (lp == glsl_precision_undefined)
		{
			if (lhs_var)
				lhs_var->precision = rp;
			ass->lhs->set_precision (rp);
			*(bool*)data = true;
		}
	}
}

static void propagate_precision_call(ir_instruction *ir, void *data)
{
	ir_call* call = ir->as_call();
	if (!call)
		return;
	if (call->get_precision() == glsl_precision_undefined /*&& call->get_callee()->precision == glsl_precision_undefined*/)
	{
		glsl_precision prec_params_max = glsl_precision_undefined;
		exec_list_iterator iter_sig  = call->get_callee()->parameters.iterator();
		foreach_iter(exec_list_iterator, iter_param, call->actual_parameters)
		{
			ir_variable* sig_param = (ir_variable*)iter_sig.get();
			ir_rvalue* param = (ir_rvalue*)iter_param.get();

			glsl_precision p = (glsl_precision)sig_param->precision;
			if (p == glsl_precision_undefined)
				p = param->get_precision();

			prec_params_max = higher_precision (prec_params_max, p);

			iter_sig.next();
		}
		if (call->get_precision() != prec_params_max)
		{
			call->set_precision (prec_params_max);
			*(bool*)data = true;
		}
	}
}

static bool propagate_precision(exec_list* list)
{
	bool anyProgress = false;
	bool res;
	do {
		res = false;
		foreach_iter(exec_list_iterator, iter, *list) {
			ir_instruction* ir = (ir_instruction*)iter.get();
			visit_tree (ir, propagate_precision_deref, &res);
			visit_tree (ir, propagate_precision_assign, &res);
			visit_tree (ir, propagate_precision_call, &res);
		}
		anyProgress |= res;
	} while (res);
	return anyProgress;
}

glslopt_shader* glslopt_optimize (glslopt_ctx* ctx, glslopt_shader_type type, const char* shaderSource, unsigned options)
{
	glslopt_shader* shader = new (ctx->mem_ctx) glslopt_shader ();

	GLenum glType = 0;
	PrintGlslMode printMode;
	switch (type) {
	case kGlslOptShaderVertex: glType = GL_VERTEX_SHADER; printMode = kPrintGlslVertex; break;
	case kGlslOptShaderFragment: glType = GL_FRAGMENT_SHADER; printMode = kPrintGlslFragment; break;
	}
	if (!glType)
	{
		shader->infoLog = ralloc_asprintf (ctx->mem_ctx, "Unknown shader type %d", (int)type);
		shader->status = false;
		return shader;
	}

	_mesa_glsl_parse_state* state = new (ctx->mem_ctx) _mesa_glsl_parse_state (&ctx->mesa_ctx, glType, ctx->mem_ctx);
	state->error = 0;

	if (!(options & kGlslOptionSkipPreprocessor))
	{
		state->error = preprocess (state, &shaderSource, &state->info_log, state->extensions, ctx->mesa_ctx.API);
		if (state->error)
		{
			shader->status = !state->error;
			shader->infoLog = state->info_log;
			return shader;
		}
	}

	_mesa_glsl_lexer_ctor (state, shaderSource);
	_mesa_glsl_parse (state);
	_mesa_glsl_lexer_dtor (state);

	exec_list* ir = new (ctx->mem_ctx) exec_list();

	if (!state->error && !state->translation_unit.is_empty())
		_mesa_ast_to_hir (ir, state);

	// Un-optimized output
	if (!state->error) {
		validate_ir_tree(ir);
		shader->rawOutput = _mesa_print_ir_glsl(ir, state, ralloc_strdup(ctx->mem_ctx, ""), printMode);
	}

	// Optimization passes
	const bool linked = !(options & kGlslOptionNotFullShader);
	if (!state->error && !ir->is_empty())
	{
		bool progress;
		do {
			progress = false;
			bool progress2;
			debug_print_ir ("Initial", ir, state, ctx->mem_ctx);
			progress2 = do_function_inlining(ir); progress |= progress2; if (progress2) debug_print_ir ("After inlining", ir, state, ctx->mem_ctx);
			progress2 = do_dead_functions(ir); progress |= progress2; if (progress2) debug_print_ir ("After dead functions", ir, state, ctx->mem_ctx);
			progress2 = do_structure_splitting(ir); progress |= progress2; if (progress2) debug_print_ir ("After struct splitting", ir, state, ctx->mem_ctx);
			progress2 = do_if_simplification(ir); progress |= progress2; if (progress2) debug_print_ir ("After if simpl", ir, state, ctx->mem_ctx);
			progress2 = propagate_precision (ir); progress |= progress2; if (progress2) debug_print_ir ("After prec propagation", ir, state, ctx->mem_ctx);
			progress2 = do_copy_propagation(ir); progress |= progress2; if (progress2) debug_print_ir ("After copy propagation", ir, state, ctx->mem_ctx);
			progress2 = do_copy_propagation_elements(ir); progress |= progress2; if (progress2) debug_print_ir ("After copy propagation elems", ir, state, ctx->mem_ctx);
			if (!linked) {
				progress2 = do_dead_code_unlinked(ir); progress |= progress2; if (progress2) debug_print_ir ("After dead code unlinked", ir, state, ctx->mem_ctx);
			} else {
				progress2 = do_dead_code(ir); progress |= progress2; if (progress2) debug_print_ir ("After dead code", ir, state, ctx->mem_ctx);
			}
			progress2 = do_dead_code_local(ir); progress |= progress2; if (progress2) debug_print_ir ("After dead code local", ir, state, ctx->mem_ctx);
			progress2 = propagate_precision (ir); progress |= progress2; if (progress2) debug_print_ir ("After prec propagation", ir, state, ctx->mem_ctx);
			progress2 = do_tree_grafting(ir); progress |= progress2; if (progress2) debug_print_ir ("After tree grafting", ir, state, ctx->mem_ctx);
			progress2 = do_constant_propagation(ir); progress |= progress2; if (progress2) debug_print_ir ("After const propagation", ir, state, ctx->mem_ctx);
			if (!linked) {
				progress2 = do_constant_variable_unlinked(ir); progress |= progress2; if (progress2) debug_print_ir ("After const variable unlinked", ir, state, ctx->mem_ctx);
			} else {
				progress2 = do_constant_variable(ir); progress |= progress2; if (progress2) debug_print_ir ("After const variable", ir, state, ctx->mem_ctx);
			}
			progress2 = do_constant_folding(ir); progress |= progress2; if (progress2) debug_print_ir ("After const folding", ir, state, ctx->mem_ctx);
			progress2 = do_algebraic(ir); progress |= progress2; if (progress2) debug_print_ir ("After algebraic", ir, state, ctx->mem_ctx);
			progress2 = do_lower_jumps(ir); progress |= progress2; if (progress2) debug_print_ir ("After lower jumps", ir, state, ctx->mem_ctx);
			progress2 = do_vec_index_to_swizzle(ir); progress |= progress2; if (progress2) debug_print_ir ("After vec index to swizzle", ir, state, ctx->mem_ctx);
			//progress2 = do_vec_index_to_cond_assign(ir); progress |= progress2; if (progress2) debug_print_ir ("After vec index to cond assign", ir, state, ctx->mem_ctx);
			progress2 = do_swizzle_swizzle(ir); progress |= progress2; if (progress2) debug_print_ir ("After swizzle swizzle", ir, state, ctx->mem_ctx);
			progress2 = do_noop_swizzle(ir); progress |= progress2; if (progress2) debug_print_ir ("After noop swizzle", ir, state, ctx->mem_ctx);
			progress2 = optimize_redundant_jumps(ir); progress |= progress2; if (progress2) debug_print_ir ("After redundant jumps", ir, state, ctx->mem_ctx);

			loop_state *ls = analyze_loop_variables(ir);
			progress2 = set_loop_controls(ir, ls); progress |= progress2;
			progress2 = unroll_loops(ir, ls, 8); progress |= progress2;
			delete ls;
		} while (progress);

		validate_ir_tree(ir);
	}

	// Final optimized output
	if (!state->error)
	{
		shader->optimizedOutput = _mesa_print_ir_glsl(ir, state, ralloc_strdup(ctx->mem_ctx, ""), printMode);
	}

	shader->status = !state->error;
	shader->infoLog = state->info_log;

	ralloc_free (ir);
	ralloc_free (state);

	return shader;
}

void glslopt_shader_delete (glslopt_shader* shader)
{
	delete shader;
}

bool glslopt_get_status (glslopt_shader* shader)
{
	return shader->status;
}

const char* glslopt_get_output (glslopt_shader* shader)
{
	return shader->optimizedOutput;
}

const char* glslopt_get_raw_output (glslopt_shader* shader)
{
	return shader->rawOutput;
}

const char* glslopt_get_log (glslopt_shader* shader)
{
	return shader->infoLog;
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Designer of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "tabordereditor.h"

#include <metadatabase_p.h>
#include <qdesigner_command_p.h>
#include <qdesigner_utils_p.h>
#include <qlayout_widget_p.h>
#include <orderdialog_p.h>

#include <QtDesigner/QExtensionManager>
#include <QtDesigner/QDesignerFormWindowInterface>
#include <QtDesigner/QDesignerFormWindowCursorInterface>
#include <QtDesigner/QDesignerFormEditorInterface>
#include <QtDesigner/QDesignerWidgetFactoryInterface>
#include <QtDesigner/QDesignerPropertySheetExtension>

#include <QtGui/QPainter>
#include <QtGui/QMouseEvent>
#include <QtGui/QResizeEvent>
#include <QtGui/QMenu>
#include <QtGui/QApplication>

Q_DECLARE_METATYPE(QWidgetList)

QT_BEGIN_NAMESPACE

namespace {
    enum { VBOX_MARGIN = 1, HBOX_MARGIN = 4, BG_ALPHA = 32 };
}

static QRect fixRect(const QRect &r)
{
    return QRect(r.x(), r.y(), r.width() - 1, r.height() - 1);
}

namespace qdesigner_internal {

TabOrderEditor::TabOrderEditor(QDesignerFormWindowInterface *form, QWidget *parent) :
    QWidget(parent),
    m_form_window(form),
    m_bg_widget(0),
    m_undo_stack(form->commandHistory()),
    m_font_metrics(font()),
    m_current_index(0),
    m_beginning(true)
{
    connect(form, SIGNAL(widgetRemoved(QWidget*)), this, SLOT(widgetRemoved(QWidget*)));

    QFont tabFont = font();
    tabFont.setPointSize(tabFont.pointSize()*2);
    tabFont.setBold(true);
    setFont(tabFont);
    m_font_metrics = QFontMetrics(tabFont);
    setAttribute(Qt::WA_MouseTracking, true);
}

QDesignerFormWindowInterface *TabOrderEditor::formWindow() const
{
    return m_form_window;
}

void TabOrderEditor::setBackground(QWidget *background)
{
    if (background == m_bg_widget) {
        return;
    }

    m_bg_widget = background;
    updateBackground();
}

void TabOrderEditor::updateBackground()
{
    if (m_bg_widget == 0) {
        // nothing to do
        return;
    }

    initTabOrder();
    update();
}

void TabOrderEditor::widgetRemoved(QWidget*)
{
    initTabOrder();
}

void TabOrderEditor::showEvent(QShowEvent *e)
{
    QWidget::showEvent(e);
    updateBackground();
}

QRect TabOrderEditor::indicatorRect(int index) const
{
    if (index < 0 || index >= m_tab_order_list.size())
        return QRect();

    const QWidget *w = m_tab_order_list.at(index);
    const QString text = QString::number(index + 1);

    const QPoint tl = mapFromGlobal(w->mapToGlobal(w->rect().topLeft()));
    const QSize size = m_font_metrics.size(Qt::TextSingleLine, text);
    QRect r(tl - QPoint(size.width(), size.height())/2, size);
    r = QRect(r.left() - HBOX_MARGIN, r.top() - VBOX_MARGIN,
                r.width() + HBOX_MARGIN*2, r.height() + VBOX_MARGIN*2);

    return r;
}

static bool isWidgetVisible(QWidget *widget)
{
    while (widget && widget->parentWidget()) {
        if (!widget->isVisibleTo(widget->parentWidget()))
            return false;

        widget = widget->parentWidget();
    }

    return true;
}

void TabOrderEditor::paintEvent(QPaintEvent *e)
{
    QPainter p(this);
    p.setClipRegion(e->region());

    int cur = m_current_index - 1;
    if (m_beginning == false && cur < 0)
        cur = m_tab_order_list.size() - 1;

    for (int i = 0; i < m_tab_order_list.size(); ++i) {
        QWidget *widget = m_tab_order_list.at(i);
        if (!isWidgetVisible(widget))
            continue;

        const QRect r = indicatorRect(i);

        QColor c = Qt::darkGreen;
        if (i == cur)
            c = Qt::red;
        else if (i > cur)
            c = Qt::blue;
        p.setPen(c);
        c.setAlpha(BG_ALPHA);
        p.setBrush(c);
        p.drawRect(fixRect(r));

        p.setPen(Qt::white);
        p.drawText(r, QString::number(i + 1), QTextOption(Qt::AlignCenter));
    }
}

bool TabOrderEditor::skipWidget(QWidget *w) const
{
    if (qobject_cast<QLayoutWidget*>(w)
            || w == formWindow()->mainContainer()
            || w->isHidden())
        return true;

    if (!formWindow()->isManaged(w)) {
        return true;
    }

    QExtensionManager *ext = formWindow()->core()->extensionManager();
    if (const QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(ext, w)) {
        const int index = sheet->indexOf(QLatin1String("focusPolicy"));
        if (index != -1) {
            bool ok = false;
            Qt::FocusPolicy q = (Qt::FocusPolicy) Utils::valueOf(sheet->property(index), &ok);
            return !ok || q == Qt::NoFocus;
        }
    }

    return true;
}

void TabOrderEditor::initTabOrder()
{
    m_tab_order_list.clear();

    QDesignerFormEditorInterface *core = formWindow()->core();

    if (const QDesignerMetaDataBaseItemInterface *item = core->metaDataBase()->item(formWindow())) {
        m_tab_order_list = item->tabOrder();
    }

    // Remove any widgets that have been removed form the form
    for (int i = 0; i < m_tab_order_list.size(); ) {
        QWidget *w = m_tab_order_list.at(i);
        if (!formWindow()->mainContainer()->isAncestorOf(w) || skipWidget(w))
            m_tab_order_list.removeAt(i);
        else
            ++i;
    }

    // Append any widgets that are in the form but are not in the tab order
    QList<QWidget *> childQueue;
    childQueue.append(formWindow()->mainContainer());
    while (!childQueue.isEmpty()) {
        QWidget *child = childQueue.takeFirst();
        childQueue += qvariant_cast<QWidgetList>(child->property("_q_widgetOrder"));

        if (skipWidget(child))
            continue;

        if (!m_tab_order_list.contains(child))
            m_tab_order_list.append(child);
    }

    // Just in case we missed some widgets
    QDesignerFormWindowCursorInterface *cursor = formWindow()->cursor();
    for (int i = 0; i < cursor->widgetCount(); ++i) {

        QWidget *widget = cursor->widget(i);
        if (skipWidget(widget))
            continue;

        if (!m_tab_order_list.contains(widget))
            m_tab_order_list.append(widget);
    }

    m_indicator_region = QRegion();
    for (int i = 0; i < m_tab_order_list.size(); ++i) {
        if (m_tab_order_list.at(i)->isVisible())
            m_indicator_region |= indicatorRect(i);
    }

    if (m_current_index >= m_tab_order_list.size())
        m_current_index = m_tab_order_list.size() - 1;
    if (m_current_index < 0)
        m_current_index = 0;
}

void TabOrderEditor::mouseMoveEvent(QMouseEvent *e)
{
    e->accept();
#ifndef QT_NO_CURSOR
    if (m_indicator_region.contains(e->pos()))
        setCursor(Qt::PointingHandCursor);
    else
        setCursor(QCursor());
#endif
}

int TabOrderEditor::widgetIndexAt(const QPoint &pos) const
{
    int target_index = -1;
    for (int i = 0; i < m_tab_order_list.size(); ++i) {
        if (!m_tab_order_list.at(i)->isVisible())
            continue;
        if (indicatorRect(i).contains(pos)) {
            target_index = i;
            break;
        }
    }

    return target_index;
}

void TabOrderEditor::mousePressEvent(QMouseEvent *e)
{
    e->accept();

    if (!m_indicator_region.contains(e->pos())) {
        if (QWidget *child = m_bg_widget->childAt(e->pos())) {
            QDesignerFormEditorInterface *core = m_form_window->core();
            if (core->widgetFactory()->isPassiveInteractor(child)) {

                QMouseEvent event(QEvent::MouseButtonPress,
                                    child->mapFromGlobal(e->globalPos()),
                                    e->button(), e->buttons(), e->modifiers());

                qApp->sendEvent(child, &event);

                QMouseEvent event2(QEvent::MouseButtonRelease,
                                    child->mapFromGlobal(e->globalPos()),
                                    e->button(), e->buttons(), e->modifiers());

                qApp->sendEvent(child, &event2);

                updateBackground();
            }
        }
        return;
    }

    if (e->button() != Qt::LeftButton)
        return;

    const int target_index = widgetIndexAt(e->pos());
    if (target_index == -1)
        return;

    m_beginning = false;

    if (e->modifiers() & Qt::ControlModifier) {
        m_current_index = target_index + 1;
        if (m_current_index >= m_tab_order_list.size())
            m_current_index = 0;
        update();
        return;
    }

    if (m_current_index == -1)
        return;

    m_tab_order_list.swap(target_index, m_current_index);

    ++m_current_index;
    if (m_current_index == m_tab_order_list.size())
        m_current_index = 0;

    TabOrderCommand *cmd = new TabOrderCommand(formWindow());
    cmd->init(m_tab_order_list);
    formWindow()->commandHistory()->push(cmd);
}

void TabOrderEditor::contextMenuEvent(QContextMenuEvent *e)
{
    QMenu menu(this);
    const int target_index = widgetIndexAt(e->pos());
    QAction *setIndex = menu.addAction(tr("Start from Here"));
    setIndex->setEnabled(target_index >= 0);

    QAction *resetIndex = menu.addAction(tr("Restart"));
    menu.addSeparator();
    QAction *showDialog = menu.addAction(tr("Tab Order List..."));
    showDialog->setEnabled(m_tab_order_list.size() > 1);

    QAction *result = menu.exec(e->globalPos());
    if (result == resetIndex) {
        m_current_index = 0;
        m_beginning = true;
        update();
    } else if (result == setIndex) {
        m_beginning = false;
        m_current_index = target_index + 1;
        if (m_current_index >= m_tab_order_list.size())
            m_current_index = 0;
        update();
    } else if (result == showDialog) {
        showTabOrderDialog();
    }
}

void TabOrderEditor::mouseDoubleClickEvent(QMouseEvent *e)
{
    if (e->button() != Qt::LeftButton)
        return;

    const int target_index = widgetIndexAt(e->pos());
    if (target_index >= 0)
        return;

    m_beginning = true;
    m_current_index = 0;
    update();
}

void TabOrderEditor::resizeEvent(QResizeEvent *e)
{
    updateBackground();
    QWidget::resizeEvent(e);
}

void TabOrderEditor::showTabOrderDialog()
{
    if (m_tab_order_list.size() < 2)
        return;
    OrderDialog dlg(this);
    dlg.setWindowTitle(tr("Tab Order List"));
    dlg.setDescription(tr("Tab Order"));
    dlg.setFormat(OrderDialog::TabOrderFormat);
    dlg.setPageList(m_tab_order_list);

    if (dlg.exec() == QDialog::Rejected)
        return;

    const QWidgetList newOrder = dlg.pageList();
    if (newOrder == m_tab_order_list)
        return;

    m_tab_order_list = newOrder;
    TabOrderCommand *cmd = new TabOrderCommand(formWindow());
    cmd->init(m_tab_order_list);
    formWindow()->commandHistory()->push(cmd);
    update();
}

}

QT_END_NAMESPACE
<commit_msg>skip widget when its focusPolicy is Qt::ClickFocus in TabOrderEditor<commit_after>/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Designer of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "tabordereditor.h"

#include <metadatabase_p.h>
#include <qdesigner_command_p.h>
#include <qdesigner_utils_p.h>
#include <qlayout_widget_p.h>
#include <orderdialog_p.h>

#include <QtDesigner/QExtensionManager>
#include <QtDesigner/QDesignerFormWindowInterface>
#include <QtDesigner/QDesignerFormWindowCursorInterface>
#include <QtDesigner/QDesignerFormEditorInterface>
#include <QtDesigner/QDesignerWidgetFactoryInterface>
#include <QtDesigner/QDesignerPropertySheetExtension>

#include <QtGui/QPainter>
#include <QtGui/QMouseEvent>
#include <QtGui/QResizeEvent>
#include <QtGui/QMenu>
#include <QtGui/QApplication>

Q_DECLARE_METATYPE(QWidgetList)

QT_BEGIN_NAMESPACE

namespace {
    enum { VBOX_MARGIN = 1, HBOX_MARGIN = 4, BG_ALPHA = 32 };
}

static QRect fixRect(const QRect &r)
{
    return QRect(r.x(), r.y(), r.width() - 1, r.height() - 1);
}

namespace qdesigner_internal {

TabOrderEditor::TabOrderEditor(QDesignerFormWindowInterface *form, QWidget *parent) :
    QWidget(parent),
    m_form_window(form),
    m_bg_widget(0),
    m_undo_stack(form->commandHistory()),
    m_font_metrics(font()),
    m_current_index(0),
    m_beginning(true)
{
    connect(form, SIGNAL(widgetRemoved(QWidget*)), this, SLOT(widgetRemoved(QWidget*)));

    QFont tabFont = font();
    tabFont.setPointSize(tabFont.pointSize()*2);
    tabFont.setBold(true);
    setFont(tabFont);
    m_font_metrics = QFontMetrics(tabFont);
    setAttribute(Qt::WA_MouseTracking, true);
}

QDesignerFormWindowInterface *TabOrderEditor::formWindow() const
{
    return m_form_window;
}

void TabOrderEditor::setBackground(QWidget *background)
{
    if (background == m_bg_widget) {
        return;
    }

    m_bg_widget = background;
    updateBackground();
}

void TabOrderEditor::updateBackground()
{
    if (m_bg_widget == 0) {
        // nothing to do
        return;
    }

    initTabOrder();
    update();
}

void TabOrderEditor::widgetRemoved(QWidget*)
{
    initTabOrder();
}

void TabOrderEditor::showEvent(QShowEvent *e)
{
    QWidget::showEvent(e);
    updateBackground();
}

QRect TabOrderEditor::indicatorRect(int index) const
{
    if (index < 0 || index >= m_tab_order_list.size())
        return QRect();

    const QWidget *w = m_tab_order_list.at(index);
    const QString text = QString::number(index + 1);

    const QPoint tl = mapFromGlobal(w->mapToGlobal(w->rect().topLeft()));
    const QSize size = m_font_metrics.size(Qt::TextSingleLine, text);
    QRect r(tl - QPoint(size.width(), size.height())/2, size);
    r = QRect(r.left() - HBOX_MARGIN, r.top() - VBOX_MARGIN,
                r.width() + HBOX_MARGIN*2, r.height() + VBOX_MARGIN*2);

    return r;
}

static bool isWidgetVisible(QWidget *widget)
{
    while (widget && widget->parentWidget()) {
        if (!widget->isVisibleTo(widget->parentWidget()))
            return false;

        widget = widget->parentWidget();
    }

    return true;
}

void TabOrderEditor::paintEvent(QPaintEvent *e)
{
    QPainter p(this);
    p.setClipRegion(e->region());

    int cur = m_current_index - 1;
    if (m_beginning == false && cur < 0)
        cur = m_tab_order_list.size() - 1;

    for (int i = 0; i < m_tab_order_list.size(); ++i) {
        QWidget *widget = m_tab_order_list.at(i);
        if (!isWidgetVisible(widget))
            continue;

        const QRect r = indicatorRect(i);

        QColor c = Qt::darkGreen;
        if (i == cur)
            c = Qt::red;
        else if (i > cur)
            c = Qt::blue;
        p.setPen(c);
        c.setAlpha(BG_ALPHA);
        p.setBrush(c);
        p.drawRect(fixRect(r));

        p.setPen(Qt::white);
        p.drawText(r, QString::number(i + 1), QTextOption(Qt::AlignCenter));
    }
}

bool TabOrderEditor::skipWidget(QWidget *w) const
{
    if (qobject_cast<QLayoutWidget*>(w)
            || w == formWindow()->mainContainer()
            || w->isHidden())
        return true;

    if (!formWindow()->isManaged(w)) {
        return true;
    }

    QExtensionManager *ext = formWindow()->core()->extensionManager();
    if (const QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(ext, w)) {
        const int index = sheet->indexOf(QLatin1String("focusPolicy"));
        if (index != -1) {
            bool ok = false;
            Qt::FocusPolicy q = (Qt::FocusPolicy) Utils::valueOf(sheet->property(index), &ok);
            return !ok || !(q & Qt::TabFocus);
        }
    }

    return true;
}

void TabOrderEditor::initTabOrder()
{
    m_tab_order_list.clear();

    QDesignerFormEditorInterface *core = formWindow()->core();

    if (const QDesignerMetaDataBaseItemInterface *item = core->metaDataBase()->item(formWindow())) {
        m_tab_order_list = item->tabOrder();
    }

    // Remove any widgets that have been removed form the form
    for (int i = 0; i < m_tab_order_list.size(); ) {
        QWidget *w = m_tab_order_list.at(i);
        if (!formWindow()->mainContainer()->isAncestorOf(w) || skipWidget(w))
            m_tab_order_list.removeAt(i);
        else
            ++i;
    }

    // Append any widgets that are in the form but are not in the tab order
    QList<QWidget *> childQueue;
    childQueue.append(formWindow()->mainContainer());
    while (!childQueue.isEmpty()) {
        QWidget *child = childQueue.takeFirst();
        childQueue += qvariant_cast<QWidgetList>(child->property("_q_widgetOrder"));

        if (skipWidget(child))
            continue;

        if (!m_tab_order_list.contains(child))
            m_tab_order_list.append(child);
    }

    // Just in case we missed some widgets
    QDesignerFormWindowCursorInterface *cursor = formWindow()->cursor();
    for (int i = 0; i < cursor->widgetCount(); ++i) {

        QWidget *widget = cursor->widget(i);
        if (skipWidget(widget))
            continue;

        if (!m_tab_order_list.contains(widget))
            m_tab_order_list.append(widget);
    }

    m_indicator_region = QRegion();
    for (int i = 0; i < m_tab_order_list.size(); ++i) {
        if (m_tab_order_list.at(i)->isVisible())
            m_indicator_region |= indicatorRect(i);
    }

    if (m_current_index >= m_tab_order_list.size())
        m_current_index = m_tab_order_list.size() - 1;
    if (m_current_index < 0)
        m_current_index = 0;
}

void TabOrderEditor::mouseMoveEvent(QMouseEvent *e)
{
    e->accept();
#ifndef QT_NO_CURSOR
    if (m_indicator_region.contains(e->pos()))
        setCursor(Qt::PointingHandCursor);
    else
        setCursor(QCursor());
#endif
}

int TabOrderEditor::widgetIndexAt(const QPoint &pos) const
{
    int target_index = -1;
    for (int i = 0; i < m_tab_order_list.size(); ++i) {
        if (!m_tab_order_list.at(i)->isVisible())
            continue;
        if (indicatorRect(i).contains(pos)) {
            target_index = i;
            break;
        }
    }

    return target_index;
}

void TabOrderEditor::mousePressEvent(QMouseEvent *e)
{
    e->accept();

    if (!m_indicator_region.contains(e->pos())) {
        if (QWidget *child = m_bg_widget->childAt(e->pos())) {
            QDesignerFormEditorInterface *core = m_form_window->core();
            if (core->widgetFactory()->isPassiveInteractor(child)) {

                QMouseEvent event(QEvent::MouseButtonPress,
                                    child->mapFromGlobal(e->globalPos()),
                                    e->button(), e->buttons(), e->modifiers());

                qApp->sendEvent(child, &event);

                QMouseEvent event2(QEvent::MouseButtonRelease,
                                    child->mapFromGlobal(e->globalPos()),
                                    e->button(), e->buttons(), e->modifiers());

                qApp->sendEvent(child, &event2);

                updateBackground();
            }
        }
        return;
    }

    if (e->button() != Qt::LeftButton)
        return;

    const int target_index = widgetIndexAt(e->pos());
    if (target_index == -1)
        return;

    m_beginning = false;

    if (e->modifiers() & Qt::ControlModifier) {
        m_current_index = target_index + 1;
        if (m_current_index >= m_tab_order_list.size())
            m_current_index = 0;
        update();
        return;
    }

    if (m_current_index == -1)
        return;

    m_tab_order_list.swap(target_index, m_current_index);

    ++m_current_index;
    if (m_current_index == m_tab_order_list.size())
        m_current_index = 0;

    TabOrderCommand *cmd = new TabOrderCommand(formWindow());
    cmd->init(m_tab_order_list);
    formWindow()->commandHistory()->push(cmd);
}

void TabOrderEditor::contextMenuEvent(QContextMenuEvent *e)
{
    QMenu menu(this);
    const int target_index = widgetIndexAt(e->pos());
    QAction *setIndex = menu.addAction(tr("Start from Here"));
    setIndex->setEnabled(target_index >= 0);

    QAction *resetIndex = menu.addAction(tr("Restart"));
    menu.addSeparator();
    QAction *showDialog = menu.addAction(tr("Tab Order List..."));
    showDialog->setEnabled(m_tab_order_list.size() > 1);

    QAction *result = menu.exec(e->globalPos());
    if (result == resetIndex) {
        m_current_index = 0;
        m_beginning = true;
        update();
    } else if (result == setIndex) {
        m_beginning = false;
        m_current_index = target_index + 1;
        if (m_current_index >= m_tab_order_list.size())
            m_current_index = 0;
        update();
    } else if (result == showDialog) {
        showTabOrderDialog();
    }
}

void TabOrderEditor::mouseDoubleClickEvent(QMouseEvent *e)
{
    if (e->button() != Qt::LeftButton)
        return;

    const int target_index = widgetIndexAt(e->pos());
    if (target_index >= 0)
        return;

    m_beginning = true;
    m_current_index = 0;
    update();
}

void TabOrderEditor::resizeEvent(QResizeEvent *e)
{
    updateBackground();
    QWidget::resizeEvent(e);
}

void TabOrderEditor::showTabOrderDialog()
{
    if (m_tab_order_list.size() < 2)
        return;
    OrderDialog dlg(this);
    dlg.setWindowTitle(tr("Tab Order List"));
    dlg.setDescription(tr("Tab Order"));
    dlg.setFormat(OrderDialog::TabOrderFormat);
    dlg.setPageList(m_tab_order_list);

    if (dlg.exec() == QDialog::Rejected)
        return;

    const QWidgetList newOrder = dlg.pageList();
    if (newOrder == m_tab_order_list)
        return;

    m_tab_order_list = newOrder;
    TabOrderCommand *cmd = new TabOrderCommand(formWindow());
    cmd->init(m_tab_order_list);
    formWindow()->commandHistory()->push(cmd);
    update();
}

}

QT_END_NAMESPACE
<|endoftext|>


<commit_before>#include <SPI.h>
#include <Wire.h>
#include "spi_cmd.h"
#include "commands.h"

extern byte buff[256];

void spi_cmd_init() {
  long spi_speed;
  byte bytesread;

  bytesread = Serial.readBytes(buff, 1);

  if (bytesread == 0) {
    Serial.write(ERROR_RECV); //Ошибка
    Serial.flush();
    return;
  }

  if (buff[0] == 0) {
    spi_speed = 8000000;
  } else if (buff[0] == 1) {
    spi_speed = 4000000;
  } else if (buff[0] == 2) {
    spi_speed = 2000000;
  } else if (buff[0] == 3) {
    spi_speed = 1000000;
  } else {
    spi_speed = 8000000;
  }

  SPI.begin();
  SPI.beginTransaction(SPISettings(spi_speed, MSBFIRST, SPI_MODE0));

  Serial.write(FUNC_SPI_INIT); //Подтверждаем команду
  Serial.flush();
}

void spi_cmd_deinit() {
  SPI.endTransaction();
  SPI.end();
  Serial.write(FUNC_SPI_DEINIT); //Подтверждаем команду
  Serial.flush();
}

void spi_cmd_read() {
  int bytesread;
  int prog_nbytes;
  byte spi_cs_hi;

  //Получаем остальные данные
  bytesread = Serial.readBytes(buff, 3);
  if (bytesread < 3) {
    Serial.write(ERROR_RECV); //Ошибка
    Serial.flush();
    return;
  }

  digitalWrite(CSPin, LOW);

  spi_cs_hi = buff[0];

  prog_nbytes = buff[1];
  prog_nbytes = prog_nbytes << 8;
  prog_nbytes = prog_nbytes | buff[2];

  Serial.write(FUNC_SPI_READ); //Подтверждаем команду
  Serial.flush();

  //Работаем с SPI
  while (prog_nbytes > 0) {
    if (prog_nbytes >= rchunk) {
      SPI.transfer(buff, rchunk);
      prog_nbytes = prog_nbytes - Serial.write(buff, rchunk);
    } else {
      SPI.transfer(buff, prog_nbytes);
      prog_nbytes = prog_nbytes - Serial.write(buff, prog_nbytes);
    }

    Serial.flush();

    bytesread = Serial.readBytes(buff, 1);
      if ((bytesread == 0) || (buff[0] != ACK)) {
      digitalWrite(CSPin, HIGH);
      return;
      }
  }

  if (spi_cs_hi) digitalWrite(CSPin, HIGH);

}

void spi_cmd_write() {
  int bytesread;
  int prog_nbytes;
  int len;
  byte spi_cs_hi;

  //Получаем остальные данные
  bytesread = Serial.readBytes(buff, 3);
  if (bytesread < 3) {
    Serial.write(ERROR_RECV); //Ошибка
    Serial.flush();
    return;
  }

  digitalWrite(CSPin, LOW);

  spi_cs_hi = buff[0];

  prog_nbytes = buff[1];
  prog_nbytes = prog_nbytes << 8;
  prog_nbytes = prog_nbytes | buff[2];
  len = prog_nbytes;

  Serial.write(FUNC_SPI_WRITE); //Подтверждаем команду
  Serial.flush();

  //Работаем с SPI
  while (prog_nbytes > 0) {
    if (prog_nbytes >= wchunk) {
      bytesread = Serial.readBytes(buff, wchunk);
      SPI.transfer(buff, wchunk);
    } else {
      bytesread = Serial.readBytes(buff, prog_nbytes);
      SPI.transfer(buff, prog_nbytes);
    }

    if (bytesread == 0) {
      digitalWrite(CSPin, HIGH);
      return;
    }

    prog_nbytes = prog_nbytes - bytesread;

    Serial.write(ACK);
    Serial.flush();
  }

  if (spi_cs_hi) digitalWrite(CSPin, HIGH);
}
<commit_msg>Поправлен режим cs пина в прошивке ардуино<commit_after>#include <SPI.h>
#include <Wire.h>
#include "spi_cmd.h"
#include "commands.h"

extern byte buff[256];

void spi_cmd_init() {
  long spi_speed;
  byte bytesread;

  bytesread = Serial.readBytes(buff, 1);

  if (bytesread == 0) {
    Serial.write(ERROR_RECV); //Ошибка
    Serial.flush();
    return;
  }

  if (buff[0] == 0) {
    spi_speed = 8000000;
  } else if (buff[0] == 1) {
    spi_speed = 4000000;
  } else if (buff[0] == 2) {
    spi_speed = 2000000;
  } else if (buff[0] == 3) {
    spi_speed = 1000000;
  } else {
    spi_speed = 8000000;
  }

  SPI.begin();
  SPI.beginTransaction(SPISettings(spi_speed, MSBFIRST, SPI_MODE0));
  pinMode(CSPin, OUTPUT);

  Serial.write(FUNC_SPI_INIT); //Подтверждаем команду
  Serial.flush();
}

void spi_cmd_deinit() {
  SPI.endTransaction();
  SPI.end();
  pinMode(CSPin, INPUT);

  Serial.write(FUNC_SPI_DEINIT); //Подтверждаем команду
  Serial.flush();
}

void spi_cmd_read() {
  int bytesread;
  int prog_nbytes;
  byte spi_cs_hi;

  //Получаем остальные данные
  bytesread = Serial.readBytes(buff, 3);
  if (bytesread < 3) {
    Serial.write(ERROR_RECV); //Ошибка
    Serial.flush();
    return;
  }

  digitalWrite(CSPin, LOW);

  spi_cs_hi = buff[0];

  prog_nbytes = buff[1];
  prog_nbytes = prog_nbytes << 8;
  prog_nbytes = prog_nbytes | buff[2];

  Serial.write(FUNC_SPI_READ); //Подтверждаем команду
  Serial.flush();

  //Работаем с SPI
  while (prog_nbytes > 0) {
    if (prog_nbytes >= rchunk) {
      SPI.transfer(buff, rchunk);
      prog_nbytes = prog_nbytes - Serial.write(buff, rchunk);
    } else {
      SPI.transfer(buff, prog_nbytes);
      prog_nbytes = prog_nbytes - Serial.write(buff, prog_nbytes);
    }

    Serial.flush();

    bytesread = Serial.readBytes(buff, 1);
      if ((bytesread == 0) || (buff[0] != ACK)) {
      digitalWrite(CSPin, HIGH);
      return;
      }
  }

  if (spi_cs_hi) digitalWrite(CSPin, HIGH);

}

void spi_cmd_write() {
  int bytesread;
  int prog_nbytes;
  int len;
  byte spi_cs_hi;

  //Получаем остальные данные
  bytesread = Serial.readBytes(buff, 3);
  if (bytesread < 3) {
    Serial.write(ERROR_RECV); //Ошибка
    Serial.flush();
    return;
  }

  digitalWrite(CSPin, LOW);

  spi_cs_hi = buff[0];

  prog_nbytes = buff[1];
  prog_nbytes = prog_nbytes << 8;
  prog_nbytes = prog_nbytes | buff[2];
  len = prog_nbytes;

  Serial.write(FUNC_SPI_WRITE); //Подтверждаем команду
  Serial.flush();

  //Работаем с SPI
  while (prog_nbytes > 0) {
    if (prog_nbytes >= wchunk) {
      bytesread = Serial.readBytes(buff, wchunk);
      SPI.transfer(buff, wchunk);
    } else {
      bytesread = Serial.readBytes(buff, prog_nbytes);
      SPI.transfer(buff, prog_nbytes);
    }

    if (bytesread == 0) {
      digitalWrite(CSPin, HIGH);
      return;
    }

    prog_nbytes = prog_nbytes - bytesread;

    Serial.write(ACK);
    Serial.flush();
  }

  if (spi_cs_hi) digitalWrite(CSPin, HIGH);
}
<|endoftext|>


<commit_before>// Fizzim.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "basictypes.h"

#include <vector>

// TestParser.cpp : Defines the entry point for the console application.
//

#include <expat.h>

#include <string>

int Depth;

FILE* outFile;
class Group;
static std::vector<Group*> s_Groups;
static std::vector<char*> s_Strings;

class Group
{
public:
	Group() :	m_BoxID(-1),
				m_TextID(-1),
				m_ArcID(-1),
				m_From(-1),
				m_To(-1)
	{
	}

	void Render(FILE* outFile)
	{
		if (m_BoxID != -1)
		{
			fprintf(outFile, "box %ld, %s\n", m_BoxID, s_Strings[m_TextID]);
		}
		else if (m_ArcID != -1)
		{
			fprintf(outFile, "arc %ld, %s from %ld to %ld\n", m_ArcID, s_Strings[m_TextID], m_From, m_To);
		}
	}

	int16 m_BoxID;
	int16 m_TextID;
	int16 m_ArcID;
	int16 m_From;
	int16 m_To;
};

#define kBox 0
#define kArc 1
#define kText 2

static Group* s_pCurrGroup = 0;

static int groupNest = 0;

static void start(void *data, const char *el, const char **attr)
{
	// parse group
	if (!strcmp(el, "dia:group"))
	{
		if (s_pCurrGroup)
			printf("Error - nested groups not yet supported\n");

		++groupNest;
	}

	// else parse object and its attributes
	// currently, all objects have to be contained within a group
	else if (!strcmp(el, "dia:object"))
	{
		if (!s_pCurrGroup)
		{
			s_pCurrGroup = new Group();
		}

		int16 kind = -1;
		int16 id;
		for (int i = 0; attr[i]; i += 2)
		{
			if (!strcmp(attr[i], "type"))
			{
				if (!strcmp(attr[i+1], "UML - State"))
				{
					kind = kBox;
				}
				else if (!strcmp(attr[i+1], "Standard - Box"))
				{
					kind = kBox;
				}
				else if (!strcmp(attr[i+1], "Standard - Text"))
				{
					kind = kText;
				}
				else if (!strcmp(attr[i+1], "FS - Orthflow"))
				{
					kind = kArc;
				}
				else if (!strcmp(attr[i+1], "Standard - ZigZagLine"))
				{
					kind = kArc;
				}
			}
			else if (!strcmp(attr[i], "id"))
			{
				const char* sId = attr[i+1];
				id = atoi(&sId[1]);
			}
		}

		switch (kind)
		{
		case kBox:	s_pCurrGroup->m_BoxID = id; break;

		// don't record text, text id's are actually the names
		//case kText:	s_pCurrGroup->m_TextID = id; break;

		case kArc:	s_pCurrGroup->m_ArcID = id; break;
		}
	}

	// we might actually be a connection
	else if (s_pCurrGroup && !strcmp(el, "dia:connection"))
	{
		int16 handle = -1;
		int16 to;
		for (int i = 0; attr[i]; i += 2)
		{
			if (!strcmp(attr[i], "handle"))
			{
				handle = atoi(attr[i+1]);
			}
			else if (!strcmp(attr[i], "to"))
			{
				const char* sId = attr[i+1];
				to = atoi(&sId[1]);
			}
		}

		if (handle == 0)
			s_pCurrGroup->m_From = to;
		else
			s_pCurrGroup->m_To = to;
	}

  int i;

  for (i = 0; i < Depth; i++)
    fprintf(outFile, "  ");

  fprintf(outFile, "%s", el);

  for (i = 0; attr[i]; i += 2) {
    fprintf(outFile, " %s='%s'", attr[i], attr[i + 1]);
  }

  fprintf(outFile, "\n");
  Depth++;
}  /* End of start handler */

static void end(void *data, const char *el)
{
	if (s_pCurrGroup)
	{
		// terminating a group?
		if (!strcmp(el, "dia:group"))
		{
			--groupNest;

			// if completely denested...
			if (!groupNest)
			{
				s_Groups.push_back(s_pCurrGroup);
				s_pCurrGroup = 0;
			}
		}

		// terminating an object?
		else if (!strcmp(el, "dia:object"))
		{
			// if not grouped, push back the current group
			if (0 == groupNest)
			{
				s_Groups.push_back(s_pCurrGroup);
				s_pCurrGroup = 0;
			}
		}
	}

	Depth--;
}  /* End of end handler */

static void FizzimCharacterDataHandler(void *userData, const XML_Char *s, int len)
{
	if (s_pCurrGroup && s[0] == '#')
	{
		char buff[2048];
		strncpy(buff, s+1, len-1);

		if (s[len-1] != '#')
		{
			printf("Error - Found whitespace in name. %s", buff);
		}
		else
		{
			buff[len-2] = '\0';	// discard the trailing #
		}

		if (s_pCurrGroup->m_ArcID != -1)
		{
			char* pString = new char[len+1];
			strcpy(pString, buff);
			s_pCurrGroup->m_TextID = s_Strings.size();
			s_Strings.push_back(pString);
			printf("Arc: textid:%ld %s\n", s_pCurrGroup->m_TextID, buff);
		}
		else if (s_pCurrGroup->m_BoxID != -1)
		{
			char* pString = new char[len+1];
			strcpy(pString, buff);
			s_pCurrGroup->m_TextID = s_Strings.size();
			s_Strings.push_back(pString);
			printf("Node: textid:%ld %s\n", s_pCurrGroup->m_TextID, buff);
		}
		else
		{
			printf("??? %s\n", buff);
		}
	}
}

void SanityCheck()
{
	// first, make sure one and only start node exists
	int startNodes = 0;

	int i;
	for (i = 0; i < s_Strings.size(); ++i)
	{
		if (!stricmp("start", s_Strings[i]))
		{
			++startNodes;
		}
	}

	switch(startNodes)
	{
	case 0:		printf("Error: No start node found\n");	break;
	case 1:												break;	// perfect
	default:	printf("Error: More than one start node found\n"); break;
	}
}

int main(int argc, char* argv[])
{
	if (argc < 2)
	{
		printf("No filename specified.\n");
		exit(-1);
	}

	outFile = fopen("test.txt", "wt");

	std::string filename(argv[1]);

	FILE* inFile = fopen(filename.c_str(), "rb");
	int result = fseek(inFile, 0, SEEK_END);
	int fileLength = ftell(inFile);
	result = fseek(inFile, 0, SEEK_SET);

	char* buffer = new char[fileLength+2];

	fileLength = fread(buffer, 1, fileLength, inFile);
	buffer[fileLength] = 0;

	printf("read %ld bytes\n", fileLength);

	XML_Parser p = XML_ParserCreate(NULL);
	if (! p) {
		fprintf(stderr, "Couldn't allocate memory for parser\n");
		exit(-1);
	}

	XML_SetElementHandler(p, start, end);
	XML_SetCharacterDataHandler(p, FizzimCharacterDataHandler);

	bool done = false;

	if (! XML_Parse(p, buffer, fileLength-1, done))
	{
		printf("Parse error at line %d:\n%s\n",
			XML_GetCurrentLineNumber(p),
			XML_ErrorString(XML_GetErrorCode(p)));
		done = true;
	}

	fclose(outFile);

	// now sanity check the read-in data

	SanityCheck();

	outFile = fopen("test.fsm", "wt");

	fprintf(outFile, "nodes: \n");

	printf("Found %ld groups\n", s_Groups.size());

	int i;
	for (i = 0; i < s_Groups.size(); ++i)
		s_Groups[i]->Render(outFile);

	fclose(outFile);

	// deallocate the groups
	for (i = 0; i < s_Groups.size(); ++i)
		delete s_Groups[i];

	delete [] buffer;

	return 0;
}
<commit_msg>successfully parses a dia file and outputs a landru file as a test<commit_after>// Fizzim.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <vector>

#include <expat.h>

#include "basictypes.h"
#include "Fizzim.h"
#include "StringTable.h"

///////////////////// LANDRU EXPORT ////////////////////////////////////

void FizzimLandruExport(FILE* pOutFile, Fizzim::MachineSet& machines)
{
	fprintf(pOutFile, "Landru {\n");
	for (int i = 0; i < machines.m_Nodes.size(); ++i)
	{
		int machineName = machines.m_Nodes[i]->m_Name;
		fprintf(pOutFile, "   %s {\n", s_StringTable[machineName]);

		for (int j = 0; j < machines.m_Nodes[i]->m_Transitions.size(); ++j)
		{
			int gotoID = machines.m_Nodes[machines.m_Nodes[i]->m_Transitions[j]->m_To]->m_Name;
			int conditionID = machines.m_Nodes[i]->m_Transitions[j]->m_Condition;
			fprintf(pOutFile, "      on (%s) { goto %s }\n", s_StringTable[conditionID], s_StringTable[gotoID]);
		}
		fprintf(pOutFile, "   }\n");
	}
	fprintf(pOutFile, "}\n");
}

///////////////////// XML IMPORT  /////////////////////////////////////

int Depth;

FILE* outFile;
class Group;
static std::vector<Group*> s_Groups;

static StringTable s_StringTable;

class Group
{
public:
	Group() :	m_NodeID(-1),
				m_TextID(-1),
				m_ArcID(-1),
				m_From(-1),
				m_To(-1)
	{
	}

	void Render(FILE* outFile)
	{
		if (m_NodeID != -1)
		{
			fprintf(outFile, "box %ld, %s\n", m_NodeID, s_StringTable[m_TextID]);
		}
		else if (m_ArcID != -1)
		{
			fprintf(outFile, "arc %ld, %s from %ld to %ld\n", m_ArcID, s_StringTable[m_TextID], m_From, m_To);
		}
	}

	int16 m_NodeID;
	int16 m_TextID;
	int16 m_ArcID;
	int16 m_From;
	int16 m_To;
};

#define kBox 0
#define kArc 1
#define kText 2

static Group* s_pCurrGroup = 0;

static int groupNest = 0;

static void start(void *data, const char *el, const char **attr)
{
	// parse group
	if (!strcmp(el, "dia:group"))
	{
		if (s_pCurrGroup)
			printf("Error - nested groups not yet supported\n");

		++groupNest;
	}

	// else parse object and its attributes
	// currently, all objects have to be contained within a group
	else if (!strcmp(el, "dia:object"))
	{
		if (!s_pCurrGroup)
		{
			s_pCurrGroup = new Group();
		}

		int16 kind = -1;
		int16 id;
		for (int i = 0; attr[i]; i += 2)
		{
			if (!strcmp(attr[i], "type"))
			{
				if (!strcmp(attr[i+1], "UML - State"))
				{
					kind = kBox;
				}
				else if (!strcmp(attr[i+1], "Standard - Box"))
				{
					kind = kBox;
				}
				else if (!strcmp(attr[i+1], "Standard - Text"))
				{
					kind = kText;
				}
				else if (!strcmp(attr[i+1], "FS - Orthflow"))
				{
					kind = kArc;
				}
				else if (!strcmp(attr[i+1], "Standard - ZigZagLine"))
				{
					kind = kArc;
				}
			}
			else if (!strcmp(attr[i], "id"))
			{
				const char* sId = attr[i+1];
				id = atoi(&sId[1]);
			}
		}

		switch (kind)
		{
		case kBox:	s_pCurrGroup->m_NodeID = id; break;

		// don't record text, text id's are actually the names
		//case kText:	s_pCurrGroup->m_TextID = id; break;

		case kArc:	s_pCurrGroup->m_ArcID = id; break;
		}
	}

	// we might actually be a connection
	else if (s_pCurrGroup && !strcmp(el, "dia:connection"))
	{
		int16 handle = -1;
		int16 to;
		for (int i = 0; attr[i]; i += 2)
		{
			if (!strcmp(attr[i], "handle"))
			{
				handle = atoi(attr[i+1]);
			}
			else if (!strcmp(attr[i], "to"))
			{
				const char* sId = attr[i+1];
				to = atoi(&sId[1]);
			}
		}

		if (handle == 0)
			s_pCurrGroup->m_From = to;
		else
			s_pCurrGroup->m_To = to;
	}

  int i;

  for (i = 0; i < Depth; i++)
    fprintf(outFile, "  ");

  fprintf(outFile, "%s", el);

  for (i = 0; attr[i]; i += 2) {
    fprintf(outFile, " %s='%s'", attr[i], attr[i + 1]);
  }

  fprintf(outFile, "\n");
  Depth++;
}  /* End of start handler */

static void end(void *data, const char *el)
{
	if (s_pCurrGroup)
	{
		// terminating a group?
		if (!strcmp(el, "dia:group"))
		{
			--groupNest;

			// if completely denested...
			if (!groupNest)
			{
				s_Groups.push_back(s_pCurrGroup);
				s_pCurrGroup = 0;
			}
		}

		// terminating an object?
		else if (!strcmp(el, "dia:object"))
		{
			// if not grouped, push back the current group
			if (0 == groupNest)
			{
				s_Groups.push_back(s_pCurrGroup);
				s_pCurrGroup = 0;
			}
		}
	}

	--Depth;
}  /* End of end handler */

static void FizzimCharacterDataHandler(void *userData, const XML_Char *s, int len)
{
	if (s_pCurrGroup && s[0] == '#')
	{
		char buff[2048];
		strncpy(buff, s+1, len-1);

		if (s[len-1] != '#')
		{
			printf("Error - Found whitespace in name. %s", buff);
		}
		else
		{
			buff[len-2] = '\0';	// discard the trailing #
		}

		if (s_pCurrGroup->m_ArcID != -1)
		{
			char* pString = new char[len+1];
			strcpy(pString, buff);
			s_pCurrGroup->m_TextID = s_StringTable.Add(pString);
		}
		else if (s_pCurrGroup->m_NodeID != -1)
		{
			char* pString = new char[len+1];
			strcpy(pString, buff);
			s_pCurrGroup->m_TextID = s_StringTable.Add(pString);
		}
		else
		{
			printf("??? %s\n", buff);
		}
	}
}

void SanityCheck()
{
}

class NodeDescriptor
{
public:
	NodeDescriptor(int id, int name) : m_ID(id), m_TextID(name), m_HasIncomingArc(false) { }

	int		m_ID;
	int		m_TextID;
	bool	m_HasIncomingArc;
};

class ArcDescriptor
{
public:
	ArcDescriptor(int id, int name, int from, int to) : m_ID(id), m_TextID(name), m_From(from), m_To(to) { }

	int		m_ID;
	int		m_TextID;
	int		m_From;
	int		m_To;
};

void CreateMachines(Fizzim::MachineSet& machines)
{
	int i;

	std::vector <NodeDescriptor*>	allNodes;
	std::vector <ArcDescriptor*>	allArcs;

	// find all nodes and arcs
	for (i = 0; i < s_Groups.size(); ++i)
	{
		if (s_Groups[i]->m_NodeID != -1)
		{
			NodeDescriptor* pND = new NodeDescriptor(s_Groups[i]->m_NodeID, s_Groups[i]->m_TextID);
			allNodes.push_back(pND);
		}
		else if (s_Groups[i]->m_ArcID != -1)
		{
			ArcDescriptor* pAD = new ArcDescriptor(s_Groups[i]->m_NodeID, s_Groups[i]->m_TextID, s_Groups[i]->m_From, s_Groups[i]->m_To);
			allArcs.push_back(pAD);
		}
	}

	// now mark all nodes that are transitioned into
	for (i = 0; i < allArcs.size(); ++i)
	{
		int to = allArcs[i]->m_To;
		for (int j = 0; j < allNodes.size(); ++j)
		{
			if (allNodes[j]->m_ID == to)
				allNodes[j]->m_HasIncomingArc = true;
		}
	}

	std::vector <int> nodeIDs;

	// loop over all nodes
	for (i = 0; i < allNodes.size(); ++i)
	{
		// record all start nodes
		if (!allNodes[i]->m_HasIncomingArc)
		{
			machines.m_StartNodes.push_back(machines.m_Nodes.size());
		}

		int id = allNodes[i]->m_ID;

		// record all states
		Fizzim::Node* pNode = new Fizzim::Node(allNodes[i]->m_TextID);
		nodeIDs.push_back(allNodes[i]->m_ID);

		// add all transitions from this state
		for (int j = 0; j < allArcs.size(); ++j)
		{
			if (allArcs[j]->m_From == id)
			{
				Fizzim::Transition* pTrans = new Fizzim::Transition(allArcs[j]->m_TextID, allArcs[j]->m_To);
				pNode->m_Transitions.push_back(pTrans);
			}
		}

		machines.m_Nodes.push_back(pNode);
	}

	// now resolve all transitions to refer to the proper nodes

	for (i = 0; i < machines.m_Nodes.size(); ++i)
	{
		// loop over all transitions within a state
		for (int j = 0; j < machines.m_Nodes[i]->m_Transitions.size(); ++j)
		{
			// search all nodeIDs for the one to transition to
			for (int k = 0; k < nodeIDs.size(); ++k)
			{
				// if the cached nodeID refers to the node we want to transition to,
				if (machines.m_Nodes[i]->m_Transitions[j]->m_To == nodeIDs[k])
				{
					// then k is the index of the node we are transitioning to
					machines.m_Nodes[i]->m_Transitions[j]->m_To = k;

					// stop the search and continue with the next transition.
					break;
				}
			}
		}
	}

	// clean up
	for (i = 0; i < allNodes.size(); ++i)
		delete allNodes[i];
	for (i = 0; i < allArcs.size(); ++i)
		delete allArcs[i];
}

///////////////////// MAIN /////////////////////////////////////////////

int main(int argc, char* argv[])
{
	if (argc < 2)
	{
		printf("No filename specified.\n");
		exit(-1);
	}

	outFile = fopen("test.txt", "wt");

	std::string filename(argv[1]);

	FILE* inFile = fopen(filename.c_str(), "rb");
	int result = fseek(inFile, 0, SEEK_END);
	int fileLength = ftell(inFile);
	result = fseek(inFile, 0, SEEK_SET);

	char* buffer = new char[fileLength+2];

	fileLength = fread(buffer, 1, fileLength, inFile);
	buffer[fileLength] = 0;

	printf("read %ld bytes\n", fileLength);

	XML_Parser p = XML_ParserCreate(NULL);
	if (! p) {
		fprintf(stderr, "Couldn't allocate memory for parser\n");
		exit(-1);
	}

	XML_SetElementHandler(p, start, end);
	XML_SetCharacterDataHandler(p, FizzimCharacterDataHandler);

	bool done = false;

	if (! XML_Parse(p, buffer, fileLength-1, done))
	{
		printf("Parse error at line %d:\n%s\n",
			XML_GetCurrentLineNumber(p),
			XML_ErrorString(XML_GetErrorCode(p)));
		done = true;
	}

	fclose(outFile);

	Fizzim::MachineSet machines;
	CreateMachines(machines);

	outFile = fopen("test.landru", "wt");
	FizzimLandruExport(outFile, machines);
	fclose(outFile);

	// now sanity check the read-in data
	SanityCheck();

	// deallocate the groups
	for (int i = 0; i < s_Groups.size(); ++i)
		delete s_Groups[i];

	delete [] buffer;

	return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2016 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <folly/portability/Fcntl.h>

#ifdef _WIN32
#include <folly/portability/Sockets.h>
#include <folly/portability/Windows.h>

namespace folly {
namespace portability {
namespace fcntl {
int creat(char const* fn, int pm) { return _creat(fn, pm); }

int fcntl(int fd, int cmd, ...) {
  va_list args;
  int res = -1;
  va_start(args, cmd);
  switch (cmd) {
    case F_GETFD: {
      HANDLE h = (HANDLE)_get_osfhandle(fd);
      if (h != INVALID_HANDLE_VALUE) {
        DWORD flags;
        if (GetHandleInformation(h, &flags)) {
          res = flags & HANDLE_FLAG_INHERIT;
        }
      }
      break;
    }
    case F_SETFD: {
      int flags = va_arg(args, int);
      HANDLE h = (HANDLE)_get_osfhandle(fd);
      if (h != INVALID_HANDLE_VALUE) {
        if (SetHandleInformation(
                h, HANDLE_FLAG_INHERIT, (DWORD)(flags & FD_CLOEXEC))) {
          res = 0;
        }
      }
      break;
    }
    case F_GETFL: {
      // No idea how to get the IO blocking mode, so return 0.
      res = 0;
      break;
    }
    case F_SETFL: {
      int flags = va_arg(args, int);
      if (flags & O_NONBLOCK) {
        // If it's not a socket, it's probably a pipe, and
        // those are non-blocking by default with Windows.
        if (folly::portability::sockets::is_fh_socket(fd)) {
          SOCKET s = (SOCKET)_get_osfhandle(fd);
          if (s != INVALID_SOCKET) {
            u_long nonBlockingEnabled = 1;
            res = ioctlsocket(s, FIONBIO, &nonBlockingEnabled);
          }
        } else {
          res = 0;
        }
      }
      break;
    }
  }
  va_end(args);
  return res;
}

int open(char const* fn, int of, int pm) {
  int fh;
  errno_t res = _sopen_s(&fh, fn, of, _SH_DENYNO, pm);
  return res ? -1 : fh;
}

int posix_fallocate(int fd, off_t offset, off_t len) {
  // We'll pretend we always have enough space. We
  // can't exactly pre-allocate on windows anyways.
  return 0;
}
}
}
}
#endif
<commit_msg>Fix the mode being used in the implementation of open in the Fcntl portability header<commit_after>/*
 * Copyright 2016 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <folly/portability/Fcntl.h>

#ifdef _WIN32
#include <folly/portability/Sockets.h>
#include <folly/portability/SysStat.h>
#include <folly/portability/Windows.h>

namespace folly {
namespace portability {
namespace fcntl {
int creat(char const* fn, int pm) { return _creat(fn, pm); }

int fcntl(int fd, int cmd, ...) {
  va_list args;
  int res = -1;
  va_start(args, cmd);
  switch (cmd) {
    case F_GETFD: {
      HANDLE h = (HANDLE)_get_osfhandle(fd);
      if (h != INVALID_HANDLE_VALUE) {
        DWORD flags;
        if (GetHandleInformation(h, &flags)) {
          res = flags & HANDLE_FLAG_INHERIT;
        }
      }
      break;
    }
    case F_SETFD: {
      int flags = va_arg(args, int);
      HANDLE h = (HANDLE)_get_osfhandle(fd);
      if (h != INVALID_HANDLE_VALUE) {
        if (SetHandleInformation(
                h, HANDLE_FLAG_INHERIT, (DWORD)(flags & FD_CLOEXEC))) {
          res = 0;
        }
      }
      break;
    }
    case F_GETFL: {
      // No idea how to get the IO blocking mode, so return 0.
      res = 0;
      break;
    }
    case F_SETFL: {
      int flags = va_arg(args, int);
      if (flags & O_NONBLOCK) {
        // If it's not a socket, it's probably a pipe, and
        // those are non-blocking by default with Windows.
        if (folly::portability::sockets::is_fh_socket(fd)) {
          SOCKET s = (SOCKET)_get_osfhandle(fd);
          if (s != INVALID_SOCKET) {
            u_long nonBlockingEnabled = 1;
            res = ioctlsocket(s, FIONBIO, &nonBlockingEnabled);
          }
        } else {
          res = 0;
        }
      }
      break;
    }
  }
  va_end(args);
  return res;
}

int open(char const* fn, int of, int pm) {
  int fh;
  int realMode = _S_IREAD;
  if ((of & _O_RDWR) == _O_RDWR) {
    realMode = _S_IREAD | _S_IWRITE;
  } else if ((of & _O_WRONLY) == _O_WRONLY) {
    realMode = _S_IWRITE;
  } else if ((of & _O_RDONLY) != _O_RDONLY) {
    // One of these needs to be present, just fail if
    // none are.
    return -1;
  }
  errno_t res = _sopen_s(&fh, fn, of, _SH_DENYNO, realMode);
  return res ? -1 : fh;
}

int posix_fallocate(int fd, off_t offset, off_t len) {
  // We'll pretend we always have enough space. We
  // can't exactly pre-allocate on windows anyways.
  return 0;
}
}
}
}
#endif
<|endoftext|>


<commit_before>/***************************************************************************
 *  @file       main.cpp
 *  @author     Alan.W
 *  @date       28  Jan 2014
 *  @remark     This code is for the exercises from C++ Primer 5th Edition
 *  @note
 ***************************************************************************/
// Exercise 15.28:
// Define a vector to hold Quote objects but put Bulk_quote objects into that
// vector. Compute the total net_price of all the elements in the vector.
//
// Exercise 15.29:
// Repeat your program, but this time store shared_ptrs to objects of type
// Quote. Explain any discrepancy in the sum generated by the this version and
// the previous program.
//
//  Since the vector from the previous exercise holds objects, there's no polymorphism
//  happened while calling the virtual function net_price. Essentially, the obejcts
//  held in it are the Quote subjects of the Bulk_quote objects being pushed back,
//  Thus, the virtual net_price functions called are Quote::net_price. As a result,
//  no discount was applied. The outcome was 9090
//
//  The obejcts held for this exercise are smart pointers to the Quote objects.In this
//  case, ppolymorphism happened as expected.The actual virtual functions being called
//  are Bulk_quote::net_price that ensure discount is applied.Thus, the outcome is 6363.
//  It can be found that 30% dicount has been applied to the price calculation.
//
//
// If there is no discrepancy, explain why there isn’t one.
//

#include <iostream>
#include <string>
#include <vector>
#include <memory>

#include "quote.h"
#include "bulk_quote.h"
#include "limit_quote.h"
#include "disc_quote.h"

int main()
{
    /**
     * @brief ex15.28   outcome == 9090
     */
    std::vector<Quote> v;
    for(unsigned i =1; i != 10; ++i)
        v.push_back(Bulk_quote("sss", i * 10.1, 10, 0.3));

    double total = 0;
    for (const auto& b : v)
    {
        total += b.net_price(20);
    }
    std::cout << total << std::endl;

    std::cout << "======================\n\n";

    /**
     * @brief ex15.29   outccome == 6363
     */
    std::vector<std::shared_ptr<Quote>> pv;

    for(unsigned i =1; i != 10; ++i)
        pv.push_back(std::make_shared<Bulk_quote>(Bulk_quote("sss", i * 10.1, 10, 0.3)));

    double total_p = 0;
    for (auto p : pv)
    {
        total_p +=  p->net_price(20);
    }
    std::cout << total_p << std::endl;

    return 0;

}
<commit_msg>fixed a little typo in ex15.28.29/main.cpp<commit_after>/***************************************************************************
 *  @file       main.cpp
 *  @author     Alan.W
 *  @date       28  Jan 2014
 *  @remark     This code is for the exercises from C++ Primer 5th Edition
 *  @note
 ***************************************************************************/
// Exercise 15.28:
// Define a vector to hold Quote objects but put Bulk_quote objects into that
// vector. Compute the total net_price of all the elements in the vector.
//
// Exercise 15.29:
// Repeat your program, but this time store shared_ptrs to objects of type
// Quote. Explain any discrepancy in the sum generated by the this version and
// the previous program.
//
//  Since the vector from the previous exercise holds objects, there's no polymorphism
//  happened while calling the virtual function net_price. Essentially, the objects
//  held in it are the Quote subjects of the Bulk_quote objects being pushed back,
//  Thus, the virtual net_price functions called are Quote::net_price. As a result,
//  no discount was applied. The outcome was 9090
//
//  The obejcts held for this exercise are smart pointers to the Quote objects.In this
//  case, ppolymorphism happened as expected.The actual virtual functions being called
//  are Bulk_quote::net_price that ensure discount is applied.Thus, the outcome is 6363.
//  It can be found that 30% dicount has been applied to the price calculation.
//
//
// If there is no discrepancy, explain why there isn’t one.
//

#include <iostream>
#include <string>
#include <vector>
#include <memory>

#include "quote.h"
#include "bulk_quote.h"
#include "limit_quote.h"
#include "disc_quote.h"

int main()
{
    /**
     * @brief ex15.28   outcome == 9090
     */
    std::vector<Quote> v;
    for(unsigned i =1; i != 10; ++i)
        v.push_back(Bulk_quote("sss", i * 10.1, 10, 0.3));

    double total = 0;
    for (const auto& b : v)
    {
        total += b.net_price(20);
    }
    std::cout << total << std::endl;

    std::cout << "======================\n\n";

    /**
     * @brief ex15.29   outccome == 6363
     */
    std::vector<std::shared_ptr<Quote>> pv;

    for(unsigned i =1; i != 10; ++i)
        pv.push_back(std::make_shared<Bulk_quote>(Bulk_quote("sss", i * 10.1, 10, 0.3)));

    double total_p = 0;
    for (auto p : pv)
    {
        total_p +=  p->net_price(20);
    }
    std::cout << total_p << std::endl;

    return 0;

}
<|endoftext|>