#include "support.h" #include #include #include #include #include int _strlen(CONST_STRPTR str) { int len = 0; while (*str++) len++; return len; } struct Task * NewCreateTaskTags(struct TagItem *tags) { struct Task *task = NULL; APTR entry = (APTR)GetTagData(TASKTAG_PC, 0, tags); APTR task_name = (APTR)GetTagData(TASKTAG_NAME, (ULONG)"task", tags); APTR userdata = (APTR)GetTagData(TASKTAG_USERDATA, 0, tags); ULONG task_name_len = _strlen(task_name) + 1; UBYTE priority = GetTagData(TASKTAG_PRI, 0, tags); ULONG stacksize = GetTagData(TASKTAG_STACKSIZE, 8192, tags); ULONG args[] = { GetTagData(TASKTAG_ARG1, 0, tags), GetTagData(TASKTAG_ARG2, 0, tags), GetTagData(TASKTAG_ARG3, 0, tags), GetTagData(TASKTAG_ARG4, 0, tags) }; ULONG argcnt = 0; if (FindTagItem(TASKTAG_ARG4, tags)) { argcnt = 4; } else if (FindTagItem(TASKTAG_ARG3, tags)) { argcnt = 3; } else if (FindTagItem(TASKTAG_ARG2, tags)) { argcnt = 2; } else if (FindTagItem(TASKTAG_ARG1, tags)) { argcnt = 1; } if (entry != NULL) { task = AllocMem(sizeof(struct Task), MEMF_PUBLIC | MEMF_CLEAR); struct MemList *ml = AllocMem(sizeof(struct MemList) + 2*sizeof(struct MemEntry), MEMF_PUBLIC | MEMF_CLEAR); ULONG *stack = AllocMem(stacksize, MEMF_PUBLIC | MEMF_CLEAR); ULONG *sp = (ULONG *)((ULONG)stack + stacksize); STRPTR name_copy = AllocMem(task_name_len, MEMF_PUBLIC | MEMF_CLEAR); CopyMem((APTR)task_name, name_copy, task_name_len); ml->ml_NumEntries = 3; ml->ml_ME[0].me_Un.meu_Addr = task; ml->ml_ME[0].me_Length = sizeof(struct Task); ml->ml_ME[1].me_Un.meu_Addr = stack; ml->ml_ME[1].me_Length = stacksize; ml->ml_ME[2].me_Un.meu_Addr = name_copy; ml->ml_ME[2].me_Length = task_name_len; sp -= argcnt; for (int i=0; i < argcnt; i++) { sp[i] = args[i]; } task->tc_UserData = userdata; task->tc_SPLower = stack; task->tc_SPUpper = (APTR)((ULONG)stack + stacksize); task->tc_SPReg = sp; task->tc_Node.ln_Name = name_copy; task->tc_Node.ln_Type = NT_TASK; task->tc_Node.ln_Pri = priority; NewList(&task->tc_MemEntry); AddHead(&task->tc_MemEntry, &ml->ml_Node); AddTask(task, entry, NULL); } return task; } static void int_itoa(char *buf, char base, uintptr_t value, char zero_pad, int precision, int size_mod, char big, int alternate_form, int neg, char sign) { int length = 0; do { char c = value % base; if (c >= 10) { if (big) c += 'A'-10; else c += 'a'-10; } else c += '0'; value = value / base; buf[length++] = c; } while(value != 0); if (precision != 0) { while (length < precision) buf[length++] = '0'; } else if (size_mod != 0 && zero_pad) { int sz_mod = size_mod; if (alternate_form) { if (base == 16) sz_mod -= 2; else if (base == 8) sz_mod -= 1; } if (neg) sz_mod -= 1; while (length < sz_mod) buf[length++] = '0'; } if (alternate_form) { if (base == 8) buf[length++] = '0'; if (base == 16) { buf[length++] = big ? 'X' : 'x'; buf[length++] = '0'; } } if (neg) buf[length++] = '-'; else { if (sign == '+') buf[length++] = '+'; else if (sign == ' ') buf[length++] = ' '; } for (int i=0; i < length/2; i++) { char tmp = buf[i]; buf[i] = buf[length - i - 1]; buf[length - i - 1] = tmp; } buf[length] = 0; } typedef void (*putc_func)(void *data, char c); void vkprintf_pc(putc_func putc_f, void *putc_data, const char * restrict format, va_list args) { char tmpbuf[32]; while(*format) { char c; char alternate_form = 0; int size_mod = 0; int length_mod = 0; int precision = 0; char zero_pad = 0; char *str; char sign = 0; char leftalign = 0; uintptr_t value = 0; intptr_t ivalue = 0; char big = 0; c = *format++; if (c != '%') { putc_f(putc_data, c); } else { c = *format++; if (c == '#') { alternate_form = 1; c = *format++; } if (c == '-') { leftalign = 1; c = *format++; } if (c == ' ' || c == '+') { sign = c; c = *format++; } if (c == '0') { zero_pad = 1; c = *format++; } while(c >= '0' && c <= '9') { size_mod = size_mod * 10; size_mod = size_mod + c - '0'; c = *format++; } if (c == '.') { c = *format++; while(c >= '0' && c <= '9') { precision = precision * 10; precision = precision + c - '0'; c = *format++; } } big = 0; if (c == 'h') { c = *format++; if (c == 'h') { c = *format++; length_mod = 1; } else length_mod = 2; } else if (c == 'l') { c = *format++; if (c == 'l') { c = *format++; length_mod = 8; } else length_mod = 4; } else if (c == 'j') { c = *format++; length_mod = 9; } else if (c == 't') { c = *format++; length_mod = 10; } else if (c == 'z') { c = *format++; length_mod = 11; } switch (c) { case 0: return; case '%': putc_f(putc_data, '%'); break; case 'p': value = va_arg(args, uintptr_t); int_itoa(tmpbuf, 16, value, 1, 2*sizeof(uintptr_t), 2*sizeof(uintptr_t), big, 1, 0, sign); str = tmpbuf; size_mod -= _strlen(str) - 1; while (*str) { putc_f(putc_data, *str++); } break; case 'X': big = 1; /* fallthrough */ case 'x': switch (length_mod) { case 8: value = va_arg(args, uint64_t); break; case 9: value = va_arg(args, uintmax_t); break; case 10: value = va_arg(args, uintptr_t); break; case 11: value = va_arg(args, ULONG); break; default: value = va_arg(args, unsigned int); break; } int_itoa(tmpbuf, 16, value, zero_pad, precision, size_mod, big, alternate_form, 0, sign); str = tmpbuf; size_mod -= _strlen(str) - 1; if (!leftalign) while(size_mod-- > 0) putc_f(putc_data, ' '); while(*str) { putc_f(putc_data, *str++); } if (leftalign) while(size_mod-- > 0) putc_f(putc_data, ' '); break; case 'u': switch (length_mod) { case 8: value = va_arg(args, uint64_t); break; case 9: value = va_arg(args, uintmax_t); break; case 10: value = va_arg(args, uintptr_t); break; case 11: value = va_arg(args, ULONG); break; default: value = va_arg(args, unsigned int); break; } int_itoa(tmpbuf, 10, value, zero_pad, precision, size_mod, 0, alternate_form, 0, sign); str = tmpbuf; size_mod -= _strlen(str) - 1; if (!leftalign) while(size_mod-- > 0) putc_f(putc_data, ' '); while(*str) { putc_f(putc_data, *str++); } if (leftalign) while(size_mod-- > 0) putc_f(putc_data, ' '); break; case 'd': case 'i': switch (length_mod) { case 8: ivalue = va_arg(args, int64_t); break; case 9: ivalue = va_arg(args, intmax_t); break; case 10: ivalue = va_arg(args, intptr_t); break; case 11: ivalue = va_arg(args, ULONG); break; default: ivalue = va_arg(args, int); break; } if (ivalue < 0) int_itoa(tmpbuf, 10, -ivalue, zero_pad, precision, size_mod, 0, alternate_form, 1, sign); else int_itoa(tmpbuf, 10, ivalue, zero_pad, precision, size_mod, 0, alternate_form, 0, sign); str = tmpbuf; size_mod -= _strlen(str) - 1; if (!leftalign) while(size_mod-- > 0) putc_f(putc_data, ' '); while(*str) { putc_f(putc_data, *str++); } if (leftalign) while(size_mod-- > 0) putc_f(putc_data, ' '); break; case 'o': switch (length_mod) { case 8: value = va_arg(args, uint64_t); break; case 9: value = va_arg(args, uintmax_t); break; case 10: value = va_arg(args, uintptr_t); break; case 11: value = va_arg(args, ULONG); break; default: value = va_arg(args, uint32_t); break; } int_itoa(tmpbuf, 8, value, zero_pad, precision, size_mod, 0, alternate_form, 0, sign); str = tmpbuf; size_mod -= _strlen(str) - 1; if (!leftalign) while(size_mod-- > 0) putc_f(putc_data, ' '); while(*str) { putc_f(putc_data, *str++); } if (leftalign) while(size_mod-- > 0) putc_f(putc_data, ' '); break; case 'c': putc_f(putc_data, va_arg(args, int)); break; case 's': { str = va_arg(args, char *); do { if (*str == 0) break; else putc_f(putc_data, *str); size_mod--; } while(*str++ && --precision); while (size_mod-- > 0) putc_f(putc_data, ' '); } break; default: putc_f(putc_data, c); break; } } } } void putc_s(void *data, char c) { char **ppchr = data; char *pchr = *ppchr; *pchr++ = c; *pchr = 0; *ppchr = pchr; } void _sprintf(char *buf, const char * restrict format, ...) { va_list v; va_start(v, format); vkprintf_pc(putc_s, &buf, format, v); va_end(v); }