1 /* yForth? - A Forth interpreter written in ANSI C
2 * Copyright (C) 2012 Luca Padovani
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 <http://www.gnu.org/licenses/>.
16 * ------------------------------------------------------------------------
17 * Module name: block.c
18 * Abstract: Block word set implementation
27 /**************************************************************************/
28 /* VARIABLES **************************************************************/
29 /**************************************************************************/
34 FILE *block_file; /* FILE used to implement blocks */
36 struct _block_data *block_data;
37 struct _block_buffer *block_buffer;
39 static int block_clock; /* Used to select the next block to
40 deallocate. Based on the "clock
44 /**************************************************************************/
45 /* WORDS ******************************************************************/
46 /**************************************************************************/
49 register UCell u = (UCell) *sp;
50 register int b = search_block(u);
51 if (b < 0) b = allocate_block(u, 1);
53 sp[0] = (Cell) &block_buffer[b].buffer;
57 register UCell u = (UCell) *sp;
58 register int b = search_block(u);
59 if (b < 0) b = allocate_block(u, 0);
61 sp[0] = (Cell) &block_buffer[b].buffer;
67 for (i = 0; i < NUM_BLOCKS; i++) block_data[i].block_no = 0;
71 register UCell block_no = (UCell) *sp;
72 save_input_specification();
74 _input_buffer = (Char *) *sp++;
75 _in_input_buffer = BLOCK_SIZE;
79 restore_input_specification();
82 void _save_buffers() {
84 for (i = 0; i < NUM_BLOCKS; i++) if (block_data[i].dirty) save_block(i);
88 block_data[current_block].dirty = 1;
91 /**************************************************************************/
92 /* AUXILIARY FUNCTIONS ****************************************************/
93 /**************************************************************************/
95 int search_block(UCell block_no) {
97 for (i = 0; i < NUM_BLOCKS && block_data[i].block_no != block_no; i++) ;
98 return (i < NUM_BLOCKS ? i : -1);
101 int allocate_block(UCell block_no, int load) {
103 register int b = search_block(0);
105 if (block_data[block_clock].dirty) save_block(block_clock);
107 block_clock = (block_clock + 1) % NUM_BLOCKS;
109 if (load) load_block(block_no, b);
113 void load_block(UCell block_no, int b) {
114 block_data[b].block_no = block_no;
115 block_data[b].dirty = 0;
116 fseek(block_file, ((long) (block_no - 1)) * BLOCK_SIZE, SEEK_SET);
117 fread(&block_buffer[b].buffer, BLOCK_SIZE, 1, block_file);
120 void save_block(int b) {
121 fseek(block_file, ((long) (block_data[b].block_no - 1)) * BLOCK_SIZE, SEEK_SET);
122 fwrite(&block_buffer[b].buffer, BLOCK_SIZE, 1, block_file);
123 block_data[b].dirty = 0;
126 int open_block_file(char *name) {
127 block_file = fopen(name, "r+b");
128 if (!block_file) block_file = fopen(name, "r+b");
130 block_data = (struct _block_data *) malloc(NUM_BLOCKS * sizeof(struct _block_data));
131 block_buffer = (struct _block_buffer *) malloc(NUM_BLOCKS * sizeof(struct _block_buffer));
132 if (block_data && block_buffer) {
134 for (i = 0; i < NUM_BLOCKS; i++) block_data[i].block_no = 0;
135 } else block_file = NULL;
137 return (block_file ? 0 : -1);
140 void close_block_file() {