main.c (18807B)
1#include <stdio.h> 2#include <stdlib.h> 3#include <stdbool.h> 4#include <string.h> 5#include <ctype.h> 6 7#define BEEP_VALUE_HIGH 1 8#define BEEP_VALUE_LOW 0 9 10#define BEEP_REGISTER_COUNT 50 11 12typedef enum { 13 BEEP_OK = 0, 14 BEEP_ERROR = -1, 15} beep_err_t; 16 17typedef long beep_uid_t; 18 19typedef struct beep_board beep_board_t; 20typedef struct beep_node beep_node_t; 21typedef struct beep_element beep_element_t; 22 23typedef enum { 24 BEEP_TYPE_NONE, 25 BEEP_TYPE_UNKNOWN, 26 BEEP_TYPE_WIRE_Y, 27 BEEP_TYPE_WIRE_X, 28 BEEP_TYPE_NODE, 29 BEEP_TYPE_ELEMENT, 30} beep_type_t; 31 32typedef struct { 33 beep_type_t type; 34 char *str; 35 size_t len; 36 size_t ref_idx; 37 char *var_str; 38 size_t var_len; 39} beep_token_t; 40 41typedef struct { 42 beep_token_t *token; 43} beep_cell_t; 44 45typedef int beep_value_t; 46 47typedef struct { 48 beep_uid_t element_uid; 49 size_t idx; 50 beep_value_t value; 51} beep_channel_t; 52 53struct beep_node { 54 beep_uid_t uid; 55 beep_node_t **nodes; 56 size_t nodes_len; 57 beep_channel_t *channels; 58 size_t channels_len; 59 bool is_dirty; 60}; 61 62struct beep_element { 63 beep_uid_t uid; 64 char *type; 65 char *var; 66 beep_node_t *in; 67 beep_node_t *out; 68 void (*update)(beep_board_t *self, beep_element_t *element); 69}; 70 71typedef struct { 72 beep_uid_t element_uid; 73 beep_value_t value; 74} beep_signal_t; 75 76typedef struct { 77 beep_element_t *elements; 78 size_t elements_len; 79 beep_node_t *nodes; 80 size_t nodes_len; 81} beep_state_t; 82 83typedef struct { 84 beep_value_t values[BEEP_REGISTER_COUNT]; 85} beep_registry_t; 86 87struct beep_board { 88 char *buffer; 89 size_t rows; 90 size_t cols; 91 beep_cell_t *cells; 92 beep_token_t *tokens; 93 size_t len; 94 beep_state_t state; 95 beep_registry_t registry; 96}; 97 98static beep_uid_t _BEEP_UID_COUNT = 0; 99 100beep_uid_t beep_uid(void) { 101 return ++_BEEP_UID_COUNT; 102} 103 104void beep_token_init(beep_token_t *self) { 105 *self = (beep_token_t) { 106 .type = BEEP_TYPE_UNKNOWN, 107 .str = NULL, 108 .len = 0, 109 .ref_idx = -1, 110 .var_str = NULL, 111 .var_len = 0, 112 }; 113} 114 115void beep_node_init(beep_node_t *self) { 116 *self = (beep_node_t) { 117 .uid = beep_uid(), 118 .nodes = NULL, 119 .nodes_len = 0, 120 .channels = NULL, 121 .channels_len = 0, 122 .is_dirty = false, 123 }; 124} 125 126void beep_node_index(beep_node_t *self, beep_uid_t element_uid, size_t idx) { 127 size_t i = 0; 128 for (; i < self->channels_len; i++) { 129 if (self->channels[i].element_uid == element_uid) { 130 return; 131 } 132 } 133 self->channels = realloc(self->channels, sizeof(beep_channel_t) * (self->channels_len + 1)); 134 beep_channel_t *channel = &self->channels[self->channels_len]; 135 channel->element_uid = element_uid; 136 channel->idx = idx; 137 channel->value = 0; 138 self->channels_len++; 139 i = 0; 140 for (; i < self->nodes_len; i++) { 141 beep_node_t *node = self->nodes[i]; 142 beep_node_index(node, element_uid, idx + 1); 143 } 144} 145 146void beep_node_update(beep_node_t *self, const beep_signal_t signal) { 147 size_t i = 0; 148 beep_channel_t *channel = NULL; 149 for (; i < self->channels_len; i++) { 150 if (self->channels[i].element_uid == signal.element_uid) { 151 channel = &self->channels[i]; 152 break; 153 } 154 } 155 if (channel == NULL) { 156 return; 157 } 158 channel->value = signal.value; 159 self->is_dirty = true; 160 i = 0; 161 for (; i < self->nodes_len; i++) { 162 beep_node_t *node = self->nodes[i]; 163 size_t j = 0; 164 for (; j < node->channels_len; j++) { 165 beep_channel_t *node_channel = &node->channels[j]; 166 if (node_channel->element_uid == channel->element_uid && node_channel->idx > channel->idx) { 167 beep_node_update(node, signal); 168 break; 169 } 170 } 171 } 172} 173 174beep_value_t beep_node_value(beep_node_t *self) { 175 size_t i = 0; 176 for (; i < self->channels_len; i++) { 177 beep_channel_t *channel = &self->channels[i]; 178 if (channel->value == BEEP_VALUE_HIGH) { 179 return BEEP_VALUE_HIGH; 180 } 181 } 182 self->is_dirty = false; 183 return BEEP_VALUE_LOW; 184} 185 186void beep_registry_set(beep_board_t *self, size_t idx, beep_value_t value) { 187 if (idx >= BEEP_REGISTER_COUNT) { 188 return; 189 } 190 self->registry.values[idx] = value; 191} 192 193beep_value_t *beep_registry_get(beep_board_t *self, size_t idx) { 194 if (idx >= BEEP_REGISTER_COUNT) { 195 return NULL; 196 } 197 return &self->registry.values[idx]; 198} 199 200void BEEP_REG_UPDATE(beep_board_t *self, beep_element_t *element) { 201 if (element->var == NULL) { 202 return; 203 } 204 size_t idx = atoi(element->var); 205 if (element->in->is_dirty) { 206 beep_value_t value_in = beep_node_value(element->in); 207 beep_registry_set(self, idx, value_in); 208 printf("[REG] %s --> [%zu]\n", value_in ? "HIGH" : "LOW", idx); 209 } 210 beep_value_t value_out = *beep_registry_get(self, idx); 211 beep_node_update(element->out, (beep_signal_t) { element->uid, value_out }); 212 printf("[REG] [%zu] --> %s\n", idx, value_out ? "HIGH" : "LOW"); 213} 214 215void BEEP_BTN_UPDATE(beep_board_t *self, beep_element_t *element) { 216 (void) self; 217 (void) element; 218} 219 220void BEEP_NOT_UPDATE(beep_board_t *self, beep_element_t *element) { 221 (void) self; 222 beep_value_t value_in = beep_node_value(element->in); 223 beep_value_t value_out = !value_in; 224 printf("[NOT] %s --> %s\n", value_in ? "HIGH" : "LOW", value_out ? "HIGH" : "LOW"); 225 beep_node_update(element->out, (beep_signal_t) { element->uid, value_out }); 226} 227 228void BEEP_ADD_UPDATE(beep_board_t *self, beep_element_t *element) { 229 (void) self; 230 (void) element; 231} 232 233void BEEP_BULB_UPDATE(beep_board_t *self, beep_element_t *element) { 234 (void) self; 235 beep_value_t value_in = beep_node_value(element->in); 236 printf("[BULB] %s\n", value_in ? "HIGH" : "LOW"); 237} 238 239void beep_element_init(beep_element_t *self, beep_token_t *token) { 240 size_t i = 0; 241 for (; i < token->len; i++) { 242 if (i < token->len && token->str[i] == '(') { 243 break; 244 } 245 } 246 size_t type_len = i; 247 char *type = malloc(sizeof(char) * (type_len + 1)); 248 memcpy(type, token->str, type_len); 249 type[type_len] = '\0'; 250 char *var = NULL; 251 if (token->var_str != NULL) { 252 var = malloc(sizeof(char) * (type_len + 1)); 253 memcpy(var, token->var_str, token->var_len); 254 var[token->var_len] = '\0'; 255 } 256 void (*update)(beep_board_t *self, beep_element_t *element) = NULL; 257 if (strcmp(type, "REG") == 0) { 258 update = BEEP_REG_UPDATE; 259 } 260 if (strcmp(type, "BTN") == 0) { 261 update = BEEP_BTN_UPDATE; 262 } 263 if (strcmp(type, "NOT") == 0) { 264 update = BEEP_NOT_UPDATE; 265 } 266 if (strcmp(type, "ADD") == 0) { 267 update = BEEP_ADD_UPDATE; 268 } 269 if (strcmp(type, "BULB") == 0) { 270 update = BEEP_BULB_UPDATE; 271 } 272 beep_node_t *node_in = malloc(sizeof(beep_node_t)); 273 beep_node_init(node_in); 274 beep_node_t *node_out = malloc(sizeof(beep_node_t)); 275 beep_node_init(node_out); 276 *self = (beep_element_t) { 277 .uid = beep_uid(), 278 .type = type, 279 .var = var, 280 .in = node_in, 281 .out = node_out, 282 .update = update, 283 }; 284} 285 286beep_cell_t *beep_board_at(beep_board_t *self, size_t row, size_t col) { 287 if (self == NULL) { 288 return NULL; 289 } 290 if (row >= self->rows || col >= self->cols) { 291 return NULL; 292 } 293 return &self->cells[row * self->cols + col]; 294} 295 296beep_err_t beep_file_read(char *filename, char **buffer) { 297 FILE *file = fopen(filename, "r"); 298 if (file == NULL) { 299 return BEEP_ERROR; 300 } 301 fseek(file, 0, SEEK_END); 302 size_t len = ftell(file); 303 fseek(file, 0, SEEK_SET); 304 *buffer = malloc(sizeof(char) * (len + 1)); 305 fread(*buffer, sizeof(char), len, file); 306 (*buffer)[len] = '\0'; 307 fclose(file); 308 return BEEP_OK; 309} 310 311beep_err_t beep_board_read(beep_board_t *self, char *buffer) { 312 if (self == NULL) { 313 return BEEP_ERROR; 314 } 315 // read dimensions (rows, cols) 316 size_t len = strlen(buffer); 317 size_t i = 0; 318 size_t ln_set = i; 319 for (; i < len; i++) { 320 char c = buffer[i]; 321 if (c == '\n') { 322 size_t ln_len = i - ln_set; 323 if (i > 0 && buffer[i - 1] == '\r') { 324 ln_len--; 325 } 326 if (ln_len > self->cols) { 327 self->cols = ln_len; 328 } 329 ln_set = i + 1; 330 self->rows++; 331 } 332 } 333 if (ln_set < len) { 334 size_t ln_len = i - ln_set; 335 if (i > 0 && buffer[i - 1] == '\r') { 336 ln_len--; 337 } 338 if (ln_len > self->cols) { 339 self->cols = ln_len; 340 } 341 self->rows++; 342 } 343 // fill board 344 self->buffer = malloc(sizeof(char) * self->rows * self->cols); 345 memset(self->buffer, ' ', self->rows * self->cols); 346 i = 0; 347 ln_set = i; 348 size_t ln = i; 349 for (; i < len; i++) { 350 size_t ln_idx = i - ln_set; 351 char c = buffer[i]; 352 if (c == '\r') { 353 continue; 354 } 355 if (c == '\n') { 356 ln_set = i + 1; 357 ln++; 358 continue; 359 } 360 if (ln_idx < self->cols) { 361 self->buffer[ln * self->cols + ln_idx] = c; 362 } 363 } 364 return BEEP_OK; 365} 366 367beep_err_t beep_board_tokenize(beep_board_t *self) { 368 if (self == NULL) { 369 return BEEP_ERROR; 370 } 371 // read tokens 372 size_t i = 0; 373 size_t len = self->rows * self->cols; 374 for (; i < len; i++) { 375 char c = self->buffer[i]; 376 if (c == ' ' || c == '-' || c == '|' || c == '+') { 377 self->tokens = realloc(self->tokens, sizeof(beep_token_t) * (self->len + 1)); 378 beep_token_t *token = &self->tokens[self->len]; 379 beep_token_init(token); 380 switch (c) { 381 case ' ': 382 token->type = BEEP_TYPE_NONE; 383 break; 384 case '-': 385 token->type = BEEP_TYPE_WIRE_X; 386 break; 387 case '|': 388 token->type = BEEP_TYPE_WIRE_Y; 389 break; 390 case '+': 391 token->type = BEEP_TYPE_NODE; 392 break; 393 } 394 token->str = self->buffer + i; 395 token->len = 1; 396 self->len++; 397 } 398 else if (isalpha(c)) { 399 size_t token_set = i; 400 char *var_str = NULL; 401 size_t var_len = -1; 402 while (i < len && isalpha(self->buffer[i])) { 403 i++; 404 } 405 if (i < len && self->buffer[i] == '(') { 406 size_t i_reset = i; 407 i++; 408 size_t var_set = i; 409 while (i < len && self->buffer[i] != ')') { 410 i++; 411 } 412 if (i < len && self->buffer[i] == ')') { 413 var_str = self->buffer + var_set; 414 var_len = i - var_set; 415 i++; 416 } 417 else { 418 i = i_reset; 419 } 420 } 421 self->tokens = realloc(self->tokens, sizeof(beep_token_t) * (self->len + 1)); 422 beep_token_t *token = &self->tokens[self->len]; 423 token->type = BEEP_TYPE_ELEMENT; 424 token->str = self->buffer + token_set; 425 token->len = i - token_set; 426 if (var_str != NULL) { 427 token->var_str = var_str; 428 token->var_len = var_len; 429 } 430 self->len++; 431 i--; 432 } 433 else { 434 self->tokens = realloc(self->tokens, sizeof(beep_token_t) * (self->len + 1)); 435 beep_token_t *token = &self->tokens[self->len]; 436 token->type = BEEP_TYPE_UNKNOWN; 437 token->str = self->buffer + i; 438 token->len = 1; 439 self->len++; 440 } 441 } 442 // create cells 443 self->cells = calloc(self->rows * self->cols, sizeof(beep_cell_t)); 444 i = 0; 445 size_t cell_idx = i; 446 for (; i < self->len; i++) { 447 beep_token_t *token = &self->tokens[i]; 448 size_t j = 0; 449 for (; j < token->len; j++) { 450 beep_cell_t *cell = &self->cells[cell_idx + j]; 451 cell->token = token; 452 } 453 cell_idx += token->len; 454 } 455 return BEEP_OK; 456} 457 458beep_err_t beep_board_construct(beep_board_t *self) { 459 if (self == NULL) { 460 return BEEP_ERROR; 461 } 462 beep_state_t *state = &self->state; 463 // create elements/nodes 464 size_t i = 0; 465 for (; i < self->len; i++) { 466 beep_token_t *token = &self->tokens[i]; 467 if (token->type == BEEP_TYPE_ELEMENT) { 468 state->elements = realloc(state->elements, sizeof(beep_element_t) * (state->elements_len + 1)); 469 beep_element_t *element = &state->elements[state->elements_len]; 470 beep_element_init(element, token); 471 token->ref_idx = state->elements_len; 472 state->elements_len++; 473 } 474 if (token->type == BEEP_TYPE_NODE) { 475 state->nodes = realloc(state->nodes, sizeof(beep_node_t) * (state->nodes_len + 1)); 476 beep_node_t *node = &state->nodes[state->nodes_len]; 477 beep_node_init(node); 478 token->ref_idx = state->nodes_len; 479 state->nodes_len++; 480 } 481 } 482 // link all horizontal wires 483 for (size_t y = 0; y < self->rows; y++) { 484 size_t x = 0; 485 beep_cell_t *cell_set = NULL; 486 while (x < self->cols) { 487 beep_cell_t *cell = beep_board_at(self, y, x); 488 if (cell->token->type == BEEP_TYPE_WIRE_X) { 489 if (x > 0) { 490 cell_set = beep_board_at(self, y, x - 1); 491 } 492 while (x < self->cols && cell->token->type == BEEP_TYPE_WIRE_X) { 493 cell = beep_board_at(self, y, ++x); 494 } 495 if (cell != NULL && cell_set != NULL) { 496 beep_type_t type_set = cell_set->token->type; 497 beep_type_t type_end = cell->token->type; 498 if ( 499 (type_set == BEEP_TYPE_ELEMENT || type_set == BEEP_TYPE_NODE) && 500 (type_end == BEEP_TYPE_ELEMENT || type_end == BEEP_TYPE_NODE) 501 ) { 502 beep_node_t *node_set = NULL; 503 beep_node_t *node_end = NULL; 504 if (type_set == BEEP_TYPE_ELEMENT) { 505 beep_element_t *element = &state->elements[cell_set->token->ref_idx]; 506 node_set = element->out; 507 } 508 if (type_set == BEEP_TYPE_NODE) { 509 node_set = &state->nodes[cell_set->token->ref_idx]; 510 } 511 if (type_end == BEEP_TYPE_ELEMENT) { 512 beep_element_t *element = &state->elements[cell->token->ref_idx]; 513 node_end = element->in; 514 } 515 if (type_end == BEEP_TYPE_NODE) { 516 node_end = &state->nodes[cell->token->ref_idx]; 517 } 518 if (node_set != NULL && node_end != NULL) { 519 node_set->nodes = realloc(node_set->nodes, sizeof(beep_node_t *) * (node_set->nodes_len + 1)); 520 node_set->nodes[node_set->nodes_len] = node_end; 521 node_set->nodes_len++; 522 node_end->nodes = realloc(node_end->nodes, sizeof(beep_node_t *) * (node_end->nodes_len + 1)); 523 node_end->nodes[node_end->nodes_len] = node_set; 524 node_end->nodes_len++; 525 } 526 } 527 } 528 x--; 529 } 530 x++; 531 } 532 } 533 // link all vertical wires 534 for (size_t x = 0; x < self->cols; x++) { 535 size_t y = 0; 536 beep_cell_t *cell_set = NULL; 537 while (y < self->rows) { 538 beep_cell_t *cell = beep_board_at(self, y, x); 539 if (cell->token->type == BEEP_TYPE_WIRE_Y) { 540 if (y > 0) { 541 cell_set = beep_board_at(self, y - 1, x); 542 } 543 while (y < self->rows && cell->token->type == BEEP_TYPE_WIRE_Y) { 544 cell = beep_board_at(self, ++y, x); 545 } 546 if (cell != NULL && cell_set != NULL) { 547 beep_type_t type_set = cell_set->token->type; 548 beep_type_t type_end = cell->token->type; 549 if (type_set == BEEP_TYPE_NODE && type_end == BEEP_TYPE_NODE) { 550 beep_node_t *node_set = &state->nodes[cell_set->token->ref_idx]; 551 beep_node_t *node_end = &state->nodes[cell->token->ref_idx]; 552 node_set->nodes = realloc(node_set->nodes, sizeof(beep_node_t *) * (node_set->nodes_len + 1)); 553 node_set->nodes[node_set->nodes_len] = node_end; 554 node_set->nodes_len++; 555 node_end->nodes = realloc(node_end->nodes, sizeof(beep_node_t *) * (node_end->nodes_len + 1)); 556 node_end->nodes[node_end->nodes_len] = node_set; 557 node_end->nodes_len++; 558 } 559 } 560 y--; 561 } 562 y++; 563 } 564 } 565 // channel indexing 566 i = 0; 567 for (; i < state->elements_len; i++) { 568 beep_element_t *element = &state->elements[i]; 569 beep_node_index(element->out, element->uid, 0); 570 } 571 return BEEP_OK; 572} 573 574beep_err_t beep_board_init(beep_board_t *self, char *buffer) { 575 if (buffer == NULL) { 576 return BEEP_ERROR; 577 } 578 *self = (beep_board_t) { 579 .buffer = NULL, 580 .rows = 0, 581 .cols = 0, 582 .cells = NULL, 583 .tokens = NULL, 584 .len = 0, 585 .state = {0}, 586 .registry = { 587 .values = {0}, 588 }, 589 }; 590 memset(self->registry.values, BEEP_VALUE_LOW, sizeof(beep_value_t) * BEEP_REGISTER_COUNT); 591 beep_err_t ret; 592 if ((ret = beep_board_read(self, buffer)) == BEEP_ERROR) { 593 return ret; 594 } 595 for (size_t y = 0; y < self->rows; y++) { 596 for (size_t x = 0; x < self->cols; x++) { 597 printf("%c", self->buffer[y * self->cols + x]); 598 } 599 printf("\n"); 600 } 601 printf("\n"); 602 if ((ret = beep_board_tokenize(self)) == BEEP_ERROR) { 603 return ret; 604 } 605 for (size_t y = 0; y < self->rows; y++) { 606 for (size_t x = 0; x < self->cols; x++) { 607 size_t idx = y * self->cols + x; 608 beep_cell_t *cell = &self->cells[idx]; 609 switch (cell->token->type) { 610 case BEEP_TYPE_NONE: 611 printf("."); 612 break; 613 case BEEP_TYPE_UNKNOWN: 614 printf("?"); 615 break; 616 case BEEP_TYPE_WIRE_Y: 617 printf("Y"); 618 break; 619 case BEEP_TYPE_WIRE_X: 620 printf("X"); 621 break; 622 case BEEP_TYPE_NODE: 623 printf("N"); 624 break; 625 case BEEP_TYPE_ELEMENT: 626 printf("E"); 627 break; 628 } 629 } 630 printf("\n"); 631 } 632 printf("\n"); 633 if ((ret = beep_board_construct(self)) == BEEP_ERROR) { 634 return ret; 635 } 636 return BEEP_OK; 637} 638 639beep_err_t beep_board_load(beep_board_t *self, char *filename) { 640 char *buffer = NULL; 641 if (beep_file_read(filename, &buffer) < 0) { 642 return BEEP_ERROR; 643 } 644 beep_err_t ret = beep_board_init(self, buffer); 645 free(buffer); 646 return ret; 647} 648 649void beep_board_free(beep_board_t *self) { 650 if (self == NULL) { 651 return; 652 } 653 free(self->buffer); 654 free(self->cells); 655 free(self->tokens); 656 beep_state_t *state = &self->state; 657 if (state->elements_len > 0) { 658 size_t i = 0; 659 for (; i < state->elements_len; i++) { 660 beep_element_t *element = &state->elements[i]; 661 free(element->type); 662 if (element->var != NULL) { 663 free(element->var); 664 } 665 free(element->in); 666 free(element->out); 667 } 668 free(state->elements); 669 } 670 if (state->nodes_len > 0) { 671 size_t i = 0; 672 for (; i < state->nodes_len; i++) { 673 beep_node_t *node = &state->nodes[i]; 674 if (node->nodes_len > 0) { 675 free(node->nodes); 676 } 677 if (node->channels_len > 0) { 678 free(node->channels); 679 } 680 } 681 free(state->nodes); 682 } 683} 684 685void beep_update(beep_board_t *self) { 686 printf("----- update -----\n"); 687 beep_state_t *state = &self->state; 688 size_t i = 0; 689 for (; i < state->elements_len; i++) { 690 beep_element_t *element = &state->elements[i]; 691 if (element->update == NULL) { 692 continue; 693 } 694 element->update(self, element); 695 } 696} 697 698int main(void) { 699 beep_board_t board; 700 if (beep_board_load(&board, "./files/sample") < 0) { 701 return BEEP_ERROR; 702 } 703 beep_update(&board); 704 beep_registry_set(&board, 0, BEEP_VALUE_HIGH); 705 beep_update(&board); 706 beep_registry_set(&board, 0, BEEP_VALUE_LOW); 707 beep_update(&board); 708 beep_board_free(&board); 709 return BEEP_OK; 710}