Shop OBEX P1 Docs P2 Docs Learn Events
No scani in Simpletext library?? — Parallax Forums

No scani in Simpletext library??

twm47099twm47099 Posts: 867
edited 2016-01-28 06:45 in Learn with BlocklyProp
For most of my prop C programming, I use the "i" (no floating point) versions of print,sprint, dprint, etc. (printi, sprinti, dprinti, etc.) because they use about 5k bytes less memory than the non-"i" versions

Today I was writing some code for the EMIC2, and one of the things I wanted to do was get a string couple of numbers typed in from the Simple Terminal, do some arithmetic on them, and have the math & answer spoken by the EMIC2.

I tried to use the scani function (listed in the Simpletext documentation) to read in text numbers from the terminal, but I kept getting an invalid function error. I eventually just used scan and everything worked, but with quite a penalty on memory use.

When I looked through the c files in the simpletext library, I noticed that while there were "i" versions of the other functions, there was no scani.c or sscani.c

Is that intentional? If possible, it would be useful to have scani and sscani added to the library.

Thanks
Tom

Comments

  • You can often use atoi() instead. Not quite as convenient as scan(), but much lighter weight.
  • I mis-spoke in my op. I meant to say that I wanted to input a number from the terminal using scani.

    Jason,
    I will try using atoi. I think I would get the number as a string using the Simple Library function:
    getStr (&mybuffer,32);
    and then
    int a = atoi (&mybuffer);

    Does that seem right?

    Tom
  • Yup, I think so. atoi just takes a string of characters and converts to a number until it hits a non-number character, so start on the first digit (or the - sign) and it should work fine. If the user enters a non digit character (even a space) that can confuse it, so just be aware of that.
  • If you find yourself needing more than atoi, PropWare also has this functionality built-in with its Scanner class
  • Now that I'm not on my phone I wanted to provide some more detail on that Scanner class. A demo can be seen here which shows off three different ways to gather data from the terminal: gets, >>, and input_prompt. To read a number you can use the easiest though:
    #include <PropWare/scanner.h>
    #include <PropWare/printer/printer.h>
    
    int main () {
      int x;
    
      pwOut << "Enter a number: ";
      pwIn >> x;
    
      pwOut << "You entered '" << x << "' as your number.\n";
      return 0;
    }
    

  • Jason,
    I tried the getStr/atoi method I mentioned above and it worked.

    I took some notes on memory usage:

    1. non-"i" print/dprint functions with scan: 11,784 bytes.
    2. non-"i" functions with getStr/atoi: 10,908 bytes
    3. "i" functions with scan: 9,560 bytes
    4. "i" functions with getStr/atoi: 6,532 bytes.

    Deleting the getStr and atoi statements showed they used only approx 300 bytes (3 instances).

    So there is a significant memory savings (out of 32K) by using the "i" functions, and using getStr and atoi has very little memory cost compared with scan.

    Tom
  • twm47099twm47099 Posts: 867
    edited 2016-01-28 18:34
    David,
    At sometime in the future, I want to use Propware, but for now I am working on learning Spin, PASM, and C (SimpleIDE style).

    One of my big problems with the other C type languages/implementations is the complexity with building (compiling/linking/loading/?) a working program. That is where tools like Proptool, PropIDE, and SimpleIDE (and for that matter the different forths) make it easier to learn the languages. I can fight with the logic and syntax of the language without wondering if I screwed up the build commands.

    I'm not sure if there is a clear reference document somewhere to such build processes, the commands and options. With the languages when I have a syntax problem, I can go to the standard or a reference to get it straight, but with the builds I have no idea where to go or even what questions to ask or search on.

    Tom
  • twm47099 wrote: »
    David,
    At sometime in the future, I want to use Propware, but for now I am working on learning Spin, PASM, and C (SimpleIDE style).

    One of my big problems with the other C type languages/implementations is the complexity with building (compiling/linking/loading/?) a working program. That is where tools like Proptool, PropIDE, and SimpleIDE (and for that matter the different forths) make it easier to learn the languages. I can fight with the logic and syntax of the language without wondering if I screwed up the build commands.

    I recently documented how to use PropWare's libraries with SimpleIDE. Perhaps that will ease any transition you might make. This way you don't have to mess with building PropWare or using PropWare's build system to compile your own project; just click a few buttons in SimpleIDE and then start using PropWare libraries right from your existing project. The most difficult part is renaming your file from whatever.c to whatever.cpp (which, admittedly, is weirdly difficult)
    twm47099 wrote: »
    I'm not sure if there is a clear reference document somewhere to such build processes, the commands and options. With the languages when I have a syntax problem, I can go to the standard or a reference to get it straight, but with the builds I have no idea where to go or even what questions to ask or search on.

    Tom

    That's harder. The problem is that there are lots of different ways to build programs - lots of different "toolchains". The toolchain is a whole collection of executables, so you have to learn about multiple executables. Then you also have to learn about each of the different toolchains so that you can pick the best one for your needs. Thankfully, the Propeller only has two C/C++ toolchains: PropGCC and Catalina. So the choice isn't too hard.

    Once you learn the toolchain, it is then recommended (though not required) that you learn a "build system," such as Make, CMake, QMake, etc. The choices are truly endless here! Any build system can be tweaked to work for a Propeller, so the question is how much work are you willing to do to make your build system work with your system. In this case, a couple options have made things easier for you: common.mk shipped with every distribution of PropGCC, and PropWare's CMake installation.

    Long story short, I understand why you might think it is intimidating. Thankfully, whenever you want to start learning, PropWare's build system is as easy as it gets for the Propeller. I've documented it here.
  • twm47099 wrote: »
    Deleting the getStr and atoi statements showed they used only approx 300 bytes (3 instances).

    So there is a significant memory savings (out of 32K) by using the "i" functions, and using getStr and atoi has very little memory cost compared with scan.

    That's one of the reasons I tend to use my own functions for things like that instead of libraries, unless I know the cost. With PropGCC, function-level linking doesn't appear to be supported, so the linker is only able to remove unused code with the granularity of a single source code file (which becomes one object file). If you're only using a single function in a library of code, you pay the memory cost of all the other code that comes with it in the same file.

    The "scan" functions support many options for formatting and parsing, and they're driven by the source string, so the compiler can't really tell in advance what you'll be using, so even if it *did* support function level linking, it wouldn't be able to reduce it. If you're only using it to parse an int, using the scan() functions is like using a sledgehammer to push in a thumbtack. :) The atoi style functions tend to be much faster.
  • DavidZemonDavidZemon Posts: 2,973
    edited 2016-01-28 22:18
    JasonDorie wrote: »
    twm47099 wrote: »
    Deleting the getStr and atoi statements showed they used only approx 300 bytes (3 instances).

    So there is a significant memory savings (out of 32K) by using the "i" functions, and using getStr and atoi has very little memory cost compared with scan.

    That's one of the reasons I tend to use my own functions for things like that instead of libraries, unless I know the cost. With PropGCC, function-level linking doesn't appear to be supported, so the linker is only able to remove unused code with the granularity of a single source code file (which becomes one object file). If you're only using a single function in a library of code, you pay the memory cost of all the other code that comes with it in the same file.

    There are four ways that I know of to fix this.

    1) Put every function in its own file
    2) Compile with "-ffunction-sections -fdata-sections" and link with "-Wl,--gc-sections"
    3) Link with -lto (not supported in PropGCC with GCC 4.6)
    4) Use header-only libraries

    Simple libraries use solution #1. PropWare uses both #2 and #4. Hopefully we'll be able to use #3 when the new version of PropGCC is complete, which will be based off of GCC 6.0 (or later).

    The problem with print, printi, scan, and scani is that the compiler has no way of knowing which format specifiers are needed. It is not smart enough to inspect your string literals and then prune out the unneeded ones. PropWare gets around this by using templates, which means that the compiler is able to prune unneeded functions based on what parameters are given to printf (still not smart enough to inspect the string literal with the format specifiers :P ). This is also why PropWare doesn't have the print/printi confusion. If you don't give printf a floating point number, the floating point function won't be included in your binary, simple as that :)
  • Header-only libraries obliterate the ability to use statics or globals, so that's not really an option. Templates can be grossly inefficient because of the way they generate code. (They aren't always, there are ways around it - I use them often). For use on a micro with limited memory, function level linking is an arguable necessity, which is why the Simple libs do everything in their own file, but that's a pain in the @$$ way to code.

    Every time I see something like, "oh, just use -ffunction-sections -fvoodoo+chicken+dance -blood_sacrifice on the command line!" I die a little inside. You shouldn't have to remember obscure passwords to get efficient code, or access to any feature, really. I like IDEs that generate the command lines for you. (yes, I'm spoiled)
  • DavidZemonDavidZemon Posts: 2,973
    edited 2016-01-28 22:36
    JasonDorie wrote: »
    Header-only libraries obliterate the ability to use statics or globals, so that's not really an option. Templates can be grossly inefficient because of the way they generate code. (They aren't always, there are ways around it - I use them often). For use on a micro with limited memory, function level linking is an arguable necessity, which is why the Simple libs do everything in their own file, but that's a pain in the @$$ way to code.

    For C code, absolutely header-only would be a joke :). For C++, it's great. There are a few times that I've needed a global variable and had to use source files - like `pwOut` so that users don't have to create a UART object and then attach it to a Printer.

    And yea, the templates can get large. So that's why I try to use the << and >> operators whenever possible. Easy and effecient! But, PropWare::Printer and PropWare::Scanner provide both :)
    JasonDorie wrote: »
    Every time I see something like, "oh, just use -ffunction-sections -fvoodoo+chicken+dance -blood_sacrifice on the command line!" I die a little inside. You shouldn't have to remember obscure passwords to get efficient code, or access to any feature, really. I like IDEs that generate the command lines for you. (yes, I'm spoiled)

    That's what any build system is for. Write it once and forget it. I had to look it up in PropWare's source code just to write the post above :P
  • jazzedjazzed Posts: 11,803
    edited 2016-01-29 02:02
    JasonDorie wrote: »
    Every time I see something like, "oh, just use -ffunction-sections -fvoodoo+chicken+dance -blood_sacrifice on the command line!" I die a little inside. You shouldn't have to remember obscure passwords to get efficient code, or access to any feature, really. I like IDEs that generate the command lines for you. (yes, I'm spoiled)

    SimpleIDE does this gc incantation for you if you check "Enable Pruning" in the Project/Compiler area (easier to remember if you know about it). This is how libArduino projects can fit on Propeller.

    The disadvantage of the gc method is if you only have a little pruning, the file output can actually be bigger in some cases.

    Tom I don't know how we missed scani, but I too have used the gets/atoi workaround thinking "hmm, what happened?"

    Hmm, the user guide seems to be missing the "Enable Pruning" checkbox so I can't verify if it's in the project compiler or linker tab since I don't have the program installed here.
  • Steve,
    I wonder if there is something about scan and sscan that made having an "i" version problematic. Both only have the non-"i" versions.

    Tom
  • I've commented on this before, but I feel the need to do it again. In my opinion, it is not a good idea to have nonstandard versions of scanf, sscanf, printf, etc. This teaches new C programs to use nonstandard names, which will cause confusion for them in the future when they share code with others on non-Parallax processors.

    I understand that scan, sscan, scani, print and other proprietary names are used to provide libraries with a smaller size than the stdio library. However, this could be handled by using the standard function names and specifying a limited library instead of the full stdio library.

    I realize that the ship has already sailed on the use of scan, sscan, etc., and it's probably too late to try to rectify this. However, I just feel compelled to comment on the use of nonstandard names.
Sign In or Register to comment.