fix types for ARM support; fix errno handling; minor fixes; license GPL3 or later fix
[guish.git] / src / exec.c
blobb5ef48390de88f0af7b71be20df589684dff9f2d
1 /*************************************************************************
2 * Copyright (C) 2023 Francesco Palumbo <phranz@subfc.net>, Naples (Italy)
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 *************************************************************************/
19 #include <errno.h>
21 #include "exec.h"
22 #include "widgets.h"
23 #include "dectypes.h"
24 #include "tokenizer.h"
25 #include "sourcedriver.h"
26 #include "syntax.h"
27 #include "evaluator.h"
28 #include "debug.h"
30 extern vec_strline_t* strace;
31 extern unsigned long flags;
32 extern unsigned long options;
33 extern widget_t* it;
34 extern map_widwidget_t* widgets;
36 extern map_widloci_t* widlines;
37 extern map_widloci_t* widareas;
38 extern map_widarcssets_t* widarcssets;
39 extern map_widarcssets_t* widarcsareas;
40 extern map_widloci_t* widloci;
41 extern map_widloci_t* widpixels;
42 extern map_widnamedpoints_t* widnamedpoints;
44 static cmd valid_subphrase(element E, cmd c, vec_token_t* v) {
45 if (!it || (E != E_ALL && (element)it->etype != E))
46 return CMD_NONE;
48 return ((int)v->count - (int)(cargs(c))) >= 0 ? c : CMD_NONE;
51 static int load_subject(vec_token_t* v) {
52 showtokens(v);
53 token_t* ft;
54 unsigned long wid;
55 widget_t* w;
56 if (!v->first(v, &ft))
57 return 0;
58 errno = 0;
59 wid = strtoul(ft->data, NULL, 10);
60 if (errno != EINVAL && errno != ERANGE && wid) {
61 if (!widgets->get(widgets, wid, &w))
62 err(ft->source, ft->lineno, "error, unknown window id '%lu'.\n", wid);
63 it = w;
64 debug("subject loaded: %lu\n", it->wid);
65 v->pop_back(v, &ft);
66 release(ft);
67 return 1;
69 return 0;
72 size_t exec(vec_token_t* v) {
73 showtokens(v);
74 cmd c = CMD_NONE;
75 token_t* b = NULL;
76 token_t* o = NULL;
78 if (!v->first(v, &o))
79 return 0;
80 if (o->type == T_BLOCK) {
81 token_t* t;
82 o->block->data->first(o->block->data, &t);
83 err(t->source, t->lineno, "error, cannot execute a block as a command!\n");
86 unsigned long ln = 0;
87 char* sn = NULL;
88 while (v->count) {
89 v->first(v, &o);
90 if (kid(o->data))
91 return v->count;
92 if (load_subject(v))
93 continue;
94 if (!it)
95 err(o->source, o->lineno, "error, no implied subject or unknown command '%s'.\n", o->data);
96 ln = o->lineno;
97 sn = o->source;
98 v->pop_back(v, &o);
99 c = cidbe(it->etype, o->data);
100 debug("cidbe for e: '%d' data: '%s', c: %d\n", it->etype, o->data, c);
101 if (!c)
102 c = cid(o->data);
103 debug("from token '%s', command: %d\n", o->data, c);
105 // generic widget commands
106 switch (c) {
107 case CMD_TRAY:
108 if(!valid_subphrase(E_ALL, c, v))
109 goto badnargs;
110 tray(it);
111 break;
112 case CMD_GHOST:
113 if(!valid_subphrase(E_ALL, c, v))
114 goto badnargs;
115 ghost(it);
116 break;
117 case CMD_FULLSCREEN:
118 if(!valid_subphrase(E_ALL, c, v))
119 goto badnargs;
120 fullscreen(it);
121 break;
122 case CMD_CENTER:
123 if(!valid_subphrase(E_ALL, c, v))
124 goto badnargs;
125 center(it);
126 break;
127 case CMD_SHOW:
128 if(!valid_subphrase(E_ALL, c, v))
129 goto badnargs;
130 show(it);
131 break;
132 case CMD_DRAW: {
133 if (!v->count) {
134 loci_t* l;
135 if (widlines && widlines->get(widlines, it->wid, &l)) {
136 widlines->remove(widlines, it->wid);
137 release(l);
139 arcssets_t* a;
140 if (widarcssets && widarcssets->get(widarcssets, it->wid, &a)) {
141 widarcssets->remove(widarcssets, it->wid);
142 release(a);
144 if (widarcsareas && widarcsareas->get(widarcsareas, it->wid, &a)) {
145 widarcsareas->remove(widarcsareas, it->wid);
146 release(a);
148 if (widareas && widareas->get(widareas, it->wid, &l)) {
149 widareas->remove(widareas, it->wid);
150 release(l);
152 if (widloci && widloci->get(widloci, it->wid, &l)) {
153 widloci->remove(widloci, it->wid);
154 release(l);
156 if (widpixels && widpixels->get(widpixels, it->wid, &l)) {
157 widpixels->remove(widpixels, it->wid);
158 release(l);
160 namedpoints_t* n;
161 if (widnamedpoints && widnamedpoints->get(widnamedpoints, it->wid, &n)) {
162 widnamedpoints->remove(widnamedpoints, it->wid);
163 release(n);
165 it->draw(it);
166 break;
168 char type;
169 v->pop_back(v, &b);
170 assert_notblock(b, "draw operation", o->data);
171 type = *b->data;
172 release(b);
174 switch (type) {
175 case 'l':
176 case 'p':
177 case 'L':
178 case 'P':
179 case 'x': {
180 map_widloci_t** set = NULL;
181 void (*op)(widget_t*, char*, vec_int_t*) = NULL;
182 switch (type) {
183 case 'l': set = &widlines; op = addlines; break;
184 case 'p': set = &widloci; op = addpoints; break;
185 case 'x': set = &widpixels; op = addpixels; break;
186 case 'L':
187 case 'P': set = &widareas; op = addarea; break;
189 if (!v->count) {
190 loci_t* l;
191 if (*set && (*set)->get(*set, it->wid, &l)) {
192 (*set)->remove(*set, it->wid);
193 release(l);
195 it->draw(it);
196 break;
198 token_t* col;
199 if (v->count < 3)
200 goto badnargs;
202 v->pop_back(v, &col);
203 assert_notblock(col, "color", o->data);
205 vec_int_t* ps = alloc(vec_int_t);
206 while (v->count) {
207 v->pop_back(v, &b);
208 assert_notblock(b, "coord", o->data);
209 int x = tolong(b);
210 release(b);
211 if (!v->pop_back(v, &b))
212 err(sn, ln, "error, missing coord.\n");
213 assert_notblock(b, "coord", o->data);
214 int y = tolong(b);
215 release(b);
216 ps->push(ps, x);
217 ps->push(ps, y);
219 op(it, col->data, ps);
220 release(col);
221 release(ps);
222 break;
224 case 'a':
225 case 'A': {
226 if (!v->count) {
227 map_widarcssets_t** set = (c == 'a' ? &widarcssets : &widarcsareas);
228 arcssets_t* a;
229 if (*set && (*set)->get(*set, it->wid, &a)) {
230 (*set)->remove(*set, it->wid);
231 release(a);
233 it->draw(it);
234 break;
236 if (v->count < 7)
237 goto badnargs;
239 token_t* col;
240 v->pop_back(v, &col);
241 assert_notblock(col, "color", o->data);
242 vec_int_t* arcs = alloc(vec_int_t);
243 while (v->count) {
244 if (v->count < 6)
245 goto badnargs;
246 v->pop_back(v, &b);
247 assert_notblock(b, "coord", o->data);
248 int x = tolong(b);
249 release(b);
250 v->pop_back(v, &b);
251 assert_notblock(b, "coord", o->data);
252 int y = tolong(b);
253 release(b);
254 v->pop_back(v, &b);
255 assert_notblock(b, "width", o->data);
256 int ww = tolong(b);
257 release(b);
258 v->pop_back(v, &b);
259 assert_notblock(b, "height", o->data);
260 int hh = tolong(b);
261 release(b);
262 v->pop_back(v, &b);
263 assert_notblock(b, "angle", o->data);
264 int angle1 = tolong(b);
265 release(b);
266 v->pop_back(v, &b);
267 assert_notblock(b, "angle", o->data);
268 int angle2 = tolong(b);
269 release(b);
271 arcs->push(arcs, x);
272 arcs->push(arcs, y);
273 arcs->push(arcs, ww);
274 arcs->push(arcs, hh);
275 arcs->push(arcs, angle1);
276 arcs->push(arcs, angle2);
278 addarcs(it, type == 'A', col->data, arcs);
279 release(arcs);
280 release(col);
281 break;
283 case 'n': {
284 if (!v->count) {
285 namedpoints_t* l;
286 if (widnamedpoints && widnamedpoints->get(widnamedpoints, it->wid, &l)) {
287 widnamedpoints->remove(widnamedpoints, it->wid);
288 release(l);
290 it->draw(it);
291 break;
293 if (v->count < 4)
294 goto badnargs;
296 token_t* col;
297 token_t* name;
298 v->pop_back(v, &col);
299 assert_notblock(col, "color", o->data);
301 v->pop_back(v, &name);
302 assert_notblock(name, "name", o->data);
304 v->pop_back(v, &b);
305 assert_notblock(b, "coord", o->data);
306 int x = tolong(b);
307 release(b);
308 v->pop_back(v, &b);
309 assert_notblock(b, "coord", o->data);
310 int y = tolong(b);
311 release(b);
312 addnamedpoint(it, col->data, name->data, x, y);
313 release(col);
314 release(name);
315 break;
317 default:
318 err(sn, ln, "error, unknown draw operation '%c'.\n", type);
320 break;
322 case CMD_HIDE:
323 if(!valid_subphrase(E_ALL, c, v))
324 goto badnargs;
325 hide(it);
326 break;
327 case CMD_FOCUS:
328 if(!valid_subphrase(E_ALL, c, v))
329 goto badnargs;
330 focus(it);
331 break;
332 case CMD_TOP:
333 if(!valid_subphrase(E_ALL, c, v))
334 goto badnargs;
335 settop(it);
336 break;
337 case CMD_BOTTOM:
338 if(!valid_subphrase(E_ALL, c, v))
339 goto badnargs;
340 setbottom(it);
341 break;
342 case CMD_CLOSE:
343 if(!valid_subphrase(E_ALL, c, v))
344 goto badnargs;
345 wclose(it);
346 break;
347 case CMD_CLICK:
348 if(!valid_subphrase(E_ALL, c, v))
349 goto badnargs;
350 trigger(it->wid, SIG_CLICKED);
351 break;
352 case CMD_LOWER:
353 if(!valid_subphrase(E_ALL, c, v))
354 goto badnargs;
355 lower(it);
356 break;
357 case CMD_RAISE:
358 if(!valid_subphrase(E_ALL, c, v))
359 goto badnargs;
360 wraise(it);
361 break;
362 case CMD_MAXIMIZE:
363 if(!valid_subphrase(E_ALL, c, v))
364 goto badnargs;
365 maximize(it);
366 break;
367 case CMD_FREEZE:
368 if(!valid_subphrase(E_ALL, c, v))
369 goto badnargs;
370 freeze(it);
371 break;
372 case CMD_UNFREEZE:
373 if(!valid_subphrase(E_ALL, c, v))
374 goto badnargs;
375 unfreeze(it);
376 break;
377 case CMD_FIT:
378 if(!valid_subphrase(E_ALL, c, v))
379 goto badnargs;
380 fit(it);
381 break;
382 case CMD_FILL:
383 if(!valid_subphrase(E_ALL, c, v))
384 goto badnargs;
385 fill(it, 0);
386 break;
387 case CMD_FILLNOLIMIT:
388 if(!valid_subphrase(E_ALL, c, v))
389 goto badnargs;
390 fill(it, 1);
391 break;
392 case CMD_FILLRIGHT:
393 if(!valid_subphrase(E_ALL, c, v))
394 goto badnargs;
395 fill_right(it, 0);
396 break;
397 case CMD_FILLRIGHTNOLIMIT:
398 if(!valid_subphrase(E_ALL, c, v))
399 goto badnargs;
400 fill_right(it, 1);
401 break;
402 case CMD_FILLBOTTOM:
403 if(!valid_subphrase(E_ALL, c, v))
404 goto badnargs;
405 fill_bottom(it, 0);
406 break;
407 case CMD_FILLBOTTOMNOLIMIT:
408 if(!valid_subphrase(E_ALL, c, v))
409 goto badnargs;
410 fill_bottom(it, 1);
411 break;
412 case CMD_SETDEFAULT:
413 if(!valid_subphrase(E_ALL, c, v))
414 goto badnargs;
415 setdefault(it);
416 break;
417 case CMD_BYPASSWM:
418 if(!valid_subphrase(E_ALL, c, v))
419 goto badnargs;
420 bypasswm(it, 1);
421 if (it->flags & F_VISIBLE) {
422 hide(it);
423 show(it);
425 break;
426 case CMD_FOLLOWWM:
427 if(!valid_subphrase(E_ALL, c, v))
428 goto badnargs;
429 bypasswm(it, 0);
430 if (it->flags & F_VISIBLE) {
431 hide(it);
432 show(it);
434 break;
435 case CMD_CLEAR:
436 if(!valid_subphrase(E_ALL, c, v))
437 goto badnargs;
438 clear(it);
439 break;
440 case CMD_SETTEXT:
441 if(!valid_subphrase(E_ALL, c, v))
442 goto badnargs;
443 v->pop_back(v, &b);
444 b = repr(b, 1);
445 settext(it, b->data);
446 release(b);
447 break;
448 case CMD_ADDTEXT:
449 if(!valid_subphrase(E_ALL, c, v))
450 goto badnargs;
451 v->pop_back(v, &b);
452 b = repr(b, 1);
453 addtext(it, b->data);
454 release(b);
455 break;
456 case CMD_DEFTEXT:
457 if(!valid_subphrase(E_ALL, c, v))
458 goto badnargs;
459 v->pop_back(v, &b);
460 assert_notblock(b, "first", o->data);
461 token_t* val = alloc(token_t);
462 val->type = T_QUOTE;
463 val->lineno = b->lineno;
464 val->source = b->source;
465 val->data = salloc(it->data);
466 define(b, val, NULL, NULL);
467 release(b);
468 release(val);
469 break;
470 case CMD_ENTITLE:
471 if(!valid_subphrase(E_ALL, c, v))
472 goto badnargs;
473 v->pop_back(v, &b);
474 b = repr(b, 1);
475 entitle(it, b->data);
476 release(b);
477 break;
478 case CMD_STYLE:
479 if(!valid_subphrase(E_ALL, c, v))
480 goto badnargs;
481 v->pop_back(v, &b);
482 b = repr(b, 1);
483 style(it, b->data);
484 release(b);
485 break;
486 case CMD_RESIZE: {
487 if(!valid_subphrase(E_ALL, c, v))
488 goto badnargs;
489 v->pop_back(v, &b);
490 assert_notblock(b, "first", o->data);
491 int wx = tolong(b);
492 release(b);
493 v->pop_back(v, &b);
494 assert_notblock(b, "second", o->data);
495 int hx = tolong(b);
496 resize(it, wx, hx);
497 release(b);
498 break;
500 case CMD_MOVE: {
501 if(!valid_subphrase(E_ALL, c, v))
502 goto badnargs;
503 v->pop_back(v, &b);
504 assert_notblock(b, "first", o->data);
505 int x = tolong(b);
506 release(b);
507 v->pop_back(v, &b);
508 assert_notblock(b, "second", o->data);
509 int y = tolong(b);
510 release(b);
511 move(it, x, y);
512 break;
514 case CMD_MOVEALIGN: {
515 if(!valid_subphrase(E_ALL, c, v))
516 goto badnargs;
517 v->first(v, &b);
518 assert_notblock(b, "first", o->data);
519 unsigned long wid = tolong(b);
520 widget_t* r;
521 if (!wid || !widgets->get(widgets, wid, &r)) {
522 err(b->source, b->lineno, "error, no widget with id '%lu'.\n", wid);
523 } else {
524 v->pop_back(v, &b);
525 release(b);
526 v->pop_back(v, &b);
527 assert_notblock(b, "second", o->data);
528 movealigns(it, r, b->data);
529 release(b);
531 break;
533 case CMD_TGRIP:
534 if(!valid_subphrase(E_ALL, c, v))
535 goto badnargs;
536 tgrip(it);
537 break;
538 case CMD_TXMOVABLE:
539 if(!valid_subphrase(E_ALL, c, v))
540 goto badnargs;
541 txmov(it);
542 break;
543 case CMD_TYMOVABLE:
544 if(!valid_subphrase(E_ALL, c, v))
545 goto badnargs;
546 tymov(it);
547 break;
548 case CMD_SHOWINPUT:
549 if(!valid_subphrase(E_INPUT, c, v))
550 goto badnargs;
551 showinput(it);
552 break;
553 case CMD_HIDEINPUT:
554 if(!valid_subphrase(E_INPUT, c, v))
555 goto badnargs;
556 hideinput(it);
557 break;
558 case CMD_PASSWORD:
559 if(!valid_subphrase(E_INPUT, c, v))
560 goto badnargs;
561 password(it);
562 break;
563 case CMD_TRET:
564 if(!valid_subphrase(E_INPUT, c, v))
565 goto badnargs;
566 tret(it);
567 break;
568 case CMD_EQUALIZE:
569 if(!valid_subphrase(E_PAGE, c, v))
570 goto badnargs;
571 equalize(it);
572 break;
573 case CMD_STYLESUBS:
574 if(!valid_subphrase(E_PAGE, c, v))
575 goto badnargs;
576 v->pop_back(v, &b);
577 b = repr(b, 1);
578 stylesubs(it, b->data);
579 release(b);
580 break;
581 case CMD_VERTICAL:
582 if(!valid_subphrase(E_PAGE, c, v))
583 goto badnargs;
584 vertical(it);
585 break;
586 case CMD_HORIZONTAL:
587 if(!valid_subphrase(E_PAGE, c, v))
588 goto badnargs;
589 horizontal(it);
590 break;
591 case CMD_SWAP:
592 if(!valid_subphrase(E_PAGE, c, v))
593 goto badnargs;
594 token_t* fw;
595 token_t* sw;
596 v->pop_back(v, &fw);
597 assert_notblock(fw, "first", o->data);
598 v->pop_back(v, &sw);
599 assert_notblock(sw, "second", o->data);
600 swap(it, fw->data, sw->data);
601 release(fw);
602 release(sw);
603 break;
604 case CMD_INVERT:
605 if(!valid_subphrase(E_PAGE, c, v))
606 goto badnargs;
607 invert(it);
608 break;
609 case CMD_EXPLODE:
610 if(!valid_subphrase(E_PAGE, c, v))
611 goto badnargs;
612 explode(it);
613 break;
614 case CMD_EMBED:
615 if(!valid_subphrase(E_PAGE, c, v))
616 goto badnargs;
617 v->pop_back(v, &b);
618 assert_notblock(b, "first", o->data);
619 embed(it, b->data);
620 release(b);
621 break;
622 case CMD_FITEMBED:
623 if(!valid_subphrase(E_PAGE, c, v))
624 goto badnargs;
625 v->pop_back(v, &b);
626 assert_notblock(b, "first", o->data);
627 fitembed(it, b->data);
628 release(b);
629 break;
630 case CMD_UNTIE:
631 if(!valid_subphrase(E_PAGE, c, v))
632 goto badnargs;
633 v->pop_back(v, &b);
634 assert_notblock(b, "first", o->data);
635 untie(it, b->data);
636 release(b);
637 break;
638 case CMD_FITUNTIE:
639 if(!valid_subphrase(E_PAGE, c, v))
640 goto badnargs;
641 v->pop_back(v, &b);
642 assert_notblock(b, "first", o->data);
643 fituntie(it, b->data);
644 release(b);
645 break;
646 case CMD_CHECK:
647 if(!valid_subphrase(E_CHECKBOX, c, v))
648 goto badnargs;
649 check(it);
650 break;
651 case CMD_UNCHECK:
652 if(!valid_subphrase(E_CHECKBOX, c, v))
653 goto badnargs;
654 uncheck(it);
655 break;
656 default:
657 err(o->source, o->lineno, "error, unknown command '%s'\n", o->data);
659 release(o);
661 showtokens(v);
662 return v->count;
663 badnargs:
664 err(sn, ln, "error, invalid number of parameters for command '%s'\n", o->data);