Metropoli BBS
VIEWER: globals.pas MODE: TEXT (CP437)
{$ifdef tp}
{E+,N+}
{$endif}
{****************************************************************************

                    Copyright (c) 1993,96 by Florian Klaempfl

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

unit globals;

  interface

    uses
       cobjects,dos,strings,objects;

    const
       { version string }
       version = '0.6.2'
{$ifdef tp}
{$else}
       +' 386'
{$endif}
       ;

       { Signifikante ID-Länge }
       maxidlen = 64;
{$ifdef tp}
       maxinputlen = 10000;
{$else}
       { größer sind auch meine größten Quelltexte }
       { nicht                                     }
       maxinputlen = 512*1024;
{$endif}

    type
       { Puffer für die Eingabe}
       tinputbuffer = array[0..maxinputlen] of char;

       pinputbuffer = ^tinputbuffer;

       pinputstack = ^tinputstack;

       tinputstack = record
          filenotatend : boolean;
          f : file;
          buffersize : word;
          inputbuffer : pinputbuffer;
          inputpointer : word;
          filename : pstring;
          line_no : longint;
          next : pinputstack;
       end;

       { Fehlerkonstanten }

       errorconst = (endoffile,
                     dupid,
                     syntax_error,
                     out_of_mem,
                     unknown_id,
                     ill_character,
                     too_long_source,
                     inline_not_supported,
                     near_ignored,
                     far_ignored,
                     interrupt_ignored,
                     priv_meth_not_virtual,
                     const_cannot_priv,
                     dest_cannot_priv,
                     id_not_found,
                     no_local_objects,
                     no_anonym_objects,
                     type_id_expect,
                     id_already_type,
                     type_id_not_defined,
                     error_in_type,
                     statement_expect,
                     error_in_integer,
                     error_in_expression,
                     type_mismatch,
                     too_complex_expr,
                     continue_not_allowed,
                     break_not_allowed,
                     exceptions_not_allowed,
                     invalid_qualifizier,
                     invalid_for_var,
                     ordinal_expect,
                     upper_l_lower,
                     ill_unit_name,
                     malformed_unit,
                     error_reading_unit,
                     rec_unit_def,
                     too_much_units,
                     ill_char_const,
                     overloaded_no_proc,
                     same_parameters,
                     no_para_match,
                     too_much_matches,
                     proc_must_handleexceptions,
                     forward_not_resolved,
                     cannot_open_input,
                     header_dont_match,
                     ill_field,
                     para_too_big,
                     too_much_lexlevel,
                     ill_switch,
                     cannot_open_incfile,
                     type_must_be_rec_or_class,
                     unit_not_found,
                     dup_enum,
                     pointer_expect,
                     not_same_target,
                     type_const_not_possible,
                     double_caselabel,
                     range_check_error,
                     ill_type_cast,
                     class_type_expect,
                     no_overloaded_procvars,
                     cannot_open_asmfile,
                     string_too_long,
                     object_type_expect,
                     method_id_expect,
                     header_dont_match_any_member,
                     take_extended_syntax,
                     file_must_call_by_referenz,
                     string_exceed_line,
                     ill_unit_version,
                     error_in_real,
                     no_paras_2_destructor,
                     fail_only_in_constructor,
                     only_pack_records_,
                     too_much_endifs,
                     endif_expect,
                     var_must_be_referenz,
                     def_only_in_program,
                     overloaded_are_not_both_virtual,
                     ol_meths_not_same_ret,
                     overloaded_support_exceptions_false,
                     dont_call_exported_direct,
                     dont_nest_export,
                     methods_dont_be_export,
                     self_not_in_method,
                     call_by_ref_without_typeconv,
                     typeid_here_not_allowed,
                     class_expected,
                     no_super_class,
                     generic_methods_only_in_methods,
                     there_is_no_super_class,
                     pointer_to_class_expect,
                     member_cd_call_from_method,
                     only_one_destructor,
                     expr_have_to_be_constructor_call,
                     id_no_member,
                     expr_have_to_be_destructor_call,
                     a_error_const,
                     illsettype,
                     illsetexpr,
                     typeconflict_in_set,
                     ill_colon_qualifier,
                     false_with_expr,
                     use_int_div_int_op,
                     cannot_write_unitfile,
                     invalid_record_const,
                     konstrucname_init,
                     destrucname_done,
                     set_element_are_not_comp,
                     ill_label_pos,
                     label_not_found,
                     goto_label_not_support,
                     set_expected,
                     id_is_no_label_id,
                     label_already_defined,
                     label_not_defined,
                     cons_always_obj,
                     asmerror,
                     symbol_not_used,
                     void_function,
                     inefficient_code,
                     unreachable_code,
                     overloaded_must_be_all_global,
                     operator_not_overloaded);

       ttoken = (PLUS,MINUS,STAR,SLASH,EQUAL,GT,LT,LECKKLAMMER,RECKKLAMMER,
                 POINT,COMMA,LKLAMMER,RKLAMMER,COLON,SEMICOLON,CARET,
                 KLAMMERAFFE,ASSIGNMENT,UNEQUAL,LTE,GTE,POINTPOINT,
                 ID,REALNUMBER,_EOF,INTCONST,CSTRING,CCHAR,

                 _ABSOLUTE,_AND,_ARRAY,_ASM,_ASSEMBLER,_BEGIN,
                 _BREAK,_CASE,_CONST,_CONSTRUCTOR,_CONTINUE,
                 _DESTRUCTOR,_DISPOSE,_DIV,_DO,_DOWNTO,_ELSE,_END,
                 _EXIT,_EXPORT,_EXTERNAL,_FAIL,_FALSE,_FAR,{ _FILE,} _FOR,
                 _FORWARD,_FUNCTION,_GOTO,_IF,_IMPLEMENTATION,_IN,
                 _INHERITED,_INLINE,_INTERFACE,_INTERRUPT,
                 _LABEL,_MOD,_NEAR,_NEW,_NIL,_NOT,_OBJECT,
                 _OF,_OTHERWISE,_OR,_PACKED,_PRIVATE,
                 _PROCEDURE,_PROGRAM,_PROTECTED,_PUBLIC,
                 _RECORD,_REPEAT,_SELF,
                 _SET,_SHL,_SHR,_STRING,_THEN,_TO,
                 _TRUE,_TYPE,_UNIT,_UNTIL,
                 _USES,_VAR,_VIRTUAL,_WHILE,_WITH,_XOR,
                 { since Delphi 2 }
                 _CLASS,_EXCEPT,_TRY,_ON,_AS,_IS,
                 { for operator overloading }
                 _OPERATOR
                 );

       tcswitch = (cs_check_overflow,cs_genexceptcode,cs_maxoptimieren,
         cs_omitstackframe,cs_littlesize,cs_optimize,cs_debuginfo,
         cs_compilesystem,cs_rangechecking,cs_warnings,cs_support_goto,
         cs_support_macros,cs_check_unit_name,cs_iocheck,cs_checkconsname);

       tcswitches = set of tcswitch;

       stringid = string[maxidlen];

       pdouble = ^double;

       pbyte = ^byte;

       plongint = ^longint;

       tprocessors = (i386,i486,pentium);

       tcompilerstate = record
          switches : tcswitches;
          exprlevel : byte;
       end;

    var
       inputdir : string[80];
       inputfile : string;
       inputextension : extstr;
       linkresponse : text;
       writeasmfile,quiet : boolean;

       { contains the enviroment variable PPBIN }
       env_ppbin : string;

       initswitches : tcswitches;
       initexprlevel : byte;
       { alignement of records }
       initpackrecords : word;

       { akt. state }
       aktswitches : tcswitches;
       aktexprlevel : byte;
       aktpackrecords : word;

       { Länge der Quelltextes }
       sourcesize : longint;

       unitpath : dirstr;          { Pfad zur PP.EXE um PPU-Dateien   }
                                   { in diesem Verzeichnis suchen zu  }
                                   { koennen                          }
       inputstack : pinputstack;

       abslines : longint;         { Anzahl der wirklich uebersetzten Zeilen }
       exterror : pchar;           { erweiterte Informationen ueber einen Fehler }

       codegeneration : boolean;   { wird auf false gesetzt wenn einfacher   }
                                   { Fehler auftritt und damit keine Ausgabe }
                                   { erfolgen soll                           }

       errorcount : word;          { Anzahl der aufgetretenen Fehler }
{$ifdef TP}
       use_big : boolean;          { true, wenn die "große"-Compilerversion }
                                   { gewählt werden soll, mit EMS-Nutzung   }
       symbolstream : temsstream;  { EMS-Stream, in welchem bei use_big=true  }
                                   { die Symbole abgelegt werden              }
{$endif}
       gendeffile  : boolean;      { true, wenn eine DEF-Datei erzeugt werden soll }
       genpm : boolean;            { true, wenn in DEF-Datei WINDOWAPI angegeben werden soll }
       description : string;       { gibt die Beschreibung in der DEF-Datei an     }
       defdatei : text;            { Textdatei für DEF-Datei }

       errortext : boolean;
       errorfile : text;

       linkofiles : tstringcontainer;
       opt_processors : tprocessors;

       { true, if C styled macros should be allowed }
       support_macros : boolean;

       language : char;

    procedure warning(w : errorconst);
    procedure error(w : errorconst);
    procedure _asm_error(w : errorconst;l : longint);
    procedure fatalerror(w : errorconst);
    procedure internalerror(i : integer);
    function upper(const s : string) : string;
    procedure uppervar(var s : string);
    function tostr(i : longint) : string;
    function tostr_with_plus(i : longint) : string;
    procedure globalsinit;
    function ibm2ascii(const s : string) : string;
    function double2str(d : double) : string;
    procedure setstring(var p : pchar;const s : string);

    function min(a,b : longint) : longint;
    function max(a,b : longint) : longint;

    { sucht Datei mit Namen f in den in path angegebenen Verzeichnissen }
    function search(const f : string;path : string;var b : boolean) : string;

{$ifdef debug}
    { if the pointer don't point to the heap then write an error }
    function assigned(p : pointer) : boolean;
{$endif}

    type
       perrorrec = ^terrorrec;

       terrorrec = record
          data : pstring;
          next : perrorrec;
       end;

    var
       errorlist : perrorrec;

  implementation

  {$ifdef debug}

    function assigned(p : pointer) : boolean;

      var
         lp : longint;

      begin
         lp:=longint(seg(p^))*16+longint(ofs(p^));
         if (lp<>0) and
            ((lp<longint(seg(heaporg^))*16+longint(ofs(heaporg^))) or
            (lp>longint(seg(heapptr^))*16+longint(ofs(heapptr^)))) then
           runerror(230);
         assigned:=lp<>0;
      end;

  {$endif}

    function min(a,b : longint) : longint;

      begin
         if a>b then
           min:=b
         else min:=a;
      end;

    function max(a,b : longint) : longint;

      begin
         if a<b then
           max:=b
         else max:=a;
      end;

    function geterrormsg(i : integer) : string;

      var
         t : text;
         s : string;
         hp : perrorrec;
         last : perrorrec;
         errnr : integer;

      begin
         if errorlist=nil then
           begin
              assign(t,unitpath+'ERROR'+language+'.MSG');
              {$i-}
              reset(t);
              {$i+}
              errnr:=ioresult;
              if errnr<>0 then
                begin
                   case language of
                      'D' : begin
                               if errortext then
                                 begin
                                    writeln(errorfile,'Fehler ',i);
                                    writeln(errorfile,'**** Fehlertextdatei ERRORD.MSG nicht gefunden (Fehler ',
                                      errnr,'). *****');
                                 end
                               else
                                 begin
                                    writeln('Fehler ',i);
                                    writeln('**** Fehlertextdatei ERRORD.MSG nicht gefunden (Fehler ',errnr,'). *****');
                                 end;
                            end;
                      'E' : begin
                               if errortext then
                                 begin
                                    writeln(errorfile,'error ',i);
                                    writeln(errorfile,'**** error file ERRORE.MSG not found (error ',errnr,'). *****');
                                 end
                               else
                                 begin
                                    writeln('error ',i);
                                    writeln('**** error file ERRORE.MSG not found (error ',errnr,'). *****');
                                 end;
                            end;
                   end;
                   halt(1);
                end;
              while not(eof(t)) do
                begin
                   new(hp);
                   hp^.next:=nil;
                   readln(t,s);
                   hp^.data:=stringdup(s);
                   if errorlist=nil then
                     errorlist:=hp
                   else last^.next:=hp;
                   last:=hp;
                end;
              close(t);
           end;
         hp:=errorlist;
         for i:=i downto 1 do
           hp:=hp^.next;
         geterrormsg:=hp^.data^;
      end;

    function ibm2ascii(const s : string) : string;

      var
         i : integer;
         hs : string;
         b : byte;

      begin
         hs:='';
         for i:=1 to length(s) do
           if ((ord(s[i])>127) or (ord(s[i])<32)) or (s[i]='"') then
             begin
                b:=ord(s[i]);
                hs:=hs+'\'+tostr(b div 64);
                b:=b mod 64;
                hs:=hs+tostr(b div 8);
                b:=b mod 8;
                hs:=hs+tostr(b);
                if (i<length(s)) and
                  (ord(s[i+1])>=48) and  (ord(s[i+1])<=57) then
                  hs:=hs+'"'#13#10#9'.ascii "';
             end
           else if s[i]='\' then
             hs:=hs+'\\'
           else hs:=hs+s[i];
         ibm2ascii:=hs;
      end;

    function double2str(d : double) : string;

      var
         hs : string;

      begin
         str(d,hs);
{$ifdef tp}         
         { TP fügt bei positiven Zahlen am Anfang           }
         { ein Leerzeichen ein, dieses in ein '+' umwandeln }
         if hs[1]=' ' then
           hs[1]:='+';
{$endif}
         double2str:='0d'+hs;
      end;

    procedure warning(w : errorconst);

      begin
         if errortext then
           write(errorfile,'?  ',inputstack^.filename^,'(',inputstack^.line_no,'): ',geterrormsg(longint(w)))
         else
           write('?  ',inputstack^.filename^,'(',inputstack^.line_no,'): ',geterrormsg(longint(w)));
         if exterror<>nil then
           begin
              if errortext then
                write(errorfile,' ',exterror)
              else
                write(' ',exterror);
              strdispose(exterror);
              exterror:=nil;
           end;
         if errortext then
           writeln(errorfile)
         else
           writeln;
      end;

    procedure _asm_error(w : errorconst;l : longint);

      begin
         inc(errorcount);
         if errortext then
           write(errorfile,'!  assembler:',inputstack^.filename^,'(',l,'): ',geterrormsg(longint(w)))
         else
           write('!  assembler:',inputstack^.filename^,'(',l,'): ',geterrormsg(longint(w)));
         if exterror<>nil then
           begin
              if errortext then
                write(errorfile,' ',exterror)
              else
                write(' ',exterror);
              strdispose(exterror);
              exterror:=nil;
           end;
         if errortext then
           writeln(errorfile)
         else
           writeln;
         codegeneration:=false;

         { view only 50 errors }
         if errorcount>50 then halt(1);
      end;

    procedure error(w : errorconst);

      begin
         inc(errorcount);
         if errortext then
           write(errorfile,'!  ',inputstack^.filename^,'(',inputstack^.line_no,'): ',geterrormsg(longint(w)))
         else
           write('!  ',inputstack^.filename^,'(',inputstack^.line_no,'): ',geterrormsg(longint(w)));
         if exterror<>nil then
           begin
              if errortext then
                write(errorfile,' ',exterror)
              else
                write(' ',exterror);
              strdispose(exterror);
              exterror:=nil;
           end;
         if errortext then
           writeln(errorfile)
         else
           writeln;
         codegeneration:=false;

         { view only 50 errors }
         if errorcount>50 then halt(1);
      end;

    procedure fatalerror(w : errorconst);

      begin
         if errortext then
           write(errorfile,'!! ',inputstack^.filename^,'(',inputstack^.line_no,'): ',geterrormsg(longint(w)))
         else
           write('!! ',inputstack^.filename^,'(',inputstack^.line_no,'): ',geterrormsg(longint(w)));
         if exterror<>nil then
           begin
              if errortext then
                write(errorfile,' ',exterror)
              else
                write(' ',exterror);
              strdispose(exterror);
              exterror:=nil;
           end;
         if errortext then
           writeln(errorfile)
         else
           writeln;
         halt(1);
      end;

    procedure internalerror(i : integer);

      begin
         if not(quiet) then writeln;
         if errortext then
           writeln(errorfile,'#  ',inputstack^.filename^,'(',inputstack^.line_no,'): Interner Fehler ',i)
         else
           writeln('#  ',inputstack^.filename^,'(',inputstack^.line_no,'): Interner Fehler ',i);
         halt(1);
      end;

    function upper(const s : string) : string;

      var i : integer;
          hs : string;

      begin
         hs:='';
         for i:=1 to length(s) do
  	   hs:=hs+upcase(s[i]);
  	 upper:=hs;
      end;

    procedure uppervar(var s : string);

      var
         i : integer;

      begin
         for i:=1 to length(s) do
           s[i]:=upcase(s[i]);
      end;

   function tostr(i : longint) : string;

     var hs : string;

     begin
        str(i,hs);
        tostr:=hs;
     end;

   function tostr_with_plus(i : longint) : string;

     var hs : string;

     begin
        str(i,hs);
        if i>=0 then
          tostr_with_plus:='+'+hs
        else
          tostr_with_plus:=hs;
     end;

   procedure setstring(var p : pchar;const s : string);

     begin
{$ifdef TP}
        if use_big then
          begin
              p:=pchar(symbolstream.size);
              symbolstream.seek(longint(p));
             symbolstream.writestr(@s);
          end
        else
{$endif TP}
          p:=strpnew(s);
     end;

   function search(const f : string;path : string;var b : boolean) : string;

     var
        dirinfo : searchrec;
        singlepasstring : string;
        start,pos : byte;

     begin
        start:=1;
        b:=true;
        repeat
          pos:=system.pos(';',path);
          if pos=0 then
            pos:=length(path)+1;
          singlepasstring:=copy(path,start,pos-start);
          delete(path,start,pos-start+1);
          findfirst(singlepasstring+'\'+f,anyfile,dirinfo);
          if doserror=0 then
            begin
               search:=singlepasstring+'\';
               exit;
            end;
        until path='';
        b:=false;
     end;

   procedure globalsinit;

     begin
        { set global (for any file) compiler switches }
        opt_processors:=i386;
        writeasmfile:=false;
        quiet:=true;
        errortext:=false;
        language:='E';
        gendeffile:=false;
        genpm:=false;
        description:='compiled by FPKPascal';

        { set the local switches informations }
        initswitches:=[cs_warnings,cs_genexceptcode,cs_check_unit_name];
        initexprlevel:=1;
        initpackrecords:=2;

        { statistic value }
        abslines:=1;
{$ifdef tp}
        use_big:=false;
{$endif tp}
        { init container for files to link }
        linkofiles.init;
        linkofiles.doubles:=false;

        { error management }
        { pointer to error msgs }
        errorlist:=nil;
        { extended error description }
        exterror:=nil;
        { count of errors }
        errorcount:=0;
        { true, if no compiler error }
        codegeneration:=true;
     end;

end.
[ RETURN TO DIRECTORY ]