rem: image->info->unit = INCH;
context: parse_drillfile(gerb_file_t *fd){    drill_state_t *state = NULL;    gerb_image_t *image = NULL;    gerb_net_t *curr_net = NULL;    int read;    double x_scale = 1, y_scale = 1;    state = new_state(state);    if (state == NULL)	GERB_FATAL_ERROR("malloc state failed\n");    image = new_gerb_image(image);    if (image == NULL)	GERB_FATAL_ERROR("malloc image failed\n");    curr_net = image->netlist;    drill_guess_format(fd, image);    if (image && image->format ){	x_scale = pow(10.0, (double)image->format->x_dec);	y_scale = pow(10.0, (double)image->format->y_dec);    }    while ((read = gerb_fgetc(fd)) != EOF) {	switch ((char)read) {	case ';' :	    /* Comment found. Eat rest of line */	    eat_line(fd);	    break;	case 'F' :	    /* Z axis feed speed. Silently ignored */	    eat_line(fd);	    break;	case 'G':	    /* Most G codes aren't used, for now */	    switch(drill_parse_G_code(fd, image)) {	    case DRILL_G_ROUT :		GERB_COMPILE_ERROR("Rout mode data is not supported\n");		break;	    case DRILL_G_DRILL :		break;	    case DRILL_G_ABSOLUTE :		state->coordinate_mode = DRILL_MODE_ABSOLUTE;		break;	    case DRILL_G_INCREMENTAL :		state->coordinate_mode = DRILL_MODE_INCREMENTAL;		break;	    case DRILL_G_ZEROSET :		if((read = gerb_fgetc(fd)) == EOF)		    GERB_COMPILE_ERROR("Unexpected EOF\n");		drill_parse_coordinate(fd, (char)read, 1.0 / x_scale, state);		state->origin_x = state->curr_x;		state->origin_y = state->curr_y;		break;	    default :		eat_line(fd);		break;	    }	    break;	case 'M':	    switch(drill_parse_M_code(fd, image)) {	    case DRILL_M_HEADER :		state->curr_section = DRILL_HEADER;		break;	    case DRILL_M_ENDHEADER :		state->curr_section = DRILL_DATA;		break;	    case DRILL_M_METRIC :		/* This is taken care of elsewhere */		break;	    case DRILL_M_IMPERIAL :		/* This is taken care of elsewhere */		break;	    case DRILL_M_LONGMESSAGE :	    case DRILL_M_MESSAGE :		/* Until we have a console, these are ignored */	    case DRILL_M_CANNEDTEXT :		/* Ignored, probably permanently */		eat_line(fd);		break;	    case DRILL_M_NOT_IMPLEMENTED :	    case DRILL_M_ENDPATTERN :	    case DRILL_M_TIPCHECK :		break;	    case DRILL_M_END :		/* M00 has optional arguments */		eat_line(fd);	    case DRILL_M_ENDREWIND :		free(state);		/* KLUDGE. All images, regardless of input format,		   are returned in INCH format */		image->info->unit = INCH;		return image;		break;	    default:		GERB_COMPILE_ERROR("Strange M code found.\n");	    }	    break;	case 'S':	    /* Spindle speed. Silently ignored */	    eat_line(fd);	    break;	case 'T':	    drill_parse_T_code(fd, state, image);	    break;	case 'X':	case 'Y':	    /* Hole coordinate found. Do some parsing */	    drill_parse_coordinate(fd, read, 1.0 / x_scale, state);	    curr_net->next = (gerb_net_t *)malloc(sizeof(gerb_net_t));	    curr_net = curr_net->next;	    memset((void *)curr_net, 0, sizeof(gerb_net_t));	    curr_net->start_x = (double)state->curr_x;	    curr_net->start_y = (double)state->curr_y;	    /* KLUDGE. This function isn't allowed to return anything	       but inches */	    if(image->info->unit == MM) {		(double)curr_net->start_x /= 25.4;		(double)curr_net->start_y /= 25.4;	    }	    curr_net->stop_x = curr_net->start_x - state->origin_x;	    curr_net->stop_y = curr_net->start_y - state->origin_y;	    curr_net->aperture = state->current_tool;	    curr_net->aperture_state = FLASH;	    /* Find min and max of image.	       Mustn't forget (again) to add the hole radius */	    image->info->min_x =		min(image->info->min_x,		    (curr_net->start_x -		     image->aperture[state->current_tool]->parameter[0] / 2));	    image->info->min_y =		min(image->info->min_y,		    (curr_net->start_y -		     image->aperture[state->current_tool]->parameter[0] / 2));	    image->info->max_x =		max(image->info->max_x,		    (curr_net->start_x +		     image->aperture[state->current_tool]->parameter[0] / 2));	    image->info->max_y =		max(image->info->max_y,		    (curr_net->start_y +		     image->aperture[state->current_tool]->parameter[0] / 2));	    break;	case '%':	    state->curr_section = DRILL_DATA;	    break;	case 10 :   /* White space */	case 13 :	case ' ' :	case '\t' :	    break;	default:	    if(state->curr_section == DRILL_HEADER) {		/* Unrecognised crap in the header is thrown away */		eat_line(fd);	    } else {		fprintf(stderr,			"Warning: Found ill fitting character '%c' [0x%02x] inside data, ignoring\n",			read, read);	    }	}    }    fprintf(stderr, "Warning: File is missing drill End-Of-File\n");    return image;} /* parse_drillfile */