PowerBASIC has its own method of passing a variable number of arguments but it can be done with more flexibility using a DWORD array which can contain DWORD numbers and DWORD sized pointers in any number required without the high overhead of the normal technique. Once you dimension a DWORD array of whatever count you require which can be large, you just pass an argument count and the number of arguments that match it.
You will notice a number of procedures that are not part of standard PowerBASIC which are in the library "gplib.lib" as I am currently rationalising 20 years of text based source for PowerBASIC so I can find my way around it quickly and a SLL based library is the most efficient method I can see for doing this.
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
#compile exe "vararg.exe"
$link "gplib.lib" ' custom PowerBASIC library
MACRO FUNCTION btxt(quoted) ' return basic text address
MACROTEMP bst
LOCAL bst as STRING
bst = quoted
END MACRO = StrPtr(bst)
MACRO LineFeed = zconout CodePtr(lnfd) ' line feed to console
GLOBAL arglist() as DWORD
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FUNCTION PBmain as LONG
DIM arglist(64) as DWORD ' dimension the array
arglist(0) = 4 ' set the argument count
arglist(1) = 1234 ' load the array
arglist(2) = 5678
arglist(3) = 9012
arglist(4) = 3456
numproc arglist() ' call the test procedure
a$ = "One"
arglist(0) = 4 ' set the argument count
arglist(1) = StrPtr(a$) ' pass a basic dynamic string
arglist(2) = btxt("Two") ' pass a pointer to quoted text
arglist(3) = btxt("Three")
arglist(4) = btxt("Four")
txtproc arglist()
a$ = "How D"
arglist(0) = 0 ' unused
arglist(1) = StrPtr(a$) ' pass a basic dynamic string
arglist(2) = btxt("Basic String") ' pass a basic dynamic string
arglist(3) = 1234 ' pass a number
MixProc arglist()
pause ' pause so you can see it
erase arglist() ' clean up the array on exit
End FUNCTION
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FUNCTION numproc(arg() as DWORD) as DWORD
LOCAL cntr as DWORD ' the passed item count
LOCAL icnt as DWORD ' loop iteration counter
cntr = arg(0) ' load the counter
icnt = 0 ' zero iteration counter
stlp: ' display the array items
! add icnt, 1
conout ustr(arg(icnt))
! sub cntr, 1
! jnz stlp
LineFeed
End FUNCTION
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FUNCTION txtproc(arg() as DWORD) as DWORD
LOCAL cntr as DWORD ' the passed item count
LOCAL icnt as DWORD ' loop iteration counter
cntr = arg(0) ' load the counter
icnt = 0 ' zero iteration counter
lpst:
! add icnt, 1
zconout arg(icnt)
zconout CodePtr(lnfd)
! sub cntr, 1
! jnz lpst
LineFeed
End FUNCTION
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FUNCTION MixProc(arg() as DWORD) as DWORD
conout ustr(arg(0)) ' unused counter
zconout arg(1):LineFeed ' display string
zconout arg(2):LineFeed ' display string
conout ustr(arg(3)) ' display number
LineFeed
END FUNCTION
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
ASMDATA lnfd
db 13,10,0
END ASMDATA
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤