⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cc2.pas

📁 C,C++ To Delphi转换器 C,C++ To Delphi转换器
💻 PAS
字号:
Unit CC2;
(*
** Small-C Compiler -- Part 2 -- Front End and Miscellaneous.
** Copyright 1982, 1983, 1985, 1988 J. E. Hendrix
** All rights reserved.
*)
Interface

uses
 CLIB,CC;

(********************** input functions **********************)
procedure preprocess;
procedure keepch(c:char);
procedure ifline;
procedure _inline;
function inbyte:char;

(********************* scanning functions ********************)

(*
** test if next input string is legal symbol name
*)
function symname(sname:pchar):boolean;
procedure need(str:pchar);
procedure ns;
function match(lit:pchar):boolean;
function streq(str1,str2:pchar):integer;
function amatch(lit:pchar; len:integer):boolean;
function astreq(str1,str2:pchar; len:integer):integer;
function nextop(list:pchar):boolean;
procedure blanks;
function white:boolean;
function gch:char;
procedure bump(n:integer);
procedure kill;
procedure skip;
function endst:boolean;

(*********** symbol table management functions ***********)
function addsym(_sname:pchar; id, _type:char; size, value:integer; lgpp:pchar; class:integer):pointer;
(*
** search for symbol match
** on return cptr points to slot found or empty slot
*)
function search(sname, buf:pchar; len:integer; _end:pchar; max, off:integer):boolean;
function hash(sname:pchar):integer;
function findglb(_sname:pchar):pointer;
function findloc(_sname:pchar):pointer;
function nextsym(entry:pchar):pchar;

(******** while queue management functions *********)
procedure addwhile(ptr:pinteger);
function readwhile(ptr:pinteger):pointer;
procedure delwhile;

(****************** utility functions ********************)

(*
** test if c is alphabetic
*)
function alpha(c:char):boolean;
(*
** test if given character is alphanumeric
*)
function an(c:char):boolean;
(*
** return next avail internal label number
*)
function getlabel:integer;
(*
** get integer of length len from address addr
** (byte sequence set by "putint")
*)
function getint(addr:pchar; len:integer):integer;
(*
** put integer i of length len into address addr
** (low byte first)
*)
procedure putint(i:integer; addr:pchar; len:integer);
procedure lout(line:pchar; fd:integer);

(******************* error functions *********************)
procedure illname;
procedure multidef(sname:pchar);
procedure needlval;
procedure noiferr;
procedure error(msg:pchar);
procedure errout(msg:pchar;fp:integer);

Implementation

uses
 STDIO,CC1;

var
 lptr_1,lptr_2:char; { lptr[-1] & lptr[-2] }

procedure preprocess;
 var
  k:integer;
  c:char;
 begin
  if (ccode=YES) then begin
   line := mline;
   ifline;
   if (_eof) then exit;
  end else begin
   _inline;
   exit;
  end;
  pptr := -1;
  while (ch<>NEWLINE) and (ch<>#0) do begin
    if white then begin
     keepch(' ');
     while white do gch;
    end else
    if(ch = '"') then begin
     keepch(ch);
     gch;
     while (ch<>'"') or ((lptr_1 = '\') and (lptr_2 <> '\')) do begin
      if (ch=#0) then begin
       error('no quote');
       break;
      end;
      keepch(gch);
     end;
     gch;
     keepch('"');
    end else
    if (ch='''') then begin
     keepch('''');
     gch;
     while (ch<>#39) or ((lptr_1='\')and(lptr_2 <> '\')) do begin
      if ch=#0 then begin
       error('no apostrophe');
       break;
      end;
      keepch(gch);
     end;
     gch;
     keepch('''');
    end else
    if (ch='/') and (nch='*') then begin
     bump(2);
     while ((ch='*')and(nch='/'))=false do begin
      if(ch<>#0) then bump(1) else begin
       ifline;
       if (_eof) then break;
      end;
     end;
     bump(2);
    end else
    if an(ch) then begin
     k := 0;
     while an(ch) and (k<NAMEMAX) do begin
      msname[k]:=ch; inc(k);
      gch;
     end;
     msname[k]:=#0;
     if search(msname, macn, NAMESIZE+2, @macn[MACNEND], MACNBR, 0) then begin
      k := getint(cptr+NAMESIZE, 2);
      c:=macq[k];
      while c<>#0 do begin
       keepch(c);
       inc(k);
       c:=macq[k];
      end;
      while an(ch) do gch;
     end else begin
      k := 0;
      c:=msname[k]; inc(k);
      while (c<>#0) do begin
       keepch(c);
       c:=msname[k]; inc(k);
      end;
     end;
    end else
     keepch(gch);
   end;
  if (pptr >= LINEMAX) then error('line too long');
  keepch(#0);
  line := pline;
  bump(0);
 end;

procedure keepch(c:char);
 begin
  if (pptr < LINEMAX) then begin
   inc(pptr);
   pline[pptr] := c;
  end;
 end;

procedure ifline;
 begin
  while(true) do begin
   _inline;
   if (_eof) then exit;
   if match('#ifdef') then begin
    inc(iflevel);
    if (skiplevel<>0) then continue;
    symname(msname);
    if not search(msname, macn, NAMESIZE+2, @macn[MACNEND], MACNBR, 0) then
     skiplevel := iflevel;
    continue;
   end;
   if match('#ifndef') then begin
    inc(iflevel);
    if(skiplevel<>0) then continue;
    symname(msname);
    if search(msname, macn, NAMESIZE+2, @macn[MACNEND], MACNBR, 0) then
     skiplevel := iflevel;
     continue;
    end;
    if match('#else') then begin
     if(iflevel<>0) then begin
      if(skiplevel = iflevel) then skiplevel := 0
      else if(skiplevel = 0) then skiplevel := iflevel;
     end
     else noiferr;
     continue;
    end;
    if match('#endif') then begin
     if(iflevel<>0) then begin
      if(skiplevel = iflevel) then skiplevel := 0;
      dec(iflevel);
     end
     else noiferr;
     continue;
    end;
    if(skiplevel<>0) then continue;
    if(ch = #0) then continue;
    break;
   end;
  end;

procedure _inline;   (* numerous revisions *)
 var
  k, _unit:integer;
 begin
  {poll(1);}           (* allow operator interruption *)
  if(input = EOF) then openfile;
  if(_eof) then exit;
  _unit:=input2;
  if(_unit = EOF) then _unit := input;
  if(fgets(line, LINEMAX, _unit) = nil) then begin
   fclose(_unit);
   if(input2 <> EOF) then input2 := EOF
   else input  := EOF;
   line := nil;
  end
  else if(listfp<>0) then begin
   if(listfp = output) then fputc(';', output);
   fputs(line, listfp);
  end;
  bump(0);
 end;

function inbyte:char;
 begin
  while(ch=#0) do begin
   if _eof then begin inbyte:=#0; exit end;
   preprocess;
  end;
  inbyte:=gch;
 end;

function symname(sname:pchar):boolean;
 var
  k:integer;
  c:char;
 begin
  blanks;
  if not alpha(ch) then begin
   symname:=(sname=nil);
   exit;
  end;
  k:=0;
  while an(ch) do begin
   sname[k]:=gch;
   if (k < NAMEMAX) then inc(k);
  end;
  sname[k]:=#0;
  symname:=true;
 end;

procedure need(str:pchar);
 begin
  if not match(str) then error('missing token');
 end;

procedure ns;
 begin
  if not match(';') then error('no semicolon') else errflag:=0;
 end;

function match(lit:pchar):boolean;
 var
  k:integer;
 begin
  blanks;
  k:=streq(lptr,lit);
  if (k<>0) then begin
   bump(k);
   match:=true;
  end else
   match:=false;
 end;

function streq(str1,str2:pchar):integer;
 var
  k:integer;
 begin
  k:=0;
  while (str2[k]<>#0) do begin
   if(str1[k] <> str2[k]) then begin
    streq:=0;
    exit;
   end;
   inc(k);
  end;
  streq:=k;
 end;

function amatch(lit:pchar; len:integer):boolean;
 var
  k:integer;
 begin
  blanks;
  k:=astreq(lptr, lit, len);
  if (k<>0) then begin
   bump(k);
   amatch:=true;
  end else
   amatch:=false;
 end;

function astreq(str1,str2:pchar; len:integer):integer;
 var
  k:integer;
 begin
  k:=0;
  while (k < len) do begin
   if(str1[k] <> str2[k]) then break;
   (*
   ** must detect end of symbol table names terminated by
   ** symbol length in binary
   *)
   if(str2[k] < ' ') then break;
   if(str1[k] < ' ') then break;
   inc(k);
  end;
  if an(str1[k]) or an(str2[k]) then
   astreq:=0
  else
   astreq:=k;
 end;

function nextop(list:pchar):boolean;
 var
  op:array[0..3] of char;
 begin
  opindex:=0;
  blanks;
  while (true) do begin
   opsize := 0;
   while(list^ > ' ') do begin
    op[opsize]:=list^;
    inc(list);
    inc(opsize);
   end;
   op[opsize]:=#0;
   opsize:=streq(lptr,op);
   if (opsize<>0) then
    if (lptr[opsize] <> '=')
    and(lptr[opsize] <> lptr[opsize-1]) then begin
     nextop:=true;
     exit;
    end;
   if list^<>#0 then begin
    inc(list);
    inc(opindex);
   end else
    nextop:=false;
  end;
 end;

procedure blanks;
 begin
  while (true) do begin
   while(ch<>#0) do begin
    if white then gch else exit;
    if line = mline then exit;
    preprocess;
    if _eof then break;
   end;
  end;
 end;

function white:boolean;
 begin
  {avail(YES);}  (* abort on stack/symbol table overflow *)
  white:=(lptr<>nil)and(lptr^<=' ');
 end;

function gch:char;
 begin
  lptr_2:=lptr_1;
  lptr_1:=ch;
  gch:=ch;
  if ch<>#0 then bump(1);
 end;

procedure bump(n:integer);
 begin
  if (n<>0) then inc(lptr,n) else lptr:=line;
  nch:=lptr^;
  ch:=nch;
  if (ch<>#0) then nch := lptr[1];
 end;

procedure kill;
 begin
  line^:=#0;
  bump(0);
 end;

procedure skip;
 begin
  if an(inbyte)then
   while an(ch) do gch
  else
   while an(ch) do begin
    if(ch=#0) then break;
    gch;
   end;
  blanks;
 end;

function endst:boolean;
 begin
  blanks;
  endst:=(streq(lptr, ';')<>0) or (ch=#0);
 end;

function addsym(_sname:pchar; id, _type:char; size, value:integer; lgpp:pchar; class:integer):pointer;
 var
  cptr3:integer;
 begin
  if(lgpp = glbptr) then begin
   cptr2:=findglb(_sname);
   if cptr2<>nil then begin
    addsym:=cptr2;
    exit;
   end;
   if(cptr=nil) then begin
    error('global symbol table overflow');
    addsym:=nil;
    exit;
   end;
  end else begin
   if (locptr > @symtab[ENDLOC-SYMMAX]) then begin
    error('local symbol table overflow');
    abort(ERRCODE);
   end;
   cptr:=lgpp;
  end;
  cptr[sIDENT] := id;
  cptr[sTYPE]  := _type;
  cptr[sCLASS] := chr(class);
  putint(size, @cptr[SIZE], 2);
  putint(value, @cptr[sOFFSET], 2);
  cptr2:=@cptr[sNAME];
  cptr3:=0{cptr2};
  while an(_sname^) do begin
   cptr2^:=_sname^;
   inc(cptr2);
   inc(_sname);
   inc(cptr3);
  end;
  if(lgpp = locptr) then begin
   cptr2^:= chr(cptr3); {cptr2 - cptr3; }        (* set length *)
   lgpp  := @cptr2[1];
  end;
  addsym:=cptr;
 end;

function search(sname, buf:pchar; len:integer; _end:pchar; max, off:integer):boolean;
 begin
  cptr:=@buf[(hash(sname) mod (max-1))*len];
  cptr2:=cptr;
  while cptr<>nil do begin
   if astreq(sname, @cptr[off], NAMEMAX)>0 then begin
    search:=true;
    exit;
   end;
   cptr:=@cptr[len];
   if cptr>=_end then cptr:=buf;
   if cptr = cptr2 then begin
    search:=(cptr=nil);
   end;
  end;
  search:=false;
 end;

function hash(sname:pchar):integer;
 var
  i,c:integer;
 begin
  i:=0;
  c:=ord(sname^);
  while c<>0 do begin
   i:=i shl 1+c;
   inc(sname);
   c:=ord(sname^);
  end;
  hash:=i;
 end;

function findglb(_sname:pchar):pointer;
 begin
  if search(_sname,@symtab[STARTGLB],SYMMAX,@symtab[ENDGLB],NUMGLBS,sNAME) then
   findglb:=cptr
  else
   findglb:=nil;
 end;

function findloc(_sname:pchar):pointer;
 begin
  cptr:=locptr;
  dec(cptr); (* search backward for block locals *)
  while (cptr > @symtab[STARTLOC]) do begin
   dec(cptr,ord(cptr^));
   if astreq(_sname, cptr, NAMEMAX)>0 then begin
    dec(cptr,sNAME);
    findloc:=cptr;
   end;
   dec(cptr,sNAME+1);
  end;
  findloc:=nil;
 end;

function nextsym(entry:pchar):pchar;
 begin
  entry:=@entry[sNAME];
  repeat inc(entry) until entry^>=' '; (* find length byte *)
  nextsym:=entry;
 end;

procedure addwhile(ptr:pinteger);
 var
  k:integer;
 begin
{  ptr[WQSP]   := csp; ??  }      (* and stk ptr *)
  ptr^[WQLOOP] := getlabel;  (* and looping label *)
  ptr^[WQEXIT] := getlabel;  (* and exit label *)
  if (wqptr = @wq^[WQMAX]) then begin
    error('control statement nesting limit');
    abort(ERRCODE);
  end;
  k := 0;
  while (k < WQSIZ) do begin
   wqptr^[1]:=ptr^[k];
   inc(wqptr);
   inc(k);
  end;
 end;

function readwhile(ptr:pinteger):pointer;
 begin
  {if(ptr <= wq) then begin
   error('out of context');
   readwhile:=nil;
  end else} begin
   dec(ptr,WQSIZ);
   readwhile:=ptr;
  end;
 end;

procedure delwhile;
 begin
  {if(wqptr > wq) wqptr -= WQSIZ;}
  dec(wqptr);
 end;

function alpha(c:char):boolean;
 begin
  alpha:=(c='_') or isalpha(c);
 end;

function an(c:char):boolean;
 begin
  an:= alpha(c) or isdigit(c);
 end;

function getlabel:integer;
 begin
  inc(nxtlab);
  getlabel:=nxtlab;
 end;

function getint(addr:pchar; len:integer):integer;
 var
  i:integer;
 begin
  i:=ord(addr[len-1]); (* high order byte sign extended *)
  while len>0 do begin
   dec(len);
   i:=(i shl 8) or ord(addr[len])
  end;
  getint:=i;
 end;

procedure putint(i:integer; addr:pchar; len:integer);
 begin
  while len>0 do begin
   dec(len);
   addr^:=chr(i);
   i:=i shr 8;
  end;
 end;

procedure lout(line:pchar; fd:integer);
 begin
  fputs(line, fd);
  fputc(NEWLINE, fd);
 end;

(******************* error functions *********************)

procedure illname;
 begin
  error('illegal symbol');
  skip;
 end;

procedure multidef(sname:pchar);
 begin
  error('already defined');
 end;

procedure needlval;
 begin
  error('must be lvalue');
 end;

procedure noiferr;
 begin
  error('no matching #if...');
  errflag := 0;
 end;

procedure error(msg:pchar);
 begin
  if (errflag<>0) then exit else errflag:=1;
  lout(line, stderr);
  errout(msg, stderr);
  if (alarm<>0) then fputc(#7, stderr);
  if (pause<>0) then while (fgetc(stderr) <> NEWLINE) do;
  if (listfp > 0) then errout(msg, listfp);
 end;

procedure errout(msg:pchar; fp:integer);
 var
  k:pchar;
 begin
  k:=@line[2];
  while k<lptr do begin
   fputc(' ',fp);
   inc(k);
  end;
  lout('/\', fp);
  fputs('**** ', fp);
  lout(msg, fp);
 end;


end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -