- struct loc_str *next;
- };
- static struct loc_str *root = NULL;
- struct loc_str *ls, *ls_last;
- int len;
- int size;
- char *p;
- static char *loc = NULL;
- static int loc_size = 0;
-
- if ((p = strrchr(file, '/')) == NULL) {
- p = file; /* keep the whole name */
- } else {
- p++; /* just the last path element */
- }
-
- len = strlen (p);
- size = len + 1 + NUM_STR_SIZE + 1;
- if (size > loc_size) {
- size = ((size + 64 - 1) / 64) * 64; /* might as well get a bunch */
- /*
- * We should free the previous loc area, but we have marked it
- * as a non-leak and the library considers it an error to free
- * such an area, so we just ignore it. We probably grabbed
- * enough the first time that this will not even happen.
- */
- loc = malloc (size);
- if (loc == NULL) {
- return "??"; /* not much better than abort */
- }
- malloc_mark (loc);
- loc_size = size;
- }
-
- strcpy (loc, p);
- ap_snprintf(loc + len, 1 + NUM_STR_SIZE, "@%d", line);
-
- for (ls_last = NULL, ls = root; ls != NULL; ls_last = ls, ls = ls->next) {
- if (strcmp (loc, ls->str) == 0) {
- break;
+ LIST_ENTRY(loc_str) le;
+ } *ls;
+ static LIST_HEAD(, loc_str) root = LIST_HEAD_INITIALIZER(root);
+ static char loc[256]; /* big enough for filename@lineno */
+ const char *p;
+
+ if ((p = strrchr(file, '/')) != NULL)
+ file = p + 1; /* just the last path element */
+
+ snprintf(loc, sizeof(loc), "%s@%d", file, line);
+
+ for (ls = LIST_FIRST(&root); ls != NULL; ls = LIST_NEXT(ls, le)) {
+ if (strcmp(loc, ls->str) == 0) {
+ if (ls != LIST_FIRST(&root)) {
+ /*
+ * This is a repeat and was not at the head of the list.
+ * Unlink it and move it to the front.
+ */
+ LIST_REMOVE(ls, le);
+ LIST_INSERT_HEAD(&root, ls, le);
+ }
+ return (ls->str);