summaryrefslogtreecommitdiff
path: root/appl/wm/mpeg/vlc.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/wm/mpeg/vlc.b')
-rw-r--r--appl/wm/mpeg/vlc.b213
1 files changed, 213 insertions, 0 deletions
diff --git a/appl/wm/mpeg/vlc.b b/appl/wm/mpeg/vlc.b
new file mode 100644
index 00000000..96e136e9
--- /dev/null
+++ b/appl/wm/mpeg/vlc.b
@@ -0,0 +1,213 @@
+implement Vlc;
+
+include "sys.m";
+include "draw.m";
+include "bufio.m";
+
+#
+# Construct expanded Vlc (variable length code) tables
+# from vlc description files.
+#
+
+sys: Sys;
+bufio: Bufio;
+Iobuf: import bufio;
+
+stderr: ref Sys->FD;
+
+sv: adt
+{
+ s: int;
+ v: string;
+};
+
+s2list: type list of (string, string);
+bits, size: int;
+table: array of sv;
+prog: string;
+undef: string = "UNDEF";
+xfixed: int = 0;
+complete: int = 0;
+paren: int = 0;
+
+Vlc: module
+{
+ init: fn(nil: ref Draw->Context, args: list of string);
+};
+
+init(nil: ref Draw->Context, args: list of string)
+{
+ sys = load Sys Sys->PATH;
+ stderr = sys->fildes(2);
+ sargs := makestr(args);
+ prog = hd args;
+ args = tl args;
+ bufio = load Bufio Bufio->PATH;
+ if (bufio == nil) {
+ sys->fprint(stderr, "%s: could not load %s: %r\n", prog, Bufio->PATH);
+ return;
+ }
+ inf := bufio->fopen(sys->fildes(0), Bufio->OREAD);
+ if (inf == nil) {
+ sys->fprint(stderr, "%s: fopen stdin failed: %r\n", prog);
+ return;
+ }
+ while (args != nil && len hd args && (a := hd args)[0] == '-') {
+ flag:
+ for (x := 1; x < len a; x++) {
+ case a[x] {
+ 'c' =>
+ complete = 1;
+ 'f' =>
+ xfixed = 1;
+ 'p' =>
+ paren = 1;
+ 'u' =>
+ if (++x == len a) {
+ args = tl args;
+ if (args == nil)
+ usage();
+ undef = hd args;
+ } else
+ undef = a[x:];
+ break flag;
+ * =>
+ usage();
+ return;
+ }
+ }
+ args = tl args;
+ }
+ vlc := "vlc";
+ if (args != nil) {
+ if (tl args != nil) {
+ usage();
+ return;
+ }
+ vlc = hd args;
+ }
+ il: s2list;
+ while ((l := inf.gets('\n')) != nil) {
+ if (l[0] == '#')
+ continue;
+ (n, t) := sys->tokenize(l, " \t\n");
+ if (n != 2) {
+ sys->fprint(stderr, "%s: bad input: %s", prog, l);
+ return;
+ }
+ il = (hd t, hd tl t) :: il;
+ }
+ (n, nl) := expand(il);
+ bits = n;
+ size = 1 << bits;
+ table = array[size] of sv;
+ maketable(nl);
+ printtable(vlc, sargs);
+}
+
+usage()
+{
+ sys->fprint(stderr, "usage: %s [-cfp] [-u undef] [stem]\n", prog);
+}
+
+makestr(l: list of string): string
+{
+ s, t: string;
+ while (l != nil) {
+ s = s + t + hd l;
+ t = " ";
+ l = tl l;
+ }
+ return s;
+}
+
+expand(l: s2list): (int, s2list)
+{
+ nl: s2list;
+ max := 0;
+ while (l != nil) {
+ (bs, val) := hd l;
+ n := len bs;
+ if (n > max)
+ max = n;
+ if (bs[n - 1] == 's') {
+ t := bs[:n - 1];
+ nl = (t + "0", val) :: (t + "1", "-" + val) :: nl;
+ } else
+ nl = (bs, val) :: nl;
+ l = tl l;
+ }
+ return (max, nl);
+}
+
+maketable(l: s2list)
+{
+ while (l != nil) {
+ (bs, val) := hd l;
+ z := len bs;
+ if (xfixed && z != bits)
+ error(sys->sprint("string %s too short", bs));
+ s := bits - z;
+ v := value(bs) << s;
+ n := 1 << s;
+ for (i := 0; i < n; i++) {
+ if (table[v].v != nil)
+ error(sys->sprint("repeat match for %x", v));
+ table[v] = (z, val);
+ v++;
+ }
+ l = tl l;
+ }
+}
+
+value(s: string): int
+{
+ n := len s;
+ v := 0;
+ for (i := 0; i < n; i++) {
+ case s[i] {
+ '0' =>
+ v <<= 1;
+ '1'=>
+ v = (v << 1) | 1;
+ * =>
+ error("bad bitstream: " + s);
+ }
+ }
+ return v;
+}
+
+printtable(s, a: string)
+{
+ sys->print("# %s\n", a);
+ sys->print("%s_size: con %d;\n", s, size);
+ sys->print("%s_bits: con %d;\n", s, bits);
+ sys->print("%s_table:= array[] of {\n", s);
+ for (i := 0; i < size; i++) {
+ if (table[i].v != nil) {
+ if (xfixed) {
+ if (paren)
+ sys->print("\t(%s),\n", table[i].v);
+ else
+ sys->print("\t%s,\n", table[i].v);
+ } else
+ sys->print("\t(%d, %s),\n", table[i].s, table[i].v);
+ } else if (!complete) {
+ if (xfixed) {
+ if (paren)
+ sys->print("\t(%s),\n", undef);
+ else
+ sys->print("\t%s,\n", undef);
+ } else
+ sys->print("\t(0, %s),\n", undef);
+ } else
+ error(sys->sprint("no match for %x", i));
+ }
+ sys->print("};\n");
+}
+
+error(s: string)
+{
+ sys->fprint(stderr, "%s: error: %s\n", prog, s);
+ exit;
+}