1 /* $Id: insert.c,v 1.9 1994/06/24 11:11:14 ceriel Exp $ */
3 /* Implementation of C_insertpart, C_beginpart, and C_endpart.
4 Basic methodology: place the parts either in memory or on a temporary
5 file, in the order received, and remember this order. Then, in a second
6 "pass", write out the code.
7 An optimization is possible: as long as the order in which the parts
8 are received corresponds to the order in which they must be written,
9 they can be written immediately.
16 char *C_tmpdir = TMP_DIR;
17 static Part *C_stable[TABSIZ];
19 static char *C_old_top;
20 static char *C_old_opp;
23 static File *C_old_ofp;
29 /* Get the byte at offset "b" from the start of the
30 temporary file, and try to do so in an efficient way.
32 static long start_core, curr_pos;
34 if (b < start_core || b >= curr_pos) {
35 /* the block wanted is not in core, so get it */
36 long nb = (b & ~(BUFSIZ - 1));
41 if (sys_seek(C_tfr, nb, 0, &curr_pos) == 0) {
46 C_ibuf = Malloc(BUFSIZ);
48 if (sys_read(C_tfr, C_ibuf, BUFSIZ, &n) == 0) {
55 return C_ibuf[(int) (b - start_core)];
60 static Part *C_findpart();
66 /* Output part "id", if present.
68 Part *p = C_findpart(id);
71 C_out_parts(p->p_parts);
78 register PartOfPart *pp;
80 /* Output the list of chunks started by "pp".
81 The list is build in reverse order, so this routine is
84 PartOfPart *prev = 0, *next;
95 if (pp->pp_type == INSERT) {
96 (*C_outpart)(pp->pp_id);
99 /* copy the chunk to output */
101 register char *s = C_BASE + pp->pp_begin;
102 char *se = C_BASE + pp->pp_end;
108 register long b = pp->pp_begin;
110 while (b < pp->pp_end) {
125 /* Look for part "part" in the table.
126 Return 0 if not present,
128 register Part *p = C_stable[part % TABSIZ];
130 while (p && p->p_id != part) {
136 extern char *strcpy(), *strcat(), *mktemp();
142 if (C_tmpfile == 0) {
143 static char tmpbuf[64];
144 register char *p = tmpbuf;
147 strcat(p, "/CodeXXXXXX");
148 C_tmpfile = mktemp(p);
149 if (! sys_open(p, OP_WRITE, &C_old_ofp)) {
152 if (! sys_open(p, OP_READ, &C_tfr)) {
212 /* See if part "part", and all the parts it consists of,
213 are available. Return 1 if they are, 0 otherwize
215 register Part *p = C_findpart(part);
216 register PartOfPart *pp;
219 if (p == 0) return 0;
221 if (p->p_flags & BUSY) {
222 /* recursive call ends up here, and this just should
223 not happen. It is an error of the programmer using
233 if (pp->pp_type == INSERT && ! available(pp->pp_id)) {
237 else pp = pp->pp_next;
247 /* Create a Part structure with id "part", and return a
248 pointer to it, after checking that is does not exist
251 register Part *p = C_findpart(part);
252 register int index = part % TABSIZ;
255 /* multiple defined part ... */
259 p = (Part *) Malloc(sizeof(Part));
261 p->p_next = C_stable[index];
273 /* End the current chunk of part *p.
277 register PartOfPart *pp = p->p_parts;
279 pp->pp_end = C_current_out - C_BASE;
280 if (pp->pp_begin == pp->pp_end) {
281 /* nothing in this chunk, so give it back */
282 p->p_parts = pp->pp_next;
292 /* Resume part "p", by creating a new PartOfPart structure
295 register PartOfPart *pp = (PartOfPart *) Malloc(sizeof(PartOfPart));
299 pp->pp_next = p->p_parts;
302 pp->pp_begin = C_current_out - C_BASE;
309 /* Insert part "part" in the current part. If C_sequential is
310 still set and the part to be inserted is available now,
314 register PartOfPart *pp;
319 if (C_sequential && available(part)) {
325 /* stop the sequential stuff, by creating a part */
335 /* Now, add the insertion of "part" to the current part. */
336 pp = (PartOfPart *) Malloc(sizeof(PartOfPart));
337 pp->pp_next = p->p_parts;
339 pp->pp_type = INSERT;
348 /* Now follows the definition for part "part".
349 Suspend the current part, and add part "part" to the
352 register Part *p = mkpart(part);
358 end_partofpart(C_curr_part);
360 p->p_prevpart = C_curr_part;
368 /* End the current part. The parameter "part" is just there
369 for the checking. Do we really need it ???
371 register Part *p = C_curr_part;
373 if (p->p_id != part) {
374 /* illegal C_endpart ... */
379 if (p->p_prevpart) resume(p->p_prevpart);