This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Function too complex

I have a function,but the compiler terminated because the function is too complex.

C51 FATAL-ERROR -
  ACTION:  GENERATING INTERMEDIATE CODE
  ERROR:   FUNCTION '_siParseDescriptor' (LINE 1058, T=400,L=132,l=1): TOO COMPLEX
C51 TERMINATED.

  • Mike,

    Can you post the offending function?

    Stefan

  • "Can you post the offending function?"

    Is that going to be practical, given that it's so complicated that it breaks the compiler!!??

  • Make sure you have matched braces, parnthesis, and semicolons !

  • ......
    CreateSatelliteDeliverySystemDescriptor (Descriptor,
                BcdCharToInt (sds->frequency1) * 10L * 1000 * 1000 +
                BcdCharToInt (sds->frequency2) * 100L * 1000 +
                BcdCharToInt (sds->frequency3) * 1000L +
                BcdCharToInt (sds->frequency4) * 10,
                (sds->west_east_flag ? 1 : -1) *
                (BcdCharToInt (sds->orbital_position1) * 100 +
                BcdCharToInt (sds->orbital_position2)),
                sds->modulation,
                sds->polarization,
                BcdCharToInt (sds->symbol_rate1) * 10L * 1000 +
                BcdCharToInt (sds->symbol_rate2) * 100L +
                BcdCharToInt (sds->symbol_rate3),
                sds->fec_inner);
    ......
    
    CreateSatelliteDeliverySystemDescriptor is a macro defined as follow:
    struct SatelliteDeliverySystemDescriptor {
       struct NODE          Node;
       uint16_t             Tag;
       long                 Frequency;
       short                OrbitalPosition;
       short                Modulation;
       char                 Polarization;
       long                 SymbolRate;
       char                 FEC;
    };
    
    #define CreateSatelliteDeliverySystemDescriptor(descr, freq, orb, mod, polar, sr, fec)    do    {       xCreateNode (((struct SatelliteDeliverySystemDescriptor *)descr), NULL);       ((struct SatelliteDeliverySystemDescriptor *)descr)->Tag = DESCR_SAT_DEL_SYS;       ((struct SatelliteDeliverySystemDescriptor *)descr)->Frequency = freq;       ((struct SatelliteDeliverySystemDescriptor *)descr)->OrbitalPosition = orb;       ((struct SatelliteDeliverySystemDescriptor *)descr)->Modulation = mod;       ((struct SatelliteDeliverySystemDescriptor *)descr)->Polarization = polar;       ((struct SatelliteDeliverySystemDescriptor *)descr)->SymbolRate = sr;       ((struct SatelliteDeliverySystemDescriptor *)descr)->FEC = fec;    } while (0)
    
    and BcdCharToInt is also a macro defined as follow:
    #define BcdCharToInt(x) (10*((x & 0xF0)>>4) + (x & 0xF))
    
    xCreateNode is a function which create a node of link.
    The above code result compiler fatal error:Function too complex.But after I make a bit ot change to the above code,this fatal error disappear:
    ......
    long freq =   BcdCharToInt (sds->frequency1) * 10L * 1000 * 1000 +
                BcdCharToInt (sds->frequency2) * 100L * 1000 +
                BcdCharToInt (sds->frequency3) * 1000L +
                BcdCharToInt (sds->frequency4) * 10;
    long srate = BcdCharToInt (sds->symbol_rate1) * 10L * 1000 +
                BcdCharToInt (sds->symbol_rate2) * 100L +
                BcdCharToInt (sds->symbol_rate3);
    
    CreateSatelliteDeliverySystemDescriptor (Descriptor,
                freq,
                (sds->west_east_flag ? 1 : -1) *
                (BcdCharToInt (sds->orbital_position1) * 100 +
                BcdCharToInt (sds->orbital_position2)),
                sds->modulation,
                sds->polarization,
                srate,
                sds->fec_inner);
    ......
    
    or just delete the reverse second parameter's constant suffix(expression's result is truncated according to ANSI C specification,which results bug):
    CreateSatelliteDeliverySystemDescriptor (Descriptor,
                BcdCharToInt (sds->frequency1) * 10L * 1000 * 1000 +
                BcdCharToInt (sds->frequency2) * 100L * 1000 +
                BcdCharToInt (sds->frequency3) * 1000L +
                BcdCharToInt (sds->frequency4) * 10,
                (sds->west_east_flag ? 1 : -1) *
                (BcdCharToInt (sds->orbital_position1) * 100 +
                BcdCharToInt (sds->orbital_position2)),
                sds->modulation,
                sds->polarization,
                BcdCharToInt (sds->symbol_rate1) * 10 * 1000 +
                BcdCharToInt (sds->symbol_rate2) * 100 +
                BcdCharToInt (sds->symbol_rate3),
                sds->fec_inner);
    
    The above source code is just a piece of code in function siParseDescriptor.C51 User's Guide 09 2001,P190,interprets as follow:

    GENERATING INTERMEDIATE CODE
    The source file contains a function that is too large to be translated into
    pseudo-code by the compiler. Try breaking the function into smaller
    functions and re-compiling.

    But it doesn't seem to apply to the above code.

  • Maybe the macro expansion is going wrong due to insufficient or misplaced parentheses? If the preprocessor output file is generated before you get the error you might be able to spot what's going wrong, but I doubt it - it'll probably be incomprehensible.

    Do you have to use macros? Much less confusing to use functions.

    Stefan

  • That code has just about broken the forum never mind the compiler. Took me ages to find the post button.

    Stefan

  • For starters, I think you should get rid of all those casts. They're either superfluous
    or dangerous, but they're quite certainly not going to help you with anything.

    I second the suggestion that you really should turn this initializer macro into a function.

    All those BcdCharToInt() results multiplied with powers of ten strongly suggest
    you're doing yourself a disfavour in that area, too. You need a Bcd4CharsToInt(),
    and it should be function, not a macro.

    Putting it all together, you're abusing macros, to the point of overstressing the compiler.

    [Error message...]
    But it doesn't seem to apply to the above code.

    What ever made you think it didn't? Get yourself a preprocessor listing for
    this source file, open it in an editor window, look at it, and then say that again...

  • Take a look at Andy's Handy Hint for Debugging Preprocessor Problems:
    http://www.8052.com/forum/read.phtml?id=29152

    Note that the preprocessor listing is itself a 'C' source file - so you can get the compiler to compile it. This might pinpoint the error a bit more closely?

  • I suspect the problem is just the complexity of that huge, huge, expression. When you introduce the intermediate variables, you simply the amount of code in one chunk, which I imagine is why the code starts to compile.

    What's the purpose of the "do {} while(0)" in your create macro? Simple curly braces should work as well to introduce a local block.

    Also, just as a readability and style nitpick, complicated macros are probably better defined using the backslash to allow them to occupy multiple lines.

    #define CreateSatelliteDeliverySystemDescriptor(descr, freq, orb, mod, polar, sr, fec)     {                                                                                      xCreateNode (((struct SatelliteDeliverySystemDescriptor *)descr), NULL);                                      ((struct SatelliteDeliverySystemDescriptor *)descr)->Tag = DESCR_SAT_DEL_SYS;                   ((struct SatelliteDeliverySystemDescriptor *)descr)->Frequency = freq;                          ((struct SatelliteDeliverySystemDescriptor *)descr)->OrbitalPosition = orb;                     ((struct SatelliteDeliverySystemDescriptor *)descr)->Modulation = mod;                          ((struct SatelliteDeliverySystemDescriptor *)descr)->Polarization = polar;                      ((struct SatelliteDeliverySystemDescriptor *)descr)->SymbolRate = sr;                           ((struct SatelliteDeliverySystemDescriptor *)descr)->FEC = fec;                                 }
    

    Get rid of the cast (or at least typedef a shorter name) and it'd be readable.

    I'd recommend against the casts in this case for safety reasons, too. Macros can't type-check their arguments, unlike functions. With the casts in place, if someone passes in a descr that's not really a SDSDesc*, the casts will just hammer away the type mismatch warning, and you'll have an ugly problem to debug. Without the casts, the compiler will generate a warning on the attempted dereference of the pointer. If a cast is necessary, let the caller supply it rather than the macro.

  • too comples to compile
    how about "too complex to rtead"

    Why does "real C" programmers insist on cramming more than a human can understand into a single statement.

    As far as I can see this can easiy be broken up in 4-10 understandable statements.

    Is there really a reason to make it as tough as posssible on the next guy/gal assigned maintenance of the code?

    Erik

  • "What's the purpose of the "do {} while(0)" in your create macro?
    Simple curly braces should work as well to introduce a local block."


    Not quite. Consider the use of a function-like macro (i.e., terminated with a semicolon)
    in an if/else clause expanding to the curly brace from only. Please refer to:

    http://www.eskimo.com/~scs/C-faq/q10.4.html

    The do/while(0) method is the safe way to define a function-like (multi-statement) macro.