Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /***********************************************************************
  2.  *
  3.  *  avra - Assembler for the Atmel AVR microcontroller series
  4.  *
  5.  *  Copyright (C) 1998-2004 Jon Anders Haugum, Tobias Weber
  6.  *
  7.  * coff.c - Common Object File Format (COFF) support
  8.  *
  9.  *      This file was developed for the avra assembler in order to produce COFF output files
  10.  *  for use with the Atmel AVR Studio.  The Lean C Compiler (LCC) debugging stabs
  11.  *      output was used as input to the assembler.  The information used to develop this file
  12.  *  was obtained from various sources on the Internet, most notably, the Free Software Foundation,
  13.  *  The "stabs" debug format, ??? Chapter 7: Common Object File Format (COFF),
  14.  *
  15.  *      This software has absolutely no warrantee!  The money you paid for this will be
  16.  *  promptly refunded if not fully satisfied.
  17.  *
  18.  *      Beta release 1/20/2000 by Bob Harris
  19.  *
  20.  *      This software has not been fully tested and probably has a few software deficiencies.
  21.  *  Some software support may be possible by sending a problem description report to
  22.  *  rth@mclean.sparta.com
  23.  *
  24.  *  Made the recommended change in write_coff_program().
  25.  *  Fixed an obvious typo in SkipPastDigits().  The if() statement was terminated
  26.  *  with a semicolon, which terminated the if(); early.  JEG 4-01-03
  27.  */
  28.  
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include <ctype.h>
  33. #include <time.h>
  34.  
  35. #include "misc.h"
  36. #include "avra.h"
  37. #include "args.h"
  38.  
  39. #include "coff.h"
  40. #include "device.h"     /* device flash and eeprom size */
  41.  
  42.  
  43. struct FundamentalType {
  44.  
  45.     char const *pString;
  46.     int Type;
  47.     int Size;
  48. };
  49.  
  50. struct FundamentalType FundamentalTypes[] = {
  51.     {"null", T_NULL, 0},
  52.     {"void", T_VOID, 0},
  53.     {"char", T_CHAR, 1},
  54.     {"short", T_SHORT, 1},
  55.     {"int", T_INT, 1},
  56.     {"long", T_LONG, 2},
  57.     {"float", T_FLOAT, 4},
  58.     {"double", T_DOUBLE, 4},
  59.     {"struct", T_STRUCT, 0},
  60.     {"union", T_UNION, 0},
  61.     {"enum",  T_ENUM, 0},
  62.     {"moe", T_MOE, 0},
  63.     {"unsigned char", T_UCHAR, 1},
  64.     {"unsigned short", T_USHORT, 1},
  65.     {"unsigned int", T_UINT, 1},
  66.     {"unsigned long", T_ULONG, 2},
  67.     {"long double", T_LNGDBL, 2},
  68.     {"long long int", T_LONG, 2},
  69.     {"long int", T_LONG, 2},
  70.     {"unsigned long long", T_ULONG, 2},
  71.     {"signed char", T_CHAR, 1},
  72.     {0, 0}
  73. };
  74.  
  75.  
  76. struct coff_info *ci;
  77.  
  78. /****************************************************************************************/
  79.  
  80. FILE *open_coff_file(struct prog_info *pi, char *filename){
  81.  
  82.     int ok /*, i*/;
  83.     FILE *fp;
  84.     //unsigned long *pu4;
  85.     char*p;
  86.  
  87.  
  88.     ci = calloc( 1, sizeof(struct coff_info) );
  89.     if ( !ci )
  90.         return( 0 );
  91.  
  92.     ok = True;
  93.     /* default values */
  94.     ci->CurrentFileNumber = 0;
  95.     ci->pRomMemory = 0;
  96.     ci->pEEPRomMemory = 0;
  97.     ci->MaxRomAddress = 0;
  98.     ci->MaxEepromAddress = 0;
  99.     ci->NeedLineNumberFixup = 0;
  100.     ci->GlobalStartAddress = -1;
  101.     ci->GlobalEndAddress = 0;
  102.  
  103.     /* Linked lists start out at zero */
  104.     InitializeList( &ci->ListOfSectionHeaders );
  105.     InitializeList( &ci->ListOfRawData );
  106.     InitializeList( &ci->ListOfRelocations );
  107.     InitializeList( &ci->ListOfLineNumbers );
  108.     InitializeList( &ci->ListOfSymbols );
  109.     InitializeList( &ci->ListOfGlobals );
  110.     InitializeList( &ci->ListOfSpecials );
  111.     InitializeList( &ci->ListOfUndefined );
  112.     InitializeList( &ci->ListOfStrings );
  113.     InitializeList( &ci->ListOfTypes );
  114.     InitializeList( &ci->ListOfSplitLines );
  115.  
  116.     /* add two default sections to SectionHeaders */
  117.     if (  !AllocateListObject( &ci->ListOfSectionHeaders, sizeof(struct external_scnhdr) ) ||
  118.           !AllocateListObject( &ci->ListOfSectionHeaders, sizeof(struct external_scnhdr) ) ) {
  119.  
  120.         fprintf(stderr, "\nOut of memory allocating section headers!");
  121.         return( 0 );
  122.     }
  123.  
  124.     /* add to string table */
  125.     p = (char *)AllocateListObject( &ci->ListOfStrings,  4 );
  126.     if ( !p ) {
  127.         fprintf(stderr, "\nOut of memory allocating string table space!");
  128.         return( 0 );
  129.     }
  130.  
  131.     /* Allocate space for binary output into ROM, and EEPROM memory buffers for COFF output */
  132.     /* ASSUMES ci->device is accurate */
  133.     if ( (ci->pRomMemory = AllocateListObject( &ci->ListOfRawData, pi->device->flash_size * 2 ) ) != 0) {
  134.         if ( (ci->pEEPRomMemory = AllocateListObject( &ci->ListOfRawData, pi->device->eeprom_size )) != 0) {
  135.             ok = True; /* only true if both buffers are properly allocated */
  136.             /* now fill them with 0xff's to simulate flash erasure */
  137.             memset( (void *)ci->pRomMemory, 0xff, pi->device->flash_size * 2 );
  138.             memset(    (   void    *)ci->pEEPRomMemory,    0xff,    pi->device->eeprom_size    );
  139.         }
  140.     }
  141.     if ( ok != True )
  142.         return( 0 );
  143.  
  144.     fp = fopen(filename,"wb");
  145.     if ( fp == NULL ) {
  146.         fprintf(stderr,"Error: cannot write coff file\n");
  147.         return( fp );
  148.     }
  149.     /* simulate void type .stabs void:t15=r1;*/
  150.     stab_add_local_type( "void", "15=r1;0;0;" );
  151.  
  152.     return( fp );  
  153. }
  154.  
  155. /****************************************************************************************/
  156. void write_coff_file(struct prog_info *pi){
  157.  
  158.     //FILE *fp;
  159.     //struct label *label;
  160.     char /* File[256],*/*p;
  161.     struct external_scnhdr *pSectionHdr;
  162.     struct syment *pEntry;
  163.     union auxent *pAux;
  164.     unsigned long *plong;
  165.     int NumberOfSymbols, SymbolIndex, LastFileIndex, LastFunctionIndex, LastFunctionAddress;
  166.     LISTNODE *pNode;
  167.     int LinesOffset, SymbolsOffset, StringsOffset, RawOffset;
  168.     struct lineno *pLine;
  169.  
  170.     /* add two special sections */
  171.     /* one for .text */
  172.     if (  ( pEntry = (struct syment*)AllocateTwoListObjects( &ci->ListOfSpecials, sizeof(struct syment) * 2 ) ) == 0 ) {
  173.         fprintf(stderr, "\nOut of memory allocating special headers for .text!");
  174.         return;
  175.     }
  176.     memset( pEntry->n_name, 0, 8 );
  177.     strcpy( pEntry->n_name, ".text" );
  178.     pEntry->n_value = 0;
  179.     pEntry->n_scnum = 1;
  180.     pEntry->n_type = 0;
  181.     pEntry->n_sclass = C_STAT;
  182.     pEntry->n_numaux = 1;
  183.     pEntry++;
  184.     pAux = (union auxent *)pEntry;
  185.     pAux->x_scn.x_scnlen = ci->MaxRomAddress + 2;
  186.     pAux->x_scn.x_nreloc = 0;
  187.     pAux->x_scn.x_nlinno = ci->ListOfLineNumbers.TotalItems;
  188.     /* one for .bss */
  189.     if (  ( pEntry = (struct syment*)AllocateTwoListObjects( &ci->ListOfSpecials, sizeof(struct syment) * 2 ) ) == 0 ) {
  190.         fprintf(stderr, "\nOut of memory allocating special header for .bss!");
  191.         return;
  192.     }
  193.     memset( pEntry->n_name, 0, 8 );
  194.     strcpy( pEntry->n_name, ".bss" );
  195.     if ( ci->GlobalStartAddress == -1 ) {
  196.         ci->GlobalEndAddress = ci->GlobalStartAddress = 0x60;
  197.     }
  198.     pEntry->n_value = ci->GlobalStartAddress;
  199.     pEntry->n_scnum = 2;
  200.     pEntry->n_type = 0;
  201.     pEntry->n_sclass = C_STAT;
  202.     pEntry->n_numaux = 1;
  203.     pEntry++;
  204.     pAux = (union auxent *)pEntry;
  205.     pAux->x_scn.x_scnlen = 0; /* we don't store any data here */
  206.     pAux->x_scn.x_nreloc = 0;
  207.     pAux->x_scn.x_nlinno = 0;
  208.  
  209.     /* one more for .data - eeprom ??? */
  210.  
  211.     /* Calculate common offsets into the file */
  212.     RawOffset = sizeof(struct external_filehdr) + ci->ListOfSectionHeaders.TotalBytes;
  213.     LinesOffset = RawOffset + ci->MaxRomAddress + 2; /* ignore eeprom for now */
  214.     SymbolsOffset = LinesOffset + ci->ListOfLineNumbers.TotalBytes;
  215.     StringsOffset = SymbolsOffset + ci->ListOfSymbols.TotalBytes + ci->ListOfSpecials.TotalBytes + ci->ListOfGlobals.TotalBytes;
  216.  
  217.     /* Clean up loose ends in string table */
  218.     if ( !(plong  = (unsigned long *)FindFirstListObject(&ci->ListOfStrings))  ) {
  219.         fprintf(stderr,"\nInternal error in string table!");
  220.         return;
  221.     }
  222.     *plong = ci->ListOfStrings.TotalBytes; /* Size of string table */
  223.  
  224.     /* Clean up loose ends in symbol table */
  225.  
  226.     /*  symbol table - Filename value - index to next .file or global symbol */
  227.     /* The value of that symbol equals the symbol table entry index of the next .file symbol or .global */
  228.     LastFunctionAddress = ci->MaxRomAddress;
  229.     NumberOfSymbols = ci->ListOfSymbols.TotalItems + ci->ListOfSpecials.TotalItems + ci->ListOfGlobals.TotalItems;
  230.     SymbolIndex = LastFileIndex = NumberOfSymbols;
  231.     LastFunctionIndex = 0; /* set to zero on last function */
  232.     for ( pEntry = (struct syment *)FindLastListObject(&ci->ListOfSymbols);
  233.         pEntry != 0;
  234.         pEntry = (struct syment *)FindNextLastListObject(&ci->ListOfSymbols) ) {
  235.  
  236.         /* Search for .file entries designated by C_FILE */
  237.         if ( pEntry->n_sclass == C_FILE ) {
  238.             pEntry->n_value = LastFileIndex;
  239.             LastFileIndex = SymbolIndex; /* save current index */
  240.         }
  241.         /* Search for Function entries C_EXT */
  242.         else if (  pEntry->n_sclass == C_EXT ) {
  243.             pEntry++;
  244.             pAux = (union auxent *)pEntry;
  245.             pAux->x_sym.x_misc.x_fsize = LastFunctionAddress - pEntry->n_value; /* function updated size */
  246.             pAux->x_sym.x_fcnary.x_fcn.x_lnnoptr += LinesOffset;
  247.             LastFunctionAddress = pEntry->n_value;
  248.             pAux->x_sym.x_fcnary.x_fcn.x_endndx = LastFunctionIndex; /* point to next function index */
  249.             pAux->x_sym.x_tvndx = 0; /* ??? */
  250.             LastFunctionIndex = SymbolIndex;
  251.         } else if (  (pEntry->n_sclass == C_FCN ) || ( pEntry->n_sclass == C_BLOCK) ) {
  252.             if ( pEntry->n_name[1] == 'b' ) {
  253.                 /* .bf and .bb */
  254.                 pEntry++;
  255.                 pAux = (union auxent *)pEntry;
  256.                 pAux->x_sym.x_fcnary.x_fcn.x_endndx = LastFunctionIndex;
  257.             }
  258.         }
  259.         /* else do nothing */
  260.  
  261.         /* update current symbol index */
  262.         pNode = GetCurrentNode( &ci->ListOfSymbols );
  263.         SymbolIndex -= ( pNode->Size / sizeof(struct syment) );
  264.     }
  265.  
  266.     // File Header
  267.     ci->FileHeader.f_magic = MAGIC_NUMBER_AVR;
  268.     ci->FileHeader.f_nscns = 2;
  269. //    ci->FileHeader.f_timdat = time( (time_t *)&ci->FileHeader.f_timdat);
  270.     ci->FileHeader.f_timdat = pi->time;
  271.     ci->FileHeader.f_symptr = SymbolsOffset;
  272.     ci->FileHeader.f_nsyms = NumberOfSymbols;
  273.     ci->FileHeader.f_opthdr = 0;
  274.     ci->FileHeader.f_flags = 0xff; /*F_RELFLG;*/ /* No relocation information available */
  275.  
  276.     /* write it out */
  277.     if ( fwrite(&ci->FileHeader, 1, sizeof(struct external_filehdr), pi->coff_file ) !=  sizeof(struct external_filehdr) ) {
  278.         fprintf(stderr,"\nFile error writing header ...(disk full?)");
  279.         return;
  280.     }
  281.  
  282.     // Optional Information
  283.  
  284.     // Section 1 Header
  285.     pSectionHdr = (struct external_scnhdr *)FindFirstListObject(&ci->ListOfSectionHeaders);
  286.     if ( !pSectionHdr ) {
  287.         fprintf(stderr, "\nInternal Coff error - cannot find section header .text!");
  288.         return;
  289.     }
  290.     memset( &pSectionHdr->s_name[0], 0, sizeof(struct external_scnhdr) );
  291.     strcpy( &pSectionHdr->s_name[0], ".text");
  292.     pSectionHdr->s_paddr = 0;
  293.     pSectionHdr->s_vaddr = 0;
  294.     pSectionHdr->s_size = ci->MaxRomAddress + 2; /* remember the last instruction */
  295.     pSectionHdr->s_scnptr = RawOffset;
  296.     pSectionHdr->s_relptr = 0;
  297.     pSectionHdr->s_lnnoptr = LinesOffset;
  298.     pSectionHdr->s_nreloc = 0;
  299.     pSectionHdr->s_nlnno = ci->ListOfLineNumbers.TotalBytes/sizeof(struct lineno);
  300.     pSectionHdr->s_flags = STYP_TEXT;
  301.  
  302.     /* write it out */
  303.     if ( fwrite(&pSectionHdr->s_name[0], 1, sizeof(struct external_scnhdr), pi->coff_file ) !=  sizeof(struct external_scnhdr) ) {
  304.         fprintf(stderr,"\nFile error writing section header ...(disk full?)");
  305.         return;
  306.     }
  307.  
  308.     // Section 2 Header
  309.     pSectionHdr = (struct external_scnhdr *)FindNextListObject(&ci->ListOfSectionHeaders);
  310.     if ( !pSectionHdr ) {
  311.         fprintf(stderr, "\nInternal Coff error - cannot find section header .bss!");
  312.         return;
  313.     }
  314.     memset( &pSectionHdr->s_name[0], 0, sizeof(struct external_scnhdr) );
  315.     strcpy( &pSectionHdr->s_name[0], ".bss");
  316.     /* later expansion */
  317.     pSectionHdr->s_paddr = ci->GlobalStartAddress;
  318.     pSectionHdr->s_vaddr = ci->GlobalStartAddress;
  319.     pSectionHdr->s_flags = STYP_DATA; /* seems it should be STYP_BSS */
  320.  
  321.     /* write it out */
  322.     if ( fwrite(&pSectionHdr->s_name[0], 1, sizeof(struct external_scnhdr), pi->coff_file ) !=  sizeof(struct external_scnhdr) ) {
  323.         fprintf(stderr,"\nFile error writing section header ...(disk full?)");
  324.         return;
  325.     }
  326.  
  327.     /* Section N Header - .data or eeprom */
  328.  
  329.     // Raw Data for Section 1
  330.     if ( (p = FindFirstListObject(&ci->ListOfRawData) ) == 0 ) {
  331.         fprintf(stderr,"\nInternal error - unable to find binary data!");
  332.         return;
  333.     }
  334.  
  335.     /* write it out */
  336.     if ( fwrite( p, 1, ci->MaxRomAddress + 2, pi->coff_file ) != (size_t)(ci->MaxRomAddress + 2) ) {
  337.         fprintf(stderr,"\nFile error writing raw .text data ...(disk full?)");
  338.         return;
  339.     }
  340.     // Raw data for section n
  341.  
  342.     // Relocation Info for section 1
  343.  
  344.     // Relocation info for section n
  345.  
  346.     // Line numbers for section 1
  347.     for ( pLine = (struct lineno *)FindFirstListObject( &ci->ListOfLineNumbers );
  348.         pLine != 0;
  349.         pLine = (struct lineno *)FindNextListObject( &ci->ListOfLineNumbers ) ) {
  350.  
  351.         pNode = GetCurrentNode( &ci->ListOfLineNumbers );
  352.  
  353.         /* write it out */
  354.         if ( fwrite( pLine, 1, pNode->Size, pi->coff_file ) != pNode->Size ) {
  355.             fprintf(stderr,"\nFile error writing line numbers ...(disk full?)");
  356.             return;
  357.         }
  358.     }
  359.  
  360.  
  361.     // Line numbers for section n
  362.  
  363.     // Symbol table
  364.     for ( pEntry = (struct syment *)FindFirstListObject( &ci->ListOfSymbols );
  365.         pEntry != 0;
  366.         pEntry = (struct syment *)FindNextListObject( &ci->ListOfSymbols ) ) {
  367.  
  368.         pNode = GetCurrentNode( &ci->ListOfSymbols );
  369.  
  370.         /* write it out */
  371.         if ( fwrite( pEntry, 1, pNode->Size, pi->coff_file ) != pNode->Size ) {
  372.             fprintf(stderr,"\nFile error writing symbol table ...(disk full?)");
  373.             return;
  374.         }
  375.     }
  376.  
  377.     // Symbol table of Globals
  378.     for ( pEntry = (struct syment *)FindFirstListObject( &ci->ListOfGlobals );
  379.         pEntry != 0;
  380.         pEntry = (struct syment *)FindNextListObject( &ci->ListOfGlobals ) ) {
  381.  
  382.         pNode = GetCurrentNode( &ci->ListOfGlobals );
  383.  
  384.         /* write it out */
  385.         if ( fwrite( pEntry, 1, pNode->Size, pi->coff_file ) != pNode->Size ) {
  386.             fprintf(stderr,"\nFile error writing global symbols ...(disk full?)");
  387.             return;
  388.         }
  389.     }
  390.  
  391.     /* Specials .text, .bss, .data */
  392.  
  393.     for ( pEntry = (struct syment *)FindFirstListObject( &ci->ListOfSpecials );
  394.         pEntry != 0;
  395.         pEntry = (struct syment *)FindNextListObject( &ci->ListOfSpecials ) ) {
  396.  
  397.         pNode = GetCurrentNode( &ci->ListOfSpecials );
  398.  
  399.         /* write it out */
  400.         if ( fwrite( pEntry, 1, pNode->Size, pi->coff_file ) != pNode->Size ) {
  401.             fprintf(stderr,"\nFile error writing special symbols ...(disk full?)");
  402.             return;
  403.         }
  404.     }
  405.  
  406.     // String Table
  407.     for ( p = (char *)FindFirstListObject( &ci->ListOfStrings );
  408.         p != 0;
  409.         p = (char *)FindNextListObject( &ci->ListOfStrings ) ) {
  410.  
  411.         pNode = GetCurrentNode( &ci->ListOfStrings );
  412.  
  413.         /* write it out */
  414.         if ( fwrite( p, 1, pNode->Size, pi->coff_file ) != pNode->Size ) {
  415.             fprintf(stderr,"\nFile error writing strings data ...(disk full?)");
  416.             return;
  417.         }
  418.     }
  419.  
  420.     return;
  421. }
  422.  
  423. /****************************************************************************************/
  424.  
  425. void write_coff_eeprom( struct prog_info *pi, int address, unsigned char data){
  426.  
  427.     if ( !GET_ARG(pi->args, ARG_COFF) )
  428.         return;
  429.  
  430.     /* Coff output keeps track of binary data in memory buffers */
  431.     if ( ci->pEEPRomMemory ) {
  432.         if ( address <= pi->device->eeprom_size ) {
  433.             *(ci->pEEPRomMemory + address) = data;
  434.             if ( address >= ci->MaxEepromAddress )
  435.                 ci->MaxEepromAddress = address;   /* keep high water mark */
  436.         } else {
  437.             pi->error_count++;
  438.             fprintf(stderr, "Error: EEPROM address %d exceeds max range %d", address, pi->device->eeprom_size );
  439.         }
  440.     }
  441. }
  442. /****************************************************************************************/
  443.  
  444. void write_coff_program( struct prog_info *pi, int address, unsigned int data){
  445.  
  446.     unsigned char *pByte;
  447.  
  448.     if ( !GET_ARG(pi->args, ARG_COFF) )
  449.         return;
  450.  
  451.     /* Coff output keeps track of binary data in memory buffers, address is in bytes not words */
  452.     if ( ci->pRomMemory ) {
  453. /* JEG  if ( address <= pi->device->flash_size ) {  */  /* JEG 4-23-03 */
  454.                 if ( address <= pi->device->flash_size*2 ) {
  455.             pByte = (unsigned char *)(ci->pRomMemory + address); /* point to low byte in memory */
  456.             *pByte++ = (data & 0xff);   /* low byte */
  457.             *pByte = ((data >> 8) & 0xff); /* high byte */
  458.  
  459.             if ( address >= ci->MaxRomAddress )
  460.                 ci->MaxRomAddress = address;   /* keep high water mark */
  461.         } else {
  462.             pi->error_count++;
  463. /* JEG          fprintf(stderr, "Error: FLASH address %d exceeds max range %d", address, pi->device->flash_size ); */
  464.                         fprintf(stderr, "Error: FLASH address %d exceeds max range %d", address, pi->device->flash_size*2 );
  465.         }
  466.     }
  467. }
  468.  
  469. /****************************************************************************************/
  470.  
  471. void close_coff_file(struct prog_info *pi, FILE *fp){
  472.  
  473.     /* close the output file */
  474.     fclose( fp );
  475.     pi->coff_file = 0;
  476.  
  477.     /* free all the internal memory buffers used by ci */
  478.  
  479.     FreeList( &ci->ListOfSectionHeaders );
  480.     FreeList( &ci->ListOfRawData );
  481.     FreeList( &ci->ListOfRelocations );
  482.     FreeList( &ci->ListOfLineNumbers );
  483.     FreeList(    &ci->ListOfSymbols    );
  484.     FreeList( &ci->ListOfGlobals );
  485.     FreeList( &ci->ListOfUndefined );
  486.     FreeList( &ci->ListOfStrings );
  487.     FreeList( &ci->ListOfTypes );
  488.     FreeList( &ci->ListOfSplitLines );
  489.  
  490.     /* now free ci */
  491.     free( ci );
  492.     ci = 0;
  493. }
  494.  
  495. /****************************************************************************************/
  496.  
  497. int parse_stabs( struct prog_info *pi, char *p ){
  498.  
  499.     int ok = True;
  500.     int TypeCode, n;
  501.     char *pString, *p2, *p3, *p4, *p5, *pType, *pEnd, *pp, *pJoined;
  502.  
  503.  
  504.     if ( !GET_ARG(pi->args, ARG_COFF) || ( pi->pass == PASS_1 ) )
  505.         return(True);
  506.  
  507.     /* stabs debugging information is in the form:
  508.     .stabs "symbolic info string", HexorDecimalTypecode, parm3, parm4, parm5
  509.     parm1, parm2, parm3 depend on typecode
  510.  
  511.     N_LSYM      0x80            local sym: name,,0,type,offset
  512.     N_OPT       0x3c            compiler options
  513.     N_SO        0x64            source file name: name,,0,0,address
  514.     N_SOL       0x84            #included file name: name,,0,0,address
  515.     N_FUN       0x24            procedure: name,,0,linenumber,address
  516.     N_GSYM      0x20            global symbol: name,,0,type,0
  517.     N_LCSYM     0x28            .lcomm symbol: name,,0,type,address
  518.     N_STSYM     0x26            static symbol: name,,0,type,address
  519.     N_RSYM      0x40            register sym: name,,0,type,register
  520.     N_PSYM      0xa0            parameter: name,,0,type,offset
  521.  
  522.     */
  523.  
  524.     /* Look for multiple commands per line */
  525.  
  526.     /* .stabs "linktag:T19=s46next:20=*19,0,16;last:20,16,16;a:21=ar1;0;2;22=ar1;0;3;1,32,96;\\",128,0,0,0 */
  527.     /* .stabs "b:23=ar1;0;4;24=ar1;0;5;2,128,240;;",128,0,0,0 */
  528.  
  529.  
  530.     /* Look for continuation lines per line */
  531.  
  532.     /* Get String information as a token */
  533.     /* Parse the tokens in the stabn line buffer */
  534.     pString = get_next_token(p, TERM_DOUBLEQUOTE );     /* zap first doublequote */
  535.     p2 = get_next_token(pString, TERM_DOUBLEQUOTE );    /* zap last doublequote */
  536.     p2 = get_next_token(p2, TERM_COMMA );               /* zap comma */
  537.     p3 = get_next_token(p2, TERM_COMMA );
  538.     p4 = get_next_token(p3, TERM_COMMA );
  539.     p5 = get_next_token(p4, TERM_COMMA );
  540.     pEnd = get_next_token(p5, TERM_END ); /* zap CR LF, make ASCIIZ */
  541.  
  542.     if ( !pString || !p2 || !p3 || !p4 || !p5 )
  543.         return( False );
  544.  
  545.     /* Check for split lines */
  546.     n = strlen( pString );
  547.     if ( ( pString[n - 1] == '\\' ) && (pString[n - 2] == '\\') ) {
  548.         /* We have a continuation string here */
  549.         pString[n - 2] = 0;
  550.         n -= 2;
  551.         if ( !(pp = (char *)AllocateListObject( &ci->ListOfSplitLines, n + 1 ))  ) {
  552.             fprintf(stderr, "\nOut of memory allocating continuation line!");
  553.             return( False );
  554.         }
  555.         strcpy( pp, pString ); /* loose the continuation characters */
  556.         return(True);
  557.     }
  558.     if ( ci->ListOfSplitLines.TotalItems > 0 ) {
  559.         /* Join lines together and process */
  560.         if ( !(pJoined = calloc( 1, n + ci->ListOfSplitLines.TotalBytes ) ) ) {
  561.             fprintf(stderr, "\nOut of memory joining continuation lines!");
  562.             return( False );
  563.         }
  564.         for ( pp = (char *)FindFirstListObject( &ci->ListOfSplitLines );
  565.             pp != 0;
  566.             pp = (char *)FindNextListObject( &ci->ListOfSplitLines ) ) {
  567.  
  568.             strcat( pJoined, pp ); /* connect the lines */
  569.         }
  570.         strcat( pJoined, pString );
  571.         FreeList( &ci->ListOfSplitLines );
  572.         if ( !AddListObject( &ci->ListOfSplitLines, pJoined, n + ci->ListOfSplitLines.TotalBytes )  ) {
  573.             fprintf(stderr, "\nUnable to add joined continuation line");
  574.             return( False );
  575.         }
  576.         pString = pJoined;
  577.     }
  578.  
  579.  
  580.     if ( *p2 == '0' )
  581.         TypeCode = atox(p2);    /* presume to be hex 0x */
  582.     else
  583.         TypeCode = atoi(p2);
  584.  
  585.     switch ( TypeCode ) {
  586.  
  587.     case N_OPT:     /* compiler options */
  588.         break;      /* nothing used here */
  589.  
  590.     case N_SO:      /* source file name: name,,0,0,address */
  591.         ok = stab_add_filename( pString, p5 );
  592.         break;
  593.  
  594.     case N_GSYM:    /* global symbol: name,,0,type,0 */
  595.         pType = get_next_token(pString, TERM_COLON );   /* separate at colon */
  596.         ok = stab_add_global( pi, pString, pType );
  597.         break;
  598.  
  599.     case N_FUN:     /* procedure: name,,0,linenumber,address */
  600.         ok = stab_add_function( pi, pString, p5 );
  601.         break;
  602.  
  603.     case N_LSYM:    /* local sym: name,,0,type,offset */
  604.         /* pString, p2 = TypeCode, p3 = 0, p4 = 0, p5 = offset */
  605.         pType = get_next_token(pString, TERM_COLON );   /* pType = symbol descriptor (character after the colon) */
  606.         if ( *pType == 't')
  607.             ok = stab_add_local_type( pString, ++pType );
  608.         else if (*pType == 'T')
  609.             ok = stab_add_tag_type( pString, ++pType );
  610.         else
  611.             ok = stab_add_local( pi, pString, pType, p5 );
  612.         break;
  613.  
  614.     case N_RSYM:    /* Symbol:[P|r]type,0,size,register */
  615.         pType = get_next_token(pString, TERM_COLON );   /* separate at colon */
  616.         ok = stab_add_local_register( pi, pString, pType, p5 );
  617.         break;
  618.  
  619.     case N_LCSYM:   /* .lcomm symbol: name,,0,type,address */
  620.         ok = True;
  621.         break;  /* ignore constants */
  622.  
  623.     case N_STSYM:   /* static symbol: name,,0,type,address */
  624.         pType = get_next_token(pString, TERM_COLON );   /* separate at colon */
  625.         ok = stab_add_static_symbol( pi, pString, pType, p5 );
  626.         break;
  627.  
  628.     case N_PSYM:    /* parameter: name,,0,type,offset */
  629.         pType = get_next_token(pString, TERM_COLON );   /* separate at colon */
  630.         ok = stab_add_parameter_symbol( pi, pString, pType, p5 );
  631.         break;
  632.  
  633.     case N_SOL:     /* #included file name: name,,0,0,address */
  634.         ok = True;
  635.         break;  /* ignore include files */
  636.  
  637.     default:
  638.         ok = False;
  639.     }
  640.  
  641.     if ( ci->ListOfSplitLines.TotalItems > 0 )
  642.         FreeList( &ci->ListOfSplitLines );
  643.  
  644.     return( ok );
  645. }
  646. /****************************************************************************************/
  647.  
  648. int parse_stabn( struct prog_info *pi, char *p ){
  649.  
  650.     int ok = True;
  651.     int TypeCode /* , LineNumber */, Level;
  652.     char *p1, *p2, *p3, *p4, *pLabel, *pFunction, *pEnd;
  653.  
  654.     /* stabn debugging information is in the form:
  655.     .stabn TypeCode, 0, parm1, parm2
  656.     parm1 is level
  657.     parm2 is Label-Function
  658.  
  659.     compiler currently produces the following TypeCodes:
  660.     N_LBRAC     0xc0            left bracket: 0,,0,nesting level,address
  661.     N_RBRAC     0xe0            right bracket: 0,,0,nesting level,address
  662.     N_SLINE     0x44            src line: 0,,0,linenumber,address
  663.     */
  664.  
  665.     if ( !GET_ARG(pi->args, ARG_COFF) || ( pi->pass == PASS_1 ) )
  666.         return(True);
  667.  
  668.     /* Parse the tokens in the stabn line buffer */
  669.     p1 = get_next_token(p, TERM_SPACE );
  670.     p2 = get_next_token(p1, TERM_COMMA );
  671.     p3 = get_next_token(p2, TERM_COMMA );
  672.     p4 = get_next_token(p3, TERM_COMMA );
  673.     pEnd = get_next_token(p4, TERM_END ); /* zap CR LF, make ASCIIZ */
  674.  
  675.     if ( !p1 || !p2 || !p3 || !p4 )
  676.         return( False );
  677.  
  678.     /* first convert TypeCode to binary */
  679.     if ( *p1 == '0' )
  680.         TypeCode = atox(p1);    /* presume to be hex 0x */
  681.     else
  682.         TypeCode = atoi(p1);
  683.  
  684.     Level = atoi(p3);   /* line number or level */
  685.     pLabel = p4;                /* Assembly label */
  686.     pFunction = get_next_token( pLabel, TERM_DASH ); /* Function */
  687.  
  688.     switch ( TypeCode ) {
  689.     case N_SLINE:           /* src line: 0,,0,linenumber,address */
  690.         ok = stab_add_lineno( pi, Level, pLabel, pFunction );
  691.         break;
  692.  
  693.     case N_LBRAC:           /* left bracket: 0,,0,nesting level,address */
  694.         ok = stab_add_lbracket( pi, Level, pLabel, pFunction );
  695.         break;
  696.  
  697.     case N_RBRAC:           /* right bracket: 0,,0,nesting level,address */
  698.         ok = stab_add_rbracket( pi, Level, pLabel, pFunction );
  699.         break;
  700.  
  701.     default:
  702.         fprintf(stderr, "\nUnknown .stabn TypeCode = 0x%x", TypeCode );
  703.         ok = False;
  704.     }
  705.     return( ok );
  706. }
  707.  
  708. /****************************************************************************************/
  709. int stab_add_lineno(  struct prog_info *pi, int LineNumber, char *pLabel, char *pFunction ){
  710.  
  711.     int Address;
  712.     struct lineno *pln;
  713.     struct syment *pEntry;
  714.     union auxent *pAux;
  715.  
  716.     /* Allocate LineNumber Table entry and fill it in */
  717.     pln = (struct lineno *)AllocateListObject(&ci->ListOfLineNumbers, sizeof(struct lineno)  );
  718.     if ( !pln ) {
  719.         fprintf(stderr, "\nOut of memory allocating lineno table for function %s", pFunction );
  720.         return( False );
  721.     }
  722.     /* set value field to be address of label in bytes */
  723.     if ( !get_symbol(pi, pLabel, &Address) ) {
  724.         fprintf(stderr, "\nUnable to locate label %s", pLabel );
  725.         return( False );
  726.     }
  727.     pln->l_addr.l_paddr = Address * 2; /* need byte quanities */
  728.  
  729.     /* Line number is relative to beginning of function, starts at 1 */
  730.     if ( ci->FunctionStartLine == 0 ) {
  731.         /* This line number is that same as the function start */
  732.         ci->FunctionStartLine = LineNumber;
  733.     }
  734.     pln->l_lnno = LineNumber - ci->FunctionStartLine + 1;
  735.     ci->CurrentSourceLine = LineNumber; /* keep track of source line for .eb .ef arrays */
  736.     if ( ci->NeedLineNumberFixup ) {
  737.         /* need to go into symbol table and fix last NeedLineNumberFixup entries */
  738.         for ( pEntry = (struct syment *)FindLastListObject(&ci->ListOfSymbols);
  739.             (pEntry != 0) && ( ci->NeedLineNumberFixup != 0);
  740.             pEntry = (struct syment *)FindNextLastListObject(&ci->ListOfSymbols) ) {
  741.  
  742.             /* Fix up line number entries */
  743.             if ( (pEntry->n_sclass == C_FCN ) || ( pEntry->n_sclass == C_BLOCK ) || ( pEntry->n_sclass == C_EXT) ) {
  744.                 pEntry++;
  745.                 pAux = (union auxent *)pEntry;
  746.                 pAux->x_sym.x_misc.x_lnsz.x_lnno = LineNumber;
  747.                 ci->NeedLineNumberFixup--;
  748.             }
  749.         }
  750.     }
  751.  
  752.     return(True);
  753. }
  754. /****************************************************************************************/
  755.  
  756. int stab_add_lbracket( struct prog_info *pi, int Level, char *pLabel, char *pFunction ){
  757.  
  758.     int Address;
  759.     struct syment *pEntry;
  760.     union auxent *pAux;
  761.     //char *p;
  762.     //struct lineno *pln;
  763.  
  764.     if ( !get_symbol(pi, pLabel, &Address) ) {
  765.         fprintf(stderr, "\nUnable to locate label %s", pLabel );
  766.         return( False );
  767.     }
  768.  
  769.     /* Now create a .bb symbol table entry and aux entry too */
  770.     pEntry = (struct syment *)AllocateTwoListObjects( &ci->ListOfSymbols,  sizeof(struct syment) * 2 );
  771.     if ( !pEntry ) {
  772.         fprintf(stderr, "\nOut of memory allocating symbol table entry for .bb %s", pLabel );
  773.         return( False );
  774.     }
  775.     /* n_name */
  776.     memset( pEntry->n_name, 0, 8 );
  777.     strcpy( pEntry->n_name, ".bb" );
  778.  
  779.     pEntry->n_value = Address * 2;  /* bytes not words */
  780.     pEntry->n_scnum = 1;    /* .text */
  781.     pEntry->n_type = 0;
  782.     pEntry->n_sclass = C_BLOCK;
  783.     pEntry->n_numaux = 1;
  784.     pEntry++;   /* point to aux entry */
  785.     pAux = (union auxent *)pEntry;
  786.     pAux->x_sym.x_misc.x_lnsz.x_lnno = 0;   /* UNKNOWN - post process */
  787.     pAux->x_sym.x_misc.x_lnsz.x_size = 0;   /* UNKNOWN - post process */
  788.     ci->NeedLineNumberFixup++; /* once for .bb block */
  789.     return(True);
  790. }
  791.  
  792. /****************************************************************************************/
  793. int stab_add_rbracket( struct prog_info *pi, int Level, char *pLabel, char *pFunction ){
  794.  
  795.     int Address;
  796.     struct syment *pEntry;
  797.     union auxent *pAux;
  798.     //char *p;
  799.     //struct lineno *pln;
  800.  
  801.     if ( !get_symbol(pi, pLabel, &Address) ) {
  802.         fprintf(stderr, "\nUnable to locate label %s", pLabel );
  803.         return( False );
  804.     }
  805.  
  806.     /* Now create a .eb symbol table entry */
  807.     pEntry = (struct syment *)AllocateTwoListObjects( &ci->ListOfSymbols,  sizeof(struct syment) * 2 );
  808.     if ( !pEntry ) {
  809.         fprintf(stderr, "\nOut of memory allocating symbol table entry for .eb %s", pLabel );
  810.         return( False );
  811.     }
  812.     /* n_name */
  813.     memset( pEntry->n_name, 0, 8 );
  814.     strcpy( pEntry->n_name, ".eb" );
  815.     pEntry->n_sclass = C_BLOCK;
  816.     pEntry->n_value = Address * 2;  /* bytes not words */
  817.     pEntry->n_scnum = 1;    /* .text */
  818.     pEntry->n_type = 0;
  819.     pEntry->n_numaux = 1;
  820.     pEntry++;   /* point to aux entry */
  821.     pAux = (union auxent *)pEntry;
  822.     pAux->x_sym.x_misc.x_lnsz.x_lnno = ci->CurrentSourceLine;
  823.  
  824.     /* create an .ef if at level 0 */
  825.     if ( Level == 0 ) {
  826.  
  827.         /* Now create a .ef symbol table entry */
  828.         pEntry = (struct syment *)AllocateTwoListObjects( &ci->ListOfSymbols,  sizeof(struct syment) * 2 );
  829.         if ( !pEntry ) {
  830.             fprintf(stderr, "\nOut of memory allocating symbol table entry for .ef %s", pLabel );
  831.             return( False );
  832.         }
  833.         /* n_name */
  834.         memset( pEntry->n_name, 0, 8 );
  835.         strcpy( pEntry->n_name, ".ef" );
  836.         pEntry->n_sclass = C_FCN;
  837.         pEntry->n_value = Address * 2;  /* bytes not words */
  838.         pEntry->n_scnum = 1;    /* .text */
  839.         pEntry->n_type = 0;
  840.         pEntry->n_numaux = 1;
  841.         pEntry++;   /* point to aux entry */
  842.         pAux = (union auxent *)pEntry;
  843.         pAux->x_sym.x_misc.x_lnsz.x_lnno = ci->CurrentSourceLine;
  844.     }
  845.     return(True);
  846. }
  847.  
  848. /****************************************************************************************/
  849. int stab_add_filename( char *pName, char *pLabel ){
  850.  
  851.     int ok, n;
  852.     struct syment *pEntry;
  853.     union auxent *pAux;
  854.     char *p;
  855.  
  856.     /* if( pLabel == "Ltext0" ) then beginning of .text, pName = cwd, next pName = file */
  857.  
  858.     /* if( pLabel == "Letext" ) then end of .text , pName == NULL */
  859.  
  860.     /* we only need the one not ending in Slash */
  861.     ok = True;
  862.     n = strlen(pName);
  863.     if ( n > 0 ) {
  864.         if ( ( pName[ n - 1] == '\\') || (pName[ n - 1] == '/') )
  865.             return(True); /* ignore */
  866.     } else
  867.         return(True);
  868.  
  869.  
  870.     /* allocate entry in symbol table list */
  871.     pEntry = (struct syment *)AllocateTwoListObjects(
  872.                                                     &ci->ListOfSymbols,  sizeof(struct syment) * 2 ); /* aux entry too */
  873.     if ( !pEntry ) {
  874.         fprintf(stderr, "\nOut of memory allocating symbol table entry for global %s", pName );
  875.         return( False );
  876.     }
  877.     /* n_name */
  878.     memset( pEntry->n_name, 0, 8 );
  879.     strcpy( pEntry->n_name, ".file" );
  880.     /* n_value is determined after processing done UNKNOWN - post process */
  881.     /* The value of that symbol equals the symbol table entry index of the next .file symbol or .global */
  882.     /* post process */
  883.     pEntry->n_scnum = N_DEBUG;
  884.     pEntry->n_sclass = C_FILE;
  885.     pEntry->n_numaux = 1;
  886.     pEntry++;   /* point to aux entry */
  887.     pAux = (union auxent *)pEntry;
  888.  
  889.     /* Add Label name to symbol table */
  890.     if ( n <= FILNMLEN ) {
  891.         /* inline filename */
  892.         memset( pAux->x_file.x_fname, 0, FILNMLEN );
  893.         strncpy( pAux->x_file.x_fname, pName, n ); /* might not be zero terminated */
  894.     } else {
  895.         pAux->x_file.x_n.x_zeroes = 0;  /* symbol name is in string table */
  896.         pAux->x_file.x_n.x_offset = ci->ListOfStrings.TotalBytes;
  897.  
  898.         /* add to string table */
  899.         p = (char *)AllocateListObject( &ci->ListOfStrings,  n + 1 );
  900.         if ( !p ) {
  901.             fprintf(stderr, "\nOut of memory allocating string table space!");
  902.             return( False );
  903.         }
  904.         strcpy( p, pName );
  905.     }
  906.     return( ok );
  907. }
  908.  
  909. /****************************************************************************************/
  910. int stab_add_function( struct prog_info *pi, char *pName, char *pLabel ){
  911.  
  912.     int n, Address;
  913.     unsigned short CoffType, Type;
  914.     struct syment *pEntry;
  915.     char *pType;
  916.     struct lineno *pln;
  917.     union auxent *pAux;
  918.     int SymbolIndex;
  919.  
  920.     pType = get_next_token(pName, TERM_COLON ); /* pType = symbol descriptor (character after the colon) */
  921.     Type = atoi(pType + 1);     /* skip past F, predefined variable type */
  922.     if ( (CoffType = GetCoffType( Type )) == 0 ) {
  923.         fprintf(stderr, "\nUnrecognized return type found for function %s = %d", pName, Type );
  924.         return(False);
  925.     }
  926.     /* Get Current Symbol Index, Allocate Symbol Table entry and fill it in */
  927.     SymbolIndex = ci->ListOfSymbols.TotalItems;
  928.     pEntry = (struct syment *)AllocateTwoListObjects( &ci->ListOfSymbols, sizeof(struct syment) * 2 );
  929.     if ( !pEntry ) {
  930.         fprintf(stderr, "\nOut of memory allocating symbol table entry for function %s", pName );
  931.         return( False );
  932.     }
  933.     if ( (n = AddNameToEntry( pName, pEntry )) == 0 ) {
  934.         fprintf(stderr,"\nOut of memory adding local %s to string table", pName );
  935.     }
  936.     if ( !get_symbol(pi, pLabel, &Address) ) {
  937.         fprintf(stderr, "\nUnable to locate function %s", pName );
  938.         return( False );
  939.     }
  940.     pEntry->n_value = Address * 2;  /* convert words to bytes */
  941.     pEntry->n_scnum = 2;    /* .bss */
  942.     if ( (CoffType = GetCoffType( Type )) == 0 ) {
  943.         fprintf(stderr, "\nUnrecognized type found for function %s = %d", pName, Type );
  944.         return(False);
  945.     }
  946.     pEntry->n_type = (unsigned short)(CoffType | (DT_FCN << 4));
  947.     pEntry->n_sclass = C_EXT;
  948.     pEntry->n_numaux = 1;
  949.     pEntry++;   /* point to aux entry */
  950.     pAux = (union auxent *)pEntry;
  951.     pAux->x_sym.x_tagndx = SymbolIndex + 1; /* point to the .bf entry index */
  952.     // wrong!
  953.     //  pAux->x_sym.x_misc.x_lnsz.x_lnno = ci->ListOfLineNumbers.TotalBytes; /* Relative Fixup point to where line numbers start */
  954.     //  pAux->x_sym.x_misc.x_lnsz.x_size = 0; /* UNKNOWN till next function called */
  955.     pAux->x_sym.x_misc.x_fsize = 0; /* unknown till end */
  956.     pAux->x_sym.x_fcnary.x_fcn.x_lnnoptr = ci->ListOfLineNumbers.TotalBytes; /* relative offset to line number entry */
  957.     pAux->x_sym.x_fcnary.x_fcn.x_endndx = 0; /* index to next entry */
  958.  
  959.     /* Now add function entry into the line number table */
  960.     /* Allocate Symbol Table entry and fill it in */
  961.     pln = (struct lineno *)AllocateListObject(&ci->ListOfLineNumbers, sizeof(struct lineno)  );
  962.     if ( !pln ) {
  963.         fprintf(stderr, "\nOut of memory allocating lineno table for function %s", pName );
  964.         return( False );
  965.     }
  966.     pln->l_lnno = 0;
  967.     pln->l_addr.l_symndx = SymbolIndex;
  968.  
  969.     /* Initialize the FunctionStartLine from the beginning of the function */
  970.     ci->FunctionStartLine = 0;
  971.  
  972.     /* Allocate Symbol Table entry and fill it in */
  973.     pEntry = (struct syment *)AllocateTwoListObjects( &ci->ListOfSymbols, sizeof(struct syment) * 2 );
  974.     if ( !pEntry ) {
  975.         fprintf(stderr, "\nOut of memory allocating symbol table entry .bf for function %s", pName );
  976.         return( False );
  977.     }
  978.     memset( pEntry->n_name, 0, 8 );
  979.     strcpy( pEntry->n_name, ".bf" );
  980.     pEntry->n_value = Address * 2;  /* bytes not words */
  981.     pEntry->n_scnum = 1;    /* .text */
  982.     pEntry->n_type = 0;
  983.     pEntry->n_sclass = C_FCN;
  984.     pEntry->n_numaux = 1;
  985.     pEntry++;   /* point to aux entry */
  986.     pAux = (union auxent *)pEntry;
  987.     pAux->x_sym.x_misc.x_lnsz.x_lnno = 0;   /* UNKNOWN - post process */
  988.     pAux->x_sym.x_misc.x_lnsz.x_size = 0;   /* UNKNOWN - post process */
  989.  
  990.     ci->NeedLineNumberFixup++; /* once for function C_EXT symbol */
  991.     ci->NeedLineNumberFixup++; /* once for .bf block */
  992.     return( True );
  993. }
  994. /****************************************************************************************/
  995.  
  996. int stab_add_global( struct prog_info *pi, char *pName, char *pType ){
  997.  
  998.     int n, Address, IsArray, SymbolIndex;
  999.     unsigned short CoffType, Type;
  1000.     struct syment *pEntry;
  1001.     char *p;
  1002.     STABCOFFMAP *pMap;
  1003.  
  1004.  
  1005.     n = strlen( pName );    /* see if it's 8 bytes or less */
  1006.     Type = atoi(pType + 1);     /* skip past G, predefined variable type */
  1007.     if ( (CoffType = GetCoffType( Type )) == 0 ) {
  1008.         fprintf(stderr, "\nUnrecognized type found for global %s = %d", pName, Type );
  1009.         return(False);
  1010.     }
  1011.     pMap = (STABCOFFMAP *)GetCurrentListObject( &ci->ListOfTypes );
  1012.  
  1013.     SymbolIndex = ci->ListOfSymbols.TotalItems;
  1014.     /* Allocate Symbol Table entry and fill it in, Auxiliary table if its an array */
  1015.     if ( IsTypeArray( CoffType ) == True ) {
  1016.         IsArray = True;
  1017.         pEntry = (struct syment *)AllocateTwoListObjects( &ci->ListOfGlobals, sizeof(struct syment) * 2 );
  1018.     } else {
  1019.         IsArray = False;
  1020.         pEntry = (struct syment *)AllocateListObject( &ci->ListOfGlobals, sizeof(struct syment) );
  1021.     }
  1022.     if ( (n = AddNameToEntry( pName, pEntry )) == 0 ) {
  1023.         fprintf(stderr,"\nOut of memory adding local %s to string table", pName );
  1024.     }
  1025.     /* set value field to be address of label in bytes */
  1026.     /* add underscore to lookup label */
  1027.     if ( (p = calloc( 1, n + 2)) == 0 ) {
  1028.         fprintf(stderr,"\nOut of memory adding global %s", pName );
  1029.         return(False);
  1030.     }
  1031.     *p = '_';
  1032.     strcpy( p + 1, pName );
  1033.     if ( !get_symbol(pi, p, &Address) ) {
  1034.         fprintf(stderr, "\nUnable to locate global %s", p );
  1035.         free( p );
  1036.         return( False );
  1037.     }
  1038.     free( p );
  1039.     pEntry->n_value = Address;  /* already in bytes */
  1040.     if ( ci->GlobalStartAddress == -1 ) {
  1041.         ci->GlobalStartAddress = Address;
  1042.     }
  1043.     if ( Address < ci->GlobalStartAddress )
  1044.         ci->GlobalStartAddress = Address;
  1045.     if ( Address > ci->GlobalEndAddress )
  1046.         ci->GlobalEndAddress = Address;
  1047.  
  1048.     pEntry->n_scnum = 2;    /* .bss */
  1049.     pEntry->n_type = CoffType;
  1050.     pEntry->n_sclass = C_STAT;
  1051.     if ( IsArray == False )
  1052.         pEntry->n_numaux = 0;
  1053.     else {
  1054.         pEntry->n_numaux = 1;
  1055.         pEntry++;
  1056.         AddArrayAuxInfo( (union auxent *)pEntry, (unsigned short)SymbolIndex, pMap );
  1057.     }
  1058.     return( True );
  1059. }
  1060.  
  1061. /****************************************************************************************/
  1062. int stab_add_local(  struct prog_info *pi, char *pName, char *pType, char *pOffset  ){
  1063.  
  1064.     int n, Offset, IsArray;
  1065.     unsigned short CoffType, Type, SymbolIndex;
  1066.     struct syment *pEntry;
  1067.     STABCOFFMAP *pMap;
  1068.  
  1069.     n = strlen( pName );    /* see if it's 8 bytes or less */
  1070.     Type = atoi(pType);     /* predefined variable type */
  1071.     Offset = atoi(pOffset); /* offset in stack frame */
  1072.     if ( (CoffType = GetCoffType( Type )) == 0 ) {
  1073.         fprintf(stderr, "\nUnrecognized type found for local %s = %d", pName, Type );
  1074.         return(False);
  1075.     }
  1076.     pMap = (STABCOFFMAP *)GetCurrentListObject( &ci->ListOfTypes );
  1077.     SymbolIndex = ci->ListOfSymbols.TotalItems;
  1078.     /* Allocate Symbol Table entry and fill it in, Auxiliary table if its an array */
  1079.     if ( IsTypeArray( CoffType ) == True ) {
  1080.         IsArray = True;
  1081.         pEntry = (struct syment *)AllocateTwoListObjects( &ci->ListOfGlobals, sizeof(struct syment) * 2 );
  1082.     } else {
  1083.         IsArray = False;
  1084.         pEntry = (struct syment *)AllocateListObject( &ci->ListOfSymbols, sizeof(struct syment) );
  1085.     }
  1086.     if ( (n = AddNameToEntry( pName, pEntry )) == 0 ) {
  1087.         fprintf(stderr,"\nOut of memory adding local %s to string table", pName );
  1088.     }
  1089.     pEntry->n_type = CoffType;
  1090.     pEntry->n_sclass = C_AUTO;
  1091.     pEntry->n_scnum = N_ABS;
  1092.     pEntry->n_value = Offset + 1; /* Silly avr studio is set in its ways */
  1093.     if ( IsArray == False )
  1094.         pEntry->n_numaux = 0;
  1095.     else {
  1096.         pEntry->n_numaux = 1;
  1097.         pEntry++;
  1098.         AddArrayAuxInfo( (union auxent *)pEntry, SymbolIndex, pMap );
  1099.     }
  1100.     return( True );
  1101. }
  1102.  
  1103. /****************************************************************************************/
  1104. int stab_add_parameter_symbol( struct prog_info *pi, char *pName, char *pType, char *pOffset  ){
  1105.  
  1106.     int n, Offset;
  1107.     unsigned short CoffType, Type;
  1108.     struct syment *pEntry;
  1109.  
  1110.     n = strlen( pName );    /* see if it's 8 bytes or less */
  1111.     Type = atoi(pType);     /* predefined variable type */
  1112.     Offset = atoi(pOffset); /* offset in stack frame */
  1113.     if ( (CoffType = GetCoffType( Type )) == 0 ) {
  1114.         fprintf(stderr, "\nUnrecognized type found for %s = %d", pName, Type );
  1115.         return(False);
  1116.     }
  1117.     /* Allocate Symbol Table entry and fill it in */
  1118.     pEntry = (struct syment *)AllocateListObject( &ci->ListOfSymbols, sizeof(struct syment) );
  1119.     if ( (n = AddNameToEntry( pName, pEntry )) == 0 ) {
  1120.         fprintf(stderr,"\nOut of memory adding local %s to string table", pName );
  1121.     }
  1122.     pEntry->n_type = CoffType;
  1123.     pEntry->n_sclass = C_ARG;
  1124.     pEntry->n_scnum = N_ABS;
  1125.     pEntry->n_value = Offset;
  1126.     pEntry->n_numaux = 0;
  1127.     return( True );
  1128. }
  1129. /****************************************************************************************/
  1130. int stab_add_static_symbol(  struct prog_info *pi, char *pName, char *pType, char *pLabel  ){
  1131.  
  1132.     int n, Address;
  1133.     unsigned short CoffType, Type;
  1134.     struct syment *pEntry;
  1135.  
  1136.     n = strlen( pName );    /* see if it's 8 bytes or less */
  1137.     Type = atoi(pType + 1);     /* skip past S, predefined variable type */
  1138.     if ( (CoffType = GetCoffType( Type )) == 0 ) {
  1139.         fprintf(stderr, "\nUnrecognized type found for %s = %d", pName, Type );
  1140.         return(False);
  1141.     }
  1142.     /* Allocate Symbol Table entry and fill it in */
  1143.     pEntry = (struct syment *)AllocateListObject( &ci->ListOfSymbols, sizeof(struct syment) );
  1144.     if ( (n = AddNameToEntry( pName, pEntry )) == 0 ) {
  1145.         fprintf(stderr,"\nOut of memory adding local %s to string table", pName );
  1146.     }
  1147.     pEntry->n_type = CoffType;
  1148.     pEntry->n_sclass = C_STAT;
  1149.     pEntry->n_scnum = N_ABS;
  1150.     if ( !get_symbol(pi, pLabel, &Address) ) {
  1151.         fprintf(stderr, "\nUnable to locate label %s", pLabel );
  1152.         return( False );
  1153.     }
  1154.     pEntry->n_value = Address * 2;  /* find address of variable in bytes */
  1155.     pEntry->n_numaux = 0;
  1156.     return( True );
  1157. }
  1158. /****************************************************************************************/
  1159.  
  1160. int stab_add_local_register(  struct prog_info *pi, char *pName, char *pType, char *pRegister  ){
  1161.  
  1162.     int n, Register, Size;
  1163.     unsigned short CoffType, Type;
  1164.     struct syment *pEntry;
  1165.  
  1166.     n = strlen( pName );    /* see if it's 8 bytes or less */
  1167.     Type = (unsigned short)atoi(pType + 1);     /* skip past P, predefined variable type */
  1168.     Register = atoi(pRegister); /* offset in stack frame */
  1169.     if ( (CoffType = GetCoffType( Type )) == 0 ) {
  1170.         fprintf(stderr, "\nUnrecognized type found for %s = %d", pName, Type );
  1171.         return(False);
  1172.     }
  1173.     Size = GetCoffTypeSize( Type ); /* Silly requirement for avr studio */
  1174.     /* Allocate Symbol Table entry and fill it in */
  1175.     pEntry = (struct syment *)AllocateListObject( &ci->ListOfSymbols, sizeof(struct syment) );
  1176.     if ( (n = AddNameToEntry( pName, pEntry )) == 0 ) {
  1177.         fprintf(stderr,"\nOut of memory adding local %s to string table", pName );
  1178.         return(False);
  1179.     }
  1180.     pEntry->n_type = CoffType;
  1181.     //  if( (*pType == 'r') || (*pType == 'R') )
  1182.     //          pEntry->n_sclass = C_REG;
  1183.     //  else if( (*pType == 'p') || (*pType == 'P') )
  1184.     pEntry->n_sclass = C_REGPARM;   /* Silly avr studio only accepts this for registers */
  1185.     //  else{
  1186.     //      fprintf(stderr,"\nUnknown register type -> %s", pType );
  1187.     //          return(False);
  1188.     //  }
  1189.     pEntry->n_scnum = N_ABS;
  1190.     pEntry->n_numaux = 0;
  1191.     if ( Size == 1 )
  1192.         pEntry->n_value = 0xffffff00 | Register; /* Silly requirement for avr studio */
  1193.     else if ( Size == 2 )
  1194.         pEntry->n_value = 0xffff0000 | ((Register + 1) << 8) | Register; /* Silly requirement for avr studio */
  1195.     else if ( Size == 4 )
  1196.         pEntry->n_value = ((Register + 3) << 24) | ((Register + 3) << 16) | ((Register + 1) << 8) | Register; /* Silly requirement for avr studio */
  1197.     else {
  1198.         fprintf(stderr,"\nUnknown register size (%d) and coff type (%d)", Size, CoffType );
  1199.         return(False);
  1200.     }
  1201.     return( True );
  1202. }
  1203.  
  1204. /****************************************************************************************/
  1205.  
  1206. int stab_add_local_type( char *pName, char *pType ){
  1207.  
  1208.     char *p;
  1209.     unsigned short StabType;
  1210.  
  1211.     /* .stabs "int:t1=r1;-128;127;",128,0,0,0 */
  1212.     /* .stabs ":t20=ar1;0;1;21=ar1;0;1;2",128,0,0,0 */
  1213.     /* pType-----^                                   */
  1214.     /* Stab Type - convert to Coff type at end (after inline assignments */
  1215.     if ( GetStabType( pType, &StabType, &p ) != True ) {
  1216.         fprintf(stderr,"\nInvalid tag type found in structure item -> %s", p);
  1217.         return(False);      
  1218.     }
  1219.  
  1220.     return(True);
  1221. }
  1222.  
  1223. /****************************************************************************************/
  1224.  
  1225. int GetStructUnionTagItem( char *p, char **pEnd, char **pName, unsigned short *pType, unsigned short *pBitOffset, unsigned short *pBitSize) {
  1226.  
  1227.     unsigned short StabType;
  1228.     /* Structure or Union Tag Item consists of -> name:type,bitoffset,bitsize; */
  1229.  
  1230.     /* name */
  1231.     *pName = p;
  1232.     while ( *p && (*p != ':') ) p++; // locate colon
  1233.     if ( *p != ':' ) {
  1234.       fprintf(stderr,"\nNo colon found in structure item -> %s", *pName);
  1235.       return(False);      
  1236.     }
  1237.     *p++ = 0; // Asciiz
  1238.  
  1239.     /* Stab Type - convert to Coff type at end (after inline assignments */
  1240.     if ( GetStabType( p, &StabType, &p ) != True ) {
  1241.         fprintf(stderr,"\nInvalid tag type found in structure item -> %s", p);
  1242.         return(False);      
  1243.     }
  1244.  
  1245.     /* BitSize */
  1246.     if ( *p != ',' ) {
  1247.         fprintf(stderr,"\nNo Bit size found in structure item -> %s", p );
  1248.         return(False);      
  1249.     }
  1250.     *pBitOffset = (unsigned short)atoi( ++p );
  1251.     while ( *p && (*p >= '0') && (*p <= '9') ) p++; // locate end of digits
  1252.  
  1253.     /* BitOffset */
  1254.     if ( *p != ',' ) {
  1255.         fprintf(stderr,"\nNo Bit offset found in structure item -> %s", p );
  1256.         return(False);      
  1257.     }
  1258.     *pBitSize =  (unsigned short)atoi( ++p );
  1259.     while ( *p && (*p >= '0') && (*p <= '9') ) p++; // locate end of digits
  1260.  
  1261.     /* Now convert stab type to COFF */
  1262.     if ( (*pType = GetCoffType( (unsigned short)StabType)) == 0 ) {
  1263.         fprintf(stderr,"\nNo COFF type found for stab type %d", StabType );
  1264.         return(   False);          
  1265.     }
  1266.     if ( *++p == ';' ) /* Now eat last semicolon(s) */
  1267.         p++;
  1268.     *pEnd = p;
  1269.  
  1270.     return( True );
  1271. }
  1272. /****************************************************************************************/
  1273.  
  1274. int GetEnumTagItem( char *p, char **pEnd, char **pEnumName, int *pEnumValue ) {
  1275.  
  1276.     /* Enum Tag Item consists of -> member1:value,member2:value2,; */
  1277.     *pEnumName = p;
  1278.     while ( *p && (*p != ':') ) p++; // locate colon
  1279.     if ( *p != ':' ) {
  1280.       fprintf(stderr,"\nNo colon found in enum item -> %s", *pEnumName);
  1281.       return(False);      
  1282.     }
  1283.     *p++ = 0; // Asciiz
  1284.     *pEnumValue = atoi(p);
  1285.  
  1286.     while ( *p && (*p >= '0') && (*p <= '9') ) p++; // locate end of digits
  1287.     if ( *p != ',' ) {
  1288.         fprintf(stderr,"\nNo comma found after enum value -> %s", p );
  1289.         return(False);      
  1290.     }
  1291.     if ( *++p ==';' )
  1292.         p++; /* eat last semicolon */
  1293.     *pEnd = p;
  1294.     return( True );
  1295. }
  1296.  
  1297. /****************************************************************************************/
  1298. int GetArrayType( char *p, char **pEnd, STABCOFFMAP *pMap, unsigned short *DerivedBits, int ExtraLevels ){
  1299.  
  1300.     int MinIndex, MaxIndex, Result, Size, i;
  1301.     char *pMinIndex, *pMaxIndex, *pType;
  1302.     unsigned short Type;
  1303.  
  1304.     Result = True;
  1305.  
  1306.     pMinIndex = pMaxIndex = pType = 0;    
  1307.     while ( *p && (*p != ';') ) p++;   /* find min index */
  1308.     pMinIndex = ++p;
  1309.     while ( *p && (*p != ';') ) p++;   /* find max index */
  1310.     pMaxIndex = ++p;
  1311.     while ( *p && (*p != ';') ) p++;   /* find type index */
  1312.     pType = ++p;
  1313.  
  1314.     /* bump the pointers to the digits */
  1315.     if ( !isdigit(*pMinIndex) )
  1316.         Result = False;
  1317.     if ( !isdigit(*pMaxIndex) )
  1318.         Result = False;
  1319.     if ( !isdigit(*pType) )
  1320.         Result = False;
  1321.     /* Is syntax ok ? */
  1322.     if ( Result != True ) {
  1323.         fprintf(stderr,"\nSyntax error on array parameters %s%s%s", pMinIndex, pMaxIndex, pType );
  1324.         return(False);
  1325.     }
  1326.     MinIndex = atoi(pMinIndex);
  1327.     MaxIndex = atoi(pMaxIndex);
  1328.  
  1329.     if ( GetStabType( p, &Type, &p ) != True )
  1330.         return(False);
  1331.  
  1332.     if ( !SetupDefinedType( Type, pMap, DerivedBits, ExtraLevels ) )
  1333.         return( False );
  1334.  
  1335.     /* Now update the size based on the indicies */
  1336.     Size = (MaxIndex - MinIndex) + 1;
  1337.     pMap->ByteSize *= Size;
  1338.     pMap->Line = ci->CurrentSourceLine;
  1339.     /* add the dimension information */
  1340.     for ( i = 5; i >= 0; i-- ) {
  1341.         if ( pMap->Dimensions[i] != 0 ) {
  1342.             i++;
  1343.             pMap->Dimensions[i] = Size;
  1344.             break;
  1345.         }
  1346.     }
  1347.  
  1348.     *pEnd = p;
  1349.     return(True);
  1350. }
  1351.  
  1352. /****************************************************************************************/
  1353. int GetStabType( char *p, unsigned short *pType, char **pEnd ) {
  1354.  
  1355.     STABCOFFMAP *pMap;
  1356.     int extra, ok;
  1357.     unsigned short derivedbits[6];
  1358.     unsigned short LStabType, RStabType;
  1359.     char *pHigh, *pLow;
  1360.  
  1361.  
  1362.     LStabType = atoi( p );
  1363.     while ( *p && (*p >= '0') && (*p <= '9') ) p++; // locate end of digits
  1364.  
  1365.     *pType = LStabType;
  1366.  
  1367.     if ( GetCoffType( LStabType ) != 0 ) {
  1368.         *pEnd = p;
  1369.         return(True);
  1370.     }
  1371.     if ( *p != '=' ) {
  1372.         fprintf(stderr, "\nSyntax error in type assignment -> %s", p );
  1373.         return(False);
  1374.     }
  1375.     p++;
  1376.  
  1377.     /* Allocate space for new internal type */
  1378.     if ( !(pMap = (STABCOFFMAP *)AllocateListObject(&ci->ListOfTypes, sizeof(STABCOFFMAP)) ) ) {
  1379.         fprintf(stderr, "\nOut of memory allocating type info!");
  1380.         return(False);
  1381.     }
  1382.     pMap->StabType = LStabType;
  1383.  
  1384.     /* process items to right of equals */
  1385.     for ( extra = 0; extra < 6; extra++ ) {
  1386.  
  1387.         if ( isdigit( *p ) ) {
  1388.             /* Finally found base type, try to terminate loop */
  1389.             GetStabType( p, &RStabType, &p );
  1390.             //                  RStabType = atoi( p );
  1391.             while ( *p && (*p >= '0') && (*p <= '9') ) p++; // locate end of digits
  1392.             if ( SetupDefinedType( RStabType, pMap, &derivedbits[0], extra ) != True )
  1393.                 return( False );
  1394.             break;
  1395.         } else if ( *p == 'a' ) {
  1396.             derivedbits[extra] = DT_ARY;
  1397.             p++;
  1398.             /* Calculate size */
  1399.             /* Since type assignment will be made we need to set extra bits here */
  1400.             extra++;
  1401.             /* =ar1;MinIndex;MaxIndex;BaseType */
  1402.             if ( GetArrayType( p, &p, pMap, &derivedbits[0], extra  ) != True )
  1403.                 return(False);
  1404.             break;
  1405.  
  1406.         } else if ( *p == 'f' ) {
  1407.             derivedbits[extra] = DT_FCN;
  1408.             p++;
  1409.         } else if ( *p == '*' ) {
  1410.             derivedbits[extra] = DT_PTR;
  1411.             p++;
  1412.         } else if ( *p == 'r' ) {
  1413.             //                  if( LStabType < 15 )
  1414.             //                          ok = GetInternalType( pString, pMap ); /* internal types not yet installed */
  1415.             //                  else
  1416.             while ( *p && (*p != ';' ) ) p++;
  1417.             pLow = p++;
  1418.             while ( *p && (*p != ';' ) ) p++;
  1419.             pHigh = p++;
  1420.             ok = GetSubRangeType( LStabType, pMap, pLow, pHigh );
  1421.             if ( ok != True )
  1422.                 return(False);
  1423.             while ( *p && (*p != ';' ) ) p++; /* find end of range */
  1424.             p++;
  1425.             break;
  1426.         } else {
  1427.             fprintf(stderr, "\nUnrecognized Type modifier %c!", *p );
  1428.             return(False);
  1429.         }
  1430.     }
  1431.     *pEnd = p; /* Update return pointer */
  1432.  
  1433.     return(True);
  1434. }
  1435.  
  1436.  
  1437. /****************************************************************************************/
  1438. int stab_add_tag_type( char *pName, char *pString ){
  1439.  
  1440.     int SymbolIndex, StabType, TotalSize, n, EnumValue;
  1441.     unsigned short TagType, ItemType, BitOffset, BitSize;
  1442.     char *p;
  1443.     struct syment* pEntry;
  1444.     union auxent *pAux;
  1445.     STABCOFFMAP *pMap;
  1446.  
  1447.     /* We arrived here due to :T defining either a structure, union or enumeration */
  1448.     /* store the basic type as for internals and emit coff structures for debugging */
  1449.     /* .stabs "stag:T17=s2i:1,0,8;c:2,8,8;;",128,0,0,0 */
  1450.     /* .stabs "2:T18=u2a:2,0,8;b:1,0,8;c:6,0,16;;",128,0,0,0 */
  1451.     /* .stabs "1:T19=eenum1:1,enum2:2,enum3:3,;",128,0,0,0 */
  1452.     /* we don't care about the name */
  1453.  
  1454.  
  1455.     /* check for bogus errors */
  1456.     if ( !pName || !pString ) {
  1457.         fprintf(stderr,"\nInvalid .stabs type format - no information!");
  1458.         return(False);
  1459.     }
  1460.  
  1461.     p = pString;
  1462.     /* Stab Type - convert to Coff type at end (after inline assignments */
  1463.     if ( (StabType = (unsigned short)atoi(p)) == 0 ) {
  1464.         fprintf(stderr,"\nInvalid .stabs type format - no information! - > %s", p );
  1465.         return(False);
  1466.     }
  1467.     while ( *p && (*p >= '0') && (*p <= '9') ) p++; // locate end of digits
  1468.     if ( *p != '=' ) {
  1469.         fprintf(stderr,"\nInvalid .stabs type format - no equals - > %s", p );
  1470.         return(False);
  1471.     }
  1472.     SymbolIndex = ci->ListOfSymbols.TotalItems;
  1473.     if (  ( pEntry = (struct syment*)AllocateTwoListObjects( &ci->ListOfGlobals, sizeof(struct syment) * 2 ) ) == 0 ) {
  1474.         fprintf(stderr, "\nOut of memory allocating symbol tag entries");
  1475.         return(False);
  1476.     }
  1477.     /* Prepare Tag Header */
  1478.     if ( (n = AddNameToEntry( pName, pEntry )) == 0 ) {
  1479.         fprintf(stderr,"\nOut of memory adding local %s to string table", pString );
  1480.         return(False);
  1481.     }
  1482.     if ( !(pMap = (STABCOFFMAP *)AllocateListObject(&ci->ListOfTypes, sizeof(STABCOFFMAP)) ) ) {
  1483.         fprintf(stderr, "\nOut of memory allocating type info!");
  1484.         return(False);
  1485.     }
  1486.     pMap->StabType = StabType;
  1487.     pEntry->n_value = 0;
  1488.     pEntry->n_scnum = N_DEBUG;
  1489.     pEntry->n_numaux = 1;
  1490.     if ( *++p == 's' ) {
  1491.         TagType = pEntry->n_type = pMap->CoffType = T_STRUCT;
  1492.         pEntry->n_sclass = C_STRTAG;
  1493.         TotalSize = (unsigned short)atoi(++p);
  1494.     } else if ( *p == 'u' ) {
  1495.         TagType = pEntry->n_type = pMap->CoffType = T_UNION;
  1496.         pEntry->n_sclass = C_UNTAG;
  1497.         TotalSize = (unsigned short)atoi(++p);
  1498.     } else if ( *p == 'e' ) {
  1499.         TagType = pEntry->n_type = pMap->CoffType = T_ENUM;
  1500.         pEntry->n_sclass = C_ENTAG;
  1501.         TotalSize = FundamentalTypes[T_INT].Size; /* use size of int for enums */
  1502.     } else {
  1503.         fprintf(stderr,"\nUnknown tag type -> %s", p );
  1504.         return(False);
  1505.     }
  1506.     while ( *p && (*p >= '0') && (*p <= '9') ) p++; // locate end of digits
  1507.     pEntry++;   /* point to aux entry */
  1508.     pAux = (union auxent *)pEntry;
  1509.     pAux->x_sym.x_tagndx = SymbolIndex;
  1510.     pAux->x_sym.x_misc.x_lnsz.x_size = TotalSize;
  1511.  
  1512.     /* update our local knowledge of tag type */
  1513.     pMap->CoffType = TagType;
  1514.     pMap->ByteSize = TotalSize;
  1515.     pMap->Line = ci->CurrentSourceLine;
  1516.  
  1517.     /* Process the items until the end of the line */
  1518.     while ( *pName ) {
  1519.  
  1520.         if (  ( pEntry = (struct syment*)AllocateTwoListObjects( &ci->ListOfGlobals, sizeof(struct syment) * 2 ) ) == 0 ) {
  1521.             fprintf(stderr, "\nOut of memory allocating symbol tag member entries");
  1522.             return(False);
  1523.         }
  1524.  
  1525.         if ( TagType == T_STRUCT ) {
  1526.             if ( GetStructUnionTagItem( p, &p, &pName, &ItemType, &BitOffset, &BitSize) != True ) {
  1527.                 return(False);
  1528.             }
  1529.             pEntry->n_value = BitOffset/8;
  1530.             pEntry->n_type = ItemType;
  1531.             pEntry->n_sclass = C_MOS;
  1532.         } else if ( TagType == T_UNION ) {
  1533.             if ( GetStructUnionTagItem(  p, &p, &pName, &ItemType, &BitOffset, &BitSize) != True ) {
  1534.                 return(False);
  1535.             }
  1536.             pEntry->n_value = BitOffset/8;
  1537.             pEntry->n_type = ItemType;
  1538.             pEntry->n_sclass = C_MOU;
  1539.         } else { /* T_ENUM */
  1540.             if ( GetEnumTagItem( p, &p, &pName, &EnumValue ) != True ) {
  1541.                 return(False);
  1542.             }
  1543.             pEntry->n_value = EnumValue;
  1544.             pEntry->n_type = TotalSize;
  1545.             pEntry->n_sclass = C_MOE;
  1546.         }
  1547.  
  1548.         /* Prepare Common Tag Header items */
  1549.         if ( (n = AddNameToEntry( pName, pEntry )) == 0 ) {
  1550.             fprintf(stderr,"\nOut of memory adding local %s to string table", pString );
  1551.             return(False);
  1552.         }
  1553.         pEntry->n_scnum = N_ABS;
  1554.         pEntry->n_numaux = 1;
  1555.         pEntry++;   /* point to aux entry */
  1556.         pAux = (union auxent *)pEntry;
  1557.         pAux->x_sym.x_tagndx = SymbolIndex;
  1558.         pAux->x_sym.x_misc.x_lnsz.x_size = TotalSize;
  1559.         pName = p;
  1560.     }
  1561.  
  1562.     /* End of Structures/Unions/Enumberations */
  1563.     if (  ( pEntry = (struct syment*)AllocateTwoListObjects( &ci->ListOfGlobals, sizeof(struct syment) * 2 ) ) == 0 ) {
  1564.         fprintf(stderr, "\nOut of memory allocating special headers for structure!");
  1565.         return(False);
  1566.     }
  1567.     strcpy( pEntry->n_name, ".eos" );
  1568.     pEntry->n_value = TotalSize;
  1569.     pEntry->n_scnum = N_ABS;
  1570.     pEntry->n_type = 0;
  1571.     pEntry->n_sclass = C_EOS;
  1572.     pEntry->n_numaux = 1;
  1573.     pEntry++;   /* point to aux entry */
  1574.     pAux = (union auxent *)pEntry;
  1575.     pAux->x_sym.x_tagndx = SymbolIndex; /* point to the .bf entry index */
  1576.     pAux->x_sym.x_misc.x_lnsz.x_size = TotalSize;
  1577.  
  1578.     return(True);
  1579. }
  1580.  
  1581. /****************************************************************************************/
  1582. int SetupDefinedType( unsigned short Type, STABCOFFMAP *pMap, unsigned short *DerivedBits, int ExtraLevels ){
  1583.  
  1584.     int i, Dlimit, Dstart;
  1585.     unsigned short StabType;
  1586.  
  1587.     StabType = pMap->StabType; /* save the new type we found earlier */
  1588.     if ( CopyStabCoffMap( Type, pMap ) != True ) {
  1589.         fprintf(stderr, "\nCould not find defined type %d", Type );
  1590.         return(False);
  1591.     }
  1592.     pMap->StabType = StabType; /* save the new type we found earlier */
  1593.  
  1594.     /* Determine existing derived types for base class */
  1595.     for ( i = 0; i < 6; i++ ) {
  1596.         if ( (pMap->CoffType & ( 3 << (4 + i + i))) == 0 )
  1597.             break;
  1598.     }
  1599.     Dstart = i;
  1600.     Dlimit = i + ExtraLevels;
  1601.     if ( (Dlimit) >= 6 ) {
  1602.         fprintf(stderr, "\nStab Type %d has too many derived (%d) types!", pMap->StabType, Dlimit );
  1603.         return(False);
  1604.     }
  1605.     /* Add the new derived levels */
  1606.     for ( ; i < Dlimit; i++ ) {
  1607.         pMap->CoffType |= ( ( DerivedBits[i - Dstart] & 3) << (4 + i + i) ); /* add in the derived bits */
  1608.     }
  1609.     return(True);
  1610. }
  1611.  
  1612. /****************************************************************************************/
  1613. int GetArrayDefinitions( STABCOFFMAP *pMap , char *pMinIndex, char *pMaxIndex, char *pType, unsigned short *DerivedBits, int ExtraLevels ){
  1614.  
  1615.     int MinIndex, MaxIndex, Result, Size, i;
  1616.     unsigned short Type;
  1617.  
  1618.     Result = True;
  1619.     if ( (*pMinIndex != ';') || (*pMaxIndex != ';') || (*pType != ';') )
  1620.         Result = False;
  1621.     /* bump the pointers to the digits */
  1622.     pMinIndex++;
  1623.     if ( !isdigit(*pMinIndex) )
  1624.         Result = False;
  1625.     pMaxIndex++;
  1626.     if ( !isdigit(*pMaxIndex) )
  1627.         Result = False;
  1628.     pType++;
  1629.     if ( !isdigit(*pType) )
  1630.         Result = False;
  1631.     /* Is syntax ok ? */
  1632.     if ( Result != True ) {
  1633.         fprintf(stderr,"\nSyntax error on array parameters %s%s%s", pMinIndex, pMaxIndex, pType );
  1634.         return(False);
  1635.     }
  1636.     MinIndex = atoi(pMinIndex);
  1637.     MaxIndex = atoi(pMaxIndex);
  1638.     Type = (unsigned short)atoi(pType);
  1639.     if (    SetupDefinedType(    Type,    pMap,    DerivedBits,    ExtraLevels    )    !=    True    )
  1640.         return( False );
  1641.     /* Now update the size based on the indicies */
  1642.     Size = (MaxIndex - MinIndex) + 1;
  1643.     pMap->ByteSize *= Size;
  1644.     pMap->Line = ci->CurrentSourceLine;
  1645.     /* add the dimension information */
  1646.     for ( i = 5; i >= 0; i-- ) {
  1647.         if ( pMap->Dimensions[i] != 0 ) {
  1648.             i++;
  1649.             pMap->Dimensions[i] = Size;
  1650.             break;
  1651.         }
  1652.     }
  1653.     return(True);
  1654. }
  1655.  
  1656. /****************************************************************************************/
  1657.  
  1658. int GetInternalType( char *pName, STABCOFFMAP *pMap ){
  1659.  
  1660.     int n, found, i;
  1661.  
  1662.     if ( !pName ) {
  1663.         return(False);
  1664.     }
  1665.  
  1666.     found = False;
  1667.     n = strlen(pName);
  1668.     /* Find out if it is a local type */
  1669.     for (i = 0; FundamentalTypes[i].pString != 0; i++) {
  1670.         if ( !strncmp(pName, FundamentalTypes[i].pString, n) ) {
  1671.             /* found an internal type */
  1672.             pMap->CoffType = FundamentalTypes[i].Type;
  1673.             pMap->ByteSize = FundamentalTypes[i].Size;
  1674.             found = True;
  1675.         }
  1676.     }
  1677.     return(found);
  1678. }
  1679.  
  1680. /****************************************************************************************/
  1681. int GetSubRangeType( unsigned short Type, STABCOFFMAP *pMap , char *pLow, char *pHigh ){
  1682.  
  1683.     int Result, i;
  1684.     long High, Low;
  1685.     unsigned long Test;
  1686.  
  1687.     Result = True;
  1688.     if ( (*pLow != ';') || (*pHigh != ';') || (Type <= 0) )
  1689.         Result = False;
  1690.  
  1691.     /* Is syntax ok ? */
  1692.     if ( Result != True ) {
  1693.         fprintf(stderr,"\nSyntax error on sub range parameters!" );
  1694.         return(False);
  1695.     }
  1696.     Low = atol(++pLow);
  1697.     High = atol(++pHigh);
  1698.  
  1699.     /* Special handling of type void */
  1700.     if ( (Low == 0) && (High == 0) ) {
  1701.         /* Declare type void */
  1702.         pMap->ByteSize =0;
  1703.         pMap->CoffType = T_VOID;
  1704.         pMap->Line = ci->CurrentSourceLine;
  1705.         return(True);
  1706.     }
  1707.  
  1708.     if ( (pMap->CoffType = GetCoffType( Type )) != 0 ) {
  1709.         pMap->ByteSize = GetCoffTypeSize( Type );
  1710.     } else {
  1711.         /* Try to base everything off integer */
  1712.         pMap->ByteSize = FundamentalTypes[T_INT].Size;
  1713.     }
  1714.  
  1715.     /* Now calculate the byte size */
  1716.     if ( High == 0 ) {
  1717.         pMap->ByteSize = (unsigned short)Low; /* floating point */
  1718.     } else {
  1719.         if ( Low == 0 ) {
  1720.             /* Unsigned */
  1721.             Test = (unsigned long)High;
  1722.         } else if ( Low < 0 ) {
  1723.             /* signed */
  1724.             Test = (unsigned long)High << 1;
  1725.         } else {
  1726.             if ( Low <= High )
  1727.                 Test = (unsigned long)High;
  1728.             else
  1729.                 Test = (unsigned long)Low;
  1730.         }
  1731.         if ( pMap->ByteSize == 0 ) {
  1732.             fprintf(stderr,"\nType Range Error 1, need previous type %d size!", pMap->CoffType );
  1733.             return(False);
  1734.         }
  1735.         for ( i = 0; i < sizeof(unsigned long); i++ ) {
  1736.             if ( !(Test & (0xff << (i * 8))) )
  1737.                 break;
  1738.         }
  1739.         pMap->ByteSize = i;
  1740.     }
  1741.     /* Now determine the best fit based on byte size, compare against IAR Compiler */
  1742.     if ( pMap->ByteSize == 1 ) {
  1743.         if ( Low < 0 )
  1744.             pMap->CoffType = T_CHAR;
  1745.         else
  1746.             pMap->CoffType = T_UCHAR;
  1747.     } else if ( pMap->ByteSize == 2 ) {
  1748.         if ( Low < 0 )
  1749.             pMap->CoffType = T_INT;
  1750.         else
  1751.             pMap->CoffType = T_UINT;
  1752.     } else if ( pMap->ByteSize == 4 ) {
  1753.         if ( Low == 0 )
  1754.             pMap->CoffType = T_FLOAT;
  1755.         if ( Low < 0 )
  1756.             pMap->CoffType = T_LONG;
  1757.         else
  1758.             pMap->CoffType = T_ULONG;
  1759.     } else {
  1760.         fprintf(stderr,"\nGetSubRangeType failure - byte size %d", pMap->ByteSize );
  1761.         return(False);
  1762.     }
  1763.     return(True);
  1764. }
  1765.  
  1766. /****************************************************************************************/
  1767. int CopyStabCoffMap( unsigned short StabType, STABCOFFMAP *pMap ){
  1768.  
  1769.     STABCOFFMAP *p;
  1770.  
  1771.     for ( p = FindFirstListObject( &ci->ListOfTypes ); p != 0; p = FindNextListObject( &ci->ListOfTypes) ) {
  1772.         if ( p->StabType == StabType ) {
  1773.             memcpy( pMap, p, sizeof(STABCOFFMAP) );
  1774.             return(True);
  1775.         }
  1776.     }
  1777.     return( False ); /* Nothing found */
  1778. }
  1779.  
  1780. /****************************************************************************************/
  1781. unsigned short GetCoffType( unsigned short StabType ){
  1782.  
  1783.     STABCOFFMAP *p;
  1784.  
  1785.     for ( p = FindFirstListObject( &ci->ListOfTypes ); p != 0; p = FindNextListObject( &ci->ListOfTypes) ) {
  1786.         if ( p->StabType == StabType )
  1787.             return( p->CoffType );
  1788.     }
  1789.     return( 0 ); /* Nothing found */
  1790. }
  1791.  
  1792. /****************************************************************************************/
  1793. unsigned short GetCoffTypeSize( unsigned short StabType ){
  1794.  
  1795.     STABCOFFMAP *p;
  1796.  
  1797.     for ( p = FindFirstListObject( &ci->ListOfTypes ); p != 0; p = FindNextListObject( &ci->ListOfTypes) ) {
  1798.         if ( p->StabType == StabType )
  1799.             return( p->ByteSize );
  1800.     }
  1801.     return( 0 ); /* Nothing found */
  1802. }
  1803.  
  1804.  
  1805. /****************************************************************************************/
  1806. int GetDigitLength( char *p ){
  1807.  
  1808.     int i;
  1809.  
  1810.     if ( p == 0 )
  1811.         return(0);
  1812.  
  1813.     for ( i = 0; (*p != 0) && ( *p >= '0' ) && ( *p <= '9' ); i++ );
  1814.  
  1815.     return( i );
  1816.  
  1817. }
  1818.  
  1819. /****************************************************************************************/
  1820. int GetStringDelimiters( char *pString, char **pTokens, int MaxTokens ){
  1821.  
  1822.     int i;
  1823.     char *p;
  1824.  
  1825.     p = pString;
  1826.  
  1827.     if ( !p )
  1828.         return( 0 );
  1829.  
  1830.     for ( i = 0; i < MaxTokens; i++ ) {
  1831.         while ( True ) {
  1832.             if ( (*p == ':') || (*p == ';') || (*p == '=') || (*p == ',') || (*p == '"') || (*p == 0 ) ) {
  1833.                 *(pTokens + i) = p; /* Remember this location */
  1834.                 p++;
  1835.                 if ( *p == 0 )
  1836.                     return( i );
  1837.                 break;
  1838.             }
  1839.             p++;
  1840.         }
  1841.     }
  1842.     return( i );
  1843. }
  1844.  
  1845. /****************************************************************************************/
  1846. int IsTypeArray( unsigned short CoffType ){
  1847.  
  1848.     int Result;
  1849.  
  1850.     Result = False;
  1851.  
  1852.     if ( (CoffType & (DT_ARY << 4 )) == (DT_ARY << 4 ) )
  1853.         Result = True;
  1854.     if ( (CoffType & (DT_ARY << 6 )) == (DT_ARY << 6 ) )
  1855.         Result = True;
  1856.     if ( (CoffType & (DT_ARY << 8 )) == (DT_ARY << 8 ) )
  1857.         Result = True;
  1858.     if ( (CoffType & (DT_ARY << 10 )) == (DT_ARY << 10 ) )
  1859.         Result = True;
  1860.     if ( (CoffType & (DT_ARY << 12 )) == (DT_ARY << 12 ) )
  1861.         Result = True;
  1862.     if ( (CoffType & (DT_ARY << 14 )) == (DT_ARY << 14 ) )
  1863.         Result = True;
  1864.  
  1865.     return(Result);
  1866. }
  1867.  
  1868. /****************************************************************************************/
  1869. void AddArrayAuxInfo( union auxent *pAux, unsigned short SymbolIndex, STABCOFFMAP *pMap ){
  1870.  
  1871.     int i;
  1872.  
  1873.     pAux->x_sym.x_tagndx = SymbolIndex; /* point to the .bf entry index */
  1874.     pAux->x_sym.x_misc.x_lnsz.x_lnno =  pMap->Line;
  1875.     pAux->x_sym.x_misc.x_lnsz.x_size = pMap->ByteSize;
  1876.     for ( i = 0; i < 4; i++ )
  1877.         pAux->x_sym.x_fcnary.x_ary.x_dimen[i] = pMap->Dimensions[i];
  1878. }
  1879.  
  1880. /****************************************************************************************/
  1881. int AddNameToEntry( char *pName, struct syment *pEntry ) {
  1882.  
  1883.     int n;
  1884.     char *p;
  1885.  
  1886.     n = strlen( pName );    /* see if it's 8 bytes or less */
  1887.     if ( n <= 8 ) {
  1888.         strncpy( pEntry->n_name, pName, 8 );
  1889.     } else {
  1890.         /* point to current offset in string table */
  1891.         pEntry->n_offset = ci->ListOfStrings.TotalBytes;        
  1892.         /* Allocate string table entry */
  1893.         if ( (p = (char *)AllocateListObject( &ci->ListOfStrings, n + 1 )) == 0 ) {
  1894.             return(0);
  1895.         }
  1896.         strcpy( p, pName );
  1897.     }
  1898.     return(n); /* return size of string */
  1899. }
  1900.  
  1901. /****************************************************************************************/
  1902.  
  1903. char *SkipPastDigits( char *p ){
  1904.  
  1905.     if ( !p )
  1906.         return(p);
  1907. /*      if ( *p == 0 );  */  /* JEG 5-01-03 */
  1908.         if ( *p == 0 )
  1909.     return(p);   /* This line s/b indented JEG */
  1910.     for ( p--; (*p >= '0') && (*p <= '9') && (*p != 0); p-- );
  1911.     return(p);
  1912. }
  1913.  
  1914. /****************************************************************************************/
  1915.  
  1916. /****************************************************************************************/
  1917. /****************************************************************************************/
  1918. /* List management routines */
  1919. /****************************************************************************************/
  1920. /****************************************************************************************/
  1921.  
  1922. /****************************************************************************************/
  1923.  
  1924. /****************************************************************************************/
  1925. void InitializeList( LISTNODEHEAD *pHead ){
  1926.  
  1927.     pHead->Node.Next = &pHead->Node;
  1928.     pHead->Node.Last = &pHead->Node;
  1929.     pHead->TotalBytes = 0;
  1930.     pHead->TotalItems = 0;
  1931.     pHead->current = &pHead->Node;
  1932.     return;
  1933. }
  1934.  
  1935. /****************************************************************************************/
  1936.  
  1937. void *AllocateTwoListObjects( LISTNODEHEAD *pHead, int size ){
  1938.  
  1939.     void *p;
  1940.  
  1941.     if ( (p = AllocateListObject( pHead, size ) ) )
  1942.         pHead->TotalItems++;   /* already incremented once in addtolist */
  1943.     return( p );
  1944. }
  1945.  
  1946. /****************************************************************************************/
  1947. void *AllocateListObject( LISTNODEHEAD *pHead, int size ){
  1948.  
  1949.     void *pObject;
  1950.  
  1951.     LISTNODE *pNode;
  1952.  
  1953.     if ( (pObject = calloc( 1, size )) != 0 ) {
  1954.         if ( !(pNode = AddListObject( pHead, pObject, size )) ) {
  1955.             free( pObject );
  1956.             pObject = 0;
  1957.         }
  1958.     }
  1959.     return( pObject );
  1960. }
  1961.  
  1962. /****************************************************************************************/
  1963. LISTNODE  *AddListObject(LISTNODEHEAD *pHead, void *pObject, int size ){
  1964.  
  1965.     LISTNODE *pNode;
  1966.  
  1967.     if ( (pNode = calloc( 1, sizeof(LISTNODE) )) != 0 ) {
  1968.         pNode->pObject = pObject;
  1969.         pNode->Size = size;
  1970.         pNode->FileNumber = ci->CurrentFileNumber;
  1971.         AddNodeToList( pHead, pNode );
  1972.     }
  1973.     return( pNode );
  1974. }
  1975.  
  1976. /****************************************************************************************/
  1977. LISTNODE *AllocateListNode( void *pObject, int size ){
  1978.  
  1979.     LISTNODE *pNew;
  1980.  
  1981.     if ( (pNew = calloc( 1, sizeof( LISTNODE ) ) ) != 0 ) {
  1982.         /* Then we initialize the node */
  1983.         pNew->pObject = pObject;
  1984.         pNew->Size = size;
  1985.         pNew->FileNumber = ci->CurrentFileNumber;
  1986.     }
  1987.     return(pNew);
  1988. }
  1989.  
  1990. /****************************************************************************************/
  1991. void AddNodeToList( LISTNODEHEAD *pHead, LISTNODE *pNode ){
  1992.  
  1993.     LISTNODE *p;
  1994.  
  1995.     p = &pHead->Node;
  1996.  
  1997.     pNode->Next = p->Last->Next;
  1998.     p->Last->Next = pNode;
  1999.     pNode->Last = p->Last;
  2000.     p->Last = pNode;
  2001.  
  2002.     /* and update current size of data contained in the list */
  2003.     pHead->TotalBytes += pNode->Size;
  2004.     pHead->TotalItems++;
  2005. }
  2006.  
  2007. /****************************************************************************************/
  2008. void RemoveNodeFromList( LISTNODEHEAD *pHead, LISTNODE *pNode ){
  2009.  
  2010.     pNode->Last->Next = pNode->Next;
  2011.     pNode->Next->Last = pNode->Last;
  2012.  
  2013.     pHead->TotalBytes -= pNode->Size;
  2014.     pHead->TotalItems--;
  2015. }
  2016.  
  2017.  
  2018. /****************************************************************************************/
  2019. void *FindFirstListObject( LISTNODEHEAD *pHead ){
  2020.  
  2021.     if ( pHead->Node.Next == &pHead->Node )
  2022.         return(0);  /* Nothing in list */
  2023.  
  2024.     pHead->current = pHead->Node.Next;
  2025.     return( pHead->current->pObject );
  2026. }
  2027. /****************************************************************************************/
  2028. void *FindNextListObject( LISTNODEHEAD *pHead ){
  2029.  
  2030.     if ( pHead->current->Next == &pHead->Node )
  2031.         return( 0 );
  2032.  
  2033.     pHead->current = pHead->current->Next;
  2034.  
  2035.     return( pHead->current->pObject );
  2036. }
  2037. /****************************************************************************************/
  2038.  
  2039. LISTNODE *GetCurrentNode( LISTNODEHEAD *pHead ){
  2040.  
  2041.     return( pHead->current );
  2042. }
  2043.  
  2044. /****************************************************************************************/
  2045. void *GetCurrentListObject( LISTNODEHEAD *pHead ){
  2046.  
  2047.     return( pHead->current->pObject );
  2048. }
  2049.  
  2050.  
  2051. /****************************************************************************************/
  2052. void *FindLastListObject( LISTNODEHEAD *pHead ){
  2053.  
  2054.     if ( pHead->Node.Last == &pHead->Node )
  2055.         return(0);  /* Nothing in list */
  2056.  
  2057.     pHead->current = pHead->Node.Last;
  2058.     return( pHead->current->pObject );
  2059. }
  2060. /****************************************************************************************/
  2061. void *FindNextLastListObject( LISTNODEHEAD *pHead ){
  2062.  
  2063.     if ( pHead->current->Last == &pHead->Node )
  2064.         return( 0 );
  2065.  
  2066.     pHead->current = pHead->current->Last;
  2067.  
  2068.     return( pHead->current->pObject );
  2069. }
  2070.  
  2071. /****************************************************************************************/
  2072.  
  2073. void FreeList( LISTNODEHEAD *pHead ){
  2074.  
  2075.     LISTNODE *pNode;
  2076.  
  2077.     for ( pNode = pHead->Node.Last; pNode->Next != &pHead->Node; pNode = pHead->Node.Last ) {
  2078.  
  2079.         RemoveNodeFromList( pHead, pNode );
  2080.         free( pNode->pObject );
  2081.         free( pNode );
  2082.     }
  2083.     pHead->TotalBytes = 0;
  2084.     pHead->TotalItems = 0;
  2085.     pHead->current = &pHead->Node;
  2086. }
  2087. /****************************************************************************************/
  2088.  
  2089.  
  2090.