/* $FabBSD$ */ /* * Copyright (c) 2010 Hypertriton, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include const char *cnc_tool_strings[] = { "none", "drill", "holesaw", "endmill", "slitsaw", "facemill", "gearcutter" }; const char *cnc_endmill_nose_strings[] = { "flat", "rounded", "tapered", "ball", "chamfer", "dovetail", "t-slot", "corner-rounding", "convex-radius", "concave-radius" }; #define FIELD_SEP "|:;,/ " /* * Initialize tool from a drill specification string: * diameter:[length]:[point-angle] */ static int cnc_parse_drill(char *s, struct cnc_tool *t) { char *tok, *ep; int wire; /* Parse the drill diameter */ if ((tok = strsep(&s, FIELD_SEP)) == NULL) { cnc_set_error("Missing drill diameter"); return (-1); } if (isalpha(tok[0]) && isupper(tok[0])) { t->data.drill.dia = cnc_drill_letter[(*tok)-'A']; } else if ((tok[0] == '#' || tolower(tok[0]) == 'w') && tok[1] != '\0') { wire = (int)strtoul(&tok[1], &ep, 10); if (wire < 0 || wire > 80) { cnc_set_error("No such wire drill number: %d", wire); return (-1); } t->data.drill.dia = cnc_drill_wire[wire]; } else { if (cnc_dist_parse(&t->data.drill.dia, tok) == -1) { cnc_set_error("Drill diameter: %s", cnc_get_error()); return (-1); } } /* Parse the drill length */ if ((tok = strsep(&s, FIELD_SEP)) != NULL && tok[0] != '\0') { if (cnc_dist_parse(&t->data.drill.len, tok) == -1) { cnc_set_error("Drill length: %s", cnc_get_error()); return (-1); } } /* Parse the drill point angle */ if ((tok = strsep(&s, FIELD_SEP)) != NULL && tok[0] != '\0') { if (cnc_angle_parse(&t->data.drill.ptAngle, tok) == -1) { cnc_set_error("Drill point angle: %s", cnc_get_error()); return (-1); } } return (0); } static void cnc_print_drill(const struct cnc_tool *t) { printf("%f dia", t->data.drill.dia); if (t->data.drill.len != 0) printf(", %f len", t->data.drill.len); if (t->data.drill.ptAngle != 0) printf(", %d deg", t->data.drill.ptAngle); } /* * Initialize tool from a hole saw specification string: * diameter:[length]:[point-angle] */ static int cnc_parse_holesaw(char *s, struct cnc_tool *t) { char *tID, *tOD, *ep; int wire; /* Parse the hole saw ID and OD */ if ((tID = strsep(&s, FIELD_SEP)) == NULL || (tOD = strsep(&s, FIELD_SEP)) == NULL) { cnc_set_error("Missing ID/OD"); return (-1); } if (cnc_dist_parse(&t->data.holesaw.id, tID) == -1) { cnc_set_error("Holesaw ID: %s", cnc_get_error()); return (-1); } if (cnc_dist_parse(&t->data.holesaw.od, tOD) == -1) { cnc_set_error("Holesaw OD: %s", cnc_get_error()); return (-1); } return (0); } static void cnc_print_holesaw(const struct cnc_tool *t) { printf("%f ID, %f OD", t->data.holesaw.id, t->data.holesaw.od); } const struct { int (*parseFn)(char *s, struct cnc_tool *); void (*printFn)(const struct cnc_tool *); } cnc_tool_fns[] = { { NULL, NULL }, { cnc_parse_drill, cnc_print_drill }, { cnc_parse_holesaw, cnc_print_holesaw } }; /* Parse a tool specification string. */ int cnc_tool_parse(const char *s, struct cnc_tool *t) { char *sDup; int i; for (i = 0; i < CNC_TOOL_LAST; i++) { if (strncasecmp(s, cnc_tool_strings[i], strlen(cnc_tool_strings[i])) == 0) break; } if (i == CNC_TOOL_LAST) { cnc_set_error("No such tool: `%s'", s); return (-1); } if ((sDup = strdup(s)) == NULL) { cnc_set_error("Out of memory"); return (-1); } if (cnc_tool_fns[i].parseFn(sDup, t) == -1) { free(sDup); return (-1); } free(sDup); return (0); } /* Print tool information */ void cnc_tool_print(const struct cnc_tool *t) { fputs( " [", stdout); if (t->atc != -1) { printf("atc%d:", t->atc); } fputs(cnc_tool_strings[t->type], stdout); if (t->type == CNC_TOOL_ENDMILL) { fputc('/', stdout); fputs(cnc_endmill_nose_strings[t->data.endmill.nose], stdout); } fputs("] ", stdout); switch (t->type) { case CNC_TOOL_DRILL: printf(" dia=%f", t->data.drill.dia); if (t->data.drill.len != 0) printf(" len=%f", t->data.drill.len); if (t->data.drill.ptAngle != 0) printf(" point=%d", t->data.drill.ptAngle); break; case CNC_TOOL_HOLESAW: printf(" ID=%f", t->data.holesaw.id); printf(" OD=%f", t->data.holesaw.od); if (t->data.holesaw.len != 0) printf(" len=%f", t->data.holesaw.len); break; case CNC_TOOL_ENDMILL: printf(" %s=%f", (t->data.endmill.nose == CNC_ENDMILL_TAPERED) ? "tip-dia":"dia", t->data.endmill.dia); printf(" %s=%f", (t->data.endmill.nose == CNC_ENDMILL_TSLOT) ? "face-wd":"len", t->data.endmill.len); switch (t->data.endmill.nose) { case CNC_ENDMILL_CHAMFER: case CNC_ENDMILL_DOVETAIL: printf(" angle=%d", t->data.endmill.angle); break; case CNC_ENDMILL_ROUNDED: case CNC_ENDMILL_CORNER_ROUNDING: case CNC_ENDMILL_CONVEX_RADIUS: case CNC_ENDMILL_CONCAVE_RADIUS: printf(" radius=%f", t->data.endmill.r); break; } break; default: break; } printf("\n"); }