home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
gdead.berkeley.edu
/
gdead.berkeley.edu.tar
/
gdead.berkeley.edu
/
pub
/
cad-tools
/
ciftomann.tar
/
CD
/
parser.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-01-28
|
13KB
|
596 lines
/*
* parser.c
*
* Copyright -C- 1981 Giles C. Billingsley
* sccsid "%W% %G%"
*
* KIC is a graphics editor that was developed by the integrated
* circuits group of the Electronics Research Laboratory and the
* Department of Electrical Engineering and Computer Sciences at
* the University of California, Berkeley, California. The program
* KIC is available free of charge to any interested party.
* The sale, resale, or use of this program for profit without the
* express written consent of the Department of Electrical Engineering
* and Computer Sciences, University of California, Berkeley, California,
* is forbidden.
*/
/*
* Fast CIF file parser.
*
* It is easy to use it to write programs that traverse a CIF file.
*
* Examples follows.
* 1. A program that translates CIF to STREAM.
* 2. A pattern factoring program for PG tape generation.
* See TI's PFP.
* 3. A statistics generation program.
* 4. A program that extracts each symbol, generates a name for it, and
* writes it to a file. See the CD package.
* 5. A program that builds a binary representation of the CIF file that can
* then be edited via procedure calls and then written back to the CIF
* file. See the CD package.
*
* Here's how you use it.
*
* First, you include the files actions.c and parser.h.
* Then you invoke PCIF(CIFFileName,StatusString,StatusInt).
* Each time the parser recognizes a CIF command, it invokes an action routine.
* You should fill in the action routines in the file Actions.c.
* Each action routine name is prefixed by A.
*
* Each parser routine and global variable name is prefixed by P.
* StatusInt == PFAILED if the parse failed and an error message along with
* about where in the CIF file the error is in the StatusString.
* Else StatusInt == PSUCCEEDED and StatusString == "".
*
*/
#include "parser.h"
#include "cd.h"
/* Library routines */
#ifndef vms
char *sprintf();
#endif
PCIF(CIFFileName,StatusString,StatusInt)
char *CIFFileName,**StatusString;
int *StatusInt;
{
PStatus[0] = EOS;
*StatusString = PStatus;
if((PCIFFileDesc = POpen(CIFFileName,"r",(char *)NULL,(char **)NULL))
== NULL){
PChar = EOF;
PError("Can't open CIF file.");
*StatusInt = PFAILED;
return;
}
loop{
PCharacter(PReturned,PSTRIPWHITESPACE2,PDONTFAILONEOF);
if(PReturned == PFAILED){
fclose(PCIFFileDesc);
*StatusInt = PFAILED;
return;
}
elif(PChar == 'D'){
PCharacter(PReturned,PSTRIPWHITESPACE2,PFAILONEOF);
if(PReturned == PFAILED){
fclose(PCIFFileDesc);
*StatusInt = PFAILED;
return;
}
elif(PChar == 'S'){
if(PSymbol() == PFAILED){
fclose(PCIFFileDesc);
*StatusInt = PFAILED;
return;
}
}
elif(PChar == 'D'){
if(PDeleteSymbol() == PFAILED){
fclose(PCIFFileDesc);
*StatusInt = PFAILED;
return;
}
}
}
elif(PChar == 'E'){
*StatusInt = PEnd();
return;
}
elif((PReturned = PPrimitiveCommand()) == PFAILED){
fclose(PCIFFileDesc);
*StatusInt = PFAILED;
return;
}
elif(PReturned == PNOTAPPLICABLE){
PError("Can't understand next command.");
fclose(PCIFFileDesc);
*StatusInt = PFAILED;
return;
}
}
}
PPrimitiveCommand(){
if(PChar == 'P')
return(PPolygon());
elif(PChar == 'B')
return(PBox());
elif(PChar == 'W')
return(PWire());
elif(PChar == 'L')
return(PLayer());
elif(PChar == 'C')
return(PCall());
elif(PChar == 'R')
return(PRoundFlash());
elif('0' <= PChar And PChar <= '9')
return(PUserExtension());
elif(PChar == '(')
return(PComment());
elif(PChar == ';')
return(PSUCCEEDED);
else
return(PNOTAPPLICABLE);
}
PEnd(){
AEnd();
fclose(PCIFFileDesc);
return(PSUCCEEDED);
}
PSymbol(){
char For;
int SymbolNum,A,B;
#ifdef TRACT
fprintf(stderr," ENTERING PSYMBOL\n");
#endif
PInteger(PReturned,PFAILONEOF);
if(PReturned == PFAILED)
return(PFAILED);
SymbolNum = PInt;
A = B = 1;
/* look for scaling factor */
for(For = '0'; For <= '9'; ++For){
PLookAhead(PReturned,PSTRIPWHITESPACE3,For);
if(PReturned == PFAILED)
return(PFAILED);
if(PChar == For){
ungetc(For,PCIFFileDesc);
if(PPoint(&A,&B) == PFAILED)
return(PFAILED);
break;
}
}
PLookForSemi(PReturned);
if(PReturned == PFAILED)
return(PFAILED);
if(ABeginSymbol(SymbolNum,A,B) == PFAILED){
PErrorCD();
return(PFAILED);
}
if(PReturned == PFAILED)
return(PFAILED);
loop{
PCharacter(PReturned,PSTRIPWHITESPACE1,PFAILONEOF);
if(PReturned == PFAILED)
return(PFAILED);
if((PReturned = PPrimitiveCommand()) == PFAILED){
return(PFAILED);
}
elif(PReturned == PNOTAPPLICABLE)
break;
}
if(PChar != 'D')
return(PFAILED);
PCharacter(PReturned,PSTRIPWHITESPACE2,PFAILONEOF);
if(PReturned == PFAILED)
return(PFAILED);
if(PChar != 'F')
return(PFAILED);
PLookForSemi(PReturned);
if(PReturned == PFAILED)
return(PFAILED);
AEndSymbol();
return(PSUCCEEDED);
}
PDeleteSymbol(){
PInteger(PReturned,PFAILONEOF);
if(PReturned == PFAILED)
return(PFAILED);
else{
PLookForSemi(PReturned);
if(PReturned == PFAILED)
return(PFAILED);
ADeleteSymbol(PInt);
return(PSUCCEEDED);
}
}
PCall(){
int SymbolNum,X,Y;
PInteger(PReturned,PFAILONEOF);
if(PReturned == PFAILED)
return(PFAILED);
SymbolNum = PInt;
if(ABeginCall(SymbolNum) == PFAILED){
PErrorCD();
return(PFAILED);
}
loop{
PCharacter(PReturned,PSTRIPWHITESPACE2,PFAILONEOF);
if(PReturned == PFAILED)
return(PFAILED);
elif(PChar == 'T'){
if(PPoint(&X,&Y) == PFAILED){
PError("Can't parse translation transform.");
return(PFAILED);
}
elif(AT(CDTRANSLATE,X,Y) == PFAILED){
PErrorCD();
return(PFAILED);
}
}
elif(PChar == 'M'){
PCharacter(PReturned,PSTRIPWHITESPACE2,PFAILONEOF);
if(PReturned == PFAILED){
PErrorEOF();
return(PFAILED);
}
elif(PChar == 'X'){
if(AT(CDMIRRORX,X,Y) == PFAILED){
PErrorCD();
return(PFAILED);
}
}
elif(PChar == 'Y'){
if(AT(CDMIRRORY,X,Y) == PFAILED){
PErrorCD();
return(PFAILED);
}
}
else{
PError("Can't parse mirror transform.");
return(PFAILED);
}
}
elif(PChar == 'R'){
if(PPoint(&X,&Y) == PFAILED){
PError("Can't parse rotation transform.");
return(PFAILED);
}
if(AT(CDROTATE,X,Y) == PFAILED){
PErrorCD();
return(PFAILED);
}
}
elif(PChar == ';')
break;
else{
PError("Can't parse transformation.");
return(PFAILED);
}
}
if(AEndCall() == PFAILED){
PErrorCD();
return(PFAILED);
}
return(PSUCCEEDED);
}
PPolygon(){
struct p *Path;
#ifdef TRACE
fprintf(stderr," ENTERING PPOLYGON\n");
#endif
if(PPath(&Path) == PFAILED)
return(PFAILED);
#ifdef TRACE
fprintf(stderr," LEAVING PPATH\n");
#endif
if(APolygon(Path) == PFAILED){
PErrorCD();
return(PFAILED);
}
#ifdef TRACE
fprintf(stderr," LEAVING PPOLYGON\n");
#endif
return(PSUCCEEDED);
}
PBox(){
int Length,Width,X,Y,XDirection,YDirection;
XDirection = 1;
YDirection = 0;
PInteger(PReturned,PFAILONEOF);
if(PReturned == PFAILED)
return(PFAILED);
Length = PInt;
PInteger(PReturned,PFAILONEOF);
if(PReturned == PFAILED)
return(PFAILED);
Width = PInt;
if(PPoint(&X,&Y) == PFAILED)
return(PFAILED);
PLookForSemi(PReturned);
if(PReturned == PFAILED)
return(PFAILED);
elif(PChar != ';'){
if(PPoint(&XDirection,&YDirection) == PFAILED)
return(PFAILED);
PLookForSemi(PReturned);
if(PReturned == PFAILED Or PChar != ';'){
PErrorNoSemicolon();
return(PFAILED);
}
}
if(ABox(Length,Width,X,Y,XDirection,YDirection) == PFAILED){
PErrorCD();
return(PFAILED);
}
return(PSUCCEEDED);
}
PRoundFlash(){
int Width,X,Y;
PInteger(PReturned,PFAILONEOF);
if(PReturned == PFAILED)
return(PFAILED);
Width = PInt;
if(PPoint(&X,&Y) == PFAILED)
return(PFAILED);
PLookForSemi(PReturned);
if(PReturned == PFAILED)
return(PFAILED);
elif(PChar != ';'){
PErrorNoSemicolon();
return(PFAILED);
}
if(ARoundFlash(Width,X,Y) == PFAILED){
PErrorCD();
return(PFAILED);
}
return(PSUCCEEDED);
}
PWire(){
int Width;
struct p *Path;
#ifdef TRACE
fprintf(stderr," ENTERING PWIRE\n");
#endif
PInteger(PReturned,PFAILONEOF);
if(PReturned == PFAILED)
return(PFAILED);
Width = PInt;
#ifdef TRACE
fprintf(stderr," ENTERING PPATH\n");
#endif
if(PPath(&Path) == PFAILED)
return(PFAILED);
if(AWire(Width,Path) == PFAILED){
PErrorCD();
return(PFAILED);
}
return(PSUCCEEDED);
}
PPath(Path)
struct p **Path;
{
int X,Y;
struct p *Pair;
*Path = NULL;
loop{
PLookForSemi(PReturned);
#ifdef TRACE
if(PReturned == PFAILED)
fprintf(stderr," PPATH FAILED AFTER PLOOKAHEAD\n");
#endif
if(PReturned == PFAILED)
return(PFAILED);
elif(PChar == ';')
break;
else{
if(PPoint(&X,&Y) == PFAILED)
return(PFAILED);
#ifdef TRACE
fprintf(stderr," PPATH POINT %d, %d\n",X,Y);
#endif
if((Pair = (struct p *)malloc(sizeof(struct p))) == NULL){
PError("Out of memory.");
return(PFAILED);
}
Pair->pSucc = *Path;
Pair->pX = X;
Pair->pY = Y;
*Path = Pair;
}
}
return(PSUCCEEDED);
}
PPoint(X,Y)
int *X,*Y;
{
/* it is assumed that a LookAhead is done prior to calling PPoint */
PInteger(PReturned,PFAILONEOF);
if(PReturned == PFAILED)
return(PFAILED);
*X = PInt;
PLookForSemi(PReturned);
if(PReturned == PFAILED)
return(PFAILED);
elif(PChar == ';'){
PError("Bad X,Y path element.");
return(PFAILED);
}
PInteger(PReturned,PFAILONEOF);
if(PReturned == PFAILED)
return(PFAILED);
*Y = PInt;
return(PSUCCEEDED);
}
PLayer(){
char Technology,Mask[4];
int i;
Mask[0] = Mask[1] = Mask[2] = ' '; Mask[3] = NULL;
PCharacter(PReturned,PSTRIPWHITESPACE2,PFAILONEOF);
if(PReturned == PFAILED)
return(PFAILED);
if(PChar == ';'){
PError("At least one character expected after L in layer command.");
return(PFAILED);
}
Technology = PChar;
for(i=0; i<3; ++i){
if((PChar = getc(PCIFFileDesc)) == EOF){
PErrorEOF();
return(PFAILED);
}
elif(PChar == ';'){
if(ALayer(Technology,Mask) == PSUCCEEDED)
return(PSUCCEEDED);
else{
PErrorUndefinedLayer(Technology,Mask);
return(PFAILED);
}
}
Mask[i] = PChar;
/* check for valid CIF layer name character */
if(Not ((PChar >= '0' And PChar <= '9') Or
(PChar >= 'A' And PChar <= 'Z'))){
PErrorUndefinedLayer(Technology,Mask);
return(PFAILED);
}
}
/* clear the semicolon */
PCharacter(PReturned,PSTRIPWHITESPACE1,PFAILONEOF);
if(PReturned == PFAILED){
return(PFAILED);
}
elif(PChar == ';'){
if(ALayer(Technology,Mask) == PSUCCEEDED)
return(PSUCCEEDED);
else{
PErrorUndefinedLayer(Technology,Mask);
return(PFAILED);
}
}
PError("Illegal CIF layer name with > 4 characters discovered.");
return(PFAILED);
}
PUserExtension(){
char Digit;
int Int1;
Digit = PChar;
Int1 = 0;
loop{
PCharacter(PReturned,PLEAVEWHITESPACE,PFAILONEOF);
if(PReturned == PFAILED)
return(PFAILED);
elif(PChar == ';'){
PString[Int1] = EOS;
if(AUserExtension(Digit,PString) == PFAILED){
PErrorCD();
return(PFAILED);
}
#ifdef TRACE
fprintf(stderr,"PString = %s\n",PString);
#endif
return(PSUCCEEDED);
}
elif(Int1 == PSTRINGSIZE){
PError("User extension command longer than 1920 characters.");
return(PFAILED);
}
else PString[Int1++] = PChar;
}
}
PComment(){
int Int1;
Int1 = 0;
loop{
PCharacter(PReturned,PLEAVEWHITESPACE,PFAILONEOF);
if(PReturned == PFAILED)
return(PFAILED);
elif(PChar == ')'){
PCharacter(PReturned,PSTRIPWHITESPACE1,PFAILONEOF);
if(PReturned == PFAILED)
return(PFAILED);
elif(PChar == ';'){
PString[Int1] = EOS;
AComment(PString);
return(PSUCCEEDED);
}
elif(Int1 == PSTRINGSIZE){
PError("Comment command longer than 1920 characters.");
return(PFAILED);
}
else{
PErrorNoSemicolon();
return(PFAILED);
}
}
else PString[Int1++] = PChar;
}
}
PError(PErrorMessage)
char *PErrorMessage;
{
int Int1;
for(Int1 = 0;Int1 < 20;++Int1){
if(PChar == EOF)
break;
PCharacter(PReturned,PLEAVEWHITESPACE,PFAILONEOF);
if(PReturned == PFAILED)
break;
PString[Int1] = PChar;
}
PString[Int1] = EOS;
sprintf(PStatus,"%s. Failed at around %s.",PErrorMessage,PString);
#ifdef TRACE
fprintf(stderr,"%s\n",PErrorMessage);
#endif
}
PErrorEOF(){
PError("Early EOF.");
}
PErrorNoSemicolon(){
PError("; expected and not found.");
}
PErrorUndefinedLayer(Tech,Mask)
char Tech,*Mask;
{
char buf[35];
sprintf(buf,"Undefined layer: %c%s. ",Tech,Mask);
PError(buf);
}
PErrorCD(){
PError(CDStatusString);
}