home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / UTILITY / FILE / XLAT11.ZIP / XFERXLAT.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1990-08-12  |  16.8 KB  |  439 lines

  1. Program xferxlat;
  2. { Transfer a XLAT translation table between COM and table files.             }
  3. { FreeWare by TapirSoft Gisbert W.Selke, Aug 1990                            }
  4.  
  5. {$UNDEF  DEBUG }        { DEFINE while debugging }
  6.  
  7. {$A+,B-,D+,E+,F-,I+,L+,N-,O-,V- }
  8. {$M 16384,0,16384 }
  9. {$IFDEF DEBUG }
  10.   {$R+,S+ }
  11. {$ELSE }
  12.   {$R-,S- }
  13. {$ENDIF }
  14.  
  15.   Const progname  = 'XferXlat';
  16.         version   = '1.1';
  17.         copyright = 'FreeWare by TapirSoft Gisbert W.Selke, Aug 1990';
  18.         idstring10= 'XLAT10';
  19.         idstring11= 'XLAT11';
  20.         idlength  = Length(idstring10);
  21.         hexnibble : string[16] = '0123456789ABCDEF';
  22.         digits    : string[10] = '0123456789';
  23.  
  24.   Const fbufsize = 4096;
  25.         width    = 18;
  26.  
  27.   Type tabletype = Array [byte] Of byte;
  28.        fbuftype  = Array [1..fbufsize] Of byte;
  29.  
  30.   Var fnamep, fnamet, fnameo : string;
  31.       xlat  : File;
  32.       tabf  : text;
  33.       fbuf  : fbuftype;
  34.       fsize : word;
  35.       transtype : byte;
  36.       doinvert : boolean;
  37.       descript, intername : string;
  38.       tstart, tabstart, interstart : word;
  39.       desclen  : byte;
  40.       xlatid   : byte;
  41.       table    : tabletype;
  42.       exitsave : Pointer;
  43.  
  44.   Function LoCase(ch : char) : char;
  45.   { make characters lower case; national special characters, too!            }
  46.     Inline($58/$3C/$41/$72/$39/$3C/$5A/$76/$33/$3C/$8E/$75/$02/$B0/$84
  47.     /$3C/$99/$75/$02/$B0/$94/$3C/$9A/$75/$02/$B0/$81
  48.     /$3C/$80/$75/$02/$B0/$87/$3C/$8F/$75/$02/$B0/$86
  49.     /$3C/$90/$75/$02/$B0/$82/$3C/$92/$75/$02/$B0/$91
  50.     /$3C/$A5/$75/$02/$B0/$A4/$EB/03/90/$04/$20);
  51.  
  52.   Function hexbyte(b : byte) : string;
  53.   { convert a byte to a string                                               }
  54.   Begin                                                            { hexbyte }
  55.     hexbyte := hexnibble[Succ(b ShR 4)] + hexnibble[Succ(b And $0F)];
  56.   End;                                                             { hexbtye }
  57.  
  58.   Procedure abort(msg : string; errcode : byte);
  59.   { show message and die                                                     }
  60.   Begin                                                              { abort }
  61.     writeln(msg);
  62.     Halt(errcode);
  63.   End;                                                               { abort }
  64.  
  65.   Procedure invert;
  66.   { invert a translation table                                               }
  67.     Var temp : tabletype;
  68.         i : byte;
  69.   Begin                                                             { invert }
  70.     For i :=   0     To   255 Do temp[i] := 0;
  71.     For i := 255 DownTo     0 Do temp[table[i]] := i;
  72.     table := temp;
  73.   End;                                                              { invert }
  74.  
  75.   Procedure loadcom(fname : string; loadcomplete : boolean);
  76.   { load a COM file. if not loadcomplete, then load table data only          }
  77.  
  78.     Const proginfoptr = 4;
  79.  
  80.     Var i, xfsize, xinterstart, xtstart, xtabstart : word;
  81.         xdesclen : byte;
  82.         temp : string;
  83.         fbuf1 : fbuftype;
  84.  
  85.   Begin                                                            { loadcom }
  86.     i := FileMode;
  87.     FileMode := 0;
  88.     Assign(xlat,fname);
  89.     {$I- }
  90.     Reset(xlat,1);
  91.     FileMode := i;
  92.     If IOResult <> 0 Then abort('File ' + fname + ' not found',2);
  93.     BlockRead(xlat,fbuf1,fbufsize,xfsize);
  94.     Close(xlat);
  95.     {$I+ }
  96.     If IOResult <> 0 Then abort('Error reading file ' + fname,3);
  97.     i := fbuf1[proginfoptr] + 1;
  98.     temp[0] := Chr(idlength);
  99.     Move(fbuf1[i],temp[1],idlength);
  100.     xlatid := 0;
  101.     If temp = idstring10 Then xlatid := 10;
  102.     If temp = idstring11 Then xlatid := 11;
  103.     If xlatid = 0 Then abort('Unknown programme version ' + temp + ' in ' +
  104.                              fname,4);
  105.     Move(fbuf1[i+8],xinterstart,2);
  106.     If xinterstart >= xfsize Then abort('File ' + fname +
  107.                                         ' has invalid format',5);
  108.     Inc(xinterstart);
  109.     xtstart := Succ(fbuf1[i+6]);
  110.     xdesclen := fbuf1[i+7];
  111.     Move(fbuf1[i+10],xtabstart,2);
  112.     Inc(xtabstart);
  113.     Move(fbuf1[xtstart],descript[1],xdesclen);
  114.     Move(fbuf1[xtabstart],table,256);
  115.     Move(fbuf1[xinterstart],intername[1],8);
  116.     intername[0] := #8;
  117.     If loadcomplete Then
  118.     Begin
  119.       fbuf        := fbuf1;
  120.       fsize       := xfsize;
  121.       interstart  := xinterstart;
  122.       tstart      := xtstart;
  123.       tabstart    := xtabstart;
  124.       desclen     := xdesclen;
  125.       descript[0] := Chr(desclen);
  126.     End
  127.     Else
  128.     Begin
  129.       For i := Succ(xdesclen) To desclen Do descript[i] := ' ';
  130.     End;
  131.   End;                                                             { loadcom }
  132.  
  133.   Procedure savecom(fname : string);
  134.   { save a translation table as a COM file                                   }
  135.     Var iwrite : word;
  136.   Begin                                                            { savecom }
  137.     intername := fname;
  138.     While (intername <> '') And (Pos(':',intername) > 0) Do
  139.                                   Delete(intername,1,Pos(':',intername));
  140.     While (intername <> '') And (Pos('\',intername) > 0) Do
  141.                                   Delete(intername,1,Pos('\',intername));
  142.     While (intername <> '') And (Pos('.',intername) > 0) Do
  143.                                   Delete(intername,Pos('.',intername),255);
  144.     While Length(intername) < 8 Do intername := intername + ' ';
  145.     {$I- }
  146.     Assign(xlat,fname);
  147.     Rewrite(xlat,1);
  148.     If IOResult <> 0 Then abort('Cannot open ' + fname + ' for output',10);
  149.     Move(descript[1],fbuf[tstart],desclen);
  150.     Move(table,fbuf[tabstart],256);
  151.     Move(intername[1],fbuf[interstart],8);
  152.     BlockWrite(xlat,fbuf,fsize,iwrite);
  153.     If iwrite <> fsize Then abort('Error writing file ' + fname,11);
  154.     Close(xlat);
  155.     {$I+ }
  156.   End;                                                             { savecom }
  157.  
  158.   Procedure loadtable(fname : string);
  159.   { load a translation table from an ASCII table file                        }
  160.  
  161.     Var i : byte;
  162.         tab1 : tabletype;
  163.         descript1, lin, cmd, froms, tos, tname : string;
  164.         fromval, toval : byte;
  165.         ok : boolean;
  166.  
  167.     Function gettok(s : string; Var ptr : byte) : string;
  168.     { returns next token from s, or ''                                       }
  169.       Var beg : byte;
  170.     Begin                                                           { gettok }
  171.       While (ptr <= Length(s)) And ((s[ptr] = ' ') Or (s[ptr] = #9)) Do
  172.                                                                      Inc(ptr);
  173.       beg := ptr;
  174.       While (ptr <= Length(s)) And (s[ptr] <> ' ') And (s[ptr] <> #9) Do
  175.       Begin
  176.         s[ptr] := UpCase(s[ptr]);
  177.         Inc(ptr);
  178.       End;
  179.       gettok := Copy(s,beg,ptr-beg);
  180.     End;                                                            { gettok }
  181.  
  182.     Function decoval(s : string; Var ok : boolean) : byte;
  183.     { decodes a decimal or hexadecimal (prefixed by 'x') value               }
  184.       Var i1, i2, num : byte;
  185.     Begin                                                          { decoval }
  186.       num := 0;
  187.       ok := False;
  188.       If s <> '' Then
  189.       Begin
  190.         If (s[1] = 'X') And (Length(s) >= 1) And (Length(s) <= 3) Then
  191.         Begin
  192.           If Length(s) = 2 Then
  193.           Begin
  194.             s[1] := '0';
  195.             i2 := 1;
  196.           End
  197.             Else i2 := 2;
  198.           i1 := Pos(s[i2],hexnibble);
  199.           i2 := Pos(s[Succ(i2)],hexnibble);
  200.           ok := (i1 > 0) And (i2 > 0);
  201.           If ok Then num := Pred(i1) ShL 4 + Pred(i2);
  202.         End
  203.         Else
  204.         Begin
  205.           For i2 := 1 To Length(s) Do
  206.           Begin
  207.             i1 := Pos(s[i2],digits);
  208.             ok := ok And (i1 > 0);
  209.             If ok Then
  210.             Begin
  211.               If 10*word(num)+ i1 <= 256 Then num := 10*num + Pred(i1);
  212.             End;
  213.           End;
  214.         End;
  215.       End;
  216.       decoval := num;
  217.     End;                                                           { decoval }
  218.  
  219.   Begin                                                          { loadtable }
  220.     i := FileMode;
  221.     FileMode := 0;
  222.     Assign(tabf,fname);
  223.     {$I- }
  224.     Reset(tabf);
  225.     FileMode := i;
  226.     If IOResult <> 0 Then abort('File ' + fname + ' not found',6);
  227.     descript1 := '';
  228.     For i := 0 To 255 Do tab1[i] := i;
  229.     While Not EoF(tabf) Do
  230.     Begin
  231.       readln(tabf,lin);
  232.       If Pos(';',lin) > 0 Then Delete(lin,Pos(';',lin),255);
  233.       While (lin <> '') And ((lin[1] = ' ') Or (lin[1] = #9)) Do
  234.                                                            Delete(lin,1,1);
  235.       i := 1;
  236.       cmd := gettok(lin,i);
  237.       If cmd = '' Then cmd := ' ';
  238.       If Length(cmd) > 1 Then cmd := '?';
  239.       Case UpCase(cmd[1]) Of
  240.         'V' : Begin { version string }
  241.                 If (gettok(lin,i) <> idstring10) And
  242.                    (gettok(lin,i) <> idstring11) Then abort('Translation ' +
  243.                                      'table version must be ' + idstring10 +
  244.                                      ' or ' + idstring11,7);
  245.               End;
  246.         'D' : Begin { description }
  247.                 descript1 := Copy(lin,i,255);
  248.                 While (descript1 <> '') And ((descript1[1] = ' ') Or
  249.                        (descript1[1] = #9)) Do Delete(descript1,1,1);
  250.                 While (descript1 <> '') And
  251.                       ((descript1[Length(descript1)] = ' ')
  252.                         Or (descript1[Length(descript1)] = #9))
  253.                       Do Delete(descript1,Length(descript1),1);
  254.                 If Length(descript1) > desclen Then
  255.                   Delete(descript1,Succ(desclen),255);
  256.                 While Length(descript1) < desclen Do
  257.                                               descript1 := descript1 + ' ';
  258.               End;
  259.         'T' : Begin { translation pair }
  260.                 froms := gettok(lin,i);
  261.                 tos   := gettok(lin,i);
  262.                 ok := (Length(froms) >= 1) And (Length(froms) <= 3) And
  263.                       (Length(tos) >= 1)   And (Length(tos) <= 3);
  264.                 If ok Then
  265.                 Begin
  266.                   fromval := decoval(froms,ok);
  267.                   If ok Then toval := decoval(tos,ok);
  268.                   If ok then tab1[fromval] := toval;
  269.                 End;
  270.                 If Not ok Then abort('Illegal translation directive ' +
  271.                                       Copy(lin,1,20) + ' in file ' + fname,8);
  272.               End;
  273.         ' ' : ; { ignore empty lines }
  274.         Else abort('Illegal directive ' + Copy(lin,1,20) + ' in file ' +
  275.                    fname,9);
  276.       End;
  277.     End;
  278.     Close(tabf);
  279.     intername := fname;
  280.     descript := descript1;
  281.     table := tab1;
  282.   End;                                                           { loadtable }
  283.  
  284.   Procedure savetable(fname : string);
  285.   { save a translation table to an ASCII table file                          }
  286.     Var i : byte;
  287.   Begin                                                          { savetable }
  288.     intername := fname;
  289.     While (intername <> '') And (Pos(':',intername) > 0) Do
  290.                                   Delete(intername,1,Pos(':',intername));
  291.     While (intername <> '') And (Pos('\',intername) > 0) Do
  292.                                   Delete(intername,1,Pos('\',intername));
  293.     While (intername <> '') And (Pos('.',intername) > 0) Do
  294.                                   Delete(intername,Pos('.',intername),255);
  295.     While Length(intername) < 8 Do intername := intername + ' ';
  296.     Assign(tabf,fname);
  297.     {$I- }
  298.     Rewrite(tabf);
  299.     If IOResult <> 0 Then abort('Cannot open ' + fname + ' for output',12);
  300.     writeln(tabf,'; Translation table for use with ConfXLat');
  301.     writeln(tabf,'; Everything after a '';'' is a comment.');
  302.     writeln(tabf,'; Values are decimal by default, and hexadecimal if ',
  303.                  'preceded by ''x''.');
  304.     writeln(tabf,'V ',idstring10,' ':20,'; version');
  305.     writeln(tabf,'D ',descript,'   ; description (max length: ',desclen,
  306.                  ')');
  307.     writeln(tabf,'; Translation table follows.');
  308.     writeln(tabf,'; Start each row with a ''T''; first value is mapped to ',
  309.                  'second value.');
  310.     writeln(tabf,'; Missing values will be mapped to themselves.');
  311.     For i := 0 To 255 Do writeln(tabf,'T  x',hexbyte(i):2,
  312.                                       ' x',hexbyte(table[i]):2);
  313.     writeln(tabf,'; End of translation table');
  314.     If IOResult <> 0 Then abort('Error writing file ' + fname,12);
  315.     Close(tabf);
  316.     {$I+ }
  317.   End;                                                           { savetable }
  318.  
  319.   Procedure usage;
  320.   { show usage info                                                          }
  321.   Begin                                                              { usage }
  322.     writeln;
  323.     writeln('Transfers Xlat translation tables between COM files and tables');
  324.     writeln('Choose one of four transfer types:');
  325.     writeln('To build a filter/driver using a translation table file:');
  326.     writeln('    xferxlat  xlat1.com xlat2.tbl xlat3.com  [/i]');
  327.     writeln('To build a driver from a filter or vice versa:');
  328.     writeln('    xferxlat  xlat1.com xlat2.com xlat3.com  [/i]');
  329.     writeln('To build a translation table file from a filter/driver:');
  330.     writeln('    xferxlat  xlat1.com xlat3.tbl            [/i]');
  331.     writeln('To build a filter from a filter or a driver from a driver:');
  332.     writeln('    xferxlat  xlat1.com xlat3.com            [/i]');
  333.     writeln('where xlat1 determines the flavour (filter/driver) of xlat3');
  334.     writeln('and   xlat2 determines the contents of the translation.');
  335.     writeln('The optional /i requests inversion of the table.');
  336.     writeln('For the first and third arguments, the .COM extension is ',
  337.             'optional;');
  338.     writeln('for the second argument, the extension determines the type of ',
  339.             'transfer.');
  340.     writeln;
  341.     Halt(1);
  342.   End;                                                               { usage }
  343.  
  344.   Procedure parseargs;
  345.   { parse command line; determine what sort of translation we want           }
  346.  
  347.     Const comext = '.com';
  348.  
  349.     Var temp : string;
  350.         i, k : byte;
  351.  
  352.     Function iscom(fname : string) : boolean;
  353.     { does fname have .COM extension?                                        }
  354.     Begin                                                            { iscom }
  355.       iscom := Pos(comext,fname) > 0;
  356.     End;                                                             { iscom }
  357.  
  358.   Begin                                                          { parseargs }
  359.     fnamep := '';
  360.     fnamet := '';
  361.     fnameo := '';
  362.     doinvert := False;
  363.     For i := 1 To ParamCount Do
  364.     Begin
  365.       temp := ParamStr(i);
  366.       For k := 1 To Length(temp) Do temp[k] := LoCase(temp[k]);
  367.       If (Length(temp) = 2) And (temp[1] In ['-','/']) And (temp[2] = 'i') Then
  368.       Begin
  369.         If doinvert Then usage;
  370.         doinvert := True;
  371.       End
  372.       Else
  373.       Begin
  374.         If fnamep = '' Then
  375.         Begin
  376.           If Not iscom(temp) Then temp := temp + comext;
  377.           fnamep := temp;
  378.         End
  379.         Else
  380.         Begin
  381.           If fnamet = '' Then fnamet := temp
  382.           Else
  383.           Begin
  384.             If fnameo = '' Then
  385.             Begin
  386.               If Not iscom(temp) Then temp := temp + comext;
  387.               fnameo := temp;
  388.             End
  389.             Else usage;
  390.           End;
  391.         End;
  392.       End;
  393.     End;
  394.     If fnamet = '' Then usage;
  395.     If fnameo = '' Then
  396.     Begin
  397.       fnameo := fnamet;
  398.       fnamet := '';
  399.       If iscom(fnameo) Then transtype := 4
  400.                        Else transtype := 3;
  401.     End
  402.     Else
  403.     Begin
  404.       If iscom(fnamet) Then transtype := 2
  405.                        Else transtype := 1;
  406.     End;
  407.   End;                                                           { parseargs }
  408.  
  409.   {$F+ } Procedure myexit; {$F- }
  410.   { exit procedure                                                           }
  411.   Begin                                                             { myexit }
  412.     ExitProc := exitsave;
  413.     writeln(progname,' ',version,' - translation filter/driver transfer');
  414.     writeln(copyright);
  415.     writeln;
  416.     writeln('This programme, and the filters, resident drivers, and tables,');
  417.     writeln('may be used and copied freely.');
  418.     writeln('However, it comes without any guarantees;');
  419.     writeln('the whole risk of its use lies with the user.');
  420.   End;                                                              { myexit }
  421.  
  422. Begin                                                                 { main }
  423.   exitsave := ExitProc;
  424.   ExitProc := @myexit;
  425.   parseargs;
  426.   desclen := 0;
  427.   loadcom(fnamep,True);
  428.   If transtype = 1 Then loadtable(fnamet);
  429.   If transtype = 2 Then loadcom(fnamet,False);
  430.   If doinvert Then
  431.   Begin
  432.     invert;
  433.     descript[Pred(desclen)] := '/';
  434.     descript[desclen] := 'i';
  435.   End;
  436.   If transtype = 3 Then savetable(fnameo)
  437.                    Else savecom(fnameo);
  438. End.
  439.