Remove old version.

This commit is contained in:
Olaf Seibert 2016-02-21 11:03:27 +01:00
parent 404a7e726d
commit 0cb8000e5f
21 changed files with 0 additions and 9727 deletions

View File

@ -1,12 +0,0 @@
15-July-2001
version 0.2
removed references to snprintf from dumpobj.c and
mlb.c for portability
fixed a type cast warning in dumpobj.c compare_gsdlines
Removed strcasecmp from macro11.c for portability
Removed references to wnewmem.c from makefile (isn't needed)
makefile more compatible with non-gnu make and compiler
main prints version 0.2
14-July-2001
First release, version 0.1.

View File

@ -1,677 +0,0 @@
/* Dump and interpret an object file. */
/*
Copyright (c) 2001, Richard Krehbiel
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
o Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
o Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
o Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include "rad50.h"
#include "util.h"
#define WORD(cp) ((*(cp) & 0xff) + ((*((cp)+1) & 0xff) << 8))
int psectid = 0;
char *psects[256];
FILE *bin = NULL;
int badbin = 0;
int xferad = 1;
char *readrec(FILE *fp, int *len)
{
int c, i;
int chksum;
char *buf;
chksum = 0;
while(c = fgetc(fp), c != EOF && c == 0)
;
if(c == EOF)
return NULL;
if(c != 1)
{
fprintf(stderr, "Improperly formatted OBJ file (1)\n");
return NULL; // Not a properly formatted file.
}
chksum -= c;
c = fgetc(fp);
if(c != 0)
{
fprintf(stderr, "Improperly formatted OBJ file (2)\n");
return NULL; // Not properly formatted
}
chksum -= c; // even though for 0 the checksum isn't changed...
c = fgetc(fp);
if(c == EOF)
{
fprintf(stderr, "Improperly formatted OBJ file (3)\n");
return NULL;
}
*len = c;
chksum -= c;
c = fgetc(fp);
if(c == EOF)
{
fprintf(stderr, "Improperly formatted OBJ file (4)\n");
return NULL;
}
*len += (c << 8);
chksum -= c;
*len -= 4; // Subtract header and length bytes from length
if(*len < 0)
{
fprintf(stderr, "Improperly formatted OBJ file (5)\n");
return NULL;
}
buf = malloc(*len);
if(buf == NULL)
{
fprintf(stderr, "Out of memory allocating %d bytes\n", *len);
return NULL; // Bad alloc
}
i = fread(buf, 1, *len, fp);
if(i < *len)
{
free(buf);
fprintf(stderr, "Improperly formatted OBJ file (6)\n");
return NULL;
}
for(i = 0; i < *len; i++)
{
chksum -= (buf[i] & 0xff);
}
c = fgetc(fp);
c &= 0xff;
chksum &= 0xff;
if(c != chksum)
{
free(buf);
fprintf(stderr, "Bad record checksum, "
"calculated=%d, recorded=%d\n", chksum, c);
return NULL;
}
return buf;
}
void dump_bytes(char *buf, int len)
{
int i, j;
for(i = 0; i < len; i += 8)
{
printf("\t%3.3o: ", i);
for(j = i; j < len && j < i+8; j++)
{
printf("%3.3o ", buf[j] & 0xff);
}
printf("%*s", (i+8 - j) * 4, "");
for(j = i; j < len && j < i+8; j++)
{
int c = buf[j] & 0xff;
if(!isprint(c))
c = '.';
putchar(c);
}
putchar('\n');
}
}
void dump_words(unsigned addr, char *buf, int len)
{
int i, j;
for(i = 0; i < len; i += 8)
{
printf("\t%6.6o: ", addr);
for(j = i; j < len && j < i+8; j += 2)
{
if(len - j >= 2)
{
unsigned word = WORD(buf + j);
printf("%6.6o ", word);
}
else
printf("%3.3o ", buf[j] & 0xff);
}
printf("%*s", (i+8 - j) * 7 / 2, "");
for(j = i; j < len && j < i+8; j++)
{
int c = buf[j] & 0xff;
if(!isprint(c))
c = '.';
putchar(c);
}
putchar('\n');
addr += 8;
}
}
void dump_bin(unsigned addr, char *buf, int len)
{
int chksum; /* Checksum is negative sum of all
bytes including header and length */
int FBR_LEAD1 = 1, FBR_LEAD2 = 0;
int i;
unsigned hdrlen = len + 6;
for(i = 0; i < 8; i++) fputc (0, bin);
chksum = 0;
if(fputc(FBR_LEAD1, bin) == EOF) return; /* All recs begin with 1,0 */
chksum -= FBR_LEAD1;
if(fputc(FBR_LEAD2, bin) == EOF) return;
chksum -= FBR_LEAD2;
i = hdrlen & 0xff; /* length, lsb */
chksum -= i;
if(fputc(i, bin) == EOF) return;
i = (hdrlen >> 8) & 0xff; /* length, msb */
chksum -= i;
if(fputc(i, bin) == EOF) return;
i = addr & 0xff; /* origin, msb */
chksum -= i;
if(fputc(i, bin) == EOF) return;
i = (addr >> 8) & 0xff; /* origin, lsb */
chksum -= i;
if(fputc(i, bin) == EOF) return;
if ((len == 0) || (buf == NULL)) return; /* end of tape block */
i = fwrite(buf, 1, len, bin);
if(i < len) return;
while(len > 0) /* All the data bytes */
{
chksum -= *buf++ & 0xff;
len--;
}
chksum &= 0xff;
fputc(chksum, bin); /* Followed by the checksum byte */
return; /* Worked okay. */
}
void trim(char *buf)
{
char *cp;
for(cp = buf + strlen(buf); cp > buf; cp--)
{
if(cp[-1] != ' ')
break;
}
*cp = 0;
}
char **all_gsds = NULL;
int nr_gsds = 0;
int gsdsize = 0;
void add_gsdline(char *line)
{
if(nr_gsds >= gsdsize || all_gsds == NULL)
{
gsdsize += 128;
all_gsds = realloc(all_gsds, gsdsize * sizeof(char *));
if(all_gsds == NULL)
{
fprintf(stderr, "Out of memory\n");
exit(EXIT_FAILURE);
}
}
all_gsds[nr_gsds++] = line;
}
void got_gsd(char *cp, int len)
{
int i;
char *gsdline;
for(i = 2; i < len; i += 8)
{
char name[8];
unsigned value;
unsigned flags;
gsdline = malloc(256);
if(gsdline == NULL)
{
fprintf(stderr, "Out of memory\n");
exit(EXIT_FAILURE);
}
unrad50(WORD(cp+i), name);
unrad50(WORD(cp+i+2), name+3);
name[6] = 0;
value = WORD(cp+i+6);
flags = cp[i+4] & 0xff;
switch(cp[i+5] & 0xff)
{
case 0:
sprintf(gsdline,
"\tMODNAME %s=%o flags=%o\n", name, value, flags);
break;
case 1:
sprintf(gsdline,
"\tCSECT %s=%o flags=%o\n", name, value, flags);
break;
case 2:
sprintf(gsdline,
"\tISD %s=%o flags=%o\n", name, value, flags);
break;
case 3:
sprintf(gsdline,
"\tXFER %s=%o flags=%o\n", name, value, flags);
xferad = value;
break;
case 4:
sprintf(gsdline,
"\tGLOBAL %s=%o %s flags=%o\n",
name, value, cp[i+4] & 8 ? "DEF" : "REF", flags);
break;
case 5:
sprintf(gsdline,
"\tPSECT %s=%o flags=%o\n", name, value, flags);
psects[psectid] = strdup(name);
trim(psects[psectid++]);
break;
case 6:
sprintf(gsdline,
"\tIDENT %s=%o flags=%o\n", name, value, flags);
break;
case 7:
sprintf(gsdline,
"\tVSECT %s=%o flags=%o\n", name, value, flags);
break;
default:
sprintf(gsdline,
"\t***Unknown GSD entry type %d flags=%o\n",
cp[i+5] & 0xff, flags);
break;
}
gsdline = realloc(gsdline, strlen(gsdline)+1);
add_gsdline(gsdline);
}
}
int compare_gsdlines(const void *p1, const void *p2)
{
const char * const *l1 = p1, * const *l2 = p2;
return strcmp(*l1, *l2);
}
void got_endgsd(char *cp, int len)
{
int i;
qsort(all_gsds, nr_gsds, sizeof(char *), compare_gsdlines);
printf("GSD:\n");
for(i = 0; i < nr_gsds; i++)
{
fputs(all_gsds[i], stdout);
free(all_gsds[i]);
}
printf("ENDGSD\n");
free(all_gsds);
}
unsigned last_text_addr = 0;
void got_text(char *cp, int len)
{
unsigned addr = WORD(cp+2);
last_text_addr = addr;
printf("TEXT ADDR=%o LEN=%o\n", last_text_addr, len-4);
dump_words(last_text_addr, cp+4, len-4);
if (bin) dump_bin(last_text_addr, cp+4, len-4);
}
void rad50name(char *cp, char *name)
{
unrad50(WORD(cp), name);
unrad50(WORD(cp+2), name+3);
name[6] = 0;
trim(name);
}
void got_rld(char *cp, int len)
{
int i;
printf("RLD\n");
for(i = 2; i < len;)
{
unsigned addr;
unsigned word;
unsigned disp = cp[i+1] & 0xff;
char name[8];
char *byte;
addr = last_text_addr + disp - 4;
byte = "";
if(cp[i] & 0200)
byte = " byte";
switch(cp[i] & 0x7f)
{
case 01:
printf("\tInternal%s %o=%o\n", byte, addr, WORD(cp+i+2));
i += 4;
break;
case 02:
rad50name(cp+i+2, name);
printf("\tGlobal%s %o=%s\n", byte, addr, name);
i += 6;
break;
case 03:
printf("\tInternal displaced%s %o=%o\n", byte, addr, WORD(cp+i+2));
i += 4;
badbin = 1;
break;
case 04:
rad50name(cp+i+2, name);
printf("\tGlobal displaced%s %o=%s\n", byte, addr, name);
i += 6;
badbin = 1;
break;
case 05:
rad50name(cp+i+2, name);
word = WORD(cp+i+6);
printf("\tGlobal plus offset%s %o=%s+%o\n",
byte, addr, name, word);
i += 8;
badbin = 1;
break;
case 06:
rad50name(cp+i+2, name);
word = WORD(cp+i+6);
printf("\tGlobal plus offset displaced%s %o=%s+%o\n",
byte, addr, name, word);
i += 8;
badbin = 1;
break;
case 07:
rad50name(cp+i+2, name);
word = WORD(cp+i+6);
printf("\tLocation counter definition %s+%o\n",
name, word);
i += 8;
last_text_addr = word;
break;
case 010:
word = WORD(cp+i+2);
printf("\tLocation counter modification %o\n", word);
i += 4;
last_text_addr = word;
break;
case 011:
printf("\t.LIMIT %o\n", addr);
i += 2;
break;
case 012:
rad50name(cp+i+2, name);
printf("\tPSECT%s %o=%s\n", byte, addr, name);
i += 6;
badbin = 1;
break;
case 014:
rad50name(cp+i+2, name);
printf("\tPSECT displaced%s %o=%s+%o\n", byte, addr, name, word);
i += 6;
badbin = 1;
break;
case 015:
rad50name(cp+i+2, name);
word = WORD(cp+i+6);
printf("\tPSECT plus offset%s %o=%s+%o\n",
byte, addr, name, word);
i += 8;
badbin = 1;
break;
case 016:
rad50name(cp+i+2, name);
word = WORD(cp+i+6);
printf("\tPSECT plus offset displaced%s %o=%s+%o\n",
byte, addr, name, word);
i += 8;
badbin = 1;
break;
case 017:
badbin = 1;
printf("\tComplex%s %o=", byte, addr);
i += 2;
{
char *xp = cp + i;
int size;
for(;;)
{
size = 1;
switch(*xp)
{
case 000:
fputs("nop ", stdout); break;
case 001:
fputs("+ ", stdout); break;
case 002:
fputs("- ", stdout); break;
case 003:
fputs("* ", stdout); break;
case 004:
fputs("/ ", stdout); break;
case 005:
fputs("& ", stdout); break;
case 006:
fputs("! ", stdout); break;
case 010:
fputs("neg ", stdout); break;
case 011:
fputs("^C ", stdout); break;
case 012:
fputs("store ", stdout); break;
case 013:
fputs("store{disp} ", stdout); break;
case 016:
rad50name(xp+1, name);
printf("%s ", name);
size = 5;
break;
case 017:
assert((xp[1] & 0377) < psectid);
printf("%s:%o ",
psects[xp[1] & 0377],
WORD(xp+2));
size = 4;
break;
case 020:
printf("%o ", WORD(xp+1));
size = 3;
break;
default:
printf("**UNKNOWN COMPLEX CODE** %o\n", *xp & 0377);
return;
}
i += size;
if(*xp == 012 || *xp == 013)
break;
xp += size;
}
fputc('\n', stdout);
break;
}
default:
printf("\t***Unknown RLD code %o\n", cp[i] & 0xff);
return;
}
}
}
void got_isd(char *cp, int len)
{
printf("ISD len=%o\n");
}
void got_endmod(char *cp, int len)
{
printf("ENDMOD\n");
}
void got_libhdr(char *cp, int len)
{
printf("LIBHDR\n");
}
void got_libend(char *cp, int len)
{
printf("LIBEND\n");
}
int main(int argc, char *argv[])
{
int len;
FILE *fp;
char *cp;
fp = fopen(argv[1], "rb");
if(fp == NULL)
return EXIT_FAILURE;
if(argv[2])
{
bin = fopen(argv[2], "wb");
if(bin == NULL) return EXIT_FAILURE;
}
while((cp = readrec(fp, &len)) != NULL)
{
switch(cp[0] & 0xff)
{
case 1:
got_gsd(cp, len);
break;
case 2:
got_endgsd(cp, len);
break;
case 3:
got_text(cp, len);
break;
case 4:
got_rld(cp, len);
break;
case 5:
got_isd(cp, len);
break;
case 6:
got_endmod(cp, len);
break;
case 7:
got_libhdr(cp, len);
break;
case 8:
got_libend(cp, len);
break;
default:
printf("Unknown record type %d\n", cp[0] & 0xff);
break;
}
free(cp);
}
if (bin)
{ dump_bin (xferad, NULL, 0);
fclose (bin);
if (badbin) fprintf (stderr, "Probable errors in binary file\n");
}
fclose (fp);
return EXIT_SUCCESS;
}

View File

@ -1,114 +0,0 @@
# Microsoft Developer Studio Project File - Name="dumpobj" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=dumpobj - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "dumpobj.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "dumpobj.mak" CFG="dumpobj - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "dumpobj - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "dumpobj - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""$/macro11", BAAAAAAA"
# PROP Scc_LocalPath "."
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "dumpobj - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "dumpobj___Release"
# PROP Intermediate_Dir "dumpobj___Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "dumpobj - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "dumpobj___Debug"
# PROP Intermediate_Dir "dumpobj___Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "dumpobj - Win32 Release"
# Name "dumpobj - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\dumpobj.c
# End Source File
# Begin Source File
SOURCE=.\Rad50.c
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\Rad50.h
# End Source File
# Begin Source File
SOURCE=.\util.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

View File

@ -1,30 +0,0 @@
Copyright (c) 2001, Richard Krehbiel
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
o Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
o Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
o Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.

File diff suppressed because it is too large Load Diff

View File

@ -1,180 +0,0 @@
# Microsoft Developer Studio Project File - Name="macro11" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=macro11 - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "macro11.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "macro11.mak" CFG="macro11 - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "macro11 - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "macro11 - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""$/macro11", BAAAAAAA"
# PROP Scc_LocalPath "."
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "macro11 - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# SUBTRACT LINK32 /profile
# Begin Special Build Tool
TargetPath=.\Release\macro11.exe
SOURCE="$(InputPath)"
PostBuild_Cmds=copy $(TargetPath) c:\bin
# End Special Build Tool
!ELSEIF "$(CFG)" == "macro11 - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "MEM_DEBUG" /FR /FD /GZ /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# SUBTRACT LINK32 /profile
# Begin Special Build Tool
TargetPath=.\Debug\macro11.exe
SOURCE="$(InputPath)"
PostBuild_Cmds=copy $(TargetPath) c:\bin
# End Special Build Tool
!ENDIF
# Begin Target
# Name "macro11 - Win32 Release"
# Name "macro11 - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\macro11.c
# End Source File
# Begin Source File
SOURCE=.\mlb.c
# End Source File
# Begin Source File
SOURCE=.\object.c
# End Source File
# Begin Source File
SOURCE=.\rad50.c
# End Source File
# Begin Source File
SOURCE=.\stream2.c
# End Source File
# Begin Source File
SOURCE=.\util.c
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\macro11.h
# End Source File
# Begin Source File
SOURCE=.\mlb.h
# End Source File
# Begin Source File
SOURCE=.\object.h
# End Source File
# Begin Source File
SOURCE=.\Rad50.h
# End Source File
# Begin Source File
SOURCE=.\stream2.h
# End Source File
# Begin Source File
SOURCE=.\util.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# Begin Source File
SOURCE=.\Changes
# End Source File
# Begin Source File
SOURCE=.\License
# End Source File
# Begin Source File
SOURCE=.\Makefile
# End Source File
# Begin Source File
SOURCE=.\Readme
# End Source File
# Begin Source File
SOURCE=.\Todo
# End Source File
# End Target
# End Project

View File

@ -1,53 +0,0 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "dumpobj"=.\dumpobj.dsp - Package Owner=<4>
Package=<5>
{{{
begin source code control
"$/macro11", BAAAAAAA
.
end source code control
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "macro11"=.\macro11.dsp - Package Owner=<4>
Package=<5>
{{{
begin source code control
"$/macro11", BAAAAAAA
.
end source code control
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
begin source code control
"$/macro11", BAAAAAAA
.
end source code control
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@ -1,39 +0,0 @@
#ifndef MACRO11_H
#define MACRO11_H
/*
Copyright (c) 2001, Richard Krehbiel
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
o Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
o Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
o Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/
extern void *memcheck(void *p);
#endif

View File

@ -1,38 +0,0 @@
CFLAGS = -O -g
MACRO11_SRCS = macro11.c mlb.c object.c stream2.c util.c rad50.c
MACRO11_OBJS = $(MACRO11_SRCS:.c=.o)
DUMPOBJ_SRCS = dumpobj.c rad50.c
DUMPOBJ_OBJS = $(DUMPOBJ_SRCS:.c=.o)
ALL_SRCS = $(MACRO11_SRCS) $(DUMPOBJ_SRCS)
all: macro11 dumpobj
tags: macro11 dumpobj
ctags *.c *.h
macro11: $(MACRO11_OBJS) makefile
$(CC) $(CFLAGS) -o macro11 $(MACRO11_OBJS) -lm
dumpobj: $(DUMPOBJ_OBJS) makefile
$(CC) $(CFLAGS) -o dumpobj $(DUMPOBJ_OBJS)
MACRO11_OBJS: makefile
DUMPOBJ_OBJS: makefile
clean:
-rm -f $(MACRO11_OBJS) $(DUMPOBJ_OBJS) macro11 dumpobj
macro11.o: macro11.c macro11.h rad50.h object.h stream2.h \
mlb.h util.h
mlb.o: mlb.c rad50.h stream2.h mlb.h macro11.h util.h
object.o: object.c rad50.h object.h
stream2.o: stream2.c macro11.h stream2.h
util.o: util.c util.h
rad50.o: rad50.c rad50.h
dumpobj.o: dumpobj.c rad50.h util.h
rad50.o: rad50.c rad50.h

View File

@ -1,319 +0,0 @@
/* Routines for reading from an RT-11 macro library (like SYSMAC.SML) */
/*
Copyright (c) 2001, Richard Krehbiel
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
o Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
o Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
o Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "rad50.h"
#include "stream2.h"
#include "mlb.h"
#include "macro11.h"
#include "util.h"
#define WORD(cp) ((*(cp) & 0xff) + ((*((cp)+1) & 0xff) << 8))
/* BYTEPOS calculates the byte position within the macro libray file.
I use this to sort the entries by their start position, in order to
be able to calculate the entries' sizes, which isn't actually
stored in the directory. */
#define BYTEPOS(rec) ((WORD((rec)+4) & 32767) * 512 + (WORD((rec)+6) & 511))
extern FILE *lstfile;
/* compare_position is the qsort callback function that compares byte
locations within the macro library */
static int compare_position(const void *arg1, const void *arg2)
{
const char *c1 = arg1, *c2 = arg2;
if(BYTEPOS(c1) < BYTEPOS(c2))
return -1;
if(BYTEPOS(c1) > BYTEPOS(c2))
return 1;
return 0;
}
/* trim removes trailing blanks from a string. */
static void trim(char *buf)
{
char *cp = buf + strlen(buf);
while(--cp >= buf && *cp == ' ')
*cp = 0;
}
/* mlb_open opens a file which is given to be a macro library. */
/* Returns NULL on failure. */
MLB *mlb_open(char *name)
{
MLB *mlb = memcheck(malloc(sizeof(MLB)));
char *buff;
unsigned entsize;
unsigned nr_entries;
unsigned start_block;
int i;
mlb->directory = NULL;
mlb->fp = fopen(name, "rb");
if(mlb->fp == NULL)
{
mlb_close(mlb);
return NULL;
}
buff = memcheck(malloc(044)); /* Size of MLB library header */
if(fread(buff, 1, 044, mlb->fp) < 044)
{
mlb_close(mlb);
free(buff);
return NULL;
}
if(WORD(buff) != 01001) /* Is this really a macro library? */
{
mlb_close(mlb); /* Nope. */
return NULL;
}
entsize = WORD(buff + 032); /* The size of each macro directory
entry */
nr_entries = WORD(buff + 036); /* The number of directory entries */
start_block = WORD(buff + 034); /* The start RT-11 block of the
directory */
free(buff); /* Done with that header. */
/* Allocate a buffer for the disk directory */
buff = memcheck(malloc(nr_entries * entsize));
fseek(mlb->fp, start_block * 512, SEEK_SET); /* Go to the directory */
/* Read the disk directory */
if(fread(buff, entsize, nr_entries, mlb->fp) < nr_entries)
{
mlb_close(mlb); /* Sorry, read error. */
free(buff);
return NULL;
}
/* Shift occupied directory entries to the front of the array
before sorting */
{
int j;
for(i = 0, j = nr_entries; i < j; i++)
{
char *ent1, *ent2;
ent1 = buff + (i * entsize);
/* Unused entries have 0177777 0177777 for the RAD50 name,
which is not legal RAD50. */
if(WORD(ent1) == 0177777 &&
WORD(ent1 + 2) == 0177777)
{
while(--j > i &&
(ent2 = buff + (j * entsize),
WORD(ent2) == 0177777 &&
WORD(ent2+2) == 0177777))
;
if(j <= i)
break; /* All done. */
memcpy(ent1, ent2, entsize); /* Move used entry
into unused entry's
space */
memset(ent2, 0377, entsize); /* Mark entry unused */
}
}
/* Now i contains the actual number of entries. */
mlb->nentries = i;
/* Sort the array by file position */
qsort(buff, i, entsize, compare_position);
/* Now, allocate my in-memory directory */
mlb->directory = memcheck(malloc(sizeof(MLBENT) * mlb->nentries));
memset(mlb->directory, 0, sizeof(MLBENT) * mlb->nentries);
/* Build in-memory directory */
for(j = 0; j < i; j++)
{
char radname[16];
char *ent;
ent = buff + (j * entsize);
unrad50(WORD(ent), radname);
unrad50(WORD(ent+2), radname+3);
radname[6] = 0;
trim(radname);
mlb->directory[j].label = memcheck(strdup(radname));
mlb->directory[j].position = BYTEPOS(ent);
if(j < i-1)
{
mlb->directory[j].length =
BYTEPOS(ent + entsize) - BYTEPOS(ent);
}
else
{
unsigned long max;
char c;
fseek(mlb->fp, 0, SEEK_END);
max = ftell(mlb->fp);
/* Look for last non-zero */
do
{
max--;
fseek(mlb->fp, max, SEEK_SET);
c = fgetc(mlb->fp);
} while(max > 0 && c == 0);
max++;
mlb->directory[j].length = max - BYTEPOS(ent);
}
}
free(buff);
}
/* Done. Return the struct that represents the opened MLB. */
return mlb;
}
/* mlb_close discards MLB and closes the file. */
void mlb_close(MLB *mlb)
{
if(mlb)
{
int i;
if(mlb->directory)
{
for(i = 0; i < mlb->nentries; i++)
{
if(mlb->directory[i].label)
free(mlb->directory[i].label);
}
free(mlb->directory);
}
if(mlb->fp)
fclose(mlb->fp);
free(mlb);
}
}
/* mlb_entry returns a BUFFER containing the specified entry from the
macro library, or NULL if not found. */
BUFFER *mlb_entry(MLB *mlb, char *name)
{
int i;
MLBENT *ent;
BUFFER *buf;
char *bp;
int c;
for(i = 0; i < mlb->nentries; i++)
{
ent = &mlb->directory[i];
if(strcmp(mlb->directory[i].label, name) == 0)
break;
}
if(i >= mlb->nentries)
return NULL;
/* Allocate a buffer to hold the text */
buf = new_buffer();
buffer_resize(buf, ent->length+1); /* Make it large enough */
bp = buf->buffer;
fseek(mlb->fp, ent->position, SEEK_SET);
for(i = 0; i < ent->length; i++)
{
c = fgetc(mlb->fp); /* Get macro byte */
if(c == '\r' || c == 0) /* If it's a carriage return or 0,
discard it. */
continue;
*bp++ = c;
}
*bp++ = 0; /* Store trailing 0 delim */
/* Now resize that buffer to the length actually read. */
buffer_resize(buf, bp - buf->buffer);
return buf;
}
/* mlb_extract - walk thru a macro library and store it's contents
into files in the current directory.
See, I had decided not to bother writing macro library maintenance
tools, since the user can call macros directly from the file
system. But if you've already got a macro library without the
sources, you can use this to extract the entries and maintain them
in the file system from thence forward.
*/
void mlb_extract(MLB *mlb)
{
int i;
FILE *fp;
BUFFER *buf;
for(i = 0; i < mlb->nentries; i++)
{
char name[32];
buf = mlb_entry(mlb, mlb->directory[i].label);
sprintf(name, "%s.MAC", mlb->directory[i].label);
fp = fopen(name, "w");
fwrite(buf->buffer, 1, buf->length, fp);
fclose(fp);
buffer_free(buf);
}
}

View File

@ -1,62 +0,0 @@
#ifndef MLB_H
#define MLB_H
/*
Copyright (c) 2001, Richard Krehbiel
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
o Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
o Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
o Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/
#include "stream2.h"
/* Routines to open and read entries from a macro library */
typedef struct mlbent
{
char *label;
unsigned long position;
int length;
} MLBENT;
typedef struct mlb
{
FILE *fp;
MLBENT *directory;
int nentries;
} MLB;
extern MLB *mlb_open(char *name);
extern BUFFER *mlb_entry(MLB *mlb, char *name);
extern void mlb_close(MLB *mlb);
extern void mlb_extract(MLB *mlb);
#endif /* MLB_H */

View File

@ -1,861 +0,0 @@
/*
object.c - writes RT-11 compatible .OBJ files.
Ref: RT-11 Software Support Manual, File Formats.
*/
/*
Copyright (c) 2001, Richard Krehbiel
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
o Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
o Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
o Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "rad50.h"
#include "object.h"
#include "macro11.h"
/*
writerec writes "formatted binary records."
Each is preceeded by any number of 0 bytes, begins with a 1,0 pair,
followed by 2 byte length, followed by data, followed by 1 byte
negative checksum.
*/
static int writerec(FILE *fp, char *data, int len)
{
int chksum; /* Checksum is negative sum of all
bytes including header and length */
int i;
unsigned hdrlen = len + 4;
if(fp == NULL)
return 1; /* Silently ignore this attempt to write. */
chksum = 0;
if(fputc(FBR_LEAD1, fp) == EOF) /* All recs begin with 1,0 */
return 0;
chksum -= FBR_LEAD1;
if(fputc(FBR_LEAD2, fp) == EOF)
return 0;
chksum -= FBR_LEAD2;
i = hdrlen & 0xff; /* length, lsb */
chksum -= i;
if(fputc(i, fp) == EOF)
return 0;
i = (hdrlen >> 8) & 0xff; /* length, msb */
chksum -= i;
if(fputc(i, fp) == EOF)
return 0;
i = fwrite(data, 1, len, fp);
if(i < len)
return 0;
while(len > 0) /* All the data bytes */
{
chksum -= *data++ & 0xff;
len--;
}
chksum &= 0xff;
fputc(chksum, fp); /* Followed by the checksum byte */
return 1; /* Worked okay. */
}
/* gsd_init - prepare a GSD prior to writing GSD records */
void gsd_init(GSD *gsd, FILE *fp)
{
gsd->fp = fp;
gsd->buf[0] = OBJ_GSD; /* GSD records start with 1,0 */
gsd->buf[1] = 0;
gsd->offset = 2; /* Offset for further additions */
}
/* gsd_flush - write buffered GSD records */
int gsd_flush(GSD *gsd)
{
if(gsd->offset > 2)
{
if(!writerec(gsd->fp, gsd->buf, gsd->offset))
return 0;
gsd_init(gsd, gsd->fp);
}
return 1;
}
/* gsd_write - buffers a GSD record */
/* All GSD entries have the following 8 byte format: */
/* 4 bytes RAD50 name */
/* 1 byte flags */
/* 1 byte type */
/* 2 bytes value */
static int gsd_write(GSD *gsd, char *name, int flags,
int type, int value)
{
char *cp;
unsigned radtbl[2];
if(gsd->offset > sizeof(gsd->buf) - 8)
{
if(!gsd_flush(gsd))
return 0;
}
rad50x2(name, radtbl);
cp = gsd->buf + gsd->offset;
*cp++ = radtbl[0] & 0xff;
*cp++ = (radtbl[0] >> 8) & 0xff;
*cp++ = radtbl[1] & 0xff;
*cp++ = (radtbl[1] >> 8) & 0xff;
*cp++ = flags;
*cp++ = type;
*cp++ = value & 0xff;
*cp = (value >> 8) & 0xff;
gsd->offset += 8;
return 1;
}
/* gsd_mod - Write module name to GSD */
int gsd_mod(GSD *gsd, char *modname)
{
return gsd_write(gsd, modname, 0, GSD_MODNAME, 0);
}
/* gsd_csect - Write a control section name & size to the GSD */
int gsd_csect(GSD *gsd, char *sectname, int size)
{
return gsd_write(gsd, sectname, 0, GSD_CSECT, size);
}
/* gsd_intname - Write an internal symbol (ignored by RT-11 linker) */
int gsd_intname(GSD *gsd, char *name, unsigned value)
{
return gsd_write(gsd, name, 0, GSD_ISN, value);
}
/* gsd_xfer - Write a program transfer address to GSD */
int gsd_xfer(GSD *gsd, char *name, unsigned value)
{
return gsd_write(gsd, name, 010, GSD_XFER, value);
}
/* gsd_global - Write a global definition or reference to GSD */
/* Caller must be aware of the proper flags. */
int gsd_global(GSD *gsd, char *name, int flags, unsigned value)
{
return gsd_write(gsd, name, flags, GSD_GLOBAL, value);
}
/* Write a program section to the GSD */
/* Caller must be aware of the proper flags. */
int gsd_psect(GSD *gsd, char *name, int flags, int size)
{
return gsd_write(gsd, name, flags, GSD_PSECT, size);
}
/* Write program ident to GSD */
int gsd_ident(GSD *gsd, char *name)
{
return gsd_write(gsd, name, 0, GSD_IDENT, 0);
}
/* Write virtual array declaration to GSD */
int gsd_virt(GSD *gsd, char *name, int size)
{
return gsd_write(gsd, name, 0, GSD_VSECT, size);
}
/* Write ENDGSD record */
int gsd_end(GSD *gsd)
{
gsd->buf[0] = OBJ_ENDGSD;
gsd->buf[1] = 0;
return writerec(gsd->fp, gsd->buf, 2);
}
/* TEXT and RLD record handling */
/* TEXT records contain the plain binary of the program. An RLD
record refers to the prior TEXT record, giving relocation
information. */
/* text_init prepares a TEXT_RLD prior to writing */
void text_init(TEXT_RLD *tr, FILE *fp, unsigned addr)
{
tr->fp = fp;
tr->text[0] = OBJ_TEXT; /* text records begin with 3, 0 */
tr->text[1] = 0;
tr->text[2] = addr & 0xff; /* and are followed by load address */
tr->text[3] = (addr >> 8) & 0xff;
tr->txt_offset = 4; /* Here's where recording new text will begin */
tr->rld[0] = OBJ_RLD; /* RLD records begin with 4, 0 */
tr->rld[1] = 0;
tr->txt_addr = addr;
tr->rld_offset = 2; /* And are followed by RLD entries */
}
/* text_flush - flushes buffer TEXT and RLD records. */
int text_flush(TEXT_RLD *tr)
{
if(tr->txt_offset > 4)
{
if(!writerec(tr->fp, tr->text, tr->txt_offset))
return 0;
}
if(tr->rld_offset > 2)
{
if(!writerec(tr->fp, tr->rld, tr->rld_offset))
return 0;
}
return 1;
}
/* Used to ensure that TEXT and RLD information will be in adjacent
records. If not enough space exists in either buffer, both are
flushed. */
static int text_fit(TEXT_RLD *tr, unsigned addr,
int txtsize, int rldsize)
{
if(tr->txt_offset + txtsize <= sizeof(tr->text) &&
tr->rld_offset + rldsize <= sizeof(tr->rld) &&
(txtsize == 0 || tr->txt_addr + tr->txt_offset - 4 == addr))
return 1; /* All's well. */
if(!text_flush(tr))
return 0;
text_init(tr, tr->fp, addr);
return 1;
}
/* text_word_i - internal text_word. Used when buffer space is
already assured. */
static void text_word_i(TEXT_RLD *tr, unsigned w, int size)
{
tr->text[tr->txt_offset++] = w & 0xff;
if(size > 1)
tr->text[tr->txt_offset++] = (w >> 8) & 0xff;
}
/* text_word - write constant word to text */
int text_word(TEXT_RLD *tr, unsigned *addr, int size, unsigned word)
{
if(!text_fit(tr, *addr, size, 0))
return 0;
text_word_i(tr, word, size);
*addr += size; /* Update the caller's DOT */
return 1; /* say "ok". */
}
/* rld_word - adds a word to the RLD information. */
static void rld_word(TEXT_RLD *tr, unsigned wd)
{
tr->rld[tr->rld_offset++] = wd & 0xff;
tr->rld[tr->rld_offset++] = (wd >> 8) & 0xff;
}
/* rld_byte - adds a byte to rld information. */
static void rld_byte(TEXT_RLD *tr, unsigned byte)
{
tr->rld[tr->rld_offset++] = byte & 0xff;
}
/* rld_code - write the typical RLD first-word code. Encodes the
given address as the offset into the prior TEXT record. */
static void rld_code(TEXT_RLD *tr, unsigned code, unsigned addr, int size)
{
unsigned offset = addr - tr->txt_addr + 4;
rld_word(tr, code | offset << 8 | (size == 1 ? 0200 : 0));
}
/* rld_code_naddr - typical RLD entries refer to a text address. This
one is used when the RLD code does not. */
static void rld_code_naddr(TEXT_RLD *tr, unsigned code, int size)
{
rld_word(tr, code | (size == 1 ? 0200 : 0));
}
/* write a word with a psect-relative value */
int text_internal_word(TEXT_RLD *tr, unsigned *addr,
int size, unsigned word)
{
if(!text_fit(tr, *addr, size, 4))
return 0;
text_word_i(tr, word, size);
rld_code(tr, RLD_INT, *addr, size);
rld_word(tr, word);
*addr += size;
return 1;
}
/* write a word which is an absolute reference to a global symbol */
int text_global_word(TEXT_RLD *tr, unsigned *addr,
int size, unsigned word, char *global)
{
unsigned radtbl[2];
if(!text_fit(tr, *addr, size, 6))
return 0;
text_word_i(tr, word, size);
rld_code(tr, RLD_GLOBAL, *addr, size);
rad50x2(global, radtbl);
rld_word(tr, radtbl[0]);
rld_word(tr, radtbl[1]);
*addr += size;
return 1;
}
/* Write a word which is a PC-relative reference to an absolute address */
int text_displaced_word(TEXT_RLD *tr,
unsigned *addr, int size, unsigned word)
{
if(!text_fit(tr, *addr, size, 4))
return 0;
text_word_i(tr, word, size);
rld_code(tr, RLD_INT_DISP, *addr, size);
rld_word(tr, word);
*addr += size;
return 1;
}
/* write a word which is a PC-relative reference to a global symbol */
int text_global_displaced_word(TEXT_RLD *tr,
unsigned *addr, int size,
unsigned word, char *global)
{
unsigned radtbl[2];
if(!text_fit(tr, *addr, size, 6))
return 0;
text_word_i(tr, word, size);
rld_code(tr, RLD_GLOBAL_DISP, *addr, size);
rad50x2(global, radtbl);
rld_word(tr, radtbl[0]);
rld_word(tr, radtbl[1]);
*addr += size;
return 1;
}
/* write a word which is an absolute reference to a global symbol plus
an offset */
/* Optimizes to text_global_word when the offset is zero. */
int text_global_offset_word(TEXT_RLD *tr,
unsigned *addr, int size,
unsigned word, char *global)
{
unsigned radtbl[2];
if(word == 0)
return text_global_word(tr, addr, size, word, global);
if(!text_fit(tr, *addr, size, 8))
return 0;
text_word_i(tr, word, size);
rld_code(tr, RLD_GLOBAL_OFFSET, *addr, size);
rad50x2(global, radtbl);
rld_word(tr, radtbl[0]);
rld_word(tr, radtbl[1]);
rld_word(tr, word);
*addr += size;
return 1;
}
/* write a word which is a PC-relative reference to a global symbol
plus an offset */
/* Optimizes to text_global_displaced_word when the offset is zero. */
int text_global_displaced_offset_word(TEXT_RLD *tr,
unsigned *addr, int size,
unsigned word, char *global)
{
unsigned radtbl[2];
if(word == 0)
return text_global_displaced_word(tr, addr, size, word, global);
if(!text_fit(tr, *addr, size, 8))
return 0;
text_word_i(tr, word, size);
rld_code(tr, RLD_GLOBAL_OFFSET_DISP, *addr, size);
rad50x2(global, radtbl);
rld_word(tr, radtbl[0]);
rld_word(tr, radtbl[1]);
rld_word(tr, word);
*addr += size;
return 1;
}
/* Define current program counter, plus PSECT */
/* Different because it must be the last RLD entry in a block. That's
because TEXT records themselves contain the current text
address. */
int text_define_location(TEXT_RLD *tr, char *name, unsigned *addr)
{
unsigned radtbl[2];
if(!text_fit(tr, *addr, 0, 8)) /* No text space used */
return 0;
rld_code_naddr(tr, RLD_LOCDEF, 2); /* RLD code for "location
counter def" with no offset */
rad50x2(name, radtbl);
rld_word(tr, radtbl[0]); /* Set current section name */
rld_word(tr, radtbl[1]);
rld_word(tr, *addr); /* Set current location addr */
if(!text_flush(tr)) /* Flush that block out. */
return 0;
text_init(tr, tr->fp, *addr); /* Set new text address */
return 1;
}
/* Modify current program counter, assuming current PSECT */
/* Location counter modification is similarly weird */
/* (I wonder - why is this RLD code even here? TEXT records contain
thair own start address.) */
int text_modify_location(TEXT_RLD *tr, unsigned *addr)
{
if(!text_fit(tr, *addr, 0, 4)) /* No text space used */
return 0;
rld_code_naddr(tr, RLD_LOCMOD, 2); /* RLD code for "location
counter mod" with no offset */
rld_word(tr, *addr); /* Set current location addr */
if(!text_flush(tr)) /* Flush that block out. */
return 0;
text_init(tr, tr->fp, *addr); /* Set new text address */
return 1;
}
/* write two words containing program limits (the .LIMIT directive) */
int text_limits(TEXT_RLD *tr, unsigned *addr)
{
if(!text_fit(tr, *addr, 4, 2))
return 0;
text_word_i(tr, 0, 2);
text_word_i(tr, 0, 2);
rld_code(tr, RLD_LIMITS, *addr, 2);
*addr += 4;
return 1;
}
/* write a word which is the start address of a different PSECT */
int text_psect_word(TEXT_RLD *tr,
unsigned *addr, int size,
unsigned word, char *name)
{
unsigned radtbl[2];
if(!text_fit(tr, *addr, size, 6))
return 0;
text_word_i(tr, word, size);
rld_code(tr, RLD_PSECT, *addr, size);
rad50x2(name, radtbl);
rld_word(tr, radtbl[0]);
rld_word(tr, radtbl[1]);
*addr += size;
return 1;
}
/* write a word which is an offset from the start of a different PSECT */
/* Optimizes to text_psect_word when offset is zero */
int text_psect_offset_word(TEXT_RLD *tr,
unsigned *addr, int size,
unsigned word, char *name)
{
unsigned radtbl[2];
if(word == 0)
return text_psect_word(tr, addr, size, word, name);
if(!text_fit(tr, *addr, size, 8))
return 0;
text_word_i(tr, word, size);
rld_code(tr, RLD_PSECT_OFFSET, *addr, size);
rad50x2(name, radtbl);
rld_word(tr, radtbl[0]);
rld_word(tr, radtbl[1]);
rld_word(tr, word);
*addr += size;
return 1;
}
/* write a word which is the address of a different PSECT, PC-relative */
int text_psect_displaced_word(TEXT_RLD *tr, unsigned *addr,
int size, unsigned word, char *name)
{
unsigned radtbl[2];
if(!text_fit(tr, *addr, size, 6))
return 0;
text_word_i(tr, word, size);
rld_code(tr, RLD_PSECT_DISP, *addr, size);
rad50x2(name, radtbl);
rld_word(tr, radtbl[0]);
rld_word(tr, radtbl[1]);
*addr += size;
return 1;
}
/* write a word which is an offset from the address of a different
PSECT, PC-relative */
/* Optimizes to text_psect_displaced_word when offset is zero */
int text_psect_displaced_offset_word(TEXT_RLD *tr,
unsigned *addr, int size,
unsigned word, char *name)
{
unsigned radtbl[2];
if(word == 0)
return text_psect_displaced_word(tr, addr, size, word, name);
if(!text_fit(tr, *addr, size, 8))
return 0;
text_word_i(tr, word, size);
rld_code(tr, RLD_PSECT_OFFSET_DISP, *addr, size);
rad50x2(name, radtbl);
rld_word(tr, radtbl[0]);
rld_word(tr, radtbl[1]);
rld_word(tr, word);
*addr += size;
return 1;
}
/* complex relocation! */
/* A complex relocation expression is where a piece of code is fed to
the linker asking it to do some math for you, and store the result
in a program word. The code is a stack-based language. */
/* complex_begin initializes a TEXT_COMPLEX */
void text_complex_begin(TEXT_COMPLEX *tx)
{
tx->len = 0;
}
/* text_complex_fit checks if a complex expression will fit and
returns a pointer to it's location */
static char *text_complex_fit(TEXT_COMPLEX *tx, int size)
{
int len;
if(tx->len + size > sizeof(tx->accum))
return NULL; /* Expression has grown too complex. */
len = tx->len;
tx->len += size;
return tx->accum + len;
}
/* text_complex_byte stores a single byte. */
static int text_complex_byte(TEXT_COMPLEX *tx, unsigned byte)
{
char *cp = text_complex_fit(tx, 1);
if(!cp)
return 0;
*cp = byte;
return 1;
}
/* text_complex_add - add top two stack elements */
int text_complex_add(TEXT_COMPLEX *tx)
{
return text_complex_byte(tx, CPLX_ADD);
}
/* text_complex_sub - subtract top two stack elements. */
/* You know, I think these function labels are self-explanatory... */
int text_complex_sub(TEXT_COMPLEX *tx)
{
return text_complex_byte(tx, CPLX_SUB);
}
int text_complex_mul(TEXT_COMPLEX *tx)
{
return text_complex_byte(tx, CPLX_MUL);
}
int text_complex_div(TEXT_COMPLEX *tx)
{
return text_complex_byte(tx, CPLX_DIV);
}
int text_complex_and(TEXT_COMPLEX *tx)
{
return text_complex_byte(tx, CPLX_AND);
}
int text_complex_or(TEXT_COMPLEX *tx)
{
return text_complex_byte(tx, CPLX_OR);
}
int text_complex_xor(TEXT_COMPLEX *tx)
{
return text_complex_byte(tx, CPLX_XOR);
}
int text_complex_com(TEXT_COMPLEX *tx)
{
return text_complex_byte(tx, CPLX_COM);
}
int text_complex_neg(TEXT_COMPLEX *tx)
{
return text_complex_byte(tx, CPLX_NEG);
}
/* text_complex_lit pushes a literal value to the stack. */
int text_complex_lit(TEXT_COMPLEX *tx, unsigned word)
{
char *cp = text_complex_fit(tx, 3);
if(!cp)
return 0;
*cp++ = CPLX_CONST;
*cp++ = word & 0xff;
*cp = (word >> 8) & 0xff;
return 1;
}
/* text_complex_global pushes the value of a global variable to the
stack */
int text_complex_global(TEXT_COMPLEX *tx, char *name)
{
unsigned radtbl[2];
char *cp = text_complex_fit(tx, 5);
if(!cp)
return 0;
rad50x2(name, radtbl);
*cp++ = CPLX_GLOBAL;
*cp++ = radtbl[0] & 0xff;
*cp++ = (radtbl[0] >> 8) & 0xff;
*cp++ = radtbl[1] & 0xff;
*cp = (radtbl[1] >> 8) & 0xff;
return 1;
}
/* text_complex_psect pushes the value of an offset into a PSECT to
the stack. */
/* What was not documented in the Software Support manual is that
PSECT "sect" numbers are assigned in the order they appear in the
source program, and the order they appear in the GSD. i.e. the
first PSECT GSD is assigned sector 0 (which is always the default
absolute section so that's a bad example), the next sector 1,
etc. */
int text_complex_psect(TEXT_COMPLEX *tx, unsigned sect, unsigned offset)
{
char *cp = text_complex_fit(tx, 4);
if(!cp)
return 0;
*cp++ = CPLX_REL;
*cp++ = sect & 0xff;
*cp++ = offset & 0xff;
*cp = (offset >> 8) & 0xff;
return 1;
}
/* text_complex_commit - store the result of the complex expression
and end the RLD code. */
int text_complex_commit(TEXT_RLD *tr, unsigned *addr,
int size, TEXT_COMPLEX *tx, unsigned word)
{
int i;
text_complex_byte(tx, CPLX_STORE);
if(!text_fit(tr, *addr, size, tx->len + 2))
return 0;
rld_code(tr, RLD_COMPLEX, *addr, size);
for(i = 0; i < tx->len; i++)
rld_byte(tr, tx->accum[i]);
text_word_i(tr, word, size);
*addr += size;
return 1;
}
/* text_complex_commit_displaced - store the result of the complex
expression, relative to the current PC, and end the RLD code */
int text_complex_commit_displaced(TEXT_RLD *tr,
unsigned *addr, int size,
TEXT_COMPLEX *tx, unsigned word)
{
int i;
text_complex_byte(tx, CPLX_STORE_DISP);
if(!text_fit(tr, *addr, size, tx->len + 2))
return 0;
rld_code(tr, RLD_COMPLEX, *addr, size);
for(i = 0; i < tx->len; i++)
rld_byte(tr, tx->accum[i]);
text_word_i(tr, word, size);
*addr += size;
return 1;
}
/* Write end-of-object-module to file. */
int write_endmod(FILE *fp)
{
char endmod[2] = { OBJ_ENDMOD, 0 };
return writerec(fp, endmod, 2);
}

View File

@ -1,210 +0,0 @@
#ifndef OBJECT_H
#define OBJECT_H
/* Object file constant definitions */
/*
Copyright (c) 2001, Richard Krehbiel
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
o Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
o Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
o Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/
#define FBR_LEAD1 1 /* The byte value that defines the
beginning of a formatted binary
record */
#define FBR_LEAD2 0 /* Followed by a 0 */
/* Followed by two bytes length */
/* Followed by (length-4) bytes data */
/* Followed by a 1 byte checksum */
/* which is the negative sum of all
preceeding bytes */
#define OBJ_GSD 01 /* GSD (Global symbol directory) */
#define OBJ_ENDGSD 02 /* ENDGSD */
#define OBJ_TEXT 03 /* TEXT */
#define OBJ_RLD 04 /* RLD (Relocation directory) */
#define OBJ_ISD 05 /* ISD (Internal symbol directory,
currently unused) */
#define OBJ_ENDMOD 06 /* ENDMOD (End of object module) */
#define OBJ_LIBHDR 07 /* LIBHDR (Object Library header) */
#define OBJ_LIBEND 010 /* LIBEND (Object Library header end) */
#define GSD_MODNAME 00 /* Module name */
#define GSD_CSECT 01 /* Control section name */
#define GSD_ISN 02 /* Internal symbol name */
#define GSD_XFER 03 /* Transfer address */
#define GSD_GLOBAL 04 /* Global symbol definition/reference */
#define GSD_PSECT 05 /* PSECT name */
#define GSD_IDENT 06 /* IDENT */
#define GSD_VSECT 07 /* VSECT (Virtual array declaration) */
#define GLOBAL_WEAK 01 /* GLOBAL is weak, else strong */
#define GLOBAL_DEF 010 /* GLOBAL is definition, else reference */
#define GLOBAL_REL 040 /* GLOBAL is relative, else absolute */
#define PSECT_SAV 001 /* PSECT is a root section, else overlay */
#define PSECT_COM 004 /* PSECT is merged common area, else
contatenated */
#define PSECT_RO 020 /* PSECT is read-only, else R/W */
#define PSECT_REL 040 /* PSECT is relative, else absolute
(absolute implies PSECT_COM) */
#define PSECT_GBL 0100 /* PSECT is overlay-global, else
overlay-local */
#define PSECT_DATA 0200 /* PSECT contains data, else instructions */
#define RLD_INT 01 /* "Internal relocation" */
#define RLD_GLOBAL 02 /* "Global relocation" */
#define RLD_INT_DISP 03 /* "Internal displaced" */
#define RLD_GLOBAL_DISP 04 /* "Global displaced" */
#define RLD_GLOBAL_OFFSET 05 /* "Global additive" */
#define RLD_GLOBAL_OFFSET_DISP 06 /* "Global additive displaced" */
#define RLD_LOCDEF 07 /* "Location counter definition" */
#define RLD_LOCMOD 010 /* "Location counter modification" */
#define RLD_LIMITS 011 /* ".LIMIT" */
#define RLD_PSECT 012 /* "P-sect" */
#define RLD_PSECT_DISP 014 /* "P-sect displaced" */
#define RLD_PSECT_OFFSET 015 /* "P-sect additive" */
#define RLD_PSECT_OFFSET_DISP 016 /* "P-sect additive displaced" */
#define RLD_COMPLEX 017 /* "Complex" */
#define RLD_BYTE 0200 /* RLD modifies a byte, else a word */
/* Note: complex relocation is not well documented (in particular, no effort
is made to define a section's "sector number"), but I'll just guess
it's a stack language. */
#define CPLX_NOP 00 /* NOP - used for padding */
#define CPLX_ADD 01
#define CPLX_SUB 02
#define CPLX_MUL 03
#define CPLX_DIV 04
#define CPLX_AND 05
#define CPLX_OR 06
#define CPLX_XOR 07
#define CPLX_NEG 010
#define CPLX_COM 011
#define CPLX_STORE 012 /* Store result, terminate complex string. */
#define CPLX_STORE_DISP 013 /* Store result PC-relative, terminate */
#define CPLX_GLOBAL 016 /* Followed by four bytes RAD50 global name */
#define CPLX_REL 017 /* Followed by one byte "sector
number" and two bytes offset */
#define CPLX_CONST 020 /* Followed by two bytes constant value */
typedef struct gsd
{
FILE *fp; /* The file assigned for output */
char buf[122]; /* space for 15 GSD entries */
int offset; /* Current buffer for GSD entries */
} GSD;
void gsd_init(GSD *gsd, FILE *fp);
int gsd_flush(GSD *gsd);
int gsd_mod(GSD *gsd, char *modname);
int gsd_csect(GSD *gsd, char *sectname, int size);
int gsd_intname(GSD *gsd, char *name, unsigned value);
int gsd_xfer(GSD *gsd, char *name, unsigned value);
int gsd_global(GSD *gsd, char *name, int flags, unsigned value);
int gsd_psect(GSD *gsd, char *name, int flags, int size);
int gsd_ident(GSD *gsd, char *name);
int gsd_virt(GSD *gsd, char *name, int size);
int gsd_end(GSD *gsd);
typedef struct text_rld
{
FILE *fp; /* The object file, or NULL */
char text[128]; /* text buffer */
unsigned txt_addr; /* The base text address */
int txt_offset; /* Current text offset */
char rld[128]; /* RLD buffer */
int rld_offset; /* Current RLD offset */
} TEXT_RLD;
void text_init(TEXT_RLD *tr, FILE *fp, unsigned addr);
int text_flush(TEXT_RLD *tr);
int text_word(TEXT_RLD *tr, unsigned *addr, int size, unsigned word);
int text_internal_word(TEXT_RLD *tr, unsigned *addr, int size,
unsigned word);
int text_global_word(TEXT_RLD *tr, unsigned *addr, int size,
unsigned word, char *global);
int text_displaced_word(TEXT_RLD *tr, unsigned *addr, int size,
unsigned word);
int text_global_displaced_word(TEXT_RLD *tr, unsigned *addr, int size,
unsigned word, char *global);
int text_global_offset_word(TEXT_RLD *tr, unsigned *addr, int size,
unsigned word, char *global);
int text_global_displaced_offset_word(TEXT_RLD *tr, unsigned *addr,
int size, unsigned word,
char *global);
int text_define_location(TEXT_RLD *tr, char *name,
unsigned *addr);
int text_modify_location(TEXT_RLD *tr, unsigned *addr);
int text_limits(TEXT_RLD *tr, unsigned *addr);
int text_psect_word(TEXT_RLD *tr, unsigned *addr, int size,
unsigned word, char *name);
int text_psect_offset_word(TEXT_RLD *tr, unsigned *addr,
int size, unsigned word, char *name);
int text_psect_displaced_word(TEXT_RLD *tr, unsigned *addr,
int size, unsigned word, char *name);
int text_psect_displaced_offset_word(TEXT_RLD *tr, unsigned *addr,
int size, unsigned word,
char *name);
typedef struct text_complex
{
char accum[126];
int len;
} TEXT_COMPLEX;
void text_complex_begin(TEXT_COMPLEX *tx);
int text_complex_add(TEXT_COMPLEX *tx);
int text_complex_sub(TEXT_COMPLEX *tx);
int text_complex_mul(TEXT_COMPLEX *tx);
int text_complex_div(TEXT_COMPLEX *tx);
int text_complex_and(TEXT_COMPLEX *tx);
int text_complex_or(TEXT_COMPLEX *tx);
int text_complex_xor(TEXT_COMPLEX *tx);
int text_complex_com(TEXT_COMPLEX *tx);
int text_complex_neg(TEXT_COMPLEX *tx);
int text_complex_lit(TEXT_COMPLEX *tx, unsigned word);
int text_complex_global(TEXT_COMPLEX *tx, char *name);
int text_complex_psect(TEXT_COMPLEX *tx, unsigned sect,
unsigned offset);
int text_complex_commit(TEXT_RLD *tr, unsigned *addr,
int size, TEXT_COMPLEX *tx,
unsigned word);
int text_complex_commit_displaced(TEXT_RLD *tr, unsigned *addr,
int size, TEXT_COMPLEX *tx,
unsigned word);
int write_endmod(FILE *fp);
#endif /* OBJECT_J */

View File

@ -1,117 +0,0 @@
/* Functions to convert RAD50 to or from ASCII. */
/*
Copyright (c) 2001, Richard Krehbiel
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
o Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
o Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
o Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "rad50.h"
static char radtbl[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ$. 0123456789";
/* rad50 converts from 0 to 3 ASCII (or EBCDIC, if your compiler is so
inclined) characters into a RAD50 word. */
unsigned rad50(char *cp, char **endp)
{
unsigned long acc = 0;
char *rp;
if(endp)
*endp = cp;
if(!*cp) /* Got to check for end-of-string
manually, because strchr will call
it a hit. :-/ */
return acc;
rp = strchr(radtbl, toupper(*cp));
if(rp == NULL) /* Not a RAD50 character */
return acc;
acc = (rp - radtbl) * 03100; /* Convert */
cp++;
/* Now, do the same thing two more times... */
if(endp)
*endp = cp;
if(!*cp)
return acc;
rp = strchr(radtbl, toupper(*cp));
if(rp == NULL)
return acc;
acc += (rp - radtbl) * 050;
cp++;
if(endp)
*endp = cp;
if(!*cp)
return acc;
rp = strchr(radtbl, toupper(*cp));
if(rp == NULL)
return acc;
acc += (rp - radtbl);
cp++;
if(endp)
*endp = cp;
return acc; /* Done. */
}
/* rad50x2 - converts from 0 to 6 characters into two words of RAD50. */
void rad50x2(char *cp, unsigned *rp)
{
*rp++ = rad50(cp, &cp);
*rp = 0;
if(*cp)
*rp = rad50(cp, &cp);
}
/* unrad50 - converts a RAD50 word to three characters of ASCII. */
void unrad50(unsigned word, char *cp)
{
if(word < 0175000) /* Is it legal RAD50? */
{
cp[0] = radtbl[word / 03100];
cp[1] = radtbl[(word / 050) % 050];
cp[2] = radtbl[word % 050];
}
else
cp[0] = cp[1] = cp[2] = ' ';
}

View File

@ -1,43 +0,0 @@
#ifndef RAD50_H
#define RAD50_H
/*
Copyright (c) 2001, Richard Krehbiel
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
o Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
o Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
o Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/
extern unsigned rad50(char *cp, char **endp);
extern void rad50x2(char *cp, unsigned *rp);
extern void unrad50(unsigned word, char *cp);
#endif /* RAD50_H */

View File

@ -1,380 +0,0 @@
/* functions for managing a stack of file and buffer input streams. */
/*
Copyright (c) 2001, Richard Krehbiel
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
o Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
o Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
o Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include "macro11.h"
#include "stream2.h"
/* BUFFER functions */
/* new_buffer allocates a new buffer */
BUFFER *new_buffer(void)
{
BUFFER *buf = memcheck(malloc(sizeof(BUFFER)));
buf->length = 0;
buf->size = 0;
buf->use = 1;
buf->buffer = NULL;
return buf;
}
/* buffer_resize makes the buffer at least the requested size. */
/* If the buffer is already larger, then it will attempt */
/* to shrink it. */
void buffer_resize(BUFFER *buff, int size)
{
buff->size = size;
buff->length = size;
if(size == 0)
{
free(buff->buffer);
buff->buffer = NULL;
}
else
{
if(buff->buffer == NULL)
buff->buffer = memcheck(malloc(buff->size));
else
buff->buffer = memcheck(realloc(buff->buffer, buff->size));
}
}
/* buffer_clone makes a copy of a buffer */
/* Basically it increases the use count */
BUFFER *buffer_clone(BUFFER *from)
{
if(from)
from->use++;
return from;
}
/* buffer_free frees a buffer */
/* It decreases the use count, and if zero, */
/* frees the memory. */
void buffer_free(BUFFER *buf)
{
if(buf)
{
if(--(buf->use) == 0)
{
free(buf->buffer);
free(buf);
}
}
}
/* Append characters to the buffer. */
void buffer_appendn(BUFFER *buf, char *str, int len)
{
int needed = buf->length + len + 1;
if(needed >= buf->size)
{
buf->size = needed + GROWBUF_INCR;
if(buf->buffer == NULL)
buf->buffer = memcheck(malloc(buf->size));
else
buf->buffer = memcheck(realloc(buf->buffer, buf->size));
}
memcpy(buf->buffer + buf->length, str, len);
buf->length += len;
buf->buffer[buf->length] = 0;
}
/* append a text line (zero or newline-delimited) */
void buffer_append_line(BUFFER *buf, char *str)
{
char *nl;
if((nl = strchr(str, '\n')) != NULL)
buffer_appendn(buf, str, nl - str + 1);
else
buffer_appendn(buf, str, strlen(str));
}
/* Base STREAM class methods */
/* stream_construct initializes a newly allocated STREAM */
void stream_construct(STREAM *str, char *name)
{
str->line = 0;
str->name = memcheck(strdup(name));
str->next = NULL;
str->vtbl = NULL;
}
/* stream_delete destroys and deletes (frees) a STREAM */
void stream_delete(STREAM *str)
{
free(str->name);
free(str);
}
/* *** class BUFFER_STREAM implementation */
/* STREAM::gets for a buffer stream */
char *buffer_stream_gets(STREAM *str)
{
char *nl;
char *cp;
BUFFER_STREAM *bstr = (BUFFER_STREAM *)str;
BUFFER *buf = bstr->buffer;
if(buf == NULL)
return NULL; /* No buffer */
if(bstr->offset >= buf->length)
return NULL;
cp = buf->buffer + bstr->offset;
/* Find the next line in preparation for the next call */
nl = memchr(cp, '\n', buf->length - bstr->offset);
if(nl)
nl++;
bstr->offset = nl - buf->buffer;
str->line++;
return cp;
}
/* STREAM::close for a buffer stream */
void buffer_stream_delete(STREAM *str)
{
BUFFER_STREAM *bstr = (BUFFER_STREAM *)str;
buffer_free(bstr->buffer);
stream_delete(str);
}
/* STREAM::rewind for a buffer stream */
void buffer_stream_rewind(STREAM *str)
{
BUFFER_STREAM *bstr = (BUFFER_STREAM *)str;
bstr->offset = 0;
str->line = 0;
}
/* BUFFER_STREAM vtbl */
STREAM_VTBL buffer_stream_vtbl = { buffer_stream_delete,
buffer_stream_gets,
buffer_stream_rewind };
void buffer_stream_construct(BUFFER_STREAM *bstr, BUFFER *buf, char *name)
{
bstr->stream.vtbl = &buffer_stream_vtbl;
bstr->stream.name = memcheck(strdup(name));
bstr->buffer = buffer_clone(buf);
bstr->offset = 0;
bstr->stream.line = 0;
}
void buffer_stream_set_buffer(BUFFER_STREAM *bstr, BUFFER *buf)
{
if(bstr->buffer)
buffer_free(bstr->buffer);
bstr->buffer = buffer_clone(buf);
bstr->offset = 0;
}
/* new_buffer_stream clones the given buffer, gives it the name, */
/* and creates a BUFFER_STREAM to reference it */
STREAM *new_buffer_stream(BUFFER *buf, char *name)
{
BUFFER_STREAM *bstr = memcheck(malloc(sizeof(BUFFER_STREAM)));
buffer_stream_construct(bstr, buf, name);
return &bstr->stream;
}
/* *** FILE_STREAM implementation */
/* Implement STREAM::gets for a file stream */
static char *file_gets(STREAM *str)
{
int i, c;
FILE_STREAM *fstr = (FILE_STREAM *)str;
if(fstr->fp == NULL)
return NULL;
if(feof(fstr->fp))
return NULL;
/* Read single characters, end of line when '\n' or '\f' hit */
i = 0;
while(c = fgetc(fstr->fp),
c != '\n' && c != '\f' && c != EOF)
{
if(c == 0)
continue; /* Don't buffer zeros */
if(c == '\r')
continue; /* Don't buffer carriage returns either */
if(i < STREAM_BUFFER_SIZE - 2)
fstr->buffer[i++] = c;
}
fstr->buffer[i++] = '\n'; /* Silently transform formfeeds
into newlines */
fstr->buffer[i] = 0;
if(c == '\n')
fstr->stream.line++; /* Count a line */
return fstr->buffer;
}
/* Implement STREAM::destroy for a file stream */
void file_destroy(STREAM *str)
{
FILE_STREAM *fstr = (FILE_STREAM *)str;
fclose(fstr->fp);
free(fstr->buffer);
stream_delete(str);
}
/* Implement STREAM::rewind for a file stream */
void file_rewind(STREAM *str)
{
FILE_STREAM *fstr = (FILE_STREAM *)str;
rewind(fstr->fp);
str->line = 0;
}
static STREAM_VTBL file_stream_vtbl = { file_destroy, file_gets,
file_rewind };
/* Prepare and open a stream from a file. */
STREAM *new_file_stream(char *filename)
{
FILE *fp;
FILE_STREAM *str;
fp = fopen(filename, "r");
if(fp == NULL)
return NULL;
str = memcheck(malloc(sizeof(FILE_STREAM)));
str->stream.vtbl = &file_stream_vtbl;
str->stream.name = memcheck(strdup(filename));
str->buffer = memcheck(malloc(STREAM_BUFFER_SIZE));
str->fp = fp;
str->stream.line = 0;
return &str->stream;
}
/* STACK functions */
/* stack_init prepares a stack */
void stack_init(STACK *stack)
{
stack->top = NULL; /* Too simple */
}
/* stack_pop removes and deletes the topmost STRAM on the stack */
void stack_pop(STACK *stack)
{
STREAM *top = stack->top;
STREAM *next = top->next;
top->vtbl->delete(top);
stack->top = next;
}
/* stack_push pushes a STREAM onto the top of the stack */
void stack_push(STACK *stack, STREAM *str)
{
str->next = stack->top;
stack->top = str;
}
/* stack_gets calls vtbl->gets for the topmost stack entry. When
topmost streams indicate they're exhausted, they are popped and
deleted, until the stack is exhausted. */
char *stack_gets(STACK *stack)
{
char *line;
if(stack->top == NULL)
return NULL;
while((line = stack->top->vtbl->gets(stack->top)) == NULL)
{
stack_pop(stack);
if(stack->top == NULL)
return NULL;
}
return line;
}

View File

@ -1,110 +0,0 @@
#ifndef STREAM2_H
#define STREAM2_H
/*
Copyright (c) 2001, Richard Krehbiel
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
o Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
o Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
o Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/
struct stream;
typedef struct stream_vtbl
{
void (*delete)(struct stream *stream); // Destructor
char *(*gets)(struct stream *stream); // "gets" function
void (*rewind)(struct stream *stream); // "rewind" function
} STREAM_VTBL;
typedef struct stream
{
STREAM_VTBL *vtbl; // Pointer to dispatch table
char *name; // Stream name
int line; // Current line number in stream
struct stream *next; // Next stream in stack
} STREAM;
typedef struct file_stream
{
STREAM stream; // Base class
FILE *fp; // File pointer
char *buffer; // Line buffer
} FILE_STREAM;
typedef struct buffer
{
char *buffer; // Pointer to text
int size; // Size of buffer
int length; // Occupied size of buffer
int use; // Number of users of buffer
} BUFFER;
#define GROWBUF_INCR 1024 // Buffers grow by leaps and bounds
typedef struct buffer_stream
{
STREAM stream; // Base class
BUFFER *buffer; // text buffer
int offset; // Current read offset
} BUFFER_STREAM;
typedef struct stack
{
STREAM *top; // Top of stacked stream pieces
} STACK;
#define STREAM_BUFFER_SIZE 1024 // This limits the max size of an input line.
BUFFER *new_buffer(void);
BUFFER *buffer_clone(BUFFER *from);
void buffer_resize(BUFFER *buff, int size);
void buffer_free(BUFFER *buf);
void buffer_appendn(BUFFER *buf, char *str, int len);
void buffer_append_line(BUFFER *buf, char *str);
STREAM *new_buffer_stream(BUFFER *buf, char *name);
void buffer_stream_set_buffer(BUFFER_STREAM *bstr, BUFFER *buf);
/* Provide these so that macro11 can derive from a BUFFER_STREAM */
extern STREAM_VTBL buffer_stream_vtbl;
void buffer_stream_construct(BUFFER_STREAM *bstr, BUFFER *buf, char *name);
char *buffer_stream_gets(STREAM *str);
void buffer_stream_delete(STREAM *str);
void buffer_stream_rewind(STREAM *str);
STREAM *new_file_stream(char *filename);
void stack_init(STACK *stack);
void stack_push(STACK *stack, STREAM *str);
void stack_pop(STACK *stack);
char *stack_gets(STACK *stack);
#endif /* STREAM2_H */

View File

@ -1,57 +0,0 @@
I was not able to locate a Macro-11 language reference manual any more
recent than for RT11 version *3*, so I used that plus my recollection
of more modern features. It was enough to get the RT11 V5.4 kernel
built, plus a significant chunk of our own code.
The biggest missing feature is full featured listings. The .LIST and
.NLIST directives are ignored, as is .SBTTL. No table of contents is
accumulated or printed. No symbol cross referencing is done (most
likely I'll just write a CTAGS file, not a cross reference listing).
Many errors still go unchecked. Off the top of my head, I recall that
object and listing file output errors are ignored.
.FLT4 format may be inaccurate in the low bits. This is because IEEE
64 bit format has two fewer mantissa bits than 64 bit PDP-11 format.
Without writing soft-float routines, there's not much I can do abbout
it.
Expression math is done in native width, almost certainly 32 bits.
Truncation to 16 bits is done only for listing and output. This may
make some output differ in the presence of 16-bit overflows and
underflows. I don't think this needs fixing.
.REM blocks containing code can screw up .MACRO, .REPT, .IRP, .IRPC.
read_body in macro11.c would need to be able to parse and ignore .REM
blocks.
Need to search a path for the .INCLUDE directive. Right now it only
takes a complete file name. And most likely, existing code will have
RT-11 style file names; I don't know what to do about that, except put
in a device name parser.
Possible enhancements:
It would be very simple to make macro11 resolve internal symbols with
more that 6 significant characters. Even so, only the first 6 would
be used for external symbols, and you have to be wary of existing code
that used (for example) .LOOKU rather than .LOOKUP, since these two
would become distinct.
SYM = 0
MOV SYM(R0),R0 ; macro11 could optimize SYM(R0) into just (R0)
I dream of automatically fixing branches out of range. Easy when the
destination is backwards, difficult when it's forwards. I have this
idea: during the first assembly pass, all branches generate a long
branch if the target symbol is undefined, otherwise an "optimized"
branch (short or long) if the target is defined. Then keep a
128-instruction FIFO of generated instructions. Each FIFO entry is
tagged with context and symbol definition as they are pushed to the
FIFO. When an instruction gets pulled from the FIFO because it's more
than 128 words away, the FIFO is searched for long branches that point
to this location; any such are shortened, and any symbols defined
following their location in the stream are adjusted. In the second
assembly pass, the FIFOs aren't used because all jump distances are
known, and the right sized branch (JMP or Bcc) can be generated.

View File

@ -1,172 +0,0 @@
/* Some generally useful routines */
/* The majority of the non-portable code is in here. */
/*
Copyright (c) 2001, Richard Krehbiel
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
o Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
o Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
o Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "util.h"
#ifdef WIN32
#include <sys/types.h>
#include <sys/stat.h>
#define stat _stat
#else
#include <sys/stat.h>
#include <unistd.h>
#endif
/* Sure, the library typically provides some kind of
ultoa or _ultoa function. But since it's merely typical
and not standard, and since the function is so simple,
I'll write my own.
It's significant feature is that it'll produce representations in
any number base from 2 to 36.
*/
char *my_ultoa(unsigned long val, char *buf, unsigned int base)
{
static char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char *strt = buf, *end;
do
{
*buf++ = digits[val % base];
val /= base;
} while(val != 0);
*buf = 0; /* delimit */
end = buf+1;
/* Now reverse the bytes */
while(buf > strt)
{
char temp;
temp = *--buf;
*buf = *strt;
*strt++ = temp;
}
return end;
}
/* Ditto my_ultoa. This actually emits
a signed representation in other number bases. */
char *my_ltoa(long val, char *buf, unsigned int base)
{
unsigned long uval;
if(val < 0)
uval = -val, *buf++ = '-';
else
uval = val;
return my_ultoa(uval, buf, base);
}
/*
_searchenv is a function provided by the MSVC library that finds
files which may be anywhere along a path which appears in an
environment variable. I duplicate that function for portability.
Note also that mine avoids destination buffer overruns.
Note: uses strtok. This means it'll screw you up if you
expect your strtok context to remain intact when you use
this function.
*/
void my_searchenv(char *name, char *envname, char *hitfile, int hitlen)
{
char *env;
char *envcopy;
char *cp;
*hitfile = 0; /* Default failure indication */
/* Note: If the given name is absolute, then don't search the
path, but use it as is. */
if(
#ifdef WIN32
strchr(name, ':') != NULL || /* Contain a drive spec? */
name[0] == '\\' || /* Start with absolute ref? */
#endif
name[0] == '/') /* Start with absolute ref? */
{
strncpy(hitfile, name, hitlen); /* Copy to target */
return;
}
env = getenv(envname);
if(env == NULL)
return; /* Variable not defined, no search. */
envcopy = strdup(env); /* strtok destroys it's text
argument. I don't want the return
value from getenv destroyed. */
while((cp = strtok(envcopy, PATHSEP)) != NULL)
{
struct stat info;
char *concat = malloc(strlen(cp) + strlen(name) + 2);
if(concat == NULL)
{
free(envcopy);
return;
}
strcpy(concat, cp);
if(concat[strlen(concat)-1] != '/')
strcat(concat, "/");
strcat(concat, name);
if(!stat(concat, &info))
{
/* Copy the file name to hitfile. Assure that it's really
zero-delimited. */
strncpy(hitfile, concat, hitlen-1);
hitfile[hitlen-1] = 0;
free(envcopy);
return;
}
}
/* If I fall out of that loop, then hitfile indicates no match,
and return. */
}

View File

@ -1,56 +0,0 @@
#ifndef UTIL_H
#define UTIL_H
/*
Copyright (c) 2001, Richard Krehbiel
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
o Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
o Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
o Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/
char *my_ultoa(unsigned long val, char *buf, unsigned int base);
char *my_ltoa(long val, char *buf, unsigned int base);
void my_searchenv(char *name, char *envname,
char *hitfile, int hitlen);
/* Cover a few platform-dependencies */
#ifdef WIN32
typedef unsigned __int64 ulong64;
#define strdup _strdup
#define putenv _putenv
#define PATHSEP ";"
#else
typedef unsigned long long ulong64;
#define PATHSEP ":"
#endif
#endif /* UTIL_H */