1use std::collections::HashMap;
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
30pub enum StdHeader {
31 Assert, Ctype, Errno, Float, Limits, Locale, Math, Setjmp, Signal, Stdarg, Stdbool, Stddef, Stdint, Stdio, Stdlib, String, Time, Unistd, Fcntl, Dirent, SysTypes, SysStat, SysMman, Wchar, }
57
58impl StdHeader {
59 pub fn from_filename(filename: &str) -> Option<Self> {
69 match filename {
70 "assert.h" => Some(Self::Assert),
71 "ctype.h" => Some(Self::Ctype),
72 "errno.h" => Some(Self::Errno),
73 "float.h" => Some(Self::Float),
74 "limits.h" => Some(Self::Limits),
75 "locale.h" => Some(Self::Locale),
76 "math.h" => Some(Self::Math),
77 "setjmp.h" => Some(Self::Setjmp),
78 "signal.h" => Some(Self::Signal),
79 "stdarg.h" => Some(Self::Stdarg),
80 "stdbool.h" => Some(Self::Stdbool),
81 "stddef.h" => Some(Self::Stddef),
82 "stdint.h" => Some(Self::Stdint),
83 "stdio.h" => Some(Self::Stdio),
84 "stdlib.h" => Some(Self::Stdlib),
85 "string.h" => Some(Self::String),
86 "time.h" => Some(Self::Time),
87 "unistd.h" => Some(Self::Unistd),
89 "fcntl.h" => Some(Self::Fcntl),
90 "dirent.h" => Some(Self::Dirent),
91 "sys/types.h" => Some(Self::SysTypes),
92 "sys/stat.h" => Some(Self::SysStat),
93 "sys/mman.h" => Some(Self::SysMman),
94 "wchar.h" => Some(Self::Wchar),
95 _ => None,
96 }
97 }
98}
99
100#[derive(Debug, Clone, PartialEq, Eq)]
102pub struct Parameter {
103 pub name: String,
104 pub type_str: String,
105}
106
107impl Parameter {
108 pub fn new(name: impl Into<String>, type_str: impl Into<String>) -> Self {
109 Self {
110 name: name.into(),
111 type_str: type_str.into(),
112 }
113 }
114}
115
116#[derive(Debug, Clone, PartialEq, Eq)]
118pub struct FunctionProto {
119 pub name: String,
120 pub return_type: String,
121 pub parameters: Vec<Parameter>,
122 pub is_variadic: bool,
123 pub header: StdHeader,
124 pub c99_section: String,
125}
126
127impl FunctionProto {
128 pub fn to_c_declaration(&self) -> String {
130 let params = if self.parameters.is_empty() {
131 "void".to_string()
132 } else {
133 let mut p = self
134 .parameters
135 .iter()
136 .map(|param| format!("{} {}", param.type_str, param.name))
137 .collect::<Vec<_>>()
138 .join(", ");
139
140 if self.is_variadic {
141 p.push_str(", ...");
142 }
143
144 p
145 };
146
147 format!("{} {}({});", self.return_type, self.name, params)
148 }
149}
150
151pub struct StdlibPrototypes {
155 functions: HashMap<String, FunctionProto>,
156}
157
158impl StdlibPrototypes {
159 pub fn new() -> Self {
161 let mut functions = HashMap::new();
162
163 functions.insert(
169 "malloc".to_string(),
170 FunctionProto {
171 name: "malloc".to_string(),
172 return_type: "void*".to_string(),
173 parameters: vec![Parameter::new("size", "size_t")],
174 is_variadic: false,
175 header: StdHeader::Stdlib,
176 c99_section: "§7.22.3.4".to_string(),
177 },
178 );
179
180 functions.insert(
181 "calloc".to_string(),
182 FunctionProto {
183 name: "calloc".to_string(),
184 return_type: "void*".to_string(),
185 parameters: vec![
186 Parameter::new("nmemb", "size_t"),
187 Parameter::new("size", "size_t"),
188 ],
189 is_variadic: false,
190 header: StdHeader::Stdlib,
191 c99_section: "§7.22.3.2".to_string(),
192 },
193 );
194
195 functions.insert(
196 "realloc".to_string(),
197 FunctionProto {
198 name: "realloc".to_string(),
199 return_type: "void*".to_string(),
200 parameters: vec![
201 Parameter::new("ptr", "void*"),
202 Parameter::new("size", "size_t"),
203 ],
204 is_variadic: false,
205 header: StdHeader::Stdlib,
206 c99_section: "§7.22.3.5".to_string(),
207 },
208 );
209
210 functions.insert(
211 "free".to_string(),
212 FunctionProto {
213 name: "free".to_string(),
214 return_type: "void".to_string(),
215 parameters: vec![Parameter::new("ptr", "void*")],
216 is_variadic: false,
217 header: StdHeader::Stdlib,
218 c99_section: "§7.22.3.3".to_string(),
219 },
220 );
221
222 functions.insert(
224 "rand".to_string(),
225 FunctionProto {
226 name: "rand".to_string(),
227 return_type: "int".to_string(),
228 parameters: vec![],
229 is_variadic: false,
230 header: StdHeader::Stdlib,
231 c99_section: "§7.22.2.1".to_string(),
232 },
233 );
234
235 functions.insert(
236 "srand".to_string(),
237 FunctionProto {
238 name: "srand".to_string(),
239 return_type: "void".to_string(),
240 parameters: vec![Parameter::new("seed", "unsigned int")],
241 is_variadic: false,
242 header: StdHeader::Stdlib,
243 c99_section: "§7.22.2.2".to_string(),
244 },
245 );
246
247 functions.insert(
249 "atoi".to_string(),
250 FunctionProto {
251 name: "atoi".to_string(),
252 return_type: "int".to_string(),
253 parameters: vec![Parameter::new("nptr", "const char*")],
254 is_variadic: false,
255 header: StdHeader::Stdlib,
256 c99_section: "§7.22.1.2".to_string(),
257 },
258 );
259
260 functions.insert(
261 "atol".to_string(),
262 FunctionProto {
263 name: "atol".to_string(),
264 return_type: "long".to_string(),
265 parameters: vec![Parameter::new("nptr", "const char*")],
266 is_variadic: false,
267 header: StdHeader::Stdlib,
268 c99_section: "§7.22.1.3".to_string(),
269 },
270 );
271
272 functions.insert(
273 "atof".to_string(),
274 FunctionProto {
275 name: "atof".to_string(),
276 return_type: "double".to_string(),
277 parameters: vec![Parameter::new("nptr", "const char*")],
278 is_variadic: false,
279 header: StdHeader::Stdlib,
280 c99_section: "§7.22.1.1".to_string(),
281 },
282 );
283
284 functions.insert(
285 "strtol".to_string(),
286 FunctionProto {
287 name: "strtol".to_string(),
288 return_type: "long".to_string(),
289 parameters: vec![
290 Parameter::new("nptr", "const char*"),
291 Parameter::new("endptr", "char**"),
292 Parameter::new("base", "int"),
293 ],
294 is_variadic: false,
295 header: StdHeader::Stdlib,
296 c99_section: "§7.22.1.4".to_string(),
297 },
298 );
299
300 functions.insert(
301 "strtod".to_string(),
302 FunctionProto {
303 name: "strtod".to_string(),
304 return_type: "double".to_string(),
305 parameters: vec![
306 Parameter::new("nptr", "const char*"),
307 Parameter::new("endptr", "char**"),
308 ],
309 is_variadic: false,
310 header: StdHeader::Stdlib,
311 c99_section: "§7.22.1.3".to_string(),
312 },
313 );
314
315 functions.insert(
317 "exit".to_string(),
318 FunctionProto {
319 name: "exit".to_string(),
320 return_type: "void".to_string(),
321 parameters: vec![Parameter::new("status", "int")],
322 is_variadic: false,
323 header: StdHeader::Stdlib,
324 c99_section: "§7.22.4.4".to_string(),
325 },
326 );
327
328 functions.insert(
329 "abort".to_string(),
330 FunctionProto {
331 name: "abort".to_string(),
332 return_type: "void".to_string(),
333 parameters: vec![],
334 is_variadic: false,
335 header: StdHeader::Stdlib,
336 c99_section: "§7.22.4.1".to_string(),
337 },
338 );
339
340 functions.insert(
341 "getenv".to_string(),
342 FunctionProto {
343 name: "getenv".to_string(),
344 return_type: "char*".to_string(),
345 parameters: vec![Parameter::new("name", "const char*")],
346 is_variadic: false,
347 header: StdHeader::Stdlib,
348 c99_section: "§7.22.4.6".to_string(),
349 },
350 );
351
352 functions.insert(
353 "system".to_string(),
354 FunctionProto {
355 name: "system".to_string(),
356 return_type: "int".to_string(),
357 parameters: vec![Parameter::new("command", "const char*")],
358 is_variadic: false,
359 header: StdHeader::Stdlib,
360 c99_section: "§7.22.4.8".to_string(),
361 },
362 );
363
364 functions.insert(
366 "qsort".to_string(),
367 FunctionProto {
368 name: "qsort".to_string(),
369 return_type: "void".to_string(),
370 parameters: vec![
371 Parameter::new("base", "void*"),
372 Parameter::new("nmemb", "size_t"),
373 Parameter::new("size", "size_t"),
374 Parameter::new("compar", "int (*)(const void*, const void*)"),
375 ],
376 is_variadic: false,
377 header: StdHeader::Stdlib,
378 c99_section: "§7.22.5.2".to_string(),
379 },
380 );
381
382 functions.insert(
383 "bsearch".to_string(),
384 FunctionProto {
385 name: "bsearch".to_string(),
386 return_type: "void*".to_string(),
387 parameters: vec![
388 Parameter::new("key", "const void*"),
389 Parameter::new("base", "const void*"),
390 Parameter::new("nmemb", "size_t"),
391 Parameter::new("size", "size_t"),
392 Parameter::new("compar", "int (*)(const void*, const void*)"),
393 ],
394 is_variadic: false,
395 header: StdHeader::Stdlib,
396 c99_section: "§7.22.5.1".to_string(),
397 },
398 );
399
400 functions.insert(
402 "abs".to_string(),
403 FunctionProto {
404 name: "abs".to_string(),
405 return_type: "int".to_string(),
406 parameters: vec![Parameter::new("j", "int")],
407 is_variadic: false,
408 header: StdHeader::Stdlib,
409 c99_section: "§7.22.6.1".to_string(),
410 },
411 );
412
413 functions.insert(
414 "labs".to_string(),
415 FunctionProto {
416 name: "labs".to_string(),
417 return_type: "long".to_string(),
418 parameters: vec![Parameter::new("j", "long")],
419 is_variadic: false,
420 header: StdHeader::Stdlib,
421 c99_section: "§7.22.6.1".to_string(),
422 },
423 );
424
425 functions.insert(
431 "printf".to_string(),
432 FunctionProto {
433 name: "printf".to_string(),
434 return_type: "int".to_string(),
435 parameters: vec![Parameter::new("format", "const char*")],
436 is_variadic: true,
437 header: StdHeader::Stdio,
438 c99_section: "§7.21.6.1".to_string(),
439 },
440 );
441
442 functions.insert(
443 "fprintf".to_string(),
444 FunctionProto {
445 name: "fprintf".to_string(),
446 return_type: "int".to_string(),
447 parameters: vec![
448 Parameter::new("stream", "FILE*"),
449 Parameter::new("format", "const char*"),
450 ],
451 is_variadic: true,
452 header: StdHeader::Stdio,
453 c99_section: "§7.21.6.1".to_string(),
454 },
455 );
456
457 functions.insert(
458 "sprintf".to_string(),
459 FunctionProto {
460 name: "sprintf".to_string(),
461 return_type: "int".to_string(),
462 parameters: vec![
463 Parameter::new("str", "char*"),
464 Parameter::new("format", "const char*"),
465 ],
466 is_variadic: true,
467 header: StdHeader::Stdio,
468 c99_section: "§7.21.6.5".to_string(),
469 },
470 );
471
472 functions.insert(
473 "snprintf".to_string(),
474 FunctionProto {
475 name: "snprintf".to_string(),
476 return_type: "int".to_string(),
477 parameters: vec![
478 Parameter::new("str", "char*"),
479 Parameter::new("size", "size_t"),
480 Parameter::new("format", "const char*"),
481 ],
482 is_variadic: true,
483 header: StdHeader::Stdio,
484 c99_section: "§7.21.6.5".to_string(),
485 },
486 );
487
488 functions.insert(
490 "scanf".to_string(),
491 FunctionProto {
492 name: "scanf".to_string(),
493 return_type: "int".to_string(),
494 parameters: vec![Parameter::new("format", "const char*")],
495 is_variadic: true,
496 header: StdHeader::Stdio,
497 c99_section: "§7.21.6.2".to_string(),
498 },
499 );
500
501 functions.insert(
502 "fscanf".to_string(),
503 FunctionProto {
504 name: "fscanf".to_string(),
505 return_type: "int".to_string(),
506 parameters: vec![
507 Parameter::new("stream", "FILE*"),
508 Parameter::new("format", "const char*"),
509 ],
510 is_variadic: true,
511 header: StdHeader::Stdio,
512 c99_section: "§7.21.6.2".to_string(),
513 },
514 );
515
516 functions.insert(
517 "sscanf".to_string(),
518 FunctionProto {
519 name: "sscanf".to_string(),
520 return_type: "int".to_string(),
521 parameters: vec![
522 Parameter::new("str", "const char*"),
523 Parameter::new("format", "const char*"),
524 ],
525 is_variadic: true,
526 header: StdHeader::Stdio,
527 c99_section: "§7.21.6.4".to_string(),
528 },
529 );
530
531 functions.insert(
533 "fopen".to_string(),
534 FunctionProto {
535 name: "fopen".to_string(),
536 return_type: "FILE*".to_string(),
537 parameters: vec![
538 Parameter::new("filename", "const char*"),
539 Parameter::new("mode", "const char*"),
540 ],
541 is_variadic: false,
542 header: StdHeader::Stdio,
543 c99_section: "§7.21.5.3".to_string(),
544 },
545 );
546
547 functions.insert(
548 "fclose".to_string(),
549 FunctionProto {
550 name: "fclose".to_string(),
551 return_type: "int".to_string(),
552 parameters: vec![Parameter::new("stream", "FILE*")],
553 is_variadic: false,
554 header: StdHeader::Stdio,
555 c99_section: "§7.21.5.1".to_string(),
556 },
557 );
558
559 functions.insert(
560 "fread".to_string(),
561 FunctionProto {
562 name: "fread".to_string(),
563 return_type: "size_t".to_string(),
564 parameters: vec![
565 Parameter::new("ptr", "void*"),
566 Parameter::new("size", "size_t"),
567 Parameter::new("nmemb", "size_t"),
568 Parameter::new("stream", "FILE*"),
569 ],
570 is_variadic: false,
571 header: StdHeader::Stdio,
572 c99_section: "§7.21.8.1".to_string(),
573 },
574 );
575
576 functions.insert(
577 "fwrite".to_string(),
578 FunctionProto {
579 name: "fwrite".to_string(),
580 return_type: "size_t".to_string(),
581 parameters: vec![
582 Parameter::new("ptr", "const void*"),
583 Parameter::new("size", "size_t"),
584 Parameter::new("nmemb", "size_t"),
585 Parameter::new("stream", "FILE*"),
586 ],
587 is_variadic: false,
588 header: StdHeader::Stdio,
589 c99_section: "§7.21.8.2".to_string(),
590 },
591 );
592
593 functions.insert(
594 "fseek".to_string(),
595 FunctionProto {
596 name: "fseek".to_string(),
597 return_type: "int".to_string(),
598 parameters: vec![
599 Parameter::new("stream", "FILE*"),
600 Parameter::new("offset", "long"),
601 Parameter::new("whence", "int"),
602 ],
603 is_variadic: false,
604 header: StdHeader::Stdio,
605 c99_section: "§7.21.9.2".to_string(),
606 },
607 );
608
609 functions.insert(
610 "ftell".to_string(),
611 FunctionProto {
612 name: "ftell".to_string(),
613 return_type: "long".to_string(),
614 parameters: vec![Parameter::new("stream", "FILE*")],
615 is_variadic: false,
616 header: StdHeader::Stdio,
617 c99_section: "§7.21.9.4".to_string(),
618 },
619 );
620
621 functions.insert(
622 "rewind".to_string(),
623 FunctionProto {
624 name: "rewind".to_string(),
625 return_type: "void".to_string(),
626 parameters: vec![Parameter::new("stream", "FILE*")],
627 is_variadic: false,
628 header: StdHeader::Stdio,
629 c99_section: "§7.21.9.3".to_string(),
630 },
631 );
632
633 functions.insert(
635 "getchar".to_string(),
636 FunctionProto {
637 name: "getchar".to_string(),
638 return_type: "int".to_string(),
639 parameters: vec![],
640 is_variadic: false,
641 header: StdHeader::Stdio,
642 c99_section: "§7.21.7.6".to_string(),
643 },
644 );
645
646 functions.insert(
647 "putchar".to_string(),
648 FunctionProto {
649 name: "putchar".to_string(),
650 return_type: "int".to_string(),
651 parameters: vec![Parameter::new("c", "int")],
652 is_variadic: false,
653 header: StdHeader::Stdio,
654 c99_section: "§7.21.7.8".to_string(),
655 },
656 );
657
658 functions.insert(
659 "fgetc".to_string(),
660 FunctionProto {
661 name: "fgetc".to_string(),
662 return_type: "int".to_string(),
663 parameters: vec![Parameter::new("stream", "FILE*")],
664 is_variadic: false,
665 header: StdHeader::Stdio,
666 c99_section: "§7.21.7.1".to_string(),
667 },
668 );
669
670 functions.insert(
671 "fputc".to_string(),
672 FunctionProto {
673 name: "fputc".to_string(),
674 return_type: "int".to_string(),
675 parameters: vec![
676 Parameter::new("c", "int"),
677 Parameter::new("stream", "FILE*"),
678 ],
679 is_variadic: false,
680 header: StdHeader::Stdio,
681 c99_section: "§7.21.7.3".to_string(),
682 },
683 );
684
685 functions.insert(
686 "fgets".to_string(),
687 FunctionProto {
688 name: "fgets".to_string(),
689 return_type: "char*".to_string(),
690 parameters: vec![
691 Parameter::new("s", "char*"),
692 Parameter::new("size", "int"),
693 Parameter::new("stream", "FILE*"),
694 ],
695 is_variadic: false,
696 header: StdHeader::Stdio,
697 c99_section: "§7.21.7.2".to_string(),
698 },
699 );
700
701 functions.insert(
702 "fputs".to_string(),
703 FunctionProto {
704 name: "fputs".to_string(),
705 return_type: "int".to_string(),
706 parameters: vec![
707 Parameter::new("s", "const char*"),
708 Parameter::new("stream", "FILE*"),
709 ],
710 is_variadic: false,
711 header: StdHeader::Stdio,
712 c99_section: "§7.21.7.4".to_string(),
713 },
714 );
715
716 functions.insert(
717 "puts".to_string(),
718 FunctionProto {
719 name: "puts".to_string(),
720 return_type: "int".to_string(),
721 parameters: vec![Parameter::new("s", "const char*")],
722 is_variadic: false,
723 header: StdHeader::Stdio,
724 c99_section: "§7.21.7.9".to_string(),
725 },
726 );
727
728 functions.insert(
734 "memcpy".to_string(),
735 FunctionProto {
736 name: "memcpy".to_string(),
737 return_type: "void*".to_string(),
738 parameters: vec![
739 Parameter::new("dest", "void*"),
740 Parameter::new("src", "const void*"),
741 Parameter::new("n", "size_t"),
742 ],
743 is_variadic: false,
744 header: StdHeader::String,
745 c99_section: "§7.23.2.1".to_string(),
746 },
747 );
748
749 functions.insert(
750 "memmove".to_string(),
751 FunctionProto {
752 name: "memmove".to_string(),
753 return_type: "void*".to_string(),
754 parameters: vec![
755 Parameter::new("dest", "void*"),
756 Parameter::new("src", "const void*"),
757 Parameter::new("n", "size_t"),
758 ],
759 is_variadic: false,
760 header: StdHeader::String,
761 c99_section: "§7.23.2.2".to_string(),
762 },
763 );
764
765 functions.insert(
766 "strcpy".to_string(),
767 FunctionProto {
768 name: "strcpy".to_string(),
769 return_type: "char*".to_string(),
770 parameters: vec![
771 Parameter::new("dest", "char*"),
772 Parameter::new("src", "const char*"),
773 ],
774 is_variadic: false,
775 header: StdHeader::String,
776 c99_section: "§7.23.2.3".to_string(),
777 },
778 );
779
780 functions.insert(
781 "strncpy".to_string(),
782 FunctionProto {
783 name: "strncpy".to_string(),
784 return_type: "char*".to_string(),
785 parameters: vec![
786 Parameter::new("dest", "char*"),
787 Parameter::new("src", "const char*"),
788 Parameter::new("n", "size_t"),
789 ],
790 is_variadic: false,
791 header: StdHeader::String,
792 c99_section: "§7.23.2.4".to_string(),
793 },
794 );
795
796 functions.insert(
798 "strcat".to_string(),
799 FunctionProto {
800 name: "strcat".to_string(),
801 return_type: "char*".to_string(),
802 parameters: vec![
803 Parameter::new("dest", "char*"),
804 Parameter::new("src", "const char*"),
805 ],
806 is_variadic: false,
807 header: StdHeader::String,
808 c99_section: "§7.23.3.1".to_string(),
809 },
810 );
811
812 functions.insert(
813 "strncat".to_string(),
814 FunctionProto {
815 name: "strncat".to_string(),
816 return_type: "char*".to_string(),
817 parameters: vec![
818 Parameter::new("dest", "char*"),
819 Parameter::new("src", "const char*"),
820 Parameter::new("n", "size_t"),
821 ],
822 is_variadic: false,
823 header: StdHeader::String,
824 c99_section: "§7.23.3.2".to_string(),
825 },
826 );
827
828 functions.insert(
830 "memcmp".to_string(),
831 FunctionProto {
832 name: "memcmp".to_string(),
833 return_type: "int".to_string(),
834 parameters: vec![
835 Parameter::new("s1", "const void*"),
836 Parameter::new("s2", "const void*"),
837 Parameter::new("n", "size_t"),
838 ],
839 is_variadic: false,
840 header: StdHeader::String,
841 c99_section: "§7.23.4.1".to_string(),
842 },
843 );
844
845 functions.insert(
846 "strcmp".to_string(),
847 FunctionProto {
848 name: "strcmp".to_string(),
849 return_type: "int".to_string(),
850 parameters: vec![
851 Parameter::new("s1", "const char*"),
852 Parameter::new("s2", "const char*"),
853 ],
854 is_variadic: false,
855 header: StdHeader::String,
856 c99_section: "§7.23.4.2".to_string(),
857 },
858 );
859
860 functions.insert(
861 "strncmp".to_string(),
862 FunctionProto {
863 name: "strncmp".to_string(),
864 return_type: "int".to_string(),
865 parameters: vec![
866 Parameter::new("s1", "const char*"),
867 Parameter::new("s2", "const char*"),
868 Parameter::new("n", "size_t"),
869 ],
870 is_variadic: false,
871 header: StdHeader::String,
872 c99_section: "§7.23.4.4".to_string(),
873 },
874 );
875
876 functions.insert(
878 "memchr".to_string(),
879 FunctionProto {
880 name: "memchr".to_string(),
881 return_type: "void*".to_string(),
882 parameters: vec![
883 Parameter::new("s", "const void*"),
884 Parameter::new("c", "int"),
885 Parameter::new("n", "size_t"),
886 ],
887 is_variadic: false,
888 header: StdHeader::String,
889 c99_section: "§7.23.5.1".to_string(),
890 },
891 );
892
893 functions.insert(
894 "strchr".to_string(),
895 FunctionProto {
896 name: "strchr".to_string(),
897 return_type: "char*".to_string(),
898 parameters: vec![
899 Parameter::new("s", "const char*"),
900 Parameter::new("c", "int"),
901 ],
902 is_variadic: false,
903 header: StdHeader::String,
904 c99_section: "§7.23.5.2".to_string(),
905 },
906 );
907
908 functions.insert(
909 "strrchr".to_string(),
910 FunctionProto {
911 name: "strrchr".to_string(),
912 return_type: "char*".to_string(),
913 parameters: vec![
914 Parameter::new("s", "const char*"),
915 Parameter::new("c", "int"),
916 ],
917 is_variadic: false,
918 header: StdHeader::String,
919 c99_section: "§7.23.5.5".to_string(),
920 },
921 );
922
923 functions.insert(
924 "strstr".to_string(),
925 FunctionProto {
926 name: "strstr".to_string(),
927 return_type: "char*".to_string(),
928 parameters: vec![
929 Parameter::new("haystack", "const char*"),
930 Parameter::new("needle", "const char*"),
931 ],
932 is_variadic: false,
933 header: StdHeader::String,
934 c99_section: "§7.23.5.7".to_string(),
935 },
936 );
937
938 functions.insert(
939 "strtok".to_string(),
940 FunctionProto {
941 name: "strtok".to_string(),
942 return_type: "char*".to_string(),
943 parameters: vec![
944 Parameter::new("str", "char*"),
945 Parameter::new("delim", "const char*"),
946 ],
947 is_variadic: false,
948 header: StdHeader::String,
949 c99_section: "§7.23.5.8".to_string(),
950 },
951 );
952
953 functions.insert(
955 "memset".to_string(),
956 FunctionProto {
957 name: "memset".to_string(),
958 return_type: "void*".to_string(),
959 parameters: vec![
960 Parameter::new("s", "void*"),
961 Parameter::new("c", "int"),
962 Parameter::new("n", "size_t"),
963 ],
964 is_variadic: false,
965 header: StdHeader::String,
966 c99_section: "§7.23.6.1".to_string(),
967 },
968 );
969
970 functions.insert(
971 "strlen".to_string(),
972 FunctionProto {
973 name: "strlen".to_string(),
974 return_type: "size_t".to_string(),
975 parameters: vec![Parameter::new("s", "const char*")],
976 is_variadic: false,
977 header: StdHeader::String,
978 c99_section: "§7.23.6.3".to_string(),
979 },
980 );
981
982 functions.insert(
983 "strdup".to_string(),
984 FunctionProto {
985 name: "strdup".to_string(),
986 return_type: "char*".to_string(),
987 parameters: vec![Parameter::new("s", "const char*")],
988 is_variadic: false,
989 header: StdHeader::String,
990 c99_section: "POSIX".to_string(),
991 },
992 );
993
994 functions.insert(
999 "isspace".to_string(),
1000 FunctionProto {
1001 name: "isspace".to_string(),
1002 return_type: "int".to_string(),
1003 parameters: vec![Parameter::new("c", "int")],
1004 is_variadic: false,
1005 header: StdHeader::Ctype,
1006 c99_section: "§7.4.1.10".to_string(),
1007 },
1008 );
1009
1010 functions.insert(
1011 "isdigit".to_string(),
1012 FunctionProto {
1013 name: "isdigit".to_string(),
1014 return_type: "int".to_string(),
1015 parameters: vec![Parameter::new("c", "int")],
1016 is_variadic: false,
1017 header: StdHeader::Ctype,
1018 c99_section: "§7.4.1.5".to_string(),
1019 },
1020 );
1021
1022 functions.insert(
1023 "isalpha".to_string(),
1024 FunctionProto {
1025 name: "isalpha".to_string(),
1026 return_type: "int".to_string(),
1027 parameters: vec![Parameter::new("c", "int")],
1028 is_variadic: false,
1029 header: StdHeader::Ctype,
1030 c99_section: "§7.4.1.2".to_string(),
1031 },
1032 );
1033
1034 functions.insert(
1035 "isalnum".to_string(),
1036 FunctionProto {
1037 name: "isalnum".to_string(),
1038 return_type: "int".to_string(),
1039 parameters: vec![Parameter::new("c", "int")],
1040 is_variadic: false,
1041 header: StdHeader::Ctype,
1042 c99_section: "§7.4.1.1".to_string(),
1043 },
1044 );
1045
1046 functions.insert(
1047 "isupper".to_string(),
1048 FunctionProto {
1049 name: "isupper".to_string(),
1050 return_type: "int".to_string(),
1051 parameters: vec![Parameter::new("c", "int")],
1052 is_variadic: false,
1053 header: StdHeader::Ctype,
1054 c99_section: "§7.4.1.11".to_string(),
1055 },
1056 );
1057
1058 functions.insert(
1059 "islower".to_string(),
1060 FunctionProto {
1061 name: "islower".to_string(),
1062 return_type: "int".to_string(),
1063 parameters: vec![Parameter::new("c", "int")],
1064 is_variadic: false,
1065 header: StdHeader::Ctype,
1066 c99_section: "§7.4.1.7".to_string(),
1067 },
1068 );
1069
1070 functions.insert(
1071 "tolower".to_string(),
1072 FunctionProto {
1073 name: "tolower".to_string(),
1074 return_type: "int".to_string(),
1075 parameters: vec![Parameter::new("c", "int")],
1076 is_variadic: false,
1077 header: StdHeader::Ctype,
1078 c99_section: "§7.4.2.1".to_string(),
1079 },
1080 );
1081
1082 functions.insert(
1083 "toupper".to_string(),
1084 FunctionProto {
1085 name: "toupper".to_string(),
1086 return_type: "int".to_string(),
1087 parameters: vec![Parameter::new("c", "int")],
1088 is_variadic: false,
1089 header: StdHeader::Ctype,
1090 c99_section: "§7.4.2.2".to_string(),
1091 },
1092 );
1093
1094 functions.insert(
1099 "clock".to_string(),
1100 FunctionProto {
1101 name: "clock".to_string(),
1102 return_type: "clock_t".to_string(),
1103 parameters: vec![],
1104 is_variadic: false,
1105 header: StdHeader::Time,
1106 c99_section: "§7.23.2.1".to_string(),
1107 },
1108 );
1109
1110 functions.insert(
1111 "time".to_string(),
1112 FunctionProto {
1113 name: "time".to_string(),
1114 return_type: "time_t".to_string(),
1115 parameters: vec![Parameter::new("timer", "time_t*")],
1116 is_variadic: false,
1117 header: StdHeader::Time,
1118 c99_section: "§7.23.2.4".to_string(),
1119 },
1120 );
1121
1122 functions.insert(
1127 "sqrt".to_string(),
1128 FunctionProto {
1129 name: "sqrt".to_string(),
1130 return_type: "double".to_string(),
1131 parameters: vec![Parameter::new("x", "double")],
1132 is_variadic: false,
1133 header: StdHeader::Math,
1134 c99_section: "§7.12.7.5".to_string(),
1135 },
1136 );
1137
1138 functions.insert(
1139 "sin".to_string(),
1140 FunctionProto {
1141 name: "sin".to_string(),
1142 return_type: "double".to_string(),
1143 parameters: vec![Parameter::new("x", "double")],
1144 is_variadic: false,
1145 header: StdHeader::Math,
1146 c99_section: "§7.12.4.6".to_string(),
1147 },
1148 );
1149
1150 functions.insert(
1151 "cos".to_string(),
1152 FunctionProto {
1153 name: "cos".to_string(),
1154 return_type: "double".to_string(),
1155 parameters: vec![Parameter::new("x", "double")],
1156 is_variadic: false,
1157 header: StdHeader::Math,
1158 c99_section: "§7.12.4.5".to_string(),
1159 },
1160 );
1161
1162 functions.insert(
1163 "pow".to_string(),
1164 FunctionProto {
1165 name: "pow".to_string(),
1166 return_type: "double".to_string(),
1167 parameters: vec![Parameter::new("x", "double"), Parameter::new("y", "double")],
1168 is_variadic: false,
1169 header: StdHeader::Math,
1170 c99_section: "§7.12.7.4".to_string(),
1171 },
1172 );
1173
1174 functions.insert(
1175 "fabs".to_string(),
1176 FunctionProto {
1177 name: "fabs".to_string(),
1178 return_type: "double".to_string(),
1179 parameters: vec![Parameter::new("x", "double")],
1180 is_variadic: false,
1181 header: StdHeader::Math,
1182 c99_section: "§7.12.7.2".to_string(),
1183 },
1184 );
1185
1186 functions.insert(
1187 "ceil".to_string(),
1188 FunctionProto {
1189 name: "ceil".to_string(),
1190 return_type: "double".to_string(),
1191 parameters: vec![Parameter::new("x", "double")],
1192 is_variadic: false,
1193 header: StdHeader::Math,
1194 c99_section: "§7.12.9.1".to_string(),
1195 },
1196 );
1197
1198 functions.insert(
1199 "floor".to_string(),
1200 FunctionProto {
1201 name: "floor".to_string(),
1202 return_type: "double".to_string(),
1203 parameters: vec![Parameter::new("x", "double")],
1204 is_variadic: false,
1205 header: StdHeader::Math,
1206 c99_section: "§7.12.9.2".to_string(),
1207 },
1208 );
1209
1210 functions.insert(
1211 "round".to_string(),
1212 FunctionProto {
1213 name: "round".to_string(),
1214 return_type: "double".to_string(),
1215 parameters: vec![Parameter::new("x", "double")],
1216 is_variadic: false,
1217 header: StdHeader::Math,
1218 c99_section: "§7.12.9.6".to_string(),
1219 },
1220 );
1221
1222 functions.insert(
1223 "trunc".to_string(),
1224 FunctionProto {
1225 name: "trunc".to_string(),
1226 return_type: "double".to_string(),
1227 parameters: vec![Parameter::new("x", "double")],
1228 is_variadic: false,
1229 header: StdHeader::Math,
1230 c99_section: "§7.12.9.8".to_string(),
1231 },
1232 );
1233
1234 functions.insert(
1235 "exp".to_string(),
1236 FunctionProto {
1237 name: "exp".to_string(),
1238 return_type: "double".to_string(),
1239 parameters: vec![Parameter::new("x", "double")],
1240 is_variadic: false,
1241 header: StdHeader::Math,
1242 c99_section: "§7.12.6.1".to_string(),
1243 },
1244 );
1245
1246 functions.insert(
1247 "log".to_string(),
1248 FunctionProto {
1249 name: "log".to_string(),
1250 return_type: "double".to_string(),
1251 parameters: vec![Parameter::new("x", "double")],
1252 is_variadic: false,
1253 header: StdHeader::Math,
1254 c99_section: "§7.12.6.7".to_string(),
1255 },
1256 );
1257
1258 functions.insert(
1259 "log10".to_string(),
1260 FunctionProto {
1261 name: "log10".to_string(),
1262 return_type: "double".to_string(),
1263 parameters: vec![Parameter::new("x", "double")],
1264 is_variadic: false,
1265 header: StdHeader::Math,
1266 c99_section: "§7.12.6.8".to_string(),
1267 },
1268 );
1269
1270 functions.insert(
1271 "tan".to_string(),
1272 FunctionProto {
1273 name: "tan".to_string(),
1274 return_type: "double".to_string(),
1275 parameters: vec![Parameter::new("x", "double")],
1276 is_variadic: false,
1277 header: StdHeader::Math,
1278 c99_section: "§7.12.4.7".to_string(),
1279 },
1280 );
1281
1282 functions.insert(
1283 "asin".to_string(),
1284 FunctionProto {
1285 name: "asin".to_string(),
1286 return_type: "double".to_string(),
1287 parameters: vec![Parameter::new("x", "double")],
1288 is_variadic: false,
1289 header: StdHeader::Math,
1290 c99_section: "§7.12.4.2".to_string(),
1291 },
1292 );
1293
1294 functions.insert(
1295 "acos".to_string(),
1296 FunctionProto {
1297 name: "acos".to_string(),
1298 return_type: "double".to_string(),
1299 parameters: vec![Parameter::new("x", "double")],
1300 is_variadic: false,
1301 header: StdHeader::Math,
1302 c99_section: "§7.12.4.1".to_string(),
1303 },
1304 );
1305
1306 functions.insert(
1307 "atan".to_string(),
1308 FunctionProto {
1309 name: "atan".to_string(),
1310 return_type: "double".to_string(),
1311 parameters: vec![Parameter::new("x", "double")],
1312 is_variadic: false,
1313 header: StdHeader::Math,
1314 c99_section: "§7.12.4.3".to_string(),
1315 },
1316 );
1317
1318 functions.insert(
1319 "atan2".to_string(),
1320 FunctionProto {
1321 name: "atan2".to_string(),
1322 return_type: "double".to_string(),
1323 parameters: vec![Parameter::new("y", "double"), Parameter::new("x", "double")],
1324 is_variadic: false,
1325 header: StdHeader::Math,
1326 c99_section: "§7.12.4.4".to_string(),
1327 },
1328 );
1329
1330 functions.insert(
1331 "fmod".to_string(),
1332 FunctionProto {
1333 name: "fmod".to_string(),
1334 return_type: "double".to_string(),
1335 parameters: vec![Parameter::new("x", "double"), Parameter::new("y", "double")],
1336 is_variadic: false,
1337 header: StdHeader::Math,
1338 c99_section: "§7.12.10.1".to_string(),
1339 },
1340 );
1341
1342 functions.insert(
1347 "pipe".to_string(),
1348 FunctionProto {
1349 name: "pipe".to_string(),
1350 return_type: "int".to_string(),
1351 parameters: vec![Parameter::new("pipefd", "int*")],
1352 is_variadic: false,
1353 header: StdHeader::Unistd,
1354 c99_section: "POSIX".to_string(),
1355 },
1356 );
1357
1358 functions.insert(
1359 "fork".to_string(),
1360 FunctionProto {
1361 name: "fork".to_string(),
1362 return_type: "pid_t".to_string(),
1363 parameters: vec![],
1364 is_variadic: false,
1365 header: StdHeader::Unistd,
1366 c99_section: "POSIX".to_string(),
1367 },
1368 );
1369
1370 functions.insert(
1371 "read".to_string(),
1372 FunctionProto {
1373 name: "read".to_string(),
1374 return_type: "ssize_t".to_string(),
1375 parameters: vec![
1376 Parameter::new("fd", "int"),
1377 Parameter::new("buf", "void*"),
1378 Parameter::new("count", "size_t"),
1379 ],
1380 is_variadic: false,
1381 header: StdHeader::Unistd,
1382 c99_section: "POSIX".to_string(),
1383 },
1384 );
1385
1386 functions.insert(
1387 "write".to_string(),
1388 FunctionProto {
1389 name: "write".to_string(),
1390 return_type: "ssize_t".to_string(),
1391 parameters: vec![
1392 Parameter::new("fd", "int"),
1393 Parameter::new("buf", "const void*"),
1394 Parameter::new("count", "size_t"),
1395 ],
1396 is_variadic: false,
1397 header: StdHeader::Unistd,
1398 c99_section: "POSIX".to_string(),
1399 },
1400 );
1401
1402 functions.insert(
1403 "close".to_string(),
1404 FunctionProto {
1405 name: "close".to_string(),
1406 return_type: "int".to_string(),
1407 parameters: vec![Parameter::new("fd", "int")],
1408 is_variadic: false,
1409 header: StdHeader::Unistd,
1410 c99_section: "POSIX".to_string(),
1411 },
1412 );
1413
1414 functions.insert(
1415 "lseek".to_string(),
1416 FunctionProto {
1417 name: "lseek".to_string(),
1418 return_type: "off_t".to_string(),
1419 parameters: vec![
1420 Parameter::new("fd", "int"),
1421 Parameter::new("offset", "off_t"),
1422 Parameter::new("whence", "int"),
1423 ],
1424 is_variadic: false,
1425 header: StdHeader::Unistd,
1426 c99_section: "POSIX".to_string(),
1427 },
1428 );
1429
1430 functions.insert(
1431 "open".to_string(),
1432 FunctionProto {
1433 name: "open".to_string(),
1434 return_type: "int".to_string(),
1435 parameters: vec![
1436 Parameter::new("pathname", "const char*"),
1437 Parameter::new("flags", "int"),
1438 ],
1439 is_variadic: true, header: StdHeader::Fcntl,
1441 c99_section: "POSIX".to_string(),
1442 },
1443 );
1444
1445 functions.insert(
1446 "dup".to_string(),
1447 FunctionProto {
1448 name: "dup".to_string(),
1449 return_type: "int".to_string(),
1450 parameters: vec![Parameter::new("oldfd", "int")],
1451 is_variadic: false,
1452 header: StdHeader::Unistd,
1453 c99_section: "POSIX".to_string(),
1454 },
1455 );
1456
1457 functions.insert(
1458 "dup2".to_string(),
1459 FunctionProto {
1460 name: "dup2".to_string(),
1461 return_type: "int".to_string(),
1462 parameters: vec![
1463 Parameter::new("oldfd", "int"),
1464 Parameter::new("newfd", "int"),
1465 ],
1466 is_variadic: false,
1467 header: StdHeader::Unistd,
1468 c99_section: "POSIX".to_string(),
1469 },
1470 );
1471
1472 functions.insert(
1473 "getenv".to_string(),
1474 FunctionProto {
1475 name: "getenv".to_string(),
1476 return_type: "char*".to_string(),
1477 parameters: vec![Parameter::new("name", "const char*")],
1478 is_variadic: false,
1479 header: StdHeader::Stdlib,
1480 c99_section: "§7.22.4.6".to_string(),
1481 },
1482 );
1483
1484 functions.insert(
1489 "opendir".to_string(),
1490 FunctionProto {
1491 name: "opendir".to_string(),
1492 return_type: "DIR*".to_string(),
1493 parameters: vec![Parameter::new("name", "const char*")],
1494 is_variadic: false,
1495 header: StdHeader::Dirent,
1496 c99_section: "POSIX".to_string(),
1497 },
1498 );
1499
1500 functions.insert(
1501 "readdir".to_string(),
1502 FunctionProto {
1503 name: "readdir".to_string(),
1504 return_type: "struct dirent*".to_string(),
1505 parameters: vec![Parameter::new("dirp", "DIR*")],
1506 is_variadic: false,
1507 header: StdHeader::Dirent,
1508 c99_section: "POSIX".to_string(),
1509 },
1510 );
1511
1512 functions.insert(
1513 "closedir".to_string(),
1514 FunctionProto {
1515 name: "closedir".to_string(),
1516 return_type: "int".to_string(),
1517 parameters: vec![Parameter::new("dirp", "DIR*")],
1518 is_variadic: false,
1519 header: StdHeader::Dirent,
1520 c99_section: "POSIX".to_string(),
1521 },
1522 );
1523
1524 Self { functions }
1525 }
1526
1527 pub fn get_prototype(&self, name: &str) -> Option<&FunctionProto> {
1529 self.functions.get(name)
1530 }
1531
1532 pub fn inject_prototypes_for_header(&self, header: StdHeader) -> String {
1546 let mut result = String::new();
1547
1548 result.push_str(&format!(
1550 "// Built-in prototypes for {:?} (ISO C99 §7)\n",
1551 header
1552 ));
1553 result.push_str("typedef unsigned long size_t;\n");
1554 result.push_str("typedef long ssize_t;\n");
1555 result.push_str("typedef long ptrdiff_t;\n");
1556 result.push_str("#define NULL 0\n");
1558
1559 match header {
1561 StdHeader::Stdio => {
1562 result.push_str("struct _IO_FILE;\n");
1563 result.push_str("typedef struct _IO_FILE FILE;\n");
1564 result.push_str("extern FILE* stdin;\n");
1566 result.push_str("extern FILE* stdout;\n");
1567 result.push_str("extern FILE* stderr;\n");
1568 result.push_str("#define EOF (-1)\n");
1570 result.push_str("#define SEEK_SET 0\n");
1571 result.push_str("#define SEEK_CUR 1\n");
1572 result.push_str("#define SEEK_END 2\n");
1573 result.push_str("#define BUFSIZ 8192\n");
1574 result.push_str("#define L_tmpnam 20\n");
1575 result.push_str("#define _IONBF 2\n");
1576 result.push_str("#define _IOLBF 1\n");
1577 result.push_str("#define _IOFBF 0\n");
1578 }
1579 StdHeader::Errno => {
1580 result.push_str("extern int errno;\n");
1581 result.push_str("#define EACCES 13\n");
1582 result.push_str("#define ENOENT 2\n");
1583 result.push_str("#define EINVAL 22\n");
1584 result.push_str("#define ENOMEM 12\n");
1585 result.push_str("#define ERANGE 34\n");
1586 }
1587 StdHeader::Time => {
1588 result.push_str("typedef long time_t;\n");
1589 result.push_str("typedef long clock_t;\n");
1590 result.push_str("struct tm;\n");
1591 result.push_str("#define CLOCKS_PER_SEC 1000000\n");
1592 }
1593 StdHeader::Stdarg => {
1594 result.push_str("typedef void* va_list;\n");
1596 result.push_str("#define va_start(ap, last) ((void)0)\n");
1597 result.push_str("#define va_end(ap) ((void)0)\n");
1598 result.push_str("#define va_arg(ap, type) (*(type*)0)\n");
1599 }
1600 StdHeader::Stdbool => {
1601 result.push_str("typedef _Bool bool;\n");
1602 result.push_str("#define true 1\n");
1603 result.push_str("#define false 0\n");
1604 }
1605 StdHeader::Stdint => {
1606 result.push_str("typedef signed char int8_t;\n");
1607 result.push_str("typedef short int16_t;\n");
1608 result.push_str("typedef int int32_t;\n");
1609 result.push_str("typedef long long int64_t;\n");
1610 result.push_str("typedef unsigned char uint8_t;\n");
1611 result.push_str("typedef unsigned short uint16_t;\n");
1612 result.push_str("typedef unsigned int uint32_t;\n");
1613 result.push_str("typedef unsigned long long uint64_t;\n");
1614 result.push_str("typedef long intptr_t;\n");
1615 result.push_str("typedef unsigned long uintptr_t;\n");
1616 }
1617 StdHeader::Unistd => {
1618 result.push_str("typedef int pid_t;\n");
1620 result.push_str("typedef long off_t;\n");
1621 result.push_str("typedef unsigned int uid_t;\n");
1622 result.push_str("typedef unsigned int gid_t;\n");
1623 result.push_str("#define STDIN_FILENO 0\n");
1624 result.push_str("#define STDOUT_FILENO 1\n");
1625 result.push_str("#define STDERR_FILENO 2\n");
1626 result.push_str("#define F_OK 0\n");
1628 result.push_str("#define R_OK 4\n");
1629 result.push_str("#define W_OK 2\n");
1630 result.push_str("#define X_OK 1\n");
1631 result.push_str("#define _SC_OPEN_MAX 4\n");
1633 result.push_str("#define _SC_PAGESIZE 30\n");
1634 }
1635 StdHeader::Fcntl => {
1636 result.push_str("#define O_RDONLY 0\n");
1638 result.push_str("#define O_WRONLY 1\n");
1639 result.push_str("#define O_RDWR 2\n");
1640 result.push_str("#define O_CREAT 0100\n");
1641 result.push_str("#define O_TRUNC 01000\n");
1642 result.push_str("#define O_APPEND 02000\n");
1643 result.push_str("#define O_NONBLOCK 04000\n");
1644 result.push_str("#define LOCK_SH 1\n");
1646 result.push_str("#define LOCK_EX 2\n");
1647 result.push_str("#define LOCK_UN 8\n");
1648 }
1649 StdHeader::Dirent => {
1650 result.push_str("struct dirent { char d_name[256]; };\n");
1651 result.push_str("typedef struct __dirstream DIR;\n");
1652 }
1653 StdHeader::SysTypes => {
1654 result.push_str("typedef int pid_t;\n");
1655 result.push_str("typedef long off_t;\n");
1656 result.push_str("typedef unsigned int mode_t;\n");
1657 result.push_str("typedef long ssize_t;\n");
1658 }
1659 StdHeader::SysStat => {
1660 result.push_str("struct stat { long st_size; int st_mode; };\n");
1661 result.push_str("#define S_ISREG(m) (((m) & 0170000) == 0100000)\n");
1662 result.push_str("#define S_ISDIR(m) (((m) & 0170000) == 0040000)\n");
1663 }
1664 StdHeader::SysMman => {
1665 result.push_str("#define PROT_NONE 0\n");
1667 result.push_str("#define PROT_READ 1\n");
1668 result.push_str("#define PROT_WRITE 2\n");
1669 result.push_str("#define PROT_EXEC 4\n");
1670 result.push_str("#define MAP_SHARED 1\n");
1672 result.push_str("#define MAP_PRIVATE 2\n");
1673 result.push_str("#define MAP_ANONYMOUS 0x20\n");
1674 result.push_str("#define MAP_FAILED ((void*)-1)\n");
1675 }
1676 StdHeader::Wchar => {
1677 result.push_str("typedef int wchar_t;\n");
1678 result.push_str("typedef int wint_t;\n");
1679 result.push_str("#define WEOF (-1)\n");
1680 }
1681 StdHeader::Signal => {
1682 result.push_str("typedef void (*sighandler_t)(int);\n");
1683 result.push_str("#define SIGINT 2\n");
1684 result.push_str("#define SIGTERM 15\n");
1685 }
1686 StdHeader::Limits => {
1687 result.push_str("#define CHAR_BIT 8\n");
1688 result.push_str("#define CHAR_MIN (-128)\n");
1689 result.push_str("#define CHAR_MAX 127\n");
1690 result.push_str("#define SHRT_MIN (-32768)\n");
1691 result.push_str("#define SHRT_MAX 32767\n");
1692 result.push_str("#define INT_MIN (-2147483647-1)\n");
1693 result.push_str("#define INT_MAX 2147483647\n");
1694 result.push_str("#define UINT_MAX 4294967295U\n");
1695 result.push_str("#define LONG_MIN (-9223372036854775807L-1)\n");
1696 result.push_str("#define LONG_MAX 9223372036854775807L\n");
1697 result.push_str("#define PATH_MAX 4096\n");
1698 }
1699 StdHeader::Ctype => {
1700 }
1703 StdHeader::Math => {
1704 result.push_str("#define M_PI 3.14159265358979323846\n");
1706 result.push_str("#define M_E 2.71828182845904523536\n");
1707 result.push_str("#define INFINITY (1.0/0.0)\n");
1708 result.push_str("#define NAN (0.0/0.0)\n");
1709 }
1710 _ => {}
1711 }
1712
1713 result.push('\n');
1714
1715 let mut protos: Vec<_> = self
1720 .functions
1721 .values()
1722 .filter(|p| p.header == header)
1723 .filter(|p| {
1724 !p.parameters
1726 .iter()
1727 .any(|param| param.type_str.contains("(*"))
1728 })
1729 .collect();
1730 protos.sort_by_key(|p| &p.name);
1731
1732 for proto in protos {
1733 result.push_str(&proto.to_c_declaration());
1734 result.push('\n');
1735 }
1736
1737 result
1738 }
1739
1740 pub fn inject_all_prototypes(&self) -> String {
1745 let mut result = String::new();
1746
1747 result.push_str("// Built-in stdlib prototypes (ISO C99 §7)\n");
1749 result.push_str("typedef unsigned long size_t;\n");
1750 result.push_str("typedef long ssize_t;\n");
1751 result.push_str("typedef long ptrdiff_t;\n");
1752 result.push_str("#define NULL 0\n");
1754 result.push_str("struct _IO_FILE;\n");
1755 result.push_str("typedef struct _IO_FILE FILE;\n");
1756 result.push_str("extern FILE* stdin;\n");
1758 result.push_str("extern FILE* stdout;\n");
1759 result.push_str("extern FILE* stderr;\n");
1760 result.push_str("#define EOF (-1)\n");
1761 result.push_str("#define SEEK_SET 0\n");
1762 result.push_str("#define SEEK_CUR 1\n");
1763 result.push_str("#define SEEK_END 2\n");
1764 result.push_str("typedef int pid_t;\n");
1766 result.push_str("typedef long off_t;\n");
1767 result.push_str("typedef long time_t;\n");
1768 result.push_str("typedef long clock_t;\n");
1769 result.push_str("typedef int wchar_t;\n");
1770 result.push_str("extern int errno;\n");
1771 result.push_str("#define CLOCKS_PER_SEC 1000000\n");
1773 result.push_str("#define PATH_MAX 4096\n");
1774 result.push('\n');
1775
1776 let mut protos: Vec<_> = self.functions.values().collect();
1778 protos.sort_by_key(|p| &p.name);
1779
1780 for proto in protos {
1781 result.push_str(&proto.to_c_declaration());
1782 result.push('\n');
1783 }
1784
1785 result
1786 }
1787
1788 pub fn len(&self) -> usize {
1790 self.functions.len()
1791 }
1792
1793 pub fn is_empty(&self) -> bool {
1795 self.functions.is_empty()
1796 }
1797}
1798
1799impl Default for StdlibPrototypes {
1800 fn default() -> Self {
1801 Self::new()
1802 }
1803}
1804
1805#[cfg(test)]
1806#[path = "inject_prototype_tests.rs"]
1807mod inject_prototype_tests;
1808
1809#[cfg(test)]
1810mod tests {
1811 use super::*;
1812
1813 #[test]
1814 fn test_function_proto_to_c_declaration() {
1815 let proto = FunctionProto {
1816 name: "malloc".to_string(),
1817 return_type: "void*".to_string(),
1818 parameters: vec![Parameter::new("size", "size_t")],
1819 is_variadic: false,
1820 header: StdHeader::Stdlib,
1821 c99_section: "§7.22.3.4".to_string(),
1822 };
1823
1824 assert_eq!(proto.to_c_declaration(), "void* malloc(size_t size);");
1825 }
1826
1827 #[test]
1828 fn test_variadic_function_proto() {
1829 let proto = FunctionProto {
1830 name: "printf".to_string(),
1831 return_type: "int".to_string(),
1832 parameters: vec![Parameter::new("format", "const char*")],
1833 is_variadic: true,
1834 header: StdHeader::Stdio,
1835 c99_section: "§7.21.6.1".to_string(),
1836 };
1837
1838 assert_eq!(
1839 proto.to_c_declaration(),
1840 "int printf(const char* format, ...);"
1841 );
1842 }
1843
1844 #[test]
1845 fn test_no_param_function_proto() {
1846 let proto = FunctionProto {
1847 name: "rand".to_string(),
1848 return_type: "int".to_string(),
1849 parameters: vec![],
1850 is_variadic: false,
1851 header: StdHeader::Stdlib,
1852 c99_section: "§7.22.2.1".to_string(),
1853 };
1854
1855 assert_eq!(proto.to_c_declaration(), "int rand(void);");
1856 }
1857
1858 #[test]
1863 fn test_inject_header_common_preamble_present_for_all_headers() {
1864 let stdlib = StdlibPrototypes::new();
1865 let headers = [
1866 StdHeader::Stdio,
1867 StdHeader::Errno,
1868 StdHeader::Time,
1869 StdHeader::Stdarg,
1870 StdHeader::Stdbool,
1871 StdHeader::Stdint,
1872 StdHeader::Unistd,
1873 StdHeader::Fcntl,
1874 StdHeader::Dirent,
1875 StdHeader::SysTypes,
1876 StdHeader::SysStat,
1877 StdHeader::SysMman,
1878 StdHeader::Wchar,
1879 StdHeader::Signal,
1880 StdHeader::Limits,
1881 StdHeader::Ctype,
1882 StdHeader::Math,
1883 StdHeader::Assert,
1884 StdHeader::Float,
1885 StdHeader::Locale,
1886 StdHeader::Setjmp,
1887 StdHeader::Stddef,
1888 StdHeader::Stdlib,
1889 StdHeader::String,
1890 ];
1891 for header in &headers {
1892 let result = stdlib.inject_prototypes_for_header(*header);
1893 assert!(
1894 result.contains("typedef unsigned long size_t;"),
1895 "{:?} missing size_t",
1896 header
1897 );
1898 assert!(
1899 result.contains("typedef long ssize_t;"),
1900 "{:?} missing ssize_t",
1901 header
1902 );
1903 assert!(
1904 result.contains("typedef long ptrdiff_t;"),
1905 "{:?} missing ptrdiff_t",
1906 header
1907 );
1908 assert!(
1909 result.contains("#define NULL 0"),
1910 "{:?} missing NULL",
1911 header
1912 );
1913 assert!(
1914 result.contains("// Built-in prototypes for"),
1915 "{:?} missing comment header",
1916 header
1917 );
1918 }
1919 }
1920
1921 #[test]
1926 fn test_inject_header_stdio_type_definitions() {
1927 let stdlib = StdlibPrototypes::new();
1928 let result = stdlib.inject_prototypes_for_header(StdHeader::Stdio);
1929 assert!(result.contains("struct _IO_FILE;"));
1930 assert!(result.contains("typedef struct _IO_FILE FILE;"));
1931 assert!(result.contains("extern FILE* stdin;"));
1932 assert!(result.contains("extern FILE* stdout;"));
1933 assert!(result.contains("extern FILE* stderr;"));
1934 }
1935
1936 #[test]
1937 fn test_inject_header_stdio_macros() {
1938 let stdlib = StdlibPrototypes::new();
1939 let result = stdlib.inject_prototypes_for_header(StdHeader::Stdio);
1940 assert!(result.contains("#define EOF (-1)"));
1941 assert!(result.contains("#define SEEK_SET 0"));
1942 assert!(result.contains("#define SEEK_CUR 1"));
1943 assert!(result.contains("#define SEEK_END 2"));
1944 assert!(result.contains("#define BUFSIZ 8192"));
1945 assert!(result.contains("#define L_tmpnam 20"));
1946 assert!(result.contains("#define _IONBF 2"));
1947 assert!(result.contains("#define _IOLBF 1"));
1948 assert!(result.contains("#define _IOFBF 0"));
1949 }
1950
1951 #[test]
1952 fn test_inject_header_stdio_functions() {
1953 let stdlib = StdlibPrototypes::new();
1954 let result = stdlib.inject_prototypes_for_header(StdHeader::Stdio);
1955 assert!(result.contains("int printf(const char* format, ...);"));
1957 assert!(result.contains("int fprintf(FILE* stream, const char* format, ...);"));
1958 assert!(result.contains("int sprintf(char* str, const char* format, ...);"));
1959 assert!(result.contains("int snprintf(char* str, size_t size, const char* format, ...);"));
1960 assert!(result.contains("int scanf(const char* format, ...);"));
1962 assert!(result.contains("int fscanf(FILE* stream, const char* format, ...);"));
1963 assert!(result.contains("int sscanf(const char* str, const char* format, ...);"));
1964 assert!(result.contains("FILE* fopen("));
1966 assert!(result.contains("int fclose(FILE* stream);"));
1967 assert!(result.contains("size_t fread("));
1968 assert!(result.contains("size_t fwrite("));
1969 assert!(result.contains("int fseek("));
1970 assert!(result.contains("long ftell(FILE* stream);"));
1971 assert!(result.contains("void rewind(FILE* stream);"));
1972 assert!(result.contains("int getchar(void);"));
1974 assert!(result.contains("int putchar(int c);"));
1975 assert!(result.contains("int fgetc(FILE* stream);"));
1976 assert!(result.contains("int fputc(int c, FILE* stream);"));
1977 assert!(result.contains("char* fgets("));
1978 assert!(result.contains("int fputs("));
1979 assert!(result.contains("int puts(const char* s);"));
1980 }
1981
1982 #[test]
1983 fn test_inject_header_stdio_does_not_contain_stdlib_functions() {
1984 let stdlib = StdlibPrototypes::new();
1985 let result = stdlib.inject_prototypes_for_header(StdHeader::Stdio);
1986 assert!(!result.contains("void* malloc("));
1988 assert!(!result.contains("void free("));
1989 }
1990
1991 #[test]
1996 fn test_inject_header_errno_definitions() {
1997 let stdlib = StdlibPrototypes::new();
1998 let result = stdlib.inject_prototypes_for_header(StdHeader::Errno);
1999 assert!(result.contains("extern int errno;"));
2000 assert!(result.contains("#define EACCES 13"));
2001 assert!(result.contains("#define ENOENT 2"));
2002 assert!(result.contains("#define EINVAL 22"));
2003 assert!(result.contains("#define ENOMEM 12"));
2004 assert!(result.contains("#define ERANGE 34"));
2005 }
2006
2007 #[test]
2008 fn test_inject_header_errno_no_functions() {
2009 let stdlib = StdlibPrototypes::new();
2010 let result = stdlib.inject_prototypes_for_header(StdHeader::Errno);
2011 assert!(!result.contains("int printf("));
2013 assert!(!result.contains("void* malloc("));
2014 }
2015
2016 #[test]
2021 fn test_inject_header_time_type_definitions() {
2022 let stdlib = StdlibPrototypes::new();
2023 let result = stdlib.inject_prototypes_for_header(StdHeader::Time);
2024 assert!(result.contains("typedef long time_t;"));
2025 assert!(result.contains("typedef long clock_t;"));
2026 assert!(result.contains("struct tm;"));
2027 assert!(result.contains("#define CLOCKS_PER_SEC 1000000"));
2028 }
2029
2030 #[test]
2031 fn test_inject_header_time_functions() {
2032 let stdlib = StdlibPrototypes::new();
2033 let result = stdlib.inject_prototypes_for_header(StdHeader::Time);
2034 assert!(result.contains("clock_t clock(void);"));
2035 assert!(result.contains("time_t time(time_t* timer);"));
2036 }
2037
2038 #[test]
2043 fn test_inject_header_stdarg_definitions() {
2044 let stdlib = StdlibPrototypes::new();
2045 let result = stdlib.inject_prototypes_for_header(StdHeader::Stdarg);
2046 assert!(result.contains("typedef void* va_list;"));
2047 assert!(result.contains("#define va_start(ap, last) ((void)0)"));
2048 assert!(result.contains("#define va_end(ap) ((void)0)"));
2049 assert!(result.contains("#define va_arg(ap, type) (*(type*)0)"));
2050 }
2051
2052 #[test]
2057 fn test_inject_header_stdbool_definitions() {
2058 let stdlib = StdlibPrototypes::new();
2059 let result = stdlib.inject_prototypes_for_header(StdHeader::Stdbool);
2060 assert!(result.contains("typedef _Bool bool;"));
2061 assert!(result.contains("#define true 1"));
2062 assert!(result.contains("#define false 0"));
2063 }
2064
2065 #[test]
2070 fn test_inject_header_stdint_type_definitions() {
2071 let stdlib = StdlibPrototypes::new();
2072 let result = stdlib.inject_prototypes_for_header(StdHeader::Stdint);
2073 assert!(result.contains("typedef signed char int8_t;"));
2074 assert!(result.contains("typedef short int16_t;"));
2075 assert!(result.contains("typedef int int32_t;"));
2076 assert!(result.contains("typedef long long int64_t;"));
2077 assert!(result.contains("typedef unsigned char uint8_t;"));
2078 assert!(result.contains("typedef unsigned short uint16_t;"));
2079 assert!(result.contains("typedef unsigned int uint32_t;"));
2080 assert!(result.contains("typedef unsigned long long uint64_t;"));
2081 assert!(result.contains("typedef long intptr_t;"));
2082 assert!(result.contains("typedef unsigned long uintptr_t;"));
2083 }
2084
2085 #[test]
2090 fn test_inject_header_unistd_type_definitions() {
2091 let stdlib = StdlibPrototypes::new();
2092 let result = stdlib.inject_prototypes_for_header(StdHeader::Unistd);
2093 assert!(result.contains("typedef int pid_t;"));
2094 assert!(result.contains("typedef long off_t;"));
2095 assert!(result.contains("typedef unsigned int uid_t;"));
2096 assert!(result.contains("typedef unsigned int gid_t;"));
2097 }
2098
2099 #[test]
2100 fn test_inject_header_unistd_macros() {
2101 let stdlib = StdlibPrototypes::new();
2102 let result = stdlib.inject_prototypes_for_header(StdHeader::Unistd);
2103 assert!(result.contains("#define STDIN_FILENO 0"));
2104 assert!(result.contains("#define STDOUT_FILENO 1"));
2105 assert!(result.contains("#define STDERR_FILENO 2"));
2106 assert!(result.contains("#define F_OK 0"));
2107 assert!(result.contains("#define R_OK 4"));
2108 assert!(result.contains("#define W_OK 2"));
2109 assert!(result.contains("#define X_OK 1"));
2110 assert!(result.contains("#define _SC_OPEN_MAX 4"));
2111 assert!(result.contains("#define _SC_PAGESIZE 30"));
2112 }
2113
2114 #[test]
2115 fn test_inject_header_unistd_functions() {
2116 let stdlib = StdlibPrototypes::new();
2117 let result = stdlib.inject_prototypes_for_header(StdHeader::Unistd);
2118 assert!(result.contains("int pipe(int* pipefd);"));
2119 assert!(result.contains("pid_t fork(void);"));
2120 assert!(result.contains("ssize_t read(int fd, void* buf, size_t count);"));
2121 assert!(result.contains("ssize_t write(int fd, const void* buf, size_t count);"));
2122 assert!(result.contains("int close(int fd);"));
2123 assert!(result.contains("off_t lseek(int fd, off_t offset, int whence);"));
2124 assert!(result.contains("int dup(int oldfd);"));
2125 assert!(result.contains("int dup2(int oldfd, int newfd);"));
2126 }
2127
2128 #[test]
2133 fn test_inject_header_fcntl_macros() {
2134 let stdlib = StdlibPrototypes::new();
2135 let result = stdlib.inject_prototypes_for_header(StdHeader::Fcntl);
2136 assert!(result.contains("#define O_RDONLY 0"));
2137 assert!(result.contains("#define O_WRONLY 1"));
2138 assert!(result.contains("#define O_RDWR 2"));
2139 assert!(result.contains("#define O_CREAT 0100"));
2140 assert!(result.contains("#define O_TRUNC 01000"));
2141 assert!(result.contains("#define O_APPEND 02000"));
2142 assert!(result.contains("#define O_NONBLOCK 04000"));
2143 assert!(result.contains("#define LOCK_SH 1"));
2144 assert!(result.contains("#define LOCK_EX 2"));
2145 assert!(result.contains("#define LOCK_UN 8"));
2146 }
2147
2148 #[test]
2149 fn test_inject_header_fcntl_functions() {
2150 let stdlib = StdlibPrototypes::new();
2151 let result = stdlib.inject_prototypes_for_header(StdHeader::Fcntl);
2152 assert!(result.contains("int open(const char* pathname, int flags, ...);"));
2153 }
2154
2155 #[test]
2160 fn test_inject_header_dirent_type_definitions() {
2161 let stdlib = StdlibPrototypes::new();
2162 let result = stdlib.inject_prototypes_for_header(StdHeader::Dirent);
2163 assert!(result.contains("struct dirent { char d_name[256]; };"));
2164 assert!(result.contains("typedef struct __dirstream DIR;"));
2165 }
2166
2167 #[test]
2168 fn test_inject_header_dirent_functions() {
2169 let stdlib = StdlibPrototypes::new();
2170 let result = stdlib.inject_prototypes_for_header(StdHeader::Dirent);
2171 assert!(result.contains("DIR* opendir(const char* name);"));
2172 assert!(result.contains("struct dirent* readdir(DIR* dirp);"));
2173 assert!(result.contains("int closedir(DIR* dirp);"));
2174 }
2175
2176 #[test]
2181 fn test_inject_header_sys_types_definitions() {
2182 let stdlib = StdlibPrototypes::new();
2183 let result = stdlib.inject_prototypes_for_header(StdHeader::SysTypes);
2184 assert!(result.contains("typedef int pid_t;"));
2185 assert!(result.contains("typedef long off_t;"));
2186 assert!(result.contains("typedef unsigned int mode_t;"));
2187 assert!(result.contains("typedef long ssize_t;"));
2188 }
2189
2190 #[test]
2195 fn test_inject_header_sys_stat_definitions() {
2196 let stdlib = StdlibPrototypes::new();
2197 let result = stdlib.inject_prototypes_for_header(StdHeader::SysStat);
2198 assert!(result.contains("struct stat { long st_size; int st_mode; };"));
2199 assert!(result.contains("#define S_ISREG(m)"));
2200 assert!(result.contains("#define S_ISDIR(m)"));
2201 }
2202
2203 #[test]
2208 fn test_inject_header_sys_mman_macros() {
2209 let stdlib = StdlibPrototypes::new();
2210 let result = stdlib.inject_prototypes_for_header(StdHeader::SysMman);
2211 assert!(result.contains("#define PROT_NONE 0"));
2212 assert!(result.contains("#define PROT_READ 1"));
2213 assert!(result.contains("#define PROT_WRITE 2"));
2214 assert!(result.contains("#define PROT_EXEC 4"));
2215 assert!(result.contains("#define MAP_SHARED 1"));
2216 assert!(result.contains("#define MAP_PRIVATE 2"));
2217 assert!(result.contains("#define MAP_ANONYMOUS 0x20"));
2218 assert!(result.contains("#define MAP_FAILED ((void*)-1)"));
2219 }
2220
2221 #[test]
2226 fn test_inject_header_wchar_definitions() {
2227 let stdlib = StdlibPrototypes::new();
2228 let result = stdlib.inject_prototypes_for_header(StdHeader::Wchar);
2229 assert!(result.contains("typedef int wchar_t;"));
2230 assert!(result.contains("typedef int wint_t;"));
2231 assert!(result.contains("#define WEOF (-1)"));
2232 }
2233
2234 #[test]
2239 fn test_inject_header_signal_definitions() {
2240 let stdlib = StdlibPrototypes::new();
2241 let result = stdlib.inject_prototypes_for_header(StdHeader::Signal);
2242 assert!(result.contains("typedef void (*sighandler_t)(int);"));
2243 assert!(result.contains("#define SIGINT 2"));
2244 assert!(result.contains("#define SIGTERM 15"));
2245 }
2246
2247 #[test]
2252 fn test_inject_header_limits_macros() {
2253 let stdlib = StdlibPrototypes::new();
2254 let result = stdlib.inject_prototypes_for_header(StdHeader::Limits);
2255 assert!(result.contains("#define CHAR_BIT 8"));
2256 assert!(result.contains("#define CHAR_MIN (-128)"));
2257 assert!(result.contains("#define CHAR_MAX 127"));
2258 assert!(result.contains("#define SHRT_MIN (-32768)"));
2259 assert!(result.contains("#define SHRT_MAX 32767"));
2260 assert!(result.contains("#define INT_MIN (-2147483647-1)"));
2261 assert!(result.contains("#define INT_MAX 2147483647"));
2262 assert!(result.contains("#define UINT_MAX 4294967295U"));
2263 assert!(result.contains("#define LONG_MIN (-9223372036854775807L-1)"));
2264 assert!(result.contains("#define LONG_MAX 9223372036854775807L"));
2265 assert!(result.contains("#define PATH_MAX 4096"));
2266 }
2267
2268 #[test]
2273 fn test_inject_header_ctype_functions() {
2274 let stdlib = StdlibPrototypes::new();
2275 let result = stdlib.inject_prototypes_for_header(StdHeader::Ctype);
2276 assert!(result.contains("int isspace(int c);"));
2277 assert!(result.contains("int isdigit(int c);"));
2278 assert!(result.contains("int isalpha(int c);"));
2279 assert!(result.contains("int isalnum(int c);"));
2280 assert!(result.contains("int isupper(int c);"));
2281 assert!(result.contains("int islower(int c);"));
2282 assert!(result.contains("int tolower(int c);"));
2283 assert!(result.contains("int toupper(int c);"));
2284 }
2285
2286 #[test]
2287 fn test_inject_header_ctype_no_extra_type_defs() {
2288 let stdlib = StdlibPrototypes::new();
2289 let result = stdlib.inject_prototypes_for_header(StdHeader::Ctype);
2290 assert!(!result.contains("typedef struct _IO_FILE FILE;"));
2292 assert!(!result.contains("typedef long time_t;"));
2293 }
2294
2295 #[test]
2300 fn test_inject_header_math_macros() {
2301 let stdlib = StdlibPrototypes::new();
2302 let result = stdlib.inject_prototypes_for_header(StdHeader::Math);
2303 assert!(result.contains("#define M_PI 3.14159265358979323846"));
2304 assert!(result.contains("#define M_E 2.71828182845904523536"));
2305 assert!(result.contains("#define INFINITY (1.0/0.0)"));
2306 assert!(result.contains("#define NAN (0.0/0.0)"));
2307 }
2308
2309 #[test]
2310 fn test_inject_header_math_trig_functions() {
2311 let stdlib = StdlibPrototypes::new();
2312 let result = stdlib.inject_prototypes_for_header(StdHeader::Math);
2313 assert!(result.contains("double sin(double x);"));
2314 assert!(result.contains("double cos(double x);"));
2315 assert!(result.contains("double tan(double x);"));
2316 assert!(result.contains("double asin(double x);"));
2317 assert!(result.contains("double acos(double x);"));
2318 assert!(result.contains("double atan(double x);"));
2319 assert!(result.contains("double atan2(double y, double x);"));
2320 }
2321
2322 #[test]
2323 fn test_inject_header_math_power_and_log_functions() {
2324 let stdlib = StdlibPrototypes::new();
2325 let result = stdlib.inject_prototypes_for_header(StdHeader::Math);
2326 assert!(result.contains("double sqrt(double x);"));
2327 assert!(result.contains("double pow(double x, double y);"));
2328 assert!(result.contains("double exp(double x);"));
2329 assert!(result.contains("double log(double x);"));
2330 assert!(result.contains("double log10(double x);"));
2331 }
2332
2333 #[test]
2334 fn test_inject_header_math_rounding_functions() {
2335 let stdlib = StdlibPrototypes::new();
2336 let result = stdlib.inject_prototypes_for_header(StdHeader::Math);
2337 assert!(result.contains("double fabs(double x);"));
2338 assert!(result.contains("double ceil(double x);"));
2339 assert!(result.contains("double floor(double x);"));
2340 assert!(result.contains("double round(double x);"));
2341 assert!(result.contains("double trunc(double x);"));
2342 assert!(result.contains("double fmod(double x, double y);"));
2343 }
2344
2345 #[test]
2350 fn test_inject_header_assert_has_common_preamble() {
2351 let stdlib = StdlibPrototypes::new();
2352 let result = stdlib.inject_prototypes_for_header(StdHeader::Assert);
2353 assert!(result.contains("// Built-in prototypes for Assert"));
2355 assert!(result.contains("typedef unsigned long size_t;"));
2356 assert!(result.contains("#define NULL 0"));
2357 }
2358
2359 #[test]
2360 fn test_inject_header_assert_no_header_specific_types() {
2361 let stdlib = StdlibPrototypes::new();
2362 let result = stdlib.inject_prototypes_for_header(StdHeader::Assert);
2363 assert!(!result.contains("typedef struct _IO_FILE FILE;"));
2365 assert!(!result.contains("typedef long time_t;"));
2366 assert!(!result.contains("extern int errno;"));
2367 }
2368
2369 #[test]
2374 fn test_inject_header_float_has_common_preamble() {
2375 let stdlib = StdlibPrototypes::new();
2376 let result = stdlib.inject_prototypes_for_header(StdHeader::Float);
2377 assert!(result.contains("// Built-in prototypes for Float"));
2378 assert!(result.contains("typedef unsigned long size_t;"));
2379 assert!(result.contains("#define NULL 0"));
2380 }
2381
2382 #[test]
2383 fn test_inject_header_float_no_functions() {
2384 let stdlib = StdlibPrototypes::new();
2385 let result = stdlib.inject_prototypes_for_header(StdHeader::Float);
2386 assert!(!result.contains("double sin("));
2388 assert!(!result.contains("int printf("));
2389 }
2390
2391 #[test]
2396 fn test_inject_header_locale_has_common_preamble() {
2397 let stdlib = StdlibPrototypes::new();
2398 let result = stdlib.inject_prototypes_for_header(StdHeader::Locale);
2399 assert!(result.contains("// Built-in prototypes for Locale"));
2400 assert!(result.contains("typedef unsigned long size_t;"));
2401 }
2402
2403 #[test]
2408 fn test_inject_header_setjmp_has_common_preamble() {
2409 let stdlib = StdlibPrototypes::new();
2410 let result = stdlib.inject_prototypes_for_header(StdHeader::Setjmp);
2411 assert!(result.contains("// Built-in prototypes for Setjmp"));
2412 assert!(result.contains("typedef unsigned long size_t;"));
2413 }
2414
2415 #[test]
2420 fn test_inject_header_stddef_has_common_preamble() {
2421 let stdlib = StdlibPrototypes::new();
2422 let result = stdlib.inject_prototypes_for_header(StdHeader::Stddef);
2423 assert!(result.contains("// Built-in prototypes for Stddef"));
2424 assert!(result.contains("typedef unsigned long size_t;"));
2425 assert!(result.contains("typedef long ptrdiff_t;"));
2426 }
2427
2428 #[test]
2433 fn test_inject_header_stdlib_memory_functions() {
2434 let stdlib = StdlibPrototypes::new();
2435 let result = stdlib.inject_prototypes_for_header(StdHeader::Stdlib);
2436 assert!(result.contains("void* malloc(size_t size);"));
2437 assert!(result.contains("void* calloc(size_t nmemb, size_t size);"));
2438 assert!(result.contains("void* realloc(void* ptr, size_t size);"));
2439 assert!(result.contains("void free(void* ptr);"));
2440 }
2441
2442 #[test]
2443 fn test_inject_header_stdlib_conversion_functions() {
2444 let stdlib = StdlibPrototypes::new();
2445 let result = stdlib.inject_prototypes_for_header(StdHeader::Stdlib);
2446 assert!(result.contains("int atoi(const char* nptr);"));
2447 assert!(result.contains("long atol(const char* nptr);"));
2448 assert!(result.contains("double atof(const char* nptr);"));
2449 assert!(result.contains("long strtol(const char* nptr, char** endptr, int base);"));
2450 assert!(result.contains("double strtod(const char* nptr, char** endptr);"));
2451 }
2452
2453 #[test]
2454 fn test_inject_header_stdlib_process_functions() {
2455 let stdlib = StdlibPrototypes::new();
2456 let result = stdlib.inject_prototypes_for_header(StdHeader::Stdlib);
2457 assert!(result.contains("void exit(int status);"));
2458 assert!(result.contains("void abort(void);"));
2459 assert!(result.contains("char* getenv(const char* name);"));
2460 assert!(result.contains("int system(const char* command);"));
2461 }
2462
2463 #[test]
2464 fn test_inject_header_stdlib_random_functions() {
2465 let stdlib = StdlibPrototypes::new();
2466 let result = stdlib.inject_prototypes_for_header(StdHeader::Stdlib);
2467 assert!(result.contains("int rand(void);"));
2468 assert!(result.contains("void srand(unsigned int seed);"));
2469 }
2470
2471 #[test]
2472 fn test_inject_header_stdlib_arithmetic_functions() {
2473 let stdlib = StdlibPrototypes::new();
2474 let result = stdlib.inject_prototypes_for_header(StdHeader::Stdlib);
2475 assert!(result.contains("int abs(int j);"));
2476 assert!(result.contains("long labs(long j);"));
2477 }
2478
2479 #[test]
2480 fn test_inject_header_stdlib_skips_function_pointer_params() {
2481 let stdlib = StdlibPrototypes::new();
2482 let result = stdlib.inject_prototypes_for_header(StdHeader::Stdlib);
2483 assert!(
2485 !result.contains("void qsort("),
2486 "qsort with function pointer param should be filtered out"
2487 );
2488 assert!(
2489 !result.contains("void* bsearch("),
2490 "bsearch with function pointer param should be filtered out"
2491 );
2492 }
2493
2494 #[test]
2495 fn test_inject_header_stdlib_does_not_contain_stdio_functions() {
2496 let stdlib = StdlibPrototypes::new();
2497 let result = stdlib.inject_prototypes_for_header(StdHeader::Stdlib);
2498 assert!(!result.contains("int printf("));
2499 assert!(!result.contains("FILE* fopen("));
2500 }
2501
2502 #[test]
2507 fn test_inject_header_string_copy_functions() {
2508 let stdlib = StdlibPrototypes::new();
2509 let result = stdlib.inject_prototypes_for_header(StdHeader::String);
2510 assert!(result.contains("void* memcpy(void* dest, const void* src, size_t n);"));
2511 assert!(result.contains("void* memmove(void* dest, const void* src, size_t n);"));
2512 assert!(result.contains("char* strcpy(char* dest, const char* src);"));
2513 assert!(result.contains("char* strncpy(char* dest, const char* src, size_t n);"));
2514 }
2515
2516 #[test]
2517 fn test_inject_header_string_concat_functions() {
2518 let stdlib = StdlibPrototypes::new();
2519 let result = stdlib.inject_prototypes_for_header(StdHeader::String);
2520 assert!(result.contains("char* strcat(char* dest, const char* src);"));
2521 assert!(result.contains("char* strncat(char* dest, const char* src, size_t n);"));
2522 }
2523
2524 #[test]
2525 fn test_inject_header_string_comparison_functions() {
2526 let stdlib = StdlibPrototypes::new();
2527 let result = stdlib.inject_prototypes_for_header(StdHeader::String);
2528 assert!(result.contains("int memcmp(const void* s1, const void* s2, size_t n);"));
2529 assert!(result.contains("int strcmp(const char* s1, const char* s2);"));
2530 assert!(result.contains("int strncmp(const char* s1, const char* s2, size_t n);"));
2531 }
2532
2533 #[test]
2534 fn test_inject_header_string_search_functions() {
2535 let stdlib = StdlibPrototypes::new();
2536 let result = stdlib.inject_prototypes_for_header(StdHeader::String);
2537 assert!(result.contains("void* memchr(const void* s, int c, size_t n);"));
2538 assert!(result.contains("char* strchr(const char* s, int c);"));
2539 assert!(result.contains("char* strrchr(const char* s, int c);"));
2540 assert!(result.contains("char* strstr(const char* haystack, const char* needle);"));
2541 assert!(result.contains("char* strtok(char* str, const char* delim);"));
2542 }
2543
2544 #[test]
2545 fn test_inject_header_string_misc_functions() {
2546 let stdlib = StdlibPrototypes::new();
2547 let result = stdlib.inject_prototypes_for_header(StdHeader::String);
2548 assert!(result.contains("void* memset(void* s, int c, size_t n);"));
2549 assert!(result.contains("size_t strlen(const char* s);"));
2550 assert!(result.contains("char* strdup(const char* s);"));
2551 }
2552
2553 #[test]
2554 fn test_inject_header_string_does_not_contain_math() {
2555 let stdlib = StdlibPrototypes::new();
2556 let result = stdlib.inject_prototypes_for_header(StdHeader::String);
2557 assert!(!result.contains("double sin("));
2558 assert!(!result.contains("#define M_PI"));
2559 }
2560
2561 #[test]
2566 fn test_inject_header_isolation_no_cross_contamination() {
2567 let stdlib = StdlibPrototypes::new();
2568
2569 let stdio_result = stdlib.inject_prototypes_for_header(StdHeader::Stdio);
2571 let string_result = stdlib.inject_prototypes_for_header(StdHeader::String);
2572 let math_result = stdlib.inject_prototypes_for_header(StdHeader::Math);
2573 let ctype_result = stdlib.inject_prototypes_for_header(StdHeader::Ctype);
2574
2575 assert!(!stdio_result.contains("size_t strlen("));
2577 assert!(!stdio_result.contains("void* memcpy("));
2578
2579 assert!(!string_result.contains("int printf("));
2581 assert!(!string_result.contains("FILE* fopen("));
2582
2583 assert!(!math_result.contains("int isspace("));
2585 assert!(!math_result.contains("int toupper("));
2586
2587 assert!(!ctype_result.contains("double sqrt("));
2589 assert!(!ctype_result.contains("#define M_PI"));
2590 }
2591
2592 #[test]
2593 fn test_inject_header_functions_are_sorted_alphabetically() {
2594 let stdlib = StdlibPrototypes::new();
2595 let result = stdlib.inject_prototypes_for_header(StdHeader::String);
2596
2597 let memchr_pos = result.find("void* memchr(").unwrap();
2599 let memcmp_pos = result.find("int memcmp(").unwrap();
2600 let memcpy_pos = result.find("void* memcpy(").unwrap();
2601 let strlen_pos = result.find("size_t strlen(").unwrap();
2602 let strstr_pos = result.find("char* strstr(").unwrap();
2603
2604 assert!(memchr_pos < memcmp_pos);
2605 assert!(memcmp_pos < memcpy_pos);
2606 assert!(memcpy_pos < strlen_pos);
2607 assert!(strlen_pos < strstr_pos);
2608 }
2609
2610 #[test]
2611 fn test_inject_header_comment_contains_header_name() {
2612 let stdlib = StdlibPrototypes::new();
2613
2614 let result = stdlib.inject_prototypes_for_header(StdHeader::Stdio);
2615 assert!(result.contains("// Built-in prototypes for Stdio"));
2616
2617 let result = stdlib.inject_prototypes_for_header(StdHeader::Math);
2618 assert!(result.contains("// Built-in prototypes for Math"));
2619
2620 let result = stdlib.inject_prototypes_for_header(StdHeader::SysMman);
2621 assert!(result.contains("// Built-in prototypes for SysMman"));
2622 }
2623
2624 #[test]
2625 fn test_inject_header_result_ends_with_declarations() {
2626 let stdlib = StdlibPrototypes::new();
2627 let result = stdlib.inject_prototypes_for_header(StdHeader::Stdlib);
2629 for line in result.lines() {
2631 if line.contains('(') && line.contains(')') && !line.starts_with("//") && !line.starts_with("#") && !line.starts_with("typedef") && !line.starts_with("struct") && !line.starts_with("extern") {
2632 assert!(
2633 line.ends_with(';'),
2634 "Function declaration line should end with semicolon: {}",
2635 line
2636 );
2637 }
2638 }
2639 }
2640}