|
|
researchv9-SUN3(old)
%{
static char ID[] = "@(#) ld.lex: 1.10 12/1/83";
#include "system.h"
#include <stdio.h>
#include <signal.h>
#include "bool.h"
#include "paths.h"
#include "sgs.h"
#include "structs.h" /* global structure definitions */
#include "extrns.h" /* external function definitions */
#include "y.tab.h" /* tokens generated by yacc */
#if !ONEPROC || TRVEC
#include "tv.h"
#include "ldtv.h"
#endif
#include "aouthdr.h"
#if ONEPROC
#include "instr.h"
#endif
extern char version[]; /* ld version information */
/*
* There are four start states for the lex parse:
*
* A : look for initial keyword of a ld directive
* MEMoREG : scan a ld directive
* COMA : skip a stand-alone comment
* COMoMR : skip a comment at the end of a directive
*/
#define RET1(a) {yylval.ivalue=a;moveit(1,a);return(a);}
#define RET2(a,b) {yylval.sptr=a;moveit(2,yylval.sptr);return(b);}
#define RET3(a,b) {yylval.lptr=a;moveit(3,yylval.lptr);return(b);}
#define LSAVSIZE 6
static long lsavarea[LSAVSIZE]; /* local save area for integer tokens */
static int lsavndx = 0;
extern long *savelng();
#define CSAVSIZE 1024
static char csavarea[CSAVSIZE]; /* local save area for string tokens */
static char *csavptr = &csavarea[0];
extern char *savestr();
char inline[256]; /* global save area for the current input line */
char *inptr = &inline[0];
char **argptr; /* main procedure argument list */
int argcnt; /* and count */
extern int in_y_exp; /* in_y_exp :
* TRUE : yacc is parsing assignment
* FALSE : yacc is not in assignment
*
* See explanation is ld.yac.
*/
int assigncnt; /* number of assignment slots */
#if FLEXNAMES
# define STRBASE 6144
#else
# define STRBASE 3072
#endif
/*eject*/
%}
%start A MEMoREG COMA COMoMR
%%
%{
long longint; /* local variables used in processing */
char *p; /* numbers and strings */
%}
<A>"/*" BEGIN COMA;
<MEMoREG>"/*" BEGIN COMoMR;
<COMA>"*/" BEGIN A;
<COMoMR>"*/" BEGIN MEMoREG;
<COMA,COMoMR>. ;
<A>MEMORY { BEGIN MEMoREG; RET1(MEMORY); }
<A>REGIONS { BEGIN MEMoREG; RET1(REGIONS); }
<A>TV { BEGIN MEMoREG; RET1(TV); }
<A>SECTIONS RET1(SECTIONS);
<A>DSECT RET1(DSECT);
<A>NOLOAD RET1(NOLOAD);
<A>COPY RET1(COPY);
<A>INFO RET1(INFO);
<MEMoREG>"}" { BEGIN A; RET1(RBRACE); }
<MEMoREG>ORIGIN|origin|org|o RET1(ORG);
<MEMoREG>LENGTH|length|len|l RET1(LEN);
<MEMoREG>SPARE|spare|s RET1(SPARE);
<MEMoREG>RANGE|range RET1(RANGE);
<MEMoREG>ASSIGN|assign RET1(ASSIGN);
<A,MEMoREG>"." RET1(DOT);
<A,MEMoREG>"}" RET1(RBRACE);
<A,MEMoREG>"{" RET1(LBRACE);
<A,MEMoREG>")" RET1(RPAREN);
<A,MEMoREG>"(" RET1(LPAREN);
<A,MEMoREG>":" RET1(COLON);
<A,MEMoREG>";" RET1(SEMICOL);
<A,MEMoREG>"-" RET1(MINUS);
<A,MEMoREG>"=" RET1(EQ);
<A,MEMoREG>">" RET1(GT);
<A,MEMoREG>"," RET1(COMMA);
<A,MEMoREG>"&" RET1(AND);
<A,MEMoREG>"&&" RET1(ANDAND);
<A,MEMoREG>"|" RET1(OR);
<A,MEMoREG>"||" RET1(OROR);
<A,MEMoREG>"==" RET1(EQEQ);
<A,MEMoREG>"!=" RET1(NE);
<A,MEMoREG>"~" RET1(BNOT);
<A,MEMoREG>"!" RET1(NOT);
<A,MEMoREG>"/" RET1(DIV);
<A,MEMoREG>"*" RET1(MULT);
<A,MEMoREG>"%" RET1(PC);
<A,MEMoREG>"<" RET1(LT);
<A,MEMoREG>">=" RET1(GE);
<A,MEMoREG>"<=" RET1(LE);
<A,MEMoREG>"<<" RET1(LSHIFT);
<A,MEMoREG>">>" RET1(RSHIFT);
<A,MEMoREG>"+" RET1(PLUS);
<A,MEMoREG>"+=" RET1(PLUSEQ);
<A,MEMoREG>"-=" RET1(MINUSEQ);
<A,MEMoREG>"*=" RET1(MULTEQ);
<A,MEMoREG>"/=" RET1(DIVEQ);
<A,MEMoREG>ALIGN|align RET1(ALIGN);
<A,MEMoREG>BLOCK|block RET1(BLOCK);
<A,MEMoREG>GROUP|group RET1(GROUP);
<A,MEMoREG>PHY|phy RET1(PHY);
"\n" {
lineno++;
inptr = &inline[0];
}
[ \t]+ {
*inptr++ = ' ';
*inptr = '\0';
}
<A,MEMoREG>[0][0-7]* {
longint = 0L;
for(p=yytext+1; *p != '\0'; p++) {
longint = longint * 8 + (*p-'0');
}
RET3(savelng(longint), LONGINT);
}
<A,MEMoREG>[0-9]+ {
longint = 0L;
for(p=yytext; *p != '\0'; p++) {
longint = longint * 10 + (*p-'0');
}
RET3(savelng(longint), LONGINT);
}
<A,MEMoREG>0[Xx][0-9a-fA-F]+ {
longint = 0L;
for(p=yytext+2; *p != '\0'; p++) {
longint = longint << 4;
if (*p >= '0' && *p <= '9')
longint += *p-'0';
else if (*p >= 'a' && *p <= 'f')
longint += *p-'a'+10;
else longint += *p-'A'+10;
}
RET3(savelng(longint), LONGINT);
}
<A,MEMoREG>[a-zA-Z0-9$._]+"/"("*"|"=") {
yyless(yyleng-2);
RET2(savestr(yytext), NAME);
}
<A,MEMoREG>[a-zA-Z0-9$._/]+"/"("*"|"=") {
if ( in_y_exp )
REJECT;
yyless(yyleng-2);
RET2(savestr(yytext), FILENAME);
}
<A,MEMoREG>[a-zA-Z0-9$._]+ {
RET2(savestr(yytext), NAME);
}
<A,MEMoREG>[a-zA-Z0-9$._/]+ {
if ( in_y_exp )
REJECT;
RET2(savestr(yytext), FILENAME);
}
%%
/*eject*/
main(argc,argv)
int argc;
char *argv[];
{
/*
* This is the MAIN procdure for PASS 1 of ld
*
* PASS 1 is the parsing pass:
* 1. The ld command line, and any specified ifiles, are
* scanned for good syntax.
* 2. Control blocks are constructed, containing the information
* extracted from the input.
* 3. If there are no errors, the control blocks are written out
* to a "transfer file", for reading by PASS 2.
* 4. If there are no errors, PASS 2 is called via a system
* "execl" call.
*/
/*
* Initialize PASS 1
*/
initpass1();
argptr = argv;
argcnt = argc;
if ( argcnt <= 1 )
{
fprintf( stderr, "Usage: %sld [ options ] file ...\n", SGS );
exit(1);
}
/*
* Process the command-line arguments to ld
*/
lineno = 0;
curfilnm = savefn("*command line*");
while( --argcnt )
if( **++argptr == '-' )
/*
* The argument is a flag
*/
pflags( ++(*argptr), FALSE );
else {
/*
* The argument is a file name
*/
BEGIN A;
filespec(*argptr);
}
/*
* Perform a consistency check among the ld flags:
* 1. "-h" and "-X" flags
* 2. "-ild", "-r", and "-a" flags
* 3. "-r" and "-s" flags
* 4. "-p" and "-B" flags
*
* Assign default values to the ld flags
* 1. "-h" flag
* 2. "-a" flag
* 3. "-p" flag
*/
if( Xflag )
if( hflag > 0 ) {
if( hflag < sizeof(AOUTHDR) )
lderror(1, 0,NULL, "optional header size (%d bytes) is too small to contain the UNIX a.out header (%d bytes)",
hflag, sizeof(AOUTHDR) );
}
else
hflag = sizeof(AOUTHDR);
#if ILDOPT
if (ildflag) {
rflag = 1;
if (sflag) {
lderror (0, 0, NULL, "both -ild and -s flags are set. -s flag turned off");
sflag = 0;
}
}
#endif
if( rflag && sflag ) {
lderror(0, 0,NULL, "both -r and -s flags are set. -s flag turned off" );
sflag = 0;
}
if ( Bflag && (pflag > 0) && (pflag < Bflag)) {
lderror(0, 0, NULL, "pflag(%d) less than Bflag, set to value of Bflag(%d)\n",
pflag, Bflag);
pflag = Bflag;
}
if( ! rflag )
aflag = 1;
/*
* Supply version information
*/
if( Vflag ) {
fprintf( stderr, "\n%sld : %s : Version %s",
SGSNAME, RELEASE, version );
if( Vflag == 2 ) {
#if AR16WR
fprintf( stderr, " : PDP 11/70-45 : " );
#endif
#if AR32WR
fprintf( stderr, " : VAX 11/780 : " );
#endif
#if ! AR16WR && ! AR32WR
#ifdef u3b
fprintf( stderr, " : 3B-20 : " );
#else
fprintf( stderr, " : non-DEC : ");
#endif
#endif
#if TS
fprintf( stderr, "UN*X TS" );
#else
fprintf( stderr, "UN*X" );
#endif
}
fprintf( stderr, "\n" );
}
/*
* Exit if any errors were found, or if this is a "parse only"
* run
*/
if( (errlev != 0) || (cflag == 1) ) {
#if !ONEPROC
unlink( trnname );
#endif
exit(errlev);
}
/*
* Call PASS 2
*/
#if ONEPROC
pass2();
}
#else
callpass2();
unlink( trnname );
lderror(2, 0,NULL, "failure to load pass 2 of %sld", SGS);
}
/*eject*/
ldexit()
{
/*
* PASS 1: clean up and exit after a fatal error
*/
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_DFL);
signal(SIGTERM, SIG_IGN);
signal(SIGHUP, SIG_DFL);
exit(13); /* unlucky break */
}
/*eject*/
#endif
long *
savelng(l)
long l;
{
/*
* Copy a long token into local save area and return a pointer to it.
*
* The save area is used as a circular buffer
*/
lsavndx++;
lsavndx %= LSAVSIZE;
lsavarea[lsavndx] = l;
return( &lsavarea[lsavndx] );
}
char *
savestr(p)
char *p;
{
/*
* Copy a string into local save area and return a pointer to it
*
* The save area is used as a circular buffer
*/
register char *saveptr;
if( csavptr > (csavarea + CSAVSIZE - 256) )
csavptr = csavarea;
saveptr = csavptr;
while( *csavptr++ = *p++ );
return( saveptr );
}
moveit(type, value)
int type, value;
{
register char *p;
p = &yytext[0];
while( *inptr++ = *p++ );
inptr--;
#if DEBUG
if( dflag > 3 ) {
fprintf(stderr, "line: <%s> return: <", inline);
switch( type ) {
case 1:
fprintf(stderr, "%d>\n", value);
break;
case 2:
fprintf(stderr, "%s>\n", (char *) value);
break;
case 3:
fprintf(stderr, "%08lx>\n", * (long *) value);
break;
}
}
#endif
}
/*eject*/
initpass1()
{
register int oldmode;
int ldexit();
#if ONEPROC
long times();
#endif
/*
* Set the following signals to be caught, unless ld is running in the
* background. In this case, leave them set at "ignore"
*/
if( signal(SIGINT, ldexit) == SIG_IGN )
signal(SIGINT, SIG_IGN);
if( signal(SIGHUP, ldexit) == SIG_IGN )
signal(SIGHUP, SIG_IGN);
if( signal(SIGQUIT, ldexit) == SIG_IGN )
signal(SIGQUIT, SIG_IGN);
#if ONEPROC
ttime = times(&ptimes);
#else
/*
* Create the "transfer file" used to pass information to PASS 2
*/
sprintf(trnname, "%s/%s", TMPDIR, "ldXXXXX");
mktemp(trnname);
oldmode = umask( 0 );
if( close( creat(trnname,0644) ) == -1 ) {
umask( oldmode );
lderror(2, 0,NULL, "can't create intermediate %sld file %s",
SGS, trnname);
}
umask( oldmode );
#endif
/*
* Allocate the global file name save area
*/
strbase = myalloc(STRBASE);
strnext = strbase;
strlimit = strbase + STRBASE;
#if ONEPROC && (!NOSDP)
/*
* Initialize the Software Demand Paging System
*/
syminit();
#endif
}
/*eject*/
#if !ONEPROC
callpass2()
{
/*
* Output PASS 1 information to the "transfer file"
*
* 1. reserve space for flags and list headers
* 2. output lists
* 3. output flags and list headers
*/
trnfdes = fopen(trnname, "w");
skp_tf_hdr();
wrt_tf();
wrt_tf_hdr();
fclose( trnfdes );
/*
* Exit, if this is a "generate transfer file run" only
*/
if( cflag == 2 ) {
fprintf( stderr, "ld transfer file name: %s\n", trnname );
exit(0);
}
#if DEBUG
if( dflag > 2 )
fprintf( stderr, "ld transfer file name: %s\n", trnname );
#endif
/*
* Execute PASS 2
*/
execl(LD2, LD2, trnname, 0);
}
/*eject*/
skp_tf_hdr()
{
/*
* Reserve space for control and descriptor information collected during
* PASS 1
*
* This information is of fixed length, and comes at the very beginning
* of the transfer file
*/
register long length;
length =
7 * sizeof(int) + /* list sizes */
13 * sizeof(char) + /* flags */
#if UNIX || XL
1 * sizeof(char) + /* xflag */
#endif
#if ILDOPT
1 * sizeof(char) + /* ildflag */
#endif
#if PAGING
1 * sizeof(char) + /* Fflag */
#endif
#if PAGING
1 * sizeof(char) + /* zflag */
#endif
#if COMMON
2 * sizeof(char) + /* tflag and Mflag */
#endif
3 * sizeof(int) + /* control values */
3 * sizeof(short) + /* VStamp, fill and magic */
128 + /* output file name */
8 + /* program entry pt */
sizeof(TVINFO) + /* tv information */
1 * sizeof(int); /* flags + counts */
fseek( trnfdes, length, 0 );
}
/*eject*/
wrt_tf()
{
/*
* Output the bulk of the information extracted from PASS 1:
*
* 1. The names of input ifiles, input *.o and archive files, and
* output sections
* 2. The data structures describing the ld directives
*/
MEMTYPE *outds1();
REGION *outds2();
ACTITEM *outds3(), *outds4(), *outds6();
TVASSIGN *outds8();
/*
* 1. Output saved strings
*/
fwrite( strbase, 1, (strnext - strbase), trnfdes );
/*
* 2a. Output DEFSYM data structures
*/
symcnt = 0;
if( symlist.head ) {
register ACTITEM *a;
a = (ACTITEM *) symlist.head;
while( a ) {
a = outds3(a);
symcnt++;
}
}
/*
* 2b. Output MEMTYPE data structures
*/
memcnt = 0;
if( memlist.head ) {
register MEMTYPE *m;
m = (MEMTYPE *) memlist.head;
while( m ) {
m = outds1(m);
memcnt++;
}
}
/*
* 2c. Output REGION data structures
*/
regcnt = 0;
if( reglist.head ) {
register REGION *r;
r = (REGION *) reglist.head;
while( r ) {
r = outds2(r);
regcnt++;
}
}
/*
* 2d. Output information on input *.o and archive library files
*/
ldfcnt = 0;
if( ldfilist.head ) {
register ACTITEM *a;
a = (ACTITEM *) ldfilist.head;
while( a ) {
a = outds3(a);
ldfcnt++;
}
}
/*
* 2e. Output information on output sections
*/
bldcnt = 0;
if( bldoutsc.head ) {
register ACTITEM *a;
a = (ACTITEM *) bldoutsc.head;
while( a ) {
a = outds4(a);
bldcnt++;
}
}
/*
* 2f. Output information on assignments
*/
expcnt = 0;
if( explist.head ) {
register ACTITEM *a;
a = (ACTITEM *) explist.head;
while( a ) {
a = outds6(a);
expcnt++;
}
}
/*
* 2g. Output information on slot assignments
*/
tvslotcnt = 0;
if (tvslot1 != NULL) {
register TVASSIGN *s;
s = tvslot1;
while (s != NULL) {
s = outds8(s);
++tvslotcnt;
}
}
}
/*eject*/
wrt_tf_hdr()
{
/*
* Output control and descriptor information obtained during PASS 1
*
* This information is of fixed length, and comes at the very beginning
* of the transfer file
*/
int length;
fseek( trnfdes, 0L, 0 );
/*
* Output the sizes of the lists built during PASS 1
*
* 1. symbol definition/undefinition
* 2. MEMORY directives
* 3. REGIONS directives
* 4. input *.o and archive library files
* 5. output sections
* 6. assignment directives
* 7. tv slot assignment directives
*/
fwrite( &symcnt, sizeof(int), 1, trnfdes );
fwrite( &memcnt, sizeof(int), 1, trnfdes );
fwrite( ®cnt, sizeof(int), 1, trnfdes );
fwrite( &ldfcnt, sizeof(int), 1, trnfdes );
fwrite( &bldcnt, sizeof(int), 1, trnfdes );
fwrite( &expcnt, sizeof(int), 1, trnfdes );
fwrite(&tvslotcnt, sizeof(int), 1, trnfdes);
/*
* Output the ld control flags
*/
fwrite( &aflag, sizeof(char), 1, trnfdes );
fwrite( &cflag, sizeof(char), 1, trnfdes );
fwrite( &dflag, sizeof(char), 1, trnfdes );
fwrite( &iflag, sizeof(char), 1, trnfdes );
fwrite( &mflag, sizeof(char), 1, trnfdes );
fwrite( &rflag, sizeof(char), 1, trnfdes );
fwrite( &sflag, sizeof(char), 1, trnfdes );
fwrite( &tvflag, sizeof(char), 1, trnfdes );
fwrite( &Hflag, sizeof(char), 1, trnfdes );
fwrite( &Nflag, sizeof(char), 1, trnfdes );
fwrite( &Sflag, sizeof(char), 1, trnfdes );
fwrite( &Vflag, sizeof(char), 1, trnfdes );
fwrite( &Xflag, sizeof(char), 1, trnfdes );
fwrite( &hflag, sizeof(int), 1, trnfdes );
fwrite( &pflag, sizeof(int), 1, trnfdes );
fwrite( &Bflag, sizeof(int), 1, trnfdes );
fwrite( &VSflag, sizeof(short), 1, trnfdes);
#if UNIX || XL
fwrite( &xflag, sizeof(char), 1, trnfdes );
#endif
#if COMMON
fwrite( &tflag, sizeof(char), 1, trnfdes );
fwrite( &Mflag, sizeof(char), 1, trnfdes );
#endif
#if PAGING
fwrite( &Fflag, sizeof(char), 1, trnfdes );
#endif
#if PAGING
fwrite( &zflag, sizeof(char), 1, trnfdes );
#endif
#if ILDOPT
fwrite( &ildflag, sizeof(char), 1, trnfdes );
#endif
/*
* Output various values extracted from the parse
*/
fwrite( &globfill, sizeof(short), 1, trnfdes );
fwrite( &magic, sizeof(unsigned short), 1, trnfdes );
fwrite( outfilnm, 128, 1, trnfdes );
fwrite( epsymbol, 8, 1, trnfdes );
/* convert filename from ptr to index */
if (tvspec.tvinflnm != NULL)
tvspec.tvinflnm = (char *) ((int) tvspec.tvinflnm - (int) strbase);
fwrite( &tvspec, sizeof(TVINFO), 1, trnfdes );
/*
* Output the size of the saved strings
*/
length = strnext - strbase;
fwrite( &length, sizeof(int), 1, trnfdes );
}
/*eject*/
MEMTYPE *
outds1(m)
MEMTYPE *m;
{
/*
* Output one MEMTYPE data structure
*/
fwrite( m, 1, sizeof(MEMTYPE), trnfdes );
return( m->mtnext );
}
REGION *
outds2(r)
REGION *r;
{
/*
* Output one REGION data structure
*/
fwrite( r, 1, sizeof(REGION), trnfdes );
return( r->rgnext );
}
/*eject*/
ACTITEM *
outds3(a)
ACTITEM *a;
{
/*
* Output one AILDFILE, AILDLBRY, AIADFILE, or AIDFNSYM data structure
*
* Convert a "pointer to a string" to a "index to a string"
*/
a->ldlbry.aiinflnm = (char *) ((int) a->ldlbry.aiinflnm - (int) strbase);
a->ldlbry.aifilnam = (char *) ((int) a->ldlbry.aifilnam - (int) strbase);
fwrite( a, 1, sizeof(ACTITEM), trnfdes );
return( a->ldlbry.ainext );
}
ACTITEM *
outds4(a)
ACTITEM *a;
{
/*
* Output one AIDFNSCN or AIDFNGRP data structure
*
* Convert a "pointer to a string" to a "index to a string"
*/
register ACTITEM *anext, *b;
ACTITEM *outds5();
anext = a->dfnscn.ainext;
a->dfnscn.aiinflnm = (char *) ((int) a->dfnscn.aiinflnm - (int) strbase);
fwrite( a, 1, sizeof(ACTITEM), trnfdes );
b = (ACTITEM *) a->dfnscn.sectspec.head;
switch( a->dfnscn.aitype ) {
case AIDFNSCN:
while( b )
switch( b->addscn.aitype ) {
case AIADDSCN:
b = outds5(b);
break;
case AIADFILE:
b = outds3(b);
break;
case AIEVEXPR:
b = outds6(b);
break;
}
break;
case AIDFNGRP:
while( b )
b = outds4(b);
break;
default:
lderror(2,0,NULL,"failure dumping an AIDFNxxx data structure\n");
}
return( a->dfnscn.ainext );
}
ACTITEM *
outds5(a)
ACTITEM *a;
{
/*
* Output one AIADDSCN data structure
*
* Convert a "pointer to a string" to a "index to a string"
*/
a->addscn.aiinflnm = (char *) ((int) a->addscn.aiinflnm - (int) strbase);
a->addscn.aiscfile = (char *) ((int) a->addscn.aiscfile - (int) strbase);
fwrite( a, 1, sizeof(ACTITEM), trnfdes );
return( a->addscn.ainext );
}
ACTITEM *
outds6(a)
ACTITEM *a;
{
/*
* Output one AIEVEXPR data structure
*
* Convert a "pointer to a string" to a "index to a string"
*/
a->evexpr.aiinflnm = (char *) ((int) a->evexpr.aiinflnm - (int) strbase);
fwrite( a, 1, sizeof(ACTITEM), trnfdes );
outds7( a->evexpr.aiexptr );
return( a->evexpr.ainext );
}
outds7(e)
ENODE *e;
{
/*
* Output one ENODE data structure
*/
switch( (unsigned) e->gnode.exop ) {
case INT:
case DOT:
fwrite( e, 1, sizeof(ENODE), trnfdes );
break;
case NAME:
fwrite( e, 1, sizeof(ENODE), trnfdes );
break;
default:
fwrite( e, 1, sizeof(ENODE), trnfdes );
if( e->gnode.exleft )
outds7(e->gnode.exleft);
if( e->gnode.exright )
outds7(e->gnode.exright);
}
}
TVASSIGN *
outds8(s)
TVASSIGN *s;
{
/*
* Output one tv slot assignment (TVASSIGN) structure
*/
fwrite( s, sizeof(TVASSIGN), 1, trnfdes);
return( s->nxtslot );
}
#endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.