home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 177.lha / Deemu_v1.0 / config.c < prev    next >
C/C++ Source or Header  |  1988-04-28  |  10KB  |  490 lines

  1.  
  2. /*
  3.  *  CONFIG.C
  4.  *
  5.  *  (C)Copyright 1988, Matthew Dillon, All Rights Reserved.
  6.  *  Permission is granted to distribute for non-profit only.
  7.  *
  8.  *  config file1 file2 file3.... filen
  9.  *
  10.  *  Configure one or more executables.    The executables must conform to
  11.  *  the Static User Modifiable Data Standard        (SUMDS)
  12.  *
  13.  *  This program configures the static parameters of C programs which
  14.  *  contain the appropriate structures.  Unknown parameters may be
  15.  *  configured in raw hex if you know the format.
  16.  */
  17.  
  18. #include <stdio.h>
  19.  
  20. #define arysize(array)  (sizeof(array)/sizeof(array[0]))
  21.  
  22. extern void *malloc();
  23.  
  24. typedef unsigned char    ubyte;
  25. typedef unsigned short    uword;
  26. typedef unsigned long    ulong;
  27.  
  28. char Show;
  29. char XDebug;
  30.  
  31. main(ac, av)
  32. char *av[];
  33. {
  34.     register short i;
  35.     FILE *fi;
  36.     long pos, len;
  37.  
  38.     puts("CONFIG V1.00, Matthew Dillon.");
  39.     for (i = 1; i < ac; ++i) {
  40.     fi = fopen(av[i], "r+");
  41.     if (fi == NULL) {
  42.         printf("Could not open %s for reading\n", av[i]);
  43.         continue;
  44.     }
  45.     switch(FindData(fi, &pos, &len)) {
  46.     case -2:
  47.         printf("%s contains unknown hunk #%ld\n", av[i], pos);
  48.         break;
  49.     case -1:
  50.         printf("%s is not an executable\n", av[i]);
  51.         break;
  52.     case  0:
  53.         printf("could not find configuration header in %s\n", av[i]);
  54.         break;
  55.     case  1:
  56.         switch(Configure(fi, pos, len*4)) {
  57.         case -3:
  58.         printf("Unable to malloc %ld bytes\n", len);
  59.         break;
  60.         case -2:
  61.         puts("Error reading data block or badly formatted data");
  62.         break;
  63.         case -1:
  64.         puts("No 'END ' entry found in header");
  65.         break;
  66.         case 0:
  67.         puts("No modifications made to file");
  68.         break;
  69.         case 1:
  70.         puts("File updated");
  71.         break;
  72.         }
  73.         break;
  74.     }
  75.     fclose(fi);
  76.     }
  77. }
  78.  
  79. /*
  80.  *  Search through the beginning of all HUNK_DATA hunks for 'STRT', 0
  81.  *
  82.  *  symb:   object modules only, not defined here.
  83.  *    HUNK_OVERLAY cannot be handled yet.
  84.  */
  85.  
  86. #define HUNK_UNIT    999    /*  N, Nlws of name        */
  87. #define HUNK_NAME    1000    /*  N, Nlws of name        */
  88. #define HUNK_CODE    1001    /*  N, Nlws of code        */
  89. #define HUNK_DATA    1002    /*  N, Nlws of data        */
  90. #define HUNK_BSS    1003    /*  N    (Nlws of bss)       */
  91. #define HUNK_RELOC32    1004    /*  N, (N+1)lws, N ... 0    */
  92. #define HUNK_RELOC16    1005    /*  N, (N+1)lws, N ... 0    */
  93. #define HUNK_RELOC8    1006    /*  N, (N+1)lws, N ... 0    */
  94. #define HUNK_EXT    1007    /*  N, symb,symb... 0        */
  95. #define HUNK_SYMBOL    1008    /*  N, symb,symb... 0        */
  96. #define HUNK_DEBUG    1009    /*  N, Nlws of debug        */
  97. #define HUNK_END    1010    /*  -                */
  98. #define HUNK_HEADER    1011    /*  N, Nlwsname, N.. 0, tabsize, F, L, F-L+1 sizes  */
  99. #define HUNK_OVERLAY    1013    /*  tabsize, M+2,M+1 ... ovr data table         */
  100. #define HUNK_BREAK    1014    /*  -                */
  101.  
  102. FindData(fi, ppos, plen)
  103. FILE *fi;
  104. long *ppos;
  105. long *plen;
  106. {
  107.     long type;
  108.     long len;
  109.     long pos;
  110.     long ary[3];
  111.     static long buf[256];
  112.  
  113.     if (fread(&type, 4, 1, fi) != 1 || type != HUNK_HEADER)
  114.     return(-1);
  115.     for (;;) {
  116.     if (fread(&len, 4, 1, fi) != 1)
  117.         return(-1);
  118.     if (len == 0)
  119.         break;
  120.     fseek(fi, len*4, 1);
  121.     }
  122.     if (fread(ary, 4, 3, fi) != 3)
  123.     return(-1);
  124.     fseek(fi, 4*(ary[2] - ary[1] + 1), 1);
  125.  
  126.     while (fread(&type, 4, 1, fi) == 1) {
  127.     len = 0;
  128.     if (XDebug)
  129.         printf("type: %ld\n", type);
  130.     switch(type) {
  131.     case HUNK_CODE:
  132.         fread(&len, 4, 1, fi);
  133.         break;
  134.     case HUNK_DATA:
  135.         fread(&len, 4, 1, fi);      /*  # of longwords  */
  136.         pos = ftell(fi);
  137.         if (len >= 4) {
  138.         register short i;
  139.         register short j = (len > arysize(buf)) ? arysize(buf) : len;
  140.         register long *ptr;
  141.         fread(buf, j, 4, fi);
  142.         for (i = 0; i < j; ++i) {
  143.             ptr = buf + i;
  144.             if (ptr[0] == 'STRT' && ptr[1] == 0) {
  145.             *ppos = pos+i*4;
  146.             *plen = len - i;
  147.             fseek(fi, *ppos, 0);
  148.             return(1);
  149.             }
  150.             ptr = (long *)((short *)ptr + 1);
  151.             if (ptr[0] == 'STRT' && ptr[1] == 0) {
  152.             *ppos = pos+i*4+2;
  153.             *plen = len - i;
  154.             fseek(fi, *ppos, 0);
  155.             return(1);
  156.             }
  157.         }
  158.         }
  159.         fseek(fi, pos, 0);
  160.         break;
  161.     case HUNK_BSS:
  162.         fread(&len, 4, 1, fi);
  163.         len = 0;
  164.         break;
  165.     case HUNK_RELOC32:
  166.     case HUNK_RELOC16:
  167.     case HUNK_RELOC8:
  168.         for (;;) {
  169.         if (fread(&len, 4, 1, fi) != 1)
  170.             return(-1);
  171.         if (len == 0)
  172.             break;
  173.         ++len;
  174.         fseek(fi, len*4, 1);
  175.         }
  176.         break;
  177.     case HUNK_SYMBOL:
  178.         for (;;) {
  179.         if (fread(&len, 4, 1, fi) != 1)
  180.             return(-1);
  181.         if (len == 0)
  182.             break;
  183.         len = (len + 1) & 0x00FFFFFF;
  184.         if (len <= 32)                  /*  reading is faster */
  185.             fread(buf, len, 4, fi);
  186.         else                /*  very long name?   */
  187.             fseek(fi, len*4, 1);
  188.         }
  189.         break;
  190.     case HUNK_DEBUG:
  191.         if (fread(&len, 4, 1, fi) != 1)
  192.         return(-1);
  193.         break;
  194.     case HUNK_END:
  195.         break;
  196.     default:
  197.         *ppos = type;
  198.         return(-2);
  199.     }
  200.     fseek(fi, len*4, 1);
  201.     }
  202.     return(0);
  203. }
  204.  
  205. Configure(fi, pos, len)
  206. FILE *fi;
  207. long pos;
  208. long len;        /*  bytes   */
  209. {
  210.     register uword *buf = malloc(len+1);
  211.     register long i;
  212.     short j;
  213.     long modified = 0;
  214.     short numentries = 0;
  215.  
  216.     len >>= 1;        /*  Words   */
  217.  
  218.     if (buf == NULL)
  219.     return(-3);
  220.     fseek(fi, pos, 0);
  221.     if (fread(buf, len, 2, fi) != 2)
  222.     return(-2);
  223.     for (i = 4; i < len;) {
  224.     if (buf[i] == 'EN' && buf[i+1] == 'D ' && buf[i+2] == 0)
  225.         break;
  226.     ++numentries;
  227.     i += 4 + ((buf[i+3]+1)>>1);
  228.     }
  229.     if (i > len)
  230.     return(-2);
  231.     if (i == len)
  232.     return(-1);
  233.  
  234.     len = i;
  235.     printf("%ld entries found\n\n", numentries);
  236.  
  237.     for (i = 4; i < len;) {
  238.     register long data = (buf[i]<<16)|buf[i+1];
  239.     long dlen = buf[i+3];
  240.     uword *ptr = buf + i + 4;
  241.  
  242.     printf("----(%c%c%c%c,%2ld): ", data>>24, data>>16, data>>8, data, dlen);
  243.     switch(data) {
  244.     case 'NW  ':
  245.         puts("NEW WINDOW STRUCTURE");
  246.         modified += Edit_WINP(ptr, dlen);
  247.         break;
  248.     case 'TEXT':
  249.         puts("TEXT");
  250.         modified += Edit_TEXT(ptr, dlen);
  251.         break;
  252.     default:
  253.         puts("UNKNOWN STRUCTURE, HEX EDIT");
  254.         modified += Edit_Hex(ptr, dlen);
  255.         break;
  256.     }
  257.     i += 4 + ((dlen+1)>>1);
  258.     puts("");
  259.     }
  260.     {
  261.     long response = (modified) ? 0 : 'n';
  262.     char ibuf[64];
  263.  
  264.     while (response != 'y' && response != 'n') {
  265.         printf("Write data back to file (y/n): ");
  266.         fflush(stdout);
  267.         if (gets(ibuf) == NULL)
  268.         break;
  269.         response = ibuf[0] | 0x20;
  270.     }
  271.     if (response == 'y') {
  272.         fseek(fi, pos, 0);
  273.         fwrite(buf, len, 2, fi);
  274.         return(1);
  275.     } else {
  276.         return(0);
  277.     }
  278.     }
  279. }
  280.  
  281. Edit_WINP(buf, bytes)
  282. char *buf;
  283. short bytes;
  284. {
  285.     short i;
  286.     short modified = 0;
  287.  
  288.     for (i = 0; i < bytes;) {
  289.     switch(i) {
  290.     case 0:     /*    LeftEdge    */
  291.         modified += strscanvalue(buf+i, 2, "LeftEdge", "(Negative = Relative to Screen Right)");
  292.         i += 2;
  293.         break;
  294.     case 2:     /*    TopEdge     */
  295.         modified += strscanvalue(buf+i, 2, "TopEdge", "(Negative = Relative to Screen Bottom)");
  296.         i += 2;
  297.         break;
  298.     case 4:     /*    Width        */
  299.         modified += strscanvalue(buf+i, 2, "Width", "(0 = Full Width, < 0 = ScreenWidth - (-width)");
  300.         i += 2;
  301.         break;
  302.     case 6:     /*    Height    */
  303.         modified += strscanvalue(buf+i, 2, "Height", "(0 = Full Height, < 0 = ScreenHeight - (-height)");
  304.         i += 2;
  305.         break;
  306.     case 8:     /*    DetailPen   */
  307.         modified += strscanvalue(buf+i, 1, "DetailPen", NULL);
  308.         ++i;
  309.         break;
  310.     case 9:     /*    BlockPen    */
  311.         modified += strscanvalue(buf+i, 1, "BlockPen", NULL);
  312.         ++i;
  313.         break;
  314.     case 10:    /*    IDCMP        */
  315.         modified += strscanvalue(buf+i, 4, "IDCMP", NULL);
  316.         i += 4;
  317.         break;
  318.     case 14:    /*    Flags        */
  319.         modified += strscanvalue(buf+i, 4, "Flags", NULL);
  320.         i += 4;
  321.         break;
  322.     default:
  323.         i = bytes;
  324.         break;
  325.     }
  326.     }
  327.     return(modified);
  328. }
  329.  
  330. /*
  331.  *  Edit TEXT.    The buffer holds a 'type' string, \0, then space for a text
  332.  *  string.
  333.  */
  334.  
  335. Edit_TEXT(lb, len)
  336. char *lb;
  337. {
  338.     register short i, slen;
  339.     char buf[256];
  340.     char *prompt = lb;
  341.  
  342.     while (*lb) {
  343.     ++lb;
  344.     --len;
  345.     }
  346.     ++lb;
  347.     --len;
  348.     if (len <= 0) {
  349.     puts("TEXT ERROR: UNTERMINATED BUFFER");
  350.     return(0);
  351.     }
  352. loop:
  353.     printf("%-15s (%ld chars max) (%15s) :", prompt, len - 1, lb);
  354.     if (gets(buf) == NULL || buf[0] == 0)
  355.     strcpy(buf, lb);
  356.     if (strcmp(buf, lb) != 0) {
  357.     slen = strlen(buf);
  358.     if (slen > len - 1) {
  359.         printf("Maximum of %ld chars!", len - 1);
  360.         goto loop;
  361.     }
  362.     strcpy(lb, buf);
  363.     return(1);
  364.     }
  365.     return(0);
  366. }
  367.  
  368. Edit_Extended(i, size, lb)
  369. short i;
  370. char *lb;
  371. {
  372.     printf("    #%ld (Blind entry) ", i);
  373.     return(scanvalue(lb, size));
  374. }
  375.  
  376. Edit_Hex(lb, len)
  377. char *lb;
  378. long len;
  379. {
  380.     short modified = 0;
  381.     short i;
  382.  
  383.     puts("    (Unknown Type, blind data entry)");
  384.     for (i = 0; i < len; ++i) {
  385.     printf("    Entry %2ld/%2ld ", i, len-1);
  386.     modified += scanvalue(lb+i, 1);
  387.     }
  388.     return(modified);
  389. }
  390.  
  391. strscanvalue(lb, size, prompt, desc)
  392. char *lb;
  393. char *prompt;
  394. char *desc;
  395. {
  396.     if (desc)
  397.     printf(" note: %s\n", desc);
  398.     printf("%15s ", prompt);
  399.     return(scanvalue(lb, size));
  400. }
  401.  
  402. scanvalue(lb, size)
  403. ubyte *lb;
  404. {
  405.     register long val;
  406.     register char *str;
  407.     short neg;
  408.     char buf[128];
  409.  
  410. top:
  411.     switch(size) {
  412.     case 1:
  413.     val = *lb;
  414.     printf("(      $%02x     %3ld) :", val, (char)val);
  415.     break;
  416.     case 2:
  417.     val = *(uword *)lb;
  418.     printf("(    $%04x  %6ld) :", val, (short)val);
  419.     break;
  420.     case 4:
  421.     val = *(long *)lb;
  422.     printf("($%08lx %7ld) :", val, val);
  423.     break;
  424.     }
  425.     fflush(stdout);
  426.  
  427.     neg = 1;
  428.     if (gets(buf) && buf[0]) {
  429.     val = 0;
  430.     str = buf;
  431.     if (*str == '-') {
  432.         neg = -1;
  433.         ++str;
  434.     }
  435.                             /*    hex */
  436.     if (str[0] == '$' || (str[0] == '0' && (str[1]|0x20) == 'x')) {
  437.         if (*str++ != '$')
  438.         ++str;
  439.         for (; *str; ++str) {
  440.         *str |= 0x20;
  441.         if (*str >= '0' && *str <= '9') {
  442.             val = (val << 4) | (*str & 15);
  443.             continue;
  444.         }
  445.         if (*str >= 'a' && *str <= 'f') {
  446.             val = (val << 4) | (*str - 'a' + 10);
  447.             continue;
  448.         }
  449.         break;
  450.         }
  451.     } else
  452.     if (*str == '%') {                          /*  binary  */
  453.         for (++str; *str >= '0' && *str <= '1'; ++str)
  454.         val = (val << 1) | (*str & 1);
  455.     } else if (*str) {                          /*  decimal */
  456.         for (; *str >= '0' && *str <= '9'; ++str)
  457.         val = val * 10 + *str - '0';
  458.     }
  459.     if (*str) {
  460.         printf("Illegal char '%c', try again\n    ? ", *str);
  461.         goto top;
  462.     }
  463.     }
  464.     if (neg < 0)
  465.     val = -val;
  466.     switch(size) {
  467.     case 1:
  468.     if ((ubyte)val != *lb) {
  469.         *lb = val;
  470.         return(1);
  471.     }
  472.     break;
  473.     case 2:
  474.     if ((uword)val != *(uword *)lb) {
  475.         *(uword *)lb = val;
  476.         return(1);
  477.     }
  478.     break;
  479.     case 4:
  480.     if (val != *(long *)lb) {
  481.         *(long *)lb = val;
  482.         return(1);
  483.     }
  484.     break;
  485.     }
  486.     return(0);
  487. }
  488.  
  489.  
  490.