Imported Upstream version 0.1beta
[debian/yforth] / block.c
1 /* yForth? - Written by Luca Padovani (C) 1996/97
2  * ------------------------------------------------------------------------
3  * This software is FreeWare as long as it comes with this header in each
4  * source file, anyway you can use it or any part of it whatever
5  * you want. It comes without any warranty, so use it at your own risk.
6  * ------------------------------------------------------------------------
7  * Module name:     block.c
8  * Abstract:        Block word set implementation
9  */
10
11 #include <stdio.h>
12 #include <malloc.h>
13 #include "yforth.h"
14 #include "core.h"
15 #include "block.h"
16
17 /**************************************************************************/
18 /* VARIABLES **************************************************************/
19 /**************************************************************************/
20
21 UCell _b_l_k;
22 UCell current_block;
23
24 FILE *block_file;                   /* FILE used to implement blocks */
25
26 struct _block_data *block_data;
27 struct _block_buffer *block_buffer;
28
29 static int block_clock;             /* Used to select the next block to
30                                        deallocate. Based on the "clock
31                                        algorithm
32                                     */
33
34 /**************************************************************************/
35 /* WORDS ******************************************************************/
36 /**************************************************************************/
37
38 void _block() {
39         register UCell u = (UCell) *sp;
40         register int b = search_block(u);
41         if (b < 0) b = allocate_block(u, 1);
42         current_block = b;
43         sp[0] = (Cell) &block_buffer[b].buffer;
44 }
45
46 void _buffer() {
47         register UCell u = (UCell) *sp;
48         register int b = search_block(u);
49         if (b < 0) b = allocate_block(u, 0);
50         current_block = b;
51         sp[0] = (Cell) &block_buffer[b].buffer;
52 }
53
54 void _flush() {
55         register int i;
56         _save_buffers();
57         for (i = 0; i < NUM_BLOCKS; i++) block_data[i].block_no = 0;
58 }
59
60 void _load() {
61         register UCell block_no = (UCell) *sp;
62         save_input_specification();
63         _block();
64         _input_buffer = (Char *) *sp++;
65         _in_input_buffer = BLOCK_SIZE;
66         _to_in = 0;
67         _b_l_k = block_no;
68         _interpret();
69         restore_input_specification();
70 }
71
72 void _save_buffers() {
73         register int i;
74         for (i = 0; i < NUM_BLOCKS; i++) if (block_data[i].dirty) save_block(i);
75 }
76
77 void _update() {
78         block_data[current_block].dirty = 1;
79 }
80
81 /**************************************************************************/
82 /* AUXILIARY FUNCTIONS ****************************************************/
83 /**************************************************************************/
84
85 int search_block(UCell block_no) {
86         register int i;
87         for (i = 0; i < NUM_BLOCKS && block_data[i].block_no != block_no; i++) ;
88         return (i < NUM_BLOCKS ? i : -1);
89 }
90
91 int allocate_block(UCell block_no, int load) {
92         register int i;
93         register int b = search_block(0);
94         if (b < 0) {
95         if (block_data[block_clock].dirty) save_block(block_clock);
96         b = block_clock;
97         block_clock = (block_clock + 1) % NUM_BLOCKS;
98         }
99         if (load) load_block(block_no, b);
100     return (b);
101 }
102
103 void load_block(UCell block_no, int b) {
104         block_data[b].block_no = block_no;
105         block_data[b].dirty = 0;
106         fseek(block_file, ((long) (block_no - 1)) * BLOCK_SIZE, SEEK_SET);
107         fread(&block_buffer[b].buffer, BLOCK_SIZE, 1, block_file);
108 }
109
110 void save_block(int b) {
111         fseek(block_file, ((long) (block_data[b].block_no - 1)) * BLOCK_SIZE, SEEK_SET);
112         fwrite(&block_buffer[b].buffer, BLOCK_SIZE, 1, block_file);
113         block_data[b].dirty = 0;
114 }
115
116 int open_block_file(char *name) {
117         block_file = fopen(name, "r+b");
118         if (!block_file) block_file = fopen(name, "r+b");
119         if (block_file) {
120                 block_data = (struct _block_data *) malloc(NUM_BLOCKS * sizeof(struct _block_data));
121                 block_buffer = (struct _block_buffer *) malloc(NUM_BLOCKS * sizeof(struct _block_buffer));
122                 if (block_data && block_buffer) {
123                         int i;
124                         for (i = 0; i < NUM_BLOCKS; i++) block_data[i].block_no = 0;
125                 } else block_file = NULL;
126         }
127         return (block_file ? 0 : -1);
128 }
129
130 void close_block_file() {
131         if (block_file) {
132                 _save_buffers();
133                 fclose(block_file);
134         }
135 }