View Javadoc

1   package com.tapina.robe.swi.clib.stdio;
2   
3   import com.tapina.robe.swi.clib.Stub;
4   import com.tapina.robe.swi.clib.VarArgs;
5   import com.tapina.robe.swi.clib.stdio.printf.PrintfEngine;
6   import com.tapina.robe.runtime.Environment;
7   import com.tapina.robe.runtime.MemoryMap;
8   
9   /***
10   * This function is identical to sprintf, but the arguments are replaced by a3, which should have been initialised
11   * by va_start.
12   * Returns: The number of characters output, or a negative value if there was an error.
13   */
14  public class VSPrintF extends Stub {
15      public void executeStub(Environment environment) {
16          // It seems like a3 is a pointer to a pointer to the argument, from looking at the macro definitions
17          /*
18              #define va_start(ap, parmN) ((void)(*(ap) = \
19              (char *)&(parmN) + sizeof(parmN)))
20  
21              #define va_arg(ap,type) (sizeof(type) < 4 ? \
22              (type) *(int *)((*(ap)+=4)-4) : \
23              *(type *)((*(ap)+=sizeof(type))-sizeof(type)))
24  
25              #define va_end(ap) ((void)(*(ap) = (char *)-256))
26          */
27          final int[] R = environment.getCpu().R;
28          final MemoryMap memoryMap = environment.getMemoryMap();
29          final String formatString = memoryMap.getString0(R[1]);
30          // NB: varargs are treated as normal arguments (i.e. passed in a1, a2, a3, a4 then stack).
31          final String out = PrintfEngine.getInstance().sprintf(formatString, new VarArgs(memoryMap, memoryMap.getWord(R[2])));
32          memoryMap.storeString0(R[0], out);
33          R[0] = out.length();
34  
35      }
36  }