home *** CD-ROM | disk | FTP | other *** search
-
- (*
- * TPTC - Turbo Pascal to C translator
- *
- * (C) 1988 Samuel H. Smith (rev. 13-Feb-88)
- *
- *)
-
- (********************************************************************)
- (*
- * process pascal data type specifications
- *
- *)
-
- function psimpletype: string80;
- {parse a simple (single keyword and predefined) type; returns the
- translated type specification; sets the current data type}
- var
- sym: symptr;
-
- begin
- if debug_parse then write(' <simpletype>');
-
- sym := locatesym(ltok);
- if sym <> nil then
- begin
- curtype := sym^.symtype;
- if cursuptype = ss_none then
- cursuptype := sym^.suptype;
- curlimit := sym^.limit;
- curbase := sym^.base;
- curpars := sym^.parcount;
- end;
-
- psimpletype := usetok;
- end;
-
-
- (********************************************************************)
- procedure pdatatype(stoclass: anystring;
- var vars: paramlist;
- prefix: anystring;
- suffix: anystring;
- addsemi: boolean);
- {parse any full data type specification; input is a list of variables
- to be declared with this data type; stoclass is a storage class prefix
- (usually 'static ', '', 'typedef ', or 'extern '. prefix and suffix
- are variable name modifiers used in pointer and subscript translations;
- recursive for complex data types}
-
- const
- forward_typedef: anystring = '';
- forward_undef: anystring = '';
-
- var
- i: integer;
- ts: anystring;
- ex: anystring;
- sym: symptr;
- nbase: integer;
- bbase: integer;
- nsuper: supertypes;
-
- procedure pvarlist;
- var
- i: integer;
- pcnt: integer;
-
- begin
- ts := '';
- pcnt := -1;
-
- if tok = 'ABSOLUTE' then
- begin
- if debug_parse then write(' <abs>');
- gettok; {consume the ABSOLUTE}
- ts := pexpr; {get the absolute lvalue}
-
- if tok[1] = ':' then {absolute addressing}
- begin
- gettok;
- ts := ' = MK_FP('+ts+','+pexpr+')';
- end
-
- else {variable aliasing}
- begin
- if ts[1] = '*' then
- ts := ' = ' + copy(ts,2,255)
- else
- ts := ' = &(' + ts + ')';
- end;
-
- {convert new variable into a pointer if needed}
- if length(prefix) = 0 then
- prefix := '*';
-
- {force automatic pointer dereference in expressions}
- pcnt := -2;
- end;
-
- if cursuptype = ss_none then
- cursuptype := ss_scalar;
-
- for i := 1 to vars.n do
- begin
- newsym(vars.id[i],curtype,cursuptype,pcnt,withlevel,curlimit,nbase);
- puts(prefix+vars.id[i]+suffix+ts);
- if i < vars.n then
- puts(', ');
- end;
- end;
-
-
- procedure parray;
- begin
- if debug_parse then write(' <array>');
- gettok; {consume the ARRAY}
-
- repeat
- gettok; {consume the [ or ,}
-
- ts := pexpr; {consume the lower subscript expression}
- if isnumber(ts) then
- nbase := atoi(ts)
- else
- nbase := curbase;
-
- if tok = '..' then
- begin
- gettok; {consume the ..}
- ts := pexpr;
-
- subtract_base(ts,nbase-1);
- end
- else
-
- begin {subscript by typename - look up type range}
- sym := locatesym(ts);
- if sym <> nil then
- begin
- nbase := sym^.base;
- if (sym^.limit > 0) and (sym^.suptype <> ss_const) then
- ts := ' /* ' + ts + ' */ ' + itoa(sym^.limit-nbase+1);
- end;
- end;
-
- suffix := suffix + '[' + ts + ']';
-
- until tok[1] <> ',';
-
- gettok; {consume the ]}
- gettok; {consume the OF}
-
- cursuptype := ss_array;
- end;
-
-
- procedure pstring;
- begin
- if debug_parse then write(' <string>');
- gettok; {consume the STRING}
-
- if tok[1] = '[' then
- begin
- gettok; {consume the [}
-
- nsuper := cursuptype;
- ts := pexpr;
- cursuptype := nsuper;
- subtract_base(ts,-1); {increment string size by one}
- suffix := suffix + '[' + ts + ']';
-
- gettok; {consume the ]}
- end
- else
- suffix := suffix + '[STRSIZ]';
-
- puts(ljust(stoclass+'char',identlen));
- curtype := s_string;
- nbase := 1;
- pvarlist;
- end;
-
-
- procedure ptext;
- begin
- if debug_parse then write(' <text>');
- gettok; {consume the TEXT}
-
- if tok[1] = '[' then
- begin
- gettok; {consume the [}
- nsuper := cursuptype;
- ts := pexpr;
- cursuptype := nsuper;
- gettok; {consume the ]}
- end;
-
- puts(ljust(stoclass+'text',identlen));
- curtype := s_file;
- pvarlist;
- end;
-
-
- procedure pfile;
- begin
- if debug_parse then write(' <file>');
- gettok; {consume the FILE}
-
- if tok = 'OF' then
- begin
- gettok; {consume the OF}
- ts := tok;
- gettok; {consume the recordtype}
- ts := '/* file of '+ts+' */ ';
- end
- else
- ts := '/* untyped file */ ';
-
- puts(ljust(stoclass+'int',identlen)+ts);
- curtype := s_file;
- pvarlist;
- end;
-
-
- procedure pset;
- begin
- if debug_parse then write(' <set>');
- gettok; {consume the SET}
- gettok; {consume the OF}
-
- ts := '/* ';
- if toktype = identifier then
- ts := ts + usetok
- else
-
- if tok = '(' then
- begin
- repeat
- ts := ts + usetok
- until (tok[1] = ')') or recovery;
- ts := ts + usetok;
- end
-
- else
- ts := ts + psetof;
-
- puts(ljust(stoclass+'setrec',identlen)+ts+' */ ');
- curtype := s_struct;
- pvarlist;
- end;
-
-
- procedure pvariant;
- begin
- if debug_parse then write(' <variant>');
- gettok; {consume the CASE}
-
- ts := ltok;
- gettok; {consume the selector identifier}
-
- if tok[1] = ':' then
- begin
- gettok; {consume the :}
- puts(ltok+' '+ts+ '; /* Selector */');
- gettok; {consume the selector type}
- end
- else
- puts(' /* Selector is '+ts+' */');
-
- gettok;
- puts('union { ');
- newline;
-
- while (tok <> '}') and not recovery do
- begin
- ts := pexpr; {parse the selector constant}
- while tok[1] = ',' do
- begin
- gettok;
- ts := pexpr;
- end;
-
- gettok; {consume the :}
-
- puts(' struct { ');
-
- ts := 's' + ts;
- decl_prefix := 'v.'+ts+'.';
- pvar;
- decl_prefix := '';
-
- gettok; {consume the ')'}
-
- puts(' } '+ts+';');
-
- {arrange for reference translation}
- newsym(ts,s_void,ss_struct,-1,0,0,0);
- cursym^.repid := ts;
-
- if tok[1] = ';' then
- gettok;
- end;
-
- puts(' } v;');
- newline;
- end;
-
-
- procedure precord;
- begin
- if debug_parse then write(' <record>');
- puts(stoclass+'struct '+vars.id[1]+' { ');
-
- inc(withlevel);
- pvar; {process each record member}
-
- if tok = 'CASE' then {process the variant part, if any}
- pvariant;
- dec(withlevel);
-
- puttok; {output the closing brace}
- gettok; {and consume it}
-
- curtype := s_struct;
- cursuptype := ss_struct;
- pvarlist; {output any variables of this record type}
-
- {convert a #define into a typedef in case of a forward pointer decl}
- if length(forward_typedef) > 0 then
- begin
- puts(';');
- newline;
- puts(forward_undef);
- newline;
- puts(forward_typedef);
- forward_typedef := '';
- end;
- end;
-
-
- procedure penum;
- var
- members: integer;
-
- begin
- if debug_parse then write(' <enum>');
- puts(stoclass+'enum { ');
-
- gettok;
- members := 0;
- repeat
- puts(ltok);
- if toktype = identifier then
- inc(members);
- gettok;
- until (tok[1] = ')') or recovery;
-
- puts(' } ');
- gettok; {consume the )}
-
- curtype := s_int;
- curlimit := members-1;
- nbase := 0;
- pvarlist;
- end;
-
-
- procedure pintrange;
- begin
- if debug_parse then write(' <int.range>');
- ex := pexpr; {consume the lower limit expression}
- nbase := atoi(ex);
-
- if tok <> '..' then
- begin
- syntax('".." expected');
- exit;
- end;
-
- gettok; {consume the ..}
- ts := pexpr; {consume the number}
-
- sym := locatesym(ts);
- if sym <> nil then
- if sym^.limit > 0 then
- ts := itoa(sym^.limit);
-
- curtype := s_int;
- curlimit := atoi(ts);
- puts(ljust(stoclass+'int',identlen)+'/* '+ex+'..'+ts+' */ ');
- pvarlist;
- end;
-
- procedure pcharrange;
- begin
- if debug_parse then write(' <char.range>');
- ex := pexpr; {consume the lower limit expression}
- nbase := ord(ex[2]);
-
- if tok <> '..' then
- begin
- syntax('".." expected');
- exit;
- end;
-
- gettok; {consume the ..}
- ts := pexpr; {consume the number}
-
- sym := locatesym(ts);
- if sym <> nil then
- if sym^.limit > 0 then
- ts := itoa(sym^.limit);
-
- curtype := s_char;
- curlimit := ord(ts[2]);
- puts(ljust(stoclass+'char',identlen)+'/* '+ex+'..'+ts+' */ ');
- pvarlist;
- end;
-
- procedure psimple;
- begin
- ex := psimpletype;
- if cursuptype <> ss_array then
- nbase := curbase;
-
- if tok = '..' then
- begin
- if debug_parse then write(' <range>');
- gettok; {consume the ..}
- ts := pexpr; {consume the high limit}
-
- sym := locatesym(ts);
- if sym <> nil then
- if sym^.limit > 0 then
- ts := itoa(sym^.limit);
-
- curtype := s_int;
- curlimit := curbase;
- puts(ljust(stoclass+'int',identlen)+'/* '+ex+'..'+ex+' */ ');
- pvarlist;
- exit;
- end;
-
- {pointer to simpletype?}
- i := pos('^',ex);
- if i <> 0 then
- begin
- if debug_parse then write(' <pointer>');
- delete(ex,i,1);
- prefix := '*';
- cursuptype := ss_pointer;
- end;
-
- sym := locatesym(ex);
-
- {potential forward pointer reference?}
- if (stoclass = 'typedef ') and (vars.n = 1) and
- (prefix = '*') and (sym = nil) then
- begin
- if debug_parse then write(' <forward>');
- newsym(vars.id[1],curtype,cursuptype,-1,0,curlimit,0);
- puts(ljust('#define '+vars.id[1],identlen)+'struct '+ex+' *');
- forward_undef := '#undef '+vars.id[1];
- forward_typedef := 'typedef struct '+ex+' *'+vars.id[1];
- addsemi := false;
- end
- else
-
- {ordinary simple types}
- begin
- if debug_parse then write(' <simple>');
- puts(ljust(stoclass+ex,identlen));
- pvarlist;
- end;
- end;
-
- begin
- cursuptype := ss_none;
- curlimit := 0;
- nbase := 0;
-
- if tok = 'EXTERNAL' then
- begin
- gettok; {consume the EXTERNAL}
- stoclass := 'extern '+stoclass;
- end;
-
- if tok = 'PACKED' then
- gettok;
- while tok = 'ARRAY' do
- parray;
- if tok = 'PACKED' then
- gettok;
-
- if tok = 'STRING' then pstring
- else if tok = 'TEXT' then ptext
- else if tok = 'FILE' then pfile
- else if tok = 'SET' then pset
- else if tok = '(' then penum
- else if tok = 'RECORD' then precord
- else if toktype = number then pintrange
- else if toktype = chars then pcharrange
- else psimple;
-
- if addsemi then
- puts(';');
- puts(' ');
-
- if tok[1] = ';' then
- gettok;
- end;
-
-
- (********************************************************************)
- (*
- * declaration keyword processors
- * const, type, var, label
- *
- * all enter with tok=section type
- * exit with tok=new section or begin or proc or func
- *
- *)
-
- procedure pconst;
- {parse and translate a constant section}
- var
- vars: paramlist;
- parlev: integer;
- exp: string;
- dup: boolean;
-
- begin
- if debug_parse then write(' <const>');
- gettok;
-
- while (toktype <> keyword) and not recovery do
- begin
- nospace := false;
- vars.n := 1;
- vars.id[1] := ltok;
-
- gettok; {consume the id}
-
- if tok[1] = '=' then {untyped constant}
- begin
- if debug_parse then write(' <untyped.const>');
-
- {$b-} {requires short-circuit evaluation}
- dup := (unitlevel > 0) and (cursym <> nil) and
- (cursym^.suptype = ss_const);
-
- gettok; {consume the =}
-
- exp := pexpr;
- curtype := cexprtype;
- if isnumber(exp) then
- curlimit := atoi(exp);
-
- {prefix identifier if needed to prevent conflict with other defines}
- newsym(vars.id[1],curtype,ss_const,-1,0,curlimit,0);
- if dup then
- begin
- vars.id[1] := procnum + '_' + vars.id[1];
- cursym^.repid := vars.id[1];
- end;
-
- puts(ljust('#define '+vars.id[1],identlen));
- puts(exp);
- puts(' ');
-
- gettok; {consume the ;}
- end
- else
-
- begin {typed constants}
- if debug_parse then write(' <typed.const>');
-
- gettok; {consume the :}
-
- pdatatype('',vars,'','',false);
-
- if tok[1] <> '=' then
- begin
- syntax('"=" expected');
- exit;
- end;
-
- gettok; {consume the =}
-
- puts(' = ');
- parlev := 0;
-
- repeat
- if tok[1] = '[' then
- begin
- gettok;
- exp := psetof;
- gettok;
- puts(exp);
- end
- else
-
- if tok[1] = '(' then
- begin
- inc(parlev);
- puts('{');
- gettok;
- end
- else
-
- if tok[1] = ')' then
- begin
- dec(parlev);
- puts('}');
- gettok;
- end
- else
-
- if tok[1] = ',' then
- begin
- puttok;
- gettok;
- end
- else
-
- if (parlev > 0) and (tok[1] = ';') then
- begin
- puts(',');
- gettok;
- end
- else
-
- if tok[1] <> ';' then
- begin
- exp := pexpr;
- if tok[1] = ':' then
- gettok {discard 'member-identifier :'}
- else
- puts(exp);
- end;
-
- until ((parlev = 0) and (tok[1] = ';')) or recovery;
-
- puttok; {output the final ;}
- gettok;
- end;
- end;
- end;
-
-
- (********************************************************************)
- procedure ptype;
- {parse and translate a type section}
- var
- vars: paramlist;
-
- begin
- if debug_parse then write(' <type>');
- gettok;
-
- while (toktype <> keyword) do
- begin
- vars.n := 1;
- vars.id[1] := usetok;
-
- if tok = '=' then
- gettok
- else
- begin
- syntax('"=" expected');
- exit;
- end;
-
- nospace := false;
- pdatatype('typedef ',vars,'','',true);
- end;
-
- end;
-
-
- (********************************************************************)
- procedure pvar;
- {parse and translate a variable section}
- var
- vars: paramlist;
- sto: string20;
- begin
- if debug_parse then write(' <var>');
-
- if in_interface and (withlevel = 0) then
- sto := 'extern '
- else
- sto := '';
-
- vars.n := 0;
- gettok;
-
- while (toktype <> keyword) and (tok[1] <> '}') and (tok[1] <> ')') do
- begin
- nospace := true;
-
- repeat
- if tok[1] = ',' then
- gettok;
-
- inc(vars.n);
- if vars.n > maxparam then
- fatal('Too many identifiers (pvar)');
- vars.id[vars.n] := ltok;
- gettok;
- until tok[1] <> ',';
-
- if tok[1] <> ':' then
- begin
- syntax('":" expected');
- exit;
- end;
-
- gettok; {consume the :}
- nospace := false;
- pdatatype(sto,vars,'','',true);
- vars.n := 0;
- end;
- end;
-
-
-