/* lkmain.c */ /* * (C) Copyright 1989 * All Rights Reserved * * Alan R. Baldwin * 721 Berkeley St. * Kent, Ohio 44240 */ #include #include "aslink.h" VOID main(argc, argv) char *argv[]; { register char *p; register c, i; FILE *afile(); pflag = 1; startp = (struct lfile *) new (sizeof (struct lfile)); for (i=1; if_type = F_STD; break; case 'f': case 'F': startp->f_type = F_LNK; break; case 'n': case 'N': pflag = 0; break; case 'p': case 'P': pflag = 1; break; default: usage(); } } } else { if (startp->f_type == F_LNK) { startp->f_idp = p; } } } if (startp->f_type == NULL) usage(); if (startp->f_type == F_LNK && startp->f_idp == NULL) usage(); cfp = NULL; sfp = NULL; filep = startp; while (1) { ip = ib; if (getline() == 0) break; if (pflag && sfp != stdin) fprintf(stdout, "%s\n", ip); if (*ip == NULL || parse()) break; } fclose(sfp); if (linkp == NULL) usage(); syminit(); for (pass=0; pass<2; ++pass) { cfp = NULL; sfp = NULL; filep = linkp; hp = NULL; radix = 10; while (getline()) { ip = ib; link(); } if (pass == 0) { /* * Set area base addresses. */ setbas(); /* * Link all area addresses. */ lnkarea(); /* * Process global definitions. */ setgbl(); /* * Check for undefined globals. */ symdef(stderr); /* * Output Link Map. */ if (mflag) map(); /* * Open output file */ if (oflag == 1) ofp = afile(linkp->f_idp, "ihx", 1); if (oflag == 2) ofp = afile(linkp->f_idp, "s19", 1); } else { reloc('E'); } } } VOID link() { register c; if ((c=endline()) == 0) { return; } switch (c) { case 'X': radix = 16; break; case 'D': radix = 10; break; case 'Q': radix = 8; break; case 'H': if (pass == 0) { newhead(); } else { if (hp == 0) { hp = headp; } else { hp = hp->h_hp; } } break; case 'M': if (pass == 0) module(); break; case 'A': if (pass == 0) newarea(); break; case 'S': if (pass == 0) newsym(); break; case 'T': case 'R': if (pass == 0) break; reloc(c); break; default: break; } if (c == 'X' || c == 'D' || c == 'Q') { if ((c = get()) == 'H') { hilo = 1; } else if (c == 'L') { hilo = 0; } } } VOID map() { register i; register struct head *hdp; /* * Open Map File */ mfp = afile(linkp->f_idp, "map", 1); /* * Output Map Area Lists */ page = 0; lop = NLPP; slew(mfp); ap = areap; while (ap) { lstarea(ap); ap = ap->a_ap; } /* * List Linked Files */ newpag(mfp); fprintf(mfp, "\nFiles Linked [ module(s) ]\n\n"); hdp = headp; filep = linkp; while (filep) { fprintf(mfp, "%-16s", filep->f_idp); i = 0; while (hdp->h_lfile == filep) { if (i % 5) { fprintf(mfp, ", %8.8s", hdp->m_id); } else { if (i) { fprintf(mfp, ",\n%20s%8.8s", "", hdp->m_id); } else { fprintf(mfp, " [ %8.8s", hdp->m_id); } } hdp = hdp->h_hp; i++; } if (i) fprintf(mfp, " ]"); fprintf(mfp, "\n"); filep = filep->f_flp; } /* * List Base Address Definitions */ if (basep) { newpag(mfp); fprintf(mfp, "\nUser Base Address Definitions\n\n"); bsp = basep; while (bsp) { fprintf(mfp, "%s\n", bsp->b_strp); bsp = bsp->b_base; } } /* * List Global Definitions */ if (globlp) { newpag(mfp); fprintf(mfp, "\nUser Global Definitions\n\n"); gsp = globlp; while (gsp) { fprintf(mfp, "%s\n", gsp->g_strp); gsp = gsp->g_globl; } } fprintf(mfp, "\n\f"); symdef(mfp); fclose(mfp); } int parse() { register c; char fid[NINPUT]; while (c = getnb()) { if ( c == '-') { while (ctype[c=get()] == LETTER) { switch(c) { case 'i': case 'I': oflag = 1; break; case 's': case 'S': oflag = 2; break; case 'm': case 'M': ++mflag; break; case 'x': case 'X': xflag = 0; break; case 'q': case 'Q': xflag = 1; break; case 'd': case 'D': xflag = 2; break; case 'e': case 'E': return(1); case 'n': case 'N': pflag = 0; break; case 'p': case 'P': pflag = 1; break; case 'b': case 'B': bassav(); return(0); case 'g': case 'G': gblsav(); return(0); default: fprintf(stderr, "Invalid option\n"); exit(1); } } } else if (ctype[c] == LETTER || ctype[c] == DIGIT) { if (linkp == NULL) { linkp = (struct lfile *) new (sizeof (struct lfile)); lfp = linkp; } else { lfp->f_flp = (struct lfile *) new (sizeof (struct lfile)); lfp = lfp->f_flp; } getfid(fid, c); lfp->f_idp = (char *) new (strlen(fid)+1); strcpy(lfp->f_idp, fid); lfp->f_type = F_REL; } else if (c == ';') { return(0); } else if (c == ',') { ; } else { fprintf(stderr, "Invalid input"); exit(1); } } return(0); } /* * Base string save */ VOID bassav() { if (basep == NULL) { basep = (struct base *) new (sizeof (struct base)); bsp = basep; } else { bsp->b_base = (struct base *) new (sizeof (struct base)); bsp = bsp->b_base; } unget(getnb()); bsp->b_strp = (char *) new (strlen(ip)+1); strcpy(bsp->b_strp, ip); } VOID setbas() { register v; char id[NCPS]; bsp = basep; while (bsp) { ip = bsp->b_strp; getid(id, -1); if (getnb() == '=') { v = expr(0); for (ap = areap; ap != NULL; ap = ap->a_ap) { if (symeq(id, ap->a_id)) break; } if (ap == NULL) { fprintf(stderr, "No definition of area %s\n", id); } else { ap->a_addr = v; } } else { fprintf(stderr, "No '=' in base expression"); } bsp = bsp->b_base; } } /* * Global string save */ VOID gblsav() { if (globlp == NULL) { globlp = (struct globl *) new (sizeof (struct globl)); gsp = globlp; } else { gsp->g_globl = (struct globl *) new (sizeof (struct globl)); gsp = gsp->g_globl; } unget(getnb()); gsp->g_strp = (char *) new (strlen(ip)+1); strcpy(gsp->g_strp, ip); } VOID setgbl() { register v; register struct sym *sp; char id[NCPS]; gsp = globlp; while (gsp) { ip = gsp->g_strp; getid(id, -1); if (getnb() == '=') { v = expr(0); sp = lkpsym(id, 0); if (sp == NULL) { fprintf(stderr, "No definition of symbol %s\n", id); } else { if (sp->s_flag & S_DEF) { fprintf(stderr, "Redefinition of symbol %s\n", id); sp->s_axp = NULL; } sp->s_addr = v; sp->s_type |= S_DEF; } } else { fprintf(stderr, "No '=' in global expression"); } gsp = gsp->g_globl; } } FILE * afile(fn, ft, wf) char *fn; char *ft; { register char *p1, *p2, *p3; register c; FILE *fp; char fb[FILSPC]; p1 = fn; p2 = fb; p3 = ft; while ((c = *p1++) && c != '.') { if (p2 < &fb[FILSPC-4]) *p2++ = c; } *p2++ = '.'; if (*p3 == 0) { if (c == '.') { p3 = p1; } else { p3 = "rel"; } } while (c = *p3++) { if (p2 < &fb[FILSPC-1]) *p2++ = c; } *p2++ = 0; if ((fp = fopen(fb, wf?"w":"r")) == NULL) { fprintf(stderr, "%s: cannot %s.\n", fb, wf?"create":"open"); exit(1); } return (fp); } char *usetxt[] = { "Startup:", " -c Command line input", " -f file [.lnk] File input", "Usage: [-Options] file [file ...]", " -p Prompt and echo of file.lnk to stdout(default)", " -n No echo of file.lnk to stdout", "Relocation:", " -b area base address = expression", " -g global symbol = expression", "Map format:", " -m Map output generated as file.map", " -x Hexidecimal (default)", " -d Decimal", " -q Octal", "Output:", " -i Intel Hex as file.ihx", " -s Motorola S19 as file.s19", "End:", " -e or null line terminates input", "", 0 }; VOID usage() { register char **dp; for (dp = usetxt; *dp; dp++) fprintf(stderr, "%s\n", *dp); exit(1); }