A => sky/WIP +0 -0
A => sky/cmd/cmd.c +157 -0
@@ 0,0 1,157 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <bio.h>
+
+#include "debug.h"
+#include "lex.h"
+
+#include "dat.h"
+#include "fns.h"
+
+struct Cmdnode *mknode(void);
+int eqsig(Cmd *c1, Cmd *c2);
+int (*(getfun)(struct Cmdnode*, Cmd*))(Tok*, int);
+
+Cmdctxt*
+mkcmdctxt(int fd)
+{
+ Cmdctxt *ctxt;
+ if((ctxt=malloc(sizeof(Cmdctxt)))==nil)
+ return nil;
+ ctxt->fd = fd;
+ if((ctxt->head=mknode())==nil){
+ free(ctxt);
+ return nil;
+ }
+
+ return ctxt;
+}
+
+
+int
+cmdreg(Cmdctxt *ctxt, Cmd *c)
+{
+ struct Cmdnode *head;
+ head = ctxt->head;
+
+ /* the tail node is always pre-allocated but unset */
+ while(head->next){
+ if(eqsig(c, head->c)){
+ head->c->fun = c->fun;
+ return 0;
+ }
+ head=head->next;
+ }
+
+ if((head->next=mknode())==nil)
+ return Loverflow;
+
+ *(head->c) = *c;
+
+ return 0;
+}
+
+void
+cmdterm(Cmdctxt *ctxt)
+{
+ struct Cmdnode *head, *nxt;
+ head = ctxt->head;
+
+ while(head){
+ nxt = head->next;
+ free(head->c);
+ free(head);
+ head = nxt;
+ }
+}
+
+void
+cmdproc(void *ctxt)
+{
+ struct Cmdnode *head;
+ int fd;
+ Lexer l;
+ Tok t, argv[Cmaxargs];
+ Cmd c;
+ int (*efun)(Tok*, int);
+ char *err;
+
+ head = ((Cmdctxt*)ctxt)->head;
+ fd = ((Cmdctxt*)ctxt)->fd;
+ memset(&c, 0, sizeof(Cmd));
+
+ linit(&l, fd, lexstart());
+
+ while(t = lnexttok(&l), t.typ != Teof){
+ DBPRINT(10, "tok: %d(%S)\n", t.typ, t.str);
+ switch(t.typ){
+ case Terror:
+ err = "parse error";
+error: fprint(2, "%s in cmd %S (last token: %S)\n", err, *c.str ? c.str : L"nil", t.str);
+ memset(&c, 0, sizeof(Cmd));
+ break;
+ case Tcmd:
+ runestrncpy(c.str, t.str, Ltoksize+1);
+ break;
+ case Teos:
+ if((efun = getfun(head, &c)) == nil){
+ err = "unrecognised function signature";
+ goto error;
+ }
+ if((*efun)(argv, c.argc) < 0){
+ err = "invalid data";
+ goto error;
+ }
+ memset(&c, 0, sizeof(Cmd));
+ break;
+ case Tidentifier:
+ case Tdecimal:
+ case Tstr:
+ c.argtyp[c.argc] = t.typ;
+ argv[c.argc++] = t;
+ break;
+ break;
+ }
+ }
+}
+
+struct Cmdnode*
+mknode(void)
+{
+ struct Cmdnode *h;
+ if((h=malloc(sizeof(struct Cmdnode)))==nil)
+ return nil;
+ memset(h, 0, sizeof(struct Cmdnode));
+ if((h->c=malloc(sizeof(Cmd)))==nil){
+ free(h);
+ return nil;
+ }
+ memset(h->c, 0, sizeof(Cmd));
+
+ return h;
+}
+
+int
+eqsig(Cmd *c1, Cmd *c2)
+{
+ int i, *a1, *a2;
+
+ if(!c1 || !c2) return 0;
+ if(runestrncmp(c1->str, c2->str, Ltoksize+1) || c1->argc != c2->argc) return 0;
+ for(i=0, a1=c1->argtyp, a2=c2->argtyp; i<c1->argc; i++)
+ if(*a1++ != *a2++) return 0;
+
+ return 1;
+}
+
+int (*(getfun)(struct Cmdnode *h, Cmd *c))(Tok*, int)
+{
+ /* last node is always unset */
+ while(h->next){
+ if(eqsig(c, h->c)) return h->c->fun;
+ h = h->next;
+ }
+
+ return nil;
+}
A => sky/cmd/dat.h +40 -0
@@ 0,0 1,40 @@
+typedef struct Cmd Cmd;
+typedef struct Cmdctxt Cmdctxt;
+
+enum
+{
+ Teof = Leof,
+ Terror = -10,
+ Tcomment = 0,
+ Tcmd,
+ Teos,
+ Tidentifier,
+ Tdecimal,
+ Tstr,
+};
+
+enum
+{
+ Cmaxargs = 32,
+ Coverflow = -10,
+};
+
+struct Cmd
+{
+ Rune str[Ltoksize+1];
+ int argc, argtyp[Cmaxargs];
+ int (*fun)(Tok*, int);
+};
+
+struct Cmdnode
+{
+ Cmd *c;
+ struct Cmdnode *next;
+};
+
+struct Cmdctxt
+{
+ struct Cmdnode *head;
+ int fd;
+};
+
A => sky/cmd/fns.h +8 -0
@@ 0,0 1,8 @@
+/* lex.c */
+State lexstart(void);
+
+/* cmd.c */
+Cmdctxt *mkcmdctxt(int fd);
+int cmdreg(Cmdctxt *ctxt, Cmd *c);
+void cmdproc(void *ctxt);
+void cmdterm(Cmdctxt *ctxt);
No newline at end of file
A => sky/cmd/lex.c +255 -0
@@ 0,0 1,255 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <bio.h>
+
+#include "debug.h"
+#include "lex.h"
+
+#include "dat.h"
+#include "fns.h"
+
+State seof(Lexer *l, void *aux);
+State serror(Lexer *l, void *aux);
+State scmd(Lexer *l, void *aux);
+State scomment(Lexer *l, void *aux);
+State sswtch(Lexer *l, void *aux);
+State seos(Lexer *l, void *aux);
+State sidentifier(Lexer *l, void *aux);
+State sdecimal(Lexer *l, void *aux);
+State sstr(Lexer *l, void *aux);
+
+State
+lexstart(void)
+{
+ State nxt;
+
+ nxt.fun = &scmd;
+ return nxt;
+}
+
+State
+seof(Lexer *l, void *aux)
+{
+ State nxt;
+
+ lemit(l, Teof);
+
+ nxt.fun = &seof;
+ return nxt;
+}
+
+State
+serror(Lexer *l, void *aux)
+{
+ State nxt;
+
+ if(lpeek(l) == Leof){
+ nxt.fun = &seof;
+ return nxt;
+ }
+
+ lemit(l, Terror);
+
+ nxt.fun = &scmd;
+ return nxt;
+}
+
+State
+scmd(Lexer *l, void *aux)
+{
+ State nxt;
+ Rune *s;
+ long len;
+
+ lacceptrun(l, L" \t\n");
+ lignore(l);
+
+ if(laccept(l, L";")){
+ lbackup(l);
+ nxt.fun = &seos;
+ return nxt;
+ }
+
+ lacceptuntil(l, L" \t\n");
+
+ if((len = llen(l)) < 0){
+ nxt.fun = &serror;
+ nxt.aux = "cmd";
+ return nxt;
+ }else if(len == 0){
+ nxt.fun = &scmd;
+ return nxt;
+ }
+
+ if(*l->b == L'#')
+ nxt.fun = &scomment;
+ else{
+ lemit(l, Tcmd);
+ nxt.fun = &sswtch;
+ }
+
+ return nxt;
+}
+
+State
+scomment(Lexer *l, void *aux)
+{
+ State nxt;
+
+ if(lacceptuntil(l, L"\n") < 0){
+ nxt.fun = &serror;
+ nxt.aux = "comment";
+ return nxt;
+ }
+ laccept(l, L"\n");
+ lignore(l);
+
+ nxt.fun = &scmd;
+ return nxt;
+}
+
+State
+sswtch(Lexer *l, void *aux)
+{
+ State nxt;
+
+ lacceptrun(l, L" \t\n");
+ lignore(l);
+
+ switch(lpeek(l)){
+ case L';':
+ nxt.fun = &seos;
+ return nxt;
+ case L'#':
+ nxt.fun = &scomment;
+ return nxt;
+ case L'"':
+ nxt.fun = &sstr;
+ return nxt;
+ }
+
+ if(laccept(l, L"0123456789-+.")){
+ lbackup(l);
+ nxt.fun = &sdecimal;
+ return nxt;
+ }
+
+ if(laccept(l, L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_")){
+ lbackup(l);
+ nxt.fun = &sidentifier;
+ return nxt;
+ }
+
+ nxt.fun = &serror;
+ nxt.aux = "sswtch";
+ return nxt;
+}
+
+State
+seos(Lexer *l, void *aux)
+{
+ State nxt;
+
+ lacceptrun(l, L" \t\n");
+ lignore(l);
+
+ if(!laccept(l, L";")){
+ nxt.fun = &serror;
+ nxt.aux = "eos";
+ return nxt;
+ }
+
+ lemit(l, Teos);
+
+ nxt.fun = &scmd;
+ return nxt;
+}
+
+State
+sidentifier(Lexer *l, void *aux)
+{
+ State nxt;
+
+ lacceptrun(l, L" \t\n");
+ lignore(l);
+
+ if(!laccept(l, L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_")){
+ nxt.fun = &serror;
+ nxt.aux = "identifier";
+ return nxt;
+ }
+
+ if(lacceptrun(l, L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_.0123456789") < 0){
+ nxt.fun = &serror;
+ nxt.aux = "identifier";
+ return nxt;
+ }
+
+ lemit(l, Tidentifier);
+
+ nxt.fun = &sswtch;
+ return nxt;
+}
+
+State
+sdecimal(Lexer *l, void *aux)
+{
+ State nxt;
+
+ lacceptrun(l, L" \t\n");
+ lignore(l);
+
+ if(!laccept(l, L"0123456789.+-")){
+ nxt.fun = &serror;
+ nxt.aux = "decimal";
+ return nxt;
+ }
+ lbackup(l);
+
+ laccept(l, L"+-");
+ lacceptrun(l, L"0123456789");
+ laccept(l, L".");
+ lacceptrun(l, L"0123456789");
+ laccept(l, L"eE");
+ laccept(l, L"+-");
+ if(lacceptrun(l, L"0123456789") < 0){
+ nxt.fun = &serror;
+ nxt.aux = "decimal";
+ return nxt;
+ }
+
+ lemit(l, Tdecimal);
+
+ nxt.fun = &sswtch;
+ return nxt;
+}
+
+State
+sstr(Lexer *l, void *aux)
+{
+ State nxt;
+
+ lacceptrun(l, L" \t\n");
+ lignore(l);
+
+ if(!laccept(l, L"\"")){
+ nxt.fun = &serror;
+ nxt.aux = "str";
+ return nxt;
+ }
+ lignore(l);
+
+ if(lacceptuntil(l, L"\"") < 0){
+ nxt.fun = &serror;
+ nxt.aux = "str";
+ return nxt;
+ }
+
+ lemit(l, Tstr);
+ laccept(l, L"\"");
+
+ nxt.fun = &sswtch;
+ return nxt;
+}
+
A => sky/cmd/mkfile +23 -0
@@ 0,0 1,23 @@
+</$objtype/mkfile
+
+TARG=test_lex test_cmd
+
+INCDIR=../include
+
+CFLAGS=-I$INCDIR
+LIB=../liblex/liblex.a
+
+OFILES=\
+ cmd.$O\
+ lex.$O\
+
+HFILES=\
+ dat.h\
+ fns.h\
+
+UPDATE=\
+ mkfile\
+ $HFILES\
+ ${OFILES:%.$O=%.c}\
+
+</sys/src/cmd/mkmany
A => sky/cmd/test_cmd.c +92 -0
@@ 0,0 1,92 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <bio.h>
+
+#include "lex.h"
+
+#include "dat.h"
+#include "fns.h"
+
+enum
+{
+ STACK = 256*1024,
+};
+
+double
+runeatof(Rune *s)
+{
+ char cs[Ltoksize+1], *c;
+ int i;
+
+ for(i=0, c=cs; i<Ltoksize && *s; i++)
+ *c++ = *s++;
+ *c = '\0';
+
+ return atof(cs);
+}
+
+int
+add(Tok *argv, int argc)
+{
+ int i;
+ double a, sum;
+
+ print("add ");
+ for(i=0, sum=0; i<argc; i++, argv++){
+ print("%S", argv->str);
+ a = runeatof(argv->str);
+ print("(%f) ", a);
+ sum += a;
+ }
+ print("=> %f\n", sum);
+ return 0;
+}
+
+int
+mult(Tok *argv, int argc)
+{
+ int i;
+ double a, prod;
+
+ print("mult ");
+ for(i=0, prod=1; i<argc; i++, argv++){
+ print("%S", argv->str);
+ a = runeatof(argv->str);
+ print("(%f) ", a);
+ prod *= a;
+ }
+ print("=> %f\n", prod);
+ return 0;
+}
+
+void
+threadmain(int argc, char *argv[])
+{
+ Cmdctxt *ctxt;
+ Cmd c;
+
+ if((ctxt = mkcmdctxt(0)) == nil)
+ sysfatal("out of memory!");
+
+ runestrcpy(c.str, L"add");
+ c.argc = 2;
+ c.argtyp[0] = c.argtyp[1] = c.argtyp[2] = Tdecimal;
+ c.fun = &add;
+ cmdreg(ctxt, &c);
+
+ c.argc = 3;
+ cmdreg(ctxt, &c);
+
+ runestrcpy(c.str, L"mult");
+ c.argc = 2;
+ c.fun = &mult;
+ cmdreg(ctxt, &c);
+
+ c.argc = 3;
+ cmdreg(ctxt, &c);
+
+ proccreate(&cmdproc, ctxt, STACK);
+
+ for(;;);
+}
A => sky/cmd/test_lex.c +61 -0
@@ 0,0 1,61 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <bio.h>
+
+#include "lex.h"
+
+#include "dat.h"
+#include "fns.h"
+
+enum
+{
+ STACK = 64*1024,
+};
+
+void
+parseproc(void *arg)
+{
+ Lexer l;
+ Tok t;
+
+ linit(&l, 0, lexstart());
+
+ while(t = lnexttok(&l), t.typ != Teof){
+ print("next: %d > ", t.typ);
+ switch(t.typ){
+ case Teof:
+ print("Teof: ");
+ break;
+ case Terror:
+ print("Terror: ");
+ break;
+ case Tcmd:
+ print("Tcmd: ");
+ break;
+ case Teos:
+ print("Teos: ");
+ break;
+ case Tidentifier:
+ print("Tidentifier: ");
+ break;
+ case Tdecimal:
+ print("Tdecimal: ");
+ break;
+ case Tstr:
+ print("Tstr: ");
+ break;
+ }
+ print("%S\n", t.str);
+ }
+
+ exits(0);
+}
+
+void
+threadmain(int argc, char *argv[])
+{
+ proccreate(&parseproc, nil, STACK);
+
+ for(;;);
+}
A => sky/include/debug.h +6 -0
@@ 0,0 1,6 @@
+#ifndef DEBUG_LEVEL
+#define DEBUG_LEVEL 0
+#endif
+
+#define DBIF(l) if((l)<=DEBUG_LEVEL)
+#define DBPRINT(l, ...) if((l)<=DEBUG_LEVEL) fprint(2, __VA_ARGS__);
M sky/include/lex.h +16 -7
@@ 2,24 2,29 @@ typedef struct State State;
typedef struct Tok Tok;
typedef struct Lexer Lexer;
-enum {
- Ltoksize = 256,
+enum
+{
+ Ltoksize = 512,
Leof = -1,
Loverflow = -10,
};
/* wrapper to simulate recursive function type */
-struct State {
- State (*next)(Lexer *l);
+struct State
+{
+ State (*fun)(Lexer*, void*);
+ void *aux;
};
-struct Tok {
+struct Tok
+{
int typ;
Rune str[Ltoksize+1];
};
-struct Lexer {
+struct Lexer
+{
Biobuf *bp;
Rune b[Ltoksize+1], *cur;
int start, pos;
@@ 36,7 41,11 @@ long lpeek(Lexer *l);
void lignore(Lexer *l);
int laccept(Lexer *l, Rune *s);
-void lacceptrun(Lexer *l, Rune *s);
+long lacceptrun(Lexer *l, Rune *s);
+long lacceptuntil(Lexer *l, Rune *s);
void lemit(Lexer *l, int typ);
Tok lnexttok(Lexer *l);
+
+long llen(Lexer *l);
+Rune *lestr(Lexer *l);
M sky/include/sky.h +17 -11
@@ 1,4 1,4 @@
-/** dat **/
+#pragma lib "libsky.a"
typedef struct Gdloc Gdloc;
typedef struct Eqloc Eqloc;
@@ 10,49 10,57 @@ typedef struct Viewangle Viewangle;
typedef struct Camera Camera;
/* geodetic location */
-struct Gdloc {
+struct Gdloc
+{
double lat; /* in rad */
double lng; /* in rad */
double alt; /* in meters from mean sea level */
};
/* equatorial location */
-struct Eqloc {
+struct Eqloc
+{
double ra; /* right ascension in rad */
double dec; /* declination in rad */
};
/* horizontal location */
-struct Hzloc {
+struct Hzloc
+{
double az; /* azimuth in rad */
double z; /* zenith in rad (complement of elevation) */
};
/* galactic location */
-struct Gxloc {
+struct Gxloc
+{
double b; /* galactic latitude in rad */
double l; /* galactic longitude in rad */
};
/* 2D projection */
-struct Planar {
+struct Planar
+{
double x, y;
};
-struct Obs {
+struct Obs
+{
Gdloc g;
double P; /* pressure in kPa */
double T; /* temperature in K */
double rh; /* relative humidity */
};
-struct Viewangle {
+struct Viewangle
+{
double az; /* azimuth in rad */
double z; /* zenith in rad (complement of elevation) */
double roll; /* roll in rad */
};
-struct Camera {
+struct Camera
+{
double f; /* focal length in mm */
double w, h; /* sensor dimensions in mm */
int wpx, hpx; /* sensor dimensions in pixels */
@@ 77,8 85,6 @@ struct Camera {
#define NTP_K 293.15d
-/** fns **/
-
Eqloc gx2eq00(Gxloc gx);
Gxloc eq2gx00(Eqloc eq);
M sky/liblex/lex.c +60 -6
@@ 3,6 3,8 @@
#include <thread.h>
#include <bio.h>
+#include "debug.h"
+
#include "lex.h"
int
@@ 11,7 13,12 @@ linit(Lexer *l, int fd, State state)
if((l->c=chancreate(sizeof(Tok), 2)) == nil)
return Leof;
- if(Binit(l->bp, fd, OREAD) == Beof) {
+ if((l->bp = malloc(sizeof(Biobuf))) == nil){
+ chanfree(l->c);
+ return Loverflow;
+ }
+ if(Binit(l->bp, fd, OREAD) == Beof){
+ free(l->bp);
chanfree(l->c);
return Leof;
}
@@ 28,6 35,7 @@ lterm(Lexer *l)
{
chanfree(l->c);
Bterm(l->bp);
+ free(l->bp);
}
long
@@ 78,16 86,36 @@ laccept(Lexer *l, Rune *s)
if((c = lnext(l)) < 0) return 0;
- if(runestrchr(s, c) != 0) return 1;
+ if(runestrchr(s, c) != nil) return 1;
lbackup(l);
return 0;
}
-void
+long
lacceptrun(Lexer *l, Rune *s)
{
- while(laccept(l, s));
+ long c;
+ int p, done;
+
+ p = l->pos;
+ while((c = lnext(l)) >= 0 && !(done = !runestrchr(s, c)));
+ if(done) lbackup(l);
+
+ return done ? l->pos-p : Loverflow;
+}
+
+long
+lacceptuntil(Lexer *l, Rune *s)
+{
+ long c;
+ int p, done;
+
+ p = l->pos;
+ while((c = lnext(l)) >= 0 && !(done = !!runestrchr(s, c)));
+ if(done) lbackup(l);
+
+ return done ? l->pos-p : Loverflow;
}
void
@@ 97,7 125,8 @@ lemit(Lexer *l, int typ)
t.typ = typ;
runestrncpy(t.str, l->b, l->pos-l->start);
- t.str[Ltoksize] = 0;
+ t.str[l->pos-l->start] = L'\0';
+ lignore(l);
send(l->c, &t);
}
@@ 107,6 136,31 @@ lnexttok(Lexer *l)
{
Tok t;
- while(!nbrecv(l->c, &t)) l->state = l->state.next(l);
+ while(!nbrecv(l->c, &t)) l->state = l->state.fun(l, l->state.aux);
+
return t;
}
+
+long
+llen(Lexer *l)
+{
+ long len;
+
+ len = l->pos - l->start;
+ return len >= 0 && len < Ltoksize ? len : Loverflow;
+}
+
+Rune*
+lestr(Lexer *l){
+ Rune *s;
+ long len;
+
+ len = llen(l);
+ if(len < 0) return nil;
+ if((s=malloc((len+1)*sizeof(Rune))) == nil) return nil;
+
+ runestrncpy(s, l->b, len);
+ s[len] = L'\0';
+
+ return s;
+}
No newline at end of file