1 (* varargs.mod provides a basic vararg facility for GNU Modula-2.
3 Copyright (C) 2015-2024 Free Software Foundation, Inc.
4 Contributed by Gaius Mulley <gaius@glam.ac.uk>.
6 This file is part of GNU Modula-2.
8 GNU Modula-2 is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 GNU Modula-2 is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Modula-2; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. *)
22 IMPLEMENTATION MODULE varargs
;
24 FROM Storage
IMPORT ALLOCATE
, DEALLOCATE
;
25 FROM libc
IMPORT memcpy
;
26 FROM SYSTEM
IMPORT ADDRESS
, TSIZE, ADR
, BYTE
;
33 vararg
= POINTER TO RECORD
38 arg
: ARRAY [0..MaxArg
] OF argDesc
;
46 ptrToByte
= POINTER TO BYTE
;
50 arg - fills in, a, with the next argument. The size of, a, must be an exact
51 match with the original vararg parameter.
54 PROCEDURE arg (v
: vararg
; VAR a
: ARRAY OF BYTE
) ;
62 HALT (* too many calls to arg. *)
64 IF HIGH(a
)+1=arg
[i
].len
74 HALT (* parameter mismatch. *)
83 nargs - returns the number of arguments wrapped in, v.
86 PROCEDURE nargs (v
: vararg
) : CARDINAL ;
93 copy - returns a copy of, v.
96 PROCEDURE copy (v
: vararg
) : vararg
;
107 ALLOCATE (contents
, size
) ;
108 contents
:= memcpy (contents
, v^.contents
, size
) ;
109 FOR j
:= 0 TO nArgs
DO
110 offset
:= VAL (CARDINAL, VAL (ptrToByte
, v^.contents
) - VAL (ptrToByte
, v^.arg
[j
].ptr
)) ;
111 arg
[j
].ptr
:= VAL (ptrToByte
, contents
) ;
112 INC (arg
[j
].ptr
, offset
) ;
113 arg
[j
].len
:= v^.arg
[j
].len
;
121 replace - fills the next argument with, a. The size of, a,
122 must be an exact match with the original vararg
126 PROCEDURE replace (v
: vararg
; VAR a
: ARRAY OF BYTE
) ;
134 HALT (* too many calls to arg. *)
136 IF HIGH(a
)+1=arg
[i
].len
146 HALT (* parameter mismatch. *)
154 next - assigns the next arg to be collected as, i.
157 PROCEDURE next (v
: vararg
; i
: CARDINAL) ;
164 end - destructor for vararg, v.
167 PROCEDURE end (VAR v
: vararg
) ;
171 DEALLOCATE (v^.contents
, TSIZE (vararg
)) ;
178 start1 - wraps up argument, a, into a vararg.
181 PROCEDURE start1 (a
: ARRAY OF BYTE
) : vararg
;
189 size
:= HIGH (a
) + 1;
190 ALLOCATE (contents
, size
) ;
191 contents
:= memcpy (contents
, ADR (a
), size
) ;
192 arg
[0].ptr
:= contents
;
200 start2 - wraps up arguments, a, b, into a vararg.
203 PROCEDURE start2 (a
, b
: ARRAY OF BYTE
) : vararg
;
212 size
:= HIGH (a
) + HIGH (b
) + 2 ;
213 ALLOCATE (contents
, size
) ;
214 p
:= memcpy (contents
, ADR (a
), HIGH (a
) + 1) ;
216 arg
[0].len
:= HIGH (a
) + 1 ;
217 INC (p
, arg
[0].len
) ;
218 p
:= memcpy (p
, ADR (b
), HIGH (b
) + 1) ;
220 arg
[1].len
:= HIGH (b
) + 1
227 start3 - wraps up arguments, a, b, c, into a vararg.
230 PROCEDURE start3 (a
, b
, c
: ARRAY OF BYTE
) : vararg
;
239 size
:= HIGH (a
) + HIGH (b
) + HIGH (c
) + 3 ;
240 ALLOCATE (contents
, size
) ;
241 p
:= memcpy (contents
, ADR (a
), HIGH (a
) + 1) ;
243 arg
[0].len
:= HIGH (a
) + 1 ;
244 INC (p
, arg
[0].len
) ;
245 p
:= memcpy (p
, ADR (b
), HIGH (b
) + 1) ;
247 arg
[1].len
:= HIGH (b
) + 1 ;
248 INC (p
, arg
[1].len
) ;
249 p
:= memcpy (p
, ADR (c
), HIGH (c
) + 1) ;
251 arg
[2].len
:= HIGH (c
) + 1
258 start4 - wraps up arguments, a, b, c, d, into a vararg.
261 PROCEDURE start4 (a
, b
, c
, d
: ARRAY OF BYTE
) : vararg
;
270 size
:= HIGH (a
) + HIGH (b
) + HIGH (c
) + HIGH (d
) + 4 ;
271 ALLOCATE (contents
, size
) ;
272 p
:= memcpy (contents
, ADR (a
), HIGH (a
) + 1) ;
273 arg
[0].len
:= HIGH (a
) + 1 ;
274 INC (p
, arg
[0].len
) ;
275 p
:= memcpy (p
, ADR (b
), HIGH (b
) + 1) ;
277 arg
[1].len
:= HIGH (b
) + 1 ;
278 INC (p
, arg
[1].len
) ;
279 p
:= memcpy (p
, ADR (c
), HIGH (c
) + 1) ;
281 arg
[2].len
:= HIGH (c
) + 1 ;
282 INC (p
, arg
[2].len
) ;
283 p
:= memcpy (p
, ADR (c
), HIGH (c
) + 1) ;
285 arg
[3].len
:= HIGH (c
) + 1