Macro: HANDLE$MESSAGE$2

Module location: FMAC line 11827 (view source)

  #IFDEF UI.EXISTS
  #ELSE
    USE UI
  #ENDIF

  // if the publish meta-attribute is set, we want to generate the RegisterInterface command before we do anything in this new method.
  // we will also check as many things as possible to make sure this is a valid place for this. We expect this:
  // 1. to appear in classes and not objects
  // 2. cannot be global, FOR, or desktop
  // 3. cannnot be override

  // If the meta attribute Published is true, we handle special case for webapps.
  // note I am not checking for the Mangle_names ifdef - I just assume it's true (hasn't been unset for many versions).
  #IFMATTR Published true  // This is true if the Published attribute is active and its value is true
    // method must be an object method and not For, global or overloaded
    #IFSAME !3 GLOBAL FOR OVERLOADED // any of these are not allowed. Note that DESKTOP is already converted to For cDesktop at this point
      #ERROR DFERR_COMP_ILLEGAL_CODE_PLACEMENT "The Publish meta tag cannot be used with GLOBAL, DESKTOP, FOR, or OVERLOADED methods."
    #ELSE
      #IF (!b = 1)   // the only valid place for this is within a method within an object.
        MESSAGE$ADDRESS !1_!2  // create id symbol for this message. We do this to avoid fowward reference error in registerInterface
        #SPUSH
        #PUBLISH  //  This creates the Send RegisterInterface line and puts the result in !$, based on the original source line which is expected to be something like Function Foo Integer iArg...
        !$        //  This would then actually call Send RegisterInterface
        #REM !$
        #SPOP
       #ELSE
         #ERROR DFERR_COMP_ILLEGAL_CODE_PLACEMENT "The Publish meta tag can only be used within methods defined directly inside of objects."
      #ENDIF
    #ENDIF
  #ENDIF



  // procedure construct_object only allowed in class
  #IF (!b & 1) // if in object
    #IFDEF MANGLE_NAMES
      #IFSAME !1 MSG
        #IFSAME !2 CONSTRUCT_OBJECT
          #ERROR DFERR_COMP_ILLEGAL_CODE_PLACEMENT Construct_object .not. allowed in objects
        #ENDIF
      #ENDIF
    #ELSE
      #IFSAME !1 MSG_CONSTRUCT_OBJECT
        #ERROR DFERR_COMP_ILLEGAL_CODE_PLACEMENT Construct_object .not. allowed in objects
      #ENDIF
    #ENDIF
  #ENDIF

  // not allowed to nest methods
  // Check flag to determine whether we are already in a method.
  #IF (!b & 4)
    #ERROR DFERR_COMP_ILLEGAL_CODE_PLACEMENT Procedures and Functions may .not. be nested.
  #ELSE
    // non global methods are not allowed class child-objects

    #IFNDEF MANGLE_NAMES

      #IFSAME !2 GLOBAL
      #ELSE
        #IF ((!b & 3)=3) // if in class object
          #ERROR DFERR_COMP_ILLEGAL_CODE_PLACEMENT Methods .not. allowed in class child-objects
        #ENDIF
      #ENDIF

    #ELSE

      #IFSAME !3 GLOBAL
      #ELSE
        #IF ((!b & 3)=3) // if in class object
          #ERROR DFERR_COMP_ILLEGAL_CODE_PLACEMENT Methods .not. allowed in class child-objects
        #ENDIF
      #ENDIF

    #ENDIF
  #ENDIF

  // Give error if the stack symbol NUM_ARGUMENTS is defined.
  #CHECK NUM_ARGUMENTS _T

  //
  #SET ZN$ !n     // static nesting level
  #SET ZM$ 0      // # objects in method
  #PUSH !Zg
  #PUSH !Za
  #SET ZA$ !a
  #PUSH !Zu
  #DATA
  #STKSYM                      // forget all old stack symbols
  #SET B$ (!b | 4)             // set flag to in_procedure

  // This was changed to allow us to prohibit arguments with num_arguments inside the scope of a function.
  #REPLACE NUM_ARGUMENTS |SI0  // define the arg count

  #IFDEF MANGLE_NAMES
    #SREP __@INSIDE_FUNCTION@__   |CI1   // lets other commands check that they are inside a function scope.
  #ENDIF

  #IFNDEF MANGLE_NAMES


  #ELSE

  //  This is the mangling code.

    #IFSAME !3 GLOBAL
      #DPUSH |CI0         // No message
      #DPUSH |CI0         // for no class
      // Check if overloaded symbol is already defined.
      #IFSAME OVERLOADED !4 !5 !6 !7 !8 !9
        #ERROR DFERR_COMP_ILLEGAL_METHOD_DEFINTION Global functions/procedures cannot be overloaded
      #ELSE
        #IFDEF !1_!2_OVERLOADED
          #ERROR DFERR_COMP_ILLEGAL_METHOD_DEFINTION This Method Was Previously Defined As Overloaded
        #ELSE
          #IFDEF !1_!2
            #ERROR DFERR_COMP_ILLEGAL_METHOD_DEFINTION Global method !1 !2 Already Defined
          #ELSE
            #SET ZG$ (0-!a-2)   // make it negative to distuinguish it
            #REPLACE !1_!2 |CI!Zg
          #ENDIF
        #ENDIF
      #ENDIF
      CHECK$METHOD$ARGUMENT$LIST !4 !5 !6 !7 !8 !9
      #IF (!0>1)          // do we have arguments?
        #SET ZG$ 1        // starting argument number
        DEFINE_ARGUMENTS !4 !5 !6 !7 !8 !9
      #ENDIF

      HANDLE$MESSAGE$HELP !1 !1_!2 !3 !4 !5 !6 !7 !8 !9

    #ELSE  // not global functions

      // make sure message is not already defined as a global
      #IFDEF !1_!2
        #IF (!1_!2<0)  // if defined as a global already, we have an error
          #ERROR DFERR_COMP_ILLEGAL_METHOD_DEFINTION !1 !2 already defined as a Global method
        #ENDIF
      #ENDIF

      // Mangling case & Using FOR
      #IFSAME !3 FOR          // are we explicit about the class?

        #IFSAME OVERLOADED !5 !6 !7 !8 !9
          #IFDEF !1_!2
            #ERROR DFERR_COMP_ILLEGAL_METHOD_DEFINTION This Method Was Previously Defined As non-overloaded
          #ELSE
            // we don't support Byref with overloading
            #IFSAME BYREF !5 !6 !7 !8 !9
              #ERROR DFERR_COMP_ILLEGAL_METHOD_DEFINTION "BYREF not allowed in overloaded methods"
            #ENDIF
            // Mangle name of method.
            #MARG !1_!2 !5 !6 !7 !8 !9
            // Also lock name without parameters and sugar.
            #IFNDEF !1_!2_OVERLOADED
              #REPLACE !1_!2_OVERLOADED  |CI1
            #ENDIF
            MESSAGE$ADDRESS !?         // create id symbol for this message
            #DPUSH !?
          #ENDIF
        #ELSE   // FOR class, but not an overloaded function.

          #IFDEF !1_!2_OVERLOADED
            #ERROR DFERR_COMP_ILLEGAL_METHOD_DEFINTION This Method Was Previously Defined As Overloaded
          #ELSE
            MESSAGE$ADDRESS  !1_!2  // create id symbol for this message
            #DPUSH !1_!2
          #ENDIF

        #ENDIF

        #IFDEF !4
          #IFSAME !4 DESKTOP
            #IFDEF IS$WINDOWS
              #DPUSH U_cObject  // Message for the desktop class
            #ELSE
              #DPUSH U_DESKTOP  // Message for the desktop class
            #ENDIF
          #ELSE
            #DPUSH !4         // Message for the named class
          #ENDIF
        #ELSE
          #CHECK U_!4 _RSDNU   // Check the class to see if it exists.
          #DPUSH U_!4         // Message for the named class
        #ENDIF

        CHECK$METHOD$ARGUMENT$LIST !5 !6 !7 !8 !9

        #IF (!0>3)
          #SET ZG$ 1                  // starting argument number
          DEFINE_ARGUMENTS !5 !6 !7 !8 !9
        #ENDIF

        #IFSAME OVERLOADED !4 !5 !6 !7 !8 !9              // Non global
          HANDLE$MESSAGE$HELP !1 !? !5 !6 !7 !8 !9
        #ELSE
          HANDLE$MESSAGE$HELP !1 !1_!2 !5 !6 !7 !8 !9
        #ENDIF

      #ELSE // Method is declared in a class or in an object
        #IF (!b & 2)              // obj_flag == in_class?
        #ELSE
          #IF (!b & 1)            // in_object, instance method
            !A [] CLONE$CLASS     // if in object, clone the class
          #ENDIF
        #ENDIF

        #IFSAME OVERLOADED !3 !4 !5 !6 !7 !8 !9
          #IFDEF !1_!2
            #ERROR DFERR_COMP_ILLEGAL_METHOD_DEFINTION This Method Was Previously Defined As non-overloaded
          #ELSE
            // we don't support Byref with overloading
            #IFSAME BYREF !3 !4 !5 !6 !7 !8 !9
              #ERROR DFERR_COMP_ILLEGAL_METHOD_DEFINTION "BYREF not allowed in overloaded methods"
            #ENDIF
            #MARG !1_!2 !3 !4 !5 !6 !7 !8 !9
            MESSAGE$ADDRESS !?
            #IFNDEF !1_!2_OVERLOADED
              #REPLACE !1_!2_OVERLOADED  |CI1
            #ENDIF
            #DPUSH !?               // the message
          #ENDIF
        #ELSE
          // a non-overlaoded message
          #IFDEF !1_!2_OVERLOADED
            #ERROR DFERR_COMP_ILLEGAL_METHOD_DEFINTION This Method Was Previously Defined As Overloaded
          #ELSE
            MESSAGE$ADDRESS  !1_!2  // create id symbol for this message
            #DPUSH !1_!2
          #ENDIF
        #ENDIF

        // push the proper destination for the message
        #IF (!b & 2)             // obj_flag == in_class?
          #DPUSH U_!$            // handle msg for "current class"
        #ELSE
          #IF (!b & 1)           // in_object, instance method
            #DPUSH |CI0          // handle for objects class
          #ELSE                  // Message is out on desktop and not identfied w/ FOR Xxxxx
            #IFDEF IS$WINDOWS      // 8.3: if windows we are going to place this on the cDesktop object
                                   // which will allow all objects to delegate to it, which is probably
                                   // what people expect. Prior to 8.3, it create a "for desktop" so all classes/objects
                                   // immediately understood this. This represents a change in behavior.
              #REM Ambiguous methods on .DESKTOP. are .not. recommended (Obsolete technique)
              // this is not a real error but we can use this to look at ambiguous desktop methods to make make sure
              // that they are being used in the proper 8.3 style. This warning is controlled by the method
              // Compiler_desktop_method_warnings ON|OFF (OFF is default)
              #IF (!Zl & 4)
                 #ERROR DFERR_COMP_ILLEGAL_METHOD_DEFINTION Ambiguous method on .Desktop. Should be "Desktop" or "Global" or moved.
              #ENDIF
              #DPUSH U_cObject     // Message for the desktop (UI_OBJECT) class. Not advised for VDF after 8.2
            #ELSE
              #DPUSH U_DESKTOP     // Message for the desktop (UI_OBJECT) class. Not advised for VDF after 8.2
            #ENDIF
          #ENDIF   // stand alone message that gets defined as U_DESKTOP
        #ENDIF     // end of else of object method
        CHECK$METHOD$ARGUMENT$LIST !3 !4 !5 !6 !7 !8 !9
        #IF (!0>1)                // do we have arguments?
          #SET ZG$ 1                  // starting argument number
          DEFINE_ARGUMENTS !3 !4 !5 !6 !7 !8 !9
        #ENDIF

        #IFSAME OVERLOADED !3 !4 !5 !6 !7 !8 !9
          HANDLE$MESSAGE$HELP !1 !? !3 !4 !5 !6 !7 !8 !9
        #ELSE
          HANDLE$MESSAGE$HELP !1 !1_!2 !3 !4 !5 !6 !7 !8 !9
        #ENDIF

      #ENDIF       // class method
    #ENDIF
  #ENDIF  // mangling case

//  !A [] HANDLE$FOR |CI0 |VL     // handle the message
  !A [] $0454 |CI0 |VL
  #FREF OBJ$!Za$ENDPROC !a      // fref the end procedure line

  #IFDEF MANGLE_NAMES
    // MG added code here to check the parameter count.
    #IFDEF !1_!2_OVERLOADED
       // Check parameter count
      #DATA
      #DPUSH NUM_ARGUMENTS
      #DPUSH |CI!Zg
      #DPUSH !?

      #IFSAME !1 GET
        #DPUSH |CI1
      #ELSE
        #IFSAME !1 MSG
          #DPUSH |CI2
        #ELSE
          #IFSAME !1 SET
            #DPUSH |CI3
          #ENDIF
        #ENDIF
      #ENDIF
      !A [] $0467 |CI0 |VL
      #FORBID  NUM_ARGUMENTS  300 "NUM_ARGUMENTS was used in an overloaded method"
    #ENDIF
  #ENDIF
  #SET ZG$ 0                    // starting argument number for locals

  // JJT - changed in 9.1. This used to occur when the first local was created. Since this is executed at runtime
  // this created a situation where the first local might be in a block that is not executed. When moved to here
  // the local init command is always executed. We still strongly discourage the declartion of variables anywhere
  // accept the top of a method block. This simply fixes and unintended side-effect of our implementation.
  //!A [] LOCAL$ARGUMENT |CI0  // Create the command to save the local count,
  !A [] $0456 |CI0
  #FREF OBJ$!Za$LNUM !a       // and tell flex to update it later.