ref: 955e17e750cdeef05f22e7fe2be9d04211c705e6
author: Jacob Moody <moody@posixcafe.org>
date: Sat May 13 23:31:52 EDT 2023
init
--- /dev/null
+++ b/dfc.y
@@ -1,0 +1,489 @@
+%{
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <ctype.h>
+
+int goteof;
+int lineno;
+int yyparse(void);
+void yyerror(char*);
+
+enum{
+ Big,
+ Little,
+};
+
+int ordermode = Big;
+
+enum{
+ TCmplx,
+ TNum,
+ TUchar,
+ TU16,
+ TU32,
+ TU64,
+ TVLA,
+};
+
+typedef struct Field Field;
+typedef struct Sym Sym;
+
+struct Sym{
+ char *name;
+ int type;
+ int val;
+ char *from;
+};
+
+struct Field{
+ char *name;
+ int len;
+ Sym sym;
+};
+
+
+Field tobe[128];
+int ntobe;
+
+Sym defs[128];
+int ndef;
+
+static void
+mklower(char *d, char *e, char *s)
+{
+ assert(d <= e-1);
+ for(; *s != 0 && d < e-1; s++){
+ if(!isascii(*s))
+ continue;
+ *d++ = tolower(*s);
+ }
+ *d = 0;
+}
+
+static char*
+size2type(int x)
+{
+ switch(x){
+ case 1:
+ return "uchar";
+ case 2:
+ return "u16int";
+ case 3: case 4:
+ return "u32int";
+ case 5: case 6: case 7: case 8:
+ return "u64int";
+ default:
+ yyerror("invalid size");
+ return nil;
+ }
+}
+
+static int
+aligned(int x)
+{
+ switch(x){
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static void
+byteprint(void)
+{
+ int x, y;
+ int shift;
+
+ if(ordermode == Big)
+ for(x = 2; x <= 8; x++){
+ print("#define GET%d(p) ", x);
+ for(shift = 0, y = x-1; y >= 0; y--, shift += 8){
+ print("(%s)(p)[%d]", size2type(x), y);
+ if(shift != 0)
+ print("<<%d", shift);
+ if(y != 0)
+ print(" | ");
+ }
+ print("\n");
+ print("#define PUT%d(p, u) ", x);
+ for(shift = 8*(x-1), y = 0; y < x; y++, shift -= 8){
+ print("(p)[%d] = (u)", y);
+ if(shift != 0)
+ print(">>%d, ", shift);
+ }
+ print("\n");
+ }
+
+ if(ordermode == Little)
+ for(x = 2; x <= 8; x++){
+ print("#define GET%d(p) ", x);
+ for(shift = 0, y = 0; y < x; y++, shift += 8){
+ print("(%s)(p)[%d]", size2type(x), y);
+ if(shift != 0)
+ print("<<%d", shift);
+ if(y != x-1)
+ print(" | ");
+ }
+ print("\n");
+ print("#define PUT%d(p, u) ", x);
+ for(shift = 8*(x-1), y = x - 1; y >= 0; y--, shift -= 8){
+ print("(p)[%d] = (u)", y);
+ if(shift != 0)
+ print(">>%d, ", shift);
+ }
+ print("\n");
+ }
+ print("\n");
+}
+
+static void
+cprint(char *name)
+{
+ int i;
+ char buf[128];
+
+/*
+ print("typedef struct %s %s;\n", name, name);
+ print("struct %s{\n", name);
+ for(i = 0; i < ntobe; i++){
+ if(tobe[i].sym.type == TCmplx){
+ print("\t%s %s;\n", tobe[i].sym.name, tobe[i].name);
+ continue;
+ }
+ if(tobe[i].len == 0)
+ print("\tuchar *%s;\n", tobe[i].name);
+ else if(aligned(tobe[i].len))
+ print("\t%s %s;\n", size2type(tobe[i].len), tobe[i].name);
+ else
+ print("\tuchar %s[%d];\n", tobe[i].name, tobe[i].len);
+ }
+ print("};\n\n");
+*/
+
+ mklower(buf, buf + sizeof buf - 1, name);
+ print("long\nget%s(%s *ret, uchar *data)\n{\n\tlong n;\n\n\tn = 0;\n", buf, name);
+ for(i = 0; i < ntobe; i++){
+ switch(tobe[i].sym.type){
+ case TCmplx:
+ mklower(buf, buf + sizeof buf - 1, tobe[i].sym.name);
+ print("\tn += get%s(&ret->%s, data+n);\n", buf, tobe[i].name);
+ continue;
+ case TVLA:
+ print("\tret->%s = data+n;\n", tobe[i].name);
+ print("\tn += ret->%s;\n", tobe[i].sym.from);
+ continue;
+ }
+ if(tobe[i].len == 1)
+ print("\tret->%s = data[n];\n", tobe[i].name);
+ else if(aligned(tobe[i].len))
+ print("\tret->%s = GET%d(data+n);\n", tobe[i].name, tobe[i].len);
+ else
+ print("\tmemcpy(ret->%s, data+n, %d);\n", tobe[i].name, tobe[i].len);
+ print("\tn += %d;\n", tobe[i].len);
+ }
+ print("\treturn n;\n}\n\n");
+
+ mklower(buf, buf + sizeof buf - 1, name);
+ print("long\nput%s(uchar *dst, %s *src)\n{\n\tlong n;\n\n\tn = 0;\n", buf, name);
+ for(i = 0; i < ntobe; i++){
+ switch(tobe[i].sym.type){
+ case TCmplx:
+ mklower(buf, buf + sizeof buf - 1, tobe[i].sym.name);
+ print("\tn += put%s(dst+n, &src->%s);\n", buf, tobe[i].name);
+ continue;
+ case TVLA:
+ print("\tmemmove(dst+n, src->%s, src->%s);\n", tobe[i].name, tobe[i].sym.from);
+ print("\tn += src->%s;\n", tobe[i].sym.from);
+ continue;
+ }
+ if(tobe[i].len == 1)
+ print("\tdst[n] = src->%s;\n", tobe[i].name);
+ else if(aligned(tobe[i].len))
+ print("\tPUT%d(dst+n, src->%s);\n", tobe[i].len, tobe[i].name);
+ else
+ print("\tmemcpy(dst+n, src->%s, %d);\n", tobe[i].name, tobe[i].len);
+ print("\tn += %d;\n", tobe[i].len);
+ }
+ print("\treturn n;\n}\n\n");
+}
+
+%}
+
+%union
+{
+ char *sval;
+ long ival;
+ Sym yval;
+}
+
+%type <sval> name
+%type <ival> num
+%type <yval> type
+
+%left '{' '}' '[' ']' ';' '=' '(' ')' '.'
+
+%token STRUCT TYPEDEF UCHAR U16 U32 U64
+%token <sval> NAME NUM CHAR
+%token <ival> VAR CMPLX
+
+%%
+
+prog:
+ prog top
+| top
+|
+
+name:
+ NAME
+ {
+ $$ = $1;
+ }
+
+num:
+ NUM
+ {
+ $$ = atoi($1);
+ }
+| VAR
+ {
+ $$ = defs[$1].val;
+ }
+
+type:
+ UCHAR
+ {
+ $$.type = TUchar;
+ $$.val = 1;
+ }
+| U16
+ {
+ $$.type = TU16;
+ $$.val = 2;
+ }
+| U32
+ {
+ $$.type = TU32;
+ $$.val = 4;
+ }
+| U64
+ {
+ $$.type = TU64;
+ $$.val = 8;
+ }
+| CMPLX
+ {
+ $$ = defs[$1];
+ }
+
+sem:
+ sem ';'
+| ';'
+
+top:
+ TYPEDEF STRUCT name name sem
+| STRUCT name '{' members '}' sem
+ {
+ cprint($2);
+ defs[ndef].name = $2;
+ defs[ndef].type = TCmplx;
+ defs[ndef].val = -1;
+ ntobe = 0;
+ ndef++;
+ }
+| name '=' num sem
+ {
+ defs[ndef].name = $1;
+ defs[ndef].type = TNum;
+ defs[ndef].val = $3;
+ ndef++;
+ }
+
+members:
+ members member
+| member
+
+member:
+ type name sem
+ {
+ tobe[ntobe].name = $2;
+ tobe[ntobe].len = $1.val;
+ tobe[ntobe].sym = $1;
+ ntobe++;
+ }
+| type name '[' num ']' sem
+ {
+ tobe[ntobe].name = $2;
+ tobe[ntobe].len = $4;
+ tobe[ntobe].sym = $1;
+ ntobe++;
+ }
+| type name '[' '.' name ']' sem
+ {
+
+ tobe[ntobe].name = $2;
+ tobe[ntobe].len = 0;
+ $1.type = TVLA;
+ $1.from = $5;
+ tobe[ntobe].sym = $1;
+ ntobe++;
+ }
+
+%%
+
+Biobuf *bin;
+
+int
+getch(void)
+{
+ int c;
+
+ c = Bgetc(bin);
+ if(c == Beof){
+ goteof = 1;
+ return -1;
+ }
+ if(c == '\n')
+ lineno++;
+ return c;
+}
+
+void
+ungetc(void)
+{
+ Bungetc(bin);
+}
+
+void
+yyerror(char *s)
+{
+ fprint(2, "%d: %s\n", lineno, s);
+ exits(s);
+}
+
+int
+yylex(void)
+{
+ static char buf[200];
+ char *p;
+ int c;
+ int i;
+
+Loop:
+ c = getch();
+ switch(c){
+ case -1:
+ return -1;
+ case ' ':
+ case '\t':
+ case '\n':
+ goto Loop;
+ case '/':
+ if(getch() != '*'){
+ ungetc();
+ goto Loop;
+ }
+More:
+ while((c = getch()) > 0)
+ if(c == '*')
+ break;
+ if(c != '*')
+ goto Loop;
+ if(getch() == '/')
+ goto Loop;
+ goto More;
+ case '#':
+ while((c = getch()) > 0)
+ if(c == '\n')
+ break;
+ goto Loop;
+ }
+
+ switch(c){
+ case ';': case '=':
+ case '{': case '}':
+ case '[': case ']':
+ case '(': case ')':
+ case '.':
+ return c;
+ }
+
+ ungetc();
+ p = buf;
+ for(;;){
+ c = getch();
+ if((c >= Runeself)
+ || (c == '_')
+ || (c == ':')
+ || (c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z')
+ || (c >= '0' && c <= '9')){
+ *p++ = c;
+ continue;
+ }
+ ungetc();
+ break;
+ }
+ *p = '\0';
+
+ if(strcmp(buf, "struct") == 0)
+ return STRUCT;
+ if(strcmp(buf, "typedef") == 0)
+ return TYPEDEF;
+ if(strcmp(buf, "uchar") == 0)
+ return UCHAR;
+ if(strcmp(buf, "u16int") == 0)
+ return U16;
+ if(strcmp(buf, "u32int") == 0)
+ return U32;
+ if(strcmp(buf, "u64int") == 0)
+ return U64;
+
+ for(i = 0; i < ndef; i++){
+ if(strcmp(buf, defs[i].name) != 0)
+ continue;
+ yylval.ival = i;
+ return defs[i].type == TNum ? VAR : CMPLX;
+ }
+
+ yylval.sval = strdup(buf);
+ return (buf[0] >= '0' && buf[0] <= '9') ? NUM : NAME;
+}
+
+void
+usage(void)
+{
+ fprint(2, "usage: %s [-lb] dat.h\n", argv0);
+ exits("usage");
+}
+
+void
+main(int argc, char **argv)
+{
+ ARGBEGIN{
+ case 'l':
+ ordermode = Little;
+ break;
+ case 'b':
+ ordermode = Big;
+ break;
+ default:
+ usage();
+ break;
+ }ARGEND;
+ if(argc != 1)
+ usage();
+ bin = Bopen(argv[0], OREAD);
+ goteof = 0;
+ print("#include <u.h>\n#include <libc.h>\n#include \"%s\"\n\n", argv[0]);
+ byteprint();
+ while(!goteof)
+ yyparse();
+ Bterm(bin);
+ exits(nil);
+}
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,11 @@
+</$objtype/mkfile
+
+BIN=$home/bin/$objtype
+TARG=dfc
+OFILES=\
+ y.tab.$O\
+
+YFILES=\
+ dfc.y\
+
+</sys/src/cmd/mkone