#include "gdsparse.h" #include #include #include #define GDS_ERROR(fmt, ...) printf("[PARSE_ERROR] " fmt "\n", #__VA_ARGS__) #define GDS_WARN(fmt, ...) printf("[PARSE_WARNING] " fmt "\n", #__VA_ARGS__) enum parsing_state {PARSING_LENGTH = 0, PARSING_TYPE, PARSING_DAT}; enum record { HEADER = 0x0002, BGNLIB = 0x0102, LIBNAME = 0x0206, UNITS = 0x0305, ENDLIB = 0x0400, BGNSTR = 0x0500, STRNAME = 0x0606, ENDSTR = 0x0700, }; static struct gds_library * append_library(struct gds_library *curr_arr, unsigned int curr_count) { unsigned int size = (curr_count +1) * sizeof(struct gds_library); return (struct gds_library *)realloc(curr_arr, size); } static struct gds_cell * append_cell(struct gds_cell *curr_arr, unsigned int curr_count) { unsigned int size = (curr_count +1) * sizeof(struct gds_cell); return (struct gds_cell *)realloc(curr_arr, size); } static int name_library(struct gds_library *current_library, unsigned int bytes, char* data) { int len; data[bytes] = 0; // Append '0' len = strlen(data); if (len > CELL_NAME_MAX-1) { GDS_ERROR("Library name '%s' too long: %d\n", data, len); return -1; } else { strcpy(current_library->name, data); printf("Named library: %s\n", current_library->name); } return 0; } static int name_cell(struct gds_cell *cell, unsigned int bytes, char* data) { int len; data[bytes] = 0; // Append '0' len = strlen(data); if (len > CELL_NAME_MAX-1) { GDS_ERROR("Library name '%s' too long: %d\n", data, len); return -1; } else { strcpy(cell->name, data); printf("Named library: %s\n", cell->name); } return 0; } int parse_gds_from_file(const char *filename, struct gds_library **library_array, unsigned int *count) { char workbuff[1024]; int read; int run = 1; FILE *gds_file = NULL; uint16_t rec_data_length; enum record rec_type; enum parsing_state state = PARSING_LENGTH; struct gds_library *current_lib = NULL; struct gds_cell *current_cell = NULL; struct gds_graphics *current_graphics = NULL; struct gds_cell_instance *current_s_reference = NULL; //////////// struct gds_library *lib_arr = NULL; struct gds_cell *cell_arr = NULL; unsigned int lib_arr_cnt = 0; unsigned int cell_arr_cnt = 0; /* open File */ gds_file = fopen(filename, "r"); if (gds_file == NULL) { GDS_ERROR("Could not open File %s", filename); return -1; } /* Record parser */ while (run == 1) { switch (state) { case PARSING_LENGTH: read = fread(workbuff, sizeof(char), 2, gds_file); if (read != 2 && (current_cell != NULL || current_graphics != NULL || current_lib != NULL || current_s_reference != NULL)) { GDS_ERROR("End of File. with openend structs/libs"); run = -2; break; } else if (read != 2) { /* EOF */ run = 0; break; } rec_data_length = (uint16_t)((((uint16_t)(workbuff[0])) << 8) | (uint16_t)(workbuff[1])); if (rec_data_length < 4) { /* Possible Zero-Padding: */ run = 0; GDS_WARN("Zero Padding detected!"); if (current_cell != NULL || current_graphics != NULL || current_lib != NULL || current_s_reference != NULL) { GDS_ERROR("Not all structures closed"); run = -2; } break; } rec_data_length -= 4; state = PARSING_TYPE; break; case PARSING_TYPE: read = fread(workbuff, sizeof(char), 2, gds_file); if (read != 2) { run = -2; GDS_ERROR("Unexpected end of file"); break; } rec_type = (uint16_t)((((uint16_t)(workbuff[0])) << 8) | (uint16_t)(workbuff[1])); state = PARSING_DAT; /* if begin: Allocate structures */ switch (rec_type) { case BGNLIB: lib_arr = append_library(lib_arr, lib_arr_cnt); lib_arr_cnt++; if (lib_arr == NULL) { GDS_ERROR("Allocating memory failed"); run = -3; break; } printf("Entering Lib\n"); current_lib = &(lib_arr[lib_arr_cnt-1]); break; case ENDLIB: if (current_lib == NULL) { run = -4; GDS_ERROR("Closing Library with no opened library"); break; } current_lib = NULL; printf("Leaving Library\n"); case BGNSTR: cell_arr = append_cell(cell_arr, cell_arr_cnt); cell_arr_cnt++; if (lib_arr == NULL) { GDS_ERROR("Allocating memory failed"); run = -3; break; } printf("Entering Cell\n"); current_cell = &(cell_arr[cell_arr_cnt-1]); break; case ENDSTR: if (current_cell == NULL) { run = -4; GDS_ERROR("Closing cell with no opened cell"); break; } current_cell = NULL; printf("Leaving Cell\n"); break; } break; case PARSING_DAT: read = fread(workbuff, sizeof(char), rec_data_length, gds_file); state = PARSING_LENGTH; if (read != rec_data_length) { GDS_ERROR("Could not read enough data"); run = -5; break; } /* No Data -> No Processing */ if (!read) break; switch (rec_type) { case LIBNAME: name_library(current_lib, read,workbuff); break; case STRNAME: name_cell(current_cell, read, workbuff); break; } break; } } fclose(gds_file); *library_array = lib_arr; *count = lib_arr_cnt; return run; }