|
|
1.1 root 1: /* VMS mapping of data and alloc arena for GNU Emacs.
2: Copyright (C) 1986, 1987 Free Software Foundation, Inc.
3:
4: This file is part of GNU Emacs.
5:
6: GNU Emacs is free software; you can redistribute it and/or modify
7: it under the terms of the GNU General Public License as published by
8: the Free Software Foundation; either version 1, or (at your option)
9: any later version.
10:
11: GNU Emacs is distributed in the hope that it will be useful,
12: but WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14: GNU General Public License for more details.
15:
16: You should have received a copy of the GNU General Public License
17: along with GNU Emacs; see the file COPYING. If not, write to
18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19:
20: /* Written by Mukesh Prasad. */
21:
22: #ifdef VMS
23:
24: #include "config.h"
25: #include "lisp.h"
26: #include <rab.h>
27: #include <fab.h>
28: #include <rmsdef.h>
29: #include <secdef.h>
30:
31: /* RMS block size */
32: #define BLOCKSIZE 512
33:
34: /* Maximum number of bytes to be written in one RMS write.
35: * Must be a multiple of BLOCKSIZE.
36: */
37: #define MAXWRITE (BLOCKSIZE * 30)
38:
39: /* This funniness is to ensure that sdata occurs alphabetically BEFORE the
40: $DATA psect and that edata occurs after ALL Emacs psects. This is
41: because the VMS linker sorts all psects in a cluster alphabetically
42: during the linking, unless you use the cluster_psect command. Emacs
43: uses the cluster command to group all Emacs psects into one cluster;
44: this keeps the dumped data separate from any loaded libraries. */
45:
46: #ifdef __GNUC__
47: /* We need a large sdata array because otherwise the impure storage will end up
48: in low memory, and this will screw up garbage collection (Emacs will not
49: be able to tell the difference between a string length and an address).
50: This array guarantees that the impure storage is at a sufficiently high
51: address so that this problem will not occur. */
52: char sdata[8192] asm("_$$PsectAttributes_NOOVR$$$D$ATA") ;
53: char edata[512] asm("_$$PsectAttributes_NOOVR$$__DATA") ;
54: #else
55: globaldef {"$D$ATA"} char sdata[512]; /* Start of saved data area */
56: globaldef {"__DATA"} char edata[512]; /* End of saved data area */
57: #endif
58:
59: /* Structure to write into first block of map file.
60: */
61:
62: struct map_data
63: {
64: char * sdata; /* Start of data area */
65: char * edata; /* End of data area */
66: int datablk; /* Block in file to map data area from/to */
67: };
68:
69: static void fill_fab (), fill_rab ();
70: static int write_data ();
71:
72: extern char *start_of_data ();
73: extern int vms_out_initial; /* Defined in malloc.c */
74:
75: /* Maps in the data and alloc area from the map file.
76: */
77:
78: int
79: mapin_data (name)
80: char * name;
81: {
82: struct FAB fab;
83: struct RAB rab;
84: int status, size;
85: int inadr[2];
86: struct map_data map_data;
87:
88:
89: /* Open map file. */
90: fab = cc$rms_fab;
91: fab.fab$b_fac = FAB$M_BIO|FAB$M_GET;
92: fab.fab$l_fna = name;
93: fab.fab$b_fns = strlen (name);
94: status = sys$open (&fab);
95: if (status != RMS$_NORMAL)
96: {
97: printf ("Map file not available, running bare Emacs....\n");
98: return 0; /* Map file not available */
99: }
100: /* Connect the RAB block */
101: rab = cc$rms_rab;
102: rab.rab$l_fab = &fab;
103: rab.rab$b_rac = RAB$C_SEQ;
104: rab.rab$l_rop = RAB$M_BIO;
105: status = sys$connect (&rab);
106: if (status != RMS$_NORMAL)
107: lib$stop (status);
108: /* Read the header data */
109: rab.rab$l_ubf = (char *) &map_data;
110: rab.rab$w_usz = sizeof (map_data);
111: rab.rab$l_bkt = 0;
112: status = sys$read (&rab);
113: if (status != RMS$_NORMAL)
114: lib$stop (status);
115: status = sys$close (&fab);
116: if (status != RMS$_NORMAL)
117: lib$stop (status);
118: if (map_data.sdata != start_of_data ())
119: {
120: printf ("Start of data area has moved: cannot map in data.\n");
121: return 0;
122: }
123: if (map_data.edata != edata)
124: {
125: printf ("End of data area has moved: cannot map in data.\n");
126: return 0;
127: }
128: fab.fab$l_fop |= FAB$M_UFO;
129: status = sys$open (&fab);
130: if (status != RMS$_NORMAL)
131: lib$stop (status);
132: /* Map data area. */
133: inadr[0] = (int) map_data.sdata;
134: inadr[1] = (int) map_data.edata;
135: status = sys$crmpsc (inadr, 0, 0, SEC$M_CRF | SEC$M_WRT, 0, 0, 0,
136: fab.fab$l_stv, 0, map_data.datablk, 0, 0);
137: if (! (status & 1))
138: lib$stop (status);
139: }
140:
141: /* Writes the data and alloc area to the map file.
142: */
143: mapout_data (into)
144: char * into;
145: {
146: struct FAB fab;
147: struct RAB rab;
148: int status;
149: struct map_data map_data;
150: int datasize, msize;
151:
152: if (vms_out_initial)
153: {
154: error ("Out of initial allocation. Must rebuild emacs with more memory (VMS_ALLOCATION_SIZE).");
155: return 0;
156: }
157: map_data.sdata = start_of_data ();
158: map_data.edata = edata;
159: datasize = map_data.edata - map_data.sdata + 1;
160: map_data.datablk = 2 + (sizeof (map_data) + BLOCKSIZE - 1) / BLOCKSIZE;
161: /* Create map file. */
162: fab = cc$rms_fab;
163: fab.fab$b_fac = FAB$M_BIO|FAB$M_PUT;
164: fab.fab$l_fna = into;
165: fab.fab$b_fns = strlen (into);
166: fab.fab$l_fop = FAB$M_CBT;
167: fab.fab$b_org = FAB$C_SEQ;
168: fab.fab$b_rat = 0;
169: fab.fab$b_rfm = FAB$C_VAR;
170: fab.fab$l_alq = 1 + map_data.datablk +
171: ((datasize + BLOCKSIZE - 1) / BLOCKSIZE);
172: status = sys$create (&fab);
173: if (status != RMS$_NORMAL)
174: {
175: error ("Could not create map file");
176: return 0;
177: }
178: /* Connect the RAB block */
179: rab = cc$rms_rab;
180: rab.rab$l_fab = &fab;
181: rab.rab$b_rac = RAB$C_SEQ;
182: rab.rab$l_rop = RAB$M_BIO;
183: status = sys$connect (&rab);
184: if (status != RMS$_NORMAL)
185: {
186: error ("RMS connect to map file failed");
187: return 0;
188: }
189: /* Write the header */
190: rab.rab$l_rbf = (char *) &map_data;
191: rab.rab$w_rsz = sizeof (map_data);
192: status = sys$write (&rab);
193: if (status != RMS$_NORMAL)
194: {
195: error ("RMS write (header) to map file failed");
196: return 0;
197: }
198: if (! write_data (&rab, map_data.datablk, map_data.sdata, datasize))
199: return 0;
200: status = sys$close (&fab);
201: if (status != RMS$_NORMAL)
202: {
203: error ("RMS close on map file failed");
204: return 0;
205: }
206: return 1;
207: }
208:
209: static int
210: write_data (rab, firstblock, data, length)
211: struct RAB * rab;
212: char * data;
213: {
214: int status;
215:
216: rab->rab$l_bkt = firstblock;
217: while (length > 0)
218: {
219: rab->rab$l_rbf = data;
220: rab->rab$w_rsz = length > MAXWRITE ? MAXWRITE : length;
221: status = sys$write (rab, 0, 0);
222: if (status != RMS$_NORMAL)
223: {
224: error ("RMS write to map file failed");
225: return 0;
226: }
227: data = &data[MAXWRITE];
228: length -= MAXWRITE;
229: rab->rab$l_bkt = 0;
230: }
231: return 1;
232: } /* write_data */
233:
234: #endif /* VMS */
235:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.