fmt.odin 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349
  1. package fmt
  2. import "core:runtime"
  3. import "core:os"
  4. import "core:mem"
  5. import "core:unicode/utf8"
  6. import "core:types"
  7. import "core:strconv"
  8. _BUFFER_SIZE :: 1<<12;
  9. String_Buffer :: distinct [dynamic]byte;
  10. Fmt_Info :: struct {
  11. minus: bool,
  12. plus: bool,
  13. space: bool,
  14. zero: bool,
  15. hash: bool,
  16. width_set: bool,
  17. prec_set: bool,
  18. width: int,
  19. prec: int,
  20. indent: int,
  21. reordered: bool,
  22. good_arg_index: bool,
  23. buf: ^String_Buffer,
  24. arg: any, // Temporary
  25. }
  26. string_buffer_from_slice :: proc(backing: []byte) -> String_Buffer {
  27. s := transmute(mem.Raw_Slice)backing;
  28. d := mem.Raw_Dynamic_Array{
  29. data = s.data,
  30. len = 0,
  31. cap = s.len,
  32. allocator = mem.nil_allocator(),
  33. };
  34. return transmute(String_Buffer)d;
  35. }
  36. to_string :: proc(buf: String_Buffer) -> string {
  37. return string(buf[:]);
  38. }
  39. write_string :: proc(buf: ^String_Buffer, s: string) {
  40. append_string(buf, s);
  41. }
  42. write_bytes :: proc(buf: ^String_Buffer, data: []byte) {
  43. append(buf, ..data);
  44. }
  45. write_byte :: proc(buf: ^String_Buffer, data: byte) {
  46. append(buf, data);
  47. }
  48. write_rune :: proc(buf: ^String_Buffer, r: rune) {
  49. if r < utf8.RUNE_SELF {
  50. write_byte(buf, byte(r));
  51. return;
  52. }
  53. b, n := utf8.encode_rune(r);
  54. write_bytes(buf, b[:n]);
  55. }
  56. write_encoded_rune :: proc(buf: ^String_Buffer, r: rune) {
  57. write_byte(buf, '\'');
  58. switch r {
  59. case '\a': write_string(buf, "\\a");
  60. case '\b': write_string(buf, "\\b");
  61. case '\e': write_string(buf, "\\e");
  62. case '\f': write_string(buf, "\\f");
  63. case '\n': write_string(buf, "\\n");
  64. case '\r': write_string(buf, "\\r");
  65. case '\t': write_string(buf, "\\t");
  66. case '\v': write_string(buf, "\\v");
  67. case:
  68. if r < 32 {
  69. write_string(buf, "\\x");
  70. b: [2]byte;
  71. s := strconv.append_bits(b[:], u64(r), 16, true, 64, strconv.digits, nil);
  72. switch len(s) {
  73. case 0: write_string(buf, "00");
  74. case 1: write_rune(buf, '0');
  75. case 2: write_string(buf, s);
  76. }
  77. } else {
  78. write_rune(buf, r);
  79. }
  80. }
  81. write_byte(buf, '\'');
  82. }
  83. write_u64 :: proc(buf: ^String_Buffer, i: u64, base: int) {
  84. b: [129]byte;
  85. s := strconv.append_bits(b[:], u64(i), base, false, 64, strconv.digits, nil);
  86. write_string(buf, s);
  87. }
  88. write_i64 :: proc(buf: ^String_Buffer, i: i64, base: int) {
  89. b: [129]byte;
  90. s := strconv.append_bits(b[:], u64(i), base, true, 64, strconv.digits, nil);
  91. write_string(buf, s);
  92. }
  93. fprint :: proc(fd: os.Handle, args: ..any) -> int {
  94. data: [_BUFFER_SIZE]byte;
  95. buf := string_buffer_from_slice(data[:]);
  96. res := sbprint(&buf, ..args);
  97. os.write_string(fd, res);
  98. return len(res);
  99. }
  100. fprintln :: proc(fd: os.Handle, args: ..any) -> int {
  101. data: [_BUFFER_SIZE]byte;
  102. buf := string_buffer_from_slice(data[:]);
  103. res := sbprintln(&buf, ..args);
  104. os.write_string(fd, res);
  105. return len(res);
  106. }
  107. fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int {
  108. data: [_BUFFER_SIZE]byte;
  109. buf := string_buffer_from_slice(data[:]);
  110. res := sbprintf(&buf, fmt, ..args);
  111. os.write_string(fd, res);
  112. return len(res);
  113. }
  114. // print* procedures return the number of bytes written
  115. print :: proc(args: ..any) -> int { return fprint(os.stdout, ..args); }
  116. print_err :: proc(args: ..any) -> int { return fprint(os.stderr, ..args); }
  117. println :: proc(args: ..any) -> int { return fprintln(os.stdout, ..args); }
  118. println_err :: proc(args: ..any) -> int { return fprintln(os.stderr, ..args); }
  119. printf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stdout, fmt, ..args); }
  120. printf_err :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stderr, fmt, ..args); }
  121. // aprint* procedures return a string that was allocated with the current context
  122. // They must be freed accordingly
  123. aprint :: proc(args: ..any) -> string {
  124. buf := String_Buffer(make([dynamic]byte));
  125. sbprint(&buf, ..args);
  126. return to_string(buf);
  127. }
  128. aprintln :: proc(args: ..any) -> string {
  129. buf := String_Buffer(make([dynamic]byte));
  130. sbprintln(&buf, ..args);
  131. return to_string(buf);
  132. }
  133. aprintf :: proc(fmt: string, args: ..any) -> string {
  134. buf := String_Buffer(make([dynamic]byte));
  135. sbprintf(&buf, fmt, ..args);
  136. return to_string(buf);
  137. }
  138. // bprint* procedures return a string using a buffer from an array
  139. bprint :: proc(buf: []byte, args: ..any) -> string {
  140. sb := string_buffer_from_slice(buf[0:len(buf)]);
  141. return sbprint(&sb, ..args);
  142. }
  143. bprintln :: proc(buf: []byte, args: ..any) -> string {
  144. sb := string_buffer_from_slice(buf[0:len(buf)]);
  145. return sbprintln(&sb, ..args);
  146. }
  147. bprintf :: proc(buf: []byte, fmt: string, args: ..any) -> string {
  148. sb := string_buffer_from_slice(buf[0:len(buf)]);
  149. return sbprintf(&sb, fmt, ..args);
  150. }
  151. fprint_type :: proc(fd: os.Handle, info: ^runtime.Type_Info) {
  152. data: [_BUFFER_SIZE]byte;
  153. buf := string_buffer_from_slice(data[:]);
  154. write_type(&buf, info);
  155. os.write(fd, buf[:]);
  156. }
  157. write_typeid :: proc(buf: ^String_Buffer, id: typeid) {
  158. write_type(buf, type_info_of(id));
  159. }
  160. write_type :: proc(buf: ^String_Buffer, ti: ^runtime.Type_Info) {
  161. if ti == nil {
  162. write_string(buf, "nil");
  163. return;
  164. }
  165. switch info in ti.variant {
  166. case runtime.Type_Info_Named:
  167. write_string(buf, info.name);
  168. case runtime.Type_Info_Integer:
  169. a := any{typeid = typeid_of(ti)};
  170. switch in a {
  171. case int: write_string(buf, "int");
  172. case uint: write_string(buf, "uint");
  173. case uintptr: write_string(buf, "uintptr");
  174. case:
  175. write_byte(buf, info.signed ? 'i' : 'u');
  176. write_i64(buf, i64(8*ti.size), 10);
  177. }
  178. case runtime.Type_Info_Rune:
  179. write_string(buf, "rune");
  180. case runtime.Type_Info_Float:
  181. write_byte(buf, 'f');
  182. write_i64(buf, i64(8*ti.size), 10);
  183. case runtime.Type_Info_Complex:
  184. write_string(buf, "complex");
  185. write_i64(buf, i64(8*ti.size), 10);
  186. case runtime.Type_Info_String:
  187. if info.is_cstring {
  188. write_string(buf, "cstring");
  189. } else {
  190. write_string(buf, "string");
  191. }
  192. case runtime.Type_Info_Boolean:
  193. a := any{typeid = typeid_of(ti)};
  194. switch in a {
  195. case bool: write_string(buf, "bool");
  196. case:
  197. write_byte(buf, 'b');
  198. write_i64(buf, i64(8*ti.size), 10);
  199. }
  200. case runtime.Type_Info_Any:
  201. write_string(buf, "any");
  202. case runtime.Type_Info_Type_Id:
  203. write_string(buf, "typeid");
  204. case runtime.Type_Info_Pointer:
  205. if info.elem == nil {
  206. write_string(buf, "rawptr");
  207. } else {
  208. write_string(buf, "^");
  209. write_type(buf, info.elem);
  210. }
  211. case runtime.Type_Info_Procedure:
  212. write_string(buf, "proc");
  213. if info.params == nil {
  214. write_string(buf, "()");
  215. } else {
  216. t := info.params.variant.(runtime.Type_Info_Tuple);
  217. write_string(buf, "(");
  218. for t, i in t.types {
  219. if i > 0 do write_string(buf, ", ");
  220. write_type(buf, t);
  221. }
  222. write_string(buf, ")");
  223. }
  224. if info.results != nil {
  225. write_string(buf, " -> ");
  226. write_type(buf, info.results);
  227. }
  228. case runtime.Type_Info_Tuple:
  229. count := len(info.names);
  230. if count != 1 do write_string(buf, "(");
  231. for name, i in info.names {
  232. if i > 0 do write_string(buf, ", ");
  233. t := info.types[i];
  234. if len(name) > 0 {
  235. write_string(buf, name);
  236. write_string(buf, ": ");
  237. }
  238. write_type(buf, t);
  239. }
  240. if count != 1 do write_string(buf, ")");
  241. case runtime.Type_Info_Array:
  242. write_string(buf, "[");
  243. write_i64(buf, i64(info.count), 10);
  244. write_string(buf, "]");
  245. write_type(buf, info.elem);
  246. case runtime.Type_Info_Dynamic_Array:
  247. write_string(buf, "[dynamic]");
  248. write_type(buf, info.elem);
  249. case runtime.Type_Info_Slice:
  250. write_string(buf, "[]");
  251. write_type(buf, info.elem);
  252. case runtime.Type_Info_Map:
  253. write_string(buf, "map[");
  254. write_type(buf, info.key);
  255. write_byte(buf, ']');
  256. write_type(buf, info.value);
  257. case runtime.Type_Info_Struct:
  258. write_string(buf, "struct ");
  259. if info.is_packed do write_string(buf, "#packed ");
  260. if info.is_raw_union do write_string(buf, "#raw_union ");
  261. if info.custom_align {
  262. write_string(buf, "#align ");
  263. write_i64(buf, i64(ti.align), 10);
  264. write_byte(buf, ' ');
  265. }
  266. write_byte(buf, '{');
  267. for name, i in info.names {
  268. if i > 0 do write_string(buf, ", ");
  269. write_string(buf, name);
  270. write_string(buf, ": ");
  271. write_type(buf, info.types[i]);
  272. }
  273. write_byte(buf, '}');
  274. case runtime.Type_Info_Union:
  275. write_string(buf, "union {");
  276. for variant, i in info.variants {
  277. if i > 0 do write_string(buf, ", ");
  278. write_type(buf, variant);
  279. }
  280. write_string(buf, "}");
  281. case runtime.Type_Info_Enum:
  282. write_string(buf, "enum ");
  283. write_type(buf, info.base);
  284. write_string(buf, " {");
  285. for name, i in info.names {
  286. if i > 0 do write_string(buf, ", ");
  287. write_string(buf, name);
  288. }
  289. write_string(buf, "}");
  290. case runtime.Type_Info_Bit_Field:
  291. write_string(buf, "bit_field ");
  292. if ti.align != 1 {
  293. write_string(buf, "#align ");
  294. write_i64(buf, i64(ti.align), 10);
  295. write_rune(buf, ' ');
  296. }
  297. write_string(buf, " {");
  298. for name, i in info.names {
  299. if i > 0 do write_string(buf, ", ");
  300. write_string(buf, name);
  301. write_string(buf, ": ");
  302. write_i64(buf, i64(info.bits[i]), 10);
  303. }
  304. write_string(buf, "}");
  305. case runtime.Type_Info_Bit_Set:
  306. write_string(buf, "bit_set[");
  307. switch {
  308. case types.is_enum(info.elem):
  309. write_type(buf, info.elem);
  310. case types.is_rune(info.elem):
  311. write_encoded_rune(buf, rune(info.lower));
  312. write_string(buf, "..");
  313. write_encoded_rune(buf, rune(info.upper));
  314. case:
  315. write_i64(buf, info.lower, 10);
  316. write_string(buf, "..");
  317. write_i64(buf, info.upper, 10);
  318. }
  319. if info.underlying != nil {
  320. write_string(buf, "; ");
  321. write_type(buf, info.underlying);
  322. }
  323. write_byte(buf, ']');
  324. }
  325. }
  326. _parse_int :: proc(s: string, offset: int) -> (result: int, new_offset: int, ok: bool) {
  327. is_digit :: inline proc(r: byte) -> bool { return '0' <= r && r <= '9' }
  328. new_offset = offset;
  329. for new_offset <= len(s) {
  330. c := s[new_offset];
  331. if !is_digit(c) do break;
  332. new_offset += 1;
  333. result *= 10;
  334. result += int(c)-'0';
  335. }
  336. ok = new_offset > offset;
  337. return;
  338. }
  339. _arg_number :: proc(fi: ^Fmt_Info, arg_index: int, format: string, offset, arg_count: int) -> (index, new_offset: int, ok: bool) {
  340. parse_arg_number :: proc(format: string) -> (int, int, bool) {
  341. if len(format) < 3 do return 0, 1, false;
  342. for i in 1..len(format)-1 {
  343. if format[i] == ']' {
  344. width, new_index, ok := _parse_int(format, 1);
  345. if !ok || new_index != i {
  346. return 0, i+1, false;
  347. }
  348. return width-1, i+1, true;
  349. }
  350. }
  351. return 0, 1, false;
  352. }
  353. if len(format) <= offset || format[offset] != '[' {
  354. return arg_index, offset, false;
  355. }
  356. fi.reordered = true;
  357. width: int;
  358. index, width, ok = parse_arg_number(format[offset:]);
  359. if ok && 0 <= index && index < arg_count {
  360. return index, offset+width, true;
  361. }
  362. fi.good_arg_index = false;
  363. return arg_index, offset+width, false;
  364. }
  365. int_from_arg :: proc(args: []any, arg_index: int) -> (int, int, bool) {
  366. num := 0;
  367. new_arg_index := arg_index;
  368. ok := true;
  369. if arg_index < len(args) {
  370. arg := args[arg_index];
  371. arg.typeid = runtime.typeid_base(arg.typeid);
  372. switch i in arg {
  373. case int: num = i;
  374. case i8: num = int(i);
  375. case i16: num = int(i);
  376. case i32: num = int(i);
  377. case i64: num = int(i);
  378. case u8: num = int(i);
  379. case u16: num = int(i);
  380. case u32: num = int(i);
  381. case u64: num = int(i);
  382. case:
  383. ok = false;
  384. }
  385. }
  386. return num, new_arg_index, ok;
  387. }
  388. fmt_bad_verb :: proc(using fi: ^Fmt_Info, verb: rune) {
  389. assert(verb != 'v');
  390. write_string(buf, "%!");
  391. write_rune(buf, verb);
  392. write_byte(buf, '(');
  393. if arg.typeid != nil {
  394. write_typeid(buf, arg.typeid);
  395. write_byte(buf, '=');
  396. fmt_value(fi, arg, 'v');
  397. } else {
  398. write_string(buf, "<nil>");
  399. }
  400. write_byte(buf, ')');
  401. }
  402. fmt_bool :: proc(using fi: ^Fmt_Info, b: bool, verb: rune) {
  403. switch verb {
  404. case 't', 'v':
  405. write_string(buf, b ? "true" : "false");
  406. case:
  407. fmt_bad_verb(fi, verb);
  408. }
  409. }
  410. fmt_write_padding :: proc(fi: ^Fmt_Info, width: int) {
  411. if width <= 0 do return;
  412. pad_byte: byte = '0';
  413. if fi.space do pad_byte = ' ';
  414. for _ in 0..width-1 {
  415. write_byte(fi.buf, pad_byte);
  416. }
  417. }
  418. _fmt_int :: proc(fi: ^Fmt_Info, u: u64, base: int, is_signed: bool, bit_size: int, digits: string) {
  419. _, neg := strconv.is_integer_negative(u, is_signed, bit_size);
  420. BUF_SIZE :: 256;
  421. if fi.width_set || fi.prec_set {
  422. width := fi.width + fi.prec + 3; // 3 extra bytes for sign and prefix
  423. if width > BUF_SIZE {
  424. // TODO(bill):????
  425. panic("_fmt_int: buffer overrun. Width and precision too big");
  426. }
  427. }
  428. prec := 0;
  429. if fi.prec_set {
  430. prec = fi.prec;
  431. if prec == 0 && u == 0 {
  432. prev_zero := fi.zero;
  433. fi.zero = false;
  434. fmt_write_padding(fi, fi.width);
  435. fi.zero = prev_zero;
  436. return;
  437. }
  438. } else if fi.zero && fi.width_set {
  439. prec = fi.width;
  440. if neg || fi.plus || fi.space {
  441. // There needs to be space for the "sign"
  442. prec -= 1;
  443. }
  444. }
  445. switch base {
  446. case 2, 8, 10, 12, 16:
  447. break;
  448. case:
  449. panic("_fmt_int: unknown base, whoops");
  450. }
  451. buf: [256]byte;
  452. start := 0;
  453. using strconv.Int_Flag;
  454. flags: strconv.Int_Flags;
  455. if fi.hash && !fi.zero do flags |= {Prefix};
  456. if fi.plus do flags |= {Plus};
  457. if fi.space do flags |= {Space};
  458. s := strconv.append_bits(buf[start:], u, base, is_signed, bit_size, digits, flags);
  459. if fi.hash && fi.zero {
  460. c: byte = 0;
  461. switch base {
  462. case 2: c = 'b';
  463. case 8: c = 'o';
  464. case 12: c = 'z';
  465. case 16: c = 'x';
  466. }
  467. if c != 0 {
  468. write_byte(fi.buf, '0');
  469. write_byte(fi.buf, c);
  470. }
  471. }
  472. prev_zero := fi.zero;
  473. defer fi.zero = prev_zero;
  474. fi.zero = false;
  475. _pad(fi, s);
  476. }
  477. __DIGITS_LOWER := "0123456789abcdefx";
  478. __DIGITS_UPPER := "0123456789ABCDEFX";
  479. fmt_rune :: proc(fi: ^Fmt_Info, r: rune, verb: rune) {
  480. switch verb {
  481. case 'c', 'r', 'v':
  482. write_rune(fi.buf, r);
  483. case:
  484. fmt_int(fi, u64(r), false, 32, verb);
  485. }
  486. }
  487. fmt_int :: proc(fi: ^Fmt_Info, u: u64, is_signed: bool, bit_size: int, verb: rune) {
  488. switch verb {
  489. case 'v': _fmt_int(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER);
  490. case 'b': _fmt_int(fi, u, 2, is_signed, bit_size, __DIGITS_LOWER);
  491. case 'o': _fmt_int(fi, u, 8, is_signed, bit_size, __DIGITS_LOWER);
  492. case 'd': _fmt_int(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER);
  493. case 'z': _fmt_int(fi, u, 12, is_signed, bit_size, __DIGITS_LOWER);
  494. case 'x': _fmt_int(fi, u, 16, is_signed, bit_size, __DIGITS_LOWER);
  495. case 'X': _fmt_int(fi, u, 16, is_signed, bit_size, __DIGITS_UPPER);
  496. case 'c', 'r':
  497. fmt_rune(fi, rune(u), verb);
  498. case 'U':
  499. r := rune(u);
  500. if r < 0 || r > utf8.MAX_RUNE {
  501. fmt_bad_verb(fi, verb);
  502. } else {
  503. write_string(fi.buf, "U+");
  504. _fmt_int(fi, u, 16, false, bit_size, __DIGITS_UPPER);
  505. }
  506. case:
  507. fmt_bad_verb(fi, verb);
  508. }
  509. }
  510. _pad :: proc(fi: ^Fmt_Info, s: string) {
  511. if !fi.width_set {
  512. write_string(fi.buf, s);
  513. return;
  514. }
  515. width := fi.width - utf8.rune_count_from_string(s);
  516. if fi.minus { // right pad
  517. write_string(fi.buf, s);
  518. fmt_write_padding(fi, width);
  519. } else { // left pad
  520. fmt_write_padding(fi, width);
  521. write_string(fi.buf, s);
  522. }
  523. }
  524. fmt_float :: proc(fi: ^Fmt_Info, v: f64, bit_size: int, verb: rune) {
  525. switch verb {
  526. // case 'e', 'E', 'f', 'F', 'g', 'G', 'v':
  527. // case 'f', 'F', 'v':
  528. case 'f', 'F', 'v':
  529. prec: int = 3;
  530. if fi.prec_set do prec = fi.prec;
  531. buf: [386]byte;
  532. str := strconv.append_float(buf[1:], v, 'f', prec, bit_size);
  533. str = string(buf[:len(str)+1]);
  534. if str[1] == '+' || str[1] == '-' {
  535. str = str[1:];
  536. } else {
  537. str[0] = '+';
  538. }
  539. if fi.space && !fi.plus && str[0] == '+' {
  540. str[0] = ' ';
  541. }
  542. if len(str) > 1 && str[1] == 'N' && str[1] == 'I' {
  543. write_string(fi.buf, str);
  544. return;
  545. }
  546. if fi.plus || str[0] != '+' {
  547. if fi.zero && fi.width_set && fi.width > len(str) {
  548. write_byte(fi.buf, str[0]);
  549. fmt_write_padding(fi, fi.width - len(str));
  550. write_string(fi.buf, str[1:]);
  551. } else {
  552. _pad(fi, str);
  553. }
  554. } else {
  555. _pad(fi, str[1:]);
  556. }
  557. case:
  558. fmt_bad_verb(fi, verb);
  559. }
  560. }
  561. fmt_string :: proc(fi: ^Fmt_Info, s: string, verb: rune) {
  562. switch verb {
  563. case 's', 'v':
  564. write_string(fi.buf, s);
  565. case 'x', 'X':
  566. space := fi.space;
  567. fi.space = false;
  568. defer fi.space = space;
  569. for i in 0..len(s)-1 {
  570. if i > 0 && space do write_byte(fi.buf, ' ');
  571. char_set := __DIGITS_UPPER;
  572. if verb == 'x' do char_set = __DIGITS_LOWER;
  573. _fmt_int(fi, u64(s[i]), 16, false, 8, char_set);
  574. }
  575. case:
  576. fmt_bad_verb(fi, verb);
  577. }
  578. }
  579. fmt_cstring :: proc(fi: ^Fmt_Info, s: cstring, verb: rune) {
  580. fmt_string(fi, string(s), verb);
  581. }
  582. fmt_pointer :: proc(fi: ^Fmt_Info, p: rawptr, verb: rune) {
  583. switch verb {
  584. case 'p', 'v':
  585. u := u64(uintptr(p));
  586. if !fi.hash || verb == 'v' {
  587. write_string(fi.buf, "0x");
  588. }
  589. _fmt_int(fi, u, 16, false, 8*size_of(rawptr), __DIGITS_UPPER);
  590. case:
  591. fmt_bad_verb(fi, verb);
  592. }
  593. }
  594. enum_value_to_string :: proc(v: any) -> (string, bool) {
  595. v.typeid = runtime.typeid_base(v.typeid);
  596. type_info := type_info_of(v.typeid);
  597. switch e in type_info.variant {
  598. case: return "", false;
  599. case runtime.Type_Info_Enum:
  600. get_str :: proc(i: $T, e: runtime.Type_Info_Enum) -> (string, bool) {
  601. if types.is_string(e.base) {
  602. for val, idx in e.values {
  603. if v, ok := val.(T); ok && v == i {
  604. return e.names[idx], true;
  605. }
  606. }
  607. } else if len(e.values) == 0 {
  608. return "", true;
  609. } else {
  610. for val, idx in e.values {
  611. if v, ok := val.(T); ok && v == i {
  612. return e.names[idx], true;
  613. }
  614. }
  615. }
  616. return "", false;
  617. }
  618. a := any{v.data, typeid_of(runtime.type_info_base(e.base))};
  619. switch v in a {
  620. case rune: return get_str(v, e);
  621. case i8: return get_str(v, e);
  622. case i16: return get_str(v, e);
  623. case i32: return get_str(v, e);
  624. case i64: return get_str(v, e);
  625. case int: return get_str(v, e);
  626. case u8: return get_str(v, e);
  627. case u16: return get_str(v, e);
  628. case u32: return get_str(v, e);
  629. case u64: return get_str(v, e);
  630. case uint: return get_str(v, e);
  631. case uintptr: return get_str(v, e);
  632. }
  633. }
  634. return "", false;
  635. }
  636. string_to_enum_value :: proc(T: type, s: string) -> (T, bool) {
  637. ti := type_info_base(type_info_of(T));
  638. if e, ok := ti.variant.(Type_Info_Enum); ok {
  639. for str, idx in e.names {
  640. if s == str {
  641. // NOTE(bill): Unsafe cast
  642. ptr := cast(^T)&e.values[idx];
  643. return ptr^, true;
  644. }
  645. }
  646. }
  647. return T{}, false;
  648. }
  649. fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
  650. if v.typeid == nil || v.data == nil {
  651. write_string(fi.buf, "<nil>");
  652. return;
  653. }
  654. type_info := type_info_of(v.typeid);
  655. switch e in type_info.variant {
  656. case: fmt_bad_verb(fi, verb);
  657. case runtime.Type_Info_Enum:
  658. switch verb {
  659. case: fmt_bad_verb(fi, verb);
  660. case 'd', 'f':
  661. fmt_arg(fi, any{v.data, typeid_of(runtime.type_info_base(e.base))}, verb);
  662. case 's', 'v':
  663. str, ok := enum_value_to_string(v);
  664. if !ok do str = "!%(BAD ENUM VALUE)";
  665. write_string(fi.buf, str);
  666. }
  667. }
  668. }
  669. enum_value_to_u64 :: proc(ev: runtime.Type_Info_Enum_Value) -> u64 {
  670. switch i in ev {
  671. case rune: return u64(i);
  672. case i8: return u64(i);
  673. case i16: return u64(i);
  674. case i32: return u64(i);
  675. case i64: return u64(i);
  676. case int: return u64(i);
  677. case u8: return u64(i);
  678. case u16: return u64(i);
  679. case u32: return u64(i);
  680. case u64: return u64(i);
  681. case uint: return u64(i);
  682. case uintptr: return u64(i);
  683. }
  684. return 0;
  685. }
  686. fmt_bit_set :: proc(fi: ^Fmt_Info, v: any, name: string = "") {
  687. type_info := type_info_of(v.typeid);
  688. switch info in type_info.variant {
  689. case runtime.Type_Info_Named:
  690. val := v;
  691. val.typeid = info.base.id;
  692. fmt_bit_set(fi, val, info.name);
  693. case runtime.Type_Info_Bit_Set:
  694. bits: u64;
  695. bit_size := u64(8*type_info.size);
  696. verb := 'b';
  697. switch bit_size {
  698. case 0: bits = 0;
  699. case 8: bits = u64( (^u8)(v.data)^);
  700. case 16: bits = u64((^u16)(v.data)^);
  701. case 32: bits = u64((^u32)(v.data)^);
  702. case 64: bits = u64((^u64)(v.data)^);
  703. case: panic("unknown bit_size size");
  704. }
  705. et := runtime.type_info_base(info.elem);
  706. if name != "" {
  707. write_string(fi.buf, name);
  708. } else {
  709. write_type(fi.buf, type_info);
  710. }
  711. write_byte(fi.buf, '{');
  712. defer write_byte(fi.buf, '}');
  713. e, is_enum := et.variant.(runtime.Type_Info_Enum);
  714. commas := 0;
  715. loop: for i in 0 .. bit_size-1 {
  716. if bits & (1<<i) == 0 {
  717. continue loop;
  718. }
  719. if commas > 0 do write_string(fi.buf, ", ");
  720. defer commas += 1;
  721. if is_enum do for ev, evi in e.values {
  722. v := enum_value_to_u64(ev);
  723. if v == i {
  724. write_string(fi.buf, e.names[evi]);
  725. continue loop;
  726. }
  727. }
  728. write_i64(fi.buf, i64(i), 10);
  729. }
  730. }
  731. }
  732. fmt_bit_field :: proc(fi: ^Fmt_Info, v: any, name: string = "") {
  733. type_info := type_info_of(v.typeid);
  734. switch info in type_info.variant {
  735. case runtime.Type_Info_Named:
  736. val := v;
  737. val.typeid = info.base.id;
  738. fmt_bit_field(fi, val, info.name);
  739. case runtime.Type_Info_Bit_Field:
  740. data: u64 = 0;
  741. switch type_info.size {
  742. case 1: data = cast(u64) (^u8)(v.data)^;
  743. case 2: data = cast(u64)(^u16)(v.data)^;
  744. case 4: data = cast(u64)(^u32)(v.data)^;
  745. case 8: data = cast(u64)(^u64)(v.data)^;
  746. }
  747. if name != "" {
  748. write_string(fi.buf, name);
  749. write_byte(fi.buf, '{');
  750. } else {
  751. write_string(fi.buf, "bit_field{");
  752. }
  753. for name, i in info.names {
  754. if i > 0 {
  755. write_string(fi.buf, ", ");
  756. }
  757. bits := u64(info.bits[i]);
  758. offset := u64(info.offsets[i]);
  759. write_string(fi.buf, name);
  760. write_string(fi.buf, " = ");
  761. n := 8*u64(size_of(u64));
  762. sa := n - bits;
  763. u := data>>offset;
  764. u <<= sa;
  765. u >>= sa;
  766. write_u64(fi.buf, u, 10);
  767. }
  768. write_byte(fi.buf, '}');
  769. case:
  770. write_string(fi.buf, "HERE");
  771. }
  772. }
  773. fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
  774. if v.data == nil || v.typeid == nil {
  775. write_string(fi.buf, "<nil>");
  776. return;
  777. }
  778. type_info := type_info_of(v.typeid);
  779. switch info in type_info.variant {
  780. case runtime.Type_Info_Named:
  781. switch b in info.base.variant {
  782. case runtime.Type_Info_Struct:
  783. if verb != 'v' {
  784. fmt_bad_verb(fi, verb);
  785. return;
  786. }
  787. if b.is_raw_union {
  788. write_string(fi.buf, info.name);
  789. write_string(fi.buf, "{}");
  790. return;
  791. };
  792. write_string(fi.buf, info.name);
  793. write_byte(fi.buf, '{');
  794. hash := fi.hash; defer fi.hash = hash;
  795. indent := fi.indent; defer fi.indent -= 1;
  796. fi.hash = false;
  797. fi.indent += 1;
  798. if hash do write_byte(fi.buf, '\n');
  799. for _, i in b.names {
  800. if !hash && i > 0 do write_string(fi.buf, ", ");
  801. if hash do for in 0..fi.indent-1 do write_byte(fi.buf, '\t');
  802. write_string(fi.buf, b.names[i]);
  803. write_string(fi.buf, " = ");
  804. if t := b.types[i]; types.is_any(t) {
  805. write_string(fi.buf, "any{}");
  806. } else {
  807. data := rawptr(uintptr(v.data) + b.offsets[i]);
  808. fmt_arg(fi, any{data, typeid_of(t)}, 'v');
  809. }
  810. if hash do write_string(fi.buf, ",\n");
  811. }
  812. if hash do for in 0..indent-1 do write_byte(fi.buf, '\t');
  813. write_byte(fi.buf, '}');
  814. case runtime.Type_Info_Bit_Set:
  815. fmt_bit_set(fi, v);
  816. case runtime.Type_Info_Bit_Field:
  817. fmt_bit_field(fi, v);
  818. case:
  819. fmt_value(fi, any{v.data, typeid_of(info.base)}, verb);
  820. }
  821. case runtime.Type_Info_Boolean: fmt_arg(fi, v, verb);
  822. case runtime.Type_Info_Integer: fmt_arg(fi, v, verb);
  823. case runtime.Type_Info_Rune: fmt_arg(fi, v, verb);
  824. case runtime.Type_Info_Float: fmt_arg(fi, v, verb);
  825. case runtime.Type_Info_Complex: fmt_arg(fi, v, verb);
  826. case runtime.Type_Info_String: fmt_arg(fi, v, verb);
  827. case runtime.Type_Info_Pointer:
  828. if v.typeid == typeid_of(^runtime.Type_Info) {
  829. write_type(fi.buf, (^^runtime.Type_Info)(v.data)^);
  830. } else {
  831. fmt_pointer(fi, (^rawptr)(v.data)^, verb);
  832. }
  833. case runtime.Type_Info_Array:
  834. write_byte(fi.buf, '[');
  835. defer write_byte(fi.buf, ']');
  836. for i in 0..info.count-1 {
  837. if i > 0 do write_string(fi.buf, ", ");
  838. data := uintptr(v.data) + uintptr(i*info.elem_size);
  839. fmt_arg(fi, any{rawptr(data), typeid_of(info.elem)}, verb);
  840. }
  841. case runtime.Type_Info_Dynamic_Array:
  842. write_byte(fi.buf, '[');
  843. defer write_byte(fi.buf, ']');
  844. array := cast(^mem.Raw_Dynamic_Array)v.data;
  845. for i in 0..array.len-1 {
  846. if i > 0 do write_string(fi.buf, ", ");
  847. data := uintptr(array.data) + uintptr(i*info.elem_size);
  848. fmt_arg(fi, any{rawptr(data), typeid_of(info.elem)}, verb);
  849. }
  850. case runtime.Type_Info_Slice:
  851. write_byte(fi.buf, '[');
  852. defer write_byte(fi.buf, ']');
  853. slice := cast(^mem.Raw_Slice)v.data;
  854. for i in 0..slice.len-1 {
  855. if i > 0 do write_string(fi.buf, ", ");
  856. data := uintptr(slice.data) + uintptr(i*info.elem_size);
  857. fmt_arg(fi, any{rawptr(data), typeid_of(info.elem)}, verb);
  858. }
  859. case runtime.Type_Info_Map:
  860. if verb != 'v' {
  861. fmt_bad_verb(fi, verb);
  862. return;
  863. }
  864. write_string(fi.buf, "map[");
  865. defer write_byte(fi.buf, ']');
  866. m := (^mem.Raw_Map)(v.data);
  867. if m != nil {
  868. assert(info.generated_struct != nil);
  869. entries := &m.entries;
  870. gs := runtime.type_info_base(info.generated_struct).variant.(runtime.Type_Info_Struct);
  871. ed := runtime.type_info_base(gs.types[1]).variant.(runtime.Type_Info_Dynamic_Array);
  872. entry_type := ed.elem.variant.(runtime.Type_Info_Struct);
  873. entry_size := ed.elem_size;
  874. for i in 0..entries.len-1 {
  875. if i > 0 do write_string(fi.buf, ", ");
  876. data := uintptr(entries.data) + uintptr(i*entry_size);
  877. header := cast(^runtime.Map_Entry_Header)data;
  878. if types.is_string(info.key) {
  879. write_string(fi.buf, header.key.str);
  880. } else {
  881. fi := Fmt_Info{buf = fi.buf};
  882. fmt_arg(&fi, any{rawptr(&header.key.hash), typeid_of(info.key)}, 'v');
  883. }
  884. write_string(fi.buf, "=");
  885. value := data + entry_type.offsets[2];
  886. fmt_arg(fi, any{rawptr(value), typeid_of(info.value)}, 'v');
  887. }
  888. }
  889. case runtime.Type_Info_Struct:
  890. if info.is_raw_union {
  891. write_string(fi.buf, "(raw_union)");
  892. return;
  893. }
  894. write_byte(fi.buf, '{');
  895. defer write_byte(fi.buf, '}');
  896. fi.indent += 1; defer fi.indent -= 1;
  897. hash := fi.hash; defer fi.hash = hash;
  898. fi.hash = false;
  899. if hash do write_byte(fi.buf, '\n');
  900. for _, i in info.names {
  901. if !hash && i > 0 do write_string(fi.buf, ", ");
  902. if hash {
  903. for in 0..fi.indent-1 {
  904. write_byte(fi.buf, '\t');
  905. }
  906. }
  907. write_string(fi.buf, info.names[i]);
  908. write_string(fi.buf, " = ");
  909. if t := info.types[i]; types.is_any(t) {
  910. write_string(fi.buf, "any{}");
  911. } else {
  912. data := uintptr(v.data) + info.offsets[i];
  913. fmt_arg(fi, any{rawptr(data), typeid_of(t)}, 'v');
  914. }
  915. if hash do write_string(fi.buf, ",\n");
  916. }
  917. case runtime.Type_Info_Union:
  918. tag_ptr := uintptr(v.data) + info.tag_offset;
  919. tag_any := any{rawptr(tag_ptr), typeid_of(info.tag_type)};
  920. tag: i64 = -1;
  921. switch i in tag_any {
  922. case u8: tag = i64(i);
  923. case i8: tag = i64(i);
  924. case u16: tag = i64(i);
  925. case i16: tag = i64(i);
  926. case u32: tag = i64(i);
  927. case i32: tag = i64(i);
  928. case u64: tag = i64(i);
  929. case i64: tag = i64(i);
  930. case: panic("Invalid union tag type");
  931. }
  932. if v.data == nil || tag == 0 {
  933. write_string(fi.buf, "nil");
  934. } else {
  935. id := typeid_of(info.variants[tag-1]);
  936. fmt_arg(fi, any{v.data, id}, verb);
  937. }
  938. case runtime.Type_Info_Enum:
  939. fmt_enum(fi, v, verb);
  940. case runtime.Type_Info_Procedure:
  941. ptr := (^rawptr)(v.data)^;
  942. if ptr == nil {
  943. write_string(fi.buf, "nil");
  944. } else {
  945. write_typeid(fi.buf, v.typeid);
  946. write_string(fi.buf, " @ ");
  947. fmt_pointer(fi, ptr, 'p');
  948. }
  949. case runtime.Type_Info_Type_Id:
  950. id := (^typeid)(v.data)^;
  951. write_typeid(fi.buf, id);
  952. case runtime.Type_Info_Bit_Field:
  953. fmt_bit_field(fi, v);
  954. case runtime.Type_Info_Bit_Set:
  955. fmt_bit_set(fi, v);
  956. }
  957. }
  958. fmt_complex :: proc(fi: ^Fmt_Info, c: complex128, bits: int, verb: rune) {
  959. switch verb {
  960. case 'f', 'F', 'v':
  961. r, i := real(c), imag(c);
  962. fmt_float(fi, r, bits/2, verb);
  963. if !fi.plus && i >= 0 {
  964. write_rune(fi.buf, '+');
  965. }
  966. fmt_float(fi, i, bits/2, verb);
  967. write_rune(fi.buf, 'i');
  968. case:
  969. fmt_bad_verb(fi, verb);
  970. return;
  971. }
  972. }
  973. fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) {
  974. if arg == nil {
  975. write_string(fi.buf, "<nil>");
  976. return;
  977. }
  978. fi.arg = arg;
  979. if verb == 'T' {
  980. ti := type_info_of(arg.typeid);
  981. switch a in arg {
  982. case ^runtime.Type_Info: ti = a;
  983. }
  984. write_type(fi.buf, ti);
  985. return;
  986. }
  987. base_arg := arg;
  988. base_arg.typeid = runtime.typeid_base(base_arg.typeid);
  989. switch a in base_arg {
  990. case bool: fmt_bool(fi, bool(a), verb);
  991. case b8: fmt_bool(fi, bool(a), verb);
  992. case b16: fmt_bool(fi, bool(a), verb);
  993. case b32: fmt_bool(fi, bool(a), verb);
  994. case b64: fmt_bool(fi, bool(a), verb);
  995. case any: fmt_arg(fi, a, verb);
  996. case rune: fmt_rune(fi, a, verb);
  997. case f32: fmt_float(fi, f64(a), 32, verb);
  998. case f64: fmt_float(fi, a, 64, verb);
  999. case complex64: fmt_complex(fi, complex128(a), 64, verb);
  1000. case complex128: fmt_complex(fi, a, 128, verb);
  1001. case i8: fmt_int(fi, u64(a), true, 8, verb);
  1002. case u8: fmt_int(fi, u64(a), false, 8, verb);
  1003. case i16: fmt_int(fi, u64(a), true, 16, verb);
  1004. case u16: fmt_int(fi, u64(a), false, 16, verb);
  1005. case i32: fmt_int(fi, u64(a), true, 32, verb);
  1006. case u32: fmt_int(fi, u64(a), false, 32, verb);
  1007. case i64: fmt_int(fi, u64(a), true, 64, verb);
  1008. case u64: fmt_int(fi, u64(a), false, 64, verb);
  1009. case int: fmt_int(fi, u64(a), true, 8*size_of(int), verb);
  1010. case uint: fmt_int(fi, u64(a), false, 8*size_of(uint), verb);
  1011. case uintptr: fmt_int(fi, u64(a), false, 8*size_of(uintptr), verb);
  1012. case string: fmt_string(fi, a, verb);
  1013. case cstring: fmt_cstring(fi, a, verb);
  1014. case typeid: write_typeid(fi.buf, a);
  1015. case: fmt_value(fi, arg, verb);
  1016. }
  1017. }
  1018. sbprint :: proc(buf: ^String_Buffer, args: ..any) -> string {
  1019. fi: Fmt_Info;
  1020. prev_string := false;
  1021. fi.buf = buf;
  1022. for arg, i in args {
  1023. is_string := arg != nil && types.is_string(type_info_of(arg.typeid));
  1024. if i > 0 && !is_string && !prev_string {
  1025. write_byte(buf, ' ');
  1026. }
  1027. fmt_value(&fi, args[i], 'v');
  1028. prev_string = is_string;
  1029. }
  1030. return to_string(buf^);
  1031. }
  1032. sbprintln :: proc(buf: ^String_Buffer, args: ..any) -> string {
  1033. fi: Fmt_Info;
  1034. fi.buf = buf;
  1035. for _, i in args {
  1036. if i > 0 do write_byte(buf, ' ');
  1037. fmt_value(&fi, args[i], 'v');
  1038. }
  1039. write_byte(buf, '\n');
  1040. return to_string(buf^);
  1041. }
  1042. sbprintf :: proc(b: ^String_Buffer, fmt: string, args: ..any) -> string {
  1043. fi: Fmt_Info;
  1044. arg_index: int = 0;
  1045. end := len(fmt);
  1046. was_prev_index := false;
  1047. loop: for i := 0; i < end; /**/ {
  1048. fi = Fmt_Info{buf = b, good_arg_index = true};
  1049. prev_i := i;
  1050. for i < end && fmt[i] != '%' {
  1051. i += 1;
  1052. }
  1053. if i > prev_i {
  1054. write_string(b, fmt[prev_i:i]);
  1055. }
  1056. if i >= end {
  1057. break loop;
  1058. }
  1059. // Process a "verb"
  1060. i += 1;
  1061. prefix_loop: for ; i < end; i += 1 {
  1062. switch fmt[i] {
  1063. case '+':
  1064. fi.plus = true;
  1065. case '-':
  1066. fi.minus = true;
  1067. fi.zero = false;
  1068. case ' ':
  1069. fi.space = true;
  1070. case '#':
  1071. fi.hash = true;
  1072. case '0':
  1073. fi.zero = !fi.minus;
  1074. case:
  1075. break prefix_loop;
  1076. }
  1077. }
  1078. arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args));
  1079. // Width
  1080. if i < end && fmt[i] == '*' {
  1081. i += 1;
  1082. fi.width, arg_index, fi.width_set = int_from_arg(args, arg_index);
  1083. if !fi.width_set {
  1084. write_string(b, "%!(BAD WIDTH)");
  1085. }
  1086. if fi.width < 0 {
  1087. fi.width = -fi.width;
  1088. fi.minus = true;
  1089. fi.zero = false;
  1090. }
  1091. was_prev_index = false;
  1092. } else {
  1093. fi.width, i, fi.width_set = _parse_int(fmt, i);
  1094. if was_prev_index && fi.width_set { // %[6]2d
  1095. fi.good_arg_index = false;
  1096. }
  1097. }
  1098. // Precision
  1099. if i < end && fmt[i] == '.' {
  1100. i += 1;
  1101. if was_prev_index { // %[6].2d
  1102. fi.good_arg_index = false;
  1103. }
  1104. if i < end && fmt[i] == '*' {
  1105. arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args));
  1106. i += 1;
  1107. fi.prec, arg_index, fi.prec_set = int_from_arg(args, arg_index);
  1108. if fi.prec < 0 {
  1109. fi.prec = 0;
  1110. fi.prec_set = false;
  1111. }
  1112. if !fi.prec_set {
  1113. write_string(fi.buf, "%!(BAD PRECISION)");
  1114. }
  1115. was_prev_index = false;
  1116. } else {
  1117. fi.prec, i, fi.prec_set = _parse_int(fmt, i);
  1118. if !fi.prec_set {
  1119. // fi.prec_set = true;
  1120. // fi.prec = 0;
  1121. }
  1122. }
  1123. }
  1124. if !was_prev_index {
  1125. arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args));
  1126. }
  1127. if i >= end {
  1128. write_string(b, "%!(NO VERB)");
  1129. break loop;
  1130. }
  1131. verb, w := utf8.decode_rune_from_string(fmt[i:]);
  1132. i += w;
  1133. switch {
  1134. case verb == '%':
  1135. write_byte(b, '%');
  1136. case !fi.good_arg_index:
  1137. write_string(b, "%!(BAD ARGUMENT NUMBER)");
  1138. case arg_index >= len(args):
  1139. write_string(b, "%!(MISSING ARGUMENT)");
  1140. case:
  1141. fmt_arg(&fi, args[arg_index], verb);
  1142. arg_index += 1;
  1143. }
  1144. }
  1145. if !fi.reordered && arg_index < len(args) {
  1146. write_string(b, "%!(EXTRA ");
  1147. for arg, index in args[arg_index:] {
  1148. if index > 0 do write_string(b, ", ");
  1149. if arg == nil do write_string(b, "<nil>");
  1150. else do fmt_arg(&fi, args[index], 'v');
  1151. }
  1152. write_string(b, ")");
  1153. }
  1154. return to_string(b^);
  1155. }