home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 23 / IOPROG_23.ISO / SOFT / ASM / BCDASM.ZIP / BCDASM / AWK / ASH.AWK next >
Encoding:
AWK Script  |  1997-06-03  |  6.8 KB  |  211 lines

  1. #
  2. # AWK script to create a header file from an assembly language
  3. # source (Intel x86), listing labels and variables by segment.
  4. # Morten Elling, April 1995 + May 1997.
  5. #
  6. # Usage
  7. #   awk -f ash.awk [NEARS=1] [TYPES=0] [IDEAL=1] file.asm [>output.fil]
  8. #   NEARS=1 : INclude non-local near code labels (default = 0)
  9. #   TYPES=0 : EXclude struc, record, enum types  (default = 1)
  10. #   IDEAL=1 : Assume Ideal syntax  (auto-detect = default = 0)
  11. #
  12. # Notes
  13. #   Despite several limitations, this script can be a time saver
  14. #   by providing a list of labels, procedures, and variables per
  15. #   segment in the form of global (externdef) declarations.
  16. #
  17. #   Doesn't understand conditional blocks, includes, or line
  18. #   continuation. Ignores comments, macros, and repeat blocks.
  19. #   Understands generic or simplified segmentation, or mixed,
  20. #   but does not properly handle:
  21. #     - [generic] nested segments
  22. #     - [simplified] named far segments (e.g. .code fharcode)
  23. #     - segment ordering (due to AWK's associative arrays)
  24. #   Understands MASM and Ideal mode syntax, strucs and records.
  25. #   Treats 'sym: db 1' as a byte label if NEARS = 0.
  26.  
  27.  
  28. ##### Make set array from string
  29. function zsplit(str, arr     ,i, j ,temp) {    # i,j,temp = locals
  30.     j = split(str, temp);
  31.     for (i = 1; i <= j; i++)  arr[temp[i]] = 1;
  32. }
  33.  
  34.  
  35. BEGIN    { # Initialize; AWK zero-inits all variables.
  36.     TYPES = 1;        # Overridden by cmd. line if appropriate
  37.     NOSEG = "unknown";
  38.  
  39.     print "Just a minute, Admiral" >"CON"
  40.     printf ("\n; %s\n", tolower(ARGV[ARGC-1]) );    # Filespec
  41.  
  42.  
  43.     segdir     = ".code .data .const .data? .stack .fardata .fardata?" \
  44.            " codeseg dataseg const udataseg stack fardata ufardata";
  45.     labeldir = "proc label ";
  46.     typdir     = "struc record union enum typedef ";
  47.     data2dir = "db dw dd df dp dq dt byte word dword" \
  48.            " sbyte sword sdword real4 real8 real10";
  49.     idealdir = "proc label ideal ";        # 1st token on a line
  50.     distspec = "near far near16 near32 far16 far32";
  51.  
  52.     # Make sets of directive names
  53.     zsplit(segdir, cannedsegset);
  54.     zsplit(labeldir, labelset);
  55.     zsplit(typdir  , typeset);
  56.     zsplit(data2dir, data2set);
  57.     zsplit(idealdir, idealset);
  58.     zsplit(distspec, distset);
  59.  
  60.  
  61.     curseg = NOSEG;
  62.     symcount[curseg] = 1;
  63. }
  64.  
  65. { ##### Main loop begins #######################
  66.  
  67.   if ($1 ~ /^;/)   next;            # Skip comment lines
  68.   if ($1 ~ /^%$/)  $1 = "";            # Strip immed. macro
  69.  
  70.   tok1 = tolower($1);                # Lowercase field no. 1
  71.   tok2 = tolower($2);                # Lowercase field no. 2
  72.  
  73.  
  74.   ##### Ideal/MASM mode change
  75.   if (!IDEAL)
  76.     IDEAL = (tok1 in idealset);        # Auto-detect
  77.   if (IDEAL)
  78.     { tokk = tok1;  toki = $2; }        # Keyword before identifier
  79.   else
  80.     { tokk = tok2;  toki = $1; }        # Identifier before keyword
  81.  
  82.  
  83.   ##### Ignore comment
  84.   if (!IDEAL && tok1 == "comment") {
  85.     tmp = substr($2,1,1);
  86.     while (getline == 1)            # Read until
  87.       if (index($0, tmp)) break;        #   end of comment
  88.     next;                    # Skip to next line
  89.   }
  90.  
  91.   ##### Ignore macro/rept/irp
  92.   if (tokk == "macro" || tok1 == "rept" || tok1 == "irp") {
  93.     while (getline == 1)            # Read until "endm"
  94.       if ($1 ~ /^(E|e)(N|n)(D|d)(M|m)$/) break;
  95.     next;                    # Skip to next line
  96.   }
  97.  
  98.  
  99.   ##### Segment directive
  100.   if (tokk == "segment" || tok1 in cannedsegset) {
  101.     if (tokk == "segment") curseg = toki
  102.     else curseg = toupper(tok1);        # Set current segment
  103.     if (symcount[curseg] == 0)
  104.       symcount[curseg]++;            # Need this for void segs
  105.     next;                    # Skip to next line
  106.   }
  107.  
  108.  
  109.   ##### Proc/label declaration
  110.   if (tokk in labelset) {
  111.     i = ++symcount[curseg];         # Step symbol counter
  112.     syms[curseg,i] = toki;            # Add symbol name to array
  113.     gtyp = (($3 != "") ? $3 : "unknown");    # Get distance/type, if any
  114.     if ((tokk == "proc") &&
  115.        !(tolower(gtyp) in distset))        # Default to model-
  116.           gtyp = "proc";                    #  dependent size ("proc")
  117.     syms[curseg,i,typ] = gtyp;        # Set type
  118.     next;                    # Skip to next line
  119.   }
  120.  
  121.  
  122.   if (NEARS) {
  123.   ##### Non-local near code label
  124.   if ($1 ~ /^[A-Za-z_$?][A-Za-z_$?0-9@]*:$/ ) {
  125.     i = ++symcount[curseg];         # Step symbol counter
  126.     syms[curseg,i] = \
  127.         substr($1, 1, index($1,":")-1);    # Add symbol name to array
  128.     syms[curseg,i,typ] = "Near";        # Distance is near
  129.     next;                    # Skip to next line
  130.   }
  131.   } # endif (NEARS)
  132.  
  133.  
  134.   ##### Data allocation (Ideal and MASM syntax identical)
  135.   #    (Avoid false match on "mov dword ptr memvar, eax")
  136.   if ((tok2 in data2set) && ($3 !~ /^(P|p)(T|t)(R|r)$/)) {
  137.     i = ++symcount[curseg];         # Step symbol counter
  138.     syms[curseg,i] = $1;            # Add symbol name to array
  139.     if    (tok2 == "db")    gtyp = "byte"
  140.     else if (tok2 == "dw")    gtyp = "word"
  141.     else if (tok2 == "dd")    gtyp = "dword"
  142.     else if (tok2 == "df")    gtyp = "fword"
  143.     else if (tok2 == "dp")    gtyp = "pword"
  144.     else if (tok2 == "dq")    gtyp = "qword"
  145.     else if (tok2 == "dt")    gtyp = "tbyte"
  146.     else if (tok2 == "byte")   gtyp = "BYTE"
  147.     else if (tok2 == "word")   gtyp = "WORD"
  148.     else if (tok2 == "dword")  gtyp = "DWORD"
  149.     else if (tok2 == "sbyte")  gtyp = "SBYTE"
  150.     else if (tok2 == "sword")  gtyp = "SWORD"
  151.     else if (tok2 == "sdword") gtyp = "SDWORD"
  152.     else if (tok2 == "real4")  gtyp = "REAL4"
  153.     else if (tok2 == "real8")  gtyp = "REAL8"
  154.     else if (tok2 == "real10") gtyp = "REAL10"
  155.     else gtyp = "unknown";
  156.     syms[curseg,i,typ] = gtyp;        # Set data type
  157.     next;                    # Skip to next line
  158.   }
  159.  
  160.  
  161.   if (TYPES) {
  162.   ##### Struc/record/enum definition
  163.   if (tokk in typeset) {
  164.     typs[++typecount] = tolower(toki);    # Add type name to array
  165.     if (tokk=="struc" || tokk=="union") {
  166.        while (getline == 1)         # Read until "ends"
  167.           if ($2 ~ /^(E|e)(N|n)(D|d)(S|s)$/ ||
  168.           $1 ~ /^(E|e)(N|n)(D|d)(S|s)$/) break;
  169.     }
  170.     next;                    # Skip to next line
  171.   }
  172.  
  173.   ##### Struc/record/enum allocation
  174.   j = 1;
  175.   while (j <= typecount)            # See if token is
  176.     if (tok2 == typs[j++]) {            #  a struc, record etc.
  177.     i = ++symcount[curseg];         # Step counter
  178.     syms[curseg,i] = $1;            # Add symbol name to array
  179.     syms[curseg,i,typ] = $2;        # Set data type
  180.     }
  181.   } # endif (TYPES)
  182.  
  183.  
  184. } ##### Main loop ends #########################
  185. END {
  186.     ##### For each segment, print results on the form:
  187.     #    segname [SEGMENT]
  188.     #    global    sym_name    :sym_type
  189.     #    [segname ENDS]
  190.  
  191.     if (IDEAL) printf("; ideal\n")
  192.      else printf("; global equ externdef\n");
  193.     for (curseg in symcount) {
  194.        if (curseg == NOSEG && symcount[curseg] == 1) continue;
  195.        pad = (length(curseg) < 8 ? "\t" : " ");
  196.        if (tolower(curseg) in cannedsegset) {
  197.           printf ("\n\t%s\n", curseg) }
  198.         else {
  199.           if (IDEAL) printf ("\n\tSEGMENT\t%s\n", curseg)
  200.           else       printf ("\n\t%s%sSEGMENT\n", curseg, pad);
  201.        }
  202.        for (i = 2; i <= symcount[curseg]; i++)    # 1st is void
  203.           printf "\tglobal\t%-24s%s\n",
  204.              syms[curseg,i], ":" syms[curseg,i,typ];
  205.        if (!(tolower(curseg) in cannedsegset)) {
  206.           if (IDEAL) { printf ("\tENDS\t%s\n", curseg) }
  207.           else       { printf ("\t%s%sENDS\n", curseg, pad) }
  208.        }
  209.     } # endfor
  210. } # eof
  211.