/* * CIF parser code. * See "cif2ps.c" for authors' names and addresses. * Please honor the authors by not removing their attributions. */ #include "define.h" #include #define DELTA_A 'a' - 'A' init_cif() { layer = 0; } /*init_cif*/ get_next_cifline(stringer) char *stringer; { int i; int c; for(i = 0; i < MAXLINE; i++) { c = getchar(); if (c == ';') { stringer[i] = '\0'; return(i); } else if (c == '\n') { stringer[i] = ' '; no_lines++; } else if (c == EOF) { stringer[i] = '\0'; if (i) return(i); return(EOF); } else if (c == '(') { while (getchar() != ')') ; } else stringer[i] = c; } /* for (i ...) */ fprintf(stderr, "Cifline exceeded bounds\n"); stringer[i] = '\0'; cif_output(stderr, stringer); exit(1); /*NOTREACHED*/ } /*get_next_cifline*/ cif_output(filer, cif) FILE *filer; char *cif; { fprintf(filer, "%s\t\t(*near line %d*)\n", cif, no_lines); } /*cif_output*/ trim_cif(cif) char *cif; { int i, j, toggle_white; i = 0; j = 0; toggle_white = 1; /*so no white at beginning*/ for (i = 0; i < MAXLINE; i++) { if (cif[i] == COMMA) { cif[i] = WHITE; } if (cif[i] == '\0') { cif[j] = '\0'; return; } else if (white(cif[i])) { if ( !toggle_white) /*makes one white space*/ { cif[j++] = ' '; toggle_white = 1; } } else { cif[j++] = cif[i]; if (toggle_white) toggle_white = 0; } } /*for*/ } /*trim_cif*/ white(chr) char chr; { switch(chr) { case ' ': case '\t': return(1); default: return(0); } } /*white*/ symboltype *allocsymbol() { unsigned size = sizeof(symboltype); symboltype *symbol; symbol =(symboltype *) malloc(size); symbol->typer = 0; symbol->primitive.box = NULL; symbol->next = NULL; return(symbol); } /*allocsymbol*/ boxtype *allocbox() { unsigned size = sizeof(boxtype); boxtype *box; box = (boxtype *) malloc(size); return(box); } /*allocbox*/ int get_index(num) int num; { int i; for(i = 0; i <= last_symbol; i++) { if (symbol_table[i].symbol == num) return(i); } return(-1); } /*get_index*/ output_all_symbolnums(filer) FILE *filer; { int i; fprintf(filer, "Symbols are:\n"); for(i = 0; i <= last_symbol; i++) fprintf(filer, "%d\t%s\n", symbol_table[i].symbol, symbol_table[i].name); } /*output_all_symbolnums*/ do_cif() { char cif[MAXLINE]; while (get_next_cifline(cif) != EOF) { trim_cif(cif); switch(cif[0]) { case 'D': switch(cif[1]) { case 'S': ds(cif, DSTYPE); break; case 'F': df(); break; default: fprintf(stderr, "Unknown command in CIF\n"); cif_output(stderr, cif); break; } /*switch(cif[1]*/ break; case '9': switch(cif[1]) { case WHITE: nine(cif); break; case '4': ninety_four(cif); break; default: fprintf(stderr, "Unknown command in CIF\n"); cif_output(stderr, cif); break; } /*switchcif[1]*/ break; case 'B': cif_box(cif); break; case 'C': call_symbol(cif); break; case 'L': cif_change_layer(cif); break; case 'P': cif_polygon(cif); break; case 'R': cif_round(cif); break; case 'W': cif_wire(cif); break; case 0: break; case 'E': return; default: fprintf(stderr, "Syntax error:\n"); cif_output(stderr, cif); break; } /*switch*/ } /* while (get_next_cifline(cif)...) */ fprintf(stderr, "Premature end of file\n"); } /*do_cif*/ ds(cif, typer) char *cif; int typer; { int last_read, symnum, temp_index; char token[MAXTOKEN]; symboltype *symbol; last_read = get_token(cif, 2, token); /* space optional */ if (last_read == -1) { fprintf(stderr, "no symbol in DS\n"); cif_output(stderr, cif); return; } (void) sscanf(token, "%d", &symnum); temp_index = get_index(symnum); if (temp_index == -1) { if (++last_symbol == MAXSYMBOLS) { fprintf(stderr, "Exceeded the number of allowed symbols\n"); exit(1); } temp_index = last_symbol; } symbol_table[temp_index].symbol = symnum; symbol_table[temp_index].ll.x = BIGINT; symbol_table[temp_index].ll.y = BIGINT; symbol_table[temp_index].ur.x = -BIGINT; symbol_table[temp_index].ur.y = -BIGINT; symbol_table[temp_index].name[0] = '\0'; symbol_table[temp_index].a = 1; symbol_table[temp_index].b = 1; a_over_b = 1; symbol = allocsymbol(); if (typer == DSTYPE) { current_symbol_index = temp_index; present_symbol = symbol; } symbol->typer = DSTYPE; symbol_table[temp_index].pointer = symbol; *symbol_table[temp_index].name = '\0'; last_read = get_token(cif, last_read, token); if (last_read == -1) return; (void) sscanf(token, "%d", &(symbol_table[temp_index].a)); if (symbol_table[temp_index].a == 0) { fprintf(stderr, "read a 0 for A in DS\n"); cif_output(stderr, cif); symbol_table[temp_index].a = 1; } last_read = get_token(cif, last_read, token); if (last_read == -1) { fprintf(stderr, "A but no B in DS\n"); cif_output(stderr, cif); a_over_b = ((float) symbol_table[temp_index].a) / ((float) symbol_table[temp_index].b); return; } (void) sscanf(token, "%d", &(symbol_table[temp_index].b)); if (symbol_table[temp_index].b == 0) { fprintf(stderr, "read a 0 for B in DS\n"); cif_output(stderr, cif); symbol_table[temp_index].b = 1; } a_over_b = ((float) symbol_table[temp_index].a) / ((float) symbol_table[temp_index].b); } /*ds*/ int get_token(cif, from, token) /* copies token into *token */ char *cif; int from; char *token; { int i; /* passed end of cif statement yet? */ if ((from > 0) && (cif[from - 1] == '\0')) return(-1); /* skip leading white space */ while (cif[from] == WHITE) from++; for (i = 0; ((cif[i+from] != WHITE) && (cif[i+from] != COMMA));i++) { if (i >= MAXTOKEN-1) { fprintf(stderr,"token overflow!\n"); cif_output(stderr,cif); exit(1); } if (cif[i + from] == '\0') break; token[i] = cif[i + from]; } token[i] = '\0'; if (i == 0) return(-1); else return(i + from + 1); } /*get_token*/ df() { current_symbol_index = 0; present_symbol = symbol_table[current_symbol_index].pointer; } /*df*/ cif_box(cif) char *cif; { int next_one, i; int temp[4]; char token[MAXTOKEN]; boxtype *box, *allocbox(); bang_symbol(); present_symbol->typer = BOXTYPE; box = allocbox(); present_symbol->primitive.box = box; box->layer = layer; next_one = 1; /* space optional */ for(i = 0; i < 4; i++) { next_one = get_token(cif, next_one, token); if (next_one == -1) { fprintf(stderr, "incomplete box\n"); cif_output(stderr, cif); return; } (void) sscanf(token, "%d", &(temp[i])); } /* *temp = width, height, center-x, center-y */ box->llx = a_over_b * (temp[2] - temp[0]/2); box->urx = a_over_b * (temp[2] + temp[0]/2); box->lly = a_over_b * (temp[3] - temp[1]/2); box->ury = a_over_b * (temp[3] + temp[1]/2); } /*cif_box*/ cif_change_layer(cif) char *cif; { char token[MAXTOKEN]; if (-1 == get_token(cif, 1, token)) { /* space optional */ fprintf(stderr, "Error in layer command\n"); cif_output(stderr, cif); exit(1); } layer = layer_lookup(token); } /*cif_change_layers*/ #define PATHMALLOC 4 /* number of points per malloc */ cif_path(cif,ptpoints,ptarray) char *cif; /* the input statement */ int *ptpoints; /* place to return number of points */ int **ptarray; /* place to return address of array */ { static char *error = "can't read path"; static char token[MAXTOKEN]; static int x,y; int points=0; int column=0; /* current column in cif line */ int pointsMax = PATHMALLOC; /* initial size of array */ int *pointsArray = (int *) malloc( (unsigned) (PATHMALLOC*2*sizeof(int))); /* read all the points into the array */ while(-1 != (column = get_token(cif, column, token))) { if(1 != sscanf(token, "%d", &x)) { fprintf(stderr,"%s point %d X\n", error, points); cif_output(stderr,cif); points=0; break; } column = get_token(cif, column, token); if((column == -1) || (1 != sscanf(token, "%d", &y))) { fprintf(stderr,"%s point %d Y\n", error, points); cif_output(stderr,cif); points=0; break; } /* make sure there's room for the new X,Y */ if (points >= pointsMax) { pointsMax += PATHMALLOC; pointsArray = (int *) realloc((char *) pointsArray, (unsigned) (pointsMax * 2 * sizeof(int))); } if (!pointsArray) { fprintf(stderr,"out of memory\n"); exit(1); } /* store the X,Y pair in the array */ pointsArray[2*points] = x * a_over_b; pointsArray[2*points+1] = y * a_over_b; points++; } /* while (-1 != (column = get_token(...))) */ *ptpoints = points; *ptarray = pointsArray; } /* cif_path() */ cif_polygon(cif) char *cif; { static char *error = "can't read polygon"; ngontype *ngon; int points=0; int *pointsArray; /* read in the path (list of points) */ cif_path(&(cif[1]), &points, &pointsArray); /* make sure polygon has enough points */ if (points < 3) { fprintf(stderr,"degenerate polygon\n"); cif_output(stderr,cif); free((char *) pointsArray); return; } /* Finish up... */ bang_symbol(); present_symbol->typer = NGONTYPE; ngon = (ngontype *) malloc(sizeof(ngontype)); present_symbol->primitive.ngon = ngon; ngon->layer = layer; ngon->numPoints = points; ngon->ptrPoints = pointsArray; } /* cif_polygon() */ cif_round(cif) char *cif; { static char *error = "can't read roundflash %s\n"; static char token[MAXTOKEN]; static int x,y,r; int column=1; /* space optional */ roundtype *round; column = get_token(cif, column, token); if((column == -1) || (1 != sscanf(token, "%d", &x))) { fprintf(stderr,error,"X"); cif_output(stderr,cif); return; } column = get_token(cif, column, token); if((column == -1) || (1 != sscanf(token, "%d", &y))) { fprintf(stderr,error,"Y"); cif_output(stderr,cif); return; } column = get_token(cif, column, token); if((column == -1) || (1 != sscanf(token, "%d", &r))) { fprintf(stderr,error,"radius"); cif_output(stderr,cif); return; } /* Finish up... */ bang_symbol(); present_symbol->typer = ROUNDTYPE; round = (roundtype *) malloc(sizeof(roundtype)); present_symbol->primitive.round = round; round->layer = layer; round->x = x * a_over_b; round->y = y * a_over_b; round->r = r * a_over_b; } /* cif_round() */ cif_wire(cif) char *cif; { static char *error = "can't read wire"; static char token[MAXTOKEN]; static int width; int column=1; /* current column in cif line */ wiretype *wire; int points=0; int *pointsArray; /* read the wire width */ column = get_token(cif, column, token); if((column == -1) || (1 != sscanf(token, "%d", &width))) { fprintf(stderr,error,"width"); cif_output(stderr,cif); return; } /* read in the path (list of points) */ cif_path(&(cif[column]), &points, &pointsArray); /* make sure wire has enough points */ if (points < 2) { fprintf(stderr,"degenerate wire\n"); cif_output(stderr,cif); free((char *) pointsArray); return; } /* Finish up... */ bang_symbol(); present_symbol->typer = WIRETYPE; wire = (wiretype *) malloc(sizeof(wiretype)); present_symbol->primitive.wire = wire; wire->layer = layer; wire->width = width * a_over_b; wire->numPoints = points; wire->ptrPoints = pointsArray; } /* cif_wire() */ nine(cif) char *cif; { int foobar; char token[MAXTOKEN]; foobar = get_token(cif, 1, token); /* space optional */ if (foobar == -1) { fprintf(stderr, "Error in 9 command\n"); cif_output(stderr, cif); return; } (void) sscanf(token, "%s", symbol_table[current_symbol_index].name); } /*nine*/ bang_symbol() { present_symbol->next = allocsymbol(); present_symbol = present_symbol->next; } /*bang_symbol*/ ninety_four(cif) char *cif; { int last_read; char token[MAXTOKEN]; ninety_fourtype *ninety_four, *allocninety_four(); bang_symbol(); present_symbol->typer = NINETY_FOURTYPE; ninety_four = allocninety_four(); present_symbol->primitive.ninety_four = ninety_four; last_read = get_token(cif, 2, token); /* space optional */ if (last_read == -1) { fprintf(stderr, "no text in ninety_four\n"); cif_output(stderr, cif); return; } (void) sscanf(token, "%s", ninety_four->name); last_read = get_token(cif, last_read, token); if (last_read == -1) { fprintf(stderr, "no x in ninety_four\n"); cif_output(stderr, cif); return; } (void) sscanf(token, "%d", &(ninety_four->x)); ninety_four->x *= a_over_b; last_read = get_token(cif, last_read, token); if (last_read == -1) { fprintf(stderr, "no y in ninety_four\n"); cif_output(stderr, cif); return; } (void) sscanf(token, "%d", &(ninety_four->y)); ninety_four->y *= a_over_b; last_read = get_token(cif, last_read, token); if (last_read != -1) /*don't need layer on 94*/ ninety_four->layer = -1; } /*ninety_four*/ calltype *alloccall() { unsigned size = sizeof(calltype); calltype *call; call =(calltype *) malloc(size); call->symbol = -999; identity_matrix(call->matrix); return(call); } /*alloccall*/ ninety_fourtype *allocninety_four() { unsigned size = sizeof(ninety_fourtype); ninety_fourtype *ninety_four; ninety_four =(ninety_fourtype *) malloc(size); ninety_four->layer = 0; ninety_four->x = 0; ninety_four->y = 0; ninety_four->name[0] = '\0'; return(ninety_four); } /*allocninety_four*/