home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / EFFO / forum16.lzh / SOFTWARE / C / HEXED / hexed.c < prev    next >
Text File  |  1991-03-25  |  13KB  |  502 lines

  1. /*
  2.    hexeditor made up of three parts:
  3.      - creating hexdump
  4.      - editing hexdump using standard texteditor
  5.      - retransforming hexdump to binary file
  6.  
  7.    (C) Helmut Hoheisel-Zimmermann, D-2300 Kiel
  8.        03/91
  9. */
  10.  
  11.  
  12. /* includes :                            */
  13.  
  14. #include <stdio.h>
  15. #include <strings.h>
  16. #include <ctype.h>
  17.  
  18.  
  19. /* externals :                            */
  20.  
  21. extern char *_prgname () ;
  22.  
  23.  
  24. /* constants :                            */
  25.  
  26. #define TEMPDIR_DEFAULT "/r0"    /* dir for temporary files    */
  27. #define EDITOR_DEFAULT  "vi"    /* texteditor's name        */
  28. #define EDOPTS_DEFAULT  ""    /* options for texteditor    */
  29. #define EDGOTO_DEFAULT  "+"    /* goto option for texteditor    */
  30.  
  31. #define FORMAT_ERROR    -2    /* wrong retransform format    */
  32. #define END_OF_LINE     -1    /* normal end of line        */
  33.  
  34.  
  35. /* globals :                            */
  36.  
  37. char *tempdir = TEMPDIR_DEFAULT ;
  38. char *editor = EDITOR_DEFAULT ;
  39. char *edit_opts = EDOPTS_DEFAULT ;
  40. char *edit_goto = EDGOTO_DEFAULT ;
  41.  
  42.  
  43.  
  44. /****************************************************************/
  45. /* usage-message and exit :                    */
  46. void usage ()
  47.  
  48. {
  49. fprintf ( stderr, "Syntax: %s [<opts>] <path> {[<opts>] | [<path>]}\n", _prgname () ) ;
  50. fprintf ( stderr, "Function: dump, edit and retransform file(s) with binary data\n" ) ;
  51. fprintf ( stderr, "Options:\n" ) ;
  52. fprintf ( stderr, "     -t=<dir>       use <dir> for temporary files (default: '%s')\n", tempdir ) ;
  53. fprintf ( stderr, "     -e=<editor>    use <editor> as the texteditor (default: '%s')\n", editor ) ;
  54. fprintf ( stderr, "     -eo=<opts>     use editor-<opts> (default: '%s')\n", edit_opts ) ;
  55. fprintf ( stderr, "     -eg=<opts>     use editor-<opts> to go to specified line (default: '%s')\n", edit_goto ) ;
  56. fprintf ( stderr, "     -?             show this message\n\n" ) ;
  57. fprintf ( stderr, "Format for dumped lines as generated by '%s':\n", _prgname () ) ;
  58. fprintf ( stderr, "  bytecount         (optional) will not be interpreted by retransformation\n" ) ;
  59. fprintf ( stderr, "  blank(s)          (at least one blank, obligatory) as separator\n" ) ;
  60. fprintf ( stderr, "  hexdata bytes     (an arbitrary number) each of it consisting of one or two\n" ) ;
  61. fprintf ( stderr, "                    hex-digits; the bytes are separated by blank(s)\n" ) ;
  62. fprintf ( stderr, "  blank & ; & ASCII (optional) arbitrary comment or ASCII-representation\n\n" ) ;
  63. fprintf ( stderr, "Alternatively the following line format can be retransformed:\n" ) ;
  64. fprintf ( stderr, "  .a                inits ASCII-line\n" ) ;
  65. fprintf ( stderr, "  blank(s)          (optional) as separator\n" ) ;
  66. fprintf ( stderr, "  delimiter         arbitrary ASCII-character except blank as delimiter\n" ) ;
  67. fprintf ( stderr, "  ASCII-data        text without delimiter\n" ) ;
  68. fprintf ( stderr, "  delimiter & ASCII (optional, delimiter as defined above) arbitrary comment\n" ) ;
  69. exit ( 0 ) ;
  70. }
  71.  
  72.  
  73. /****************************************************************/
  74. /* scan for options :                        */
  75. void getargs ( ac, av )
  76.      int  *ac ;
  77.      char *av [] ;
  78.  
  79. {
  80. register int i ;
  81. int  maxac ;
  82. char **avfilenames ;
  83.  
  84.  
  85. for ( i = 1, maxac = *ac, avfilenames = av + 1 ; i < maxac ; i ++ )
  86.   {
  87.   if ( *av [i] == '-' )
  88.     {        /* parameter is option :    */
  89.     switch ( *( av [i] + 1 ) )
  90.       {
  91.       case 't' :
  92.         if ( *( av [i] + 2 ) != '=' )
  93.           {
  94.           usage () ;
  95.           }
  96.         tempdir = av [i] + 3 ;
  97.         break ;
  98.  
  99.       case 'e' :
  100.         switch ( *( av [i] + 2 ) )
  101.           {
  102.           case '=' :
  103.             editor = av [i] + 3 ;
  104.             break ;
  105.  
  106.           case 'o' :
  107.             if ( *( av [i] + 3 ) != '=' )
  108.               {
  109.               usage () ;
  110.               }
  111.             edit_opts = av [i] + 4 ;
  112.             break ;
  113.  
  114.           case 'g' :
  115.             if ( *( av [i] + 3 ) != '=' )
  116.               {
  117.               usage () ;
  118.               }
  119.             edit_goto = av [i] + 4 ;
  120.             break ;
  121.  
  122.           default :    /* illegal 2. option letter    */
  123.             usage () ;
  124.             break ;
  125.           }
  126.         break ;
  127.  
  128.       default :        /* illegal option letter    */
  129.         usage () ;
  130.         break ;
  131.       }        /* end switch ( option letter    */
  132.  
  133.     ( *ac ) -- ;
  134.     }        /* end if ( option        */
  135.   else
  136.     {        /* filename            */
  137.     * avfilenames ++ = av [i] ;
  138.     }
  139.   }        /* end for ( i ...        */
  140. if ( *ac < 2 )
  141.   {
  142.   usage () ;
  143.   }
  144. }
  145.  
  146.  
  147. /****************************************************************/
  148. /* return pointer to pure filename without directories :    */
  149. char *get_filename ( path )
  150.      char *path ;
  151.  
  152. {
  153. register char *cp ;
  154.  
  155.  
  156. for ( cp = path + strlen ( path ) - 1 ; cp >= path ; cp -- )
  157.   {
  158.   if ( *cp == '/' )
  159.     {
  160.     break ;
  161.     }
  162.   }
  163. return ( cp + 1 ) ;
  164. }
  165.  
  166.  
  167. /****************************************************************/
  168. /* get hexdump filename from binary data filename :        */
  169. char *hd_filename ( path )
  170.      char *path ;
  171.  
  172. {
  173. static char namebuf [160] ;
  174.  
  175.  
  176. sprintf ( namebuf, "%s/%s.hd", tempdir, get_filename ( path ) ) ;
  177. return ( namebuf ) ;
  178. }
  179.  
  180.  
  181. /****************************************************************/
  182. /* create one dump file :                    */
  183. void gen_dump ( source_path )
  184.     char *source_path ;        /* name of sourcefile        */
  185.  
  186. {
  187. char *hd_path ;            /* dump file name        */
  188. FILE *hdfile ;            /* dump file pointer        */
  189. FILE *srcfile ;            /* source file pointer        */
  190. register int current = 0 ;    /* current byte number        */
  191. char ascii [16] ;        /* buffer for ASCII represent.    */
  192. register int ch ;        /* character read from input    */
  193. register int index ;        /* column index            */
  194.  
  195.  
  196. hd_path = hd_filename ( source_path ) ;
  197. fprintf ( stderr, "Creating '%s' from '%s'.\n", hd_path, source_path ) ;
  198. if ( ( hdfile = fopen ( hd_path, "w" ) ) == (FILE*) 0 )
  199.   {
  200.   fprintf ( stderr, "error: can't create '%s' !\n", hd_path ) ;
  201.   exit ( 1 ) ;
  202.   }
  203.  
  204. if ( ( srcfile = fopen ( source_path, "r" ) ) != (FILE*) 0 )
  205.   {            /* source is available :        */
  206.   while ( ( ch = getc ( srcfile ) ) != EOF )
  207.     {
  208.     switch ( index = current % 16 )
  209.       {
  210.       case 0 :            /* start of dump line :        */
  211.         memset ( ascii, ' ', 16 ) ;
  212.     ascii [ index ] = ch < 127 && isprint ( ch ) ? ch : '.' ;
  213.     fprintf ( hdfile, "%06X  %02x", current, ch ) ;
  214.     break ;
  215.  
  216.       case 15 :            /* last byte of this line :    */
  217.     ascii [ index ] = ch < 127 && isprint ( ch ) ? ch : '.' ;
  218.     fprintf ( hdfile, " %02x  ; %.16s\n", ch, ascii ) ;
  219.     break ;
  220.  
  221.       case 4 :            /* quarters of the line :    */
  222.       case 8 :
  223.       case 12 :
  224.     putc ( ' ', hdfile ) ;
  225.  
  226.       default :            /* else :            */
  227.     ascii [ index ] = ch < 127 && isprint ( ch ) ? ch : '.' ;
  228.     fprintf ( hdfile, " %02x", ch ) ;
  229.     break ;
  230.       }
  231.     current ++ ;
  232.     }
  233.  
  234.   if ( current % 16 )
  235.     {
  236.     if ( index < 4 )
  237.       {
  238.       putc ( ' ', hdfile ) ;
  239.       }
  240.     if ( index < 8 )
  241.       {
  242.       putc ( ' ', hdfile ) ;
  243.       }
  244.     if ( index < 12 )
  245.       {
  246.       putc ( ' ', hdfile ) ;
  247.       }
  248.     fprintf ( hdfile, "%*s  ; %.*s\n", ( 15 - index ) * 3, "", index + 1 , ascii ) ;
  249.     }
  250.  
  251.   fclose ( srcfile ) ;
  252.   }
  253.  
  254. fprintf ( hdfile, "%06X\n", current ) ;
  255. fclose ( hdfile ) ;
  256. }
  257.  
  258.  
  259. /****************************************************************/
  260. /* retransform one dump file :                    */
  261. int dedump ( source_path )
  262.     char *source_path ;        /* name of sourcefile        */
  263.  
  264. {
  265. char *hd_path ;            /* dump file name        */
  266. FILE *hdfile ;            /* dump file pointer        */
  267. FILE *srcfile ;            /* source file pointer        */
  268. char line [512] ;        /* one dump line        */
  269. register char *akt ;        /* actual char ptr        */
  270. register int ch ;        /* actual char            */
  271. int  lnr ;            /* line number            */
  272. register int phase ;        /* status            */
  273. char *errtext ;            /* error text for format errors    */
  274. int  delimiter ;        /* delimiter for ASCII text    */
  275. char *bytestart ;        /* pointer to begin of hexbyte    */
  276.  
  277.  
  278. hd_path = hd_filename ( source_path ) ;
  279. fprintf ( stderr, "Generating '%s' from '%s'.\n", source_path, hd_path ) ;
  280. if ( ( hdfile = fopen ( hd_path, "r" ) ) == (FILE*) 0 )
  281.   {
  282.   fprintf ( stderr, "error: can't open '%s' !\n", hd_path ) ;
  283.   return ( -1 ) ;
  284.   }
  285.  
  286. if ( ( srcfile = fopen ( source_path, "w" ) ) == (FILE*) 0 )
  287.   {
  288.   fclose ( hdfile ) ;
  289.   fprintf ( stderr, "error: can't open '%s' !\n", source_path ) ;
  290.   return ( -1 ) ;
  291.   }
  292.  
  293. lnr = 0 ;    /* assumes: editor counts lines from 1 to ...    */
  294. while ( ( akt = fgets ( line, sizeof ( line ), hdfile ) ) != (char *) 0 )
  295.   {
  296.   *( line + strlen ( line ) - 1 ) = '\0' ;
  297.   lnr ++ ;
  298.   for ( phase = 0 ; phase >= 0 ; akt ++ )
  299.     {
  300.     ch = *akt ;
  301.     if ( ch == '\0' )
  302.       {
  303.       phase = END_OF_LINE ;
  304.       }
  305.     switch ( phase )
  306.       {
  307.       case 0 :        /* start of line :            */
  308.         if ( ch == '.' )
  309.           {
  310.           phase ++ ;        /* begin of ASCII line ?    */
  311.           }
  312.         else
  313.           {
  314.                 /* to ensure correct handling    */
  315.                 /* of EOL in hexbyte (phase 7):    */
  316.           *( line + strlen ( line ) ) = ' ' ;
  317.           if ( isspace ( ch ) )
  318.             {
  319.             phase = 6 ;        /* hexdump after linenumber ?    */
  320.             }
  321.           else
  322.             {
  323.             if ( isxdigit ( ch ) )
  324.               {
  325.               phase = 5 ;    /* hexdump linenumber        */
  326.               }
  327.             else
  328.               {
  329.               errtext = "illegal first char" ;
  330.               phase = FORMAT_ERROR ;
  331.               }
  332.             }
  333.           }
  334.         break ;
  335.  
  336.       case 1 :        /* ASCII line ?                */
  337.         if ( ch == 'a' || ch == 'A' )
  338.           {
  339.           phase ++ ;        /* look for delimiter        */
  340.           }
  341.         else
  342.           {
  343.           errtext = "no ASCII line !" ;
  344.           phase = FORMAT_ERROR ;
  345.              }
  346.         break ;
  347.  
  348.       case 2 :        /* scan for delimiter :            */
  349.         if ( ! isspace ( ch ) )
  350.           {
  351.           delimiter = ch ;
  352.           phase ++ ;        /* transfer ASCII text        */
  353.           }
  354.         break ;
  355.  
  356.       case 3 :
  357.         if ( ch == delimiter )
  358.           {
  359.           phase = END_OF_LINE ;
  360.           }
  361.         else
  362.           {
  363.           putc ( ch, srcfile ) ;
  364.           }
  365.         break ;
  366.  
  367.       case 5 :        /* linenumber of hexdump :        */
  368.         if ( isspace ( ch ) )
  369.           {
  370.           phase ++ ;
  371.           }
  372.         else
  373.           {
  374.           if ( ! isxdigit ( ch ) )
  375.             {
  376.         errtext = "illegal char in linenumber" ;
  377.         phase = FORMAT_ERROR ;
  378.             }
  379.           }
  380.         break ;
  381.  
  382.       case 6 :        /* space before hexbyte :        */
  383.         if ( ch == ';' )
  384.           {
  385.           phase = END_OF_LINE ;
  386.           }
  387.         else
  388.           {
  389.       if ( isxdigit ( ch ) )
  390.             {
  391.             bytestart = akt ;
  392.             phase ++ ;        /* transform hexbyte        */
  393.             }
  394.           else
  395.             {
  396.             if ( ! isspace ( ch ) )
  397.               {
  398.           errtext = "illegal char between hexbytes" ;
  399.           phase = FORMAT_ERROR ;
  400.               }
  401.             }
  402.           }
  403.         break ;
  404.  
  405.       case 7 :        /* in hexbyte :                */
  406.         if ( isspace ( ch ) )
  407.           {
  408.           if ( akt - bytestart > 2 )
  409.             {
  410.         errtext = "illegal size of hexbyte" ;
  411.         phase = FORMAT_ERROR ;
  412.             }
  413.           else
  414.             {
  415.             sscanf ( bytestart, "%x", &delimiter ) ;
  416.             putc ( delimiter, srcfile ) ;
  417.             phase -- ;        /* space between hexbytes    */
  418.             }
  419.           }
  420.         else
  421.           {
  422.           if ( ! isxdigit ( ch ) )
  423.             {
  424.         errtext = "illegal char in hexbyte" ;
  425.         phase = FORMAT_ERROR ;
  426.             }
  427.           }
  428.         break ;
  429.  
  430.       default :
  431.         break ;
  432.       }
  433.     }
  434.  
  435.   if ( phase == FORMAT_ERROR )
  436.     {
  437.     fprintf ( stderr, " -> format error in line no. %d : %s !\n", lnr, errtext ) ;
  438.     fprintf ( stderr, "    press 'return' to continue !\n" ) ;
  439.     getchar () ;
  440.     fclose ( srcfile ) ;
  441.     fclose ( hdfile ) ;
  442.     if ( *edit_goto == '\0' )
  443.       {        /* no goto option :                    */
  444.       sprintf ( line, "%s %s", editor, hd_path ) ;
  445.       }
  446.     else
  447.       {
  448.       sprintf ( line, "%s %s%d %s", editor, edit_goto, lnr, hd_path ) ;
  449.       }
  450.     system ( line ) ;
  451.     return ( dedump ( source_path ) ) ;        /* recursive !!!    */
  452.     }
  453.  
  454.   }
  455.  
  456. fclose ( srcfile ) ;
  457. fclose ( hdfile ) ;
  458. return ( 0 ) ;
  459. }
  460.  
  461.  
  462. /****************************************************************/
  463. /* main program :                        */
  464. main ( argc, argv )
  465.     int  argc ;
  466.     char *argv [] ;
  467.  
  468. {
  469. register int cnt ;
  470. char cmd_buf [512] ;        /* for system-call        */
  471.  
  472.  
  473. getargs ( &argc, argv ) ;    /* scan parameters :        */
  474.  
  475.                 /* create dump files :        */
  476. for ( cnt = 1 ; cnt < argc ; cnt ++ )
  477.   {
  478.   gen_dump ( argv [ cnt ] ) ;
  479.   }
  480.  
  481.                 /* edit dump files :        */
  482. sprintf ( cmd_buf, "chd %s ; %s %s ", tempdir, editor, edit_opts ) ;
  483. for ( cnt = 1 ; cnt < argc ; cnt ++ )
  484.   {
  485.   strcat ( cmd_buf, " " ) ;
  486.   strcat ( cmd_buf, get_filename ( argv [ cnt ] ) ) ;
  487.   strcat ( cmd_buf, ".hd " ) ;
  488.   }
  489. system ( cmd_buf ) ;
  490.  
  491.                 /* retransform dump files :    */
  492. for ( cnt = 1 ; cnt < argc ; cnt ++ )
  493.   {
  494.   if ( dedump ( argv [ cnt ] ) >= 0 )
  495.     {
  496.     unlink ( hd_filename ( argv [ cnt ] ) ) ;
  497.     }
  498.   }
  499. }
  500.  
  501.  
  502.