No announcement yet.

'Procedures': How best to ... ?

  • Filter
  • Time
  • Show
Clear All
new posts

  • 'Procedures': How best to ... ?

    I am developing several 'Procedures', (not subroutines or functions),
    which I would like to call from several different totally unrelated
    main programs. Can someone please tell me how is the best way to
    accomplish this?

    My original plan was to develop these procedures, and then cut-and-
    paste them into the calling programs. Then, 1) I found that I cannot
    cut-and-paste between programs for some reason; but, more importantly,
    after thinking about it, it would be nicer to be able to maintain and
    extend these procedures in only one place, rather than in each of the
    individual calling programs.

    I have read a little about creating 'units', but don't know if this is
    the best approach.

    BTW, I am using 3.5.
    In all cases the main programs will only send data to these procedures.

    Thank you very much for any guidance,

  • #2
    David, it sounds for all the world like you are developing your
    own libraries. If this is the case, your best bet would be, indeed,
    be to compile your "procedures" into units and then link them to
    the main program.

    You can also leave them as text source then "$Include" them as

    BTW: You can cut-n-paste with PB/DOS in a manner of speaking.
    Use Ctrl K-B and Ctrl K-K to highlight the code then use Ctrl K-W
    to write the code to a disk file. In the other program(s), use
    Ctrl K-R to read the file into the program you are working on.
    Works for me!!

    Hope this helps

    There are no atheists in a fox hole or the morning of a math test.
    If my flag offends you, I'll help you pack.


    • #3
      My personal preference is to create common units of ranking levels.
      Then combine several units in a PB Library of them which is called
      forth in each program. By 'ranking levels' I mean the the lowest
      level unit contains the most common SUBS that will be needed and can
      be CALLED from any code which then becomes an executable.

      Right or wrong, the lowest level of these units can also be CALLED
      by other units. Thus they are NESTED such CALLS. But the executables
      only contain the minimum common code that is ever needed.

      That also starts one down the road toward decisions on what to name
      one's variables! It focuses one on what can become common named of
      common type variable data that is needed from any higher level code
      that reaches into these lower level common level SUBS, built into
      UNITS and thence into LIBS of them.

      For example, my lowest level common code contains generic video and
      keyboard I/O operations, for example, for everything else I write.
      You might think it crazy to think about what to use for a 'common
      name' for the coordinates for screen horizontal and vertical position.
      But a million and a quarter lines of PB source later I'm darned glad
      I settled on GX% for all vertical line number coordinates and GY%
      for all horizontal column number coordinates for all my work.

      Yes, virtually every line of my code is commented! But you can only
      go so far in that. And MOST IMPORTANT is this. Every comment line
      and word your write into your source code may be excluded as to the
      number of characters you use up of the 64K generic code space that PB
      will allow you. But that is *NOT* true of the bytes required for a
      variable name. Sure I could have used, "Cursor_screen_line%" instead
      of "GX%" for that variable name. It would have been much clearer for
      any subsequent code maintainer to have followed that in my code. But
      let's see just what doing really definitive declaration of variable
      names would have done to just one of my major executables, OK?

      Of the now 114 major code chunks in my suite all done in PB 3.5, there
      are 27 UNITS, of which I think the worst nesting levels hit to three
      'ranks; deep. And if your work covers a very large playing field for
      very complex code action, you'll soon, I think, hit another decision
      point in how to create SUBS which have access to a lot more than just
      the allowable 16 variables that may be used in a PB SUB operation.

      That's been one of the major stumbling blocks I've had to face in
      the use of PB at this point. I want to use non-global variables which
      are not PUBLIC in nature. But there is simply no way to do this as
      I can see this. Take just the action of obtaining a single byte from
      the keyboard, for example. Over ten years of this and considering
      that a single byte from the keyboard has to integrate into all possible
      MENU libraries, as well as being MOUSE related, with timing control,
      hidden functions, even screen related array reporting for direct video
      overlay work for help and block move/hiding; it takes me thirty-two
      calling parameters for every single byte I get from the keyboard in
      the suite!

      Every single byte I read from the keyboard takes, at this point, 333
      discrete lines of code to process properly for suite-wide operations
      needed! And I assure you, chuckle, it is at the very lowest core
      level as a SUB in the floor level UNIT which is combined into the
      lowest best PBL that I can create for use here.

      So what to do about the fact that 32 parameters are needed for every
      single keystroke I need in every program? Why, yes, all of them are
      very carefully thought out as to a meaningful name. I could have used
      things like the PB mouse routines for that portion of the work such ]
      as the name "Button%", "Row%" or "Column%". You bet things should be
      self descriptive. But I can't carry the needed variable names into,
      for example, the SUB for just getting a keystroke, and am going to
      have to make use of the PUBLIC form of passing parameters into each
      time I even get a keystroke. There aren't even close to the needed
      number of allowable parameters that can be privately passed as PB is
      given to us today. So .. sigh .. I might as well bite the bullet. We
      make **ALL* the parameters needed to get a keystroke in the whole
      program suite PUBLIC parameters.

      There are many reading this who would scream bloody expletives at me
      for that .. or for you for doing it. But when a project becomes very
      pervasive and has to be server-server related over a huge embedded
      system box operation, things get out of hand. I am coming close to
      the roughly 2400 allowable variable max in PB's platform in a number
      of my executables at this point, sigh. And there is simply no possible
      way to break the code down to smaller units because the global operations
      issues are simply that huge. Wince.

      And then that leads to the next step in making sure you don't start
      down the mixup of variables that are type different between SUBS or
      FUNCTIONS, but of the same name. So every variable I ever use has to
      have the type designator on it! And every variable that is PUBLIC is
      read into every program or whatever I create as a master INCLUDE pure
      source code chuck common to every program. But wait! There's more!

      So far we've talked about just the commonality in getting a keystroke
      anywhere in the suite. But what about the commonality of getting a
      line of input from anywhere in the suite? Obviously whatever is
      involved in getting a keystroke is a lower level part of getting a
      line of input data. Getting a line of input data for anything in the
      suite has even more common variables which will be needed no matter
      what that line input does! And that 'line input' isn't at all the
      function pre-made for us by PB called LINE INPUT which has no real
      way to handle many of the other needed common level interface
      attributes which have to either be calling parameters or PUBLIC data
      for optimal use in a large suite like my work.

      So .. sigh, the line input SUB for the suite is another one thousand
      four hundred and eight lines (1408) of 'common code' that obviously
      has to be involved in every program I will ever write. And .. using
      the same requirements for 'common variables' that also include handling
      every single byte or intervening mouse stroke with it .. we have only
      SEVENTY (70) absolutely needed calling parameters for just getting
      a single input line of code. After all .. what are the screen width
      allowances for the line, the prompt, the color of the I/O, the filter
      limitations for the data? Surely you get the idea. Nobody could
      ever contemplate over 1700 lines of source code in their programs for
      every time they wanted to find out the name of this or that? And
      you would waste a horrible amount of time handling cut and paste for
      every common task you do. That is what SUBS and FUNCTIONS are all
      about, right?

      Don't forget about error handling and hard line numbers that are
      unique and buried in your nower nested SUBS and so on, though. Not
      if you don't want to do things all over and a lot more work when
      you start usint EXIT FAR to handle them, grin. So that means, since
      we only fave what, about 65,000 possible lines in source code for
      PB, your numbering schema better use the highest level line numbers
      for marker points in the lowest level SUBS and so on! Say, the
      50,000 up line numbers? That's what I did long ago and far away.

      And even 80 available calling parameters for a SUB wouldn't get the job
      done even for the basic level of I/O work in every program here. So,
      sigh, the COMDIMZP.BAS include file which has to be a part of everything
      I write in PB only has three hundred (300) PUBLIC variables in it as
      reported by Paul Sittler's BASTOOLS utility:

      BASTOOLS (v0.0R Mar 25 1991) run 6/1/4 15:39:42. Input File: COMDIMZP.BAS
      Variables cross-referenced to 267 physical line numbers.

      AA%(: 96 100
      AR$(: 130 132
      .. (snipped!)
      sKey: 177 186

      325 Variables cross-referenced to 267 physical line numbers.
      BASTOOLS (v0.0R Mar 25 1991) run 6/1/4 15:39:42.
      Output File: COMDIMZP.VAR
      Elapsed time for run was: 00:00:00

      But, sKey doesn't have a type fixed to it? I didn't create that one,
      grin. But attaching a variable type to each variable name sure has a
      LOT to be said for it when you do an auto-translation for BASIC code
      to source code for C/C++ in an emergency! You get to see exactly what
      to do with each variable in the auto-translation, grin!

      Plus, when I do a similar BASTOOLS run on a major 27,000 line source
      code for, say the PRCHANGE.EXE program which edits the proffesional
      case files in my suite in:

      PRCHANGE EXE 437005 11-16-03 4:55a 27473 Profnl case editor

      Of the 27473 lines of total source in PB 3.5 for that 437K executable
      which is composed of 4795 MAIN module source code lines we see:

      BASTOOLS Version 0.0R dated Mar 25 1991 @ 23:13:21

      Copyright 1988, 1989, 1990, 1991 by Paul M. Sittler. All rights reserved.
      BASTOOLS (v0.0R Mar 25 1991) run 6/1/4 15:52:47.

      Input File: PRCHANGE.BAS
      Reading PRCHANGE.BAS and making Variables crossref table.
      Line #4795
      Writing Variables cross-reference file PRCHANGE.VAR
      Line #913, 502 Items
      BASTOOLS (v0.0R Mar 25 1991) run 6/1/4 15:52:49. Output File: PRCHANGE.VAR
      All done. Elapsed time for run was: 00:00:02

      In the file PRCHANGE.VAR generated we'll see that GX% byte input
      coordinated variable called in the lines of the MAIN module only!

      : 303 477 702 711 722 738 774
      : 778 781 784 787 790 793 799
      : 806 810 813 825 829 832 835
      : 838 841 844 848 855 858 861
      : 1237 1254 1270 1286 1302 1318 1466
      : 1534 1550 1566 1632 1648 1664 1680
      : 1697 1713 1733 1780 1796 1812 1828
      : 1844 1861 1878 2078 2122 2198 2317
      : 2340 2383 2429 2484 2507 2530 2550
      : 2570 2590 2610 2631 2915 2923 2927
      : 2930 2933 2936 2939 2968 2973 2977
      : 3004 3009 3013 3046 3238 3275 3337
      : 3395 3492 3626 3708 3726 3808 3814
      : 3833 3868 3930 3951 3952 3969 3999
      : 4059 4080 4702 4755

      And that doesn't include, obviously, every other PBU in every other
      PBL and even the INCLUDE files that are specific to this executable
      which has the over 27,000 lines of source the PB compiler reports
      when it compiles the code.

      My best suggestion to anyone starting on this UNIT and LIB journey
      is to take a serious look at what you are doing and where you want
      to go on a long journey into the future. Consider carefully just
      how you intend to input keyboard data and present screen data. That
      even goes into MENU work, use of the various screen levels in BASIC
      which will let you pop portions of the screen away in memory and paste
      in other things such as buttons, help blocks, and I/O areas. Either
      take the time to coordinate your own creative work here, including
      the variable names that you will find you need that are really PUBLIC
      and can be chunked into a common INCLUDE file, or purchase one of
      or gain the legitimate free use of some I/O and display operation
      someone else has created to help you. If you use somebody else's
      code for this, consider adopting their variable names to save you
      much time and work.

      Sure Bob and crew gave us LOCATE(row, column). But, in my humble
      opinion, one had better think about where that belongs in code. And
      in my case, though I use the raw function in places, most of the
      time it is in a SUB which is called relavent to other things. Yes,
      the code may be slower this way. But as time goes in a major effort,
      as the years go by working on it common routines made up into UNITS
      and into LIB's with the wonderful tools given you are crucial.

      The life you save may be your own!

      Mike Luther
      [email protected]
      Mike Luther
      [email protected]


      • #4
        I, too am a fan of $INCLUDE.

        THat way you can...

        $COMPILE EXE
        $INCLUDE ""
        The one thing you should do if you want reusable stuff is absolutely positively use no SHARED or EXTERNAL or PUBLIC variables. Create every procedure so that it can either generate the data it needs or the procedure receives that data as a parameter.


        Michael Mattias
        Tal Systems Inc. (retired)
        Racine WI USA
        [email protected]


        • #5
          You guys are great!

          Mel: I have now successfully employed $INCLUDE, but haven't gotten to
          units yet because I am still developing. But I will!

          Mike: Thank you for your most extensive reply and for all the time
          you spent on it. You make some very good points. It is clear to
          me however that your requirements are much more stringent than mine.
          For me, this is more of a 'spare-time hobby', so I can tolerate a
          few undisciplined screw-ups that wouldn't get by in the professional
          world. But I'll bookmark your reply for when I become more prolific!

          Michael: As above, re $INCLUDE and units. I am having trouble however
          trying to follow your direction, "absolutely positively use no SHARED",
          because, by virtue of what they do, all of the procedures must be
          called by the main program, at the time of the main program's choosing,
          and cannot be called by each other. (However one does use data created
          by the others.) If you have encountered something like this before,
          and were able to solve it without SHARED, I would be pleased to hear
          how you were able to accomplish it.

          Thanks again for your insights folks!


          • #6
            Originally posted by David Jeppesen:
            ...were able to solve it without SHARED...
            David, what Michael was talking about is using "odd" variables
            in a unit. Take the following example:
            $compile unit
            function DoSomething(a,b,c,d$) public
            end function
            Now this function would be available to all programs requiring
            only 4 variables to be passed. Now suppose, in one particular
            program, you need a 5th variable. You could:
            $compile unit
            function DoSomething(a,b,c,d$) public
            shared e$
            end function
            This is what he is refering to as to be avoided. Up to a point,
            I agree but sometimes, it's unavoidable. In this example, I
            personally would copy the 1st file over to a 2nd to keep

            There are no atheists in a fox hole or the morning of a math test.
            If my flag offends you, I'll help you pack.


            • #7
              With shared:
              function DoSomething(a,b,c,d$) AS LONG
                shared e$
              end function
              Without shared:
              function DoSomething(a,b,c,d$,e$) AS LONG
              end function
              Now function DoSomething can be #INCLUDEd in anything.

              If you are setting out to make 'DoSomething' a reusable function, it can't require any external variables.

              OTOH you can use SHARED variables if you have a collection of functions which will be compiled into a UNIT file; i.e., the SHARED variables are OK... as long as you never intend to use any of those functions except by $LINKing the PBU file.

              Bottom line is, you need to invest some time <U>planning</U> your function libraries and #INCLUDE files <U>before</U> you start coding.

              Michael Mattias
              Tal Systems Inc. (retired)
              Racine WI USA
              [email protected]


              • #8
                Thanks again for all your help and insights! I think I've got it

                I've studied everything you all have written and have to admit
                that it has forced me into some introspection! Here I have been
                programming for many years, (ahem, since the early '60s), and am
                still bumbling along, an unreformed pragmatist. I write just enough
                code to get me an answer that works, and then move on to the next
                problem. But you guys make a science of it! It's good that the
                world's IT systems rely upon people like you instead of like me!

                Thanks again for your indulgence,