~ubuntu-branches/ubuntu/utopic/simh/utopic

« back to all changes in this revision

Viewing changes to TOOLS/crossassemblers/macro11/mlb.c

  • Committer: Bazaar Package Importer
  • Author(s): Vince Mulhollon
  • Date: 2004-04-20 20:01:26 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040420200126-ehsuleda8xcgi51h
Tags: 3.2.0-1
New upstream 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Routines for reading from an RT-11 macro library (like SYSMAC.SML) */
 
2
 
 
3
/*
 
4
Copyright (c) 2001, Richard Krehbiel
 
5
All rights reserved.
 
6
 
 
7
Redistribution and use in source and binary forms, with or without
 
8
modification, are permitted provided that the following conditions are
 
9
met:
 
10
 
 
11
o Redistributions of source code must retain the above copyright
 
12
  notice, this list of conditions and the following disclaimer.
 
13
 
 
14
o Redistributions in binary form must reproduce the above copyright
 
15
  notice, this list of conditions and the following disclaimer in the
 
16
  documentation and/or other materials provided with the distribution.
 
17
 
 
18
o Neither the name of the copyright holder nor the names of its
 
19
  contributors may be used to endorse or promote products derived from
 
20
  this software without specific prior written permission.
 
21
 
 
22
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
23
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
24
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
25
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 
26
HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 
27
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 
28
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 
29
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 
30
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 
31
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 
32
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 
33
DAMAGE.
 
34
*/
 
35
 
 
36
#include <stdio.h>
 
37
#include <stddef.h>
 
38
#include <stdlib.h>
 
39
#include <string.h>
 
40
 
 
41
#include "rad50.h"
 
42
 
 
43
#include "stream2.h"
 
44
 
 
45
#include "mlb.h"
 
46
 
 
47
#include "macro11.h"
 
48
 
 
49
#include "util.h"
 
50
 
 
51
#define WORD(cp) ((*(cp) & 0xff) + ((*((cp)+1) & 0xff) << 8))
 
52
 
 
53
/* BYTEPOS calculates the byte position within the macro libray file.
 
54
   I use this to sort the entries by their start position, in order to
 
55
   be able to calculate the entries' sizes, which isn't actually
 
56
   stored in the directory. */
 
57
 
 
58
#define BYTEPOS(rec) ((WORD((rec)+4) & 32767) * 512 + (WORD((rec)+6) & 511))
 
59
 
 
60
extern FILE *lstfile;
 
61
 
 
62
/* compare_position is the qsort callback function that compares byte
 
63
   locations within the macro library */
 
64
static int compare_position(const void *arg1, const void *arg2)
 
65
{
 
66
        const char *c1 = arg1, *c2 = arg2;
 
67
 
 
68
        if(BYTEPOS(c1) < BYTEPOS(c2))
 
69
                return -1;
 
70
        if(BYTEPOS(c1) > BYTEPOS(c2))
 
71
                return 1;
 
72
        return 0;
 
73
}
 
74
 
 
75
 
 
76
/* trim removes trailing blanks from a string. */
 
77
static void trim(char *buf)
 
78
{
 
79
        char *cp = buf + strlen(buf);
 
80
        while(--cp >= buf && *cp == ' ')
 
81
                *cp = 0;
 
82
}
 
83
 
 
84
/* mlb_open opens a file which is given to be a macro library. */
 
85
/* Returns NULL on failure. */
 
86
 
 
87
MLB *mlb_open(char *name)
 
88
{
 
89
        MLB *mlb = memcheck(malloc(sizeof(MLB)));
 
90
        char *buff;
 
91
        unsigned entsize;
 
92
        unsigned nr_entries;
 
93
        unsigned start_block;
 
94
        int i;
 
95
 
 
96
        mlb->directory = NULL;
 
97
        
 
98
        mlb->fp = fopen(name, "rb");
 
99
        if(mlb->fp == NULL)
 
100
        {
 
101
                mlb_close(mlb);
 
102
                return NULL;
 
103
        }
 
104
 
 
105
        buff = memcheck(malloc(044));                   /* Size of MLB library header */
 
106
 
 
107
        if(fread(buff, 1, 044, mlb->fp) < 044)
 
108
        {
 
109
                mlb_close(mlb);
 
110
                free(buff);
 
111
                return NULL;
 
112
        }
 
113
 
 
114
        if(WORD(buff) != 01001)         /* Is this really a macro library? */
 
115
        {
 
116
                mlb_close(mlb);                 /* Nope. */
 
117
                return NULL;
 
118
        }
 
119
 
 
120
        entsize = WORD(buff + 032);     /* The size of each macro directory
 
121
                                                                   entry */
 
122
        nr_entries = WORD(buff + 036); /* The number of directory entries */
 
123
        start_block = WORD(buff + 034); /* The start RT-11 block of the
 
124
                                                                           directory */
 
125
 
 
126
        free(buff);                                     /* Done with that header. */
 
127
 
 
128
        /* Allocate a buffer for the disk directory */
 
129
        buff = memcheck(malloc(nr_entries * entsize));
 
130
        fseek(mlb->fp, start_block * 512, SEEK_SET); /* Go to the directory */
 
131
        
 
132
        /* Read the disk directory */
 
133
        if(fread(buff, entsize, nr_entries, mlb->fp) < nr_entries)
 
134
        {
 
135
                mlb_close(mlb);                 /* Sorry, read error. */
 
136
                free(buff);
 
137
                return NULL;
 
138
        }
 
139
 
 
140
        /* Shift occupied directory entries to the front of the array
 
141
           before sorting */
 
142
 
 
143
        {
 
144
                int j;
 
145
                for(i = 0, j = nr_entries; i < j; i++)
 
146
                {
 
147
                        char *ent1, *ent2;
 
148
                        ent1 = buff + (i * entsize);
 
149
                        /* Unused entries have 0177777 0177777 for the RAD50 name,
 
150
                           which is not legal RAD50. */
 
151
                        if(WORD(ent1) == 0177777 &&
 
152
                                WORD(ent1 + 2) == 0177777)
 
153
                        {
 
154
                                while(--j > i &&
 
155
                                        (ent2 = buff + (j * entsize),
 
156
                                        WORD(ent2) == 0177777 &&
 
157
                                        WORD(ent2+2) == 0177777))
 
158
                                        ;
 
159
                                if(j <= i)
 
160
                                        break;          /* All done. */
 
161
                                memcpy(ent1, ent2, entsize);    /* Move used entry
 
162
                                                                                                   into unused entry's
 
163
                                                                                                   space */
 
164
                                memset(ent2, 0377, entsize);    /* Mark entry unused */ 
 
165
                        }
 
166
                }
 
167
 
 
168
                /* Now i contains the actual number of entries. */
 
169
 
 
170
                mlb->nentries = i;
 
171
 
 
172
                /* Sort the array by file position */
 
173
 
 
174
                qsort(buff, i, entsize, compare_position);
 
175
 
 
176
                /* Now, allocate my in-memory directory */
 
177
                mlb->directory = memcheck(malloc(sizeof(MLBENT) * mlb->nentries));
 
178
                memset(mlb->directory, 0, sizeof(MLBENT) * mlb->nentries);
 
179
 
 
180
                /* Build in-memory directory */
 
181
                for(j = 0; j < i; j++)
 
182
                {
 
183
                        char radname[16];
 
184
                        char *ent;
 
185
 
 
186
                        ent = buff + (j * entsize);
 
187
 
 
188
                        unrad50(WORD(ent), radname);
 
189
                        unrad50(WORD(ent+2), radname+3);
 
190
                        radname[6] = 0;
 
191
 
 
192
                        trim(radname);
 
193
 
 
194
                        mlb->directory[j].label = memcheck(strdup(radname));
 
195
                        mlb->directory[j].position = BYTEPOS(ent);
 
196
                        if(j < i-1)
 
197
                        {
 
198
                                mlb->directory[j].length =
 
199
                                        BYTEPOS(ent + entsize) - BYTEPOS(ent);
 
200
                        }
 
201
                        else
 
202
                        {
 
203
                                unsigned long max;
 
204
                                char c;
 
205
                                fseek(mlb->fp, 0, SEEK_END);
 
206
                                max = ftell(mlb->fp);
 
207
                                /* Look for last non-zero */
 
208
                                do
 
209
                                {
 
210
                                        max--;
 
211
                                        fseek(mlb->fp, max, SEEK_SET);
 
212
                                        c = fgetc(mlb->fp);
 
213
                                } while(max > 0 && c == 0);
 
214
                                max++;
 
215
                                mlb->directory[j].length = max - BYTEPOS(ent);
 
216
                        }
 
217
                }
 
218
 
 
219
                free(buff);
 
220
 
 
221
        }
 
222
 
 
223
        /* Done.  Return the struct that represents the opened MLB. */
 
224
        return mlb;
 
225
}
 
226
 
 
227
/* mlb_close discards MLB and closes the file. */
 
228
void mlb_close(MLB *mlb)
 
229
{
 
230
        if(mlb)
 
231
        {
 
232
                int i;
 
233
                if(mlb->directory)
 
234
                {
 
235
                        for(i = 0; i < mlb->nentries; i++)
 
236
                        {
 
237
                                if(mlb->directory[i].label)
 
238
                                        free(mlb->directory[i].label);
 
239
                        }
 
240
                        free(mlb->directory);
 
241
                }
 
242
                if(mlb->fp)
 
243
                        fclose(mlb->fp);
 
244
 
 
245
                free(mlb);
 
246
        }
 
247
}
 
248
 
 
249
/* mlb_entry returns a BUFFER containing the specified entry from the
 
250
   macro library, or NULL if not found. */
 
251
 
 
252
BUFFER *mlb_entry(MLB *mlb, char *name)
 
253
{
 
254
        int i;
 
255
        MLBENT *ent;
 
256
        BUFFER *buf;
 
257
        char *bp;
 
258
        int c;
 
259
 
 
260
        for(i = 0; i < mlb->nentries; i++)
 
261
        {
 
262
                ent = &mlb->directory[i];
 
263
                if(strcmp(mlb->directory[i].label, name) == 0)
 
264
                        break;
 
265
        }
 
266
 
 
267
        if(i >= mlb->nentries)
 
268
                return NULL;
 
269
 
 
270
        /* Allocate a buffer to hold the text */
 
271
        buf = new_buffer();
 
272
        buffer_resize(buf, ent->length+1); /* Make it large enough */
 
273
        bp = buf->buffer;
 
274
 
 
275
        fseek(mlb->fp, ent->position, SEEK_SET);
 
276
 
 
277
        for(i = 0; i < ent->length; i++)
 
278
        {
 
279
                c = fgetc(mlb->fp);             /* Get macro byte */
 
280
                if(c == '\r' || c == 0) /* If it's a carriage return or 0,
 
281
                                                                   discard it. */
 
282
                        continue;
 
283
                *bp++ = c;
 
284
        }
 
285
        *bp++ = 0;                                      /* Store trailing 0 delim */
 
286
 
 
287
        /* Now resize that buffer to the length actually read. */
 
288
        buffer_resize(buf, bp - buf->buffer);
 
289
 
 
290
        return buf;
 
291
}
 
292
 
 
293
/* mlb_extract - walk thru a macro library and store it's contents
 
294
   into files in the current directory.
 
295
 
 
296
   See, I had decided not to bother writing macro library maintenance
 
297
   tools, since the user can call macros directly from the file
 
298
   system.  But if you've already got a macro library without the
 
299
   sources, you can use this to extract the entries and maintain them
 
300
   in the file system from thence forward.
 
301
*/
 
302
 
 
303
void mlb_extract(MLB *mlb)
 
304
{
 
305
        int i;
 
306
        FILE *fp;
 
307
        BUFFER *buf;
 
308
 
 
309
        for(i = 0; i < mlb->nentries; i++)
 
310
        {
 
311
                char name[32];
 
312
                buf = mlb_entry(mlb, mlb->directory[i].label);
 
313
                sprintf(name, "%s.MAC", mlb->directory[i].label);
 
314
                fp = fopen(name, "w");
 
315
                fwrite(buf->buffer, 1, buf->length, fp);
 
316
                fclose(fp);
 
317
                buffer_free(buf);
 
318
        }
 
319
}