47 #include <sys/types.h>
61 #define DPRINTF(...) do { if (DEBUG) printf(__VA_ARGS__); } while (0)
64 #define DRILL_READ_DOUBLE_SIZE 32
67 DRILL_NONE, DRILL_HEADER, DRILL_DATA
68 } drill_file_section_t;
71 DRILL_MODE_ABSOLUTE, DRILL_MODE_INCREMENTAL
72 } drill_coordinate_mode_t;
82 typedef struct drill_state {
86 drill_file_section_t curr_section;
87 drill_coordinate_mode_t coordinate_mode;
97 number_fmt_t number_format, header_number_format;
99 number_fmt_t backup_number_format;
118 drill_g_code_t route_mode;
128 static drill_g_code_t drill_parse_G_code(gerb_file_t *fd,
130 static drill_m_code_t drill_parse_M_code(gerb_file_t *fd, drill_state_t *state,
132 static int drill_parse_T_code(gerb_file_t *fd, drill_state_t *state,
134 static int drill_parse_header_is_metric(gerb_file_t *fd, drill_state_t *state,
136 static int drill_parse_header_is_metric_comment(gerb_file_t *fd, drill_state_t *state,
138 static int drill_parse_header_is_inch(gerb_file_t *fd, drill_state_t *state,
140 static int drill_parse_header_is_ici(gerb_file_t *fd, drill_state_t *state,
142 static void drill_parse_coordinate(gerb_file_t *fd,
char firstchar,
144 unsigned int file_line);
145 static drill_state_t *new_state(drill_state_t *state);
147 drill_state_t *state,
150 double prev_x,
double prev_y);
152 drill_state_t *state,
155 double prev_x,
double prev_y);
156 static double read_double(gerb_file_t *fd, number_fmt_t fmt,
158 static void eat_line(gerb_file_t *fd);
159 static void eat_whitespace(gerb_file_t *fd);
160 static char *get_line(gerb_file_t *fd);
161 static int file_check_str(gerb_file_t *fd,
const char *str);
174 static const char *suppression_list[] = {
181 static const char *units_list[] = {
197 static gerbv_HID_Attribute drill_attribute_list[] = {
199 {N_(
"autodetect"), N_(
"Try to autodetect the file format"),
200 HID_Boolean, 0, 0, {1, 0, 0}, 0, 0, 0},
202 {N_(
"zero_suppression"), N_(
"Zero suppression"),
203 HID_Enum, 0, 0, {0, 0, 0}, suppression_list, 0, 0},
205 {N_(
"units"), N_(
"Length units"),
206 HID_Enum, 0, 0, {0, 0, 0}, units_list, 0, 0},
208 {N_(
"digits"), N_(
"Number of digits. For trailing zero suppression,"
209 " this is the number of digits before the decimal point. "
210 "Otherwise this is the number of digits after the decimal point."),
211 HID_Integer, 0, 20, {5, 0, 0}, 0, 0, 0},
214 {
"tool_units",
"Tool size units",
215 HID_Enum, 0, 0, {0, 0, 0}, units_list, 0, 0},
220 drill_attribute_merge (gerbv_HID_Attribute *dest,
int ndest, gerbv_HID_Attribute *src,
int nsrc)
229 for (i = 0 ; i < nsrc ; i++) {
232 while (j < ndest && strcmp (src[i].name, dest[j].name) != 0)
236 if (j < ndest && src[i].type == dest[j].type) {
237 dest[j].default_val = src[i].default_val;
239 GERB_MESSAGE(
"Ignoring \"%s\" attribute for drill file", src[i].name);
248 info->min_x = MIN(info->min_x, bbox->
left);
249 info->min_y = MIN(info->min_y, bbox->
bottom);
250 info->max_x = MAX(info->max_x, bbox->
right);
251 info->max_y = MAX(info->max_y, bbox->
top);
258 drill_add_drill_hole (
gerbv_image_t *image, drill_state_t *state,
265 drill_stats_increment_drill_counter(image->
drill_stats->drill_list,
266 state->current_tool);
269 if (curr_net->
next == NULL) {
270 GERB_FATAL_ERROR(
"malloc curr_net->next failed in %s()",
274 curr_net = curr_net->
next;
277 curr_net->
start_x = state->curr_x;
278 curr_net->
start_y = state->curr_y;
291 curr_net->
aperture = state->current_tool;
296 if(image->
aperture[state->current_tool] == NULL) {
301 r = image->
aperture[state->current_tool]->parameter[0] / 2;
309 drill_update_image_info_min_max_from_bbox(image->
info, bbox);
320 drill_add_route_segment(
gerbv_image_t *image, drill_state_t *state,
322 double prev_x,
double prev_y)
326 double start_x, start_y, stop_x, stop_y;
329 if (curr_net->
next == NULL) {
330 GERB_FATAL_ERROR(
"malloc curr_net->next failed in %s()",
334 curr_net = curr_net->
next;
340 stop_x = state->curr_x;
341 stop_y = state->curr_y;
354 curr_net->
stop_x = stop_x;
355 curr_net->
stop_y = stop_y;
356 curr_net->
aperture = state->current_tool;
362 if (image->
aperture[state->current_tool] == NULL) {
367 r = image->
aperture[state->current_tool]->parameter[0] / 2;
370 bbox->
left = MIN(start_x, stop_x) - r;
371 bbox->
right = MAX(start_x, stop_x) + r;
372 bbox->
bottom = MIN(start_y, stop_y) - r;
373 bbox->
top = MAX(start_y, stop_y) + r;
375 drill_update_image_info_min_max_from_bbox(image->
info, bbox);
386 drill_add_arc_segment(
gerbv_image_t *image, drill_state_t *state,
388 double prev_x,
double prev_y)
392 double start_x, start_y, stop_x, stop_y;
393 double delta_cp_x, delta_cp_y;
394 double d1x, d1y, d2x, d2y;
399 if (curr_net->
next == NULL)
400 GERB_FATAL_ERROR(
"malloc curr_net->next failed in %s()",
403 curr_net = curr_net->
next;
409 stop_x = state->curr_x;
410 stop_y = state->curr_y;
411 delta_cp_x = state->delta_cp_x;
412 delta_cp_y = state->delta_cp_y;
427 curr_net->
stop_x = stop_x;
428 curr_net->
stop_y = stop_y;
429 curr_net->
aperture = state->current_tool;
432 cw = (state->route_mode == DRILL_G_CWMOVE);
437 curr_net->
cirseg = g_new0(gerbv_cirseg_t, 1);
438 if (curr_net->
cirseg == NULL)
439 GERB_FATAL_ERROR(
"malloc cirseg failed in %s()", __FUNCTION__);
441 curr_net->
cirseg->cp_x = start_x + delta_cp_x;
442 curr_net->
cirseg->cp_y = start_y + delta_cp_y;
446 d2x = stop_x - curr_net->
cirseg->cp_x;
447 d2y = stop_y - curr_net->
cirseg->cp_y;
450 if (fabs(d1x) < DBL_EPSILON) d1x = 0;
451 if (fabs(d1y) < DBL_EPSILON) d1y = 0;
452 if (fabs(d2x) < DBL_EPSILON) d2x = 0;
453 if (fabs(d2y) < DBL_EPSILON) d2y = 0;
455 curr_net->
cirseg->width = hypot(delta_cp_x, delta_cp_y) * 2.0;
458 alfa = atan2(d1y, d1x);
459 beta = atan2(d2y, d2x);
470 if (alfa - beta < DBL_EPSILON)
473 if (beta - alfa < DBL_EPSILON)
477 curr_net->
cirseg->angle1 = RAD2DEG(alfa);
478 curr_net->
cirseg->angle2 = RAD2DEG(beta);
481 if (image->
aperture[state->current_tool] == NULL)
486 r = image->
aperture[state->current_tool]->parameter[0] / 2;
489 double ang1, ang2, step_pi_2, x, y;
491 ang1 = DEG2RAD(MIN(curr_net->
cirseg->angle1,
492 curr_net->
cirseg->angle2));
493 ang2 = DEG2RAD(MAX(curr_net->
cirseg->angle1,
494 curr_net->
cirseg->angle2));
497 x = curr_net->
cirseg->cp_x +
498 curr_net->
cirseg->width * cos(ang1) / 2;
499 y = curr_net->
cirseg->cp_y +
500 curr_net->
cirseg->width * sin(ang1) / 2;
507 for (step_pi_2 = (floor(ang1 / M_PI_2) + 1) * M_PI_2;
508 step_pi_2 < MIN(ang2, ang1 + 2 * M_PI);
509 step_pi_2 += M_PI_2) {
510 x = curr_net->
cirseg->cp_x +
511 curr_net->
cirseg->width * cos(step_pi_2) / 2;
512 y = curr_net->
cirseg->cp_y +
513 curr_net->
cirseg->width * sin(step_pi_2) / 2;
514 bbox->
left = MIN(bbox->
left, x - r);
517 bbox->
top = MAX(bbox->
top, y + r);
521 x = curr_net->
cirseg->cp_x +
522 curr_net->
cirseg->width * cos(ang2) / 2;
523 y = curr_net->
cirseg->cp_y +
524 curr_net->
cirseg->width * sin(ang2) / 2;
525 bbox->
left = MIN(bbox->
left, x - r);
528 bbox->
top = MAX(bbox->
top, y + r);
531 drill_update_image_info_min_max_from_bbox(image->
info, bbox);
538 parse_drillfile(gerb_file_t *fd, gerbv_HID_Attribute *attr_list,
int n_attr,
int reload)
540 drill_state_t *state = NULL;
543 gerbv_HID_Attribute *hid_attrs;
545 gboolean parsing_done = FALSE;
548 unsigned int file_line = 1;
555 setlocale(LC_NUMERIC,
"C" );
558 DPRINTF(
"In parse_drillfile, about to create image for this layer\n");
562 GERB_FATAL_ERROR(
"malloc image failed in %s()", __FUNCTION__);
565 if (reload && attr_list != NULL) {
569 image->
info->n_attr = n_attr;
570 image->
info->attr_list = gerbv_attribute_dup(attr_list, n_attr);
577 image->
info->n_attr =
sizeof (drill_attribute_list) /
sizeof (drill_attribute_list[0]);
578 image->
info->attr_list = gerbv_attribute_dup (drill_attribute_list, image->
info->n_attr);
581 drill_attribute_merge (image->
info->attr_list, image->
info->n_attr,
591 GERB_FATAL_ERROR(
"malloc stats failed in %s()", __FUNCTION__);
596 state = new_state(state);
598 GERB_FATAL_ERROR(
"malloc state failed in %s()", __FUNCTION__);
602 if (image->
format == NULL) {
603 GERB_FATAL_ERROR(
"malloc format failed in %s()", __FUNCTION__);
608 hid_attrs = image->
info->attr_list;
610 if (!hid_attrs[HA_auto].default_val.int_value) {
612 state->number_format = FMT_USER;
613 state->decimals = hid_attrs[HA_digits].default_val.int_value;
615 if (
GERBV_UNIT_MM == hid_attrs[HA_xy_units].default_val.int_value) {
619 switch (hid_attrs[HA_suppression].default_val.int_value) {
634 DPRINTF(
"%s(): Starting parsing of drill file \"%s\"\n",
635 __FUNCTION__, fd->filename);
637 while (!parsing_done && (read = gerb_fgetc(fd)) != EOF) {
639 switch ((
char) read) {
643 if (drill_parse_header_is_metric_comment(fd, state, image, file_line)) {
648 _(
"Comment \"%s\" at line %u in file \"%s\""),
649 tmps, file_line, fd->filename);
650 DPRINTF(
" Comment with ';' \"%s\" at line %u\n",
657 tmps = get_line (fd);
658 if (strcmp (tmps,
"DETECT,ON") == 0 ||
659 strcmp (tmps,
"DETECT,OFF") == 0) {
662 if (strcmp (tmps,
"DETECT,ON") == 0) {
670 tmps2 = g_strdup_printf (
"%s\n%s", stats->detect, tmps3);
671 g_free (stats->detect);
673 tmps2 = g_strdup_printf (
"%s", tmps3);
675 stats->detect = tmps2;
678 _(
"Unrecognised string \"%s\" in header "
679 "at line %u in file \"%s\""),
680 tmps, file_line, fd->filename);
687 tmps = get_line (fd);
690 if (0 == strcmp (tmps,
"FMAT,2")) {
695 if (0 == strcmp (tmps,
"FMAT,1")) {
696 gerbv_stats_printf(stats->error_list,
698 _(
"File in unsupported format 1 "
699 "at line %u in file \"%s\""),
700 file_line, fd->filename);
708 gerbv_stats_printf(stats->error_list,
710 _(
"Unrecognised string \"%s\" in header "
711 "at line %u in file \"%s\""),
712 tmps, file_line, fd->filename);
719 drill_g_code_t g_code;
721 switch (g_code = drill_parse_G_code(fd, image, file_line)) {
725 state->route_mode = DRILL_G_DRILL;
726 state->tool_down = FALSE;
730 state->route_mode = DRILL_G_ROUT;
732 case DRILL_G_LINEARMOVE :
733 state->route_mode = DRILL_G_LINEARMOVE;
735 case DRILL_G_CWMOVE :
736 state->route_mode = DRILL_G_CWMOVE;
738 case DRILL_G_CCWMOVE :
739 state->route_mode = DRILL_G_CCWMOVE;
742 case DRILL_G_SLOT : {
747 if (EOF == (read = gerb_fgetc(fd))) {
748 gerbv_stats_printf(stats->error_list,
750 _(
"Unexpected EOF found in file \"%s\""),
755 drill_parse_coordinate(fd, read, image, state, file_line);
758 curr_net->
stop_x = state->curr_x;
759 curr_net->
stop_y = state->curr_y;
767 r = image->
aperture[state->current_tool]->parameter[0]/2;
775 drill_update_image_info_min_max_from_bbox(image->
info, bbox);
782 case DRILL_G_ABSOLUTE :
783 state->coordinate_mode = DRILL_MODE_ABSOLUTE;
786 case DRILL_G_INCREMENTAL :
787 state->coordinate_mode = DRILL_MODE_INCREMENTAL;
790 case DRILL_G_ZEROSET :
791 if (EOF == (read = gerb_fgetc(fd))) {
792 gerbv_stats_printf(stats->error_list,
794 _(
"Unexpected EOF found in file \"%s\""),
799 drill_parse_coordinate(fd, (
char)read, image,
801 state->origin_x = state->curr_x;
802 state->origin_y = state->curr_y;
805 case DRILL_G_UNKNOWN:
807 gerbv_stats_printf(stats->error_list,
809 _(
"Unrecognized string \"%s\" found "
810 "at line %u in file \"%s\""),
811 tmps, file_line, fd->filename);
818 _(
"Unsupported G%02d (%s) code "
819 "at line %u in file \"%s\""),
821 file_line, fd->filename);
831 if (drill_parse_header_is_inch(fd, state, image, file_line)) {
835 if (drill_parse_header_is_ici(fd, state, image, file_line)) {
840 gerbv_stats_printf(stats->error_list,
842 _(
"Unrecognized string \"%s\" found "
843 "at line %u in file \"%s\""),
844 tmps, file_line, fd->filename);
852 switch (m_code = drill_parse_M_code(fd, state, image, file_line)) {
853 case DRILL_M_HEADER :
854 state->curr_section = DRILL_HEADER;
856 case DRILL_M_HEADEREND :
857 state->curr_section = DRILL_DATA;
868 gerbv_stats_printf(stats->error_list,
870 _(
"End of Excellon header reached "
871 "but no leading/trailing zero "
872 "handling specified "
873 "at line %u in file \"%s\""),
874 file_line, fd->filename);
875 gerbv_stats_printf(stats->error_list,
877 _(
"Assuming leading zeros in file \"%s\""),
882 case DRILL_M_METRIC :
884 && state->curr_section != DRILL_HEADER) {
887 gerbv_stats_printf(stats->error_list,
889 _(
"M71 code found but no METRIC "
890 "specification in header "
891 "at line %u in file \"%s\""),
892 file_line, fd->filename);
893 gerbv_stats_printf(stats->error_list,
895 _(
"Assuming all tool sizes are MM in file \"%s\""),
899 for (
int tool_num = TOOL_MIN; tool_num < TOOL_MAX;
904 size = image->
aperture[tool_num]->parameter[0];
905 drill_stats_modify_drill_list(stats->drill_list,
912 image->
aperture[tool_num]->parameter[0] /= 25.4;
917 state->number_format = state->backup_number_format;
921 case DRILL_M_IMPERIAL :
923 if (state->number_format != FMT_00_0000) {
925 state->backup_number_format = state->number_format;
927 state->number_format = FMT_00_0000;
933 case DRILL_M_CANNEDTEXTX :
934 case DRILL_M_CANNEDTEXTY :
937 _(
"Canned text \"%s\" "
938 "at line %u in drill file \"%s\""),
939 tmps, file_line, fd->filename);
942 case DRILL_M_MESSAGELONG :
943 case DRILL_M_MESSAGE :
946 _(
"Message \"%s\" embedded "
947 "at line %u in drill file \"%s\""),
948 tmps, file_line, fd->filename);
951 case DRILL_M_PATTERNEND :
952 case DRILL_M_TOOLTIPCHECK :
955 case DRILL_M_ZAXISROUTEPOSITIONDEPTHCTRL:
956 case DRILL_M_ZAXISROUTEPOSITION:
957 state->tool_down = TRUE;
959 case DRILL_M_RETRACTCLAMPING:
960 case DRILL_M_RETRACTNOCLAMPING:
961 state->tool_down = FALSE;
970 case DRILL_M_ENDREWIND :
974 case DRILL_M_UNKNOWN:
977 if (drill_parse_header_is_metric(fd, state, image, file_line)) {
983 gerbv_stats_printf(stats->error_list,
985 _(
"Unrecognized string \"%s\" found "
986 "at line %u in file \"%s\""),
987 tmps, file_line, fd->filename);
995 _(
"Unsupported M%02d (%s) code found "
996 "at line %u in file \"%s\""),
998 file_line, fd->filename);
1006 if (state->curr_section == DRILL_HEADER) {
1009 _(
"Not allowed 'R' code in the header "
1010 "at line %u in file \"%s\""),
1011 file_line, fd->filename);
1013 double start_x, start_y;
1014 double step_x, step_y;
1030 start_x = state->curr_x;
1031 start_y = state->curr_y;
1034 c = gerb_fgetc (fd);
1036 while (
'0' <= c && c <=
'9') {
1037 rcnt = 10*rcnt + (c -
'0');
1038 c = gerb_fgetc (fd);
1040 DPRINTF(
"working on R code (repeat) with a number of reps equal to %d\n", rcnt);
1044 step_x = read_double(fd, state->number_format, image->
format->omit_zeros, state->decimals);
1045 c = gerb_fgetc (fd);
1050 step_y = read_double(fd, state->number_format, image->
format->omit_zeros, state->decimals);
1055 DPRINTF(
"Getting ready to repeat the drill %d times with delta_x = %g, delta_y = %g\n", rcnt, step_x, step_y);
1058 for (c = 1 ; c <= rcnt ; c++) {
1059 state->curr_x = start_x + c*step_x;
1060 state->curr_y = start_y + c*step_y;
1061 DPRINTF(
" Repeat #%d - new location is (%g, %g)\n", c, state->curr_x, state->curr_y);
1062 curr_net = drill_add_drill_hole (image, state, stats, curr_net);
1070 _(
"Ignoring setting spindle speed "
1071 "at line %u in drill file \"%s\""),
1072 file_line, fd->filename);
1076 drill_parse_T_code(fd, state, image, file_line);
1077 state->route_mode = DRILL_G_DRILL;
1078 state->tool_down = FALSE;
1082 tmps = get_line (fd);
1084 if (0 != strcmp (tmps,
"VER,1")) {
1086 _(
"Undefined string \"%s\" in header "
1087 "at line %u in file \"%s\""),
1088 tmps, file_line, fd->filename);
1095 double prev_x = state->curr_x;
1096 double prev_y = state->curr_y;
1099 drill_parse_coordinate(fd, read, image, state, file_line);
1101 if ((state->route_mode == DRILL_G_ROUT ||
1102 state->route_mode == DRILL_G_LINEARMOVE ||
1103 state->route_mode == DRILL_G_CWMOVE ||
1104 state->route_mode == DRILL_G_CCWMOVE) && !state->tool_down) {
1106 state->delta_cp_x = 0;
1107 state->delta_cp_y = 0;
1111 if ((state->route_mode == DRILL_G_CWMOVE ||
1112 state->route_mode == DRILL_G_CCWMOVE) && state->tool_down) {
1114 curr_net = drill_add_arc_segment(image, state, stats,
1115 curr_net, prev_x, prev_y);
1116 state->delta_cp_x = 0;
1117 state->delta_cp_y = 0;
1118 }
else if ((state->route_mode == DRILL_G_LINEARMOVE ||
1119 state->route_mode == DRILL_G_ROUT) && state->tool_down) {
1121 curr_net = drill_add_route_segment(image, state, stats,
1122 curr_net, prev_x, prev_y);
1125 curr_net = drill_add_drill_hole(image, state, stats, curr_net);
1131 state->curr_section = DRILL_DATA;
1138 read = gerb_fgetc(fd);
1139 if (read !=
'\r' && read != EOF) {
1148 read = gerb_fgetc(fd);
1149 if (read !=
'\n' && read != EOF) {
1161 if (DRILL_HEADER == state->curr_section) {
1163 _(
"Undefined code '%s' (0x%x) found in header "
1164 "at line %u in file \"%s\""),
1165 gerbv_escape_char(read), read,
1166 file_line, fd->filename);
1170 tmps = get_line(fd);
1172 _(
"Unrecognised string \"%s\" in header "
1173 "at line %u in file \"%s\""),
1174 tmps, file_line, fd->filename);
1178 _(
"Ignoring undefined character '%s' (0x%x) "
1179 "found inside data at line %u in file \"%s\""),
1180 gerbv_escape_char(read), read, file_line, fd->filename);
1185 if (!parsing_done) {
1187 _(
"No EOF found in drill file \"%s\""), fd->filename);
1190 DPRINTF(
"%s(): Populating file attributes\n", __FUNCTION__);
1192 hid_attrs = image->
info->attr_list;
1194 switch (state->unit) {
1196 hid_attrs[HA_xy_units].default_val.int_value =
GERBV_UNIT_MM;
1204 switch (state->number_format) {
1207 hid_attrs[HA_digits].default_val.int_value = 2;
1211 hid_attrs[HA_digits].default_val.int_value = 3;
1215 hid_attrs[HA_digits].default_val.int_value = 4;
1219 DPRINTF(
"%s(): Keeping user specified number of decimal places (%d)\n",
1221 hid_attrs[HA_digits].default_val.int_value);
1228 switch (image->
format->omit_zeros) {
1230 hid_attrs[HA_suppression].default_val.int_value = SUP_LEAD;
1234 hid_attrs[HA_suppression].default_val.int_value = SUP_TRAIL;
1238 hid_attrs[HA_suppression].default_val.int_value = SUP_NONE;
1254 drill_file_p(gerb_file_t *fd, gboolean *returnFoundBinary)
1256 char *buf=NULL, *tbuf;
1263 gboolean found_binary = FALSE;
1264 gboolean found_M48 = FALSE;
1265 gboolean found_M30 = FALSE;
1266 gboolean found_percent = FALSE;
1267 gboolean found_T = FALSE;
1268 gboolean found_X = FALSE;
1269 gboolean found_Y = FALSE;
1270 gboolean end_comments=FALSE;
1272 tbuf = g_malloc(MAXL);
1275 "malloc buf failed while checking for drill file in %s()",
1279 while (fgets(tbuf, MAXL, fd->fd) != NULL) {
1284 if(g_strstr_len(buf, len,
";")!=NULL){
1285 for (i = 0; i < len-1; ++i) {
1289 && buf[i+1] !=
'\n') {
1290 end_comments = TRUE;
1308 for (i = 0; i < len; i++) {
1309 ascii = (int) buf[i];
1310 if ((ascii > 128) || (ascii < 0)) {
1311 found_binary = TRUE;
1316 if (g_strstr_len(buf, len,
"M48")) {
1321 if (g_strstr_len(buf, len,
"M30")) {
1322 if (found_percent) {
1328 if ((letter = g_strstr_len(buf, len,
"%")) != NULL) {
1329 if ((letter[1] ==
'\r') || (letter[1] ==
'\n')) {
1330 found_percent = TRUE;
1335 if ((letter = g_strstr_len(buf, len,
"T")) != NULL) {
1336 if (!found_T && (found_X || found_Y)) {
1339 if (isdigit( (
int) letter[1])) {
1346 if ((letter = g_strstr_len(buf, len,
"X")) != NULL) {
1347 ascii = (int) letter[1];
1348 if ((ascii >= zero) && (ascii <= nine)) {
1352 if ((letter = g_strstr_len(buf, len,
"Y")) != NULL) {
1353 ascii = (int) letter[1];
1354 if ((ascii >= zero) && (ascii <= nine)) {
1362 *returnFoundBinary = found_binary;
1365 if ( ((found_X || found_Y) && found_T) &&
1366 (found_M48 || (found_percent && found_M30)) ) {
1368 }
else if (found_M48 && found_percent && found_M30) {
1383 drill_parse_T_code(gerb_file_t *fd, drill_state_t *state,
1387 gboolean done = FALSE;
1391 gerbv_aperture_t *apert;
1395 DPRINTF(
"---> entering %s()...\n", __FUNCTION__);
1399 temp = gerb_fgetc(fd);
1400 DPRINTF(
" Found a char '%s' (0x%02x) after the T\n",
1401 gerbv_escape_char(temp), temp);
1404 if((temp ==
'C') && ((fd->ptr + 2) < fd->datalen)){
1405 if(gerb_fgetc(fd) ==
'S'){
1406 if (gerb_fgetc(fd) ==
'T' ){
1408 tmps = get_line(fd++);
1410 _(
"Tool change stop switch found \"%s\" "
1411 "at line %u in file \"%s\""),
1412 tmps, file_line, fd->filename);
1422 if( !(isdigit(temp) != 0 || temp ==
'+' || temp ==
'-') ) {
1425 _(
"OrCAD bug: Junk text found in place of tool definition"));
1426 tmps = get_line(fd);
1428 _(
"Junk text \"%s\" "
1429 "at line %u in file \"%s\""),
1430 tmps, file_line, fd->filename);
1433 _(
"Ignoring junk text"));
1439 tool_num = (int) gerb_fgetint(fd, NULL);
1440 DPRINTF(
" Handling tool T%d at line %u\n", tool_num, file_line);
1442 if (tool_num == 0) {
1446 if (tool_num < TOOL_MIN || tool_num >= TOOL_MAX) {
1448 _(
"Out of bounds drill number %d "
1449 "at line %u in file \"%s\""),
1450 tool_num, file_line, fd->filename);
1455 state->current_tool = tool_num;
1459 temp = gerb_fgetc(fd);
1464 switch((
char)temp) {
1467 DPRINTF(
" Read a size of %g\n", size);
1471 }
else if(size >= 4.0) {
1479 _(
"Read a drill of diameter %g inches "
1480 "at line %u in file \"%s\""),
1481 size, file_line, fd->filename);
1483 _(
"Assuming units are mils"));
1487 if (size <= 0. || size >= 10000.) {
1489 _(
"Unreasonable drill size %g found for drill %d "
1490 "at line %u in file \"%s\""),
1491 size, tool_num, file_line, fd->filename);
1493 if (apert != NULL) {
1498 if (apert->parameter[0] != size
1500 || apert->nuf_parameters != 1
1503 gerbv_stats_printf(stats->error_list,
1505 _(
"Found redefinition of drill %d "
1506 "at line %u in file \"%s\""),
1507 tool_num, file_line, fd->filename);
1510 apert = image->
aperture[tool_num] =
1511 g_new0(gerbv_aperture_t, 1);
1512 if (apert == NULL) {
1513 GERB_FATAL_ERROR(
"malloc tool failed in %s()",
1520 apert->parameter[0] = size;
1522 apert->nuf_parameters = 1;
1530 string = g_strdup_printf(
"%s", (state->unit ==
GERBV_UNIT_MM ? _(
"mm") : _(
"inch")));
1531 drill_stats_add_to_drill_list(stats->drill_list,
1541 gerb_fgetint(fd, NULL);
1552 temp = gerb_fgetc(fd);
1555 _(
"Unexpected EOF encountered in header of "
1556 "drill file \"%s\""), fd->filename);
1559 if (
'\n' == temp ||
'\r' == temp) {
1567 if (apert == NULL) {
1570 apert = image->
aperture[tool_num] = g_new0(gerbv_aperture_t, 1);
1571 if (apert == NULL) {
1572 GERB_FATAL_ERROR(
"malloc tool failed in %s()", __FUNCTION__);
1576 dia = gerbv_get_tool_diameter(tool_num);
1582 dia = (double)(16 + 8 * tool_num) / 1000;
1588 if (tool_num != 0) {
1590 _(
"Tool %02d used without being defined "
1591 "at line %u in file \"%s\""),
1592 tool_num, file_line, fd->filename);
1594 _(
"Setting a default size of %g\""), dia);
1599 apert->nuf_parameters = 1;
1600 apert->parameter[0] = dia;
1604 if (tool_num != 0) {
1607 string = g_strdup_printf(
"%s",
1609 drill_stats_add_to_drill_list(stats->drill_list,
1617 DPRINTF(
"<---- ...leaving %s()\n", __FUNCTION__);
1624 static drill_m_code_t
1625 drill_parse_M_code(gerb_file_t *fd, drill_state_t *state,
1629 drill_m_code_t m_code;
1632 DPRINTF(
"---> entering %s() ...\n", __FUNCTION__);
1634 op[0] = gerb_fgetc(fd);
1635 op[1] = gerb_fgetc(fd);
1641 _(
"Unexpected EOF found while parsing M-code in file \"%s\""),
1644 return DRILL_M_UNKNOWN;
1647 DPRINTF(
" Compare M-code \"%s\" at line %u\n", op, file_line);
1649 switch (m_code = atoi(op)) {
1652 if (0 != strncmp(op,
"00", 2)) {
1653 m_code = DRILL_M_UNKNOWN;
1704 case DRILL_M_UNKNOWN:
1709 DPRINTF(
"<---- ...leaving %s()\n", __FUNCTION__);
1716 drill_parse_header_is_metric(gerb_file_t *fd, drill_state_t *state,
1722 DPRINTF(
" %s(): entering\n", __FUNCTION__);
1731 if (DRILL_HEADER != state->curr_section) {
1735 switch (file_check_str(fd,
"METRIC")) {
1738 _(
"Unexpected EOF found while parsing \"%s\" string "
1739 "in file \"%s\""),
"METRIC", fd->filename);
1747 gboolean found_junk = FALSE;
1749 if (
',' != gerb_fgetc(fd)) {
1756 switch (c = gerb_fgetc(fd)) {
1759 if (
'Z' != gerb_fgetc(fd)) {
1765 DPRINTF(
" %s(): Detected a file that probably has "
1766 "trailing zero suppression\n", __FUNCTION__);
1769 DPRINTF(
" %s(): Detected a file that probably has "
1770 "leading zero suppression\n", __FUNCTION__);
1774 if (!state->autod && state->number_format == FMT_USER
1775 && state->digits_before > 0 && c ==
'L') {
1778 state->decimals = state->digits_before;
1781 if (state->autod && state->number_format != FMT_USER) {
1790 state->header_number_format =
1791 state->number_format = FMT_000_000;
1792 state->decimals = 3;
1795 if (
',' == gerb_fgetc(fd)) {
1804 if (
'0' != gerb_fgetc(fd)
1805 ||
'0' != gerb_fgetc(fd)) {
1812 op[0] = gerb_fgetc(fd);
1813 op[1] = gerb_fgetc(fd);
1821 if (0 == strcmp(op,
"0.")) {
1824 if (
'0' != gerb_fgetc(fd)
1825 ||
'0' != gerb_fgetc(fd)) {
1833 state->number_format = FMT_0000_00;
1834 state->decimals = 2;
1839 if (0 != strcmp(op,
".0")) {
1846 if (
'0' != gerb_fgetc(fd)) {
1851 if (
'0' == gerb_fgetc(fd)
1853 state->number_format = FMT_000_000;
1854 state->decimals = 3;
1859 state->number_format = FMT_000_00;
1860 state->decimals = 2;
1876 gerbv_stats_printf(stats->error_list,
1878 _(
"Found junk after METRIC command "
1879 "at line %u in file \"%s\""),
1880 file_line, fd->filename);
1899 drill_parse_header_is_metric_comment(gerb_file_t *fd, drill_state_t *state,
1903 DPRINTF(
" %s(): entering\n", __FUNCTION__);
1905 if (DRILL_HEADER != state->curr_section) {
1909 switch (file_check_str(fd,
"FILE_FORMAT")) {
1912 _(
"Unexpected EOF found while parsing \"%s\" string "
1913 "in file \"%s\" on line %u"),
1914 "FILE_FORMAT", fd->filename, file_line);
1921 if (file_check_str(fd,
"=") != 1) {
1923 _(
"Expected '=' while parsing \"%s\" string "
1924 "in file \"%s\" on line %u"),
1925 "FILE_FORMAT", fd->filename, file_line);
1930 int digits_before = gerb_fgetint(fd, &len);
1935 _(
"Expected integer after '=' while parsing \"%s\" string "
1936 "in file \"%s\" on line %u"),
1937 "FILE_FORMAT", fd->filename, file_line);
1941 if (file_check_str(fd,
":") != 1) {
1943 _(
"Expected ':' while parsing \"%s\" string "
1944 "in file \"%s\" on line %u"),
1945 "FILE_FORMAT", fd->filename, file_line);
1950 int digits_after = gerb_fgetint(fd, &len);
1954 _(
"Expected integer after ':' while parsing \"%s\" string "
1955 "in file \"%s\" on line %u"),
1956 "FILE_FORMAT", fd->filename, file_line);
1960 state->header_number_format = state->number_format = FMT_USER;
1961 state->decimals = digits_after;
1962 state->digits_before = digits_before;
1969 drill_parse_header_is_inch(gerb_file_t *fd, drill_state_t *state,
1975 DPRINTF(
" %s(): entering\n", __FUNCTION__);
1977 if (DRILL_HEADER != state->curr_section) {
1981 switch (file_check_str(fd,
"INCH")) {
1984 _(
"Unexpected EOF found while parsing \"%s\" string "
1985 "in file \"%s\""),
"INCH", fd->filename);
1993 if (
',' != gerb_fgetc(fd)) {
1998 if (c != EOF &&
'Z' == gerb_fgetc(fd)) {
2003 state->header_number_format =
2004 state->number_format = FMT_00_0000;
2005 state->decimals = 4;
2006 }
else if (state->number_format == FMT_USER
2007 && state->digits_before > 0) {
2010 state->decimals = state->digits_before;
2017 state->header_number_format =
2018 state->number_format = FMT_00_0000;
2019 state->decimals = 4;
2026 gerbv_stats_printf(stats->error_list,
2028 _(
"Found junk '%s' after "
2030 "at line %u in file \"%s\""),
2031 gerbv_escape_char(c),
2032 file_line, fd->filename);
2036 gerbv_stats_printf(stats->error_list,
2038 _(
"Found junk '%s' after INCH command "
2039 "at line %u in file \"%s\""),
2040 gerbv_escape_char(c),
2041 file_line, fd->filename);
2055 drill_parse_header_is_ici(gerb_file_t *fd, drill_state_t *state,
2060 switch (file_check_str(fd,
"ICI,ON")) {
2063 _(
"Unexpected EOF found while parsing \"%s\" string "
2064 "in file \"%s\""),
"ICI,ON", fd->filename);
2068 state->coordinate_mode = DRILL_MODE_INCREMENTAL;
2072 switch (file_check_str(fd,
"ICI,OFF")) {
2075 _(
"Unexpected EOF found while parsing \"%s\" string "
2076 "in file \"%s\""),
"ICI,OFF", fd->filename);
2080 state->coordinate_mode = DRILL_MODE_ABSOLUTE;
2088 static drill_g_code_t
2089 drill_parse_G_code(gerb_file_t *fd,
gerbv_image_t *image,
unsigned int file_line)
2092 drill_g_code_t g_code;
2095 DPRINTF(
"---> entering %s()...\n", __FUNCTION__);
2097 op[0] = gerb_fgetc(fd);
2098 op[1] = gerb_fgetc(fd);
2104 _(
"Unexpected EOF found while parsing G-code in file \"%s\""),
2106 return DRILL_G_UNKNOWN;
2109 DPRINTF(
" Compare G-code \"%s\" at line %u\n", op, file_line);
2111 switch (g_code = atoi(op)) {
2114 if (0 != strncmp(op,
"00", 2)) {
2115 g_code = DRILL_G_UNKNOWN;
2147 case DRILL_G_UNKNOWN:
2153 DPRINTF(
"<---- ...leaving %s()\n", __FUNCTION__);
2163 drill_parse_coordinate(gerb_file_t *fd,
char firstchar,
2165 unsigned int file_line)
2170 gboolean found_x = FALSE;
2172 gboolean found_y = FALSE;
2174 gboolean found_i = FALSE;
2176 gboolean found_j = FALSE;
2180 if (firstchar ==
'X') {
2181 x = read_double(fd, state->number_format, image->
format->omit_zeros, state->decimals);
2183 }
else if (firstchar ==
'Y') {
2184 y = read_double(fd, state->number_format, image->
format->omit_zeros, state->decimals);
2186 }
else if (firstchar ==
'I') {
2187 i_val = read_double(fd, state->number_format, image->
format->omit_zeros, state->decimals);
2189 }
else if (firstchar ==
'J') {
2190 j_val = read_double(fd, state->number_format, image->
format->omit_zeros, state->decimals);
2197 firstchar = gerb_fgetc(fd);
2199 if(state->coordinate_mode == DRILL_MODE_ABSOLUTE) {
2206 }
else if(state->coordinate_mode == DRILL_MODE_INCREMENTAL) {
2215 _(
"Coordinate mode is not absolute and not incremental "
2216 "at line %u in file \"%s\""),
2217 file_line, fd->filename);
2222 state->delta_cp_x = i_val;
2224 state->delta_cp_y = j_val;
2230 static drill_state_t *
2231 new_state(drill_state_t *state)
2233 state = g_new0(drill_state_t, 1);
2234 if (state != NULL) {
2236 state->curr_section = DRILL_NONE;
2237 state->coordinate_mode = DRILL_MODE_ABSOLUTE;
2238 state->origin_x = 0.0;
2239 state->origin_y = 0.0;
2241 state->backup_number_format = FMT_000_000;
2242 state->header_number_format = state->number_format = FMT_00_0000;
2244 state->decimals = 4;
2245 state->route_mode = DRILL_G_DRILL;
2246 state->tool_down = FALSE;
2257 read_double(gerb_file_t *fd, number_fmt_t fmt,
gerbv_omit_zeros_t omit_zeros,
int decimals)
2260 char temp[DRILL_READ_DOUBLE_SIZE];
2263 gboolean decimal_point = FALSE;
2264 gboolean sign_prepend = FALSE;
2266 memset(temp, 0,
sizeof(temp));
2268 read = gerb_fgetc(fd);
2269 while(read != EOF && i < (DRILL_READ_DOUBLE_SIZE -1) &&
2270 (isdigit(read) || read ==
'.' || read ==
',' || read ==
'+' || read ==
'-')) {
2271 if(read ==
',' || read ==
'.') decimal_point = TRUE;
2281 if(read ==
'-' || read ==
'+') {
2282 sign_prepend = TRUE;
2285 temp[i++] = (char)read;
2286 read = gerb_fgetc(fd);
2292 if (decimal_point) {
2293 result = strtod(temp, NULL);
2295 unsigned int wantdigits;
2297 char tmp2[DRILL_READ_DOUBLE_SIZE];
2299 memset(tmp2, 0,
sizeof(tmp2));
2322 wantdigits = decimals;
2327 fprintf(stderr, _(
"%s(): omit_zeros == GERBV_OMIT_ZEROS_TRAILING but fmt = %d.\n"
2328 "This should never have happened\n"), __FUNCTION__, fmt);
2342 if (wantdigits >
sizeof(tmp2) - 2) {
2343 fprintf(stderr, _(
"%s(): wantdigits = %d which exceeds the maximum allowed size\n"),
2344 __FUNCTION__, wantdigits);
2353 DPRINTF(
"%s(): wantdigits = %d, strlen(\"%s\") = %ld\n",
2354 __FUNCTION__, wantdigits, temp, (
long) strlen(temp));
2355 for (i = 0 ; i < wantdigits && i < strlen(temp) ; i++) {
2358 for ( ; i < wantdigits ; i++) {
2362 for ( ; i <= strlen(temp) ; i++) {
2363 tmp2[i] = temp[i-1];
2365 DPRINTF(
"%s(): After dealing with trailing zero suppression, convert \"%s\"\n", __FUNCTION__, tmp2);
2368 for (i = 0 ; i <= strlen(tmp2) && i <
sizeof (temp) ; i++) {
2393 scale = pow (10.0, -1.0*decimals);
2398 fprintf (stderr, _(
"%s(): Unhandled fmt ` %d\n"), __FUNCTION__, fmt);
2403 result = strtod(temp, NULL) * scale;
2406 DPRINTF(
" %s()=%f: fmt=%d, omit_zeros=%d, decimals=%d \n",
2407 __FUNCTION__, result, fmt, omit_zeros, decimals);
2416 eat_line(gerb_file_t *fd)
2421 read = gerb_fgetc(fd);
2422 }
while (read !=
'\n' && read !=
'\r' && read != EOF);
2433 eat_whitespace(gerb_file_t *fd)
2438 read = gerb_fgetc(fd);
2439 }
while ((read ==
' ' || read ==
'\t') && read != EOF);
2449 get_line(gerb_file_t *fd)
2453 gchar *tmps=g_strdup(
"");
2455 read = gerb_fgetc(fd);
2456 while (read !=
'\n' && read !=
'\r' && read != EOF) {
2457 retstring = g_strdup_printf(
"%s%c", tmps, read);
2465 read = gerb_fgetc(fd);
2483 file_check_str(gerb_file_t *fd,
const char *str)
2487 for (
int i = 0; str[i] !=
'\0'; i++) {
2514 return N_(
"rout mode");
2515 case DRILL_G_LINEARMOVE:
2516 return N_(
"linear mode");
2517 case DRILL_G_CWMOVE:
2518 return N_(
"circular CW mode");
2519 case DRILL_G_CCWMOVE:
2520 return N_(
"circular CCW mode");
2521 case DRILL_G_VARIABLEDWELL:
2522 return N_(
"variable dwell");
2524 return N_(
"drill mode");
2525 case DRILL_G_OVERRIDETOOLSPEED:
2526 return N_(
"override tool feed or speed");
2527 case DRILL_G_ROUTCIRCLE:
2528 return N_(
"routed CW circle");
2529 case DRILL_G_ROUTCIRCLECCW:
2530 return N_(
"routed CCW circle");
2531 case DRILL_G_VISTOOL:
2532 return N_(
"select vision tool");
2533 case DRILL_G_VISSINGLEPOINTOFFSET:
2534 return N_(
"single point vision offset");
2535 case DRILL_G_VISMULTIPOINTTRANS:
2536 return N_(
"multipoint vision translation");
2537 case DRILL_G_VISCANCEL:
2538 return N_(
"cancel vision translation or offset");
2539 case DRILL_G_VISCORRHOLEDRILL:
2540 return N_(
"vision corrected single hole drilling");
2541 case DRILL_G_VISAUTOCALIBRATION:
2542 return N_(
"vision system autocalibration");
2543 case DRILL_G_CUTTERCOMPOFF:
2544 return N_(
"cutter compensation off");
2545 case DRILL_G_CUTTERCOMPLEFT:
2546 return N_(
"cutter compensation left");
2547 case DRILL_G_CUTTERCOMPRIGHT:
2548 return N_(
"cutter compensation right");
2549 case DRILL_G_VISSINGLEPOINTOFFSETREL:
2550 return N_(
"single point vision relative offset");
2551 case DRILL_G_VISMULTIPOINTTRANSREL:
2552 return N_(
"multipoint vision relative translation");
2553 case DRILL_G_VISCANCELREL:
2554 return N_(
"cancel vision relative translation or offset");
2555 case DRILL_G_VISCORRHOLEDRILLREL:
2556 return N_(
"vision corrected single hole relative drilling");
2557 case DRILL_G_PACKDIP2:
2558 return N_(
"dual in line package");
2559 case DRILL_G_PACKDIP:
2560 return N_(
"dual in line package");
2561 case DRILL_G_PACK8PINL:
2562 return N_(
"eight pin L package");
2564 return N_(
"canned circle");
2566 return N_(
"canned slot");
2567 case DRILL_G_ROUTSLOT:
2568 return N_(
"routed step slot");
2569 case DRILL_G_ABSOLUTE:
2570 return N_(
"absolute input mode");
2571 case DRILL_G_INCREMENTAL:
2572 return N_(
"incremental input mode");
2573 case DRILL_G_ZEROSET:
2574 return N_(
"zero set");
2576 case DRILL_G_UNKNOWN:
2578 return N_(
"unknown G-code");
2588 return N_(
"end of program");
2589 case DRILL_M_PATTERNEND:
2590 return N_(
"pattern end");
2591 case DRILL_M_REPEATPATTERNOFFSET:
2592 return N_(
"repeat pattern offset");
2593 case DRILL_M_STOPOPTIONAL:
2594 return N_(
"stop optional");
2595 case DRILL_M_SANDREND:
2596 return N_(
"step and repeat end");
2597 case DRILL_M_STOPINSPECTION:
2598 return N_(
"stop for inspection");
2599 case DRILL_M_ZAXISROUTEPOSITIONDEPTHCTRL:
2600 return N_(
"Z-axis rout position with depth control");
2601 case DRILL_M_ZAXISROUTEPOSITION:
2602 return N_(
"Z-axis rout position");
2603 case DRILL_M_RETRACTCLAMPING:
2604 return N_(
"retract with clamping");
2605 case DRILL_M_RETRACTNOCLAMPING:
2606 return N_(
"retract without clamping");
2607 case DRILL_M_TOOLTIPCHECK:
2608 return N_(
"tool tip check");
2609 case DRILL_M_PATTERN:
2610 return N_(
"pattern start");
2611 case DRILL_M_ENDREWIND:
2612 return N_(
"end of program with rewind");
2613 case DRILL_M_MESSAGELONG:
2614 return N_(
"long operator message");
2615 case DRILL_M_MESSAGE:
2616 return N_(
"operator message");
2617 case DRILL_M_HEADER:
2618 return N_(
"header start");
2619 case DRILL_M_VISANDRPATTERN:
2620 return N_(
"vision step and repeat pattern start");
2621 case DRILL_M_VISANDRPATTERNREWIND:
2622 return N_(
"vision step and repeat rewind");
2623 case DRILL_M_VISANDRPATTERNOFFSETCOUNTERCTRL:
2624 return N_(
"vision step and repeat offset counter control");
2625 case DRILL_M_REFSCALING:
2626 return N_(
"reference scaling on");
2627 case DRILL_M_REFSCALINGEND:
2628 return N_(
"reference scaling off");
2629 case DRILL_M_PECKDRILLING:
2630 return N_(
"peck drilling on");
2631 case DRILL_M_PECKDRILLINGEND:
2632 return N_(
"peck drilling off");
2633 case DRILL_M_SWAPAXIS:
2634 return N_(
"swap axes");
2635 case DRILL_M_METRIC:
2636 return N_(
"metric measuring mode");
2637 case DRILL_M_IMPERIAL:
2638 return N_(
"inch measuring mode");
2639 case DRILL_M_MIRRORX:
2640 return N_(
"mirror image X-axis");
2641 case DRILL_M_MIRRORY:
2642 return N_(
"mirror image Y-axis");
2643 case DRILL_M_HEADEREND:
2644 return N_(
"header end");
2645 case DRILL_M_CANNEDTEXTX:
2646 return N_(
"canned text along X-axis");
2647 case DRILL_M_CANNEDTEXTY:
2648 return N_(
"canned text along Y-axis");
2649 case DRILL_M_USERDEFPATTERN:
2650 return N_(
"user defined stored pattern");
2652 case DRILL_M_UNKNOWN:
2654 return N_(
"unknown M-code");
Dynamic GUI window creation header info.
const char * drill_g_code_name(drill_g_code_t g_code)
Return drill G-code name by code number.
const char * drill_m_code_name(drill_m_code_t m_code)
Return drill M-code name by code number.
Header info for the Excellon drill parsing functions.
gerbv_drill_stats_t * gerbv_drill_stats_new(void)
Allocates a new drill_stats structure.
Header info to the statistics generating functions for Excellon drill files.
void gerbv_destroy_image(gerbv_image_t *image)
Free an image structure.
gerbv_image_t * gerbv_create_image(gerbv_image_t *image, const gchar *type)
Allocate a new gerbv_image structure.
The main header file for the libgerbv library.
@ GERBV_APERTURE_STATE_ON
@ GERBV_APERTURE_STATE_FLASH
@ GERBV_OMIT_ZEROS_TRAILING
@ GERBV_OMIT_ZEROS_EXPLICIT
@ GERBV_OMIT_ZEROS_LEADING
@ GERBV_OMIT_ZEROS_UNSPECIFIED
@ GERBV_INTERPOLATION_CW_CIRCULAR
@ GERBV_INTERPOLATION_CCW_CIRCULAR
@ GERBV_INTERPOLATION_LINEARx1
gerbv_layertype_t layertype
gerbv_drill_stats_t * drill_stats
gerbv_aperture_t * aperture[APERTURE_MAX]
gerbv_netstate_t * states
gerbv_image_info_t * info
gerbv_render_size_t boundingBox
gerbv_aperture_state_t aperture_state
gerbv_interpolation_t interpolation