function bad(FileName,trace);
% function bad(FileName,trace) basic dsp compiler for the 
% Texas Instruments DSP
% FileName : Name of the basic DSP program
% trace    : 0 (quiet mode) or 1 (verbose mode)
%
% This program is under the GNU licence. You are allowed to use it,
% but not to modify it. If you have any question, comment or bug 
% report, please send an email to f.auger@ieee.org
% Contributions are also welcome.

% (c) F. Auger, june 1999

BadVersion=0.1;                % Version of the bad compiler
fprintf('Basic DSP compiler version %3.1f, ', BadVersion);
fprintf('F. Auger, 1999\n\n');

if (nargin==0),
 FileName = input('Name of the .bad file : ','s');
 trace=0; 
elseif (nargin==1), 
 trace=0; 
end;

Instructions=badfread(FileName,trace);                               % read the basic program file
if length(Instructions)==0, return; end;

% Because the end of a comment is the cariage return char,
% the compiler reads the instructions line by line.

CharNum=1; 
[InstructionsLine,CharNum,Continue]=badxline(Instructions,CharNum);

if strcmp(InstructionsLine(1:8),'dspbasic')==0,                      % the first instruction should start with 'DSPBASIC'
 fprintf('error while reading file %s\n', FileName);                 % followed by the name of the compiling function
 fprintf('in the line /%s/\n',InstructionsLine);
 fprintf('the program should start by DspBasic\n');
 return
end;

CompilerName=InstructionsLine(9:length(InstructionsLine));           % search the name of the compiling function
CompilerNameLength=length(CompilerName);

if CompilerNameLength==0,
 fprintf('error while reading file %s\n', FileName);
 fprintf('in the line /%s/\n',InstructionsLine);
 fprintf('there is no compiling function\n');
 return
end;

while double(CompilerName(1))==32,
 CompilerName=CompilerName(2:CompilerNameLength);
 CompilerNameLength=length(CompilerName);
end;

if trace,
 fprintf('This program will call %s \n',CompilerName);
end;

if trace, fprintf('Opening %s.cst\n',FileName); end;                 % open the .cst file, and see if everything's fine
[CstFid,OpeningMessage]=fopen([FileName, '.cst'],'w');
if CstFid<0,
 fprintf('error when opening the file %s.cst\n',FileName);
 fprintf('%s\n',OpeningMessage);
 return
end;

if trace, fprintf('Opening %s.var\n',FileName); end;                 % open the .var file, and see if everything's fine
[VarFid,OpeningMessage]=fopen([FileName, '.var'],'w');
if VarFid<0,
 fprintf('error when opening the file %s.var\n',FileName);
 fprintf('%s\n',OpeningMessage);
 return
end;

if trace, fprintf('Opening %s.vad\n',FileName); end;                 % open the .vad file, and see if everything's fine
[VadFid,OpeningMessage]=fopen([FileName, '.vad'],'w');
if VadFid<0,
 fprintf('error when opening the file %s.vad\n',FileName);
 fprintf('%s\n',OpeningMessage);
 return
end;

if trace, fprintf('Opening %s.prg\n',FileName); end;                 % open the .prg file, and see if everything's fine
[PrgFid,OpeningMessage]=fopen([FileName, '.prg'],'w');
if PrgFid<0,
 fprintf('error when opening the file %s.prg\n',FileName);
 fprintf('%s\n',OpeningMessage);
 return
end;

Fids=[CstFid VarFid VadFid PrgFid];

if strcmp(CompilerName,'c31dsk'),
 [ConstList,FVarList,IVarList,LabelList]=c31dsk(1,Fids);             % first, call the compiling function so as to initialize it
 Continue=1;                                                         % true heart of the compiler
 while Continue,
  [InstructionsLine,CharNum,Continue]=badxline(Instructions,CharNum);
  if Continue,
   [ConstList,FVarList,IVarList,LabelList]=c31dsk(2,Fids,InstructionsLine,...
                                                  ConstList,FVarList,IVarList,LabelList);
   if trace, fprintf('line /%s/ extracted\n',InstructionsLine); end;
  end;
 end;
 c31dsk(3,Fids);                                                     % finally, call the compiling function once again
else
 fprintf('Unknown CompilerName %s\n', CompilerName);
 return
end;


if trace, fprintf('Closing %s.cst\n',FileName); end;                 % Closing the .cst file
ClosingFileStatus=fclose(CstFid);
if ClosingFileStatus==-1,
 fprintf('Error when closing %s.cst\n', FileName);
end;

if trace, fprintf('Closing %s.var\n',FileName); end;                 % Closing the .var file
ClosingFileStatus=fclose(VarFid);
if ClosingFileStatus==-1,
 fprintf('Error when closing %s.var\n', FileName);
end;

if trace, fprintf('Closing %s.vad\n',FileName); end;                 % Closing the .vad file
ClosingFileStatus=fclose(VadFid);
if ClosingFileStatus==-1,
 fprintf('Error when closing %s.vad\n', FileName);
end;


if trace, fprintf('Closing %s.prg\n',FileName); end;                 % Closing the .prg file
ClosingFileStatus=fclose(PrgFid);
if ClosingFileStatus==-1,
 fprintf('Error when closing %s.prg\n', FileName);
end;

% end of compilation : generate the .asm file

%open the .asm file, and see if everything's fine
if trace, fprintf('Opening %s.asm\n',FileName); end;
[AsmFid,OpeningMessage]=fopen([FileName, '.asm'],'w');
if AsmFid<0,
 fprintf('error when opening the file %s.asm\n',FileName);
 fprintf('%s\n',OpeningMessage);
 return
end;

% first lines of the .asm file
% I hope that this works for every compiler
Date= clock;
fprintf(AsmFid, '; File %s.asm\r\n',FileName);
fprintf(AsmFid, '; generated by the Basic DSP compiler Ver %4.2f\r\n', BadVersion);
fprintf(AsmFid, '; %i/%i/%i, %i:%i:%4.2f\r\n', Date(1),Date(2),Date(3),Date(4),Date(5),Date(6));
fprintf(AsmFid, '\r\n');

% put the .cst file in the .asm file, and delete the .cst file
[CstFid,OpeningMessage]=fopen([FileName, '.cst'],'r');
fwrite(AsmFid, fread(CstFid)); fclose(CstFid);
delete([FileName, '.cst']);

% put the .var file in the .asm file, and delete the .var file
[VarFid,OpeningMessage]=fopen([FileName, '.var'],'r');
fwrite(AsmFid, fread(VarFid)); fclose(VarFid);
delete([FileName, '.var']);

% put the .vad file in the .asm file, and delete the .vad file
[VadFid,OpeningMessage]=fopen([FileName, '.vad'],'r');
fwrite(AsmFid, fread(VadFid)); fclose(VadFid);
delete([FileName, '.vad']);

% put the .prg file in the .asm file, and delete the .prg file
[PrgFid,OpeningMessage]=fopen([FileName, '.prg'],'r');
fwrite(AsmFid, fread(PrgFid)); fclose(PrgFid);
delete([FileName, '.prg']);

if trace, fprintf('Closing %s.asm\n',FileName); end;                 % close the .asm file
ClosingFileStatus=fclose(AsmFid);
if ClosingFileStatus==-1,
 fprintf('Error when closing %s.asm\n', FileName);
end;

if exist('callasm.txt','file')                                       % run the assembler ?
 fprintf('Calling the assembler with the callasm.txt parameters\n');
 [AsmIdentifier,OpeningMessage]=fopen('callasm.txt','r');
 if AsmIdentifier<0,
  fprintf('error when opening the file callasm.txt\n');
  fprintf('The file does probably not exist.\n');
  fprintf('%s\n',OpeningMessage);
 end;
 AsmParameters=lower(char(fread(AsmIdentifier)));
 ClosingFileStatus=fclose(AsmIdentifier);
 if ClosingFileStatus==-1,
  fprintf('Error when closing the Basic Dsp Program file.\n'); 
 end;
 AsmIndex=1; 
 [AsmLocation,AsmIndex,Continue]=badxline(AsmParameters,AsmIndex);   % read the location of the assembler
 if Continue,
  [AsmOptions,AsmIndex,Continue]=badxline(AsmParameters,AsmIndex);   % optional parameters
 else
  AsmOptions='';
 end;
 dos([AsmLocation' , ' ', FileName, '.asm ', AsmOptions' ]);  % run the assembler
end;


% well, it's finished. Good bye !
