Metropoli BBS
VIEWER: pp.pas MODE: TEXT (CP437)
{****************************************************************************

                   Copyright (c) 1993,96 by Florian Klaempfl

 ****************************************************************************}

{$ifdef tp}
{$M 38000,16384,32000}
{E+,N+}
{$endif}

program pp;

  uses
     globals,systems,parser,dos,scanner,asmgen,symtable,
{$ifdef tp}
     objects,
{$endif}
     tree;

  const
     copyright = 'Copyright (c) 1993,96 by FP Klaempfl';

{$ifdef inc_date}
     released = {$I C:\PASDATE.INC}; { released sollte ein String mit     }
                                     { dem aktuellen Datum sein,          }
                                     { bei mir wird PASDATE.INC jeden Tag }
                                     { neu in der AUTOEXEC.BAT erzeugt    }
{$endif}

  procedure error(const s : string);

    begin
       case language of
          'D' : writeln('Fehler: ',s);
          'E' : writeln('error: ',s);
       end;
       halt(1);
    end;

  procedure init;

    var
       s,opts : string;
       p : pathstr;
       d : dirstr;
       n : namestr;
       i,j : integer;
       resf : text;
       res,endofparas : boolean;

    procedure illparas;

      begin
         case language of
            'D' : begin
                     write('Illegaler Parameter: ',opts);
                     writeln('  Aufruf mit -? gibt Liste der Optionen aus');
                  end;
            'E' : begin
                     write('illegal parameter: ',opts);
                     writeln('  -? writes help pages');
                  end;
         end;
         halt(1);
      end;

    procedure printhilfe_d;

      var
         s : string;

      begin
{$ifdef tp}
         writeln('PPC [Optionen] <inputfile> [Optionen]');
{$else}
         writeln('PPC386 [Optionen] <inputfile> [Optionen]');
{$endif}
         writeln('  + schaltet eine Option ein, - ab');
         writeln('  mit * markierte Optionen haben momentan keine Wirkung');
         writeln('  mit ! markierte Optionen nur teilweise implementiert');
         writeln('  -a+   Ausgabe einer Assemblerdatei und benutzt externen Assembler');
{$ifdef tp}         
         writeln('  -b+   Der Compiler benutzt EMS => geringere Geschwindigkeit');
{$endif}         
         writeln('* -B    Browseroptionen');
         writeln('           * -Ba alle Informationen');
         writeln('           * -Bg globale Informationen');
         writeln('           * -Bl lokale Informationen');
         writeln('  -C     Codegeneratoroptionen');
         writeln('           * -Ca automatischer Aufruf von Kon- und Destruktoren');
         writeln('           * -Ce es werden keine Laufzeit-Fehler generiert,');
         writeln('                 sondern stattdessen Exceptions erzeugt');
         writeln('             -Chxxxx  xxxx gibt die maximale Heapgröße in Bytes an ');
         writeln('                 (muß kleiner 67107840 und größer 1023 sein; 4000000 Default)');
         writeln('             -Ci Ein-,Ausgabeüberprüfung');
         writeln('             -Co testet auf Überläufe bei Integer-Operationen');
         writeln('             -Cr Test auf Bereichsüberschreitungen');
         writeln('             -Csxxxx gibt die maximale Stackgröße in Bytes an (nur OS/2)');
         writeln('                 (muß kleiner 67107840 und größer 1023 sein; 8096 Default)');
         writeln('             -C3 Optimierung für i386');
         writeln('             -C4 Optimierung für i486');
         writeln('  -dxxx  definiert das Symbol xxx');
{$ifdef tp}
{$else}
         writeln;
{$endif}
         write('*** Weiter mit Return. ***');
         readln(s);
         writeln('             -C5 Optimierung für Pentium');
         writeln('  -D     steuert die Erzeugung einer DEF-Datei unter OS/2');
         writeln('             -Ddxxxx xxxx ist Beschreibung');
         writeln('             -Do erzeuge DEF-Datei');
         writeln('             -Dw PM-Anwendung');
         writeln('  -g     Es werden Debuggerinformationen erzeugt');
         writeln('  -F     leitet Ausgaben um');
         writeln('             -Fexxxx leitet Fehlermeldungen nach xxxx um');
         writeln('  -L     Sprache');
         writeln('             -LD Deutsch');
         writeln('             -LE Englisch');
         writeln('  -l     Ausgabe des Programmlogos');
         writeln('  -i     Programminformation');
         writeln;
         writeln('  -O     Optimiereroptionen');
         writeln('             -Oa einfache Optimierungen');
         writeln('             -Og Optimierung auf Größe');
         writeln('             -OG Optimierung auf Geschwindigkeit');
         writeln('             -Ox maximale Optimierung');
         writeln('  -q-    Der Compiler zeigt die Fortschritte beim Übersetzen an');
         writeln('  -S     Syntaxoptionen');
         writeln('             -Sa Einstellung der Ausdruckbehandlung');
         writeln('                 eine höheres Level schließt die unteren ein');
         writeln('                 -Sa0 nur ANSI-Pascalausdrücke erlaubt');
         write('*** Weiter mit Return. ***');
         readln(s);
         writeln('                 -Sa1 Funktionsresultate muessen nicht zugewiesen werden');
         writeln('                 -Sa2 @-Operator liefert einen typisierten Pointer');
         writeln('                 -Sa4 typisierte Zuweisungsrückgabewerte');
         writeln('                 -Sa9 auch seiteneffektlose Ausdrücke erlaubt');
         writeln('             -Sg die Verwendung von LABEL und GOTO ist erlaubt');
         writeln('             -Sm Makros wie in C werden unterstützt');
         writeln('             -Sn keine Exceptionunterstützung');
         writeln('             -Ss der Name von Konstruktoren muß immer init sein');
         writeln('                 der Name von Destruktoren muß immer done sein');
         writeln('  -T     Zielbetriebssystem');
         writeln('             -TDOS DOS-Extender von DJ Delorie');
         writeln('             -TOS2 OS/2');
         writeln('          !  -TLINUX Linux');
         writeln('          !  -TWin32 Windows 32 Bit');
         writeln('  -U     Unit-Optionen');
         writeln('             -Un der Name der Unit wird nicht überprüft');
         writeln('             -Us eine System-Unit wird übersetzt');
         writeln('  -h,-?  zeigt diesen Hilfebildschirm');
         halt(1);
      end;

    procedure printhilfe_e;

      var
         s : string;

      begin
{$ifdef tp}
         writeln('PPC [options] <inputfile> [options]');
{$else}
         writeln('PPC386 [options] <inputfile> [options]');
{$endif}
         writeln('  + switch option on, - off');
         writeln('  with * marked options have no effect');
         writeln('  with ! marked options are only partial implemented');
         writeln('  -a+   generate asm file and uses AS.EXE to assemble');
{$ifdef tp}
         writeln('  -b+   use EMS');
{$endif}
         writeln('* -B    browser options');
         writeln('           * -Ba ');
         writeln('           * -Bg ');
         writeln('           * -Bl ');
         writeln('  -C     code generation options');
         writeln('           * -Ca ');
         writeln('           * -Ce ');
         writeln('                 ');
         writeln('             -Chxxxx  xxxx bytes heap ');
         writeln('                 (must be less than 67107840 und greater than 1023');
         writeln('             -Ci IO-checking');
         writeln('             -Co check overflow of integer operations');
         writeln('             -Cr range checking');
         writeln('             -Csxxxx stack size (only OS/2)');
         writeln('             ');
         writeln('             -C3 optimize for i386');
         writeln('             -C4 optimize for i486');
         writeln('  -dxxx  defines the symbol xxx');
{$ifdef tp}
{$else}
         writeln;
{$endif}
         write('*** press return ***');
         readln(s);
         writeln('             -C5 optimizations for pentium (tm)');
         writeln('  -D     controlls the generation of DEF file (only OS/2)');
         writeln('             -Ddxxxx xxxx is the description');
         writeln('             -Do generate DEF file');
         writeln('             -Dw PM application');
         writeln('  -g     generate debugger informations');
         writeln('  -F     redirect output');
         writeln('             -Fexxxx redirect error output to xxxx');
         writeln('  -L     set language');
         writeln('             -LD german');
         writeln('             -LE english');
         writeln('  -l     write logo');
         writeln('  -i     information');
         writeln;
         writeln('  -O     optimizations');
         writeln('             -Oa simple o');
         writeln('             -Og optimize for size');
         writeln('             -OG optimize for time');
         writeln('             -Ox optimize max');
         writeln('  -q-    write some information when compiling');
         writeln('  -S     syntax options');
         writeln('             -Sa semantic check of expressions');
         writeln('                 a higher level includes the lower');
         writeln('                 -Sa0 only ANSI pascal expressions are allowed');
         write('*** press return ***');
         readln(s);
         writeln('                 -Sa1 functions results havn''t to be assigned to variables');
         writeln('                 -Sa2 @-operator returns typed pointer');
         writeln('                 -Sa4 assigment results are typed (allows a:=b:=0)');
         writeln('                 -Sa9 allows expressions with no side effect');
         writeln('             -Sg allows LABEL and GOTO');
         writeln('             -Sm support macros like C');
         writeln('             -Sn no exception support');
         writeln('             -Ss the name of constructors must be init');
         writeln('                 the name of destructors must be done');
         writeln('  -T     target operating system');
         writeln('             -TDOS DOS extender by DJ Delorie');
         writeln('             -TOS2 OS/2 2.x');
         writeln('          !  -TLINUX Linux');
         writeln('          !  -TWin32 Windows 32 Bit');
         writeln('  -U     unit options');
         writeln('             -Un don''t check the unit name');
         writeln('             -Us compile a system unit');
         writeln('  -h,-?  shows this help');
         halt(1);
      end;

    procedure getparastring;

      begin
         endofparas:=false;
         if res then
           begin
              readln(resf,opts);
              if eof(resf) then
                begin
                   close(resf);
                   res:=false;
                end
           end
         else
           begin
              if i<paramcount then
                begin
                   inc(i);
                   if i=paramcount then
                     endofparas:=true;
                   opts:=paramstr(i);
                   if opts[1]='@' then
                     begin
                        res:=true;
                        assign(resf,copy(opts,2,length(opts)-1));
                        reset(resf);
                        getparastring;
                     end;
                end;
           end;
      end;

    procedure info_d;

      begin
         writeln('FPKPascal  Version ',version,'    ',copyright);
{$ifdef inc_date}
         writeln('Freigegeben am: ',released);
{$endif}
         writeln('Compiler: FP Klämpfl');
         writeln('Runtime-Library: FP Klämpfl und MH Spiegel');
         {writeln('Editor:                      **********');}
         writeln('Dieses Programm darf verwenden, verändert und weiter-');
         writeln('gegebenwerden, solange daraus niemand finanzielle Vorteile');
         writeln('entstehen. Beim Weitergeben darf eine Kopiergebühr');
         writeln('von maximal 15 DM verlangt werden (inkl. aller dazu-');
         writeln('gehörigen Leistungen wie Datenträger...)');
         writeln('Sollte das Programm kommerziell eingesetzt werden,');
         writeln('so ist mit mir zwecks Lizenzgebühren Verbindung');
         writeln('aufzunehmen. Adresse siehe unten');
         writeln('Wenn Sie im Programm einen Fehler entdecken oder ');
         writeln('Verbesserungsvorschläge haben, so informieren Sie');
         writeln('bitte mich (Fehler bitte mit Angabe der Compiler-');
         writeln('version und problematischem Quelltext):');
         writeln;
         writeln('              Florian Klämpfl');
         writeln('              Feldstr. 4');
         writeln('        91096 Möhrendorf');
         writeln('              Deutschland');
         writeln;
         writeln('	  EMail: fnklaemp@cip.ft.uni-erlangen.de');
         halt(1);
      end;

    procedure info_e;

      begin
         writeln('FPKPascal  Version ',version,'    ',copyright);
         writeln;
         writeln('This program can be modified, used and distributed');
         writeln('if noboby gets money. A donation for copying of');
         writeln('10$ is allowed. Commercial use is not allowed.');
         writeln;
         writeln('Report bugs,suggestions etc to:');
         writeln('	  fnklaemp@cip.ft.uni-erlangen.de');
         halt(1);
      end;

    procedure setbool(var b : boolean);

      begin
         if length(opts)=2 then b:=true
         else if length(opts)=3 then
            begin
               if opts[3]='+' then b:=true
               else if opts[3]='-' then b:=false
               else illparas;
            end
         else illparas;
      end;

    var
       code : word;
       hs : string;
       as_res : text;
       mac : pmacrosym;

    begin
       res:=false;
       i:=0;
       p:='';
       if paramcount=0 then
         case language of
            'D' : printhilfe_d;
            'E' : printhilfe_e;
         end;
       endofparas:=false;
       while not(endofparas) do
         begin
            getparastring;
            if (opts[1]='-') then
              begin
                 case opts[2] of
                    'h','?' : if length(opts)=2 then
                                case language of
                                   'D' : printhilfe_d;
                                   'E' : printhilfe_e;
                                end;
                    'a'     : setbool(writeasmfile);
{$ifdef tp}
                    'b'     : setbool(use_big);
{$endif}
                    'B'     : begin
                                 for j:=3 to length(opts) do
                                 case opts[j] of
                                     'a' : ;
                                     'g' : ;
                                     'l' : ;
                                     else illparas;
                                 end;
                              end;
                    'C'     : begin
                                 for j:=3 to length(opts) do
                                 case opts[j] of
                                     'a' : ;
                                     'e' : ;
                                     'h' : begin
                                              val(copy(opts,j+1,length(opts)-j),heapsize,code);
                                              if (code<>0) or (heapsize>=67107840) or
                                                (heapsize<1024) then
                                                illparas;
                                              break;
                                           end;
                                     'i' : initswitches:=initswitches+[cs_iocheck];
                                     'o' : initswitches:=initswitches+[cs_check_overflow];
                                     'r' : initswitches:=initswitches+[cs_rangechecking];
                                     's' : begin
                                              val(copy(opts,j+1,length(opts)-j),stacksize,code);
                                              if (code<>0) or (stacksize>=67107840) or
                                                (stacksize<1024) then
                                                illparas;
                                              break;
                                           end;
                                     '3' : opt_processors:=i386;
                                     '4' : opt_processors:=i486;
                                     '5' : opt_processors:=pentium;
                                     else illparas;
                                 end;
                              end;
                    'd'     : begin
                                 mac:=new(pmacrosym,init(copy(opts,3,255)));
                                 mac^.defined:=true;
                                 macros^.insert(mac);
                              end;
                    'D'     : begin
                                 for j:=3 to length(opts) do
                                 case opts[j] of
                                     'd' : begin
                                              description:=copy(opts,j+1,length(opts)-j);
                                              break;
                                           end;
                                     'o' : gendeffile:=true;
                                     'w' : genpm:=true;
                                     else illparas;
                                 end;
                              end;
                    'F'     : begin
                                 for j:=3 to length(opts) do
                                   case opts[j] of
                                      'e' : begin
                                               errortext:=true;
                                               assign(errorfile,
                                                 copy(opts,j+1,length(s)-j));
                                               {$I-}
                                               rewrite(errorfile);
                                               {$I+}
                                               if ioresult<>0 then
                                                 error('Fehlerlogdatei kann nicht geöffnet werden');
                                               break;
                                            end;
                                    else illparas;
                                 end;
                              end;
                    'g'     : initswitches:=initswitches+[cs_debuginfo];
                    'i'     : case language of
                                 'D' : info_d;
                                 'E' : info_e;
                              end;

                    'l'     : begin
                                 if length(opts)<>2 then
                                   illparas;
                                 write('FPKPascal  Version ',version);
{$ifdef inc_date}
                                 case language of
                                    'D' : write(' vom ',released);
                                    'E' : write(' of ',released);
                                 end;
{$endif}
                                 writeln;
                                 writeln(copyright);
                              end;
                    'L'     : begin
                                 if length(opts)<>3 then
                                   illparas;
                                 case opts[3] of
                                    'E' : language:='E';
                                    'D' : language:='D';
                                    else illparas;
                                 end
                              end;
                    'q'     : setbool(quiet);
                    'O'     : begin
                                 for j:=3 to length(opts) do
                                 case opts[j] of
                                    'a' : initswitches:=initswitches+[cs_optimize];
                                    'g' : initswitches:=initswitches+[cs_littlesize];
                                    'G' : initswitches:=initswitches-[cs_littlesize];
                                    'x' : initswitches:=initswitches+[cs_optimize,
                                            cs_maxoptimieren];
                                    else illparas;
                                 end;
                              end;
                    'S'     : begin
                                 for j:=3 to length(opts) do
                                   case opts[j] of
                                     'a' : begin
                                              if j<length(opts) then inc(j)
                                                else illparas;
                                              val(opts[j],initexprlevel,code);
                                              if code<>0 then
                                                illparas;
                                           end;
                                     'g' : initswitches:=initswitches+[cs_support_goto];
                                     'm' : initswitches:=initswitches+[cs_support_macros];
                                     'n' : initswitches:=initswitches-[cs_genexceptcode];
                                     's' : initswitches:=initswitches+[cs_checkconsname];
                                     else illparas;
                                   end;
                              end;
                    'T'     : begin
                                 hs:='';
                                 hs:=copy(opts,3,length(opts)-2);
                                 if not(set_string_target(hs)) then
                                   illparas;
                              end;
                    'U'     : begin
                                 for j:=3 to length(opts) do
                                   case opts[j] of
                                     's' : initswitches:=initswitches+[cs_compilesystem];
                                     'n' : initswitches:=initswitches+[cs_check_unit_name];
                                     else illparas;
                                   end;
                              end;
                    else illparas;
                 end
              end
            else if opts[1]='@' then
              begin
                 case language of
                    'D' : writeln('Response-Dateiangaben in Response-Dateien werden nicht unterstützt');
                    'E' : writeln('nested response files are not supported');
                 end;
                 halt(1);
              end
            else
              begin
                 if length(p)<>0 then
                   case language of
                      'D' : error('Es kann nur eine Quelldatei angegeben werden');
                      'E' : error('Only one source file supported');
                   end;
                 p:=opts;
              end;
         end;
       if p='' then
         case language of
            'D' : error('Keine Quelldatei angegeben');
            'E' : error('No source file name in command line');
         end;
       p:=upper(p);
       fsplit(p,d,n,inputextension);
       if inputextension='' then inputextension:='.PP';

       inputfile:=n;
       inputdir:=d;
       if gendeffile then
         begin
            if target_info.target<>target_OS2 then
              case language of
                 'D' : error('DEF-Datei kann nur für OS/2 erzeugt werden');
                 'E' : error('DEF file can be created only for OS/2');
              end;
            assign(defdatei,inputdir+inputfile+'.DEF');
            {$I-}
            rewrite(defdatei);
            {$I+}
            if ioresult<>0 then
              case language of
                 'D' : error('DEF-Datei kann nicht erzeugt werden');
                 'E' : error('DEF file can''t be created');
              end;
            write(defdatei,'NAME '+inputfile);
            if genpm then
              write(defdatei,' WINDOWAPI');
            writeln(defdatei,#13#10#13#10'PROTMODE'#13#10);
            writeln(defdatei,'DESCRIPTION '+''''+description+''''#13#10);
            writeln(defdatei,'DATA'#9'MULTIPLE'#13#10);
            writeln(defdatei,'STACKSIZE'#9+tostr(stacksize));
            writeln(defdatei,'HEAPSIZE'#9+tostr(heapsize)+#13#10);
            write(defdatei,'EXPORTS');
         end;
    end;

  function getrealtime : real;

    var
       h,m,s,s100 : word;

    begin
       gettime(h,m,s,s100);
       getrealtime:=h*3600.0+m*60.0+s+s100/100.0;
    end;

  var
     starttime : single;
     data_size : longint;
     hs1 : namestr;
     hs2 : extstr;
     start : real;
     oldexit : pointer;

  procedure myexit;far;

    begin
       if gendeffile then
         close(defdatei);
       { Fehlerdatei schließen }
       if errortext then
         close(errorfile);
{$ifdef tp}
       if use_big then
         symbolstream.done;
       if (erroraddr<>nil) then
         case exitcode of
            203 : begin
                     erroraddr:=nil;
                     case language of
                        'D' : writeln('Nicht genügend Speicher');
                        'E' : writeln('Out of memory');
                     end;
                  end;
            202 : begin
                     erroraddr:=nil;
                     case language of
                        'D' : writeln('Stacküberlauf');
                        'E' : writeln('Stack overflow');
                     end;
                  end;
         end;
{$endif}
       exitproc:=oldexit;
    end;

{$ifdef tp}
  procedure do_streamerror;far;

    begin
       if symbolstream.status=-2 then
         case language of
            'D' : writeln('Nicht genügend EMS-Speicher');
            'E' : writeln('Not enough EMS memory');
         end
       else
         case language of
            'D' : writeln('Fehler ',symbolstream.status,' bei der Nutzung von EMS');
            'E' : writeln('error ',symbolstream.status,' when using EMS');
         end;
       halt(1);
    end;
{$endif}

  var
    hs3 : string;
    i : longint;

begin
   start:=getrealtime;
   hs3:=paramstr(0);
{$ifdef tp}
{$else}
   for i:=1 to length(hs3) do
     if hs3[i]='/' then
       hs3[i]:='\';
{$endif}
   env_ppbin:=getenv('PPBIN');
   if not(env_ppbin[length(env_ppbin)]='\') then
     env_ppbin:=env_ppbin+'\';
   fsplit(hs3,unitpath,hs1,hs2);
   { einige Units initialisieren }
   { inits only node management }
   init_tree;
   globalsinit;

   init_symtable;


   { call  *** after ***  init_symtable because macros must be init... }
   init;
{$ifdef tp}
   if use_big then
     begin
        streamerror:=@do_streamerror;
        symbolstream.init(10000,4000000);
        if symbolstream.errorinfo=stiniterror then
          do_streamerror;
        { Kein String darf die Position 0 haben, da dies ein nil-Pointer ist }
        { also irgendetwas schreiben: }
        symbolstream.writestr(@inputfile);
     end;
{$endif}
   oldexit:=exitproc;
   exitproc:=@myexit;

   if not quiet then
     begin
        writeln(hs3);
        writeln(inputdir+inputfile+inputextension);
     end;
   initscanner(inputdir+inputfile+inputextension);
   asmgeninit;

   compile('','');
   if not(quiet) then
     begin
        if codegeneration then
          begin
             if writeasmfile then
               case language of
                  'D' : write(asmlines,' Zeilen erzeugt, ');
                  'E' : write(asmlines,' lines generated, ');
               end;

             case language of
                'D' : write(abslines,' Zeilen übersetzt, ');
                'E' : write(abslines,' lines compiled, ');
             end;
{$ifdef tp}
             writeln(getrealtime-start:0:1,'s');
{$else}
             writeln(getrealtime-start,'s');
{$endif}
          end;
     end;
   halt(0);
end.
[ RETURN TO DIRECTORY ]