ref: b574ea6ce2f6fb2aa129da26687d4affeb1faabc
dir: /misc.c/
#include <u.h>
#include <libc.h>
#include <thread.h>
#include "pdf.h"
enum {
Us,
Them,
};
typedef struct Exec Exec;
struct Exec {
char *file;
char **argv;
int p[2];
Channel *pid;
};
static char *otypes[] = {
[Obool] = "bool",
[Onum] = "num",
[Ostr] = "str",
[Oname] = "name",
[Oarray] = "array",
[Odict] = "dict",
[Ostream] = "stream",
[Onull] = "null",
[Oindir] = "indir",
};
Object null = {
.type = Onull,
};
int
Ofmt(Fmt *f)
{
Object *o;
int i;
o = va_arg(f->args, Object*);
if(o == nil || o == &null)
return fmtprint(f, "null");
switch(o->type){
case Obool:
return fmtprint(f, o->bool ? "true" : "false");
case Onum:
return fmtprint(f, "%g", o->num.d);
case Ostr:
case Oop:
if(isutf8(o->str, o->len))
return fmtprint(f, "%q", o->str);
return fmtprint(f, "<%.*H>", o->len, o->str);
case Oname:
return fmtprint(f, "/%s", o->name);
case Oarray:
fmtprint(f, "[");
for(i = 0; i < o->array.ne; i++)
fmtprint(f, "%s%O", i > 0 ? ", " : "", o->array.e[i]);
return fmtprint(f, "]");
case Ostream: /* FIXME dump the stream? */
case Odict:
fmtprint(f, "<<");
for(i = 0; i < o->dict.nkv; i++)
fmtprint(f, "%s%s = %O", i > 0 ? ", " : "", o->dict.kv[i].key, o->dict.kv[i].value);
return fmtprint(f, ">>%s", o->type == Ostream ? "+stream" : "");
case Onull:
return fmtprint(f, "null");
case Oindir:
return fmtprint(f, "@%d[gen=%d]", o->indir.id, o->indir.gen);
}
return fmtprint(f, "???");
}
int
Tfmt(Fmt *f)
{
Object *o;
o = va_arg(f->args, Object*);
if(o == nil || o == &null)
return fmtprint(f, "null");
if(o->type < 0 || o->type >= nelem(otypes))
return fmtprint(f, "????");
return fmtprint(f, "%s", otypes[o->type]);
}
int
⊗fmt(Fmt *f)
{
Xref x;
x = va_arg(f->args, Xref);
if(x.objstm > 0)
return fmtprint(f, "<compressed id=%d objstm=%d index=%d>", x.id, x.objstm, x.index);
return fmtprint(f, "<uncompressed id=%d off=%d gen=%d>", x.id, x.off, x.gen);
}
int
isws(int c)
{
return /* \0 is missing on purpose */
c == '\t' || c == '\n' || c == '\f' || c == '\r' ||
c == ' ';
}
int
isdelim(int c)
{
return
c == '(' || c == ')' || c == '<' || c == '>' ||
c == '[' || c == ']' || c == '{' || c == '}' ||
c == '/' || c == '%';
}
int
isutf8(char *s, int len)
{
int i, n;
Rune r;
for(i = 0; i < len; i += n, s += n){
if((n = chartorune(&r, s)) < 1 || r == Runeerror)
break;
}
return i >= len;
}
static void
pexec(void *args)
{
Exec *e = args;
if(e->p[0] >= 0){
dup(e->p[Them], 0);
dup(e->p[Them], 1);
close(e->p[0]);
close(e->p[1]);
}else{
close(0);
close(1);
}
procexec(e->pid, e->file, e->argv);
}
int
pipeexec(int *fd, char *file, char **argv)
{
int pid;
Exec e;
e.file = file;
e.argv = argv;
e.pid = chancreate(sizeof(int), 0);
e.p[0] = e.p[1] = -1;
if(fd != nil){
pipe(e.p);
*fd = e.p[Us];
}
procrfork(pexec, &e, 4096, RFFDG);
recv(e.pid, &pid);
chanfree(e.pid);
if(fd != nil){
close(e.p[Them]);
if(pid < 0)
close(e.p[Us]);
}
return pid;
}