home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 529a.lha / OMDS / omds.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-03  |  11.9 KB  |  519 lines

  1. /*
  2.  * OMDS - The 99% solution for converting OMD output into assembleable sources.
  3.  * ©1991, Mike Schwartz, all rights reserved.
  4.  * Placed in the public domain, with the limitation that NO printed version
  5.  * may be sold for ANY price.
  6.  *
  7.  * Description:
  8.  *    SAS C 5.10a comes with a program called OMD, which is capable of
  9.  *    disassembling object files created by the SAS C compiler.  The
  10.  *    only drawback is that OMD prepares a "worthless" pretty listing
  11.  *    of the disassembly which is not suitable for use with an assembler.
  12.  *    The process of converting the output of OMD to source code by hand
  13.  *    is tedious and prone to human error, especially if a large number
  14.  *    of files need to be converted.  This program will assist greatly
  15.  *    in the conversion process.
  16.  *
  17.  * Use:
  18.  *    First, you must compile your sources withe the C compiler using
  19.  *    at least -d1 (debugging info) option.  Then you need to run OMD
  20.  *    on the .o file created by the compiler to create a listing file
  21.  *    (redirect stdout).  Then you run OMDS on the listing file and
  22.  *    it will create an assemblable source file as output.
  23.  *
  24.  * Invocation:
  25.  *    OMD listingFile outputFile
  26.  *    Where:
  27.  *        listingFile is the output file from OMD
  28.  *        outputFile is the file that OMDS will write
  29.  *
  30.  * Limitations:
  31.  *    The SAS 'C' compiler sometimes creates code for twitch statements
  32.  *    that cause OMD to not disassemble correctly.  OMDS will complain
  33.  *    about "syntax" of the listing file in this case.  In order to get
  34.  *    an assemblable source file, the switch statement must be recoded
  35.  *    as if...else if .... else if ... 
  36.  *
  37.  *    Also, when OMD generates data for the initialized and uninitialized
  38.  *    data for the .o file, it generates a "hex dump" format in the listing
  39.  *    file.  OMD has problems with this hex dump format when it looks like
  40.  *    this:
  41.  *        oooo xx xx xx xx gg .....
  42.  *    Where
  43.  *        oooo is a 4 digit hex offset
  44.  *        xx is a two digit hex number/value
  45.  *        gg (followed by a space) is the first three characters of
  46.  *            the ascii part of the hex dump
  47.  *        .... is the rest of the ascii part of the hex dump
  48.  *    The workaround for this problem is to edit the listing file
  49.  *    and delete the ascii portion of the hex dump altogether.
  50.  *
  51.  * Disclaimer:
  52.  *    The author makes no guarantees or warantees as to the correctness
  53.  *    or buglessness of the program.  Sorry about the lack of comments,
  54.  *    but 'C' is a write-once language anyway :)  It should compile with
  55.  *    no problems under Manx 'C', but who'd want to anyway :)
  56.  */
  57. #include    "exec/types.h"
  58. #include    "fcntl.h"
  59. #include    "stdio.h"
  60.  
  61. typedef struct SYMBOL {
  62.     char        name[256];
  63.     ULONG        section;
  64.     ULONG        offset;
  65. } SYMBOL;
  66.  
  67. #define    MAXSYMS        1024
  68. SYMBOL    *symArray;
  69. int    nextSym = 0;
  70.  
  71. FILE    *infp, *outfp;
  72. char    inbuf[256], *inp;
  73. char    token[256], *tokp;
  74.  
  75. int    pass;
  76. int    sect2Size = 0;
  77.  
  78. BOOL    getin() {
  79.     if (!fgets(inbuf, 256, infp)) { inp = 0; return 0; }
  80.     inbuf[strlen(inbuf)-1] = '\0';
  81.     inp = &inbuf[0];
  82.     return !0;
  83. }
  84.  
  85. BOOL    gettok() {
  86.     char    *outp = &token[0];
  87.     short    parenCnt = 0;
  88.  
  89.     while (*inp && (*inp == ' ' || *inp == '\t' || *inp == ',')) inp++;
  90.     while (*inp && (*inp != ' ' && *inp != '\t')) {
  91.         if (*inp == '(') parenCnt++;
  92.         else if (*inp == ')') parenCnt--;
  93.         else if (!parenCnt && *inp == ',') break;
  94.         *outp++ = *inp++;
  95.     }
  96.     *outp = '\0';
  97.     tokp = &token[0];
  98.     return strlen(token) ? !0 : 0;
  99. }
  100.  
  101. ULONG    hex(c)
  102. char    c;
  103. {
  104.     if (c >= 'A' && c <= 'F') c = c-'A'+10;
  105.     else if (c >= 'a' && c <= 'f') c = c-'a'+10;
  106.     else c = c-'0';
  107.     return (ULONG)c;
  108. }
  109.  
  110. BOOL    ishex(c)
  111. {
  112.     if (c >= '0' && c <= '9') return !0;
  113.     if (c >= 'A' && c <= 'F') return !0;
  114.     if (c >= 'a' && c <= 'f') return !0;
  115.     return 0;
  116. }
  117.  
  118. ULONG    htoi(s)
  119. char    *s;
  120. {
  121.     ULONG    v = 0;
  122.  
  123.     while (ishex(*s)) {
  124.         v <<= 4;
  125.         v += hex(*s++);
  126.     }
  127.     return v;
  128. }
  129.  
  130. char    *branches[] = {
  131.     "BCC", "BCS", "BEQ", "BGE", "BGT", "BHI", "BLE", "BLS", "BLT", "BMI", "BNE", "BPL", "BVC", "BVS", "BRA", 
  132.     "BSR",
  133.     0,
  134. };
  135.  
  136. BOOL    isbranch(b)
  137. char    *b;
  138. {
  139.     short    i;
  140.  
  141.     for (i=0; branches[i]; i++)
  142.         if (!strncmp(b, branches[i], 3)) return !0;
  143.     return 0;
  144. }
  145.  
  146. char    *registers[] = {
  147.     "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "SP",
  148.     0,
  149. };
  150.  
  151. BOOL    isregister(b)
  152. char    *b;
  153. {
  154.     short    i;
  155.  
  156.     for (i=0; registers[i]; i++)
  157.         if (!strncmp(b, registers[i], 2)) return !0;
  158.     return 0;
  159. }
  160.  
  161. void    add_symbol(lab, sect, off)
  162. char    *lab;
  163. ULONG    sect;
  164. ULONG    off;
  165. {
  166.     SYMBOL    *ps = &symArray[nextSym];
  167.     short    i;
  168.  
  169.     for (i=0; i<nextSym; i++) {
  170.         if (sect != symArray[i].section || off != symArray[i].offset || strcmp(lab, symArray[i].name))
  171.             continue;
  172.         if (symArray[i].name[0] != '_') strcpy(symArray[i].name, lab);
  173.         return;
  174.     }
  175.     if (nextSym >= MAXSYMS) {
  176.         printf("too many symbols\n");
  177.         exit(999);
  178.     }
  179.     strcpy(ps->name, lab);
  180.     ps->section = sect;
  181.     ps->offset = off;
  182.     nextSym++;
  183. }
  184.  
  185. SYMBOL    *lookup_value(v, sect)
  186. ULONG    v, sect;
  187. {
  188.     short    i;
  189.  
  190.     for (i=0; i<nextSym; i++)
  191.         if (symArray[i].offset == v && symArray[i].section == sect) return &symArray[i];
  192.     return 0;
  193. }
  194.  
  195. void    ParseExternalDefinitions() {
  196.     char    label[256];
  197.     ULONG    offset, section;
  198.     int    i;
  199.     SYMBOL    *ps;
  200.  
  201.     while (getin()) {
  202.         if (strcmp(inbuf, "EXTERNAL DEFINITIONS")) continue;
  203.         if (!getin()) break;
  204.         while (getin() && strlen(inbuf)) {
  205.             while (gettok()) {
  206.                 if (!token[0]) break;
  207.                 strcpy(label, token);
  208.                 if (!gettok()) {
  209.                     printf("error in EXTERNAL DEFINITIONS\n");
  210.                     exit(999);
  211.                 }
  212.                 offset = 0;
  213.                 while (*tokp != '-') offset = (offset<<4)+hex(*tokp++);
  214.                 tokp++;
  215.                 section = hex(*tokp++);
  216.                 section = (section*16)+hex(*tokp++);
  217.                 if (pass == 1) add_symbol(label, section, offset);
  218.             }
  219.         }
  220.         if (pass == 2) return;
  221.         for (i=0; i<nextSym; i++) {
  222.             ps = &symArray[i];
  223.             fprintf(outfp, "\t\tXDEF\t%s\t\t; sect: %d  offset: %04x\n", ps->name, ps->section, ps->offset);
  224.         }
  225.         fprintf(outfp, "\n");
  226.         return;
  227.     }
  228.     printf("No EXTERNAL DEFINITIONS found, OMD file must be incorrect!\n");
  229.     exit(999);
  230. }
  231.  
  232. void    CheckOperand(op)
  233. char    *op;
  234. {
  235.     char    work[256];
  236.     SYMBOL    *ps;
  237.  
  238.     if (!strncmp(op, "01.", 3)) {
  239.         strcpy(work, "D");
  240.         strcat(work, &op[3]);
  241.         if (pass == 1) {
  242.             if (!lookup_value(htoi(&op[3], 1))) add_symbol(work, 1, htoi(&op[3]));
  243.         }
  244.         else {
  245.             if (ps = lookup_value(htoi(&op[3], 1)))
  246.                 strcpy(op, ps->name);
  247.             else
  248.                 strcpy(op, work);
  249.         }
  250.     }
  251.     else if (!strncmp(op, "02.", 3)) {
  252.         strcpy(work, "B");
  253.         strcat(work, &op[3]);
  254.         if (pass == 1) {
  255.             if (!lookup_value(htoi(&op[3], 2))) add_symbol(work, 2, htoi(&op[3]));
  256.         }
  257.         else {
  258.             if (ps = lookup_value(htoi(&op[3], 2)))
  259.                 strcpy(op, ps->name);
  260.             else
  261.                 strcpy(op, work);
  262.         }
  263.     }
  264.     else if (!isregister(op) && ishex(op[0])) {
  265.         strcpy(work, "$");
  266.         strcat(work, op);
  267.         strcpy(op, work);
  268.     }
  269. }
  270.  
  271. void    ParseSection00() {
  272.     ULONG    offset;
  273.     int    i;
  274.     char    opcode[256], op1[256], op2[256];
  275.  
  276.     if (!getin()) {
  277.         printf("Premature end of file in Section 00\n");
  278.         exit(999);
  279.     }
  280.     if (strncmp(inbuf, "SECTION 00", 10)) {
  281.         printf("Invalid text in Section00:\n%s\n", inbuf);
  282.         exit(999);
  283.     }
  284.     while (getin()) {
  285.         if (inbuf[0] == ';') { if (pass == 2) fprintf(outfp, "%s\n", inbuf); continue; }
  286.         if (!gettok()) break;
  287.         if (token[0] != '|' || !gettok()) {
  288.             printf("Invalid text in Section00:\n%s\n", inbuf);
  289.             exit(999);
  290.         }
  291.         offset = 0;
  292.         while (*tokp) offset = (offset*16)+hex(*tokp++);
  293.         tokp++;
  294.         for (i=0; i<nextSym; i++) {
  295.             if (symArray[i].section == 0 && offset == symArray[i].offset) {
  296.                 if (pass == 2) {
  297.                     if (strlen(symArray[i].name) < 8)
  298.                         fprintf(outfp, "%s\t\t", symArray[i].name);
  299.                     else
  300.                         fprintf(outfp, "%s\t", symArray[i].name);
  301.                 }
  302.                 break;
  303.             }
  304.         }
  305.         if (pass == 2 && i >= nextSym) fprintf(outfp, "\t\t");
  306.         inp = &inbuf[45];
  307.         while (*inp != ' ') inp++;
  308.         if (!gettok()) {
  309.             printf("Invalid text in Section 00:\n%s\n", inbuf);
  310.             exit(999);
  311.         }
  312.         strcpy(opcode, token);
  313.         op1[0] = '\0';
  314.         if (gettok()) strcpy(op1, token);
  315.         op2[0] = '\0';
  316.         if (gettok()) strcpy(op2, token);
  317.  
  318.         if (isbranch(opcode)) {
  319.             SYMBOL    *ps = lookup_value(htoi(op1));
  320.  
  321.             if (!ps) {
  322.                 strcpy(op2, "L");
  323.                 strcat(op2, op1);
  324.             }
  325.             else {
  326.                 strcpy(op2, ps->name);
  327.             }
  328.             if (pass == 1)
  329.                 add_symbol(op2, 0, htoi(op1));
  330.             else
  331.                 fprintf(outfp, "%s\t%s\n", opcode, op2);
  332.             continue;
  333.         }
  334.         if (op1[0] == '#')
  335.             CheckOperand(&op1[1]);
  336.         else
  337.             CheckOperand(op1);
  338.         if (op2[0] == '#')
  339.             CheckOperand(&op2[1]);
  340.         else
  341.             CheckOperand(op2);
  342.  
  343.         if (pass == 1) continue;
  344.         if (!op2[0])
  345.             fprintf(outfp, "%s\t%s\n", opcode, op1);
  346.         else
  347.             fprintf(outfp, "%s\t%s,%s\n", opcode, op1, op2);
  348.     }
  349.     fprintf(outfp, "\n");
  350. }
  351.  
  352. static    ULONG    dsoffset = 0;
  353.  
  354. void    DefineStorageByte() {
  355.     SYMBOL    *ps = lookup_value(dsoffset, 2);
  356.  
  357.     if (pass == 1) return;
  358.     if (!ps) {
  359.         fprintf(outfp, "\t\tDS.B\t1\t\t; offset = $%04x\n", dsoffset);
  360.     }
  361.     else if (strlen(ps->name)< 8) {
  362.         fprintf(outfp, "%s\t\tDS.B\t1\t\t; offset = $%04x\n", ps->name, dsoffset);
  363.     }
  364.     else {
  365.         fprintf(outfp, "%s\tDS.B\t1\t\t; offset = $%04x\n", ps->name, dsoffset);
  366.     }
  367.     dsoffset++;
  368. }
  369.  
  370. static    ULONG    dcoffset = 0;
  371.  
  372. void    DefineConstantByte(c) 
  373. UBYTE    c;
  374. {
  375.     SYMBOL    *ps = lookup_value(dcoffset, 1);
  376.  
  377.     if (pass == 1) return;
  378.     if (!ps) {
  379.         fprintf(outfp, "\t\tDC.B\t$%02x\t\t; offset = $%04x\n", c, dcoffset);
  380.     }
  381.     else if (strlen(ps->name)< 8) {
  382.         fprintf(outfp, "%s\t\tDC.B\t$%02x\t\t; offset = $%04x\n", ps->name, c, dcoffset);
  383.     }
  384.     else {
  385.         fprintf(outfp, "%s\tDC.B\t$%02x\t\t; offset = $%04x\n", ps->name, c, dcoffset);
  386.     }
  387.     dcoffset++;
  388. }
  389.  
  390. void    DefineConstantLongName(name)
  391. char    *name;
  392. {
  393.     SYMBOL    *ps = lookup_value(dcoffset, 1);
  394.  
  395.     if (pass == 1) return;
  396.     if (!ps) {
  397.         fprintf(outfp, "\t\tDC.L\t%s\t\t; offset = $%04x\n", name, dcoffset);
  398.     }
  399.     else if (strlen(ps->name)< 8) {
  400.         fprintf(outfp, "%s\t\tDC.L\t%s\t\t; offset = $%04x\n", ps->name, name, dcoffset);
  401.     }
  402.     else {
  403.         fprintf(outfp, "%s\tDC.L\t%s\t\t; offset = $%04x\n", ps->name, name, dcoffset);
  404.     }
  405.     dcoffset += 4;
  406. }
  407.  
  408. void    gettok01() {
  409.     if (!gettok()) {
  410.         printf("Syntax error ParseSection01:\n%s\n", inbuf);
  411.         exit(999);
  412.     }
  413. }
  414.  
  415. void    ParseSection01() {
  416.     ULONG    start, end;
  417.  
  418.     if (!getin()) return;
  419.     if (!strncmp(inp, "SECTION 02", 10)) {
  420.         if (pass == 2)     fprintf(outfp, ";***** Uninitialized data\n\n");
  421.         end = htoi(&inp[15]);
  422.         for (start = 0; start<=end; start++) DefineStorageByte();
  423.         return;
  424.     }
  425.     if (strncmp(inp, "SECTION 01", 10)) {
  426.         printf("Syntax error ParseSection01: \n%s\n", inp);
  427.         exit(999);
  428.     }
  429.     if (pass == 2)     fprintf(outfp, ";***** Initialized data\n\n");
  430.  
  431.     while (getin() && strlen(inp)) {
  432.         if (!strncmp(inp, "OFFSETS", 7)) {
  433.             inp = &inp[7];
  434.             gettok01();
  435.             start = htoi(token);
  436.             gettok01();        /* THROUGH */
  437.             gettok01();
  438.             end = htoi(token);
  439.             while (start <= end) { 
  440.                 DefineConstantByte(0); start++; 
  441.             }
  442.         }
  443.         else {
  444.             gettok01();        /* hex offset */
  445.             gettok01();
  446.             if (strlen(token) != 2) {    /* dc.l required */
  447.                 if (!gettok()) {
  448.                     printf("Syntax error parsesection01:\n%s\n", inbuf);
  449.                     exit(999);
  450.                 }
  451.                 CheckOperand(token);
  452.                 DefineConstantLongName(token);
  453.                 continue;
  454.             }
  455.             for (start=0; start<16; start++) {
  456.                 DefineConstantByte(htoi(token));
  457.                 if (!gettok()) break;
  458.                 if (strlen(token) != 2) break;
  459.             }
  460.         }
  461.     }
  462. }
  463. void    ParseSection02() {
  464.     ULONG    start, end;
  465.  
  466.     if (!getin()) return;
  467.     if (!strncmp(inp, "SECTION 02", 10)) {
  468.         if (pass == 2)     fprintf(outfp, "\n;***** Uninitialized data\n\n");
  469.         end = htoi(&inp[15]);
  470.         for (start = 0; start<=end; start++) DefineStorageByte();
  471.     }
  472. }
  473.  
  474. main(ac, av)
  475. int    ac;
  476. char    *av[];
  477. {
  478.     if (ac != 3) {
  479.         printf("Usage: omds omdfile outfile\n");
  480.         printf("\tconverts OMD output into assembly source\n");
  481.         exit(999);
  482.     }
  483.     symArray = (SYMBOL *)malloc(MAXSYMS*sizeof(SYMBOL));
  484.     if (!symArray) {
  485.         printf("Insufficient memory\n");
  486.         exit(999);
  487.     }
  488.     infp = fopen(av[1], "r");
  489.     if (!infp) {
  490.         printf("Can't open %s\n", av[1]);
  491.         exit(999);
  492.     }
  493.     outfp = fopen(av[2], "w");
  494.     if (!outfp) {
  495.         printf("Can't open %s\n", av[2]);
  496.         exit(999);
  497.     }
  498.     printf("Converting %s to %s\n", av[1], av[2]);
  499.     fprintf(outfp, "; OMDS of file: %s\n\n", av[1]);
  500.     pass = 1;
  501.     ParseExternalDefinitions();
  502.     ParseSection00();
  503.     ParseSection01();
  504.     ParseSection02();
  505.     fclose(infp);
  506.     infp = fopen(av[1], "r");
  507.     if (!infp) {
  508.         printf("Can't open %s\n", av[1]);
  509.         exit(999);
  510.     }
  511.     pass = 2;
  512.     ParseExternalDefinitions();
  513.     ParseSection00();
  514.     ParseSection01();
  515.     ParseSection02();
  516.     fclose(outfp);
  517. }
  518.  
  519.