Contact me: hankecnc@gmail.com

nuts_bolts.c 中的 strtod() 可能会读取比您预期更多的行 #122

推推 grbl 3年前 (2023-01-21) 156次浏览

关闭
csdexter 打开了这个问题 2012 年 10 月 6 日 · 8条评论
关闭

nuts_bolts.c 中的 strtod() 可能会读取比您预期更多的行#122

csdexter 打开了这个问题 2012 年 10 月 6 日 · 8条评论

注释

nuts_bolts.c 中的 strtod() 可能会读取比您预期更多的行 #122

strtod() 会将“E”解析为科学计数法,但“E”是 G-Code 中的一个词(而 G-Code 根本不使用科学计数法)。
strtod() 会将“0X”解析为 base-16 数字,这可能会给零件和工具带来灾难(想想 G01 Y0 X12:G 将解析为“1”,Y 将解析为 0x12 = 18 而不是 0)。

今晚我会为我的叉子想出一个修复程序,因为你的叉子也使用 strtod() ,所以打开它作为提醒。如果我的修复对你来说不错,请随意挑选它。

nuts_bolts.c 中的 strtod() 可能会读取比您预期更多的行 #122
作者

这是针对您的nuts_bolts.c (HEAD) 的修复,以使其尽可能容易地应用/合并。

希望这可以帮助 :)

--- nuts_bolts.c.orig   2012-10-06 00:09:59.100195145 +0100            
+++ nuts_bolts.c        2012-10-06 00:16:31.430258230 +0100            
@@ -2,11 +2,11 @@                                                      
   nuts_bolts.c - Shared functions                                     
   Part of Grbl                                                        

   Copyright (c) 2009-2011 Simen Svale Skogsrud                        
   Copyright (c) 2011-2012 Sungeun K. Jeon                             
-                                                                      
+                                                                      
   Grbl is free software: you can redistribute it and/or modify        
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or   
   (at your option) any later version.                                 

@@ -22,18 +22,35 @@                                                    
 #include "nuts_bolts.h"                                               
 #include <stdint.h>                                                   
 #include <stdlib.h>                                                   
 #include <util/delay.h>                                               

-int read_double(char *line, uint8_t *char_counter, double *double_ptr)                                                                                         
+int read_double(char *line, uint8_t *char_counter, double *double_ptr)         
 {                                                                              
   char *start = line + *char_counter;                                          
   char *end;                                                                   
-                                                                               
+  char saveChar = '\0';                                                        
+  uint8_t saveIndex = *char_counter;                                           
+                                                                               
+  if(line[saveIndex] == '+' || line[saveIndex] == '-') {                       
+   saveIndex++; // Skip over sign, if present                                  
+  }
+  while (line[saveIndex] &&
+     ((line[saveIndex] >= '0' && line[saveIndex] <= '9') || line[saveIndex] == '.')) {
+    saveIndex++; // Find the end of the number
+  }
+  if(line[saveIndex]) { // Otherwise it's \0 anyway, no need to fixup
+    saveChar = line[saveIndex];
+    line[saveIndex] = '\0';
+  }
+  // strtod() will now see only the number and nothing beyond it
   *double_ptr = strtod(start, &end);
-  if(end == start) {
-    return(false);
+  if(saveChar) {
+    line[saveIndex] = saveChar; // Undo the fix, if needed
+  }
+  if(end == start) {
+    return(false);
   };

   *char_counter = end - line;
   return(true);
 }
nuts_bolts.c 中的 strtod() 可能会读取比您预期更多的行 #122
成员

唔。我能够测试并验证“E”字符是否以科学计数法正确解析,但不是您提供的“0X”十六进制示例。它正确地分隔了“Y”和“X”这两个词。不知道为什么这是不同的。我使用与 Arduino IDE v1.0 一起打包的 avr-gcc。我想知道这是否与它有关。

就科学记数法而言,我在我们使用的 NIST 标准中没有看到任何参考资料明确指出不能使用科学记数法,也没有将“E”字符保留为 g 代码字。我知道 g 代码在制造商和标准之间非常分散,许多词之间可能会有很大差异。你能提供这方面的参考吗?

nuts_bolts.c 中的 strtod() 可能会读取比您预期更多的行 #122
成员

我搜索了 NIST g 代码标准,其中有一节讨论什么是“数字”。它描述了一个仅包含“0-9”字符和可选的 +、- 和 的值。人物。所以看起来’E’已经出来了。

但是,我认为 protocol.c 中的 protocol_process() 是主动搜索此字符的更好位置,因为它已经在解析来自串行流的每个传入字符,并且可以向用户报告无效数字。

至于 ‘0X’ 十六进制的东西,我们需要找出为什么你会看到这个问题,而不是我在标准 grbl 版本上。

nuts_bolts.c 中的 strtod() 可能会读取比您预期更多的行 #122
作者

EG代码中的词是车床上螺纹加工的精确进给率。它可能很旧,今天很少使用,但仍然是标准的一部分,因此可能会在野外遇到它而且,最重要的是,就像你发现的那样,G 代码中的浮点数使用科学记数法,所以不口译员应该读1.2E10作 1.2 * 10^10 而不是前一个单词的 1.2 和单词的 10 E
参考:

  • CNC 编程手册(Peter Smid,第 2 版),第 13 章,第 92 页
  • RS274NGC v3(Kramer 等人),标题 3.3.2.1,第 17 页

关于 protocol_process() 评论,我认为 E 字不应该从流中完全剥离,而是防止干扰 strtod() 的解析语义。我发送的 diff 只是其中一种方法,我相信还有很多方法可供选择 :)

关于0X十六进制解码(在 的特定情况下strtod(),它也受P二进制指数定界符的影响——就像E十进制指数定界符一样),它只会在当前块被方便地安排以得出行为。这意味着当前扫描的单词的值必须写成一个紧跟 0单词的X单词(并且可选地后跟P单词以获得最大的破坏效果)。
对于(错误的)E解码,您只需要当前单词的值由该E单词后继即可。

实际例子:

  • G0 X0.010 Y50.2— 这将解析为 G 0x0.010 (= 0.003906),这将导致错误(无效命令)而不是 G 0 和 X 0.010。请注意,整个X单词都被转换吃掉了,其余代码看不到
  • G01 X50.2 E10 Y32.2— 这将解析为 G 1、X 50.2E10 (= 502000000000.0)、Y 32.2 而不是 G 1、X 50.2、E 10 和 Y 32.2。整个E单词就像上面一样被吃光了
  • G82 Z0 X15 P4— 这将解析为 G 82、Z 0x15.2P4 (= 338.0) 而不是 G 82、Z 0、X 15 和 P 4
nuts_bolts.c 中的 strtod() 可能会读取比您预期更多的行 #122

我看到了 0x 移植到 ARM 的问题(issue#94),我的快速修复是检查
next_statement() 中的 0x 序列并返回正确的值

nuts_bolts.c 中的 strtod() 可能会读取比您预期更多的行 #122
成员

案例和要点,Radu。我一直在思考如何优雅地解决这个问题。那么,在没有 base16 和指数解析的情况下编写我们自己的简化 strtod() 函数会有什么问题吗?代码看起来非常直接和简短,我们可以将它安装到 nuts_bolts.c 中。这似乎直接解决了这个问题,而不是建立一个检查系统。如果我理解正确,这甚至可以节省一些字节。

nuts_bolts.c 中的 strtod() 可能会读取比您预期更多的行 #122
作者

是的,编写自定义 strtod() 可能是最好的方法,因为所需的功能比原始功能少——因此代码大小的减少是可以预料的。

nuts_bolts.c 中的 strtod() 可能会读取比您预期更多的行 #122

还应注意,reprap Gcode 使用“E”来设置挤出机电机的速度。

喜欢 (0)