From: Michael D. Lowis Date: Tue, 1 Nov 2022 19:22:01 +0000 (-0400) Subject: cleanup cruft and add first pass protocol parser X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=69d635c52f4c9af8eda169a650f1f415161a7f9b;p=proto%2Faos.git cleanup cruft and add first pass protocol parser --- diff --git a/.gitignore b/.gitignore index 3f87daf..12d18d3 100644 --- a/.gitignore +++ b/.gitignore @@ -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 index 0000000..bddc06d --- /dev/null +++ b/share/mbus/protocols/broker @@ -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 index 54927f3..0000000 --- a/tools/build.c +++ /dev/null @@ -1,397 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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 index fd5141f..0000000 --- a/tools/build.sh +++ /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 index 0000000..866e96a --- /dev/null +++ b/tools/mbus_parse @@ -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 \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(".",".")