<commit_before>/*
 * IceWM
 *
 * Copyright (C) 1997-2002 Marko Macek
 */
#include "config.h"

#ifndef NO_WINDOW_OPTIONS
#include "yfull.h"
#include "wmoption.h"
#include "wmframe.h"

#include "WinMgr.h"
#include "base.h"
#include "sysdep.h"
#include <stdlib.h>

#include "intl.h"

#if 0
static int strnullcmp(const char *a, const char *b) {
    return a ? (b ? strcmp(a, b) : 1) : (b ? -1 : 0);
}
#endif

upath winOptFile;
WindowOptions *defOptions = 0;
WindowOptions *hintOptions = 0;

WindowOption::WindowOption(ustring n_class_instance):
    w_class_instance(n_class_instance),
    icon(0),
    functions(0), function_mask(0),
    decors(0), decor_mask(0),
    options(0), option_mask(0),
    workspace(WinWorkspaceInvalid),
    layer(WinLayerInvalid),
#ifdef CONFIG_TRAY
    tray(WinTrayInvalid),
#endif
    gflags(0), gx(0), gy(0), gw(0), gh(0)
{
}

WindowOption::~WindowOption() {
    ////delete[] name; name = 0;
    ////delete[] icon; icon = 0;
}

static int wo_cmp(ustring a_class_instance,
                  const WindowOption *pivot)
{
    int cmp = a_class_instance.compareTo(pivot->w_class_instance);
    return cmp;
}

WindowOption *WindowOptions::getWindowOption(ustring a_class_instance,
                                             bool create, bool remove)
{
    int lo = 0, hi = fWinOptions.getCount();

    while (lo < hi) {
        const int pv = (lo + hi) / 2;
	const WindowOption *pivot = fWinOptions[pv];

        int cmp = wo_cmp(a_class_instance,
                         pivot);
        if (cmp > 0) {
            lo = pv + 1;
            continue;
        } else if (cmp < 0) {
            hi = pv;
            continue;
        }

        if (remove) {
            static WindowOption result = *pivot;
            fWinOptions.remove(pv);
            return &result;
        }

        return fWinOptions.getItem(pv);
    }

    if (!create) return 0;

    WindowOption *newopt = new WindowOption(a_class_instance);

    MSG(("inserting window option %p at position %d", newopt, lo));
    fWinOptions.insert(lo, newopt);

#ifdef DEBUG
    for (int i = 0; i < fWinOptions.getCount(); ++i)
    	MSG(("> %d: %p", i, fWinOptions[i]));
#endif

    return newopt;
}

void WindowOptions::setWinOption(ustring n_class_instance,
                                 const char *opt, const char *arg)
{
    WindowOption *op = getWindowOption(n_class_instance, true);

    //msg("%s-%s-%s", class_instance, opt, arg);

    if (strcmp(opt, "icon") == 0) {
        delete [] op->icon;
        op->icon = newstr(arg);
    } else if (strcmp(opt, "workspace") == 0) {
        op->workspace = atoi(arg);
    } else if (strcmp(opt, "geometry") == 0) {
        int rx, ry;
        unsigned int rw, rh;

        op->gx = 0;
        op->gy = 0;
        op->gw = 0;
        op->gh = 0;

        //msg("parsing %s", arg);
        if ((op->gflags = XParseGeometry(arg, &rx, &ry, &rw, &rh)) != 0) {
            if (op->gflags & XNegative)
                rx = - rx;
            if (op->gflags & YNegative)
                ry = - ry;
            op->gx = rx;
            op->gy = ry;
            op->gw = rw;
            op->gh = rh;
            //msg("parsed %d %d %d %d %X", rx, ry, rw, rh, op->gflags);
        }
    } else if (strcmp(opt, "layer") == 0) {
        char *endptr;
        long l = strtol(arg, &endptr, 10);

        op->layer = WinLayerInvalid;

        if (arg[0] && !endptr[0])
            op->layer = l;
        else {
            struct {
                const char *name;
                int layer;
            } layers[] = {
                { "Desktop", WinLayerDesktop }, //
                { "Below", WinLayerBelow }, //
                { "Normal", WinLayerNormal }, //
                { "OnTop", WinLayerOnTop }, //
                { "Dock", WinLayerDock }, //
                { "AboveDock", WinLayerAboveDock }, //
                { "Menu", WinLayerMenu }
            };
            for (unsigned int i = 0; i < ACOUNT(layers); i++)
                if (strcmp(layers[i].name, arg) == 0)
                    op->layer = layers[i].layer;
        }
#ifdef CONFIG_TRAY
    } else if (strcmp(opt, "tray") == 0) {
        char *endptr;
        long const t(strtol(arg, &endptr, 10));

        op->tray = WinTrayInvalid;

        if (arg[0] && !endptr[0])
            op->tray = t;
        else {
            struct {
                const char *name;
                int tray;
            } tray_ops[] = {
                { "Ignore", WinTrayIgnore },
                { "Minimized", WinTrayMinimized },
                { "Exclusive", WinTrayExclusive },
                { "1", WinTrayExclusive }
            };
            for (unsigned int i = 0; i < ACOUNT(tray_ops); i++)
                if (strcmp(tray_ops[i].name, arg) == 0)
                    op->tray = tray_ops[i].tray;
        }
#endif
    } else {
        static struct {
            int what;
            const char *name;
            unsigned long flag;
        } options[] = {
            { 0, "fMove", YFrameWindow::ffMove }, //
            { 0, "fResize", YFrameWindow::ffResize }, //
            { 0, "fClose", YFrameWindow::ffClose }, //
            { 0, "fMinimize", YFrameWindow::ffMinimize }, //
            { 0, "fMaximize", YFrameWindow::ffMaximize }, //
            { 0, "fHide", YFrameWindow::ffHide }, //
            { 0, "fRollup", YFrameWindow::ffRollup }, //
            { 1, "dTitleBar", YFrameWindow::fdTitleBar }, //
            { 1, "dSysMenu", YFrameWindow::fdSysMenu }, //
            { 1, "dBorder", YFrameWindow::fdBorder }, //
            { 1, "dResize", YFrameWindow::fdResize }, //
            { 1, "dClose", YFrameWindow::fdClose }, //
            { 1, "dMinimize", YFrameWindow::fdMinimize }, //
            { 1, "dMaximize", YFrameWindow::fdMaximize }, //
            { 1, "dHide", YFrameWindow::fdHide },
            { 1, "dRollup", YFrameWindow::fdRollup },
            { 1, "dDepth", YFrameWindow::fdDepth },
            { 2, "allWorkspaces", YFrameWindow::foAllWorkspaces }, //
            { 2, "ignoreTaskBar", YFrameWindow::foIgnoreTaskBar }, //
            { 2, "noIgnoreTaskBar", YFrameWindow::foNoIgnoreTaskBar }, //
            { 2, "ignoreWinList", YFrameWindow::foIgnoreWinList }, //
            { 2, "ignoreQuickSwitch", YFrameWindow::foIgnoreQSwitch }, //
            { 2, "fullKeys", YFrameWindow::foFullKeys }, //
            { 2, "noFocusOnAppRaise", YFrameWindow::foNoFocusOnAppRaise }, //
            { 2, "ignoreNoFocusHint", YFrameWindow::foIgnoreNoFocusHint }, //
            { 2, "ignorePositionHint", YFrameWindow::foIgnorePosition }, //
            { 2, "doNotCover", YFrameWindow::foDoNotCover }, //
            { 2, "doNotFocus", YFrameWindow::foDoNotFocus }, //
            { 2, "startFullscreen", YFrameWindow::foFullscreen },
            { 2, "startMinimized", YFrameWindow::foMinimized }, //
            { 2, "startMaximized", YFrameWindow::foMaximizedVert | YFrameWindow::foMaximizedHorz }, //
            { 2, "startMaximizedVert", YFrameWindow::foMaximizedVert }, //
            { 2, "startMaximizedHorz", YFrameWindow::foMaximizedHorz }, //
            { 2, "nonICCCMconfigureRequest", YFrameWindow::foNonICCCMConfigureRequest },
            { 2, "forcedClose", YFrameWindow::foForcedClose },
            { 2, "noFocusOnMap", YFrameWindow::foNoFocusOnMap },
            { 2, "ignoreUrgentHint", YFrameWindow::foIgnoreUrgent },
            { 2, "appTakesFocus", YFrameWindow::foAppTakesFocus }
        };

        for (unsigned int a = 0; a < ACOUNT(options); a++) {
            unsigned long *what, *what_mask;

            if (options[a].what == 0) {
                what = &op->functions;
                what_mask  = &op->function_mask;
            } else if (options[a].what == 1) {
                what = &op->decors;
                what_mask = &op->decor_mask;
            } else if (options[a].what == 2) {
                what = &op->options;
                what_mask = &op->option_mask;
            } else {
                msg(_("Error in window option: %s"), opt);
                break;
            }

            if (strcmp(opt, options[a].name) == 0) {
                if (*what == 2 && options[a].flag == YFrameWindow::foIgnoreWinList)
                    DEPRECATE("ignoreWinlist windowoption");
                if (*what == 2 && options[a].flag == YFrameWindow::foIgnoreQSwitch)
                    DEPRECATE("ignoreQuickSwitch windowoption");
                if (atoi(arg) != 0)
                    *what = (*what) | options[a].flag;
                else
                    *what = (*what) & ~options[a].flag;
                *what_mask =  (*what_mask) | options[a].flag;
                return ;
            }
        }
        msg(_("Unknown window option: %s"), opt);
    }
}

void WindowOptions::mergeWindowOption(WindowOption &cm,
                                      ustring a_class_instance,
                                      bool remove)
{
    WindowOption *wo = getWindowOption(a_class_instance, false, remove);
    if (wo)
        combineOptions(cm, *wo);
}

void WindowOptions::combineOptions(WindowOption &cm, WindowOption &n) {
    if (!cm.icon && n.icon) cm.icon = n.icon;
    cm.functions |= n.functions & ~cm.function_mask;
    cm.function_mask |= n.function_mask;
    cm.decors |= n.decors & ~cm.decor_mask;
    cm.decor_mask |= n.decor_mask;
    cm.options |= n.options & ~cm.option_mask;
    cm.option_mask |= n.option_mask;
    if (n.workspace != WinWorkspaceInvalid)
        cm.workspace = n.workspace;
    if (n.layer != (long)WinLayerInvalid)
        cm.layer = n.layer;
#ifdef CONFIG_TRAY
    if (n.tray != (long)WinTrayInvalid)
        cm.tray = n.tray;
#endif
    if ((n.gflags & XValue) && !(cm.gflags & XValue)) {
        cm.gx = n.gx;
        cm.gflags |= XValue;
        if (n.gflags & XNegative)
            cm.gflags |= XNegative;
    }
    if ((n.gflags & YValue) && !(cm.gflags & YValue)) {
        cm.gy = n.gy;
        cm.gflags |= YValue;
        if (n.gflags & YNegative)
            cm.gflags |= YNegative;
    }
    if ((n.gflags & WidthValue) && !(cm.gflags & WidthValue)) {
        cm.gw = n.gw;
        cm.gflags |= WidthValue;
    }
    if ((n.gflags & HeightValue) && !(cm.gflags & HeightValue)) {
        cm.gh = n.gh;
        cm.gflags |= HeightValue;
    }
}

char *parseWinOptions(char *data) {
    char *p = data;
    char *w, *e, *c;
    char *class_instance;

    char *opt;

    while (*p) {
        while (*p == ' ' || *p == '\t' || *p == '\n')
            p++;
        if (*p == '#') {
            while (*p && *p != '\n') {
                if (*p == '\\' && p[1] != 0)
                    p++;
                p++;
            }
            continue;
        }
        w = p;
        c = 0;
        while (*p && *p != ':') {
            if (*p == '\\' && p[1] != 0)
                p++;
            else if (*p == '.')
                c = p;
            p++;
        }
        e = p;

        if (e == w || *p == 0)
            break;
        if (c == 0) {
            msg(_("Syntax error in window options"));
            break;
        }

        if (c - w + 1 == 0)
            class_instance = 0;
        else {
            char *d = w, *p = w;
            while (p < c) {
                if (*p == '\\' && p + 1 < c)
                    p++;
                *d++ = *p++;
            }

/// TODO #warning "separate handling of class and instance, the current way is a hack"
            class_instance = newstr(w, d - w);
            if (class_instance == 0)
                goto nomem;
            MSG(("class_instance: (%s)", class_instance));
        }

        *e = 0;
        c++;
        opt = c;
        e++;

        p = e;
        while (*p == ' ' || *p == '\t')
            p++;

        w = p;
        while (*p && (*p != '\n' && *p != ' ' && *p != '\t'))
            p++;

        if (*p != 0) {
            *p = 0;
            defOptions->setWinOption(class_instance, opt, w);
            delete[] class_instance;
        } else {
            defOptions->setWinOption(class_instance, opt, w);
            delete class_instance;
            break;
        }
        p++;
    }
    return p;
nomem:
    msg(_("Out of memory for window options"));
    return 0;
}

void loadWinOptions(upath optFile) {
    if (optFile == null)
        return ;

    int fd = open(cstring(optFile.path()).c_str(), O_RDONLY | O_TEXT);

    if (fd == -1)
        return ;

    struct stat sb;

    if (fstat(fd, &sb) == -1) {
        close(fd);
        return;
    }

    int len = sb.st_size;

    char *buf = new char[len + 1];
    if (buf == 0) {
        close(fd);
        return;
    }

    if ((len = read(fd, buf, len)) < 0) {
        delete[] buf;
        close(fd);
        return;
    }

    buf[len] = 0;
    close(fd);

    parseWinOptions(buf);

    delete[] buf;
}
#endif
<commit_msg>stricter parsing of whitespace in winoptions. Fix a delete[]. Fix a leak for icon. Simplify loadWinOptions.<commit_after>/*
 * IceWM
 *
 * Copyright (C) 1997-2002 Marko Macek
 */
#include "config.h"

#ifndef NO_WINDOW_OPTIONS
#include "yfull.h"
#include "wmoption.h"
#include "wmframe.h"

#include "WinMgr.h"
#include "base.h"
#include "sysdep.h"
#include <stdlib.h>

#include "ascii.h"
#include "intl.h"

#if 0
static int strnullcmp(const char *a, const char *b) {
    return a ? (b ? strcmp(a, b) : 1) : (b ? -1 : 0);
}
#endif

upath winOptFile;
WindowOptions *defOptions = 0;
WindowOptions *hintOptions = 0;

WindowOption::WindowOption(ustring n_class_instance):
    w_class_instance(n_class_instance),
    icon(0),
    functions(0), function_mask(0),
    decors(0), decor_mask(0),
    options(0), option_mask(0),
    workspace(WinWorkspaceInvalid),
    layer(WinLayerInvalid),
#ifdef CONFIG_TRAY
    tray(WinTrayInvalid),
#endif
    gflags(0), gx(0), gy(0), gw(0), gh(0)
{
}

WindowOption::~WindowOption() {
    ////delete[] name; name = 0;
    delete[] icon;
}

static int wo_cmp(ustring a_class_instance,
                  const WindowOption *pivot)
{
    int cmp = a_class_instance.compareTo(pivot->w_class_instance);
    return cmp;
}

WindowOption *WindowOptions::getWindowOption(ustring a_class_instance,
                                             bool create, bool remove)
{
    int lo = 0, hi = fWinOptions.getCount();

    while (lo < hi) {
        const int pv = (lo + hi) / 2;
	const WindowOption *pivot = fWinOptions[pv];

        int cmp = wo_cmp(a_class_instance,
                         pivot);
        if (cmp > 0) {
            lo = pv + 1;
            continue;
        } else if (cmp < 0) {
            hi = pv;
            continue;
        }

        if (remove) {
            static WindowOption result = *pivot;
            fWinOptions.remove(pv);
            return &result;
        }

        return fWinOptions.getItem(pv);
    }

    if (!create) return 0;

    WindowOption *newopt = new WindowOption(a_class_instance);

    MSG(("inserting window option %p at position %d", newopt, lo));
    fWinOptions.insert(lo, newopt);

#ifdef DEBUG
    for (int i = 0; i < fWinOptions.getCount(); ++i)
    	MSG(("> %d: %p", i, fWinOptions[i]));
#endif

    return newopt;
}

void WindowOptions::setWinOption(ustring n_class_instance,
                                 const char *opt, const char *arg)
{
    WindowOption *op = getWindowOption(n_class_instance, true);

    //msg("%s-%s-%s", class_instance, opt, arg);

    if (strcmp(opt, "icon") == 0) {
        delete [] op->icon;
        op->icon = newstr(arg);
    } else if (strcmp(opt, "workspace") == 0) {
        op->workspace = atoi(arg);
    } else if (strcmp(opt, "geometry") == 0) {
        int rx, ry;
        unsigned int rw, rh;

        op->gx = 0;
        op->gy = 0;
        op->gw = 0;
        op->gh = 0;

        //msg("parsing %s", arg);
        if ((op->gflags = XParseGeometry(arg, &rx, &ry, &rw, &rh)) != 0) {
            if (op->gflags & XNegative)
                rx = - rx;
            if (op->gflags & YNegative)
                ry = - ry;
            op->gx = rx;
            op->gy = ry;
            op->gw = rw;
            op->gh = rh;
            //msg("parsed %d %d %d %d %X", rx, ry, rw, rh, op->gflags);
        }
    } else if (strcmp(opt, "layer") == 0) {
        char *endptr;
        long l = strtol(arg, &endptr, 10);

        op->layer = WinLayerInvalid;

        if (arg[0] && !endptr[0])
            op->layer = l;
        else {
            static const struct {
                const char name[12];
                int layer;
            } layers[] = {
                { "Desktop", WinLayerDesktop }, //
                { "Below", WinLayerBelow }, //
                { "Normal", WinLayerNormal }, //
                { "OnTop", WinLayerOnTop }, //
                { "Dock", WinLayerDock }, //
                { "AboveDock", WinLayerAboveDock }, //
                { "Menu", WinLayerMenu }
            };
            for (unsigned int i = 0; i < ACOUNT(layers); i++)
                if (strcmp(layers[i].name, arg) == 0)
                    op->layer = layers[i].layer;
        }
#ifdef CONFIG_TRAY
    } else if (strcmp(opt, "tray") == 0) {
        char *endptr;
        long const t(strtol(arg, &endptr, 10));

        op->tray = WinTrayInvalid;

        if (arg[0] && !endptr[0])
            op->tray = t;
        else {
            static const struct {
                const char name[12];
                int tray;
            } tray_ops[] = {
                { "Ignore", WinTrayIgnore },
                { "Minimized", WinTrayMinimized },
                { "Exclusive", WinTrayExclusive },
                { "1", WinTrayExclusive }
            };
            for (unsigned int i = 0; i < ACOUNT(tray_ops); i++)
                if (strcmp(tray_ops[i].name, arg) == 0)
                    op->tray = tray_ops[i].tray;
        }
#endif
    } else {
        static const struct {
            int what;
            const char *name;
            unsigned long flag;
        } options[] = {
            { 0, "fMove", YFrameWindow::ffMove }, //
            { 0, "fResize", YFrameWindow::ffResize }, //
            { 0, "fClose", YFrameWindow::ffClose }, //
            { 0, "fMinimize", YFrameWindow::ffMinimize }, //
            { 0, "fMaximize", YFrameWindow::ffMaximize }, //
            { 0, "fHide", YFrameWindow::ffHide }, //
            { 0, "fRollup", YFrameWindow::ffRollup }, //
            { 1, "dTitleBar", YFrameWindow::fdTitleBar }, //
            { 1, "dSysMenu", YFrameWindow::fdSysMenu }, //
            { 1, "dBorder", YFrameWindow::fdBorder }, //
            { 1, "dResize", YFrameWindow::fdResize }, //
            { 1, "dClose", YFrameWindow::fdClose }, //
            { 1, "dMinimize", YFrameWindow::fdMinimize }, //
            { 1, "dMaximize", YFrameWindow::fdMaximize }, //
            { 1, "dHide", YFrameWindow::fdHide },
            { 1, "dRollup", YFrameWindow::fdRollup },
            { 1, "dDepth", YFrameWindow::fdDepth },
            { 2, "allWorkspaces", YFrameWindow::foAllWorkspaces }, //
            { 2, "ignoreTaskBar", YFrameWindow::foIgnoreTaskBar }, //
            { 2, "noIgnoreTaskBar", YFrameWindow::foNoIgnoreTaskBar }, //
            { 2, "ignoreWinList", YFrameWindow::foIgnoreWinList }, //
            { 2, "ignoreQuickSwitch", YFrameWindow::foIgnoreQSwitch }, //
            { 2, "fullKeys", YFrameWindow::foFullKeys }, //
            { 2, "noFocusOnAppRaise", YFrameWindow::foNoFocusOnAppRaise }, //
            { 2, "ignoreNoFocusHint", YFrameWindow::foIgnoreNoFocusHint }, //
            { 2, "ignorePositionHint", YFrameWindow::foIgnorePosition }, //
            { 2, "doNotCover", YFrameWindow::foDoNotCover }, //
            { 2, "doNotFocus", YFrameWindow::foDoNotFocus }, //
            { 2, "startFullscreen", YFrameWindow::foFullscreen },
            { 2, "startMinimized", YFrameWindow::foMinimized }, //
            { 2, "startMaximized", YFrameWindow::foMaximizedVert | YFrameWindow::foMaximizedHorz }, //
            { 2, "startMaximizedVert", YFrameWindow::foMaximizedVert }, //
            { 2, "startMaximizedHorz", YFrameWindow::foMaximizedHorz }, //
            { 2, "nonICCCMconfigureRequest", YFrameWindow::foNonICCCMConfigureRequest },
            { 2, "forcedClose", YFrameWindow::foForcedClose },
            { 2, "noFocusOnMap", YFrameWindow::foNoFocusOnMap },
            { 2, "ignoreUrgentHint", YFrameWindow::foIgnoreUrgent },
            { 2, "appTakesFocus", YFrameWindow::foAppTakesFocus }
        };

        for (unsigned int a = 0; a < ACOUNT(options); a++) {
            unsigned long *what, *what_mask;

            if (options[a].what == 0) {
                what = &op->functions;
                what_mask  = &op->function_mask;
            } else if (options[a].what == 1) {
                what = &op->decors;
                what_mask = &op->decor_mask;
            } else if (options[a].what == 2) {
                what = &op->options;
                what_mask = &op->option_mask;
            } else {
                msg(_("Error in window option: %s"), opt);
                break;
            }

            if (strcmp(opt, options[a].name) == 0) {
                if (*what == 2 && options[a].flag == YFrameWindow::foIgnoreWinList)
                    DEPRECATE("ignoreWinlist windowoption");
                if (*what == 2 && options[a].flag == YFrameWindow::foIgnoreQSwitch)
                    DEPRECATE("ignoreQuickSwitch windowoption");
                if (atoi(arg) != 0)
                    *what = (*what) | options[a].flag;
                else
                    *what = (*what) & ~options[a].flag;
                *what_mask =  (*what_mask) | options[a].flag;
                return ;
            }
        }
        msg(_("Unknown window option: %s"), opt);
    }
}

void WindowOptions::mergeWindowOption(WindowOption &cm,
                                      ustring a_class_instance,
                                      bool remove)
{
    WindowOption *wo = getWindowOption(a_class_instance, false, remove);
    if (wo)
        combineOptions(cm, *wo);
}

void WindowOptions::combineOptions(WindowOption &cm, WindowOption &n) {
    if (!cm.icon && n.icon) cm.icon = newstr(n.icon);
    cm.functions |= n.functions & ~cm.function_mask;
    cm.function_mask |= n.function_mask;
    cm.decors |= n.decors & ~cm.decor_mask;
    cm.decor_mask |= n.decor_mask;
    cm.options |= n.options & ~cm.option_mask;
    cm.option_mask |= n.option_mask;
    if (n.workspace != WinWorkspaceInvalid)
        cm.workspace = n.workspace;
    if (n.layer != (long)WinLayerInvalid)
        cm.layer = n.layer;
#ifdef CONFIG_TRAY
    if (n.tray != (long)WinTrayInvalid)
        cm.tray = n.tray;
#endif
    if ((n.gflags & XValue) && !(cm.gflags & XValue)) {
        cm.gx = n.gx;
        cm.gflags |= XValue;
        if (n.gflags & XNegative)
            cm.gflags |= XNegative;
    }
    if ((n.gflags & YValue) && !(cm.gflags & YValue)) {
        cm.gy = n.gy;
        cm.gflags |= YValue;
        if (n.gflags & YNegative)
            cm.gflags |= YNegative;
    }
    if ((n.gflags & WidthValue) && !(cm.gflags & WidthValue)) {
        cm.gw = n.gw;
        cm.gflags |= WidthValue;
    }
    if ((n.gflags & HeightValue) && !(cm.gflags & HeightValue)) {
        cm.gh = n.gh;
        cm.gflags |= HeightValue;
    }
}

char *parseWinOptions(char *data) {
    char *p, *w, *e, *c;
    char *class_instance;
    char *opt;

    for (p = data; *p; ++p) {
        if (ASCII::isWhiteSpace(*p))
            continue;

        if (*p == '#') {
            while (*++p && *p != '\n')
                if (*p == '\\' && p[1] != 0)
                    p++;
            continue;
        }

        w = p;
        c = 0;
        while (*p && *p != ':') {
            if (*p == '\\' && p[1] != 0)
                p++;
            else if (*p == '.')
                c = p;
            p++;
        }
        e = p;

        if (e == w || *p == 0)
            break;
        if (c == 0) {
            msg(_("Syntax error in window options"));
            break;
        }

        if (c - w + 1 == 0)
            class_instance = 0;
        else {
            char *d = w, *p = w;
            while (p < c) {
                if (*p == '\\' && p + 1 < c)
                    p++;
                *d++ = *p++;
            }

/// TODO #warning "separate handling of class and instance, the current way is a hack"
            class_instance = newstr(w, d - w);
            if (class_instance == 0)
                goto nomem;
            MSG(("class_instance: (%s)", class_instance));
        }

        *e = 0;
        c++;
        opt = c;
        e++;

        p = e;
        while (*p == ' ' || *p == '\t')
            p++;

        w = p;
        while (*p && false == ASCII::isWhiteSpace(*p))
            p++;

        if (*p != 0) {
            *p = 0;
            defOptions->setWinOption(class_instance, opt, w);
            delete[] class_instance;
        } else {
            defOptions->setWinOption(class_instance, opt, w);
            delete[] class_instance;
            break;
        }
    }
    return p;
nomem:
    msg(_("Out of memory for window options"));
    return 0;
}

void loadWinOptions(upath optFile) {
    if (optFile.nonempty()) {
        char *buf = load_text_file(cstring(optFile));
        if (buf) {
            parseWinOptions(buf);
            delete[] buf;
        }
    }
}
#endif
<|endoftext|>


<commit_before>
#include "wrapper.h"
#include "reporthandler.h"
#include "fileout.h"
#include "typesystem/typedatabase.h"
#include "main.h"
#include "asttoxml.h"
#include "parser/binder.h"

QString Wrapper::include_directory = QString();

void ReportHandler_message_handler(const std::string &str) {
    ReportHandler::warning(QString::fromStdString(str));
}

Wrapper::Wrapper(int argc, char *argv[]) :
        default_file("targets/qtjambi_masterinclude.h"),
        default_system("targets/build_all.xml"),
        pp_file("preprocessed.tmp") {

    gs = GeneratorSet::getInstance();
    args = parseArguments(argc, argv);
    handleArguments();
    assignVariables();
}

void Wrapper::handleArguments() {
    if (args.contains("no-suppress-warnings")) {
        TypeDatabase *db = TypeDatabase::instance();
        db->setSuppressWarnings(false);
    }

    if (args.contains("include-eclipse-warnings")) {
        TypeDatabase *db = TypeDatabase::instance();
        db->setIncludeEclipseWarnings(true);
    }

    if (args.contains("debug-level")) {
        QString level = args.value("debug-level");
        if (level == "sparse") {
            ReportHandler::setDebugLevel(ReportHandler::SparseDebug);
        } else if (level == "medium") {
            ReportHandler::setDebugLevel(ReportHandler::MediumDebug);
        } else if (level == "full") {
            ReportHandler::setDebugLevel(ReportHandler::FullDebug);
        } else if (level == "types") {
            ReportHandler::setDebugLevel(ReportHandler::TypeDebug);
        }
    }

    if (args.contains("dummy")) {
        FileOut::dummy = true;
    }

    if (args.contains("diff")) {
        FileOut::diff = true;
    }

    if (args.contains("rebuild-only")) {
        QStringList classes = args.value("rebuild-only").split(",", QString::SkipEmptyParts);
        TypeDatabase::instance()->setRebuildClasses(classes);
    }

    if (args.contains("qt-include-directory"))
        include_directory = args.value("qt-include-directory");

    if (args.contains("include-paths")) {        // split on path
        QString arg = args.value("include-paths");
#if defined(Q_OS_WIN32)
        QChar pathSeparator(';');
#else
        QChar pathSeparator(':');
#endif
        if(arg.length() > 0) {
            const QChar firstChar = arg.at(0);
            if(firstChar == QChar(':') || firstChar == QChar(';'))
                pathSeparator = firstChar;	// this allows override default trick
        }
        includePathsList = arg.split(pathSeparator, QString::SkipEmptyParts);
    }

    if (args.contains("input-directory")) {
        default_file = QDir(args.value("input-directory")).absoluteFilePath(default_file);
        default_system = QDir(args.value("input-directory")).absoluteFilePath(default_system);
    }

    if (args.contains("output-directory"))
        pp_file = QDir(args.value("output-directory")).absoluteFilePath(pp_file);

    if (args.contains("cpp-output-directory"))
        gs->cppOutDir = args.value("cpp-output-directory");

    if (args.contains("java-output-directory"))
        gs->javaOutDir = args.value("java-output-directory");
}

void Wrapper::assignVariables() {
    //set file name
    fileName = args.value("arg-1");

    //set typesystem filename
    typesystemFileName = args.value("arg-2");
    if (args.contains("arg-3"))
        displayHelp(gs);

    //set filename to default masterinclude if is empty
    if (fileName.isEmpty())
        fileName = default_file;

    //if type system filename is empty, set it to default system file...
    if (typesystemFileName.isEmpty())
        typesystemFileName = default_system;

    //if filename or typesystem filename is still empty, show help
    if (fileName.isEmpty() || typesystemFileName.isEmpty())
        displayHelp(gs);

    //if generatorset can't read arguments, show help
    if (!gs->readParameters(args))
        displayHelp(gs);
}

int Wrapper::runJambiGenerator() {
    printf("Running the Qt Jambi Generator. Please wait while source files are being generated...\n");

    //parse the type system file
    if (!TypeDatabase::instance()->parseFile(typesystemFileName, args.value("input-directory")))
        qFatal("Cannot parse file: '%s'", qPrintable(typesystemFileName));

    //removing file here for theoretical case of wanting to parse two master include files here
    QFile::remove(pp_file);
    //preprocess using master include, preprocessed file and command line given include paths, if any
    if (!Preprocess::preprocess(fileName, pp_file, args.value("phonon-include"), includePathsList)) {
        fprintf(stderr, "Preprocessor failed on file: '%s'\n", qPrintable(fileName));
        return 1;
    }

    //convert temp preprocessed file to xml
    if (args.contains("ast-to-xml")) {
        astToXML(pp_file);
        return 0;
    }

    Binder::installMessageHandler(ReportHandler_message_handler);

    gs->buildModel(pp_file);

    if (args.contains("dump-object-tree")) {
        gs->dumpObjectTree();
        return 0;
    }

    printf("%s\n", qPrintable(gs->generate()));

    printf("Done, %d warnings (%d known issues)\n", ReportHandler::warningCount(),
           ReportHandler::suppressedCount());

    return 0;
}

void Wrapper::displayHelp(GeneratorSet* generatorSet) {
#if defined(Q_OS_WIN32)
    char path_splitter = ';';
#else
    char path_splitter = ':';
#endif
    printf("Usage:\n  generator [options] header-file typesystem-file\n\n");
    printf("Available options:\n\n");
    printf("General:\n");
    printf("  --debug-level=[types|sparse|medium|full]  \n"
           "  --dump-object-tree                        \n"
           "  --help, -h or -?                          \n"
           "  --no-suppress-warnings                    \n"
           "  --include-eclipse-warnings                \n"
           "  --input-directory=[dir]                   \n"
           "  --output-directory=[dir]                  \n"
           "  --cpp-output-directory=[dir]              \n"
           "  --java-output-directory=[dir]             \n"
           "  --include-paths=<path>[%c<path>%c...]     \n"
           "  --print-stdout                            \n"
           "  --qt-include-directory=[dir]              \n"
           "  --qtjambi-debug-tools                     \n",
           path_splitter, path_splitter);

    printf("%s", qPrintable(generatorSet->usage()));
    exit(0);
}

QMap<QString, QString> Wrapper::parseArguments(int argc, char *argv[]) {
    QMap<QString, QString> args;

    int argNum = 0;
    for (int i = 1; i < argc; ++i) {
        QString arg(argv[i]);
        arg = arg.trimmed();

        if (arg.startsWith("--")) {
            int split = arg.indexOf("=");

            if (split > 0)
                args[arg.mid(2).left(split-2)] = arg.mid(split + 1).trimmed();
            else
                args[arg.mid(2)] = QString();

        } else if (arg.startsWith("-")) {
            args[arg.mid(1)] = QString();
        } else {
            argNum++;
            args[QString("arg-%1").arg(argNum)] = arg;
        }
    }

    return args;
}
<commit_msg>(split) New option to override the name of the preprocess.tmp file via new generator --output-preprocess-file option.<commit_after>
#include "wrapper.h"
#include "reporthandler.h"
#include "fileout.h"
#include "typesystem/typedatabase.h"
#include "main.h"
#include "asttoxml.h"
#include "parser/binder.h"

QString Wrapper::include_directory = QString();

void ReportHandler_message_handler(const std::string &str) {
    ReportHandler::warning(QString::fromStdString(str));
}

Wrapper::Wrapper(int argc, char *argv[]) :
        default_file("targets/qtjambi_masterinclude.h"),
        default_system("targets/build_all.xml"),
        pp_file("preprocessed.tmp") {

    gs = GeneratorSet::getInstance();
    args = parseArguments(argc, argv);
    handleArguments();
    assignVariables();
}

void Wrapper::handleArguments() {
    if (args.contains("no-suppress-warnings")) {
        TypeDatabase *db = TypeDatabase::instance();
        db->setSuppressWarnings(false);
    }

    if (args.contains("include-eclipse-warnings")) {
        TypeDatabase *db = TypeDatabase::instance();
        db->setIncludeEclipseWarnings(true);
    }

    if (args.contains("debug-level")) {
        QString level = args.value("debug-level");
        if (level == "sparse") {
            ReportHandler::setDebugLevel(ReportHandler::SparseDebug);
        } else if (level == "medium") {
            ReportHandler::setDebugLevel(ReportHandler::MediumDebug);
        } else if (level == "full") {
            ReportHandler::setDebugLevel(ReportHandler::FullDebug);
        } else if (level == "types") {
            ReportHandler::setDebugLevel(ReportHandler::TypeDebug);
        }
    }

    if (args.contains("dummy")) {
        FileOut::dummy = true;
    }

    if (args.contains("diff")) {
        FileOut::diff = true;
    }

    if (args.contains("rebuild-only")) {
        QStringList classes = args.value("rebuild-only").split(",", QString::SkipEmptyParts);
        TypeDatabase::instance()->setRebuildClasses(classes);
    }

    if (args.contains("qt-include-directory"))
        include_directory = args.value("qt-include-directory");

    if (args.contains("include-paths")) {        // split on path
        QString arg = args.value("include-paths");
#if defined(Q_OS_WIN32)
        QChar pathSeparator(';');
#else
        QChar pathSeparator(':');
#endif
        if(arg.length() > 0) {
            const QChar firstChar = arg.at(0);
            if(firstChar == QChar(':') || firstChar == QChar(';'))
                pathSeparator = firstChar;	// this allows override default trick
        }
        includePathsList = arg.split(pathSeparator, QString::SkipEmptyParts);
    }

    if (args.contains("input-directory")) {
        default_file = QDir(args.value("input-directory")).absoluteFilePath(default_file);
        default_system = QDir(args.value("input-directory")).absoluteFilePath(default_system);
    }

    if (args.contains("output-preprocess-file"))
        pp_file = args.value("output-preprocess-file");

    if (args.contains("output-directory"))
        pp_file = QDir(args.value("output-directory")).absoluteFilePath(pp_file);

    if (args.contains("cpp-output-directory"))
        gs->cppOutDir = args.value("cpp-output-directory");

    if (args.contains("java-output-directory"))
        gs->javaOutDir = args.value("java-output-directory");
}

void Wrapper::assignVariables() {
    //set file name
    fileName = args.value("arg-1");

    //set typesystem filename
    typesystemFileName = args.value("arg-2");
    if (args.contains("arg-3"))
        displayHelp(gs);

    //set filename to default masterinclude if is empty
    if (fileName.isEmpty())
        fileName = default_file;

    //if type system filename is empty, set it to default system file...
    if (typesystemFileName.isEmpty())
        typesystemFileName = default_system;

    //if filename or typesystem filename is still empty, show help
    if (fileName.isEmpty() || typesystemFileName.isEmpty())
        displayHelp(gs);

    //if generatorset can't read arguments, show help
    if (!gs->readParameters(args))
        displayHelp(gs);
}

int Wrapper::runJambiGenerator() {
    printf("Running the Qt Jambi Generator. Please wait while source files are being generated...\n");

    //parse the type system file
    if (!TypeDatabase::instance()->parseFile(typesystemFileName, args.value("input-directory")))
        qFatal("Cannot parse file: '%s'", qPrintable(typesystemFileName));

    //removing file here for theoretical case of wanting to parse two master include files here
    QFile::remove(pp_file);
    //preprocess using master include, preprocessed file and command line given include paths, if any
    if (!Preprocess::preprocess(fileName, pp_file, args.value("phonon-include"), includePathsList)) {
        fprintf(stderr, "Preprocessor failed on file: '%s'\n", qPrintable(fileName));
        return 1;
    }

    //convert temp preprocessed file to xml
    if (args.contains("ast-to-xml")) {
        astToXML(pp_file);
        return 0;
    }

    Binder::installMessageHandler(ReportHandler_message_handler);

    gs->buildModel(pp_file);

    if (args.contains("dump-object-tree")) {
        gs->dumpObjectTree();
        return 0;
    }

    printf("%s\n", qPrintable(gs->generate()));

    printf("Done, %d warnings (%d known issues)\n", ReportHandler::warningCount(),
           ReportHandler::suppressedCount());

    return 0;
}

void Wrapper::displayHelp(GeneratorSet* generatorSet) {
#if defined(Q_OS_WIN32)
    char path_splitter = ';';
#else
    char path_splitter = ':';
#endif
    printf("Usage:\n  generator [options] header-file typesystem-file\n\n");
    printf("Available options:\n\n");
    printf("General:\n");
    printf("  --debug-level=[types|sparse|medium|full]  \n"
           "  --dump-object-tree                        \n"
           "  --help, -h or -?                          \n"
           "  --no-suppress-warnings                    \n"
           "  --include-eclipse-warnings                \n"
           "  --input-directory=[dir]                   \n"
           "  --output-directory=[dir]                  \n"
           "  --cpp-output-directory=[dir]              \n"
           "  --java-output-directory=[dir]             \n"
           "  --output-preprocess-file=[file|path]      \n"
           "  --include-paths=<path>[%c<path>%c...]     \n"
           "  --print-stdout                            \n"
           "  --qt-include-directory=[dir]              \n"
           "  --qtjambi-debug-tools                     \n",
           path_splitter, path_splitter);

    printf("%s", qPrintable(generatorSet->usage()));
    exit(0);
}

QMap<QString, QString> Wrapper::parseArguments(int argc, char *argv[]) {
    QMap<QString, QString> args;

    int argNum = 0;
    for (int i = 1; i < argc; ++i) {
        QString arg(argv[i]);
        arg = arg.trimmed();

        if (arg.startsWith("--")) {
            int split = arg.indexOf("=");

            if (split > 0)
                args[arg.mid(2).left(split-2)] = arg.mid(split + 1).trimmed();
            else
                args[arg.mid(2)] = QString();

        } else if (arg.startsWith("-")) {
            args[arg.mid(1)] = QString();
        } else {
            argNum++;
            args[QString("arg-%1").arg(argNum)] = arg;
        }
    }

    return args;
}
<|endoftext|>


<commit_before>/*
Copyright 2016 Fixstars Corporation

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 <libsgm_wrapper.h>

namespace sgm {
	LibSGMWrapper::LibSGMWrapper(const sgm::StereoSGM::Parameters& param) : sgm_(nullptr), param_(param), prev_(nullptr) {}
	LibSGMWrapper::~LibSGMWrapper() = default;

	struct LibSGMWrapper::Info {
		int width;
		int height;
		int src_pitch;
		int dst_pitch;
		int input_depth_bits;
	};

#ifdef WITH_OPENCV
	void LibSGMWrapper::execute(const cv::cuda::GpuMat& I1, const cv::cuda::GpuMat& I2, cv::cuda::GpuMat& disparity) {
		// TODO: implement
	}

#endif // WITH_OPENCV
}
<commit_msg>Implement GpuMat wrapper<commit_after>/*
Copyright 2016 Fixstars Corporation

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 <libsgm_wrapper.h>

namespace sgm {
	LibSGMWrapper::LibSGMWrapper(const sgm::StereoSGM::Parameters& param) : sgm_(nullptr), param_(param), prev_(nullptr) {}
	LibSGMWrapper::~LibSGMWrapper() = default;

	struct LibSGMWrapper::Info {
		int width;
		int height;
		int src_pitch;
		int dst_pitch;
		int input_depth_bits;

		bool operator==(const sgm::LibSGMWrapper::Info& rhs) {
			return
				width == rhs.width
				&& height == rhs.height
				&& src_pitch == rhs.src_pitch
				&& dst_pitch == rhs.dst_pitch
				&& input_depth_bits == rhs.input_depth_bits;
		}
		bool operator!=(const sgm::LibSGMWrapper::Info& rhs) {
			return !(*this == rhs);
		}
	};

#ifdef WITH_OPENCV
	void LibSGMWrapper::execute(const cv::cuda::GpuMat& I1, const cv::cuda::GpuMat& I2, cv::cuda::GpuMat& disparity) {
		const cv::Size size = I1.size();
		CV_Assert(size == I2.size());
		CV_Assert(I1.type() == I2.type());
		const int depth = I1.depth();
		CV_Assert(depth == CV_8U || depth == CV_16U);
		if (disparity.size() != size
				|| disparity.depth() != CV_16U) {
			disparity.create(size, CV_16U);
		}
		std::unique_ptr<Info> info(new Info());
		info->width = size.width;
		info->height = size.height;
		info->src_pitch = static_cast<int>(I1.step1());
		info->dst_pitch = static_cast<int>(disparity.step1());
		info->input_depth_bits = static_cast<int>(I1.elemSize1()) * 8;
		if (sgm_.get() == nullptr
				|| info != prev_) {
			sgm_.reset(new StereoSGM(info->width, info->height, DISPARITY_SIZE, info->input_depth_bits, OUTPUT_DEPTH_BITS, info->src_pitch, info->dst_pitch, sgm::EXECUTE_INOUT_CUDA2CUDA, param_));
		}
		prev_ = std::move(info);

		sgm_->execute(I1.data, I2.data, disparity.data);
	}
#endif // WITH_OPENCV
}
<|endoftext|>


<commit_before>// This file is part of the "x0" project
//   (c) 2009-2015 Christian Parpart <https://github.com/christianparpart>
//
// x0 is free software: you can redistribute it and/or modify it under
// the terms of the GNU Affero General Public License v3.0.
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

#include <x0d/XzeroModule.h>
#include <x0d/XzeroDaemon.h>
#include <x0d/sysconfig.h>

#include <xzero-flow/ASTPrinter.h>
#include <xzero/logging/ConsoleLogTarget.h>
#include <xzero/logging.h>
#include <xzero/io/FileUtil.h>
#include <xzero/cli/CLI.h>
#include <xzero/cli/Flags.h>
#include <xzero/Application.h>
#include <iostream>
#include <unistd.h>

#define PACKAGE_VERSION X0_VERSION
#define PACKAGE_HOMEPAGE_URL "https://xzero.io"

using namespace xzero;
using namespace xzero::http;

void printHelp(const CLI& cli) {
  std::cout
    << "x0d: Xzero HTTP Web Server " PACKAGE_VERSION
        << " [" PACKAGE_HOMEPAGE_URL "]" << std::endl
    << "Copyright (c) 2009-2015 by Christian Parpart <trapni@gmail.com>" << std::endl
    << std::endl
    << "Usage: x0d [options ...]" << std::endl
    << std::endl
    << "Options:" << std::endl
    << cli.helpText() << std::endl;
}

class PidFile { // {{{
 public:
  PidFile(const std::string& path);
  ~PidFile();

 private:
  std::string path_;
};

PidFile::PidFile(const std::string& path)
    : path_(path) {
  // TODO: sanity-check (flock?) to ensure that we're the one.
  logInfo("x0d", "Writing main process ID $0 into file $1",
          getpid(), path_);
  FileUtil::write(path_, StringUtil::toString(getpid()));
}

PidFile::~PidFile() {
  FileUtil::rm(path_);
}
// }}}

int main(int argc, const char* argv[]) {
  try {
    Application::init();

    CLI cli;
    cli.defineBool("help", 'h', "Prints this help and terminates.")
       .defineString("config", 'c', "PATH", "Specify a custom configuration file.", X0D_CONFIGFILE, nullptr)
       .defineString("user", 'u', "NAME", "User privileges to drop down to.", Application::userName())
       .defineString("group", 'g', "NAME", "Group privileges to drop down to.", Application::groupName())
       .defineString("log-level", 'L', "ENUM", "Defines the minimum log level.", "info", nullptr)
       .defineString("log-target", 0, "ENUM", "Specifies logging target. One of syslog, file, systemd, console.", "console", nullptr)
       .defineString("log-file", 'l', "PATH", "Path to application log file.", "", nullptr)
       .defineString("instant", 'i', "PATH[:PORT]", "Enable instant-mode (does not need config file).", "", nullptr)
       .defineNumber("optimization-level", 'O', "LEVEL", "Sets the configuration optimization level.", 1)
       .defineBool("daemonize", 'd', "Forks the process into background.")
       .defineString("pid-file", 0, "PATH",
                     "Path to PID-file this process will store its main PID.",
                     FileUtil::joinPaths(X0D_STATEDIR, "x0d.pid"),
                     nullptr)
       .defineBool("dump-ast", 0, "Dumps configuration AST and exits.")
       .defineBool("dump-ir", 0, "Dumps configuration IR and exits.")
       .defineBool("dump-tc", 0, "Dumps configuration opcode stream and exits.")
       ;

    Flags flags = cli.evaluate(argc, argv);

    if (flags.getBool("help")) {
      printHelp(cli);
      return 0;
    }

    // {{{ setup logging
    Logger::get()->setMinimumLogLevel(make_loglevel(flags.getString("log-level")));

    std::string logTarget = flags.getString("log-target");
    if (logTarget == "null") {
      ; // ignore
    } else if (logTarget == "console") {
      Logger::get()->addTarget(ConsoleLogTarget::get());
    } else if (logTarget == "file") {
      ; // TODO
    } else if (logTarget == "syslog") {
      ; // TODO Logger::get()->addTarget(SyslogTarget::get());
    } else if (logTarget == "systemd") {
      ; // TODO Logger::get()->addTarget(SystemdLogTarget::get());
    } else {
      fprintf(stderr, "Invalid log target \"%s\".\n", logTarget.c_str());
      return 1;
    }
    // }}}

    x0d::XzeroDaemon x0d;

    x0d.setOptimizationLevel(flags.getNumber("optimization-level"));

    x0d.loadConfigFile(flags.getString("config"));

    bool exitBeforeRun = false;

    if (flags.getBool("dump-ast")) {
      xzero::flow::ASTPrinter::print(x0d.programAST());
      exitBeforeRun = true;
    }

    if (flags.getBool("dump-ir")) {
      x0d.programIR()->dump();
      exitBeforeRun = true;
    }

    if (flags.getBool("dump-tc")) {
      x0d.program()->dump();
      exitBeforeRun = true;
    }

    if (exitBeforeRun)
      return 0;

    if (!x0d.configure())
      return 1;

    std::string pidfilepath = FileUtil::realpath(flags.getString("pid-file"));
    std::string pidfiledir = FileUtil::dirname(pidfilepath);
    if (!FileUtil::exists(pidfiledir)) {
      FileUtil::mkdir_p(pidfiledir);
      FileUtil::chown(pidfiledir, flags.getString("user"),
                                  flags.getString("group"));
    }

    Application::dropPrivileges(flags.getString("user"), flags.getString("group"));

    if (flags.getBool("daemonize")) {
      Application::daemonize();
    }

    PidFile pidFile = pidfilepath;

    x0d.run();
  } catch (const std::exception& e) {
    fprintf(stderr, "Unhandled exception caught. %s\n", e.what());
    return 1;
  }

  return 0;
}
<commit_msg>x0d: minor bugfix in pid-file handling<commit_after>// This file is part of the "x0" project
//   (c) 2009-2015 Christian Parpart <https://github.com/christianparpart>
//
// x0 is free software: you can redistribute it and/or modify it under
// the terms of the GNU Affero General Public License v3.0.
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

#include <x0d/XzeroModule.h>
#include <x0d/XzeroDaemon.h>
#include <x0d/sysconfig.h>

#include <xzero-flow/ASTPrinter.h>
#include <xzero/logging/ConsoleLogTarget.h>
#include <xzero/logging.h>
#include <xzero/io/FileUtil.h>
#include <xzero/cli/CLI.h>
#include <xzero/cli/Flags.h>
#include <xzero/Application.h>
#include <iostream>
#include <unistd.h>

#define PACKAGE_VERSION X0_VERSION
#define PACKAGE_HOMEPAGE_URL "https://xzero.io"

using namespace xzero;
using namespace xzero::http;

void printHelp(const CLI& cli) {
  std::cout
    << "x0d: Xzero HTTP Web Server " PACKAGE_VERSION
        << " [" PACKAGE_HOMEPAGE_URL "]" << std::endl
    << "Copyright (c) 2009-2015 by Christian Parpart <trapni@gmail.com>" << std::endl
    << std::endl
    << "Usage: x0d [options ...]" << std::endl
    << std::endl
    << "Options:" << std::endl
    << cli.helpText() << std::endl;
}

class PidFile { // {{{
 public:
  PidFile(const std::string& path);
  ~PidFile();

 private:
  std::string path_;
};

PidFile::PidFile(const std::string& path)
    : path_(path) {
  // TODO: sanity-check (flock?) to ensure that we're the one.
  logInfo("x0d", "Writing main process ID $0 into file $1",
          getpid(), path_);
  FileUtil::write(path_, StringUtil::toString(getpid()));
}

PidFile::~PidFile() {
  FileUtil::rm(path_);
}
// }}}

int main(int argc, const char* argv[]) {
  try {
    Application::init();

    CLI cli;
    cli.defineBool("help", 'h', "Prints this help and terminates.")
       .defineString("config", 'c', "PATH", "Specify a custom configuration file.", X0D_CONFIGFILE, nullptr)
       .defineString("user", 'u', "NAME", "User privileges to drop down to.", Application::userName())
       .defineString("group", 'g', "NAME", "Group privileges to drop down to.", Application::groupName())
       .defineString("log-level", 'L', "ENUM", "Defines the minimum log level.", "info", nullptr)
       .defineString("log-target", 0, "ENUM", "Specifies logging target. One of syslog, file, systemd, console.", "console", nullptr)
       .defineString("log-file", 'l', "PATH", "Path to application log file.", "", nullptr)
       .defineString("instant", 'i', "PATH[:PORT]", "Enable instant-mode (does not need config file).", "", nullptr)
       .defineNumber("optimization-level", 'O', "LEVEL", "Sets the configuration optimization level.", 1)
       .defineBool("daemonize", 'd', "Forks the process into background.")
       .defineString("pid-file", 0, "PATH",
                     "Path to PID-file this process will store its main PID.",
                     FileUtil::joinPaths(X0D_STATEDIR, "x0d.pid"),
                     nullptr)
       .defineBool("dump-ast", 0, "Dumps configuration AST and exits.")
       .defineBool("dump-ir", 0, "Dumps configuration IR and exits.")
       .defineBool("dump-tc", 0, "Dumps configuration opcode stream and exits.")
       ;

    Flags flags = cli.evaluate(argc, argv);

    if (flags.getBool("help")) {
      printHelp(cli);
      return 0;
    }

    // {{{ setup logging
    Logger::get()->setMinimumLogLevel(make_loglevel(flags.getString("log-level")));

    std::string logTarget = flags.getString("log-target");
    if (logTarget == "null") {
      ; // ignore
    } else if (logTarget == "console") {
      Logger::get()->addTarget(ConsoleLogTarget::get());
    } else if (logTarget == "file") {
      ; // TODO
    } else if (logTarget == "syslog") {
      ; // TODO Logger::get()->addTarget(SyslogTarget::get());
    } else if (logTarget == "systemd") {
      ; // TODO Logger::get()->addTarget(SystemdLogTarget::get());
    } else {
      fprintf(stderr, "Invalid log target \"%s\".\n", logTarget.c_str());
      return 1;
    }
    // }}}

    x0d::XzeroDaemon x0d;

    x0d.setOptimizationLevel(flags.getNumber("optimization-level"));

    x0d.loadConfigFile(flags.getString("config"));

    bool exitBeforeRun = false;

    if (flags.getBool("dump-ast")) {
      xzero::flow::ASTPrinter::print(x0d.programAST());
      exitBeforeRun = true;
    }

    if (flags.getBool("dump-ir")) {
      x0d.programIR()->dump();
      exitBeforeRun = true;
    }

    if (flags.getBool("dump-tc")) {
      x0d.program()->dump();
      exitBeforeRun = true;
    }

    if (exitBeforeRun)
      return 0;

    if (!x0d.configure())
      return 1;

    std::string pidfilepath = FileUtil::absolutePath(flags.getString("pid-file"));
    std::string pidfiledir = FileUtil::dirname(pidfilepath);
    if (!FileUtil::exists(pidfiledir)) {
      FileUtil::mkdir_p(pidfiledir);
      FileUtil::chown(pidfiledir, flags.getString("user"),
                                  flags.getString("group"));
    }

    Application::dropPrivileges(flags.getString("user"), flags.getString("group"));

    if (flags.getBool("daemonize")) {
      Application::daemonize();
    }

    PidFile pidFile = pidfilepath;

    x0d.run();
  } catch (const std::exception& e) {
    fprintf(stderr, "Unhandled exception caught. %s\n", e.what());
    return 1;
  }

  return 0;
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkPlaneSource.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkPlaneSource.h"
#include "vtkFloatPoints.h"
#include "vtkFloatNormals.h"
#include "vtkFloatTCoords.h"
#include "vtkMath.h"
#include "vtkTransform.h"

// Description:
// Construct plane perpendicular to z-axis, resolution 1x1, width and height 1.0,
// and centered at the origin.
vtkPlaneSource::vtkPlaneSource()
{
  this->XResolution = 1;
  this->YResolution = 1;

  this->Origin[0] = this->Origin[1] = -0.5;
  this->Origin[2] = 0.0;

  this->Point1[0] = 0.5;
  this->Point1[1] = -0.5;
  this->Point1[2] = 0.0;

  this->Point2[0] = -0.5;
  this->Point2[1] = 0.5;
  this->Point2[2] = 0.0;

  this->Normal[2] = 1.0;
  this->Normal[0] = this->Normal[1] = 0.0;

  this->Center[0] = this->Center[1] = this->Center[2] = 0.0;
}

// Description:
// Set the number of x-y subdivisions in the plane.
void vtkPlaneSource::SetResolution(const int xR, const int yR)
{
  if ( xR != this->XResolution || yR != this->YResolution )
    {
    this->XResolution = xR;
    this->YResolution = yR;

    this->XResolution = (this->XResolution > 0 ? this->XResolution : 1);
    this->YResolution = (this->YResolution > 0 ? this->YResolution : 1);

    this->Modified();
    }
}

void vtkPlaneSource::Execute()
{
  float x[3], tc[2], v1[3], v2[3];
  int pts[4];
  int i, j, ii;
  int numPts;
  int numPolys;
  vtkFloatPoints *newPoints;
  vtkFloatNormals *newNormals;
  vtkFloatTCoords *newTCoords;
  vtkCellArray *newPolys;
  vtkPolyData *output = this->GetOutput();

  // Check input
  for ( i=0; i < 3; i++ )
    {
    v1[i] = this->Point1[i] - this->Origin[i];
    v2[i] = this->Point2[i] - this->Origin[i];
    }
  if ( !this->UpdatePlane(v1,v2) ) return;

  //
  // Set things up; allocate memory
  //
  numPts = (this->XResolution+1) * (this->YResolution+1);
  numPolys = this->XResolution * this->YResolution;

  newPoints = vtkFloatPoints::New();
  newPoints->Allocate(numPts);
  newNormals = vtkFloatNormals::New();
  newNormals->Allocate(numPts);
  newTCoords = vtkFloatTCoords::New();
  newTCoords->Allocate(numPts,2);

  newPolys = vtkCellArray::New();
  newPolys->Allocate(newPolys->EstimateSize(numPolys,4));
//
// Generate points and point data
//
  for (numPts=0, i=0; i<(this->YResolution+1); i++)
    {
    tc[1] = (float) i / this->YResolution;
    for (j=0; j<(this->XResolution+1); j++)
      {
      tc[0] = (float) j / this->XResolution;

      for ( ii=0; ii < 3; ii++)
        {
        x[ii] = this->Origin[ii] + tc[0]*v1[ii] + tc[1]*v2[ii];
        }

      newPoints->InsertPoint(numPts,x);
      newTCoords->InsertTCoord(numPts,tc);
      newNormals->InsertNormal(numPts++,this->Normal);
      }
    }
//
// Generate polygon connectivity
//
  for (i=0; i<this->YResolution; i++)
    {
    for (j=0; j<this->XResolution; j++)
      {
      pts[0] = j + i*(this->XResolution+1);
      pts[1] = pts[0] + 1;
      pts[2] = pts[0] + this->XResolution + 2;
      pts[3] = pts[0] + this->XResolution + 1;
      newPolys->InsertNextCell(4,pts);
      }
    }
//
// Update ourselves and release memory
//
  output->SetPoints(newPoints);
  newPoints->Delete();

  output->GetPointData()->SetNormals(newNormals);
  newNormals->Delete();

  output->GetPointData()->SetTCoords(newTCoords);
  newTCoords->Delete();

  output->SetPolys(newPolys);
  newPolys->Delete();
}

// Description:
// Set the normal to the plane. Will modify the Origin, Point1, and Point2
// instance variables as necessary (i.e., rotate the plane around its center).
void vtkPlaneSource::SetNormal(float N[3])
{
  float n[3], v1[3], v2[3], p[4];
  float rotVector[3], theta;
  int i;
  vtkTransform transform;

  // compute plane axes
  for ( i=0; i < 3; i++)
    {
    n[i] = N[i];
    v1[i] = this->Point1[i] - this->Origin[i];
    v2[i] = this->Point2[i] - this->Origin[i];
    }

  //make sure input is decent
  if ( vtkMath::Normalize(n) == 0.0 )
    {
    vtkErrorMacro(<<"Specified zero normal");
    return;
    }
  if ( !this->UpdatePlane(v1,v2) ) return;

  //compute rotation vector
  vtkMath::Cross(this->Normal,n,rotVector);
  if ( vtkMath::Normalize(rotVector) == 0.0 ) return; //no rotation
  theta = acos((double)vtkMath::Dot(this->Normal,n)) / vtkMath::DegreesToRadians();

  // create rotation matrix
  transform.PostMultiply();

  transform.Translate(-this->Center[0],-this->Center[1],-this->Center[2]);
  transform.RotateWXYZ(theta,rotVector[0],rotVector[1],rotVector[2]);
  transform.Translate(this->Center[0],this->Center[1],this->Center[2]);

  // transform the three defining points
  transform.SetPoint(this->Origin[0],this->Origin[1],this->Origin[2],1.0);
  transform.GetPoint(p);
  for (i=0; i < 3; i++) this->Origin[i] = p[i] / p[3];

  transform.SetPoint(this->Point1[0],this->Point1[1],this->Point1[2],1.0);
  transform.GetPoint(p);
  for (i=0; i < 3; i++) this->Point1[i] = p[i] / p[3];

  transform.SetPoint(this->Point2[0],this->Point2[1],this->Point2[2],1.0);
  transform.GetPoint(p);
  for (i=0; i < 3; i++) this->Point2[i] = p[i] / p[3];

  this->Modified();
}

// Description:
// Set the normal to the plane. Will modify the Origin, Point1, and Point2
// instance variables as necessary (i.e., rotate the plane around its center).
void vtkPlaneSource::SetNormal(float nx, float ny, float nz)
{
  float n[3];

  n[0] = nx; n[1] = ny; n[2] = nz;
  this->SetNormal(n);
}

// Description:
// Set the center of the plane. Will modify the Origin, Point1, and Point2
// instance variables as necessary (i.e., translate the plane).
void vtkPlaneSource::SetCenter(float center[3])
{
  if ( this->Center[0] == center[0] && this->Center[1] == center[1] &&
  this->Center[2] == center[2] )
    {
    return; //no change
    }
  else
    {
    int i;
    float v1[3], v2[3];

    for ( i=0; i < 3; i++ )
      {
      v1[i] = this->Point1[i] - this->Origin[i];
      v2[i] = this->Point2[i] - this->Origin[i];
      }

    for ( i=0; i < 3; i++ )
      {
      this->Center[i] = center[i];
      this->Origin[i] = this->Center[i] - 0.5*(v1[i] + v2[i]);
      this->Point1[i] = this->Origin[i] + v1[i];
      this->Point2[i] = this->Origin[i] + v2[i];
      }
    this->Modified();
    }
}

// Description:
// Set the center of the plane. Will modify the Origin, Point1, and Point2
// instance variables as necessary (i.e., translate the plane).
void vtkPlaneSource::SetCenter(float x, float y, float z)
{
  float center[3];

  center[0] = x; center[1] = y; center[2] = z;
  this->SetCenter(center);
}

// modifies the normal and origin
void vtkPlaneSource::SetPoint1(float pnt[3])
{
  if ( this->Point1[0] == pnt[0] && this->Point1[1] == pnt[1] &&
       this->Point1[2] == pnt[2] )
    {
    return; //no change
    }
  else
    {
    int i;
    float v1[3], v2[3];

    for ( i=0; i < 3; i++ )
      {
      this->Point1[i] = pnt[i];
      v1[i] = this->Point1[i] - this->Origin[i];
      v2[i] = this->Point2[i] - this->Origin[i];
      }

    // set plane normal
    vtkMath::Cross(v1,v2,this->Normal);
    if ( vtkMath::Normalize(this->Normal) == 0.0 )
      {
      vtkErrorMacro(<<"Bad plane coordinate system");
      }
    this->Modified();
    }
}

// modifies the normal and origin
void vtkPlaneSource::SetPoint2(float pnt[3])
{
  if ( this->Point2[0] == pnt[0] && this->Point2[1] == pnt[1] &&
       this->Point2[2] == pnt[2] )
    {
    return; //no change
    }
  else
    {
    int i;
    float v1[3], v2[3];

    for ( i=0; i < 3; i++ )
      {
      this->Point2[i] = pnt[i];
      v1[i] = this->Point1[i] - this->Origin[i];
      v2[i] = this->Point2[i] - this->Origin[i];
      }
    // set plane normal
    vtkMath::Cross(v1,v2,this->Normal);
    if ( vtkMath::Normalize(this->Normal) == 0.0 )
      {
      vtkErrorMacro(<<"Bad plane coordinate system");
      }
    this->Modified();
    }
}

void vtkPlaneSource::SetPoint1(float x, float y, float z)
{
  float pnt[3];

  pnt[0] = x; pnt[1] = y; pnt[2] = z;
  this->SetPoint1(pnt);
}
void vtkPlaneSource::SetPoint2(float x, float y, float z)
{
  float pnt[3];

  pnt[0] = x; pnt[1] = y; pnt[2] = z;
  this->SetPoint2(pnt);
}

// Description:
// Translate the plane in the direction of the normal by the distance specified.
// Negative values move the plane in the opposite direction.
void vtkPlaneSource::Push(float distance)
{
  if ( distance == 0.0 ) return;

  for ( int i=0; i < 3; i++ )
    {
    this->Origin[i] += distance * this->Normal[i];
    this->Point1[i] += distance * this->Normal[i];
    this->Point2[i] += distance * this->Normal[i];
    }

  this->Modified();
}

// Protected method updates normals and plane center from two axes.
int vtkPlaneSource::UpdatePlane(float v1[3], float v2[3])
{
  // set plane center
  for ( int i=0; i < 3; i++ )
    {
    this->Center[i] = this->Origin[i] + 0.5*(v1[i] + v2[i]);
    }

  // set plane normal
  vtkMath::Cross(v1,v2,this->Normal);
  if ( vtkMath::Normalize(this->Normal) == 0.0 )
    {
    vtkErrorMacro(<<"Bad plane coordinate system");
    return 0;
    }
  else
    {
    return 1;
    }
}

void vtkPlaneSource::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkPolyDataSource::PrintSelf(os,indent);

  os << indent << "X Resolution: " << this->XResolution << "\n";
  os << indent << "Y Resolution: " << this->YResolution << "\n";

  os << indent << "Origin: (" << this->Origin[0] << ", "
                              << this->Origin[1] << ", "
                              << this->Origin[2] << ")\n";

  os << indent << "Point 1: (" << this->Point1[0] << ", "
                               << this->Point1[1] << ", "
                               << this->Point1[2] << ")\n";

  os << indent << "Point 2: (" << this->Point2[0] << ", "
                               << this->Point2[1] << ", "
                               << this->Point2[2] << ")\n";

  os << indent << "Normal: (" << this->Normal[0] << ", "
                              << this->Normal[1] << ", "
                              << this->Normal[2] << ")\n";

  os << indent << "Center: (" << this->Center[0] << ", "
                              << this->Center[1] << ", "
                              << this->Center[2] << ")\n";

}
<commit_msg>ERR: SetNormal was not updating Normal ivar<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkPlaneSource.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkPlaneSource.h"
#include "vtkFloatPoints.h"
#include "vtkFloatNormals.h"
#include "vtkFloatTCoords.h"
#include "vtkMath.h"
#include "vtkTransform.h"

// Description:
// Construct plane perpendicular to z-axis, resolution 1x1, width and height 1.0,
// and centered at the origin.
vtkPlaneSource::vtkPlaneSource()
{
  this->XResolution = 1;
  this->YResolution = 1;

  this->Origin[0] = this->Origin[1] = -0.5;
  this->Origin[2] = 0.0;

  this->Point1[0] = 0.5;
  this->Point1[1] = -0.5;
  this->Point1[2] = 0.0;

  this->Point2[0] = -0.5;
  this->Point2[1] = 0.5;
  this->Point2[2] = 0.0;

  this->Normal[2] = 1.0;
  this->Normal[0] = this->Normal[1] = 0.0;

  this->Center[0] = this->Center[1] = this->Center[2] = 0.0;
}

// Description:
// Set the number of x-y subdivisions in the plane.
void vtkPlaneSource::SetResolution(const int xR, const int yR)
{
  if ( xR != this->XResolution || yR != this->YResolution )
    {
    this->XResolution = xR;
    this->YResolution = yR;

    this->XResolution = (this->XResolution > 0 ? this->XResolution : 1);
    this->YResolution = (this->YResolution > 0 ? this->YResolution : 1);

    this->Modified();
    }
}

void vtkPlaneSource::Execute()
{
  float x[3], tc[2], v1[3], v2[3];
  int pts[4];
  int i, j, ii;
  int numPts;
  int numPolys;
  vtkFloatPoints *newPoints;
  vtkFloatNormals *newNormals;
  vtkFloatTCoords *newTCoords;
  vtkCellArray *newPolys;
  vtkPolyData *output = this->GetOutput();

  // Check input
  for ( i=0; i < 3; i++ )
    {
    v1[i] = this->Point1[i] - this->Origin[i];
    v2[i] = this->Point2[i] - this->Origin[i];
    }
  if ( !this->UpdatePlane(v1,v2) ) return;

  //
  // Set things up; allocate memory
  //
  numPts = (this->XResolution+1) * (this->YResolution+1);
  numPolys = this->XResolution * this->YResolution;

  newPoints = vtkFloatPoints::New();
  newPoints->Allocate(numPts);
  newNormals = vtkFloatNormals::New();
  newNormals->Allocate(numPts);
  newTCoords = vtkFloatTCoords::New();
  newTCoords->Allocate(numPts,2);

  newPolys = vtkCellArray::New();
  newPolys->Allocate(newPolys->EstimateSize(numPolys,4));
//
// Generate points and point data
//
  for (numPts=0, i=0; i<(this->YResolution+1); i++)
    {
    tc[1] = (float) i / this->YResolution;
    for (j=0; j<(this->XResolution+1); j++)
      {
      tc[0] = (float) j / this->XResolution;

      for ( ii=0; ii < 3; ii++)
        {
        x[ii] = this->Origin[ii] + tc[0]*v1[ii] + tc[1]*v2[ii];
        }

      newPoints->InsertPoint(numPts,x);
      newTCoords->InsertTCoord(numPts,tc);
      newNormals->InsertNormal(numPts++,this->Normal);
      }
    }
//
// Generate polygon connectivity
//
  for (i=0; i<this->YResolution; i++)
    {
    for (j=0; j<this->XResolution; j++)
      {
      pts[0] = j + i*(this->XResolution+1);
      pts[1] = pts[0] + 1;
      pts[2] = pts[0] + this->XResolution + 2;
      pts[3] = pts[0] + this->XResolution + 1;
      newPolys->InsertNextCell(4,pts);
      }
    }
//
// Update ourselves and release memory
//
  output->SetPoints(newPoints);
  newPoints->Delete();

  output->GetPointData()->SetNormals(newNormals);
  newNormals->Delete();

  output->GetPointData()->SetTCoords(newTCoords);
  newTCoords->Delete();

  output->SetPolys(newPolys);
  newPolys->Delete();
}

// Description:
// Set the normal to the plane. Will modify the Origin, Point1, and Point2
// instance variables as necessary (i.e., rotate the plane around its center).
void vtkPlaneSource::SetNormal(float N[3])
{
  float n[3], v1[3], v2[3], p[4];
  float rotVector[3], theta;
  int i;
  vtkTransform transform;

  // compute plane axes
  for ( i=0; i < 3; i++)
    {
    n[i] = N[i];
    v1[i] = this->Point1[i] - this->Origin[i];
    v2[i] = this->Point2[i] - this->Origin[i];
    }

  //make sure input is decent
  if ( vtkMath::Normalize(n) == 0.0 )
    {
    vtkErrorMacro(<<"Specified zero normal");
    return;
    }
  if ( !this->UpdatePlane(v1,v2) ) return;

  //compute rotation vector
  vtkMath::Cross(this->Normal,n,rotVector);
  if ( vtkMath::Normalize(rotVector) == 0.0 ) return; //no rotation
  theta = acos((double)vtkMath::Dot(this->Normal,n)) / vtkMath::DegreesToRadians();

  // create rotation matrix
  transform.PostMultiply();

  transform.Translate(-this->Center[0],-this->Center[1],-this->Center[2]);
  transform.RotateWXYZ(theta,rotVector[0],rotVector[1],rotVector[2]);
  transform.Translate(this->Center[0],this->Center[1],this->Center[2]);

  // transform the three defining points
  transform.SetPoint(this->Origin[0],this->Origin[1],this->Origin[2],1.0);
  transform.GetPoint(p);
  for (i=0; i < 3; i++) this->Origin[i] = p[i] / p[3];

  transform.SetPoint(this->Point1[0],this->Point1[1],this->Point1[2],1.0);
  transform.GetPoint(p);
  for (i=0; i < 3; i++) this->Point1[i] = p[i] / p[3];

  transform.SetPoint(this->Point2[0],this->Point2[1],this->Point2[2],1.0);
  transform.GetPoint(p);
  for (i=0; i < 3; i++) this->Point2[i] = p[i] / p[3];

  for (i=0; i < 3; i++) this->Normal[i] = n[i];
  this->Modified();
}

// Description:
// Set the normal to the plane. Will modify the Origin, Point1, and Point2
// instance variables as necessary (i.e., rotate the plane around its center).
void vtkPlaneSource::SetNormal(float nx, float ny, float nz)
{
  float n[3];

  n[0] = nx; n[1] = ny; n[2] = nz;
  this->SetNormal(n);
}

// Description:
// Set the center of the plane. Will modify the Origin, Point1, and Point2
// instance variables as necessary (i.e., translate the plane).
void vtkPlaneSource::SetCenter(float center[3])
{
  if ( this->Center[0] == center[0] && this->Center[1] == center[1] &&
  this->Center[2] == center[2] )
    {
    return; //no change
    }
  else
    {
    int i;
    float v1[3], v2[3];

    for ( i=0; i < 3; i++ )
      {
      v1[i] = this->Point1[i] - this->Origin[i];
      v2[i] = this->Point2[i] - this->Origin[i];
      }

    for ( i=0; i < 3; i++ )
      {
      this->Center[i] = center[i];
      this->Origin[i] = this->Center[i] - 0.5*(v1[i] + v2[i]);
      this->Point1[i] = this->Origin[i] + v1[i];
      this->Point2[i] = this->Origin[i] + v2[i];
      }
    this->Modified();
    }
}

// Description:
// Set the center of the plane. Will modify the Origin, Point1, and Point2
// instance variables as necessary (i.e., translate the plane).
void vtkPlaneSource::SetCenter(float x, float y, float z)
{
  float center[3];

  center[0] = x; center[1] = y; center[2] = z;
  this->SetCenter(center);
}

// modifies the normal and origin
void vtkPlaneSource::SetPoint1(float pnt[3])
{
  if ( this->Point1[0] == pnt[0] && this->Point1[1] == pnt[1] &&
       this->Point1[2] == pnt[2] )
    {
    return; //no change
    }
  else
    {
    int i;
    float v1[3], v2[3];

    for ( i=0; i < 3; i++ )
      {
      this->Point1[i] = pnt[i];
      v1[i] = this->Point1[i] - this->Origin[i];
      v2[i] = this->Point2[i] - this->Origin[i];
      }

    // set plane normal
    vtkMath::Cross(v1,v2,this->Normal);
    if ( vtkMath::Normalize(this->Normal) == 0.0 )
      {
      vtkErrorMacro(<<"Bad plane coordinate system");
      }
    this->Modified();
    }
}

// modifies the normal and origin
void vtkPlaneSource::SetPoint2(float pnt[3])
{
  if ( this->Point2[0] == pnt[0] && this->Point2[1] == pnt[1] &&
       this->Point2[2] == pnt[2] )
    {
    return; //no change
    }
  else
    {
    int i;
    float v1[3], v2[3];

    for ( i=0; i < 3; i++ )
      {
      this->Point2[i] = pnt[i];
      v1[i] = this->Point1[i] - this->Origin[i];
      v2[i] = this->Point2[i] - this->Origin[i];
      }
    // set plane normal
    vtkMath::Cross(v1,v2,this->Normal);
    if ( vtkMath::Normalize(this->Normal) == 0.0 )
      {
      vtkErrorMacro(<<"Bad plane coordinate system");
      }
    this->Modified();
    }
}

void vtkPlaneSource::SetPoint1(float x, float y, float z)
{
  float pnt[3];

  pnt[0] = x; pnt[1] = y; pnt[2] = z;
  this->SetPoint1(pnt);
}
void vtkPlaneSource::SetPoint2(float x, float y, float z)
{
  float pnt[3];

  pnt[0] = x; pnt[1] = y; pnt[2] = z;
  this->SetPoint2(pnt);
}

// Description:
// Translate the plane in the direction of the normal by the distance specified.
// Negative values move the plane in the opposite direction.
void vtkPlaneSource::Push(float distance)
{
  if ( distance == 0.0 ) return;

  for ( int i=0; i < 3; i++ )
    {
    this->Origin[i] += distance * this->Normal[i];
    this->Point1[i] += distance * this->Normal[i];
    this->Point2[i] += distance * this->Normal[i];
    }

  this->Modified();
}

// Protected method updates normals and plane center from two axes.
int vtkPlaneSource::UpdatePlane(float v1[3], float v2[3])
{
  // set plane center
  for ( int i=0; i < 3; i++ )
    {
    this->Center[i] = this->Origin[i] + 0.5*(v1[i] + v2[i]);
    }

  // set plane normal
  vtkMath::Cross(v1,v2,this->Normal);
  if ( vtkMath::Normalize(this->Normal) == 0.0 )
    {
    vtkErrorMacro(<<"Bad plane coordinate system");
    return 0;
    }
  else
    {
    return 1;
    }
}

void vtkPlaneSource::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkPolyDataSource::PrintSelf(os,indent);

  os << indent << "X Resolution: " << this->XResolution << "\n";
  os << indent << "Y Resolution: " << this->YResolution << "\n";

  os << indent << "Origin: (" << this->Origin[0] << ", "
                              << this->Origin[1] << ", "
                              << this->Origin[2] << ")\n";

  os << indent << "Point 1: (" << this->Point1[0] << ", "
                               << this->Point1[1] << ", "
                               << this->Point1[2] << ")\n";

  os << indent << "Point 2: (" << this->Point2[0] << ", "
                               << this->Point2[1] << ", "
                               << this->Point2[2] << ")\n";

  os << indent << "Normal: (" << this->Normal[0] << ", "
                              << this->Normal[1] << ", "
                              << this->Normal[2] << ")\n";

  os << indent << "Center: (" << this->Center[0] << ", "
                              << this->Center[1] << ", "
                              << this->Center[2] << ")\n";

}
<|endoftext|>


<commit_before>/*
* Copyright 2014 Adam Hollidge <adam@anh.io>
*/

#include <SGP4.h>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <utility>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>

using namespace std;

// Chronological sort.
bool chron(const Tle& a, const Tle& b)
{
    return a.Epoch() < b.Epoch();
}

class Groundtrack
{
public:
    Groundtrack(DateTime start_date,
                DateTime end_date,
                int dt,
                std::vector<Tle> tles)
                : start_date_(start_date),
                  end_date_(end_date_),
                  dt_(TimeSpan(0, 0, dt)),
                  tles_(tles),
                  active_tle_(0)
{
    std::sort(tles_.begin(), tles_.end(), chron);
    cout << "dt:\t" << dt_ << endl;
}

    std::string GeoJSON()
    {
        DateTime currtime(start_date_);
        SGP4 sgp(tles_[active_tle_]);

        cout << currtime.ToString() << endl;

        return "GeoJSON";
    }

private:
    DateTime            start_date_;
    DateTime            end_date_;
    TimeSpan            dt_;
    std::vector<Tle>    tles_;
    size_t              active_tle_; // index into tles_.
};

int main(int argc, char **argv)
{
    struct tm start_tm, end_tm;
    DateTime start_time, end_time;
    long long dt = 60; // delta time between groundtrack points
	int c;
    char *s_opt = 0, *e_opt = 0, *t_opt = 0;
    char *zero_opt = 0, *one_opt = 0, *two_opt = 0;

    std::string options("0:1:2:3:s:e:t:");
    while ( (c = getopt(argc, argv, options.c_str())) != -1) {
        switch (c) {
        case '0':
        	std::cout << "Option 0: " << optarg << "\n";
        	zero_opt = optarg;
        	break;
        case '1':
        std::cout << "Option 0: " << optarg << "\n";
        	one_opt = optarg;
        	break;
        case '2':
        	std::cout << "Option 0: " << optarg << "\n";
        	two_opt = optarg;
            break;
        case 's':
            s_opt = optarg;
            if (strptime(s_opt, "%Y-%m-%d %H:%M:%S", &start_tm) == NULL) {
                cerr << "Error parsing start time.\n";
                exit(0);
            }
            cout << start_tm.tm_mon << endl;
            start_time.Initialise(1900 + start_tm.tm_year,
                                  start_tm.tm_mon + 1,
                                  start_tm.tm_mday,
                                  start_tm.tm_hour,
                                  start_tm.tm_min,
                                  start_tm.tm_sec,
                                  0);
            break;
        case 'e':
            e_opt = optarg;
            if (strptime(e_opt, "%Y-%m-%d %H:%M:%S", &end_tm) == NULL) {
                cerr << "Error parsing end time.\n";
                exit(0);
            }
            end_time.Initialise(1900 + end_tm.tm_year,
                                end_tm.tm_mon + 1,
                                end_tm.tm_mday,
                                end_tm.tm_hour,
                                end_tm.tm_min,
                                end_tm.tm_sec,
                                0);
            break;
        case 't':
            t_opt = optarg;
            dt = atoll(t_opt);
            break;
        case '?':
            break;
        default:
            printf ("?? getopt returned character code 0%o ??\n", c);
        }
    }

    // Parse non-option arguments.
    if (optind < argc) {
        while (optind < argc)
            printf ("%s ", argv[optind++]);
        printf ("\n");
    }

    // Handle TLEs piped into stdin.
    string line1, line2;
    vector<Tle> tles;
    while(getline(cin, line1)) {
        getline(cin, line2);
        Tle tle(line1, line2);
        if (tle.Epoch() >= start_time && tle.Epoch() <= end_time)
            tles.push_back(tle);
    }
    Groundtrack gt(start_time, end_time, dt, std::move(tles));
    cout << gt.GeoJSON() << endl;

    exit (0);
	return 0;
}<commit_msg>Correct init of end_date_ in initializer list.<commit_after>/*
* Copyright 2014 Adam Hollidge <adam@anh.io>
*/

#include <SGP4.h>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <utility>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>

using namespace std;

// Chronological sort.
bool chron(const Tle& a, const Tle& b)
{
    return a.Epoch() < b.Epoch();
}

class Groundtrack
{
public:
    Groundtrack(DateTime start_date,
                DateTime end_date,
                int dt,
                std::vector<Tle> tles)
                : start_date_(start_date),
                  end_date_(end_date),
                  dt_(TimeSpan(0, 0, dt)),
                  tles_(tles),
                  active_tle_(0)
{
    std::sort(tles_.begin(), tles_.end(), chron);
    cout << "dt:\t" << dt_ << endl;
}

    std::string GeoJSON()
    {
        DateTime currtime(start_date_);
        SGP4 sgp(tles_[active_tle_]);
        cout << currtime.ToString() << endl;
        cout << end_date_.ToString() << endl;
        while (currtime < end_date_)
        {
            currtime = currtime.Add(dt_);
            cout << currtime.ToString() << endl;
        }
        return "GeoJSON";
    }

private:
    DateTime            start_date_;
    DateTime            end_date_;
    TimeSpan            dt_;
    std::vector<Tle>    tles_;
    size_t              active_tle_; // index into tles_.
};

int main(int argc, char **argv)
{
    struct tm start_tm, end_tm;
    DateTime start_time, end_time;
    long long dt = 60; // delta time between groundtrack points
	int c;
    char *s_opt = 0, *e_opt = 0, *t_opt = 0;
    char *zero_opt = 0, *one_opt = 0, *two_opt = 0;

    std::string options("0:1:2:3:s:e:t:");
    while ( (c = getopt(argc, argv, options.c_str())) != -1) {
        switch (c) {
        case '0':
        	std::cout << "Option 0: " << optarg << "\n";
        	zero_opt = optarg;
        	break;
        case '1':
        std::cout << "Option 0: " << optarg << "\n";
        	one_opt = optarg;
        	break;
        case '2':
        	std::cout << "Option 0: " << optarg << "\n";
        	two_opt = optarg;
            break;
        case 's':
            s_opt = optarg;
            if (strptime(s_opt, "%Y-%m-%d %H:%M:%S", &start_tm) == NULL) {
                cerr << "Error parsing start time.\n";
                exit(0);
            }
            cout << start_tm.tm_mon << endl;
            start_time.Initialise(1900 + start_tm.tm_year,
                                  start_tm.tm_mon + 1,
                                  start_tm.tm_mday,
                                  start_tm.tm_hour,
                                  start_tm.tm_min,
                                  start_tm.tm_sec,
                                  0);
            break;
        case 'e':
            e_opt = optarg;
            if (strptime(e_opt, "%Y-%m-%d %H:%M:%S", &end_tm) == NULL) {
                cerr << "Error parsing end time.\n";
                exit(0);
            }
            end_time.Initialise(1900 + end_tm.tm_year,
                                end_tm.tm_mon + 1,
                                end_tm.tm_mday,
                                end_tm.tm_hour,
                                end_tm.tm_min,
                                end_tm.tm_sec,
                                0);
            cout << end_time.ToString() << endl;
            break;
        case 't':
            t_opt = optarg;
            dt = atoll(t_opt);
            break;
        case '?':
            break;
        default:
            printf ("?? getopt returned character code 0%o ??\n", c);
        }
    }

    // Parse non-option arguments.
    if (optind < argc) {
        while (optind < argc)
            printf ("%s ", argv[optind++]);
        printf ("\n");
    }

    // Handle TLEs piped into stdin.
    string line1, line2;
    vector<Tle> tles;
    while(getline(cin, line1)) {
        getline(cin, line2);
        Tle tle(line1, line2);
        if (tle.Epoch() >= start_time && tle.Epoch() <= end_time)
            tles.push_back(tle);
    }
    Groundtrack gt(start_time, end_time, dt, std::move(tles));
    cout << gt.GeoJSON() << endl;

    exit (0);
	return 0;
}<|endoftext|>