LibstdioASTTransformer.java
package edu.udel.cis.vsl.tass.library.libstdio;
import java.util.ArrayList;
import edu.udel.cis.vsl.tass.ast.IF.ASTFactoryIF;
import edu.udel.cis.vsl.tass.ast.IF.ASTTransformerIF;
import edu.udel.cis.vsl.tass.ast.IF.AbstractSyntaxTreeIF;
import edu.udel.cis.vsl.tass.ast.IF.GlobalScopeNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.IdentifierNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.SequenceNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.TypeDefinitionNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.type.CompositeTypeNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.type.TypeNodeIF;
import edu.udel.cis.vsl.tass.model.IF.SyntaxException;
import edu.udel.cis.vsl.tass.util.Pair;
import edu.udel.cis.vsl.tass.util.TASSInternalException;
/**
* Adds types to the AST: STDIO_File and STDIO_Stream. A skeleton definition of
* STDIO_Stream should already be present (from parsing stdio.h), but will have
* to be modified.
*
* More precisely, the AST is expected to have a global scope node N of the form
* "typedef ... FILE". This will (1) insert the typedef of STDIO_File given
* below as a global scope node just before N, and (2) replace the "..." in N
* with the definition of "struct STDIO_Stream" given below.
*
* <code>
* typedef struct STDIO_File {
* char filename[]; // the name of the file (including path)
* boolean isOutput; // is this an output file?
* boolean isInput; // is this an input file?
* boolean isBinary; // can be binary or text
* boolean isWide; // wide orientation
* char[][] contents; // file contents: ragged array
* } STDIO_File;
*
* typedef struct STDIO_Stream {
* STDIO_File *file; // file to which this stream refers
* boolean isOpen; // is this stream open?
* int position1; // current word in file
* int position2; // character index in word
* int mode; // Stream mode: r/w/a
* } FILE;
* </code>
*
* @author siegel
*
*/
public class LibstdioASTTransformer implements ASTTransformerIF {
private ASTFactoryIF astFactory;
public LibstdioASTTransformer(ASTFactoryIF astFactory) {
this.astFactory = astFactory;
}
public ASTFactoryIF astFactory() {
return astFactory;
}
@Override
public String name() {
return "libstdio";
}
private void add(ArrayList<Pair<String, TypeNodeIF>> fields,
String fieldName, TypeNodeIF typeNode) {
fields.add(new Pair<String, TypeNodeIF>(fieldName, typeNode));
}
/**
* Finds the global scope node child which is typedef FILE, inserts a global
* scope node before it, defining new type modify the FILE type definition.
*/
@Override
public void transform(AbstractSyntaxTreeIF ast) throws SyntaxException {
SequenceNodeIF<GlobalScopeNodeIF> root = ast.rootNode()
.globalScopeNodes();
int numChildren = root.numChildren();
int fileTypeIndex = -1;
ArrayList<Pair<String, TypeNodeIF>> fileFields = new ArrayList<Pair<String, TypeNodeIF>>(), streamFields = new ArrayList<Pair<String, TypeNodeIF>>();
CompositeTypeNodeIF fileTypeNode, streamTypeNode;
TypeDefinitionNodeIF fileTypedefNode, streamTypedefNode = null;
for (int i = 0; i < numChildren; i++) {
GlobalScopeNodeIF child = root.getSequenceChild(i);
if (child instanceof TypeDefinitionNodeIF) {
TypeDefinitionNodeIF typeDef = (TypeDefinitionNodeIF) child;
IdentifierNodeIF identifier = typeDef.identifier();
String typeName = identifier.name();
if ("FILE".equals(typeName)) {
fileTypeIndex = i;
streamTypedefNode = (TypeDefinitionNodeIF) child;
break;
}
}
}
if (streamTypedefNode == null)
throw new TASSInternalException(
"stdlib AST transformer unable to find FILE typedef");
add(fileFields, "filename", astFactory.arrayTypeNode(astFactory
.characterTypeNode()));
add(fileFields, "isOutput", astFactory.booleanTypeNode());
add(fileFields, "isInput", astFactory.booleanTypeNode());
add(fileFields, "isBinary", astFactory.booleanTypeNode());
add(fileFields, "isWide", astFactory.booleanTypeNode());
add(fileFields, "contents", astFactory.arrayTypeNode(astFactory
.arrayTypeNode(astFactory.characterTypeNode())));
fileTypeNode = astFactory.compositeTypeNode("STDIO_File", fileFields,
false);
fileTypedefNode = astFactory.typeDefinitionNode(astFactory
.identifierNode("STDIO_File"), fileTypeNode);
root.insertChild(fileTypeIndex, fileTypedefNode);
add(streamFields, "file", astFactory.pointerTypeNode(astFactory
.typeReferenceNode(fileTypedefNode)));
add(streamFields, "isOpen", astFactory.booleanTypeNode());
add(streamFields, "position1", astFactory.integerTypeNode());
add(streamFields, "position2", astFactory.integerTypeNode());
add(streamFields, "mode", astFactory.integerTypeNode());
streamTypeNode = astFactory.compositeTypeNode("STDIO_Stream",
streamFields, false);
streamTypedefNode.setType(streamTypeNode);
}
}