root/magic.c
/*DEFINITIONS
This source file includes following definitions.1 #include <stdio.h> 2 #include <string.h> 3 #include <stddef.h> 4 #include <stdlib.h> 5 #include "magic.h" 6 #include "nav.h" 7 8 #define O_EQUALS(b, hint) if (strcmp(b, hint) == 0) 9 10 static bool is_indent(const char *line, size_t limit) { 11 size_t pos = 0; 12 13 while (*line != '\0' && pos++ < limit) { 14 if (*line != ' ' && *line != '\t') return false; 15 16 line++; 17 } 18 19 return true; 20 } 21 22 static size_t count_chr(const char *line, size_t limit, int chr) { 23 size_t cnt = 0; 24 const char *ol = line; 25 26 while ((line = memchr(line, chr, limit - (line - ol)))) { 27 line++; cnt++; 28 } 29 30 return cnt; 31 } 32 33 static const char *i_strrstr(const char *haystack, const char *needle) { 34 const char *laststack = NULL; 35 while ((haystack = strstr(haystack, needle))) { 36 laststack = haystack; 37 haystack += strlen(needle); 38 } 39 return laststack; 40 } 41 42 static const char *hdr_is_c_or_cpp(const char *path) { 43 FILE *fptr; 44 45 if ((fptr = fopen(path, "r")) == NULL) return NULL; 46 47 const char *lang = "C"; 48 const char *finder; 49 50 char *line = NULL; 51 size_t len = 0; 52 bool in_comment = false; 53 54 while (getline(&line, &len, fptr) != -1) { 55 /* TODO: Treat semicolon & newline as delims? */ 56 if ((finder = i_strrstr(line, "/*"))) 57 if ((count_chr(line, finder - line, '"') & 1) == 0) { 58 in_comment = true; finder += 2; 59 } 60 if (in_comment && strstr(finder ? finder : line, "*/")) 61 in_comment = false; 62 #define FIND_CPP(sym) (finder = strstr(line, sym " ")) 63 if (in_comment || !(FIND_CPP("class") || FIND_CPP("namespace"))) 64 continue; 65 if (finder == line || is_indent(line, finder - line)) { 66 lang = "C++"; 67 break; 68 } 69 } 70 71 fclose(fptr); 72 free(line); 73 return lang; 74 } 75 76 const char *unsure_guess(const char *path) { 77 const char *bname = get_bname(path); 78 79 #define G_EQUALS(hint) O_EQUALS(bname, hint) 80 81 G_EQUALS("Makefile") return "Makefile"; 82 G_EQUALS("Doxyfile") return "Doxygen"; 83 G_EQUALS("makefile") return "Makefile"; /* This sometimes happens */ 84 85 FILE *fptr; 86 if ((fptr = fopen(path, "r")) == NULL) return NULL; 87 88 #define G_BUFMAX 64 89 char buffer[G_BUFMAX] = {}; 90 size_t reads = 0; 91 int c = 0; 92 do { 93 c = fgetc(fptr); 94 if (feof(fptr) || reads >= G_BUFMAX || c == '\n' || c == '\r') break; 95 buffer[reads] = c; 96 reads++; 97 } while (1); 98 99 fclose(fptr); 100 101 if (strlen(buffer) < 1) return NULL; 102 103 #define G_CONTAINS(hint) if (strstr(buffer, hint)) 104 105 /* Check if a shebang exists at all, do non-shebang checks if not */ 106 if (strstr(buffer, "#!/") != buffer) { 107 G_CONTAINS("# Doxyfile") return "Doxygen"; 108 G_CONTAINS("# vim") 109 G_CONTAINS("perl") return "Perl"; 110 111 return NULL; 112 } 113 114 G_CONTAINS("python") return "Python"; 115 G_CONTAINS("perl") return "Perl"; 116 117 G_CONTAINS("sh") { 118 G_CONTAINS("pwsh") return "PowerShell"; 119 G_CONTAINS("fish") return "Fish"; 120 121 return "Shell"; 122 } 123 124 return NULL; 125 } 126 127 const char *unsure_override(const char *path, const char *ext) { 128 O_EQUALS(ext, "h") return hdr_is_c_or_cpp(path); 129 130 return NULL; 131 }
/*