Need Help with PropGCC (Function types & prototypes) [SOLVED]

JonnyMacJonnyMac Posts: 6,574
edited 2019-12-18 - 18:55:47 in Propeller 1
I thought it would be a fun diversion to port my TM1637 driver to C -- I am now regretting that, but angry enough not to quit.

I keep getting silly warnings like this:
TM1637_Demo.c:45:3: warning: implicit declaration of function 'tm1637_begin' [-Wimplicit-function-declaration]
TM1637_Demo.c:46:3: warning: implicit declaration of function 'tm1637_write' [-Wimplicit-function-declaration]
TM1637_Demo.c:47:3: warning: implicit declaration of function 'tm1637_end' [-Wimplicit-function-declaration]

...but when I add function prototypes, things get even worse:
TM1637_Demo.c:45:3: warning: implicit declaration of function 'tm1637_begin' [-Wimplicit-function-declaration]
TM1637_Demo.c:46:3: warning: implicit declaration of function 'tm1637_write' [-Wimplicit-function-declaration]
TM1637_Demo.c:47:3: warning: implicit declaration of function 'tm1637_end' [-Wimplicit-function-declaration]

Why? Why is PropGCC giving my functions an implicit type when I am EXPLICITLY declaring them as void or uint8_t?

Comments

  • JonnyMacJonnyMac Posts: 6,574
    edited 2019-12-18 - 18:57:33
    Here's where I am in the event someone wants to set me straight.

    Here is the corrected code; this compiles as expected.
    // =================================================================================================
    //
    //   File....... TM1637_Demo.c
    //               *** work in progress ***
    //   Purpose.... Demonstration code for TM1637 modules
    //   Author..... Jon "JonnyMac" McPhalen
    //               Copyright (c) 2019 Jon McPhalen
    //               -- MIT license applies
    //   E-mail..... jon@jonmcphalen.com
    //   Started....
    //   Updated.... 18 DEC 2016
    //
    // =================================================================================================
    
    
    #include <propeller.h>
    #include <stdint.h>
    
    
    #define  WR_DATA  0x40
    #define  RD_BTN   0x42
    #define  WR_FIXD  0x44
    #define  DSP_OFF  0x80
    #define  DSP_ON   0x88
    #define  WR_SEGS  0xC0
    
    uint32_t cmask;
    uint32_t dmask;
    uint8_t  size;
    uint8_t  buffer[6];
    
     
    uint8_t  tm1637_setup(uint8_t cpin, uint8_t dpin, uint8_t ncols);
    void     tm1637_clear();
    void     tm1637_fill(uint8_t segments);
    void     tm1637_set_segments(uint8_t col, uint8_t segments);
    uint8_t  tm1637_send_command(uint8_t cmd);
    void     tm1637_start();
    uint8_t  tm1637_write(uint8_t b) ;
    uint8_t  tm1637_read();
    void     tm1637_stop();
     
    
    uint8_t tm1637_setup(uint8_t cpin, uint8_t dpin, uint8_t ncols)
    {
      cmask = 1 << cpin;                                            // create masks for pins
      dmask = 1 << dpin;
    
      if ((ncols >= 2) && (ncols <= 6))                             // set display size
        size = ncols;
      else
        size = 4;
    
      DIRA &= ~cmask;                                               // float pin
      OUTA &= ~cmask;                                               // write 0 to output bit
      DIRA &= ~dmask;
      OUTA &= ~dmask;
    
      return tm1637_send_command(0);                                // verify defice connected
    }
    
    
    void tm1637_clear()
    {
      tm1637_fill(0);
    }
    
    
    void tm1637_fill(uint8_t segments)
    {
      for (uint8_t i = 0; i < 6; i++)
        buffer[i] = segments;
    
      tm1637_start();
      tm1637_write(WR_SEGS);
      for (uint8_t i = 0; i < 6; i++)
        tm1637_write(segments);  
      tm1637_stop();
    }
    
    
    void tm1637_set_segments(uint8_t col, uint8_t segments)
    {
      if (col >= size)
        return;
    
      buffer[col] = segments;
    
      tm1637_start();
      tm1637_write(WR_SEGS);
      tm1637_write(segments);
      tm1637_stop();
    }
    
    
    uint8_t tm1637_send_command(uint8_t cmd)
    {
      tm1637_start();
      uint8_t ackbit = tm1637_write(cmd);
      tm1637_stop();
    
      return ackbit;
    }
    
    
    void tm1637_start()
    {
      DIRA &= ~cmask;                                               // float pins to pull-ups
      DIRA &= ~dmask;
      // 5us delay
      DIRA |= dmask;                                                // dio low
      // 5us delay
      DIRA |= cmask;                                                // clock low
    }
    
    
    uint8_t tm1637_write(uint8_t b)
    {
      for (uint8_t i = 0; i < 8; i++) {
        if (b & 0x01 == 1)
          DIRA &= ~dmask;
        else
          DIRA |= dmask;
        b >>= 1;
        // 5us delay
        DIRA &= ~cmask;
        // 5us delay
        DIRA |= cmask;
      }
    
      DIRA &= ~dmask;
      // 5us delay
      DIRA &= ~cmask;
      // 5us delay
      uint8_t ackbit = (INA & dmask == 0) ? 0 : 1;
      DIRA |= cmask;
    
      return ackbit;
    }
    
    
    uint8_t tm1637_read()
    {
      uint8_t b = 0;
      uint8_t mask = 0x80;
    
      DIRA &= ~dmask;
    
      for (uint8_t i = 0; i < 8; i++) {
        DIRA &= ~cmask;
        // 5us delay
        if (INA & dmask)
          b |= mask;
        mask >>= 1;
        DIRA |= cmask;
        // 5us delay
      }
    
      DIRA |= dmask;
      // 5us delay
      DIRA &= ~cmask;
      // 5us delay
      DIRA |= cmask;
    }
    
    
    void tm1637_stop()
    {
      DIRA |= cmask;
      DIRA |= dmask;
      // 5us delay
      DIRA &= ~cmask;
      // 5us delay
      DIRA &= ~dmask;
    }
    
    
    // -------------------------------------------------------------------------------------------------
    
    void main()
    {
      while (1) {
        // do something
      }
    }
    
  • maccamacca Posts: 236
    edited 2019-12-18 - 07:31:15
    JonnyMac wrote: »
    Why? Why is PropGCC giving my functions an implicit type when I am EXPLICITLY declaring them as void or uint8_t?

    The two warning blocks seems the same to me (wrong copy/paste ?), anyway, C see declarations from top to down in the source, whenever you call a function that is defined after it assumes a standard declaration, then it throws a warning if the actual definition is different.
    In your code, tm1637_begin and tm1637_end are not present (this will give you an error in the linker phase), tm1637_write is used in the fill function but defined later after the start function.

    If you uncomment the function declarations at top, you should be fine (well, after adding a semicolon after the fill prototype).
    Or reorder the functions so they call only functions defined before them, if possible.
  • VonSzarvasVonSzarvas Posts: 1,869
    edited 2019-12-18 - 08:13:05
    JonnyMac wrote: »
    I thought it would be a fun diversion to port my TM1637 driver to C -- I am now regretting that, but angry enough not to quit.

    :) :) :) Sharing the pain with a wry smile!




    To fix up the compile errors, try replacing your currently commented out block of function declarations with this code:
    uint8_t  tm1637_setup(uint8_t cpin, uint8_t dpin, uint8_t ncols);
    void     tm1637_clear();
    void     tm1637_fill(uint8_t segments);
    void     tm1637_set_segments(uint8_t col, uint8_t segments);
    void     tm1637_start();
    uint8_t  tm1637_write(uint8_t b) ;
    uint8_t  tm1637_read();
    void     tm1637_stop();
    uint8_t  tm1637_send_command(uint8_t cmd);
    void     tm1637_end();
    void     tm1637_begin();
    
    void tm1637_end() { }
    void tm1637_begin() { }
    


    You were missing a couple functions, and also the _fill declaration was missing a semicolon at the end of the line.


    One other thing... Do those if/else constructs require curly braces ?
    Oh- and also the For loops ? I'm not sure about that.



  • VonSzarvasVonSzarvas Posts: 1,869
    edited 2019-12-18 - 08:11:12
    Update... OK, I couldn't resist trying, which leads me to a question about the curly braces...

    These code snippets seem to compile OK from Jon's example in SimpleIDE.... at least there's no reported errors.
    if ((ncols >= 2) && (ncols <= 6))                             // set display size
        size = ncols;
      else 
        size = 4;
    

    and
    for (uint8_t i = 0; i < 6; i++)
         tm1637_write(segments);
    


    However, are curly braces required to ensure the code operates as expected ? What are the rules about that ?
    It looks like "braces not required when code follows on 1 line only".... Is that a correct assumption ?
    They look great for Spin (indented) though :)
  • if/else/for/while and friends only affect the next statement that follows. What the curly braces actually do here is group multiple statements together as a "compound statement". You can also use curly braces on their own when you want to create a new local variable scope.
  • Wuerfel_21 wrote: »
    if/else/for/while and friends only affect the next statement that follows. What the curly braces actually do here is group multiple statements together as a "compound statement". You can also use curly braces on their own when you want to create a new local variable scope.

    That makes it very clear; Thanks @Wuerfel_21
  • VonSzarvas wrote: »
    Oh- and also the For loops ? I'm not sure about that.
    You need to set "Other Compiler Options" to:
    -std=c99
    
    when declaring the i variable in statements like:
    for (uint8_t i = 0; i < 6; i++)
    

    dgately

  • JonnyMacJonnyMac Posts: 6,574
    edited 2019-12-18 - 17:46:07
    This has been my frustration with C for the Propeller since the beginning: it seems like it has to be crow-barred to make it work. I find this frustrating given the success of C on other platforms.

    My syntax is correct. I'm not a master of C, but I know it well enough to get syntax right (and I keep a few books handy to double-check when I have questions).
    The compiler setting (-std=C99) was already in place.

    I apologize... I may have caused bit of confusion by renaming a couple functions after posting the original warnings. These are the warnings with the code above (function prototypes commented out).
    Project Directory: C:/Users/jmcph/Documents/SimpleIDE/My Projects/

    SimpleIDE Version 1.1.2
    C:/Users/jmcph/Documents/SimpleIDE/Learn/Simple Libraries/
    C:/Users/jmcph/Documents/SimpleIDE/ Updated on: 2019-10-22

    propeller-elf-gcc.exe -v GCC 4.6.1 (propellergcc_v1_0_0_2408)
    propeller-elf-gcc.exe -I . -L . -o lmm/TM1637_Demo.elf -Os -mlmm -m32bit-doubles -fno-exceptions -std=c99 TM1637_Demo.c -lm
    TM1637_Demo.c: In function 'tm1637_setup':
    TM1637_Demo.c:59:3: warning: implicit declaration of function 'tm1637_send_command' [-Wimplicit-function-declaration]
    TM1637_Demo.c: In function 'tm1637_clear':
    TM1637_Demo.c:65:3: warning: implicit declaration of function 'tm1637_fill' [-Wimplicit-function-declaration]
    TM1637_Demo.c: At top level:
    TM1637_Demo.c:69:6: warning: conflicting types for 'tm1637_fill' [enabled by default]
    TM1637_Demo.c:65:3: note: previous implicit declaration of 'tm1637_fill' was here
    TM1637_Demo.c: In function 'tm1637_fill':
    TM1637_Demo.c:74:3: warning: implicit declaration of function 'tm1637_begin' [-Wimplicit-function-declaration]
    TM1637_Demo.c:75:3: warning: implicit declaration of function 'tm1637_write' [-Wimplicit-function-declaration]
    TM1637_Demo.c:78:3: warning: implicit declaration of function 'tm1637_end' [-Wimplicit-function-declaration]
    TM1637_Demo.c: In function 'tm1637_set_segments':
    TM1637_Demo.c:89:3: warning: implicit declaration of function 'tm1637_start' [-Wimplicit-function-declaration]
    TM1637_Demo.c: At top level:
    TM1637_Demo.c:96:9: error: conflicting types for 'tm1637_send_command'
    TM1637_Demo.c:59:10: note: previous implicit declaration of 'tm1637_send_command' was here
    TM1637_Demo.c: In function 'tm1637_send_command':
    TM1637_Demo.c:100:3: warning: implicit declaration of function 'tm1637_stop' [-Wimplicit-function-declaration]
    TM1637_Demo.c: At top level:
    TM1637_Demo.c:106:6: warning: conflicting types for 'tm1637_start' [enabled by default]
    TM1637_Demo.c:89:3: note: previous implicit declaration of 'tm1637_start' was here
    TM1637_Demo.c:117:9: error: conflicting types for 'tm1637_write'
    TM1637_Demo.c:75:3: note: previous implicit declaration of 'tm1637_write' was here
    TM1637_Demo.c:167:6: warning: conflicting types for 'tm1637_stop' [enabled by default]
    TM1637_Demo.c:100:3: note: previous implicit declaration of 'tm1637_stop' was here
    Done. Build Failed!

    These are the warnings when I remove the comment block from the function prototypes.
    Project Directory: C:/Users/jmcph/Documents/SimpleIDE/My Projects/

    SimpleIDE Version 1.1.2
    C:/Users/jmcph/Documents/SimpleIDE/Learn/Simple Libraries/
    C:/Users/jmcph/Documents/SimpleIDE/ Updated on: 2019-10-22

    propeller-elf-gcc.exe -v GCC 4.6.1 (propellergcc_v1_0_0_2408)
    propeller-elf-gcc.exe -I . -L . -o lmm/TM1637_Demo.elf -Os -mlmm -m32bit-doubles -fno-exceptions -std=c99 TM1637_Demo.c -lm
    TM1637_Demo.c: In function 'tm1637_fill':
    TM1637_Demo.c:45:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
    TM1637_Demo.c:64:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
    TM1637_Demo.c:70:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
    TM1637_Demo.c:83:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
    TM1637_Demo.c:97:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
    TM1637_Demo.c:107:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
    TM1637_Demo.c:118:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
    TM1637_Demo.c:143:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
    TM1637_Demo.c:168:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
    TM1637_Demo.c:181:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
    TM1637_Demo.c:35:10: error: old-style parameter declarations in prototyped function definition
    TM1637_Demo.c:185:1: error: expected '{' at end of input
    Done. Build Failed!
  • The forward-declaration of tm1637_fill is missing the semicolon
  • The reason the error messages in old GCC are so bad is partially because the parser is being held together by duct tape and partially because it is easy to accidentially invoke obscure GCC extensions (did you know you can create a function inside another function?). So when it encounters a syntax error, it gets in a bad state and just keeps trying to interpret everything that comes after in the wrong context until the file is over, burying the actual location of the problem beneath a million lines of nonsense. As such, one always has to look at the first error in a file.

    This is a lot better in recent GCC versions (due to GCC's monopoly on being a decent C/C++ compiler being disturbed by clang/LLVM), but alas, no one maintained the Prop version.
  • Thank you, thank helped quite a lot. Still having issues ("conflicting types") that I don't understand.
    SimpleIDE Version 1.1.2
    C:/Users/jmcph/Documents/SimpleIDE/Learn/Simple Libraries/
    C:/Users/jmcph/Documents/SimpleIDE/ Updated on: 2019-10-22

    propeller-elf-gcc.exe -v GCC 4.6.1 (propellergcc_v1_0_0_2408)
    propeller-elf-gcc.exe -I . -L . -o lmm/TM1637_Demo.elf -Os -mlmm -m32bit-doubles -fno-exceptions -std=c99 TM1637_Demo.c -lm
    TM1637_Demo.c: In function 'tm1637_setup':
    TM1637_Demo.c:59:3: warning: implicit declaration of function 'tm1637_send_command' [-Wimplicit-function-declaration]
    TM1637_Demo.c: In function 'tm1637_fill':
    TM1637_Demo.c:74:3: warning: implicit declaration of function 'tm1637_begin' [-Wimplicit-function-declaration]
    TM1637_Demo.c:78:3: warning: implicit declaration of function 'tm1637_end' [-Wimplicit-function-declaration]
    TM1637_Demo.c: At top level:
    TM1637_Demo.c:96:9: error: conflicting types for 'tm1637_send_command'
    TM1637_Demo.c:59:10: note: previous implicit declaration of 'tm1637_send_command' was here
    Done. Build Failed!
  • You're not declaring tm1637_send_command before you're using it, so the compiler implicitly declares it with a signature of "int tm1637_send_command(int)" and then falls on its face when you later define it as "uint8_t tm1637_send_command(uint8_t)"
  • This kind of problem goes away when you actually declare all the non-static functions in a *.c file in a corresponding *.h file, as is usually done.
  • JonnyMacJonnyMac Posts: 6,574
    edited 2019-12-18 - 18:58:10
    Thank you. That function was added when I had the function prototypes commented out. With that correction the error messages began to make sense and I was able to touch-up the last few gotchas (self induced by renaming a couple of the functions).

    It compiles now.
  • Wuerfel_21 wrote: »
    This kind of problem goes away when you actually declare all the non-static functions in a *.c file in a corresponding *.h file, as is usually done.

    I understand. I am -- at the moment -- simply translating my Spin library code to C. Once everything is working I will move the move things to the .h and .c files as one would expect with a proper library.
  • Good news: I am able to control the display with C! I will no finish porting the library code and converting it to a proper C library. Then I'll port my Spin demo.

    To those, especially @Wuerfel_21, who assisted, thank you.
  • JonnyMac wrote: »
    Wuerfel_21 wrote: »
    This kind of problem goes away when you actually declare all the non-static functions in a *.c file in a corresponding *.h file, as is usually done.

    I understand. I am -- at the moment -- simply translating my Spin library code to C. Once everything is working I will move the move things to the .h and .c files as one would expect with a proper library.

    A lot of the translation from Spin to C can be automated via spin2cpp, if you'd like to save time.
  • A lot of the translation from Spin to C can be automated via spin2cpp, if you'd like to save time.

    I could, but it would deny me the opportunity to learn as I go. For me this is about learning, not about saving time.
  • JonnyMac,

    I have several text files where I keep notes about language conversions so I don't have to keep relearning what to do.

    I don't know what system you use but it's a good idea to keep notes on what to do or what to be careful of.

    As for style, I prefer to indent braces under the function or statement that they go with.
Sign In or Register to comment.