+static void StdFunc_memset (FuncDesc* F attribute ((unused)),
+ ExprDesc* lval attribute ((unused)))
+/* Handle the memset function */
+{
+ /* Argument types */
+ static type Arg1Type[] = { T_PTR, T_VOID, T_END }; /* void* */
+ static type Arg2Type[] = { T_INT, T_END }; /* int */
+ static type Arg3Type[] = { T_UINT, T_END }; /* size_t */
+
+ unsigned Flags;
+ ExprDesc Arg;
+ int MemSet = 1; /* Use real memset if true */
+ unsigned ParamSize = 0;
+
+
+ /* Check the prototype of the function against what we know about it, so
+ * we can detect errors.
+ */
+ /* ### */
+
+ /* Argument #1 */
+ Flags = ParseArg (Arg1Type, &Arg);
+ g_push (Flags, Arg.ConstVal);
+ ParamSize += SizeOf (Arg1Type);
+ ConsumeComma ();
+
+ /* Argument #2. This argument is special in that we will call another
+ * function if it is a constant zero.
+ */
+ Flags = ParseArg (Arg2Type, &Arg);
+ if ((Flags & CF_CONST) != 0 && Arg.ConstVal == 0) {
+ /* Don't call memset, call bzero instead */
+ MemSet = 0;
+ } else {
+ /* Push the argument */
+ g_push (Flags, Arg.ConstVal);
+ ParamSize += SizeOf (Arg2Type);
+ }
+ ConsumeComma ();
+
+ /* Argument #3. Since memset is a fastcall function, we must load the
+ * arg into the primary if it is not already there. This parameter is
+ * also ignored for the calculation of the parameter size, since it is
+ * not passed via the stack.
+ */
+ Flags = ParseArg (Arg3Type, &Arg);
+ if (Flags & CF_CONST) {
+ exprhs (CF_FORCECHAR, 0, &Arg);
+ }
+
+ /* Emit the actual function call */
+ g_call (CF_NONE, MemSet? "memset" : "_bzero", ParamSize);
+
+ /* We expect the closing brace */
+ ConsumeRParen ();
+}
+
+
+
+static void StdFunc_strlen (FuncDesc* F attribute ((unused)),
+ ExprDesc* lval attribute ((unused)))