GDS-Render v1.2.1
gds-parser.c
Go to the documentation of this file.
1/*
2 * GDSII-Converter
3 * Copyright (C) 2018 Mario Hüttel <mario.huettel@gmx.net>
4 *
5 * This file is part of GDSII-Converter.
6 *
7 * GDSII-Converter is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * GDSII-Converter is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
18 */
19
37#include <stdlib.h>
38#include <stdio.h>
39#include <string.h>
40#include <stdbool.h>
41#include <math.h>
42#include <cairo.h>
43#include <glib/gi18n.h>
44
46
51#define GDS_DEFAULT_UNITS (10E-9)
52
53#define GDS_ERROR(fmt, ...) printf("[PARSE_ERROR] " fmt "\n", ##__VA_ARGS__)
54#define GDS_WARN(fmt, ...) printf("[PARSE_WARNING] " fmt "\n", ##__VA_ARGS__)
56#if GDS_PRINT_DEBUG_INFOS
58 #define GDS_INF(fmt, ...) printf(fmt, ##__VA_ARGS__)
59#else
60 #define GDS_INF(fmt, ...)
61#endif
63 INVALID = 0x0000,
64 HEADER = 0x0002,
65 BGNLIB = 0x0102,
66 LIBNAME = 0x0206,
67 UNITS = 0x0305,
68 ENDLIB = 0x0400,
69 BGNSTR = 0x0502,
70 STRNAME = 0x0606,
71 ENDSTR = 0x0700,
72 BOUNDARY = 0x0800,
73 PATH = 0x0900,
74 SREF = 0x0A00,
75 ENDEL = 0x1100,
76 XY = 0x1003,
77 MAG = 0x1B05,
78 ANGLE = 0x1C05,
79 SNAME = 0x1206,
80 STRANS = 0x1A01,
81 BOX = 0x2D00,
82 LAYER = 0x0D02,
83 DATATYPE = 0x0E02,
84 WIDTH = 0x0F03,
85 PATHTYPE = 0x2102,
86 COLROW = 0x1302,
87 AREF = 0x0B00
88};
89
101 double angle;
104 int rows;
105};
106
114static int name_cell_ref(struct gds_cell_instance *cell_inst,
115 unsigned int bytes, char *data)
116{
117 int len;
118
119 if (cell_inst == NULL) {
120 GDS_ERROR("Naming cell ref with no opened cell ref");
121 return -1;
122 }
123 data[bytes] = 0; // Append '0'
124 len = (int)strlen(data);
125 if (len > CELL_NAME_MAX-1) {
126 GDS_ERROR("Cell name '%s' too long: %d\n", data, len);
127 return -1;
128 }
129
130 /* else: */
131 strcpy(cell_inst->ref_name, data);
132 GDS_INF("\tCell referenced: %s\n", cell_inst->ref_name);
133
134 return 0;
135}
136
144static int name_array_cell_ref(struct gds_cell_array_instance *cell_inst,
145 unsigned int bytes, char *data)
146{
147 int len;
148
149 if (cell_inst == NULL) {
150 GDS_ERROR("Naming array cell ref with no opened cell ref");
151 return -1;
152 }
153 data[bytes] = 0; // Append '0'
154 len = (int)strlen(data);
155 if (len > CELL_NAME_MAX-1) {
156 GDS_ERROR("Cell name '%s' too long: %d\n", data, len);
157 return -1;
158 }
159
160 /* else: */
161 strcpy(cell_inst->ref_name, data);
162 GDS_INF("\tCell referenced: %s\n", cell_inst->ref_name);
163
164 return 0;
165}
166
172static double gds_convert_double(const char *data)
173{
174 bool sign_bit;
175 int i;
176 double ret_val;
177 char current_byte;
178 int bit = 0;
179 int exponent;
180
181 sign_bit = ((data[0] & 0x80) ? true : false);
182
183 /* Check for real 0 */
184 for (i = 0; i < 8; i++) {
185 if (data[i] != 0)
186 break;
187 if (i == 7) {
188 /* All 8 bytes are 0 */
189 return 0.0;
190 }
191 }
192
193 /* Value is other than 0 */
194 ret_val = 0.0;
195 for (i = 8; i < 64; i++) {
196 current_byte = data[i/8];
197 bit = i % 8;
198 /* isolate bit */
199 if ((current_byte & (0x80 >> bit)))
200 ret_val += pow(2, ((double)(-i+7)));
201
202 }
203
204 /* Parse exponent and sign bit */
205 exponent = (int)(data[0] & 0x7F);
206 exponent -= 64;
207 ret_val *= pow(16, exponent) * (sign_bit == true ? -1 : 1);
208
209 return ret_val;
210}
211
217static signed int gds_convert_signed_int(const char *data)
218{
219 int ret;
220
221 if (!data) {
222 GDS_ERROR("Conversion from GDS data to signed int failed.");
223 return 0;
224 }
225
226 ret = (signed int)(((((int)data[0]) & 0xFF) << 24) |
227 ((((int)data[1]) & 0xFF) << 16) |
228 (((int)(data[2]) & 0xFF) << 8) |
229 (((int)(data[3]) & 0xFF) << 0));
230 return ret;
231}
232
238static int16_t gds_convert_signed_int16(const char *data)
239{
240 if (!data) {
241 GDS_ERROR("This should not happen");
242 return 0;
243 }
244 return (int16_t)((((int16_t)(data[0]) & 0xFF) << 8) |
245 (((int16_t)(data[1]) & 0xFF) << 0));
246}
247
253static uint16_t gds_convert_unsigned_int16(const char *data)
254{
255 if (!data) {
256 GDS_ERROR("This should not happen");
257 return 0;
258 }
259 return (uint16_t)((((uint16_t)(data[0]) & 0xFF) << 8) |
260 (((uint16_t)(data[1]) & 0xFF) << 0));
261}
262
269static GList *append_library(GList *curr_list, struct gds_library **library_ptr)
270{
271 struct gds_library *lib;
272
273 lib = (struct gds_library *)malloc(sizeof(struct gds_library));
274 if (lib) {
275 lib->cells = NULL;
276 lib->name[0] = 0;
277 lib->unit_in_meters = GDS_DEFAULT_UNITS; // Default. Will be overwritten
278 lib->cell_names = NULL;
279 } else
280 return NULL;
281 if (library_ptr)
282 *library_ptr = lib;
283
284 return g_list_append(curr_list, lib);
285}
286
294static __attribute__((warn_unused_result)) GList *prepend_graphics(GList *curr_list, enum graphics_type type,
295 struct gds_graphics **graphics_ptr)
296{
297 struct gds_graphics *gfx;
298
299 gfx = (struct gds_graphics *)malloc(sizeof(struct gds_graphics));
300 if (gfx) {
301 gfx->datatype = 0;
302 gfx->layer = 0;
303 gfx->vertices = NULL;
304 gfx->width_absolute = 0;
305 gfx->gfx_type = type;
307 } else
308 return NULL;
309
310 if (graphics_ptr)
311 *graphics_ptr = gfx;
312
313 return g_list_prepend(curr_list, gfx);
314}
315
323static GList *append_vertex(GList *curr_list, int x, int y)
324{
325 struct gds_point *vertex;
326
327 vertex = (struct gds_point *)malloc(sizeof(struct gds_point));
328 if (vertex) {
329 vertex->x = x;
330 vertex->y = y;
331 } else
332 return NULL;
333 return g_list_append(curr_list, vertex);
334}
335
344static GList *append_cell(GList *curr_list, struct gds_cell **cell_ptr)
345{
346 struct gds_cell *cell;
347
348 cell = (struct gds_cell *)malloc(sizeof(struct gds_cell));
349 if (cell) {
350 cell->child_cells = NULL;
351 cell->graphic_objs = NULL;
352 cell->name[0] = 0;
353 cell->parent_library = NULL;
356 } else
357 return NULL;
358 /* return cell */
359 if (cell_ptr)
360 *cell_ptr = cell;
361
362 return g_list_append(curr_list, cell);
363}
364
373static GList *append_cell_ref(GList *curr_list, struct gds_cell_instance **instance_ptr)
374{
375 struct gds_cell_instance *inst;
376
377 inst = (struct gds_cell_instance *)
378 malloc(sizeof(struct gds_cell_instance));
379 if (inst) {
380 inst->cell_ref = NULL;
381 inst->ref_name[0] = 0;
382 inst->magnification = 1.0;
383 inst->flipped = 0;
384 inst->angle = 0.0;
385 } else
386 return NULL;
387
388 if (instance_ptr)
389 *instance_ptr = inst;
390
391 return g_list_append(curr_list, inst);
392}
393
401static int name_library(struct gds_library *current_library,
402 unsigned int bytes, char *data)
403{
404 int len;
405
406 if (current_library == NULL) {
407 GDS_ERROR("Naming cell with no opened library");
408 return -1;
409 }
410
411 data[bytes] = 0; // Append '0'
412 len = (int)strlen(data);
413 if (len > CELL_NAME_MAX-1) {
414 GDS_ERROR("Library name '%s' too long: %d\n", data, len);
415 return -1;
416 }
417
418 strcpy(current_library->name, data);
419 GDS_INF("Named library: %s\n", current_library->name);
420
421 return 0;
422}
423
432static int name_cell(struct gds_cell *cell, unsigned int bytes,
433 char *data, struct gds_library *lib)
434{
435 int len;
436
437 if (cell == NULL) {
438 GDS_ERROR("Naming library with no opened library");
439 return -1;
440 }
441 data[bytes] = 0; // Append '0'
442 len = (int)strlen(data);
443 if (len > CELL_NAME_MAX-1) {
444 GDS_ERROR("Cell name '%s' too long: %d\n", data, len);
445 return -1;
446 }
447
448 strcpy(cell->name, data);
449 GDS_INF("Named cell: %s\n", cell->name);
450
451 /* Append cell name to lib's list of names */
452 lib->cell_names = g_list_append(lib->cell_names, cell->name);
453
454 return 0;
455}
456
464static void parse_reference_list(gpointer gcell_ref, gpointer glibrary)
465{
466 struct gds_cell_instance *inst = (struct gds_cell_instance *)gcell_ref;
467 struct gds_library *lib = (struct gds_library *)glibrary;
468 GList *cell_item;
469 struct gds_cell *cell;
470
471 GDS_INF("\t\t\tReference: %s: ", inst->ref_name);
472 /* Find cell */
473 for (cell_item = lib->cells; cell_item != NULL;
474 cell_item = cell_item->next) {
475
476 cell = (struct gds_cell *)cell_item->data;
477 /* Check if cell is found */
478 if (!strcmp(cell->name, inst->ref_name)) {
479 GDS_INF("found\n");
480 /* update reference link */
481 inst->cell_ref = cell;
482 return;
483 }
484 }
485
486 GDS_INF("MISSING!\n");
487 GDS_WARN("referenced cell could not be found in library");
488}
489
496static void scan_cell_reference_dependencies(gpointer gcell, gpointer library)
497{
498 struct gds_cell *cell = (struct gds_cell *)gcell;
499
500 GDS_INF("\tScanning cell: %s\n", cell->name);
501
502 /* Scan all library references */
503 g_list_foreach(cell->child_cells, parse_reference_list, library);
504
505}
506
514static void scan_library_references(gpointer library_list_item, gpointer user)
515{
516 struct gds_library *lib = (struct gds_library *)library_list_item;
517 (void)user;
518
519 GDS_INF("Scanning Library: %s\n", lib->name);
520 g_list_foreach(lib->cells, scan_cell_reference_dependencies, lib);
521}
522
530static void gds_parse_date(const char *buffer, int length, struct gds_time_field *mod_date, struct gds_time_field *access_date)
531{
532
533 struct gds_time_field *temp_date;
534
535 if (!access_date || !mod_date) {
536 GDS_WARN("Date structures invalid");
537 return;
538 }
539
540 if (length != (2*6*2)) {
541 GDS_WARN("Could not parse date field! Not the specified length");
542 return;
543 }
544
545 for (temp_date = mod_date; 1; temp_date = access_date) {
546 temp_date->year = gds_convert_unsigned_int16(buffer);
547 buffer += 2;
548 temp_date->month = gds_convert_unsigned_int16(buffer);
549 buffer += 2;
550 temp_date->day = gds_convert_unsigned_int16(buffer);
551 buffer += 2;
552 temp_date->hour = gds_convert_unsigned_int16(buffer);
553 buffer += 2;
554 temp_date->minute = gds_convert_unsigned_int16(buffer);
555 buffer += 2;
556 temp_date->second = gds_convert_unsigned_int16(buffer);
557 buffer += 2;
558
559 if (temp_date == access_date)
560 break;
561 }
562}
563
575static void convert_aref_to_sref(struct gds_cell_array_instance *aref, struct gds_cell *container_cell)
576{
577 struct gds_point origin;
578 struct gds_point row_shift_vector;
579 struct gds_point col_shift_vector;
580 struct gds_cell_instance *sref_inst = NULL;
581 int col;
582 int row;
583
584 if (!aref || !container_cell)
585 return;
586
587 if (aref->columns == 0 || aref->rows == 0) {
588 GDS_ERROR("Conversion of array instance aborted. No rows / columns.");
589 return;
590 }
591 origin.x = aref->control_points[0].x;
592 origin.y = aref->control_points[0].y;
593
594 row_shift_vector.x = (aref->control_points[2].x - origin.x) / aref->rows;
595 row_shift_vector.y = (aref->control_points[2].y - origin.y) / aref->rows;
596 col_shift_vector.x = (aref->control_points[1].x - origin.x) / aref->columns;
597 col_shift_vector.y = (aref->control_points[1].y - origin.y) / aref->columns;
598
599 /* Iterate over columns and rows */
600 for (col = 0; col < aref->columns; col++) {
601 for (row = 0; row < aref->rows; row++) {
602 /* Create new instance for this row/column and configure data */
603 container_cell->child_cells = append_cell_ref(container_cell->child_cells, &sref_inst);
604 if (!sref_inst) {
605 GDS_ERROR("Appending cell ref failed!");
606 continue;
607 }
608
609 sref_inst->angle = aref->angle;
610 sref_inst->magnification = aref->magnification;
611 sref_inst->flipped = aref->flipped;
612 strncpy(sref_inst->ref_name, aref->ref_name, CELL_NAME_MAX);
613 sref_inst->origin.x = origin.x + row_shift_vector.x * row + col_shift_vector.x * col;
614 sref_inst->origin.y = origin.y + row_shift_vector.y * row + col_shift_vector.y * col;
615 }
616 }
617 GDS_INF("Converted AREF to SREFs\n");
618}
619
620int parse_gds_from_file(const char *filename, GList **library_list)
621{
622 char *workbuff;
623 int read;
624 int i;
625 int run = 1;
626 FILE *gds_file = NULL;
627 uint16_t rec_data_length;
628 enum gds_record rec_type;
629 struct gds_library *current_lib = NULL;
630 struct gds_cell *current_cell = NULL;
631 struct gds_graphics *current_graphics = NULL;
632 struct gds_cell_instance *current_s_reference = NULL;
633 struct gds_cell_array_instance *current_a_reference = NULL;
634 struct gds_cell_array_instance temp_a_reference;
635 int x, y;
637 GList *lib_list;
638
639 lib_list = *library_list;
640
641 /* Allocate working buffer */
642 workbuff = (char *)malloc(sizeof(char)*128*1024);
643
644 if(!workbuff)
645 return -100;
646
647 /* open File */
648 gds_file = fopen(filename, "rb");
649 if (gds_file == NULL) {
650 GDS_ERROR("Could not open File %s", filename);
651 return -1;
652 }
653
654 /* Record parser */
655 while (run == 1) {
656 rec_type = INVALID;
657 read = fread(workbuff, sizeof(char), 2, gds_file);
658 if (read != 2 && (current_cell != NULL ||
659 current_graphics != NULL ||
660 current_lib != NULL ||
661 current_s_reference != NULL)) {
662 GDS_ERROR("End of File. with openend structs/libs");
663 run = -2;
664 break;
665 } else if (read != 2) {
666 /* EOF */
667 run = 0;
668 break;
669 }
670
671 rec_data_length = gds_convert_unsigned_int16(workbuff);
672
673 if (rec_data_length < 4) {
674 /* Possible Zero-Padding: */
675 run = 0;
676 GDS_WARN("Zero Padding detected!");
677 if (current_cell != NULL ||
678 current_graphics != NULL ||
679 current_lib != NULL ||
680 current_s_reference != NULL) {
681 GDS_ERROR("Not all structures closed");
682 run = -2;
683 }
684 break;
685 }
686 rec_data_length -= 4;
687
688 read = fread(workbuff, sizeof(char), 2, gds_file);
689 if (read != 2) {
690 run = -2;
691 GDS_ERROR("Unexpected end of file");
692 break;
693 }
694 rec_type = gds_convert_unsigned_int16(workbuff);
695
696
697 /* if begin: Allocate structures */
698 switch (rec_type) {
699 case BGNLIB:
700 lib_list = append_library(lib_list, &current_lib);
701 if (lib_list == NULL) {
702 GDS_ERROR("Allocating memory failed");
703 run = -3;
704 break;
705
706 }
707 GDS_INF("Entering Lib\n");
708 break;
709 case ENDLIB:
710 if (current_lib == NULL) {
711 run = -4;
712 GDS_ERROR("Closing Library with no opened library");
713 break;
714 }
715
716 /* Check for open Cells */
717 if (current_cell != NULL) {
718 run = -4;
719 GDS_ERROR("Closing Library with opened cells");
720 break;
721 }
722 current_lib = NULL;
723 GDS_INF("Leaving Library\n");
724 break;
725 case BGNSTR:
726 if (current_lib == NULL) {
727 GDS_ERROR("Defining Cell outside of library!\n");
728 run = -4;
729 break;
730 }
731 current_lib->cells = append_cell(current_lib->cells, &current_cell);
732 if (current_lib->cells == NULL) {
733 GDS_ERROR("Allocating memory failed");
734 run = -3;
735 break;
736 }
737
738 current_cell->parent_library = current_lib;
739
740 GDS_INF("Entering cell\n");
741 break;
742 case ENDSTR:
743 if (current_cell == NULL) {
744 run = -4;
745 GDS_ERROR("Closing cell with no opened cell");
746 break;
747 }
748 /* Check for open Elements */
749 if (current_graphics != NULL || current_s_reference != NULL) {
750 run = -4;
751 GDS_ERROR("Closing cell with opened Elements");
752 break;
753 }
754 current_cell = NULL;
755 GDS_INF("Leaving Cell\n");
756 break;
757 case BOX:
758 case BOUNDARY:
759 if (current_cell == NULL) {
760 GDS_ERROR("Boundary/Box outside of cell");
761 run = -3;
762 break;
763 }
764 current_cell->graphic_objs = prepend_graphics(current_cell->graphic_objs,
765 (rec_type == BOUNDARY
767 : GRAPHIC_BOX),
768 &current_graphics);
769 if (current_cell->graphic_objs == NULL) {
770 GDS_ERROR("Memory allocation failed");
771 run = -4;
772 break;
773 }
774 GDS_INF("\tEntering boundary/Box\n");
775 break;
776 case SREF:
777 if (current_cell == NULL) {
778 GDS_ERROR("Cell Reference outside of cell");
779 run = -3;
780 break;
781 }
782 current_cell->child_cells = append_cell_ref(current_cell->child_cells,
783 &current_s_reference);
784 if (current_cell->child_cells == NULL) {
785 GDS_ERROR("Memory allocation failed");
786 run = -4;
787 break;
788 }
789
790 GDS_INF("\tEntering reference\n");
791 break;
792 case PATH:
793 if (current_cell == NULL) {
794 GDS_ERROR("Path outside of cell");
795 run = -3;
796 break;
797 }
798 current_cell->graphic_objs = prepend_graphics(current_cell->graphic_objs,
799 GRAPHIC_PATH, &current_graphics);
800 if (current_cell->graphic_objs == NULL) {
801 GDS_ERROR("Memory allocation failed");
802 run = -4;
803 break;
804 }
805 GDS_INF("\tEntering Path\n");
806 break;
807 case ENDEL:
808 if (current_graphics != NULL) {
809 GDS_INF("\tLeaving %s\n", (current_graphics->gfx_type == GRAPHIC_POLYGON ? "boundary" : "path"));
810 current_graphics = NULL;
811 }
812 if (current_s_reference != NULL) {
813 GDS_INF("\tLeaving Reference\n");
814 current_s_reference = NULL;
815 }
816 if (current_a_reference != NULL) {
817 GDS_INF("\tLeaving Array Reference\n");
818 convert_aref_to_sref(current_a_reference, current_cell);
819 current_a_reference = NULL;
820 }
821
822 break;
823 case XY:
824 if (current_graphics) {
825
826 } else if (current_s_reference) {
827 if (rec_data_length != 8) {
828 GDS_WARN("Instance has weird coordinates. Rendered output might be screwed!");
829 }
830 } else if (current_a_reference) {
831 if (rec_data_length != (3*(4+4)))
832 GDS_WARN("Array instance has weird coordinates. Rendered output might be screwed!");
833 }
834 break;
835 case AREF:
836 if (current_cell == NULL) {
837 GDS_ERROR("Cell array reference outside of cell");
838 run = -3;
839 break;
840 }
841
842 if (current_a_reference != NULL) {
843 GDS_ERROR("Recursive cell array reference");
844 run = -3;
845 break;
846 }
847
848 GDS_INF("Entering Array Reference\n");
849
850 /* Array references are coverted after fully declared. Therefore,
851 * only a static buffer is needed
852 */
853 current_a_reference = &temp_a_reference;
854 current_a_reference->ref_name[0] = '\0';
855 current_a_reference->angle = 0.0;
856 current_a_reference->magnification = 1.0;
857 current_a_reference->flipped = 0;
858 current_a_reference->rows = 0;
859 current_a_reference->columns = 0;
860 break;
861 case COLROW:
862 case MAG:
863 case ANGLE:
864 case STRANS:
865 case WIDTH:
866 case PATHTYPE:
867 case UNITS:
868 case LIBNAME:
869 case SNAME:
870 case LAYER:
871 case DATATYPE:
872 case STRNAME:
873 break;
874 default:
875 GDS_INF("Unhandled Record: %04x, len: %u\n", (unsigned int)rec_type, (unsigned int)rec_data_length);
876 break;
877 } /* switch(rec_type) */
878
879
880 /* No Data -> No Processing, go back to top */
881 if (!rec_data_length || run != 1) continue;
882
883 read = fread(workbuff, sizeof(char), rec_data_length, gds_file);
884
885 if (read != rec_data_length) {
886 GDS_ERROR("Could not read enough data: requested: %u, read: %u | Type: 0x%04x\n",
887 (unsigned int)rec_data_length, (unsigned int)read, (unsigned int)rec_type);
888 run = -5;
889 break;
890 }
891
892 switch (rec_type) {
893 case AREF:
894 case HEADER:
895 case ENDLIB:
896 case ENDSTR:
897 case BOUNDARY:
898 case PATH:
899 case SREF:
900 case ENDEL:
901 case BOX:
902 case INVALID:
903 break;
904
905 case COLROW:
906 if (!current_a_reference) {
907 GDS_ERROR("COLROW record defined outside of array instance");
908 break;
909 }
910 if (rec_data_length != 4 || read != 4) {
911 GDS_ERROR("COLUMN/ROW count record contains too few data. Won't set column and row counts (%d, %d)",
912 rec_data_length, read);
913 break;
914 }
915 current_a_reference->columns = (int)gds_convert_signed_int16(&workbuff[0]);
916 current_a_reference->rows = (int)gds_convert_signed_int16(&workbuff[2]);
917 GDS_INF("\tRows: %d\n\tColumns: %d\n", current_a_reference->rows, current_a_reference->columns);
918 break;
919 case UNITS:
920 if (!current_lib) {
921 GDS_WARN("Units defined outside of library!\n");
922 break;
923 }
924
925 if (rec_data_length != 16) {
926 GDS_WARN("Unit define incomplete. Will assume database unit of %E meters\n", current_lib->unit_in_meters);
927 break;
928 }
929
930 current_lib->unit_in_meters = gds_convert_double(&workbuff[8]);
931 GDS_INF("Length of database unit: %E meters\n", current_lib->unit_in_meters);
932 break;
933 case BGNLIB:
934 /* Parse date record */
935 gds_parse_date(workbuff, read, &current_lib->mod_time, &current_lib->access_time);
936 break;
937 case BGNSTR:
938 gds_parse_date(workbuff, read, &current_cell->mod_time, &current_cell->access_time);
939 break;
940 case LIBNAME:
941 name_library(current_lib, (unsigned int)read, workbuff);
942 break;
943 case STRNAME:
944 name_cell(current_cell, (unsigned int)read, workbuff, current_lib);
945 break;
946 case XY:
947 if (current_s_reference) {
948 /* Get origin of reference */
949 current_s_reference->origin.x = gds_convert_signed_int(workbuff);
950 current_s_reference->origin.y = gds_convert_signed_int(&workbuff[4]);
951 GDS_INF("\t\tSet origin to: %d/%d\n", current_s_reference->origin.x,
952 current_s_reference->origin.y);
953 } else if (current_graphics) {
954 for (i = 0; i < read/8; i++) {
955 x = gds_convert_signed_int(&workbuff[i*8]);
956 y = gds_convert_signed_int(&workbuff[i*8+4]);
957 current_graphics->vertices =
958 append_vertex(current_graphics->vertices, x, y);
959 GDS_INF("\t\tSet coordinate: %d/%d\n", x, y);
960
961 }
962 } else if (current_a_reference) {
963 for (i = 0; i < 3; i++) {
964 x = gds_convert_signed_int(&workbuff[i*8]);
965 y = gds_convert_signed_int(&workbuff[i*8+4]);
966 current_a_reference->control_points[i].x = x;
967 current_a_reference->control_points[i].y = y;
968 GDS_INF("\tSet control point %d: %d/%d\n", i, x, y);
969 }
970 }
971 break;
972 case STRANS:
973 if (current_s_reference) {
974 current_s_reference->flipped = ((workbuff[0] & 0x80) ? 1 : 0);
975 } else if (current_a_reference) {
976 current_a_reference->flipped = ((workbuff[0] & 0x80) ? 1 : 0);
977 } else {
978 GDS_ERROR("Transformation defined outside of instance");
979 break;
980 }
981 break;
982 case SNAME:
983 if (current_s_reference) {
984 name_cell_ref(current_s_reference, (unsigned int)read, workbuff);
985 } else if (current_a_reference) {
986 name_array_cell_ref(current_a_reference, (unsigned int)read, workbuff);
987 } else {
988 GDS_ERROR("Reference name set outside of cell reference");
989 }
990 break;
991 case WIDTH:
992 if (!current_graphics) {
993 GDS_WARN("Width defined outside of path element");
994 }
995 current_graphics->width_absolute = gds_convert_signed_int(workbuff);
996 break;
997 case LAYER:
998 if (!current_graphics) {
999 GDS_WARN("Layer has to be defined inside graphics object. Probably unknown object. Implement it yourself!");
1000 break;
1001 }
1002 current_graphics->layer = gds_convert_signed_int16(workbuff);
1003 if (current_graphics->layer < 0) {
1004 GDS_WARN("Layer negative!\n");
1005 }
1006 GDS_INF("\t\tAdded layer %d\n", (int)current_graphics->layer);
1007 break;
1008 case DATATYPE:
1009 if (!current_graphics) {
1010 GDS_WARN("Datatype has to be defined inside graphics object. Probably unknown object. Implement it yourself!");
1011 break;
1012 }
1013 current_graphics->datatype = gds_convert_signed_int16(workbuff);
1014 if (current_graphics->datatype < 0)
1015 GDS_WARN("Datatype negative!");
1016 GDS_INF("\t\tAdded datatype %d\n", (int)current_graphics->datatype);
1017 break;
1018 case MAG:
1019 if (rec_data_length != 8) {
1020 GDS_WARN("Magnification is not an 8 byte real. Results may be wrong");
1021 }
1022 if (current_graphics != NULL && current_s_reference != NULL) {
1023 GDS_ERROR("Open Graphics and Cell Reference\n\tMissing ENDEL?");
1024 run = -6;
1025 break;
1026 }
1027 if (current_s_reference != NULL) {
1028 current_s_reference->magnification = gds_convert_double(workbuff);
1029 GDS_INF("\t\tMagnification defined: %lf\n", current_s_reference->magnification);
1030 }
1031 if (current_a_reference != NULL) {
1032 current_a_reference->magnification = gds_convert_double(workbuff);
1033 GDS_INF("\t\tMagnification defined: %lf\n", current_a_reference->magnification);
1034 }
1035 break;
1036 case ANGLE:
1037 if (rec_data_length != 8) {
1038 GDS_WARN("Angle is not an 8 byte real. Results may be wrong");
1039 }
1040 if (current_graphics != NULL && current_s_reference != NULL && current_a_reference != NULL) {
1041 GDS_ERROR("Open Graphics and Cell Reference\n\tMissing ENDEL?");
1042 run = -6;
1043 break;
1044 }
1045 if (current_s_reference != NULL) {
1046 current_s_reference->angle = gds_convert_double(workbuff);
1047 GDS_INF("\t\tAngle defined: %lf\n", current_s_reference->angle);
1048 }
1049 if (current_a_reference != NULL) {
1050 current_a_reference->angle = gds_convert_double(workbuff);
1051 GDS_INF("\t\tAngle defined: %lf\n", current_a_reference->angle);
1052 }
1053 break;
1054 case PATHTYPE:
1055 if (current_graphics == NULL) {
1056 GDS_WARN("Path type defined outside of path. Ignoring");
1057 break;
1058 }
1059 if (current_graphics->gfx_type == GRAPHIC_PATH) {
1060 current_graphics->path_render_type = (enum path_type)gds_convert_signed_int16(workbuff);
1061 GDS_INF("\t\tPathtype: %d\n", current_graphics->path_render_type);
1062 } else {
1063 GDS_WARN("Path type defined inside non-path graphics object. Ignoring");
1064 }
1065 break;
1066
1067 }
1068
1069 } /* while(run == 1) */
1070
1071 fclose(gds_file);
1072
1073 if (!run) {
1074 /* Iterate and find references to cells */
1075 g_list_foreach(lib_list, scan_library_references, NULL);
1076 }
1077
1078 *library_list = lib_list;
1079
1080 free(workbuff);
1081
1082 return run;
1083}
1084
1089static void delete_cell_inst_element(struct gds_cell_instance *cell_inst)
1090{
1091 if (cell_inst)
1092 free(cell_inst);
1093}
1094
1099static void delete_vertex(struct gds_point *vertex)
1100{
1101 if (vertex)
1102 free(vertex);
1103}
1104
1109static void delete_graphics_obj(struct gds_graphics *gfx)
1110{
1111 if (!gfx)
1112 return;
1113
1114 g_list_free_full(gfx->vertices, (GDestroyNotify)delete_vertex);
1115 free(gfx);
1116}
1117
1122static void delete_cell_element(struct gds_cell *cell)
1123{
1124 if (!cell)
1125 return;
1126
1127 g_list_free_full(cell->child_cells, (GDestroyNotify)delete_cell_inst_element);
1128 g_list_free_full(cell->graphic_objs, (GDestroyNotify)delete_graphics_obj);
1129 free(cell);
1130}
1131
1136static void delete_library_element(struct gds_library *lib)
1137{
1138 if (!lib)
1139 return;
1140
1141 g_list_free(lib->cell_names);
1142 g_list_free_full(lib->cells, (GDestroyNotify)delete_cell_element);
1143 free(lib);
1144}
1145
1146int clear_lib_list(GList **library_list)
1147{
1148 if (!library_list)
1149 return 0;
1150
1151 if (*library_list == NULL)
1152 return 0;
1153
1154 g_list_free_full(*library_list, (GDestroyNotify)delete_library_element);
1155 *library_list = NULL;
1156 return 0;
1157}
1158
Header file for the GDS-Parser.
static void delete_cell_element(struct gds_cell *cell)
delete_cell_element
Definition: gds-parser.c:1122
static int name_cell_ref(struct gds_cell_instance *cell_inst, unsigned int bytes, char *data)
Name cell reference.
Definition: gds-parser.c:114
#define GDS_DEFAULT_UNITS
Default units assumed for library.
Definition: gds-parser.c:51
static GList * append_cell(GList *curr_list, struct gds_cell **cell_ptr)
append_cell Append a gds_cell to a list
Definition: gds-parser.c:344
static GList * append_vertex(GList *curr_list, int x, int y)
Appends vertext List.
Definition: gds-parser.c:323
static void delete_vertex(struct gds_point *vertex)
delete_vertex
Definition: gds-parser.c:1099
static int name_library(struct gds_library *current_library, unsigned int bytes, char *data)
Name a gds_library.
Definition: gds-parser.c:401
static int name_array_cell_ref(struct gds_cell_array_instance *cell_inst, unsigned int bytes, char *data)
Name cell reference.
Definition: gds-parser.c:144
static void convert_aref_to_sref(struct gds_cell_array_instance *aref, struct gds_cell *container_cell)
Convert AREF to a bunch of SREFs and append them to container_cell.
Definition: gds-parser.c:575
#define GDS_WARN(fmt,...)
Print GDS warning.
Definition: gds-parser.c:54
#define GDS_ERROR(fmt,...)
Print GDS error.
Definition: gds-parser.c:53
static double gds_convert_double(const char *data)
Convert GDS 8-byte real to double.
Definition: gds-parser.c:172
static signed int gds_convert_signed_int(const char *data)
Convert GDS INT32 to int.
Definition: gds-parser.c:217
static void scan_library_references(gpointer library_list_item, gpointer user)
Scans library's cell references.
Definition: gds-parser.c:514
static GList * append_cell_ref(GList *curr_list, struct gds_cell_instance **instance_ptr)
Append a cell reference to the reference GList.
Definition: gds-parser.c:373
static void delete_graphics_obj(struct gds_graphics *gfx)
delete_graphics_obj
Definition: gds-parser.c:1109
#define GDS_INF(fmt,...)
Definition: gds-parser.c:60
static void parse_reference_list(gpointer gcell_ref, gpointer glibrary)
Search for cell reference gcell_ref in glibrary.
Definition: gds-parser.c:464
static void gds_parse_date(const char *buffer, int length, struct gds_time_field *mod_date, struct gds_time_field *access_date)
gds_parse_date
Definition: gds-parser.c:530
static void delete_cell_inst_element(struct gds_cell_instance *cell_inst)
delete_cell_inst_element
Definition: gds-parser.c:1089
static void scan_cell_reference_dependencies(gpointer gcell, gpointer library)
Scans cell references inside cell This function searches all the references in gcell and updates the ...
Definition: gds-parser.c:496
graphics_type
Types of graphic objects.
Definition: gds-types.h:49
gds_record
Definition: gds-parser.c:62
int clear_lib_list(GList **library_list)
Deletes all libraries including cells, references etc.
Definition: gds-parser.c:1146
static GList * prepend_graphics(GList *curr_list, enum graphics_type type, struct gds_graphics **graphics_ptr)
Prepend graphics to list.
Definition: gds-parser.c:294
static int name_cell(struct gds_cell *cell, unsigned int bytes, char *data, struct gds_library *lib)
Names a gds_cell.
Definition: gds-parser.c:432
path_type
Defines the line caps of a path.
Definition: gds-types.h:58
static uint16_t gds_convert_unsigned_int16(const char *data)
Convert GDS UINT16 String to uint16.
Definition: gds-parser.c:253
int parse_gds_from_file(const char *filename, GList **library_list)
Parse a GDS file.
Definition: gds-parser.c:620
static int16_t gds_convert_signed_int16(const char *data)
Convert GDS INT16 to int16.
Definition: gds-parser.c:238
static GList * append_library(GList *curr_list, struct gds_library **library_ptr)
Append library to list.
Definition: gds-parser.c:269
static void delete_library_element(struct gds_library *lib)
delete_library_element
Definition: gds-parser.c:1136
#define CELL_NAME_MAX
Maximum length of a gds_cell::name or a gds_library::name.
Definition: gds-types.h:37
@ GRAPHIC_POLYGON
An arbitrary polygon.
Definition: gds-types.h:51
@ GRAPHIC_PATH
Path. Esentially a line.
Definition: gds-types.h:50
@ GRAPHIC_BOX
A rectangle.
Definition: gds-types.h:52
@ ANGLE
Definition: gds-parser.c:78
@ UNITS
Definition: gds-parser.c:67
@ XY
Definition: gds-parser.c:76
@ DATATYPE
Definition: gds-parser.c:83
@ LAYER
Definition: gds-parser.c:82
@ COLROW
Definition: gds-parser.c:86
@ HEADER
Definition: gds-parser.c:64
@ BOX
Definition: gds-parser.c:81
@ SREF
Definition: gds-parser.c:74
@ BGNLIB
Definition: gds-parser.c:65
@ SNAME
Definition: gds-parser.c:79
@ MAG
Definition: gds-parser.c:77
@ AREF
Definition: gds-parser.c:87
@ STRNAME
Definition: gds-parser.c:70
@ WIDTH
Definition: gds-parser.c:84
@ BGNSTR
Definition: gds-parser.c:69
@ STRANS
Definition: gds-parser.c:80
@ ENDEL
Definition: gds-parser.c:75
@ ENDLIB
Definition: gds-parser.c:68
@ LIBNAME
Definition: gds-parser.c:66
@ BOUNDARY
Definition: gds-parser.c:72
@ PATHTYPE
Definition: gds-parser.c:85
@ ENDSTR
Definition: gds-parser.c:71
@ PATH
Definition: gds-parser.c:73
@ INVALID
Definition: gds-parser.c:63
@ PATH_FLUSH
Definition: gds-types.h:58
@ GDS_CELL_CHECK_NOT_RUN
Definition: gds-types.h:45
Struct representing an array instantiation.
Definition: gds-parser.c:96
struct gds_point control_points[3]
The three control points.
Definition: gds-parser.c:99
int rows
Row count.
Definition: gds-parser.c:104
int flipped
Mirror each instance on x-axis before rotation.
Definition: gds-parser.c:100
int columns
Column count.
Definition: gds-parser.c:103
double angle
Angle of rotation for each instance (counter clockwise) in degrees.
Definition: gds-parser.c:101
double magnification
Magnification of each instance.
Definition: gds-parser.c:102
struct gds_cell * cell_ref
Referenced gds_cell structure.
Definition: gds-parser.c:98
char ref_name[CELL_NAME_MAX]
Name of referenced cell.
Definition: gds-parser.c:97
int unresolved_child_count
Number of unresolved cell instances inside this cell. Default: GDS_CELL_CHECK_NOT_RUN.
Definition: gds-types.h:72
int affected_by_reference_loop
1 if the cell is affected by a reference loop and therefore not renderable. Default: GDS_CELL_CHECK_N...
Definition: gds-types.h:73
This represents an instanc of a cell inside another cell.
Definition: gds-types.h:110
int flipped
Mirrored on x-axis before rotation.
Definition: gds-types.h:114
double angle
Angle of rotation (counter clockwise) in degrees.
Definition: gds-types.h:115
double magnification
magnification
Definition: gds-types.h:116
struct gds_cell * cell_ref
Referenced gds_cell structure.
Definition: gds-types.h:112
struct gds_point origin
Origin.
Definition: gds-types.h:113
char ref_name[CELL_NAME_MAX]
Name of referenced cell.
Definition: gds-types.h:111
A Cell inside a gds_library.
Definition: gds-types.h:122
struct gds_time_field mod_time
Definition: gds-types.h:124
struct gds_cell_checks checks
Checking results.
Definition: gds-types.h:129
struct gds_time_field access_time
Definition: gds-types.h:125
char name[CELL_NAME_MAX]
Definition: gds-types.h:123
GList * child_cells
List of gds_cell_instance elements.
Definition: gds-types.h:126
struct gds_library * parent_library
Pointer to parent library.
Definition: gds-types.h:128
GList * graphic_objs
List of gds_graphics.
Definition: gds-types.h:127
A GDS graphics object.
Definition: gds-types.h:98
int16_t datatype
Data type of graphic object.
Definition: gds-types.h:104
enum graphics_type gfx_type
Type of graphic.
Definition: gds-types.h:99
enum path_type path_render_type
Line cap.
Definition: gds-types.h:101
int width_absolute
Width. Not used for objects other than paths.
Definition: gds-types.h:102
int16_t layer
Layer the graphic object is on.
Definition: gds-types.h:103
GList * vertices
List of gds_point.
Definition: gds-types.h:100
GDS Toplevel library.
Definition: gds-types.h:135
struct gds_time_field mod_time
Definition: gds-types.h:137
double unit_in_meters
Definition: gds-types.h:139
struct gds_time_field access_time
Definition: gds-types.h:138
GList * cells
Definition: gds-types.h:140
char name[CELL_NAME_MAX]
Definition: gds-types.h:136
GList * cell_names
Definition: gds-types.h:141
A point in the 2D plane. Sometimes referred to as vertex.
Definition: gds-types.h:63
Date information for cells and libraries.
Definition: gds-types.h:86
uint16_t second
Definition: gds-types.h:92
uint16_t hour
Definition: gds-types.h:90
uint16_t month
Definition: gds-types.h:88
uint16_t year
Definition: gds-types.h:87
uint16_t minute
Definition: gds-types.h:91
uint16_t day
Definition: gds-types.h:89