aboutsummaryrefslogtreecommitdiff
path: root/SingleSource/UnitTests/2003-08-11-VaListArg.c
blob: f72f56c503826385a9fc9ee05d2a43a46babecdb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/*
 * Test passing a va_list argument to a function and other uses
 * of va_list, in things other than va_arg.
 */
#include <stdio.h>
#include <stdarg.h>

/* 5 bytes. */
typedef struct DWordS_struct    { int i; char c; } DWordS;

/* 12 bytes if d is 4-byte aligned; 16 bytes if d is 8-byte aligned. */
typedef struct QuadWordS_struct { int i; double d; } QuadWordS;

/* 20 bytes if d is 4-byte aligned; 28 bytes if d is 8-byte aligned
 * (assuming pointer size is 4 bytes and 8 bytes respectively). */
typedef struct LargeS_struct { int i; double d; DWordS* ptr; int j; } LargeS;

void test(char *fmt, va_list ap) {
  int d;
  char c, *s;
  DWordS dw;
  QuadWordS qw;
  LargeS ls;

  while (*fmt)
    switch(*fmt++) {
    case 's':           /* string */
      s = va_arg(ap, char *);
      printf("string %s\n", s);
      break;
    case 'i':           /* int */
      d = va_arg(ap, int);
      printf("int %d\n", d);
      break;
    case 'd':
      printf("double %f\n", va_arg(ap, double));
      break;
    case 'l':
      printf("long long %lld\n", va_arg(ap, long long));
      break;
    case 'c':           /* char */
      /* need a cast here since va_arg only
         takes fully promoted types */
      c = (char) va_arg(ap, int);
      printf("char %c\n", c);
      break;
    case 'D':
      dw = va_arg(ap, DWordS);
      printf("DWord { %d, %c }\n", dw.i, dw.c);
      break;
    case 'Q':
      qw = va_arg(ap, QuadWordS);
      printf("QuadWord { %d, %f }\n", qw.i, qw.d);
      break;
    case 'L':
      ls = va_arg(ap, LargeS);
      printf("LargeS { %d, %f, 0x%d, %d }\n", ls.i, ls.d, ls.ptr != 0, ls.j);
      break;
    }
  va_end(ap);
}

void testVaListArg(char *fmt, ...) {
  va_list ap;
  va_start(ap, fmt);
  test(fmt, ap);
  va_end(ap);
}

void testVaCopyArg(char *fmt, ...) {
  va_list ap, aq;
  va_start(ap, fmt);
  va_copy(aq, ap);    /* test va_copy */
  test(fmt, aq);
  va_end(aq);
  va_end(ap);
}

int main() {
  DWordS dw = { 18, 'a' };
  QuadWordS qw = { 19, 20.0 };
  LargeS ls = { 21, 22.0, &dw, 23 };

  testVaListArg("ssiciiiiis", "abc", "def", -123, 'a', 123, 6, 7, 8, 9, "10 args done!");
  testVaCopyArg("ssiciiiiis", "abc", "def", -123, 'a', 123, 6, 7, 8, 9, "10 args done!");

  /* test promotion & 64-bit types */
  testVaListArg("ddil", 1.0, 2.0f, (short)32764, 12345677823423LL);
  testVaCopyArg("ddil", 1.0, 2.0f, (short)32764, 12345677823423LL);

  /* test passing structs by value to varargs */
  testVaListArg("DQL", dw, qw, ls);
  testVaCopyArg("DQL", dw, qw, ls);

  return 0;
}