46 #include <sys/types.h>
64 #define DRILL_READ_DOUBLE_SIZE 32
70 } drill_file_section_t;
74 DRILL_MODE_INCREMENTAL
75 } drill_coordinate_mode_t;
85 typedef struct drill_state {
89 drill_file_section_t curr_section;
90 drill_coordinate_mode_t coordinate_mode;
100 number_fmt_t number_format, header_number_format;
102 number_fmt_t backup_number_format;
117 static drill_g_code_t drill_parse_G_code(gerb_file_t* fd,
gerbv_image_t* image, ssize_t file_line);
118 static drill_m_code_t
119 drill_parse_M_code(gerb_file_t* fd, drill_state_t* state,
gerbv_image_t* image, ssize_t file_line);
120 static int drill_parse_T_code(gerb_file_t* fd, drill_state_t* state,
gerbv_image_t* image, ssize_t file_line);
121 static int drill_parse_header_is_metric(gerb_file_t* fd, drill_state_t* state,
gerbv_image_t* image, ssize_t file_line);
123 drill_parse_header_is_metric_comment(gerb_file_t* fd, drill_state_t* state,
gerbv_image_t* image, ssize_t file_line);
124 static int drill_parse_header_is_inch(gerb_file_t* fd, drill_state_t* state,
gerbv_image_t* image, ssize_t file_line);
125 static int drill_parse_header_is_ici(gerb_file_t* fd, drill_state_t* state,
gerbv_image_t* image, ssize_t file_line);
127 drill_parse_coordinate(gerb_file_t* fd,
char firstchar,
gerbv_image_t* image, drill_state_t* state, ssize_t file_line);
128 static drill_state_t* new_state(drill_state_t* state);
129 static double read_double(gerb_file_t* fd, number_fmt_t fmt,
gerbv_omit_zeros_t omit_zeros,
int decimals);
130 static void eat_line(gerb_file_t* fd);
131 static void eat_whitespace(gerb_file_t* fd);
132 static char* get_line(gerb_file_t* fd);
133 static int file_check_str(gerb_file_t* fd,
const char* str);
146 static const char* suppression_list[] = { N_(
"None"), N_(
"Leading"), N_(
"Trailing"), 0 };
148 static const char* units_list[] = { N_(
"inch"), N_(
"mm"), 0 };
160 static gerbv_HID_Attribute drill_attribute_list[] = {
162 { N_(
"autodetect"),N_(
"Try to autodetect the file format"),HID_Boolean, 0,0, { 1, 0, 0 },0, 0,0 },
164 {N_(
"zero_suppression"), N_(
"Zero suppression"), HID_Enum, 0, 0, { 0, 0, 0 }, suppression_list, 0, 0},
166 { N_(
"units"), N_(
"Length units"), HID_Enum, 0, 0, { 0, 0, 0 }, units_list, 0, 0},
169 N_(
"Number of digits. For trailing zero suppression,"
170 " this is the number of digits before the decimal point. "
171 "Otherwise this is the number of digits after the decimal point."),
178 {
"tool_units",
"Tool size units",
179 HID_Enum, 0, 0, {0, 0, 0}, units_list, 0, 0},
184 drill_attribute_merge(gerbv_HID_Attribute* dest,
int ndest, gerbv_HID_Attribute* src,
int nsrc) {
192 for (i = 0; i < nsrc; i++) {
195 while (j < ndest && strcmp(src[i].name, dest[j].name) != 0)
199 if (j < ndest && src[i].type == dest[j].type) {
200 dest[j].default_val = src[i].default_val;
202 GERB_MESSAGE(
"Ignoring \"%s\" attribute for drill file", src[i].name);
209 info->min_x = MIN(info->min_x, bbox->
left);
210 info->min_y = MIN(info->min_y, bbox->
bottom);
211 info->max_x = MAX(info->max_x, bbox->
right);
212 info->max_y = MAX(info->max_y, bbox->
top);
224 drill_stats_increment_drill_counter(image->
drill_stats->drill_list, state->current_tool);
227 if (curr_net->
next == NULL)
228 GERB_FATAL_ERROR(
"malloc curr_net->next failed in %s()", __FUNCTION__);
230 curr_net = curr_net->
next;
233 curr_net->
start_x = state->curr_x;
234 curr_net->
start_y = state->curr_y;
247 curr_net->
aperture = state->current_tool;
252 if (image->
aperture[state->current_tool] == NULL)
256 r = image->
aperture[state->current_tool]->parameter[0] / 2;
264 drill_update_image_info_min_max_from_bbox(image->
info, bbox);
271 parse_drillfile(gerb_file_t* fd, gerbv_HID_Attribute* attr_list,
int n_attr,
int reload) {
272 drill_state_t* state = NULL;
275 gerbv_HID_Attribute* hid_attrs;
279 ssize_t file_line = 1;
286 setlocale(LC_NUMERIC,
"C");
289 dprintf(
"In parse_drillfile, about to create image for this layer\n");
293 GERB_FATAL_ERROR(
"malloc image failed in %s()", __FUNCTION__);
295 if (reload && attr_list != NULL) {
299 image->
info->n_attr = n_attr;
300 image->
info->attr_list = gerbv_attribute_dup(attr_list, n_attr);
307 image->
info->n_attr =
sizeof(drill_attribute_list) /
sizeof(drill_attribute_list[0]);
308 image->
info->attr_list = gerbv_attribute_dup(drill_attribute_list, image->
info->n_attr);
311 drill_attribute_merge(image->
info->attr_list, image->
info->n_attr, attr_list, n_attr);
320 GERB_FATAL_ERROR(
"malloc stats failed in %s()", __FUNCTION__);
324 state = new_state(state);
326 GERB_FATAL_ERROR(
"malloc state failed in %s()", __FUNCTION__);
329 if (image->
format == NULL)
330 GERB_FATAL_ERROR(
"malloc format failed in %s()", __FUNCTION__);
334 hid_attrs = image->
info->attr_list;
336 if (!hid_attrs[HA_auto].default_val.int_value) {
338 state->number_format = FMT_USER;
339 state->decimals = hid_attrs[HA_digits].default_val.int_value;
341 if (
GERBV_UNIT_MM == hid_attrs[HA_xy_units].default_val.int_value)
344 switch (hid_attrs[HA_suppression].default_val.int_value) {
353 dprintf(
"%s(): Starting parsing of drill file \"%s\"\n", __FUNCTION__, fd->filename);
355 while ((read = gerb_fgetc(fd)) != EOF) {
357 switch ((
char)read) {
361 if (drill_parse_header_is_metric_comment(fd, state, image, file_line)) {
366 stats->error_list,
GERBV_MESSAGE_NOTE, -1, _(
"Comment \"%s\" at line %ld in file \"%s\""), tmps,
367 file_line, fd->filename
369 dprintf(
" Comment with ';' \"%s\" at line %ld\n", tmps, file_line);
376 if (strcmp(tmps,
"DETECT,ON") == 0 || strcmp(tmps,
"DETECT,OFF") == 0) {
379 if (strcmp(tmps,
"DETECT,ON") == 0)
386 tmps2 = g_strdup_printf(
"%s\n%s", stats->detect, tmps3);
387 g_free(stats->detect);
389 tmps2 = g_strdup_printf(
"%s", tmps3);
391 stats->detect = tmps2;
395 _(
"Unrecognised string \"%s\" in header "
396 "at line %ld in file \"%s\""),
397 tmps, file_line, fd->filename
408 if (0 == strcmp(tmps,
"FMAT,2")) {
413 if (0 == strcmp(tmps,
"FMAT,1")) {
416 _(
"File in unsupported format 1 "
417 "at line %ld in file \"%s\""),
418 file_line, fd->filename
429 _(
"Unrecognised string \"%s\" in header "
430 "at line %ld in file \"%s\""),
431 tmps, file_line, fd->filename
440 drill_g_code_t g_code;
442 switch (g_code = drill_parse_G_code(fd, image, file_line)) {
454 if (EOF == (read = gerb_fgetc(fd))) {
457 _(
"Unexpected EOF found in file \"%s\""), fd->filename
462 drill_parse_coordinate(fd, read, image, state, file_line);
465 curr_net->
stop_x = state->curr_x;
466 curr_net->
stop_y = state->curr_y;
474 r = image->
aperture[state->current_tool]->parameter[0] / 2;
482 drill_update_image_info_min_max_from_bbox(image->
info, bbox);
489 case DRILL_G_ABSOLUTE: state->coordinate_mode = DRILL_MODE_ABSOLUTE;
break;
491 case DRILL_G_INCREMENTAL: state->coordinate_mode = DRILL_MODE_INCREMENTAL;
break;
493 case DRILL_G_ZEROSET:
494 if (EOF == (read = gerb_fgetc(fd))) {
497 _(
"Unexpected EOF found in file \"%s\""), fd->filename
502 drill_parse_coordinate(fd, (
char)read, image, state, file_line);
503 state->origin_x = state->curr_x;
504 state->origin_y = state->curr_y;
507 case DRILL_G_UNKNOWN:
511 _(
"Unrecognized string \"%s\" found "
512 "at line %ld in file \"%s\""),
513 tmps, file_line, fd->filename
522 _(
"Unsupported G%02d (%s) code "
523 "at line %ld in file \"%s\""),
535 if (drill_parse_header_is_inch(fd, state, image, file_line))
538 if (drill_parse_header_is_ici(fd, state, image, file_line))
544 _(
"Unrecognized string \"%s\" found "
545 "at line %ld in file \"%s\""),
546 tmps, file_line, fd->filename
556 switch (m_code = drill_parse_M_code(fd, state, image, file_line)) {
557 case DRILL_M_HEADER: state->curr_section = DRILL_HEADER;
break;
558 case DRILL_M_HEADEREND:
559 state->curr_section = DRILL_DATA;
572 _(
"End of Excellon header reached "
573 "but no leading/trailing zero "
574 "handling specified "
575 "at line %ld in file \"%s\""),
576 file_line, fd->filename
580 _(
"Assuming leading zeros in file \"%s\""), fd->filename
591 _(
"M71 code found but no METRIC "
592 "specification in header "
593 "at line %ld in file \"%s\""),
594 file_line, fd->filename
598 _(
"Assuming all tool sizes are MM in file \"%s\""), fd->filename
602 for (
int tool_num = TOOL_MIN; tool_num < TOOL_MAX; tool_num++) {
606 size = image->
aperture[tool_num]->parameter[0];
607 drill_stats_modify_drill_list(stats->drill_list, tool_num, size,
"MM");
611 image->
aperture[tool_num]->parameter[0] /= 25.4;
616 state->number_format = state->backup_number_format;
620 case DRILL_M_IMPERIAL:
622 if (state->number_format != FMT_00_0000)
624 state->backup_number_format = state->number_format;
625 state->number_format = FMT_00_0000;
631 case DRILL_M_CANNEDTEXTX:
632 case DRILL_M_CANNEDTEXTY:
636 _(
"Canned text \"%s\" "
637 "at line %ld in drill file \"%s\""),
638 tmps, file_line, fd->filename
642 case DRILL_M_MESSAGELONG:
643 case DRILL_M_MESSAGE:
647 _(
"Message \"%s\" embedded "
648 "at line %ld in drill file \"%s\""),
649 tmps, file_line, fd->filename
653 case DRILL_M_PATTERNEND:
654 case DRILL_M_TOOLTIPCHECK:
break;
660 case DRILL_M_ENDREWIND:
goto drill_parse_end;
break;
662 case DRILL_M_UNKNOWN:
665 if (drill_parse_header_is_metric(fd, state, image, file_line))
672 _(
"Unrecognized string \"%s\" found "
673 "at line %ld in file \"%s\""),
674 tmps, file_line, fd->filename
684 _(
"Unsupported M%02d (%s) code found "
685 "at line %ld in file \"%s\""),
695 if (state->curr_section == DRILL_HEADER) {
699 _(
"Not allowed 'R' code in the header "
700 "at line %ld in file \"%s\""),
701 file_line, fd->filename
704 double start_x, start_y;
705 double step_x, step_y;
721 start_x = state->curr_x;
722 start_y = state->curr_y;
727 while (
'0' <= c && c <=
'9') {
728 rcnt = 10 * rcnt + (c -
'0');
731 dprintf(
"working on R code (repeat) with a number of reps equal to %d\n", rcnt);
735 step_x = read_double(fd, state->number_format, image->
format->omit_zeros, state->decimals);
741 step_y = read_double(fd, state->number_format, image->
format->omit_zeros, state->decimals);
747 "Getting ready to repeat the drill %d times with delta_x = %g, delta_y = %g\n", rcnt, step_x,
752 for (c = 1; c <= rcnt; c++) {
753 state->curr_x = start_x + c * step_x;
754 state->curr_y = start_y + c * step_y;
755 dprintf(
" Repeat #%d - new location is (%g, %g)\n", c, state->curr_x, state->curr_y);
756 curr_net = drill_add_drill_hole(image, state, stats, curr_net);
763 _(
"Ignoring setting spindle speed "
764 "at line %ld in drill file \"%s\""),
765 file_line, fd->filename
769 case 'T': drill_parse_T_code(fd, state, image, file_line);
break;
774 if (0 != strcmp(tmps,
"VER,1")) {
777 _(
"Undefined string \"%s\" in header "
778 "at line %ld in file \"%s\""),
779 tmps, file_line, fd->filename
788 drill_parse_coordinate(fd, read, image, state, file_line);
791 curr_net = drill_add_drill_hole(image, state, stats, curr_net);
794 case '%': state->curr_section = DRILL_DATA;
break;
800 read = gerb_fgetc(fd);
801 if (read !=
'\r' && read != EOF)
809 read = gerb_fgetc(fd);
810 if (read !=
'\n' && read != EOF)
820 if (DRILL_HEADER == state->curr_section) {
823 _(
"Undefined code '%s' (0x%x) found in header "
824 "at line %ld in file \"%s\""),
825 gerbv_escape_char(read), read, file_line, fd->filename
833 _(
"Unrecognised string \"%s\" in header "
834 "at line %ld in file \"%s\""),
835 tmps, file_line, fd->filename
841 _(
"Ignoring undefined character '%s' (0x%x) "
842 "found inside data at line %ld in file \"%s\""),
843 gerbv_escape_char(read), read, file_line, fd->filename
850 stats->error_list,
GERBV_MESSAGE_ERROR, -1, _(
"No EOF found in drill file \"%s\""), fd->filename
854 dprintf(
"%s(): Populating file attributes\n", __FUNCTION__);
856 hid_attrs = image->
info->attr_list;
858 switch (state->unit) {
861 default: hid_attrs[HA_xy_units].default_val.int_value =
GERBV_UNIT_INCH;
break;
864 switch (state->number_format) {
866 case FMT_0000_00: hid_attrs[HA_digits].default_val.int_value = 2;
break;
868 case FMT_000_000: hid_attrs[HA_digits].default_val.int_value = 3;
break;
870 case FMT_00_0000: hid_attrs[HA_digits].default_val.int_value = 4;
break;
874 "%s(): Keeping user specified number of decimal places (%d)\n", __FUNCTION__,
875 hid_attrs[HA_digits].default_val.int_value
882 switch (image->
format->omit_zeros) {
887 default: hid_attrs[HA_suppression].default_val.int_value = SUP_NONE;
break;
901 drill_file_p(gerb_file_t* fd, gboolean* returnFoundBinary) {
902 char * buf = NULL, *tbuf;
909 gboolean found_binary = FALSE;
910 gboolean found_M48 = FALSE;
911 gboolean found_M30 = FALSE;
912 gboolean found_percent = FALSE;
913 gboolean found_T = FALSE;
914 gboolean found_X = FALSE;
915 gboolean found_Y = FALSE;
916 gboolean end_comments = FALSE;
918 tbuf = g_malloc(MAXL);
920 GERB_FATAL_ERROR(
"malloc buf failed while checking for drill file in %s()", __FUNCTION__);
922 while (fgets(tbuf, MAXL, fd->fd) != NULL) {
927 if (g_strstr_len(buf, len,
";") != NULL) {
928 for (i = 0; i < len - 1; ++i) {
929 if (buf[i] ==
'\n' && buf[i + 1] !=
';' && buf[i + 1] !=
'\r' && buf[i + 1] !=
'\n') {
945 for (i = 0; i < len; i++) {
947 if ((ascii > 128) || (ascii < 0)) {
953 if (g_strstr_len(buf, len,
"M48")) {
958 if (g_strstr_len(buf, len,
"M30")) {
965 if ((letter = g_strstr_len(buf, len,
"%")) != NULL) {
966 if ((letter[1] ==
'\r') || (letter[1] ==
'\n'))
967 found_percent = TRUE;
971 if ((letter = g_strstr_len(buf, len,
"T")) != NULL) {
972 if (!found_T && (found_X || found_Y)) {
975 if (isdigit((
int)letter[1])) {
982 if ((letter = g_strstr_len(buf, len,
"X")) != NULL) {
983 ascii = (int)letter[1];
984 if ((ascii >= zero) && (ascii <= nine)) {
988 if ((letter = g_strstr_len(buf, len,
"Y")) != NULL) {
989 ascii = (int)letter[1];
990 if ((ascii >= zero) && (ascii <= nine)) {
998 *returnFoundBinary = found_binary;
1001 if (((found_X || found_Y) && found_T) && (found_M48 || (found_percent && found_M30)))
1003 else if (found_M48 && found_percent && found_M30)
1016 drill_parse_T_code(gerb_file_t* fd, drill_state_t* state,
gerbv_image_t* image, ssize_t file_line) {
1018 gboolean done = FALSE;
1022 gerbv_aperture_t* apert;
1026 dprintf(
"---> entering %s()...\n", __FUNCTION__);
1030 temp = gerb_fgetc(fd);
1031 dprintf(
" Found a char '%s' (0x%02x) after the T\n", gerbv_escape_char(temp), temp);
1034 if ((temp ==
'C') && ((fd->ptr + 2) < fd->datalen)) {
1035 if (gerb_fgetc(fd) ==
'S') {
1036 if (gerb_fgetc(fd) ==
'T') {
1038 tmps = get_line(fd++);
1041 _(
"Tool change stop switch found \"%s\" "
1042 "at line %ld in file \"%s\""),
1043 tmps, file_line, fd->filename
1054 if (!(isdigit(temp) != 0 || temp ==
'+' || temp ==
'-')) {
1057 stats->error_list,
GERBV_MESSAGE_ERROR, -1, _(
"OrCAD bug: Junk text found in place of tool definition")
1059 tmps = get_line(fd);
1062 _(
"Junk text \"%s\" "
1063 "at line %ld in file \"%s\""),
1064 tmps, file_line, fd->filename
1073 tool_num = (int)gerb_fgetint(fd, NULL);
1074 dprintf(
" Handling tool T%d at line %ld\n", tool_num, file_line);
1079 if (tool_num < TOOL_MIN || tool_num >= TOOL_MAX) {
1082 _(
"Out of bounds drill number %d "
1083 "at line %ld in file \"%s\""),
1084 tool_num, file_line, fd->filename
1090 state->current_tool = tool_num;
1094 temp = gerb_fgetc(fd);
1099 switch ((
char)temp) {
1102 dprintf(
" Read a size of %g\n", size);
1106 }
else if (size >= 4.0) {
1115 _(
"Read a drill of diameter %g inches "
1116 "at line %ld in file \"%s\""),
1117 size, file_line, fd->filename
1123 if (size <= 0. || size >= 10000.) {
1126 _(
"Unreasonable drill size %g found for drill %d "
1127 "at line %ld in file \"%s\""),
1128 size, tool_num, file_line, fd->filename
1131 if (apert != NULL) {
1141 _(
"Found redefinition of drill %d "
1142 "at line %ld in file \"%s\""),
1143 tool_num, file_line, fd->filename
1147 apert = image->
aperture[tool_num] = g_new0(gerbv_aperture_t, 1);
1149 GERB_FATAL_ERROR(
"malloc tool failed in %s()", __FUNCTION__);
1154 apert->parameter[0] = size;
1156 apert->nuf_parameters = 1;
1164 string = g_strdup_printf(
"%s", (state->unit ==
GERBV_UNIT_MM ? _(
"mm") : _(
"inch")));
1165 drill_stats_add_to_drill_list(
1166 stats->drill_list, tool_num, state->unit ==
GERBV_UNIT_MM ? size * 25.4 : size,
string
1174 gerb_fgetint(fd, NULL);
1185 temp = gerb_fgetc(fd);
1189 _(
"Unexpected EOF encountered in header of "
1190 "drill file \"%s\""),
1195 if (
'\n' == temp ||
'\r' == temp)
1202 if (apert == NULL) {
1205 apert = image->
aperture[tool_num] = g_new0(gerbv_aperture_t, 1);
1207 GERB_FATAL_ERROR(
"malloc tool failed in %s()", __FUNCTION__);
1210 dia = gerbv_get_tool_diameter(tool_num);
1216 dia = (double)(16 + 8 * tool_num) / 1000;
1222 if (tool_num != 0) {
1225 _(
"Tool %02d used without being defined "
1226 "at line %ld in file \"%s\""),
1227 tool_num, file_line, fd->filename
1236 apert->nuf_parameters = 1;
1237 apert->parameter[0] = dia;
1241 if (tool_num != 0) {
1244 string = g_strdup_printf(
"%s", (state->unit ==
GERBV_UNIT_MM ? _(
"mm") : _(
"inch")));
1245 drill_stats_add_to_drill_list(
1246 stats->drill_list, tool_num, state->unit ==
GERBV_UNIT_MM ? dia * 25.4 : dia,
string
1252 dprintf(
"<---- ...leaving %s()\n", __FUNCTION__);
1258 static drill_m_code_t
1259 drill_parse_M_code(gerb_file_t* fd, drill_state_t* state,
gerbv_image_t* image, ssize_t file_line) {
1261 drill_m_code_t m_code;
1264 dprintf(
"---> entering %s() ...\n", __FUNCTION__);
1266 op[0] = gerb_fgetc(fd);
1267 op[1] = gerb_fgetc(fd);
1270 if (op[0] == EOF || op[1] == EOF) {
1272 stats->error_list,
GERBV_MESSAGE_ERROR, -1, _(
"Unexpected EOF found while parsing M-code in file \"%s\""),
1276 return DRILL_M_UNKNOWN;
1279 dprintf(
" Compare M-code \"%s\" at line %ld\n", op, file_line);
1281 switch (m_code = atoi(op)) {
1284 if (0 != strncmp(op,
"00", 2)) {
1285 m_code = DRILL_M_UNKNOWN;
1292 case 1: stats->M01++;
break;
1293 case 18: stats->M18++;
break;
1294 case 25: stats->M25++;
break;
1295 case 30: stats->M30++;
break;
1296 case 45: stats->M45++;
break;
1297 case 47: stats->M47++;
break;
1298 case 48: stats->M48++;
break;
1307 case 95: stats->M95++;
break;
1308 case 97: stats->M97++;
break;
1309 case 98: stats->M98++;
break;
1312 case DRILL_M_UNKNOWN:
break;
1315 dprintf(
"<---- ...leaving %s()\n", __FUNCTION__);
1322 drill_parse_header_is_metric(gerb_file_t* fd, drill_state_t* state,
gerbv_image_t* image, ssize_t file_line) {
1326 dprintf(
" %s(): entering\n", __FUNCTION__);
1335 if (DRILL_HEADER != state->curr_section)
1338 switch (file_check_str(fd,
"METRIC")) {
1342 _(
"Unexpected EOF found while parsing \"%s\" string "
1344 "METRIC", fd->filename
1353 if (
',' != gerb_fgetc(fd)) {
1358 switch (c = gerb_fgetc(fd)) {
1361 if (
'Z' != gerb_fgetc(fd))
1366 " %s(): Detected a file that probably has "
1367 "trailing zero suppression\n",
1374 " %s(): Detected a file that probably has "
1375 "leading zero suppression\n",
1382 if (state->autod && state->number_format != FMT_USER) {
1391 state->header_number_format = state->number_format = FMT_000_000;
1392 state->decimals = 3;
1395 if (
',' == gerb_fgetc(fd))
1404 if (
'0' != gerb_fgetc(fd) ||
'0' != gerb_fgetc(fd))
1409 op[0] = gerb_fgetc(fd);
1410 op[1] = gerb_fgetc(fd);
1412 if (EOF == op[0] || EOF == op[1])
1415 if (0 == strcmp(op,
"0.")) {
1418 if (
'0' != gerb_fgetc(fd) ||
'0' != gerb_fgetc(fd))
1424 state->number_format = FMT_0000_00;
1425 state->decimals = 2;
1430 if (0 != strcmp(op,
".0"))
1435 if (
'0' != gerb_fgetc(fd))
1438 if (
'0' == gerb_fgetc(fd) && state->autod) {
1439 state->number_format = FMT_000_000;
1440 state->decimals = 3;
1445 state->number_format = FMT_000_00;
1446 state->decimals = 2;
1460 _(
"Found junk after METRIC command "
1461 "at line %ld in file \"%s\""),
1462 file_line, fd->filename
1479 drill_parse_header_is_metric_comment(gerb_file_t* fd, drill_state_t* state,
gerbv_image_t* image, ssize_t file_line) {
1482 dprintf(
" %s(): entering\n", __FUNCTION__);
1484 if (DRILL_HEADER != state->curr_section) {
1488 switch (file_check_str(fd,
"FILE_FORMAT")) {
1492 _(
"Unexpected EOF found while parsing \"%s\" string "
1493 "in file \"%s\" on line %ld"),
1494 "FILE_FORMAT", fd->filename, file_line
1501 if (file_check_str(fd,
"=") != 1) {
1504 _(
"Expected '=' while parsing \"%s\" string "
1505 "in file \"%s\" on line %ld"),
1506 "FILE_FORMAT", fd->filename, file_line
1512 gerb_fgetint(fd, &len);
1517 _(
"Expected integer after '=' while parsing \"%s\" string "
1518 "in file \"%s\" on line %ld"),
1519 "FILE_FORMAT", fd->filename, file_line
1524 if (file_check_str(fd,
":") != 1) {
1527 _(
"Expected ':' while parsing \"%s\" string "
1528 "in file \"%s\" on line %ld"),
1529 "FILE_FORMAT", fd->filename, file_line
1535 int digits_after = gerb_fgetint(fd, &len);
1539 _(
"Expected integer after ':' while parsing \"%s\" string "
1540 "in file \"%s\" on line %ld"),
1541 "FILE_FORMAT", fd->filename, file_line
1546 state->header_number_format = state->number_format = FMT_USER;
1547 state->decimals = digits_after;
1554 drill_parse_header_is_inch(gerb_file_t* fd, drill_state_t* state,
gerbv_image_t* image, ssize_t file_line) {
1558 dprintf(
" %s(): entering\n", __FUNCTION__);
1560 if (DRILL_HEADER != state->curr_section)
1563 switch (file_check_str(fd,
"INCH")) {
1567 _(
"Unexpected EOF found while parsing \"%s\" string "
1569 "INCH", fd->filename
1577 if (
',' != gerb_fgetc(fd)) {
1582 if (c != EOF &&
'Z' == gerb_fgetc(fd)) {
1587 state->header_number_format = state->number_format = FMT_00_0000;
1588 state->decimals = 4;
1595 state->header_number_format = state->number_format = FMT_00_0000;
1596 state->decimals = 4;
1603 _(
"Found junk '%s' after "
1605 "at line %ld in file \"%s\""),
1606 gerbv_escape_char(c), file_line, fd->filename
1613 _(
"Found junk '%s' after INCH command "
1614 "at line %ld in file \"%s\""),
1615 gerbv_escape_char(c), file_line, fd->filename
1628 drill_parse_header_is_ici(gerb_file_t* fd, drill_state_t* state,
gerbv_image_t* image, ssize_t file_line) {
1631 switch (file_check_str(fd,
"ICI,ON")) {
1635 _(
"Unexpected EOF found while parsing \"%s\" string "
1637 "ICI,ON", fd->filename
1641 case 1: state->coordinate_mode = DRILL_MODE_INCREMENTAL;
return 1;
1644 switch (file_check_str(fd,
"ICI,OFF")) {
1648 _(
"Unexpected EOF found while parsing \"%s\" string "
1650 "ICI,OFF", fd->filename
1654 case 1: state->coordinate_mode = DRILL_MODE_ABSOLUTE;
return 1;
1661 static drill_g_code_t
1662 drill_parse_G_code(gerb_file_t* fd,
gerbv_image_t* image, ssize_t file_line) {
1664 drill_g_code_t g_code;
1667 dprintf(
"---> entering %s()...\n", __FUNCTION__);
1669 op[0] = gerb_fgetc(fd);
1670 op[1] = gerb_fgetc(fd);
1673 if (op[0] == EOF || op[1] == EOF) {
1675 stats->error_list,
GERBV_MESSAGE_ERROR, -1, _(
"Unexpected EOF found while parsing G-code in file \"%s\""),
1678 return DRILL_G_UNKNOWN;
1681 dprintf(
" Compare G-code \"%s\" at line %ld\n", op, file_line);
1683 switch (g_code = atoi(op)) {
1686 if (0 != strncmp(op,
"00", 2)) {
1687 g_code = DRILL_G_UNKNOWN;
1694 case 1: stats->G01++;
break;
1695 case 2: stats->G02++;
break;
1696 case 3: stats->G03++;
break;
1697 case 5: stats->G05++;
break;
1698 case 85: stats->G85++;
break;
1699 case 90: stats->G90++;
break;
1700 case 91: stats->G91++;
break;
1701 case 93: stats->G93++;
break;
1703 case DRILL_G_UNKNOWN:
1704 default: stats->G_unknown++;
break;
1707 dprintf(
"<---- ...leaving %s()\n", __FUNCTION__);
1716 drill_parse_coordinate(gerb_file_t* fd,
char firstchar,
gerbv_image_t* image, drill_state_t* state, ssize_t file_line) {
1720 gboolean found_x = FALSE;
1722 gboolean found_y = FALSE;
1725 if (firstchar ==
'X') {
1726 x = read_double(fd, state->number_format, image->
format->omit_zeros, state->decimals);
1728 }
else if (firstchar ==
'Y') {
1729 y = read_double(fd, state->number_format, image->
format->omit_zeros, state->decimals);
1736 firstchar = gerb_fgetc(fd);
1738 if (state->coordinate_mode == DRILL_MODE_ABSOLUTE) {
1745 }
else if (state->coordinate_mode == DRILL_MODE_INCREMENTAL) {
1755 _(
"Coordinate mode is not absolute and not incremental "
1756 "at line %ld in file \"%s\""),
1757 file_line, fd->filename
1764 static drill_state_t*
1765 new_state(drill_state_t* state) {
1766 state = g_new0(drill_state_t, 1);
1767 if (state != NULL) {
1769 state->curr_section = DRILL_NONE;
1770 state->coordinate_mode = DRILL_MODE_ABSOLUTE;
1771 state->origin_x = 0.0;
1772 state->origin_y = 0.0;
1774 state->backup_number_format = FMT_000_000;
1775 state->header_number_format = state->number_format = FMT_00_0000;
1777 state->decimals = 4;
1787 read_double(gerb_file_t* fd, number_fmt_t fmt,
gerbv_omit_zeros_t omit_zeros,
int decimals) {
1789 char temp[DRILL_READ_DOUBLE_SIZE];
1790 unsigned int i = 0, ndigits = 0;
1792 gboolean decimal_point = FALSE;
1793 gboolean sign_prepend = FALSE;
1795 memset(temp, 0,
sizeof(temp));
1797 read = gerb_fgetc(fd);
1798 while (read != EOF && i < (DRILL_READ_DOUBLE_SIZE - 1)
1799 && (isdigit(read) || read ==
'.' || read ==
',' || read ==
'+' || read ==
'-')) {
1800 if (read ==
',' || read ==
'.')
1801 decimal_point = TRUE;
1813 if (read ==
'-' || read ==
'+')
1814 sign_prepend = TRUE;
1816 temp[i++] = (char)read;
1817 read = gerb_fgetc(fd);
1823 if (decimal_point) {
1824 result = strtod(temp, NULL);
1826 unsigned int wantdigits;
1828 char tmp2[DRILL_READ_DOUBLE_SIZE];
1830 memset(tmp2, 0,
sizeof(tmp2));
1836 case FMT_00_0000: wantdigits = 2;
break;
1838 case FMT_000_000: wantdigits = 3;
break;
1840 case FMT_0000_00: wantdigits = 4;
break;
1842 case FMT_000_00: wantdigits = 3;
break;
1844 case FMT_USER: wantdigits = decimals;
break;
1850 _(
"%s(): omit_zeros == GERBV_OMIT_ZEROS_TRAILING but fmt = %d.\n"
1851 "This should never have happened\n"),
1865 if (wantdigits >
sizeof(tmp2) - 2) {
1867 stderr, _(
"%s(): wantdigits = %d which exceeds the maximum allowed size\n"), __FUNCTION__,
1879 "%s(): wantdigits = %d, strlen(\"%s\") = %ld\n", __FUNCTION__, wantdigits, temp, (
long)strlen(temp)
1881 for (i = 0; i < wantdigits && i < strlen(temp); i++) {
1884 for (; i < wantdigits; i++) {
1888 for (; i <= strlen(temp); i++) {
1889 tmp2[i] = temp[i - 1];
1891 dprintf(
"%s(): After dealing with trailing zero suppression, convert \"%s\"\n", __FUNCTION__, tmp2);
1894 for (i = 0; i <= strlen(tmp2) && i <
sizeof(temp); i++) {
1905 case FMT_00_0000: scale = 1E-4;
break;
1907 case FMT_000_000: scale = 1E-3;
break;
1910 case FMT_0000_00: scale = 1E-2;
break;
1912 case FMT_USER: scale = pow(10.0, -1.0 * decimals);
break;
1916 fprintf(stderr, _(
"%s(): Unhandled fmt ` %d\n"), __FUNCTION__, fmt);
1921 result = strtod(temp, NULL) * scale;
1924 dprintf(
" %s()=%f: fmt=%d, omit_zeros=%d, decimals=%d \n", __FUNCTION__, result, fmt, omit_zeros, decimals);
1933 eat_line(gerb_file_t* fd) {
1937 read = gerb_fgetc(fd);
1938 }
while (read !=
'\n' && read !=
'\r' && read != EOF);
1948 eat_whitespace(gerb_file_t* fd) {
1952 read = gerb_fgetc(fd);
1953 }
while ((read ==
' ' || read ==
'\t') && read != EOF);
1962 get_line(gerb_file_t* fd) {
1965 gchar* tmps = g_strdup(
"");
1967 read = gerb_fgetc(fd);
1968 while (read !=
'\n' && read !=
'\r' && read != EOF) {
1969 retstring = g_strdup_printf(
"%s%c", tmps, read);
1977 read = gerb_fgetc(fd);
1994 file_check_str(gerb_file_t* fd,
const char* str) {
1997 for (
int i = 0; str[i] !=
'\0'; i++) {
2022 case DRILL_G_ROUT:
return N_(
"rout mode");
2023 case DRILL_G_LINEARMOVE:
return N_(
"linear mode");
2024 case DRILL_G_CWMOVE:
return N_(
"circular CW mode");
2025 case DRILL_G_CCWMOVE:
return N_(
"circular CCW mode");
2026 case DRILL_G_VARIABLEDWELL:
return N_(
"variable dwell");
2027 case DRILL_G_DRILL:
return N_(
"drill mode");
2028 case DRILL_G_OVERRIDETOOLSPEED:
return N_(
"override tool feed or speed");
2029 case DRILL_G_ROUTCIRCLE:
return N_(
"routed CW circle");
2030 case DRILL_G_ROUTCIRCLECCW:
return N_(
"routed CCW circle");
2031 case DRILL_G_VISTOOL:
return N_(
"select vision tool");
2032 case DRILL_G_VISSINGLEPOINTOFFSET:
return N_(
"single point vision offset");
2033 case DRILL_G_VISMULTIPOINTTRANS:
return N_(
"multipoint vision translation");
2034 case DRILL_G_VISCANCEL:
return N_(
"cancel vision translation or offset");
2035 case DRILL_G_VISCORRHOLEDRILL:
return N_(
"vision corrected single hole drilling");
2036 case DRILL_G_VISAUTOCALIBRATION:
return N_(
"vision system autocalibration");
2037 case DRILL_G_CUTTERCOMPOFF:
return N_(
"cutter compensation off");
2038 case DRILL_G_CUTTERCOMPLEFT:
return N_(
"cutter compensation left");
2039 case DRILL_G_CUTTERCOMPRIGHT:
return N_(
"cutter compensation right");
2040 case DRILL_G_VISSINGLEPOINTOFFSETREL:
return N_(
"single point vision relative offset");
2041 case DRILL_G_VISMULTIPOINTTRANSREL:
return N_(
"multipoint vision relative translation");
2042 case DRILL_G_VISCANCELREL:
return N_(
"cancel vision relative translation or offset");
2043 case DRILL_G_VISCORRHOLEDRILLREL:
return N_(
"vision corrected single hole relative drilling");
2044 case DRILL_G_PACKDIP2:
return N_(
"dual in line package");
2045 case DRILL_G_PACKDIP:
return N_(
"dual in line package");
2046 case DRILL_G_PACK8PINL:
return N_(
"eight pin L package");
2047 case DRILL_G_CIRLE:
return N_(
"canned circle");
2048 case DRILL_G_SLOT:
return N_(
"canned slot");
2049 case DRILL_G_ROUTSLOT:
return N_(
"routed step slot");
2050 case DRILL_G_ABSOLUTE:
return N_(
"absolute input mode");
2051 case DRILL_G_INCREMENTAL:
return N_(
"incremental input mode");
2052 case DRILL_G_ZEROSET:
return N_(
"zero set");
2054 case DRILL_G_UNKNOWN:
2055 default:
return N_(
"unknown G-code");
2064 case DRILL_M_END:
return N_(
"end of program");
2065 case DRILL_M_PATTERNEND:
return N_(
"pattern end");
2066 case DRILL_M_REPEATPATTERNOFFSET:
return N_(
"repeat pattern offset");
2067 case DRILL_M_STOPOPTIONAL:
return N_(
"stop optional");
2068 case DRILL_M_SANDREND:
return N_(
"step and repeat end");
2069 case DRILL_M_STOPINSPECTION:
return N_(
"stop for inspection");
2070 case DRILL_M_ZAXISROUTEPOSITIONDEPTHCTRL:
return N_(
"Z-axis rout position with depth control");
2071 case DRILL_M_ZAXISROUTEPOSITION:
return N_(
"Z-axis rout position");
2072 case DRILL_M_RETRACTCLAMPING:
return N_(
"retract with clamping");
2073 case DRILL_M_RETRACTNOCLAMPING:
return N_(
"retract without clamping");
2074 case DRILL_M_TOOLTIPCHECK:
return N_(
"tool tip check");
2075 case DRILL_M_PATTERN:
return N_(
"pattern start");
2076 case DRILL_M_ENDREWIND:
return N_(
"end of program with rewind");
2077 case DRILL_M_MESSAGELONG:
return N_(
"long operator message");
2078 case DRILL_M_MESSAGE:
return N_(
"operator message");
2079 case DRILL_M_HEADER:
return N_(
"header start");
2080 case DRILL_M_VISANDRPATTERN:
return N_(
"vision step and repeat pattern start");
2081 case DRILL_M_VISANDRPATTERNREWIND:
return N_(
"vision step and repeat rewind");
2082 case DRILL_M_VISANDRPATTERNOFFSETCOUNTERCTRL:
return N_(
"vision step and repeat offset counter control");
2083 case DRILL_M_REFSCALING:
return N_(
"reference scaling on");
2084 case DRILL_M_REFSCALINGEND:
return N_(
"reference scaling off");
2085 case DRILL_M_PECKDRILLING:
return N_(
"peck drilling on");
2086 case DRILL_M_PECKDRILLINGEND:
return N_(
"peck drilling off");
2087 case DRILL_M_SWAPAXIS:
return N_(
"swap axes");
2088 case DRILL_M_METRIC:
return N_(
"metric measuring mode");
2089 case DRILL_M_IMPERIAL:
return N_(
"inch measuring mode");
2090 case DRILL_M_MIRRORX:
return N_(
"mirror image X-axis");
2091 case DRILL_M_MIRRORY:
return N_(
"mirror image Y-axis");
2092 case DRILL_M_HEADEREND:
return N_(
"header end");
2093 case DRILL_M_CANNEDTEXTX:
return N_(
"canned text along X-axis");
2094 case DRILL_M_CANNEDTEXTY:
return N_(
"canned text along Y-axis");
2095 case DRILL_M_USERDEFPATTERN:
return N_(
"user defined stored pattern");
2097 case DRILL_M_UNKNOWN:
2098 default:
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_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