file: pre.cpp
#include <stdio.h>
#include "direct.h"
#include "pre.h"
preprocessor::preprocessor(String assembly_file) :_unfinished_files()
{
ifstream *file=new ifstream;
file->open(assembly_file, ios::in);
// fprintf(stderr, "file==%x\n", file); //debug
_unfinished_files.push_back(file); //puts main file on the file stack.
_else_legal.push_back(false); //you can't have an else outside of
//a #if...
_depth=0; //depth in if's is zero.
line_number=0;
_compilable=true; //compile code.
_arg=new String[max_args +1];
initialize_directive();
}
//////////////////////////////////////////////////////
preprocessor::~preprocessor()
{
/*
//destroy the set of things "defined"
_defined.clear();
//destroy the map of directive functions. //OVERLOAD CALL: directive: direct.h(?), direct.h(?), direct.h(?), direct.h(?), direct.h(?), direct.h(?)
direct.clear();
*/ // debug
}
//////////////////////////////////////////////////////
bool preprocessor::next(line &out)
{ //vars
bool flag;
ifstream *file= new ifstream;
bool c=compilable(); //compilable
char char_line[max_len]; //later will change it so that I
//can read in any size line. add
if (!_unfinished_files.empty()) {
file=_unfinished_files.back();
if(!file->eof()) {
file->getline(char_line, max_len);
file_line=(String) char_line;
//Do something with the line.
_is_pound=is_pound();
if (_is_pound)
numarg=get_key();
//if c is false, then #ifdef, #ifndef, or #else says that we do not
//compile this line. if c is true, then we do. is_compilable
//tells us if the line itself is compilable (ie. not a comment
//or directive, except #define x y) //OVERLOAD CALL: directive: direct.h(?), direct.h(?), direct.h(?), direct.h(?), direct.h(?), direct.h(?)
if (!is_compilable())
c=false;
out=line(file_line,++line_number, c);
//the line is ready to be sent, now do preparations
//for next line if this line was a directive. //OVERLOAD CALL: directive: direct.h(?), direct.h(?), direct.h(?), direct.h(?), direct.h(?), direct.h(?)
if (_is_pound){
map<String, directive*, strless>::iterator call; //OVERLOAD CALL: directive: direct.h(?), direct.h(?), direct.h(?), direct.h(?), direct.h(?), direct.h(?)
call = direct.find(_arg[0]);
if (call!=direct.end())
(*(*call).second) (this);
else
//they used '#' at the front of the line without calling a
//directive. error on this line. //OVERLOAD CALL: directive: direct.h(?), direct.h(?), direct.h(?), direct.h(?), direct.h(?), direct.h(?)
;
}
//Done with the line.
flag=true; }
else { // file == EOF.
file->close(); //done with the file.
_unfinished_files.pop_back();
flag=next(out); } } //calls next again, so it opens up next file, and tries again. //OVERLOAD CALL: next: resolved_line.cc(resolved_line), line.cpp(line), pre.cpp(preprocessor)
else // no more files...done
{
flag=false;
if (depth !=0)
//call an error, a #endif was expected.
;}
return flag;
}
//////////////////////////////////////////////////////
bool preprocessor::value_defined() const
{
if (_arg[0] !="define")
return false;
else
return (numarg==3); //'#define x y' has three args, include #define.
}
/////////////////////////////////////////////////
/*
Description: This function gets the first identifier from
the line. skips over #,;,tab,space
used to get the keywords after a #
returns a pointer to a copy of the
identifier.
This function is only called if is_pound is true.
THis method gets the first two arguments from the
line, and it also returns how many arguments it got
1: just the directive //OVERLOAD CALL: directive: direct.h(?), direct.h(?), direct.h(?), direct.h(?), direct.h(?), direct.h(?)
2: and one argument
3: two arguments.
4: more than two arguments
*/
int preprocessor::get_key() const
{
int numarg;
Regex delim = "[ \t]+";
numarg=split(eatws(file_line), _arg, max_args+1, delim);
_arg[0].del("#"); //deletes the first '#' from the directive. //OVERLOAD CALL: directive: direct.h(?), direct.h(?), direct.h(?), direct.h(?), direct.h(?), direct.h(?)
return (numarg);
}
///////////////////////////////////////////////
/*
name: eatws
Description: takes in a string, eats all of the white space
at the front of the string, then returns a string
with all this white space gone.
white space is 'space' and 'tab'.
*/
String preprocessor::eatws(String out) const
{
bool done=false; //set done=true when a non-space, non-tab character is hit.
char f;
if (!out.empty()) {
while ( (out.length() >0) && (!done)) {
f=out.firstchar();
if ( (f==' ') || (f=='\t'))
out.del(f);
else done = true;
}
}
return out;
}
///////////////////////////////////////////////
C++ to HTML Conversion by ctoohtml