fmt.odin 27 KB

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