master xplshn/aruu / scripts / genbox.sh
  1#!/bin/sh
  2# genbox.sh - generate the aruu-box dispatch table
  3#
  4# does one thing: given a list of object file paths on argv, each one
  5# of BOX_OBJ's own outputs (".box/cmd/<category>/<tool>.o"), emit the c
  6# source for aruu-box's dispatch table and main() on stdout
  7#
  8set -e
  9
 10[ $# -gt 0 ] || {
 11        printf "genbox: no object paths given\n" >&2
 12        exit 1
 13}
 14
 15# derive category, tool basestem, and c symbol from one BOX_OBJ output
 16# path. the symbol transform (tr '.-' '__', append _main) must match
 17# BOX_OBJ's own objcopy step exactly, see the CATEGORY_OF/symbol
 18# comment in ninqu.rules for why this is a shell transform and not a
 19# map
 20path_category() {
 21        rest=${1#.box/cmd/}
 22        printf "%s\n" "${rest%%/*}"
 23}
 24
 25path_tool() {
 26        rest=${1##*/}
 27        printf "%s\n" "${rest%.o}"
 28}
 29
 30path_symbol() {
 31        tool=$(path_tool "$1")
 32        printf "%s\n" "$(echo "$tool" | tr '.-' '__')_main"
 33}
 34
 35cat << 'HEAD'
 36/* this file is autogenerated by genbox.sh. do not edit */
 37
 38# include "wexec.h"
 39# include "util.h"
 40
 41# include <stdio.h>
 42# include <stdlib.h>
 43# include <string.h>
 44# include <unistd.h>
 45
 46HEAD
 47
 48# extern decls, in the order ninqu passed the objects in (BOX_OBJ's
 49# own glob order, one category at a time)
 50for obj in "$@"; do
 51        sym=$(path_symbol "$obj")
 52        echo "int ${sym}(int, char **);"
 53done
 54
 55cat << 'MID'
 56
 57struct Cmd {
 58        const char *name;
 59        int (*fn)(int, char **);
 60        const char *category;
 61};
 62
 63static struct Cmd cmds[] = {
 64MID
 65
 66categories=$(
 67        for obj in "$@"; do
 68                path_category "$obj"
 69        done | sort -u
 70)
 71
 72for category in $categories; do
 73        for obj in "$@"; do
 74                [ "$(path_category "$obj")" = "$category" ] || continue
 75                tool=$(path_tool "$obj")
 76                sym=$(path_symbol "$obj")
 77                printf '\t{ "%s", %s, "%s" },\n' "$tool" "$sym" "$category"
 78                if [ "$tool" = "test" ]; then
 79                        printf '\t{ "[", %s, "%s" },\n' "$sym" "$category"
 80                fi
 81        done
 82done
 83
 84cat << 'TAIL'
 85        { NULL, NULL, NULL }
 86};
 87
 88static void
 89usage(void)
 90{
 91        struct Cmd *c;
 92        const char *last;
 93        int col;
 94
 95        last = NULL;
 96        col = 0;
 97        fprintf(stderr, "usage: %s [-i path] [command [args...]]\n", argv0);
 98        for (c = cmds; c->name; c++) {
 99                if (!last || strcmp(c->category, last) != 0) {
100                        if (last)
101                                fprintf(stderr, "\n\n");
102                        last = c->category;
103                        fprintf(stderr, "%s:\n", last);
104                        col = 0;
105                }
106                if (col == 0) {
107                        fprintf(stderr, "\t%s", c->name);
108                        col = 8 + strlen(c->name);
109                } else if (col + 2 + strlen(c->name) >= 78) {
110                        fprintf(stderr, ",\n\t%s", c->name);
111                        col = 8 + strlen(c->name);
112                } else {
113                        fprintf(stderr, ", %s", c->name);
114                        col += 2 + strlen(c->name);
115                }
116        }
117        if (last)
118                fputc('\n', stderr);
119        exit(1);
120}
121
122static void
123x_install(const char *path)
124{
125        struct Cmd *c;
126        char buf[4096];
127        int r;
128
129        for (c = cmds; c->name; c++) {
130                r = snprintf(buf, sizeof buf, "%s/%s", path, c->name);
131                if (r < 0 || r >= (int)sizeof buf)
132                        eprintf("install: '%s/%s': path too long\n", path, c->name);
133                remove(buf);
134                if (symlink("aruu-box", buf) < 0)
135                        eprintf("install: symlink '%s':", buf);
136        }
137}
138
139int
140main(int argc, char *argv[])
141{
142        struct Cmd *c;
143        char *s;
144
145        argv0 = argv[0];
146
147        for (c = cmds; c->name; c++)
148                wexec_register(c->name, c->fn);
149
150        s = strrchr(argv[0], '/');
151        if (s)
152                s++;
153        else
154                s = argv[0];
155
156        if (strcmp(s, "aruu-box") == 0) {
157                if (argc < 2)
158                        usage();
159                argc--;
160                argv++;
161                if (strcmp(argv[0], "-i") == 0) {
162                        if (argc < 2)
163                                eprintf("usage: aruu-box -i path\n");
164                        x_install(argv[1]);
165                        return 0;
166                }
167                s = strrchr(argv[0], '/');
168                if (s)
169                        s++;
170                else
171                        s = argv[0];
172        }
173        for (c = cmds; c->name; c++) {
174                if (strcmp(c->name, s) == 0) {
175                        argv0 = (char *)c->name;
176                        argv[0] = (char *)c->name;
177                        return c->fn(argc, argv);
178                }
179        }
180        enprintf(127, "%s: not found\n", s);
181        return 1;
182}
183TAIL