]> git.mdlowis.com Git - proto/aos.git/commitdiff
cleanup cruft and add first pass protocol parser
authorMichael D. Lowis <mike.lowis@gentex.com>
Tue, 1 Nov 2022 19:22:01 +0000 (15:22 -0400)
committerMichael D. Lowis <mike.lowis@gentex.com>
Tue, 1 Nov 2022 19:22:01 +0000 (15:22 -0400)
.gitignore
share/mbus/protocols/broker [new file with mode: 0644]
tools/build.c [deleted file]
tools/build.sh [deleted file]
tools/mbus_parse [new file with mode: 0755]

index 3f87dafd6be09bea629a28e6e16d3b120b2afe74..12d18d323a6aad6e8cea4394a5ee055e8e648e09 100644 (file)
@@ -2,3 +2,4 @@ build/
 build.bin
 tags
 rules.mk
+temp
diff --git a/share/mbus/protocols/broker b/share/mbus/protocols/broker
new file mode 100644 (file)
index 0000000..bddc06d
--- /dev/null
@@ -0,0 +1,27 @@
+protocol Broker do
+    ##
+    # Client Connection Management
+    ##
+    procedure(:Connect,
+        :ConnectRequest, :ConnectResponse)
+
+    message(:ConnectRequest)
+        .hostname(String)
+
+    message(:ConnectResponse)
+        .status(:Integer)
+        .node_id(:Integer)
+
+    message(:NodeConnected)
+        .node_id(:Integer)
+        .hostname(:String)
+
+    message(:NodeDisconnected)
+        .node_id(:Integer)
+
+
+    ##
+    # Client Connection
+    ##
+
+end
\ No newline at end of file
diff --git a/tools/build.c b/tools/build.c
deleted file mode 100644 (file)
index 54927f3..0000000
+++ /dev/null
@@ -1,397 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-enum { F_FILES, F_DIRS };
-
-typedef struct Target {
-    struct Target* next;
-    char** outputs;
-    char** inputs;
-    void (*build)(struct Target*);
-} Target;
-
-int MaxJobs = 12;
-
-char* CCCMD[] = {
-    "cc",
-    "-Wall", "-Wextra", "-Werror",
-    "-Iinc/",
-    "-I/usr/X11/include/",
-    "-I/usr/X11/include/freetype2",
-    "-I/usr/include/freetype2/",
-    "-g", "-c", "-o",
-    /* output */
-    /* inputs */
-    NULL
-};
-
-char* ARCMD[] = {
-    "ar", "rcs",
-    NULL
-};
-
-char* LDCMD[] = {
-    "cc",
-    "-L./build/lib",
-    "-L/usr/X11/lib/",
-    "-g", "-o",
-    /* output */
-    /* inputs */
-    /* LIBS */
-    NULL
-};
-
-char* LIBS[] = {
-    "-lnet",
-    "-lui",
-    "-la",
-    "-lX11",
-    "-lXft",
-    "-lfontconfig",
-    NULL
-};
-
-Target* Srcs = NULL;
-Target* Libs = NULL;
-Target* Bins = NULL;
-
-/*
-    Helper Routines
-*/
-
-static char* strmcat(char* first, ...)
-{
-    va_list args;
-    /* calculate the length of the final string */
-    size_t len = strlen(first);
-    va_start(args, first);
-    for (char* s = NULL; (s = va_arg(args, char*));)
-    {
-        len += strlen(s);
-    }
-    va_end(args);
-    /* allocate the final string and copy the args into it */
-    char *str  = malloc(len+1), *curr = str;
-    while (first && *first)
-    {
-        *(curr++) = *(first++);
-    }
-    va_start(args, first);
-    for (char* s = NULL; (s = va_arg(args, char*));)
-    {
-        while (s && *s)
-        {
-            *(curr++) = *(s++);
-        }
-    }
-    va_end(args);
-    /* null terminate and return */
-    *curr = '\0';
-    return str;
-}
-
-static char** dir_entries(char* path, int flags)
-{
-    size_t nentries = 0;
-    char** entries = calloc(1, sizeof(char*));
-    struct dirent* entry = NULL;
-    struct stat attrs = {0};
-
-    DIR* dir = opendir(path);
-    while ( (entry = readdir(dir)) )
-    {
-        if (entry->d_name[0] == '.') continue;
-        char* epath = strmcat(path, "/", entry->d_name, 0);
-        memset(&attrs, 0, sizeof(attrs));
-        stat(epath, &attrs);
-        if ( ((flags == F_FILES) && !S_ISDIR(attrs.st_mode)) ||
-             ((flags == F_DIRS) && S_ISDIR(attrs.st_mode)) )
-        {
-            entries = realloc(entries, (nentries+2)*sizeof(char*));
-            entries[nentries++] = epath;
-            entries[nentries] = NULL;
-        }
-    }
-
-    return entries;
-}
-
-char** make_cmd(char*** cmd_parts)
-{
-    size_t count = 0;
-    char** cmd = NULL;
-    for (; *cmd_parts; cmd_parts++)
-    {
-        char** subpart = *cmd_parts;
-        for (; *subpart; subpart++)
-        {
-            cmd = realloc(cmd, ++count * sizeof(char*));
-            cmd[count-1] = *subpart;
-        }
-    }
-    cmd = realloc(cmd, ++count * sizeof(char*));
-    cmd[count-1] = NULL;
-    return cmd;
-}
-
-void print_cmd(char** cmd)
-{
-    for (; *cmd; cmd++)
-    {
-        printf("%s ", *cmd);
-    }
-    puts("");
-}
-
-int wait_for_jobs(int count)
-{
-    int ret_status = 0;
-    do
-    {
-        int status = 0;
-        waitpid(-1, &status, 0);
-        if (WIFEXITED(status))
-        {
-            count--;
-        }
-        int exitcode = WEXITSTATUS(status);
-        ret_status = (!ret_status ? exitcode : ret_status);
-    }
-    while (count > 0);
-    return ret_status;
-}
-
-void make_dirs(char** outputs)
-{
-    for (; *outputs; outputs++)
-    {
-        char* out = strdup(*outputs);
-        char* slash = strrchr(out, '/');
-        if (slash)
-        {
-            *slash = '\0';
-            mkdir(out, 0755);
-        }
-    }
-}
-
-time_t timestamp(char* path)
-{
-    struct stat s;
-    time_t mtime = 0;
-    if (!stat(path, &s))
-    {
-        mtime = s.st_mtime;
-    }
-    return mtime;
-}
-
-int should_rebuild(char** outputs, char** inputs)
-{
-    time_t mtime = 0;
-    for (; *outputs; outputs++)
-    {
-        time_t mt = timestamp(*outputs);
-        mtime = (mt > mtime ? mt : mtime);
-    }
-    for (; *inputs; inputs++)
-    {
-        time_t mt = timestamp(*inputs);
-        if (mt > mtime)
-        {
-            return 1; /* rebuild! */
-        }
-    }
-    return 0; /* no need to rebuild */
-}
-
-/*
-    Build Routines
-*/
-
-void object(Target* tgt)
-{
-    char** cmd = make_cmd((char**[]){ CCCMD, tgt->outputs, tgt->inputs, NULL });
-    print_cmd(cmd);
-    make_dirs(tgt->outputs);
-    exit(execvp(cmd[0], cmd));
-}
-
-void library(Target* tgt)
-{
-    char** cmd = make_cmd((char**[]){ ARCMD, tgt->outputs, tgt->inputs, NULL });
-    print_cmd(cmd);
-    exit(execvp(cmd[0], cmd));
-}
-
-void binary(Target* tgt)
-{
-    char** cmd = make_cmd((char**[]){
-        LDCMD, tgt->outputs, tgt->inputs, LIBS, NULL });
-    print_cmd(cmd);
-    exit(execvp(cmd[0], cmd));
-}
-
-/*
-    Target List Routines
-*/
-
-void add_target(Target** list, char** outputs, char** inputs, void (*build)(Target*))
-{
-    Target* tgt = calloc(1, sizeof(Target));
-    tgt->next = *list;
-    tgt->outputs = outputs;
-    tgt->inputs = inputs;
-    tgt->build = build;
-    *list = tgt;
-}
-
-/*
-    Target Routines
-*/
-
-char* add_src(char* src)
-{
-    char* obj = strmcat("build/obj/", src, 0);
-    obj[strlen(obj)-1] = 'o';
-    char** outputs = calloc(2, sizeof(char*));
-    outputs[0] = obj;
-    char** inputs = calloc(2, sizeof(char*));
-    inputs[0] = src;
-    add_target(&Srcs, outputs, inputs, object);
-    return obj;
-}
-
-char* add_lib(char* path, char** srcs)
-{
-    char* libname = strrchr(path, '/') + 1;
-    char* lib = strmcat("build/lib/lib", libname, ".a", 0);
-    char** outputs = calloc(2, sizeof(char*));
-    outputs[0] = lib;
-    add_target(&Libs, outputs, srcs, library);
-    return lib;
-}
-
-char* add_bin(char* path, char** srcs)
-{
-    char* binname = strdup(strrchr(path, '/') + 1);
-    char* ext = strrchr(binname, '.');
-
-    if (ext)
-    {
-        *ext = '\0';
-    }
-    char* bin = strmcat("build/bin/", binname, 0);
-    char** outputs = calloc(2, sizeof(char*));
-    outputs[0] = bin;
-    add_target(&Bins, outputs, srcs, binary);
-
-    return bin;
-}
-
-char** add_srcs(char* path)
-{
-    char** srcs = dir_entries(path, F_FILES);
-    for (char** s = srcs; *s; s++)
-    {
-        char* obj = add_src(*s);
-        *s = obj;
-    }
-
-    return srcs;
-}
-
-/*
-    Build Routines
-*/
-
-void build_targets(Target* targets)
-{
-    int exitcode = 0;
-    int count = 0;
-
-    for (; !exitcode && targets; targets = targets->next)
-    {
-        count++;
-        int pid = fork();
-        if (pid == 0)
-        {
-            if (targets->build == binary || should_rebuild(targets->outputs, targets->inputs))
-            {
-                targets->build(targets);
-            }
-            exit(0);
-        }
-        else if (count >= MaxJobs)
-        {
-            int code = wait_for_jobs(1);
-            exitcode = (!exitcode ? code : exitcode);
-            count--;
-        }
-    }
-    int code = wait_for_jobs(count);
-    exitcode = (!exitcode ? code : exitcode);
-
-    if (exitcode)
-    {
-        printf("Job Failed!\n");
-        exit(exitcode);
-    }
-}
-
-/*
-    Main Routine
-*/
-
-int main(int argc, char** argv)
-{
-    (void)argc, (void)argv;
-
-    /* register all of the libraries */
-    char** libs = dir_entries("lib", F_DIRS);
-    for (; *libs; libs++)
-    {
-        char** srcs = add_srcs(*libs);
-        add_lib(*libs, srcs);
-    }
-
-    /* register all the complex binaries */
-    char** cbins = dir_entries("bin", F_DIRS);
-    for (; *cbins; cbins++)
-    {
-        char** srcs = add_srcs(*cbins);
-        add_bin(*cbins, srcs);
-    }
-
-    /* register all the simple binaries */
-    char** sbins = dir_entries("bin", F_FILES);
-    for (; *sbins; sbins++)
-    {
-        char** srcs = calloc(2, sizeof(char*));
-        srcs[0] = add_src(*sbins);
-        add_bin(*sbins, srcs);
-    }
-
-    /* create output directories */
-    mkdir("build/", 0755);
-    mkdir("build/obj/", 0755);
-    mkdir("build/obj/bin/", 0755);
-    mkdir("build/obj/lib/", 0755);
-    mkdir("build/bin/", 0755);
-    mkdir("build/lib/", 0755);
-
-    /* now build all of the things */
-    build_targets(Srcs);
-    build_targets(Libs);
-    build_targets(Bins);
-
-    return 0;
-}
\ No newline at end of file
diff --git a/tools/build.sh b/tools/build.sh
deleted file mode 100755 (executable)
index fd5141f..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-
-if [ "tools/build.c" -nt "tools/build.bin" ]; then
-  cc -Wall -Wextra -Werror -o tools/build.bin tools/build.c
-fi
-./tools/build.bin
diff --git a/tools/mbus_parse b/tools/mbus_parse
new file mode 100755 (executable)
index 0000000..866e96a
--- /dev/null
@@ -0,0 +1,145 @@
+#!/bin/env ruby
+
+# Base Data Types:
+#     String
+#     Integer
+#     Float
+#     Bool
+#
+# Aggregate Types:
+#     Array
+#     Record
+
+require 'fileutils'
+
+Procedure = Struct.new(:name, :request, :response)
+
+module Generate
+  def self.typedef(f, proto, msg)
+    f.puts "typedef struct {"
+    msg.fields.each do |k,v|
+      f.puts "    #{v} #{k};"
+    end
+    f.puts "} #{proto}_#{msg.name}_T;\n\n"
+  end
+
+  def self.prototype(f, proto, obj, terminator = "")
+    if obj.is_a? Procedure
+      req = obj.request
+      res = obj.response
+      args = ["MBusConnection* conn"]
+      args += req.fields.map {|e| "#{e[1]} #{e[0]}" }
+      args += ["#{proto}_#{res.name}_T* res"]
+      f.print "int #{proto}_#{obj.name}(#{args.join(", ")})"
+    else
+      f.print "int #{proto}_#{obj.name}(MBusMessage* data, #{proto}_#{obj.name}_T* msg)"
+    end
+    f.puts terminator
+  end
+
+  def self.declaration(f, proto, proc, terminator = "")
+    prototype(f, proto, proc, terminator)
+  end
+
+  def self.definition(f, proto, obj)
+    if obj.is_a? Procedure
+      procedure(f, proto, obj)
+    else
+      accessor(f, proto, obj)
+    end
+  end
+
+  def self.accessor(f, proto, msg)
+    prototype(f, proto, msg)
+    f.puts "{"
+    f.puts "    int status = 1;"
+    msg.fields.each do |k,v|
+      f.puts "    status &&= MBus_#{v}(data, &(msg->#{k});"
+    end
+    f.puts "    return status;"
+    f.puts "}\n\n"
+  end
+
+  def self.procedure(f, proto, proc)
+    prototype(f, proto, proc)
+    f.puts "{"
+    f.puts "    int status = 1;"
+    f.puts "    MBusMessage msg;"
+    f.puts "    status &&= MBus_MessageCreate(conn, &msg);"
+    f.puts "    #{proto}_#{proc.request.name}_T out_data = {"
+    proc.request.fields.each do |name, type|
+      f.puts "        .#{name} = #{name},"
+    end
+    f.puts "    };"
+    f.puts "    status &&= #{proto}_#{proc.request.name}(&msg, &out_data);"
+    f.puts "    status &&= MBus_SendRequest(conn, &msg);"
+    f.puts "    status &&= #{proto}_#{proc.response.name}(&msg, res);"
+    f.puts "    status &&= MBus_MessageDestroy(&msg);"
+    f.puts "    return status;"
+    f.puts "}\n\n"
+  end
+end
+
+class Message
+  attr_reader :name
+  attr_reader :fields
+
+  def initialize(name)
+    @name = name
+    @fields = {}
+  end
+
+  def method_missing(sym, *args, &block)
+    @fields[sym] = args[0]
+    self
+  end
+end
+
+class Parser < Object
+  def initialize(path)
+    @protocols = {}
+    instance_eval(File.read(path))
+  end
+
+  def self.const_missing(const)
+    const
+  end
+
+  def dump(hdrpath, srcpath)
+    FileUtils.mkdir_p(hdrpath)
+    FileUtils.mkdir_p(srcpath)
+    @protocols.each do |proto,members|
+      hdr = File.open(File.join(hdrpath, "#{proto}.h"), "wb")
+      src = File.open(File.join(srcpath, "#{proto}.c"), "wb")
+      hdr.print "#include <MBus.h>\n\n"
+      src.print "#include <#{proto}.h>\n\n"
+      members.each do |k,v|
+        if v.is_a? Message
+          Generate.typedef(hdr, proto, v)
+        end
+        Generate.declaration(hdr, proto, v, ";\n\n")
+        Generate.definition(src, proto, v)
+      end
+    end
+  end
+
+  def protocol(name, &block)
+    @protocol = {}
+    instance_eval(&block)
+    @protocols[name] = @protocol
+    @protocol = nil
+  end
+
+  def message(name, &block)
+    @protocol[name] ||= Message.new(name)
+    @protocol[name]
+  end
+
+  def procedure(name, req_msg, resp_msg)
+    req = message(req_msg)
+    res = message(resp_msg)
+    @protocol[name] ||= Procedure.new(name, req, res)
+  end
+end
+
+Parser.new(ARGV[0]).dump(".",".")