src/main.cpp
author David Anderson <dvander@alliedmods.net>
Tue Jan 01 20:07:09 2013 -0800 (2013-01-01)
changeset 254 cd167be62cbe
parent 251 ca99a81745fe
permissions -rw-r--r--
Fix Linux build.
     1 /* vim: set ts=4 sw=4 tw=99 et:
     2  *
     3  * Copyright (C) 2012 David Anderson
     4  *
     5  * This file is part of SourcePawn.
     6  *
     7  * SourcePawn is free software: you can redistribute it and/or modify it under
     8  * the terms of the GNU General Public License as published by the Free
     9  * Software Foundation, either version 3 of the License, or (at your option)
    10  * any later version.
    11  * 
    12  * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
    13  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU General Public License along with
    17  * SourcePawn. If not, see http://www.gnu.org/licenses/.
    18  */
    19 #include <stdio.h>
    20 #include <stdlib.h>
    21 #include <string.h>
    22 #include "../include/keima.h"
    23 #include "Utility.h"
    24 #include "Platform.h"
    25 #ifdef WIN32
    26 # include <Windows.h>
    27 # include <direct.h>
    28 #else
    29 # include <unistd.h>
    30 #endif
    31 
    32 using namespace Ke;
    33 
    34 class MessageReporter : public IMessageReporter
    35 {
    36   public:
    37     void onOutOfMemory() {
    38         fprintf(stderr, "Out of memory!\n");
    39     }
    40     void onUncaughtException(const char *message) {
    41         fprintf(stderr, "Uncaught exception: %s\n", message);
    42 
    43         IStackFrameIterator *iter = Keima::NewStackFrameIterator();
    44         unsigned index = 0;
    45 
    46         const char *filename = iter->source();
    47         if (!filename)
    48             filename = "<anonymous>";
    49         if (const char *tail = strrchr(filename, '/'))
    50             filename = tail + 1;
    51 #ifdef WIN32
    52         if (const char *tail = strrchr(filename, '\\'))
    53             filename = tail + 1;
    54 #endif
    55 
    56         while (!iter->done() && index < 10) {
    57             fprintf(stderr, "[%d] %s (%s line %d)\n",
    58                     index,
    59                     iter->function(),
    60                     filename,
    61                     iter->lineNumber());
    62             iter->prev();
    63             index++;
    64         }
    65     }
    66     virtual void beginCompilationErrors(const char *file) {
    67         fprintf(stderr, "Displaying compilation errors for \"%s\"\n", file);
    68     }
    69     virtual void reportCompilationError(const char *message, unsigned line, unsigned col) {
    70         fprintf(stderr, "  line %d, col %d: %s\n", line, col, message);
    71     }
    72     virtual void endCompilationErrors() {
    73     }
    74 } s_Reporter;
    75 
    76 class MainCollector : public Ke::IPublicFunctionListener
    77 {
    78   public:
    79     MainCollector()
    80     {
    81     }
    82     void registerPublic(Handle<Function> fun) {
    83         Local<String> str = fun->name();
    84         if (str && strcmp(str->chars(), "main") == 0)
    85             fun_ = fun;
    86     }
    87 
    88     void unregisterPublic(Handle<Function> fun) {
    89         if (fun_ == fun)
    90             fun_ = Handle<Function>();
    91     }
    92 
    93     Handle<Function> fun() const {
    94         return fun_;
    95     }
    96 
    97   private:
    98     Root<Function> fun_;
    99 };
   100 
   101 intptr_t PrintFloat(void *blah, intptr_t *params)
   102 {
   103     fprintf(stdout, "%f", *reinterpret_cast<float *>(&params[1]));
   104     return 0;
   105 }
   106 
   107 intptr_t PrintNum(void *blah, intptr_t *params)
   108 {
   109     fprintf(stdout, "%i", *reinterpret_cast<int *>(&params[1]));
   110     return 0;
   111 }
   112 
   113 intptr_t PrintString(void *blah, intptr_t *params)
   114 {
   115     fprintf(stdout, "%s", *reinterpret_cast<const char **>(&params[1]));
   116     return 0;
   117 }
   118 
   119 int main(int argc, char **argv)
   120 {
   121     if (argc < 2) {
   122         fprintf(stderr, "Usage: <file>\n");
   123         return 1;
   124     }
   125 
   126     if (!Keima::Initialize())
   127         return 1;
   128 
   129     ke::AutoFree<char> fullpath;
   130     if (!ke::OS::GetAbsolutePath(argv[1], fullpath))
   131         return 1;
   132 
   133     ke::AutoFree<char> path, name;
   134     if (!ke::OS::SplitPath(*fullpath, path, name))
   135         return 1;
   136 
   137     int rval = 0;
   138 
   139     Keima::InstallMessageReporter(&s_Reporter);
   140     do {
   141         MainCollector entry;
   142         Keima::SetPublicFunctionListener(&entry);
   143 
   144         HandleScope scope;
   145         Local<Package> package = Package::New(Handle<Package>(), Handle<String>(), *path, Package::Normal);
   146         if (!package) {
   147             rval = 1;
   148             break;
   149         }
   150 
   151         if (!Keima::Compile(package, *name)) {
   152             rval = 1;
   153             break;
   154         }
   155 
   156         Keima::CollectGarbage();
   157 
   158         Keima::BindNative("PrintFloat", (void *)PrintFloat);
   159         Keima::BindNative("PrintNum", (void *)PrintNum);
   160         Keima::BindNative("PrintString", (void *)PrintString);
   161 
   162         Handle<Function> fun = entry.fun();
   163 
   164         if (!fun) {
   165             fprintf(stdout, "Not running; no public 'main'.\n");
   166         } else {
   167             if (!Keima::Invoke(fun, NULL, 0, true, &rval))
   168                 rval = 1;
   169         }
   170     } while (0);
   171 
   172     Keima::Shutdown();
   173 
   174     return rval;
   175 }
   176 
   177 /* Overload a few things to prevent libstdc++ linking */
   178 #if defined __linux__ || defined __APPLE__
   179 extern "C" void __cxa_pure_virtual(void)
   180 {
   181 }
   182 
   183 void *operator new(size_t size)
   184 {
   185     return malloc(size);
   186 }
   187 
   188 void *operator new[](size_t size) 
   189 {
   190     return malloc(size);
   191 }
   192 
   193 void operator delete(void *ptr) 
   194 {
   195     free(ptr);
   196 }
   197 
   198 void operator delete[](void * ptr)
   199 {
   200     free(ptr);
   201 }
   202 #endif
   203