]> git.lizzy.rs Git - plan9front.git/blob - sys/src/games/linden.c
devcons: fix permissions for reboot and sysstat
[plan9front.git] / sys / src / games / linden.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <ctype.h>
5
6 Biobuf *Bin;
7
8 typedef struct Symbol Symbol;
9 typedef struct SString SString;
10
11 enum { TSTRING = -2 };
12
13 struct Symbol {
14         Rune name;
15         SString *rule;
16         char *output;
17         Symbol *next;
18 };
19
20 struct SString {
21         int n;
22         Symbol **d;
23 };
24 #pragma varargck type "σ" SString*
25
26 Symbol *syms;
27 SString *sstring;
28 char strbuf[1024];
29
30 void *
31 emalloc(ulong n)
32 {
33         void *v;
34         
35         v = malloc(n);
36         if(v == nil) sysfatal("malloc: %r");
37         memset(v, 0, n);
38         setmalloctag(v, getcallerpc(&n));
39         return v;
40 }
41
42 void
43 sstringaddsym(SString *a, Symbol *b)
44 {
45         a->d = realloc(a->d, (a->n + 1) * sizeof(Symbol *));
46         a->d[a->n++] = b;
47 }
48
49 void
50 sstringappend(SString *a, SString *b)
51 {
52         a->d = realloc(a->d, (a->n + b->n) * sizeof(Symbol *));
53         memcpy(a->d + a->n, b->d, b->n * sizeof(Symbol *));
54         a->n += b->n;
55 }
56
57 Symbol *
58 getsym(Rune name)
59 {
60         Symbol **sp;
61         
62         for(sp = &syms; *sp != nil; sp = &(*sp)->next)
63                 if(name == (*sp)->name)
64                         return *sp;
65         *sp = emalloc(sizeof(Symbol));
66         (*sp)->name = name;
67         return *sp;
68 }
69
70 int peektok = -1;
71
72 int
73 lex(void)
74 {
75         int c;
76         char *p;
77         
78         if(peektok >= 0){
79                 c = peektok;
80                 peektok = -1;
81                 return c;
82         }
83         do
84                 c = Bgetrune(Bin);
85         while(c >= 0 && c < 0x80 && isspace(c) && c != '\n');
86         if(c == '\''){
87                 p = strbuf;
88                 for(;;){
89                         c = Bgetc(Bin);
90                         if(c == '\'') break;
91                         if(p < strbuf + sizeof(strbuf) - 1)
92                                 *p++ = c;
93                 }
94                 *p = 0;
95                 return TSTRING;
96         }
97         return c;
98 }
99
100 int
101 peek(void)
102 {
103         if(peektok >= 0) return peektok;
104         return peektok = lex();
105 }
106
107 SString *
108 symstring(void)
109 {
110         int c;
111         SString *r;
112         
113         r = emalloc(sizeof(SString));
114         for(;;){
115                 c = peek();
116                 if(c == '\n' || c == ':')
117                         break;
118                 lex();
119                 r->d = realloc(r->d, (r->n + 1) * sizeof(Symbol *));
120                 r->d[r->n++] = getsym(c);
121         }
122         return r;
123 }
124
125 int
126 fmtsstring(Fmt *f)
127 {
128         SString *s;
129         int i;
130         
131         s = va_arg(f->args, SString *);
132         for(i = 0; i < s->n; i++)
133                 fmtprint(f, "%C", s->d[i]->name);
134         return 0;
135 }
136
137 void
138 syntax(void)
139 {
140         sysfatal("syntax error");
141 }
142
143 void
144 parse(void)
145 {
146         Symbol *s;
147         int c;
148
149         sstring = symstring();
150         while(peek() > 0){
151                 if(peek() == '\n') {lex(); continue;}
152                 if(peek() == ':') syntax();
153                 s = getsym(lex());
154                 c = lex();
155                 if(c == ':')
156                         s->rule = symstring();
157                 else if(c == '='){
158                         if(lex() != TSTRING) syntax();
159                         s->output = strdup(strbuf);
160                 }else
161                         syntax();
162                 c = lex();
163                 if(c != -1 && c != '\n') syntax();
164         }
165 }
166
167 SString *
168 iterate(SString *in)
169 {
170         SString *r;
171         int i;
172         
173         r = emalloc(sizeof(SString));
174         for(i = 0; i < in->n; i++)
175                 if(in->d[i]->rule == nil)
176                         sstringaddsym(r, in->d[i]);
177                 else
178                         sstringappend(r, in->d[i]->rule);
179         return r;
180 }
181
182 void
183 main()
184 {
185         int i, j;
186
187         fmtinstall(L'σ', fmtsstring);
188         Bin = Bfdopen(0, OREAD);
189         if(Bin == nil) sysfatal("Bfdopen: %r");
190         parse();
191         for(j = 0; j < 9; j++){
192                 for(i = 0; i < sstring->n; i++)
193                         if(sstring->d[i]->output != nil)
194                                 print("%s\n", sstring->d[i]->output);
195                 print("end\n");
196                 sstring = iterate(sstring);
197         }
198 }