Aerospace



Discussion Forum

Home

Company Information

Information Request

Linux How-to Guides

ADSP 21xx
Digital Signal Processing
Tutorials

SW Utilities

On-line Order Form

Aerospace Projects

Commercial Projects

Circuit Boards

Server Support


bonk

Have you found this site useful? Did we save you time? Did we cure your head-ache? Is your hair growing back now?

Please make a donation to help with maintenance.


Objective Real-Time Software on the ADSP21XX

ASL21 Compatible Linker Locater

Introduction

In this chapter, we present the full ANSI C source code of a compatible linker for the ADSP 21XX family of DSP. This linker is currently still in Beta form. It is intended to become an alternative for the LD21 linker and would in its final form be able to handle overlays for the 218X series.

The code is written using a 16 bit ANSI C compiler, which ensures that it would be possible to port the linker to any platform.

Missing features

The current version still has significant features missing, although it is useable for a small embedded system if one would create the link and locate response file with care, to locate circular buffers and absolute segments manually:

  • Overlay handling is not supported
  • Circular buffers are not located correctly
  • Absolute segments are ignored
  • Cannot link object library files

Structure

The linker consists of the following code modules:

  • ASL21.C - Source Linker. Link source code and initializers into two monster files target.src and target.ini. All identifiers are listed in the target.mem file.
  • ASG21.C - Garbage disposal. Filters all input files and removes garbage characters before processing starts.
  • ASE21.C - External definition resolver. Attempts to resolve all external, global and entry definitions.
  • ASO21.C - Origin locater. Locate all identifiers according to the target memory definition in target.loc and creates a memory map file target.map.
  • ASA21.C - Anotater. Anotates the source code with the results of the linker and locater and creates the executable file target.exe.

Module ASL21

/*********************************************************************
*
* Name:  ASL21.C
* Description: ADSP linker/locater
*
* Copyright (c) Aerospace Software Ltd, 1998.
*
* Revision  Date     Author            Remarks
* -------------------------------------------------------------------
* 1.0       July 98  Herman Oosthuysen
*
*********************************************************************/

#define ASL
#include "dos.h"
#include "stdio.h"
#include "string.h"
#include "ctype.h"
#include "asl21.h"
#undef ASL

/*********************************************************************
* Code
*********************************************************************/
void main(int argc, char *argv[])
{
   FILE           *cdefile = NULL;      /* Assembled Code */
   FILE           *objfile = NULL;      /* Destination label offsets */
   FILE           *intfile = NULL;      /* Initialization data */
   FILE           *locfile = NULL;      /* Link and Locate data */
   FILE           *memfile = NULL;      /* Linker memory map */
   FILE           *srcfile = NULL;      /* Concatenated source file */
   FILE           *inifile = NULL;      /* Concatenated initialization file */
   FILE           *exefile = NULL;      /* Located executable source */
   FILE           *mapfile = NULL;      /* Locator memory map */
   FILE           *symfile = NULL;      /* Symbols */

   char           filename[12];
   char           name[12];
   char           locname[12];
   char           line[256];
   char           work[256];
   char           token[32];
   char           *search;
   char           *tok;
   int            row;
   int            mpos;
   int            pos;
   int            cnt;
   int            length = 0;
   int            linking;
   int            varsize;
   char           err = 0;

   /* show opening lines */
   asl_copyright_display();

   /* Argument error handler */
   if(argc < 2)
   {
      printf("Example: asl21 targetname\n\n\r");
      exit(1);
   }

   /* Extract the target file name */
   pos = strcspn(argv[1], ".");
   if(pos > 8)
   pos = 8;
   for(cnt = 0; cnt < pos; cnt++)
      name[cnt] = argv[1][cnt];
   name[pos] = 0;

   /*
    * open all general I/O files
    */
   asl_open_files(&inifile, &srcfile, &locfile, &exefile, &mapfile, &symfile, &memfile, filename, name);

   /*
    * Linker
    */
   printf("Linking...\n\r");
   linking = TRUE;

   /*
    * LOC file read till the .OBJECTS keyword
    */
   do
   {
      length = asl_rd_line(locfile, line);
      if(length == EOF)
      {
         printf("%s.loc file error 1\n\r", name);
         exit(1);
      }
   }while(stricmp(line, ASL_OBJ) != 0);

   do
   {
      /* read the first file name from the list */
      length = asl_rd_line(locfile, line);
      if(length == EOF)
      {
         printf("%s.loc file error 2\n\r", name);
         exit(1);
      }

      /*
       * Exit upon .ENDOBJECTS keyword
       */
      if(stricmp(line, ASL_EOBJ) != 0)
      {
         /*
          * open all the link files
          */
         asl_link_files(&cdefile, &objfile, &intfile, line, filename, locname);
         
         /*
          * Append the code and constants to the monster Source file
          */
         asl_concat_src(cdefile, srcfile);
         asl_concat_src(intfile, inifile);

         /*
          * OBJ file add object information to the Linker .mem file
          */
         asl_parse_module(objfile, memfile, locname, &row);
         asl_parse_label(objfile, memfile, &row);
         asl_parse_modsize(objfile, memfile, &row);
         asl_parse_variable(objfile, memfile, &row);
         asl_parse_global(objfile, memfile, &row);
         asl_parse_entry(objfile, memfile, &row);
         asl_parse_external(objfile, memfile, &row);
      }
      else
         linking = FALSE;

   }while(linking);
   printf("Linker Done!\n\n\r");

   /*
    * Resolve extern definitions
    */
   fclose(memfile);
   strcpy(filename, name);
   strcat(filename, ".mem");
   memfile = fopen(filename, "rb");

   err = ase_err_check(memfile, mapfile, name);

   /*
    * Locate the code and create a map file of all label addresses
    */
   err = aso_org(memfile, locfile, inifile, mapfile, name);

   /*
    * Create and Annotate the exe file from the monster src file
    */
        fclose(inifile);
   strcpy(filename, name);
        strcat(filename, ".ini");
        inifile = fopen(filename, "rb");

   fclose(srcfile);
   strcpy(filename, name);
   strcat(filename, ".src");
   srcfile = fopen(filename, "rb");

   fclose(mapfile);
   strcpy(filename, name);
   strcat(filename, ".map");
   mapfile = fopen(filename, "rb");
   
   asa_annotate(inifile, srcfile, exefile, mapfile);
   

   /* Close all the files */
   flushall();
   fcloseall();

   printf("\n\rCheers, have fun!\n\r");

   exit(0);
}


/*********************************************************************
* Name:        asl_copyright_display
* Description: display copyright notice in files
* Constraints: none
*********************************************************************/
void asl_copyright_display(void)
{
   printf("\n\r%s\n\r", ASL_NOTICE1);
   printf("%s\n\r", ASL_NOTICE2); 
   printf("%s\n\n\r", ASL_NOTICE3); 
}
   
/*********************************************************************
* Name:        asl_copyright_file
* Description: print copyright notice in files
* Constraints: none
*********************************************************************/
void asl_copyright_files(FILE *file)
{
   fprintf(file, "%s\n", ASL_NOTICE1);
   fprintf(file, "%s\n", ASL_NOTICE2); 
   fprintf(file, "%s\n\n", ASL_NOTICE3); 
}
   
/*********************************************************************
* Name:        asl_open_files
* Description: open all the general I/O files
* Constraints: none
*********************************************************************/
void asl_open_files(FILE **inifile, FILE **srcfile, FILE **locfile, FILE **exefile,
                    FILE **mapfile, FILE **symfile, FILE **memfile,
                    char *filename, char *name)
{
   /* build a concatenated initialization file name */
   strcpy(filename, name);
   strcat(filename, ".ini");
   *inifile = fopen(filename, "wb");
   if(*inifile == NULL)
   {
      printf("Ini file %s error 6\n\r", name);
      exit(1);
   }

   /* build a concatenated source file name */
   strcpy(filename, name);
   strcat(filename, ".src");
   *srcfile = fopen(filename, "wb");
   if(*srcfile == NULL)
   {
      printf("Src file %s error 6\n\r", name);
      exit(1);
   }

   /* build a Link and Locate data file name */
   strcpy(filename, name);
   strcat(filename, ".loc");
   asg_filter(filename);
   *locfile = fopen(filename, "rb");
   if(*locfile == NULL)
   {
      printf("Loc file %s error 6\n\r", name);
      exit(1);
   }

   /* build a located executable  file name */
   strcpy(filename, name);
   strcat(filename, ".exe");
   *exefile = fopen(filename, "wb");
   if(*exefile == NULL)
   {
      printf("Exe file %s error 7\n\r", name);
      exit(1);
   }

   /* build a locater memory map file name */
   strcpy(filename, name);
   strcat(filename, ".map");
   *mapfile = fopen(filename, "wb");
   if(*mapfile == NULL)
   {
      printf("Map file %s error 8\n\r", name);
      exit(1);
   }
   asl_copyright_files(*mapfile);

   /* build a locater symbol file name */
   strcpy(filename, name);
   strcat(filename, ".sym");
   *symfile = fopen(filename, "wb");
   if(*symfile == NULL)
   {
      printf("%s.sym file error 9\n\r", name);
      exit(1);
   }
   asl_copyright_files(*symfile);

   /* build a linker memory map file name */
   strcpy(filename, name);
   strcat(filename, ".mem");
   *memfile = fopen(filename, "wb");
   if(*memfile == NULL)
   {
      printf("%s.mem file error 10\n\r", name);
      exit(1);
   }
   asl_copyright_files(*memfile);
}


/*********************************************************************
* Name:        asl_link_files
* Description: open all the link files
* Constraints: none
*********************************************************************/
void asl_link_files(FILE **cdefile, FILE **objfile, FILE **intfile,
          char *line, char *filename, char *name)
{
   int   pos;
   int   cnt;

   /* Extract the target file name */
   pos = strcspn(line, ".");
   if(pos > 8)
   pos = 8;
   for(cnt = 0; cnt < pos; cnt++)
      name[cnt] = line[cnt];
   name[pos] = 0;

   /* build a code file name */
   strcpy(filename, name);
   strcat(filename, ".cde");
   asg_filter(filename);
   *cdefile = fopen(filename, "rb");
   if(*cdefile == NULL)
   {
      printf("%s.cde file error 3\n\r", name);
      exit(1);
   }

   /* build an object file name */
   strcpy(filename, name);
   strcat(filename, ".obj");
   asg_filter(filename);
   *objfile = fopen(filename, "rb");
   if(*objfile == NULL)
   {
      printf("%s.obj file error 4\n\r", name);
      exit(1);
   }

   /* build an initialization file name */
   strcpy(filename, name);
   strcat(filename, ".int");
   asg_filter(filename);
   *intfile = fopen(filename, "rb");
   if(*intfile == NULL)
   {
      printf("%s.int file error 5\n\r", name);
      exit(1);
   }
}

/*********************************************************************
* Name:        asl_concat_src      
* Description: concatenate the cde to the monster src file
* Constraints: none
*********************************************************************/
void  asl_concat_src(FILE *cdefile, FILE *srcfile)
{
   int   data;
   
   fprintf(srcfile, "\n\n");     /* for readability */
   data = fgetc(cdefile);
   while(data != EOF)
   {
      fputc(data, srcfile);      /* copy characters */
      data = fgetc(cdefile);
   }
}

/*********************************************************************
* Name:        asl_parse_external
* Description: parse the procedure/variable external definitions in the OBJ file
* Constraints: none
*********************************************************************/
void asl_parse_external(FILE *objfile, FILE *memfile, int *row)
{
   char           line[256];
   char           work[256];
   char           token[32];
   char           *tok;
   char           *search;
   int            varsize;
   int            pos;
   int            mpos;
   int            length = 0;

   /*
    * list all externals
    */
   fprintf(memfile, "\n");
   rewind(objfile);
   *row = 0;
   do
   {
      do
      {
         *row++;
         length = asl_rd_line(objfile, line);
         if(length != EOF)
         {
            pos = asl_find_token(line, work, ASC_DNLINK, ASC_DOLLARS);
            if(pos > 0)
            {
               pos = asl_marked_token(line, work, ASC_EXTERN, token, ASC_DOTSPACE);
               if(pos > 0)
               {
                  fprintf(memfile, "\n%s %s", ASM_EXTERNAL, token);
                  do
                  {
                     /* find next token */
                     search = NULL;
                     tok = strtok(search, ASC_COMMAS);
                     if(tok == NULL)
                        break;
                     else
                        fprintf(memfile, "\n%s %s", ASM_EXTERNAL, tok);
                  }while(tok != NULL);
               }
            }
         }
         else
            pos = 0;
      }while((pos == 0) && (length != EOF));
   }while(length != EOF);
   
   /*
    * end the mem file neatly
    */
   fprintf(memfile, "\n\r");
}

/*********************************************************************
* Name:        asl_parse_entry
* Description: parse the procedure entry definitions in the OBJ file
* Constraints: none
*********************************************************************/
void asl_parse_entry(FILE *objfile, FILE *memfile, int *row)
{
   char           line[256];
   char           work[256];
   char           token[32];
   char           *tok;
   char           *search;
   int            varsize;
   int            pos;
   int            mpos;
   int            length = 0;

   /*
    * list all entrypoints
    */
   fprintf(memfile, "\n");
   rewind(objfile);
   *row = 0;
   do
   {
      do
      {
         *row++;
         length = asl_rd_line(objfile, line);
         if(length != EOF)
         {
            pos = asl_find_token(line, work, ASC_DNLINK, ASC_DOLLARS);
            if(pos > 0)
            {
               pos = asl_marked_token(line, work, ASC_ENTRY, token, ASC_DOTSPACE);
               if(pos > 0)
               {
                  fprintf(memfile, "\n%s %s", ASM_ENTRY, token);
                  do
                  {
                     /* find next token */
                     search = NULL;
                     tok = strtok(search, ASC_COMMAS);
                     if(tok == NULL)
                        break;
                     else
                        fprintf(memfile, "\n%s %s", ASM_ENTRY, tok);
                  }while(tok != NULL);
               }
            }
         }
         else
            pos = 0;
      }while((pos == 0) && (length != EOF));
   }while(length != EOF);
}

/*********************************************************************
* Name:        asl_parse_global
* Description: parse the global definitions in the OBJ file
* Constraints: none
*********************************************************************/
void asl_parse_global(FILE *objfile, FILE *memfile, int *row)
{
   char           line[256];
   char           work[256];
   char           token[32];
   char           *tok;
   char           *search;
   int            varsize;
   int            pos;
   int            mpos;
   int            length = 0;

   /*
    * list all globals
    */
   fprintf(memfile, "\n");
   rewind(objfile);
   *row = 0;
   do
   {
      do
      {
         *row++;
         length = asl_rd_line(objfile, line);
         if(length != EOF)
         {
            pos = asl_find_token(line, work, ASC_DNLINK, ASC_DOLLARS);
            if(pos > 0)
            {
               pos = asl_marked_token(line, work, ASC_GLOBAL, token, ASC_DOTSPACE);
               if(pos > 0)
               {
                  fprintf(memfile, "\n%s %s", ASM_GLOBAL, token);
                  do
                  {
                     /* find next token */
                     search = NULL;
                     tok = strtok(search, ASC_COMMAS);
                     if(tok == NULL)
                        break;
                     else
                        fprintf(memfile, "\n%s %s", ASM_GLOBAL, tok);
                  }while(tok != NULL);
               }
            }
         }
         else
            pos = 0;
      }while((pos == 0) && (length != EOF));
   }while(length != EOF);
}

/*********************************************************************
* Name:        asl_parse_variable
* Description: parse the variable lists in the OBJ file
* Constraints: none
*********************************************************************/
void asl_parse_variable(FILE *objfile, FILE *memfile, int *row)
{
   char           line[256];
   char           work[256];
   char           token[32];
   char           *tok;
   char           *search;
   int            varsize;
   int            pos;
   int            mpos;
   int            length = 0;

   /*
    * find all constants/variables
    */
   rewind(objfile);
   row = 0;
   do
   {
      do
      {
         row++;
         length = asl_rd_line(objfile, line);
         if(length != EOF)
         {
            pos = asl_find_token(line, work, ASC_DNLINK, ASC_DOLLARS);
            if(pos > 0)
            {
               pos = asl_find_token(line, work, ASC_VAR, ASC_DOTCOMMA);
               if(pos > 0)
               {
                  fprintf(memfile, "\n\n%s", ASM_SPACE);
                  pos = asl_find_token(line, work, ASC_PM, ASC_DOTCOMMA);
                  if(pos > 0)
                     fprintf(memfile, " %s", ASM_PM_SEG);
                  pos = asl_find_token(line, work, ASC_DM, ASC_DOTCOMMA);
                  if(pos > 0)
                     fprintf(memfile, " %s", ASM_DM_SEG);

                  pos = asl_find_token(line, work, ASC_CIRC, ASC_COMMAS);
                  if(pos > 0)
                     fprintf(memfile, "\n%s", ASM_CIRCULAR);

                  pos = asl_marked_token(line, work, ASC_SEGNAME, token, ASC_DOTCOMMA);
                  if(pos > 0)
                     fprintf(memfile, "\n%s %s", ASM_SEGMENT, token);
                  else
                     fprintf(memfile, "\n%s %s", ASM_SEGMENT, ASM_DONTCARE);

                  /* variable and size list */
                  varsize = 0;
                  pos = asl_marked_token(line, work, ASC_NAME, token, ASC_COMMAS);
                  if(pos > 0)
                  {
                     fprintf(memfile, "\n%s %s", ASM_VARIABLE, token);
                     do
                     {
                        /* find next token */
                        search = NULL;
                        tok = strtok(search, ASC_COMMAS);
                        if(tok == NULL)
                        {
                           if(!varsize)
                              fprintf(memfile, " %s", ASM_DEF_SIZE);
                           break;
                        }
                        else
                        {
                           if(isdigit(tok[1]))
                           {
                              varsize = 1;
                              fprintf(memfile, " %s", &tok[1]);
                           }
                           else
                           {
                              varsize = 0;
                              fprintf(memfile, "\n%s %s", ASM_VARIABLE, tok);
                           }
                        }

                     }while(tok != NULL);
                  }
               }
            }
         }
         else
            pos = 0;
      }while((pos == 0) && (length != EOF));
   }while(length != EOF);
}

/*********************************************************************
* Name:        asl_parse_modsize
* Description: parse the module size in the OBJ file
* Constraints: none
*********************************************************************/
void asl_parse_modsize(FILE *objfile, FILE *memfile, int *row)
{
   char           line[256];
   char           work[256];
   char           token[32];
   int            pos;
   int            mpos;
   int            length = 0;

   /*
    * find the module code size
    */
   rewind(objfile);
   row = 0;
   do
   {
      row++;
      length = asl_rd_line(objfile, line);
      if(length != EOF)
      {
         mpos = asl_find_token(line, work, ASC_MODULE, ASC_DOLLARS);
         if(mpos > 0)
         {
            pos = asl_find_token(line, work, ASC_MODOUT, ASC_DOTCOMMA);
            if(pos > 0)
            {
               pos = asl_marked_token(line, work, ASC_MODSIZE, token, ASC_COMMAS);
               if(pos > 0)
                  fprintf(memfile, "\n\n%s %s", ASM_MODSIZE, token);
            }
         }
      }
   }while(length != EOF);
}

/*********************************************************************
* Name:        asl_parse_label
* Description: parse the label references in the OBJ file
* Constraints: none
*********************************************************************/
void asl_parse_label(FILE *objfile, FILE *memfile, int *row)
{
   char           line[256];
   char           work[256];
   char           token[32];
   int            pos;
   int            length = 0;

   /*
    * find all label addresses
    * labels are in PM by definition
    */
   fprintf(memfile, "\n\n%s %s", ASM_SPACE, ASM_PM_SEG);
   do
   {
      do
      {
         *row++;
         length = asl_rd_line(objfile, line);
         if(length != EOF)
         {
            pos = asl_find_token(line, work, ASC_DNLINK, ASC_DOLLARS);
            if(pos > 0)
            {
               pos = asl_marked_token(line, work, ASC_LABEL, token, ASC_DOTSPACE);
               if(pos > 0)
                  fprintf(memfile, "\n%s %s", ASM_LABEL, token);
               pos = asl_marked_token(line, work, ASC_OFFSET, token, ASC_COMMAS);
               if(pos > 0)
                  fprintf(memfile, " %s", token);
            }
         }
         else
            pos = 0;
      }while((pos == 0) && (length != EOF));
   }while(length != EOF);
}

/*********************************************************************
* Name:        asl_parse_module
* Description: parse the module name line in the OBJ file
* Constraints: none
*********************************************************************/
void asl_parse_module(FILE *objfile, FILE *memfile, char *name, int *row)
{
   char           line[256];
   char           work[256];
   char           token[32];
   int            mpos;
   int            pos;
   int            length = 0;

   /*
    * find module and segment names in $m line in obj file
    * the PM/DM indication in the module line is superfluous,
    * so don't parse it.
    */
   *row = 0;
   fprintf(memfile, "\n\n%s = %s.obj", ASM_FILE, name);
   do
   {
      *row++;
      length = asl_rd_line(objfile, line);
      if(length == EOF)
      {
         printf("%s.obj file error 11 line %u\n\r", name, row);
         exit(1);
      }
      mpos = asl_find_token(line, work, ASC_MODULE, ASC_DOLLARS);
      if(mpos > 0)
      {
         pos = asl_marked_token(line, work, ASC_NAME, token, ASC_COMMAS);
         if(pos > 0)
            fprintf(memfile, "\n%s %s", ASM_MODULE, token);
         else
            fprintf(memfile, "\n%s %s", ASM_MODULE, ASM_UNKNOWN);

         pos = asl_marked_token(line, work, ASC_ABSOLUTE, token, ASC_COMMAS);
         if(pos > 0)
            fprintf(memfile, "\n%s %s", ASM_ORIGIN, token);

         pos = asl_marked_token(line, work, ASC_SEGNAME, token, ASC_COMMAS);
         if(pos > 0)
            fprintf(memfile, "\n%s %s", ASM_SEGMENT, token);
         else
            fprintf(memfile, "\n%s %s", ASM_SEGMENT, ASM_DONTCARE);
      }

   }while((mpos == 0) && (length != EOF));
}

/*********************************************************************
* Name:        asl_find_token
* Description: Find a known string token
* Constraints: return the token length in AX
*              returns zero if no matching token found
*********************************************************************/
int   asl_find_token(char *line, char *work, char *token, char *delimiters)
{
   int   len;
   char   *search;
   char  *tok;

   len = strlen(token);
   strcpy(work, line);
   search = work;

   /* read until the token matches */
   do
   {
      tok = strtok(search, delimiters);
      search = NULL;
   }while(((strncmp(tok, token, len)) != 0) &&
      (tok != NULL));

   /* test the token */
   if(tok == NULL)
      len = 0;

   return len;
}

/*********************************************************************
* Name:        asl_marked_token
* Description: Find a string token following a marker string
* Constraints: return the token length in AX
*              returns zero if no matching token found
*********************************************************************/
int   asl_marked_token(char *line, char *work, char *marker, char *token, char *delimiters)
{
   int   len;
   char   *search;
   char  *tok;

   len = strlen(marker);
   strcpy(work, line);
   search = work;

   /* read tokens until the marker matches */
   do
   {
      tok = strtok(search, delimiters);
      search = NULL;
   }while(((strncmp(tok, marker, len)) != 0) &&
      (tok != NULL));

   /* strip the marker from the token */
   if(tok != NULL)
      strcpy(token, &tok[len]);
   else
      len = 0;

   return len;
}

/*********************************************************************
* Name:        asl_rd_line
* Description: Read a line from a file, skipping empty lines
* Constraints: return the length read in AX
*********************************************************************/
int   asl_rd_line(FILE *infile, char *line)
{
   int   cnt = 0;

   do
   {
      line[cnt] = fgetc(infile);
   }while((line[cnt] != EOF) && (iscntrl(line[cnt])));

   while((line[cnt] != EOF) && (!iscntrl(line[cnt])))
   {
      cnt++;
      line[cnt] = fgetc(infile);
   }

   if(line[cnt] == EOF)
   cnt = EOF;
   line[cnt] = 0;

   return cnt;
}

/*************************** EOF - ASL21 ****************************/


Module ASG21

/*********************************************************************
*
* Name:        asg21.c
* Description: Garbage removal 
*              Filter garbage characters from an input file
*
* Copyright (c) Aerospace Software Ltd, 1998.
*
* Revision  Date     Author            Remarks
* -------------------------------------------------------------------
* 1.0       July 98  Herman Oosthuysen
*
*********************************************************************/

#define  ASG
#include "dos.h"
#include "stdio.h"
#include "string.h"
#include "ctype.h"
#include "asl21.h"
#undef   ASG

/*********************************************************************
* Code
*********************************************************************/
/*********************************************************************
* Name:        asg_filter
* Description: Filter garbage characters from a file
* Constraints: none
*********************************************************************/
void asg_filter(char *filename)
{
   FILE  *tmpfile;
   FILE  *infile;
        int   data = 0;
   int   work;

   /*
    * Open the files for filtering
    */
        infile = fopen(filename, "rb");

        remove(ASG_TMPFILE);
   tmpfile = fopen(ASG_TMPFILE, "wb");

   if((tmpfile == NULL) || (infile == NULL))
        {
      printf("Garbage filter File I/O Error. Disk Full?\n\r");
      exit(1);
   }


   /*
    * Filter out all garbage characters in the source files
    * and end it with a single CPM EOF marker
    * to ensure that the text string parsing algorithms will
    * work reliably.
    *
    * Allow characters from Space to Tilde, as well as
    * Line Feed, Cariage Return and Tab only, 
    * while removing all other garbage.
    */
   while(data != EOF)
   {
                data = fgetc(infile);
      work = data;
      if(((work >= ASG_SP) && (work <= ASG_TL)) ||
         (work == ASG_CR) || (work == ASG_LF) || (work == ASG_HT))
                        fputc(work, tmpfile);
   }
   fprintf(tmpfile, "\n\r");
   fputc(ASG_SIB, tmpfile);

   /*
    * Rename the files
         */
        fclose(infile);
        fclose(tmpfile);
        remove(filename);
        rename(ASG_TMPFILE, filename);

}


Module ASE21

/*********************************************************************
*
* Name:        ASE21.C
* Description: ADSP linker/locater external definition resolver
*              Verify that all external definitions can be resolved
*              List unresolved externals on screen and in the map file
*
* Copyright (c) Aerospace Software Ltd, 1998.
*
* Revision  Date     Author            Remarks
* -------------------------------------------------------------------
* 1.0       July 98  Herman Oosthuysen
*
*********************************************************************/

#include "dos.h"
#include "stdio.h"
#include "string.h"
#include "ctype.h"
#include "asl21.h"


/*********************************************************************
* Code
*********************************************************************/
/*********************************************************************
* Name:        ase_err_check
* Description: scan MEM file and resolve entry, external and global defs
*              ensure that for every external, there is either a global
*              or an entry definition.
* Constraints: returns ar = err, 0 = OK, 1 = error
*********************************************************************/
int   ase_err_check(FILE *memfile, FILE *mapfile, char *name)
{
   FILE     *tmpfile;
   char     filename[256];
   int      data;
   int      err = 0;
   int      length;
   int      len;
   int      len2;
   char     line[1024];
   char     line2[1024];
   char     *token;
   char     *extlabel;
   char     *glblabel;
   char     *search;
   int      found;

   /*
    * copy the mem file to a temporary file
    * to enable execution of a comparitive search
    */
        printf("Cross Checking...\n\r");
   rewind(memfile);
   strcpy(filename, name);
   strcat(filename, ".mem");

   strcpy(filename, name);
   strcat(filename, ".tmp");
   remove(filename);
   tmpfile = fopen(filename, "wb");

   if(tmpfile != NULL)
   {
      /*
       * simple file copy
       */
      data = fgetc(memfile);
      while(data != EOF)
      {
         fputc(data, tmpfile);
         data = fgetc(memfile);
      }
      fclose(tmpfile);

      tmpfile = fopen(filename, "rb");
      rewind(memfile);

      /*
       * Wind up the mapfile
       */
      rewind(mapfile);
      asl_copyright_files(mapfile);

      /*
       * find and test all the external definitions
       * every .EXTERNAL should have either a .ENTRY or .GLOBAL
       */
      do
      {
         /*
          * find an external definition in the MEM file
          */
         do
         {
            length = asl_rd_line(memfile, line);
            token = strtok(line, ASC_SPACE);
                        }while(((stricmp(token, ASM_EXTERNAL)) != 0) && (length != EOF));

         search = NULL;
         extlabel = strtok(search, ASC_SPACE);

         /*
          * find a matching entry/global definition in the TMP file
                         */

                        if(extlabel != NULL)
                        {
                                rewind(tmpfile);
                                err = 1;
                                do
                                {
                                        found = FALSE;
                                        do
                                        {
                                                len2 = asl_rd_line(tmpfile, line2);
                                                token = strtok(line2, ASC_SPACE);
                                                found = (stricmp(token, ASM_GLOBAL) == 0);
                                                found |= (stricmp(token, ASM_ENTRY) == 0);
                                        }while((!found) && (len2 != EOF));

                                        if(found)
                                        {
                                                search = NULL;
                                                glblabel = strtok(search, ASC_SPACE);
                                                err = strcmp(glblabel, extlabel);
                                        }
                                }while((err != 0) && (len2 != EOF));

                                /*
                                 * Display and save unresolved externals
                                 */
                                if(err != 0)
                                {
                                        err = 0;
                                        printf("Unresolved external definition %s\n\r", extlabel);
                                        fprintf(mapfile, "Unresolved external definition %s\n", extlabel);
                                }
                        }
      }while(length != EOF);
   }
        else
   {
      printf("File I/O error - disk full?\n\r");
      err = 1;
   }
   fclose(tmpfile);
   remove(filename);
   printf("Cross Checker done!\n\n\r");

   return err;
}



/************************* EOF-ASE21.C ******************************/


Module ASO21

/*********************************************************************
*
* Name:        ASO21.C
* Description: Origin locater
*              Sort the contents of the mem file and create a located
*              map file according to the information in the loc file.
*
* Copyright (c) Aerospace Software Ltd, 1998.
*
* Revision  Date     Author            Remarks
* -------------------------------------------------------------------
* 1.0       July 98  Herman Oosthuysen
*
*********************************************************************/

#include "dos.h"
#include "stdio.h"
#include "string.h"
#include "ctype.h"
#include "asl21.h"


/*********************************************************************
* Code
*********************************************************************/
char        aso_pmfill[ASO_MEMSIZE];      /* overlap tracking */
char        aso_dmfill[ASO_MEMSIZE];

/*********************************************************************
* Name:        aso_org
* Description: scan MEM file and locate the code and variables
* Constraints: returns ar = err, 0 = OK, 1 = error
*              Since the addressable space of this processor is small, simply open
*              large arrays for data and code space labels, to look for overlaps, while
*              performing the actual locating directly to a map file.
*
* Note:        Does not locate circular buffers or absolute segments
*********************************************************************/
int   aso_org(FILE *memfile, FILE *locfile, FILE *inifile, FILE *mapfile, char *name)
{
   int      err = 0;
   int      loclength = 0;
   int      locln = 0;
   int      memlength = 0;
   int      memln = 0;

   char     line[1024] = "";
   char     segname[256] = "";
   char     *token;
   char     *search;

   char     modstr[32] = ASM_DONTCARE;
   char     spacestr[32] = ASM_PM_SEG;
   char     segstr[32] = ASM_DONTCARE;
   char     labelstr[32] = "";
   char     varstr[32] = "";

   int      space = 0;
   int      modstart = 0;
   int      modend = 0;
   int      modsize = 0;
   int      segstart = 0;
   int      segend = 0;
   int      address = 0;
   int      labeloffset = 0;
   int      varsize = 0;

   int      overlay = FALSE;
   int      cnt;
   int      haveseg = FALSE;
   int      havemod = FALSE;

   /* File error check */
   printf("Locating...\n\r");
   if((memfile == NULL) || (locfile == NULL) || 
      (inifile == NULL) || (mapfile == NULL))
   {
      printf("\n\rFile I/O Error!!! - Disk Full!?\n\r");
      exit(1);
   }

   /*
    * rewind the information files
    * and append to the mapfile
    */
   rewind(memfile);
   rewind(locfile);

   /*
    * Flush the overlap checking arrays
    */
   for(cnt = 0; cnt < ASO_MEMSIZE; cnt++)
   {
      aso_pmfill[cnt] = ASO_FREE;
      aso_dmfill[cnt] = ASO_FREE;
   }

   /*
    * LOC file read till the .PMSEGMENTS keyword
    */
   do
   {
      locln++;
      loclength = asl_rd_line(locfile, line);
      if(loclength == EOF)
      {
         printf("%s.loc file error line = %u, no .PMSEGMENTS definition\n\r", name, locln);
         exit(1);
      }
   }while((stricmp(line, ASL_PMSEG) != 0) &&
          (stricmp(line, ASL_DMSEG) != 0));

   /*
    * Code or data space?
    */
   if(stricmp(line, ASL_PMSEG) == 0)
      space = ASO_CODESPACE;
   else
      space = ASO_DATASPACE;

   /*
    * run over the locfile and locate all segments
    * in the memfile
    */
   while (loclength != EOF)
   {
      /*
       * find a segment definition in the locfile
       * extract the start and end of the segment
       */
      token = strtok(line, ASC_SPACE);
      strcpy(segname, token);

      /*
       * Code or data space?
       * put DONTCARE segments in the first available space
       */
                if(stricmp(segname, ASL_PMSEG) == 0)
                {
         space = ASO_CODESPACE;
                        strcpy(segname, ASM_DONTCARE);
                }

                else if(stricmp(segname, ASL_DMSEG) == 0)
                {
         space = ASO_DATASPACE;
                        strcpy(segname, ASM_DONTCARE);
                }


      /*
       * end if not a name, but a .END directive
       */
      else if(stricmp(segname, ASL_END) == 0)
         loclength = EOF;

      else
      {
         /*
                         * find segment start and ignore comments etc
          */
         search = NULL;
         token = strtok(search, ASC_SPACE);
                        if((token != NULL) && ((stricmp(segname, ASM_DONTCARE) != 0)))
                        {
            sscanf(token, "%04X", &segstart);

                                /* find segment end */
                                search = NULL;
                                token = strtok(search, ASC_SPACE);
                                if((token != NULL) && ((stricmp(segname, ASM_DONTCARE) != 0)))
                                        sscanf(token, "%04X", &segend);
                        }
      }


      /*
       * run through the memfile and copy everything in this segment
       * to the mapfile while simultaneously locating it
       * first find the absolute modules and locate them
       * then locate all the named segments
       * if .SEGMENT is DONTCARE then locate it in the last segment
       * assume that memfile has a certain order to it
       */

                /* rewind the memfile */
                rewind(memfile);
                memlength = 0;
                address = segstart;

      while(memlength != EOF)
      {
         memln++;
         memlength = asl_rd_line(memfile, line);
         if(memlength != EOF)
         {
            /* find the first token */
            token = strtok(line, ASC_SPACE);

            /*
             * .MODULE directive?
             */
            if(stricmp(token, ASM_MODULE) == 0)
            {
               /* find module name */
               search = NULL;
               token = strtok(search, ASC_SPACE);
               if(token != NULL)
               {
                  havemod = TRUE;
                  strcpy(modstr, token);
               }
            }

            /*
             * .SPACE directive?
             */
                                else if(stricmp(token, ASM_SPACE) == 0)
            {
               /* find space type */
               search = NULL;
               token = strtok(search, ASC_SPACE);
               if(token != NULL)
               {
                  strcpy(spacestr, token);
               }
            }

            /*
             * .SEGMENT directive?
             */
                                else if(stricmp(token, ASM_SEGMENT) == 0)
            {
               /* find segment name */
               search = NULL;
               token = strtok(search, ASC_SPACE);
               if(token != NULL)
               {
                  strcpy(segstr, token);
                  if(stricmp(segstr, segname) == 0)
                  {
                     /* correct segment: Print info collected to map file */
                     if(havemod)
                     {
                        modstart = address;
                        fprintf(mapfile, "\n%s %s %04X", ASM_MODULE, modstr, modstart);
                                                                havemod = FALSE;
                                                        }

                     fprintf(mapfile, "\n\n%s %s", ASM_SPACE, spacestr);
                     fprintf(mapfile, "\n%s %s", ASM_SEGMENT, segstr);
                     overlay = FALSE;
                     haveseg = TRUE;
                  }
                  else
                     /* wrong segment, loop back */
                                                        haveseg = FALSE;
               }
            }

            /*
             * If the memfile segment is matching the locfile
             * relocate it on the fly to the mapfile
             */
            if(haveseg)
            {
               /*
                * .MODSIZE directive?
                */
               if(stricmp(token, ASM_MODSIZE) == 0)
               {
                  /* find module size */
                  search = NULL;
                  token = strtok(search, ASC_SPACE);
                  if(token != NULL)
                  {
                     sscanf(token, "%04X", &modsize);
                     modend = modstart + modsize;
                     address = modend + 1;
                     fprintf(mapfile, "\n%s %s %04X %04X %04X", ASM_MODSIZE, modstr, modstart, modend, modsize);
                  }
               }

               /*
                * .LABEL directive?
                */
                                        else if(stricmp(token, ASM_LABEL) == 0)
               {
                  /* find label name */
                  search = NULL;
                  token = strtok(search, ASC_SPACE);
                  if(token != NULL)
                  {
                     strcpy(labelstr, token);

                     /* find label offset */
                     search = NULL;
                                                        token = strtok(search, ASC_SPACE);

                     if(token != NULL)
                     {
                        /* locate the program label */
                                                                sscanf(token, "%04X", &labeloffset);

                        for(cnt = address; cnt <= (modstart + labeloffset); cnt++)
                        {
                           /* verify that address is still within limits */
                                                                        if((address >= segend) && (stricmp(segstr, ASM_DONTCARE) != 0))
                           {
                                                                                printf("Segment %s overflow at address %04X\n\r", segstr, address);
                              fprintf(mapfile, "\nERROR: Segment %s overflow at address %04X", segstr, address);
                              break;
                                                                        }

                           /*
                            * mark the start of an overlay, since it
                            * may very well be an error!
                            */
                           if(aso_pmfill[cnt] == ASO_INUSE)
                           {
                              if(overlay == FALSE)
                                 fprintf(mapfile, "\n%s", ASL_OVERLAY);
                              overlay = TRUE;
                           }
                           aso_pmfill[cnt] = ASO_INUSE;
                        }
                        address = modstart + labeloffset;
                        fprintf(mapfile, "\n%s %s %04X", ASM_LABEL, labelstr, address);

                        /* next address */
                        address++;

                     }
                  }
               }

               /*
                * .VARIABLE directive?
                */
                                        else if(stricmp(token, ASM_VARIABLE) == 0)
               {
                  /* find variable name */
                  search = NULL;
                                                token = strtok(search, ASC_SPACE);

                  if(token != NULL)
                  {
                     strcpy(varstr, token);

                     /* find variable size */
                     search = NULL;
                                                        token = strtok(search, ASC_SPACE);

                     if(token != NULL)
                     {
                        /* locate the variable */
                                                                sscanf(token, "%04X", &varsize);

                        for(cnt = address; cnt <= (address + varsize); cnt++)
                        {
                           /* verify that address is still within limits */
                           if(address >= segend)
                           {
                              printf("\n\rSegment %s overflow at address %04X", segstr, address);
                              fprintf(mapfile, "\nERROR: Segment %s overflow at address %04X", segstr, address);
                              break;
                                                                        }

                           /*
                            * mark the start of an overlay, since it
                            * may very well be an error!
                            */
                           if(aso_dmfill[cnt] == ASO_INUSE)
                           {
                                                                                if(overlay == FALSE)
                                 fprintf(mapfile, "\n%s", ASL_OVERLAY);
                                                                                overlay = TRUE;
                           }
                           aso_dmfill[cnt] = ASO_INUSE;
                        }
                        fprintf(mapfile, "\n%s %s %04X %04X", ASM_VARIABLE, varstr, address, varsize);

                        /* next address */
                        address += varsize + 1;
                     }
                  }
               }
            }
         }
      }

      /*
       * get the next locfile entry
       */
      locln++;
      loclength = asl_rd_line(locfile, line);
   }
   printf("Locater done!\n\n\r");

   return err;
}



/************************* EOF-ASO21.C ******************************/


Module ASA21

/*********************************************************************
*
* Name:        asa21.c
* Description: Annotate the source files with the information in the
*              map file.
*
* Copyright (c) Aerospace Software Ltd, 1998.
*
* Revision  Date     Author            Remarks
* -------------------------------------------------------------------
* 1.0       July 98  Herman Oosthuysen
*
*********************************************************************/

#define  ANA
#include "dos.h"
#include "stdio.h"
#include "string.h"
#include "ctype.h"
#include "asl21.h"
#undef   ANA

/*********************************************************************
* Code
*********************************************************************/

/*********************************************************************
* Name:        Basic source annotation
* Description: copy src to exe file and fix the addresses
* Constraints: Assumes there are no external definition errors since
*              these should have been caught by ase21.
*              First search the map file locally based on the module 
*              name, if not found search again globally.
*********************************************************************/
void asa_annotate(FILE *inifile, FILE *srcfile, FILE *exefile,
                  FILE *mapfile)
{
   char                 line[1024];
        char                 mline[1024];
   char                 work[1024];
   char                 token[32];
   char                 label[32];
   char                 module[32];
   char                 pointer[32];

        char                 space[3];
        char                                            pspace[3];
   char                 address[4];
   char                 offset[4];
   char                 code[6];
   char                 fixup[4];
   unsigned int         codefix;
   unsigned int         addrfix;

   int                  length;
   int                  mlength;
   int                  spos;
   int                  mpos;
   int                  pos;
   int                  mlen;
   int                  cnt;
   int                  value;
   char                 *tok;
   char                 *lbltok;
   char                 *initok;
   char                 *search;
   char                 first = TRUE;
        char                 coderr = FALSE;
        char                 moderr = TRUE;
        int                  found = FALSE;

   /*
    * put the file header in the exe file:
    * esc esc i
    */
   printf("Annotating...\n\r");
   fprintf(exefile, "%c%ci\n", ASA_ESC, ASA_ESC);

   /*
    * scan and copy every line in the src file
    * if it has a label then
    * scan the map file for the address and fix the code
    */
   length = asl_rd_line(srcfile, line);
   while(length != EOF)
   {
      /*
       * $m.i,d,rAmodule
       * Find the module name and add an offset statement
       * to the exe file, of the form:
       * @PA
       * XXXX
       */
      spos = asl_find_token(line, work, ASC_MODULE, ASC_DOLLARS);
      if(spos > 0)
      {
                        moderr = TRUE;
         spos = asl_marked_token(line, work, ASC_NAME, token, ASC_COMMAS);
         if(spos > 0)
         {
            /*
             * search the map file for the module offset
             */
            strcpy(module, token);

                                found = asa_lookup(mapfile, NULL, module, offset, space);

                        if(found)
                        {
                                /*
                                 * Unless this is the first module,
                                 * put a dummy checksum in the exe file, to keep the
                                 * ADI SPL21 utility happy:
                                 * #123456789AB
                                 */
                                if(!first)
                                        fprintf(exefile, "%s\n", ASA_DUMMY_SUM);
                                first = FALSE;

                                /*
                                 * print the module offset of the form:
                                 * @PA
                                 * XXXX
                                 */
               fprintf(exefile, "%s\n%s\n", ASA_CODE, offset);
               moderr = FALSE;
            }
         }
      }

      /*
       * find the $c24_bit_code
       */
      if(!moderr)
      {
         spos = asl_find_token(line, work, ASC_CODE, ASC_DOLSPACE);
         if(spos > 0)
         {
            /*
             * Get the ASCII Hex instruction code string
             * skipping the $c leader
                         */
                        tok = strtok(line, ASC_DOLSPACE);
                        if(tok != NULL)
                                strcpy(code, &tok[2]);

            /*
             * see whether there is a label on this line
             */
            spos = asl_marked_token(line, work, ASC_UPLINK, token, ASC_DOTSPACE);
            if(spos > 0)
            {
               /*
                * search the map file for the label address
                * either .LABEL or .VARIABLE
                */
                                        coderr = TRUE;
               strcpy(label, token);


                                found = asa_lookup(mapfile, module, label, address, space);
                                if(!found)
                                   found = asa_lookup(mapfile, NULL, label, address, space);
                                
               /*
                * fix the code with the address
                * all opcodes carry the address offset by 1 nibble
                */
               if(found)
               {
                  codefix = sscanf("%04x", &code[1]);
                  addrfix = sscanf("%04x", address);
                  codefix &= ASA_CODE_MASK;
                  codefix |= addrfix;
                  sprintf(fixup, "%04x", codefix);
                  for(cnt = 0; cnt < 4; cnt++)
                     code[cnt + 1] = fixup[cnt];
               }
               else
                  printf("\n\rCode fixup failed in module %s", module);
            }
            /*
             * print the code to the exe file
             * in the form:
             * XXXXXX
             */
            if(!coderr)
               fprintf(exefile, "%s\n", code);
            else
               fprintf(exefile, "CODE FIXUP ERROR!\n");
         }
      }


      /*
       * get the next src line to work on
       */
      length = asl_rd_line(srcfile, line);
   }

   /*
    * Add the initialized variables in PM and DM
    * from the ini file to the exe file.
    * Initializer data statements have the following form:
    * $iCBAUD_PERIOD 00B400
    * Initializer pointer statements have the following form:
    * $iCUART_O_PTR ,puart_tx_buffer
    * and they can be mixed and/or listed as for this two dimentional
    * table:
    * $iME_TBL ,pme_init 000000 ,pme_do_nothing 000100 ,pme_start 000000
    */
   rewind(inifile);
        do
   {
      /*
       * find a variable/constant label
       * then get the initializer, which can be either a value or a pointer
       */
                length = asl_rd_line(inifile, line);
      spos = asl_find_token(line, work, ASC_INIT, ASC_DOLSPACE);
      strcpy(work, line);                       /* save the line */
      if(spos > 0)
      {
         /*
          * read the variable/constant label
          */
         lbltok = strtok(line, ASC_INITS);
                strcpy(label, lbltok);
                
                /*
                 * find the module name in the ini file
                 */
         mpos = asl_find_token(line, work, ASC_MODULE, ASC_DOLLARS);
         if(mpos > 0)
         {
            pos = asl_marked_token(line, work, ASC_NAME, token, ASC_COMMAS);
            if(pos > 0)
               strcpy(module, token);
         }

         /*
          * find the label 
          */
         if(lbltok != NULL)
         {
            /*
             * Lookup the variable / constant address
             * and write and entry in the exe file of the form
             * @DA
             * xxxx address
             * xxxx initializer or
             *
             * @PA
             * xxxx address
             * xxxxxx initializer
             */
                                found = asa_lookup(mapfile, module, label, address, space);
                                if(!found)
                                   found = asa_lookup(mapfile, NULL, label, address, space);
                                
                                if(found)
                                {
                                        if(stricmp(space, ASM_PM_SEG) == 0)
                                                strcpy(space, ASA_CODE);
                                        else if(stricmp(space, ASM_DM_SEG) == 0)
                                                strcpy(space, ASA_DATA);
                                        fprintf(exefile, "%s\n%s\n%s\n", ASA_DUMMY_SUM, space, address);
                                }
                                else
                                        printf("Map file entry %s not found\n\r", label);

            /*
                                 * strtok gets confused by the search in the map file
                                 * therefore cannot search with a NULL pointer
                                 */
                                lbltok = strtok(work, ASC_INITS);
                                search = lbltok + strlen(lbltok) + 1;
            do
            {
                                        initok = strtok(search, ASC_COMMAS);
                                        search = initok + strlen(initok) + 1;
                        if(initok != NULL)
                        {
                           /*
                            * is the string numeric or text?
                                                 */
                                                value = isdigit(initok[0]);
                                                if(value)
                  {
                     /*
                      * numeric = initializer value
                      * values are always saved in the LSB
                      * whether PM or DM
                      */
                                                   strcpy(code, initok);
                  }
                                                else
                  {
                     /*
                      * text = pointer name
                                                         * lookup the pointer value in the map file
                                                         * copy and drop the p prefix
                      */
                                                        strcpy(pointer, &initok[1]);
                                                        found = asa_lookup(mapfile, module, pointer, code, pspace);
                                        if(!found)
                                           found = asa_lookup(mapfile, NULL, label, address, space);

                     /*
                      * if PM then
                      * code = code SHL 8
                      */
                                                        if(found)
                                                        {
                                                                if(stricmp(space, ASA_CODE) == 0)
                                                                   strcat(code, ASA_00H);
                                                        }
                                                        else
                                                                printf("Map file pointer %s not found\n\r", pointer);
                                                }

                  /*
                   * save the initializer
                   */
                  fprintf(exefile, "%s\n", code);
               }
            }while(initok != NULL);
         }
      }
        }while(length != EOF);

   /*
    * put the exe file footer:
    * esc esc o
    */
   fprintf(exefile, "%s\n%c%co\n", ASA_DUMMY_SUM, ASA_ESC, ASA_ESC);
   printf("Annotater done!\n\n\r");
}



/*********************************************************************
* Name:        asa_lookup
* Description: find the address and memory space of a token in the
*              specified module
* Constraints: if the module == NULL then search global
*********************************************************************/
int asa_lookup(FILE *mapfile, char *module, char *label,
               char *address, char *space)
{
   char  line[1024];
   char  mod[32];
        char  *token;
        char    *search;
   int   length;
   int   found = FALSE;

   /*
    * error check
    */
   if(mapfile == NULL)
      return found;

   rewind(mapfile);

   do
   {
      /*
       * read a line
       */
      length = asl_rd_line(mapfile, line);

      if(length > 0)
      {
         token = strtok(line, ASC_SPACE);
         if(token != NULL)
         {
            /*
             * record the memory space
             */
            if(stricmp(token, ASM_SPACE) == 0)
            {
               search = NULL;
               token = strtok(search, ASC_SPACE);
               if(token != NULL)
               {
                  strcpy(space, token);
               }
            }

            /*
             * record the module
             */
                                else if((stricmp(token, ASM_MODULE) == 0) &&
                                                        (module != NULL))
            {
               search = NULL;
               token = strtok(search, ASC_SPACE);
               if(token != NULL)
               {
                  strcpy(mod, token);
               }
            }

            /*
             * find the label/variable/module address
             */
            if(((stricmp(token, ASM_VARIABLE) == 0) ||
                    (stricmp(token, ASM_LABEL) == 0) ||
                    (stricmp(token, ASM_MODULE) == 0)) &&
                   ((stricmp(mod, module) == 0) ||
                    (module == NULL)))
            {
               search = NULL;
               token = strtok(search, ASC_SPACE);
               if(token != NULL)
               {
                  /*
                   * first find the label
                   */
                  if(stricmp(label, token) == 0)
                  {
                     /*
                      * then the address
                      */
                     search = NULL;
                     token = strtok(search, ASC_SPACE);
                     if(token != NULL)
                     {
                        strcpy(address, token);
                        found = TRUE;
                     }
                  }
               }
            }
         }
      }
        }while((length != EOF) && (!found));

   return found;
}



Header file

/*********************************************************************
*
* Name:  ASL21.H
* Description: ADSP linker/locater
*
* Copyright (c) Aerospace Software Ltd, 1998.
*
* Revision  Date     Author            Remarks
* -------------------------------------------------------------------
* 1.0       July 98  Herman Oosthuysen
*
*********************************************************************/

#ifdef ASL
#define GLOBAL
#else
#define GLOBAL extern
#endif

/************************** Literals *******************************/
/*
 * Copyright notice
 */
#define ASL_NOTICE1  "ASL21 version 1.0, ADSP 21XX Linker/Locater"
#define ASL_NOTICE2  "Copyright (c) Aerospace Software Ltd., 1998."
#define ASL_NOTICE3  "email: aerosoft@agt.net web: www.agt.net/public/aerosoft"

#define TRUE   1
#define PASS   1
#define FALSE  0
#define FAIL   0

/*
 * LOC File markers
 */
#define ASL_OBJ      ".OBJECTS"
#define ASL_EOBJ     ".ENDOBJECTS"
#define ASL_PMSEG    ".PMSEGMENTS"
#define ASL_PMEND    ".ENDPMSEGMENTS"
#define ASL_DMSEG    ".DMSEGMENTS"
#define ASL_DMEND    ".ENDDMSEGMENTS"
#define ASL_END      ".END"
#define ASL_OVERLAY  ".OVERLAY"


/*
 * MEM file markers
 */
#define ASM_MODULE   ".MODULE"
#define ASM_UNKNOWN  "UNKNOWN"
#define ASM_FILE     ".FILE"
#define ASM_SPACE    ".SPACE"
#define ASM_ORIGIN   ".ORIGIN"
#define ASM_SEGMENT  ".SEGMENT"
#define ASM_DONTCARE "DONTCARE"
#define ASM_LABEL    ".LABEL"
#define ASM_MODSIZE  ".MODSIZE"
#define ASM_PM_SEG   "PM"
#define ASM_DM_SEG   "DM"
#define ASM_CIRCULAR ".CIRCULAR"
#define ASM_VARIABLE ".VARIABLE"
#define ASM_DEF_SIZE "0001"
#define ASM_GLOBAL   ".GLOBAL"
#define ASM_ENTRY    ".ENTRY"
#define ASM_EXTERNAL ".EXTERNAL"

/*
 * CDE file markers
 */
/* $ commands */
#define ASC_CODE     "c"
#define ASC_MODULE   "m"
#define ASC_INIT     "i"
#define ASC_DNLINK   "d"

/* dot-comma commands */
#define ASC_VAR      "v"
#define ASC_MODIN    "i"
#define ASC_MODOUT   "o"
#define ASC_UPLINK   "u"
#define ASC_PM       "p"
#define ASC_DM       "d"

/* dot-space commands */
#define ASC_LABEL    "l"
#define ASC_ENTRY    "e"
#define ASC_GLOBAL   "g"
#define ASC_EXTERN   "x"

/* comma commands */
#define ASC_NAME     "rA"
#define ASC_FIXUP    "f"
#define ASC_POINTER  "p"
#define ASC_OFFSET   "o"
#define ASC_MODSIZE  "l"
#define ASC_SEGNAME  "n"
#define ASC_ABSOLUTE "a"
#define ASC_VARSIZE  "s"
#define ASC_CIRC     "c"

/* Command delimiters */
#define ASC_DELIMIT  " .,\n\r\x1A\x09\xFF"
#define ASC_DOLLARS  "$.\n\r\x1A\x09\xFF"
#define ASC_DOLSPACE "$ \n\r\x1A\x09\xFF"
#define ASC_DOTSPACE " .\n\r\x1A\x09\xFF"
#define ASC_DOTCOMMA ".,\n\r\x1A\x09\xFF"
#define ASC_COMMAS   " ,\n\r\x1A\x09\xFF"
#define ASC_SPACE    " \n\r\x1A\x09\xFF"
#define ASC_INITS    " $i\n\r\x1A\x09\xFF"

/* Locater constants */
#define ASO_MEMSIZE     0x4000
#define ASO_CODESPACE   0
#define ASO_DATASPACE   1
#define ASO_FREE        0
#define ASO_INUSE       1

/* Annotater constants */
#define ASA_ESC         0x1B
#define ASA_CODE_MASK   0x3FFF
#define ASA_DUMMY_SUM   "#123456789AB"
#define ASA_CODE        "@PA"
#define ASA_DATA        "@DA"
#define ASA_00H         "00"

/* Garbage filter constants */
#define ASG_TMPFILE     "garbage.tmp"
#define ASG_HT          0x09
#define ASG_CR          0x0D
#define ASG_LF          0x0A
#define ASG_SP          0x20
#define ASG_TL          0x7E
#define ASG_SIB         0x1A

/************************** Variables *******************************/


/************************** Prototypes ******************************/
int   asl_rd_line(FILE *infile, char *line);

int   asl_marked_token(char *line, char *work, char *marker, 
                       char *token, char *delimeters);
                       
int   asl_find_token(char *line, char *work, char *token, 
                     char *delimiters);
                     
void  asl_concat_src(FILE *cdefile, FILE *srcfile);

void  asl_parse_module(FILE *objfile, FILE *memfile, char *name, 
                       int *row);
                       
void  asl_parse_label(FILE *objfile, FILE *memfile, int *row);

void  asl_parse_modsize(FILE *objfile, FILE *memfile, int *row);

void  asl_parse_variable(FILE *objfile, FILE *memfile, int *row);

void  asl_parse_global(FILE *objfile, FILE *memfile, int *row);

void  asl_parse_entry(FILE *objfile, FILE *memfile, int *row);

void  asl_parse_external(FILE *objfile, FILE *memfile, int *row);

void  asl_link_files(FILE **cdefile, FILE **objfile, FILE **intfile,
                     char *line, char *filename, char *name);
                     
void asl_open_files(FILE **inifile, FILE **srcfile, FILE **locfile, 
                    FILE **exefile, FILE **mapfile, FILE **symfile, 
                    FILE **memfile, char *filename, char *name);
                    
void  asl_copyright_files(FILE *file);

void  asl_copyright_display(void);

int   ase_err_check(FILE *memfile, FILE *mapfile, char *name);

int   aso_org(FILE *memfile, FILE *locfile, FILE *inifile, 
              FILE *mapfile, char *name);
              
void asa_annotate(FILE *inifile, FILE *srcfile, FILE *exefile, 
                  FILE *mapfile);
                  
void asg_filter(char *filename);

int asa_lookup(FILE *mapfile, char *module, char *label, 
               char *address, char *space);


/****************************** EOF-ASL21.H *************************/


Link and Locate Response File Example

UART Link and locate information
Don't put comments in between key word pairs!

List all the object files between these two key words:
.OBJECTS
645ut.obj INT_PM
.ENDOBJECTS

You can put comments here...
Note that unnamed DONTCARE segments will be put in the
first available segment of the right type.

First list the PM segments,
.PMSEGMENTS
INT_PM    0000 2FFF
INT_CONST 3000 3FFF
.ENDPMSEGMENTS

then list the DM segments and
keep the addresses in incrementing order.
.DMSEGMENTS
INT_DM    0000 2FFF
INT_INIT  3000 3FFF
.ENDDMSEGMENTS

.END



Operation

All linker and locater object module names and parameters should be specified in a response file as described above.

If the response file is named target.loc, invoke the linker locater with the following command:

asl target


Copyright © 1996-2008, Aerospace Software Ltd., GPL.