| 4205 | } |
| 4206 | |
| 4207 | static void classify_layer(const char *pkg, int in, int out_deg, bool has_routes, |
| 4208 | bool has_entry_points, const char **layer, const char **reason) { |
| 4209 | static CBM_TLS char reason_buf[CBM_SZ_128]; |
| 4210 | if (has_entry_points && out_deg > 0 && in == 0) { |
| 4211 | *layer = "entry"; |
| 4212 | *reason = "has entry points, only outbound calls"; |
| 4213 | return; |
| 4214 | } |
| 4215 | if (has_routes) { |
| 4216 | *layer = "api"; |
| 4217 | *reason = "has HTTP route definitions"; |
| 4218 | return; |
| 4219 | } |
| 4220 | if (in > out_deg && in > ST_MIN_INDEGREE) { |
| 4221 | snprintf(reason_buf, sizeof(reason_buf), "high fan-in (%d in, %d out)", in, out_deg); |
| 4222 | *layer = "core"; |
| 4223 | *reason = reason_buf; |
| 4224 | return; |
| 4225 | } |
| 4226 | if (out_deg == 0 && in > 0) { |
| 4227 | *layer = "leaf"; |
| 4228 | *reason = "only inbound calls, no outbound"; |
| 4229 | return; |
| 4230 | } |
| 4231 | if (in == 0 && out_deg > 0) { |
| 4232 | *layer = "entry"; |
| 4233 | *reason = "only outbound calls"; |
| 4234 | return; |
| 4235 | } |
| 4236 | snprintf(reason_buf, sizeof(reason_buf), "fan-in=%d, fan-out=%d", in, out_deg); |
| 4237 | *layer = "internal"; |
| 4238 | *reason = reason_buf; |
| 4239 | (void)pkg; |
| 4240 | } |
| 4241 | |
| 4242 | /* Find or insert a package name, returning its index. Returns -1 if full. */ |
| 4243 | static int find_or_add_pkg(char **all_pkgs, int *npkgs, int max_pkgs, const char *pkg) { |